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

📄 vrrpd.c

📁 VRRP双机热备份协议源吗
💻 C
📖 第 1 页 / 共 3 页
字号:
{	if( vsrv->naddr == 0 ){		fprintf(stderr, "provide at least one ip for the virtual server\n");		return -1;	}	if( vsrv->vrid == 0 ){		fprintf(stderr, "the virtual id must be set!\n");		return -1;	}	if( vsrv->vif.ipaddr == 0 ){		fprintf(stderr, "the interface ipaddr must be set!\n");		return -1;	}	/* make vrrp use the native hwaddr and not the virtual one */	if( vsrv->no_vmac ){		memcpy( vrrp_hwaddr, vsrv->vif.hwaddr,sizeof(vsrv->vif.hwaddr));	}	return(0);}/**************************************************************** NAME	: vrrp_read				00/02/07 00:04:53 AIM	: REMARK	:****************************************************************/static int vrrp_read( vrrp_rt *vsrv, char *buf, int buflen ){	fd_set		readfds;	struct timeval	timeout;	uint32_t	next	= 0xFFFFFFFF;	int		len	= 0;	/* cpu the next timer */	if( VRRP_TIMER_IS_RUNNING( vsrv->adver_timer ) ){		int32_t	delta = VRRP_TIMER_DELTA(vsrv->adver_timer);		if( delta < 0 )	delta = 0;		next = VRRP_MIN( next, delta );	}else{	/* here vsrv->ms_down_timer is assumed running */		int32_t	delta = VRRP_TIMER_DELTA(vsrv->ms_down_timer);		assert( VRRP_TIMER_IS_RUNNING( vsrv->ms_down_timer ) );		if( delta < 0 )	delta = 0;		next = VRRP_MIN( next, delta );	}	/* setup the select() */	FD_ZERO( &readfds );	FD_SET( vsrv->sockfd, &readfds );	timeout.tv_sec	= next / VRRP_TIMER_HZ;	timeout.tv_usec = next % VRRP_TIMER_HZ;//printf( "val %u,%u %u\n", timeout.tv_sec, timeout.tv_usec, next );	if( select( vsrv->sockfd + 1, &readfds, NULL, NULL, &timeout ) > 0 ){		len = read( vsrv->sockfd, buf, buflen );//		printf("packet received (%d bytes)\n",len);		if( vrrp_in_chk( vsrv, (struct iphdr *)buf ) ){			printf("bogus packet!\n");			len = 0;		}	}	return len;}/**************************************************************** NAME	: send_gratuitous_arp			00/05/11 11:56:30 AIM	: REMARK	: rfc0826	: WORK: ugly because heavily hardcoded for ethernet****************************************************************/static int send_gratuitous_arp( vrrp_rt *vsrv, int addr, int vAddrF ){struct m_arphdr  {    unsigned short int ar_hrd;          /* Format of hardware address.  */    unsigned short int ar_pro;          /* Format of protocol address.  */    unsigned char ar_hln;               /* Length of hardware address.  */    unsigned char ar_pln;               /* Length of protocol address.  */    unsigned short int ar_op;           /* ARP opcode (command).  */    /* Ethernet looks like this : This bit is variable sized however...  */    unsigned char __ar_sha[ETH_ALEN];   /* Sender hardware address.  */    unsigned char __ar_sip[4];          /* Sender IP address.  */    unsigned char __ar_tha[ETH_ALEN];   /* Target hardware address.  */    unsigned char __ar_tip[4];          /* Target IP address.  */  };	char	buf[sizeof(struct m_arphdr)+ETHER_HDR_LEN];	char	buflen	= sizeof(struct m_arphdr)+ETHER_HDR_LEN;	struct ether_header 	*eth	= (struct ether_header *)buf;	struct m_arphdr	*arph = (struct m_arphdr *)(buf+vrrp_dlt_len(vsrv));	char	*hwaddr	= vAddrF ? vrrp_hwaddr : vsrv->vif.hwaddr;	int	hwlen	= ETH_ALEN;	/* hardcoded for ethernet */	memset( eth->ether_dhost, 0xFF, ETH_ALEN );	memcpy( eth->ether_shost, hwaddr, hwlen );	eth->ether_type	= htons(ETHERTYPE_ARP);	/* build the arp payload */	memset( arph, 0, sizeof( *arph ) );	arph->ar_hrd	= htons(ARPHRD_ETHER);	arph->ar_pro	= htons(ETHERTYPE_IP);	arph->ar_hln	= 6;	arph->ar_pln	= 4;	arph->ar_op	= htons(ARPOP_REQUEST);	memcpy( arph->__ar_sha, hwaddr, hwlen );	addr = htonl(addr);	memcpy( arph->__ar_sip, &addr, sizeof(addr) );	memcpy( arph->__ar_tip, &addr, sizeof(addr) );	return vrrp_send_pkt( vsrv, buf, buflen );}/**************************************************************** NAME	: state_gotomaster			00/02/07 00:15:26 AIM	: REMARK	: called when the state is now MASTER****************************************************************/static void state_goto_master( vrrp_rt *vsrv ){	int	i;	vrrp_if	*vif = &vsrv->vif;	/* set the VRRP MAC address -- rfc2338.7.3 */	if( !vsrv->no_vmac ){		hwaddr_set( vif->ifname, vrrp_hwaddr, sizeof(vrrp_hwaddr) );		rcvhwaddr_op( vif->ifname, vif->hwaddr, sizeof(vif->hwaddr), 1);	}	/* add the ip addresses */	ipaddr_ops( vsrv, 1 );	/* send an advertisement */	vrrp_send_adv( vsrv, vsrv->priority );	/* send gratuitous arp for each virtual ip */	for( i = 0; i < vsrv->naddr; i++ )		send_gratuitous_arp( vsrv, vsrv->vaddr[i].addr, 1 );	/* init the struct */	VRRP_TIMER_SET( vsrv->adver_timer, vsrv->adver_int );	vsrv->state = VRRP_STATE_MAST;}/**************************************************************** NAME	: state_leavemaster			00/02/07 00:15:26 AIM	: REMARK	: called when the state is no more MASTER****************************************************************/static void state_leave_master( vrrp_rt *vsrv, int advF ){	uint32_t	addr[1024];	vrrp_if		*vif = &vsrv->vif;	/* restore the original MAC addresses */	if( !vsrv->no_vmac ){		hwaddr_set( vif->ifname, vif->hwaddr, sizeof(vif->hwaddr) );		rcvhwaddr_op( vif->ifname, vif->hwaddr, sizeof(vif->hwaddr), 0);	}	/* remove the ip addresses */	ipaddr_ops( vsrv, 0 );	/* if we stop vrrpd, warn the other routers to speed up the recovery */	if( advF ){		vrrp_send_adv( vsrv, VRRP_PRIO_STOP );	}	/* send gratuitous ARP for all the non-vrrp ip addresses to update	** the cache of remote hosts using these addresses */	if( !vsrv->no_vmac ){		int		i, naddr;		naddr = ipaddr_list( ifname_to_idx(vif->ifname), addr				, sizeof(addr)/sizeof(addr[0]) );		for( i = 0; i < naddr; i++ )			send_gratuitous_arp( vsrv, addr[i], 0 );	}}/**************************************************************** NAME	: state_init				00/02/07 00:15:26 AIM	: REMARK	: rfc2338.6.4.1****************************************************************/static void state_init( vrrp_rt *vsrv ){	if( vsrv->priority == VRRP_PRIO_OWNER 			|| vsrv->wantstate == VRRP_STATE_MAST ){		state_goto_master( vsrv );	} else {		int delay = 3*vsrv->adver_int + VRRP_TIMER_SKEW(vsrv);		VRRP_TIMER_SET( vsrv->ms_down_timer, delay );		vsrv->state = VRRP_STATE_BACK;	}}/**************************************************************** NAME	: state_back				00/02/07 00:15:26 AIM	: REMARK	: rfc2338.6.4.2****************************************************************/static void state_back( vrrp_rt *vsrv ){	char		buf[300];	/* WORK: lame ! */	int		len	= vrrp_read( vsrv, buf, sizeof(buf) );	struct iphdr	*iph	= (struct iphdr *)buf;	vrrp_pkt	*hd	= (vrrp_pkt *)((char *)iph + (iph->ihl<<2));	if( (!len && VRRP_TIMER_EXPIRED(vsrv->ms_down_timer)) 			|| vsrv->wantstate == VRRP_STATE_MAST ){		state_goto_master( vsrv );		return;	}	if( !len )	return;	if ( hd->priority == 0 ) {		VRRP_TIMER_SET( vsrv->ms_down_timer, VRRP_TIMER_SKEW(vsrv) );	} else if( !vsrv->preempt || hd->priority >= vsrv->priority ) {		int delay = 3*vsrv->adver_int + VRRP_TIMER_SKEW(vsrv);		VRRP_TIMER_SET( vsrv->ms_down_timer, delay );	}}/**************************************************************** NAME	: state_mast				00/02/07 00:15:26 AIM	: REMARK	: rfc2338.6.4.3****************************************************************/static void state_mast( vrrp_rt *vsrv ){	char		buf[300];	/* WORK: lame ! */	int		len	= vrrp_read( vsrv, buf, sizeof(buf) );	struct iphdr	*iph	= (struct iphdr *)buf;	vrrp_pkt	*hd	= (vrrp_pkt *)((char *)iph + (iph->ihl<<2));	if( vsrv->wantstate == VRRP_STATE_BACK ){		goto be_backup;	}	if( !len && VRRP_TIMER_EXPIRED(vsrv->adver_timer) ){		vrrp_send_adv( vsrv, vsrv->priority );		VRRP_TIMER_SET(vsrv->adver_timer,vsrv->adver_int);		return;	}	if( !len )	return;	if( hd->priority == 0 ){		vrrp_send_adv( vsrv, vsrv->priority );		VRRP_TIMER_SET(vsrv->adver_timer,vsrv->adver_int);	}else if( hd->priority > vsrv->priority ||			(hd->priority == vsrv->priority &&			ntohl(iph->saddr) > vsrv->vif.ipaddr) ){		int delay	= 3*vsrv->adver_int + VRRP_TIMER_SKEW(vsrv);be_backup:		VRRP_TIMER_SET( vsrv->ms_down_timer, delay );		VRRP_TIMER_CLR( vsrv->adver_timer );		state_leave_master( vsrv, 0 );		vsrv->state	= VRRP_STATE_BACK;	}}/**************************************************************** NAME	: open_sock				00/02/07 12:40:00 AIM	: open the socket and join the multicast group. REMARK	:****************************************************************/static int open_sock( vrrp_rt *vsrv ){	struct	ip_mreq req;	int	ret;	/* open the socket */	vsrv->sockfd = socket( AF_INET, SOCK_RAW, IPPROTO_VRRP );	if( vsrv->sockfd < 0 ){		int	err = errno;		VRRP_LOG(("cant open raw socket. errno=%d. (try to run it as root)\n"						, err));		return -1;	}	/* join the multicast group */	memset( &req, 0, sizeof (req));	req.imr_multiaddr.s_addr = htonl(INADDR_VRRP_GROUP);	req.imr_interface.s_addr = htonl(vsrv->vif.ipaddr);	ret = setsockopt (vsrv->sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP,			       (char *) &req, sizeof (struct ip_mreq));	if( ret < 0 ){		int	err = errno;		VRRP_LOG(("cant do IP_ADD_MEMBERSHIP errno=%d\n",err));		return -1;	}	return 0;}/**************************************************************** NAME	: signal_end				00/05/10 23:20:36 AIM	: REMARK	:****************************************************************/static void signal_end( int nosig ){	vrrp_rt	*vsrv = &glob_vsrv;	/* remove the pid file */	pidfile_rm( vsrv );	/* if the deamon is master, leave this state */	if( vsrv->state == VRRP_STATE_MAST ){		state_leave_master( vsrv, 1 );	}	exit( 0 );}/**************************************************************** NAME	: signal_user				00/05/10 23:20:36 AIM	: REMARK	:****************************************************************/static void signal_user( int nosig ){	vrrp_rt	*vsrv = &glob_vsrv;	if( nosig == SIGUSR1 ){		vsrv->wantstate = VRRP_STATE_MAST;	}	if( nosig == SIGUSR2 ){		vsrv->wantstate = VRRP_STATE_BACK;	}		/* rearm the signal */	signal( nosig, signal_user );}/**************************************************************** NAME	: main					00/02/06 08:48:02 AIM	: REMARK	:****************************************************************/int main( int argc, char *argv[] ){	vrrp_rt	*vsrv = &glob_vsrv;#if 1	/* for debug only */	setbuf(stdout,NULL);	setbuf(stderr,NULL);#endif		snprintf( PidDir, sizeof(PidDir), "%s", VRRP_PIDDIR_DFL );	init_virtual_srv(vsrv);	/* parse the command line */	argc = parse_cmdline(vsrv,argc, argv );	if( argc < 0 ) {		return -1;	}	/* add the virtual server ip */	for( ; argv[argc]; argc++ ){		uint32_t ipaddr = inet_addr( argv[argc] );		cfg_add_ipaddr( vsrv, ntohl(ipaddr) );	}	/* check if the minimal configuration has been done */	if( chk_min_cfg( vsrv ) ){		fprintf(stderr, "try '%s -h' to read the help\n", argv[0]);		return -1;	}	if( open_sock( vsrv ) ){		return -1;	}	/* the init is completed */	vsrv->initF = 1;	/* init signal handler */	signal( SIGINT, signal_end );	signal( SIGTERM, signal_end );	signal( SIGUSR1, signal_user );	signal( SIGUSR2, signal_user );	/* try to write a pid file */	if( pidfile_exist( vsrv ) )	return -1;	pidfile_write( vsrv );	/* main loop */	while( 1 ){		switch( vsrv->state ){		case VRRP_STATE_INIT:	state_init( vsrv );	break;		case VRRP_STATE_BACK:	state_back( vsrv );	break;		case VRRP_STATE_MAST:	state_mast( vsrv );	break;		}	}	return(0);}

⌨️ 快捷键说明

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