1 /* $NetBSD: iscsid_discover.c,v 1.5 2016/05/29 13:35:45 mlelstv Exp $ */
2
3 /*-
4 * Copyright (c) 2005,2006,2011 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Wasabi Systems, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #ifndef ISCSI_MINIMAL
33
34 #include "iscsid_globals.h"
35 #include "isns.h"
36 #include "isns_defs.h"
37
38 #include <sys/socket.h>
39 #include <netinet/in.h>
40 #include <netinet/tcp.h>
41 #include <netdb.h>
42
43 #define MY_FLAGS ISNS_FLAG_REPLACE_REG
44
45
46 /**********************************************************************
47 **********************************************************************/
48
49 uint32_t isns_id = 0; /* isns ID counter */
50
51 ISNS_HANDLE isns_handle = ISNS_INVALID_HANDLE;
52
53 /**********************************************************************
54 **********************************************************************/
55
56 /*
57 * xlate_ip
58 * Support routine to translate binary IP into string form for storage in
59 * target object. Handles IPv6 and IPv4 formats.
60 *
61 * Parameters:
62 * dest the destination string
63 * data the source (from iSNS address field)
64 *
65 * Returns: status
66 */
67
68 static void
xlate_ip(uint8_t * dest,size_t size,void * data)69 xlate_ip(uint8_t *dest, size_t size, void *data)
70 {
71 uint16_t *wdt = (uint16_t *) data;
72 size_t cc;
73 int i;
74 char *dst = (char *)dest;
75 char *dt = data;
76
77 for (i = 0; i < 5 && !wdt[i]; i++) {
78 }
79 if (i == 5 && wdt[5] == 0xffff) {
80 snprintf(dst, size, "%d.%d.%d.%d",
81 dt[12], dt[13], dt[14], dt[15]);
82 } else {
83 for (cc = 0, i = 0; i < 7; i++) {
84 cc += snprintf(&dst[cc], size - cc, "%x:", wdt[i]);
85 }
86 snprintf(&dst[cc], size - cc, "%x", wdt[7]);
87 }
88 }
89
90
91 /*
92 * get_isns_target_info
93 * Support routine to query the server for the attributes of the given target.
94 *
95 * Parameters:
96 * TargetName The target name to query.
97 *
98 * Returns: status
99 */
100
101 static uint32_t
get_isns_target_info(isns_t * isns,uint8_t * TargetName)102 get_isns_target_info(isns_t * isns, uint8_t * TargetName)
103 {
104 int retval;
105 ISNS_TRANS t;
106 uint32_t tag;
107 uint32_t data_len;
108 void *data_p;
109 uint32_t u32;
110 struct timespec tout = { 5, 0 };
111 uint32_t status;
112 target_t *targ;
113 char name[ISCSI_STRING_LENGTH];
114 char alias[ISCSI_STRING_LENGTH];
115 iscsi_portal_address_t addr;
116
117 t = isns_new_trans(isns_handle, isnsp_DevAttrQry, MY_FLAGS);
118 if (ISNS_INVALID_TRANS == t) {
119 DEB(10,("%s: get_targets iscsi_new_trans failed", __func__));
120 return ISCSID_STATUS_NO_RESOURCES;
121 }
122 isns_add_string(t, isnst_iSCSIName, (char *)isns->reg_iscsi_name);
123 isns_add_string(t, isnst_iSCSIName, (char *)TargetName);
124
125 isns_add_tlv(t, isnst_Delimiter, 0, NULL);
126
127 isns_add_tlv(t, isnst_iSCSIName, 0, NULL); /* 32: name */
128 isns_add_tlv(t, isnst_iSCSINodeType, 0, NULL); /* 33: node type */
129 isns_add_tlv(t, isnst_iSCSIAlias, 0, NULL); /* 34: alias */
130 /* ToDo: get security attributes... */
131 /* isns_add_tlv (t, isnst_PortalSecBmap, 0, NULL); */
132 /*tag=27: security bitmap */
133
134 retval = isns_send_trans(t, &tout, &status);
135 DEB(9, ("isns_send_trans called, returns %d, status %d", retval, status));
136 if (retval) {
137 DEB(10,("iSNS Attribute Query failed, rc = %d", retval));
138 isns_free_trans(t);
139 return ISCSID_STATUS_ISNS_SERVER_ERROR;
140 }
141 /* First is target name (the one we put in), ignore */
142 if (isns_get_tlv(t, ISNS_TLV_FIRST, &tag, &data_len, &data_p)) {
143 DEB(10,("iSNS Attribute Query returned nothing"));
144 isns_free_trans(t);
145 return ISCSID_STATUS_ISNS_SERVER_ERROR;
146 }
147 if (tag != isnst_iSCSIName) {
148 DEB(10,("iSNS Query returned bad type (tag = %d, length = %d)",
149 tag, data_len));
150 isns_free_trans(t);
151 return ISCSID_STATUS_ISNS_SERVER_ERROR;
152 }
153
154 isns_get_tlv(t, ISNS_TLV_NEXT, &tag, &data_len, &data_p);
155 if (tag != isnst_Delimiter) {
156 DEB(10,("Attr Query Missing Delimiter (tag = %d, length = %d)",
157 tag, data_len));
158 isns_free_trans(t);
159 return ISCSID_STATUS_ISNS_SERVER_ERROR;
160 }
161
162 isns_get_tlv(t, ISNS_TLV_NEXT, &tag, &data_len, &data_p);
163 if (tag != isnst_iSCSIName || !data_len || data_len >= ISCSI_STRING_LENGTH) {
164 DEB(10,("iSNS Query returned no or invalid name (tag = %d, "
165 "length = %d)", tag, data_len));
166 isns_free_trans(t);
167 return ISCSID_STATUS_ISNS_SERVER_ERROR;
168 }
169 strlcpy(name, (char *) data_p, sizeof(name));
170
171 isns_get_tlv(t, ISNS_TLV_NEXT, &tag, &data_len, &data_p);
172 if (tag != isnst_iSCSINodeType || data_len != 4) {
173 DEB(10,("iSNS Query returned no or invalid node type (tag = %d, "
174 "length = %d)", tag, data_len));
175 isns_free_trans(t);
176 return ISCSID_STATUS_ISNS_SERVER_ERROR;
177 }
178 u32 = ntohl(*((uint32_t *) data_p));
179 if (!(u32 & 1)) {
180 DEB(10,("iSNS Query returned bad type (type=%x, should be 1)", u32));
181 isns_free_trans(t);
182 return ISCSID_STATUS_ISNS_SERVER_ERROR;
183 }
184
185 isns_get_tlv(t, ISNS_TLV_NEXT, &tag, &data_len, &data_p);
186 if (tag == isnst_iSCSIAlias) {
187 if (data_len >= ISCSI_STRING_LENGTH) {
188 DEB(10,("iSNS Query returned invalid alias (tag=%d, length=%d)",
189 tag, data_len));
190 isns_free_trans(t);
191 return ISCSID_STATUS_ISNS_SERVER_ERROR;
192 }
193 strlcpy(alias, (char *) data_p, sizeof(alias));
194 isns_get_tlv(t, ISNS_TLV_NEXT, &tag, &data_len, &data_p);
195 } else
196 alias[0] = 0;
197
198 isns_free_trans(t);
199
200 if (ISNS_INVALID_TRANS ==
201 (t = isns_new_trans(isns_handle, isnsp_DevAttrQry, MY_FLAGS))) {
202 DEB(10,("get_targets iscsi_new_trans failed"));
203 return ISCSID_STATUS_NO_RESOURCES;
204 }
205 isns_add_string(t, isnst_iSCSIName, (char *)isns->reg_iscsi_name);
206 isns_add_string(t, isnst_iSCSIName, (char *)TargetName);
207
208 isns_add_tlv(t, isnst_Delimiter, 0, NULL);
209
210 isns_add_tlv(t, isnst_PGiSCSIName, 0, NULL); /* 48: portal name */
211 isns_add_tlv(t, isnst_PGPortIPAddr, 0, NULL); /* 49: portal IP */
212 isns_add_tlv(t, isnst_PGPortIPPort, 0, NULL); /* 50: portal port */
213 isns_add_tlv(t, isnst_PGTag, 0, NULL); /* 51: group tag */
214
215 retval = isns_send_trans(t, &tout, &status);
216 DEB(9, ("isns_send_trans called, returns %d, status %d", retval, status));
217 if (retval) {
218 DEB(10,("iSNS Attribute Query failed, rc = %d", retval));
219 isns_free_trans(t);
220 return ISCSID_STATUS_ISNS_SERVER_ERROR;
221 }
222 /* First is target name (the one we put in), ignore */
223 if (isns_get_tlv(t, ISNS_TLV_FIRST, &tag, &data_len, &data_p)) {
224 DEB(10,("iSNS Attribute Query returned nothing"));
225 isns_free_trans(t);
226 return ISCSID_STATUS_ISNS_SERVER_ERROR;
227 }
228 if (tag != isnst_iSCSIName) {
229 DEB(10,("iSNS Query2 returned bad name (tag = %d, length = %d)",
230 tag, data_len));
231 isns_free_trans(t);
232 return ISCSID_STATUS_ISNS_SERVER_ERROR;
233 }
234
235 isns_get_tlv(t, ISNS_TLV_NEXT, &tag, &data_len, &data_p);
236 if (tag != isnst_Delimiter) {
237 DEB(10,("Attr Query2 Missing Delimiter (tag = %d, length = %d)",
238 tag, data_len));
239 isns_free_trans(t);
240 return ISCSID_STATUS_ISNS_SERVER_ERROR;
241 }
242
243 while (!isns_get_tlv(t, ISNS_TLV_NEXT, &tag, &data_len, &data_p)) {
244 if (tag != isnst_PGiSCSIName || !data_len ||
245 data_len >= ISCSI_STRING_LENGTH) {
246 DEB(10,("iSNS Query2 returned no or invalid name (tag=%d, "
247 "length=%d)", tag, data_len));
248 isns_free_trans(t);
249 return ISCSID_STATUS_ISNS_SERVER_ERROR;
250 }
251 strlcpy(name, (char *) data_p, sizeof(name));
252
253 isns_get_tlv(t, ISNS_TLV_NEXT, &tag, &data_len, &data_p);
254 if (tag != isnst_PGPortIPAddr || data_len != 16) {
255 DEB(10,("iSNS Query returned no or invalid address (tag=%d, "
256 "length=%d)", tag, data_len));
257 isns_free_trans(t);
258 return ISCSID_STATUS_ISNS_SERVER_ERROR;
259 }
260 xlate_ip(addr.address, sizeof(addr.address), (uint8_t *) data_p);
261
262 /* Now comes the port */
263 isns_get_tlv(t, ISNS_TLV_NEXT, &tag, &data_len, &data_p);
264 if (tag != isnst_PGPortIPPort || data_len != 4) {
265 DEB(10,("iSNS Query returned no or invalid port (tag=%d, "
266 "length=%d)", tag, data_len));
267 isns_free_trans(t);
268 return ISCSID_STATUS_ISNS_SERVER_ERROR;
269 }
270 u32 = ntohl(*((uint32_t *) data_p));
271 if (u32 & 0xffff0000) {
272 DEB(10,("iSNS Query returned invalid port (flags=%x, "
273 "should be 0)", u32 >> 16));
274 isns_free_trans(t);
275 return ISCSID_STATUS_ISNS_SERVER_ERROR;
276 }
277 addr.port = (uint16_t) u32;
278
279 /* And each target must have a group tag */
280 isns_get_tlv(t, ISNS_TLV_NEXT, &tag, &data_len, &data_p);
281 if (tag != isnst_PGTag || (data_len && data_len != 4)) {
282 DEB(10,("iSNS Query returned no or invalid group tag (tag=%d, "
283 "length=%d)", tag, data_len));
284 isns_free_trans(t);
285 return ISCSID_STATUS_ISNS_SERVER_ERROR;
286 }
287 if (data_len) {
288 u32 = ntohl(*((uint32_t *) data_p));
289 addr.group_tag = (uint16_t) u32;
290 } else
291 addr.group_tag = 0;
292
293 /* we have everything necessary to describe the target, add it. */
294
295 DEB(2, ("Adding <%s>, IP <%s>, Port %d, Tag %d",
296 name, addr.address, addr.port, addr.group_tag));
297
298 if ((targ = add_discovered_target((unsigned char *)name, &addr, PORTAL_TYPE_ISNS,
299 isns->entry.sid.id)) == NULL) {
300 isns_free_trans(t);
301 return ISCSID_STATUS_NO_RESOURCES;
302 }
303
304 if (alias[0]) {
305 strlcpy((char *)targ->TargetAlias, alias,
306 sizeof(targ->TargetAlias));
307 }
308 }
309 isns_free_trans(t);
310
311 return ISCSID_STATUS_SUCCESS;
312 }
313
314
315 /*
316 * deregister_isns_server
317 * Support routine to deregister the initiator from the iSNS server
318 *
319 * Parameters: The server descriptor
320 *
321 * Returns: status
322 */
323
324 static uint32_t
deregister_isns_server(isns_t * isns)325 deregister_isns_server(isns_t * isns)
326 {
327 int retval;
328 ISNS_TRANS t;
329 struct timespec tout = { 5, 0 };
330 uint32_t status;
331
332 /*
333 * Create transaction for deregistering with iSNS server
334 */
335
336 if (ISNS_INVALID_TRANS == (t = isns_new_trans(isns_handle, isnsp_DevDereg,
337 MY_FLAGS))) {
338 DEB(10,("dereg_isns_server iscsi_new_trans failed"));
339 return ISCSID_STATUS_NO_RESOURCES;
340 }
341
342 isns_add_string(t, isnst_iSCSIName, (char *)isns->reg_iscsi_name);
343 isns_add_tlv(t, isnst_Delimiter, 0, NULL);
344 isns_add_string(t, isnst_EID, (char *)isns->reg_entity_id);
345 isns_add_tlv(t, isnst_PortalIPAddr, (uint32_t)sizeof(isns->reg_ip_addr),
346 isns->reg_ip_addr);
347 isns_add_tlv(t, isnst_PortalPort, (uint32_t)sizeof(isns->reg_ip_port),
348 &isns->reg_ip_port);
349 isns_add_string(t, isnst_iSCSIName, (char *)isns->reg_iscsi_name);
350
351 retval = isns_send_trans(t, &tout, &status);
352 DEB(9, ("DevAttrReg request returns %d, status %d", retval, status));
353
354 isns_free_trans(t);
355 return ISCSID_STATUS_SUCCESS;
356 }
357
358 /*
359 * register_isns_server
360 *
361 * Parameters: The server descriptor
362 *
363 * Returns: status
364 */
365
366
367 static uint32_t
register_isns_server(isns_t * isns)368 register_isns_server(isns_t * isns)
369 {
370 int retval;
371 ISNS_TRANS t;
372 uint32_t u32;
373 struct timespec tout = { 5, 0 };
374 uint32_t status;
375
376 if (ISNS_INVALID_TRANS == (t = isns_new_trans(isns_handle, isnsp_DevAttrReg,
377 MY_FLAGS))) {
378 DEB(10,("iscsi_new_trans failed"));
379 return ISCSID_STATUS_NO_RESOURCES;
380 }
381
382 isns_add_string(t, isnst_iSCSIName, (char *)isns->reg_iscsi_name); /*tag=32 */
383 isns_add_tlv(t, isnst_Delimiter, 0, NULL);
384 isns_add_string(t, isnst_EID, (char *)isns->reg_entity_id);
385 u32 = htonl(2);
386 isns_add_tlv(t, isnst_EntProtocol, (uint32_t)sizeof(u32), &u32);
387 isns_add_tlv(t, isnst_PortalIPAddr, (uint32_t)sizeof(isns->reg_ip_addr),
388 isns->reg_ip_addr);
389 isns_add_tlv(t, isnst_PortalPort, (uint32_t)sizeof(isns->reg_ip_port),
390 &isns->reg_ip_port);
391 isns_add_string(t, isnst_iSCSIName, (char *)isns->reg_iscsi_name); /*tag=32 */
392 u32 = htonl(2);
393 isns_add_tlv(t, isnst_iSCSINodeType, (uint32_t)sizeof(u32), &u32);
394 /*tag=33 (node type = intiator) */
395
396 retval = isns_send_trans(t, &tout, &status);
397 DEB(9, ("DevAttrReg request returns %d, status %d", retval, status));
398 isns_free_trans(t);
399
400 if (retval || status)
401 return ISCSID_STATUS_ISNS_ERROR;
402
403 return ISCSID_STATUS_SUCCESS;
404 }
405
406
407 /*
408 * get_registration_info
409 *
410 * Parameters: The server descriptor
411 *
412 * Returns: status
413 */
414
415
416 static uint32_t
get_registration_info(isns_t * isns)417 get_registration_info(isns_t * isns)
418 {
419 struct sockaddr_storage sa;
420 unsigned n;
421
422 strlcpy((char *)isns->reg_iscsi_name, (char *)node_name.InitiatorName,
423 sizeof(isns->reg_iscsi_name));
424 strlcpy((char *)isns->reg_entity_id, (char *)node_name.InitiatorAlias,
425 sizeof(isns->reg_entity_id));
426
427 /*Get our source IP and port numbers */
428 n = sizeof(sa);
429 if (getsockname(isns->sock, (struct sockaddr *)(void *)&sa, &n)) {
430 DEB(10,("Getsockname returned error %d", errno));
431 return ISCSID_STATUS_GENERAL_ERROR;
432 }
433 switch (sa.ss_family) {
434 case AF_INET:
435 {
436 struct sockaddr_in *si =
437 (struct sockaddr_in *)(void *)&sa;
438 uint32_t *u32 = (uint32_t *)(void *)isns->reg_ip_addr;
439
440 u32[0] = u32[1] = 0;
441 u32[2] = htonl(0xffff);
442 u32[3] = htonl(si->sin_addr.s_addr);
443 isns->reg_ip_port = htons(si->sin_port);
444 }
445 break;
446
447 case AF_INET6:
448 {
449 struct sockaddr_in6 *si =
450 (struct sockaddr_in6 *)(void *) &sa;
451
452 memcpy(isns->reg_ip_addr, &si->sin6_addr,
453 sizeof(isns->reg_ip_addr));
454 isns->reg_ip_port = htons(si->sin6_port);
455 }
456 break;
457
458 default:
459 DEB(10,("Getsockname returned unknown address family: %d",
460 sa.ss_family));
461 return ISCSID_STATUS_GENERAL_ERROR;
462 }
463 return ISCSID_STATUS_SUCCESS;
464 }
465
466
467 /*
468 * iscsi_isns_serverconn - given a set of server address, try connecting
469 *
470 * Parameters: The descriptor for the iSNS server to query
471 *
472 * Returns: status
473 */
474
475 static uint32_t
iscsi_isns_serverconn(isns_t * isns)476 iscsi_isns_serverconn(isns_t * isns)
477 {
478 int sock = -1;
479 char port[16];
480 struct addrinfo hints;
481 struct addrinfo *ai, *addr;
482 int retval;
483
484 /*
485 * Initialize the iSNS library if it needs it
486 */
487
488 if (isns_handle == ISNS_INVALID_HANDLE) {
489 if ((retval = isns_init(&isns_handle, 0)) != 0) {
490 /*Couldn't initialize the iSNS library */
491 DEB(10,("isns_init failed with code %d", retval));
492 isns_handle = ISNS_INVALID_HANDLE;
493 return ISCSID_STATUS_GENERAL_ERROR;
494 }
495 }
496
497 /*
498 * Find the server address from the iSNS server list entry,
499 * and try to connect to the iSNS server
500 */
501
502 snprintf(port, sizeof(port), "%d", (isns->port) ? isns->port : ISCSI_DEFAULT_ISNS_PORT);
503 memset(&hints, 0, sizeof(hints));
504 hints.ai_family = PF_UNSPEC;
505 hints.ai_socktype = SOCK_STREAM;
506 hints.ai_protocol = IPPROTO_TCP;
507
508 retval = getaddrinfo((char *)isns->address, port, &hints, &ai);
509 if (retval) {
510 DEB(10,("getaddrinfo failed with code %d (%s)",
511 retval, gai_strerror(retval)));
512 return ISCSID_STATUS_GENERAL_ERROR;
513 }
514
515 for (addr = ai; addr != NULL; addr = addr->ai_next) {
516 sock = socket(addr->ai_family, addr->ai_socktype,
517 addr->ai_protocol);
518
519 if (sock == -1) {
520 DEB(10,("%s: socket call FAILED!", __func__));
521 freeaddrinfo(ai);
522 return (uint32_t)-1;
523 }
524
525 if (connect(sock, addr->ai_addr, addr->ai_addrlen) != -1)
526 break;
527
528 DEB(1, ("%s: connect call FAILED!", __func__));
529 close(sock);
530 sock = -1;
531 }
532
533 if (addr == NULL) {
534 DEB(10,("%s: couldn't connect!", __func__));
535 freeaddrinfo(ai);
536 return ISCSID_STATUS_GENERAL_ERROR;
537 }
538
539 if (isns_add_servercon(isns_handle, sock, addr)) {
540 DEB(10,("%s: FAILED!", __func__));
541 close(sock);
542 freeaddrinfo(ai);
543 return ISCSID_STATUS_GENERAL_ERROR;
544 }
545
546 freeaddrinfo(ai);
547 isns->sock = sock;
548
549 if ((retval = get_registration_info(isns)) != 0) {
550 return retval;
551 }
552
553 deregister_isns_server(isns);
554
555 return register_isns_server(isns);
556 }
557
558
559 /*
560 * update_isns_server_info
561 * Support routine to query the specified iSNS server for all targets
562 * Called from add_isns_server and refresh_isns_server
563 *
564 * Parameters: The descriptor for the iSNS server to query
565 *
566 * Returns: status
567 */
568
569
570 static uint32_t
update_isns_server_info(isns_t * isns)571 update_isns_server_info(isns_t * isns)
572 {
573 int retval;
574 ISNS_TRANS t;
575 uint32_t tag;
576 uint32_t data_len;
577 void *data_p;
578 uint32_t u32;
579 struct timespec tout = { 5, 0 };
580 uint32_t status;
581 uint8_t TargetName[ISCSI_STRING_LENGTH];
582
583
584 DEB(9, ("update_isns_server_info for iSNS %s", isns->address));
585
586 if (isns->sock < 0) {
587 if ((status = iscsi_isns_serverconn(isns)) != 0) {
588 /*We couldn't connect to the iSNS server */
589 DEB(9, ("update_isns_server_info iscsi_isns_serverconn failed"));
590 return status;
591 }
592 }
593
594 for (TargetName[0] = 0;;) {
595 if (ISNS_INVALID_TRANS == (t = isns_new_trans(isns_handle,
596 isnsp_DevGetNext, MY_FLAGS))) {
597 DEB(10,("update_isns_server_info iscsi_new_trans failed"));
598 return ISCSID_STATUS_NO_RESOURCES;
599 }
600
601 isns_add_string(t, isnst_iSCSIName, (char *)node_name.InitiatorName);
602
603 if (TargetName[0])
604 isns_add_string(t, isnst_iSCSIName, (char *)TargetName);
605 else
606 isns_add_tlv(t, isnst_iSCSIName, 0, NULL);
607
608 isns_add_tlv(t, isnst_Delimiter, 0, NULL);
609 isns_add_tlv(t, isnst_iSCSINodeType, 0, NULL);
610
611 if ((retval = isns_send_trans(t, &tout, &status)) != 0) {
612 DEB(10,("isns_send_trans returns rc %d, status %d",
613 retval, status));
614 isns_free_trans(t);
615 break;
616 }
617 if (status) {
618 DEB(9, ("DevGetNext Status = %d", status));
619 break;
620 }
621
622 if (isns_get_tlv(t, ISNS_TLV_FIRST, &tag, &data_len, &data_p)) {
623 DEB(10,("No TLV in DevGetNext response!"));
624 isns_free_trans(t);
625 break;
626 }
627 /* We need the name, or there's nothing left to do */
628
629 if (tag != isnst_iSCSIName || !data_len ||
630 data_len >= ISCSI_STRING_LENGTH) {
631 DEB(10,("iSNS GetNextDev returned no or invalid name (tag=%d, "
632 "length=%d)", tag, data_len));
633 isns_free_trans(t);
634 break;
635 }
636 strlcpy((char *)TargetName, (char *) data_p, sizeof(TargetName));
637
638 /* We must get at least the node type, and it must be a target */
639 if (isns_get_tlv(t, ISNS_TLV_NEXT, &tag, &data_len, &data_p)) {
640 DEB(10,("iSNS GetDevNext did not return node type"));
641 isns_free_trans(t);
642 break;
643 }
644 if (tag == isnst_Delimiter && isns_get_tlv(t, ISNS_TLV_NEXT, &tag,
645 &data_len, &data_p)) {
646 DEB(10,("iSNS GetDevNext did not return node type (past delim)"));
647 isns_free_trans(t);
648 break;
649 }
650 if (tag != isnst_iSCSINodeType || data_len != 4) {
651 DEB(10,("iSNS Query returned no or invalid node type (tag=%d, "
652 "length=%d)", tag, data_len));
653 isns_free_trans(t);
654 break;
655 }
656 u32 = ntohl(*((uint32_t *) data_p));
657 isns_free_trans(t);
658
659 if (u32 & 1)
660 get_isns_target_info(isns, TargetName);
661 }
662
663 DEB(9, ("update_isns_server_info returning SUCCESS!"));
664 return ISCSID_STATUS_SUCCESS;
665 }
666
667
668 /**********************************************************************
669 **********************************************************************/
670
671 /*
672 * create_isns:
673 * Create an isns structure and initialize it.
674 *
675 * Parameter:
676 * name The iSNS server name
677 *
678 * Returns: Pointer to isns structure, NULL if allocation failed.
679 */
680
681 static isns_t *
create_isns(iscsid_add_isns_server_req_t * req)682 create_isns(iscsid_add_isns_server_req_t * req)
683 {
684 isns_t *isns;
685
686 DEB(9, ("Create iSNS %s", req->address));
687
688 if ((isns = calloc(1, sizeof(*isns))) == NULL)
689 return NULL;
690
691 for (isns_id++; !isns_id || find_isns_id(isns_id) != NULL;)
692 isns_id++;
693
694 isns->entry.sid.id = isns_id;
695 strlcpy((char *)isns->entry.sid.name, (char *)req->name, sizeof(isns->entry.sid.name));
696 strlcpy((char *)isns->address, (char *)req->address, sizeof(isns->address));
697 isns->port = req->port;
698 isns->sock = -1;
699
700 return isns;
701 }
702
703
704 /*
705 * add_isns_server
706 * Adds an iSNS server to the server list.
707 * This command will add the address of an iSNS server to the list
708 * of iSNS servers that the discovery daemon queries to discover targets.
709 * The daemon will then register itself with the iSNS server,
710 * and query the iSNS server for the list of targets.
711 * The discovered targets will be added to the list of target portals.
712 * The response contains the ID of the iSNS server.
713 *
714 * Parameter: The parameter contains the address of the server.
715 *
716 * Returns: Nothing
717 * The response parameter is an iscsid_add_isns_server_rsp_t
718 * containing:
719 * server_id = Unique ID for the iSNS server
720 */
721
722 void
add_isns_server(iscsid_add_isns_server_req_t * req,iscsid_response_t ** prsp,int * prsp_temp)723 add_isns_server(iscsid_add_isns_server_req_t * req, iscsid_response_t ** prsp,
724 int *prsp_temp)
725 {
726 iscsid_response_t *rsp = *prsp;
727 iscsid_add_isns_server_rsp_t *res;
728 isns_t *isns;
729
730 DEB(9, ("IN add_isns_server"));
731
732 /*
733 * Make a response
734 */
735
736 rsp = make_rsp(sizeof(iscsid_add_isns_server_rsp_t), prsp, prsp_temp);
737 if (rsp == NULL) {
738 DEB(9, ("OUT add_isns_server: make_rsp FAILED"));
739 return;
740 }
741
742 res = (iscsid_add_isns_server_rsp_t *)(void *)rsp->parameter;
743
744 /*
745 * First, allocate the isns server structure to put on the list
746 */
747
748 isns = create_isns(req);
749 if (isns == NULL) {
750 rsp->status = ISCSID_STATUS_NO_RESOURCES;
751 DEB(9, ("OUT add_isns_server: create_isns FAILED!"));
752 return;
753 }
754
755 TAILQ_INSERT_TAIL(&list[ISNS_LIST].list, &isns->entry, link);
756 list[ISNS_LIST].num_entries++;
757 res->server_id = isns->entry.sid.id;
758
759 DEB(9, ("OUT add_isns_server: server_id = %d, name = %s",
760 isns->entry.sid.id, isns->address));
761
762 /*
763 * Now try to connect to the iSNS server...
764 */
765
766 update_isns_server_info(isns);
767 }
768
769
770 /*
771 * get_isns_server
772 * Returns the address of the iSNS server with the specified ID
773 *
774 * Parameters: The unique ID of the server
775 *
776 * Returns: The status returned by the driver
777 * The response parameter contains the iSNS server address as a
778 * zero-terminated UTF-8 string
779 */
780
781 void
get_isns_server(iscsid_sym_id_t * preq,iscsid_response_t ** prsp,int * prsp_temp)782 get_isns_server(iscsid_sym_id_t * preq, iscsid_response_t ** prsp,
783 int *prsp_temp)
784 {
785 iscsid_response_t *rsp = *prsp;
786 iscsid_get_isns_server_rsp_t *res;
787 isns_t *isns;
788
789 DEB(9, ("IN get_isns_server"));
790 isns = find_isns(preq);
791 if (isns == NULL) {
792 rsp->status = ISCSID_STATUS_INVALID_ISNS_ID;
793 DEB(9, ("OUT get_isns_server: find_isns FAILED!"));
794 return;
795 }
796
797 rsp = make_rsp(sizeof(iscsid_get_isns_server_rsp_t), prsp, prsp_temp);
798 if (rsp == NULL) {
799 DEB(9, ("OUT get_isns_server: make_rsp FAILED!"));
800 return;
801 }
802 res = (iscsid_get_isns_server_rsp_t *)(void *)rsp->parameter;
803
804 strlcpy((char *)res->address, (char *)isns->address,
805 sizeof(res->address));
806 res->port = isns->port;
807 res->server_id = isns->entry.sid;
808 DEB(9, ("OUT get_isns_server: id = %d, address = %s",
809 res->server_id.id, res->address));
810 }
811
812
813 /*
814 * slp_find_isns_servers
815 */
816
817 /* More Here Later... */
818
819
820 /*
821 * refresh_isns_server
822 * Query the specified iSNS servers for the list of targets.
823 *
824 * Parameters:
825 * id Server ID
826 *
827 * Returns: Status
828 */
829
830 uint32_t
refresh_isns_server(uint32_t id)831 refresh_isns_server(uint32_t id)
832 {
833 uint32_t rc;
834 isns_t *isns;
835 generic_entry_t *curr;
836 generic_entry_t *next;
837
838 isns = find_isns_id(id);
839 if (isns == NULL)
840 return ISCSID_STATUS_INVALID_ISNS_ID;
841
842 TAILQ_FOREACH(curr, &list[PORTAL_LIST].list, link) {
843 portal_t *p = (portal_t *)(void *)curr;
844 if (p->portaltype == PORTAL_TYPE_ISNS && p->discoveryid == id)
845 p->portaltype = PORTAL_TYPE_REFRESHING;
846 }
847
848 rc = update_isns_server_info(isns);
849
850 /*
851 * Go through our list of portals and look for ones
852 * that are still marked for refreshing.
853 * These are ones that are no longer there and should be removed.
854 */
855
856 for (curr = TAILQ_FIRST(&list[PORTAL_LIST].list); curr != NULL;
857 curr = next) {
858 portal_t *p = (portal_t *)(void *)curr;
859 next = TAILQ_NEXT(curr, link);
860 if (p->portaltype == PORTAL_TYPE_REFRESHING)
861 delete_portal(p, TRUE);
862 }
863
864 return rc;
865 }
866
867
868 /*
869 * remove_isns_server
870 * Removed an iSNS server.
871 * This does not remove the discovered targets from the list.
872 *
873 * Parameters: The iscid_remove_isns_req_t structure containing:
874 * server_id = unique ID of server to remove
875 *
876 * Returns: The status returned.
877 */
878
879 uint32_t
remove_isns_server(iscsid_sym_id_t * preq)880 remove_isns_server(iscsid_sym_id_t * preq)
881 {
882 generic_entry_t *curr;
883 isns_t *isns;
884 uint32_t id;
885
886 isns = find_isns(preq);
887 if (isns == NULL)
888 return ISCSID_STATUS_INVALID_ISNS_ID;
889
890 /*Deregister with the iSNS server. */
891 /*Ignore any errors during deregistration... */
892 if (isns->sock >= 0) {
893 deregister_isns_server(isns);
894 close(isns->sock);
895 }
896
897 TAILQ_REMOVE(&list[ISNS_LIST].list, &isns->entry, link);
898 list[ISNS_LIST].num_entries--;
899
900 id = isns->entry.sid.id;
901 free(isns);
902
903 TAILQ_FOREACH(curr, &list[PORTAL_LIST].list, link) {
904 portal_t *p = (portal_t *)(void *)curr;
905 if (p->portaltype == PORTAL_TYPE_ISNS && p->discoveryid == id)
906 p->discoveryid = 0; /* mark deleted */
907 }
908
909 return ISCSID_STATUS_SUCCESS;
910 }
911
912
913 /*
914 Deregister all isns servers on daemon termination
915 */
916
917 void
dereg_all_isns_servers(void)918 dereg_all_isns_servers(void)
919 {
920 generic_list_t *plist;
921 generic_entry_t *curr;
922
923 plist = &list[ISNS_LIST].list;
924 TAILQ_FOREACH(curr, plist, link)
925 deregister_isns_server((isns_t *)(void *)curr);
926 }
927
928 #endif
929
930