aboutsummaryrefslogtreecommitdiff
path: root/src/util/gnunet-service-resolver.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-01-27 12:46:51 +0000
committerChristian Grothoff <christian@grothoff.org>2012-01-27 12:46:51 +0000
commitfae775b8e3ebc6e19b97156d3a3008ee91c3b64b (patch)
tree12c7d0f18bc3f1f00f356df0f493c71ee006dda3 /src/util/gnunet-service-resolver.c
parentf4c1249ba12461abe0616963959b9470a41e1de5 (diff)
downloadgnunet-fae775b8e3ebc6e19b97156d3a3008ee91c3b64b.tar.gz
gnunet-fae775b8e3ebc6e19b97156d3a3008ee91c3b64b.zip
-fixing #2116
Diffstat (limited to 'src/util/gnunet-service-resolver.c')
-rw-r--r--src/util/gnunet-service-resolver.c363
1 files changed, 192 insertions, 171 deletions
diff --git a/src/util/gnunet-service-resolver.c b/src/util/gnunet-service-resolver.c
index 5d4c5c224..f20666a38 100644
--- a/src/util/gnunet-service-resolver.c
+++ b/src/util/gnunet-service-resolver.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 (C) 2007, 2008, 2009 Christian Grothoff (and other contributing authors) 3 (C) 2007, 2008, 2009, 2012 Christian Grothoff (and other contributing authors)
4 4
5 GNUnet is free software; you can redistribute it and/or modify 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 6 it under the terms of the GNU General Public License as published
@@ -24,13 +24,9 @@
24 * @author Christian Grothoff 24 * @author Christian Grothoff
25 */ 25 */
26#include "platform.h" 26#include "platform.h"
27#include "gnunet_disk_lib.h" 27#include "gnunet_util_lib.h"
28#include "gnunet_getopt_lib.h"
29#include "gnunet_protocols.h" 28#include "gnunet_protocols.h"
30#include "gnunet_service_lib.h"
31#include "gnunet_statistics_service.h" 29#include "gnunet_statistics_service.h"
32#include "gnunet_strings_lib.h"
33#include "gnunet_time_lib.h"
34#include "resolver.h" 30#include "resolver.h"
35 31
36/** 32/**
@@ -39,19 +35,24 @@
39struct IPCache 35struct IPCache
40{ 36{
41 /** 37 /**
42 * This is a linked list. 38 * This is a doubly linked list.
43 */ 39 */
44 struct IPCache *next; 40 struct IPCache *next;
45 41
46 /** 42 /**
43 * This is a doubly linked list.
44 */
45 struct IPCache *prev;
46
47 /**
47 * Hostname in human-readable form. 48 * Hostname in human-readable form.
48 */ 49 */
49 char *addr; 50 char *addr;
50 51
51 /** 52 /**
52 * Hostname in binary format. 53 * Binary IP address, allocated at the end of this struct.
53 */ 54 */
54 struct sockaddr *sa; 55 const void *ip;
55 56
56 /** 57 /**
57 * Last time this entry was updated. 58 * Last time this entry was updated.
@@ -64,16 +65,26 @@ struct IPCache
64 struct GNUNET_TIME_Absolute last_request; 65 struct GNUNET_TIME_Absolute last_request;
65 66
66 /** 67 /**
67 * Number of bytes in sa. 68 * Number of bytes in ip.
69 */
70 size_t ip_len;
71
72 /**
73 * Address family of the IP.
68 */ 74 */
69 socklen_t salen; 75 int af;
70}; 76};
71 77
72 78
73/** 79/**
74 * Start of the linked list of cached DNS lookup results. 80 * Start of the linked list of cached DNS lookup results.
75 */ 81 */
76static struct IPCache *head; 82static struct IPCache *cache_head;
83
84/**
85 * Tail of the linked list of cached DNS lookup results.
86 */
87static struct IPCache *cache_tail;
77 88
78 89
79#if HAVE_GETNAMEINFO 90#if HAVE_GETNAMEINFO
@@ -86,9 +97,41 @@ static void
86getnameinfo_resolve (struct IPCache *cache) 97getnameinfo_resolve (struct IPCache *cache)
87{ 98{
88 char hostname[256]; 99 char hostname[256];
100 const struct sockaddr *sa;
101 struct sockaddr_in v4;
102 struct sockaddr_in6 v6;
103 size_t salen;
104
105 switch (cache->af)
106 {
107 case AF_INET:
108 GNUNET_assert (cache->ip_len == sizeof (struct in_addr));
109 sa = (const struct sockaddr*) &v4;
110 memset (&v4, 0, sizeof (v4));
111 v4.sin_addr = * (const struct in_addr*) cache->ip;
112 v4.sin_family = AF_INET;
113#if HAVE_SOCKADDR_IN_SIN_LEN
114 v4.sin_len = sizeof (v4);
115#endif
116 salen = sizeof (v4);
117 break;
118 case AF_INET6:
119 GNUNET_assert (cache->ip_len == sizeof (struct in6_addr));
120 sa = (const struct sockaddr*) &v6;
121 memset (&v6, 0, sizeof (v6));
122 v6.sin6_addr = * (const struct in6_addr*) cache->ip;
123 v6.sin6_family = AF_INET6;
124#if HAVE_SOCKADDR_IN_SIN_LEN
125 v6.sin6_len = sizeof (v6);
126#endif
127 salen = sizeof (v6);
128 break;
129 default:
130 GNUNET_assert (0);
131 }
89 132
90 if (0 == 133 if (0 ==
91 getnameinfo (cache->sa, cache->salen, hostname, sizeof (hostname), NULL, 134 getnameinfo (sa, salen, hostname, sizeof (hostname), NULL,
92 0, 0)) 135 0, 0))
93 cache->addr = GNUNET_strdup (hostname); 136 cache->addr = GNUNET_strdup (hostname);
94} 137}
@@ -106,26 +149,15 @@ gethostbyaddr_resolve (struct IPCache *cache)
106{ 149{
107 struct hostent *ent; 150 struct hostent *ent;
108 151
109 switch (cache->sa->sa_family) 152 ent = gethostbyaddr (cache->ip,
110 { 153 cache->ip_len,
111 case AF_INET: 154 cache->af);
112 ent =
113 gethostbyaddr (&((struct sockaddr_in *) cache->sa)->sin_addr,
114 sizeof (struct in_addr), AF_INET);
115 break;
116 case AF_INET6:
117 ent =
118 gethostbyaddr (&((struct sockaddr_in6 *) cache->sa)->sin6_addr,
119 sizeof (struct in6_addr), AF_INET6);
120 break;
121 default:
122 ent = NULL;
123 }
124 if (ent != NULL) 155 if (ent != NULL)
125 cache->addr = GNUNET_strdup (ent->h_name); 156 cache->addr = GNUNET_strdup (ent->h_name);
126} 157}
127#endif 158#endif
128 159
160
129/** 161/**
130 * Resolve the given request using the available methods. 162 * Resolve the given request using the available methods.
131 * 163 *
@@ -145,7 +177,6 @@ cache_resolve (struct IPCache *cache)
145} 177}
146 178
147 179
148
149/** 180/**
150 * Get an IP address as a string (works for both IPv4 and IPv6). Note 181 * Get an IP address as a string (works for both IPv4 and IPv6). Note
151 * that the resolution happens asynchronously and that the first call 182 * that the resolution happens asynchronously and that the first call
@@ -153,83 +184,79 @@ cache_resolve (struct IPCache *cache)
153 * human-readable IP address). 184 * human-readable IP address).
154 * 185 *
155 * @param client handle to the client making the request (for sending the reply) 186 * @param client handle to the client making the request (for sending the reply)
156 * @param sa should be of type "struct sockaddr*" 187 * @param af AF_INET or AF_INET6
157 * @param salen number of bytes in sa 188 * @param ip 'struct in_addr' or 'struct in6_addr'
158 */ 189 */
159static void 190static void
160get_ip_as_string (struct GNUNET_SERVER_Client *client, 191get_ip_as_string (struct GNUNET_SERVER_Client *client,
161 const struct sockaddr *sa, socklen_t salen) 192 int af,
193 const void *ip)
162{ 194{
163 struct IPCache *cache; 195 struct IPCache *pos;
164 struct IPCache *prev; 196 struct IPCache *next;
165 struct GNUNET_TIME_Absolute now; 197 struct GNUNET_TIME_Absolute now;
166 struct GNUNET_SERVER_TransmitContext *tc; 198 struct GNUNET_SERVER_TransmitContext *tc;
199 size_t ip_len;
167 200
168 if (salen < sizeof (struct sockaddr)) 201 switch (af)
169 { 202 {
170 GNUNET_break (0); 203 case AF_INET:
171 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 204 ip_len = sizeof (struct in_addr);
172 return; 205 break;
206 case AF_INET6:
207 ip_len = sizeof (struct in6_addr);
208 break;
209 default:
210 GNUNET_assert (0);
173 } 211 }
174 now = GNUNET_TIME_absolute_get (); 212 now = GNUNET_TIME_absolute_get ();
175 cache = head; 213 next = cache_head;
176 prev = NULL; 214 while ( (NULL != (pos = next)) &&
177 while ((cache != NULL) && 215 ( (pos->af != af) ||
178 ((cache->salen != salen) || (0 != memcmp (cache->sa, sa, salen)))) 216 (pos->ip_len != ip_len) ||
217 (0 != memcmp (pos->ip, ip, ip_len))) )
179 { 218 {
180 if (GNUNET_TIME_absolute_get_duration (cache->last_request).rel_value < 219 next = pos->next;
220 if (GNUNET_TIME_absolute_get_duration (pos->last_request).rel_value <
181 60 * 60 * 1000) 221 60 * 60 * 1000)
182 { 222 {
183 if (prev != NULL) 223 GNUNET_CONTAINER_DLL_remove (cache_head,
184 { 224 cache_tail,
185 prev->next = cache->next; 225 pos);
186 GNUNET_free_non_null (cache->addr); 226 GNUNET_free_non_null (pos->addr);
187 GNUNET_free (cache->sa); 227 GNUNET_free (pos);
188 GNUNET_free (cache);
189 cache = prev->next;
190 }
191 else
192 {
193 head = cache->next;
194 GNUNET_free_non_null (cache->addr);
195 GNUNET_free (cache->sa);
196 GNUNET_free (cache);
197 cache = head;
198 }
199 continue; 228 continue;
200 } 229 }
201 prev = cache;
202 cache = cache->next;
203 } 230 }
204 if (cache != NULL) 231 if (pos != NULL)
205 { 232 {
206 cache->last_request = now; 233 pos->last_request = now;
207 if (GNUNET_TIME_absolute_get_duration (cache->last_request).rel_value < 234 if (GNUNET_TIME_absolute_get_duration (pos->last_request).rel_value <
208 60 * 60 * 1000) 235 60 * 60 * 1000)
209 { 236 {
210 GNUNET_free_non_null (cache->addr); 237 GNUNET_free_non_null (pos->addr);
211 cache->addr = NULL; 238 pos->addr = NULL;
212 cache->salen = 0; 239 cache_resolve (pos);
213 cache_resolve (cache);
214 } 240 }
215 } 241 }
216 else 242 else
217 { 243 {
218 cache = GNUNET_malloc (sizeof (struct IPCache)); 244 pos = GNUNET_malloc (sizeof (struct IPCache) + ip_len);
219 cache->next = head; 245 pos->ip = &pos[1];
220 cache->salen = salen; 246 memcpy (&pos[1], ip, ip_len);
221 cache->sa = GNUNET_malloc (salen); 247 pos->last_request = now;
222 memcpy (cache->sa, sa, salen); 248 pos->last_refresh = now;
223 cache->last_request = GNUNET_TIME_absolute_get (); 249 pos->ip_len = ip_len;
224 cache->last_refresh = GNUNET_TIME_absolute_get (); 250 pos->af = af;
225 cache->addr = NULL; 251 GNUNET_CONTAINER_DLL_insert (cache_head,
226 cache_resolve (cache); 252 cache_tail,
227 head = cache; 253 pos);
254 cache_resolve (pos);
228 } 255 }
229 tc = GNUNET_SERVER_transmit_context_create (client); 256 tc = GNUNET_SERVER_transmit_context_create (client);
230 if (cache->addr != NULL) 257 if (pos->addr != NULL)
231 GNUNET_SERVER_transmit_context_append_data (tc, cache->addr, 258 GNUNET_SERVER_transmit_context_append_data (tc, pos->addr,
232 strlen (cache->addr) + 1, 259 strlen (pos->addr) + 1,
233 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); 260 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE);
234 GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0, 261 GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
235 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); 262 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE);
@@ -240,7 +267,7 @@ get_ip_as_string (struct GNUNET_SERVER_Client *client,
240#if HAVE_GETADDRINFO 267#if HAVE_GETADDRINFO
241static int 268static int
242getaddrinfo_resolve (struct GNUNET_SERVER_TransmitContext *tc, 269getaddrinfo_resolve (struct GNUNET_SERVER_TransmitContext *tc,
243 const char *hostname, int domain) 270 const char *hostname, int af)
244{ 271{
245 int s; 272 int s;
246 struct addrinfo hints; 273 struct addrinfo hints;
@@ -250,7 +277,7 @@ getaddrinfo_resolve (struct GNUNET_SERVER_TransmitContext *tc,
250 memset (&hints, 0, sizeof (struct addrinfo)); 277 memset (&hints, 0, sizeof (struct addrinfo));
251// FIXME in PlibC 278// FIXME in PlibC
252#ifndef MINGW 279#ifndef MINGW
253 hints.ai_family = domain; 280 hints.ai_family = af;
254#else 281#else
255 hints.ai_family = AF_INET; 282 hints.ai_family = AF_INET;
256#endif 283#endif
@@ -260,8 +287,8 @@ getaddrinfo_resolve (struct GNUNET_SERVER_TransmitContext *tc,
260 { 287 {
261 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Could not resolve `%s' (%s): %s\n"), 288 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Could not resolve `%s' (%s): %s\n"),
262 hostname, 289 hostname,
263 (domain == 290 (af ==
264 AF_INET) ? "IPv4" : ((domain == AF_INET6) ? "IPv6" : "any"), 291 AF_INET) ? "IPv4" : ((af == AF_INET6) ? "IPv6" : "any"),
265 gai_strerror (s)); 292 gai_strerror (s));
266 if ((s == EAI_BADFLAGS) || (s == EAI_MEMORY) 293 if ((s == EAI_BADFLAGS) || (s == EAI_MEMORY)
267#ifndef MINGW 294#ifndef MINGW
@@ -279,9 +306,24 @@ getaddrinfo_resolve (struct GNUNET_SERVER_TransmitContext *tc,
279 pos = result; 306 pos = result;
280 while (pos != NULL) 307 while (pos != NULL)
281 { 308 {
282 GNUNET_SERVER_transmit_context_append_data (tc, pos->ai_addr, 309 switch (pos->ai_family)
283 pos->ai_addrlen, 310 {
284 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); 311 case AF_INET:
312 GNUNET_SERVER_transmit_context_append_data (tc,
313 &((struct sockaddr_in*) pos->ai_addr)->sin_addr,
314 sizeof (struct in_addr),
315 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE);
316 break;
317 case AF_INET6:
318 GNUNET_SERVER_transmit_context_append_data (tc,
319 &((struct sockaddr_in6*) pos->ai_addr)->sin6_addr,
320 sizeof (struct in6_addr),
321 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE);
322 break;
323 default:
324 /* unsupported, skip */
325 break;
326 }
285 pos = pos->ai_next; 327 pos = pos->ai_next;
286 } 328 }
287 freeaddrinfo (result); 329 freeaddrinfo (result);
@@ -289,18 +331,17 @@ getaddrinfo_resolve (struct GNUNET_SERVER_TransmitContext *tc,
289} 331}
290#endif 332#endif
291 333
334
292#if HAVE_GETHOSTBYNAME2 335#if HAVE_GETHOSTBYNAME2
293static int 336static int
294gethostbyname2_resolve (struct GNUNET_SERVER_TransmitContext *tc, 337gethostbyname2_resolve (struct GNUNET_SERVER_TransmitContext *tc,
295 const char *hostname, int domain) 338 const char *hostname, int af)
296{ 339{
297 struct hostent *hp; 340 struct hostent *hp;
298 struct sockaddr_in a4;
299 struct sockaddr_in6 a6;
300 int ret1; 341 int ret1;
301 int ret2; 342 int ret2;
302 343
303 if (domain == AF_UNSPEC) 344 if (af == AF_UNSPEC)
304 { 345 {
305 ret1 = gethostbyname2_resolve (tc, hostname, AF_INET); 346 ret1 = gethostbyname2_resolve (tc, hostname, AF_INET);
306 ret2 = gethostbyname2_resolve (tc, hostname, AF_INET6); 347 ret2 = gethostbyname2_resolve (tc, hostname, AF_INET6);
@@ -310,7 +351,7 @@ gethostbyname2_resolve (struct GNUNET_SERVER_TransmitContext *tc,
310 return GNUNET_SYSERR; 351 return GNUNET_SYSERR;
311 return GNUNET_NO; 352 return GNUNET_NO;
312 } 353 }
313 hp = gethostbyname2 (hostname, domain); 354 hp = gethostbyname2 (hostname, af);
314 if (hp == NULL) 355 if (hp == NULL)
315 { 356 {
316 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 357 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -318,42 +359,38 @@ gethostbyname2_resolve (struct GNUNET_SERVER_TransmitContext *tc,
318 hstrerror (h_errno)); 359 hstrerror (h_errno));
319 return GNUNET_SYSERR; 360 return GNUNET_SYSERR;
320 } 361 }
321 GNUNET_assert (hp->h_addrtype == domain); 362 GNUNET_assert (hp->h_addrtype == af);
322 if (domain == AF_INET) 363 switch (af)
323 { 364 {
365 case AF_INET:
324 GNUNET_assert (hp->h_length == sizeof (struct in_addr)); 366 GNUNET_assert (hp->h_length == sizeof (struct in_addr));
325 memset (&a4, 0, sizeof (a4)); 367 GNUNET_SERVER_transmit_context_append_data (tc,
326 a4.sin_family = AF_INET; 368 hp->h_addr_list[0],
327#if HAVE_SOCKADDR_IN_SIN_LEN 369 hp->h_length,
328 a4.sin_len = (u_char) sizeof (struct sockaddr_in);
329#endif
330 memcpy (&a4.sin_addr, hp->h_addr_list[0], hp->h_length);
331 GNUNET_SERVER_transmit_context_append_data (tc, &a4, sizeof (a4),
332 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); 370 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE);
333 } 371 break;
334 else 372 case AF_INET6:
335 {
336 GNUNET_assert (hp->h_length == sizeof (struct in6_addr)); 373 GNUNET_assert (hp->h_length == sizeof (struct in6_addr));
337 memset (&a6, 0, sizeof (a6)); 374 GNUNET_SERVER_transmit_context_append_data (tc,
338 a6.sin6_family = AF_INET6; 375 hp->h_addr_list[0],
339#if HAVE_SOCKADDR_IN_SIN_LEN 376 hp->h_length,
340 a6.sin6_len = (u_char) sizeof (struct sockaddr_in6);
341#endif
342 memcpy (&a6.sin6_addr, hp->h_addr_list[0], hp->h_length);
343 GNUNET_SERVER_transmit_context_append_data (tc, &a6, sizeof (a6),
344 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); 377 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE);
378 break;
379 default:
380 GNUNET_break (0);
381 return GNUNET_SYSERR;
345 } 382 }
346 return GNUNET_OK; 383 return GNUNET_OK;
347} 384}
348#endif 385#endif
349 386
387
350#if HAVE_GETHOSTBYNAME 388#if HAVE_GETHOSTBYNAME
351static int 389static int
352gethostbyname_resolve (struct GNUNET_SERVER_TransmitContext *tc, 390gethostbyname_resolve (struct GNUNET_SERVER_TransmitContext *tc,
353 const char *hostname) 391 const char *hostname)
354{ 392{
355 struct hostent *hp; 393 struct hostent *hp;
356 struct sockaddr_in addr;
357 394
358 hp = GETHOSTBYNAME (hostname); 395 hp = GETHOSTBYNAME (hostname);
359 if (hp == NULL) 396 if (hp == NULL)
@@ -369,13 +406,9 @@ gethostbyname_resolve (struct GNUNET_SERVER_TransmitContext *tc,
369 return GNUNET_SYSERR; 406 return GNUNET_SYSERR;
370 } 407 }
371 GNUNET_assert (hp->h_length == sizeof (struct in_addr)); 408 GNUNET_assert (hp->h_length == sizeof (struct in_addr));
372 memset (&addr, 0, sizeof (addr)); 409 GNUNET_SERVER_transmit_context_append_data (tc,
373 addr.sin_family = AF_INET; 410 hp->h_addr_list[0],
374#if HAVE_SOCKADDR_IN_SIN_LEN 411 hp->h_length,
375 addr.sin_len = (u_char) sizeof (struct sockaddr_in);
376#endif
377 memcpy (&addr.sin_addr, hp->h_addr_list[0], hp->h_length);
378 GNUNET_SERVER_transmit_context_append_data (tc, &addr, sizeof (addr),
379 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); 412 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE);
380 return GNUNET_OK; 413 return GNUNET_OK;
381} 414}
@@ -387,11 +420,11 @@ gethostbyname_resolve (struct GNUNET_SERVER_TransmitContext *tc,
387 * 420 *
388 * @param client where to send the IP address 421 * @param client where to send the IP address
389 * @param hostname the hostname to resolve 422 * @param hostname the hostname to resolve
390 * @param domain AF_INET or AF_INET6; use AF_UNSPEC for "any" 423 * @param af AF_INET or AF_INET6; use AF_UNSPEC for "any"
391 */ 424 */
392static void 425static void
393get_ip_from_hostname (struct GNUNET_SERVER_Client *client, const char *hostname, 426get_ip_from_hostname (struct GNUNET_SERVER_Client *client, const char *hostname,
394 int domain) 427 int af)
395{ 428{
396 int ret; 429 int ret;
397 struct GNUNET_SERVER_TransmitContext *tc; 430 struct GNUNET_SERVER_TransmitContext *tc;
@@ -400,14 +433,14 @@ get_ip_from_hostname (struct GNUNET_SERVER_Client *client, const char *hostname,
400 ret = GNUNET_NO; 433 ret = GNUNET_NO;
401#if HAVE_GETADDRINFO 434#if HAVE_GETADDRINFO
402 if (ret == GNUNET_NO) 435 if (ret == GNUNET_NO)
403 ret = getaddrinfo_resolve (tc, hostname, domain); 436 ret = getaddrinfo_resolve (tc, hostname, af);
404#endif 437#endif
405#if HAVE_GETHOSTBYNAME2 438#if HAVE_GETHOSTBYNAME2
406 if (ret == GNUNET_NO) 439 if (ret == GNUNET_NO)
407 ret = gethostbyname2_resolve (tc, hostname, domain); 440 ret = gethostbyname2_resolve (tc, hostname, af);
408#endif 441#endif
409#if HAVE_GETHOSTBYNAME 442#if HAVE_GETHOSTBYNAME
410 if ((ret == GNUNET_NO) && ((domain == AF_UNSPEC) || (domain == PF_INET))) 443 if ((ret == GNUNET_NO) && ((af == AF_UNSPEC) || (af == PF_INET)))
411 gethostbyname_resolve (tc, hostname); 444 gethostbyname_resolve (tc, hostname);
412#endif 445#endif
413 GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0, 446 GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
@@ -429,11 +462,10 @@ handle_get (void *cls, struct GNUNET_SERVER_Client *client,
429{ 462{
430 uint16_t msize; 463 uint16_t msize;
431 const struct GNUNET_RESOLVER_GetMessage *msg; 464 const struct GNUNET_RESOLVER_GetMessage *msg;
432 const char *hostname; 465 const void *ip;
433 const struct sockaddr *sa;
434 uint16_t size; 466 uint16_t size;
435 int direction; 467 int direction;
436 int domain; 468 int af;
437 469
438 msize = ntohs (message->size); 470 msize = ntohs (message->size);
439 if (msize < sizeof (struct GNUNET_RESOLVER_GetMessage)) 471 if (msize < sizeof (struct GNUNET_RESOLVER_GetMessage))
@@ -445,10 +477,12 @@ handle_get (void *cls, struct GNUNET_SERVER_Client *client,
445 msg = (const struct GNUNET_RESOLVER_GetMessage *) message; 477 msg = (const struct GNUNET_RESOLVER_GetMessage *) message;
446 size = msize - sizeof (struct GNUNET_RESOLVER_GetMessage); 478 size = msize - sizeof (struct GNUNET_RESOLVER_GetMessage);
447 direction = ntohl (msg->direction); 479 direction = ntohl (msg->direction);
448 domain = ntohl (msg->domain); 480 af = ntohl (msg->af);
449 if (direction == GNUNET_NO) 481 if (direction == GNUNET_NO)
450 { 482 {
451 /* IP from hostname */ 483 /* IP from hostname */
484 const char *hostname;
485
452 hostname = (const char *) &msg[1]; 486 hostname = (const char *) &msg[1];
453 if (hostname[size - 1] != '\0') 487 if (hostname[size - 1] != '\0')
454 { 488 {
@@ -460,55 +494,43 @@ handle_get (void *cls, struct GNUNET_SERVER_Client *client,
460 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Resolver asked to look up `%s'.\n"), 494 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Resolver asked to look up `%s'.\n"),
461 hostname); 495 hostname);
462#endif 496#endif
463 get_ip_from_hostname (client, hostname, domain); 497 get_ip_from_hostname (client, hostname, af);
498 return;
464 } 499 }
465 else 500 ip = &msg[1];
501 switch (af)
466 { 502 {
467#if DEBUG_RESOLVER 503 case AF_INET:
468 char buf[INET6_ADDRSTRLEN]; 504 if (size != sizeof (struct in_addr))
469#endif
470 if (size < sizeof (struct sockaddr))
471 { 505 {
472 GNUNET_break (0); 506 GNUNET_break (0);
473 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 507 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
474 return; 508 return;
475 } 509 }
476 sa = (const struct sockaddr *) &msg[1]; 510 break;
477 switch (sa->sa_family) 511 case AF_INET6:
512 if (size != sizeof (struct in6_addr))
478 { 513 {
479 case AF_INET:
480 if (size != sizeof (struct sockaddr_in))
481 {
482 GNUNET_break (0);
483 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
484 return;
485 }
486#if DEBUG_RESOLVER
487 inet_ntop (AF_INET, sa, buf, size);
488#endif
489 break;
490 case AF_INET6:
491 if (size != sizeof (struct sockaddr_in6))
492 {
493 GNUNET_break (0);
494 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
495 return;
496 }
497#if DEBUG_RESOLVER
498 inet_ntop (AF_INET6, sa, buf, size);
499#endif
500 break;
501 default:
502 GNUNET_break (0); 514 GNUNET_break (0);
503 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 515 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
504 return; 516 return;
505 } 517 }
518 break;
519 default:
520 GNUNET_break (0);
521 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
522 return;
523 }
506#if DEBUG_RESOLVER 524#if DEBUG_RESOLVER
525 {
526 char buf[INET6_ADDRSTRLEN];
527
507 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 528 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
508 _("Resolver asked to look up IP address `%s'.\n"), buf); 529 _("Resolver asked to look up IP address `%s'.\n"),
509#endif 530 inet_ntop (af, ip, buf, sizeof (buf)));
510 get_ip_as_string (client, sa, size);
511 } 531 }
532#endif
533 get_ip_as_string (client, af, ip);
512} 534}
513 535
514 536
@@ -541,21 +563,20 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
541int 563int
542main (int argc, char *const *argv) 564main (int argc, char *const *argv)
543{ 565{
544 int ret;
545 struct IPCache *pos; 566 struct IPCache *pos;
567 int ret;
546 568
547 ret = 569 ret =
548 (GNUNET_OK == 570 (GNUNET_OK ==
549 GNUNET_SERVICE_run (argc, argv, "resolver", GNUNET_SERVICE_OPTION_NONE, 571 GNUNET_SERVICE_run (argc, argv, "resolver", GNUNET_SERVICE_OPTION_NONE,
550 &run, NULL)) ? 0 : 1; 572 &run, NULL)) ? 0 : 1;
551 573 while (NULL != (pos = cache_head))
552 while (head != NULL)
553 { 574 {
554 pos = head->next; 575 GNUNET_CONTAINER_DLL_remove (cache_head,
555 GNUNET_free_non_null (head->addr); 576 cache_tail,
556 GNUNET_free (head->sa); 577 pos);
557 GNUNET_free (head); 578 GNUNET_free_non_null (pos->addr);
558 head = pos; 579 GNUNET_free (pos);
559 } 580 }
560 return ret; 581 return ret;
561} 582}