apr-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Colm MacCarthaigh <c...@stdlib.net>
Subject Re: [Patch] IPv6 on Tru64 broken
Date Mon, 25 Aug 2003 17:00:22 GMT
On Mon, Aug 25, 2003 at 12:19:27PM -0400, Jeff Trawick wrote:
> >IPv6 with Apache on tru64 has been broken for a while now, and I finally 
> >got round to figuring out what it was. It appears that Tru64's
> >getaddrinfo returns ai_addrlen of 32 for AF_INET6 address, but that
> >sizeof(struct sockaddr_in6) is 28.
> >
> >This meant that apr_sockaddr_vars_set() was blindly setting salen
> >to 28, and then later when Apache called bind( , , 28) Tru64 bombed
> >out in unpleasant error land. Patch attached. 
> 
> I'm not sure I would use the word "blindly", as we're using 
> sizeof(sockaddr_in6). 

True, but the return of getaddrinfo is being ignored is what I mean.

> If getaddrinfo() returns IPv6 addresses larger 
> than that, we're hosed at that point and shouldn't be copying into the 
> apr_sockaddr_info_t anyway.

We get away with it, just about. Allthough the full length is
copied; 

    429         new_sa->pool = p;
    430         memcpy(&new_sa->sa, ai->ai_addr, ai->ai_addrlen);
    431         apr_sockaddr_vars_set(new_sa, ai->ai_family, port);

it's salen itself that gets overwritten. This then gets reset back
to a sensible value with the assignment in vars_set and the patch.
It's moderately bold, but it works out fine.

Now, back to the reason why it does any of this; bind() is expecting
a struct sockaddr_in6.sin6_addr to be passed, which would make the
extra 4 bytes it's looking for correspond to sockaddr_in6.sin6_scope_id. 
This makes sense in a freaky-dec-developer kind of way, though it really 
is a bug. 

I'm guessing it means that the devlopers originally thought it might 
be useful to allow people to bind() to scoped addresses , and to do 
this you'd need an interface index (for the unitiated; IPv6 scoped 
addresses are interface-specific).

Now, because in Apache the address we pass is always global unicast
and IN6_IS_ADDR_LINKLOCAL/IN6_IS_ADDR_SITELOCAL/IN6_IS_ADDR_MULTICAST
are never going to evaluate to true, bind() never bothers looking
for the scope id. Which is a good thing since binding to the 32nd
system interface would probably not be the desired behaviour.

> Isn't the first step to see why getaddrinfo() is returning IPv6 
> addresses larger than sizeof(sockaddr_in6) and take it from there? 

I really should have included that. It's an OS bug, but it's 
a consistent one. bind() simply fails if passed 28, and works
fine with 32, so we might aswell pass it what it wants. I 
have it running right now at http://listserv.heanet.ie/ .

Actually now that I think about it, maybe the patch below is a
better idea. 

> (Alternatively, why am I confused?)

I am too, but I've been playing with it all day now and it really
does behave like this. Nothing on DU suprises me anymore.

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

Mime
View raw message