static int icmp6_router_solicitation_timeout(sd_event_source *s, uint64_t usec, void *userdata) { sd_icmp6_nd *nd = userdata; uint64_t time_now, next_timeout; struct ether_addr unset = { }; struct ether_addr *addr = NULL; int r; assert(s); assert(nd); assert(nd->event); nd->timeout = sd_event_source_unref(nd->timeout); if (nd->nd_sent >= ICMP6_MAX_ROUTER_SOLICITATIONS) { icmp6_nd_notify(nd, ICMP6_EVENT_ROUTER_ADVERTISMENT_TIMEOUT); nd->state = ICMP6_ROUTER_ADVERTISMENT_LISTEN; } else { if (memcmp(&nd->mac_addr, &unset, sizeof(struct ether_addr))) addr = &nd->mac_addr; r = dhcp_network_icmp6_send_router_solicitation(nd->fd, addr); if (r < 0) log_icmp6_nd(nd, "Error sending Router Solicitation"); else { nd->state = ICMP6_ROUTER_SOLICITATION_SENT; log_icmp6_nd(nd, "Sent Router Solicitation"); } nd->nd_sent++; r = sd_event_now(nd->event, CLOCK_MONOTONIC, &time_now); if (r < 0) { icmp6_nd_notify(nd, r); return 0; } next_timeout = time_now + ICMP6_ROUTER_SOLICITATION_INTERVAL; r = sd_event_add_time(nd->event, &nd->timeout, CLOCK_MONOTONIC, next_timeout, 0, icmp6_router_solicitation_timeout, nd); if (r < 0) { icmp6_nd_notify(nd, r); return 0; } r = sd_event_source_set_priority(nd->timeout, nd->event_priority); if (r < 0) { icmp6_nd_notify(nd, r); return 0; } } return 0; }
static int icmp6_router_advertisment_recv(sd_event_source *s, int fd, uint32_t revents, void *userdata) { sd_icmp6_nd *nd = userdata; ssize_t len; struct nd_router_advert ra; int event = ICMP6_EVENT_ROUTER_ADVERTISMENT_NONE; assert(s); assert(nd); assert(nd->event); /* only interested in Managed/Other flag */ len = read(fd, &ra, sizeof(ra)); if ((size_t)len < sizeof(ra)) return 0; if (ra.nd_ra_type != ND_ROUTER_ADVERT) return 0; if (ra.nd_ra_code != 0) return 0; nd->timeout = sd_event_source_unref(nd->timeout); nd->state = ICMP6_ROUTER_ADVERTISMENT_LISTEN; if (ra.nd_ra_flags_reserved & ND_RA_FLAG_OTHER ) event = ICMP6_EVENT_ROUTER_ADVERTISMENT_OTHER; if (ra.nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) event = ICMP6_EVENT_ROUTER_ADVERTISMENT_MANAGED; log_icmp6_nd(nd, "Received Router Advertisement flags %s/%s", (ra.nd_ra_flags_reserved & ND_RA_FLAG_MANAGED)? "MANAGED": "none", (ra.nd_ra_flags_reserved & ND_RA_FLAG_OTHER)? "OTHER": "none"); icmp6_nd_notify(nd, event); return 0; }