GNUnet  0.11.x
Data Structures | Macros | Functions | Variables
resolver_api.c File Reference

resolver for writing a tool More...

#include "platform.h"
#include "gnunet_util_lib.h"
#include "gnunet_protocols.h"
#include "gnunet_resolver_service.h"
#include "resolver.h"
Include dependency graph for resolver_api.c:

Go to the source code of this file.

Data Structures

struct  GNUNET_RESOLVER_RequestHandle
 Handle to a request given to the resolver. More...
 

Macros

#define LOG(kind, ...)   GNUNET_log_from (kind, "util-resolver-api", __VA_ARGS__)
 
#define LOG_STRERROR(kind, syscall)
 
#define MAX_HOSTNAME   1024
 Maximum supported length for a hostname. More...
 

Functions

static int check_config ()
 Check that the resolver service runs on localhost (or equivalent). More...
 
void GNUNET_RESOLVER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
 Create the connection to the resolver service. More...
 
void GNUNET_RESOLVER_disconnect ()
 Destroy the connection to the resolver service. More...
 
static void shutdown_task (void *cls)
 Task executed on system shutdown. More...
 
static void check_disconnect ()
 Consider disconnecting if we have no further requests pending. More...
 
static char * no_resolve (int af, const void *ip, socklen_t ip_len)
 Convert IP address to string without DNS resolution. More...
 
static void reconnect (void)
 Adjust exponential back-off and reconnect to the service. More...
 
static void mq_error_handler (void *cls, enum GNUNET_MQ_Error error)
 Generic error handler, called with the appropriate error code and the same closure specified at the creation of the message queue. More...
 
static void process_requests ()
 Process pending requests to the resolver. More...
 
static int check_response (void *cls, const struct GNUNET_RESOLVER_ResponseMessage *msg)
 Check validity of response with a hostname for a DNS lookup. More...
 
static void handle_response (void *cls, const struct GNUNET_RESOLVER_ResponseMessage *msg)
 Check validity of response with a hostname for a DNS lookup. More...
 
static void numeric_resolution (void *cls)
 We've been asked to lookup the address for a hostname and were given a valid numeric string. More...
 
static void loopback_resolution (void *cls)
 We've been asked to lookup the address for a hostname and were given a variant of "loopback". More...
 
static void reconnect_task (void *cls)
 Now try to reconnect to the resolver service. More...
 
static void handle_lookup_timeout (void *cls)
 A DNS resolution timed out. More...
 
struct GNUNET_RESOLVER_RequestHandleGNUNET_RESOLVER_ip_get (const char *hostname, int af, struct GNUNET_TIME_Relative timeout, GNUNET_RESOLVER_AddressCallback callback, void *callback_cls)
 Convert a string to one or more IP addresses. More...
 
static void numeric_reverse (void *cls)
 We've been asked to convert an address to a string without a reverse lookup, either because the client asked for it or because the DNS lookup hit a timeout. More...
 
struct GNUNET_RESOLVER_RequestHandleGNUNET_RESOLVER_hostname_get (const struct sockaddr *sa, socklen_t salen, int do_resolve, struct GNUNET_TIME_Relative timeout, GNUNET_RESOLVER_HostnameCallback callback, void *cls)
 Get an IP address as a string. More...
 
char * GNUNET_RESOLVER_local_fqdn_get ()
 Get local fully qualified af name. More...
 
struct GNUNET_RESOLVER_RequestHandleGNUNET_RESOLVER_hostname_resolve (int af, struct GNUNET_TIME_Relative timeout, GNUNET_RESOLVER_AddressCallback callback, void *cls)
 Looking our own hostname. More...
 
void GNUNET_RESOLVER_request_cancel (struct GNUNET_RESOLVER_RequestHandle *rh)
 Cancel a request that is still pending with the resolver. More...
 

Variables

static const char * loopback []
 Possible hostnames for "loopback". More...
 
static const struct GNUNET_CONFIGURATION_Handleresolver_cfg
 Configuration. More...
 
static struct GNUNET_MQ_Handlemq
 Our connection to the resolver service, created on-demand, but then persists until error or shutdown. More...
 
static struct GNUNET_RESOLVER_RequestHandlereq_head
 Head of DLL of requests. More...
 
static struct GNUNET_RESOLVER_RequestHandlereq_tail
 Tail of DLL of requests. More...
 
static uint32_t last_request_id
 ID of the last request we sent to the service. More...
 
static struct GNUNET_TIME_Relative backoff
 How long should we wait to reconnect? More...
 
static struct GNUNET_SCHEDULER_Taskr_task
 Task for reconnecting. More...
 
static struct GNUNET_SCHEDULER_Tasks_task
 Task ID of shutdown task; only present while we have a connection to the resolver service. More...
 

Detailed Description

resolver for writing a tool

Author
Christian Grothoff

Definition in file resolver_api.c.

Macro Definition Documentation

◆ LOG

