xref: /openbmc/ipmitool/lib/ipmi_main.c (revision 169d9ac3)
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