1/* $NetBSD: isns.c,v 1.2 2019/10/08 19:38:27 christos Exp $ */ 2 3/*- 4 * Copyright (c) 2004,2009 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Wasabi Systems, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#include <sys/cdefs.h> 33__RCSID("$NetBSD: isns.c,v 1.2 2019/10/08 19:38:27 christos Exp $"); 34 35/* 36 * isns.c 37 */ 38 39#include <sys/types.h> 40#include <sys/param.h> 41#include <sys/uio.h> 42#include <sys/poll.h> 43 44#include <errno.h> 45#include <stdio.h> 46#include <string.h> 47#include <unistd.h> 48 49#include "isns.h" 50#include "isns_config.h" 51 52 53 54/* 55 * isns_init() 56 */ 57int 58isns_init(ISNS_HANDLE *isns_handle_p, int is_server) 59{ 60 struct isns_config_s *cfg_p; 61 int rval; 62 63 *isns_handle_p = NULL; 64 65 if ((cfg_p = isns_new_config()) == NULL) { 66 DBG("isns_init: error on isns_new_config()\n"); 67 return ENOMEM; 68 } 69 70 cfg_p->is_server = is_server; 71 cfg_p->curtask_p = NULL; 72 73 if ((rval = pipe(cfg_p->pipe_fds)) != 0) { 74 DBG("isns_init: error on wepe_sys_pipe()\n"); 75 isns_destroy_config(cfg_p); 76 return rval; 77 } 78 79 if ((cfg_p->kq = kqueue()) == -1) { 80 DBG("isns_init: error on kqueue()\n"); 81 isns_destroy_config(cfg_p); 82 return -1; 83 } 84 85 rval = isns_change_kevent_list(cfg_p, (uintptr_t)cfg_p->pipe_fds[0], 86 EVFILT_READ, EV_ADD | EV_ENABLE, (int64_t)0, 87 (intptr_t)isns_kevent_pipe); 88 if (rval == -1) { 89 DBG("isns_init: error on isns_change_kevent_list() " 90 "for isns_kevent_pipe\n"); 91 isns_destroy_config(cfg_p); 92 return rval; 93 } 94 95 isns_init_buffer_pool(); 96 rval = isns_add_buffer_pool(ISNS_BUF_SIZE, ISNS_BUF_COUNT); 97 if (rval != 0) { 98 DBG("isns_init: error on isns_init_buffer_pool()\n"); 99 isns_destroy_config(cfg_p); 100 return rval; 101 } 102 rval = isns_add_buffer_pool((int)ISNS_SMALL_BUF_SIZE, ISNS_SMALL_BUF_COUNT); 103 if (rval != 0) { 104 DBG("isns_init: error on isns_init_buffer_pool() [small]\n"); 105 isns_destroy_config(cfg_p); 106 isns_destroy_buffer_pool(); 107 return rval; 108 } 109 110 if ((rval = isns_thread_create(cfg_p)) != 0) { 111 DBG("isns_init: error on isns_thread_create()\n"); 112 isns_destroy_config(cfg_p); 113 isns_destroy_buffer_pool(); 114 return rval; 115 } 116 117 *isns_handle_p = (ISNS_HANDLE)cfg_p; 118 119 return 0; 120} 121 122 123/* 124 * isns_add_servercon() 125 */ 126int 127isns_add_servercon(ISNS_HANDLE isns_handle, int fd, struct addrinfo *ai) 128{ 129 struct isns_config_s *cfg_p; 130 struct isns_task_s *task_p; 131 struct addrinfo *ai_p; 132 size_t len; 133 134 if (isns_handle == ISNS_INVALID_HANDLE) 135 return EINVAL; 136 137 cfg_p = (struct isns_config_s *)isns_handle; 138 139 ai_p = (struct addrinfo *)isns_malloc(sizeof(struct addrinfo)); 140 if (ai_p == NULL) 141 return ENOMEM; 142 143 ai_p->ai_flags = ai->ai_flags; 144 ai_p->ai_family = ai->ai_family; 145 ai_p->ai_socktype = ai->ai_socktype; 146 ai_p->ai_protocol = ai->ai_protocol; 147 ai_p->ai_addrlen = ai->ai_addrlen; 148 if (ai->ai_canonname != NULL) { 149 len = strlen(ai->ai_canonname); 150 ai_p->ai_canonname = (char *)isns_malloc(len + 1); 151 if (ai_p->ai_canonname == NULL) { 152 isns_free(ai_p); 153 return ENOMEM; 154 } 155 memset(ai_p->ai_canonname, '\0', len + 1); 156 strlcpy(ai_p->ai_canonname, ai->ai_canonname, len + 1); 157 } else 158 ai_p->ai_canonname = NULL; 159 if (ai->ai_addr != NULL) { 160 ai_p->ai_addr = (struct sockaddr *)isns_malloc(ai_p-> 161 ai_addrlen); 162 if (ai_p->ai_addr == NULL) { 163 if (ai_p->ai_canonname != NULL) 164 isns_free(ai_p->ai_canonname); 165 isns_free(ai_p); 166 return ENOMEM; 167 } 168 memcpy(ai_p->ai_addr, ai->ai_addr, ai_p->ai_addrlen); 169 } else 170 ai_p->ai_addr = NULL; 171 ai_p->ai_next = NULL; 172 173 /* Build task and kick off task processing */ 174 task_p = isns_new_task(cfg_p, ISNS_TASK_INIT_SOCKET_IO, 1); 175 task_p->var.init_socket_io.sd = fd; 176 task_p->var.init_socket_io.ai_p = ai_p; 177 178 isns_taskq_insert_head(cfg_p, task_p); 179 isns_issue_cmd(cfg_p, ISNS_CMD_PROCESS_TASKQ); 180 isns_wait_task(task_p, NULL); 181 182 return 0; 183} 184 185 186/* 187 * isns_init_reg_refresh() 188 */ 189int 190isns_init_reg_refresh(ISNS_HANDLE isns_handle, const char *node, int interval) 191{ 192 struct isns_config_s *cfg_p; 193 struct isns_task_s *task_p; 194 struct isns_refresh_s *ref_p; 195 196 if (isns_handle == ISNS_INVALID_HANDLE) 197 return EINVAL; 198 199 /* Build INIT_REFRESH task with info provided. */ 200 cfg_p = (struct isns_config_s *)isns_handle; 201 task_p = isns_new_task(cfg_p, ISNS_TASK_INIT_REFRESH, 0); 202 if (task_p == NULL) 203 return ENOMEM; 204 205 ref_p = (struct isns_refresh_s *) 206 isns_malloc(sizeof(struct isns_refresh_s)); 207 if (ref_p == NULL) { 208 isns_free_task(task_p); 209 return ENOMEM; 210 } 211 212 (void) snprintf(ref_p->node, sizeof(ref_p->node), "%.*s", 213 (int)sizeof(ref_p->node)-1, node); 214 ref_p->interval = interval; 215 ref_p->trans_p = NULL; 216 task_p->var.init_refresh.ref_p = ref_p; 217 218 isns_taskq_insert_tail(cfg_p, task_p); 219 isns_issue_cmd(cfg_p, ISNS_CMD_PROCESS_TASKQ); 220 221 return 0; 222} 223 224 225/* 226 * isns_stop() 227 */ 228void isns_stop(ISNS_HANDLE isns_handle) 229{ 230 struct isns_config_s *cfg_p = (struct isns_config_s *)isns_handle; 231 232 DBG("isns_stop: entered\n"); 233 234 isns_issue_cmd(cfg_p, ISNS_CMD_STOP); 235 236 isns_thread_destroy(cfg_p); 237 isns_destroy_config(cfg_p); 238 isns_destroy_buffer_pool(); 239} 240