Blame lib/ipmi_sol.c

Packit Service ed0f68
/*                                 
Packit Service ed0f68
 * Copyright (c) 2003 Sun Microsystems, Inc.  All Rights Reserved.
Packit Service ed0f68
 * 
Packit Service ed0f68
 * Redistribution and use in source and binary forms, with or without
Packit Service ed0f68
 * modification, are permitted provided that the following conditions
Packit Service ed0f68
 * are met:
Packit Service ed0f68
 * 
Packit Service ed0f68
 * Redistribution of source code must retain the above copyright
Packit Service ed0f68
 * notice, this list of conditions and the following disclaimer.
Packit Service ed0f68
 * 
Packit Service ed0f68
 * Redistribution in binary form must reproduce the above copyright
Packit Service ed0f68
 * notice, this list of conditions and the following disclaimer in the
Packit Service ed0f68
 * documentation and/or other materials provided with the distribution.
Packit Service ed0f68
 * 
Packit Service ed0f68
 * Neither the name of Sun Microsystems, Inc. or the names of
Packit Service ed0f68
 * contributors may be used to endorse or promote products derived
Packit Service ed0f68
 * from this software without specific prior written permission.
Packit Service ed0f68
 * 
Packit Service ed0f68
 * This software is provided "AS IS," without a warranty of any kind.
Packit Service ed0f68
 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
Packit Service ed0f68
 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
Packit Service ed0f68
 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
Packit Service ed0f68
 * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
Packit Service ed0f68
 * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
Packit Service ed0f68
 * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.  IN NO EVENT WILL
Packit Service ed0f68
 * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
Packit Service ed0f68
 * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
Packit Service ed0f68
 * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
Packit Service ed0f68
 * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
Packit Service ed0f68
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
Packit Service ed0f68
 */
Packit Service ed0f68
#define _XOPEN_SOURCE
Packit Service ed0f68
#define _BSD_SOURCE || \
Packit Service ed0f68
	(_XOPEN_SOURCE >= 500 || \
Packit Service ed0f68
                       _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED) && \
Packit Service ed0f68
	!(_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700)
Packit Service ed0f68
Packit Service ed0f68
#include <stdlib.h>
Packit Service ed0f68
#include <string.h>
Packit Service ed0f68
#include <strings.h>
Packit Service ed0f68
#include <stdio.h>
Packit Service ed0f68
#include <sys/types.h>
Packit Service ed0f68
#include <sys/stat.h>
Packit Service ed0f68
#include <sys/select.h>
Packit Service ed0f68
#include <sys/time.h>
Packit Service ed0f68
#include <time.h>
Packit Service ed0f68
#include <signal.h>
Packit Service ed0f68
#include <unistd.h>
Packit Service ed0f68
Packit Service ed0f68
#if defined(HAVE_CONFIG_H)
Packit Service ed0f68
# include <config.h>
Packit Service ed0f68
#endif
Packit Service ed0f68
Packit Service ed0f68
#if defined(HAVE_TERMIOS_H)
Packit Service ed0f68
# include <termios.h>
Packit Service ed0f68
#elif defined (HAVE_SYS_TERMIOS_H)
Packit Service ed0f68
# include <sys/termios.h>
Packit Service ed0f68
#endif
Packit Service ed0f68
Packit Service ed0f68
#include <ipmitool/helper.h>
Packit Service ed0f68
#include <ipmitool/log.h>
Packit Service ed0f68
#include <ipmitool/ipmi.h>
Packit Service ed0f68
#include <ipmitool/ipmi_intf.h>
Packit Service ed0f68
#include <ipmitool/ipmi_sol.h>
Packit Service ed0f68
#include <ipmitool/ipmi_strings.h>
Packit Service ed0f68
#include <ipmitool/bswap.h>
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
#define SOL_PARAMETER_SET_IN_PROGRESS           0x00
Packit Service ed0f68
#define SOL_PARAMETER_SOL_ENABLE                0x01
Packit Service ed0f68
#define SOL_PARAMETER_SOL_AUTHENTICATION        0x02
Packit Service ed0f68
#define SOL_PARAMETER_CHARACTER_INTERVAL        0x03
Packit Service ed0f68
#define SOL_PARAMETER_SOL_RETRY                 0x04
Packit Service ed0f68
#define SOL_PARAMETER_SOL_NON_VOLATILE_BIT_RATE 0x05
Packit Service ed0f68
#define SOL_PARAMETER_SOL_VOLATILE_BIT_RATE     0x06
Packit Service ed0f68
#define SOL_PARAMETER_SOL_PAYLOAD_CHANNEL       0x07
Packit Service ed0f68
#define SOL_PARAMETER_SOL_PAYLOAD_PORT          0x08
Packit Service ed0f68
Packit Service ed0f68
#define MAX_SOL_RETRY 6
Packit Service ed0f68
Packit Service ed0f68
const struct valstr sol_parameter_vals[] = {
Packit Service ed0f68
	{ SOL_PARAMETER_SET_IN_PROGRESS,           "Set In Progress (0)" },
Packit Service ed0f68
	{ SOL_PARAMETER_SOL_ENABLE,                "Enable (1)" },
Packit Service ed0f68
	{ SOL_PARAMETER_SOL_AUTHENTICATION,        "Authentication (2)" },
Packit Service ed0f68
	{ SOL_PARAMETER_CHARACTER_INTERVAL,        "Character Interval (3)" },
Packit Service ed0f68
	{ SOL_PARAMETER_SOL_RETRY,                 "Retry (4)" },
Packit Service ed0f68
	{ SOL_PARAMETER_SOL_NON_VOLATILE_BIT_RATE, "Nonvolatile Bitrate (5)" },
Packit Service ed0f68
	{ SOL_PARAMETER_SOL_VOLATILE_BIT_RATE,     "Volatile Bitrate (6)" },
Packit Service ed0f68
	{ SOL_PARAMETER_SOL_PAYLOAD_CHANNEL,       "Payload Channel (7)" },
Packit Service ed0f68
	{ SOL_PARAMETER_SOL_PAYLOAD_PORT,          "Payload Port (8)" },
Packit Service ed0f68
	{ 0x00, NULL },
Packit Service ed0f68
};
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
static struct timeval _start_keepalive;
Packit Service ed0f68
static struct termios _saved_tio;
Packit Service ed0f68
static int            _in_raw_mode = 0;
Packit Service ed0f68
static int            _disable_keepalive = 0;
Packit Service ed0f68
static int            _use_sol_for_keepalive = 0;
Packit Service ed0f68
Packit Service ed0f68
extern int verbose;
Packit Service ed0f68
Packit Service ed0f68
/*
Packit Service ed0f68
 * ipmi_sol_payload_access
Packit Service ed0f68
 */
Packit Service ed0f68
int
Packit Service ed0f68
ipmi_sol_payload_access(struct ipmi_intf * intf, uint8_t channel,
Packit Service ed0f68
		uint8_t userid, int enable)
