]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
No point in looping on the raw socket anymore thanks to eloop.
authorRoy Marples <roy@marples.name>
Sat, 14 May 2016 12:57:32 +0000 (12:57 +0000)
committerRoy Marples <roy@marples.name>
Sat, 14 May 2016 12:57:32 +0000 (12:57 +0000)
This allows endless DHCP / ARP to be interuptable.

arp.c
dhcp.c
if-bsd.c
if-linux.c
if.h

diff --git a/arp.c b/arp.c
index ab313673fda00619a7241593442061a497ebc005..64f1237160dbfac0e8935ff92f720e70d6acf45f 100644 (file)
--- a/arp.c
+++ b/arp.c
@@ -123,7 +123,7 @@ arp_packet(void *arg)
 {
        struct interface *ifp = arg;
        const struct interface *ifn;
-       uint8_t arp_buffer[ARP_LEN];
+       uint8_t buf[ARP_LEN];
        struct arphdr ar;
        struct arp_msg arm;
        ssize_t bytes;
@@ -134,65 +134,62 @@ arp_packet(void *arg)
 
        state = ARP_STATE(ifp);
        flags = 0;
-       while (!(flags & RAW_EOF)) {
-               bytes = if_readraw(ifp, state->fd,
-                   arp_buffer, sizeof(arp_buffer), &flags);
-               if (bytes == -1) {
-                       logger(ifp->ctx, LOG_ERR,
-                           "%s: arp if_readrawpacket: %m", ifp->name);
-                       arp_close(ifp);
-                       return;
-               }
-               /* We must have a full ARP header */
-               if ((size_t)bytes < sizeof(ar))
-                       continue;
-               memcpy(&ar, arp_buffer, sizeof(ar));
-               /* Families must match */
-               if (ar.ar_hrd != htons(ifp->family))
-                       continue;
+       bytes = if_readraw(ifp, state->fd, buf, sizeof(buf), &flags);
+       if (bytes == -1) {
+               logger(ifp->ctx, LOG_ERR,
+                   "%s: arp if_readrawpacket: %m", ifp->name);
+               arp_close(ifp);
+               return;
+       }
+       /* We must have a full ARP header */
+       if ((size_t)bytes < sizeof(ar))
+               return;
+       memcpy(&ar, buf, sizeof(ar));
+       /* Families must match */
+       if (ar.ar_hrd != htons(ifp->family))
+               return;
 #if 0
-               /* These checks are enforced in the BPF filter. */
-               /* Protocol must be IP. */
-               if (ar.ar_pro != htons(ETHERTYPE_IP))
-                       continue;
-               /* Only these types are recognised */
-               if (ar.ar_op != htons(ARPOP_REPLY) &&
-                   ar.ar_op != htons(ARPOP_REQUEST))
-                       continue;
+       /* These checks are enforced in the BPF filter. */
+       /* Protocol must be IP. */
+       if (ar.ar_pro != htons(ETHERTYPE_IP))
+               continue;
+       /* Only these types are recognised */
+       if (ar.ar_op != htons(ARPOP_REPLY) &&
+           ar.ar_op != htons(ARPOP_REQUEST))
+               continue;
 #endif
-               if (ar.ar_pln != sizeof(arm.sip.s_addr))
-                       continue;
-
-               /* Get pointers to the hardware addreses */
-               hw_s = arp_buffer + sizeof(ar);
-               hw_t = hw_s + ar.ar_hln + ar.ar_pln;
-               /* Ensure we got all the data */
-               if ((hw_t + ar.ar_hln + ar.ar_pln) - arp_buffer > bytes)
-                       continue;
-               /* Ignore messages from ourself */
-               TAILQ_FOREACH(ifn, ifp->ctx->ifaces, next) {
-                       if (ar.ar_hln == ifn->hwlen &&
-                           memcmp(hw_s, ifn->hwaddr, ifn->hwlen) == 0)
-                               break;
-               }
-               if (ifn) {
+       if (ar.ar_pln != sizeof(arm.sip.s_addr))
+               return;
+
+       /* Get pointers to the hardware addreses */
+       hw_s = buf + sizeof(ar);
+       hw_t = hw_s + ar.ar_hln + ar.ar_pln;
+       /* Ensure we got all the data */
+       if ((hw_t + ar.ar_hln + ar.ar_pln) - buf > bytes)
+               return;
+       /* Ignore messages from ourself */
+       TAILQ_FOREACH(ifn, ifp->ctx->ifaces, next) {
+               if (ar.ar_hln == ifn->hwlen &&
+                   memcmp(hw_s, ifn->hwaddr, ifn->hwlen) == 0)
+                       break;
+       }
+       if (ifn) {
 #if 0
-                       logger(ifp->ctx, LOG_DEBUG,
-                           "%s: ignoring ARP from self", ifp->name);
+               logger(ifp->ctx, LOG_DEBUG,
+                   "%s: ignoring ARP from self", ifp->name);
 #endif
-                       continue;
-               }
-               /* Copy out the HW and IP addresses */
-               memcpy(&arm.sha, hw_s, ar.ar_hln);
-               memcpy(&arm.sip.s_addr, hw_s + ar.ar_hln, ar.ar_pln);
-               memcpy(&arm.tha, hw_t, ar.ar_hln);
-               memcpy(&arm.tip.s_addr, hw_t + ar.ar_hln, ar.ar_pln);
-
-               /* Run the conflicts */
-               TAILQ_FOREACH_SAFE(astate, &state->arp_states, next, astaten) {
-                       if (astate->conflicted_cb)
-                               astate->conflicted_cb(astate, &arm);
-               }
+               return;
+       }
+       /* Copy out the HW and IP addresses */
+       memcpy(&arm.sha, hw_s, ar.ar_hln);
+       memcpy(&arm.sip.s_addr, hw_s + ar.ar_hln, ar.ar_pln);
+       memcpy(&arm.tha, hw_t, ar.ar_hln);
+       memcpy(&arm.tip.s_addr, hw_t + ar.ar_hln, ar.ar_pln);
+
+       /* Run the conflicts */
+       TAILQ_FOREACH_SAFE(astate, &state->arp_states, next, astaten) {
+               if (astate->conflicted_cb)
+                       astate->conflicted_cb(astate, &arm);
        }
 }
 
diff --git a/dhcp.c b/dhcp.c
index 2cd1ac62f0d7900a65d902c61795082f28580541..fc0a0b2f0a4887509ee63b9bbb733c05e1ef93a1 100644 (file)
--- a/dhcp.c
+++ b/dhcp.c
@@ -3100,69 +3100,57 @@ dhcp_handlepacket(void *arg)
        /* Need this API due to BPF */
        flags = 0;
        bootp = NULL;
-       while (!(flags & RAW_EOF)) {
-               bytes = (size_t)if_readraw(ifp, state->raw_fd,
-                   buf, sizeof(buf), &flags);
-               if ((ssize_t)bytes == -1) {
-                       logger(ifp->ctx, LOG_ERR,
-                           "%s: dhcp if_readrawpacket: %m", ifp->name);
-                       dhcp_close(ifp);
-                       arp_close(ifp);
-                       break;
-               }
-               if (valid_udp_packet(buf, bytes,
-                   &from, flags & RAW_PARTIALCSUM) == -1)
-               {
-                       logger(ifp->ctx, LOG_ERR,
-                           "%s: invalid UDP packet from %s",
-                           ifp->name, inet_ntoa(from));
-                       continue;
-               }
-               i = whitelisted_ip(ifp->options, from.s_addr);
-               if (i == 0) {
-                       logger(ifp->ctx, LOG_WARNING,
-                           "%s: non whitelisted DHCP packet from %s",
-                           ifp->name, inet_ntoa(from));
-                       continue;
-               } else if (i != 1 &&
-                   blacklisted_ip(ifp->options, from.s_addr) == 1)
-               {
-                       logger(ifp->ctx, LOG_WARNING,
-                           "%s: blacklisted DHCP packet from %s",
-                           ifp->name, inet_ntoa(from));
-                       continue;
-               }
-               if (ifp->flags & IFF_POINTOPOINT &&
-                   state->brd.s_addr != from.s_addr)
-               {
-                       logger(ifp->ctx, LOG_WARNING,
-                           "%s: server %s is not destination",
-                           ifp->name, inet_ntoa(from));
-               }
-               /*
-                * DHCP has a variable option area rather than a fixed
-                * vendor area.
-                * Because DHCP uses the BOOTP protocol it should
-                * still send BOOTP sized packets to be RFC compliant.
-                * However some servers send a truncated vendor area.
-                * dhcpcd can work fine without the vendor area being sent.
-                */
-               bytes = get_udp_data(&bootp, buf);
-               if (bytes < offsetof(struct bootp, vend)) {
-                       logger(ifp->ctx, LOG_ERR,
-                           "%s: truncated packet (%zu) from %s",
-                           ifp->name, bytes, inet_ntoa(from));
-                       continue;
-               }
-               /* But to make our IS_DHCP macro easy, ensure the vendor
-                * area has at least 4 octets. */
-               while (bytes < offsetof(struct bootp, vend) + 4)
-                       bootp[bytes++] = '\0';
-
-               dhcp_handledhcp(ifp, (struct bootp *)bootp, bytes, &from);
-               if (state->raw_fd == -1)
-                       break;
+       bytes = (size_t)if_readraw(ifp, state->raw_fd,buf, sizeof(buf), &flags);
+       if ((ssize_t)bytes == -1) {
+               logger(ifp->ctx, LOG_ERR,
+                   "%s: dhcp if_readrawpacket: %m", ifp->name);
+               dhcp_close(ifp);
+               arp_close(ifp);
+               return;
        }
+       if (valid_udp_packet(buf, bytes, &from, flags & RAW_PARTIALCSUM) == -1)
+       {
+               logger(ifp->ctx, LOG_ERR, "%s: invalid UDP packet from %s",
+                   ifp->name, inet_ntoa(from));
+               return;
+       }
+       i = whitelisted_ip(ifp->options, from.s_addr);
+       if (i == 0) {
+               logger(ifp->ctx, LOG_WARNING,
+                   "%s: non whitelisted DHCP packet from %s",
+                   ifp->name, inet_ntoa(from));
+               return;
+       } else if (i != 1 && blacklisted_ip(ifp->options, from.s_addr) == 1) {
+               logger(ifp->ctx, LOG_WARNING,
+                   "%s: blacklisted DHCP packet from %s",
+                   ifp->name, inet_ntoa(from));
+               return;
+       }
+       if (ifp->flags & IFF_POINTOPOINT && state->brd.s_addr != from.s_addr) {
+               logger(ifp->ctx, LOG_WARNING,
+                   "%s: server %s is not destination",
+                   ifp->name, inet_ntoa(from));
+       }
+       /*
+        * DHCP has a variable option area rather than a fixed vendor area.
+        * Because DHCP uses the BOOTP protocol it should still send BOOTP
+        * sized packets to be RFC compliant.
+        * However some servers send a truncated vendor area.
+        * dhcpcd can work fine without the vendor area being sent.
+        */
+       bytes = get_udp_data(&bootp, buf);
+       if (bytes < offsetof(struct bootp, vend)) {
+               logger(ifp->ctx, LOG_ERR,
+                   "%s: truncated packet (%zu) from %s",
+                   ifp->name, bytes, inet_ntoa(from));
+               return;
+       }
+       /* But to make our IS_DHCP macro easy, ensure the vendor
+        * area has at least 4 octets. */
+       while (bytes < offsetof(struct bootp, vend) + 4)
+               bootp[bytes++] = '\0';
+
+       dhcp_handledhcp(ifp, (struct bootp *)bootp, bytes, &from);
 }
 
 static void
index 86215c788cfe6f16114b84cc897e46d516f3f64f..0f35ce2a18b9f736573cd4332e5ecf73fc76aad2 100644 (file)
--- a/if-bsd.c
+++ b/if-bsd.c
@@ -522,10 +522,8 @@ if_readraw(struct interface *ifp, int fd, void *data, size_t len, int *flags)
 next:
                state->buffer_pos += BPF_WORDALIGN(packet.bh_hdrlen +
                    packet.bh_caplen);
-               if (state->buffer_pos >= state->buffer_len) {
+               if (state->buffer_pos >= state->buffer_len)
                        state->buffer_len = state->buffer_pos = 0;
-                       *flags |= RAW_EOF;
-               }
                if (bytes != -1)
                        return bytes;
        }
index d3d1ec0c1f7b920cafe8393668ffe6c09d2ce01f..404b2c968db6f4b08e2cb09057fc99e8579fe6a5 100644 (file)
@@ -1334,7 +1334,7 @@ if_readraw(__unused struct interface *ifp, int fd,
        bytes = recvmsg(fd, &msg, 0);
        if (bytes == -1)
                return -1;
-       *flags = RAW_EOF; /* We only ever read one packet */
+       *flags = 0;
        if (bytes) {
 #ifdef PACKET_AUXDATA
                for (cmsg = CMSG_FIRSTHDR(&msg);
diff --git a/if.h b/if.h
index 33f05cab896002a1a2a66615b1928de99ec4397f..b4a9f983e9e491fb1c83fc4b4cd6676a9cae49a4 100644 (file)
--- a/if.h
+++ b/if.h
@@ -80,8 +80,7 @@
            ((addr & IN_CLASSB_NET) == 0xc0a80000))
 #endif
 
-#define RAW_EOF                        1 << 0
-#define RAW_PARTIALCSUM                2 << 0
+#define RAW_PARTIALCSUM                1 << 0
 
 #ifdef __sun
 /* platform does not supply AF_LINK with getifaddrs. */