📄 ping_group.c
字号:
/* $Id: ping_group.c,v 1.13 2004/10/24 13:00:13 lge Exp $ *//* * ping_group.c: ICMP-echo-based heartbeat code for heartbeat. * * This allows a group of nodes to be pinged. The group is * considered to be available if any of the nodes are available. * * Copyright (C) 2003 Horms <horms@verge.net.au> * * Based heavily on ping.c * Copyright (C) 2000 Alan Robertson <alanr@unix.sh> * * The checksum code in this file code was borrowed from the ping program. * * SECURITY NOTE: It would be very easy for someone to masquerade as the * device that you're pinging. If they don't know the password, all they can * do is echo back the packets that you're sending out, or send out old ones. * This does mean that if you're using such an approach, that someone could * make you think you have quorum when you don't during a cluster partition. * The danger in that seems small, but you never know ;-) * * 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>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <errno.h>#include <string.h>#include <ctype.h>#include <fcntl.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <sys/param.h>#ifdef HAVE_NETINET_IN_SYSTM_H# include <netinet/in_systm.h>#endif /* HAVE_NETINET_IN_SYSTM_H */#ifdef HAVE_NETINET_IP_H# include <netinet/ip.h>#endif /* HAVE_NETINET_IP_H */#include <netinet/ip_icmp.h>#ifdef HAVE_NETINET_IP_H# include <netinet/ip.h>#endif /* HAVE_NETINET_IP_H */#ifdef HAVE_NETINET_IP_VAR_H# include <netinet/ip_var.h>#endif /* HAVE_NETINET_IP_VAR_H */#ifdef HAVE_NETINET_IP_COMPAT_H# include <netinet/ip_compat.h>#endif /* HAVE_NETINET_IP_COMPAT_H */#ifdef HAVE_NETINET_IP_FW_H# include <netinet/ip_fw.h>#endif /* HAVE_NETINET_IP_FW_H */#include <netdb.h>#include <heartbeat.h>#include <HBcomm.h>#include <clplumbing/realtime.h>#ifdef linux# define ICMP_HDR_SZ sizeof(struct icmphdr) /* 8 */#else# define ICMP_HDR_SZ 8#endif#define PIL_PLUGINTYPE HB_COMM_TYPE#define PIL_PLUGINTYPE_S HB_COMM_TYPE_S#define PIL_PLUGIN ping_group#define PIL_PLUGIN_S "ping_group"#define PIL_PLUGINLICENSE LICENSE_LGPL#define PIL_PLUGINLICENSEURL URL_LGPL#include <pils/plugin.h>#define NSLOT 128 /* How old ping sequence numbers can be to still count */typedef struct ping_group_node ping_group_node_t;struct ping_group_node { struct sockaddr_in addr; /* ping addr */ ping_group_node_t *next;};typedef struct { int ident; /* heartbeat pid */ int sock; /* ping socket */ ping_group_node_t *node; size_t nnode; int slot[NSLOT]; int iseq; /* sequence number */} ping_group_private_t;static int ping_group_parse(const char *line);static int ping_group_open (struct hb_media* mp);static int ping_group_close (struct hb_media* mp);static void* ping_group_read (struct hb_media* mp, int* lenp);static int ping_group_write (struct hb_media* mp ,void* msg, int len);static struct hb_media * ping_group_new(const char *name);static int in_cksum (u_short * buf, size_t nbytes);static int ping_group_mtype(char **buffer);static int ping_group_descr(char **buffer);static int ping_group_isping(void);#define ISPINGGROUPOBJECT(mp) \ ((mp) && ((mp)->vf == (void*)&ping_group_ops))#define PINGGROUPASSERT(mp) g_assert(ISPINGGROUPOBJECT(mp))static struct hb_media_fns ping_group_ops ={ NULL, /* Create single object function */ ping_group_parse, /* whole-line parse function */ ping_group_open, ping_group_close, ping_group_read, ping_group_write, ping_group_mtype, ping_group_descr, ping_group_isping,};PIL_PLUGIN_BOILERPLATE2("1.0", Debug)static const PILPluginImports* PluginImports;static PILPlugin* OurPlugin;static PILInterface* OurInterface;static struct hb_media_imports* OurImports;static void* interfprivate;#define LOG PluginImports->log#define MALLOC PluginImports->alloc#define STRDUP PluginImports->mstrdup#define 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 , &ping_group_ops , NULL /*close */ , &OurInterface , (void*)&OurImports , interfprivate); }static intping_group_mtype(char **buffer) { *buffer = STRDUP(PIL_PLUGIN_S); if (!*buffer) { return 0; } return strlen(*buffer);}static intping_group_descr(char **buffer) { *buffer = STRDUP("ping group membership"); if (!*buffer) { return 0; } return strlen(*buffer);}/* Yes, a ping device */static intping_group_isping(void) { return 1;}static ping_group_node_t *new_ping_group_node(const char *host){ ping_group_node_t* node; node = (ping_group_node_t*)MALLOC(sizeof(ping_group_node_t)); if(!node) { return(NULL); } memset(node, 0, sizeof(ping_group_node_t));#ifdef HAVE_SOCKADDR_IN_SIN_LEN node->addr.sin_len = sizeof(struct sockaddr_in);#endif node->addr.sin_family = AF_INET; if (inet_pton(AF_INET, host, (void *)&node->addr.sin_addr) <= 0) { struct hostent *hp; hp = gethostbyname(host); if (hp == NULL) { PILCallLog(LOG, PIL_CRIT, "unknown host: %s: %s" , host, strerror(errno)); FREE(node); return NULL; } node->addr.sin_family = hp->h_addrtype; memcpy(&node->addr.sin_addr, hp->h_addr, hp->h_length); } return(node);}static intping_group_add_node(struct hb_media* media, const char *host){ ping_group_private_t *priv; ping_group_node_t *node; PINGGROUPASSERT(media); priv = (ping_group_private_t *)media->pd; node = new_ping_group_node(host); if(!node) { return(HA_FAIL); } node->next = priv->node; priv->node = node; priv->nnode++; return(HA_OK);}/* * Create new ping heartbeat object * Name of host is passed as a parameter */static struct hb_media *ping_group_new(const char *name){ ping_group_private_t* priv; struct hb_media * media; char * tmp; priv = (ping_group_private_t*)MALLOC(sizeof(ping_group_private_t)); if(!priv) { return(NULL); } memset(priv, 0, sizeof(ping_group_private_t)); priv->ident = getpid() & 0xFFFF; media = (struct hb_media *) MALLOC(sizeof(struct hb_media)); if(!media) { FREE(priv); return(NULL); } media->pd = (void*)priv; tmp = STRDUP(name); if(!tmp) { FREE(priv); FREE(media); return(NULL); } media->name = tmp; add_node(tmp, PINGNODE_I); /* Fake it so that PINGGROUPASSERT() will work * before the media is registered */ media->vf = (void*)&ping_group_ops; return(media);}static voidping_group_destroy_data(struct hb_media* media){ ping_group_private_t* priv; ping_group_node_t * node; PINGGROUPASSERT(media); priv = (ping_group_private_t *)media->pd; while(priv->node) { node = priv->node; priv->node = node->next; FREE(node); }}static voidping_group_destroy(struct hb_media* media){ ping_group_private_t* priv; PINGGROUPASSERT(media); priv = (ping_group_private_t *)media->pd; ping_group_destroy_data(media); FREE(priv); media->pd = NULL; /* XXX: How can we free this? Should media->name really be const? * And on the same topic, how are media unregistered / freed ? */ /* tmp = (char *)media->name; FREE(tmp); media->name = NULL; */}/* * Close UDP/IP broadcast heartbeat interface */static intping_group_close(struct hb_media* mp){ ping_group_private_t * ei; int rc = HA_OK; PINGGROUPASSERT(mp); ei = (ping_group_private_t *) mp->pd; if (ei->sock >= 0) { if (close(ei->sock) < 0) { rc = HA_FAIL; } } ping_group_destroy_data(mp); return(rc);}/* * Receive a heartbeat ping reply packet. */static void *ping_group_read(struct hb_media* mp, int *lenp){ ping_group_private_t * ei; union { char cbuf[MAXLINE+ICMP_HDR_SZ];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -