]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Support kernels which implement RFC5227.
authorRoy Marples <roy@marples.name>
Fri, 14 Oct 2016 08:55:04 +0000 (08:55 +0000)
committerRoy Marples <roy@marples.name>
Fri, 14 Oct 2016 08:55:04 +0000 (08:55 +0000)
This means we don't have to open an ARP socket unless we need to ARPing.
Allow ARP an ARPing to be optional features.

README
arp.c
arp.h
configure
dhcp.c
dhcp.h
dhcpcd.c
ipv4.c
ipv4ll.c

diff --git a/README b/README
index e2389015567e186fc6edd4d4f587ad55ae50badd..50a69c77f9c624abb8d1b9ba66b3b1bf4cdfee20 100644 (file)
--- a/README
+++ b/README
@@ -24,6 +24,8 @@ dhcpcd can also be made smaller by removing the IPv4 or IPv6 stack:
   *  --disable-inet6
 Or by removing the following features:
   *  --disable-auth
+  *  --disable-arp
+  *  --disable-arping
   *  --disable-ipv4ll
   *  --disable-dhcp6
 
diff --git a/arp.c b/arp.c
index d08907f6aef42ff67d0bed546b432a5b5cb04ab1..02536caaa3a353515e2ba8cabe6b6fcdad93c5c4 100644 (file)
--- a/arp.c
+++ b/arp.c
@@ -52,6 +52,7 @@
 #include "if-options.h"
 #include "ipv4ll.h"
 
+#if defined(ARP) && (!defined(KERNEL_RFC5227) || defined(ARPING))
 #define ARP_LEN                                                                      \
        (sizeof(struct arphdr) + (2 * sizeof(uint32_t)) + (2 * HWADDR_LEN))
 
@@ -101,26 +102,6 @@ eexit:
        return -1;
 }
 
-void
-arp_report_conflicted(const struct arp_state *astate,
-    const struct arp_msg *amsg)
-{
-
-       if (amsg != NULL) {
-               char buf[HWADDR_LEN * 3];
-
-               logger(astate->iface->ctx, LOG_ERR,
-                   "%s: hardware address %s claims %s",
-                   astate->iface->name,
-                   hwaddr_ntoa(amsg->sha, astate->iface->hwlen,
-                   buf, sizeof(buf)),
-                   inet_ntoa(astate->failed));
-       } else
-               logger(astate->iface->ctx, LOG_ERR,
-                   "%s: DAD detected %s",
-                   astate->iface->name, inet_ntoa(astate->failed));
-}
-
 static void
 arp_packet(struct interface *ifp, uint8_t *data, size_t len)
 {
@@ -184,6 +165,18 @@ arp_packet(struct interface *ifp, uint8_t *data, size_t len)
        }
 }
 
