From c6cc455dd191fbea56ee14a0ef88a7d655a6fe9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Courr=C3=A8ges-Anglas?= Date: Fri, 22 Mar 2019 10:56:13 +0100 Subject: [PATCH 48/57] Fix cmsg(3) API usage on OpenBSD msg_controllen should be set using CMSG_SPACE() to account for padding. RFC3542 provides more details: While sending an application may or may not include padding at the end of last ancillary data in msg_controllen and implementations must accept both as valid. At least OpenBSD rejects control messages if msg_controllen doesn't account for padding, so use CMSG_SPACE() for maximal portability. This is consistent with the example provided in the Linux cmsg(3) manpage. Signed-off-by: Kevin Darbyshire-Bryant --- src/forward.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) --- a/src/forward.c +++ b/src/forward.c @@ -65,13 +65,15 @@ int send_from(int fd, int nowild, char * struct in_pktinfo p; p.ipi_ifindex = 0; p.ipi_spec_dst = source->addr4; + msg.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo)); memcpy(CMSG_DATA(cmptr), &p, sizeof(p)); - msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); + cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); cmptr->cmsg_level = IPPROTO_IP; cmptr->cmsg_type = IP_PKTINFO; #elif defined(IP_SENDSRCADDR) + msg.msg_controllen = CMSG_SPACE(sizeof(struct in_addr)); memcpy(CMSG_DATA(cmptr), &(source->addr4), sizeof(source->addr4)); - msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_addr)); + cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_addr)); cmptr->cmsg_level = IPPROTO_IP; cmptr->cmsg_type = IP_SENDSRCADDR; #endif @@ -81,8 +83,9 @@ int send_from(int fd, int nowild, char * struct in6_pktinfo p; p.ipi6_ifindex = iface; /* Need iface for IPv6 to handle link-local addrs */ p.ipi6_addr = source->addr6; + msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)); memcpy(CMSG_DATA(cmptr), &p, sizeof(p)); - msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); + cmptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); cmptr->cmsg_type = daemon->v6pktinfo; cmptr->cmsg_level = IPPROTO_IPV6; }