IPV6_RECVPKTINFO not working for IPv4-mapped addresses on Linux?

Hannes Frederic Sowa hannes at stressinduktion.org
Mon Jan 20 15:23:32 CET 2014

On Mon, Jan 20, 2014 at 03:00:33PM +0100, Gert Doering wrote:
> On Mon, Jan 20, 2014 at 12:49:56PM +0000, Benedikt Stockebrand wrote:
> > Gert Doering <gert at space.net> writes:
> > 
> > > So I would activate both IPPROTO_IPV6/IPV6_RECVPKTINFO *and* 
> > > SOL_IP/IP_PKTINFO, and depending on the "real" address family I'll see 
> > > one or the other?
> > 
> > I've run into this sort of problems a few years ago, but I used a
> > different solution: I didn't use mapped addresses but two separate
> > sockets, one for IPv4 and another for IPv6.  It isn't nice, but it
> > sorted out the problem in a way that worked on all platforms I tested
> > without any problems or #ifdefs or whatever.
> I expected that suggestion :-)  (actually I expected a much longer 
> discussion about the evilness of IPv4-mapped addresses on an IPv6 
> socket, but to my pleasant surprise, the actual fix came much faster)

Hmm, I hope that does not cause any problems in the long term, as e.g. easier
disclosure of randomized ports on DNS servers by misguided ICMP errors because
of some ancient routing header stuff which is still enabled in some address
family on routers or end hosts.

I guess for DNS servers it is best to keep both ports separate. Also dual
personality sockets do add a lot of complexity to the kernel and we had some
bugs because of that. But the decision had been done and we cannot roll it
back now.

> (I'm surprised your code didn't need #ifdefs for the IPv4 part, as the
> ancilliary socket stuff is completely different on Linux and the BSDs
> here...  IP_PKTINFO vs. IP_RECVDSTADDR... for IPv6 it's the same, but
> even there you have 2292-only and 3542 implementations)

I put 2292 opts on my todo list but had no fun in porting the "old"
options to the new agnostic address family handler over yesterday. It
should be done nonetheless.

As for the ifdefs, linux does try to avoid them and it is of no good style to
use them. We mainly use them in headers and keep the code paths clean of
them (see e.g. ipv6_sk_rxinfo in the patch).

That said, we have a lot functions which just have two variants of their
static inline functions or macros, which just do nothing or return NULL
if ipv6 is not enabled compiletime (e.g. inet6_sk). Constant folding in
gcc optimizes that away completley then.

> > Of course, the key question then is how much trouble is it to fix that
> > in the existing application code base.
> Much :-).  
> This *is* a long-term goal, though, to enable OpenVPN to listen on multiple
> sockets in parallel (including "udp and tcp" in the same server), but this 
> part of the code is *old*, has way too many options, and runs on way too 
> many systems with their own specific surprises.

Even your test program was quite large. ;)

Thanks for that, it was easy to test the new code with that.

> We're slowly working our way through it, and what we'll have in 
> OpenVPN 2.4 is "clean dual-stack handling with a single socket" 
> (2.3 has "IPv4 and IPv6", but no real "call getaddrinfo(), use IPv4 
> or IPv6, depending on what getaddrinfo() returns and what works"
> mechanics).
> So, for the time being, the decision was to go for a single server 
> socket at this point and fix other stuff first.  Then come back.

Sounds great, I hope no other problems show up. ;)



More information about the ipv6-ops mailing list