]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Rework the raw packet API so we work directly with a fd.
authorRoy Marples <roy@marples.name>
Fri, 13 May 2016 15:41:58 +0000 (15:41 +0000)
committerRoy Marples <roy@marples.name>
Fri, 13 May 2016 15:41:58 +0000 (15:41 +0000)
It's possible the underlying mechanism might not use the fd as a primary
resource, so add the if_closeraw() function.

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

diff --git a/arp.c b/arp.c
index 20fcd7ae9bcf12109b067e96d157942d0865b539..30cc3aeab0060b257758f22226e1fcc170673b19 100644 (file)
--- a/arp.c
+++ b/arp.c
@@ -62,6 +62,7 @@ arp_request(const struct interface *ifp, in_addr_t sip, in_addr_t tip)
        struct arphdr ar;
        size_t len;
        uint8_t *p;
+       const struct iarp_state *state;
 
        ar.ar_hrd = htons(ifp->family);
        ar.ar_pro = htons(ETHERTYPE_IP);
@@ -88,7 +89,9 @@ arp_request(const struct interface *ifp, in_addr_t sip, in_addr_t tip)
        APPEND(&sip, sizeof(sip));
        ZERO(ifp->hwlen);
        APPEND(&tip, sizeof(tip));
-       return if_sendrawpacket(ifp, ETHERTYPE_ARP, arp_buffer, len);
+
+       state = ARP_CSTATE(ifp);
+       return if_sendraw(ifp, state->fd, ETHERTYPE_ARP, arp_buffer, len);
 
 eexit:
        errno = ENOBUFS;