#define LOG (   kind,
  ... 
)    GNUNET_log_from (kind, "util-resolver-api", __VA_ARGS__)

Definition at line 32 of file resolver_api.c.

◆ LOG_STRERROR

#define LOG_STRERROR (   kind,
  syscall 
)
Value:
"util-resolver-api", \
syscall)
#define GNUNET_log_from_strerror(level, component, cmd)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...

Definition at line 34 of file resolver_api.c.

◆ MAX_HOSTNAME

#define MAX_HOSTNAME   1024

Maximum supported length for a hostname.

Definition at line 41 of file resolver_api.c.

Function Documentation

◆ check_config()

static int check_config ( )
static

Check that the resolver service runs on localhost (or equivalent).

Returns
GNUNET_OK if the resolver is properly configured, GNUNET_SYSERR otherwise.

Definition at line 190 of file resolver_api.c.

191 {
192  char *hostname;
193  struct sockaddr_in v4;
194  struct sockaddr_in6 v6;
195 
196  if (GNUNET_OK ==
198  "resolver",
199  "UNIXPATH"))
200  return GNUNET_OK;
201  memset (&v4, 0, sizeof(v4));
202  v4.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
203  v4.sin_family = AF_INET;
204 #if HAVE_SOCKADDR_IN_SIN_LEN
205  v4.sin_len = sizeof(v4);
206 #endif
207  memset (&v6, 0, sizeof(v6));
208  v6.sin6_family = AF_INET6;
209 #if HAVE_SOCKADDR_IN_SIN_LEN
210  v6.sin6_len = sizeof(v6);
211 #endif
212  if (GNUNET_OK !=
214  "resolver",
215  "HOSTNAME",
216  &hostname))
217  {
219  _ (
220  "Missing `%s' for `%s' in configuration, DNS resolution will be unavailable.\n"),
221  "HOSTNAME",
222  "resolver");
223  return GNUNET_SYSERR;
224  }
225  if ((1 == inet_pton (AF_INET, hostname, &v4)) ||
226  (1 == inet_pton (AF_INET6, hostname, &v6)))
227  {
229  return GNUNET_OK;
230  }
231  for (unsigned int i = 0;
232  NULL != loopback[i];
233  i++)
234  if (0 == strcasecmp (loopback[i],
235  hostname))
236  {
238  return GNUNET_OK;
239  }
241  _ (
242  "Missing `%s' or numeric IP address for `%s' of `%s' in configuration, DNS resolution will be unavailable.\n"),
243  "localhost",
244  "HOSTNAME",
245  "resolver");
247  return GNUNET_SYSERR;
248 }
static char * hostname
Our hostname; we give this to all the peers we start.
@ GNUNET_OK
Definition: gnunet_common.h:95
@ GNUNET_SYSERR
Definition: gnunet_common.h:93
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_have_value(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Test if we have a value for a particular option.
@ GNUNET_ERROR_TYPE_INFO
#define GNUNET_free(ptr)
Wrapper around free.
#define _(String)
GNU gettext support macro.
Definition: platform.h:177
static const char * loopback[]
Possible hostnames for "loopback".
Definition: resolver_api.c:47
static const struct GNUNET_CONFIGURATION_Handle * resolver_cfg
Configuration.
Definition: resolver_api.c:57
#define LOG(kind,...)
Definition: resolver_api.c:32

References _, GNUNET_CONFIGURATION_get_value_string(), GNUNET_CONFIGURATION_have_value(), GNUNET_ERROR_TYPE_INFO, GNUNET_free, GNUNET_OK, GNUNET_SYSERR, hostname, LOG, loopback, and resolver_cfg.

Referenced by GNUNET_RESOLVER_hostname_get(), and GNUNET_RESOLVER_ip_get().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ shutdown_task()

static void shutdown_task ( void *  cls)
static

Task executed on system shutdown.

Definition at line 305 of file resolver_api.c.

306 {
307  (void) cls;
308  s_task = NULL;
311 }
void GNUNET_RESOLVER_disconnect()
Destroy the connection to the resolver service.
Definition: resolver_api.c:269
#define GNUNET_TIME_UNIT_MILLISECONDS
One millisecond.
static struct GNUNET_SCHEDULER_Task * s_task
Task ID of shutdown task; only present while we have a connection to the resolver service.
Definition: resolver_api.c:94
static struct GNUNET_TIME_Relative backoff
How long should we wait to reconnect?
Definition: resolver_api.c:83

References backoff, GNUNET_RESOLVER_RequestHandle::cls, GNUNET_RESOLVER_disconnect(), GNUNET_TIME_UNIT_MILLISECONDS, and s_task.

Referenced by check_disconnect(), and process_requests().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_disconnect()

static void check_disconnect ( )
static

Consider disconnecting if we have no further requests pending.

Definition at line 318 of file resolver_api.c.

319 {
320  for (struct GNUNET_RESOLVER_RequestHandle *rh = req_head;
321  NULL != rh;
322  rh = rh->next)
323  if (GNUNET_SYSERR != rh->was_transmitted)
324  return;
325  if (NULL != r_task)
326  {
328  r_task = NULL;
329  }
330  if (NULL != s_task)
331  return;
333  &shutdown_task,
334  NULL);
335 }
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:972
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1269
static void shutdown_task(void *cls)
Task executed on system shutdown.
Definition: resolver_api.c:305
static struct GNUNET_RESOLVER_RequestHandle * req_head
Head of DLL of requests.
Definition: resolver_api.c:68
static struct GNUNET_SCHEDULER_Task * r_task
Task for reconnecting.
Definition: resolver_api.c:88
Handle to a request given to the resolver.
Definition: resolver_api.c:103
struct GNUNET_RESOLVER_RequestHandle * next
Next entry in DLL of requests.
Definition: resolver_api.c:107

