GNUnet  0.10.x
w32nsp-resolve.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2012 GNUnet e.V.
4 
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.
9 
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.
14 
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/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19 */
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)
27 
28 #include <ws2tcpip.h>
29 #include <windows.h>
30 #include <nspapi.h>
31 #include <ws2spi.h>
32 #include <nspapi.h>
33 #include <initguid.h>
34 #include "gnunet_w32nsp_lib.h"
35 #include <stdio.h>
36 
37 typedef int (WSPAPI *LPNSPSTARTUP) (LPGUID lpProviderId, LPNSP_ROUTINE lpnspRoutines);
38 
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}};
42 
43 DEFINE_GUID(W32_DNS, 0x22059D40, 0x7E9E, 0x11CF, 0xAE, 0x5A, 0x00, 0xAA, 0x00, 0xA7, 0x11, 0x2B);
44 
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);
57 
58 //
59 // Utility to turn a list of offsets into a list of addresses. Used
60 // to convert structures returned as BLOBs.
61 //
62 
63 VOID
64 FixList(PCHAR ** List, PCHAR Base)
65 {
66  if(*List)
67  {
68  PCHAR * Addr;
69 
70  Addr = *List = (PCHAR *)( ((DWORD)*List + Base) );
71  while(*Addr)
72  {
73  *Addr = (PCHAR)(((DWORD)*Addr + Base));
74  Addr++;
75  }
76  }
77 }
78 
79 
80 //
81 // Routine to convert a hostent returned in a BLOB to one with
82 // usable pointers. The structure is converted in-place.
83 //
84 VOID
85 UnpackHostEnt(struct hostent * hostent)
86 {
87  PCHAR pch;
88 
89  pch = (PCHAR)hostent;
90 
91  if(hostent->h_name)
92  {
93  hostent->h_name = (PCHAR)((DWORD)hostent->h_name + pch);
94  }
95  FixList(&hostent->h_aliases, pch);
96  FixList(&hostent->h_addr_list, pch);
97 }
98 
99 
100 static void
101 print_hostent (struct hostent *he)
102 {
103  int i;
104  char **pAlias;
105 
106  printf("\tOfficial name: %s\n", he->h_name);
107  for (i=0, pAlias = he->h_aliases; *pAlias != 0; pAlias++) {
108  printf("\tAlternate name #%d: %s\n", ++i, *pAlias);
109  }
110  printf("\tAddress type: ");
111  switch (he->h_addrtype) {
112  case AF_INET:
113  printf("AF_INET\n");
114  break;
115  case AF_INET6:
116  printf("AF_INET6\n");
117  break;
118  case AF_NETBIOS:
119  printf("AF_NETBIOS\n");
120  break;
121  default:
122  printf(" %d\n", he->h_addrtype);
123  break;
124  }
125  printf("\tAddress length: %d\n", he->h_length);
126 
127  if (he->h_addrtype == AF_INET) {
128  struct sockaddr_in addr;
129  memset (&addr, 0, sizeof (addr));
130  addr.sin_family = AF_INET;
131  addr.sin_port = 0;
132  i = 0;
133  while (he->h_addr_list[i] != 0) {
134  char buf[1024];
135  DWORD buflen = 1024;
136  addr.sin_addr = *(struct in_addr *) he->h_addr_list[i++];
137  if (NO_ERROR == WSAAddressToStringA ((LPSOCKADDR) &addr, sizeof (addr), NULL, buf, &buflen))
138  printf("\tIPv4 Address #%d: %s\n", i, buf);
139  else
140  printf("\tIPv4 Address #%d: Can't convert: %lu\n", i, GetLastError ());
141  }
142  } else if (he->h_addrtype == AF_INET6) {
143  struct sockaddr_in6 addr;
144  memset (&addr, 0, sizeof (addr));
145  addr.sin6_family = AF_INET6;
146  addr.sin6_port = 0;
147  i = 0;
148  while (he->h_addr_list[i] != 0) {
149  char buf[1024];
150  DWORD buflen = 1024;
151  addr.sin6_addr = *(struct in6_addr *) he->h_addr_list[i++];
152  if (NO_ERROR == WSAAddressToStringA ((LPSOCKADDR) &addr, sizeof (addr), NULL, buf, &buflen))
153  printf("\tIPv6 Address #%d: %s\n", i, buf);
154  else
155  printf("\tIPv6 Address #%d: Can't convert: %lu\n", i, GetLastError ());
156  }
157  }
158 }
159 
160 
161 int
162 main (int argc, char **argv)
163 {
164  int ret;
165  int r = 1;
166  WSADATA wsd;
167  GUID prov;
168  GUID sc;
169  wchar_t *cmdl;
170  int wargc;
171  wchar_t **wargv;
172 
173  if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
174  {
175  fprintf (stderr, "WSAStartup() failed: %lu\n", GetLastError());
176  return 5;
177  }
178 
179  cmdl = GetCommandLineW ();
180  if (cmdl == NULL)
181  {
182  WSACleanup();
183  return 2;
184  }
185  wargv = CommandLineToArgvW (cmdl, &wargc);
186  if (wargv == NULL)
187  {
188  WSACleanup();
189  return 3;
190  }
191  r = 4;
192 
193  if (wargc == 5)
194  {
195  if (wcscmp (wargv[1], L"A") == 0)
196  sc = SVCID_DNS_TYPE_A;
197  else if (wcscmp (wargv[1], L"AAAA") == 0)
198  sc = SVCID_DNS_TYPE_AAAA;
199  else if (wcscmp (wargv[1], L"name") == 0)
200  sc = SVCID_HOSTNAME;
201  else if (wcscmp (wargv[1], L"addr") == 0)
202  sc = SVCID_INET_HOSTADDRBYNAME;
203  else
204  wargc -= 1;
205  if (wcscmp (wargv[4], L"mswdns") == 0)
206  prov = W32_DNS;
207  else if (wcscmp (wargv[4], L"gnunetdns") == 0)
208  prov = GNUNET_NAMESPACE_PROVIDER_DNS;
209  else
210  wargc -= 1;
211  }
212  else if (wargc == 3)
213  {
214  }
215  else
216  {
217  fprintf (stderr, "Usage: %S <record type> <service name> <NSP library path> <NSP id>\n"
218  "record type - one of the following: A | AAAA | name | addr\n"
219  "service name - a string to resolve; \" \" (a space) means 'blank'\n"
220  "NSP library path - path to libw32nsp\n"
221  "NSP id - one of the following: mswdns | gnunetdns\n",
222  wargv[0]);
223  }
224 
225  if (wargc == 5)
226  {
227  HMODULE nsp;
228 
229  nsp = LoadLibraryW (wargv[3]);
230  if (nsp == NULL)
231  {
232  fprintf (stderr, "Failed to load library `%S'\n", wargv[3]);
233  }
234  else
235  {
236  LPNSPSTARTUP startup = (LPNSPSTARTUP) GetProcAddress (nsp, "NSPStartup");
237  if (startup == NULL)
238  startup = (LPNSPSTARTUP) GetProcAddress (nsp, "NSPStartup@8");
239  if (startup != NULL)
240  {
241  NSP_ROUTINE api;
242  api.cbSize = sizeof (api);
243  ret = startup (&prov, &api);
244  if (NO_ERROR != ret)
245  fprintf (stderr, "startup failed: %lu\n", GetLastError ());
246  else
247  {
248  HANDLE lookup;
249  WSAQUERYSETW search;
250  char buf[4096];
251  WSAQUERYSETW *result = (WSAQUERYSETW *) buf;
252  DWORD resultsize;
253  DWORD err;
254  memset (&search, 0, sizeof (search));
255  search.dwSize = sizeof (search);
256  search.lpszServiceInstanceName = (wcscmp (wargv[2], L" ") == 0) ? NULL : wargv[2];
257  search.lpServiceClassId = &sc;
258  search.lpNSProviderId = &prov;
259  search.dwNameSpace = NS_ALL;
260  ret = api.NSPLookupServiceBegin (&prov, &search, NULL, LUP_RETURN_ALL, &lookup);
261  if (ret != NO_ERROR)
262  {
263  fprintf (stderr, "lookup start failed\n");
264  }
265  else
266  {
267  resultsize = 4096;
268  ret = api.NSPLookupServiceNext (lookup, LUP_RETURN_ALL, &resultsize, result);
269  err = GetLastError ();
270  if (ret != NO_ERROR)
271  {
272  fprintf (stderr, "lookup next failed: %lu\n", err);
273  }
274  else
275  {
276  int i;
277  printf ("Got result:\n");
278  printf (" lpszServiceInstanceName: %S\n", result->lpszServiceInstanceName ? result->lpszServiceInstanceName : L"NULL");
279  if (result->lpServiceClassId)
280  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",
281  result->lpServiceClassId->Data1, result->lpServiceClassId->Data2, result->lpServiceClassId->Data3, result->lpServiceClassId->Data4[0],
282  result->lpServiceClassId->Data4[1], result->lpServiceClassId->Data4[2], result->lpServiceClassId->Data4[3], result->lpServiceClassId->Data4[4],
283  result->lpServiceClassId->Data4[5], result->lpServiceClassId->Data4[6], result->lpServiceClassId->Data4[7]);
284  else
285  printf (" lpServiceClassId: NULL\n");
286  if (result->lpVersion)
287  printf (" lpVersion: 0x%08lX, %d\n", result->lpVersion->dwVersion, result->lpVersion->ecHow);
288  else
289  printf (" lpVersion: NULL\n");
290  printf (" lpszComment: %S\n", result->lpszComment ? result->lpszComment : L"NULL");
291  printf (" dwNameSpace: %lu\n", result->dwNameSpace);
292  if (result->lpNSProviderId)
293  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",
294  result->lpNSProviderId->Data1, result->lpNSProviderId->Data2, result->lpNSProviderId->Data3, result->lpNSProviderId->Data4[0],
295  result->lpNSProviderId->Data4[1], result->lpNSProviderId->Data4[2], result->lpNSProviderId->Data4[3], result->lpNSProviderId->Data4[4],
296  result->lpNSProviderId->Data4[5], result->lpNSProviderId->Data4[6], result->lpNSProviderId->Data4[7]);
297  else
298  printf (" lpNSProviderId: NULL\n");
299  printf (" lpszContext: %S\n", result->lpszContext ? result->lpszContext : L"NULL");
300  printf (" dwNumberOfProtocols: %lu\n", result->dwNumberOfProtocols);
301  printf (" lpszQueryString: %S\n", result->lpszQueryString ? result->lpszQueryString : L"NULL");
302  printf (" dwNumberOfCsAddrs: %lu\n", result->dwNumberOfCsAddrs);
303  for (i = 0; i < result->dwNumberOfCsAddrs; i++)
304  {
305  switch (result->lpcsaBuffer[i].iSocketType)
306  {
307  case SOCK_STREAM:
308  printf (" %d: iSocketType = SOCK_STREAM\n", i);
309  break;
310  case SOCK_DGRAM:
311  printf (" %d: iSocketType = SOCK_DGRAM\n", i);
312  break;
313  default:
314  printf (" %d: iSocketType = %d\n", i, result->lpcsaBuffer[i].iSocketType);
315  }
316  switch (result->lpcsaBuffer[i].iProtocol)
317  {
318  case IPPROTO_TCP:
319  printf (" %d: iProtocol = IPPROTO_TCP\n", i);
320  break;
321  case IPPROTO_UDP:
322  printf (" %d: iProtocol = IPPROTO_UDP\n", i);
323  break;
324  default:
325  printf (" %d: iProtocol = %d\n", i, result->lpcsaBuffer[i].iProtocol);
326  }
327  switch (result->lpcsaBuffer[i].LocalAddr.lpSockaddr->sa_family)
328  {
329  case AF_INET:
330  printf (" %d: loc family = AF_INET\n", i);
331  break;
332  case AF_INET6:
333  printf (" %d: loc family = AF_INET6\n", i);
334  break;
335  default:
336  printf (" %d: loc family = %hu\n", i, result->lpcsaBuffer[i].LocalAddr.lpSockaddr->sa_family);
337  }
338  switch (result->lpcsaBuffer[i].RemoteAddr.lpSockaddr->sa_family)
339  {
340  case AF_INET:
341  printf (" %d: rem family = AF_INET\n", i);
342  break;
343  case AF_INET6:
344  printf (" %d: rem family = AF_INET6\n", i);
345  break;
346  default:
347  printf (" %d: rem family = %hu\n", i, result->lpcsaBuffer[i].RemoteAddr.lpSockaddr->sa_family);
348  }
349  char buf[1024];
350  DWORD buflen = 1024;
351  if (NO_ERROR == WSAAddressToStringA (result->lpcsaBuffer[i].LocalAddr.lpSockaddr, result->lpcsaBuffer[i].LocalAddr.iSockaddrLength, NULL, buf, &buflen))
352  printf("\tLocal Address #%d: %s\n", i, buf);
353  else
354  printf("\tLocal Address #%d: Can't convert: %lu\n", i, GetLastError ());
355  buflen = 1024;
356  if (NO_ERROR == WSAAddressToStringA (result->lpcsaBuffer[i].RemoteAddr.lpSockaddr, result->lpcsaBuffer[i].RemoteAddr.iSockaddrLength, NULL, buf, &buflen))
357  printf("\tRemote Address #%d: %s\n", i, buf);
358  else
359  printf("\tRemote Address #%d: Can't convert: %lu\n", i, GetLastError ());
360  }
361  printf (" dwOutputFlags: 0x%08lX\n", result->dwOutputFlags);
362  printf (" lpBlob: 0x%p\n", result->lpBlob);
363  if (result->lpBlob)
364  {
365  struct hostent *he = malloc (result->lpBlob->cbSize);
366  if (he != NULL)
367  {
368  GNUNET_memcpy (he, result->lpBlob->pBlobData, result->lpBlob->cbSize);
369  UnpackHostEnt (he);
370  print_hostent (he);
371  free (he);
372  }
373  }
374  }
375  ret = api.NSPLookupServiceEnd (lookup);
376  if (ret != NO_ERROR)
377  printf ("NSPLookupServiceEnd() failed: %lu\n", GetLastError ());
378  }
379  api.NSPCleanup (&prov);
380  }
381  }
382  FreeLibrary (nsp);
383  }
384  }
385  else if (wargc == 3)
386  {
387  int s;
388  ADDRINFOW hints;
389  ADDRINFOW *result;
390  ADDRINFOW *pos;
391 
392  memset (&hints, 0, sizeof (struct addrinfo));
393  hints.ai_family = AF_UNSPEC;
394  hints.ai_socktype = SOCK_STREAM;
395 
396  if (0 != (s = GetAddrInfoW (wargv[2], NULL, &hints, &result)))
397  {
398  fprintf (stderr, "Cound not resolve `%S' using GetAddrInfoW: %lu\n",
399  wargv[2], GetLastError ());
400  }
401  else
402  {
403  for (pos = result; pos != NULL; pos = pos->ai_next)
404  {
405  wchar_t tmpbuf[1024];
406  DWORD buflen = 1024;
407  if (0 == WSAAddressToStringW (pos->ai_addr, pos->ai_addrlen, NULL, tmpbuf, &buflen))
408  fprintf (stderr, "Result:\n"
409  " flags: 0x%X\n"
410  " family: 0x%X\n"
411  " socktype: 0x%X\n"
412  " protocol: 0x%X\n"
413  " addrlen: %u\n"
414  " addr: %S\n"
415  " canonname: %S\n",
416  pos->ai_flags,
417  pos->ai_family,
418  pos->ai_socktype,
419  pos->ai_protocol,
420  pos->ai_addrlen,
421  tmpbuf,
422  pos->ai_canonname);
423  else
424  fprintf (stderr, "Result:\n"
425  " flags: 0x%X\n"
426  " family: 0x%X\n"
427  " socktype: 0x%X\n"
428  " protocol: 0x%X\n"
429  " addrlen: %u\n"
430  " addr: %S\n"
431  " canonname: %S\n",
432  pos->ai_flags,
433  pos->ai_family,
434  pos->ai_socktype,
435  pos->ai_protocol,
436  pos->ai_addrlen,
437  L"<can't stringify>",
438  pos->ai_canonname);
439  }
440  if (NULL != result)
441  FreeAddrInfoW (result);
442  }
443  }
444  WSACleanup();
445  return r;
446 }
#define DEFINE_DNS_GUID(a, x)
int(WSPAPI * LPNSPSTARTUP)(LPGUID lpProviderId, LPNSP_ROUTINE lpnspRoutines)
static void print_hostent(struct hostent *he)
static int ret
Final status code.
Definition: gnunet-arm.c:89
#define GNUNET_memcpy(dst, src, n)
static char buf[2048]
int main(int argc, char **argv)
static int result
Global testing status.
GUID ip4
GUID host
static struct GNUNET_FS_SearchContext * sc
Definition: gnunet-search.c:37
static struct GNUNET_SCHEDULER_Task * pch
Handle for the parent_control_handler() Task.
Definition: os_priority.c:71
VOID UnpackHostEnt(struct hostent *hostent)
VOID FixList(PCHAR **List, PCHAR Base)
DEFINE_GUID(W32_DNS, 0x22059D40, 0x7E9E, 0x11CF, 0xAE, 0x5A, 0x00, 0xAA, 0x00, 0xA7, 0x11, 0x2B)
GUID ip6