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?

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

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.


-- 
mail: a...@thur.de      http://adi.thur.de      PGP: v2-key via keyserver

Scheiße wird nicht dadurch besser oder sicherer, dass man ein paar
Shareware-Warnlämpchen dranpappt. (Robin S. Socha über "Desktop-Firewalls")

Reply via email to