+void
+arp_close(struct interface *ifp)
+{
+       struct iarp_state *state;
+
+       if ((state = ARP_STATE(ifp)) != NULL && state->fd != -1) {
+               eloop_event_delete(ifp->ctx->eloop, state->fd);
+               if_closeraw(ifp, state->fd);
+               state->fd = -1;
+       }
+}
+
 static void
 arp_read(void *arg)
 {
@@ -215,6 +208,8 @@ arp_open(struct interface *ifp)
 {
        struct iarp_state *state;
 
+printf("ARP OPENED!!!\n");
+
        state = ARP_STATE(ifp);
        if (state->fd == -1) {
                state->fd = if_openraw(ifp, ETHERTYPE_ARP);
@@ -228,6 +223,59 @@ arp_open(struct interface *ifp)
        return state->fd;
 }
 
+static void
+arp_probed(void *arg)
+{
+       struct arp_state *astate = arg;
+
+       astate->probed_cb(astate);
+}
+
+static void
+arp_probe1(void *arg)
+{
+       struct arp_state *astate = arg;
+       struct interface *ifp = astate->iface;
+       struct timespec tv;
+
+       if (++astate->probes < PROBE_NUM) {
+               tv.tv_sec = PROBE_MIN;
+               tv.tv_nsec = (suseconds_t)arc4random_uniform(
+                   (PROBE_MAX - PROBE_MIN) * NSEC_PER_SEC);
+               timespecnorm(&tv);
+               eloop_timeout_add_tv(ifp->ctx->eloop, &tv, arp_probe1, astate);
+       } else {
+               tv.tv_sec = ANNOUNCE_WAIT;
+               tv.tv_nsec = 0;
+               eloop_timeout_add_tv(ifp->ctx->eloop, &tv, arp_probed, astate);
+       }
+       logger(ifp->ctx, LOG_DEBUG,
+           "%s: ARP probing %s (%d of %d), next in %0.1f seconds",
+           ifp->name, inet_ntoa(astate->addr),
+           astate->probes ? astate->probes : PROBE_NUM, PROBE_NUM,
+           timespec_to_double(&tv));
+       if (arp_request(ifp, 0, astate->addr.s_addr) == -1)
+               logger(ifp->ctx, LOG_ERR, "send_arp: %m");
+}
+
+void
+arp_probe(struct arp_state *astate)
+{
+
+       if (arp_open(astate->iface) == -1) {
+               logger(astate->iface->ctx, LOG_ERR,
+                   "%s: %s: %m", __func__, astate->iface->name);
+               return;
+       }
+       astate->probes = 0;
+       logger(astate->iface->ctx, LOG_DEBUG, "%s: probing for %s",
+           astate->iface->name, inet_ntoa(astate->addr));
+       arp_probe1(astate);
+}
+#else  /* !ARP */
+#define arp_close(ifp) {}
+#endif /* ARP */
+
 static void
 arp_announced(void *arg)
 {
@@ -238,8 +286,7 @@ arp_announced(void *arg)
                return;
        }
 
-       /* As there is no announced callback, free the ARP state. */
-       arp_free(astate);
+       /* Keep the ARP state open to handle ongoing ACD. */
 }
 
 static void
@@ -248,6 +295,11 @@ arp_announce1(void *arg)
        struct arp_state *astate = arg;
        struct interface *ifp = astate->iface;
 
+#ifdef KERNEL_RFC5227
+       /* We rely on the kernel announcing correctly.
+        * As the timings are not random we can callback safely. */
+       astate->claims++;
+#else
        if (++astate->claims < ANNOUNCE_NUM)
                logger(ifp->ctx, LOG_DEBUG,
                    "%s: ARP announcing %s (%d of %d), "
@@ -261,6 +313,7 @@ arp_announce1(void *arg)
                    astate->claims, ANNOUNCE_NUM);
        if (arp_request(ifp, astate->addr.s_addr, astate->addr.s_addr) == -1)
                logger(ifp->ctx, LOG_ERR, "send_arp: %m");
+#endif
        eloop_timeout_add_sec(ifp->ctx->eloop, ANNOUNCE_WAIT,
            astate->claims < ANNOUNCE_NUM ? arp_announce1 : arp_announced,
            astate);
@@ -270,63 +323,36 @@ void
 arp_announce(struct arp_state *astate)
 {
 
+#ifndef KERNEL_RFC5227
        if (arp_open(astate->iface) == -1) {
                logger(astate->iface->ctx, LOG_ERR,
                    "%s: %s: %m", __func__, astate->iface->name);
                return;
        }
+#endif
+
        astate->claims = 0;
        arp_announce1(astate);
 }
 
-static void
-arp_probed(void *arg)
-{
-       struct arp_state *astate = arg;
-
-       astate->probed_cb(astate);
-}
-
-static void
-arp_probe1(void *arg)
-{
-       struct arp_state *astate = arg;
-       struct interface *ifp = astate->iface;
-       struct timespec tv;
-
-       if (++astate->probes < PROBE_NUM) {
-               tv.tv_sec = PROBE_MIN;
-               tv.tv_nsec = (suseconds_t)arc4random_uniform(
-                   (PROBE_MAX - PROBE_MIN) * NSEC_PER_SEC);
-               timespecnorm(&tv);
-               eloop_timeout_add_tv(ifp->ctx->eloop, &tv, arp_probe1, astate);
-       } else {
-               tv.tv_sec = ANNOUNCE_WAIT;
-               tv.tv_nsec = 0;
-               eloop_timeout_add_tv(ifp->ctx->eloop, &tv, arp_probed, astate);
-       }
-       logger(ifp->ctx, LOG_DEBUG,
-           "%s: ARP probing %s (%d of %d), next in %0.1f seconds",
-           ifp->name, inet_ntoa(astate->addr),
-           astate->probes ? astate->probes : PROBE_NUM, PROBE_NUM,
-           timespec_to_double(&tv));
-       if (arp_request(ifp, 0, astate->addr.s_addr) == -1)
-               logger(ifp->ctx, LOG_ERR, "send_arp: %m");
-}
-
 void
-arp_probe(struct arp_state *astate)
+arp_report_conflicted(const struct arp_state *astate,
+    const struct arp_msg *amsg)
 {
 
-       if (arp_open(astate->iface) == -1) {
+       if (amsg != NULL) {
+               char buf[HWADDR_LEN * 3];
+
                logger(astate->iface->ctx, LOG_ERR,
-                   "%s: %s: %m", __func__, astate->iface->name);
-               return;
-       }
-       astate->probes = 0;
-       logger(astate->iface->ctx, LOG_DEBUG, "%s: probing for %s",
-           astate->iface->name, inet_ntoa(astate->addr));
-       arp_probe1(astate);
+                   "%s: hardware address %s claims %s",
+                   astate->iface->name,
+                   hwaddr_ntoa(amsg->sha, astate->iface->hwlen,
+                   buf, sizeof(buf)),
+                   inet_ntoa(astate->failed));
+       } else
+               logger(astate->iface->ctx, LOG_ERR,
+                   "%s: DAD detected %s",
+                   astate->iface->name, inet_ntoa(astate->failed));
 }
 
 struct arp_state *
