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