You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Justin Erenkrantz <ju...@erenkrantz.com> on 2003/08/12 04:28:20 UTC

[PATCH] Default Listen with IPv6 enabled incorrect

When I updated to HEAD just now on my Solaris box, httpd wouldn't start
with this:

[Mon Aug 11 19:10:08 2003] [crit] (EAI 8)host/servname not known:
alloc_listener: failed to set up sockaddr for ::
Syntax error on line 217 of .../conf/httpd.conf:
Listen setup failed

Line 217 is:

Listen 8080

Something that simple should work.  Yet, it looks like if we have IPv6
compiled in, we will assume that all non-qualified addresses are IPv6.
That seems wrong.  (I have no idea why this never appeared before.)

Any arguments on tossing the find_default_family function altogether, and
just going to 0.0.0.0 when the addr isn't specified?  If you want IPv6, you
should explicitly specify it with 'Listen ::8080' or something, but
assuming that since we have IPv6 available that the unqualified addresses
must be IPv6 doesn't make sense and is badness.  -- justin

Index: server/listen.c
===================================================================
RCS file: /home/cvs/httpd-2.0/server/listen.c,v
retrieving revision 1.86
diff -u -r1.86 listen.c
--- server/listen.c 31 Mar 2003 04:30:38 -0000  1.86
+++ server/listen.c 12 Aug 2003 02:22:34 -0000
@@ -235,38 +235,6 @@
 }


-static void find_default_family(apr_pool_t *p)
-{
-#if APR_HAVE_IPV6
-    /* We know the platform supports IPv6, but this particular
-     * system may not have IPv6 enabled.  See if we can get an
-     * AF_INET6 socket and bind to an ephemeral port.  (On most
-     * systems, getting an AF_INET6 socket is a sufficient test.
-     * On certain levels of OpenUNIX, getting the socket is
-     * successful but bind always returns ENETUNREACH.)
-     */
-    if (default_family == APR_UNSPEC) {
-        apr_status_t sock_rv;
-        apr_socket_t *tmp_sock;
-        apr_sockaddr_t *sa;
-
-        if ((sock_rv = apr_socket_create(&tmp_sock, APR_INET6, 
SOCK_STREAM, p))
-            == APR_SUCCESS &&
-            apr_sockaddr_info_get(&sa, NULL, APR_INET6, 0, 0, p) == 
APR_SUCCESS &&
-            apr_bind(tmp_sock, sa) == APR_SUCCESS) {
-            default_family = APR_INET6;
-        }
-        else {
-            default_family = APR_INET;
-        }
-        if (sock_rv == APR_SUCCESS) {
-            apr_socket_close(tmp_sock);
-        }
-    }
-#endif
-}
-
-
 static const char *alloc_listener(process_rec *process, char *addr, 
apr_port_t port)
 {
     ap_listen_rec **walk;
@@ -276,21 +244,10 @@
     apr_sockaddr_t *sa;

     if (!addr) { /* don't bind to specific interface */
-        find_default_family(process->pool);
-        switch(default_family) {
-        case APR_INET:
-            addr = "0.0.0.0";
-            break;
-
-#if APR_HAVE_IPV6
-        case APR_INET6:
-            addr = "::";
-            break;
-#endif
-
-        default:
-            ap_assert(1 != 1); /* should not occur */
-        }
+        /* We should default to IPv4 when we have no address specified
+         * even if we have IPv6.
+         */
+        addr = "0.0.0.0";
     }

     /* see if we've got an old listener for this address:port */



Re: [PATCH] Default Listen with IPv6 enabled incorrect

Posted by "Colm MacCarthaigh,,," <co...@stdlib.net>.
On Tue, Aug 12, 2003 at 09:04:05AM -0700, Justin Erenkrantz wrote:
> >If IPv6 has been enabled, that should bind to :: , this is the standard
> >behaviour of all IPv6 apps, and to not do so would be utterly broken.
> >If by some quirk the OS doesn't support IPv4 over IPv6 sockets, then
> >getaddrinfo PF_UNSPEC magic should return the correct linked list to
> >handle this.
> 
> Um, then wouldn't it only be listening on IPv6 sockets, not IPv4?

Yep :)

> Surely that can't be right.  -- justin

It is, in fact it's the only way you can do it on some stacks (Linux
is an example of one). The socket will accept IPv4 addresses and
treat them as IPv4 mapped IPv6 addresses. They look like:

	::ffff:193.1.219.90 

