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 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include "fcinfo.h" 27 #include <libintl.h> 28 #include <fcntl.h> 29 #include <errno.h> 30 #include <assert.h> 31 #include <ctype.h> 32 #include <sys/list.h> 33 #include <stddef.h> 34 #include <strings.h> 35 #include <libfcoe.h> 36 #include <libscf.h> 37 #include <syslog.h> 38 39 static const char *FCOE_DRIVER_PATH = "/devices/fcoe:admin"; 40 41 static char * 42 WWN2str(char *buf, FCOE_PORT_WWN *wwn) { 43 int j; 44 unsigned char *pc = (unsigned char *)&(wwn->wwn[0]); 45 buf[0] = '\0'; 46 for (j = 0; j < 16; j += 2) { 47 sprintf(&buf[j], "%02X", (int)*pc++); 48 } 49 return (buf); 50 } 51 52 static int 53 isValidWWN(char *wwn) 54 { 55 int index; 56 57 if (wwn == NULL) { 58 return (0); 59 } 60 61 if (strlen(wwn) != 16) { 62 return (0); 63 } 64 65 for (index = 0; index < 16; index++) { 66 if (isxdigit(wwn[index])) { 67 continue; 68 } 69 return (0); 70 } 71 return (1); 72 } 73 74 static uint64_t wwnconvert(uchar_t *wwn) 75 { 76 uint64_t tmp; 77 memcpy(&tmp, wwn, sizeof (uint64_t)); 78 return (ntohll(tmp)); 79 } 80 81 /* 82 * prints out all the HBA port information 83 */ 84 void 85 printFCOEPortInfo(FCOE_PORT_ATTRIBUTE *attr) 86 { 87 int i; 88 if (attr == NULL) { 89 return; 90 } 91 fprintf(stdout, gettext("HBA Port WWN: %016llx\n"), 92 wwnconvert((unsigned char *)&attr->port_wwn)); 93 94 fprintf(stdout, gettext("\tPort Type: %s\n"), 95 (attr->port_type == 0) ? "Initiator" : "Target"); 96 97 fprintf(stdout, gettext("\tMAC Name: %s\n"), attr->mac_link_name); 98 99 fprintf(stdout, gettext("\tMTU Size: %d\n"), attr->mtu_size); 100 101 fprintf(stdout, gettext("\tMAC Factory Address: ")); 102 for (i = 0; i < 6; i++) { 103 fprintf(stdout, gettext("%02x"), attr->mac_factory_addr[i]); 104 } 105 fprintf(stdout, gettext("\n\tMAC Current Address: ")); 106 for (i = 0; i < 6; i++) { 107 fprintf(stdout, gettext("%02x"), attr->mac_current_addr[i]); 108 } 109 fprintf(stdout, gettext("\n\tPromiscuous Mode: %s\n"), 110 attr->mac_promisc == 1 ? "On" : "Off"); 111 } 112 113 /* 114 * Initialize scf fcoe service access 115 * handle - returned handle 116 * service - returned service handle 117 */ 118 static int 119 fcoe_cfg_scf_init(scf_handle_t **handle, scf_service_t **service) 120 { 121 scf_scope_t *scope = NULL; 122 int ret; 123 124 if ((*handle = scf_handle_create(SCF_VERSION)) == NULL) { 125 syslog(LOG_ERR, "scf_handle_create failed - %s", 126 scf_strerror(scf_error())); 127 ret = FCOE_ERROR; 128 goto err; 129 } 130 131 if (scf_handle_bind(*handle) == -1) { 132 syslog(LOG_ERR, "scf_handle_bind failed - %s", 133 scf_strerror(scf_error())); 134 ret = FCOE_ERROR; 135 goto err; 136 } 137 138 if ((*service = scf_service_create(*handle)) == NULL) { 139 syslog(LOG_ERR, "scf_service_create failed - %s", 140 scf_strerror(scf_error())); 141 ret = FCOE_ERROR; 142 goto err; 143 } 144 145 if ((scope = scf_scope_create(*handle)) == NULL) { 146 syslog(LOG_ERR, "scf_scope_create failed - %s", 147 scf_strerror(scf_error())); 148 ret = FCOE_ERROR; 149 goto err; 150 } 151 152 if (scf_handle_get_scope(*handle, SCF_SCOPE_LOCAL, scope) == -1) { 153 syslog(LOG_ERR, "scf_handle_get_scope failed - %s", 154 scf_strerror(scf_error())); 155 ret = FCOE_ERROR; 156 goto err; 157 } 158 159 if (scf_scope_get_service(scope, FCOE_SERVICE, *service) == -1) { 160 syslog(LOG_ERR, "scf_scope_get_service failed - %s", 161 scf_strerror(scf_error())); 162 ret = FCOE_ERROR_SERVICE_NOT_FOUND; 163 goto err; 164 } 165 166 scf_scope_destroy(scope); 167 168 return (FCOE_SUCCESS); 169 170 err: 171 if (*handle != NULL) { 172 scf_handle_destroy(*handle); 173 } 174 if (*service != NULL) { 175 scf_service_destroy(*service); 176 *service = NULL; 177 } 178 if (scope != NULL) { 179 scf_scope_destroy(scope); 180 } 181 return (ret); 182 } 183 184 185 static int 186 fcoe_adm_add_remove_scf_entry(char *mac_name, 187 char *pwwn, char *nwwn, 188 int is_target, int is_promiscuous, int addRemoveFlag) 189 { 190 scf_handle_t *handle = NULL; 191 scf_service_t *svc = NULL; 192 scf_propertygroup_t *pg = NULL; 193 scf_transaction_t *tran = NULL; 194 scf_transaction_entry_t *entry = NULL; 195 scf_property_t *prop = NULL; 196 scf_value_t *valueLookup = NULL; 197 scf_iter_t *valueIter = NULL; 198 scf_value_t **valueSet = NULL; 199 int ret = FCOE_SUCCESS; 200 boolean_t createProp = B_FALSE; 201 int lastAlloc = 0; 202 char buf[FCOE_PORT_LIST_LENGTH] = {0}; 203 char memberName[FCOE_PORT_LIST_LENGTH] = {0}; 204 boolean_t found = B_FALSE; 205 int i = 0; 206 int valueArraySize = 0; 207 int commitRet; 208 209 sprintf(memberName, "%s:%s:%s:%d:%d", mac_name, pwwn, nwwn, 210 is_target, is_promiscuous); 211 212 ret = fcoe_cfg_scf_init(&handle, &svc); 213 if (ret != FCOE_SUCCESS) { 214 goto out; 215 } 216 217 if (((pg = scf_pg_create(handle)) == NULL) || 218 ((tran = scf_transaction_create(handle)) == NULL) || 219 ((entry = scf_entry_create(handle)) == NULL) || 220 ((prop = scf_property_create(handle)) == NULL) || 221 ((valueIter = scf_iter_create(handle)) == NULL)) { 222 ret = FCOE_ERROR; 223 goto out; 224 } 225 226 /* get property group or create it */ 227 if (scf_service_get_pg(svc, FCOE_PG_NAME, pg) == -1) { 228 if ((scf_error() == SCF_ERROR_NOT_FOUND)) { 229 if (scf_service_add_pg(svc, FCOE_PG_NAME, 230 SCF_GROUP_APPLICATION, 0, pg) == -1) { 231 syslog(LOG_ERR, "add pg failed - %s", 232 scf_strerror(scf_error())); 233 ret = FCOE_ERROR; 234 } else { 235 createProp = B_TRUE; 236 } 237 } else { 238 syslog(LOG_ERR, "get pg failed - %s", 239 scf_strerror(scf_error())); 240 ret = FCOE_ERROR; 241 } 242 if (ret != FCOE_SUCCESS) { 243 goto out; 244 } 245 } 246 247 /* to make sure property exists */ 248 if (createProp == B_FALSE) { 249 if (scf_pg_get_property(pg, FCOE_PORT_LIST, prop) == -1) { 250 if ((scf_error() == SCF_ERROR_NOT_FOUND)) { 251 createProp = B_TRUE; 252 } else { 253 syslog(LOG_ERR, "get property failed - %s", 254 scf_strerror(scf_error())); 255 ret = FCOE_ERROR; 256 goto out; 257 } 258 } 259 } 260 261 /* Begin the transaction */ 262 if (scf_transaction_start(tran, pg) == -1) { 263 syslog(LOG_ERR, "start transaction failed - %s", 264 scf_strerror(scf_error())); 265 ret = FCOE_ERROR; 266 goto out; 267 } 268 269 valueSet = (scf_value_t **)calloc(1, sizeof (*valueSet) 270 * (lastAlloc = PORT_LIST_ALLOC)); 271 if (valueSet == NULL) { 272 ret = FCOE_ERROR_NOMEM; 273 goto out; 274 } 275 276 if (createProp) { 277 if (scf_transaction_property_new(tran, entry, FCOE_PORT_LIST, 278 SCF_TYPE_USTRING) == -1) { 279 if (scf_error() == SCF_ERROR_EXISTS) { 280 ret = FCOE_ERROR_EXISTS; 281 } else { 282 syslog(LOG_ERR, 283 "transaction property new failed - %s", 284 scf_strerror(scf_error())); 285 ret = FCOE_ERROR; 286 } 287 goto out; 288 } 289 } else { 290 if (scf_transaction_property_change(tran, entry, 291 FCOE_PORT_LIST, SCF_TYPE_USTRING) == -1) { 292 syslog(LOG_ERR, 293 "transaction property change failed - %s", 294 scf_strerror(scf_error())); 295 ret = FCOE_ERROR; 296 goto out; 297 } 298 299 if (scf_pg_get_property(pg, FCOE_PORT_LIST, prop) == -1) { 300 syslog(LOG_ERR, "get property failed - %s", 301 scf_strerror(scf_error())); 302 ret = FCOE_ERROR; 303 goto out; 304 } 305 306 valueLookup = scf_value_create(handle); 307 if (valueLookup == NULL) { 308 syslog(LOG_ERR, "scf value alloc failed - %s", 309 scf_strerror(scf_error())); 310 ret = FCOE_ERROR; 311 goto out; 312 } 313 314 if (scf_iter_property_values(valueIter, prop) == -1) { 315 syslog(LOG_ERR, "iter value failed - %s", 316 scf_strerror(scf_error())); 317 ret = FCOE_ERROR; 318 goto out; 319 } 320 321 while (scf_iter_next_value(valueIter, valueLookup) == 1) { 322 char *macnameIter = NULL; 323 char buftmp[FCOE_PORT_LIST_LENGTH] = {0}; 324 325 bzero(buf, sizeof (buf)); 326 if (scf_value_get_ustring(valueLookup, 327 buf, MAXNAMELEN) == -1) { 328 syslog(LOG_ERR, "iter value failed- %s", 329 scf_strerror(scf_error())); 330 ret = FCOE_ERROR; 331 break; 332 } 333 strcpy(buftmp, buf); 334 macnameIter = strtok(buftmp, ":"); 335 if (bcmp(macnameIter, mac_name, 336 strlen(mac_name)) == 0) { 337 if (addRemoveFlag == FCOE_SCF_ADD) { 338 ret = FCOE_ERROR_EXISTS; 339 break; 340 } else { 341 found = B_TRUE; 342 continue; 343 } 344 } 345 346 valueSet[i] = scf_value_create(handle); 347 if (valueSet[i] == NULL) { 348 syslog(LOG_ERR, "scf value alloc failed - %s", 349 scf_strerror(scf_error())); 350 ret = FCOE_ERROR; 351 break; 352 } 353 354 if (scf_value_set_ustring(valueSet[i], buf) == -1) { 355 syslog(LOG_ERR, "set value failed 1- %s", 356 scf_strerror(scf_error())); 357 ret = FCOE_ERROR; 358 break; 359 } 360 361 if (scf_entry_add_value(entry, valueSet[i]) == -1) { 362 syslog(LOG_ERR, "add value failed - %s", 363 scf_strerror(scf_error())); 364 ret = FCOE_ERROR; 365 break; 366 } 367 368 i++; 369 370 if (i >= lastAlloc) { 371 lastAlloc += PORT_LIST_ALLOC; 372 valueSet = realloc(valueSet, 373 sizeof (*valueSet) * lastAlloc); 374 if (valueSet == NULL) { 375 ret = FCOE_ERROR; 376 break; 377 } 378 } 379 } 380 } 381 382 valueArraySize = i; 383 if (!found && (addRemoveFlag == FCOE_SCF_REMOVE)) { 384 ret = FCOE_ERROR_MEMBER_NOT_FOUND; 385 } 386 if (ret != FCOE_SUCCESS) { 387 goto out; 388 } 389 390 if (addRemoveFlag == FCOE_SCF_ADD) { 391 /* 392 * Now create the new entry 393 */ 394 valueSet[i] = scf_value_create(handle); 395 if (valueSet[i] == NULL) { 396 syslog(LOG_ERR, "scf value alloc failed - %s", 397 scf_strerror(scf_error())); 398 ret = FCOE_ERROR; 399 goto out; 400 } else { 401 valueArraySize++; 402 } 403 404 /* 405 * Set the new member name 406 */ 407 if (scf_value_set_ustring(valueSet[i], memberName) == -1) { 408 syslog(LOG_ERR, "set value failed 2- %s", 409 scf_strerror(scf_error())); 410 ret = FCOE_ERROR; 411 goto out; 412 } 413 414 /* 415 * Add the new member 416 */ 417 if (scf_entry_add_value(entry, valueSet[i]) == -1) { 418 syslog(LOG_ERR, "add value failed - %s", 419 scf_strerror(scf_error())); 420 ret = FCOE_ERROR; 421 goto out; 422 } 423 } 424 425 if ((commitRet = scf_transaction_commit(tran)) != 1) { 426 syslog(LOG_ERR, "transaction commit failed - %s", 427 scf_strerror(scf_error())); 428 if (commitRet == 0) { 429 ret = FCOE_ERROR_BUSY; 430 } else { 431 ret = FCOE_ERROR; 432 } 433 goto out; 434 } 435 436 out: 437 /* 438 * Free resources 439 */ 440 if (handle != NULL) { 441 scf_handle_destroy(handle); 442 } 443 if (svc != NULL) { 444 scf_service_destroy(svc); 445 } 446 if (pg != NULL) { 447 scf_pg_destroy(pg); 448 } 449 if (tran != NULL) { 450 scf_transaction_destroy(tran); 451 } 452 if (entry != NULL) { 453 scf_entry_destroy(entry); 454 } 455 if (prop != NULL) { 456 scf_property_destroy(prop); 457 } 458 if (valueIter != NULL) { 459 scf_iter_destroy(valueIter); 460 } 461 if (valueLookup != NULL) { 462 scf_value_destroy(valueLookup); 463 } 464 465 /* 466 * Free valueSet scf resources 467 */ 468 if (valueArraySize > 0) { 469 for (i = 0; i < valueArraySize; i++) { 470 scf_value_destroy(valueSet[i]); 471 } 472 } 473 /* 474 * Now free the pointer array to the resources 475 */ 476 if (valueSet != NULL) { 477 free(valueSet); 478 } 479 480 return (ret); 481 } 482 483 int 484 fcoe_adm_create_port(int objects, char *argv[], 485 cmdOptions_t *options) 486 { 487 FCOE_STATUS status = FCOE_STATUS_OK; 488 uint64_t nodeWWN, portWWN; 489 FCOE_PORT_WWN pwwn, nwwn; 490 FCOE_UINT8 macLinkName[FCOE_MAX_MAC_NAME_LEN]; 491 FCOE_UINT8 promiscuous = 0; 492 int createini = 0, createtgt = 0; 493 494 /* check the mac name operand */ 495 assert(objects == 1); 496 497 strcpy((char *)macLinkName, argv[0]); 498 bzero(&pwwn, 8); 499 bzero(&nwwn, 8); 500 501 for (; options->optval; options++) { 502 switch (options->optval) { 503 case 'i': 504 createini = 1; 505 break; 506 507 case 't': 508 createtgt = 1; 509 break; 510 case 'p': 511 if (!isValidWWN(options->optarg)) { 512 fprintf(stderr, 513 gettext("Error: Invalid Port WWN\n")); 514 return (1); 515 } 516 sscanf(options->optarg, "%016llx", &portWWN); 517 portWWN = htonll(portWWN); 518 memcpy(&pwwn, &portWWN, sizeof (portWWN)); 519 break; 520 521 case 'n': 522 if (!isValidWWN(options->optarg)) { 523 fprintf(stderr, 524 gettext("Error: Invalid Node WWN\n")); 525 return (1); 526 } 527 sscanf(options->optarg, "%016llx", &nodeWWN); 528 nodeWWN = htonll(nodeWWN); 529 memcpy(&nwwn, &nodeWWN, sizeof (nodeWWN)); 530 break; 531 case 'f': 532 promiscuous = 1; 533 break; 534 535 default: 536 fprintf(stderr, gettext("Error: Illegal option: %c\n"), 537 options->optval); 538 return (1); 539 } 540 } 541 542 if (createini == 1 && createtgt == 1) { 543 fprintf(stderr, "Error: Option -i and -t should " 544 "not be both specified\n"); 545 return (1); 546 } 547 status = FCOE_CreatePort(macLinkName, 548 createtgt == 1 ? FCOE_PORTTYPE_TARGET : 549 FCOE_PORTTYPE_INITIATOR, pwwn, nwwn, promiscuous); 550 551 if (status != FCOE_STATUS_OK) { 552 switch (status) { 553 case FCOE_STATUS_ERROR_BUSY: 554 fprintf(stderr, 555 gettext("Error: fcoe driver is busy\n")); 556 break; 557 558 case FCOE_STATUS_ERROR_ALREADY: 559 fprintf(stderr, 560 gettext("Error: Existing FCoE port " 561 "found on the specified MAC link\n")); 562 break; 563 564 case FCOE_STATUS_ERROR_PERM: 565 fprintf(stderr, 566 gettext("Error: Not enough permission to " 567 "open fcoe device\n")); 568 break; 569 570 case FCOE_STATUS_ERROR_OPEN_DEV: 571 fprintf(stderr, 572 gettext("Error: Failed to open fcoe device\n")); 573 break; 574 575 case FCOE_STATUS_ERROR_WWN_SAME: 576 fprintf(stderr, 577 gettext("Error: Port WWN is same as Node " 578 "WWN\n")); 579 break; 580 581 case FCOE_STATUS_ERROR_MAC_LEN: 582 fprintf(stderr, 583 gettext("Error: MAC name exceeds maximum " 584 "length\n")); 585 break; 586 587 case FCOE_STATUS_ERROR_PWWN_CONFLICTED: 588 fprintf(stderr, 589 gettext("Error: The specified Port WWN " 590 "is already in use\n")); 591 break; 592 593 case FCOE_STATUS_ERROR_NWWN_CONFLICTED: 594 fprintf(stderr, 595 gettext("Error: The specified Node WWN " 596 "is already in use\n")); 597 break; 598 599 case FCOE_STATUS_ERROR_NEED_JUMBO_FRAME: 600 fprintf(stderr, 601 gettext("Error: MTU size of the specified " 602 "MAC link needs to be increased to 2500 " 603 "or above\n")); 604 break; 605 606 case FCOE_STATUS_ERROR_CREATE_MAC: 607 fprintf(stderr, 608 gettext("Error: Out of memory\n")); 609 break; 610 611 612 case FCOE_STATUS_ERROR_OPEN_MAC: 613 fprintf(stderr, 614 gettext("Error: Failed to open the " 615 "specified MAC link\n")); 616 break; 617 618 case FCOE_STATUS_ERROR_CREATE_PORT: 619 fprintf(stderr, 620 gettext("Error: Failed to create FCoE " 621 "port on the specified MAC link\n")); 622 break; 623 624 case FCOE_STATUS_ERROR_VNIC_UNSUPPORT: 625 fprintf(stderr, 626 gettext("Error: VNIC is not supported\n")); 627 break; 628 629 case FCOE_STATUS_ERROR: 630 default: 631 fprintf(stderr, 632 gettext("Error: Due to reason code %d\n"), status); 633 } 634 return (1); 635 } else { 636 char cpwwn[17], cnwwn[17]; 637 638 WWN2str(cpwwn, &pwwn); 639 WWN2str(cnwwn, &nwwn); 640 641 fcoe_adm_add_remove_scf_entry((char *)macLinkName, 642 cpwwn, 643 cnwwn, 644 createtgt, 645 promiscuous, 646 FCOE_SCF_ADD); 647 return (0); 648 } 649 } 650 651 int 652 fcoe_adm_delete_port(int objects, char *argv[]) 653 { 654 FCOE_STATUS status; 655 FCOE_UINT8 *macLinkName; 656 657 /* check the mac name operand */ 658 assert(objects == 1); 659 660 macLinkName = (FCOE_UINT8 *) argv[0]; 661 662 status = FCOE_DeletePort(macLinkName); 663 if (status != FCOE_STATUS_OK) { 664 switch (status) { 665 case FCOE_STATUS_ERROR_BUSY: 666 fprintf(stderr, 667 gettext("Error: fcoe driver is busy\n")); 668 break; 669 670 case FCOE_STATUS_ERROR_ALREADY: 671 fprintf(stderr, 672 gettext("Error: FCoE port not found on the " 673 "specified MAC link\n")); 674 break; 675 676 case FCOE_STATUS_ERROR_PERM: 677 fprintf(stderr, 678 gettext("Error: Not enough permission to " 679 "open fcoe device\n")); 680 break; 681 682 case FCOE_STATUS_ERROR_MAC_LEN: 683 fprintf(stderr, 684 gettext("Failed: MAC name exceeds maximum " 685 "length 32\n")); 686 break; 687 688 case FCOE_STATUS_ERROR_OPEN_DEV: 689 fprintf(stderr, 690 gettext("Error: Failed to open fcoe device\n")); 691 break; 692 693 case FCOE_STATUS_ERROR_MAC_NOT_FOUND: 694 fprintf(stderr, 695 gettext("Error: FCoE port not found on the " 696 "specified MAC link\n")); 697 break; 698 699 case FCOE_STATUS_ERROR_OFFLINE_DEV: 700 fprintf(stderr, 701 gettext("Error: Please use stmfadm to offline " 702 "the FCoE target first\n")); 703 break; 704 705 case FCOE_STATUS_ERROR: 706 default: 707 fprintf(stderr, 708 gettext("Error: Due to reason code %d\n"), status); 709 } 710 return (1); 711 } else { 712 fcoe_adm_add_remove_scf_entry((char *)macLinkName, 713 "", 714 "", 715 0, 716 0, 717 FCOE_SCF_REMOVE); 718 return (0); 719 } 720 } 721 722 int 723 fcoe_adm_list_ports(cmdOptions_t *options) 724 { 725 FCOE_STATUS status; 726 int showini = 0, showtgt = 0; 727 FCOE_UINT32 port_num; 728 FCOE_PORT_ATTRIBUTE *portlist = NULL; 729 int i; 730 int ret; 731 732 for (; options->optval; options++) { 733 switch (options->optval) { 734 case 'i': 735 showini = 1; 736 break; 737 738 case 't': 739 showtgt = 1; 740 break; 741 742 default: 743 fprintf(stderr, gettext("Error: Illegal option: %c\n"), 744 options->optval); 745 return (1); 746 } 747 } 748 if (showini == 0 && showtgt == 0) { 749 showini = 1; 750 showtgt = 1; 751 } 752 753 status = FCOE_GetPortList(&port_num, &portlist); 754 755 if (status != FCOE_STATUS_OK) { 756 switch (status) { 757 case FCOE_STATUS_ERROR_BUSY: 758 fprintf(stderr, 759 gettext("Error: fcoe driver is busy\n")); 760 break; 761 762 case FCOE_STATUS_ERROR_PERM: 763 fprintf(stderr, 764 gettext("Error: Not enough permission to " 765 "open fcoe device\n")); 766 break; 767 768 case FCOE_STATUS_ERROR_OPEN_DEV: 769 fprintf(stderr, 770 gettext("Error: Failed to open fcoe device\n")); 771 break; 772 773 case FCOE_STATUS_ERROR_INVAL_ARG: 774 fprintf(stderr, 775 gettext("Error: Invalid argument\n")); 776 break; 777 778 case FCOE_STATUS_ERROR_MORE_DATA: 779 fprintf(stderr, 780 gettext("Error: More data\n")); 781 break; 782 783 case FCOE_STATUS_ERROR: 784 default: 785 fprintf(stderr, 786 gettext("Error: Due to reason code %d\n"), status); 787 } 788 ret = 1; 789 } else { 790 if (port_num == 0) { 791 fprintf(stdout, gettext("No FCoE Ports Found!\n")); 792 } else { 793 for (i = 0; i < port_num; i++) { 794 if ((portlist[i].port_type == 795 FCOE_PORTTYPE_INITIATOR && 796 showini == 1) || (showtgt == 1 && 797 portlist[i].port_type == 798 FCOE_PORTTYPE_TARGET)) { 799 printFCOEPortInfo(&portlist[i]); 800 } 801 } 802 } 803 ret = 0; 804 } 805 806 if (portlist != NULL) { 807 free(portlist); 808 } 809 return (ret); 810 811 } 812 813 int 814 fcoe_adm_create_portlist(cmdOptions_t *options) 815 { 816 scf_handle_t *handle = NULL; 817 scf_service_t *svc = NULL; 818 scf_propertygroup_t *pg = NULL; 819 scf_transaction_t *tran = NULL; 820 scf_transaction_entry_t *entry = NULL; 821 scf_property_t *prop = NULL; 822 scf_value_t *valueLookup = NULL; 823 scf_iter_t *valueIter = NULL; 824 char buf[FCOE_PORT_LIST_LENGTH] = {0}; 825 int commitRet; 826 int create_target = 0, create_initiator = 0; 827 828 /* Check what type of port list will be created */ 829 for (; options->optval; options++) { 830 switch (options->optval) { 831 case 'i': 832 create_initiator = 1; 833 break; 834 case 't': 835 create_target = 1; 836 break; 837 default: 838 fprintf(stderr, gettext("Error: Illegal option: %c\n"), 839 options->optval); 840 return (1); 841 } 842 } 843 844 if (create_initiator == 0 && create_target == 0) { 845 create_initiator = 1; 846 create_target = 1; 847 } 848 849 commitRet = fcoe_cfg_scf_init(&handle, &svc); 850 if (commitRet != FCOE_SUCCESS) { 851 goto out; 852 } 853 854 if (((pg = scf_pg_create(handle)) == NULL) || 855 ((tran = scf_transaction_create(handle)) == NULL) || 856 ((entry = scf_entry_create(handle)) == NULL) || 857 ((prop = scf_property_create(handle)) == NULL) || 858 ((valueIter = scf_iter_create(handle)) == NULL)) { 859 goto out; 860 } 861 862 /* get property group or create it */ 863 if (scf_service_get_pg(svc, FCOE_PG_NAME, pg) == -1) { 864 goto out; 865 } 866 867 if (scf_pg_get_property(pg, FCOE_PORT_LIST, prop) == -1) { 868 syslog(LOG_ERR, "get property failed - %s", 869 scf_strerror(scf_error())); 870 goto out; 871 } 872 873 valueLookup = scf_value_create(handle); 874 if (valueLookup == NULL) { 875 syslog(LOG_ERR, "scf value alloc failed - %s", 876 scf_strerror(scf_error())); 877 goto out; 878 } 879 880 if (scf_iter_property_values(valueIter, prop) == -1) { 881 syslog(LOG_ERR, "iter value failed - %s", 882 scf_strerror(scf_error())); 883 goto out; 884 } 885 while (scf_iter_next_value(valueIter, valueLookup) == 1) { 886 uint8_t *macLinkName = NULL; 887 char *remainder = NULL; 888 FCOE_PORT_WWN pwwn, nwwn; 889 uint64_t nodeWWN, portWWN; 890 int is_target, is_promiscuous; 891 892 bzero(buf, sizeof (buf)); 893 bzero(&pwwn, sizeof (pwwn)); 894 bzero(&nwwn, sizeof (nwwn)); 895 if (scf_value_get_ustring(valueLookup, buf, MAXNAMELEN) == -1) { 896 syslog(LOG_ERR, "iter value failed - %s", 897 scf_strerror(scf_error())); 898 break; 899 } 900 macLinkName = (uint8_t *)strtok(buf, ":"); 901 remainder = strtok(NULL, "#"); 902 sscanf(remainder, "%016llx:%016llx:%d:%d", 903 &portWWN, &nodeWWN, &is_target, &is_promiscuous); 904 if ((!create_target && is_target) || 905 (!create_initiator && !is_target)) { 906 continue; 907 } 908 909 nodeWWN = htonll(nodeWWN); 910 memcpy(&nwwn, &nodeWWN, sizeof (nodeWWN)); 911 portWWN = htonll(portWWN); 912 memcpy(&pwwn, &portWWN, sizeof (portWWN)); 913 914 FCOE_CreatePort(macLinkName, 915 is_target ? FCOE_PORTTYPE_TARGET : FCOE_PORTTYPE_INITIATOR, 916 pwwn, nwwn, is_promiscuous); 917 } 918 919 out: 920 /* 921 * Free resources 922 */ 923 if (handle != NULL) { 924 scf_handle_destroy(handle); 925 } 926 if (svc != NULL) { 927 scf_service_destroy(svc); 928 } 929 if (pg != NULL) { 930 scf_pg_destroy(pg); 931 } 932 if (tran != NULL) { 933 scf_transaction_destroy(tran); 934 } 935 if (entry != NULL) { 936 scf_entry_destroy(entry); 937 } 938 if (prop != NULL) { 939 scf_property_destroy(prop); 940 } 941 if (valueIter != NULL) { 942 scf_iter_destroy(valueIter); 943 } 944 if (valueLookup != NULL) { 945 scf_value_destroy(valueLookup); 946 } 947 948 return (0); 949 } 950