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

📄 vrrpd.c

📁 VRRP双机热备份协议源吗
💻 C
📖 第 1 页 / 共 3 页
字号:
/*==========================[ (c) JME SOFT  ]===================================FILE        : [vrrp.c]CREATED     : 00/02/02 12:54:37		LAST SAVE    : 00/10/04 22:11:39WHO         : jerome@mycpu Linux 2.2.14REMARK      :================================================================================- 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.==============================================================================*//* system include */#include <stdio.h>#include <assert.h>#include <net/ethernet.h>#include <netinet/ip.h>#include <stdlib.h>#include <unistd.h>#include <signal.h>#include <string.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/time.h>#include <netinet/in.h>#include <arpa/inet.h>#include <time.h>#include <sys/errno.h>#include <net/if.h>#include <net/if_arp.h>#include <net/ethernet.h>#include <sys/ioctl.h>#include <ctype.h>#include <string.h>/* local include */#include "vrrpd.h"#include "ipaddr.h"int ip_id = 0;	/* to have my own ip_id creates collision with kernel ip->id		** but it should be ok because the packets are unlikely to be		** fragmented (they are non routable and small) */		/* WORK: this packet isnt routed, i can check the outgoing MTU		** to warn the user only if the outoing mtu is too small */static char vrrp_hwaddr[6];	// WORK: lame hardcoded for ethernetstatic vrrp_rt	glob_vsrv;	/* a global because used in the signal handler*/static char	PidDir[FILENAME_MAX+1];/**************************************************************** NAME	: get_pid_name				00/10/04 21:06:44 AIM	:  REMARK	:****************************************************************/static char *pidfile_get_name( vrrp_rt *vsrv ){	static char pidfile[FILENAME_MAX+1];	snprintf( pidfile, sizeof(pidfile), "%s/" VRRP_PID_FORMAT					, PidDir					, vsrv->vif.ifname 					, vsrv->vrid );	return pidfile;}/**************************************************************** NAME	: pidfile_write				00/10/04 21:12:26 AIM	:  REMARK	: write the pid file****************************************************************/static int pidfile_write( vrrp_rt *vsrv ){	char	*name	= pidfile_get_name(vsrv);	FILE	*fOut	= fopen( name, "w" );	if( !fOut ){		fprintf( stderr, "Can't open %s (errno %d %s)\n", name 						, errno						, strerror(errno) 						);		return -1;	}	fprintf( fOut, "%d\n", getpid() );	fclose( fOut );	return(0);}/**************************************************************** NAME	: pidfile_rm				00/10/04 21:12:26 AIM	:  REMARK	:****************************************************************/static void pidfile_rm( vrrp_rt *vsrv ){	unlink( pidfile_get_name(vsrv) );}/**************************************************************** NAME	: pidfile_exist				00/10/04 21:12:26 AIM	: return 0 if there is no valid pid in the pidfile or no pidfile REMARK	: ****************************************************************/static int pidfile_exist( vrrp_rt *vsrv ){	char	*name	= pidfile_get_name(vsrv);	FILE	*fIn	= fopen( name, "r" );	pid_t	pid;	/* if there is no file */	if( !fIn )		return 0;	fscanf( fIn, "%d", &pid );	fclose( fIn );	/* if there is no process, remove the stale file */	if( kill( pid, 0 ) ){		fprintf(stderr, "Remove a stale pid file %s\n", name );		pidfile_rm( vsrv );		return 0;	}	/* if the kill suceed, return an error */	return -1;}/**************************************************************** NAME	: in_csum				00/05/10 20:12:20 AIM	: compute a IP checksum REMARK	: from kuznet's iputils****************************************************************/static u_short in_csum( u_short *addr, int len, u_short csum){	register int nleft = len;	const u_short *w = addr;	register u_short answer;	register int sum = csum;	/*	 *  Our algorithm is simple, using a 32 bit accumulator (sum),	 *  we add sequential 16 bit words to it, and at the end, fold	 *  back all the carry bits from the top 16 bits into the lower	 *  16 bits.	 */	while (nleft > 1)  {		sum += *w++;		nleft -= 2;	}	/* mop up an odd byte, if necessary */	if (nleft == 1)		sum += htons(*(u_char *)w << 8);	/*	 * add back carry outs from top 16 bits to low 16 bits	 */	sum = (sum >> 16) + (sum & 0xffff);	/* add hi 16 to low 16 */	sum += (sum >> 16);			/* add carry */	answer = ~sum;				/* truncate to 16 bits */	return (answer);}/**************************************************************** NAME	: get_dev_from_ip			00/02/08 06:51:32 AIM	: REMARK	:****************************************************************/static uint32_t ifname_to_ip( char *ifname ){	struct ifreq	ifr;	int		fd	= socket(AF_INET, SOCK_DGRAM, 0);	uint32_t	addr	= 0;	if (fd < 0) 	return (-1);	strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));	if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) == 0) {		struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr;		addr = ntohl(sin->sin_addr.s_addr);	}	close(fd);	return addr;}/**************************************************************** NAME	: get_dev_from_ip			00/02/08 06:51:32 AIM	: REMARK	:****************************************************************/static int ifname_to_idx( char *ifname ){	struct ifreq	ifr;	int		fd	= socket(AF_INET, SOCK_DGRAM, 0);	int		ifindex = -1;	if (fd < 0) 	return (-1);	strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));	if (ioctl(fd, SIOCGIFINDEX, (char *)&ifr) == 0)		ifindex = ifr.ifr_ifindex;	close(fd);	return ifindex;}/**************************************************************** NAME	: rcvhwaddr_op				00/02/08 06:51:32 AIM	: REMARK	:****************************************************************/static int rcvhwaddr_op( char *ifname, char *addr, int addrlen, int addF ){	struct ifreq	ifr;	int		fd	= socket(AF_INET, SOCK_DGRAM, 0);	int		ret;	if (fd < 0) 	return (-1);	strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));	memcpy( ifr.ifr_hwaddr.sa_data, addr, addrlen );	ifr.ifr_hwaddr.sa_family = AF_UNSPEC;	ret = ioctl(fd, addF ? SIOCADDMULTI : SIOCDELMULTI, (char *)&ifr);	if( ret ){		printf("Can't %s on %s. errno=%d\n"			, addF ? "SIOCADDMULTI" : "SIOCDELMULTI"			, ifname, errno );	}	close(fd);	return ret;}/**************************************************************** NAME	: hwaddr_set				00/02/08 06:51:32 AIM	: REMARK	: linux refuse to change the hwaddress if the interface is up****************************************************************/static int hwaddr_set( char *ifname, char *addr, int addrlen ){	struct ifreq	ifr;	int		fd	= socket(AF_INET, SOCK_DGRAM, 0);	int		ret;	unsigned long	flags;	if (fd < 0) 	return (-1);	strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));	/* get the flags */	ret = ioctl(fd, SIOCGIFFLAGS, (char *)&ifr);	if( ret )	goto end;	flags = ifr.ifr_flags;	/* set the interface down */	ifr.ifr_flags &= ~IFF_UP;	ret = ioctl(fd, SIOCSIFFLAGS, (char *)&ifr);	if( ret )	goto end;	/* change the hwaddr */	memcpy( ifr.ifr_hwaddr.sa_data, addr, addrlen );	ifr.ifr_hwaddr.sa_family = AF_UNIX;	ret = ioctl(fd, SIOCSIFHWADDR, (char *)&ifr);	if( ret )	goto end;	/* set the interface up */	ifr.ifr_flags = flags;	ret = ioctl(fd, SIOCSIFFLAGS, (char *)&ifr);	if( ret )	goto end;end:;if( ret )	printf("error errno=%d\n",errno);	close(fd);	return ret;}/**************************************************************** NAME	: hwaddr_get				00/02/08 06:51:32 AIM	: REMARK	:****************************************************************/static int hwaddr_get( char *ifname, char *addr, int addrlen ){	struct ifreq	ifr;	int		fd	= socket(AF_INET, SOCK_DGRAM, 0);	int		ret;	if (fd < 0) 	return (-1);	strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));	ret = ioctl(fd, SIOCGIFHWADDR, (char *)&ifr);	memcpy( addr, ifr.ifr_hwaddr.sa_data, addrlen );//printf("%x:%x:%x:%x:%x:%x\n", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5] );	close(fd);	return ret;}/**************************************************************** NAME	: ipaddr_ops				00/02/08 06:51:32 AIM	: REMARK	:****************************************************************/static int ipaddr_ops( vrrp_rt *vsrv, int addF ){	int	i, err	= 0;	int	ifidx	= ifname_to_idx( vsrv->vif.ifname );	struct in_addr in;	for( i = 0; i < vsrv->naddr; i++ ){		vip_addr	*vadd = &vsrv->vaddr[i];		if( !addF && !vadd->deletable ) 	continue;		if( ipaddr_op( ifidx , vadd->addr, addF)){			err = 1;			vadd->deletable = 0;			in.s_addr = htonl(vadd->addr);			VRRP_LOG(("cant %s the address %s to %s\n"						, addF ? "set" : "remove"						, inet_ntoa(in)						, vsrv->vif.ifname));		}else{			vadd->deletable = 1;		}	}	return err;}/**************************************************************** NAME	: vrrp_dlthd_len			00/02/02 15:16:23 AIM	: return the vrrp header size in byte REMARK	:****************************************************************/static int vrrp_dlt_len( vrrp_rt *rt ){	return ETHER_HDR_LEN;	/* hardcoded for ethernet */}/**************************************************************** NAME	: vrrp_iphdr_len			00/02/02 15:16:23 AIM	: return the ip  header size in byte REMARK	:****************************************************************/static int vrrp_iphdr_len( vrrp_rt *vsrv ){	return sizeof( struct iphdr );}/**************************************************************** NAME	: vrrp_hd_len				00/02/02 15:16:23 AIM	: return the vrrp header size in byte REMARK	:****************************************************************/static int vrrp_hd_len( vrrp_rt *vsrv ){	return sizeof( vrrp_pkt ) + vsrv->naddr*sizeof(uint32_t)						+ VRRP_AUTH_LEN;}/**************************************************************** NAME	: vrrp_in_chk				00/02/02 12:54:54 AIM	: check a incoming packet. return 0 if the pkt is valid, != 0 else REMARK	: rfc2338.7.1****************************************************************/static int vrrp_in_chk( vrrp_rt *vsrv, struct iphdr *ip ){	int		ihl = ip->ihl << 2;	vrrp_pkt *	hd = (vrrp_pkt *)((char *)ip + ihl);	vrrp_if 	*vif	= &vsrv->vif;	/* MUST verify that the IP TTL is 255 */	if( ip->ttl != VRRP_IP_TTL ) {		VRRP_LOG(("invalid ttl. %d and expect %d", ip->ttl,VRRP_IP_TTL));		return 1;	}	/* MUST verify the VRRP version */	if( (hd->vers_type >> 4) != VRRP_VERSION ){		VRRP_LOG(("invalid version. %d and expect %d"			, (hd->vers_type >> 4), VRRP_VERSION));		return 1;	}	/* MUST verify that the received packet length is greater than or	** equal to the VRRP header */	if( (ntohs(ip->tot_len)-ihl) <= sizeof(vrrp_pkt) ){		VRRP_LOG(("ip payload too short. %d and expect at least %d"			, ntohs(ip->tot_len)-ihl, sizeof(vrrp_pkt) ));		return 1;	}	/* WORK: MUST verify the VRRP checksum */	if( in_csum( (u_short*)hd, vrrp_hd_len(vsrv), 0) ){		VRRP_LOG(("Invalid vrrp checksum" ));		return 1;	}/* MUST perform authentication specified by Auth Type */ 	/* check the authentication type */	if( vif->auth_type != hd->auth_type ){				VRRP_LOG(("receive a %d auth, expecting %d!", vif->auth_type							, hd->auth_type));

⌨️ 快捷键说明

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