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