xref: /openbmc/ipmitool/lib/ipmi_firewall.c (revision 2d79e69f)
1 /*
2  * Copyright (c) 2005 International Business Machines, Inc.  All Rights Reserved.
3  * Copyright (c) 2003 Sun Microsystems, Inc.  All Rights Reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * Redistribution of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *
12  * Redistribution in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  *
16  * Neither the name of Sun Microsystems, Inc. or the names of
17  * contributors may be used to endorse or promote products derived
18  * from this software without specific prior written permission.
19  *
20  * This software is provided "AS IS," without a warranty of any kind.
21  * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
22  * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
23  * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
24  * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
25  * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
26  * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.  IN NO EVENT WILL
27  * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
28  * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
29  * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
30  * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
31  * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
32  */
33 
34 #include <stdlib.h>
35 #include <string.h>
36 #include <stdio.h>
37 #include <time.h>
38 
39 #include <ipmitool/helper.h>
40 #include <ipmitool/log.h>
41 #include <ipmitool/bswap.h>
42 #include <ipmitool/ipmi.h>
43 #include <ipmitool/ipmi_intf.h>
44 #include <ipmitool/ipmi_firewall.h>
45 #include <ipmitool/ipmi_strings.h>
46 
47 static void
printf_firewall_usage(void)48 printf_firewall_usage(void)
49 {
50 	lprintf(LOG_NOTICE,
51 "Firmware Firewall Commands:");
52 	lprintf(LOG_NOTICE,
53 "\tinfo [channel H] [lun L]");
54 	lprintf(LOG_NOTICE,
55 "\tinfo [channel H] [lun L [netfn N [command C [subfn S]]]]");
56 	lprintf(LOG_NOTICE,
57 "\tenable [channel H] [lun L [netfn N [command C [subfn S]]]]");
58 	lprintf(LOG_NOTICE,
59 "\tdisable [channel H] [lun L [netfn N [command C [subfn S]]]] [force])");
60 	lprintf(LOG_NOTICE,
61 "\treset [channel H]");
62 	lprintf(LOG_NOTICE,
63 "\t\twhere H is a Channel, L is a LUN, N is a NetFn,");
64 	lprintf(LOG_NOTICE,
65 "\t\tC is a Command and S is a Sub-Function");
66 }
67 
68 void
printf_firewall_info_usage(void)69 printf_firewall_info_usage(void)
70 {
71 	lprintf(LOG_NOTICE,
72 "info [channel H]");
73 	lprintf(LOG_NOTICE,
74 "\tList all of the firewall information for all LUNs, NetFns");
75 	lprintf(LOG_NOTICE,
76 "\tand Commands, This is a long list and is not very human readable.");
77 	lprintf(LOG_NOTICE,
78 "info [channel H] lun L");
79 	lprintf(LOG_NOTICE,
80 "\tThis also prints a long list that is not very human readable.");
81 	lprintf(LOG_NOTICE,
82 "info [channel H] lun L netfn N");
83 	lprintf(LOG_NOTICE,
84 "\tThis prints out information for a single LUN/NetFn pair.");
85 	lprintf(LOG_NOTICE,
86 "\tThat is not really very usable, but at least it is short.");
87 	lprintf(LOG_NOTICE,
88 "info [channel H] lun L netfn N command C");
89 	lprintf(LOG_NOTICE,
90 "\tThis is the one you want -- it prints out detailed human");
91 	lprintf(LOG_NOTICE,
92 "\treadable information.  It shows the support, configurable, and");
93 	lprintf(LOG_NOTICE,
94 "\tenabled bits for the Command C on LUN/NetFn pair L,N and the");
95 	lprintf(LOG_NOTICE,
96 "\tsame information about each of its Sub-functions.");
97 }
98 
99 // print n bytes of bit field bf (if invert, print ~bf)
print_bitfield(const unsigned char * bf,int n,int invert,int loglevel)100 static void print_bitfield(const unsigned char * bf, int n, int invert, int loglevel) {
101 	int i = 0;
102 	if (loglevel < 0) {
103 		while (i<n) {
104 			printf("%02x", (unsigned char) (invert?~bf[i]:bf[i]));
105 			if (++i % 4 == 0)
106 				printf(" ");
107 		}
108 		printf("\n");
109 	} else {
110 		while (i<n) {
111 			lprintf(loglevel, "%02x", (unsigned char) (invert?~bf[i]:bf[i]));
112 			if (++i % 4 == 0)
113 				lprintf(loglevel, " ");
114 		}
115 		lprintf(loglevel, "\n");
116 	}
117 
118 }
119 
120 static int
ipmi_firewall_parse_args(int argc,char ** argv,struct ipmi_function_params * p)121 ipmi_firewall_parse_args(int argc, char ** argv, struct ipmi_function_params * p)
122 {
123 	int i;
124 	uint8_t conv_err = 0;
125 
126 	if (!p) {
127 		lprintf(LOG_ERR, "ipmi_firewall_parse_args: p is NULL");
128 		return -1;
129 	}
130 	for (i=0; i<argc; i++) {
131 		if (strncmp(argv[i], "channel", 7) == 0 && (++i < argc)) {
132 			uint8_t channel_tmp = 0;
133 			if (is_ipmi_channel_num(argv[i], &channel_tmp) != 0) {
134 				conv_err = 1;
135 				break;
136 			} else {
137 				p->channel = channel_tmp;
138 			}
139 		}
140 		else if (strncmp(argv[i], "lun", 3) == 0 && (++i < argc)) {
141 			if (str2int(argv[i], &(p->lun)) != 0) {
142 				lprintf(LOG_ERR, "Given lun '%s' is invalid.", argv[i]);
143 				conv_err = 1;
144 				break;
145 			}
146 		}
147 		else if (strncmp(argv[i], "force", 5) == 0) {
148 			p->force = 1;
149 		}
150 		else if (strncmp(argv[i], "netfn", 5) == 0 && (++i < argc)) {
151 			if (str2int(argv[i], &(p->netfn)) != 0) {
152 				lprintf(LOG_ERR, "Given netfn '%s' is invalid.", argv[i]);
153 				conv_err = 1;
154 				break;
155 			}
156 		}
157 		else if (strncmp(argv[i], "command", 7) == 0 && (++i < argc)) {
158 			if (str2int(argv[i], &(p->command)) != 0) {
159 				lprintf(LOG_ERR, "Given command '%s' is invalid.", argv[i]);
160 				conv_err = 1;
161 				break;
162 			}
163 		}
164 		else if (strncmp(argv[i], "subfn", 5) == 0 && (++i < argc)) {
165 			if (str2int(argv[i], &(p->subfn)) != 0) {
166 				lprintf(LOG_ERR, "Given subfn '%s' is invalid.", argv[i]);
167 				conv_err = 1;
168 				break;
169 			}
170 		}
171 	}
172 	if (conv_err != 0) {
173 		return (-1);
174 	}
175 	if (p->subfn >= MAX_SUBFN) {
176 		lprintf(LOG_ERR, "subfn is out of range (0-%d)", MAX_SUBFN-1);
177 		return -1;
178 	}
179 	if (p->command >= MAX_COMMAND) {
180 		lprintf(LOG_ERR, "command is out of range (0-%d)", MAX_COMMAND-1);
181 		return -1;
182 	}
183 	if (p->netfn >= MAX_NETFN) {
184 		lprintf(LOG_ERR, "netfn is out of range (0-%d)", MAX_NETFN-1);
185 		return -1;
186 	}
187 	if (p->lun >= MAX_LUN) {
188 		lprintf(LOG_ERR, "lun is out of range (0-%d)", MAX_LUN-1);
189 		return -1;
190 	}
191 	if (p->netfn >= 0 && p->lun < 0) {
192 		lprintf(LOG_ERR, "if netfn is set, so must be lun");
193 		return -1;
194 	}
195 	if (p->command >= 0 && p->netfn < 0) {
196 		lprintf(LOG_ERR, "if command is set, so must be netfn");
197 		return -1;
198 	}
199 	if (p->subfn >= 0 && p->command < 0) {
200 		lprintf(LOG_ERR, "if subfn is set, so must be command");
201 		return -1;
202 	}
203 	return 0;
204 }
205 
206 /* _get_netfn_suport
207  *
208  * @intf:	ipmi interface
209  * @channel:	ipmi channel
210  * @lun:	a pointer to a 4 byte field
211  * @netfn:	a pointer to a 128-bit bitfield (16 bytes)
212  *
213  * returns 0 on success and fills in the bitfield for
214  * the 32 netfn * 4 LUN pairs that support commands
215  * returns -1 on error
216  */
217 static int
_get_netfn_support(struct ipmi_intf * intf,int channel,unsigned char * lun,unsigned char * netfn)218 _get_netfn_support(struct ipmi_intf * intf, int channel, unsigned char * lun, unsigned char * netfn)
219 {
220 	struct ipmi_rs * rsp;
221 	struct ipmi_rq req;
222 	unsigned char * d, rqdata;
223 	unsigned int l;
224 
225 	if (!lun || !netfn) {
226 		lprintf(LOG_ERR, "_get_netfn_suport: lun or netfn is NULL");
227 		return -1;
228 	}
229 
230 	memset(&req, 0, sizeof(req));
231 	req.msg.netfn = IPMI_NETFN_APP;
232 	req.msg.cmd = BMC_GET_NETFN_SUPPORT;
233 	rqdata = (unsigned char) channel;
234 	req.msg.data = &rqdata;
235 	req.msg.data_len = 1;
236 
237 	rsp = intf->sendrecv(intf, &req);
238 	if (rsp == NULL) {
239 		lprintf(LOG_ERR, "Get NetFn Support command failed");
240 		return -1;
241 	}
242 	if (rsp->ccode > 0) {
243 		lprintf(LOG_ERR, "Get NetFn Support command failed: %s",
244 			val2str(rsp->ccode, completion_code_vals));
245 		return -1;
246 	}
247 
248 	d = rsp->data;
249 	for (l=0; l<4; l++) {
250 		lun[l] = (*d)>>(2*l) & 0x3;
251 	}
252 	d++;
253 
254 	memcpy(netfn, d, 16);
255 
256 	return 0;
257 }
258 
259 /* _get_command_suport
260  *
261  * @intf:	ipmi interface
262  * @p:		a pointer to a struct ipmi_function_params
263  * @lnfn:	a pointer to a struct lun_netfn_support
264  *
265  * returns 0 on success and fills in lnfn according to the request in p
266  * returns -1 on error
267  */
268 static int
_get_command_support(struct ipmi_intf * intf,struct ipmi_function_params * p,struct lun_netfn_support * lnfn)269 _get_command_support(struct ipmi_intf * intf,
270 	struct ipmi_function_params * p, struct lun_netfn_support * lnfn)
271 {
272 	struct ipmi_rs * rsp;
273 	struct ipmi_rq req;
274 	unsigned char * d, rqdata[3];
275 	unsigned int c;
276 
277 	if (!p || !lnfn) {
278 		lprintf(LOG_ERR, "_get_netfn_suport: p or lnfn is NULL");
279 		return -1;
280 	}
281 
282 	memset(&req, 0, sizeof(req));
283 	req.msg.netfn = IPMI_NETFN_APP;
284 	req.msg.cmd = BMC_GET_COMMAND_SUPPORT;
285 	rqdata[0] = (unsigned char) p->channel;
286 	rqdata[1] = p->netfn;
287 	rqdata[2] = p->lun;
288 	req.msg.data = rqdata;
289 	req.msg.data_len = 3;
290 
291 	rsp = intf->sendrecv(intf, &req);
292 	if (rsp == NULL) {
293 		lprintf(LOG_ERR, "Get Command Support (LUN=%d, NetFn=%d, op=0) command failed", p->lun, p->netfn);
294 		return -1;
295 	}
296 	if (rsp->ccode > 0) {
297 		lprintf(LOG_ERR, "Get Command Support (LUN=%d, NetFn=%d, op=0) command failed: %s",
298 			p->lun, p->netfn, val2str(rsp->ccode, completion_code_vals));
299 		return -1;
300 	}
301 
302 	d = rsp->data;
303 	for (c=0; c<128; c++) {
304 		if (!(d[c>>3] & (1<<(c%8))))
305 			lnfn->command[c].support |= BIT_AVAILABLE;
306 	}
307 	memcpy(lnfn->command_mask, d, MAX_COMMAND_BYTES/2);
308 
309 	memset(&req, 0, sizeof(req));
310 	req.msg.netfn = IPMI_NETFN_APP;
311 	req.msg.cmd = BMC_GET_COMMAND_SUPPORT;
312 	rqdata[0] = (unsigned char) p->channel;
313 	rqdata[1] = 0x40 | p->netfn;
314 	rqdata[2] = p->lun;
315 	req.msg.data = rqdata;
316 	req.msg.data_len = 3;
317 
318 	rsp = intf->sendrecv(intf, &req);
319 	if (rsp == NULL) {
320 		lprintf(LOG_ERR, "Get Command Support (LUN=%d, NetFn=%d, op=1) command failed", p->lun, p->netfn);
321 		return -1;
322 	}
323 	if (rsp->ccode > 0) {
324 		lprintf(LOG_ERR, "Get Command Support (LUN=%d, NetFn=%d, op=1) command failed: %s",
325 			p->lun, p->netfn, val2str(rsp->ccode, completion_code_vals));
326 		return -1;
327 	}
328 
329 	d = rsp->data;
330 	for (c=0; c<128; c++) {
331 		if (!(d[c>>3] & (1<<(c%8))))
332 			lnfn->command[128+c].support |= BIT_AVAILABLE;
333 	}
334 	memcpy(lnfn->command_mask+MAX_COMMAND_BYTES/2, d, MAX_COMMAND_BYTES/2);
335 	return 0;
336 }
337 
338 /* _get_command_configurable
339  *
340  * @intf:	ipmi interface
341  * @p:		a pointer to a struct ipmi_function_params
342  * @lnfn:	a pointer to a struct lun_netfn_support
343  *
344  * returns 0 on success and fills in lnfn according to the request in p
345  * returns -1 on error
346  */
347 static int
_get_command_configurable(struct ipmi_intf * intf,struct ipmi_function_params * p,struct lun_netfn_support * lnfn)348 _get_command_configurable(struct ipmi_intf * intf,
349 	struct ipmi_function_params * p, struct lun_netfn_support * lnfn)
350 {
351 	struct ipmi_rs * rsp;
352 	struct ipmi_rq req;
353 	unsigned char * d, rqdata[3];
354 	unsigned int c;
355 
356 	if (!p || !lnfn) {
357 		lprintf(LOG_ERR, "_get_command_configurable: p or lnfn is NULL");
358 		return -1;
359 	}
360 
361 	memset(&req, 0, sizeof(req));
362 	req.msg.netfn = IPMI_NETFN_APP;
363 	req.msg.cmd = BMC_GET_CONFIGURABLE_COMMANDS;
364 	rqdata[0] = (unsigned char) p->channel;
365 	rqdata[1] = p->netfn;
366 	rqdata[2] = p->lun;
367 	req.msg.data = rqdata;
368 	req.msg.data_len = 3;
369 
370 	rsp = intf->sendrecv(intf, &req);
371 	if (rsp == NULL) {
372 		lprintf(LOG_ERR, "Get Configurable Command (LUN=%d, NetFn=%d, op=0) command failed", p->lun, p->netfn);
373 		return -1;
374 	}
375 	if (rsp->ccode > 0) {
376 		lprintf(LOG_ERR, "Get Configurable Command (LUN=%d, NetFn=%d, op=0) command failed: %s",
377 			p->lun, p->netfn, val2str(rsp->ccode, completion_code_vals));
378 		return -1;
379 	}
380 
381 	d = rsp->data;
382 	for (c=0; c<128; c++) {
383 		if (d[c>>3] & (1<<(c%8)))
384 			lnfn->command[c].support |= BIT_CONFIGURABLE;
385 	}
386 	memcpy(lnfn->config_mask, d, MAX_COMMAND_BYTES/2);
387 
388 	memset(&req, 0, sizeof(req));
389 	req.msg.netfn = IPMI_NETFN_APP;
390 	req.msg.cmd = BMC_GET_CONFIGURABLE_COMMANDS;
391 	rqdata[0] = (unsigned char) p->channel;
392 	rqdata[1] = 0x40 | p->netfn;
393 	rqdata[2] = p->lun;
394 	req.msg.data = rqdata;
395 	req.msg.data_len = 3;
396 
397 	rsp = intf->sendrecv(intf, &req);
398 	if (rsp == NULL) {
399 		lprintf(LOG_ERR, "Get Configurable Command (LUN=%d, NetFn=%d, op=1) command failed", p->lun, p->netfn);
400 		return -1;
401 	}
402 	if (rsp->ccode > 0) {
403 		lprintf(LOG_ERR, "Get Configurable Command (LUN=%d, NetFn=%d, op=1) command failed: %s",
404 			p->lun, p->netfn, val2str(rsp->ccode, completion_code_vals));
405 		return -1;
406 	}
407 
408 	d = rsp->data;
409 	for (c=0; c<128; c++) {
410 		if (d[c>>3] & (1<<(c%8)))
411 			lnfn->command[128+c].support |= BIT_CONFIGURABLE;
412 	}
413 	memcpy(lnfn->config_mask+MAX_COMMAND_BYTES/2, d, MAX_COMMAND_BYTES/2);
414 	return 0;
415 }
416 
417 /* _get_command_enables
418  *
419  * @intf:	ipmi interface
420  * @p:		a pointer to a struct ipmi_function_params
421  * @lnfn:	a pointer to a struct lun_netfn_support
422  *
423  * returns 0 on success and fills in lnfn according to the request in p
424  * returns -1 on error
425  */
426 static int
_get_command_enables(struct ipmi_intf * intf,struct ipmi_function_params * p,struct lun_netfn_support * lnfn)427 _get_command_enables(struct ipmi_intf * intf,
428 	struct ipmi_function_params * p, struct lun_netfn_support * lnfn)
429 {
430 	struct ipmi_rs * rsp;
431 	struct ipmi_rq req;
432 	unsigned char * d, rqdata[3];
433 	unsigned int c;
434 
435 	if (!p || !lnfn) {
436 		lprintf(LOG_ERR, "_get_command_enables: p or lnfn is NULL");
437 		return -1;
438 	}
439 
440 	memset(&req, 0, sizeof(req));
441 	req.msg.netfn = IPMI_NETFN_APP;
442 	req.msg.cmd = BMC_GET_COMMAND_ENABLES;
443 	rqdata[0] = (unsigned char) p->channel;
444 	rqdata[1] = p->netfn;
445 	rqdata[2] = p->lun;
446 	req.msg.data = rqdata;
447 	req.msg.data_len = 3;
448 
449 	rsp = intf->sendrecv(intf, &req);
450 	if (rsp == NULL) {
451 		lprintf(LOG_ERR, "Get Command Enables (LUN=%d, NetFn=%d, op=0) command failed", p->lun, p->netfn);
452 		return -1;
453 	}
454 	if (rsp->ccode > 0) {
455 		lprintf(LOG_ERR, "Get Command Enables (LUN=%d, NetFn=%d, op=0) command failed: %s",
456 			p->lun, p->netfn, val2str(rsp->ccode, completion_code_vals));
457 		return -1;
458 	}
459 
460 	d = rsp->data;
461 	for (c=0; c<128; c++) {
462 		if (d[c>>3] & (1<<(c%8)))
463 			lnfn->command[c].support |= BIT_ENABLED;
464 	}
465 	memcpy(lnfn->enable_mask, d, MAX_COMMAND_BYTES/2);
466 
467 	memset(&req, 0, sizeof(req));
468 	req.msg.netfn = IPMI_NETFN_APP;
469 	req.msg.cmd = BMC_GET_COMMAND_ENABLES;
470 	rqdata[0] = (unsigned char) p->channel;
471 	rqdata[1] = 0x40 | p->netfn;
472 	rqdata[2] = p->lun;
473 	req.msg.data = rqdata;
474 	req.msg.data_len = 3;
475 
476 	rsp = intf->sendrecv(intf, &req);
477 	if (rsp == NULL) {
478 		lprintf(LOG_ERR, "Get Command Enables (LUN=%d, NetFn=%d, op=1) command failed", p->lun, p->netfn);
479 		return -1;
480 	}
481 	if (rsp->ccode > 0) {
482 		lprintf(LOG_ERR, "Get Command Enables (LUN=%d, NetFn=%d, op=1) command failed: %s",
483 			p->lun, p->netfn, val2str(rsp->ccode, completion_code_vals));
484 		return -1;
485 	}
486 
487 	d = rsp->data;
488 	for (c=0; c<128; c++) {
489 		if (d[c>>3] & (1<<(c%8)))
490 			lnfn->command[128+c].support |= BIT_ENABLED;
491 	}
492 	memcpy(lnfn->enable_mask+MAX_COMMAND_BYTES/2, d, MAX_COMMAND_BYTES/2);
493 	return 0;
494 }
495 
496 /* _set_command_enables
497  *
498  * @intf:	ipmi interface
499  * @p:		a pointer to a struct ipmi_function_params
500  * @lnfn:	a pointer to a struct lun_netfn_support that contains current info
501  * @enable:	a pointer to a 32 byte bitfield that contains the desired enable state
502  * @gun:	here is a gun to shoot yourself in the foot.  If this is true
503  * 		you are allowed to disable this command
504  *
505  * returns 0 on success
506  * returns -1 on error
507  */
508 static int
_set_command_enables(struct ipmi_intf * intf,struct ipmi_function_params * p,struct lun_netfn_support * lnfn,unsigned char * enable,int gun)509 _set_command_enables(struct ipmi_intf * intf,
510 	struct ipmi_function_params * p, struct lun_netfn_support * lnfn,
511 	unsigned char * enable, int gun)
512 {
513 	struct ipmi_rs * rsp;
514 	struct ipmi_rq req;
515 	unsigned char rqdata[19];
516 	unsigned int c;
517 
518 	if (!p || !lnfn) {
519 		lprintf(LOG_ERR, "_set_command_enables: p or lnfn is NULL");
520 		return -1;
521 	}
522 
523 	lprintf(LOG_INFO, "support:            ");
524 	print_bitfield(lnfn->command_mask, MAX_COMMAND_BYTES, 1, LOG_INFO);
525 	lprintf(LOG_INFO, "configurable:       ");
526 	print_bitfield(lnfn->config_mask, MAX_COMMAND_BYTES, 0, LOG_INFO);
527 	lprintf(LOG_INFO, "enabled:            ");
528 	print_bitfield(lnfn->enable_mask, MAX_COMMAND_BYTES, 0, LOG_INFO);
529 	lprintf(LOG_INFO, "enable mask before: ");
530 	print_bitfield(enable, MAX_COMMAND_BYTES, 0, LOG_INFO);
531 
532 	// mask off the appropriate bits (if not configurable, set enable bit
533 	// must be the same as the current enable bit)
534 	for (c=0; c<(MAX_COMMAND_BYTES); c++) {
535 		enable[c] = (lnfn->config_mask[c] & enable[c]) |
536 			(~lnfn->config_mask[c] & lnfn->enable_mask[c]);
537 	}
538 
539 	// take the gun out of their hand if they are not supposed to have it
540 	if (!gun) {
541 		enable[SET_COMMAND_ENABLE_BYTE] =
542 			(lnfn->config_mask[SET_COMMAND_ENABLE_BYTE]
543 			 & SET_COMMAND_ENABLE_BIT) |
544 			(~lnfn->config_mask[SET_COMMAND_ENABLE_BYTE]
545 			 & lnfn->enable_mask[SET_COMMAND_ENABLE_BYTE]);
546 	}
547 	lprintf(LOG_INFO, "enable mask after: ");
548 	print_bitfield(enable, MAX_COMMAND_BYTES, 0, LOG_INFO);
549 
550 	memset(&req, 0, sizeof(req));
551 	req.msg.netfn = IPMI_NETFN_APP;
552 	req.msg.cmd = BMC_SET_COMMAND_ENABLES;
553 	rqdata[0] = (unsigned char) p->channel;
554 	rqdata[1] = p->netfn;
555 	rqdata[2] = p->lun;
556 	memcpy(&rqdata[3], enable, MAX_COMMAND_BYTES/2);
557 	req.msg.data = rqdata;
558 	req.msg.data_len = 19;
559 
560 	rsp = intf->sendrecv(intf, &req);
561 	if (rsp == NULL) {
562 		lprintf(LOG_ERR, "Set Command Enables (LUN=%d, NetFn=%d, op=0) command failed", p->lun, p->netfn);
563 		return -1;
564 	}
565 	if (rsp->ccode > 0) {
566 		lprintf(LOG_ERR, "Set Command Enables (LUN=%d, NetFn=%d, op=0) command failed: %s",
567 			p->lun, p->netfn, val2str(rsp->ccode, completion_code_vals));
568 		return -1;
569 	}
570 
571 	memset(&req, 0, sizeof(req));
572 	req.msg.netfn = IPMI_NETFN_APP;
573 	req.msg.cmd = BMC_SET_COMMAND_ENABLES;
574 	rqdata[0] = (unsigned char) p->channel;
575 	rqdata[1] = 0x40 | p->netfn;
576 	rqdata[2] = p->lun;
577 	memcpy(&rqdata[3], enable+MAX_COMMAND_BYTES/2, MAX_COMMAND_BYTES/2);
578 	req.msg.data = rqdata;
579 	req.msg.data_len = 19;
580 
581 	rsp = intf->sendrecv(intf, &req);
582 	if (rsp == NULL) {
583 		lprintf(LOG_ERR, "Set Command Enables (LUN=%d, NetFn=%d, op=1) command failed", p->lun, p->netfn);
584 		return -1;
585 	}
586 	if (rsp->ccode > 0) {
587 		lprintf(LOG_ERR, "Set Command Enables (LUN=%d, NetFn=%d, op=1) command failed: %s",
588 			p->lun, p->netfn, val2str(rsp->ccode, completion_code_vals));
589 		return -1;
590 	}
591 
592 	return 0;
593 }
594 
595 /* _get_subfn_support
596  *
597  * @intf:	ipmi interface
598  * @p:		a pointer to a struct ipmi_function_params
599  * @cmd:	a pointer to a struct command_support
600  *
601  * returns 0 on success and fills in cmd according to the request in p
602  * returns -1 on error
603  */
604 static int
_get_subfn_support(struct ipmi_intf * intf,struct ipmi_function_params * p,struct command_support * cmd)605 _get_subfn_support(struct ipmi_intf * intf,
606 	struct ipmi_function_params * p, struct command_support * cmd)
607 {
608 	struct ipmi_rs * rsp;
609 	struct ipmi_rq req;
610 	unsigned char rqdata[4];
611 
612 	if (!p || !cmd) {
613 		lprintf(LOG_ERR, "_get_subfn_support: p or cmd is NULL");
614 		return -1;
615 	}
616 
617 	memset(&req, 0, sizeof(req));
618 	req.msg.netfn = IPMI_NETFN_APP;
619 	req.msg.cmd = BMC_GET_COMMAND_SUBFUNCTION_SUPPORT;
620 	rqdata[0] = (unsigned char) p->channel;
621 	rqdata[1] = p->netfn;
622 	rqdata[2] = p->lun;
623 	rqdata[3] = p->command;
624 	req.msg.data = rqdata;
625 	req.msg.data_len = 4;
626 
627 	rsp = intf->sendrecv(intf, &req);
628 	if (rsp == NULL) {
629 		lprintf(LOG_ERR, "Get Command Sub-function Support (LUN=%d, NetFn=%d, command=%d) command failed", p->lun, p->netfn, p->command);
630 		return -1;
631 	}
632 	if (rsp->ccode > 0) {
633 		lprintf(LOG_ERR, "Get Command Sub-function Support (LUN=%d, NetFn=%d, command=%d) command failed: %s",
634 			p->lun, p->netfn, p->command, val2str(rsp->ccode, completion_code_vals));
635 		return -1;
636 	}
637 
638 	memcpy(cmd->subfn_support, rsp->data, sizeof(cmd->subfn_support));
639 	return 0;
640 }
641 
642 /* _get_subfn_configurable
643  *
644  * @intf:	ipmi interface
645  * @p:		a pointer to a struct ipmi_function_params
646  * @cmd:	a pointer to a struct command_support
647  *
648  * returns 0 on success and fills in cmd according to the request in p
649  * returns -1 on error
650  */
651 static int
_get_subfn_configurable(struct ipmi_intf * intf,struct ipmi_function_params * p,struct command_support * cmd)652 _get_subfn_configurable(struct ipmi_intf * intf,
653 	struct ipmi_function_params * p, struct command_support * cmd)
654 {
655 	struct ipmi_rs * rsp;
656 	struct ipmi_rq req;
657 	unsigned char rqdata[4];
658 
659 	if (!p || !cmd) {
660 		lprintf(LOG_ERR, "_get_subfn_configurable: p or cmd is NULL");
661 		return -1;
662 	}
663 
664 	memset(&req, 0, sizeof(req));
665 	req.msg.netfn = IPMI_NETFN_APP;
666 	req.msg.cmd = BMC_GET_CONFIGURABLE_COMMAND_SUBFUNCTIONS;
667 	rqdata[0] = (unsigned char) p->channel;
668 	rqdata[1] = p->netfn;
669 	rqdata[2] = p->lun;
670 	rqdata[3] = p->command;
671 	req.msg.data = rqdata;
672 	req.msg.data_len = 4;
673 
674 	rsp = intf->sendrecv(intf, &req);
675 	if (rsp == NULL) {
676 		lprintf(LOG_ERR, "Get Configurable Command Sub-function (LUN=%d, NetFn=%d, command=%d) command failed", p->lun, p->netfn, p->command);
677 		return -1;
678 	}
679 	if (rsp->ccode > 0) {
680 		lprintf(LOG_ERR, "Get Configurable Command Sub-function (LUN=%d, NetFn=%d, command=%d) command failed: %s",
681 			p->lun, p->netfn, p->command, val2str(rsp->ccode, completion_code_vals));
682 		return -1;
683 	}
684 
685 	memcpy(cmd->subfn_config, rsp->data, sizeof(cmd->subfn_config));
686 	return 0;
687 }
688 
689 /* _get_subfn_enables
690  *
691  * @intf:	ipmi interface
692  * @p:		a pointer to a struct ipmi_function_params
693  * @cmd:	a pointer to a struct command_support
694  *
695  * returns 0 on success and fills in cmd according to the request in p
696  * returns -1 on error
697  */
698 static int
_get_subfn_enables(struct ipmi_intf * intf,struct ipmi_function_params * p,struct command_support * cmd)699 _get_subfn_enables(struct ipmi_intf * intf,
700 	struct ipmi_function_params * p, struct command_support * cmd)
701 {
702 	struct ipmi_rs * rsp;
703 	struct ipmi_rq req;
704 	unsigned char rqdata[4];
705 
706 	if (!p || !cmd) {
707 		lprintf(LOG_ERR, "_get_subfn_enables: p or cmd is NULL");
708 		return -1;
709 	}
710 
711 	memset(&req, 0, sizeof(req));
712 	req.msg.netfn = IPMI_NETFN_APP;
713 	req.msg.cmd = BMC_GET_COMMAND_SUBFUNCTION_ENABLES;
714 	rqdata[0] = (unsigned char) p->channel;
715 	rqdata[1] = p->netfn;
716 	rqdata[2] = p->lun;
717 	rqdata[3] = p->command;
718 	req.msg.data = rqdata;
719 	req.msg.data_len = 4;
720 
721 	rsp = intf->sendrecv(intf, &req);
722 	if (rsp == NULL) {
723 		lprintf(LOG_ERR, "Get Command Sub-function Enables (LUN=%d, NetFn=%d, command=%d) command failed", p->lun, p->netfn, p->command);
724 		return -1;
725 	}
726 	if (rsp->ccode > 0) {
727 		lprintf(LOG_ERR, "Get Command Sub-function Enables (LUN=%d, NetFn=%d, command=%d) command failed: %s",
728 			p->lun, p->netfn, p->command, val2str(rsp->ccode, completion_code_vals));
729 		return -1;
730 	}
731 
732 	memcpy(cmd->subfn_enable, rsp->data, sizeof(cmd->subfn_enable));
733 	return 0;
734 }
735 
736 /* _set_subfn_enables
737  *
738  * @intf:	ipmi interface
739  * @p:  	a pointer to a struct ipmi_function_params
740  * @cmd:	a pointer to a struct command_support
741  * @enable:	a pointer to a 4 byte bitfield that contains the desired enable state
742  *
743  * returns 0 on success (and modifies enable to be the bits it actually set)
744  * returns -1 on error
745  */
746 static int
_set_subfn_enables(struct ipmi_intf * intf,struct ipmi_function_params * p,struct command_support * cmd,unsigned char * enable)747 _set_subfn_enables(struct ipmi_intf * intf,
748 	struct ipmi_function_params * p, struct command_support * cmd,
749 	unsigned char * enable)
750 {
751 	struct ipmi_rs * rsp;
752 	struct ipmi_rq req;
753 	unsigned char rqdata[8];
754 	unsigned int c;
755 
756 	if (!p || !cmd) {
757 		lprintf(LOG_ERR, "_set_subfn_enables: p or cmd is NULL");
758 		return -1;
759 	}
760 
761 	lprintf(LOG_INFO, "support:            ");
762 	print_bitfield(cmd->subfn_support, MAX_SUBFN_BYTES, 1, LOG_INFO);
763 	lprintf(LOG_INFO, "configurable:       ");
764 	print_bitfield(cmd->subfn_config, MAX_SUBFN_BYTES, 0, LOG_INFO);
765 	lprintf(LOG_INFO, "enabled:            ");
766 	print_bitfield(cmd->subfn_enable, MAX_SUBFN_BYTES, 0, LOG_INFO);
767 	lprintf(LOG_INFO, "enable mask before: ");
768 	print_bitfield(enable, MAX_SUBFN_BYTES, 0, LOG_INFO);
769 	// mask off the appropriate bits (if not configurable, set enable bit
770 	// must be the same as the current enable bit)
771 	for (c=0; c<sizeof(cmd->subfn_enable); c++) {
772 		enable[c] = (cmd->subfn_config[c] & enable[c]) |
773 			(~cmd->subfn_config[c] & cmd->subfn_enable[c]);
774 	}
775 	lprintf(LOG_INFO, "enable mask after: ");
776 	print_bitfield(enable, MAX_SUBFN_BYTES, 0, LOG_INFO);
777 
778 	memset(&req, 0, sizeof(req));
779 	req.msg.netfn = IPMI_NETFN_APP;
780 	req.msg.cmd = BMC_SET_COMMAND_SUBFUNCTION_ENABLES;
781 	rqdata[0] = (unsigned char) p->channel;
782 	rqdata[1] = p->netfn;
783 	rqdata[2] = p->lun;
784 	rqdata[3] = p->command;
785 	memcpy(&rqdata[4], enable, MAX_SUBFN_BYTES);
786 	req.msg.data = rqdata;
787 	req.msg.data_len = 8;
788 
789 	rsp = intf->sendrecv(intf, &req);
790 	if (rsp == NULL) {
791 		lprintf(LOG_ERR, "Set Command Sub-function Enables (LUN=%d, NetFn=%d, command=%d) command failed", p->lun, p->netfn, p->command);
792 		return -1;
793 	}
794 	if (rsp->ccode > 0) {
795 		lprintf(LOG_ERR, "Set Command Sub-function Enables (LUN=%d, NetFn=%d, command=%d) command failed: %s",
796 			p->lun, p->netfn, p->command, val2str(rsp->ccode, completion_code_vals));
797 		return -1;
798 	}
799 
800 	return 0;
801 }
802 
803 /* _gather_info
804  *
805  * @intf:	ipmi interface
806  * @p:		a pointer to a struct ipmi_function_params
807  * @bmc:	a pointer to a struct bmc_fn_support
808  * @enable:	a pointer to a 4 byte bitfield that contains the desired enable state
809  *
810  * returns 0 on success and fills in bmc according to request p
811  * returns -1 on error
812  */
_gather_info(struct ipmi_intf * intf,struct ipmi_function_params * p,struct bmc_fn_support * bmc)813 static int _gather_info(struct ipmi_intf * intf, struct ipmi_function_params * p, struct bmc_fn_support * bmc)
814 {
815 	int ret, l, n;
816 	unsigned char lun[MAX_LUN], netfn[16];
817 
818 	ret = _get_netfn_support(intf, p->channel, lun, netfn);
819 	if (!ret) {
820 		for (l=0; l<MAX_LUN; l++) {
821 			if (p->lun >= 0 && p->lun != l)
822 				continue;
823 			bmc->lun[l].support = lun[l];
824 			if (lun[l]) {
825 				for (n=0; n<MAX_NETFN_PAIR; n++) {
826 					int offset = l*MAX_NETFN_PAIR+n;
827 					bmc->lun[l].netfn[n].support =
828 						!!(netfn[offset>>3] & (1<<(offset%8)));
829 				}
830 			}
831 		}
832 	}
833 	if (p->netfn >= 0) {
834 		if (!((p->lun < 0 || bmc->lun[p->lun].support) &&
835 		      (p->netfn < 0 || bmc->lun[p->lun].netfn[p->netfn>>1].support))) {
836 			lprintf(LOG_ERR, "LUN or LUN/NetFn pair %d,%d not supported", p->lun, p->netfn);
837 			return 0;
838 		}
839 		ret = _get_command_support(intf, p, &(bmc->lun[p->lun].netfn[p->netfn>>1]));
840 		ret |= _get_command_configurable(intf, p, &(bmc->lun[p->lun].netfn[p->netfn>>1]));
841 		ret |= _get_command_enables(intf, p, &(bmc->lun[p->lun].netfn[p->netfn>>1]));
842 		if (!ret && p->command >= 0) {
843 			ret = _get_subfn_support(intf, p,
844 						 &(bmc->lun[p->lun].netfn[p->netfn>>1].command[p->command]));
845 			ret |= _get_subfn_configurable(intf, p,
846 						       &(bmc->lun[p->lun].netfn[p->netfn>>1].command[p->command]));
847 			ret |= _get_subfn_enables(intf, p,
848 						  &(bmc->lun[p->lun].netfn[p->netfn>>1].command[p->command]));
849 		}
850 	}
851 	else if (p->lun >= 0) {
852 		l = p->lun;
853 		if (bmc->lun[l].support) {
854 			for (n=0; n<MAX_NETFN_PAIR; n++) {
855 				p->netfn = n*2;
856 				if (bmc->lun[l].netfn[n].support) {
857 					ret = _get_command_support(intf, p, &(bmc->lun[l].netfn[n]));
858 					ret |= _get_command_configurable(intf, p, &(bmc->lun[l].netfn[n]));
859 					ret |= _get_command_enables(intf, p, &(bmc->lun[l].netfn[n]));
860 				}
861 				if (ret)
862 					bmc->lun[l].netfn[n].support = 0;
863 			}
864 		}
865 		p->netfn = -1;
866 	} else {
867 		for (l=0; l<4; l++) {
868 			p->lun = l;
869 			if (bmc->lun[l].support) {
870 				for (n=0; n<MAX_NETFN_PAIR; n++) {
871 					p->netfn = n*2;
872 					if (bmc->lun[l].netfn[n].support) {
873 						ret = _get_command_support(intf, p, &(bmc->lun[l].netfn[n]));
874 						ret |= _get_command_configurable(intf, p, &(bmc->lun[l].netfn[n]));
875 						ret |= _get_command_enables(intf, p, &(bmc->lun[l].netfn[n]));
876 					}
877 					if (ret)
878 						bmc->lun[l].netfn[n].support = 0;
879 				}
880 			}
881 		}
882 		p->lun = -1;
883 		p->netfn = -1;
884 	}
885 
886 	return 0;
887 }
888 
889 /* ipmi_firewall_info - print out info for firewall functions
890  *
891  * @intf:	ipmi inteface
892  * @argc:	argument count
893  * @argv:	argument list
894  *
895  * returns 0 on success
896  * returns -1 on error
897  */
898 static int
ipmi_firewall_info(struct ipmi_intf * intf,int argc,char ** argv)899 ipmi_firewall_info(struct ipmi_intf * intf, int argc, char ** argv)
900 {
901 	int ret = 0;
902 	struct ipmi_function_params p = {0xe, -1, -1, -1, -1};
903 	struct bmc_fn_support * bmc_fn_support;
904 	unsigned int l, n, c;
905 
906 	if ((argc > 0 && strncmp(argv[0], "help", 4) == 0) || ipmi_firewall_parse_args(argc, argv, &p) < 0)
907 	{
908 		printf_firewall_info_usage();
909 		return 0;
910 	}
911 
912 	bmc_fn_support = malloc(sizeof(struct bmc_fn_support));
913 	if (!bmc_fn_support) {
914 		lprintf(LOG_ERR, "malloc struct bmc_fn_support failed");
915 		return -1;
916 	}
917 
918 	ret = _gather_info(intf, &p, bmc_fn_support);
919 
920 	if (p.command >= 0) {
921       struct command_support * cmd;
922 		if (!((p.lun < 0 || bmc_fn_support->lun[p.lun].support) &&
923 			(p.netfn < 0 || bmc_fn_support->lun[p.lun].netfn[p.netfn>>1].support) &&
924 			bmc_fn_support->lun[p.lun].netfn[p.netfn>>1].command[p.command].support))
925 		{
926 			lprintf(LOG_ERR, "Command 0x%02x not supported on LUN/NetFn pair %02x,%02x",
927 				p.command, p.lun, p.netfn);
928 			free(bmc_fn_support);
929 			bmc_fn_support = NULL;
930 			return 0;
931 		}
932 		cmd =
933 			&bmc_fn_support->lun[p.lun].netfn[p.netfn>>1].command[p.command];
934 		c = cmd->support;
935 		printf("(A)vailable, (C)onfigurable, (E)nabled: | A | C | E |\n");
936 		printf("-----------------------------------------------------\n");
937 		printf("LUN %01d, NetFn 0x%02x, Command 0x%02x:        | %c | %c | %c |\n",
938 			p.lun, p.netfn, p.command,
939 			(c & BIT_AVAILABLE) ? 'X' : ' ',
940 			(c & BIT_CONFIGURABLE) ? 'X' : ' ',
941 			(c & BIT_ENABLED) ? 'X': ' ');
942 
943 		for (n=0; n<MAX_SUBFN; n++) {
944 			printf("sub-function 0x%02x:                      | %c | %c | %c |\n", n,
945 				(!bit_test(cmd->subfn_support, n)) ? 'X' : ' ',
946 				(bit_test(cmd->subfn_config, n)) ? 'X' : ' ',
947 				(bit_test(cmd->subfn_enable, n)) ? 'X' : ' ');
948 		}
949 	}
950 	else if (p.netfn >= 0) {
951 		if (!((p.lun < 0 || bmc_fn_support->lun[p.lun].support) &&
952 			(bmc_fn_support->lun[p.lun].netfn[p.netfn>>1].support)))
953 		{
954 			lprintf(LOG_ERR, "LUN or LUN/NetFn pair %02x,%02x not supported",
955 				p.lun, p.netfn);
956 			free(bmc_fn_support);
957 			bmc_fn_support = NULL;
958 			return 0;
959 		}
960 		n = p.netfn >> 1;
961 		l = p.lun;
962 		printf("Commands on LUN 0x%02x, NetFn 0x%02x\n", p.lun, p.netfn);
963 		printf("support:      ");
964 		print_bitfield(bmc_fn_support->lun[l].netfn[n].command_mask,
965 				MAX_COMMAND_BYTES, 1, -1);
966 		printf("configurable: ");
967 		print_bitfield(bmc_fn_support->lun[l].netfn[n].config_mask,
968 				MAX_COMMAND_BYTES, 0, -1);
969 		printf("enabled:      ");
970 		print_bitfield(bmc_fn_support->lun[l].netfn[n].enable_mask,
971 				MAX_COMMAND_BYTES, 0, -1);
972 	}
973 	else {
974 	    for (l=0; l<4; l++) {
975                 p.lun = l;
976                 if (bmc_fn_support->lun[l].support) {
977                     for (n=0; n<MAX_NETFN_PAIR; n++) {
978                         p.netfn = n*2;
979                         if (bmc_fn_support->lun[l].netfn[n].support) {
980                             printf("%02x,%02x support:      ", p.lun, p.netfn);
981                             print_bitfield(bmc_fn_support->lun[l].netfn[n].command_mask,
982                                     MAX_COMMAND_BYTES, 1, -1);
983                             printf("%02x,%02x configurable: ", p.lun, p.netfn);
984                             print_bitfield(bmc_fn_support->lun[l].netfn[n].config_mask,
985                                     MAX_COMMAND_BYTES, 0, -1);
986                             printf("%02x,%02x enabled:      ", p.lun, p.netfn);
987                             print_bitfield(bmc_fn_support->lun[l].netfn[n].enable_mask,
988                                     MAX_COMMAND_BYTES, 0, -1);
989                         }
990                     }
991                 }
992             }
993             p.lun = -1;
994             p.netfn = -1;
995 	}
996 
997 	free(bmc_fn_support);
998 	bmc_fn_support = NULL;
999 	return ret;
1000 }
1001 
1002 /* ipmi_firewall_enable_disable  -  enable/disable BMC functions
1003  *
1004  * @intf:	ipmi inteface
1005  * @enable:     whether to enable or disable
1006  * @argc:	argument count
1007  * @argv:	argument list
1008  *
1009  * returns 0 on success
1010  * returns -1 on error
1011  */
1012 static int
ipmi_firewall_enable_disable(struct ipmi_intf * intf,int enable,int argc,char ** argv)1013 ipmi_firewall_enable_disable(struct ipmi_intf * intf, int enable, int argc, char ** argv)
1014 {
1015 	struct ipmi_function_params p = {0xe, -1, -1, -1, -1};
1016 	struct bmc_fn_support * bmc_fn_support;
1017 	int ret;
1018 	unsigned int l, n, c;
1019 	unsigned char enables[MAX_COMMAND_BYTES];
1020 
1021 	if (argc < 1 || strncmp(argv[0], "help", 4) == 0) {
1022 		char * s1 = enable?"en":"dis";
1023 		char * s2 = enable?"":" [force]";
1024 		printf("%sable [channel H] lun L netfn N%s\n", s1, s2);
1025 		printf("\t%sable all commands on this LUN/NetFn pair\n", s1);
1026 		printf("%sable [channel H] lun L netfn N command C%s\n", s1, s2);
1027 		printf("\t%sable Command C and all its Sub-functions for this LUN/NetFn pair\n", s1);
1028 		printf("%sable [channel H] lun L netfn N command C subfn S\n", s1);
1029 		printf("\t%sable Sub-function S for Command C for this LUN/NetFn pair\n", s1);
1030 		if (!enable) {
1031 			printf("* force will allow you to disable the \"Command Set Enable\" command\n");
1032 			printf("\tthereby letting you shoot yourself in the foot\n");
1033 			printf("\tthis is only recommended for advanced users\n");
1034 		}
1035 		return 0;
1036 	}
1037 	if (ipmi_firewall_parse_args(argc, argv, &p) < 0)
1038 		return -1;
1039 
1040 	bmc_fn_support = malloc(sizeof(struct bmc_fn_support));
1041 	if (!bmc_fn_support) {
1042 		lprintf(LOG_ERR, "malloc struct bmc_fn_support failed");
1043 		return -1;
1044 	}
1045 
1046 	ret = _gather_info(intf, &p, bmc_fn_support);
1047 	if (ret < 0) {
1048 		free(bmc_fn_support);
1049 		bmc_fn_support = NULL;
1050 		return ret;
1051 	}
1052 
1053 	l = p.lun;
1054 	n = p.netfn>>1;
1055 	c = p.command;
1056 	if (p.subfn >= 0) {
1057 		// firewall (en|dis)able [channel c] lun l netfn n command m subfn s
1058 		// (en|dis)able this sub-function for this commnad on this lun/netfn pair
1059 		memcpy(enables,
1060 			bmc_fn_support->lun[l].netfn[n].command[c].subfn_enable,
1061 			MAX_SUBFN_BYTES);
1062 		bit_set(enables, p.subfn, enable);
1063 		ret = _set_subfn_enables(intf, &p,
1064 			&bmc_fn_support->lun[l].netfn[n].command[c], enables);
1065 
1066 	} else if (p.command >= 0) {
1067 		// firewall (en|dis)able [channel c] lun l netfn n command m
1068 		//    (en|dis)able all subfn and command for this commnad on this lun/netfn pair
1069 		memset(enables, enable?0xff:0, MAX_SUBFN_BYTES);
1070 		ret = _set_subfn_enables(intf, &p,
1071 			&bmc_fn_support->lun[l].netfn[n].command[c], enables);
1072 		memcpy(enables,
1073 			&bmc_fn_support->lun[l].netfn[n].enable_mask, sizeof(enables));
1074 		bit_set(enables, p.command, enable);
1075 		ret |= _set_command_enables(intf, &p,
1076 			&bmc_fn_support->lun[l].netfn[n], enables, p.force);
1077 	} else if (p.netfn >= 0) {
1078 		// firewall (en|dis)able [channel c] lun l netfn n
1079 		//    (en|dis)able all commnads on this lun/netfn pair
1080 		memset(enables, enable?0xff:0, sizeof(enables));
1081 		ret = _set_command_enables(intf, &p,
1082 			&bmc_fn_support->lun[l].netfn[n], enables, p.force);
1083 		/*
1084 		   } else if (p.lun >= 0) {
1085 		// firewall (en|dis)able [channel c] lun l
1086 		//    (en|dis)able all commnads on all netfn pairs for this lun
1087 		*/
1088 	}
1089 	free(bmc_fn_support);
1090 	bmc_fn_support = NULL;
1091 	return ret;
1092 }
1093 
1094 /* ipmi_firewall_reset - reset firmware firewall to enable everything
1095  *
1096  * @intf:	ipmi inteface
1097  * @argc:	argument count
1098  * @argv:	argument list
1099  *
1100  * returns 0 on success
1101  * returns -1 on error
1102  */
1103 static int
ipmi_firewall_reset(struct ipmi_intf * intf,int argc,char ** argv)1104 ipmi_firewall_reset(struct ipmi_intf * intf, int argc, char ** argv)
1105 {
1106 	struct ipmi_function_params p = {0xe, -1, -1, -1, -1};
1107 	struct bmc_fn_support * bmc_fn_support;
1108 	int ret;
1109 	unsigned int l, n, c;
1110 	unsigned char enables[MAX_COMMAND_BYTES];
1111 
1112 	if (argc < 1) {
1113 		lprintf(LOG_ERR, "Not enough parameters given.");
1114 		printf_firewall_usage();
1115 		return (-1);
1116 	} else if (argc > 0 && strncmp(argv[0], "help", 4) == 0) {
1117 		printf_firewall_usage();
1118 		return 0;
1119 	}
1120 	if (ipmi_firewall_parse_args(argc, argv, &p) < 0)
1121 		return -1;
1122 
1123 	bmc_fn_support = malloc(sizeof(struct bmc_fn_support));
1124 	if (!bmc_fn_support) {
1125 		lprintf(LOG_ERR, "malloc struct bmc_fn_support failed");
1126 		return -1;
1127 	}
1128 
1129 	ret = _gather_info(intf, &p, bmc_fn_support);
1130 	if (ret < 0) {
1131 		free(bmc_fn_support);
1132 		bmc_fn_support = NULL;
1133 		return ret;
1134 	}
1135 
1136 	for (l=0; l<MAX_LUN; l++) {
1137 		p.lun = l;
1138 		for (n=0; n<MAX_NETFN; n+=2) {
1139 			p.netfn = n;
1140 			for (c=0; c<MAX_COMMAND; c++) {
1141 				p.command = c;
1142 				printf("reset lun %d, netfn %d, command %d, subfn\n", l, n, c);
1143 				memset(enables, 0xff, MAX_SUBFN_BYTES);
1144 				ret = _set_subfn_enables(intf, &p,
1145 					&bmc_fn_support->lun[l].netfn[n].command[c], enables);
1146 			}
1147 			printf("reset lun %d, netfn %d, command\n", l, n);
1148 			memset(enables, 0xff, sizeof(enables));
1149 			ret = _set_command_enables(intf, &p,
1150 				&bmc_fn_support->lun[l].netfn[n], enables, 0);
1151 		}
1152 	}
1153 
1154 	free(bmc_fn_support);
1155 	bmc_fn_support = NULL;
1156 	return ret;
1157 }
1158 
1159 
1160 /* ipmi_firewall_main - top-level handler for firmware firewall functions
1161  *
1162  * @intf:	ipmi interface
1163  * @argc:	number of arguments
1164  * @argv:	argument list
1165  *
1166  * returns 0 on success
1167  * returns -1 on error
1168  */
1169 int
ipmi_firewall_main(struct ipmi_intf * intf,int argc,char ** argv)1170 ipmi_firewall_main(struct ipmi_intf * intf, int argc, char ** argv)
1171 {
1172 	int rc = 0;
1173 
1174 	if (argc < 1 || strncmp(argv[0], "help", 4) == 0) {
1175 		printf_firewall_usage();
1176 	}
1177 	else if (strncmp(argv[0], "info", 4) == 0) {
1178 		rc = ipmi_firewall_info(intf, argc-1, &(argv[1]));
1179 	}
1180 	else if (strncmp(argv[0], "enable", 6) == 0) {
1181 		rc = ipmi_firewall_enable_disable(intf, 1, argc-1, &(argv[1]));
1182 	}
1183 	else if (strncmp(argv[0], "disable", 7) == 0) {
1184 		rc = ipmi_firewall_enable_disable(intf, 0, argc-1, &(argv[1]));
1185 	}
1186 	else if (strncmp(argv[0], "reset", 5) == 0) {
1187 		rc = ipmi_firewall_reset(intf, argc-1, &(argv[1]));
1188 	}
1189 	else {
1190 		printf_firewall_usage();
1191 	}
1192 
1193 	return rc;
1194 }
1195