mirror of
https://github.com/ipmitool/ipmitool.git
synced 2026-06-24 06:11:36 +00:00
Move all files one level up in the file hierarcy, to avoid the useless ipmitool directory.
This commit is contained in:
43
src/plugins/Makefile.am
Normal file
43
src/plugins/Makefile.am
Normal file
@@ -0,0 +1,43 @@
|
||||
# Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# Redistribution of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# Redistribution in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# Neither the name of Sun Microsystems, Inc. or the names of
|
||||
# contributors may be used to endorse or promote products derived
|
||||
# from this software without specific prior written permission.
|
||||
#
|
||||
# This software is provided "AS IS," without a warranty of any kind.
|
||||
# ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
||||
# INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
||||
# PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
||||
# SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
|
||||
# FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||
# OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
|
||||
# SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
|
||||
# OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
|
||||
# PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
|
||||
# LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
||||
# EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/include
|
||||
|
||||
SUBDIRS = @INTF_LAN@ @INTF_LANPLUS@ @INTF_OPEN@ @INTF_LIPMI@ @INTF_IMB@ @INTF_BMC@ @INTF_FREE@ @INTF_SERIAL@ @INTF_DUMMY@
|
||||
DIST_SUBDIRS = lan lanplus open lipmi imb bmc free serial dummy
|
||||
|
||||
noinst_LTLIBRARIES = libintf.la
|
||||
libintf_la_SOURCES = ipmi_intf.c
|
||||
libintf_la_LDFLAGS = -export-dynamic
|
||||
libintf_la_LIBADD = @IPMITOOL_INTF_LIB@
|
||||
libintf_la_DEPENDENCIES = @IPMITOOL_INTF_LIB@
|
||||
|
||||
41
src/plugins/bmc/Makefile.am
Normal file
41
src/plugins/bmc/Makefile.am
Normal file
@@ -0,0 +1,41 @@
|
||||
# Copyright (c) 2004 Sun Microsystems, Inc. All Rights Reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# Redistribution of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# Redistribution in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# Neither the name of Sun Microsystems, Inc. or the names of
|
||||
# contributors may be used to endorse or promote products derived
|
||||
# from this software without specific prior written permission.
|
||||
#
|
||||
# This software is provided "AS IS," without a warranty of any kind.
|
||||
# ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
||||
# INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
||||
# PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
||||
# SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
|
||||
# FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||
# OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
|
||||
# SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
|
||||
# OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
|
||||
# PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
|
||||
# LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
||||
# EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/include
|
||||
|
||||
EXTRA_LTLIBRARIES = libintf_bmc.la
|
||||
noinst_LTLIBRARIES = @INTF_BMC_LIB@
|
||||
libintf_bmc_la_LIBADD = $(top_builddir)/lib/libipmitool.la
|
||||
libintf_bmc_la_SOURCES = \
|
||||
bmc.c bmc.h \
|
||||
bmc_intf.h
|
||||
|
||||
351
src/plugins/bmc/bmc.c
Normal file
351
src/plugins/bmc/bmc.c
Normal file
@@ -0,0 +1,351 @@
|
||||
/*
|
||||
* Copyright (c) 2004 Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistribution of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistribution in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of Sun Microsystems, Inc. or the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* This software is provided "AS IS," without a warranty of any kind.
|
||||
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
||||
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
||||
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
|
||||
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
|
||||
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
|
||||
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
|
||||
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
|
||||
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
||||
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* interface routines between ipmitool and the bmc kernel driver
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stropts.h>
|
||||
#include <stddef.h>
|
||||
#include <stropts.h>
|
||||
|
||||
#include <ipmitool/ipmi.h>
|
||||
#include <ipmitool/ipmi_intf.h>
|
||||
#include "bmc_intf.h"
|
||||
|
||||
#include "bmc.h"
|
||||
|
||||
static int curr_seq;
|
||||
static int bmc_method(int fd, int *if_type);
|
||||
struct ipmi_rs *(*sendrecv_fn)(struct ipmi_intf *, struct ipmi_rq *) = NULL;
|
||||
extern int verbose;
|
||||
|
||||
static void dump_request(bmc_req_t *request);
|
||||
static void dump_response(bmc_rsp_t *response);
|
||||
static struct ipmi_rs *ipmi_bmc_send_cmd_ioctl(struct ipmi_intf *intf,
|
||||
struct ipmi_rq *req);
|
||||
static struct ipmi_rs *ipmi_bmc_send_cmd_putmsg(struct ipmi_intf *intf,
|
||||
struct ipmi_rq *req);
|
||||
|
||||
#define MESSAGE_BUFSIZE 1024
|
||||
|
||||
struct ipmi_intf ipmi_bmc_intf = {
|
||||
name: "bmc",
|
||||
desc: "IPMI v2.0 BMC interface",
|
||||
open: ipmi_bmc_open,
|
||||
close: ipmi_bmc_close,
|
||||
sendrecv: ipmi_bmc_send_cmd};
|
||||
|
||||
void
|
||||
ipmi_bmc_close(struct ipmi_intf *intf)
|
||||
{
|
||||
if (intf && intf->fd >= 0)
|
||||
close(intf->fd);
|
||||
|
||||
intf->opened = 0;
|
||||
intf->manufacturer_id = IPMI_OEM_UNKNOWN;
|
||||
intf->fd = -1;
|
||||
}
|
||||
|
||||
int
|
||||
ipmi_bmc_open(struct ipmi_intf *intf)
|
||||
{
|
||||
int method;
|
||||
|
||||
if (!intf)
|
||||
return -1;
|
||||
|
||||
/* Open local device */
|
||||
intf->fd = open(BMC_DEV, O_RDWR);
|
||||
|
||||
if (intf->fd <= 0) {
|
||||
perror("Could not open bmc device");
|
||||
return (-1);
|
||||
}
|
||||
curr_seq = 0;
|
||||
|
||||
intf->opened = 1;
|
||||
|
||||
if (bmc_method(intf->fd, &method) < 0) {
|
||||
perror("Could not determine bmc messaging interface");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
sendrecv_fn = (method == BMC_PUTMSG_METHOD) ?
|
||||
ipmi_bmc_send_cmd_putmsg : ipmi_bmc_send_cmd_ioctl;
|
||||
|
||||
intf->manufacturer_id = ipmi_get_oem(intf);
|
||||
return (intf->fd);
|
||||
}
|
||||
|
||||
struct ipmi_rs *
|
||||
ipmi_bmc_send_cmd(struct ipmi_intf *intf, struct ipmi_rq *req)
|
||||
{
|
||||
/* If not already opened open the device or network connection */
|
||||
if (!intf->opened && intf->open && intf->open(intf) < 0)
|
||||
return NULL;
|
||||
|
||||
/* sendrecv_fn cannot be NULL at this point */
|
||||
return ((*sendrecv_fn)(intf, req));
|
||||
}
|
||||
|
||||
static struct ipmi_rs *
|
||||
ipmi_bmc_send_cmd_ioctl(struct ipmi_intf *intf, struct ipmi_rq *req)
|
||||
{
|
||||
struct strioctl istr;
|
||||
static struct bmc_reqrsp reqrsp;
|
||||
static struct ipmi_rs rsp;
|
||||
|
||||
memset(&reqrsp, 0, sizeof (reqrsp));
|
||||
reqrsp.req.fn = req->msg.netfn;
|
||||
reqrsp.req.lun = 0;
|
||||
reqrsp.req.cmd = req->msg.cmd;
|
||||
reqrsp.req.datalength = req->msg.data_len;
|
||||
memcpy(reqrsp.req.data, req->msg.data, req->msg.data_len);
|
||||
reqrsp.rsp.datalength = RECV_MAX_PAYLOAD_SIZE;
|
||||
|
||||
istr.ic_cmd = IOCTL_IPMI_KCS_ACTION;
|
||||
istr.ic_timout = 0;
|
||||
istr.ic_dp = (char *)&reqrsp;
|
||||
istr.ic_len = sizeof (struct bmc_reqrsp);
|
||||
|
||||
if (verbose) {
|
||||
printf("--\n");
|
||||
dump_request(&reqrsp.req);
|
||||
printf("--\n");
|
||||
}
|
||||
|
||||
if (ioctl(intf->fd, I_STR, &istr) < 0) {
|
||||
perror("BMC IOCTL: I_STR");
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (verbose > 2) {
|
||||
dump_response(&reqrsp.rsp);
|
||||
printf("--\n");
|
||||
}
|
||||
|
||||
memset(&rsp, 0, sizeof (struct ipmi_rs));
|
||||
rsp.ccode = reqrsp.rsp.ccode;
|
||||
rsp.data_len = reqrsp.rsp.datalength;
|
||||
|
||||
/* Decrement for sizeof lun, cmd and ccode */
|
||||
rsp.data_len -= 3;
|
||||
|
||||
if (!rsp.ccode && (rsp.data_len > 0))
|
||||
memcpy(rsp.data, reqrsp.rsp.data, rsp.data_len);
|
||||
|
||||
return (&rsp);
|
||||
}
|
||||
|
||||
static struct ipmi_rs *
|
||||
ipmi_bmc_send_cmd_putmsg(struct ipmi_intf *intf, struct ipmi_rq *req)
|
||||
{
|
||||
struct strbuf sb;
|
||||
int flags = 0;
|
||||
static uint32_t msg_seq = 0;
|
||||
|
||||
/*
|
||||
* The length of the message structure is equal to the size of the
|
||||
* bmc_req_t structure, PLUS any additional data space in excess of
|
||||
* the data space already reserved in the data member + <n> for
|
||||
* the rest of the members in the bmc_msg_t structure.
|
||||
*/
|
||||
int msgsz = offsetof(bmc_msg_t, msg) + sizeof(bmc_req_t) +
|
||||
((req->msg.data_len > SEND_MAX_PAYLOAD_SIZE) ?
|
||||
(req->msg.data_len - SEND_MAX_PAYLOAD_SIZE) : 0);
|
||||
bmc_msg_t *msg = malloc(msgsz);
|
||||
bmc_req_t *request = (bmc_req_t *)&msg->msg[0];
|
||||
bmc_rsp_t *response;
|
||||
static struct ipmi_rs rsp;
|
||||
struct ipmi_rs *ret = NULL;
|
||||
|
||||
msg->m_type = BMC_MSG_REQUEST;
|
||||
msg->m_id = msg_seq++;
|
||||
request->fn = req->msg.netfn;
|
||||
request->lun = 0;
|
||||
request->cmd = req->msg.cmd;
|
||||
request->datalength = req->msg.data_len;
|
||||
memcpy(request->data, req->msg.data, req->msg.data_len);
|
||||
|
||||
sb.len = msgsz;
|
||||
sb.buf = (unsigned char *)msg;
|
||||
|
||||
if (verbose) {
|
||||
printf("--\n");
|
||||
dump_request(request);
|
||||
printf("--\n");
|
||||
}
|
||||
|
||||
if (putmsg(intf->fd, NULL, &sb, 0) < 0) {
|
||||
perror("BMC putmsg: ");
|
||||
free(msg);
|
||||
msg = NULL;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
free(msg);
|
||||
msg = NULL;
|
||||
|
||||
sb.buf = malloc(MESSAGE_BUFSIZE);
|
||||
sb.maxlen = MESSAGE_BUFSIZE;
|
||||
|
||||
if (getmsg(intf->fd, NULL, &sb, &flags) < 0) {
|
||||
perror("BMC getmsg: ");
|
||||
free(sb.buf);
|
||||
sb.buf = NULL;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
msg = (bmc_msg_t *)sb.buf;
|
||||
|
||||
if (verbose > 3) {
|
||||
printf("Got msg (id 0x%x) type 0x%x\n", msg->m_id, msg->m_type);
|
||||
}
|
||||
|
||||
|
||||
/* Did we get an error back from the stream? */
|
||||
switch (msg->m_type) {
|
||||
|
||||
case BMC_MSG_RESPONSE:
|
||||
response = (bmc_rsp_t *)&msg->msg[0];
|
||||
|
||||
if (verbose > 2) {
|
||||
dump_response(response);
|
||||
printf("--\n");
|
||||
}
|
||||
|
||||
memset(&rsp, 0, sizeof (struct ipmi_rs));
|
||||
rsp.ccode = response->ccode;
|
||||
rsp.data_len = response->datalength;
|
||||
|
||||
if (!rsp.ccode && (rsp.data_len > 0))
|
||||
memcpy(rsp.data, response->data, rsp.data_len);
|
||||
|
||||
ret = &rsp;
|
||||
break;
|
||||
|
||||
case BMC_MSG_ERROR:
|
||||
/* In case of an error, msg->msg[0] has the error code */
|
||||
printf("bmc_send_cmd: %s\n", strerror(msg->msg[0]));
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
free(sb.buf);
|
||||
sb.buf = NULL;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine which interface to use. Returns the interface method
|
||||
* to use.
|
||||
*/
|
||||
static int
|
||||
bmc_method(int fd, int *if_type)
|
||||
{
|
||||
struct strioctl istr;
|
||||
int retval = 0;
|
||||
uint8_t method = BMC_PUTMSG_METHOD;
|
||||
|
||||
istr.ic_cmd = IOCTL_IPMI_INTERFACE_METHOD;
|
||||
istr.ic_timout = 0;
|
||||
istr.ic_dp = (uint8_t *)&method;
|
||||
istr.ic_len = 1;
|
||||
|
||||
/*
|
||||
* If the ioctl doesn't exist, we should get an EINVAL back.
|
||||
* Bail out on any other error.
|
||||
*/
|
||||
if (ioctl(fd, I_STR, &istr) < 0) {
|
||||
|
||||
if (errno != EINVAL)
|
||||
retval = -1;
|
||||
else
|
||||
method = BMC_IOCTL_METHOD;
|
||||
}
|
||||
|
||||
if (retval == 0)
|
||||
*if_type = method;
|
||||
|
||||
return (retval);
|
||||
}
|
||||
|
||||
static void
|
||||
dump_request(bmc_req_t *request)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("BMC req.fn : 0x%x\n", request->fn);
|
||||
printf("BMC req.lun : 0x%x\n", request->lun);
|
||||
printf("BMC req.cmd : 0x%x\n", request->cmd);
|
||||
printf("BMC req.datalength : 0x%x\n", request->datalength);
|
||||
printf("BMC req.data : ");
|
||||
|
||||
if (request->datalength > 0) {
|
||||
for (i = 0; i < request->datalength; i++)
|
||||
printf("0x%x ", request->data[i]);
|
||||
} else {
|
||||
printf("<NONE>");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void
|
||||
dump_response(bmc_rsp_t *response)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("BMC rsp.fn : 0x%x\n", response->fn);
|
||||
printf("BMC rsp.lun : 0x%x\n", response->lun);
|
||||
printf("BMC rsp.cmd : 0x%x\n", response->cmd);
|
||||
printf("BMC rsp.ccode : 0x%x\n", response->ccode);
|
||||
printf("BMC rsp.datalength : 0x%x\n", response->datalength);
|
||||
printf("BMC rsp.data : ");
|
||||
|
||||
if (response->datalength > 0) {
|
||||
for (i = 0; i < response->datalength; i++)
|
||||
printf("0x%x ", response->data[i]);
|
||||
} else {
|
||||
printf("<NONE>");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
52
src/plugins/bmc/bmc.h
Normal file
52
src/plugins/bmc/bmc.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2004 Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistribution of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistribution in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of Sun Microsystems, Inc. or the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* This software is provided "AS IS," without a warranty of any kind.
|
||||
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
||||
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
||||
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
|
||||
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
|
||||
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
|
||||
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
|
||||
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
|
||||
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
||||
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
#ifndef _IPMI_BMC_H_
|
||||
#define _IPMI_BMC_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <ipmitool/ipmi.h>
|
||||
|
||||
#define BMC_DEV "/dev/bmc"
|
||||
|
||||
struct ipmi_rs *ipmi_bmc_send_cmd(struct ipmi_intf *intf, struct ipmi_rq *req);
|
||||
int ipmi_bmc_open(struct ipmi_intf *intf);
|
||||
void ipmi_bmc_close(struct ipmi_intf *intf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _IPMI_BMC_H_ */
|
||||
207
src/plugins/bmc/bmc_intf.h
Normal file
207
src/plugins/bmc/bmc_intf.h
Normal file
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Copyright (c) 2004 Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistribution of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistribution in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of Sun Microsystems, Inc. or the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* This software is provided "AS IS," without a warranty of any kind.
|
||||
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
||||
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
||||
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
|
||||
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
|
||||
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
|
||||
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
|
||||
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
|
||||
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
||||
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
#ifndef _BMC_INTF_H
|
||||
#define _BMC_INTF_H
|
||||
|
||||
#pragma ident "@(#)bmc_intf.h 1.2 05/03/07 SMI"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define BMC_SUCCESS 0x0
|
||||
#define BMC_FAILURE 0x1
|
||||
|
||||
#define BMC_NETFN_CHASSIS 0x0
|
||||
#define BMC_NETFN_BRIDGE 0x2
|
||||
#define BMC_NETFN_SE 0x4
|
||||
#define BMC_NETFN_APP 0x6
|
||||
#define BMC_NETFN_FIRMWARE 0x8
|
||||
#define BMC_NETFN_STORAGE 0xa
|
||||
#define BMC_NETFN_TRANSPORT 0xc
|
||||
|
||||
#define SEND_MAX_PAYLOAD_SIZE 34 /* MAX payload */
|
||||
#define RECV_MAX_PAYLOAD_SIZE 33 /* MAX payload */
|
||||
#define BMC_MIN_RESPONSE_SIZE 3
|
||||
#define BMC_MIN_REQUEST_SIZE 2
|
||||
#define BMC_MAX_RESPONSE_SIZE (BMC_MIN_RESPONSE_SIZE + RECV_MAX_PAYLOAD_SIZE)
|
||||
#define BMC_MAX_REQUEST_SIZE (BMC_MIN_REQUEST_SIZE + BMC_MAX_RESPONSE_SIZE)
|
||||
|
||||
#define BUF_SIZE 256
|
||||
#define MAX_BUF_SIZE 256
|
||||
|
||||
/*
|
||||
* Useful macros
|
||||
*/
|
||||
#define FORM_NETFNLUN(net, lun) ((((net) << 2) | ((lun) & 0x3)))
|
||||
#define GET_NETFN(netfn) (((netfn) >> 2) & 0x3f)
|
||||
#define GET_LUN(netfn) (netfn & 0x3)
|
||||
#define RESP_NETFN(nflun) ((nflun) | 1)
|
||||
#define ISREQUEST(nl) (((nl) & 1) == 0) /* test for request */
|
||||
#define ISRESPONSE(nl) (((nl) & 1) == 1) /* test for response */
|
||||
|
||||
|
||||
/* for checking BMC specific stuff */
|
||||
#define BMC_GET_DEVICE_ID 0x1 /* GET DEVICE ID COMMAND */
|
||||
#define BMC_IPMI_15_VER 0x51 /* IPMI 1.5 definion */
|
||||
|
||||
/* BMC Completion Code and OEM Completion Code */
|
||||
#define BMC_IPMI_UNSPECIFIC_ERROR 0xFF /* Unspecific Error */
|
||||
#define BMC_IPMI_INVALID_COMMAND 0xC1 /* Invalid Command */
|
||||
#define BMC_IPMI_COMMAND_TIMEOUT 0xC3 /* Command Timeout */
|
||||
#define BMC_IPMI_DATA_LENGTH_EXCEED 0xC8 /* DataLength exceeded limit */
|
||||
#define BMC_IPMI_OEM_FAILURE_SENDBMC 0x7E /* Cannot send BMC req */
|
||||
|
||||
|
||||
#define IOCTL_IPMI_KCS_ACTION 0x01
|
||||
#define IOCTL_IPMI_INTERFACE_METHOD 0x02
|
||||
|
||||
/* Interface methods returned from IOCTL_IPMI_INTERFACE_METHOD ioctl: */
|
||||
|
||||
#define BMC_IOCTL_METHOD 0 /* Not returned from ioctl, */
|
||||
/* but can be used by */
|
||||
/* applications that want to */
|
||||
/* compare against an */
|
||||
/* alternative method. */
|
||||
#define BMC_PUTMSG_METHOD 1
|
||||
|
||||
/*
|
||||
* bmc_req_t is the data structure to send
|
||||
* request packet from applications to the driver
|
||||
* module.
|
||||
*
|
||||
* the request pkt is mainly for KCS-interface-BMC
|
||||
* messages. Since the system interface is session-less
|
||||
* connections, the packet won't have any session
|
||||
* information.
|
||||
*
|
||||
* the data payload will be 2 bytes less than max
|
||||
* BMC supported packet size.
|
||||
* the address of the responder is always BMC and so
|
||||
* rsSa field is not required.
|
||||
*/
|
||||
typedef struct bmc_req {
|
||||
uint8_t fn; /* netFn for command */
|
||||
uint8_t lun; /* logical unit on responder */
|
||||
uint8_t cmd; /* command */
|
||||
uint8_t datalength; /* length of following data */
|
||||
uint8_t data[SEND_MAX_PAYLOAD_SIZE]; /* request data */
|
||||
} bmc_req_t;
|
||||
|
||||
/*
|
||||
* bmc_rsp_t is the data structure to send
|
||||
* respond packet from applications to the driver
|
||||
* module.
|
||||
*
|
||||
* the respond pkt is mainly for KCS-interface-BMC
|
||||
* messages. Since the system interface is session-less
|
||||
* connections, the packet won't have any session
|
||||
* information.
|
||||
*
|
||||
* the data payload will be 2 bytes less than max
|
||||
* BMC supported packet size.
|
||||
*/
|
||||
typedef struct bmc_rsp {
|
||||
uint8_t fn; /* netFn for command */
|
||||
uint8_t lun; /* logical unit on responder */
|
||||
uint8_t cmd; /* command */
|
||||
uint8_t ccode; /* completion code */
|
||||
uint8_t datalength; /* Length */
|
||||
uint8_t data[RECV_MAX_PAYLOAD_SIZE]; /* response */
|
||||
} bmc_rsp_t;
|
||||
|
||||
/*
|
||||
* the data structure for synchronous operation via ioctl (DEPRECATED)
|
||||
*/
|
||||
typedef struct bmc_reqrsp {
|
||||
bmc_req_t req; /* request half */
|
||||
bmc_rsp_t rsp; /* response half */
|
||||
} bmc_reqrsp_t;
|
||||
|
||||
|
||||
/*
|
||||
* The new way of communicating with the bmc driver is to use putmsg() to
|
||||
* send a message of a particular type. Replies from the driver also have this
|
||||
* form, and will require the user to process the type field before examining
|
||||
* the rest of the reply.
|
||||
*
|
||||
* The only change that must be observed when using the request and response
|
||||
* structures defined above is as follows:
|
||||
* when sending messages to the bmc driver, the data portion is now variable
|
||||
* (the caller must allocate enough space to store the all structure members,
|
||||
* plus enough space to cover the amount of data in the request), e.g.:
|
||||
*
|
||||
* bmc_msg_t *msg = malloc(offsetof(bmc_msg_t, msg) + sizeof(bmc_req_t) + 10);
|
||||
*
|
||||
* The amount allocated for the message is (# of bytes before the msg field) +
|
||||
* the size of a bmc_req_t (which includes SEND_MAX_PAYLOAD_SIZE
|
||||
* bytes in the data field), plus an additional 10 bytes for the data
|
||||
* field (so the data field would occupy (SEND_MAX_PAYLOAD_SIZE + 10)
|
||||
* bytes). The datalength member must reflect the amount of data in the
|
||||
* request's data field (as was required when using the ioctl interface).
|
||||
*/
|
||||
typedef struct bmc_msg {
|
||||
uint8_t m_type; /* Message type (see below) */
|
||||
uint32_t m_id; /* Message ID */
|
||||
uint8_t reserved[32];
|
||||
uint8_t msg[1]; /* Variable length message data */
|
||||
} bmc_msg_t;
|
||||
|
||||
|
||||
/*
|
||||
* An error response passed back from the bmc driver will have its m_id
|
||||
* field set to BMC_UNKNOWN_MSG_ID if a message is sent to it that is not
|
||||
* at least as large as a bmc_msg_t.
|
||||
*/
|
||||
#define BMC_UNKNOWN_MSG_ID ~((uint32_t)0)
|
||||
|
||||
|
||||
/*
|
||||
* Possible values for the m_type field in bmc_msg_t:
|
||||
*/
|
||||
#define BMC_MSG_REQUEST 1 /* BMC request (as above, sent to the */
|
||||
/* driver by the user), bmc_msg.msg */
|
||||
/* begins with the bmc_req_t */
|
||||
/* structure. */
|
||||
#define BMC_MSG_RESPONSE 2 /* BMC response (sent by the driver) */
|
||||
/* bmc_msg.msg begins with the */
|
||||
/* bmc_rsp_t structure. */
|
||||
#define BMC_MSG_ERROR 3 /* Error while processing a user msg */
|
||||
/* msg[0] is the error code */
|
||||
/* (interpret as an errno value) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BMC_INTF_H */
|
||||
8
src/plugins/dummy/Makefile.am
Normal file
8
src/plugins/dummy/Makefile.am
Normal file
@@ -0,0 +1,8 @@
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/include
|
||||
|
||||
EXTRA_LTLIBRARIES = libintf_dummy.la
|
||||
noinst_LTLIBRARIES = @INTF_DUMMY_LIB@
|
||||
libintf_dummy_la_LIBADD = $(top_builddir)/lib/libipmitool.la
|
||||
libintf_dummy_la_SOURCES = dummy.c
|
||||
286
src/plugins/dummy/dummy.c
Normal file
286
src/plugins/dummy/dummy.c
Normal file
@@ -0,0 +1,286 @@
|
||||
/* Copyright (c) 2013 Zdenek Styblik, All Rights Reserved
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistribution of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistribution in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of Zdenek Styblik or the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* This software is provided "AS IS," without a warranty of any kind.
|
||||
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
||||
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
||||
* Zdenek Styblik SHALL NOT BE LIABLE
|
||||
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
|
||||
* Zdenek Styblik BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
|
||||
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
|
||||
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
|
||||
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
||||
* EVEN IF Zdenek Styblik HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <ipmitool/ipmi.h>
|
||||
#include <ipmitool/ipmi_intf.h>
|
||||
#include <ipmitool/helper.h>
|
||||
#include <ipmitool/log.h>
|
||||
|
||||
#include "dummy.h"
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
extern int verbose;
|
||||
|
||||
/* data_read - read data from socket
|
||||
*
|
||||
* @data_ptr - pointer to memory where to store read data
|
||||
* @data_len - how much to read from socket
|
||||
*
|
||||
* return 0 on success, otherwise (-1)
|
||||
*/
|
||||
int
|
||||
data_read(int fd, void *data_ptr, int data_len)
|
||||
{
|
||||
int rc = 0;
|
||||
int data_read = 0;
|
||||
int data_total = 0;
|
||||
int try = 1;
|
||||
int errno_save = 0;
|
||||
if (data_len < 0) {
|
||||
return (-1);
|
||||
}
|
||||
while (data_total < data_len && try < 4) {
|
||||
errno = 0;
|
||||
/* TODO - add poll() */
|
||||
data_read = read(fd, data_ptr, data_len);
|
||||
errno_save = errno;
|
||||
if (data_read > 0) {
|
||||
data_total+= data_read;
|
||||
}
|
||||
if (errno_save != 0) {
|
||||
if (errno_save == EINTR || errno_save == EAGAIN) {
|
||||
try++;
|
||||
sleep(2);
|
||||
continue;
|
||||
} else {
|
||||
errno = errno_save;
|
||||
perror("dummy failed on read(): ");
|
||||
rc = (-1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (try > 3 && data_total != data_len) {
|
||||
rc = (-1);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* data_write - write data to the socket
|
||||
*
|
||||
* @data_ptr - ptr to data to send
|
||||
* @data_len - how long is the data to send
|
||||
*
|
||||
* returns 0 on success, otherwise (-1)
|
||||
*/
|
||||
int
|
||||
data_write(int fd, void *data_ptr, int data_len)
|
||||
{
|
||||
int rc = 0;
|
||||
int data_written = 0;
|
||||
int data_total = 0;
|
||||
int try = 1;
|
||||
int errno_save = 0;
|
||||
if (data_len < 0) {
|
||||
return (-1);
|
||||
}
|
||||
while (data_total < data_len && try < 4) {
|
||||
errno = 0;
|
||||
/* TODO - add poll() */
|
||||
data_written = write(fd, data_ptr, data_len);
|
||||
errno_save = errno;
|
||||
if (data_read > 0) {
|
||||
data_total+= data_written;
|
||||
}
|
||||
if (errno_save != 0) {
|
||||
if (errno_save == EINTR || errno_save == EAGAIN) {
|
||||
try++;
|
||||
sleep(2);
|
||||
continue;
|
||||
} else {
|
||||
errno = errno_save;
|
||||
perror("dummy failed on read(): ");
|
||||
rc = (-1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (try > 3 && data_total != data_len) {
|
||||
rc = (-1);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* ipmi_dummyipmi_close - send "BYE" and close socket
|
||||
*
|
||||
* @intf - ptr to initialize ipmi_intf struct
|
||||
*
|
||||
* returns void
|
||||
*/
|
||||
static void
|
||||
ipmi_dummyipmi_close(struct ipmi_intf *intf)
|
||||
{
|
||||
struct dummy_rq req;
|
||||
int data_total = 0;
|
||||
int data_written = 0;
|
||||
int try = 0;
|
||||
if (intf->fd < 0) {
|
||||
return;
|
||||
}
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.msg.netfn = 0x3f;
|
||||
req.msg.cmd = 0xff;
|
||||
if (data_write(intf->fd, &req, sizeof(req)) != 0) {
|
||||
lprintf(LOG_ERR, "dummy failed to send 'BYE'");
|
||||
}
|
||||
close(intf->fd);
|
||||
intf->fd = (-1);
|
||||
intf->opened = 0;
|
||||
}
|
||||
|
||||
/* ipmi_dummyipmi_open - open socket and prepare ipmi_intf struct
|
||||
*
|
||||
* @intf - ptr to ipmi_inf struct
|
||||
*
|
||||
* returns 0 on success, (-1) on error
|
||||
*/
|
||||
static int
|
||||
ipmi_dummyipmi_open(struct ipmi_intf *intf)
|
||||
{
|
||||
struct sockaddr_un address;
|
||||
int len;
|
||||
int rc;
|
||||
|
||||
if (intf->opened == 1) {
|
||||
return intf->fd;
|
||||
}
|
||||
intf->fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (intf->fd == (-1)) {
|
||||
lprintf(LOG_ERR, "dummy failed on socket()");
|
||||
return (-1);
|
||||
}
|
||||
address.sun_family = AF_UNIX;
|
||||
strcpy(address.sun_path, DUMMY_SOCKET_PATH);
|
||||
len = sizeof(address);
|
||||
rc = connect(intf->fd, (struct sockaddr *)&address, len);
|
||||
if (rc != 0) {
|
||||
perror("dummy failed on connect(): ");
|
||||
return (-1);
|
||||
}
|
||||
intf->opened = 1;
|
||||
return intf->fd;
|
||||
}
|
||||
|
||||
/* ipmi_dummyipmi_send_cmd - send IPMI payload and await reply
|
||||
*
|
||||
* @intf - ptr to initialized ipmi_intf struct
|
||||
* @req - ptr to ipmi_rq struct to send
|
||||
*
|
||||
* return pointer to struct ipmi_rs OR NULL on error
|
||||
*/
|
||||
static struct ipmi_rs*
|
||||
ipmi_dummyipmi_send_cmd(struct ipmi_intf *intf, struct ipmi_rq *req)
|
||||
{
|
||||
static struct ipmi_rs rsp;
|
||||
struct dummy_rq req_dummy;
|
||||
struct dummy_rs rsp_dummy;
|
||||
if (intf == NULL || intf->fd < 0 || intf->opened != 1) {
|
||||
lprintf(LOG_ERR, "dummy failed on intf check.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(&req_dummy, 0, sizeof(req_dummy));
|
||||
req_dummy.msg.netfn = req->msg.netfn;
|
||||
req_dummy.msg.lun = req->msg.lun;
|
||||
req_dummy.msg.cmd = req->msg.cmd;
|
||||
req_dummy.msg.target_cmd = req->msg.target_cmd;
|
||||
req_dummy.msg.data_len = req->msg.data_len;
|
||||
req_dummy.msg.data = req->msg.data;
|
||||
if (verbose) {
|
||||
lprintf(LOG_NOTICE, ">>> IPMI req");
|
||||
lprintf(LOG_NOTICE, "msg.data_len: %i",
|
||||
req_dummy.msg.data_len);
|
||||
lprintf(LOG_NOTICE, "msg.netfn: %x", req_dummy.msg.netfn);
|
||||
lprintf(LOG_NOTICE, "msg.cmd: %x", req_dummy.msg.cmd);
|
||||
lprintf(LOG_NOTICE, "msg.target_cmd: %x",
|
||||
req_dummy.msg.target_cmd);
|
||||
lprintf(LOG_NOTICE, "msg.lun: %x", req_dummy.msg.lun);
|
||||
lprintf(LOG_NOTICE, ">>>");
|
||||
}
|
||||
if (data_write(intf->fd, &req_dummy,
|
||||
sizeof(struct dummy_rq)) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (req->msg.data_len > 0) {
|
||||
if (data_write(intf->fd, (uint8_t *)(req->msg.data),
|
||||
req_dummy.msg.data_len) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
memset(&rsp_dummy, 0, sizeof(rsp_dummy));
|
||||
if (data_read(intf->fd, &rsp_dummy, sizeof(struct dummy_rs)) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (rsp_dummy.data_len > 0) {
|
||||
if (data_read(intf->fd, (uint8_t *)&rsp.data,
|
||||
rsp_dummy.data_len) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
rsp.ccode = rsp_dummy.ccode;
|
||||
rsp.data_len = rsp_dummy.data_len;
|
||||
rsp.msg.netfn = rsp_dummy.msg.netfn;
|
||||
rsp.msg.cmd = rsp_dummy.msg.cmd;
|
||||
rsp.msg.seq = rsp_dummy.msg.seq;
|
||||
rsp.msg.lun = rsp_dummy.msg.lun;
|
||||
if (verbose) {
|
||||
lprintf(LOG_NOTICE, "<<< IPMI rsp");
|
||||
lprintf(LOG_NOTICE, "ccode: %x", rsp.ccode);
|
||||
lprintf(LOG_NOTICE, "data_len: %i", rsp.data_len);
|
||||
lprintf(LOG_NOTICE, "msg.netfn: %x", rsp.msg.netfn);
|
||||
lprintf(LOG_NOTICE, "msg.cmd: %x", rsp.msg.cmd);
|
||||
lprintf(LOG_NOTICE, "msg.seq: %x", rsp.msg.seq);
|
||||
lprintf(LOG_NOTICE, "msg.lun: %x", rsp.msg.lun);
|
||||
lprintf(LOG_NOTICE, "<<<");
|
||||
}
|
||||
return &rsp;
|
||||
}
|
||||
|
||||
struct ipmi_intf ipmi_dummy_intf = {
|
||||
name: "dummy",
|
||||
desc: "Linux DummyIPMI Interface",
|
||||
open: ipmi_dummyipmi_open,
|
||||
close: ipmi_dummyipmi_close,
|
||||
sendrecv: ipmi_dummyipmi_send_cmd,
|
||||
my_addr: IPMI_BMC_SLAVE_ADDR,
|
||||
target_addr: IPMI_BMC_SLAVE_ADDR,
|
||||
};
|
||||
30
src/plugins/dummy/dummy.h
Normal file
30
src/plugins/dummy/dummy.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef IPMI_DUMMYIPMI_H
|
||||
# define IPMI_DUMMYIPMI_H
|
||||
|
||||
# define DUMMY_SOCKET_PATH "/tmp/.ipmi_dummy"
|
||||
|
||||
struct dummy_rq {
|
||||
struct {
|
||||
uint8_t netfn;
|
||||
uint8_t lun;
|
||||
uint8_t cmd;
|
||||
uint8_t target_cmd;
|
||||
uint16_t data_len;
|
||||
uint8_t *data;
|
||||
} msg;
|
||||
};
|
||||
|
||||
struct dummy_rs {
|
||||
struct {
|
||||
uint8_t netfn;
|
||||
uint8_t cmd;
|
||||
uint8_t seq;
|
||||
uint8_t lun;
|
||||
} msg;
|
||||
|
||||
uint8_t ccode;
|
||||
int data_len;
|
||||
uint8_t *data;
|
||||
};
|
||||
|
||||
#endif
|
||||
9
src/plugins/free/Makefile.am
Normal file
9
src/plugins/free/Makefile.am
Normal file
@@ -0,0 +1,9 @@
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/include
|
||||
|
||||
EXTRA_LTLIBRARIES = libintf_free.la
|
||||
noinst_LTLIBRARIES = @INTF_FREE_LIB@
|
||||
libintf_free_la_LIBADD = $(top_builddir)/lib/libipmitool.la
|
||||
libintf_free_la_SOURCES = free.c
|
||||
libintf_free_la_LDFLAGS = -lfreeipmi
|
||||
318
src/plugins/free/free.c
Normal file
318
src/plugins/free/free.c
Normal file
@@ -0,0 +1,318 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistribution of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistribution in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of Sun Microsystems, Inc. or the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* This software is provided "AS IS," without a warranty of any kind.
|
||||
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
||||
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
||||
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
|
||||
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
|
||||
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
|
||||
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
|
||||
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
|
||||
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
||||
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*
|
||||
* You acknowledge that this software is not designed or intended for use
|
||||
* in the design, construction, operation or maintenance of any nuclear
|
||||
* facility.
|
||||
*/
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <ipmitool/ipmi.h>
|
||||
#include <ipmitool/ipmi_intf.h>
|
||||
|
||||
#include <freeipmi/freeipmi.h>
|
||||
#if IPMI_INTF_FREE_0_3_0 || IPMI_INTF_FREE_0_4_0 || IPMI_INTF_FREE_0_5_0
|
||||
#include <freeipmi/udm/ipmi-udm.h>
|
||||
#endif
|
||||
|
||||
#if IPMI_INTF_FREE_0_6_0
|
||||
ipmi_ctx_t dev = NULL;
|
||||
#else /* !IPMI_INTF_FREE_0_6_0 */
|
||||
ipmi_device_t dev = NULL;
|
||||
#endif /* !IPMI_INTF_FREE_0_6_0 */
|
||||
|
||||
extern int verbose;
|
||||
|
||||
static int ipmi_free_open(struct ipmi_intf * intf)
|
||||
{
|
||||
int kcs_ret = -1, ssif_ret = -1;
|
||||
|
||||
if (getuid() != 0) {
|
||||
fprintf(stderr, "Permission denied, must be root\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if IPMI_INTF_FREE_0_3_0
|
||||
if (!(dev = ipmi_open_inband (IPMI_DEVICE_KCS,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
IPMI_FLAGS_DEFAULT))) {
|
||||
if (!(dev = ipmi_open_inband (IPMI_DEVICE_SSIF,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
IPMI_FLAGS_DEFAULT))) {
|
||||
perror("ipmi_open_inband()");
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
#elif IPMI_INTF_FREE_0_4_0
|
||||
if (!(dev = ipmi_device_create())) {
|
||||
perror("ipmi_device_create");
|
||||
goto cleanup;
|
||||
}
|
||||
if (ipmi_open_inband (dev,
|
||||
IPMI_DEVICE_KCS,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
IPMI_FLAGS_DEFAULT) < 0) {
|
||||
if (ipmi_open_inband (dev,
|
||||
IPMI_DEVICE_SSIF,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
IPMI_FLAGS_DEFAULT) < 0) {
|
||||
fprintf(stderr,
|
||||
"ipmi_open_inband(): %s\n",
|
||||
ipmi_device_strerror(ipmi_device_errnum(dev)));
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
#elif IPMI_INTF_FREE_0_5_0
|
||||
if (!(dev = ipmi_device_create())) {
|
||||
perror("ipmi_device_create");
|
||||
goto cleanup;
|
||||
}
|
||||
if (ipmi_open_inband (dev,
|
||||
IPMI_DEVICE_KCS,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
IPMI_FLAGS_DEFAULT) < 0) {
|
||||
if (ipmi_open_inband (dev,
|
||||
IPMI_DEVICE_SSIF,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
IPMI_FLAGS_DEFAULT) < 0) {
|
||||
fprintf(stderr,
|
||||
"ipmi_open_inband(): %s\n",
|
||||
ipmi_device_strerror(ipmi_device_errnum(dev)));
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
#elif IPMI_INTF_FREE_0_6_0
|
||||
if (!(dev = ipmi_ctx_create())) {
|
||||
perror("ipmi_ctx_create");
|
||||
goto cleanup;
|
||||
}
|
||||
if (ipmi_ctx_open_inband (dev,
|
||||
IPMI_DEVICE_KCS,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
IPMI_FLAGS_DEFAULT) < 0) {
|
||||
if (ipmi_ctx_open_inband (dev,
|
||||
IPMI_DEVICE_SSIF,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
IPMI_FLAGS_DEFAULT) < 0) {
|
||||
fprintf(stderr,
|
||||
"ipmi_open_inband(): %s\n",
|
||||
ipmi_ctx_strerror(ipmi_ctx_errnum(dev)));
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
intf->opened = 1;
|
||||
intf->manufacturer_id = ipmi_get_oem(intf);
|
||||
return 0;
|
||||
cleanup:
|
||||
if (dev) {
|
||||
#if IPMI_INTF_FREE_0_3_0
|
||||
ipmi_close_device(dev);
|
||||
#elif IPMI_INTF_FREE_0_4_0 || IPMI_INTF_FREE_0_5_0
|
||||
ipmi_close_device(dev);
|
||||
ipmi_device_destroy(dev);
|
||||
#elif IPMI_INTF_FREE_0_6_0
|
||||
ipmi_ctx_close(dev);
|
||||
ipmi_ctx_destroy(dev);
|
||||
#endif
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void ipmi_free_close(struct ipmi_intf * intf)
|
||||
{
|
||||
if (dev) {
|
||||
#if IPMI_INTF_FREE_0_3_0
|
||||
ipmi_close_device(dev);
|
||||
#elif IPMI_INTF_FREE_0_4_0 || IPMI_INTF_FREE_0_5_0
|
||||
ipmi_close_device(dev);
|
||||
ipmi_device_destroy(dev);
|
||||
#elif IPMI_INTF_FREE_0_6_0
|
||||
ipmi_ctx_close(dev);
|
||||
ipmi_ctx_destroy(dev);
|
||||
#endif
|
||||
}
|
||||
intf->opened = 0;
|
||||
intf->manufacturer_id = IPMI_OEM_UNKNOWN;
|
||||
}
|
||||
|
||||
static struct ipmi_rs * ipmi_free_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
|
||||
{
|
||||
u_int8_t lun = req->msg.lun;
|
||||
u_int8_t cmd = req->msg.cmd;
|
||||
u_int8_t netfn = req->msg.netfn;
|
||||
u_int8_t rq_buf[IPMI_BUF_SIZE];
|
||||
u_int8_t rs_buf[IPMI_BUF_SIZE];
|
||||
u_int32_t rs_buf_len = IPMI_BUF_SIZE;
|
||||
int32_t rs_len;
|
||||
|
||||
static struct ipmi_rs rsp;
|
||||
|
||||
/* achu: FreeIPMI requests have the cmd as the first byte of
|
||||
* the data. Responses have cmd as the first byte and
|
||||
* completion code as the second byte. This differs from some
|
||||
* other APIs, so it must be compensated for within the ipmitool
|
||||
* interface.
|
||||
*/
|
||||
|
||||
if (!intf || !req)
|
||||
return NULL;
|
||||
|
||||
if (!intf->opened && intf->open && intf->open(intf) < 0)
|
||||
return NULL;
|
||||
|
||||
if (req->msg.data_len > IPMI_BUF_SIZE)
|
||||
return NULL;
|
||||
|
||||
memset(rq_buf, '\0', IPMI_BUF_SIZE);
|
||||
memset(rs_buf, '\0', IPMI_BUF_SIZE);
|
||||
memcpy(rq_buf, &cmd, 1);
|
||||
|
||||
if (req->msg.data)
|
||||
memcpy(rq_buf + 1, req->msg.data, req->msg.data_len);
|
||||
|
||||
if (intf->target_addr != 0
|
||||
&& intf->target_addr != IPMI_BMC_SLAVE_ADDR) {
|
||||
#if IPMI_INTF_FREE_BRIDGING
|
||||
if ((rs_len = ipmi_cmd_raw_ipmb(dev,
|
||||
intf->target_channel,
|
||||
intf->target_addr,
|
||||
lun,
|
||||
netfn,
|
||||
rq_buf,
|
||||
req->msg.data_len + 1,
|
||||
rs_buf,
|
||||
rs_buf_len)) < 0) {
|
||||
if (verbose > 3)
|
||||
fprintf(stderr,
|
||||
"ipmi_cmd_raw_ipmb: %s\n",
|
||||
ipmi_ctx_strerror(ipmi_ctx_errnum(dev)));
|
||||
/* Compared to FreeIPMI, user is expected to input
|
||||
* the target channel on the command line, it is not automatically
|
||||
* discovered. So that is the likely cause of an error.
|
||||
*
|
||||
* Instead of returning an error, return a bad response so output
|
||||
* of ipmitool commands looks like other interfaces
|
||||
*/
|
||||
rs_len = 2;
|
||||
rs_buf[0] = 0;
|
||||
rs_buf[1] = 0xC1; /* invalid command */
|
||||
}
|
||||
#else /* !IPMI_INTF_FREE_BRIDGING */
|
||||
if (verbose > 3)
|
||||
fprintf(stderr, "sensor bridging not supported in this driver version");
|
||||
/* instead of returning an error, return a bad response so output
|
||||
* of ipmitool commands looks like other interfaces
|
||||
*/
|
||||
rs_len = 2;
|
||||
rs_buf[0] = 0;
|
||||
rs_buf[1] = 0xC1; /* invalid command */
|
||||
#endif /* !IPMI_INTF_FREE_BRIDGING */
|
||||
}
|
||||
else {
|
||||
if ((rs_len = ipmi_cmd_raw(dev,
|
||||
lun,
|
||||
netfn,
|
||||
rq_buf,
|
||||
req->msg.data_len + 1,
|
||||
rs_buf,
|
||||
rs_buf_len)) < 0) {
|
||||
#if IPMI_INTF_FREE_0_3_0
|
||||
perror("ipmi_cmd_raw");
|
||||
#elif IPMI_INTF_FREE_0_4_0 || IPMI_INTF_FREE_0_5_0
|
||||
fprintf(stderr,
|
||||
"ipmi_cmd_raw: %s\n",
|
||||
ipmi_device_strerror(ipmi_device_errnum(dev)));
|
||||
#elif IPMI_INTF_FREE_0_6_0
|
||||
fprintf(stderr,
|
||||
"ipmi_cmd_raw: %s\n",
|
||||
ipmi_ctx_strerror(ipmi_ctx_errnum(dev)));
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
memset(&rsp, 0, sizeof(struct ipmi_rs));
|
||||
rsp.ccode = (unsigned char)rs_buf[1];
|
||||
rsp.data_len = (int)rs_len - 2;
|
||||
|
||||
if (!rsp.ccode && rsp.data_len)
|
||||
memcpy(rsp.data, rs_buf + 2, rsp.data_len);
|
||||
|
||||
return &rsp;
|
||||
}
|
||||
|
||||
struct ipmi_intf ipmi_free_intf = {
|
||||
name: "free",
|
||||
desc: "FreeIPMI IPMI Interface",
|
||||
open: ipmi_free_open,
|
||||
close: ipmi_free_close,
|
||||
sendrecv: ipmi_free_send_cmd,
|
||||
target_addr: IPMI_BMC_SLAVE_ADDR,
|
||||
};
|
||||
|
||||
39
src/plugins/imb/Makefile.am
Normal file
39
src/plugins/imb/Makefile.am
Normal file
@@ -0,0 +1,39 @@
|
||||
# Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# Redistribution of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# Redistribution in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# Neither the name of Sun Microsystems, Inc. or the names of
|
||||
# contributors may be used to endorse or promote products derived
|
||||
# from this software without specific prior written permission.
|
||||
#
|
||||
# This software is provided "AS IS," without a warranty of any kind.
|
||||
# ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
||||
# INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
||||
# PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
||||
# SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
|
||||
# FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||
# OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
|
||||
# SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
|
||||
# OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
|
||||
# PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
|
||||
# LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
||||
# EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/include
|
||||
|
||||
EXTRA_LTLIBRARIES = libintf_imb.la
|
||||
noinst_LTLIBRARIES = @INTF_IMB_LIB@
|
||||
libintf_imb_la_LIBADD = $(top_builddir)/lib/libipmitool.la
|
||||
libintf_imb_la_SOURCES = imbapi.c imbapi.h imb.c
|
||||
|
||||
131
src/plugins/imb/imb.c
Normal file
131
src/plugins/imb/imb.c
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistribution of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistribution in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of Sun Microsystems, Inc. or the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* This software is provided "AS IS," without a warranty of any kind.
|
||||
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
||||
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
||||
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
|
||||
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
|
||||
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
|
||||
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
|
||||
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
|
||||
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
||||
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <ipmitool/ipmi.h>
|
||||
#include <ipmitool/ipmi_intf.h>
|
||||
#include <ipmitool/helper.h>
|
||||
|
||||
#include "imbapi.h"
|
||||
|
||||
#define IPMI_IMB_TIMEOUT (1000 * 1000)
|
||||
#define IPMI_IMB_MAX_RETRY 3
|
||||
#define IPMI_IMB_DEV "/dev/imb"
|
||||
#define IPMI_IMB_BUF_SIZE 64
|
||||
|
||||
extern int verbose;
|
||||
|
||||
static int ipmi_imb_open(struct ipmi_intf * intf)
|
||||
{
|
||||
struct stat stbuf;
|
||||
|
||||
if (stat(IPMI_IMB_DEV, &stbuf) < 0) {
|
||||
printf("Error: no IMB driver found at %s!\n", IPMI_IMB_DEV);
|
||||
return -1;
|
||||
}
|
||||
|
||||
intf->opened = 1;
|
||||
intf->manufacturer_id = ipmi_get_oem(intf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ipmi_imb_close(struct ipmi_intf * intf)
|
||||
{
|
||||
intf->opened = 0;
|
||||
intf->manufacturer_id = IPMI_OEM_UNKNOWN;
|
||||
}
|
||||
|
||||
static struct ipmi_rs * ipmi_imb_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
|
||||
{
|
||||
IMBPREQUESTDATA imbreq;
|
||||
static struct ipmi_rs rsp;
|
||||
int status, i;
|
||||
unsigned char ccode;
|
||||
|
||||
imbreq.rsSa = IPMI_BMC_SLAVE_ADDR;
|
||||
imbreq.rsLun = 0;
|
||||
imbreq.busType = 0;
|
||||
imbreq.netFn = req->msg.netfn;
|
||||
imbreq.cmdType = req->msg.cmd;
|
||||
|
||||
imbreq.data = req->msg.data;
|
||||
imbreq.dataLength = req->msg.data_len;
|
||||
|
||||
if (verbose > 1) {
|
||||
printf("IMB rsSa : %x\n", imbreq.rsSa);
|
||||
printf("IMB netFn : %x\n", imbreq.netFn);
|
||||
printf("IMB cmdType : %x\n", imbreq.cmdType);
|
||||
printf("IMB dataLength : %d\n", imbreq.dataLength);
|
||||
}
|
||||
|
||||
rsp.data_len = IPMI_IMB_BUF_SIZE;
|
||||
memset(rsp.data, 0, rsp.data_len);
|
||||
|
||||
for (i=0; i<IPMI_IMB_MAX_RETRY; i++) {
|
||||
if (verbose > 2)
|
||||
printbuf(imbreq.data, imbreq.dataLength, "ipmi_imb request");
|
||||
status = SendTimedImbpRequest(&imbreq, IPMI_IMB_TIMEOUT,
|
||||
rsp.data, &rsp.data_len, &ccode);
|
||||
if (status == 0) {
|
||||
if (verbose > 2)
|
||||
printbuf(rsp.data, rsp.data_len, "ipmi_imb response");
|
||||
break;
|
||||
}
|
||||
/* error */
|
||||
printf("Error sending IMB request, status=%x ccode=%x\n",
|
||||
status, ccode);
|
||||
}
|
||||
|
||||
rsp.ccode = ccode;
|
||||
|
||||
return &rsp;
|
||||
}
|
||||
|
||||
struct ipmi_intf ipmi_imb_intf = {
|
||||
name: "imb",
|
||||
desc: "Intel IMB Interface",
|
||||
open: ipmi_imb_open,
|
||||
close: ipmi_imb_close,
|
||||
sendrecv: ipmi_imb_send_cmd,
|
||||
target_addr: IPMI_BMC_SLAVE_ADDR,
|
||||
};
|
||||
|
||||
2090
src/plugins/imb/imbapi.c
Normal file
2090
src/plugins/imb/imbapi.c
Normal file
File diff suppressed because it is too large
Load Diff
652
src/plugins/imb/imbapi.h
Normal file
652
src/plugins/imb/imbapi.h
Normal file
@@ -0,0 +1,652 @@
|
||||
/*M*
|
||||
// PVCS:
|
||||
// $Workfile: imb_api.h $
|
||||
// $Revision: 1.2 $
|
||||
// $Modtime: Jul 22 2002 16:40:32 $
|
||||
// $Author: iceblink $
|
||||
//
|
||||
// Combined include files needed for imbapi.c
|
||||
//
|
||||
*M*/
|
||||
/*----------------------------------------------------------------------*
|
||||
The BSD License
|
||||
Copyright (c) 2002, Intel Corporation
|
||||
All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
a.. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
b.. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
c.. Neither the name of Intel Corporation nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*----------------------------------------------------------------------*/
|
||||
#ifndef _WINDEFS_H
|
||||
#define _WINDEFS_H
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
#ifndef WIN32
|
||||
/* WIN32 defines this in stdio.h */
|
||||
#ifndef _WCHAR_T
|
||||
#define _WCHAR_T
|
||||
typedef long wchar_t;
|
||||
#endif
|
||||
#endif
|
||||
#define far
|
||||
#define near
|
||||
#define FAR far
|
||||
#define NEAR near
|
||||
#ifndef CONST
|
||||
#define CONST const
|
||||
#endif
|
||||
typedef unsigned long DWORD;
|
||||
typedef int BOOL;
|
||||
typedef unsigned char BYTE;
|
||||
typedef unsigned short WORD;
|
||||
typedef float FLOAT;
|
||||
typedef FLOAT *PFLOAT;
|
||||
typedef BOOL near *PBOOL;
|
||||
typedef BOOL far *LPBOOL;
|
||||
typedef BYTE near *PBYTE;
|
||||
typedef BYTE far *LPBYTE;
|
||||
typedef int near *PINT;
|
||||
typedef int far *LPINT;
|
||||
typedef WORD near *PWORD;
|
||||
typedef WORD far *LPWORD;
|
||||
typedef long far *LPLONG;
|
||||
typedef DWORD near *PDWORD;
|
||||
typedef DWORD far *LPDWORD;
|
||||
typedef void far *LPVOID;
|
||||
typedef CONST void far *LPCVOID;
|
||||
typedef int INT;
|
||||
typedef unsigned int UINT;
|
||||
typedef unsigned int *PUINT;
|
||||
typedef DWORD NTSTATUS;
|
||||
/*
|
||||
File structures
|
||||
*/
|
||||
#ifndef WIN32
|
||||
typedef struct _OVERLAPPED {
|
||||
DWORD Internal;
|
||||
DWORD InternalHigh;
|
||||
DWORD Offset;
|
||||
DWORD OffsetHigh;
|
||||
/* HANDLE hEvent; */
|
||||
} OVERLAPPED, *LPOVERLAPPED;
|
||||
#endif
|
||||
/*
|
||||
* Data structure redefines
|
||||
*/
|
||||
typedef char CHAR;
|
||||
typedef short SHORT;
|
||||
typedef long LONG;
|
||||
typedef char * PCHAR;
|
||||
typedef short * PSHORT;
|
||||
typedef long * PLONG;
|
||||
typedef unsigned char UCHAR;
|
||||
typedef unsigned short USHORT;
|
||||
typedef unsigned long ULONG;
|
||||
typedef unsigned char * PUCHAR;
|
||||
typedef unsigned short * PUSHORT;
|
||||
typedef unsigned long * PULONG;
|
||||
typedef char CCHAR;
|
||||
typedef short CSHORT;
|
||||
typedef ULONG CLONG;
|
||||
typedef CCHAR * PCCHAR;
|
||||
typedef CSHORT * PCSHORT;
|
||||
typedef CLONG * PCLONG;
|
||||
typedef void * PVOID;
|
||||
#ifndef WIN32
|
||||
typedef void VOID;
|
||||
typedef struct _LARGE_INTEGER {
|
||||
ULONG LowPart;
|
||||
LONG HighPart;
|
||||
} LARGE_INTEGER;
|
||||
typedef struct _ULARGE_INTEGER {
|
||||
ULONG LowPart;
|
||||
ULONG HighPart;
|
||||
} ULARGE_INTEGER;
|
||||
#endif
|
||||
typedef LARGE_INTEGER * PLARGE_INTEGER;
|
||||
typedef LARGE_INTEGER PHYSICAL_ADDRESS;
|
||||
typedef LARGE_INTEGER * PPHYSICAL_ADDRESS;
|
||||
typedef ULARGE_INTEGER * PULARGE_INTEGER;
|
||||
typedef UCHAR BOOLEAN;
|
||||
typedef BOOLEAN *PBOOLEAN;
|
||||
typedef wchar_t WCHAR;
|
||||
typedef WCHAR *PWCHAR, *PWSTR;
|
||||
typedef CONST WCHAR *LPCWSTR, *PCWSTR;
|
||||
|
||||
#ifndef _SYS_TYPES_H
|
||||
#ifndef _CADDR_T
|
||||
#define _CADDR_T
|
||||
typedef char * caddr_t;
|
||||
#endif
|
||||
#endif
|
||||
/*
|
||||
Unicode strings are counted 16-bit character strings. If they are
|
||||
NULL terminated, Length does not include trailing NULL.
|
||||
*/
|
||||
typedef struct _UNICODE_STRING {
|
||||
USHORT Length;
|
||||
USHORT MaximumLength;
|
||||
PWSTR Buffer;
|
||||
} UNICODE_STRING;
|
||||
typedef UNICODE_STRING *PUNICODE_STRING;
|
||||
#define UNICODE_NULL ((WCHAR)0) /* winnt*/
|
||||
#define IN /* */
|
||||
#define OUT /* */
|
||||
#define OPTIONAL /* */
|
||||
|
||||
#ifndef WIN32
|
||||
#define FIELD_OFFSET(type, field) ((LONG)&(((type *)0)->field))
|
||||
#define UNREFERENCED_PARAMETER(x)
|
||||
typedef int HANDLE;
|
||||
#define INVALID_HANDLE_VALUE ((HANDLE)-1)
|
||||
#endif
|
||||
typedef HANDLE *PHANDLE;
|
||||
/*
|
||||
Define the method codes for how buffers are passed for I/O and FS controls
|
||||
*/
|
||||
#define METHOD_BUFFERED 0
|
||||
/*
|
||||
Define the access check value for any access
|
||||
The FILE_READ_ACCESS and FILE_WRITE_ACCESS constants are also defined in
|
||||
ntioapi.h as FILE_READ_DATA and FILE_WRITE_DATA. The values for these
|
||||
constants *MUST* always be in sync.
|
||||
*/
|
||||
#define FILE_ANY_ACCESS 0
|
||||
/*
|
||||
These are the generic rights.
|
||||
*/
|
||||
#define MAX_PATH 260
|
||||
#define GetLastError() (NTstatus.Status)
|
||||
/*
|
||||
Macro definition for defining IOCTL and FSCTL function control codes. Note
|
||||
that function codes 0-2047 are reserved for Microsoft Corporation, and
|
||||
2048-4095 are reserved for customers.
|
||||
*/
|
||||
/*
|
||||
* Linux drivers expect ioctls defined using macros defined in ioctl.h.
|
||||
* So, instead of using the CTL_CODE defined for NT and UW, I define CTL_CODE
|
||||
* using these macros. That way imb_if.h, where the ioctls are defined get
|
||||
* to use the correct ioctl command we expect.
|
||||
* Notes: I am using the generic _IO macro instead of the more specific
|
||||
* ones. The macros expect 8bit entities, so I am cleaning what is sent to
|
||||
* us from imb_if.h - Mahendra
|
||||
*/
|
||||
#ifndef WIN32
|
||||
#define CTL_CODE(DeviceType, Function, Method, Access)\
|
||||
_IO(DeviceType & 0x00FF, Function & 0x00FF)
|
||||
#else
|
||||
#define CTL_CODE( DeviceType, Function, Method, Access ) ((ULONG)( \
|
||||
((ULONG)(DeviceType) << 16) | ((ULONG)(Access) << 14) | ((ULONG)(Function) << 2) | ((ULONG)Method) \
|
||||
))
|
||||
#endif
|
||||
#endif /*_WINDEFS_H */
|
||||
/*----------------------------------------------------------------------*/
|
||||
#ifndef _SMI_H
|
||||
#define _SMI_H
|
||||
#define SMI_Version1_00 0x00001000
|
||||
struct smi {
|
||||
DWORD smi_VersionNo;
|
||||
DWORD smi_Reserved1;
|
||||
DWORD smi_Reserved2;
|
||||
LPVOID ntstatus; /* address of NT status block*/
|
||||
LPVOID lpvInBuffer; /* address of buffer for input data*/
|
||||
DWORD cbInBuffer; /* size of input buffer*/
|
||||
LPVOID lpvOutBuffer; /* address of output buffer*/
|
||||
DWORD cbOutBuffer; /* size of output buffer*/
|
||||
LPDWORD lpcbBytesReturned; /* address of actual bytes of output*/
|
||||
LPOVERLAPPED lpoOverlapped; /* address of overlapped structure*/
|
||||
};
|
||||
#ifndef STATUS_SUCCESS
|
||||
typedef struct _IO_STATUS_BLOCK {
|
||||
ULONG Status;
|
||||
ULONG Information;
|
||||
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
|
||||
/*
|
||||
* I2C ioctl's return NTStatus codes
|
||||
*/
|
||||
#define STATUS_SUCCESS (0x00000000U)
|
||||
#define STATUS_UNSUCCESSFUL (0xC0000001U)
|
||||
#define STATUS_DEVICE_BUSY (0x80000011U)
|
||||
#ifndef WIN32
|
||||
#define STATUS_PENDING (0x00000103U)
|
||||
// see <win2000ddk>\inc\winnt.h(1171)
|
||||
#endif
|
||||
#define STATUS_INVALID_PARAMETER (0xC000000DU)
|
||||
#define STATUS_INVALID_DEVICE_REQUEST (0xC0000010U)
|
||||
#define STATUS_BUFFER_TOO_SMALL (0xC0000023U)
|
||||
#define STATUS_FILE_CLOSED (0xC0000128U)
|
||||
#define STATUS_INSUFFICIENT_RESOURCES (0xC000009AU)
|
||||
#define STATUS_NO_DATA_DETECTED (0x80000022U)
|
||||
#define STATUS_NO_SUCH_DEVICE (0xC000000EU)
|
||||
#define STATUS_ALLOTTED_EXCEEDED (0xC000000FU)
|
||||
#define STATUS_IO_DEVICE_ERROR (0xC0000185U)
|
||||
#define STATUS_TOO_MANY_OPEN_FILES (0xC000011FU)
|
||||
#define STATUS_ACCESS_DENIED (0xC0000022U)
|
||||
#define STATUS_BUFFER_OVERFLOW (0x80000005U)
|
||||
#define STATUS_CANCELLED (0xC0000120U)
|
||||
#endif /* STATUS_SUCCESS*/
|
||||
#endif /* _SMI_H*/
|
||||
/*----------------------------------------------------------------------*/
|
||||
#ifndef IMB_IF__
|
||||
#define IMB_IF__
|
||||
/*
|
||||
* This is the structure passed in to the IOCTL_IMB_SHUTDOWN_CODE request
|
||||
*/
|
||||
typedef struct {
|
||||
int code;
|
||||
int delayTime;
|
||||
} ShutdownCmdBuffer;
|
||||
#define SD_NO_ACTION 0
|
||||
#define SD_RESET 1
|
||||
#define SD_POWER_OFF 2
|
||||
#pragma pack(1)
|
||||
/*
|
||||
* This is the generic IMB packet format, the final checksum cant be
|
||||
* represented in this structure and will show up as the last data byte
|
||||
*/
|
||||
typedef struct {
|
||||
BYTE rsSa;
|
||||
BYTE nfLn;
|
||||
BYTE cSum1;
|
||||
BYTE rqSa;
|
||||
BYTE seqLn;
|
||||
BYTE cmd;
|
||||
BYTE data[1];
|
||||
} ImbPacket;
|
||||
#define MIN_IMB_PACKET_SIZE 7
|
||||
#define MAX_IMB_PACKET_SIZE 33
|
||||
/*
|
||||
* This is the standard IMB response format where the first byte of
|
||||
* IMB packet data is interpreted as a command completion code.
|
||||
*/
|
||||
typedef struct {
|
||||
BYTE rsSa;
|
||||
BYTE nfLn;
|
||||
BYTE cSum1;
|
||||
BYTE rqSa;
|
||||
BYTE seqLn;
|
||||
BYTE cmd;
|
||||
BYTE cCode;
|
||||
BYTE data[1];
|
||||
} ImbRespPacket;
|
||||
#define MIN_IMB_RESPONSE_SIZE 7 /* min packet + completion code */
|
||||
#define MAX_IMB_RESPONSE_SIZE MAX_IMB_PACKET_SIZE
|
||||
/************************
|
||||
* ImbRequestBuffer
|
||||
************************/
|
||||
/*D*
|
||||
// Name: ImbRequestBuffer
|
||||
// Purpose: Structure definition for holding IMB message data
|
||||
// Context: Used by SendTimedImbpMessage and SendTimedI2cMessge
|
||||
// functions in the library interface. In use, it is overlayed on a
|
||||
// char buffer of size MIN_IMB_REQ_BUF_SIZE +
|
||||
// Fields:
|
||||
// respBufSize size of the response buffer
|
||||
//
|
||||
// timeout timeout value in milli seconds
|
||||
//
|
||||
// req body of request to send
|
||||
//
|
||||
*D*/
|
||||
typedef struct {
|
||||
BYTE rsSa;
|
||||
BYTE cmd;
|
||||
BYTE netFn;
|
||||
BYTE rsLun;
|
||||
BYTE dataLength;
|
||||
BYTE data[1];
|
||||
} ImbRequest;
|
||||
typedef struct {
|
||||
DWORD flags; /* request flags*/
|
||||
#define NO_RESPONSE_EXPECTED 0x01 /*dont wait around for an IMB response*/
|
||||
DWORD timeOut; /* in uSec units*/
|
||||
ImbRequest req; /* message buffer*/
|
||||
} ImbRequestBuffer;
|
||||
#define MIN_IMB_REQ_BUF_SIZE 13 /* a buffer without any request data*/
|
||||
/************************
|
||||
* ImbResponseBuffer
|
||||
************************/
|
||||
/*D*
|
||||
// Name: ImbResponseBuffer
|
||||
// Purpose: Structure definition for response of a previous send
|
||||
// Context: Used by DeviceIoControl to pass the message to be sent to
|
||||
// MISSMIC port
|
||||
// Fields:
|
||||
// cCode completion code returned by firmware
|
||||
// data buffer for response data from firmware
|
||||
*D*/
|
||||
typedef struct {
|
||||
BYTE cCode;
|
||||
BYTE data[1];
|
||||
} ImbResponseBuffer;
|
||||
#define MIN_IMB_RESP_BUF_SIZE 1
|
||||
#define MAX_IMB_RESP_SIZE (MIN_IMB_RESP_BUF_SIZE + MAX_IMB_RESPONSE_SIZE)
|
||||
#pragma pack()
|
||||
/*
|
||||
* Async message access structures and types
|
||||
*/
|
||||
typedef DWORD ImbAsyncSeq;
|
||||
/*
|
||||
* This is the structure passed in to IOCTL_IMB_GET_ASYNC_MSG
|
||||
*/
|
||||
typedef struct {
|
||||
DWORD timeOut;
|
||||
ImbAsyncSeq lastSeq;
|
||||
} ImbAsyncRequest;
|
||||
#define ASYNC_SEQ_START 0
|
||||
typedef struct {
|
||||
ImbAsyncSeq thisSeq;
|
||||
BYTE data[1];
|
||||
} ImbAsyncResponse;
|
||||
#define MIN_ASYNC_RESP_SIZE sizeof( ImbAsyncSeq )
|
||||
#define MAX_ASYNC_RESP_SIZE (MIN_ASYNC_RESP_SIZE + MAX_IMB_PACKET_SIZE)
|
||||
/*
|
||||
** Driver Ioctls
|
||||
** In Linux, these calculate to:
|
||||
** IOCTL_IMB_SEND_MESSAGE =1082
|
||||
** IOCTL_IMB_GET_ASYNC_MSG =1088
|
||||
** IOCTL_IMB_MAP_MEMORY =108e
|
||||
** IOCTL_IMB_UNMAP_MEMORY =1090
|
||||
** IOCTL_IMB_SHUTDOWN_CODE =1092
|
||||
** IOCTL_IMB_REGISTER_ASYNC_OBJ =1098
|
||||
** IOCTL_IMB_DEREGISTER_ASYNC_OBJ=109a
|
||||
** IOCTL_IMB_CHECK_EVENT =109c
|
||||
** IOCTL_IMB_POLL_ASYNC =1094
|
||||
*/
|
||||
#define FILE_DEVICE_IMB 0x00008010
|
||||
#define IOCTL_IMB_BASE 0x00000880
|
||||
#define IOCTL_IMB_SEND_MESSAGE CTL_CODE(FILE_DEVICE_IMB, (IOCTL_IMB_BASE + 2), METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_IMB_GET_ASYNC_MSG CTL_CODE(FILE_DEVICE_IMB, (IOCTL_IMB_BASE + 8), METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_IMB_MAP_MEMORY CTL_CODE(FILE_DEVICE_IMB, (IOCTL_IMB_BASE + 14), METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_IMB_UNMAP_MEMORY CTL_CODE(FILE_DEVICE_IMB, (IOCTL_IMB_BASE + 16), METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_IMB_SHUTDOWN_CODE CTL_CODE(FILE_DEVICE_IMB, (IOCTL_IMB_BASE + 18), METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_IMB_REGISTER_ASYNC_OBJ CTL_CODE(FILE_DEVICE_IMB, (IOCTL_IMB_BASE + 24), METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_IMB_DEREGISTER_ASYNC_OBJ CTL_CODE(FILE_DEVICE_IMB, (IOCTL_IMB_BASE + 26), METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_IMB_CHECK_EVENT CTL_CODE(FILE_DEVICE_IMB, (IOCTL_IMB_BASE + 28), METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_IMB_POLL_ASYNC CTL_CODE(FILE_DEVICE_IMB, (IOCTL_IMB_BASE + 20), METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#endif /* IMB_IF__ */
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* No asynchronous messages available */
|
||||
#define IMB_MSG_NOT_AVAILABLE ((NTSTATUS)0xE0070012L)
|
||||
#ifdef IMBLOG_H__
|
||||
/* Define the facility codes */
|
||||
#define FACILITY_RPC_STUBS 0x3
|
||||
#define FACILITY_RPC_RUNTIME 0x2
|
||||
#define FACILITY_IO_ERROR_CODE 0x4
|
||||
#define IMB_IO_ERROR_CODE 0x7
|
||||
|
||||
#define STATUS_SEVERITY_WARNING 0x2
|
||||
#define STATUS_SEVERITY_SUCCESS 0x0
|
||||
#define STATUS_SEVERITY_INFORMATIONAL 0x1
|
||||
#define STATUS_SEVERITY_ERROR 0x3
|
||||
/* Not enough memory for internal storage of device %1. */
|
||||
#define INSUFFICIENT_RESOURCES ((NTSTATUS)0xE0070001L)
|
||||
|
||||
#define INVALID_INPUT_BUFFER ((NTSTATUS)0xE0070002L)
|
||||
|
||||
#define INVALID_OUTPUT_BUFFER ((NTSTATUS)0xE0070003L)
|
||||
|
||||
#define IMB_SEND_TIMEOUT ((NTSTATUS)0xE0070004L)
|
||||
|
||||
#define IMB_RECEIVE_TIMEOUT ((NTSTATUS)0xE0070005L)
|
||||
|
||||
#define IMB_IF_SEND_TIMEOUT ((NTSTATUS)0xE0070006L)
|
||||
|
||||
#define IMB_IF_RECEIVE_TIMEOUT ((NTSTATUS)0xE0040007L)
|
||||
|
||||
#define HARDWARE_FAILURE ((NTSTATUS)0xE0040008L)
|
||||
|
||||
#define DRIVER_FAILURE ((NTSTATUS)0xE0040009L)
|
||||
|
||||
#define IMB_INVALID_IF_RESPONSE ((NTSTATUS)0xE004000AL)
|
||||
|
||||
#define IMB_INVALID_PACKET ((NTSTATUS)0xE004000BL)
|
||||
|
||||
#define IMB_RESPONSE_DATA_OVERFLOW ((NTSTATUS)0xE004000CL)
|
||||
|
||||
#define IMB_INVALID_REQUEST ((NTSTATUS)0xE007000DL)
|
||||
|
||||
#define INVALID_DRIVER_IOCTL ((NTSTATUS)0xE007000EL)
|
||||
|
||||
#define INVALID_DRIVER_REQUEST ((NTSTATUS)0xE007000FL)
|
||||
|
||||
#define IMB_CANT_GET_SMS_BUFFER ((NTSTATUS)0xE0070010L)
|
||||
|
||||
#define INPUT_BUFFER_TOO_SMALL ((NTSTATUS)0xE0070011L)
|
||||
|
||||
#define IMB_SEND_ERROR ((NTSTATUS)0xE0070013L)
|
||||
#endif /* IMBLOG_H__ */
|
||||
/*----------------------------------------------------------------------*/
|
||||
#ifndef IMBAPI_H__
|
||||
#define IMBAPI_H__
|
||||
#include <sys/types.h>
|
||||
#define WRITE_READ_I2C 0x52
|
||||
#define WRITE_EMP_BUFFER 0x7a
|
||||
#define GET_DEVICE_ID 0x1
|
||||
#define SEND_MESSAGE 0x34
|
||||
#define BMC_SA 0x20
|
||||
#define BMC_LUN 0
|
||||
#define APP_NETFN 0x06
|
||||
#define IPMI_09_VERSION 0x90
|
||||
#define IPMI_10_VERSION 0x01
|
||||
|
||||
#define IPMI_15_VERSION 0x51
|
||||
|
||||
#ifndef IPMI10_GET_DEVICE_ID_RESP_LENGTH
|
||||
#define IPMI10_GET_DEVICE_ID_RESP_LENGTH 12
|
||||
#endif
|
||||
|
||||
#define IPMB_CHANNEL 0x0
|
||||
#define EMP_CHANNEL 0x1
|
||||
#define LAN_CHANNEL 0x2
|
||||
#define RESERVED_LUN 0x3
|
||||
#define IPMB_LUN 0x2
|
||||
#define EMP_LUN 0x0
|
||||
|
||||
#define PUBLIC_BUS 0
|
||||
|
||||
#define BMC_CONTROLLER 0x20
|
||||
#define FPC_CONTROLLER 0x22
|
||||
typedef enum {
|
||||
ACCESN_OK,
|
||||
ACCESN_ERROR,
|
||||
ACCESN_OUT_OF_RANGE,
|
||||
ACCESN_END_OF_DATA,
|
||||
ACCESN_UNSUPPORTED,
|
||||
ACCESN_INVALID_TRANSACTION,
|
||||
ACCESN_TIMED_OUT
|
||||
} ACCESN_STATUS;
|
||||
#pragma pack(1)
|
||||
/*
|
||||
* Request structure provided to SendTimedImbpRequest()
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned char cmdType;
|
||||
unsigned char rsSa;
|
||||
unsigned char busType;
|
||||
unsigned char netFn;
|
||||
unsigned char rsLun;
|
||||
unsigned char * data;
|
||||
int dataLength;
|
||||
} IMBPREQUESTDATA;
|
||||
/*
|
||||
* Request structure provided to SendTimedI2cRequest()
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned char rsSa;
|
||||
unsigned char busType;
|
||||
unsigned char numberOfBytesToRead;
|
||||
unsigned char * data;
|
||||
int dataLength;
|
||||
} I2CREQUESTDATA;
|
||||
#pragma pack()
|
||||
/*#ifdef IMB_API
|
||||
*
|
||||
* This section is provided to be able to compile using imb_if.h
|
||||
*
|
||||
*
|
||||
* function return type. This is also defined in the local instrumentation
|
||||
* so we ifdef here to avoid conflict.
|
||||
*/
|
||||
#define METHOD_BUFFERED 0
|
||||
#define FILE_ANY_ACCESS 0
|
||||
/*
|
||||
* This is necessary to compile using memIf.h
|
||||
*/
|
||||
typedef enum _INTERFACE_TYPE
|
||||
{
|
||||
Internal,
|
||||
Isa,
|
||||
Eisa,
|
||||
MicroChannel,
|
||||
TurboChannel,
|
||||
MaximumInterfaceType
|
||||
} INTERFACE_TYPE, * PINTERFACE_TYPE;
|
||||
#ifdef WIN32
|
||||
/* From memIf.h */
|
||||
#pragma pack(1)
|
||||
typedef struct
|
||||
{
|
||||
INTERFACE_TYPE InterfaceType; // Isa, Eisa, etc....
|
||||
ULONG BusNumber; // Bus number
|
||||
PHYSICAL_ADDRESS BusAddress; // Bus-relative address
|
||||
ULONG AddressSpace; // 0 is memory, 1 is I/O
|
||||
ULONG Length; // Length of section to map
|
||||
} PHYSICAL_MEMORY_INFO, * PPHYSICAL_MEMORY_INFO;
|
||||
#pragma pack()
|
||||
#endif
|
||||
/*#else // not IMB_API */
|
||||
/*
|
||||
* These are defined in imb_if.h but are needed by users of the imbapi library
|
||||
*/
|
||||
#define ASYNC_SEQ_START 0
|
||||
/*
|
||||
* This is the generic IMB packet format, the final checksum cant be
|
||||
* represented in this structure and will show up as the last data byte
|
||||
*/
|
||||
/*
|
||||
#define MIN_IMB_PACKET_SIZE 7
|
||||
#define MAX_IMB_PACKET_SIZE 33
|
||||
*/
|
||||
#define MAX_BUFFER_SIZE 64
|
||||
/*#endif // IMB_API */
|
||||
/******************************
|
||||
* FUNCTION PROTOTYPES
|
||||
******************************/
|
||||
ACCESN_STATUS
|
||||
SendTimedImbpRequest (
|
||||
IMBPREQUESTDATA *reqPtr,
|
||||
int timeOut,
|
||||
BYTE * respDataPtr,
|
||||
int * respDataLen,
|
||||
BYTE * completionCode
|
||||
);
|
||||
ACCESN_STATUS
|
||||
SendTimedI2cRequest (
|
||||
I2CREQUESTDATA *reqPtr,
|
||||
int timeOut,
|
||||
BYTE * respDataPtr,
|
||||
int * respDataLen,
|
||||
BYTE * completionCode
|
||||
);
|
||||
ACCESN_STATUS
|
||||
SendAsyncImbpRequest (
|
||||
IMBPREQUESTDATA *reqPtr,
|
||||
BYTE * seqNo
|
||||
);
|
||||
ACCESN_STATUS
|
||||
GetAsyncImbpMessage (
|
||||
ImbPacket * msgPtr,
|
||||
DWORD * msgLen,
|
||||
DWORD timeOut,
|
||||
ImbAsyncSeq * seqNo,
|
||||
DWORD channelNumber
|
||||
);
|
||||
ACCESN_STATUS
|
||||
GetAsyncImbpMessage_Ex (
|
||||
ImbPacket * msgPtr,
|
||||
DWORD * msgLen,
|
||||
DWORD timeOut,
|
||||
ImbAsyncSeq * seqNo,
|
||||
DWORD channelNumber,
|
||||
BYTE * sessionHandle,
|
||||
BYTE * privilege
|
||||
);
|
||||
ACCESN_STATUS
|
||||
UnmapPhysicalMemory( int virtualAddress, int Length );
|
||||
ACCESN_STATUS
|
||||
StartAsyncMesgPoll(void);
|
||||
ACCESN_STATUS
|
||||
MapPhysicalMemory (
|
||||
int startAddress,
|
||||
int addressLength,
|
||||
int *virtualAddress
|
||||
);
|
||||
ACCESN_STATUS
|
||||
SetShutDownCode (
|
||||
int delayTime,
|
||||
int code
|
||||
);
|
||||
ACCESN_STATUS
|
||||
SendTimedEmpMessageResponse (
|
||||
ImbPacket * ptr,
|
||||
char *responseDataBuf,
|
||||
int responseDataLen,
|
||||
int timeOut
|
||||
);
|
||||
ACCESN_STATUS
|
||||
SendTimedEmpMessageResponse_Ex (
|
||||
ImbPacket * ptr,
|
||||
char *responseDataBuf,
|
||||
int responseDataLen,
|
||||
int timeOut,
|
||||
BYTE sessionHandle,
|
||||
BYTE channelNumber
|
||||
);
|
||||
ACCESN_STATUS
|
||||
SendTimedLanMessageResponse (
|
||||
ImbPacket * ptr,
|
||||
char *responseDataBuf,
|
||||
int responseDataLen,
|
||||
int timeOut
|
||||
);
|
||||
ACCESN_STATUS
|
||||
SendTimedLanMessageResponse_Ex (
|
||||
ImbPacket * ptr,
|
||||
char *responseDataBuf,
|
||||
int responseDataLen,
|
||||
int timeOut ,
|
||||
BYTE sessionHandle,
|
||||
BYTE channelNumber
|
||||
);
|
||||
ACCESN_STATUS
|
||||
IsAsyncMessageAvailable (unsigned int eventId );
|
||||
ACCESN_STATUS
|
||||
RegisterForImbAsyncMessageNotification (unsigned int *handleId);
|
||||
ACCESN_STATUS
|
||||
UnRegisterForImbAsyncMessageNotification (unsigned int handleId,int iFlag);
|
||||
BYTE GetIpmiVersion(void);
|
||||
#endif /* IMBAPI_H__ */
|
||||
499
src/plugins/ipmi_intf.c
Normal file
499
src/plugins/ipmi_intf.c
Normal file
@@ -0,0 +1,499 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistribution of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistribution in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of Sun Microsystems, Inc. or the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* This software is provided "AS IS," without a warranty of any kind.
|
||||
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
||||
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
||||
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
|
||||
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
|
||||
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
|
||||
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
|
||||
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
|
||||
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
||||
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#if defined(IPMI_INTF_LAN) || defined (IPMI_INTF_LANPLUS)
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <unistd.h>
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include <ipmitool/ipmi_intf.h>
|
||||
#include <ipmitool/ipmi.h>
|
||||
#include <ipmitool/ipmi_sdr.h>
|
||||
#include <ipmitool/log.h>
|
||||
|
||||
#ifdef IPMI_INTF_OPEN
|
||||
extern struct ipmi_intf ipmi_open_intf;
|
||||
#endif
|
||||
#ifdef IPMI_INTF_IMB
|
||||
extern struct ipmi_intf ipmi_imb_intf;
|
||||
#endif
|
||||
#ifdef IPMI_INTF_LIPMI
|
||||
extern struct ipmi_intf ipmi_lipmi_intf;
|
||||
#endif
|
||||
#ifdef IPMI_INTF_BMC
|
||||
extern struct ipmi_intf ipmi_bmc_intf;
|
||||
#endif
|
||||
#ifdef IPMI_INTF_LAN
|
||||
extern struct ipmi_intf ipmi_lan_intf;
|
||||
#endif
|
||||
#ifdef IPMI_INTF_LANPLUS
|
||||
extern struct ipmi_intf ipmi_lanplus_intf;
|
||||
#endif
|
||||
#ifdef IPMI_INTF_FREE
|
||||
extern struct ipmi_intf ipmi_free_intf;
|
||||
#endif
|
||||
#ifdef IPMI_INTF_SERIAL
|
||||
extern struct ipmi_intf ipmi_serial_term_intf;
|
||||
extern struct ipmi_intf ipmi_serial_bm_intf;
|
||||
#endif
|
||||
#ifdef IPMI_INTF_DUMMY
|
||||
extern struct ipmi_intf ipmi_dummy_intf;
|
||||
#endif
|
||||
|
||||
struct ipmi_intf * ipmi_intf_table[] = {
|
||||
#ifdef IPMI_INTF_OPEN
|
||||
&ipmi_open_intf,
|
||||
#endif
|
||||
#ifdef IPMI_INTF_IMB
|
||||
&ipmi_imb_intf,
|
||||
#endif
|
||||
#ifdef IPMI_INTF_LIPMI
|
||||
&ipmi_lipmi_intf,
|
||||
#endif
|
||||
#ifdef IPMI_INTF_BMC
|
||||
&ipmi_bmc_intf,
|
||||
#endif
|
||||
#ifdef IPMI_INTF_LAN
|
||||
&ipmi_lan_intf,
|
||||
#endif
|
||||
#ifdef IPMI_INTF_LANPLUS
|
||||
&ipmi_lanplus_intf,
|
||||
#endif
|
||||
#ifdef IPMI_INTF_FREE
|
||||
&ipmi_free_intf,
|
||||
#endif
|
||||
#ifdef IPMI_INTF_SERIAL
|
||||
&ipmi_serial_term_intf,
|
||||
&ipmi_serial_bm_intf,
|
||||
#endif
|
||||
#ifdef IPMI_INTF_DUMMY
|
||||
&ipmi_dummy_intf,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
/* ipmi_intf_print - Print list of interfaces
|
||||
*
|
||||
* no meaningful return code
|
||||
*/
|
||||
void ipmi_intf_print(struct ipmi_intf_support * intflist)
|
||||
{
|
||||
struct ipmi_intf ** intf;
|
||||
struct ipmi_intf_support * sup;
|
||||
int def = 1;
|
||||
int found;
|
||||
|
||||
lprintf(LOG_NOTICE, "Interfaces:");
|
||||
|
||||
for (intf = ipmi_intf_table; intf && *intf; intf++) {
|
||||
|
||||
if (intflist != NULL) {
|
||||
found = 0;
|
||||
for (sup=intflist; sup->name != NULL; sup++) {
|
||||
if (strncmp(sup->name, (*intf)->name, strlen(sup->name)) == 0 &&
|
||||
strncmp(sup->name, (*intf)->name, strlen((*intf)->name)) == 0 &&
|
||||
sup->supported == 1)
|
||||
found = 1;
|
||||
}
|
||||
if (found == 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
lprintf(LOG_NOTICE, "\t%-12s %s %s",
|
||||
(*intf)->name, (*intf)->desc,
|
||||
def ? "[default]" : "");
|
||||
def = 0;
|
||||
}
|
||||
lprintf(LOG_NOTICE, "");
|
||||
}
|
||||
|
||||
/* ipmi_intf_load - Load an interface from the interface table above
|
||||
* If no interface name is given return first entry
|
||||
*
|
||||
* @name: interface name to try and load
|
||||
*
|
||||
* returns pointer to inteface structure if found
|
||||
* returns NULL on error
|
||||
*/
|
||||
struct ipmi_intf * ipmi_intf_load(char * name)
|
||||
{
|
||||
struct ipmi_intf ** intf;
|
||||
struct ipmi_intf * i;
|
||||
|
||||
if (name == NULL) {
|
||||
i = ipmi_intf_table[0];
|
||||
if (i->setup != NULL && (i->setup(i) < 0)) {
|
||||
lprintf(LOG_ERR, "Unable to setup "
|
||||
"interface %s", name);
|
||||
return NULL;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
for (intf = ipmi_intf_table;
|
||||
((intf != NULL) && (*intf != NULL));
|
||||
intf++) {
|
||||
i = *intf;
|
||||
if (strncmp(name, i->name, strlen(name)) == 0) {
|
||||
if (i->setup != NULL && (i->setup(i) < 0)) {
|
||||
lprintf(LOG_ERR, "Unable to setup "
|
||||
"interface %s", name);
|
||||
return NULL;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
ipmi_intf_session_set_hostname(struct ipmi_intf * intf, char * hostname)
|
||||
{
|
||||
if (intf->session == NULL)
|
||||
return;
|
||||
|
||||
memset(intf->session->hostname, 0, 16);
|
||||
|
||||
if (hostname != NULL) {
|
||||
memcpy(intf->session->hostname, hostname,
|
||||
__min(strlen(hostname), 64));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ipmi_intf_session_set_username(struct ipmi_intf * intf, char * username)
|
||||
{
|
||||
if (intf->session == NULL)
|
||||
return;
|
||||
|
||||
memset(intf->session->username, 0, 17);
|
||||
|
||||
if (username == NULL)
|
||||
return;
|
||||
|
||||
memcpy(intf->session->username, username, __min(strlen(username), 16));
|
||||
}
|
||||
|
||||
void
|
||||
ipmi_intf_session_set_password(struct ipmi_intf * intf, char * password)
|
||||
{
|
||||
if (intf->session == NULL)
|
||||
return;
|
||||
|
||||
memset(intf->session->authcode, 0, IPMI_AUTHCODE_BUFFER_SIZE);
|
||||
|
||||
if (password == NULL) {
|
||||
intf->session->password = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
intf->session->password = 1;
|
||||
memcpy(intf->session->authcode, password,
|
||||
__min(strlen(password), IPMI_AUTHCODE_BUFFER_SIZE));
|
||||
}
|
||||
|
||||
void
|
||||
ipmi_intf_session_set_privlvl(struct ipmi_intf * intf, uint8_t level)
|
||||
{
|
||||
if (intf->session == NULL)
|
||||
return;
|
||||
|
||||
intf->session->privlvl = level;
|
||||
}
|
||||
|
||||
void
|
||||
ipmi_intf_session_set_lookupbit(struct ipmi_intf * intf, uint8_t lookupbit)
|
||||
{
|
||||
if (intf->session == NULL)
|
||||
return;
|
||||
|
||||
intf->session->v2_data.lookupbit = lookupbit;
|
||||
}
|
||||
|
||||
void
|
||||
ipmi_intf_session_set_cipher_suite_id(struct ipmi_intf * intf, uint8_t cipher_suite_id)
|
||||
{
|
||||
if (intf->session == NULL)
|
||||
return;
|
||||
|
||||
intf->session->cipher_suite_id = cipher_suite_id;
|
||||
}
|
||||
|
||||
void
|
||||
ipmi_intf_session_set_sol_escape_char(struct ipmi_intf * intf, char sol_escape_char)
|
||||
{
|
||||
if (intf->session == NULL)
|
||||
return;
|
||||
|
||||
intf->session->sol_escape_char = sol_escape_char;
|
||||
}
|
||||
|
||||
void
|
||||
ipmi_intf_session_set_kgkey(struct ipmi_intf * intf, char * kgkey)
|
||||
{
|
||||
if (intf->session == NULL)
|
||||
return;
|
||||
|
||||
memset(intf->session->v2_data.kg, 0, IPMI_KG_BUFFER_SIZE);
|
||||
|
||||
if (kgkey == NULL)
|
||||
return;
|
||||
|
||||
memcpy(intf->session->v2_data.kg, kgkey,
|
||||
__min(strlen(kgkey), IPMI_KG_BUFFER_SIZE));
|
||||
}
|
||||
|
||||
void
|
||||
ipmi_intf_session_set_port(struct ipmi_intf * intf, int port)
|
||||
{
|
||||
if (intf->session == NULL)
|
||||
return;
|
||||
|
||||
intf->session->port = port;
|
||||
}
|
||||
|
||||
void
|
||||
ipmi_intf_session_set_authtype(struct ipmi_intf * intf, uint8_t authtype)
|
||||
{
|
||||
if (intf->session == NULL)
|
||||
return;
|
||||
|
||||
/* clear password field if authtype NONE specified */
|
||||
if (authtype == IPMI_SESSION_AUTHTYPE_NONE) {
|
||||
memset(intf->session->authcode, 0, IPMI_AUTHCODE_BUFFER_SIZE);
|
||||
intf->session->password = 0;
|
||||
}
|
||||
|
||||
intf->session->authtype_set = authtype;
|
||||
}
|
||||
|
||||
void
|
||||
ipmi_intf_session_set_timeout(struct ipmi_intf * intf, uint32_t timeout)
|
||||
{
|
||||
if (intf->session == NULL)
|
||||
return;
|
||||
|
||||
intf->session->timeout = timeout;
|
||||
}
|
||||
|
||||
void
|
||||
ipmi_intf_session_set_retry(struct ipmi_intf * intf, int retry)
|
||||
{
|
||||
if (intf->session == NULL)
|
||||
return;
|
||||
|
||||
intf->session->retry = retry;
|
||||
}
|
||||
|
||||
void
|
||||
ipmi_cleanup(struct ipmi_intf * intf)
|
||||
{
|
||||
ipmi_sdr_list_empty(intf);
|
||||
}
|
||||
|
||||
#if defined(IPMI_INTF_LAN) || defined (IPMI_INTF_LANPLUS)
|
||||
int
|
||||
ipmi_intf_socket_connect(struct ipmi_intf * intf)
|
||||
{
|
||||
struct ipmi_session *session;
|
||||
|
||||
struct sockaddr_storage addr;
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *rp0 = NULL, *rp;
|
||||
char service[NI_MAXSERV];
|
||||
int rc;
|
||||
|
||||
if (!intf || intf->session == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
session = intf->session;
|
||||
|
||||
if (session->hostname == NULL || strlen((const char *)session->hostname) == 0) {
|
||||
lprintf(LOG_ERR, "No hostname specified!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* open port to BMC */
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
|
||||
sprintf(service, "%d", session->port);
|
||||
/* Obtain address(es) matching host/port */
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
|
||||
hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
|
||||
hints.ai_flags = 0; /* use AI_NUMERICSERV for no name resolution */
|
||||
hints.ai_protocol = IPPROTO_UDP; /* */
|
||||
|
||||
if (getaddrinfo(session->hostname, service, &hints, &rp0) != 0) {
|
||||
lprintf(LOG_ERR, "Address lookup for %s failed",
|
||||
session->hostname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* getaddrinfo() returns a list of address structures.
|
||||
* Try each address until we successfully connect(2).
|
||||
* If socket(2) (or connect(2)) fails, we (close the socket
|
||||
* and) try the next address.
|
||||
*/
|
||||
|
||||
session->ai_family = AF_UNSPEC;
|
||||
for (rp = rp0; rp != NULL; rp = rp->ai_next) {
|
||||
/* We are only interested in IPv4 and IPv6 */
|
||||
if ((rp->ai_family != AF_INET6) && (rp->ai_family != AF_INET)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
intf->fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
|
||||
if (intf->fd == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rp->ai_family == AF_INET) {
|
||||
if (connect(intf->fd, rp->ai_addr, rp->ai_addrlen) != -1) {
|
||||
memcpy(&session->addr, rp->ai_addr, rp->ai_addrlen);
|
||||
session->addrlen = rp->ai_addrlen;
|
||||
session->ai_family = rp->ai_family;
|
||||
break; /* Success */
|
||||
}
|
||||
} else if (rp->ai_family == AF_INET6) {
|
||||
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)rp->ai_addr;
|
||||
char hbuf[NI_MAXHOST];
|
||||
socklen_t len;
|
||||
|
||||
/* The scope was specified on the command line e.g. with -H FE80::219:99FF:FEA0:BD95%eth0 */
|
||||
if (addr6->sin6_scope_id != 0) {
|
||||
len = sizeof(struct sockaddr_in6);
|
||||
if (getnameinfo((struct sockaddr *)addr6, len, hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) == 0) {
|
||||
lprintf(LOG_DEBUG, "Trying address: %s scope=%d",
|
||||
hbuf,
|
||||
addr6->sin6_scope_id);
|
||||
}
|
||||
if (connect(intf->fd, rp->ai_addr, rp->ai_addrlen) != -1) {
|
||||
memcpy(&session->addr, rp->ai_addr, rp->ai_addrlen);
|
||||
session->addrlen = rp->ai_addrlen;
|
||||
session->ai_family = rp->ai_family;
|
||||
break; /* Success */
|
||||
}
|
||||
} else {
|
||||
/* No scope specified, try to get this from the list of interfaces */
|
||||
struct ifaddrs *ifaddrs = NULL;
|
||||
struct ifaddrs *ifa = NULL;
|
||||
|
||||
if (getifaddrs(&ifaddrs) < 0) {
|
||||
lprintf(LOG_ERR, "Interface address lookup for %s failed",
|
||||
session->hostname);
|
||||
break;
|
||||
}
|
||||
|
||||
for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
|
||||
if (ifa->ifa_addr == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ifa->ifa_addr->sa_family == AF_INET6) {
|
||||
struct sockaddr_in6 *tmp6 = (struct sockaddr_in6 *)ifa->ifa_addr;
|
||||
|
||||
/* Skip unwanted addresses */
|
||||
if (IN6_IS_ADDR_MULTICAST(&tmp6->sin6_addr)) {
|
||||
continue;
|
||||
}
|
||||
if (IN6_IS_ADDR_LOOPBACK(&tmp6->sin6_addr)) {
|
||||
continue;
|
||||
}
|
||||
len = sizeof(struct sockaddr_in6);
|
||||
if ( getnameinfo((struct sockaddr *)tmp6, len, hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) == 0) {
|
||||
lprintf(LOG_DEBUG, "Testing %s interface address: %s scope=%d",
|
||||
ifa->ifa_name != NULL ? ifa->ifa_name : "???",
|
||||
hbuf,
|
||||
tmp6->sin6_scope_id);
|
||||
}
|
||||
|
||||
if (tmp6->sin6_scope_id != 0) {
|
||||
addr6->sin6_scope_id = tmp6->sin6_scope_id;
|
||||
} else {
|
||||
/*
|
||||
* No scope information in interface address information
|
||||
* On some OS'es, getifaddrs() is returning out the 'kernel' representation
|
||||
* of scoped addresses which stores the scope in the 3rd and 4th
|
||||
* byte. See also this page:
|
||||
* http://www.freebsd.org/doc/en/books/developers-handbook/ipv6.html
|
||||
*/
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&tmp6->sin6_addr)
|
||||
&& (tmp6->sin6_addr.s6_addr16[1] != 0)) {
|
||||
addr6->sin6_scope_id = ntohs(tmp6->sin6_addr.s6_addr16[1]);
|
||||
}
|
||||
}
|
||||
|
||||
/* OK, now try to connect with the scope id from this interface address */
|
||||
if (addr6->sin6_scope_id != 0) {
|
||||
if (connect(intf->fd, rp->ai_addr, rp->ai_addrlen) != -1) {
|
||||
memcpy(&session->addr, rp->ai_addr, rp->ai_addrlen);
|
||||
session->addrlen = rp->ai_addrlen;
|
||||
session->ai_family = rp->ai_family;
|
||||
lprintf(LOG_DEBUG, "Successful connected on %s interface with scope id %d", ifa->ifa_name, tmp6->sin6_scope_id);
|
||||
break; /* Success */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
freeifaddrs(ifaddrs);
|
||||
}
|
||||
}
|
||||
if (session->ai_family != AF_UNSPEC) {
|
||||
break;
|
||||
}
|
||||
close(intf->fd);
|
||||
intf->fd = -1;
|
||||
}
|
||||
|
||||
/* No longer needed */
|
||||
freeaddrinfo(rp0);
|
||||
|
||||
return ((intf->fd != -1) ? 0 : -1);
|
||||
}
|
||||
#endif
|
||||
|
||||
39
src/plugins/lan/Makefile.am
Normal file
39
src/plugins/lan/Makefile.am
Normal file
@@ -0,0 +1,39 @@
|
||||
# Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# Redistribution of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# Redistribution in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# Neither the name of Sun Microsystems, Inc. or the names of
|
||||
# contributors may be used to endorse or promote products derived
|
||||
# from this software without specific prior written permission.
|
||||
#
|
||||
# This software is provided "AS IS," without a warranty of any kind.
|
||||
# ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
||||
# INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
||||
# PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
||||
# SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
|
||||
# FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||
# OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
|
||||
# SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
|
||||
# OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
|
||||
# PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
|
||||
# LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
||||
# EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/include
|
||||
|
||||
EXTRA_LTLIBRARIES = libintf_lan.la
|
||||
noinst_LTLIBRARIES = @INTF_LAN_LIB@
|
||||
libintf_lan_la_LIBADD = $(top_builddir)/lib/libipmitool.la
|
||||
libintf_lan_la_SOURCES = lan.c lan.h asf.h rmcp.h auth.c auth.h md5.c md5.h
|
||||
|
||||
75
src/plugins/lan/asf.h
Normal file
75
src/plugins/lan/asf.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistribution of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistribution in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of Sun Microsystems, Inc. or the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* This software is provided "AS IS," without a warranty of any kind.
|
||||
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
||||
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
||||
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
|
||||
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
|
||||
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
|
||||
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
|
||||
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
|
||||
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
||||
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
#ifndef IPMI_ASF_H
|
||||
#define IPMI_ASF_H
|
||||
|
||||
#include <ipmitool/helper.h>
|
||||
#include "lan.h"
|
||||
|
||||
#define ASF_RMCP_IANA 0x000011be
|
||||
|
||||
#define ASF_TYPE_PING 0x80
|
||||
#define ASF_TYPE_PONG 0x40
|
||||
|
||||
static const struct valstr asf_type_vals[] __attribute__((unused)) = {
|
||||
{ 0x10, "Reset" },
|
||||
{ 0x11, "Power-up" },
|
||||
{ 0x12, "Unconditional Power-down" },
|
||||
{ 0x13, "Power Cycle" },
|
||||
{ 0x40, "Presence Pong" },
|
||||
{ 0x41, "Capabilities Response" },
|
||||
{ 0x42, "System State Response" },
|
||||
{ 0x80, "Presence Ping" },
|
||||
{ 0x81, "Capabilities Request" },
|
||||
{ 0x82, "System State Request" },
|
||||
{ 0x00, NULL }
|
||||
};
|
||||
|
||||
/* ASF message header */
|
||||
#ifdef HAVE_PRAGMA_PACK
|
||||
#pragma pack(1)
|
||||
#endif
|
||||
struct asf_hdr {
|
||||
uint32_t iana;
|
||||
uint8_t type;
|
||||
uint8_t tag;
|
||||
uint8_t __reserved;
|
||||
uint8_t len;
|
||||
} ATTRIBUTE_PACKING;
|
||||
#ifdef HAVE_PRAGMA_PACK
|
||||
#pragma pack(0)
|
||||
#endif
|
||||
|
||||
int handle_asf(struct ipmi_intf * intf, uint8_t * data, int data_len);
|
||||
|
||||
#endif /* IPMI_ASF_H */
|
||||
220
src/plugins/lan/auth.c
Normal file
220
src/plugins/lan/auth.c
Normal file
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistribution of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistribution in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of Sun Microsystems, Inc. or the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* This software is provided "AS IS," without a warranty of any kind.
|
||||
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
||||
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
||||
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
|
||||
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
|
||||
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
|
||||
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
|
||||
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
|
||||
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
||||
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <ipmitool/helper.h>
|
||||
#include <ipmitool/bswap.h>
|
||||
#include <ipmitool/ipmi.h>
|
||||
#include <ipmitool/ipmi_intf.h>
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CRYPTO_MD2
|
||||
# include <openssl/md2.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CRYPTO_MD5
|
||||
# include <openssl/md5.h>
|
||||
#else
|
||||
# include "md5.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* multi-session authcode generation for MD5
|
||||
* H(password + session_id + msg + session_seq + password)
|
||||
*
|
||||
* Use OpenSSL implementation of MD5 algorithm if found
|
||||
*/
|
||||
uint8_t * ipmi_auth_md5(struct ipmi_session * s, uint8_t * data, int data_len)
|
||||
{
|
||||
#ifdef HAVE_CRYPTO_MD5
|
||||
MD5_CTX ctx;
|
||||
static uint8_t md[16];
|
||||
uint32_t temp;
|
||||
|
||||
#if WORDS_BIGENDIAN
|
||||
temp = BSWAP_32(s->in_seq);
|
||||
#else
|
||||
temp = s->in_seq;
|
||||
#endif
|
||||
memset(md, 0, 16);
|
||||
memset(&ctx, 0, sizeof(MD5_CTX));
|
||||
|
||||
MD5_Init(&ctx);
|
||||
MD5_Update(&ctx, (const uint8_t *)s->authcode, 16);
|
||||
MD5_Update(&ctx, (const uint8_t *)&s->session_id, 4);
|
||||
MD5_Update(&ctx, (const uint8_t *)data, data_len);
|
||||
MD5_Update(&ctx, (const uint8_t *)&temp, sizeof(uint32_t));
|
||||
MD5_Update(&ctx, (const uint8_t *)s->authcode, 16);
|
||||
MD5_Final(md, &ctx);
|
||||
|
||||
if (verbose > 3)
|
||||
printf(" MD5 AuthCode : %s\n", buf2str(md, 16));
|
||||
|
||||
return md;
|
||||
#else /*HAVE_CRYPTO_MD5*/
|
||||
md5_state_t state;
|
||||
static md5_byte_t digest[16];
|
||||
uint32_t temp;
|
||||
|
||||
memset(digest, 0, 16);
|
||||
memset(&state, 0, sizeof(md5_state_t));
|
||||
|
||||
md5_init(&state);
|
||||
|
||||
md5_append(&state, (const md5_byte_t *)s->authcode, 16);
|
||||
md5_append(&state, (const md5_byte_t *)&s->session_id, 4);
|
||||
md5_append(&state, (const md5_byte_t *)data, data_len);
|
||||
|
||||
#if WORDS_BIGENDIAN
|
||||
temp = BSWAP_32(s->in_seq);
|
||||
#else
|
||||
temp = s->in_seq;
|
||||
#endif
|
||||
md5_append(&state, (const md5_byte_t *)&temp, 4);
|
||||
md5_append(&state, (const md5_byte_t *)s->authcode, 16);
|
||||
|
||||
md5_finish(&state, digest);
|
||||
|
||||
if (verbose > 3)
|
||||
printf(" MD5 AuthCode : %s\n", buf2str(digest, 16));
|
||||
return digest;
|
||||
#endif /*HAVE_CRYPTO_MD5*/
|
||||
}
|
||||
|
||||
/*
|
||||
* multi-session authcode generation for MD2
|
||||
* H(password + session_id + msg + session_seq + password)
|
||||
*
|
||||
* Use OpenSSL implementation of MD2 algorithm if found.
|
||||
* This function is analogous to ipmi_auth_md5
|
||||
*/
|
||||
uint8_t * ipmi_auth_md2(struct ipmi_session * s, uint8_t * data, int data_len)
|
||||
{
|
||||
#ifdef HAVE_CRYPTO_MD2
|
||||
MD2_CTX ctx;
|
||||
static uint8_t md[16];
|
||||
uint32_t temp;
|
||||
|
||||
#if WORDS_BIGENDIAN
|
||||
temp = BSWAP_32(s->in_seq);
|
||||
#else
|
||||
temp = s->in_seq;
|
||||
#endif
|
||||
memset(md, 0, 16);
|
||||
memset(&ctx, 0, sizeof(MD2_CTX));
|
||||
|
||||
MD2_Init(&ctx);
|
||||
MD2_Update(&ctx, (const uint8_t *)s->authcode, 16);
|
||||
MD2_Update(&ctx, (const uint8_t *)&s->session_id, 4);
|
||||
MD2_Update(&ctx, (const uint8_t *)data, data_len);
|
||||
MD2_Update(&ctx, (const uint8_t *)&temp, sizeof(uint32_t));
|
||||
MD2_Update(&ctx, (const uint8_t *)s->authcode, 16);
|
||||
MD2_Final(md, &ctx);
|
||||
|
||||
if (verbose > 3)
|
||||
printf(" MD2 AuthCode : %s\n", buf2str(md, 16));
|
||||
|
||||
return md;
|
||||
#else /*HAVE_CRYPTO_MD2*/
|
||||
static uint8_t md[16];
|
||||
memset(md, 0, 16);
|
||||
printf("WARNING: No internal support for MD2! "
|
||||
"Please re-compile with OpenSSL.\n");
|
||||
return md;
|
||||
#endif /*HAVE_CRYPTO_MD2*/
|
||||
}
|
||||
|
||||
/* special authentication method */
|
||||
uint8_t * ipmi_auth_special(struct ipmi_session * s)
|
||||
{
|
||||
#ifdef HAVE_CRYPTO_MD5
|
||||
MD5_CTX ctx;
|
||||
static uint8_t md[16];
|
||||
uint8_t challenge[16];
|
||||
int i;
|
||||
|
||||
memset(challenge, 0, 16);
|
||||
memset(md, 0, 16);
|
||||
memset(&ctx, 0, sizeof(MD5_CTX));
|
||||
|
||||
MD5_Init(&ctx);
|
||||
MD5_Update(&ctx, (const uint8_t *)s->authcode, strlen((const char *)s->authcode));
|
||||
MD5_Final(md, &ctx);
|
||||
|
||||
for (i=0; i<16; i++)
|
||||
challenge[i] = s->challenge[i] ^ md[i];
|
||||
|
||||
memset(md, 0, 16);
|
||||
memset(&ctx, 0, sizeof(MD5_CTX));
|
||||
|
||||
MD5_Init(&ctx);
|
||||
MD5_Update(&ctx, (const uint8_t *)challenge, 16);
|
||||
MD5_Final(md, &ctx);
|
||||
|
||||
return md;
|
||||
#else /*HAVE_CRYPTO_MD5*/
|
||||
int i;
|
||||
md5_state_t state;
|
||||
static md5_byte_t digest[16];
|
||||
uint8_t challenge[16];
|
||||
|
||||
memset(challenge, 0, 16);
|
||||
memset(digest, 0, 16);
|
||||
memset(&state, 0, sizeof(md5_state_t));
|
||||
|
||||
md5_init(&state);
|
||||
md5_append(&state, (const md5_byte_t *)s->authcode, strlen(s->authcode));
|
||||
md5_finish(&state, digest);
|
||||
|
||||
for (i=0; i<16; i++)
|
||||
challenge[i] = s->challenge[i] ^ digest[i];
|
||||
|
||||
memset(digest, 0, 16);
|
||||
memset(&state, 0, sizeof(md5_state_t));
|
||||
|
||||
md5_init(&state);
|
||||
md5_append(&state, (const md5_byte_t *)challenge, 16);
|
||||
md5_finish(&state, digest);
|
||||
|
||||
return digest;
|
||||
#endif /*HAVE_CRYPTO_MD5*/
|
||||
}
|
||||
|
||||
40
src/plugins/lan/auth.h
Normal file
40
src/plugins/lan/auth.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistribution of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistribution in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of Sun Microsystems, Inc. or the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* This software is provided "AS IS," without a warranty of any kind.
|
||||
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
||||
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
||||
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
|
||||
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
|
||||
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
|
||||
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
|
||||
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
|
||||
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
||||
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
#ifndef IPMI_AUTH_H
|
||||
#define IPMI_AUTH_H
|
||||
|
||||
uint8_t * ipmi_auth_md2(struct ipmi_session * s, uint8_t * data, int data_len);
|
||||
uint8_t * ipmi_auth_md5(struct ipmi_session * s, uint8_t * data, int data_len);
|
||||
uint8_t * ipmi_auth_special(struct ipmi_session * s);
|
||||
|
||||
#endif /*IPMI_AUTH_H*/
|
||||
2071
src/plugins/lan/lan.c
Normal file
2071
src/plugins/lan/lan.c
Normal file
File diff suppressed because it is too large
Load Diff
41
src/plugins/lan/lan.h
Normal file
41
src/plugins/lan/lan.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistribution of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistribution in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of Sun Microsystems, Inc. or the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* This software is provided "AS IS," without a warranty of any kind.
|
||||
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
||||
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
||||
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
|
||||
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
|
||||
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
|
||||
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
|
||||
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
|
||||
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
||||
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
#ifndef IPMI_LAN_H
|
||||
#define IPMI_LAN_H
|
||||
|
||||
#include <ipmitool/ipmi.h>
|
||||
#include <ipmitool/ipmi_intf.h>
|
||||
|
||||
extern struct ipmi_intf ipmi_lan_intf;
|
||||
|
||||
#endif /*IPMI_LAN_H*/
|
||||
381
src/plugins/lan/md5.c
Normal file
381
src/plugins/lan/md5.c
Normal file
@@ -0,0 +1,381 @@
|
||||
/*
|
||||
Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
L. Peter Deutsch
|
||||
ghost@aladdin.com
|
||||
|
||||
*/
|
||||
/* $Id: md5.c,v 1.1 2003/11/18 17:56:02 iceblink Exp $ */
|
||||
/*
|
||||
Independent implementation of MD5 (RFC 1321).
|
||||
|
||||
This code implements the MD5 Algorithm defined in RFC 1321, whose
|
||||
text is available at
|
||||
http://www.ietf.org/rfc/rfc1321.txt
|
||||
The code is derived from the text of the RFC, including the test suite
|
||||
(section A.5) but excluding the rest of Appendix A. It does not include
|
||||
any code or documentation that is identified in the RFC as being
|
||||
copyrighted.
|
||||
|
||||
The original and principal author of md5.c is L. Peter Deutsch
|
||||
<ghost@aladdin.com>. Other authors are noted in the change history
|
||||
that follows (in reverse chronological order):
|
||||
|
||||
2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
|
||||
either statically or dynamically; added missing #include <string.h>
|
||||
in library.
|
||||
2002-03-11 lpd Corrected argument list for main(), and added int return
|
||||
type, in test program and T value program.
|
||||
2002-02-21 lpd Added missing #include <stdio.h> in test program.
|
||||
2000-07-03 lpd Patched to eliminate warnings about "constant is
|
||||
unsigned in ANSI C, signed in traditional"; made test program
|
||||
self-checking.
|
||||
1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
|
||||
1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
|
||||
1999-05-03 lpd Original version.
|
||||
*/
|
||||
|
||||
#include "md5.h"
|
||||
#include <string.h>
|
||||
|
||||
#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
|
||||
#ifdef ARCH_IS_BIG_ENDIAN
|
||||
# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
|
||||
#else
|
||||
# define BYTE_ORDER 0
|
||||
#endif
|
||||
|
||||
#define T_MASK ((md5_word_t)~0)
|
||||
#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
|
||||
#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
|
||||
#define T3 0x242070db
|
||||
#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
|
||||
#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
|
||||
#define T6 0x4787c62a
|
||||
#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
|
||||
#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
|
||||
#define T9 0x698098d8
|
||||
#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
|
||||
#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
|
||||
#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
|
||||
#define T13 0x6b901122
|
||||
#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
|
||||
#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
|
||||
#define T16 0x49b40821
|
||||
#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
|
||||
#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
|
||||
#define T19 0x265e5a51
|
||||
#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
|
||||
#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
|
||||
#define T22 0x02441453
|
||||
#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
|
||||
#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
|
||||
#define T25 0x21e1cde6
|
||||
#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
|
||||
#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
|
||||
#define T28 0x455a14ed
|
||||
#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
|
||||
#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
|
||||
#define T31 0x676f02d9
|
||||
#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
|
||||
#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
|
||||
#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
|
||||
#define T35 0x6d9d6122
|
||||
#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
|
||||
#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
|
||||
#define T38 0x4bdecfa9
|
||||
#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
|
||||
#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
|
||||
#define T41 0x289b7ec6
|
||||
#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
|
||||
#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
|
||||
#define T44 0x04881d05
|
||||
#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
|
||||
#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
|
||||
#define T47 0x1fa27cf8
|
||||
#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
|
||||
#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
|
||||
#define T50 0x432aff97
|
||||
#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
|
||||
#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
|
||||
#define T53 0x655b59c3
|
||||
#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
|
||||
#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
|
||||
#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
|
||||
#define T57 0x6fa87e4f
|
||||
#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
|
||||
#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
|
||||
#define T60 0x4e0811a1
|
||||
#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
|
||||
#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
|
||||
#define T63 0x2ad7d2bb
|
||||
#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
|
||||
|
||||
|
||||
static void
|
||||
md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
|
||||
{
|
||||
md5_word_t
|
||||
a = pms->abcd[0], b = pms->abcd[1],
|
||||
c = pms->abcd[2], d = pms->abcd[3];
|
||||
md5_word_t t;
|
||||
#if BYTE_ORDER > 0
|
||||
/* Define storage only for big-endian CPUs. */
|
||||
md5_word_t X[16];
|
||||
#else
|
||||
/* Define storage for little-endian or both types of CPUs. */
|
||||
md5_word_t xbuf[16];
|
||||
const md5_word_t *X;
|
||||
#endif
|
||||
|
||||
{
|
||||
#if BYTE_ORDER == 0
|
||||
/*
|
||||
* Determine dynamically whether this is a big-endian or
|
||||
* little-endian machine, since we can use a more efficient
|
||||
* algorithm on the latter.
|
||||
*/
|
||||
static const int w = 1;
|
||||
|
||||
if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
|
||||
#endif
|
||||
#if BYTE_ORDER <= 0 /* little-endian */
|
||||
{
|
||||
/*
|
||||
* On little-endian machines, we can process properly aligned
|
||||
* data without copying it.
|
||||
*/
|
||||
if (!((data - (const md5_byte_t *)0) & 3)) {
|
||||
/* data are properly aligned */
|
||||
X = (const md5_word_t *)data;
|
||||
} else {
|
||||
/* not aligned */
|
||||
memcpy(xbuf, data, 64);
|
||||
X = xbuf;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if BYTE_ORDER == 0
|
||||
else /* dynamic big-endian */
|
||||
#endif
|
||||
#if BYTE_ORDER >= 0 /* big-endian */
|
||||
{
|
||||
/*
|
||||
* On big-endian machines, we must arrange the bytes in the
|
||||
* right order.
|
||||
*/
|
||||
const md5_byte_t *xp = data;
|
||||
int i;
|
||||
|
||||
# if BYTE_ORDER == 0
|
||||
X = xbuf; /* (dynamic only) */
|
||||
# else
|
||||
# define xbuf X /* (static only) */
|
||||
# endif
|
||||
for (i = 0; i < 16; ++i, xp += 4)
|
||||
xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
|
||||
|
||||
/* Round 1. */
|
||||
/* Let [abcd k s i] denote the operation
|
||||
a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + F(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 0, 7, T1);
|
||||
SET(d, a, b, c, 1, 12, T2);
|
||||
SET(c, d, a, b, 2, 17, T3);
|
||||
SET(b, c, d, a, 3, 22, T4);
|
||||
SET(a, b, c, d, 4, 7, T5);
|
||||
SET(d, a, b, c, 5, 12, T6);
|
||||
SET(c, d, a, b, 6, 17, T7);
|
||||
SET(b, c, d, a, 7, 22, T8);
|
||||
SET(a, b, c, d, 8, 7, T9);
|
||||
SET(d, a, b, c, 9, 12, T10);
|
||||
SET(c, d, a, b, 10, 17, T11);
|
||||
SET(b, c, d, a, 11, 22, T12);
|
||||
SET(a, b, c, d, 12, 7, T13);
|
||||
SET(d, a, b, c, 13, 12, T14);
|
||||
SET(c, d, a, b, 14, 17, T15);
|
||||
SET(b, c, d, a, 15, 22, T16);
|
||||
#undef SET
|
||||
|
||||
/* Round 2. */
|
||||
/* Let [abcd k s i] denote the operation
|
||||
a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + G(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 1, 5, T17);
|
||||
SET(d, a, b, c, 6, 9, T18);
|
||||
SET(c, d, a, b, 11, 14, T19);
|
||||
SET(b, c, d, a, 0, 20, T20);
|
||||
SET(a, b, c, d, 5, 5, T21);
|
||||
SET(d, a, b, c, 10, 9, T22);
|
||||
SET(c, d, a, b, 15, 14, T23);
|
||||
SET(b, c, d, a, 4, 20, T24);
|
||||
SET(a, b, c, d, 9, 5, T25);
|
||||
SET(d, a, b, c, 14, 9, T26);
|
||||
SET(c, d, a, b, 3, 14, T27);
|
||||
SET(b, c, d, a, 8, 20, T28);
|
||||
SET(a, b, c, d, 13, 5, T29);
|
||||
SET(d, a, b, c, 2, 9, T30);
|
||||
SET(c, d, a, b, 7, 14, T31);
|
||||
SET(b, c, d, a, 12, 20, T32);
|
||||
#undef SET
|
||||
|
||||
/* Round 3. */
|
||||
/* Let [abcd k s t] denote the operation
|
||||
a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define H(x, y, z) ((x) ^ (y) ^ (z))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + H(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 5, 4, T33);
|
||||
SET(d, a, b, c, 8, 11, T34);
|
||||
SET(c, d, a, b, 11, 16, T35);
|
||||
SET(b, c, d, a, 14, 23, T36);
|
||||
SET(a, b, c, d, 1, 4, T37);
|
||||
SET(d, a, b, c, 4, 11, T38);
|
||||
SET(c, d, a, b, 7, 16, T39);
|
||||
SET(b, c, d, a, 10, 23, T40);
|
||||
SET(a, b, c, d, 13, 4, T41);
|
||||
SET(d, a, b, c, 0, 11, T42);
|
||||
SET(c, d, a, b, 3, 16, T43);
|
||||
SET(b, c, d, a, 6, 23, T44);
|
||||
SET(a, b, c, d, 9, 4, T45);
|
||||
SET(d, a, b, c, 12, 11, T46);
|
||||
SET(c, d, a, b, 15, 16, T47);
|
||||
SET(b, c, d, a, 2, 23, T48);
|
||||
#undef SET
|
||||
|
||||
/* Round 4. */
|
||||
/* Let [abcd k s t] denote the operation
|
||||
a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + I(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 0, 6, T49);
|
||||
SET(d, a, b, c, 7, 10, T50);
|
||||
SET(c, d, a, b, 14, 15, T51);
|
||||
SET(b, c, d, a, 5, 21, T52);
|
||||
SET(a, b, c, d, 12, 6, T53);
|
||||
SET(d, a, b, c, 3, 10, T54);
|
||||
SET(c, d, a, b, 10, 15, T55);
|
||||
SET(b, c, d, a, 1, 21, T56);
|
||||
SET(a, b, c, d, 8, 6, T57);
|
||||
SET(d, a, b, c, 15, 10, T58);
|
||||
SET(c, d, a, b, 6, 15, T59);
|
||||
SET(b, c, d, a, 13, 21, T60);
|
||||
SET(a, b, c, d, 4, 6, T61);
|
||||
SET(d, a, b, c, 11, 10, T62);
|
||||
SET(c, d, a, b, 2, 15, T63);
|
||||
SET(b, c, d, a, 9, 21, T64);
|
||||
#undef SET
|
||||
|
||||
/* Then perform the following additions. (That is increment each
|
||||
of the four registers by the value it had before this block
|
||||
was started.) */
|
||||
pms->abcd[0] += a;
|
||||
pms->abcd[1] += b;
|
||||
pms->abcd[2] += c;
|
||||
pms->abcd[3] += d;
|
||||
}
|
||||
|
||||
void
|
||||
md5_init(md5_state_t *pms)
|
||||
{
|
||||
pms->count[0] = pms->count[1] = 0;
|
||||
pms->abcd[0] = 0x67452301;
|
||||
pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
|
||||
pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
|
||||
pms->abcd[3] = 0x10325476;
|
||||
}
|
||||
|
||||
void
|
||||
md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
|
||||
{
|
||||
const md5_byte_t *p = data;
|
||||
int left = nbytes;
|
||||
int offset = (pms->count[0] >> 3) & 63;
|
||||
md5_word_t nbits = (md5_word_t)(nbytes << 3);
|
||||
|
||||
if (nbytes <= 0)
|
||||
return;
|
||||
|
||||
/* Update the message length. */
|
||||
pms->count[1] += nbytes >> 29;
|
||||
pms->count[0] += nbits;
|
||||
if (pms->count[0] < nbits)
|
||||
pms->count[1]++;
|
||||
|
||||
/* Process an initial partial block. */
|
||||
if (offset) {
|
||||
int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
|
||||
|
||||
memcpy(pms->buf + offset, p, copy);
|
||||
if (offset + copy < 64)
|
||||
return;
|
||||
p += copy;
|
||||
left -= copy;
|
||||
md5_process(pms, pms->buf);
|
||||
}
|
||||
|
||||
/* Process full blocks. */
|
||||
for (; left >= 64; p += 64, left -= 64)
|
||||
md5_process(pms, p);
|
||||
|
||||
/* Process a final partial block. */
|
||||
if (left)
|
||||
memcpy(pms->buf, p, left);
|
||||
}
|
||||
|
||||
void
|
||||
md5_finish(md5_state_t *pms, md5_byte_t digest[16])
|
||||
{
|
||||
static const md5_byte_t pad[64] = {
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
md5_byte_t data[8];
|
||||
int i;
|
||||
|
||||
/* Save the length before padding. */
|
||||
for (i = 0; i < 8; ++i)
|
||||
data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
|
||||
/* Pad to 56 bytes mod 64. */
|
||||
md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
|
||||
/* Append the length. */
|
||||
md5_append(pms, data, 8);
|
||||
for (i = 0; i < 16; ++i)
|
||||
digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
|
||||
}
|
||||
91
src/plugins/lan/md5.h
Normal file
91
src/plugins/lan/md5.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved.
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
L. Peter Deutsch
|
||||
ghost@aladdin.com
|
||||
|
||||
*/
|
||||
/* $Id: md5.h,v 1.1 2003/11/18 17:56:02 iceblink Exp $ */
|
||||
/*
|
||||
Independent implementation of MD5 (RFC 1321).
|
||||
|
||||
This code implements the MD5 Algorithm defined in RFC 1321, whose
|
||||
text is available at
|
||||
http://www.ietf.org/rfc/rfc1321.txt
|
||||
The code is derived from the text of the RFC, including the test suite
|
||||
(section A.5) but excluding the rest of Appendix A. It does not include
|
||||
any code or documentation that is identified in the RFC as being
|
||||
copyrighted.
|
||||
|
||||
The original and principal author of md5.h is L. Peter Deutsch
|
||||
<ghost@aladdin.com>. Other authors are noted in the change history
|
||||
that follows (in reverse chronological order):
|
||||
|
||||
2002-04-13 lpd Removed support for non-ANSI compilers; removed
|
||||
references to Ghostscript; clarified derivation from RFC 1321;
|
||||
now handles byte order either statically or dynamically.
|
||||
1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
|
||||
1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
|
||||
added conditionalization for C++ compilation from Martin
|
||||
Purschke <purschke@bnl.gov>.
|
||||
1999-05-03 lpd Original version.
|
||||
*/
|
||||
|
||||
#ifndef md5_INCLUDED
|
||||
# define md5_INCLUDED
|
||||
|
||||
/*
|
||||
* This package supports both compile-time and run-time determination of CPU
|
||||
* byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
|
||||
* compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
|
||||
* defined as non-zero, the code will be compiled to run only on big-endian
|
||||
* CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
|
||||
* run on either big- or little-endian CPUs, but will run slightly less
|
||||
* efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
|
||||
*/
|
||||
|
||||
typedef unsigned char md5_byte_t; /* 8-bit byte */
|
||||
typedef unsigned int md5_word_t; /* 32-bit word */
|
||||
|
||||
/* Define the state of the MD5 Algorithm. */
|
||||
typedef struct md5_state_s {
|
||||
md5_word_t count[2]; /* message length in bits, lsw first */
|
||||
md5_word_t abcd[4]; /* digest buffer */
|
||||
md5_byte_t buf[64]; /* accumulate block */
|
||||
} md5_state_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/* Initialize the algorithm. */
|
||||
void md5_init(md5_state_t *pms);
|
||||
|
||||
/* Append a string to the message. */
|
||||
void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
|
||||
|
||||
/* Finish the message and return the digest. */
|
||||
void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* md5_INCLUDED */
|
||||
99
src/plugins/lan/rmcp.h
Normal file
99
src/plugins/lan/rmcp.h
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistribution of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistribution in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of Sun Microsystems, Inc. or the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* This software is provided "AS IS," without a warranty of any kind.
|
||||
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
||||
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
||||
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
|
||||
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
|
||||
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
|
||||
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
|
||||
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
|
||||
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
||||
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
#ifndef IPMI_RMCP_H
|
||||
#define IPMI_RMCP_H
|
||||
|
||||
#include <ipmitool/helper.h>
|
||||
#include "lan.h"
|
||||
#include "asf.h"
|
||||
|
||||
#define RMCP_VERSION_1 0x06
|
||||
|
||||
#define RMCP_UDP_PORT 0x26f /* port 623 */
|
||||
#define RMCP_UDP_SECURE_PORT 0x298 /* port 664 */
|
||||
|
||||
#define RMCP_TYPE_MASK 0x80
|
||||
#define RMCP_TYPE_NORM 0x00
|
||||
#define RMCP_TYPE_ACK 0x01
|
||||
|
||||
static const struct valstr rmcp_type_vals[] __attribute__((unused)) = {
|
||||
{ RMCP_TYPE_NORM, "Normal RMCP" },
|
||||
{ RMCP_TYPE_ACK, "RMCP ACK" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
#define RMCP_CLASS_MASK 0x1f
|
||||
#define RMCP_CLASS_ASF 0x06
|
||||
#define RMCP_CLASS_IPMI 0x07
|
||||
#define RMCP_CLASS_OEM 0x08
|
||||
|
||||
static const struct valstr rmcp_class_vals[] __attribute__((unused)) = {
|
||||
{ RMCP_CLASS_ASF, "ASF" },
|
||||
{ RMCP_CLASS_IPMI, "IPMI" },
|
||||
{ RMCP_CLASS_OEM, "OEM" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
#ifdef HAVE_PRAGMA_PACK
|
||||
#pragma pack(1)
|
||||
#endif
|
||||
/* RMCP message header */
|
||||
struct rmcp_hdr {
|
||||
uint8_t ver;
|
||||
uint8_t __reserved;
|
||||
uint8_t seq;
|
||||
uint8_t class;
|
||||
} ATTRIBUTE_PACKING;
|
||||
#ifdef HAVE_PRAGMA_PACK
|
||||
#pragma pack(0)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PRAGMA_PACK
|
||||
#pragma pack(1)
|
||||
#endif
|
||||
struct rmcp_pong {
|
||||
struct rmcp_hdr rmcp;
|
||||
struct asf_hdr asf;
|
||||
uint32_t iana;
|
||||
uint32_t oem;
|
||||
uint8_t sup_entities;
|
||||
uint8_t sup_interact;
|
||||
uint8_t reserved[6];
|
||||
} ATTRIBUTE_PACKING;
|
||||
#ifdef HAVE_PRAGMA_PACK
|
||||
#pragma pack(0)
|
||||
#endif
|
||||
|
||||
int handle_rmcp(struct ipmi_intf * intf, uint8_t * data, int data_len);
|
||||
|
||||
#endif /* IPMI_RMCP_H */
|
||||
45
src/plugins/lanplus/Makefile.am
Normal file
45
src/plugins/lanplus/Makefile.am
Normal file
@@ -0,0 +1,45 @@
|
||||
# Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# Redistribution of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# Redistribution in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# Neither the name of Sun Microsystems, Inc. or the names of
|
||||
# contributors may be used to endorse or promote products derived
|
||||
# from this software without specific prior written permission.
|
||||
#
|
||||
# This software is provided "AS IS," without a warranty of any kind.
|
||||
# ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
||||
# INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
||||
# PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
||||
# SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
|
||||
# FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||
# OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
|
||||
# SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
|
||||
# OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
|
||||
# PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
|
||||
# LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
||||
# EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/include
|
||||
|
||||
EXTRA_LTLIBRARIES = libintf_lanplus.la
|
||||
noinst_LTLIBRARIES = @INTF_LANPLUS_LIB@
|
||||
libintf_lanplus_la_LIBADD = $(top_builddir)/lib/libipmitool.la
|
||||
libintf_lanplus_la_SOURCES = \
|
||||
rmcp.h asf.h \
|
||||
lanplus.c lanplus.h \
|
||||
lanplus_strings.c \
|
||||
lanplus_crypt.c lanplus_crypt.h \
|
||||
lanplus_dump.h lanplus_dump.c \
|
||||
lanplus_crypt_impl.h lanplus_crypt_impl.c
|
||||
|
||||
74
src/plugins/lanplus/README.lanplus
Normal file
74
src/plugins/lanplus/README.lanplus
Normal file
@@ -0,0 +1,74 @@
|
||||
This interface exists to provide a means of connecting to an IPMIv2 enabled
|
||||
BMC. In some places, the IPMIv2 specification is either unclear or
|
||||
inconsistent, and interpretations of the intent of the specification had to
|
||||
be made at the discretion of the implementor. The purpose of this
|
||||
document is to make those decisions clear so that 1) they can be reviewed
|
||||
by others and 2) so that the rationale for those decisions can be made
|
||||
clear.
|
||||
|
||||
* Though it's not stated explicitly with which algorithm the K1 and K2 keys
|
||||
should be generated, we chose to use the authentication algorithm. The
|
||||
specification states that K1 and K2 are generated with an HMAC algorithm,
|
||||
and all of the authentication algorithms (except for "none") are HMAC
|
||||
algorithms, whereas the integrity algorithms are not all HMAC. See section
|
||||
13.32 for details about K1 and K2, and section
|
||||
|
||||
|
||||
* The IPMIv2 specification describes a key, Kg, that is the "BMC key".
|
||||
This key functions as a global key that is required to be known in addition
|
||||
to the user's key, by authenticating users. If the BMC has a null Kg, the
|
||||
users key, Kuid, is used in its place in algorithms where Kg is required,
|
||||
per the specification section 13.33. A user can obtain the status of Kg by
|
||||
querying the BMC with the Get Channel Authentication Capabilities command.
|
||||
Currently, this implementation does not provide a way for a user to specify
|
||||
Kg for BMCs that require it.
|
||||
|
||||
|
||||
* The specification is unclear as to which key is used for HMAC based
|
||||
integrity checking. One the one hand, section 13.28.4 states explicitly
|
||||
that HMAC integrity algorithms use the session integrity key as the HMAC
|
||||
key. Confusing that matter is a statement in section 13.32 regarding the
|
||||
creation of additional keying material. In this section it is stated that
|
||||
"all keying material for the RSP integrity and confidentiality algorithms
|
||||
will be generated by processing a pre-defined set of constants using HMAC
|
||||
per [RFC2104], keyed by sik". And "For the mandatory-to-implement
|
||||
integrity and confidentiality algorithms defined in this specification,
|
||||
processing the first two (2) constants will generate the require amount of
|
||||
keying material." We decided to use K1 as our HMAC key for the generation
|
||||
of authentication codes (integrity checking). Furthermore, we are using
|
||||
all 20 bytes of K1.
|
||||
|
||||
|
||||
* IPMIv2 compliant BMCs are supposed to support 20 byte passwords, as well
|
||||
store metadata describing whether the password was stored as a 16 byte or
|
||||
20 byte class password. We do not currently support 20 byte passwords. It
|
||||
should be noted that there are obvious mistakes in the SET USER PASSWORD
|
||||
command specification, as it mentions the ability to query for 16/20 byte
|
||||
password status, but the packet format does not support this.
|
||||
|
||||
|
||||
* The IPMIv2 specification describes a type of login called a "role only
|
||||
login." This feature allows a user to login providing only a requested
|
||||
privilege level and a password. We do not currently support this feature.
|
||||
Supporting this feature would only require the ability to specify
|
||||
username/privilege lookups in the RAKP 1 message sent from ipmitool. We
|
||||
currently specify the use of username only lookups for authentication.
|
||||
|
||||
|
||||
* In the IPMIv2 packet description in table 13-8 of the IPMv2
|
||||
specification, there are two fields that are rather ambiguous in meaning.
|
||||
The fields are "Pad Length" and "Next Header". Although neither field is
|
||||
listed as belonging to the IPMIv2 packet format, we include/expect them
|
||||
both in our IPMIv2 packets. Are rationale is 1) the Next Headers field's
|
||||
comment states what the value of that field should be for IPMIv2, and 2)
|
||||
for the most part the ASF and IPMIv2 fields seem to parallel each other,
|
||||
and we feel that the Pad Length and Next Header fields were left out of the
|
||||
IPMIv2 column by mistake.
|
||||
|
||||
|
||||
* The GET CHANNEL CIPHER SUITES command documentation seems to have
|
||||
mistakes. The "start of record" byte is stated to be either 0x30 or 0x31,
|
||||
whereas the detailed description in table 22-18 leads us to believe that
|
||||
this byte should really be 0xC0 or 0xC1. Also the description of bits 5:0
|
||||
in the start of record byte should probably be 00_0000 rather than 00_000.
|
||||
|
||||
76
src/plugins/lanplus/README.sol
Normal file
76
src/plugins/lanplus/README.sol
Normal file
@@ -0,0 +1,76 @@
|
||||
This document was last updated for release 1.8.8.
|
||||
|
||||
This document explains how Serial Over Lan is implemented on in the
|
||||
ipmitool IPMI client. Obviously, the code itself is authoritative, but
|
||||
this document should serve as a good starting point.
|
||||
|
||||
Serial Over Lan (SOL) is defined in the IPMI v2 specification published by
|
||||
Intel and available at http://www.intel.com/design/servers/ipmi/. SOL
|
||||
functionality is built on top of the RMCP+ protocol as an additional
|
||||
payload type (type 1).
|
||||
|
||||
The high end SOL logic is implemented in src/ipmitool/lib/ipmi_sol.c. SOL
|
||||
sessions are begun in ipmitool using the "sol activate" command. This
|
||||
command maps directly to the IPMI Activate Payload command. It first
|
||||
verifies that an RMCP+ session (lanplus interface) is being used to
|
||||
establish the session. Although the spec allows for a SOL connection to be
|
||||
established on a port different than the RMCP+ port that the "activate
|
||||
payload" command issued, ipmitool does not support this.
|
||||
|
||||
Once a session has been established (the activate payload command
|
||||
succeeds), ipmitool simply loops over a select() on user input and data
|
||||
returned from the BMC. All user input is first filtered so that special
|
||||
escape sequences can suspend or deactivate the SOL session and so that data
|
||||
can be broken into chunks no greater than N bytes. This maximum is
|
||||
specified by the BMC in the response to the Activate Payload command.
|
||||
|
||||
User input to the BMC is handled in ipmitool/src/plugins/lanplus/lanplus.c.
|
||||
Every SOL packet (with one exception) traveling in either direction causes
|
||||
the recipient to return an acknowledgement packet, though acks themself are
|
||||
not acknowledged. The transport layer in lanplus.c handles the logic
|
||||
regarding acks, partial acks, sequence numbers. SOL acknowledgements
|
||||
packets be acks, partial acks (the remote destination processed only some
|
||||
of the data), and nacks (requests to stop sending packets). Nacks are not
|
||||
honored by ipmitool.
|
||||
|
||||
Note that one way that SOL communication differs from standard IPMI
|
||||
commands, is that it is not simply a request response protocol. Packets
|
||||
may be returned asyncrhonously from the BMC. When establishing a SOL
|
||||
session, ipmitool registers a callback for asynchonously received data.
|
||||
This call back simply prints text returned from the BMC.
|
||||
|
||||
Once a user has chosen to exit the SOL session (with ~.) ipmitool sends the
|
||||
IPMI SOL Deactivate command to the BMC.
|
||||
|
||||
The standard code path for SOL logic follows:
|
||||
ipmi_sol_main (ipmi_sol.c):
|
||||
|
||||
ipmi_sol_activate (ipmi_sol.c):
|
||||
Argument validation
|
||||
Creation and dispatch of IPMI Activate Payload command
|
||||
|
||||
ipmi_sol_red_pill (ipmi_sol.c):
|
||||
Loop on select() for user input and data returned from the BMC
|
||||
Periodic dispatch of "keep alive" packet to the BMC.
|
||||
Send user input to the BMC and BMC data to the console.
|
||||
|
||||
processSolUserInput (ipmi_sol.c):
|
||||
Process possible escape sequences (~., ~B, etc.)
|
||||
Send (with retries) user data to the BMC
|
||||
Partial creation of packet payload
|
||||
|
||||
ipmi_lanplus_send_sol (lanplus.c):
|
||||
Completion of packet payload
|
||||
Send (with retries) of SOL packet
|
||||
|
||||
ipmi_lanplus_send_payload (lanplus.c):
|
||||
Creation of RMCP+ packet
|
||||
Details general to all V2 packet processing, as
|
||||
well as a some logic to handle ack reception.
|
||||
|
||||
is_sol_partial_ack (lanplus.c):
|
||||
Determine whether a data needs to be resent
|
||||
|
||||
ipmi_lanplus_recv_sol (lanplus.c):
|
||||
Handle data received by the BMC. Ack as appropriate.
|
||||
|
||||
75
src/plugins/lanplus/asf.h
Normal file
75
src/plugins/lanplus/asf.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistribution of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistribution in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of Sun Microsystems, Inc. or the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* This software is provided "AS IS," without a warranty of any kind.
|
||||
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
||||
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
||||
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
|
||||
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
|
||||
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
|
||||
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
|
||||
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
|
||||
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
||||
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
#ifndef IPMI_ASF_H
|
||||
#define IPMI_ASF_H
|
||||
|
||||
#include <ipmitool/helper.h>
|
||||
#include "lanplus.h"
|
||||
|
||||
#define ASF_RMCP_IANA 0x000011be
|
||||
|
||||
#define ASF_TYPE_PING 0x80
|
||||
#define ASF_TYPE_PONG 0x40
|
||||
|
||||
static const struct valstr asf_type_vals[] __attribute__((unused)) = {
|
||||
{ 0x10, "Reset" },
|
||||
{ 0x11, "Power-up" },
|
||||
{ 0x12, "Unconditional Power-down" },
|
||||
{ 0x13, "Power Cycle" },
|
||||
{ 0x40, "Presence Pong" },
|
||||
{ 0x41, "Capabilities Response" },
|
||||
{ 0x42, "System State Response" },
|
||||
{ 0x80, "Presence Ping" },
|
||||
{ 0x81, "Capabilities Request" },
|
||||
{ 0x82, "System State Request" },
|
||||
{ 0x00, NULL }
|
||||
};
|
||||
|
||||
/* ASF message header */
|
||||
#ifdef HAVE_PRAGMA_PACK
|
||||
#pragma pack(1)
|
||||
#endif
|
||||
struct asf_hdr {
|
||||
uint32_t iana;
|
||||
uint8_t type;
|
||||
uint8_t tag;
|
||||
uint8_t __reserved;
|
||||
uint8_t len;
|
||||
} ATTRIBUTE_PACKING;
|
||||
#ifdef HAVE_PRAGMA_PACK
|
||||
#pragma pack(0)
|
||||
#endif
|
||||
|
||||
int handle_asf(struct ipmi_intf * intf, uint8_t * data, int data_len);
|
||||
|
||||
#endif /* IPMI_ASF_H */
|
||||
3599
src/plugins/lanplus/lanplus.c
Normal file
3599
src/plugins/lanplus/lanplus.c
Normal file
File diff suppressed because it is too large
Load Diff
126
src/plugins/lanplus/lanplus.h
Normal file
126
src/plugins/lanplus/lanplus.h
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistribution of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistribution in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of Sun Microsystems, Inc. or the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* This software is provided "AS IS," without a warranty of any kind.
|
||||
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
||||
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
||||
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
|
||||
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
|
||||
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
|
||||
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
|
||||
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
|
||||
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
||||
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
#ifndef IPMI_LANPLUS_H
|
||||
#define IPMI_LANPLUS_H
|
||||
|
||||
#include <ipmitool/ipmi.h>
|
||||
|
||||
#define IPMI_LANPLUS_PORT 0x26f
|
||||
|
||||
/*
|
||||
* RAKP return codes. These values come from table 13-15 of the IPMI v2
|
||||
* specification.
|
||||
*/
|
||||
#define IPMI_RAKP_STATUS_NO_ERRORS 0x00
|
||||
#define IPMI_RAKP_STATUS_INSUFFICIENT_RESOURCES_FOR_SESSION 0x01
|
||||
#define IPMI_RAKP_STATUS_INVALID_SESSION_ID 0x02
|
||||
#define IPMI_RAKP_STATUS_INVALID_PAYLOAD_TYPE 0x03
|
||||
#define IPMI_RAKP_STATUS_INVALID_AUTHENTICATION_ALGORITHM 0x04
|
||||
#define IPMI_RAKP_STATUS_INVALID_INTEGRITTY_ALGORITHM 0x05
|
||||
#define IPMI_RAKP_STATUS_NO_MATCHING_AUTHENTICATION_PAYLOAD 0x06
|
||||
#define IPMI_RAKP_STATUS_NO_MATCHING_INTEGRITY_PAYLOAD 0x07
|
||||
#define IPMI_RAKP_STATUS_INACTIVE_SESSION_ID 0x08
|
||||
#define IPMI_RAKP_STATUS_INVALID_ROLE 0x09
|
||||
#define IPMI_RAKP_STATUS_UNAUTHORIZED_ROLE_REQUESTED 0x0A
|
||||
#define IPMI_RAKP_STATUS_INSUFFICIENT_RESOURCES_FOR_ROLE 0x0B
|
||||
#define IPMI_RAKP_STATUS_INVALID_NAME_LENGTH 0x0C
|
||||
#define IPMI_RAKP_STATUS_UNAUTHORIZED_NAME 0x0D
|
||||
#define IPMI_RAKP_STATUS_UNAUTHORIZED_GUID 0x0E
|
||||
#define IPMI_RAKP_STATUS_INVALID_INTEGRITY_CHECK_VALUE 0x0F
|
||||
#define IPMI_RAKP_STATUS_INVALID_CONFIDENTIALITY_ALGORITHM 0x10
|
||||
#define IPMI_RAKP_STATUS_NO_CIPHER_SUITE_MATCH 0x11
|
||||
#define IPMI_RAKP_STATUS_ILLEGAL_PARAMTER 0x12
|
||||
|
||||
|
||||
#define IPMI_LAN_CHANNEL_1 0x07
|
||||
#define IPMI_LAN_CHANNEL_2 0x06
|
||||
#define IPMI_LAN_CHANNEL_E 0x0e
|
||||
|
||||
#define IPMI_LAN_TIMEOUT 1
|
||||
#define IPMI_LAN_RETRY 4
|
||||
|
||||
#define IPMI_PRIV_CALLBACK 1
|
||||
#define IPMI_PRIV_USER 2
|
||||
#define IPMI_PRIV_OPERATOR 3
|
||||
#define IPMI_PRIV_ADMIN 4
|
||||
#define IPMI_PRIV_OEM 5
|
||||
|
||||
|
||||
#define IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE 0x10
|
||||
|
||||
|
||||
/* Session message offsets, from table 13-8 of the v2 specification */
|
||||
#define IPMI_LANPLUS_OFFSET_AUTHTYPE 0x04
|
||||
#define IPMI_LANPLUS_OFFSET_PAYLOAD_TYPE 0x05
|
||||
#define IPMI_LANPLUS_OFFSET_SESSION_ID 0x06
|
||||
#define IPMI_LANPLUS_OFFSET_SEQUENCE_NUM 0x0A
|
||||
#define IPMI_LANPLUS_OFFSET_PAYLOAD_SIZE 0x0E
|
||||
#define IPMI_LANPLUS_OFFSET_PAYLOAD 0x10
|
||||
|
||||
|
||||
#define IPMI_GET_CHANNEL_AUTH_CAP 0x38
|
||||
|
||||
/*
|
||||
* TODO: these are wild guesses and should be checked
|
||||
*/
|
||||
#define IPMI_MAX_CONF_HEADER_SIZE 0x20
|
||||
#define IPMI_MAX_PAYLOAD_SIZE 0xFFFF /* Includes confidentiality header/trailer */
|
||||
#define IPMI_MAX_CONF_TRAILER_SIZE 0x20
|
||||
#define IPMI_MAX_INTEGRITY_PAD_SIZE 0x20
|
||||
#define IPMI_MAX_AUTH_CODE_SIZE 0x20
|
||||
|
||||
#define IPMI_REQUEST_MESSAGE_SIZE 0x07
|
||||
#define IPMI_MAX_MAC_SIZE 0x14 /* The largest mac we ever expect to generate */
|
||||
#define IPMI_SHA1_AUTHCODE_SIZE 0x0C
|
||||
|
||||
/*
|
||||
*This is accurate, as long as we're only passing 1 auth algorithm,
|
||||
* one integrity algorithm, and 1 encyrption alogrithm
|
||||
*/
|
||||
#define IPMI_OPEN_SESSION_REQUEST_SIZE 32
|
||||
#define IPMI_RAKP1_MESSAGE_SIZE 44
|
||||
#define IPMI_RAKP3_MESSAGE_MAX_SIZE 28
|
||||
|
||||
#define IPMI_MAX_USER_NAME_LENGTH 16
|
||||
|
||||
extern const struct valstr ipmi_privlvl_vals[];
|
||||
extern const struct valstr ipmi_authtype_vals[];
|
||||
|
||||
extern struct ipmi_intf ipmi_lanplus_intf;
|
||||
|
||||
struct ipmi_rs * ipmi_lan_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req);
|
||||
int ipmi_lanplus_open(struct ipmi_intf * intf);
|
||||
void ipmi_lanplus_close(struct ipmi_intf * intf);
|
||||
int ipmiv2_lan_ping(struct ipmi_intf * intf);
|
||||
|
||||
#endif /*IPMI_LAN_H*/
|
||||
934
src/plugins/lanplus/lanplus_crypt.c
Normal file
934
src/plugins/lanplus/lanplus_crypt.c
Normal file
@@ -0,0 +1,934 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistribution of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistribution in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of Sun Microsystems, Inc. or the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* This software is provided "AS IS," without a warranty of any kind.
|
||||
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
||||
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
||||
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
|
||||
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
|
||||
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
|
||||
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
|
||||
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
|
||||
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
||||
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
# include <config.h>
|
||||
#endif
|
||||
#include <ipmitool/bswap.h>
|
||||
#include <ipmitool/log.h>
|
||||
#include "lanplus.h"
|
||||
#include "lanplus_crypt.h"
|
||||
#include "lanplus_crypt_impl.h"
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* lanplus_rakp2_hmac_matches
|
||||
*
|
||||
* param session holds all the state data that we need to generate the hmac
|
||||
* param hmac is the HMAC sent by the BMC in the RAKP 2 message
|
||||
*
|
||||
* The HMAC was generated [per RFC2404] from :
|
||||
*
|
||||
* SIDm - Remote console session ID
|
||||
* SIDc - BMC session ID
|
||||
* Rm - Remote console random number
|
||||
* Rc - BMC random number
|
||||
* GUIDc - BMC guid
|
||||
* ROLEm - Requested privilege level (entire byte)
|
||||
* ULENGTHm - Username length
|
||||
* <UNAMEm> - Username (absent for null user names)
|
||||
*
|
||||
* generated by using Kuid. I am aware that the subscripts on the values
|
||||
* look backwards, but that's the way they are written in the specification.
|
||||
*
|
||||
* If the authentication algorithm is IPMI_AUTH_RAKP_NONE, we return success.
|
||||
*
|
||||
* return 0 on success (the authcode matches)
|
||||
* 1 on failure (the authcode does not match)
|
||||
*/
|
||||
int
|
||||
lanplus_rakp2_hmac_matches(const struct ipmi_session * session,
|
||||
const uint8_t * bmc_mac, struct ipmi_intf * intf)
|
||||
{
|
||||
uint8_t * buffer;
|
||||
int bufferLength, i;
|
||||
uint8_t mac[20];
|
||||
uint32_t macLength;
|
||||
|
||||
uint32_t SIDm_lsbf, SIDc_lsbf;
|
||||
|
||||
|
||||
if (session->v2_data.auth_alg == IPMI_AUTH_RAKP_NONE)
|
||||
return 1;
|
||||
|
||||
/* We don't yet support other algorithms */
|
||||
assert(session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA1);
|
||||
|
||||
|
||||
bufferLength =
|
||||
4 + /* SIDm */
|
||||
4 + /* SIDc */
|
||||
16 + /* Rm */
|
||||
16 + /* Rc */
|
||||
16 + /* GUIDc */
|
||||
1 + /* ROLEm */
|
||||
1 + /* ULENGTHm */
|
||||
strlen((const char *)session->username); /* optional */
|
||||
|
||||
buffer = malloc(bufferLength);
|
||||
if (buffer == NULL) {
|
||||
lprintf(LOG_ERR, "ipmitool: malloc failure");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill the buffer. I'm assuming that we're using the LSBF representation of the
|
||||
* multibyte numbers in use.
|
||||
*/
|
||||
|
||||
/* SIDm */
|
||||
SIDm_lsbf = session->v2_data.console_id;
|
||||
#if WORDS_BIGENDIAN
|
||||
SIDm_lsbf = BSWAP_32(SIDm_lsbf);
|
||||
#endif
|
||||
|
||||
memcpy(buffer, &SIDm_lsbf, 4);
|
||||
|
||||
/* SIDc */
|
||||
SIDc_lsbf = session->v2_data.bmc_id;
|
||||
#if WORDS_BIGENDIAN
|
||||
SIDc_lsbf = BSWAP_32(SIDc_lsbf);
|
||||
#endif
|
||||
memcpy(buffer + 4, &SIDc_lsbf, 4);
|
||||
|
||||
/* Rm */
|
||||
#if WORDS_BIGENDIAN
|
||||
for (i = 0; i < 16; ++i)
|
||||
buffer[8 + i] = session->v2_data.console_rand[16 - 1 - i];
|
||||
#else
|
||||
for (i = 0; i < 16; ++i)
|
||||
buffer[8 + i] = session->v2_data.console_rand[i];
|
||||
#endif
|
||||
|
||||
/* Rc */
|
||||
#if WORDS_BIGENDIAN
|
||||
for (i = 0; i < 16; ++i)
|
||||
buffer[24 + i] = session->v2_data.bmc_rand[16 - 1 - i];
|
||||
#else
|
||||
for (i = 0; i < 16; ++i)
|
||||
buffer[24 + i] = session->v2_data.bmc_rand[i];
|
||||
#endif
|
||||
|
||||
/* GUIDc */
|
||||
#if WORDS_BIGENDIAN
|
||||
for (i = 0; i < 16; ++i)
|
||||
buffer[40 + i] = session->v2_data.bmc_guid[16 - 1 - i];
|
||||
#else
|
||||
for (i = 0; i < 16; ++i)
|
||||
buffer[40 + i] = session->v2_data.bmc_guid[i];
|
||||
#endif
|
||||
|
||||
/* ROLEm */
|
||||
buffer[56] = session->v2_data.requested_role;
|
||||
|
||||
if (ipmi_oem_active(intf, "i82571spt")) {
|
||||
/*
|
||||
* The HMAC calculation code in the Intel 82571 GbE
|
||||
* skips this bit! Looks like a GbE bug, but we need
|
||||
* to work around it here anyway...
|
||||
*/
|
||||
buffer[56] &= ~0x10;
|
||||
}
|
||||
|
||||
/* ULENGTHm */
|
||||
buffer[57] = strlen((const char *)session->username);
|
||||
|
||||
/* UserName [optional] */
|
||||
for (i = 0; i < buffer[57]; ++i)
|
||||
buffer[58 + i] = session->username[i];
|
||||
|
||||
if (verbose > 2)
|
||||
{
|
||||
printbuf((const uint8_t *)buffer, bufferLength, ">> rakp2 mac input buffer");
|
||||
printbuf((const uint8_t *)session->authcode, IPMI_AUTHCODE_BUFFER_SIZE, ">> rakp2 mac key");
|
||||
}
|
||||
|
||||
/*
|
||||
* The buffer is complete. Let's hash.
|
||||
*/
|
||||
lanplus_HMAC(session->v2_data.auth_alg,
|
||||
session->authcode,
|
||||
IPMI_AUTHCODE_BUFFER_SIZE,
|
||||
buffer,
|
||||
bufferLength,
|
||||
mac,
|
||||
&macLength);
|
||||
|
||||
free(buffer);
|
||||
buffer = NULL;
|
||||
|
||||
|
||||
if (verbose > 2)
|
||||
{
|
||||
printbuf(mac, macLength, ">> rakp2 mac as computed by the remote console");
|
||||
}
|
||||
|
||||
return (memcmp(bmc_mac, mac, macLength) == 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* lanplus_rakp4_hmac_matches
|
||||
*
|
||||
* param session holds all the state data that we need to generate the hmac
|
||||
* param hmac is the HMAC sent by the BMC in the RAKP 4 message
|
||||
*
|
||||
* The HMAC was generated [per RFC2404] from :
|
||||
*
|
||||
* Rm - Remote console random number
|
||||
* SIDc - BMC session ID
|
||||
* GUIDc - BMC guid
|
||||
*
|
||||
* generated by using SIK (the session integrity key). I am aware that the
|
||||
* subscripts on the values look backwards, but that's the way they are
|
||||
* written in the specification.
|
||||
*
|
||||
* If the authentication algorithm is IPMI_AUTH_RAKP_NONE, we return success.
|
||||
*
|
||||
* return 1 on success (the authcode matches)
|
||||
* 0 on failure (the authcode does not match)
|
||||
*
|
||||
*/
|
||||
int
|
||||
lanplus_rakp4_hmac_matches(const struct ipmi_session * session,
|
||||
const uint8_t * bmc_mac, struct ipmi_intf * intf)
|
||||
{
|
||||
uint8_t * buffer;
|
||||
int bufferLength, i;
|
||||
uint8_t mac[20];
|
||||
uint32_t macLength;
|
||||
uint32_t SIDc_lsbf;
|
||||
|
||||
if (ipmi_oem_active(intf, "intelplus")){
|
||||
/* Intel BMC responds with the integrity Algorithm in RAKP4 */
|
||||
if (session->v2_data.integrity_alg == IPMI_INTEGRITY_NONE)
|
||||
return 1;
|
||||
|
||||
/* We don't yet support other algorithms */
|
||||
assert(session->v2_data.integrity_alg == IPMI_INTEGRITY_HMAC_SHA1_96);
|
||||
} else {
|
||||
if (session->v2_data.auth_alg == IPMI_AUTH_RAKP_NONE)
|
||||
return 1;
|
||||
|
||||
/* We don't yet support other algorithms */
|
||||
assert(session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA1);
|
||||
}
|
||||
|
||||
bufferLength =
|
||||
16 + /* Rm */
|
||||
4 + /* SIDc */
|
||||
16; /* GUIDc */
|
||||
|
||||
buffer = (uint8_t *)malloc(bufferLength);
|
||||
if (buffer == NULL) {
|
||||
lprintf(LOG_ERR, "ipmitool: malloc failure");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill the buffer. I'm assuming that we're using the LSBF representation of the
|
||||
* multibyte numbers in use.
|
||||
*/
|
||||
|
||||
/* Rm */
|
||||
#if WORDS_BIGENDIAN
|
||||
for (i = 0; i < 16; ++i)
|
||||
buffer[i] = session->v2_data.console_rand[16 - 1 - i];
|
||||
#else
|
||||
for (i = 0; i < 16; ++i)
|
||||
buffer[i] = session->v2_data.console_rand[i];
|
||||
#endif
|
||||
|
||||
|
||||
/* SIDc */
|
||||
SIDc_lsbf = session->v2_data.bmc_id;
|
||||
#if WORDS_BIGENDIAN
|
||||
SIDc_lsbf = BSWAP_32(SIDc_lsbf);
|
||||
#endif
|
||||
memcpy(buffer + 16, &SIDc_lsbf, 4);
|
||||
|
||||
|
||||
/* GUIDc */
|
||||
#if WORDS_BIGENDIAN
|
||||
for (i = 0; i < 16; ++i)
|
||||
buffer[i + 20] = session->v2_data.bmc_guid[16 - 1 - i];
|
||||
#else
|
||||
for (i = 0; i < 16; ++i)
|
||||
buffer[i + 20] = session->v2_data.bmc_guid[i];
|
||||
#endif
|
||||
|
||||
|
||||
if (verbose > 2)
|
||||
{
|
||||
printbuf((const uint8_t *)buffer, bufferLength, ">> rakp4 mac input buffer");
|
||||
printbuf(session->v2_data.sik, 20l, ">> rakp4 mac key (sik)");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The buffer is complete. Let's hash.
|
||||
*/
|
||||
lanplus_HMAC((ipmi_oem_active(intf, "intelplus"))
|
||||
? session->v2_data.integrity_alg
|
||||
: session->v2_data.auth_alg ,
|
||||
session->v2_data.sik,
|
||||
IPMI_SIK_BUFFER_SIZE,
|
||||
buffer,
|
||||
bufferLength,
|
||||
mac,
|
||||
&macLength);
|
||||
|
||||
if (verbose > 2)
|
||||
{
|
||||
printbuf(bmc_mac, macLength, ">> rakp4 mac as computed by the BMC");
|
||||
printbuf(mac, macLength, ">> rakp4 mac as computed by the remote console");
|
||||
}
|
||||
|
||||
|
||||
|
||||
free(buffer);
|
||||
buffer = NULL;
|
||||
assert(macLength == 20);
|
||||
return (memcmp(bmc_mac, mac, 12) == 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* lanplus_generate_rakp3_auth_code
|
||||
*
|
||||
* This auth code is an HMAC generated with :
|
||||
*
|
||||
* Rc - BMC random number
|
||||
* SIDm - Console session ID
|
||||
* ROLEm - Requested privilege level (entire byte)
|
||||
* ULENGTHm - Username length
|
||||
* <USERNAME> - Usename (absent for null usernames)
|
||||
*
|
||||
* The key used to generated the MAC is Kuid
|
||||
*
|
||||
* I am aware that the subscripts look backwards, but that is the way they are
|
||||
* written in the spec.
|
||||
*
|
||||
* param output_buffer [out] will hold the generated MAC
|
||||
* param session [in] holds all the state data we need to generate the auth code
|
||||
* param mac_length [out] will be set to the length of the auth code
|
||||
*
|
||||
* returns 0 on success
|
||||
* 1 on failure
|
||||
*/
|
||||
int
|
||||
lanplus_generate_rakp3_authcode(uint8_t * output_buffer,
|
||||
const struct ipmi_session * session,
|
||||
uint32_t * mac_length, struct ipmi_intf * intf)
|
||||
{
|
||||
int ret = 0;
|
||||
int input_buffer_length, i;
|
||||
uint8_t * input_buffer;
|
||||
uint32_t SIDm_lsbf;
|
||||
|
||||
|
||||
if (session->v2_data.auth_alg == IPMI_AUTH_RAKP_NONE)
|
||||
{
|
||||
*mac_length = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We don't yet support other algorithms */
|
||||
assert(session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA1);
|
||||
|
||||
input_buffer_length =
|
||||
16 + /* Rc */
|
||||
4 + /* SIDm */
|
||||
1 + /* ROLEm */
|
||||
1 + /* ULENGTHm */
|
||||
strlen((const char *)session->username);
|
||||
|
||||
input_buffer = malloc(input_buffer_length);
|
||||
if (input_buffer == NULL) {
|
||||
lprintf(LOG_ERR, "ipmitool: malloc failure");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill the buffer. I'm assuming that we're using the LSBF representation of the
|
||||
* multibyte numbers in use.
|
||||
*/
|
||||
|
||||
/* Rc */
|
||||
#if WORDS_BIGENDIAN
|
||||
for (i = 0; i < 16; ++i)
|
||||
input_buffer[i] = session->v2_data.bmc_rand[16 - 1 - i];
|
||||
#else
|
||||
for (i = 0; i < 16; ++i)
|
||||
input_buffer[i] = session->v2_data.bmc_rand[i];
|
||||
#endif
|
||||
|
||||
/* SIDm */
|
||||
SIDm_lsbf = session->v2_data.console_id;
|
||||
#if WORDS_BIGENDIAN
|
||||
SIDm_lsbf = BSWAP_32(SIDm_lsbf);
|
||||
#endif
|
||||
memcpy(input_buffer + 16, &SIDm_lsbf, 4);
|
||||
|
||||
/* ROLEm */
|
||||
if (ipmi_oem_active(intf, "intelplus") || ipmi_oem_active(intf, "i82571spt"))
|
||||
input_buffer[20] = session->privlvl;
|
||||
else
|
||||
input_buffer[20] = session->v2_data.requested_role;
|
||||
|
||||
/* ULENGTHm */
|
||||
input_buffer[21] = strlen((const char *)session->username);
|
||||
|
||||
/* USERNAME */
|
||||
for (i = 0; i < input_buffer[21]; ++i)
|
||||
input_buffer[22 + i] = session->username[i];
|
||||
|
||||
if (verbose > 2)
|
||||
{
|
||||
printbuf((const uint8_t *)input_buffer, input_buffer_length, ">> rakp3 mac input buffer");
|
||||
printbuf((const uint8_t *)session->authcode, IPMI_AUTHCODE_BUFFER_SIZE, ">> rakp3 mac key");
|
||||
}
|
||||
|
||||
lanplus_HMAC(session->v2_data.auth_alg,
|
||||
session->authcode,
|
||||
IPMI_AUTHCODE_BUFFER_SIZE,
|
||||
input_buffer,
|
||||
input_buffer_length,
|
||||
output_buffer,
|
||||
mac_length);
|
||||
|
||||
if (verbose > 2)
|
||||
printbuf((const uint8_t *)output_buffer, *mac_length, "generated rakp3 mac");
|
||||
|
||||
|
||||
free(input_buffer);
|
||||
input_buffer = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* lanplus_generate_sik
|
||||
*
|
||||
* Generate the session integrity key (SIK) used for integrity checking
|
||||
* during the IPMI v2 / RMCP+ session
|
||||
*
|
||||
* This session integrity key is a HMAC generated with :
|
||||
*
|
||||
* Rm - Console generated random number
|
||||
* Rc - BMC generated random number
|
||||
* ROLEm - Requested privilege level (entire byte)
|
||||
* ULENGTHm - Username length
|
||||
* <USERNAME> - Usename (absent for null usernames)
|
||||
*
|
||||
* The key used to generated the SIK is Kg if Kg is not null (two-key logins are
|
||||
* enabled). Otherwise Kuid (the user authcode) is used as the key to genereate
|
||||
* the SIK.
|
||||
*
|
||||
* I am aware that the subscripts look backwards, but that is the way they are
|
||||
* written in the spec.
|
||||
*
|
||||
* param session [in/out] contains our input and output fields.
|
||||
*
|
||||
* returns 0 on success
|
||||
* 1 on failure
|
||||
*/
|
||||
int
|
||||
lanplus_generate_sik(struct ipmi_session * session, struct ipmi_intf * intf)
|
||||
{
|
||||
uint8_t * input_buffer;
|
||||
int input_buffer_length, i;
|
||||
uint8_t * input_key;
|
||||
uint32_t mac_length;
|
||||
|
||||
|
||||
memset(session->v2_data.sik, 0, IPMI_SIK_BUFFER_SIZE);
|
||||
|
||||
if (session->v2_data.auth_alg == IPMI_AUTH_RAKP_NONE)
|
||||
return 0;
|
||||
|
||||
/* We don't yet support other algorithms */
|
||||
assert(session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA1);
|
||||
|
||||
input_buffer_length =
|
||||
16 + /* Rm */
|
||||
16 + /* Rc */
|
||||
1 + /* ROLEm */
|
||||
1 + /* ULENGTHm */
|
||||
strlen((const char *)session->username);
|
||||
|
||||
input_buffer = malloc(input_buffer_length);
|
||||
if (input_buffer == NULL) {
|
||||
lprintf(LOG_ERR, "ipmitool: malloc failure");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill the buffer. I'm assuming that we're using the LSBF representation of the
|
||||
* multibyte numbers in use.
|
||||
*/
|
||||
|
||||
/* Rm */
|
||||
#if WORDS_BIGENDIAN
|
||||
for (i = 0; i < 16; ++i)
|
||||
input_buffer[i] = session->v2_data.console_rand[16 - 1 - i];
|
||||
#else
|
||||
for (i = 0; i < 16; ++i)
|
||||
input_buffer[i] = session->v2_data.console_rand[i];
|
||||
#endif
|
||||
|
||||
|
||||
/* Rc */
|
||||
#if WORDS_BIGENDIAN
|
||||
for (i = 0; i < 16; ++i)
|
||||
input_buffer[16 + i] = session->v2_data.bmc_rand[16 - 1 - i];
|
||||
#else
|
||||
for (i = 0; i < 16; ++i)
|
||||
input_buffer[16 + i] = session->v2_data.bmc_rand[i];
|
||||
#endif
|
||||
|
||||
/* ROLEm */
|
||||
input_buffer[32] = session->v2_data.requested_role;
|
||||
|
||||
if (ipmi_oem_active(intf, "i82571spt")) {
|
||||
/*
|
||||
* The HMAC calculation code in the Intel 82571 GbE
|
||||
* skips this bit! Looks like a GbE bug, but we need
|
||||
* to work around it here anyway...
|
||||
*/
|
||||
input_buffer[32] &= ~0x10;
|
||||
}
|
||||
|
||||
/* ULENGTHm */
|
||||
input_buffer[33] = strlen((const char *)session->username);
|
||||
|
||||
/* USERNAME */
|
||||
for (i = 0; i < input_buffer[33]; ++i)
|
||||
input_buffer[34 + i] = session->username[i];
|
||||
|
||||
if (session->v2_data.kg[0])
|
||||
{
|
||||
/* We will be hashing with Kg */
|
||||
/*
|
||||
* Section 13.31 of the IPMI v2 spec describes the SIK creation
|
||||
* using Kg. It specifies that Kg should not be truncated.
|
||||
* Kg is set in ipmi_intf.
|
||||
*/
|
||||
input_key = session->v2_data.kg;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We will be hashing with Kuid */
|
||||
input_key = session->authcode;
|
||||
}
|
||||
|
||||
|
||||
if (verbose >= 2)
|
||||
printbuf((const uint8_t *)input_buffer, input_buffer_length, "session integrity key input");
|
||||
|
||||
lanplus_HMAC(session->v2_data.auth_alg,
|
||||
input_key,
|
||||
IPMI_AUTHCODE_BUFFER_SIZE,
|
||||
input_buffer,
|
||||
input_buffer_length,
|
||||
session->v2_data.sik,
|
||||
&mac_length);
|
||||
|
||||
free(input_buffer);
|
||||
input_buffer = NULL;
|
||||
assert(mac_length == 20);
|
||||
|
||||
/*
|
||||
* The key MAC generated is 20 bytes, but we will only be using the first
|
||||
* 12 for SHA1 96
|
||||
*/
|
||||
if (verbose >= 2)
|
||||
printbuf(session->v2_data.sik, 20, "Generated session integrity key");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* lanplus_generate_k1
|
||||
*
|
||||
* Generate K1, the key presumably used to generate integrity authcodes
|
||||
*
|
||||
* We use the authentication algorithm to generated the HMAC, using
|
||||
* the session integrity key (SIK) as our key.
|
||||
*
|
||||
* param session [in/out].
|
||||
*
|
||||
* returns 0 on success
|
||||
* 1 on failure
|
||||
*/
|
||||
int
|
||||
lanplus_generate_k1(struct ipmi_session * session)
|
||||
{
|
||||
uint32_t mac_length;
|
||||
|
||||
uint8_t CONST_1[] =
|
||||
{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
|
||||
|
||||
if (session->v2_data.auth_alg == IPMI_AUTH_RAKP_NONE)
|
||||
memcpy(session->v2_data.k1, CONST_1, 20);
|
||||
else
|
||||
{
|
||||
lanplus_HMAC(session->v2_data.auth_alg,
|
||||
session->v2_data.sik,
|
||||
IPMI_SIK_BUFFER_SIZE, /* SIK length */
|
||||
CONST_1,
|
||||
20,
|
||||
session->v2_data.k1,
|
||||
&mac_length);
|
||||
assert(mac_length == 20);
|
||||
}
|
||||
|
||||
if (verbose >= 2)
|
||||
printbuf(session->v2_data.k1, 20, "Generated K1");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* lanplus_generate_k2
|
||||
*
|
||||
* Generate K2, the key used for RMCP+ AES encryption.
|
||||
*
|
||||
* We use the authentication algorithm to generated the HMAC, using
|
||||
* the session integrity key (SIK) as our key.
|
||||
*
|
||||
* param session [in/out].
|
||||
*
|
||||
* returns 0 on success
|
||||
* 1 on failure
|
||||
*/
|
||||
int
|
||||
lanplus_generate_k2(struct ipmi_session * session)
|
||||
{
|
||||
uint32_t mac_length;
|
||||
|
||||
uint8_t CONST_2[] =
|
||||
{0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
|
||||
|
||||
if (session->v2_data.auth_alg == IPMI_AUTH_RAKP_NONE)
|
||||
memcpy(session->v2_data.k2, CONST_2, 20);
|
||||
else
|
||||
{
|
||||
lanplus_HMAC(session->v2_data.auth_alg,
|
||||
session->v2_data.sik,
|
||||
IPMI_SIK_BUFFER_SIZE, /* SIK length */
|
||||
CONST_2,
|
||||
20,
|
||||
session->v2_data.k2,
|
||||
&mac_length);
|
||||
assert(mac_length == 20);
|
||||
}
|
||||
|
||||
if (verbose >= 2)
|
||||
printbuf(session->v2_data.k2, 20, "Generated K2");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* lanplus_encrypt_payload
|
||||
*
|
||||
* Perform the appropriate encryption on the input data. Output the encrypted
|
||||
* data to output, including the required confidentiality header and trailer.
|
||||
* If the crypt_alg is IPMI_CRYPT_NONE, simply copy the input to the output and
|
||||
* set bytes_written to input_length.
|
||||
*
|
||||
* param crypt_alg specifies the encryption algorithm (from table 13-19 of the
|
||||
* IPMI v2 spec)
|
||||
* param key is the used as input to the encryption algorithmf
|
||||
* param input is the input data to be encrypted
|
||||
* param input_length is the length of the input data to be encrypted
|
||||
* param output is the cipher text generated by the encryption process
|
||||
* param bytes_written is the number of bytes written during the encryption
|
||||
* process
|
||||
*
|
||||
* returns 0 on success
|
||||
* 1 on failure
|
||||
*/
|
||||
int
|
||||
lanplus_encrypt_payload(uint8_t crypt_alg,
|
||||
const uint8_t * key, const uint8_t * input,
|
||||
uint32_t input_length, uint8_t * output,
|
||||
uint16_t * bytes_written)
|
||||
{
|
||||
uint8_t * padded_input;
|
||||
uint32_t mod, i, bytes_encrypted;
|
||||
uint8_t pad_length = 0;
|
||||
|
||||
if (crypt_alg == IPMI_CRYPT_NONE)
|
||||
{
|
||||
/* Just copy the input to the output */
|
||||
*bytes_written = input_length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Currently, we only support AES */
|
||||
assert(crypt_alg == IPMI_CRYPT_AES_CBC_128);
|
||||
assert(input_length <= IPMI_MAX_PAYLOAD_SIZE);
|
||||
|
||||
|
||||
/*
|
||||
* The input to the AES encryption algorithm has to be a multiple of the
|
||||
* block size (16 bytes). The extra byte we are adding is the pad length
|
||||
* byte.
|
||||
*/
|
||||
mod = (input_length + 1) % IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE;
|
||||
if (mod)
|
||||
pad_length = IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE - mod;
|
||||
|
||||
padded_input = (uint8_t*)malloc(input_length + pad_length + 1);
|
||||
if (padded_input == NULL) {
|
||||
lprintf(LOG_ERR, "ipmitool: malloc failure");
|
||||
return 1;
|
||||
}
|
||||
memcpy(padded_input, input, input_length);
|
||||
|
||||
/* add the pad */
|
||||
for (i = 0; i < pad_length; ++i)
|
||||
padded_input[input_length + i] = i + 1;
|
||||
|
||||
/* add the pad length */
|
||||
padded_input[input_length + pad_length] = pad_length;
|
||||
|
||||
/* Generate an initialization vector, IV, for the encryption process */
|
||||
if (lanplus_rand(output, IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE))
|
||||
{
|
||||
lprintf(LOG_ERR, "lanplus_encrypt_payload: Error generating IV");
|
||||
if (padded_input != NULL) {
|
||||
free(padded_input);
|
||||
padded_input = NULL;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (verbose > 2)
|
||||
printbuf(output, IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE, ">> Initialization vector");
|
||||
|
||||
|
||||
|
||||
lanplus_encrypt_aes_cbc_128(output, /* IV */
|
||||
key, /* K2 */
|
||||
padded_input, /* Data to encrypt */
|
||||
input_length + pad_length + 1, /* Input length */
|
||||
output + IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE, /* output */
|
||||
&bytes_encrypted); /* bytes written */
|
||||
|
||||
*bytes_written =
|
||||
IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE + /* IV */
|
||||
bytes_encrypted;
|
||||
|
||||
free(padded_input);
|
||||
padded_input = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* lanplus_has_valid_auth_code
|
||||
*
|
||||
* Determine whether the packets authcode field is valid for packet.
|
||||
*
|
||||
* We always return success if any of the following are true.
|
||||
* - this is not an IPMIv2 packet
|
||||
* - the session is not yet active
|
||||
* - the packet specifies that it is not authenticated
|
||||
* - the integrity algorithm agreed upon during session creation is "none"
|
||||
*
|
||||
* The authcode is computed using the specified integrity algorithm starting
|
||||
* with the AuthType / Format field, and ending with the field immediately
|
||||
* preceeding the authcode itself.
|
||||
*
|
||||
* The key key used to generate the authcode MAC is K1.
|
||||
*
|
||||
* param rs holds the response structure.
|
||||
* param session holds our session state, including our chosen algorithm, key, etc.
|
||||
*
|
||||
* returns 1 on success (authcode is valid)
|
||||
* 0 on failure (autchode integrity check failed)
|
||||
*/
|
||||
int
|
||||
lanplus_has_valid_auth_code(struct ipmi_rs * rs, struct ipmi_session * session)
|
||||
{
|
||||
uint8_t * bmc_authcode;
|
||||
uint8_t generated_authcode[IPMI_MAX_MAC_SIZE];
|
||||
uint32_t generated_authcode_length;
|
||||
|
||||
|
||||
if ((rs->session.authtype != IPMI_SESSION_AUTHTYPE_RMCP_PLUS) ||
|
||||
(session->v2_data.session_state != LANPLUS_STATE_ACTIVE) ||
|
||||
(! rs->session.bAuthenticated) ||
|
||||
(session->v2_data.integrity_alg == IPMI_INTEGRITY_NONE))
|
||||
return 1;
|
||||
|
||||
/* We only support SHA1-96 now */
|
||||
assert(session->v2_data.integrity_alg == IPMI_INTEGRITY_HMAC_SHA1_96);
|
||||
|
||||
/*
|
||||
* For SHA1-96, the authcode will be the last 12 bytes in the packet
|
||||
*/
|
||||
bmc_authcode = rs->data + (rs->data_len - IPMI_SHA1_AUTHCODE_SIZE);
|
||||
|
||||
lanplus_HMAC(session->v2_data.integrity_alg,
|
||||
session->v2_data.k1,
|
||||
IPMI_AUTHCODE_BUFFER_SIZE,
|
||||
rs->data + IPMI_LANPLUS_OFFSET_AUTHTYPE,
|
||||
rs->data_len - IPMI_LANPLUS_OFFSET_AUTHTYPE - IPMI_SHA1_AUTHCODE_SIZE,
|
||||
generated_authcode,
|
||||
&generated_authcode_length);
|
||||
|
||||
if (verbose > 3)
|
||||
{
|
||||
lprintf(LOG_DEBUG+2, "Validating authcode");
|
||||
printbuf(session->v2_data.k1, 20, "K1");
|
||||
printbuf(rs->data + IPMI_LANPLUS_OFFSET_AUTHTYPE,
|
||||
rs->data_len - IPMI_LANPLUS_OFFSET_AUTHTYPE - IPMI_SHA1_AUTHCODE_SIZE,
|
||||
"Authcode Input Data");
|
||||
printbuf(generated_authcode, 12, "Generated authcode");
|
||||
printbuf(bmc_authcode, 12, "Expected authcode");
|
||||
}
|
||||
|
||||
|
||||
assert(generated_authcode_length == 20);
|
||||
return (memcmp(bmc_authcode, generated_authcode, 12) == 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* lanplus_decrypt_payload
|
||||
*
|
||||
*
|
||||
* param input points to the beginning of the payload (which will be the IV if
|
||||
* we are using AES)
|
||||
* param payload_size [out] will be set to the size of the payload EXCLUDING
|
||||
* padding
|
||||
*
|
||||
* returns 0 on success (we were able to successfully decrypt the packet)
|
||||
* 1 on failure (we were unable to successfully decrypt the packet)
|
||||
*/
|
||||
int
|
||||
lanplus_decrypt_payload(uint8_t crypt_alg, const uint8_t * key,
|
||||
const uint8_t * input, uint32_t input_length,
|
||||
uint8_t * output, uint16_t * payload_size)
|
||||
{
|
||||
uint8_t * decrypted_payload;
|
||||
uint32_t bytes_decrypted;
|
||||
|
||||
if (crypt_alg == IPMI_CRYPT_NONE)
|
||||
{
|
||||
/* We are not encrypted. The paylaod size is is everything. */
|
||||
*payload_size = input_length;
|
||||
memmove(output, input, input_length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We only support AES */
|
||||
assert(crypt_alg == IPMI_CRYPT_AES_CBC_128);
|
||||
|
||||
decrypted_payload = (uint8_t*)malloc(input_length);
|
||||
if (decrypted_payload == NULL) {
|
||||
lprintf(LOG_ERR, "ipmitool: malloc failure");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
lanplus_decrypt_aes_cbc_128(input, /* IV */
|
||||
key, /* Key */
|
||||
input +
|
||||
IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE, /* Data to decrypt */
|
||||
input_length -
|
||||
IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE, /* Input length */
|
||||
decrypted_payload, /* output */
|
||||
&bytes_decrypted); /* bytes written */
|
||||
|
||||
if (bytes_decrypted != 0)
|
||||
{
|
||||
/* Success */
|
||||
uint8_t conf_pad_length;
|
||||
int i;
|
||||
|
||||
memmove(output,
|
||||
decrypted_payload,
|
||||
bytes_decrypted);
|
||||
|
||||
/*
|
||||
* We have to determine the payload size, by substracting the padding, etc.
|
||||
* The last byte of the decrypted payload is the confidentiality pad length.
|
||||
*/
|
||||
conf_pad_length = decrypted_payload[bytes_decrypted - 1];
|
||||
*payload_size = bytes_decrypted - conf_pad_length - 1;
|
||||
|
||||
/*
|
||||
* Extra test to make sure that the padding looks like it should (should start
|
||||
* with 0x01, 0x02, 0x03, etc...
|
||||
*/
|
||||
for (i = 0; i < conf_pad_length; ++i)
|
||||
{
|
||||
if (decrypted_payload[*payload_size + i] != (i + 1))
|
||||
{
|
||||
lprintf(LOG_ERR, "Malformed payload padding");
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lprintf(LOG_ERR, "ERROR: lanplus_decrypt_aes_cbc_128 decryptd 0 bytes");
|
||||
assert(0);
|
||||
}
|
||||
|
||||
free(decrypted_payload);
|
||||
decrypted_payload = NULL;
|
||||
return (bytes_decrypted == 0);
|
||||
}
|
||||
75
src/plugins/lanplus/lanplus_crypt.h
Normal file
75
src/plugins/lanplus/lanplus_crypt.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistribution of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistribution in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of Sun Microsystems, Inc. or the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* This software is provided "AS IS," without a warranty of any kind.
|
||||
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
||||
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
||||
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
|
||||
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
|
||||
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
|
||||
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
|
||||
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
|
||||
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
||||
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
#ifndef IPMI_LANPLUS_CRYPT_H
|
||||
#define IPMI_LANPLUS_CRYPT_H
|
||||
|
||||
#include <ipmitool/ipmi_intf.h>
|
||||
|
||||
/*
|
||||
* See the implementation file for documentation
|
||||
* ipmi_intf can be used for oem specific implementations
|
||||
* e.g. if (ipmi_oem_active(intf, "OEM_XYZ"))
|
||||
*/
|
||||
|
||||
int lanplus_rakp2_hmac_matches(const struct ipmi_session * session,
|
||||
const uint8_t * hmac,
|
||||
struct ipmi_intf * intf);
|
||||
int lanplus_rakp4_hmac_matches(const struct ipmi_session * session,
|
||||
const uint8_t * hmac,
|
||||
struct ipmi_intf * intf);
|
||||
int lanplus_generate_rakp3_authcode(uint8_t * buffer,
|
||||
const struct ipmi_session * session,
|
||||
uint32_t * auth_length,
|
||||
struct ipmi_intf * intf);
|
||||
int lanplus_generate_sik(struct ipmi_session * session, struct ipmi_intf * intf);
|
||||
int lanplus_generate_k1(struct ipmi_session * session);
|
||||
int lanplus_generate_k2(struct ipmi_session * session);
|
||||
int lanplus_encrypt_payload(uint8_t crypt_alg,
|
||||
const uint8_t * key,
|
||||
const uint8_t * input,
|
||||
uint32_t input_length,
|
||||
uint8_t * output,
|
||||
uint16_t * bytesWritten);
|
||||
int lanplus_decrypt_payload(uint8_t crypt_alg,
|
||||
const uint8_t * key,
|
||||
const uint8_t * input,
|
||||
uint32_t input_length,
|
||||
uint8_t * output,
|
||||
uint16_t * payload_size);
|
||||
int lanplus_has_valid_auth_code(struct ipmi_rs * rs,
|
||||
struct ipmi_session * session);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* IPMI_LANPLUS_CRYPT_H */
|
||||
293
src/plugins/lanplus/lanplus_crypt_impl.c
Normal file
293
src/plugins/lanplus/lanplus_crypt_impl.c
Normal file
@@ -0,0 +1,293 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistribution of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistribution in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of Sun Microsystems, Inc. or the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* This software is provided "AS IS," without a warranty of any kind.
|
||||
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
||||
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
||||
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
|
||||
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
|
||||
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
|
||||
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
|
||||
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
|
||||
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
||||
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
#include "ipmitool/log.h"
|
||||
#include "ipmitool/ipmi_constants.h"
|
||||
#include "lanplus.h"
|
||||
#include "lanplus_crypt_impl.h"
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/err.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* lanplus_seed_prng
|
||||
*
|
||||
* Seed our PRNG with the specified number of bytes from /dev/random
|
||||
*
|
||||
* param bytes specifies the number of bytes to read from /dev/random
|
||||
*
|
||||
* returns 0 on success
|
||||
* 1 on failure
|
||||
*/
|
||||
int lanplus_seed_prng(uint32_t bytes)
|
||||
{
|
||||
if (! RAND_load_file("/dev/urandom", bytes))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* lanplus_rand
|
||||
*
|
||||
* Generate a random number of the specified size
|
||||
*
|
||||
* param num_bytes [in] is the size of the random number to be
|
||||
* generated
|
||||
* param buffer [out] is where we will place our random number
|
||||
*
|
||||
* return 0 on success
|
||||
* 1 on failure
|
||||
*/
|
||||
int
|
||||
lanplus_rand(uint8_t * buffer, uint32_t num_bytes)
|
||||
{
|
||||
#undef IPMI_LANPLUS_FAKE_RAND
|
||||
#ifdef IPMI_LANPLUS_FAKE_RAND
|
||||
|
||||
/*
|
||||
* This code exists so that we can easily find the generated random number
|
||||
* in the hex dumps.
|
||||
*/
|
||||
int i;
|
||||
for (i = 0; i < num_bytes; ++i)
|
||||
buffer[i] = 0x70 | i;
|
||||
|
||||
return 0;
|
||||
#else
|
||||
return (! RAND_bytes(buffer, num_bytes));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* lanplus_HMAC
|
||||
*
|
||||
* param mac specifies the algorithm to be used, currently only SHA1 is supported
|
||||
* param key is the key used for HMAC generation
|
||||
* param key_len is the lenght of key
|
||||
* param d is the data to be MAC'd
|
||||
* param n is the length of the data at d
|
||||
* param md is the result of the HMAC algorithm
|
||||
* param md_len is the length of md
|
||||
*
|
||||
* returns a pointer to md
|
||||
*/
|
||||
uint8_t *
|
||||
lanplus_HMAC(uint8_t mac,
|
||||
const void *key,
|
||||
int key_len,
|
||||
const uint8_t *d,
|
||||
int n,
|
||||
uint8_t *md,
|
||||
uint32_t *md_len)
|
||||
{
|
||||
const EVP_MD *evp_md = NULL;
|
||||
|
||||
if ((mac == IPMI_AUTH_RAKP_HMAC_SHA1) ||
|
||||
(mac == IPMI_INTEGRITY_HMAC_SHA1_96))
|
||||
evp_md = EVP_sha1();
|
||||
else
|
||||
{
|
||||
lprintf(LOG_DEBUG, "Invalid mac type 0x%x in lanplus_HMAC\n", mac);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
return HMAC(evp_md, key, key_len, d, n, md, (unsigned int *)md_len);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* lanplus_encrypt_aes_cbc_128
|
||||
*
|
||||
* Encrypt with the AES CBC 128 algorithm
|
||||
*
|
||||
* param iv is the 16 byte initialization vector
|
||||
* param key is the 16 byte key used by the AES algorithm
|
||||
* param input is the data to be encrypted
|
||||
* param input_length is the number of bytes to be encrypted. This MUST
|
||||
* be a multiple of the block size, 16.
|
||||
* param output is the encrypted output
|
||||
* param bytes_written is the number of bytes written. This param is set
|
||||
* to 0 on failure, or if 0 bytes were input.
|
||||
*/
|
||||
void
|
||||
lanplus_encrypt_aes_cbc_128(const uint8_t * iv,
|
||||
const uint8_t * key,
|
||||
const uint8_t * input,
|
||||
uint32_t input_length,
|
||||
uint8_t * output,
|
||||
uint32_t * bytes_written)
|
||||
{
|
||||
EVP_CIPHER_CTX ctx;
|
||||
EVP_CIPHER_CTX_init(&ctx);
|
||||
EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv);
|
||||
EVP_CIPHER_CTX_set_padding(&ctx, 0);
|
||||
|
||||
|
||||
*bytes_written = 0;
|
||||
|
||||
if (input_length == 0)
|
||||
return;
|
||||
|
||||
if (verbose >= 5)
|
||||
{
|
||||
printbuf(iv, 16, "encrypting with this IV");
|
||||
printbuf(key, 16, "encrypting with this key");
|
||||
printbuf(input, input_length, "encrypting this data");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The default implementation adds a whole block of padding if the input
|
||||
* data is perfectly aligned. We would like to keep that from happening.
|
||||
* We have made a point to have our input perfectly padded.
|
||||
*/
|
||||
assert((input_length % IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE) == 0);
|
||||
|
||||
|
||||
if(!EVP_EncryptUpdate(&ctx, output, (int *)bytes_written, input, input_length))
|
||||
{
|
||||
/* Error */
|
||||
*bytes_written = 0;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t tmplen;
|
||||
|
||||
if(!EVP_EncryptFinal_ex(&ctx, output + *bytes_written, (int *)&tmplen))
|
||||
{
|
||||
*bytes_written = 0;
|
||||
return; /* Error */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Success */
|
||||
*bytes_written += tmplen;
|
||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* lanplus_decrypt_aes_cbc_128
|
||||
*
|
||||
* Decrypt with the AES CBC 128 algorithm
|
||||
*
|
||||
* param iv is the 16 byte initialization vector
|
||||
* param key is the 16 byte key used by the AES algorithm
|
||||
* param input is the data to be decrypted
|
||||
* param input_length is the number of bytes to be decrypted. This MUST
|
||||
* be a multiple of the block size, 16.
|
||||
* param output is the decrypted output
|
||||
* param bytes_written is the number of bytes written. This param is set
|
||||
* to 0 on failure, or if 0 bytes were input.
|
||||
*/
|
||||
void
|
||||
lanplus_decrypt_aes_cbc_128(const uint8_t * iv,
|
||||
const uint8_t * key,
|
||||
const uint8_t * input,
|
||||
uint32_t input_length,
|
||||
uint8_t * output,
|
||||
uint32_t * bytes_written)
|
||||
{
|
||||
EVP_CIPHER_CTX ctx;
|
||||
EVP_CIPHER_CTX_init(&ctx);
|
||||
EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv);
|
||||
EVP_CIPHER_CTX_set_padding(&ctx, 0);
|
||||
|
||||
|
||||
if (verbose >= 5)
|
||||
{
|
||||
printbuf(iv, 16, "decrypting with this IV");
|
||||
printbuf(key, 16, "decrypting with this key");
|
||||
printbuf(input, input_length, "decrypting this data");
|
||||
}
|
||||
|
||||
|
||||
*bytes_written = 0;
|
||||
|
||||
if (input_length == 0)
|
||||
return;
|
||||
|
||||
/*
|
||||
* The default implementation adds a whole block of padding if the input
|
||||
* data is perfectly aligned. We would like to keep that from happening.
|
||||
* We have made a point to have our input perfectly padded.
|
||||
*/
|
||||
assert((input_length % IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE) == 0);
|
||||
|
||||
|
||||
if (!EVP_DecryptUpdate(&ctx, output, (int *)bytes_written, input, input_length))
|
||||
{
|
||||
/* Error */
|
||||
lprintf(LOG_DEBUG, "ERROR: decrypt update failed");
|
||||
*bytes_written = 0;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t tmplen;
|
||||
|
||||
if (!EVP_DecryptFinal_ex(&ctx, output + *bytes_written, (int *)&tmplen))
|
||||
{
|
||||
char buffer[1000];
|
||||
ERR_error_string(ERR_get_error(), buffer);
|
||||
lprintf(LOG_DEBUG, "the ERR error %s", buffer);
|
||||
lprintf(LOG_DEBUG, "ERROR: decrypt final failed");
|
||||
*bytes_written = 0;
|
||||
return; /* Error */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Success */
|
||||
*bytes_written += tmplen;
|
||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||
}
|
||||
}
|
||||
|
||||
if (verbose >= 5)
|
||||
{
|
||||
lprintf(LOG_DEBUG, "Decrypted %d encrypted bytes", input_length);
|
||||
printbuf(output, *bytes_written, "Decrypted this data");
|
||||
}
|
||||
}
|
||||
66
src/plugins/lanplus/lanplus_crypt_impl.h
Normal file
66
src/plugins/lanplus/lanplus_crypt_impl.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistribution of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistribution in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of Sun Microsystems, Inc. or the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* This software is provided "AS IS," without a warranty of any kind.
|
||||
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
||||
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
||||
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
|
||||
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
|
||||
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
|
||||
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
|
||||
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
|
||||
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
||||
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
#ifndef IPMI_LANPLUS_CRYPT_IMPL_H
|
||||
#define IPMI_LANPLUS_CRYPT_IMPL_H
|
||||
|
||||
|
||||
int
|
||||
lanplus_seed_prng(uint32_t bytes);
|
||||
|
||||
int
|
||||
lanplus_rand(uint8_t * buffer, uint32_t num_bytes);
|
||||
|
||||
uint8_t *
|
||||
lanplus_HMAC(uint8_t mac, const void *key, int key_len,
|
||||
const uint8_t *d, int n, uint8_t *md,
|
||||
uint32_t *md_len);
|
||||
|
||||
void
|
||||
lanplus_encrypt_aes_cbc_128(const uint8_t * iv,
|
||||
const uint8_t * key,
|
||||
const uint8_t * input,
|
||||
uint32_t input_length,
|
||||
uint8_t * output,
|
||||
uint32_t * bytes_written);
|
||||
|
||||
|
||||
void
|
||||
lanplus_decrypt_aes_cbc_128(const uint8_t * iv,
|
||||
const uint8_t * key,
|
||||
const uint8_t * input,
|
||||
uint32_t input_length,
|
||||
uint8_t * output,
|
||||
uint32_t * bytes_written);
|
||||
|
||||
|
||||
#endif /* IPMI_LANPLUS_CRYPT_IMPL_H */
|
||||
192
src/plugins/lanplus/lanplus_dump.c
Normal file
192
src/plugins/lanplus/lanplus_dump.c
Normal file
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistribution of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistribution in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of Sun Microsystems, Inc. or the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* This software is provided "AS IS," without a warranty of any kind.
|
||||
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
||||
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
||||
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
|
||||
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
|
||||
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
|
||||
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
|
||||
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
|
||||
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
||||
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
#include "lanplus.h"
|
||||
#include "lanplus_dump.h"
|
||||
|
||||
extern const struct valstr ipmi_rakp_return_codes[];
|
||||
extern const struct valstr ipmi_priv_levels[];
|
||||
extern const struct valstr ipmi_auth_algorithms[];
|
||||
extern const struct valstr ipmi_integrity_algorithms[];
|
||||
extern const struct valstr ipmi_encryption_algorithms[];
|
||||
|
||||
#define DUMP_PREFIX_INCOMING "<<"
|
||||
|
||||
void lanplus_dump_open_session_response(const struct ipmi_rs * rsp)
|
||||
{
|
||||
if (verbose < 2)
|
||||
return;
|
||||
|
||||
printf("%sOPEN SESSION RESPONSE\n", DUMP_PREFIX_INCOMING);
|
||||
|
||||
printf("%s Message tag : 0x%02x\n",
|
||||
DUMP_PREFIX_INCOMING,
|
||||
rsp->payload.open_session_response.message_tag);
|
||||
printf("%s RMCP+ status : %s\n",
|
||||
DUMP_PREFIX_INCOMING,
|
||||
val2str(rsp->payload.open_session_response.rakp_return_code,
|
||||
ipmi_rakp_return_codes));
|
||||
printf("%s Maximum privilege level : %s\n",
|
||||
DUMP_PREFIX_INCOMING,
|
||||
val2str(rsp->payload.open_session_response.max_priv_level,
|
||||
ipmi_priv_levels));
|
||||
printf("%s Console Session ID : 0x%08lx\n",
|
||||
DUMP_PREFIX_INCOMING,
|
||||
(long)rsp->payload.open_session_response.console_id);
|
||||
|
||||
/* only tag, status, privlvl, and console id are returned if error */
|
||||
if (rsp->payload.open_session_response.rakp_return_code !=
|
||||
IPMI_RAKP_STATUS_NO_ERRORS)
|
||||
return;
|
||||
|
||||
printf("%s BMC Session ID : 0x%08lx\n",
|
||||
DUMP_PREFIX_INCOMING,
|
||||
(long)rsp->payload.open_session_response.bmc_id);
|
||||
printf("%s Negotiated authenticatin algorithm : %s\n",
|
||||
DUMP_PREFIX_INCOMING,
|
||||
val2str(rsp->payload.open_session_response.auth_alg,
|
||||
ipmi_auth_algorithms));
|
||||
printf("%s Negotiated integrity algorithm : %s\n",
|
||||
DUMP_PREFIX_INCOMING,
|
||||
val2str(rsp->payload.open_session_response.integrity_alg,
|
||||
ipmi_integrity_algorithms));
|
||||
printf("%s Negotiated encryption algorithm : %s\n",
|
||||
DUMP_PREFIX_INCOMING,
|
||||
val2str(rsp->payload.open_session_response.crypt_alg,
|
||||
ipmi_encryption_algorithms));
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void lanplus_dump_rakp2_message(const struct ipmi_rs * rsp, uint8_t auth_alg)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (verbose < 2)
|
||||
return;
|
||||
|
||||
printf("%sRAKP 2 MESSAGE\n", DUMP_PREFIX_INCOMING);
|
||||
|
||||
printf("%s Message tag : 0x%02x\n",
|
||||
DUMP_PREFIX_INCOMING,
|
||||
rsp->payload.rakp2_message.message_tag);
|
||||
|
||||
printf("%s RMCP+ status : %s\n",
|
||||
DUMP_PREFIX_INCOMING,
|
||||
val2str(rsp->payload.rakp2_message.rakp_return_code,
|
||||
ipmi_rakp_return_codes));
|
||||
|
||||
printf("%s Console Session ID : 0x%08lx\n",
|
||||
DUMP_PREFIX_INCOMING,
|
||||
(long)rsp->payload.rakp2_message.console_id);
|
||||
|
||||
printf("%s BMC random number : 0x", DUMP_PREFIX_INCOMING);
|
||||
for (i = 0; i < 16; ++i)
|
||||
printf("%02x", rsp->payload.rakp2_message.bmc_rand[i]);
|
||||
printf("\n");
|
||||
|
||||
printf("%s BMC GUID : 0x", DUMP_PREFIX_INCOMING);
|
||||
for (i = 0; i < 16; ++i)
|
||||
printf("%02x", rsp->payload.rakp2_message.bmc_guid[i]);
|
||||
printf("\n");
|
||||
|
||||
switch(auth_alg)
|
||||
{
|
||||
case IPMI_AUTH_RAKP_NONE:
|
||||
printf("%s Key exchange auth code : none\n", DUMP_PREFIX_INCOMING);
|
||||
break;
|
||||
case IPMI_AUTH_RAKP_HMAC_SHA1:
|
||||
printf("%s Key exchange auth code [sha1] : 0x", DUMP_PREFIX_INCOMING);
|
||||
for (i = 0; i < 20; ++i)
|
||||
printf("%02x", rsp->payload.rakp2_message.key_exchange_auth_code[i]);
|
||||
printf("\n");
|
||||
break;
|
||||
case IPMI_AUTH_RAKP_HMAC_MD5:
|
||||
printf("%s Key exchange auth code [md5] : 0x", DUMP_PREFIX_INCOMING);
|
||||
for (i = 0; i < 16; ++i)
|
||||
printf("%02x", rsp->payload.rakp2_message.key_exchange_auth_code[i]);
|
||||
printf("\n");
|
||||
break;
|
||||
default:
|
||||
printf("%s Key exchange auth code : invalid", DUMP_PREFIX_INCOMING);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void lanplus_dump_rakp4_message(const struct ipmi_rs * rsp, uint8_t auth_alg)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (verbose < 2)
|
||||
return;
|
||||
|
||||
printf("%sRAKP 4 MESSAGE\n", DUMP_PREFIX_INCOMING);
|
||||
|
||||
printf("%s Message tag : 0x%02x\n",
|
||||
DUMP_PREFIX_INCOMING,
|
||||
rsp->payload.rakp4_message.message_tag);
|
||||
|
||||
printf("%s RMCP+ status : %s\n",
|
||||
DUMP_PREFIX_INCOMING,
|
||||
val2str(rsp->payload.rakp4_message.rakp_return_code,
|
||||
ipmi_rakp_return_codes));
|
||||
|
||||
printf("%s Console Session ID : 0x%08lx\n",
|
||||
DUMP_PREFIX_INCOMING,
|
||||
(long)rsp->payload.rakp4_message.console_id);
|
||||
|
||||
switch(auth_alg)
|
||||
{
|
||||
case IPMI_AUTH_RAKP_NONE:
|
||||
printf("%s Key exchange auth code : none\n", DUMP_PREFIX_INCOMING);
|
||||
break;
|
||||
case IPMI_AUTH_RAKP_HMAC_SHA1:
|
||||
printf("%s Key exchange auth code [sha1] : 0x", DUMP_PREFIX_INCOMING);
|
||||
for (i = 0; i < 12; ++i)
|
||||
printf("%02x", rsp->payload.rakp4_message.integrity_check_value[i]);
|
||||
printf("\n");
|
||||
break;
|
||||
case IPMI_AUTH_RAKP_HMAC_MD5:
|
||||
printf("%s Key exchange auth code [md5] : 0x", DUMP_PREFIX_INCOMING);
|
||||
for (i = 0; i < 12; ++i)
|
||||
printf("%02x", rsp->payload.rakp4_message.integrity_check_value[i]);
|
||||
printf("\n");
|
||||
break;
|
||||
default:
|
||||
printf("%s Key exchange auth code : invalid", DUMP_PREFIX_INCOMING);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
45
src/plugins/lanplus/lanplus_dump.h
Normal file
45
src/plugins/lanplus/lanplus_dump.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistribution of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistribution in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of Sun Microsystems, Inc. or the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* This software is provided "AS IS," without a warranty of any kind.
|
||||
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
||||
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
||||
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
|
||||
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
|
||||
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
|
||||
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
|
||||
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
|
||||
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
||||
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef IPMI_LANPLUS_DUMP_H
|
||||
#define IPMI_LANPLUS_DUMP_H
|
||||
|
||||
#include <ipmitool/ipmi_intf.h>
|
||||
|
||||
/* See the implementation file for documentation */
|
||||
void lanplus_dump_open_session_response(const struct ipmi_rs * rsp);
|
||||
void lanplus_dump_rakp2_message(const struct ipmi_rs * rsp, uint8_t auth_alg);
|
||||
void lanplus_dump_rakp4_message(const struct ipmi_rs * rsp, uint8_t auth_alg);
|
||||
|
||||
|
||||
#endif /* IPMI_LANPLUS_DUMP_H */
|
||||
39
src/plugins/lanplus/lanplus_strings.c
Normal file
39
src/plugins/lanplus/lanplus_strings.c
Normal file
@@ -0,0 +1,39 @@
|
||||
#include "lanplus.h"
|
||||
#include "ipmitool/ipmi_constants.h"
|
||||
|
||||
const struct valstr ipmi_rakp_return_codes[] = {
|
||||
|
||||
{ IPMI_RAKP_STATUS_NO_ERRORS, "no errors" },
|
||||
{ IPMI_RAKP_STATUS_INSUFFICIENT_RESOURCES_FOR_SESSION, "insufficient resources for session" },
|
||||
{ IPMI_RAKP_STATUS_INVALID_SESSION_ID, "invalid session ID" },
|
||||
{ IPMI_RAKP_STATUS_INVALID_PAYLOAD_TYPE, "invalid payload type" },
|
||||
{ IPMI_RAKP_STATUS_INVALID_AUTHENTICATION_ALGORITHM, "invalid authentication algorithm" },
|
||||
{ IPMI_RAKP_STATUS_INVALID_INTEGRITTY_ALGORITHM, "invalid integrity algorithm" },
|
||||
{ IPMI_RAKP_STATUS_NO_MATCHING_AUTHENTICATION_PAYLOAD, "no matching authentication algorithm"},
|
||||
{ IPMI_RAKP_STATUS_NO_MATCHING_INTEGRITY_PAYLOAD, "no matching integrity payload" },
|
||||
{ IPMI_RAKP_STATUS_INACTIVE_SESSION_ID, "inactive session ID" },
|
||||
{ IPMI_RAKP_STATUS_INVALID_ROLE, "invalid role" },
|
||||
{ IPMI_RAKP_STATUS_UNAUTHORIZED_ROLE_REQUESTED, "unauthorized role requested" },
|
||||
{ IPMI_RAKP_STATUS_INSUFFICIENT_RESOURCES_FOR_ROLE, "insufficient resources for role" },
|
||||
{ IPMI_RAKP_STATUS_INVALID_NAME_LENGTH, "invalid name length" },
|
||||
{ IPMI_RAKP_STATUS_UNAUTHORIZED_NAME, "unauthorized name" },
|
||||
{ IPMI_RAKP_STATUS_UNAUTHORIZED_GUID, "unauthorized GUID" },
|
||||
{ IPMI_RAKP_STATUS_INVALID_INTEGRITY_CHECK_VALUE, "invalid integrity check value" },
|
||||
{ IPMI_RAKP_STATUS_INVALID_CONFIDENTIALITY_ALGORITHM, "invalid confidentiality algorithm" },
|
||||
{ IPMI_RAKP_STATUS_NO_CIPHER_SUITE_MATCH, "no matching cipher suite" },
|
||||
{ IPMI_RAKP_STATUS_ILLEGAL_PARAMTER, "illegal parameter" },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
|
||||
const struct valstr ipmi_priv_levels[] = {
|
||||
{ IPMI_PRIV_CALLBACK, "callback" },
|
||||
{ IPMI_PRIV_USER, "user" },
|
||||
{ IPMI_PRIV_OPERATOR, "operator" },
|
||||
{ IPMI_PRIV_ADMIN, "admin" },
|
||||
{ IPMI_PRIV_OEM, "oem" },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
|
||||
|
||||
82
src/plugins/lanplus/rmcp.h
Normal file
82
src/plugins/lanplus/rmcp.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistribution of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistribution in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of Sun Microsystems, Inc. or the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* This software is provided "AS IS," without a warranty of any kind.
|
||||
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
||||
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
||||
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
|
||||
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
|
||||
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
|
||||
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
|
||||
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
|
||||
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
||||
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
#ifndef IPMI_RMCP_H
|
||||
#define IPMI_RMCP_H
|
||||
|
||||
#include <ipmitool/helper.h>
|
||||
#include "lanplus.h"
|
||||
|
||||
#define RMCP_VERSION_1 0x06
|
||||
|
||||
#define RMCP_UDP_PORT 0x26f /* port 623 */
|
||||
#define RMCP_UDP_SECURE_PORT 0x298 /* port 664 */
|
||||
|
||||
#define RMCP_TYPE_MASK 0x80
|
||||
#define RMCP_TYPE_NORM 0x00
|
||||
#define RMCP_TYPE_ACK 0x01
|
||||
|
||||
static const struct valstr rmcp_type_vals[] __attribute__((unused)) = {
|
||||
{ RMCP_TYPE_NORM, "Normal RMCP" },
|
||||
{ RMCP_TYPE_ACK, "RMCP ACK" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
#define RMCP_CLASS_MASK 0x1f
|
||||
#define RMCP_CLASS_ASF 0x06
|
||||
#define RMCP_CLASS_IPMI 0x07
|
||||
#define RMCP_CLASS_OEM 0x08
|
||||
|
||||
static const struct valstr rmcp_class_vals[] __attribute__((unused)) = {
|
||||
{ RMCP_CLASS_ASF, "ASF" },
|
||||
{ RMCP_CLASS_IPMI, "IPMI" },
|
||||
{ RMCP_CLASS_OEM, "OEM" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
/* RMCP message header */
|
||||
#ifdef HAVE_PRAGMA_PACK
|
||||
#pragma pack(1)
|
||||
#endif
|
||||
struct rmcp_hdr {
|
||||
uint8_t ver;
|
||||
uint8_t __reserved;
|
||||
uint8_t seq;
|
||||
uint8_t class;
|
||||
} ATTRIBUTE_PACKING;
|
||||
#ifdef HAVE_PRAGMA_PACK
|
||||
#pragma pack(0)
|
||||
#endif
|
||||
|
||||
int handle_rmcp(struct ipmi_intf * intf, uint8_t * data, int data_len);
|
||||
|
||||
#endif /* IPMI_RMCP_H */
|
||||
39
src/plugins/lipmi/Makefile.am
Normal file
39
src/plugins/lipmi/Makefile.am
Normal file
@@ -0,0 +1,39 @@
|
||||
# Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# Redistribution of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# Redistribution in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# Neither the name of Sun Microsystems, Inc. or the names of
|
||||
# contributors may be used to endorse or promote products derived
|
||||
# from this software without specific prior written permission.
|
||||
#
|
||||
# This software is provided "AS IS," without a warranty of any kind.
|
||||
# ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
||||
# INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
||||
# PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
||||
# SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
|
||||
# FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||
# OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
|
||||
# SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
|
||||
# OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
|
||||
# PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
|
||||
# LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
||||
# EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/include
|
||||
|
||||
EXTRA_LTLIBRARIES = libintf_lipmi.la
|
||||
noinst_LTLIBRARIES = @INTF_LIPMI_LIB@
|
||||
libintf_lipmi_la_LIBADD = $(top_builddir)/lib/libipmitool.la
|
||||
libintf_lipmi_la_SOURCES = lipmi.c
|
||||
|
||||
129
src/plugins/lipmi/lipmi.c
Normal file
129
src/plugins/lipmi/lipmi.c
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistribution of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistribution in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of Sun Microsystems, Inc. or the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* This software is provided "AS IS," without a warranty of any kind.
|
||||
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
||||
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
||||
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
|
||||
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
|
||||
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
|
||||
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
|
||||
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
|
||||
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
||||
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stropts.h>
|
||||
|
||||
#include <ipmitool/ipmi.h>
|
||||
#include <ipmitool/ipmi_intf.h>
|
||||
|
||||
#include <sys/lipmi/lipmi_intf.h>
|
||||
|
||||
#define IPMI_LIPMI_DEV "/dev/lipmi"
|
||||
|
||||
extern int verbose;
|
||||
|
||||
static int ipmi_lipmi_open(struct ipmi_intf * intf)
|
||||
{
|
||||
intf->fd = open(IPMI_LIPMI_DEV, O_RDWR);
|
||||
if (intf->fd < 0) {
|
||||
perror("Could not open lipmi device");
|
||||
return -1;
|
||||
}
|
||||
intf->opened = 1;
|
||||
intf->manufacturer_id = ipmi_get_oem(intf);
|
||||
return intf->fd;
|
||||
}
|
||||
|
||||
static void ipmi_lipmi_close(struct ipmi_intf * intf)
|
||||
{
|
||||
if (intf && intf->fd >= 0)
|
||||
close(intf->fd);
|
||||
intf->fd = -1;
|
||||
intf->opened = 0;
|
||||
intf->manufacturer_id = IPMI_OEM_UNKNOWN;
|
||||
}
|
||||
|
||||
static struct ipmi_rs * ipmi_lipmi_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
|
||||
{
|
||||
struct strioctl istr;
|
||||
static struct lipmi_reqrsp reqrsp;
|
||||
static struct ipmi_rs rsp;
|
||||
static int curr_seq = 0;
|
||||
|
||||
if (!intf || !req)
|
||||
return NULL;
|
||||
|
||||
if (!intf->opened && intf->open && intf->open(intf) < 0)
|
||||
return NULL;
|
||||
|
||||
memset(&reqrsp, 0, sizeof(reqrsp));
|
||||
reqrsp.req.fn = req->msg.netfn;
|
||||
reqrsp.req.lun = 0;
|
||||
reqrsp.req.cmd = req->msg.cmd;
|
||||
reqrsp.req.datalength = req->msg.data_len;
|
||||
memcpy(reqrsp.req.data, req->msg.data, req->msg.data_len);
|
||||
reqrsp.rsp.datalength = RECV_MAX_PAYLOAD_SIZE;
|
||||
|
||||
istr.ic_cmd = IOCTL_IPMI_KCS_ACTION;
|
||||
istr.ic_timout = 0;
|
||||
istr.ic_dp = (char *)&reqrsp;
|
||||
istr.ic_len = sizeof(struct lipmi_reqrsp);
|
||||
|
||||
if (verbose > 1) {
|
||||
printf("LIPMI req.fn : %x\n", reqrsp.req.fn);
|
||||
printf("LIPMI req.lun : %x\n", reqrsp.req.lun);
|
||||
printf("LIPMI req.cmd : %x\n", reqrsp.req.cmd);
|
||||
printf("LIPMI req.datalength : %d\n", reqrsp.req.datalength);
|
||||
}
|
||||
|
||||
if (ioctl(intf->fd, I_STR, &istr) < 0) {
|
||||
perror("LIPMI IOCTL: I_STR");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(&rsp, 0, sizeof(struct ipmi_rs));
|
||||
rsp.ccode = reqrsp.rsp.ccode;
|
||||
rsp.data_len = reqrsp.rsp.datalength;
|
||||
|
||||
if (!rsp.ccode && rsp.data_len)
|
||||
memcpy(rsp.data, reqrsp.rsp.data, rsp.data_len);
|
||||
|
||||
return &rsp;
|
||||
}
|
||||
|
||||
struct ipmi_intf ipmi_lipmi_intf = {
|
||||
name: "lipmi",
|
||||
desc: "Solaris x86 LIPMI Interface",
|
||||
open: ipmi_lipmi_open,
|
||||
close: ipmi_lipmi_close,
|
||||
sendrecv: ipmi_lipmi_send_cmd,
|
||||
target_addr: IPMI_BMC_SLAVE_ADDR,
|
||||
};
|
||||
|
||||
46
src/plugins/lipmi/lipmi.h
Normal file
46
src/plugins/lipmi/lipmi.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistribution of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistribution in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of Sun Microsystems, Inc. or the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* This software is provided "AS IS," without a warranty of any kind.
|
||||
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
||||
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
||||
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
|
||||
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
|
||||
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
|
||||
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
|
||||
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
|
||||
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
||||
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
#ifndef IPMI_LIPMI_H
|
||||
#define IPMI_LIPMI_H
|
||||
|
||||
#include <ipmitool/ipmi.h>
|
||||
#include <ipmitool/ipmi_intf.h>
|
||||
|
||||
#define LIPMI_DEV "/dev/lipmi"
|
||||
|
||||
struct ipmi_rs * ipmi_lipmi_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req);
|
||||
int ipmi_lipmi_open(struct ipmi_intf * intf);
|
||||
void ipmi_lipmi_close(struct ipmi_intf * intf);
|
||||
int lipmi_intf_setup(struct ipmi_intf ** intf);
|
||||
|
||||
#endif
|
||||
39
src/plugins/open/Makefile.am
Normal file
39
src/plugins/open/Makefile.am
Normal file
@@ -0,0 +1,39 @@
|
||||
# Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# Redistribution of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# Redistribution in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# Neither the name of Sun Microsystems, Inc. or the names of
|
||||
# contributors may be used to endorse or promote products derived
|
||||
# from this software without specific prior written permission.
|
||||
#
|
||||
# This software is provided "AS IS," without a warranty of any kind.
|
||||
# ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
||||
# INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
||||
# PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
||||
# SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
|
||||
# FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||
# OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
|
||||
# SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
|
||||
# OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
|
||||
# PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
|
||||
# LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
||||
# EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/include
|
||||
|
||||
EXTRA_LTLIBRARIES = libintf_open.la
|
||||
noinst_LTLIBRARIES = @INTF_OPEN_LIB@
|
||||
libintf_open_la_LIBADD = $(top_builddir)/lib/libipmitool.la
|
||||
libintf_open_la_SOURCES = open.c open.h
|
||||
|
||||
413
src/plugins/open/open.c
Normal file
413
src/plugins/open/open.c
Normal file
@@ -0,0 +1,413 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistribution of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistribution in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of Sun Microsystems, Inc. or the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* This software is provided "AS IS," without a warranty of any kind.
|
||||
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
||||
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
||||
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
|
||||
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
|
||||
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
|
||||
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
|
||||
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
|
||||
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
||||
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <ipmitool/ipmi.h>
|
||||
#include <ipmitool/ipmi_intf.h>
|
||||
#include <ipmitool/helper.h>
|
||||
#include <ipmitool/log.h>
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_SYS_IOCCOM_H)
|
||||
# include <sys/ioccom.h>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_OPENIPMI_H)
|
||||
# if defined(HAVE_LINUX_COMPILER_H)
|
||||
# include <linux/compiler.h>
|
||||
# endif
|
||||
# include <linux/ipmi.h>
|
||||
#elif defined(HAVE_FREEBSD_IPMI_H)
|
||||
/* FreeBSD OpenIPMI-compatible header */
|
||||
# include <sys/ipmi.h>
|
||||
#else
|
||||
# include "open.h"
|
||||
#endif
|
||||
|
||||
extern int verbose;
|
||||
|
||||
static int
|
||||
ipmi_openipmi_open(struct ipmi_intf * intf)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
char ipmi_dev[16];
|
||||
char ipmi_devfs[16];
|
||||
char ipmi_devfs2[16];
|
||||
int devnum = 0;
|
||||
|
||||
devnum = intf->devnum;
|
||||
|
||||
sprintf(ipmi_dev, "/dev/ipmi%d", devnum);
|
||||
sprintf(ipmi_devfs, "/dev/ipmi/%d", devnum);
|
||||
sprintf(ipmi_devfs2, "/dev/ipmidev/%d", devnum);
|
||||
lprintf(LOG_DEBUG, "Using ipmi device %d", devnum);
|
||||
|
||||
intf->fd = open(ipmi_dev, O_RDWR);
|
||||
|
||||
if (intf->fd < 0) {
|
||||
intf->fd = open(ipmi_devfs, O_RDWR);
|
||||
if (intf->fd < 0) {
|
||||
intf->fd = open(ipmi_devfs2, O_RDWR);
|
||||
}
|
||||
if (intf->fd < 0) {
|
||||
lperror(LOG_ERR, "Could not open device at %s or %s or %s",
|
||||
ipmi_dev, ipmi_devfs , ipmi_devfs2);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ioctl(intf->fd, IPMICTL_SET_GETS_EVENTS_CMD, &i) < 0) {
|
||||
lperror(LOG_ERR, "Could not enable event receiver");
|
||||
return -1;
|
||||
}
|
||||
|
||||
intf->opened = 1;
|
||||
|
||||
/* This is never set to 0, the default is IPMI_BMC_SLAVE_ADDR */
|
||||
if (intf->my_addr != 0) {
|
||||
if (intf->set_my_addr(intf, intf->my_addr) < 0) {
|
||||
lperror(LOG_ERR, "Could not set IPMB address");
|
||||
return -1;
|
||||
}
|
||||
lprintf(LOG_DEBUG, "Set IPMB address to 0x%x",
|
||||
intf->my_addr );
|
||||
}
|
||||
|
||||
intf->manufacturer_id = ipmi_get_oem(intf);
|
||||
return intf->fd;
|
||||
}
|
||||
static int
|
||||
ipmi_openipmi_set_my_addr(struct ipmi_intf *intf, uint8_t addr)
|
||||
{
|
||||
unsigned int a = addr;
|
||||
if (ioctl(intf->fd, IPMICTL_SET_MY_ADDRESS_CMD, &a) < 0) {
|
||||
lperror(LOG_ERR, "Could not set IPMB address");
|
||||
return -1;
|
||||
}
|
||||
intf->my_addr = addr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
ipmi_openipmi_close(struct ipmi_intf * intf)
|
||||
{
|
||||
if (intf->fd >= 0) {
|
||||
close(intf->fd);
|
||||
intf->fd = -1;
|
||||
}
|
||||
|
||||
intf->opened = 0;
|
||||
intf->manufacturer_id = IPMI_OEM_UNKNOWN;
|
||||
}
|
||||
|
||||
static struct ipmi_rs *
|
||||
ipmi_openipmi_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
|
||||
{
|
||||
struct ipmi_recv recv;
|
||||
struct ipmi_addr addr;
|
||||
struct ipmi_system_interface_addr bmc_addr = {
|
||||
addr_type: IPMI_SYSTEM_INTERFACE_ADDR_TYPE,
|
||||
channel: IPMI_BMC_CHANNEL,
|
||||
};
|
||||
struct ipmi_ipmb_addr ipmb_addr = {
|
||||
addr_type: IPMI_IPMB_ADDR_TYPE,
|
||||
};
|
||||
struct ipmi_req _req;
|
||||
static struct ipmi_rs rsp;
|
||||
static int curr_seq = 0;
|
||||
fd_set rset;
|
||||
|
||||
uint8_t * data = NULL;
|
||||
int data_len = 0;
|
||||
|
||||
|
||||
if (intf == NULL || req == NULL)
|
||||
return NULL;
|
||||
|
||||
ipmb_addr.channel = intf->target_channel & 0x0f;
|
||||
|
||||
if (intf->opened == 0 && intf->open != NULL)
|
||||
if (intf->open(intf) < 0)
|
||||
return NULL;
|
||||
|
||||
if (verbose > 2)
|
||||
printbuf(req->msg.data, req->msg.data_len,
|
||||
"OpenIPMI Request Message");
|
||||
|
||||
/*
|
||||
* setup and send message
|
||||
*/
|
||||
|
||||
memset(&_req, 0, sizeof(struct ipmi_req));
|
||||
|
||||
if (intf->target_addr != 0 &&
|
||||
intf->target_addr != intf->my_addr) {
|
||||
/* use IPMB address if needed */
|
||||
ipmb_addr.slave_addr = intf->target_addr;
|
||||
ipmb_addr.lun = req->msg.lun;
|
||||
lprintf(LOG_DEBUG, "Sending request 0x%x to "
|
||||
"IPMB target @ 0x%x:0x%x (from 0x%x)",
|
||||
req->msg.cmd,
|
||||
intf->target_addr,intf->target_channel, intf->my_addr);
|
||||
|
||||
if(intf->transit_addr != 0 && intf->transit_addr != intf->my_addr) {
|
||||
uint8_t index = 0;
|
||||
|
||||
lprintf(LOG_DEBUG, "Encapsulating data sent to "
|
||||
"end target [0x%02x,0x%02x] using transit [0x%02x,0x%02x] from 0x%x ",
|
||||
(0x40 | intf->target_channel),
|
||||
intf->target_addr,
|
||||
intf->transit_channel,
|
||||
intf->transit_addr,
|
||||
intf->my_addr
|
||||
);
|
||||
|
||||
/* Convert Message to 'Send Message' */
|
||||
/* Supplied req : req , internal req : _req */
|
||||
|
||||
if (verbose > 4) {
|
||||
fprintf(stderr, "Converting message:\n");
|
||||
fprintf(stderr, " netfn = 0x%x\n", req->msg.netfn );
|
||||
fprintf(stderr, " cmd = 0x%x\n", req->msg.cmd);
|
||||
if (recv.msg.data && recv.msg.data_len) {
|
||||
fprintf(stderr, " data_len = %d\n", req->msg.data_len);
|
||||
fprintf(stderr, " data = %s\n",
|
||||
buf2str(req->msg.data,req->msg.data_len));
|
||||
}
|
||||
}
|
||||
|
||||
/* Modify target address to use 'transit' instead */
|
||||
ipmb_addr.slave_addr = intf->transit_addr;
|
||||
ipmb_addr.channel = intf->transit_channel;
|
||||
|
||||
/* FIXME backup "My address" */
|
||||
data_len = req->msg.data_len + 8;
|
||||
data = malloc(data_len);
|
||||
if (data == NULL) {
|
||||
lprintf(LOG_ERR, "ipmitool: malloc failure");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(data, 0, data_len);
|
||||
|
||||
data[index++] = (0x40|intf->target_channel);
|
||||
data[index++] = intf->target_addr;
|
||||
data[index++] = ( req->msg.netfn << 2 ) | req->msg.lun ;
|
||||
data[index++] = ipmi_csum(data+1, 2);
|
||||
data[index++] = 0xFF; /* normally 0x20 , overwritten by IPMC */
|
||||
data[index++] = ( (0) << 2) | 0 ; /* FIXME */
|
||||
data[index++] = req->msg.cmd;
|
||||
memcpy( (data+index) , req->msg.data, req->msg.data_len);
|
||||
index += req->msg.data_len;
|
||||
data[index++] = ipmi_csum( (data+4),(req->msg.data_len + 3) );
|
||||
|
||||
if (verbose > 4) {
|
||||
fprintf(stderr, "Encapsulated message:\n");
|
||||
fprintf(stderr, " netfn = 0x%x\n", IPMI_NETFN_APP );
|
||||
fprintf(stderr, " cmd = 0x%x\n", 0x34 );
|
||||
if (data && data_len) {
|
||||
fprintf(stderr, " data_len = %d\n", data_len);
|
||||
fprintf(stderr, " data = %s\n",
|
||||
buf2str(data,data_len));
|
||||
}
|
||||
}
|
||||
}
|
||||
_req.addr = (unsigned char *) &ipmb_addr;
|
||||
_req.addr_len = sizeof(ipmb_addr);
|
||||
} else {
|
||||
/* otherwise use system interface */
|
||||
lprintf(LOG_DEBUG+2, "Sending request 0x%x to "
|
||||
"System Interface", req->msg.cmd);
|
||||
bmc_addr.lun = req->msg.lun;
|
||||
_req.addr = (unsigned char *) &bmc_addr;
|
||||
_req.addr_len = sizeof(bmc_addr);
|
||||
}
|
||||
|
||||
_req.msgid = curr_seq++;
|
||||
|
||||
/* In case of a bridge request */
|
||||
if( data != NULL && data_len != 0 ) {
|
||||
_req.msg.data = data;
|
||||
_req.msg.data_len = data_len;
|
||||
_req.msg.netfn = IPMI_NETFN_APP;
|
||||
_req.msg.cmd = 0x34;
|
||||
|
||||
} else {
|
||||
_req.msg.data = req->msg.data;
|
||||
_req.msg.data_len = req->msg.data_len;
|
||||
_req.msg.netfn = req->msg.netfn;
|
||||
_req.msg.cmd = req->msg.cmd;
|
||||
}
|
||||
|
||||
if (ioctl(intf->fd, IPMICTL_SEND_COMMAND, &_req) < 0) {
|
||||
lperror(LOG_ERR, "Unable to send command");
|
||||
if (data != NULL) {
|
||||
free(data);
|
||||
data = NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* wait for and retrieve response
|
||||
*/
|
||||
|
||||
if (intf->noanswer) {
|
||||
if (data != NULL) {
|
||||
free(data);
|
||||
data = NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FD_ZERO(&rset);
|
||||
FD_SET(intf->fd, &rset);
|
||||
|
||||
if (select(intf->fd+1, &rset, NULL, NULL, NULL) < 0) {
|
||||
lperror(LOG_ERR, "I/O Error");
|
||||
if (data != NULL) {
|
||||
free(data);
|
||||
data = NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
if (FD_ISSET(intf->fd, &rset) == 0) {
|
||||
lprintf(LOG_ERR, "No data available");
|
||||
if (data != NULL) {
|
||||
free(data);
|
||||
data = NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
recv.addr = (unsigned char *) &addr;
|
||||
recv.addr_len = sizeof(addr);
|
||||
recv.msg.data = rsp.data;
|
||||
recv.msg.data_len = sizeof(rsp.data);
|
||||
|
||||
/* get data */
|
||||
if (ioctl(intf->fd, IPMICTL_RECEIVE_MSG_TRUNC, &recv) < 0) {
|
||||
lperror(LOG_ERR, "Error receiving message");
|
||||
if (errno != EMSGSIZE) {
|
||||
if (data != NULL) {
|
||||
free(data);
|
||||
data = NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (verbose > 4) {
|
||||
fprintf(stderr, "Got message:");
|
||||
fprintf(stderr, " type = %d\n", recv.recv_type);
|
||||
fprintf(stderr, " channel = 0x%x\n", addr.channel);
|
||||
fprintf(stderr, " msgid = %ld\n", recv.msgid);
|
||||
fprintf(stderr, " netfn = 0x%x\n", recv.msg.netfn);
|
||||
fprintf(stderr, " cmd = 0x%x\n", recv.msg.cmd);
|
||||
if (recv.msg.data && recv.msg.data_len) {
|
||||
fprintf(stderr, " data_len = %d\n", recv.msg.data_len);
|
||||
fprintf(stderr, " data = %s\n",
|
||||
buf2str(recv.msg.data, recv.msg.data_len));
|
||||
}
|
||||
}
|
||||
|
||||
if(intf->transit_addr != 0 && intf->transit_addr != intf->my_addr) {
|
||||
uint8_t index = 0;
|
||||
|
||||
/* ipmb_addr.transit_slave_addr = intf->transit_addr; */
|
||||
lprintf(LOG_DEBUG, "Decapsulating data received from transit "
|
||||
"IPMB target @ 0x%x", intf->transit_addr);
|
||||
|
||||
/* comp code */
|
||||
/* Check data */
|
||||
|
||||
if( recv.msg.data[0] == 0 ) {
|
||||
recv.msg.netfn = recv.msg.data[2] >> 2;
|
||||
recv.msg.cmd = recv.msg.data[6];
|
||||
|
||||
recv.msg.data = memmove(recv.msg.data ,recv.msg.data+7 , recv.msg.data_len - 7);
|
||||
recv.msg.data_len -=8;
|
||||
|
||||
if (verbose > 4) {
|
||||
fprintf(stderr, "Decapsulated message:\n");
|
||||
fprintf(stderr, " netfn = 0x%x\n", recv.msg.netfn );
|
||||
fprintf(stderr, " cmd = 0x%x\n", recv.msg.cmd);
|
||||
if (recv.msg.data && recv.msg.data_len) {
|
||||
fprintf(stderr, " data_len = %d\n", recv.msg.data_len);
|
||||
fprintf(stderr, " data = %s\n",
|
||||
buf2str(recv.msg.data,recv.msg.data_len));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* save completion code */
|
||||
rsp.ccode = recv.msg.data[0];
|
||||
rsp.data_len = recv.msg.data_len - 1;
|
||||
|
||||
/* save response data for caller */
|
||||
if (rsp.ccode == 0 && rsp.data_len > 0) {
|
||||
memmove(rsp.data, rsp.data + 1, rsp.data_len);
|
||||
rsp.data[recv.msg.data_len] = 0;
|
||||
}
|
||||
|
||||
if (data != NULL) {
|
||||
free(data);
|
||||
data = NULL;
|
||||
}
|
||||
|
||||
return &rsp;
|
||||
}
|
||||
|
||||
struct ipmi_intf ipmi_open_intf = {
|
||||
name: "open",
|
||||
desc: "Linux OpenIPMI Interface",
|
||||
open: ipmi_openipmi_open,
|
||||
close: ipmi_openipmi_close,
|
||||
sendrecv: ipmi_openipmi_send_cmd,
|
||||
set_my_addr: ipmi_openipmi_set_my_addr,
|
||||
my_addr: IPMI_BMC_SLAVE_ADDR,
|
||||
target_addr: 0, /* init so -m local_addr does not cause bridging */
|
||||
};
|
||||
106
src/plugins/open/open.h
Normal file
106
src/plugins/open/open.h
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistribution of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistribution in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of Sun Microsystems, Inc. or the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* This software is provided "AS IS," without a warranty of any kind.
|
||||
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
||||
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
||||
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
|
||||
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
|
||||
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
|
||||
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
|
||||
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
|
||||
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
||||
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
#ifndef IPMI_OPENIPMI_H
|
||||
#define IPMI_OPENIPMI_H
|
||||
|
||||
#define IPMI_MAX_ADDR_SIZE 0x20
|
||||
#define IPMI_BMC_CHANNEL 0xf
|
||||
#define IPMI_NUM_CHANNELS 0x10
|
||||
|
||||
#define IPMI_SYSTEM_INTERFACE_ADDR_TYPE 0x0c
|
||||
#define IPMI_IPMB_ADDR_TYPE 0x01
|
||||
#define IPMI_IPMB_BROADCAST_ADDR_TYPE 0x41
|
||||
|
||||
#define IPMI_RESPONSE_RECV_TYPE 1
|
||||
#define IPMI_ASYNC_EVENT_RECV_TYPE 2
|
||||
#define IPMI_CMD_RECV_TYPE 3
|
||||
|
||||
struct ipmi_addr {
|
||||
int addr_type;
|
||||
short channel;
|
||||
char data[IPMI_MAX_ADDR_SIZE];
|
||||
};
|
||||
|
||||
struct ipmi_msg {
|
||||
unsigned char netfn;
|
||||
unsigned char cmd;
|
||||
unsigned short data_len;
|
||||
unsigned char *data;
|
||||
};
|
||||
|
||||
struct ipmi_req {
|
||||
unsigned char *addr;
|
||||
unsigned int addr_len;
|
||||
long msgid;
|
||||
struct ipmi_msg msg;
|
||||
};
|
||||
|
||||
struct ipmi_recv {
|
||||
int recv_type;
|
||||
unsigned char *addr;
|
||||
unsigned int addr_len;
|
||||
long msgid;
|
||||
struct ipmi_msg msg;
|
||||
};
|
||||
|
||||
struct ipmi_cmdspec {
|
||||
unsigned char netfn;
|
||||
unsigned char cmd;
|
||||
};
|
||||
|
||||
struct ipmi_system_interface_addr {
|
||||
int addr_type;
|
||||
short channel;
|
||||
unsigned char lun;
|
||||
};
|
||||
|
||||
struct ipmi_ipmb_addr {
|
||||
int addr_type;
|
||||
short channel;
|
||||
unsigned char slave_addr;
|
||||
unsigned char lun;
|
||||
};
|
||||
|
||||
#define IPMI_IOC_MAGIC 'i'
|
||||
#define IPMICTL_RECEIVE_MSG_TRUNC _IOWR(IPMI_IOC_MAGIC, 11, struct ipmi_recv)
|
||||
#define IPMICTL_RECEIVE_MSG _IOWR(IPMI_IOC_MAGIC, 12, struct ipmi_recv)
|
||||
#define IPMICTL_SEND_COMMAND _IOR(IPMI_IOC_MAGIC, 13, struct ipmi_req)
|
||||
#define IPMICTL_REGISTER_FOR_CMD _IOR(IPMI_IOC_MAGIC, 14, struct ipmi_cmdspec)
|
||||
#define IPMICTL_UNREGISTER_FOR_CMD _IOR(IPMI_IOC_MAGIC, 15, struct ipmi_cmdspec)
|
||||
#define IPMICTL_SET_GETS_EVENTS_CMD _IOR(IPMI_IOC_MAGIC, 16, int)
|
||||
#define IPMICTL_SET_MY_ADDRESS_CMD _IOR(IPMI_IOC_MAGIC, 17, unsigned int)
|
||||
#define IPMICTL_GET_MY_ADDRESS_CMD _IOR(IPMI_IOC_MAGIC, 18, unsigned int)
|
||||
#define IPMICTL_SET_MY_LUN_CMD _IOR(IPMI_IOC_MAGIC, 19, unsigned int)
|
||||
#define IPMICTL_GET_MY_LUN_CMD _IOR(IPMI_IOC_MAGIC, 20, unsigned int)
|
||||
|
||||
#endif /*IPMI_OPENIPMI_H*/
|
||||
38
src/plugins/serial/Makefile.am
Normal file
38
src/plugins/serial/Makefile.am
Normal file
@@ -0,0 +1,38 @@
|
||||
# * Copyright (c) 2012 Pigeon Point Systems. All Rights Reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# Redistribution of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# Redistribution in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# Neither the name of Pigeon Point Systems, Inc. or the names of
|
||||
# contributors may be used to endorse or promote products derived
|
||||
# from this software without specific prior written permission.
|
||||
#
|
||||
# This software is provided "AS IS," without a warranty of any kind.
|
||||
# ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
||||
# INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
||||
# PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
||||
# PIGEON POINT SYSTEMS ("PPS") AND ITS LICENSORS SHALL NOT BE LIABLE
|
||||
# FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||
# OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
|
||||
# PPS OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
|
||||
# OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
|
||||
# PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
|
||||
# LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
||||
# EVEN IF PPS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/include
|
||||
|
||||
EXTRA_LTLIBRARIES = libintf_serial.la
|
||||
noinst_LTLIBRARIES = @INTF_SERIAL_LIB@
|
||||
libintf_serial_la_LIBADD = $(top_builddir)/lib/libipmitool.la
|
||||
libintf_serial_la_SOURCES = serial_terminal.c serial_basic.c
|
||||
1025
src/plugins/serial/serial_basic.c
Normal file
1025
src/plugins/serial/serial_basic.c
Normal file
File diff suppressed because it is too large
Load Diff
915
src/plugins/serial/serial_terminal.c
Normal file
915
src/plugins/serial/serial_terminal.c
Normal file
@@ -0,0 +1,915 @@
|
||||
/*
|
||||
* Copyright (c) 2007-2012 Pigeon Point Systems. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistribution of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistribution in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of Pigeon Point Systems nor the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* This software is provided "AS IS," without a warranty of any kind.
|
||||
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
||||
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
||||
* PIGEON POINT SYSTEMS ("PPS") AND ITS LICENSORS SHALL NOT BE LIABLE
|
||||
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
|
||||
* PPS OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
|
||||
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
|
||||
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
|
||||
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
||||
* EVEN IF PPS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
/* Serial Interface, Terminal Mode plugin. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/poll.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include <ipmitool/ipmi.h>
|
||||
#include <ipmitool/ipmi_intf.h>
|
||||
#include <ipmitool/helper.h>
|
||||
#include <ipmitool/log.h>
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#define IPMI_SERIAL_TIMEOUT 5
|
||||
#define IPMI_SERIAL_RETRY 5
|
||||
#define IPMI_SERIAL_MAX_RESPONSE 256
|
||||
|
||||
/*
|
||||
* Terminal Mode interface is required to support 40 byte transactions.
|
||||
*/
|
||||
#define IPMI_SERIAL_MAX_RQ_SIZE 37 /* 40 - 3 */
|
||||
#define IPMI_SERIAL_MAX_RS_SIZE 36 /* 40 - 4 */
|
||||
|
||||
/*
|
||||
* IPMB message header
|
||||
*/
|
||||
struct ipmb_msg_hdr {
|
||||
unsigned char rsSA;
|
||||
unsigned char netFn; /* NET FN | RS LUN */
|
||||
unsigned char csum1;
|
||||
unsigned char rqSA;
|
||||
unsigned char rqSeq; /* RQ SEQ | RQ LUN */
|
||||
unsigned char cmd;
|
||||
unsigned char data[0];
|
||||
};
|
||||
|
||||
/*
|
||||
* Send Message command request for IPMB-format
|
||||
*/
|
||||
struct ipmi_send_message_rq {
|
||||
unsigned char channel;
|
||||
struct ipmb_msg_hdr msg;
|
||||
};
|
||||
|
||||
/*
|
||||
* Get Message command response for IPMB-format
|
||||
*/
|
||||
struct ipmi_get_message_rp {
|
||||
unsigned char completion;
|
||||
unsigned char channel;
|
||||
unsigned char netFn;
|
||||
unsigned char csum1;
|
||||
unsigned char rsSA;
|
||||
unsigned char rqSeq;
|
||||
unsigned char cmd;
|
||||
unsigned char data[0];
|
||||
};
|
||||
|
||||
/*
|
||||
* Terminal mode message header
|
||||
*/
|
||||
struct serial_term_hdr {
|
||||
unsigned char netFn;
|
||||
unsigned char seq;
|
||||
unsigned char cmd;
|
||||
};
|
||||
|
||||
/*
|
||||
* Sending context
|
||||
*/
|
||||
struct serial_term_request_ctx {
|
||||
uint8_t netFn;
|
||||
uint8_t sa;
|
||||
uint8_t seq;
|
||||
uint8_t cmd;
|
||||
};
|
||||
|
||||
/*
|
||||
* Table of supported baud rates
|
||||
*/
|
||||
static const struct {
|
||||
int baudinit;
|
||||
int baudrate;
|
||||
} rates[] = {
|
||||
{ B2400, 2400 },
|
||||
{ B9600, 9600 },
|
||||
{ B19200, 19200 },
|
||||
{ B38400, 38400 },
|
||||
{ B57600, 57600 },
|
||||
{ B115200, 115200 },
|
||||
{ B230400, 230400 },
|
||||
#ifdef B460800
|
||||
{ B460800, 460800 },
|
||||
#endif
|
||||
};
|
||||
|
||||
static int is_system;
|
||||
|
||||
static int
|
||||
ipmi_serial_term_open(struct ipmi_intf * intf)
|
||||
{
|
||||
struct termios ti;
|
||||
unsigned int rate = 9600;
|
||||
char *p;
|
||||
int i;
|
||||
|
||||
if (!intf->devfile) {
|
||||
lprintf(LOG_ERR, "Serial device is not specified");
|
||||
return -1;
|
||||
}
|
||||
|
||||
is_system = 0;
|
||||
|
||||
/* check if baud rate is specified */
|
||||
if ((p = strchr(intf->devfile, ':'))) {
|
||||
char * pp;
|
||||
|
||||
/* separate device name from baud rate */
|
||||
*p++ = '\0';
|
||||
|
||||
/* check for second colon */
|
||||
if ((pp = strchr(p, ':'))) {
|
||||
/* this is needed to normally acquire baud rate */
|
||||
*pp++ = '\0';
|
||||
|
||||
/* check if it is a system interface */
|
||||
if (pp[0] == 'S' || pp[0] == 's') {
|
||||
is_system = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (str2uint(p, &rate)) {
|
||||
lprintf(LOG_ERR, "Invalid baud rate specified\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
intf->fd = open(intf->devfile, O_RDWR | O_NONBLOCK, 0);
|
||||
if (intf->fd < 0) {
|
||||
lperror(LOG_ERR, "Could not open device at %s", intf->devfile);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(rates) / sizeof(rates[0]); i++) {
|
||||
if (rates[i].baudrate == rate) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i >= sizeof(rates) / sizeof(rates[0])) {
|
||||
lprintf(LOG_ERR, "Unsupported baud rate %i specified", rate);
|
||||
return -1;
|
||||
}
|
||||
|
||||
tcgetattr(intf->fd, &ti);
|
||||
|
||||
cfsetispeed(&ti, rates[i].baudinit);
|
||||
cfsetospeed(&ti, rates[i].baudinit);
|
||||
|
||||
/* 8N1 */
|
||||
ti.c_cflag &= ~PARENB;
|
||||
ti.c_cflag &= ~CSTOPB;
|
||||
ti.c_cflag &= ~CSIZE;
|
||||
ti.c_cflag |= CS8;
|
||||
|
||||
/* enable the receiver and set local mode */
|
||||
ti.c_cflag |= (CLOCAL | CREAD);
|
||||
|
||||
/* no flow control */
|
||||
ti.c_cflag &= ~CRTSCTS;
|
||||
ti.c_iflag &= ~(IGNBRK | IGNCR | INLCR | ICRNL | INPCK | ISTRIP
|
||||
| IXON | IXOFF | IXANY);
|
||||
#ifdef IUCLC
|
||||
/* Only disable uppercase-to-lowercase mapping on input for
|
||||
platforms supporting the flag. */
|
||||
ti.c_iflag &= ~(IUCLC);
|
||||
#endif
|
||||
|
||||
ti.c_oflag &= ~(OPOST);
|
||||
ti.c_lflag &= ~(ICANON | ISIG | ECHO | ECHONL | NOFLSH);
|
||||
|
||||
/* set the new options for the port with flushing */
|
||||
tcsetattr(intf->fd, TCSAFLUSH, &ti);
|
||||
|
||||
if (intf->session->timeout == 0)
|
||||
intf->session->timeout = IPMI_SERIAL_TIMEOUT;
|
||||
if (intf->session->retry == 0)
|
||||
intf->session->retry = IPMI_SERIAL_RETRY;
|
||||
|
||||
intf->opened = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
ipmi_serial_term_close(struct ipmi_intf * intf)
|
||||
{
|
||||
if (intf->opened) {
|
||||
close(intf->fd);
|
||||
intf->fd = -1;
|
||||
}
|
||||
|
||||
if (intf->session) {
|
||||
free(intf->session);
|
||||
intf->session = NULL;
|
||||
}
|
||||
|
||||
intf->opened = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function waits for incoming byte during timeout (ms).
|
||||
*/
|
||||
static int
|
||||
serial_wait_for_data(struct ipmi_intf * intf)
|
||||
{
|
||||
int n;
|
||||
struct pollfd pfd;
|
||||
|
||||
pfd.fd = intf->fd;
|
||||
pfd.events = POLLIN;
|
||||
pfd.revents = 0;
|
||||
|
||||
n = poll(&pfd, 1, intf->session->timeout*1000);
|
||||
if (n < 0) {
|
||||
lperror(LOG_ERR, "Poll for serial data failed");
|
||||
return -1;
|
||||
} else if (!n) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a line from serial port
|
||||
* Returns > 0 if there is a line, < 0 on error or timeout
|
||||
*/
|
||||
static int
|
||||
serial_read_line(struct ipmi_intf * intf, char *str, int len)
|
||||
{
|
||||
int rv, i;
|
||||
|
||||
*str = 0;
|
||||
i = 0;
|
||||
while (i < len) {
|
||||
if (serial_wait_for_data(intf)) {
|
||||
return -1;
|
||||
}
|
||||
rv = read(intf->fd, str + i, 1);
|
||||
if (rv < 0) {
|
||||
return -1;
|
||||
} else if (!rv) {
|
||||
lperror(LOG_ERR, "Serial read failed: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (str[i] == '\n' || str[i] == '\r') {
|
||||
if (verbose > 4) {
|
||||
char c = str[i];
|
||||
str[i] = '\0';
|
||||
fprintf(stderr, "Received data: %s\n", str);
|
||||
str[i] = c;
|
||||
}
|
||||
return i + 1;
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
lprintf(LOG_ERR, "Serial data is too long");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send zero-terminated string to serial port
|
||||
* Returns the string length or negative error code
|
||||
*/
|
||||
static int
|
||||
serial_write_line(struct ipmi_intf * intf, const char *str)
|
||||
{
|
||||
int rv, cnt = 0;
|
||||
int cb = strlen(str);
|
||||
|
||||
while (cnt < cb) {
|
||||
rv = write(intf->fd, str + cnt, cb - cnt);
|
||||
if (rv < 0) {
|
||||
return -1;
|
||||
} else if (rv == 0) {
|
||||
return -1;
|
||||
}
|
||||
cnt += rv;
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
/*
|
||||
* Flush the buffers
|
||||
*/
|
||||
static int
|
||||
serial_flush(struct ipmi_intf * intf)
|
||||
{
|
||||
#if defined(TCFLSH)
|
||||
return ioctl(intf->fd, TCFLSH, TCIOFLUSH);
|
||||
#elif defined(TIOCFLUSH)
|
||||
return ioctl(intf->fd, TIOCFLUSH);
|
||||
#else
|
||||
# error "unsupported platform, missing flush support (TCFLSH/TIOCFLUSH)"
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Receive IPMI response from the device
|
||||
* Len: buffer size
|
||||
* Returns: -1 or response lenth on success
|
||||
*/
|
||||
static int
|
||||
recv_response(struct ipmi_intf * intf, unsigned char *data, int len)
|
||||
{
|
||||
char hex_rs[IPMI_SERIAL_MAX_RESPONSE * 3];
|
||||
int i, j, resp_len = 0;
|
||||
unsigned long rv;
|
||||
char *p, *pp;
|
||||
char ch, str_hex[3];
|
||||
|
||||
p = hex_rs;
|
||||
while (1) {
|
||||
if ((rv = serial_read_line(intf, p, sizeof(hex_rs) - resp_len)) < 0) {
|
||||
/* error */
|
||||
return -1;
|
||||
}
|
||||
p += rv;
|
||||
resp_len += rv;
|
||||
if (*(p - 2) == ']' && (*(p - 1) == '\n' || *(p - 1) == '\r')) {
|
||||
*p = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
p = strrchr(hex_rs, '[');
|
||||
if (!p) {
|
||||
lprintf(LOG_ERR, "Serial response is invalid");
|
||||
return -1;
|
||||
}
|
||||
|
||||
p++;
|
||||
pp = strchr(p, ']');
|
||||
if (!pp) {
|
||||
lprintf(LOG_ERR, "Serial response is invalid");
|
||||
return -1;
|
||||
}
|
||||
*pp = 0;
|
||||
|
||||
/* was it an error? */
|
||||
if (strncmp(p, "ERR ", 4) == 0) {
|
||||
serial_write_line(intf, "\r\r\r\r");
|
||||
sleep(1);
|
||||
serial_flush(intf);
|
||||
errno = 0;
|
||||
rv = strtoul(p + 4, &p, 16);
|
||||
if ((rv && rv < 0x100 && *p == '\0')
|
||||
|| (rv == 0 && !errno)) {
|
||||
/* The message didn't get it through. The upper
|
||||
level will have to re-send */
|
||||
return 0;
|
||||
} else {
|
||||
lprintf(LOG_ERR, "Serial response is invalid");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* this is needed for correct string to long conversion */
|
||||
str_hex[2] = 0;
|
||||
|
||||
/* parse the response */
|
||||
i = 0;
|
||||
j = 0;
|
||||
while (*p) {
|
||||
if (i >= len) {
|
||||
lprintf(LOG_ERR, "Serial response is too long(%d, %d)", i, len);
|
||||
return -1;
|
||||
}
|
||||
ch = *(p++);
|
||||
if (isxdigit(ch)) {
|
||||
str_hex[j++] = ch;
|
||||
} else {
|
||||
if (j == 1 || !isspace(ch)) {
|
||||
lprintf(LOG_ERR, "Serial response is invalid");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (j == 2) {
|
||||
unsigned long tmp;
|
||||
errno = 0;
|
||||
/* parse the hex number */
|
||||
tmp = strtoul(str_hex, NULL, 16);
|
||||
if ( tmp > 0xFF || ( !tmp && errno ) ) {
|
||||
lprintf(LOG_ERR, "Serial response is invalid");
|
||||
return -1;
|
||||
}
|
||||
data[i++] = tmp;
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate sequence number for tracking
|
||||
*/
|
||||
static uint8_t
|
||||
serial_term_alloc_seq(void)
|
||||
{
|
||||
static uint8_t seq = 0;
|
||||
if (++seq == 64) {
|
||||
seq = 0;
|
||||
}
|
||||
return seq;
|
||||
}
|
||||
|
||||
/*
|
||||
* Build IPMB message to be transmitted
|
||||
*/
|
||||
static int
|
||||
serial_term_build_msg(const struct ipmi_intf * intf,
|
||||
const struct ipmi_rq * req, uint8_t * msg, size_t max_len,
|
||||
struct serial_term_request_ctx * ctx, int * msg_len)
|
||||
{
|
||||
uint8_t * data = msg, seq;
|
||||
struct serial_term_hdr * term_hdr = (struct serial_term_hdr *) msg;
|
||||
struct ipmi_send_message_rq * outer_rq = NULL;
|
||||
struct ipmi_send_message_rq * inner_rq = NULL;
|
||||
int bridging_level;
|
||||
|
||||
/* acquire bridging level */
|
||||
if (intf->target_addr && intf->target_addr != intf->my_addr) {
|
||||
if (intf->transit_addr != 0) {
|
||||
bridging_level = 2;
|
||||
} else {
|
||||
bridging_level = 1;
|
||||
}
|
||||
} else {
|
||||
bridging_level = 0;
|
||||
}
|
||||
|
||||
/* check overall packet length */
|
||||
if(req->msg.data_len + 3 + bridging_level * 8 > max_len) {
|
||||
lprintf(LOG_ERR, "ipmitool: Message data is too long");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* allocate new sequence number */
|
||||
seq = serial_term_alloc_seq() << 2;
|
||||
|
||||
/* check for bridging */
|
||||
if (bridging_level) {
|
||||
/* compose terminal message header */
|
||||
term_hdr->netFn = 0x18;
|
||||
term_hdr->seq = seq;
|
||||
term_hdr->cmd = 0x34;
|
||||
|
||||
/* set pointer to send message request data */
|
||||
outer_rq = (struct ipmi_send_message_rq *) (term_hdr + 1);
|
||||
|
||||
if (bridging_level == 2) {
|
||||
/* compose the outer send message request */
|
||||
outer_rq->channel = intf->transit_channel | 0x40;
|
||||
outer_rq->msg.rsSA = intf->transit_addr;
|
||||
outer_rq->msg.netFn = 0x18;
|
||||
outer_rq->msg.csum1 = -(outer_rq->msg.rsSA + outer_rq->msg.netFn);
|
||||
outer_rq->msg.rqSA = intf->my_addr;
|
||||
outer_rq->msg.rqSeq = seq;
|
||||
outer_rq->msg.cmd = 0x34;
|
||||
|
||||
/* inner request is further */
|
||||
inner_rq = (outer_rq + 1);
|
||||
} else {
|
||||
/* there is only one header */
|
||||
inner_rq = outer_rq;
|
||||
}
|
||||
|
||||
/* compose the inner send message request */
|
||||
inner_rq->channel = intf->target_channel | 0x40;
|
||||
inner_rq->msg.rsSA = intf->target_addr;
|
||||
inner_rq->msg.netFn = (req->msg.netfn << 2) | req->msg.lun;
|
||||
inner_rq->msg.csum1 = -(inner_rq->msg.rsSA + inner_rq->msg.netFn);
|
||||
inner_rq->msg.rqSA = intf->my_addr;
|
||||
inner_rq->msg.rqSeq = seq;
|
||||
inner_rq->msg.cmd = req->msg.cmd;
|
||||
|
||||
/* check if interface is the system one */
|
||||
if (is_system) {
|
||||
/* need response to LUN 2 */
|
||||
outer_rq->msg.rqSeq |= 2;
|
||||
|
||||
/* do not track response */
|
||||
outer_rq->channel &= ~0x40;
|
||||
|
||||
/* restore BMC SA if bridging not to primary IPMB channel */
|
||||
if (outer_rq->channel) {
|
||||
outer_rq->msg.rqSA = IPMI_BMC_SLAVE_ADDR;
|
||||
}
|
||||
}
|
||||
|
||||
/* fill the second context */
|
||||
ctx[1].netFn = outer_rq->msg.netFn;
|
||||
ctx[1].sa = outer_rq->msg.rsSA;
|
||||
ctx[1].seq = outer_rq->msg.rqSeq;
|
||||
ctx[1].cmd = outer_rq->msg.cmd;
|
||||
|
||||
/* move write pointer */
|
||||
msg = (uint8_t *)(inner_rq + 1);
|
||||
} else {
|
||||
/* compose terminal message header */
|
||||
term_hdr->netFn = (req->msg.netfn << 2) | req->msg.lun;
|
||||
term_hdr->seq = seq;
|
||||
term_hdr->cmd = req->msg.cmd;
|
||||
|
||||
/* move write pointer */
|
||||
msg = (uint8_t *)(term_hdr + 1);
|
||||
}
|
||||
|
||||
/* fill the first context */
|
||||
ctx[0].netFn = term_hdr->netFn;
|
||||
ctx[0].seq = term_hdr->seq;
|
||||
ctx[0].cmd = term_hdr->cmd;
|
||||
|
||||
/* write request data */
|
||||
memcpy(msg, req->msg.data, req->msg.data_len);
|
||||
|
||||
/* move write pointer */
|
||||
msg += req->msg.data_len;
|
||||
|
||||
if (bridging_level) {
|
||||
/* write inner message checksum */
|
||||
*msg++ = ipmi_csum(&inner_rq->msg.rqSA, req->msg.data_len + 3);
|
||||
|
||||
/* check for double bridging */
|
||||
if (bridging_level == 2) {
|
||||
/* write outer message checksum */
|
||||
*msg++ = ipmi_csum(&outer_rq->msg.rqSA, 4);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* save message length */
|
||||
*msg_len = msg - data;
|
||||
|
||||
/* return bridging level */
|
||||
return bridging_level;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send message to serial port
|
||||
*/
|
||||
static int
|
||||
serial_term_send_msg(struct ipmi_intf * intf, uint8_t * msg, int msg_len)
|
||||
{
|
||||
int i, size, tmp = 0;
|
||||
uint8_t * buf, * data;
|
||||
|
||||
if (verbose > 3) {
|
||||
fprintf(stderr, "Sending request:\n");
|
||||
fprintf(stderr, " NetFN/rsLUN = 0x%x\n", msg[0]);
|
||||
fprintf(stderr, " rqSeq = 0x%x\n", msg[1]);
|
||||
fprintf(stderr, " cmd = 0x%x\n", msg[2]);
|
||||
if (msg_len > 7) {
|
||||
fprintf(stderr, " data_len = %d\n", msg_len - 3);
|
||||
fprintf(stderr, " data = %s\n",
|
||||
buf2str(msg + 3, msg_len - 3));
|
||||
}
|
||||
}
|
||||
|
||||
if (verbose > 4) {
|
||||
fprintf(stderr, "Message data:\n");
|
||||
fprintf(stderr, " %s\n", buf2str(msg, msg_len));
|
||||
}
|
||||
|
||||
/* calculate required buffer size */
|
||||
size = msg_len * 2 + 4;
|
||||
|
||||
/* allocate buffer for output data */
|
||||
buf = data = (uint8_t *) alloca(size);
|
||||
|
||||
if (!buf) {
|
||||
lperror(LOG_ERR, "ipmitool: alloca error");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* start character */
|
||||
*buf++ = '[';
|
||||
|
||||
/* body */
|
||||
for (i = 0; i < msg_len; i++) {
|
||||
buf += sprintf( buf, "%02x", msg[i]);
|
||||
}
|
||||
|
||||
/* stop character */
|
||||
*buf++ = ']';
|
||||
|
||||
/* carriage return */
|
||||
*buf++ = '\r';
|
||||
|
||||
/* line feed */
|
||||
*buf++ = '\n';
|
||||
|
||||
/* write data to serial port */
|
||||
tmp = write(intf->fd, data, size);
|
||||
if (tmp <= 0) {
|
||||
lperror(LOG_ERR, "ipmitool: write error");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for request response
|
||||
*/
|
||||
static int
|
||||
serial_term_wait_response(struct ipmi_intf * intf,
|
||||
struct serial_term_request_ctx * req_ctx,
|
||||
uint8_t * msg, size_t max_len)
|
||||
{
|
||||
struct serial_term_hdr * hdr = (struct serial_term_hdr *) msg;
|
||||
int msg_len;
|
||||
|
||||
/* wait for response(s) */
|
||||
do {
|
||||
/* receive message */
|
||||
msg_len = recv_response(intf, msg, max_len);
|
||||
|
||||
/* check if valid message received */
|
||||
if (msg_len > 0) {
|
||||
/* validate message size */
|
||||
if (msg_len < 4) {
|
||||
/* either bad response or non-related message */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* check for the waited response */
|
||||
if (hdr->netFn == (req_ctx->netFn|4)
|
||||
&& (hdr->seq & ~3) == req_ctx->seq
|
||||
&& hdr->cmd == req_ctx->cmd) {
|
||||
/* check if something new has been parsed */
|
||||
if (verbose > 3) {
|
||||
fprintf(stderr, "Got response:\n");
|
||||
fprintf(stderr, " NetFN/rsLUN = 0x%x\n", msg[0]);
|
||||
fprintf(stderr, " rqSeq/Bridge = 0x%x\n", msg[1]);
|
||||
fprintf(stderr, " cmd = 0x%x\n", msg[2]);
|
||||
fprintf(stderr, " completion code = 0x%x\n", msg[3]);
|
||||
if (msg_len > 8) {
|
||||
fprintf(stderr, " data_len = %d\n",
|
||||
msg_len - 4);
|
||||
fprintf(stderr, " data = %s\n",
|
||||
buf2str(msg + 4, msg_len - 4));
|
||||
}
|
||||
}
|
||||
|
||||
/* move to start from completion code */
|
||||
memmove(msg, hdr + 1, msg_len - sizeof (*hdr));
|
||||
|
||||
/* the waited one */
|
||||
return msg_len - sizeof (*hdr);
|
||||
}
|
||||
}
|
||||
} while (msg_len > 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get message from receive message queue
|
||||
*/
|
||||
static int
|
||||
serial_term_get_message(struct ipmi_intf * intf,
|
||||
struct serial_term_request_ctx * req_ctx,
|
||||
uint8_t * msg, size_t max_len)
|
||||
{
|
||||
uint8_t data[IPMI_SERIAL_MAX_RESPONSE];
|
||||
struct serial_term_request_ctx tmp_ctx;
|
||||
struct ipmi_get_message_rp * rp = (struct ipmi_get_message_rp *) data;
|
||||
struct serial_term_hdr hdr;
|
||||
clock_t start, tm;
|
||||
int rv, netFn, rqSeq;
|
||||
|
||||
start = clock();
|
||||
|
||||
do {
|
||||
/* fill-in request context */
|
||||
tmp_ctx.netFn = 0x18;
|
||||
tmp_ctx.seq = serial_term_alloc_seq() << 2;
|
||||
tmp_ctx.cmd = 0x33;
|
||||
|
||||
/* fill-in request data */
|
||||
hdr.netFn = tmp_ctx.netFn;
|
||||
hdr.seq = tmp_ctx.seq;
|
||||
hdr.cmd = tmp_ctx.cmd;
|
||||
|
||||
/* send request */
|
||||
serial_flush(intf);
|
||||
serial_term_send_msg(intf, (uint8_t *) &hdr, 3);
|
||||
|
||||
/* wait for response */
|
||||
rv = serial_term_wait_response(intf, &tmp_ctx, data, sizeof (data));
|
||||
|
||||
/* check for IO error or timeout */
|
||||
if (rv <= 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
netFn = (req_ctx->netFn & ~3)|(req_ctx->seq & 3)|4;
|
||||
rqSeq = req_ctx->seq & ~3;
|
||||
|
||||
/* check completion code */
|
||||
if (rp->completion == 0) {
|
||||
/* check for the waited response */
|
||||
if (rp->netFn == netFn
|
||||
&& rp->rsSA == req_ctx->sa
|
||||
&& rp->rqSeq == rqSeq
|
||||
&& rp->cmd == req_ctx->cmd) {
|
||||
/* copy the rest of message */
|
||||
memcpy(msg, rp + 1, rv - sizeof (*rp) - 1);
|
||||
return rv - sizeof (*rp) - 1;
|
||||
}
|
||||
} else if (rp->completion != 0x80) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
tm = clock() - start;
|
||||
|
||||
tm /= CLOCKS_PER_SEC;
|
||||
} while (tm < intf->session->timeout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ipmi_rs *
|
||||
ipmi_serial_term_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
|
||||
{
|
||||
static struct ipmi_rs rsp;
|
||||
uint8_t msg[IPMI_SERIAL_MAX_RESPONSE], * resp = msg;
|
||||
struct serial_term_request_ctx req_ctx[2];
|
||||
int retry, rv, msg_len, bridging_level;
|
||||
|
||||
if (!intf->opened && intf->open && intf->open(intf) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Send the message and receive the answer */
|
||||
for (retry = 0; retry < intf->session->retry; retry++) {
|
||||
/* build output message */
|
||||
bridging_level = serial_term_build_msg(intf, req, msg,
|
||||
sizeof (msg), req_ctx, &msg_len);
|
||||
if (msg_len < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* send request */
|
||||
serial_flush(intf);
|
||||
serial_term_send_msg(intf, msg, msg_len);
|
||||
|
||||
/* wait for response */
|
||||
rv = serial_term_wait_response(intf, &req_ctx[0], msg, sizeof (msg));
|
||||
|
||||
/* check for IO error */
|
||||
if (rv < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* check for timeout */
|
||||
if (rv == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* check for bridging */
|
||||
if (bridging_level && msg[0] == 0) {
|
||||
/* in the case of payload interface we check receive message queue */
|
||||
if (is_system) {
|
||||
/* check message flags */
|
||||
rv = serial_term_get_message(intf, &req_ctx[1],
|
||||
msg, sizeof (msg));
|
||||
|
||||
/* check for IO error */
|
||||
if (rv < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* check for timeout */
|
||||
if (rv == 0) {
|
||||
continue;
|
||||
}
|
||||
/* check if response for inner request is not encapsulated */
|
||||
} else if (rv == 1) {
|
||||
/* wait for response for inner request */
|
||||
rv = serial_term_wait_response(intf, &req_ctx[1],
|
||||
msg, sizeof (msg));
|
||||
|
||||
/* check for IO error */
|
||||
if (rv < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* check for timeout */
|
||||
if (rv == 0) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
/* skip outer level header */
|
||||
resp = msg + sizeof (struct ipmb_msg_hdr) + 1;
|
||||
/* decrement response size */
|
||||
rv -= + sizeof (struct ipmb_msg_hdr) + 2;
|
||||
}
|
||||
|
||||
/* check response size */
|
||||
if (resp[0] == 0 && bridging_level == 2 && rv < 8) {
|
||||
lprintf(LOG_ERR, "ipmitool: Message response is too short");
|
||||
/* invalid message length */
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* check for double bridging */
|
||||
if (bridging_level == 2 && resp[0] == 0) {
|
||||
/* get completion code */
|
||||
rsp.ccode = resp[7];
|
||||
rsp.data_len = rv - 9;
|
||||
memcpy(rsp.data, resp + 8, rsp.data_len);
|
||||
} else {
|
||||
rsp.ccode = resp[0];
|
||||
rsp.data_len = rv - 1;
|
||||
memcpy(rsp.data, resp + 1, rsp.data_len);
|
||||
}
|
||||
|
||||
/* return response */
|
||||
return &rsp;
|
||||
}
|
||||
|
||||
/* no valid response */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
ipmi_serial_term_setup(struct ipmi_intf * intf)
|
||||
{
|
||||
intf->session = malloc(sizeof(struct ipmi_session));
|
||||
if (intf->session == NULL) {
|
||||
lprintf(LOG_ERR, "ipmitool: malloc failure");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(intf->session, 0, sizeof(struct ipmi_session));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ipmi_serial_term_set_my_addr(struct ipmi_intf * intf, uint8_t addr)
|
||||
{
|
||||
intf->my_addr = addr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ipmi_intf ipmi_serial_term_intf = {
|
||||
name: "serial-terminal",
|
||||
desc: "Serial Interface, Terminal Mode",
|
||||
setup: ipmi_serial_term_setup,
|
||||
open: ipmi_serial_term_open,
|
||||
close: ipmi_serial_term_close,
|
||||
sendrecv: ipmi_serial_term_send_cmd,
|
||||
set_my_addr:ipmi_serial_term_set_my_addr
|
||||
};
|
||||
Reference in New Issue
Block a user