Apache handles these just fine for the most part, and the addresses
are translated into the correct AF for logging and so on. E.g on
Linux:

colmmacc@byron:~$ netstat -an | grep 80
tcp        0      0 :::80                   :::* 	LISTEN   

byron:/home/colmmacc# tail -1 /var/log/apache/access.log
193.1.219.104 - - [15/May/2003:11:22:39 +0100] "GET / HTTP/1.0" 200 4110
"-" "check_http/1.32.2.6 (netsaint-plugins 1.2.9-4)"

Allthough on some platforms (Tru64) I'm tracking down a bug which
seems to leave the addresses mapped for variables like REMOTE_ADDR.

There's also some slight Access List type problems in that IPv4
ACLs don't get applied properly in some situations because of
this, and also mapped addresses in access lists never seem to work.
I can't allow/deny ::ffff:$something for example, which really
I should be able to.

I have an AF-indepentent access list implementation which I wrote
for NSD which I'm working on utilising in APR for apache which should
fix a lot of these niggly problems, but havnt had much time to work
on it lately.

-- 
Colm MacCárthaigh                        Public Key: colm+pgp@stdlib.net
colm@stdlib.net					  http://www.stdlib.net/

Re: [PATCH] Default Listen with IPv6 enabled incorrect

Posted by Justin Erenkrantz <ju...@erenkrantz.com>.
--On Tuesday, August 12, 2003 3:22 PM +0100 "Colm MacCarthaigh,,," 
<co...@stdlib.net> wrote:

> If IPv6 has been enabled, that should bind to :: , this is the standard
> behaviour of all IPv6 apps, and to not do so would be utterly broken.
> If by some quirk the OS doesn't support IPv4 over IPv6 sockets, then
> getaddrinfo PF_UNSPEC magic should return the correct linked list to
> handle this.

Um, then wouldn't it only be listening on IPv6 sockets, not IPv4?

Surely that can't be right.  -- justin

Re: [PATCH] Default Listen with IPv6 enabled incorrect

Posted by "Colm MacCarthaigh,,," <co...@stdlib.net>.
On Mon, Aug 11, 2003 at 07:28:20PM -0700, Justin Erenkrantz wrote:
> Listen 8080

If IPv6 has been enabled, that should bind to :: , this is the standard
behaviour of all IPv6 apps, and to not do so would be utterly broken.
If by some quirk the OS doesnt support IPv4 over IPv6 sockets, then
getaddrinfo PF_UNSPEC magic should return the correct linked list to
handle this.

Changing this would break a lot of existing installs on people!

> Any arguments on tossing the find_default_family function altogether, and
> just going to 0.0.0.0 when the addr isn't specified?  If you want IPv6, you
> should explicitly specify it with 'Listen ::8080' or something, 

This would be a bug. It's not like IPv6 is an optional extra!

> but
> assuming that since we have IPv6 available that the unqualified addresses
> must be IPv6 doesn't make sense and is badness.  -- justin

I think you this 100% the wrong way around. It's extreme goodness,

-- 
Colm MacCárthaigh                        Public Key: colm+pgp@stdlib.net
colm@stdlib.net					  http://www.stdlib.net/

Re: [PATCH] Default Listen with IPv6 enabled incorrect

Posted by Justin Erenkrantz <ju...@erenkrantz.com>.
--On Wednesday, August 13, 2003 1:59 AM +0100 "Colm MacCarthaigh,,," 
<co...@stdlib.net> wrote:

> This is the real bug, Apache shouldn't be second-guessing getaddrinfo,
> APR's call_resolver is an excellent example of how to do it properly,
> AI_ADDRCONFIG is the key. Trouble is apr_sockaddr_info_get isnt
> calling it for us. This is an APR bug, see the attached patch.

Okay, I just committed variants of your patch to CVS that work for me on 
Solaris.  The biggest gotcha was setting servname to be non-NULL when hostname 
was NULL.

Thanks!  -- justin


Re: [PATCH] Default Listen with IPv6 enabled incorrect

Posted by Justin Erenkrantz <ju...@erenkrantz.com>.
--On Wednesday, August 13, 2003 2:58 AM +0100 "Colm MacCarthaigh,,," 
<co...@stdlib.net> wrote:

> Solaris getaddrinfo takes it, at least in the
> version I'm using. Though now that I've tested it,
> it doesn't seem to honour it :(
>
> Solaris is where Justin is seeing the problem.
> Gah, back to sqaure one. (well, square 1.1).

Since Joe Orton was the one who added that AI_ADDRCONFIG flag, he should be 
the one who speaks up on this.

I now have a server that runs, which is more than I could say yesterday.  -- 
justin

Re: [PATCH] Default Listen with IPv6 enabled incorrect

Posted by "Colm MacCarthaigh,,," <co...@stdlib.net>.
On Tue, Aug 12, 2003 at 06:17:12PM -0700, Wan-Teh Chang wrote:
> Regarding your patch: I think it is fine to
> assume that AI_PASSIVE is defined if
> getaddrinfo() exists.  

Same here, but it seemed more consistent with the existing
code to check anyway.

> all the getaddrinfo() implementations I know of
> conform to either RFC 2133 or RFC 2553 and do
> not take the AI_ADDRCONFIG flag.  (RFC 2553 has
> AI_ADDRCONFIG but it is for getipnodebyname().)

Solaris getaddrinfo takes it, at least in the
version I'm using. Though now that I've tested it,
it doesnt seem to honour it :(

Solaris is where Justin is seeing the problem.
Gah, back to sqaure one. (well, square 1.1).

-- 
Colm MacCárthaigh                        Public Key: colm+pgp@stdlib.net
colm@stdlib.net					  http://www.stdlib.net/

Re: [PATCH] Default Listen with IPv6 enabled incorrect

Posted by Joe Orton <jo...@manyfish.co.uk>.
On Tue, Aug 12, 2003 at 06:17:12PM -0700, Wan-Teh Chang wrote:
> Regarding a previous patch to use AI_ADDRCONFIG:
> all the getaddrinfo() implementations I know of
> conform to either RFC 2133 or RFC 2553 and do
> not take the AI_ADDRCONFIG flag.

glibc is getting support for this.

>  (RFC 2553 has
> AI_ADDRCONFIG but it is for getipnodebyname().)
> It is risky to assume that when AI_ADDRCONFIG is
> passed to these getaddrinfo() implementations,
> getaddrinfo() will either silently ignore it or
> fail with the EAI_BADFLAGS error.  It is better
> to confirm that getaddrinfo() conforms to RFC
> 3493 before passing AI_ADDRCONFIG to it.

I think it's a pretty small risk, but you're probably
right. I tested all the getaddrinfo() implementations I
could find and they did the right thing; it's not like
this is going to be a risk for anyone porting APR to old
Unixes.

Regards,

joe

Re: [PATCH] Default Listen with IPv6 enabled incorrect

Posted by Wan-Teh Chang <wt...@netscape.com>.
Regarding your patch: I think it is fine to
assume that AI_PASSIVE is defined if
getaddrinfo() exists.  AI_PASSIVE is in RFC
2133, the first "Basic Socket Interface Extensions
for IPv6" RFC.

Regarding a previous patch to use AI_ADDRCONFIG:
all the getaddrinfo() implementations I know of
conform to either RFC 2133 or RFC 2553 and do
not take the AI_ADDRCONFIG flag.  (RFC 2553 has
AI_ADDRCONFIG but it is for getipnodebyname().)
It is risky to assume that when AI_ADDRCONFIG is
passed to these getaddrinfo() implementations,
getaddrinfo() will either silently ignore it or
fail with the EAI_BADFLAGS error.  It is better
to confirm that getaddrinfo() conforms to RFC
3493 before passing AI_ADDRCONFIG to it.

Wan-Teh


Re: [PATCH] Default Listen with IPv6 enabled incorrect

Posted by Justin Erenkrantz <ju...@erenkrantz.com>.
--On Wednesday, August 13, 2003 1:59 AM +0100 "Colm MacCarthaigh,,," 
<co...@stdlib.net> wrote:

> This is the real bug, Apache shouldn't be second-guessing getaddrinfo,
> APR's call_resolver is an excellent example of how to do it properly,
> AI_ADDRCONFIG is the key. Trouble is apr_sockaddr_info_get isnt
> calling it for us. This is an APR bug, see the attached patch.

Okay, I just committed variants of your patch to CVS that work for me on 
Solaris.  The biggest gotcha was setting servname to be non-NULL when hostname 
was NULL.

Thanks!  -- justin


Re: [PATCH] Default Listen with IPv6 enabled incorrect

Posted by "Colm MacCarthaigh,,," <co...@stdlib.net>.
(Cc:ing dev@apr now, because of APR patch)

On Tue, Aug 12, 2003 at 10:12:45AM -0700, Justin Erenkrantz wrote:
> --On Tuesday, August 12, 2003 5:58 PM +0100 "Colm MacCarthaigh,,," 
> <co...@stdlib.net> wrote:
> 
> >Even lo0 ? That's hard ;)
> 
> % ifconfig -a6
> %

As an asside I maintain that this is a broken system configuration, it's 
just as if you had IPv4 built in, but chose not to configure any IPv4 
addresses. What would have Apache do in such a situation ? Surely exiting 
is appropriate ...

But since you're less wrong than I am on this one, using AI_ADDRCONFIG
is best. This will weed out the problem.

But just to make clear I think "Listen 80" *really* needs to mean 
"Listen on port 80", not "Listen on port 80 in IPv4 only" :)

