Blame lib/ipmi_sunoem.c

Packit d14fb6
/*
Packit d14fb6
 * Copyright (c) 2009, 2014, Oracle and/or its affiliates. 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
#define _XOPEN_SOURCE
Packit d14fb6
Packit d14fb6
#include <stdlib.h>
Packit d14fb6
#include <stdio.h>
Packit d14fb6
#include <string.h>
Packit d14fb6
#include <strings.h>
Packit d14fb6
#include <sys/socket.h>
Packit d14fb6
#include <netinet/in.h>
Packit d14fb6
#include <arpa/inet.h>
Packit d14fb6
#include <errno.h>
Packit d14fb6
#include <time.h>
Packit d14fb6
#include <unistd.h>
Packit d14fb6
#include <signal.h>
Packit d14fb6
#include <ctype.h>
Packit d14fb6
#include <sys/time.h>
Packit d14fb6
#include <limits.h>
Packit d14fb6
#include <fcntl.h>
Packit d14fb6
#include <sys/select.h>
Packit d14fb6
Packit d14fb6
#include <termios.h>
Packit d14fb6
Packit d14fb6
#include <ipmitool/ipmi.h>
Packit d14fb6
#include <ipmitool/ipmi_intf.h>
Packit d14fb6
#include <ipmitool/helper.h>
Packit d14fb6
#include <ipmitool/log.h>
Packit d14fb6
#include <ipmitool/ipmi_sel.h>
Packit d14fb6
#include <ipmitool/ipmi_sdr.h>
Packit d14fb6
#include <ipmitool/ipmi_strings.h>
Packit d14fb6
#include <ipmitool/ipmi_channel.h>
Packit d14fb6
#include <ipmitool/ipmi_sunoem.h>
Packit d14fb6
#include <ipmitool/ipmi_raw.h>
Packit d14fb6
Packit d14fb6
static const struct valstr sunoem_led_type_vals[] = {
Packit d14fb6
	{ 0, "OK2RM" },
Packit d14fb6
	{ 1, "SERVICE" },
Packit d14fb6
	{ 2, "ACT" },
Packit d14fb6
	{ 3, "LOCATE" },
Packit d14fb6
	{ 0xFF, NULL },
Packit d14fb6
};
Packit d14fb6
Packit d14fb6
static const struct valstr sunoem_led_mode_vals[] = {
Packit d14fb6
	{ 0, "OFF" },
Packit d14fb6
	{ 1, "ON" },
Packit d14fb6
	{ 2, "STANDBY" },
Packit d14fb6
	{ 3, "SLOW" },
Packit d14fb6
	{ 4, "FAST" },
Packit d14fb6
	{ 0xFF, NULL },
Packit d14fb6
};
Packit d14fb6
Packit d14fb6
static const struct valstr sunoem_led_mode_optvals[] = {
Packit d14fb6
	{ 0, "STEADY_OFF" },
Packit d14fb6
	{ 1, "STEADY_ON" },
Packit d14fb6
	{ 2, "STANDBY_BLINK" },
Packit d14fb6
	{ 3, "SLOW_BLINK" },
Packit d14fb6
	{ 4, "FAST_BLINK" },
Packit d14fb6
	{ 0xFF, NULL },
Packit d14fb6
};
Packit d14fb6
Packit d14fb6
#define SUNOEM_SUCCESS 1
Packit d14fb6
Packit d14fb6
#define IPMI_SUNOEM_GETFILE_VERSION {3,2,0,0}
Packit d14fb6
#define IPMI_SUNOEM_GETBEHAVIOR_VERSION {3,2,0,0}
Packit d14fb6
Packit d14fb6
/*
Packit d14fb6
 * PRINT_NORMAL: print out the LED value as normal
Packit d14fb6
 * PRINT_ERROR: print out "na" for the LED value
Packit d14fb6
 */
