1fcf3ce44SJohn Forte /* 2fcf3ce44SJohn Forte * CDDL HEADER START 3fcf3ce44SJohn Forte * 4fcf3ce44SJohn Forte * The contents of this file are subject to the terms of the 5fcf3ce44SJohn Forte * Common Development and Distribution License (the "License"). 6fcf3ce44SJohn Forte * You may not use this file except in compliance with the License. 7fcf3ce44SJohn Forte * 8fcf3ce44SJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9fcf3ce44SJohn Forte * or http://www.opensolaris.org/os/licensing. 10fcf3ce44SJohn Forte * See the License for the specific language governing permissions 11fcf3ce44SJohn Forte * and limitations under the License. 12fcf3ce44SJohn Forte * 13fcf3ce44SJohn Forte * When distributing Covered Code, include this CDDL HEADER in each 14fcf3ce44SJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15fcf3ce44SJohn Forte * If applicable, add the following below this CDDL HEADER, with the 16fcf3ce44SJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying 17fcf3ce44SJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner] 18fcf3ce44SJohn Forte * 19fcf3ce44SJohn Forte * CDDL HEADER END 20fcf3ce44SJohn Forte */ 21fcf3ce44SJohn Forte /* 22fcf3ce44SJohn Forte * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23fcf3ce44SJohn Forte * Use is subject to license terms. 24fcf3ce44SJohn Forte * 25fcf3ce44SJohn Forte * iSNS Client 26fcf3ce44SJohn Forte */ 27fcf3ce44SJohn Forte 28fcf3ce44SJohn Forte #include "iscsi.h" /* For ISCSI_MAX_IOVEC */ 29fcf3ce44SJohn Forte #include "isns_protocol.h" 30fcf3ce44SJohn Forte #include "isns_client.h" 31fcf3ce44SJohn Forte #include "persistent.h" 32fcf3ce44SJohn Forte 33fcf3ce44SJohn Forte #ifdef _KERNEL 34fcf3ce44SJohn Forte #include <sys/sunddi.h> 35fcf3ce44SJohn Forte #else 36fcf3ce44SJohn Forte #include <stdlib.h> 37fcf3ce44SJohn Forte #endif 38fcf3ce44SJohn Forte #include <netinet/tcp.h> 39fcf3ce44SJohn Forte #include <sys/types.h> 40fcf3ce44SJohn Forte 41fcf3ce44SJohn Forte /* For local use */ 42fcf3ce44SJohn Forte #define ISNS_MAX_IOVEC 5 43fcf3ce44SJohn Forte #define MAX_XID (2^16) 44fcf3ce44SJohn Forte #define MAX_RCV_RSP_COUNT 10 /* Maximum number of unmatched xid */ 45fcf3ce44SJohn Forte #define ISNS_RCV_TIMEOUT 5 46fcf3ce44SJohn Forte #define ISNS_RCV_RETRY_MAX 2 47fcf3ce44SJohn Forte #define IPV4_RSVD_BYTES 10 48fcf3ce44SJohn Forte 49fcf3ce44SJohn Forte typedef struct isns_reg_arg { 50fcf3ce44SJohn Forte iscsi_addr_t *isns_server_addr; 51fcf3ce44SJohn Forte uint8_t *node_name; 52fcf3ce44SJohn Forte size_t node_name_len; 53fcf3ce44SJohn Forte uint8_t *node_alias; 54fcf3ce44SJohn Forte size_t node_alias_len; 55fcf3ce44SJohn Forte uint32_t node_type; 56fcf3ce44SJohn Forte uint8_t *lhba_handle; 57fcf3ce44SJohn Forte } isns_reg_arg_t; 58fcf3ce44SJohn Forte 59fcf3ce44SJohn Forte typedef struct isns_async_thread_arg { 60fcf3ce44SJohn Forte uint8_t *lhba_handle; 61fcf3ce44SJohn Forte void *listening_so; 62fcf3ce44SJohn Forte } isns_async_thread_arg_t; 63fcf3ce44SJohn Forte 64fcf3ce44SJohn Forte /* One global queue to serve all LHBA instances. */ 65fcf3ce44SJohn Forte static ddi_taskq_t *reg_query_taskq; 66fcf3ce44SJohn Forte static kmutex_t reg_query_taskq_mutex; 67fcf3ce44SJohn Forte 68fcf3ce44SJohn Forte /* One global queue to serve all LHBA instances. */ 69fcf3ce44SJohn Forte static ddi_taskq_t *scn_taskq; 70fcf3ce44SJohn Forte static kmutex_t scn_taskq_mutex; 71fcf3ce44SJohn Forte 72fcf3ce44SJohn Forte /* One globally maintained transaction ID. */ 73fcf3ce44SJohn Forte static uint16_t xid = 0; 74fcf3ce44SJohn Forte 75fcf3ce44SJohn Forte /* 76fcf3ce44SJohn Forte * One SCN callback registration per LHBA instance. For now, since we 77fcf3ce44SJohn Forte * support only one instance, we create one place holder for the 78fcf3ce44SJohn Forte * callback. 79fcf3ce44SJohn Forte */ 80fcf3ce44SJohn Forte void (*scn_callback_p)(void *); 81fcf3ce44SJohn Forte 82fcf3ce44SJohn Forte /* 83fcf3ce44SJohn Forte * One thread, port, local address, and listening socket per LHBA instance. 84fcf3ce44SJohn Forte * For now, since we support only one instance, we create one set of place 85fcf3ce44SJohn Forte * holder for these data. 86fcf3ce44SJohn Forte */ 87fcf3ce44SJohn Forte static boolean_t esi_scn_thr_to_shutdown = B_FALSE; 88fcf3ce44SJohn Forte static iscsi_thread_t *esi_scn_thr_id = NULL; 89fcf3ce44SJohn Forte static iscsi_addr_t *local_addr = NULL; 90fcf3ce44SJohn Forte static void *instance_listening_so = NULL; 91fcf3ce44SJohn Forte /* 92fcf3ce44SJohn Forte * This mutex protects all the per LHBA instance variables, i.e., 93fcf3ce44SJohn Forte * esi_scn_thr_to_shutdown, esi_scn_thr_id, local_addr, and 94fcf3ce44SJohn Forte * instance_listening_so. 95fcf3ce44SJohn Forte */ 96fcf3ce44SJohn Forte static kmutex_t esi_scn_thr_mutex; 97fcf3ce44SJohn Forte 98fcf3ce44SJohn Forte /* iSNS related helpers */ 99fcf3ce44SJohn Forte /* Return status */ 100fcf3ce44SJohn Forte #define ISNS_OK 0 101fcf3ce44SJohn Forte #define ISNS_BAD_SVR_ADDR 1 102fcf3ce44SJohn Forte #define ISNS_INTERNAL_ERR 2 103fcf3ce44SJohn Forte #define ISNS_CANNOT_FIND_LOCAL_ADDR 3 104fcf3ce44SJohn Forte static int discover_isns_server(uint8_t *lhba_handle, 105fcf3ce44SJohn Forte iscsi_addr_list_t **isns_server_addrs); 106fcf3ce44SJohn Forte static int create_esi_scn_thr(uint8_t *lhba_handle, 107fcf3ce44SJohn Forte iscsi_addr_t *isns_server_addr); 108fcf3ce44SJohn Forte static void esi_scn_thr_cleanup(void); 109fcf3ce44SJohn Forte static void register_isns_client(void *arg); 110fcf3ce44SJohn Forte static isns_status_t do_isns_dev_attr_reg(iscsi_addr_t *isns_server_addr, 111fcf3ce44SJohn Forte uint8_t *node_name, uint8_t *node_alias, uint32_t node_type); 112fcf3ce44SJohn Forte static isns_status_t do_isns_dev_dereg(iscsi_addr_t *isns_server_addr, 113fcf3ce44SJohn Forte uint8_t *node_name); 114fcf3ce44SJohn Forte 115fcf3ce44SJohn Forte /* 116fcf3ce44SJohn Forte * Make query to all iSNS servers visible to the specified LHBA. 117fcf3ce44SJohn Forte * The query could be made for all target nodes or for a specific target 118fcf3ce44SJohn Forte * node. 119fcf3ce44SJohn Forte */ 120fcf3ce44SJohn Forte static isns_status_t do_isns_query(boolean_t is_query_all_nodes_b, 121fcf3ce44SJohn Forte uint8_t *lhba_handle, uint8_t *target_node_name, 122fcf3ce44SJohn Forte uint8_t *source_node_name, uint8_t *source_node_alias, 123fcf3ce44SJohn Forte uint32_t source_node_type, isns_portal_group_list_t **pg_list); 124fcf3ce44SJohn Forte 125fcf3ce44SJohn Forte /* 126fcf3ce44SJohn Forte * Create DevAttrQuery message requesting portal group information for all 127fcf3ce44SJohn Forte * target nodes. Send it to the specified iSNS server. Parse the 128fcf3ce44SJohn Forte * DevAttrQueryRsp PDU and translate the results into a portal group list 129fcf3ce44SJohn Forte * object. 130fcf3ce44SJohn Forte */ 131fcf3ce44SJohn Forte static isns_status_t do_isns_dev_attr_query_all_nodes( 132fcf3ce44SJohn Forte iscsi_addr_t *isns_server_addr, uint8_t *node_name, 133fcf3ce44SJohn Forte uint8_t *node_alias, isns_portal_group_list_t **pg_list); 134fcf3ce44SJohn Forte 135fcf3ce44SJohn Forte /* 136fcf3ce44SJohn Forte * Create DevAttrQuery message requesting portal group information for the 137fcf3ce44SJohn Forte * specified target node. Send it to the specified iSNS server. Parse the 138fcf3ce44SJohn Forte * DevAttrQueryRsp PDU and translate the results into a portal group list 139fcf3ce44SJohn Forte * object. 140fcf3ce44SJohn Forte */ 141fcf3ce44SJohn Forte static isns_status_t do_isns_dev_attr_query_one_node( 142fcf3ce44SJohn Forte iscsi_addr_t *isns_server_addr, uint8_t *target_node_name, 143fcf3ce44SJohn Forte uint8_t *source_node_name, uint8_t *source_node_alias, 144fcf3ce44SJohn Forte uint32_t source_node_type, isns_portal_group_list_t **pg_list); 145fcf3ce44SJohn Forte 146fcf3ce44SJohn Forte static void isns_service_esi_scn(iscsi_thread_t *thread, void* arg); 147fcf3ce44SJohn Forte static void (*scn_callback_lookup(uint8_t *lhba_handle))(void *); 148fcf3ce44SJohn Forte 149fcf3ce44SJohn Forte /* Transport related helpers */ 150fcf3ce44SJohn Forte static void *isns_open(iscsi_addr_t *isns_server_addr); 151fcf3ce44SJohn Forte static ssize_t isns_send_pdu(void *socket, isns_pdu_t *pdu); 152fcf3ce44SJohn Forte static size_t isns_rcv_pdu(void *so, isns_pdu_t **pdu, size_t *pdu_size); 153fcf3ce44SJohn Forte static boolean_t find_local_portal(iscsi_addr_t *isns_server_addr, 154fcf3ce44SJohn Forte iscsi_addr_t **local_addr, void **listening_so); 155fcf3ce44SJohn Forte 156fcf3ce44SJohn Forte /* iSNS protocol related helpers */ 157fcf3ce44SJohn Forte static size_t isns_create_pdu_header(uint16_t func_id, 158fcf3ce44SJohn Forte uint16_t flags, isns_pdu_t **pdu); 159fcf3ce44SJohn Forte static int isns_add_attr(isns_pdu_t *pdu, 160fcf3ce44SJohn Forte size_t max_pdu_size, uint32_t attr_id, uint32_t attr_len, 161fcf3ce44SJohn Forte void *attr_data, uint32_t attr_numeric_data); 162fcf3ce44SJohn Forte static uint16_t create_xid(void); 163fcf3ce44SJohn Forte static size_t isns_create_dev_attr_reg_pdu( 164fcf3ce44SJohn Forte uint8_t *node_name, uint8_t *node_alias, uint32_t node_type, 165fcf3ce44SJohn Forte uint16_t *xid, isns_pdu_t **out_pdu); 166fcf3ce44SJohn Forte static size_t isns_create_dev_dereg_pdu(uint8_t *node_name, 167fcf3ce44SJohn Forte uint16_t *xid_p, isns_pdu_t **out_pdu); 168fcf3ce44SJohn Forte static size_t isns_create_dev_attr_qry_target_nodes_pdu( 169fcf3ce44SJohn Forte uint8_t *node_name, uint8_t *node_alias, uint16_t *xid, 170fcf3ce44SJohn Forte isns_pdu_t **out_pdu); 171fcf3ce44SJohn Forte static size_t isns_create_dev_attr_qry_one_pg_pdu( 172fcf3ce44SJohn Forte uint8_t *target_node_name, uint8_t *source_node_name, 173fcf3ce44SJohn Forte uint16_t *xid, isns_pdu_t **out_pdu); 174fcf3ce44SJohn Forte static size_t isns_create_esi_rsp_pdu(uint32_t rsp_status_code, 175fcf3ce44SJohn Forte isns_pdu_t *pdu, uint16_t *xid, isns_pdu_t **out_pdu); 176fcf3ce44SJohn Forte static size_t isns_create_scn_reg_pdu(uint8_t *node_name, 177fcf3ce44SJohn Forte uint8_t *node_alias, uint16_t *xid, isns_pdu_t **out_pdu); 178fcf3ce44SJohn Forte static size_t isns_create_scn_dereg_pdu(uint8_t *node_name, 179fcf3ce44SJohn Forte uint16_t *xid_p, isns_pdu_t **out_pdu); 180fcf3ce44SJohn Forte static size_t isns_create_scn_rsp_pdu(uint32_t rsp_status_code, 181fcf3ce44SJohn Forte isns_pdu_t *pdu, uint16_t *xid, isns_pdu_t **out_pdu); 182fcf3ce44SJohn Forte static uint32_t isns_process_dev_attr_reg_rsp(isns_pdu_t *resp_pdu_p); 183fcf3ce44SJohn Forte static uint32_t isns_process_dev_attr_dereg_rsp(isns_pdu_t *resp_pdu_p); 184fcf3ce44SJohn Forte 185fcf3ce44SJohn Forte /* 186fcf3ce44SJohn Forte * Process and parse a DevAttrQryRsp message. The routine creates a list 187fcf3ce44SJohn Forte * of Portal Group objects if the message is parasable without any issue. 188fcf3ce44SJohn Forte * If the parsing is not successful, the pg_list will be set to NULL. 189fcf3ce44SJohn Forte */ 190fcf3ce44SJohn Forte static uint32_t isns_process_dev_attr_qry_target_nodes_pdu( 191fcf3ce44SJohn Forte iscsi_addr_t *isns_server_addr, uint16_t payload_funcId, 192fcf3ce44SJohn Forte isns_resp_t *resp_p, size_t resp_len, 193fcf3ce44SJohn Forte isns_portal_group_list_t **pg_list); 194fcf3ce44SJohn Forte static uint32_t isns_process_scn_reg_rsp(isns_pdu_t *resp_pdu_p); 195fcf3ce44SJohn Forte static uint32_t isns_process_scn_dereg_rsp(isns_pdu_t *resp_pdu_p); 196fcf3ce44SJohn Forte static uint32_t isns_process_esi(isns_pdu_t *esi_pdu_p); 197fcf3ce44SJohn Forte static uint32_t isns_process_scn(isns_pdu_t *scn_pdu_p, uint8_t *lhba_handle); 198fcf3ce44SJohn Forte 199fcf3ce44SJohn Forte void 200fcf3ce44SJohn Forte isns_client_init() 201fcf3ce44SJohn Forte { 202fcf3ce44SJohn Forte mutex_init(®_query_taskq_mutex, NULL, MUTEX_DRIVER, NULL); 203fcf3ce44SJohn Forte mutex_enter(®_query_taskq_mutex); 204fcf3ce44SJohn Forte reg_query_taskq = ddi_taskq_create(NULL, "isns_reg_query_taskq", 205fcf3ce44SJohn Forte 1, TASKQ_DEFAULTPRI, 0); 206fcf3ce44SJohn Forte mutex_exit(®_query_taskq_mutex); 207fcf3ce44SJohn Forte 208fcf3ce44SJohn Forte mutex_init(&scn_taskq_mutex, NULL, MUTEX_DRIVER, NULL); 209fcf3ce44SJohn Forte mutex_enter(&scn_taskq_mutex); 210fcf3ce44SJohn Forte scn_taskq = ddi_taskq_create(NULL, "isns_scn_taskq", 211fcf3ce44SJohn Forte 1, TASKQ_DEFAULTPRI, 0); 212fcf3ce44SJohn Forte mutex_exit(&scn_taskq_mutex); 213fcf3ce44SJohn Forte 214fcf3ce44SJohn Forte mutex_init(&esi_scn_thr_mutex, NULL, MUTEX_DRIVER, NULL); 215fcf3ce44SJohn Forte 216fcf3ce44SJohn Forte /* MISC initializations. */ 217fcf3ce44SJohn Forte scn_callback_p = NULL; 218fcf3ce44SJohn Forte esi_scn_thr_id = NULL; 219fcf3ce44SJohn Forte local_addr = NULL; 220fcf3ce44SJohn Forte instance_listening_so = NULL; 221fcf3ce44SJohn Forte esi_scn_thr_to_shutdown = B_FALSE; 222fcf3ce44SJohn Forte xid = 0; 223fcf3ce44SJohn Forte } 224fcf3ce44SJohn Forte 225fcf3ce44SJohn Forte void 226fcf3ce44SJohn Forte isns_client_cleanup() 227fcf3ce44SJohn Forte { 228fcf3ce44SJohn Forte ddi_taskq_t *tmp_taskq_p; 229fcf3ce44SJohn Forte 230fcf3ce44SJohn Forte mutex_enter(&scn_taskq_mutex); 231fcf3ce44SJohn Forte tmp_taskq_p = scn_taskq; 232fcf3ce44SJohn Forte scn_taskq = NULL; 233fcf3ce44SJohn Forte mutex_exit(&scn_taskq_mutex); 234fcf3ce44SJohn Forte ddi_taskq_destroy(tmp_taskq_p); 235fcf3ce44SJohn Forte 236fcf3ce44SJohn Forte mutex_enter(®_query_taskq_mutex); 237fcf3ce44SJohn Forte tmp_taskq_p = reg_query_taskq; 238fcf3ce44SJohn Forte reg_query_taskq = NULL; 239fcf3ce44SJohn Forte mutex_exit(®_query_taskq_mutex); 240fcf3ce44SJohn Forte ddi_taskq_destroy(tmp_taskq_p); 241fcf3ce44SJohn Forte 242fcf3ce44SJohn Forte mutex_destroy(®_query_taskq_mutex); 243fcf3ce44SJohn Forte mutex_destroy(&scn_taskq_mutex); 244fcf3ce44SJohn Forte 245fcf3ce44SJohn Forte esi_scn_thr_cleanup(); 246fcf3ce44SJohn Forte 247fcf3ce44SJohn Forte mutex_destroy(&esi_scn_thr_mutex); 248fcf3ce44SJohn Forte } 249fcf3ce44SJohn Forte 250fcf3ce44SJohn Forte isns_status_t 251fcf3ce44SJohn Forte isns_reg(uint8_t *lhba_handle, 252fcf3ce44SJohn Forte uint8_t *node_name, 253fcf3ce44SJohn Forte size_t node_name_len, 254fcf3ce44SJohn Forte uint8_t *node_alias, 255fcf3ce44SJohn Forte size_t node_alias_len, 256fcf3ce44SJohn Forte uint32_t node_type, 257fcf3ce44SJohn Forte void (*scn_callback)(void *)) 258fcf3ce44SJohn Forte { 259fcf3ce44SJohn Forte int i; 260fcf3ce44SJohn Forte int list_space; 261fcf3ce44SJohn Forte iscsi_addr_list_t *isns_server_addr_list; 262fcf3ce44SJohn Forte isns_reg_arg_t *reg_args_p; 263fcf3ce44SJohn Forte 264fcf3ce44SJohn Forte /* Look up the iSNS Server address(es) based on the specified ISID */ 265fcf3ce44SJohn Forte if (discover_isns_server(lhba_handle, &isns_server_addr_list) != 266fcf3ce44SJohn Forte ISNS_OK) { 267fcf3ce44SJohn Forte return (isns_no_svr_found); 268fcf3ce44SJohn Forte } 269fcf3ce44SJohn Forte 270fcf3ce44SJohn Forte /* No iSNS server discovered - no registration needed. */ 271fcf3ce44SJohn Forte if (isns_server_addr_list->al_out_cnt == 0) { 272fcf3ce44SJohn Forte list_space = sizeof (iscsi_addr_list_t); 273fcf3ce44SJohn Forte kmem_free(isns_server_addr_list, list_space); 274fcf3ce44SJohn Forte isns_server_addr_list = NULL; 275fcf3ce44SJohn Forte return (isns_no_svr_found); 276fcf3ce44SJohn Forte } 277fcf3ce44SJohn Forte 278fcf3ce44SJohn Forte /* Check and create ESI/SCN threads and populate local address */ 279fcf3ce44SJohn Forte for (i = 0; i < isns_server_addr_list->al_out_cnt; i++) { 280fcf3ce44SJohn Forte if (create_esi_scn_thr(lhba_handle, 281fcf3ce44SJohn Forte &(isns_server_addr_list->al_addrs[i])) == ISNS_OK) { 282fcf3ce44SJohn Forte break; 283fcf3ce44SJohn Forte } 284fcf3ce44SJohn Forte } 285fcf3ce44SJohn Forte if (i == isns_server_addr_list->al_out_cnt) { 286fcf3ce44SJohn Forte /* 287fcf3ce44SJohn Forte * Problem creating ESI/SCN thread 288fcf3ce44SJohn Forte * Free the server list 289fcf3ce44SJohn Forte */ 290fcf3ce44SJohn Forte list_space = sizeof (iscsi_addr_list_t); 291fcf3ce44SJohn Forte if (isns_server_addr_list->al_out_cnt > 0) { 292fcf3ce44SJohn Forte list_space += (sizeof (iscsi_addr_t) * 293fcf3ce44SJohn Forte (isns_server_addr_list->al_out_cnt - 1)); 294fcf3ce44SJohn Forte } 295fcf3ce44SJohn Forte kmem_free(isns_server_addr_list, list_space); 296fcf3ce44SJohn Forte isns_server_addr_list = NULL; 297fcf3ce44SJohn Forte return (isns_internal_err); 298fcf3ce44SJohn Forte } 299fcf3ce44SJohn Forte 300fcf3ce44SJohn Forte /* Register against all iSNS servers discovered. */ 301fcf3ce44SJohn Forte for (i = 0; i < isns_server_addr_list->al_out_cnt; i++) { 302fcf3ce44SJohn Forte reg_args_p = kmem_zalloc(sizeof (isns_reg_arg_t), KM_SLEEP); 303fcf3ce44SJohn Forte reg_args_p->isns_server_addr = 304fcf3ce44SJohn Forte kmem_zalloc(sizeof (iscsi_addr_t), KM_SLEEP); 305fcf3ce44SJohn Forte bcopy(&isns_server_addr_list->al_addrs[i], 306fcf3ce44SJohn Forte reg_args_p->isns_server_addr, sizeof (iscsi_addr_t)); 307fcf3ce44SJohn Forte reg_args_p->node_name = kmem_zalloc(node_name_len, KM_SLEEP); 308fcf3ce44SJohn Forte bcopy(node_name, reg_args_p->node_name, node_name_len); 309fcf3ce44SJohn Forte reg_args_p->node_name_len = node_name_len; 310fcf3ce44SJohn Forte reg_args_p->node_alias = kmem_zalloc(node_alias_len, KM_SLEEP); 311fcf3ce44SJohn Forte bcopy(node_alias, reg_args_p->node_alias, node_alias_len); 312fcf3ce44SJohn Forte reg_args_p->node_alias_len = node_alias_len; 313fcf3ce44SJohn Forte reg_args_p->node_type = node_type; 314fcf3ce44SJohn Forte 315fcf3ce44SJohn Forte /* Dispatch the registration request */ 316fcf3ce44SJohn Forte register_isns_client(reg_args_p); 317fcf3ce44SJohn Forte } 318fcf3ce44SJohn Forte 319fcf3ce44SJohn Forte /* Free the server list */ 320fcf3ce44SJohn Forte list_space = sizeof (iscsi_addr_list_t); 321fcf3ce44SJohn Forte if (isns_server_addr_list->al_out_cnt > 0) { 322fcf3ce44SJohn Forte list_space += (sizeof (iscsi_addr_t) * 323fcf3ce44SJohn Forte (isns_server_addr_list->al_out_cnt - 1)); 324fcf3ce44SJohn Forte } 325fcf3ce44SJohn Forte kmem_free(isns_server_addr_list, list_space); 326fcf3ce44SJohn Forte isns_server_addr_list = NULL; 327fcf3ce44SJohn Forte 328fcf3ce44SJohn Forte /* Register the scn_callback. */ 329fcf3ce44SJohn Forte scn_callback_p = scn_callback; 330fcf3ce44SJohn Forte 331fcf3ce44SJohn Forte return (isns_ok); 332fcf3ce44SJohn Forte } 333fcf3ce44SJohn Forte 334fcf3ce44SJohn Forte isns_status_t 335fcf3ce44SJohn Forte isns_reg_one_server(entry_t *isns_server, 336fcf3ce44SJohn Forte uint8_t *lhba_handle, 337fcf3ce44SJohn Forte uint8_t *node_name, 338fcf3ce44SJohn Forte size_t node_name_len, 339fcf3ce44SJohn Forte uint8_t *node_alias, 340fcf3ce44SJohn Forte size_t node_alias_len, 341fcf3ce44SJohn Forte uint32_t node_type, 342fcf3ce44SJohn Forte void (*scn_callback)(void *)) 343fcf3ce44SJohn Forte { 344fcf3ce44SJohn Forte int status; 345fcf3ce44SJohn Forte iscsi_addr_t *ap; 346fcf3ce44SJohn Forte isns_reg_arg_t *reg_args_p; 347fcf3ce44SJohn Forte 348fcf3ce44SJohn Forte ap = (iscsi_addr_t *)kmem_zalloc(sizeof (iscsi_addr_t), KM_SLEEP); 349fcf3ce44SJohn Forte ap->a_port = isns_server->e_port; 350fcf3ce44SJohn Forte ap->a_addr.i_insize = isns_server->e_insize; 351fcf3ce44SJohn Forte if (isns_server->e_insize == sizeof (struct in_addr)) { 352fcf3ce44SJohn Forte ap->a_addr.i_addr.in4.s_addr = (isns_server->e_u.u_in4.s_addr); 353fcf3ce44SJohn Forte } else if (isns_server->e_insize == sizeof (struct in6_addr)) { 354fcf3ce44SJohn Forte bcopy(&(isns_server->e_u.u_in6.s6_addr), 355fcf3ce44SJohn Forte ap->a_addr.i_addr.in6.s6_addr, 356fcf3ce44SJohn Forte sizeof (struct in6_addr)); 357fcf3ce44SJohn Forte } else { 358fcf3ce44SJohn Forte kmem_free(ap, sizeof (iscsi_addr_t)); 359fcf3ce44SJohn Forte return (isns_op_failed); 360fcf3ce44SJohn Forte } 361fcf3ce44SJohn Forte 362fcf3ce44SJohn Forte /* Check and create ESI/SCN threads and populate local address */ 363fcf3ce44SJohn Forte if ((status = create_esi_scn_thr(lhba_handle, ap)) 364fcf3ce44SJohn Forte != ISNS_OK) { 365fcf3ce44SJohn Forte /* Problem creating ESI/SCN thread */ 366fcf3ce44SJohn Forte DTRACE_PROBE1(isns_reg_one_server_create_esi_scn_thr, 367fcf3ce44SJohn Forte int, status); 368fcf3ce44SJohn Forte kmem_free(ap, sizeof (iscsi_addr_t)); 369fcf3ce44SJohn Forte return (isns_internal_err); 370fcf3ce44SJohn Forte } 371fcf3ce44SJohn Forte 372fcf3ce44SJohn Forte reg_args_p = kmem_zalloc(sizeof (isns_reg_arg_t), KM_SLEEP); 373fcf3ce44SJohn Forte reg_args_p->isns_server_addr = 374fcf3ce44SJohn Forte kmem_zalloc(sizeof (iscsi_addr_t), KM_SLEEP); 375fcf3ce44SJohn Forte bcopy(ap, reg_args_p->isns_server_addr, sizeof (iscsi_addr_t)); 376fcf3ce44SJohn Forte reg_args_p->node_name = kmem_zalloc(node_name_len, KM_SLEEP); 377fcf3ce44SJohn Forte bcopy(node_name, reg_args_p->node_name, node_name_len); 378fcf3ce44SJohn Forte reg_args_p->node_name_len = node_name_len; 379fcf3ce44SJohn Forte reg_args_p->node_alias = kmem_zalloc(node_alias_len, KM_SLEEP); 380fcf3ce44SJohn Forte bcopy(node_alias, reg_args_p->node_alias, node_alias_len); 381fcf3ce44SJohn Forte reg_args_p->node_alias_len = node_alias_len; 382fcf3ce44SJohn Forte reg_args_p->node_type = node_type; 383fcf3ce44SJohn Forte 384fcf3ce44SJohn Forte /* Dispatch the registration request */ 385fcf3ce44SJohn Forte register_isns_client(reg_args_p); 386fcf3ce44SJohn Forte 387fcf3ce44SJohn Forte /* Register the scn_callback. */ 388fcf3ce44SJohn Forte scn_callback_p = scn_callback; 389fcf3ce44SJohn Forte 390fcf3ce44SJohn Forte kmem_free(ap, sizeof (iscsi_addr_t)); 391fcf3ce44SJohn Forte return (isns_ok); 392fcf3ce44SJohn Forte } 393fcf3ce44SJohn Forte 394fcf3ce44SJohn Forte isns_status_t 395fcf3ce44SJohn Forte isns_dereg(uint8_t *lhba_handle, 396fcf3ce44SJohn Forte uint8_t *node_name) 397fcf3ce44SJohn Forte { 398fcf3ce44SJohn Forte int i; 399fcf3ce44SJohn Forte int isns_svr_lst_sz; 400fcf3ce44SJohn Forte int list_space; 401fcf3ce44SJohn Forte iscsi_addr_list_t *isns_server_addr_list = NULL; 402fcf3ce44SJohn Forte isns_status_t dereg_stat, combined_dereg_stat; 403fcf3ce44SJohn Forte 404fcf3ce44SJohn Forte /* Look up the iSNS Server address(es) based on the specified ISID */ 405fcf3ce44SJohn Forte if (discover_isns_server(lhba_handle, &isns_server_addr_list) != 406fcf3ce44SJohn Forte ISNS_OK) { 407fcf3ce44SJohn Forte return (isns_no_svr_found); 408fcf3ce44SJohn Forte } 409fcf3ce44SJohn Forte ASSERT(isns_server_addr_list != NULL); 410fcf3ce44SJohn Forte if (isns_server_addr_list->al_out_cnt == 0) { 411fcf3ce44SJohn Forte isns_svr_lst_sz = sizeof (iscsi_addr_list_t); 412fcf3ce44SJohn Forte kmem_free(isns_server_addr_list, isns_svr_lst_sz); 413fcf3ce44SJohn Forte isns_server_addr_list = NULL; 414fcf3ce44SJohn Forte return (isns_no_svr_found); 415fcf3ce44SJohn Forte } 416fcf3ce44SJohn Forte 417fcf3ce44SJohn Forte combined_dereg_stat = isns_ok; 418fcf3ce44SJohn Forte for (i = 0; i < isns_server_addr_list->al_out_cnt; i++) { 419fcf3ce44SJohn Forte dereg_stat = do_isns_dev_dereg( 420fcf3ce44SJohn Forte &isns_server_addr_list->al_addrs[i], 421fcf3ce44SJohn Forte node_name); 422fcf3ce44SJohn Forte if (dereg_stat == isns_ok) { 423fcf3ce44SJohn Forte if (combined_dereg_stat != isns_ok) { 424fcf3ce44SJohn Forte combined_dereg_stat = isns_op_partially_failed; 425fcf3ce44SJohn Forte } 426fcf3ce44SJohn Forte } else { 427fcf3ce44SJohn Forte if (combined_dereg_stat == isns_ok) { 428fcf3ce44SJohn Forte combined_dereg_stat = isns_op_partially_failed; 429fcf3ce44SJohn Forte } 430fcf3ce44SJohn Forte } 431fcf3ce44SJohn Forte } 432fcf3ce44SJohn Forte 433fcf3ce44SJohn Forte /* Free the server list. */ 434fcf3ce44SJohn Forte list_space = sizeof (iscsi_addr_list_t); 435fcf3ce44SJohn Forte if (isns_server_addr_list->al_out_cnt > 0) { 436fcf3ce44SJohn Forte list_space += (sizeof (iscsi_addr_t) * 437fcf3ce44SJohn Forte (isns_server_addr_list->al_out_cnt - 1)); 438fcf3ce44SJohn Forte } 439fcf3ce44SJohn Forte kmem_free(isns_server_addr_list, list_space); 440fcf3ce44SJohn Forte isns_server_addr_list = NULL; 441fcf3ce44SJohn Forte 442fcf3ce44SJohn Forte /* Cleanup ESI/SCN thread. */ 443fcf3ce44SJohn Forte esi_scn_thr_cleanup(); 444fcf3ce44SJohn Forte 445fcf3ce44SJohn Forte return (combined_dereg_stat); 446fcf3ce44SJohn Forte } 447fcf3ce44SJohn Forte 448fcf3ce44SJohn Forte isns_status_t 449fcf3ce44SJohn Forte isns_dereg_one_server(entry_t *isns_server, 450fcf3ce44SJohn Forte uint8_t *node_name, 451fcf3ce44SJohn Forte boolean_t is_last_isns_server_b) 452fcf3ce44SJohn Forte { 453fcf3ce44SJohn Forte iscsi_addr_t *ap; 454fcf3ce44SJohn Forte isns_status_t dereg_stat; 455fcf3ce44SJohn Forte 456fcf3ce44SJohn Forte ap = (iscsi_addr_t *)kmem_zalloc(sizeof (iscsi_addr_t), KM_SLEEP); 457fcf3ce44SJohn Forte ap->a_port = isns_server->e_port; 458fcf3ce44SJohn Forte ap->a_addr.i_insize = isns_server->e_insize; 459fcf3ce44SJohn Forte if (isns_server->e_insize == sizeof (struct in_addr)) { 460fcf3ce44SJohn Forte ap->a_addr.i_addr.in4.s_addr = (isns_server->e_u.u_in4.s_addr); 461fcf3ce44SJohn Forte } else if (isns_server->e_insize == sizeof (struct in6_addr)) { 462fcf3ce44SJohn Forte bcopy(&(isns_server->e_u.u_in6.s6_addr), 463fcf3ce44SJohn Forte ap->a_addr.i_addr.in6.s6_addr, 464fcf3ce44SJohn Forte sizeof (struct in6_addr)); 465fcf3ce44SJohn Forte } else { 466fcf3ce44SJohn Forte kmem_free(ap, sizeof (iscsi_addr_t)); 467fcf3ce44SJohn Forte return (isns_op_failed); 468fcf3ce44SJohn Forte } 469fcf3ce44SJohn Forte 470fcf3ce44SJohn Forte dereg_stat = do_isns_dev_dereg(ap, node_name); 471fcf3ce44SJohn Forte 472fcf3ce44SJohn Forte kmem_free(ap, sizeof (iscsi_addr_t)); 473fcf3ce44SJohn Forte 474fcf3ce44SJohn Forte if (is_last_isns_server_b == B_TRUE) { 475fcf3ce44SJohn Forte /* 476fcf3ce44SJohn Forte * Clean up ESI/SCN thread resource if it is the 477fcf3ce44SJohn Forte * last known iSNS server. 478fcf3ce44SJohn Forte */ 479fcf3ce44SJohn Forte esi_scn_thr_cleanup(); 480fcf3ce44SJohn Forte } 481fcf3ce44SJohn Forte 482fcf3ce44SJohn Forte return (dereg_stat); 483fcf3ce44SJohn Forte } 484fcf3ce44SJohn Forte 485fcf3ce44SJohn Forte isns_status_t 486fcf3ce44SJohn Forte isns_query(uint8_t *lhba_handle, 487fcf3ce44SJohn Forte uint8_t *node_name, 488fcf3ce44SJohn Forte uint8_t *node_alias, 489fcf3ce44SJohn Forte uint32_t node_type, 490fcf3ce44SJohn Forte isns_portal_group_list_t **pg_list) 491fcf3ce44SJohn Forte { 492fcf3ce44SJohn Forte return (do_isns_query(B_TRUE, 493fcf3ce44SJohn Forte lhba_handle, 494fcf3ce44SJohn Forte (uint8_t *)"", 495fcf3ce44SJohn Forte node_name, 496fcf3ce44SJohn Forte node_alias, 497fcf3ce44SJohn Forte node_type, 498fcf3ce44SJohn Forte pg_list)); 499fcf3ce44SJohn Forte } 500fcf3ce44SJohn Forte 501fcf3ce44SJohn Forte /* ARGSUSED */ 502fcf3ce44SJohn Forte isns_status_t 503fcf3ce44SJohn Forte isns_query_one_server(iscsi_addr_t *isns_server_addr, 504fcf3ce44SJohn Forte uint8_t *lhba_handle, 505fcf3ce44SJohn Forte uint8_t *node_name, 506fcf3ce44SJohn Forte uint8_t *node_alias, 507fcf3ce44SJohn Forte uint32_t node_type, 508fcf3ce44SJohn Forte isns_portal_group_list_t **pg_list) 509fcf3ce44SJohn Forte { 510fcf3ce44SJohn Forte return (do_isns_dev_attr_query_all_nodes(isns_server_addr, 511fcf3ce44SJohn Forte node_name, 512fcf3ce44SJohn Forte node_alias, 513fcf3ce44SJohn Forte pg_list)); 514fcf3ce44SJohn Forte } 515fcf3ce44SJohn Forte 516fcf3ce44SJohn Forte isns_status_t 517fcf3ce44SJohn Forte isns_query_one_node(uint8_t *target_node_name, 518fcf3ce44SJohn Forte uint8_t *lhba_handle, 519fcf3ce44SJohn Forte uint8_t *source_node_name, 520fcf3ce44SJohn Forte uint8_t *source_node_alias, 521fcf3ce44SJohn Forte uint32_t source_node_type, 522fcf3ce44SJohn Forte isns_portal_group_list_t **pg_list) 523fcf3ce44SJohn Forte { 524fcf3ce44SJohn Forte return (do_isns_query(B_FALSE, 525fcf3ce44SJohn Forte lhba_handle, 526fcf3ce44SJohn Forte target_node_name, 527fcf3ce44SJohn Forte source_node_name, 528fcf3ce44SJohn Forte source_node_alias, 529fcf3ce44SJohn Forte source_node_type, 530fcf3ce44SJohn Forte pg_list)); 531fcf3ce44SJohn Forte } 532fcf3ce44SJohn Forte 533fcf3ce44SJohn Forte /* ARGSUSED */ 534fcf3ce44SJohn Forte isns_status_t 535fcf3ce44SJohn Forte isns_query_one_server_one_node(iscsi_addr_t *isns_server_addr, 536fcf3ce44SJohn Forte uint8_t *target_node_name, 537fcf3ce44SJohn Forte uint8_t *lhba_handle, 538fcf3ce44SJohn Forte uint8_t *source_node_name, 539fcf3ce44SJohn Forte uint8_t *source_node_alias, 540fcf3ce44SJohn Forte uint32_t source_node_type, 541fcf3ce44SJohn Forte isns_portal_group_list_t **pg_list) { 542fcf3ce44SJohn Forte /* Not supported yet. */ 543fcf3ce44SJohn Forte *pg_list = NULL; 544fcf3ce44SJohn Forte return (isns_op_failed); 545fcf3ce44SJohn Forte } 546fcf3ce44SJohn Forte 547fcf3ce44SJohn Forte /* ARGSUSED */ 548fcf3ce44SJohn Forte static 549fcf3ce44SJohn Forte int 550fcf3ce44SJohn Forte discover_isns_server(uint8_t *lhba_handle, 551fcf3ce44SJohn Forte iscsi_addr_list_t **isns_server_addrs) 552fcf3ce44SJohn Forte { 553fcf3ce44SJohn Forte entry_t e; 554fcf3ce44SJohn Forte int i; 555fcf3ce44SJohn Forte int isns_server_count = 1; 556fcf3ce44SJohn Forte int list_space; 557fcf3ce44SJohn Forte void *void_p; 558fcf3ce44SJohn Forte 559fcf3ce44SJohn Forte /* 560fcf3ce44SJohn Forte * Use supported iSNS server discovery method to find out all the 561fcf3ce44SJohn Forte * iSNS servers. For now, only static configuration method is 562fcf3ce44SJohn Forte * supported. 563fcf3ce44SJohn Forte */ 564fcf3ce44SJohn Forte isns_server_count = 0; 565fcf3ce44SJohn Forte void_p = NULL; 566fcf3ce44SJohn Forte persistent_isns_addr_lock(); 567fcf3ce44SJohn Forte while (persistent_isns_addr_next(&void_p, &e) == B_TRUE) { 568fcf3ce44SJohn Forte isns_server_count++; 569fcf3ce44SJohn Forte } 570fcf3ce44SJohn Forte persistent_isns_addr_unlock(); 571fcf3ce44SJohn Forte 572fcf3ce44SJohn Forte list_space = sizeof (iscsi_addr_list_t); 573fcf3ce44SJohn Forte if (isns_server_count > 0) { 574fcf3ce44SJohn Forte list_space += (sizeof (iscsi_addr_t) * (isns_server_count - 1)); 575fcf3ce44SJohn Forte } 576fcf3ce44SJohn Forte *isns_server_addrs = (iscsi_addr_list_t *)kmem_zalloc(list_space, 577fcf3ce44SJohn Forte KM_SLEEP); 578fcf3ce44SJohn Forte (*isns_server_addrs)->al_out_cnt = isns_server_count; 579fcf3ce44SJohn Forte 580fcf3ce44SJohn Forte persistent_isns_addr_lock(); 581fcf3ce44SJohn Forte i = 0; 582fcf3ce44SJohn Forte void_p = NULL; 583fcf3ce44SJohn Forte while (persistent_isns_addr_next(&void_p, &e) == B_TRUE) { 584fcf3ce44SJohn Forte iscsi_addr_t *ap; 585fcf3ce44SJohn Forte 586fcf3ce44SJohn Forte ap = &((*isns_server_addrs)->al_addrs[i]); 587fcf3ce44SJohn Forte ap->a_port = e.e_port; 588fcf3ce44SJohn Forte ap->a_addr.i_insize = e.e_insize; 589fcf3ce44SJohn Forte if (e.e_insize == sizeof (struct in_addr)) { 590fcf3ce44SJohn Forte ap->a_addr.i_addr.in4.s_addr = (e.e_u.u_in4.s_addr); 591fcf3ce44SJohn Forte } else if (e.e_insize == sizeof (struct in6_addr)) { 592fcf3ce44SJohn Forte bcopy(&e.e_u.u_in6.s6_addr, 593fcf3ce44SJohn Forte ap->a_addr.i_addr.in6.s6_addr, 594fcf3ce44SJohn Forte sizeof (struct in6_addr)); 595fcf3ce44SJohn Forte } else { 596fcf3ce44SJohn Forte kmem_free(*isns_server_addrs, list_space); 597fcf3ce44SJohn Forte *isns_server_addrs = NULL; 598fcf3ce44SJohn Forte (*isns_server_addrs)->al_out_cnt = 0; 599fcf3ce44SJohn Forte return (ISNS_BAD_SVR_ADDR); 600fcf3ce44SJohn Forte } 601fcf3ce44SJohn Forte i++; 602fcf3ce44SJohn Forte } 603fcf3ce44SJohn Forte persistent_isns_addr_unlock(); 604fcf3ce44SJohn Forte 605fcf3ce44SJohn Forte return (ISNS_OK); 606fcf3ce44SJohn Forte } 607fcf3ce44SJohn Forte 608fcf3ce44SJohn Forte static 609fcf3ce44SJohn Forte int 610fcf3ce44SJohn Forte create_esi_scn_thr(uint8_t *lhba_handle, iscsi_addr_t *isns_server_address) 611fcf3ce44SJohn Forte { 612fcf3ce44SJohn Forte iscsi_addr_t *tmp_local_addr; 613fcf3ce44SJohn Forte void *listening_so = NULL; 614fcf3ce44SJohn Forte 615fcf3ce44SJohn Forte ASSERT(lhba_handle != NULL); 616fcf3ce44SJohn Forte ASSERT(isns_server_address != NULL); 617fcf3ce44SJohn Forte 618fcf3ce44SJohn Forte /* Determine local port and address. */ 619fcf3ce44SJohn Forte mutex_enter(&esi_scn_thr_mutex); 620fcf3ce44SJohn Forte if (local_addr == NULL) { 621fcf3ce44SJohn Forte boolean_t rval; 622fcf3ce44SJohn Forte rval = find_local_portal(isns_server_address, 623fcf3ce44SJohn Forte &tmp_local_addr, &listening_so); 624fcf3ce44SJohn Forte if (rval == B_FALSE) { 625fcf3ce44SJohn Forte local_addr = NULL; 626fcf3ce44SJohn Forte mutex_exit(&esi_scn_thr_mutex); 627fcf3ce44SJohn Forte if (listening_so != NULL) { 628fcf3ce44SJohn Forte iscsi_net->close(listening_so); 629fcf3ce44SJohn Forte } 630fcf3ce44SJohn Forte return (ISNS_CANNOT_FIND_LOCAL_ADDR); 631fcf3ce44SJohn Forte } 632fcf3ce44SJohn Forte local_addr = tmp_local_addr; 633fcf3ce44SJohn Forte } 634fcf3ce44SJohn Forte mutex_exit(&esi_scn_thr_mutex); 635fcf3ce44SJohn Forte 636fcf3ce44SJohn Forte /* 637fcf3ce44SJohn Forte * Bringing up of the thread should happen regardless of the 638fcf3ce44SJohn Forte * subsequent registration status. That means, do not destroy the 639fcf3ce44SJohn Forte * ESI/SCN thread already created. 640fcf3ce44SJohn Forte */ 641fcf3ce44SJohn Forte /* Check and create ESI/SCN thread. */ 642fcf3ce44SJohn Forte mutex_enter(&esi_scn_thr_mutex); 643fcf3ce44SJohn Forte if (esi_scn_thr_id == NULL) { 644fcf3ce44SJohn Forte char thr_name[ISCSI_TH_MAX_NAME_LEN]; 645fcf3ce44SJohn Forte int rval; 646fcf3ce44SJohn Forte isns_async_thread_arg_t *larg; 647fcf3ce44SJohn Forte 648fcf3ce44SJohn Forte /* Assume the LHBA handle has a length of 4 */ 649fcf3ce44SJohn Forte if (snprintf(thr_name, sizeof (thr_name) - 1, 650fcf3ce44SJohn Forte "isns_client_esi_%x%x%x%x", 651fcf3ce44SJohn Forte lhba_handle[0], 652fcf3ce44SJohn Forte lhba_handle[1], 653fcf3ce44SJohn Forte lhba_handle[2], 654fcf3ce44SJohn Forte lhba_handle[3]) >= 655fcf3ce44SJohn Forte sizeof (thr_name)) { 656fcf3ce44SJohn Forte esi_scn_thr_id = NULL; 657fcf3ce44SJohn Forte if (local_addr != NULL) { 658fcf3ce44SJohn Forte kmem_free(local_addr, sizeof (iscsi_addr_t)); 659fcf3ce44SJohn Forte local_addr = NULL; 660fcf3ce44SJohn Forte } 661fcf3ce44SJohn Forte if (listening_so != NULL) { 662fcf3ce44SJohn Forte iscsi_net->close(listening_so); 663fcf3ce44SJohn Forte listening_so = NULL; 664fcf3ce44SJohn Forte } 665fcf3ce44SJohn Forte mutex_exit(&esi_scn_thr_mutex); 666fcf3ce44SJohn Forte return (ISNS_INTERNAL_ERR); 667fcf3ce44SJohn Forte } 668fcf3ce44SJohn Forte 669fcf3ce44SJohn Forte larg = kmem_zalloc(sizeof (isns_async_thread_arg_t), KM_SLEEP); 670fcf3ce44SJohn Forte larg->lhba_handle = lhba_handle; 671fcf3ce44SJohn Forte larg->listening_so = listening_so; 672fcf3ce44SJohn Forte instance_listening_so = listening_so; 673fcf3ce44SJohn Forte esi_scn_thr_to_shutdown = B_FALSE; 674fcf3ce44SJohn Forte esi_scn_thr_id = iscsi_thread_create(NULL, 675fcf3ce44SJohn Forte thr_name, isns_service_esi_scn, (void *)larg); 676fcf3ce44SJohn Forte if (esi_scn_thr_id == NULL) { 677fcf3ce44SJohn Forte if (local_addr != NULL) { 678fcf3ce44SJohn Forte kmem_free(local_addr, sizeof (iscsi_addr_t)); 679fcf3ce44SJohn Forte local_addr = NULL; 680fcf3ce44SJohn Forte } 681fcf3ce44SJohn Forte if (listening_so != NULL) { 682fcf3ce44SJohn Forte iscsi_net->close(listening_so); 683fcf3ce44SJohn Forte listening_so = NULL; 684fcf3ce44SJohn Forte instance_listening_so = NULL; 685fcf3ce44SJohn Forte } 686fcf3ce44SJohn Forte mutex_exit(&esi_scn_thr_mutex); 687fcf3ce44SJohn Forte return (ISNS_INTERNAL_ERR); 688fcf3ce44SJohn Forte } 689fcf3ce44SJohn Forte 690fcf3ce44SJohn Forte rval = iscsi_thread_start(esi_scn_thr_id); 691fcf3ce44SJohn Forte if (rval == B_FALSE) { 692fcf3ce44SJohn Forte iscsi_thread_destroy(esi_scn_thr_id); 693fcf3ce44SJohn Forte esi_scn_thr_id = NULL; 694fcf3ce44SJohn Forte if (local_addr != NULL) { 695fcf3ce44SJohn Forte kmem_free(local_addr, sizeof (iscsi_addr_t)); 696fcf3ce44SJohn Forte local_addr = NULL; 697fcf3ce44SJohn Forte } 698fcf3ce44SJohn Forte if (listening_so != NULL) { 699fcf3ce44SJohn Forte iscsi_net->close(listening_so); 700fcf3ce44SJohn Forte listening_so = NULL; 701fcf3ce44SJohn Forte instance_listening_so = NULL; 702fcf3ce44SJohn Forte } 703fcf3ce44SJohn Forte mutex_exit(&esi_scn_thr_mutex); 704fcf3ce44SJohn Forte return (ISNS_INTERNAL_ERR); 705fcf3ce44SJohn Forte } 706fcf3ce44SJohn Forte iscsi_thread_send_wakeup(esi_scn_thr_id); 707fcf3ce44SJohn Forte } 708fcf3ce44SJohn Forte mutex_exit(&esi_scn_thr_mutex); 709fcf3ce44SJohn Forte 710fcf3ce44SJohn Forte return (ISNS_OK); 711fcf3ce44SJohn Forte } 712fcf3ce44SJohn Forte 713fcf3ce44SJohn Forte static 714fcf3ce44SJohn Forte void 715fcf3ce44SJohn Forte register_isns_client(void *arg) 716fcf3ce44SJohn Forte { 717fcf3ce44SJohn Forte isns_reg_arg_t *reg_args; 718fcf3ce44SJohn Forte isns_status_t status; 719fcf3ce44SJohn Forte 720fcf3ce44SJohn Forte reg_args = (isns_reg_arg_t *)arg; 721fcf3ce44SJohn Forte 722fcf3ce44SJohn Forte /* Deregister stale registration (if any). */ 723fcf3ce44SJohn Forte status = do_isns_dev_dereg(reg_args->isns_server_addr, 724fcf3ce44SJohn Forte reg_args->node_name); 725fcf3ce44SJohn Forte 726fcf3ce44SJohn Forte if (status == isns_open_conn_err) { 727fcf3ce44SJohn Forte /* Cannot open connection to the server. Stop proceeding. */ 728fcf3ce44SJohn Forte kmem_free(reg_args->isns_server_addr, sizeof (iscsi_addr_t)); 729fcf3ce44SJohn Forte reg_args->isns_server_addr = NULL; 730fcf3ce44SJohn Forte kmem_free(reg_args->node_name, reg_args->node_name_len); 731fcf3ce44SJohn Forte reg_args->node_name = NULL; 732fcf3ce44SJohn Forte kmem_free(reg_args->node_alias, reg_args->node_alias_len); 733fcf3ce44SJohn Forte reg_args->node_alias = NULL; 734fcf3ce44SJohn Forte kmem_free(reg_args, sizeof (isns_reg_arg_t)); 735fcf3ce44SJohn Forte return; 736fcf3ce44SJohn Forte } 737fcf3ce44SJohn Forte 738fcf3ce44SJohn Forte DTRACE_PROBE1(register_isns_client_dereg, isns_status_t, status); 739fcf3ce44SJohn Forte 740fcf3ce44SJohn Forte /* New registration. */ 741fcf3ce44SJohn Forte status = do_isns_dev_attr_reg(reg_args->isns_server_addr, 742fcf3ce44SJohn Forte reg_args->node_name, reg_args->node_alias, reg_args->node_type); 743fcf3ce44SJohn Forte 744fcf3ce44SJohn Forte DTRACE_PROBE1(register_isns_client_reg, isns_status_t, status); 745fcf3ce44SJohn Forte 746fcf3ce44SJohn Forte /* Cleanup */ 747fcf3ce44SJohn Forte kmem_free(reg_args->isns_server_addr, sizeof (iscsi_addr_t)); 748fcf3ce44SJohn Forte reg_args->isns_server_addr = NULL; 749fcf3ce44SJohn Forte kmem_free(reg_args->node_name, reg_args->node_name_len); 750fcf3ce44SJohn Forte reg_args->node_name = NULL; 751fcf3ce44SJohn Forte kmem_free(reg_args->node_alias, reg_args->node_alias_len); 752fcf3ce44SJohn Forte reg_args->node_alias = NULL; 753fcf3ce44SJohn Forte kmem_free(reg_args, sizeof (isns_reg_arg_t)); 754fcf3ce44SJohn Forte } 755fcf3ce44SJohn Forte 756fcf3ce44SJohn Forte static 757fcf3ce44SJohn Forte isns_status_t 758fcf3ce44SJohn Forte do_isns_dev_attr_reg(iscsi_addr_t *isns_server_addr, 759fcf3ce44SJohn Forte uint8_t *node_name, uint8_t *node_alias, uint32_t node_type) 760fcf3ce44SJohn Forte { 761fcf3ce44SJohn Forte int rcv_rsp_cnt = 0; 762fcf3ce44SJohn Forte int rsp_status; 763fcf3ce44SJohn Forte isns_pdu_t *in_pdu, *out_pdu; 764fcf3ce44SJohn Forte isns_status_t rval; 765fcf3ce44SJohn Forte size_t bytes_received, in_pdu_size = 0, out_pdu_size = 0; 766fcf3ce44SJohn Forte uint16_t xid; 767fcf3ce44SJohn Forte void *so = NULL; 768fcf3ce44SJohn Forte 769fcf3ce44SJohn Forte out_pdu_size = isns_create_dev_attr_reg_pdu( 770fcf3ce44SJohn Forte node_name, 771fcf3ce44SJohn Forte node_alias, 772fcf3ce44SJohn Forte node_type, 773fcf3ce44SJohn Forte &xid, &out_pdu); 774fcf3ce44SJohn Forte if (out_pdu_size == 0) { 775fcf3ce44SJohn Forte return (isns_create_msg_err); 776fcf3ce44SJohn Forte } 777fcf3ce44SJohn Forte 778fcf3ce44SJohn Forte ASSERT(out_pdu != NULL); 779fcf3ce44SJohn Forte ASSERT(out_pdu_size > 0); 780fcf3ce44SJohn Forte 781fcf3ce44SJohn Forte so = isns_open(isns_server_addr); 782fcf3ce44SJohn Forte if (so == NULL) { 783fcf3ce44SJohn Forte /* Log a message and return */ 784fcf3ce44SJohn Forte kmem_free(out_pdu, out_pdu_size); 785fcf3ce44SJohn Forte out_pdu = NULL; 786fcf3ce44SJohn Forte return (isns_open_conn_err); 787fcf3ce44SJohn Forte } 788fcf3ce44SJohn Forte 789fcf3ce44SJohn Forte if (isns_send_pdu(so, out_pdu) != 0) { 790fcf3ce44SJohn Forte iscsi_net->close(so); 791fcf3ce44SJohn Forte kmem_free(out_pdu, out_pdu_size); 792fcf3ce44SJohn Forte out_pdu = NULL; 793fcf3ce44SJohn Forte return (isns_send_msg_err); 794fcf3ce44SJohn Forte } 795fcf3ce44SJohn Forte 796fcf3ce44SJohn Forte /* Done with the out PDU - free it */ 797fcf3ce44SJohn Forte kmem_free(out_pdu, out_pdu_size); 798fcf3ce44SJohn Forte out_pdu = NULL; 799fcf3ce44SJohn Forte 800fcf3ce44SJohn Forte rcv_rsp_cnt = 0; 801fcf3ce44SJohn Forte rval = isns_ok; 802fcf3ce44SJohn Forte for (;;) { 803fcf3ce44SJohn Forte bytes_received = isns_rcv_pdu(so, &in_pdu, &in_pdu_size); 804fcf3ce44SJohn Forte ASSERT(bytes_received >= (size_t)0); 805fcf3ce44SJohn Forte if (bytes_received == 0) { 806fcf3ce44SJohn Forte ASSERT(in_pdu == NULL); 807fcf3ce44SJohn Forte ASSERT(in_pdu_size == 0); 808fcf3ce44SJohn Forte rval = isns_rcv_msg_err; 809fcf3ce44SJohn Forte break; 810fcf3ce44SJohn Forte } 811fcf3ce44SJohn Forte 812fcf3ce44SJohn Forte ASSERT(in_pdu != NULL); 813fcf3ce44SJohn Forte ASSERT(in_pdu_size > 0); 814fcf3ce44SJohn Forte 815fcf3ce44SJohn Forte if (ntohs(in_pdu->xid) != xid) { 816fcf3ce44SJohn Forte rcv_rsp_cnt++; 817fcf3ce44SJohn Forte if (rcv_rsp_cnt < MAX_RCV_RSP_COUNT) { 818fcf3ce44SJohn Forte continue; 819fcf3ce44SJohn Forte } else { 820fcf3ce44SJohn Forte /* Exceed maximum receive count. */ 821fcf3ce44SJohn Forte kmem_free(in_pdu, in_pdu_size); 822fcf3ce44SJohn Forte in_pdu = NULL; 823fcf3ce44SJohn Forte rval = isns_no_rsp_rcvd; 824fcf3ce44SJohn Forte break; 825fcf3ce44SJohn Forte } 826fcf3ce44SJohn Forte } 827fcf3ce44SJohn Forte 828fcf3ce44SJohn Forte rsp_status = isns_process_dev_attr_reg_rsp(in_pdu); 829fcf3ce44SJohn Forte if (rsp_status != ISNS_RSP_SUCCESSFUL) { 830fcf3ce44SJohn Forte if (rsp_status == ISNS_RSP_SRC_UNAUTHORIZED) { 831fcf3ce44SJohn Forte rval = isns_op_partially_failed; 832fcf3ce44SJohn Forte } else { 833fcf3ce44SJohn Forte rval = isns_op_failed; 834fcf3ce44SJohn Forte } 835fcf3ce44SJohn Forte } 836fcf3ce44SJohn Forte kmem_free(in_pdu, in_pdu_size); 837fcf3ce44SJohn Forte in_pdu = NULL; 838fcf3ce44SJohn Forte break; 839fcf3ce44SJohn Forte } 840fcf3ce44SJohn Forte 841fcf3ce44SJohn Forte if (rval != isns_ok) { 842fcf3ce44SJohn Forte iscsi_net->close(so); 843fcf3ce44SJohn Forte return (rval); 844fcf3ce44SJohn Forte } 845fcf3ce44SJohn Forte 846fcf3ce44SJohn Forte /* Always register SCN */ 847fcf3ce44SJohn Forte out_pdu_size = isns_create_scn_reg_pdu( 848fcf3ce44SJohn Forte node_name, node_alias, 849fcf3ce44SJohn Forte &xid, &out_pdu); 850fcf3ce44SJohn Forte if (out_pdu_size == 0) { 851fcf3ce44SJohn Forte iscsi_net->close(so); 852fcf3ce44SJohn Forte return (isns_create_msg_err); 853fcf3ce44SJohn Forte } 854fcf3ce44SJohn Forte 855fcf3ce44SJohn Forte ASSERT(out_pdu != NULL); 856fcf3ce44SJohn Forte ASSERT(out_pdu_size > 0); 857fcf3ce44SJohn Forte 858fcf3ce44SJohn Forte if (isns_send_pdu(so, out_pdu) != 0) { 859fcf3ce44SJohn Forte iscsi_net->close(so); 860fcf3ce44SJohn Forte kmem_free(out_pdu, out_pdu_size); 861fcf3ce44SJohn Forte out_pdu = NULL; 862fcf3ce44SJohn Forte return (isns_send_msg_err); 863fcf3ce44SJohn Forte } 864fcf3ce44SJohn Forte 865fcf3ce44SJohn Forte /* Done with the out PDU - free it */ 866fcf3ce44SJohn Forte kmem_free(out_pdu, out_pdu_size); 867fcf3ce44SJohn Forte out_pdu = NULL; 868fcf3ce44SJohn Forte 869fcf3ce44SJohn Forte rcv_rsp_cnt = 0; 870fcf3ce44SJohn Forte for (;;) { 871fcf3ce44SJohn Forte bytes_received = isns_rcv_pdu(so, &in_pdu, &in_pdu_size); 872fcf3ce44SJohn Forte ASSERT(bytes_received >= (size_t)0); 873fcf3ce44SJohn Forte if (bytes_received == 0) { 874fcf3ce44SJohn Forte ASSERT(in_pdu == NULL); 875fcf3ce44SJohn Forte ASSERT(in_pdu_size == 0); 876fcf3ce44SJohn Forte rval = isns_rcv_msg_err; 877fcf3ce44SJohn Forte break; 878fcf3ce44SJohn Forte } 879fcf3ce44SJohn Forte 880fcf3ce44SJohn Forte ASSERT(in_pdu != NULL); 881fcf3ce44SJohn Forte ASSERT(in_pdu_size > 0); 882fcf3ce44SJohn Forte 883fcf3ce44SJohn Forte if (ntohs(in_pdu->xid) != xid) { 884fcf3ce44SJohn Forte rcv_rsp_cnt++; 885fcf3ce44SJohn Forte if (rcv_rsp_cnt < MAX_RCV_RSP_COUNT) { 886fcf3ce44SJohn Forte continue; 887fcf3ce44SJohn Forte } else { 888fcf3ce44SJohn Forte /* Exceed maximum receive count. */ 889fcf3ce44SJohn Forte kmem_free(in_pdu, in_pdu_size); 890fcf3ce44SJohn Forte in_pdu = NULL; 891fcf3ce44SJohn Forte rval = isns_no_rsp_rcvd; 892fcf3ce44SJohn Forte break; 893fcf3ce44SJohn Forte } 894fcf3ce44SJohn Forte } 895fcf3ce44SJohn Forte 896fcf3ce44SJohn Forte rsp_status = isns_process_scn_reg_rsp(in_pdu); 897fcf3ce44SJohn Forte if (rsp_status != ISNS_RSP_SUCCESSFUL) { 898fcf3ce44SJohn Forte rval = isns_op_failed; 899fcf3ce44SJohn Forte } 900fcf3ce44SJohn Forte kmem_free(in_pdu, in_pdu_size); 901fcf3ce44SJohn Forte in_pdu = NULL; 902fcf3ce44SJohn Forte break; 903fcf3ce44SJohn Forte } 904fcf3ce44SJohn Forte 905fcf3ce44SJohn Forte iscsi_net->close(so); 906fcf3ce44SJohn Forte 907fcf3ce44SJohn Forte return (rval); 908fcf3ce44SJohn Forte } 909fcf3ce44SJohn Forte 910fcf3ce44SJohn Forte static 911fcf3ce44SJohn Forte isns_status_t 912fcf3ce44SJohn Forte do_isns_dev_dereg(iscsi_addr_t *isns_server_addr, 913fcf3ce44SJohn Forte uint8_t *node_name) 914fcf3ce44SJohn Forte { 915fcf3ce44SJohn Forte int rcv_rsp_cnt = 0; 916fcf3ce44SJohn Forte int rsp_status; 917fcf3ce44SJohn Forte isns_pdu_t *in_pdu, *out_pdu; 918fcf3ce44SJohn Forte isns_status_t rval; 919fcf3ce44SJohn Forte size_t bytes_received, in_pdu_size = 0, out_pdu_size = 0; 920fcf3ce44SJohn Forte uint16_t xid; 921fcf3ce44SJohn Forte void *so = NULL; 922fcf3ce44SJohn Forte 923fcf3ce44SJohn Forte out_pdu_size = isns_create_dev_dereg_pdu( 924fcf3ce44SJohn Forte node_name, 925fcf3ce44SJohn Forte &xid, &out_pdu); 926fcf3ce44SJohn Forte if (out_pdu_size == 0) { 927fcf3ce44SJohn Forte return (isns_create_msg_err); 928fcf3ce44SJohn Forte } 929fcf3ce44SJohn Forte 930fcf3ce44SJohn Forte ASSERT(out_pdu != NULL); 931fcf3ce44SJohn Forte ASSERT(out_pdu_size > 0); 932fcf3ce44SJohn Forte 933fcf3ce44SJohn Forte so = isns_open(isns_server_addr); 934fcf3ce44SJohn Forte if (so == NULL) { 935fcf3ce44SJohn Forte /* Log a message and return */ 936fcf3ce44SJohn Forte kmem_free(out_pdu, out_pdu_size); 937fcf3ce44SJohn Forte out_pdu = NULL; 938fcf3ce44SJohn Forte return (isns_open_conn_err); 939fcf3ce44SJohn Forte } 940fcf3ce44SJohn Forte 941fcf3ce44SJohn Forte if (isns_send_pdu(so, out_pdu) != 0) { 942fcf3ce44SJohn Forte iscsi_net->close(so); 943fcf3ce44SJohn Forte kmem_free(out_pdu, out_pdu_size); 944fcf3ce44SJohn Forte out_pdu = NULL; 945fcf3ce44SJohn Forte return (isns_send_msg_err); 946fcf3ce44SJohn Forte } 947fcf3ce44SJohn Forte 948fcf3ce44SJohn Forte /* Done with the out PDU - free it */ 949fcf3ce44SJohn Forte kmem_free(out_pdu, out_pdu_size); 950fcf3ce44SJohn Forte out_pdu = NULL; 951fcf3ce44SJohn Forte 952fcf3ce44SJohn Forte rcv_rsp_cnt = 0; 953fcf3ce44SJohn Forte rval = isns_ok; 954fcf3ce44SJohn Forte for (;;) { 955fcf3ce44SJohn Forte bytes_received = isns_rcv_pdu(so, &in_pdu, &in_pdu_size); 956fcf3ce44SJohn Forte ASSERT(bytes_received >= (size_t)0); 957fcf3ce44SJohn Forte if (bytes_received == 0) { 958fcf3ce44SJohn Forte ASSERT(in_pdu == NULL); 959fcf3ce44SJohn Forte ASSERT(in_pdu_size == 0); 960fcf3ce44SJohn Forte rval = isns_rcv_msg_err; 961fcf3ce44SJohn Forte break; 962fcf3ce44SJohn Forte } 963fcf3ce44SJohn Forte 964fcf3ce44SJohn Forte ASSERT(in_pdu != NULL); 965fcf3ce44SJohn Forte ASSERT(in_pdu_size > 0); 966fcf3ce44SJohn Forte 967fcf3ce44SJohn Forte if (ntohs(in_pdu->xid) != xid) { 968fcf3ce44SJohn Forte rcv_rsp_cnt++; 969fcf3ce44SJohn Forte if (rcv_rsp_cnt < MAX_RCV_RSP_COUNT) { 970fcf3ce44SJohn Forte continue; 971fcf3ce44SJohn Forte } else { 972fcf3ce44SJohn Forte /* Exceed maximum receive count. */ 973fcf3ce44SJohn Forte kmem_free(in_pdu, in_pdu_size); 974fcf3ce44SJohn Forte in_pdu = NULL; 975fcf3ce44SJohn Forte rval = isns_no_rsp_rcvd; 976fcf3ce44SJohn Forte break; 977fcf3ce44SJohn Forte } 978fcf3ce44SJohn Forte } 979fcf3ce44SJohn Forte 980fcf3ce44SJohn Forte rsp_status = isns_process_dev_attr_dereg_rsp(in_pdu); 981fcf3ce44SJohn Forte if (rsp_status != ISNS_RSP_SUCCESSFUL) { 982fcf3ce44SJohn Forte rval = isns_op_failed; 983fcf3ce44SJohn Forte } 984fcf3ce44SJohn Forte kmem_free(in_pdu, in_pdu_size); 985fcf3ce44SJohn Forte in_pdu = NULL; 986fcf3ce44SJohn Forte break; 987fcf3ce44SJohn Forte } 988fcf3ce44SJohn Forte 989fcf3ce44SJohn Forte if (rval != isns_ok) { 990fcf3ce44SJohn Forte iscsi_net->close(so); 991fcf3ce44SJohn Forte return (rval); 992fcf3ce44SJohn Forte } 993fcf3ce44SJohn Forte 994fcf3ce44SJohn Forte /* Always deregister SCN */ 995fcf3ce44SJohn Forte out_pdu_size = isns_create_scn_dereg_pdu( 996fcf3ce44SJohn Forte node_name, 997fcf3ce44SJohn Forte &xid, &out_pdu); 998fcf3ce44SJohn Forte if (out_pdu_size == 0) { 999fcf3ce44SJohn Forte iscsi_net->close(so); 1000fcf3ce44SJohn Forte return (isns_create_msg_err); 1001fcf3ce44SJohn Forte } 1002fcf3ce44SJohn Forte 1003fcf3ce44SJohn Forte ASSERT(out_pdu != NULL); 1004fcf3ce44SJohn Forte ASSERT(out_pdu_size > 0); 1005fcf3ce44SJohn Forte 1006fcf3ce44SJohn Forte if (isns_send_pdu(so, out_pdu) != 0) { 1007fcf3ce44SJohn Forte iscsi_net->close(so); 1008fcf3ce44SJohn Forte kmem_free(out_pdu, out_pdu_size); 1009fcf3ce44SJohn Forte out_pdu = NULL; 1010fcf3ce44SJohn Forte return (isns_send_msg_err); 1011fcf3ce44SJohn Forte } 1012fcf3ce44SJohn Forte 1013fcf3ce44SJohn Forte /* Done with the out PDU - free it */ 1014fcf3ce44SJohn Forte kmem_free(out_pdu, out_pdu_size); 1015fcf3ce44SJohn Forte out_pdu = NULL; 1016fcf3ce44SJohn Forte 1017fcf3ce44SJohn Forte rcv_rsp_cnt = 0; 1018fcf3ce44SJohn Forte for (;;) { 1019fcf3ce44SJohn Forte bytes_received = isns_rcv_pdu(so, &in_pdu, &in_pdu_size); 1020fcf3ce44SJohn Forte ASSERT(bytes_received >= (size_t)0); 1021fcf3ce44SJohn Forte if (bytes_received == 0) { 1022fcf3ce44SJohn Forte ASSERT(in_pdu == NULL); 1023fcf3ce44SJohn Forte ASSERT(in_pdu_size == 0); 1024fcf3ce44SJohn Forte rval = isns_rcv_msg_err; 1025fcf3ce44SJohn Forte break; 1026fcf3ce44SJohn Forte } 1027fcf3ce44SJohn Forte 1028fcf3ce44SJohn Forte ASSERT(in_pdu != NULL); 1029fcf3ce44SJohn Forte ASSERT(in_pdu_size > 0); 1030fcf3ce44SJohn Forte 1031fcf3ce44SJohn Forte if (ntohs(in_pdu->xid) != xid) { 1032fcf3ce44SJohn Forte rcv_rsp_cnt++; 1033fcf3ce44SJohn Forte if (rcv_rsp_cnt < MAX_RCV_RSP_COUNT) { 1034fcf3ce44SJohn Forte continue; 1035fcf3ce44SJohn Forte } else { 1036fcf3ce44SJohn Forte /* Exceed maximum receive count. */ 1037fcf3ce44SJohn Forte kmem_free(in_pdu, in_pdu_size); 1038fcf3ce44SJohn Forte in_pdu = NULL; 1039fcf3ce44SJohn Forte rval = isns_no_rsp_rcvd; 1040fcf3ce44SJohn Forte break; 1041fcf3ce44SJohn Forte } 1042fcf3ce44SJohn Forte } 1043fcf3ce44SJohn Forte 1044fcf3ce44SJohn Forte rsp_status = isns_process_scn_dereg_rsp(in_pdu); 1045fcf3ce44SJohn Forte if (rsp_status != ISNS_RSP_SUCCESSFUL) { 1046fcf3ce44SJohn Forte rval = isns_op_failed; 1047fcf3ce44SJohn Forte } 1048fcf3ce44SJohn Forte kmem_free(in_pdu, in_pdu_size); 1049fcf3ce44SJohn Forte in_pdu = NULL; 1050fcf3ce44SJohn Forte break; 1051fcf3ce44SJohn Forte } 1052fcf3ce44SJohn Forte 1053fcf3ce44SJohn Forte iscsi_net->close(so); 1054fcf3ce44SJohn Forte 1055fcf3ce44SJohn Forte return (rval); 1056fcf3ce44SJohn Forte } 1057fcf3ce44SJohn Forte 1058fcf3ce44SJohn Forte static 1059fcf3ce44SJohn Forte isns_status_t 1060fcf3ce44SJohn Forte do_isns_query(boolean_t is_query_all_nodes_b, 1061fcf3ce44SJohn Forte uint8_t *lhba_handle, 1062fcf3ce44SJohn Forte uint8_t *target_node_name, 1063fcf3ce44SJohn Forte uint8_t *source_node_name, 1064fcf3ce44SJohn Forte uint8_t *source_node_alias, 1065fcf3ce44SJohn Forte uint32_t source_node_type, 1066fcf3ce44SJohn Forte isns_portal_group_list_t **pg_list) 1067fcf3ce44SJohn Forte { 1068fcf3ce44SJohn Forte int i, j, k; 1069fcf3ce44SJohn Forte int combined_num_of_pgs, combined_pg_lst_sz, 1070fcf3ce44SJohn Forte isns_svr_lst_sz, 1071fcf3ce44SJohn Forte tmp_pg_list_sz, 1072fcf3ce44SJohn Forte tmp_pg_lists_sz; 1073fcf3ce44SJohn Forte iscsi_addr_list_t *isns_server_addr_list = NULL; 1074fcf3ce44SJohn Forte isns_portal_group_t *pg; 1075fcf3ce44SJohn Forte isns_portal_group_list_t *combined_pg_list, 1076fcf3ce44SJohn Forte *tmp_pg_list, **tmp_pg_lists; 1077fcf3ce44SJohn Forte isns_status_t qry_stat, combined_qry_stat; 1078fcf3ce44SJohn Forte 1079fcf3ce44SJohn Forte /* Look up the iSNS Server address(es) based on the specified ISID */ 1080fcf3ce44SJohn Forte if (discover_isns_server(lhba_handle, &isns_server_addr_list) != 1081fcf3ce44SJohn Forte ISNS_OK) { 1082fcf3ce44SJohn Forte *pg_list = NULL; 1083fcf3ce44SJohn Forte return (isns_no_svr_found); 1084fcf3ce44SJohn Forte } 1085fcf3ce44SJohn Forte if (isns_server_addr_list->al_out_cnt == 0) { 1086fcf3ce44SJohn Forte isns_svr_lst_sz = sizeof (iscsi_addr_list_t); 1087fcf3ce44SJohn Forte kmem_free(isns_server_addr_list, isns_svr_lst_sz); 1088fcf3ce44SJohn Forte isns_server_addr_list = NULL; 1089fcf3ce44SJohn Forte *pg_list = NULL; 1090fcf3ce44SJohn Forte return (isns_no_svr_found); 1091fcf3ce44SJohn Forte } 1092fcf3ce44SJohn Forte 1093fcf3ce44SJohn Forte /* 1094fcf3ce44SJohn Forte * isns_server_addr_list->al_out_cnt should not be zero by the 1095fcf3ce44SJohn Forte * time it comes to this point. 1096fcf3ce44SJohn Forte */ 1097fcf3ce44SJohn Forte tmp_pg_lists_sz = isns_server_addr_list->al_out_cnt * 1098fcf3ce44SJohn Forte sizeof (isns_portal_group_list_t *); 1099fcf3ce44SJohn Forte tmp_pg_lists = (isns_portal_group_list_t **)kmem_zalloc( 1100fcf3ce44SJohn Forte tmp_pg_lists_sz, KM_SLEEP); 1101fcf3ce44SJohn Forte combined_num_of_pgs = 0; 1102fcf3ce44SJohn Forte combined_qry_stat = isns_ok; 1103fcf3ce44SJohn Forte for (i = 0; i < isns_server_addr_list->al_out_cnt; i++) { 1104fcf3ce44SJohn Forte if (is_query_all_nodes_b) { 1105fcf3ce44SJohn Forte qry_stat = do_isns_dev_attr_query_all_nodes( 1106fcf3ce44SJohn Forte &isns_server_addr_list->al_addrs[i], 1107fcf3ce44SJohn Forte source_node_name, 1108fcf3ce44SJohn Forte source_node_alias, 1109fcf3ce44SJohn Forte &tmp_pg_list); 1110fcf3ce44SJohn Forte } else { 1111fcf3ce44SJohn Forte qry_stat = do_isns_dev_attr_query_one_node( 1112fcf3ce44SJohn Forte &isns_server_addr_list->al_addrs[i], 1113fcf3ce44SJohn Forte target_node_name, 1114fcf3ce44SJohn Forte source_node_name, 1115fcf3ce44SJohn Forte source_node_alias, 1116fcf3ce44SJohn Forte source_node_type, 1117fcf3ce44SJohn Forte &tmp_pg_list); 1118fcf3ce44SJohn Forte } 1119fcf3ce44SJohn Forte 1120fcf3ce44SJohn Forte /* Record the portal group list retrieved from this server. */ 1121fcf3ce44SJohn Forte tmp_pg_lists[i] = tmp_pg_list; 1122fcf3ce44SJohn Forte if (tmp_pg_list != NULL) { 1123fcf3ce44SJohn Forte combined_num_of_pgs += tmp_pg_list->pg_out_cnt; 1124fcf3ce44SJohn Forte } 1125fcf3ce44SJohn Forte 1126fcf3ce44SJohn Forte if (qry_stat == isns_ok) { 1127fcf3ce44SJohn Forte if (combined_qry_stat != isns_ok) { 1128fcf3ce44SJohn Forte combined_qry_stat = isns_op_partially_failed; 1129fcf3ce44SJohn Forte } 1130fcf3ce44SJohn Forte } else { 1131fcf3ce44SJohn Forte if (combined_qry_stat != isns_op_partially_failed) { 1132fcf3ce44SJohn Forte if (combined_qry_stat == isns_ok && i > 0) { 1133fcf3ce44SJohn Forte combined_qry_stat = 1134fcf3ce44SJohn Forte isns_op_partially_failed; 1135fcf3ce44SJohn Forte } else { 1136fcf3ce44SJohn Forte combined_qry_stat = qry_stat; 1137fcf3ce44SJohn Forte } 1138fcf3ce44SJohn Forte } 1139fcf3ce44SJohn Forte } 1140fcf3ce44SJohn Forte 1141fcf3ce44SJohn Forte if (is_query_all_nodes_b == B_FALSE) { 1142fcf3ce44SJohn Forte if (qry_stat == isns_ok) { 1143fcf3ce44SJohn Forte /* 1144fcf3ce44SJohn Forte * Break out of the loop if we already got 1145fcf3ce44SJohn Forte * the node information for one node. 1146fcf3ce44SJohn Forte */ 1147fcf3ce44SJohn Forte break; 1148fcf3ce44SJohn Forte } 1149fcf3ce44SJohn Forte } 1150fcf3ce44SJohn Forte } 1151fcf3ce44SJohn Forte 1152fcf3ce44SJohn Forte /* Merge the retrieved portal lists */ 1153fcf3ce44SJohn Forte combined_pg_lst_sz = sizeof (isns_portal_group_list_t); 1154fcf3ce44SJohn Forte if (combined_num_of_pgs > 0) { 1155fcf3ce44SJohn Forte combined_pg_lst_sz += (combined_num_of_pgs - 1) * 1156fcf3ce44SJohn Forte sizeof (isns_portal_group_t); 1157fcf3ce44SJohn Forte } 1158fcf3ce44SJohn Forte combined_pg_list = (isns_portal_group_list_t *)kmem_zalloc( 1159fcf3ce44SJohn Forte combined_pg_lst_sz, KM_SLEEP); 1160fcf3ce44SJohn Forte 1161fcf3ce44SJohn Forte combined_pg_list->pg_out_cnt = combined_num_of_pgs; 1162fcf3ce44SJohn Forte k = 0; 1163fcf3ce44SJohn Forte for (i = 0; i < isns_server_addr_list->al_out_cnt; i++) { 1164fcf3ce44SJohn Forte if (tmp_pg_lists[i] == NULL) { 1165fcf3ce44SJohn Forte continue; 1166fcf3ce44SJohn Forte } 1167fcf3ce44SJohn Forte for (j = 0; j < tmp_pg_lists[i]->pg_out_cnt; j++) { 1168fcf3ce44SJohn Forte pg = &(combined_pg_list->pg_list[k]); 1169fcf3ce44SJohn Forte bcopy(&(tmp_pg_lists[i]->pg_list[j]), 1170fcf3ce44SJohn Forte pg, sizeof (isns_portal_group_t)); 1171fcf3ce44SJohn Forte k++; 1172fcf3ce44SJohn Forte } 1173fcf3ce44SJohn Forte tmp_pg_list_sz = sizeof (isns_portal_group_list_t); 1174fcf3ce44SJohn Forte if (tmp_pg_lists[i]->pg_out_cnt > 0) { 1175fcf3ce44SJohn Forte tmp_pg_list_sz += (tmp_pg_lists[i]->pg_out_cnt - 1) * 1176fcf3ce44SJohn Forte sizeof (isns_portal_group_t); 1177fcf3ce44SJohn Forte } 1178fcf3ce44SJohn Forte kmem_free(tmp_pg_lists[i], tmp_pg_list_sz); 1179fcf3ce44SJohn Forte tmp_pg_lists[i] = NULL; 1180fcf3ce44SJohn Forte } 1181fcf3ce44SJohn Forte kmem_free(tmp_pg_lists, tmp_pg_lists_sz); 1182fcf3ce44SJohn Forte tmp_pg_lists = NULL; 1183fcf3ce44SJohn Forte 1184fcf3ce44SJohn Forte isns_svr_lst_sz = sizeof (iscsi_addr_list_t); 1185fcf3ce44SJohn Forte if (isns_server_addr_list->al_out_cnt > 0) { 1186fcf3ce44SJohn Forte isns_svr_lst_sz += (sizeof (iscsi_addr_t) * 1187fcf3ce44SJohn Forte (isns_server_addr_list->al_out_cnt - 1)); 1188fcf3ce44SJohn Forte } 1189fcf3ce44SJohn Forte kmem_free(isns_server_addr_list, isns_svr_lst_sz); 1190fcf3ce44SJohn Forte isns_server_addr_list = NULL; 1191fcf3ce44SJohn Forte 1192fcf3ce44SJohn Forte DTRACE_PROBE1(list, isns_portal_group_list_t *, combined_pg_list); 1193fcf3ce44SJohn Forte 1194fcf3ce44SJohn Forte *pg_list = combined_pg_list; 1195fcf3ce44SJohn Forte return (combined_qry_stat); 1196fcf3ce44SJohn Forte } 1197fcf3ce44SJohn Forte 1198fcf3ce44SJohn Forte static 1199fcf3ce44SJohn Forte isns_status_t 1200fcf3ce44SJohn Forte do_isns_dev_attr_query_all_nodes(iscsi_addr_t *isns_server_addr, 1201fcf3ce44SJohn Forte uint8_t *node_name, 1202fcf3ce44SJohn Forte uint8_t *node_alias, 1203fcf3ce44SJohn Forte isns_portal_group_list_t **pg_list) 1204fcf3ce44SJohn Forte { 1205fcf3ce44SJohn Forte int bytes_received; 1206fcf3ce44SJohn Forte int rcv_rsp_cnt = 0; 1207fcf3ce44SJohn Forte int rsp_status; 1208fcf3ce44SJohn Forte uint16_t xid, seq_id = 0, func_id; 1209fcf3ce44SJohn Forte isns_pdu_t *in_pdu, *out_pdu; 1210fcf3ce44SJohn Forte isns_pdu_mult_payload_t *combined_pdu = NULL, *old_combined_pdu = NULL; 1211fcf3ce44SJohn Forte isns_status_t qry_stat; 1212fcf3ce44SJohn Forte size_t out_pdu_size = 0, in_pdu_size = 0; 1213fcf3ce44SJohn Forte size_t old_combined_pdu_size = 0, combined_pdu_size = 0; 1214fcf3ce44SJohn Forte void *so = NULL; 1215fcf3ce44SJohn Forte uint8_t *payload_ptr; 1216fcf3ce44SJohn Forte 1217fcf3ce44SJohn Forte /* Initialize */ 1218fcf3ce44SJohn Forte *pg_list = NULL; 1219fcf3ce44SJohn Forte 1220fcf3ce44SJohn Forte so = isns_open(isns_server_addr); 1221fcf3ce44SJohn Forte if (so == NULL) { 1222fcf3ce44SJohn Forte /* Log a message and return */ 1223fcf3ce44SJohn Forte return (isns_open_conn_err); 1224fcf3ce44SJohn Forte } 1225fcf3ce44SJohn Forte 1226fcf3ce44SJohn Forte /* 1227fcf3ce44SJohn Forte * Then, ask for all PG attributes. Filter the non-target nodes. 1228fcf3ce44SJohn Forte */ 1229fcf3ce44SJohn Forte out_pdu_size = isns_create_dev_attr_qry_target_nodes_pdu( 1230fcf3ce44SJohn Forte node_name, node_alias, &xid, &out_pdu); 1231fcf3ce44SJohn Forte if (out_pdu_size == 0) { 1232fcf3ce44SJohn Forte iscsi_net->close(so); 1233fcf3ce44SJohn Forte return (isns_create_msg_err); 1234fcf3ce44SJohn Forte } 1235fcf3ce44SJohn Forte 1236fcf3ce44SJohn Forte ASSERT(out_pdu != NULL); 1237fcf3ce44SJohn Forte ASSERT(out_pdu_size > 0); 1238fcf3ce44SJohn Forte 1239fcf3ce44SJohn Forte if (isns_send_pdu(so, out_pdu) != 0) { 1240fcf3ce44SJohn Forte iscsi_net->close(so); 1241fcf3ce44SJohn Forte kmem_free(out_pdu, out_pdu_size); 1242fcf3ce44SJohn Forte out_pdu = NULL; 1243fcf3ce44SJohn Forte return (isns_send_msg_err); 1244fcf3ce44SJohn Forte } 1245fcf3ce44SJohn Forte 1246fcf3ce44SJohn Forte /* Done with the out PDU - free it */ 1247fcf3ce44SJohn Forte kmem_free(out_pdu, out_pdu_size); 1248fcf3ce44SJohn Forte out_pdu = NULL; 1249fcf3ce44SJohn Forte 1250fcf3ce44SJohn Forte rcv_rsp_cnt = 0; 1251fcf3ce44SJohn Forte qry_stat = isns_ok; 1252fcf3ce44SJohn Forte for (;;) { 1253fcf3ce44SJohn Forte uint16_t flags; 1254fcf3ce44SJohn Forte 1255fcf3ce44SJohn Forte bytes_received = isns_rcv_pdu(so, &in_pdu, &in_pdu_size); 1256fcf3ce44SJohn Forte ASSERT(bytes_received >= 0); 1257fcf3ce44SJohn Forte if (bytes_received == 0) { 1258fcf3ce44SJohn Forte ASSERT(in_pdu == NULL); 1259fcf3ce44SJohn Forte ASSERT(in_pdu_size == 0); 1260fcf3ce44SJohn Forte qry_stat = isns_rcv_msg_err; 1261fcf3ce44SJohn Forte break; 1262fcf3ce44SJohn Forte } 1263fcf3ce44SJohn Forte 1264fcf3ce44SJohn Forte ASSERT(in_pdu != NULL); 1265fcf3ce44SJohn Forte ASSERT(in_pdu_size > 0); 1266fcf3ce44SJohn Forte 1267fcf3ce44SJohn Forte /* 1268fcf3ce44SJohn Forte * make sure we are processing the right transaction id 1269fcf3ce44SJohn Forte */ 1270fcf3ce44SJohn Forte if (ntohs(in_pdu->xid) != xid) { 1271fcf3ce44SJohn Forte rcv_rsp_cnt++; 1272fcf3ce44SJohn Forte if (rcv_rsp_cnt < MAX_RCV_RSP_COUNT) { 1273fcf3ce44SJohn Forte kmem_free(in_pdu, in_pdu_size); 1274fcf3ce44SJohn Forte in_pdu = NULL; 1275fcf3ce44SJohn Forte continue; 1276fcf3ce44SJohn Forte } else { 1277fcf3ce44SJohn Forte /* Exceed maximum receive count. */ 1278fcf3ce44SJohn Forte kmem_free(in_pdu, in_pdu_size); 1279fcf3ce44SJohn Forte in_pdu = NULL; 1280fcf3ce44SJohn Forte qry_stat = isns_no_rsp_rcvd; 1281fcf3ce44SJohn Forte break; 1282fcf3ce44SJohn Forte } 1283fcf3ce44SJohn Forte } 1284fcf3ce44SJohn Forte 1285fcf3ce44SJohn Forte /* 1286fcf3ce44SJohn Forte * check to see if FIRST and LAST PDU flag is set 1287fcf3ce44SJohn Forte * if they are both set, then this response only has one 1288fcf3ce44SJohn Forte * pdu and we can process the pdu 1289fcf3ce44SJohn Forte */ 1290fcf3ce44SJohn Forte flags = in_pdu->flags; 1291fcf3ce44SJohn Forte if (((flags & ISNS_FLAG_FIRST_PDU) == ISNS_FLAG_FIRST_PDU) && 1292fcf3ce44SJohn Forte ((flags & ISNS_FLAG_LAST_PDU) == ISNS_FLAG_LAST_PDU)) { 1293fcf3ce44SJohn Forte rsp_status = 1294fcf3ce44SJohn Forte isns_process_dev_attr_qry_target_nodes_pdu( 1295fcf3ce44SJohn Forte isns_server_addr, 1296fcf3ce44SJohn Forte in_pdu->func_id, 1297fcf3ce44SJohn Forte (isns_resp_t *)in_pdu->payload, 1298fcf3ce44SJohn Forte (size_t)in_pdu->payload_len, 1299fcf3ce44SJohn Forte pg_list); 1300fcf3ce44SJohn Forte kmem_free(in_pdu, in_pdu_size); 1301fcf3ce44SJohn Forte in_pdu = NULL; 1302fcf3ce44SJohn Forte break; 1303fcf3ce44SJohn Forte } 1304fcf3ce44SJohn Forte /* 1305fcf3ce44SJohn Forte * this pdu is part of a multi-pdu response. save off the 1306fcf3ce44SJohn Forte * the payload of this pdu and continue processing 1307fcf3ce44SJohn Forte */ 1308fcf3ce44SJohn Forte if ((flags & ISNS_FLAG_FIRST_PDU) == ISNS_FLAG_FIRST_PDU) { 1309fcf3ce44SJohn Forte /* This is the first pdu, make sure sequence ID is 0 */ 1310fcf3ce44SJohn Forte if (in_pdu->seq != 0) { 1311fcf3ce44SJohn Forte cmn_err(CE_NOTE, "isns query response invalid: " 1312fcf3ce44SJohn Forte "first pdu is not sequence ID 0"); 1313fcf3ce44SJohn Forte kmem_free(in_pdu, in_pdu_size); 1314fcf3ce44SJohn Forte in_pdu = NULL; 1315fcf3ce44SJohn Forte return (isns_op_failed); 1316fcf3ce44SJohn Forte } 1317fcf3ce44SJohn Forte seq_id = 0; 1318fcf3ce44SJohn Forte 1319fcf3ce44SJohn Forte /* create new pdu and copy in data from old pdu */ 1320fcf3ce44SJohn Forte combined_pdu_size = ISNSP_MULT_PAYLOAD_HEADER_SIZE + 1321fcf3ce44SJohn Forte in_pdu->payload_len; 1322fcf3ce44SJohn Forte combined_pdu = (isns_pdu_mult_payload_t *)kmem_zalloc( 1323fcf3ce44SJohn Forte combined_pdu_size, KM_SLEEP); 1324fcf3ce44SJohn Forte func_id = in_pdu->func_id; 1325fcf3ce44SJohn Forte combined_pdu->payload_len = in_pdu->payload_len; 1326fcf3ce44SJohn Forte bcopy(in_pdu->payload, combined_pdu->payload, 1327fcf3ce44SJohn Forte in_pdu->payload_len); 1328fcf3ce44SJohn Forte 1329fcf3ce44SJohn Forte /* done with in_pdu, free it */ 1330fcf3ce44SJohn Forte kmem_free(in_pdu, in_pdu_size); 1331fcf3ce44SJohn Forte in_pdu = NULL; 1332fcf3ce44SJohn Forte } else { 1333fcf3ce44SJohn Forte seq_id++; 1334fcf3ce44SJohn Forte if (in_pdu->seq != seq_id) { 1335fcf3ce44SJohn Forte cmn_err(CE_NOTE, "isns query response invalid: " 1336fcf3ce44SJohn Forte "Missing sequence ID %d from isns query " 1337fcf3ce44SJohn Forte "response.", seq_id); 1338fcf3ce44SJohn Forte kmem_free(in_pdu, in_pdu_size); 1339fcf3ce44SJohn Forte in_pdu = NULL; 1340fcf3ce44SJohn Forte if (combined_pdu != NULL) { 1341fcf3ce44SJohn Forte kmem_free(combined_pdu, 1342fcf3ce44SJohn Forte combined_pdu_size); 1343fcf3ce44SJohn Forte combined_pdu = NULL; 1344fcf3ce44SJohn Forte } 1345fcf3ce44SJohn Forte return (isns_op_failed); 1346fcf3ce44SJohn Forte } 1347fcf3ce44SJohn Forte /* 1348fcf3ce44SJohn Forte * if conbined_pdu_size is still zero, then we never 1349fcf3ce44SJohn Forte * processed the first pdu 1350fcf3ce44SJohn Forte */ 1351fcf3ce44SJohn Forte if (combined_pdu_size == 0) { 1352fcf3ce44SJohn Forte cmn_err(CE_NOTE, "isns query response invalid: " 1353fcf3ce44SJohn Forte "Did not receive first pdu.\n"); 1354fcf3ce44SJohn Forte kmem_free(in_pdu, in_pdu_size); 1355fcf3ce44SJohn Forte in_pdu = NULL; 1356fcf3ce44SJohn Forte return (isns_op_failed); 1357fcf3ce44SJohn Forte } 1358fcf3ce44SJohn Forte /* save off the old combined pdu */ 1359fcf3ce44SJohn Forte old_combined_pdu_size = combined_pdu_size; 1360fcf3ce44SJohn Forte old_combined_pdu = combined_pdu; 1361fcf3ce44SJohn Forte 1362fcf3ce44SJohn Forte /* 1363fcf3ce44SJohn Forte * alloc a new pdu big enough to also hold the new 1364fcf3ce44SJohn Forte * pdu payload 1365fcf3ce44SJohn Forte */ 1366fcf3ce44SJohn Forte combined_pdu_size += in_pdu->payload_len; 1367fcf3ce44SJohn Forte combined_pdu = (isns_pdu_mult_payload_t *)kmem_zalloc( 1368fcf3ce44SJohn Forte combined_pdu_size, KM_SLEEP); 1369fcf3ce44SJohn Forte 1370fcf3ce44SJohn Forte /* 1371fcf3ce44SJohn Forte * copy the old pdu into the new allocated pdu buffer 1372fcf3ce44SJohn Forte * and append on the new pdu payload that we just 1373fcf3ce44SJohn Forte * received 1374fcf3ce44SJohn Forte */ 1375fcf3ce44SJohn Forte bcopy(old_combined_pdu, combined_pdu, 1376fcf3ce44SJohn Forte old_combined_pdu_size); 1377fcf3ce44SJohn Forte 1378fcf3ce44SJohn Forte payload_ptr = combined_pdu->payload + 1379fcf3ce44SJohn Forte combined_pdu->payload_len; 1380fcf3ce44SJohn Forte combined_pdu->payload_len += in_pdu->payload_len; 1381fcf3ce44SJohn Forte bcopy(in_pdu->payload, payload_ptr, 1382fcf3ce44SJohn Forte in_pdu->payload_len); 1383fcf3ce44SJohn Forte 1384fcf3ce44SJohn Forte /* free in_pdu and old_combined_pdu */ 1385fcf3ce44SJohn Forte kmem_free(in_pdu, in_pdu_size); 1386fcf3ce44SJohn Forte kmem_free(old_combined_pdu, old_combined_pdu_size); 1387fcf3ce44SJohn Forte in_pdu = NULL; 1388fcf3ce44SJohn Forte old_combined_pdu = NULL; 1389fcf3ce44SJohn Forte } 1390fcf3ce44SJohn Forte /* 1391fcf3ce44SJohn Forte * check to see if this is the LAST pdu. 1392fcf3ce44SJohn Forte * if it is, we can process it and move on 1393fcf3ce44SJohn Forte * otherwise continue to wait for the next pdu 1394fcf3ce44SJohn Forte */ 1395fcf3ce44SJohn Forte if ((flags & ISNS_FLAG_LAST_PDU) == ISNS_FLAG_LAST_PDU) { 1396fcf3ce44SJohn Forte rsp_status = 1397fcf3ce44SJohn Forte isns_process_dev_attr_qry_target_nodes_pdu( 1398fcf3ce44SJohn Forte isns_server_addr, 1399fcf3ce44SJohn Forte func_id, 1400fcf3ce44SJohn Forte (isns_resp_t *)combined_pdu->payload, 1401fcf3ce44SJohn Forte combined_pdu->payload_len, 1402fcf3ce44SJohn Forte pg_list); 1403fcf3ce44SJohn Forte kmem_free(combined_pdu, combined_pdu_size); 1404fcf3ce44SJohn Forte combined_pdu = NULL; 1405fcf3ce44SJohn Forte break; 1406fcf3ce44SJohn Forte } 1407fcf3ce44SJohn Forte } 1408fcf3ce44SJohn Forte if (rsp_status != ISNS_RSP_SUCCESSFUL) { 1409fcf3ce44SJohn Forte qry_stat = isns_op_failed; 1410fcf3ce44SJohn Forte } 1411fcf3ce44SJohn Forte 1412fcf3ce44SJohn Forte iscsi_net->close(so); 1413fcf3ce44SJohn Forte 1414fcf3ce44SJohn Forte return (qry_stat); 1415fcf3ce44SJohn Forte } 1416fcf3ce44SJohn Forte 1417fcf3ce44SJohn Forte /* ARGSUSED */ 1418fcf3ce44SJohn Forte static 1419fcf3ce44SJohn Forte isns_status_t 1420fcf3ce44SJohn Forte do_isns_dev_attr_query_one_node(iscsi_addr_t *isns_server_addr, 1421fcf3ce44SJohn Forte uint8_t *target_node_name, 1422fcf3ce44SJohn Forte uint8_t *source_node_name, 1423fcf3ce44SJohn Forte uint8_t *source_node_alias, 1424fcf3ce44SJohn Forte uint32_t source_node_type, 1425fcf3ce44SJohn Forte isns_portal_group_list_t **pg_list) 1426fcf3ce44SJohn Forte { 1427fcf3ce44SJohn Forte int bytes_received; 1428fcf3ce44SJohn Forte int rcv_rsp_cnt; 1429fcf3ce44SJohn Forte int rsp_status; 1430fcf3ce44SJohn Forte isns_pdu_t *in_pdu, *out_pdu; 1431fcf3ce44SJohn Forte isns_status_t rval; 1432fcf3ce44SJohn Forte size_t out_pdu_size = 0, in_pdu_size = 0; 1433fcf3ce44SJohn Forte uint16_t xid; 1434fcf3ce44SJohn Forte void *so = NULL; 1435fcf3ce44SJohn Forte 1436fcf3ce44SJohn Forte /* Obtain the list of target type storage nodes first */ 1437fcf3ce44SJohn Forte out_pdu_size = isns_create_dev_attr_qry_one_pg_pdu( 1438fcf3ce44SJohn Forte target_node_name, source_node_name, &xid, &out_pdu); 1439fcf3ce44SJohn Forte if (out_pdu_size == 0) { 1440fcf3ce44SJohn Forte return (isns_create_msg_err); 1441fcf3ce44SJohn Forte } 1442fcf3ce44SJohn Forte 1443fcf3ce44SJohn Forte ASSERT(out_pdu != NULL); 1444fcf3ce44SJohn Forte ASSERT(out_pdu_size > 0); 1445fcf3ce44SJohn Forte 1446fcf3ce44SJohn Forte so = isns_open(isns_server_addr); 1447fcf3ce44SJohn Forte if (so == NULL) { 1448fcf3ce44SJohn Forte /* Log a message and return */ 1449fcf3ce44SJohn Forte kmem_free(out_pdu, out_pdu_size); 1450fcf3ce44SJohn Forte out_pdu = NULL; 1451fcf3ce44SJohn Forte return (isns_open_conn_err); 1452fcf3ce44SJohn Forte } 1453fcf3ce44SJohn Forte 1454fcf3ce44SJohn Forte if (isns_send_pdu(so, out_pdu) != 0) { 1455fcf3ce44SJohn Forte iscsi_net->close(so); 1456fcf3ce44SJohn Forte kmem_free(out_pdu, out_pdu_size); 1457fcf3ce44SJohn Forte out_pdu = NULL; 1458fcf3ce44SJohn Forte return (isns_send_msg_err); 1459fcf3ce44SJohn Forte } 1460fcf3ce44SJohn Forte 1461fcf3ce44SJohn Forte /* Done with the out PDU - free it */ 1462fcf3ce44SJohn Forte kmem_free(out_pdu, out_pdu_size); 1463fcf3ce44SJohn Forte out_pdu = NULL; 1464fcf3ce44SJohn Forte 1465fcf3ce44SJohn Forte rcv_rsp_cnt = 0; 1466fcf3ce44SJohn Forte rval = isns_ok; 1467fcf3ce44SJohn Forte for (;;) { 1468fcf3ce44SJohn Forte bytes_received = isns_rcv_pdu(so, &in_pdu, &in_pdu_size); 1469fcf3ce44SJohn Forte ASSERT(bytes_received >= 0); 1470fcf3ce44SJohn Forte if (bytes_received == 0) { 1471fcf3ce44SJohn Forte ASSERT(in_pdu == NULL); 1472fcf3ce44SJohn Forte ASSERT(in_pdu_size == 0); 1473fcf3ce44SJohn Forte rval = isns_rcv_msg_err; 1474fcf3ce44SJohn Forte break; 1475fcf3ce44SJohn Forte } 1476fcf3ce44SJohn Forte 1477fcf3ce44SJohn Forte ASSERT(in_pdu != NULL); 1478fcf3ce44SJohn Forte ASSERT(in_pdu_size > 0); 1479fcf3ce44SJohn Forte 1480fcf3ce44SJohn Forte if (ntohs(in_pdu->xid) != xid) { 1481fcf3ce44SJohn Forte rcv_rsp_cnt++; 1482fcf3ce44SJohn Forte if (rcv_rsp_cnt < MAX_RCV_RSP_COUNT) { 1483fcf3ce44SJohn Forte continue; 1484fcf3ce44SJohn Forte } else { 1485fcf3ce44SJohn Forte /* Exceed maximum receive count. */ 1486fcf3ce44SJohn Forte kmem_free(in_pdu, in_pdu_size); 1487fcf3ce44SJohn Forte in_pdu = NULL; 1488fcf3ce44SJohn Forte rval = isns_no_rsp_rcvd; 1489fcf3ce44SJohn Forte break; 1490fcf3ce44SJohn Forte } 1491fcf3ce44SJohn Forte } 1492fcf3ce44SJohn Forte 1493fcf3ce44SJohn Forte rsp_status = isns_process_dev_attr_qry_target_nodes_pdu( 1494fcf3ce44SJohn Forte isns_server_addr, in_pdu->func_id, 1495fcf3ce44SJohn Forte (isns_resp_t *)in_pdu->payload, (size_t)in_pdu->payload_len, 1496fcf3ce44SJohn Forte pg_list); 1497fcf3ce44SJohn Forte if (rsp_status != ISNS_RSP_SUCCESSFUL) { 1498fcf3ce44SJohn Forte rval = isns_op_failed; 1499fcf3ce44SJohn Forte } 1500fcf3ce44SJohn Forte kmem_free(in_pdu, in_pdu_size); 1501fcf3ce44SJohn Forte in_pdu = NULL; 1502fcf3ce44SJohn Forte break; 1503fcf3ce44SJohn Forte } 1504fcf3ce44SJohn Forte 1505fcf3ce44SJohn Forte iscsi_net->close(so); 1506fcf3ce44SJohn Forte 1507fcf3ce44SJohn Forte return (rval); 1508fcf3ce44SJohn Forte } 1509fcf3ce44SJohn Forte 1510fcf3ce44SJohn Forte static 1511fcf3ce44SJohn Forte void 1512fcf3ce44SJohn Forte *isns_open(iscsi_addr_t *isns_server_addr) 1513fcf3ce44SJohn Forte { 1514fcf3ce44SJohn Forte int rval = 0; 1515fcf3ce44SJohn Forte union { 1516fcf3ce44SJohn Forte struct sockaddr sin; 1517fcf3ce44SJohn Forte struct sockaddr_in s_in4; 1518fcf3ce44SJohn Forte struct sockaddr_in6 s_in6; 1519fcf3ce44SJohn Forte } sa_rsvr = { 0 }; 1520fcf3ce44SJohn Forte void *so; 1521*0f1702c5SYu Xiangning struct sockaddr_in6 t_addr; 1522*0f1702c5SYu Xiangning socklen_t t_addrlen; 1523fcf3ce44SJohn Forte 1524*0f1702c5SYu Xiangning bzero(&t_addr, sizeof (struct sockaddr_in6)); 1525*0f1702c5SYu Xiangning t_addrlen = sizeof (struct sockaddr_in6); 1526fcf3ce44SJohn Forte if (isns_server_addr->a_addr.i_insize == sizeof (struct in_addr)) { 1527fcf3ce44SJohn Forte /* IPv4 */ 1528fcf3ce44SJohn Forte sa_rsvr.s_in4.sin_family = AF_INET; 1529fcf3ce44SJohn Forte sa_rsvr.s_in4.sin_port = htons(isns_server_addr->a_port); 1530fcf3ce44SJohn Forte sa_rsvr.s_in4.sin_addr.s_addr = 1531fcf3ce44SJohn Forte isns_server_addr->a_addr.i_addr.in4.s_addr; 1532fcf3ce44SJohn Forte 1533fcf3ce44SJohn Forte /* Create socket */ 1534fcf3ce44SJohn Forte so = iscsi_net->socket(AF_INET, SOCK_STREAM, 0); 1535fcf3ce44SJohn Forte } else { 1536fcf3ce44SJohn Forte /* IPv6 */ 1537fcf3ce44SJohn Forte sa_rsvr.s_in6.sin6_family = AF_INET6; 1538fcf3ce44SJohn Forte bcopy(&(isns_server_addr->a_addr.i_addr.in6), 1539fcf3ce44SJohn Forte sa_rsvr.s_in6.sin6_addr.s6_addr, 1540fcf3ce44SJohn Forte sizeof (struct in6_addr)); 1541fcf3ce44SJohn Forte sa_rsvr.s_in6.sin6_port = htons(isns_server_addr->a_port); 1542fcf3ce44SJohn Forte /* Create socket */ 1543fcf3ce44SJohn Forte so = iscsi_net->socket(AF_INET6, SOCK_STREAM, 0); 1544fcf3ce44SJohn Forte } 1545fcf3ce44SJohn Forte 1546fcf3ce44SJohn Forte if (so == NULL) { 1547fcf3ce44SJohn Forte return (NULL); 1548fcf3ce44SJohn Forte } 1549fcf3ce44SJohn Forte 1550fcf3ce44SJohn Forte rval = iscsi_net->connect(so, &sa_rsvr.sin, 1551fcf3ce44SJohn Forte (isns_server_addr->a_addr.i_insize == sizeof (struct in_addr)) ? 1552fcf3ce44SJohn Forte sizeof (struct sockaddr_in) : 1553fcf3ce44SJohn Forte sizeof (struct sockaddr_in6), 0, 0); 1554fcf3ce44SJohn Forte 1555fcf3ce44SJohn Forte if (rval != 0) { 1556fcf3ce44SJohn Forte /* Flag value 2 indicates both cantsend and cantrecv */ 1557fcf3ce44SJohn Forte iscsi_net->shutdown(so, 2); 1558fcf3ce44SJohn Forte iscsi_net->close(so); 1559fcf3ce44SJohn Forte return (NULL); 1560fcf3ce44SJohn Forte } 1561fcf3ce44SJohn Forte 1562*0f1702c5SYu Xiangning (void) iscsi_net->getsockname(so, (struct sockaddr *)&t_addr, 1563*0f1702c5SYu Xiangning &t_addrlen); 1564fcf3ce44SJohn Forte 1565fcf3ce44SJohn Forte return (so); 1566fcf3ce44SJohn Forte } 1567fcf3ce44SJohn Forte 1568fcf3ce44SJohn Forte static ssize_t 1569fcf3ce44SJohn Forte isns_send_pdu(void *socket, isns_pdu_t *pdu) 1570fcf3ce44SJohn Forte { 1571fcf3ce44SJohn Forte int iovlen = 0; 1572fcf3ce44SJohn Forte iovec_t iovec[ISNS_MAX_IOVEC]; 1573fcf3ce44SJohn Forte struct msghdr msg; 1574fcf3ce44SJohn Forte size_t send_len; 1575fcf3ce44SJohn Forte size_t total_len = 0; 1576fcf3ce44SJohn Forte 1577fcf3ce44SJohn Forte ASSERT(iovlen < ISNS_MAX_IOVEC); 1578fcf3ce44SJohn Forte iovec[iovlen].iov_base = (void *)pdu; 1579fcf3ce44SJohn Forte iovec[iovlen].iov_len = (ISNSP_HEADER_SIZE); 1580fcf3ce44SJohn Forte total_len += (ISNSP_HEADER_SIZE); 1581fcf3ce44SJohn Forte iovlen++; 1582fcf3ce44SJohn Forte 1583fcf3ce44SJohn Forte ASSERT(iovlen < ISNS_MAX_IOVEC); 1584fcf3ce44SJohn Forte iovec[iovlen].iov_base = (void *)pdu->payload; 1585fcf3ce44SJohn Forte iovec[iovlen].iov_len = ntohs(pdu->payload_len); 1586fcf3ce44SJohn Forte total_len += ntohs(pdu->payload_len); 1587fcf3ce44SJohn Forte iovlen++; 1588fcf3ce44SJohn Forte 1589fcf3ce44SJohn Forte /* Initialization of the message header. */ 1590fcf3ce44SJohn Forte bzero(&msg, sizeof (msg)); 1591fcf3ce44SJohn Forte msg.msg_iov = &iovec[0]; 1592fcf3ce44SJohn Forte msg.msg_flags = MSG_WAITALL; 1593fcf3ce44SJohn Forte msg.msg_iovlen = iovlen; 1594fcf3ce44SJohn Forte 1595fcf3ce44SJohn Forte send_len = iscsi_net->sendmsg(socket, &msg); 1596fcf3ce44SJohn Forte return (send_len == total_len ? 0 : -1); 1597fcf3ce44SJohn Forte } 1598fcf3ce44SJohn Forte 1599fcf3ce44SJohn Forte static 1600fcf3ce44SJohn Forte size_t 1601fcf3ce44SJohn Forte isns_rcv_pdu(void *socket, isns_pdu_t **pdu, size_t *pdu_size) 1602fcf3ce44SJohn Forte { 1603fcf3ce44SJohn Forte int poll_cnt; 1604fcf3ce44SJohn Forte iovec_t iovec[ISNS_MAX_IOVEC]; 1605fcf3ce44SJohn Forte isns_pdu_t *tmp_pdu_hdr; 1606fcf3ce44SJohn Forte size_t bytes_received, total_bytes_received = 0, payload_len = 0; 1607fcf3ce44SJohn Forte struct msghdr msg; 1608fcf3ce44SJohn Forte uint8_t *tmp_pdu_data; 1609fcf3ce44SJohn Forte 1610fcf3ce44SJohn Forte /* Receive the header first */ 1611fcf3ce44SJohn Forte tmp_pdu_hdr = (isns_pdu_t *)kmem_zalloc(ISNSP_HEADER_SIZE, KM_SLEEP); 1612fcf3ce44SJohn Forte (void) memset((char *)&iovec[0], 0, sizeof (iovec_t)); 1613fcf3ce44SJohn Forte iovec[0].iov_base = (void *)tmp_pdu_hdr; 1614fcf3ce44SJohn Forte iovec[0].iov_len = ISNSP_HEADER_SIZE; 1615fcf3ce44SJohn Forte 1616fcf3ce44SJohn Forte /* Initialization of the message header. */ 1617fcf3ce44SJohn Forte bzero(&msg, sizeof (msg)); 1618fcf3ce44SJohn Forte msg.msg_iov = &iovec[0]; 1619fcf3ce44SJohn Forte msg.msg_flags = MSG_WAITALL; 1620fcf3ce44SJohn Forte msg.msg_iovlen = 1; 1621fcf3ce44SJohn Forte 1622fcf3ce44SJohn Forte /* Poll and receive the packets. */ 1623fcf3ce44SJohn Forte poll_cnt = 0; 1624fcf3ce44SJohn Forte do { 1625fcf3ce44SJohn Forte bytes_received = iscsi_net->recvmsg(socket, &msg, 1626fcf3ce44SJohn Forte ISNS_RCV_TIMEOUT); 1627fcf3ce44SJohn Forte if (bytes_received == 0) { 1628fcf3ce44SJohn Forte /* Not yet. Increase poll count and try again. */ 1629fcf3ce44SJohn Forte poll_cnt++; 1630fcf3ce44SJohn Forte continue; 1631fcf3ce44SJohn Forte } else { 1632fcf3ce44SJohn Forte /* OK data received. */ 1633fcf3ce44SJohn Forte break; 1634fcf3ce44SJohn Forte } 1635fcf3ce44SJohn Forte } while (poll_cnt < ISNS_RCV_RETRY_MAX); 1636fcf3ce44SJohn Forte 1637fcf3ce44SJohn Forte DTRACE_PROBE2(isns_rcv_pdu_hdr_summary, 1638fcf3ce44SJohn Forte int, poll_cnt, int, bytes_received); 1639fcf3ce44SJohn Forte if (poll_cnt >= ISNS_RCV_RETRY_MAX) { 1640fcf3ce44SJohn Forte kmem_free(tmp_pdu_hdr, ISNSP_HEADER_SIZE); 1641fcf3ce44SJohn Forte *pdu = NULL; 1642fcf3ce44SJohn Forte *pdu_size = 0; 1643fcf3ce44SJohn Forte return (0); 1644fcf3ce44SJohn Forte } 1645fcf3ce44SJohn Forte if (bytes_received == 0 || bytes_received != ISNSP_HEADER_SIZE) { 1646fcf3ce44SJohn Forte kmem_free(tmp_pdu_hdr, ISNSP_HEADER_SIZE); 1647fcf3ce44SJohn Forte *pdu = NULL; 1648fcf3ce44SJohn Forte *pdu_size = 0; 1649fcf3ce44SJohn Forte return (0); 1650fcf3ce44SJohn Forte } 1651fcf3ce44SJohn Forte total_bytes_received += bytes_received; 1652fcf3ce44SJohn Forte 1653fcf3ce44SJohn Forte payload_len = ntohs(tmp_pdu_hdr->payload_len); 1654fcf3ce44SJohn Forte DTRACE_PROBE1(isns_rcv_pdu_probe1, int, payload_len); 1655fcf3ce44SJohn Forte /* Verify the received payload len is within limit */ 1656fcf3ce44SJohn Forte if (payload_len > ISNSP_MAX_PAYLOAD_SIZE) { 1657fcf3ce44SJohn Forte kmem_free(tmp_pdu_hdr, ISNSP_HEADER_SIZE); 1658fcf3ce44SJohn Forte *pdu = NULL; 1659fcf3ce44SJohn Forte *pdu_size = 0; 1660fcf3ce44SJohn Forte return (0); 1661fcf3ce44SJohn Forte } 1662fcf3ce44SJohn Forte 1663fcf3ce44SJohn Forte /* Proceed to receive additional data. */ 1664fcf3ce44SJohn Forte tmp_pdu_data = kmem_zalloc(payload_len, KM_SLEEP); 1665fcf3ce44SJohn Forte (void) memset((char *)&iovec[0], 0, sizeof (iovec_t)); 1666fcf3ce44SJohn Forte iovec[0].iov_base = (void *)tmp_pdu_data; 1667fcf3ce44SJohn Forte iovec[0].iov_len = payload_len; 1668fcf3ce44SJohn Forte 1669fcf3ce44SJohn Forte /* Initialization of the message header. */ 1670fcf3ce44SJohn Forte bzero(&msg, sizeof (msg)); 1671fcf3ce44SJohn Forte msg.msg_iov = &iovec[0]; 1672fcf3ce44SJohn Forte msg.msg_flags = MSG_WAITALL; 1673fcf3ce44SJohn Forte msg.msg_iovlen = 1; 1674fcf3ce44SJohn Forte 1675fcf3ce44SJohn Forte /* Poll and receive the rest of the PDU. */ 1676fcf3ce44SJohn Forte poll_cnt = 0; 1677fcf3ce44SJohn Forte do { 1678fcf3ce44SJohn Forte bytes_received = iscsi_net->recvmsg(socket, &msg, 1679fcf3ce44SJohn Forte ISNS_RCV_TIMEOUT); 1680fcf3ce44SJohn Forte if (bytes_received == 0) { 1681fcf3ce44SJohn Forte /* Not yet. Increase poll count and try again. */ 1682fcf3ce44SJohn Forte poll_cnt++; 1683fcf3ce44SJohn Forte continue; 1684fcf3ce44SJohn Forte } else { 1685fcf3ce44SJohn Forte /* OK data received. */ 1686fcf3ce44SJohn Forte break; 1687fcf3ce44SJohn Forte } 1688fcf3ce44SJohn Forte } while (poll_cnt < ISNS_RCV_RETRY_MAX); 1689fcf3ce44SJohn Forte 1690fcf3ce44SJohn Forte DTRACE_PROBE2(isns_rcv_pdu_data_summary, 1691fcf3ce44SJohn Forte int, poll_cnt, int, bytes_received); 1692fcf3ce44SJohn Forte 1693fcf3ce44SJohn Forte if (poll_cnt >= ISNS_RCV_RETRY_MAX) { 1694fcf3ce44SJohn Forte kmem_free(tmp_pdu_data, payload_len); 1695fcf3ce44SJohn Forte kmem_free(tmp_pdu_hdr, ISNSP_HEADER_SIZE); 1696fcf3ce44SJohn Forte *pdu = NULL; 1697fcf3ce44SJohn Forte *pdu_size = 0; 1698fcf3ce44SJohn Forte return (0); 1699fcf3ce44SJohn Forte } 1700fcf3ce44SJohn Forte if (bytes_received == 0 || bytes_received != payload_len) { 1701fcf3ce44SJohn Forte kmem_free(tmp_pdu_data, payload_len); 1702fcf3ce44SJohn Forte kmem_free(tmp_pdu_hdr, ISNSP_HEADER_SIZE); 1703fcf3ce44SJohn Forte *pdu = NULL; 1704fcf3ce44SJohn Forte *pdu_size = 0; 1705fcf3ce44SJohn Forte return (0); 1706fcf3ce44SJohn Forte } 1707fcf3ce44SJohn Forte total_bytes_received += bytes_received; 1708fcf3ce44SJohn Forte 1709fcf3ce44SJohn Forte *pdu_size = ISNSP_HEADER_SIZE + payload_len; 1710fcf3ce44SJohn Forte (*pdu) = (isns_pdu_t *)kmem_zalloc((*pdu_size), KM_SLEEP); 1711fcf3ce44SJohn Forte (*pdu)->version = ntohs(tmp_pdu_hdr->version); 1712fcf3ce44SJohn Forte (*pdu)->func_id = ntohs(tmp_pdu_hdr->func_id); 1713fcf3ce44SJohn Forte (*pdu)->payload_len = payload_len; 1714fcf3ce44SJohn Forte (*pdu)->flags = ntohs(tmp_pdu_hdr->flags); 1715fcf3ce44SJohn Forte (*pdu)->xid = ntohs(tmp_pdu_hdr->xid); 1716fcf3ce44SJohn Forte (*pdu)->seq = ntohs(tmp_pdu_hdr->seq); 1717fcf3ce44SJohn Forte bcopy(tmp_pdu_data, &((*pdu)->payload), payload_len); 1718fcf3ce44SJohn Forte 1719fcf3ce44SJohn Forte kmem_free(tmp_pdu_data, payload_len); 1720fcf3ce44SJohn Forte tmp_pdu_data = NULL; 1721fcf3ce44SJohn Forte kmem_free(tmp_pdu_hdr, ISNSP_HEADER_SIZE); 1722fcf3ce44SJohn Forte tmp_pdu_hdr = NULL; 1723fcf3ce44SJohn Forte 1724fcf3ce44SJohn Forte return (total_bytes_received); 1725fcf3ce44SJohn Forte } 1726fcf3ce44SJohn Forte 1727fcf3ce44SJohn Forte 1728fcf3ce44SJohn Forte /* 1729fcf3ce44SJohn Forte * isns_create_dev_attr_reg_pdu - isns client registration pdu 1730fcf3ce44SJohn Forte */ 1731fcf3ce44SJohn Forte static size_t 1732fcf3ce44SJohn Forte isns_create_dev_attr_reg_pdu( 1733fcf3ce44SJohn Forte uint8_t *node_name, 1734fcf3ce44SJohn Forte uint8_t *node_alias, 1735fcf3ce44SJohn Forte uint32_t node_type, 1736fcf3ce44SJohn Forte uint16_t *xid_p, 1737fcf3ce44SJohn Forte isns_pdu_t **out_pdu) 1738fcf3ce44SJohn Forte { 1739fcf3ce44SJohn Forte in_port_t local_port; 1740fcf3ce44SJohn Forte isns_pdu_t *pdu; 1741fcf3ce44SJohn Forte size_t pdu_size, node_name_len, node_alias_len; 1742fcf3ce44SJohn Forte uint16_t flags; 1743fcf3ce44SJohn Forte 1744fcf3ce44SJohn Forte ASSERT(node_name != NULL); 1745fcf3ce44SJohn Forte ASSERT(node_alias != NULL); 1746fcf3ce44SJohn Forte ASSERT(local_addr != NULL); 1747fcf3ce44SJohn Forte 1748fcf3ce44SJohn Forte /* RFC 4171 section 6.1 - NULLs included in the length. */ 1749fcf3ce44SJohn Forte node_name_len = strlen((char *)node_name) + 1; 1750fcf3ce44SJohn Forte node_alias_len = strlen((char *)node_alias) + 1; 1751fcf3ce44SJohn Forte 1752fcf3ce44SJohn Forte if (node_name_len == 1) { 1753fcf3ce44SJohn Forte *out_pdu = NULL; 1754fcf3ce44SJohn Forte return (0); 1755fcf3ce44SJohn Forte } 1756fcf3ce44SJohn Forte 1757fcf3ce44SJohn Forte /* 1758fcf3ce44SJohn Forte * Create DevAttrReg Message 1759fcf3ce44SJohn Forte * 1760fcf3ce44SJohn Forte * Enable the replace bit so that we can update 1761fcf3ce44SJohn Forte * existing registration 1762fcf3ce44SJohn Forte */ 1763fcf3ce44SJohn Forte flags = ISNS_FLAG_FIRST_PDU | 1764fcf3ce44SJohn Forte ISNS_FLAG_LAST_PDU | 1765fcf3ce44SJohn Forte ISNS_FLAG_REPLACE_REG; 1766fcf3ce44SJohn Forte pdu_size = isns_create_pdu_header(ISNS_DEV_ATTR_REG, flags, &pdu); 1767fcf3ce44SJohn Forte *xid_p = pdu->xid; 1768fcf3ce44SJohn Forte 1769fcf3ce44SJohn Forte /* Source attribute */ 1770fcf3ce44SJohn Forte if (isns_add_attr(pdu, pdu_size, ISNS_ISCSI_NAME_ATTR_ID, 1771fcf3ce44SJohn Forte node_name_len, node_name, 0) != 0) { 1772fcf3ce44SJohn Forte kmem_free(pdu, pdu_size); 1773fcf3ce44SJohn Forte *out_pdu = NULL; 1774fcf3ce44SJohn Forte return (0); 1775fcf3ce44SJohn Forte } 1776fcf3ce44SJohn Forte 1777fcf3ce44SJohn Forte /* 1778fcf3ce44SJohn Forte * Message Key Attributes 1779fcf3ce44SJohn Forte * 1780fcf3ce44SJohn Forte * EID attribute - Section 6.2.1 1781fcf3ce44SJohn Forte * This is required for re-registrations or Replace 1782fcf3ce44SJohn Forte * Bit is ignored - Section 5.6.5.1 1783fcf3ce44SJohn Forte */ 1784fcf3ce44SJohn Forte if (isns_add_attr(pdu, pdu_size, ISNS_EID_ATTR_ID, 1785fcf3ce44SJohn Forte node_name_len, node_name, 0) != 0) { 1786fcf3ce44SJohn Forte kmem_free(pdu, pdu_size); 1787fcf3ce44SJohn Forte *out_pdu = NULL; 1788fcf3ce44SJohn Forte return (0); 1789fcf3ce44SJohn Forte } 1790fcf3ce44SJohn Forte 1791fcf3ce44SJohn Forte /* Delimiter */ 1792fcf3ce44SJohn Forte if (isns_add_attr(pdu, pdu_size, ISNS_DELIMITER_ATTR_ID, 0, 0, 0) 1793fcf3ce44SJohn Forte != 0) { 1794fcf3ce44SJohn Forte kmem_free(pdu, pdu_size); 1795fcf3ce44SJohn Forte *out_pdu = NULL; 1796fcf3ce44SJohn Forte return (0); 1797fcf3ce44SJohn Forte } 1798fcf3ce44SJohn Forte 1799fcf3ce44SJohn Forte /* EID attribute - Section 6.2.1 */ 1800fcf3ce44SJohn Forte if (isns_add_attr(pdu, pdu_size, ISNS_EID_ATTR_ID, 1801fcf3ce44SJohn Forte node_name_len, node_name, 0) != 0) { 1802fcf3ce44SJohn Forte kmem_free(pdu, pdu_size); 1803fcf3ce44SJohn Forte *out_pdu = NULL; 1804fcf3ce44SJohn Forte return (0); 1805fcf3ce44SJohn Forte } 1806fcf3ce44SJohn Forte 1807fcf3ce44SJohn Forte /* ENTITY Protocol - Section 6.2.2 */ 1808fcf3ce44SJohn Forte if (isns_add_attr(pdu, pdu_size, ISNS_ENTITY_PROTOCOL_ATTR_ID, 4, 1809fcf3ce44SJohn Forte 0, ISNS_ENTITY_PROTOCOL_ISCSI) != 0) { 1810fcf3ce44SJohn Forte kmem_free(pdu, pdu_size); 1811fcf3ce44SJohn Forte *out_pdu = NULL; 1812fcf3ce44SJohn Forte return (0); 1813fcf3ce44SJohn Forte } 1814fcf3ce44SJohn Forte 1815fcf3ce44SJohn Forte /* iSCSI Name - Section 6.4.1 */ 1816fcf3ce44SJohn Forte if (isns_add_attr(pdu, pdu_size, ISNS_ISCSI_NAME_ATTR_ID, 1817fcf3ce44SJohn Forte node_name_len, node_name, 0) != 0) { 1818fcf3ce44SJohn Forte kmem_free(pdu, pdu_size); 1819fcf3ce44SJohn Forte *out_pdu = NULL; 1820fcf3ce44SJohn Forte return (0); 1821fcf3ce44SJohn Forte } 1822fcf3ce44SJohn Forte 1823fcf3ce44SJohn Forte /* iSCSI Alias - Section 6.4.3 Optional */ 1824fcf3ce44SJohn Forte if (node_alias_len > 1) { 1825fcf3ce44SJohn Forte if (isns_add_attr(pdu, pdu_size, ISNS_ISCSI_ALIAS_ATTR_ID, 1826fcf3ce44SJohn Forte node_alias_len, node_alias, 0) != 0) { 1827fcf3ce44SJohn Forte kmem_free(pdu, pdu_size); 1828fcf3ce44SJohn Forte *out_pdu = NULL; 1829fcf3ce44SJohn Forte return (0); 1830fcf3ce44SJohn Forte } 1831fcf3ce44SJohn Forte } 1832fcf3ce44SJohn Forte 1833fcf3ce44SJohn Forte /* iSCSI Node Type - Section 6.4.2 */ 1834fcf3ce44SJohn Forte if (isns_add_attr(pdu, pdu_size, ISNS_ISCSI_NODE_TYPE_ATTR_ID, 4, 1835fcf3ce44SJohn Forte 0, node_type) != 0) { 1836fcf3ce44SJohn Forte kmem_free(pdu, pdu_size); 1837fcf3ce44SJohn Forte *out_pdu = NULL; 1838fcf3ce44SJohn Forte return (0); 1839fcf3ce44SJohn Forte } 1840fcf3ce44SJohn Forte 1841fcf3ce44SJohn Forte mutex_enter(&esi_scn_thr_mutex); 1842fcf3ce44SJohn Forte local_port = local_addr->a_port; 1843fcf3ce44SJohn Forte mutex_exit(&esi_scn_thr_mutex); 1844fcf3ce44SJohn Forte 1845fcf3ce44SJohn Forte mutex_enter(&esi_scn_thr_mutex); 1846fcf3ce44SJohn Forte /* Portal IP Address - Section 6.5.2 */ 1847fcf3ce44SJohn Forte if (isns_add_attr(pdu, pdu_size, ISNS_PORTAL_IP_ADDR_ATTR_ID, 16, 1848fcf3ce44SJohn Forte &(local_addr->a_addr.i_addr.in4), 1849fcf3ce44SJohn Forte local_addr->a_addr.i_insize) != 0) { 1850fcf3ce44SJohn Forte kmem_free(pdu, pdu_size); 1851fcf3ce44SJohn Forte *out_pdu = NULL; 1852fcf3ce44SJohn Forte mutex_exit(&esi_scn_thr_mutex); 1853fcf3ce44SJohn Forte return (0); 1854fcf3ce44SJohn Forte } 1855fcf3ce44SJohn Forte mutex_exit(&esi_scn_thr_mutex); 1856fcf3ce44SJohn Forte 1857fcf3ce44SJohn Forte /* Portal Port - Section 6.5.3 */ 1858fcf3ce44SJohn Forte if (isns_add_attr(pdu, pdu_size, ISNS_PORTAL_PORT_ATTR_ID, 4, 0, 1859fcf3ce44SJohn Forte local_port) != 0) { 1860fcf3ce44SJohn Forte kmem_free(pdu, pdu_size); 1861fcf3ce44SJohn Forte *out_pdu = NULL; 1862fcf3ce44SJohn Forte return (0); 1863fcf3ce44SJohn Forte } 1864fcf3ce44SJohn Forte 1865fcf3ce44SJohn Forte /* SCN Port - Section 6.3.7 */ 1866fcf3ce44SJohn Forte if (isns_add_attr(pdu, pdu_size, ISNS_SCN_PORT_ATTR_ID, 4, 0, 1867fcf3ce44SJohn Forte local_port) != 0) { 1868fcf3ce44SJohn Forte kmem_free(pdu, pdu_size); 1869fcf3ce44SJohn Forte *out_pdu = NULL; 1870fcf3ce44SJohn Forte return (0); 1871fcf3ce44SJohn Forte } 1872fcf3ce44SJohn Forte 1873fcf3ce44SJohn Forte /* ESI Port - Section 6.3.5 */ 1874fcf3ce44SJohn Forte if (isns_add_attr(pdu, pdu_size, ISNS_ESI_PORT_ATTR_ID, 4, 0, 1875fcf3ce44SJohn Forte local_port) != 0) { 1876fcf3ce44SJohn Forte kmem_free(pdu, pdu_size); 1877fcf3ce44SJohn Forte *out_pdu = NULL; 1878fcf3ce44SJohn Forte return (0); 1879fcf3ce44SJohn Forte } 1880fcf3ce44SJohn Forte 1881fcf3ce44SJohn Forte *out_pdu = pdu; 1882fcf3ce44SJohn Forte return (pdu_size); 1883fcf3ce44SJohn Forte } 1884fcf3ce44SJohn Forte 1885fcf3ce44SJohn Forte /* 1886fcf3ce44SJohn Forte * isns_create_dev_dereg_pdu - Create an iSNS PDU for deregistration. 1887fcf3ce44SJohn Forte */ 1888fcf3ce44SJohn Forte static size_t 1889fcf3ce44SJohn Forte isns_create_dev_dereg_pdu( 1890fcf3ce44SJohn Forte uint8_t *node_name, 1891fcf3ce44SJohn Forte uint16_t *xid_p, 1892fcf3ce44SJohn Forte isns_pdu_t **out_pdu) 1893fcf3ce44SJohn Forte { 1894fcf3ce44SJohn Forte isns_pdu_t *pdu; 1895fcf3ce44SJohn Forte size_t pdu_size, node_name_len; 1896fcf3ce44SJohn Forte uint16_t flags; 1897fcf3ce44SJohn Forte 1898fcf3ce44SJohn Forte ASSERT(node_name != NULL); 1899fcf3ce44SJohn Forte 1900fcf3ce44SJohn Forte /* RFC 4171 section 6.1 - NULLs included in the length. */ 1901fcf3ce44SJohn Forte node_name_len = strlen((char *)node_name) + 1; 1902fcf3ce44SJohn Forte 1903fcf3ce44SJohn Forte if (node_name_len == 1) { 1904fcf3ce44SJohn Forte *out_pdu = NULL; 1905fcf3ce44SJohn Forte return (0); 1906fcf3ce44SJohn Forte } 1907fcf3ce44SJohn Forte 1908fcf3ce44SJohn Forte /* 1909fcf3ce44SJohn Forte * Create DevDeReg Message 1910fcf3ce44SJohn Forte */ 1911fcf3ce44SJohn Forte flags = ISNS_FLAG_FIRST_PDU | 1912fcf3ce44SJohn Forte ISNS_FLAG_LAST_PDU; 1913fcf3ce44SJohn Forte pdu_size = isns_create_pdu_header(ISNS_DEV_DEREG, flags, &pdu); 1914fcf3ce44SJohn Forte *xid_p = pdu->xid; 1915fcf3ce44SJohn Forte 1916fcf3ce44SJohn Forte /* Source attribute */ 1917fcf3ce44SJohn Forte if (isns_add_attr(pdu, pdu_size, ISNS_ISCSI_NAME_ATTR_ID, 1918fcf3ce44SJohn Forte node_name_len, node_name, 0) != 0) { 1919fcf3ce44SJohn Forte kmem_free(pdu, pdu_size); 1920fcf3ce44SJohn Forte *out_pdu = NULL; 1921fcf3ce44SJohn Forte return (0); 1922fcf3ce44SJohn Forte } 1923fcf3ce44SJohn Forte 1924fcf3ce44SJohn Forte /* Delimiter */ 1925fcf3ce44SJohn Forte if (isns_add_attr(pdu, pdu_size, ISNS_DELIMITER_ATTR_ID, 0, 0, 0) 1926fcf3ce44SJohn Forte != 0) { 1927fcf3ce44SJohn Forte kmem_free(pdu, pdu_size); 1928fcf3ce44SJohn Forte *out_pdu = NULL; 1929fcf3ce44SJohn Forte return (0); 1930fcf3ce44SJohn Forte } 1931fcf3ce44SJohn Forte 1932fcf3ce44SJohn Forte /* Entity Identifier */ 1933fcf3ce44SJohn Forte if (isns_add_attr(pdu, pdu_size, ISNS_EID_ATTR_ID, 1934fcf3ce44SJohn Forte node_name_len, node_name, 0) != 0) { 1935fcf3ce44SJohn Forte kmem_free(pdu, pdu_size); 1936fcf3ce44SJohn Forte *out_pdu = NULL; 1937fcf3ce44SJohn Forte return (0); 1938fcf3ce44SJohn Forte } 1939fcf3ce44SJohn Forte 1940fcf3ce44SJohn Forte *out_pdu = pdu; 1941fcf3ce44SJohn Forte return (pdu_size); 1942fcf3ce44SJohn Forte } 1943fcf3ce44SJohn Forte 1944fcf3ce44SJohn Forte /* 1945fcf3ce44SJohn Forte * isns_create_dev_attr_target_nodes_pdu - get all accessible targets 1946fcf3ce44SJohn Forte * 1947fcf3ce44SJohn Forte * Querys for a list of all accessible target nodes for this 1948fcf3ce44SJohn Forte * initiator. Requests all required login information (name, 1949fcf3ce44SJohn Forte * ip, port, tpgt). 1950fcf3ce44SJohn Forte */ 1951fcf3ce44SJohn Forte static size_t 1952fcf3ce44SJohn Forte isns_create_dev_attr_qry_target_nodes_pdu( 1953fcf3ce44SJohn Forte uint8_t *node_name, 1954fcf3ce44SJohn Forte uint8_t *node_alias, 1955fcf3ce44SJohn Forte uint16_t *xid_p, isns_pdu_t **out_pdu) 1956fcf3ce44SJohn Forte { 1957fcf3ce44SJohn Forte isns_pdu_t *pdu_p; 1958fcf3ce44SJohn Forte uint16_t flags; 1959fcf3ce44SJohn Forte size_t pdu_size, node_name_len; 1960fcf3ce44SJohn Forte 1961fcf3ce44SJohn Forte ASSERT(node_name != NULL); 1962fcf3ce44SJohn Forte ASSERT(node_alias != NULL); 1963fcf3ce44SJohn Forte 1964fcf3ce44SJohn Forte /* RFC 4171 section 6.1 - NULLs included in the length. */ 1965fcf3ce44SJohn Forte node_name_len = strlen((char *)node_name) + 1; 1966fcf3ce44SJohn Forte 1967fcf3ce44SJohn Forte if (node_name_len == 1) { 1968fcf3ce44SJohn Forte *out_pdu = NULL; 1969fcf3ce44SJohn Forte return (0); 1970fcf3ce44SJohn Forte } 1971fcf3ce44SJohn Forte 1972fcf3ce44SJohn Forte /* Create DevAttrQry Message */ 1973fcf3ce44SJohn Forte flags = ISNS_FLAG_FIRST_PDU | 1974fcf3ce44SJohn Forte ISNS_FLAG_LAST_PDU; 1975fcf3ce44SJohn Forte pdu_size = isns_create_pdu_header(ISNS_DEV_ATTR_QRY, flags, &pdu_p); 1976fcf3ce44SJohn Forte *xid_p = pdu_p->xid; 1977fcf3ce44SJohn Forte 1978fcf3ce44SJohn Forte /* Source attribute */ 1979fcf3ce44SJohn Forte if (isns_add_attr(pdu_p, pdu_size, ISNS_ISCSI_NAME_ATTR_ID, 1980fcf3ce44SJohn Forte node_name_len, node_name, 0) != 0) { 1981fcf3ce44SJohn Forte kmem_free(pdu_p, pdu_size); 1982fcf3ce44SJohn Forte *out_pdu = NULL; 1983fcf3ce44SJohn Forte return (0); 1984fcf3ce44SJohn Forte } 1985fcf3ce44SJohn Forte 1986fcf3ce44SJohn Forte /* 1987fcf3ce44SJohn Forte * Message Key Attribute 1988fcf3ce44SJohn Forte * 1989fcf3ce44SJohn Forte * iSCSI Node Type 1990fcf3ce44SJohn Forte * Query target nodes only 1991fcf3ce44SJohn Forte */ 1992fcf3ce44SJohn Forte if (isns_add_attr(pdu_p, pdu_size, ISNS_ISCSI_NODE_TYPE_ATTR_ID, 1993fcf3ce44SJohn Forte 4, 0, ISNS_TARGET_NODE_TYPE) != 0) { 1994fcf3ce44SJohn Forte kmem_free(pdu_p, pdu_size); 1995fcf3ce44SJohn Forte *out_pdu = NULL; 1996fcf3ce44SJohn Forte return (0); 1997fcf3ce44SJohn Forte } 1998fcf3ce44SJohn Forte 1999fcf3ce44SJohn Forte /* Delimiter */ 2000fcf3ce44SJohn Forte if (isns_add_attr(pdu_p, pdu_size, 2001fcf3ce44SJohn Forte ISNS_DELIMITER_ATTR_ID, 0, 0, 0) != 0) { 2002fcf3ce44SJohn Forte kmem_free(pdu_p, pdu_size); 2003fcf3ce44SJohn Forte *out_pdu = NULL; 2004fcf3ce44SJohn Forte return (0); 2005fcf3ce44SJohn Forte } 2006fcf3ce44SJohn Forte 2007fcf3ce44SJohn Forte /* PG iSCSI Name - Zero length TLV */ 2008fcf3ce44SJohn Forte if (isns_add_attr(pdu_p, pdu_size, ISNS_PG_ISCSI_NAME_ATTR_ID, 2009fcf3ce44SJohn Forte 0, 0, 0) != 0) { 2010fcf3ce44SJohn Forte kmem_free(pdu_p, pdu_size); 2011fcf3ce44SJohn Forte *out_pdu = NULL; 2012fcf3ce44SJohn Forte return (0); 2013fcf3ce44SJohn Forte } 2014fcf3ce44SJohn Forte 2015fcf3ce44SJohn Forte /* PG Portal IP Address - Zero length TLV */ 2016fcf3ce44SJohn Forte if (isns_add_attr(pdu_p, pdu_size, ISNS_PG_PORTAL_IP_ADDR_ATTR_ID, 2017fcf3ce44SJohn Forte 0, 0, 0) != 0) { 2018fcf3ce44SJohn Forte kmem_free(pdu_p, pdu_size); 2019fcf3ce44SJohn Forte *out_pdu = NULL; 2020fcf3ce44SJohn Forte return (0); 2021fcf3ce44SJohn Forte } 2022fcf3ce44SJohn Forte 2023fcf3ce44SJohn Forte /* PG Portal Port - Zero length TLV */ 2024fcf3ce44SJohn Forte if (isns_add_attr(pdu_p, pdu_size, ISNS_PG_PORTAL_PORT_ATTR_ID, 2025fcf3ce44SJohn Forte 0, 0, 0) != 0) { 2026fcf3ce44SJohn Forte kmem_free(pdu_p, pdu_size); 2027fcf3ce44SJohn Forte *out_pdu = NULL; 2028fcf3ce44SJohn Forte return (0); 2029fcf3ce44SJohn Forte } 2030fcf3ce44SJohn Forte 2031fcf3ce44SJohn Forte /* PG Portal Group Tag - Zero length TLV */ 2032fcf3ce44SJohn Forte if (isns_add_attr(pdu_p, pdu_size, 2033fcf3ce44SJohn Forte ISNS_PG_TAG_ATTR_ID, 0, 0, 0) != 0) { 2034fcf3ce44SJohn Forte kmem_free(pdu_p, pdu_size); 2035fcf3ce44SJohn Forte *out_pdu = NULL; 2036fcf3ce44SJohn Forte return (0); 2037fcf3ce44SJohn Forte } 2038fcf3ce44SJohn Forte 2039fcf3ce44SJohn Forte *out_pdu = pdu_p; 2040fcf3ce44SJohn Forte return (pdu_size); 2041fcf3ce44SJohn Forte } 2042fcf3ce44SJohn Forte 2043fcf3ce44SJohn Forte static 2044fcf3ce44SJohn Forte size_t 2045fcf3ce44SJohn Forte isns_create_dev_attr_qry_one_pg_pdu( 2046fcf3ce44SJohn Forte uint8_t *target_node_name, 2047fcf3ce44SJohn Forte uint8_t *source_node_name, 2048fcf3ce44SJohn Forte uint16_t *xid_p, 2049fcf3ce44SJohn Forte isns_pdu_t **out_pdu) 2050fcf3ce44SJohn Forte { 2051fcf3ce44SJohn Forte isns_pdu_t *pdu_p; 2052fcf3ce44SJohn Forte uint16_t flags; 2053fcf3ce44SJohn Forte size_t pdu_size, source_node_name_len, target_node_name_len; 2054fcf3ce44SJohn Forte 2055fcf3ce44SJohn Forte ASSERT(target_node_name != NULL); 2056fcf3ce44SJohn Forte ASSERT(source_node_name != NULL); 2057fcf3ce44SJohn Forte 2058fcf3ce44SJohn Forte /* RFC 4171 section 6.1 - NULLs included in the length. */ 2059fcf3ce44SJohn Forte source_node_name_len = strlen((char *)source_node_name) + 1; 2060fcf3ce44SJohn Forte target_node_name_len = strlen((char *)target_node_name) + 1; 2061fcf3ce44SJohn Forte 2062fcf3ce44SJohn Forte if (source_node_name_len == 1) { 2063fcf3ce44SJohn Forte *out_pdu = NULL; 2064fcf3ce44SJohn Forte return (0); 2065fcf3ce44SJohn Forte } 2066fcf3ce44SJohn Forte 2067fcf3ce44SJohn Forte /* Create DevAttrQry message scoped to target_node_name */ 2068fcf3ce44SJohn Forte flags = ISNS_FLAG_FIRST_PDU | 2069fcf3ce44SJohn Forte ISNS_FLAG_LAST_PDU; 2070fcf3ce44SJohn Forte pdu_size = isns_create_pdu_header(ISNS_DEV_ATTR_QRY, flags, &pdu_p); 2071fcf3ce44SJohn Forte *xid_p = pdu_p->xid; 2072fcf3ce44SJohn Forte 2073fcf3ce44SJohn Forte /* Source attribute */ 2074fcf3ce44SJohn Forte if (isns_add_attr(pdu_p, pdu_size, ISNS_ISCSI_NAME_ATTR_ID, 2075fcf3ce44SJohn Forte source_node_name_len, source_node_name, 0) != 0) { 2076fcf3ce44SJohn Forte kmem_free(pdu_p, pdu_size); 2077fcf3ce44SJohn Forte *out_pdu = NULL; 2078fcf3ce44SJohn Forte return (0); 2079fcf3ce44SJohn Forte } 2080fcf3ce44SJohn Forte 2081fcf3ce44SJohn Forte /* Message key attribute */ 2082fcf3ce44SJohn Forte /* iSCSI Node Name */ 2083fcf3ce44SJohn Forte if (isns_add_attr(pdu_p, pdu_size, ISNS_ISCSI_NAME_ATTR_ID, 2084fcf3ce44SJohn Forte target_node_name_len, 2085fcf3ce44SJohn Forte target_node_name, 0) != 0) { 2086fcf3ce44SJohn Forte kmem_free(pdu_p, pdu_size); 2087fcf3ce44SJohn Forte *out_pdu = NULL; 2088fcf3ce44SJohn Forte return (0); 2089fcf3ce44SJohn Forte } 2090fcf3ce44SJohn Forte 2091fcf3ce44SJohn Forte /* Delimiter */ 2092fcf3ce44SJohn Forte if (isns_add_attr(pdu_p, pdu_size, 2093fcf3ce44SJohn Forte ISNS_DELIMITER_ATTR_ID, 0, 0, 0) != 0) { 2094fcf3ce44SJohn Forte kmem_free(pdu_p, pdu_size); 2095fcf3ce44SJohn Forte *out_pdu = NULL; 2096fcf3ce44SJohn Forte return (0); 2097fcf3ce44SJohn Forte } 2098fcf3ce44SJohn Forte 2099fcf3ce44SJohn Forte /* PG iSCSI Name - Zero length TLV */ 2100fcf3ce44SJohn Forte if (isns_add_attr(pdu_p, pdu_size, ISNS_PG_ISCSI_NAME_ATTR_ID, 2101fcf3ce44SJohn Forte 0, 0, 0) != 0) { 2102fcf3ce44SJohn Forte kmem_free(pdu_p, pdu_size); 2103fcf3ce44SJohn Forte *out_pdu = NULL; 2104fcf3ce44SJohn Forte return (0); 2105fcf3ce44SJohn Forte } 2106fcf3ce44SJohn Forte 2107fcf3ce44SJohn Forte /* PG Portal IP Address - Zero length TLV */ 2108fcf3ce44SJohn Forte if (isns_add_attr(pdu_p, pdu_size, ISNS_PG_PORTAL_IP_ADDR_ATTR_ID, 2109fcf3ce44SJohn Forte 0, 0, 0) != 0) { 2110fcf3ce44SJohn Forte kmem_free(pdu_p, pdu_size); 2111fcf3ce44SJohn Forte *out_pdu = NULL; 2112fcf3ce44SJohn Forte return (0); 2113fcf3ce44SJohn Forte } 2114fcf3ce44SJohn Forte 2115fcf3ce44SJohn Forte /* PG Portal Port - Zero length TLV */ 2116fcf3ce44SJohn Forte if (isns_add_attr(pdu_p, pdu_size, ISNS_PG_PORTAL_PORT_ATTR_ID, 2117fcf3ce44SJohn Forte 0, 0, 0) != 0) { 2118fcf3ce44SJohn Forte kmem_free(pdu_p, pdu_size); 2119fcf3ce44SJohn Forte *out_pdu = NULL; 2120fcf3ce44SJohn Forte return (0); 2121fcf3ce44SJohn Forte } 2122fcf3ce44SJohn Forte 2123fcf3ce44SJohn Forte /* PG Portal Group Tag - Zero length TLV */ 2124fcf3ce44SJohn Forte if (isns_add_attr(pdu_p, pdu_size, 2125fcf3ce44SJohn Forte ISNS_PG_TAG_ATTR_ID, 0, 0, 0) != 0) { 2126fcf3ce44SJohn Forte kmem_free(pdu_p, pdu_size); 2127fcf3ce44SJohn Forte *out_pdu = NULL; 2128fcf3ce44SJohn Forte return (0); 2129fcf3ce44SJohn Forte } 2130fcf3ce44SJohn Forte 2131fcf3ce44SJohn Forte *out_pdu = pdu_p; 2132fcf3ce44SJohn Forte return (pdu_size); 2133fcf3ce44SJohn Forte } 2134fcf3ce44SJohn Forte 2135fcf3ce44SJohn Forte static 2136fcf3ce44SJohn Forte size_t 2137fcf3ce44SJohn Forte isns_create_scn_reg_pdu( 2138fcf3ce44SJohn Forte uint8_t *node_name, 2139fcf3ce44SJohn Forte uint8_t *node_alias, 2140fcf3ce44SJohn Forte uint16_t *xid_p, 2141fcf3ce44SJohn Forte isns_pdu_t **out_pdu) 2142fcf3ce44SJohn Forte { 2143fcf3ce44SJohn Forte isns_pdu_t *pdu; 2144fcf3ce44SJohn Forte size_t pdu_size, node_name_len; 2145fcf3ce44SJohn Forte uint16_t flags; 2146fcf3ce44SJohn Forte 2147fcf3ce44SJohn Forte ASSERT(node_name != NULL); 2148fcf3ce44SJohn Forte ASSERT(node_alias != NULL); 2149fcf3ce44SJohn Forte 2150fcf3ce44SJohn Forte /* RFC 4171 section 6.1 - NULLs included in the length. */ 2151fcf3ce44SJohn Forte node_name_len = strlen((char *)node_name) + 1; 2152fcf3ce44SJohn Forte 2153fcf3ce44SJohn Forte if (node_name_len == 1) { 2154fcf3ce44SJohn Forte *out_pdu = NULL; 2155fcf3ce44SJohn Forte return (0); 2156fcf3ce44SJohn Forte } 2157fcf3ce44SJohn Forte 2158fcf3ce44SJohn Forte /* Create SCNReg Message */ 2159fcf3ce44SJohn Forte flags = ISNS_FLAG_FIRST_PDU | 2160fcf3ce44SJohn Forte ISNS_FLAG_LAST_PDU; 2161fcf3ce44SJohn Forte pdu_size = isns_create_pdu_header(ISNS_SCN_REG, flags, &pdu); 2162fcf3ce44SJohn Forte *xid_p = pdu->xid; 2163fcf3ce44SJohn Forte 2164fcf3ce44SJohn Forte /* Source attribute */ 2165fcf3ce44SJohn Forte if (isns_add_attr(pdu, pdu_size, ISNS_ISCSI_NAME_ATTR_ID, 2166fcf3ce44SJohn Forte node_name_len, node_name, 0) != 0) { 2167fcf3ce44SJohn Forte kmem_free(pdu, pdu_size); 2168fcf3ce44SJohn Forte *out_pdu = NULL; 2169fcf3ce44SJohn Forte return (0); 2170fcf3ce44SJohn Forte } 2171fcf3ce44SJohn Forte 2172fcf3ce44SJohn Forte /* Message attribute */ 2173fcf3ce44SJohn Forte if (isns_add_attr(pdu, pdu_size, ISNS_ISCSI_NAME_ATTR_ID, 2174fcf3ce44SJohn Forte node_name_len, node_name, 0) != 0) { 2175fcf3ce44SJohn Forte kmem_free(pdu, pdu_size); 2176fcf3ce44SJohn Forte *out_pdu = NULL; 2177fcf3ce44SJohn Forte return (0); 2178fcf3ce44SJohn Forte } 2179fcf3ce44SJohn Forte 2180fcf3ce44SJohn Forte /* Delimiter */ 2181fcf3ce44SJohn Forte if (isns_add_attr(pdu, pdu_size, ISNS_DELIMITER_ATTR_ID, 0, 0, 0) 2182fcf3ce44SJohn Forte != 0) { 2183fcf3ce44SJohn Forte kmem_free(pdu, pdu_size); 2184fcf3ce44SJohn Forte *out_pdu = NULL; 2185fcf3ce44SJohn Forte return (0); 2186fcf3ce44SJohn Forte } 2187fcf3ce44SJohn Forte 2188fcf3ce44SJohn Forte /* Operating attribute */ 2189fcf3ce44SJohn Forte if (isns_add_attr(pdu, pdu_size, ISNS_ISCSI_SCN_BITMAP_ATTR_ID, 2190fcf3ce44SJohn Forte 4, 2191fcf3ce44SJohn Forte 0, 2192fcf3ce44SJohn Forte /* 2193fcf3ce44SJohn Forte * Microsoft seems to not differentiate between init and 2194fcf3ce44SJohn Forte * target. Hence, it makes no difference to turn on/off 2195fcf3ce44SJohn Forte * the initiator/target bit. 2196fcf3ce44SJohn Forte */ 2197fcf3ce44SJohn Forte ISNS_TARGET_SELF_INFO_ONLY | 2198fcf3ce44SJohn Forte ISNS_OBJ_REMOVED | 2199fcf3ce44SJohn Forte ISNS_OBJ_ADDED | 2200fcf3ce44SJohn Forte ISNS_OBJ_UPDATED) != 0) { 2201fcf3ce44SJohn Forte kmem_free(pdu, pdu_size); 2202fcf3ce44SJohn Forte *out_pdu = NULL; 2203fcf3ce44SJohn Forte return (0); 2204fcf3ce44SJohn Forte } 2205fcf3ce44SJohn Forte 2206fcf3ce44SJohn Forte *out_pdu = pdu; 2207fcf3ce44SJohn Forte return (pdu_size); 2208fcf3ce44SJohn Forte } 2209fcf3ce44SJohn Forte 2210fcf3ce44SJohn Forte static 2211fcf3ce44SJohn Forte size_t 2212fcf3ce44SJohn Forte isns_create_scn_dereg_pdu( 2213fcf3ce44SJohn Forte uint8_t *node_name, 2214fcf3ce44SJohn Forte uint16_t *xid_p, 2215fcf3ce44SJohn Forte isns_pdu_t **out_pdu) 2216fcf3ce44SJohn Forte { 2217fcf3ce44SJohn Forte isns_pdu_t *pdu; 2218fcf3ce44SJohn Forte size_t pdu_size, node_name_len; 2219fcf3ce44SJohn Forte uint16_t flags; 2220fcf3ce44SJohn Forte 2221fcf3ce44SJohn Forte ASSERT(node_name != NULL); 2222fcf3ce44SJohn Forte 2223fcf3ce44SJohn Forte /* RFC 4171 section 6.1 - NULLs included in the length. */ 2224fcf3ce44SJohn Forte node_name_len = strlen((char *)node_name) + 1; 2225fcf3ce44SJohn Forte 2226fcf3ce44SJohn Forte if (node_name_len == 1) { 2227fcf3ce44SJohn Forte *out_pdu = NULL; 2228fcf3ce44SJohn Forte return (0); 2229fcf3ce44SJohn Forte } 2230fcf3ce44SJohn Forte 2231fcf3ce44SJohn Forte /* Create SCNReg Message */ 2232fcf3ce44SJohn Forte flags = ISNS_FLAG_FIRST_PDU | 2233fcf3ce44SJohn Forte ISNS_FLAG_LAST_PDU; 2234fcf3ce44SJohn Forte pdu_size = isns_create_pdu_header(ISNS_SCN_DEREG, flags, &pdu); 2235fcf3ce44SJohn Forte *xid_p = pdu->xid; 2236fcf3ce44SJohn Forte 2237fcf3ce44SJohn Forte /* Source attribute */ 2238fcf3ce44SJohn Forte if (isns_add_attr(pdu, pdu_size, ISNS_ISCSI_NAME_ATTR_ID, 2239fcf3ce44SJohn Forte node_name_len, node_name, 0) != 0) { 2240fcf3ce44SJohn Forte kmem_free(pdu, pdu_size); 2241fcf3ce44SJohn Forte *out_pdu = NULL; 2242fcf3ce44SJohn Forte return (0); 2243fcf3ce44SJohn Forte } 2244fcf3ce44SJohn Forte 2245fcf3ce44SJohn Forte /* Message attribute */ 2246fcf3ce44SJohn Forte if (isns_add_attr(pdu, pdu_size, ISNS_ISCSI_NAME_ATTR_ID, 2247fcf3ce44SJohn Forte node_name_len, node_name, 0) != 0) { 2248fcf3ce44SJohn Forte kmem_free(pdu, pdu_size); 2249fcf3ce44SJohn Forte *out_pdu = NULL; 2250fcf3ce44SJohn Forte return (0); 2251fcf3ce44SJohn Forte } 2252fcf3ce44SJohn Forte 2253fcf3ce44SJohn Forte /* Delimiter */ 2254fcf3ce44SJohn Forte if (isns_add_attr(pdu, pdu_size, ISNS_DELIMITER_ATTR_ID, 0, 0, 0) 2255fcf3ce44SJohn Forte != 0) { 2256fcf3ce44SJohn Forte kmem_free(pdu, pdu_size); 2257fcf3ce44SJohn Forte *out_pdu = NULL; 2258fcf3ce44SJohn Forte return (0); 2259fcf3ce44SJohn Forte } 2260fcf3ce44SJohn Forte 2261fcf3ce44SJohn Forte /* No operating attribute */ 2262fcf3ce44SJohn Forte 2263fcf3ce44SJohn Forte *out_pdu = pdu; 2264fcf3ce44SJohn Forte return (pdu_size); 2265fcf3ce44SJohn Forte } 2266fcf3ce44SJohn Forte 2267fcf3ce44SJohn Forte static 2268fcf3ce44SJohn Forte size_t 2269fcf3ce44SJohn Forte isns_create_esi_rsp_pdu(uint32_t rsp_status_code, 2270fcf3ce44SJohn Forte isns_pdu_t *esi_pdu, 2271fcf3ce44SJohn Forte uint16_t *xid_p, 2272fcf3ce44SJohn Forte isns_pdu_t **out_pdu) 2273fcf3ce44SJohn Forte { 2274fcf3ce44SJohn Forte isns_pdu_t *pdu_p; 2275fcf3ce44SJohn Forte uint16_t flags; 2276fcf3ce44SJohn Forte uint8_t *payload_ptr; 2277fcf3ce44SJohn Forte uint32_t swapped_status_code = htonl(rsp_status_code); 2278fcf3ce44SJohn Forte size_t pdu_size, payload_len = 0; 2279fcf3ce44SJohn Forte 2280fcf3ce44SJohn Forte /* Create ESIRsp Message */ 2281fcf3ce44SJohn Forte flags = ISNS_FLAG_FIRST_PDU | 2282fcf3ce44SJohn Forte ISNS_FLAG_LAST_PDU; 2283fcf3ce44SJohn Forte pdu_size = isns_create_pdu_header(ISNS_ESI_RSP, flags, &pdu_p); 2284fcf3ce44SJohn Forte *xid_p = pdu_p->xid; 2285fcf3ce44SJohn Forte 2286fcf3ce44SJohn Forte payload_len = ntohs(pdu_p->payload_len); 2287fcf3ce44SJohn Forte 2288fcf3ce44SJohn Forte /* Status Code */ 2289fcf3ce44SJohn Forte payload_ptr = pdu_p->payload + payload_len; 2290fcf3ce44SJohn Forte bcopy(&swapped_status_code, payload_ptr, 4); 2291fcf3ce44SJohn Forte payload_len += 4; 2292fcf3ce44SJohn Forte 2293fcf3ce44SJohn Forte payload_ptr = pdu_p->payload + payload_len; 2294fcf3ce44SJohn Forte if ((esi_pdu->payload_len) < ISNSP_MAX_PAYLOAD_SIZE) { 2295fcf3ce44SJohn Forte bcopy(esi_pdu->payload, payload_ptr, 2296fcf3ce44SJohn Forte (esi_pdu->payload_len)); 2297fcf3ce44SJohn Forte payload_len += (esi_pdu->payload_len); 2298fcf3ce44SJohn Forte } else { 2299fcf3ce44SJohn Forte bcopy(esi_pdu->payload, payload_ptr, ISNSP_MAX_PAYLOAD_SIZE); 2300fcf3ce44SJohn Forte payload_len += ISNSP_MAX_PAYLOAD_SIZE; 2301fcf3ce44SJohn Forte } 2302fcf3ce44SJohn Forte pdu_p->payload_len = htons(payload_len); 2303fcf3ce44SJohn Forte 2304fcf3ce44SJohn Forte /* Delimiter */ 2305fcf3ce44SJohn Forte if (isns_add_attr(pdu_p, pdu_size, ISNS_DELIMITER_ATTR_ID, 0, 0, 0) 2306fcf3ce44SJohn Forte != 0) { 2307fcf3ce44SJohn Forte kmem_free(pdu_p, pdu_size); 2308fcf3ce44SJohn Forte *out_pdu = NULL; 2309fcf3ce44SJohn Forte return (0); 2310fcf3ce44SJohn Forte } 2311fcf3ce44SJohn Forte 2312fcf3ce44SJohn Forte *out_pdu = pdu_p; 2313fcf3ce44SJohn Forte return (pdu_size); 2314fcf3ce44SJohn Forte } 2315fcf3ce44SJohn Forte 2316fcf3ce44SJohn Forte static 2317fcf3ce44SJohn Forte size_t 2318fcf3ce44SJohn Forte isns_create_scn_rsp_pdu(uint32_t rsp_status_code, 2319fcf3ce44SJohn Forte isns_pdu_t *scn_pdu, 2320fcf3ce44SJohn Forte uint16_t *xid_p, 2321fcf3ce44SJohn Forte isns_pdu_t **out_pdu) 2322fcf3ce44SJohn Forte { 2323fcf3ce44SJohn Forte isns_pdu_t *pdu_p; 2324fcf3ce44SJohn Forte uint16_t flags; 2325fcf3ce44SJohn Forte uint8_t *payload_ptr; 2326fcf3ce44SJohn Forte uint32_t swapped_status_code = htonl(rsp_status_code); 2327fcf3ce44SJohn Forte size_t pdu_size, payload_len = 0; 2328fcf3ce44SJohn Forte 2329fcf3ce44SJohn Forte /* Create SCNRsp Message */ 2330fcf3ce44SJohn Forte flags = ISNS_FLAG_FIRST_PDU | 2331fcf3ce44SJohn Forte ISNS_FLAG_LAST_PDU; 2332fcf3ce44SJohn Forte pdu_size = isns_create_pdu_header(ISNS_SCN_RSP, flags, &pdu_p); 2333fcf3ce44SJohn Forte *xid_p = pdu_p->xid; 2334fcf3ce44SJohn Forte 2335fcf3ce44SJohn Forte payload_len = ntohs(pdu_p->payload_len); 2336fcf3ce44SJohn Forte 2337fcf3ce44SJohn Forte /* Status Code */ 2338fcf3ce44SJohn Forte payload_ptr = pdu_p->payload + payload_len; 2339fcf3ce44SJohn Forte bcopy(&swapped_status_code, payload_ptr, 4); 2340fcf3ce44SJohn Forte payload_len += 4; 2341fcf3ce44SJohn Forte 2342fcf3ce44SJohn Forte payload_ptr = pdu_p->payload + payload_len; 2343fcf3ce44SJohn Forte if ((scn_pdu->payload_len) < ISNSP_MAX_PAYLOAD_SIZE) { 2344fcf3ce44SJohn Forte bcopy(scn_pdu->payload, payload_ptr, 2345fcf3ce44SJohn Forte (scn_pdu->payload_len)); 2346fcf3ce44SJohn Forte payload_len += (scn_pdu->payload_len); 2347fcf3ce44SJohn Forte } else { 2348fcf3ce44SJohn Forte bcopy(scn_pdu->payload, payload_ptr, ISNSP_MAX_PAYLOAD_SIZE); 2349fcf3ce44SJohn Forte payload_len += ISNSP_MAX_PAYLOAD_SIZE; 2350fcf3ce44SJohn Forte } 2351fcf3ce44SJohn Forte pdu_p->payload_len = htons(payload_len); 2352fcf3ce44SJohn Forte 2353fcf3ce44SJohn Forte /* Delimiter */ 2354fcf3ce44SJohn Forte if (isns_add_attr(pdu_p, pdu_size, ISNS_DELIMITER_ATTR_ID, 0, 0, 0) 2355fcf3ce44SJohn Forte != 0) { 2356fcf3ce44SJohn Forte kmem_free(pdu_p, pdu_size); 2357fcf3ce44SJohn Forte *out_pdu = NULL; 2358fcf3ce44SJohn Forte return (0); 2359fcf3ce44SJohn Forte } 2360fcf3ce44SJohn Forte 2361fcf3ce44SJohn Forte *out_pdu = pdu_p; 2362fcf3ce44SJohn Forte return (pdu_size); 2363fcf3ce44SJohn Forte } 2364fcf3ce44SJohn Forte 2365fcf3ce44SJohn Forte static 2366fcf3ce44SJohn Forte uint32_t 2367fcf3ce44SJohn Forte isns_process_dev_attr_reg_rsp(isns_pdu_t *resp_pdu_p) 2368fcf3ce44SJohn Forte { 2369fcf3ce44SJohn Forte isns_resp_t *resp_p; 2370fcf3ce44SJohn Forte 2371fcf3ce44SJohn Forte if (resp_pdu_p->func_id != ISNS_DEV_ATTR_REG_RSP) { 2372fcf3ce44SJohn Forte /* If this happens the iSNS server may have a problem. */ 2373fcf3ce44SJohn Forte return (ISNS_RSP_MSG_FORMAT_ERROR); 2374fcf3ce44SJohn Forte } 2375fcf3ce44SJohn Forte 2376fcf3ce44SJohn Forte /* Check response's status code */ 2377fcf3ce44SJohn Forte resp_p = (isns_resp_t *)resp_pdu_p->payload; 2378fcf3ce44SJohn Forte if (ntohl(resp_p->status) != ISNS_RSP_SUCCESSFUL) { 2379fcf3ce44SJohn Forte return (ntohl(resp_p->status)); 2380fcf3ce44SJohn Forte } 2381fcf3ce44SJohn Forte 2382fcf3ce44SJohn Forte return (ISNS_RSP_SUCCESSFUL); 2383fcf3ce44SJohn Forte } 2384fcf3ce44SJohn Forte 2385fcf3ce44SJohn Forte static 2386fcf3ce44SJohn Forte uint32_t 2387fcf3ce44SJohn Forte isns_process_dev_attr_dereg_rsp(isns_pdu_t *resp_pdu_p) 2388fcf3ce44SJohn Forte { 2389fcf3ce44SJohn Forte isns_resp_t *resp_p; 2390fcf3ce44SJohn Forte 2391fcf3ce44SJohn Forte if (resp_pdu_p->func_id != ISNS_DEV_DEREG_RSP) { 2392fcf3ce44SJohn Forte /* If this happens the iSNS server may have a problem. */ 2393fcf3ce44SJohn Forte return (ISNS_RSP_MSG_FORMAT_ERROR); 2394fcf3ce44SJohn Forte } 2395fcf3ce44SJohn Forte 2396fcf3ce44SJohn Forte /* Check response's status code */ 2397fcf3ce44SJohn Forte resp_p = (isns_resp_t *)resp_pdu_p->payload; 2398fcf3ce44SJohn Forte if (ntohl(resp_p->status) != ISNS_RSP_SUCCESSFUL) { 2399fcf3ce44SJohn Forte return (ntohl(resp_p->status)); 2400fcf3ce44SJohn Forte } 2401fcf3ce44SJohn Forte 2402fcf3ce44SJohn Forte return (ISNS_RSP_SUCCESSFUL); 2403fcf3ce44SJohn Forte } 2404fcf3ce44SJohn Forte 2405fcf3ce44SJohn Forte static 2406fcf3ce44SJohn Forte uint32_t 2407fcf3ce44SJohn Forte isns_process_scn_reg_rsp(isns_pdu_t *resp_pdu_p) 2408fcf3ce44SJohn Forte { 2409fcf3ce44SJohn Forte isns_resp_t *resp_p; 2410fcf3ce44SJohn Forte 2411fcf3ce44SJohn Forte ASSERT(resp_pdu_p != NULL); 2412fcf3ce44SJohn Forte if (resp_pdu_p->func_id != ISNS_SCN_REG_RSP) { 2413fcf3ce44SJohn Forte /* If this happens the iSNS server may have a problem. */ 2414fcf3ce44SJohn Forte return (ISNS_RSP_MSG_FORMAT_ERROR); 2415fcf3ce44SJohn Forte } 2416fcf3ce44SJohn Forte 2417fcf3ce44SJohn Forte /* Check response's status code */ 2418fcf3ce44SJohn Forte resp_p = (isns_resp_t *)resp_pdu_p->payload; 2419fcf3ce44SJohn Forte if (ntohl(resp_p->status) != ISNS_RSP_SUCCESSFUL) { 2420fcf3ce44SJohn Forte return (ntohl(resp_p->status)); 2421fcf3ce44SJohn Forte } 2422fcf3ce44SJohn Forte return (ISNS_RSP_SUCCESSFUL); 2423fcf3ce44SJohn Forte } 2424fcf3ce44SJohn Forte 2425fcf3ce44SJohn Forte static 2426fcf3ce44SJohn Forte uint32_t 2427fcf3ce44SJohn Forte isns_process_scn_dereg_rsp(isns_pdu_t *resp_pdu_p) 2428fcf3ce44SJohn Forte { 2429fcf3ce44SJohn Forte isns_resp_t *resp_p; 2430fcf3ce44SJohn Forte 2431fcf3ce44SJohn Forte ASSERT(resp_pdu_p != NULL); 2432fcf3ce44SJohn Forte if (resp_pdu_p->func_id != ISNS_SCN_DEREG_RSP) { 2433fcf3ce44SJohn Forte /* If this happens the iSNS server may have a problem. */ 2434fcf3ce44SJohn Forte return (ISNS_RSP_MSG_FORMAT_ERROR); 2435fcf3ce44SJohn Forte } 2436fcf3ce44SJohn Forte 2437fcf3ce44SJohn Forte /* Check response's status code */ 2438fcf3ce44SJohn Forte resp_p = (isns_resp_t *)resp_pdu_p->payload; 2439fcf3ce44SJohn Forte if (ntohl(resp_p->status) != ISNS_RSP_SUCCESSFUL) { 2440fcf3ce44SJohn Forte return (ntohl(resp_p->status)); 2441fcf3ce44SJohn Forte } 2442fcf3ce44SJohn Forte return (ISNS_RSP_SUCCESSFUL); 2443fcf3ce44SJohn Forte } 2444fcf3ce44SJohn Forte 2445fcf3ce44SJohn Forte static 2446fcf3ce44SJohn Forte uint32_t 2447fcf3ce44SJohn Forte isns_process_dev_attr_qry_target_nodes_pdu( 2448fcf3ce44SJohn Forte iscsi_addr_t *isns_server_addr, uint16_t payload_funcId, 2449fcf3ce44SJohn Forte isns_resp_t *resp_p, size_t resp_len, 2450fcf3ce44SJohn Forte isns_portal_group_list_t **pg_list) 2451fcf3ce44SJohn Forte { 2452fcf3ce44SJohn Forte boolean_t done_b, found_delimiter_b, target_node_type_b; 2453fcf3ce44SJohn Forte int num_of_pgs = 0, pg_sz, idx; 2454fcf3ce44SJohn Forte isns_tlv_t *attr_tlv_p; 2455fcf3ce44SJohn Forte uint8_t *data_p; 2456fcf3ce44SJohn Forte uint32_t len, total_payload_len = 0; 2457fcf3ce44SJohn Forte isns_portal_group_t *pg; 2458fcf3ce44SJohn Forte uint8_t junk[IPV4_RSVD_BYTES]; 2459fcf3ce44SJohn Forte 2460fcf3ce44SJohn Forte *pg_list = NULL; 2461fcf3ce44SJohn Forte bzero(junk, IPV4_RSVD_BYTES); 2462fcf3ce44SJohn Forte 2463fcf3ce44SJohn Forte if (payload_funcId != ISNS_DEV_ATTR_QRY_RSP) { 2464fcf3ce44SJohn Forte /* If this happens the iSNS server may have a problem. */ 2465fcf3ce44SJohn Forte return (ISNS_RSP_MSG_FORMAT_ERROR); 2466fcf3ce44SJohn Forte } 2467fcf3ce44SJohn Forte 2468fcf3ce44SJohn Forte if (ntohl(resp_p->status) != ISNS_RSP_SUCCESSFUL) { 2469fcf3ce44SJohn Forte return (ntohl(resp_p->status)); 2470fcf3ce44SJohn Forte } 2471fcf3ce44SJohn Forte 2472fcf3ce44SJohn Forte /* 2473fcf3ce44SJohn Forte * If payload is smaller than the length of even 1 attribute 2474fcf3ce44SJohn Forte * there is something wrong with the PDU. 2475fcf3ce44SJohn Forte */ 2476fcf3ce44SJohn Forte if (resp_len < (ISNS_TLV_ATTR_ID_LEN + 2477fcf3ce44SJohn Forte ISNS_TLV_ATTR_LEN_LEN)) { 2478fcf3ce44SJohn Forte return (ISNS_RSP_MSG_FORMAT_ERROR); 2479fcf3ce44SJohn Forte } 2480fcf3ce44SJohn Forte 2481fcf3ce44SJohn Forte /* 2482fcf3ce44SJohn Forte * Expected DevAttrQryRsp message format: 2483fcf3ce44SJohn Forte * 2484fcf3ce44SJohn Forte * Status Code 2485fcf3ce44SJohn Forte * iSCSI Node Type 2486fcf3ce44SJohn Forte * Delimiter 2487fcf3ce44SJohn Forte * PG iSCSI Name [Optional] 2488fcf3ce44SJohn Forte * PG Portal IP Address [Optional] 2489fcf3ce44SJohn Forte * PG Portal Port [Optional] 2490fcf3ce44SJohn Forte * PG Tag [Optional] 2491fcf3ce44SJohn Forte * PG iSCSI Name [Optional] 2492fcf3ce44SJohn Forte * PG Portal IP Address [Optional] 2493fcf3ce44SJohn Forte * PG Portal Port [Optional] 2494fcf3ce44SJohn Forte * PG Tag [Optional] 2495fcf3ce44SJohn Forte * . 2496fcf3ce44SJohn Forte * . 2497fcf3ce44SJohn Forte * . 2498fcf3ce44SJohn Forte */ 2499fcf3ce44SJohn Forte data_p = resp_p->data; 2500fcf3ce44SJohn Forte done_b = B_FALSE; 2501fcf3ce44SJohn Forte found_delimiter_b = B_FALSE; 2502fcf3ce44SJohn Forte num_of_pgs = 0; 2503fcf3ce44SJohn Forte total_payload_len = sizeof (resp_p->status); 2504fcf3ce44SJohn Forte /* Find out the number of entries retrieved */ 2505fcf3ce44SJohn Forte while (!done_b) { 2506fcf3ce44SJohn Forte attr_tlv_p = (isns_tlv_t *)data_p; 2507fcf3ce44SJohn Forte if (ntohl(attr_tlv_p->attr_id) == ISNS_DELIMITER_ATTR_ID) { 2508fcf3ce44SJohn Forte if (found_delimiter_b) { 2509fcf3ce44SJohn Forte done_b = B_TRUE; 2510fcf3ce44SJohn Forte } else { 2511fcf3ce44SJohn Forte found_delimiter_b = B_TRUE; 2512fcf3ce44SJohn Forte } 2513fcf3ce44SJohn Forte } else if (ntohl(attr_tlv_p->attr_id) == 2514fcf3ce44SJohn Forte ISNS_PG_TAG_ATTR_ID) { 2515fcf3ce44SJohn Forte num_of_pgs++; 2516fcf3ce44SJohn Forte } 2517fcf3ce44SJohn Forte len = ntohl(attr_tlv_p->attr_len); 2518fcf3ce44SJohn Forte 2519fcf3ce44SJohn Forte total_payload_len += (ISNS_TLV_ATTR_ID_LEN + 2520fcf3ce44SJohn Forte ISNS_TLV_ATTR_LEN_LEN + len); 2521fcf3ce44SJohn Forte if (total_payload_len >= resp_len) { 2522fcf3ce44SJohn Forte done_b = B_TRUE; 2523fcf3ce44SJohn Forte } else { 2524fcf3ce44SJohn Forte data_p += (ISNS_TLV_ATTR_ID_LEN + 2525fcf3ce44SJohn Forte ISNS_TLV_ATTR_LEN_LEN + len); 2526fcf3ce44SJohn Forte } 2527fcf3ce44SJohn Forte } 2528fcf3ce44SJohn Forte 2529fcf3ce44SJohn Forte pg_sz = sizeof (isns_portal_group_list_t); 2530fcf3ce44SJohn Forte if (num_of_pgs > 0) { 2531fcf3ce44SJohn Forte pg_sz += (num_of_pgs - 1) * sizeof (isns_portal_group_t); 2532fcf3ce44SJohn Forte } 2533fcf3ce44SJohn Forte DTRACE_PROBE1(isns_process_dev_attr_qry_target_nodes_pdu_pg_size, 2534fcf3ce44SJohn Forte int, pg_sz); 2535fcf3ce44SJohn Forte /* 2536fcf3ce44SJohn Forte * Once we passed this point, if for any reason we need to return 2537fcf3ce44SJohn Forte * because of a failure, we need to free the memory allocated for 2538fcf3ce44SJohn Forte * the pg_list and nullify it. 2539fcf3ce44SJohn Forte */ 2540fcf3ce44SJohn Forte *pg_list = (isns_portal_group_list_t *)kmem_zalloc(pg_sz, KM_SLEEP); 2541fcf3ce44SJohn Forte (*pg_list)->pg_out_cnt = 0; 2542fcf3ce44SJohn Forte 2543fcf3ce44SJohn Forte /* Assign the isns_server information to all portal groups */ 2544fcf3ce44SJohn Forte for (idx = 0; idx < num_of_pgs; idx++) { 2545fcf3ce44SJohn Forte pg = &((*pg_list)->pg_list[idx]); 2546fcf3ce44SJohn Forte bcopy(&isns_server_addr->a_addr, &pg->isns_server_ip, 2547fcf3ce44SJohn Forte sizeof (iscsi_ipaddr_t)); 2548fcf3ce44SJohn Forte pg->isns_server_port = isns_server_addr->a_port; 2549fcf3ce44SJohn Forte } 2550fcf3ce44SJohn Forte 2551fcf3ce44SJohn Forte data_p = resp_p->data; 2552fcf3ce44SJohn Forte done_b = B_FALSE; 2553fcf3ce44SJohn Forte found_delimiter_b = B_FALSE; 2554fcf3ce44SJohn Forte total_payload_len = sizeof (resp_p->status); 2555fcf3ce44SJohn Forte while (!done_b) { 2556fcf3ce44SJohn Forte attr_tlv_p = (isns_tlv_t *)data_p; 2557fcf3ce44SJohn Forte pg = &((*pg_list)->pg_list[(*pg_list)->pg_out_cnt]); 2558fcf3ce44SJohn Forte switch (ntohl(attr_tlv_p->attr_id)) { 2559fcf3ce44SJohn Forte case ISNS_DELIMITER_ATTR_ID: 2560fcf3ce44SJohn Forte if (found_delimiter_b) { 2561fcf3ce44SJohn Forte done_b = B_TRUE; 2562fcf3ce44SJohn Forte } else { 2563fcf3ce44SJohn Forte found_delimiter_b = B_TRUE; 2564fcf3ce44SJohn Forte } 2565fcf3ce44SJohn Forte break; 2566fcf3ce44SJohn Forte 2567fcf3ce44SJohn Forte case ISNS_PG_ISCSI_NAME_ATTR_ID: 2568fcf3ce44SJohn Forte target_node_type_b = B_TRUE; 2569fcf3ce44SJohn Forte bcopy(attr_tlv_p->attr_value, 2570fcf3ce44SJohn Forte (char *)pg->pg_iscsi_name, 2571fcf3ce44SJohn Forte ntohl(attr_tlv_p->attr_len) < 2572fcf3ce44SJohn Forte ISCSI_MAX_NAME_LEN ? 2573fcf3ce44SJohn Forte ntohl(attr_tlv_p->attr_len) : 2574fcf3ce44SJohn Forte ISCSI_MAX_NAME_LEN); 2575fcf3ce44SJohn Forte 2576fcf3ce44SJohn Forte DTRACE_PROBE1(isns_dev_attr_qry_process1, 2577fcf3ce44SJohn Forte char *, (char *)pg->pg_iscsi_name); 2578fcf3ce44SJohn Forte break; 2579fcf3ce44SJohn Forte 2580fcf3ce44SJohn Forte case ISNS_PG_PORTAL_IP_ADDR_ATTR_ID: 2581fcf3ce44SJohn Forte if (target_node_type_b) { 2582fcf3ce44SJohn Forte /* 2583fcf3ce44SJohn Forte * Section 6.3.1 - The Portal IP Address 2584fcf3ce44SJohn Forte * is a 16-byte field that may contain 2585fcf3ce44SJohn Forte * an IPv4 or IPv6 address. When this 2586fcf3ce44SJohn Forte * field contains an IPv4 address, it 2587fcf3ce44SJohn Forte * is stored as an IPv4-mapped IPv6 2588fcf3ce44SJohn Forte * address 2589fcf3ce44SJohn Forte */ 2590fcf3ce44SJohn Forte if (ntohl(attr_tlv_p->attr_len) != 16) { 2591fcf3ce44SJohn Forte #define STRING_AALR "address attribute length received " 2592fcf3ce44SJohn Forte #define STRING_FISE16 "from iSNS server, Expected = 16, " 2593fcf3ce44SJohn Forte cmn_err(CE_NOTE, "Wrong IP " 2594fcf3ce44SJohn Forte STRING_AALR 2595fcf3ce44SJohn Forte STRING_FISE16 2596fcf3ce44SJohn Forte "Received = %d", 2597fcf3ce44SJohn Forte ntohl( 2598fcf3ce44SJohn Forte attr_tlv_p->attr_len)); 2599fcf3ce44SJohn Forte return ( 2600fcf3ce44SJohn Forte ISNS_RSP_MSG_FORMAT_ERROR); 2601fcf3ce44SJohn Forte #undef STRING_AALR 2602fcf3ce44SJohn Forte #undef STRING_FISE16 2603fcf3ce44SJohn Forte } 2604fcf3ce44SJohn Forte 2605fcf3ce44SJohn Forte /* 2606fcf3ce44SJohn Forte * Section 6.3.1 and RFC 2373 state 2607fcf3ce44SJohn Forte * that an IPv4 address will be denoted 2608fcf3ce44SJohn Forte * by the 10 top bytes as all zero 2609fcf3ce44SJohn Forte * followed by either 2 bytes of 2610fcf3ce44SJohn Forte * 0x0000 or 0xFFFF The 0x0000 states 2611fcf3ce44SJohn Forte * that the address is is IPv6 capable 2612fcf3ce44SJohn Forte * and 0xFFFF states its not capable. 2613fcf3ce44SJohn Forte */ 2614fcf3ce44SJohn Forte if ((bcmp(attr_tlv_p->attr_value, junk, 2615fcf3ce44SJohn Forte IPV4_RSVD_BYTES) == 0) && 2616fcf3ce44SJohn Forte (((attr_tlv_p->attr_value[10] == 2617fcf3ce44SJohn Forte 0x00) && 2618fcf3ce44SJohn Forte (attr_tlv_p->attr_value[11] == 2619fcf3ce44SJohn Forte 0x00)) || 2620fcf3ce44SJohn Forte ((attr_tlv_p->attr_value[10] == 2621fcf3ce44SJohn Forte 0xFF) && 2622fcf3ce44SJohn Forte (attr_tlv_p->attr_value[11] == 2623fcf3ce44SJohn Forte 0xFF)))) { 2624fcf3ce44SJohn Forte 2625fcf3ce44SJohn Forte /* IPv4 */ 2626fcf3ce44SJohn Forte bcopy(attr_tlv_p->attr_value + 2627fcf3ce44SJohn Forte 12, &pg->pg_ip_addr.u_ip4, 2628fcf3ce44SJohn Forte sizeof (struct in_addr)); 2629fcf3ce44SJohn Forte pg->insize = 2630fcf3ce44SJohn Forte sizeof (struct in_addr); 2631fcf3ce44SJohn Forte } else { 2632fcf3ce44SJohn Forte /* IPv6 */ 2633fcf3ce44SJohn Forte bcopy(attr_tlv_p->attr_value, 2634fcf3ce44SJohn Forte &pg->pg_ip_addr.u_ip6, 2635fcf3ce44SJohn Forte sizeof (struct in6_addr)); 2636fcf3ce44SJohn Forte pg->insize = 2637fcf3ce44SJohn Forte sizeof (struct in6_addr); 2638fcf3ce44SJohn Forte } 2639fcf3ce44SJohn Forte } 2640fcf3ce44SJohn Forte break; 2641fcf3ce44SJohn Forte 2642fcf3ce44SJohn Forte case ISNS_PG_PORTAL_PORT_ATTR_ID: 2643fcf3ce44SJohn Forte if (target_node_type_b) { 2644fcf3ce44SJohn Forte pg->pg_port = 2645fcf3ce44SJohn Forte ntohl(*(uint32_t *) 2646fcf3ce44SJohn Forte (*attr_tlv_p). 2647fcf3ce44SJohn Forte attr_value); 2648fcf3ce44SJohn Forte } 2649fcf3ce44SJohn Forte 2650fcf3ce44SJohn Forte break; 2651fcf3ce44SJohn Forte 2652fcf3ce44SJohn Forte case ISNS_PG_TAG_ATTR_ID: 2653fcf3ce44SJohn Forte if (target_node_type_b) { 2654fcf3ce44SJohn Forte pg->pg_tag = 2655fcf3ce44SJohn Forte ntohl(*(uint32_t *) 2656fcf3ce44SJohn Forte (*attr_tlv_p). 2657fcf3ce44SJohn Forte attr_value); 2658fcf3ce44SJohn Forte } 2659fcf3ce44SJohn Forte (*pg_list)->pg_out_cnt++; 2660fcf3ce44SJohn Forte target_node_type_b = B_FALSE; 2661fcf3ce44SJohn Forte break; 2662fcf3ce44SJohn Forte 2663fcf3ce44SJohn Forte default: 2664fcf3ce44SJohn Forte break; 2665fcf3ce44SJohn Forte } 2666fcf3ce44SJohn Forte 2667fcf3ce44SJohn Forte len = ntohl(attr_tlv_p->attr_len); 2668fcf3ce44SJohn Forte total_payload_len += (ISNS_TLV_ATTR_ID_LEN + 2669fcf3ce44SJohn Forte ISNS_TLV_ATTR_LEN_LEN + len); 2670fcf3ce44SJohn Forte if ((total_payload_len >= resp_len) || 2671fcf3ce44SJohn Forte ((*pg_list)->pg_out_cnt == num_of_pgs)) { 2672fcf3ce44SJohn Forte done_b = B_TRUE; 2673fcf3ce44SJohn Forte } else { 2674fcf3ce44SJohn Forte data_p += (ISNS_TLV_ATTR_ID_LEN + 2675fcf3ce44SJohn Forte ISNS_TLV_ATTR_LEN_LEN + len); 2676fcf3ce44SJohn Forte } 2677fcf3ce44SJohn Forte } 2678fcf3ce44SJohn Forte 2679fcf3ce44SJohn Forte return (ISNS_RSP_SUCCESSFUL); 2680fcf3ce44SJohn Forte } 2681fcf3ce44SJohn Forte 2682fcf3ce44SJohn Forte /* ARGSUSED */ 2683fcf3ce44SJohn Forte static 2684fcf3ce44SJohn Forte uint32_t 2685fcf3ce44SJohn Forte isns_process_esi(isns_pdu_t *esi_pdu_p) 2686fcf3ce44SJohn Forte { 2687fcf3ce44SJohn Forte /* There's nothing particular to process for ESI. */ 2688fcf3ce44SJohn Forte return (ISNS_RSP_SUCCESSFUL); 2689fcf3ce44SJohn Forte } 2690fcf3ce44SJohn Forte 2691fcf3ce44SJohn Forte static 2692fcf3ce44SJohn Forte uint32_t 2693fcf3ce44SJohn Forte isns_process_scn(isns_pdu_t *scn_pdu_p, uint8_t *lhba_handle) 2694fcf3ce44SJohn Forte { 2695fcf3ce44SJohn Forte boolean_t dest_attr_found_b; 2696fcf3ce44SJohn Forte boolean_t done_b; 2697fcf3ce44SJohn Forte boolean_t scn_type_found_b; 2698fcf3ce44SJohn Forte isns_scn_callback_arg_t *scn_args_p; 2699fcf3ce44SJohn Forte isns_tlv_t *attr_tlv_p; 2700fcf3ce44SJohn Forte uint8_t *data_p; 2701fcf3ce44SJohn Forte uint8_t *src_attr; 2702fcf3ce44SJohn Forte uint32_t attr_eff_len, normalized_attr_len; 2703fcf3ce44SJohn Forte uint32_t scn_type; 2704fcf3ce44SJohn Forte uint32_t total_payload_len; 2705fcf3ce44SJohn Forte void (*scn_callback_to_use)(void *); 2706fcf3ce44SJohn Forte 2707fcf3ce44SJohn Forte /* get the lhba_handle to use for the call back */ 2708fcf3ce44SJohn Forte scn_callback_to_use = scn_callback_lookup(lhba_handle); 2709fcf3ce44SJohn Forte if (scn_callback_to_use == NULL) { 2710fcf3ce44SJohn Forte return (ISNS_RSP_INTERNAL_ERROR); 2711fcf3ce44SJohn Forte } 2712fcf3ce44SJohn Forte 2713fcf3ce44SJohn Forte dest_attr_found_b = B_FALSE; 2714fcf3ce44SJohn Forte scn_type = 0; 2715fcf3ce44SJohn Forte scn_type_found_b = B_FALSE; 2716fcf3ce44SJohn Forte data_p = scn_pdu_p->payload; 2717fcf3ce44SJohn Forte done_b = B_FALSE; 2718fcf3ce44SJohn Forte total_payload_len = 0; 2719fcf3ce44SJohn Forte src_attr = (uint8_t *)kmem_zalloc(ISCSI_MAX_NAME_LEN, KM_SLEEP); 2720fcf3ce44SJohn Forte /* 2721fcf3ce44SJohn Forte * Section 5.6.5.8 states an SCN can have more than one 2722fcf3ce44SJohn Forte * source attribute. Process all attributes until we 2723fcf3ce44SJohn Forte * each process all the data or encounter the delimiter. 2724fcf3ce44SJohn Forte */ 2725fcf3ce44SJohn Forte while (!done_b) { 2726fcf3ce44SJohn Forte attr_tlv_p = (isns_tlv_t *)data_p; 2727fcf3ce44SJohn Forte 2728fcf3ce44SJohn Forte switch (ntohl(attr_tlv_p->attr_id)) { 2729fcf3ce44SJohn Forte /* ISNS_ISCSI_NAME_ATTR_ID - attribute name */ 2730fcf3ce44SJohn Forte case ISNS_ISCSI_NAME_ATTR_ID: 2731fcf3ce44SJohn Forte attr_eff_len = strlen( 2732fcf3ce44SJohn Forte (char *)attr_tlv_p->attr_value) + 1; 2733fcf3ce44SJohn Forte /* 2734fcf3ce44SJohn Forte * The attribute length must be 4-byte aligned. 2735fcf3ce44SJohn Forte * Section 5.1.3, RFC 4171. 2736fcf3ce44SJohn Forte */ 2737fcf3ce44SJohn Forte normalized_attr_len = (attr_eff_len % 4) == 0 ? 2738fcf3ce44SJohn Forte (attr_eff_len) : 2739fcf3ce44SJohn Forte (attr_eff_len + (4 - (attr_eff_len % 4))); 2740fcf3ce44SJohn Forte if (normalized_attr_len != 2741fcf3ce44SJohn Forte ntohl(attr_tlv_p->attr_len)) { 2742fcf3ce44SJohn Forte /* This SCN is bad. */ 2743fcf3ce44SJohn Forte kmem_free(src_attr, ISCSI_MAX_NAME_LEN); 2744fcf3ce44SJohn Forte return (ISNS_RSP_MSG_FORMAT_ERROR); 2745fcf3ce44SJohn Forte } 2746fcf3ce44SJohn Forte 2747fcf3ce44SJohn Forte /* Check if this was the Destination Attribute */ 2748fcf3ce44SJohn Forte if ((dest_attr_found_b == B_TRUE) && 2749fcf3ce44SJohn Forte (scn_type_found_b == B_TRUE)) { 2750fcf3ce44SJohn Forte bzero(src_attr, ISCSI_MAX_NAME_LEN); 2751fcf3ce44SJohn Forte bcopy(attr_tlv_p->attr_value, 2752fcf3ce44SJohn Forte (char *)src_attr, 2753fcf3ce44SJohn Forte ntohl(attr_tlv_p->attr_len) < 2754fcf3ce44SJohn Forte ISCSI_MAX_NAME_LEN ? 2755fcf3ce44SJohn Forte ntohl(attr_tlv_p->attr_len) : 2756fcf3ce44SJohn Forte ISCSI_MAX_NAME_LEN); 2757fcf3ce44SJohn Forte 2758fcf3ce44SJohn Forte /* allocate new callback structure */ 2759fcf3ce44SJohn Forte scn_args_p = 2760fcf3ce44SJohn Forte (isns_scn_callback_arg_t *)kmem_zalloc( 2761fcf3ce44SJohn Forte sizeof (isns_scn_callback_arg_t), 2762fcf3ce44SJohn Forte KM_SLEEP); 2763fcf3ce44SJohn Forte scn_args_p->scn_type = ntohl(scn_type); 2764fcf3ce44SJohn Forte bcopy(src_attr, scn_args_p->source_key_attr, 2765fcf3ce44SJohn Forte sizeof (scn_args_p->source_key_attr)); 2766fcf3ce44SJohn Forte 2767fcf3ce44SJohn Forte /* Dispatch the callback to process the SCN */ 2768fcf3ce44SJohn Forte mutex_enter(&scn_taskq_mutex); 2769fcf3ce44SJohn Forte if (scn_taskq != NULL) { 2770fcf3ce44SJohn Forte (void) ddi_taskq_dispatch(scn_taskq, 2771fcf3ce44SJohn Forte scn_callback_to_use, 2772fcf3ce44SJohn Forte scn_args_p, DDI_SLEEP); 2773fcf3ce44SJohn Forte } 2774fcf3ce44SJohn Forte mutex_exit(&scn_taskq_mutex); 2775fcf3ce44SJohn Forte } else { 2776fcf3ce44SJohn Forte /* Skip Destination Attribute */ 2777fcf3ce44SJohn Forte dest_attr_found_b = B_TRUE; 2778fcf3ce44SJohn Forte } 2779fcf3ce44SJohn Forte break; 2780fcf3ce44SJohn Forte 2781fcf3ce44SJohn Forte /* ISNS_ISCSI_SCN_BITMAP_ATTR_ID - change type */ 2782fcf3ce44SJohn Forte case ISNS_ISCSI_SCN_BITMAP_ATTR_ID: 2783fcf3ce44SJohn Forte /* 2784fcf3ce44SJohn Forte * Determine the type of action to take for this SCN. 2785fcf3ce44SJohn Forte */ 2786fcf3ce44SJohn Forte scn_type_found_b = B_TRUE; 2787fcf3ce44SJohn Forte bcopy(&(attr_tlv_p->attr_value), &scn_type, 4); 2788fcf3ce44SJohn Forte break; 2789fcf3ce44SJohn Forte 2790fcf3ce44SJohn Forte /* ISNS_DELIMITER_ATTR_ID - end of the payload of a message */ 2791fcf3ce44SJohn Forte case ISNS_DELIMITER_ATTR_ID: 2792fcf3ce44SJohn Forte done_b = B_TRUE; 2793fcf3ce44SJohn Forte break; 2794fcf3ce44SJohn Forte } 2795fcf3ce44SJohn Forte 2796fcf3ce44SJohn Forte if (done_b == B_FALSE) { 2797fcf3ce44SJohn Forte total_payload_len += ntohl(attr_tlv_p->attr_len) + 2798fcf3ce44SJohn Forte ISNS_TLV_ATTR_ID_LEN + ISNS_TLV_ATTR_LEN_LEN; 2799fcf3ce44SJohn Forte if ((total_payload_len >= scn_pdu_p->payload_len) || 2800fcf3ce44SJohn Forte (total_payload_len > ISNSP_MAX_PAYLOAD_SIZE)) { 2801fcf3ce44SJohn Forte /* No more Attributes to process */ 2802fcf3ce44SJohn Forte done_b = B_TRUE; 2803fcf3ce44SJohn Forte } else { 2804fcf3ce44SJohn Forte if (scn_pdu_p->payload_len - 2805fcf3ce44SJohn Forte total_payload_len <= 2806fcf3ce44SJohn Forte ISNS_TLV_ATTR_ID_LEN + 2807fcf3ce44SJohn Forte ISNS_TLV_ATTR_LEN_LEN) { 2808fcf3ce44SJohn Forte /* 2809fcf3ce44SJohn Forte * The rest of the data in the PDU 2810fcf3ce44SJohn Forte * is less than the size of a valid 2811fcf3ce44SJohn Forte * iSNS TLV. This next attribute 2812fcf3ce44SJohn Forte * probably spans across the PDU 2813fcf3ce44SJohn Forte * boundary. For now, do not 2814fcf3ce44SJohn Forte * process it further. 2815fcf3ce44SJohn Forte */ 2816fcf3ce44SJohn Forte done_b = B_TRUE; 2817fcf3ce44SJohn Forte } else { 2818fcf3ce44SJohn Forte /* Advance to the next Attribute */ 2819fcf3ce44SJohn Forte data_p += (ISNS_TLV_ATTR_ID_LEN + 2820fcf3ce44SJohn Forte ISNS_TLV_ATTR_LEN_LEN + 2821fcf3ce44SJohn Forte ntohl(attr_tlv_p->attr_len)); 2822fcf3ce44SJohn Forte } 2823fcf3ce44SJohn Forte } 2824fcf3ce44SJohn Forte } 2825fcf3ce44SJohn Forte } 2826fcf3ce44SJohn Forte 2827fcf3ce44SJohn Forte kmem_free(src_attr, ISCSI_MAX_NAME_LEN); 2828fcf3ce44SJohn Forte return (ISNS_RSP_SUCCESSFUL); 2829fcf3ce44SJohn Forte } 2830fcf3ce44SJohn Forte 2831fcf3ce44SJohn Forte static 2832fcf3ce44SJohn Forte size_t 2833fcf3ce44SJohn Forte isns_create_pdu_header(uint16_t func_id, uint16_t flags, isns_pdu_t **pdu) 2834fcf3ce44SJohn Forte { 2835fcf3ce44SJohn Forte /* 2836fcf3ce44SJohn Forte * It should be ok to assume ISNSP_MAX_PDU_SIZE is large enough 2837fcf3ce44SJohn Forte * since we are creating our own PDU which is fully under our control. 2838fcf3ce44SJohn Forte */ 2839fcf3ce44SJohn Forte size_t pdu_size = ISNSP_MAX_PDU_SIZE; 2840fcf3ce44SJohn Forte 2841fcf3ce44SJohn Forte *pdu = (isns_pdu_t *)kmem_zalloc(pdu_size, KM_SLEEP); 2842fcf3ce44SJohn Forte (void) memset((*pdu), 0, pdu_size); 2843fcf3ce44SJohn Forte (*pdu)->version = htons((uint16_t)ISNSP_VERSION); 2844fcf3ce44SJohn Forte (*pdu)->func_id = htons((uint16_t)func_id); 2845fcf3ce44SJohn Forte (*pdu)->payload_len = htons(0); 2846fcf3ce44SJohn Forte (*pdu)->flags = htons((uint16_t)(flags | ISNS_FLAG_CLIENT)); 2847fcf3ce44SJohn Forte (*pdu)->xid = htons(create_xid()); 2848fcf3ce44SJohn Forte (*pdu)->seq = htons(0); 2849fcf3ce44SJohn Forte 2850fcf3ce44SJohn Forte return (pdu_size); 2851fcf3ce44SJohn Forte } 2852fcf3ce44SJohn Forte 2853fcf3ce44SJohn Forte static 2854fcf3ce44SJohn Forte int 2855fcf3ce44SJohn Forte isns_add_attr(isns_pdu_t *pdu, 2856fcf3ce44SJohn Forte size_t max_pdu_size, 2857fcf3ce44SJohn Forte uint32_t attr_id, 2858fcf3ce44SJohn Forte uint32_t attr_len, 2859fcf3ce44SJohn Forte void *attr_data, 2860fcf3ce44SJohn Forte uint32_t attr_numeric_data) 2861fcf3ce44SJohn Forte { 2862fcf3ce44SJohn Forte isns_tlv_t *attr_tlv; 2863fcf3ce44SJohn Forte uint8_t *payload_ptr; 2864fcf3ce44SJohn Forte uint16_t payload_len; 2865fcf3ce44SJohn Forte uint32_t normalized_attr_len; 2866fcf3ce44SJohn Forte uint64_t attr_tlv_len; 2867fcf3ce44SJohn Forte 2868fcf3ce44SJohn Forte /* The attribute length must be 4-byte aligned. Section 5.1.3. */ 2869fcf3ce44SJohn Forte normalized_attr_len = (attr_len % 4) == 0 ? (attr_len) : 2870fcf3ce44SJohn Forte (attr_len + (4 - (attr_len % 4))); 2871fcf3ce44SJohn Forte attr_tlv_len = ISNS_TLV_ATTR_ID_LEN 2872fcf3ce44SJohn Forte + ISNS_TLV_ATTR_LEN_LEN 2873fcf3ce44SJohn Forte + normalized_attr_len; 2874fcf3ce44SJohn Forte /* Check if we are going to exceed the maximum PDU length. */ 2875fcf3ce44SJohn Forte payload_len = ntohs(pdu->payload_len); 2876fcf3ce44SJohn Forte if ((payload_len + attr_tlv_len) > max_pdu_size) { 2877fcf3ce44SJohn Forte return (1); 2878fcf3ce44SJohn Forte } 2879fcf3ce44SJohn Forte 2880fcf3ce44SJohn Forte attr_tlv = (isns_tlv_t *)kmem_zalloc(attr_tlv_len, KM_SLEEP); 2881fcf3ce44SJohn Forte 2882fcf3ce44SJohn Forte attr_tlv->attr_id = htonl(attr_id); 2883fcf3ce44SJohn Forte 2884fcf3ce44SJohn Forte switch (attr_id) { 2885fcf3ce44SJohn Forte case ISNS_DELIMITER_ATTR_ID: 2886fcf3ce44SJohn Forte break; 2887fcf3ce44SJohn Forte 2888fcf3ce44SJohn Forte case ISNS_PORTAL_IP_ADDR_ATTR_ID: 2889fcf3ce44SJohn Forte case ISNS_PG_PORTAL_IP_ADDR_ATTR_ID: 2890fcf3ce44SJohn Forte if (attr_numeric_data == sizeof (in_addr_t)) { 2891fcf3ce44SJohn Forte /* IPv4 */ 2892fcf3ce44SJohn Forte attr_tlv->attr_value[10] = 0xFF; 2893fcf3ce44SJohn Forte attr_tlv->attr_value[11] = 0xFF; 2894fcf3ce44SJohn Forte bcopy(attr_data, ((attr_tlv->attr_value) + 12), 2895fcf3ce44SJohn Forte sizeof (in_addr_t)); 2896fcf3ce44SJohn Forte } else if (attr_numeric_data == sizeof (in6_addr_t)) { 2897fcf3ce44SJohn Forte /* IPv6 */ 2898fcf3ce44SJohn Forte bcopy(attr_data, attr_tlv->attr_value, 2899fcf3ce44SJohn Forte sizeof (in6_addr_t)); 2900fcf3ce44SJohn Forte } else if (attr_numeric_data == 0) { 2901fcf3ce44SJohn Forte /* EMPTY */ 2902fcf3ce44SJohn Forte /* Do nothing */ 2903fcf3ce44SJohn Forte } else { 2904fcf3ce44SJohn Forte kmem_free(attr_tlv, attr_tlv_len); 2905fcf3ce44SJohn Forte attr_tlv = NULL; 2906fcf3ce44SJohn Forte return (1); 2907fcf3ce44SJohn Forte } 2908fcf3ce44SJohn Forte break; 2909fcf3ce44SJohn Forte 2910fcf3ce44SJohn Forte case ISNS_EID_ATTR_ID: 2911fcf3ce44SJohn Forte case ISNS_ISCSI_NAME_ATTR_ID: 2912fcf3ce44SJohn Forte case ISNS_ISCSI_ALIAS_ATTR_ID: 2913fcf3ce44SJohn Forte case ISNS_PG_ISCSI_NAME_ATTR_ID: 2914fcf3ce44SJohn Forte bcopy((char *)attr_data, 2915fcf3ce44SJohn Forte attr_tlv->attr_value, 2916fcf3ce44SJohn Forte attr_len); 2917fcf3ce44SJohn Forte break; 2918fcf3ce44SJohn Forte 2919fcf3ce44SJohn Forte default: 2920fcf3ce44SJohn Forte switch (normalized_attr_len) { 2921fcf3ce44SJohn Forte case 0: 2922fcf3ce44SJohn Forte break; 2923fcf3ce44SJohn Forte 2924fcf3ce44SJohn Forte case 4: 2925fcf3ce44SJohn Forte *(uint32_t *)attr_tlv->attr_value = 2926fcf3ce44SJohn Forte htonl(attr_numeric_data); 2927fcf3ce44SJohn Forte break; 2928fcf3ce44SJohn Forte 2929fcf3ce44SJohn Forte case 8: 2930fcf3ce44SJohn Forte *(uint64_t *)attr_tlv->attr_value = 2931fcf3ce44SJohn Forte BE_64((uint64_t) 2932fcf3ce44SJohn Forte attr_numeric_data); 2933fcf3ce44SJohn Forte break; 2934fcf3ce44SJohn Forte } 2935fcf3ce44SJohn Forte } 2936fcf3ce44SJohn Forte 2937fcf3ce44SJohn Forte attr_tlv->attr_len = htonl(normalized_attr_len); 2938fcf3ce44SJohn Forte /* 2939fcf3ce44SJohn Forte * Convert the network byte ordered payload length to host byte 2940fcf3ce44SJohn Forte * ordered for local address calculation. 2941fcf3ce44SJohn Forte */ 2942fcf3ce44SJohn Forte payload_len = ntohs(pdu->payload_len); 2943fcf3ce44SJohn Forte payload_ptr = pdu->payload + payload_len; 2944fcf3ce44SJohn Forte bcopy(attr_tlv, payload_ptr, attr_tlv_len); 2945fcf3ce44SJohn Forte payload_len += attr_tlv_len; 2946fcf3ce44SJohn Forte 2947fcf3ce44SJohn Forte /* 2948fcf3ce44SJohn Forte * Convert the host byte ordered payload length back to network 2949fcf3ce44SJohn Forte * byte ordered - it's now ready to be sent on the wire. 2950fcf3ce44SJohn Forte */ 2951fcf3ce44SJohn Forte pdu->payload_len = htons(payload_len); 2952fcf3ce44SJohn Forte 2953fcf3ce44SJohn Forte kmem_free(attr_tlv, attr_tlv_len); 2954fcf3ce44SJohn Forte attr_tlv = NULL; 2955fcf3ce44SJohn Forte 2956fcf3ce44SJohn Forte return (0); 2957fcf3ce44SJohn Forte } 2958fcf3ce44SJohn Forte 2959fcf3ce44SJohn Forte /* ARGSUSED */ 2960fcf3ce44SJohn Forte static 2961fcf3ce44SJohn Forte void 2962fcf3ce44SJohn Forte isns_service_esi_scn(iscsi_thread_t *thread, void *arg) 2963fcf3ce44SJohn Forte { 2964fcf3ce44SJohn Forte int clnt_len; 2965fcf3ce44SJohn Forte isns_async_thread_arg_t *larg; 2966fcf3ce44SJohn Forte isns_pdu_t *in_pdu; 2967fcf3ce44SJohn Forte size_t bytes_received, in_pdu_size = 0; 2968fcf3ce44SJohn Forte uint8_t *lhba_handle; 2969*0f1702c5SYu Xiangning struct sockaddr_in6 t_addr; 2970*0f1702c5SYu Xiangning socklen_t t_addrlen; 2971fcf3ce44SJohn Forte union { 2972fcf3ce44SJohn Forte struct sockaddr sin; 2973fcf3ce44SJohn Forte struct sockaddr_in s_in4; 2974fcf3ce44SJohn Forte struct sockaddr_in6 s_in6; 2975fcf3ce44SJohn Forte } clnt_addr = { 0 }; 2976fcf3ce44SJohn Forte union { 2977fcf3ce44SJohn Forte struct sockaddr_in soa4; 2978fcf3ce44SJohn Forte struct sockaddr_in6 soa6; 2979fcf3ce44SJohn Forte } local_conn_prop; 2980fcf3ce44SJohn Forte void *listening_so, *connecting_so; 2981fcf3ce44SJohn Forte 2982fcf3ce44SJohn Forte larg = (isns_async_thread_arg_t *)arg; 2983fcf3ce44SJohn Forte listening_so = larg->listening_so; 2984fcf3ce44SJohn Forte lhba_handle = larg->lhba_handle; 2985fcf3ce44SJohn Forte 2986fcf3ce44SJohn Forte /* Done using the argument - free it */ 2987fcf3ce44SJohn Forte kmem_free(larg, sizeof (*larg)); 2988*0f1702c5SYu Xiangning bzero(&t_addr, sizeof (struct sockaddr_in6)); 2989*0f1702c5SYu Xiangning t_addrlen = sizeof (struct sockaddr_in6); 2990fcf3ce44SJohn Forte 2991*0f1702c5SYu Xiangning (void) iscsi_net->getsockname(listening_so, 2992*0f1702c5SYu Xiangning (struct sockaddr *)&t_addr, &t_addrlen); 2993*0f1702c5SYu Xiangning if (t_addrlen <= sizeof (local_conn_prop)) { 2994*0f1702c5SYu Xiangning bcopy(&t_addr, &local_conn_prop, t_addrlen); 2995fcf3ce44SJohn Forte } 2996fcf3ce44SJohn Forte 2997fcf3ce44SJohn Forte if (iscsi_net->listen(listening_so, 5) < 0) { 2998fcf3ce44SJohn Forte iscsi_net->close(listening_so); 2999fcf3ce44SJohn Forte } 3000fcf3ce44SJohn Forte 3001fcf3ce44SJohn Forte for (;;) { 3002fcf3ce44SJohn Forte int rval; 3003fcf3ce44SJohn Forte isns_pdu_t *out_pdu; 3004fcf3ce44SJohn Forte size_t out_pdu_size; 3005fcf3ce44SJohn Forte 3006fcf3ce44SJohn Forte clnt_len = sizeof (clnt_addr); 3007fcf3ce44SJohn Forte 3008fcf3ce44SJohn Forte /* Blocking call */ 3009fcf3ce44SJohn Forte connecting_so = iscsi_net->accept( 3010*0f1702c5SYu Xiangning listening_so, &clnt_addr.sin, &clnt_len); 3011fcf3ce44SJohn Forte 3012fcf3ce44SJohn Forte mutex_enter(&esi_scn_thr_mutex); 3013fcf3ce44SJohn Forte if (esi_scn_thr_to_shutdown == B_TRUE) { 3014fcf3ce44SJohn Forte /* Terminate the thread if instructed to do so. */ 3015fcf3ce44SJohn Forte mutex_exit(&esi_scn_thr_mutex); 3016fcf3ce44SJohn Forte return; 3017fcf3ce44SJohn Forte } 3018fcf3ce44SJohn Forte mutex_exit(&esi_scn_thr_mutex); 3019fcf3ce44SJohn Forte 3020fcf3ce44SJohn Forte if (connecting_so == NULL) { 3021fcf3ce44SJohn Forte iscsi_net->close(listening_so); 3022fcf3ce44SJohn Forte continue; 3023fcf3ce44SJohn Forte } 3024fcf3ce44SJohn Forte 3025fcf3ce44SJohn Forte bytes_received = isns_rcv_pdu(connecting_so, &in_pdu, 3026fcf3ce44SJohn Forte &in_pdu_size); 3027fcf3ce44SJohn Forte if (in_pdu == NULL) { 3028fcf3ce44SJohn Forte continue; 3029fcf3ce44SJohn Forte } 3030fcf3ce44SJohn Forte if (bytes_received == 0) { 3031fcf3ce44SJohn Forte continue; 3032fcf3ce44SJohn Forte } 3033fcf3ce44SJohn Forte 3034fcf3ce44SJohn Forte switch (in_pdu->func_id) { 3035fcf3ce44SJohn Forte case ISNS_ESI: 3036fcf3ce44SJohn Forte case ISNS_SCN: 3037fcf3ce44SJohn Forte if (in_pdu->func_id == ISNS_ESI) { 3038fcf3ce44SJohn Forte rval = isns_process_esi(in_pdu); 3039fcf3ce44SJohn Forte out_pdu_size = isns_create_esi_rsp_pdu( 3040fcf3ce44SJohn Forte rval, 3041fcf3ce44SJohn Forte in_pdu, 3042fcf3ce44SJohn Forte &xid, 3043fcf3ce44SJohn Forte &out_pdu); 3044fcf3ce44SJohn Forte } else if (in_pdu->func_id == ISNS_SCN) { 3045fcf3ce44SJohn Forte rval = isns_process_scn(in_pdu, 3046fcf3ce44SJohn Forte lhba_handle); 3047fcf3ce44SJohn Forte out_pdu_size = isns_create_scn_rsp_pdu( 3048fcf3ce44SJohn Forte rval, 3049fcf3ce44SJohn Forte in_pdu, 3050fcf3ce44SJohn Forte &xid, 3051fcf3ce44SJohn Forte &out_pdu); 3052fcf3ce44SJohn Forte } else { 3053fcf3ce44SJohn Forte /* 3054fcf3ce44SJohn Forte * Ignore all traffics other than 3055fcf3ce44SJohn Forte * ESI and SCN. 3056fcf3ce44SJohn Forte */ 3057fcf3ce44SJohn Forte kmem_free(in_pdu, in_pdu_size); 3058fcf3ce44SJohn Forte in_pdu = NULL; 3059fcf3ce44SJohn Forte continue; 3060fcf3ce44SJohn Forte } 3061fcf3ce44SJohn Forte 3062fcf3ce44SJohn Forte if (out_pdu_size == 0) { 3063fcf3ce44SJohn Forte kmem_free(in_pdu, in_pdu_size); 3064fcf3ce44SJohn Forte in_pdu = NULL; 3065fcf3ce44SJohn Forte continue; 3066fcf3ce44SJohn Forte } 3067fcf3ce44SJohn Forte 3068fcf3ce44SJohn Forte (void) isns_send_pdu(connecting_so, out_pdu); 3069fcf3ce44SJohn Forte 3070fcf3ce44SJohn Forte kmem_free(out_pdu, out_pdu_size); 3071fcf3ce44SJohn Forte out_pdu = NULL; 3072fcf3ce44SJohn Forte kmem_free(in_pdu, in_pdu_size); 3073fcf3ce44SJohn Forte in_pdu = NULL; 3074fcf3ce44SJohn Forte 3075fcf3ce44SJohn Forte iscsi_net->close(connecting_so); 3076fcf3ce44SJohn Forte break; 3077fcf3ce44SJohn Forte 3078fcf3ce44SJohn Forte default: 3079fcf3ce44SJohn Forte kmem_free(in_pdu, in_pdu_size); 3080fcf3ce44SJohn Forte in_pdu = NULL; 3081fcf3ce44SJohn Forte continue; 3082fcf3ce44SJohn Forte } 3083fcf3ce44SJohn Forte } 3084fcf3ce44SJohn Forte } 3085fcf3ce44SJohn Forte 3086fcf3ce44SJohn Forte static 3087fcf3ce44SJohn Forte boolean_t 3088fcf3ce44SJohn Forte find_local_portal(iscsi_addr_t *isns_server_addr, 3089fcf3ce44SJohn Forte iscsi_addr_t **local_addr, void **listening_so) 3090fcf3ce44SJohn Forte { 3091fcf3ce44SJohn Forte char local_addr_str[256]; 3092fcf3ce44SJohn Forte union { 3093fcf3ce44SJohn Forte struct sockaddr_in soa4; 3094fcf3ce44SJohn Forte struct sockaddr_in6 soa6; 3095fcf3ce44SJohn Forte } local_conn_prop = { 0 }; 3096fcf3ce44SJohn Forte union { 3097fcf3ce44SJohn Forte struct sockaddr sin; 3098fcf3ce44SJohn Forte struct sockaddr_in s_in4; 3099fcf3ce44SJohn Forte struct sockaddr_in6 s_in6; 3100fcf3ce44SJohn Forte } serv_addr = { 0 }; 3101fcf3ce44SJohn Forte void *so; 3102*0f1702c5SYu Xiangning struct sockaddr_in6 t_addr; 3103*0f1702c5SYu Xiangning socklen_t t_addrlen; 3104fcf3ce44SJohn Forte 3105fcf3ce44SJohn Forte *local_addr = NULL; 3106fcf3ce44SJohn Forte *listening_so = NULL; 3107fcf3ce44SJohn Forte 3108*0f1702c5SYu Xiangning bzero(&t_addr, sizeof (struct sockaddr_in6)); 3109*0f1702c5SYu Xiangning t_addrlen = sizeof (struct sockaddr_in6); 3110fcf3ce44SJohn Forte /* 3111fcf3ce44SJohn Forte * Determine the local IP address. 3112fcf3ce44SJohn Forte */ 3113fcf3ce44SJohn Forte so = isns_open(isns_server_addr); 3114fcf3ce44SJohn Forte if (so == NULL) { 3115fcf3ce44SJohn Forte return (B_FALSE); 3116fcf3ce44SJohn Forte } 3117fcf3ce44SJohn Forte 3118*0f1702c5SYu Xiangning iscsi_net->getsockname(so, (struct sockaddr *)&t_addr, &t_addrlen); 3119*0f1702c5SYu Xiangning if (t_addrlen > sizeof (local_conn_prop)) { 3120fcf3ce44SJohn Forte iscsi_net->close(so); 3121fcf3ce44SJohn Forte return (B_FALSE); 3122fcf3ce44SJohn Forte } 3123fcf3ce44SJohn Forte 3124*0f1702c5SYu Xiangning bcopy(&t_addr, &local_conn_prop, t_addrlen); 3125*0f1702c5SYu Xiangning t_addrlen = sizeof (struct sockaddr_in6); 3126fcf3ce44SJohn Forte if (local_conn_prop.soa4.sin_family == AF_INET) { 3127fcf3ce44SJohn Forte *local_addr = (iscsi_addr_t *)kmem_zalloc(sizeof (iscsi_addr_t), 3128fcf3ce44SJohn Forte KM_SLEEP); 3129fcf3ce44SJohn Forte (*local_addr)->a_addr.i_addr.in4.s_addr = 3130fcf3ce44SJohn Forte local_conn_prop.soa4.sin_addr.s_addr; 3131fcf3ce44SJohn Forte (*local_addr)->a_addr.i_insize = sizeof (in_addr_t); 3132fcf3ce44SJohn Forte } else if (local_conn_prop.soa4.sin_family == AF_INET6) { 3133fcf3ce44SJohn Forte /* EMPTY */ 3134fcf3ce44SJohn Forte } else { 3135fcf3ce44SJohn Forte iscsi_net->close(so); 3136fcf3ce44SJohn Forte return (B_FALSE); 3137fcf3ce44SJohn Forte } 3138fcf3ce44SJohn Forte 3139fcf3ce44SJohn Forte iscsi_net->close(so); 3140fcf3ce44SJohn Forte 3141fcf3ce44SJohn Forte /* 3142fcf3ce44SJohn Forte * Determine the local IP address. (End) 3143fcf3ce44SJohn Forte */ 3144fcf3ce44SJohn Forte 3145fcf3ce44SJohn Forte serv_addr.s_in4.sin_family = AF_INET; 3146fcf3ce44SJohn Forte /* 3147fcf3ce44SJohn Forte * Use INADDR_ANY to accept connections from any of the connected 3148fcf3ce44SJohn Forte * networks. 3149fcf3ce44SJohn Forte */ 3150fcf3ce44SJohn Forte serv_addr.s_in4.sin_addr.s_addr = htonl(INADDR_ANY); 3151fcf3ce44SJohn Forte /* 3152fcf3ce44SJohn Forte * Use port number 0 to allow the system to assign a unique unused 3153fcf3ce44SJohn Forte * port. 3154fcf3ce44SJohn Forte */ 3155fcf3ce44SJohn Forte serv_addr.s_in4.sin_port = htons(0); 3156fcf3ce44SJohn Forte 3157fcf3ce44SJohn Forte so = iscsi_net->socket(AF_INET, SOCK_STREAM, 0); 3158fcf3ce44SJohn Forte if (so == NULL) { 3159fcf3ce44SJohn Forte kmem_free((*local_addr), sizeof (iscsi_addr_t)); 3160fcf3ce44SJohn Forte *local_addr = NULL; 3161fcf3ce44SJohn Forte return (B_FALSE); 3162fcf3ce44SJohn Forte } 3163fcf3ce44SJohn Forte 3164fcf3ce44SJohn Forte if (iscsi_net->bind(so, &serv_addr.sin, 3165fcf3ce44SJohn Forte sizeof (struct sockaddr), 0, 0) < 0) { 3166fcf3ce44SJohn Forte kmem_free((*local_addr), sizeof (iscsi_addr_t)); 3167fcf3ce44SJohn Forte *local_addr = NULL; 3168fcf3ce44SJohn Forte iscsi_net->close(so); 3169fcf3ce44SJohn Forte return (B_FALSE); 3170fcf3ce44SJohn Forte } 3171fcf3ce44SJohn Forte 3172*0f1702c5SYu Xiangning (void) iscsi_net->getsockname(so, (struct sockaddr *)&t_addr, 3173*0f1702c5SYu Xiangning &t_addrlen); 3174*0f1702c5SYu Xiangning if (t_addrlen <= sizeof (local_conn_prop)) { 3175*0f1702c5SYu Xiangning bcopy(&t_addr, &local_conn_prop, t_addrlen); 3176fcf3ce44SJohn Forte (*local_addr)->a_port = ntohs(local_conn_prop.soa4.sin_port); 3177fcf3ce44SJohn Forte } else { 3178fcf3ce44SJohn Forte (*local_addr)->a_port = ISNS_DEFAULT_ESI_SCN_PORT; 3179fcf3ce44SJohn Forte } 3180fcf3ce44SJohn Forte 3181fcf3ce44SJohn Forte *listening_so = so; 3182fcf3ce44SJohn Forte 3183fcf3ce44SJohn Forte (void) inet_ntop(AF_INET, (void *)&((*local_addr)->a_addr.i_addr.in4), 3184fcf3ce44SJohn Forte local_addr_str, 256); 3185fcf3ce44SJohn Forte 3186fcf3ce44SJohn Forte return (B_TRUE); 3187fcf3ce44SJohn Forte } 3188fcf3ce44SJohn Forte 3189fcf3ce44SJohn Forte /* ARGSUSED */ 3190fcf3ce44SJohn Forte static 3191fcf3ce44SJohn Forte void 3192fcf3ce44SJohn Forte (*scn_callback_lookup(uint8_t *lhba_handle))(void *) 3193fcf3ce44SJohn Forte { 3194fcf3ce44SJohn Forte /* 3195fcf3ce44SJohn Forte * When we support multiple HBA instance we will use lhba_handle 3196fcf3ce44SJohn Forte * to look up the associated SCN callback. For now, we only support 3197fcf3ce44SJohn Forte * one HBA instance therefore we always return the same SCN callback. 3198fcf3ce44SJohn Forte */ 3199fcf3ce44SJohn Forte return (scn_callback_p); 3200fcf3ce44SJohn Forte } 3201fcf3ce44SJohn Forte 3202fcf3ce44SJohn Forte static 3203fcf3ce44SJohn Forte uint16_t 3204fcf3ce44SJohn Forte create_xid() 3205fcf3ce44SJohn Forte { 3206fcf3ce44SJohn Forte return (xid++ % MAX_XID); 3207fcf3ce44SJohn Forte } 3208fcf3ce44SJohn Forte 3209fcf3ce44SJohn Forte static 3210fcf3ce44SJohn Forte void 3211fcf3ce44SJohn Forte esi_scn_thr_cleanup() 3212fcf3ce44SJohn Forte { 3213fcf3ce44SJohn Forte boolean_t clear_esi_scn_thr_id_b = B_FALSE; 3214fcf3ce44SJohn Forte boolean_t clear_instance_listening_so_b = B_FALSE; 3215fcf3ce44SJohn Forte boolean_t clear_local_addr_b = B_FALSE; 3216fcf3ce44SJohn Forte iscsi_thread_t *tmp_esi_scn_thr_id = NULL; 3217fcf3ce44SJohn Forte 3218fcf3ce44SJohn Forte mutex_enter(&esi_scn_thr_mutex); 3219fcf3ce44SJohn Forte tmp_esi_scn_thr_id = esi_scn_thr_id; 3220fcf3ce44SJohn Forte mutex_exit(&esi_scn_thr_mutex); 3221fcf3ce44SJohn Forte if (tmp_esi_scn_thr_id != NULL) { 3222fcf3ce44SJohn Forte boolean_t unblock_esi_scn_thr_b = B_TRUE; 3223fcf3ce44SJohn Forte 3224fcf3ce44SJohn Forte /* Instruct the ESI/SCN to shut itself down. */ 3225fcf3ce44SJohn Forte mutex_enter(&esi_scn_thr_mutex); 3226fcf3ce44SJohn Forte esi_scn_thr_to_shutdown = B_TRUE; 3227fcf3ce44SJohn Forte if (instance_listening_so != NULL && 3228fcf3ce44SJohn Forte local_addr != NULL) { 3229fcf3ce44SJohn Forte isns_pdu_t *out_pdu; 3230fcf3ce44SJohn Forte size_t out_pdu_size; 3231fcf3ce44SJohn Forte void *connecting_so; 3232fcf3ce44SJohn Forte 3233fcf3ce44SJohn Forte /* 3234fcf3ce44SJohn Forte * Open a connection to the local address and send 3235fcf3ce44SJohn Forte * a dummy header to unblock the accept call so that 3236fcf3ce44SJohn Forte * the ESI/SCN thread has a chance to terminate 3237fcf3ce44SJohn Forte * itself. 3238fcf3ce44SJohn Forte */ 3239fcf3ce44SJohn Forte connecting_so = isns_open(local_addr); 3240fcf3ce44SJohn Forte if (connecting_so == NULL) { 3241fcf3ce44SJohn Forte unblock_esi_scn_thr_b = B_FALSE; 3242fcf3ce44SJohn Forte mutex_exit(&esi_scn_thr_mutex); 3243fcf3ce44SJohn Forte } else { 3244fcf3ce44SJohn Forte out_pdu_size = isns_create_pdu_header(0, 3245fcf3ce44SJohn Forte ISNS_FLAG_FIRST_PDU | 3246fcf3ce44SJohn Forte ISNS_FLAG_LAST_PDU, 3247fcf3ce44SJohn Forte &out_pdu); 3248fcf3ce44SJohn Forte if (isns_send_pdu(connecting_so, 3249fcf3ce44SJohn Forte out_pdu) != 0) { 3250fcf3ce44SJohn Forte unblock_esi_scn_thr_b = B_FALSE; 3251fcf3ce44SJohn Forte } else { 3252fcf3ce44SJohn Forte unblock_esi_scn_thr_b = B_TRUE; 3253fcf3ce44SJohn Forte } 3254fcf3ce44SJohn Forte iscsi_net->close(connecting_so); 3255fcf3ce44SJohn Forte kmem_free(out_pdu, out_pdu_size); 3256fcf3ce44SJohn Forte out_pdu = NULL; 3257fcf3ce44SJohn Forte mutex_exit(&esi_scn_thr_mutex); 3258fcf3ce44SJohn Forte } 3259fcf3ce44SJohn Forte } else { 3260fcf3ce44SJohn Forte mutex_exit(&esi_scn_thr_mutex); 3261fcf3ce44SJohn Forte } 3262fcf3ce44SJohn Forte 3263fcf3ce44SJohn Forte if (unblock_esi_scn_thr_b == B_TRUE) { 3264fcf3ce44SJohn Forte clear_instance_listening_so_b = B_TRUE; 3265fcf3ce44SJohn Forte clear_esi_scn_thr_id_b = B_TRUE; 3266fcf3ce44SJohn Forte clear_local_addr_b = B_TRUE; 3267fcf3ce44SJohn Forte } 3268fcf3ce44SJohn Forte } 3269fcf3ce44SJohn Forte 3270fcf3ce44SJohn Forte if (clear_instance_listening_so_b && 3271fcf3ce44SJohn Forte clear_esi_scn_thr_id_b && 3272fcf3ce44SJohn Forte clear_local_addr_b) { 3273fcf3ce44SJohn Forte (void) iscsi_thread_stop(esi_scn_thr_id); 3274fcf3ce44SJohn Forte iscsi_thread_destroy(esi_scn_thr_id); 3275fcf3ce44SJohn Forte 3276fcf3ce44SJohn Forte mutex_enter(&esi_scn_thr_mutex); 3277fcf3ce44SJohn Forte esi_scn_thr_id = NULL; 3278fcf3ce44SJohn Forte 3279fcf3ce44SJohn Forte /* 3280fcf3ce44SJohn Forte * Shutdown and close the listening socket. 3281fcf3ce44SJohn Forte */ 3282fcf3ce44SJohn Forte iscsi_net->shutdown(instance_listening_so, 2); 3283fcf3ce44SJohn Forte iscsi_net->close(instance_listening_so); 3284fcf3ce44SJohn Forte instance_listening_so = NULL; 3285fcf3ce44SJohn Forte 3286fcf3ce44SJohn Forte if (local_addr != NULL) { 3287fcf3ce44SJohn Forte kmem_free(local_addr, sizeof (iscsi_addr_t)); 3288fcf3ce44SJohn Forte local_addr = NULL; 3289fcf3ce44SJohn Forte } 3290fcf3ce44SJohn Forte mutex_exit(&esi_scn_thr_mutex); 3291fcf3ce44SJohn Forte } 3292fcf3ce44SJohn Forte } 3293