1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <stdio.h> 28 #include <unistd.h> 29 #include <stdlib.h> 30 #include <strings.h> 31 #include <syslog.h> 32 #include <netdb.h> 33 #include <pthread.h> 34 #include <signal.h> 35 #include <errno.h> 36 #include <netinet/in.h> 37 #include <sys/types.h> 38 #include <sys/socket.h> 39 #include <arpa/inet.h> 40 41 #include <iscsitgt_impl.h> 42 43 #include "isns_protocol.h" 44 #include "isns_client.h" 45 #include "target.h" 46 #include "queue.h" 47 48 49 typedef struct { 50 uint32_t pf_family; 51 uint32_t ip_len; 52 uint32_t ai_addrlen; 53 union { 54 in_addr_t in; 55 in6_addr_t in6; 56 } ip_adr; 57 } ip_t; 58 59 #define ISNS_TGT_LOGOUT 54321 60 61 extern target_queue_t *mgmtq; 62 63 /* 64 * Global 65 * Parameters for ESI/SCN processing. 66 * scn_port: ESI/SCN port to receive ISNS_ESI & ISNS_SCN messages 67 * isns_args: 68 * eid_ip: Entity IP info 69 */ 70 static int scn_port = 0; 71 static esi_scn_arg_t isns_args = {{0}, {0}, 0}; 72 static ip_t eid_ip; 73 static int num_reg = 0; 74 static pthread_t scn_tid = 0; 75 static pthread_t isns_tid = 0; 76 static Boolean_t isns_shutdown = True; 77 static Boolean_t connection_thr_bail_out = False; 78 static int ISNS_SLEEP_SECS = 20; 79 Boolean_t isns_server_connection_thr_running = False; 80 target_queue_t *mgmtq = NULL; 81 82 static int get_ip_addr(char *node, ip_t *sa); 83 static int isns_op_all(uint16_t); 84 static int append_tpgt(tgt_node_t *, isns_pdu_t *); 85 static void process_esi(int, isns_pdu_t *); 86 static void process_scn(int, isns_pdu_t *); 87 static void *esi_scn_thr(void *); 88 static int process_rsp(isns_pdu_t *, isns_rsp_t *); 89 static int isns_dev_attr_reg(int, tgt_node_t *, char *, char *); 90 static int isns_dev_attr_dereg(int, char *); 91 static int isns_scn_reg(int, char *); 92 static int isns_scn_dereg(int so, char *node); 93 static tgt_node_t *find_tgt_by_name(char *, char **); 94 static tgt_node_t *find_next_tgt(tgt_node_t *, char **); 95 static int isns_populate_and_update_server_info(Boolean_t state); 96 static int get_addr_family(char *node); 97 98 /* 99 * find_tgt_by_name searches DB by iscsi name or local name, if found 100 * returns tgt_node_t. iname needs to be free by caller. 101 */ 102 static tgt_node_t * 103 find_tgt_by_name(char *targ, char **iname) 104 { 105 tgt_node_t *tgt = NULL; 106 107 while ((tgt = tgt_node_next_child(targets_config, XML_ELEMENT_TARG, 108 tgt)) != NULL) { 109 if (tgt_find_value_str(tgt, XML_ELEMENT_INAME, iname) 110 == FALSE) { 111 syslog(LOG_ALERT, "ISNS: Missing iscsi name\n"); 112 break; 113 } 114 /* match either iscsi name or local name */ 115 if (strcmp(targ, tgt->x_value) == 0 || 116 strcmp(targ, *iname) == 0) { 117 return (tgt); 118 } 119 free(*iname); 120 } 121 return (NULL); 122 } 123 124 static tgt_node_t * 125 find_next_tgt(tgt_node_t *tgt, char **iname) 126 { 127 while ((tgt = tgt_node_next_child(targets_config, XML_ELEMENT_TARG, 128 tgt)) != NULL) { 129 if (tgt_find_value_str(tgt, XML_ELEMENT_INAME, iname) 130 == FALSE) { 131 continue; 132 } 133 return (tgt); 134 } 135 return (NULL); 136 } 137 138 /* 139 * Find ip-addr associated with TPGT, don't send if no ip-addr is 140 * found for a TPGT 141 */ 142 static int 143 append_tpgt(tgt_node_t *tgt, isns_pdu_t *cmd) 144 { 145 tgt_node_t *t, *x; 146 tgt_node_t *pgt = NULL; 147 tgt_node_t *iplist = NULL; 148 tgt_node_t *tpgt = NULL; 149 ip_t eid; 150 151 /* Always add the default TPGT (1) */ 152 (void) isns_append_attr(cmd, ISNS_PG_TAG_ATTR_ID, ISNS_PG_TAG_SZ, NULL, 153 1); 154 if (isns_append_attr(cmd, ISNS_PG_PORTAL_IP_ADDR_ATTR_ID, 155 eid_ip.ai_addrlen, (void *)&eid_ip.ip_adr, 156 eid_ip.ip_len) != 0) { 157 return (-1); 158 } 159 if (isns_append_attr(cmd, ISNS_PG_PORTAL_PORT_ATTR_ID, 160 ISNS_PORT_SZ, NULL, iscsi_port) != 0) { 161 return (-1); 162 } 163 164 /* Get the remainning TPGT-LIST */ 165 if ((t = tgt_node_next(tgt, XML_ELEMENT_TPGTLIST, NULL)) 166 != NULL) { 167 /* find tgpt from tpgt-list */ 168 while ((pgt = tgt_node_next(t, XML_ELEMENT_TPGT, pgt)) 169 != NULL) { 170 /* update isns only if TPGT contains ip_addr */ 171 while ((tpgt = tgt_node_next_child(main_config, 172 XML_ELEMENT_TPGT, tpgt)) != NULL) { 173 if (strcmp(pgt->x_value, tpgt->x_value) != 0) 174 continue; 175 if ((iplist = tgt_node_next(tpgt, 176 XML_ELEMENT_IPADDRLIST, NULL)) != NULL) 177 break; 178 } 179 if (tpgt == NULL || iplist == NULL) 180 continue; 181 if (isns_append_attr(cmd, ISNS_PG_TAG_ATTR_ID, 182 ISNS_PG_TAG_SZ, NULL, 183 strtol(pgt->x_value, NULL, 0)) != 0) { 184 return (-1); 185 } 186 187 /* get ip-addr & port */ 188 for (x = iplist->x_child; x; x = x->x_sibling) { 189 if (get_ip_addr(x->x_value, &eid) < 0) 190 continue; 191 if (isns_append_attr(cmd, 192 ISNS_PG_PORTAL_IP_ADDR_ATTR_ID, 193 eid.ai_addrlen, (void *)&eid.ip_adr, 194 eid.ip_len) != 0) { 195 return (-1); 196 } 197 if (isns_append_attr(cmd, 198 ISNS_PG_PORTAL_PORT_ATTR_ID, 199 ISNS_PORT_SZ, NULL, iscsi_port) != 0) { 200 return (-1); 201 } 202 } 203 } 204 } 205 206 return (0); 207 } 208 209 /* 210 * process_scn() 211 * -Added/Updated object: nop, initiator is verified during connect 212 * 213 * -Removed object: logout_targ if still connected 214 * 215 * RFC 4171 section 5.6.5.9 216 * destination attribute is always the 1st attribute in the SCN message, 217 * then follows by SCN_BITMAP(35) & Source_Attribute(32) 218 */ 219 static void 220 process_scn(int so, isns_pdu_t *scn) 221 { 222 uint8_t *ptr = scn->payload; 223 isns_tlv_t *tlv; 224 uint16_t cnt = 0; 225 uint32_t got_dest = 0; 226 uint32_t got_source = 0; 227 uint32_t bitmap = 0; 228 uint32_t got_bitmap = 0; 229 char dest[MAXNAMELEN]; 230 char source[MAXNAMELEN]; 231 232 queue_prt(mgmtq, Q_ISNS_DBG, "PROCESS_SCN %u\n", 233 scn->payload_len); 234 235 if (scn->payload_len < TAG_LEN_SZ) { 236 syslog(LOG_ALERT, "ISNS SCN message error\n"); 237 return; 238 } 239 240 while (cnt < scn->payload_len) { 241 /* LINTED */ 242 tlv = (isns_tlv_t *)ptr; 243 tlv->attr_id = ntohl(tlv->attr_id); 244 tlv->attr_len = ntohl(tlv->attr_len); 245 queue_prt(mgmtq, Q_ISNS_DBG, "PROCESS_SCN %u %u\n", 246 tlv->attr_id, tlv->attr_len); 247 /* 248 * devAttrQry the source attribute, process if node_type 249 * is initiator 250 */ 251 switch (tlv->attr_id) { 252 case ISNS_ISCSI_NAME_ATTR_ID: 253 if (got_dest == 0) { 254 bcopy(tlv->attr_value, dest, 255 tlv->attr_len); 256 queue_prt(mgmtq, Q_ISNS_DBG, 257 "PROCESS_SCN dest %s\n", dest); 258 got_dest = 1; 259 } else { 260 bcopy(tlv->attr_value, source, 261 tlv->attr_len); 262 queue_prt(mgmtq, Q_ISNS_DBG, 263 "PROCESS_SCN source %s\n", source); 264 got_source = 1; 265 } 266 break; 267 case ISNS_ISCSI_SCN_BITMAP_ATTR_ID: 268 bcopy(tlv->attr_value, &bitmap, tlv->attr_len); 269 bitmap = ntohl(bitmap); 270 queue_prt(mgmtq, Q_ISNS_DBG, 271 "PROCESS_SCN bitmap %u\n", bitmap); 272 got_bitmap = 1; 273 break; 274 default: 275 queue_prt(mgmtq, Q_ISNS_DBG, 276 "PROCESS_SCN DEFAULT\n"); 277 break; 278 } 279 280 if (got_source && !got_bitmap) { 281 queue_prt(mgmtq, Q_ISNS_DBG, 282 "process_scn: message out-of-order\n"); 283 return; 284 } 285 286 if (got_source && got_bitmap) { 287 switch (bitmap) { 288 case ISNS_OBJ_ADDED: 289 case ISNS_OBJ_UPDATED: 290 queue_prt(mgmtq, Q_ISNS_DBG, 291 "PROCESS_SCN OBJ ADDED"); 292 (void) isns_update(); 293 break; 294 case ISNS_OBJ_REMOVED: 295 queue_prt(mgmtq, Q_ISNS_DBG, 296 "PROCESS_SCN OBJ REMOVED"); 297 /* logout target */ 298 if (got_dest == 0) { 299 syslog(LOG_ALERT, 300 "ISNS protocol error\n"); 301 continue; 302 } 303 logout_targ(dest); 304 break; 305 default: 306 break; 307 } 308 309 /* clear got_xxx */ 310 got_source = 0; 311 got_bitmap = 1; 312 } 313 314 /* next attribute */ 315 cnt += ISNS_ATTR_SZ(tlv->attr_len); 316 ptr += ISNS_ATTR_SZ(tlv->attr_len); 317 } 318 queue_prt(mgmtq, Q_ISNS_DBG, "DONE PROCESS_SCN\n"); 319 } 320 321 /* 322 * Process ESI requires a success response only 323 */ 324 static void 325 process_esi(int so, isns_pdu_t *esi) 326 { 327 isns_rsp_t *cmd; 328 int pl_len; 329 330 if (isns_create_pdu(ISNS_ESI_RSP, 0, (isns_pdu_t **)&cmd) != 0) { 331 return; 332 } 333 334 pl_len = esi->payload_len + ISNS_STATUS_SZ; 335 if (pl_len > MAX_PDU_PAYLOAD_SZ) { 336 syslog(LOG_ALERT, "process_esi: payload size exceeded"); 337 isns_free_pdu(cmd); 338 return; 339 } 340 341 /* change the xid to the request xid */ 342 cmd->xid = htons(esi->xid); 343 cmd->status = htonl(ISNS_RSP_SUCCESSFUL); 344 345 /* copy original data */ 346 bcopy(esi->payload, cmd->data, esi->payload_len); 347 cmd->pdu_len = htons(pl_len); 348 349 if (isns_send(so, (isns_pdu_t *)cmd) < 0) { 350 syslog(LOG_ALERT, "process_esi failed to isns_send"); 351 } 352 353 isns_free_pdu(cmd); 354 } 355 356 static int 357 is_isns_server_up(char *server) { 358 int so; 359 socklen_t len; 360 struct sockaddr sa; 361 362 /* no server specified */ 363 if (server == NULL) { 364 return (-1); 365 } 366 /* 367 * open isns server connect and determine which PF_INET to use 368 */ 369 if ((so = isns_open(server)) < 0) { 370 syslog(LOG_ERR, 371 "isns server %s not found", 372 server); 373 return (-1); 374 } 375 len = sizeof (sa); 376 if (getsockname(so, &sa, &len) < 0) { 377 isns_close(so); 378 syslog(LOG_ALERT, 379 "isns getsockname failed"); 380 return (-1); 381 } 382 isns_close(so); 383 384 if (sa.sa_family != PF_INET && 385 sa.sa_family != PF_INET6) { 386 syslog(LOG_ERR, 387 "isns unknown domain type"); 388 return (-1); 389 } 390 return (0); 391 } 392 393 /* 394 * This thread sit's in a loop and ensures that it keeps checking for 395 * connection to isns_server. Once the connection works it registers 396 * with the isns and bails out. 397 * We expect the isns server to be fault taulerant and has persistence 398 * for the registered entries. 399 */ 400 static void * 401 isns_server_connection_thr(void *arg) 402 { 403 Boolean_t registered_targets = False; 404 char server[MAXHOSTNAMELEN + 1] = {0}; 405 406 while (isns_shutdown == False && 407 connection_thr_bail_out == False) { 408 /* current server */ 409 (void) strcpy(server, isns_args.server); 410 411 if (is_isns_server_up(server) == 0) { 412 if (registered_targets == False) { 413 /* 414 * register all targets, what happens if 415 * no targets are created yet? this should 416 * not be a failure, when new target gets 417 * created, update gets call. what if SCN 418 * register fails? 419 */ 420 if (isns_reg_all() == 0) { 421 /* scn register all targets */ 422 if (isns_op_all(ISNS_SCN_REG) != 0) { 423 syslog(LOG_ERR, 424 "SCN registrations" 425 " failed\n"); 426 (void) isns_op_all( 427 ISNS_DEV_DEREG); 428 registered_targets = False; 429 } else { 430 registered_targets = True; 431 break; 432 } 433 } 434 } 435 } else { 436 syslog(LOG_INFO, 437 "isns server %s is not reachable", 438 server); 439 registered_targets = False; 440 } 441 (void) sleep(ISNS_SLEEP_SECS); 442 /* If isns was disabled, deregister and close the thread */ 443 if (isns_enabled() == False) { 444 syslog(LOG_INFO, 445 "isns server is disabled, dergister target"); 446 isns_fini(); 447 break; 448 } 449 450 } 451 queue_message_set(mgmtq, 0, msg_pthread_join, 452 (void *)(uintptr_t)pthread_self()); 453 454 return (NULL); 455 } 456 457 /* 458 * esi_scn_thr() is the thread creates an end point to receive and process 459 * ESI & SCN messages. This thread is created when isns_access is enabled 460 * and for the duration of the iscsi daemon 461 */ 462 static void * 463 esi_scn_thr(void *arg) 464 { 465 struct sockaddr sa, *ai; 466 struct sockaddr_in sin; 467 struct sockaddr_in6 sin6; 468 int so, fd, pf; 469 socklen_t len; 470 char strport[NI_MAXSERV]; 471 isns_pdu_t *scn = NULL; 472 struct timeval timeout; 473 fd_set fdset; 474 int socket_ready = 0; 475 476 pf = get_addr_family(isns_args.entity); 477 if (pf == PF_INET) { 478 bzero(&sin, sizeof (sin)); 479 sin.sin_family = PF_INET; 480 sin.sin_port = htons(0); 481 sin.sin_addr.s_addr = INADDR_ANY; 482 ai = (struct sockaddr *)&sin; 483 len = sizeof (sin); 484 } else if (pf == PF_INET6) { 485 bzero(&sin6, sizeof (sin6)); 486 sin6.sin6_family = PF_INET6; 487 sin6.sin6_port = htons(0); 488 sin6.sin6_addr = in6addr_any; 489 ai = (struct sockaddr *)&sin6; 490 len = sizeof (sin6); 491 } else { 492 syslog(LOG_ERR, "Bad address family. Exit esi_scn_thr"); 493 return (NULL); 494 } 495 496 /* 497 * create and bind SCN socket 498 * save the scn port info 499 */ 500 if ((so = socket(pf, SOCK_STREAM, 0)) == -1) { 501 syslog(LOG_ALERT, "create isns socket failed"); 502 return (NULL); 503 } 504 505 (void) setsockopt(so, SOL_SOCKET, SO_REUSEADDR, 0, 0); 506 507 if (bind(so, ai, len) < 0) { 508 syslog(LOG_ALERT, "esi_scn_thr: bind failed"); 509 (void) close(so); 510 return (NULL); 511 } 512 513 /* get scn port info */ 514 len = sizeof (sa); 515 if (getsockname(so, &sa, &len) < 0) { 516 syslog(LOG_ALERT, "isns getsockname failed"); 517 (void) close(so); 518 return (NULL); 519 } 520 if (getnameinfo(&sa, len, NULL, 0, strport, NI_MAXSERV, 521 NI_NUMERICSERV) != 0) { 522 syslog(LOG_ALERT, "isns getnameinfo failed"); 523 (void) close(so); 524 return (NULL); 525 } 526 scn_port = atoi(strport); 527 528 529 if (listen(so, 5) < 0) { 530 syslog(LOG_ALERT, "esi_scn_thr: failed listen"); 531 (void) close(so); 532 return (NULL); 533 } 534 535 /* listen for esi or scn messages */ 536 while (isns_shutdown == False) { 537 /* ISNS_ESI_INTERVAL_ATTR_ID is set to 10s */ 538 timeout.tv_sec = 10; 539 timeout.tv_usec = 0; 540 FD_ZERO(&fdset); 541 FD_SET(so, &fdset); 542 543 socket_ready = select(so + 1, &fdset, NULL, NULL, &timeout); 544 545 /* If disabled bail out, dont care about packets */ 546 if (isns_enabled() == False) { 547 syslog(LOG_INFO, 548 "isns server is disabled, dergister target"); 549 isns_fini(); 550 (void) close(so); 551 return (NULL); 552 } 553 554 if (socket_ready < 0) { 555 syslog(LOG_ERR, 556 "esi_scn_thr: select failed, retrying."); 557 continue; 558 } else if (socket_ready == 0) { /* timeout */ 559 continue; 560 } else { 561 /* Socket is ready */ 562 if ((fd = accept(so, &sa, &len)) < 0) { 563 syslog(LOG_ALERT, "esi_scn_thr: failed accept"); 564 continue; 565 } 566 } 567 if (isns_recv(fd, (isns_rsp_t **)&scn) == 0) { 568 /* Just return success for ESI */ 569 switch (scn->func_id) { 570 case ISNS_ESI: 571 process_esi(fd, scn); 572 break; 573 case ISNS_SCN: 574 /* call the SCN process function */ 575 process_scn(fd, scn); 576 break; 577 default: 578 syslog(LOG_ERR, 579 "esi_scn_thr: Invalid funcid %d\n", 580 scn->func_id); 581 break; 582 } 583 /* free response resource */ 584 isns_free_pdu(scn); 585 } else { 586 syslog(LOG_ALERT, "esi_scn_thr fails isns_recv "); 587 } 588 589 (void) close(fd); 590 } 591 (void) close(so); 592 return (NULL); 593 } 594 595 /* 596 * Perform operation on all targets 597 */ 598 static int 599 isns_op_all(uint16_t op) 600 { 601 int so; 602 tgt_node_t *tgt = NULL; 603 char *iname; 604 605 if (isns_server_connection_thr_running == False) { 606 syslog(LOG_ERR, 607 "isns_op_all: iSNS discovery is not running." 608 " Check the previous iSNS initialization error."); 609 return (-1); 610 } 611 612 if ((so = isns_open(isns_args.server)) == -1) { 613 syslog(LOG_ERR, "isns_op_all: failed to open isns server %s", 614 isns_args.server); 615 return (-1); 616 } 617 618 while ((tgt = tgt_node_next_child(targets_config, XML_ELEMENT_TARG, 619 tgt)) != NULL) { 620 if (tgt_find_value_str(tgt, XML_ELEMENT_INAME, &iname) 621 == FALSE) { 622 continue; 623 } 624 625 switch (op) { 626 case ISNS_DEV_DEREG: 627 if (isns_dev_attr_dereg(so, iname) == -1) { 628 syslog(LOG_ERR, 629 "ISNS de-register failed\n"); 630 } 631 num_reg = 0; 632 break; 633 case ISNS_SCN_DEREG: 634 if (isns_scn_dereg(so, iname) == -1) { 635 syslog(LOG_ERR, 636 "ISNS SCN de-register failed\n"); 637 } 638 break; 639 case ISNS_SCN_REG: 640 if (isns_scn_reg(so, iname) == -1) { 641 syslog(LOG_ERR, 642 "ISNS SCN register failed\n"); 643 } 644 break; 645 case ISNS_TGT_LOGOUT: 646 logout_targ(iname); 647 break; 648 default: 649 break; 650 } 651 652 free(iname); 653 } 654 isns_close(so); 655 return (0); 656 } 657 658 static int 659 isns_populate_and_update_server_info(Boolean_t update) { 660 char *isns_srv, *isns_port; 661 int retcode = 0; 662 663 /* get isns server info */ 664 (void) tgt_find_value_str(main_config, XML_ELEMENT_ISNS_SERV, 665 &isns_srv); 666 if (isns_srv == NULL) { 667 syslog(LOG_INFO, 668 "The server has not been setup, " 669 "but enabling the isns access"); 670 retcode = -1; 671 return (retcode); 672 } 673 isns_port = strchr(isns_srv, ':'); 674 if (isns_port == NULL) { 675 isns_args.isns_port = ISNS_DEFAULT_SERVER_PORT; 676 } else { 677 isns_args.isns_port = strtoul(isns_port + 1, NULL, 0); 678 if (isns_args.isns_port == 0) { 679 isns_args.isns_port = ISNS_DEFAULT_SERVER_PORT; 680 } 681 *isns_port = '\0'; 682 } 683 684 if (update == True) { 685 /* isns_server changed */ 686 if (strcmp(isns_srv, isns_args.server) != 0) { 687 /* de-reg from old iSNS server if it is setup */ 688 syslog(LOG_INFO, 689 "Detected a new isns server, deregistering" 690 " %s", isns_args.server); 691 (void) isns_dereg_all(); 692 (void) strcpy(isns_args.server, isns_srv); 693 /* Register with the new server */ 694 if (isns_reg_all() == 0) { 695 /* scn register all targets */ 696 if (isns_op_all(ISNS_SCN_REG) != 0) { 697 syslog(LOG_ERR, 698 "SCN registrations failed\n"); 699 (void) isns_op_all(ISNS_DEV_DEREG); 700 retcode = -1; 701 } 702 } 703 } 704 } else { 705 (void) strcpy(isns_args.server, isns_srv); 706 } 707 free(isns_srv); 708 return (retcode); 709 } 710 711 /* 712 * isns_init() needs to be call before all ISNS operations. 713 * Save the isns_server & entity name. 714 * Start esi_scn_thr to receive ESI & SCN messages 715 */ 716 int 717 isns_init(target_queue_t *q) 718 { 719 if (q != NULL) 720 mgmtq = q; 721 722 if (isns_enabled() == False) 723 return (0); 724 725 /* get local hostname for entity usage */ 726 if ((gethostname(isns_args.entity, MAXHOSTNAMELEN) < 0) || 727 (get_ip_addr(isns_args.entity, &eid_ip) < 0)) { 728 syslog(LOG_ERR, "isns_init: failed to get host name or host ip" 729 " address for ENTITY properties"); 730 return (-1); 731 } 732 733 isns_shutdown = False; 734 735 (void) isns_populate_and_update_server_info(False); 736 if (pthread_create(&scn_tid, NULL, 737 esi_scn_thr, (void *)&isns_args) != 738 0) { 739 syslog(LOG_ALERT, "isns_init failed to pthread_create"); 740 (void) pthread_kill(isns_tid, SIGKILL); 741 return (-1); 742 } 743 744 if (pthread_create(&isns_tid, NULL, isns_server_connection_thr, 745 (void *)NULL) != 0) { 746 syslog(LOG_ALERT, 747 "isns_init failed to create the " 748 "isns connection thr"); 749 return (-1); 750 } 751 752 isns_server_connection_thr_running = True; 753 return (0); 754 } 755 756 /* 757 * isns_update gets call on modify_admin, this is changes to 758 * isns access and/or isns server 759 */ 760 int 761 isns_update() 762 { 763 Boolean_t is_isns_enabled = isns_enabled(); 764 /* 765 * If the isns thread was not started before and we are going 766 * enabled from disabled start the threads. 767 */ 768 if (isns_server_connection_thr_running == False) { 769 if (is_isns_enabled == True) { 770 if (isns_init(NULL) != 0) { 771 return (-1); 772 } else { 773 return (0); 774 } 775 } else { 776 syslog(LOG_INFO, 777 "isns_update: isns is disabled"); 778 } 779 } else { 780 /* 781 * isns is disabled after enabled, 782 * log off all targets and fini isns service 783 */ 784 if (is_isns_enabled == False) { 785 isns_shutdown = True; 786 /* pthread_join for the isns thread */ 787 (void) pthread_join(isns_tid, NULL); 788 (void) pthread_join(scn_tid, NULL); 789 isns_server_connection_thr_running = False; 790 } else { 791 /* 792 * Incase the original thread is still running 793 * we should reap it 794 */ 795 connection_thr_bail_out = True; 796 (void) pthread_join(isns_tid, NULL); 797 connection_thr_bail_out = False; 798 799 /* 800 * Read the configuration file incase the server 801 * has changed. 802 */ 803 if (isns_populate_and_update_server_info(True) == -1) { 804 return (-1); 805 } 806 } 807 } 808 return (0); 809 } 810 811 /* 812 * isns_fini is called when isns access is disabled 813 */ 814 void 815 isns_fini() 816 { 817 /* 818 * de-register all targets 1st, this prevents initiator from 819 * logging back in 820 */ 821 (void) isns_op_all(ISNS_SCN_DEREG); 822 (void) isns_op_all(ISNS_DEV_DEREG); 823 824 /* log off all targets */ 825 (void) isns_op_all(ISNS_TGT_LOGOUT); 826 } 827 828 static int 829 get_addr_family(char *node) { 830 struct addrinfo *ai = NULL; 831 int ret; 832 833 if ((ret = getaddrinfo(node, NULL, NULL, &ai)) != 0) { 834 syslog(LOG_ALERT, "get_addr_family: server %s not found : %s", 835 node, gai_strerror(ret)); 836 return (-1); 837 } 838 ret = ai->ai_family; 839 freeaddrinfo(ai); 840 return (ret); 841 } 842 843 static int 844 get_ip_addr(char *node, ip_t *sa) 845 { 846 struct addrinfo *ai = NULL, *aip; 847 struct sockaddr_in *sin; 848 struct sockaddr_in6 *sin6; 849 int ret; 850 851 if ((ret = getaddrinfo(node, NULL, NULL, &ai)) != 0) { 852 syslog(LOG_ALERT, "get_ip_addr: %s not found : %s", 853 node, gai_strerror(ret)); 854 return (-1); 855 } 856 857 bzero(sa, sizeof (ip_t)); 858 aip = ai; 859 do { 860 sa->ai_addrlen = aip->ai_addrlen; 861 sa->pf_family = aip->ai_family; 862 switch (aip->ai_family) { 863 case PF_INET: 864 /* LINTED */ 865 sin = (struct sockaddr_in *)aip->ai_addr; 866 sa->ip_len = sizeof (in_addr_t); 867 bcopy(&sin->sin_addr, (void *)&sa->ip_adr.in, 868 sa->ip_len); 869 freeaddrinfo(ai); 870 return (0); 871 case PF_INET6: 872 /* LINTED */ 873 sin6 = (struct sockaddr_in6 *)aip->ai_addr; 874 sa->ip_len = sizeof (in6_addr_t); 875 bcopy(&sin6->sin6_addr, &sa->ip_adr.in6, 876 sa->ip_len); 877 freeaddrinfo(ai); 878 return (0); 879 default: 880 continue; 881 } 882 } while ((aip = aip->ai_next) != NULL); 883 884 freeaddrinfo(ai); 885 return (-1); 886 } 887 888 /* 889 * Process isns response, need to verify same transaction id, func_id 890 * as the isns command, the isns command is in network byte order, 891 * the isns response is in host byte order 892 */ 893 static int 894 process_rsp(isns_pdu_t *cmd, isns_rsp_t *rsp) 895 { 896 queue_prt(mgmtq, Q_ISNS_DBG, "PROCESS_RSP"); 897 /* 898 * Process responses: 899 * -verify sucessful response 900 * -verify match xid 901 * -process operating attributes 902 * For DevAttrReg & DevAttrQry and most isns command, 903 * the response func_id is command_func_id | 0x8000. 904 */ 905 rsp->status = ntohl(rsp->status); 906 if (rsp->status != ISNS_RSP_SUCCESSFUL || 907 rsp->xid != ntohs(cmd->xid) || 908 rsp->func_id != (ntohs(cmd->func_id) | 0x8000)) { 909 queue_prt(mgmtq, Q_ISNS_DBG, 910 "cmd failed with: status= %d xid= %d %d "\ 911 "response attribute %x\n", rsp->status, rsp->xid,\ 912 ntohs(cmd->xid), rsp->func_id); 913 return (-1); 914 } 915 916 return (0); 917 } 918 919 /* 920 * DevAttrDereg 921 */ 922 static int 923 isns_dev_attr_dereg(int so, char *node) 924 { 925 isns_pdu_t *cmd = NULL; 926 isns_rsp_t *rsp = NULL; 927 uint32_t flags = 0; 928 int ret = -1; 929 930 queue_prt(mgmtq, Q_ISNS_DBG, "ISNS_DEV_ATTR_DEREG"); 931 932 if (isns_create_pdu(ISNS_DEV_DEREG, flags, &cmd) != 0) { 933 return (-1); 934 } 935 936 /* add source attribute */ 937 if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, 938 STRLEN(node), node, 0) != 0) { 939 goto error; 940 } 941 942 /* add delimiter */ 943 if (isns_append_attr(cmd, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0) != 0) { 944 goto error; 945 } 946 947 /* add operation attributes */ 948 if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, 949 STRLEN(node), node, 0) != 0) { 950 goto error; 951 } 952 953 /* send pdu */ 954 if (isns_send(so, cmd) == -1) { 955 syslog(LOG_ERR, "isns_dev_attr_dereg fails isns_send"); 956 goto error; 957 } 958 959 /* get isns response */ 960 if (isns_recv(so, &rsp) == -1) { 961 syslog(LOG_ERR, "isns_dev_attr_dereg fails isns_recv "); 962 goto error; 963 } 964 965 /* process response */ 966 if (process_rsp(cmd, rsp) == 0) { 967 /* 968 * Keep the num_reg to a non-negative number. 969 * num_reg is used to keep track of whether there was 970 * any registration occurred or not. Deregstration should 971 * be followed by registration but in case dereg occurs 972 * and somehow it is succeeded keeping num_reg to 0 prevent 973 * any negative effect on subsequent registration. 974 */ 975 if (num_reg > 0) num_reg--; 976 ret = 0; 977 } 978 979 error: 980 /* Free all resouces here */ 981 if (cmd) 982 isns_free_pdu(cmd); 983 if (rsp) 984 isns_free_pdu(rsp); 985 return (ret); 986 } 987 988 /* 989 * Register a new node, need to find another node that is already registered 990 * DevAttrReg 991 * RFC 4171 Section 5.6.5.5 indicated SCN-port-tag (23) needed to be 992 * included in the registration 993 * Also need to register ESI-port-tag (20) see Section 6.3.5 994 */ 995 static int 996 isns_dev_attr_reg(int so, tgt_node_t *tgt, char *node, char *alias) 997 { 998 isns_pdu_t *cmd = NULL; 999 isns_rsp_t *rsp = NULL; 1000 uint32_t flags = 0; 1001 int ret = 0; 1002 Boolean_t found = False; 1003 tgt_node_t *src = NULL; 1004 char *src_nm = NULL; 1005 1006 queue_prt(mgmtq, Q_ISNS_DBG, "ISNS_DEV_ATTR_REG"); 1007 1008 if ((so = isns_open(isns_args.server)) == -1) { 1009 return (-1); 1010 } 1011 1012 if (num_reg == 0) { 1013 flags |= ISNS_FLAG_REPLACE_REG; 1014 } 1015 1016 if (isns_create_pdu(ISNS_DEV_ATTR_REG, flags, &cmd) != 0) { 1017 return (-1); 1018 } 1019 1020 if (num_reg == 0) { 1021 /* add new node to source attribute */ 1022 if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, 1023 STRLEN(node), node, 0) != 0) { 1024 goto error; 1025 } 1026 } else { 1027 /* find a registered node to use */ 1028 do { 1029 src = find_next_tgt(src, &src_nm); 1030 if (src == NULL) { 1031 syslog(LOG_ALERT, "ISNS out of sync\n"); 1032 goto error; 1033 } 1034 if (tgt == src) { 1035 free(src_nm); 1036 src_nm = NULL; 1037 continue; 1038 } else { 1039 found = True; 1040 } 1041 } while (found == False); 1042 1043 if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, 1044 STRLEN(src_nm), src_nm, 0) != 0) { 1045 goto error; 1046 } 1047 } 1048 1049 /* add message key attribute */ 1050 if (isns_append_attr(cmd, ISNS_EID_ATTR_ID, 1051 STRLEN(isns_args.entity), isns_args.entity, 0) != 0) { 1052 goto error; 1053 } 1054 1055 /* add delimiter */ 1056 if (isns_append_attr(cmd, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0) != 0) { 1057 goto error; 1058 } 1059 1060 /* add operation attributes */ 1061 1062 /* entity id */ 1063 if (isns_append_attr(cmd, ISNS_EID_ATTR_ID, 1064 STRLEN(isns_args.entity), isns_args.entity, 0) != 0) { 1065 goto error; 1066 } 1067 1068 /* entity type */ 1069 if (isns_append_attr(cmd, ISNS_ENTITY_PROTOCOL_ATTR_ID, 1070 ISNS_ENTITY_TYP_SZ, NULL, ISNS_ENTITY_PROTOCOL_ISCSI) != 0) { 1071 goto error; 1072 } 1073 1074 /* 1075 * Register entity portal properties the 1st time 1076 */ 1077 if (num_reg == 0) { 1078 /* portal ip-addr */ 1079 if (isns_append_attr(cmd, ISNS_PORTAL_IP_ADDR_ATTR_ID, 1080 eid_ip.ai_addrlen, (void *)&eid_ip.ip_adr, 1081 eid_ip.ip_len) != 0) { 1082 goto error; 1083 } 1084 1085 /* portal port */ 1086 if (isns_append_attr(cmd, ISNS_PORTAL_PORT_ATTR_ID, 1087 ISNS_PORT_SZ, NULL, iscsi_port) != 0) { 1088 goto error; 1089 } 1090 1091 /* ESI interval */ 1092 if (isns_append_attr(cmd, ISNS_ESI_INTERVAL_ATTR_ID, 1093 ISNS_ESI_TICK_SZ, NULL, 10) != 0) { 1094 goto error; 1095 } 1096 1097 /* scn port */ 1098 if (isns_append_attr(cmd, ISNS_SCN_PORT_ATTR_ID, 1099 ISNS_PORT_SZ, NULL, scn_port) != 0) { 1100 goto error; 1101 } 1102 1103 /* esi port */ 1104 if (isns_append_attr(cmd, ISNS_ESI_PORT_ATTR_ID, 1105 ISNS_PORT_SZ, NULL, scn_port) != 0) { 1106 goto error; 1107 } 1108 } 1109 1110 /* iscsi node name */ 1111 if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, 1112 STRLEN(node), node, 0) != 0) { 1113 goto error; 1114 } 1115 1116 /* iscsi node type */ 1117 if (isns_append_attr(cmd, ISNS_ISCSI_NODE_TYPE_ATTR_ID, 1118 ISNS_NODE_TYP_SZ, NULL, ISNS_TARGET_NODE_TYPE) != 0) { 1119 goto error; 1120 } 1121 1122 /* iscsi node alias */ 1123 if (isns_append_attr(cmd, ISNS_ISCSI_ALIAS_ATTR_ID, 1124 STRLEN(alias), alias, 0) != 0) { 1125 goto error; 1126 } 1127 1128 /* PGT */ 1129 if (append_tpgt(tgt, cmd) != 0) { 1130 goto error; 1131 } 1132 1133 /* send pdu */ 1134 if (isns_send(so, cmd) == -1) { 1135 goto error; 1136 } 1137 1138 /* get isns response */ 1139 if (isns_recv(so, &rsp) == -1) { 1140 goto error; 1141 } 1142 1143 /* process response */ 1144 if ((ret = process_rsp(cmd, rsp)) == 0) { 1145 num_reg++; 1146 } 1147 1148 error: 1149 /* Free all resouces here */ 1150 if (cmd) 1151 isns_free_pdu(cmd); 1152 if (rsp) 1153 isns_free_pdu(rsp); 1154 if (src_nm) 1155 free(src_nm); 1156 return (ret); 1157 } 1158 1159 /* 1160 * DevAttrQry for iscsi initiator 1161 * See RFC 4171 Sect. 5.6.5.2 for query detail 1162 */ 1163 static int 1164 isns_dev_attr_qry(int so, char *target, char *initiator) 1165 { 1166 isns_pdu_t *cmd; 1167 isns_rsp_t *rsp; 1168 uint32_t flags = 0; 1169 int ret = -1; 1170 size_t remain; 1171 isns_tlv_t *tlv; 1172 uint8_t *ptr; 1173 1174 queue_prt(mgmtq, Q_ISNS_DBG, "ISNS_DEV_ATTR_QRY"); 1175 1176 if (isns_create_pdu(ISNS_DEV_ATTR_QRY, flags, &cmd) != 0) { 1177 return (-1); 1178 } 1179 1180 /* source attribute */ 1181 if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, 1182 STRLEN(target), target, 0) == -1) { 1183 goto error; 1184 } 1185 1186 /* message key attribute */ 1187 /* iscsi initiator node type */ 1188 if (isns_append_attr(cmd, ISNS_ISCSI_NODE_TYPE_ATTR_ID, 1189 ISNS_NODE_TYP_SZ, NULL, ISNS_INITIATOR_NODE_TYPE) == -1) { 1190 goto error; 1191 } 1192 1193 /* delimiter */ 1194 if (isns_append_attr(cmd, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0) == -1) { 1195 goto error; 1196 } 1197 1198 /* 1199 * operating attributes 1200 * Query Iscsi initiator with zero length TLV operating 1201 * attribute 1202 */ 1203 1204 /* iscsi name */ 1205 if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, 1206 0, NULL, 0) != 0) { 1207 goto error; 1208 } 1209 1210 if (isns_send(so, cmd) == -1) { 1211 syslog(LOG_ERR, "isns_dev_attr_qry fails isns_send"); 1212 goto error; 1213 } 1214 1215 /* recv response */ 1216 if (isns_recv(so, &rsp) == -1) { 1217 syslog(LOG_ERR, "isns_dev_attr_qry fails isns_recv "); 1218 goto error; 1219 } 1220 1221 /* process response */ 1222 if ((ret = process_rsp(cmd, rsp)) == 0) { 1223 /* compare initiator name to the response, success if found */ 1224 /* subtract out status word */ 1225 remain = rsp->pdu_len - ISNS_STATUS_SZ; 1226 ptr = rsp->data; 1227 1228 while (remain > 0) { 1229 /* LINTED */ 1230 tlv = (isns_tlv_t *)ptr; 1231 1232 /* debug only */ 1233 print_ntoh_tlv(tlv); 1234 1235 /* process tag-len-value */ 1236 ntoh_tlv(tlv); 1237 /* 1238 * let's process the data, only interested 1239 * in iscsi name, skip everything else for 1240 * now. 1241 */ 1242 if (tlv->attr_id == ISNS_ISCSI_NAME_ATTR_ID) { 1243 if (strncmp((char *)tlv->attr_value, initiator, 1244 tlv->attr_len) == 0) { 1245 break; 1246 } 1247 } 1248 /* next tlv */ 1249 remain -= ISNS_ATTR_SZ(tlv->attr_len); 1250 ptr += ISNS_ATTR_SZ(tlv->attr_len); 1251 } 1252 ret = (remain > 0) ? 1 : 0; 1253 } 1254 1255 error: 1256 if (cmd) 1257 isns_free_pdu(cmd); 1258 if (rsp) 1259 isns_free_pdu(rsp); 1260 return (ret); 1261 } 1262 1263 /* 1264 * SCNReg 1265 * See RFC 4171 Section 5.6.5.5 1266 */ 1267 static int 1268 isns_scn_reg(int so, char *node) 1269 { 1270 isns_pdu_t *cmd; 1271 isns_rsp_t *rsp; 1272 uint32_t flags = 0; 1273 uint32_t bitmap = 0; 1274 int ret = -1; 1275 1276 queue_prt(mgmtq, Q_ISNS_DBG, "ISNS_SCN_REG"); 1277 1278 if (isns_create_pdu(ISNS_SCN_REG, flags, &cmd) != 0) { 1279 return (-1); 1280 } 1281 1282 /* source attribute */ 1283 if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, 1284 STRLEN(node), node, 0) == -1) { 1285 goto error; 1286 } 1287 1288 /* message key attribute */ 1289 /* iscsi initiator node name */ 1290 if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, 1291 STRLEN(node), node, 0) != 0) { 1292 goto error; 1293 } 1294 1295 /* delimiter */ 1296 if (isns_append_attr(cmd, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0) == -1) { 1297 goto error; 1298 } 1299 1300 /* SCN bitmap */ 1301 bitmap = ISNS_INIT_SELF_INFO_ONLY | ISNS_OBJ_REMOVED | 1302 ISNS_OBJ_ADDED | ISNS_OBJ_UPDATED; 1303 if (isns_append_attr(cmd, ISNS_ISCSI_SCN_BITMAP_ATTR_ID, 1304 ISNS_SCN_BITMAP_SZ, NULL, bitmap) == -1) { 1305 goto error; 1306 } 1307 1308 if (isns_send(so, cmd) == -1) { 1309 syslog(LOG_ERR, "isns_scn_reg fails isns_send"); 1310 goto error; 1311 } 1312 1313 if (isns_recv(so, &rsp) == -1) { 1314 syslog(LOG_ERR, "isns_scn_reg fails isns_recv "); 1315 goto error; 1316 } 1317 1318 /* process response */ 1319 if (process_rsp(cmd, rsp) == 0) { 1320 ret = 0; 1321 } 1322 1323 error: 1324 if (cmd) 1325 isns_free_pdu(cmd); 1326 if (rsp) 1327 isns_free_pdu(rsp); 1328 return (ret); 1329 } 1330 1331 1332 /* 1333 * SCNDereg 1334 */ 1335 static int 1336 isns_scn_dereg(int so, char *node) 1337 { 1338 isns_pdu_t *cmd = NULL; 1339 isns_rsp_t *rsp = NULL; 1340 uint32_t flags = 0; 1341 int ret = -1; 1342 1343 queue_prt(mgmtq, Q_ISNS_DBG, "ISNS_SCN_DEREG"); 1344 1345 if (isns_create_pdu(ISNS_SCN_DEREG, flags, &cmd) != 0) { 1346 return (-1); 1347 } 1348 1349 /* source attribute */ 1350 if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, 1351 STRLEN(node), node, 0) == -1) { 1352 goto error; 1353 } 1354 1355 /* message key attribute */ 1356 /* iscsi initiator node name */ 1357 if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, 1358 STRLEN(node), node, 0) != 0) { 1359 goto error; 1360 } 1361 1362 if (isns_append_attr(cmd, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0) == -1) { 1363 goto error; 1364 } 1365 1366 if (isns_send(so, cmd) == -1) { 1367 syslog(LOG_ERR, "isns_scn_reg fails isns_send"); 1368 goto error; 1369 } 1370 1371 if (isns_recv(so, &rsp) == -1) { 1372 syslog(LOG_ERR, "isns_scn_reg fails isns_recv "); 1373 goto error; 1374 } 1375 1376 /* process response */ 1377 if (process_rsp(cmd, rsp) == 0) { 1378 ret = 0; 1379 } 1380 1381 error: 1382 if (cmd) 1383 isns_free_pdu(cmd); 1384 if (rsp) 1385 isns_free_pdu(rsp); 1386 return (ret); 1387 } 1388 1389 /* 1390 * isns_reg is called to register new target 1391 */ 1392 int 1393 isns_reg(char *targ) 1394 { 1395 int so; 1396 tgt_node_t *tgt; 1397 char *iqn = NULL; 1398 1399 if (isns_server_connection_thr_running == False) { 1400 syslog(LOG_ERR, 1401 "isns_reg: iSNS discovery is not running." 1402 " Check the previous iSNS initialization error."); 1403 return (-1); 1404 } 1405 1406 if ((so = isns_open(isns_args.server)) == -1) { 1407 syslog(LOG_ERR, "isns_reg failed with server: %s", 1408 isns_args.server); 1409 return (-1); 1410 } 1411 1412 /* 1413 * Open targets_config and devAttrReg all nodes 1414 */ 1415 if ((tgt = find_tgt_by_name(targ, &iqn)) != NULL) { 1416 if (isns_dev_attr_reg(so, tgt, iqn, tgt->x_value) != 0) { 1417 syslog(LOG_ALERT, "ISNS registration failed %s\n", 1418 tgt->x_value); 1419 goto error; 1420 } 1421 if (isns_scn_reg(so, iqn) == -1) { 1422 syslog(LOG_ERR, "ISNS SCN register failed\n"); 1423 } 1424 } 1425 1426 error: 1427 if (iqn) 1428 free(iqn); 1429 isns_close(so); 1430 return (0); 1431 } 1432 1433 1434 /* 1435 * Register all iscsi target nodes from the XML database 1436 * Alway use the ISNS_FLAG_REPLACE_REG flag 1437 */ 1438 int 1439 isns_reg_all() 1440 { 1441 int so; 1442 uint32_t flags = ISNS_FLAG_REPLACE_REG; 1443 isns_pdu_t *cmd = NULL; 1444 isns_rsp_t *rsp = NULL; 1445 char *n = NULL; 1446 char *a = NULL; 1447 char alias[MAXNAMELEN]; 1448 char iname[MAXNAMELEN]; 1449 tgt_node_t *tgt = NULL; 1450 int ret = -1; 1451 int tgt_cnt = 0; 1452 1453 if (isns_server_connection_thr_running == False) { 1454 syslog(LOG_ERR, 1455 "isns_reg_all: iSNS discovery is not running." 1456 " Check the previous iSNS initialization error."); 1457 return (-1); 1458 } 1459 1460 /* 1461 * get the 1st target and use it for the source attribute 1462 */ 1463 if ((tgt = tgt_node_next_child(targets_config, XML_ELEMENT_TARG, tgt)) 1464 == NULL) { 1465 return (0); 1466 } 1467 if (tgt->x_value == NULL) { 1468 syslog(LOG_ALERT, "ISNS: target with NULL local name\n"); 1469 return (-1); 1470 } 1471 if (tgt_find_value_str(tgt, XML_ELEMENT_INAME, &n) 1472 == FALSE) { 1473 syslog(LOG_ALERT, "ISNS: no XML_ELEMENT_INAME found\n"); 1474 return (-1); 1475 } 1476 (void) strcpy(iname, n); 1477 free(n); 1478 if ((so = isns_open(isns_args.server)) == -1) { 1479 syslog(LOG_ALERT, "ISNS: fails to connect to %s\n", 1480 isns_args.server); 1481 return (-1); 1482 } 1483 1484 if (isns_create_pdu(ISNS_DEV_ATTR_REG, flags, &cmd) != 0) { 1485 goto error; 1486 } 1487 1488 /* source attribute */ 1489 if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, 1490 STRLEN(iname), iname, 0) != 0) { 1491 goto error; 1492 } 1493 1494 /* add message key attribute */ 1495 if (isns_append_attr(cmd, ISNS_EID_ATTR_ID, 1496 STRLEN(isns_args.entity), isns_args.entity, 0) != 0) { 1497 goto error; 1498 } 1499 1500 /* add delimiter */ 1501 if (isns_append_attr(cmd, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0) != 0) { 1502 goto error; 1503 } 1504 1505 /* entity id */ 1506 if (isns_append_attr(cmd, ISNS_EID_ATTR_ID, 1507 STRLEN(isns_args.entity), isns_args.entity, 0) != 0) { 1508 goto error; 1509 } 1510 1511 /* entity type */ 1512 if (isns_append_attr(cmd, ISNS_ENTITY_PROTOCOL_ATTR_ID, 1513 ISNS_ENTITY_TYP_SZ, NULL, ISNS_ENTITY_PROTOCOL_ISCSI) != 0) { 1514 goto error; 1515 } 1516 1517 /* portal ip-addr */ 1518 if (isns_append_attr(cmd, ISNS_PORTAL_IP_ADDR_ATTR_ID, 1519 eid_ip.ai_addrlen, (void *)&eid_ip.ip_adr, 1520 eid_ip.ip_len) != 0) { 1521 goto error; 1522 } 1523 1524 /* portal port */ 1525 if (isns_append_attr(cmd, ISNS_PORTAL_PORT_ATTR_ID, 1526 ISNS_PORT_SZ, NULL, iscsi_port) != 0) { 1527 goto error; 1528 } 1529 1530 /* ESI interval */ 1531 if (isns_append_attr(cmd, ISNS_ESI_INTERVAL_ATTR_ID, 1532 ISNS_ESI_TICK_SZ, NULL, 10) != 0) { 1533 goto error; 1534 } 1535 1536 1537 /* scn port */ 1538 if (isns_append_attr(cmd, ISNS_SCN_PORT_ATTR_ID, 1539 ISNS_PORT_SZ, NULL, scn_port) != 0) { 1540 goto error; 1541 } 1542 1543 /* esi port */ 1544 if (isns_append_attr(cmd, ISNS_ESI_PORT_ATTR_ID, 1545 ISNS_PORT_SZ, NULL, scn_port) != 0) { 1546 goto error; 1547 } 1548 1549 /* 1550 * Open targets_config and devAttrReg all nodes 1551 */ 1552 tgt = NULL; 1553 while ((tgt = tgt_node_next_child(targets_config, XML_ELEMENT_TARG, 1554 tgt)) != NULL) { 1555 if (tgt->x_value == NULL) { 1556 syslog(LOG_ALERT, "ISNS: target with NULL name\n"); 1557 continue; 1558 } 1559 /* use this value as alias if alias is not set */ 1560 (void) strcpy(alias, tgt->x_value); 1561 1562 if (tgt_find_value_str(tgt, XML_ELEMENT_INAME, &n) 1563 == FALSE) { 1564 continue; 1565 } 1566 (void) strcpy(iname, n); 1567 free(n); 1568 1569 /* find alias */ 1570 if (tgt_find_value_str(tgt, XML_ELEMENT_ALIAS, &a) 1571 == TRUE) { 1572 (void) strcpy(alias, a); 1573 free(a); 1574 } 1575 1576 tgt_cnt++; /* increment target count */ 1577 1578 /* operation attributes */ 1579 if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, 1580 STRLEN(iname), iname, 0) != 0) { 1581 goto error; 1582 } 1583 if (isns_append_attr(cmd, ISNS_ISCSI_NODE_TYPE_ATTR_ID, 1584 4, NULL, ISNS_TARGET_NODE_TYPE) != 0) { 1585 goto error; 1586 } 1587 if (isns_append_attr(cmd, ISNS_ISCSI_ALIAS_ATTR_ID, 1588 STRLEN(alias), alias, 0) != 0) { 1589 goto error; 1590 } 1591 1592 if (append_tpgt(tgt, cmd) != 0) { 1593 goto error; 1594 } 1595 1596 } 1597 1598 /* send pdu */ 1599 if (isns_send(so, cmd) == -1) { 1600 goto error; 1601 } 1602 1603 /* get isns response */ 1604 if (isns_recv(so, &rsp) == -1) { 1605 goto error; 1606 } 1607 1608 /* process response */ 1609 if (process_rsp(cmd, rsp) == 0) { 1610 ret = 0; 1611 num_reg = tgt_cnt; 1612 queue_prt(mgmtq, Q_ISNS_DBG, "DevAttrRegAll successful"); 1613 } else { 1614 syslog(LOG_ALERT, "DevAttrReg failed"); 1615 } 1616 1617 error: 1618 if (cmd) 1619 isns_free_pdu(cmd); 1620 if (rsp) 1621 isns_free_pdu(rsp); 1622 isns_close(so); 1623 return (ret); 1624 } 1625 1626 /* 1627 * Deregister an iscsi target node 1628 */ 1629 int 1630 isns_dereg(char *name) 1631 { 1632 int so; 1633 int ret; 1634 1635 if (isns_server_connection_thr_running == False) { 1636 syslog(LOG_ERR, 1637 "isns_dereg: iSNS discovery is not running." 1638 " Check the previous iSNS initialization error."); 1639 return (-1); 1640 } 1641 1642 if ((so = isns_open(isns_args.server)) == -1) { 1643 return (-1); 1644 } 1645 1646 ret = isns_dev_attr_dereg(so, name); 1647 1648 isns_close(so); 1649 return (ret); 1650 } 1651 1652 /* 1653 * Update an existing iscsi target property 1654 */ 1655 int 1656 isns_dev_update(char *targ, uint32_t mods) 1657 { 1658 int so; 1659 int flags = 0; /* update only */ 1660 char *iname = NULL; 1661 char *dummy = NULL; 1662 char alias[MAXNAMELEN]; 1663 tgt_node_t *tgt = NULL; 1664 isns_pdu_t *cmd; 1665 isns_rsp_t *rsp; 1666 int ret = -1; 1667 1668 if (mods == 0) 1669 return (0); 1670 1671 if (isns_server_connection_thr_running == False) { 1672 syslog(LOG_ERR, 1673 "isns_dev_update: iSNS discovery is not running." 1674 " Check the previous iSNS initialization error."); 1675 return (-1); 1676 } 1677 1678 if ((tgt = find_tgt_by_name(targ, &iname)) != NULL) { 1679 if (tgt_find_value_str(tgt, XML_ELEMENT_ALIAS, &dummy) == 1680 True) { 1681 (void) strcpy(alias, dummy); 1682 free(dummy); 1683 } else 1684 (void) strcpy(alias, tgt->x_value); 1685 1686 if ((so = isns_open(isns_args.server)) < 0) { 1687 goto error; 1688 } 1689 1690 if (isns_create_pdu(ISNS_DEV_ATTR_REG, flags, &cmd)) { 1691 goto error; 1692 } 1693 /* source attr, msg key, delimiter */ 1694 if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, 1695 STRLEN(iname), iname, 0) != 0) { 1696 goto error; 1697 } 1698 if (isns_append_attr(cmd, ISNS_EID_ATTR_ID, 1699 STRLEN(isns_args.entity), isns_args.entity, 0) != 0) { 1700 goto error; 1701 } 1702 if (isns_append_attr(cmd, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0) 1703 != 0) { 1704 goto error; 1705 } 1706 1707 /* 1708 * get current operating attributes, alias & portal group 1709 * objects, these should be the only things that get change 1710 */ 1711 (void) isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, 1712 STRLEN(iname), iname, 0); 1713 (void) isns_append_attr(cmd, ISNS_ISCSI_NODE_TYPE_ATTR_ID, 1714 ISNS_NODE_TYP_SZ, NULL, ISNS_TARGET_NODE_TYPE); 1715 1716 if (mods & ISNS_MOD_ALIAS) 1717 if (isns_append_attr(cmd, ISNS_ISCSI_ALIAS_ATTR_ID, 1718 STRLEN(alias), alias, 0) != 0) { 1719 goto error; 1720 } 1721 1722 if (mods & ISNS_MOD_TPGT) 1723 if (append_tpgt(tgt, cmd) != 0) { 1724 goto error; 1725 } 1726 1727 if (isns_send(so, (isns_pdu_t *)cmd) < 0) { 1728 goto error; 1729 } 1730 1731 if (isns_recv(so, &rsp) == -1) { 1732 goto error; 1733 } 1734 1735 /* process response, if failed do a isns_reg_all */ 1736 if ((ret = process_rsp(cmd, rsp)) == -1) { 1737 if (isns_reg_all() != 0 || isns_scn_reg_all() != 0) { 1738 syslog(LOG_ALERT, "ISNS register failed\n"); 1739 goto error; 1740 } 1741 ret = 0; 1742 } else { 1743 if (isns_scn_reg(so, iname) == -1) { 1744 syslog(LOG_ERR, "ISNS SCN register failed\n"); 1745 goto error; 1746 } 1747 ret = 0; 1748 } 1749 } else { 1750 syslog(LOG_ERR, "ISNS: fails to update target %s\n", alias); 1751 } 1752 1753 error: 1754 if (cmd) 1755 isns_free_pdu(cmd); 1756 if (rsp) 1757 isns_free_pdu(rsp); 1758 if (iname) 1759 free(iname); 1760 isns_close(so); 1761 return (ret); 1762 } 1763 1764 1765 /* 1766 * Deregister all iscsi target nodes from the XML database 1767 */ 1768 int 1769 isns_dereg_all() 1770 { 1771 return (isns_op_all(ISNS_DEV_DEREG)); 1772 } 1773 1774 int 1775 isns_scn_reg_all() 1776 { 1777 return (isns_op_all(ISNS_SCN_REG)); 1778 } 1779 1780 int 1781 isns_scn_dereg_all() 1782 { 1783 return (isns_op_all(ISNS_SCN_DEREG)); 1784 } 1785 1786 /* 1787 * Query an iscsi initiator node 1788 */ 1789 Boolean_t 1790 isns_qry_initiator(char *target, char *initiator) 1791 { 1792 int so; 1793 int ret; 1794 1795 if (isns_server_connection_thr_running == False) { 1796 syslog(LOG_ERR, 1797 "isns_qry_initiator: iSNS discovery is not running" 1798 " Check the previous iSNS initialization error."); 1799 return (-1); 1800 } 1801 1802 if ((so = isns_open(isns_args.server)) == -1) { 1803 syslog(LOG_ERR, "isns_qry failed"); 1804 return (-1); 1805 } 1806 1807 ret = isns_dev_attr_qry(so, target, initiator); 1808 1809 isns_close(so); 1810 return (ret == 1 ? True : False); 1811 } 1812 1813 Boolean_t 1814 isns_enabled() 1815 { 1816 Boolean_t isns_access = False; 1817 char *isns_srv = NULL; 1818 1819 (void) tgt_find_value_boolean(main_config, XML_ELEMENT_ISNS_ACCESS, 1820 &isns_access); 1821 /* get isns server info */ 1822 if (isns_access == True) { 1823 if (tgt_find_value_str(main_config, XML_ELEMENT_ISNS_SERV, 1824 &isns_srv) == True) { 1825 free(isns_srv); 1826 return (True); 1827 } 1828 } 1829 return (False); 1830 } 1831