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