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

📄 mcast.c

📁 linux集群服务器软件代码包
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Set up socket for sending multicast UDP heartbeats */static intmcast_make_send_sock(struct hb_media * hbm){	int sockfd;	struct mcast_private * mcp;	MCASTASSERT(hbm);	mcp = (struct mcast_private *) hbm->pd;	if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {		PILCallLog(LOG, PIL_WARN, "Error getting socket: %s", strerror(errno));		return(sockfd);   	}	if (set_mcast_if(sockfd, mcp->interface) < 0) {		PILCallLog(LOG, PIL_WARN, "Error setting outbound mcast interface: %s", strerror(errno));	}	if (set_mcast_loop(sockfd, mcp->loop) < 0) {		PILCallLog(LOG, PIL_WARN, "Error setting outbound mcast loopback value: %s", strerror(errno));	}	if (set_mcast_ttl(sockfd, mcp->ttl) < 0) {		PILCallLog(LOG, PIL_WARN, "Error setting outbound mcast TTL: %s", strerror(errno));	}	if (fcntl(sockfd,F_SETFD, FD_CLOEXEC)) {		PILCallLog(LOG, PIL_WARN, "Error setting the close-on-exec flag: %s", strerror(errno));	}	return(sockfd);}/* * Set up socket for listening to heartbeats (UDP multicasts) */#define	MAXBINDTRIES	10static intmcast_make_receive_sock(struct hb_media * hbm){	struct mcast_private * mcp;	int	sockfd;	int	bindtries;	int	boundyet=0;	int	one=1;	int	rc;	int	binderr=0;	MCASTASSERT(hbm);	mcp = (struct mcast_private *) hbm->pd;	if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {		PILCallLog(LOG, PIL_CRIT, "Error getting socket");		return -1;	}	/* set REUSEADDR option on socket so you can bind a multicast */	/* reader to multiple interfaces */	if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(one)) < 0){		PILCallLog(LOG, PIL_CRIT, "Error setsockopt(SO_REUSEADDR)");	}        	/* ripped off from udp.c, if we all use SO_REUSEADDR */	/* this shouldn't be necessary  */	/* 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) {		rc=bind(sockfd, (struct sockaddr *)&mcp->addr, sizeof(mcp->addr));		binderr=errno;		if (rc==0) {			boundyet=1;		} else if (rc == -1) {			if (binderr == EADDRINUSE) {				PILCallLog(LOG, PIL_CRIT, "Can't bind (EADDRINUSE), "					"retrying");				sleep(1);			} else	{ 			/* don't keep trying if the error isn't caused by */			/* the address being in use already...real error */				break;			}		}	}	if (!boundyet) {		if (binderr == EADDRINUSE) {			/* This happens with multiple udp or ppp interfaces */			PILCallLog(LOG, PIL_INFO			,	"Someone already listening on port %d [%s]"			,	mcp->port			,	mcp->interface);			PILCallLog(LOG, PIL_INFO, "multicast read process exiting");			close(sockfd);			cleanexit(0);		} else {			PILCallLog(LOG, PIL_WARN, "Unable to bind socket. Giving up: %s", strerror(errno));			close(sockfd);			return(-1);		}	}	/* join the multicast group...this is what really makes this a */	/* multicast reader */	if (join_mcast_group(sockfd, &mcp->mcast, mcp->interface) == -1) {		PILCallLog(LOG, PIL_CRIT, "Can't join multicast group %s on interface %s",			inet_ntoa(mcp->mcast), mcp->interface);		PILCallLog(LOG, PIL_INFO, "multicast read process exiting");		close(sockfd);		cleanexit(0);	}	if (ANYDEBUG) 		PILCallLog(LOG, PIL_DEBUG, "Successfully joined multicast group %s on"			"interface %s", inet_ntoa(mcp->mcast), mcp->interface);			if (fcntl(sockfd,F_SETFD, FD_CLOEXEC)) {		PILCallLog(LOG, PIL_WARN, "Error setting the close-on-exec flag: %s", strerror(errno));	}	return(sockfd);}static struct mcast_private *new_mcast_private(const char *ifn, const char *mcast, u_short port,		u_char ttl, u_char loop){	struct mcast_private *mcp;	mcp = MALLOCT(struct mcast_private);	if (mcp == NULL)  {		return NULL;	}	mcp->interface = (char *)STRDUP(ifn);	if(mcp->interface == NULL) {		FREE(mcp);		return NULL;	}	/* Set up multicast address */	if (inet_pton(AF_INET, mcast, (void *)&mcp->mcast) <= 0) {		FREE(mcp->interface);		FREE(mcp);		return NULL;	}	memset(&mcp->addr, 0, sizeof(mcp->addr));	/* zero the struct */	mcp->addr.sin_family = AF_INET;		/* host byte order */	mcp->addr.sin_port = htons(port);	/* short, network byte order */	mcp->addr.sin_addr = mcp->mcast;	mcp->port = port;	mcp->wsocket = -1;	mcp->rsocket = -1;	mcp->ttl=ttl;	mcp->loop=loop;	return(mcp);}/* set_mcast_loop takes a boolean flag, loop, which is useful on * a writing socket.  with loop enabled (the default on a multicast socket) * the outbound packet will get looped back and received by the sending * interface, if it is listening for the multicast group and port that the * packet was sent to.  Returns 0 on success -1 on failure. */static int set_mcast_loop(int sockfd, u_char loop){	return setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop));}/* set_mcast_ttl will set the time-to-live value for the writing socket. * the socket default is TTL=1.  The TTL is used to limit the scope of the * packet and can range from 0-255.   * TTL     Scope * ---------------------------------------------------------------------- *    0    Restricted to the same host. Won't be output by any interface. *    1    Restricted to the same subnet. Won't be forwarded by a router. *  <32    Restricted to the same site, organization or department. *  <64    Restricted to the same region. * <128    Restricted to the same continent. * <255    Unrestricted in scope. Global. * * Returns 0 on success -1 on failure. */static intset_mcast_ttl(int sockfd, u_char ttl){	return setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));}/* * set_mcast_if takes the name of an interface (i.e. eth0) and then * sets that as the interface to use for outbound multicast traffic. * If ifname is NULL, then it the OS will assign the interface. * Returns 0 on success -1 on faliure. */static intset_mcast_if(int sockfd, char *ifname){	int rc;	struct in_addr addr;	/* Zero out the struct... we only care about the address... */	memset(&addr, 0, sizeof(addr));	rc = if_getaddr(ifname, &addr);	if (rc == -1)		return -1;	return setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_IF	,	(void*)&addr, sizeof(addr));}/* join_mcast_group is used to join a multicast group.  the group is * specified by a class D multicast address 224.0.0.0/8 in the in_addr * structure passed in as a parameter.  The interface name can be used * to "bind" the multicast group to a specific interface (or any * interface if ifname is NULL); * returns 0 on success, -1 on failure. */static intjoin_mcast_group(int sockfd, struct in_addr *addr, char *ifname){	struct ip_mreq	mreq_add;	memset(&mreq_add, 0, sizeof(mreq_add));	memcpy(&mreq_add.imr_multiaddr, addr, sizeof(struct in_addr));	if (ifname) {		if_getaddr(ifname, &mreq_add.imr_interface);	}	return setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void*)&mreq_add, sizeof(mreq_add));}/* if_getaddr gets the ip address from an interface * specified by name and places it in addr. * returns 0 on success and -1 on failure. */static intif_getaddr(const char *ifname, struct in_addr *addr){	int	fd;	struct ifreq	if_info;		if (!addr)		return -1;	addr->s_addr = INADDR_ANY;	memset(&if_info, 0, sizeof(if_info));	if (ifname) {		strncpy(if_info.ifr_name, ifname, IFNAMSIZ-1);	} else {	/* ifname is NULL, so use any address */		return 0;	}	if ((fd=socket(AF_INET, SOCK_DGRAM, 0)) == -1)	{		PILCallLog(LOG, PIL_CRIT, "Error getting socket");		return -1;	}	if (Debug > 0) {		PILCallLog(LOG, PIL_DEBUG, "looking up address for %s"		,	if_info.ifr_name);	}	if (ioctl(fd, SIOCGIFADDR, &if_info) < 0) {		PILCallLog(LOG, PIL_CRIT, "Error ioctl(SIOCGIFADDR): %s"		,	strerror(errno));		close(fd);		return -1;	}	/*	 * This #define w/void cast is to quiet alignment errors on some	 * platforms (notably Solaris)	 */#define SOCKADDR_IN(a)        ((struct sockaddr_in *)((void*)(a))) 	memcpy(addr, &(SOCKADDR_IN(&if_info.ifr_addr)->sin_addr)	,	sizeof(struct in_addr));	close(fd);	return 0;}/* returns true or false */static intis_valid_dev(const char *dev){	int rc=0;	if (dev) {		struct in_addr addr;		if (if_getaddr(dev, &addr) != -1)			rc = 1;	}	return rc;}/* returns true or false */#define MCAST_NET	0xf0000000#define MCAST_BASE	0xe0000000static intis_valid_mcast_addr(const char *addr){	unsigned long mc_addr;	/* make sure address is in host byte order */	mc_addr = ntohl(inet_addr(addr));	if ((mc_addr & MCAST_NET) == MCAST_BASE)		return 1;	return 0;}/* return port number on success, 0 on failure */static intget_port(const char *port, u_short *p){	/* not complete yet */	*p=(u_short)atoi(port);	return 0;}/* returns ttl on succes, -1 on failure */static intget_ttl(const char *ttl, u_char *t){	/* not complete yet */	*t=(u_char)atoi(ttl);	return 0;}/* returns loop on success, -1 on failure */static intget_loop(const char *loop, u_char *l){	/* not complete yet */	*l=(u_char)atoi(loop);	return 0;}/* * $Log: mcast.c,v $ * Revision 1.22  2004/10/24 13:00:13  lge * -pedantic-errors fixes 2: *  * error: ISO C forbids forward references to 'enum' types *    error: comma at end of enumerator list *    error: ISO C does not allow extra ';' outside of a function * * Revision 1.21  2004/10/06 10:55:17  lars * - Define PIL_PLUGIN_BOILERPLATE() as it used to be, which implies a *   prototype for the closepi function. * - Define PIL_PLUGIN_BOILERPLATE2() which just takes two arguments and *   fills in NULL for all those plugins which don't use the closepi() *   functionality. * * Revision 1.20  2004/09/27 04:23:30  alan * Put in some code to print out failure cases better, and also to * better diagnose bad configurations. * * Revision 1.19  2004/05/11 22:04:35  alan * Changed all the HBcomm plugins to use PILCallLog() for logging instead of calling * the function pointer directly. * Also, in the process fixed several mismatches between arguments and format strings, and * a couple of format string vulnerabilities. * * Revision 1.18  2004/04/28 22:30:29  alan * Put in some fixes for extra freeing of memory in the communications plugins. * * Revision 1.17  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.16  2004/02/17 22:11:59  lars * Pet peeve removal: _Id et al now gone, replaced with consistent Id header. * * Revision 1.15  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.14  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.13  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.12  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.11  2002/10/21 10:17:19  horms * hb api clients may now be built outside of the heartbeat tree * * Revision 1.10  2002/09/19 22:40:18  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.9  2002/09/12 03:52:07  alan * Fixed up a comment :-(. * * Revision 1.8  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.7  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.6  2002/05/01 23:50:35  alan * Put in some comments about how the code avoids potential buffer overruns. * * Revision 1.5  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.4  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.3  2002/01/17 15:21:23  alan * Put in Ram Pai's patch for the bug in the multicast code. * * Revision 1.2  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.1  2001/08/10 17:16:44  alan * New code for the new plugin loading system. * * Revision 1.11  2001/06/23 04:30:26  alan * Changed the code to use inet_pton() when it's available, and * emulate it when it's not...  Patch was from Chris Wright. * * Revision 1.10  2001/06/08 04:57:48  alan * Changed "config.h" to <portability.h> * */

⌨️ 快捷键说明

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