Blame lib/ipmi_firewall.c

Packit d14fb6
/*
Packit d14fb6
 * Copyright (c) 2005 International Business Machines, Inc.  All Rights Reserved.
Packit d14fb6
 * Copyright (c) 2003 Sun Microsystems, Inc.  All Rights Reserved.
Packit d14fb6
 * 
Packit d14fb6
 * Redistribution and use in source and binary forms, with or without
Packit d14fb6
 * modification, are permitted provided that the following conditions
Packit d14fb6
 * are met:
Packit d14fb6
 * 
Packit d14fb6
 * Redistribution of source code must retain the above copyright
Packit d14fb6
 * notice, this list of conditions and the following disclaimer.
Packit d14fb6
 * 
Packit d14fb6
 * Redistribution in binary form must reproduce the above copyright
Packit d14fb6
 * notice, this list of conditions and the following disclaimer in the
Packit d14fb6
 * documentation and/or other materials provided with the distribution.
Packit d14fb6
 * 
Packit d14fb6
 * Neither the name of Sun Microsystems, Inc. or the names of
Packit d14fb6
 * contributors may be used to endorse or promote products derived
Packit d14fb6
 * from this software without specific prior written permission.
Packit d14fb6
 * 
Packit d14fb6
 * This software is provided "AS IS," without a warranty of any kind.
Packit d14fb6
 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
Packit d14fb6
 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
Packit d14fb6
 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
Packit d14fb6
 * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
Packit d14fb6
 * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
Packit d14fb6
 * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.  IN NO EVENT WILL
Packit d14fb6
 * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
Packit d14fb6
 * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
Packit d14fb6
 * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
Packit d14fb6
 * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
Packit d14fb6
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
Packit d14fb6
 */
