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); }
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)); } } } }
/* * 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, ¤t->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; }
/* * 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, ¤t->Address, address_text, INET6_ADDRSTRLEN); /* If a non-authorized client sent a solicitation, ignore it (logging later) */ if (dest != NULL && memcmp(dest, ¤t->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; }
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)); } }
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)); } }
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); }
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); } } } }
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); }
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); } }
int dhcp_network_icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) { return send_ra(0); }