Beispiel #1
0
static void process_rs(struct Interface *iface, unsigned char *msg, int len, struct sockaddr_in6 *addr)
{
	double delay;
	double next;
	struct timespec ts;
	uint8_t *opt_str;

	/* validation */
	len -= sizeof(struct nd_router_solicit);

	opt_str = (uint8_t *) (msg + sizeof(struct nd_router_solicit));

	while (len > 0) {
		int optlen;

		if (len < 2) {
			flog(LOG_WARNING, "trailing garbage in RS");
			return;
		}

		optlen = (opt_str[1] << 3);

		if (optlen == 0) {
			flog(LOG_WARNING, "zero length option in RS");
			return;
		} else if (optlen > len) {
			flog(LOG_WARNING, "option length greater than total length in RS");
			return;
		}

		if (*opt_str == ND_OPT_SOURCE_LINKADDR && IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr)) {
			flog(LOG_WARNING, "received icmpv6 RS packet with unspecified source address and there is a lladdr option");
			return;
		}

		len -= optlen;
		opt_str += optlen;
	}

	clock_gettime(CLOCK_MONOTONIC, &ts);

	delay = MAX_RA_DELAY_TIME * rand() / (RAND_MAX + 1.0);

	if (iface->UnicastOnly) {
		send_ra_forall(iface, &addr->sin6_addr);
	} else if (timespecdiff(&ts, &iface->last_multicast) / 1000.0 < iface->MinDelayBetweenRAs) {
		/* last RA was sent only a few moments ago, don't send another immediately. */
		next =
		    iface->MinDelayBetweenRAs - (ts.tv_sec + ts.tv_nsec / 1000000000.0) + (iface->last_multicast.tv_sec + iface->last_multicast.tv_nsec / 1000000000.0) + delay / 1000.0;
		iface->next_multicast = next_timespec(next);
	} else {
		/* no RA sent in a while, send a multicast reply */
		send_ra_forall(iface, NULL);
		next = rand_between(iface->MinRtrAdvInterval, iface->MaxRtrAdvInterval);
		iface->next_multicast = next_timespec(next);
	}
}
Beispiel #2
0
void
stop_adverts(void)
{
    struct Interface *iface;

    /*
    *	send final RA (a SHOULD in RFC4861 section 6.2.5)
    */

    /* BEGIN: Added by z67728, 2009/12/28 PN:AU4D02322 Radvd模块关闭后,默认路由器将会失效。
    现将前缀地址的首选时间和在链标志去除,防止PC继续使用该地址通信. */    
    if ( 0 == g_iReadTestFlag )
    {        
        disable_oldprefix();
        disable_oldstataddr();
    }
    /* END:   Added by z67728, 2009/12/28 */

    for (iface=IfaceList; iface; iface=iface->next) {
        if( ! iface->UnicastOnly ) {
            if (iface->AdvSendAdvert) {
                /* send a final advertisement with zero Router Lifetime */
                iface->AdvDefaultLifetime = 0;
                send_ra_forall(sock, iface, NULL);
            }
        }
    }
}
Beispiel #3
0
void
kickoff_adverts(void)
{
	struct Interface *iface;

	/*
	 *	send initial advertisement and set timers
	 */

	for(iface=IfaceList; iface; iface=iface->next)
	{
		if( iface->UnicastOnly )
			break;

		init_timer(&iface->tm, timer_handler, (void *) iface);

		if (!iface->AdvSendAdvert)
			break;

		/* send an initial advertisement */
		send_ra_forall(sock, iface, NULL);

		iface->init_racount++;

		set_timer(&iface->tm,
			  min(MAX_INITIAL_RTR_ADVERT_INTERVAL,
			      iface->MaxRtrAdvInterval));
	}
}
Beispiel #4
0
void
kickoff_adverts(void)
{
	struct Interface *iface;

	/*
	 *	send initial advertisement and set timers
	 */

	for(iface=IfaceList; iface; iface=iface->next)
	{
		double next;


		gettimeofday(&iface->last_ra_time, NULL);

		if( iface->UnicastOnly )
			continue;

		gettimeofday(&iface->last_multicast, NULL);

		if (!iface->AdvSendAdvert)
			continue;

		/* send an initial advertisement */
		if (send_ra_forall(iface, NULL) == 0) {

			iface->init_racount++;

			next = min(MAX_INITIAL_RTR_ADVERT_INTERVAL, iface->MaxRtrAdvInterval);
			iface->next_multicast = next_timeval(next);
		}
	}
}
Beispiel #5
0
static void stop_advert_foo(struct Interface *iface, void *data)
{
	if (!iface->UnicastOnly) {
		/* send a final advertisement with zero Router Lifetime */
		dlog(LOG_DEBUG, 4, "stopping all adverts on %s", iface->props.name);
		iface->state_info.cease_adv = 1;
		int sock = *(int *)data;
		send_ra_forall(sock, iface, NULL);
	}
}
Beispiel #6
0
static void timer_handler(int sock, struct Interface *iface)
{
	dlog(LOG_DEBUG, 1, "timer_handler called for %s", iface->props.name);

	if (send_ra_forall(sock, iface, NULL) != 0) {
		dlog(LOG_DEBUG, 4, "send_ra_forall failed on interface %s", iface->props.name);
	}

	double next = rand_between(iface->MinRtrAdvInterval, iface->MaxRtrAdvInterval);

	reschedule_iface(iface, next);
}
Beispiel #7
0
/* BEGIN: Added by z67728, 2009/12/26 PN:AU4D02322 */
void
disable_oldprefix(void)
{
    if ( 0 == g_iReadTestFlag )
    {        
    	struct Interface *iface;

    	/*
    	 *	RA配置发生变化时,将变化前的前缀设置为无效.
    	 */

    	for (iface=IfaceList; iface; iface=iface->next) {
    		if( ! iface->UnicastOnly ) {
    			if (iface->AdvSendAdvert) {
    				/* send a final advertisement with zero Router Lifetime */
    				if ( NULL != iface->AdvPrefixList )
    				{
    				    while ( 1 )
    				    {
    				        /* 只能修改时间,不能修改其他参数.否则客户端认为此RA非法. 
                            The only way to cancela previous on-link indication is to 
                            advertise that prefix with the L-bit set and the Lifetime 
                            set to zero.  */
                            iface->AdvPrefixList->AdvOnLinkFlag        = 0;
    				        iface->AdvPrefixList->AdvValidLifetime     = 0;
                            iface->AdvPrefixList->AdvPreferredLifetime = 0;
                            
                            if ( NULL == iface->AdvPrefixList->next)
                            {
                                break;
                            }
                            else
                            {
                                iface->AdvPrefixList = iface->AdvPrefixList->next;
                                continue;
                            }
    				    }
                        
        				send_ra_forall(sock, iface, NULL);
    				}
    			}
    		}
    	}
    }
    
    return;
}
Beispiel #8
0
/*
 *      send initial advertisement and set timers
 */
