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.
Since preserving the value for addrlen returned by getaddrinfo is
a good idea in any event I havn't made this #ifdef OSF1, there
may be more systems which rely on this behaviour and there's nothing
in the standards prohibiting it.
Also attached is a C prog to test which systems behave in this
manner;
bash-2.05a$ uname -a
OSF1 athene.heanet.ie V5.1 732 alpha
bash-2.05a$ gcc -o madness madness.c
bash-2.05a$ ./madness
sizeof(struct sockaddr_in6) = 28
addrinfo->ai_addrlen = 32
--
Colm MacC�rthaigh Public Key: [EMAIL PROTECTED]
[EMAIL PROTECTED] http://www.stdlib.net/
Index: srclib/apr/network_io/unix/sockaddr.c
===================================================================
RCS file: /home/cvspublic/apr/network_io/unix/sockaddr.c,v
retrieving revision 1.42
diff -u -r1.42 sockaddr.c
--- srclib/apr/network_io/unix/sockaddr.c 15 Aug 2003 02:21:55 -0000
1.42
+++ srclib/apr/network_io/unix/sockaddr.c 25 Aug 2003 15:27:53 -0000
@@ -429,6 +429,14 @@
new_sa->pool = p;
memcpy(&new_sa->sa, ai->ai_addr, ai->ai_addrlen);
apr_sockaddr_vars_set(new_sa, ai->ai_family, port);
+
+ /* Over-rule the value set by apr_sockaddr_vars_set;
+ * sizeof(struct sockaddr_in6) != ai_addrlen for
+ * AF_INET6 on some systems (Tru64). This would lead
+ * to an error when we try to bind() without the right
+ * Address Length.
+ */
+ new_sa->salen = ai->ai_addrlen;
if (!prev_sa) { /* first element in new list */
if (hostname) {
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <stdio.h>
int main(int argc, char **argv)
{
struct addrinfo hints;
struct addrinfo * res;
int error;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_INET6;
hints.ai_flags = AI_PASSIVE;
hints.ai_socktype = SOCK_STREAM;
if ((error = getaddrinfo(NULL, "80", &hints, &res)) < 0)
{
fprintf(stderr, "%s: error in getaddrinfo: %s\n", argv[0], gai_strerror(error));
exit(1);
}
printf("sizeof(struct sockaddr_in6) = %d\n", sizeof(struct sockaddr_in6));
printf("addrinfo->ai_addrlen = %d\n", res->ai_addrlen);
return 0;
}