From: Roy Marples Date: Fri, 25 Oct 2019 11:49:01 +0000 (+0100) Subject: Split *_recv() into *_recv() and *_recvmsg() functions X-Git-Tag: v8.1.2~37 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c548c5b3662b0a2981c130d8f6d943c7dc5fe1b7;p=thirdparty%2Fdhcpcd.git Split *_recv() into *_recv() and *_recvmsg() functions The *_recvmsg() function has the whole packet in the first and only iov. Serves little purpose now, but will be used in the future. --- diff --git a/src/dhcp.c b/src/dhcp.c index 6ffd139b..2dd0bbda 100644 --- a/src/dhcp.c +++ b/src/dhcp.c @@ -3450,6 +3450,35 @@ dhcp_readbpf(void *arg) state->bpf_flags &= ~BPF_READING; } +static void +dhcp_recvmsg(struct dhcpcd_ctx *ctx, struct msghdr *msg) +{ + struct sockaddr_in *from = (struct sockaddr_in *)msg->msg_name; + struct iovec *iov = &msg->msg_iov[0]; + struct interface *ifp; + const struct dhcp_state *state; + + ifp = if_findifpfromcmsg(ctx, msg, NULL); + if (ifp == NULL) { + logerr(__func__); + return; + } + state = D_CSTATE(ifp); + if (state == NULL) { + logdebugx("%s: received BOOTP for inactive interface", + ifp->name); + return; + } + + if (state->bpf_fd != -1) { + /* Avoid a duplicate read if BPF is open for the interface. */ + return; + } + + dhcp_handlebootp(ifp, (struct bootp *)iov->iov_base, iov->iov_len, + &from->sin_addr); +} + static void dhcp_readudp(struct dhcpcd_ctx *ctx, struct interface *ifp) { @@ -3485,27 +3514,8 @@ dhcp_readudp(struct dhcpcd_ctx *ctx, struct interface *ifp) return; } - if (ifp == NULL) { - ifp = if_findifpfromcmsg(ctx, &msg, NULL); - if (ifp == NULL) { - logerr(__func__); - return; - } - state = D_CSTATE(ifp); - if (state == NULL) { - logdebugx("%s: received BOOTP for inactive interface", - ifp->name); - return; - } - } - - if (state->bpf_fd != -1) { - /* Avoid a duplicate read if BPF is open for the interface. */ - return; - } - - dhcp_handlebootp(ifp, (struct bootp *)(void *)buf, (size_t)bytes, - &from.sin_addr); + iov.iov_len = (size_t)bytes; + dhcp_recvmsg(ctx, &msg); } static void diff --git a/src/dhcp6.c b/src/dhcp6.c index 4ef2e565..98d506bb 100644 --- a/src/dhcp6.c +++ b/src/dhcp6.c @@ -3465,23 +3465,10 @@ dhcp6_recvif(struct interface *ifp, const char *sfrom, } static void -dhcp6_recv(struct dhcpcd_ctx *ctx, struct ipv6_addr *ia) +dhcp6_recvmsg(struct dhcpcd_ctx *ctx, struct msghdr *msg, struct ipv6_addr *ia) { - struct sockaddr_in6 from; - unsigned char buf[64 * 1024]; /* Maximum UDP message size */ - struct iovec iov = { - .iov_base = buf, - .iov_len = sizeof(buf), - }; - unsigned char ctl[CMSG_SPACE(sizeof(struct in6_pktinfo))] = { 0 }; - struct msghdr msg = { - .msg_name = &from, .msg_namelen = sizeof(from), - .msg_iov = &iov, .msg_iovlen = 1, - .msg_control = ctl, .msg_controllen = sizeof(ctl), - }; - int s; - size_t len; - ssize_t bytes; + struct sockaddr_in6 *from = msg->msg_name; + size_t len = msg->msg_iov[0].iov_len; char sfrom[INET6_ADDRSTRLEN]; struct interface *ifp; struct dhcp6_message *r; @@ -3489,14 +3476,7 @@ dhcp6_recv(struct dhcpcd_ctx *ctx, struct ipv6_addr *ia) uint8_t *o; uint16_t ol; - s = ia != NULL ? ia->dhcp6_fd : ctx->dhcp6_fd; - bytes = recvmsg(s, &msg, 0); - if (bytes == -1) { - logerr(__func__); - return; - } - len = (size_t)bytes; - inet_ntop(AF_INET6, &from.sin6_addr, sfrom, sizeof(sfrom)); + inet_ntop(AF_INET6, &from->sin6_addr, sfrom, sizeof(sfrom)); if (len < sizeof(struct dhcp6_message)) { logerrx("DHCPv6 packet too short from %s", sfrom); return; @@ -3505,14 +3485,14 @@ dhcp6_recv(struct dhcpcd_ctx *ctx, struct ipv6_addr *ia) if (ia != NULL) ifp = ia->iface; else { - ifp = if_findifpfromcmsg(ctx, &msg, NULL); + ifp = if_findifpfromcmsg(ctx, msg, NULL); if (ifp == NULL) { logerr(__func__); return; } } - r = (struct dhcp6_message *)buf; + r = (struct dhcp6_message *)msg->msg_iov[0].iov_base; o = dhcp6_findmoption(r, len, D6_OPTION_CLIENTID, &ol); if (o == NULL || ol != ctx->duid_len || memcmp(o, ctx->duid, ol) != 0) @@ -3580,6 +3560,35 @@ dhcp6_recv(struct dhcpcd_ctx *ctx, struct ipv6_addr *ia) dhcp6_recvif(ifp, sfrom, r, len); } +static void +dhcp6_recv(struct dhcpcd_ctx *ctx, struct ipv6_addr *ia) +{ + struct sockaddr_in6 from; + unsigned char buf[64 * 1024]; /* Maximum UDP message size */ + struct iovec iov = { + .iov_base = buf, + .iov_len = sizeof(buf), + }; + unsigned char ctl[CMSG_SPACE(sizeof(struct in6_pktinfo))] = { 0 }; + struct msghdr msg = { + .msg_name = &from, .msg_namelen = sizeof(from), + .msg_iov = &iov, .msg_iovlen = 1, + .msg_control = ctl, .msg_controllen = sizeof(ctl), + }; + int s; + ssize_t bytes; + + s = ia != NULL ? ia->dhcp6_fd : ctx->dhcp6_fd; + bytes = recvmsg(s, &msg, 0); + if (bytes == -1) { + logerr(__func__); + return; + } + + iov.iov_len = (size_t)bytes; + dhcp6_recvmsg(ctx, &msg, ia); +} + static void dhcp6_recvaddr(void *arg) { diff --git a/src/ipv6nd.c b/src/ipv6nd.c index 929b071d..44beb400 100644 --- a/src/ipv6nd.c +++ b/src/ipv6nd.c @@ -1718,6 +1718,51 @@ ipv6nd_drop(struct interface *ifp) } } +static void +ipv6nd_recvmsg(struct dhcpcd_ctx *ctx, struct msghdr *msg) +{ + struct sockaddr_in6 *from = (struct sockaddr_in6 *)msg->msg_name; + char sfrom[INET6_ADDRSTRLEN]; + int hoplimit = 0; + struct icmp6_hdr *icp; + struct interface *ifp; + size_t len = msg->msg_iov[0].iov_len; + + inet_ntop(AF_INET6, &from->sin6_addr, sfrom, sizeof(sfrom)); + if ((size_t)len < sizeof(struct icmp6_hdr)) { + logerrx("IPv6 ICMP packet too short from %s", sfrom); + return; + } + +#ifdef __sun + if_findifpfromcmsg(ctx, msg, &hoplimit); +#else + ifp = if_findifpfromcmsg(ctx, msg, &hoplimit); + if (ifp == NULL) { + logerr(__func__); + return; + } +#endif + + /* Don't do anything if the user hasn't configured it. */ + if (ifp->active != IF_ACTIVE_USER || + !(ifp->options->options & DHCPCD_IPV6)) + return; + + icp = (struct icmp6_hdr *)msg->msg_iov[0].iov_base; + if (icp->icmp6_code == 0) { + switch(icp->icmp6_type) { + case ND_ROUTER_ADVERT: + ipv6nd_handlera(ctx, from, sfrom, + ifp, icp, (size_t)len, hoplimit); + return; + } + } + + logerrx("invalid IPv6 type %d or code %d from %s", + icp->icmp6_type, icp->icmp6_code, sfrom); +} + static void ipv6nd_handledata(void *arg) { @@ -1736,10 +1781,6 @@ ipv6nd_handledata(void *arg) .msg_control = ctl, .msg_controllen = sizeof(ctl), }; ssize_t len; - char sfrom[INET6_ADDRSTRLEN]; - int hoplimit = 0; - struct icmp6_hdr *icp; - struct interface *ifp; #ifdef __sun struct rs_state *state; @@ -1757,39 +1798,9 @@ ipv6nd_handledata(void *arg) logerr(__func__); return; } - inet_ntop(AF_INET6, &from.sin6_addr, sfrom, sizeof(sfrom)); - if ((size_t)len < sizeof(struct icmp6_hdr)) { - logerrx("IPv6 ICMP packet too short from %s", sfrom); - return; - } - -#ifdef __sun - if_findifpfromcmsg(ctx, &msg, &hoplimit); -#else - ifp = if_findifpfromcmsg(ctx, &msg, &hoplimit); - if (ifp == NULL) { - logerr(__func__); - return; - } -#endif - /* Don't do anything if the user hasn't configured it. */ - if (ifp->active != IF_ACTIVE_USER || - !(ifp->options->options & DHCPCD_IPV6)) - return; - - icp = (struct icmp6_hdr *)buf; - if (icp->icmp6_code == 0) { - switch(icp->icmp6_type) { - case ND_ROUTER_ADVERT: - ipv6nd_handlera(ctx, &from, sfrom, - ifp, icp, (size_t)len, hoplimit); - return; - } - } - - logerrx("invalid IPv6 type %d or code %d from %s", - icp->icmp6_type, icp->icmp6_code, sfrom); + iov.iov_len = (size_t)len; + ipv6nd_recvmsg(ctx, &msg); } static void