示例#1
0
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;
}
示例#2
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;
}