- // Rearm timer
- int msecs;
- odhcpd_urandom(&msecs, sizeof(msecs));
- msecs = (labs(msecs) % (1000 * (MaxRtrAdvInterval
- - MinRtrAdvInterval))) + (MinRtrAdvInterval * 1000);
- uloop_timeout_set(&iface->timer_rs, msecs);
+ return msecs;
+}
+
+
+static void trigger_router_advert(struct uloop_timeout *event)
+{
+ struct interface *iface = container_of(event, struct interface, timer_rs);
+ int msecs = send_router_advert(iface, NULL);
+
+ // Rearm timer if not shut down
+ if (event->cb)
+ uloop_timeout_set(event, msecs);
+}
+
+
+// Event handler for incoming ICMPv6 packets
+static void handle_icmpv6(void *addr, void *data, size_t len,
+ struct interface *iface, _unused void *dest)
+{
+ struct icmp6_hdr *hdr = data;
+ struct sockaddr_in6 *from = addr;
+
+ if (!router_icmpv6_valid(addr, data, len))
+ return;
+
+ if ((iface->ra == RELAYD_SERVER && !iface->master)) { // Server mode
+ if (hdr->icmp6_type == ND_ROUTER_SOLICIT)
+ send_router_advert(iface, &from->sin6_addr);
+ } else if (iface->ra == RELAYD_RELAY) { // Relay mode
+ if (hdr->icmp6_type == ND_ROUTER_ADVERT && iface->master)
+ forward_router_advertisement(data, len);
+ else if (hdr->icmp6_type == ND_ROUTER_SOLICIT && !iface->master)
+ forward_router_solicitation(odhcpd_get_master_interface());
+ }