From: Danny Mayer Date: Fri, 5 May 2006 12:48:59 +0000 (-0400) Subject: Bug #504 Collection of changes to retry DNS in case unable to get definitive answer X-Git-Tag: NTP_4_2_1P248_RC~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c718cba8b70d66ae6ebbc4836c8fff7e6d67d083;p=thirdparty%2Fntp.git Bug #504 Collection of changes to retry DNS in case unable to get definitive answer bk: 445b49bbEXZWxkJ4bDSd1Ve8HJf7Ow --- diff --git a/libntp/ntp_rfc2553.c b/libntp/ntp_rfc2553.c index 231aea1ff..26d1af678 100644 --- a/libntp/ntp_rfc2553.c +++ b/libntp/ntp_rfc2553.c @@ -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; diff --git a/ntpd/ntp_intres.c b/ntpd/ntp_intres.c index 1c587ee17..12431f85f 100644 --- a/ntpd/ntp_intres.c +++ b/ntpd/ntp_intres.c @@ -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 index 000000000..827b00706 --- /dev/null +++ b/ports/winnt/libntp/dnslookup.c @@ -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 +#include +#include +#include +#include +#include +#include +#include + +/* + * 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); +} + diff --git a/ports/winnt/libntp/libntp.dsp b/ports/winnt/libntp/libntp.dsp index abac36c95..d9cb08e5f 100644 --- a/ports/winnt/libntp/libntp.dsp +++ b/ports/winnt/libntp/libntp.dsp @@ -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