Packit Service ed0f68
{
Packit Service ed0f68
	struct ipmi_rq req;
Packit Service ed0f68
	struct ipmi_rs *rsp;
Packit Service ed0f68
	int rc = (-1);
Packit Service ed0f68
	uint8_t data[6];
Packit Service ed0f68
Packit Service ed0f68
	memset(&req, 0, sizeof(req));
Packit Service ed0f68
	req.msg.netfn = IPMI_NETFN_APP;
Packit Service ed0f68
	req.msg.cmd = IPMI_SET_USER_PAYLOAD_ACCESS;
Packit Service ed0f68
	req.msg.data = data;
Packit Service ed0f68
	req.msg.data_len = 6;
Packit Service ed0f68
Packit Service ed0f68
	memset(data, 0, 6);
Packit Service ed0f68
	/* channel */
Packit Service ed0f68
	data[0] = channel & 0xf;
Packit Service ed0f68
	/* user id */
Packit Service ed0f68
	data[1] = userid & 0x3f;
Packit Service ed0f68
	if (!enable) {
Packit Service ed0f68
		/* disable */
Packit Service ed0f68
		data[1] |= 0x40;
Packit Service ed0f68
	}
Packit Service ed0f68
	/* payload 1 is SOL */
Packit Service ed0f68
	data[2] = 0x02;
Packit Service ed0f68
	rsp = intf->sendrecv(intf, &req;;
Packit Service ed0f68
	if (rsp == NULL) {
Packit Service ed0f68
		lprintf(LOG_ERR, "Error %sabling SOL payload for user %d on channel %d",
Packit Service ed0f68
				enable ? "en" : "dis", userid, channel);
Packit Service ed0f68
		rc = (-1);
Packit Service ed0f68
	} else if (rsp->ccode != 0) {
Packit Service ed0f68
		lprintf(LOG_ERR, "Error %sabling SOL payload for user %d on channel %d: %s",
Packit Service ed0f68
				enable ? "en" : "dis", userid, channel,
Packit Service ed0f68
				val2str(rsp->ccode, completion_code_vals));
Packit Service ed0f68
		rc = (-1);
Packit Service ed0f68
	} else {
Packit Service ed0f68
		rc = 0;
Packit Service ed0f68
	}
Packit Service ed0f68
	return rc;
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
int
Packit Service ed0f68
ipmi_sol_payload_access_status(struct ipmi_intf * intf,
Packit Service ed0f68
				uint8_t channel,
Packit Service ed0f68
				uint8_t userid)
Packit Service ed0f68
{
Packit Service ed0f68
	struct ipmi_rq req;
Packit Service ed0f68
	struct ipmi_rs *rsp;
Packit Service ed0f68
	uint8_t data[2];
Packit Service ed0f68
Packit Service ed0f68
	memset(&req, 0, sizeof(req));
Packit Service ed0f68
	req.msg.netfn    = IPMI_NETFN_APP;
Packit Service ed0f68
	req.msg.cmd      = IPMI_GET_USER_PAYLOAD_ACCESS;
Packit Service ed0f68
	req.msg.data     = data;
Packit Service ed0f68
	req.msg.data_len = sizeof(data);
Packit Service ed0f68
Packit Service ed0f68
	data[0] = channel & 0xf;	/* channel */
Packit Service ed0f68
	data[1] = userid & 0x3f;	/* user id */
Packit Service ed0f68
	rsp = intf->sendrecv(intf, &req;;
Packit Service ed0f68
Packit Service ed0f68
	if (rsp == NULL) {
Packit Service ed0f68
		lprintf(LOG_ERR, "Error. No valid response received.");
Packit Service ed0f68
		return -1;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	switch(rsp->ccode) {
Packit Service ed0f68
		case 0x00:
Packit Service ed0f68
			if (rsp->data_len != 4) {
Packit Service ed0f68
				lprintf(LOG_ERR, "Error parsing SOL payload status for user %d on channel %d",
Packit Service ed0f68
					userid, channel);
Packit Service ed0f68
				return -1;
Packit Service ed0f68
			}
Packit Service ed0f68
Packit Service ed0f68
			printf("User %d on channel %d is %sabled\n",
Packit Service ed0f68
				userid, channel, (rsp->data[0] & 0x02) ? "en":"dis");
Packit Service ed0f68
			return 0;
Packit Service ed0f68
Packit Service ed0f68
		default:
Packit Service ed0f68
			lprintf(LOG_ERR, "Error getting SOL payload status for user %d on channel %d: %s",
Packit Service ed0f68
				userid, channel, 
Packit Service ed0f68
				val2str(rsp->ccode, completion_code_vals));
Packit Service ed0f68
			return -1;
Packit Service ed0f68
	}
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
/*
Packit Service ed0f68
 * ipmi_get_sol_info
Packit Service ed0f68
 */
Packit Service ed0f68
int
Packit Service ed0f68
ipmi_get_sol_info(
Packit Service ed0f68
				  struct ipmi_intf * intf,
Packit Service ed0f68
				  uint8_t channel,
Packit Service ed0f68
				  struct sol_config_parameters * params)
Packit Service ed0f68
{
Packit Service ed0f68
	struct ipmi_rs * rsp;
Packit Service ed0f68
	struct ipmi_rq req;
Packit Service ed0f68
	uint8_t data[4];
Packit Service ed0f68
Packit Service ed0f68
	memset(&req, 0, sizeof(req));
Packit Service ed0f68
	req.msg.netfn    = IPMI_NETFN_TRANSPORT;
Packit Service ed0f68
	req.msg.cmd      = IPMI_GET_SOL_CONFIG_PARAMETERS;
Packit Service ed0f68
	req.msg.data_len = 4;
Packit Service ed0f68
	req.msg.data     = data;
Packit Service ed0f68
Packit Service ed0f68
	/*
Packit Service ed0f68
	 * set in progress
Packit Service ed0f68
	 */
Packit Service ed0f68
	memset(data, 0, sizeof(data));
Packit Service ed0f68
	data[0] = channel;                       /* channel number     */
Packit Service ed0f68
	data[1] = SOL_PARAMETER_SET_IN_PROGRESS; /* parameter selector */
Packit Service ed0f68
	data[2] = 0x00;                          /* set selector       */
Packit Service ed0f68
	data[3] = 0x00;                          /* block selector     */
Packit Service ed0f68
Packit Service ed0f68
	rsp = intf->sendrecv(intf, &req;;
Packit Service ed0f68
	if (rsp == NULL) {
Packit Service ed0f68
		lprintf(LOG_ERR, "Error: No response requesting SOL parameter '%s'",
Packit Service ed0f68
				val2str(data[1], sol_parameter_vals));
Packit Service ed0f68
		return (-1);
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	switch (rsp->ccode) {
Packit Service ed0f68
		case 0x00:
Packit Service ed0f68
			if (rsp->data_len == 2) {
Packit Service ed0f68
				params->set_in_progress = rsp->data[1];
Packit Service ed0f68
			} else {
Packit Service ed0f68
				lprintf(LOG_ERR, "Error: Unexpected data length (%d) received "
Packit Service ed0f68
						"for SOL parameter '%s'",
Packit Service ed0f68
						rsp->data_len,
Packit Service ed0f68
						val2str(data[1], sol_parameter_vals));
Packit Service ed0f68
			}
Packit Service ed0f68
			break;
Packit Service ed0f68
		case 0x80:
Packit Service ed0f68
			lprintf(LOG_ERR, "Info: SOL parameter '%s' not supported",
Packit Service ed0f68
					val2str(data[1], sol_parameter_vals));
Packit Service ed0f68
			break;
Packit Service ed0f68
		default:
Packit Service ed0f68
			lprintf(LOG_ERR, "Error requesting SOL parameter '%s': %s",
Packit Service ed0f68
				val2str(data[1], sol_parameter_vals),
Packit Service ed0f68
				val2str(rsp->ccode, completion_code_vals));
Packit Service ed0f68
			return (-1);
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	/*
Packit Service ed0f68
	 * SOL enable
Packit Service ed0f68
	 */
Packit Service ed0f68
	memset(data, 0, sizeof(data));
Packit Service ed0f68
	data[0] = channel;                  /* channel number     */
Packit Service ed0f68
	data[1] = SOL_PARAMETER_SOL_ENABLE; /* parameter selector */
Packit Service ed0f68
	data[2] = 0x00;                     /* set selector       */
Packit Service ed0f68
	data[3] = 0x00;                     /* block selector     */
Packit Service ed0f68
Packit Service ed0f68
	rsp = intf->sendrecv(intf, &req;;
Packit Service ed0f68
	if (rsp == NULL) {
Packit Service ed0f68
		lprintf(LOG_ERR, "Error: No response requesting SOL parameter '%s'",
Packit Service ed0f68
				val2str(data[1], sol_parameter_vals));
Packit Service ed0f68
		return (-1);
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	switch (rsp->ccode) {
Packit Service ed0f68
		case 0x00:
Packit Service ed0f68
			if (rsp->data_len == 2) {
Packit Service ed0f68
				params->enabled = rsp->data[1];
Packit Service ed0f68
			} else {
Packit Service ed0f68
				lprintf(LOG_ERR, "Error: Unexpected data length (%d) received "
Packit Service ed0f68
						"for SOL parameter '%s'",
Packit Service ed0f68
						rsp->data_len,
Packit Service ed0f68
						val2str(data[1], sol_parameter_vals));
Packit Service ed0f68
			}
Packit Service ed0f68
			break;
Packit Service ed0f68
		case 0x80:
Packit Service ed0f68
			lprintf(LOG_ERR, "Info: SOL parameter '%s' not supported",
Packit Service ed0f68
					val2str(data[1], sol_parameter_vals));
Packit Service ed0f68
			break;
Packit Service ed0f68
		default:
Packit Service ed0f68
			lprintf(LOG_ERR, "Error requesting SOL parameter '%s': %s",
Packit Service ed0f68
				val2str(data[1], sol_parameter_vals),
Packit Service ed0f68
				val2str(rsp->ccode, completion_code_vals));
Packit Service ed0f68
			return (-1);
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	/*
Packit Service ed0f68
	 * SOL authentication
Packit Service ed0f68
	 */
Packit Service ed0f68
	memset(data, 0, sizeof(data));
Packit Service ed0f68
	data[0] = channel;                          /* channel number     */
Packit Service ed0f68
	data[1] = SOL_PARAMETER_SOL_AUTHENTICATION; /* parameter selector */
Packit Service ed0f68
	data[2] = 0x00;                             /* set selector       */
Packit Service ed0f68
	data[3] = 0x00;                             /* block selector     */
Packit Service ed0f68
Packit Service ed0f68
	rsp = intf->sendrecv(intf, &req;;
Packit Service ed0f68
	if (rsp == NULL) {
Packit Service ed0f68
		lprintf(LOG_ERR, "Error: No response requesting SOL parameter '%s'",
Packit Service ed0f68
				val2str(data[1], sol_parameter_vals));
Packit Service ed0f68
		return (-1);
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	switch (rsp->ccode) {
Packit Service ed0f68
		case 0x00:
Packit Service ed0f68
			if (rsp->data_len == 2) {
Packit Service ed0f68
				params->force_encryption     = ((rsp->data[1] & 0x80)? 1 : 0);
Packit Service ed0f68
				params->force_authentication = ((rsp->data[1] & 0x40)? 1 : 0);
Packit Service ed0f68
				params->privilege_level      = rsp->data[1] & 0x0F;
Packit Service ed0f68
			} else {
Packit Service ed0f68
				lprintf(LOG_ERR, "Error: Unexpected data length (%d) received "
Packit Service ed0f68
						"for SOL parameter '%s'",
Packit Service ed0f68
						rsp->data_len,
Packit Service ed0f68
						val2str(data[1], sol_parameter_vals));
Packit Service ed0f68
			}
Packit Service ed0f68
			break;
Packit Service ed0f68
		case 0x80:
Packit Service ed0f68
			lprintf(LOG_ERR, "Info: SOL parameter '%s' not supported",
Packit Service ed0f68
					val2str(data[1], sol_parameter_vals));
Packit Service ed0f68
			break;
Packit Service ed0f68
		default:
Packit Service ed0f68
			lprintf(LOG_ERR, "Error requesting SOL parameter '%s': %s",
Packit Service ed0f68
				val2str(data[1], sol_parameter_vals),
Packit Service ed0f68
				val2str(rsp->ccode, completion_code_vals));
Packit Service ed0f68
			return (-1);
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	/*
Packit Service ed0f68
	 * Character accumulate interval and character send interval
Packit Service ed0f68
	 */
Packit Service ed0f68
	memset(data, 0, sizeof(data));
Packit Service ed0f68
	data[0] = channel;                          /* channel number     */
Packit Service ed0f68
	data[1] = SOL_PARAMETER_CHARACTER_INTERVAL; /* parameter selector */
Packit Service ed0f68
	data[2] = 0x00;                             /* set selector       */
Packit Service ed0f68
	data[3] = 0x00;                             /* block selector     */
Packit Service ed0f68
Packit Service ed0f68
	rsp = intf->sendrecv(intf, &req;;
Packit Service ed0f68
	if (rsp == NULL) {
Packit Service ed0f68
		lprintf(LOG_ERR, "Error: No response requesting SOL parameter '%s'",
Packit Service ed0f68
				val2str(data[1], sol_parameter_vals));
Packit Service ed0f68
		return (-1);
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	switch (rsp->ccode) {
Packit Service ed0f68
		case 0x00:
Packit Service ed0f68
			if (rsp->data_len == 3) {
Packit Service ed0f68
				params->character_accumulate_level = rsp->data[1];
Packit Service ed0f68
				params->character_send_threshold   = rsp->data[2];
Packit Service ed0f68
			} else {
Packit Service ed0f68
				lprintf(LOG_ERR, "Error: Unexpected data length (%d) received "
Packit Service ed0f68
						"for SOL parameter '%s'",
Packit Service ed0f68
						rsp->data_len,
Packit Service ed0f68
						val2str(data[1], sol_parameter_vals));
Packit Service ed0f68
			}
Packit Service ed0f68
			break;
Packit Service ed0f68
		case 0x80:
Packit Service ed0f68
			lprintf(LOG_ERR, "Info: SOL parameter '%s' not supported",
Packit Service ed0f68
					val2str(data[1], sol_parameter_vals));
Packit Service ed0f68
			break;
Packit Service ed0f68
		default:
Packit Service ed0f68
			lprintf(LOG_ERR, "Error requesting SOL parameter '%s': %s",
Packit Service ed0f68
				val2str(data[1], sol_parameter_vals),
Packit Service ed0f68
				val2str(rsp->ccode, completion_code_vals));
Packit Service ed0f68
			return (-1);
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	/*
Packit Service ed0f68
	 * SOL retry
Packit Service ed0f68
	 */
Packit Service ed0f68
	memset(data, 0, sizeof(data));
Packit Service ed0f68
	data[0] = channel;                 /* channel number     */
Packit Service ed0f68
	data[1] = SOL_PARAMETER_SOL_RETRY; /* parameter selector */
Packit Service ed0f68
	data[2] = 0x00;                    /* set selector       */
Packit Service ed0f68
	data[3] = 0x00;                    /* block selector     */
Packit Service ed0f68
Packit Service ed0f68
	rsp = intf->sendrecv(intf, &req;;
Packit Service ed0f68
	if (rsp == NULL) {
Packit Service ed0f68
		lprintf(LOG_ERR, "Error: No response requesting SOL parameter '%s'",
Packit Service ed0f68
				val2str(data[1], sol_parameter_vals));
Packit Service ed0f68
		return (-1);
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	switch (rsp->ccode) {
Packit Service ed0f68
		case 0x00:
Packit Service ed0f68
			if (rsp->data_len == 3) {
Packit Service ed0f68
				params->retry_count    = rsp->data[1];
Packit Service ed0f68
				params->retry_interval = rsp->data[2];
Packit Service ed0f68
			} else {
Packit Service ed0f68
				lprintf(LOG_ERR, "Error: Unexpected data length (%d) received "
Packit Service ed0f68
						"for SOL parameter '%s'",
Packit Service ed0f68
						rsp->data_len,
Packit Service ed0f68
						val2str(data[1], sol_parameter_vals));
Packit Service ed0f68
			}
Packit Service ed0f68
			break;
Packit Service ed0f68
		case 0x80:
Packit Service ed0f68
			lprintf(LOG_ERR, "Info: SOL parameter '%s' not supported",
Packit Service ed0f68
					val2str(data[1], sol_parameter_vals));
Packit Service ed0f68
			break;
Packit Service ed0f68
		default:
Packit Service ed0f68
			lprintf(LOG_ERR, "Error requesting SOL parameter '%s': %s",
Packit Service ed0f68
				val2str(data[1], sol_parameter_vals),
Packit Service ed0f68
				val2str(rsp->ccode, completion_code_vals));
Packit Service ed0f68
			return (-1);
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	/*
Packit Service ed0f68
	 * SOL non-volatile bit rate
Packit Service ed0f68
	 */
Packit Service ed0f68
	memset(data, 0, sizeof(data));
Packit Service ed0f68
	data[0] = channel;                                 /* channel number     */
Packit Service ed0f68
	data[1] = SOL_PARAMETER_SOL_NON_VOLATILE_BIT_RATE; /* parameter selector */
Packit Service ed0f68
	data[2] = 0x00;                                    /* set selector       */
Packit Service ed0f68
	data[3] = 0x00;                                    /* block selector     */
Packit Service ed0f68
Packit Service ed0f68
	rsp = intf->sendrecv(intf, &req;;
Packit Service ed0f68
	if (rsp == NULL) {
Packit Service ed0f68
		lprintf(LOG_ERR, "Error: No response requesting SOL parameter '%s'",
Packit Service ed0f68
				val2str(data[1], sol_parameter_vals));
Packit Service ed0f68
		return (-1);
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	switch (rsp->ccode) {
Packit Service ed0f68
		case 0x00:
Packit Service ed0f68
			if (rsp->data_len == 2) {
Packit Service ed0f68
				params->non_volatile_bit_rate = rsp->data[1] & 0x0F;
Packit Service ed0f68
			} else {
Packit Service ed0f68
				lprintf(LOG_ERR, "Error: Unexpected data length (%d) received "
Packit Service ed0f68
						"for SOL parameter '%s'",
Packit Service ed0f68
						rsp->data_len,
Packit Service ed0f68
						val2str(data[1], sol_parameter_vals));
Packit Service ed0f68
			}
Packit Service ed0f68
			break;
Packit Service ed0f68
		case 0x80:
Packit Service ed0f68
			lprintf(LOG_ERR, "Info: SOL parameter '%s' not supported",
Packit Service ed0f68
					val2str(data[1], sol_parameter_vals));
Packit Service ed0f68
			break;
Packit Service ed0f68
		default:
Packit Service ed0f68
			lprintf(LOG_ERR, "Error requesting SOL parameter '%s': %s",
Packit Service ed0f68
				val2str(data[1], sol_parameter_vals),
Packit Service ed0f68
				val2str(rsp->ccode, completion_code_vals));
Packit Service ed0f68
			return (-1);
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	/*
Packit Service ed0f68
	 * SOL volatile bit rate
Packit Service ed0f68
	 */
Packit Service ed0f68
	memset(data, 0, sizeof(data));
Packit Service ed0f68
	data[0] = channel;                             /* channel number     */
Packit Service ed0f68
	data[1] = SOL_PARAMETER_SOL_VOLATILE_BIT_RATE; /* parameter selector */
Packit Service ed0f68
	data[2] = 0x00;                                /* set selector       */
Packit Service ed0f68
	data[3] = 0x00;                                /* block selector     */
Packit Service ed0f68
Packit Service ed0f68
	rsp = intf->sendrecv(intf, &req;;
Packit Service ed0f68
	if (rsp == NULL) {
Packit Service ed0f68
		lprintf(LOG_ERR, "Error: No response requesting SOL parameter '%s'",
Packit Service ed0f68
				val2str(data[1], sol_parameter_vals));
Packit Service ed0f68
		return (-1);
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	switch (rsp->ccode) {
Packit Service ed0f68
		case 0x00:
Packit Service ed0f68
			if (rsp->data_len == 2) {
Packit Service ed0f68
				params->volatile_bit_rate = rsp->data[1] & 0x0F;
Packit Service ed0f68
			} else {
Packit Service ed0f68
				lprintf(LOG_ERR, "Error: Unexpected data length (%d) received "
Packit Service ed0f68
						"for SOL parameter '%s'",
Packit Service ed0f68
						rsp->data_len,
Packit Service ed0f68
						val2str(data[1], sol_parameter_vals));
Packit Service ed0f68
			}
Packit Service ed0f68
			break;
Packit Service ed0f68
		case 0x80:
Packit Service ed0f68
			lprintf(LOG_ERR, "Info: SOL parameter '%s' not supported",
Packit Service ed0f68
					val2str(data[1], sol_parameter_vals));
Packit Service ed0f68
			break;
Packit Service ed0f68
		default:
Packit Service ed0f68
			lprintf(LOG_ERR, "Error requesting SOL parameter '%s': %s",
Packit Service ed0f68
				val2str(data[1], sol_parameter_vals),
Packit Service ed0f68
				val2str(rsp->ccode, completion_code_vals));
Packit Service ed0f68
			return (-1);
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	/*
Packit Service ed0f68
	 * SOL payload channel
Packit Service ed0f68
	 */
Packit Service ed0f68
	memset(data, 0, sizeof(data));
Packit Service ed0f68
	data[0] = channel;                           /* channel number     */
Packit Service ed0f68
	data[1] = SOL_PARAMETER_SOL_PAYLOAD_CHANNEL; /* parameter selector */
Packit Service ed0f68
	data[2] = 0x00;                              /* set selector       */
Packit Service ed0f68
	data[3] = 0x00;                              /* block selector     */
Packit Service ed0f68
Packit Service ed0f68
	rsp = intf->sendrecv(intf, &req;;
Packit Service ed0f68
	if (rsp == NULL) {
Packit Service ed0f68
		lprintf(LOG_ERR, "Error: No response requesting SOL parameter '%s'",
Packit Service ed0f68
				val2str(data[1], sol_parameter_vals));
Packit Service ed0f68
		return (-1);
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	switch (rsp->ccode) {
Packit Service ed0f68
		case 0x00:
Packit Service ed0f68
			if (rsp->data_len == 2) {
Packit Service ed0f68
				params->payload_channel = rsp->data[1];
Packit Service ed0f68
			} else {
Packit Service ed0f68
				lprintf(LOG_ERR, "Error: Unexpected data length (%d) received "
Packit Service ed0f68
						"for SOL parameter '%s'",
Packit Service ed0f68
						rsp->data_len,
Packit Service ed0f68
						val2str(data[1], sol_parameter_vals));
Packit Service ed0f68
			}
Packit Service ed0f68
			break;
Packit Service ed0f68
		case 0x80:
Packit Service ed0f68
			lprintf(LOG_ERR, "Info: SOL parameter '%s' not supported - defaulting to 0x%02x",
Packit Service ed0f68
					val2str(data[1], sol_parameter_vals), channel);
Packit Service ed0f68
			params->payload_channel = channel;
Packit Service ed0f68
			break;
Packit Service ed0f68
		default:
Packit Service ed0f68
			lprintf(LOG_ERR, "Error requesting SOL parameter '%s': %s",
Packit Service ed0f68
					val2str(data[1], sol_parameter_vals),
Packit Service ed0f68
					val2str(rsp->ccode, completion_code_vals));
Packit Service ed0f68
			return (-1);
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	/*
Packit Service ed0f68
	 * SOL payload port
Packit Service ed0f68
	 */
Packit Service ed0f68
	memset(data, 0, sizeof(data));
Packit Service ed0f68
	data[0] = channel;                        /* channel number     */
Packit Service ed0f68
	data[1] = SOL_PARAMETER_SOL_PAYLOAD_PORT; /* parameter selector */
Packit Service ed0f68
	data[2] = 0x00;                           /* set selector       */
Packit Service ed0f68
	data[3] = 0x00;                           /* block selector     */
Packit Service ed0f68
Packit Service ed0f68
	rsp = intf->sendrecv(intf, &req;;
Packit Service ed0f68
	if (rsp == NULL) {
Packit Service ed0f68
		lprintf(LOG_ERR, "Error: No response requesting SOL parameter '%s'",
Packit Service ed0f68
				val2str(data[1], sol_parameter_vals));
Packit Service ed0f68
		return (-1);
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	switch (rsp->ccode) {
Packit Service ed0f68
		case 0x00:
Packit Service ed0f68
			if (rsp->data_len == 3) {
Packit Service ed0f68
				params->payload_port = (rsp->data[1]) | (rsp->data[2] << 8);
Packit Service ed0f68
			} else {
Packit Service ed0f68
				lprintf(LOG_ERR, "Error: Unexpected data length (%d) received "
Packit Service ed0f68
						"for SOL parameter '%s'",
Packit Service ed0f68
						rsp->data_len,
Packit Service ed0f68
						val2str(data[1], sol_parameter_vals));
Packit Service ed0f68
			}
Packit Service ed0f68
			break;
Packit Service ed0f68
		case 0x80:
Packit Service ed0f68
			if( intf->session != NULL ) {
Packit Service ed0f68
				lprintf(LOG_ERR, "Info: SOL parameter '%s' not supported - defaulting to %d",
Packit Service ed0f68
						val2str(data[1], sol_parameter_vals), intf->ssn_params.port);
Packit Service ed0f68
				params->payload_port = intf->ssn_params.port;
Packit Service ed0f68
			} else {
Packit Service ed0f68
				lprintf(LOG_ERR,
Packit Service ed0f68
						"Info: SOL parameter '%s' not supported - can't determine which "
Packit Service ed0f68
						"payload port to use on NULL session",
Packit Service ed0f68
						val2str(data[1], sol_parameter_vals));
Packit Service ed0f68
						return (-1);               
Packit Service ed0f68
			}
Packit Service ed0f68
			break;
Packit Service ed0f68
		default:
Packit Service ed0f68
			lprintf(LOG_ERR, "Error requesting SOL parameter '%s': %s",
Packit Service ed0f68
				val2str(data[1], sol_parameter_vals),
Packit Service ed0f68
				val2str(rsp->ccode, completion_code_vals));
Packit Service ed0f68
			return (-1);
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	return 0;
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
/*
Packit Service ed0f68
 * ipmi_print_sol_info
Packit Service ed0f68
 */
Packit Service ed0f68
static int
Packit Service ed0f68
ipmi_print_sol_info(struct ipmi_intf * intf, uint8_t channel)
Packit Service ed0f68
{
Packit Service ed0f68
	struct sol_config_parameters params = {0};
Packit Service ed0f68
	if (ipmi_get_sol_info(intf, channel, &params))
Packit Service ed0f68
		return -1;
Packit Service ed0f68
Packit Service ed0f68
	if (csv_output)
Packit Service ed0f68
	{
Packit Service ed0f68
		printf("%s,",
Packit Service ed0f68
			   val2str(params.set_in_progress & 0x03,
Packit Service ed0f68
					   ipmi_set_in_progress_vals));
Packit Service ed0f68
		printf("%s,", params.enabled?"true": "false");
Packit Service ed0f68
		printf("%s,", params.force_encryption?"true":"false");
Packit Service ed0f68
		printf("%s,", params.force_encryption?"true":"false");
Packit Service ed0f68
		printf("%s,",
Packit Service ed0f68
			   val2str(params.privilege_level, ipmi_privlvl_vals));
Packit Service ed0f68
		printf("%d,", params.character_accumulate_level * 5);
Packit Service ed0f68
		printf("%d,", params.character_send_threshold);
Packit Service ed0f68
		printf("%d,", params.retry_count);
Packit Service ed0f68
		printf("%d,", params.retry_interval * 10);
Packit Service ed0f68
Packit Service ed0f68
		printf("%s,",
Packit Service ed0f68
			   val2str(params.volatile_bit_rate, ipmi_bit_rate_vals));
Packit Service ed0f68
Packit Service ed0f68
		printf("%s,",
Packit Service ed0f68
			   val2str(params.non_volatile_bit_rate, ipmi_bit_rate_vals));
Packit Service ed0f68
Packit Service ed0f68
		printf("%d,", params.payload_channel);
Packit Service ed0f68
		printf("%d\n", params.payload_port);
Packit Service ed0f68
	}
Packit Service ed0f68
	else
Packit Service ed0f68
	{
Packit Service ed0f68
		printf("Set in progress                 : %s\n",
Packit Service ed0f68
			   val2str(params.set_in_progress & 0x03,
Packit Service ed0f68
					   ipmi_set_in_progress_vals));
Packit Service ed0f68
		printf("Enabled                         : %s\n",
Packit Service ed0f68
			   params.enabled?"true": "false");
Packit Service ed0f68
		printf("Force Encryption                : %s\n",
Packit Service ed0f68
			   params.force_encryption?"true":"false");
Packit Service ed0f68
		printf("Force Authentication            : %s\n",
Packit Service ed0f68
			   params.force_authentication?"true":"false");
Packit Service ed0f68
		printf("Privilege Level                 : %s\n",
Packit Service ed0f68
			   val2str(params.privilege_level, ipmi_privlvl_vals));
Packit Service ed0f68
		printf("Character Accumulate Level (ms) : %d\n",
Packit Service ed0f68
			   params.character_accumulate_level * 5);
Packit Service ed0f68
		printf("Character Send Threshold        : %d\n",
Packit Service ed0f68
			   params.character_send_threshold);
Packit Service ed0f68
		printf("Retry Count                     : %d\n",
Packit Service ed0f68
			   params.retry_count);
Packit Service ed0f68
		printf("Retry Interval (ms)             : %d\n",
Packit Service ed0f68
			   params.retry_interval * 10);
Packit Service ed0f68
Packit Service ed0f68
		printf("Volatile Bit Rate (kbps)        : %s\n",
Packit Service ed0f68
			   val2str(params.volatile_bit_rate, ipmi_bit_rate_vals));
Packit Service ed0f68
Packit Service ed0f68
		printf("Non-Volatile Bit Rate (kbps)    : %s\n",
Packit Service ed0f68
			   val2str(params.non_volatile_bit_rate, ipmi_bit_rate_vals));
Packit Service ed0f68
Packit Service ed0f68
		printf("Payload Channel                 : %d (0x%02x)\n",
Packit Service ed0f68
			   params.payload_channel, params.payload_channel);
Packit Service ed0f68
		printf("Payload Port                    : %d\n",
Packit Service ed0f68
			   params.payload_port);
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	return 0;
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
/*
Packit Service ed0f68
 * Small function to validate that user-supplied SOL
Packit Service ed0f68
 * configuration parameter values we store in uint8_t
Packit Service ed0f68
 * data type falls within valid range.  With minval
Packit Service ed0f68
 * and maxval parameters we can use the same function
Packit Service ed0f68
 * to validate parameters that have different ranges
Packit Service ed0f68
 * of values.
Packit Service ed0f68
 *
Packit Service ed0f68
 * function will return -1 if value is not valid, or
Packit Service ed0f68
 * will return 0 if valid.
Packit Service ed0f68
 */
Packit Service ed0f68
int ipmi_sol_set_param_isvalid_uint8_t( const char *strval,
Packit Service ed0f68
					const char *name,
Packit Service ed0f68
					int base,
Packit Service ed0f68
					uint8_t minval,
Packit Service ed0f68
					uint8_t maxval,
Packit Service ed0f68
					uint8_t *out_value)
Packit Service ed0f68
{
Packit Service ed0f68
	if (str2uchar(strval, out_value) != 0 || (*out_value < minval)
Packit Service ed0f68
			|| (*out_value > maxval)) {
Packit Service ed0f68
		lprintf(LOG_ERR, "Invalid value %s for parameter %s",
Packit Service ed0f68
			strval, name);
Packit Service ed0f68
		lprintf(LOG_ERR, "Valid values are %d-%d", minval, maxval);
Packit Service ed0f68
		return -1;
Packit Service ed0f68
	}
Packit Service ed0f68
	return 0;
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
/*
Packit Service ed0f68
 * ipmi_sol_set_param
Packit Service ed0f68
 *
Packit Service ed0f68
 * Set the specified Serial Over LAN value to the specified
Packit Service ed0f68
 * value
Packit Service ed0f68
 *
Packit Service ed0f68
 * return 0 on success,
Packit Service ed0f68
 *        -1 on failure
Packit Service ed0f68
 */
Packit Service ed0f68
static int
Packit Service ed0f68
ipmi_sol_set_param(struct ipmi_intf * intf,
Packit Service ed0f68
		   uint8_t            channel,
Packit Service ed0f68
		   const char       * param,
Packit Service ed0f68
		   const char       * value,
Packit Service ed0f68
		   uint8_t            guarded)
Packit Service ed0f68
{
Packit Service ed0f68
	struct ipmi_rs * rsp;
Packit Service ed0f68
	struct ipmi_rq   req;
Packit Service ed0f68
	uint8_t          data[4];
Packit Service ed0f68
	int              bGuarded = guarded; /* Use set-in-progress indicator? */
Packit Service ed0f68
Packit Service ed0f68
	memset(&req, 0, sizeof(req));
Packit Service ed0f68
	req.msg.netfn    = IPMI_NETFN_TRANSPORT;           /* 0x0c */
Packit Service ed0f68
	req.msg.cmd      = IPMI_SET_SOL_CONFIG_PARAMETERS; /* 0x21 */
Packit Service ed0f68
	req.msg.data     = data;
Packit Service ed0f68
Packit Service ed0f68
	data[0] = channel;
Packit Service ed0f68
Packit Service ed0f68
	/*
Packit Service ed0f68
	 * set-in-progress
Packit Service ed0f68
	 */
Packit Service ed0f68
	if (! strcmp(param, "set-in-progress"))
Packit Service ed0f68
	{
Packit Service ed0f68
		bGuarded = 0; /* We _ARE_ the set-in-progress indicator */
Packit Service ed0f68
		req.msg.data_len = 3;
Packit Service ed0f68
		data[1] = SOL_PARAMETER_SET_IN_PROGRESS;
Packit Service ed0f68
Packit Service ed0f68
		if (! strcmp(value, "set-complete"))
Packit Service ed0f68
			data[2] = 0x00;
Packit Service ed0f68
		else if (! strcmp(value, "set-in-progress"))
Packit Service ed0f68
			data[2] = 0x01;
Packit Service ed0f68
		else if (! strcmp(value, "commit-write"))
Packit Service ed0f68
			data[2] = 0x02;
Packit Service ed0f68
		else
Packit Service ed0f68
		{
Packit Service ed0f68
			lprintf(LOG_ERR, "Invalid value %s for parameter %s",
Packit Service ed0f68
				   value, param);
Packit Service ed0f68
			lprintf(LOG_ERR, "Valid values are set-complete, set-in-progress "
Packit Service ed0f68
				   "and commit-write");
Packit Service ed0f68
			return -1;
Packit Service ed0f68
		}
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
	/*
Packit Service ed0f68
	 * enabled
Packit Service ed0f68
	 */
Packit Service ed0f68
	else if (! strcmp(param, "enabled"))
Packit Service ed0f68
	{
Packit Service ed0f68
		req.msg.data_len = 3;
Packit Service ed0f68
		data[1] = SOL_PARAMETER_SOL_ENABLE;
Packit Service ed0f68
Packit Service ed0f68
		if (! strcmp(value, "true"))
Packit Service ed0f68
			data[2] = 0x01;
Packit Service ed0f68
		else if (! strcmp(value, "false"))
Packit Service ed0f68
			data[2] = 0x00;
Packit Service ed0f68
		else
Packit Service ed0f68
		{
Packit Service ed0f68
			lprintf(LOG_ERR, "Invalid value %s for parameter %s",
Packit Service ed0f68
				   value, param);
Packit Service ed0f68
			lprintf(LOG_ERR, "Valid values are true and false");
Packit Service ed0f68
			return -1;
Packit Service ed0f68
		}
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
	/*
Packit Service ed0f68
	 * force-payload-encryption 
Packit Service ed0f68
	 */
Packit Service ed0f68
	else if (! strcmp(param, "force-encryption"))
Packit Service ed0f68
	{
Packit Service ed0f68
		struct sol_config_parameters params;
Packit Service ed0f68
Packit Service ed0f68
		req.msg.data_len = 3;
Packit Service ed0f68
		data[1] = SOL_PARAMETER_SOL_AUTHENTICATION;
Packit Service ed0f68
Packit Service ed0f68
		if (! strcmp(value, "true"))
Packit Service ed0f68
			data[2] = 0x80;
Packit Service ed0f68
		else if (! strcmp(value, "false"))
Packit Service ed0f68
			data[2] = 0x00;
Packit Service ed0f68
		else
Packit Service ed0f68
		{
Packit Service ed0f68
			lprintf(LOG_ERR, "Invalid value %s for parameter %s",
Packit Service ed0f68
				   value, param);
Packit Service ed0f68
			lprintf(LOG_ERR, "Valid values are true and false");
Packit Service ed0f68
			return -1;
Packit Service ed0f68
		}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
		/* We need other values to complete the request */
Packit Service ed0f68
		if (ipmi_get_sol_info(intf, channel, &params))
Packit Service ed0f68
		{
Packit Service ed0f68
			lprintf(LOG_ERR, "Error fetching SOL parameters for %s update",
Packit Service ed0f68
				   param);
Packit Service ed0f68
			return -1;
Packit Service ed0f68
		}
Packit Service ed0f68
Packit Service ed0f68
		data[2] |= params.force_authentication? 0x40 : 0x00;
Packit Service ed0f68
		data[2] |= params.privilege_level;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
	/*
Packit Service ed0f68
	 * force-payload-authentication
Packit Service ed0f68
	 */
Packit Service ed0f68
	else if (! strcmp(param, "force-authentication"))
Packit Service ed0f68
	{
Packit Service ed0f68
		struct sol_config_parameters params;
Packit Service ed0f68
Packit Service ed0f68
		req.msg.data_len = 3;
Packit Service ed0f68
		data[1] = SOL_PARAMETER_SOL_AUTHENTICATION;
Packit Service ed0f68
Packit Service ed0f68
		if (! strcmp(value, "true"))
Packit Service ed0f68
			data[2] = 0x40;
Packit Service ed0f68
		else if (! strcmp(value, "false"))
Packit Service ed0f68
			data[2] = 0x00;
Packit Service ed0f68
		else
Packit Service ed0f68
		{
Packit Service ed0f68
			lprintf(LOG_ERR, "Invalid value %s for parameter %s",
Packit Service ed0f68
				   value, param);
Packit Service ed0f68
			lprintf(LOG_ERR, "Valid values are true and false");
Packit Service ed0f68
			return -1;
Packit Service ed0f68
		}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
		/* We need other values to complete the request */
Packit Service ed0f68
		if (ipmi_get_sol_info(intf, channel, &params))
Packit Service ed0f68
		{
Packit Service ed0f68
			lprintf(LOG_ERR, "Error fetching SOL parameters for %s update",
Packit Service ed0f68
				   param);
Packit Service ed0f68
			return -1;
Packit Service ed0f68
		}
Packit Service ed0f68
Packit Service ed0f68
		data[2] |= params.force_encryption? 0x80 : 0x00;
Packit Service ed0f68
		data[2] |= params.privilege_level;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
	/*
Packit Service ed0f68
	 * privilege-level
Packit Service ed0f68
	 */
Packit Service ed0f68
	else if (! strcmp(param, "privilege-level"))
Packit Service ed0f68
	{
Packit Service ed0f68
		struct sol_config_parameters params;
Packit Service ed0f68
Packit Service ed0f68
		req.msg.data_len = 3;
Packit Service ed0f68
		data[1] = SOL_PARAMETER_SOL_AUTHENTICATION;
Packit Service ed0f68
Packit Service ed0f68
		if (! strcmp(value, "user"))
Packit Service ed0f68
			data[2] = 0x02;
Packit Service ed0f68
		else if (! strcmp(value, "operator"))
Packit Service ed0f68
			data[2] = 0x03;
Packit Service ed0f68
		else if (! strcmp(value, "admin"))
Packit Service ed0f68
			data[2] = 0x04;
Packit Service ed0f68
		else if (! strcmp(value, "oem"))
Packit Service ed0f68
			data[2] = 0x05;
Packit Service ed0f68
		else
Packit Service ed0f68
		{
Packit Service ed0f68
			lprintf(LOG_ERR, "Invalid value %s for parameter %s",
Packit Service ed0f68
				   value, param);
Packit Service ed0f68
			lprintf(LOG_ERR, "Valid values are user, operator, admin, and oem");
Packit Service ed0f68
			return -1;
Packit Service ed0f68
		}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
		/* We need other values to complete the request */
Packit Service ed0f68
		if (ipmi_get_sol_info(intf, channel, &params))
Packit Service ed0f68
		{
Packit Service ed0f68
			lprintf(LOG_ERR, "Error fetching SOL parameters for %s update",
Packit Service ed0f68
				   param);
Packit Service ed0f68
			return -1;
Packit Service ed0f68
		}
Packit Service ed0f68
Packit Service ed0f68
		data[2] |= params.force_encryption?     0x80 : 0x00;
Packit Service ed0f68
		data[2] |= params.force_authentication? 0x40 : 0x00;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
	/*
Packit Service ed0f68
	 * character-accumulate-level
Packit Service ed0f68
	 */
Packit Service ed0f68
	else if (! strcmp(param, "character-accumulate-level"))
Packit Service ed0f68
	{
Packit Service ed0f68
		struct sol_config_parameters params;
Packit Service ed0f68
Packit Service ed0f68
		req.msg.data_len = 4;
Packit Service ed0f68
		data[1] = SOL_PARAMETER_CHARACTER_INTERVAL;
Packit Service ed0f68
Packit Service ed0f68
		/* validate user-supplied input */
Packit Service ed0f68
		if (ipmi_sol_set_param_isvalid_uint8_t(value, param, 0, 1, 255, &data[2]))
Packit Service ed0f68
			return -1;
Packit Service ed0f68
Packit Service ed0f68
		/* We need other values to complete the request */
Packit Service ed0f68
		if (ipmi_get_sol_info(intf, channel, &params))
Packit Service ed0f68
		{
Packit Service ed0f68
			lprintf(LOG_ERR, "Error fetching SOL parameters for %s update",
Packit Service ed0f68
				   param);
Packit Service ed0f68
			return -1;
Packit Service ed0f68
		}
Packit Service ed0f68
Packit Service ed0f68
		data[3] = params.character_send_threshold;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
	/*
Packit Service ed0f68
	 * character-send-threshold
Packit Service ed0f68
	 */
Packit Service ed0f68
	else if (! strcmp(param, "character-send-threshold"))
Packit Service ed0f68
	{
Packit Service ed0f68
		struct sol_config_parameters params;
Packit Service ed0f68
Packit Service ed0f68
		req.msg.data_len = 4;
Packit Service ed0f68
		data[1] = SOL_PARAMETER_CHARACTER_INTERVAL;
Packit Service ed0f68
Packit Service ed0f68
		/* validate user-supplied input */
Packit Service ed0f68
		if (ipmi_sol_set_param_isvalid_uint8_t(value, param, 0, 0, 255, &data[3]))
Packit Service ed0f68
			return -1;
Packit Service ed0f68
Packit Service ed0f68
		/* We need other values to complete the request */
Packit Service ed0f68
		if (ipmi_get_sol_info(intf, channel, &params))
Packit Service ed0f68
		{
Packit Service ed0f68
			lprintf(LOG_ERR, "Error fetching SOL parameters for %s update",
Packit Service ed0f68
				   param);
Packit Service ed0f68
			return -1;
Packit Service ed0f68
		}
Packit Service ed0f68
Packit Service ed0f68
		data[2] = params.character_accumulate_level;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
	/*
Packit Service ed0f68
	 * retry-count
Packit Service ed0f68
	 */
Packit Service ed0f68
	else if (! strcmp(param, "retry-count"))
Packit Service ed0f68
	{
Packit Service ed0f68
		struct sol_config_parameters params;
Packit Service ed0f68
Packit Service ed0f68
		req.msg.data_len = 4;
Packit Service ed0f68
		data[1] = SOL_PARAMETER_SOL_RETRY;
Packit Service ed0f68
Packit Service ed0f68
		/* validate user input, 7 is max value */
Packit Service ed0f68
		if (ipmi_sol_set_param_isvalid_uint8_t(value, param, 0, 0, 7, &data[2]))
Packit Service ed0f68
			return -1;
Packit Service ed0f68
Packit Service ed0f68
		/* We need other values to complete the request */
Packit Service ed0f68
		if (ipmi_get_sol_info(intf, channel, &params))
Packit Service ed0f68
		{
Packit Service ed0f68
			lprintf(LOG_ERR, "Error fetching SOL parameters for %s update",
Packit Service ed0f68
				   param);
Packit Service ed0f68
			return -1;
Packit Service ed0f68
		}
Packit Service ed0f68
Packit Service ed0f68
		data[3] = params.retry_interval;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
	/*
Packit Service ed0f68
	 * retry-interval
Packit Service ed0f68
	 */
Packit Service ed0f68
	else if (! strcmp(param, "retry-interval"))
Packit Service ed0f68
	{
Packit Service ed0f68
		struct sol_config_parameters params;
Packit Service ed0f68
Packit Service ed0f68
		req.msg.data_len = 4;
Packit Service ed0f68
		data[1] = SOL_PARAMETER_SOL_RETRY;
Packit Service ed0f68
Packit Service ed0f68
		/* validate user-supplied input */
Packit Service ed0f68
		if (ipmi_sol_set_param_isvalid_uint8_t(value, param, 0, 0, 255, &data[3]))
Packit Service ed0f68
			return -1;
Packit Service ed0f68
Packit Service ed0f68
		/* We need other values to complete the request */
Packit Service ed0f68
		if (ipmi_get_sol_info(intf, channel, &params))
Packit Service ed0f68
		{
Packit Service ed0f68
			lprintf(LOG_ERR, "Error fetching SOL parameters for %s update",
Packit Service ed0f68
				   param);
Packit Service ed0f68
			return -1;
Packit Service ed0f68
		}
Packit Service ed0f68
Packit Service ed0f68
		data[2] = params.retry_count;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
	/*
Packit Service ed0f68
	 * non-volatile-bit-rate
Packit Service ed0f68
	 */
Packit Service ed0f68
	else if (! strcmp(param, "non-volatile-bit-rate"))
Packit Service ed0f68
	{
Packit Service ed0f68
		req.msg.data_len = 3;
Packit Service ed0f68
		data[1] = SOL_PARAMETER_SOL_NON_VOLATILE_BIT_RATE;
Packit Service ed0f68
Packit Service ed0f68
		if (!strcmp(value, "serial"))
Packit Service ed0f68
		{
Packit Service ed0f68
			data[2] = 0x00;
Packit Service ed0f68
		}
Packit Service ed0f68
		else if (!strcmp(value, "9.6"))
Packit Service ed0f68
		{
Packit Service ed0f68
			data[2] = 0x06;
Packit Service ed0f68
		}
Packit Service ed0f68
		else if (!strcmp(value, "19.2"))
Packit Service ed0f68
		{
Packit Service ed0f68
			data[2] = 0x07;
Packit Service ed0f68
		}
Packit Service ed0f68
		else if (!strcmp(value, "38.4"))
Packit Service ed0f68
		{
Packit Service ed0f68
			data[2] = 0x08;
Packit Service ed0f68
		}
Packit Service ed0f68
		else if (!strcmp(value, "57.6"))
Packit Service ed0f68
		{
Packit Service ed0f68
			data[2] = 0x09;
Packit Service ed0f68
		}
Packit Service ed0f68
		else if (!strcmp(value, "115.2"))
Packit Service ed0f68
		{
Packit Service ed0f68
			data[2] = 0x0A;
Packit Service ed0f68
		}
Packit Service ed0f68
		else
Packit Service ed0f68
		{
Packit Service ed0f68
			lprintf(LOG_ERR, "Invalid value \"%s\" for parameter \"%s\"",
Packit Service ed0f68
				   value,
Packit Service ed0f68
				   param);
Packit Service ed0f68
			lprintf(LOG_ERR, "Valid values are serial, 9.6 19.2, 38.4, 57.6 and 115.2");
Packit Service ed0f68
			return -1;
Packit Service ed0f68
		}
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
	/*
Packit Service ed0f68
	 * volatile-bit-rate
Packit Service ed0f68
	 */
Packit Service ed0f68
	else if (! strcmp(param, "volatile-bit-rate"))
Packit Service ed0f68
	{
Packit Service ed0f68
		req.msg.data_len = 3;
Packit Service ed0f68
		data[1] = SOL_PARAMETER_SOL_VOLATILE_BIT_RATE;
Packit Service ed0f68
Packit Service ed0f68
		if (!strcmp(value, "serial"))
Packit Service ed0f68
		{
Packit Service ed0f68
			data[2] = 0x00;
Packit Service ed0f68
		}
Packit Service ed0f68
		else if (!strcmp(value, "9.6"))
Packit Service ed0f68
		{
Packit Service ed0f68
			data[2] = 0x06;
Packit Service ed0f68
		}
Packit Service ed0f68
		else if (!strcmp(value, "19.2"))
Packit Service ed0f68
		{
Packit Service ed0f68
			data[2] = 0x07;
Packit Service ed0f68
		}
Packit Service ed0f68
		else if (!strcmp(value, "38.4"))
Packit Service ed0f68
		{
Packit Service ed0f68
			data[2] = 0x08;
Packit Service ed0f68
		}
Packit Service ed0f68
		else if (!strcmp(value, "57.6"))
Packit Service ed0f68
		{
Packit Service ed0f68
			data[2] = 0x09;
Packit Service ed0f68
		}
Packit Service ed0f68
		else if (!strcmp(value, "115.2"))
Packit Service ed0f68
		{
Packit Service ed0f68
			data[2] = 0x0A;
Packit Service ed0f68
		}
Packit Service ed0f68
		else
Packit Service ed0f68
		{
Packit Service ed0f68
			lprintf(LOG_ERR, "Invalid value \"%s\" for parameter \"%s\"",
Packit Service ed0f68
				   value,
Packit Service ed0f68
				   param);
Packit Service ed0f68
			lprintf(LOG_ERR, "Valid values are serial, 9.6 19.2, 38.4, 57.6 and 115.2");
Packit Service ed0f68
			return -1;
Packit Service ed0f68
		}
Packit Service ed0f68
	}
Packit Service ed0f68
	else
Packit Service ed0f68
	{
Packit Service ed0f68
		lprintf(LOG_ERR, "Error: invalid SOL parameter %s", param);
Packit Service ed0f68
		return -1;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
	/*
Packit Service ed0f68
	 * Execute the request
Packit Service ed0f68
	 */
Packit Service ed0f68
	if (bGuarded &&
Packit Service ed0f68
		(ipmi_sol_set_param(intf,
Packit Service ed0f68
				    channel,
Packit Service ed0f68
				    "set-in-progress",
Packit Service ed0f68
				    "set-in-progress",
Packit Service ed0f68
				    bGuarded)))
Packit Service ed0f68
	{
Packit Service ed0f68
		lprintf(LOG_ERR, "Error: set of parameter \"%s\" failed", param);
Packit Service ed0f68
		return -1;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
	/* The command proper */
Packit Service ed0f68
	rsp = intf->sendrecv(intf, &req;;
Packit Service ed0f68
Packit Service ed0f68
	if (rsp == NULL) {
Packit Service ed0f68
		lprintf(LOG_ERR, "Error setting SOL parameter '%s'", param);
Packit Service ed0f68
		return -1;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	if (!(!strncmp(param, "set-in-progress", 15) && !strncmp(value, "commit-write", 12)) &&
Packit Service ed0f68
	    rsp->ccode > 0) {
Packit Service ed0f68
		switch (rsp->ccode) {
Packit Service ed0f68
		case 0x80:
Packit Service ed0f68
			lprintf(LOG_ERR, "Error setting SOL parameter '%s': "
Packit Service ed0f68
				"Parameter not supported", param);
Packit Service ed0f68
			break;
Packit Service ed0f68
		case 0x81:
Packit Service ed0f68
			lprintf(LOG_ERR, "Error setting SOL parameter '%s': "
Packit Service ed0f68
				"Attempt to set set-in-progress when not in set-complete state",
Packit Service ed0f68
				param);
Packit Service ed0f68
			break;
Packit Service ed0f68
		case 0x82:
Packit Service ed0f68
			lprintf(LOG_ERR, "Error setting SOL parameter '%s': "
Packit Service ed0f68
				"Attempt to write read-only parameter", param);
Packit Service ed0f68
			break;
Packit Service ed0f68
		case 0x83:
Packit Service ed0f68
			lprintf(LOG_ERR, "Error setting SOL parameter '%s': "
Packit Service ed0f68
				"Attempt to read write-only parameter", param);
Packit Service ed0f68
			break;
Packit Service ed0f68
		default:
Packit Service ed0f68
			lprintf(LOG_ERR, "Error setting SOL parameter '%s' to '%s': %s",
Packit Service ed0f68
				param, value, val2str(rsp->ccode, completion_code_vals));
Packit Service ed0f68
			break;
Packit Service ed0f68
		}
Packit Service ed0f68
Packit Service ed0f68
		if (bGuarded &&
Packit Service ed0f68
			(ipmi_sol_set_param(intf,
Packit Service ed0f68
					    channel,
Packit Service ed0f68
					    "set-in-progress",
Packit Service ed0f68
					    "set-complete",
Packit Service ed0f68
					    bGuarded)))
Packit Service ed0f68
		{
Packit Service ed0f68
			lprintf(LOG_ERR, "Error could not set \"set-in-progress\" "
Packit Service ed0f68
				   "to \"set-complete\"");
Packit Service ed0f68
		}
Packit Service ed0f68
Packit Service ed0f68
		return -1;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
	/*
Packit Service ed0f68
	 * The commit write could very well fail, but that's ok.
Packit Service ed0f68
	 * It may not be implemented.
Packit Service ed0f68
	 */
Packit Service ed0f68
	if (bGuarded)
Packit Service ed0f68
		ipmi_sol_set_param(intf,
Packit Service ed0f68
				   channel,
Packit Service ed0f68
				   "set-in-progress",
Packit Service ed0f68
				   "commit-write",
Packit Service ed0f68
				   bGuarded);
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
	if (bGuarded &&
Packit Service ed0f68
 		ipmi_sol_set_param(intf,
Packit Service ed0f68
				   channel,
Packit Service ed0f68
				   "set-in-progress",
Packit Service ed0f68
				   "set-complete",
Packit Service ed0f68
				   bGuarded))
Packit Service ed0f68
	{
Packit Service ed0f68
		lprintf(LOG_ERR, "Error could not set \"set-in-progress\" "
Packit Service ed0f68
			   "to \"set-complete\"");
Packit Service ed0f68
		return -1;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	return 0;
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
void
Packit Service ed0f68
leave_raw_mode(void)
Packit Service ed0f68
{
Packit Service ed0f68
	if (!_in_raw_mode)
Packit Service ed0f68
		return;
Packit Service ed0f68
	if (tcsetattr(fileno(stdin), TCSADRAIN, &_saved_tio) == -1)
Packit Service ed0f68
		perror("tcsetattr");
Packit Service ed0f68
	else
Packit Service ed0f68
		_in_raw_mode = 0;
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
void
Packit Service ed0f68
enter_raw_mode(void)
Packit Service ed0f68
{
Packit Service ed0f68
	struct termios tio;
Packit Service ed0f68
	if (tcgetattr(fileno(stdin), &tio) == -1) {
Packit Service ed0f68
		perror("tcgetattr");
Packit Service ed0f68
		return;
Packit Service ed0f68
	}
Packit Service ed0f68
	_saved_tio = tio;
Packit Service ed0f68
	tio.c_iflag |= IGNPAR;
Packit Service ed0f68
	tio.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF);
Packit Service ed0f68
	tio.c_lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL);
Packit Service ed0f68
	//	#ifdef IEXTEN
Packit Service ed0f68
	tio.c_lflag &= ~IEXTEN;
Packit Service ed0f68
	//	#endif
Packit Service ed0f68
	tio.c_oflag &= ~OPOST;
Packit Service ed0f68
	tio.c_cc[VMIN] = 1;
Packit Service ed0f68
	tio.c_cc[VTIME] = 0;
Packit Service ed0f68
	if (tcsetattr(fileno(stdin), TCSADRAIN, &tio) == -1)
Packit Service ed0f68
		perror("tcsetattr");
Packit Service ed0f68
	else
Packit Service ed0f68
		_in_raw_mode = 1;
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
static void
Packit Service ed0f68
sendBreak(struct ipmi_intf * intf)
Packit Service ed0f68
{
Packit Service ed0f68
	struct ipmi_v2_payload  v2_payload;
Packit Service ed0f68
Packit Service ed0f68
	memset(&v2_payload, 0, sizeof(v2_payload));
Packit Service ed0f68
Packit Service ed0f68
	v2_payload.payload.sol_packet.character_count = 0;
Packit Service ed0f68
	v2_payload.payload.sol_packet.generate_break  = 1;
Packit Service ed0f68
Packit Service ed0f68
	intf->send_sol(intf, &v2_payload);
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
/*
Packit Service ed0f68
 * suspendSelf
Packit Service ed0f68
 *
Packit Service ed0f68
 * Put ourself in the background
Packit Service ed0f68
 *
Packit Service ed0f68
 * param bRestoreTty specifies whether we will put our self back
Packit Service ed0f68
 *       in raw mode when we resume
Packit Service ed0f68
 */
Packit Service ed0f68
static void
Packit Service ed0f68
suspendSelf(int bRestoreTty)
Packit Service ed0f68
{
Packit Service ed0f68
	leave_raw_mode();
Packit Service ed0f68
	kill(getpid(), SIGTSTP);
Packit Service ed0f68
Packit Service ed0f68
	if (bRestoreTty)
Packit Service ed0f68
		enter_raw_mode();
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
/*
Packit Service ed0f68
 * printSolEscapeSequences
Packit Service ed0f68
 *
Packit Service ed0f68
 * Send some useful documentation to the user
Packit Service ed0f68
 */
Packit Service ed0f68
static void
Packit Service ed0f68
printSolEscapeSequences(struct ipmi_intf * intf)
Packit Service ed0f68
{
Packit Service ed0f68
	printf(
Packit Service ed0f68
		   "%c?\n\
Packit Service ed0f68
	Supported escape sequences:\n\
Packit Service ed0f68
	%c.  - terminate connection\n\
Packit Service ed0f68
	%c^Z - suspend ipmitool\n\
Packit Service ed0f68
	%c^X - suspend ipmitool, but don't restore tty on restart\n\
Packit Service ed0f68
	%cB  - send break\n\
Packit Service ed0f68
	%c?  - this message\n\
Packit Service ed0f68
	%c%c  - send the escape character by typing it twice\n\
Packit Service ed0f68
	(Note that escapes are only recognized immediately after newline.)\n",
Packit Service ed0f68
		   intf->ssn_params.sol_escape_char,
Packit Service ed0f68
		   intf->ssn_params.sol_escape_char,
Packit Service ed0f68
		   intf->ssn_params.sol_escape_char,
Packit Service ed0f68
		   intf->ssn_params.sol_escape_char,
Packit Service ed0f68
		   intf->ssn_params.sol_escape_char,
Packit Service ed0f68
		   intf->ssn_params.sol_escape_char,
Packit Service ed0f68
		   intf->ssn_params.sol_escape_char,
Packit Service ed0f68
		   intf->ssn_params.sol_escape_char);
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
/*
Packit Service ed0f68
 * output
Packit Service ed0f68
 *
Packit Service ed0f68
 * Send the specified data to stdout
Packit Service ed0f68
 */
Packit Service ed0f68
static void
Packit Service ed0f68
output(struct ipmi_rs * rsp)
Packit Service ed0f68
{
Packit Service ed0f68
	/* Add checks to make sure it is actually SOL data, in general I see
Packit Service ed0f68
	 * outside code mostly trying to guard against this happening, but
Packit Service ed0f68
	 * some places fail to do so, so I do so here to make sure nothing gets
Packit Service ed0f68
	 * through.  If non-sol data comes through here, there is probably 
Packit Service ed0f68
	 * a packet that won't get processed somewhere else, but the alternative
Packit Service ed0f68
	 * of outputting corrupt data is worse.  Generally I see the get device
Packit Service ed0f68
	 * id response make it here somehow.  I assume it is a heartbeat and the
Packit Service ed0f68
	 * other code will retry if it cares about the response and misses it.
Packit Service ed0f68
	 */
Packit Service ed0f68
	if (rsp &&
Packit Service ed0f68
	    (rsp->session.authtype    == IPMI_SESSION_AUTHTYPE_RMCP_PLUS) &&
Packit Service ed0f68
	    (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL))
Packit Service ed0f68
	{
Packit Service ed0f68
		int i;
Packit Service ed0f68
Packit Service ed0f68
		for (i = 0; i < rsp->data_len; ++i)
Packit Service ed0f68
			putc(rsp->data[i], stdout);
Packit Service ed0f68
Packit Service ed0f68
		fflush(stdout);
Packit Service ed0f68
	}
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
/*
Packit Service ed0f68
 * ipmi_sol_deactivate
Packit Service ed0f68
 */
Packit Service ed0f68
static int
Packit Service ed0f68
ipmi_sol_deactivate(struct ipmi_intf * intf, int instance)
Packit Service ed0f68
{
Packit Service ed0f68
	struct ipmi_rs * rsp;
Packit Service ed0f68
	struct ipmi_rq   req;
Packit Service ed0f68
	uint8_t          data[6];
Packit Service ed0f68
Packit Service ed0f68
	if ((instance <= 0) || (instance > 15)) {
Packit Service ed0f68
		lprintf(LOG_ERR, "Error: Instance must range from 1 to 15");
Packit Service ed0f68
		return -1;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	memset(&req, 0, sizeof(req));
Packit Service ed0f68
	req.msg.netfn    = IPMI_NETFN_APP;
Packit Service ed0f68
	req.msg.cmd      = IPMI_DEACTIVATE_PAYLOAD;
Packit Service ed0f68
	req.msg.data_len = 6;
Packit Service ed0f68
	req.msg.data     = data;
Packit Service ed0f68
Packit Service ed0f68
	memset(data, 0, sizeof(data));
Packit Service ed0f68
	data[0] = IPMI_PAYLOAD_TYPE_SOL;  /* payload type      */
Packit Service ed0f68
	data[1] = instance;               /* payload instance. */
Packit Service ed0f68
Packit Service ed0f68
	/* Lots of important data */
Packit Service ed0f68
	data[2] = 0;
Packit Service ed0f68
	data[3] = 0;
Packit Service ed0f68
	data[4] = 0;
Packit Service ed0f68
	data[5] = 0;
Packit Service ed0f68
Packit Service ed0f68
	rsp = intf->sendrecv(intf, &req;;
Packit Service ed0f68
Packit Service ed0f68
	if (NULL != rsp) {
Packit Service ed0f68
		switch (rsp->ccode) {
Packit Service ed0f68
			case 0x00:
Packit Service ed0f68
				return 0;
Packit Service ed0f68
			case 0x80:
Packit Service ed0f68
				lprintf(LOG_ERR, "Info: SOL payload already de-activated");
Packit Service ed0f68
				break;
Packit Service ed0f68
			case 0x81:
Packit Service ed0f68
				lprintf(LOG_ERR, "Info: SOL payload type disabled");
Packit Service ed0f68
				break;
Packit Service ed0f68
			default:
Packit Service ed0f68
				lprintf(LOG_ERR, "Error de-activating SOL payload: %s",
Packit Service ed0f68
					val2str(rsp->ccode, completion_code_vals));
Packit Service ed0f68
				break;
Packit Service ed0f68
		}
Packit Service ed0f68
	} else {
Packit Service ed0f68
		lprintf(LOG_ERR, "Error: No response de-activating SOL payload");
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	return -1;
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
/*
Packit Service ed0f68
 * processSolUserInput
Packit Service ed0f68
 *
Packit Service ed0f68
 * Act on user input into the SOL session.  The only reason this
Packit Service ed0f68
 * is complicated is that we have to process escape sequences.
Packit Service ed0f68
 *
Packit Service ed0f68
 * return   0 on success
Packit Service ed0f68
 *          1 if we should exit
Packit Service ed0f68
 *        < 0 on error (BMC probably closed the session)
Packit Service ed0f68
 */
Packit Service ed0f68
static int
Packit Service ed0f68
processSolUserInput(
Packit Service ed0f68
					struct ipmi_intf * intf,
Packit Service ed0f68
					uint8_t    * input,
Packit Service ed0f68
					uint16_t   buffer_length)
Packit Service ed0f68
{
Packit Service ed0f68
	static int escape_pending = 0;
Packit Service ed0f68
	static int last_was_cr    = 1;
Packit Service ed0f68
	struct ipmi_v2_payload v2_payload;
Packit Service ed0f68
	int  length               = 0;
Packit Service ed0f68
	int  retval               = 0;
Packit Service ed0f68
	char ch;
Packit Service ed0f68
	int  i;
Packit Service ed0f68
Packit Service ed0f68
	memset(&v2_payload, 0, sizeof(v2_payload));
Packit Service ed0f68
Packit Service ed0f68
	/*
Packit Service ed0f68
	 * Our first order of business is to check the input for escape
Packit Service ed0f68
	 * sequences to act on.
Packit Service ed0f68
	 */
Packit Service ed0f68
	for (i = 0; i < buffer_length; ++i)
Packit Service ed0f68
	{
Packit Service ed0f68
		ch = input[i];
Packit Service ed0f68
Packit Service ed0f68
		if (escape_pending){
Packit Service ed0f68
			escape_pending = 0;
Packit Service ed0f68
Packit Service ed0f68
			/*
Packit Service ed0f68
			 * Process a possible escape sequence.
Packit Service ed0f68
			 */
Packit Service ed0f68
			switch (ch) {
Packit Service ed0f68
			case '.':
Packit Service ed0f68
				printf("%c. [terminated ipmitool]\n",
Packit Service ed0f68
				       intf->ssn_params.sol_escape_char);
Packit Service ed0f68
				retval = 1;
Packit Service ed0f68
				break;
Packit Service ed0f68
Packit Service ed0f68
			case 'Z' - 64:
Packit Service ed0f68
				printf("%c^Z [suspend ipmitool]\n",
Packit Service ed0f68
				       intf->ssn_params.sol_escape_char);
Packit Service ed0f68
				suspendSelf(1); /* Restore tty back to raw */
Packit Service ed0f68
				continue;
Packit Service ed0f68
Packit Service ed0f68
			case 'X' - 64:
Packit Service ed0f68
				printf("%c^Z [suspend ipmitool]\n",
Packit Service ed0f68
				       intf->ssn_params.sol_escape_char);
Packit Service ed0f68
				suspendSelf(0); /* Don't restore to raw mode */
Packit Service ed0f68
				continue;
Packit Service ed0f68
Packit Service ed0f68
			case 'B':
Packit Service ed0f68
				printf("%cB [send break]\n",
Packit Service ed0f68
				       intf->ssn_params.sol_escape_char);
Packit Service ed0f68
				sendBreak(intf);
Packit Service ed0f68
				continue;
Packit Service ed0f68
Packit Service ed0f68
			case '?':
Packit Service ed0f68
				printSolEscapeSequences(intf);
Packit Service ed0f68
				continue;
Packit Service ed0f68
Packit Service ed0f68
			default:
Packit Service ed0f68
				if (ch != intf->ssn_params.sol_escape_char)
Packit Service ed0f68
					v2_payload.payload.sol_packet.data[length++] =
Packit Service ed0f68
						intf->ssn_params.sol_escape_char;
Packit Service ed0f68
				v2_payload.payload.sol_packet.data[length++] = ch;
Packit Service ed0f68
			}
Packit Service ed0f68
		}
Packit Service ed0f68
Packit Service ed0f68
		else
Packit Service ed0f68
		{
Packit Service ed0f68
			if (last_was_cr && (ch == intf->ssn_params.sol_escape_char)) {
Packit Service ed0f68
				escape_pending = 1;
Packit Service ed0f68
				continue;
Packit Service ed0f68
			}
Packit Service ed0f68
Packit Service ed0f68
			v2_payload.payload.sol_packet.data[length++] =	ch;
Packit Service ed0f68
		}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
		/*
Packit Service ed0f68
		 * Normal character.  Record whether it was a newline.
Packit Service ed0f68
		 */
Packit Service ed0f68
		last_was_cr = (ch == '\r' || ch == '\n');
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
	/*
Packit Service ed0f68
	 * If there is anything left to process we dispatch it to the BMC,
Packit Service ed0f68
	 * send intf->session->sol_data.max_outbound_payload_size bytes
Packit Service ed0f68
	 * at a time.
Packit Service ed0f68
	 */
Packit Service ed0f68
	if (length)
Packit Service ed0f68
	{
Packit Service ed0f68
		struct ipmi_rs * rsp = NULL;
Packit Service ed0f68
		int try = 0;
Packit Service ed0f68
Packit Service ed0f68
		while (try < intf->ssn_params.retry) {
Packit Service ed0f68
Packit Service ed0f68
			v2_payload.payload.sol_packet.character_count = length;
Packit Service ed0f68
Packit Service ed0f68
			rsp = intf->send_sol(intf, &v2_payload);
Packit Service ed0f68
Packit Service ed0f68
			if (rsp)
Packit Service ed0f68
			{
Packit Service ed0f68
				break;
Packit Service ed0f68
			}
Packit Service ed0f68
Packit Service ed0f68
			usleep(5000);
Packit Service ed0f68
			try++;
Packit Service ed0f68
		}
Packit Service ed0f68
Packit Service ed0f68
		if (! rsp)
Packit Service ed0f68
		{
Packit Service ed0f68
			lprintf(LOG_ERR, "Error sending SOL data: FAIL");
Packit Service ed0f68
			retval = -1;
Packit Service ed0f68
		}
Packit Service ed0f68
Packit Service ed0f68
		/* If the sequence number is set we know we have new data */
Packit Service ed0f68
		if (retval == 0)
Packit Service ed0f68
			if ((rsp->session.authtype == IPMI_SESSION_AUTHTYPE_RMCP_PLUS) &&
Packit Service ed0f68
			    (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL)        &&
Packit Service ed0f68
			    (rsp->payload.sol_packet.packet_sequence_number))
Packit Service ed0f68
				output(rsp);
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	return retval;
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
static int
Packit Service ed0f68
ipmi_sol_keepalive_using_sol(struct ipmi_intf * intf)
Packit Service ed0f68
{
Packit Service ed0f68
	struct ipmi_v2_payload v2_payload;
Packit Service ed0f68
	struct timeval end;
Packit Service ed0f68
Packit Service ed0f68
	if (_disable_keepalive)
Packit Service ed0f68
		return 0;
Packit Service ed0f68
Packit Service ed0f68
	gettimeofday(&end, 0);
Packit Service ed0f68
Packit Service ed0f68
	if (end.tv_sec - _start_keepalive.tv_sec > SOL_KEEPALIVE_TIMEOUT) {
Packit Service ed0f68
		memset(&v2_payload, 0, sizeof(v2_payload));
Packit Service ed0f68
		v2_payload.payload.sol_packet.character_count = 0;
Packit Service ed0f68
		if (intf->send_sol(intf, &v2_payload) == NULL)
Packit Service ed0f68
			return -1;
Packit Service ed0f68
		/* good return, reset start time */
Packit Service ed0f68
		gettimeofday(&_start_keepalive, 0);
Packit Service ed0f68
	}
Packit Service ed0f68
	return 0;
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
static int
Packit Service ed0f68
ipmi_sol_keepalive_using_getdeviceid(struct ipmi_intf * intf)
Packit Service ed0f68
{
Packit Service ed0f68
	struct timeval  end;
Packit Service ed0f68
Packit Service ed0f68
	if (_disable_keepalive)
Packit Service ed0f68
		return 0;
Packit Service ed0f68
Packit Service ed0f68
	gettimeofday(&end, 0);
Packit Service ed0f68
Packit Service ed0f68
	if (end.tv_sec - _start_keepalive.tv_sec > SOL_KEEPALIVE_TIMEOUT) {
Packit Service ed0f68
		if (intf->keepalive(intf) != 0)
Packit Service ed0f68
         		return -1;
Packit Service ed0f68
		/* good return, reset start time */
Packit Service ed0f68
		gettimeofday(&_start_keepalive, 0);
Packit Service ed0f68
   	}
Packit Service ed0f68
	return 0;
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
/*
Packit Service ed0f68
 * ipmi_sol_red_pill
Packit Service ed0f68
 */
Packit Service ed0f68
static int
Packit Service ed0f68
ipmi_sol_red_pill(struct ipmi_intf * intf, int instance)
Packit Service ed0f68
{
Packit Service ed0f68
	char   * buffer;
Packit Service ed0f68
	int    numRead;
Packit Service ed0f68
	int    bShouldExit       = 0;
Packit Service ed0f68
	int    bBmcClosedSession = 0;
Packit Service ed0f68
	fd_set read_fds;
Packit Service ed0f68
	struct timeval tv;
Packit Service ed0f68
	int    retval;
Packit Service ed0f68
	int    buffer_size = intf->session->sol_data.max_inbound_payload_size;
Packit Service ed0f68
	int    keepAliveRet = 0;
Packit Service ed0f68
	int    retrySol = 0;
Packit Service ed0f68
Packit Service ed0f68
	/* Subtract SOL header from max_inbound_payload_size */
Packit Service ed0f68
	if (buffer_size > 4)
Packit Service ed0f68
		buffer_size -= 4;
Packit Service ed0f68
Packit Service ed0f68
	buffer = (char*)malloc(buffer_size);
Packit Service ed0f68
	if (buffer == NULL) {
Packit Service ed0f68
		lprintf(LOG_ERR, "ipmitool: malloc failure"); 
Packit Service ed0f68
		return -1;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	/* Initialize keepalive start time */
Packit Service ed0f68
	gettimeofday(&_start_keepalive, 0);
Packit Service ed0f68
Packit Service ed0f68
	enter_raw_mode();
Packit Service ed0f68
Packit Service ed0f68
	while (! bShouldExit)
Packit Service ed0f68
	{
Packit Service ed0f68
		FD_ZERO(&read_fds);
Packit Service ed0f68
		FD_SET(0, &read_fds);
Packit Service ed0f68
		FD_SET(intf->fd, &read_fds);
Packit Service ed0f68
Packit Service ed0f68
		if (!ipmi_oem_active(intf,"i82571spt"))
Packit Service ed0f68
		{
Packit Service ed0f68
			/* Send periodic keepalive packet */
Packit Service ed0f68
			if(_use_sol_for_keepalive == 0)
Packit Service ed0f68
			{
Packit Service ed0f68
				keepAliveRet = ipmi_sol_keepalive_using_getdeviceid(intf);
Packit Service ed0f68
			}
Packit Service ed0f68
			else
Packit Service ed0f68
			{
Packit Service ed0f68
				keepAliveRet = ipmi_sol_keepalive_using_sol(intf);
Packit Service ed0f68
			}
Packit Service ed0f68
		
Packit Service ed0f68
			if (keepAliveRet != 0)
Packit Service ed0f68
			{
Packit Service ed0f68
				/*
Packit Service ed0f68
				 * Retrying the keep Alive before declaring a communication
Packit Service ed0f68
				 * lost state with the IPMC. Helpful when the payload is
Packit Service ed0f68
				 * reset and brings down the connection temporarily. Otherwise,
Packit Service ed0f68
				 * if we send getDevice Id to check the status of IPMC during
Packit Service ed0f68
				 * this down time when the connection is restarting, SOL will
Packit Service ed0f68
				 * exit even though the IPMC is available and the session is open.
Packit Service ed0f68
				 */
Packit Service ed0f68
				if (retrySol == MAX_SOL_RETRY)
Packit Service ed0f68
				{
Packit Service ed0f68
					/* no response to Get Device ID keepalive message */
Packit Service ed0f68
					bShouldExit = 1;
Packit Service ed0f68
					continue;
Packit Service ed0f68
				}
Packit Service ed0f68
				else
Packit Service ed0f68
				{
Packit Service ed0f68
					retrySol++;
Packit Service ed0f68
				}
Packit Service ed0f68
			}
Packit Service ed0f68
			else
Packit Service ed0f68
			{
Packit Service ed0f68
				/* if the keep Alive is successful reset retries to zero */
Packit Service ed0f68
				retrySol = 0;
Packit Service ed0f68
			}
Packit Service ed0f68
		} /* !oem="i82571spt" */
Packit Service ed0f68
		/* Wait up to half a second */
Packit Service ed0f68
		tv.tv_sec =  0;
Packit Service ed0f68
		tv.tv_usec = 500000;
Packit Service ed0f68
Packit Service ed0f68
		retval = select(intf->fd + 1, &read_fds, NULL, NULL, &tv;;
Packit Service ed0f68
Packit Service ed0f68
		if (retval)
Packit Service ed0f68
		{
Packit Service ed0f68
			if (retval == -1)
Packit Service ed0f68
			{
Packit Service ed0f68
				/* ERROR */
Packit Service ed0f68
				perror("select");
Packit Service ed0f68
				return -1;
Packit Service ed0f68
			}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
			/*
Packit Service ed0f68
			 * Process input from the user
Packit Service ed0f68
			 */
Packit Service ed0f68
			if (FD_ISSET(0, &read_fds))
Packit Service ed0f68
	 		{
Packit Service ed0f68
				memset(buffer, 0, buffer_size);
Packit Service ed0f68
				numRead = read(fileno(stdin),
Packit Service ed0f68
							   buffer,
Packit Service ed0f68
							   buffer_size);
Packit Service ed0f68
Packit Service ed0f68
				if (numRead > 0)
Packit Service ed0f68
				{
Packit Service ed0f68
					int rc = processSolUserInput(intf, (uint8_t *)buffer, numRead);
Packit Service ed0f68
Packit Service ed0f68
					if (rc)
Packit Service ed0f68
					{
Packit Service ed0f68
						if (rc < 0)
Packit Service ed0f68
							bShouldExit = bBmcClosedSession = 1;
Packit Service ed0f68
						else
Packit Service ed0f68
							bShouldExit = 1;
Packit Service ed0f68
					}
Packit Service ed0f68
				}
Packit Service ed0f68
				else
Packit Service ed0f68
				{
Packit Service ed0f68
					bShouldExit = 1;
Packit Service ed0f68
				}
Packit Service ed0f68
			}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
			/*
Packit Service ed0f68
			 * Process input from the BMC
Packit Service ed0f68
			 */
Packit Service ed0f68
			else if (FD_ISSET(intf->fd, &read_fds))
Packit Service ed0f68
			{
Packit Service ed0f68
				struct ipmi_rs * rs =intf->recv_sol(intf);
Packit Service ed0f68
				if (rs) {
Packit Service ed0f68
					output(rs);
Packit Service ed0f68
				} else {
Packit Service ed0f68
					bShouldExit = bBmcClosedSession = 1;
Packit Service ed0f68
				}
Packit Service ed0f68
 			}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
			/*
Packit Service ed0f68
			 * ERROR in select
Packit Service ed0f68
			 */
Packit Service ed0f68
 			else
Packit Service ed0f68
			{
Packit Service ed0f68
				lprintf(LOG_ERR, "Error: Select returned with nothing to read");
Packit Service ed0f68
				bShouldExit = 1;
Packit Service ed0f68
			}
Packit Service ed0f68
		}
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	leave_raw_mode();
Packit Service ed0f68
Packit Service ed0f68
	if (keepAliveRet != 0)
Packit Service ed0f68
	{
Packit Service ed0f68
		lprintf(LOG_ERR, "Error: No response to keepalive - Terminating session");
Packit Service ed0f68
		/* attempt to clean up anyway */
Packit Service ed0f68
		ipmi_sol_deactivate(intf, instance);
Packit Service ed0f68
		exit(1);
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	if (bBmcClosedSession)
Packit Service ed0f68
	{
Packit Service ed0f68
		lprintf(LOG_ERR, "SOL session closed by BMC");
Packit Service ed0f68
		exit(1);
Packit Service ed0f68
	}
Packit Service ed0f68
	else
Packit Service ed0f68
		ipmi_sol_deactivate(intf, instance);
Packit Service ed0f68
Packit Service ed0f68
	return 0;
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
/*
Packit Service ed0f68
 * ipmi_sol_activate
Packit Service ed0f68
 */
Packit Service ed0f68
static int
Packit Service ed0f68
ipmi_sol_activate(struct ipmi_intf * intf, int looptest, int interval,
Packit Service ed0f68
		int instance)
Packit Service ed0f68
{
Packit Service ed0f68
	struct ipmi_rs * rsp;
Packit Service ed0f68
	struct ipmi_rq   req;
Packit Service ed0f68
	struct activate_payload_rsp ap_rsp;
Packit Service ed0f68
	uint8_t    data[6];
Packit Service ed0f68
	uint8_t    bSolEncryption     = 1;
Packit Service ed0f68
	uint8_t    bSolAuthentication = 1;
Packit Service ed0f68
Packit Service ed0f68
	/*
Packit Service ed0f68
	 * This command is only available over RMCP+ (the lanplus
Packit Service ed0f68
	 * interface).
Packit Service ed0f68
	 */
Packit Service ed0f68
	if (strncmp(intf->name, "lanplus", 7) != 0)
Packit Service ed0f68
	{
Packit Service ed0f68
		lprintf(LOG_ERR, "Error: This command is only available over the "
Packit Service ed0f68
			   "lanplus interface");
Packit Service ed0f68
		return -1;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	if ((instance <= 0) || (instance > 15)) {
Packit Service ed0f68
		lprintf(LOG_ERR, "Error: Instance must range from 1 to 15");
Packit Service ed0f68
		return -1;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
	/*
Packit Service ed0f68
	 * Setup a callback so that the lanplus processing knows what
Packit Service ed0f68
	 * to do with packets that come unexpectedly (while waiting for
Packit Service ed0f68
	 * an ACK, perhaps.
Packit Service ed0f68
	 */
Packit Service ed0f68
	intf->session->sol_data.sol_input_handler = output;
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
	memset(&req, 0, sizeof(req));
Packit Service ed0f68
	req.msg.netfn    = IPMI_NETFN_APP;
Packit Service ed0f68
	req.msg.cmd      = IPMI_ACTIVATE_PAYLOAD;
Packit Service ed0f68
	req.msg.data_len = 6;
Packit Service ed0f68
	req.msg.data     = data;
Packit Service ed0f68
Packit Service ed0f68
	data[0] = IPMI_PAYLOAD_TYPE_SOL;  /* payload type     */
Packit Service ed0f68
	data[1] = instance;               /* payload instance */
Packit Service ed0f68
Packit Service ed0f68
	/* Lots of important data.  Most is default */
Packit Service ed0f68
	data[2]  = bSolEncryption?     0x80 : 0;
Packit Service ed0f68
	data[2] |= bSolAuthentication? 0x40 : 0;
Packit Service ed0f68
	data[2] |= IPMI_SOL_SERIAL_ALERT_MASK_DEFERRED;
Packit Service ed0f68
Packit Service ed0f68
	if (ipmi_oem_active(intf, "intelplus")) {
Packit Service ed0f68
		data[2] |= IPMI_SOL_BMC_ASSERTS_CTS_MASK_TRUE;
Packit Service ed0f68
	} else if (ipmi_oem_active(intf, "i82571spt")) {
Packit Service ed0f68
		/*
Packit Service ed0f68
		 * A quote from Intel: "Engineering believes the problem
Packit Service ed0f68
		 * lies within the Auxiliary data being sent with the
Packit Service ed0f68
		 * 'Activate Payload' command from IPMITool.  IPMITool
Packit Service ed0f68
		 * sends a C6h which sets some bits having to do with
Packit Service ed0f68
		 * encryption and some behavior dealing with CTS DCD/DSR.
Packit Service ed0f68
		 * I recommend that the customer modify this request
Packit Service ed0f68
		 * to send 08h instead. This is what our internal utility
Packit Service ed0f68
		 * sends and it works without issue. I will work with
Packit Service ed0f68
		 * engineering to ensure the settings that IPMITool uses
Packit Service ed0f68
		 * (C6h) are supported in the future.
Packit Service ed0f68
		 */
Packit Service ed0f68
		data[2] = 0x08;
Packit Service ed0f68
	} else {
Packit Service ed0f68
		data[2] |= IPMI_SOL_BMC_ASSERTS_CTS_MASK_FALSE;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	data[3] = 0x00; /* reserved */
Packit Service ed0f68
	data[4] = 0x00; /* reserved */
Packit Service ed0f68
	data[5] = 0x00; /* reserved */
Packit Service ed0f68
Packit Service ed0f68
	rsp = intf->sendrecv(intf, &req;;
Packit Service ed0f68
Packit Service ed0f68
	if (NULL != rsp) {
Packit Service ed0f68
		switch (rsp->ccode) {
Packit Service ed0f68
			case 0x00: 
Packit Service ed0f68
				if (rsp->data_len == 12) {
Packit Service ed0f68
					break;
Packit Service ed0f68
				} else {
Packit Service ed0f68
					lprintf(LOG_ERR, "Error: Unexpected data length (%d) received "
Packit Service ed0f68
						   "in payload activation response",
Packit Service ed0f68
						   rsp->data_len);
Packit Service ed0f68
					return -1;
Packit Service ed0f68
				}
Packit Service ed0f68
				break;
Packit Service ed0f68
			case 0x80:
Packit Service ed0f68
				lprintf(LOG_ERR, "Info: SOL payload already active on another session");
Packit Service ed0f68
				return -1;
Packit Service ed0f68
			case 0x81:
Packit Service ed0f68
				lprintf(LOG_ERR, "Info: SOL payload disabled");
Packit Service ed0f68
				return -1;
Packit Service ed0f68
			case 0x82:
Packit Service ed0f68
				lprintf(LOG_ERR, "Info: SOL payload activation limit reached");
Packit Service ed0f68
				return -1;
Packit Service ed0f68
			case 0x83:
Packit Service ed0f68
				lprintf(LOG_ERR, "Info: cannot activate SOL payload with encryption");
Packit Service ed0f68
				return -1;
Packit Service ed0f68
			case 0x84:
Packit Service ed0f68
				lprintf(LOG_ERR, "Info: cannot activate SOL payload without encryption");
Packit Service ed0f68
				return -1;
Packit Service ed0f68
			default:
Packit Service ed0f68
				lprintf(LOG_ERR, "Error activating SOL payload: %s",
Packit Service ed0f68
					val2str(rsp->ccode, completion_code_vals));
Packit Service ed0f68
				return -1;
Packit Service ed0f68
		}
Packit Service ed0f68
	} else {
Packit Service ed0f68
		lprintf(LOG_ERR, "Error: No response activating SOL payload");
Packit Service ed0f68
		return -1;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
	memcpy(&ap_rsp, rsp->data, sizeof(struct activate_payload_rsp));
Packit Service ed0f68
Packit Service ed0f68
	intf->session->sol_data.max_inbound_payload_size =
Packit Service ed0f68
		(ap_rsp.inbound_payload_size[1] << 8) |
Packit Service ed0f68
		ap_rsp.inbound_payload_size[0];
Packit Service ed0f68
Packit Service ed0f68
	intf->session->sol_data.max_outbound_payload_size =
Packit Service ed0f68
		(ap_rsp.outbound_payload_size[1] << 8) |
Packit Service ed0f68
		ap_rsp.outbound_payload_size[0];
Packit Service ed0f68
Packit Service ed0f68
	intf->session->sol_data.port =
Packit Service ed0f68
		(ap_rsp.payload_udp_port[1] << 8) |
Packit Service ed0f68
		ap_rsp.payload_udp_port[0];
Packit Service ed0f68
Packit Service ed0f68
	intf->session->timeout = 1;
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
	/* NOTE: the spec does allow for SOL traffic to be sent on
Packit Service ed0f68
	 * a different port.  we do not yet support that feature. */
Packit Service ed0f68
	if (intf->session->sol_data.port != intf->ssn_params.port)
Packit Service ed0f68
	{
Packit Service ed0f68
		/* try byteswapping port in case BMC sent it incorrectly */
Packit Service ed0f68
		uint16_t portswap = BSWAP_16(intf->session->sol_data.port);
Packit Service ed0f68
Packit Service ed0f68
		if (portswap == intf->ssn_params.port) {
Packit Service ed0f68
			intf->session->sol_data.port = portswap;
Packit Service ed0f68
		}
Packit Service ed0f68
		else {
Packit Service ed0f68
			lprintf(LOG_ERR, "Error: BMC requests SOL session on different port");
Packit Service ed0f68
			return -1;
Packit Service ed0f68
		}
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	printf("[SOL Session operational.  Use %c? for help]\n",
Packit Service ed0f68
	       intf->ssn_params.sol_escape_char);
Packit Service ed0f68
Packit Service ed0f68
	if(looptest == 1)
Packit Service ed0f68
	{
Packit Service ed0f68
		ipmi_sol_deactivate(intf, instance);
Packit Service ed0f68
		usleep(interval*1000);
Packit Service ed0f68
		return 0;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	/*
Packit Service ed0f68
	 * At this point we are good to go with our SOL session.  We
Packit Service ed0f68
	 * need to listen to
Packit Service ed0f68
	 * 1) STDIN for user input
Packit Service ed0f68
	 * 2) The FD for incoming SOL packets
Packit Service ed0f68
	 */
Packit Service ed0f68
	if (ipmi_sol_red_pill(intf, instance))
Packit Service ed0f68
	{
Packit Service ed0f68
		lprintf(LOG_ERR, "Error in SOL session");
Packit Service ed0f68
		return -1;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	return 0;
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
/*
Packit Service ed0f68
 * print_sol_usage
Packit Service ed0f68
 */
Packit Service ed0f68
static void
Packit Service ed0f68
print_sol_usage(void)
Packit Service ed0f68
{
Packit Service ed0f68
	lprintf(LOG_NOTICE, "SOL Commands: info [<channel number>]");
Packit Service ed0f68
	lprintf(LOG_NOTICE, "              set <parameter> <value> [channel]");
Packit Service ed0f68
	lprintf(LOG_NOTICE, "              payload <enable|disable|status> [channel] [userid]");
Packit Service ed0f68
	lprintf(LOG_NOTICE, "              activate [<usesolkeepalive|nokeepalive>] [instance=<number>]");
Packit Service ed0f68
	lprintf(LOG_NOTICE, "              deactivate [instance=<number>]");
Packit Service ed0f68
	lprintf(LOG_NOTICE, "              looptest [<loop times> [<loop interval(in ms)> [<instance>]]]");
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
/*
Packit Service ed0f68
 * print_sol_set_usage
Packit Service ed0f68
 */
Packit Service ed0f68
static void
Packit Service ed0f68
print_sol_set_usage(void)
Packit Service ed0f68
{
Packit Service ed0f68
	lprintf(LOG_NOTICE, "\nSOL set parameters and values: \n");
Packit Service ed0f68
  	lprintf(LOG_NOTICE, "  set-in-progress             set-complete | "
Packit Service ed0f68
		"set-in-progress | commit-write");
Packit Service ed0f68
	lprintf(LOG_NOTICE, "  enabled                     true | false");
Packit Service ed0f68
	lprintf(LOG_NOTICE, "  force-encryption            true | false");
Packit Service ed0f68
	lprintf(LOG_NOTICE, "  force-authentication        true | false");
Packit Service ed0f68
	lprintf(LOG_NOTICE, "  privilege-level             user | operator | admin | oem");
Packit Service ed0f68
	lprintf(LOG_NOTICE, "  character-accumulate-level  <in 5 ms increments>");
Packit Service ed0f68
	lprintf(LOG_NOTICE, "  character-send-threshold    N");
Packit Service ed0f68
	lprintf(LOG_NOTICE, "  retry-count                 N");
Packit Service ed0f68
	lprintf(LOG_NOTICE, "  retry-interval              <in 10 ms increments>");
Packit Service ed0f68
	lprintf(LOG_NOTICE, "  non-volatile-bit-rate       "
Packit Service ed0f68
		"serial | 9.6 | 19.2 | 38.4 | 57.6 | 115.2");
Packit Service ed0f68
	lprintf(LOG_NOTICE, "  volatile-bit-rate           "
Packit Service ed0f68
		"serial | 9.6 | 19.2 | 38.4 | 57.6 | 115.2");
Packit Service ed0f68
	lprintf(LOG_NOTICE, "");
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
/* ipmi_sol_main */
Packit Service ed0f68
int
Packit Service ed0f68
ipmi_sol_main(struct ipmi_intf * intf, int argc, char ** argv)
Packit Service ed0f68
{
Packit Service ed0f68
	int retval = 0;
Packit Service ed0f68
	if (!argc || !strncmp(argv[0], "help", 4)) {
Packit Service ed0f68
		/* Help */
Packit Service ed0f68
		print_sol_usage();
Packit Service ed0f68
	} else if (!strncmp(argv[0], "info", 4)) {
Packit Service ed0f68
		/* Info */
Packit Service ed0f68
		uint8_t channel;
Packit Service ed0f68
		if (argc == 1) {
Packit Service ed0f68
			/* Ask about the current channel */
Packit Service ed0f68
			channel = 0x0E;
Packit Service ed0f68
		} else if (argc == 2) {
Packit Service ed0f68
			if (is_ipmi_channel_num(argv[1], &channel) != 0) {
Packit Service ed0f68
				return (-1);
Packit Service ed0f68
			}
Packit Service ed0f68
		} else {
Packit Service ed0f68
			print_sol_usage();
Packit Service ed0f68
			return -1;
Packit Service ed0f68
		}
Packit Service ed0f68
		retval = ipmi_print_sol_info(intf, channel);
Packit Service ed0f68
	} else if (!strncmp(argv[0], "payload", 7)) {
Packit Service ed0f68
		/* Payload enable or disable */
Packit Service ed0f68
		uint8_t channel = 0xe;
Packit Service ed0f68
		uint8_t userid = 1;
Packit Service ed0f68
		int enable = -1;
Packit Service ed0f68
		if (argc == 1 || argc > 4) {
Packit Service ed0f68
			print_sol_usage();
Packit Service ed0f68
			return -1;
Packit Service ed0f68
		}
Packit Service ed0f68
		if (argc >= 3) {
Packit Service ed0f68
			if (is_ipmi_channel_num(argv[2], &channel) != 0) {
Packit Service ed0f68
				return (-1);
Packit Service ed0f68
			}
Packit Service ed0f68
		}
Packit Service ed0f68
		if (argc == 4) {
Packit Service ed0f68
			if (is_ipmi_user_id(argv[3], &userid) != 0) {
Packit Service ed0f68
				return (-1);
Packit Service ed0f68
			}
Packit Service ed0f68
		}
Packit Service ed0f68
		if (!strncmp(argv[1], "enable", 6)) {
Packit Service ed0f68
			enable = 1;
Packit Service ed0f68
		} else if (!strncmp(argv[1], "disable", 7)) {
Packit Service ed0f68
			enable = 0;
Packit Service ed0f68
		} else if (!strncmp(argv[1], "status", 6)) {
Packit Service ed0f68
			return ipmi_sol_payload_access_status(intf, channel, userid);
Packit Service ed0f68
		} else {
Packit Service ed0f68
			print_sol_usage();
Packit Service ed0f68
			return -1;
Packit Service ed0f68
		}
Packit Service ed0f68
		retval = ipmi_sol_payload_access(intf, channel, userid, enable);
Packit Service ed0f68
	} else if (!strncmp(argv[0], "set", 3)) {
Packit Service ed0f68
		/* Set a parameter value */
Packit Service ed0f68
		uint8_t channel = 0xe;
Packit Service ed0f68
		uint8_t guard = 1;
Packit Service ed0f68
		if (argc == 3) {
Packit Service ed0f68
			channel = 0xe;
Packit Service ed0f68
		} else if (argc == 4) {
Packit Service ed0f68
			if (!strncmp(argv[3], "noguard", 7)) {
Packit Service ed0f68
				guard = 0;
Packit Service ed0f68
			} else {
Packit Service ed0f68
				if (is_ipmi_channel_num(argv[3], &channel) != 0) {
Packit Service ed0f68
					return (-1);
Packit Service ed0f68
				}
Packit Service ed0f68
			}
Packit Service ed0f68
		} else if (argc == 5) {
Packit Service ed0f68
			if (is_ipmi_channel_num(argv[3], &channel) != 0) {
Packit Service ed0f68
				return (-1);
Packit Service ed0f68
			}
Packit Service ed0f68
			if (!strncmp(argv[4], "noguard", 7)) {
Packit Service ed0f68
				guard = 0;
Packit Service ed0f68
			}
Packit Service ed0f68
		} else {
Packit Service ed0f68
			print_sol_set_usage();
Packit Service ed0f68
			return -1;
Packit Service ed0f68
		}
Packit Service ed0f68
		retval = ipmi_sol_set_param(intf, channel, argv[1], argv[2], guard);
Packit Service ed0f68
	} else if (!strncmp(argv[0], "activate", 8)) {
Packit Service ed0f68
		/* Activate */
Packit Service ed0f68
		int i;
Packit Service ed0f68
		uint8_t instance = 1;
Packit Service ed0f68
		for (i = 1; i < argc; i++) {
Packit Service ed0f68
			if (!strncmp(argv[i], "usesolkeepalive", 15)) {
Packit Service ed0f68
				_use_sol_for_keepalive = 1;
Packit Service ed0f68
			} else if (!strncmp(argv[i], "nokeepalive", 11)) {
Packit Service ed0f68
				_disable_keepalive = 1;
Packit Service ed0f68
			} else if (!strncmp(argv[i], "instance=", 9)) {
Packit Service ed0f68
				if (str2uchar(argv[i] + 9, &instance) != 0) {
Packit Service ed0f68
					lprintf(LOG_ERR, "Given instance '%s' is invalid.", argv[i] + 9);
Packit Service ed0f68
					print_sol_usage();
Packit Service ed0f68
					return -1;
Packit Service ed0f68
				}
Packit Service ed0f68
			} else {
Packit Service ed0f68
				print_sol_usage();
Packit Service ed0f68
				return -1;
Packit Service ed0f68
			}
Packit Service ed0f68
		}
Packit Service ed0f68
		retval = ipmi_sol_activate(intf, 0, 0, instance);
Packit Service ed0f68
	} else if (!strncmp(argv[0], "deactivate", 10)) {
Packit Service ed0f68
		/* Dectivate */
Packit Service ed0f68
		int i;
Packit Service ed0f68
		uint8_t instance = 1;
Packit Service ed0f68
		for (i = 1; i < argc; i++) {
Packit Service ed0f68
			if (!strncmp(argv[i], "instance=", 9)) {
Packit Service ed0f68
				if (str2uchar(argv[i] + 9, &instance) != 0) {
Packit Service ed0f68
					lprintf(LOG_ERR,
Packit Service ed0f68
							"Given instance '%s' is invalid.",
Packit Service ed0f68
							argv[i] + 9);
Packit Service ed0f68
					print_sol_usage();
Packit Service ed0f68
					return -1;
Packit Service ed0f68
				}
Packit Service ed0f68
			} else {
Packit Service ed0f68
				print_sol_usage();
Packit Service ed0f68
				return -1;
Packit Service ed0f68
			}
Packit Service ed0f68
		}
Packit Service ed0f68
		retval = ipmi_sol_deactivate(intf, instance);
Packit Service ed0f68
	} else if (!strncmp(argv[0], "looptest", 8)) {
Packit Service ed0f68
		/* SOL loop test: Activate and then Dectivate */
Packit Service ed0f68
		int cnt = 200;
Packit Service ed0f68
		int interval = 100; /* Unit is: ms */
Packit Service ed0f68
		uint8_t instance = 1;
Packit Service ed0f68
		if (argc > 4) {
Packit Service ed0f68
			print_sol_usage();
Packit Service ed0f68
			return -1;
Packit Service ed0f68
		}
Packit Service ed0f68
		if (argc != 1) {
Packit Service ed0f68
			/* at least 2 */
Packit Service ed0f68
			if (str2int(argv[1], &cnt) != 0) {
Packit Service ed0f68
				lprintf(LOG_ERR, "Given cnt '%s' is invalid.",
Packit Service ed0f68
						argv[1]);
Packit Service ed0f68
				return (-1);
Packit Service ed0f68
			}
Packit Service ed0f68
			if (cnt <= 0) {
Packit Service ed0f68
				cnt = 200;
Packit Service ed0f68
			}
Packit Service ed0f68
		}
Packit Service ed0f68
		if (argc >= 3) {
Packit Service ed0f68
			if (str2int(argv[2], &interval) != 0) {
Packit Service ed0f68
				lprintf(LOG_ERR, "Given interval '%s' is invalid.",
Packit Service ed0f68
						argv[2]);
Packit Service ed0f68
				return (-1);
Packit Service ed0f68
			}
Packit Service ed0f68
			if (interval < 0) {
Packit Service ed0f68
				interval = 0;
Packit Service ed0f68
			}
Packit Service ed0f68
		}
Packit Service ed0f68
		if (argc >= 4) {
Packit Service ed0f68
			if (str2uchar(argv[3], &instance) != 0) {
Packit Service ed0f68
				lprintf(LOG_ERR, "Given instance '%s' is invalid.",
Packit Service ed0f68
						argv[3]);
Packit Service ed0f68
				print_sol_usage();
Packit Service ed0f68
				return -1;
Packit Service ed0f68
			}
Packit Service ed0f68
		}
Packit Service ed0f68
Packit Service ed0f68
		while (cnt > 0) {
Packit Service ed0f68
			printf("remain loop test counter: %d\n", cnt);
Packit Service ed0f68
			retval = ipmi_sol_activate(intf, 1, interval, instance);
Packit Service ed0f68
			if (retval) {
Packit Service ed0f68
				printf("SOL looptest failed: %d\n",
Packit Service ed0f68
						retval);
Packit Service ed0f68
				break;
Packit Service ed0f68
			}
Packit Service ed0f68
			cnt -= 1;
Packit Service ed0f68
		}
Packit Service ed0f68
	} else {
Packit Service ed0f68
		print_sol_usage();
Packit Service ed0f68
		retval = -1;
Packit Service ed0f68
	}
Packit Service ed0f68
	return retval;
Packit Service ed0f68
}