From: Roy Marples Date: Tue, 21 Oct 2014 22:55:30 +0000 (+0000) Subject: RFC 3927 Section 2.1 states that the random number generator should be X-Git-Tag: v6.6.0~17 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=673c00481ac14baffb37cd9decfd1538f5eee45d;p=thirdparty%2Fdhcpcd.git RFC 3927 Section 2.1 states that the random number generator should be seeded with a known value derived from the IEEE 802 MAC address and that the first 256 and last 256 addresses are reserved for future use. --- diff --git a/dhcp.h b/dhcp.h index 71410235..48e1bba0 100644 --- a/dhcp.h +++ b/dhcp.h @@ -212,13 +212,18 @@ struct dhcp_state { time_t nakoff; uint32_t xid; int socket; + + /* ARP */ int probes; int claims; - int conflicts; - time_t defend; struct in_addr fail; size_t arping_index; + /* IPv4LL */ + char randomstate[128]; + int conflicts; + time_t defend; + int raw_fd; int arp_fd; size_t buffer_size, buffer_len, buffer_pos; diff --git a/ipv4ll.c b/ipv4ll.c index ab4b5c08..bc37e376 100644 --- a/ipv4ll.c +++ b/ipv4ll.c @@ -71,29 +71,36 @@ ipv4ll_make_lease(uint32_t addr) } static struct dhcp_message * -ipv4ll_find_lease(struct dhcpcd_ctx *ctx) +ipv4ll_find_lease(const struct interface *ifp) { uint32_t addr; - struct interface *ifp; + struct interface *ifp2; const struct dhcp_state *state; for (;;) { - addr = ntohl(LINKLOCAL_ADDR | - (uint32_t)(abs((int)arc4random_uniform(0xFD00)) + 0x0100)); + addr = ntohl(LINKLOCAL_ADDR | random() & 0x0000FFFF); - /* Sanity */ - if (!IN_LINKLOCAL(htonl(addr))) + state = D_CSTATE(ifp); + /* No point using a failed address */ + if (addr == state->fail.s_addr) + continue; + + /* RFC 3927 Section 2.1 states that the first 256 and + * last 256 addresses are reserved for future use */ + if (!IN_LINKLOCAL(htonl(addr)) || + (htonl(addr) & 0x0000FF00) == 0x0000 || + (htonl(addr) & 0x0000FF00) == 0xFF00) continue; /* Ensure we don't have the address on another interface */ - TAILQ_FOREACH(ifp, ctx->ifaces, next) { - state = D_CSTATE(ifp); + TAILQ_FOREACH(ifp2, ifp->ctx->ifaces, next) { + state = D_CSTATE(ifp2); if (state && state->addr.s_addr == addr) break; } /* Yay, this should be a unique and workable IPv4LL address */ - if (ifp == NULL) + if (ifp2 == NULL) break; } return ipv4ll_make_lease(addr); @@ -115,6 +122,21 @@ ipv4ll_start(void *arg) struct dhcp_state *state = D_STATE(ifp); uint32_t addr; + /* RFC 3927 Section 2.1 states that the random number generator + * SHOULD be seeded with a value derived from persistent information + * such as the IEEE 802 MAC address. */ + if (state->conflicts == 0) { + unsigned int seed; + + if (sizeof(seed) > ifp->hwlen) { + seed = 0; + memcpy(&seed, ifp->hwaddr, ifp->hwlen); + } else + memcpy(&seed, ifp->hwaddr + ifp->hwlen - sizeof(seed), + sizeof(seed)); + initstate(seed, state->randomstate, sizeof(state->randomstate)); + } + eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp); state->probes = 0; state->claims = 0; @@ -133,6 +155,7 @@ ipv4ll_start(void *arg) } state->state = DHS_INIT_IPV4LL; + setstate(state->randomstate); /* We maybe rebooting an IPv4LL address. */ if (!IN_LINKLOCAL(htonl(addr))) { syslog(LOG_INFO, "%s: probing for an IPv4LL address", @@ -140,15 +163,15 @@ ipv4ll_start(void *arg) addr = 0; } if (addr == 0) - state->offer = ipv4ll_find_lease(ifp->ctx); + state->offer = ipv4ll_find_lease(ifp); else state->offer = ipv4ll_make_lease(addr); - if (state->offer == NULL) + if (state->offer == NULL) { syslog(LOG_ERR, "%s: %m", __func__); - else { - state->lease.frominfo = 0; - arp_probe(ifp); + return; } + state->lease.frominfo = 0; + arp_probe(ifp); } void