]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
Bug #504 Collection of changes to retry DNS in case unable to get definitive answer
authorDanny Mayer <mayer@ntp.org>
Fri, 5 May 2006 12:48:59 +0000 (08:48 -0400)
committerDanny Mayer <mayer@ntp.org>
Fri, 5 May 2006 12:48:59 +0000 (08:48 -0400)
bk: 445b49bbEXZWxkJ4bDSd1Ve8HJf7Ow

libntp/ntp_rfc2553.c
ntpd/ntp_intres.c
ports/winnt/libntp/dnslookup.c [new file with mode: 0644]
ports/winnt/libntp/libntp.dsp

index 231aea1ffabc710a2098943b44c71b53fb116bdb..26d1af678f3b6a00751d6efa7b7ec0d3dcfee7d7 100644 (file)
@@ -101,6 +101,30 @@ static char *ai_errlist[] = {
        "Unknown error",                                /* EAI_MAX        */
 };
 
+
+int
+DNSlookup_name(
+       const char FAR *name,
+       int ai_family,
+       struct hostent **Addresses
+);
+
+#ifndef SYS_WINNT
+/*
+ * Encapsulate gethostbyname to control the error code
+ */
+int
+DNSlookup_name(
+       const char FAR *name,
+       int ai_family,
+       struct hostent **Addresses
+)
+{
+       *Addresses = gethostbyname(name);
+       return (h_errno);
+}
+#endif
+
 static int do_nodename P((const char *nodename, struct addrinfo *ai,
     const struct addrinfo *hints));
 
@@ -244,10 +268,17 @@ void
 freeaddrinfo(struct addrinfo *ai)
 {
        if (ai->ai_canonname != NULL)
+       {
                free(ai->ai_canonname);
+               ai->ai_canonname = NULL;
+       }
        if (ai->ai_addr != NULL)
+       {
                free(ai->ai_addr);
+               ai->ai_addr = NULL;
+       }
        free(ai);
+       ai = NULL;
 }
 
 int
