fetchmail-friends
[Top] [All Lists]

IPv6 Maintainers... was Re: [fetchmail]6.0.0 release is imminent

2002-06-21 07:49:52
All,

        I asked Eric for an executive decision on some IPv6 issues.
His executive decision was to have me solicit feedback from the list
and then make a decision and he would accept the patch.  So this
is the first part.  I'm soliciting input to a couple of problems
with IPv6.  If one of the IPv6 maintainers wishes to just rise up
and fix it, great!  Eric will take the patch and I'll be a happy camper.

        Here it is in a nutshell.  There are two problem in the IPv6
code that gets particulary ugly when dealing with IPv6-only sites
or IPv6-only names but is a sleeping problem even with dual address names.

        Problem 1:

        When Trying to reference IPv6 only host names (no DNS "A" record,
only DNS "AAAA" records), fetchmail does not work at all.  It refuses
because it can not resolve the host canonical name using gethostbyname.
For hosts with both A records and AAAA records, fetchmail works, but
for the wrong reason.  It resolves the host canonical name using the
IPv4 address and then uses IPv6 to contact the host.

        Solution:

        When supporting IPv6, all references to gethostbyname must be
replaced by getaddrinfo.  Consequently, the code must change to match
the returned structures and memory management.

        Options:

        We can #if all such blocks of code under #if ENABLE_INET6
and have both styles of code ala the way it is currently done in SockOpen()
[socket.c].

        =or=

        We can provide a stub "getaddrinfo" function, as is done in
OpenSSH, for those platforms (IPv4 only) which do not have the getaddrinfo
function.  Since those platforms are inherently IPv4 only, it can be a
simplified version of getaddrinfo (as in OpenSSH).  Then all the calls
and supporting code for gethostbyname can simply be converted to the
getaddrinfo call and some of the code (and supporting tables) collapsed
into common source instead of #if'ed.  Advantages...  Reduced source code
complexity by eliminating redundant code.  Disadvantages...  Somewhat more
complex patch (but not much more complex since we need the code to use
getaddrinfo anyways).

        My personal preference is for the later, especially if we can
use existing functionality from another project (TBD).


        Problem 2 (this one is ugly):

        The code in checkaliases compares addresses to see when to
names refer to the same system.  The heuristic is that if two names
have any one address in common, they must be aliases of each other.
The code in there makes several gethostbyname calls and only works
for IPv4.  Comparing addresses in IPv6 is a lot more complicated.
In addition to the size of the addresses being 128 bits long for
the comparision, IPv6 supports multiple autoconfigured addresses
for interfaces and, often, interfaces will have three or more addresses
in different "Scopes".  An interface will have a "link-local" scope
(address begins fe80::), may have a "site-local" scoped address (address
begins fec0::) and may have one or more global addresses (address begins
with 3ffe: for the 6Bone addresses or 2002: for deployed TLA, top level
agragator, addresses).  In most of these cases, if the lower 64 bits
of the address is an autoconfigured EUI address (ff:fe in the middle 16
bits of the adderss) then the address matches the host if the lower
64 bits match, regardless of the top 64 bit prefix.  Comparing IPv4
addresses to IPv6 "compatibility" addresses is another can of worms.

        Solution:

        Enhance checkaliases.c to use getaddrinfo for IPv6 addresses
and compare addresses from either the AF_INET or AF_INET6 families.

        Options:

        Just compare the full addresses or do we add heuristics to
crack and understand the different fields in the IPv6 address and
match addresses with differing prefixes but point to the same host
based on the EUI address and/or the IPv4 compatibility addresses
(ffff::n.n.n.n and ::n.n.n.n).

        This is a call for input and/or patches.

        Attached below is the previous message in this thread, just
prior to my asking Eric for his executive decision, with some
additional comments...

        Mike
