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