⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 apcmastersnmp.c

📁 在LINUX下实现HA的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: apcmastersnmp.c,v 1.8.2.5 2005/04/27 18:58:41 blaschke Exp $ *//* * Stonith module for APC Masterswitch (SNMP) * Copyright (c) 2001 Andreas Piesk <a.piesk@gmx.net> * * 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 <portability.h>#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <stdio.h>#include <stdlib.h>#include <syslog.h>#include <errno.h>#include <libintl.h>#include <netdb.h>#include <string.h>#include <unistd.h>#include <glib.h>#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#include <stonith/stonith.h>#define PIL_PLUGINTYPE          STONITH_TYPE#define PIL_PLUGINTYPE_S        STONITH_TYPE_S#define PIL_PLUGIN              apcmastersnmp#define PIL_PLUGIN_S            "apcmastersnmp"#define PIL_PLUGINLICENSE 	LICENSE_LGPL#define PIL_PLUGINLICENSEURL 	URL_LGPL#include <pils/plugin.h>/* * apcmastersnmpclose is called as part of unloading the apcmastersnmp STONITH plugin. * If there was any global data allocated, or file descriptors opened, etc. * which is associated with the plugin, and not a single interface * in particular, here's our chance to clean it up. */static voidapcmastersnmpclosepi(PILPlugin*pi){}/* * apcmastersnmpcloseintf called as part of shutting down the apcmastersnmp STONITH * interface.  If there was any global data allocated, or file descriptors * opened, etc.  which is associated with the apcmastersnmp implementation, * here's our chance to clean it up. */static PIL_rcapcmastersnmpcloseintf(PILInterface* pi, void* pd){	return PIL_OK;}void *		apcmastersnmp_new(void);void		apcmastersnmp_destroy(Stonith *);int		apcmastersnmp_set_config_file(Stonith *, const char * cfgname);int		apcmastersnmp_set_config_info(Stonith *, const char * info);const char *	apcmastersnmp_getinfo(Stonith * s, int InfoType);int		apcmastersnmp_status(Stonith * );int		apcmastersnmp_reset_req(Stonith * s, int request, const char * host);char **		apcmastersnmp_hostlist(Stonith  *);void		apcmastersnmp_free_hostlist(char **);static struct stonith_ops apcmastersnmpOps ={	apcmastersnmp_new,		/* Create new STONITH object	*/	apcmastersnmp_destroy,		/* Destroy STONITH object	*/	apcmastersnmp_set_config_file,	/* set configuration from file	*/	apcmastersnmp_set_config_info,	/* Get configuration from file	*/	apcmastersnmp_getinfo,		/* Return STONITH info string	*/	apcmastersnmp_status,		/* Return STONITH device status	*/	apcmastersnmp_reset_req,	/* Request a reset */	apcmastersnmp_hostlist,		/* Return list of supported hosts */	apcmastersnmp_free_hostlist	/* free above list */};PIL_PLUGIN_BOILERPLATE("1.0", Debug, apcmastersnmpclosepi);static const PILPluginImports*  PluginImports;static PILPlugin*               OurPlugin;static PILInterface*		OurInterface;static StonithImports*		OurImports;static void*			interfprivate;#define APC_MALLOC		PluginImports->alloc#define APC_STRDUP  		PluginImports->mstrdup#define APC_FREE		PluginImports->mfreePIL_rcPIL_PLUGIN_INIT(PILPlugin*us, const PILPluginImports* imports);PIL_rcPIL_PLUGIN_INIT(PILPlugin*us, const PILPluginImports* imports){	/* Force the compiler to do a little type checking */	(void)(PILPluginInitFun)PIL_PLUGIN_INIT;	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	,	&apcmastersnmpOps	,	apcmastersnmpcloseintf		/*close */	,	&OurInterface	,	(void*)&OurImports	,	&interfprivate); }/* * APCMaster tested with APC Masterswitch 9212 *//* device ID */#define	DEVICE				"APCMasterSNMP-Stonith"/* outlet commands / status codes */#define OUTLET_ON			1#define OUTLET_OFF			2#define OUTLET_REBOOT			3#define OUTLET_NO_CMD_PEND		2/* oids */#define OID_IDENT			".1.3.6.1.4.1.318.1.1.4.1.4.0"#define OID_NUM_OUTLETS			".1.3.6.1.4.1.318.1.1.4.4.1.0"#define OID_OUTLET_NAMES		".1.3.6.1.4.1.318.1.1.4.5.2.1.3.%i"#define OID_OUTLET_STATE		".1.3.6.1.4.1.318.1.1.4.4.2.1.3.%i"#define OID_OUTLET_COMMAND_PENDING	".1.3.6.1.4.1.318.1.1.4.4.2.1.2.%i"#define OID_OUTLET_REBOOT_DURATION	".1.3.6.1.4.1.318.1.1.4.5.2.1.5.%i"/* own defines */#define MAX_STRING			128/* structur of stonith object */struct APCDevice {    const char *APCid;		/* id of object */    struct snmp_session *sptr;	/* != NULL -> session created */    char *hostname;		/* masterswitch's hostname or ip address */    int port;			/* snmp port */    char *community;		/* snmp community (r/w access) */    int num_outlets;		/* number of outlets */};/* for checking hardware (issue a warning if mismatch) */static const char* APC_tested_ident[] = {"AP9606","AP7920","AP_other_well_tested"};/* constant strings */static const char *APCid = DEVICE;static const char *NOTapcID = "destroyed (APCMasterswitch)";#ifndef MIN/* some macros */#	define MIN( i, j ) ( i > j ? j : i )#endif#define	ISAPCDEV(i) (((i)!= NULL && (i)->pinfo != NULL)	&& \                    ((struct APCDevice *)(i->pinfo))->APCid == APCid)#define ISCONFIGED(i) (((struct APCDevice *)(i->pinfo))->sptr != NULL )#define _(text) dgettext(ST_TEXTDOMAIN, text)#ifndef APC_MALLOCT#  define APC_MALLOCT(t) ((t *)(APC_MALLOC(sizeof(t))))#endif/* * stonith prototypes  *//* * own prototypes  */void APC_error(struct snmp_session *sptr, const char *fn, const char *msg);struct snmp_session *APC_open(char *hostname, int port, char *community);int APC_parse_config_info(struct APCDevice *ad, const char *info);void *APC_read(struct snmp_session *sptr, const char *objname, int type);int APC_write(struct snmp_session *sptr, const char *objname, char type,	      char *value);/* *  log snmp error */void APC_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);    syslog(LOG_ERR,        "%s: %s (cliberr: %i / snmperr: %i / error: %s).",	fn, msg, cliberr, snmperr, errstr);    free(errstr);}/* *  creates a snmp session */struct snmp_session *APC_open(char *hostname, int port, char *community){    static struct snmp_session session;    struct snmp_session *sptr;    /* create session */    snmp_sess_init(&session);    /* fill session */    session.peername = hostname;    session.version = SNMP_VERSION_1;    session.remote_port = port;    session.community = (unsigned char*) community;    session.community_len = strlen(community);    session.retries = 5;    session.timeout = 1000000;    /* open session */    sptr = snmp_open(&session);    if (sptr == NULL) {        APC_error(&session, __FUNCTION__, "cannot open snmp session");    }    /* return pointer to opened session */    return (sptr);}/* * parse config */intAPC_parse_config_info(struct APCDevice *ad, const char *info){    static char hostname[MAX_STRING];    static int port;    static char community[MAX_STRING];    int *i;#ifdef APC_DEBUG    syslog(LOG_DEBUG, "%s: called.", __FUNCTION__);#endif    if (sscanf(info, "%s %i %s", hostname, &port, community) == 3) {	ad->hostname = hostname;	ad->port = port;	ad->community = community;	/* try to resolve the hostname/ip-address */	if (gethostbyname(hostname) != NULL) {            /* init snmp library */            init_snmp("apcmastersnmp");	    /* now try to get a snmp session */	    if ((ad->sptr = APC_open(hostname, port, community)) != NULL) {		/* ok, get the number of outlets from the masterswitch */		if ((i = APC_read(ad->sptr, OID_NUM_OUTLETS, ASN_INTEGER))		    == NULL) {		    syslog(LOG_ERR, "%s: cannot read number of outlets.",			   __FUNCTION__);		    return (S_ACCESS);		}		/* store the number of outlets */		ad->num_outlets = *i;#ifdef APC_DEBUG		syslog(LOG_DEBUG, "%s: number of outlets: %i.",			   __FUNCTION__, ad->num_outlets );#endif		/* everything went well */		return (S_OK);	    }else{	        syslog(LOG_ERR, "%s: cannot create snmp session.",	            __FUNCTION__);            }	}else{            syslog(LOG_ERR, "%s: cannot resolve hostname '%s', h_errno %d.",               __FUNCTION__, hostname, h_errno);        }    }else{        syslog(LOG_ERR, "%s: cannot parse config info '%s'.", __FUNCTION__,            info);    }    /* no valid config */    return (S_BADCONFIG);}/* * read value of given oid and return it as string */void *APC_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;#ifdef APC_DEBUG    syslog(LOG_DEBUG, "%s: requested objname '%s'.", __FUNCTION__, objname );#endif    /* convert objname into oid; return NULL if invalid */    if (!read_objid(objname, name, &namelen)) {        syslog(LOG_ERR, "%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{		syslog(LOG_ERR, "%s: error in response packet, reason %ld [%s].",                    __FUNCTION__, resp->errstat, snmp_errstring(resp->errstat));	    }	}else{            APC_error(sptr, __FUNCTION__, "error sending/receiving pdu");        }	/* free repsonse pdu (necessary?) */	snmp_free_pdu(resp);    }else{        APC_error(sptr, __FUNCTION__, "cannot create pdu");    }    /* error: return nothing */    return (NULL);}/* * write value of given oid */intAPC_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;#ifdef APC_DEBUG    syslog(LOG_DEBUG, "%s: requested objname '%s'.", __FUNCTION__, objname );#endif    /* convert objname into oid; return NULL if invalid */    if (!read_objid(objname, name, &namelen)) {        syslog(LOG_ERR, "%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 {		syslog(LOG_ERR, "%s: error in response packet, reason %ld [%s].",                    __FUNCTION__, resp->errstat, snmp_errstring(resp->errstat));	    }	}else{            APC_error(sptr, __FUNCTION__, "error sending/receiving pdu");	}	/* free pdu (again: necessary?) */	snmp_free_pdu(resp);    }else{        APC_error(sptr, __FUNCTION__, "cannot create pdu");    }    /* error */    return (FALSE);}/* * return the status for this device  */int apcmastersnmp_status(Stonith * s){    struct APCDevice *ad;    char *ident;    int i;#ifdef APC_DEBUG    syslog(LOG_DEBUG, "%s: called.", __FUNCTION__);#endif    if (!ISAPCDEV(s)) {	syslog(LOG_ERR, "%s: invalid argument.", __FUNCTION__);	return (S_INVAL);    }    if (!ISCONFIGED(s)) {	syslog(LOG_ERR, "%s: device is UNCONFIGURED!", __FUNCTION__);	return (S_OOPS);    }    ad = (struct APCDevice *) s->pinfo;    if ((ident = APC_read(ad->sptr, OID_IDENT, ASN_OCTET_STR)) == NULL) {	syslog(LOG_ERR, "%s: cannot read ident.", __FUNCTION__);	return (S_ACCESS);    }    /* issue a warning if ident mismatches */    for(i=DIMOF(APC_tested_ident) -1; i >=0 ; i--)      if (strcmp(ident, APC_tested_ident[i]) == 0) break;    if (i<0) {	syslog(LOG_WARNING,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -