#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>
#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_BADFLAGS);
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_FAIL);
}
}
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 = (char *) addr_list;
return 0;
}
int
DNSlookup_name(
const char *name,
int ai_family,
struct hostent **Addresses
)
{
char buffer[sizeof(WSAQUERYSET) + 2048];
WSAQUERYSET query;
struct hostent *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;
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)
{
return (ReturnCode(WSAGetLastError()));
}
retcode = EAI_NONAME;
dwLength = sizeof(buffer);
while(err == 0)
{
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 = sizeof(struct in_addr);
addrlist = malloc(sizeof(char *));
*addrlist = NULL;
}
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;
*Addresses = addr;
}
else
{
#ifdef FORCE_DNSRETRY
if (errcode == WSANO_DATA)
msyslog(LOG_ERR, "Address not found for %s", name);
#endif
retcode = ReturnCode(errcode);
}
WSALookupServiceEnd(handle);
return (retcode);
}