Packit d14fb6
Packit d14fb6
#include <stdlib.h>
Packit d14fb6
#include <string.h>
Packit d14fb6
#include <stdio.h>
Packit d14fb6
#include <time.h>
Packit d14fb6
Packit d14fb6
#include <ipmitool/helper.h>
Packit d14fb6
#include <ipmitool/log.h>
Packit d14fb6
#include <ipmitool/bswap.h>
Packit d14fb6
#include <ipmitool/ipmi.h>
Packit d14fb6
#include <ipmitool/ipmi_intf.h>
Packit d14fb6
#include <ipmitool/ipmi_firewall.h>
Packit d14fb6
#include <ipmitool/ipmi_strings.h>
Packit d14fb6
Packit d14fb6
static void
Packit d14fb6
printf_firewall_usage(void)
Packit d14fb6
{
Packit d14fb6
	lprintf(LOG_NOTICE,
Packit d14fb6
"Firmware Firewall Commands:");
Packit d14fb6
	lprintf(LOG_NOTICE,
Packit d14fb6
"\tinfo [channel H] [lun L]");
Packit d14fb6
	lprintf(LOG_NOTICE,
Packit d14fb6
"\tinfo [channel H] [lun L [netfn N [command C [subfn S]]]]");
Packit d14fb6
	lprintf(LOG_NOTICE,
Packit d14fb6
"\tenable [channel H] [lun L [netfn N [command C [subfn S]]]]");
Packit d14fb6
	lprintf(LOG_NOTICE,
Packit d14fb6
"\tdisable [channel H] [lun L [netfn N [command C [subfn S]]]] [force])");
Packit d14fb6
	lprintf(LOG_NOTICE,
Packit d14fb6
"\treset [channel H]");
Packit d14fb6
	lprintf(LOG_NOTICE,
Packit d14fb6
"\t\twhere H is a Channel, L is a LUN, N is a NetFn,");
Packit d14fb6
	lprintf(LOG_NOTICE,
Packit d14fb6
"\t\tC is a Command and S is a Sub-Function");
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
void
Packit d14fb6
printf_firewall_info_usage(void)
Packit d14fb6
{
Packit d14fb6
	lprintf(LOG_NOTICE,
Packit d14fb6
"info [channel H]");
Packit d14fb6
	lprintf(LOG_NOTICE,
Packit d14fb6
"\tList all of the firewall information for all LUNs, NetFns");
Packit d14fb6
	lprintf(LOG_NOTICE,
Packit d14fb6
"\tand Commands, This is a long list and is not very human readable.");
Packit d14fb6
	lprintf(LOG_NOTICE,
Packit d14fb6
"info [channel H] lun L");
Packit d14fb6
	lprintf(LOG_NOTICE,
Packit d14fb6
"\tThis also prints a long list that is not very human readable.");
Packit d14fb6
	lprintf(LOG_NOTICE,
Packit d14fb6
"info [channel H] lun L netfn N");
Packit d14fb6
	lprintf(LOG_NOTICE,
Packit d14fb6
"\tThis prints out information for a single LUN/NetFn pair.");
Packit d14fb6
	lprintf(LOG_NOTICE,
Packit d14fb6
"\tThat is not really very usable, but at least it is short.");
Packit d14fb6
	lprintf(LOG_NOTICE,
Packit d14fb6
"info [channel H] lun L netfn N command C");
Packit d14fb6
	lprintf(LOG_NOTICE,
Packit d14fb6
"\tThis is the one you want -- it prints out detailed human");
Packit d14fb6
	lprintf(LOG_NOTICE,
Packit d14fb6
"\treadable information.  It shows the support, configurable, and");
Packit d14fb6
	lprintf(LOG_NOTICE,
Packit d14fb6
"\tenabled bits for the Command C on LUN/NetFn pair L,N and the");
Packit d14fb6
	lprintf(LOG_NOTICE,
Packit d14fb6
"\tsame information about each of its Sub-functions.");
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
// print n bytes of bit field bf (if invert, print ~bf)
Packit d14fb6
static void print_bitfield(const unsigned char * bf, int n, int invert, int loglevel) {
Packit d14fb6
	int i = 0;
Packit d14fb6
	if (loglevel < 0) {
Packit d14fb6
		while (i
Packit d14fb6
			printf("%02x", (unsigned char) (invert?~bf[i]:bf[i]));
Packit d14fb6
			if (++i % 4 == 0)
Packit d14fb6
				printf(" ");
Packit d14fb6
		}
Packit d14fb6
		printf("\n");
Packit d14fb6
	} else {
Packit d14fb6
		while (i
Packit d14fb6
			lprintf(loglevel, "%02x", (unsigned char) (invert?~bf[i]:bf[i]));
Packit d14fb6
			if (++i % 4 == 0)
Packit d14fb6
				lprintf(loglevel, " ");
Packit d14fb6
		}
Packit d14fb6
		lprintf(loglevel, "\n");
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
static int
Packit d14fb6
ipmi_firewall_parse_args(int argc, char ** argv, struct ipmi_function_params * p)
Packit d14fb6
{
Packit d14fb6
	int i;
Packit d14fb6
	uint8_t conv_err = 0;
Packit d14fb6
Packit d14fb6
	if (!p) {
Packit d14fb6
		lprintf(LOG_ERR, "ipmi_firewall_parse_args: p is NULL");
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
	for (i=0; i
Packit d14fb6
		if (strncmp(argv[i], "channel", 7) == 0 && (++i < argc)) {
Packit d14fb6
			uint8_t channel_tmp = 0;
Packit d14fb6
			if (is_ipmi_channel_num(argv[i], &channel_tmp) != 0) {
Packit d14fb6
				conv_err = 1;
Packit d14fb6
				break;
Packit d14fb6
			} else {
Packit d14fb6
				p->channel = channel_tmp;
Packit d14fb6
			}
Packit d14fb6
		}
Packit d14fb6
		else if (strncmp(argv[i], "lun", 3) == 0 && (++i < argc)) {
Packit d14fb6
			if (str2int(argv[i], &(p->lun)) != 0) {
Packit d14fb6
				lprintf(LOG_ERR, "Given lun '%s' is invalid.", argv[i]);
Packit d14fb6
				conv_err = 1;
Packit d14fb6
				break;
Packit d14fb6
			}
Packit d14fb6
		}
Packit d14fb6
		else if (strncmp(argv[i], "force", 5) == 0) {
Packit d14fb6
			p->force = 1;
Packit d14fb6
		}
Packit d14fb6
		else if (strncmp(argv[i], "netfn", 5) == 0 && (++i < argc)) {
Packit d14fb6
			if (str2int(argv[i], &(p->netfn)) != 0) {
Packit d14fb6
				lprintf(LOG_ERR, "Given netfn '%s' is invalid.", argv[i]);
Packit d14fb6
				conv_err = 1;
Packit d14fb6
				break;
Packit d14fb6
			}
Packit d14fb6
		}
Packit d14fb6
		else if (strncmp(argv[i], "command", 7) == 0 && (++i < argc)) {
Packit d14fb6
			if (str2int(argv[i], &(p->command)) != 0) {
Packit d14fb6
				lprintf(LOG_ERR, "Given command '%s' is invalid.", argv[i]);
Packit d14fb6
				conv_err = 1;
Packit d14fb6
				break;
Packit d14fb6
			}
Packit d14fb6
		}
Packit d14fb6
		else if (strncmp(argv[i], "subfn", 5) == 0 && (++i < argc)) {
Packit d14fb6
			if (str2int(argv[i], &(p->subfn)) != 0) {
Packit d14fb6
				lprintf(LOG_ERR, "Given subfn '%s' is invalid.", argv[i]);
Packit d14fb6
				conv_err = 1;
Packit d14fb6
				break;
Packit d14fb6
			}
Packit d14fb6
		}
Packit d14fb6
	}
Packit d14fb6
	if (conv_err != 0) {
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
	if (p->subfn >= MAX_SUBFN) {
Packit d14fb6
		lprintf(LOG_ERR, "subfn is out of range (0-%d)", MAX_SUBFN-1);
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
	if (p->command >= MAX_COMMAND) {
Packit d14fb6
		lprintf(LOG_ERR, "command is out of range (0-%d)", MAX_COMMAND-1);
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
	if (p->netfn >= MAX_NETFN) {
Packit d14fb6
		lprintf(LOG_ERR, "netfn is out of range (0-%d)", MAX_NETFN-1);
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
	if (p->lun >= MAX_LUN) {
Packit d14fb6
		lprintf(LOG_ERR, "lun is out of range (0-%d)", MAX_LUN-1);
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
	if (p->netfn >= 0 && p->lun < 0) {
Packit d14fb6
		lprintf(LOG_ERR, "if netfn is set, so must be lun");
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
	if (p->command >= 0 && p->netfn < 0) {
Packit d14fb6
		lprintf(LOG_ERR, "if command is set, so must be netfn");
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
	if (p->subfn >= 0 && p->command < 0) {
Packit d14fb6
		lprintf(LOG_ERR, "if subfn is set, so must be command");
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
	return 0;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
/* _get_netfn_suport
Packit d14fb6
 *
Packit d14fb6
 * @intf:	ipmi interface
Packit d14fb6
 * @channel:	ipmi channel
Packit d14fb6
 * @lun:	a pointer to a 4 byte field
Packit d14fb6
 * @netfn:	a pointer to a 128-bit bitfield (16 bytes)
Packit d14fb6
 *
Packit d14fb6
 * returns 0 on success and fills in the bitfield for 
Packit d14fb6
 * the 32 netfn * 4 LUN pairs that support commands
Packit d14fb6
 * returns -1 on error
Packit d14fb6
 */
Packit d14fb6
static int
Packit d14fb6
_get_netfn_support(struct ipmi_intf * intf, int channel, unsigned char * lun, unsigned char * netfn)
Packit d14fb6
{
Packit d14fb6
	struct ipmi_rs * rsp;
Packit d14fb6
	struct ipmi_rq req;
Packit d14fb6
	unsigned char * d, rqdata;
Packit d14fb6
	unsigned int l;
Packit d14fb6
Packit d14fb6
	if (!lun || !netfn) {
Packit d14fb6
		lprintf(LOG_ERR, "_get_netfn_suport: lun or netfn is NULL");
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	memset(&req, 0, sizeof(req));
Packit d14fb6
	req.msg.netfn = IPMI_NETFN_APP;
Packit d14fb6
	req.msg.cmd = BMC_GET_NETFN_SUPPORT;
Packit d14fb6
	rqdata = (unsigned char) channel;
Packit d14fb6
	req.msg.data = &rqdata;
Packit d14fb6
	req.msg.data_len = 1;
Packit d14fb6
Packit d14fb6
	rsp = intf->sendrecv(intf, &req;;
Packit d14fb6
	if (rsp == NULL) {
Packit d14fb6
		lprintf(LOG_ERR, "Get NetFn Support command failed");
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
	if (rsp->ccode > 0) {
Packit d14fb6
		lprintf(LOG_ERR, "Get NetFn Support command failed: %s",
Packit d14fb6
			val2str(rsp->ccode, completion_code_vals));
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	d = rsp->data;
Packit d14fb6
	for (l=0; l<4; l++) {
Packit d14fb6
		lun[l] = (*d)>>(2*l) & 0x3;
Packit d14fb6
	}
Packit d14fb6
	d++;
Packit d14fb6
Packit d14fb6
	memcpy(netfn, d, 16);
Packit d14fb6
Packit d14fb6
	return 0;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
/* _get_command_suport
Packit d14fb6
 *
Packit d14fb6
 * @intf:	ipmi interface
Packit d14fb6
 * @p:		a pointer to a struct ipmi_function_params
Packit d14fb6
 * @lnfn:	a pointer to a struct lun_netfn_support
Packit d14fb6
 *
Packit d14fb6
 * returns 0 on success and fills in lnfn according to the request in p
Packit d14fb6
 * returns -1 on error
Packit d14fb6
 */
Packit d14fb6
static int
Packit d14fb6
_get_command_support(struct ipmi_intf * intf,
Packit d14fb6
	struct ipmi_function_params * p, struct lun_netfn_support * lnfn)
Packit d14fb6
{
Packit d14fb6
	struct ipmi_rs * rsp;
Packit d14fb6
	struct ipmi_rq req;
Packit d14fb6
	unsigned char * d, rqdata[3];
Packit d14fb6
	unsigned int c;
Packit d14fb6
Packit d14fb6
	if (!p || !lnfn) {
Packit d14fb6
		lprintf(LOG_ERR, "_get_netfn_suport: p or lnfn is NULL");
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	memset(&req, 0, sizeof(req));
Packit d14fb6
	req.msg.netfn = IPMI_NETFN_APP;
Packit d14fb6
	req.msg.cmd = BMC_GET_COMMAND_SUPPORT;
Packit d14fb6
	rqdata[0] = (unsigned char) p->channel;
Packit d14fb6
	rqdata[1] = p->netfn;
Packit d14fb6
	rqdata[2] = p->lun;
Packit d14fb6
	req.msg.data = rqdata;
Packit d14fb6
	req.msg.data_len = 3;
Packit d14fb6
Packit d14fb6
	rsp = intf->sendrecv(intf, &req;;
Packit d14fb6
	if (rsp == NULL) {
Packit d14fb6
		lprintf(LOG_ERR, "Get Command Support (LUN=%d, NetFn=%d, op=0) command failed", p->lun, p->netfn);
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
	if (rsp->ccode > 0) {
Packit d14fb6
		lprintf(LOG_ERR, "Get Command Support (LUN=%d, NetFn=%d, op=0) command failed: %s",
Packit d14fb6
			p->lun, p->netfn, val2str(rsp->ccode, completion_code_vals));
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	d = rsp->data;
Packit d14fb6
	for (c=0; c<128; c++) {
Packit d14fb6
		if (!(d[c>>3] & (1<<(c%8))))
Packit d14fb6
			lnfn->command[c].support |= BIT_AVAILABLE;
Packit d14fb6
	}
Packit d14fb6
	memcpy(lnfn->command_mask, d, MAX_COMMAND_BYTES/2);
Packit d14fb6
Packit d14fb6
	memset(&req, 0, sizeof(req));
Packit d14fb6
	req.msg.netfn = IPMI_NETFN_APP;
Packit d14fb6
	req.msg.cmd = BMC_GET_COMMAND_SUPPORT;
Packit d14fb6
	rqdata[0] = (unsigned char) p->channel;
Packit d14fb6
	rqdata[1] = 0x40 | p->netfn;
Packit d14fb6
	rqdata[2] = p->lun;
Packit d14fb6
	req.msg.data = rqdata;
Packit d14fb6
	req.msg.data_len = 3;
Packit d14fb6
Packit d14fb6
	rsp = intf->sendrecv(intf, &req;;
Packit d14fb6
	if (rsp == NULL) {
Packit d14fb6
		lprintf(LOG_ERR, "Get Command Support (LUN=%d, NetFn=%d, op=1) command failed", p->lun, p->netfn);
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
	if (rsp->ccode > 0) {
Packit d14fb6
		lprintf(LOG_ERR, "Get Command Support (LUN=%d, NetFn=%d, op=1) command failed: %s",
Packit d14fb6
			p->lun, p->netfn, val2str(rsp->ccode, completion_code_vals));
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	d = rsp->data;
Packit d14fb6
	for (c=0; c<128; c++) {
Packit d14fb6
		if (!(d[c>>3] & (1<<(c%8))))
Packit d14fb6
			lnfn->command[128+c].support |= BIT_AVAILABLE;
Packit d14fb6
	}
Packit d14fb6
	memcpy(lnfn->command_mask+MAX_COMMAND_BYTES/2, d, MAX_COMMAND_BYTES/2);
Packit d14fb6
	return 0;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
/* _get_command_configurable
Packit d14fb6
 *
Packit d14fb6
 * @intf:	ipmi interface
Packit d14fb6
 * @p:		a pointer to a struct ipmi_function_params
Packit d14fb6
 * @lnfn:	a pointer to a struct lun_netfn_support
Packit d14fb6
 *
Packit d14fb6
 * returns 0 on success and fills in lnfn according to the request in p
Packit d14fb6
 * returns -1 on error
Packit d14fb6
 */
Packit d14fb6
static int
Packit d14fb6
_get_command_configurable(struct ipmi_intf * intf,
Packit d14fb6
	struct ipmi_function_params * p, struct lun_netfn_support * lnfn)
Packit d14fb6
{
Packit d14fb6
	struct ipmi_rs * rsp;
Packit d14fb6
	struct ipmi_rq req;
Packit d14fb6
	unsigned char * d, rqdata[3];
Packit d14fb6
	unsigned int c;
Packit d14fb6
Packit d14fb6
	if (!p || !lnfn) {
Packit d14fb6
		lprintf(LOG_ERR, "_get_command_configurable: p or lnfn is NULL");
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	memset(&req, 0, sizeof(req));
Packit d14fb6
	req.msg.netfn = IPMI_NETFN_APP;
Packit d14fb6
	req.msg.cmd = BMC_GET_CONFIGURABLE_COMMANDS;
Packit d14fb6
	rqdata[0] = (unsigned char) p->channel;
Packit d14fb6
	rqdata[1] = p->netfn;
Packit d14fb6
	rqdata[2] = p->lun;
Packit d14fb6
	req.msg.data = rqdata;
Packit d14fb6
	req.msg.data_len = 3;
Packit d14fb6
Packit d14fb6
	rsp = intf->sendrecv(intf, &req;;
Packit d14fb6
	if (rsp == NULL) {
Packit d14fb6
		lprintf(LOG_ERR, "Get Configurable Command (LUN=%d, NetFn=%d, op=0) command failed", p->lun, p->netfn);
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
	if (rsp->ccode > 0) {
Packit d14fb6
		lprintf(LOG_ERR, "Get Configurable Command (LUN=%d, NetFn=%d, op=0) command failed: %s",
Packit d14fb6
			p->lun, p->netfn, val2str(rsp->ccode, completion_code_vals));
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	d = rsp->data;
Packit d14fb6
	for (c=0; c<128; c++) {
Packit d14fb6
		if (d[c>>3] & (1<<(c%8)))
Packit d14fb6
			lnfn->command[c].support |= BIT_CONFIGURABLE;
Packit d14fb6
	}
Packit d14fb6
	memcpy(lnfn->config_mask, d, MAX_COMMAND_BYTES/2);
Packit d14fb6
Packit d14fb6
	memset(&req, 0, sizeof(req));
Packit d14fb6
	req.msg.netfn = IPMI_NETFN_APP;
Packit d14fb6
	req.msg.cmd = BMC_GET_CONFIGURABLE_COMMANDS;
Packit d14fb6
	rqdata[0] = (unsigned char) p->channel;
Packit d14fb6
	rqdata[1] = 0x40 | p->netfn;
Packit d14fb6
	rqdata[2] = p->lun;
Packit d14fb6
	req.msg.data = rqdata;
Packit d14fb6
	req.msg.data_len = 3;
Packit d14fb6
Packit d14fb6
	rsp = intf->sendrecv(intf, &req;;
Packit d14fb6
	if (rsp == NULL) {
Packit d14fb6
		lprintf(LOG_ERR, "Get Configurable Command (LUN=%d, NetFn=%d, op=1) command failed", p->lun, p->netfn);
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
	if (rsp->ccode > 0) {
Packit d14fb6
		lprintf(LOG_ERR, "Get Configurable Command (LUN=%d, NetFn=%d, op=1) command failed: %s",
Packit d14fb6
			p->lun, p->netfn, val2str(rsp->ccode, completion_code_vals));
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	d = rsp->data;
Packit d14fb6
	for (c=0; c<128; c++) {
Packit d14fb6
		if (d[c>>3] & (1<<(c%8)))
Packit d14fb6
			lnfn->command[128+c].support |= BIT_CONFIGURABLE;
Packit d14fb6
	}
Packit d14fb6
	memcpy(lnfn->config_mask+MAX_COMMAND_BYTES/2, d, MAX_COMMAND_BYTES/2);
Packit d14fb6
	return 0;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
/* _get_command_enables
Packit d14fb6
 *
Packit d14fb6
 * @intf:	ipmi interface
Packit d14fb6
 * @p:		a pointer to a struct ipmi_function_params
Packit d14fb6
 * @lnfn:	a pointer to a struct lun_netfn_support
Packit d14fb6
 *
Packit d14fb6
 * returns 0 on success and fills in lnfn according to the request in p
Packit d14fb6
 * returns -1 on error
Packit d14fb6
 */
Packit d14fb6
static int
Packit d14fb6
_get_command_enables(struct ipmi_intf * intf,
Packit d14fb6
	struct ipmi_function_params * p, struct lun_netfn_support * lnfn)
Packit d14fb6
{
Packit d14fb6
	struct ipmi_rs * rsp;
Packit d14fb6
	struct ipmi_rq req;
Packit d14fb6
	unsigned char * d, rqdata[3];
Packit d14fb6
	unsigned int c;
Packit d14fb6
Packit d14fb6
	if (!p || !lnfn) {
Packit d14fb6
		lprintf(LOG_ERR, "_get_command_enables: p or lnfn is NULL");
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	memset(&req, 0, sizeof(req));
Packit d14fb6
	req.msg.netfn = IPMI_NETFN_APP;
Packit d14fb6
	req.msg.cmd = BMC_GET_COMMAND_ENABLES;
Packit d14fb6
	rqdata[0] = (unsigned char) p->channel;
Packit d14fb6
	rqdata[1] = p->netfn;
Packit d14fb6
	rqdata[2] = p->lun;
Packit d14fb6
	req.msg.data = rqdata;
Packit d14fb6
	req.msg.data_len = 3;
Packit d14fb6
Packit d14fb6
	rsp = intf->sendrecv(intf, &req;;
Packit d14fb6
	if (rsp == NULL) {
Packit d14fb6
		lprintf(LOG_ERR, "Get Command Enables (LUN=%d, NetFn=%d, op=0) command failed", p->lun, p->netfn);
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
	if (rsp->ccode > 0) {
Packit d14fb6
		lprintf(LOG_ERR, "Get Command Enables (LUN=%d, NetFn=%d, op=0) command failed: %s",
Packit d14fb6
			p->lun, p->netfn, val2str(rsp->ccode, completion_code_vals));
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	d = rsp->data;
Packit d14fb6
	for (c=0; c<128; c++) {
Packit d14fb6
		if (d[c>>3] & (1<<(c%8)))
Packit d14fb6
			lnfn->command[c].support |= BIT_ENABLED;
Packit d14fb6
	}
Packit d14fb6
	memcpy(lnfn->enable_mask, d, MAX_COMMAND_BYTES/2);
Packit d14fb6
Packit d14fb6
	memset(&req, 0, sizeof(req));
Packit d14fb6
	req.msg.netfn = IPMI_NETFN_APP;
Packit d14fb6
	req.msg.cmd = BMC_GET_COMMAND_ENABLES;
Packit d14fb6
	rqdata[0] = (unsigned char) p->channel;
Packit d14fb6
	rqdata[1] = 0x40 | p->netfn;
Packit d14fb6
	rqdata[2] = p->lun;
Packit d14fb6
	req.msg.data = rqdata;
Packit d14fb6
	req.msg.data_len = 3;
Packit d14fb6
Packit d14fb6
	rsp = intf->sendrecv(intf, &req;;
Packit d14fb6
	if (rsp == NULL) {
Packit d14fb6
		lprintf(LOG_ERR, "Get Command Enables (LUN=%d, NetFn=%d, op=1) command failed", p->lun, p->netfn);
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
	if (rsp->ccode > 0) {
Packit d14fb6
		lprintf(LOG_ERR, "Get Command Enables (LUN=%d, NetFn=%d, op=1) command failed: %s",
Packit d14fb6
			p->lun, p->netfn, val2str(rsp->ccode, completion_code_vals));
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	d = rsp->data;
Packit d14fb6
	for (c=0; c<128; c++) {
Packit d14fb6
		if (d[c>>3] & (1<<(c%8)))
Packit d14fb6
			lnfn->command[128+c].support |= BIT_ENABLED;
Packit d14fb6
	}
Packit d14fb6
	memcpy(lnfn->enable_mask+MAX_COMMAND_BYTES/2, d, MAX_COMMAND_BYTES/2);
Packit d14fb6
	return 0;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
/* _set_command_enables
Packit d14fb6
 *
Packit d14fb6
 * @intf:	ipmi interface
Packit d14fb6
 * @p:		a pointer to a struct ipmi_function_params
Packit d14fb6
 * @lnfn:	a pointer to a struct lun_netfn_support that contains current info
Packit d14fb6
 * @enable:	a pointer to a 32 byte bitfield that contains the desired enable state
Packit d14fb6
 * @gun:	here is a gun to shoot yourself in the foot.  If this is true
Packit d14fb6
 * 		you are allowed to disable this command
Packit d14fb6
 *
Packit d14fb6
 * returns 0 on success
Packit d14fb6
 * returns -1 on error
Packit d14fb6
 */
Packit d14fb6
static int
Packit d14fb6
_set_command_enables(struct ipmi_intf * intf,
Packit d14fb6
	struct ipmi_function_params * p, struct lun_netfn_support * lnfn,
Packit d14fb6
	unsigned char * enable, int gun)
Packit d14fb6
{
Packit d14fb6
	struct ipmi_rs * rsp;
Packit d14fb6
	struct ipmi_rq req;
Packit d14fb6
	unsigned char rqdata[19];
Packit d14fb6
	unsigned int c;
Packit d14fb6
Packit d14fb6
	if (!p || !lnfn) {
Packit d14fb6
		lprintf(LOG_ERR, "_set_command_enables: p or lnfn is NULL");
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	lprintf(LOG_INFO, "support:            ");
Packit d14fb6
	print_bitfield(lnfn->command_mask, MAX_COMMAND_BYTES, 1, LOG_INFO);
Packit d14fb6
	lprintf(LOG_INFO, "configurable:       ");
Packit d14fb6
	print_bitfield(lnfn->config_mask, MAX_COMMAND_BYTES, 0, LOG_INFO);
Packit d14fb6
	lprintf(LOG_INFO, "enabled:            ");
Packit d14fb6
	print_bitfield(lnfn->enable_mask, MAX_COMMAND_BYTES, 0, LOG_INFO);
Packit d14fb6
	lprintf(LOG_INFO, "enable mask before: ");
Packit d14fb6
	print_bitfield(enable, MAX_COMMAND_BYTES, 0, LOG_INFO);
Packit d14fb6
Packit d14fb6
	// mask off the appropriate bits (if not configurable, set enable bit
Packit d14fb6
	// must be the same as the current enable bit)
Packit d14fb6
	for (c=0; c<(MAX_COMMAND_BYTES); c++) {
Packit d14fb6
		enable[c] = (lnfn->config_mask[c] & enable[c]) |
Packit d14fb6
			(~lnfn->config_mask[c] & lnfn->enable_mask[c]);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	// take the gun out of their hand if they are not supposed to have it
Packit d14fb6
	if (!gun) {
Packit d14fb6
		enable[SET_COMMAND_ENABLE_BYTE] = 
Packit d14fb6
			(lnfn->config_mask[SET_COMMAND_ENABLE_BYTE]
Packit d14fb6
			 & SET_COMMAND_ENABLE_BIT) |
Packit d14fb6
			(~lnfn->config_mask[SET_COMMAND_ENABLE_BYTE]
Packit d14fb6
			 & lnfn->enable_mask[SET_COMMAND_ENABLE_BYTE]);
Packit d14fb6
	}
Packit d14fb6
	lprintf(LOG_INFO, "enable mask after: ");
Packit d14fb6
	print_bitfield(enable, MAX_COMMAND_BYTES, 0, LOG_INFO);
Packit d14fb6
Packit d14fb6
	memset(&req, 0, sizeof(req));
Packit d14fb6
	req.msg.netfn = IPMI_NETFN_APP;
Packit d14fb6
	req.msg.cmd = BMC_SET_COMMAND_ENABLES;
Packit d14fb6
	rqdata[0] = (unsigned char) p->channel;
Packit d14fb6
	rqdata[1] = p->netfn;
Packit d14fb6
	rqdata[2] = p->lun;
Packit d14fb6
	memcpy(&rqdata[3], enable, MAX_COMMAND_BYTES/2);
Packit d14fb6
	req.msg.data = rqdata;
Packit d14fb6
	req.msg.data_len = 19;
Packit d14fb6
Packit d14fb6
	rsp = intf->sendrecv(intf, &req;;
Packit d14fb6
	if (rsp == NULL) {
Packit d14fb6
		lprintf(LOG_ERR, "Set Command Enables (LUN=%d, NetFn=%d, op=0) command failed", p->lun, p->netfn);
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
	if (rsp->ccode > 0) {
Packit d14fb6
		lprintf(LOG_ERR, "Set Command Enables (LUN=%d, NetFn=%d, op=0) command failed: %s",
Packit d14fb6
			p->lun, p->netfn, val2str(rsp->ccode, completion_code_vals));
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	memset(&req, 0, sizeof(req));
Packit d14fb6
	req.msg.netfn = IPMI_NETFN_APP;
Packit d14fb6
	req.msg.cmd = BMC_SET_COMMAND_ENABLES;
Packit d14fb6
	rqdata[0] = (unsigned char) p->channel;
Packit d14fb6
	rqdata[1] = 0x40 | p->netfn;
Packit d14fb6
	rqdata[2] = p->lun;
Packit d14fb6
	memcpy(&rqdata[3], enable+MAX_COMMAND_BYTES/2, MAX_COMMAND_BYTES/2);
Packit d14fb6
	req.msg.data = rqdata;
Packit d14fb6
	req.msg.data_len = 19;
Packit d14fb6
Packit d14fb6
	rsp = intf->sendrecv(intf, &req;;
Packit d14fb6
	if (rsp == NULL) {
Packit d14fb6
		lprintf(LOG_ERR, "Set Command Enables (LUN=%d, NetFn=%d, op=1) command failed", p->lun, p->netfn);
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
	if (rsp->ccode > 0) {
Packit d14fb6
		lprintf(LOG_ERR, "Set Command Enables (LUN=%d, NetFn=%d, op=1) command failed: %s",
Packit d14fb6
			p->lun, p->netfn, val2str(rsp->ccode, completion_code_vals));
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	return 0;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
/* _get_subfn_support
Packit d14fb6
 *
Packit d14fb6
 * @intf:	ipmi interface
Packit d14fb6
 * @p:		a pointer to a struct ipmi_function_params
Packit d14fb6
 * @cmd:	a pointer to a struct command_support
Packit d14fb6
 *
Packit d14fb6
 * returns 0 on success and fills in cmd according to the request in p
Packit d14fb6
 * returns -1 on error
Packit d14fb6
 */
Packit d14fb6
static int
Packit d14fb6
_get_subfn_support(struct ipmi_intf * intf,
Packit d14fb6
	struct ipmi_function_params * p, struct command_support * cmd)
Packit d14fb6
{
Packit d14fb6
	struct ipmi_rs * rsp;
Packit d14fb6
	struct ipmi_rq req;
Packit d14fb6
	unsigned char rqdata[4];
Packit d14fb6
Packit d14fb6
	if (!p || !cmd) {
Packit d14fb6
		lprintf(LOG_ERR, "_get_subfn_support: p or cmd is NULL");
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	memset(&req, 0, sizeof(req));
Packit d14fb6
	req.msg.netfn = IPMI_NETFN_APP;
Packit d14fb6
	req.msg.cmd = BMC_GET_COMMAND_SUBFUNCTION_SUPPORT;
Packit d14fb6
	rqdata[0] = (unsigned char) p->channel;
Packit d14fb6
	rqdata[1] = p->netfn;
Packit d14fb6
	rqdata[2] = p->lun;
Packit d14fb6
	rqdata[3] = p->command;
Packit d14fb6
	req.msg.data = rqdata;
Packit d14fb6
	req.msg.data_len = 4;
Packit d14fb6
Packit d14fb6
	rsp = intf->sendrecv(intf, &req;;
Packit d14fb6
	if (rsp == NULL) {
Packit d14fb6
		lprintf(LOG_ERR, "Get Command Sub-function Support (LUN=%d, NetFn=%d, command=%d) command failed", p->lun, p->netfn, p->command);
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
	if (rsp->ccode > 0) {
Packit d14fb6
		lprintf(LOG_ERR, "Get Command Sub-function Support (LUN=%d, NetFn=%d, command=%d) command failed: %s",
Packit d14fb6
			p->lun, p->netfn, p->command, val2str(rsp->ccode, completion_code_vals));
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	memcpy(cmd->subfn_support, rsp->data, sizeof(cmd->subfn_support));
Packit d14fb6
	return 0;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
/* _get_subfn_configurable
Packit d14fb6
 *
Packit d14fb6
 * @intf:	ipmi interface
Packit d14fb6
 * @p:		a pointer to a struct ipmi_function_params
Packit d14fb6
 * @cmd:	a pointer to a struct command_support
Packit d14fb6
 *
Packit d14fb6
 * returns 0 on success and fills in cmd according to the request in p
Packit d14fb6
 * returns -1 on error
Packit d14fb6
 */
Packit d14fb6
static int
Packit d14fb6
_get_subfn_configurable(struct ipmi_intf * intf,
Packit d14fb6
	struct ipmi_function_params * p, struct command_support * cmd)
Packit d14fb6
{
Packit d14fb6
	struct ipmi_rs * rsp;
Packit d14fb6
	struct ipmi_rq req;
Packit d14fb6
	unsigned char rqdata[4];
Packit d14fb6
Packit d14fb6
	if (!p || !cmd) {
Packit d14fb6
		lprintf(LOG_ERR, "_get_subfn_configurable: p or cmd is NULL");
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	memset(&req, 0, sizeof(req));
Packit d14fb6
	req.msg.netfn = IPMI_NETFN_APP;
Packit d14fb6
	req.msg.cmd = BMC_GET_CONFIGURABLE_COMMAND_SUBFUNCTIONS;
Packit d14fb6
	rqdata[0] = (unsigned char) p->channel;
Packit d14fb6
	rqdata[1] = p->netfn;
Packit d14fb6
	rqdata[2] = p->lun;
Packit d14fb6
	rqdata[3] = p->command;
Packit d14fb6
	req.msg.data = rqdata;
Packit d14fb6
	req.msg.data_len = 4;
Packit d14fb6
Packit d14fb6
	rsp = intf->sendrecv(intf, &req;;
Packit d14fb6
	if (rsp == NULL) {
Packit d14fb6
		lprintf(LOG_ERR, "Get Configurable Command Sub-function (LUN=%d, NetFn=%d, command=%d) command failed", p->lun, p->netfn, p->command);
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
	if (rsp->ccode > 0) {
Packit d14fb6
		lprintf(LOG_ERR, "Get Configurable Command Sub-function (LUN=%d, NetFn=%d, command=%d) command failed: %s",
Packit d14fb6
			p->lun, p->netfn, p->command, val2str(rsp->ccode, completion_code_vals));
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	memcpy(cmd->subfn_config, rsp->data, sizeof(cmd->subfn_config));
Packit d14fb6
	return 0;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
/* _get_subfn_enables
Packit d14fb6
 *
Packit d14fb6
 * @intf:	ipmi interface
Packit d14fb6
 * @p:		a pointer to a struct ipmi_function_params
Packit d14fb6
 * @cmd:	a pointer to a struct command_support
Packit d14fb6
 *
Packit d14fb6
 * returns 0 on success and fills in cmd according to the request in p
Packit d14fb6
 * returns -1 on error
Packit d14fb6
 */
Packit d14fb6
static int
Packit d14fb6
_get_subfn_enables(struct ipmi_intf * intf,
Packit d14fb6
	struct ipmi_function_params * p, struct command_support * cmd)
Packit d14fb6
{
Packit d14fb6
	struct ipmi_rs * rsp;
Packit d14fb6
	struct ipmi_rq req;
Packit d14fb6
	unsigned char rqdata[4];
Packit d14fb6
Packit d14fb6
	if (!p || !cmd) {
Packit d14fb6
		lprintf(LOG_ERR, "_get_subfn_enables: p or cmd is NULL");
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	memset(&req, 0, sizeof(req));
Packit d14fb6
	req.msg.netfn = IPMI_NETFN_APP;
Packit d14fb6
	req.msg.cmd = BMC_GET_COMMAND_SUBFUNCTION_ENABLES;
Packit d14fb6
	rqdata[0] = (unsigned char) p->channel;
Packit d14fb6
	rqdata[1] = p->netfn;
Packit d14fb6
	rqdata[2] = p->lun;
Packit d14fb6
	rqdata[3] = p->command;
Packit d14fb6
	req.msg.data = rqdata;
Packit d14fb6
	req.msg.data_len = 4;
Packit d14fb6
Packit d14fb6
	rsp = intf->sendrecv(intf, &req;;
Packit d14fb6
	if (rsp == NULL) {
Packit d14fb6
		lprintf(LOG_ERR, "Get Command Sub-function Enables (LUN=%d, NetFn=%d, command=%d) command failed", p->lun, p->netfn, p->command);
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
	if (rsp->ccode > 0) {
Packit d14fb6
		lprintf(LOG_ERR, "Get Command Sub-function Enables (LUN=%d, NetFn=%d, command=%d) command failed: %s",
Packit d14fb6
			p->lun, p->netfn, p->command, val2str(rsp->ccode, completion_code_vals));
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	memcpy(cmd->subfn_enable, rsp->data, sizeof(cmd->subfn_enable));
Packit d14fb6
	return 0;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
/* _set_subfn_enables
Packit d14fb6
 *
Packit d14fb6
 * @intf:	ipmi interface
Packit d14fb6
 * @p:  	a pointer to a struct ipmi_function_params
Packit d14fb6
 * @cmd:	a pointer to a struct command_support
Packit d14fb6
 * @enable:	a pointer to a 4 byte bitfield that contains the desired enable state
Packit d14fb6
 *
Packit d14fb6
 * returns 0 on success (and modifies enable to be the bits it actually set)
Packit d14fb6
 * returns -1 on error
Packit d14fb6
 */
Packit d14fb6
static int
Packit d14fb6
_set_subfn_enables(struct ipmi_intf * intf,
Packit d14fb6
	struct ipmi_function_params * p, struct command_support * cmd,
Packit d14fb6
	unsigned char * enable)
Packit d14fb6
{
Packit d14fb6
	struct ipmi_rs * rsp;
Packit d14fb6
	struct ipmi_rq req;
Packit d14fb6
	unsigned char rqdata[8];
Packit d14fb6
	unsigned int c;
Packit d14fb6
Packit d14fb6
	if (!p || !cmd) {
Packit d14fb6
		lprintf(LOG_ERR, "_set_subfn_enables: p or cmd is NULL");
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	lprintf(LOG_INFO, "support:            ");
Packit d14fb6
	print_bitfield(cmd->subfn_support, MAX_SUBFN_BYTES, 1, LOG_INFO);
Packit d14fb6
	lprintf(LOG_INFO, "configurable:       ");
Packit d14fb6
	print_bitfield(cmd->subfn_config, MAX_SUBFN_BYTES, 0, LOG_INFO);
Packit d14fb6
	lprintf(LOG_INFO, "enabled:            ");
Packit d14fb6
	print_bitfield(cmd->subfn_enable, MAX_SUBFN_BYTES, 0, LOG_INFO);
Packit d14fb6
	lprintf(LOG_INFO, "enable mask before: ");
Packit d14fb6
	print_bitfield(enable, MAX_SUBFN_BYTES, 0, LOG_INFO);
Packit d14fb6
	// mask off the appropriate bits (if not configurable, set enable bit
Packit d14fb6
	// must be the same as the current enable bit)
Packit d14fb6
	for (c=0; c<sizeof(cmd->subfn_enable); c++) {
Packit d14fb6
		enable[c] = (cmd->subfn_config[c] & enable[c]) |
Packit d14fb6
			(~cmd->subfn_config[c] & cmd->subfn_enable[c]);
Packit d14fb6
	}
Packit d14fb6
	lprintf(LOG_INFO, "enable mask after: ");
Packit d14fb6
	print_bitfield(enable, MAX_SUBFN_BYTES, 0, LOG_INFO);
Packit d14fb6
Packit d14fb6
	memset(&req, 0, sizeof(req));
Packit d14fb6
	req.msg.netfn = IPMI_NETFN_APP;
Packit d14fb6
	req.msg.cmd = BMC_SET_COMMAND_SUBFUNCTION_ENABLES;
Packit d14fb6
	rqdata[0] = (unsigned char) p->channel;
Packit d14fb6
	rqdata[1] = p->netfn;
Packit d14fb6
	rqdata[2] = p->lun;
Packit d14fb6
	rqdata[3] = p->command;
Packit d14fb6
	memcpy(&rqdata[4], enable, MAX_SUBFN_BYTES);
Packit d14fb6
	req.msg.data = rqdata;
Packit d14fb6
	req.msg.data_len = 8;
Packit d14fb6
Packit d14fb6
	rsp = intf->sendrecv(intf, &req;;
Packit d14fb6
	if (rsp == NULL) {
Packit d14fb6
		lprintf(LOG_ERR, "Set Command Sub-function Enables (LUN=%d, NetFn=%d, command=%d) command failed", p->lun, p->netfn, p->command);
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
	if (rsp->ccode > 0) {
Packit d14fb6
		lprintf(LOG_ERR, "Set Command Sub-function Enables (LUN=%d, NetFn=%d, command=%d) command failed: %s",
Packit d14fb6
			p->lun, p->netfn, p->command, val2str(rsp->ccode, completion_code_vals));
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	return 0;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
/* _gather_info
Packit d14fb6
 *
Packit d14fb6
 * @intf:	ipmi interface
Packit d14fb6
 * @p:		a pointer to a struct ipmi_function_params
Packit d14fb6
 * @bmc:	a pointer to a struct bmc_fn_support
Packit d14fb6
 * @enable:	a pointer to a 4 byte bitfield that contains the desired enable state
Packit d14fb6
 *
Packit d14fb6
 * returns 0 on success and fills in bmc according to request p
Packit d14fb6
 * returns -1 on error
Packit d14fb6
 */
Packit d14fb6
static int _gather_info(struct ipmi_intf * intf, struct ipmi_function_params * p, struct bmc_fn_support * bmc)
Packit d14fb6
{
Packit d14fb6
	int ret, l, n;
Packit d14fb6
	unsigned char lun[MAX_LUN], netfn[16];
Packit d14fb6
Packit d14fb6
	ret = _get_netfn_support(intf, p->channel, lun, netfn);
Packit d14fb6
	if (!ret) {
Packit d14fb6
		for (l=0; l
Packit d14fb6
			if (p->lun >= 0 && p->lun != l)
Packit d14fb6
				continue;
Packit d14fb6
			bmc->lun[l].support = lun[l];
Packit d14fb6
			if (lun[l]) {
Packit d14fb6
				for (n=0; n
Packit d14fb6
					int offset = l*MAX_NETFN_PAIR+n;
Packit d14fb6
					bmc->lun[l].netfn[n].support = 
Packit d14fb6
						!!(netfn[offset>>3] & (1<<(offset%8)));
Packit d14fb6
				}
Packit d14fb6
			}
Packit d14fb6
		}
Packit d14fb6
	}
Packit d14fb6
	if (p->netfn >= 0) {
Packit d14fb6
		if (!((p->lun < 0 || bmc->lun[p->lun].support) &&
Packit d14fb6
		      (p->netfn < 0 || bmc->lun[p->lun].netfn[p->netfn>>1].support))) {
Packit d14fb6
			lprintf(LOG_ERR, "LUN or LUN/NetFn pair %d,%d not supported", p->lun, p->netfn);
Packit d14fb6
			return 0;
Packit d14fb6
		}
Packit d14fb6
		ret = _get_command_support(intf, p, &(bmc->lun[p->lun].netfn[p->netfn>>1]));
Packit d14fb6
		ret |= _get_command_configurable(intf, p, &(bmc->lun[p->lun].netfn[p->netfn>>1]));
Packit d14fb6
		ret |= _get_command_enables(intf, p, &(bmc->lun[p->lun].netfn[p->netfn>>1]));
Packit d14fb6
		if (!ret && p->command >= 0) {
Packit d14fb6
			ret = _get_subfn_support(intf, p,
Packit d14fb6
						 &(bmc->lun[p->lun].netfn[p->netfn>>1].command[p->command]));
Packit d14fb6
			ret |= _get_subfn_configurable(intf, p,
Packit d14fb6
						       &(bmc->lun[p->lun].netfn[p->netfn>>1].command[p->command]));
Packit d14fb6
			ret |= _get_subfn_enables(intf, p,
Packit d14fb6
						  &(bmc->lun[p->lun].netfn[p->netfn>>1].command[p->command]));
Packit d14fb6
		}
Packit d14fb6
	}
Packit d14fb6
	else if (p->lun >= 0) {
Packit d14fb6
		l = p->lun;
Packit d14fb6
		if (bmc->lun[l].support) {
Packit d14fb6
			for (n=0; n
Packit d14fb6
				p->netfn = n*2;
Packit d14fb6
				if (bmc->lun[l].netfn[n].support) {
Packit d14fb6
					ret = _get_command_support(intf, p, &(bmc->lun[l].netfn[n]));
Packit d14fb6
					ret |= _get_command_configurable(intf, p, &(bmc->lun[l].netfn[n]));
Packit d14fb6
					ret |= _get_command_enables(intf, p, &(bmc->lun[l].netfn[n]));
Packit d14fb6
				}
Packit d14fb6
				if (ret)
Packit d14fb6
					bmc->lun[l].netfn[n].support = 0;
Packit d14fb6
			}
Packit d14fb6
		}
Packit d14fb6
		p->netfn = -1;
Packit d14fb6
	} else {
Packit d14fb6
		for (l=0; l<4; l++) {
Packit d14fb6
			p->lun = l;
Packit d14fb6
			if (bmc->lun[l].support) {
Packit d14fb6
				for (n=0; n
Packit d14fb6
					p->netfn = n*2;
Packit d14fb6
					if (bmc->lun[l].netfn[n].support) {
Packit d14fb6
						ret = _get_command_support(intf, p, &(bmc->lun[l].netfn[n]));
Packit d14fb6
						ret |= _get_command_configurable(intf, p, &(bmc->lun[l].netfn[n]));
Packit d14fb6
						ret |= _get_command_enables(intf, p, &(bmc->lun[l].netfn[n]));
Packit d14fb6
					}
Packit d14fb6
					if (ret)
Packit d14fb6
						bmc->lun[l].netfn[n].support = 0;
Packit d14fb6
				}
Packit d14fb6
			}
Packit d14fb6
		}
Packit d14fb6
		p->lun = -1;
Packit d14fb6
		p->netfn = -1;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	return 0;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
/* ipmi_firewall_info - print out info for firewall functions
Packit d14fb6
 *
Packit d14fb6
 * @intf:	ipmi inteface
Packit d14fb6
 * @argc:	argument count
Packit d14fb6
 * @argv:	argument list
Packit d14fb6
 *
Packit d14fb6
 * returns 0 on success
Packit d14fb6
 * returns -1 on error
Packit d14fb6
 */
Packit d14fb6
static int
Packit d14fb6
ipmi_firewall_info(struct ipmi_intf * intf, int argc, char ** argv)
Packit d14fb6
{
Packit d14fb6
	int ret = 0;
Packit d14fb6
	struct ipmi_function_params p = {0xe, -1, -1, -1, -1, 0};
Packit d14fb6
	struct bmc_fn_support * bmc_fn_support;
Packit d14fb6
	unsigned int l, n, c;
Packit d14fb6
Packit d14fb6
	if ((argc > 0 && strncmp(argv[0], "help", 4) == 0) || ipmi_firewall_parse_args(argc, argv, &p) < 0)
Packit d14fb6
	{
Packit d14fb6
		printf_firewall_info_usage();
Packit d14fb6
		return 0;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	bmc_fn_support = malloc(sizeof(struct bmc_fn_support));
Packit d14fb6
	if (!bmc_fn_support) {
Packit d14fb6
		lprintf(LOG_ERR, "malloc struct bmc_fn_support failed");
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	ret = _gather_info(intf, &p, bmc_fn_support);
Packit d14fb6
Packit d14fb6
	if (p.command >= 0) {
Packit d14fb6
      struct command_support * cmd;
Packit d14fb6
		if (!((p.lun < 0 || bmc_fn_support->lun[p.lun].support) &&
Packit d14fb6
			(p.netfn < 0 || bmc_fn_support->lun[p.lun].netfn[p.netfn>>1].support) &&
Packit d14fb6
			bmc_fn_support->lun[p.lun].netfn[p.netfn>>1].command[p.command].support))
Packit d14fb6
		{
Packit d14fb6
			lprintf(LOG_ERR, "Command 0x%02x not supported on LUN/NetFn pair %02x,%02x",
Packit d14fb6
				p.command, p.lun, p.netfn);
Packit d14fb6
			free(bmc_fn_support);
Packit d14fb6
			bmc_fn_support = NULL;
Packit d14fb6
			return 0;
Packit d14fb6
		}
Packit d14fb6
		cmd =
Packit d14fb6
			&bmc_fn_support->lun[p.lun].netfn[p.netfn>>1].command[p.command];
Packit d14fb6
		c = cmd->support;
Packit d14fb6
		printf("(A)vailable, (C)onfigurable, (E)nabled: | A | C | E |\n");
Packit d14fb6
		printf("-----------------------------------------------------\n");
Packit d14fb6
		printf("LUN %01d, NetFn 0x%02x, Command 0x%02x:        | %c | %c | %c |\n",
Packit d14fb6
			p.lun, p.netfn, p.command,
Packit d14fb6
			(c & BIT_AVAILABLE) ? 'X' : ' ',
Packit d14fb6
			(c & BIT_CONFIGURABLE) ? 'X' : ' ',
Packit d14fb6
			(c & BIT_ENABLED) ? 'X': ' ');
Packit d14fb6
Packit d14fb6
		for (n=0; n
Packit d14fb6
			printf("sub-function 0x%02x:                      | %c | %c | %c |\n", n,
Packit d14fb6
				(!bit_test(cmd->subfn_support, n)) ? 'X' : ' ',
Packit d14fb6
				(bit_test(cmd->subfn_config, n)) ? 'X' : ' ',
Packit d14fb6
				(bit_test(cmd->subfn_enable, n)) ? 'X' : ' ');
Packit d14fb6
		}
Packit d14fb6
	}
Packit d14fb6
	else if (p.netfn >= 0) {
Packit d14fb6
		if (!((p.lun < 0 || bmc_fn_support->lun[p.lun].support) &&
Packit d14fb6
			(bmc_fn_support->lun[p.lun].netfn[p.netfn>>1].support)))
Packit d14fb6
		{
Packit d14fb6
			lprintf(LOG_ERR, "LUN or LUN/NetFn pair %02x,%02x not supported",
Packit d14fb6
				p.lun, p.netfn);
Packit d14fb6
			free(bmc_fn_support);
Packit d14fb6
			bmc_fn_support = NULL;
Packit d14fb6
			return 0;
Packit d14fb6
		}
Packit d14fb6
		n = p.netfn >> 1;
Packit d14fb6
		l = p.lun;
Packit d14fb6
		printf("Commands on LUN 0x%02x, NetFn 0x%02x\n", p.lun, p.netfn);
Packit d14fb6
		printf("support:      ");
Packit d14fb6
		print_bitfield(bmc_fn_support->lun[l].netfn[n].command_mask,
Packit d14fb6
				MAX_COMMAND_BYTES, 1, -1);
Packit d14fb6
		printf("configurable: ");
Packit d14fb6
		print_bitfield(bmc_fn_support->lun[l].netfn[n].config_mask,
Packit d14fb6
				MAX_COMMAND_BYTES, 0, -1);
Packit d14fb6
		printf("enabled:      ");
Packit d14fb6
		print_bitfield(bmc_fn_support->lun[l].netfn[n].enable_mask,
Packit d14fb6
				MAX_COMMAND_BYTES, 0, -1);
Packit d14fb6
	}
Packit d14fb6
	else {
Packit d14fb6
	    for (l=0; l<4; l++) {
Packit d14fb6
                p.lun = l;
Packit d14fb6
                if (bmc_fn_support->lun[l].support) {
Packit d14fb6
                    for (n=0; n
Packit d14fb6
                        p.netfn = n*2;
Packit d14fb6
                        if (bmc_fn_support->lun[l].netfn[n].support) {
Packit d14fb6
                            printf("%02x,%02x support:      ", p.lun, p.netfn);
Packit d14fb6
                            print_bitfield(bmc_fn_support->lun[l].netfn[n].command_mask,
Packit d14fb6
                                    MAX_COMMAND_BYTES, 1, -1);
Packit d14fb6
                            printf("%02x,%02x configurable: ", p.lun, p.netfn);
Packit d14fb6
                            print_bitfield(bmc_fn_support->lun[l].netfn[n].config_mask,
Packit d14fb6
                                    MAX_COMMAND_BYTES, 0, -1);
Packit d14fb6
                            printf("%02x,%02x enabled:      ", p.lun, p.netfn);
Packit d14fb6
                            print_bitfield(bmc_fn_support->lun[l].netfn[n].enable_mask,
Packit d14fb6
                                    MAX_COMMAND_BYTES, 0, -1);
Packit d14fb6
                        }
Packit d14fb6
                    }
Packit d14fb6
                }
Packit d14fb6
            }
Packit d14fb6
            p.lun = -1;
Packit d14fb6
            p.netfn = -1;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	free(bmc_fn_support);
Packit d14fb6
	bmc_fn_support = NULL;
Packit d14fb6
	return ret;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
/* ipmi_firewall_enable_disable  -  enable/disable BMC functions
Packit d14fb6
 *
Packit d14fb6
 * @intf:	ipmi inteface
Packit d14fb6
 * @enable:     whether to enable or disable
Packit d14fb6
 * @argc:	argument count
Packit d14fb6
 * @argv:	argument list
Packit d14fb6
 *
Packit d14fb6
 * returns 0 on success
Packit d14fb6
 * returns -1 on error
Packit d14fb6
 */
Packit d14fb6
static int
Packit d14fb6
ipmi_firewall_enable_disable(struct ipmi_intf * intf, int enable, int argc, char ** argv)
Packit d14fb6
{
Packit d14fb6
	struct ipmi_function_params p = {0xe, -1, -1, -1, -1, 0};
Packit d14fb6
	struct bmc_fn_support * bmc_fn_support;
Packit d14fb6
	int ret;
Packit d14fb6
	unsigned int l, n, c;
Packit d14fb6
	unsigned char enables[MAX_COMMAND_BYTES];
Packit d14fb6
Packit d14fb6
	if (argc < 1 || strncmp(argv[0], "help", 4) == 0) {
Packit d14fb6
		char * s1 = enable?"en":"dis";
Packit d14fb6
		char * s2 = enable?"":" [force]";
Packit d14fb6
		printf("%sable [channel H] lun L netfn N%s\n", s1, s2);
Packit d14fb6
		printf("\t%sable all commands on this LUN/NetFn pair\n", s1);
Packit d14fb6
		printf("%sable [channel H] lun L netfn N command C%s\n", s1, s2);
Packit d14fb6
		printf("\t%sable Command C and all its Sub-functions for this LUN/NetFn pair\n", s1);
Packit d14fb6
		printf("%sable [channel H] lun L netfn N command C subfn S\n", s1);
Packit d14fb6
		printf("\t%sable Sub-function S for Command C for this LUN/NetFn pair\n", s1);
Packit d14fb6
		if (!enable) {
Packit d14fb6
			printf("* force will allow you to disable the \"Command Set Enable\" command\n");
Packit d14fb6
			printf("\tthereby letting you shoot yourself in the foot\n");
Packit d14fb6
			printf("\tthis is only recommended for advanced users\n");
Packit d14fb6
		}
Packit d14fb6
		return 0;
Packit d14fb6
	}
Packit d14fb6
	if (ipmi_firewall_parse_args(argc, argv, &p) < 0)
Packit d14fb6
		return -1;
Packit d14fb6
Packit d14fb6
	bmc_fn_support = malloc(sizeof(struct bmc_fn_support));
Packit d14fb6
	if (!bmc_fn_support) {
Packit d14fb6
		lprintf(LOG_ERR, "malloc struct bmc_fn_support failed");
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	ret = _gather_info(intf, &p, bmc_fn_support);
Packit d14fb6
	if (ret < 0) {
Packit d14fb6
		free(bmc_fn_support);
Packit d14fb6
		bmc_fn_support = NULL;
Packit d14fb6
		return ret;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	l = p.lun;
Packit d14fb6
	n = p.netfn>>1;
Packit d14fb6
	c = p.command;
Packit d14fb6
	if (p.subfn >= 0) {
Packit d14fb6
		// firewall (en|dis)able [channel c] lun l netfn n command m subfn s
Packit d14fb6
		// (en|dis)able this sub-function for this commnad on this lun/netfn pair
Packit d14fb6
		memcpy(enables,
Packit d14fb6
			bmc_fn_support->lun[l].netfn[n].command[c].subfn_enable,
Packit d14fb6
			MAX_SUBFN_BYTES);
Packit d14fb6
		bit_set(enables, p.subfn, enable);
Packit d14fb6
		ret = _set_subfn_enables(intf, &p,
Packit d14fb6
			&bmc_fn_support->lun[l].netfn[n].command[c], enables);
Packit d14fb6
Packit d14fb6
	} else if (p.command >= 0) {
Packit d14fb6
		// firewall (en|dis)able [channel c] lun l netfn n command m
Packit d14fb6
		//    (en|dis)able all subfn and command for this commnad on this lun/netfn pair
Packit d14fb6
		memset(enables, enable?0xff:0, MAX_SUBFN_BYTES);
Packit d14fb6
		ret = _set_subfn_enables(intf, &p,
Packit d14fb6
			&bmc_fn_support->lun[l].netfn[n].command[c], enables);
Packit d14fb6
		memcpy(enables,
Packit d14fb6
			&bmc_fn_support->lun[l].netfn[n].enable_mask, sizeof(enables));
Packit d14fb6
		bit_set(enables, p.command, enable);
Packit d14fb6
		ret |= _set_command_enables(intf, &p,
Packit d14fb6
			&bmc_fn_support->lun[l].netfn[n], enables, p.force);
Packit d14fb6
	} else if (p.netfn >= 0) {
Packit d14fb6
		// firewall (en|dis)able [channel c] lun l netfn n
Packit d14fb6
		//    (en|dis)able all commnads on this lun/netfn pair
Packit d14fb6
		memset(enables, enable?0xff:0, sizeof(enables));
Packit d14fb6
		ret = _set_command_enables(intf, &p,
Packit d14fb6
			&bmc_fn_support->lun[l].netfn[n], enables, p.force);
Packit d14fb6
		/*
Packit d14fb6
		   } else if (p.lun >= 0) {
Packit d14fb6
		// firewall (en|dis)able [channel c] lun l
Packit d14fb6
		//    (en|dis)able all commnads on all netfn pairs for this lun
Packit d14fb6
		*/
Packit d14fb6
	}
Packit d14fb6
	free(bmc_fn_support);
Packit d14fb6
	bmc_fn_support = NULL;
Packit d14fb6
	return ret;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
/* ipmi_firewall_reset - reset firmware firewall to enable everything
Packit d14fb6
 *
Packit d14fb6
 * @intf:	ipmi inteface
Packit d14fb6
 * @argc:	argument count
Packit d14fb6
 * @argv:	argument list
Packit d14fb6
 *
Packit d14fb6
 * returns 0 on success
Packit d14fb6
 * returns -1 on error
Packit d14fb6
 */
Packit d14fb6
static int
Packit d14fb6
ipmi_firewall_reset(struct ipmi_intf * intf, int argc, char ** argv)
Packit d14fb6
{
Packit d14fb6
	struct ipmi_function_params p = {0xe, -1, -1, -1, -1, 0};
Packit d14fb6
	struct bmc_fn_support * bmc_fn_support;
Packit d14fb6
	int ret;
Packit d14fb6
	unsigned int l, n, c;
Packit d14fb6
	unsigned char enables[MAX_COMMAND_BYTES];
Packit d14fb6
Packit d14fb6
	if (argc < 1) {
Packit d14fb6
		lprintf(LOG_ERR, "Not enough parameters given.");
Packit d14fb6
		printf_firewall_usage();
Packit d14fb6
		return (-1);
Packit d14fb6
	} else if (argc > 0 && strncmp(argv[0], "help", 4) == 0) {
Packit d14fb6
		printf_firewall_usage();
Packit d14fb6
		return 0;
Packit d14fb6
	}
Packit d14fb6
	if (ipmi_firewall_parse_args(argc, argv, &p) < 0)
Packit d14fb6
		return -1;
Packit d14fb6
Packit d14fb6
	bmc_fn_support = malloc(sizeof(struct bmc_fn_support));
Packit d14fb6
	if (!bmc_fn_support) {
Packit d14fb6
		lprintf(LOG_ERR, "malloc struct bmc_fn_support failed");
Packit d14fb6
		return -1;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	ret = _gather_info(intf, &p, bmc_fn_support);
Packit d14fb6
	if (ret < 0) {
Packit d14fb6
		free(bmc_fn_support);
Packit d14fb6
		bmc_fn_support = NULL;
Packit d14fb6
		return ret;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	for (l=0; l
Packit d14fb6
		p.lun = l;
Packit d14fb6
		for (n=0; n
Packit d14fb6
			p.netfn = n*2;
Packit d14fb6
			for (c=0; c
Packit d14fb6
				p.command = c;
Packit d14fb6
				printf("reset lun %d, netfn %d, command %d, subfn\n", l, n, c);
Packit d14fb6
				memset(enables, 0xff, MAX_SUBFN_BYTES);
Packit d14fb6
				ret = _set_subfn_enables(intf, &p,
Packit d14fb6
					&bmc_fn_support->lun[l].netfn[n].command[c], enables);
Packit d14fb6
			}
Packit d14fb6
			printf("reset lun %d, netfn %d, command\n", l, n);
Packit d14fb6
			memset(enables, 0xff, sizeof(enables));
Packit d14fb6
			ret = _set_command_enables(intf, &p,
Packit d14fb6
				&bmc_fn_support->lun[l].netfn[n], enables, 0);
Packit d14fb6
		}
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	free(bmc_fn_support);
Packit d14fb6
	bmc_fn_support = NULL;
Packit d14fb6
	return ret;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
Packit d14fb6
/* ipmi_firewall_main - top-level handler for firmware firewall functions
Packit d14fb6
 *
Packit d14fb6
 * @intf:	ipmi interface
Packit d14fb6
 * @argc:	number of arguments
Packit d14fb6
 * @argv:	argument list
Packit d14fb6
 *
Packit d14fb6
 * returns 0 on success
Packit d14fb6
 * returns -1 on error
Packit d14fb6
 */
Packit d14fb6
int
Packit d14fb6
ipmi_firewall_main(struct ipmi_intf * intf, int argc, char ** argv)
Packit d14fb6
{
Packit d14fb6
	int rc = 0;
Packit d14fb6
Packit d14fb6
	if (argc < 1 || strncmp(argv[0], "help", 4) == 0) {
Packit d14fb6
		printf_firewall_usage();
Packit d14fb6
	}
Packit d14fb6
	else if (strncmp(argv[0], "info", 4) == 0) {
Packit d14fb6
		rc = ipmi_firewall_info(intf, argc-1, &(argv[1]));
Packit d14fb6
	}
Packit d14fb6
	else if (strncmp(argv[0], "enable", 6) == 0) {
Packit d14fb6
		rc = ipmi_firewall_enable_disable(intf, 1, argc-1, &(argv[1]));
Packit d14fb6
	}
Packit d14fb6
	else if (strncmp(argv[0], "disable", 7) == 0) {
Packit d14fb6
		rc = ipmi_firewall_enable_disable(intf, 0, argc-1, &(argv[1]));
Packit d14fb6
	}
Packit d14fb6
	else if (strncmp(argv[0], "reset", 5) == 0) {
Packit d14fb6
		rc = ipmi_firewall_reset(intf, argc-1, &(argv[1]));
Packit d14fb6
	}
Packit d14fb6
	else {
Packit d14fb6
		printf_firewall_usage();
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	return rc;
Packit d14fb6
}