xref: /openbmc/ipmitool/lib/ipmi_main.c (revision 531569ec)
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 *
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
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
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
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  */
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 		if (ipmi_main_intf->session) {
276 			ipmi_main_intf->session->retry = 1;
277 		}
278 		/* close interface */
279 		ipmi_main_intf->close(ipmi_main_intf);
280 	}
281 	exit(-1);
282 }
283 
284 /* ipmi_parse_hex - convert hexadecimal numbers to ascii string
285  *                  Input string must be composed of two-characer hexadecimal numbers.
286  *                  There is no separator between the numbers. Each number results in one character
287  *                  of the converted string.
288  *
289  *                  Example: ipmi_parse_hex("50415353574F5244") returns 'PASSWORD'
290  *
291  * @param str:  input string. It must contain only even number of '0'-'9','a'-'f' and 'A-F' characters.
292  * @returns converted ascii string
293  * @returns NULL on error
294  */
295 static unsigned char *
296 ipmi_parse_hex(const char *str)
297 {
298 	const char * p;
299 	unsigned char * out, *q;
300 	unsigned char b = 0;
301 	int shift = 4;
302 
303 	if (strlen(str) == 0)
304 		return NULL;
305 
306 	if (strlen(str) % 2 != 0) {
307 		lprintf(LOG_ERR, "Number of hex_kg characters is not even");
308 		return NULL;
309 	}
310 
311 	if (strlen(str) > (IPMI_KG_BUFFER_SIZE-1)*2) {
312 		lprintf(LOG_ERR, "Kg key is too long");
313 		return NULL;
314 	}
315 
316 	out = calloc(IPMI_KG_BUFFER_SIZE, sizeof(unsigned char));
317 	if (out == NULL) {
318 		lprintf(LOG_ERR, "malloc failure");
319 		return NULL;
320 	}
321 
322 	for (p = str, q = out; *p; p++) {
323 		if (!isxdigit(*p)) {
324 			lprintf(LOG_ERR, "Kg_hex is not hexadecimal number");
325 			free(out);
326 			out = NULL;
327 			return NULL;
328 		}
329 
330 		if (*p < 'A') /* it must be 0-9 */
331 			b = *p - '0';
332 		else /* it's A-F or a-f */
333 			b = (*p | 0x20) - 'a' + 10; /* convert to lowercase and to 10-15 */
334 
335 		*q = *q + b << shift;
336 		if (shift)
337 			shift = 0;
338 		else {
339 			shift = 4;
340 			q++;
341 		}
342 	}
343 
344 	return out;
345 }
346 
347 static uint8_t
348 ipmi_acquire_ipmb_address(struct ipmi_intf * intf)
349 {
350 	if (intf->picmg_avail) {
351 		return ipmi_picmg_ipmb_address(intf);
352 	} else if (intf->vita_avail) {
353 		return ipmi_vita_ipmb_address(intf);
354 	} else {
355 		return 0;
356     }
357 }
358 
359 /* ipmi_parse_options  -  helper function to handle parsing command line options
360  *
361  * @argc:	count of options
362  * @argv:	list of options
363  * @cmdlist:	list of supported commands
364  * @intflist:	list of supported interfaces
365  *
366  * returns 0 on success
367  * returns -1 on error
368  */
369 int
370 ipmi_main(int argc, char ** argv,
371 		struct ipmi_cmd * cmdlist,
372 		struct ipmi_intf_support * intflist)
373 {
374 	struct ipmi_intf_support * sup;
375 	int privlvl = 0;
376 	uint8_t target_addr = 0;
377 	uint8_t target_channel = 0;
378 
379 	uint8_t transit_addr = 0;
380 	uint8_t transit_channel = 0;
381 	uint8_t target_lun     = 0;
382 	uint8_t arg_addr = 0;
383 	uint8_t addr = 0;
384 	uint16_t my_long_packet_size=0;
385 	uint8_t my_long_packet_set=0;
386 	uint8_t lookupbit = 0x10;	/* use name-only lookup by default */
387 	int retry = 0;
388 	uint32_t timeout = 0;
389 	int authtype = -1;
390 	char * tmp_pass = NULL;
391 	char * tmp_env = NULL;
392 	char * hostname = NULL;
393 	char * username = NULL;
394 	char * password = NULL;
395 	char * intfname = NULL;
396 	char * progname = NULL;
397 	char * oemtype  = NULL;
398 	char * sdrcache = NULL;
399 	unsigned char * kgkey = NULL;
400 	char * seloem   = NULL;
401 	int port = 0;
402 	int devnum = 0;
403 	int cipher_suite_id = 3; /* See table 22-19 of the IPMIv2 spec */
404 	int argflag, i, found;
405 	int rc = -1;
406 	char sol_escape_char = SOL_ESCAPE_CHARACTER_DEFAULT;
407 	char * devfile  = NULL;
408 
409 	/* save program name */
410 	progname = strrchr(argv[0], '/');
411 	progname = ((progname == NULL) ? argv[0] : progname+1);
412 	signal(SIGINT, ipmi_catch_sigint);
413 
414 	while ((argflag = getopt(argc, (char **)argv, OPTION_STRING)) != -1)
415 	{
416 		switch (argflag) {
417 		case 'I':
418 			if (intfname) {
419 				free(intfname);
420 				intfname = NULL;
421 			}
422 			intfname = strdup(optarg);
423 			if (intfname == NULL) {
424 				lprintf(LOG_ERR, "%s: malloc failure", progname);
425 				goto out_free;
426 			}
427 			if (intflist != NULL) {
428 				found = 0;
429 				for (sup=intflist; sup->name != NULL; sup++) {
430 					if (strncmp(sup->name, intfname, strlen(intfname)) == 0 &&
431 							strncmp(sup->name, intfname, strlen(sup->name)) == 0 &&
432 							sup->supported == 1)
433 						found = 1;
434 				}
435 				if (!found) {
436 					lprintf(LOG_ERR, "Interface %s not supported", intfname);
437 					goto out_free;
438 				}
439 			}
440 			break;
441 		case 'h':
442 			ipmi_option_usage(progname, cmdlist, intflist);
443 			rc = 0;
444 			goto out_free;
445 			break;
446 		case 'V':
447 			printf("%s version %s\n", progname, VERSION);
448 			rc = 0;
449 			goto out_free;
450 			break;
451 		case 'd':
452 			if (str2int(optarg, &devnum) != 0) {
453 				lprintf(LOG_ERR, "Invalid parameter given or out of range for '-d'.");
454 				rc = -1;
455 				goto out_free;
456 			}
457 			/* Check if device number is -gt 0; I couldn't find limit for
458 			 * kernels > 2.6, thus right side is unlimited.
459 			 */
460 			if (devnum < 0) {
461 				lprintf(LOG_ERR, "Device number %i is out of range.", devnum);
462 				rc = -1;
463 				goto out_free;
464 			}
465 			break;
466 		case 'p':
467 			if (str2int(optarg, &port) != 0) {
468 				lprintf(LOG_ERR, "Invalid parameter given or out of range for '-p'.");
469 				rc = -1;
470 				goto out_free;
471 			}
472 			/* Check if port is -gt 0 && port is -lt 65535 */
473 			if (port < 0 || port > 65535) {
474 				lprintf(LOG_ERR, "Port number %i is out of range.", port);
475 				rc = -1;
476 				goto out_free;
477 			}
478 			break;
479 		case 'C':
480 			if (str2int(optarg, &cipher_suite_id) != 0) {
481 				lprintf(LOG_ERR, "Invalid parameter given or out of range for '-C'.");
482 				rc = -1;
483 				goto out_free;
484 			}
485 			/* add check Cipher is -gt 0 */
486 			if (cipher_suite_id < 0) {
487 				lprintf(LOG_ERR, "Cipher suite ID %i is invalid.", cipher_suite_id);
488 				rc = -1;
489 				goto out_free;
490 			}
491 			break;
492 		case 'v':
493 			verbose++;
494 			break;
495 		case 'c':
496 			csv_output = 1;
497 			break;
498 		case 'H':
499 			if (hostname) {
500 				free(hostname);
501 				hostname = NULL;
502 			}
503 			hostname = strdup(optarg);
504 			if (hostname == NULL) {
505 				lprintf(LOG_ERR, "%s: malloc failure", progname);
506 				goto out_free;
507 			}
508 			break;
509 		case 'f':
510 			if (password) {
511 				free(password);
512 				password = NULL;
513 			}
514 			password = ipmi_password_file_read(optarg);
515 			if (password == NULL)
516 				lprintf(LOG_ERR, "Unable to read password "
517 						"from file %s", optarg);
518 			break;
519 		case 'a':
520 #ifdef HAVE_GETPASSPHRASE
521 			tmp_pass = getpassphrase("Password: ");
522 #else
523 			tmp_pass = getpass("Password: ");
524 #endif
525 			if (tmp_pass != NULL) {
526 				if (password) {
527 					free(password);
528 					password = NULL;
529 				}
530 				password = strdup(tmp_pass);
531 				tmp_pass = NULL;
532 				if (password == NULL) {
533 					lprintf(LOG_ERR, "%s: malloc failure", progname);
534 					goto out_free;
535 				}
536 			}
537 			break;
538 		case 'k':
539 			if (kgkey) {
540 				free(kgkey);
541 				kgkey = NULL;
542 			}
543 			kgkey = strdup(optarg);
544 			if (kgkey == NULL) {
545 				lprintf(LOG_ERR, "%s: malloc failure", progname);
546 				goto out_free;
547 			}
548 			break;
549 		case 'K':
550 			if ((tmp_env = getenv("IPMI_KGKEY"))) {
551 				if (kgkey) {
552 					free(kgkey);
553 					kgkey = NULL;
554 				}
555 				kgkey = strdup(tmp_env);
556 				if (kgkey == NULL) {
557 					lprintf(LOG_ERR, "%s: malloc failure", progname);
558 					goto out_free;
559 				}
560 			} else {
561 				lprintf(LOG_WARN, "Unable to read kgkey from environment");
562 			}
563 			break;
564 		case 'y':
565 			if (kgkey) {
566 				free(kgkey);
567 				kgkey = NULL;
568 			}
569 			kgkey = ipmi_parse_hex(optarg);
570 			if (kgkey == NULL) {
571 				goto out_free;
572 			}
573 			break;
574 		case 'Y':
575 #ifdef HAVE_GETPASSPHRASE
576 			tmp_pass = getpassphrase("Key: ");
577 #else
578 			tmp_pass = getpass("Key: ");
579 #endif
580 			if (tmp_pass != NULL) {
581 				if (kgkey) {
582 					free(kgkey);
583 					kgkey = NULL;
584 				}
585 				kgkey = strdup(tmp_pass);
586 				tmp_pass = NULL;
587 				if (kgkey == NULL) {
588 					lprintf(LOG_ERR, "%s: malloc failure", progname);
589 					goto out_free;
590 				}
591 			}
592 			break;
593 		case 'U':
594 			if (username) {
595 				free(username);
596 				username = NULL;
597 			}
598 			if (strlen(optarg) > 16) {
599 				lprintf(LOG_ERR, "Username is too long (> 16 bytes)");
600 				goto out_free;
601 			}
602 			username = strdup(optarg);
603 			if (username == NULL) {
604 				lprintf(LOG_ERR, "%s: malloc failure", progname);
605 				goto out_free;
606 			}
607 			break;
608 		case 'S':
609 			if (sdrcache) {
610 				free(sdrcache);
611 				sdrcache = NULL;
612 			}
613 			sdrcache = strdup(optarg);
614 			if (sdrcache == NULL) {
615 				lprintf(LOG_ERR, "%s: malloc failure", progname);
616 				goto out_free;
617 			}
618 			break;
619 		case 'D':
620 			/* check for subsequent instance of -D */
621 			if (devfile) {
622 				/* free memory for previous string */
623 				free(devfile);
624 			}
625 			devfile = strdup(optarg);
626 			if (devfile == NULL) {
627 				lprintf(LOG_ERR, "%s: malloc failure", progname);
628 				goto out_free;
629 			}
630 			break;
631 #ifdef ENABLE_ALL_OPTIONS
632 		case 'o':
633 			if (oemtype) {
634 				free(oemtype);
635 				oemtype = NULL;
636 			}
637 			oemtype = strdup(optarg);
638 			if (oemtype == NULL) {
639 				lprintf(LOG_ERR, "%s: malloc failure", progname);
640 				goto out_free;
641 			}
642 			if (strncmp(oemtype, "list", 4) == 0 ||
643 					strncmp(oemtype, "help", 4) == 0) {
644 				ipmi_oem_print();
645 				rc = 0;
646 				goto out_free;
647 			}
648 			break;
649 		case 'g':
650 			/* backwards compatible oem hack */
651 			if (oemtype) {
652 				free(oemtype);
653 				oemtype = NULL;
654 			}
655 			oemtype = strdup("intelwv2");
656 			break;
657 		case 's':
658 			/* backwards compatible oem hack */
659 			if (oemtype) {
660 				free(oemtype);
661 				oemtype = NULL;
662 			}
663 			oemtype = strdup("supermicro");
664 			break;
665 		case 'P':
666 			if (password) {
667 				free(password);
668 				password = NULL;
669 			}
670 			password = strdup(optarg);
671 			if (password == NULL) {
672 				lprintf(LOG_ERR, "%s: malloc failure", progname);
673 				goto out_free;
674 			}
675 
676 			/* Prevent password snooping with ps */
677 			i = strlen(optarg);
678 			memset(optarg, 'X', i);
679 			break;
680 		case 'E':
681 			if ((tmp_env = getenv("IPMITOOL_PASSWORD"))) {
682 				if (password) {
683 					free(password);
684 					password = NULL;
685 				}
686 				password = strdup(tmp_env);
687 				if (password == NULL) {
688 					lprintf(LOG_ERR, "%s: malloc failure", progname);
689 					goto out_free;
690 				}
691 			}
692 			else if ((tmp_env = getenv("IPMI_PASSWORD"))) {
693 				if (password) {
694 					free(password);
695 					password = NULL;
696 				}
697 				password = strdup(tmp_env);
698 				if (password == NULL) {
699 					lprintf(LOG_ERR, "%s: malloc failure", progname);
700 					goto out_free;
701 				}
702 			}
703 			else {
704 				lprintf(LOG_WARN, "Unable to read password from environment");
705 			}
706 			break;
707 		case 'L':
708 			i = strlen(optarg);
709 			if ((i > 0) && (optarg[i-1] == '+')) {
710 				lookupbit = 0;
711 				optarg[i-1] = 0;
712 			}
713 			privlvl = str2val(optarg, ipmi_privlvl_vals);
714 			if (privlvl == 0xFF) {
715 				lprintf(LOG_WARN, "Invalid privilege level %s", optarg);
716 			}
717 			break;
718 		case 'A':
719 			authtype = str2val(optarg, ipmi_authtype_session_vals);
720 			break;
721 		case 't':
722 			if (str2uchar(optarg, &target_addr) != 0) {
723 				lprintf(LOG_ERR, "Invalid parameter given or out of range for '-t'.");
724 				rc = -1;
725 				goto out_free;
726 			}
727 			break;
728 		case 'b':
729 			if (str2uchar(optarg, &target_channel) != 0) {
730 				lprintf(LOG_ERR, "Invalid parameter given or out of range for '-b'.");
731 				rc = -1;
732 				goto out_free;
733 			}
734 			break;
735 		case 'T':
736 			if (str2uchar(optarg, &transit_addr) != 0) {
737 				lprintf(LOG_ERR, "Invalid parameter given or out of range for '-T'.");
738 				rc = -1;
739 				goto out_free;
740 			}
741 			break;
742 		case 'B':
743 			if (str2uchar(optarg, &transit_channel) != 0) {
744 				lprintf(LOG_ERR, "Invalid parameter given or out of range for '-B'.");
745 				rc = -1;
746 				goto out_free;
747 			}
748 			break;
749 		case 'l':
750 			if (str2uchar(optarg, &target_lun) != 0) {
751 				lprintf(LOG_ERR, "Invalid parameter given or out of range for '-l'.");
752 				rc = 1;
753 				goto out_free;
754 			}
755 			break;
756 		case 'm':
757 			if (str2uchar(optarg, &arg_addr) != 0) {
758 				lprintf(LOG_ERR, "Invalid parameter given or out of range for '-m'.");
759 				rc = -1;
760 				goto out_free;
761 			}
762 			break;
763 		case 'e':
764 			sol_escape_char = optarg[0];
765 			break;
766 		case 'O':
767 			if (seloem) {
768 				free(seloem);
769 				seloem = NULL;
770 			}
771 			seloem = strdup(optarg);
772 			if (seloem == NULL) {
773 				lprintf(LOG_ERR, "%s: malloc failure", progname);
774 				goto out_free;
775 			}
776 			break;
777 		case 'z':
778 			if (str2ushort(optarg, &my_long_packet_size) != 0) {
779 				lprintf(LOG_ERR, "Invalid parameter given or out of range for '-z'.");
780 				rc = -1;
781 				goto out_free;
782 			}
783 			break;
784 		/* Retry and Timeout */
785 		case 'R':
786 			if (str2int(optarg, &retry) != 0 || retry < 0) {
787 				lprintf(LOG_ERR, "Invalid parameter given or out of range for '-R'.");
788 				rc = -1;
789 				goto out_free;
790 			}
791 			break;
792 		case 'N':
793 			if (str2uint(optarg, &timeout) != 0) {
794 				lprintf(LOG_ERR, "Invalid parameter given or out of range for '-N'.");
795 				rc = -1;
796 				goto out_free;
797 			}
798 			break;
799 #endif
800 		default:
801 			ipmi_option_usage(progname, cmdlist, intflist);
802 			goto out_free;
803 		}
804 	}
805 
806 	/* check for command before doing anything */
807 	if (argc-optind > 0 &&
808 			strncmp(argv[optind], "help", 4) == 0) {
809 		ipmi_cmd_print(cmdlist);
810 		rc = 0;
811 		goto out_free;
812 	}
813 
814 	/*
815 	 * If the user has specified a hostname (-H option)
816 	 * then this is a remote access session.
817 	 *
818 	 * If no password was specified by any other method
819 	 * and the authtype was not explicitly set to NONE
820 	 * then prompt the user.
821 	 */
822 	if (hostname != NULL && password == NULL &&
823 			(authtype != IPMI_SESSION_AUTHTYPE_NONE || authtype < 0)) {
824 #ifdef HAVE_GETPASSPHRASE
825 		tmp_pass = getpassphrase("Password: ");
826 #else
827 		tmp_pass = getpass("Password: ");
828 #endif
829 		if (tmp_pass != NULL) {
830 			password = strdup(tmp_pass);
831 			tmp_pass = NULL;
832 			if (password == NULL) {
833 				lprintf(LOG_ERR, "%s: malloc failure", progname);
834 				goto out_free;
835 			}
836 		}
837 	}
838 
839 	/* if no interface was specified but a
840 	 * hostname was then use LAN by default
841 	 * otherwise the default is hardcoded
842 	 * to use the first entry in the list
843 	 */
844 	if (intfname == NULL && hostname != NULL) {
845 		intfname = strdup("lan");
846 		if (intfname == NULL) {
847 			lprintf(LOG_ERR, "%s: malloc failure", progname);
848 			goto out_free;
849 		}
850 	}
851 
852 	if (password != NULL && intfname != NULL) {
853 		if (strcmp(intfname, "lan") == 0 && strlen(password) > 16) {
854 			lprintf(LOG_ERR, "%s: password is longer than 16 bytes.", intfname);
855 			rc = -1;
856 			goto out_free;
857 		} else if (strcmp(intfname, "lanplus") == 0 && strlen(password) > 20) {
858 			lprintf(LOG_ERR, "%s: password is longer than 20 bytes.", intfname);
859 			rc = -1;
860 			goto out_free;
861 		}
862 	} /* if (password != NULL && intfname != NULL) */
863 
864 	/* load interface */
865 	ipmi_main_intf = ipmi_intf_load(intfname);
866 	if (ipmi_main_intf == NULL) {
867 		lprintf(LOG_ERR, "Error loading interface %s", intfname);
868 		goto out_free;
869 	}
870 
871 	/* setup log */
872 	log_init(progname, 0, verbose);
873 
874 	/* run OEM setup if found */
875 	if (oemtype != NULL &&
876 	    ipmi_oem_setup(ipmi_main_intf, oemtype) < 0) {
877 		lprintf(LOG_ERR, "OEM setup for \"%s\" failed", oemtype);
878 		goto out_free;
879 	}
880 
881 	/* set session variables */
882 	if (hostname != NULL)
883 		ipmi_intf_session_set_hostname(ipmi_main_intf, hostname);
884 	if (username != NULL)
885 		ipmi_intf_session_set_username(ipmi_main_intf, username);
886 	if (password != NULL)
887 		ipmi_intf_session_set_password(ipmi_main_intf, password);
888 	if (kgkey != NULL)
889 		ipmi_intf_session_set_kgkey(ipmi_main_intf, kgkey);
890 	if (port > 0)
891 		ipmi_intf_session_set_port(ipmi_main_intf, port);
892 	if (authtype >= 0)
893 		ipmi_intf_session_set_authtype(ipmi_main_intf, (uint8_t)authtype);
894 	if (privlvl > 0)
895 		ipmi_intf_session_set_privlvl(ipmi_main_intf, (uint8_t)privlvl);
896 	else
897 		ipmi_intf_session_set_privlvl(ipmi_main_intf,
898 				IPMI_SESSION_PRIV_ADMIN);	/* default */
899 	/* Adding retry and timeout for interface that support it */
900 	if (retry > 0)
901 		ipmi_intf_session_set_retry(ipmi_main_intf, retry);
902 	if (timeout > 0)
903 		ipmi_intf_session_set_timeout(ipmi_main_intf, timeout);
904 
905 	ipmi_intf_session_set_lookupbit(ipmi_main_intf, lookupbit);
906 	ipmi_intf_session_set_sol_escape_char(ipmi_main_intf, sol_escape_char);
907 	ipmi_intf_session_set_cipher_suite_id(ipmi_main_intf, cipher_suite_id);
908 
909 	ipmi_main_intf->devnum = devnum;
910 
911 	/* setup device file if given */
912 	ipmi_main_intf->devfile = devfile;
913 
914 	/* Open the interface with the specified or default IPMB address */
915 	ipmi_main_intf->my_addr = arg_addr ? arg_addr : IPMI_BMC_SLAVE_ADDR;
916 	if (ipmi_main_intf->open != NULL) {
917 		if (ipmi_main_intf->open(ipmi_main_intf) < 0) {
918 			goto out_free;
919 		}
920 	}
921 	/*
922 	 * Attempt picmg/vita discovery of the actual interface address unless
923 	 * the users specified an address.
924 	 *	Address specification always overrides discovery
925 	 */
926 	if (picmg_discover(ipmi_main_intf)) {
927 		ipmi_main_intf->picmg_avail = 1;
928 	} else if (vita_discover(ipmi_main_intf)) {
929 		ipmi_main_intf->vita_avail = 1;
930 	}
931 
932 	if (arg_addr) {
933 		addr = arg_addr;
934 	} else {
935 		lprintf(LOG_DEBUG, "Acquire IPMB address");
936 		addr = ipmi_acquire_ipmb_address(ipmi_main_intf);
937 		lprintf(LOG_INFO,  "Discovered IPMB address 0x%x", addr);
938 	}
939 
940 	/*
941 	 * If we discovered the ipmb address and it is not the same as what we
942 	 * used for open, Set the discovered IPMB address as my address if the
943 	 * interface supports it.
944 	 */
945 	if (addr != 0 && addr != ipmi_main_intf->my_addr &&
946 						ipmi_main_intf->set_my_addr) {
947 		/*
948 		 * Only set the interface address on interfaces which support
949 		 * it
950 		 */
951 		(void) ipmi_main_intf->set_my_addr(ipmi_main_intf, addr);
952 	}
953 
954 	/* If bridging addresses are specified, handle them */
955 	if (target_addr > 0) {
956 		ipmi_main_intf->target_addr = target_addr;
957 		ipmi_main_intf->target_lun = target_lun ;
958 		ipmi_main_intf->target_channel = target_channel ;
959 	}
960 	if (transit_addr > 0) {
961 		/* sanity check, transit makes no sense without a target */
962 		if ((transit_addr != 0 || transit_channel != 0) &&
963 			ipmi_main_intf->target_addr == 0) {
964 			lprintf(LOG_ERR,
965 				"Transit address/channel %#x/%#x ignored. "
966 				"Target address must be specified!",
967 				transit_addr, transit_channel);
968 			goto out_free;
969 		}
970 
971 		ipmi_main_intf->transit_addr    = transit_addr;
972 		ipmi_main_intf->transit_channel = transit_channel;
973 	}
974 	if (ipmi_main_intf->target_addr > 0) {
975 		/* must be admin level to do this over lan */
976 		ipmi_intf_session_set_privlvl(ipmi_main_intf, IPMI_SESSION_PRIV_ADMIN);
977 		/* Get the ipmb address of the targeted entity */
978 		ipmi_main_intf->target_ipmb_addr =
979 					ipmi_acquire_ipmb_address(ipmi_main_intf);
980 		lprintf(LOG_DEBUG, "Specified addressing     Target  %#x:%#x Transit %#x:%#x",
981 					   ipmi_main_intf->target_addr,
982 					   ipmi_main_intf->target_channel,
983 					   ipmi_main_intf->transit_addr,
984 					   ipmi_main_intf->transit_channel);
985 		if (ipmi_main_intf->target_ipmb_addr) {
986 			lprintf(LOG_INFO, "Discovered Target IPMB-0 address %#x",
987 					   ipmi_main_intf->target_ipmb_addr);
988 		}
989 	}
990 
991 	lprintf(LOG_DEBUG, "Interface address: my_addr %#x "
992 			   "transit %#x:%#x target %#x:%#x "
993 			   "ipmb_target %#x\n",
994 			ipmi_main_intf->my_addr,
995 			ipmi_main_intf->transit_addr,
996 			ipmi_main_intf->transit_channel,
997 			ipmi_main_intf->target_addr,
998 			ipmi_main_intf->target_channel,
999 			ipmi_main_intf->target_ipmb_addr);
1000 
1001 	/* parse local SDR cache if given */
1002 	if (sdrcache != NULL) {
1003 		ipmi_sdr_list_cache_fromfile(ipmi_main_intf, sdrcache);
1004 	}
1005 	/* Parse SEL OEM file if given */
1006 	if (seloem != NULL) {
1007 		ipmi_sel_oem_init(seloem);
1008 	}
1009 
1010 	/* Enable Big Buffer when requested */
1011 	if ( my_long_packet_size != 0 ) {
1012 		/* Enable Big Buffer when requested */
1013 		if (!ipmi_oem_active(ipmi_main_intf, "kontron") ||
1014 			ipmi_kontronoem_set_large_buffer(ipmi_main_intf,
1015 					my_long_packet_size ) == 0) {
1016 			printf("Setting large buffer to %i\n", my_long_packet_size);
1017 			my_long_packet_set = 1;
1018 			ipmi_intf_set_max_request_data_size(ipmi_main_intf,
1019 					my_long_packet_size);
1020 		}
1021 	}
1022 
1023 	ipmi_main_intf->cmdlist = cmdlist;
1024 
1025 	/* now we finally run the command */
1026 	if (argc-optind > 0)
1027 		rc = ipmi_cmd_run(ipmi_main_intf, argv[optind], argc-optind-1,
1028 				&(argv[optind+1]));
1029 	else
1030 		rc = ipmi_cmd_run(ipmi_main_intf, NULL, 0, NULL);
1031 
1032 	if (my_long_packet_set == 1) {
1033 		if (ipmi_oem_active(ipmi_main_intf, "kontron")) {
1034 			/* Restore defaults */
1035 			ipmi_kontronoem_set_large_buffer( ipmi_main_intf, 0 );
1036 		}
1037 	}
1038 
1039 	/* clean repository caches */
1040 	ipmi_cleanup(ipmi_main_intf);
1041 
1042 	/* call interface close function if available */
1043 	if (ipmi_main_intf->opened > 0 && ipmi_main_intf->close != NULL)
1044 		ipmi_main_intf->close(ipmi_main_intf);
1045 
1046 	out_free:
1047 	log_halt();
1048 
1049 	if (intfname != NULL) {
1050 		free(intfname);
1051 		intfname = NULL;
1052 	}
1053 	if (hostname != NULL) {
1054 		free(hostname);
1055 		hostname = NULL;
1056 	}
1057 	if (username != NULL) {
1058 		free(username);
1059 		username = NULL;
1060 	}
1061 	if (password != NULL) {
1062 		free(password);
1063 		password = NULL;
1064 	}
1065 	if (oemtype != NULL) {
1066 		free(oemtype);
1067 		oemtype = NULL;
1068 	}
1069 	if (seloem != NULL) {
1070 		free(seloem);
1071 		seloem = NULL;
1072 	}
1073 	if (kgkey != NULL) {
1074 		free(kgkey);
1075 		kgkey = NULL;
1076 	}
1077 	if (sdrcache != NULL) {
1078 		free(sdrcache);
1079 		sdrcache = NULL;
1080 	}
1081 	if (devfile) {
1082 		free(devfile);
1083 		devfile = NULL;
1084 	}
1085 
1086 	return rc;
1087 }
1088 
1089 
1090