2 This file is part of GNUnet.
3 (C) 2012 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
21 * @file gns/w32nsp-resolve.c
22 * @brief W32 integration for GNS
31 #include "gnunet_w32nsp_lib.h"
34 typedef int (WSPAPI *LPNSPSTARTUP) (LPGUID lpProviderId, LPNSP_ROUTINE lpnspRoutines);
36 GUID host = {0x0002a800,0,0,{ 0xC0,0,0,0,0,0,0,0x46 }};
37 GUID ip4 = {0x00090035,0,1,{ 0xc0,0,0,0,0,0,0,0x046}};
38 GUID ip6 = {0x00090035,0,0x001c, { 0xc0,0,0,0,0,0,0,0x046}};
40 DEFINE_GUID(W32_DNS, 0x22059D40, 0x7E9E, 0x11CF, 0xAE, 0x5A, 0x00, 0xAA, 0x00, 0xA7, 0x11, 0x2B);
42 #define DEFINE_DNS_GUID(a,x) DEFINE_GUID(a, 0x00090035, 0x0000, x, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46)
43 DEFINE_DNS_GUID(SVCID_DNS_TYPE_A, 0x0001);
44 DEFINE_DNS_GUID(SVCID_DNS_TYPE_NS, 0x0002);
45 DEFINE_DNS_GUID(SVCID_DNS_TYPE_CNAME, 0x0005);
46 DEFINE_DNS_GUID(SVCID_DNS_TYPE_SOA, 0x0006);
47 DEFINE_DNS_GUID(SVCID_DNS_TYPE_PTR, 0x000c);
48 DEFINE_DNS_GUID(SVCID_DNS_TYPE_MX, 0x000f);
49 DEFINE_DNS_GUID(SVCID_DNS_TYPE_TEXT, 0x0010);
50 DEFINE_DNS_GUID(SVCID_DNS_TYPE_AAAA, 0x001c);
51 DEFINE_DNS_GUID(SVCID_DNS_TYPE_SRV, 0x0021);
52 DEFINE_GUID(SVCID_HOSTNAME, 0x0002a800, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
53 DEFINE_GUID(SVCID_INET_HOSTADDRBYNAME, 0x0002a803, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
56 // Utility to turn a list of offsets into a list of addresses. Used
57 // to convert structures returned as BLOBs.
61 FixList(PCHAR ** List, PCHAR Base)
67 Addr = *List = (PCHAR *)( ((DWORD)*List + Base) );
70 *Addr = (PCHAR)(((DWORD)*Addr + Base));
78 // Routine to convert a hostent returned in a BLOB to one with
79 // usable pointers. The structure is converted in-place.
82 UnpackHostEnt(struct hostent * hostent)
90 hostent->h_name = (PCHAR)((DWORD)hostent->h_name + pch);
92 FixList(&hostent->h_aliases, pch);
93 FixList(&hostent->h_addr_list, pch);
98 print_hostent (struct hostent *he)
103 printf("\tOfficial name: %s\n", he->h_name);
104 for (i=0, pAlias = he->h_aliases; *pAlias != 0; pAlias++) {
105 printf("\tAlternate name #%d: %s\n", ++i, *pAlias);
107 printf("\tAddress type: ");
108 switch (he->h_addrtype) {
113 printf("AF_INET6\n");
116 printf("AF_NETBIOS\n");
119 printf(" %d\n", he->h_addrtype);
122 printf("\tAddress length: %d\n", he->h_length);
124 if (he->h_addrtype == AF_INET) {
125 struct sockaddr_in addr;
126 memset (&addr, 0, sizeof (addr));
127 addr.sin_family = AF_INET;
130 while (he->h_addr_list[i] != 0) {
133 addr.sin_addr = *(struct in_addr *) he->h_addr_list[i++];
134 if (NO_ERROR == WSAAddressToStringA ((LPSOCKADDR) &addr, sizeof (addr), NULL, buf, &buflen))
135 printf("\tIPv4 Address #%d: %s\n", i, buf);
137 printf("\tIPv4 Address #%d: Can't convert: %lu\n", i, GetLastError ());
139 } else if (he->h_addrtype == AF_INET6) {
140 struct sockaddr_in6 addr;
141 memset (&addr, 0, sizeof (addr));
142 addr.sin6_family = AF_INET6;
145 while (he->h_addr_list[i] != 0) {
148 addr.sin6_addr = *(struct in6_addr *) he->h_addr_list[i++];
149 if (NO_ERROR == WSAAddressToStringA ((LPSOCKADDR) &addr, sizeof (addr), NULL, buf, &buflen))
150 printf("\tIPv6 Address #%d: %s\n", i, buf);
152 printf("\tIPv6 Address #%d: Can't convert: %lu\n", i, GetLastError ());
159 main (int argc, char **argv)
170 if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
172 fprintf (stderr, "WSAStartup() failed: %lu\n", GetLastError());
176 cmdl = GetCommandLineW ();
182 wargv = CommandLineToArgvW (cmdl, &wargc);
192 if (wcscmp (wargv[1], L"A") == 0)
193 sc = SVCID_DNS_TYPE_A;
194 else if (wcscmp (wargv[1], L"AAAA") == 0)
195 sc = SVCID_DNS_TYPE_AAAA;
196 else if (wcscmp (wargv[1], L"name") == 0)
198 else if (wcscmp (wargv[1], L"addr") == 0)
199 sc = SVCID_INET_HOSTADDRBYNAME;
202 if (wcscmp (wargv[4], L"mswdns") == 0)
204 else if (wcscmp (wargv[4], L"gnunetdns") == 0)
205 prov = GNUNET_NAMESPACE_PROVIDER_DNS;
214 fprintf (stderr, "Usage: %S <record type> <service name> <NSP library path> <NSP id>\n"
215 "record type - one of the following: A | AAAA | name | addr\n"
216 "service name - a string to resolve; \" \" (a space) means 'blank'\n"
217 "NSP library path - path to libw32nsp\n"
218 "NSP id - one of the following: mswdns | gnunetdns\n",
226 nsp = LoadLibraryW (wargv[3]);
229 fprintf (stderr, "Failed to load library `%S'\n", wargv[3]);
233 LPNSPSTARTUP startup = (LPNSPSTARTUP) GetProcAddress (nsp, "NSPStartup");
235 startup = (LPNSPSTARTUP) GetProcAddress (nsp, "NSPStartup@8");
239 api.cbSize = sizeof (api);
240 ret = startup (&prov, &api);
242 fprintf (stderr, "startup failed: %lu\n", GetLastError ());
248 WSAQUERYSETW *result = (WSAQUERYSETW *) buf;
251 memset (&search, 0, sizeof (search));
252 search.dwSize = sizeof (search);
253 search.lpszServiceInstanceName = (wcscmp (wargv[2], L" ") == 0) ? NULL : wargv[2];
254 search.lpServiceClassId = ≻
255 search.lpNSProviderId = &prov;
256 search.dwNameSpace = NS_ALL;
257 ret = api.NSPLookupServiceBegin (&prov, &search, NULL, LUP_RETURN_ALL, &lookup);
260 fprintf (stderr, "lookup start failed\n");
265 ret = api.NSPLookupServiceNext (lookup, LUP_RETURN_ALL, &resultsize, result);
266 err = GetLastError ();
269 fprintf (stderr, "lookup next failed: %lu\n", err);
274 printf ("Got result:\n");
275 printf (" lpszServiceInstanceName: %S\n", result->lpszServiceInstanceName ? result->lpszServiceInstanceName : L"NULL");
276 if (result->lpServiceClassId)
277 printf (" lpServiceClassId: { 0x%08lX,0x%04X,0x%04X, { 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X } }\n",
278 result->lpServiceClassId->Data1, result->lpServiceClassId->Data2, result->lpServiceClassId->Data3, result->lpServiceClassId->Data4[0],
279 result->lpServiceClassId->Data4[1], result->lpServiceClassId->Data4[2], result->lpServiceClassId->Data4[3], result->lpServiceClassId->Data4[4],
280 result->lpServiceClassId->Data4[5], result->lpServiceClassId->Data4[6], result->lpServiceClassId->Data4[7]);
282 printf (" lpServiceClassId: NULL\n");
283 if (result->lpVersion)
284 printf (" lpVersion: 0x%08lX, %d\n", result->lpVersion->dwVersion, result->lpVersion->ecHow);
286 printf (" lpVersion: NULL\n");
287 printf (" lpszComment: %S\n", result->lpszComment ? result->lpszComment : L"NULL");
288 printf (" dwNameSpace: %lu\n", result->dwNameSpace);
289 if (result->lpNSProviderId)
290 printf (" lpNSProviderId: { 0x%08lX,0x%04X,0x%04X, { 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X } }\n",
291 result->lpNSProviderId->Data1, result->lpNSProviderId->Data2, result->lpNSProviderId->Data3, result->lpNSProviderId->Data4[0],
292 result->lpNSProviderId->Data4[1], result->lpNSProviderId->Data4[2], result->lpNSProviderId->Data4[3], result->lpNSProviderId->Data4[4],
293 result->lpNSProviderId->Data4[5], result->lpNSProviderId->Data4[6], result->lpNSProviderId->Data4[7]);
295 printf (" lpNSProviderId: NULL\n");
296 printf (" lpszContext: %S\n", result->lpszContext ? result->lpszContext : L"NULL");
297 printf (" dwNumberOfProtocols: %lu\n", result->dwNumberOfProtocols);
298 printf (" lpszQueryString: %S\n", result->lpszQueryString ? result->lpszQueryString : L"NULL");
299 printf (" dwNumberOfCsAddrs: %lu\n", result->dwNumberOfCsAddrs);
300 for (i = 0; i < result->dwNumberOfCsAddrs; i++)
302 switch (result->lpcsaBuffer[i].iSocketType)
305 printf (" %d: iSocketType = SOCK_STREAM\n", i);
308 printf (" %d: iSocketType = SOCK_DGRAM\n", i);
311 printf (" %d: iSocketType = %d\n", i, result->lpcsaBuffer[i].iSocketType);
313 switch (result->lpcsaBuffer[i].iProtocol)
316 printf (" %d: iProtocol = IPPROTO_TCP\n", i);
319 printf (" %d: iProtocol = IPPROTO_UDP\n", i);
322 printf (" %d: iProtocol = %d\n", i, result->lpcsaBuffer[i].iProtocol);
324 switch (result->lpcsaBuffer[i].LocalAddr.lpSockaddr->sa_family)
327 printf (" %d: loc family = AF_INET\n", i);
330 printf (" %d: loc family = AF_INET6\n", i);
333 printf (" %d: loc family = %hu\n", i, result->lpcsaBuffer[i].LocalAddr.lpSockaddr->sa_family);
335 switch (result->lpcsaBuffer[i].RemoteAddr.lpSockaddr->sa_family)
338 printf (" %d: rem family = AF_INET\n", i);
341 printf (" %d: rem family = AF_INET6\n", i);
344 printf (" %d: rem family = %hu\n", i, result->lpcsaBuffer[i].RemoteAddr.lpSockaddr->sa_family);
348 if (NO_ERROR == WSAAddressToStringA (result->lpcsaBuffer[i].LocalAddr.lpSockaddr, result->lpcsaBuffer[i].LocalAddr.iSockaddrLength, NULL, buf, &buflen))
349 printf("\tLocal Address #%d: %s\n", i, buf);
351 printf("\tLocal Address #%d: Can't convert: %lu\n", i, GetLastError ());
353 if (NO_ERROR == WSAAddressToStringA (result->lpcsaBuffer[i].RemoteAddr.lpSockaddr, result->lpcsaBuffer[i].RemoteAddr.iSockaddrLength, NULL, buf, &buflen))
354 printf("\tRemote Address #%d: %s\n", i, buf);
356 printf("\tRemote Address #%d: Can't convert: %lu\n", i, GetLastError ());
358 printf (" dwOutputFlags: 0x%08lX\n", result->dwOutputFlags);
359 printf (" lpBlob: 0x%p\n", result->lpBlob);
362 struct hostent *he = malloc (result->lpBlob->cbSize);
365 memcpy (he, result->lpBlob->pBlobData, result->lpBlob->cbSize);
372 ret = api.NSPLookupServiceEnd (lookup);
374 printf ("NSPLookupServiceEnd() failed: %lu\n", GetLastError ());
376 api.NSPCleanup (&prov);
389 memset (&hints, 0, sizeof (struct addrinfo));
390 hints.ai_family = AF_UNSPEC;
391 hints.ai_socktype = SOCK_STREAM;
393 if (0 != (s = GetAddrInfoW (wargv[2], NULL, &hints, &result)))
395 fprintf (stderr, "Cound not resolve `%S' using GetAddrInfoW: %lu\n",
396 wargv[2], GetLastError ());
400 for (pos = result; pos != NULL; pos = pos->ai_next)
402 wchar_t tmpbuf[1024];
404 if (0 == WSAAddressToStringW (pos->ai_addr, pos->ai_addrlen, NULL, tmpbuf, &buflen))
405 fprintf (stderr, "Result:\n"
421 fprintf (stderr, "Result:\n"
434 L"<can't stringify>",
438 FreeAddrInfoW (result);