2 This file is part of GNUnet.
3 Copyright (C) 2012 GNUnet e.V.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
21 * @file gns/w32nsp-resolve.c
22 * @brief W32 integration for GNS
25 /* Instead of including gnunet_common.h */
26 #define GNUNET_memcpy(dst, src, n) do { if (0 != n) { (void)memcpy(dst, src, n); } } while (0)
34 #include "gnunet_w32nsp_lib.h"
37 typedef int (WSPAPI *LPNSPSTARTUP)(LPGUID lpProviderId, LPNSP_ROUTINE lpnspRoutines);
39 GUID host = { 0x0002a800, 0, 0, { 0xC0, 0, 0, 0, 0, 0, 0, 0x46 } };
40 GUID ip4 = { 0x00090035, 0, 1, { 0xc0, 0, 0, 0, 0, 0, 0, 0x046 } };
41 GUID ip6 = { 0x00090035, 0, 0x001c, { 0xc0, 0, 0, 0, 0, 0, 0, 0x046 } };
43 DEFINE_GUID(W32_DNS, 0x22059D40, 0x7E9E, 0x11CF, 0xAE, 0x5A, 0x00, 0xAA, 0x00, 0xA7, 0x11, 0x2B);
45 #define DEFINE_DNS_GUID(a, x) DEFINE_GUID(a, 0x00090035, 0x0000, x, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46)
46 DEFINE_DNS_GUID(SVCID_DNS_TYPE_A, 0x0001);
47 DEFINE_DNS_GUID(SVCID_DNS_TYPE_NS, 0x0002);
48 DEFINE_DNS_GUID(SVCID_DNS_TYPE_CNAME, 0x0005);
49 DEFINE_DNS_GUID(SVCID_DNS_TYPE_SOA, 0x0006);
50 DEFINE_DNS_GUID(SVCID_DNS_TYPE_PTR, 0x000c);
51 DEFINE_DNS_GUID(SVCID_DNS_TYPE_MX, 0x000f);
52 DEFINE_DNS_GUID(SVCID_DNS_TYPE_TEXT, 0x0010);
53 DEFINE_DNS_GUID(SVCID_DNS_TYPE_AAAA, 0x001c);
54 DEFINE_DNS_GUID(SVCID_DNS_TYPE_SRV, 0x0021);
55 DEFINE_GUID(SVCID_HOSTNAME, 0x0002a800, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
56 DEFINE_GUID(SVCID_INET_HOSTADDRBYNAME, 0x0002a803, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
59 // Utility to turn a list of offsets into a list of addresses. Used
60 // to convert structures returned as BLOBs.
64 FixList(PCHAR ** List, PCHAR Base)
70 Addr = *List = (PCHAR *)(((DWORD)*List + Base));
73 *Addr = (PCHAR)(((DWORD)*Addr + Base));
81 // Routine to convert a hostent returned in a BLOB to one with
82 // usable pointers. The structure is converted in-place.
85 UnpackHostEnt(struct hostent * hostent)
93 hostent->h_name = (PCHAR)((DWORD)hostent->h_name + pch);
95 FixList(&hostent->h_aliases, pch);
96 FixList(&hostent->h_addr_list, pch);
101 print_hostent(struct hostent *he)
106 printf("\tOfficial name: %s\n", he->h_name);
107 for (i = 0, pAlias = he->h_aliases; *pAlias != 0; pAlias++)
109 printf("\tAlternate name #%d: %s\n", ++i, *pAlias);
111 printf("\tAddress type: ");
112 switch (he->h_addrtype)
119 printf("AF_INET6\n");
123 printf("AF_NETBIOS\n");
127 printf(" %d\n", he->h_addrtype);
130 printf("\tAddress length: %d\n", he->h_length);
132 if (he->h_addrtype == AF_INET)
134 struct sockaddr_in addr;
135 memset(&addr, 0, sizeof(addr));
136 addr.sin_family = AF_INET;
139 while (he->h_addr_list[i] != 0)
143 addr.sin_addr = *(struct in_addr *)he->h_addr_list[i++];
144 if (NO_ERROR == WSAAddressToStringA((LPSOCKADDR)&addr, sizeof(addr), NULL, buf, &buflen))
145 printf("\tIPv4 Address #%d: %s\n", i, buf);
147 printf("\tIPv4 Address #%d: Can't convert: %lu\n", i, GetLastError());
150 else if (he->h_addrtype == AF_INET6)
152 struct sockaddr_in6 addr;
153 memset(&addr, 0, sizeof(addr));
154 addr.sin6_family = AF_INET6;
157 while (he->h_addr_list[i] != 0)
161 addr.sin6_addr = *(struct in6_addr *)he->h_addr_list[i++];
162 if (NO_ERROR == WSAAddressToStringA((LPSOCKADDR)&addr, sizeof(addr), NULL, buf, &buflen))
163 printf("\tIPv6 Address #%d: %s\n", i, buf);
165 printf("\tIPv6 Address #%d: Can't convert: %lu\n", i, GetLastError());
172 main(int argc, char **argv)
183 if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
185 fprintf(stderr, "WSAStartup() failed: %lu\n", GetLastError());
189 cmdl = GetCommandLineW();
195 wargv = CommandLineToArgvW(cmdl, &wargc);
205 if (wcscmp(wargv[1], L"A") == 0)
206 sc = SVCID_DNS_TYPE_A;
207 else if (wcscmp(wargv[1], L"AAAA") == 0)
208 sc = SVCID_DNS_TYPE_AAAA;
209 else if (wcscmp(wargv[1], L"name") == 0)
211 else if (wcscmp(wargv[1], L"addr") == 0)
212 sc = SVCID_INET_HOSTADDRBYNAME;
215 if (wcscmp(wargv[4], L"mswdns") == 0)
217 else if (wcscmp(wargv[4], L"gnunetdns") == 0)
218 prov = GNUNET_NAMESPACE_PROVIDER_DNS;
227 fprintf(stderr, "Usage: %S <record type> <service name> <NSP library path> <NSP id>\n"
228 "record type - one of the following: A | AAAA | name | addr\n"
229 "service name - a string to resolve; \" \" (a space) means 'blank'\n"
230 "NSP library path - path to libw32nsp\n"
231 "NSP id - one of the following: mswdns | gnunetdns\n",
239 nsp = LoadLibraryW(wargv[3]);
242 fprintf(stderr, "Failed to load library `%S'\n", wargv[3]);
246 LPNSPSTARTUP startup = (LPNSPSTARTUP)GetProcAddress(nsp, "NSPStartup");
248 startup = (LPNSPSTARTUP)GetProcAddress(nsp, "NSPStartup@8");
252 api.cbSize = sizeof(api);
253 ret = startup(&prov, &api);
255 fprintf(stderr, "startup failed: %lu\n", GetLastError());
261 WSAQUERYSETW *result = (WSAQUERYSETW *)buf;
264 memset(&search, 0, sizeof(search));
265 search.dwSize = sizeof(search);
266 search.lpszServiceInstanceName = (wcscmp(wargv[2], L" ") == 0) ? NULL : wargv[2];
267 search.lpServiceClassId = ≻
268 search.lpNSProviderId = &prov;
269 search.dwNameSpace = NS_ALL;
270 ret = api.NSPLookupServiceBegin(&prov, &search, NULL, LUP_RETURN_ALL, &lookup);
273 fprintf(stderr, "lookup start failed\n");
278 ret = api.NSPLookupServiceNext(lookup, LUP_RETURN_ALL, &resultsize, result);
279 err = GetLastError();
282 fprintf(stderr, "lookup next failed: %lu\n", err);
287 printf("Got result:\n");
288 printf(" lpszServiceInstanceName: %S\n", result->lpszServiceInstanceName ? result->lpszServiceInstanceName : L"NULL");
289 if (result->lpServiceClassId)
290 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",
291 result->lpServiceClassId->Data1, result->lpServiceClassId->Data2, result->lpServiceClassId->Data3, result->lpServiceClassId->Data4[0],
292 result->lpServiceClassId->Data4[1], result->lpServiceClassId->Data4[2], result->lpServiceClassId->Data4[3], result->lpServiceClassId->Data4[4],
293 result->lpServiceClassId->Data4[5], result->lpServiceClassId->Data4[6], result->lpServiceClassId->Data4[7]);
295 printf(" lpServiceClassId: NULL\n");
296 if (result->lpVersion)
297 printf(" lpVersion: 0x%08lX, %d\n", result->lpVersion->dwVersion, result->lpVersion->ecHow);
299 printf(" lpVersion: NULL\n");
300 printf(" lpszComment: %S\n", result->lpszComment ? result->lpszComment : L"NULL");
301 printf(" dwNameSpace: %lu\n", result->dwNameSpace);
302 if (result->lpNSProviderId)
303 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",
304 result->lpNSProviderId->Data1, result->lpNSProviderId->Data2, result->lpNSProviderId->Data3, result->lpNSProviderId->Data4[0],
305 result->lpNSProviderId->Data4[1], result->lpNSProviderId->Data4[2], result->lpNSProviderId->Data4[3], result->lpNSProviderId->Data4[4],
306 result->lpNSProviderId->Data4[5], result->lpNSProviderId->Data4[6], result->lpNSProviderId->Data4[7]);
308 printf(" lpNSProviderId: NULL\n");
309 printf(" lpszContext: %S\n", result->lpszContext ? result->lpszContext : L"NULL");
310 printf(" dwNumberOfProtocols: %lu\n", result->dwNumberOfProtocols);
311 printf(" lpszQueryString: %S\n", result->lpszQueryString ? result->lpszQueryString : L"NULL");
312 printf(" dwNumberOfCsAddrs: %lu\n", result->dwNumberOfCsAddrs);
313 for (i = 0; i < result->dwNumberOfCsAddrs; i++)
315 switch (result->lpcsaBuffer[i].iSocketType)
318 printf(" %d: iSocketType = SOCK_STREAM\n", i);
322 printf(" %d: iSocketType = SOCK_DGRAM\n", i);
326 printf(" %d: iSocketType = %d\n", i, result->lpcsaBuffer[i].iSocketType);
328 switch (result->lpcsaBuffer[i].iProtocol)
331 printf(" %d: iProtocol = IPPROTO_TCP\n", i);
335 printf(" %d: iProtocol = IPPROTO_UDP\n", i);
339 printf(" %d: iProtocol = %d\n", i, result->lpcsaBuffer[i].iProtocol);
341 switch (result->lpcsaBuffer[i].LocalAddr.lpSockaddr->sa_family)
344 printf(" %d: loc family = AF_INET\n", i);
348 printf(" %d: loc family = AF_INET6\n", i);
352 printf(" %d: loc family = %hu\n", i, result->lpcsaBuffer[i].LocalAddr.lpSockaddr->sa_family);
354 switch (result->lpcsaBuffer[i].RemoteAddr.lpSockaddr->sa_family)
357 printf(" %d: rem family = AF_INET\n", i);
361 printf(" %d: rem family = AF_INET6\n", i);
365 printf(" %d: rem family = %hu\n", i, result->lpcsaBuffer[i].RemoteAddr.lpSockaddr->sa_family);
369 if (NO_ERROR == WSAAddressToStringA(result->lpcsaBuffer[i].LocalAddr.lpSockaddr, result->lpcsaBuffer[i].LocalAddr.iSockaddrLength, NULL, buf, &buflen))
370 printf("\tLocal Address #%d: %s\n", i, buf);
372 printf("\tLocal Address #%d: Can't convert: %lu\n", i, GetLastError());
374 if (NO_ERROR == WSAAddressToStringA(result->lpcsaBuffer[i].RemoteAddr.lpSockaddr, result->lpcsaBuffer[i].RemoteAddr.iSockaddrLength, NULL, buf, &buflen))
375 printf("\tRemote Address #%d: %s\n", i, buf);
377 printf("\tRemote Address #%d: Can't convert: %lu\n", i, GetLastError());
379 printf(" dwOutputFlags: 0x%08lX\n", result->dwOutputFlags);
380 printf(" lpBlob: 0x%p\n", result->lpBlob);
383 struct hostent *he = malloc(result->lpBlob->cbSize);
386 GNUNET_memcpy(he, result->lpBlob->pBlobData, result->lpBlob->cbSize);
393 ret = api.NSPLookupServiceEnd(lookup);
395 printf("NSPLookupServiceEnd() failed: %lu\n", GetLastError());
397 api.NSPCleanup(&prov);
410 memset(&hints, 0, sizeof(struct addrinfo));
411 hints.ai_family = AF_UNSPEC;
412 hints.ai_socktype = SOCK_STREAM;
414 if (0 != (s = GetAddrInfoW(wargv[2], NULL, &hints, &result)))
416 fprintf(stderr, "Cound not resolve `%S' using GetAddrInfoW: %lu\n",
417 wargv[2], GetLastError());
421 for (pos = result; pos != NULL; pos = pos->ai_next)
423 wchar_t tmpbuf[1024];
425 if (0 == WSAAddressToStringW(pos->ai_addr, pos->ai_addrlen, NULL, tmpbuf, &buflen))
426 fprintf(stderr, "Result:\n"
442 fprintf(stderr, "Result:\n"
455 L"<can't stringify>",
459 FreeAddrInfoW(result);