From 8945f73d946a9323daf8dfc1bf5b3884cf6d7664 Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Thu, 26 Jun 2014 13:30:27 +0200 Subject: [PATCH] Ensures that msg_controllen includes last padding. Although RFC 3542 allows both cases, Theo de Raadt thinks he knows better, and msg_controllen without last padding fails on OpenBSD. Thanks to Job Snijders for the bugreport. --- sysdep/bsd/sysio.h | 4 +++- sysdep/linux/sysio.h | 4 +++- sysdep/unix/io.c | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/sysdep/bsd/sysio.h b/sysdep/bsd/sysio.h index fa3969bd..df5e0236 100644 --- a/sysdep/bsd/sysio.h +++ b/sysdep/bsd/sysio.h @@ -141,6 +141,7 @@ sk_prepare_cmsgs4(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen) #ifdef IP_SENDSRCADDR struct cmsghdr *cm; struct in_addr *sa; + int controllen = 0; msg->msg_control = cbuf; msg->msg_controllen = cbuflen; @@ -149,11 +150,12 @@ sk_prepare_cmsgs4(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen) cm->cmsg_level = IPPROTO_IP; cm->cmsg_type = IP_SENDSRCADDR; cm->cmsg_len = CMSG_LEN(sizeof(*sa)); + controllen += CMSG_SPACE(sizeof(*sa)); sa = (struct in_addr *) CMSG_DATA(cm); *sa = ipa_to_in4(s->saddr); - msg->msg_controllen = cm->cmsg_len; + msg->msg_controllen = controllen; #endif } diff --git a/sysdep/linux/sysio.h b/sysdep/linux/sysio.h index 5fd75c90..c1561cbf 100644 --- a/sysdep/linux/sysio.h +++ b/sysdep/linux/sysio.h @@ -154,6 +154,7 @@ sk_prepare_cmsgs4(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen) { struct cmsghdr *cm; struct in_pktinfo *pi; + int controllen = 0; msg->msg_control = cbuf; msg->msg_controllen = cbuflen; @@ -162,13 +163,14 @@ sk_prepare_cmsgs4(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen) cm->cmsg_level = SOL_IP; cm->cmsg_type = IP_PKTINFO; cm->cmsg_len = CMSG_LEN(sizeof(*pi)); + controllen += CMSG_SPACE(sizeof(*pi)); pi = (struct in_pktinfo *) CMSG_DATA(cm); pi->ipi_ifindex = s->iface ? s->iface->index : 0; pi->ipi_spec_dst = ipa_to_in4(s->saddr); pi->ipi_addr = ipa_to_in4(IPA_NONE); - msg->msg_controllen = cm->cmsg_len; + msg->msg_controllen = controllen; } diff --git a/sysdep/unix/io.c b/sysdep/unix/io.c index 5a0c07e5..a5477695 100644 --- a/sysdep/unix/io.c +++ b/sysdep/unix/io.c @@ -705,6 +705,7 @@ sk_prepare_cmsgs6(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen) { struct cmsghdr *cm; struct in6_pktinfo *pi; + int controllen = 0; msg->msg_control = cbuf; msg->msg_controllen = cbuflen; @@ -713,12 +714,13 @@ sk_prepare_cmsgs6(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen) cm->cmsg_level = SOL_IPV6; cm->cmsg_type = IPV6_PKTINFO; cm->cmsg_len = CMSG_LEN(sizeof(*pi)); + controllen += CMSG_SPACE(sizeof(*pi)); pi = (struct in6_pktinfo *) CMSG_DATA(cm); pi->ipi6_ifindex = s->iface ? s->iface->index : 0; pi->ipi6_addr = ipa_to_in6(s->saddr); - msg->msg_controllen = cm->cmsg_len; + msg->msg_controllen = controllen; }