References GNUNET_SCHEDULER_add_delayed(), GNUNET_SCHEDULER_cancel(), GNUNET_SYSERR, GNUNET_TIME_UNIT_MILLISECONDS, GNUNET_RESOLVER_RequestHandle::next, r_task, req_head, s_task, and shutdown_task().

Referenced by GNUNET_RESOLVER_request_cancel(), and reconnect().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ no_resolve()

static char* no_resolve ( int  af,
const void *  ip,
socklen_t  ip_len 
)
static

Convert IP address to string without DNS resolution.

Parameters
afaddress family
ipthe address
ip_lennumber of bytes in ip
Returns
address as a string, NULL on error

Definition at line 347 of file resolver_api.c.

350 {
351  char buf[INET6_ADDRSTRLEN];
352 
353  switch (af)
354  {
355  case AF_INET:
356  if (ip_len != sizeof(struct in_addr))
357  return NULL;
358  if (NULL ==
359  inet_ntop (AF_INET,
360  ip,
361  buf,
362  sizeof(buf)))
363  {
365  "inet_ntop");
366  return NULL;
367  }
368  break;
369 
370  case AF_INET6:
371  if (ip_len != sizeof(struct in6_addr))
372  return NULL;
373  if (NULL ==
374  inet_ntop (AF_INET6,
375  ip,
376  buf,
377  sizeof(buf)))
378  {
380  "inet_ntop");
381  return NULL;
382  }
383  break;
384 
385  default:
386  GNUNET_break (0);
387  return NULL;
388  }
389  return GNUNET_strdup (buf);
390 }
static char buf[2048]
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
@ GNUNET_ERROR_TYPE_WARNING
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define LOG_STRERROR(kind, syscall)
Definition: resolver_api.c:34

References GNUNET_RESOLVER_RequestHandle::af, buf, GNUNET_break, GNUNET_ERROR_TYPE_WARNING, GNUNET_strdup, and LOG_STRERROR.

Referenced by handle_lookup_timeout(), handle_response(), and numeric_reverse().

Here is the caller graph for this function:

◆ reconnect()

static void reconnect ( void  )
static

Adjust exponential back-off and reconnect to the service.

Definition at line 827 of file resolver_api.c.

828 {
830 
831  if (NULL != r_task)
832  return;
833  GNUNET_assert (NULL == mq);
834  if (NULL != (rh = req_head))
835  {
836  switch (rh->was_transmitted)
837  {
838  case GNUNET_NO:
839  /* nothing more to do */
840  break;
841 
842  case GNUNET_YES:
843  /* disconnected, transmit again! */
845  break;
846 
847  case GNUNET_SYSERR:
848  /* request was cancelled, remove entirely */
850  req_tail,
851  rh);
852  GNUNET_free (rh);
853  check_disconnect ();
854  break;
855 
856  default:
857  GNUNET_assert (0);
858  break;
859  }
860  }
862  "Will try to connect to DNS service in %s\n",
864  GNUNET_YES));
865  GNUNET_assert (NULL != resolver_cfg);
868  NULL);
870 }
@ GNUNET_YES
Definition: gnunet_common.h:97
@ GNUNET_NO
Definition: gnunet_common.h:94
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
@ GNUNET_ERROR_TYPE_DEBUG
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition: strings.c:557
#define GNUNET_TIME_STD_BACKOFF(r)
Perform our standard exponential back-off calculation, starting at 1 ms and then going by a factor of...
static struct GNUNET_RESOLVER_RequestHandle * req_tail
Tail of DLL of requests.
Definition: resolver_api.c:73
static void check_disconnect()
Consider disconnecting if we have no further requests pending.
Definition: resolver_api.c:318
static struct GNUNET_MQ_Handle * mq
Our connection to the resolver service, created on-demand, but then persists until error or shutdown.
Definition: resolver_api.c:63
static void reconnect_task(void *cls)
Now try to reconnect to the resolver service.
Definition: resolver_api.c:791
int was_transmitted
Has this request been transmitted to the service? GNUNET_YES if transmitted GNUNET_NO if not transmit...
Definition: resolver_api.c:158

