{
struct arp_state *astate = arg;
struct interface *ifp = astate->iface;
+ struct ipv4_addr *ia;
if (++astate->claims < ANNOUNCE_NUM)
logdebugx("%s: ARP announcing %s (%d of %d), "
logdebugx("%s: ARP announcing %s (%d of %d)",
ifp->name, inet_ntoa(astate->addr),
astate->claims, ANNOUNCE_NUM);
+
+ /* The kernel will send a Gratuitous ARP for newly added addresses.
+ * So we can avoid sending the same. */
+ ia = ipv4_iffindaddr(ifp, &astate->addr, NULL);
+ if (astate->claims == 1 && ia != NULL && ia->flags & IPV4_AF_NEW)
+ goto skip_request;
+
if (arp_request(ifp, &astate->addr, &astate->addr) == -1)
logerr(__func__);
+
+skip_request:
+ /* No longer a new address. */
+ if (ia != NULL)
+ ia->flags |= ~IPV4_AF_NEW;
+
eloop_timeout_add_sec(ifp->ctx->eloop, ANNOUNCE_WAIT,
astate->claims < ANNOUNCE_NUM ? arp_announce1 : arp_announced,
astate);
}
-/*
- * XXX FIXME
- * Kernels supporting RFC5227 will announce the address when it's
- * added.
- * dhcpcd should not announce when this happens, nor need to open
- * a BPF socket for it.
- * Also, an address might be added to a non preferred inteface when
- * the same address exists on a preferred one so we need to instruct
- * the kernel not to announce the address somehow.
- */
-
void
arp_announce(struct arp_state *astate)
{
{
struct arp_state *astate;
+ if (ifp->flags & IFF_NOARP)
+ return;
+
astate = arp_find(ifp, ia);
if (astate == NULL) {
astate = arp_new(ifp, ia);
{
struct ipv4_state *state;
struct ipv4_addr *ia;
- bool is_new = false;
#ifdef ALIAS_ADDR
int replaced, blank;
struct ipv4_addr *replaced_ia;
#ifdef IN_IFF_TENTATIVE
ia->addr_flags = IN_IFF_TENTATIVE;
#endif
- is_new = true;
- }
+ ia->flags = IPV4_AF_NEW;
+ } else
+ ia->flags |= ~IPV4_AF_NEW;
ia->mask = *mask;
ia->brd = *bcast;
}
#endif
- if (is_new)
+ if (ia->flags & IPV4_AF_NEW)
TAILQ_INSERT_TAIL(&state->addrs, ia, next);
return ia;
}
#ifdef ARP
/* Announce the preferred address to
* kick ARP caches. */
- if (!(ifp->flags & IFF_NOARP))
- arp_announceaddr(ifp->ctx,&lease->addr);
+ arp_announceaddr(ifp->ctx,&lease->addr);
#endif
}
script_runreason(ifp, state->reason);
rt_build(ifp->ctx, AF_INET);
#ifdef ARP
- if (!(ifp->flags & IFF_NOARP))
- arp_announceaddr(ifp->ctx, &state->addr->addr);
+ arp_announceaddr(ifp->ctx, &state->addr->addr);
#endif
if (state->state == DHS_BOUND) {
TAILQ_HEAD(ipv4_addrhead, ipv4_addr);
#define IPV4_AF_STALE (1U << 0)
+#define IPV4_AF_NEW (1U << 1)
#define IPV4_ADDR_EQ(a1, a2) ((a1) && (a1)->addr.s_addr == (a2)->addr.s_addr)
#define IPV4_MASK1_EQ(a1, a2) ((a1) && (a1)->mask.s_addr == (a2)->mask.s_addr)