GNUnet  0.19.4
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 33 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 35 of file resolver_api.c.

◆ MAX_HOSTNAME

#define MAX_HOSTNAME   1024

Maximum supported length for a hostname.

Definition at line 42 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 191 of file resolver_api.c.

192 {
193  char *hostname;
194  struct sockaddr_in v4;
195  struct sockaddr_in6 v6;
196 
197  if (GNUNET_OK ==
199  "resolver",
200  "UNIXPATH"))
201  return GNUNET_OK;
202  memset (&v4, 0, sizeof(v4));
203  v4.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
204  v4.sin_family = AF_INET;
205 #if HAVE_SOCKADDR_IN_SIN_LEN
206  v4.sin_len = sizeof(v4);
207 #endif
208  memset (&v6, 0, sizeof(v6));
209  v6.sin6_family = AF_INET6;
210 #if HAVE_SOCKADDR_IN_SIN_LEN
211  v6.sin6_len = sizeof(v6);
212 #endif
213  if (GNUNET_OK !=
215  "resolver",
216  "HOSTNAME",
217  &hostname))
218  {
220  _ (
221  "Missing `%s' for `%s' in configuration, DNS resolution will be unavailable.\n"),
222  "HOSTNAME",
223  "resolver");
224  return GNUNET_SYSERR;
225  }
226  if ((1 == inet_pton (AF_INET, hostname, &v4)) ||
227  (1 == inet_pton (AF_INET6, hostname, &v6)))
228  {
230  return GNUNET_OK;
231  }
232  for (unsigned int i = 0;
233  NULL != loopback[i];
234  i++)
235  if (0 == strcasecmp (loopback[i],
236  hostname))
237  {
239  return GNUNET_OK;
240  }
242  _ (
243  "Missing `%s' or numeric IP address for `%s' of `%s' in configuration, DNS resolution will be unavailable.\n"),
244  "localhost",
245  "HOSTNAME",
246  "resolver");
248  return GNUNET_SYSERR;
249 }
static char * hostname
Our hostname; we give this to all the peers we start.
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_OK
@ GNUNET_SYSERR
@ 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:48
static const struct GNUNET_CONFIGURATION_Handle * resolver_cfg
Configuration.
Definition: resolver_api.c:58
#define LOG(kind,...)
Definition: resolver_api.c:33

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 306 of file resolver_api.c.

307 {
308  (void) cls;
309  s_task = NULL;
312 }
void GNUNET_RESOLVER_disconnect()
Destroy the connection to the resolver service.
Definition: resolver_api.c:270
#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:95
static struct GNUNET_TIME_Relative backoff
How long should we wait to reconnect?
Definition: resolver_api.c:84

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 319 of file resolver_api.c.

320 {
321  for (struct GNUNET_RESOLVER_RequestHandle *rh = req_head;
322  NULL != rh;
323  rh = rh->next)
324  if (GNUNET_SYSERR != rh->was_transmitted)
325  return;
326  if (NULL != r_task)
327  {
329  r_task = NULL;
330  }
331  if (NULL != s_task)
332  return;
334  &shutdown_task,
335  NULL);
336 }
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:975
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:1272
static void shutdown_task(void *cls)
Task executed on system shutdown.
Definition: resolver_api.c:306
static struct GNUNET_RESOLVER_RequestHandle * req_head
Head of DLL of requests.
Definition: resolver_api.c:69
static struct GNUNET_SCHEDULER_Task * r_task
Task for reconnecting.
Definition: resolver_api.c:89
Handle to a request given to the resolver.
Definition: resolver_api.c:104
struct GNUNET_RESOLVER_RequestHandle * next
Next entry in DLL of requests.
Definition: resolver_api.c:108

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 348 of file resolver_api.c.

351 {
352  char buf[INET6_ADDRSTRLEN];
353 
354  switch (af)
355  {
356  case AF_INET:
357  if (ip_len != sizeof(struct in_addr))
358  return NULL;
359  if (NULL ==
360  inet_ntop (AF_INET,
361  ip,
362  buf,
363  sizeof(buf)))
364  {
366  "inet_ntop");
367  return NULL;
368  }
369  break;
370 
371  case AF_INET6:
372  if (ip_len != sizeof(struct in6_addr))
373  return NULL;
374  if (NULL ==
375  inet_ntop (AF_INET6,
376  ip,
377  buf,
378  sizeof(buf)))
379  {
381  "inet_ntop");
382  return NULL;
383  }
384  break;
385 
386  default:
387  GNUNET_break (0);
388  return NULL;
389  }
390  return GNUNET_strdup (buf);
391 }
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:35

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 828 of file resolver_api.c.

