2 This file is part of GNUnet.
3 (C) 2009 Christian Grothoff (and other contributing authors)
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.
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.
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.
22 * @file resolver/resolver_api.c
23 * @brief resolver for writing a tool
24 * @author Christian Grothoff
27 #include "gnunet_getopt_lib.h"
28 #include "gnunet_client_lib.h"
29 #include "gnunet_protocols.h"
30 #include "gnunet_resolver_service.h"
31 #include "gnunet_server_lib.h"
35 struct GetAddressContext
37 GNUNET_RESOLVER_AddressCallback callback;
39 struct GNUNET_RESOLVER_GetMessage *msg;
40 struct GNUNET_CLIENT_Connection *client;
41 struct GNUNET_TIME_Absolute timeout;
47 * Convert IP address to string without DNS resolution.
50 no_resolve (const struct sockaddr *sa, socklen_t salen)
53 char inet4[INET_ADDRSTRLEN];
54 char inet6[INET6_ADDRSTRLEN];
56 if (salen < sizeof (struct sockaddr))
58 switch (sa->sa_family)
61 if (salen != sizeof (struct sockaddr_in))
64 &((struct sockaddr_in *) sa)->sin_addr,
65 inet4, INET_ADDRSTRLEN);
66 ret = GNUNET_strdup (inet4);
69 if (salen != sizeof (struct sockaddr_in6))
72 &((struct sockaddr_in6 *) sa)->sin6_addr,
73 inet6, INET6_ADDRSTRLEN);
74 ret = GNUNET_strdup (inet6);
85 handle_address_response (void *cls, const struct GNUNET_MessageHeader *msg)
87 struct GetAddressContext *gac = cls;
89 const struct sockaddr *sa;
95 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
96 _("Timeout trying to resolve hostname.\n"));
97 gac->callback (gac->cls, NULL, 0);
98 GNUNET_CLIENT_disconnect (gac->client);
102 if (GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE != ntohs (msg->type))
105 gac->callback (gac->cls, NULL, 0);
106 GNUNET_CLIENT_disconnect (gac->client);
111 size = ntohs (msg->size);
112 if (size == sizeof (struct GNUNET_MessageHeader))
115 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
116 _("Received end message resolving hostname.\n"));
118 gac->callback (gac->cls, NULL, 0);
119 GNUNET_CLIENT_disconnect (gac->client);
123 sa = (const struct sockaddr *) &msg[1];
124 salen = size - sizeof (struct GNUNET_MessageHeader);
125 if (salen < sizeof (struct sockaddr))
128 gac->callback (gac->cls, NULL, 0);
129 GNUNET_CLIENT_disconnect (gac->client);
135 char *ips = no_resolve (sa, salen);
136 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Resolver returns `%s'.\n"), ips);
140 gac->callback (gac->cls, sa, salen);
141 GNUNET_CLIENT_receive (gac->client,
142 &handle_address_response,
144 GNUNET_TIME_absolute_get_remaining (gac->timeout));
149 transmit_get_ip (void *cls, size_t size, void *buf)
151 struct GetAddressContext *actx = cls;
156 /* timeout / error */
157 GNUNET_free (actx->msg);
158 actx->callback (actx->cls, NULL, 0);
159 GNUNET_CLIENT_disconnect (actx->client);
163 ms = ntohs (actx->msg->header.size);
164 GNUNET_assert (size >= ms);
165 memcpy (buf, actx->msg, ms);
166 GNUNET_free (actx->msg);
168 GNUNET_CLIENT_receive (actx->client,
169 &handle_address_response,
171 GNUNET_TIME_absolute_get_remaining (actx->timeout));
178 * Convert a string to one or more IP addresses.
180 * @param sched scheduler to use
181 * @param cfg configuration to use
182 * @param hostname the hostname to resolve
183 * @param domain AF_INET or AF_INET6; use AF_UNSPEC for "any"
184 * @param callback function to call with addresses
185 * @param cls closure for callback
186 * @param timeout how long to try resolving
189 GNUNET_RESOLVER_ip_get (struct GNUNET_SCHEDULER_Handle *sched,
190 const struct GNUNET_CONFIGURATION_Handle *cfg,
191 const char *hostname,
193 struct GNUNET_TIME_Relative timeout,
194 GNUNET_RESOLVER_AddressCallback callback, void *cls)
196 struct GNUNET_CLIENT_Connection *client;
197 struct GNUNET_RESOLVER_GetMessage *msg;
198 struct GetAddressContext *actx;
201 slen = strlen (hostname) + 1;
202 if (slen + sizeof (struct GNUNET_RESOLVER_GetMessage) >
203 GNUNET_SERVER_MAX_MESSAGE_SIZE)
206 callback (cls, NULL, 0);
209 client = GNUNET_CLIENT_connect (sched, "resolver", cfg);
212 callback (cls, NULL, 0);
215 msg = GNUNET_malloc (sizeof (struct GNUNET_RESOLVER_GetMessage) + slen);
217 htons (sizeof (struct GNUNET_RESOLVER_GetMessage) + slen);
218 msg->header.type = htons (GNUNET_MESSAGE_TYPE_RESOLVER_REQUEST);
219 msg->direction = htonl (GNUNET_NO);
220 msg->domain = htonl (domain);
221 memcpy (&msg[1], hostname, slen);
222 actx = GNUNET_malloc (sizeof (struct GetAddressContext));
223 actx->callback = callback;
225 actx->client = client;
226 actx->timeout = GNUNET_TIME_relative_to_absolute (timeout);
230 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
231 _("Resolver requests DNS resolution of hostname `%s'.\n"),
235 GNUNET_CLIENT_notify_transmit_ready (client,
238 GNUNET_RESOLVER_GetMessage),
239 timeout, &transmit_get_ip, actx))
243 callback (cls, NULL, 0);
244 GNUNET_CLIENT_disconnect (client);
250 struct GetHostnameContext
252 GNUNET_RESOLVER_HostnameCallback callback;
254 struct GNUNET_RESOLVER_GetMessage *msg;
255 struct GNUNET_CLIENT_Connection *client;
256 struct GNUNET_TIME_Absolute timeout;
261 handle_hostname_response (void *cls, const struct GNUNET_MessageHeader *msg)
263 struct GetHostnameContext *ghc = cls;
265 const char *hostname;
269 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
270 _("Timeout trying to resolve IP address.\n"));
271 ghc->callback (ghc->cls, NULL);
272 GNUNET_CLIENT_disconnect (ghc->client);
276 size = ntohs (msg->size);
277 if (size == sizeof (struct GNUNET_MessageHeader))
280 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
281 _("Received end message resolving IP address.\n"));
283 ghc->callback (ghc->cls, NULL);
284 GNUNET_CLIENT_disconnect (ghc->client);
288 hostname = (const char *) &msg[1];
289 if (hostname[size - sizeof (struct GNUNET_MessageHeader) - 1] != '\0')
292 ghc->callback (ghc->cls, NULL);
293 GNUNET_CLIENT_disconnect (ghc->client);
298 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
299 _("Resolver returns `%s'.\n"), hostname);
301 ghc->callback (ghc->cls, hostname);
302 GNUNET_CLIENT_receive (ghc->client,
303 &handle_hostname_response,
305 GNUNET_TIME_absolute_get_remaining (ghc->timeout));
310 transmit_get_hostname (void *cls, size_t size, void *buf)
312 struct GetHostnameContext *hctx = cls;
317 GNUNET_free (hctx->msg);
318 hctx->callback (hctx->cls, NULL);
319 GNUNET_CLIENT_disconnect (hctx->client);
323 msize = ntohs (hctx->msg->header.size);
324 GNUNET_assert (size >= msize);
325 memcpy (buf, hctx->msg, msize);
326 GNUNET_free (hctx->msg);
328 GNUNET_CLIENT_receive (hctx->client,
329 &handle_hostname_response,
331 GNUNET_TIME_absolute_get_remaining (hctx->timeout));
339 * Get an IP address as a string.
341 * @param sched scheduler to use
342 * @param cfg configuration to use
343 * @param sa host address
344 * @param salen length of host address
345 * @param do_resolve use GNUNET_NO to return numeric hostname
346 * @param timeout how long to try resolving
347 * @param callback function to call with hostnames
348 * @param cls closure for callback
351 GNUNET_RESOLVER_hostname_get (struct GNUNET_SCHEDULER_Handle *sched,
352 const struct GNUNET_CONFIGURATION_Handle *cfg,
353 const struct sockaddr *sa,
356 struct GNUNET_TIME_Relative timeout,
357 GNUNET_RESOLVER_HostnameCallback callback,
361 struct GNUNET_CLIENT_Connection *client;
362 struct GNUNET_RESOLVER_GetMessage *msg;
363 struct GetHostnameContext *hctx;
365 if (GNUNET_NO == do_resolve)
367 result = no_resolve (sa, salen);
369 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
370 _("Resolver returns `%s'.\n"), result);
372 callback (cls, result);
375 GNUNET_free (result);
376 callback (cls, NULL);
380 if (salen + sizeof (struct GNUNET_RESOLVER_GetMessage) >
381 GNUNET_SERVER_MAX_MESSAGE_SIZE)
384 callback (cls, NULL);
387 client = GNUNET_CLIENT_connect (sched, "resolver", cfg);
390 callback (cls, NULL);
393 msg = GNUNET_malloc (sizeof (struct GNUNET_RESOLVER_GetMessage) + salen);
395 htons (sizeof (struct GNUNET_RESOLVER_GetMessage) + salen);
396 msg->header.type = htons (GNUNET_MESSAGE_TYPE_RESOLVER_REQUEST);
397 msg->direction = htonl (GNUNET_YES);
398 msg->domain = htonl (sa->sa_family);
399 memcpy (&msg[1], sa, salen);
401 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
402 _("Resolver requests DNS resolution of IP address.\n"));
404 hctx = GNUNET_malloc (sizeof (struct GetHostnameContext));
405 hctx->callback = callback;
407 hctx->client = client;
408 hctx->timeout = GNUNET_TIME_relative_to_absolute (timeout);
411 GNUNET_CLIENT_notify_transmit_ready (client,
413 GNUNET_RESOLVER_GetMessage)
415 &transmit_get_hostname, hctx))
418 callback (cls, NULL);
419 GNUNET_CLIENT_disconnect (client);
425 * Maximum supported length of hostname
427 #define MAX_HOSTNAME 1024
431 * Resolve our hostname to an IP address.
433 * @param sched scheduler to use
434 * @param cfg configuration to use
435 * @param domain AF_INET or AF_INET6; use AF_UNSPEC for "any"
436 * @param callback function to call with addresses
437 * @param cls closure for callback
438 * @param timeout how long to try resolving
441 GNUNET_RESOLVER_hostname_resolve (struct GNUNET_SCHEDULER_Handle *sched,
442 const struct GNUNET_CONFIGURATION_Handle *cfg,
444 struct GNUNET_TIME_Relative timeout,
445 GNUNET_RESOLVER_AddressCallback callback,
448 char hostname[MAX_HOSTNAME];
450 if (0 != gethostname (hostname, sizeof (hostname) - 1))
452 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR |
453 GNUNET_ERROR_TYPE_BULK, "gethostname");
454 callback (cls, NULL, 0);
458 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
459 _("Resolving our hostname `%s'\n"), hostname);
461 GNUNET_RESOLVER_ip_get (sched,
462 cfg, hostname, domain, timeout, callback, cls);
468 /* end of resolver_api.c */