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