References backoff, check_disconnect(), GNUNET_assert, GNUNET_CONTAINER_DLL_remove, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_NO, GNUNET_SCHEDULER_add_delayed(), GNUNET_STRINGS_relative_time_to_string(), GNUNET_SYSERR, GNUNET_TIME_STD_BACKOFF, GNUNET_YES, LOG, mq, r_task, reconnect_task(), req_head, req_tail, resolver_cfg, and GNUNET_RESOLVER_RequestHandle::was_transmitted.

Referenced by handle_response(), mq_error_handler(), process_requests(), and reconnect_task().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ mq_error_handler()

static void mq_error_handler ( void *  cls,
enum GNUNET_MQ_Error  error 
)
static

Generic error handler, called with the appropriate error code and the same closure specified at the creation of the message queue.

Not every message queue implementation supports an error handler.

Parameters
clsNULL
errorerror code

Definition at line 409 of file resolver_api.c.

411 {
412  (void) cls;
414  mq = NULL;
416  "MQ error %d, reconnecting\n",
417  error);
418  reconnect ();
419 }
void GNUNET_MQ_destroy(struct GNUNET_MQ_Handle *mq)
Destroy the message queue.
Definition: mq.c:837
static void reconnect(void)
Adjust exponential back-off and reconnect to the service.
Definition: resolver_api.c:827

References GNUNET_RESOLVER_RequestHandle::cls, GNUNET_ERROR_TYPE_DEBUG, GNUNET_MQ_destroy(), LOG, mq, and reconnect().

Referenced by reconnect_task().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ process_requests()

static void process_requests ( )
static

Process pending requests to the resolver.

Definition at line 426 of file resolver_api.c.

427 {
429  struct GNUNET_MQ_Envelope *env;
431 
432  if (NULL == mq)
433  {
434  reconnect ();
435  return;
436  }
437  if (NULL == rh)
438  {
439  /* nothing to do, release socket really soon if there is nothing
440  * else happening... */
441  if (NULL == s_task)
442  s_task =
444  &shutdown_task,
445  NULL);
446  return;
447  }
448  if (GNUNET_NO != rh->was_transmitted)
449  return; /* waiting for reply */
451  rh->data_len,
453  msg->direction = htonl (rh->direction);
454  msg->af = htonl (rh->af);
455  msg->client_id = rh->id;
456  GNUNET_memcpy (&msg[1],
457  &rh[1],
458  rh->data_len);
460  "Transmitting DNS resolution request (ID %u) to DNS service\n",
461  rh->id);
463  env);
465 }
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition: mq.c:355
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct.
Definition: gnunet_mq_lib.h:52
#define GNUNET_MESSAGE_TYPE_RESOLVER_REQUEST
Request DNS resolution.
Request for the resolver.
Definition: resolver.h:44
size_t data_len
Length of the data that follows this struct.
Definition: resolver_api.c:178
int af
Desired address family.
Definition: resolver_api.c:145
uint32_t id
Identifies the request.
Definition: resolver_api.c:150
int direction
Desired direction (IP to name or name to IP)
Definition: resolver_api.c:168

References GNUNET_RESOLVER_RequestHandle::af, GNUNET_RESOLVER_RequestHandle::data_len, GNUNET_RESOLVER_RequestHandle::direction, env, GNUNET_ERROR_TYPE_DEBUG, GNUNET_memcpy, GNUNET_MESSAGE_TYPE_RESOLVER_REQUEST, GNUNET_MQ_msg_extra, GNUNET_MQ_send(), GNUNET_NO, GNUNET_SCHEDULER_add_delayed(), GNUNET_TIME_UNIT_MILLISECONDS, GNUNET_YES, GNUNET_RESOLVER_RequestHandle::id, LOG, mq, msg, reconnect(), req_head, s_task, shutdown_task(), and GNUNET_RESOLVER_RequestHandle::was_transmitted.

Referenced by GNUNET_RESOLVER_hostname_get(), GNUNET_RESOLVER_ip_get(), handle_lookup_timeout(), handle_response(), and reconnect_task().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_response()

static int check_response ( void *  cls,
const struct GNUNET_RESOLVER_ResponseMessage msg 
)
static

Check validity of response with a hostname for a DNS lookup.

Parameters
clsNULL
msgmessage with the hostname

Definition at line 475 of file resolver_api.c.

477 {
478  (void) cls;
479  (void) msg;
480 
481  /* implemented in #handle_response() for now */
482  return GNUNET_OK;
483 }

References GNUNET_RESOLVER_RequestHandle::cls, GNUNET_OK, and msg.

◆ handle_response()

static void handle_response ( void *  cls,
const struct GNUNET_RESOLVER_ResponseMessage msg 
)
static

Check validity of response with a hostname for a DNS lookup.

NOTE: right now rather messy, might want to use different message types for different response formats in the future.

Parameters
clsNULL
msgmessage with the response

Definition at line 495 of file resolver_api.c.

