small whitespace change
[oweals/gnunet.git] / src / util / test_resolver_api.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009 Christian Grothoff (and other contributing authors)
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 2, 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., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20 /**
21  * @file resolver/test_resolver_api.c
22  * @brief testcase for resolver_api.c
23  */
24 #include "platform.h"
25 #include "gnunet_common.h"
26 #include "gnunet_getopt_lib.h"
27 #include "gnunet_os_lib.h"
28 #include "gnunet_program_lib.h"
29 #include "gnunet_scheduler_lib.h"
30 #include "gnunet_resolver_service.h"
31 #include "resolver.h"
32
33 #define VERBOSE GNUNET_NO
34
35 // Using dns rootservers to check gnunet's resolver service
36 // a.root-servers.net <-> 198.41.0.4 is a fix 1:1 mapping that should not change over years
37 // For more information have a look at IANA's website http://www.root-servers.org/
38 #define ROOTSERVER_NAME "a.root-servers.net"
39 #define ROOTSERVER_IP   "198.41.0.4"
40
41 static void
42 check_hostname (void *cls, const struct sockaddr *sa, socklen_t salen)
43 {
44   int *ok = cls;
45
46   if (salen == 0)
47     {
48       (*ok) &= ~8;
49       return;
50     }
51   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
52               _("Got IP address `%s' for our host.\n"),
53               GNUNET_a2s (sa, salen));
54 }
55
56
57 static void
58 check_localhost_num (void *cls, const char *hostname)
59 {
60   int *ok = cls;
61   if (hostname == NULL)
62     return;
63   if (0 == strcmp (hostname, "127.0.0.1"))
64     {
65 #if DEBUG_RESOLVER
66       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
67                   "Received correct hostname `%s'.\n", hostname);
68 #endif
69       (*ok) &= ~4;
70     }
71   else
72     {
73 #if DEBUG_RESOLVER
74       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
75                   "Received invalid hostname `%s'.\n", hostname);
76 #endif
77       GNUNET_break (0);
78     }
79 }
80
81 static void
82 check_localhost (void *cls, const char *hostname)
83 {
84   int *ok = cls;
85   if (hostname == NULL)
86     return;
87   if (0 == strcmp (hostname, "localhost"))
88     {
89 #if DEBUG_RESOLVER
90       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
91                   "Received correct hostname `%s'.\n", hostname);
92 #endif
93       (*ok) &= ~2;
94     }
95   else
96     {
97 #if DEBUG_RESOLVER
98       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
99                   "Received invalid hostname `%s'.\n", hostname);
100 #endif
101       GNUNET_break (0);
102     }
103 }
104
105 static void
106 check_127 (void *cls, const struct sockaddr *sa, socklen_t salen)
107 {
108   int *ok = cls;
109   const struct sockaddr_in *sai = (const struct sockaddr_in *) sa;
110
111   if (sa == NULL)
112     return;
113   GNUNET_assert (sizeof (struct sockaddr_in) == salen);
114   if (sai->sin_addr.s_addr == htonl (INADDR_LOOPBACK))
115     {
116 #if DEBUG_RESOLVER
117       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received correct address.\n");
118 #endif
119       (*ok) &= ~1;
120     }
121   else
122     {
123 #if DEBUG_RESOLVER
124       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received incorrect address.\n");
125 #endif
126       GNUNET_break (0);
127     }
128 }
129
130 static void
131 check_rootserver_ip (void *cls, const struct sockaddr *sa, socklen_t salen)
132 {
133   int *ok = cls;
134   const struct sockaddr_in *sai = (const struct sockaddr_in *) sa;
135
136   if (sa == NULL)
137     return;
138   GNUNET_assert (sizeof (struct sockaddr_in) == salen);
139   
140   if ( 0 == strcmp(inet_ntoa(sai->sin_addr),ROOTSERVER_IP))
141     {
142 #if DEBUG_RESOLVER
143       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received correct rootserver ip address.\n");
144 #endif
145       (*ok) &= ~1;
146     }
147   else
148     {
149 #if DEBUG_RESOLVER
150       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received incorrect rootserver ip address.\n");
151 #endif
152       GNUNET_break (0);
153     }
154 }
155
156 static void
157 check_rootserver_name (void *cls, const char *hostname)
158 {
159   int *ok = cls;
160   if (hostname == NULL)
161    return;
162     
163   if (0 == strcmp (hostname, ROOTSERVER_NAME))
164     {
165 #if DEBUG_RESOLVER
166       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
167                   "Received correct rootserver hostname `%s'.\n", hostname);
168 #endif
169       (*ok) &= ~2;
170     }
171   else
172     {
173 #if DEBUG_RESOLVER
174       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
175                   "Received invalid rootserver hostname `%s'.\n", hostname);
176 #endif
177       GNUNET_break (0);
178     }
179 }
180
181 static void
182 run (void *cls,
183      struct GNUNET_SCHEDULER_Handle *sched,
184      char *const *args,
185      const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg)
186 {
187   struct sockaddr_in sa;
188   struct GNUNET_TIME_Relative timeout =
189     GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
190                                    2500);
191   memset (&sa, 0, sizeof (sa));
192   sa.sin_family = AF_INET;
193   sa.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
194   GNUNET_RESOLVER_ip_get (sched,
195                           cfg,
196                           "localhost", AF_INET, timeout, &check_127, cls);
197   GNUNET_RESOLVER_hostname_get (sched,
198                                 cfg,
199                                 (const struct sockaddr *) &sa,
200                                 sizeof (struct sockaddr),
201                                 GNUNET_YES, timeout, &check_localhost, cls);
202   GNUNET_RESOLVER_hostname_get (sched,
203                                 cfg,
204                                 (const struct sockaddr *) &sa,
205                                 sizeof (struct sockaddr),
206                                 GNUNET_NO,
207                                 timeout, &check_localhost_num, cls);
208   GNUNET_RESOLVER_hostname_resolve (sched,
209                                     cfg,
210                                     AF_UNSPEC, timeout, &check_hostname, cls);
211   // Testing non-local dns resolution
212   // DNS Rootserver to test: a.root-servers.net - 198.41.0.4  
213   
214   char const * rootserver_name = ROOTSERVER_NAME;
215   
216   struct hostent *rootserver;
217   
218   rootserver = gethostbyname(rootserver_name);
219   if (rootserver == NULL)
220     {
221       // Error: resolving ip addresses does not work
222       #if DEBUG_RESOLVER
223       switch (h_errno)
224         {
225         
226         case HOST_NOT_FOUND: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "gethostbyname() could not lookup ip address: HOST_NOT_FOUND\n");break;
227         case NO_ADDRESS: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "gethostbyname() could not lookup ip address: NO_ADDRESS\n");break;
228         case NO_RECOVERY: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "gethostbyname() could not lookup ip address: NO_RECOVERY\n");break;
229         case TRY_AGAIN: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "gethostbyname() could not lookup ip address: TRY_AGAIN\n");break;
230         }
231       #endif
232       GNUNET_break (0);
233     }
234   else 
235   {
236     // Counting returned ip addresses
237     int count_ips =0 ;
238     while (rootserver->h_addr_list[count_ips]!=NULL)
239     {
240       count_ips++;
241     }    
242     if ( count_ips > 1) 
243     {
244       #if DEBUG_RESOLVER
245         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ip range for root name server, but a root nameserver has only 1 ip\n");
246       #endif
247       GNUNET_break (0);
248     }
249     
250     // Comparing to resolved address to the address the root nameserver should have
251     if ( strcmp(inet_ntoa( *(struct in_addr *) rootserver->h_addr_list[0]),ROOTSERVER_IP) !=0)
252     {
253       #if DEBUG_RESOLVER
254         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ip and ip for root name server differ\n");
255       #endif
256       GNUNET_break (0);      
257     }
258     
259     #if DEBUG_RESOLVER
260         GNUNET_log (GNUNET_ERROR_TYPE_INFO, "System's own forward name resolution is working\n");
261     #endif
262     
263     // Resolve the same using GNUNET
264     GNUNET_RESOLVER_ip_get (sched, cfg, ROOTSERVER_NAME, AF_INET, timeout, &check_rootserver_ip, cls);
265     
266     // Success: forward lookups work as exptected
267     
268     
269     // Next step: reverse lookups
270
271     struct in_addr rootserver_addr;
272     rootserver->h_name="";
273     if ( 1 != inet_pton(AF_INET, ROOTSERVER_IP, &rootserver_addr))
274     {
275       #if DEBUG_RESOLVER
276         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Could not transform root nameserver ip addressr\n");
277       #endif
278       GNUNET_break (0); 
279     }
280     
281     rootserver = gethostbyaddr(&rootserver_addr, sizeof(rootserver_addr), AF_INET);
282     if (rootserver == NULL)
283     {
284       // Error: resolving ip addresses does not work
285       #if DEBUG_RESOLVER
286       switch (h_errno)
287         {
288         
289         case HOST_NOT_FOUND: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "gethostbyaddr() could not lookup ip address: HOST_NOT_FOUND\n");break;
290         case NO_ADDRESS: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "gethostbyaddr() could not lookup ip address: NO_ADDRESS\n");break;
291         case NO_RECOVERY: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "gethostbyaddr() could not lookup ip address: NO_RECOVERY\n");break;
292         case TRY_AGAIN: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "gethostbyaddr() could not lookup ip address: TRY_AGAIN\n");break;
293         }
294       #endif
295       GNUNET_break (0);
296     }
297
298     if ( 0 != strcmp( rootserver->h_name,ROOTSERVER_NAME))
299     {
300       #if DEBUG_RESOLVER
301         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received hostname and hostname for root name server differ\n");
302       #endif
303       GNUNET_break (0); 
304     }
305     
306     #if DEBUG_RESOLVER
307         GNUNET_log (GNUNET_ERROR_TYPE_INFO, "System's own reverse name resolution is working\n");
308     #endif
309     // Resolve the same using GNUNET
310    
311     memset (&sa, 0, sizeof (sa));
312     sa.sin_family = AF_INET;
313     inet_aton(ROOTSERVER_IP, &sa.sin_addr.s_addr);
314     
315     GNUNET_RESOLVER_hostname_get (sched,
316                                 cfg,
317                                 (const struct sockaddr *) &sa,
318                                 sizeof (struct sockaddr),
319                                 GNUNET_YES,
320                                 timeout, &check_rootserver_name, cls);
321     
322     // Success: reverse lookups work as exptected    
323   } 
324 }
325
326 static int
327 check ()
328 {
329   int ok = 1 + 2 + 4 + 8;
330   char *fn;
331   char *pfx;
332   pid_t pid;
333   char *const argv[] = { "test-resolver-api",
334     "-c",
335     "test_resolver_api_data.conf",
336 #if VERBOSE
337     "-L", "DEBUG",
338 #endif
339     NULL
340   };
341   struct GNUNET_GETOPT_CommandLineOption options[] = {
342     GNUNET_GETOPT_OPTION_END
343   };
344   pfx = GNUNET_OS_installation_get_path(GNUNET_OS_IPK_BINDIR);
345   GNUNET_asprintf(&fn, "%s%cgnunet-service-resolver",
346                   pfx,
347                   DIR_SEPARATOR);
348   GNUNET_free (pfx);
349   pid = GNUNET_OS_start_process (NULL, NULL, fn,
350                                  "gnunet-service-resolver",
351 #if VERBOSE
352                                  "-L", "DEBUG",
353 #endif
354                                  "-c", "test_resolver_api_data.conf", NULL);
355   GNUNET_free (fn);
356   GNUNET_assert (GNUNET_OK == GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1,
357                                            argv, "test-resolver-api", "nohelp",
358                                            options, &run, &ok));
359   if (0 != PLIBC_KILL (pid, SIGTERM))
360     {
361       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
362       ok = 1;
363     }
364   GNUNET_OS_process_wait (pid);
365   if (ok != 0)
366     fprintf (stderr, "Missed some resolutions: %u\n", ok);
367   return ok;
368 }
369
370 int
371 main (int argc, char *argv[])
372 {
373   int ret;
374
375   GNUNET_log_setup ("test-resolver-api",
376 #if VERBOSE
377                     "DEBUG",
378 #else
379                     "WARNING",
380 #endif
381                     NULL);
382   ret = check ();
383
384   return ret;
385 }
386
387 /* end of test_resolver_api.c */