1 /* 2 * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * Redistribution of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 11 * Redistribution in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * Neither the name of Sun Microsystems, Inc. or the names of 16 * contributors may be used to endorse or promote products derived 17 * from this software without specific prior written permission. 18 * 19 * This software is provided "AS IS," without a warranty of any kind. 20 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, 21 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A 22 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. 23 * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE 24 * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING 25 * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL 26 * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, 27 * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR 28 * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF 29 * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, 30 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 31 */ 32 33 #include <stdlib.h> 34 #include <string.h> 35 #include <strings.h> 36 #include <stdio.h> 37 #include <sys/types.h> 38 #include <sys/stat.h> 39 #include <sys/select.h> 40 #include <sys/time.h> 41 #include <signal.h> 42 #include <unistd.h> 43 44 45 #include <termios.h> 46 47 #include <ipmitool/helper.h> 48 #include <ipmitool/log.h> 49 #include <ipmitool/ipmi.h> 50 #include <ipmitool/ipmi_strings.h> 51 #include <ipmitool/ipmi_intf.h> 52 #include <ipmitool/ipmi_isol.h> 53 54 static struct termios _saved_tio; 55 static int _in_raw_mode = 0; 56 57 extern int verbose; 58 59 #define ISOL_ESCAPE_CHARACTER '~' 60 61 /* 62 * ipmi_get_isol_info 63 */ 64 static int ipmi_get_isol_info(struct ipmi_intf * intf, 65 struct isol_config_parameters * params) 66 { 67 struct ipmi_rs * rsp; 68 struct ipmi_rq req; 69 unsigned char data[6]; 70 71 memset(&req, 0, sizeof(req)); 72 req.msg.netfn = IPMI_NETFN_ISOL; 73 req.msg.cmd = GET_ISOL_CONFIG; 74 req.msg.data = data; 75 req.msg.data_len = 4; 76 77 /* GET ISOL ENABLED CONFIG */ 78 79 memset(data, 0, 6); 80 data[0] = 0x00; 81 data[1] = ISOL_ENABLE_PARAM; 82 data[2] = 0x00; /* block */ 83 data[3] = 0x00; /* selector */ 84 85 rsp = intf->sendrecv(intf, &req); 86 if (rsp == NULL) { 87 lprintf(LOG_ERR, "Error in Get ISOL Config Command"); 88 return -1; 89 } 90 if (rsp->ccode == 0xc1) { 91 lprintf(LOG_ERR, "IPMI v1.5 Serial Over Lan (ISOL) not supported!"); 92 return -1; 93 } 94 if (rsp->ccode > 0) { 95 lprintf(LOG_ERR, "Error in Get ISOL Config Command: %s", 96 val2str(rsp->ccode, completion_code_vals)); 97 return -1; 98 } 99 params->enabled = rsp->data[1]; 100 101 /* GET ISOL AUTHENTICATON CONFIG */ 102 103 memset(data, 0, 6); 104 data[0] = 0x00; 105 data[1] = ISOL_AUTHENTICATION_PARAM; 106 data[2] = 0x00; /* block */ 107 data[3] = 0x00; /* selector */ 108 109 rsp = intf->sendrecv(intf, &req); 110 if (rsp == NULL) { 111 lprintf(LOG_ERR, "Error in Get ISOL Config Command"); 112 return -1; 113 } 114 if (rsp->ccode > 0) { 115 lprintf(LOG_ERR, "Error in Get ISOL Config Command: %s", 116 val2str(rsp->ccode, completion_code_vals)); 117 return -1; 118 } 119 params->privilege_level = rsp->data[1]; 120 121 /* GET ISOL BAUD RATE CONFIG */ 122 123 memset(data, 0, 6); 124 data[0] = 0x00; 125 data[1] = ISOL_BAUD_RATE_PARAM; 126 data[2] = 0x00; /* block */ 127 data[3] = 0x00; /* selector */ 128 129 rsp = intf->sendrecv(intf, &req); 130 if (rsp == NULL) { 131 lprintf(LOG_ERR, "Error in Get ISOL Config Command"); 132 return -1; 133 } 134 if (rsp->ccode > 0) { 135 lprintf(LOG_ERR, "Error in Get ISOL Config Command: %s", 136 val2str(rsp->ccode, completion_code_vals)); 137 return -1; 138 } 139 params->bit_rate = rsp->data[1]; 140 141 return 0; 142 } 143 144 static int ipmi_print_isol_info(struct ipmi_intf * intf) 145 { 146 struct isol_config_parameters params = {0}; 147 if (ipmi_get_isol_info(intf, ¶ms)) 148 return -1; 149 150 if (csv_output) 151 { 152 printf("%s,", (params.enabled & 0x1)?"true": "false"); 153 printf("%s,", 154 val2str((params.privilege_level & 0xf), ipmi_privlvl_vals)); 155 printf("%s,", 156 val2str((params.bit_rate & 0xf), ipmi_bit_rate_vals)); 157 } 158 else 159 { 160 printf("Enabled : %s\n", 161 (params.enabled & 0x1)?"true": "false"); 162 printf("Privilege Level : %s\n", 163 val2str((params.privilege_level & 0xf), ipmi_privlvl_vals)); 164 printf("Bit Rate (kbps) : %s\n", 165 val2str((params.bit_rate & 0xf), ipmi_bit_rate_vals)); 166 } 167 168 return 0; 169 } 170 171 static int ipmi_isol_set_param(struct ipmi_intf * intf, 172 const char *param, 173 const char *value) 174 { 175 struct ipmi_rs * rsp; 176 struct ipmi_rq req; 177 unsigned char data[6]; 178 struct isol_config_parameters params = {0}; 179 180 /* We need other values to complete the request */ 181 if (ipmi_get_isol_info(intf, ¶ms)) 182 return -1; 183 184 memset(&req, 0, sizeof(req)); 185 req.msg.netfn = IPMI_NETFN_ISOL; 186 req.msg.cmd = SET_ISOL_CONFIG; 187 req.msg.data = data; 188 req.msg.data_len = 3; 189 190 memset(data, 0, 6); 191 192 /* 193 * enabled 194 */ 195 if (strcmp(param, "enabled") == 0) 196 { 197 data[1] = ISOL_ENABLE_PARAM; 198 if (strcmp(value, "true") == 0) 199 data[2] = 0x01; 200 else if (strcmp(value, "false") == 0) 201 data[2] = 0x00; 202 else { 203 lprintf(LOG_ERR, "Invalid value %s for parameter %s", 204 value, param); 205 lprintf(LOG_ERR, "Valid values are true and false"); 206 return -1; 207 } 208 } 209 210 /* 211 * privilege-level 212 */ 213 else if (strcmp(param, "privilege-level") == 0) 214 { 215 data[1] = ISOL_AUTHENTICATION_PARAM; 216 if (! strcmp(value, "user")) 217 data[2] = 0x02; 218 else if (! strcmp(value, "operator")) 219 data[2] = 0x03; 220 else if (! strcmp(value, "admin")) 221 data[2] = 0x04; 222 else if (! strcmp(value, "oem")) 223 data[2] = 0x05; 224 else 225 { 226 lprintf(LOG_ERR, "Invalid value %s for parameter %s", 227 value, param); 228 lprintf(LOG_ERR, "Valid values are user, operator, admin, and oem"); 229 return -1; 230 } 231 /* We need to mask bit7 from the fetched value */ 232 data[2] |= (params.privilege_level & 0x80) ? 0x80 : 0x00; 233 } 234 235 /* 236 * bit-rate 237 */ 238 else if (strcmp(param, "bit-rate") == 0) 239 { 240 data[1] = ISOL_BAUD_RATE_PARAM; 241 if (strncmp(value, "9.6", 3) == 0) { 242 data[2] = 0x06; 243 } 244 else if (strncmp(value, "19.2", 4) == 0) { 245 data[2] = 0x07; 246 } 247 else if (strncmp(value, "38.4", 4) == 0) { 248 data[2] = 0x08; 249 } 250 else if (strncmp(value, "57.6", 4) == 0) { 251 data[2] = 0x09; 252 } 253 else if (strncmp(value, "115.2", 5) == 0) { 254 data[2] = 0x0A; 255 } 256 else { 257 lprintf(LOG_ERR, "ISOL - Unsupported baud rate: %s", value); 258 lprintf(LOG_ERR, "Valid values are 9.6, 19.2, 38.4, 57.6 and 115.2"); 259 return -1; 260 } 261 } 262 else 263 { 264 lprintf(LOG_ERR, "Error: invalid ISOL parameter %s", param); 265 return -1; 266 } 267 268 269 /* 270 * Execute the request 271 */ 272 273 rsp = intf->sendrecv(intf, &req); 274 if (rsp == NULL) { 275 lprintf(LOG_ERR, "Error setting ISOL parameter '%s'", param); 276 return -1; 277 } 278 if (rsp->ccode > 0) { 279 lprintf(LOG_ERR, "Error setting ISOL parameter '%s': %s", 280 param, val2str(rsp->ccode, completion_code_vals)); 281 return -1; 282 } 283 284 return 0; 285 } 286 287 static void 288 leave_raw_mode(void) 289 { 290 if (!_in_raw_mode) 291 return; 292 if (tcsetattr(fileno(stdin), TCSADRAIN, &_saved_tio) == -1) 293 perror("tcsetattr"); 294 else 295 _in_raw_mode = 0; 296 } 297 298 299 300 static void 301 enter_raw_mode(void) 302 { 303 struct termios tio; 304 if (tcgetattr(fileno(stdin), &tio) == -1) { 305 perror("tcgetattr"); 306 return; 307 } 308 _saved_tio = tio; 309 tio.c_iflag |= IGNPAR; 310 tio.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF)\ 311 ; 312 tio.c_lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL); 313 // #ifdef IEXTEN 314 tio.c_lflag &= ~IEXTEN; 315 // #endif 316 tio.c_oflag &= ~OPOST; 317 tio.c_cc[VMIN] = 1; 318 tio.c_cc[VTIME] = 0; 319 if (tcsetattr(fileno(stdin), TCSADRAIN, &tio) == -1) 320 perror("tcsetattr"); 321 else 322 _in_raw_mode = 1; 323 } 324 325 326 static void 327 sendBreak(struct ipmi_intf * intf) 328 { 329 struct ipmi_v2_payload v2_payload; 330 331 memset(&v2_payload, 0, sizeof(v2_payload)); 332 333 v2_payload.payload.sol_packet.character_count = 0; 334 v2_payload.payload.sol_packet.generate_break = 1; 335 336 intf->send_sol(intf, &v2_payload); 337 } 338 339 /* 340 * suspendSelf 341 * 342 * Put ourself in the background 343 * 344 * param bRestoreTty specifies whether we will put our self back 345 * in raw mode when we resume 346 */ 347 static void 348 suspendSelf(int bRestoreTty) 349 { 350 leave_raw_mode(); 351 kill(getpid(), SIGTSTP); 352 353 if (bRestoreTty) 354 enter_raw_mode(); 355 } 356 357 358 359 /* 360 * printiSolEscapeSequences 361 * 362 * Send some useful documentation to the user 363 */ 364 static void 365 printiSolEscapeSequences(void) 366 { 367 printf( 368 "%c?\n\ 369 Supported escape sequences:\n\ 370 %c. - terminate connection\n\ 371 %c^Z - suspend ipmitool\n\ 372 %c^X - suspend ipmitool, but don't restore tty on restart\n\ 373 %cB - send break\n\ 374 %c? - this message\n\ 375 %c%c - send the escape character by typing it twice\n\ 376 (Note that escapes are only recognized immediately after newline.)\n", 377 ISOL_ESCAPE_CHARACTER, 378 ISOL_ESCAPE_CHARACTER, 379 ISOL_ESCAPE_CHARACTER, 380 ISOL_ESCAPE_CHARACTER, 381 ISOL_ESCAPE_CHARACTER, 382 ISOL_ESCAPE_CHARACTER, 383 ISOL_ESCAPE_CHARACTER, 384 ISOL_ESCAPE_CHARACTER); 385 } 386 387 388 389 /* 390 * output 391 * 392 * Send the specified data to stdout 393 */ 394 static void 395 output(struct ipmi_rs * rsp) 396 { 397 if (rsp) 398 { 399 int i; 400 for (i = 0; i < rsp->data_len; ++i) 401 putc(rsp->data[i], stdout); 402 403 fflush(stdout); 404 } 405 } 406 407 /* 408 * ipmi_isol_deactivate 409 */ 410 static int 411 ipmi_isol_deactivate(struct ipmi_intf * intf) 412 { 413 struct ipmi_rs * rsp; 414 struct ipmi_rq req; 415 uint8_t data[6]; 416 417 memset(&req, 0, sizeof(req)); 418 req.msg.netfn = IPMI_NETFN_ISOL; 419 req.msg.cmd = ACTIVATE_ISOL; 420 req.msg.data = data; 421 req.msg.data_len = 5; 422 423 memset(data, 0, 6); 424 data[0] = 0x00; /* Deactivate */ 425 data[1] = 0x00; 426 data[2] = 0x00; 427 data[3] = 0x00; 428 data[5] = 0x00; 429 430 rsp = intf->sendrecv(intf, &req); 431 if (rsp == NULL) { 432 lprintf(LOG_ERR, "Error deactivating ISOL"); 433 return -1; 434 } 435 if (rsp->ccode > 0) { 436 lprintf(LOG_ERR, "Error deactivating ISOL: %s", 437 val2str(rsp->ccode, completion_code_vals)); 438 return -1; 439 } 440 /* response contain 4 additional bytes : 80 00 32 ff 441 Don't know what to use them for yet... */ 442 return 0; 443 } 444 445 /* 446 * processiSolUserInput 447 * 448 * Act on user input into the ISOL session. The only reason this 449 * is complicated is that we have to process escape sequences. 450 * 451 * return 0 on success 452 * 1 if we should exit 453 * < 0 on error (BMC probably closed the session) 454 */ 455 static int 456 processiSolUserInput(struct ipmi_intf * intf, 457 uint8_t * input, 458 uint16_t buffer_length) 459 { 460 static int escape_pending = 0; 461 static int last_was_cr = 1; 462 struct ipmi_v2_payload v2_payload; 463 int length = 0; 464 int retval = 0; 465 char ch; 466 int i; 467 468 memset(&v2_payload, 0, sizeof(v2_payload)); 469 470 /* 471 * Our first order of business is to check the input for escape 472 * sequences to act on. 473 */ 474 for (i = 0; i < buffer_length; ++i) 475 { 476 ch = input[i]; 477 478 if (escape_pending){ 479 escape_pending = 0; 480 481 /* 482 * Process a possible escape sequence. 483 */ 484 switch (ch) { 485 case '.': 486 printf("%c. [terminated ipmitool]\n", ISOL_ESCAPE_CHARACTER); 487 retval = 1; 488 break; 489 case 'Z' - 64: 490 printf("%c^Z [suspend ipmitool]\n", ISOL_ESCAPE_CHARACTER); 491 suspendSelf(1); /* Restore tty back to raw */ 492 continue; 493 494 case 'X' - 64: 495 printf("%c^X [suspend ipmitool]\n", ISOL_ESCAPE_CHARACTER); 496 suspendSelf(0); /* Don't restore to raw mode */ 497 continue; 498 499 case 'B': 500 printf("%cb [send break]\n", ISOL_ESCAPE_CHARACTER); 501 sendBreak(intf); 502 continue; 503 504 case '?': 505 printiSolEscapeSequences(); 506 continue; 507 default: 508 if (ch != ISOL_ESCAPE_CHARACTER) 509 v2_payload.payload.sol_packet.data[length++] = 510 ISOL_ESCAPE_CHARACTER; 511 v2_payload.payload.sol_packet.data[length++] = ch; 512 } 513 } 514 515 else 516 { 517 if (last_was_cr && (ch == ISOL_ESCAPE_CHARACTER)) { 518 escape_pending = 1; 519 continue; 520 } 521 522 v2_payload.payload.sol_packet.data[length++] = ch; 523 } 524 525 526 /* 527 * Normal character. Record whether it was a newline. 528 */ 529 last_was_cr = (ch == '\r' || ch == '\n'); 530 } 531 532 /* 533 * If there is anything left to process we dispatch it to the BMC, 534 * send intf->session->sol_data.max_outbound_payload_size bytes 535 * at a time. 536 */ 537 if (length) 538 { 539 struct ipmi_rs * rsp; 540 541 v2_payload.payload.sol_packet.flush_outbound = 1; /* Not sure if necessary ? */ 542 v2_payload.payload.sol_packet.character_count = length; 543 rsp = intf->send_sol(intf, &v2_payload); 544 545 if (! rsp) { 546 lprintf(LOG_ERR, "Error sending SOL data"); 547 retval = -1; 548 } 549 550 /* If the sequence number is set we know we have new data */ 551 else if ((rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL) && 552 (rsp->payload.sol_packet.packet_sequence_number)) 553 output(rsp); 554 } 555 return retval; 556 } 557 558 /* 559 * ipmi_isol_red_pill 560 */ 561 static int 562 ipmi_isol_red_pill(struct ipmi_intf * intf) 563 { 564 char * buffer; 565 int numRead; 566 int bShouldExit = 0; 567 int bBmcClosedSession = 0; 568 fd_set read_fds; 569 struct timeval tv; 570 int retval; 571 int buffer_size = 255; 572 int timedout = 0; 573 574 buffer = (char*)malloc(buffer_size); 575 if (buffer == NULL) { 576 lprintf(LOG_ERR, "ipmitool: malloc failure"); 577 return -1; 578 } 579 580 enter_raw_mode(); 581 582 while (! bShouldExit) 583 { 584 FD_ZERO(&read_fds); 585 FD_SET(0, &read_fds); 586 FD_SET(intf->fd, &read_fds); 587 588 /* Wait up to half a second */ 589 tv.tv_sec = 0; 590 tv.tv_usec = 500000; 591 592 retval = select(intf->fd + 1, &read_fds, NULL, NULL, &tv); 593 594 if (retval) 595 { 596 if (retval == -1) 597 { 598 /* ERROR */ 599 perror("select"); 600 return -1; 601 } 602 603 timedout = 0; 604 605 /* 606 * Process input from the user 607 */ 608 if (FD_ISSET(0, &read_fds)) 609 { 610 memset(buffer, 0, buffer_size); 611 numRead = read(fileno(stdin), 612 buffer, 613 buffer_size); 614 615 if (numRead > 0) 616 { 617 int rc = processiSolUserInput(intf, buffer, numRead); 618 619 if (rc) 620 { 621 if (rc < 0) 622 bShouldExit = bBmcClosedSession = 1; 623 else 624 bShouldExit = 1; 625 } 626 } 627 else 628 { 629 bShouldExit = 1; 630 } 631 } 632 633 634 /* 635 * Process input from the BMC 636 */ 637 else if (FD_ISSET(intf->fd, &read_fds)) 638 { 639 struct ipmi_rs * rs = intf->recv_sol(intf); 640 if (! rs) 641 { 642 bShouldExit = bBmcClosedSession = 1; 643 } 644 else 645 output(rs); 646 } 647 648 649 /* 650 * ERROR in select 651 */ 652 else 653 { 654 lprintf(LOG_ERR, "Error: Select returned with nothing to read"); 655 bShouldExit = 1; 656 } 657 } 658 else 659 { 660 if ((++timedout) == 20) /* Every 10 seconds we send a keepalive */ 661 { 662 intf->keepalive(intf); 663 timedout = 0; 664 } 665 } 666 } 667 668 leave_raw_mode(); 669 670 if (bBmcClosedSession) 671 { 672 lprintf(LOG_ERR, "SOL session closed by BMC"); 673 } 674 else 675 ipmi_isol_deactivate(intf); 676 677 return 0; 678 } 679 680 /* 681 * ipmi_isol_activate 682 */ 683 static int 684 ipmi_isol_activate(struct ipmi_intf * intf) 685 { 686 struct ipmi_rs * rsp; 687 struct ipmi_rq req; 688 uint8_t data[6]; 689 struct isol_config_parameters params; 690 691 if (ipmi_get_isol_info(intf, ¶ms)) 692 return -1; 693 694 if (!(params.enabled & 0x1)) { 695 lprintf(LOG_ERR, "ISOL is not enabled!"); 696 return -1; 697 } 698 699 /* 700 * Setup a callback so that the lanplus processing knows what 701 * to do with packets that come unexpectedly (while waiting for 702 * an ACK, perhaps. 703 */ 704 intf->session->sol_data.sol_input_handler = output; 705 706 memset(&req, 0, sizeof(req)); 707 req.msg.netfn = IPMI_NETFN_ISOL; 708 req.msg.cmd = ACTIVATE_ISOL; 709 req.msg.data = data; 710 req.msg.data_len = 5; 711 712 memset(data, 0, 6); 713 data[0] = 0x01; 714 data[1] = 0x00; 715 data[2] = 0x00; 716 data[3] = 0x00; 717 data[5] = 0x00; 718 719 rsp = intf->sendrecv(intf, &req); 720 if (NULL != rsp) { 721 switch (rsp->ccode) { 722 case 0x00: 723 if (rsp->data_len == 4) { 724 break; 725 } else { 726 lprintf(LOG_ERR, "Error: Unexpected data length (%d) received " 727 "in ISOL activation response", 728 rsp->data_len); 729 return -1; 730 } 731 break; 732 case 0x80: 733 lprintf(LOG_ERR, "Info: ISOL already active on another session"); 734 return -1; 735 case 0x81: 736 lprintf(LOG_ERR, "Info: ISOL disabled"); 737 return -1; 738 case 0x82: 739 lprintf(LOG_ERR, "Info: ISOL activation limit reached"); 740 return -1; 741 default: 742 lprintf(LOG_ERR, "Error activating ISOL: %s", 743 val2str(rsp->ccode, completion_code_vals)); 744 return -1; 745 } 746 } else { 747 lprintf(LOG_ERR, "Error: No response activating ISOL"); 748 return -1; 749 } 750 751 /* response contain 4 additional bytes : 80 01 32 ff 752 Don't know what to use them for yet... */ 753 754 printf("[SOL Session operational. Use %c? for help]\n", 755 ISOL_ESCAPE_CHARACTER); 756 757 /* 758 * At this point we are good to go with our SOL session. We 759 * need to listen to 760 * 1) STDIN for user input 761 * 2) The FD for incoming SOL packets 762 */ 763 if (ipmi_isol_red_pill(intf)) { 764 lprintf(LOG_ERR, "Error in SOL session"); 765 return -1; 766 } 767 768 return 0; 769 } 770 771 static void print_isol_set_usage(void) { 772 lprintf(LOG_NOTICE, "\nISOL set parameters and values: \n"); 773 lprintf(LOG_NOTICE, " enabled true | false"); 774 lprintf(LOG_NOTICE, " privilege-level user | operator | admin | oem"); 775 lprintf(LOG_NOTICE, " bit-rate " 776 "9.6 | 19.2 | 38.4 | 57.6 | 115.2"); 777 lprintf(LOG_NOTICE, ""); 778 } 779 780 static void print_isol_usage(void) { 781 lprintf(LOG_NOTICE, "ISOL Commands: info"); 782 lprintf(LOG_NOTICE, " set <parameter> <setting>"); 783 lprintf(LOG_NOTICE, " activate"); 784 } 785 786 int ipmi_isol_main(struct ipmi_intf * intf, int argc, char ** argv) 787 { 788 int ret = 0; 789 790 /* 791 * Help 792 */ 793 if (!argc || !strncmp(argv[0], "help", 4)) 794 print_isol_usage(); 795 796 /* 797 * Info 798 */ 799 else if (!strncmp(argv[0], "info", 4)) { 800 ret = ipmi_print_isol_info(intf); 801 } 802 803 /* 804 * Set a parameter value 805 */ 806 else if (!strncmp(argv[0], "set", 3)) { 807 if (argc < 3) { 808 print_isol_set_usage(); 809 return -1; 810 } 811 ret = ipmi_isol_set_param(intf, argv[1], argv[2]); 812 } 813 814 /* 815 * Activate 816 */ 817 else if (!strncmp(argv[0], "activate", 8)) { 818 ret = ipmi_isol_activate(intf); 819 } 820 821 else { 822 print_isol_usage(); 823 ret = -1; 824 } 825 826 return ret; 827 } 828