1/* $NetBSD: iscsid_discover.c,v 1.3 2011/11/20 01:23:57 agc 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 49uint32_t isns_id = 0; /* isns ID counter */ 50 51ISNS_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 68static void 69xlate_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 101static uint32_t 102get_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 DEBOUT(("%s: get_targets iscsi_new_trans failed\n", __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\n", retval, status)); 136 if (retval) { 137 DEBOUT(("iSNS Attribute Query failed, rc = %d\n", 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 DEBOUT(("iSNS Attribute Query returned nothing\n")); 144 isns_free_trans(t); 145 return ISCSID_STATUS_ISNS_SERVER_ERROR; 146 } 147 if (tag != isnst_iSCSIName) { 148 DEBOUT(("iSNS Query returned bad type (tag = %d, length = %d)\n", 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 DEBOUT(("Attr Query Missing Delimiter (tag = %d, length = %d)\n", 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 DEBOUT(("iSNS Query returned no or invalid name (tag = %d, " 165 "length = %d)\n", 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 DEBOUT(("iSNS Query returned no or invalid node type (tag = %d, " 174 "length = %d)\n", 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 DEBOUT(("iSNS Query returned bad type (type=%x, should be 1)\n", 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 DEBOUT(("iSNS Query returned invalid alias (tag=%d, length=%d)\n", 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 DEBOUT(("get_targets iscsi_new_trans failed\n")); 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\n", retval, status)); 217 if (retval) { 218 DEBOUT(("iSNS Attribute Query failed, rc = %d\n", 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 DEBOUT(("iSNS Attribute Query returned nothing\n")); 225 isns_free_trans(t); 226 return ISCSID_STATUS_ISNS_SERVER_ERROR; 227 } 228 if (tag != isnst_iSCSIName) { 229 DEBOUT(("iSNS Query2 returned bad name (tag = %d, length = %d)\n", 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 DEBOUT(("Attr Query2 Missing Delimiter (tag = %d, length = %d)\n", 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 DEBOUT(("iSNS Query2 returned no or invalid name (tag=%d, " 247 "length=%d)\n", 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 DEBOUT(("iSNS Query returned no or invalid address (tag=%d, " 256 "length=%d)\n", 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 DEBOUT(("iSNS Query returned no or invalid port (tag=%d, " 266 "length=%d)\n", 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 DEBOUT(("iSNS Query returned invalid port (flags=%x, " 273 "should be 0)\n", 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 DEBOUT(("iSNS Query returned no or invalid group tag (tag=%d, " 283 "length=%d)\n", 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(1, ("Adding <%s>, IP <%s>, Port %d, Tag %d\n", 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 324static uint32_t 325deregister_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 DEBOUT(("dereg_isns_server iscsi_new_trans failed\n")); 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\n", 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 367static uint32_t 368register_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 DEBOUT(("iscsi_new_trans failed\n")); 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\n", 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 416static uint32_t 417get_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 DEBOUT(("Getsockname returned error %d\n", 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 DEBOUT(("Getsockname returned unknown address family: %d\n", 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 475static uint32_t 476iscsi_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 DEBOUT(("isns_init failed with code %d\n", 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 DEBOUT(("getaddrinfo failed with code %d (%s)\n", 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 DEBOUT(("%s: socket call FAILED!\n", __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!\n", __func__)); 529 close(sock); 530 sock = -1; 531 } 532 533 if (addr == NULL) { 534 DEBOUT(("%s: couldn't connect!\n", __func__)); 535 freeaddrinfo(ai); 536 return ISCSID_STATUS_GENERAL_ERROR; 537 } 538 539 if (isns_add_servercon(isns_handle, sock, addr)) { 540 DEBOUT(("%s: FAILED!\n", __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 570static uint32_t 571update_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\n", 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\n")); 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 DEBOUT(("update_isns_server_info iscsi_new_trans failed\n")); 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 DEBOUT(("isns_send_trans returns rc %d, status %d\n", 613 retval, status)); 614 isns_free_trans(t); 615 break; 616 } 617 if (status) { 618 DEB(9, ("DevGetNext Status = %d\n", status)); 619 break; 620 } 621 622 if (isns_get_tlv(t, ISNS_TLV_FIRST, &tag, &data_len, &data_p)) { 623 DEBOUT(("No TLV in DevGetNext response!\n")); 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 DEBOUT(("iSNS GetNextDev returned no or invalid name (tag=%d, " 632 "length=%d)\n", 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 DEBOUT(("iSNS GetDevNext did not return node type\n")); 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 DEBOUT(("iSNS GetDevNext did not return node type (past delim)\n")); 647 isns_free_trans(t); 648 break; 649 } 650 if (tag != isnst_iSCSINodeType || data_len != 4) { 651 DEBOUT(("iSNS Query returned no or invalid node type (tag=%d, " 652 "length=%d)\n", 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!\n")); 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 681static isns_t * 682create_isns(iscsid_add_isns_server_req_t * req) 683{ 684 isns_t *isns; 685 686 DEB(9, ("Create iSNS %s\n", 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 722void 723add_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\n")); 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\n")); 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!\n")); 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\n", 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 781void 782get_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\n")); 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!\n")); 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!\n")); 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\n", 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 830uint32_t 831refresh_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 879uint32_t 880remove_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 917void 918dereg_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