arp_announce1(astate);
}
-void
+struct arp_state *
arp_ifannounceaddr(struct interface *ifp, const struct in_addr *ia)
{
struct arp_state *astate;
if (ifp->flags & IFF_NOARP)
- return;
+ return NULL;
astate = arp_find(ifp, ia);
if (astate == NULL) {
astate = arp_new(ifp, ia);
if (astate == NULL)
- return;
+ return NULL;
astate->announced_cb = arp_free;
}
arp_announce(astate);
+ return astate;
}
-void
+struct arp_state *
arp_announceaddr(struct dhcpcd_ctx *ctx, const struct in_addr *ia)
{
struct interface *ifp, *iff = NULL;
iff = ifp;
}
if (iff == NULL)
- return;
+ return NULL;
- arp_ifannounceaddr(iff, ia);
+ return arp_ifannounceaddr(iff, ia);
}
struct arp_state *
struct arp_state *arp_new(struct interface *, const struct in_addr *);
void arp_probe(struct arp_state *);
void arp_announce(struct arp_state *);
-void arp_announceaddr(struct dhcpcd_ctx *, const struct in_addr *);
-void arp_ifannounceaddr(struct interface *, const struct in_addr *);
+struct arp_state *arp_announceaddr(struct dhcpcd_ctx *, const struct in_addr *);
+struct arp_state *arp_ifannounceaddr(struct interface *, const struct in_addr *);
void arp_cancel(struct arp_state *);
struct arp_state * arp_find(struct interface *, const struct in_addr *);
void arp_free(struct arp_state *);
.s_addr = HTONL(LINKLOCAL_BCAST)
};
-static in_addr_t
+static void
ipv4ll_pickaddr(struct interface *ifp)
{
- struct in_addr addr;
+ struct in_addr addr = { .s_addr = 0 };
struct ipv4ll_state *state;
state = IPV4LL_STATE(ifp);
/* Restore the original random state */
setstate(ifp->ctx->randomstate);
- return addr.s_addr;
+ state->pickedaddr = addr;
}
int
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;
- arp_free(astate);
- if (state->arp == astate)
- state->arp = NULL;
}
+#ifndef KERNEL_RFC5227
/* This is the callback by ARP freeing */
static void
-ipv4ll_arpfree(struct arp_state *astate)
+ipv4ll_free_arp(struct arp_state *astate)
{
struct ipv4ll_state *state;
{
struct ipv4ll_state *state;
struct ipv4_addr *ia;
+ struct arp_state *astate;
state = IPV4LL_STATE(ifp);
ia = ipv4_iffindaddr(ifp, &state->pickedaddr, &inaddr_llmask);
return;
}
rt_build(ifp->ctx, AF_INET);
- arp_announceaddr(ifp->ctx, &ia->addr);
+ astate = arp_announceaddr(ifp->ctx, &ia->addr);
+ if (astate != NULL)
+ astate->announced_cb = ipv4ll_announced_arp;
script_runreason(ifp, "IPV4LL");
dhcpcd_daemonise(ifp->ctx);
}
if (++state->conflicts == MAX_CONFLICTS)
logerrx("%s: failed to acquire an IPv4LL address",
ifp->name);
- state->pickedaddr.s_addr = ipv4ll_pickaddr(ifp);
+ ipv4ll_pickaddr(ifp);
eloop_timeout_add_sec(ifp->ctx->eloop,
state->conflicts >= MAX_CONFLICTS ?
RATE_LIMIT_INTERVAL : PROBE_WAIT,
state->addr = NULL;
rt_build(ifp->ctx, AF_INET);
script_runreason(ifp, "IPV4LL");
- state->pickedaddr.s_addr = ipv4ll_pickaddr(ifp);
+ ipv4ll_pickaddr(ifp);
ipv4ll_start(ifp);
}
#ifdef IN_IFF_DUPLICATED
loginfox("%s: using IPv4LL address %s", ifp->name, ia->saddr);
#endif
- ipv4ll_not_found(ifp);
- return;
+ } else {
+ loginfox("%s: probing for an IPv4LL address", ifp->name);
+ if (repick || state->pickedaddr.s_addr == INADDR_ANY)
+ ipv4ll_pickaddr(ifp);
}
- 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
+#ifdef KERNEL_RFC5227
+ ipv4ll_not_found(ifp);
+#else
ipv4ll_freearp(ifp);
- state->arp = astate = arp_new(ifp, NULL);
+ state->arp = astate = arp_new(ifp, &state->pickedaddr);
if (state->arp == NULL)
return;
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
+ astate->free_cb = ipv4ll_free_arp;
arp_probe(astate);
#endif
}