On Sat, Apr 01, 2006 at 12:03:00AM +0200, Adrian Knoth wrote:
> On Fri, Mar 31, 2006 at 11:06:55AM -0800, Brooks Davis wrote:
> 
> > > One little problem here is that it is possible to disable the
> > > IPv6-mapped IPv4 addresses at least under Linux and some BSD variants.
> > > For Linux, have a look at sys.net.ipv6.bindv6only.  Some authors even
> > More specifically, KAME derived (BSD) stacks disable them by default so
> 
> In addition, OpenBSD doesn't provide mapped addresses. Though this
> is a violation of RFC 4291, RFC 4038 "recommends" this approach:
> 
>    Note that some systems will disable (by default) support for internal
>    IPv4-mapped IPv6 addresses.  The security concerns regarding these
>    are legitimate, but disabling them internally breaks one transition
>    mechanism for server applications originally written to bind() and
>    listen() to a single socket by using a wildcard address.  This forces
>    the software developer to rewrite the daemon to create two separate
>    sockets, one for IPv4 only and the other for IPv6 only, and then to
>    use select().  However, mapping-enabling of IPv4 addresses on any
>    particular system is controlled by the OS owner and not necessarily
>    by a developer.  This complicates developers' work, as they now have
>    to rewrite the daemon network code to handle both environments, even
>    for the same OS.
>
> > it might be best to assume it doesn't work since you'll probably have
> > to support that case anyway.
> 
> ACK. But what does this imply? Do we already have select()ed
> binds, in other words, can we simply spawn two listen()-sockets?

Looking at the code in btl_tcp_component.c it looks like it mostly is.
You'd just have to add another socket and register another event for it.

> If we conclude not to use mapped addresses, will we end up
> with btl/tcp and btl/tcp6?

I'd certainly hope not.

> The OS support issue can be handled this way:
> 
> union sockaddr_union {
>         struct sockaddr sa;
>         struct sockaddr_in sin;
> #ifdef HAVE_IPV6
>         struct sockaddr_in6 sin6;
> #endif
> };
> 
> and later:
> 
> /* copy IP to sockaddr */
> static inline void
> sin_set_ip(union sockaddr_union *so, const struct ip_addr *ip)
> {
>         if (ip == NULL) {
> #ifdef HAVE_IPV6
>                 so->sin6.sin6_family = AF_INET6;
>                 so->sin6.sin6_addr = in6addr_any;
> #else
>                 so->sin.sin_family = AF_INET;
>                 so->sin.sin_addr.s_addr = INADDR_ANY;
> #endif
>                 return;
>         }
> 
> 
> (code shamelessly borrowed from dovecot/src/lib/network.c)
> 
> It might be a little harder to read, but it keeps both
> versions (IPv4-only and IPv6) close together.

Based on experiences at work, I'd say dovecot is NOT a good example to
copy from.  We're running it on a dual stack network and you have to run
two copies which is lame.

-- Brooks

-- 
Any statement of the form "X is the one, true Y" is FALSE.
PGP fingerprint 655D 519C 26A7 82E7 2529  9BF0 5D8E 8BE9 F238 1AD4

Attachment: pgp4UMCu0tlPE.pgp
Description: PGP signature

Reply via email to