Пример #1
0
static void test_rs_done(sd_icmp6_nd *nd, int event, void *userdata) {
        sd_event *e = userdata;
        static int idx = 0;
        struct {
                uint8_t flag;
                int event;
        } flag_event[] = {
                { 0, ICMP6_EVENT_ROUTER_ADVERTISMENT_NONE },
                { ND_RA_FLAG_OTHER, ICMP6_EVENT_ROUTER_ADVERTISMENT_OTHER },
                { ND_RA_FLAG_MANAGED, ICMP6_EVENT_ROUTER_ADVERTISMENT_MANAGED }
        };
        uint32_t mtu;

        assert_se(nd);

        assert_se(event == flag_event[idx].event);
        idx++;

        if (verbose)
                printf("  got event %d\n", event);

        if (idx < 3) {
                send_ra(flag_event[idx].flag);
                return;
        }

        assert_se(sd_icmp6_ra_get_mtu(nd, &mtu) == -ENOMSG);

        sd_event_exit(e, 0);
}
Пример #2
0
static void test_rs_done(sd_ndisc *nd, uint8_t flags, const struct in6_addr *gateway, unsigned lifetime, int pref, void *userdata) {
        sd_event *e = userdata;
        static unsigned idx = 0;
        uint8_t flags_array[] = {
                0,
                0,
                0,
                ND_RA_FLAG_OTHER,
                ND_RA_FLAG_MANAGED
        };
        uint32_t mtu;

        assert_se(nd);

        assert_se(flags == flags_array[idx]);
        idx++;

        if (verbose)
                printf("  got event 0x%02x\n", flags);

        if (idx < ELEMENTSOF(flags_array)) {
                send_ra(flags_array[idx]);
                return;
        }

        assert_se(sd_ndisc_get_mtu(nd, &mtu) == -ENOMSG);

        sd_event_exit(e, 0);
}
void
kickoff_adverts(void)
{
	struct Interface *iface;

	/*
	 *	send initial advertisement and set timers
	 */

	for(iface=IfaceList; iface; iface=iface->next)
	{
		if( ! iface->UnicastOnly )
		{
			init_timer(&iface->tm, timer_handler, (void *) iface);
			if (iface->AdvSendAdvert)
			{
				/* send an initial advertisement */
				send_ra(sock, iface, NULL);

				iface->init_racount++;

				set_timer(&iface->tm,
					  min(MAX_INITIAL_RTR_ADVERT_INTERVAL,
					      iface->MaxRtrAdvInterval));
			}
		}
	}
}
Пример #4
0
/*
 * Sends an advertisement for all specified clients of this interface
 * (or via broadcast, if there are no restrictions configured).
 *
 * If a destination address is given, the RA will be sent to the destination
 * address only, but only if it was configured.
 *
 */
int send_ra_forall(int sock, struct Interface *iface, struct in6_addr *dest)
{
	/* when netlink is not available (disabled or BSD), ensure_iface_setup is necessary. */
	if (ensure_iface_setup(sock, iface) < 0) {
		dlog(LOG_DEBUG, 3, "not sending RA for %s, interface is not ready", iface->props.name);
		return -1;
	}

	if (iface->state_info.racount < MAX_INITIAL_RTR_ADVERTISEMENTS)
		iface->state_info.racount++;

	/* If no list of clients was specified for this interface, we broadcast */
	if (iface->ClientList == NULL) {
		if (dest == NULL && iface->UnicastOnly) {
			dlog(LOG_DEBUG, 5, "no client list, no destination, unicast only...doing nothing");
			return 0;
		}
		return send_ra(sock, iface, dest);
	}

	/* If clients are configured, send the advertisement to all of them via unicast */
	for (struct Clients * current = iface->ClientList; current; current = current->next) {
		/* If a non-authorized client sent a solicitation, ignore it (logging later) */
		if (dest != NULL && memcmp(dest, &current->Address, sizeof(struct in6_addr)) != 0)
			continue;

		send_ra(sock, iface, &(current->Address));

		/* If we should only send the RA to a specific address, we are done */
		if (dest != NULL)
			return 0;
	}

	if (dest == NULL)
		return 0;

	/* If we refused a client's solicitation, log it if debugging is high enough */
	if (get_debuglevel() >= 5) {
		char address_text[INET6_ADDRSTRLEN] = { "" };
		inet_ntop(AF_INET6, dest, address_text, INET6_ADDRSTRLEN);
		dlog(LOG_DEBUG, 5, "Not answering request from %s, not configured", address_text);
	}

	return 0;
}
Пример #5
0
/*
 * Sends an advertisement for all specified clients of this interface
 * (or via broadcast, if there are no restrictions configured).
 *
 * If a destination address is given, the RA will be sent to the destination
 * address only, but only if it was configured.
 *
 */
