mirror of
https://github.com/ipmitool/ipmitool.git
synced 2025-05-10 18:47:22 +00:00
ID: 44 - dummy interface support - fake-ipmistack project
Commit adds support for a 'dummy' interface in order to communicate with fake-ipmistack.
This commit is contained in:
parent
c7412e5815
commit
efdeb12724
@ -60,6 +60,7 @@ xenable_intf_imb=yes
|
||||
xenable_intf_open=yes
|
||||
xenable_intf_lipmi=yes
|
||||
#xenable_intf_serial=yes
|
||||
xenable_intf_dummy=no
|
||||
xenable_all_options=yes
|
||||
xenable_ipmishell=yes
|
||||
|
||||
@ -503,6 +504,18 @@ if test "x$xenable_intf_bmc" = "xyes"; then
|
||||
IPMITOOL_INTF_LIB="$IPMITOOL_INTF_LIB bmc/libintf_bmc.la"
|
||||
fi
|
||||
|
||||
dnl enable Dummy interface for testing
|
||||
AC_ARG_ENABLE([intf-dummy],
|
||||
[AC_HELP_STRING([--enable-intf-dummy],
|
||||
[enable Dummy(test) interface [default=no]])],
|
||||
[xenable_intf_dummy=$enableval], [xenable_intf_dummy=no])
|
||||
if test "x$xenable_intf_dummy" = "xyes"; then
|
||||
AC_DEFINE(IPMI_INTF_DUMMY, [1], [Define to 1 to enable Dummy interface.])
|
||||
AC_SUBST(INTF_DUMMY, [dummy])
|
||||
AC_SUBST(INTF_DUMMY_LIB, [libintf_dummy.la])
|
||||
IPMITOOL_INTF_LIB="$IPMITOOL_INTF_LIB dummy/libintf_dummy.la"
|
||||
fi
|
||||
|
||||
AC_SUBST(IPMITOOL_INTF_LIB)
|
||||
|
||||
if test "x$xenable_ipmishell" = "xyes"; then
|
||||
@ -602,7 +615,8 @@ AC_CONFIG_FILES([Makefile
|
||||
src/plugins/imb/Makefile
|
||||
src/plugins/bmc/Makefile
|
||||
src/plugins/lipmi/Makefile
|
||||
src/plugins/serial/Makefile])
|
||||
src/plugins/serial/Makefile
|
||||
src/plugins/dummy/Makefile])
|
||||
|
||||
AC_OUTPUT
|
||||
|
||||
@ -618,6 +632,7 @@ AC_MSG_RESULT([ imb : $xenable_intf_imb])
|
||||
AC_MSG_RESULT([ bmc : $xenable_intf_bmc])
|
||||
AC_MSG_RESULT([ lipmi : $xenable_intf_lipmi])
|
||||
AC_MSG_RESULT([ serial : $xenable_intf_serial])
|
||||
AC_MSG_RESULT([ dummy : $xenable_intf_dummy])
|
||||
AC_MSG_RESULT([])
|
||||
AC_MSG_RESULT([Extra tools])
|
||||
AC_MSG_RESULT([ ipmievd : yes])
|
||||
|
@ -32,8 +32,8 @@ 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@
|
||||
DIST_SUBDIRS = lan lanplus open lipmi imb bmc free serial
|
||||
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
|
||||
|
8
ipmitool/src/plugins/dummy/Makefile.am
Normal file
8
ipmitool/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
ipmitool/src/plugins/dummy/dummy.c
Normal file
286
ipmitool/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
ipmitool/src/plugins/dummy/dummy.h
Normal file
30
ipmitool/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
|
@ -66,6 +66,9 @@ extern struct ipmi_intf ipmi_free_intf;
|
||||
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
|
||||
@ -92,6 +95,9 @@ struct ipmi_intf * ipmi_intf_table[] = {
|
||||
#ifdef IPMI_INTF_SERIAL
|
||||
&ipmi_serial_term_intf,
|
||||
&ipmi_serial_bm_intf,
|
||||
#endif
|
||||
#ifdef IPMI_INTF_DUMMY
|
||||
&ipmi_dummy_intf,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user