aboutsummaryrefslogtreecommitdiff
path: root/src/util
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
parentf4c1249ba12461abe0616963959b9470a41e1de5 (diff)
downloadgnunet-fae775b8e3ebc6e19b97156d3a3008ee91c3b64b.tar.gz
gnunet-fae775b8e3ebc6e19b97156d3a3008ee91c3b64b.zip
-fixing #2116
Diffstat (limited to 'src/util')
-rw-r--r--src/util/gnunet-resolver.c86
-rw-r--r--src/util/gnunet-service-resolver.c363
-rw-r--r--src/util/resolver.h25
-rw-r--r--src/util/resolver_api.c102
4 files changed, 359 insertions, 217 deletions
diff --git a/src/util/gnunet-resolver.c b/src/util/gnunet-resolver.c
index 131693dd1..142dd0d2f 100644
--- a/src/util/gnunet-resolver.c
+++ b/src/util/gnunet-resolver.c
@@ -30,12 +30,39 @@
30#define GET_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1) 30#define GET_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
31 31
32/** 32/**
33 * Flag for reverse lookup.
34 */
35static int reverse;
36
37
38/**
39 * Prints each hostname obtained from DNS.
40 *
41 * @param cls closure (unused)
42 * @param hostname one of the names for the host, NULL
43 * on the last call to the callback
44 */
45static void
46print_hostname (void *cls,
47 const char *hostname)
48{
49 if (NULL == hostname)
50 return;
51 FPRINTF (stdout, "%s\n", hostname);
52}
53
54
55/**
33 * Callback function to display address. 56 * Callback function to display address.
57 *
58 * @param cls closure (unused)
59 * @param addr one of the addresses of the host, NULL for the last address
60 * @param addrlen length of the address
34 */ 61 */
35static void 62static void
36printer (void *cls, const struct sockaddr *addr, socklen_t addrlen) 63print_sockaddr (void *cls, const struct sockaddr *addr, socklen_t addrlen)
37{ 64{
38 if (addr == NULL) 65 if (NULL == addr)
39 return; 66 return;
40 FPRINTF (stdout, "%s\n", GNUNET_a2s (addr, addrlen)); 67 FPRINTF (stdout, "%s\n", GNUNET_a2s (addr, addrlen));
41} 68}
@@ -53,9 +80,57 @@ static void
53run (void *cls, char *const *args, const char *cfgfile, 80run (void *cls, char *const *args, const char *cfgfile,
54 const struct GNUNET_CONFIGURATION_Handle *cfg) 81 const struct GNUNET_CONFIGURATION_Handle *cfg)
55{ 82{
83 const struct sockaddr *sa;
84 socklen_t salen;
85 struct sockaddr_in v4;
86 struct sockaddr_in6 v6;
87
56 if (args[0] == NULL) 88 if (args[0] == NULL)
57 return; 89 return;
58 GNUNET_RESOLVER_ip_get (args[0], AF_UNSPEC, GET_TIMEOUT, &printer, NULL); 90 if (! reverse)
91 {
92 GNUNET_RESOLVER_ip_get (args[0], AF_UNSPEC, GET_TIMEOUT, &print_sockaddr, NULL);
93 return;
94 }
95
96 sa = NULL;
97 memset (&v4, 0, sizeof (v4));
98 v4.sin_family = AF_INET;
99#if HAVE_SOCKADDR_IN_SIN_LEN
100 v4.sin_len = sizeof (v4);
101#endif
102 if (1 == inet_pton (AF_INET,
103 args[0],
104 &v4.sin_addr))
105 {
106 sa = (struct sockaddr *) &v4;
107 salen = sizeof (v4);
108 }
109 memset (&v6, 0, sizeof (v6));
110 v6.sin6_family = AF_INET6;
111#if HAVE_SOCKADDR_IN_SIN_LEN
112 v6.sin6_len = sizeof (v6);
113#endif
114 if (1 == inet_pton (AF_INET6,
115 args[0],
116 &v6.sin6_addr))
117 {
118 sa = (struct sockaddr *) &v6;
119 salen = sizeof (v6);
120 }
121 if (NULL == sa)
122 {
123 fprintf (stderr,
124 "`%s' is not a valid IP: %s\n",
125 args[0],
126 strerror (errno));
127 return;
128 }
129 GNUNET_RESOLVER_hostname_get (sa, salen,
130 GNUNET_YES,
131 GET_TIMEOUT,
132 &print_hostname,
133 NULL);
59} 134}
60 135
61/** 136/**
@@ -69,11 +144,14 @@ int
69main (int argc, char *const *argv) 144main (int argc, char *const *argv)
70{ 145{
71 static const struct GNUNET_GETOPT_CommandLineOption options[] = { 146 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
147 { 'r', "reverse", NULL,
148 gettext_noop ("perform a reverse lookup"),
149 0, &GNUNET_GETOPT_set_one, &reverse },
72 GNUNET_GETOPT_OPTION_END 150 GNUNET_GETOPT_OPTION_END
73 }; 151 };
74 return (GNUNET_OK == 152 return (GNUNET_OK ==
75 GNUNET_PROGRAM_run (argc, argv, "gnunet-resolver [hostname]", 153 GNUNET_PROGRAM_run (argc, argv, "gnunet-resolver [hostname]",
76 gettext_noop ("Test GNUnet DNS resolver code."), 154 gettext_noop ("Use build-in GNUnet stub resolver"),
77 options, &run, NULL)) ? 0 : 1; 155 options, &run, NULL)) ? 0 : 1;
78} 156}
79 157
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}
diff --git a/src/util/resolver.h b/src/util/resolver.h
index eca753a55..2c0de9910 100644
--- a/src/util/resolver.h
+++ b/src/util/resolver.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 (C) 2009 Christian Grothoff (and other contributing authors) 3 (C) 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
@@ -32,20 +32,20 @@
32GNUNET_NETWORK_STRUCT_BEGIN 32GNUNET_NETWORK_STRUCT_BEGIN
33 33
34/** 34/**
35 * Request for the resolver. Followed by either 35 * Request for the resolver. Followed by either the "struct sockaddr"
36 * the "struct sockaddr" or the 0-terminated hostname. 36 * or the 0-terminated hostname.
37 * 37 *
38 * The response will be one or more messages of type 38 * The response will be one or more messages of type
39 * RESOLVER_RESPONSE, each with the message header 39 * RESOLVER_RESPONSE, each with the message header immediately
40 * immediately followed by the requested data 40 * followed by the requested data (0-terminated hostname or struct
41 * (hostname or struct sockaddr, depending on direction). 41 * in[6]_addr, depending on direction). The last RESOLVER_RESPONSE
42 * The last RESOLVER_RESPONSE will just be a header 42 * will just be a header without any data (used to indicate the end of
43 * without any data (used to indicate the end of the list). 43 * the list).
44 */ 44 */
45struct GNUNET_RESOLVER_GetMessage 45struct GNUNET_RESOLVER_GetMessage
46{ 46{
47 /** 47 /**
48 * Type: GNUNET_MESSAGE_TYPE_STATISTICS_VALUE 48 * Type: GNUNET_MESSAGE_TYPE_RESOLVER_REQUEST
49 */ 49 */
50 struct GNUNET_MessageHeader header; 50 struct GNUNET_MessageHeader header;
51 51
@@ -56,9 +56,12 @@ struct GNUNET_RESOLVER_GetMessage
56 int32_t direction GNUNET_PACKED; 56 int32_t direction GNUNET_PACKED;
57 57
58 /** 58 /**
59 * Domain to use (AF_INET, AF_INET6 or AF_UNSPEC). 59 * Address family to use (AF_INET, AF_INET6 or AF_UNSPEC).
60 */ 60 */
61 int32_t domain GNUNET_PACKED; 61 int32_t af GNUNET_PACKED;
62
63 /* followed by 0-terminated string for A/AAAA-lookup or
64 by 'struct in_addr' / 'struct in6_addr' for reverse lookup */
62 65
63}; 66};
64GNUNET_NETWORK_STRUCT_END 67GNUNET_NETWORK_STRUCT_END
diff --git a/src/util/resolver_api.c b/src/util/resolver_api.c
index 03dc2ce89..371b2165a 100644
--- a/src/util/resolver_api.c
+++ b/src/util/resolver_api.c
@@ -139,7 +139,7 @@ struct GNUNET_RESOLVER_RequestHandle
139 /** 139 /**
140 * Desired address family. 140 * Desired address family.
141 */ 141 */
142 int domain; 142 int af;
143 143
144 /** 144 /**
145 * Has this request been transmitted to the service? 145 * Has this request been transmitted to the service?
@@ -344,19 +344,18 @@ handle_response (void *cls, const struct GNUNET_MessageHeader *msg)
344{ 344{
345 struct GNUNET_RESOLVER_RequestHandle *rh = cls; 345 struct GNUNET_RESOLVER_RequestHandle *rh = cls;
346 uint16_t size; 346 uint16_t size;
347 const char *hostname;
348 const struct sockaddr *sa;
349 socklen_t salen;
350 347
351#if DEBUG_RESOLVER 348#if DEBUG_RESOLVER
352 LOG (GNUNET_ERROR_TYPE_DEBUG, "Receiving response from DNS service\n"); 349 LOG (GNUNET_ERROR_TYPE_DEBUG, "Receiving response from DNS service\n");
353#endif 350#endif
354 if (msg == NULL) 351 if (msg == NULL)
355 { 352 {
353 char buf[INET6_ADDRSTRLEN];
354
356 if (NULL != rh->name_callback) 355 if (NULL != rh->name_callback)
357 LOG (GNUNET_ERROR_TYPE_INFO, 356 LOG (GNUNET_ERROR_TYPE_INFO,
358 _("Timeout trying to resolve IP address `%s'.\n"), 357 _("Timeout trying to resolve IP address `%s'.\n"),
359 GNUNET_a2s ((const void *) &rh[1], rh->data_len)); 358 inet_ntop (rh->af, (const void *) &rh[1], buf, sizeof(buf)));
360 else 359 else
361 LOG (GNUNET_ERROR_TYPE_INFO, 360 LOG (GNUNET_ERROR_TYPE_INFO,
362 _("Timeout trying to resolve hostname `%s'.\n"), 361 _("Timeout trying to resolve hostname `%s'.\n"),
@@ -413,6 +412,8 @@ handle_response (void *cls, const struct GNUNET_MessageHeader *msg)
413 /* return reverse lookup results to caller */ 412 /* return reverse lookup results to caller */
414 if (NULL != rh->name_callback) 413 if (NULL != rh->name_callback)
415 { 414 {
415 const char *hostname;
416
416 hostname = (const char *) &msg[1]; 417 hostname = (const char *) &msg[1];
417 if (hostname[size - sizeof (struct GNUNET_MessageHeader) - 1] != '\0') 418 if (hostname[size - sizeof (struct GNUNET_MessageHeader) - 1] != '\0')
418 { 419 {
@@ -439,9 +440,38 @@ handle_response (void *cls, const struct GNUNET_MessageHeader *msg)
439 /* return lookup results to caller */ 440 /* return lookup results to caller */
440 if (NULL != rh->addr_callback) 441 if (NULL != rh->addr_callback)
441 { 442 {
442 sa = (const struct sockaddr *) &msg[1]; 443 struct sockaddr_in v4;
443 salen = size - sizeof (struct GNUNET_MessageHeader); 444 struct sockaddr_in6 v6;
444 if (salen < sizeof (struct sockaddr)) 445 const struct sockaddr *sa;
446 socklen_t salen;
447 const void *ip;
448 size_t ip_len;
449
450 ip = &msg[1];
451 ip_len = size - sizeof (struct GNUNET_MessageHeader);
452 if (ip_len == sizeof (struct in_addr))
453 {
454 memset (&v4, 0, sizeof (v4));
455 v4.sin_family = AF_INET;
456 v4.sin_addr = *(struct in_addr*) ip;
457#if HAVE_SOCKADDR_IN_SIN_LEN
458 v4.sin_len = sizeof (v4);
459#endif
460 salen = sizeof (v4);
461 sa = (const struct sockaddr *) &v4;
462 }
463 else if (ip_len == sizeof (struct in6_addr))
464 {
465 memset (&v6, 0, sizeof (v6));
466 v6.sin6_family = AF_INET6;
467 v6.sin6_addr = *(struct in6_addr*) ip;
468#if HAVE_SOCKADDR_IN_SIN_LEN
469 v6.sin6_len = sizeof (v6);
470#endif
471 salen = sizeof (v6);
472 sa = (const struct sockaddr *) &v6;
473 }
474 else
445 { 475 {
446 GNUNET_break (0); 476 GNUNET_break (0);
447 if (rh->was_transmitted != GNUNET_SYSERR) 477 if (rh->was_transmitted != GNUNET_SYSERR)
@@ -496,11 +526,11 @@ numeric_resolution (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
496 v6.sin6_len = sizeof (v6); 526 v6.sin6_len = sizeof (v6);
497#endif 527#endif
498 hostname = (const char *) &rh[1]; 528 hostname = (const char *) &rh[1];
499 if (((rh->domain == AF_UNSPEC) || (rh->domain == AF_INET)) && 529 if (((rh->af == AF_UNSPEC) || (rh->af == AF_INET)) &&
500 (1 == inet_pton (AF_INET, hostname, &v4.sin_addr))) 530 (1 == inet_pton (AF_INET, hostname, &v4.sin_addr)))
501 { 531 {
502 rh->addr_callback (rh->cls, (const struct sockaddr *) &v4, sizeof (v4)); 532 rh->addr_callback (rh->cls, (const struct sockaddr *) &v4, sizeof (v4));
503 if ((rh->domain == AF_UNSPEC) && 533 if ((rh->af == AF_UNSPEC) &&
504 (1 == inet_pton (AF_INET6, hostname, &v6.sin6_addr))) 534 (1 == inet_pton (AF_INET6, hostname, &v6.sin6_addr)))
505 { 535 {
506 /* this can happen on some systems IF "hostname" is "localhost" */ 536 /* this can happen on some systems IF "hostname" is "localhost" */
@@ -510,7 +540,7 @@ numeric_resolution (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
510 GNUNET_free (rh); 540 GNUNET_free (rh);
511 return; 541 return;
512 } 542 }
513 if (((rh->domain == AF_UNSPEC) || (rh->domain == AF_INET6)) && 543 if (((rh->af == AF_UNSPEC) || (rh->af == AF_INET6)) &&
514 (1 == inet_pton (AF_INET6, hostname, &v6.sin6_addr))) 544 (1 == inet_pton (AF_INET6, hostname, &v6.sin6_addr)))
515 { 545 {
516 rh->addr_callback (rh->cls, (const struct sockaddr *) &v6, sizeof (v6)); 546 rh->addr_callback (rh->cls, (const struct sockaddr *) &v6, sizeof (v6));
@@ -551,7 +581,7 @@ loopback_resolution (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
551 v6.sin6_len = sizeof (v6); 581 v6.sin6_len = sizeof (v6);
552#endif 582#endif
553 v6.sin6_addr = in6addr_loopback; 583 v6.sin6_addr = in6addr_loopback;
554 switch (rh->domain) 584 switch (rh->af)
555 { 585 {
556 case AF_INET: 586 case AF_INET:
557 rh->addr_callback (rh->cls, (const struct sockaddr *) &v4, sizeof (v4)); 587 rh->addr_callback (rh->cls, (const struct sockaddr *) &v4, sizeof (v4));
@@ -615,7 +645,7 @@ process_requests ()
615 htons (sizeof (struct GNUNET_RESOLVER_GetMessage) + rh->data_len); 645 htons (sizeof (struct GNUNET_RESOLVER_GetMessage) + rh->data_len);
616 msg->header.type = htons (GNUNET_MESSAGE_TYPE_RESOLVER_REQUEST); 646 msg->header.type = htons (GNUNET_MESSAGE_TYPE_RESOLVER_REQUEST);
617 msg->direction = htonl (rh->direction); 647 msg->direction = htonl (rh->direction);
618 msg->domain = htonl (rh->domain); 648 msg->af = htonl (rh->af);
619 memcpy (&msg[1], &rh[1], rh->data_len); 649 memcpy (&msg[1], &rh[1], rh->data_len);
620#if DEBUG_RESOLVER 650#if DEBUG_RESOLVER
621 LOG (GNUNET_ERROR_TYPE_DEBUG, 651 LOG (GNUNET_ERROR_TYPE_DEBUG,
@@ -711,14 +741,14 @@ reconnect ()
711 * Convert a string to one or more IP addresses. 741 * Convert a string to one or more IP addresses.
712 * 742 *
713 * @param hostname the hostname to resolve 743 * @param hostname the hostname to resolve
714 * @param domain AF_INET or AF_INET6; use AF_UNSPEC for "any" 744 * @param af AF_INET or AF_INET6; use AF_UNSPEC for "any"
715 * @param callback function to call with addresses 745 * @param callback function to call with addresses
716 * @param callback_cls closure for callback 746 * @param callback_cls closure for callback
717 * @param timeout how long to try resolving 747 * @param timeout how long to try resolving
718 * @return handle that can be used to cancel the request, NULL on error 748 * @return handle that can be used to cancel the request, NULL on error
719 */ 749 */
720struct GNUNET_RESOLVER_RequestHandle * 750struct GNUNET_RESOLVER_RequestHandle *
721GNUNET_RESOLVER_ip_get (const char *hostname, int domain, 751GNUNET_RESOLVER_ip_get (const char *hostname, int af,
722 struct GNUNET_TIME_Relative timeout, 752 struct GNUNET_TIME_Relative timeout,
723 GNUNET_RESOLVER_AddressCallback callback, 753 GNUNET_RESOLVER_AddressCallback callback,
724 void *callback_cls) 754 void *callback_cls)
@@ -737,7 +767,7 @@ GNUNET_RESOLVER_ip_get (const char *hostname, int domain,
737 return NULL; 767 return NULL;
738 } 768 }
739 rh = GNUNET_malloc (sizeof (struct GNUNET_RESOLVER_RequestHandle) + slen); 769 rh = GNUNET_malloc (sizeof (struct GNUNET_RESOLVER_RequestHandle) + slen);
740 rh->domain = domain; 770 rh->af = af;
741 rh->addr_callback = callback; 771 rh->addr_callback = callback;
742 rh->cls = callback_cls; 772 rh->cls = callback_cls;
743 memcpy (&rh[1], hostname, slen); 773 memcpy (&rh[1], hostname, slen);
@@ -746,9 +776,9 @@ GNUNET_RESOLVER_ip_get (const char *hostname, int domain,
746 rh->direction = GNUNET_NO; 776 rh->direction = GNUNET_NO;
747 /* first, check if this is a numeric address */ 777 /* first, check if this is a numeric address */
748 if (((1 == inet_pton (AF_INET, hostname, &v4)) && 778 if (((1 == inet_pton (AF_INET, hostname, &v4)) &&
749 ((domain == AF_INET) || (domain == AF_UNSPEC))) || 779 ((af == AF_INET) || (af == AF_UNSPEC))) ||
750 ((1 == inet_pton (AF_INET6, hostname, &v6)) && 780 ((1 == inet_pton (AF_INET6, hostname, &v6)) &&
751 ((domain == AF_INET6) || (domain == AF_UNSPEC)))) 781 ((af == AF_INET6) || (af == AF_UNSPEC))))
752 { 782 {
753 rh->task = GNUNET_SCHEDULER_add_now (&numeric_resolution, rh); 783 rh->task = GNUNET_SCHEDULER_add_now (&numeric_resolution, rh);
754 return rh; 784 return rh;
@@ -820,14 +850,31 @@ GNUNET_RESOLVER_hostname_get (const struct sockaddr *sa, socklen_t salen,
820 void *cls) 850 void *cls)
821{ 851{
822 struct GNUNET_RESOLVER_RequestHandle *rh; 852 struct GNUNET_RESOLVER_RequestHandle *rh;
853 size_t ip_len;
854 const void *ip;
823 855
824 check_config (); 856 check_config ();
857 switch (sa->sa_family)
858 {
859 case AF_INET:
860 ip_len = sizeof (struct in_addr);
861 ip = &((const struct sockaddr_in*)sa)->sin_addr;
862 break;
863 case AF_INET6:
864 ip_len = sizeof (struct in6_addr);
865 ip = &((const struct sockaddr_in6*)sa)->sin6_addr;
866 break;
867 default:
868 GNUNET_break (0);
869 return NULL;
870 }
825 rh = GNUNET_malloc (sizeof (struct GNUNET_RESOLVER_RequestHandle) + salen); 871 rh = GNUNET_malloc (sizeof (struct GNUNET_RESOLVER_RequestHandle) + salen);
826 rh->name_callback = callback; 872 rh->name_callback = callback;
827 rh->cls = cls; 873 rh->cls = cls;
874 rh->af = sa->sa_family;
828 rh->timeout = GNUNET_TIME_relative_to_absolute (timeout); 875 rh->timeout = GNUNET_TIME_relative_to_absolute (timeout);
829 memcpy (&rh[1], sa, salen); 876 memcpy (&rh[1], ip, ip_len);
830 rh->data_len = salen; 877 rh->data_len = ip_len;
831 rh->direction = GNUNET_YES; 878 rh->direction = GNUNET_YES;
832 rh->received_response = GNUNET_NO; 879 rh->received_response = GNUNET_NO;
833 if (GNUNET_NO == do_resolve) 880 if (GNUNET_NO == do_resolve)
@@ -835,13 +882,6 @@ GNUNET_RESOLVER_hostname_get (const struct sockaddr *sa, socklen_t salen,
835 rh->task = GNUNET_SCHEDULER_add_now (&numeric_reverse, rh); 882 rh->task = GNUNET_SCHEDULER_add_now (&numeric_reverse, rh);
836 return rh; 883 return rh;
837 } 884 }
838 if (salen + sizeof (struct GNUNET_RESOLVER_GetMessage) >=
839 GNUNET_SERVER_MAX_MESSAGE_SIZE)
840 {
841 GNUNET_break (0);
842 GNUNET_free (rh);
843 return NULL;
844 }
845 GNUNET_CONTAINER_DLL_insert_tail (req_head, req_tail, rh); 885 GNUNET_CONTAINER_DLL_insert_tail (req_head, req_tail, rh);
846 rh->was_queued = GNUNET_YES; 886 rh->was_queued = GNUNET_YES;
847 if (s_task != GNUNET_SCHEDULER_NO_TASK) 887 if (s_task != GNUNET_SCHEDULER_NO_TASK)
@@ -855,7 +895,7 @@ GNUNET_RESOLVER_hostname_get (const struct sockaddr *sa, socklen_t salen,
855 895
856 896
857/** 897/**
858 * Get local fully qualified domain name 898 * Get local fully qualified af name
859 * 899 *
860 * @return fqdn 900 * @return fqdn
861 */ 901 */
@@ -888,14 +928,14 @@ GNUNET_RESOLVER_local_fqdn_get ()
888/** 928/**
889 * Looking our own hostname. 929 * Looking our own hostname.
890 * 930 *
891 * @param domain AF_INET or AF_INET6; use AF_UNSPEC for "any" 931 * @param af AF_INET or AF_INET6; use AF_UNSPEC for "any"
892 * @param callback function to call with addresses 932 * @param callback function to call with addresses
893 * @param cls closure for callback 933 * @param cls closure for callback
894 * @param timeout how long to try resolving 934 * @param timeout how long to try resolving
895 * @return handle that can be used to cancel the request, NULL on error 935 * @return handle that can be used to cancel the request, NULL on error
896 */ 936 */
897struct GNUNET_RESOLVER_RequestHandle * 937struct GNUNET_RESOLVER_RequestHandle *
898GNUNET_RESOLVER_hostname_resolve (int domain, 938GNUNET_RESOLVER_hostname_resolve (int af,
899 struct GNUNET_TIME_Relative timeout, 939 struct GNUNET_TIME_Relative timeout,
900 GNUNET_RESOLVER_AddressCallback callback, 940 GNUNET_RESOLVER_AddressCallback callback,
901 void *cls) 941 void *cls)
@@ -911,7 +951,7 @@ GNUNET_RESOLVER_hostname_resolve (int domain,
911#if DEBUG_RESOLVER 951#if DEBUG_RESOLVER
912 LOG (GNUNET_ERROR_TYPE_DEBUG, _("Resolving our hostname `%s'\n"), hostname); 952 LOG (GNUNET_ERROR_TYPE_DEBUG, _("Resolving our hostname `%s'\n"), hostname);
913#endif 953#endif
914 return GNUNET_RESOLVER_ip_get (hostname, domain, timeout, callback, cls); 954 return GNUNET_RESOLVER_ip_get (hostname, af, timeout, callback, cls);
915} 955}
916 956
917 957