Bug 4205 - enable-recvmmsg in mixed IPv4/IPv6 environment fails
enable-recvmmsg in mixed IPv4/IPv6 environment fails
Status: RESOLVED FIXED
Product: NSD
Classification: Unclassified
Component: NSD Code
4.1.x
x86_64 NetBSD
: P5 critical
Assigned To: NSD team
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2018-11-14 10:44 CET by J. Hannken-Illjes
Modified: 2018-11-20 10:50 CET (History)
1 user (show)

See Also:


Attachments
Proposed fix (2.46 KB, application/octet-stream)
2018-11-14 10:44 CET, J. Hannken-Illjes
Details

Note You need to log in before you can comment on or make changes to this bug.
Description J. Hannken-Illjes 2018-11-14 10:44:57 CET
Created attachment 534 [details]
Proposed fix

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))
static void
msgs_reset(int i)
{

    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;
}
#endif

and use it in the RECVMMSG case.
Comment 1 Wouter Wijngaards 2018-11-20 10:50:57 CET
Hi,

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