Mercurial > hg > dhcpcd
changeset 5237:65cef5f96919 draft
IPv4LL: Fix for prior on NetBSD at least.
| author | Roy Marples <roy@marples.name> |
|---|---|
| date | Wed, 20 May 2020 12:17:00 +0100 |
| parents | 40c8b6fa2033 |
| children | 73659576d485 |
| files | src/arp.c src/arp.h src/ipv4ll.c src/ipv4ll.h |
| diffstat | 4 files changed, 57 insertions(+), 113 deletions(-) [+] |
line wrap: on
line diff
--- a/src/arp.c Tue May 19 16:44:49 2020 +0000 +++ b/src/arp.c Wed May 20 12:17:00 2020 +0100 @@ -509,7 +509,7 @@ if (iap == NULL) continue; #ifdef IN_IFF_NOTUSEABLE - if (!(iap->addr_flags & IN_IFF_NOTUSEABLE)) + if (iap->addr_flags & IN_IFF_NOTUSEABLE) continue; #endif if (iff != NULL && iff->metric < ifp->metric)
--- a/src/arp.h Tue May 19 16:44:49 2020 +0000 +++ b/src/arp.h Wed May 20 12:17:00 2020 +0100 @@ -47,7 +47,8 @@ #ifdef IN_IFF_DUPLICATED /* NetBSD gained RFC 5227 support in the kernel. - * This means dhcpcd doesn't need ARP except for ARPing support. */ + * This means dhcpcd doesn't need ARP except for ARPing support + * and ARP announcing an address. */ #if defined(__NetBSD_Version__) && __NetBSD_Version__ >= 799003900 #define KERNEL_RFC5227 #endif
--- a/src/ipv4ll.c Tue May 19 16:44:49 2020 +0000 +++ b/src/ipv4ll.c Wed May 20 12:17:00 2020 +0100 @@ -57,8 +57,6 @@ .s_addr = HTONL(LINKLOCAL_BCAST) }; -static void ipv4ll_start1(struct interface *, struct arp_state *); - static in_addr_t ipv4ll_pickaddr(struct interface *ifp) { @@ -170,17 +168,19 @@ return 5; } +#ifndef KERNEL_RFC5227 static void ipv4ll_announced_arp(struct arp_state *astate) { struct ipv4ll_state *state = IPV4LL_STATE(astate->iface); state->conflicts = 0; -#ifdef KERNEL_RFC5227 arp_free(astate); -#endif + if (state->arp == astate) + state->arp = NULL; } +/* This is the callback by ARP freeing */ static void ipv4ll_arpfree(struct arp_state *astate) { @@ -191,23 +191,32 @@ state->arp = NULL; } +/* This is us freeing any ARP state */ +static void +ipv4ll_freearp(struct interface *ifp) +{ + struct ipv4ll_state *state; + + state = IPV4LL_STATE(ifp); + if (state == NULL || state->arp == NULL) + return; + + eloop_timeout_delete(ifp->ctx->eloop, NULL, state->arp); + arp_free(state->arp); + state->arp = NULL; +} +#else +#define ipv4ll_freearp(ifp) +#endif + static void ipv4ll_not_found(struct interface *ifp) { struct ipv4ll_state *state; struct ipv4_addr *ia; -#ifdef KERNEL_RFC5227 - struct arp_state *astate; - bool new_addr; -#endif state = IPV4LL_STATE(ifp); - assert(state != NULL); - ia = ipv4_iffindaddr(ifp, &state->pickedaddr, &inaddr_llmask); -#ifdef KERNEL_RFC5227 - new_addr = ia == NULL; -#endif #ifdef IN_IFF_NOTREADY if (ia == NULL || ia->addr_flags & IN_IFF_NOTREADY) #endif @@ -227,6 +236,7 @@ return; logdebugx("%s: DAD completed for %s", ifp->name, ia->saddr); #endif + test: state->addr = ia; state->down = false; @@ -236,41 +246,17 @@ return; } rt_build(ifp->ctx, AF_INET); -#ifdef KERNEL_RFC5227 - if (!new_addr) { - astate = arp_new(ifp, &ia->addr); - if (ifp->ctx->options & DHCPCD_FORKED) - return; - if (astate != NULL) { - astate->announced_cb = ipv4ll_announced_arp; - astate->free_cb = ipv4ll_arpfree; - arp_announce(astate); - } - } -#else - arp_announce(state->arp); -#endif + arp_announceaddr(ifp->ctx, &ia->addr); script_runreason(ifp, "IPV4LL"); dhcpcd_daemonise(ifp->ctx); } static void -ipv4ll_startifp(void *arg) -{ - struct interface *ifp = arg; - struct ipv4ll_state *state; - - state = IPV4LL_STATE(ifp); - ipv4ll_start1(ifp, state->arp); -} - -static void ipv4ll_found(struct interface *ifp) { struct ipv4ll_state *state = IPV4LL_STATE(ifp); - if (state->arp != NULL) - arp_cancel(state->arp); + ipv4ll_freearp(ifp); if (++state->conflicts == MAX_CONFLICTS) logerrx("%s: failed to acquire an IPv4LL address", ifp->name); @@ -278,7 +264,7 @@ eloop_timeout_add_sec(ifp->ctx->eloop, state->conflicts >= MAX_CONFLICTS ? RATE_LIMIT_INTERVAL : PROBE_WAIT, - ipv4ll_startifp, ifp); + ipv4ll_start, ifp); } static void @@ -286,62 +272,49 @@ { struct ipv4ll_state *state = IPV4LL_STATE(ifp); - if (state->arp != NULL) - arp_cancel(state->arp); + ipv4ll_freearp(ifp); ipv4_deladdr(state->addr, 1); - state->down = true; state->addr = NULL; rt_build(ifp->ctx, AF_INET); script_runreason(ifp, "IPV4LL"); state->pickedaddr.s_addr = ipv4ll_pickaddr(ifp); - ipv4ll_start1(ifp, state->arp); + ipv4ll_start(ifp); } #ifndef KERNEL_RFC5227 static void ipv4ll_not_found_arp(struct arp_state *astate) { - struct interface *ifp; - struct ipv4ll_state *state; - assert(astate != NULL); - assert(astate->iface != NULL); - - ifp = astate->iface; - state = IPV4LL_STATE(ifp); - assert(state != NULL); - assert(state->arp == astate); - ipv4ll_not_found(ifp); + ipv4ll_not_found(astate->iface); } static void ipv4ll_found_arp(struct arp_state *astate, __unused const struct arp_msg *amsg) { - struct interface *ifp = astate->iface; - struct ipv4ll_state *state = IPV4LL_STATE(ifp); - assert(state->arp == astate); - ipv4ll_found(ifp); + ipv4ll_found(astate->iface); } static void ipv4ll_defend_failed_arp(struct arp_state *astate) { - struct ipv4ll_state *state = IPV4LL_STATE(astate->iface); - assert(state->arp == astate); ipv4ll_defend_failed(astate->iface); } #endif -static void -ipv4ll_start1(struct interface *ifp, struct arp_state *astate) +void +ipv4ll_start(void *arg) { + struct interface *ifp = arg; struct ipv4ll_state *state; struct ipv4_addr *ia; bool repick; +#ifndef KERNEL_RFC5227 + struct arp_state *astate; +#endif - assert(ifp != NULL); if ((state = IPV4LL_STATE(ifp)) == NULL) { ifp->if_data[IF_DATA_IPV4LL] = calloc(1, sizeof(*state)); if ((state = IPV4LL_STATE(ifp)) == NULL) { @@ -377,26 +350,6 @@ state->seeded = true; } -#ifndef KERNEL_RFC5227 - if (astate == NULL) { - if (state->arp != NULL) - return; - if ((astate = arp_new(ifp, NULL)) == NULL) - return; - astate->found_cb = ipv4ll_found_arp; - astate->not_found_cb = ipv4ll_not_found_arp; - astate->announced_cb = ipv4ll_announced_arp; - astate->defend_failed_cb = ipv4ll_defend_failed_arp; - astate->free_cb = ipv4ll_arpfree; - state->arp = astate; - } else - assert(state->arp == astate); -#else - UNUSED(astate); -#endif - - state->down = true; - /* Find the previosuly used address. */ if (state->pickedaddr.s_addr != INADDR_ANY) ia = ipv4_iffindaddr(ifp, &state->pickedaddr, NULL); @@ -418,11 +371,9 @@ #endif state->addr = ia; + state->down = true; if (ia != NULL) { state->pickedaddr = ia->addr; -#ifndef KERNEL_RFC5227 - astate->addr = ia->addr; -#endif #ifdef IN_IFF_TENTATIVE if (ia->addr_flags & (IN_IFF_TENTATIVE | IN_IFF_DETACHED)) { loginfox("%s: waiting for DAD to complete on %s", @@ -440,9 +391,20 @@ loginfox("%s: probing for an IPv4LL address", ifp->name); if (repick || state->pickedaddr.s_addr == INADDR_ANY) state->pickedaddr.s_addr = ipv4ll_pickaddr(ifp); + #ifndef KERNEL_RFC5227 - astate->addr = state->pickedaddr; + ipv4ll_freearp(ifp); + state->arp = astate = arp_new(ifp, NULL); + if (state->arp == NULL) + return; + + astate->found_cb = ipv4ll_found_arp; + astate->not_found_cb = ipv4ll_not_found_arp; + astate->announced_cb = ipv4ll_announced_arp; + astate->defend_failed_cb = ipv4ll_defend_failed_arp; + astate->free_cb = ipv4ll_arpfree; #endif + #ifdef IN_IFF_DUPLICATED ipv4ll_not_found(ifp); #else @@ -451,26 +413,6 @@ } void -ipv4ll_start(void *arg) -{ - - ipv4ll_start1(arg, NULL); -} - -static void -ipv4ll_freearp(struct interface *ifp) -{ - struct ipv4ll_state *state; - - state = IPV4LL_STATE(ifp); - if (state == NULL || state->arp == NULL) - return; - - eloop_timeout_delete(ifp->ctx->eloop, NULL, state->arp); - arp_free(state->arp); -} - -void ipv4ll_drop(struct interface *ifp) { struct ipv4ll_state *state; @@ -516,6 +458,7 @@ if (state == NULL) return; + ipv4ll_freearp(ifp); state->pickedaddr.s_addr = INADDR_ANY; state->seeded = false; } @@ -587,9 +530,7 @@ ipv4ll_not_found(ifp); else if (ia->addr_flags & IN_IFF_DUPLICATED) { logerrx("%s: DAD detected %s", ifp->name, ia->saddr); -#ifdef KERNEL_RFC5227 - arp_freeaddr(ifp, &ia->addr); -#endif + ipv4ll_freearp(ifp); ipv4_deladdr(ia, 1); state->addr = NULL; rt_build(ifp->ctx, AF_INET);
--- a/src/ipv4ll.h Tue May 19 16:44:49 2020 +0000 +++ b/src/ipv4ll.h Wed May 20 12:17:00 2020 +0100 @@ -43,11 +43,13 @@ struct ipv4ll_state { struct in_addr pickedaddr; struct ipv4_addr *addr; - struct arp_state *arp; char randomstate[128]; bool seeded; bool down; size_t conflicts; +#ifndef KERNEL_RFC5227 + struct arp_state *arp; +#endif }; #define IPV4LL_STATE(ifp) \
