Return-Path: Delivered-To: apmail-apr-dev-archive@apr.apache.org Received: (qmail 23184 invoked by uid 500); 25 Aug 2003 15:52:42 -0000 Mailing-List: contact dev-help@apr.apache.org; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: Delivered-To: mailing list dev@apr.apache.org Received: (qmail 23048 invoked from network); 25 Aug 2003 15:52:40 -0000 Date: Mon, 25 Aug 2003 16:52:38 +0100 From: Colm MacCarthaigh To: dev@apr.apache.org Subject: [Patch] IPv6 on Tru64 broken Message-ID: <20030825155238.GA1579@castlerea.stdlib.net.> Reply-To: colm@stdlib.net Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="IJpNTDwzlM2Ie8A6" Content-Disposition: inline Content-Transfer-Encoding: 8bit User-Agent: Mutt/1.3.28i Sender: "Colm MacCarthaigh,,," X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N --IJpNTDwzlM2Ie8A6 Content-Type: text/plain; charset=iso-8859-15 Content-Disposition: inline Content-Transfer-Encoding: 8bit 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: colm+pgp@stdlib.net colm@stdlib.net http://www.stdlib.net/ --IJpNTDwzlM2Ie8A6 Content-Type: text/plain; charset=iso-8859-15 Content-Disposition: attachment; filename="salen.patch" 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) { --IJpNTDwzlM2Ie8A6 Content-Type: text/x-csrc; charset=iso-8859-15 Content-Disposition: attachment; filename="madness.c" #include #include #include #include #include #include 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; } --IJpNTDwzlM2Ie8A6--