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