From: Sarah Day Date: Thu, 11 Feb 2016 20:39:04 +0000 (-0500) Subject: Add support for IP_SENDSRCADDR for UDP pktinfo X-Git-Tag: krb5-1.15-beta1~268 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=457a4ac5057d44c0c947efc3c047c32897b54747;p=thirdparty%2Fkrb5.git Add support for IP_SENDSRCADDR for UDP pktinfo FreeBSD uses IP_RECVDSTADDR and IP_SENDSRCADDR instead of IP_PKTINFO for IPv4 pktinfo functionality. Add support for using this when IP_PKTINFO is not available. --- diff --git a/src/lib/apputils/udppktinfo.c b/src/lib/apputils/udppktinfo.c index aa601faa19..8fafb1583c 100644 --- a/src/lib/apputils/udppktinfo.c +++ b/src/lib/apputils/udppktinfo.c @@ -36,7 +36,8 @@ #define HAVE_IPV6_PKTINFO #endif -#if defined(HAVE_IP_PKTINFO) || defined(HAVE_IPV6_PKTINFO) +#if defined(HAVE_IP_PKTINFO) || defined(IP_SENDSRCADDR) || \ + defined(HAVE_IPV6_PKTINFO) #define HAVE_PKTINFO_SUPPORT #endif @@ -59,6 +60,9 @@ union pktinfo { #endif #ifdef HAVE_STRUCT_IN_PKTINFO struct in_pktinfo pi4; +#endif +#ifdef IP_RECVDSTADDR + struct in_addr iaddr; #endif char c; }; @@ -100,9 +104,20 @@ set_ipv4_recvpktinfo(int sock) sizeof(sockopt)); } -#else /* HAVE_IP_PKTINFO */ +#elif defined(IP_RECVDSTADDR) /* HAVE_IP_PKTINFO */ + +#define set_ipv4_pktinfo set_ipv4_recvdstaddr +static inline krb5_error_code +set_ipv4_recvdstaddr(int sock) +{ + int sockopt = 1; + return setsockopt(sock, IPPROTO_IP, IP_RECVDSTADDR, &sockopt, + sizeof(sockopt)); +} + +#else /* HAVE_IP_PKTINFO || IP_RECVDSTADDR */ #define set_ipv4_pktinfo(s) EINVAL -#endif /* HAVE_IP_PKTINFO */ +#endif /* HAVE_IP_PKTINFO || IP_RECVDSTADDR */ #ifdef HAVE_IPV6_PKTINFO @@ -170,9 +185,37 @@ check_cmsg_ip_pktinfo(struct cmsghdr *cmsgptr, struct sockaddr *to, return 0; } -#else /* HAVE_IP_PKTINFO */ +#elif defined(IP_RECVDSTADDR) /* HAVE_IP_PKTINFO */ + +static inline struct in_addr * +cmsg2sin(struct cmsghdr *cmsgptr) +{ + return (struct in_addr *)(void *)CMSG_DATA(cmsgptr); +} + +#define check_cmsg_v4_pktinfo check_cmsg_ip_recvdstaddr +static int +check_cmsg_ip_recvdstaddr(struct cmsghdr *cmsgptr, struct sockaddr *to, + socklen_t *tolen, aux_addressing_info * auxaddr) +{ + if (cmsgptr->cmsg_level == IPPROTO_IP && + cmsgptr->cmsg_type == IP_RECVDSTADDR && + *tolen >= sizeof(struct sockaddr_in)) { + struct in_addr *sin_addr; + + memset(to, 0, sizeof(struct sockaddr_in)); + sin_addr = cmsg2sin(cmsgptr); + sa2sin(to)->sin_addr = *sin_addr; + sa2sin(to)->sin_family = AF_INET; + *tolen = sizeof(struct sockaddr_in); + return 1; + } + return 0; +} + +#else /* HAVE_IP_PKTINFO || IP_RECVDSTADDR */ #define check_cmsg_v4_pktinfo(c, t, l, a) 0 -#endif /* HAVE_IP_PKTINFO */ +#endif /* HAVE_IP_PKTINFO || IP_RECVDSTADDR */ #ifdef HAVE_IPV6_PKTINFO @@ -314,9 +357,29 @@ set_msg_from_ip_pktinfo(struct msghdr *msg, struct cmsghdr *cmsgptr, return 0; } -#else /* HAVE_IP_PKTINFO */ +#elif defined(IP_SENDSRCADDR) /* HAVE_IP_PKTINFO */ + +#define set_msg_from_ipv4 set_msg_from_ip_sendsrcaddr +static krb5_error_code +set_msg_from_ip_sendsrcaddr(struct msghdr *msg, struct cmsghdr *cmsgptr, + struct sockaddr *from, socklen_t fromlen, + aux_addressing_info *auxaddr) +{ + struct in_addr *sin_addr = cmsg2sin(cmsgptr); + const struct sockaddr_in *from4 = sa2sin(from); + if (fromlen != sizeof(struct sockaddr_in)) + return EINVAL; + cmsgptr->cmsg_level = IPPROTO_IP; + cmsgptr->cmsg_type = IP_SENDSRCADDR; + cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in_addr)); + msg->msg_controllen = CMSG_SPACE(sizeof(struct in_addr)); + *sin_addr = from4->sin_addr; + return 0; +} + +#else /* HAVE_IP_PKTINFO || IP_SENDSRCADDR */ #define set_msg_from_ipv4(m, c, f, l, a) EINVAL -#endif /* HAVE_IP_PKTINFO */ +#endif /* HAVE_IP_PKTINFO || IP_SENDSRCADDR */ #ifdef HAVE_IPV6_PKTINFO