> >if getaddrinfo for PF_UNSPEC returns '::' in this situation
> >then it's really a lib(c|socket|nsl) bug, it does this on
> >Linux aswell, but the KAME implementation (and I believe windows)
> >have it fixed.
> 
> No, the OS is not returning '::'.  We're not using PF_UNSPEC, but 
> hard-coding PF_INET6.  (AF_INET6, AP_INET6, whatever the #define is.)

This is the real bug, Apache shouldnt be second-guessing getaddrinfo,
APR's call_resolver is an excellent example of how to do it properly,
AI_ADDRCONFIG is the key. Trouble is apr_sockaddr_info_get isnt 
calling it for us. This is an APR bug, see the attached patch.

> In alloc_listener, we're hardcoding '::' and PF_INET6 unconditionally if 
> the OS supports IPv6 (as determined by find_default_family).  (See the 
> !addr branch.)

It's not as broken as it seems, it does:

254   apr_sockaddr_info_get(&sa, NULL, APR_INET6, 0, 0, p) == APR_SUCCESS

So it *should* be valid. Problem is it *always* returns APR_SUCCESS
for a NULL hostname :(  Line 583 of apr/network_io/unix/sockaddr.c
is the real problem.

> I have a hunch that we may be able to create ephemeral ports (NULL address 
> passed in) without a configured IPv6 interface on Solaris.  Which strikes 
> me as not being totally wrong on Solaris's part.
> 
> I still maintain that my patch should be applied.  Let PF_UNSPEC figure it 
> out.

But your patch didnt do this, it just blindly returned 0.0.0.0. This
would break literally hundreds of peoples configs!

APR patch attached, it should fix your problem. I don't
have any systems I can configure easily into the state you
describe, so I can't test it properly just yet.

What should happen:
apr_sockaddr_info will call find_addresses, which will call
call_resolver which will have AI_ADDRCONFIG dutifuly set. So
if apply the patch , the problem should go away.

This all leaves listen.c bigger than it needs to be. So there's
changes in the patch for that too. The original find_default_family
didnt even compile for me anyway ;) The changes to listen.c create
one very slight logic problem in that:

 "Listen 80
  Listen 0.0.0.0 80"

will now result in a failure of apache to start because binding
to the socket twice will fail, wheras previously the dupe would
have been cought. I don't think this is a major problem.

Now, the extra cookie that we all deserve. This all shows up
a massive problem with apr_socket_create, it only creates
one socket. But apr_sockaddr_info_get returns a linked
list to many. It's allowable for AI_PASSIVE to return both
:: and 0.0.0.0, for example, or for round-robin DNS records
to return multiple addresses and this isnt handled properly.
My head hurts already.

There really needs to be an APR call that means: "walk this
linked list and creete/bind sockets for each node."

-- 
Colm MacCárthaigh                        Public Key: colm+pgp@stdlib.net
colm@stdlib.net					  http://www.stdlib.net/

Re: [PATCH] Default Listen with IPv6 enabled incorrect

Posted by "Colm MacCarthaigh,,," <co...@stdlib.net>.
(Cc:ing dev@apr now, because of APR patch)

On Tue, Aug 12, 2003 at 10:12:45AM -0700, Justin Erenkrantz wrote:
> --On Tuesday, August 12, 2003 5:58 PM +0100 "Colm MacCarthaigh,,," 
> <co...@stdlib.net> wrote:
> 
> >Even lo0 ? That's hard ;)
> 
> % ifconfig -a6
> %

As an asside I maintain that this is a broken system configuration, it's 
just as if you had IPv4 built in, but chose not to configure any IPv4 
addresses. What would have Apache do in such a situation ? Surely exiting 
is appropriate ...

But since you're less wrong than I am on this one, using AI_ADDRCONFIG
is best. This will weed out the problem.

But just to make clear I think "Listen 80" *really* needs to mean 
"Listen on port 80", not "Listen on port 80 in IPv4 only" :)