@@ -288,9 +319,10 @@ do_nodename(
        struct addrinfo *ai,
        const struct addrinfo *hints)
 {
-       struct hostent *hp;
+       struct hostent *hp = NULL;
        struct sockaddr_in *sockin;
        struct sockaddr_in6 *sockin6;
+       int errval;
 
        ai->ai_addr = calloc(sizeof(struct sockaddr_storage), 1);
        if (ai->ai_addr == NULL)
@@ -355,11 +387,13 @@ do_nodename(
        /*
         * Look for a name
         */
-       hp = gethostbyname(nodename);
+
+       errval = DNSlookup_name(nodename, AF_INET, &hp);
+
        if (hp == NULL) {
-               if (h_errno == TRY_AGAIN)
+               if (errval == TRY_AGAIN || errval == EAI_AGAIN)
                        return (EAI_AGAIN);
-               else {
+               else if (errval == EAI_NONAME) {
                        if (inet_pton(AF_INET, nodename,
                            &((struct sockaddr_in *)ai->ai_addr)->sin_addr) == 1) {
                                ((struct sockaddr *)ai->ai_addr)->sa_family = AF_INET;
@@ -367,7 +401,11 @@ do_nodename(
                                ai->ai_addrlen = sizeof(struct sockaddr_in);
                                return (0);
                        }
-                       return (EAI_FAIL);
+                       return (errval);
+               }
+               else
+               {
+                       return (errval);
                }
        }
        ai->ai_family = hp->h_addrtype;
index 1c587ee17eeb4b40f97d71d2b5e8ebf96b1bbf28..12431f85f65a9751eff67b83573b2241befa57ba 100644 (file)
@@ -509,6 +509,10 @@ findhostaddr(
                                entry->ce_config.v6_flag = 1;
                        }
                }
+               else if (error == EAI_NONAME)
+               {
+                       msyslog(LOG_ERR, "host name not found: %s", entry->ce_name);
+               }
        } else {
 #ifdef DEBUG
                if (debug > 2)
@@ -522,14 +526,24 @@ findhostaddr(
                                   NULL, 0, 0);
        }
 
+       /*
+        * If the resolver failed, see if the failure is
+        * temporary.  If so, return success.
+        */
        if (error != 0) {
-               /*
-                * If the resolver is in use, see if the failure is
-                * temporary.  If so, return success.
-                */
-               if (error == EAI_AGAIN)
-                   return (1);
-               return (0);
+               switch (error)
+               {
+               case EAI_AGAIN:
+                       return (1);
+               case EAI_NONAME:
+                       return (0);
+               case EAI_NODATA:
+               case EAI_FAIL:
+               case EAI_SYSTEM:
+                       return (1);
+               default:
+                       return (0);
+               }
        }
 
        if (entry->ce_name) {
@@ -558,7 +572,7 @@ openntp(void)
        struct addrinfo *addrResult;
        const char *localhost = "127.0.0.1";    /* Use IPv6 loopback */
 
-       if (sockfd >= 0)
+       if (sockfd != INVALID_SOCKET)
            return;
 
        memset(&hints, 0, sizeof(hints));
diff --git a/ports/winnt/libntp/dnslookup.c b/ports/winnt/libntp/dnslookup.c
new file mode 100644 (file)
index 0000000..827b007
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2006  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This module uses Windows lookup facilities to get the address information
+ * wherever it resides. This avoids calling the Internet standard funcction
+ * gethostbyname and gives us more control over the results since the
+ * Microsoft implementation seems to return the wrong error code for some
+ * conditions.
+ */
+
+#include <config.h>
+#include <ws2tcpip.h>
+#include <nspapi.h>
+#include <svcguid.h>
+#include <ntp_rfc2553.h>
+#include <malloc.h>
+#include <ntp_stdlib.h>
+#include <syslog.h>
+
+/*
+ * Set this Macro to force retries even if it fails
+ * the lookup
+ */
+#ifdef FORCE_DNSRETRY
+
+#undef EAI_NONAME
+#define EAI_NONAME EAI_AGAIN
+
+#endif
+
+typedef struct hostent hostent_t;
+
+int ReturnCode(int errcode)
+{
+       int retcode;
+
+       switch (errcode)
+       {
+       case 0:
+               return (0);
+       case WSAEINVAL:
+               return (EAI_BADHINTS);
+       case WSANO_DATA:
+               return (EAI_NONAME);
+       case WSANOTINITIALISED:
+       case WSASERVICE_NOT_FOUND:
+               return (EAI_FAIL);
+       case WSA_NOT_ENOUGH_MEMORY:
+               return (EAI_MEMORY);
+       default:
+               return (EAI_SYSTEM);
+       }
+}
+
+int
+AddToAddresses(char **Addresses, int *cnt, CSADDR_INFO *csaddr)
+{
+
+       int csize;
+       struct in_addr *sinaddr;
+       char *addr;
+       struct in_addr *addr_list;
+       struct sockaddr_in *sin;
+       sin = (struct sockaddr_in *) csaddr->RemoteAddr.lpSockaddr;
+       if (*Addresses != NULL)
+       {
+               csize = _msize(*Addresses);
+               addr_list = realloc(*Addresses, csize + sizeof(struct in_addr));
+       }
+       else
+       {
+               csize = 0;
+               addr_list = malloc(sizeof(struct in_addr));
+       }
+       addr = (char *) addr_list;
+       sinaddr = &((struct in_addr*) addr)[(*cnt)];
+       memset(sinaddr, 0, sizeof(sinaddr));
+       memcpy(sinaddr, &sin->sin_addr, sizeof(struct in_addr));
+       
+       (*cnt)++;
+       *Addresses = addr;
+       return 0;
+}
+
+int
+DNSlookup_name(
+       const char FAR *name,
+       int ai_family,
+       struct hostent **Addresses
+)
+{
+       char buffer[sizeof(WSAQUERYSET) + 2048];
+       WSAQUERYSET query;
+       hostent_t *addr = NULL;
+       char *bufaddr = NULL;
+       char ** addrlist = &bufaddr;
+       int addrcnt = 0;
+       WSAQUERYSET *results = (WSAQUERYSET *) buffer;
+       GUID    HostnameGUID = SVCID_INET_HOSTADDRBYNAME;
+       HANDLE  handle;
+       DWORD dwLength;
+       int err = 0;
+       int retcode = 0;
+       int errcode = 0;
+       DWORD i;
+
+       /*
+        * First we must create a query set
+        */
+       memset(&query, 0, sizeof(query));
+       query.dwSize = sizeof(query);
+       query.lpszServiceInstanceName = (char *)name;
+       query.dwNameSpace = NS_DNS;
+       query.lpServiceClassId = &HostnameGUID;
+
+       err = WSALookupServiceBegin(&query,
+                                 LUP_RETURN_NAME | LUP_RETURN_BLOB | LUP_RETURN_ADDR,
+                                 &handle);
+
+       if(err == SOCKET_ERROR)
+       {
+               /*
+                * Convert the error code and return
+                */
+               return (ReturnCode(WSAGetLastError()));
+       }
+
+       /*
+        * Initially none
+        * Change if we get something
+        */
+       retcode = EAI_NONAME;
+       dwLength = sizeof(buffer);
+       *addrlist = NULL;
+
+       while(err == 0)         /* Drop out when error */
+       {
+               memset(&buffer, 0, dwLength);
+               err = WSALookupServiceNext(
+                                       handle,
+                                       0,
+                                       &dwLength,
+                                       results);
+               errcode = WSAGetLastError();
+               if (results->dwNumberOfCsAddrs > 0)
+               {
+                       if (addr == NULL)
+                       {
+                               addr = (struct hostent *) malloc(sizeof(struct hostent));
+                               memset(addr, 0, sizeof(struct hostent));
+                               addr->h_addrtype = (short) results->lpcsaBuffer->iSocketType;
+                               addr->h_length = (short) results->lpcsaBuffer->RemoteAddr.iSockaddrLength;
+                       }
+                       for (i = 0; i < results->dwNumberOfCsAddrs; i++)
+                       {
+                               AddToAddresses(addrlist, &addrcnt, &results->lpcsaBuffer[i]);
+                       }
+               }
+
+       }
+       if (addr != NULL)
+       {
+               addr->h_name = (char *) name;
+               addr->h_addr_list = addrlist;
+               retcode = 0;
+       }
+       else
+       {
+#ifdef FORCE_DNSRETRY
+               /*
+                * We do this or the error would never be logged
+                */
+               if (errcode == WSANO_DATA)
+                       msyslog(LOG_ERR, "Address not found for %s", name);
+#endif
+               retcode = ReturnCode(errcode);
+       }
+       *Addresses = addr;
+       WSALookupServiceEnd(handle);
+       return (retcode);
+}
+
index abac36c9514887cf40b212a69d9b2c831fef10fb..d9cb08e5f9a967d220c5460f30f59be04a2b162a 100644 (file)
@@ -150,6 +150,10 @@ SOURCE=..\..\..\libntp\decodenetnum.c
 # End Source File
 # Begin Source File
 
+SOURCE=.\dnslookup.c
+# End Source File
+# Begin Source File
+
 SOURCE=..\..\..\libntp\dofptoa.c
 # End Source File
 # Begin Source File