]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
First try getaddrinfo() with the AI_NUMERICHOST hint and try again as
authorJohn Hay <hay@ntp.org>
Thu, 14 Nov 2002 16:20:48 +0000 (18:20 +0200)
committerJohn Hay <hay@ntp.org>
Thu, 14 Nov 2002 16:20:48 +0000 (18:20 +0200)
before if it fails. This works around the "problem" on Solaris that
return the "IPv4-mapped IPv6 address" if you give it an IPv4 address.

bk: 3dd3cd60k7yJ0nUvVjOQV-Fmnf9aPw

libntp/ntp_rfc2553.c
ntpdc/ntpdc.c
ntpq/ntpq.c

index 132f3d1b5416334fae389394a1fbe6d5229308dc..82eb2860fd4056576cae298210c99b69befc5758 100644 (file)
@@ -113,13 +113,15 @@ static char *ai_errlist[] = {
 };
 
 static int ipv4_aton P((const char *, struct sockaddr_storage *));
+static int do_nodename P((const char *nodename, struct addrinfo *ai,
+    const struct addrinfo *hints));
 
 int
 getaddrinfo (const char *nodename, const char *servname,
        const struct addrinfo *hints, struct addrinfo **res)
 {
+       int rval;
        struct addrinfo *ai;
-       struct hostent *hp;
        struct sockaddr_in *sockin;
 
        ai = calloc(sizeof(struct addrinfo), 1);
@@ -127,45 +129,18 @@ getaddrinfo (const char *nodename, const char *servname,
                return (EAI_MEMORY);
 
        if (nodename != NULL) {
-               ai->ai_addr = calloc(sizeof(struct sockaddr_storage), 1);
-               if (ai->ai_addr == NULL)
-                       return (EAI_MEMORY);
-               hp = gethostbyname(nodename);
-               if (hp == NULL) {
-                       if (h_errno == TRY_AGAIN)
-                               return (EAI_AGAIN);
-                       else {
-                               if (ipv4_aton(nodename,
-                                   (struct sockaddr_storage *)ai->ai_addr)
-                                   == 1) {
-                                       ai->ai_family = AF_INET;
-                                       ai->ai_addrlen =
-                                           sizeof(struct sockaddr_in);
-                                       *res = ai;
-                                       return (0);
-                               }
-                               return (EAI_FAIL);
-                       }
-               }
-               ai->ai_family = hp->h_addrtype;
-               ai->ai_addrlen = sizeof(struct sockaddr);
-               sockin = (struct sockaddr_in *)ai->ai_addr;
-               memcpy(&sockin->sin_addr, hp->h_addr, hp->h_length);
-               ai->ai_addr->sa_family = hp->h_addrtype;
-#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
-               ai->ai_addr->sa_len = sizeof(struct sockaddr);
-#endif
-               if (hints != NULL && hints->ai_flags & AI_CANONNAME) {
-                       ai->ai_canonname = malloc(strlen(hp->h_name));
-                       if (ai->ai_canonname == NULL)
-                               return (EAI_MEMORY);
-                       strcpy(ai->ai_canonname, hp->h_name);
+               rval = do_nodename(nodename, ai, hints);
+               if (rval != 0) {
+                       freeaddrinfo(ai);
+                       return (rval);
                }
        }
        if (nodename == NULL && hints != NULL) {
                ai->ai_addr = calloc(sizeof(struct sockaddr_storage), 1);
-               if (ai->ai_addr == NULL)
+               if (ai->ai_addr == NULL) {
+                       freeaddrinfo(ai);
                        return (EAI_MEMORY);
+               }
                ai->ai_family = AF_INET;
                ai->ai_addrlen = sizeof(struct sockaddr_storage);
                sockin = (struct sockaddr_in *)ai->ai_addr;
@@ -178,8 +153,10 @@ getaddrinfo (const char *nodename, const char *servname,
        if (servname != NULL) {
                ai->ai_family = AF_INET;
                ai->ai_socktype = SOCK_DGRAM;
-               if (strcmp(servname, "123") != 0)
+               if (strcmp(servname, "123") != 0) {
+                       freeaddrinfo(ai);
                        return (EAI_SERVICE);
+               }
                sockin = (struct sockaddr_in *)ai->ai_addr;
                sockin->sin_port = htons(NTP_PORT);
        }
@@ -230,6 +207,59 @@ gai_strerror(ecode)
        return ai_errlist[ecode];
 }
 
+static int
+do_nodename(
+       const char *nodename,
+       struct addrinfo *ai,
+       const struct addrinfo *hints)
+{
+       struct hostent *hp;
+       struct sockaddr_in *sockin;
+
+       ai->ai_addr = calloc(sizeof(struct sockaddr_storage), 1);
+       if (ai->ai_addr == NULL)
+               return (EAI_MEMORY);
+
+       if (hints != NULL && hints->ai_flags & AI_NUMERICHOST) {
+               if (ipv4_aton(nodename,
+                   (struct sockaddr_storage *)ai->ai_addr) == 1) {
+                       ai->ai_family = AF_INET;
+                       ai->ai_addrlen = sizeof(struct sockaddr_in);
+                       return (0);
+               }
+               return (EAI_NONAME);
+       }
+       hp = gethostbyname(nodename);
+       if (hp == NULL) {
+               if (h_errno == TRY_AGAIN)
+                       return (EAI_AGAIN);
+               else {
+                       if (ipv4_aton(nodename,
+                           (struct sockaddr_storage *)ai->ai_addr) == 1) {
+                               ai->ai_family = AF_INET;
+                               ai->ai_addrlen = sizeof(struct sockaddr_in);
+                               return (0);
+                       }
+                       return (EAI_FAIL);
+               }
+       }
+       ai->ai_family = hp->h_addrtype;
+       ai->ai_addrlen = sizeof(struct sockaddr);
+       sockin = (struct sockaddr_in *)ai->ai_addr;
+       memcpy(&sockin->sin_addr, hp->h_addr, hp->h_length);
+       ai->ai_addr->sa_family = hp->h_addrtype;
+#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
+       ai->ai_addr->sa_len = sizeof(struct sockaddr);
+#endif
+       if (hints != NULL && hints->ai_flags & AI_CANONNAME) {
+               ai->ai_canonname = malloc(strlen(hp->h_name));
+               if (ai->ai_canonname == NULL)
+                       return (EAI_MEMORY);
+               strcpy(ai->ai_canonname, hp->h_name);
+       }
+       return (0);
+}
+
 /*
  * ipv4_aton - return a net number (this is crude, but careful)
  */
index 0d5fce9ca67ac92b2732d5adf28ab967ebbe5014..e1ce46ffe519f14cc344743e99c0bb246413acb0 100644 (file)
@@ -411,15 +411,6 @@ openhost(
        char name[LENHOSTNAME];
        char service[5];
 
-       memset((char *)&hints, 0, sizeof(struct addrinfo));
-       hints.ai_flags = AI_CANONNAME;
-#ifdef AI_ADDRCONFIG
-       hints.ai_flags |= AI_ADDRCONFIG;
-#endif
-       hints.ai_family = ai_fam_templ;
-       hints.ai_protocol = IPPROTO_UDP;
-       hints.ai_socktype = SOCK_DGRAM;
-
        /*
         * We need to get by the [] if they were entered 
         */
@@ -434,8 +425,28 @@ openhost(
                hname = name;
        }       
 
+       /*
+        * First try to resolve it as an ip address and if that fails,
+        * do a fullblown (dns) lookup. That way we only use the dns
+        * when it is needed and work around some implementations that
+        * will return an "IPv4-mapped IPv6 address" address if you
+        * give it an IPv4 address to lookup.
+        */
        sprintf(service, "%u", NTP_PORT);
-       a_info = getaddrinfo(hname, service, &hints, &ai);      
+       memset((char *)&hints, 0, sizeof(struct addrinfo));
+       hints.ai_family = ai_fam_templ;
+       hints.ai_protocol = IPPROTO_UDP;
+       hints.ai_socktype = SOCK_DGRAM;
+       hints.ai_flags = AI_NUMERICHOST;
+
+       a_info = getaddrinfo(hname, service, &hints, &ai);
+       if (a_info == EAI_NONAME) {
+               hints.ai_flags = AI_CANONNAME;
+#ifdef AI_ADDRCONFIG
+               hints.ai_flags |= AI_ADDRCONFIG;
+#endif
+               a_info = getaddrinfo(hname, service, &hints, &ai);      
+       }
        /* Some older implementations don't like AI_ADDRCONFIG. */
        if (a_info == EAI_BADFLAGS) {
                hints.ai_flags = AI_CANONNAME;
index c9b4af94faa057c445c6d8f1c95eb8e0e9252f5a..03d4a8e5a3ecbe433aef88f80463de48ebf7939c 100644 (file)
@@ -592,15 +592,6 @@ openhost(
        char name[LENHOSTNAME];
        char service[5];
 
-       memset((char *)&hints, 0, sizeof(struct addrinfo));
-       hints.ai_flags = AI_CANONNAME;
-#ifdef AI_ADDRCONFIG
-       hints.ai_flags |= AI_ADDRCONFIG;
-#endif
-       hints.ai_family = ai_fam_templ;
-       hints.ai_protocol = IPPROTO_UDP;
-       hints.ai_socktype = SOCK_DGRAM;
-
        /*
         * We need to get by the [] if they were entered
         */
@@ -615,8 +606,28 @@ openhost(
        hname = name;
        }
 
+       /*
+        * First try to resolve it as an ip address and if that fails,
+        * do a fullblown (dns) lookup. That way we only use the dns
+        * when it is needed and work around some implementations that
+        * will return an "IPv4-mapped IPv6 address" address if you
+        * give it an IPv4 address to lookup.
+        */
        sprintf(service, "%u", NTP_PORT);
+       memset((char *)&hints, 0, sizeof(struct addrinfo));
+       hints.ai_family = ai_fam_templ;
+       hints.ai_protocol = IPPROTO_UDP;
+       hints.ai_socktype = SOCK_DGRAM;
+       hints.ai_flags = AI_NUMERICHOST;
+
        a_info = getaddrinfo(hname, service, &hints, &ai);
+       if (a_info == EAI_NONAME) {
+               hints.ai_flags = AI_CANONNAME;
+#ifdef AI_ADDRCONFIG
+               hints.ai_flags |= AI_ADDRCONFIG;
+#endif
+               a_info = getaddrinfo(hname, service, &hints, &ai);      
+       }
        /* Some older implementations don't like AI_ADDRCONFIG. */
        if (a_info == EAI_BADFLAGS) {
                hints.ai_flags = AI_CANONNAME;