source code changed to meet coding conventions
[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 root servers 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   int count_ips =0 ;
194
195   memset (&sa, 0, sizeof (sa));
196   sa.sin_family = AF_INET;
197   sa.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
198   GNUNET_RESOLVER_ip_get (sched,
199                 cfg,
200                 "localhost", AF_INET, timeout, &check_127, cls);
201   GNUNET_RESOLVER_hostname_get (sched,
202                 cfg,
203                 (const struct sockaddr *) &sa,
204                 sizeof (struct sockaddr),
205                 GNUNET_YES, timeout, &check_localhost, cls);
206   GNUNET_RESOLVER_hostname_get (sched,
207                 cfg,
208                 (const struct sockaddr *) &sa,
209                 sizeof (struct sockaddr),
210                 GNUNET_NO,
211                 timeout, &check_localhost_num, cls);
212   GNUNET_RESOLVER_hostname_resolve (sched,
213                 cfg,
214                 AF_UNSPEC, timeout, &check_hostname, cls);
215   /*
216    * Testing non-local DNS resolution
217    * DNS rootserver to test: a.root-servers.net - 198.41.0.4
218    */
219   
220   char const * rootserver_name = ROOTSERVER_NAME;
221   struct hostent *rootserver;
222   
223   rootserver = gethostbyname(rootserver_name);
224   if (rootserver == NULL)
225     {
226   /* Error: resolving ip addresses does not work */
227 #if DEBUG_RESOLVER
228           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
229                   _("gethostbyname() could not lookup IP address: %s\n"),
230                   hstrerror (h_errno));
231 #endif
232           GNUNET_break (0);
233       return;
234     }
235
236     /* Counting returned IP addresses */
237     while (rootserver->h_addr_list[count_ips]!=NULL)
238       count_ips++;
239     if ( count_ips > 1) 
240     {
241 #if DEBUG_RESOLVER
242         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "IP received range for root name server, but a root name server has only 1 IP\n");
243 #endif
244                 GNUNET_break (0);
245     }
246     
247     /* Comparing to resolved address to the address the root name server should have */
248     if ( strcmp(inet_ntoa( *(struct in_addr *) rootserver->h_addr_list[0]),ROOTSERVER_IP) !=0)
249     {
250 #if DEBUG_RESOLVER
251         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "IP received and IP for root name server differ\n");
252 #endif
253       GNUNET_break (0);      
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     /*
263      * Success: forward lookups work as expected
264      * Next step: reverse lookups
265      */
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 name server IP address\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           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
283                   _("gethostbyaddr() could not lookup hostname: %s\n"),
284                   hstrerror (h_errno));
285 #endif
286       GNUNET_break (0);
287     }
288
289     if ( 0 != strcmp( rootserver->h_name,ROOTSERVER_NAME))
290     {
291 #if DEBUG_RESOLVER
292         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received hostname and hostname for root name server differ\n");
293 #endif
294         GNUNET_break (0);
295     }
296     
297 #if DEBUG_RESOLVER
298         GNUNET_log (GNUNET_ERROR_TYPE_INFO, "System's own reverse name resolution is working\n");
299 #endif
300     /* Resolve the same using GNUNET */
301    
302     memset (&sa, 0, sizeof (sa));
303     sa.sin_family = AF_INET;
304     inet_aton(ROOTSERVER_IP, &sa.sin_addr);
305     
306     GNUNET_RESOLVER_hostname_get (sched,
307                                 cfg,
308                                 (const struct sockaddr *) &sa,
309                                 sizeof (struct sockaddr),
310                                 GNUNET_YES,
311                                 timeout, &check_rootserver_name, cls);
312 }
313
314 static int
315 check ()
316 {
317   int ok = 1 + 2 + 4 + 8;
318   char *fn;
319   char *pfx;
320   pid_t pid;
321   char *const argv[] = { "test-resolver-api",
322     "-c",
323     "test_resolver_api_data.conf",
324 #if VERBOSE
325     "-L", "DEBUG",
326 #endif
327     NULL
328   };
329   struct GNUNET_GETOPT_CommandLineOption options[] = {
330     GNUNET_GETOPT_OPTION_END
331   };
332   pfx = GNUNET_OS_installation_get_path(GNUNET_OS_IPK_BINDIR);
333   GNUNET_asprintf(&fn, "%s%cgnunet-service-resolver",
334                   pfx,
335                   DIR_SEPARATOR);
336   GNUNET_free (pfx);
337   pid = GNUNET_OS_start_process (NULL, NULL, fn,
338                                  "gnunet-service-resolver",
339 #if VERBOSE
340                                  "-L", "DEBUG",
341 #endif
342                                  "-c", "test_resolver_api_data.conf", NULL);
343   GNUNET_free (fn);
344   GNUNET_assert (GNUNET_OK == GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1,
345                                            argv, "test-resolver-api", "nohelp",
346                                            options, &run, &ok));
347   if (0 != PLIBC_KILL (pid, SIGTERM))
348     {
349       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
350       ok = 1;
351     }
352   GNUNET_OS_process_wait (pid);
353   if (ok != 0)
354     fprintf (stderr, "Missed some resolutions: %u\n", ok);
355   return ok;
356 }
357
358 int
359 main (int argc, char *argv[])
360 {
361   int ret;
362
363   GNUNET_log_setup ("test-resolver-api",
364 #if VERBOSE
365                     "DEBUG",
366 #else
367                     "WARNING",
368 #endif
369                     NULL);
370   ret = check ();
371
372   return ret;
373 }
374
375 /* end of test_resolver_api.c */