diff options
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | posix/Makefile | 3 | ||||
-rw-r--r-- | posix/tst-getaddrinfo2.c | 75 | ||||
-rw-r--r-- | sysdeps/posix/getaddrinfo.c | 41 |
4 files changed, 116 insertions, 12 deletions
diff --git a/ChangeLog b/ChangeLog index 371d384d43..5a248c3242 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2004-09-26 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/posix/getaddrinfo.c (getaddrinfo): Remove incorrect + requirement on socktype and protocol. + (gaih_inet): If numeric port number is given, return records for all + possible socket types. + * posix/tst-getaddrinfo2.c: New file. + * posix/Makefile (tests): Add tst-getaddrinfo2. [BZ #358] + 2004-09-25 Ulrich Drepper <drepper@redhat.com> * locale/loadlocale.c (_nl_intern_locale_data): Recognize LC_CTYPE diff --git a/posix/Makefile b/posix/Makefile index 766c1dd7f7..82d35378d1 100644 --- a/posix/Makefile +++ b/posix/Makefile @@ -81,7 +81,8 @@ tests := tstgetopt testfnm runtests runptests \ bug-regex17 bug-regex18 bug-regex19 bug-regex20 \ bug-regex21 bug-regex22 bug-regex23 tst-nice tst-nanosleep \ transbug tst-rxspencer tst-pcre tst-boost \ - bug-ga1 tst-vfork1 tst-vfork2 tst-waitid + bug-ga1 tst-vfork1 tst-vfork2 tst-waitid \ + tst-getaddrinfo2 xtests := bug-ga2 ifeq (yes,$(build-shared)) test-srcs := globtest diff --git a/posix/tst-getaddrinfo2.c b/posix/tst-getaddrinfo2.c new file mode 100644 index 0000000000..b0bce5925c --- /dev/null +++ b/posix/tst-getaddrinfo2.c @@ -0,0 +1,75 @@ +/* Test by David L Stevens <dlstevens@us.ibm.com> [BZ #358] */ +#include <errno.h> +#include <netdb.h> +#include <unistd.h> +#include <sys/socket.h> + +static int +do_test (void) +{ + const char portstr[] = "583"; + int port = atoi (portstr); + struct addrinfo hints, *aires, *pai; + int rv; + int res = 1; + + memset (&hints, 0, sizeof (hints)); + hints.ai_family = AF_INET; + rv = getaddrinfo (NULL, portstr, &hints, &aires); + if (rv == 0) + { + struct sockaddr_in *psin = 0; + int got_tcp, got_udp; + int err = 0; + + got_tcp = got_udp = 0; + for (pai = aires; pai; pai = pai->ai_next) + { + printf ("ai_family=%d, ai_addrlen=%d, ai_socktype=%d", + (int) pai->ai_family, (int) pai->ai_addrlen, + (int) pai->ai_socktype); + if (pai->ai_family == AF_INET) + printf (", port=%d", + ntohs (((struct sockaddr_in *) pai->ai_addr)->sin_port)); + puts (""); + + err |= pai->ai_family != AF_INET; + err |= pai->ai_addrlen != sizeof (struct sockaddr_in); + err |= pai->ai_addr == 0; + if (pai->ai_family == AF_INET) + err |= + ntohs (((struct sockaddr_in *) pai->ai_addr)->sin_port) != port; + got_tcp |= pai->ai_socktype == SOCK_STREAM; + got_udp |= pai->ai_socktype == SOCK_DGRAM; + if (err) + break; + } + if (err) + { + printf ("FAIL getaddrinfo IPv4 socktype 0,513: " + "fam %d alen %d addr 0x%08X addr/fam %d " + "addr/port %d H[%d]\n", + pai->ai_family, pai->ai_addrlen, psin, + psin ? psin->sin_family : 0, + psin ? psin->sin_port : 0, + psin ? htons (psin->sin_port) : 0); + } + else if (got_tcp && got_udp) + { + printf ("SUCCESS getaddrinfo IPv4 socktype 0,513\n"); + res = 0; + } + else + printf ("FAIL getaddrinfo IPv4 socktype 0,513 TCP %d" + " UDP %d\n", got_tcp, got_udp); + freeaddrinfo (aires); + } + else + printf ("FAIL getaddrinfo IPv4 socktype 0,513 returns %d " + "(\"%s\")\n", rv, gai_strerror (rv)); + + return res; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c index 225c1a1088..20e60de393 100644 --- a/sysdeps/posix/getaddrinfo.c +++ b/sysdeps/posix/getaddrinfo.c @@ -445,12 +445,35 @@ gaih_inet (const char *name, const struct gaih_service *service, } else { - st = __alloca (sizeof (struct gaih_servtuple)); - st->next = NULL; - st->socktype = tp->socktype; - st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY) - ? req->ai_protocol : tp->protocol); - st->port = htons (service->num); + if (req->ai_socktype || req->ai_protocol) + { + st = __alloca (sizeof (struct gaih_servtuple)); + st->next = NULL; + st->socktype = tp->socktype; + st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY) + ? req->ai_protocol : tp->protocol); + st->port = htons (service->num); + } + else + { + /* Neither socket type nor protocol is set. Return all + socket types we know about. */ + struct gaih_servtuple **lastp = &st; + for (tp = gaih_inet_typeproto + 1; tp->name[0]; ++tp) + if ((tp->protoflag & GAI_PROTO_NOSERVICE) == 0) + { + struct gaih_servtuple *newp; + + newp = __alloca (sizeof (struct gaih_servtuple)); + newp->next = NULL; + newp->socktype = tp->socktype; + newp->protocol = tp->protocol; + newp->port = htons (service->num); + + *lastp = newp; + lastp = &newp->next; + } + } } } else if (req->ai_socktype || req->ai_protocol) @@ -1493,11 +1516,7 @@ getaddrinfo (const char *name, const char *service, gaih_service.num = -1; } - else - /* Can't specify a numerical socket unless a protocol family was - given. */ - if (hints->ai_socktype == 0 && hints->ai_protocol == 0) - return EAI_SERVICE; + pservice = &gaih_service; } else |