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_CLASS_UNSUPPORT: 625 fprintf(stderr, 626 gettext("Error: Link class other than physical " 627 "link is not supported\n")); 628 break; 629 630 case FCOE_STATUS_ERROR_GET_LINKINFO: 631 fprintf(stderr, 632 gettext("Error: Failed to get link infomation " 633 "for %s\n"), macLinkName); 634 break; 635 636 case FCOE_STATUS_ERROR: 637 default: 638 fprintf(stderr, 639 gettext("Error: Due to reason code %d\n"), status); 640 } 641 return (1); 642 } else { 643 char cpwwn[17], cnwwn[17]; 644 645 WWN2str(cpwwn, &pwwn); 646 WWN2str(cnwwn, &nwwn); 647 648 fcoe_adm_add_remove_scf_entry((char *)macLinkName, 649 cpwwn, 650 cnwwn, 651 createtgt, 652 promiscuous, 653 FCOE_SCF_ADD); 654 return (0); 655 } 656 } 657 658 int 659 fcoe_adm_delete_port(int objects, char *argv[]) 660 { 661 FCOE_STATUS status; 662 FCOE_UINT8 *macLinkName; 663 664 /* check the mac name operand */ 665 assert(objects == 1); 666 667 macLinkName = (FCOE_UINT8 *) argv[0]; 668 669 status = FCOE_DeletePort(macLinkName); 670 if (status != FCOE_STATUS_OK) { 671 switch (status) { 672 case FCOE_STATUS_ERROR_BUSY: 673 fprintf(stderr, 674 gettext("Error: fcoe driver is busy\n")); 675 break; 676 677 case FCOE_STATUS_ERROR_ALREADY: 678 fprintf(stderr, 679 gettext("Error: FCoE port not found on the " 680 "specified MAC link\n")); 681 break; 682 683 case FCOE_STATUS_ERROR_PERM: 684 fprintf(stderr, 685 gettext("Error: Not enough permission to " 686 "open fcoe device\n")); 687 break; 688 689 case FCOE_STATUS_ERROR_MAC_LEN: 690 fprintf(stderr, 691 gettext("Failed: MAC name exceeds maximum " 692 "length 32\n")); 693 break; 694 695 case FCOE_STATUS_ERROR_OPEN_DEV: 696 fprintf(stderr, 697 gettext("Error: Failed to open fcoe device\n")); 698 break; 699 700 case FCOE_STATUS_ERROR_MAC_NOT_FOUND: 701 fprintf(stderr, 702 gettext("Error: FCoE port not found on the " 703 "specified MAC link\n")); 704 break; 705 706 case FCOE_STATUS_ERROR_OFFLINE_DEV: 707 fprintf(stderr, 708 gettext("Error: Please use stmfadm to offline " 709 "the FCoE target first\n")); 710 break; 711 712 case FCOE_STATUS_ERROR_GET_LINKINFO: 713 fprintf(stderr, 714 gettext("Error: Failed to get link information " 715 "for %s\n"), macLinkName); 716 break; 717 718 case FCOE_STATUS_ERROR: 719 default: 720 fprintf(stderr, 721 gettext("Error: Due to reason code %d\n"), status); 722 } 723 return (1); 724 } else { 725 fcoe_adm_add_remove_scf_entry((char *)macLinkName, 726 "", 727 "", 728 0, 729 0, 730 FCOE_SCF_REMOVE); 731 return (0); 732 } 733 } 734 735 int 736 fcoe_adm_list_ports(cmdOptions_t *options) 737 { 738 FCOE_STATUS status; 739 int showini = 0, showtgt = 0; 740 FCOE_UINT32 port_num; 741 FCOE_PORT_ATTRIBUTE *portlist = NULL; 742 int i; 743 int ret; 744 745 for (; options->optval; options++) { 746 switch (options->optval) { 747 case 'i': 748 showini = 1; 749 break; 750 751 case 't': 752 showtgt = 1; 753 break; 754 755 default: 756 fprintf(stderr, gettext("Error: Illegal option: %c\n"), 757 options->optval); 758 return (1); 759 } 760 } 761 if (showini == 0 && showtgt == 0) { 762 showini = 1; 763 showtgt = 1; 764 } 765 766 status = FCOE_GetPortList(&port_num, &portlist); 767 768 if (status != FCOE_STATUS_OK) { 769 switch (status) { 770 case FCOE_STATUS_ERROR_BUSY: 771 fprintf(stderr, 772 gettext("Error: fcoe driver is busy\n")); 773 break; 774 775 case FCOE_STATUS_ERROR_PERM: 776 fprintf(stderr, 777 gettext("Error: Not enough permission to " 778 "open fcoe device\n")); 779 break; 780 781 case FCOE_STATUS_ERROR_OPEN_DEV: 782 fprintf(stderr, 783 gettext("Error: Failed to open fcoe device\n")); 784 break; 785 786 case FCOE_STATUS_ERROR_INVAL_ARG: 787 fprintf(stderr, 788 gettext("Error: Invalid argument\n")); 789 break; 790 791 case FCOE_STATUS_ERROR_MORE_DATA: 792 fprintf(stderr, 793 gettext("Error: More data\n")); 794 break; 795 796 case FCOE_STATUS_ERROR: 797 default: 798 fprintf(stderr, 799 gettext("Error: Due to reason code %d\n"), status); 800 } 801 ret = 1; 802 } else { 803 if (port_num == 0) { 804 fprintf(stdout, gettext("No FCoE Ports Found!\n")); 805 } else { 806 for (i = 0; i < port_num; i++) { 807 if ((portlist[i].port_type == 808 FCOE_PORTTYPE_INITIATOR && 809 showini == 1) || (showtgt == 1 && 810 portlist[i].port_type == 811 FCOE_PORTTYPE_TARGET)) { 812 printFCOEPortInfo(&portlist[i]); 813 } 814 } 815 } 816 ret = 0; 817 } 818 819 if (portlist != NULL) { 820 free(portlist); 821 } 822 return (ret); 823 824 } 825 826 int 827 fcoe_adm_create_portlist(cmdOptions_t *options) 828 { 829 scf_handle_t *handle = NULL; 830 scf_service_t *svc = NULL; 831 scf_propertygroup_t *pg = NULL; 832 scf_transaction_t *tran = NULL; 833 scf_transaction_entry_t *entry = NULL; 834 scf_property_t *prop = NULL; 835 scf_value_t *valueLookup = NULL; 836 scf_iter_t *valueIter = NULL; 837 char buf[FCOE_PORT_LIST_LENGTH] = {0}; 838 int commitRet; 839 int create_target = 0, create_initiator = 0; 840 841 /* Check what type of port list will be created */ 842 for (; options->optval; options++) { 843 switch (options->optval) { 844 case 'i': 845 create_initiator = 1; 846 break; 847 case 't': 848 create_target = 1; 849 break; 850 default: 851 fprintf(stderr, gettext("Error: Illegal option: %c\n"), 852 options->optval); 853 return (1); 854 } 855 } 856 857 if (create_initiator == 0 && create_target == 0) { 858 create_initiator = 1; 859 create_target = 1; 860 } 861 862 commitRet = fcoe_cfg_scf_init(&handle, &svc); 863 if (commitRet != FCOE_SUCCESS) { 864 goto out; 865 } 866 867 if (((pg = scf_pg_create(handle)) == NULL) || 868 ((tran = scf_transaction_create(handle)) == NULL) || 869 ((entry = scf_entry_create(handle)) == NULL) || 870 ((prop = scf_property_create(handle)) == NULL) || 871 ((valueIter = scf_iter_create(handle)) == NULL)) { 872 goto out; 873 } 874 875 /* get property group or create it */ 876 if (scf_service_get_pg(svc, FCOE_PG_NAME, pg) == -1) { 877 goto out; 878 } 879 880 if (scf_pg_get_property(pg, FCOE_PORT_LIST, prop) == -1) { 881 syslog(LOG_ERR, "get property failed - %s", 882 scf_strerror(scf_error())); 883 goto out; 884 } 885 886 valueLookup = scf_value_create(handle); 887 if (valueLookup == NULL) { 888 syslog(LOG_ERR, "scf value alloc failed - %s", 889 scf_strerror(scf_error())); 890 goto out; 891 } 892 893 if (scf_iter_property_values(valueIter, prop) == -1) { 894 syslog(LOG_ERR, "iter value failed - %s", 895 scf_strerror(scf_error())); 896 goto out; 897 } 898 while (scf_iter_next_value(valueIter, valueLookup) == 1) { 899 uint8_t *macLinkName = NULL; 900 char *remainder = NULL; 901 FCOE_PORT_WWN pwwn, nwwn; 902 uint64_t nodeWWN, portWWN; 903 int is_target, is_promiscuous; 904 905 bzero(buf, sizeof (buf)); 906 bzero(&pwwn, sizeof (pwwn)); 907 bzero(&nwwn, sizeof (nwwn)); 908 if (scf_value_get_ustring(valueLookup, buf, MAXNAMELEN) == -1) { 909 syslog(LOG_ERR, "iter value failed - %s", 910 scf_strerror(scf_error())); 911 break; 912 } 913 macLinkName = (uint8_t *)strtok(buf, ":"); 914 remainder = strtok(NULL, "#"); 915 sscanf(remainder, "%016llx:%016llx:%d:%d", 916 &portWWN, &nodeWWN, &is_target, &is_promiscuous); 917 if ((!create_target && is_target) || 918 (!create_initiator && !is_target)) { 919 continue; 920 } 921 922 nodeWWN = htonll(nodeWWN); 923 memcpy(&nwwn, &nodeWWN, sizeof (nodeWWN)); 924 portWWN = htonll(portWWN); 925 memcpy(&pwwn, &portWWN, sizeof (portWWN)); 926 927 FCOE_CreatePort(macLinkName, 928 is_target ? FCOE_PORTTYPE_TARGET : FCOE_PORTTYPE_INITIATOR, 929 pwwn, nwwn, is_promiscuous); 930 } 931 932 out: 933 /* 934 * Free resources 935 */ 936 if (handle != NULL) { 937 scf_handle_destroy(handle); 938 } 939 if (svc != NULL) { 940 scf_service_destroy(svc); 941 } 942 if (pg != NULL) { 943 scf_pg_destroy(pg); 944 } 945 if (tran != NULL) { 946 scf_transaction_destroy(tran); 947 } 948 if (entry != NULL) { 949 scf_entry_destroy(entry); 950 } 951 if (prop != NULL) { 952 scf_property_destroy(prop); 953 } 954 if (valueIter != NULL) { 955 scf_iter_destroy(valueIter); 956 } 957 if (valueLookup != NULL) { 958 scf_value_destroy(valueLookup); 959 } 960 961 return (0); 962 } 963