static void kickoff_adverts(int sock, struct Interface *iface)
{
	clock_gettime(CLOCK_MONOTONIC, &iface->times.last_ra_time);

	if (iface->UnicastOnly)
		return;

	clock_gettime(CLOCK_MONOTONIC, &iface->times.last_multicast);

	/* send an initial advertisement */
	if (send_ra_forall(sock, iface, NULL) != 0) {
		dlog(LOG_DEBUG, 4, "send_ra_forall failed on interface %s", iface->props.name);
	}

	double next = min(MAX_INITIAL_RTR_ADVERT_INTERVAL, iface->MaxRtrAdvInterval);
	reschedule_iface(iface, next);
}
Beispiel #9
0
void
stop_adverts(void)
{
	struct Interface *iface;

	/*
	 *	send final RA (a SHOULD in RFC4861 section 6.2.5)
	 */

	for (iface=IfaceList; iface; iface=iface->next) {
		if( ! iface->UnicastOnly ) {
			if (iface->AdvSendAdvert) {
				/* send a final advertisement with zero Router Lifetime */
				iface->cease_adv = 1;
				send_ra_forall(iface, NULL);
			}
		}
	}
}
Beispiel #10
0
void
timer_handler(void *data)
{
	struct Interface *iface = (struct Interface *) data;
	double next;

	dlog(LOG_DEBUG, 4, "timer_handler called for %s", iface->Name);

	send_ra_forall(sock, iface, NULL);

	next = rand_between(iface->MinRtrAdvInterval, iface->MaxRtrAdvInterval); 

	if (iface->init_racount < MAX_INITIAL_RTR_ADVERTISEMENTS - 1)
	{
		iface->init_racount++;
		next = min(MAX_INITIAL_RTR_ADVERT_INTERVAL, next);
	}

	set_timer(&iface->tm, next);
}
Beispiel #11
0
void disable_oldstataddr()
{
    if ( 0 == g_iReadTestFlag )
    {        
    	struct Interface *iface;

    	/*
    	 *	RA配置发生变化时,将变化前的前缀设置为无效.
    	 */

    	for (iface=IfaceList; iface; iface=iface->next) {
    		if( ! iface->UnicastOnly ) {
    			if (iface->AdvSendAdvert) {
    				/* send a final advertisement with zero Router Lifetime */
    				if ( NULL != iface->AdvPrefixList )
    				{
    				    while ( 1 )
    				    {
                            iface->AdvManagedFlag     = 0;
    				        iface->AdvOtherConfigFlag = 0;
                            
                            if ( NULL == iface->AdvPrefixList->next)
                            {
                                break;
                            }
                            else
                            {
                                iface->AdvPrefixList = iface->AdvPrefixList->next;
                                continue;
                            }
    				    }
                        
        				send_ra_forall(sock, iface, NULL);
    				}
    			}
    		}
    	}
    }

    return;
}
Beispiel #12
0
void
timer_handler(void *data)
{
	struct Interface *iface = (struct Interface *) data;
	double next;

	dlog(LOG_DEBUG, 4, "timer_handler called for %s", iface->Name);

	if (send_ra_forall(iface, NULL) != 0) {
		return;
	}

	next = rand_between(iface->MinRtrAdvInterval, iface->MaxRtrAdvInterval);

	if (iface->init_racount < MAX_INITIAL_RTR_ADVERTISEMENTS)
	{
		iface->init_racount++;
		next = min(MAX_INITIAL_RTR_ADVERT_INTERVAL, next);
	}

	iface->next_multicast = next_timeval(next);
}
Beispiel #13
0
static void
process_rs(int sock, struct Interface *iface, unsigned char *msg, int len,
	struct sockaddr_in6 *addr)
{
	double delay;
	double next;
	struct timeval tv;
	uint8_t *opt_str;

