Bugzilla – Bug 4205
enable-recvmmsg in mixed IPv4/IPv6 environment fails
Last modified: 2018-11-20 10:50:57 CET
Created attachment 534 [details]
NetBSD builtin NSD 4.1.24 is configured with "--enable-recvmmsg". It gets EINVAL errors from sendmmsg for IPv6 queries once it got one IPv4 query.
Tracked it down to the handling of msg_hdr.msg_namelen: recvmmsg like recmsg on NetBSD copies at most msg_namelen bytes of the remote address and set msg_namelen to the minimum of its current value and the length of the address. After one IPv4 query msg_namelen is 16 so further IPv6 queries return a truncated remote address and trying to send the reply gives EINVAL as the address is invalid.
On Linux (used CentOS7) the situation is even worse: recvmmsg like recvmsg copies at most msg_namelen bytes of the remote address and set msg_namelen to the UNTRUNCATED length of the address. This makes NSD answer the first IPv6 query after an IPv4 query to a WRONG address. The first 16 bytes are valid, the remaining 12 bytes are invalid data from a recent query.
Solved it with explicit re-initialisation after query_reset, see the attached diff. It is prepared against 4.1.24 and applies cleanly to 4.1.25.
Another approach is to add
#if (!defined(NONBLOCKING_IS_BROKEN) && defined(HAVE_RECVMMSG))
query_reset(queries[i], UDP_MAX_MESSAGE_LEN, 0);
iovecs[i].iov_len = buffer_remaining(queries[i]->packet);
msgs[i].msg_hdr.msg_namelen = queries[i]->addrlen;
and use it in the RECVMMSG case.
Thank you very much for the patch and the fix. I did know there were issues with IPv6 and recvmmesg, but I had not realised it was in the reset of the value of the hdrlen. I have incorporated the patch you suggested.
Best regards, Wouter