|
Packit Service |
ed0f68 |
/*
|
|
Packit Service |
ed0f68 |
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
|
|
Packit Service |
ed0f68 |
*
|
|
Packit Service |
ed0f68 |
* Redistribution and use in source and binary forms, with or without
|
|
Packit Service |
ed0f68 |
* modification, are permitted provided that the following conditions
|
|
Packit Service |
ed0f68 |
* are met:
|
|
Packit Service |
ed0f68 |
*
|
|
Packit Service |
ed0f68 |
* Redistribution of source code must retain the above copyright
|
|
Packit Service |
ed0f68 |
* notice, this list of conditions and the following disclaimer.
|
|
Packit Service |
ed0f68 |
*
|
|
Packit Service |
ed0f68 |
* Redistribution in binary form must reproduce the above copyright
|
|
Packit Service |
ed0f68 |
* notice, this list of conditions and the following disclaimer in the
|
|
Packit Service |
ed0f68 |
* documentation and/or other materials provided with the distribution.
|
|
Packit Service |
ed0f68 |
*
|
|
Packit Service |
ed0f68 |
* Neither the name of Sun Microsystems, Inc. or the names of
|
|
Packit Service |
ed0f68 |
* contributors may be used to endorse or promote products derived
|
|
Packit Service |
ed0f68 |
* from this software without specific prior written permission.
|
|
Packit Service |
ed0f68 |
*
|
|
Packit Service |
ed0f68 |
* This software is provided "AS IS," without a warranty of any kind.
|
|
Packit Service |
ed0f68 |
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
|
Packit Service |
ed0f68 |
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
|
Packit Service |
ed0f68 |
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
|
Packit Service |
ed0f68 |
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
|
|
Packit Service |
ed0f68 |
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
|
Packit Service |
ed0f68 |
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
|
|
Packit Service |
ed0f68 |
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
|
|
Packit Service |
ed0f68 |
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
|
|
Packit Service |
ed0f68 |
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
|
|
Packit Service |
ed0f68 |
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
|
Packit Service |
ed0f68 |
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
|
Packit Service |
ed0f68 |
*/
|
|
Packit Service |
ed0f68 |
#define _XOPEN_SOURCE 700
|
|
Packit Service |
ed0f68 |
#define _BSD_SOURCE
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
#include <stdio.h>
|
|
Packit Service |
ed0f68 |
#include <fcntl.h>
|
|
Packit Service |
ed0f68 |
#include <unistd.h>
|
|
Packit Service |
ed0f68 |
#include <sys/ioctl.h>
|
|
Packit Service |
ed0f68 |
#include <errno.h>
|
|
Packit Service |
ed0f68 |
#include <stdlib.h>
|
|
Packit Service |
ed0f68 |
#include <inttypes.h>
|
|
Packit Service |
ed0f68 |
#include <string.h>
|
|
Packit Service |
ed0f68 |
#include <sys/types.h>
|
|
Packit Service |
ed0f68 |
#include <sys/stat.h>
|
|
Packit Service |
ed0f68 |
#include <signal.h>
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
#if defined(HAVE_CONFIG_H)
|
|
Packit Service |
ed0f68 |
# include <config.h>
|
|
Packit Service |
ed0f68 |
#endif
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
#if defined(HAVE_SYS_IOCCOM_H)
|
|
Packit Service |
ed0f68 |
# include <sys/ioccom.h>
|
|
Packit Service |
ed0f68 |
#endif
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
#ifdef HAVE_PATHS_H
|
|
Packit Service |
ed0f68 |
# include <paths.h>
|
|
Packit Service |
ed0f68 |
#endif
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
#ifndef _PATH_VARRUN
|
|
Packit Service |
ed0f68 |
# define _PATH_VARRUN "/var/run/"
|
|
Packit Service |
ed0f68 |
#endif
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
#ifdef IPMI_INTF_OPEN
|
|
Packit Service |
ed0f68 |
# if defined(HAVE_OPENIPMI_H)
|
|
Packit Service |
ed0f68 |
# if defined(HAVE_LINUX_COMPILER_H)
|
|
Packit Service |
ed0f68 |
# include <linux/compiler.h>
|
|
Packit Service |
ed0f68 |
# endif
|
|
Packit Service |
ed0f68 |
# include <linux/ipmi.h>
|
|
Packit Service |
ed0f68 |
# elif defined(HAVE_FREEBSD_IPMI_H)
|
|
Packit Service |
ed0f68 |
# include <sys/ipmi.h>
|
|
Packit Service |
ed0f68 |
# else
|
|
Packit Service |
ed0f68 |
# include "plugins/open/open.h"
|
|
Packit Service |
ed0f68 |
# endif
|
|
Packit Service |
ed0f68 |
# include <poll.h>
|
|
Packit Service |
ed0f68 |
#endif /* IPMI_INTF_OPEN */
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
#include <ipmitool/helper.h>
|
|
Packit Service |
ed0f68 |
#include <ipmitool/log.h>
|
|
Packit Service |
ed0f68 |
#include <ipmitool/ipmi.h>
|
|
Packit Service |
ed0f68 |
#include <ipmitool/ipmi_intf.h>
|
|
Packit Service |
ed0f68 |
#include <ipmitool/ipmi_sel.h>
|
|
Packit Service |
ed0f68 |
#include <ipmitool/ipmi_sdr.h>
|
|
Packit Service |
ed0f68 |
#include <ipmitool/ipmi_strings.h>
|
|
Packit Service |
ed0f68 |
#include <ipmitool/ipmi_main.h>
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
#define WARNING_THRESHOLD 80
|
|
Packit Service |
ed0f68 |
#define DEFAULT_PIDFILE _PATH_VARRUN "ipmievd.pid"
|
|
Packit Service |
ed0f68 |
char pidfile[64];
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
/* global variables */
|
|
Packit Service |
ed0f68 |
int verbose = 0;
|
|
Packit Service |
ed0f68 |
int csv_output = 0;
|
|
Packit Service |
ed0f68 |
uint16_t selwatch_count = 0; /* number of entries in the SEL */
|
|
Packit Service |
ed0f68 |
uint16_t selwatch_lastid = 0; /* current last entry in the SEL */
|
|
Packit Service |
ed0f68 |
int selwatch_pctused = 0; /* current percent usage in the SEL */
|
|
Packit Service |
ed0f68 |
int selwatch_overflow = 0; /* SEL overflow */
|
|
Packit Service |
ed0f68 |
int selwatch_timeout = 10; /* default to 10 seconds */
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
/* event interface definition */
|
|
Packit Service |
ed0f68 |
struct ipmi_event_intf {
|
|
Packit Service |
ed0f68 |
char name[16];
|
|
Packit Service |
ed0f68 |
char desc[128];
|
|
Packit Service |
ed0f68 |
char prefix[72];
|
|
Packit Service |
ed0f68 |
int (*setup)(struct ipmi_event_intf * eintf);
|
|
Packit Service |
ed0f68 |
int (*wait)(struct ipmi_event_intf * eintf);
|
|
Packit Service |
ed0f68 |
int (*read)(struct ipmi_event_intf * eintf);
|
|
Packit Service |
ed0f68 |
int (*check)(struct ipmi_event_intf * eintf);
|
|
Packit Service |
ed0f68 |
void (*log)(struct ipmi_event_intf * eintf, struct sel_event_record * evt);
|
|
Packit Service |
ed0f68 |
struct ipmi_intf * intf;
|
|
Packit Service |
ed0f68 |
};
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
/* Data from SEL we are interested in */
|
|
Packit Service |
ed0f68 |
typedef struct sel_data {
|
|
Packit Service |
ed0f68 |
uint16_t entries;
|
|
Packit Service |
ed0f68 |
int pctused;
|
|
Packit Service |
ed0f68 |
int overflow;
|
|
Packit Service |
ed0f68 |
} sel_data;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
static void log_event(struct ipmi_event_intf * eintf, struct sel_event_record * evt);
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
/* ~~~~~~~~~~~~~~~~~~~~~~ openipmi ~~~~~~~~~~~~~~~~~~~~ */
|
|
Packit Service |
ed0f68 |
#ifdef IPMI_INTF_OPEN
|
|
Packit Service |
ed0f68 |
static int openipmi_setup(struct ipmi_event_intf * eintf);
|
|
Packit Service |
ed0f68 |
static int openipmi_wait(struct ipmi_event_intf * eintf);
|
|
Packit Service |
ed0f68 |
static int openipmi_read(struct ipmi_event_intf * eintf);
|
|
Packit Service |
ed0f68 |
static struct ipmi_event_intf openipmi_event_intf = {
|
|
Packit Service |
ed0f68 |
.name = "open",
|
|
Packit Service |
ed0f68 |
.desc = "OpenIPMI asyncronous notification of events",
|
|
Packit Service |
ed0f68 |
.prefix = "",
|
|
Packit Service |
ed0f68 |
.setup = openipmi_setup,
|
|
Packit Service |
ed0f68 |
.wait = openipmi_wait,
|
|
Packit Service |
ed0f68 |
.read = openipmi_read,
|
|
Packit Service |
ed0f68 |
.log = log_event,
|
|
Packit Service |
ed0f68 |
};
|
|
Packit Service |
ed0f68 |
#endif
|
|
Packit Service |
ed0f68 |
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
/* ~~~~~~~~~~~~~~~~~~~~~~ selwatch ~~~~~~~~~~~~~~~~~~~~ */
|
|
Packit Service |
ed0f68 |
static int selwatch_setup(struct ipmi_event_intf * eintf);
|
|
Packit Service |
ed0f68 |
static int selwatch_wait(struct ipmi_event_intf * eintf);
|
|
Packit Service |
ed0f68 |
static int selwatch_read(struct ipmi_event_intf * eintf);
|
|
Packit Service |
ed0f68 |
static int selwatch_check(struct ipmi_event_intf * eintf);
|
|
Packit Service |
ed0f68 |
static struct ipmi_event_intf selwatch_event_intf = {
|
|
Packit Service |
ed0f68 |
.name = "sel",
|
|
Packit Service |
ed0f68 |
.desc = "Poll SEL for notification of events",
|
|
Packit Service |
ed0f68 |
.setup = selwatch_setup,
|
|
Packit Service |
ed0f68 |
.wait = selwatch_wait,
|
|
Packit Service |
ed0f68 |
.read = selwatch_read,
|
|
Packit Service |
ed0f68 |
.check = selwatch_check,
|
|
Packit Service |
ed0f68 |
.log = log_event,
|
|
Packit Service |
ed0f68 |
};
|
|
Packit Service |
ed0f68 |
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
struct ipmi_event_intf * ipmi_event_intf_table[] = {
|
|
Packit Service |
ed0f68 |
#ifdef IPMI_INTF_OPEN
|
|
Packit Service |
ed0f68 |
&openipmi_event_intf,
|
|
Packit Service |
ed0f68 |
#endif
|
|
Packit Service |
ed0f68 |
&selwatch_event_intf,
|
|
Packit Service |
ed0f68 |
NULL
|
|
Packit Service |
ed0f68 |
};
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
/*************************************************************************/
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
static void
|
|
Packit Service |
ed0f68 |
ipmievd_usage(void)
|
|
Packit Service |
ed0f68 |
{
|
|
Packit Service |
ed0f68 |
lprintf(LOG_NOTICE, "Options:");
|
|
Packit Service |
ed0f68 |
lprintf(LOG_NOTICE, "\ttimeout=# Time between checks for SEL polling method [default=10]");
|
|
Packit Service |
ed0f68 |
lprintf(LOG_NOTICE, "\tdaemon Become a daemon [default]");
|
|
Packit Service |
ed0f68 |
lprintf(LOG_NOTICE, "\tnodaemon Do NOT become a daemon");
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
/* ipmi_intf_load - Load an event interface from the table above
|
|
Packit Service |
ed0f68 |
* If no interface name is given return first entry
|
|
Packit Service |
ed0f68 |
*
|
|
Packit Service |
ed0f68 |
* @name: interface name to try and load
|
|
Packit Service |
ed0f68 |
*
|
|
Packit Service |
ed0f68 |
* returns pointer to inteface structure if found
|
|
Packit Service |
ed0f68 |
* returns NULL on error
|
|
Packit Service |
ed0f68 |
*/
|
|
Packit Service |
ed0f68 |
static struct ipmi_event_intf *
|
|
Packit Service |
ed0f68 |
ipmi_event_intf_load(char * name)
|
|
Packit Service |
ed0f68 |
{
|
|
Packit Service |
ed0f68 |
struct ipmi_event_intf ** intf;
|
|
Packit Service |
ed0f68 |
struct ipmi_event_intf * i;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
if (name == NULL) {
|
|
Packit Service |
ed0f68 |
i = ipmi_event_intf_table[0];
|
|
Packit Service |
ed0f68 |
return i;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
for (intf = ipmi_event_intf_table;
|
|
Packit Service |
ed0f68 |
((intf != NULL) && (*intf != NULL));
|
|
Packit Service |
ed0f68 |
intf++) {
|
|
Packit Service |
ed0f68 |
i = *intf;
|
|
Packit Service |
ed0f68 |
if (strncmp(name, i->name, strlen(name)) == 0) {
|
|
Packit Service |
ed0f68 |
return i;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
return NULL;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
static int
|
|
Packit Service |
ed0f68 |
compute_pctfull(uint16_t entries, uint16_t freespace)
|
|
Packit Service |
ed0f68 |
{
|
|
Packit Service |
ed0f68 |
int pctfull = 0;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
if (entries) {
|
|
Packit Service |
ed0f68 |
entries *= 16;
|
|
Packit Service |
ed0f68 |
freespace += entries;
|
|
Packit Service |
ed0f68 |
pctfull = (int)(100 * ( (double)entries / (double)freespace ));
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
return pctfull;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
static void
|
|
Packit Service |
ed0f68 |
log_event(struct ipmi_event_intf * eintf, struct sel_event_record * evt)
|
|
Packit Service |
ed0f68 |
{
|
|
Packit Service |
ed0f68 |
char *desc;
|
|
Packit Service |
ed0f68 |
const char *type;
|
|
Packit Service |
ed0f68 |
struct sdr_record_list * sdr;
|
|
Packit Service |
ed0f68 |
struct ipmi_intf * intf = eintf->intf;
|
|
Packit Service |
ed0f68 |
float trigger_reading = 0.0;
|
|
Packit Service |
ed0f68 |
float threshold_reading = 0.0;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
if (evt == NULL)
|
|
Packit Service |
ed0f68 |
return;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
if (evt->record_type == 0xf0) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_ALERT, "%sLinux kernel panic: %.11s",
|
|
Packit Service |
ed0f68 |
eintf->prefix, (char *) evt + 5);
|
|
Packit Service |
ed0f68 |
return;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
else if (evt->record_type >= 0xc0) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_NOTICE, "%sIPMI Event OEM Record %02x",
|
|
Packit Service |
ed0f68 |
eintf->prefix, evt->record_type);
|
|
Packit Service |
ed0f68 |
return;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
type = ipmi_get_sensor_type(intf, evt->sel_type.standard_type.sensor_type);
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
ipmi_get_event_desc(intf, evt, &desc);
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
sdr = ipmi_sdr_find_sdr_bynumtype(intf, evt->sel_type.standard_type.gen_id, evt->sel_type.standard_type.sensor_num,
|
|
Packit Service |
ed0f68 |
evt->sel_type.standard_type.sensor_type);
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
if (sdr == NULL) {
|
|
Packit Service |
ed0f68 |
/* could not find matching SDR record */
|
|
Packit Service |
ed0f68 |
if (desc) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_NOTICE, "%s%s sensor - %s",
|
|
Packit Service |
ed0f68 |
eintf->prefix, type, desc);
|
|
Packit Service |
ed0f68 |
free(desc);
|
|
Packit Service |
ed0f68 |
desc = NULL;
|
|
Packit Service |
ed0f68 |
} else {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_NOTICE, "%s%s sensor %02x",
|
|
Packit Service |
ed0f68 |
eintf->prefix, type,
|
|
Packit Service |
ed0f68 |
evt->sel_type.standard_type.sensor_num);
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
return;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
switch (sdr->type) {
|
|
Packit Service |
ed0f68 |
case SDR_RECORD_TYPE_FULL_SENSOR:
|
|
Packit Service |
ed0f68 |
if (evt->sel_type.standard_type.event_type == 1) {
|
|
Packit Service |
ed0f68 |
/*
|
|
Packit Service |
ed0f68 |
* Threshold Event
|
|
Packit Service |
ed0f68 |
*/
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
/* trigger reading in event data byte 2 */
|
|
Packit Service |
ed0f68 |
if (((evt->sel_type.standard_type.event_data[0] >> 6) & 3) == 1) {
|
|
Packit Service |
ed0f68 |
trigger_reading = sdr_convert_sensor_reading(
|
|
Packit Service |
ed0f68 |
sdr->record.full, evt->sel_type.standard_type.event_data[1]);
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
/* trigger threshold in event data byte 3 */
|
|
Packit Service |
ed0f68 |
if (((evt->sel_type.standard_type.event_data[0] >> 4) & 3) == 1) {
|
|
Packit Service |
ed0f68 |
threshold_reading = sdr_convert_sensor_reading(
|
|
Packit Service |
ed0f68 |
sdr->record.full, evt->sel_type.standard_type.event_data[2]);
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
lprintf(LOG_NOTICE, "%s%s sensor %s %s %s (Reading %.*f %s Threshold %.*f %s)",
|
|
Packit Service |
ed0f68 |
eintf->prefix,
|
|
Packit Service |
ed0f68 |
type,
|
|
Packit Service |
ed0f68 |
sdr->record.full->id_string,
|
|
Packit Service |
ed0f68 |
desc ? desc : "",
|
|
Packit Service |
ed0f68 |
(evt->sel_type.standard_type.event_dir
|
|
Packit Service |
ed0f68 |
? "Deasserted" : "Asserted"),
|
|
Packit Service |
ed0f68 |
(trigger_reading==(int)trigger_reading) ? 0 : 2,
|
|
Packit Service |
ed0f68 |
trigger_reading,
|
|
Packit Service |
ed0f68 |
((evt->sel_type.standard_type.event_data[0] & 0xf) % 2) ? ">" : "<",
|
|
Packit Service |
ed0f68 |
(threshold_reading==(int)threshold_reading) ? 0 : 2,
|
|
Packit Service |
ed0f68 |
threshold_reading,
|
|
Packit Service |
ed0f68 |
ipmi_sdr_get_unit_string(sdr->record.common->unit.pct,
|
|
Packit Service |
ed0f68 |
sdr->record.common->unit.modifier,
|
|
Packit Service |
ed0f68 |
sdr->record.common->unit.type.base,
|
|
Packit Service |
ed0f68 |
sdr->record.common->unit.type.modifier));
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
else if ((evt->sel_type.standard_type.event_type >= 0x2 && evt->sel_type.standard_type.event_type <= 0xc) ||
|
|
Packit Service |
ed0f68 |
(evt->sel_type.standard_type.event_type == 0x6f)) {
|
|
Packit Service |
ed0f68 |
/*
|
|
Packit Service |
ed0f68 |
* Discrete Event
|
|
Packit Service |
ed0f68 |
*/
|
|
Packit Service |
ed0f68 |
lprintf(LOG_NOTICE, "%s%s sensor %s %s %s",
|
|
Packit Service |
ed0f68 |
eintf->prefix, type,
|
|
Packit Service |
ed0f68 |
sdr->record.full->id_string, desc ? desc : "",
|
|
Packit Service |
ed0f68 |
(evt->sel_type.standard_type.event_dir
|
|
Packit Service |
ed0f68 |
? "Deasserted" : "Asserted"));
|
|
Packit Service |
ed0f68 |
if (((evt->sel_type.standard_type.event_data[0] >> 6) & 3) == 1) {
|
|
Packit Service |
ed0f68 |
/* previous state and/or severity in event data byte 2 */
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
else if (evt->sel_type.standard_type.event_type >= 0x70 && evt->sel_type.standard_type.event_type <= 0x7f) {
|
|
Packit Service |
ed0f68 |
/*
|
|
Packit Service |
ed0f68 |
* OEM Event
|
|
Packit Service |
ed0f68 |
*/
|
|
Packit Service |
ed0f68 |
lprintf(LOG_NOTICE, "%s%s sensor %s %s %s",
|
|
Packit Service |
ed0f68 |
eintf->prefix, type,
|
|
Packit Service |
ed0f68 |
sdr->record.full->id_string, desc ? desc : "",
|
|
Packit Service |
ed0f68 |
(evt->sel_type.standard_type.event_dir
|
|
Packit Service |
ed0f68 |
? "Deasserted" : "Asserted"));
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
break;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
case SDR_RECORD_TYPE_COMPACT_SENSOR:
|
|
Packit Service |
ed0f68 |
lprintf(LOG_NOTICE, "%s%s sensor %s - %s %s",
|
|
Packit Service |
ed0f68 |
eintf->prefix, type,
|
|
Packit Service |
ed0f68 |
sdr->record.compact->id_string, desc ? desc : "",
|
|
Packit Service |
ed0f68 |
(evt->sel_type.standard_type.event_dir
|
|
Packit Service |
ed0f68 |
? "Deasserted" : "Asserted"));
|
|
Packit Service |
ed0f68 |
break;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
default:
|
|
Packit Service |
ed0f68 |
lprintf(LOG_NOTICE, "%s%s sensor (0x%02x) - %s",
|
|
Packit Service |
ed0f68 |
eintf->prefix, type,
|
|
Packit Service |
ed0f68 |
evt->sel_type.standard_type.sensor_num, desc ? desc : "");
|
|
Packit Service |
ed0f68 |
break;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
if (desc) {
|
|
Packit Service |
ed0f68 |
free(desc);
|
|
Packit Service |
ed0f68 |
desc = NULL;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
/*************************************************************************/
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
/*************************************************************************/
|
|
Packit Service |
ed0f68 |
/** OpenIPMI Functions **/
|
|
Packit Service |
ed0f68 |
/*************************************************************************/
|
|
Packit Service |
ed0f68 |
#ifdef IPMI_INTF_OPEN
|
|
Packit Service |
ed0f68 |
static int
|
|
Packit Service |
ed0f68 |
openipmi_enable_event_msg_buffer(struct ipmi_intf * intf)
|
|
Packit Service |
ed0f68 |
{
|
|
Packit Service |
ed0f68 |
struct ipmi_rs * rsp;
|
|
Packit Service |
ed0f68 |
struct ipmi_rq req;
|
|
Packit Service |
ed0f68 |
uint8_t bmc_global_enables;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
/* we must read/modify/write bmc global enables */
|
|
Packit Service |
ed0f68 |
memset(&req, 0, sizeof(req));
|
|
Packit Service |
ed0f68 |
req.msg.netfn = IPMI_NETFN_APP;
|
|
Packit Service |
ed0f68 |
req.msg.cmd = 0x2f; /* Get BMC Global Enables */
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
rsp = intf->sendrecv(intf, &req;;
|
|
Packit Service |
ed0f68 |
if (rsp == NULL) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_ERR, "Get BMC Global Enables command failed");
|
|
Packit Service |
ed0f68 |
return -1;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
else if (rsp->ccode > 0) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_ERR, "Get BMC Global Enables command failed: %s",
|
|
Packit Service |
ed0f68 |
val2str(rsp->ccode, completion_code_vals));
|
|
Packit Service |
ed0f68 |
return -1;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
bmc_global_enables = rsp->data[0] | 0x04;
|
|
Packit Service |
ed0f68 |
req.msg.cmd = 0x2e; /* Set BMC Global Enables */
|
|
Packit Service |
ed0f68 |
req.msg.data = &bmc_global_enables;
|
|
Packit Service |
ed0f68 |
req.msg.data_len = 1;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
rsp = intf->sendrecv(intf, &req;;
|
|
Packit Service |
ed0f68 |
if (rsp == NULL) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_ERR, "Set BMC Global Enables command failed");
|
|
Packit Service |
ed0f68 |
return -1;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
else if (rsp->ccode > 0) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_ERR, "Set BMC Global Enables command failed: %s",
|
|
Packit Service |
ed0f68 |
val2str(rsp->ccode, completion_code_vals));
|
|
Packit Service |
ed0f68 |
return -1;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
lprintf(LOG_DEBUG, "BMC Event Message Buffer enabled");
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
return 0;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
static int
|
|
Packit Service |
ed0f68 |
openipmi_setup(struct ipmi_event_intf * eintf)
|
|
Packit Service |
ed0f68 |
{
|
|
Packit Service |
ed0f68 |
int i, r;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
/* enable event message buffer */
|
|
Packit Service |
ed0f68 |
lprintf(LOG_DEBUG, "Enabling event message buffer");
|
|
Packit Service |
ed0f68 |
r = openipmi_enable_event_msg_buffer(eintf->intf);
|
|
Packit Service |
ed0f68 |
if (r < 0) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_ERR, "Could not enable event message buffer");
|
|
Packit Service |
ed0f68 |
return -1;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
/* enable OpenIPMI event receiver */
|
|
Packit Service |
ed0f68 |
lprintf(LOG_DEBUG, "Enabling event receiver");
|
|
Packit Service |
ed0f68 |
i = 1;
|
|
Packit Service |
ed0f68 |
r = ioctl(eintf->intf->fd, IPMICTL_SET_GETS_EVENTS_CMD, &i);
|
|
Packit Service |
ed0f68 |
if (r != 0) {
|
|
Packit Service |
ed0f68 |
lperror(LOG_ERR, "Could not enable event receiver");
|
|
Packit Service |
ed0f68 |
return -1;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
return 0;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
static int
|
|
Packit Service |
ed0f68 |
openipmi_read(struct ipmi_event_intf * eintf)
|
|
Packit Service |
ed0f68 |
{
|
|
Packit Service |
ed0f68 |
struct ipmi_addr addr;
|
|
Packit Service |
ed0f68 |
struct ipmi_recv recv;
|
|
Packit Service |
ed0f68 |
uint8_t data[80];
|
|
Packit Service |
ed0f68 |
int rv;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
recv.addr = (unsigned char *) &addr;
|
|
Packit Service |
ed0f68 |
recv.addr_len = sizeof(addr);
|
|
Packit Service |
ed0f68 |
recv.msg.data = data;
|
|
Packit Service |
ed0f68 |
recv.msg.data_len = sizeof(data);
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
rv = ioctl(eintf->intf->fd, IPMICTL_RECEIVE_MSG_TRUNC, &recv;;
|
|
Packit Service |
ed0f68 |
if (rv < 0) {
|
|
Packit Service |
ed0f68 |
switch (errno) {
|
|
Packit Service |
ed0f68 |
case EINTR:
|
|
Packit Service |
ed0f68 |
return 0; /* abort */
|
|
Packit Service |
ed0f68 |
case EMSGSIZE:
|
|
Packit Service |
ed0f68 |
recv.msg.data_len = sizeof(data); /* truncated */
|
|
Packit Service |
ed0f68 |
break;
|
|
Packit Service |
ed0f68 |
default:
|
|
Packit Service |
ed0f68 |
lperror(LOG_ERR, "Unable to receive IPMI message");
|
|
Packit Service |
ed0f68 |
return -1;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
if (!recv.msg.data || recv.msg.data_len == 0) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_ERR, "No data in event");
|
|
Packit Service |
ed0f68 |
return -1;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
if (recv.recv_type != IPMI_ASYNC_EVENT_RECV_TYPE) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_ERR, "Type %x is not an event", recv.recv_type);
|
|
Packit Service |
ed0f68 |
return -1;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
lprintf(LOG_DEBUG, "netfn:%x cmd:%x ccode:%d",
|
|
Packit Service |
ed0f68 |
recv.msg.netfn, recv.msg.cmd, recv.msg.data[0]);
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
eintf->log(eintf, (struct sel_event_record *)recv.msg.data);
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
return 0;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
static int
|
|
Packit Service |
ed0f68 |
openipmi_wait(struct ipmi_event_intf * eintf)
|
|
Packit Service |
ed0f68 |
{
|
|
Packit Service |
ed0f68 |
struct pollfd pfd;
|
|
Packit Service |
ed0f68 |
int r;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
for (;;) {
|
|
Packit Service |
ed0f68 |
pfd.fd = eintf->intf->fd; /* wait on openipmi device */
|
|
Packit Service |
ed0f68 |
pfd.events = POLLIN; /* wait for input */
|
|
Packit Service |
ed0f68 |
r = poll(&pfd, 1, -1);
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
switch (r) {
|
|
Packit Service |
ed0f68 |
case 0:
|
|
Packit Service |
ed0f68 |
/* timeout is disabled */
|
|
Packit Service |
ed0f68 |
break;
|
|
Packit Service |
ed0f68 |
case -1:
|
|
Packit Service |
ed0f68 |
lperror(LOG_CRIT, "Unable to read from IPMI device");
|
|
Packit Service |
ed0f68 |
return -1;
|
|
Packit Service |
ed0f68 |
default:
|
|
Packit Service |
ed0f68 |
if (pfd.revents & POLLIN)
|
|
Packit Service |
ed0f68 |
eintf->read(eintf);
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
return 0;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
#endif /* IPMI_INTF_OPEN */
|
|
Packit Service |
ed0f68 |
/*************************************************************************/
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
/*************************************************************************/
|
|
Packit Service |
ed0f68 |
/** SEL Watch Functions **/
|
|
Packit Service |
ed0f68 |
/*************************************************************************/
|
|
Packit Service |
ed0f68 |
static int
|
|
Packit Service |
ed0f68 |
selwatch_get_data(struct ipmi_intf * intf, struct sel_data *data)
|
|
Packit Service |
ed0f68 |
{
|
|
Packit Service |
ed0f68 |
struct ipmi_rs * rsp;
|
|
Packit Service |
ed0f68 |
struct ipmi_rq req;
|
|
Packit Service |
ed0f68 |
uint16_t freespace;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
memset(&req, 0, sizeof(req));
|
|
Packit Service |
ed0f68 |
req.msg.netfn = IPMI_NETFN_STORAGE;
|
|
Packit Service |
ed0f68 |
req.msg.cmd = IPMI_CMD_GET_SEL_INFO;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
rsp = intf->sendrecv(intf, &req;;
|
|
Packit Service |
ed0f68 |
if (rsp == NULL) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_ERR, "Get SEL Info command failed");
|
|
Packit Service |
ed0f68 |
return 0;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
if (rsp->ccode > 0) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_ERR, "Get SEL Info command failed: %s",
|
|
Packit Service |
ed0f68 |
val2str(rsp->ccode, completion_code_vals));
|
|
Packit Service |
ed0f68 |
return 0;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
freespace = buf2short(rsp->data + 3);
|
|
Packit Service |
ed0f68 |
data->entries = buf2short(rsp->data + 1);
|
|
Packit Service |
ed0f68 |
data->pctused = compute_pctfull (data->entries, freespace);
|
|
Packit Service |
ed0f68 |
data->overflow = rsp->data[13] & 0x80;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
lprintf(LOG_DEBUG, "SEL count is %d", data->entries);
|
|
Packit Service |
ed0f68 |
lprintf(LOG_DEBUG, "SEL freespace is %d", freespace);
|
|
Packit Service |
ed0f68 |
lprintf(LOG_DEBUG, "SEL Percent Used: %d%%\n", data->pctused);
|
|
Packit Service |
ed0f68 |
lprintf(LOG_DEBUG, "SEL Overflow: %s", data->overflow ? "true" : "false");
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
return 1;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
static uint16_t
|
|
Packit Service |
ed0f68 |
selwatch_get_lastid(struct ipmi_intf * intf)
|
|
Packit Service |
ed0f68 |
{
|
|
Packit Service |
ed0f68 |
int next_id = 0;
|
|
Packit Service |
ed0f68 |
uint16_t curr_id = 0;
|
|
Packit Service |
ed0f68 |
struct sel_event_record evt;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
if (selwatch_count == 0)
|
|
Packit Service |
ed0f68 |
return 0;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
while (next_id != 0xffff) {
|
|
Packit Service |
ed0f68 |
curr_id = next_id;
|
|
Packit Service |
ed0f68 |
lprintf(LOG_DEBUG, "SEL Next ID: %04x", curr_id);
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
next_id = ipmi_sel_get_std_entry(intf, curr_id, &evt);
|
|
Packit Service |
ed0f68 |
if (next_id < 0)
|
|
Packit Service |
ed0f68 |
break;
|
|
Packit Service |
ed0f68 |
if (next_id == 0) {
|
|
Packit Service |
ed0f68 |
/*
|
|
Packit Service |
ed0f68 |
* usually next_id of zero means end but
|
|
Packit Service |
ed0f68 |
* retry because some hardware has quirks
|
|
Packit Service |
ed0f68 |
* and will return 0 randomly.
|
|
Packit Service |
ed0f68 |
*/
|
|
Packit Service |
ed0f68 |
next_id = ipmi_sel_get_std_entry(intf, curr_id, &evt);
|
|
Packit Service |
ed0f68 |
if (next_id <= 0)
|
|
Packit Service |
ed0f68 |
break;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
lprintf(LOG_DEBUG, "SEL lastid is %04x", curr_id);
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
return curr_id;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
static int
|
|
Packit Service |
ed0f68 |
selwatch_setup(struct ipmi_event_intf * eintf)
|
|
Packit Service |
ed0f68 |
{
|
|
Packit Service |
ed0f68 |
struct sel_data data;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
/* save current sel record count */
|
|
Packit Service |
ed0f68 |
if (selwatch_get_data(eintf->intf, &data)) {
|
|
Packit Service |
ed0f68 |
selwatch_count = data.entries;
|
|
Packit Service |
ed0f68 |
selwatch_pctused = data.pctused;
|
|
Packit Service |
ed0f68 |
selwatch_overflow = data.overflow;
|
|
Packit Service |
ed0f68 |
lprintf(LOG_DEBUG, "Current SEL count is %d", selwatch_count);
|
|
Packit Service |
ed0f68 |
/* save current last record ID */
|
|
Packit Service |
ed0f68 |
selwatch_lastid = selwatch_get_lastid(eintf->intf);
|
|
Packit Service |
ed0f68 |
lprintf(LOG_DEBUG, "Current SEL lastid is %04x", selwatch_lastid);
|
|
Packit Service |
ed0f68 |
/* display alert/warning immediatly as startup if relevant */
|
|
Packit Service |
ed0f68 |
if (selwatch_pctused >= WARNING_THRESHOLD) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_WARNING, "SEL buffer used at %d%%, please consider clearing the SEL buffer", selwatch_pctused);
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
if (selwatch_overflow) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_ALERT, "SEL buffer overflow, no SEL message can be logged until the SEL buffer is cleared");
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
return 1;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
lprintf(LOG_ERR, "Unable to retrieve SEL data");
|
|
Packit Service |
ed0f68 |
return 0;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
/* selwatch_check - check for waiting events
|
|
Packit Service |
ed0f68 |
*
|
|
Packit Service |
ed0f68 |
* this is done by reading sel info and comparing
|
|
Packit Service |
ed0f68 |
* the sel count value to what we currently know
|
|
Packit Service |
ed0f68 |
*/
|
|
Packit Service |
ed0f68 |
static int
|
|
Packit Service |
ed0f68 |
selwatch_check(struct ipmi_event_intf * eintf)
|
|
Packit Service |
ed0f68 |
{
|
|
Packit Service |
ed0f68 |
uint16_t old_count = selwatch_count;
|
|
Packit Service |
ed0f68 |
int old_pctused = selwatch_pctused;
|
|
Packit Service |
ed0f68 |
int old_overflow = selwatch_overflow;
|
|
Packit Service |
ed0f68 |
struct sel_data data;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
if (selwatch_get_data(eintf->intf, &data)) {
|
|
Packit Service |
ed0f68 |
selwatch_count = data.entries;
|
|
Packit Service |
ed0f68 |
selwatch_pctused = data.pctused;
|
|
Packit Service |
ed0f68 |
selwatch_overflow = data.overflow;
|
|
Packit Service |
ed0f68 |
if (old_overflow && !selwatch_overflow) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_NOTICE, "SEL overflow is cleared");
|
|
Packit Service |
ed0f68 |
} else if (!old_overflow && selwatch_overflow) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_ALERT, "SEL buffer overflow, no new SEL message will be logged until the SEL buffer is cleared");
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
if ((selwatch_pctused >= WARNING_THRESHOLD) && (selwatch_pctused > old_pctused)) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_WARNING, "SEL buffer is %d%% full, please consider clearing the SEL buffer", selwatch_pctused);
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
if (selwatch_count == 0) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_DEBUG, "SEL count is 0 (old=%d), resetting lastid to 0", old_count);
|
|
Packit Service |
ed0f68 |
selwatch_lastid = 0;
|
|
Packit Service |
ed0f68 |
} else if (selwatch_count < old_count) {
|
|
Packit Service |
ed0f68 |
selwatch_lastid = selwatch_get_lastid(eintf->intf);
|
|
Packit Service |
ed0f68 |
lprintf(LOG_DEBUG, "SEL count lowered, new SEL lastid is %04x", selwatch_lastid);
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
return (selwatch_count > old_count);
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
static int
|
|
Packit Service |
ed0f68 |
selwatch_read(struct ipmi_event_intf * eintf)
|
|
Packit Service |
ed0f68 |
{
|
|
Packit Service |
ed0f68 |
uint16_t curr_id = 0;
|
|
Packit Service |
ed0f68 |
int next_id = selwatch_lastid;
|
|
Packit Service |
ed0f68 |
struct sel_event_record evt;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
if (selwatch_count == 0)
|
|
Packit Service |
ed0f68 |
return -1;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
while (next_id != 0xffff) {
|
|
Packit Service |
ed0f68 |
curr_id = next_id;
|
|
Packit Service |
ed0f68 |
lprintf(LOG_DEBUG, "SEL Read ID: %04x", curr_id);
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
next_id = ipmi_sel_get_std_entry(eintf->intf, curr_id, &evt);
|
|
Packit Service |
ed0f68 |
if (next_id < 0)
|
|
Packit Service |
ed0f68 |
break;
|
|
Packit Service |
ed0f68 |
if (next_id == 0) {
|
|
Packit Service |
ed0f68 |
/*
|
|
Packit Service |
ed0f68 |
* usually next_id of zero means end but
|
|
Packit Service |
ed0f68 |
* retry because some hardware has quirks
|
|
Packit Service |
ed0f68 |
* and will return 0 randomly.
|
|
Packit Service |
ed0f68 |
*/
|
|
Packit Service |
ed0f68 |
next_id = ipmi_sel_get_std_entry(eintf->intf, curr_id, &evt);
|
|
Packit Service |
ed0f68 |
if (next_id <= 0)
|
|
Packit Service |
ed0f68 |
break;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
if (curr_id != selwatch_lastid)
|
|
Packit Service |
ed0f68 |
eintf->log(eintf, &evt);
|
|
Packit Service |
ed0f68 |
else if (curr_id == 0)
|
|
Packit Service |
ed0f68 |
eintf->log(eintf, &evt);
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
selwatch_lastid = curr_id;
|
|
Packit Service |
ed0f68 |
return 0;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
static int
|
|
Packit Service |
ed0f68 |
selwatch_wait(struct ipmi_event_intf * eintf)
|
|
Packit Service |
ed0f68 |
{
|
|
Packit Service |
ed0f68 |
for (;;) {
|
|
Packit Service |
ed0f68 |
if (eintf->check(eintf) > 0) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_DEBUG, "New Events");
|
|
Packit Service |
ed0f68 |
eintf->read(eintf);
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
sleep(selwatch_timeout);
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
return 0;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
/*************************************************************************/
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
static void
|
|
Packit Service |
ed0f68 |
ipmievd_cleanup(int signal)
|
|
Packit Service |
ed0f68 |
{
|
|
Packit Service |
ed0f68 |
struct stat st1;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
if (lstat(pidfile, &st1) == 0) {
|
|
Packit Service |
ed0f68 |
/* cleanup daemon pidfile */
|
|
Packit Service |
ed0f68 |
(void)unlink(pidfile);
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
exit(EXIT_SUCCESS);
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
int
|
|
Packit Service |
ed0f68 |
ipmievd_main(struct ipmi_event_intf * eintf, int argc, char ** argv)
|
|
Packit Service |
ed0f68 |
{
|
|
Packit Service |
ed0f68 |
int i, rc;
|
|
Packit Service |
ed0f68 |
int daemon = 1;
|
|
Packit Service |
ed0f68 |
struct sigaction act;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
memset(pidfile, 0, 64);
|
|
Packit Service |
ed0f68 |
sprintf(pidfile, "%s%d", DEFAULT_PIDFILE, eintf->intf->devnum);
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
for (i = 0; i < argc; i++) {
|
|
Packit Service |
ed0f68 |
if (strncasecmp(argv[i], "help", 4) == 0) {
|
|
Packit Service |
ed0f68 |
ipmievd_usage();
|
|
Packit Service |
ed0f68 |
return 0;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
if (strncasecmp(argv[i], "daemon", 6) == 0) {
|
|
Packit Service |
ed0f68 |
daemon = 1;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
else if (strncasecmp(argv[i], "nodaemon", 8) == 0) {
|
|
Packit Service |
ed0f68 |
daemon = 0;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
else if (strncasecmp(argv[i], "daemon=", 7) == 0) {
|
|
Packit Service |
ed0f68 |
if (strncasecmp(argv[i]+7, "on", 2) == 0 ||
|
|
Packit Service |
ed0f68 |
strncasecmp(argv[i]+7, "yes", 3) == 0)
|
|
Packit Service |
ed0f68 |
daemon = 1;
|
|
Packit Service |
ed0f68 |
else if (strncasecmp(argv[i]+7, "off", 3) == 0 ||
|
|
Packit Service |
ed0f68 |
strncasecmp(argv[i]+7, "no", 2) == 0)
|
|
Packit Service |
ed0f68 |
daemon = 0;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
else if (strncasecmp(argv[i], "timeout=", 8) == 0) {
|
|
Packit Service |
ed0f68 |
if ( (str2int(argv[i]+8, &selwatch_timeout) != 0) ||
|
|
Packit Service |
ed0f68 |
selwatch_timeout < 0) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_ERR, "Invalid input given or out of range for time-out.");
|
|
Packit Service |
ed0f68 |
return (-1);
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
else if (strncasecmp(argv[i], "pidfile=", 8) == 0) {
|
|
Packit Service |
ed0f68 |
memset(pidfile, 0, 64);
|
|
Packit Service |
ed0f68 |
strncpy(pidfile, argv[i]+8,
|
|
Packit Service |
ed0f68 |
__min(strlen((const char *)(argv[i]+8)), 63));
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
lprintf(LOG_DEBUG, "ipmievd: using pidfile %s", pidfile);
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
/*
|
|
Packit Service |
ed0f68 |
* We need to open interface before forking daemon
|
|
Packit Service |
ed0f68 |
* so error messages are not lost to syslog and
|
|
Packit Service |
ed0f68 |
* return code is successfully returned to initscript
|
|
Packit Service |
ed0f68 |
*/
|
|
Packit Service |
ed0f68 |
if (eintf->intf->open(eintf->intf) < 0) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_ERR, "Unable to open interface");
|
|
Packit Service |
ed0f68 |
return -1;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
if (daemon) {
|
|
Packit Service |
ed0f68 |
FILE *fp;
|
|
Packit Service |
ed0f68 |
struct stat st1;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
if (lstat(pidfile, &st1) == 0) {
|
|
Packit Service |
ed0f68 |
/* PID file already exists -> exit. */
|
|
Packit Service |
ed0f68 |
lprintf(LOG_ERR, "PID file '%s' already exists.", pidfile);
|
|
Packit Service |
ed0f68 |
lprintf(LOG_ERR, "Perhaps another instance is already running.");
|
|
Packit Service |
ed0f68 |
return (-1);
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
ipmi_start_daemon(eintf->intf);
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
umask(022);
|
|
Packit Service |
ed0f68 |
fp = ipmi_open_file_write(pidfile);
|
|
Packit Service |
ed0f68 |
if (fp == NULL) {
|
|
Packit Service |
ed0f68 |
/* Failed to get fp on PID file -> exit. */
|
|
Packit Service |
ed0f68 |
log_halt();
|
|
Packit Service |
ed0f68 |
log_init("ipmievd", daemon, verbose);
|
|
Packit Service |
ed0f68 |
lprintf(LOG_ERR,
|
|
Packit Service |
ed0f68 |
"Failed to open PID file '%s' for writing. Check file permission.",
|
|
Packit Service |
ed0f68 |
pidfile);
|
|
Packit Service |
ed0f68 |
exit(EXIT_FAILURE);
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
fprintf(fp, "%d\n", (int)getpid());
|
|
Packit Service |
ed0f68 |
fclose(fp);
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
/* register signal handler for cleanup */
|
|
Packit Service |
ed0f68 |
act.sa_handler = ipmievd_cleanup;
|
|
Packit Service |
ed0f68 |
act.sa_flags = 0;
|
|
Packit Service |
ed0f68 |
sigemptyset(&act.sa_mask);
|
|
Packit Service |
ed0f68 |
sigaction(SIGINT, &act, NULL);
|
|
Packit Service |
ed0f68 |
sigaction(SIGQUIT, &act, NULL);
|
|
Packit Service |
ed0f68 |
sigaction(SIGTERM, &act, NULL);
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
log_halt();
|
|
Packit Service |
ed0f68 |
log_init("ipmievd", daemon, verbose);
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
/* generate SDR cache for fast lookups */
|
|
Packit Service |
ed0f68 |
lprintf(LOG_NOTICE, "Reading sensors...");
|
|
Packit Service |
ed0f68 |
ipmi_sdr_list_cache(eintf->intf);
|
|
Packit Service |
ed0f68 |
lprintf(LOG_DEBUG, "Sensors cached");
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
/* call event handler setup routine */
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
if (eintf->setup != NULL) {
|
|
Packit Service |
ed0f68 |
rc = eintf->setup(eintf);
|
|
Packit Service |
ed0f68 |
if (rc < 0) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_ERR, "Error setting up Event Interface %s", eintf->name);
|
|
Packit Service |
ed0f68 |
return -1;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
lprintf(LOG_NOTICE, "Waiting for events...");
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
/* now launch event wait loop */
|
|
Packit Service |
ed0f68 |
if (eintf->wait != NULL) {
|
|
Packit Service |
ed0f68 |
rc = eintf->wait(eintf);
|
|
Packit Service |
ed0f68 |
if (rc < 0) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_ERR, "Error waiting for events!");
|
|
Packit Service |
ed0f68 |
return -1;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
return 0;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
int
|
|
Packit Service |
ed0f68 |
ipmievd_sel_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
Packit Service |
ed0f68 |
{
|
|
Packit Service |
ed0f68 |
struct ipmi_event_intf * eintf;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
eintf = ipmi_event_intf_load("sel");
|
|
Packit Service |
ed0f68 |
if (eintf == NULL) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_ERR, "Unable to load event interface");
|
|
Packit Service |
ed0f68 |
return -1;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
eintf->intf = intf;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
if (intf->session != NULL) {
|
|
Packit Service |
ed0f68 |
snprintf(eintf->prefix,
|
|
Packit Service |
ed0f68 |
strlen((const char *)intf->ssn_params.hostname) + 3,
|
|
Packit Service |
ed0f68 |
"%s: ", intf->ssn_params.hostname);
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
return ipmievd_main(eintf, argc, argv);
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
int
|
|
Packit Service |
ed0f68 |
ipmievd_open_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
Packit Service |
ed0f68 |
{
|
|
Packit Service |
ed0f68 |
struct ipmi_event_intf * eintf;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
/* only one interface works for this */
|
|
Packit Service |
ed0f68 |
if (strncmp(intf->name, "open", 4) != 0) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_ERR, "Invalid Interface for OpenIPMI Event Handler: %s", intf->name);
|
|
Packit Service |
ed0f68 |
return -1;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
eintf = ipmi_event_intf_load("open");
|
|
Packit Service |
ed0f68 |
if (eintf == NULL) {
|
|
Packit Service |
ed0f68 |
lprintf(LOG_ERR, "Unable to load event interface");
|
|
Packit Service |
ed0f68 |
return -1;
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
eintf->intf = intf;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
return ipmievd_main(eintf, argc, argv);
|
|
Packit Service |
ed0f68 |
}
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
struct ipmi_cmd ipmievd_cmd_list[] = {
|
|
Packit Service |
ed0f68 |
#ifdef IPMI_INTF_OPEN
|
|
Packit Service |
ed0f68 |
{ ipmievd_open_main, "open", "Use OpenIPMI for asyncronous notification of events" },
|
|
Packit Service |
ed0f68 |
#endif
|
|
Packit Service |
ed0f68 |
{ ipmievd_sel_main, "sel", "Poll SEL for notification of events" },
|
|
Packit Service |
ed0f68 |
{ NULL }
|
|
Packit Service |
ed0f68 |
};
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
int main(int argc, char ** argv)
|
|
Packit Service |
ed0f68 |
{
|
|
Packit Service |
ed0f68 |
int rc;
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
rc = ipmi_main(argc, argv, ipmievd_cmd_list, NULL);
|
|
Packit Service |
ed0f68 |
|
|
Packit Service |
ed0f68 |
if (rc < 0)
|
|
Packit Service |
ed0f68 |
exit(EXIT_FAILURE);
|
|
Packit Service |
ed0f68 |
else
|
|
Packit Service |
ed0f68 |
exit(EXIT_SUCCESS);
|
|
Packit Service |
ed0f68 |
}
|