	/* validation */
	len -= sizeof(struct nd_router_solicit);

	opt_str = (uint8_t *)(msg + sizeof(struct nd_router_solicit));

	//printf("radvd:proc_rs enter!len=%d\n",len);
	while (len > 0)
	{
		int optlen;

		if (len < 2)
		{
			flog(LOG_WARNING, "trailing garbage in RS");
	//printf("radvd:return1!!!\n");
			return;
		}

		optlen = (opt_str[1] << 3);

		if (optlen == 0)
		{
	//printf("radvd:return2!!!\n");
			flog(LOG_WARNING, "zero length option in RS");
			return;
		}
		else if (optlen > len)
		{
//	printf("radvd:return3!!!\n");
			flog(LOG_WARNING, "option length greater than total length in RS");
			return;
		}

		if (*opt_str == ND_OPT_SOURCE_LINKADDR &&
		    IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr)) {
			flog(LOG_WARNING, "received icmpv6 RS packet with unspecified source address and there is a lladdr option"); 
	printf("radvd:received icmpv6 return!!!\n");
			return;
		}

		len -= optlen;
		opt_str += optlen;
	}

//	printf("radvd:proc_rs_11\n");
	gettimeofday(&tv, NULL);

	delay = MAX_RA_DELAY_TIME*rand()/(RAND_MAX+1.0);
	dlog(LOG_DEBUG, 3, "random mdelay for %s: %.2f", iface->Name, delay);
 	
	if (iface->UnicastOnly) {
//	printf("radvd:proc_rs_22\n");
		mdelay(delay);
		send_ra_forall(sock, iface, &addr->sin6_addr);
	}
	else if ((tv.tv_sec + tv.tv_usec / 1000000.0) - (iface->last_multicast_sec +
	          iface->last_multicast_usec / 1000000.0) < iface->MinDelayBetweenRAs) {
		/* last RA was sent only a few moments ago, don't send another immediately */
//	printf("radvd:proc_rs_33\n");
		clear_timer(&iface->tm);
		next = iface->MinDelayBetweenRAs - (tv.tv_sec + tv.tv_usec / 1000000.0) +
		       (iface->last_multicast_sec + iface->last_multicast_usec / 1000000.0) + delay/1000.0;
		set_timer(&iface->tm, next);
	}
	else {
		/* no RA sent in a while, send an immediate multicast reply */
//	printf("radvd:ps_444\n");
		clear_timer(&iface->tm);
		if (send_ra_forall(sock, iface, NULL) == 0) {
			next = rand_between(iface->MinRtrAdvInterval, iface->MaxRtrAdvInterval); 
			set_timer(&iface->tm, next);
		}
	}
}