]> The Tcpdump Group git mirrors - tcpdump/commitdiff
bring in latest kame getaddrinfo (couple of bug fixes).
authoritojun <itojun>
Wed, 19 Jan 2000 04:42:20 +0000 (04:42 +0000)
committeritojun <itojun>
Wed, 19 Jan 2000 04:42:20 +0000 (04:42 +0000)
more portability checks for getaddrinfo.

checked on: netbsd141, kame/netbsd141

configure.in
missing/getaddrinfo.c
missing/getnameinfo.c

index b8523797bceb094576dfaf773b001739d30e5e37..aa1c5090db9716151a4692659da237cbd1451d8a 100644 (file)
@@ -1,4 +1,4 @@
-dnl @(#) $Header: /tcpdump/master/tcpdump/configure.in,v 1.102 2000-01-19 04:34:55 itojun Exp $ (LBL)
+dnl @(#) $Header: /tcpdump/master/tcpdump/configure.in,v 1.103 2000-01-19 04:42:20 itojun Exp $ (LBL)
 dnl
 dnl Copyright (c) 1994, 1995, 1996, 1997
 dnl    The Regents of the University of California.  All rights reserved.
@@ -6,7 +6,7 @@ dnl
 dnl Process this file with autoconf to produce a configure script.
 dnl
 
-AC_REVISION($Revision: 1.102 $)
+AC_REVISION($Revision: 1.103 $)
 AC_PREREQ(2.13)
 AC_INIT(tcpdump.c)
 
@@ -216,6 +216,7 @@ if test "$ipv6" = "yes" -a "$ipv6lib" != "none"; then
 fi
 
 
+AC_CHECK_FUNCS(getaddrinfo, [dnl
 AC_MSG_CHECKING(getaddrinfo bug)
 AC_TRY_RUN([
 #include <sys/types.h>
@@ -316,7 +317,7 @@ buggygetaddrinfo=no,
 AC_MSG_RESULT(buggy)
 buggygetaddrinfo=yes,
 AC_MSG_RESULT(buggy)
-buggygetaddrinfo=yes)
+buggygetaddrinfo=yes)], [buggygetaddrinfo=yes])
 
 if test "$buggygetaddrinfo" = "yes"; then
        if test "$ipv6" = "yes" -a "$ipv6type" != "linux"; then
index d45b14d7659cf67b658d6a1fd2d82ecbbccae0ad..bfd150c9178f843f8b06bc8115ae8f606e8357f7 100644 (file)
  * - Return values.  There are nonstandard return values defined and used
  *   in the source code.  This is because RFC2553 is silent about which error
  *   code must be returned for which situation.
- * - PF_UNSPEC case would be handled in getipnodebyname() with the AI_ALL flag.
+ * Note:
+ * - We use getipnodebyname() just for thread-safeness.  There's no intent
+ *   to let it do PF_UNSPEC (actually we never pass PF_UNSPEC to
+ *   getipnodebyname().
+ * - The code filters out AFs that are not supported by the kernel,
+ *   when globbing NULL hostname (to loopback, or wildcard).  Is it the right
+ *   thing to do?  What is the relationship with post-RFC2553 AI_ADDRCONFIG
+ *   in ai_flags?
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif 
 
 #ifndef lint
 static const char rcsid[] =
-     "@(#) $Header: /tcpdump/master/tcpdump/missing/getaddrinfo.c,v 1.7 2000-01-09 21:35:44 fenner Exp $";
+     "@(#) $Header: /tcpdump/master/tcpdump/missing/getaddrinfo.c,v 1.8 2000-01-19 04:42:21 itojun Exp $";
 #endif
 
 #include <sys/types.h>
@@ -71,17 +78,17 @@ static const char rcsid[] =
 #include "cdecl_ext.h"
 #endif 
 
-#if 0
 #ifndef HAVE_U_INT32_T
 #include "bittypes.h"
 #endif 
-#endif
 
 #ifndef HAVE_SOCKADDR_STORAGE
 #include "sockstorage.h"
 #endif 
 
+#ifndef HAVE_ADDRINFO
 #include "addrinfo.h"
+#endif
 
 #if defined(__KAME__) && defined(INET6)
 # define FAITH
@@ -374,12 +381,13 @@ getaddrinfo(hostname, servname, hints, res)
            ) {
                ai0 = *pai;
 
-               if (pai->ai_family == PF_UNSPEC)
+               if (pai->ai_family == PF_UNSPEC) {
 #ifdef PF_INET6
                        pai->ai_family = PF_INET6;
 #else
                        pai->ai_family = PF_INET;
 #endif
+               }
                error = get_portmatch(pai, servname);
                if (error)
                        ERR(error);
@@ -507,13 +515,16 @@ explore_fqdn(pai, hostname, servname, res)
        const char *servname;
        struct addrinfo **res;
 {
-       int s;
        struct hostent *hp;
        int h_error;
        int af;
+       char **aplist = NULL, *apbuf = NULL;
        char *ap;
        struct addrinfo sentinel, *cur;
        int i;
+#ifndef USE_GETIPNODEBY
+       int naddrs;
+#endif
        const struct afd *afd;
        int error;
 
@@ -522,13 +533,10 @@ explore_fqdn(pai, hostname, servname, res)
        cur = &sentinel;
 
        /*
-        * filter out AFs that are not supported by the kernel
-        * XXX errno?
+        * Do not filter unsupported AFs here.  We need to honor content of
+        * databases (/etc/hosts, DNS and others).  Otherwise we cannot
+        * replace gethostbyname() by getaddrinfo().
         */
-       s = socket(pai->ai_family, SOCK_DGRAM, 0);
-       if (s < 0)
-               return 0;
-       close(s);
 
        /*
         * if the servname does not match socktype/protocol, ignore it.
@@ -538,15 +546,16 @@ explore_fqdn(pai, hostname, servname, res)
 
        afd = find_afd(pai->ai_family);
 
+       /*
+        * post-RFC2553: should look at (pai->ai_flags & AI_ADDRCONFIG)
+        * rather than hardcoding it.  we may need to add AI_ADDRCONFIG
+        * handling code by ourselves in case we don't have getipnodebyname().
+        */
 #ifdef USE_GETIPNODEBY
        hp = getipnodebyname(hostname, pai->ai_family, AI_ADDRCONFIG, &h_error);
-#elif defined(HAVE_GETHOSTBYNAME2)
-       hp = gethostbyname2(hostname, pai->ai_family);
-#ifdef HAVE_H_ERRNO
-       h_error = h_errno;
 #else
-       h_error = EINVAL;
-#endif
+#ifdef HAVE_GETHOSTBYNAME2
+       hp = gethostbyname2(hostname, pai->ai_family);
 #else
        if (pai->ai_family != AF_INET)
                return 0;
@@ -556,7 +565,8 @@ explore_fqdn(pai, hostname, servname, res)
 #else
        h_error = EINVAL;
 #endif
-#endif
+#endif /*HAVE_GETHOSTBYNAME2*/
+#endif /*USE_GETIPNODEBY*/
 
        if (hp == NULL) {
                switch (h_error) {
@@ -585,10 +595,38 @@ explore_fqdn(pai, hostname, servname, res)
        if (hp == NULL)
                goto free;
 
-       for (i = 0; hp->h_addr_list[i] != NULL; i++) {
+#ifdef USE_GETIPNODEBY
+       aplist = hp->h_addr_list;
+#else
+       /*
+        * hp will be overwritten if we use gethostbyname2().
+        * always deep copy for simplification.
+        */
+       for (naddrs = 0; hp->h_addr_list[naddrs] != NULL; naddrs++)
+               ;
+       naddrs++;
+       aplist = (char **)malloc(sizeof(aplist[0]) * naddrs);
+       apbuf = (char *)malloc(hp->h_length * naddrs);
+       if (aplist == NULL || apbuf == NULL) {
+               error = EAI_MEMORY;
+               goto free;
+       }
+       memset(aplist, 0, sizeof(aplist[0]) * naddrs);
+       for (i = 0; i < naddrs; i++) {
+               if (hp->h_addr_list[i] == NULL) {
+                       aplist[i] = NULL;
+                       continue;
+               }
+               memcpy(&apbuf[i * hp->h_length], hp->h_addr_list[i],
+                       hp->h_length);
+               aplist[i] = &apbuf[i * hp->h_length];
+       }
+#endif
+
+       for (i = 0; aplist[i] != NULL; i++) {
                af = hp->h_addrtype;
-               ap = hp->h_addr_list[i];
-#ifdef INET6
+               ap = aplist[i];
+#ifdef AF_INET6
                if (af == AF_INET6
                 && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) {
                        af = AF_INET;
@@ -630,6 +668,10 @@ free:
        if (hp)
                freehostent(hp);
 #endif
+       if (aplist)
+               free(aplist);
+       if (apbuf)
+               free(apbuf);
        if (sentinel.ai_next)
                freeaddrinfo(sentinel.ai_next);
        return error;
@@ -662,9 +704,11 @@ explore_null(pai, hostname, servname, res)
         * XXX errno?
         */
        s = socket(pai->ai_family, SOCK_DGRAM, 0);
-       if (s < 0)
-               return 0;
-       close(s);
+       if (s < 0) {
+               if (errno != EMFILE)
+                       return 0;
+       } else
+               close(s);
 
        /*
         * if the servname does not match socktype/protocol, ignore it.
@@ -835,6 +879,10 @@ explore_numeric_scope(pai, hostname, servname, res)
 #ifdef INET6
        case AF_INET6:
                scope = if_nametoindex(cp);
+               if (scope == 0) {
+                       free(hostname2);
+                       return (EAI_NONAME);
+               }
                break;
 #endif
        }
@@ -866,9 +914,10 @@ get_name(addr, afd, res, numaddr, pai, servname)
        const struct addrinfo *pai;
        const char *servname;
 {
-       struct hostent *hp;
-       struct addrinfo *cur;
+       struct hostent *hp = NULL;
+       struct addrinfo *cur = NULL;
        int error = 0;
+       char *ap = NULL, *cn = NULL;
 #ifdef USE_GETIPNODEBY
        int h_error;
 
@@ -877,9 +926,28 @@ get_name(addr, afd, res, numaddr, pai, servname)
        hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
 #endif
        if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
+#ifdef USE_GETIPNODEBY
                GET_AI(cur, afd, hp->h_addr_list[0]);
                GET_PORT(cur, servname);
                GET_CANONNAME(cur, hp->h_name);
+#else
+               /* hp will be damaged if we use gethostbyaddr() */
+               if ((ap = (char *)malloc(hp->h_length)) == NULL) {
+                       error = EAI_MEMORY;
+                       goto free;
+               }
+               memcpy(ap, hp->h_addr_list[0], hp->h_length);
+               if ((cn = strdup(hp->h_name)) == NULL) {
+                       error = EAI_MEMORY;
+                       goto free;
+               }
+
+               GET_AI(cur, afd, ap);
+               GET_PORT(cur, servname);
+               GET_CANONNAME(cur, cn);
+               free(ap); ap = NULL;
+               free(cn); cn = NULL;
+#endif
        } else {
                GET_AI(cur, afd, numaddr);
                GET_PORT(cur, servname);
@@ -894,11 +962,14 @@ get_name(addr, afd, res, numaddr, pai, servname)
  free:
        if (cur)
                freeaddrinfo(cur);
+       if (ap)
+               free(ap);
+       if (cn)
+               free(cn);
 #ifdef USE_GETIPNODEBY
        if (hp)
                freehostent(hp);
 #endif
- /* bad: */
        *res = NULL;
        return error;
 }
@@ -950,6 +1021,7 @@ get_portmatch(ai, servname)
        const struct addrinfo *ai;
        const char *servname;
 {
+
        /* get_port does not touch first argument. when matchonly == 1. */
        return get_port((struct addrinfo *)ai, servname, 1);
 }
@@ -967,12 +1039,15 @@ get_port(ai, servname, matchonly)
 
        if (servname == NULL)
                return 0;
-       if (ai->ai_family != AF_INET
+       switch (ai->ai_family) {
+       case AF_INET:
 #ifdef AF_INET6
-           && ai->ai_family != AF_INET6
+       case AF_INET6:
 #endif
-           )
+               break;
+       default:
                return 0;
+       }
 
        switch (ai->ai_socktype) {
        case SOCK_RAW:
index b7e99c2666ce7314f6dded65b4b9195ed282944c..d3df788b8a6bd798dbcfefa5e3f0823019467a48 100644 (file)
  * - Thread safe-ness must be checked
  * - Return values.  There seems to be no standard for return value (RFC2553)
  *   but INRIA implementation returns EAI_xxx defined for getaddrinfo().
+ * - RFC2553 says that we should raise error on short buffer.  X/Open says
+ *   we need to truncate the result.  We obey RFC2553 (and X/Open should be
+ *   modified).
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif 
 
 #ifndef lint
 static const char rcsid[] =
-     "@(#) $Header: /tcpdump/master/tcpdump/missing/getnameinfo.c,v 1.4 2000-01-09 21:35:44 fenner Exp $";
+     "@(#) $Header: /tcpdump/master/tcpdump/missing/getnameinfo.c,v 1.5 2000-01-19 04:42:21 itojun Exp $";
 #endif
 
 #include <sys/types.h>
@@ -59,7 +62,9 @@ static const char rcsid[] =
 #include "cdecl_ext.h"
 #endif 
 
+#ifndef HAVE_ADDRINFO
 #include "addrinfo.h"
+#endif
 
 #define SUCCESS 0
 #define ANY 0
@@ -111,7 +116,7 @@ getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)
        u_short port;
        int family, i;
        char *addr, *p;
-       u_long v4a;
+       u_int32_t v4a;
        int h_error;
        char numserv[512];
        char numaddr[512];
@@ -140,7 +145,12 @@ getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)
        addr = (char *)sa + afd->a_off;
 
        if (serv == NULL || servlen == 0) {
-               /* what we should do? */
+               /*
+                * do nothing in this case.
+                * in case you are wondering if "&&" is more correct than
+                * "||" here: RFC2553 says that serv == NULL OR servlen == 0
+                * means that the caller does not want the result.
+                */
        } else {
                if (flags & NI_NUMERICSERV)
                        sp = NULL;
@@ -153,7 +163,7 @@ getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)
                                return ENI_MEMORY;
                        strcpy(serv, sp->s_name);
                } else {
-                       sprintf(numserv, "%d", ntohs(port));
+                       snprintf(numserv, sizeof(numserv), "%d", ntohs(port));
                        if (strlen(numserv) > servlen)
                                return ENI_MEMORY;
                        strcpy(serv, numserv);
@@ -162,11 +172,12 @@ getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)
 
        switch (sa->sa_family) {
        case AF_INET:
-               v4a = ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr);
+               v4a = (u_int32_t)
+                       ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr);
                if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
                        flags |= NI_NUMERICHOST;
                v4a >>= IN_CLASSA_NSHIFT;
-               if (v4a == 0 || v4a == IN_LOOPBACKNET)
+               if (v4a == 0)
                        flags |= NI_NUMERICHOST;                        
                break;
 #ifdef INET6
@@ -196,7 +207,12 @@ getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)
 #endif
        }
        if (host == NULL || hostlen == 0) {
-               /* what should we do? */
+               /*
+                * do nothing in this case.
+                * in case you are wondering if "&&" is more correct than
+                * "||" here: RFC2553 says that host == NULL OR hostlen == 0
+                * means that the caller does not want the result.
+                */
        } else if (flags & NI_NUMERICHOST) {
                /* NUMERICHOST and NAMEREQD conflicts with each other */
                if (flags & NI_NAMEREQD)
@@ -207,7 +223,7 @@ getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)
                if (strlen(numaddr) > hostlen)
                        return ENI_MEMORY;
                strcpy(host, numaddr);
-#ifdef INET6
+#if defined(INET6) && defined(NI_WITHSCOPEID)
                if (afd->a_af == AF_INET6 &&
                    (IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)addr) ||
                     IN6_IS_ADDR_MULTICAST((struct in6_addr *)addr)) &&