From: Roy Marples Date: Fri, 13 May 2016 15:41:58 +0000 (+0000) Subject: Rework the raw packet API so we work directly with a fd. X-Git-Tag: v6.11.1~51 X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=76c1b6856370f8659f789018b89f86279aeccf20;p=thirdparty%2Fdhcpcd.git Rework the raw packet API so we work directly with a fd. It's possible the underlying mechanism might not use the fd as a primary resource, so add the if_closeraw() function. --- diff --git a/arp.c b/arp.c index 20fcd7ae..30cc3aea 100644 --- 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 2a87cfba..1ee273e3 100644 --- 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, diff --git a/if-bsd.c b/if-bsd.c index dd033f67..57e315ff 100644 --- 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) { diff --git a/if-linux.c b/if-linux.c index 3cadbe88..2b094a32 100644 --- a/if-linux.c +++ b/if-linux.c @@ -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; diff --git a/if-sun.c b/if-sun.c index 152fe284..f66d8479 100644 --- 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 de9b2d9f..3d997291 100644 --- 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 8bce2123..09e94c99 100644 --- 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 036b5bfc..cf8941da 100644 --- 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 *);