497 {
499  uint16_t size;
500  char *nret;
501  uint32_t client_request_id = msg->client_id;
502 
503  for (; rh != NULL; rh = rh->next)
504  {
505  if (rh->id == client_request_id)
506  break;
507  }
508 
509  (void) cls;
510  if (NULL == rh)
511  {
512  /* Resolver service sent extra replies to query (after terminator)? Bad! */
513  GNUNET_break (0);
515  mq = NULL;
516  reconnect ();
517  return;
518  }
519  size = ntohs (msg->header.size);
520  if (size == sizeof(struct GNUNET_RESOLVER_ResponseMessage))
521  {
523  "Received empty response from DNS service\n");
524  /* message contains not data, just header; end of replies */
525  /* check if request was canceled */
526  if (GNUNET_SYSERR != rh->was_transmitted)
527  {
528  /* no reverse lookup was successful, return IP as string */
529  if (NULL != rh->name_callback)
530  {
531  if (GNUNET_NO == rh->received_response)
532  {
533  nret = no_resolve (rh->af,
534  &rh[1],
535  rh->data_len);
536  rh->name_callback (rh->cls, nret);
537  GNUNET_free (nret);
538  }
539  /* finally, make termination call */
540  if (GNUNET_SYSERR != rh->was_transmitted)
541  rh->name_callback (rh->cls,
542  NULL);
543  }
544  if ((NULL != rh->addr_callback) &&
546  rh->addr_callback (rh->cls,
547  NULL,
548  0);
549  }
552  process_requests ();
553  return;
554  }
555  /* return reverse lookup results to caller */
556  if (NULL != rh->name_callback)
557  {
558  const char *hostname;
559 
560  hostname = (const char *) &msg[1];
561  if (hostname[size - sizeof(struct GNUNET_RESOLVER_ResponseMessage) - 1] !=
562  '\0')
563  {
564  GNUNET_break (0);
565  if (GNUNET_SYSERR != rh->was_transmitted)
566  rh->name_callback (rh->cls,
567  NULL);
571  mq = NULL;
572  reconnect ();
573  return;
574  }
576  "Resolver returns `%s' for IP `%s'.\n",
577  hostname,
578  GNUNET_a2s ((const void *) &rh[1],
579  rh->data_len));
580  if (rh->was_transmitted != GNUNET_SYSERR)
581  rh->name_callback (rh->cls,
582  hostname);
584  }
585  /* return lookup results to caller */
586  if (NULL != rh->addr_callback)
587  {
588  struct sockaddr_in v4;
589  struct sockaddr_in6 v6;
590  const struct sockaddr *sa;
591  socklen_t salen;
592  const void *ip;
593  size_t ip_len;
594 
595  ip = &msg[1];
596  ip_len = size - sizeof(struct GNUNET_RESOLVER_ResponseMessage);
597  if (ip_len == sizeof(struct in_addr))
598  {
599  memset (&v4, 0, sizeof(v4));
600  v4.sin_family = AF_INET;
601  v4.sin_addr = *(struct in_addr*) ip;
602 #if HAVE_SOCKADDR_IN_SIN_LEN
603  v4.sin_len = sizeof(v4);
604 #endif
605  salen = sizeof(v4);
606  sa = (const struct sockaddr *) &v4;
607  }
608  else if (ip_len == sizeof(struct in6_addr))
609  {
610  memset (&v6, 0, sizeof(v6));
611  v6.sin6_family = AF_INET6;
612  v6.sin6_addr = *(struct in6_addr*) ip;
613 #if HAVE_SOCKADDR_IN_SIN_LEN
614  v6.sin6_len = sizeof(v6);
615 #endif
616  salen = sizeof(v6);
617  sa = (const struct sockaddr *) &v6;
618  }
619  else
620  {
621  GNUNET_break (0);
622  if (GNUNET_SYSERR != rh->was_transmitted)
623  rh->addr_callback (rh->cls,
624  NULL,
625  0);
629  mq = NULL;
630  reconnect ();
631  return;
632  }
634  "Received IP from DNS service\n");
635  if (GNUNET_SYSERR != rh->was_transmitted)
636  rh->addr_callback (rh->cls,
637  sa,
638  salen);
639  }
640 }
const char * GNUNET_a2s(const struct sockaddr *addr, socklen_t addrlen)
Convert a "struct sockaddr*" (IPv4 or IPv6 address) to a string (for printing debug messages).
void GNUNET_RESOLVER_request_cancel(struct GNUNET_RESOLVER_RequestHandle *rh)
Cancel a request that is still pending with the resolver.
static unsigned int size
Size of the "table".
Definition: peer.c:67
static char * no_resolve(int af, const void *ip, socklen_t ip_len)
Convert IP address to string without DNS resolution.
Definition: resolver_api.c:347
static void process_requests()
Process pending requests to the resolver.
Definition: resolver_api.c:426
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
GNUNET_RESOLVER_HostnameCallback name_callback
Callback if this is a reverse lookup request, otherwise NULL.
Definition: resolver_api.c:124
void * cls
Closure for the callbacks.
Definition: resolver_api.c:129
GNUNET_RESOLVER_AddressCallback addr_callback
Callback if this is an name resolution request, otherwise NULL.
Definition: resolver_api.c:118
int received_response
GNUNET_YES if a response was received
Definition: resolver_api.c:173