@@ -403,9 +429,8 @@ arp_free(struct arp_state *astate)
        free(astate);
 
        /* If there are no more ARP states, close the socket. */
-       if (state->fd != -1 && TAILQ_FIRST(&state->arp_states) == NULL) {
-               eloop_event_delete(ifp->ctx->eloop, state->fd);
-               if_closeraw(ifp, state->fd);
+       if (TAILQ_FIRST(&state->arp_states) == NULL) {
+               arp_close(ifp);
                free(state);
                ifp->if_data[IF_DATA_ARP] = NULL;
        }
@@ -434,10 +459,11 @@ arp_free_but(struct arp_state *astate)
 }
 
 void
-arp_close(struct interface *ifp)
+arp_drop(struct interface *ifp)
 {
 
        arp_free_but1(ifp, NULL);
+       arp_close(ifp);
 }
 
 void
diff --git a/arp.h b/arp.h
index b844e49870bacbddaafae8abf12172d1e94a863e..7e251ec022e902256acfc6350fb6599159295e92 100644 (file)
--- a/arp.h
+++ b/arp.h
 #include "dhcpcd.h"
 #include "if.h"
 
+#ifdef IN_IFF_DUPLICATED
+/* NetBSD gained RFC 5227 support in the kernel.
+ * This means dhcpcd doesn't need ARP except for ARPing support. */
+#if defined(__NetBSD_Version__) && __NetBSD_Version__ >= 799003900
+#define KERNEL_RFC5227
+#endif
+#endif
+
 struct arp_msg {
        uint16_t op;
        unsigned char sha[HWADDR_LEN];
@@ -77,21 +85,25 @@ struct iarp_state {
 #define ARP_CSTATE(ifp)                                                               \
        ((const struct iarp_state *)(ifp)->if_data[IF_DATA_ARP])
 
-#ifdef INET
+#if defined(ARP) && (!defined(KERNEL_RFC5227) || defined(ARPING))
 int arp_open(struct interface *);
 ssize_t arp_request(const struct interface *, in_addr_t, in_addr_t);
-void arp_report_conflicted(const struct arp_state *, const struct arp_msg *);
-void arp_announce(struct arp_state *);
 void arp_probe(struct arp_state *);
+void arp_close(struct interface *);
+#endif
+
+#ifdef ARP
+void arp_report_conflicted(const struct arp_state *, const struct arp_msg *);
 struct arp_state *arp_new(struct interface *, const struct in_addr *);
+struct arp_state *arp_find(struct interface *, const struct in_addr *);
+void arp_announce(struct arp_state *);
 void arp_cancel(struct arp_state *);
 void arp_free(struct arp_state *);
 void arp_free_but(struct arp_state *);
-struct arp_state *arp_find(struct interface *, const struct in_addr *);
-void arp_close(struct interface *);
+void arp_drop(struct interface *);
 
 void arp_handleifa(int, struct ipv4_addr *);
 #else
-#define arp_close(a) {}
+#define arp_drop(a) {}
 #endif
 #endif
index b47f91e13bcbfab13b4a8b4ca4e33842b3f91847..602560e2027114d403d345f63aff546cbc01c2d7 100755 (executable)
--- a/configure
+++ b/configure
@@ -7,6 +7,8 @@ exec 3>config.log
 # Ensure that we do not inherit these from env
 HOOKSET=false
 INET=
+ARP=
+ARPING=
 IPV4LL=
 INET6=
 ARC4RANDOM=
@@ -44,11 +46,15 @@ for x do
        --enable-fork) FORK=yes;;
        --disable-static) STATIC=no;;
        --enable-static) STATIC=yes;;
