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