References GNUNET_RESOLVER_RequestHandle::addr_callback, GNUNET_RESOLVER_RequestHandle::af, GNUNET_RESOLVER_RequestHandle::cls, GNUNET_RESOLVER_RequestHandle::data_len, GNUNET_a2s(), GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_MQ_destroy(), GNUNET_NO, GNUNET_RESOLVER_request_cancel(), GNUNET_SYSERR, GNUNET_YES, hostname, GNUNET_RESOLVER_RequestHandle::id, LOG, mq, msg, GNUNET_RESOLVER_RequestHandle::name_callback, GNUNET_RESOLVER_RequestHandle::next, no_resolve(), process_requests(), GNUNET_RESOLVER_RequestHandle::received_response, reconnect(), req_head, GNUNET_MessageHeader::size, size, and GNUNET_RESOLVER_RequestHandle::was_transmitted.

Here is the call graph for this function:

◆ numeric_resolution()

static void numeric_resolution ( void *  cls)
static

We've been asked to lookup the address for a hostname and were given a valid numeric string.

Perform the callbacks for the numeric addresses.

Parameters
clsstruct GNUNET_RESOLVER_RequestHandle for the request

Definition at line 651 of file resolver_api.c.

652 {
653  struct GNUNET_RESOLVER_RequestHandle *rh = cls;
654  struct sockaddr_in v4;
655  struct sockaddr_in6 v6;
656  const char *hostname;
657 
658  rh->task = NULL;
659  memset (&v4, 0, sizeof(v4));
660  v4.sin_family = AF_INET;
661 #if HAVE_SOCKADDR_IN_SIN_LEN
662  v4.sin_len = sizeof(v4);
663 #endif
664  memset (&v6, 0, sizeof(v6));
665  v6.sin6_family = AF_INET6;
666 #if HAVE_SOCKADDR_IN_SIN_LEN
667  v6.sin6_len = sizeof(v6);
668 #endif
669  hostname = (const char *) &rh[1];
670  if (((rh->af == AF_UNSPEC) ||
671  (rh->af == AF_INET)) &&
672  (1 == inet_pton (AF_INET,
673  hostname,
674  &v4.sin_addr)))
675  {
676  rh->addr_callback (rh->cls,
677  (const struct sockaddr *) &v4,
678  sizeof(v4));
679  if ((rh->af == AF_UNSPEC) &&
680  (GNUNET_SYSERR != rh->was_transmitted) &&
681  (1 == inet_pton (AF_INET6,
682  hostname,
683  &v6.sin6_addr)))
684  {
685  /* this can happen on some systems IF "hostname" is "localhost" */
686  rh->addr_callback (rh->cls,
687  (const struct sockaddr *) &v6,
688  sizeof(v6));
689  }
690  if (GNUNET_SYSERR != rh->was_transmitted)
691  rh->addr_callback (rh->cls,
692  NULL,
693  0);
694  GNUNET_free (rh);
695  return;
696  }
697  if (((rh->af == AF_UNSPEC) ||
698  (rh->af == AF_INET6)) &&
699  (1 == inet_pton (AF_INET6,
700  hostname,
701  &v6.sin6_addr)))
702  {
703  rh->addr_callback (rh->cls,
704  (const struct sockaddr *) &v6,
705  sizeof(v6));
706  if (GNUNET_SYSERR != rh->was_transmitted)
707  rh->addr_callback (rh->cls,
708  NULL,
709  0);
710  GNUNET_free (rh);
711  return;
712  }
713  /* why are we here? this task should not have been scheduled! */
714  GNUNET_assert (0);
715  GNUNET_free (rh);
716 }
struct GNUNET_SCHEDULER_Task * task
Task handle for making reply callbacks in numeric lookups asynchronous, and for timeout handling.
Definition: resolver_api.c:140

References GNUNET_RESOLVER_RequestHandle::addr_callback, GNUNET_RESOLVER_RequestHandle::af, GNUNET_RESOLVER_RequestHandle::cls, GNUNET_assert, GNUNET_free, GNUNET_SYSERR, hostname, GNUNET_RESOLVER_RequestHandle::task, and GNUNET_RESOLVER_RequestHandle::was_transmitted.

Referenced by GNUNET_RESOLVER_ip_get().

Here is the caller graph for this function:

◆ loopback_resolution()

static void loopback_resolution ( void *  cls)
static

We've been asked to lookup the address for a hostname and were given a variant of "loopback".

Perform the callbacks for the respective loopback numeric addresses.

Parameters
clsstruct GNUNET_RESOLVER_RequestHandle for the request