@@ -132,7 +135,7 @@ arp_packet(void *arg)
        state = ARP_STATE(ifp);
        flags = 0;
        while (!(flags & RAW_EOF)) {
-               bytes = if_readrawpacket(ifp, ETHERTYPE_ARP,
+               bytes = if_readraw(ifp, state->fd,
                    arp_buffer, sizeof(arp_buffer), &flags);
                if (bytes == -1) {
                        logger(ifp->ctx, LOG_ERR,
@@ -200,7 +203,7 @@ arp_open(struct interface *ifp)
 
        state = ARP_STATE(ifp);
        if (state->fd == -1) {
-               state->fd = if_openrawsocket(ifp, ETHERTYPE_ARP);
+               state->fd = if_openraw(ifp, ETHERTYPE_ARP);
                if (state->fd == -1) {
                        logger(ifp->ctx, LOG_ERR, "%s: %s: %m",
                            __func__, ifp->name);
@@ -388,7 +391,7 @@ arp_free(struct arp_state *astate)
                    TAILQ_FIRST(&state->arp_states) == NULL)
                {
                        eloop_event_delete(ifp->ctx->eloop, state->fd);
-                       close(state->fd);
+                       if_closeraw(state->fd);
                        free(state);
                        ifp->if_data[IF_DATA_ARP] = NULL;
                }
diff --git a/dhcp.c b/dhcp.c
index 2a87cfba9c5882ae72b96570e02c27870cf60aa7..1ee273e39fd29b7eaff46378b7cfcb2d8129c229 100644 (file)
--- a/dhcp.c
+++ b/dhcp.c
@@ -1499,7 +1499,7 @@ dhcp_close(struct interface *ifp)
 
        if (state->raw_fd != -1) {
                eloop_event_delete(ifp->ctx->eloop, state->raw_fd);
-               close(state->raw_fd);
+               if_closeraw(state->raw_fd);
                state->raw_fd = -1;
        }
 
@@ -1727,12 +1727,12 @@ send_message(struct interface *ifp, uint8_t type,
                size_t ulen;
 
                r = 0;
-               udp = dhcp_makeudppacket(&ulen, (uint8_t *)bootp, len, from, to);
+               udp = dhcp_makeudppacket(&ulen, (uint8_t *)bootp, len, from,to);
                if (udp == NULL) {
                        logger(ifp->ctx, LOG_ERR, "dhcp_makeudppacket: %m");
                } else {
-                       r = if_sendrawpacket(ifp, ETHERTYPE_IP,
-                           (uint8_t *)udp, ulen);
+                       r = if_sendraw(ifp, state->raw_fd,
+                           ETHERTYPE_IP, (uint8_t *)udp, ulen);
                        free(udp);
                }
                /* If we failed to send a raw packet this normally means
@@ -1742,7 +1742,7 @@ send_message(struct interface *ifp, uint8_t type,
                 * stopping the interface. */
                if (r == -1) {
                        logger(ifp->ctx, LOG_ERR,
-                           "%s: if_sendrawpacket: %m", ifp->name);
+                           "%s: if_sendraw: %m", ifp->name);
                        switch(errno) {
                        case ENETDOWN:
                        case ENETRESET:
@@ -3101,7 +3101,7 @@ dhcp_handlepacket(void *arg)
        flags = 0;
        bootp = NULL;
        while (!(flags & RAW_EOF)) {
-               bytes = (size_t)if_readrawpacket(ifp, ETHERTYPE_IP,
+               bytes = (size_t)if_readraw(ifp, state->raw_fd,
                    buf, sizeof(buf), &flags);
                if ((ssize_t)bytes == -1) {
                        logger(ifp->ctx, LOG_ERR,
@@ -3190,7 +3190,7 @@ dhcp_open(struct interface *ifp)
 
        state = D_STATE(ifp);
        if (state->raw_fd == -1) {
-               state->raw_fd = if_openrawsocket(ifp, ETHERTYPE_IP);
+               state->raw_fd = if_openraw(ifp, ETHERTYPE_IP);
                if (state->raw_fd == -1) {
                        if (errno == ENOENT) {
                                logger(ifp->ctx, LOG_ERR,
index dd033f6748a6e9eae5e65ec7594aecd5d87580e5..57e315ff258678f0cdcb998064bf5fcb387a48d9 100644 (file)
--- a/if-bsd.c
+++ b/if-bsd.c
@@ -359,8 +359,15 @@ if_findsa(struct dhcpcd_ctx *ctx, const struct sockaddr *sa)
 #ifdef INET
 const char *if_pfname = "Berkley Packet Filter";
 
+void
+if_closeraw(int fd)
+{
+
+       close(fd);
+}
+
 int
-if_openrawsocket(struct interface *ifp, uint16_t protocol)
+if_openraw(struct interface *ifp, uint16_t protocol)
 {
        struct ipv4_state *state;
        int fd = -1;
@@ -462,12 +469,11 @@ eexit:
 }
 
 ssize_t
-if_sendrawpacket(const struct interface *ifp, uint16_t protocol,
+if_sendraw(__unused const struct interface *ifp, int fd, uint16_t protocol,
     const void *data, size_t len)
 {
        struct iovec iov[2];
        struct ether_header hw;
-       int fd;
 
        memset(&hw, 0, ETHER_HDR_LEN);
        memset(&hw.ether_dhost, 0xff, ETHER_ADDR_LEN);
@@ -476,25 +482,20 @@ 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;
-       fd = ipv4_protocol_fd(ifp, protocol);
        return writev(fd, iov, 2);
 }
 
 /* BPF requires that we read the entire buffer.
  * So we pass the buffer in the API so we can loop on >1 packet. */
 ssize_t
-if_readrawpacket(struct interface *ifp, uint16_t protocol,
-    void *data, size_t len, int *flags)
+if_readraw(struct interface *ifp, int fd, void *data, size_t len, int *flags)
 {
-       int fd;
        struct bpf_hdr packet;
        ssize_t bytes;
        const unsigned char *payload;
        struct ipv4_state *state;
 
        state = IPV4_STATE(ifp);
-       fd = ipv4_protocol_fd(ifp, protocol);
-
        *flags = 0;
        for (;;) {
                if (state->buffer_len == 0) {
index 3cadbe88f325e245d3850ad16187a757f80c6377..2b094a32628ef0b7ecbfd6af23a8387b9dc94453 100644 (file)
@@ -1218,8 +1218,15 @@ struct nlmr
 #ifdef INET
 const char *if_pfname = "Packet Socket";
 
+void
+if_closeraw(int fd)
+{
+
+       close(fd);
+}
+
 int
-if_openrawsocket(struct interface *ifp, uint16_t protocol)
+if_openraw(struct interface *ifp, uint16_t protocol)
 {
        int s;
        union sockunion {
@@ -1270,7 +1277,7 @@ eexit:
 }
 
 ssize_t
-if_sendrawpacket(const struct interface *ifp, uint16_t protocol,
+if_sendraw(const struct interface *ifp, int fd, uint16_t protocol,
     const void *data, size_t len)
 {
        union sockunion {
@@ -1278,7 +1285,6 @@ if_sendrawpacket(const struct interface *ifp, uint16_t protocol,
                struct sockaddr_ll sll;
                struct sockaddr_storage ss;
        } su;
-       int fd;
 
        memset(&su, 0, sizeof(su));
        su.sll.sll_family = AF_PACKET;
@@ -1296,13 +1302,12 @@ 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);
-       fd = ipv4_protocol_fd(ifp, protocol);
 
        return sendto(fd, data, len, 0, &su.sa, sizeof(su.sll));
 }
 
 ssize_t
-if_readrawpacket(struct interface *ifp, uint16_t protocol,
+if_readraw(__unused struct interface *ifp, int fd,
     void *data, size_t len, int *flags)
 {
        struct iovec iov = {
@@ -1320,14 +1325,12 @@ if_readrawpacket(struct interface *ifp, uint16_t protocol,
 #endif
 
        ssize_t bytes;
-       int fd = -1;
 
 #ifdef PACKET_AUXDATA
        msg.msg_control = cmsgbuf;
        msg.msg_controllen = sizeof(cmsgbuf);
 #endif
 
-       fd = ipv4_protocol_fd(ifp, protocol);
        bytes = recvmsg(fd, &msg, 0);
        if (bytes == -1)
                return -1;
index 152fe284fe7c38ab5d7b139c342fceefd469de89..f66d8479a16d9a4a996ddb4cfd5a59cc384d8cf5 100644 (file)
--- a/if-sun.c
+++ b/if-sun.c
@@ -351,8 +351,15 @@ out:
 #ifdef INET
 const char *if_pfname = "SunOS";
 
+void
+if_closeraw(int fd)
+{
+
+       UNUSED(fd);
+}
+
 int
-if_openrawsocket(struct interface *ifp, uint16_t protocol)
+if_openraw(struct interface *ifp, uint16_t protocol)
 {
 
        UNUSED(ifp);
@@ -362,11 +369,12 @@ if_openrawsocket(struct interface *ifp, uint16_t protocol)
 }
 
 ssize_t
-if_sendrawpacket(const struct interface *ifp, uint16_t protocol,
+if_sendraw(const struct interface *ifp, int fd, uint16_t protocol,
     const void *data, size_t len)
 {
 
        UNUSED(ifp);
+       UNUSED(fd);
        UNUSED(protocol);
        UNUSED(data);
        UNUSED(len);
@@ -375,12 +383,12 @@ if_sendrawpacket(const struct interface *ifp, uint16_t protocol,
 }
 
 ssize_t
-if_readrawpacket(struct interface *ifp, uint16_t protocol,
+if_readraw(struct interface *ifp, int fd,
     void *data, size_t len, int *flags)
 {
 
        UNUSED(ifp);
-       UNUSED(protocol);
+       UNUSED(fd);
        UNUSED(data);
        UNUSED(len);
        UNUSED(flags);
diff --git a/if.h b/if.h
index de9b2d9fa4b800f59f1e5df5387e98659efa2b8e..3d997291f9686d85208a6c59faee1141f2ffbdfc 100644 (file)
--- a/if.h
+++ b/if.h
@@ -139,10 +139,11 @@ int if_managelink(struct dhcpcd_ctx *);
 
 #ifdef INET
 extern const char *if_pfname;
-int if_openrawsocket(struct interface *, uint16_t);
-ssize_t if_sendrawpacket(const struct interface *,
-    uint16_t, const void *, size_t);
-ssize_t if_readrawpacket(struct interface *, uint16_t, void *, size_t, int *);
+int if_openraw(struct interface *, uint16_t);
+ssize_t if_sendraw(const struct interface *, int, uint16_t,
+    const void *, size_t);
+ssize_t if_readraw(struct interface *, int, void *, size_t, int *);
+void if_closeraw(int);
 
 int if_address(const struct interface *,
     const struct in_addr *, const struct in_addr *,
diff --git a/ipv4.c b/ipv4.c
index 8bce21231a1484994962acb5813eca2fb4ba11b5..09e94c9944da97429b3e15793e21843b9901463f 100644 (file)
--- a/ipv4.c
+++ b/ipv4.c
@@ -278,25 +278,6 @@ 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);
-               assert(istate != NULL);
-               return istate->fd;
-       } else {
-               const struct dhcp_state *dstate;
-
-               dstate = D_CSTATE(ifp);
-               assert(dstate != NULL);
-               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 036b5bfce6240f25f7dc2baa48a3656e88c81eae..cf8941da320d964b8260ed5c84404a27602887b3 100644 (file)
--- a/ipv4.h
+++ b/ipv4.h
@@ -97,7 +97,6 @@ struct ipv4_state {
 #ifdef INET
 struct ipv4_state *ipv4_getstate(struct interface *);
 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 *);