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

📄 ipmilan.c

📁 在LINUX下实现HA的源代码
💻 C
字号:
/* $Id: ipmilan.c,v 1.3.2.5 2004/12/02 02:02:42 yixiong Exp $ *//* * Stonith module for ipmi lan Stonith device * * Copyright (c) 2003 Intel Corp.  *	Yixiong Zou <yixiong.zou@intel.com> * * 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 * *//* * See RADEME.ipmi for information regarding this plugin. * */#include <portability.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <errno.h>#include <syslog.h>#include <libintl.h>#include <sys/wait.h>#include <glib.h>#include <stonith/stonith.h>#define PIL_PLUGINTYPE          STONITH_TYPE#define PIL_PLUGINTYPE_S        STONITH_TYPE_S#define PIL_PLUGIN              ipmilan#define PIL_PLUGIN_S            "ipmilan"#define PIL_PLUGINLICENSE 	LICENSE_LGPL#define PIL_PLUGINLICENSEURL 	URL_LGPL#include <pils/plugin.h>#include <OpenIPMI/ipmi_types.h>#include <OpenIPMI/ipmi_auth.h>#include "ipmilan.h"/* * ipmilanclose is called as part of unloading the ipmilan 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 voidipmilanclosepi(PILPlugin*pi){}/* * ipmilancloseintf called as part of shutting down the ipmilan STONITH * interface.  If there was any global data allocated, or file descriptors * opened, etc.  which is associated with the ipmilan implementation, * here's our chance to clean it up. */static PIL_rcipmilancloseintf(PILInterface* pi, void* pd){	return PIL_OK;}static void *		ipmilan_new(void);static void		ipmilan_destroy(Stonith *);static int		ipmilan_set_config_file(Stonith *, const char * cfgname);static int		ipmilan_set_config_info(Stonith *, const char * info);static const char *	ipmilan_getinfo(Stonith * s, int InfoType);static int		ipmilan_status(Stonith * );static int		ipmilan_reset_req(Stonith * s, int request, const char * host);static char **		ipmilan_hostlist(Stonith  *);static void		ipmilan_free_hostlist(char **);static struct stonith_ops ipmilanOps ={	ipmilan_new,		/* Create new STONITH object	*/	ipmilan_destroy,		/* Destroy STONITH object	*/	ipmilan_set_config_file,	/* set configuration from file	*/	ipmilan_set_config_info,	/* Get configuration from file	*/	ipmilan_getinfo,		/* Return STONITH info string	*/	ipmilan_status,		/* Return STONITH device status	*/	ipmilan_reset_req,		/* Request a reset */	ipmilan_hostlist,		/* Return list of supported hosts */	ipmilan_free_hostlist	/* free above list */};PIL_PLUGIN_BOILERPLATE("1.0", Debug, ipmilanclosepi);static const PILPluginImports*  PluginImports;static PILPlugin*               OurPlugin;static PILInterface*		OurInterface;static StonithImports*		OurImports;static void*			interfprivate;#define LOG		PluginImports->log#define MALLOC		PluginImports->alloc#define STRDUP  	PluginImports->mstrdup#define FREE		PluginImports->mfree#define EXPECT_TOK	OurImports->ExpectToken#define STARTPROC	OurImports->StartProcessPIL_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	,	&ipmilanOps	,	ipmilancloseintf		/*close */	,	&OurInterface	,	(void*)&OurImports	,	&interfprivate); }#define	DEVICE	"ipmilan STONITH device"#define WHITESPACE	" \t\n\r\f"/* *	ipmilan STONITH device.   *  * 	ipmilanHostInfo is a double linked list. Where the prev of the head always *	points to the tail.  This is a little wierd.  But it saves me from looping *	around to find the tail when destroying the list. */struct ipmilanDevice {	const char *	ipmiid;	int		hostcount;	struct ipmilanHostInfo * 	hostlist;};static const char * ipmilanid = "ipmilanDevice-Stonith";static const char * NOTipmilanID = "Hey, dummy this has been destroyed (ipmilanDev)";#define	ISipmilanDEV(i)	(((i)!= NULL && (i)->pinfo != NULL)	\	&& ((struct ipmilanDevice *)(i->pinfo))->ipmiid == ipmilanid)#ifndef MALLOC#	define	MALLOC	malloc#endif#ifndef FREE#	define	FREE	free#endif#ifndef MALLOCT#	define     MALLOCT(t)      ((t *)(MALLOC(sizeof(t)))) #endif#define N_(text)	(text)#define _(text)		dgettext(ST_TEXTDOMAIN, text)/* * Check the status of the IPMI Lan STONITH device.  *  * NOTE: not sure what we should do here since each host is configured * seperately. *      * Two options:  *   1) always return S_OK.  *   2) using IPMI ping to confirm the status for every host that's *      configured.  *  * For now I choose the option 1 hoping that I can get by. Maybe we should * change it to option 2 later.  */static intipmilan_status(Stonith  *s){	struct ipmilanDevice * nd;	struct ipmilanHostInfo * node;	int ret;	if (!ISipmilanDEV(s)) {		syslog(LOG_ERR, "invalid argument to ipmilan_status");		return(S_OOPS);	}	ret = S_OK;	nd = (struct ipmilanDevice *)s->pinfo;	node = nd->hostlist;#if 0	do {		ret = send_ipmi_msg(node, ST_IPMI_STATUS);		if (ret) {			syslog(LOG_INFO, _("Host %s ipmilan status failure."), node->hostname);			ret = S_ACCESS;		} else {			syslog(LOG_INFO, _("Host %s ipmilan status OK."), node->hostname);		}		node = node->next;	} while (node);#endif	return ret;}/* * This function returns the list of hosts that's configured.  * * The detailed configuration is disabled because the STONITH command can be * run by anyone so there is a security risk if that to be exposed. */static char *get_config_string(struct ipmilanDevice * nd, int index){	struct ipmilanHostInfo * host;	int i;	char * buf;	if (index >= nd->hostcount || index < 0) {		return (NULL);	}	host = nd->hostlist;	for (i = 0; i < index; i++) {		host = host->next;	}	buf = STRDUP(host->hostname);	if (!buf) {		return (NULL);	}	g_strdown(buf);	return buf;}/* *	Return the list of hosts configured for this ipmilan device *	 */static char **ipmilan_hostlist(Stonith  *s){	int		numnames = 0;	char **		ret = NULL;	struct ipmilanDevice*	nd;	int		j;	if (!ISipmilanDEV(s)) {		syslog(LOG_ERR, "invalid argument to ipmilan_hostlist");		return(NULL);	}	nd = (struct ipmilanDevice*) s->pinfo;	if (nd->hostcount < 0) {		syslog(LOG_ERR		,	"unconfigured stonith object in ipmi_hostlist");		return(NULL);	}	numnames = nd->hostcount;	ret = (char **)MALLOC((numnames + 1)*sizeof(char*));	if (ret == NULL) {		syslog(LOG_ERR, "out of memory");		return (ret);	}	memset(ret, 0, (numnames + 1)*sizeof(char*));	for (j = 0; j < numnames; ++j) {		ret[j] = get_config_string(nd, j);		if (!ret[j]) {			ipmilan_free_hostlist(ret);			ret = NULL;			break;		}		g_strdown(ret[j]);	}	return(ret);}static voidipmilan_free_hostlist (char ** hlist){	char **	hl = hlist;	if (hl == NULL) {		return;	}	while (*hl) {		FREE(*hl);		*hl = NULL;		++hl;	}	FREE(hlist);	hlist = NULL;}/* *	Parse the config information, and stash it away... * *	The buffer for each string is MAX_IPMI_STRING_LEN bytes long. *      Right now it is set to 64. Hope this is enough. *	 */#define MAX_IPMI_STRING_LEN 64static intipmilan_parse_config_info(struct ipmilanDevice* nd, const char * info){	static int port;	static char name[MAX_IPMI_STRING_LEN];	static char ip[MAX_IPMI_STRING_LEN]; 	static char auth[MAX_IPMI_STRING_LEN];	static char priv[MAX_IPMI_STRING_LEN];	static char user[MAX_IPMI_STRING_LEN];	static char pass[MAX_IPMI_STRING_LEN];	struct ipmilanHostInfo * hostinfo, * head, * tail;	port = 0;	hostinfo = NULL;	memset(name, 0, MAX_IPMI_STRING_LEN);	memset(ip, 0, MAX_IPMI_STRING_LEN);	memset(auth, 0, MAX_IPMI_STRING_LEN);	memset(priv, 0, MAX_IPMI_STRING_LEN);	memset(user, 0, MAX_IPMI_STRING_LEN);	memset(pass, 0, MAX_IPMI_STRING_LEN);	do {		if (sscanf(info, "%s %s %i %s %s %s %[^\r\n\t]", 			name, ip, &port, auth, priv, user, pass) == 7 && 			strlen(user) > 1 && strlen(pass) > 1) {			if ((hostinfo = (struct ipmilanHostInfo *) MALLOC(sizeof(struct ipmilanHostInfo))) == NULL) {				syslog(LOG_ERR, "out of memory");				return (S_OOPS);			}			hostinfo->portnumber = port;			if (strncmp(auth, "none", strlen(auth)) == 0) {				hostinfo->authtype = IPMI_AUTHTYPE_NONE;			} 			else if (strncmp(auth, "md2", strlen(auth)) == 0) {				hostinfo->authtype = IPMI_AUTHTYPE_MD2;			}			else if (strncmp(auth, "md5", strlen(auth)) == 0) {				hostinfo->authtype = IPMI_AUTHTYPE_MD5;			}			else if (strncmp(auth, "straight", strlen(auth)) == 0) {				hostinfo->authtype = IPMI_AUTHTYPE_STRAIGHT;			}			else {				break;			}			if (strncmp(priv, "admin", strlen(priv)) == 0) {				hostinfo->privilege = IPMI_PRIVILEGE_ADMIN;			}			else if (strncmp(priv, "operator", strlen(priv)) == 0) {				hostinfo->privilege = IPMI_PRIVILEGE_OPERATOR;			}			else {				break;			}			if ((hostinfo->hostname = STRDUP(name)) == NULL) {				break;			}			g_strdown(hostinfo->hostname);			if ((hostinfo->ipaddr = STRDUP(ip)) == NULL) {				FREE(hostinfo->hostname);				break;			}			if (strncmp(user, "\"\"", 2)==0) {				memset(hostinfo->username, 0, sizeof(hostinfo->username));			} else {				strncpy(hostinfo->username, user, strlen(user)+1);			}			if (strncmp(pass, "\"\"", 2)==0) {				memset(hostinfo->password, 0, sizeof(hostinfo->password));			} else {				strncpy(hostinfo->password, pass, strlen(pass)+1);			}			hostinfo->next = NULL;			head = nd->hostlist;			// find the last one in the list			if (head) {				tail = head->prev;				tail->next = hostinfo;				hostinfo->prev = tail;				head->prev = hostinfo;			} else {				nd->hostlist = hostinfo;				hostinfo->prev = hostinfo;			}			// increment the host counter			nd->hostcount++;			return (S_OK);		} 		else {			break;		}	} while (0); // using this do loop here so we can have 'break' statement.	if (hostinfo) {		FREE(hostinfo);		hostinfo = NULL;	}	return (S_BADCONFIG);}/* *	Reset the given host on this Stonith device. */static intipmilan_reset_req(Stonith * s, int request, const char * host){	int rc = 0;	char *shost;	struct ipmilanDevice * nd;	struct ipmilanHostInfo * node;	if (!ISipmilanDEV(s)) {		syslog(LOG_ERR, "invalid stonith device argument to %s", __FUNCTION__);		return(S_OOPS);	}		if ((shost = STRDUP(host)) == NULL) {		syslog(LOG_ERR, "strdup failed in %s", __FUNCTION__);	}	g_strdown(shost);	nd = (struct ipmilanDevice *)s->pinfo;	node = nd->hostlist;	do {		if (strcmp(node->hostname, host) == 0) {			break;		};		node = node->next;	} while (node);		free(shost);		if (!node) {		syslog(LOG_ERR, _("host %s is not configured in this STONITH module. Please check you configuration file."), host);		return (S_OOPS);	}	rc = do_ipmi_cmd(node, request);	if (!rc) {		syslog(LOG_INFO, _("Host %s ipmilan-reset."), host);	} else {		syslog(LOG_INFO, _("Host %s ipmilan-reset error. Error = %d."), host, rc);	}	return rc;}/* *	Parse the information in the given configuration file, *	and stash it away... */static intipmilan_set_config_file(Stonith* s, const char * configname){	FILE *	cfgfile;	char	ipmiline[256];	struct ipmilanDevice*	nd;	int rc = S_BADCONFIG;	if (!ISipmilanDEV(s)) {		syslog(LOG_ERR, "invalid argument to ipmilan_set_configfile");		return(S_OOPS);	}	nd = (struct ipmilanDevice*) s->pinfo;	if ((cfgfile = fopen(configname, "r")) == NULL)  {		syslog(LOG_ERR, "Cannot open %s", configname);		return(S_BADCONFIG);	}	while (fgets(ipmiline, sizeof(ipmiline), cfgfile) != NULL){		if (*ipmiline == '#' || *ipmiline == '\n' || *ipmiline == EOS) {			continue;		}		if ((rc = ipmilan_parse_config_info(nd, ipmiline)) != S_OK) {			break;		};	}	fclose(cfgfile);	return(rc);}/* *	Parse the config information in the given string, and stash it away... */static intipmilan_set_config_info(Stonith* s, const char * info){	struct ipmilanDevice* nd;	if (!ISipmilanDEV(s)) {		syslog(LOG_ERR, "%s: invalid argument", __FUNCTION__);		return(S_OOPS);	}	nd = (struct ipmilanDevice *)s->pinfo;	return(ipmilan_parse_config_info(nd, info));}static const char *ipmilan_getinfo(Stonith * s, int reqtype){	struct ipmilanDevice* nd;	char *		ret;	if (!ISipmilanDEV(s)) {		syslog(LOG_ERR, "ipmilan_getinfo: invalid argument");		return NULL;	}	/*	 *	We look in the ST_TEXTDOMAIN catalog for our messages	 */	nd = (struct ipmilanDevice *)s->pinfo;	switch (reqtype) {		case ST_DEVICEID:			ret = _("ipmilan STONITH device");			break;		case ST_CONF_INFO_SYNTAX:			ret = _("hostname ipaddr port auth priv user pass \n"			"all fields are white-space delimited.");			break;		case ST_CONF_FILE_SYNTAX:			ret = _("hostname ipaddr port auth priv user pass \n"			"All fields are white-space delimited.  "			"Blank lines and lines beginning with # are ignored");			break;		case ST_DEVICEDESCR:			ret = _("IPMI_LAN STONITH device\n");			break;		default:			ret = NULL;			break;	}	return ret;}/* *	ipmilan Stonith destructor... * * 	The hostlist is a link list.  So have to iterate through. */static voidipmilan_destroy(Stonith *s){	struct ipmilanDevice* nd;	struct ipmilanHostInfo * host;	int i;	if (!ISipmilanDEV(s)) {		syslog(LOG_ERR, "%s: invalid argument", __FUNCTION__);		return;	}	nd = (struct ipmilanDevice *)s->pinfo;	nd->ipmiid = NOTipmilanID;	if (nd->hostlist) {		host = nd->hostlist->prev;		for (i = 0; i < nd->hostcount; i++) {			FREE(host->hostname);			FREE(host->ipaddr);			FREE(host);			host = host->prev;		}	}	nd->hostcount = -1;	FREE(nd);}/* Create a new ipmilan Stonith device.  Too bad this function can't be static */static void *ipmilan_new(void){	struct ipmilanDevice*	nd = MALLOCT(struct ipmilanDevice);	if (nd == NULL) {		syslog(LOG_ERR, "out of memory");		return(NULL);	}	memset(nd, 0, sizeof(*nd));	nd->ipmiid = ipmilanid;	nd->hostlist = NULL;	nd->hostcount = 0; 	return((void *)nd);}

⌨️ 快捷键说明

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