Definition at line 727 of file resolver_api.c.

728 {
729  struct GNUNET_RESOLVER_RequestHandle *rh = cls;
730  struct sockaddr_in v4;
731  struct sockaddr_in6 v6;
732 
733  rh->task = NULL;
734  memset (&v4, 0, sizeof(v4));
735  v4.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
736  v4.sin_family = AF_INET;
737 #if HAVE_SOCKADDR_IN_SIN_LEN
738  v4.sin_len = sizeof(v4);
739 #endif
740  memset (&v6, 0, sizeof(v6));
741  v6.sin6_family = AF_INET6;
742 #if HAVE_SOCKADDR_IN_SIN_LEN
743  v6.sin6_len = sizeof(v6);
744 #endif
745  v6.sin6_addr = in6addr_loopback;
746  switch (rh->af)
747  {
748  case AF_INET:
749  rh->addr_callback (rh->cls,
750  (const struct sockaddr *) &v4,
751  sizeof(v4));
752  break;
753 
754  case AF_INET6:
755  rh->addr_callback (rh->cls,
756  (const struct sockaddr *) &v6,
757  sizeof(v6));
758  break;
759 
760  case AF_UNSPEC:
761  rh->addr_callback (rh->cls,
762  (const struct sockaddr *) &v6,
763  sizeof(v6));
764  rh->addr_callback (rh->cls,
765  (const struct sockaddr *) &v4,
766  sizeof(v4));
767 
768  break;
769 
770  default:
771  GNUNET_break (0);
772  break;
773  }
774  if (GNUNET_SYSERR != rh->was_transmitted)
775  rh->addr_callback (rh->cls,
776  NULL,
777  0);
779  "Finished resolving hostname `%s'.\n",
780  (const char *) &rh[1]);
781  GNUNET_free (rh);
782 }

References GNUNET_RESOLVER_RequestHandle::addr_callback, GNUNET_RESOLVER_RequestHandle::af, GNUNET_RESOLVER_RequestHandle::cls, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_SYSERR, LOG, GNUNET_RESOLVER_RequestHandle::task, and GNUNET_RESOLVER_RequestHandle::was_transmitted.

Referenced by GNUNET_RESOLVER_ip_get().

Here is the caller graph for this function:

◆ reconnect_task()

static void reconnect_task ( void *  cls)
static

Now try to reconnect to the resolver service.

Parameters
clsNULL

Definition at line 791 of file resolver_api.c.

792 {
797  NULL),
799  };
800 
801  (void) cls;
802  r_task = NULL;
803  if (NULL == req_head)
804  return; /* no work pending */
806  "Trying to connect to DNS service\n");
808  "resolver",
809  handlers,
811  NULL);
812  if (NULL == mq)
813  {
815  "Failed to connect, will try again later\n");
816  reconnect ();
817  return;
818  }
819  process_requests ();
820 }
static struct GNUNET_CADET_MessageHandler handlers[]
Handlers, for diverse services.
static struct MHD_Response * response
Our canonical response.
struct GNUNET_MQ_Handle * GNUNET_CLIENT_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *service_name, const struct GNUNET_MQ_MessageHandler *handlers, GNUNET_MQ_ErrorHandler error_handler, void *error_handler_cls)
Create a message queue to connect to a GNUnet service.
Definition: client.c:1064
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
void * cls
Closure for mv and cb.
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
#define GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE
Response to a DNS resolution request.
static void mq_error_handler(void *cls, enum GNUNET_MQ_Error error)
Generic error handler, called with the appropriate error code and the same closure specified at the c...
Definition: resolver_api.c:409
Message handler for a specific message type.

References GNUNET_MQ_MessageHandler::cls, GNUNET_CLIENT_connect(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE, GNUNET_MQ_handler_end, GNUNET_MQ_hd_var_size, handlers, LOG, mq, mq_error_handler(), process_requests(), r_task, reconnect(), req_head, resolver_cfg, and response.

Referenced by reconnect().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_lookup_timeout()

static void handle_lookup_timeout ( void *  cls)
static

A DNS resolution timed out.

Notify the application.

Parameters
clsthe struct GNUNET_RESOLVER_RequestHandle *

Definition at line 879 of file resolver_api.c.

880 {
881  struct GNUNET_RESOLVER_RequestHandle *rh = cls;
882 
883  rh->task = NULL;
884  if (GNUNET_NO == rh->direction)
885  {
887  _ ("Timeout trying to resolve hostname `%s'.\n"),
888  (const char *) &rh[1]);
889  if (NULL != rh->addr_callback)
890  rh->addr_callback (rh->cls,
891  NULL,
892  0);
893  }
894  else
895  {
896 #if ! defined(GNUNET_CULL_LOGGING)
897  char buf[INET6_ADDRSTRLEN];
898 
900  _ ("Timeout trying to resolve IP address `%s'.\n"),
901  inet_ntop (rh->af,
902  (const void *) &rh[1],
903  buf,
904  sizeof(buf)));
905 #endif
906  if (GNUNET_NO == rh->received_response)
907  {
908  char *nret;
909 
910  nret = no_resolve (rh->af,
911  &rh[1],
912  rh->data_len);
913  if (NULL != rh->name_callback)
914  rh->name_callback (rh->cls, nret);
915  GNUNET_free (nret);
916  }
917  /* finally, make termination call */
918  if (NULL != rh->name_callback)
919  rh->name_callback (rh->cls,
920  NULL);
921  }
924  process_requests ();
925 }

