/* $Id: bcast.c,v 1.33.2.4 2005/01/12 02:25:47 horms 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);
/*
* bcastclose is called as part of unloading the bcast HBcomm 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 void
bcastclosepi(PILPlugin*pi)
{
}
/*
* bcastcloseintf called as part of shutting down the bcast HBcomm interface.
* If there was any global data allocated, or file descriptors opened, etc.
* which is associated with the bcast implementation, here's our chance
* to clean it up.
*/
static PIL_rc
bcastcloseintf(PILInterface* pi, void* pd)
{
return PIL_OK;
}
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_BOILERPLATE("1.0", Debug, bcastclosepi);
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->mfree
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;
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
, bcastcloseintf /*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(PIL_PLUGIN_S);
}
static int
bcast_descr(char **buffer) {
*buffer = STRDUP("UDP/IP broadcast");
if (!*buffer) {
return 0;
}
return strlen(*buffer);
}
static int
bcast_isping(void) {
return 0;
}
static int
bcast_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 int
bcast_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 int
bcast_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];
socklen_t 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 int
bcast_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 int
bcast_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);
}
}
#endif
if (fcntl(sockfd,F_SETFD, FD_CLOEXEC)) {
PILCallLog(LOG, PIL_CRIT
, "Error setting close-on-exec flag: %s"
, strerror(errno));
}
return(sockfd);
}
/*
* Set up socket for listening to heartbeats (UDP broadcasts)
*/
#define MAXBINDTRIES 10
static int
bcast_make_receive_sock(struct hb_media * mp) {
struct ip_private * ei;
struct sockaddr_in my_addr; /* my address information */
int sockfd;
int bindtries;
int boundyet=0;
int j;
BCASTASSERT(mp);
ei = (struct ip_private *) mp->pd;
memset(&(my_addr), 0, sizeof(my_addr)); /* zero my address struct */
my_addr.sin_family = AF_INET; /* host byte order */
my_addr.sin_port = htons(ei->port); /* short, network byte order */
my_addr.sin_addr.s_addr = INADDR_ANY; /* auto-fill with my IP */
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
PILCallLog(LOG, PIL_CRIT, "Error getting socket: %s"
, strerror(errno));
return(-1);
}
/*
* Set SO_REUSEADDR on the server socket s. Variable j is used
* as a scratch varable.
*
* 16th February 2000
* Added by Horms <horms@vergenet.net>
* with thanks to Clinton Work <work@scripty.com>
*/
j = 1;
if(setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR, (const void *)&j, sizeof j) <0){
/* Ignore it. It will almost always be OK anyway. */
PILCallLog(LOG, PIL_CRIT
, "Error setting socket option SO_REUSEADDR: %s"
, strerror(errno));
}
if (DEBUGPKT) {
PILCallLog(LOG, PIL_DEBUG
, "bcast_make_receive_sock: Modified %d Added option SO_REUSEADDR."
, sockfd);
}
#if defined(SO_BINDTODEVICE)
{
/*
* We want to receive packets only from this interface...
*/
struct ifreq i;
strcpy(i.ifr_name, ei->interface);
if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE
, (const void *)&i, sizeof(i)) == -1) {
PILCallLog(LOG, PIL_CRIT
, "Error setting socket option"
" SO_BINDTODEVICE(r) on %s: %s"
, i.ifr_name, strerror(errno));
close(sockfd);
return(-1);
}
if (ANYDEBUG) {
PILCallLog(LOG, PIL_DEBUG
, "SO_BINDTODEVICE(r) set for device %s"
, i.ifr_name);
}
}
#endif
/* Try binding a few times before giving up */
/* Sometimes a process with it open is exiting right now */
for(bindtries=0; !boundyet && bindtries < MAXBINDTRIES; ++bindtries) {
if (bind(sockfd, (struct sockaddr *)&my_addr
, sizeof(struct sockaddr)) < 0) {
PILCallLog(LOG, PIL_CRIT
, "Error binding socket (%s). Retrying."
, strerror(errno));
sleep(1);
}else{
boundyet = 1;
}
}
if (!boundyet) {
#if !defined(SO_BINDTODEVICE)
if (errno == EADDRINUSE) {
/* This happens with multiple bcast or ppp interfaces */
PILCallLog(LOG, PIL_INFO
, "Someone already listening on port %d [%s]"
, ei->port
, ei->interface);
PILCallLog(LOG, PIL_INFO, "BCAST read process exiting");
close(sockfd);
cleanexit(0);
}
#else
PILCallLog(LOG, PIL_CRIT
, "Unable to bind socket (%s). Giving up."
, strerror(errno));
close(sockfd);
return(-1);
#endif
}
if (fcntl(sockfd,F_SETFD, FD_CLOEXEC)) {
PILCallLog(LOG, PIL_CRIT
, "Error setting the close-on-exec flag: %s"
, strerror(errno));
}
if (DEBUGPKT) {
PILCallLog(LOG, PIL_DEBUG
, "bcast_make_receive_sock: Returning %d", sockfd);
}
return(sockfd);
}
static struct ip_private *
new_ip_interface(const char * ifn, int port)
{
struct ip_private * ep;
struct in_addr broadaddr;
/* Fetch the broadcast address for this interface */
if (if_get_broadaddr(ifn, &broadaddr) < 0) {
/* this function whines about problems... */
return (NULL);
}
/*
* We now have all the information we need. Populate our
* structure with the information we've gotten.
*/
ep = (struct ip_private *)MALLOC(sizeof(struct ip_private));
if (ep == NULL) {
return(NULL);
}
ep->bcast = broadaddr;
ep->interface = (char *)STRDUP(ifn);
if(ep->interface == NULL) {
FREE(ep);
return(NULL);
}
memset(&ep->addr, 0, sizeof(ep->addr)); /* zero the struct */
ep->addr.sin_family = AF_INET; /* host byte order */
ep->addr.sin_port = htons(port); /* short, network byte order */
ep->port = port;
ep->wsocket = -1;
ep->rsocket = -1;
ep->addr.sin_addr = ep->bcast;
return(ep);
}
/*
* ha_if.c - code that extracts information about a network interface
*
* See the linux ifconfig source code for more examples.
*
* Works on HP_UX 10.20, freebsd, linux rh6.2
* Works on solaris or Unixware (SVR4) with:
* gcc -DBSD_COMP -c ha_if.c
* Doesn't seem to work at all on Digital Unix (?)
*
* Author: Eric Z. Ayers <eric.ayers@compgen.com>
*
* Copyright (C) 2000 Computer Generation Incorporated
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include <sys/ioctl.h>
#ifdef HAVE_SYS_SOCKIO_H
# include <sys/sockio.h>
#endif
/*
if_get_broadaddr
Retrieve the ipv4 broadcast address for the specified network interface.
Inputs: ifn - the name of the network interface:
e.g. eth0, eth1, ppp0, plip0, plusb0 ...
Outputs: broadaddr - returned broadcast address.
Returns: 0 on success
-1 on failure - sets errno.
*/
int
if_get_broadaddr(const char *ifn, struct in_addr *broadaddr)
{
int return_val;
int fd = -1;
struct ifreq ifr; /* points to one interface returned from ioctl */
fd = socket (PF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
PILCallLog(LOG, PIL_CRIT
, "Error opening socket for interface %s: %s"
, ifn, strerror(errno));
return -1;
}
strncpy (ifr.ifr_name, ifn, sizeof(ifr.ifr_name));
/* Fetch the broadcast address of this interface by calling ioctl() */
return_val = ioctl(fd,SIOCGIFBRDADDR, &ifr);
if (return_val == 0 ) {
if (ifr.ifr_broadaddr.sa_family == AF_INET) {
struct sockaddr_in sin_ptr;
memcpy(&sin_ptr, &ifr.ifr_broadaddr,
sizeof(sin_ptr));
memcpy(broadaddr, &sin_ptr.sin_addr,
sizeof(*broadaddr));
/* leave return_val set to 0 to return success! */
}else{
PILCallLog(LOG, PIL_CRIT
, "Wrong family for broadcast interface %s: %s"
, ifn, strerror(errno));
return_val = -1;
}
}else{
PILCallLog(LOG, PIL_CRIT
, "Get broadcast for interface %s failed: %s"
, ifn, strerror(errno));
return_val = -1;
}
close (fd);
return return_val;
} /* end if_get_broadaddr() */
/*
* $Log: bcast.c,v $
* Revision 1.33.2.4 2005/01/12 02:25:47 horms
* Fix gcc-4.0 compile problems (Andreas Jochens)
*
* Revision 1.33.2.3 2004/09/11 06:36:33 msoffen
* Moved variable definitions to top of functions/blocks, changed comments to c style comments.
*
* Revision 1.37 2004/04/29 16:22:36 msoffen
* Changed ??? to ? ( picked up as trigraph )
*
* Revision 1.36 2004/04/28 22:30:29 alan
* Put in some fixes for extra freeing of memory in the communications plugins.
*
* Revision 1.35 2004/03/03 05:31:50 alan
* Put in Gochun Shi's new netstrings on-the-wire data format code.
* this allows sending binary data, among many other things!
*
* Revision 1.34 2004/02/17 22:11:59 lars
* Pet peeve removal: _Id et al now gone, replaced with consistent Id header.
*
* Revision 1.33 2004/01/21 11:34:15 horms
* - Replaced numerous malloc + strcpy/strncpy invocations with strdup
* * This usually makes the code a bit cleaner
* * Also is easier not to make code with potential buffer over-runs
* - Added STRDUP to pils modules
* - Removed some spurious MALLOC and FREE redefinitions
* _that could never be used_
* - Make sure the return value of strdup is honoured in error conditions
*
* Revision 1.32 2003/06/24 06:50:13 alan
* Added a missing format string.
* With the right level of debugging enabled, this could have allowed
* a hole to occur.
*
* Revision 1.31 2003/02/07 08:37:17 horms
* Removed inclusion of portability.h from .h files
* so that it does not need to be installed.
*
* Revision 1.30 2003/02/05 09:06:34 horms
* Lars put a lot of work into making sure that portability.h
* is included first, everywhere. However this broke a few
* things when building against heartbeat headers that
* have been installed (usually somewhere under /usr/include or
* /usr/local/include).
*
* This patch should resolve this problem without undoing all of
* Lars's hard work.
*
* As an asside: I think that portability.h is a virus that has
* infected all of heartbeat's code and now must also infect all
* code that builds against heartbeat. I wish that it didn't need
* to be included all over the place. Especially in headers to
* be installed on the system. However, I respect Lars's opinion
* that this is the best way to resolve some weird build problems
* in the current tree.
*
* Revision 1.29 2003/01/31 10:02:09 lars
* Various small code cleanups:
* - Lots of "signed vs unsigned" comparison fixes
* - time_t globally replaced with TIME_T
* - All seqnos moved to "seqno_t", which defaults to unsigned long
* - DIMOF() definition centralized to portability.h and typecast to int
* - EOS define moved to portability.h
* - dropped inclusion of signal.h from stonith.h, so that sigignore is
* properly defined
*
* Revision 1.28 2003/01/08 21:14:08 msoffen
* Fixed problems that prevented compiling with -Wtraditional
*
* Revision 1.27 2002/10/22 17:41:58 alan
* Added some documentation about deadtime, etc.
* Switched one of the sets of FIFOs to IPC channels.
* Added msg_from_IPC to ha_msg.c make that easier.
* Fixed a few compile errors that were introduced earlier.
* Moved hb_api_core.h out of the global include directory,
* and back into a local directory. I also make sure it doesn't get
* installed. This *shouldn't* cause problems.
* Added a ipc_waitin() function to the IPC code to allow you to wait for
* input synchronously if you really want to.
* Changes the STONITH test to default to enabled.
*
* Revision 1.26 2002/10/02 13:40:26 alan
* Fixed some potential holes pointed out by Nathan Wallwork.
*
* Revision 1.25 2002/09/19 22:40:17 alan
* Changed a few error return checks to not print anything and return
* if an error was encountered.
* Changed a few debug messages to only print if a strictly positive number
* of chars was received.
*
* Revision 1.24 2002/09/12 03:52:07 alan
* Fixed up a comment :-(.
*
* Revision 1.23 2002/09/12 03:39:45 alan
* Fixed some logging level names in the code and also
* fixed an error in the license chosen for a file.
*
* Revision 1.22 2002/09/11 07:11:23 alan
* Updated a good bit of code to use logging functions more uniformly.
* Some used printfs, and some used ha_log, and some used the PILS
* function pointers (which sidesteps the printf argument checking).
*
* Revision 1.21 2002/08/07 18:20:33 msoffen
* Cleaned up many warning messages from FreeBSD and Solaris.
* Cleaned up signal calls with SIG_IGN for Solaris to use sigignore function (to remove some warnings).
*
* Revision 1.20 2002/07/16 17:10:32 msoffen
* Changed so that Lars shouldn't have the issue with the struct copy.
*
* Revision 1.19 2002/07/16 16:18:15 msoffen
* -Re-added in LArs's comments.
*
* Revision 1.18 2002/07/16 16:16:06 msoffen
* Changed to NOT assume that the address is 1st.
*
* Revision 1.17 2002/07/16 11:47:53 lars
* Type and alignment fixes for IA64, x86_64, sparc, s390 and PPC(64).
*
* Revision 1.16 2002/06/16 06:11:26 alan
* Put in a couple of changes to the PILS interfaces
* - exported license information (name, URL)
* - imported malloc/free
*
* Revision 1.15 2002/06/16 03:42:53 alan
* Incorporated code from Stéphane Billiart to add a unicast heartbeat capability
* to heartbeat.
* Fixed a small bug in bcast.c where the "old" logging function was called
* instead of the new one.
*
* Revision 1.14 2002/05/01 23:50:35 alan
* Put in some comments about how the code avoids potential buffer overruns.
*
* Revision 1.13 2002/04/13 22:35:08 alan
* Changed ha_msg_add_nv to take an end pointer to make it safer.
* Added a length parameter to string2msg so it would be safer.
* Changed the various networking plugins to use the new string2msg().
*
* Revision 1.12 2002/04/09 12:45:36 alan
* Put in changes to the bcast, mcast and serial code such that
* interrupted system calls in reads are ignored.
*
* Revision 1.11 2002/03/25 23:54:52 alan
* Put in fixes to two bugs noted by Gamid Isayev of netzilla networks.
* One of the two fixes is also due to him.
*
* Revision 1.10 2002/03/25 23:19:36 horms
* Patches from Gamid Isayev to
*
* 1) Avoid shadowing the udpport global, hence this
* configuration option should now work.
*
* 2) Call getservbyname with a vaild protocol (udp), this should
* also allow the udpport configuration option to work.
*
* --
* Horms
*
* Revision 1.9 2001/10/03 05:33:28 alan
* Added a little more error checking for the broadcast port number...
*
* Revision 1.8 2001/10/02 20:15:41 alan
* Debug code, etc. from Matt Soffen...
*
* Revision 1.7 2001/10/02 15:52:20 alan
* Replaced bzero with memset... This is a minor portability issue...
*
* Revision 1.6 2001/10/02 05:12:19 alan
* Various portability fixes (make warnings go away) for Solaris.
*
* Revision 1.5 2001/09/07 16:18:17 alan
* Updated ping.c to conform to the new plugin loading system.
* Changed log messages in bcast, mcast, ping and serial to use the
* new logging function.
*
* Revision 1.4 2001/08/15 16:17:12 alan
* Fixed the code so that serial comm plugins build/load/work.
*
* Revision 1.3 2001/08/15 02:14:49 alan
* Put in #include net/if.h needed for FreeBSD and solaris
*
* Revision 1.2 2001/08/11 01:40:54 alan
* Removed the old copy of the heartbeat.h file, and removed a
* blank line from a file... ;-)
*
* Revision 1.1 2001/08/10 17:16:44 alan
* New code for the new plugin loading system.
*
* Revision 1.20 2001/06/19 13:56:28 alan
* FreeBSD portability patch from Matt Soffen.
* Mainly added #include "portability.h" to lots of files.
* Also added a library to Makefile.am
*/
syntax highlighted by Code2HTML, v. 0.9.1