Packit d14fb6
typedef enum
Packit d14fb6
{
Packit d14fb6
	PRINT_NORMAL = 0, PRINT_ERROR
Packit d14fb6
} print_status_t;
Packit d14fb6
Packit d14fb6
int ret_get = 0;
Packit d14fb6
int ret_set = 0;
Packit d14fb6
Packit d14fb6
static void
Packit d14fb6
ipmi_sunoem_usage(void)
Packit d14fb6
{
Packit d14fb6
	lprintf(LOG_NOTICE, "Usage: sunoem <command> [option...]");
Packit d14fb6
	lprintf(LOG_NOTICE, "");
Packit d14fb6
	lprintf(LOG_NOTICE, "Commands:");
Packit d14fb6
	lprintf(LOG_NOTICE, " - cli [<command string> ...]");
Packit d14fb6
	lprintf(LOG_NOTICE, "      Execute SP CLI commands.");
Packit d14fb6
	lprintf(LOG_NOTICE, "");
Packit d14fb6
	lprintf(LOG_NOTICE, " - led get [<sensor_id>] [ledtype]");
Packit d14fb6
	lprintf(LOG_NOTICE, "      - Read status of LED found in Generic Device Locator.");
Packit d14fb6
	lprintf(LOG_NOTICE, "");
Packit d14fb6
	lprintf(LOG_NOTICE, " - led set <sensor_id> <led_mode> [led_type]");
Packit d14fb6
	lprintf(LOG_NOTICE, "      - Set mode of LED found in Generic Device Locator.");
Packit d14fb6
	lprintf(LOG_NOTICE, "      - You can pass 'all' as the <senso_rid> to change the LED mode of all sensors.");
Packit d14fb6
	lprintf(LOG_NOTICE, "      - Use 'sdr list generic' command to get list of Generic");
Packit d14fb6
	lprintf(LOG_NOTICE, "      - Devices that are controllable LEDs.");
Packit d14fb6
	lprintf(LOG_NOTICE, "");
Packit d14fb6
	lprintf(LOG_NOTICE, "      - Required SIS LED Mode:");
Packit d14fb6
	lprintf(LOG_NOTICE, "          OFF          Off");
Packit d14fb6
	lprintf(LOG_NOTICE, "          ON           Steady On");
Packit d14fb6
	lprintf(LOG_NOTICE, "          STANDBY      100ms on 2900ms off blink rate");
Packit d14fb6
	lprintf(LOG_NOTICE, "          SLOW         1HZ blink rate");
Packit d14fb6
	lprintf(LOG_NOTICE, "          FAST         4HZ blink rate");
Packit d14fb6
	lprintf(LOG_NOTICE, "");
Packit d14fb6
	lprintf(LOG_NOTICE, "      - Optional SIS LED Type:");
Packit d14fb6
	lprintf(LOG_NOTICE, "          OK2RM        OK to Remove");
Packit d14fb6
	lprintf(LOG_NOTICE, "          SERVICE      Service Required");
Packit d14fb6
	lprintf(LOG_NOTICE, "          ACT          Activity");
Packit d14fb6
	lprintf(LOG_NOTICE, "          LOCATE       Locate");
Packit d14fb6
	lprintf(LOG_NOTICE, "");
Packit d14fb6
	lprintf(LOG_NOTICE, " - nacname <ipmi_nac_name>");
Packit d14fb6
	lprintf(LOG_NOTICE, "      - Returns the full nac name");
Packit d14fb6
	lprintf(LOG_NOTICE, "");
Packit d14fb6
	lprintf(LOG_NOTICE, " - ping NUMBER <q>");
Packit d14fb6
	lprintf(LOG_NOTICE, "      - Send and Receive NUMBER (64 Byte) packets.");
Packit d14fb6
	lprintf(LOG_NOTICE, "");
Packit d14fb6
	lprintf(LOG_NOTICE, "      - q - Quiet. Displays output at start and end");
Packit d14fb6
	lprintf(LOG_NOTICE, "");
Packit d14fb6
	lprintf(LOG_NOTICE, " - getval <target_name>");
Packit d14fb6
	lprintf(LOG_NOTICE, "      - Returns the ILOM property value");
Packit d14fb6
	lprintf(LOG_NOTICE, "");
Packit d14fb6
	lprintf(LOG_NOTICE, " - setval <property name> <property value> <timeout>");
Packit d14fb6
	lprintf(LOG_NOTICE, "      - Sets the ILOM property value");
Packit d14fb6
	lprintf(LOG_NOTICE, "      - If timeout is not specified, the default is 5 sec.");
Packit d14fb6
	lprintf(LOG_NOTICE, "      - NOTE: must be executed locally on host, not remotely over LAN!");
Packit d14fb6
	lprintf(LOG_NOTICE, "");
Packit d14fb6
	lprintf(LOG_NOTICE, " - sshkey del <user_id>");
Packit d14fb6
	lprintf(LOG_NOTICE, "      - Delete ssh key for user id from authorized_keys,");
Packit d14fb6
	lprintf(LOG_NOTICE, "      - view users with 'user list' command.");
Packit d14fb6
	lprintf(LOG_NOTICE, "");
Packit d14fb6
	lprintf(LOG_NOTICE, " - sshkey set <user_id> <id_rsa.pub>");
Packit d14fb6
	lprintf(LOG_NOTICE, "      - Set ssh key for a userid into authorized_keys,");
Packit d14fb6
	lprintf(LOG_NOTICE, "      - view users with 'user list' command.");
Packit d14fb6
	lprintf(LOG_NOTICE, "");
Packit d14fb6
	lprintf(LOG_NOTICE, " - version");
Packit d14fb6
	lprintf(LOG_NOTICE, "      - Display the software version");
Packit d14fb6
	lprintf(LOG_NOTICE, "");
Packit d14fb6
	lprintf(LOG_NOTICE, " - nacname <ipmi_nac_name>");
Packit d14fb6
	lprintf(LOG_NOTICE, "      - Returns the full nac name");
Packit d14fb6
	lprintf(LOG_NOTICE, "");
Packit d14fb6
	lprintf(LOG_NOTICE, " - getfile <file_string_id> <destination_file_name>");
Packit d14fb6
	lprintf(LOG_NOTICE, "      - Copy file <file_string_id> to <destination_file_name>");
Packit d14fb6
	lprintf(LOG_NOTICE, "");
Packit d14fb6
	lprintf(LOG_NOTICE, "      - File string ids:");
Packit d14fb6
	lprintf(LOG_NOTICE, "          SSH_PUBKEYS");
Packit d14fb6
	lprintf(LOG_NOTICE, "          DIAG_PASSED");
Packit d14fb6
	lprintf(LOG_NOTICE, "          DIAG_FAILED");
Packit d14fb6
	lprintf(LOG_NOTICE, "          DIAG_END_TIME");
Packit d14fb6
	lprintf(LOG_NOTICE, "          DIAG_INVENTORY");
Packit d14fb6
	lprintf(LOG_NOTICE, "          DIAG_TEST_LOG");
Packit d14fb6
	lprintf(LOG_NOTICE, "          DIAG_START_TIME");
Packit d14fb6
	lprintf(LOG_NOTICE, "          DIAG_UEFI_LOG");
Packit d14fb6
	lprintf(LOG_NOTICE, "          DIAG_TEST_LOG");
Packit d14fb6
	lprintf(LOG_NOTICE, "          DIAG_LAST_LOG");
Packit d14fb6
	lprintf(LOG_NOTICE, "          DIAG_LAST_CMD");
Packit d14fb6
	lprintf(LOG_NOTICE, "");
Packit d14fb6
	lprintf(LOG_NOTICE, " - getbehavior <behavior_string_id>");
Packit d14fb6
	lprintf(LOG_NOTICE, "      - Test if ILOM behavior is enabled");
Packit d14fb6
	lprintf(LOG_NOTICE, "");
Packit d14fb6
	lprintf(LOG_NOTICE, "      - Behavior string ids:");
Packit d14fb6
	lprintf(LOG_NOTICE, "          SUPPORTS_SIGNED_PACKAGES");
Packit d14fb6
	lprintf(LOG_NOTICE, "          REQUIRES_SIGNED_PACKAGES");
Packit d14fb6
	lprintf(LOG_NOTICE, "");
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
#define SUNOEM_FAN_MODE_AUTO    0x00
Packit d14fb6
#define SUNOEM_FAN_MODE_MANUAL  0x01
Packit d14fb6
Packit d14fb6
static void
Packit d14fb6
__sdr_list_empty(struct sdr_record_list * head)
Packit d14fb6
{
Packit d14fb6
	struct sdr_record_list * e, *f;
Packit d14fb6
	for (e = head; e != NULL; e = f) {
Packit d14fb6
		f = e->next;
Packit d14fb6
		free(e);
Packit d14fb6
	}
Packit d14fb6
	head = NULL;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
/*
Packit d14fb6
 *  led_print
Packit d14fb6
 *  Print out the led name and the state, if stat is PRINT_NORMAL.
Packit d14fb6
 *  Otherwise, print out the led name and "na".
Packit d14fb6
 *  The state parameter is not referenced if stat is not PRINT_NORMAL.
Packit d14fb6
 */
Packit d14fb6
static void
Packit d14fb6
led_print(const char * name, print_status_t stat, uint8_t state)
Packit d14fb6
{
Packit d14fb6
	const char *theValue;
Packit d14fb6
Packit d14fb6
	if (stat == PRINT_NORMAL) {
Packit d14fb6
		theValue = val2str(state, sunoem_led_mode_vals);
Packit d14fb6
	} else {
Packit d14fb6
		theValue = "na";
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	if (csv_output) {
Packit d14fb6
		printf("%s,%s\n", name, theValue);
Packit d14fb6
	} else {
Packit d14fb6
		printf("%-16s | %s\n", name, theValue);
Packit d14fb6
	}
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
#define CC_NORMAL                  0x00
Packit d14fb6
#define CC_PARAM_OUT_OF_RANGE      0xc9
Packit d14fb6
#define CC_DEST_UNAVAILABLE        0xd3
Packit d14fb6
#define CC_UNSPECIFIED_ERR         0xff
Packit d14fb6
#define CC_INSUFFICIENT_PRIVILEGE  0xd4
Packit d14fb6
#define CC_INV_CMD                 0xc1
Packit d14fb6
#define CC_INV_DATA_FIELD          0xcc
Packit d14fb6
Packit d14fb6
/*
Packit d14fb6
 * sunoem_led_get(....)
Packit d14fb6
 *
Packit d14fb6
 * OUTPUT:
Packit d14fb6
 *   SUNOEM_EC_INVALID_ARG         if dev is NULL,
Packit d14fb6
 *   SUNOEM_EC_BMC_NOT_RESPONDING  if no reply is obtained from BMC,
Packit d14fb6
 *   SUNOEM_EC_BMC_CCODE_NONZERO   if completion code is nonzero,
Packit d14fb6
 *   SUNOEM_EC_SUCCESS             otherwise.
Packit d14fb6
 */
Packit d14fb6
static sunoem_ec_t
Packit d14fb6
sunoem_led_get(struct ipmi_intf * intf,	struct sdr_record_generic_locator * dev,
Packit d14fb6
		int ledtype, struct ipmi_rs **loc_rsp)
Packit d14fb6
{
Packit d14fb6
	struct ipmi_rs * rsp;
Packit d14fb6
	struct ipmi_rq req;
Packit d14fb6
	uint8_t rqdata[7];
Packit d14fb6
	int rqdata_len;
Packit d14fb6
Packit d14fb6
	if (dev == NULL) {
Packit d14fb6
		*loc_rsp = NULL;
Packit d14fb6
		return (SUNOEM_EC_INVALID_ARG);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	rqdata[0] = dev->dev_slave_addr;
Packit d14fb6
	if (ledtype == 0xFF)
Packit d14fb6
		rqdata[1] = dev->oem;
Packit d14fb6
	else
Packit d14fb6
		rqdata[1] = ledtype;
Packit d14fb6
Packit d14fb6
	rqdata[2] = dev->dev_access_addr;
Packit d14fb6
	rqdata[3] = dev->oem;
Packit d14fb6
	rqdata[4] = dev->entity.id;
Packit d14fb6
	rqdata[5] = dev->entity.instance;
Packit d14fb6
	rqdata[6] = 0;
Packit d14fb6
	rqdata_len = 7;
Packit d14fb6
Packit d14fb6
	req.msg.netfn = IPMI_NETFN_SUNOEM;
Packit d14fb6
	req.msg.cmd = IPMI_SUNOEM_LED_GET;
Packit d14fb6
	req.msg.lun = dev->lun;
Packit d14fb6
	req.msg.data = rqdata;
Packit d14fb6
	req.msg.data_len = rqdata_len;
Packit d14fb6
Packit d14fb6
	rsp = intf->sendrecv(intf, &req;;
Packit d14fb6
	/*
Packit d14fb6
	 * Just return NULL if there was
Packit d14fb6
	 * an error.
Packit d14fb6
	 */
Packit d14fb6
	if (rsp == NULL) {
Packit d14fb6
		*loc_rsp = NULL;
Packit d14fb6
		return (SUNOEM_EC_BMC_NOT_RESPONDING);
Packit d14fb6
	} else if (rsp->ccode > 0) {
Packit d14fb6
		*loc_rsp = rsp;
Packit d14fb6
		return (SUNOEM_EC_BMC_CCODE_NONZERO);
Packit d14fb6
	} else {
Packit d14fb6
		*loc_rsp = rsp;
Packit d14fb6
		return (SUNOEM_EC_SUCCESS);
Packit d14fb6
	}
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
static struct ipmi_rs *
Packit d14fb6
sunoem_led_set(struct ipmi_intf * intf, struct sdr_record_generic_locator * dev,
Packit d14fb6
		int ledtype, int ledmode)
Packit d14fb6
{
Packit d14fb6
	struct ipmi_rs * rsp;
Packit d14fb6
	struct ipmi_rq req;
Packit d14fb6
	uint8_t rqdata[9];
Packit d14fb6
	int rqdata_len;
Packit d14fb6
Packit d14fb6
	if (dev == NULL)
Packit d14fb6
		return NULL;
Packit d14fb6
Packit d14fb6
	rqdata[0] = dev->dev_slave_addr;
Packit d14fb6
Packit d14fb6
	if (ledtype == 0xFF)
Packit d14fb6
		rqdata[1] = dev->oem;
Packit d14fb6
	else
Packit d14fb6
		rqdata[1] = ledtype;
Packit d14fb6
Packit d14fb6
	rqdata[2] = dev->dev_access_addr;
Packit d14fb6
	rqdata[3] = dev->oem;
Packit d14fb6
	rqdata[4] = ledmode;
Packit d14fb6
	rqdata[5] = dev->entity.id;
Packit d14fb6
	rqdata[6] = dev->entity.instance;
Packit d14fb6
	rqdata[7] = 0;
Packit d14fb6
	rqdata[8] = 0;
Packit d14fb6
	rqdata_len = 9;
Packit d14fb6
Packit d14fb6
	req.msg.netfn = IPMI_NETFN_SUNOEM;
Packit d14fb6
	req.msg.cmd = IPMI_SUNOEM_LED_SET;
Packit d14fb6
	req.msg.lun = dev->lun;
Packit d14fb6
	req.msg.data = rqdata;
Packit d14fb6
	req.msg.data_len = rqdata_len;
Packit d14fb6
Packit d14fb6
	rsp = intf->sendrecv(intf, &req;;
Packit d14fb6
	if (rsp == NULL) {
Packit d14fb6
		lprintf(LOG_ERR, "Sun OEM Set LED command failed.");
Packit d14fb6
		return NULL;
Packit d14fb6
	} else if (rsp->ccode > 0) {
Packit d14fb6
		lprintf(LOG_ERR, "Sun OEM Set LED command failed: %s",
Packit d14fb6
				val2str(rsp->ccode, completion_code_vals));
Packit d14fb6
		return NULL;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	return (rsp);
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
static void
Packit d14fb6
sunoem_led_get_byentity(struct ipmi_intf * intf, uint8_t entity_id,
Packit d14fb6
		uint8_t entity_inst, int ledtype)
Packit d14fb6
{
Packit d14fb6
	struct ipmi_rs * rsp;
Packit d14fb6
	struct sdr_record_list *elist, *e;
Packit d14fb6
	struct entity_id entity;
Packit d14fb6
	sunoem_ec_t res;
Packit d14fb6
Packit d14fb6
	if (entity_id == 0)
Packit d14fb6
		return;
Packit d14fb6
Packit d14fb6
	/* lookup sdrs with this entity */
Packit d14fb6
	memset(&entity, 0, sizeof(struct entity_id));
Packit d14fb6
	entity.id = entity_id;
Packit d14fb6
	entity.instance = entity_inst;
Packit d14fb6
Packit d14fb6
	elist = ipmi_sdr_find_sdr_byentity(intf, &entity);
Packit d14fb6
Packit d14fb6
	if (elist == NULL)
Packit d14fb6
		ret_get = -1;
Packit d14fb6
Packit d14fb6
	/* for each generic sensor get its led state */
Packit d14fb6
	for (e = elist; e != NULL; e = e->next) {
Packit d14fb6
		if (e->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR)
Packit d14fb6
			continue;
Packit d14fb6
Packit d14fb6
		res = sunoem_led_get(intf, e->record.genloc, ledtype, &rsp;;
Packit d14fb6
Packit d14fb6
		if (res == SUNOEM_EC_SUCCESS && rsp && rsp->data_len == 1) {
Packit d14fb6
			led_print((const char *) e->record.genloc->id_string, PRINT_NORMAL,
Packit d14fb6
					rsp->data[0]);
Packit d14fb6
		} else {
Packit d14fb6
			led_print((const char *) e->record.genloc->id_string, PRINT_ERROR,
Packit d14fb6
					0);
Packit d14fb6
			if (res != SUNOEM_EC_BMC_CCODE_NONZERO|| !rsp
Packit d14fb6
			|| rsp->ccode != CC_DEST_UNAVAILABLE) {
Packit d14fb6
				ret_get = -1;
Packit d14fb6
			}
Packit d14fb6
		}
Packit d14fb6
	}
Packit d14fb6
	__sdr_list_empty(elist);
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
static void
Packit d14fb6
sunoem_led_set_byentity(struct ipmi_intf * intf, uint8_t entity_id,
Packit d14fb6
		uint8_t entity_inst, int ledtype, int ledmode)
Packit d14fb6
{
Packit d14fb6
	struct ipmi_rs * rsp;
Packit d14fb6
	struct sdr_record_list *elist, *e;
Packit d14fb6
	struct entity_id entity;
Packit d14fb6
Packit d14fb6
	if (entity_id == 0)
Packit d14fb6
		return;
Packit d14fb6
Packit d14fb6
	/* lookup sdrs with this entity */
Packit d14fb6
	memset(&entity, 0, sizeof(struct entity_id));
Packit d14fb6
	entity.id = entity_id;
Packit d14fb6
	entity.instance = entity_inst;
Packit d14fb6
Packit d14fb6
	elist = ipmi_sdr_find_sdr_byentity(intf, &entity);
Packit d14fb6
Packit d14fb6
	if (elist == NULL)
Packit d14fb6
		ret_set = -1;
Packit d14fb6
Packit d14fb6
	/* for each generic sensor set its led state */
Packit d14fb6
	for (e = elist; e != NULL; e = e->next) {
Packit d14fb6
Packit d14fb6
		if (e->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR)
Packit d14fb6
			continue;
Packit d14fb6
Packit d14fb6
		rsp = sunoem_led_set(intf, e->record.genloc, ledtype, ledmode);
Packit d14fb6
		if (rsp && rsp->data_len == 0) {
Packit d14fb6
			led_print((const char *) e->record.genloc->id_string, PRINT_NORMAL,
Packit d14fb6
					ledmode);
Packit d14fb6
		} else if (rsp == NULL) {
Packit d14fb6
			ret_set = -1;
Packit d14fb6
		}
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	__sdr_list_empty(elist);
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
/*
Packit d14fb6
 * IPMI Request Data: 5 bytes
Packit d14fb6
 *
Packit d14fb6
 * [byte 0]  devAddr     Value from the "Device Slave Address" field in
Packit d14fb6
 *                       LED's Generic Device Locator record in the SDR
Packit d14fb6
 * [byte 1]  led         LED Type: OK2RM, ACT, LOCATE, SERVICE
Packit d14fb6
 * [byte 2]  ctrlrAddr   Controller address; value from the "Device
Packit d14fb6
 *                       Access Address" field, 0x20 if the LED is local
Packit d14fb6
 * [byte 3]  hwInfo      The OEM field from the SDR record
Packit d14fb6
 * [byte 4]  force       1 = directly access the device
Packit d14fb6
 *                       0 = go thru its controller
Packit d14fb6
 *                       Ignored if LED is local
Packit d14fb6
 *
Packit d14fb6
 * The format below is for Sun Blade Modular systems only
Packit d14fb6
 * [byte 4]  entityID    The entityID field from the SDR record
Packit d14fb6
 * [byte 5]  entityIns   The entityIns field from the SDR record
Packit d14fb6
 * [byte 6]  force       1 = directly access the device
Packit d14fb6
 *                       0 = go thru its controller
Packit d14fb6
 *                       Ignored if LED is local
Packit d14fb6
 */
Packit d14fb6
static int
Packit d14fb6
ipmi_sunoem_led_get(struct ipmi_intf * intf, int argc, char ** argv)
Packit d14fb6
{
Packit d14fb6
	struct ipmi_rs * rsp;
Packit d14fb6
	struct sdr_record_list *sdr;
Packit d14fb6
	struct sdr_record_list *alist, *a;
Packit d14fb6
	struct sdr_record_entity_assoc *assoc;
Packit d14fb6
	int ledtype = 0xFF;
Packit d14fb6
	int i;
Packit d14fb6
	sunoem_ec_t res;
Packit d14fb6
Packit d14fb6
	/*
Packit d14fb6
	 * sunoem led/sbled get <id> [type]
Packit d14fb6
	 */
Packit d14fb6
Packit d14fb6
	if (argc < 1 || strncmp(argv[0], "help", 4) == 0) {
Packit d14fb6
		ipmi_sunoem_usage();
Packit d14fb6
		return (0);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	if (argc > 1) {
Packit d14fb6
		ledtype = str2val(argv[1], sunoem_led_type_vals);
Packit d14fb6
		if (ledtype == 0xFF)
Packit d14fb6
			lprintf(LOG_ERR,
Packit d14fb6
					"Unknown ledtype, will use data from the SDR oem field");
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	if (strncasecmp(argv[0], "all", 3) == 0) {
Packit d14fb6
		/* do all generic sensors */
Packit d14fb6
		alist = ipmi_sdr_find_sdr_bytype(intf,
Packit d14fb6
		SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR);
Packit d14fb6
Packit d14fb6
		if (alist == NULL)
Packit d14fb6
			return (-1);
Packit d14fb6
Packit d14fb6
		for (a = alist; a != NULL; a = a->next) {
Packit d14fb6
			if (a->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR)
Packit d14fb6
				continue;
Packit d14fb6
			if (a->record.genloc->entity.logical)
Packit d14fb6
				continue;
Packit d14fb6
Packit d14fb6
			res = sunoem_led_get(intf, a->record.genloc, ledtype, &rsp;;
Packit d14fb6
Packit d14fb6
			if (res == SUNOEM_EC_SUCCESS && rsp && rsp->data_len == 1) {
Packit d14fb6
				led_print((const char *) a->record.genloc->id_string,
Packit d14fb6
						PRINT_NORMAL, rsp->data[0]);
Packit d14fb6
			} else {
Packit d14fb6
				led_print((const char *) a->record.genloc->id_string,
Packit d14fb6
						PRINT_ERROR, 0);
Packit d14fb6
				if (res != SUNOEM_EC_BMC_CCODE_NONZERO|| !rsp ||
Packit d14fb6
				rsp->ccode != CC_DEST_UNAVAILABLE) {
Packit d14fb6
					ret_get = -1;
Packit d14fb6
				}
Packit d14fb6
			}
Packit d14fb6
		}
Packit d14fb6
		__sdr_list_empty(alist);
Packit d14fb6
Packit d14fb6
		if (ret_get == -1)
Packit d14fb6
			return (-1);
Packit d14fb6
Packit d14fb6
		return (0);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	/* look up generic device locator record in SDR */
Packit d14fb6
	sdr = ipmi_sdr_find_sdr_byid(intf, argv[0]);
Packit d14fb6
Packit d14fb6
	if (sdr == NULL) {
Packit d14fb6
		lprintf(LOG_ERR, "No Sensor Data Record found for %s", argv[0]);
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	if (sdr->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR) {
Packit d14fb6
		lprintf(LOG_ERR, "Invalid SDR type %d", sdr->type);
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	if (!sdr->record.genloc->entity.logical) {
Packit d14fb6
		/*
Packit d14fb6
		 * handle physical entity
Packit d14fb6
		 */
Packit d14fb6
Packit d14fb6
		res = sunoem_led_get(intf, sdr->record.genloc, ledtype, &rsp;;
Packit d14fb6
Packit d14fb6
		if (res == SUNOEM_EC_SUCCESS && rsp && rsp->data_len == 1) {
Packit d14fb6
			led_print((const char *) sdr->record.genloc->id_string,
Packit d14fb6
					PRINT_NORMAL, rsp->data[0]);
Packit d14fb6
Packit d14fb6
		} else {
Packit d14fb6
			led_print((const char *) sdr->record.genloc->id_string, PRINT_ERROR,
Packit d14fb6
					0);
Packit d14fb6
			if (res != SUNOEM_EC_BMC_CCODE_NONZERO|| !rsp
Packit d14fb6
			|| rsp->ccode != CC_DEST_UNAVAILABLE) {
Packit d14fb6
				ret_get = -1;
Packit d14fb6
			}
Packit d14fb6
		}
Packit d14fb6
Packit d14fb6
		if (ret_get == -1)
Packit d14fb6
			return (-1);
Packit d14fb6
Packit d14fb6
		return (0);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	/*
Packit d14fb6
	 * handle logical entity for LED grouping
Packit d14fb6
	 */
Packit d14fb6
Packit d14fb6
	lprintf(LOG_INFO, "LED %s is logical device", argv[0]);
Packit d14fb6
Packit d14fb6
	/* get entity assoc records */
Packit d14fb6
	alist = ipmi_sdr_find_sdr_bytype(intf, SDR_RECORD_TYPE_ENTITY_ASSOC);
Packit d14fb6
Packit d14fb6
	if (alist == NULL)
Packit d14fb6
		return (-1);
Packit d14fb6
Packit d14fb6
	for (a = alist; a != NULL; a = a->next) {
Packit d14fb6
		if (a->type != SDR_RECORD_TYPE_ENTITY_ASSOC)
Packit d14fb6
			continue;
Packit d14fb6
		assoc = a->record.entassoc;
Packit d14fb6
		if (assoc == NULL)
Packit d14fb6
			continue;
Packit d14fb6
Packit d14fb6
		/* check that the entity id/instance matches our generic record */
Packit d14fb6
		if (assoc->entity.id != sdr->record.genloc->entity.id
Packit d14fb6
				|| assoc->entity.instance
Packit d14fb6
						!= sdr->record.genloc->entity.instance)
Packit d14fb6
			continue;
Packit d14fb6
Packit d14fb6
		if (assoc->flags.isrange) {
Packit d14fb6
			/*
Packit d14fb6
			 * handle ranged entity associations
Packit d14fb6
			 *
Packit d14fb6
			 * the test for non-zero entity id is handled in
Packit d14fb6
			 * sunoem_led_get_byentity()
Packit d14fb6
			 */
Packit d14fb6
Packit d14fb6
			/* first range set - id 1 and 2 must be equal */
Packit d14fb6
			if (assoc->entity_id_1 == assoc->entity_id_2)
Packit d14fb6
				for (i = assoc->entity_inst_1; i <= assoc->entity_inst_2; i++)
Packit d14fb6
					sunoem_led_get_byentity(intf, assoc->entity_id_1, i,
Packit d14fb6
							ledtype);
Packit d14fb6
Packit d14fb6
			/* second range set - id 3 and 4 must be equal */
Packit d14fb6
			if (assoc->entity_id_3 == assoc->entity_id_4)
Packit d14fb6
				for (i = assoc->entity_inst_3; i <= assoc->entity_inst_4; i++)
Packit d14fb6
					sunoem_led_get_byentity(intf, assoc->entity_id_3, i,
Packit d14fb6
							ledtype);
Packit d14fb6
		} else {
Packit d14fb6
			/*
Packit d14fb6
			 * handle entity list
Packit d14fb6
			 */
Packit d14fb6
			sunoem_led_get_byentity(intf, assoc->entity_id_1,
Packit d14fb6
					assoc->entity_inst_1, ledtype);
Packit d14fb6
			sunoem_led_get_byentity(intf, assoc->entity_id_2,
Packit d14fb6
					assoc->entity_inst_2, ledtype);
Packit d14fb6
			sunoem_led_get_byentity(intf, assoc->entity_id_3,
Packit d14fb6
					assoc->entity_inst_3, ledtype);
Packit d14fb6
			sunoem_led_get_byentity(intf, assoc->entity_id_4,
Packit d14fb6
					assoc->entity_inst_4, ledtype);
Packit d14fb6
		}
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	__sdr_list_empty(alist);
Packit d14fb6
Packit d14fb6
	if (ret_get == -1)
Packit d14fb6
		return (-1);
Packit d14fb6
Packit d14fb6
	return (0);
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
/*
Packit d14fb6
 * IPMI Request Data: 7 bytes
Packit d14fb6
 *
Packit d14fb6
 * [byte 0]  devAddr     Value from the "Device Slave Address" field in
Packit d14fb6
 *                       LED's Generic Device Locator record in the SDR
Packit d14fb6
 * [byte 1]  led         LED Type: OK2RM, ACT, LOCATE, SERVICE
Packit d14fb6
 * [byte 2]  ctrlrAddr   Controller address; value from the "Device
Packit d14fb6
 *                       Access Address" field, 0x20 if the LED is local
Packit d14fb6
 * [byte 3]  hwInfo      The OEM field from the SDR record
Packit d14fb6
 * [byte 4]  mode        LED Mode: OFF, ON, STANDBY, SLOW, FAST
Packit d14fb6
 * [byte 5]  force       TRUE - directly access the device
Packit d14fb6
 *                       FALSE - go thru its controller
Packit d14fb6
 *                       Ignored if LED is local
Packit d14fb6
 * [byte 6]  role        Used by BMC for authorization purposes
Packit d14fb6
 *
Packit d14fb6
 * The format below is for Sun Blade Modular systems only
Packit d14fb6
 * [byte 5]  entityID    The entityID field from the SDR record
Packit d14fb6
 * [byte 6]  entityIns   The entityIns field from the SDR record
Packit d14fb6
 * [byte 7]  force       TRUE - directly access the device
Packit d14fb6
 *                       FALSE - go thru its controller
Packit d14fb6
 *                       Ignored if LED is local
Packit d14fb6
 * [byte 8]  role        Used by BMC for authorization purposes
Packit d14fb6
 *
Packit d14fb6
 *
Packit d14fb6
 * IPMI Response Data: 1 byte
Packit d14fb6
 *
Packit d14fb6
 * [byte 0]  mode     LED Mode: OFF, ON, STANDBY, SLOW, FAST
Packit d14fb6
 */
Packit d14fb6
Packit d14fb6
static int
Packit d14fb6
ipmi_sunoem_led_set(struct ipmi_intf * intf, int argc, char ** argv)
Packit d14fb6
{
Packit d14fb6
	struct ipmi_rs * rsp;
Packit d14fb6
	struct sdr_record_list *sdr;
Packit d14fb6
	struct sdr_record_list *alist, *a;
Packit d14fb6
	struct sdr_record_entity_assoc *assoc;
Packit d14fb6
	int ledmode;
Packit d14fb6
	int ledtype = 0xFF;
Packit d14fb6
	int i;
Packit d14fb6
Packit d14fb6
	/*
Packit d14fb6
	 * sunoem led/sbled set <id> <mode> [type]
Packit d14fb6
	 */
Packit d14fb6
Packit d14fb6
	if (argc < 2 || strncmp(argv[0], "help", 4) == 0) {
Packit d14fb6
		ipmi_sunoem_usage();
Packit d14fb6
		return (0);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	ledmode = str2val(argv[1], sunoem_led_mode_vals);
Packit d14fb6
	if (ledmode == 0xFF) {
Packit d14fb6
		ledmode = str2val(argv[1], sunoem_led_mode_optvals);
Packit d14fb6
		if (ledmode == 0xFF) {
Packit d14fb6
			lprintf(LOG_NOTICE, "Invalid LED Mode: %s", argv[1]);
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	if (argc > 3) {
Packit d14fb6
		ledtype = str2val(argv[2], sunoem_led_type_vals);
Packit d14fb6
		if (ledtype == 0xFF)
Packit d14fb6
			lprintf(LOG_ERR,
Packit d14fb6
					"Unknown ledtype, will use data from the SDR oem field");
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	if (strncasecmp(argv[0], "all", 3) == 0) {
Packit d14fb6
		/* do all generic sensors */
Packit d14fb6
		alist = ipmi_sdr_find_sdr_bytype(intf,
Packit d14fb6
		SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR);
Packit d14fb6
Packit d14fb6
		if (alist == NULL)
Packit d14fb6
			return (-1);
Packit d14fb6
Packit d14fb6
		for (a = alist; a != NULL; a = a->next) {
Packit d14fb6
			if (a->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR)
Packit d14fb6
				continue;
Packit d14fb6
			if (a->record.genloc->entity.logical)
Packit d14fb6
				continue;
Packit d14fb6
			rsp = sunoem_led_set(intf, a->record.genloc, ledtype, ledmode);
Packit d14fb6
			if (rsp && rsp->ccode == 0)
Packit d14fb6
				led_print((const char *) a->record.genloc->id_string,
Packit d14fb6
						PRINT_NORMAL, ledmode);
Packit d14fb6
			else
Packit d14fb6
				ret_set = -1;
Packit d14fb6
		}
Packit d14fb6
		__sdr_list_empty(alist);
Packit d14fb6
Packit d14fb6
		if (ret_set == -1)
Packit d14fb6
			return (-1);
Packit d14fb6
Packit d14fb6
		return (0);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	/* look up generic device locator records in SDR */
Packit d14fb6
	sdr = ipmi_sdr_find_sdr_byid(intf, argv[0]);
Packit d14fb6
Packit d14fb6
	if (sdr == NULL) {
Packit d14fb6
		lprintf(LOG_ERR, "No Sensor Data Record found for %s", argv[0]);
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	if (sdr->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR) {
Packit d14fb6
		lprintf(LOG_ERR, "Invalid SDR type %d", sdr->type);
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	if (!sdr->record.genloc->entity.logical) {
Packit d14fb6
		/*
Packit d14fb6
		 * handle physical entity
Packit d14fb6
		 */
Packit d14fb6
		rsp = sunoem_led_set(intf, sdr->record.genloc, ledtype, ledmode);
Packit d14fb6
		if (rsp && rsp->ccode == 0)
Packit d14fb6
			led_print(argv[0], PRINT_NORMAL, ledmode);
Packit d14fb6
		else
Packit d14fb6
			return (-1);
Packit d14fb6
Packit d14fb6
		return (0);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	/*
Packit d14fb6
	 * handle logical entity for LED grouping
Packit d14fb6
	 */
Packit d14fb6
Packit d14fb6
	lprintf(LOG_INFO, "LED %s is logical device", argv[0]);
Packit d14fb6
Packit d14fb6
	/* get entity assoc records */
Packit d14fb6
	alist = ipmi_sdr_find_sdr_bytype(intf, SDR_RECORD_TYPE_ENTITY_ASSOC);
Packit d14fb6
Packit d14fb6
	if (alist == NULL)
Packit d14fb6
		return (-1);
Packit d14fb6
Packit d14fb6
	for (a = alist; a != NULL; a = a->next) {
Packit d14fb6
		if (a->type != SDR_RECORD_TYPE_ENTITY_ASSOC)
Packit d14fb6
			continue;
Packit d14fb6
		assoc = a->record.entassoc;
Packit d14fb6
		if (assoc == NULL)
Packit d14fb6
			continue;
Packit d14fb6
Packit d14fb6
		/* check that the entity id/instance matches our generic record */
Packit d14fb6
		if (assoc->entity.id != sdr->record.genloc->entity.id
Packit d14fb6
				|| assoc->entity.instance
Packit d14fb6
						!= sdr->record.genloc->entity.instance)
Packit d14fb6
			continue;
Packit d14fb6
Packit d14fb6
		if (assoc->flags.isrange) {
Packit d14fb6
			/*
Packit d14fb6
			 * handle ranged entity associations
Packit d14fb6
			 *
Packit d14fb6
			 * the test for non-zero entity id is handled in
Packit d14fb6
			 * sunoem_led_get_byentity()
Packit d14fb6
			 */
Packit d14fb6
Packit d14fb6
			/* first range set - id 1 and 2 must be equal */
Packit d14fb6
			if (assoc->entity_id_1 == assoc->entity_id_2)
Packit d14fb6
				for (i = assoc->entity_inst_1; i <= assoc->entity_inst_2; i++)
Packit d14fb6
					sunoem_led_set_byentity(intf, assoc->entity_id_1, i,
Packit d14fb6
							ledtype, ledmode);
Packit d14fb6
Packit d14fb6
			/* second range set - id 3 and 4 must be equal */
Packit d14fb6
			if (assoc->entity_id_3 == assoc->entity_id_4)
Packit d14fb6
				for (i = assoc->entity_inst_3; i <= assoc->entity_inst_4; i++)
Packit d14fb6
					sunoem_led_set_byentity(intf, assoc->entity_id_3, i,
Packit d14fb6
							ledtype, ledmode);
Packit d14fb6
		} else {
Packit d14fb6
			/*
Packit d14fb6
			 * handle entity list
Packit d14fb6
			 */
Packit d14fb6
			sunoem_led_set_byentity(intf, assoc->entity_id_1,
Packit d14fb6
					assoc->entity_inst_1, ledtype, ledmode);
Packit d14fb6
			sunoem_led_set_byentity(intf, assoc->entity_id_2,
Packit d14fb6
					assoc->entity_inst_2, ledtype, ledmode);
Packit d14fb6
			sunoem_led_set_byentity(intf, assoc->entity_id_3,
Packit d14fb6
					assoc->entity_inst_3, ledtype, ledmode);
Packit d14fb6
			sunoem_led_set_byentity(intf, assoc->entity_id_4,
Packit d14fb6
					assoc->entity_inst_4, ledtype, ledmode);
Packit d14fb6
		}
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	__sdr_list_empty(alist);
Packit d14fb6
Packit d14fb6
	if (ret_set == -1)
Packit d14fb6
		return (-1);
Packit d14fb6
Packit d14fb6
	return (0);
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
static int
Packit d14fb6
ipmi_sunoem_sshkey_del(struct ipmi_intf * intf, uint8_t uid)
Packit d14fb6
{
Packit d14fb6
	struct ipmi_rs * rsp;
Packit d14fb6
	struct ipmi_rq req;
Packit d14fb6
Packit d14fb6
	memset(&req, 0, sizeof(struct ipmi_rq));
Packit d14fb6
	req.msg.netfn = IPMI_NETFN_SUNOEM;
Packit d14fb6
	req.msg.cmd = IPMI_SUNOEM_DEL_SSH_KEY;
Packit d14fb6
	req.msg.data = &ui;;
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, "Unable to delete ssh key for UID %d", uid);
Packit d14fb6
		return (-1);
Packit d14fb6
	} else if (rsp->ccode > 0) {
Packit d14fb6
		lprintf(LOG_ERR, "Unable to delete ssh key for UID %d: %s", uid,
Packit d14fb6
				val2str(rsp->ccode, completion_code_vals));
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	printf("Deleted SSH key for user id %d\n", uid);
Packit d14fb6
	return (0);
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
#define SSHKEY_BLOCK_SIZE	64
Packit d14fb6
static int
Packit d14fb6
ipmi_sunoem_sshkey_set(struct ipmi_intf * intf, uint8_t uid, char * ifile)
Packit d14fb6
{
Packit d14fb6
	struct ipmi_rs * rsp;
Packit d14fb6
	struct ipmi_rq req;
Packit d14fb6
	FILE * fp;
Packit d14fb6
	int count = 0;
Packit d14fb6
	uint8_t wbuf[SSHKEY_BLOCK_SIZE + 3];
Packit d14fb6
	int32_t i_size = 0;
Packit d14fb6
	int32_t r = 0;
Packit d14fb6
	int32_t size = 0;
Packit d14fb6
Packit d14fb6
	if (ifile == NULL) {
Packit d14fb6
		lprintf(LOG_ERR, "Invalid or misisng input filename.");
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	fp = ipmi_open_file_read(ifile);
Packit d14fb6
	if (fp == NULL) {
Packit d14fb6
		lprintf(LOG_ERR, "Unable to open file '%s' for reading.", ifile);
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	memset(&req, 0, sizeof(struct ipmi_rq));
Packit d14fb6
	req.msg.netfn = IPMI_NETFN_SUNOEM;
Packit d14fb6
	req.msg.cmd = IPMI_SUNOEM_SET_SSH_KEY;
Packit d14fb6
	req.msg.data = wbuf;
Packit d14fb6
Packit d14fb6
	if (fseek(fp, 0, SEEK_END) == (-1)) {
Packit d14fb6
		lprintf(LOG_ERR, "Failed to seek in file '%s'.", ifile);
Packit d14fb6
		if (fp != NULL)
Packit d14fb6
			fclose(fp);
Packit d14fb6
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	size = (int32_t) ftell(fp);
Packit d14fb6
	if (size < 0) {
Packit d14fb6
		lprintf(LOG_ERR, "Failed to seek in file '%s'.", ifile);
Packit d14fb6
		if (fp != NULL)
Packit d14fb6
			fclose(fp);
Packit d14fb6
Packit d14fb6
		return (-1);
Packit d14fb6
	} else if (size == 0) {
Packit d14fb6
		lprintf(LOG_ERR, "File '%s' is empty.", ifile);
Packit d14fb6
		if (fp != NULL)
Packit d14fb6
			fclose(fp);
Packit d14fb6
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	if (fseek(fp, 0, SEEK_SET) == (-1)) {
Packit d14fb6
		lprintf(LOG_ERR, "Failed to seek in file '%s'.", ifile);
Packit d14fb6
		if (fp != NULL)
Packit d14fb6
			fclose(fp);
Packit d14fb6
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	printf("Setting SSH key for user id %d...", uid);
Packit d14fb6
Packit d14fb6
	for (r = 0; r < size; r += i_size) {
Packit d14fb6
		i_size = size - r;
Packit d14fb6
		if (i_size > SSHKEY_BLOCK_SIZE)
Packit d14fb6
			i_size = SSHKEY_BLOCK_SIZE;
Packit d14fb6
Packit d14fb6
		memset(wbuf, 0, SSHKEY_BLOCK_SIZE);
Packit d14fb6
		fseek(fp, r, SEEK_SET);
Packit d14fb6
		count = fread(wbuf + 3, 1, i_size, fp);
Packit d14fb6
		if (count != i_size) {
Packit d14fb6
			printf("failed\n");
Packit d14fb6
			lprintf(LOG_ERR, "Unable to read %ld bytes from file '%s'.", i_size,
Packit d14fb6
					ifile);
Packit d14fb6
			if (fp != NULL)
Packit d14fb6
				fclose(fp);
Packit d14fb6
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
Packit d14fb6
		printf(".");
Packit d14fb6
		fflush(stdout);
Packit d14fb6
Packit d14fb6
		wbuf[0] = uid;
Packit d14fb6
		if ((r + SSHKEY_BLOCK_SIZE) >= size)
Packit d14fb6
			wbuf[1] = 0xff;
Packit d14fb6
		else {
Packit d14fb6
			if ((r / SSHKEY_BLOCK_SIZE) > UINT8_MAX) {
Packit d14fb6
				printf("failed\n");
Packit d14fb6
				lprintf(LOG_ERR, "Unable to pack byte %ld from file '%s'.", r,
Packit d14fb6
						ifile);
Packit d14fb6
				if (fp != NULL)
Packit d14fb6
					fclose(fp);
Packit d14fb6
Packit d14fb6
				return (-1);
Packit d14fb6
			}
Packit d14fb6
			wbuf[1] = (uint8_t) (r / SSHKEY_BLOCK_SIZE);
Packit d14fb6
		}
Packit d14fb6
Packit d14fb6
		wbuf[2] = (uint8_t) i_size;
Packit d14fb6
Packit d14fb6
		req.msg.data_len = i_size + 3;
Packit d14fb6
Packit d14fb6
		rsp = intf->sendrecv(intf, &req;;
Packit d14fb6
		if (rsp == NULL) {
Packit d14fb6
			printf("failed\n");
Packit d14fb6
			lprintf(LOG_ERR, "Unable to set ssh key for UID %d.", uid);
Packit d14fb6
			if (fp != NULL)
Packit d14fb6
				fclose(fp);
Packit d14fb6
Packit d14fb6
			return (-1);
Packit d14fb6
		} /* if (rsp == NULL) */
Packit d14fb6
		if (rsp->ccode != 0) {
Packit d14fb6
			printf("failed\n");
Packit d14fb6
			lprintf(LOG_ERR, "Unable to set ssh key for UID %d, %s.", uid,
Packit d14fb6
					val2str(rsp->ccode, completion_code_vals));
Packit d14fb6
			if (fp != NULL)
Packit d14fb6
				fclose(fp);
Packit d14fb6
Packit d14fb6
			return (-1);
Packit d14fb6
		} /* if (rsp->ccode != 0) */
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	printf("done\n");
Packit d14fb6
Packit d14fb6
	fclose(fp);
Packit d14fb6
	return (0);
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
/*
Packit d14fb6
 * This structure is used in both the request to and response from the BMC.
Packit d14fb6
 */
Packit d14fb6
#define SUNOEM_CLI_LEGACY_VERSION       1
Packit d14fb6
#define SUNOEM_CLI_SEQNUM_VERSION       2
Packit d14fb6
#define SUNOEM_CLI_VERSION       SUNOEM_CLI_SEQNUM_VERSION
Packit d14fb6
#define SUNOEM_CLI_HEADER        8 /* command + spare + handle */
Packit d14fb6
#define SUNOEM_CLI_BUF_SIZE      (80 - SUNOEM_CLI_HEADER) /* Total 80 bytes */
Packit d14fb6
#define SUNOEM_CLI_MSG_SIZE(msg) (SUNOEM_CLI_HEADER + strlen((msg).buf) + 1)
Packit d14fb6
Packit d14fb6
#ifdef HAVE_PRAGMA_PACK
Packit d14fb6
#pragma pack(push, 1)
Packit d14fb6
#endif
Packit d14fb6
typedef struct
Packit d14fb6
{
Packit d14fb6
	/*
Packit d14fb6
	 * Set version to SUNOEM_CLI_VERSION.
Packit d14fb6
	 */
Packit d14fb6
	uint8_t version;
Packit d14fb6
	/*
Packit d14fb6
	 * The command in a request, or in a response indicates an error if
Packit d14fb6
	 * non-zero.
Packit d14fb6
	 */
Packit d14fb6
	uint8_t command_response;
Packit d14fb6
	uint8_t seqnum;
Packit d14fb6
	uint8_t spare;
Packit d14fb6
	/*
Packit d14fb6
	 * Opaque 4-byte handle, supplied in the response to an OPEN request,
Packit d14fb6
	 * and used in all subsequent POLL and CLOSE requests.
Packit d14fb6
	 */
Packit d14fb6
	uint8_t handle[4];
Packit d14fb6
	/*
Packit d14fb6
	 * The client data in a request, or the server data in a response. Must
Packit d14fb6
	 * by null terminated, i.e., it must be at least one byte, but can be
Packit d14fb6
	 * smaller if there's less data.
Packit d14fb6
	 */
Packit d14fb6
	char buf[SUNOEM_CLI_BUF_SIZE];
Packit d14fb6
}__attribute__((packed)) sunoem_cli_msg_t;
Packit d14fb6
#ifdef HAVE_PRAGMA_PACK
Packit d14fb6
#pragma pack(pop)
Packit d14fb6
#endif
Packit d14fb6
Packit d14fb6
/*
Packit d14fb6
 * Command codes for the command_request field in each request.
Packit d14fb6
 */
Packit d14fb6
#define SUNOEM_CLI_CMD_OPEN   0 /* Open a new connection */
Packit d14fb6
#define SUNOEM_CLI_CMD_FORCE  1 /* Close any existing connection, then open */
Packit d14fb6
#define SUNOEM_CLI_CMD_CLOSE  2 /* Close the current connection */
Packit d14fb6
#define SUNOEM_CLI_CMD_POLL   3 /* Poll for new data to/from the server */
Packit d14fb6
#define SUNOEM_CLI_CMD_EOF    4 /* Poll, client is out of data */
Packit d14fb6
Packit d14fb6
#define SUNOEM_CLI_MAX_RETRY  3 /* Maximum number of retries */
Packit d14fb6
Packit d14fb6
#define SUNOEM_CLI_INVALID_VER_ERR "Invalid version"
Packit d14fb6
#define SUNOEM_CLI_BUSY_ERR        "Busy"
Packit d14fb6
Packit d14fb6
typedef enum
Packit d14fb6
{
Packit d14fb6
	C_CTL_B = 0x02, /* same as left arrow */
Packit d14fb6
	C_CTL_C = 0x03,
Packit d14fb6
	C_CTL_D = 0x04,
Packit d14fb6
	C_CTL_F = 0x06, /* same as right arrow */
Packit d14fb6
	C_CTL_N = 0x0E, /* same as down arrow */
Packit d14fb6
	C_CTL_P = 0x10, /* same as up arrow */
Packit d14fb6
	C_DEL = 0x7f
Packit d14fb6
} canon_char_t;
Packit d14fb6
Packit d14fb6
static int
Packit d14fb6
sunoem_cli_unbufmode_start(FILE *f, struct termios *orig_ts)
Packit d14fb6
{
Packit d14fb6
	struct termios ts;
Packit d14fb6
	int rc;
Packit d14fb6
Packit d14fb6
	if ((rc = tcgetattr(fileno(f), &ts))) {
Packit d14fb6
		return (rc);
Packit d14fb6
	}
Packit d14fb6
	*orig_ts = ts;
Packit d14fb6
	ts.c_lflag &= ~(ICANON | ECHO | ISIG);
Packit d14fb6
	ts.c_cc[VMIN] = 1;
Packit d14fb6
	if ((rc = tcsetattr(fileno(f), TCSAFLUSH, &ts))) {
Packit d14fb6
		return (rc);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	return (0);
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
static int
Packit d14fb6
sunoem_cli_unbufmode_stop(FILE *f, struct termios *ts)
Packit d14fb6
{
Packit d14fb6
	int rc;
Packit d14fb6
Packit d14fb6
	if ((rc = tcsetattr(fileno(f), TCSAFLUSH, ts))) {
Packit d14fb6
		return (rc);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	return (0);
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
static int
Packit d14fb6
ipmi_sunoem_cli(struct ipmi_intf * intf, int argc, char *argv[])
Packit d14fb6
{
Packit d14fb6
	struct ipmi_rs *rsp;
Packit d14fb6
	struct ipmi_rq req;
Packit d14fb6
	sunoem_cli_msg_t cli_req;
Packit d14fb6
	sunoem_cli_msg_t *cli_rsp;
Packit d14fb6
	int arg_num = 0;
Packit d14fb6
	int arg_pos = 0;
Packit d14fb6
	time_t wait_time = 0;
Packit d14fb6
	int retries;
Packit d14fb6
	static uint8_t SunOemCliActingVersion = SUNOEM_CLI_VERSION;
Packit d14fb6
Packit d14fb6
	unsigned short first_char = 0; /*first char on the line*/
Packit d14fb6
	struct termios orig_ts;
Packit d14fb6
	int error = 0;
Packit d14fb6
Packit d14fb6
	time_t now = 0;
Packit d14fb6
	int delay = 0;
Packit d14fb6
Packit d14fb6
	/* Prepare to open an SP shell session */
Packit d14fb6
	memset(&cli_req, 0, sizeof(cli_req));
Packit d14fb6
	cli_req.version = SunOemCliActingVersion;
Packit d14fb6
	cli_req.command_response = SUNOEM_CLI_CMD_OPEN;
Packit d14fb6
	if (argc > 0 && strcmp(argv[0], "force") == 0) {
Packit d14fb6
		cli_req.command_response = SUNOEM_CLI_CMD_FORCE;
Packit d14fb6
		argc--;
Packit d14fb6
		argv++;
Packit d14fb6
	}
Packit d14fb6
	memset(&req, 0, sizeof(req));
Packit d14fb6
	req.msg.netfn = IPMI_NETFN_SUNOEM;
Packit d14fb6
	req.msg.cmd = IPMI_SUNOEM_CLI;
Packit d14fb6
	req.msg.data = (uint8_t *) &cli_req;
Packit d14fb6
	req.msg.data_len = SUNOEM_CLI_HEADER + 1;
Packit d14fb6
	retries = 0;
Packit d14fb6
	while (1) {
Packit d14fb6
		cli_req.version = SunOemCliActingVersion;
Packit d14fb6
		rsp = intf->sendrecv(intf, &req;;
Packit d14fb6
		if (rsp == NULL) {
Packit d14fb6
			lprintf(LOG_ERR, "Sun OEM cli command failed");
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
		cli_rsp = (sunoem_cli_msg_t *) rsp->data;
Packit d14fb6
		if ((cli_rsp->command_response != 0) || (rsp->ccode != 0)) {
Packit d14fb6
			if (strncmp(cli_rsp->buf, SUNOEM_CLI_INVALID_VER_ERR,
Packit d14fb6
					sizeof(SUNOEM_CLI_INVALID_VER_ERR) - 1) == 0
Packit d14fb6
					|| strncmp(&(cli_rsp->buf[1]), SUNOEM_CLI_INVALID_VER_ERR,
Packit d14fb6
							sizeof(SUNOEM_CLI_INVALID_VER_ERR) - 1) == 0) {
Packit d14fb6
				if (SunOemCliActingVersion == SUNOEM_CLI_VERSION) {
Packit d14fb6
					/* Server doesn't support version SUNOEM_CLI_VERSION
Packit d14fb6
					 Fall back to legacy version, and try again*/
Packit d14fb6
					SunOemCliActingVersion = SUNOEM_CLI_LEGACY_VERSION;
Packit d14fb6
					continue;
Packit d14fb6
				}
Packit d14fb6
				/* Server doesn't support legacy version either */
Packit d14fb6
				lprintf(LOG_ERR, "Failed to connect: %s", cli_rsp->buf);
Packit d14fb6
				return (-1);
Packit d14fb6
			} else if (strncmp(cli_rsp->buf, SUNOEM_CLI_BUSY_ERR,
Packit d14fb6
					sizeof(SUNOEM_CLI_BUSY_ERR) - 1) == 0) {
Packit d14fb6
				if (retries++ < SUNOEM_CLI_MAX_RETRY) {
Packit d14fb6
					lprintf(LOG_INFO, "Failed to connect: %s, retrying",
Packit d14fb6
							cli_rsp->buf);
Packit d14fb6
					sleep(2);
Packit d14fb6
					continue;
Packit d14fb6
				}
Packit d14fb6
				lprintf(LOG_ERR, "Failed to connect: %s", cli_rsp->buf);
Packit d14fb6
				return (-1);
Packit d14fb6
			} else {
Packit d14fb6
				lprintf(LOG_ERR, "Failed to connect: %s", cli_rsp->buf);
Packit d14fb6
				return (-1);
Packit d14fb6
			}
Packit d14fb6
		}
Packit d14fb6
		break;
Packit d14fb6
	}
Packit d14fb6
	if (SunOemCliActingVersion == SUNOEM_CLI_SEQNUM_VERSION) {
Packit d14fb6
		/*
Packit d14fb6
		 * Bit 1 of seqnum is used as an alternating sequence number
Packit d14fb6
		 * to allow a server that supports it to detect when a retry is being sent from the host IPMI driver.
Packit d14fb6
		 * Typically when this occurs, the server's last response message would have been dropped.
Packit d14fb6
		 * Once the server detects this condition, it will know that it should retry sending the response.
Packit d14fb6
		 */
Packit d14fb6
		cli_req.seqnum ^= 0x1;
Packit d14fb6
	}
Packit d14fb6
	printf("Connected. Use ^D to exit.\n");
Packit d14fb6
	fflush(NULL);
Packit d14fb6
Packit d14fb6
	/*
Packit d14fb6
	 * Remember the handle provided in the response, and issue a
Packit d14fb6
	 * series of "poll" commands to send and get data
Packit d14fb6
	 */
Packit d14fb6
	memcpy(cli_req.handle, cli_rsp->handle, 4);
Packit d14fb6
	cli_req.command_response = SUNOEM_CLI_CMD_POLL;
Packit d14fb6
	/*
Packit d14fb6
	 * If no arguments make input unbuffered and so interactive
Packit d14fb6
	 */
Packit d14fb6
	if (argc == 0) {
Packit d14fb6
		if (sunoem_cli_unbufmode_start(stdin, &orig_ts)) {
Packit d14fb6
			lprintf(LOG_ERR, "Failed to set interactive mode: %s",
Packit d14fb6
					strerror(errno));
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
	}
Packit d14fb6
	while (rsp->ccode == 0 && cli_rsp->command_response == 0) {
Packit d14fb6
		int rc = 0;
Packit d14fb6
		int count = 0;
Packit d14fb6
		cli_req.buf[0] = '\0';
Packit d14fb6
		if (argc == 0) {
Packit d14fb6
			/*
Packit d14fb6
			 * Accept input from stdin. Use select so we don't hang if
Packit d14fb6
			 * there's no input to read. Select timeout is 500 msec.
Packit d14fb6
			 */
Packit d14fb6
			struct timeval tv = { 0, 500000 }; /* 500 msec */
Packit d14fb6
			fd_set rfds;
Packit d14fb6
			FD_ZERO(&rfds);
Packit d14fb6
			FD_SET(0, &rfds);
Packit d14fb6
			rc = select(1, &rfds, NULL, NULL, &tv;;
Packit d14fb6
			if (rc < 0) {
Packit d14fb6
				/* Select returned an error so close and exit */
Packit d14fb6
				printf("Broken pipe\n");
Packit d14fb6
				cli_req.command_response = SUNOEM_CLI_CMD_CLOSE;
Packit d14fb6
			} else if (rc > 0) {
Packit d14fb6
				/* Read data from stdin */
Packit d14fb6
				count = read(0, cli_req.buf, 1 /* sizeof (cli_req.buf) - 1 */);
Packit d14fb6
				/*
Packit d14fb6
				 * If select said there was data but there was nothing to
Packit d14fb6
				 * read. This implies user hit ^D.
Packit d14fb6
				 * Also handle ^D input when pressed as first char at a new line.
Packit d14fb6
				 */
Packit d14fb6
				if (count <= 0 || (first_char && cli_req.buf[0] == C_CTL_D)) {
Packit d14fb6
					cli_req.command_response = SUNOEM_CLI_CMD_EOF;
Packit d14fb6
					count = 0;
Packit d14fb6
				}
Packit d14fb6
				first_char = cli_req.buf[0] == '\n' || cli_req.buf[0] == '\r';
Packit d14fb6
			}
Packit d14fb6
		} else {
Packit d14fb6
			/*
Packit d14fb6
			 * Get data from command line arguments
Packit d14fb6
			 */
Packit d14fb6
			now = time(NULL);
Packit d14fb6
			if (now < wait_time) {
Packit d14fb6
				/* Do nothing; we're waiting */
Packit d14fb6
			} else if (arg_num >= argc) {
Packit d14fb6
				/* Last arg was sent. Set EOF */
Packit d14fb6
				cli_req.command_response = SUNOEM_CLI_CMD_EOF;
Packit d14fb6
			} else if (strncmp(argv[arg_num], "@wait=", 6) == 0) {
Packit d14fb6
				/* This is a wait command */
Packit d14fb6
				char *s = &argv[arg_num][6];
Packit d14fb6
				delay = 0;
Packit d14fb6
				if (*s != '\0') {
Packit d14fb6
					if (str2int(s, &delay)) {
Packit d14fb6
						delay = 0;
Packit d14fb6
					}
Packit d14fb6
					if (delay < 0) {
Packit d14fb6
						delay = 0;
Packit d14fb6
					}
Packit d14fb6
				}
Packit d14fb6
				wait_time = now + delay;
Packit d14fb6
				arg_num++;
Packit d14fb6
			} else {
Packit d14fb6
				/*
Packit d14fb6
				 * Take data from args. It may be that the argument is larger
Packit d14fb6
				 * than the request buffer can hold. So pull off BUF_SIZE
Packit d14fb6
				 * number of characters at a time. When we've consumed the
Packit d14fb6
				 * entire arg, append a newline and advance to the next arg.
Packit d14fb6
				 */
Packit d14fb6
				int i;
Packit d14fb6
				char *s = argv[arg_num];
Packit d14fb6
				for (i = arg_pos;
Packit d14fb6
						s[i] != '\0' && count < (SUNOEM_CLI_BUF_SIZE - 2);
Packit d14fb6
						i++, count++) {
Packit d14fb6
					cli_req.buf[count] = s[i];
Packit d14fb6
				}
Packit d14fb6
				if (s[i] == '\0') {
Packit d14fb6
					/* Reached end of the arg string, so append a newline */
Packit d14fb6
					cli_req.buf[count++] = '\n';
Packit d14fb6
					/* Reset pos to 0 and advance to the next arg next time */
Packit d14fb6
					arg_pos = 0;
Packit d14fb6
					arg_num++;
Packit d14fb6
				} else {
Packit d14fb6
					/*
Packit d14fb6
					 * Otherwise, there's still more characters in the arg
Packit d14fb6
					 * to send, so remember where we left off
Packit d14fb6
					 */
Packit d14fb6
					arg_pos = i;
Packit d14fb6
				}
Packit d14fb6
			}
Packit d14fb6
		}
Packit d14fb6
		/*
Packit d14fb6
		 * Now send the clients's data (if any) and get data back from the
Packit d14fb6
		 * server. Loop while the server is giving us data until we suck
Packit d14fb6
		 * it dry.
Packit d14fb6
		 */
Packit d14fb6
		do {
Packit d14fb6
			cli_req.buf[count++] = '\0'; /* Terminate the string */
Packit d14fb6
			memset(&req, 0, sizeof(req));
Packit d14fb6
			req.msg.netfn = IPMI_NETFN_SUNOEM;
Packit d14fb6
			req.msg.cmd = 0x19;
Packit d14fb6
			req.msg.data = (uint8_t *) &cli_req;
Packit d14fb6
			req.msg.data_len = SUNOEM_CLI_HEADER + count;
Packit d14fb6
			for (retries = 0; retries <= SUNOEM_CLI_MAX_RETRY; retries++) {
Packit d14fb6
				rsp = intf->sendrecv(intf, &req;;
Packit d14fb6
				if (rsp == NULL) {
Packit d14fb6
					lprintf(LOG_ERR, "Communication error.");
Packit d14fb6
					error = 1;
Packit d14fb6
					goto cleanup;
Packit d14fb6
				}
Packit d14fb6
				if (rsp->ccode == IPMI_CC_TIMEOUT) { /* Retry if timed out. */
Packit d14fb6
					if (retries == SUNOEM_CLI_MAX_RETRY) { /* If it's the last retry. */
Packit d14fb6
						lprintf(LOG_ERR, "Excessive timeout.");
Packit d14fb6
						error = 1;
Packit d14fb6
						goto cleanup;
Packit d14fb6
					}
Packit d14fb6
					continue;
Packit d14fb6
				}
Packit d14fb6
				break;
Packit d14fb6
			} /* for (retries = 0; retries <= SUNOEM_CLI_MAX_RETRY; retries++) */
Packit d14fb6
Packit d14fb6
			if (SunOemCliActingVersion == SUNOEM_CLI_SEQNUM_VERSION) {
Packit d14fb6
				cli_req.seqnum ^= 0x1; /* Toggle sequence number after request is sent */
Packit d14fb6
			}
Packit d14fb6
Packit d14fb6
			cli_rsp = (sunoem_cli_msg_t *) rsp->data;
Packit d14fb6
			/* Make sure response string is null terminated */
Packit d14fb6
			cli_rsp->buf[sizeof(cli_rsp->buf) - 1] = '\0';
Packit d14fb6
			printf("%s", cli_rsp->buf);
Packit d14fb6
			fflush(NULL); /* Flush partial lines to stdout */
Packit d14fb6
			count = 0; /* Don't re-send the client's data */
Packit d14fb6
			if (cli_req.command_response == SUNOEM_CLI_CMD_EOF
Packit d14fb6
					&& cli_rsp->command_response != 0 && rsp->ccode == 0) {
Packit d14fb6
				cli_rsp->command_response = 1;
Packit d14fb6
			}
Packit d14fb6
		} while (cli_rsp->command_response == 0 && cli_rsp->buf[0] != '\0');
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
cleanup:
Packit d14fb6
	/* Restore original input mode if cli was running interactively */
Packit d14fb6
	if (argc == 0) {
Packit d14fb6
		if (sunoem_cli_unbufmode_stop(stdin, &orig_ts)) {
Packit d14fb6
			lprintf(LOG_ERR, "Failed to restore interactive mode: %s",
Packit d14fb6
					strerror(errno));
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	return ((error == 0 && cli_rsp->command_response == SUNOEM_SUCCESS) ? 0 : -1);
Packit d14fb6
}
Packit d14fb6
#define ECHO_DATA_SIZE 64
Packit d14fb6
Packit d14fb6
#ifdef HAVE_PRAGMA_PACK
Packit d14fb6
#pragma pack(push, 1)
Packit d14fb6
#endif
Packit d14fb6
typedef struct
Packit d14fb6
{
Packit d14fb6
	uint16_t seq_num;
Packit d14fb6
	unsigned char data[ECHO_DATA_SIZE];
Packit d14fb6
}__attribute__((packed)) sunoem_echo_msg_t;
Packit d14fb6
#ifdef HAVE_PRAGMA_PACK
Packit d14fb6
#pragma pack(pop)
Packit d14fb6
#endif
Packit d14fb6
Packit d14fb6
/*
Packit d14fb6
 * Send and receive X packets to the BMC. Each packet has a
Packit d14fb6
 * payload size of (sunoem_echo_msg_t) bytes. Each packet is tagged with a
Packit d14fb6
 * sequence number
Packit d14fb6
 */
Packit d14fb6
static int
Packit d14fb6
ipmi_sunoem_echo(struct ipmi_intf * intf, int argc, char *argv[])
Packit d14fb6
{
Packit d14fb6
	struct ipmi_rs *rsp;
Packit d14fb6
	struct ipmi_rq req;
Packit d14fb6
	sunoem_echo_msg_t echo_req;
Packit d14fb6
	sunoem_echo_msg_t *echo_rsp;
Packit d14fb6
	struct timeval start_time;
Packit d14fb6
	struct timeval end_time;
Packit d14fb6
Packit d14fb6
	int rc = 0;
Packit d14fb6
	int received = 0;
Packit d14fb6
	int transmitted = 0;
Packit d14fb6
	int quiet_mode = 0;
Packit d14fb6
Packit d14fb6
	uint16_t num, i, j;
Packit d14fb6
	uint32_t total_time, resp_time, min_time, max_time;
Packit d14fb6
Packit d14fb6
	if (argc < 1) {
Packit d14fb6
		return (1);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	if (argc == 2) {
Packit d14fb6
		if (*(argv[1]) == 'q') {
Packit d14fb6
			quiet_mode = 1;
Packit d14fb6
		} else {
Packit d14fb6
			lprintf(LOG_ERR, "Unknown option '%s' given.", argv[1]);
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
	} else if (argc > 2) {
Packit d14fb6
		lprintf(LOG_ERR,
Packit d14fb6
				"Too many parameters given. See help for more information.");
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
	/* The number of packets to send/receive */
Packit d14fb6
	if (str2ushort(argv[0], &num) != 0) {
Packit d14fb6
		lprintf(LOG_ERR,
Packit d14fb6
				"Given number of packets is either invalid or out of range.");
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	/* Fill in data packet */
Packit d14fb6
	for (i = 0; i < ECHO_DATA_SIZE; i++) {
Packit d14fb6
		echo_req.data[i] = (uint8_t) i;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	memset(&req, 0, sizeof(req));
Packit d14fb6
	req.msg.netfn = IPMI_NETFN_SUNOEM;
Packit d14fb6
	req.msg.cmd = IPMI_SUNOEM_ECHO;
Packit d14fb6
	req.msg.data = (uint8_t *) &echo_req;
Packit d14fb6
	req.msg.data_len = sizeof(sunoem_echo_msg_t);
Packit d14fb6
	echo_req.seq_num = i;
Packit d14fb6
	min_time = INT_MAX;
Packit d14fb6
	max_time = 0;
Packit d14fb6
	total_time = 0;
Packit d14fb6
	for (i = 0; i < num; i++) {
Packit d14fb6
		echo_req.seq_num = i;
Packit d14fb6
		transmitted++;
Packit d14fb6
		gettimeofday(&start_time, NULL);
Packit d14fb6
		rsp = intf->sendrecv(intf, &req;;
Packit d14fb6
		gettimeofday(&end_time, NULL);
Packit d14fb6
		resp_time = ((end_time.tv_sec - start_time.tv_sec) * 1000)
Packit d14fb6
				+ ((end_time.tv_usec - start_time.tv_usec) / 1000);
Packit d14fb6
		if ((rsp == NULL) || (rsp->ccode != 0)) {
Packit d14fb6
			lprintf(LOG_ERR, "Sun OEM echo command failed. Seq # %d",
Packit d14fb6
					echo_req.seq_num);
Packit d14fb6
			rc = (-2);
Packit d14fb6
			break;
Packit d14fb6
		}
Packit d14fb6
		echo_rsp = (sunoem_echo_msg_t *) rsp->data;
Packit d14fb6
Packit d14fb6
		/* Test if sequence # is valid */
Packit d14fb6
		if (echo_rsp->seq_num != echo_req.seq_num) {
Packit d14fb6
			printf("Invalid Seq # Expecting %d Received %d\n", echo_req.seq_num,
Packit d14fb6
					echo_rsp->seq_num);
Packit d14fb6
			rc = (-2);
Packit d14fb6
			break;
Packit d14fb6
		}
Packit d14fb6
Packit d14fb6
		/* Test if response length is valid */
Packit d14fb6
		if (rsp->session.msglen == req.msg.data_len) {
Packit d14fb6
			printf("Invalid payload size for seq # %d. "
Packit d14fb6
					"Expecting %d Received %d\n", echo_rsp->seq_num,
Packit d14fb6
					req.msg.data_len, rsp->session.msglen);
Packit d14fb6
			rc = (-2);
Packit d14fb6
			break;
Packit d14fb6
		}
Packit d14fb6
Packit d14fb6
		/* Test if the data is valid */
Packit d14fb6
		for (j = 0; j < ECHO_DATA_SIZE; j++) {
Packit d14fb6
			if (echo_rsp->data[j] != j) {
Packit d14fb6
				printf("Corrupt data packet. Seq # %d Offset %d\n",
Packit d14fb6
						echo_rsp->seq_num, j);
Packit d14fb6
				break;
Packit d14fb6
			}
Packit d14fb6
		} /* for (j = 0; j < ECHO_DATA_SIZE; j++) */
Packit d14fb6
Packit d14fb6
		/* If the for loop terminated early - data is corrupt */
Packit d14fb6
		if (j != ECHO_DATA_SIZE) {
Packit d14fb6
			rc = (-2);
Packit d14fb6
			break;
Packit d14fb6
		}
Packit d14fb6
Packit d14fb6
		/* cumalative time */
Packit d14fb6
		total_time += resp_time;
Packit d14fb6
Packit d14fb6
		/* min time */
Packit d14fb6
		if (resp_time < min_time) {
Packit d14fb6
			min_time = resp_time;
Packit d14fb6
		}
Packit d14fb6
Packit d14fb6
		/* max time */
Packit d14fb6
		if (resp_time > max_time) {
Packit d14fb6
			max_time = resp_time;
Packit d14fb6
		}
Packit d14fb6
Packit d14fb6
		received++;
Packit d14fb6
		if (!quiet_mode) {
Packit d14fb6
			printf("Receive %lu Bytes - Seq. # %d time=%d ms\n",
Packit d14fb6
					sizeof(sunoem_echo_msg_t), echo_rsp->seq_num, resp_time);
Packit d14fb6
		}
Packit d14fb6
	} /* for (i = 0; i < num; i++) */
Packit d14fb6
	printf("%d packets transmitted, %d packets received\n", transmitted,
Packit d14fb6
			received);
Packit d14fb6
	if (received) {
Packit d14fb6
		printf("round-trip min/avg/max = %d/%d/%d ms\n", min_time,
Packit d14fb6
				total_time / received, max_time);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	return (rc);
Packit d14fb6
} /* ipmi_sunoem_echo(...) */
Packit d14fb6
Packit d14fb6
#ifdef HAVE_PRAGMA_PACK
Packit d14fb6
#pragma pack(push, 1)
Packit d14fb6
#endif
Packit d14fb6
typedef struct
Packit d14fb6
{
Packit d14fb6
	unsigned char oem_record_ver_num;
Packit d14fb6
	unsigned char major;
Packit d14fb6
	unsigned char minor;
Packit d14fb6
	unsigned char update;
Packit d14fb6
	unsigned char micro;
Packit d14fb6
	char nano[10];
Packit d14fb6
	char revision[10];
Packit d14fb6
	char version[40];
Packit d14fb6
	/*
Packit d14fb6
	 * When adding new fields (using the spare bytes),
Packit d14fb6
	 * add it immediately after the spare field to
Packit d14fb6
	 * ensure backward compatability.
Packit d14fb6
	 *
Packit d14fb6
	 * e.g.   char version[40];
Packit d14fb6
	 *        unsigned char spare[11];
Packit d14fb6
	 *        int new_item;
Packit d14fb6
	 *    } sunoem_version_response_t;
Packit d14fb6
	 */
Packit d14fb6
	unsigned char spare[15];
Packit d14fb6
}__attribute__((packed)) sunoem_version_response_t;
Packit d14fb6
#ifdef HAVE_PRAGMA_PACK
Packit d14fb6
#pragma pack(pop)
Packit d14fb6
#endif
Packit d14fb6
Packit d14fb6
typedef struct
Packit d14fb6
{
Packit d14fb6
	unsigned char major;
Packit d14fb6
	unsigned char minor;
Packit d14fb6
	unsigned char update;
Packit d14fb6
	unsigned char micro;
Packit d14fb6
} supported_version_t;
Packit d14fb6
Packit d14fb6
static int
Packit d14fb6
ipmi_sunoem_getversion(struct ipmi_intf * intf,
Packit d14fb6
		sunoem_version_response_t **version_rsp)
Packit d14fb6
{
Packit d14fb6
	struct ipmi_rs *rsp;
Packit d14fb6
	struct ipmi_rq req;
Packit d14fb6
Packit d14fb6
	memset(&req, 0, sizeof(req));
Packit d14fb6
	req.msg.netfn = IPMI_NETFN_SUNOEM;
Packit d14fb6
	req.msg.cmd = IPMI_SUNOEM_VERSION;
Packit d14fb6
	req.msg.data = NULL;
Packit d14fb6
	req.msg.data_len = 0;
Packit d14fb6
	rsp = intf->sendrecv(intf, &req;;
Packit d14fb6
Packit d14fb6
	if (rsp == NULL) {
Packit d14fb6
		lprintf(LOG_ERR, "Sun OEM Get SP Version Failed.");
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
	if (rsp->ccode != 0) {
Packit d14fb6
		lprintf(LOG_ERR, "Sun OEM Get SP Version Failed: %d", rsp->ccode);
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	*version_rsp = (sunoem_version_response_t *) rsp->data;
Packit d14fb6
Packit d14fb6
	return (0);
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
static void
Packit d14fb6
ipmi_sunoem_print_required_version(const supported_version_t* supp_ver)
Packit d14fb6
{
Packit d14fb6
	lprintf(LOG_ERR, "Command is not supported by this version of ILOM,"
Packit d14fb6
			" required at least: %d.%d.%d.%d", supp_ver->major, supp_ver->minor,
Packit d14fb6
			supp_ver->update, supp_ver->micro);
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
/*
Packit d14fb6
 * Function checks current version result against required version.
Packit d14fb6
 * Returns:
Packit d14fb6
 *  - negative value if current ILOM version is smaller than required or
Packit d14fb6
 *    in case of error
Packit d14fb6
 *  - positive value if current ILOM version is greater than required
Packit d14fb6
 *  - 0 if there is an exact ILOM version match
Packit d14fb6
 */
Packit d14fb6
static int
Packit d14fb6
ipmi_sunoem_checkversion(struct ipmi_intf * intf, supported_version_t* supp_ver)
Packit d14fb6
{
Packit d14fb6
	sunoem_version_response_t *version_rsp;
Packit d14fb6
	int i = 1;
Packit d14fb6
Packit d14fb6
	if (ipmi_sunoem_getversion(intf, &version_rsp)) {
Packit d14fb6
		lprintf(LOG_ERR, "Unable to get ILOM version");
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	if (version_rsp->major < supp_ver->major) return (-i);
Packit d14fb6
	if (version_rsp->major > supp_ver->major) return (i);
Packit d14fb6
	/*version_rsp->major == supp_ver->major*/
Packit d14fb6
	++i;
Packit d14fb6
Packit d14fb6
	if (version_rsp->minor < supp_ver->minor) return (-i);
Packit d14fb6
	if (version_rsp->minor > supp_ver->minor) return (i);
Packit d14fb6
	/*version_rsp->minor == supp_ver->minor*/
Packit d14fb6
	++i;
Packit d14fb6
Packit d14fb6
	if (version_rsp->update < supp_ver->update) return (-i);
Packit d14fb6
	if (version_rsp->update > supp_ver->update) return (i);
Packit d14fb6
	/*version_rsp->update == supp_ver->update*/
Packit d14fb6
	++i;
Packit d14fb6
Packit d14fb6
	if (version_rsp->micro < supp_ver->micro) return (-i);
Packit d14fb6
	if (version_rsp->micro > supp_ver->micro) return (i);
Packit d14fb6
	/*version_rsp->micro == supp_ver->micro*/
Packit d14fb6
Packit d14fb6
	return (0);
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
/*
Packit d14fb6
 * Extract the SP version data including
Packit d14fb6
 * - major #
Packit d14fb6
 * - minor #
Packit d14fb6
 * - update #
Packit d14fb6
 * - micro #
Packit d14fb6
 * - nano #
Packit d14fb6
 * - Revision/Build #
Packit d14fb6
 */
Packit d14fb6
static int
Packit d14fb6
ipmi_sunoem_version(struct ipmi_intf * intf)
Packit d14fb6
{
Packit d14fb6
	sunoem_version_response_t *version_rsp;
Packit d14fb6
	int rc = ipmi_sunoem_getversion(intf, &version_rsp);
Packit d14fb6
Packit d14fb6
	if (!rc) {
Packit d14fb6
		printf("Version: %s\n", version_rsp->version);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	return (rc);
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
/*
Packit d14fb6
 * IPMI Max string length is 16 bytes
Packit d14fb6
 * define in usr/src/common/include/ami/IPMI_SDRRecord.h
Packit d14fb6
 */
Packit d14fb6
#define MAX_ID_STR_LEN  16
Packit d14fb6
#define MAX_SUNOEM_NAC_SIZE 64
Packit d14fb6
#define LUAPI_MAX_OBJ_PATH_LEN 256
Packit d14fb6
#define LUAPI_MAX_OBJ_VAL_LEN 1024
Packit d14fb6
Packit d14fb6
#ifdef HAVE_PRAGMA_PACK
Packit d14fb6
#pragma pack(push, 1)
Packit d14fb6
#endif
Packit d14fb6
typedef struct
Packit d14fb6
{
Packit d14fb6
	unsigned char seq_num;
Packit d14fb6
	char nac_name[MAX_SUNOEM_NAC_SIZE];
Packit d14fb6
}__attribute__((packed)) sunoem_nacname_t;
Packit d14fb6
#ifdef HAVE_PRAGMA_PACK
Packit d14fb6
#pragma pack(pop)
Packit d14fb6
#endif
Packit d14fb6
Packit d14fb6
/*
Packit d14fb6
 * Retrieve the full NAC name of the IPMI target.
Packit d14fb6
 *
Packit d14fb6
 * The returned nac name may be larger than the payload size.
Packit d14fb6
 * In which case, it make take several request/payload to retrieve
Packit d14fb6
 * the entire full path name
Packit d14fb6
 *
Packit d14fb6
 * The initial seq_num is set to 0. If the return seq_num is incremented,
Packit d14fb6
 * only the 1st 72 bytes of the nac name is returned and the caller
Packit d14fb6
 * needs to get the next set of string data.
Packit d14fb6
 * If the returned seq_num is identical to the input seq_num, all data
Packit d14fb6
 * has been returned.
Packit d14fb6
 */
Packit d14fb6
static int
Packit d14fb6
ipmi_sunoem_nacname(struct ipmi_intf * intf, int argc, char *argv[])
Packit d14fb6
{
Packit d14fb6
	struct ipmi_rs *rsp;
Packit d14fb6
	struct ipmi_rq req;
Packit d14fb6
	sunoem_nacname_t nacname_req;
Packit d14fb6
	sunoem_nacname_t *nacname_rsp;
Packit d14fb6
	char full_nac_name[LUAPI_MAX_OBJ_PATH_LEN];
Packit d14fb6
Packit d14fb6
	if (argc < 1) {
Packit d14fb6
		return (1);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	if (strlen(argv[0]) > MAX_ID_STR_LEN) {
Packit d14fb6
		lprintf(LOG_ERR,
Packit d14fb6
				"Sun OEM nacname command failed: Max size on IPMI name");
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	nacname_req.seq_num = 0;
Packit d14fb6
	strcpy(nacname_req.nac_name, argv[0]);
Packit d14fb6
Packit d14fb6
	full_nac_name[0] = '\0';
Packit d14fb6
	while (1) {
Packit d14fb6
		memset(&req, 0, sizeof(req));
Packit d14fb6
		req.msg.netfn = IPMI_NETFN_SUNOEM;
Packit d14fb6
		req.msg.cmd = IPMI_SUNOEM_NACNAME;
Packit d14fb6
		req.msg.data = (uint8_t *) &nacname_req;
Packit d14fb6
		req.msg.data_len = sizeof(sunoem_nacname_t);
Packit d14fb6
		rsp = intf->sendrecv(intf, &req;;
Packit d14fb6
Packit d14fb6
		if (rsp == NULL) {
Packit d14fb6
			lprintf(LOG_ERR, "Sun OEM nacname command failed.");
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
		if (rsp->ccode != 0) {
Packit d14fb6
			lprintf(LOG_ERR, "Sun OEM nacname command failed: %d", rsp->ccode);
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
Packit d14fb6
		nacname_rsp = (sunoem_nacname_t *) rsp->data;
Packit d14fb6
		strncat(full_nac_name, nacname_rsp->nac_name, MAX_SUNOEM_NAC_SIZE);
Packit d14fb6
Packit d14fb6
		/*
Packit d14fb6
		 * break out of the loop if there is no more data
Packit d14fb6
		 * In most cases, if not all, the NAC name fits into a
Packit d14fb6
		 * single payload
Packit d14fb6
		 */
Packit d14fb6
		if (nacname_req.seq_num == nacname_rsp->seq_num) {
Packit d14fb6
			break;
Packit d14fb6
		}
Packit d14fb6
Packit d14fb6
		/* Get the next seq of string bytes */
Packit d14fb6
		nacname_req.seq_num = nacname_rsp->seq_num;
Packit d14fb6
Packit d14fb6
		/* Check if we exceeded the size of the full nac name */
Packit d14fb6
		if ((nacname_req.seq_num * MAX_SUNOEM_NAC_SIZE) > LUAPI_MAX_OBJ_PATH_LEN) {
Packit d14fb6
			lprintf(LOG_ERR,
Packit d14fb6
					"Sun OEM nacname command failed: invalid path length");
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	printf("NAC Name: %s\n", full_nac_name);
Packit d14fb6
	return (0);
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
/* Constants used by ipmi_sunoem_getval */
Packit d14fb6
#define MAX_SUNOEM_VAL_PAYLOAD 79
Packit d14fb6
#define MAX_SUNOEM_VAL_COMPACT_PAYLOAD 56
Packit d14fb6
Packit d14fb6
/*
Packit d14fb6
 * SUNOEM GET/SET LUAPI Commands
Packit d14fb6
 *
Packit d14fb6
 * SUNOEM_REQ_VAL - Request LUAPI Property Value
Packit d14fb6
 * SUNOEM_GET_VAL - Return the value from  SUNOEM_REQ_VAL
Packit d14fb6
 * SUNOEM_SET_VAL - Set the LUAPI Property value
Packit d14fb6
 * SUNOEM_GET_STATUS - Return the Status from SUNOEM_SET_VAL
Packit d14fb6
 */
Packit d14fb6
#define SUNOEM_REQ_VAL 1
Packit d14fb6
#define SUNOEM_GET_VAL 2
Packit d14fb6
#define SUNOEM_SET_VAL 3
Packit d14fb6
#define SUNOEM_GET_STATUS 4
Packit d14fb6
Packit d14fb6
/* Status Code */
Packit d14fb6
#define SUNOEM_REQ_RECV 1
Packit d14fb6
#define SUNOEM_REQ_FAILED 2
Packit d14fb6
#define SUNOEM_DATA_READY 3
Packit d14fb6
#define SUNOEM_DATA_NOT_READY 4
Packit d14fb6
#define SUNOEM_DATA_NOT_FOUND 5
Packit d14fb6
#define GETVAL_MAX_RETRIES 5
Packit d14fb6
Packit d14fb6
/* Parameter type Codes */
Packit d14fb6
#define SUNOEM_LUAPI_TARGET 0
Packit d14fb6
#define SUNOEM_LUAPI_VALUE  1
Packit d14fb6
Packit d14fb6
#ifdef HAVE_PRAGMA_PACK
Packit d14fb6
#pragma pack(push, 1)
Packit d14fb6
#endif
Packit d14fb6
typedef struct
Packit d14fb6
{
Packit d14fb6
	unsigned char cmd_code;
Packit d14fb6
	unsigned char luapi_value[MAX_SUNOEM_VAL_PAYLOAD];
Packit d14fb6
}__attribute__((packed)) sunoem_getval_t;
Packit d14fb6
#ifdef HAVE_PRAGMA_PACK
Packit d14fb6
#pragma pack(pop)
Packit d14fb6
#endif
Packit d14fb6
Packit d14fb6
/*
Packit d14fb6
 * REQUEST PAYLOAD
Packit d14fb6
 *
Packit d14fb6
 * cmd_code - SUNOEM GET/SET LUAPI Cmds - see above
Packit d14fb6
 * param_type: 0: luapi_data contains the luapi property name
Packit d14fb6
 *             1: luapi_data contains the luapi value
Packit d14fb6
 * luapi_data: Either luapi property name or value
Packit d14fb6
 * tid: Transaction ID. If 0. This is the initial request for the
Packit d14fb6
 *      param_type. If tid > 0, this luapi_data string is a concatenation
Packit d14fb6
 *      of the previous request. Handle cases where the LUAPI target name
Packit d14fb6
 *      or value is > MAX_SUNOEM_VAL_COMPACT_PAYLOAD
Packit d14fb6
 * eof: If non zero, this is the last payload for the request
Packit d14fb6
 */
Packit d14fb6
#ifdef HAVE_PRAGMA_PACK
Packit d14fb6
#pragma pack(push, 1)
Packit d14fb6
#endif
Packit d14fb6
typedef struct
Packit d14fb6
{
Packit d14fb6
	unsigned char cmd_code;
Packit d14fb6
	unsigned char param_type;
Packit d14fb6
	unsigned char tid;
Packit d14fb6
	unsigned char eof;
Packit d14fb6
	char luapi_data[MAX_SUNOEM_VAL_COMPACT_PAYLOAD];
Packit d14fb6
}__attribute__((packed)) sunoem_setval_t;
Packit d14fb6
#ifdef HAVE_PRAGMA_PACK
Packit d14fb6
#pragma pack(pop)
Packit d14fb6
#endif
Packit d14fb6
Packit d14fb6
/*
Packit d14fb6
 * RESPONSE PAYLOAD
Packit d14fb6
 *
Packit d14fb6
 * status_code - see above for code definitions
Packit d14fb6
 * tid - transaction ID - assigned ny the ILOM stack
Packit d14fb6
 */
Packit d14fb6
#ifdef HAVE_PRAGMA_PACK
Packit d14fb6
#pragma pack(push, 1)
Packit d14fb6
#endif
Packit d14fb6
typedef struct
Packit d14fb6
{
Packit d14fb6
	unsigned char status_code;
Packit d14fb6
	unsigned char tid;
Packit d14fb6
}__attribute__((packed)) sunoem_setval_resp_t;
Packit d14fb6
#ifdef HAVE_PRAGMA_PACK
Packit d14fb6
#pragma pack(pop)
Packit d14fb6
#endif
Packit d14fb6
Packit d14fb6
/*
Packit d14fb6
 * Return the ILOM target property value
Packit d14fb6
 */
Packit d14fb6
static int
Packit d14fb6
ipmi_sunoem_getval(struct ipmi_intf * intf, int argc, char *argv[])
Packit d14fb6
{
Packit d14fb6
	struct ipmi_rs *rsp;
Packit d14fb6
	struct ipmi_rq req;
Packit d14fb6
	sunoem_getval_t getval_req;
Packit d14fb6
	sunoem_getval_t *getval_rsp;
Packit d14fb6
	int i;
Packit d14fb6
Packit d14fb6
	const char* sp_path = "/SP";
Packit d14fb6
	supported_version_t supp_ver = { 3, 2, 0, 0 };
Packit d14fb6
Packit d14fb6
	if (argc < 1) {
Packit d14fb6
		return (1);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	if (strlen(argv[0]) > MAX_SUNOEM_VAL_PAYLOAD) {
Packit d14fb6
		lprintf(LOG_ERR,
Packit d14fb6
				"Sun OEM get value command failed: Max size on IPMI name");
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	if ((ipmi_sunoem_checkversion(intf, &supp_ver) < 0)
Packit d14fb6
			&& (!strncmp(argv[0], sp_path, strlen(sp_path)))) {
Packit d14fb6
		argv[0][1] = 'X'; /*replace SP by X to gain access to hidden properties*/
Packit d14fb6
		memmove(&argv[0][2], &argv[0][3], strlen(argv[0]) - 2);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	/*
Packit d14fb6
	 * Setup the initial request to fetch the data.
Packit d14fb6
	 * Upon function return, the next cmd (SUNOEM_GET_VAL)
Packit d14fb6
	 * can be requested.
Packit d14fb6
	 */
Packit d14fb6
	memset(&getval_req, 0, sizeof(getval_req));
Packit d14fb6
	strncpy((char*) getval_req.luapi_value, argv[0], MAX_SUNOEM_VAL_PAYLOAD);
Packit d14fb6
	getval_req.cmd_code = SUNOEM_REQ_VAL;
Packit d14fb6
Packit d14fb6
	memset(&req, 0, sizeof(req));
Packit d14fb6
	req.msg.netfn = IPMI_NETFN_SUNOEM;
Packit d14fb6
	req.msg.cmd = IPMI_SUNOEM_GETVAL;
Packit d14fb6
	req.msg.data = (uint8_t *) &getval_req;
Packit d14fb6
	req.msg.data_len = sizeof(sunoem_getval_t);
Packit d14fb6
	rsp = intf->sendrecv(intf, &req;;
Packit d14fb6
Packit d14fb6
	if (rsp == NULL) {
Packit d14fb6
		lprintf(LOG_ERR, "Sun OEM getval1 command failed.");
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
	if (rsp->ccode != 0) {
Packit d14fb6
		lprintf(LOG_ERR, "Sun OEM getval1 command failed: %d", rsp->ccode);
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	/*
Packit d14fb6
	 * Fetch the data value - if it is not ready,
Packit d14fb6
	 * retry the request up to GETVAL_MAX_RETRIES
Packit d14fb6
	 */
Packit d14fb6
	for (i = 0; i < GETVAL_MAX_RETRIES; i++) {
Packit d14fb6
		memset(&req, 0, sizeof(req));
Packit d14fb6
		req.msg.netfn = IPMI_NETFN_SUNOEM;
Packit d14fb6
		req.msg.cmd = IPMI_SUNOEM_GETVAL;
Packit d14fb6
		getval_req.cmd_code = SUNOEM_GET_VAL;
Packit d14fb6
		req.msg.data = (uint8_t *) &getval_req;
Packit d14fb6
		req.msg.data_len = sizeof(sunoem_getval_t);
Packit d14fb6
		rsp = intf->sendrecv(intf, &req;;
Packit d14fb6
Packit d14fb6
		if (rsp == NULL) {
Packit d14fb6
			lprintf(LOG_ERR, "Sun OEM getval2 command failed.");
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
Packit d14fb6
		if (rsp->ccode != 0) {
Packit d14fb6
			lprintf(LOG_ERR, "Sun OEM getval2 command failed: %d", rsp->ccode);
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
Packit d14fb6
		getval_rsp = (sunoem_getval_t *) rsp->data;
Packit d14fb6
Packit d14fb6
		if (getval_rsp->cmd_code == SUNOEM_DATA_READY) {
Packit d14fb6
			printf("Target Value: %s\n", getval_rsp->luapi_value);
Packit d14fb6
			return (0);
Packit d14fb6
		} else if (getval_rsp->cmd_code == SUNOEM_DATA_NOT_FOUND) {
Packit d14fb6
			lprintf(LOG_ERR, "Target: %s not found", getval_req.luapi_value);
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
Packit d14fb6
		sleep(1);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	lprintf(LOG_ERR, "Unable to retrieve target value.");
Packit d14fb6
	return (-1);
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
static int
Packit d14fb6
send_luapi_prop_name(struct ipmi_intf * intf, int len, char *prop_name,
Packit d14fb6
		unsigned char *tid_num)
Packit d14fb6
{
Packit d14fb6
	int i = 0;
Packit d14fb6
	struct ipmi_rs *rsp;
Packit d14fb6
	struct ipmi_rq req;
Packit d14fb6
	sunoem_setval_t setval_req;
Packit d14fb6
	sunoem_setval_resp_t *setval_rsp;
Packit d14fb6
Packit d14fb6
	*tid_num = 0;
Packit d14fb6
	while (i < len) {
Packit d14fb6
		/*
Packit d14fb6
		 * Setup the request,
Packit d14fb6
		 * Upon function return, the next cmd (SUNOEM_SET_VAL)
Packit d14fb6
		 * can be requested.
Packit d14fb6
		 */
Packit d14fb6
		memset(&req, 0, sizeof(req));
Packit d14fb6
		memset(&setval_req, 0, sizeof(sunoem_setval_t));
Packit d14fb6
		req.msg.netfn = IPMI_NETFN_SUNOEM;
Packit d14fb6
		req.msg.cmd = IPMI_SUNOEM_SETVAL;
Packit d14fb6
		setval_req.cmd_code = SUNOEM_SET_VAL;
Packit d14fb6
		setval_req.param_type = SUNOEM_LUAPI_TARGET;
Packit d14fb6
		setval_req.tid = *tid_num;
Packit d14fb6
		setval_req.eof = 0;
Packit d14fb6
		/*
Packit d14fb6
		 * If the property name is > payload, only copy
Packit d14fb6
		 * the payload size and increment the string offset (i)
Packit d14fb6
		 * for the next payload
Packit d14fb6
		 */
Packit d14fb6
		if (strlen(&(prop_name[i])) > MAX_SUNOEM_VAL_COMPACT_PAYLOAD) {
Packit d14fb6
			strncpy(setval_req.luapi_data, &(prop_name[i]),
Packit d14fb6
			MAX_SUNOEM_VAL_COMPACT_PAYLOAD);
Packit d14fb6
		} else {
Packit d14fb6
			strncpy(setval_req.luapi_data, &(prop_name[i]),
Packit d14fb6
					strlen(&(prop_name[i])));
Packit d14fb6
		}
Packit d14fb6
		req.msg.data = (uint8_t *) &setval_req;
Packit d14fb6
		req.msg.data_len = sizeof(sunoem_setval_t);
Packit d14fb6
		rsp = intf->sendrecv(intf, &req;;
Packit d14fb6
Packit d14fb6
		if (rsp == NULL) {
Packit d14fb6
			lprintf(LOG_ERR, "Sun OEM setval prop name: response is NULL");
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
Packit d14fb6
		if (rsp->ccode != 0) {
Packit d14fb6
			lprintf(LOG_ERR, "Sun OEM setval prop name: request failed: %d",
Packit d14fb6
					rsp->ccode);
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
Packit d14fb6
		setval_rsp = (sunoem_setval_resp_t *) rsp->data;
Packit d14fb6
Packit d14fb6
		/*
Packit d14fb6
		 * If the return code is other than data received, the
Packit d14fb6
		 * request failed
Packit d14fb6
		 */
Packit d14fb6
		if (setval_rsp->status_code != SUNOEM_REQ_RECV) {
Packit d14fb6
			lprintf(LOG_ERR,
Packit d14fb6
					"Sun OEM setval prop name: invalid status code: %d",
Packit d14fb6
					setval_rsp->status_code);
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
		/* Use the tid returned by ILOM */
Packit d14fb6
		*tid_num = setval_rsp->tid;
Packit d14fb6
		/* Increment the string offset */
Packit d14fb6
		i += MAX_SUNOEM_VAL_COMPACT_PAYLOAD;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	return (0);
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
static int
Packit d14fb6
send_luapi_prop_value(struct ipmi_intf * intf, int len,	char *prop_value,
Packit d14fb6
		unsigned char tid_num)
Packit d14fb6
{
Packit d14fb6
	int i = 0;
Packit d14fb6
	struct ipmi_rs *rsp;
Packit d14fb6
	struct ipmi_rq req;
Packit d14fb6
	sunoem_setval_t setval_req;
Packit d14fb6
	sunoem_setval_resp_t *setval_rsp;
Packit d14fb6
Packit d14fb6
	while (i < len) {
Packit d14fb6
		/*
Packit d14fb6
		 * Setup the request,
Packit d14fb6
		 * Upon function return, the next cmd (SUNOEM_GET_VAL)
Packit d14fb6
		 * can be requested.
Packit d14fb6
		 */
Packit d14fb6
		memset(&req, 0, sizeof(req));
Packit d14fb6
		memset(&setval_req, 0, sizeof(sunoem_setval_t));
Packit d14fb6
		req.msg.netfn = IPMI_NETFN_SUNOEM;
Packit d14fb6
		req.msg.cmd = IPMI_SUNOEM_SETVAL;
Packit d14fb6
		setval_req.cmd_code = SUNOEM_SET_VAL;
Packit d14fb6
		setval_req.param_type = SUNOEM_LUAPI_VALUE;
Packit d14fb6
		setval_req.tid = tid_num;
Packit d14fb6
		/*
Packit d14fb6
		 * If the property name is > payload, only copy the
Packit d14fb6
		 * the payload size and increment the string offset
Packit d14fb6
		 * for the next payload
Packit d14fb6
		 */
Packit d14fb6
		if (strlen(&(prop_value[i])) > MAX_SUNOEM_VAL_COMPACT_PAYLOAD) {
Packit d14fb6
			strncpy(setval_req.luapi_data, &(prop_value[i]),
Packit d14fb6
			MAX_SUNOEM_VAL_COMPACT_PAYLOAD);
Packit d14fb6
		} else {
Packit d14fb6
			/* Captured the entire string, mark this as the last payload */
Packit d14fb6
			strncpy(setval_req.luapi_data, &(prop_value[i]),
Packit d14fb6
					strlen(&(prop_value[i])));
Packit d14fb6
			setval_req.eof = 1;
Packit d14fb6
		}
Packit d14fb6
		req.msg.data = (uint8_t *) &setval_req;
Packit d14fb6
		req.msg.data_len = sizeof(sunoem_setval_t);
Packit d14fb6
		rsp = intf->sendrecv(intf, &req;;
Packit d14fb6
Packit d14fb6
		if (rsp == NULL) {
Packit d14fb6
			lprintf(LOG_ERR, "Sun OEM setval prop value: response is NULL");
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
Packit d14fb6
		if (rsp->ccode != 0) {
Packit d14fb6
			lprintf(LOG_ERR, "Sun OEM setval prop value: request failed: %d",
Packit d14fb6
					rsp->ccode);
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
Packit d14fb6
		setval_rsp = (sunoem_setval_resp_t *) rsp->data;
Packit d14fb6
Packit d14fb6
		/*
Packit d14fb6
		 * If the return code is other than data received, the
Packit d14fb6
		 * request failed
Packit d14fb6
		 */
Packit d14fb6
		if (setval_rsp->status_code != SUNOEM_REQ_RECV) {
Packit d14fb6
			lprintf(LOG_ERR,
Packit d14fb6
					"Sun OEM setval prop value: invalid status code: %d",
Packit d14fb6
					setval_rsp->status_code);
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
Packit d14fb6
		/* Increment the string offset */
Packit d14fb6
		i += MAX_SUNOEM_VAL_COMPACT_PAYLOAD;
Packit d14fb6
	}
Packit d14fb6
	return (0);
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
static int
Packit d14fb6
ipmi_sunoem_setval(struct ipmi_intf * intf, int argc, char *argv[])
Packit d14fb6
{
Packit d14fb6
	struct ipmi_rs *rsp;
Packit d14fb6
	struct ipmi_rq req;
Packit d14fb6
	sunoem_setval_t setval_req;
Packit d14fb6
	sunoem_setval_resp_t *setval_rsp;
Packit d14fb6
	int prop_len;
Packit d14fb6
	int value_len;
Packit d14fb6
	int i;
Packit d14fb6
	unsigned char tid_num;
Packit d14fb6
	int retries;
Packit d14fb6
Packit d14fb6
	prop_len = strlen(argv[0]);
Packit d14fb6
	value_len = strlen(argv[1]);
Packit d14fb6
	if (prop_len > LUAPI_MAX_OBJ_PATH_LEN) {
Packit d14fb6
		lprintf(LOG_ERR,
Packit d14fb6
				"Sun OEM set value command failed: Max size on property name");
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
	if (value_len > LUAPI_MAX_OBJ_VAL_LEN) {
Packit d14fb6
		lprintf(LOG_ERR,
Packit d14fb6
				"Sun OEM set value command failed: Max size on property value");
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	/* Test if there is a timeout specified */
Packit d14fb6
	if (argc == 3) {
Packit d14fb6
		if ((str2int(argv[2], &retries) != 0) || retries < 0) {
Packit d14fb6
			lprintf(LOG_ERR,
Packit d14fb6
					"Invalid input given or out of range for time-out parameter.");
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
	} else {
Packit d14fb6
		retries = GETVAL_MAX_RETRIES;
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	/* Send the property name 1st */
Packit d14fb6
	if (send_luapi_prop_name(intf, prop_len, argv[0], &tid_num) != 0) {
Packit d14fb6
		/* return if there is an error */
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	if (send_luapi_prop_value(intf, value_len, argv[1], tid_num) != 0) {
Packit d14fb6
		/* return if there is an error */
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	/*
Packit d14fb6
	 * Get The status of the command.
Packit d14fb6
	 * if it is not ready, retry the request up to
Packit d14fb6
	 * GETVAL_MAX_RETRIES
Packit d14fb6
	 */
Packit d14fb6
	for (i = 0; i < retries; i++) {
Packit d14fb6
		memset(&req, 0, sizeof(req));
Packit d14fb6
		req.msg.netfn = IPMI_NETFN_SUNOEM;
Packit d14fb6
		req.msg.cmd = IPMI_SUNOEM_SETVAL;
Packit d14fb6
		setval_req.cmd_code = SUNOEM_GET_STATUS;
Packit d14fb6
		setval_req.tid = tid_num;
Packit d14fb6
		req.msg.data = (uint8_t *) &setval_req;
Packit d14fb6
		req.msg.data_len = sizeof(sunoem_setval_t);
Packit d14fb6
		rsp = intf->sendrecv(intf, &req;;
Packit d14fb6
Packit d14fb6
		if (rsp == NULL) {
Packit d14fb6
			lprintf(LOG_ERR, "Sun OEM setval command failed.");
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
Packit d14fb6
		if (rsp->ccode != 0) {
Packit d14fb6
			lprintf(LOG_ERR, "Sun OEM setval command failed: %d", rsp->ccode);
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
Packit d14fb6
		setval_rsp = (sunoem_setval_resp_t *) rsp->data;
Packit d14fb6
Packit d14fb6
		if (setval_rsp->status_code == SUNOEM_DATA_READY) {
Packit d14fb6
			printf("Sun OEM setval command successful.\n");
Packit d14fb6
			return (0);
Packit d14fb6
		} else if (setval_rsp->status_code != SUNOEM_DATA_NOT_READY) {
Packit d14fb6
			lprintf(LOG_ERR, "Sun OEM setval command failed.");
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
Packit d14fb6
		sleep(1);
Packit d14fb6
	}
Packit d14fb6
	/* If we reached here, retries exceeded */
Packit d14fb6
	lprintf(LOG_ERR, "Sun OEM setval command failed: Command Timed Out");
Packit d14fb6
Packit d14fb6
	return (-1);
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
#define MAX_FILE_DATA_SIZE            1024
Packit d14fb6
#define MAX_FILEID_LEN                16
Packit d14fb6
#define CORE_TUNNEL_SUBCMD_GET_FILE   11
Packit d14fb6
Packit d14fb6
#ifdef HAVE_PRAGMA_PACK
Packit d14fb6
#pragma pack(push, 1)
Packit d14fb6
#endif
Packit d14fb6
typedef struct
Packit d14fb6
{
Packit d14fb6
	unsigned char cmd_code;
Packit d14fb6
	unsigned char file_id[MAX_FILEID_LEN];
Packit d14fb6
	unsigned int block_num;
Packit d14fb6
}__attribute__((packed)) getfile_req_t;
Packit d14fb6
Packit d14fb6
typedef struct
Packit d14fb6
{
Packit d14fb6
	unsigned int block_num;
Packit d14fb6
	unsigned int data_size;
Packit d14fb6
	unsigned char eof;
Packit d14fb6
	unsigned char data[MAX_FILE_DATA_SIZE];
Packit d14fb6
}__attribute__((packed)) getfile_rsp_t;
Packit d14fb6
#ifdef HAVE_PRAGMA_PACK
Packit d14fb6
#pragma pack(pop)
Packit d14fb6
#endif
Packit d14fb6
Packit d14fb6
static int
Packit d14fb6
ipmi_sunoem_getfile(struct ipmi_intf * intf, int argc, char *argv[])
Packit d14fb6
{
Packit d14fb6
	struct ipmi_rs *rsp;
Packit d14fb6
	struct ipmi_rq req;
Packit d14fb6
	getfile_req_t getfile_req;
Packit d14fb6
	getfile_rsp_t *getfile_rsp;
Packit d14fb6
	int block_num = 0;
Packit d14fb6
	int nbo_blk_num; /* Network Byte Order Block Num */
Packit d14fb6
	FILE *fp;
Packit d14fb6
	unsigned data_size;
Packit d14fb6
	supported_version_t supp_ver = IPMI_SUNOEM_GETFILE_VERSION;
Packit d14fb6
Packit d14fb6
	if (argc < 1) {
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	/*check if command is supported by this version of ilom*/
Packit d14fb6
	if (ipmi_sunoem_checkversion(intf, &supp_ver) < 0) {
Packit d14fb6
		ipmi_sunoem_print_required_version(&supp_ver);
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	/*
Packit d14fb6
	 * File ID is < MAX_FILEID_LEN
Packit d14fb6
	 * Save 1 byte for null Terminated string
Packit d14fb6
	 */
Packit d14fb6
	if (strlen(argv[0]) >= MAX_FILE_DATA_SIZE) {
Packit d14fb6
		lprintf(LOG_ERR, "File ID >= %d characters", MAX_FILEID_LEN);
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	memset(&getfile_req, 0, sizeof(getfile_req));
Packit d14fb6
	strncpy((char*) getfile_req.file_id, argv[0], MAX_FILEID_LEN - 1);
Packit d14fb6
Packit d14fb6
	/* Create the destination file */
Packit d14fb6
	fp = ipmi_open_file_write(argv[1]);
Packit d14fb6
	if (fp == NULL) {
Packit d14fb6
		lprintf(LOG_ERR, "Unable to open file: %s", argv[1]);
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	memset(&req, 0, sizeof(req));
Packit d14fb6
	req.msg.netfn = IPMI_NETFN_SUNOEM;
Packit d14fb6
	req.msg.cmd = IPMI_SUNOEM_CORE_TUNNEL;
Packit d14fb6
	req.msg.data = (uint8_t *) &getfile_req;
Packit d14fb6
	req.msg.data_len = sizeof(getfile_req_t);
Packit d14fb6
	getfile_req.cmd_code = CORE_TUNNEL_SUBCMD_GET_FILE;
Packit d14fb6
Packit d14fb6
	do {
Packit d14fb6
Packit d14fb6
		nbo_blk_num = htonl(block_num);
Packit d14fb6
		/* Block Num must be in network byte order */
Packit d14fb6
		memcpy(&(getfile_req.block_num), &nbo_blk_num,
Packit d14fb6
				sizeof(getfile_req.block_num));
Packit d14fb6
Packit d14fb6
		rsp = intf->sendrecv(intf, &req;;
Packit d14fb6
Packit d14fb6
		if (rsp == NULL) {
Packit d14fb6
			lprintf(LOG_ERR, "Sun OEM getfile command failed.");
Packit d14fb6
			fclose(fp);
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
		if (rsp->ccode != 0) {
Packit d14fb6
			lprintf(LOG_ERR, "Sun OEM getfile command failed: %d", rsp->ccode);
Packit d14fb6
			fclose(fp);
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
Packit d14fb6
		getfile_rsp = (getfile_rsp_t *) rsp->data;
Packit d14fb6
Packit d14fb6
		memcpy(&data_size, &(getfile_rsp->data_size),
Packit d14fb6
				sizeof(getfile_rsp->data_size));
Packit d14fb6
		data_size = ntohl(data_size);
Packit d14fb6
Packit d14fb6
		if (data_size > MAX_FILE_DATA_SIZE) {
Packit d14fb6
			lprintf(LOG_ERR, "Sun OEM getfile invalid data size: %d",
Packit d14fb6
					data_size);
Packit d14fb6
			fclose(fp);
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
Packit d14fb6
		/* Check if Block Num matches */
Packit d14fb6
		if (memcmp(&(getfile_req.block_num), &(getfile_rsp->block_num),
Packit d14fb6
				sizeof(getfile_req.block_num)) != 0) {
Packit d14fb6
			lprintf(LOG_ERR, "Sun OEM getfile Incorrect Block Num Returned");
Packit d14fb6
			lprintf(LOG_ERR, "Expecting: %x Received: %x",
Packit d14fb6
					getfile_req.block_num, getfile_rsp->block_num);
Packit d14fb6
			fclose(fp);
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
Packit d14fb6
		if (fwrite(getfile_rsp->data, 1, data_size, fp) != data_size) {
Packit d14fb6
			lprintf(LOG_ERR, "Sun OEM getfile write failed: %d", rsp->ccode);
Packit d14fb6
			fclose(fp);
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
Packit d14fb6
		block_num++;
Packit d14fb6
	} while (getfile_rsp->eof == 0);
Packit d14fb6
Packit d14fb6
	fclose(fp);
Packit d14fb6
Packit d14fb6
	return (0);
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
/*
Packit d14fb6
 * Query BMC for capability/behavior.
Packit d14fb6
 */
Packit d14fb6
Packit d14fb6
#define CORE_TUNNEL_SUBCMD_GET_BEHAVIOR   15
Packit d14fb6
#define SUNOEM_BEHAVIORID_SIZE            32
Packit d14fb6
Packit d14fb6
#ifdef HAVE_PRAGMA_PACK
Packit d14fb6
#pragma pack(push, 1)
Packit d14fb6
#endif
Packit d14fb6
typedef struct
Packit d14fb6
{
Packit d14fb6
	unsigned char cmd_code;
Packit d14fb6
	unsigned char behavior_id[SUNOEM_BEHAVIORID_SIZE];
Packit d14fb6
}__attribute__((packed)) getbehavior_req_t;
Packit d14fb6
Packit d14fb6
typedef struct
Packit d14fb6
{
Packit d14fb6
	unsigned char enabled;
Packit d14fb6
}__attribute__((packed)) getbehavior_rsp_t;
Packit d14fb6
#ifdef HAVE_PRAGMA_PACK
Packit d14fb6
#pragma pack(pop)
Packit d14fb6
#endif
Packit d14fb6
Packit d14fb6
static int
Packit d14fb6
ipmi_sunoem_getbehavior(struct ipmi_intf * intf, int argc, char *argv[])
Packit d14fb6
{
Packit d14fb6
	struct ipmi_rq req;
Packit d14fb6
	struct ipmi_rs *rsp;
Packit d14fb6
	getbehavior_req_t getbehavior_req;
Packit d14fb6
	getbehavior_rsp_t *getbehavior_rsp;
Packit d14fb6
	supported_version_t supp_ver = IPMI_SUNOEM_GETBEHAVIOR_VERSION;
Packit d14fb6
Packit d14fb6
	if (argc < 1) {
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	/*check if command is supported by this version of ilom*/
Packit d14fb6
	if (ipmi_sunoem_checkversion(intf, &supp_ver) < 0) {
Packit d14fb6
		ipmi_sunoem_print_required_version(&supp_ver);
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	/*
Packit d14fb6
	 * Behavior ID is < SUNOEM_BEHAVIORID_SIZE.
Packit d14fb6
	 * Save 1 byte for null terminated string
Packit d14fb6
	 */
Packit d14fb6
	if (strlen(argv[0]) >= SUNOEM_BEHAVIORID_SIZE) {
Packit d14fb6
		lprintf(LOG_ERR, "Behavior ID >= %d characters",
Packit d14fb6
		SUNOEM_BEHAVIORID_SIZE);
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	memset(&getbehavior_req, 0, sizeof(getbehavior_req));
Packit d14fb6
	strncpy(getbehavior_req.behavior_id, argv[0], SUNOEM_BEHAVIORID_SIZE - 1);
Packit d14fb6
Packit d14fb6
	memset(&req, 0, sizeof(req));
Packit d14fb6
	req.msg.netfn = IPMI_NETFN_SUNOEM;
Packit d14fb6
	req.msg.cmd = IPMI_SUNOEM_CORE_TUNNEL;
Packit d14fb6
	req.msg.data = (uint8_t *) &getbehavior_req;
Packit d14fb6
	req.msg.data_len = sizeof(getbehavior_req_t);
Packit d14fb6
	getbehavior_req.cmd_code = CORE_TUNNEL_SUBCMD_GET_BEHAVIOR;
Packit d14fb6
Packit d14fb6
	rsp = intf->sendrecv(intf, &req;;
Packit d14fb6
Packit d14fb6
	if (rsp == NULL) {
Packit d14fb6
		lprintf(LOG_ERR, "Sun OEM getbehavior command failed.");
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	if (rsp->ccode != 0) {
Packit d14fb6
		lprintf(LOG_ERR, "Sun OEM getbehavior command failed: %d", rsp->ccode);
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	getbehavior_rsp = (getbehavior_rsp_t *) rsp->data;
Packit d14fb6
	printf("ILOM behavior %s %s enabled\n", getbehavior_req.behavior_id,
Packit d14fb6
			getbehavior_rsp->enabled ? "is" : "is not");
Packit d14fb6
Packit d14fb6
	return (0);
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
int
Packit d14fb6
ipmi_sunoem_main(struct ipmi_intf * intf, int argc, char ** argv)
Packit d14fb6
{
Packit d14fb6
	int rc = 0;
Packit d14fb6
Packit d14fb6
	if (argc == 0 || strcmp(argv[0], "help") == 0) {
Packit d14fb6
		ipmi_sunoem_usage();
Packit d14fb6
		return (0);
Packit d14fb6
	} /* if (argc == 0 || strcmp(argv[0], "help") == 0) */
Packit d14fb6
Packit d14fb6
	if (strcmp(argv[0], "cli") == 0) {
Packit d14fb6
		rc = ipmi_sunoem_cli(intf, argc - 1, &argv[1]);
Packit d14fb6
	} else if ((strcmp(argv[0], "led") == 0) || (strcmp(argv[0], "sbled") == 0)) {
Packit d14fb6
		if (argc < 2) {
Packit d14fb6
			ipmi_sunoem_usage();
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
Packit d14fb6
		if (strcmp(argv[1], "get") == 0) {
Packit d14fb6
			if (argc < 3) {
Packit d14fb6
				char * arg[] = { "all" };
Packit d14fb6
				rc = ipmi_sunoem_led_get(intf, 1, arg);
Packit d14fb6
			} else {
Packit d14fb6
				rc = ipmi_sunoem_led_get(intf, argc - 2, &(argv[2]));
Packit d14fb6
			}
Packit d14fb6
		} else if (strcmp(argv[1], "set") == 0) {
Packit d14fb6
			if (argc < 4) {
Packit d14fb6
				ipmi_sunoem_usage();
Packit d14fb6
				return (-1);
Packit d14fb6
			}
Packit d14fb6
			rc = ipmi_sunoem_led_set(intf, argc - 2, &(argv[2]));
Packit d14fb6
		} else {
Packit d14fb6
			ipmi_sunoem_usage();
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
	} else if (strcmp(argv[0], "sshkey") == 0) {
Packit d14fb6
		uint8_t uid = 0;
Packit d14fb6
		if (argc < 3) {
Packit d14fb6
			ipmi_sunoem_usage();
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
		rc = str2uchar(argv[2], &uid);
Packit d14fb6
		if (rc == 0) {
Packit d14fb6
			/* conversion should be OK. */
Packit d14fb6
		} else if (rc == 2) {
Packit d14fb6
			lprintf(LOG_NOTICE, "Invalid interval given.");
Packit d14fb6
			return (-1);
Packit d14fb6
		} else {
Packit d14fb6
			/* defaults to rc = 3 */
Packit d14fb6
			lprintf(LOG_NOTICE, "Given interval is too big.");
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
Packit d14fb6
		if (strcmp(argv[1], "del") == 0) {
Packit d14fb6
			/* number of arguments, three, is already checked at this point */
Packit d14fb6
			rc = ipmi_sunoem_sshkey_del(intf, uid);
Packit d14fb6
		} else if (strcmp(argv[1], "set") == 0) {
Packit d14fb6
			if (argc < 4) {
Packit d14fb6
				ipmi_sunoem_usage();
Packit d14fb6
				return (-1);
Packit d14fb6
			}
Packit d14fb6
			rc = ipmi_sunoem_sshkey_set(intf, uid, argv[3]);
Packit d14fb6
		} else {
Packit d14fb6
			ipmi_sunoem_usage();
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
	} else if (strcmp(argv[0], "ping") == 0) {
Packit d14fb6
		if (argc < 2) {
Packit d14fb6
			ipmi_sunoem_usage();
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
		rc = ipmi_sunoem_echo(intf, argc - 1, &(argv[1]));
Packit d14fb6
	} else if (strcmp(argv[0], "version") == 0) {
Packit d14fb6
		rc = ipmi_sunoem_version(intf);
Packit d14fb6
	} else if (strcmp(argv[0], "nacname") == 0) {
Packit d14fb6
		if (argc < 2) {
Packit d14fb6
			ipmi_sunoem_usage();
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
		rc = ipmi_sunoem_nacname(intf, argc - 1, &(argv[1]));
Packit d14fb6
	} else if (strcmp(argv[0], "getval") == 0) {
Packit d14fb6
		if (argc < 2) {
Packit d14fb6
			ipmi_sunoem_usage();
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
		rc = ipmi_sunoem_getval(intf, argc - 1, &(argv[1]));
Packit d14fb6
	} else if (strcmp(argv[0], "setval") == 0) {
Packit d14fb6
		if (argc < 3) {
Packit d14fb6
			ipmi_sunoem_usage();
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
		rc = ipmi_sunoem_setval(intf, argc - 1, &(argv[1]));
Packit d14fb6
	} else if (strcmp(argv[0], "getfile") == 0) {
Packit d14fb6
		if (argc < 3) {
Packit d14fb6
			ipmi_sunoem_usage();
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
		rc = ipmi_sunoem_getfile(intf, argc - 1, &(argv[1]));
Packit d14fb6
	} else if (strcmp(argv[0], "getbehavior") == 0) {
Packit d14fb6
		if (argc < 2) {
Packit d14fb6
			ipmi_sunoem_usage();
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
		rc = ipmi_sunoem_getbehavior(intf, argc - 1, &(argv[1]));
Packit d14fb6
	} else {
Packit d14fb6
		lprintf(LOG_ERR, "Invalid sunoem command: %s", argv[0]);
Packit d14fb6
		return (-1);
Packit d14fb6
	} /* if (strcmp(argv[0], "cli") == 0) */
Packit d14fb6
Packit d14fb6
	return (rc);
Packit d14fb6
}