829 {
831 
832  if (NULL != r_task)
833  return;
834  GNUNET_assert (NULL == mq);
835  if (NULL != (rh = req_head))
836  {
837  switch (rh->was_transmitted)
838  {
839  case GNUNET_NO:
840  /* nothing more to do */
841  break;
842 
843  case GNUNET_YES:
844  /* disconnected, transmit again! */
846  break;
847 
848  case GNUNET_SYSERR:
849  /* request was cancelled, remove entirely */
851  req_tail,
852  rh);
853  GNUNET_free (rh);
854  check_disconnect ();
855  break;
856 
857  default:
858  GNUNET_assert (0);
859  break;
860  }
861  }
863  "Will try to connect to DNS service in %s\n",
865  GNUNET_YES));
866  GNUNET_assert (NULL != resolver_cfg);
869  NULL);
871 }
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
@ GNUNET_YES
@ GNUNET_NO
#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:569
#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:74
static void check_disconnect()
Consider disconnecting if we have no further requests pending.
Definition: resolver_api.c:319
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:64
static void reconnect_task(void *cls)
Now try to reconnect to the resolver service.
Definition: resolver_api.c:792
int was_transmitted
Has this request been transmitted to the service? GNUNET_YES if transmitted GNUNET_NO if not transmit...
Definition: resolver_api.c:159

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 410 of file resolver_api.c.

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

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 427 of file resolver_api.c.

428 {
430  struct GNUNET_MQ_Envelope *env;
432 
433  if (NULL == mq)
434  {
435  reconnect ();
436  return;
437  }
438  if (NULL == rh)
439  {
440  /* nothing to do, release socket really soon if there is nothing
441  * else happening... */
442  if (NULL == s_task)
443  s_task =
445  &shutdown_task,
446  NULL);
447  return;
448  }
449  if (GNUNET_NO != rh->was_transmitted)
450  return; /* waiting for reply */
452  rh->data_len,
454  msg->direction = htonl (rh->direction);
455  msg->af = htonl (rh->af);
456  msg->client_id = rh->id;
457  GNUNET_memcpy (&msg[1],
458  &rh[1],
459  rh->data_len);
461  "Transmitting DNS resolution request (ID %u) to DNS service\n",
462  rh->id);
464  env);
466 }
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:304
#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:62
#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:179
int af
Desired address family.
Definition: resolver_api.c:146
uint32_t id
Identifies the request.
Definition: resolver_api.c:151
int direction
Desired direction (IP to name or name to IP)
Definition: resolver_api.c:169

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 476 of file resolver_api.c.

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

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 496 of file resolver_api.c.