-       --disable-ipv4|--disable-inet) INET=no;;
+       --disable-ipv4|--disable-inet) INET=no; ARP=no; ARPING=no; IPV4LL=no;;
        --enable-ipv4|--enable-inet) INET=yes;;
+       --disable-arp) ARP=no; ARPING=no; IPV4LL=no;;
+       --enable-arp) ARP=yes; INET=yes;;
+       --disable-arping) ARPING=no;;
+       --enable-arping) ARPING=yes; ARP=yes; INET=yes;;
        --disable-ipv4ll) IPV4LL=no;;
-       --enable-ipv4ll) IPV4LL=yes; INET=yes;;
-       --disable-ipv6|--disable-inet6) INET6=no;;
+       --enable-ipv4ll) IPV4LL=yes; ARP=yes; INET=yes;;
+       --disable-ipv6|--disable-inet6) INET6=no; DHCP6=no;;
        --enable-ipv6|--enable-inet6) INET6=yes;;
        --disable-dhcp6) DHCP6=no;;
        --enable-dhcp6) DHCP6=yes;;
@@ -444,7 +450,16 @@ esac
 if [ -z "$INET" -o "$INET" = yes ]; then
        echo "Enabling INET support"
        echo "CPPFLAGS+=        -DINET" >>$CONFIG_MK
-       echo "DHCPCD_SRCS+=     arp.c dhcp.c ipv4.c" >>$CONFIG_MK
+       echo "DHCPCD_SRCS+=     dhcp.c ipv4.c" >>$CONFIG_MK
+       if [ -z "$ARP" -o "$ARP" = yes ]; then
+               echo "Enabling ARP support"
+               echo "CPPFLAGS+=        -DARP" >>$CONFIG_MK
+               echo "DHCPCD_SRCS+=     arp.c" >>$CONFIG_MK
+       fi
+       if [ -z "$ARPING" -o "$ARPING" = yes ]; then
+               echo "Enabling ARPing support"
+               echo "CPPFLAGS+=        -DARPING" >>$CONFIG_MK
+       fi
        if [ -z "$IPV4LL" -o "$IPV4LL" = yes ]; then
                echo "Enabling IPv4LL support"
                echo "CPPFLAGS+=        -DIPV4LL" >>$CONFIG_MK
diff --git a/dhcp.c b/dhcp.c
index c1d4282a82cea3874f8be9c3c88c46c0197adc10..fedd1d0cbb8dd26e78d421f1ba0fc74bcf2065c9 100644 (file)
--- a/dhcp.c
+++ b/dhcp.c
@@ -123,7 +123,9 @@ struct udp_bootp_packet
 };
 
 static int dhcp_open(struct interface *);
+#ifdef ARP
 static void dhcp_arp_conflicted(struct arp_state *, const struct arp_msg *);
