Annotation of embedaddon/ntp/ports/winnt/libntp/dnslookup.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2006 Internet Systems Consortium, Inc. ("ISC")
3: *
4: * Permission to use, copy, modify, and distribute this software for any
5: * purpose with or without fee is hereby granted, provided that the above
6: * copyright notice and this permission notice appear in all copies.
7: *
8: * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9: * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10: * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11: * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12: * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13: * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14: * PERFORMANCE OF THIS SOFTWARE.
15: */
16:
17: /*
18: * This module uses Windows lookup facilities to get the address information
19: * wherever it resides. This avoids calling the Internet standard funcction
20: * gethostbyname and gives us more control over the results since the
21: * Microsoft implementation seems to return the wrong error code for some
22: * conditions.
23: */
24:
25: #include <config.h>
26: #include <ws2tcpip.h>
27: #include <nspapi.h>
28: #include <svcguid.h>
29: #include <ntp_rfc2553.h>
30: #include <malloc.h>
31: #include <ntp_stdlib.h>
32: #include <syslog.h>
33:
34: /*
35: * Set this Macro to force retries even if it fails
36: * the lookup
37: */
38: #ifdef FORCE_DNSRETRY
39:
40: #undef EAI_NONAME
41: #define EAI_NONAME EAI_AGAIN
42:
43: #endif
44:
45: typedef struct hostent hostent_t;
46:
47: int ReturnCode(int errcode)
48: {
49: int retcode;
50:
51: switch (errcode)
52: {
53: case 0:
54: return (0);
55: case WSAEINVAL:
56: return (EAI_BADFLAGS);
57: case WSANO_DATA:
58: return (EAI_NONAME);
59: case WSANOTINITIALISED:
60: case WSASERVICE_NOT_FOUND:
61: return (EAI_FAIL);
62: case WSA_NOT_ENOUGH_MEMORY:
63: return (EAI_MEMORY);
64: default:
65: return (EAI_FAIL);
66: }
67: }
68:
69: int
70: AddToAddresses(char **Addresses, int *cnt, CSADDR_INFO *csaddr)
71: {
72:
73: int csize;
74: struct in_addr *sinaddr;
75: char *addr;
76: struct in_addr *addr_list;
77: struct sockaddr_in *sin;
78: sin = (struct sockaddr_in *) csaddr->RemoteAddr.lpSockaddr;
79: if (*Addresses != NULL)
80: {
81: csize = _msize(*Addresses);
82: addr_list = realloc(*Addresses, csize + sizeof(struct in_addr));
83: }
84: else
85: {
86: csize = 0;
87: addr_list = malloc(sizeof(struct in_addr));
88: }
89: addr = (char *) addr_list;
90: sinaddr = &((struct in_addr*) addr)[(*cnt)];
91: memset(sinaddr, 0, sizeof(sinaddr));
92: memcpy(sinaddr, &sin->sin_addr, sizeof(struct in_addr));
93:
94: (*cnt)++;
95: *Addresses = (char *) addr_list;
96: return 0;
97: }
98:
99: int
100: DNSlookup_name(
101: const char *name,
102: int ai_family,
103: struct hostent **Addresses
104: )
105: {
106: char buffer[sizeof(WSAQUERYSET) + 2048];
107: WSAQUERYSET query;
108: struct hostent *addr = NULL;
109: char *bufaddr = NULL;
110: char ** addrlist = &bufaddr;
111: int addrcnt = 0;
112: WSAQUERYSET *results = (WSAQUERYSET *) buffer;
113: GUID HostnameGUID = SVCID_INET_HOSTADDRBYNAME;
114: HANDLE handle;
115: DWORD dwLength;
116: int err = 0;
117: int retcode = 0;
118: int errcode = 0;
119: DWORD i;
120:
121: /*
122: * First we must create a query set
123: */
124: memset(&query, 0, sizeof(query));
125: query.dwSize = sizeof(query);
126: query.lpszServiceInstanceName = (char *)name;
127: query.dwNameSpace = NS_DNS;
128: query.lpServiceClassId = &HostnameGUID;
129:
130: err = WSALookupServiceBegin(&query,
131: LUP_RETURN_NAME | LUP_RETURN_BLOB | LUP_RETURN_ADDR,
132: &handle);
133:
134: if(err == SOCKET_ERROR)
135: {
136: /*
137: * Convert the error code and return
138: */
139: return (ReturnCode(WSAGetLastError()));
140: }
141:
142: /*
143: * Initially none
144: * Change if we get something
145: */
146: retcode = EAI_NONAME;
147: dwLength = sizeof(buffer);
148:
149: while(err == 0) /* Drop out when error */
150: {
151: memset(&buffer, 0, dwLength);
152: err = WSALookupServiceNext(
153: handle,
154: 0,
155: &dwLength,
156: results);
157: errcode = WSAGetLastError();
158: if (results->dwNumberOfCsAddrs > 0)
159: {
160: if (addr == NULL)
161: {
162: addr = (struct hostent *) malloc(sizeof(struct hostent));
163: memset(addr, 0, sizeof(struct hostent));
164: addr->h_addrtype = (short) results->lpcsaBuffer->iSocketType;
165: addr->h_length = sizeof(struct in_addr); /* Only passing back the address */
166: addrlist = malloc(sizeof(char *));
167: *addrlist = NULL;
168: }
169: for (i = 0; i < results->dwNumberOfCsAddrs; i++)
170: {
171: AddToAddresses(addrlist, &addrcnt, &results->lpcsaBuffer[i]);
172: }
173: }
174:
175: }
176: if (addr != NULL)
177: {
178: addr->h_name = (char *) name;
179: addr->h_addr_list = addrlist;
180: retcode = 0;
181: *Addresses = addr;
182: }
183: else
184: {
185: #ifdef FORCE_DNSRETRY
186: /*
187: * We do this or the error would never be logged
188: */
189: if (errcode == WSANO_DATA)
190: msyslog(LOG_ERR, "Address not found for %s", name);
191: #endif
192: retcode = ReturnCode(errcode);
193: }
194: WSALookupServiceEnd(handle);
195: return (retcode);
196: }
197:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>