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 #define _XOPEN_SOURCE 700
33
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <inttypes.h>
37 #include <signal.h>
38 #include <string.h>
39 #include <strings.h>
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 #include <unistd.h>
43 #include <fcntl.h>
44 #include <errno.h>
45 #include <ctype.h>
46
47 #include <ipmitool/helper.h>
48 #include <ipmitool/log.h>
49 #include <ipmitool/ipmi.h>
50 #include <ipmitool/ipmi_intf.h>
51 #include <ipmitool/ipmi_session.h>
52 #include <ipmitool/ipmi_sdr.h>
53 #include <ipmitool/ipmi_gendev.h>
54 #include <ipmitool/ipmi_sel.h>
55 #include <ipmitool/ipmi_fru.h>
56 #include <ipmitool/ipmi_sol.h>
57 #include <ipmitool/ipmi_isol.h>
58 #include <ipmitool/ipmi_lanp.h>
59 #include <ipmitool/ipmi_chassis.h>
60 #include <ipmitool/ipmi_mc.h>
61 #include <ipmitool/ipmi_firewall.h>
62 #include <ipmitool/ipmi_sensor.h>
63 #include <ipmitool/ipmi_channel.h>
64 #include <ipmitool/ipmi_session.h>
65 #include <ipmitool/ipmi_event.h>
66 #include <ipmitool/ipmi_user.h>
67 #include <ipmitool/ipmi_raw.h>
68 #include <ipmitool/ipmi_pef.h>
69 #include <ipmitool/ipmi_oem.h>
70 #include <ipmitool/ipmi_ekanalyzer.h>
71 #include <ipmitool/ipmi_picmg.h>
72
73 #ifdef HAVE_CONFIG_H
74 # include <config.h>
75 #endif
76
77 #ifdef ENABLE_ALL_OPTIONS
78 # define OPTION_STRING "I:hVvcgsEKYao:H:d:P:f:U:p:C:L:A:t:T:m:z:S:l:b:B:e:k:y:O:R:N:D:"
79 #else
80 # define OPTION_STRING "I:hVvcH:f:U:p:d:S:D:"
81 #endif
82
83 extern int verbose;
84 extern int csv_output;
85 extern const struct valstr ipmi_privlvl_vals[];
86 extern const struct valstr ipmi_authtype_session_vals[];
87
88 static struct ipmi_intf * ipmi_main_intf = NULL;
89
90 /* ipmi_password_file_read - Open file and read password from it
91 *
92 * @filename: file name to read from
93 *
94 * returns pointer to allocated buffer containing password
95 * (caller is expected to free when finished)
96 * returns NULL on error
97 */
98 static char *
ipmi_password_file_read(char * filename)99 ipmi_password_file_read(char * filename)
100 {
101 FILE * fp;
102 char * pass = NULL;
103 int l;
104
105 pass = malloc(21);
106 if (pass == NULL) {
107 lprintf(LOG_ERR, "ipmitool: malloc failure");
108 return NULL;
109 }
110
111 memset(pass, 0, 21);
112 fp = ipmi_open_file_read((const char *)filename);
113 if (fp == NULL) {
114 lprintf(LOG_ERR, "Unable to open password file %s",
115 filename);
116 free(pass);
117 return NULL;
118 }
119
120 /* read in id */
121 if (fgets(pass, 21, fp) == NULL) {
122 lprintf(LOG_ERR, "Unable to read password from file %s",
123 filename);
124 free(pass);
125 fclose(fp);
126 return NULL;
127 }
128
129 /* remove traling <cr><nl><tab> */
130 l = strcspn(pass, "\r\n\t");
131 if (l > 0) {
132 pass[l] = '\0';
133 }
134
135 fclose(fp);
136 return pass;
137 }
138
139
140 /*
141 * Print all the commands in the above table to stderr
142 * used for help text on command line and shell
143 */
144 void
ipmi_cmd_print(struct ipmi_cmd * cmdlist)145 ipmi_cmd_print(struct ipmi_cmd * cmdlist)
146 {
147 struct ipmi_cmd * cmd;
148 int hdr = 0;
149
150 if (cmdlist == NULL)
151 return;
152 for (cmd=cmdlist; cmd->func != NULL; cmd++) {
153 if (cmd->desc == NULL)
154 continue;
155 if (hdr == 0) {
156 lprintf(LOG_NOTICE, "Commands:");
157 hdr = 1;
158 }
159 lprintf(LOG_NOTICE, "\t%-12s %s", cmd->name, cmd->desc);
160 }
161 lprintf(LOG_NOTICE, "");
162 }
163
164 /* ipmi_cmd_run - run a command from list based on parameters
165 * called from main()
166 *
167 * 1. iterate through ipmi_cmd_list matching on name
168 * 2. call func() for that command
169 *
170 * @intf: ipmi interface
171 * @name: command name
172 * @argc: command argument count
173 * @argv: command argument list
174 *
175 * returns value from func() of that commnad if found
176 * returns -1 if command is not found
177 */
178 int
ipmi_cmd_run(struct ipmi_intf * intf,char * name,int argc,char ** argv)179 ipmi_cmd_run(struct ipmi_intf * intf, char * name, int argc, char ** argv)
180 {
181 struct ipmi_cmd * cmd = intf->cmdlist;
182
183 /* hook to run a default command if nothing specified */
184 if (name == NULL) {
185 if (cmd->func == NULL || cmd->name == NULL)
186 return -1;
187 else if (strncmp(cmd->name, "default", 7) == 0)
188 return cmd->func(intf, 0, NULL);
189 else {
190 lprintf(LOG_ERR, "No command provided!");
191 ipmi_cmd_print(intf->cmdlist);
192 return -1;
193 }
194 }
195
196 for (cmd=intf->cmdlist; cmd->func != NULL; cmd++) {
197 if (strncmp(name, cmd->name, __maxlen(cmd->name, name)) == 0)
198 break;
199 }
200 if (cmd->func == NULL) {
201 cmd = intf->cmdlist;
202 if (strncmp(cmd->name, "default", 7) == 0)
203 return cmd->func(intf, argc+1, argv-1);
204
205 lprintf(LOG_ERR, "Invalid command: %s", name);
206 ipmi_cmd_print(intf->cmdlist);
207 return -1;
208 }
209 return cmd->func(intf, argc, argv);
210 }
211
212 static void
ipmi_option_usage(const char * progname,struct ipmi_cmd * cmdlist,struct ipmi_intf_support * intflist)213 ipmi_option_usage(const char * progname, struct ipmi_cmd * cmdlist, struct ipmi_intf_support * intflist)
214 {
215 lprintf(LOG_NOTICE, "%s version %s\n", progname, VERSION);
216 lprintf(LOG_NOTICE, "usage: %s [options...] <command>\n", progname);
217 lprintf(LOG_NOTICE, " -h This help");
218 lprintf(LOG_NOTICE, " -V Show version information");
219 lprintf(LOG_NOTICE, " -v Verbose (can use multiple times)");
220 lprintf(LOG_NOTICE, " -c Display output in comma separated format");
221 lprintf(LOG_NOTICE, " -d N Specify a /dev/ipmiN device to use (default=0)");
222 lprintf(LOG_NOTICE, " -I intf Interface to use");
223 lprintf(LOG_NOTICE, " -H hostname Remote host name for LAN interface");
224 lprintf(LOG_NOTICE, " -p port Remote RMCP port [default=623]");
225 lprintf(LOG_NOTICE, " -U username Remote session username");
226 lprintf(LOG_NOTICE, " -f file Read remote session password from file");
227 lprintf(LOG_NOTICE, " -z size Change Size of Communication Channel (OEM)");
228 lprintf(LOG_NOTICE, " -S sdr Use local file for remote SDR cache");
229 lprintf(LOG_NOTICE, " -D tty:b[:s] Specify the serial device, baud rate to use");
230 lprintf(LOG_NOTICE, " and, optionally, specify that interface is the system one");
231 #ifdef ENABLE_ALL_OPTIONS
232 lprintf(LOG_NOTICE, " -a Prompt for remote password");
233 lprintf(LOG_NOTICE, " -Y Prompt for the Kg key for IPMIv2 authentication");
234 lprintf(LOG_NOTICE, " -e char Set SOL escape character");
235 lprintf(LOG_NOTICE, " -C ciphersuite Cipher suite to be used by lanplus interface");
236 lprintf(LOG_NOTICE, " -k key Use Kg key for IPMIv2 authentication");
237 lprintf(LOG_NOTICE, " -y hex_key Use hexadecimal-encoded Kg key for IPMIv2 authentication");
238 lprintf(LOG_NOTICE, " -L level Remote session privilege level [default=ADMINISTRATOR]");
239 lprintf(LOG_NOTICE, " Append a '+' to use name/privilege lookup in RAKP1");
240 lprintf(LOG_NOTICE, " -A authtype Force use of auth type NONE, PASSWORD, MD2, MD5 or OEM");
241 lprintf(LOG_NOTICE, " -P password Remote session password");
242 lprintf(LOG_NOTICE, " -E Read password from IPMI_PASSWORD environment variable");
243 lprintf(LOG_NOTICE, " -K Read kgkey from IPMI_KGKEY environment variable");
244 lprintf(LOG_NOTICE, " -m address Set local IPMB address");
245 lprintf(LOG_NOTICE, " -b channel Set destination channel for bridged request");
246 lprintf(LOG_NOTICE, " -t address Bridge request to remote target address");
247 lprintf(LOG_NOTICE, " -B channel Set transit channel for bridged request (dual bridge)");
248 lprintf(LOG_NOTICE, " -T address Set transit address for bridge request (dual bridge)");
249 lprintf(LOG_NOTICE, " -l lun Set destination lun for raw commands");
250 lprintf(LOG_NOTICE, " -o oemtype Setup for OEM (use 'list' to see available OEM types)");
251 lprintf(LOG_NOTICE, " -O seloem Use file for OEM SEL event descriptions");
252 lprintf(LOG_NOTICE, " -N seconds Specify timeout for lan [default=2] / lanplus [default=1] interface");
253 lprintf(LOG_NOTICE, " -R retry Set the number of retries for lan/lanplus interface [default=4]");
254 #endif
255 lprintf(LOG_NOTICE, "");
256
257 ipmi_intf_print(intflist);
258
259 if (cmdlist != NULL)
260 ipmi_cmd_print(cmdlist);
261 }
262 /* ipmi_catch_sigint - Handle the interrupt signal (Ctrl-C), close the
263 * interface, and exit ipmitool with error (-1)
264 *
265 * This insures that the IOL session gets freed
266 * for other callers.
267 *
268 * returns -1
269 */
ipmi_catch_sigint()270 void ipmi_catch_sigint()
271 {
272 if (ipmi_main_intf != NULL) {
273 printf("\nSIGN INT: Close Interface %s\n",ipmi_main_intf->desc);
274 /* reduce retry count to a single retry */
275 ipmi_main_intf->ssn_params.retry = 1;
276 /* close interface */
277 ipmi_main_intf->close(ipmi_main_intf);
278 }
279 exit(-1);
280 }
281
282 /* ipmi_parse_hex - convert hexadecimal numbers to ascii string
283 * Input string must be composed of two-characer hexadecimal numbers.
284 * There is no separator between the numbers. Each number results in one character
285 * of the converted string.
286 *
287 * Example: ipmi_parse_hex("50415353574F5244") returns 'PASSWORD'
288 *
289 * @param str: input string. It must contain only even number of '0'-'9','a'-'f' and 'A-F' characters.
290 * @returns converted ascii string
291 * @returns NULL on error
292 */
293 static unsigned char *
ipmi_parse_hex(const char * str)294 ipmi_parse_hex(const char *str)
295 {
296 const char * p;
297 unsigned char * out, *q;
298 unsigned char b = 0;
299 int shift = 4;
300
301 if (strlen(str) == 0)
302 return NULL;
303
304 if (strlen(str) % 2 != 0) {
305 lprintf(LOG_ERR, "Number of hex_kg characters is not even");
306 return NULL;
307 }
308
309 if (strlen(str) > (IPMI_KG_BUFFER_SIZE-1)*2) {
310 lprintf(LOG_ERR, "Kg key is too long");
311 return NULL;
312 }
313
314 out = calloc(IPMI_KG_BUFFER_SIZE, sizeof(unsigned char));
315 if (out == NULL) {
316 lprintf(LOG_ERR, "malloc failure");
317 return NULL;
318 }
319
320 for (p = str, q = out; *p; p++) {
321 if (!isxdigit(*p)) {
322 lprintf(LOG_ERR, "Kg_hex is not hexadecimal number");
323 free(out);
324 out = NULL;
325 return NULL;
326 }
327
328 if (*p < 'A') /* it must be 0-9 */
329 b = *p - '0';
330 else /* it's A-F or a-f */
331 b = (*p | 0x20) - 'a' + 10; /* convert to lowercase and to 10-15 */
332
333 *q = *q + b << shift;
334 if (shift)
335 shift = 0;
336 else {
337 shift = 4;
338 q++;
339 }
340 }
341
342 return out;
343 }
344
345 static uint8_t
ipmi_acquire_ipmb_address(struct ipmi_intf * intf)346 ipmi_acquire_ipmb_address(struct ipmi_intf * intf)
347 {
348 if (intf->picmg_avail) {
349 return ipmi_picmg_ipmb_address(intf);
350 } else if (intf->vita_avail) {
351 return ipmi_vita_ipmb_address(intf);
352 } else {
353 return 0;
354 }
355 }
356
357 /* ipmi_parse_options - helper function to handle parsing command line options
358 *
359 * @argc: count of options
360 * @argv: list of options
361 * @cmdlist: list of supported commands
362 * @intflist: list of supported interfaces
363 *
364 * returns 0 on success
365 * returns -1 on error
366 */
367 int
ipmi_main(int argc,char ** argv,struct ipmi_cmd * cmdlist,struct ipmi_intf_support * intflist)368 ipmi_main(int argc, char ** argv,
369 struct ipmi_cmd * cmdlist,
370 struct ipmi_intf_support * intflist)
371 {
372 struct ipmi_intf_support * sup;
373 int privlvl = 0;
374 uint8_t target_addr = 0;
375 uint8_t target_channel = 0;
376
377 uint8_t transit_addr = 0;
378 uint8_t transit_channel = 0;
379 uint8_t target_lun = 0;
380 uint8_t arg_addr = 0;
381 uint8_t addr = 0;
382 uint16_t my_long_packet_size=0;
383 uint8_t my_long_packet_set=0;
384 uint8_t lookupbit = 0x10; /* use name-only lookup by default */
385 int retry = 0;
386 uint32_t timeout = 0;
387 int authtype = -1;
388 char * tmp_pass = NULL;
389 char * tmp_env = NULL;
390 char * hostname = NULL;
391 char * username = NULL;
392 char * password = NULL;
393 char * intfname = NULL;
394 char * progname = NULL;
395 char * oemtype = NULL;
396 char * sdrcache = NULL;
397 unsigned char * kgkey = NULL;
398 char * seloem = NULL;
399 int port = 0;
400 int devnum = 0;
401 int cipher_suite_id = 3; /* See table 22-19 of the IPMIv2 spec */
402 int argflag, i, found;
403 int rc = -1;
404 char sol_escape_char = SOL_ESCAPE_CHARACTER_DEFAULT;
405 char * devfile = NULL;
406
407 /* save program name */
408 progname = strrchr(argv[0], '/');
409 progname = ((progname == NULL) ? argv[0] : progname+1);
410 signal(SIGINT, ipmi_catch_sigint);
411
412 while ((argflag = getopt(argc, (char **)argv, OPTION_STRING)) != -1)
413 {
414 switch (argflag) {
415 case 'I':
416 if (intfname) {
417 free(intfname);
418 intfname = NULL;
419 }
420 intfname = strdup(optarg);
421 if (intfname == NULL) {
422 lprintf(LOG_ERR, "%s: malloc failure", progname);
423 goto out_free;
424 }
425 if (intflist != NULL) {
426 found = 0;
427 for (sup=intflist; sup->name != NULL; sup++) {
428 if (strncmp(sup->name, intfname, strlen(intfname)) == 0 &&
429 strncmp(sup->name, intfname, strlen(sup->name)) == 0 &&
430 sup->supported == 1)
431 found = 1;
432 }
433 if (!found) {
434 lprintf(LOG_ERR, "Interface %s not supported", intfname);
435 goto out_free;
436 }
437 }
438 break;
439 case 'h':
440 ipmi_option_usage(progname, cmdlist, intflist);
441 rc = 0;
442 goto out_free;
443 break;
444 case 'V':
445 printf("%s version %s\n", progname, VERSION);
446 rc = 0;
447 goto out_free;
448 break;
449 case 'd':
450 if (str2int(optarg, &devnum) != 0) {
451 lprintf(LOG_ERR, "Invalid parameter given or out of range for '-d'.");
452 rc = -1;
453 goto out_free;
454 }
455 /* Check if device number is -gt 0; I couldn't find limit for
456 * kernels > 2.6, thus right side is unlimited.
457 */
458 if (devnum < 0) {
459 lprintf(LOG_ERR, "Device number %i is out of range.", devnum);
460 rc = -1;
461 goto out_free;
462 }
463 break;
464 case 'p':
465 if (str2int(optarg, &port) != 0) {
466 lprintf(LOG_ERR, "Invalid parameter given or out of range for '-p'.");
467 rc = -1;
468 goto out_free;
469 }
470 /* Check if port is -gt 0 && port is -lt 65535 */
471 if (port < 0 || port > 65535) {
472 lprintf(LOG_ERR, "Port number %i is out of range.", port);
473 rc = -1;
474 goto out_free;
475 }
476 break;
477 case 'C':
478 if (str2int(optarg, &cipher_suite_id) != 0) {
479 lprintf(LOG_ERR, "Invalid parameter given or out of range for '-C'.");
480 rc = -1;
481 goto out_free;
482 }
483 /* add check Cipher is -gt 0 */
484 if (cipher_suite_id < 0) {
485 lprintf(LOG_ERR, "Cipher suite ID %i is invalid.", cipher_suite_id);
486 rc = -1;
487 goto out_free;
488 }
489 break;
490 case 'v':
491 verbose++;
492 break;
493 case 'c':
494 csv_output = 1;
495 break;
496 case 'H':
497 if (hostname) {
498 free(hostname);
499 hostname = NULL;
500 }
501 hostname = strdup(optarg);
502 if (hostname == NULL) {
503 lprintf(LOG_ERR, "%s: malloc failure", progname);
504 goto out_free;
505 }
506 break;
507 case 'f':
508 if (password) {
509 free(password);
510 password = NULL;
511 }
512 password = ipmi_password_file_read(optarg);
513 if (password == NULL)
514 lprintf(LOG_ERR, "Unable to read password "
515 "from file %s", optarg);
516 break;
517 case 'a':
518 #ifdef HAVE_GETPASSPHRASE
519 tmp_pass = getpassphrase("Password: ");
520 #else
521 tmp_pass = getpass("Password: ");
522 #endif
523 if (tmp_pass != NULL) {
524 if (password) {
525 free(password);
526 password = NULL;
527 }
528 password = strdup(tmp_pass);
529 tmp_pass = NULL;
530 if (password == NULL) {
531 lprintf(LOG_ERR, "%s: malloc failure", progname);
532 goto out_free;
533 }
534 }
535 break;
536 case 'k':
537 if (kgkey) {
538 free(kgkey);
539 kgkey = NULL;
540 }
541 kgkey = strdup(optarg);
542 if (kgkey == NULL) {
543 lprintf(LOG_ERR, "%s: malloc failure", progname);
544 goto out_free;
545 }
546 break;
547 case 'K':
548 if ((tmp_env = getenv("IPMI_KGKEY"))) {
549 if (kgkey) {
550 free(kgkey);
551 kgkey = NULL;
552 }
553 kgkey = strdup(tmp_env);
554 if (kgkey == NULL) {
555 lprintf(LOG_ERR, "%s: malloc failure", progname);
556 goto out_free;
557 }
558 } else {
559 lprintf(LOG_WARN, "Unable to read kgkey from environment");
560 }
561 break;
562 case 'y':
563 if (kgkey) {
564 free(kgkey);
565 kgkey = NULL;
566 }
567 kgkey = ipmi_parse_hex(optarg);
568 if (kgkey == NULL) {
569 goto out_free;
570 }
571 break;
572 case 'Y':
573 #ifdef HAVE_GETPASSPHRASE
574 tmp_pass = getpassphrase("Key: ");
575 #else
576 tmp_pass = getpass("Key: ");
577 #endif
578 if (tmp_pass != NULL) {
579 if (kgkey) {
580 free(kgkey);
581 kgkey = NULL;
582 }
583 kgkey = strdup(tmp_pass);
584 tmp_pass = NULL;
585 if (kgkey == NULL) {
586 lprintf(LOG_ERR, "%s: malloc failure", progname);
587 goto out_free;
588 }
589 }
590 break;
591 case 'U':
592 if (username) {
593 free(username);
594 username = NULL;
595 }
596 if (strlen(optarg) > 16) {
597 lprintf(LOG_ERR, "Username is too long (> 16 bytes)");
598 goto out_free;
599 }
600 username = strdup(optarg);
601 if (username == NULL) {
602 lprintf(LOG_ERR, "%s: malloc failure", progname);
603 goto out_free;
604 }
605 break;
606 case 'S':
607 if (sdrcache) {
608 free(sdrcache);
609 sdrcache = NULL;
610 }
611 sdrcache = strdup(optarg);
612 if (sdrcache == NULL) {
613 lprintf(LOG_ERR, "%s: malloc failure", progname);
614 goto out_free;
615 }
616 break;
617 case 'D':
618 /* check for subsequent instance of -D */
619 if (devfile) {
620 /* free memory for previous string */
621 free(devfile);
622 }
623 devfile = strdup(optarg);
624 if (devfile == NULL) {
625 lprintf(LOG_ERR, "%s: malloc failure", progname);
626 goto out_free;
627 }
628 break;
629 #ifdef ENABLE_ALL_OPTIONS
630 case 'o':
631 if (oemtype) {
632 free(oemtype);
633 oemtype = NULL;
634 }
635 oemtype = strdup(optarg);
636 if (oemtype == NULL) {
637 lprintf(LOG_ERR, "%s: malloc failure", progname);
638 goto out_free;
639 }
640 if (strncmp(oemtype, "list", 4) == 0 ||
641 strncmp(oemtype, "help", 4) == 0) {
642 ipmi_oem_print();
643 rc = 0;
644 goto out_free;
645 }
646 break;
647 case 'g':
648 /* backwards compatible oem hack */
649 if (oemtype) {
650 free(oemtype);
651 oemtype = NULL;
652 }
653 oemtype = strdup("intelwv2");
654 break;
655 case 's':
656 /* backwards compatible oem hack */
657 if (oemtype) {
658 free(oemtype);
659 oemtype = NULL;
660 }
661 oemtype = strdup("supermicro");
662 break;
663 case 'P':
664 if (password) {
665 free(password);
666 password = NULL;
667 }
668 password = strdup(optarg);
669 if (password == NULL) {
670 lprintf(LOG_ERR, "%s: malloc failure", progname);
671 goto out_free;
672 }
673
674 /* Prevent password snooping with ps */
675 i = strlen(optarg);
676 memset(optarg, 'X', i);
677 break;
678 case 'E':
679 if ((tmp_env = getenv("IPMITOOL_PASSWORD"))) {
680 if (password) {
681 free(password);
682 password = NULL;
683 }
684 password = strdup(tmp_env);
685 if (password == NULL) {
686 lprintf(LOG_ERR, "%s: malloc failure", progname);
687 goto out_free;
688 }
689 }
690 else if ((tmp_env = getenv("IPMI_PASSWORD"))) {
691 if (password) {
692 free(password);
693 password = NULL;
694 }
695 password = strdup(tmp_env);
696 if (password == NULL) {
697 lprintf(LOG_ERR, "%s: malloc failure", progname);
698 goto out_free;
699 }
700 }
701 else {
702 lprintf(LOG_WARN, "Unable to read password from environment");
703 }
704 break;
705 case 'L':
706 i = strlen(optarg);
707 if ((i > 0) && (optarg[i-1] == '+')) {
708 lookupbit = 0;
709 optarg[i-1] = 0;
710 }
711 privlvl = str2val(optarg, ipmi_privlvl_vals);
712 if (privlvl == 0xFF) {
713 lprintf(LOG_WARN, "Invalid privilege level %s", optarg);
714 }
715 break;
716 case 'A':
717 authtype = str2val(optarg, ipmi_authtype_session_vals);
718 break;
719 case 't':
720 if (str2uchar(optarg, &target_addr) != 0) {
721 lprintf(LOG_ERR, "Invalid parameter given or out of range for '-t'.");
722 rc = -1;
723 goto out_free;
724 }
725 break;
726 case 'b':
727 if (str2uchar(optarg, &target_channel) != 0) {
728 lprintf(LOG_ERR, "Invalid parameter given or out of range for '-b'.");
729 rc = -1;
730 goto out_free;
731 }
732 break;
733 case 'T':
734 if (str2uchar(optarg, &transit_addr) != 0) {
735 lprintf(LOG_ERR, "Invalid parameter given or out of range for '-T'.");
736 rc = -1;
737 goto out_free;
738 }
739 break;
740 case 'B':
741 if (str2uchar(optarg, &transit_channel) != 0) {
742 lprintf(LOG_ERR, "Invalid parameter given or out of range for '-B'.");
743 rc = -1;
744 goto out_free;
745 }
746 break;
747 case 'l':
748 if (str2uchar(optarg, &target_lun) != 0) {
749 lprintf(LOG_ERR, "Invalid parameter given or out of range for '-l'.");
750 rc = 1;
751 goto out_free;
752 }
753 break;
754 case 'm':
755 if (str2uchar(optarg, &arg_addr) != 0) {
756 lprintf(LOG_ERR, "Invalid parameter given or out of range for '-m'.");
757 rc = -1;
758 goto out_free;
759 }
760 break;
761 case 'e':
762 sol_escape_char = optarg[0];
763 break;
764 case 'O':
765 if (seloem) {
766 free(seloem);
767 seloem = NULL;
768 }
769 seloem = strdup(optarg);
770 if (seloem == NULL) {
771 lprintf(LOG_ERR, "%s: malloc failure", progname);
772 goto out_free;
773 }
774 break;
775 case 'z':
776 if (str2ushort(optarg, &my_long_packet_size) != 0) {
777 lprintf(LOG_ERR, "Invalid parameter given or out of range for '-z'.");
778 rc = -1;
779 goto out_free;
780 }
781 break;
782 /* Retry and Timeout */
783 case 'R':
784 if (str2int(optarg, &retry) != 0 || retry < 0) {
785 lprintf(LOG_ERR, "Invalid parameter given or out of range for '-R'.");
786 rc = -1;
787 goto out_free;
788 }
789 break;
790 case 'N':
791 if (str2uint(optarg, &timeout) != 0) {
792 lprintf(LOG_ERR, "Invalid parameter given or out of range for '-N'.");
793 rc = -1;
794 goto out_free;
795 }
796 break;
797 #endif
798 default:
799 ipmi_option_usage(progname, cmdlist, intflist);
800 goto out_free;
801 }
802 }
803
804 /* check for command before doing anything */
805 if (argc-optind > 0 &&
806 strncmp(argv[optind], "help", 4) == 0) {
807 ipmi_cmd_print(cmdlist);
808 rc = 0;
809 goto out_free;
810 }
811
812 /*
813 * If the user has specified a hostname (-H option)
814 * then this is a remote access session.
815 *
816 * If no password was specified by any other method
817 * and the authtype was not explicitly set to NONE
818 * then prompt the user.
819 */
820 if (hostname != NULL && password == NULL &&
821 (authtype != IPMI_SESSION_AUTHTYPE_NONE || authtype < 0)) {
822 #ifdef HAVE_GETPASSPHRASE
823 tmp_pass = getpassphrase("Password: ");
824 #else
825 tmp_pass = getpass("Password: ");
826 #endif
827 if (tmp_pass != NULL) {
828 password = strdup(tmp_pass);
829 tmp_pass = NULL;
830 if (password == NULL) {
831 lprintf(LOG_ERR, "%s: malloc failure", progname);
832 goto out_free;
833 }
834 }
835 }
836
837 /* if no interface was specified but a
838 * hostname was then use LAN by default
839 * otherwise the default is hardcoded
840 * to use the first entry in the list
841 */
842 if (intfname == NULL && hostname != NULL) {
843 intfname = strdup("lan");
844 if (intfname == NULL) {
845 lprintf(LOG_ERR, "%s: malloc failure", progname);
846 goto out_free;
847 }
848 }
849
850 if (password != NULL && intfname != NULL) {
851 if (strcmp(intfname, "lan") == 0 && strlen(password) > 16) {
852 lprintf(LOG_ERR, "%s: password is longer than 16 bytes.", intfname);
853 rc = -1;
854 goto out_free;
855 } else if (strcmp(intfname, "lanplus") == 0 && strlen(password) > 20) {
856 lprintf(LOG_ERR, "%s: password is longer than 20 bytes.", intfname);
857 rc = -1;
858 goto out_free;
859 }
860 } /* if (password != NULL && intfname != NULL) */
861
862 /* load interface */
863 ipmi_main_intf = ipmi_intf_load(intfname);
864 if (ipmi_main_intf == NULL) {
865 lprintf(LOG_ERR, "Error loading interface %s", intfname);
866 goto out_free;
867 }
868
869 /* setup log */
870 log_init(progname, 0, verbose);
871
872 /* run OEM setup if found */
873 if (oemtype != NULL &&
874 ipmi_oem_setup(ipmi_main_intf, oemtype) < 0) {
875 lprintf(LOG_ERR, "OEM setup for \"%s\" failed", oemtype);
876 goto out_free;
877 }
878
879 /* set session variables */
880 if (hostname != NULL)
881 ipmi_intf_session_set_hostname(ipmi_main_intf, hostname);
882 if (username != NULL)
883 ipmi_intf_session_set_username(ipmi_main_intf, username);
884 if (password != NULL)
885 ipmi_intf_session_set_password(ipmi_main_intf, password);
886 if (kgkey != NULL)
887 ipmi_intf_session_set_kgkey(ipmi_main_intf, kgkey);
888 if (port > 0)
889 ipmi_intf_session_set_port(ipmi_main_intf, port);
890 if (authtype >= 0)
891 ipmi_intf_session_set_authtype(ipmi_main_intf, (uint8_t)authtype);
892 if (privlvl > 0)
893 ipmi_intf_session_set_privlvl(ipmi_main_intf, (uint8_t)privlvl);
894 else
895 ipmi_intf_session_set_privlvl(ipmi_main_intf,
896 IPMI_SESSION_PRIV_ADMIN); /* default */
897 /* Adding retry and timeout for interface that support it */
898 if (retry > 0)
899 ipmi_intf_session_set_retry(ipmi_main_intf, retry);
900 if (timeout > 0)
901 ipmi_intf_session_set_timeout(ipmi_main_intf, timeout);
902
903 ipmi_intf_session_set_lookupbit(ipmi_main_intf, lookupbit);
904 ipmi_intf_session_set_sol_escape_char(ipmi_main_intf, sol_escape_char);
905 ipmi_intf_session_set_cipher_suite_id(ipmi_main_intf, cipher_suite_id);
906
907 ipmi_main_intf->devnum = devnum;
908
909 /* setup device file if given */
910 ipmi_main_intf->devfile = devfile;
911
912 /* Open the interface with the specified or default IPMB address */
913 ipmi_main_intf->my_addr = arg_addr ? arg_addr : IPMI_BMC_SLAVE_ADDR;
914 if (ipmi_main_intf->open != NULL) {
915 if (ipmi_main_intf->open(ipmi_main_intf) < 0) {
916 goto out_free;
917 }
918 }
919 /*
920 * Attempt picmg/vita discovery of the actual interface address unless
921 * the users specified an address.
922 * Address specification always overrides discovery
923 */
924 if (picmg_discover(ipmi_main_intf)) {
925 ipmi_main_intf->picmg_avail = 1;
926 } else if (vita_discover(ipmi_main_intf)) {
927 ipmi_main_intf->vita_avail = 1;
928 }
929
930 if (arg_addr) {
931 addr = arg_addr;
932 } else {
933 lprintf(LOG_DEBUG, "Acquire IPMB address");
934 addr = ipmi_acquire_ipmb_address(ipmi_main_intf);
935 lprintf(LOG_INFO, "Discovered IPMB address 0x%x", addr);
936 }
937
938 /*
939 * If we discovered the ipmb address and it is not the same as what we
940 * used for open, Set the discovered IPMB address as my address if the
941 * interface supports it.
942 */
943 if (addr != 0 && addr != ipmi_main_intf->my_addr) {
944 if (ipmi_main_intf->set_my_addr) {
945 /*
946 * Some interfaces need special handling
947 * when changing local address
948 */
949 (void)ipmi_main_intf->set_my_addr(ipmi_main_intf, addr);
950 }
951
952 /* set local address */
953 ipmi_main_intf->my_addr = addr;
954 }
955
956 ipmi_main_intf->target_addr = ipmi_main_intf->my_addr;
957
958 /* If bridging addresses are specified, handle them */
959 if (transit_addr > 0 || target_addr > 0) {
960 /* sanity check, transit makes no sense without a target */
961 if ((transit_addr != 0 || transit_channel != 0) &&
962 target_addr == 0) {
963 lprintf(LOG_ERR,
964 "Transit address/channel %#x/%#x ignored. "
965 "Target address must be specified!",
966 transit_addr, transit_channel);
967 goto out_free;
968 }
969 ipmi_main_intf->target_addr = target_addr;
970 ipmi_main_intf->target_channel = target_channel ;
971
972 ipmi_main_intf->transit_addr = transit_addr;
973 ipmi_main_intf->transit_channel = transit_channel;
974
975
976 /* must be admin level to do this over lan */
977 ipmi_intf_session_set_privlvl(ipmi_main_intf, IPMI_SESSION_PRIV_ADMIN);
978 /* Get the ipmb address of the targeted entity */
979 ipmi_main_intf->target_ipmb_addr =
980 ipmi_acquire_ipmb_address(ipmi_main_intf);
981 lprintf(LOG_DEBUG, "Specified addressing Target %#x:%#x Transit %#x:%#x",
982 ipmi_main_intf->target_addr,
983 ipmi_main_intf->target_channel,
984 ipmi_main_intf->transit_addr,
985 ipmi_main_intf->transit_channel);
986 if (ipmi_main_intf->target_ipmb_addr) {
987 lprintf(LOG_INFO, "Discovered Target IPMB-0 address %#x",
988 ipmi_main_intf->target_ipmb_addr);
989 }
990 }
991
992 /* set target LUN (for RAW command) */
993 ipmi_main_intf->target_lun = target_lun ;
994
995 lprintf(LOG_DEBUG, "Interface address: my_addr %#x "
996 "transit %#x:%#x target %#x:%#x "
997 "ipmb_target %#x\n",
998 ipmi_main_intf->my_addr,
999 ipmi_main_intf->transit_addr,
1000 ipmi_main_intf->transit_channel,
1001 ipmi_main_intf->target_addr,
1002 ipmi_main_intf->target_channel,
1003 ipmi_main_intf->target_ipmb_addr);
1004
1005 /* parse local SDR cache if given */
1006 if (sdrcache != NULL) {
1007 ipmi_sdr_list_cache_fromfile(ipmi_main_intf, sdrcache);
1008 }
1009 /* Parse SEL OEM file if given */
1010 if (seloem != NULL) {
1011 ipmi_sel_oem_init(seloem);
1012 }
1013
1014 /* Enable Big Buffer when requested */
1015 if ( my_long_packet_size != 0 ) {
1016 /* Enable Big Buffer when requested */
1017 if (!ipmi_oem_active(ipmi_main_intf, "kontron") ||
1018 ipmi_kontronoem_set_large_buffer(ipmi_main_intf,
1019 my_long_packet_size ) == 0) {
1020 printf("Setting large buffer to %i\n", my_long_packet_size);
1021 my_long_packet_set = 1;
1022 ipmi_intf_set_max_request_data_size(ipmi_main_intf,
1023 my_long_packet_size);
1024 }
1025 }
1026
1027 ipmi_main_intf->cmdlist = cmdlist;
1028
1029 /* now we finally run the command */
1030 if (argc-optind > 0)
1031 rc = ipmi_cmd_run(ipmi_main_intf, argv[optind], argc-optind-1,
1032 &(argv[optind+1]));
1033 else
1034 rc = ipmi_cmd_run(ipmi_main_intf, NULL, 0, NULL);
1035
1036 if (my_long_packet_set == 1) {
1037 if (ipmi_oem_active(ipmi_main_intf, "kontron")) {
1038 /* Restore defaults */
1039 ipmi_kontronoem_set_large_buffer( ipmi_main_intf, 0 );
1040 }
1041 }
1042
1043 /* clean repository caches */
1044 ipmi_cleanup(ipmi_main_intf);
1045
1046 /* call interface close function if available */
1047 if (ipmi_main_intf->opened > 0 && ipmi_main_intf->close != NULL)
1048 ipmi_main_intf->close(ipmi_main_intf);
1049
1050 out_free:
1051 log_halt();
1052
1053 if (intfname != NULL) {
1054 free(intfname);
1055 intfname = NULL;
1056 }
1057 if (hostname != NULL) {
1058 free(hostname);
1059 hostname = NULL;
1060 }
1061 if (username != NULL) {
1062 free(username);
1063 username = NULL;
1064 }
1065 if (password != NULL) {
1066 free(password);
1067 password = NULL;
1068 }
1069 if (oemtype != NULL) {
1070 free(oemtype);
1071 oemtype = NULL;
1072 }
1073 if (seloem != NULL) {
1074 free(seloem);
1075 seloem = NULL;
1076 }
1077 if (kgkey != NULL) {
1078 free(kgkey);
1079 kgkey = NULL;
1080 }
1081 if (sdrcache != NULL) {
1082 free(sdrcache);
1083 sdrcache = NULL;
1084 }
1085 if (devfile) {
1086 free(devfile);
1087 devfile = NULL;
1088 }
1089
1090 return rc;
1091 }
1092
1093
1094