+#endif
 
 void
 dhcp_printoptions(const struct dhcpcd_ctx *ctx,
@@ -1880,20 +1882,26 @@ static int
 dhcp_leaseextend(struct interface *ifp)
 {
 
+#ifdef ARP
        if (ifp->options->options & DHCPCD_ARP) {
+               const struct dhcp_state *state;
                struct arp_state *astate;
 
-               if ((astate = arp_new(ifp, NULL)) == NULL)
+               state = D_CSTATE(ifp);
+               if ((astate = arp_new(ifp, &state->lease.addr)) == NULL)
                        return -1;
+               astate->conflicted_cb = dhcp_arp_conflicted;
 
+#ifndef KERNEL_RFC5227
                if (arp_open(ifp) == -1)
                        return -1;
+#endif
 
-               astate->conflicted_cb = dhcp_arp_conflicted;
                logger(ifp->ctx, LOG_WARNING,
                    "%s: extending lease until DaD failure or DHCP", ifp->name);
                return 0;
        }
+#endif
 
        logger(ifp->ctx, LOG_WARNING, "%s: extending lease", ifp->name);
        return 0;
@@ -1926,12 +1934,14 @@ dhcp_expire(void *arg)
        dhcp_expire1(ifp);
 }
 
+#ifdef ARP
 static void
 dhcp_decline(struct interface *ifp)
 {
 
        send_message(ifp, DHCP_DECLINE, NULL);
 }
+#endif
 
 static void
 dhcp_startrenew(void *arg)
@@ -1987,14 +1997,18 @@ dhcp_rebind(void *arg)
        send_rebind(ifp);
 }
 
+#ifdef ARP
 static void
 dhcp_arp_probed(struct arp_state *astate)
 {
+       struct interface *ifp;
        struct dhcp_state *state;
        struct if_options *ifo;
 
-       state = D_STATE(astate->iface);
-       ifo = astate->iface->options;
+       ifp = astate->iface;
+       state = D_STATE(ifp);
+       ifo = ifp->options;
+#ifdef ARPING
        if (state->arping_index < ifo->arping_len) {
                /* We didn't find a profile for this
                 * address or hwaddr, so move to the next
@@ -2003,19 +2017,27 @@ dhcp_arp_probed(struct arp_state *astate)
                        astate->addr.s_addr =
                            ifo->arping[state->arping_index - 1];
                        arp_probe(astate);
+                       return;
                }
-               dhcpcd_startinterface(astate->iface);
+               arp_free(astate);
+#ifdef KERNEL_RFC5227
+               /* As arping is finished, close the ARP socket.
+                * The kernel will handle ACD from here. */
+               arp_close(ifp);
+#endif
+               dhcpcd_startinterface(ifp);
                return;
        }
+#endif
 
        /* Already bound so DAD has worked */
        if (state->state == DHS_BOUND)
                return;
 
-       logger(astate->iface->ctx, LOG_DEBUG, "%s: DAD completed for %s",
-           astate->iface->name, inet_ntoa(astate->addr));
+       logger(ifp->ctx, LOG_DEBUG, "%s: DAD completed for %s",
+           ifp->name, inet_ntoa(astate->addr));
        if (state->state != DHS_INFORM)
-               dhcp_bind(astate->iface);
+               dhcp_bind(ifp);
 #ifndef IN_IFF_TENTATIVE
        else {
                struct bootp *bootp;
@@ -2025,8 +2047,7 @@ dhcp_arp_probed(struct arp_state *astate)
                len = state->new_len;
                state->new = state->offer;
                state->new_len = state->offer_len;
-               get_lease(astate->iface, &state->lease,
-                   state->new, state->new_len);
+               get_lease(ifp, &state->lease, state->new, state->new_len);
                ipv4_applyaddr(astate->iface);
                state->new = bootp;
                state->new_len = len;
@@ -2034,14 +2055,14 @@ dhcp_arp_probed(struct arp_state *astate)
 #endif
 
        /* If we forked, stop here. */
-       if (astate->iface->ctx->options & DHCPCD_FORKED)
+       if (ifp->ctx->options & DHCPCD_FORKED)
                return;
 
        /* Stop IPv4LL now we have a working DHCP address */
-       ipv4ll_drop(astate->iface);
+       ipv4ll_drop(ifp);
 
        if (ifo->options & DHCPCD_INFORM)
-               dhcp_inform(astate->iface);
+               dhcp_inform(ifp);
 }
 
 static void
@@ -2049,11 +2070,15 @@ dhcp_arp_conflicted(struct arp_state *astate, const struct arp_msg *amsg)
 {
        struct interface *ifp;
        struct dhcp_state *state;
+#ifdef ARPING
        struct if_options *ifo;
+#endif
 
        ifp = astate->iface;
-       ifo = ifp->options;
        state = D_STATE(ifp);
+
+#ifdef ARPING
+       ifo = ifp->options;
        if (state->arping_index &&
            state->arping_index <= ifo->arping_len &&
            amsg &&
@@ -2078,10 +2103,16 @@ dhcp_arp_conflicted(struct arp_state *astate, const struct arp_msg *amsg)
                }
                dhcp_close(ifp);
                arp_free(astate);
+#ifdef KERNEL_RFC5227
+               /* As arping is finished, close the ARP socket.
+                * The kernel will handle ACD from here. */
+               arp_close(ifp);
+#endif
                eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
                dhcpcd_startinterface(ifp);
                return;
        }
+#endif
 
        /* RFC 2131 3.1.5, Client-server interaction
         * NULL amsg means IN_IFF_DUPLICATED */
@@ -2131,6 +2162,7 @@ dhcp_arp_conflicted(struct arp_state *astate, const struct arp_msg *amsg)
                return;
        }
 }
