]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Move ARP state out of DHCP.
authorRoy Marples <roy@marples.name>
Fri, 19 Jun 2015 14:01:25 +0000 (14:01 +0000)
committerRoy Marples <roy@marples.name>
Fri, 19 Jun 2015 14:01:25 +0000 (14:01 +0000)
arp.c
arp.h
dhcp.c
dhcp.h
dhcpcd.h
if-bsd.c
if-linux.c
ipv4.c
ipv4.h

diff --git a/arp.c b/arp.c
index 46b6789d4043819da9d542fb292579f3f1198981..70dd324a02f6178045bf973148ef2ba82faf230a 100644 (file)
--- a/arp.c
+++ b/arp.c
@@ -122,12 +122,12 @@ arp_packet(void *arg)
        struct arphdr ar;
        struct arp_msg arm;
        ssize_t bytes;
-       struct dhcp_state *state;
+       struct iarp_state *state;
        struct arp_state *astate, *astaten;
        unsigned char *hw_s, *hw_t;
        int flags;
 
-       state = D_STATE(ifp);
+       state = ARP_STATE(ifp);
        flags = 0;
        while (!(flags & RAW_EOF)) {
                bytes = if_readrawpacket(ifp, ETHERTYPE_ARP,
@@ -186,17 +186,17 @@ arp_packet(void *arg)
 static void
 arp_open(struct interface *ifp)
 {
-       struct dhcp_state *state;
+       struct iarp_state *state;
 
-       state = D_STATE(ifp);
-       if (state->arp_fd == -1) {
-               state->arp_fd = if_openrawsocket(ifp, ETHERTYPE_ARP);
-               if (state->arp_fd == -1) {
+       state = ARP_STATE(ifp);
+       if (state->fd == -1) {
+               state->fd = if_openrawsocket(ifp, ETHERTYPE_ARP);
+               if (state->fd == -1) {
                        logger(ifp->ctx, LOG_ERR, "%s: %s: %m",
                            __func__, ifp->name);
                        return;
                }
-               eloop_event_add(ifp->ctx->eloop, state->arp_fd,
+               eloop_event_add(ifp->ctx->eloop, state->fd,
                    arp_packet, ifp, NULL, NULL);
        }
 }
@@ -297,10 +297,10 @@ arp_probe(struct arp_state *astate)
 struct arp_state *
 arp_find(struct interface *ifp, const struct in_addr *addr)
 {
+       struct iarp_state *state;
        struct arp_state *astate;
-       struct dhcp_state *state;
 
-       if ((state = D_STATE(ifp)) == NULL)
+       if ((state = ARP_STATE(ifp)) == NULL)
                goto out;
        TAILQ_FOREACH(astate, &state->arp_states, next) {
                if (astate->addr.s_addr == addr->s_addr && astate->iface == ifp)
@@ -314,20 +314,31 @@ out:
 struct arp_state *
 arp_new(struct interface *ifp, const struct in_addr *addr)
 {
+       struct iarp_state *state;
        struct arp_state *astate;
-       struct dhcp_state *state;
 
-       if (addr && (astate = arp_find(ifp, addr)))
-               return astate;
+       if ((state = ARP_STATE(ifp)) == NULL) {
+               ifp->if_data[IF_DATA_ARP] = malloc(sizeof(*state));
+               state = ARP_STATE(ifp);
+               if (state == NULL) {
+                       logger(ifp->ctx, LOG_ERR, "%s: %m", __func__);
+                       return NULL;
+               }
+               state->fd = -1;
+               TAILQ_INIT(&state->arp_states);
+       } else {
+               if (addr && (astate = arp_find(ifp, addr)))
+                       return astate;
+       }
 
        if ((astate = calloc(1, sizeof(*astate))) == NULL) {
                logger(ifp->ctx, LOG_ERR, "%s: %s: %m", ifp->name, __func__);
                return NULL;
        }
-       state = D_STATE(ifp);
        astate->iface = ifp;
        if (addr)
                astate->addr = *addr;
+       state = ARP_STATE(ifp);
        TAILQ_INSERT_TAIL(&state->arp_states, astate, next);
        return astate;
 }
@@ -342,21 +353,25 @@ arp_cancel(struct arp_state *astate)
 void
 arp_free(struct arp_state *astate)
 {
-       struct dhcp_state *state;
 
-       if (astate) {
-               eloop_timeout_delete(astate->iface->ctx->eloop, NULL, astate);
-               state = D_STATE(astate->iface);
+       if (astate != NULL) {
+               struct interface *ifp;
+               struct iarp_state *state;
+
+               ifp = astate->iface;
+               eloop_timeout_delete(ifp->ctx->eloop, NULL, astate);
+               state = ARP_STATE(ifp);
                TAILQ_REMOVE(&state->arp_states, astate, next);
                free(astate);
 
                /* If there are no more ARP states, close the socket. */
-               if (state->arp_fd != -1 &&
+               if (state->fd != -1 &&
                    TAILQ_FIRST(&state->arp_states) == NULL)
                {
-                       eloop_event_delete(ifp->ctx->eloop, state->arp_fd);
-                       close(state->arp_fd);
-                       state->arp_fd = -1;
+                       eloop_event_delete(ifp->ctx->eloop, state->fd);
+                       close(state->fd);
+                       free(state);
+                       ifp->if_data[IF_DATA_ARP] = NULL;
                }
        }
 }
@@ -364,10 +379,10 @@ arp_free(struct arp_state *astate)
 void
 arp_free_but(struct arp_state *astate)
 {
+       struct iarp_state *state;
        struct arp_state *p, *n;
-       struct dhcp_state *state;
 
-       state = D_STATE(astate->iface);
+       state = ARP_STATE(astate->iface);
        TAILQ_FOREACH_SAFE(p, &state->arp_states, next, n) {
                if (p != astate)
                        arp_free(p);
@@ -377,24 +392,16 @@ arp_free_but(struct arp_state *astate)
 void
 arp_close(struct interface *ifp)
 {
-       struct dhcp_state *state = D_STATE(ifp);
+       struct iarp_state *state;
        struct arp_state *astate;
 
-       if (state == NULL)
-               return;
-
-       if (state->arp_fd != -1) {
-               eloop_event_delete(ifp->ctx->eloop, state->arp_fd);
-               close(state->arp_fd);
-               state->arp_fd = -1;
-       }
-
-       while ((astate = TAILQ_FIRST(&state->arp_states))) {
-#ifndef __clang_analyzer__
-               /* clang guard needed for a more compex variant on this bug:
-                * http://llvm.org/bugs/show_bug.cgi?id=18222 */
+       /* Freeing the last state will also free the main state,
+        * so test for both. */
+       for (;;) {
+               if ((state = ARP_STATE(ifp)) == NULL ||
+                   (astate = TAILQ_FIRST(&state->arp_states)) == NULL)
+                       break;
                arp_free(astate);
-#endif
        }
 }
 
@@ -403,10 +410,10 @@ arp_handleifa(int cmd, struct interface *ifp, const struct in_addr *addr,
     int flags)
 {
 #ifdef IN_IFF_DUPLICATED
-       struct dhcp_state *state = D_STATE(ifp);
+       struct iarp_state *state;
        struct arp_state *astate, *asn;
 
-       if (cmd != RTM_NEWADDR || (state = D_STATE(ifp)) == NULL)
+       if (cmd != RTM_NEWADDR || (state = ARP_STATE(ifp)) == NULL)
                return;
 
        TAILQ_FOREACH_SAFE(astate, &state->arp_states, next, asn) {
diff --git a/arp.h b/arp.h
index 5e513b29dee22e4c7511646bd6f67f92bdbc31b0..ce0e91fdce390993158a24dd7dabb9f9e3519ecb 100644 (file)
--- a/arp.h
+++ b/arp.h
@@ -65,6 +65,16 @@ struct arp_state {
 };
 TAILQ_HEAD(arp_statehead, arp_state);
 
+struct iarp_state {
+       int fd;
+       struct arp_statehead arp_states;
+};
+
+#define ARP_STATE(ifp)                                                        \
+       ((struct iarp_state *)(ifp)->if_data[IF_DATA_ARP])
+#define ARP_CSTATE(ifp)                                                               \
+       ((const struct iarp_state *)(ifp)->if_data[IF_DATA_ARP])
+
 #ifdef INET
 void arp_report_conflicted(const struct arp_state *, const struct arp_msg *);
 void arp_announce(struct arp_state *);
diff --git a/dhcp.c b/dhcp.c
index f3c5610d8b6faca55f64dccff7eec902b02b8c99..04c02998ec51025281ff2e2493b69781c108fd57 100644 (file)
--- a/dhcp.c
+++ b/dhcp.c
@@ -3023,8 +3023,7 @@ dhcp_dump(struct interface *ifp)
        ifp->if_data[IF_DATA_DHCP] = state = calloc(1, sizeof(*state));
        if (state == NULL)
                goto eexit;
-       state->raw_fd = state->arp_fd = -1;
-       TAILQ_INIT(&state->arp_states);
+       state->raw_fd = -1;
        dhcp_set_leasefile(state->leasefile, sizeof(state->leasefile),
            AF_INET, ifp);
        state->new = read_lease(ifp);
@@ -3097,8 +3096,7 @@ dhcp_init(struct interface *ifp)
                if (state == NULL)
                        return -1;
                /* 0 is a valid fd, so init to -1 */
-               state->raw_fd = state->arp_fd = -1;
-               TAILQ_INIT(&state->arp_states);
+               state->raw_fd = -1;
 
                /* Now is a good time to find IPv4 routes */
                if_initrt(ifp);
diff --git a/dhcp.h b/dhcp.h
index 1ac6fa1aa3b2373521cc2b4a9a12a601adca10b4..cd5c12aca25d0a6d8a367e91247b6c2f6c5a2a33 100644 (file)
--- a/dhcp.h
+++ b/dhcp.h
@@ -213,7 +213,6 @@ struct dhcp_state {
        int socket;
 
        int raw_fd;
-       int arp_fd;
        size_t buffer_size, buffer_len, buffer_pos;
        unsigned char *buffer;
 
@@ -224,12 +223,8 @@ struct dhcp_state {
 
        char leasefile[sizeof(LEASEFILE) + IF_NAMESIZE + (IF_SSIDSIZE * 4)];
        time_t start_uptime;
-
        unsigned char *clientid;
-
        struct authstate auth;
-       struct arp_statehead arp_states;
-
        size_t arping_index;
 };
 
index f79c01d3d499b9be82ea8f91c7bf7d360a428233..31b6959ec04da7b82453a4d7dd43a064962883ed 100644 (file)
--- a/dhcpcd.h
+++ b/dhcpcd.h
 #define LINK_DOWN      -1
 
 #define IF_DATA_IPV4   0
-#define IF_DATA_IPV4LL 1
-#define IF_DATA_DHCP   2
-#define IF_DATA_IPV6   3
-#define IF_DATA_IPV6ND 4
-#define IF_DATA_DHCP6  5
-#define IF_DATA_MAX    6
+#define IF_DATA_ARP    1
+#define IF_DATA_IPV4LL 2
+#define IF_DATA_DHCP   3
+#define IF_DATA_IPV6   4
+#define IF_DATA_IPV6ND 5
+#define IF_DATA_DHCP6  6
+#define IF_DATA_MAX    7
 
 /* If the interface does not support carrier status (ie PPP),
  * dhcpcd can poll it for the relevant flags periodically */
index b6df0b43640fbe75761922263c82e2a20af427a9..e82cd1db0914fd9f32b3e6e198e192d136d02d9e 100644 (file)
--- a/if-bsd.c
+++ b/if-bsd.c
@@ -381,7 +381,6 @@ if_sendrawpacket(const struct interface *ifp, uint16_t protocol,
        struct iovec iov[2];
        struct ether_header hw;
        int fd;
-       const struct dhcp_state *state;
 
        memset(&hw, 0, ETHER_HDR_LEN);
        memset(&hw.ether_dhost, 0xff, ETHER_ADDR_LEN);
@@ -390,11 +389,7 @@ if_sendrawpacket(const struct interface *ifp, uint16_t protocol,
        iov[0].iov_len = ETHER_HDR_LEN;
        iov[1].iov_base = UNCONST(data);
        iov[1].iov_len = len;
-       state = D_CSTATE(ifp);
-       if (protocol == ETHERTYPE_ARP)
-               fd = state->arp_fd;
-       else
-               fd = state->raw_fd;
+       fd = ipv4_protocol_fd(ifp, protocol);
        return writev(fd, iov, 2);
 }
 
@@ -411,10 +406,7 @@ if_readrawpacket(struct interface *ifp, uint16_t protocol,
        struct dhcp_state *state;
 
        state = D_STATE(ifp);
-       if (protocol == ETHERTYPE_ARP)
-               fd = state->arp_fd;
-       else
-               fd = state->raw_fd;
+       fd = ipv4_protocol_fd(ifp, protocol);
 
        *flags = 0;
        for (;;) {
index 2acdf040aa5d03a40cd37a708b399c210d9b572c..6c28f8c7e5240d952dcd2bb4840006069dc9d62a 100644 (file)
@@ -1197,7 +1197,6 @@ ssize_t
 if_sendrawpacket(const struct interface *ifp, uint16_t protocol,
     const void *data, size_t len)
 {
-       const struct dhcp_state *state;
        union sockunion {
                struct sockaddr sa;
                struct sockaddr_ll sll;
@@ -1216,11 +1215,7 @@ if_sendrawpacket(const struct interface *ifp, uint16_t protocol,
                    &ipv4_bcast_addr, sizeof(ipv4_bcast_addr));
        else
                memset(&su.sll.sll_addr, 0xff, ifp->hwlen);
-       state = D_CSTATE(ifp);
-       if (protocol == ETHERTYPE_ARP)
-               fd = state->arp_fd;
-       else
-               fd = state->raw_fd;
+       fd = ipv4_protocol(ifp, protocol);
 
        return sendto(fd, data, len, 0, &su.sa, sizeof(su.sll));
 }
@@ -1253,10 +1248,7 @@ if_readrawpacket(struct interface *ifp, uint16_t protocol,
 #endif
 
        state = D_STATE(ifp);
-       if (protocol == ETHERTYPE_ARP)
-               fd = state->arp_fd;
-       else
-               fd = state->raw_fd;
+       fd = ipv4_protocol(ifp, protocol);
        bytes = recvmsg(fd, &msg, 0);
        if (bytes == -1)
                return -1;
diff --git a/ipv4.c b/ipv4.c
index 9dc5f1ac917f213dfbecab85e384f2e10ff651e7..d1d825096b05e0b81ace5443ddd5b93837cf4a60 100644 (file)
--- a/ipv4.c
+++ b/ipv4.c
@@ -28,6 +28,7 @@
 #include <sys/socket.h>
 #include <sys/types.h>
 
+#include <netinet/if_ether.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <net/route.h>
@@ -200,6 +201,23 @@ ipv4_init(struct dhcpcd_ctx *ctx)
        return 0;
 }
 
+int
+ipv4_protocol_fd(const struct interface *ifp, uint16_t protocol)
+{
+
+       if (protocol == ETHERTYPE_ARP) {
+               const struct iarp_state *istate;
+
+               istate = ARP_CSTATE(ifp);
+               return istate->fd;
+       } else {
+               const struct dhcp_state *dstate;
+
+               dstate = D_CSTATE(ifp);
+               return dstate->raw_fd;
+       }
+}
+
 /* Interface comparer for working out ordering. */
 int
 ipv4_ifcmp(const struct interface *si, const struct interface *ti)
diff --git a/ipv4.h b/ipv4.h
index 9c8422302c7278530d9a4ec1d58d9cfe47afad34..8453fc28f6831457f70bf12e8388e8183389a7f2 100644 (file)
--- a/ipv4.h
+++ b/ipv4.h
@@ -88,6 +88,7 @@ struct ipv4_state {
 
 #ifdef INET
 int ipv4_init(struct dhcpcd_ctx *);
+int ipv4_protocol_fd(const struct interface *, uint16_t);
 int ipv4_ifcmp(const struct interface *, const struct interface *);
 uint8_t inet_ntocidr(struct in_addr);
 int inet_cidrtoaddr(int, struct in_addr *);