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 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <stdlib.h> 28 #include <stdio.h> 29 #include <sys/types.h> 30 #include <sys/param.h> 31 #include <unistd.h> 32 #include <libintl.h> 33 #include <limits.h> 34 #include <string.h> 35 #include <syslog.h> 36 #include <errno.h> 37 #include <sys/stat.h> 38 #include <zone.h> 39 #include <netdb.h> 40 41 #include <iscsitgt_impl.h> 42 #include "cmdparse.h" 43 #include "helper.h" 44 45 #define CREATE SUBCOMMAND(0) 46 #define LIST SUBCOMMAND(1) 47 #define MODIFY SUBCOMMAND(2) 48 #define DELETE SUBCOMMAND(3) 49 #define SHOW SUBCOMMAND(4) 50 51 #define TARGET OBJECT(0) 52 #define INITIATOR OBJECT(1) 53 #define ADMIN OBJECT(2) 54 #define TPGT OBJECT(3) 55 #define STATS OBJECT(4) 56 57 #define VERSION_STRING_MAX_LEN 10 58 #define MAX_IPADDRESS_LEN 128 59 60 /* 61 * Version number: 62 * MAJOR - This should only change when there is an incompatible change made 63 * to the interfaces or the output. 64 * 65 * MINOR - This should change whenever there is a new command or new feature 66 * with no incompatible change. 67 */ 68 #define VERSION_STRING_MAJOR "1" 69 #define VERSION_STRING_MINOR "0" 70 71 #define OPT_ENABLE "enable" 72 #define OPT_DISABLE "disable" 73 #define OPT_TRUE "true" 74 #define OPT_FALSE "false" 75 76 /* subcommand functions */ 77 static int createFunc(int, char **, int, cmdOptions_t *, void *); 78 static int listFunc(int, char **, int, cmdOptions_t *, void *); 79 static int modifyFunc(int, char **, int, cmdOptions_t *, void *); 80 static int deleteFunc(int, char **, int, cmdOptions_t *, void *); 81 static int showFunc(int, char **, int, cmdOptions_t *, void *); 82 83 /* object functions per subcommand */ 84 static int createTarget(int, char *[], cmdOptions_t *); 85 static int createInitiator(int, char *[], cmdOptions_t *); 86 static int createTpgt(int, char *[], cmdOptions_t *); 87 static int modifyTarget(int, char *[], cmdOptions_t *); 88 static int modifyInitiator(int, char *[], cmdOptions_t *); 89 static int modifyTpgt(int, char *[], cmdOptions_t *); 90 static int modifyAdmin(int, char *[], cmdOptions_t *); 91 static int deleteTarget(int, char *[], cmdOptions_t *); 92 static int deleteInitiator(int, char *[], cmdOptions_t *); 93 static int deleteTpgt(int, char *[], cmdOptions_t *); 94 static int listTarget(int, char *[], cmdOptions_t *); 95 static int listInitiator(int, char *[], cmdOptions_t *); 96 static int listTpgt(int, char *[], cmdOptions_t *); 97 static int showAdmin(int, char *[], cmdOptions_t *); 98 static int showStats(int, char *[], cmdOptions_t *); 99 100 /* globals */ 101 char *cmdName; 102 103 /* 104 * Add new options here 105 */ 106 optionTbl_t longOptions[] = { 107 {"size", required_arg, 'z', "size k/m/g/t"}, 108 {"type", required_arg, 't', "disk/tape/osd/raw"}, 109 {"lun", required_arg, 'u', "number"}, 110 {"alias", required_arg, 'a', "value"}, 111 {"backing-store", required_arg, 'b', "pathname"}, 112 {"tpgt", required_arg, 'p', "tpgt number"}, 113 {"acl", required_arg, 'l', "local initiator"}, 114 {"maxrecv", required_arg, 'm', "max recv data segment length"}, 115 {"chap-secret", no_arg, 'C', NULL}, 116 {"chap-name", required_arg, 'H', "chap username"}, 117 {"iqn", required_arg, 'n', "iSCSI node name"}, 118 {"ip-address", required_arg, 'i', "ip address"}, 119 {"base-directory", required_arg, 'd', "directory"}, 120 {"radius-access", required_arg, 'R', "enable/disable"}, 121 {"radius-server", required_arg, 'r', "hostname[:port]"}, 122 {"radius-secret", no_arg, 'P', NULL}, 123 {"isns-access", required_arg, 'S', "enable/disable"}, 124 {"isns-server", required_arg, 's', "hostname[:port]"}, 125 {"fast-write-ack", required_arg, 'f', "enable/disable"}, 126 {"verbose", no_arg, 'v', NULL}, 127 {"interval", required_arg, 'I', "seconds"}, 128 {"count", required_arg, 'N', "number"}, 129 {"all", no_arg, 'A', NULL}, 130 {NULL, 0, 0, 0} 131 }; 132 133 /* 134 * Add new subcommands here 135 */ 136 subcommand_t subcommands[] = { 137 {"create", CREATE, createFunc}, 138 {"list", LIST, listFunc}, 139 {"modify", MODIFY, modifyFunc}, 140 {"delete", DELETE, deleteFunc}, 141 {"show", SHOW, showFunc}, 142 {NULL, 0, NULL} 143 }; 144 145 /* 146 * Add objects here 147 */ 148 object_t objects[] = { 149 {"target", TARGET}, 150 {"initiator", INITIATOR}, 151 {"admin", ADMIN}, 152 {"tpgt", TPGT}, 153 {"stats", STATS}, 154 {NULL, 0} 155 }; 156 157 /* 158 * Rules for subcommands and objects 159 * ReqiredOp, OptioalOp, NoOp, InvalidOp, MultiOp 160 */ 161 objectRules_t objectRules[] = { 162 /* 163 * create/modify/delete subcmd requires an operand 164 * list subcmd optionally requires an operand 165 * no subcmd requires no operand 166 * no subcmd is invalid for this operand 167 * no subcmd can accept multiple operands 168 */ 169 {TARGET, CREATE|MODIFY|DELETE, LIST, 0, SHOW, 0, "local-target"}, 170 /* 171 * create/modify/delete subcmd requires an operand 172 * list subcmd optionally requires an operand 173 * no subcmd requires no operand 174 * no subcmd is invalid for this operand 175 * no subcmd can accept multiple operands 176 */ 177 {INITIATOR, CREATE|MODIFY|DELETE, LIST, 0, SHOW, 0, "local-initiator"}, 178 /* 179 * no subcmd requires an operand 180 * no subcmd optionally requires an operand 181 * modify/list subcmd requires no operand 182 * create/delete subcmd are invlaid for this operand 183 * no subcmd can accept multiple operands 184 */ 185 {ADMIN, 0, 0, MODIFY|SHOW, CREATE|DELETE|LIST, 0, NULL}, 186 /* 187 * create/modify/delete subcmd requires an operand 188 * list subcmd optionally requires an operand 189 * no subcmd requires no operand 190 * no subcmd is invalid for this operand 191 * no subcmd can accept multiple operands 192 */ 193 {TPGT, CREATE|MODIFY|DELETE, LIST, 0, SHOW, 0, "local-tpgt"}, 194 /* 195 * no subcmd requires an operand 196 * list subcmd optionally requires an operand 197 * no subcmd requires no operand 198 * create/delete/modify subcmd are invalid for this operand 199 * no subcmd can accept multiple operands 200 */ 201 {STATS, 0, SHOW, 0, CREATE|MODIFY|DELETE|LIST, 0, "local-target"}, 202 {0, 0, 0, 0, 0, NULL} 203 }; 204 205 /* 206 * list of objects, subcommands, valid short options, required flag and 207 * exclusive option string 208 * 209 * If it's not here, there are no options for that object. 210 */ 211 optionRules_t optionRules[] = { 212 {TARGET, CREATE, "tuzab", B_TRUE, NULL}, 213 {TARGET, MODIFY, "plamzu", B_TRUE, NULL}, 214 {TARGET, DELETE, "ulp", B_TRUE, NULL}, 215 {TARGET, LIST, "v", B_FALSE, NULL}, 216 {INITIATOR, CREATE, "n", B_TRUE, NULL}, 217 {INITIATOR, MODIFY, "CH", B_TRUE, NULL}, 218 {INITIATOR, DELETE, "A", B_TRUE, NULL}, 219 {INITIATOR, LIST, "v", B_FALSE, NULL}, 220 {TPGT, MODIFY, "i", B_TRUE, NULL}, 221 {TPGT, DELETE, "Ai", B_TRUE, NULL}, 222 {TPGT, LIST, "v", B_FALSE, NULL}, 223 {ADMIN, MODIFY, "dHCRrPSsf", B_TRUE, NULL}, 224 {STATS, SHOW, "IN", B_FALSE, NULL}, 225 }; 226 227 228 229 /*ARGSUSED*/ 230 static int 231 createFunc(int operandLen, char *operand[], int object, cmdOptions_t *options, 232 void *addArgs) 233 { 234 int ret; 235 236 switch (object) { 237 case TARGET: 238 ret = createTarget(operandLen, operand, options); 239 break; 240 case INITIATOR: 241 ret = createInitiator(operandLen, operand, options); 242 break; 243 case TPGT: 244 ret = createTpgt(operandLen, operand, options); 245 break; 246 default: 247 (void) fprintf(stderr, "%s: %s\n", 248 cmdName, gettext("unknown object")); 249 ret = 1; 250 break; 251 } 252 return (ret); 253 } 254 255 /*ARGSUSED*/ 256 static int 257 listFunc(int operandLen, char *operand[], int object, cmdOptions_t *options, 258 void *addArgs) 259 { 260 int ret; 261 262 switch (object) { 263 case TARGET: 264 ret = listTarget(operandLen, operand, options); 265 break; 266 case INITIATOR: 267 ret = listInitiator(operandLen, operand, options); 268 break; 269 case TPGT: 270 ret = listTpgt(operandLen, operand, options); 271 break; 272 default: 273 (void) fprintf(stderr, "%s: %s\n", 274 cmdName, gettext("unknown object")); 275 ret = 1; 276 break; 277 } 278 return (ret); 279 } 280 281 /*ARGSUSED*/ 282 static int 283 showFunc(int operandLen, char *operand[], int object, cmdOptions_t *options, 284 void *addArgs) 285 { 286 int ret; 287 288 switch (object) { 289 case STATS: 290 ret = showStats(operandLen, operand, options); 291 break; 292 case ADMIN: 293 ret = showAdmin(operandLen, operand, options); 294 break; 295 default: 296 (void) fprintf(stderr, "%s: %s\n", 297 cmdName, gettext("unknown object")); 298 ret = 1; 299 break; 300 } 301 return (ret); 302 } 303 304 /*ARGSUSED*/ 305 static int 306 modifyFunc(int operandLen, char *operand[], int object, cmdOptions_t *options, 307 void *addArgs) 308 { 309 int ret; 310 311 switch (object) { 312 case TARGET: 313 ret = modifyTarget(operandLen, operand, options); 314 break; 315 case INITIATOR: 316 ret = modifyInitiator(operandLen, operand, options); 317 break; 318 case TPGT: 319 ret = modifyTpgt(operandLen, operand, options); 320 break; 321 case ADMIN: 322 ret = modifyAdmin(operandLen, operand, options); 323 break; 324 default: 325 (void) fprintf(stderr, "%s: %s\n", 326 cmdName, gettext("unknown object")); 327 ret = 1; 328 break; 329 } 330 return (ret); 331 } 332 333 /*ARGSUSED*/ 334 static int 335 deleteFunc(int operandLen, char *operand[], int object, cmdOptions_t *options, 336 void *addArgs) 337 { 338 int ret; 339 340 switch (object) { 341 case TARGET: 342 ret = deleteTarget(operandLen, operand, options); 343 break; 344 case INITIATOR: 345 ret = deleteInitiator(operandLen, operand, options); 346 break; 347 case TPGT: 348 ret = deleteTpgt(operandLen, operand, options); 349 break; 350 default: 351 (void) fprintf(stderr, "%s: %s\n", 352 cmdName, gettext("unknown object")); 353 ret = 1; 354 break; 355 } 356 return (ret); 357 } 358 359 static int 360 formatErrString(tgt_node_t *node) 361 { 362 int code = 0; 363 int rtn = 0; 364 char *msg = NULL; 365 366 if (node == NULL) { 367 (void) fprintf(stderr, "%s: %s\n", cmdName, 368 gettext("Unable to contact target daemon")); 369 return (1); 370 } 371 if ((strcmp(node->x_name, XML_ELEMENT_ERROR) == 0) && 372 (tgt_find_value_int(node, XML_ELEMENT_CODE, &code) == B_TRUE) && 373 (tgt_find_value_str(node, XML_ELEMENT_MESSAGE, &msg) == B_TRUE)) { 374 375 /* 376 * 1000 is the success code, so we don't need to display 377 * the success message. 378 */ 379 if (code != 1000) { 380 (void) fprintf(stderr, "%s: %s %s\n", 381 cmdName, gettext("Error"), msg); 382 rtn = 1; 383 } 384 } else { 385 (void) fprintf(stderr, "%s: %s\n", cmdName, 386 gettext("Bad XML response")); 387 rtn = 1; 388 } 389 if (msg) 390 free(msg); 391 return (rtn); 392 } 393 394 /*ARGSUSED*/ 395 static int 396 createTarget(int operandLen, char *operand[], cmdOptions_t *options) 397 { 398 char *first_str = NULL; 399 tgt_node_t *node; 400 cmdOptions_t *optionList = options; 401 402 if (operand == NULL) 403 return (1); 404 405 tgt_buf_add_tag(&first_str, "create", Tag_Start); 406 tgt_buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_Start); 407 tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]); 408 409 for (; optionList->optval; optionList++) { 410 switch (optionList->optval) { 411 case 't': /* type */ 412 if ((strcmp(optionList->optarg, "disk")) && 413 (strcmp(optionList->optarg, "tape")) && 414 (strcmp(optionList->optarg, "raw")) && 415 (strcmp(optionList->optarg, "osd"))) { 416 (void) fprintf(stderr, "%s: %c: %s\n", 417 cmdName, optionList->optval, 418 gettext("unknown type")); 419 free(first_str); 420 return (1); 421 } else { 422 tgt_buf_add(&first_str, 423 XML_ELEMENT_TYPE, 424 optionList->optarg); 425 } 426 break; 427 case 'z': /* size */ 428 tgt_buf_add(&first_str, XML_ELEMENT_SIZE, 429 optionList->optarg); 430 break; 431 case 'u': /* lun number */ 432 tgt_buf_add(&first_str, XML_ELEMENT_LUN, 433 optionList->optarg); 434 break; 435 case 'a': /* alias */ 436 tgt_buf_add(&first_str, XML_ELEMENT_ALIAS, 437 optionList->optarg); 438 break; 439 case 'b': /* backing store */ 440 tgt_buf_add(&first_str, XML_ELEMENT_BACK, 441 optionList->optarg); 442 break; 443 default: 444 (void) fprintf(stderr, "%s: %c: %s\n", 445 cmdName, optionList->optval, 446 gettext("unknown option")); 447 free(first_str); 448 return (1); 449 } 450 } 451 452 tgt_buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_End); 453 tgt_buf_add_tag(&first_str, "create", Tag_End); 454 455 node = tgt_door_call(first_str, 0); 456 free(first_str); 457 return (formatErrString(node)); 458 } 459 460 /*ARGSUSED*/ 461 static int 462 createInitiator(int operandLen, char *operand[], cmdOptions_t *options) 463 { 464 char *first_str = NULL; 465 tgt_node_t *node; 466 cmdOptions_t *optionList = options; 467 468 if (operand == NULL) 469 return (1); 470 if (options == NULL) 471 return (1); 472 473 tgt_buf_add_tag(&first_str, "create", Tag_Start); 474 tgt_buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_Start); 475 tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]); 476 477 switch (optionList->optval) { 478 case 'n': /* iqn */ 479 tgt_buf_add(&first_str, XML_ELEMENT_INAME, optionList->optarg); 480 break; 481 default: 482 (void) fprintf(stderr, "%s: %c: %s\n", 483 cmdName, optionList->optval, 484 gettext("unknown option")); 485 free(first_str); 486 return (1); 487 } 488 489 tgt_buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_End); 490 tgt_buf_add_tag(&first_str, "create", Tag_End); 491 492 node = tgt_door_call(first_str, 0); 493 free(first_str); 494 return (formatErrString(node)); 495 } 496 497 /*ARGSUSED*/ 498 static int 499 createTpgt(int operandLen, char *operand[], cmdOptions_t *options) 500 { 501 char *first_str = NULL; 502 tgt_node_t *node; 503 504 if (operand == NULL) 505 return (1); 506 507 tgt_buf_add_tag(&first_str, "create", Tag_Start); 508 tgt_buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_Start); 509 tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]); 510 tgt_buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_End); 511 tgt_buf_add_tag(&first_str, "create", Tag_End); 512 513 node = tgt_door_call(first_str, 0); 514 free(first_str); 515 return (formatErrString(node)); 516 } 517 518 /*ARGSUSED*/ 519 static int 520 modifyTarget(int operandLen, char *operand[], cmdOptions_t *options) 521 { 522 char *first_str = NULL; 523 tgt_node_t *node; 524 cmdOptions_t *optionList = options; 525 526 if (operand == NULL) 527 return (1); 528 529 tgt_buf_add_tag(&first_str, "modify", Tag_Start); 530 tgt_buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_Start); 531 tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]); 532 533 for (; optionList->optval; optionList++) { 534 switch (optionList->optval) { 535 case 'p': /* tpgt number */ 536 tgt_buf_add(&first_str, XML_ELEMENT_TPGT, 537 optionList->optarg); 538 break; 539 case 'l': /* acl */ 540 tgt_buf_add(&first_str, XML_ELEMENT_ACL, 541 optionList->optarg); 542 break; 543 case 'a': /* alias */ 544 tgt_buf_add(&first_str, XML_ELEMENT_ALIAS, 545 optionList->optarg); 546 break; 547 case 'm': /* max recv */ 548 tgt_buf_add(&first_str, XML_ELEMENT_MAXRECV, 549 optionList->optarg); 550 break; 551 case 'z': /* grow lun size */ 552 tgt_buf_add(&first_str, XML_ELEMENT_SIZE, 553 optionList->optarg); 554 break; 555 case 'u': 556 tgt_buf_add(&first_str, XML_ELEMENT_LUN, 557 optionList->optarg); 558 break; 559 default: 560 (void) fprintf(stderr, "%s: %c: %s\n", 561 cmdName, optionList->optval, 562 gettext("unknown option")); 563 free(first_str); 564 return (1); 565 } 566 } 567 568 tgt_buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_End); 569 tgt_buf_add_tag(&first_str, "modify", Tag_End); 570 571 node = tgt_door_call(first_str, 0); 572 free(first_str); 573 return (formatErrString(node)); 574 } 575 576 /*ARGSUSED*/ 577 static int 578 modifyInitiator(int operandLen, char *operand[], cmdOptions_t *options) 579 { 580 char *first_str = NULL; 581 tgt_node_t *node; 582 cmdOptions_t *optionList = options; 583 char chapSecret[MAX_CHAP_SECRET_LEN+1]; 584 int secretLen = 0; 585 int ret = 0; 586 587 if (operand == NULL) 588 return (1); 589 if (options == NULL) 590 return (1); 591 592 tgt_buf_add_tag(&first_str, "modify", Tag_Start); 593 tgt_buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_Start); 594 tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]); 595 596 for (; optionList->optval; optionList++) { 597 switch (optionList->optval) { 598 case 'H': /* chap-name */ 599 if (strlen(optionList->optarg) != 0) { 600 tgt_buf_add(&first_str, XML_ELEMENT_CHAPNAME, 601 optionList->optarg); 602 } else { 603 tgt_buf_add(&first_str, 604 XML_ELEMENT_DELETE_CHAPNAME, 605 OPT_TRUE); 606 } 607 break; 608 case 'C': /* chap-secret */ 609 ret = getSecret((char *)&chapSecret[0], &secretLen, 610 MIN_CHAP_SECRET_LEN, MAX_CHAP_SECRET_LEN); 611 if (ret != 0) { 612 (void) fprintf(stderr, "%s: %s\n", cmdName, 613 gettext("Cannot read CHAP secret")); 614 return (ret); 615 } 616 chapSecret[secretLen] = '\0'; 617 if (secretLen != 0) { 618 tgt_buf_add(&first_str, XML_ELEMENT_CHAPSECRET, 619 chapSecret); 620 } else { 621 tgt_buf_add(&first_str, 622 XML_ELEMENT_DELETE_CHAPSECRET, 623 OPT_TRUE); 624 } 625 break; 626 default: 627 (void) fprintf(stderr, "%s: %c: %s\n", 628 cmdName, optionList->optval, 629 gettext("unknown option")); 630 free(first_str); 631 return (1); 632 } 633 } 634 tgt_buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_End); 635 tgt_buf_add_tag(&first_str, "modify", Tag_End); 636 637 node = tgt_door_call(first_str, 0); 638 free(first_str); 639 return (formatErrString(node)); 640 } 641 642 /*ARGSUSED*/ 643 static int 644 modifyTpgt(int operandLen, char *operand[], cmdOptions_t *options) 645 { 646 char *first_str = NULL; 647 tgt_node_t *node; 648 cmdOptions_t *optionList = options; 649 boolean_t isIpv6 = B_FALSE; 650 uint16_t port; 651 char IpAddress[MAX_IPADDRESS_LEN]; 652 653 if (operand == NULL) 654 return (1); 655 if (optionList == NULL) 656 return (1); 657 658 tgt_buf_add_tag(&first_str, "modify", Tag_Start); 659 tgt_buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_Start); 660 tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]); 661 662 switch (optionList->optval) { 663 case 'i': /* ip address */ 664 if (parseAddress(optionList->optarg, 0, 665 IpAddress, 256, &port, &isIpv6) != 666 PARSE_ADDR_OK) { 667 return (1); 668 } 669 tgt_buf_add(&first_str, XML_ELEMENT_IPADDR, IpAddress); 670 break; 671 default: 672 (void) fprintf(stderr, "%s: %c: %s\n", 673 cmdName, optionList->optval, 674 gettext("unknown option")); 675 free(first_str); 676 return (1); 677 } 678 679 tgt_buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_End); 680 tgt_buf_add_tag(&first_str, "modify", Tag_End); 681 682 node = tgt_door_call(first_str, 0); 683 free(first_str); 684 return (formatErrString(node)); 685 } 686 687 /*ARGSUSED*/ 688 static int 689 modifyAdmin(int operandLen, char *operand[], cmdOptions_t *options) 690 { 691 char *first_str = NULL; 692 tgt_node_t *node; 693 cmdOptions_t *optionList = options; 694 char chapSecret[MAX_CHAP_SECRET_LEN+1]; 695 char olddir[MAXPATHLEN]; 696 char newdir[MAXPATHLEN]; 697 int secretLen = 0; 698 int ret = 0; 699 700 if (operand == NULL) 701 return (1); 702 if (options == NULL) 703 return (1); 704 705 tgt_buf_add_tag(&first_str, "modify", Tag_Start); 706 tgt_buf_add_tag(&first_str, XML_ELEMENT_ADMIN, Tag_Start); 707 tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]); 708 709 for (; optionList->optval; optionList++) { 710 switch (optionList->optval) { 711 case 'd': /* base directory */ 712 (void) getcwd(olddir, sizeof (olddir)); 713 714 /* 715 * Attempt to create the new base directory. 716 * This may fail for one of two reasons. 717 * (a) The path given is invalid or (b) it 718 * already exists. If (a) is true then then 719 * following chdir() will fail and the user 720 * notified. If (b) is true, then chdir() will 721 * succeed. 722 */ 723 (void) mkdir(optionList->optarg, 0700); 724 725 if (chdir(optionList->optarg) == -1) { 726 (void) fprintf(stderr, "%s: %s\n", 727 cmdName, gettext("Invalid path")); 728 free(first_str); 729 return (1); 730 } 731 (void) getcwd(newdir, sizeof (newdir)); 732 tgt_buf_add(&first_str, XML_ELEMENT_BASEDIR, 733 newdir); 734 (void) chdir(olddir); 735 break; 736 case 'H': /* chap name */ 737 if (strlen(optionList->optarg) != 0) { 738 tgt_buf_add(&first_str, 739 XML_ELEMENT_CHAPNAME, 740 optionList->optarg); 741 } else { 742 tgt_buf_add(&first_str, 743 XML_ELEMENT_DELETE_CHAPNAME, 744 OPT_TRUE); 745 } 746 break; 747 case 'C': /* chap secert */ 748 ret = getSecret((char *)&chapSecret[0], 749 &secretLen, 750 MIN_CHAP_SECRET_LEN, 751 MAX_CHAP_SECRET_LEN); 752 if (ret != 0) { 753 (void) fprintf(stderr, "%s: %s\n", 754 cmdName, 755 gettext("Cannot read CHAP secret")); 756 free(first_str); 757 return (ret); 758 } 759 chapSecret[secretLen] = '\0'; 760 if (secretLen != 0) { 761 tgt_buf_add(&first_str, 762 XML_ELEMENT_CHAPSECRET, 763 chapSecret); 764 } else { 765 tgt_buf_add(&first_str, 766 XML_ELEMENT_DELETE_CHAPSECRET, 767 OPT_TRUE); 768 } 769 break; 770 case 'R': /* radius access */ 771 if (strcmp(optionList->optarg, 772 OPT_ENABLE) == 0) { 773 tgt_buf_add(&first_str, 774 XML_ELEMENT_RAD_ACCESS, OPT_TRUE); 775 } else 776 if (strcmp(optionList->optarg, 777 OPT_DISABLE) == 0) { 778 tgt_buf_add(&first_str, 779 XML_ELEMENT_RAD_ACCESS, OPT_FALSE); 780 } else { 781 (void) fprintf(stderr, "%s: %s\n", 782 cmdName, 783 gettext("Option value should be" 784 "enable/disable")); 785 free(first_str); 786 return (1); 787 } 788 break; 789 case 'r': /* radius server */ 790 if (strlen(optionList->optarg) != 0) { 791 tgt_buf_add(&first_str, 792 XML_ELEMENT_RAD_SERV, 793 optionList->optarg); 794 } else { 795 tgt_buf_add(&first_str, 796 XML_ELEMENT_DELETE_RAD_SERV, 797 OPT_TRUE); 798 } 799 break; 800 case 'P': /* radius secret */ 801 ret = getSecret((char *)&chapSecret[0], 802 &secretLen, MIN_CHAP_SECRET_LEN, 803 MAX_CHAP_SECRET_LEN); 804 if (ret != 0) { 805 (void) fprintf(stderr, "%s: %s\n", 806 cmdName, 807 gettext("Cannot read RADIUS " 808 "secret")); 809 free(first_str); 810 return (ret); 811 } 812 chapSecret[secretLen] = '\0'; 813 if (secretLen != 0) { 814 tgt_buf_add(&first_str, 815 XML_ELEMENT_RAD_SECRET, 816 chapSecret); 817 } else { 818 tgt_buf_add(&first_str, 819 XML_ELEMENT_DELETE_RAD_SECRET, 820 OPT_TRUE); 821 } 822 break; 823 case 'S': /* iSNS access */ 824 if (strcmp(optionList->optarg, 825 OPT_ENABLE) == 0) { 826 tgt_buf_add(&first_str, 827 XML_ELEMENT_ISNS_ACCESS, OPT_TRUE); 828 } else 829 if (strcmp(optionList->optarg, 830 OPT_DISABLE) == 0) { 831 tgt_buf_add(&first_str, 832 XML_ELEMENT_ISNS_ACCESS, OPT_FALSE); 833 } else { 834 (void) fprintf(stderr, "%s: %s\n", 835 cmdName, 836 gettext("Option value should be" 837 "enable/disable")); 838 free(first_str); 839 return (1); 840 } 841 break; 842 case 's': /* iSNS server */ 843 if (strlen(optionList->optarg) > 844 MAXHOSTNAMELEN) { 845 (void) fprintf(stderr, "%s: %s\n", 846 cmdName, 847 gettext("option too long")); 848 return (1); 849 } 850 tgt_buf_add(&first_str, XML_ELEMENT_ISNS_SERV, 851 optionList->optarg); 852 break; 853 case 'f': /* fast write back */ 854 if (strcmp(optionList->optarg, 855 OPT_ENABLE) == 0) { 856 tgt_buf_add(&first_str, 857 XML_ELEMENT_FAST, OPT_TRUE); 858 } else 859 if (strcmp(optionList->optarg, 860 OPT_DISABLE) == 0) { 861 tgt_buf_add(&first_str, 862 XML_ELEMENT_FAST, OPT_FALSE); 863 } else { 864 (void) fprintf(stderr, "%s: %s\n", 865 cmdName, 866 gettext("Option value should be" 867 "enable/disable")); 868 free(first_str); 869 return (1); 870 } 871 break; 872 default: 873 (void) fprintf(stderr, "%s: %c: %s\n", 874 cmdName, optionList->optval, 875 gettext("unknown option")); 876 free(first_str); 877 return (1); 878 } 879 } 880 881 tgt_buf_add_tag(&first_str, XML_ELEMENT_ADMIN, Tag_End); 882 tgt_buf_add_tag(&first_str, "modify", Tag_End); 883 884 node = tgt_door_call(first_str, 0); 885 free(first_str); 886 return (formatErrString(node)); 887 } 888 889 /*ARGSUSED*/ 890 static int 891 deleteTarget(int operandLen, char *operand[], cmdOptions_t *options) 892 { 893 char *first_str = NULL; 894 tgt_node_t *node; 895 cmdOptions_t *optionList = options; 896 897 if (operand == NULL) 898 return (1); 899 if (options == NULL) 900 return (1); 901 902 tgt_buf_add_tag(&first_str, "delete", Tag_Start); 903 tgt_buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_Start); 904 tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]); 905 906 switch (optionList->optval) { 907 case 'u': /* all */ 908 tgt_buf_add(&first_str, XML_ELEMENT_LUN, optionList->optarg); 909 break; 910 case 'l': /* acl */ 911 tgt_buf_add(&first_str, XML_ELEMENT_ACL, optionList->optarg); 912 break; 913 case 'p': /* tpgt number */ 914 tgt_buf_add(&first_str, XML_ELEMENT_TPGT, optionList->optarg); 915 break; 916 default: 917 (void) fprintf(stderr, "%s: %c: %s\n", 918 cmdName, optionList->optval, 919 gettext("unknown option")); 920 free(first_str); 921 return (1); 922 } 923 924 tgt_buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_End); 925 tgt_buf_add_tag(&first_str, "delete", Tag_End); 926 927 node = tgt_door_call(first_str, 0); 928 free(first_str); 929 return (formatErrString(node)); 930 } 931 932 /*ARGSUSED*/ 933 static int 934 deleteInitiator(int operandLen, char *operand[], cmdOptions_t *options) 935 { 936 char *first_str = NULL; 937 tgt_node_t *node; 938 cmdOptions_t *optionList = options; 939 940 if (operand == NULL) 941 return (1); 942 if (options == NULL) 943 return (1); 944 945 tgt_buf_add_tag(&first_str, "delete", Tag_Start); 946 tgt_buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_Start); 947 tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]); 948 949 switch (optionList->optval) { 950 case 'A': /* all */ 951 tgt_buf_add(&first_str, XML_ELEMENT_ALL, optionList->optarg); 952 break; 953 default: 954 (void) fprintf(stderr, "%s: %c: %s\n", 955 cmdName, optionList->optval, 956 gettext("unknown option")); 957 free(first_str); 958 return (1); 959 } 960 961 tgt_buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_End); 962 tgt_buf_add_tag(&first_str, "delete", Tag_End); 963 964 node = tgt_door_call(first_str, 0); 965 free(first_str); 966 return (formatErrString(node)); 967 } 968 969 /*ARGSUSED*/ 970 static int 971 deleteTpgt(int operandLen, char *operand[], cmdOptions_t *options) 972 { 973 char *first_str = NULL; 974 tgt_node_t *node; 975 cmdOptions_t *optionList = options; 976 boolean_t isIpv6 = B_FALSE; 977 uint16_t port; 978 char IpAddress[MAX_IPADDRESS_LEN]; 979 980 if (operand == NULL) 981 return (1); 982 if (options == NULL) 983 return (1); 984 985 tgt_buf_add_tag(&first_str, "delete", Tag_Start); 986 tgt_buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_Start); 987 tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]); 988 989 switch (optionList->optval) { 990 case 'A': /* all */ 991 tgt_buf_add(&first_str, XML_ELEMENT_ALL, optionList->optarg); 992 break; 993 case 'i': /* ip address */ 994 if (parseAddress(optionList->optarg, 0, 995 IpAddress, 256, &port, &isIpv6) != 996 PARSE_ADDR_OK) { 997 return (1); 998 } 999 tgt_buf_add(&first_str, XML_ELEMENT_IPADDR, IpAddress); 1000 break; 1001 default: 1002 (void) fprintf(stderr, "%s: %c: %s\n", 1003 cmdName, optionList->optval, 1004 gettext("unknown option")); 1005 free(first_str); 1006 return (1); 1007 } 1008 1009 tgt_buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_End); 1010 tgt_buf_add_tag(&first_str, "delete", Tag_End); 1011 1012 node = tgt_door_call(first_str, 0); 1013 free(first_str); 1014 return (formatErrString(node)); 1015 } 1016 1017 static int 1018 listTarget(int operandLen, char *operand[], cmdOptions_t *options) 1019 { 1020 char *first_str = NULL; 1021 tgt_node_t *node = NULL; 1022 tgt_node_t *n1 = NULL; /* pointer to node (depth=1) */ 1023 tgt_node_t *n2 = NULL; /* pointer to node (depth=2) */ 1024 tgt_node_t *n3 = NULL; /* pointer to node (depth=3) */ 1025 tgt_node_t *n4 = NULL; /* pointer to node (depth=4) */ 1026 int conns; 1027 char buf[32]; 1028 Boolean_t verbose = False; 1029 1030 if (operand == NULL) 1031 return (1); 1032 1033 tgt_buf_add_tag(&first_str, "list", Tag_Start); 1034 tgt_buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_Start); 1035 1036 if (operandLen) 1037 tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]); 1038 1039 /* 1040 * Always retrieve the iostats which will give us the 1041 * connection count information even if we're not doing 1042 * a verbose output. 1043 */ 1044 tgt_buf_add(&first_str, XML_ELEMENT_IOSTAT, OPT_TRUE); 1045 1046 if (options) { 1047 switch (options->optval) { 1048 case 0: 1049 break; 1050 case 'v': 1051 tgt_buf_add(&first_str, XML_ELEMENT_LUNINFO, OPT_TRUE); 1052 verbose = True; 1053 break; 1054 default: 1055 (void) fprintf(stderr, "%s: %c: %s\n", cmdName, 1056 options->optval, gettext("unknown option")); 1057 free(first_str); 1058 return (1); 1059 } 1060 } 1061 1062 tgt_buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_End); 1063 tgt_buf_add_tag(&first_str, "list", Tag_End); 1064 1065 if ((node = tgt_door_call(first_str, 0)) == NULL) { 1066 (void) fprintf(stderr, "%s: %s\n", cmdName, 1067 gettext("No reponse from daemon")); 1068 return (1); 1069 } 1070 free(first_str); 1071 1072 if (strcmp(node->x_name, XML_ELEMENT_RESULT)) { 1073 (void) fprintf(stderr, "%s: %s\n", cmdName, 1074 gettext("Bad XML response")); 1075 return (1); 1076 } 1077 1078 n1 = NULL; 1079 while ((n1 = tgt_node_next_child(node, XML_ELEMENT_TARG, n1)) != NULL) { 1080 (void) printf("%s: %s\n", gettext("Target"), n1->x_value); 1081 n2 = tgt_node_next_child(n1, XML_ELEMENT_INAME, NULL); 1082 (void) printf("%s%s: %s\n", dospace(1), gettext("iSCSI Name"), 1083 n2 ? n2->x_value : gettext("Not set")); 1084 1085 if ((n2 = tgt_node_next_child(n1, XML_ELEMENT_ALIAS, NULL)) != 1086 NULL) 1087 (void) printf("%s%s: %s\n", dospace(1), 1088 gettext("Alias"), n2->x_value); 1089 1090 if ((n2 = tgt_node_next_child(n1, XML_ELEMENT_MAXRECV, NULL)) != 1091 NULL) 1092 (void) printf("%s%s: %s\n", dospace(1), 1093 gettext("MaxRecv"), n2->x_value); 1094 1095 /* 1096 * Count the number of connections available. 1097 */ 1098 n2 = NULL; 1099 conns = 0; 1100 while (n2 = tgt_node_next_child(n1, XML_ELEMENT_CONN, n2)) 1101 conns++; 1102 (void) printf("%s%s: %d\n", dospace(1), gettext("Connections"), 1103 conns); 1104 1105 if (verbose == False) 1106 continue; 1107 1108 /* 1109 * Displaying the individual connections must be done 1110 * first when verbose is turned on because you'll notice 1111 * above that we've left the output hanging with a label 1112 * indicating connections are coming next. 1113 */ 1114 n2 = NULL; 1115 while (n2 = tgt_node_next_child(n1, XML_ELEMENT_CONN, n2)) { 1116 (void) printf("%s%s:\n", dospace(2), 1117 gettext("Initiator")); 1118 (void) printf("%s%s: %s\n", dospace(3), 1119 gettext("iSCSI Name"), n2->x_value); 1120 n3 = tgt_node_next_child(n2, XML_ELEMENT_ALIAS, NULL); 1121 (void) printf("%s%s: %s\n", dospace(3), 1122 gettext("Alias"), 1123 n3 ? n3->x_value : gettext("unknown")); 1124 } 1125 1126 (void) printf("%s%s:\n", dospace(1), gettext("ACL list")); 1127 n2 = tgt_node_next_child(n1, XML_ELEMENT_ACLLIST, NULL); 1128 n3 = NULL; 1129 while (n3 = tgt_node_next_child(n2, XML_ELEMENT_INIT, n3)) { 1130 (void) printf("%s%s: %s\n", dospace(2), 1131 gettext("Initiator"), 1132 n3->x_value); 1133 } 1134 1135 (void) printf("%s%s:\n", dospace(1), gettext("TPGT list")); 1136 n2 = tgt_node_next_child(n1, XML_ELEMENT_TPGTLIST, NULL); 1137 n3 = NULL; 1138 while (n3 = tgt_node_next_child(n2, XML_ELEMENT_TPGT, n3)) { 1139 (void) printf("%s%s: %s\n", dospace(2), 1140 gettext("TPGT"), 1141 n3->x_value); 1142 } 1143 1144 (void) printf("%s%s:\n", dospace(1), 1145 gettext("LUN information")); 1146 n2 = tgt_node_next_child(n1, XML_ELEMENT_LUNINFO, NULL); 1147 n3 = NULL; 1148 while (n3 = tgt_node_next_child(n2, XML_ELEMENT_LUN, n3)) { 1149 (void) printf("%s%s: %s\n", dospace(2), gettext("LUN"), 1150 n3->x_value); 1151 1152 n4 = tgt_node_next_child(n3, XML_ELEMENT_GUID, NULL); 1153 (void) printf("%s%s: %s\n", dospace(3), gettext("GUID"), 1154 n4 ? n4->x_value : gettext("unknown")); 1155 1156 n4 = tgt_node_next_child(n3, XML_ELEMENT_VID, NULL); 1157 (void) printf("%s%s: %s\n", dospace(3), gettext("VID"), 1158 n4 ? n4->x_value : gettext("unknown")); 1159 1160 n4 = tgt_node_next_child(n3, XML_ELEMENT_PID, NULL); 1161 (void) printf("%s%s: %s\n", dospace(3), gettext("PID"), 1162 n4 ? n4->x_value : gettext("unknown")); 1163 1164 n4 = tgt_node_next_child(n3, XML_ELEMENT_DTYPE, NULL); 1165 (void) printf("%s%s: %s\n", dospace(3), gettext("Type"), 1166 n4 ? n4->x_value : gettext("unknown")); 1167 1168 n4 = tgt_node_next_child(n3, XML_ELEMENT_SIZE, NULL); 1169 if (n4 && (strtol(n4->x_value, NULL, 0) != 0)) { 1170 (void) printf("%s%s: %s\n", dospace(3), 1171 gettext("Size"), 1172 number_to_scaled_string(buf, 1173 strtoll(n4->x_value, 1174 NULL, 0), 512, 1024)); 1175 } else { 1176 (void) printf("%s%s: %s\n", dospace(3), 1177 gettext("Size"), gettext("unknown")); 1178 } 1179 1180 n4 = tgt_node_next_child(n3, XML_ELEMENT_BACK, NULL); 1181 if (n4) { 1182 (void) printf("%s%s: %s\n", dospace(3), 1183 gettext("Backing store"), n4->x_value); 1184 } 1185 1186 n4 = tgt_node_next_child(n3, XML_ELEMENT_STATUS, NULL); 1187 (void) printf("%s%s: %s\n", dospace(3), 1188 gettext("Status"), 1189 n4 ? n4->x_value : gettext("unknown")); 1190 } 1191 } 1192 1193 return (0); 1194 } 1195 1196 static int 1197 listInitiator(int operandLen, char *operand[], cmdOptions_t *options) 1198 { 1199 char *first_str = NULL; 1200 tgt_node_t *node; 1201 tgt_node_t *n1 = NULL; /* pointer to node (depth=1) */ 1202 tgt_node_t *n2 = NULL; /* pointer to node (depth=2) */ 1203 Boolean_t verbose = False; 1204 cmdOptions_t *optionList = options; 1205 1206 if (operand == NULL) 1207 return (1); 1208 1209 tgt_buf_add_tag(&first_str, "list", Tag_Start); 1210 tgt_buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_Start); 1211 1212 if (operandLen) { 1213 tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]); 1214 } 1215 if (optionList) { 1216 switch (optionList->optval) { 1217 case 0: 1218 break; 1219 case 'v': 1220 verbose = True; 1221 tgt_buf_add(&first_str, 1222 XML_ELEMENT_VERBOSE, OPT_TRUE); 1223 break; 1224 1225 default: 1226 (void) fprintf(stderr, "%s: %c: %s\n", 1227 cmdName, optionList->optval, 1228 gettext("unknown option")); 1229 free(first_str); 1230 return (1); 1231 } 1232 } 1233 1234 tgt_buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_End); 1235 tgt_buf_add_tag(&first_str, "list", Tag_End); 1236 1237 if ((node = tgt_door_call(first_str, 0)) == NULL) { 1238 (void) fprintf(stderr, "%s: %s\n", cmdName, 1239 gettext("No reponse from daemon")); 1240 return (1); 1241 } 1242 free(first_str); 1243 1244 if (strcmp(node->x_name, XML_ELEMENT_RESULT)) { 1245 (void) fprintf(stderr, "%s: %s\n", cmdName, 1246 gettext("Bad XML response")); 1247 return (1); 1248 } 1249 1250 n1 = NULL; 1251 while (n1 = tgt_node_next_child(node, XML_ELEMENT_INIT, n1)) { 1252 (void) printf("%s: %s\n", gettext("Initiator"), n1->x_value); 1253 1254 n2 = tgt_node_next_child(n1, XML_ELEMENT_INAME, NULL); 1255 (void) printf("%s%s: %s\n", dospace(1), gettext("iSCSI Name"), 1256 n2 ? n2->x_value : gettext("Not set")); 1257 1258 n2 = tgt_node_next_child(n1, XML_ELEMENT_CHAPNAME, NULL); 1259 (void) printf("%s%s: %s\n", dospace(1), gettext("CHAP Name"), 1260 n2 ? n2->x_value : gettext("Not set")); 1261 1262 if (verbose == True) { 1263 n2 = tgt_node_next_child(n1, XML_ELEMENT_CHAPSECRET, 1264 NULL); 1265 (void) printf("%s%s: %s\n", dospace(1), 1266 gettext("CHAP Secret"), 1267 n2 ? gettext("Set") : gettext("Not set")); 1268 } 1269 1270 } 1271 1272 return (0); 1273 } 1274 1275 static int 1276 listTpgt(int operandLen, char *operand[], cmdOptions_t *options) 1277 { 1278 char *first_str = NULL; 1279 tgt_node_t *node = NULL; 1280 tgt_node_t *n1 = NULL; /* pointer to node (depth=1) */ 1281 tgt_node_t *n2 = NULL; /* pointer to node (depth=2) */ 1282 cmdOptions_t *optionList = options; 1283 Boolean_t verbose = False; 1284 int addrs; 1285 1286 if (operand == NULL) 1287 return (1); 1288 1289 tgt_buf_add_tag(&first_str, "list", Tag_Start); 1290 tgt_buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_Start); 1291 1292 if (operandLen) 1293 tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]); 1294 if (optionList) { 1295 switch (optionList->optval) { 1296 case 0: /* no options, treat as --verbose */ 1297 break; 1298 case 'v': 1299 verbose = True; 1300 tgt_buf_add(&first_str, 1301 XML_ELEMENT_VERBOSE, OPT_TRUE); 1302 break; 1303 default: 1304 (void) fprintf(stderr, "%s: %c: %s\n", 1305 cmdName, optionList->optval, 1306 gettext("unknown option")); 1307 free(first_str); 1308 return (1); 1309 } 1310 } 1311 1312 tgt_buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_End); 1313 tgt_buf_add_tag(&first_str, "list", Tag_End); 1314 1315 if ((node = tgt_door_call(first_str, 0)) == NULL) { 1316 (void) fprintf(stderr, "%s: %s\n", cmdName, 1317 gettext("No reponse from daemon")); 1318 return (1); 1319 } 1320 free(first_str); 1321 1322 if (strcmp(node->x_name, XML_ELEMENT_RESULT)) { 1323 (void) fprintf(stderr, "%s: %s\n", cmdName, 1324 gettext("Bad XML response")); 1325 return (1); 1326 } 1327 1328 n1 = NULL; 1329 while (n1 = tgt_node_next_child(node, XML_ELEMENT_TPGT, n1)) { 1330 (void) printf("%s: %s\n", gettext("TPGT"), n1->x_value); 1331 n2 = NULL; 1332 addrs = 0; 1333 while (n2 = tgt_node_next(n1, XML_ELEMENT_IPADDR, n2)) { 1334 if (verbose == True) 1335 (void) printf("%s%s: %s\n", dospace(1), 1336 gettext("IP Address"), 1337 n2 ? n2->x_value : gettext("Not set")); 1338 addrs++; 1339 } 1340 1341 if (verbose == False) { 1342 (void) printf("%s%s: %d\n", dospace(1), 1343 gettext("IP Address count"), addrs); 1344 } else if (addrs == 0) { 1345 1346 /* 1347 * Verbose is true, but there where no addresses 1348 * for this TPGT. To keep the output consistent 1349 * dump a "Not set" string out. 1350 */ 1351 (void) printf("%s%s: %s\n", dospace(1), 1352 gettext("IP Address"), gettext("Not set")); 1353 } 1354 } 1355 1356 return (0); 1357 } 1358 1359 /*ARGSUSED*/ 1360 static int 1361 showAdmin(int operandLen, char *operand[], cmdOptions_t *options) 1362 { 1363 char *first_str = NULL; 1364 tgt_node_t *node = NULL; 1365 tgt_node_t *n1 = NULL; /* pointer to node (depth=1) */ 1366 tgt_node_t *n2 = NULL; /* pointer to node (depth=2) */ 1367 1368 if (operand == NULL) 1369 return (1); 1370 1371 tgt_buf_add_tag(&first_str, "list", Tag_Start); 1372 tgt_buf_add_tag(&first_str, XML_ELEMENT_ADMIN, Tag_Start); 1373 tgt_buf_add_tag(&first_str, XML_ELEMENT_ADMIN, Tag_End); 1374 tgt_buf_add_tag(&first_str, "list", Tag_End); 1375 1376 if ((node = tgt_door_call(first_str, 0)) == NULL) { 1377 (void) fprintf(stderr, "%s: %s\n", cmdName, 1378 gettext("No reponse from daemon")); 1379 return (1); 1380 } 1381 free(first_str); 1382 1383 if (strcmp(node->x_name, XML_ELEMENT_RESULT)) { 1384 (void) fprintf(stderr, "%s: %s\n", cmdName, 1385 gettext("Bad XML response")); 1386 return (1); 1387 } 1388 1389 (void) printf("%s:\n", cmdName); 1390 1391 n1 = tgt_node_next_child(node, XML_ELEMENT_ADMIN, NULL); 1392 if (n1 == NULL) { 1393 (void) fprintf(stderr, "%s: %s\n", cmdName, 1394 gettext("Bad XML response")); 1395 return (1); 1396 } 1397 1398 n2 = tgt_node_next_child(n1, XML_ELEMENT_BASEDIR, NULL); 1399 (void) printf("%s%s: %s\n", dospace(1), gettext("Base Directory"), 1400 n2 ? n2->x_value : gettext("Not set")); 1401 1402 n2 = tgt_node_next_child(n1, XML_ELEMENT_CHAPNAME, NULL); 1403 (void) printf("%s%s: %s\n", dospace(1), gettext("CHAP Name"), 1404 n2 ? n2->x_value : gettext("Not set")); 1405 1406 n2 = tgt_node_next_child(n1, XML_ELEMENT_RAD_ACCESS, NULL); 1407 (void) printf("%s%s: ", dospace(1), gettext("RADIUS Access")); 1408 if (n2) { 1409 if (strcmp(n2->x_value, OPT_TRUE) == 0) 1410 (void) printf("%s\n", gettext("Enabled")); 1411 else 1412 (void) printf("%s\n", gettext("Disabled")); 1413 } else 1414 (void) printf("%s\n", gettext("Not set")); 1415 1416 n2 = tgt_node_next_child(n1, XML_ELEMENT_RAD_SERV, NULL); 1417 (void) printf("%s%s: %s\n", dospace(1), gettext("RADIUS Server"), 1418 n2 ? n2->x_value : gettext("Not set")); 1419 1420 n2 = tgt_node_next_child(n1, XML_ELEMENT_ISNS_ACCESS, NULL); 1421 (void) printf("%s%s: ", dospace(1), gettext("iSNS Access")); 1422 if (n2) { 1423 if (strcmp(n2->x_value, OPT_TRUE) == 0) 1424 (void) printf("%s\n", gettext("Enabled")); 1425 else 1426 (void) printf("%s\n", gettext("Disabled")); 1427 } else 1428 (void) printf("%s\n", gettext("Not set")); 1429 1430 n2 = tgt_node_next_child(n1, XML_ELEMENT_ISNS_SERV, NULL); 1431 (void) printf("%s%s: %s\n", dospace(1), gettext("iSNS Server"), 1432 n2 ? n2->x_value : gettext("Not set")); 1433 1434 n2 = tgt_node_next_child(n1, XML_ELEMENT_ISNS_SERVER_STATUS, NULL); 1435 if (n2) { 1436 /* 1437 * if NULL, that means either the isns discovery is 1438 * disabled or the server address is not set. 1439 */ 1440 if (n2->x_value != NULL) { 1441 (void) printf("%s%s: ", dospace(1), 1442 gettext("iSNS Server Status")); 1443 (void) printf("%s\n", n2->x_value); 1444 } 1445 } 1446 1447 n2 = tgt_node_next_child(n1, XML_ELEMENT_FAST, NULL); 1448 (void) printf("%s%s: ", dospace(1), gettext("Fast Write ACK")); 1449 if (n2) { 1450 if (strcmp(n2->x_value, OPT_TRUE) == 0) 1451 (void) printf("%s\n", gettext("Enabled")); 1452 else 1453 (void) printf("%s\n", gettext("Disabled")); 1454 } else 1455 (void) printf("%s\n", gettext("Not set")); 1456 1457 return (0); 1458 } 1459 1460 static int 1461 showStats(int operandLen, char *operand[], cmdOptions_t *options) 1462 { 1463 char *first_str = NULL; 1464 char scale_buf[16]; 1465 tgt_node_t *node, *n1; 1466 int interval = -1; 1467 int count = -1; 1468 int header; 1469 stat_delta_t cur_data, *pd; 1470 1471 tgt_buf_add_tag(&first_str, "list", Tag_Start); 1472 tgt_buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_Start); 1473 1474 tgt_buf_add(&first_str, XML_ELEMENT_IOSTAT, OPT_TRUE); 1475 if (operandLen) 1476 tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]); 1477 1478 for (; options->optval; options++) { 1479 switch (options->optval) { 1480 case 0: 1481 break; 1482 case 'I': /* optarg = refresh interval */ 1483 interval = atoi(options->optarg); 1484 if (interval == 0) { 1485 (void) fprintf(stderr, "%s: %s\n", cmdName, 1486 gettext("interval must be non-zero")); 1487 free(first_str); 1488 return (1); 1489 } 1490 break; 1491 case 'N': 1492 count = atoi(options->optarg); 1493 if (count == 0) { 1494 (void) fprintf(stderr, "%s: %s\n", cmdName, 1495 gettext("count must be non-zero")); 1496 free(first_str); 1497 return (1); 1498 } 1499 break; 1500 default: 1501 (void) fprintf(stderr, "%s: %c: %s\n", cmdName, 1502 options->optval, gettext("unknown option")); 1503 free(first_str); 1504 return (1); 1505 } 1506 } 1507 1508 tgt_buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_End); 1509 tgt_buf_add_tag(&first_str, "list", Tag_End); 1510 1511 header = 1; 1512 /*CONSTANTCONDITION*/ 1513 while (1) { 1514 if (--header == 0) { 1515 (void) printf("%20s %12s %12s\n", " ", 1516 gettext("operations"), gettext("bandwidth ")); 1517 (void) printf("%-20s %5s %5s %5s %5s\n", 1518 gettext("device"), gettext("read"), 1519 gettext("write"), gettext("read"), 1520 gettext("write")); 1521 (void) printf("%-20s %5s %5s %5s %5s\n", 1522 "--------------------", "-----", "-----", 1523 "-----", "-----"); 1524 header = 20; 1525 } 1526 if ((node = tgt_door_call(first_str, 0)) == NULL) { 1527 (void) fprintf(stderr, "%s: %s\n", cmdName, 1528 gettext("No reponse from daemon")); 1529 return (1); 1530 } 1531 1532 if (strcmp(node->x_name, XML_ELEMENT_RESULT)) { 1533 (void) fprintf(stderr, "%s: %s\n", cmdName, 1534 gettext("Bad XML response")); 1535 free(first_str); 1536 tgt_node_free(node); 1537 stats_free(); 1538 return (1); 1539 } 1540 1541 n1 = NULL; 1542 while (n1 = tgt_node_next_child(node, XML_ELEMENT_TARG, n1)) { 1543 stats_load_counts(n1, &cur_data); 1544 if ((pd = stats_prev_counts(&cur_data)) == NULL) { 1545 free(first_str); 1546 tgt_node_free(node); 1547 return (1); 1548 } 1549 (void) printf("%-20s ", pd->device); 1550 (void) printf("%5s ", 1551 number_to_scaled_string(scale_buf, 1552 cur_data.read_cmds - pd->read_cmds, 1, 1024)); 1553 (void) printf("%5s ", 1554 number_to_scaled_string(scale_buf, 1555 cur_data.write_cmds - pd->write_cmds, 1, 1024)); 1556 (void) printf("%5s ", 1557 number_to_scaled_string(scale_buf, 1558 cur_data.read_blks - pd->read_blks, 512, 1024)); 1559 (void) printf("%5s\n", 1560 number_to_scaled_string(scale_buf, 1561 cur_data.write_blks - pd->write_blks, 512, 1024)); 1562 stats_update_counts(pd, &cur_data); 1563 } 1564 tgt_node_free(node); 1565 1566 if (count == -1) { 1567 if (interval == -1) 1568 /* No count or internal, do it just once */ 1569 break; 1570 else 1571 (void) sleep(interval); 1572 } else if (--count) { 1573 if (interval == -1) 1574 break; 1575 else 1576 (void) sleep(interval); 1577 } else 1578 break; 1579 } 1580 1581 stats_free(); 1582 free(first_str); 1583 return (0); 1584 } 1585 1586 /* 1587 * input: 1588 * execFullName - exec name of program (argv[0]) 1589 * 1590 * Returns: 1591 * command name portion of execFullName 1592 */ 1593 static char * 1594 getExecBasename(char *execFullname) 1595 { 1596 char *lastSlash, *execBasename; 1597 1598 /* guard against '/' at end of command invocation */ 1599 for (;;) { 1600 lastSlash = strrchr(execFullname, '/'); 1601 if (lastSlash == NULL) { 1602 execBasename = execFullname; 1603 break; 1604 } else { 1605 execBasename = lastSlash + 1; 1606 if (*execBasename == '\0') { 1607 *lastSlash = '\0'; 1608 continue; 1609 } 1610 break; 1611 } 1612 } 1613 return (execBasename); 1614 } 1615 1616 /* 1617 * main calls a parser that checks syntax of the input command against 1618 * various rules tables. 1619 * 1620 * The parser provides usage feedback based upon same tables by calling 1621 * two usage functions, usage and subUsage, handling command and subcommand 1622 * usage respectively. 1623 * 1624 * The parser handles all printing of usage syntactical errors 1625 * 1626 * When syntax is successfully validated, the parser calls the associated 1627 * function using the subcommands table functions. 1628 * 1629 * Syntax is as follows: 1630 * command subcommand [options] resource-type [<object>] 1631 * 1632 * The return value from the function is placed in funcRet 1633 */ 1634 int 1635 main(int argc, char *argv[]) 1636 { 1637 synTables_t synTables; 1638 char versionString[VERSION_STRING_MAX_LEN]; 1639 int ret; 1640 int funcRet; 1641 void *subcommandArgs = NULL; 1642 1643 /* set global command name */ 1644 cmdName = getExecBasename(argv[0]); 1645 1646 if (getzoneid() != GLOBAL_ZONEID) { 1647 (void) fprintf(stderr, 1648 "%s: this command is only available in the 'global' " 1649 "zone\n", cmdName); 1650 exit(1); 1651 } 1652 1653 (void) snprintf(versionString, sizeof (versionString), "%s.%s", 1654 VERSION_STRING_MAJOR, VERSION_STRING_MINOR); 1655 synTables.versionString = versionString; 1656 synTables.longOptionTbl = &longOptions[0]; 1657 synTables.subcommandTbl = &subcommands[0]; 1658 synTables.objectTbl = &objects[0]; 1659 synTables.objectRulesTbl = &objectRules[0]; 1660 synTables.optionRulesTbl = &optionRules[0]; 1661 1662 /* call the CLI parser */ 1663 ret = cmdParse(argc, argv, synTables, subcommandArgs, &funcRet); 1664 if (ret == 1) { 1665 (void) printf("%s %s(1M)\n", 1666 gettext("For more information, please see"), cmdName); 1667 return (1); 1668 } else if (ret == -1) { 1669 perror(cmdName); 1670 return (1); 1671 } 1672 1673 return (funcRet); 1674 } 1675