+#endif
 
 void
 dhcp_bind(struct interface *ifp)
@@ -2305,6 +2337,7 @@ dhcp_message_new(struct bootp **bootp,
        return sizeof(**bootp);
 }
 
+#ifdef ARP
 static int
 dhcp_arp_address(struct interface *ifp)
 {
@@ -2322,13 +2355,13 @@ dhcp_arp_address(struct interface *ifp)
        /* If the interface already has the address configured
         * then we can't ARP for duplicate detection. */
        ia = ipv4_findaddr(ifp->ctx, &addr);
+       if ((astate = arp_new(ifp, &addr)) == NULL)
+               return 0;
+       astate->probed_cb = dhcp_arp_probed;
+       astate->conflicted_cb = dhcp_arp_conflicted;
 
 #ifdef IN_IFF_TENTATIVE
        if (ia == NULL || ia->addr_flags & IN_IFF_NOTUSEABLE) {
-               if ((astate = arp_new(ifp, &addr)) != NULL) {
-                       astate->probed_cb = dhcp_arp_probed;
-                       astate->conflicted_cb = dhcp_arp_conflicted;
-               }
                if (ia == NULL) {
                        struct dhcp_lease l;
 
@@ -2347,12 +2380,8 @@ dhcp_arp_address(struct interface *ifp)
                get_lease(ifp, &l, state->offer, state->offer_len);
                logger(ifp->ctx, LOG_INFO, "%s: probing address %s/%d",
                    ifp->name, inet_ntoa(l.addr), inet_ntocidr(l.mask));
-               if ((astate = arp_new(ifp, &addr)) != NULL) {
-                       astate->probed_cb = dhcp_arp_probed;
-                       astate->conflicted_cb = dhcp_arp_conflicted;
-                       /* We need to handle DAD. */
-                       arp_probe(astate);
-               }
+               /* We need to handle DAD. */
+               arp_probe(astate);
                return 0;
        }
 #endif
@@ -2367,6 +2396,7 @@ dhcp_arp_bind(struct interface *ifp)
        if (dhcp_arp_address(ifp) == 1)
                dhcp_bind(ifp);
 }
+#endif
 
 static void
 dhcp_static(struct interface *ifp)
@@ -2395,7 +2425,11 @@ dhcp_static(struct interface *ifp)
            ia ? &ia->addr : &ifo->req_addr,
            ia ? &ia->mask : &ifo->req_mask);
        if (state->offer_len)
+#ifdef ARP
                dhcp_arp_bind(ifp);
