mirror of
https://github.com/ipmitool/ipmitool.git
synced 2025-05-11 19:17:22 +00:00
now has an option to daemonize and log SEL events to syslog
This commit is contained in:
parent
dd8b1806b5
commit
68be9c40e6
@ -45,10 +45,16 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/poll.h>
|
#include <sys/poll.h>
|
||||||
|
|
||||||
#include <linux/ipmi.h>
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_OPENIPMI_H
|
||||||
|
# include <linux/ipmi.h>
|
||||||
|
#else
|
||||||
|
# include "plugins/open/open.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <ipmitool/helper.h>
|
#include <ipmitool/helper.h>
|
||||||
|
#include <ipmitool/log.h>
|
||||||
#include <ipmitool/ipmi.h>
|
#include <ipmitool/ipmi.h>
|
||||||
#include <ipmitool/ipmi_intf.h>
|
#include <ipmitool/ipmi_intf.h>
|
||||||
#include <ipmitool/ipmi_sel.h>
|
#include <ipmitool/ipmi_sel.h>
|
||||||
@ -57,6 +63,66 @@ extern int errno;
|
|||||||
int verbose = 0;
|
int verbose = 0;
|
||||||
int csv_output = 0;
|
int csv_output = 0;
|
||||||
|
|
||||||
|
static void daemonize(void)
|
||||||
|
{
|
||||||
|
pid_t pid;
|
||||||
|
int fd;
|
||||||
|
sigset_t sighup;
|
||||||
|
|
||||||
|
/* if we are started from init no need to become daemon */
|
||||||
|
if (getppid() == 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
#ifdef SIGHUP
|
||||||
|
sigemptyset(&sighup);
|
||||||
|
sigaddset(&sighup, SIGHUP);
|
||||||
|
if (sigprocmask(SIG_UNBLOCK, &sighup, nil) < 0)
|
||||||
|
fprintf(stderr, "ERROR: could not unblock SIGHUP signal\n");
|
||||||
|
SIG_IGNORE(SIGHUP);
|
||||||
|
#endif
|
||||||
|
#ifdef SIGTTOU
|
||||||
|
SIG_IGNORE(SIGTTOU);
|
||||||
|
#endif
|
||||||
|
#ifdef SIGTTIN
|
||||||
|
SIG_IGNORE(SIGTTIN);
|
||||||
|
#endif
|
||||||
|
#ifdef SIGQUIT
|
||||||
|
SIG_IGNORE(SIGQUIT);
|
||||||
|
#endif
|
||||||
|
#ifdef SIGTSTP
|
||||||
|
SIG_IGNORE(SIGTSTP);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pid = (pid_t) fork();
|
||||||
|
if (pid < 0 || pid > 0)
|
||||||
|
exit(0);
|
||||||
|
|
||||||
|
#if defined(SIGTSTP) && defined(TIOCNOTTY)
|
||||||
|
if (setpgid(0, getpid()) == -1)
|
||||||
|
exit(1);
|
||||||
|
if ((fd = open(_PATH_TTY, O_RDWR)) >= 0) {
|
||||||
|
ioctl(fd, TIOCNOTTY, NULL);
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (setpgrp() == -1)
|
||||||
|
exit(1);
|
||||||
|
pid = (pid_t) fork();
|
||||||
|
if (pid < 0 || pid > 0)
|
||||||
|
exit(0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
chdir("/");
|
||||||
|
umask(0);
|
||||||
|
|
||||||
|
for (fd=0; fd<64; fd++)
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
open("/dev/null", O_RDWR);
|
||||||
|
dup(0);
|
||||||
|
dup(0);
|
||||||
|
}
|
||||||
|
|
||||||
static int enable_event_msg_buffer(struct ipmi_intf * intf)
|
static int enable_event_msg_buffer(struct ipmi_intf * intf)
|
||||||
{
|
{
|
||||||
struct ipmi_rs * rsp;
|
struct ipmi_rs * rsp;
|
||||||
@ -71,7 +137,7 @@ static int enable_event_msg_buffer(struct ipmi_intf * intf)
|
|||||||
|
|
||||||
rsp = intf->sendrecv(intf, &req);
|
rsp = intf->sendrecv(intf, &req);
|
||||||
if (!rsp || rsp->ccode) {
|
if (!rsp || rsp->ccode) {
|
||||||
printf("ERROR:%x Get BMC Global Enables command\n",
|
lprintf(LOG_WARNING, "Get BMC Global Enables command filed [ccode %02x]",
|
||||||
rsp ? rsp->ccode : 0);
|
rsp ? rsp->ccode : 0);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -83,17 +149,38 @@ static int enable_event_msg_buffer(struct ipmi_intf * intf)
|
|||||||
|
|
||||||
rsp = intf->sendrecv(intf, &req);
|
rsp = intf->sendrecv(intf, &req);
|
||||||
if (!rsp || rsp->ccode) {
|
if (!rsp || rsp->ccode) {
|
||||||
printf("ERROR:%x Set BMC Global Enables command\n",
|
lprintf(LOG_WARNING, "Set BMC Global Enables command failed [ccode %02x]",
|
||||||
rsp ? rsp->ccode : 0);
|
rsp ? rsp->ccode : 0);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbose)
|
lprintf(LOG_DEBUG, "BMC Event Message Buffer enabled");
|
||||||
printf("BMC Event Message Buffer enabled.\n");
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void log_event(struct sel_event_record * evt)
|
||||||
|
{
|
||||||
|
char *desc;
|
||||||
|
|
||||||
|
if (!evt)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (evt->record_type == 0xf0)
|
||||||
|
lprintf(LOG_ALERT, "Linux kernel panic: %.11s", (char *) evt + 5);
|
||||||
|
else if (evt->record_type >= 0xc0)
|
||||||
|
lprintf(LOG_NOTICE, "IPMI Event OEM Record %02x", evt->record_type);
|
||||||
|
else {
|
||||||
|
ipmi_get_event_desc(evt, &desc);
|
||||||
|
if (desc) {
|
||||||
|
lprintf(LOG_NOTICE, "%s Sensor %02x - %s",
|
||||||
|
ipmi_sel_get_sensor_type(evt->sensor_type),
|
||||||
|
evt->sensor_num, desc);
|
||||||
|
free(desc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void read_event(struct ipmi_intf * intf)
|
static void read_event(struct ipmi_intf * intf)
|
||||||
{
|
{
|
||||||
struct ipmi_addr addr;
|
struct ipmi_addr addr;
|
||||||
@ -108,125 +195,121 @@ static void read_event(struct ipmi_intf * intf)
|
|||||||
|
|
||||||
rv = ioctl(intf->fd, IPMICTL_RECEIVE_MSG_TRUNC, &recv);
|
rv = ioctl(intf->fd, IPMICTL_RECEIVE_MSG_TRUNC, &recv);
|
||||||
if (rv < 0) {
|
if (rv < 0) {
|
||||||
if (errno == EINTR)
|
switch (errno) {
|
||||||
/* abort */
|
case EINTR:
|
||||||
return;
|
return; /* abort */
|
||||||
if (errno == EMSGSIZE) {
|
case EMSGSIZE:
|
||||||
/* message truncated */
|
recv.msg.data_len = sizeof(data); /* truncated */
|
||||||
recv.msg.data_len = sizeof(data);
|
break;
|
||||||
} else {
|
default:
|
||||||
printf("ERROR: receiving IPMI message: %s\n",
|
lperror(LOG_ERR, "Unable to receive IPMI message");
|
||||||
strerror(errno));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!recv.msg.data || recv.msg.data_len == 0) {
|
if (!recv.msg.data || recv.msg.data_len == 0) {
|
||||||
printf("ERROR: No data in event!\n");
|
lprintf(LOG_ERR, "No data in event");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbose > 1) {
|
|
||||||
printf(" type = %d\n", recv.recv_type);
|
|
||||||
printf(" channel = 0x%x\n", addr.channel);
|
|
||||||
printf(" msgid = %ld\n", recv.msgid);
|
|
||||||
printf(" netfn = 0x%x\n", recv.msg.netfn);
|
|
||||||
printf(" cmd = 0x%x\n", recv.msg.cmd);
|
|
||||||
printf(" data_len = %d\n", recv.msg.data_len);
|
|
||||||
printbuf(recv.msg.data, recv.msg.data_len, "data");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (recv.recv_type != IPMI_ASYNC_EVENT_RECV_TYPE) {
|
if (recv.recv_type != IPMI_ASYNC_EVENT_RECV_TYPE) {
|
||||||
printf("ERROR: Not an event!\n");
|
lprintf(LOG_ERR, "Type %x is not an event", recv.recv_type);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbose)
|
lprintf(LOG_DEBUG, "netfn:%x cmd:%x ccode:%d",
|
||||||
ipmi_sel_print_std_entry_verbose((struct sel_event_record *)recv.msg.data);
|
recv.msg.netfn, recv.msg.cmd, recv.msg.data[0]);
|
||||||
else
|
|
||||||
ipmi_sel_print_std_entry((struct sel_event_record *)recv.msg.data);
|
log_event((struct sel_event_record *)recv.msg.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_exit(struct ipmi_intf * intf, int rv)
|
static int do_exit(struct ipmi_intf * intf, int rv)
|
||||||
{
|
{
|
||||||
if (intf)
|
if (intf)
|
||||||
intf->close(intf);
|
intf->close(intf);
|
||||||
ipmi_intf_exit();
|
log_halt();
|
||||||
exit(rv);
|
exit(rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usage(void)
|
static void usage(void)
|
||||||
{
|
{
|
||||||
printf("usage: ipmievd [-hv]\n");
|
fprintf(stderr, "usage: ipmievd [-hvd]\n");
|
||||||
printf("\n");
|
fprintf(stderr, "\n");
|
||||||
printf(" -h This help\n");
|
fprintf(stderr, " -h This help\n");
|
||||||
printf(" -v Verbose (can use multiple times)\n");
|
fprintf(stderr, " -v Verbose (can use multiple times)\n");
|
||||||
printf("\n");
|
fprintf(stderr, " -s Do NOT daemonize\n");
|
||||||
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char ** argv)
|
int main(int argc, char ** argv)
|
||||||
{
|
{
|
||||||
struct ipmi_intf * intf;
|
struct ipmi_intf * intf;
|
||||||
int r, i=1, a;
|
int r, a;
|
||||||
|
int i = 1;
|
||||||
|
int daemon = 1;
|
||||||
struct pollfd pfd;
|
struct pollfd pfd;
|
||||||
|
|
||||||
while ((a = getopt(argc, (char **)argv, "hv")) != -1) {
|
/* make sure we have UID 0 */
|
||||||
|
if (geteuid() || getuid()) {
|
||||||
|
fprintf(stderr, "Inadequate privledges\n");
|
||||||
|
do_exit(NULL, EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((a = getopt(argc, (char **)argv, "hvs")) != -1) {
|
||||||
switch (a) {
|
switch (a) {
|
||||||
case 'h':
|
case 'h':
|
||||||
usage();
|
usage();
|
||||||
|
do_exit(NULL, EXIT_SUCCESS);
|
||||||
break;
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
verbose++;
|
verbose++;
|
||||||
break;
|
break;
|
||||||
|
case 's':
|
||||||
|
daemon = 0;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
usage();
|
usage();
|
||||||
|
do_exit(NULL, EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbose)
|
if (daemon)
|
||||||
printf("Loading OpenIPMI interface plugin.\n");
|
daemonize();
|
||||||
|
|
||||||
/* init interface plugin support */
|
log_init("ipmievd", daemon, verbose);
|
||||||
r = ipmi_intf_init();
|
|
||||||
if (r < 0) {
|
|
||||||
printf("ERROR: Unable to initialize plugin interface\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* load interface plugin */
|
/* load interface */
|
||||||
intf = ipmi_intf_load("intf_open");
|
lprintf(LOG_DEBUG, "Loading OpenIPMI interface");
|
||||||
|
intf = ipmi_intf_load("open");
|
||||||
if (!intf) {
|
if (!intf) {
|
||||||
printf("ERROR: unable to load OpenIPMI interface plugin\n");
|
lprintf(LOG_ERR, "Unable to load OpenIPMI interface");
|
||||||
exit(EXIT_FAILURE);
|
do_exit(NULL, EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbose)
|
|
||||||
printf("Connecting to OpenIPMI device.\n");
|
|
||||||
|
|
||||||
/* open connection to openipmi device */
|
/* open connection to openipmi device */
|
||||||
|
lprintf(LOG_DEBUG, "Connecting to OpenIPMI device");
|
||||||
r = intf->open(intf);
|
r = intf->open(intf);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
printf("ERROR: Unable to open OpenIPMI device\n");
|
lprintf(LOG_ERR, "Unable to open OpenIPMI device");
|
||||||
exit(EXIT_FAILURE);
|
do_exit(NULL, EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* enable event message buffer */
|
/* enable event message buffer */
|
||||||
|
lprintf(LOG_DEBUG, "Enabling event message buffer");
|
||||||
r = enable_event_msg_buffer(intf);
|
r = enable_event_msg_buffer(intf);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
printf("ERROR: Unable to enable event message buffer.\n");
|
lprintf(LOG_ERR, "Could not enable event message buffer");
|
||||||
do_exit(intf, EXIT_FAILURE);
|
do_exit(intf, EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbose)
|
|
||||||
printf("Enabling event receiver.\n");
|
|
||||||
|
|
||||||
/* enable OpenIPMI event receiver */
|
/* enable OpenIPMI event receiver */
|
||||||
if (ioctl(intf->fd, IPMICTL_SET_GETS_EVENTS_CMD, &i)) {
|
lprintf(LOG_DEBUG, "Enabling event receiver");
|
||||||
perror("ERROR: Could not enable event receiver");
|
r = ioctl(intf->fd, IPMICTL_SET_GETS_EVENTS_CMD, &i);
|
||||||
|
if (r != 0) {
|
||||||
|
lperror(LOG_ERR, "Could not enable event receiver");
|
||||||
do_exit(intf, EXIT_FAILURE);
|
do_exit(intf, EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("ipmievd loaded, waiting for events...\n");
|
lprintf(LOG_NOTICE, "Waiting for events...");
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
pfd.fd = intf->fd; /* wait on openipmi device */
|
pfd.fd = intf->fd; /* wait on openipmi device */
|
||||||
@ -238,7 +321,7 @@ int main(int argc, char ** argv)
|
|||||||
/* timeout is disabled */
|
/* timeout is disabled */
|
||||||
break;
|
break;
|
||||||
case -1:
|
case -1:
|
||||||
perror("ERROR: poll operation failed");
|
lperror(LOG_CRIT, "Unable to read from IPMI device");
|
||||||
do_exit(intf, EXIT_FAILURE);
|
do_exit(intf, EXIT_FAILURE);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -247,8 +330,6 @@ int main(int argc, char ** argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbose)
|
lprintf(LOG_DEBUG, "Shutting down...");
|
||||||
printf("Exiting.\n");
|
|
||||||
|
|
||||||
do_exit(intf, EXIT_SUCCESS);
|
do_exit(intf, EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user