References _, GNUNET_RESOLVER_RequestHandle::af, buf, GNUNET_RESOLVER_RequestHandle::cls, GNUNET_RESOLVER_RequestHandle::direction, GNUNET_ERROR_TYPE_INFO, GNUNET_free, GNUNET_NO, GNUNET_RESOLVER_request_cancel(), LOG, no_resolve(), process_requests(), GNUNET_RESOLVER_RequestHandle::task, and GNUNET_RESOLVER_RequestHandle::was_transmitted.

Referenced by GNUNET_RESOLVER_hostname_get(), and GNUNET_RESOLVER_ip_get().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ numeric_reverse()

static void numeric_reverse ( void *  cls)
static

We've been asked to convert an address to a string without a reverse lookup, either because the client asked for it or because the DNS lookup hit a timeout.

Do the numeric conversion and invoke the callback.

Parameters
clsstruct GNUNET_RESOLVER_RequestHandle for the request

Definition at line 1029 of file resolver_api.c.

1030 {
1031  struct GNUNET_RESOLVER_RequestHandle *rh = cls;
1032  char *result;
1033 
1034  rh->task = NULL;
1035  result = no_resolve (rh->af,
1036  &rh[1],
1037  rh->data_len);
1039  "Resolver returns `%s'.\n",
1040  result);
1041  if (NULL != result)
1042  {
1043  rh->name_callback (rh->cls,
1044  result);
1045  GNUNET_free (result);
1046  }
1047  rh->name_callback (rh->cls,
1048  NULL);
1049  if (NULL != rh->task)
1050  {
1052  rh->task = NULL;
1053  }
1054  GNUNET_free (rh);
1055 }
static int result
Global testing status.

References GNUNET_RESOLVER_RequestHandle::af, GNUNET_RESOLVER_RequestHandle::cls, GNUNET_RESOLVER_RequestHandle::data_len, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_SCHEDULER_cancel(), LOG, GNUNET_RESOLVER_RequestHandle::name_callback, no_resolve(), result, and GNUNET_RESOLVER_RequestHandle::task.

Referenced by GNUNET_RESOLVER_hostname_get().

Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ loopback

const char* loopback[]
static
Initial value:
= {
"localhost",
"ip6-localnet",
NULL
}

Possible hostnames for "loopback".

Definition at line 47 of file resolver_api.c.

Referenced by check_config(), and GNUNET_RESOLVER_ip_get().

◆ resolver_cfg

const struct GNUNET_CONFIGURATION_Handle* resolver_cfg
static

Configuration.

Definition at line 57 of file resolver_api.c.

Referenced by check_config(), GNUNET_RESOLVER_connect(), reconnect(), and reconnect_task().

◆ mq

struct GNUNET_MQ_Handle* mq
static

Our connection to the resolver service, created on-demand, but then persists until error or shutdown.

Definition at line 63 of file resolver_api.c.

Referenced by GNUNET_RESOLVER_disconnect(), handle_response(), mq_error_handler(), process_requests(), reconnect(), and reconnect_task().

◆ req_head

struct GNUNET_RESOLVER_RequestHandle* req_head
static

◆ req_tail

struct GNUNET_RESOLVER_RequestHandle* req_tail
static

◆ last_request_id

uint32_t last_request_id
static

ID of the last request we sent to the service.

Definition at line 78 of file resolver_api.c.

Referenced by GNUNET_RESOLVER_hostname_get(), and GNUNET_RESOLVER_ip_get().

◆ backoff

struct GNUNET_TIME_Relative backoff
static

How long should we wait to reconnect?

Definition at line 78 of file resolver_api.c.

Referenced by GNUNET_RESOLVER_connect(), reconnect(), and shutdown_task().

◆ r_task

struct GNUNET_SCHEDULER_Task* r_task
static

Task for reconnecting.

Definition at line 88 of file resolver_api.c.

Referenced by check_disconnect(), GNUNET_RESOLVER_disconnect(), reconnect(), and reconnect_task().

◆ s_task

struct GNUNET_SCHEDULER_Task* s_task
static

Task ID of shutdown task; only present while we have a connection to the resolver service.

Definition at line 94 of file resolver_api.c.

Referenced by check_disconnect(), GNUNET_RESOLVER_disconnect(), GNUNET_RESOLVER_hostname_get(), GNUNET_RESOLVER_ip_get(), process_requests(), and shutdown_task().