498 {
500  uint16_t size;
501  char *nret;
502  uint32_t client_request_id = msg->client_id;
503 
504  for (; rh != NULL; rh = rh->next)
505  {
506  if (rh->id == client_request_id)
507  break;
508  }
509 
510  (void) cls;
511  if (NULL == rh)
512  {
513  /* Resolver service sent extra replies to query (after terminator)? Bad! */
514  GNUNET_break (0);
516  mq = NULL;
517  reconnect ();
518  return;
519  }
520  size = ntohs (msg->header.size);
521  if (size == sizeof(struct GNUNET_RESOLVER_ResponseMessage))
522  {
524  "Received empty response from DNS service\n");
525  /* message contains not data, just header; end of replies */
526  /* check if request was canceled */
527  if (GNUNET_SYSERR != rh->was_transmitted)
528  {
529  /* no reverse lookup was successful, return IP as string */
530  if (NULL != rh->name_callback)
531  {
532  if (GNUNET_NO == rh->received_response)
533  {
534  nret = no_resolve (rh->af,
535  &rh[1],
536  rh->data_len);
537  rh->name_callback (rh->cls, nret);
538  GNUNET_free (nret);
539  }
540  /* finally, make termination call */
541  if (GNUNET_SYSERR != rh->was_transmitted)
542  rh->name_callback (rh->cls,
543  NULL);
544  }
545  if ((NULL != rh->addr_callback) &&
547  rh->addr_callback (rh->cls,
548  NULL,
549  0);
550  }
553  process_requests ();
554  return;
555  }
556  /* return reverse lookup results to caller */
557  if (NULL != rh->name_callback)
558  {
559  const char *hostname;
560 
561  hostname = (const char *) &msg[1];
562  if (hostname[size - sizeof(struct GNUNET_RESOLVER_ResponseMessage) - 1] !=
563  '\0')
564  {
565  GNUNET_break (0);
566  if (GNUNET_SYSERR != rh->was_transmitted)
567  rh->name_callback (rh->cls,
568  NULL);
572  mq = NULL;
573  reconnect ();
574  return;
575  }
577  "Resolver returns `%s' for IP `%s'.\n",
578  hostname,
579  GNUNET_a2s ((const void *) &rh[1],
580  rh->data_len));
581  if (rh->was_transmitted != GNUNET_SYSERR)
582  rh->name_callback (rh->cls,
583  hostname);
585  }
586  /* return lookup results to caller */
587  if (NULL != rh->addr_callback)
588  {
589  struct sockaddr_in v4;
590  struct sockaddr_in6 v6;
591  const struct sockaddr *sa;
592  socklen_t salen;
593  const void *ip;
594  size_t ip_len;
595 
596  ip = &msg[1];
597  ip_len = size - sizeof(struct GNUNET_RESOLVER_ResponseMessage);
598  if (ip_len == sizeof(struct in_addr))
599  {
600  memset (&v4, 0, sizeof(v4));
601  v4.sin_family = AF_INET;
602  v4.sin_addr = *(struct in_addr*) ip;
603 #if HAVE_SOCKADDR_IN_SIN_LEN
604  v4.sin_len = sizeof(v4);
605 #endif
606  salen = sizeof(v4);
607  sa = (const struct sockaddr *) &v4;
608  }
609  else if (ip_len == sizeof(struct in6_addr))
610  {
611  memset (&v6, 0, sizeof(v6));
612  v6.sin6_family = AF_INET6;
613  v6.sin6_addr = *(struct in6_addr*) ip;
614 #if HAVE_SOCKADDR_IN_SIN_LEN
615  v6.sin6_len = sizeof(v6);
616 #endif
617  salen = sizeof(v6);
618  sa = (const struct sockaddr *) &v6;
619  }
620  else
621  {
622  GNUNET_break (0);
623  if (GNUNET_SYSERR != rh->was_transmitted)
624  rh->addr_callback (rh->cls,
625  NULL,
626  0);
630  mq = NULL;
631  reconnect ();
632  return;
633  }
635  "Received IP from DNS service\n");
636  if (GNUNET_SYSERR != rh->was_transmitted)
637  rh->addr_callback (rh->cls,
638  sa,
639  salen);
640  }
641 }
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:68
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:348
static void process_requests()
Process pending requests to the resolver.
Definition: resolver_api.c:427
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:125
void * cls
Closure for the callbacks.
Definition: resolver_api.c:130
GNUNET_RESOLVER_AddressCallback addr_callback
Callback if this is an name resolution request, otherwise NULL.
Definition: resolver_api.c:119
int received_response
GNUNET_YES if a response was received
Definition: resolver_api.c:174

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 652 of file resolver_api.c.

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

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 728 of file resolver_api.c.

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

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 792 of file resolver_api.c.

793 {
798  NULL),
800  };
801 
802  (void) cls;
803  r_task = NULL;
804  if (NULL == req_head)
805  return; /* no work pending */
807  "Trying to connect to DNS service\n");
809  "resolver",
810  handlers,
812  NULL);
813  if (NULL == mq)
814  {
816  "Failed to connect, will try again later\n");
817  reconnect ();
818  return;
819  }
820  process_requests ();
821 }
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:1057
void * cls
Closure for mv and cb.
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#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:410
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 880 of file resolver_api.c.

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

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 1030 of file resolver_api.c.

1031 {
1032  struct GNUNET_RESOLVER_RequestHandle *rh = cls;
1033  char *result;
1034 
1035  rh->task = NULL;
1036  result = no_resolve (rh->af,
1037  &rh[1],
1038  rh->data_len);
1040  "Resolver returns `%s'.\n",
1041  result);
1042  if (NULL != result)
1043  {
1044  rh->name_callback (rh->cls,
1045  result);
1046  GNUNET_free (result);
1047  }
1048  rh->name_callback (rh->cls,
1049  NULL);
1050  if (NULL != rh->task)
1051  {
1053  rh->task = NULL;
1054  }
1055  GNUNET_free (rh);
1056 }
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 48 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 58 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 64 of file resolver_api.c.

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

◆ req_head

◆ req_tail

◆ last_request_id

uint32_t last_request_id
static

ID of the last request we sent to the service.

Definition at line 79 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 79 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 89 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 95 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().