-- 
 Michael H. Warfield    |  (770) 985-6132   |  mhw(_at_)WittsEnd(_dot_)com
  /\/\|=mhw=|\/\/       |  (678) 463-0932   |  http://www.wittsend.com/mhw/
  NIC whois:  MHW9      |  An optimist believes we live in the best of all
 PGP Key: 0xDF1DD471    |  possible worlds.  A pessimist is sure of it!

On Tue, Jun 18, 2002 at 01:50:29PM -0400, Michael H. Warfield wrote:
On Tue, Jun 18, 2002 at 06:56:32PM +0200, Matthias Andree wrote:
"Michael H. Warfield" <mhw(_at_)wittsend(_dot_)com> writes:

  Looking through the OpenSSH portable code, it looks as though
we need to use the "getaddrinfo" call instead of the "gethostbyname"
call in order to properly support IPv6.  At least that's what they've
done.  I don't know if there are any platforms on which this would
be a problem, but OpenSSH doesn't have any conditional compiles wrap
around that call AFAICT.  The change is non-trivial, however.  The
returned structures are quite different.  I'm looking at it now.

Different, yes, but getaddrinfo covers it all, and you're getting the
service lookup for free. (My other mail that pointed this out has been
sent with a "wrong" from address and awaits moderation.)

        Ahh!!  A light dawns.  So THAT'S why the services tables
use the symbolic names when INET6 is enabled.  A switch to getaddrinfo
would result in collapsing that code into a common format.

  Interesting enough, SockOpen() USES getaddrinfo if INET6_ENABLE
is defined.  That explains why IPv6 works for connecting to an IPv6
host which has an IPv4 A record.  The gethostbyname calls will succeed
elsewhere but, when it comes to actually creating the socket, we get
the IPv6 connection thanks to the getaddrinfo call.  I was scratching
my head TRYING to figure out WHY nobody had seen this before.  Now I
know.  It only breaks for IPv6-Only host names and works on IPv6/IPv4
dual address names for the wrong reason.  :-<

Ouch.

  OpenSock() only uses getaddrinfo in the INET6 case but OpenSSH
seems to use it unconditionally.  We've got calls to gethostbyname
in checkaliases.c, driver.c, and env.c (the one in socket.c is covered
by the ifdef on INET6_ENABLE).  The one in driver.c is the one causing
the immediate problem and seems the easiest one to fix.  That one
is just being used to derive the canonical name and should be easy
to replace with getaddrinfo.

Hum, does getaddrinfo work on Solaris 2.6?

      I would guess not.  There doesn't seem to be a man page for it
and OpenSSH says it can't find it on 2.6.

      OpenSSH portable contains a "fake_getaddrinfo" in the openbsd-compat
directory, so that's how they are getting around the platforms that
don't support getaddrinfo.

  It looks like the ones in checkaliases.c could be a real mess,
though.  The one in env.c looks to be a problem only if we are running
from an IPv6-Only host and is less likely to occur, right now.  :-)

        Both of those sources should take into account different
prefix types for IPv6 in addition to switching to getaddrinfo.

  There are also some checks in fetchmail.c for "HAVE_GETHOSTBYNAME"
which don't look like they do any harm but raise the question if that
check is valid when using getaddrinfo.

You'd certainly have to check for getaddrinfo in configure.in to avoid
surprises to portability.

      True.  Then it's a matter of either an #ifdef like is done in
socket.c or providing a fake getaddrinfo like is done in OpenSSH.
Personally, I like the way they handled it in OpenSSH but it's not
my shot to call.

        I guess, according to Eric, it is now my shot to call.

-- 
Matthias Andree

      Mike
-- 
 Michael H. Warfield    |  (770) 985-6132   |  mhw(_at_)WittsEnd(_dot_)com
  /\/\|=mhw=|\/\/       |  (678) 463-0932   |  http://www.wittsend.com/mhw/
  NIC whois:  MHW9      |  An optimist believes we live in the best of all
 PGP Key: 0xDF1DD471    |  possible worlds.  A pessimist is sure of it!