mirror of
https://github.com/ipmitool/ipmitool.git
synced 2025-05-10 10:37:22 +00:00
860 lines
23 KiB
C
860 lines
23 KiB
C
/*
|
|
* Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* Redistribution of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
*
|
|
* Redistribution in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* Neither the name of Sun Microsystems, Inc. or the names of
|
|
* contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
*
|
|
* This software is provided "AS IS," without a warranty of any kind.
|
|
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
|
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
|
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
|
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
|
|
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
|
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
|
|
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
|
|
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
|
|
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
|
|
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
|
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <netinet/in.h>
|
|
#include <arpa/inet.h>
|
|
#include <errno.h>
|
|
#include <unistd.h>
|
|
#include <signal.h>
|
|
#include <ctype.h>
|
|
|
|
#include <ipmitool/ipmi.h>
|
|
#include <ipmitool/ipmi_intf.h>
|
|
#include <ipmitool/helper.h>
|
|
#include <ipmitool/log.h>
|
|
#include <ipmitool/ipmi_sel.h>
|
|
#include <ipmitool/ipmi_sdr.h>
|
|
#include <ipmitool/ipmi_strings.h>
|
|
#include <ipmitool/ipmi_channel.h>
|
|
#include <ipmitool/ipmi_sunoem.h>
|
|
#include <ipmitool/ipmi_raw.h>
|
|
|
|
static const struct valstr sunoem_led_type_vals[] = {
|
|
{ 0, "OK2RM" },
|
|
{ 1, "SERVICE" },
|
|
{ 2, "ACT" },
|
|
{ 3, "LOCATE" },
|
|
{ 0xFF, NULL },
|
|
};
|
|
|
|
static const struct valstr sunoem_led_mode_vals[] = {
|
|
{ 0, "OFF" },
|
|
{ 1, "ON" },
|
|
{ 2, "STANDBY" },
|
|
{ 3, "SLOW" },
|
|
{ 4, "FAST" },
|
|
{ 0xFF, NULL },
|
|
};
|
|
static const struct valstr sunoem_led_mode_optvals[] = {
|
|
{ 0, "STEADY_OFF" },
|
|
{ 1, "STEADY_ON" },
|
|
{ 2, "STANDBY_BLINK" },
|
|
{ 3, "SLOW_BLINK" },
|
|
{ 4, "FAST_BLINK" },
|
|
{ 0xFF, NULL },
|
|
};
|
|
|
|
int is_sbcmd = 0;
|
|
|
|
static void
|
|
ipmi_sunoem_usage(void)
|
|
{
|
|
lprintf(LOG_NOTICE, "usage: sunoem <command> [option...]");
|
|
lprintf(LOG_NOTICE, "");
|
|
lprintf(LOG_NOTICE, " fan speed <0-100>");
|
|
lprintf(LOG_NOTICE, " Set system fan speed (PWM duty cycle)");
|
|
lprintf(LOG_NOTICE, "");
|
|
lprintf(LOG_NOTICE, " sshkey set <userid> <id_rsa.pub>");
|
|
lprintf(LOG_NOTICE, " Set ssh key for a userid into authorized_keys,");
|
|
lprintf(LOG_NOTICE, " view users with 'user list' command.");
|
|
lprintf(LOG_NOTICE, "");
|
|
lprintf(LOG_NOTICE, " sshkey del <userid>");
|
|
lprintf(LOG_NOTICE, " Delete ssh key for userid from authorized_keys,");
|
|
lprintf(LOG_NOTICE, " view users with 'user list' command.");
|
|
lprintf(LOG_NOTICE, "");
|
|
lprintf(LOG_NOTICE, " led get <sensorid> [ledtype]");
|
|
lprintf(LOG_NOTICE,
|
|
" Read status of LED found in Generic Device Locator.");
|
|
lprintf(LOG_NOTICE, "");
|
|
lprintf(LOG_NOTICE, " led set <sensorid> <ledmode> [ledtype]");
|
|
lprintf(LOG_NOTICE,
|
|
" Set mode of LED found in Generic Device Locator.");
|
|
lprintf(LOG_NOTICE, "");
|
|
lprintf(LOG_NOTICE, " sbled get <sensorid> [ledtype]");
|
|
lprintf(LOG_NOTICE,
|
|
" Read status of LED found in Generic Device Locator");
|
|
lprintf(LOG_NOTICE, " for Sun Blade Modular Systems.");
|
|
lprintf(LOG_NOTICE, "");
|
|
lprintf(LOG_NOTICE, " sbled set <sensorid> <ledmode> [ledtype]");
|
|
lprintf(LOG_NOTICE, " Set mode of LED found in Generic Device Locator");
|
|
lprintf(LOG_NOTICE, " for Sun Blade Modular Systems.");
|
|
lprintf(LOG_NOTICE, "");
|
|
lprintf(LOG_NOTICE,
|
|
" Use 'sdr list generic' command to get list of Generic");
|
|
lprintf(LOG_NOTICE, " Devices that are controllable LEDs.");
|
|
lprintf(LOG_NOTICE, "");
|
|
lprintf(LOG_NOTICE, " Required SIS LED Mode:");
|
|
lprintf(LOG_NOTICE, " OFF Off");
|
|
lprintf(LOG_NOTICE, " ON Steady On");
|
|
lprintf(LOG_NOTICE, " STANDBY 100ms on 2900ms off blink rate");
|
|
lprintf(LOG_NOTICE, " SLOW 1HZ blink rate");
|
|
lprintf(LOG_NOTICE, " FAST 4HZ blink rate");
|
|
lprintf(LOG_NOTICE, "");
|
|
lprintf(LOG_NOTICE, " Optional SIS LED Type:");
|
|
lprintf(LOG_NOTICE, " OK2RM OK to Remove");
|
|
lprintf(LOG_NOTICE, " SERVICE Service Required");
|
|
lprintf(LOG_NOTICE, " ACT Activity");
|
|
lprintf(LOG_NOTICE, " LOCATE Locate");
|
|
lprintf(LOG_NOTICE, "");
|
|
}
|
|
|
|
/*
|
|
* IPMI Request Data: 1 byte
|
|
*
|
|
* [byte 0] FanSpeed Fan speed as percentage
|
|
*/
|
|
static int
|
|
ipmi_sunoem_fan_speed(struct ipmi_intf * intf, uint8_t speed)
|
|
{
|
|
struct ipmi_rs * rsp;
|
|
struct ipmi_rq req;
|
|
|
|
/*
|
|
* sunoem fan speed <percent>
|
|
*/
|
|
|
|
if (speed > 100) {
|
|
lprintf(LOG_NOTICE, "Invalid fan speed: %d", speed);
|
|
return -1;
|
|
}
|
|
|
|
req.msg.netfn = IPMI_NETFN_SUNOEM;
|
|
req.msg.cmd = IPMI_SUNOEM_SET_FAN_SPEED;
|
|
req.msg.data = &speed;
|
|
req.msg.data_len = 1;
|
|
|
|
rsp = intf->sendrecv(intf, &req);
|
|
if (rsp == NULL) {
|
|
lprintf(LOG_ERR, "Sun OEM Set Fan Speed command failed");
|
|
return -1;
|
|
}
|
|
else if (rsp->ccode > 0) {
|
|
lprintf(LOG_ERR, "Sun OEM Set Fan Speed command failed: %s",
|
|
val2str(rsp->ccode, completion_code_vals));
|
|
return -1;
|
|
}
|
|
|
|
printf("Set Fan speed to %d%%\n", speed);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
__sdr_list_empty(struct sdr_record_list * head)
|
|
{
|
|
struct sdr_record_list * e, * f;
|
|
for (e = head; e != NULL; e = f) {
|
|
f = e->next;
|
|
free(e);
|
|
e = NULL;
|
|
}
|
|
head = NULL;
|
|
}
|
|
|
|
static void
|
|
led_print(const char * name, uint8_t state)
|
|
{
|
|
if (csv_output)
|
|
printf("%s,%s\n", name, val2str(state, sunoem_led_mode_vals));
|
|
else
|
|
printf("%-16s | %s\n", name, val2str(state, sunoem_led_mode_vals));
|
|
}
|
|
|
|
struct ipmi_rs *
|
|
sunoem_led_get(struct ipmi_intf * intf,
|
|
struct sdr_record_generic_locator * dev,
|
|
int ledtype)
|
|
{
|
|
struct ipmi_rs * rsp;
|
|
struct ipmi_rq req;
|
|
uint8_t rqdata[7];
|
|
int rqdata_len = 5;
|
|
|
|
if (dev == NULL)
|
|
return NULL;
|
|
|
|
rqdata[0] = dev->dev_slave_addr;
|
|
if (ledtype == 0xFF)
|
|
rqdata[1] = dev->oem;
|
|
else
|
|
rqdata[1] = ledtype;
|
|
rqdata[2] = dev->dev_access_addr;
|
|
rqdata[3] = dev->oem;
|
|
if (is_sbcmd) {
|
|
rqdata[4] = dev->entity.id;
|
|
rqdata[5] = dev->entity.instance;
|
|
rqdata[6] = 0;
|
|
rqdata_len = 7;
|
|
}
|
|
else {
|
|
rqdata[4] = 0;
|
|
}
|
|
|
|
req.msg.netfn = IPMI_NETFN_SUNOEM;
|
|
req.msg.cmd = IPMI_SUNOEM_LED_GET;
|
|
req.msg.lun = dev->lun;
|
|
req.msg.data = rqdata;
|
|
req.msg.data_len = rqdata_len;
|
|
|
|
rsp = intf->sendrecv(intf, &req);
|
|
if (rsp == NULL) {
|
|
lprintf(LOG_ERR, "Sun OEM Get LED command failed");
|
|
return NULL;
|
|
}
|
|
else if (rsp->ccode > 0) {
|
|
lprintf(LOG_ERR, "Sun OEM Get LED command failed: %s",
|
|
val2str(rsp->ccode, completion_code_vals));
|
|
return NULL;
|
|
}
|
|
|
|
return rsp;
|
|
}
|
|
|
|
struct ipmi_rs *
|
|
sunoem_led_set(struct ipmi_intf * intf,
|
|
struct sdr_record_generic_locator * dev,
|
|
int ledtype, int ledmode)
|
|
{
|
|
struct ipmi_rs * rsp;
|
|
struct ipmi_rq req;
|
|
uint8_t rqdata[9];
|
|
int rqdata_len = 7;
|
|
|
|
if (dev == NULL)
|
|
return NULL;
|
|
|
|
rqdata[0] = dev->dev_slave_addr;
|
|
if (ledtype == 0xFF)
|
|
rqdata[1] = dev->oem;
|
|
else
|
|
rqdata[1] = ledtype;
|
|
rqdata[2] = dev->dev_access_addr;
|
|
rqdata[3] = dev->oem;
|
|
rqdata[4] = ledmode;
|
|
if (is_sbcmd) {
|
|
rqdata[5] = dev->entity.id;
|
|
rqdata[6] = dev->entity.instance;
|
|
rqdata[7] = 0;
|
|
rqdata[8] = 0;
|
|
rqdata_len = 9;
|
|
}
|
|
else {
|
|
rqdata[5] = 0;
|
|
rqdata[6] = 0;
|
|
}
|
|
|
|
req.msg.netfn = IPMI_NETFN_SUNOEM;
|
|
req.msg.cmd = IPMI_SUNOEM_LED_SET;
|
|
req.msg.lun = dev->lun;
|
|
req.msg.data = rqdata;
|
|
req.msg.data_len = rqdata_len;
|
|
|
|
rsp = intf->sendrecv(intf, &req);
|
|
if (rsp == NULL) {
|
|
lprintf(LOG_ERR, "Sun OEM Set LED command failed");
|
|
return NULL;
|
|
}
|
|
else if (rsp->ccode > 0) {
|
|
lprintf(LOG_ERR, "Sun OEM Set LED command failed: %s",
|
|
val2str(rsp->ccode, completion_code_vals));
|
|
return NULL;
|
|
}
|
|
|
|
return rsp;
|
|
}
|
|
|
|
static void
|
|
sunoem_led_get_byentity(struct ipmi_intf * intf, uint8_t entity_id,
|
|
uint8_t entity_inst, int ledtype)
|
|
{
|
|
struct ipmi_rs * rsp;
|
|
struct sdr_record_list *elist, *e;
|
|
struct entity_id entity;
|
|
|
|
if (entity_id == 0)
|
|
return;
|
|
|
|
/* lookup sdrs with this entity */
|
|
memset(&entity, 0, sizeof(struct entity_id));
|
|
entity.id = entity_id;
|
|
entity.instance = entity_inst;
|
|
|
|
elist = ipmi_sdr_find_sdr_byentity(intf, &entity);
|
|
|
|
/* for each generic sensor set its led state */
|
|
for (e = elist; e != NULL; e = e->next) {
|
|
if (e->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR)
|
|
continue;
|
|
rsp = sunoem_led_get(intf, e->record.genloc, ledtype);
|
|
if (rsp && rsp->data_len == 1) {
|
|
led_print((const char *)e->record.genloc->id_string, rsp->data[0]);
|
|
}
|
|
}
|
|
|
|
__sdr_list_empty(elist);
|
|
}
|
|
|
|
static void
|
|
sunoem_led_set_byentity(struct ipmi_intf * intf, uint8_t entity_id,
|
|
uint8_t entity_inst, int ledtype, int ledmode)
|
|
{
|
|
struct ipmi_rs * rsp;
|
|
struct sdr_record_list *elist, *e;
|
|
struct entity_id entity;
|
|
|
|
if (entity_id == 0)
|
|
return;
|
|
|
|
/* lookup sdrs with this entity */
|
|
memset(&entity, 0, sizeof(struct entity_id));
|
|
entity.id = entity_id;
|
|
entity.instance = entity_inst;
|
|
|
|
elist = ipmi_sdr_find_sdr_byentity(intf, &entity);
|
|
|
|
/* for each generic sensor set its led state */
|
|
for (e = elist; e != NULL; e = e->next) {
|
|
if (e->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR)
|
|
continue;
|
|
rsp = sunoem_led_set(intf, e->record.genloc, ledtype, ledmode);
|
|
if (rsp && rsp->data_len == 0) {
|
|
led_print((const char *)e->record.genloc->id_string, ledmode);
|
|
}
|
|
}
|
|
|
|
__sdr_list_empty(elist);
|
|
}
|
|
|
|
/*
|
|
* IPMI Request Data: 5 bytes
|
|
*
|
|
* [byte 0] devAddr Value from the "Device Slave Address" field in
|
|
* LED's Generic Device Locator record in the SDR
|
|
* [byte 1] led LED Type: OK2RM, ACT, LOCATE, SERVICE
|
|
* [byte 2] ctrlrAddr Controller address; value from the "Device
|
|
* Access Address" field, 0x20 if the LED is local
|
|
* [byte 3] hwInfo The OEM field from the SDR record
|
|
* [byte 4] force 1 = directly access the device
|
|
* 0 = go thru its controller
|
|
* Ignored if LED is local
|
|
*
|
|
* The format below is for Sun Blade Modular systems only
|
|
* [byte 4] entityID The entityID field from the SDR record
|
|
* [byte 5] entityIns The entityIns field from the SDR record
|
|
* [byte 6] force 1 = directly access the device
|
|
* 0 = go thru its controller
|
|
* Ignored if LED is local
|
|
*/
|
|
static int
|
|
ipmi_sunoem_led_get(struct ipmi_intf * intf, int argc, char ** argv)
|
|
{
|
|
struct ipmi_rs * rsp;
|
|
struct sdr_record_list *sdr;
|
|
struct sdr_record_list *alist, *a;
|
|
struct sdr_record_entity_assoc *assoc;
|
|
int ledtype = 0xFF;
|
|
int i;
|
|
|
|
/*
|
|
* sunoem led/sbled get <id> [type]
|
|
*/
|
|
|
|
if (argc < 1 || strncmp(argv[0], "help", 4) == 0) {
|
|
ipmi_sunoem_usage();
|
|
return 0;
|
|
}
|
|
|
|
if (argc > 1) {
|
|
ledtype = str2val(argv[1], sunoem_led_type_vals);
|
|
if (ledtype == 0xFF)
|
|
lprintf(LOG_ERR, "Unknow ledtype, will use data from the SDR oem field");
|
|
}
|
|
|
|
if (strncasecmp(argv[0], "all", 3) == 0) {
|
|
/* do all generic sensors */
|
|
alist = ipmi_sdr_find_sdr_bytype(intf,
|
|
SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR);
|
|
for (a = alist; a != NULL; a = a->next) {
|
|
if (a->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR)
|
|
continue;
|
|
if (a->record.genloc->entity.logical)
|
|
continue;
|
|
rsp = sunoem_led_get(intf, a->record.genloc, ledtype);
|
|
if (rsp && rsp->data_len == 1) {
|
|
led_print((const char *)a->record.genloc->id_string, rsp->data[0]);
|
|
}
|
|
}
|
|
__sdr_list_empty(alist);
|
|
return 0;
|
|
}
|
|
|
|
/* look up generic device locator record in SDR */
|
|
sdr = ipmi_sdr_find_sdr_byid(intf, argv[0]);
|
|
|
|
if (sdr == NULL) {
|
|
lprintf(LOG_ERR, "No Sensor Data Record found for %s", argv[0]);
|
|
return -1;
|
|
}
|
|
|
|
if (sdr->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR) {
|
|
lprintf(LOG_ERR, "Invalid SDR type %d", sdr->type);
|
|
return -1;
|
|
}
|
|
|
|
if (!sdr->record.genloc->entity.logical) {
|
|
/*
|
|
* handle physical entity
|
|
*/
|
|
rsp = sunoem_led_get(intf, sdr->record.genloc, ledtype);
|
|
if (rsp && rsp->data_len == 1) {
|
|
led_print((const char *)sdr->record.genloc->id_string, rsp->data[0]);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* handle logical entity for LED grouping
|
|
*/
|
|
|
|
lprintf(LOG_INFO, "LED %s is logical device", argv[0]);
|
|
|
|
/* get entity assoc records */
|
|
alist = ipmi_sdr_find_sdr_bytype(intf, SDR_RECORD_TYPE_ENTITY_ASSOC);
|
|
for (a = alist; a != NULL; a = a->next) {
|
|
if (a->type != SDR_RECORD_TYPE_ENTITY_ASSOC)
|
|
continue;
|
|
assoc = a->record.entassoc;
|
|
if (assoc == NULL)
|
|
continue;
|
|
|
|
/* check that the entity id/instance matches our generic record */
|
|
if (assoc->entity.id != sdr->record.genloc->entity.id ||
|
|
assoc->entity.instance != sdr->record.genloc->entity.instance)
|
|
continue;
|
|
|
|
if (assoc->flags.isrange) {
|
|
/*
|
|
* handle ranged entity associations
|
|
*
|
|
* the test for non-zero entity id is handled in
|
|
* sunoem_led_get_byentity()
|
|
*/
|
|
|
|
/* first range set - id 1 and 2 must be equal */
|
|
if (assoc->entity_id_1 == assoc->entity_id_2)
|
|
for (i = assoc->entity_inst_1; i <= assoc->entity_inst_2; i++)
|
|
sunoem_led_get_byentity(intf, assoc->entity_id_1, i, ledtype);
|
|
|
|
/* second range set - id 3 and 4 must be equal */
|
|
if (assoc->entity_id_3 == assoc->entity_id_4)
|
|
for (i = assoc->entity_inst_3; i <= assoc->entity_inst_4; i++)
|
|
sunoem_led_get_byentity(intf, assoc->entity_id_3, i, ledtype);
|
|
}
|
|
else {
|
|
/*
|
|
* handle entity list
|
|
*/
|
|
sunoem_led_get_byentity(intf, assoc->entity_id_1,
|
|
assoc->entity_inst_1, ledtype);
|
|
sunoem_led_get_byentity(intf, assoc->entity_id_2,
|
|
assoc->entity_inst_2, ledtype);
|
|
sunoem_led_get_byentity(intf, assoc->entity_id_3,
|
|
assoc->entity_inst_3, ledtype);
|
|
sunoem_led_get_byentity(intf, assoc->entity_id_4,
|
|
assoc->entity_inst_4, ledtype);
|
|
}
|
|
}
|
|
|
|
__sdr_list_empty(alist);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* IPMI Request Data: 7 bytes
|
|
*
|
|
* [byte 0] devAddr Value from the "Device Slave Address" field in
|
|
* LED's Generic Device Locator record in the SDR
|
|
* [byte 1] led LED Type: OK2RM, ACT, LOCATE, SERVICE
|
|
* [byte 2] ctrlrAddr Controller address; value from the "Device
|
|
* Access Address" field, 0x20 if the LED is local
|
|
* [byte 3] hwInfo The OEM field from the SDR record
|
|
* [byte 4] mode LED Mode: OFF, ON, STANDBY, SLOW, FAST
|
|
* [byte 5] force TRUE - directly access the device
|
|
* FALSE - go thru its controller
|
|
* Ignored if LED is local
|
|
* [byte 6] role Used by BMC for authorization purposes
|
|
*
|
|
* The format below is for Sun Blade Modular systems only
|
|
* [byte 5] entityID The entityID field from the SDR record
|
|
* [byte 6] entityIns The entityIns field from the SDR record
|
|
* [byte 7] force TRUE - directly access the device
|
|
* FALSE - go thru its controller
|
|
* Ignored if LED is local
|
|
* [byte 8] role Used by BMC for authorization purposes
|
|
*
|
|
*
|
|
* IPMI Response Data: 1 byte
|
|
*
|
|
* [byte 0] mode LED Mode: OFF, ON, STANDBY, SLOW, FAST
|
|
*/
|
|
|
|
static int
|
|
ipmi_sunoem_led_set(struct ipmi_intf * intf, int argc, char ** argv)
|
|
{
|
|
struct ipmi_rs * rsp;
|
|
struct sdr_record_list *sdr;
|
|
struct sdr_record_list *alist, *a;
|
|
struct sdr_record_entity_assoc *assoc;
|
|
int ledmode;
|
|
int ledtype = 0xFF;
|
|
int i;
|
|
|
|
/*
|
|
* sunoem led/sbled set <id> <mode> [type]
|
|
*/
|
|
|
|
if (argc < 2 || strncmp(argv[0], "help", 4) == 0) {
|
|
ipmi_sunoem_usage();
|
|
return 0;
|
|
}
|
|
|
|
ledmode = str2val(argv[1], sunoem_led_mode_vals);
|
|
if (ledmode == 0xFF) {
|
|
ledmode = str2val(argv[1], sunoem_led_mode_optvals);
|
|
if (ledmode == 0xFF) {
|
|
lprintf(LOG_NOTICE, "Invalid LED Mode: %s", argv[1]);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
if (argc > 3) {
|
|
ledtype = str2val(argv[2], sunoem_led_type_vals);
|
|
if (ledtype == 0xFF)
|
|
lprintf(LOG_ERR, "Unknow ledtype, will use data from the SDR oem field");
|
|
}
|
|
|
|
if (strncasecmp(argv[0], "all", 3) == 0) {
|
|
/* do all generic sensors */
|
|
alist = ipmi_sdr_find_sdr_bytype(intf,
|
|
SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR);
|
|
for (a = alist; a != NULL; a = a->next) {
|
|
if (a->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR)
|
|
continue;
|
|
if (a->record.genloc->entity.logical)
|
|
continue;
|
|
rsp = sunoem_led_set(intf, a->record.genloc, ledtype, ledmode);
|
|
if (rsp && rsp->ccode == 0) {
|
|
led_print((const char *)a->record.genloc->id_string, ledmode);
|
|
}
|
|
}
|
|
__sdr_list_empty(alist);
|
|
return 0;
|
|
}
|
|
|
|
/* look up generic device locator records in SDR */
|
|
sdr = ipmi_sdr_find_sdr_byid(intf, argv[0]);
|
|
|
|
if (sdr == NULL) {
|
|
lprintf(LOG_ERR, "No Sensor Data Record found for %s",
|
|
argv[0]);
|
|
return -1;
|
|
}
|
|
|
|
if (sdr->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR) {
|
|
lprintf(LOG_ERR, "Invalid SDR type %d", sdr->type);
|
|
return -1;
|
|
}
|
|
|
|
if (!sdr->record.genloc->entity.logical) {
|
|
/*
|
|
* handle physical entity
|
|
*/
|
|
rsp = sunoem_led_set(intf, sdr->record.genloc, ledtype, ledmode);
|
|
if (rsp && rsp->ccode == 0) {
|
|
led_print(argv[0], ledmode);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* handle logical entity for LED grouping
|
|
*/
|
|
|
|
lprintf(LOG_INFO, "LED %s is logical device", argv[0]);
|
|
|
|
/* get entity assoc records */
|
|
alist = ipmi_sdr_find_sdr_bytype(intf, SDR_RECORD_TYPE_ENTITY_ASSOC);
|
|
for (a = alist; a != NULL; a = a->next) {
|
|
if (a->type != SDR_RECORD_TYPE_ENTITY_ASSOC)
|
|
continue;
|
|
assoc = a->record.entassoc;
|
|
if (assoc == NULL)
|
|
continue;
|
|
|
|
/* check that the entity id/instance matches our generic record */
|
|
if (assoc->entity.id != sdr->record.genloc->entity.id ||
|
|
assoc->entity.instance != sdr->record.genloc->entity.instance)
|
|
continue;
|
|
|
|
if (assoc->flags.isrange) {
|
|
/*
|
|
* handle ranged entity associations
|
|
*
|
|
* the test for non-zero entity id is handled in
|
|
* sunoem_led_get_byentity()
|
|
*/
|
|
|
|
/* first range set - id 1 and 2 must be equal */
|
|
if (assoc->entity_id_1 == assoc->entity_id_2)
|
|
for (i = assoc->entity_inst_1; i <= assoc->entity_inst_2; i++)
|
|
sunoem_led_set_byentity(intf, assoc->entity_id_1, i, ledtype,
|
|
ledmode);
|
|
|
|
/* second range set - id 3 and 4 must be equal */
|
|
if (assoc->entity_id_3 == assoc->entity_id_4)
|
|
for (i = assoc->entity_inst_3; i <= assoc->entity_inst_4; i++)
|
|
sunoem_led_set_byentity(intf, assoc->entity_id_3, i, ledtype,
|
|
ledmode);
|
|
}
|
|
else {
|
|
/*
|
|
* handle entity list
|
|
*/
|
|
sunoem_led_set_byentity(intf, assoc->entity_id_1,
|
|
assoc->entity_inst_1, ledtype, ledmode);
|
|
sunoem_led_set_byentity(intf, assoc->entity_id_2,
|
|
assoc->entity_inst_2, ledtype, ledmode);
|
|
sunoem_led_set_byentity(intf, assoc->entity_id_3,
|
|
assoc->entity_inst_3, ledtype, ledmode);
|
|
sunoem_led_set_byentity(intf, assoc->entity_id_4,
|
|
assoc->entity_inst_4, ledtype, ledmode);
|
|
}
|
|
}
|
|
|
|
__sdr_list_empty(alist);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
ipmi_sunoem_sshkey_del(struct ipmi_intf * intf, uint8_t uid)
|
|
{
|
|
struct ipmi_rs * rsp;
|
|
struct ipmi_rq req;
|
|
|
|
memset(&req, 0, sizeof(struct ipmi_rq));
|
|
req.msg.netfn = IPMI_NETFN_SUNOEM;
|
|
req.msg.cmd = IPMI_SUNOEM_DEL_SSH_KEY;
|
|
req.msg.data = &uid;
|
|
req.msg.data_len = 1;
|
|
|
|
rsp = intf->sendrecv(intf, &req);
|
|
if (rsp == NULL) {
|
|
lprintf(LOG_ERR, "Unable to delete ssh key for UID %d", uid);
|
|
return -1;
|
|
}
|
|
else if (rsp->ccode > 0) {
|
|
lprintf(LOG_ERR, "Unable to delete ssh key for UID %d: %s", uid,
|
|
val2str(rsp->ccode, completion_code_vals));
|
|
return -1;
|
|
}
|
|
|
|
printf("Deleted SSH key for user id %d\n", uid);
|
|
return 0;
|
|
}
|
|
|
|
#define SSHKEY_BLOCK_SIZE 64
|
|
static int
|
|
ipmi_sunoem_sshkey_set(struct ipmi_intf * intf, uint8_t uid, char * ifile)
|
|
{
|
|
struct ipmi_rs * rsp;
|
|
struct ipmi_rq req;
|
|
FILE * fp;
|
|
int count;
|
|
uint16_t i_size, r, size;
|
|
uint8_t wbuf[SSHKEY_BLOCK_SIZE + 3];
|
|
|
|
if (ifile == NULL) {
|
|
lprintf(LOG_ERR, "Invalid or misisng input filename");
|
|
return -1;
|
|
}
|
|
|
|
fp = ipmi_open_file_read(ifile);
|
|
if (fp == NULL) {
|
|
lprintf(LOG_ERR, "Unable to open file %s for reading", ifile);
|
|
return -1;
|
|
}
|
|
|
|
printf("Setting SSH key for user id %d...", uid);
|
|
|
|
memset(&req, 0, sizeof(struct ipmi_rq));
|
|
req.msg.netfn = IPMI_NETFN_SUNOEM;
|
|
req.msg.cmd = IPMI_SUNOEM_SET_SSH_KEY;
|
|
req.msg.data = wbuf;
|
|
|
|
fseek(fp, 0, SEEK_END);
|
|
size = ftell(fp);
|
|
fseek(fp, 0, SEEK_SET);
|
|
|
|
for (r = 0; r < size; r += i_size) {
|
|
i_size = size - r;
|
|
if (i_size > SSHKEY_BLOCK_SIZE)
|
|
i_size = SSHKEY_BLOCK_SIZE;
|
|
|
|
memset(wbuf, 0, SSHKEY_BLOCK_SIZE);
|
|
if (-1 == fseek(fp, r, SEEK_SET)) {
|
|
lprintf(LOG_ERR, "Seek error %s. %s", ifile, strerror(errno));
|
|
return -1;
|
|
}
|
|
count = fread(wbuf+3, 1, i_size, fp);
|
|
if (count != i_size) {
|
|
lprintf(LOG_ERR, "Unable to read %d bytes from file %s", i_size, ifile);
|
|
fclose(fp);
|
|
return -1;
|
|
}
|
|
|
|
printf(".");
|
|
fflush(stdout);
|
|
|
|
wbuf[0] = uid;
|
|
if ((r + SSHKEY_BLOCK_SIZE) >= size)
|
|
wbuf[1] = 0xff;
|
|
else
|
|
wbuf[1] = (uint8_t)(r / SSHKEY_BLOCK_SIZE);
|
|
wbuf[2] = i_size;
|
|
req.msg.data_len = i_size + 3;
|
|
|
|
rsp = intf->sendrecv(intf, &req);
|
|
if (rsp == NULL) {
|
|
lprintf(LOG_ERR, "Unable to set ssh key for UID %d", uid);
|
|
break;
|
|
}
|
|
}
|
|
|
|
printf("done\n");
|
|
|
|
fclose(fp);
|
|
return 0;
|
|
}
|
|
|
|
|
|
int
|
|
ipmi_sunoem_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
{
|
|
int rc = (-1);
|
|
|
|
if (argc == 0 || strncmp(argv[0], "help", 4) == 0) {
|
|
ipmi_sunoem_usage();
|
|
return 0;
|
|
}
|
|
|
|
if (strncmp(argv[0], "fan", 3) == 0) {
|
|
if (argc == 3 && strncmp(argv[1], "speed", 5) == 0) {
|
|
uint8_t pct = 0;
|
|
if (str2uchar(argv[2], &pct) != 0 || pct > 100) {
|
|
lprintf(LOG_ERR, "Fan speed is limited to range <0..100>.");
|
|
return (-1);
|
|
}
|
|
rc = ipmi_sunoem_fan_speed(intf, pct);
|
|
}
|
|
else {
|
|
ipmi_sunoem_usage();
|
|
return (-1);
|
|
}
|
|
}
|
|
else if ((strncmp(argv[0], "led", 3) == 0)
|
|
|| (strncmp(argv[0], "sbled", 5) == 0)) {
|
|
if (argc < 2) {
|
|
ipmi_sunoem_usage();
|
|
return (-1);
|
|
}
|
|
if (strncmp(argv[0], "sbled", 5) == 0) {
|
|
is_sbcmd = 1;
|
|
}
|
|
if (strncmp(argv[1], "get", 3) == 0) {
|
|
if (argc < 3) {
|
|
char * arg[] = { "all" };
|
|
rc = ipmi_sunoem_led_get(intf, 1, arg);
|
|
}
|
|
else {
|
|
rc = ipmi_sunoem_led_get(intf, argc-2, &(argv[2]));
|
|
}
|
|
}
|
|
else if (strncmp(argv[1], "set", 3) == 0) {
|
|
if (argc < 4) {
|
|
ipmi_sunoem_usage();
|
|
return (-1);
|
|
}
|
|
rc = ipmi_sunoem_led_set(intf, argc-2, &(argv[2]));
|
|
}
|
|
else {
|
|
ipmi_sunoem_usage();
|
|
return (-1);
|
|
}
|
|
}
|
|
else if (strncmp(argv[0], "sshkey", 6) == 0) {
|
|
uint8_t uid = 0;
|
|
if (argc < 3) {
|
|
ipmi_sunoem_usage();
|
|
return (-1);
|
|
}
|
|
|
|
if (str2uchar(argv[2], &uid) != 0 || uid < 1 || uid > 63) {
|
|
lprintf(LOG_ERR, "User ID is limited to range <1..63>.");
|
|
return (-1);
|
|
}
|
|
|
|
if (strncmp(argv[1], "del", 3) == 0) {
|
|
rc = ipmi_sunoem_sshkey_del(intf, uid);
|
|
}
|
|
else if (argc == 4 && strncmp(argv[1], "set", 3) == 0) {
|
|
rc = ipmi_sunoem_sshkey_set(intf, uid, argv[3]);
|
|
}
|
|
else {
|
|
ipmi_sunoem_usage();
|
|
return (-1);
|
|
}
|
|
}
|
|
else {
|
|
ipmi_sunoem_usage();
|
|
return (-1);
|
|
}
|
|
|
|
return rc;
|
|
}
|