+#else
+               dhcp_bind(ifp);
+#endif
 }
 
 void
@@ -2440,8 +2474,10 @@ dhcp_inform(struct interface *ifp)
                                ipv4_deladdr(ia, 1);
                        state->offer_len = dhcp_message_new(&state->offer,
                            &ifo->req_addr, &ifo->req_mask);
+#ifdef ARP
                        if (dhcp_arp_address(ifp) == 0)
                                return;
+#endif
                        ia = ipv4_iffindaddr(ifp,
                            &ifo->req_addr, &ifo->req_mask);
                        assert(ia != NULL);
@@ -2925,7 +2961,7 @@ dhcp_handledhcp(struct interface *ifp, struct bootp *bootp, size_t bootp_len,
                        case 0:
                                LOGDHCP(LOG_WARNING, "IPv4LL disabled from");
                                ipv4ll_drop(ifp);
-                               arp_close(ifp);
+                               arp_drop(ifp);
                                break;
                        case 1:
                                LOGDHCP(LOG_WARNING, "IPv4LL enabled from");
@@ -3084,7 +3120,11 @@ rapidcommit:
        lease->frominfo = 0;
        eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
 
+#ifdef ARP
        dhcp_arp_bind(ifp);
+#else
+       dhcp_bind(ifp);
+#endif
 }
 
 static void *
@@ -3231,7 +3271,6 @@ dhcp_readpacket(void *arg)
                        logger(ifp->ctx, LOG_ERR,
                            "%s: dhcp if_readrawpacket: %m", ifp->name);
                        dhcp_close(ifp);
-                       arp_close(ifp);
                        return;
                }
                dhcp_handlepacket(ifp, buf, (size_t)bytes, flags);
@@ -3314,7 +3353,7 @@ dhcp_free(struct interface *ifp)
        struct dhcpcd_ctx *ctx;
 
        dhcp_close(ifp);
-       arp_close(ifp);
+       arp_drop(ifp);
        if (state) {
                free(state->old);
                free(state->new);
@@ -3467,6 +3506,7 @@ dhcp_start1(void *arg)
        state->offer = NULL;
        state->offer_len = 0;
 
+#ifdef ARPING
        if (state->arping_index < ifo->arping_len) {
                struct arp_state *astate;
 
@@ -3478,6 +3518,7 @@ dhcp_start1(void *arg)
                }
                return;
        }
+#endif
 
        if (ifo->options & DHCPCD_STATIC) {
                dhcp_static(ifp);
diff --git a/dhcp.h b/dhcp.h
index d62ead9d6a7ae4038ebf00429937ceeb36c6e10f..a21eea30ae26bb70ae5ccc52a37ee891a7e2a9bb 100644 (file)
--- a/dhcp.h
+++ b/dhcp.h
@@ -208,7 +208,9 @@ struct dhcp_state {
        struct timespec started;
        unsigned char *clientid;
        struct authstate auth;
+#ifdef ARPING
        size_t arping_index;
+#endif
 };
 
 #define D_STATE(ifp)                                                          \
index 8b8f1220e021a7fecc63ed9ed179264487c15b9b..33dfe05ee84dc279014e4a88732f02ea3a29f71e 100644 (file)
--- a/dhcpcd.c
+++ b/dhcpcd.c
@@ -370,7 +370,7 @@ dhcpcd_drop(struct interface *ifp, int stop)
        ipv6_drop(ifp);
        ipv4ll_drop(ifp);
        dhcp_drop(ifp, stop ? "STOP" : "EXPIRE");
-       arp_close(ifp);
+       arp_drop(ifp);
 }
 
 static void