> >if getaddrinfo for PF_UNSPEC returns '::' in this situation
> >then it's really a lib(c|socket|nsl) bug, it does this on
> >Linux aswell, but the KAME implementation (and I believe windows)
> >have it fixed.
> 
> No, the OS is not returning '::'.  We're not using PF_UNSPEC, but 
> hard-coding PF_INET6.  (AF_INET6, AP_INET6, whatever the #define is.)

This is the real bug, Apache shouldnt be second-guessing getaddrinfo,
APR's call_resolver is an excellent example of how to do it properly,
AI_ADDRCONFIG is the key. Trouble is apr_sockaddr_info_get isnt 
calling it for us. This is an APR bug, see the attached patch.

> In alloc_listener, we're hardcoding '::' and PF_INET6 unconditionally if 
> the OS supports IPv6 (as determined by find_default_family).  (See the 
> !addr branch.)

It's not as broken as it seems, it does:

254   apr_sockaddr_info_get(&sa, NULL, APR_INET6, 0, 0, p) == APR_SUCCESS

So it *should* be valid. Problem is it *always* returns APR_SUCCESS
for a NULL hostname :(  Line 583 of apr/network_io/unix/sockaddr.c
is the real problem.

> I have a hunch that we may be able to create ephemeral ports (NULL address 
> passed in) without a configured IPv6 interface on Solaris.  Which strikes 
> me as not being totally wrong on Solaris's part.
> 
> I still maintain that my patch should be applied.  Let PF_UNSPEC figure it 
> out.

But your patch didnt do this, it just blindly returned 0.0.0.0. This
would break literally hundreds of peoples configs!

APR patch attached, it should fix your problem. I don't
have any systems I can configure easily into the state you
describe, so I can't test it properly just yet.

What should happen:
apr_sockaddr_info will call find_addresses, which will call
call_resolver which will have AI_ADDRCONFIG dutifuly set. So
if apply the patch , the problem should go away.

This all leaves listen.c bigger than it needs to be. So there's
changes in the patch for that too. The original find_default_family
didnt even compile for me anyway ;) The changes to listen.c create
one very slight logic problem in that:

 "Listen 80
  Listen 0.0.0.0 80"

will now result in a failure of apache to start because binding
to the socket twice will fail, wheras previously the dupe would
have been cought. I don't think this is a major problem.

Now, the extra cookie that we all deserve. This all shows up
a massive problem with apr_socket_create, it only creates
one socket. But apr_sockaddr_info_get returns a linked
list to many. It's allowable for AI_PASSIVE to return both
:: and 0.0.0.0, for example, or for round-robin DNS records
to return multiple addresses and this isnt handled properly.
My head hurts already.

There really needs to be an APR call that means: "walk this
linked list and creete/bind sockets for each node."

-- 
Colm MacCárthaigh                        Public Key: colm+pgp@stdlib.net
colm@stdlib.net					  http://www.stdlib.net/

Re: [PATCH] Default Listen with IPv6 enabled incorrect

Posted by Justin Erenkrantz <ju...@erenkrantz.com>.
--On Tuesday, August 12, 2003 5:58 PM +0100 "Colm MacCarthaigh,,," 
<co...@stdlib.net> wrote:

> Even lo0 ? That's hard ;)

% ifconfig -a6
%

> if getaddrinfo for PF_UNSPEC returns '::' in this situation
> then it's really a lib(c|socket|nsl) bug, it does this on
> Linux aswell, but the KAME implementation (and I believe windows)
> have it fixed.

No, the OS is not returning '::'.  We're not using PF_UNSPEC, but hard-coding 
PF_INET6.  (AF_INET6, AP_INET6, whatever the #define is.)

In alloc_listener, we're hardcoding '::' and PF_INET6 unconditionally if the 
OS supports IPv6 (as determined by find_default_family).  (See the !addr 
branch.)

I have a hunch that we may be able to create ephemeral ports (NULL address 
passed in) without a configured IPv6 interface on Solaris.  Which strikes me 
as not being totally wrong on Solaris's part.

I still maintain that my patch should be applied.  Let PF_UNSPEC figure it 
out.  -- justin

Re: [PATCH] Default Listen with IPv6 enabled incorrect

Posted by "Colm MacCarthaigh,,," <co...@stdlib.net>.
On Tue, Aug 12, 2003 at 09:44:36AM -0700, Justin Erenkrantz wrote:
> --On Tuesday, August 12, 2003 5:33 PM +0100 "Colm MacCarthaigh,,," 
> <co...@stdlib.net> wrote:
> 
> >This is good though, if v6 is available and we can't listen there
> >then it should exit!
> 
> Let me re-state what I think the root cause of this is:
> 
> IPv6 stack is available on Solaris
> No IPv6 interfaces are currently configured

Even lo0 ? That's hard ;)

if getaddrinfo for PF_UNSPEC returns '::' in this situation
then it's really a lib(c|socket|nsl) bug, it does this on
Linux aswell, but the KAME implementation (and I believe windows)
have it fixed.

It's probably worth working around, but tbh I'd be of the opinion
that v6 not binding is just a serious an error as having v4 support
configured and not having any ipv4 addresses. It's very much a 
broken system configuration.

> So, IPv6 *could* be available, but it isn't.  I think we're making the 
> assumption that if the OS provides an IPv6 stack that we *must* use IPv6. 
> That seems broken.  We should intelligently fail-over to IPv4. 

That's the job of getaddrinfo. By rights getaddrinfo should be
clever enough to return the correct linked list no matter what.
Pity it isnt :/

-- 
Colm MacCárthaigh                        Public Key: colm+pgp@stdlib.net
colm@stdlib.net					  http://www.stdlib.net/

Re: [PATCH] Default Listen with IPv6 enabled incorrect

Posted by Justin Erenkrantz <ju...@erenkrantz.com>.
--On Tuesday, August 12, 2003 5:33 PM +0100 "Colm MacCarthaigh,,," 
<co...@stdlib.net> wrote:

> This is good though, if v6 is available and we can't listen there
> then it should exit!

Let me re-state what I think the root cause of this is:

IPv6 stack is available on Solaris
No IPv6 interfaces are currently configured

So, IPv6 *could* be available, but it isn't.  I think we're making the 
assumption that if the OS provides an IPv6 stack that we *must* use IPv6. 
That seems broken.  We should intelligently fail-over to IPv4.  -- justin

Re: [PATCH] Default Listen with IPv6 enabled incorrect

Posted by "Colm MacCarthaigh,,," <co...@stdlib.net>.
On Tue, Aug 12, 2003 at 09:02:52AM -0700, Justin Erenkrantz wrote:
> Nope, it's getaddrinfo('::', AF_INET6, 0) that causes the failure.  Are we 
> sure that '::' is standard?  I couldn't find any documentation to support 
> that.

It's not standard, but there isnt an implementor out there who
doesnt use it. That said using it is still a bad idea, since
there's nothing that mandates an implementor to using that
address.

RFC3493 standardises in6addr_any and IN6ADDR_ANY_INIT, which
are much better suited to the purpose. 

> >It isn't quite that simple.  If there is a non-qualified address in the
> >config, we try to figure out if the box supports IPv6, and if it does then
> >we get an IPv6 listening socket for that port.
> 
> But, if the IPv6 fails, we should go back to IPv4.  Instead, we just exit.

This is good though, if v6 is available and we can't listen there
then it should exit!

> getaddrinfo(NULL, AF_INET6, 0)
> 
> works on Solaris, but:
> 
> getaddrinfo('::', AF_INET6, 0)

This is broken, definitely. 

-- 
Colm MacCárthaigh                        Public Key: colm+pgp@stdlib.net
colm@stdlib.net					  http://www.stdlib.net/

Re: [PATCH] Default Listen with IPv6 enabled incorrect

Posted by Justin Erenkrantz <ju...@erenkrantz.com>.
--On Tuesday, August 12, 2003 6:43 AM -0400 Jeff Trawick 
<tr...@attglobal.net> wrote:

> I wonder if this is related to Joe's recent change to
> apr_sockaddr_info_get(), where IPv6 won't be returned if the system doesn't
> support it.  Does reverting Joe's additional flag make any difference?
> (AI_ADDRCONFIG)  It probably does, since ISTR we're specifying AF_UNSPEC for
> the family, and family=AF_UNSPEC is where AI_ADDRCONFIG works its magic.
>
> If you back out the AI_ADDRCONFIG flag, is Apache able to get an IPv6 socket
> and handle incoming IPv4 connections when you have plain "listen ###"?

Nope.  I looked at that code bit and it doesn't execute.  When we enter that 
segment, we aren't AF_UNSPEC, but AF_INET6 because find_default_family thinks 
we have IPv6 available.  So, the AI_ADDRCONFIG code doesn't execute at all.

> I guess find_default_family() has to make use of the fact that
> getaddrinfo("::", AF_UNSPEC, AI_ADDRCONFIG) will fail now in some scenarios
> where everything was happy before.

Nope, it's getaddrinfo('::', AF_INET6, 0) that causes the failure.  Are we 
sure that '::' is standard?  I couldn't find any documentation to support that.

> It isn't quite that simple.  If there is a non-qualified address in the
> config, we try to figure out if the box supports IPv6, and if it does then
> we get an IPv6 listening socket for that port.

But, if the IPv6 fails, we should go back to IPv4.  Instead, we just exit.

> Somehow I don't see the badness :)  The philosophy has been:
>
> If your box is set up for IPv4+IPv6, Apache by default will handle
> connections over either; if your box is set up for just IPv4, Apache by
> default will notice that.  Isn't that goodness?

No.  Because it's broken.  ;-)

> If the current problem is that find_default_family() needs to be smarter
> since AI_ADDRCONFIG makes some of the IPv6 logic fail where it didn't fail
> before, then let's make it smarter.

Nope.  find_default_family isn't really at fault.  Specifically, it is that:

getaddrinfo(NULL, AF_INET6, 0)

works on Solaris, but:

getaddrinfo('::', AF_INET6, 0)

returns the EAI 8 code.  find_default_family uses the first.  When no address 
is specified, the listener is attempted with the second.  And, when the second 
call fails, httpd just gives up rather than trying to fail back to IPv4.

I have no earthly idea why I'm only seeing this now.  Perhaps I never enabled 
IPv6 before now on Solaris.  -- justin

Re: [PATCH] Default Listen with IPv6 enabled incorrect

Posted by Jeff Trawick <tr...@attglobal.net>.
Justin Erenkrantz wrote:

> When I updated to HEAD just now on my Solaris box, httpd wouldn't start
> with this:
> 
> [Mon Aug 11 19:10:08 2003] [crit] (EAI 8)host/servname not known:
> alloc_listener: failed to set up sockaddr for ::

I wonder if this is related to Joe's recent change to 
apr_sockaddr_info_get(), where IPv6 won't be returned if the system 
doesn't support it.  Does reverting Joe's additional flag make any 
difference?  (AI_ADDRCONFIG)  It probably does, since ISTR we're 
specifying AF_UNSPEC for the family, and family=AF_UNSPEC is where 
AI_ADDRCONFIG works its magic.

If you back out the AI_ADDRCONFIG flag, is Apache able to get an IPv6 
socket and handle incoming IPv4 connections when you have plain "listen 
###"?

I guess find_default_family() has to make use of the fact that 
getaddrinfo("::", AF_UNSPEC, AI_ADDRCONFIG) will fail now in some 
scenarios where everything was happy before.

> Something that simple should work.  Yet, it looks like if we have IPv6
> compiled in, we will assume that all non-qualified addresses are IPv6.
> That seems wrong.  (I have no idea why this never appeared before.)

It isn't quite that simple.  If there is a non-qualified address in the 
config, we try to figure out if the box supports IPv6, and if it does 
then we get an IPv6 listening socket for that port.

> Any arguments on tossing the find_default_family function altogether, and
> just going to 0.0.0.0 when the addr isn't specified?  If you want IPv6, you
> should explicitly specify it with 'Listen ::8080' or something, but
> assuming that since we have IPv6 available that the unqualified addresses
> must be IPv6 doesn't make sense and is badness.  -- justin

Somehow I don't see the badness :)  The philosophy has been:

If your box is set up for IPv4+IPv6, Apache by default will handle 
connections over either; if your box is set up for just IPv4, Apache by 
default will notice that.  Isn't that goodness?

If the current problem is that find_default_family() needs to be smarter 
since AI_ADDRCONFIG makes some of the IPv6 logic fail where it didn't 
fail before, then let's make it smarter.