summaryrefslogtreecommitdiffstats
path: root/lib/plugins/stonith/wti_mpc.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/plugins/stonith/wti_mpc.c')
-rw-r--r--lib/plugins/stonith/wti_mpc.c856
1 files changed, 856 insertions, 0 deletions
diff --git a/lib/plugins/stonith/wti_mpc.c b/lib/plugins/stonith/wti_mpc.c
new file mode 100644
index 0000000..548f91c
--- /dev/null
+++ b/lib/plugins/stonith/wti_mpc.c
@@ -0,0 +1,856 @@
+/*
+ * Stonith module for WTI MPC (SNMP)
+ * Copyright (c) 2001 Andreas Piesk <a.piesk@gmx.net>
+ * Mangled by Sun Jiang Dong <sunjd@cn.ibm.com>, IBM, 2005
+ *
+ * Modified for WTI MPC by Denis Chapligin <chollya@satgate.net>, SatGate, 2009
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.*
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <lha_internal.h>
+
+/* device ID */
+#define DEVICE "WTI MPC"
+
+#include "stonith_plugin_common.h"
+#undef FREE /* defined by snmp stuff */
+
+#ifdef PACKAGE_BUGREPORT
+#undef PACKAGE_BUGREPORT
+#endif
+#ifdef PACKAGE_NAME
+#undef PACKAGE_NAME
+#endif
+#ifdef PACKAGE_STRING
+#undef PACKAGE_STRING
+#endif
+#ifdef PACKAGE_TARNAME
+#undef PACKAGE_TARNAME
+#endif
+#ifdef PACKAGE_VERSION
+#undef PACKAGE_VERSION
+#endif
+
+#ifdef HAVE_NET_SNMP_NET_SNMP_CONFIG_H
+# include <net-snmp/net-snmp-config.h>
+# include <net-snmp/net-snmp-includes.h>
+# include <net-snmp/agent/net-snmp-agent-includes.h>
+# define INIT_AGENT() init_master_agent()
+#else
+# include <ucd-snmp/ucd-snmp-config.h>
+# include <ucd-snmp/ucd-snmp-includes.h>
+# include <ucd-snmp/ucd-snmp-agent-includes.h>
+# ifndef NETSNMP_DS_APPLICATION_ID
+# define NETSNMP_DS_APPLICATION_ID DS_APPLICATION_ID
+# endif
+# ifndef NETSNMP_DS_AGENT_ROLE
+# define NETSNMP_DS_AGENT_ROLE DS_AGENT_ROLE
+# endif
+# define netsnmp_ds_set_boolean ds_set_boolean
+# define INIT_AGENT() init_master_agent(161, NULL, NULL)
+#endif
+
+#define PIL_PLUGIN wti_mpc
+#define PIL_PLUGIN_S "wti_mpc"
+#define PIL_PLUGINLICENSE LICENSE_LGPL
+#define PIL_PLUGINLICENSEURL URL_LGPL
+#include <pils/plugin.h>
+
+#define DEBUGCALL \
+ if (Debug) { \
+ LOG(PIL_DEBUG, "%s: called.", __FUNCTION__); \
+ }
+
+static StonithPlugin * wti_mpc_new(const char *);
+static void wti_mpc_destroy(StonithPlugin *);
+static const char * const * wti_mpc_get_confignames(StonithPlugin *);
+static int wti_mpc_set_config(StonithPlugin *, StonithNVpair *);
+static const char * wti_mpc_getinfo(StonithPlugin * s, int InfoType);
+static int wti_mpc_status(StonithPlugin * );
+static int wti_mpc_reset_req(StonithPlugin * s, int request, const char * host);
+static char ** wti_mpc_hostlist(StonithPlugin *);
+
+static struct stonith_ops wti_mpcOps ={
+ wti_mpc_new, /* Create new STONITH object */
+ wti_mpc_destroy, /* Destroy STONITH object */
+ wti_mpc_getinfo, /* Return STONITH info string */
+ wti_mpc_get_confignames, /* Get configuration parameters */
+ wti_mpc_set_config, /* Set configuration */
+ wti_mpc_status, /* Return STONITH device status */
+ wti_mpc_reset_req, /* Request a reset */
+ wti_mpc_hostlist, /* Return list of supported hosts */
+};
+
+PIL_PLUGIN_BOILERPLATE2("1.0", Debug)
+static const PILPluginImports* PluginImports;
+static PILPlugin* OurPlugin;
+static PILInterface* OurInterface;
+static StonithImports* OurImports;
+static void* interfprivate;
+
+PIL_rc
+PIL_PLUGIN_INIT(PILPlugin*us, const PILPluginImports* imports);
+
+PIL_rc
+PIL_PLUGIN_INIT(PILPlugin*us, const PILPluginImports* imports)
+{
+ /* Force the compiler to do a little type checking */
+ (void)(PILPluginInitFun)PIL_PLUGIN_INIT;
+ DEBUGCALL;
+
+ PluginImports = imports;
+ OurPlugin = us;
+
+ /* Register ourself as a plugin */
+ imports->register_plugin(us, &OurPIExports);
+
+ /* Register our interface implementation */
+ return imports->register_interface(us, PIL_PLUGINTYPE_S
+ , PIL_PLUGIN_S
+ , &wti_mpcOps
+ , NULL /*close */
+ , &OurInterface
+ , (void*)&OurImports
+ , &interfprivate);
+}
+
+/*
+ * APCMaster tested with APC Masterswitch 9212
+ */
+
+/* outlet commands / status codes */
+#define OUTLET_ON 5
+#define OUTLET_OFF 6
+#define OUTLET_REBOOT 7
+
+/* oids */
+#define OID_IDENT ".1.3.6.1.2.1.1.5.0"
+
+#define OID_GROUP_NAMES_V1 ".1.3.6.1.4.1.2634.3.1.3.1.2.%u"
+#define OID_GROUP_STATE_V1 ".1.3.6.1.4.1.2634.3.1.3.1.3.%i"
+
+#define OID_GROUP_NAMES_V3 ".1.3.6.1.4.1.2634.3.100.300.1.2.%u"
+#define OID_GROUP_STATE_V3 ".1.3.6.1.4.1.2634.3.100.300.1.3.%i"
+
+#define MAX_OUTLETS 128
+
+/*
+ snmpset -c private -v1 172.16.0.32:161
+ ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.4.1" i 1
+ The last octet in the OID is the plug number. The value can
+ be 1 thru 8 because there are 8 power plugs on this device.
+ The integer that can be set is as follows: 1=on, 2=off, and
+ 3=reset
+*/
+
+/* own defines */
+#define MAX_STRING 128
+#define ST_PORT "port"
+#define ST_MIBVERSION "mib-version"
+
+/* structur of stonith object */
+struct pluginDevice {
+ StonithPlugin sp; /* StonithPlugin object */
+ const char* pluginid; /* id of object */
+ const char* idinfo; /* type of device */
+ struct snmp_session* sptr; /* != NULL->session created */
+ char * hostname; /* masterswitch's hostname */
+ /* or ip addr */
+ int port; /* snmp port */
+ int mib_version; /* mib version to use */
+ char * community; /* snmp community (r/w) */
+ int num_outlets; /* number of outlets */
+};
+
+/* constant strings */
+static const char *pluginid = "WTI-MPC-Stonith";
+static const char *NOTpluginID = "WTI MPC device has been destroyed";
+
+#include "stonith_config_xml.h"
+
+#define XML_PORT_SHORTDESC \
+ XML_PARM_SHORTDESC_BEGIN("en") \
+ ST_PORT \
+ XML_PARM_SHORTDESC_END
+
+#define XML_PORT_LONGDESC \
+ XML_PARM_LONGDESC_BEGIN("en") \
+ "The port number on which the SNMP server is running on the STONITH device" \
+ XML_PARM_LONGDESC_END
+
+#define XML_PORT_PARM \
+ XML_PARAMETER_BEGIN(ST_PORT, "string", "1", "0") \
+ XML_PORT_SHORTDESC \
+ XML_PORT_LONGDESC \
+ XML_PARAMETER_END
+
+#define XML_MIBVERSION_SHORTDESC \
+ XML_PARM_SHORTDESC_BEGIN("en") \
+ ST_MIBVERSION \
+ XML_PARM_SHORTDESC_END
+
+#define XML_MIBVERSION_LONGDESC \
+ XML_MIBVERSION_LONGDESC_BEGIN("en") \
+ "Version number of MPC MIB that we should use. Valid values are 1 (for 1.44 firmware) and 3 (for 1.62 firmware and later)" \
+ XML_PARM_LONGDESC_END
+
+#define XML_MIBVERSION_PARM \
+ XML_PARAMETER_BEGIN(ST_MIBVERSION, "string", "1", "0") \
+ XML_PORT_SHORTDESC \
+ XML_PORT_LONGDESC \
+ XML_PARAMETER_END
+
+static const char *apcmastersnmpXML =
+ XML_PARAMETERS_BEGIN
+ XML_IPADDR_PARM
+ XML_PORT_PARM
+ XML_COMMUNITY_PARM
+ XML_MIBVERSION_PARM
+ XML_PARAMETERS_END;
+
+/*
+ * own prototypes
+ */
+
+static void MPC_error(struct snmp_session *sptr, const char *fn
+, const char *msg);
+static struct snmp_session *MPC_open(char *hostname, int port
+, char *community);
+static void *MPC_read(struct snmp_session *sptr, const char *objname
+, int type);
+static int MPC_write(struct snmp_session *sptr, const char *objname
+, char type, char *value);
+
+static void
+MPC_error(struct snmp_session *sptr, const char *fn, const char *msg)
+{
+ int snmperr = 0;
+ int cliberr = 0;
+ char *errstr;
+
+ snmp_error(sptr, &cliberr, &snmperr, &errstr);
+ LOG(PIL_CRIT
+ , "%s: %s (cliberr: %i / snmperr: %i / error: %s)."
+ , fn, msg, cliberr, snmperr, errstr);
+ free(errstr);
+}
+
+
+/*
+ * creates a snmp session
+ */
+static struct snmp_session *
+MPC_open(char *hostname, int port, char *community)
+{
+ static struct snmp_session session;
+ struct snmp_session *sptr;
+
+ DEBUGCALL;
+
+ /* create session */
+ snmp_sess_init(&session);
+
+ /* fill session */
+ session.peername = hostname;
+ session.version = SNMP_VERSION_1;
+ session.remote_port = port;
+ session.community = (u_char *)community;
+ session.community_len = strlen(community);
+ session.retries = 5;
+ session.timeout = 1000000;
+
+ /* open session */
+ sptr = snmp_open(&session);
+
+ if (sptr == NULL) {
+ MPC_error(&session, __FUNCTION__, "cannot open snmp session");
+ }
+
+ /* return pointer to opened session */
+ return (sptr);
+}
+
+/*
+ * parse config
+ */
+
+/*
+ * read value of given oid and return it as string
+ */
+static void *
+MPC_read(struct snmp_session *sptr, const char *objname, int type)
+{
+ oid name[MAX_OID_LEN];
+ size_t namelen = MAX_OID_LEN;
+ struct variable_list *vars;
+ struct snmp_pdu *pdu;
+ struct snmp_pdu *resp;
+ static char response_str[MAX_STRING];
+ static int response_int;
+
+ DEBUGCALL;
+
+ /* convert objname into oid; return NULL if invalid */
+ if (!read_objid(objname, name, &namelen)) {
+ LOG(PIL_CRIT, "%s: cannot convert %s to oid.", __FUNCTION__, objname);
+ return (NULL);
+ }
+
+ /* create pdu */
+ if ((pdu = snmp_pdu_create(SNMP_MSG_GET)) != NULL) {
+
+ /* get-request have no values */
+ snmp_add_null_var(pdu, name, namelen);
+
+ /* send pdu and get response; return NULL if error */
+ if (snmp_synch_response(sptr, pdu, &resp) == SNMPERR_SUCCESS) {
+
+ /* request succeed, got valid response ? */
+ if (resp->errstat == SNMP_ERR_NOERROR) {
+
+ /* go through the returned vars */
+ for (vars = resp->variables; vars;
+ vars = vars->next_variable) {
+
+ /* return response as string */
+ if ((vars->type == type) && (type == ASN_OCTET_STR)) {
+ memset(response_str, 0, MAX_STRING);
+ strncpy(response_str, (char *)vars->val.string,
+ MIN(vars->val_len, MAX_STRING));
+ snmp_free_pdu(resp);
+ return ((void *) response_str);
+ }
+ /* return response as integer */
+ if ((vars->type == type) && (type == ASN_INTEGER)) {
+ response_int = *vars->val.integer;
+ snmp_free_pdu(resp);
+ return ((void *) &response_int);
+ }
+ }
+ }else{
+ LOG(PIL_CRIT, "%s: error in response packet, reason %ld [%s]."
+ , __FUNCTION__, resp->errstat, snmp_errstring(resp->errstat));
+ }
+ }else{
+ MPC_error(sptr, __FUNCTION__, "error sending/receiving pdu");
+ }
+ /* free repsonse pdu (necessary?) */
+ snmp_free_pdu(resp);
+ }else{
+ MPC_error(sptr, __FUNCTION__, "cannot create pdu");
+ }
+ /* error: return nothing */
+ return (NULL);
+}
+
+/*
+ * write value of given oid
+ */
+static int
+MPC_write(struct snmp_session *sptr, const char *objname, char type,
+ char *value)
+{
+ oid name[MAX_OID_LEN];
+ size_t namelen = MAX_OID_LEN;
+ struct snmp_pdu *pdu;
+ struct snmp_pdu *resp;
+
+ DEBUGCALL;
+
+ /* convert objname into oid; return FALSE if invalid */
+ if (!read_objid(objname, name, &namelen)) {
+ LOG(PIL_CRIT, "%s: cannot convert %s to oid.", __FUNCTION__, objname);
+ return (FALSE);
+ }
+
+ /* create pdu */
+ if ((pdu = snmp_pdu_create(SNMP_MSG_SET)) != NULL) {
+
+ /* add to be written value to pdu */
+ snmp_add_var(pdu, name, namelen, type, value);
+
+ /* send pdu and get response; return NULL if error */
+ if (snmp_synch_response(sptr, pdu, &resp) == STAT_SUCCESS) {
+
+ /* go through the returned vars */
+ if (resp->errstat == SNMP_ERR_NOERROR) {
+
+ /* request successful done */
+ snmp_free_pdu(resp);
+ return (TRUE);
+
+ }else{
+ LOG(PIL_CRIT, "%s: error in response packet, reason %ld [%s]."
+ , __FUNCTION__, resp->errstat, snmp_errstring(resp->errstat));
+ }
+ }else{
+ MPC_error(sptr, __FUNCTION__, "error sending/receiving pdu");
+ }
+ /* free pdu (again: necessary?) */
+ snmp_free_pdu(resp);
+ }else{
+ MPC_error(sptr, __FUNCTION__, "cannot create pdu");
+ }
+ /* error */
+ return (FALSE);
+}
+
+/*
+ * return the status for this device
+ */
+
+static int
+wti_mpc_status(StonithPlugin * s)
+{
+ struct pluginDevice *ad;
+ char *ident;
+
+ DEBUGCALL;
+
+ ERRIFNOTCONFIGED(s, S_OOPS);
+
+ ad = (struct pluginDevice *) s;
+
+ if ((ident = MPC_read(ad->sptr, OID_IDENT, ASN_OCTET_STR)) == NULL) {
+ LOG(PIL_CRIT, "%s: cannot read ident.", __FUNCTION__);
+ return (S_ACCESS);
+ }
+
+ /* status ok */
+ return (S_OK);
+}
+
+/*
+ * return the list of hosts configured for this device
+ */
+
+static char **
+wti_mpc_hostlist(StonithPlugin * s)
+{
+ char **hl;
+ struct pluginDevice *ad;
+ int j, h, num_outlets;
+ char *outlet_name;
+ char objname[MAX_STRING];
+
+ DEBUGCALL;
+
+ ERRIFNOTCONFIGED(s, NULL);
+
+ ad = (struct pluginDevice *) s;
+
+ /* allocate memory for array of up to NUM_OUTLETS strings */
+ if ((hl = (char **)MALLOC((ad->num_outlets+1) * sizeof(char *))) == NULL) {
+ LOG(PIL_CRIT, "%s: out of memory.", __FUNCTION__);
+ return (NULL);
+ }
+ /* clear hostlist array */
+ memset(hl, 0, (ad->num_outlets + 1) * sizeof(char *));
+ num_outlets = 0;
+
+ /* read NUM_OUTLETS values and put them into hostlist array */
+ for (j = 0; j < ad->num_outlets; ++j) {
+
+ /* prepare objname */
+ switch (ad->mib_version) {
+ case 3:
+ snprintf(objname,MAX_STRING,OID_GROUP_NAMES_V3,j+1);
+ break;
+ case 1:
+ default:
+ snprintf(objname,MAX_STRING,OID_GROUP_NAMES_V1,j+1);
+ break;
+ }
+ if (Debug) {
+ LOG(PIL_DEBUG, "%s: using %s as group names oid", __FUNCTION__, objname);
+ }
+
+ /* read outlet name */
+ if ((outlet_name = MPC_read(ad->sptr, objname, ASN_OCTET_STR)) ==
+ NULL) {
+ LOG(PIL_CRIT, "%s: cannot read name for outlet %d."
+ , __FUNCTION__, j+1);
+ stonith_free_hostlist(hl);
+ hl = NULL;
+ return (hl);
+ }
+
+ /* Check whether the host is already listed */
+ for (h = 0; h < num_outlets; ++h) {
+ if (strcasecmp(hl[h],outlet_name) == 0)
+ break;
+ }
+
+ if (h >= num_outlets) {
+ /* put outletname in hostlist */
+ if (Debug) {
+ LOG(PIL_DEBUG, "%s: added %s to hostlist."
+ , __FUNCTION__, outlet_name);
+ }
+
+ if ((hl[num_outlets] = STRDUP(outlet_name)) == NULL) {
+ LOG(PIL_CRIT, "%s: out of memory.", __FUNCTION__);
+ stonith_free_hostlist(hl);
+ hl = NULL;
+ return (hl);
+ }
+ strdown(hl[num_outlets]);
+ num_outlets++;
+ }
+ }
+
+
+ if (Debug) {
+ LOG(PIL_DEBUG, "%s: %d unique hosts connected to %d outlets."
+ , __FUNCTION__, num_outlets, j);
+ }
+ /* return list */
+ return (hl);
+}
+
+/*
+ * reset the host
+ */
+
+static int
+wti_mpc_reset_req(StonithPlugin * s, int request, const char *host)
+{
+ struct pluginDevice *ad;
+ char objname[MAX_STRING];
+ char value[MAX_STRING];
+ char *outlet_name;
+ int req_oid = OUTLET_REBOOT;
+ int outlet;
+ int found_outlet=-1;
+
+ DEBUGCALL;
+
+ ERRIFNOTCONFIGED(s, S_OOPS);
+
+ ad = (struct pluginDevice *) s;
+
+ /* read max. as->num_outlets values */
+ for (outlet = 1; outlet <= ad->num_outlets; outlet++) {
+
+ /* prepare objname */
+ switch (ad->mib_version) {
+ case 3:
+ snprintf(objname,MAX_STRING,OID_GROUP_NAMES_V3,outlet);
+ break;
+ case 1:
+ default:
+ snprintf(objname,MAX_STRING,OID_GROUP_NAMES_V1,outlet);
+ break;
+ }
+
+ /* read outlet name */
+ if ((outlet_name = MPC_read(ad->sptr, objname, ASN_OCTET_STR))
+ == NULL) {
+ LOG(PIL_CRIT, "%s: cannot read name for outlet %d."
+ , __FUNCTION__, outlet);
+ return (S_ACCESS);
+ }
+ if (Debug) {
+ LOG(PIL_DEBUG, "%s: found outlet: %s.", __FUNCTION__, outlet_name);
+ }
+
+ /* found one */
+ if (strcasecmp(outlet_name, host) == 0) {
+ if (Debug) {
+ LOG(PIL_DEBUG, "%s: found %s at outlet %d."
+ , __FUNCTION__, host, outlet);
+ }
+
+ /* Ok, stop iterating over host list */
+ found_outlet=outlet;
+ break;
+ }
+ }
+ if (Debug) {
+ LOG(PIL_DEBUG, "%s: outlet: %i.", __FUNCTION__, outlet);
+ }
+
+ /* host not found in outlet names */
+ if (found_outlet == -1) {
+ LOG(PIL_CRIT, "%s: no active outlet for '%s'.", __FUNCTION__, host);
+ return (S_BADHOST);
+ }
+
+
+ /* choose the OID for the stonith request */
+ switch (request) {
+ case ST_POWERON:
+ req_oid = OUTLET_ON;
+ break;
+ case ST_POWEROFF:
+ req_oid = OUTLET_OFF;
+ break;
+ case ST_GENERIC_RESET:
+ req_oid = OUTLET_REBOOT;
+ break;
+ default: break;
+ }
+
+ /* Turn them all off */
+
+ /* prepare objnames */
+
+ switch (ad->mib_version) {
+ case 3:
+ snprintf(objname,MAX_STRING,OID_GROUP_STATE_V3,found_outlet);
+ break;
+ case 1:
+ default:
+ snprintf(objname,MAX_STRING,OID_GROUP_STATE_V1,found_outlet);
+ break;
+ }
+
+ snprintf(value, MAX_STRING, "%i", req_oid);
+
+ /* send reboot cmd */
+ if (!MPC_write(ad->sptr, objname, 'i', value)) {
+ LOG(PIL_CRIT
+ , "%s: cannot send reboot command for outlet %d."
+ , __FUNCTION__, found_outlet);
+ return (S_RESETFAIL);
+ }
+
+ return (S_OK);
+}
+
+/*
+ * Get the configuration parameter names.
+ */
+
+static const char * const *
+wti_mpc_get_confignames(StonithPlugin * s)
+{
+ static const char * ret[] = {ST_IPADDR, ST_PORT, ST_COMMUNITY, ST_MIBVERSION, NULL};
+ return ret;
+}
+
+/*
+ * Set the configuration parameters.
+ */
+
+static int
+wti_mpc_set_config(StonithPlugin * s, StonithNVpair * list)
+{
+ struct pluginDevice* sd = (struct pluginDevice *)s;
+ int rc;
+ char * i;
+ int mo;
+ char objname[MAX_STRING];
+ StonithNamesToGet namestocopy [] =
+ { {ST_IPADDR, NULL}
+ , {ST_PORT, NULL}
+ , {ST_COMMUNITY, NULL}
+ , {ST_MIBVERSION, NULL}
+ , {NULL, NULL}
+ };
+
+ DEBUGCALL;
+ ERRIFWRONGDEV(s,S_INVAL);
+ if (sd->sp.isconfigured) {
+ return S_OOPS;
+ }
+
+ if ((rc=OurImports->CopyAllValues(namestocopy, list)) != S_OK) {
+ return rc;
+ }
+ sd->hostname = namestocopy[0].s_value;
+ sd->port = atoi(namestocopy[1].s_value);
+ PluginImports->mfree(namestocopy[1].s_value);
+ sd->community = namestocopy[2].s_value;
+ sd->mib_version = atoi(namestocopy[3].s_value);
+ PluginImports->mfree(namestocopy[3].s_value);
+
+ /* try to resolve the hostname/ip-address */
+ if (gethostbyname(sd->hostname) != NULL) {
+ /* init snmp library */
+ init_snmp("wti_mpc");
+
+ /* now try to get a snmp session */
+ if ((sd->sptr = MPC_open(sd->hostname, sd->port, sd->community)) != NULL) {
+
+ /* ok, get the number of groups from the mpc */
+ sd->num_outlets=0;
+ /* We scan goup names table starting from 1 to MAX_OUTLETS */
+ /* and increase num_outlet counter on every group entry with name */
+ /* first entry without name is the mark of the end of the group table */
+ for (mo=1;mo<MAX_OUTLETS;mo++) {
+ switch (sd->mib_version) {
+ case 3:
+ snprintf(objname,MAX_STRING,OID_GROUP_NAMES_V3,mo);
+ break;
+ case 1:
+ default:
+ snprintf(objname,MAX_STRING,OID_GROUP_NAMES_V1,mo);
+ break;
+ }
+
+ if (Debug) {
+ LOG(PIL_DEBUG, "%s: used for groupTable retrieval: %s."
+ , __FUNCTION__, objname);
+ }
+
+ if ((i = MPC_read(sd->sptr, objname, ASN_OCTET_STR)) == NULL) {
+ LOG(PIL_CRIT
+ , "%s: cannot read number of outlets."
+ , __FUNCTION__);
+ return (S_ACCESS);
+ }
+ if (strlen(i)) {
+ /* store the number of outlets */
+ sd->num_outlets++;
+ } else {
+ break;
+ }
+ }
+ if (Debug) {
+ LOG(PIL_DEBUG, "%s: number of outlets: %i."
+ , __FUNCTION__, sd->num_outlets );
+ }
+
+ /* Everything went well */
+ return (S_OK);
+ }else{
+ LOG(PIL_CRIT, "%s: cannot create snmp session."
+ , __FUNCTION__);
+ }
+ }else{
+ LOG(PIL_CRIT, "%s: cannot resolve hostname '%s', h_errno %d."
+ , __FUNCTION__, sd->hostname, h_errno);
+ }
+
+ /* not a valid config */
+ return (S_BADCONFIG);
+}
+
+/*
+ * get info about the stonith device
+ */
+
+static const char *
+wti_mpc_getinfo(StonithPlugin * s, int reqtype)
+{
+ struct pluginDevice *ad;
+ const char *ret = NULL;
+
+ DEBUGCALL;
+
+ ERRIFWRONGDEV(s, NULL);
+
+ ad = (struct pluginDevice *) s;
+
+ switch (reqtype) {
+ case ST_DEVICEID:
+ ret = ad->idinfo;
+ break;
+
+ case ST_DEVICENAME:
+ ret = ad->hostname;
+ break;
+
+ case ST_DEVICEDESCR:
+ ret = "WTI MPC (via SNMP)\n"
+ "The WTI MPC can accept multiple simultaneous SNMP clients";
+ break;
+
+ case ST_DEVICEURL:
+ ret = "http://www.wti.com/";
+ break;
+
+ case ST_CONF_XML: /* XML metadata */
+ ret = apcmastersnmpXML;
+ break;
+
+ }
+ return ret;
+}
+
+
+/*
+ * APC StonithPlugin destructor...
+ */
+
+static void
+wti_mpc_destroy(StonithPlugin * s)
+{
+ struct pluginDevice *ad;
+
+ DEBUGCALL;
+
+ VOIDERRIFWRONGDEV(s);
+
+ ad = (struct pluginDevice *) s;
+
+ ad->pluginid = NOTpluginID;
+
+ /* release snmp session */
+ if (ad->sptr != NULL) {
+ snmp_close(ad->sptr);
+ ad->sptr = NULL;
+ }
+
+ /* reset defaults */
+ if (ad->hostname != NULL) {
+ PluginImports->mfree(ad->hostname);
+ ad->hostname = NULL;
+ }
+ if (ad->community != NULL) {
+ PluginImports->mfree(ad->community);
+ ad->community = NULL;
+ }
+ ad->num_outlets = 0;
+
+ PluginImports->mfree(ad);
+}
+
+/*
+ * Create a new APC StonithPlugin device. Too bad this function can't be
+ * static
+ */
+
+static StonithPlugin *
+wti_mpc_new(const char *subplugin)
+{
+ struct pluginDevice *ad = ST_MALLOCT(struct pluginDevice);
+
+ DEBUGCALL;
+
+ /* no memory for stonith-object */
+ if (ad == NULL) {
+ LOG(PIL_CRIT, "%s: out of memory.", __FUNCTION__);
+ return (NULL);
+ }
+
+ /* clear stonith-object */
+ memset(ad, 0, sizeof(*ad));
+
+ /* set defaults */
+ ad->pluginid = pluginid;
+ ad->sptr = NULL;
+ ad->hostname = NULL;
+ ad->community = NULL;
+ ad->mib_version=1;
+ ad->idinfo = DEVICE;
+ ad->sp.s_ops = &wti_mpcOps;
+
+ /* return the object */
+ return (&(ad->sp));
+}