@@ -722,7 +722,7 @@ dhcpcd_handlecarrier(struct dhcpcd_ctx *ctx, int carrier, unsigned int flags,
                        ifp->carrier = LINK_DOWN;
                        script_runreason(ifp, "NOCARRIER");
 #ifdef NOCARRIER_PRESERVE_IP
-                       arp_close(ifp);
+                       arp_drop(ifp);
                        dhcp_abort(ifp);
                        if_sortinterfaces(ctx);
                        ipv4_preferanother(ifp);
@@ -1446,6 +1446,12 @@ main(int argc, char **argv)
 #ifdef INET
                        " INET"
 #endif
+#ifdef ARP
+                       " ARP"
+#endif
+#ifdef ARPING
+                       " ARPing"
+#endif
 #ifdef IPV4LL
                        " IPv4LL"
 #endif
diff --git a/ipv4.c b/ipv4.c
index 837fb8864377f9b578cc08fc09d6d984e98ceb86..876ca0afc185c97b21f5f2040e9b12b19c4c2403 100644 (file)
--- a/ipv4.c
+++ b/ipv4.c
@@ -890,7 +890,11 @@ ipv4_deladdr(struct ipv4_addr *addr, int keeparp)
        int r;
        struct ipv4_state *state;
        struct ipv4_addr *ap;
+#ifdef ARP
        struct arp_state *astate;
+#else
+       UNUSED(keeparp);
+#endif
 
        logger(addr->iface->ctx, LOG_DEBUG,
            "%s: deleting IP address %s", addr->iface->name, addr->saddr);
@@ -902,8 +906,10 @@ ipv4_deladdr(struct ipv4_addr *addr, int keeparp)
                logger(addr->iface->ctx, LOG_ERR, "%s: %s: %m",
                    addr->iface->name, __func__);
 
+#ifdef ARP
        if (!keeparp && (astate = arp_find(addr->iface, &addr->addr)) != NULL)
                arp_free(astate);
+#endif
 
        state = IPV4_STATE(addr->iface);
        TAILQ_FOREACH(ap, &state->addrs, next) {
@@ -1237,7 +1243,7 @@ ipv4_applyaddr(void *arg)
                    ifp->name);
                return;
        }
-#ifdef IN_IFF_NOTUSEABLE
+#if defined(ARP) && defined(IN_IFF_NOTUSEABLE)
        if (ia->addr_flags & IN_IFF_NOTUSEABLE)
                return;
 #endif
@@ -1256,13 +1262,17 @@ ipv4_applyaddr(void *arg)
         * notification right now via our link socket. */
        if_initrt(ifp->ctx);
        ipv4_buildroutes(ifp->ctx);
+
+#ifdef ARP
        /* Announce the address */
        if (ifo->options & DHCPCD_ARP) {
                struct arp_state *astate;
 
-               if ((astate = arp_new(ifp, &state->addr->addr)) != NULL)
+               if ((astate = arp_find(ifp, &state->addr->addr)) != NULL)
                        arp_announce(astate);
        }
+#endif
+
        if (state->state == DHS_BOUND) {
                script_runreason(ifp, state->reason);
                dhcpcd_daemonise(ifp->ctx);
@@ -1336,7 +1346,9 @@ ipv4_handleifa(struct dhcpcd_ctx *ctx,
        }
 
        if (addr->s_addr != INADDR_ANY && addr->s_addr != INADDR_BROADCAST) {
+#ifdef ARP
                arp_handleifa(cmd, ia);
+#endif
                dhcp_handleifa(cmd, ia);
        }
 
index 398a692a5255f89c473666bf3057729af474504e..77e678aa5f8466ba1af254267a534c3c22feda7b 100644 (file)
--- a/ipv4ll.c
+++ b/ipv4ll.c
@@ -268,6 +268,11 @@ ipv4ll_conflicted(struct arp_state *astate, const struct arp_msg *amsg)
        if (state->addr != NULL &&
            astate->failed.s_addr == state->addr->addr.s_addr)
        {
+#ifdef KERNEL_RFC5227
+               logger(ifp->ctx, LOG_WARNING,
+                   "%s: IPv4LL defence failed for %s",
+                   ifp->name, state->addr->saddr);
+#else
                struct timespec now, defend;
 
                /* RFC 3927 Section 2.5 says a defence should
@@ -296,7 +301,7 @@ ipv4ll_conflicted(struct arp_state *astate, const struct arp_msg *amsg)
                        state->defend = now;
                        return;
                }
-
+#endif
                ipv4_deladdr(state->addr, 1);
                state->down = 1;
                state->addr = NULL;