?? bcast.c
字號:
/* $Id: bcast.c,v 1.40 2004/10/24 13:00:13 lge Exp $ *//* * bcast.c: UDP/IP broadcast-based communication code for heartbeat. * * Copyright (C) 1999, 2000,2001 Alan Robertson <alanr@unix.sh> * * About 150 lines of the code in this file originally borrowed in * 1999 from Tom Vogt's "Heart" program, and significantly mangled by * Alan Robertson <alanr@unix.sh> * * 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 <net/if.h>#include <arpa/inet.h>#include <heartbeat.h>#include <HBcomm.h>#if defined(SO_BINDTODEVICE)# include <net/if.h>#endif#define PIL_PLUGINTYPE HB_COMM_TYPE#define PIL_PLUGINTYPE_S HB_COMM_TYPE_S#define PIL_PLUGIN bcast#define PIL_PLUGIN_S "bcast"#define PIL_PLUGINLICENSE LICENSE_LGPL#define PIL_PLUGINLICENSEURL URL_LGPL#include <pils/plugin.h>struct ip_private { char * interface; /* Interface name */ struct in_addr bcast; /* Broadcast address */ struct sockaddr_in addr; /* Broadcast addr */ int port; int rsocket; /* Read-socket */ int wsocket; /* Write-socket */};static int bcast_init(void);struct hb_media* bcast_new(const char* interface);static int bcast_open(struct hb_media* mp);static int bcast_close(struct hb_media* mp);static void* bcast_read(struct hb_media* mp, int *lenp);static int bcast_write(struct hb_media* mp, void* msg, int len);static int bcast_make_receive_sock(struct hb_media* ei);static int bcast_make_send_sock(struct hb_media * mp);static struct ip_private * new_ip_interface(const char * ifn, int port);static int bcast_descr(char** buffer);static int bcast_mtype(char** buffer);static int bcast_isping(void);static int localudpport = -1;int if_get_broadaddr(const char *ifn, struct in_addr *broadaddr);static struct hb_media_fns bcastOps ={ bcast_new, /* Create single object function */ NULL, /* whole-line parse function */ bcast_open, bcast_close, bcast_read, bcast_write, bcast_mtype, bcast_descr, bcast_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 , &bcastOps , NULL /*close */ , &OurInterface , (void*)&OurImports , interfprivate); }#define ISBCASTOBJECT(mp) ((mp) && ((mp)->vf == (void*)&bcastOps))#define BCASTASSERT(mp) g_assert(ISBCASTOBJECT(mp))static int bcast_mtype(char** buffer) { *buffer = STRDUP(PIL_PLUGIN_S); if (!*buffer) { return 0; } return STRLEN_CONST(PIL_PLUGIN_S);}static intbcast_descr(char **buffer) { const char constret[] = "UDP/IP broadcast"; *buffer = STRDUP(constret); if (!*buffer) { return 0; } return STRLEN_CONST(constret);}static intbcast_isping(void) { return 0;}static intbcast_init(void){ struct servent* service; g_assert(OurImports != NULL); if (localudpport <= 0) { const char * chport; if ((chport = OurImports->ParamValue("udpport")) != NULL) { sscanf(chport, "%d", &localudpport); if (localudpport <= 0) { PILCallLog(LOG, PIL_CRIT , "bad port number %s" , chport); return HA_FAIL; } } } /* No port specified in the configuration... */ if (localudpport <= 0) { /* If our service name is in /etc/services, then use it */ if ((service=getservbyname(HA_SERVICENAME, "udp")) != NULL){ localudpport = ntohs(service->s_port); }else{ localudpport = UDPPORT; } } return(HA_OK);}/* * Create new UDP/IP broadcast heartbeat object * Name of interface is passed as a parameter */struct hb_media *bcast_new(const char * intf){ struct ip_private* ipi; struct hb_media * ret; bcast_init(); ipi = new_ip_interface(intf, localudpport); if (DEBUGPKT) { PILCallLog(LOG, PIL_DEBUG, "bcast_new: attempting to open %s:%d", intf , localudpport); } if (ipi == NULL) { PILCallLog(LOG, PIL_CRIT, "IP interface [%s] does not exist" , intf); return(NULL); } ret = (struct hb_media*) MALLOC(sizeof(struct hb_media)); if (ret != NULL) { char * name; memset(ret, 0, sizeof(*ret)); ret->pd = (void*)ipi; name = STRDUP(intf); if (name != NULL) { ret->name = name; } else { FREE(ret); ret = NULL; } } if (ret != NULL) { if (DEBUGPKT) { PILCallLog(LOG, PIL_DEBUG, "bcast_new: returning ret (%s)", ret->name); } }else{ FREE(ipi->interface); FREE(ipi); if (DEBUGPKT) { PILCallLog(LOG, PIL_DEBUG, "bcast_new: ret was NULL"); } } return(ret);}/* * Open UDP/IP broadcast heartbeat interface */static intbcast_open(struct hb_media* mp){ struct ip_private * ei; BCASTASSERT(mp); ei = (struct ip_private *) mp->pd; if ((ei->wsocket = bcast_make_send_sock(mp)) < 0) { return(HA_FAIL); } if ((ei->rsocket = bcast_make_receive_sock(mp)) < 0) { bcast_close(mp); return(HA_FAIL); } PILCallLog(LOG, PIL_INFO , "UDP Broadcast heartbeat started on port %d (%d) interface %s" , localudpport, ei->port, mp->name); if (DEBUGPKT) { PILCallLog(LOG, PIL_DEBUG , "bcast_open : Socket %d opened for reading" ", socket %d opened for writing." , ei->rsocket, ei->wsocket); } return(HA_OK);}/* * Close UDP/IP broadcast heartbeat interface */static intbcast_close(struct hb_media* mp){ struct ip_private * ei; int rc = HA_OK; BCASTASSERT(mp); ei = (struct ip_private *) mp->pd; if (ei->rsocket >= 0) { if (close(ei->rsocket) < 0) { rc = HA_FAIL; } } if (ei->wsocket >= 0) { if (close(ei->wsocket) < 0) { rc = HA_FAIL; } } PILCallLog(LOG, PIL_INFO , "UDP Broadcast heartbeat closed on port %d interface %s - Status: %d" , localudpport, mp->name, rc); return(rc);}/* * Receive a heartbeat broadcast packet from BCAST interface */void *bcast_read(struct hb_media* mp, int * lenp){ struct ip_private * ei; char buf[MAXLINE]; int addr_len = sizeof(struct sockaddr); struct sockaddr_in their_addr; /* connector's addr information */ int numbytes; void *pkt; BCASTASSERT(mp); ei = (struct ip_private *) mp->pd; if (DEBUGPKT) { PILCallLog(LOG, PIL_DEBUG , "bcast_read : reading from socket %d (writing to socket %d)" , ei->rsocket, ei->wsocket); } if ((numbytes=recvfrom(ei->rsocket, buf, MAXLINE-1, MSG_WAITALL , (struct sockaddr *)&their_addr, &addr_len)) == -1) { if (errno != EINTR) { PILCallLog(LOG, PIL_CRIT , "Error receiving from socket: %s" , strerror(errno)); } return NULL; } /* Avoid possible buffer overruns */ buf[numbytes] = EOS; if (DEBUGPKT) { PILCallLog(LOG, PIL_DEBUG, "got %d byte packet from %s" , numbytes, inet_ntoa(their_addr.sin_addr)); } if (DEBUGPKTCONT && numbytes > 0) { PILCallLog(LOG, PIL_DEBUG, "%s", buf); } pkt = ha_malloc(numbytes + 1); if(!pkt){ PILCallLog(LOG, PIL_CRIT , "Error in allocating memory"); return(NULL); } memcpy(pkt, buf, numbytes + 1); *lenp = numbytes +1; return(pkt);}/* * Send a heartbeat packet over broadcast UDP/IP interface */static intbcast_write(struct hb_media* mp, void *pkt, int len){ struct ip_private * ei; int rc; BCASTASSERT(mp); ei = (struct ip_private *) mp->pd; if ((rc=sendto(ei->wsocket, pkt, len, 0 , (struct sockaddr *)&ei->addr , sizeof(struct sockaddr))) != len) { PILCallLog(LOG, PIL_CRIT, "Unable to send bcast [%d] packet: %s" , rc, strerror(errno)); return(HA_FAIL); } if (DEBUGPKT) { PILCallLog(LOG, PIL_DEBUG , "bcast_write : writing %d bytes to %s (socket %d)" , rc, inet_ntoa(ei->addr.sin_addr), ei->wsocket); } if (DEBUGPKTCONT) { PILCallLog(LOG, PIL_DEBUG, "bcast pkt out: [%s]", (char*)pkt); } return(HA_OK);}/* * Set up socket for sending broadcast UDP heartbeats */static intbcast_make_send_sock(struct hb_media * mp){ int sockfd, one = 1; struct ip_private * ei; BCASTASSERT(mp); ei = (struct ip_private *) mp->pd; if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { PILCallLog(LOG, PIL_CRIT , "Error getting socket: %s", strerror(errno)); return(sockfd); } if (DEBUGPKT) { PILCallLog(LOG, PIL_DEBUG , "bcast_make_send_sock: Opened socket %d", sockfd); } /* Warn that we're going to broadcast */ if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (const void *) &one, sizeof(one))==-1){ PILCallLog(LOG, PIL_CRIT , "Error setting socket option SO_BROADCAST: %s" , strerror(errno)); close(sockfd); return(-1); } if (DEBUGPKT) { PILCallLog(LOG, PIL_DEBUG , "bcast_make_send_sock: Modified %d" " Added option SO_BROADCAST." , sockfd); }#if defined(SO_DONTROUTE) && !defined(USE_ROUTING) /* usually, we don't want to be subject to routing. */ if (setsockopt(sockfd, SOL_SOCKET, SO_DONTROUTE,(const void *) &one,sizeof(int))==-1) { PILCallLog(LOG, PIL_CRIT , "Error setting socket option SO_DONTROUTE: %s" , strerror(errno)); close(sockfd); return(-1); } if (DEBUGPKT) { PILCallLog(LOG, PIL_DEBUG, "bcast_make_send_sock:" " Modified %d Added option SO_DONTROUTE." , sockfd); }#endif#if defined(SO_BINDTODEVICE) { /* * We want to send out this particular interface * * This is so we can have redundant NICs, and heartbeat on both */ struct ifreq i; strcpy(i.ifr_name, mp->name); if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE , (const void *) &i, sizeof(i)) == -1) { PILCallLog(LOG, PIL_CRIT , "Error setting socket option SO_BINDTODEVICE" ": %s" , strerror(errno)); close(sockfd); return(-1); } if (DEBUGPKT) { PILCallLog(LOG, PIL_DEBUG , "bcast_make_send_sock: Modified %d" " Added option SO_BINDTODEVICE." , sockfd); }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -