fix /tmp removal
[oweals/gnunet.git] / src / gns / w32nsp-resolve.c
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
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.
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      General Public License for more details.
14
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., 51 Franklin Street, Fifth Floor,
18      Boston, MA 02110-1301, USA.
19 */
20 /**
21  * @file gns/w32nsp-resolve.c
22  * @brief W32 integration for GNS
23  * @author LRN
24  */
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 }