884e4ba438354e32bf100878607aca9e8a4f481a
[oweals/gnunet.git] / src / gns / w32nsp-resolve.c
1 #define INITGUID
2 #include <windows.h>
3 #include <nspapi.h>
4 #include <ws2spi.h>
5 #include <nspapi.h>
6 #include <ws2tcpip.h>
7 #include "gnunet_w32nsp_lib.h"
8 #include <stdio.h>
9
10 typedef int (WSPAPI *LPNSPSTARTUP) (LPGUID lpProviderId, LPNSP_ROUTINE lpnspRoutines);
11
12 GUID host = {0x0002a800,0,0,{ 0xC0,0,0,0,0,0,0,0x46 }};
13 GUID ip4 = {0x00090035,0,1,{ 0xc0,0,0,0,0,0,0,0x046}}; 
14 GUID ip6 = {0x00090035,0,0x001c, { 0xc0,0,0,0,0,0,0,0x046}};
15
16 DEFINE_GUID(W32_DNS, 0x22059D40, 0x7E9E, 0x11CF, 0xAE, 0x5A, 0x00, 0xAA, 0x00, 0xA7, 0x11, 0x2B);
17
18 #define DEFINE_DNS_GUID(a,x) DEFINE_GUID(a, 0x00090035, 0x0000, x, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46)
19 DEFINE_DNS_GUID(SVCID_DNS_TYPE_A, 0x0001);
20 DEFINE_DNS_GUID(SVCID_DNS_TYPE_NS, 0x0002);
21 DEFINE_DNS_GUID(SVCID_DNS_TYPE_CNAME, 0x0005);
22 DEFINE_DNS_GUID(SVCID_DNS_TYPE_SOA, 0x0006);
23 DEFINE_DNS_GUID(SVCID_DNS_TYPE_PTR, 0x000c);
24 DEFINE_DNS_GUID(SVCID_DNS_TYPE_MX, 0x000f);
25 DEFINE_DNS_GUID(SVCID_DNS_TYPE_TEXT, 0x0010);
26 DEFINE_DNS_GUID(SVCID_DNS_TYPE_AAAA, 0x001c);
27 DEFINE_DNS_GUID(SVCID_DNS_TYPE_SRV, 0x0021);
28 DEFINE_GUID(SVCID_HOSTNAME, 0x0002a800, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
29 DEFINE_GUID(SVCID_INET_HOSTADDRBYNAME, 0x0002a803, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
30
31 //
32 // Utility to turn a list of offsets into a list of addresses. Used
33 // to convert structures returned as BLOBs.
34 //
35
36 VOID FixList(PCHAR ** List, PCHAR Base)
37 {
38     if(*List)
39     {
40         PCHAR * Addr;
41
42         Addr = *List = (PCHAR *)( ((DWORD)*List + Base) );
43         while(*Addr)
44         {
45             *Addr = (PCHAR)(((DWORD)*Addr + Base));
46             Addr++;
47         }
48     }
49 }
50
51
52 //
53 // Routine to convert a hostent returned in a BLOB to one with
54 // usable pointers. The structure is converted in-place.
55 //
56 VOID UnpackHostEnt(struct hostent * hostent)
57 {
58      PCHAR pch;
59
60      pch = (PCHAR)hostent;
61
62      if(hostent->h_name)
63      {
64          hostent->h_name = (PCHAR)((DWORD)hostent->h_name + pch);
65      }
66      FixList(&hostent->h_aliases, pch);
67      FixList(&hostent->h_addr_list, pch);
68 }
69
70 void
71 print_hostent (struct hostent *he)
72 {
73   int i;
74   char **pAlias;
75   printf("\tOfficial name: %s\n", he->h_name);
76   for (pAlias = he->h_aliases; *pAlias != 0; pAlias++) {
77       printf("\tAlternate name #%d: %s\n", ++i, *pAlias);
78   }
79   printf("\tAddress type: ");
80   switch (he->h_addrtype) {
81   case AF_INET:
82       printf("AF_INET\n");
83       break;
84   case AF_INET6:
85       printf("AF_INET6\n");
86       break;
87   case AF_NETBIOS:
88       printf("AF_NETBIOS\n");
89       break;
90   default:
91       printf(" %d\n", he->h_addrtype);
92       break;
93   }
94   printf("\tAddress length: %d\n", he->h_length);
95
96   if (he->h_addrtype == AF_INET) {
97     struct sockaddr_in addr;
98     memset (&addr, 0, sizeof (addr));
99     addr.sin_family = AF_INET;
100     addr.sin_port = 0;
101     i = 0;
102     while (he->h_addr_list[i] != 0) {
103       char buf[1024];
104       DWORD buflen = 1024;
105       addr.sin_addr = *(struct in_addr *) he->h_addr_list[i++];
106       if (NO_ERROR == WSAAddressToStringA ((LPSOCKADDR) &addr, sizeof (addr), NULL, buf, &buflen))
107         printf("\tIPv4 Address #%d: %s\n", i, buf);
108       else
109         printf("\tIPv4 Address #%d: Can't convert: %lu\n", i, GetLastError ());
110     }
111   } else if (he->h_addrtype == AF_INET6) {
112     struct sockaddr_in6 addr;
113     memset (&addr, 0, sizeof (addr));
114     addr.sin6_family = AF_INET6;
115     addr.sin6_port = 0;
116     i = 0;
117     while (he->h_addr_list[i] != 0) {
118       char buf[1024];
119       DWORD buflen = 1024;
120       addr.sin6_addr = *(struct in6_addr *) he->h_addr_list[i++];
121       if (NO_ERROR == WSAAddressToStringA ((LPSOCKADDR) &addr, sizeof (addr), NULL, buf, &buflen))
122         printf("\tIPv6 Address #%d: %s\n", i, buf);
123       else
124         printf("\tIPv6 Address #%d: Can't convert: %lu\n", i, GetLastError ());
125     }
126   }
127 }
128
129 int
130 main (int argc, char **argv)
131 {
132   int ret;
133   int r = 1;
134   WSADATA wsd;
135   GUID *prov = NULL;
136   GUID *sc = NULL;
137   wchar_t *cmdl;
138   int wargc;
139   wchar_t **wargv;
140
141   if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
142   {
143     fprintf (stderr, "WSAStartup() failed: %lu\n", GetLastError());
144     return 5;
145   }
146
147   cmdl = GetCommandLineW ();
148   if (cmdl == NULL)
149   {
150     WSACleanup();
151     return 2;
152   }
153   wargv = CommandLineToArgvW (cmdl, &wargc);
154   if (wargv == NULL)
155   {
156     WSACleanup();
157     return 3;
158   }
159   r = 4;
160
161   if (wargc == 5)
162   {
163     if (wcscmp (wargv[1], L"A") == 0)
164       sc = &SVCID_DNS_TYPE_A;
165     else if (wcscmp (wargv[1], L"AAAA") == 0)
166       sc = &SVCID_DNS_TYPE_AAAA;
167     else if (wcscmp (wargv[1], L"name") == 0)
168       sc = &SVCID_HOSTNAME;
169     else if (wcscmp (wargv[1], L"addr") == 0)
170       sc = &SVCID_INET_HOSTADDRBYNAME;
171     else
172       wargc -= 1;
173     if (wcscmp (wargv[4], L"mswdns") == 0)
174       prov = &W32_DNS;
175     else if (wcscmp (wargv[4], L"gnunetdns") == 0)
176       prov = &GNUNET_NAMESPACE_PROVIDER_DNS;
177     else
178       wargc -= 1;
179   }
180
181   if (wargc == 5)
182   {
183     HMODULE nsp;
184    
185     nsp = LoadLibraryW (wargv[3]);
186     if (nsp == NULL)
187     {
188       fprintf (stderr, "Failed to load library `%S'\n", wargv[3]);
189     }
190     else
191     {
192       LPNSPSTARTUP startup = (LPNSPSTARTUP) GetProcAddress (nsp, "NSPStartup");
193       if (startup != NULL)
194       {
195         NSP_ROUTINE api;
196         ret = startup (prov, &api);
197         if (NO_ERROR != ret)
198           fprintf (stderr, "startup failed\n");
199         else
200         {
201           HANDLE lookup;
202           WSAQUERYSETW search;
203           char buf[4096];
204           WSAQUERYSETW *result = (WSAQUERYSETW *) buf;
205           DWORD resultsize;
206           DWORD err;
207           memset (&search, 0, sizeof (search));
208           search.dwSize = sizeof (search);
209           search.lpszServiceInstanceName = (wcscmp (wargv[2], L" ") == 0) ? NULL : wargv[2];
210           search.lpServiceClassId = sc;
211           search.lpNSProviderId = prov;
212           search.dwNameSpace = NS_ALL;
213           ret = api.NSPLookupServiceBegin (prov, &search, NULL, LUP_RETURN_ALL, &lookup);
214           if (ret != NO_ERROR)
215           {
216             fprintf (stderr, "lookup start failed\n");
217           }
218           else
219           {
220             resultsize = 4096;
221             ret = api.NSPLookupServiceNext (lookup, LUP_RETURN_ALL, &resultsize, result);
222             err = GetLastError ();
223             if (ret != NO_ERROR)
224             {
225               fprintf (stderr, "lookup next failed\n");
226             }
227             else
228             {
229               int i;
230               printf ("Got result:\n");
231               printf ("  lpszServiceInstanceName: %S\n", result->lpszServiceInstanceName ? result->lpszServiceInstanceName : L"NULL");
232               if (result->lpServiceClassId)
233                 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",
234                     result->lpServiceClassId->Data1, result->lpServiceClassId->Data2, result->lpServiceClassId->Data3, result->lpServiceClassId->Data4[0],
235                     result->lpServiceClassId->Data4[1], result->lpServiceClassId->Data4[2], result->lpServiceClassId->Data4[3], result->lpServiceClassId->Data4[4],
236                     result->lpServiceClassId->Data4[5], result->lpServiceClassId->Data4[6], result->lpServiceClassId->Data4[7]);
237               else
238                 printf ("  lpServiceClassId:        NULL\n");
239               if (result->lpVersion)
240                 printf ("  lpVersion:               0x%08lX, %d\n", result->lpVersion->dwVersion, result->lpVersion->ecHow);
241               else
242                 printf ("  lpVersion:               NULL\n");
243               printf ("  lpszComment:             %S\n", result->lpszComment ? result->lpszComment : L"NULL");
244               printf ("  dwNameSpace:             %lu\n", result->dwNameSpace);
245               if (result->lpNSProviderId)
246                 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",
247                     result->lpNSProviderId->Data1, result->lpNSProviderId->Data2, result->lpNSProviderId->Data3, result->lpNSProviderId->Data4[0],
248                     result->lpNSProviderId->Data4[1], result->lpNSProviderId->Data4[2], result->lpNSProviderId->Data4[3], result->lpNSProviderId->Data4[4],
249                     result->lpNSProviderId->Data4[5], result->lpNSProviderId->Data4[6], result->lpNSProviderId->Data4[7]);
250               else
251                 printf ("  lpNSProviderId:          NULL\n");
252               printf ("  lpszContext:             %S\n", result->lpszContext ? result->lpszContext : L"NULL");
253               printf ("  dwNumberOfProtocols:     %lu\n", result->dwNumberOfProtocols);
254               printf ("  lpszQueryString:         %S\n", result->lpszQueryString ? result->lpszQueryString : L"NULL");
255               printf ("  dwNumberOfCsAddrs:       %lu\n", result->dwNumberOfCsAddrs);
256               for (i = 0; i < result->dwNumberOfCsAddrs; i++)
257               {
258                 switch (result->lpcsaBuffer[i].iSocketType)
259                 {
260                 case SOCK_STREAM:
261                   printf ("    %d: iSocketType = SOCK_STREAM\n", i);
262                   break;
263                 case SOCK_DGRAM:
264                   printf ("    %d: iSocketType = SOCK_DGRAM\n", i);
265                   break;
266                 default:
267                   printf ("    %d: iSocketType = %d\n", i, result->lpcsaBuffer[i].iSocketType);
268                 }
269                 switch (result->lpcsaBuffer[i].iProtocol)
270                 {
271                 case IPPROTO_TCP:
272                   printf ("    %d: iProtocol   = IPPROTO_TCP\n", i);
273                   break;
274                 case IPPROTO_UDP:
275                   printf ("    %d: iProtocol   = IPPROTO_UDP\n", i);
276                   break;
277                 default:
278                   printf ("    %d: iProtocol   = %d\n", i, result->lpcsaBuffer[i].iProtocol);
279                 }
280                 switch (result->lpcsaBuffer[i].LocalAddr.lpSockaddr->sa_family)
281                 {
282                 case AF_INET:
283                   printf ("    %d: loc family  = AF_INET\n", i);
284                   break;
285                 case AF_INET6:
286                   printf ("    %d: loc family  = AF_INET6\n", i);
287                   break;
288                 default:
289                   printf ("    %d: loc family  = %hu\n", i, result->lpcsaBuffer[i].LocalAddr.lpSockaddr->sa_family);
290                 }
291                 switch (result->lpcsaBuffer[i].RemoteAddr.lpSockaddr->sa_family)
292                 {
293                 case AF_INET:
294                   printf ("    %d: rem family  = AF_INET\n", i);
295                   break;
296                 case AF_INET6:
297                   printf ("    %d: rem family  = AF_INET6\n", i);
298                   break;
299                 default:
300                   printf ("    %d: rem family = %hu\n", i, result->lpcsaBuffer[i].RemoteAddr.lpSockaddr->sa_family);
301                 }
302                 char buf[1024];
303                 DWORD buflen = 1024;
304                 if (NO_ERROR == WSAAddressToStringA (result->lpcsaBuffer[i].LocalAddr.lpSockaddr, result->lpcsaBuffer[i].LocalAddr.iSockaddrLength, NULL, buf, &buflen))
305                   printf("\tLocal Address #%d: %s\n", i, buf);
306                 else
307                   printf("\tLocal Address #%d: Can't convert: %lu\n", i, GetLastError ());
308                 buflen = 1024;
309                 if (NO_ERROR == WSAAddressToStringA (result->lpcsaBuffer[i].RemoteAddr.lpSockaddr, result->lpcsaBuffer[i].RemoteAddr.iSockaddrLength, NULL, buf, &buflen))
310                   printf("\tRemote Address #%d: %s\n", i, buf);
311                 else
312                   printf("\tRemote Address #%d: Can't convert: %lu\n", i, GetLastError ());
313               }
314               printf ("  dwOutputFlags:           0x%08lX\n", result->dwOutputFlags);
315               printf ("  lpBlob:                  0x%p\n", result->lpBlob);
316               if (result->lpBlob)
317               {
318                 struct hostent *he = malloc (result->lpBlob->cbSize);
319                 if (he != NULL)
320                 {
321                   memcpy (he, result->lpBlob->pBlobData, result->lpBlob->cbSize);
322                   UnpackHostEnt (he);
323                   print_hostent (he);
324                   free (he);
325                 }
326               }
327             }
328             ret = api.NSPLookupServiceEnd (lookup);
329             if (ret != NO_ERROR)
330               printf ("NSPLookupServiceEnd() failed: %lu\n", GetLastError ());
331           }
332           api.NSPCleanup (prov);
333         }
334       }
335       FreeLibrary (nsp);
336     }
337   }
338   WSACleanup();
339   return r;
340 }