From: Roy Marples Date: Tue, 19 Feb 2019 21:46:06 +0000 (+0000) Subject: Fold all CMSG parsing into a common function. X-Git-Tag: v7.2.0~31 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0ac6d9c9ebb8e179a1887181527e3684beb17df0;p=thirdparty%2Fdhcpcd.git Fold all CMSG parsing into a common function. Makes dhcpcd smaller still. --- diff --git a/src/dhcp.c b/src/dhcp.c index 4a8f5d57..fb916700 100644 --- a/src/dhcp.c +++ b/src/dhcp.c @@ -3477,36 +3477,9 @@ dhcp_readudp(struct dhcpcd_ctx *ctx, struct interface *ifp) inet_ntop(AF_INET, &from.sin_addr, sfrom, sizeof(sfrom)); if (ifp == NULL) { - struct cmsghdr *cm; - struct in_pktinfo pi; - - pi.ipi_ifindex = 0; - for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&msg); - cm; - cm = (struct cmsghdr *)CMSG_NXTHDR(&msg, cm)) - { - if (cm->cmsg_level != IPPROTO_IP) - continue; - switch(cm->cmsg_type) { - case IP_PKTINFO: - if (cm->cmsg_len == CMSG_LEN(sizeof(pi))) - memcpy(&pi, CMSG_DATA(cm), sizeof(pi)); - break; - } - } - if (pi.ipi_ifindex == 0) { - logerrx("DHCP reply did not contain index from %s", - sfrom); - return; - } - - TAILQ_FOREACH(ifp, ctx->ifaces, next) { - if (ifp->index == (unsigned int)pi.ipi_ifindex) - break; - } + ifp = if_findifpfromcmsg(ctx, &msg, NULL); if (ifp == NULL) { - logerrx("DHCP reply for unexpected interface from %s", - sfrom); + logerr(__func__); return; } } diff --git a/src/dhcp6.c b/src/dhcp6.c index c50efb66..6e83a70f 100644 --- a/src/dhcp6.c +++ b/src/dhcp6.c @@ -3498,36 +3498,9 @@ dhcp6_recv(struct dhcpcd_ctx *ctx, struct ipv6_addr *ia) if (ia != NULL) ifp = ia->iface; else { - struct cmsghdr *cm; - struct in6_pktinfo pi; - - pi.ipi6_ifindex = 0; - for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&msg); - cm; - cm = (struct cmsghdr *)CMSG_NXTHDR(&msg, cm)) - { - if (cm->cmsg_level != IPPROTO_IPV6) - continue; - switch(cm->cmsg_type) { - case IPV6_PKTINFO: - if (cm->cmsg_len == CMSG_LEN(sizeof(pi))) - memcpy(&pi, CMSG_DATA(cm), sizeof(pi)); - break; - } - } - if (pi.ipi6_ifindex == 0) { - logerrx("DHCPv6 reply did not contain index from %s", - sfrom); - return; - } - - TAILQ_FOREACH(ifp, ctx->ifaces, next) { - if (ifp->index == (unsigned int)pi.ipi6_ifindex) - break; - } + ifp = if_findifpfromcmsg(ctx, &msg, NULL); if (ifp == NULL) { - logerrx("DHCPv6 reply for unexpected interface from %s", - sfrom); + logerr(__func__); return; } } diff --git a/src/if.c b/src/if.c index 42b3e7b3..9ba286d1 100644 --- a/src/if.c +++ b/src/if.c @@ -801,6 +801,68 @@ if_sortinterfaces(struct dhcpcd_ctx *ctx) TAILQ_CONCAT(ctx->ifaces, &sorted, next); } +struct interface * +if_findifpfromcmsg(struct dhcpcd_ctx *ctx, struct msghdr *msg, int *hoplimit) +{ + struct cmsghdr *cm; + unsigned int ifindex = 0; + struct interface *ifp; +#ifdef INET + struct in_pktinfo ipi; +#endif +#ifdef INET6 + struct in6_pktinfo ipi6; +#else + UNUSED(hoplimit); +#endif + + for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(msg); + cm; + cm = (struct cmsghdr *)CMSG_NXTHDR(msg, cm)) + { +#ifdef INET + if (cm->cmsg_level == IPPROTO_IP) { + switch(cm->cmsg_type) { + case IP_PKTINFO: + if (cm->cmsg_len != CMSG_LEN(sizeof(ipi))) + continue; + memcpy(&ipi, CMSG_DATA(cm), sizeof(ipi)); + ifindex = (unsigned int)ipi.ipi_ifindex; + break; + } + } +#endif +#ifdef INET6 + if (cm->cmsg_level == IPPROTO_IPV6) { + switch(cm->cmsg_type) { + case IPV6_PKTINFO: + if (cm->cmsg_len != CMSG_LEN(sizeof(ipi6))) + continue; + memcpy(&ipi6, CMSG_DATA(cm), sizeof(ipi6)); + ifindex = (unsigned int)ipi6.ipi6_ifindex; + break; + case IPV6_HOPLIMIT: + if (cm->cmsg_len != CMSG_LEN(sizeof(int))) + continue; + if (hoplimit == NULL) + break; + memcpy(hoplimit, CMSG_DATA(cm), sizeof(int)); + break; + } + } +#endif + } + + /* Find the receiving interface */ + TAILQ_FOREACH(ifp, ctx->ifaces, next) { + if (ifp->index == ifindex) + break; + } + if (ifp == NULL) + errno = ESRCH; + return ifp; +} + int xsocket(int domain, int type, int protocol) { diff --git a/src/if.h b/src/if.h index d260d2d1..2f20764c 100644 --- a/src/if.h +++ b/src/if.h @@ -209,5 +209,7 @@ int if_getlifetime6(struct ipv6_addr *); #endif int if_machinearch(char *, size_t); +struct interface *if_findifpfromcmsg(struct dhcpcd_ctx *, + struct msghdr *, int *); int xsocket(int, int, int); #endif diff --git a/src/ipv6nd.c b/src/ipv6nd.c index 7f67287c..bef77b2a 100644 --- a/src/ipv6nd.c +++ b/src/ipv6nd.c @@ -1672,10 +1672,8 @@ ipv6nd_handledata(void *arg) .msg_control = ctl, .msg_controllen = sizeof(ctl), }; ssize_t len; - struct cmsghdr *cm; char sfrom[INET6_ADDRSTRLEN]; - int hoplimit; - struct in6_pktinfo pkt; + int hoplimit = 0; struct icmp6_hdr *icp; struct interface *ifp; @@ -1691,41 +1689,15 @@ ipv6nd_handledata(void *arg) return; } - pkt.ipi6_ifindex = 0; - hoplimit = 0; - for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&msg); - cm; - cm = (struct cmsghdr *)CMSG_NXTHDR(&msg, cm)) - { - if (cm->cmsg_level != IPPROTO_IPV6) - continue; - switch(cm->cmsg_type) { - case IPV6_PKTINFO: - if (cm->cmsg_len == CMSG_LEN(sizeof(pkt))) - memcpy(&pkt, CMSG_DATA(cm), sizeof(pkt)); - break; - case IPV6_HOPLIMIT: - if (cm->cmsg_len == CMSG_LEN(sizeof(int))) - memcpy(&hoplimit, CMSG_DATA(cm), sizeof(int)); - break; - } - } - - if (pkt.ipi6_ifindex == 0) { - logerrx("IPv6 RA/NA did not contain index from %s", sfrom); + ifp = if_findifpfromcmsg(ctx, &msg, &hoplimit); + if (ifp == NULL) { + logerr(__func__); return; } - /* Find the receiving interface */ - TAILQ_FOREACH(ifp, ctx->ifaces, next) { - if (ifp->index == (unsigned int)pkt.ipi6_ifindex) - break; - } - /* Don't do anything if the user hasn't configured it. */ - if (ifp != NULL && - (ifp->active != IF_ACTIVE_USER || - !(ifp->options->options & DHCPCD_IPV6))) + if (ifp->active != IF_ACTIVE_USER || + !(ifp->options->options & DHCPCD_IPV6)) return; icp = (struct icmp6_hdr *)buf;