int send_ra_forall(struct Interface *iface, struct in6_addr *dest)
{
	struct Clients *current;

	/* If no list of clients was specified for this interface, we broadcast */
	if (iface->ClientList == NULL) {
		if (dest == NULL && iface->UnicastOnly) {
			return 0;
		}
		return send_ra(iface, dest);
	}

	/* If clients are configured, send the advertisement to all of them via unicast */
	for (current = iface->ClientList; current; current = current->next) {
		char address_text[INET6_ADDRSTRLEN];
		memset(address_text, 0, sizeof(address_text));
		if (get_debuglevel() >= 5)
			inet_ntop(AF_INET6, &current->Address, address_text, INET6_ADDRSTRLEN);

		/* If a non-authorized client sent a solicitation, ignore it (logging later) */
		if (dest != NULL && memcmp(dest, &current->Address, sizeof(struct in6_addr)) != 0)
			continue;
		dlog(LOG_DEBUG, 5, "Sending RA to %s", address_text);
		send_ra(iface, &(current->Address));

		/* If we should only send the RA to a specific address, we are done */
		if (dest != NULL)
			return 0;
	}
	if (dest == NULL)
		return 0;

	/* If we refused a client's solicitation, log it if debugging is high enough */
	char address_text[INET6_ADDRSTRLEN];
	memset(address_text, 0, sizeof(address_text));
	if (get_debuglevel() >= 5)
		inet_ntop(AF_INET6, dest, address_text, INET6_ADDRSTRLEN);

	dlog(LOG_DEBUG, 5, "Not answering request from %s, not configured", address_text);
	return 0;
}
Пример #6
0
void radvd_reset_adverts(void) {
  if (iface->AdvSendAdvert) {
    /* send an initial advertisement */
    send_ra(sock, iface, NULL);
    
    iface->init_racount = 0;

    set_timer(&iface->tm,
              min(MAX_INITIAL_RTR_ADVERT_INTERVAL,
                  iface->MaxRtrAdvInterval));
  }
}
Пример #7
0
void radvd_kickoff_adverts(void) {
  init_timer(&iface->tm, radvd_timer_handler, (void *) iface);
  if (iface->AdvSendAdvert) {
    /* send an initial advertisement */
    send_ra(sock, iface, NULL);
    
    iface->init_racount++;

    set_timer(&iface->tm,
              min(MAX_INITIAL_RTR_ADVERT_INTERVAL,
                  iface->MaxRtrAdvInterval));
  }
}
Пример #8
0
static void start_ra(int ifindex, GSList *prefix)
{
	if (prefixes != NULL)
		g_slist_free_full(prefixes, g_free);

	prefixes = g_dhcpv6_copy_prefixes(prefix);

	enable_ipv6_forward(TRUE);

	if (timer_ra > 0)
		g_source_remove(timer_ra);

	send_ra(NULL);

	timer_ra = g_timeout_add_seconds(DEFAULT_RA_INTERVAL, send_ra, NULL);
}
Пример #9
0
void radvd_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(sock, iface, NULL);

  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);
  }

  set_timer(&iface->tm, next);
}
void
stop_adverts(void)
{
	struct Interface *iface;

	/*
	 *	send final RA (a SHOULD in RFC2461 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->AdvDefaultLifetime = 0;
				send_ra(sock, iface, NULL);
			}
		}
	}
}
Пример #11
0
static void test_rs_done(sd_icmp6_nd *nd, int event, void *userdata) {
        sd_event *e = userdata;
        static int idx = 0;
        struct {
                uint8_t flag;
                int event;
        } flag_event[] = {
                { 0, ICMP6_EVENT_ROUTER_ADVERTISMENT_NONE },
                { ND_RA_FLAG_OTHER, ICMP6_EVENT_ROUTER_ADVERTISMENT_OTHER },
                { ND_RA_FLAG_MANAGED, ICMP6_EVENT_ROUTER_ADVERTISMENT_MANAGED }
        };
        assert(nd);

        assert(event == flag_event[idx].event);
        idx++;

        if (verbose)
                printf("  got event %d\n", event);

        if (idx < 3)
                send_ra(flag_event[idx].flag);
        else
                sd_event_exit(e, 0);
}
Пример #12
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));

	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;
	}

	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) {
		mdelay(delay);
		send_ra(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 */
		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 */
		clear_timer(&iface->tm);
		send_ra(sock, iface, NULL);
		
		next = rand_between(iface->MinRtrAdvInterval, iface->MaxRtrAdvInterval); 
		set_timer(&iface->tm, next);
	}
}
Пример #13
0
int dhcp_network_icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) {
        return send_ra(0);
}