diff options
Diffstat (limited to 'lib/ipmi_main.c')
| -rw-r--r-- | lib/ipmi_main.c | 1063 | 
1 files changed, 1063 insertions, 0 deletions
| diff --git a/lib/ipmi_main.c b/lib/ipmi_main.c new file mode 100644 index 0000000..14ca183 --- /dev/null +++ b/lib/ipmi_main.c @@ -0,0 +1,1063 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc.  All Rights Reserved. + *  + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + *  + * Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + *  + * Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + *  + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + *  + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. + * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE + * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING + * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.  IN NO EVENT WILL + * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, + * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR + * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF + * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <inttypes.h> +#include <signal.h> +#include <string.h> +#include <strings.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <ctype.h> + +#include <ipmitool/helper.h> +#include <ipmitool/log.h> +#include <ipmitool/ipmi.h> +#include <ipmitool/ipmi_intf.h> +#include <ipmitool/ipmi_session.h> +#include <ipmitool/ipmi_sdr.h> +#include <ipmitool/ipmi_gendev.h> +#include <ipmitool/ipmi_sel.h> +#include <ipmitool/ipmi_fru.h> +#include <ipmitool/ipmi_sol.h> +#include <ipmitool/ipmi_isol.h> +#include <ipmitool/ipmi_lanp.h> +#include <ipmitool/ipmi_chassis.h> +#include <ipmitool/ipmi_mc.h> +#include <ipmitool/ipmi_firewall.h> +#include <ipmitool/ipmi_sensor.h> +#include <ipmitool/ipmi_channel.h> +#include <ipmitool/ipmi_session.h> +#include <ipmitool/ipmi_event.h> +#include <ipmitool/ipmi_user.h> +#include <ipmitool/ipmi_raw.h> +#include <ipmitool/ipmi_pef.h> +#include <ipmitool/ipmi_oem.h> +#include <ipmitool/ipmi_ekanalyzer.h> +#include <ipmitool/ipmi_picmg.h> + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#ifdef ENABLE_ALL_OPTIONS +# 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:" +#else +# define OPTION_STRING	"I:hVvcH:f:U:p:d:S:D:" +#endif + +extern int verbose; +extern int csv_output; +extern const struct valstr ipmi_privlvl_vals[]; +extern const struct valstr ipmi_authtype_session_vals[]; + +static struct ipmi_intf * ipmi_main_intf = NULL; + +/* ipmi_password_file_read  -  Open file and read password from it + * + * @filename:	file name to read from + * + * returns pointer to allocated buffer containing password + *   (caller is expected to free when finished) + * returns NULL on error + */ +static char * +ipmi_password_file_read(char * filename) +{ +	FILE * fp; +	char * pass = NULL; +	int l; + +	pass = malloc(21); +	if (pass == NULL) { +		lprintf(LOG_ERR, "ipmitool: malloc failure"); +		return NULL; +	} + +	memset(pass, 0, 21); +	fp = ipmi_open_file_read((const char *)filename); +	if (fp == NULL) { +		lprintf(LOG_ERR, "Unable to open password file %s", +				filename); +		free(pass); +		return NULL; +	} + +	/* read in id */ +	if (fgets(pass, 21, fp) == NULL) { +		lprintf(LOG_ERR, "Unable to read password from file %s", +				filename); +		free(pass); +		fclose(fp); +		return NULL; +	} + +	/* remove trailing whitespace */ +	l = strcspn(pass, " \r\n\t"); +	if (l > 0) { +		pass[l] = '\0'; +	} + +	fclose(fp); +	return pass; +} + + +/* + * Print all the commands in the above table to stderr + * used for help text on command line and shell + */ +void +ipmi_cmd_print(struct ipmi_cmd * cmdlist) +{ +	struct ipmi_cmd * cmd; +	int hdr = 0; + +	if (cmdlist == NULL) +		return; +	for (cmd=cmdlist; cmd->func != NULL; cmd++) { +		if (cmd->desc == NULL) +			continue; +		if (hdr == 0) { +			lprintf(LOG_NOTICE, "Commands:"); +			hdr = 1; +		} +		lprintf(LOG_NOTICE, "\t%-12s  %s", cmd->name, cmd->desc); +	} +	lprintf(LOG_NOTICE, ""); +} + +/* ipmi_cmd_run - run a command from list based on parameters + *                called from main() + * + *                1. iterate through ipmi_cmd_list matching on name + *                2. call func() for that command + * + * @intf:	ipmi interface + * @name:	command name + * @argc:	command argument count + * @argv:	command argument list + * + * returns value from func() of that commnad if found + * returns -1 if command is not found + */ +int +ipmi_cmd_run(struct ipmi_intf * intf, char * name, int argc, char ** argv) +{ +	struct ipmi_cmd * cmd = intf->cmdlist; + +	/* hook to run a default command if nothing specified */ +	if (name == NULL) { +		if (cmd->func == NULL || cmd->name == NULL) +			return -1; +		else if (strncmp(cmd->name, "default", 7) == 0) +			return cmd->func(intf, 0, NULL); +		else { +			lprintf(LOG_ERR, "No command provided!"); +			ipmi_cmd_print(intf->cmdlist); +			return -1; +		} +	} + +	for (cmd=intf->cmdlist; cmd->func != NULL; cmd++) { +		if (strncmp(name, cmd->name, __maxlen(cmd->name, name)) == 0) +			break; +	} +	if (cmd->func == NULL) { +		cmd = intf->cmdlist; +		if (strncmp(cmd->name, "default", 7) == 0) +			return cmd->func(intf, argc+1, argv-1); + +		lprintf(LOG_ERR, "Invalid command: %s", name); +		ipmi_cmd_print(intf->cmdlist); +		return -1; +	} +	return cmd->func(intf, argc, argv); +} + +static void +ipmi_option_usage(const char * progname, struct ipmi_cmd * cmdlist, struct ipmi_intf_support * intflist) +{ +	lprintf(LOG_NOTICE, "%s version %s\n", progname, VERSION); +	lprintf(LOG_NOTICE, "usage: %s [options...] <command>\n", progname); +	lprintf(LOG_NOTICE, "       -h             This help"); +	lprintf(LOG_NOTICE, "       -V             Show version information"); +	lprintf(LOG_NOTICE, "       -v             Verbose (can use multiple times)"); +	lprintf(LOG_NOTICE, "       -c             Display output in comma separated format"); +	lprintf(LOG_NOTICE, "       -d N           Specify a /dev/ipmiN device to use (default=0)"); +	lprintf(LOG_NOTICE, "       -I intf        Interface to use"); +	lprintf(LOG_NOTICE, "       -H hostname    Remote host name for LAN interface"); +	lprintf(LOG_NOTICE, "       -p port        Remote RMCP port [default=623]"); +	lprintf(LOG_NOTICE, "       -U username    Remote session username"); +	lprintf(LOG_NOTICE, "       -f file        Read remote session password from file"); +	lprintf(LOG_NOTICE, "       -z size        Change Size of Communication Channel (OEM)"); +	lprintf(LOG_NOTICE, "       -S sdr         Use local file for remote SDR cache"); +	lprintf(LOG_NOTICE, "       -D tty:b[:s]   Specify the serial device, baud rate to use"); +	lprintf(LOG_NOTICE, "                      and, optionally, specify that interface is the system one"); +#ifdef ENABLE_ALL_OPTIONS +	lprintf(LOG_NOTICE, "       -a             Prompt for remote password"); +	lprintf(LOG_NOTICE, "       -Y             Prompt for the Kg key for IPMIv2 authentication"); +	lprintf(LOG_NOTICE, "       -e char        Set SOL escape character"); +	lprintf(LOG_NOTICE, "       -C ciphersuite Cipher suite to be used by lanplus interface"); +	lprintf(LOG_NOTICE, "       -k key         Use Kg key for IPMIv2 authentication"); +	lprintf(LOG_NOTICE, "       -y hex_key     Use hexadecimal-encoded Kg key for IPMIv2 authentication"); +	lprintf(LOG_NOTICE, "       -L level       Remote session privilege level [default=ADMINISTRATOR]"); +	lprintf(LOG_NOTICE, "                      Append a '+' to use name/privilege lookup in RAKP1"); +	lprintf(LOG_NOTICE, "       -A authtype    Force use of auth type NONE, PASSWORD, MD2, MD5 or OEM"); +	lprintf(LOG_NOTICE, "       -P password    Remote session password"); +	lprintf(LOG_NOTICE, "       -E             Read password from IPMI_PASSWORD environment variable"); +	lprintf(LOG_NOTICE, "       -K             Read kgkey from IPMI_KGKEY environment variable"); +	lprintf(LOG_NOTICE, "       -m address     Set local IPMB address"); +	lprintf(LOG_NOTICE, "       -b channel     Set destination channel for bridged request"); +	lprintf(LOG_NOTICE, "       -t address     Bridge request to remote target address"); +	lprintf(LOG_NOTICE, "       -B channel     Set transit channel for bridged request (dual bridge)"); +	lprintf(LOG_NOTICE, "       -T address     Set transit address for bridge request (dual bridge)"); +	lprintf(LOG_NOTICE, "       -l lun         Set destination lun for raw commands"); +	lprintf(LOG_NOTICE, "       -o oemtype     Setup for OEM (use 'list' to see available OEM types)"); +	lprintf(LOG_NOTICE, "       -O seloem      Use file for OEM SEL event descriptions"); +	lprintf(LOG_NOTICE, "       -N seconds     Specify timeout for lan [default=2] / lanplus [default=1] interface"); +	lprintf(LOG_NOTICE, "       -R retry       Set the number of retries for lan/lanplus interface [default=4]"); +#endif +	lprintf(LOG_NOTICE, ""); + +	ipmi_intf_print(intflist); + +	if (cmdlist != NULL) +		ipmi_cmd_print(cmdlist); +} +/* ipmi_catch_sigint  -  Handle the interrupt signal (Ctrl-C), close the + *                       interface, and exit ipmitool with error (-1) + * + *                       This insures that the IOL session gets freed + *                       for other callers. + *  + * returns -1 + */ +void ipmi_catch_sigint() +{ +	if (ipmi_main_intf != NULL) { +		printf("\nSIGN INT: Close Interface %s\n",ipmi_main_intf->desc); +		ipmi_main_intf->close(ipmi_main_intf); +	} +	exit(-1); +} + +/* ipmi_parse_hex - convert hexadecimal numbers to ascii string + *                  Input string must be composed of two-characer hexadecimal numbers. + *                  There is no separator between the numbers. Each number results in one character + *                  of the converted string. + * + *                  Example: ipmi_parse_hex("50415353574F5244") returns 'PASSWORD' + * + * @param str:  input string. It must contain only even number of '0'-'9','a'-'f' and 'A-F' characters. + * @returns converted ascii string + * @returns NULL on error + */ +static unsigned char * +ipmi_parse_hex(const char *str) +{ +	const char * p; +	unsigned char * out, *q; +	unsigned char b = 0; +	int shift = 4; + +	if (strlen(str) == 0) +		return NULL; + +	if (strlen(str) % 2 != 0) { +		lprintf(LOG_ERR, "Number of hex_kg characters is not even"); +		return NULL; +	} + +	if (strlen(str) > (IPMI_KG_BUFFER_SIZE-1)*2) { +		lprintf(LOG_ERR, "Kg key is too long"); +		return NULL; +	} + +	out = calloc(IPMI_KG_BUFFER_SIZE, sizeof(unsigned char)); +	if (out == NULL) { +		lprintf(LOG_ERR, "malloc failure"); +		return NULL; +	} + +	for (p = str, q = out; *p; p++) { +		if (!isxdigit(*p)) { +			lprintf(LOG_ERR, "Kg_hex is not hexadecimal number"); +			free(out); +			out = NULL; +			return NULL; +		} + +		if (*p < 'A') /* it must be 0-9 */ +			b = *p - '0'; +		else /* it's A-F or a-f */ +			b = (*p | 0x20) - 'a' + 10; /* convert to lowercase and to 10-15 */ + +		*q = *q + b << shift; +		if (shift) +			shift = 0; +		else { +			shift = 4; +			q++; +		} +	} + +	return out; +} + +/* ipmi_parse_options  -  helper function to handle parsing command line options + * + * @argc:	count of options + * @argv:	list of options + * @cmdlist:	list of supported commands + * @intflist:	list of supported interfaces + * + * returns 0 on success + * returns -1 on error + */ +int +ipmi_main(int argc, char ** argv, +		struct ipmi_cmd * cmdlist, +		struct ipmi_intf_support * intflist) +{ +	struct ipmi_intf_support * sup; +	int privlvl = 0; +	uint8_t target_addr = 0; +	uint8_t target_channel = 0; + +	uint8_t transit_addr = 0; +	uint8_t transit_channel = 0; +	uint8_t target_lun     = 0; +	uint8_t arg_addr = 0; +	uint8_t addr = 0; +	uint16_t my_long_packet_size=0; +	uint8_t my_long_packet_set=0; +	uint8_t lookupbit = 0x10;	/* use name-only lookup by default */ +	int retry = 0; +	uint32_t timeout = 0; +	int authtype = -1; +	char * tmp_pass = NULL; +	char * tmp_env = NULL; +	char * hostname = NULL; +	char * username = NULL; +	char * password = NULL; +	char * intfname = NULL; +	char * progname = NULL; +	char * oemtype  = NULL; +	char * sdrcache = NULL; +	unsigned char * kgkey = NULL; +	char * seloem   = NULL; +	int port = 0; +	int devnum = 0; +	int cipher_suite_id = 3; /* See table 22-19 of the IPMIv2 spec */ +	int argflag, i, found; +	int rc = -1; +	char sol_escape_char = SOL_ESCAPE_CHARACTER_DEFAULT; +	char * devfile  = NULL; + +	/* save program name */ +	progname = strrchr(argv[0], '/'); +	progname = ((progname == NULL) ? argv[0] : progname+1); +	signal(SIGINT, ipmi_catch_sigint); + +	while ((argflag = getopt(argc, (char **)argv, OPTION_STRING)) != -1) +	{ +		switch (argflag) { +		case 'I': +			if (intfname) { +				free(intfname); +				intfname = NULL; +			} +			intfname = strdup(optarg); +			if (intfname == NULL) { +				lprintf(LOG_ERR, "%s: malloc failure", progname); +				goto out_free; +			} +			if (intflist != NULL) { +				found = 0; +				for (sup=intflist; sup->name != NULL; sup++) { +					if (strncmp(sup->name, intfname, strlen(intfname)) == 0 && +							strncmp(sup->name, intfname, strlen(sup->name)) == 0 && +							sup->supported == 1) +						found = 1; +				} +				if (!found) { +					lprintf(LOG_ERR, "Interface %s not supported", intfname); +					goto out_free; +				} +			} +			break; +		case 'h': +			ipmi_option_usage(progname, cmdlist, intflist); +			rc = 0; +			goto out_free; +			break; +		case 'V': +			printf("%s version %s\n", progname, VERSION); +			rc = 0; +			goto out_free; +			break; +		case 'd': +			if (str2int(optarg, &devnum) != 0) { +				lprintf(LOG_ERR, "Invalid parameter given or out of range for '-d'."); +				rc = -1; +				goto out_free; +			} +			/* Check if device number is -gt 0; I couldn't find limit for +			 * kernels > 2.6, thus right side is unlimited. +			 */ +			if (devnum < 0) { +				lprintf(LOG_ERR, "Device number %i is out of range.", devnum); +				rc = -1; +				goto out_free; +			} +			break; +		case 'p': +			if (str2int(optarg, &port) != 0) { +				lprintf(LOG_ERR, "Invalid parameter given or out of range for '-p'."); +				rc = -1; +				goto out_free; +			} +			/* Check if port is -gt 0 && port is -lt 65535 */ +			if (port < 0 || port > 65535) { +				lprintf(LOG_ERR, "Port number %i is out of range.", port); +				rc = -1; +				goto out_free; +			} +			break; +		case 'C': +			if (str2int(optarg, &cipher_suite_id) != 0) { +				lprintf(LOG_ERR, "Invalid parameter given or out of range for '-C'."); +				rc = -1; +				goto out_free; +			} +			/* add check Cipher is -gt 0 */ +			if (cipher_suite_id < 0) { +				lprintf(LOG_ERR, "Cipher suite ID %i is invalid.", cipher_suite_id); +				rc = -1; +				goto out_free; +			} +			break; +		case 'v': +			verbose++; +			break; +		case 'c': +			csv_output = 1; +			break; +		case 'H': +			if (hostname) { +				free(hostname); +				hostname = NULL; +			} +			hostname = strdup(optarg); +			if (hostname == NULL) { +				lprintf(LOG_ERR, "%s: malloc failure", progname); +				goto out_free; +			} +			break; +		case 'f': +			if (password) { +				free(password); +				password = NULL; +			} +			password = ipmi_password_file_read(optarg); +			if (password == NULL) +				lprintf(LOG_ERR, "Unable to read password " +						"from file %s", optarg); +			break; +		case 'a': +#ifdef HAVE_GETPASSPHRASE +			tmp_pass = getpassphrase("Password: "); +#else +			tmp_pass = getpass("Password: "); +#endif +			if (tmp_pass != NULL) { +				if (password) { +					free(password); +					password = NULL; +				} +				password = strdup(tmp_pass); +				tmp_pass = NULL; +				if (password == NULL) { +					lprintf(LOG_ERR, "%s: malloc failure", progname); +					goto out_free; +				} +			} +			break; +		case 'k': +			if (kgkey) { +				free(kgkey); +				kgkey = NULL; +			} +			kgkey = strdup(optarg); +			if (kgkey == NULL) { +				lprintf(LOG_ERR, "%s: malloc failure", progname); +				goto out_free; +			} +			break; +		case 'K': +			if ((tmp_env = getenv("IPMI_KGKEY"))) { +				if (kgkey) { +					free(kgkey); +					kgkey = NULL; +				} +				kgkey = strdup(tmp_env); +				if (kgkey == NULL) { +					lprintf(LOG_ERR, "%s: malloc failure", progname); +					goto out_free; +				} +			} else { +				lprintf(LOG_WARN, "Unable to read kgkey from environment"); +			} +			break; +		case 'y': +			if (kgkey) { +				free(kgkey); +				kgkey = NULL; +			} +			kgkey = ipmi_parse_hex(optarg); +			if (kgkey == NULL) { +				goto out_free; +			} +			break; +		case 'Y': +#ifdef HAVE_GETPASSPHRASE +			tmp_pass = getpassphrase("Key: "); +#else +			tmp_pass = getpass("Key: "); +#endif +			if (tmp_pass != NULL) { +				if (kgkey) { +					free(kgkey); +					kgkey = NULL; +				} +				kgkey = strdup(tmp_pass); +				tmp_pass = NULL; +				if (kgkey == NULL) { +					lprintf(LOG_ERR, "%s: malloc failure", progname); +					goto out_free; +				} +			} +			break; +		case 'U': +			if (username) { +				free(username); +				username = NULL; +			} +			if (strlen(optarg) > 16) { +				lprintf(LOG_ERR, "Username is too long (> 16 bytes)"); +				goto out_free; +			} +			username = strdup(optarg); +			if (username == NULL) { +				lprintf(LOG_ERR, "%s: malloc failure", progname); +				goto out_free; +			} +			break; +		case 'S': +			if (sdrcache) { +				free(sdrcache); +				sdrcache = NULL; +			} +			sdrcache = strdup(optarg); +			if (sdrcache == NULL) { +				lprintf(LOG_ERR, "%s: malloc failure", progname); +				goto out_free; +			} +			break; +		case 'D': +			/* check for subsequent instance of -D */ +			if (devfile) { +				/* free memory for previous string */ +				free(devfile); +			} +			devfile = strdup(optarg); +			if (devfile == NULL) { +				lprintf(LOG_ERR, "%s: malloc failure", progname); +				goto out_free; +			} +			break; +#ifdef ENABLE_ALL_OPTIONS +		case 'o': +			if (oemtype) { +				free(oemtype); +				oemtype = NULL; +			} +			oemtype = strdup(optarg); +			if (oemtype == NULL) { +				lprintf(LOG_ERR, "%s: malloc failure", progname); +				goto out_free; +			} +			if (strncmp(oemtype, "list", 4) == 0 || +					strncmp(oemtype, "help", 4) == 0) { +				ipmi_oem_print(); +				rc = 0; +				goto out_free; +			} +			break; +		case 'g': +			/* backwards compatible oem hack */ +			if (oemtype) { +				free(oemtype); +				oemtype = NULL; +			} +			oemtype = strdup("intelwv2"); +			break; +		case 's': +			/* backwards compatible oem hack */ +			if (oemtype) { +				free(oemtype); +				oemtype = NULL; +			} +			oemtype = strdup("supermicro"); +			break; +		case 'P': +			if (password) { +				free(password); +				password = NULL; +			} +			password = strdup(optarg); +			if (password == NULL) { +				lprintf(LOG_ERR, "%s: malloc failure", progname); +				goto out_free; +			} + +			/* Prevent password snooping with ps */ +			i = strlen(optarg); +			memset(optarg, 'X', i); +			break; +		case 'E': +			if ((tmp_env = getenv("IPMITOOL_PASSWORD"))) { +				if (password) { +					free(password); +					password = NULL; +				} +				password = strdup(tmp_env); +				if (password == NULL) { +					lprintf(LOG_ERR, "%s: malloc failure", progname); +					goto out_free; +				} +			} +			else if ((tmp_env = getenv("IPMI_PASSWORD"))) { +				if (password) { +					free(password); +					password = NULL; +				} +				password = strdup(tmp_env); +				if (password == NULL) { +					lprintf(LOG_ERR, "%s: malloc failure", progname); +					goto out_free; +				} +			} +			else { +				lprintf(LOG_WARN, "Unable to read password from environment"); +			} +			break; +		case 'L': +			i = strlen(optarg); +			if ((i > 0) && (optarg[i-1] == '+')) { +				lookupbit = 0; +				optarg[i-1] = 0; +			} +			privlvl = str2val(optarg, ipmi_privlvl_vals); +			if (privlvl == 0xFF) { +				lprintf(LOG_WARN, "Invalid privilege level %s", optarg); +			} +			break; +		case 'A': +			authtype = str2val(optarg, ipmi_authtype_session_vals); +			break; +		case 't': +			if (str2uchar(optarg, &target_addr) != 0) { +				lprintf(LOG_ERR, "Invalid parameter given or out of range for '-t'."); +				rc = -1; +				goto out_free; +			} +			break; +		case 'b': +			if (str2uchar(optarg, &target_channel) != 0) { +				lprintf(LOG_ERR, "Invalid parameter given or out of range for '-b'."); +				rc = -1; +				goto out_free; +			} +			break; +		case 'T': +			if (str2uchar(optarg, &transit_addr) != 0) { +				lprintf(LOG_ERR, "Invalid parameter given or out of range for '-T'."); +				rc = -1; +				goto out_free; +			} +			break; +		case 'B': +			if (str2uchar(optarg, &transit_channel) != 0) { +				lprintf(LOG_ERR, "Invalid parameter given or out of range for '-B'."); +				rc = -1; +				goto out_free; +			} +			break; +		case 'l': +			if (str2uchar(optarg, &target_lun) != 0) { +				lprintf(LOG_ERR, "Invalid parameter given or out of range for '-l'."); +				rc = 1; +				goto out_free; +			} +			break; +		case 'm': +			if (str2uchar(optarg, &arg_addr) != 0) { +				lprintf(LOG_ERR, "Invalid parameter given or out of range for '-m'."); +				rc = -1; +				goto out_free; +			} +			break; +		case 'e': +			sol_escape_char = optarg[0]; +			break; +		case 'O': +			if (seloem) { +				free(seloem); +				seloem = NULL; +			} +			seloem = strdup(optarg); +			if (seloem == NULL) { +				lprintf(LOG_ERR, "%s: malloc failure", progname); +				goto out_free; +			} +			break; +		case 'z': +			if (str2ushort(optarg, &my_long_packet_size) != 0) { +				lprintf(LOG_ERR, "Invalid parameter given or out of range for '-z'."); +				rc = -1; +				goto out_free; +			} +			break; +		/* Retry and Timeout */ +		case 'R': +			if (str2int(optarg, &retry) != 0 || retry < 0) { +				lprintf(LOG_ERR, "Invalid parameter given or out of range for '-R'."); +				rc = -1; +				goto out_free; +			} +			break; +		case 'N': +			if (str2uint(optarg, &timeout) != 0) { +				lprintf(LOG_ERR, "Invalid parameter given or out of range for '-N'."); +				rc = -1; +				goto out_free; +			} +			break; +#endif +		default: +			ipmi_option_usage(progname, cmdlist, intflist); +			goto out_free; +		} +	} + +	/* check for command before doing anything */ +	if (argc-optind > 0 && +			strncmp(argv[optind], "help", 4) == 0) { +		ipmi_cmd_print(cmdlist); +		rc = 0; +		goto out_free; +	} + +	/* +	 * If the user has specified a hostname (-H option) +	 * then this is a remote access session. +	 * +	 * If no password was specified by any other method +	 * and the authtype was not explicitly set to NONE +	 * then prompt the user. +	 */ +	if (hostname != NULL && password == NULL && +			(authtype != IPMI_SESSION_AUTHTYPE_NONE || authtype < 0)) { +#ifdef HAVE_GETPASSPHRASE +		tmp_pass = getpassphrase("Password: "); +#else +		tmp_pass = getpass("Password: "); +#endif +		if (tmp_pass != NULL) { +			password = strdup(tmp_pass); +			tmp_pass = NULL; +			if (password == NULL) { +				lprintf(LOG_ERR, "%s: malloc failure", progname); +				goto out_free; +			} +		} +	} + +	/* if no interface was specified but a +	 * hostname was then use LAN by default +	 * otherwise the default is hardcoded +	 * to use the first entry in the list +	 */ +	if (intfname == NULL && hostname != NULL) { +		intfname = strdup("lan"); +		if (intfname == NULL) { +			lprintf(LOG_ERR, "%s: malloc failure", progname); +			goto out_free; +		} +	} + +	if (password != NULL && intfname != NULL) { +		if (strcmp(intfname, "lan") == 0 && strlen(password) > 16) { +			lprintf(LOG_ERR, "%s: password is longer than 16 bytes.", intfname); +			rc = -1; +			goto out_free; +		} else if (strcmp(intfname, "lanplus") == 0 && strlen(password) > 20) { +			lprintf(LOG_ERR, "%s: password is longer than 20 bytes.", intfname); +			rc = -1; +			goto out_free; +		} +	} /* if (password != NULL && intfname != NULL) */ + +	/* load interface */ +	ipmi_main_intf = ipmi_intf_load(intfname); +	if (ipmi_main_intf == NULL) { +		lprintf(LOG_ERR, "Error loading interface %s", intfname); +		goto out_free; +	} + +	/* setup log */ +	log_init(progname, 0, verbose); + +	/* run OEM setup if found */ +	if (oemtype != NULL && +	    ipmi_oem_setup(ipmi_main_intf, oemtype) < 0) { +		lprintf(LOG_ERR, "OEM setup for \"%s\" failed", oemtype); +		goto out_free; +	} + +	/* set session variables */ +	if (hostname != NULL) +		ipmi_intf_session_set_hostname(ipmi_main_intf, hostname); +	if (username != NULL) +		ipmi_intf_session_set_username(ipmi_main_intf, username); +	if (password != NULL) +		ipmi_intf_session_set_password(ipmi_main_intf, password); +	if (kgkey != NULL) +		ipmi_intf_session_set_kgkey(ipmi_main_intf, kgkey); +	if (port > 0) +		ipmi_intf_session_set_port(ipmi_main_intf, port); +	if (authtype >= 0) +		ipmi_intf_session_set_authtype(ipmi_main_intf, (uint8_t)authtype); +	if (privlvl > 0) +		ipmi_intf_session_set_privlvl(ipmi_main_intf, (uint8_t)privlvl); +	else +		ipmi_intf_session_set_privlvl(ipmi_main_intf, +				IPMI_SESSION_PRIV_ADMIN);	/* default */ +	/* Adding retry and timeout for interface that support it */ +	if (retry > 0) +		ipmi_intf_session_set_retry(ipmi_main_intf, retry); +	if (timeout > 0) +		ipmi_intf_session_set_timeout(ipmi_main_intf, timeout); + +	ipmi_intf_session_set_lookupbit(ipmi_main_intf, lookupbit); +	ipmi_intf_session_set_sol_escape_char(ipmi_main_intf, sol_escape_char); +	ipmi_intf_session_set_cipher_suite_id(ipmi_main_intf, cipher_suite_id); + +	ipmi_main_intf->devnum = devnum; + +	/* setup device file if given */ +	ipmi_main_intf->devfile = devfile; + +	/* Open the interface with the specified or default IPMB address */ +	ipmi_main_intf->my_addr = arg_addr ? arg_addr : IPMI_BMC_SLAVE_ADDR; +	if (ipmi_main_intf->open != NULL) { +		if (ipmi_main_intf->open(ipmi_main_intf) < 0) { +			goto out_free; +		} +	} +	/* +	 * Attempt picmg discovery of the actual interface address unless +	 * the users specified an address. +	 *	Address specification always overrides discovery +	 */ +	if (picmg_discover(ipmi_main_intf) && !arg_addr) { +		lprintf(LOG_DEBUG, "Running PICMG Get Address Info"); +		addr = ipmi_picmg_ipmb_address(ipmi_main_intf); +		lprintf(LOG_INFO,  "Discovered IPMB-0 address 0x%x", addr); +	} + +	/* +	 * If we discovered the ipmb address and it is not the same as what we +	 * used for open, Set the discovered IPMB address as my address if the +	 * interface supports it. +	 */ +	if (addr != 0 && addr != ipmi_main_intf->my_addr && +						ipmi_main_intf->set_my_addr) { +		/* +		 * Only set the interface address on interfaces which support +		 * it +		 */ +		(void) ipmi_main_intf->set_my_addr(ipmi_main_intf, addr); +	} + +	/* If bridging addresses are specified, handle them */ +	if (target_addr > 0) { +		ipmi_main_intf->target_addr = target_addr; +		ipmi_main_intf->target_lun = target_lun ; +		ipmi_main_intf->target_channel = target_channel ; +	} +	if (transit_addr > 0) { +		/* sanity check, transit makes no sense without a target */ +		if ((transit_addr != 0 || transit_channel != 0) && +			ipmi_main_intf->target_addr == 0) { +			lprintf(LOG_ERR, +				"Transit address/channel %#x/%#x ignored. " +				"Target address must be specified!", +				transit_addr, transit_channel); +			goto out_free; +		} + +		ipmi_main_intf->transit_addr    = transit_addr; +		ipmi_main_intf->transit_channel = transit_channel; +	} +	if (ipmi_main_intf->target_addr > 0) { +		/* must be admin level to do this over lan */ +		ipmi_intf_session_set_privlvl(ipmi_main_intf, IPMI_SESSION_PRIV_ADMIN); +		/* Get the ipmb address of the targeted entity */ +		ipmi_main_intf->target_ipmb_addr = +					ipmi_picmg_ipmb_address(ipmi_main_intf); +		lprintf(LOG_DEBUG, "Specified addressing     Target  %#x:%#x Transit %#x:%#x", +					   ipmi_main_intf->target_addr, +					   ipmi_main_intf->target_channel, +					   ipmi_main_intf->transit_addr, +					   ipmi_main_intf->transit_channel); +		if (ipmi_main_intf->target_ipmb_addr) { +			lprintf(LOG_INFO, "Discovered Target IPMB-0 address %#x", +					   ipmi_main_intf->target_ipmb_addr); +		} +	} + +	lprintf(LOG_DEBUG, "Interface address: my_addr %#x " +			   "transit %#x:%#x target %#x:%#x " +			   "ipmb_target %#x\n", +			ipmi_main_intf->my_addr, +			ipmi_main_intf->transit_addr, +			ipmi_main_intf->transit_channel, +			ipmi_main_intf->target_addr, +			ipmi_main_intf->target_channel, +			ipmi_main_intf->target_ipmb_addr); + +	/* parse local SDR cache if given */ +	if (sdrcache != NULL) { +		ipmi_sdr_list_cache_fromfile(ipmi_main_intf, sdrcache); +	} +	/* Parse SEL OEM file if given */ +	if (seloem != NULL) { +		ipmi_sel_oem_init(seloem); +	} + +	/* Enable Big Buffer when requested */ +	if ( my_long_packet_size != 0 ) { +		/* Enable Big Buffer when requested */ +		if (!ipmi_oem_active(ipmi_main_intf, "kontron") || +			ipmi_kontronoem_set_large_buffer(ipmi_main_intf, +					my_long_packet_size ) == 0) { +			printf("Setting large buffer to %i\n", my_long_packet_size); +			my_long_packet_set = 1; +			ipmi_intf_set_max_request_data_size(ipmi_main_intf, +					my_long_packet_size); +		} +	} + +	ipmi_main_intf->cmdlist = cmdlist; + +	/* now we finally run the command */ +	if (argc-optind > 0) +		rc = ipmi_cmd_run(ipmi_main_intf, argv[optind], argc-optind-1, +				&(argv[optind+1])); +	else +		rc = ipmi_cmd_run(ipmi_main_intf, NULL, 0, NULL); + +	if (my_long_packet_set == 1) { +		if (ipmi_oem_active(ipmi_main_intf, "kontron")) { +			/* Restore defaults */ +			ipmi_kontronoem_set_large_buffer( ipmi_main_intf, 0 ); +		} +	} + +	/* clean repository caches */ +	ipmi_cleanup(ipmi_main_intf); + +	/* call interface close function if available */ +	if (ipmi_main_intf->opened > 0 && ipmi_main_intf->close != NULL) +		ipmi_main_intf->close(ipmi_main_intf); + +	out_free: +	log_halt(); + +	if (intfname != NULL) { +		free(intfname); +		intfname = NULL; +	} +	if (hostname != NULL) { +		free(hostname); +		hostname = NULL; +	} +	if (username != NULL) { +		free(username); +		username = NULL; +	} +	if (password != NULL) { +		free(password); +		password = NULL; +	} +	if (oemtype != NULL) { +		free(oemtype); +		oemtype = NULL; +	} +	if (seloem != NULL) { +		free(seloem); +		seloem = NULL; +	} +	if (kgkey != NULL) { +		free(kgkey); +		kgkey = NULL; +	} +	if (sdrcache != NULL) { +		free(sdrcache); +		sdrcache = NULL; +	} +	if (devfile) { +		free(devfile); +		devfile = NULL; +	} + +	return rc; +} + + | 
