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