GNUnet  0.20.0
gnunet-service-dns.c File Reference

service to intercept and modify DNS queries (and replies) of this system More...

#include "platform.h"
#include "gnunet_util_lib.h"
#include "gnunet_applications.h"
#include "gnunet_constants.h"
#include "gnunet_protocols.h"
#include "gnunet_signatures.h"
#include "dns.h"
#include "gnunet_dns_service.h"
#include "gnunet_statistics_service.h"
Include dependency graph for gnunet-service-dns.c:

Go to the source code of this file.

Data Structures

struct  ClientRecord
 Entry we keep for each client. More...
 
struct  RequestRecord
 Entry we keep for each active request. More...
 

Macros

#define DNS_PORT   53
 Port number for DNS. More...
 
#define LOG(kind, ...)    GNUNET_log_from (kind, "dns", __VA_ARGS__);
 Generic logging shorthand. More...
 

Enumerations

enum  RequestPhase {
  RP_INIT , RP_REQUEST_MONITOR , RP_QUERY , RP_INTERNET_DNS ,
  RP_MODIFY , RP_RESPONSE_MONITOR , RP_DROP
}
 Phases each request goes through. More...
 

Functions

static void cleanup_rr (struct RequestRecord *rr)
 We're done processing a DNS request, free associated memory. More...
 
static void cleanup_task (void *cls)
 Task run during shutdown. More...
 
static void request_done (struct RequestRecord *rr)
 We're done with some request, finish processing. More...
 
static void send_request_to_client (struct RequestRecord *rr, struct ClientRecord *cr)
 Show the payload of the given request record to the client (and wait for a response). More...
 
static void process_dns_result (void *cls, const struct GNUNET_TUN_DnsHeader *dns, size_t r)
 Callback called from DNSSTUB resolver when a resolution succeeded. More...
 
static void next_phase (struct RequestRecord *rr)
 A client has completed its processing for this request. More...
 
static void * client_connect_cb (void *cls, struct GNUNET_SERVICE_Client *client, struct GNUNET_MQ_Handle *mq)
 A client connected, setup our data structures. More...
 
static void client_disconnect_cb (void *cls, struct GNUNET_SERVICE_Client *client, void *app_ctx)
 A client disconnected, clean up after it. More...
 
static void handle_client_init (void *cls, const struct GNUNET_DNS_Register *reg)
 We got a new client. More...
 
static int check_client_response (void *cls, const struct GNUNET_DNS_Response *resp)
 Check a response from a client. More...
 
static void handle_client_response (void *cls, const struct GNUNET_DNS_Response *resp)
 Handle a response from a client. More...
 
static int process_helper_messages (void *cls, const struct GNUNET_MessageHeader *message)
 Functions with this signature are called whenever a complete message is received by the tokenizer from the DNS hijack process. More...
 
static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg_, struct GNUNET_SERVICE_Handle *service)
 
 GNUNET_SERVICE_MAIN ("dns", GNUNET_SERVICE_OPTION_NONE, &run, &client_connect_cb, &client_disconnect_cb, NULL, GNUNET_MQ_hd_fixed_size(client_init, GNUNET_MESSAGE_TYPE_DNS_CLIENT_INIT, struct GNUNET_DNS_Register, NULL), GNUNET_MQ_hd_var_size(client_response, GNUNET_MESSAGE_TYPE_DNS_CLIENT_RESPONSE, struct GNUNET_DNS_Response, NULL), GNUNET_MQ_handler_end())
 Define "main" method using service macro. More...
 

Variables

static int global_ret
 Global return value from 'main'. More...
 
static const struct GNUNET_CONFIGURATION_Handlecfg
 The configuration to use. More...
 
static struct GNUNET_STATISTICS_Handlestats
 Statistics. More...
 
static struct GNUNET_HELPER_Handlehijacker
 Handle to DNS hijacker helper process ("gnunet-helper-dns"). More...
 
static char * helper_argv [8]
 Command-line arguments we are giving to the hijacker process. More...
 
static struct ClientRecordclients_head
 Head of DLL of clients we consult. More...
 
static struct ClientRecordclients_tail
 Tail of DLL of clients we consult. More...
 
static struct RequestRecord requests [UINT16_MAX+1]
 Array of all open requests. More...
 
static uint64_t request_id_gen
 Generator for unique request IDs. More...
 
static struct GNUNET_DNSSTUB_Contextdnsstub
 Handle to the DNS Stub resolver. More...
 

Detailed Description

service to intercept and modify DNS queries (and replies) of this system

Author
Christian Grothoff

For "secure" interaction with the legacy DNS system, we permit replies only to arrive within a 5s window (and they must match ports, IPs and request IDs). Furthermore, we let the OS pick a source port, opening up to 128 sockets per address family (IPv4 or IPv6). Those sockets are closed if they are not in use for 5s (which means they will be freshly randomized afterwards). For new requests, we pick a random slot in the array with 128 socket slots (and re-use an existing socket if the slot is still in use). Thus each request will be given one of 128 random source ports, and the 128 random source ports will also change "often" (less often if the system is very busy, each time if we are mostly idle). At the same time, the system will never use more than 256 UDP sockets.

Definition in file gnunet-service-dns.c.

Macro Definition Documentation

◆ DNS_PORT

#define DNS_PORT   53

Port number for DNS.

Definition at line 52 of file gnunet-service-dns.c.

◆ LOG

#define LOG (   kind,
  ... 
)     GNUNET_log_from (kind, "dns", __VA_ARGS__);

Generic logging shorthand.

Definition at line 58 of file gnunet-service-dns.c.

Enumeration Type Documentation

◆ RequestPhase

Phases each request goes through.

Enumerator
RP_INIT 

Request has just been received.

RP_REQUEST_MONITOR 

Showing the request to all monitor clients.

If client list is empty, will enter QUERY phase.

RP_QUERY 

Showing the request to PRE-RESOLUTION clients to find an answer.

If client list is empty, will trigger global DNS request.

RP_INTERNET_DNS 

Global Internet query is now pending.

RP_MODIFY 

Client (or global DNS request) has resulted in a response.

Forward to all POST-RESOLUTION clients. If client list is empty, will enter RESPONSE_MONITOR phase.

RP_RESPONSE_MONITOR 

Showing the request to all monitor clients.

If client list is empty, give the result to the hijacker (and be done).

RP_DROP 

Some client has told us to drop the request.

Definition at line 65 of file gnunet-service-dns.c.

66 {
70  RP_INIT,
71 
77 
82  RP_QUERY,
83 
88 
94  RP_MODIFY,
95 
101 
105  RP_DROP
106 };
@ RP_REQUEST_MONITOR
Showing the request to all monitor clients.
@ RP_QUERY
Showing the request to PRE-RESOLUTION clients to find an answer.
@ RP_MODIFY
Client (or global DNS request) has resulted in a response.
@ RP_DROP
Some client has told us to drop the request.
@ RP_INTERNET_DNS
Global Internet query is now pending.
@ RP_INIT
Request has just been received.
@ RP_RESPONSE_MONITOR
Showing the request to all monitor clients.

Function Documentation

◆ cleanup_rr()

static void cleanup_rr ( struct RequestRecord rr)
static

We're done processing a DNS request, free associated memory.

Parameters
rrrequest to clean up

Definition at line 255 of file gnunet-service-dns.c.

256 {
257  GNUNET_free (rr->payload);
258  rr->payload = NULL;
259  rr->payload_length = 0;
262  0);
263 }
#define GNUNET_array_grow(arr, size, tsize)
Grow a well-typed (!) array.
#define GNUNET_free(ptr)
Wrapper around free.
char * payload
Payload of the UDP packet (the UDP payload), can be either query or already the response.
unsigned int client_wait_list_length
Length of the client_wait_list.
size_t payload_length
Number of bytes in payload.
struct ClientRecord ** client_wait_list
List of clients that still need to see this request (each entry is set to NULL when the client is don...

References RequestRecord::client_wait_list, RequestRecord::client_wait_list_length, GNUNET_array_grow, GNUNET_free, RequestRecord::payload, and RequestRecord::payload_length.

Referenced by cleanup_task(), next_phase(), request_done(), and send_request_to_client().

Here is the caller graph for this function:

◆ cleanup_task()

static void cleanup_task ( void *  cls)
static

Task run during shutdown.

Parameters
clsunused

Definition at line 272 of file gnunet-service-dns.c.

273 {
274  if (NULL != hijacker)
275  {
277  hijacker = NULL;
278  }
279  for (unsigned int i = 0; i < 8; i++)
281  for (unsigned int i = 0; i <= UINT16_MAX; i++)
282  cleanup_rr (&requests[i]);
283  if (NULL != stats)
284  {
286  GNUNET_NO);
287  stats = NULL;
288  }
289  if (NULL != dnsstub)
290  {
292  dnsstub = NULL;
293  }
294 }
static struct GNUNET_STATISTICS_Handle * stats
Statistics.
static struct GNUNET_HELPER_Handle * hijacker
Handle to DNS hijacker helper process ("gnunet-helper-dns").
static struct GNUNET_DNSSTUB_Context * dnsstub
Handle to the DNS Stub resolver.
static char * helper_argv[8]
Command-line arguments we are giving to the hijacker process.
static struct RequestRecord requests[UINT16_MAX+1]
Array of all open requests.
static void cleanup_rr(struct RequestRecord *rr)
We're done processing a DNS request, free associated memory.
void GNUNET_DNSSTUB_stop(struct GNUNET_DNSSTUB_Context *ctx)
Cleanup DNSSTUB resolver.
Definition: dnsstub.c:705
void GNUNET_HELPER_stop(struct GNUNET_HELPER_Handle *h, int soft_kill)
Kills the helper, closes the pipe, frees the handle and calls wait() on the helper process.
Definition: helper.c:538
@ GNUNET_NO
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).

References cleanup_rr(), dnsstub, GNUNET_DNSSTUB_stop(), GNUNET_free, GNUNET_HELPER_stop(), GNUNET_NO, GNUNET_STATISTICS_destroy(), helper_argv, hijacker, requests, and stats.

Referenced by run().

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

◆ request_done()

static void request_done ( struct RequestRecord rr)
static

We're done with some request, finish processing.

Parameters
rrrequest send to the network or just clean up.

Definition at line 303 of file gnunet-service-dns.c.

304 {
305  struct GNUNET_MessageHeader *hdr;
306  size_t reply_len;
307  uint16_t source_port;
308  uint16_t destination_port;
309 
312  0);
313  if (RP_RESPONSE_MONITOR != rr->phase)
314  {
315  /* no response, drop */
317  "Got no response for request %llu, dropping\n",
318  (unsigned long long) rr->request_id);
319  cleanup_rr (rr);
320  return;
321  }
322 
324  "Transmitting response for request %llu\n",
325  (unsigned long long) rr->request_id);
326  /* send response via hijacker */
327  reply_len = sizeof(struct GNUNET_MessageHeader);
328  reply_len += sizeof(struct GNUNET_TUN_Layer2PacketHeader);
329  switch (rr->src_addr.ss_family)
330  {
331  case AF_INET:
332  reply_len += sizeof(struct GNUNET_TUN_IPv4Header);
333  break;
334 
335  case AF_INET6:
336  reply_len += sizeof(struct GNUNET_TUN_IPv6Header);
337  break;
338 
339  default:
340  GNUNET_break (0);
341  cleanup_rr (rr);
342  return;
343  }
344  reply_len += sizeof(struct GNUNET_TUN_UdpHeader);
345  reply_len += rr->payload_length;
346  if (reply_len >= GNUNET_MAX_MESSAGE_SIZE)
347  {
348  /* response too big, drop */
349  GNUNET_break (0); /* how can this be? */
350  cleanup_rr (rr);
351  return;
352  }
353  {
354  char buf[reply_len] GNUNET_ALIGN;
355  size_t off;
356  struct GNUNET_TUN_IPv4Header ip4;
357  struct GNUNET_TUN_IPv6Header ip6;
358 
359  /* first, GNUnet message header */
360  hdr = (struct GNUNET_MessageHeader*) buf;
361  hdr->type = htons (GNUNET_MESSAGE_TYPE_DNS_HELPER);
362  hdr->size = htons ((uint16_t) reply_len);
363  off = sizeof(struct GNUNET_MessageHeader);
364 
365  /* first, TUN header */
366  {
368 
369  tun.flags = htons (0);
370  if (rr->src_addr.ss_family == AF_INET)
371  tun.proto = htons (ETH_P_IPV4);
372  else
373  tun.proto = htons (ETH_P_IPV6);
374  GNUNET_memcpy (&buf[off],
375  &tun,
376  sizeof(struct GNUNET_TUN_Layer2PacketHeader));
377  off += sizeof(struct GNUNET_TUN_Layer2PacketHeader);
378  }
379 
380  /* now IP header */
381  switch (rr->src_addr.ss_family)
382  {
383  case AF_INET:
384  {
385  struct sockaddr_in *src = (struct sockaddr_in *) &rr->src_addr;
386  struct sockaddr_in *dst = (struct sockaddr_in *) &rr->dst_addr;
387 
388  source_port = dst->sin_port;
389  destination_port = src->sin_port;
391  IPPROTO_UDP,
392  reply_len - off - sizeof(struct
394  &dst->sin_addr,
395  &src->sin_addr);
396  GNUNET_memcpy (&buf[off],
397  &ip4,
398  sizeof(ip4));
399  off += sizeof(ip4);
400  }
401  break;
402 
403  case AF_INET6:
404  {
405  struct sockaddr_in6 *src = (struct sockaddr_in6 *) &rr->src_addr;
406  struct sockaddr_in6 *dst = (struct sockaddr_in6 *) &rr->dst_addr;
407 
408  source_port = dst->sin6_port;
409  destination_port = src->sin6_port;
411  IPPROTO_UDP,
412  reply_len - off - sizeof(struct
414  &dst->sin6_addr,
415  &src->sin6_addr);
416  GNUNET_memcpy (&buf[off],
417  &ip6,
418  sizeof(ip6));
419  off += sizeof(ip6);
420  }
421  break;
422 
423  default:
424  GNUNET_assert (0);
425  }
426 
427  /* now UDP header */
428  {
429  struct GNUNET_TUN_UdpHeader udp;
430 
431  udp.source_port = source_port;
432  udp.destination_port = destination_port;
433  udp.len = htons (reply_len - off);
434  if (AF_INET == rr->src_addr.ss_family)
436  &udp,
437  rr->payload,
438  rr->payload_length);
439  else
441  &udp,
442  rr->payload,
443  rr->payload_length);
444  GNUNET_memcpy (&buf[off],
445  &udp,
446  sizeof(udp));
447  off += sizeof(udp);
448  }
449 
450  /* now DNS payload */
451  {
452  GNUNET_memcpy (&buf[off], rr->payload, rr->payload_length);
453  off += rr->payload_length;
454  }
455  /* final checks & sending */
456  GNUNET_assert (off == reply_len);
458  hdr,
459  GNUNET_YES,
460  NULL, NULL);
462  gettext_noop (
463  "# DNS requests answered via TUN interface"),
464  1, GNUNET_NO);
465  }
466  /* clean up, we're done */
467  cleanup_rr (rr);
468 }
#define gettext_noop(String)
Definition: gettext.h:70
#define LOG(kind,...)
Generic logging shorthand.
static char buf[2048]
static int udp
Option -u: UDP requested.
Definition: gnunet-vpn.c:75
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message,...
struct GNUNET_HELPER_SendHandle * GNUNET_HELPER_send(struct GNUNET_HELPER_Handle *h, const struct GNUNET_MessageHeader *msg, int can_drop, GNUNET_HELPER_Continuation cont, void *cont_cls)
Send an message to the helper.
Definition: helper.c:615
#define GNUNET_ALIGN
gcc-ism to force alignment; we use this to align char-arrays that may then be cast to 'struct's.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
@ GNUNET_YES
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
@ GNUNET_ERROR_TYPE_DEBUG
#define GNUNET_MESSAGE_TYPE_DNS_HELPER
Type of messages between the gnunet-helper-dns and the service.
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
void GNUNET_TUN_initialize_ipv6_header(struct GNUNET_TUN_IPv6Header *ip, uint8_t protocol, uint16_t payload_length, const struct in6_addr *src, const struct in6_addr *dst)
Initialize an IPv6 header.
Definition: tun.c:82
void GNUNET_TUN_calculate_udp4_checksum(const struct GNUNET_TUN_IPv4Header *ip, struct GNUNET_TUN_UdpHeader *udp, const void *payload, uint16_t payload_length)
Calculate IPv4 UDP checksum.
Definition: tun.c:160
GNUNET_NETWORK_STRUCT_END void GNUNET_TUN_initialize_ipv4_header(struct GNUNET_TUN_IPv4Header *ip, uint8_t protocol, uint16_t payload_length, const struct in_addr *src, const struct in_addr *dst)
Initialize an IPv4 header.
Definition: tun.c:47
#define ETH_P_IPV6
Number for IPv6.
#define ETH_P_IPV4
Number for IPv4.
void GNUNET_TUN_calculate_udp6_checksum(const struct GNUNET_TUN_IPv6Header *ip, struct GNUNET_TUN_UdpHeader *udp, const void *payload, uint16_t payload_length)
Calculate IPv6 UDP checksum.
Definition: tun.c:191
Header for all communications.
Standard IPv4 header.
Standard IPv6 header.
Header from Linux TUN interface.
uint16_t flags
Some flags (unused).
UDP packet header.
uint16_t destination_port
Destination port (in NBO).
uint16_t source_port
Source port (in NBO).
struct sockaddr_storage src_addr
Source address of the original request (for sending response).
uint64_t request_id
ID of this request, also basis for hashing.
struct sockaddr_storage dst_addr
Destination address of the original request (for potential use as exit).
enum RequestPhase phase
In which phase this this request?

References buf, cleanup_rr(), RequestRecord::client_wait_list, RequestRecord::client_wait_list_length, GNUNET_TUN_UdpHeader::destination_port, RequestRecord::dst_addr, ETH_P_IPV4, ETH_P_IPV6, GNUNET_TUN_Layer2PacketHeader::flags, gettext_noop, GNUNET_ALIGN, GNUNET_array_grow, GNUNET_assert, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_HELPER_send(), GNUNET_MAX_MESSAGE_SIZE, GNUNET_memcpy, GNUNET_MESSAGE_TYPE_DNS_HELPER, GNUNET_NO, GNUNET_STATISTICS_update(), GNUNET_TUN_calculate_udp4_checksum(), GNUNET_TUN_calculate_udp6_checksum(), GNUNET_TUN_initialize_ipv4_header(), GNUNET_TUN_initialize_ipv6_header(), GNUNET_YES, hijacker, LOG, RequestRecord::payload, RequestRecord::payload_length, RequestRecord::phase, GNUNET_TUN_Layer2PacketHeader::proto, RequestRecord::request_id, RP_RESPONSE_MONITOR, GNUNET_TUN_UdpHeader::source_port, RequestRecord::src_addr, stats, and udp.

Referenced by next_phase().

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

◆ send_request_to_client()

static void send_request_to_client ( struct RequestRecord rr,
struct ClientRecord cr 
)
static

Show the payload of the given request record to the client (and wait for a response).

Parameters
rrrequest to send to client
crclient to send the response to

Definition at line 479 of file gnunet-service-dns.c.

481 {
482  struct GNUNET_MQ_Envelope *env;
483  struct GNUNET_DNS_Request *req;
484 
485  if (sizeof(struct GNUNET_DNS_Request) + rr->payload_length >=
487  {
488  GNUNET_break (0);
489  cleanup_rr (rr);
490  return;
491  }
493  "Sending information about request %llu to local client\n",
494  (unsigned long long) rr->request_id);
495  env = GNUNET_MQ_msg_extra (req,
496  rr->payload_length,
498  req->reserved = htonl (0);
499  req->request_id = rr->request_id;
500  GNUNET_memcpy (&req[1],
501  rr->payload,
502  rr->payload_length);
503  GNUNET_MQ_send (cr->mq,
504  env);
505 }
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
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:63
#define GNUNET_MESSAGE_TYPE_DNS_CLIENT_REQUEST
Type of messages between the gnunet-helper-dns and the service.
struct GNUNET_MQ_Handle * mq
Message queue to talk to client.
Message from DNS service to client: please handle a request.
Definition: dns.h:53
uint32_t reserved
Always zero.
Definition: dns.h:62
uint64_t request_id
Unique request ID.
Definition: dns.h:67

References cleanup_rr(), env, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_MAX_MESSAGE_SIZE, GNUNET_memcpy, GNUNET_MESSAGE_TYPE_DNS_CLIENT_REQUEST, GNUNET_MQ_msg_extra, GNUNET_MQ_send(), LOG, ClientRecord::mq, RequestRecord::payload, RequestRecord::payload_length, GNUNET_DNS_Request::request_id, RequestRecord::request_id, and GNUNET_DNS_Request::reserved.

Referenced by next_phase().

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

◆ process_dns_result()

static void process_dns_result ( void *  cls,
const struct GNUNET_TUN_DnsHeader dns,
size_t  r 
)
static

Callback called from DNSSTUB resolver when a resolution succeeded.

Parameters
clsNULL
dnsthe response itself
rnumber of bytes in dns

Definition at line 735 of file gnunet-service-dns.c.

738 {
739  struct RequestRecord *rr;
740 
742  "Processing DNS result from stub resolver\n");
743  GNUNET_assert (NULL == cls);
744  if (NULL == dns)
745  return; /* ignore */
746 
747  rr = &requests[dns->id];
748  if (rr->phase != RP_INTERNET_DNS)
749  {
750  /* unexpected / bogus reply */
752  gettext_noop (
753  "# External DNS response discarded (no matching request)"),
754  1, GNUNET_NO);
756  "Received DNS reply that does not match any pending request. Dropping.\n");
757  return;
758  }
760  "Got a response from the stub resolver for DNS request %llu intercepted locally!\n",
761  (unsigned long long) rr->request_id);
762  GNUNET_free (rr->payload);
763  rr->payload = GNUNET_malloc (r);
764  GNUNET_memcpy (rr->payload,
765  dns,
766  r);
767  rr->payload_length = r;
768  next_phase (rr);
769 }
static void next_phase(struct RequestRecord *rr)
A client has completed its processing for this request.
#define GNUNET_log(kind,...)
#define GNUNET_malloc(size)
Wrapper around malloc.
uint16_t id
Unique identifier for the request/response.
Entry we keep for each active request.

References gettext_noop, GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_malloc, GNUNET_memcpy, GNUNET_NO, GNUNET_STATISTICS_update(), GNUNET_TUN_DnsHeader::id, LOG, next_phase(), RequestRecord::payload, RequestRecord::payload_length, RequestRecord::phase, RequestRecord::request_id, requests, RP_INTERNET_DNS, and stats.

Referenced by next_phase().

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

◆ next_phase()

static void next_phase ( struct RequestRecord rr)
static

A client has completed its processing for this request.

Move on.

Parameters
rrrequest to process further

Definition at line 529 of file gnunet-service-dns.c.

530 {
531  struct ClientRecord *cr;
532  int nz;
533 
534  if (rr->phase == RP_DROP)
535  {
536  cleanup_rr (rr);
537  return;
538  }
539  nz = -1;
540  for (unsigned int j = 0; j < rr->client_wait_list_length; j++)
541  {
542  if (NULL != rr->client_wait_list[j])
543  {
544  nz = (int) j;
545  break;
546  }
547  }
548  if (-1 != nz)
549  {
551  rr->client_wait_list[nz]);
552  return;
553  }
554  /* done with current phase, advance! */
556  "Request %llu now in phase %d\n",
557  (unsigned long long) rr->request_id,
558  rr->phase);
559  switch (rr->phase)
560  {
561  case RP_INIT:
563  for (cr = clients_head; NULL != cr; cr = cr->next)
564  {
565  if (0 != (cr->flags & GNUNET_DNS_FLAG_REQUEST_MONITOR))
568  cr);
569  }
570  next_phase (rr);
571  return;
572 
573  case RP_REQUEST_MONITOR:
574  rr->phase = RP_QUERY;
575  for (cr = clients_head; NULL != cr; cr = cr->next)
576  {
577  if (0 != (cr->flags & GNUNET_DNS_FLAG_PRE_RESOLUTION))
580  cr);
581  }
582  next_phase (rr);
583  return;
584 
585  case RP_QUERY:
586 #if 0
587  /* TODO: optionally, use this to forward DNS requests to the
588  * original* DNS server instead of the one we have configured...
589  (but then we need to create a fresh dnsstub for each request
590  * and* manage the timeout) */
591  switch (rr->dst_addr.ss_family)
592  {
593  case AF_INET:
594  salen = sizeof(struct sockaddr_in);
595  sa = (const struct sockaddr *) &rr->dst_addr;
596  break;
597 
598  case AF_INET6:
599  salen = sizeof(struct sockaddr_in6);
600  sa = (const struct sockaddr *) &rr->dst_addr;
601  break;
602 
603  default:
604  GNUNET_assert (0);
605  }
606 #endif
607  rr->phase = RP_INTERNET_DNS;
609  rr->payload,
610  rr->payload_length,
612  NULL);
613  if (NULL == rr->rs)
614  {
616  gettext_noop (
617  "# DNS exit failed (failed to open socket)"),
618  1,
619  GNUNET_NO);
620  cleanup_rr (rr);
621  return;
622  }
623  return;
624 
625  case RP_INTERNET_DNS:
626  rr->phase = RP_MODIFY;
627  for (cr = clients_head; NULL != cr; cr = cr->next)
628  {
629  if (0 != (cr->flags & GNUNET_DNS_FLAG_POST_RESOLUTION))
632  cr);
633  }
634  next_phase (rr);
635  return;
636 
637  case RP_MODIFY:
639  for (cr = clients_head; NULL != cr; cr = cr->next)
640  {
641  if (0 != (cr->flags & GNUNET_DNS_FLAG_RESPONSE_MONITOR))
644  cr);
645  }
646  next_phase (rr);
647  return;
648 
649  case RP_RESPONSE_MONITOR:
650  request_done (rr);
651  break;
652 
653  case RP_DROP:
654  cleanup_rr (rr);
655  break;
656 
657  default:
658  GNUNET_break (0);
659  cleanup_rr (rr);
660  break;
661  }
662 }
static void process_dns_result(void *cls, const struct GNUNET_TUN_DnsHeader *dns, size_t r)
Callback called from DNSSTUB resolver when a resolution succeeded.
static void request_done(struct RequestRecord *rr)
We're done with some request, finish processing.
static struct ClientRecord * clients_head
Head of DLL of clients we consult.
static void send_request_to_client(struct RequestRecord *rr, struct ClientRecord *cr)
Show the payload of the given request record to the client (and wait for a response).
struct GNUNET_DNSSTUB_RequestSocket * GNUNET_DNSSTUB_resolve(struct GNUNET_DNSSTUB_Context *ctx, const void *request, size_t request_len, GNUNET_DNSSTUB_ResultCallback rc, void *rc_cls)
Perform DNS resolution using our default IP from init.
Definition: dnsstub.c:526
@ GNUNET_DNS_FLAG_RESPONSE_MONITOR
Set this flag to see all requests just before they are returned to the network.
@ GNUNET_DNS_FLAG_REQUEST_MONITOR
Set this flag to see all requests first prior to resolution (for monitoring).
@ GNUNET_DNS_FLAG_PRE_RESOLUTION
This client should be called on requests that have not yet been resolved as this client provides a re...
@ GNUNET_DNS_FLAG_POST_RESOLUTION
This client wants to be called on the results of a DNS resolution (either resolved by PRE-RESOLUTION ...
#define GNUNET_array_append(arr, len, element)
Append an element to an array (growing the array by one).
Entry we keep for each client.
enum GNUNET_DNS_Flags flags
Flags for the client.
struct ClientRecord * next
Kept in doubly-linked list.
struct GNUNET_DNSSTUB_RequestSocket * rs
Socket we are using to transmit this request (must match if we receive a response).

References cleanup_rr(), RequestRecord::client_wait_list, RequestRecord::client_wait_list_length, clients_head, dnsstub, RequestRecord::dst_addr, ClientRecord::flags, gettext_noop, GNUNET_array_append, GNUNET_assert, GNUNET_break, GNUNET_DNS_FLAG_POST_RESOLUTION, GNUNET_DNS_FLAG_PRE_RESOLUTION, GNUNET_DNS_FLAG_REQUEST_MONITOR, GNUNET_DNS_FLAG_RESPONSE_MONITOR, GNUNET_DNSSTUB_resolve(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_NO, GNUNET_STATISTICS_update(), consensus-simulation::int, LOG, ClientRecord::next, RequestRecord::payload, RequestRecord::payload_length, RequestRecord::phase, process_dns_result(), request_done(), RequestRecord::request_id, RP_DROP, RP_INIT, RP_INTERNET_DNS, RP_MODIFY, RP_QUERY, RP_REQUEST_MONITOR, RP_RESPONSE_MONITOR, RequestRecord::rs, send_request_to_client(), and stats.

Referenced by client_disconnect_cb(), handle_client_response(), process_dns_result(), and process_helper_messages().

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

◆ client_connect_cb()

static void* client_connect_cb ( void *  cls,
struct GNUNET_SERVICE_Client client,
struct GNUNET_MQ_Handle mq 
)
static

A client connected, setup our data structures.

Parameters
clsunused
clienthandle of client that connected
mqmessage queue to talk to client
Returns
our struct ClientRecord

Definition at line 674 of file gnunet-service-dns.c.

677 {
678  struct ClientRecord *cr = cls;
679 
680  cr = GNUNET_new (struct ClientRecord);
681  cr->client = client;
682  cr->mq = mq;
684  clients_tail,
685  cr);
686  return cr;
687 }
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
static struct ClientRecord * clients_tail
Tail of DLL of clients we consult.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
struct GNUNET_SERVICE_Client * client
Handle to the client.

References ClientRecord::client, clients_head, clients_tail, GNUNET_CONTAINER_DLL_insert, GNUNET_new, mq, and ClientRecord::mq.

◆ client_disconnect_cb()

static void client_disconnect_cb ( void *  cls,
struct GNUNET_SERVICE_Client client,
void *  app_ctx 
)
static

A client disconnected, clean up after it.

Parameters
clsunused
clienthandle of client that disconnected
app_ctxour struct ClientRecord

Definition at line 698 of file gnunet-service-dns.c.

701 {
702  struct ClientRecord *cr = app_ctx;
703  struct RequestRecord *rr;
704 
706  clients_tail,
707  cr);
708  for (unsigned int i = 0; i < UINT16_MAX; i++)
709  {
710  rr = &requests[i];
711  if (0 == rr->client_wait_list_length)
712  continue; /* not in use */
713  for (unsigned int j = 0; j < rr->client_wait_list_length; j++)
714  {
715  if (rr->client_wait_list[j] == cr)
716  {
717  rr->client_wait_list[j] = NULL;
718  next_phase (rr);
719  }
720  }
721  }
722  GNUNET_free (cr);
723 }
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.

References RequestRecord::client_wait_list, RequestRecord::client_wait_list_length, clients_head, clients_tail, GNUNET_CONTAINER_DLL_remove, GNUNET_free, next_phase(), and requests.

Here is the call graph for this function:

◆ handle_client_init()

static void handle_client_init ( void *  cls,
const struct GNUNET_DNS_Register reg 
)
static

We got a new client.

Make sure all new DNS requests pass by its desk.

Parameters
clsthe client
regthe init message

Definition at line 779 of file gnunet-service-dns.c.

781 {
782  struct ClientRecord *cr = cls;
783 
784  cr->flags = (enum GNUNET_DNS_Flags) ntohl (reg->flags);
786 }
GNUNET_DNS_Flags
Flags that specify when to call the client's handler.
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2249
uint32_t flags
NBO encoding of enum GNUNET_DNS_Flags for the client.
Definition: dns.h:45

References ClientRecord::client, GNUNET_DNS_Register::flags, ClientRecord::flags, and GNUNET_SERVICE_client_continue().

Here is the call graph for this function:

◆ check_client_response()

static int check_client_response ( void *  cls,
const struct GNUNET_DNS_Response resp 
)
static

Check a response from a client.

Parameters
clsthe client
respthe response
Returns
GNUNET_OK (always fine)

Definition at line 797 of file gnunet-service-dns.c.

799 {
800  return GNUNET_OK; /* any payload is acceptable */
801 }
@ GNUNET_OK

References GNUNET_OK.

◆ handle_client_response()

static void handle_client_response ( void *  cls,
const struct GNUNET_DNS_Response resp 
)
static

Handle a response from a client.

Parameters
clsthe client
respthe response

Definition at line 811 of file gnunet-service-dns.c.

813 {
814  struct ClientRecord *cr = cls;
815  struct RequestRecord *rr;
816  uint16_t msize;
817  uint16_t off;
818 
819  msize = ntohs (resp->header.size);
820  off = (uint16_t) resp->request_id;
821  rr = &requests[off];
823  "Received DNS response with ID %llu from local client!\n",
824  (unsigned long long) resp->request_id);
825  if (rr->request_id != resp->request_id)
826  {
828  gettext_noop (
829  "# Client response discarded (no matching request)"),
830  1,
831  GNUNET_NO);
833  return;
834  }
835  for (unsigned int i = 0; i < rr->client_wait_list_length; i++)
836  {
837  if (NULL == rr->client_wait_list[i])
838  continue;
839  if (rr->client_wait_list[i] != cr)
840  continue;
841  rr->client_wait_list[i] = NULL;
842  switch (ntohl (resp->drop_flag))
843  {
844  case 0: /* drop */
845  rr->phase = RP_DROP;
846  break;
847 
848  case 1: /* no change */
849  break;
850 
851  case 2: /* update */
852  msize -= sizeof(struct GNUNET_DNS_Response);
853  if ((sizeof(struct GNUNET_TUN_DnsHeader) > msize) ||
854  (RP_REQUEST_MONITOR == rr->phase) ||
855  (RP_RESPONSE_MONITOR == rr->phase))
856  {
857  GNUNET_break (0);
859  next_phase (rr);
860  return;
861  }
862  GNUNET_free (rr->payload);
864  "Changing DNS reply according to client specifications\n");
865  rr->payload = GNUNET_malloc (msize);
866  rr->payload_length = msize;
867  GNUNET_memcpy (rr->payload, &resp[1], msize);
868  if (rr->phase == RP_QUERY)
869  {
870  /* clear wait list, we're moving to MODIFY phase next */
873  0);
874  }
875  /* if query changed to answer, move past DNS resolution phase... */
876  if ((RP_QUERY == rr->phase) &&
877  (rr->payload_length > sizeof(struct GNUNET_TUN_DnsHeader)) &&
878  ( ((struct GNUNET_TUN_DnsFlags*) &(((struct
879  GNUNET_TUN_DnsHeader*) rr->
880  payload)->flags))->
881  query_or_response == 1) )
882  {
883  rr->phase = RP_INTERNET_DNS;
886  0);
887  }
888  break;
889  }
890  next_phase (rr);
892  return;
893  }
894  /* odd, client was not on our list for the request, that ought
895  to be an error */
896  GNUNET_break (0);
898 }
static unsigned long long payload
How much data are we currently storing in the database?
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2330
Message from client to DNS service: here is my reply.
Definition: dns.h:77
struct GNUNET_MessageHeader header
Header of type GNUNET_MESSAGE_TYPE_DNS_CLIENT_RESPONSE.
Definition: dns.h:81
uint32_t drop_flag
Zero to drop, 1 for no change (no payload), 2 for update (message has payload).
Definition: dns.h:86
uint64_t request_id
Unique request ID.
Definition: dns.h:91
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
DNS flags (largely RFC 1035 / RFC 2136).

References ClientRecord::client, RequestRecord::client_wait_list, RequestRecord::client_wait_list_length, GNUNET_DNS_Response::drop_flag, gettext_noop, GNUNET_array_grow, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_malloc, GNUNET_memcpy, GNUNET_NO, GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_drop(), GNUNET_STATISTICS_update(), GNUNET_DNS_Response::header, LOG, next_phase(), payload, RequestRecord::payload, RequestRecord::payload_length, RequestRecord::phase, GNUNET_DNS_Response::request_id, RequestRecord::request_id, requests, RP_DROP, RP_INTERNET_DNS, RP_QUERY, RP_REQUEST_MONITOR, RP_RESPONSE_MONITOR, GNUNET_MessageHeader::size, and stats.

Here is the call graph for this function:

◆ process_helper_messages()

static int process_helper_messages ( void *  cls,
const struct GNUNET_MessageHeader message 
)
static

Functions with this signature are called whenever a complete message is received by the tokenizer from the DNS hijack process.

Parameters
clsclosure
messagethe actual message, a DNS request we should handle

Definition at line 909 of file gnunet-service-dns.c.

911 {
912  uint16_t msize;
913  const struct GNUNET_TUN_Layer2PacketHeader *tun;
914  const struct GNUNET_TUN_IPv4Header *ip4;
915  const struct GNUNET_TUN_IPv6Header *ip6;
916  const struct GNUNET_TUN_UdpHeader *udp;
917  const struct GNUNET_TUN_DnsHeader *dns;
918  struct RequestRecord *rr;
919  struct sockaddr_in *srca4;
920  struct sockaddr_in6 *srca6;
921  struct sockaddr_in *dsta4;
922  struct sockaddr_in6 *dsta6;
923 
925  "Intercepted message via DNS hijacker\n");
926  msize = ntohs (message->size);
927  if (msize < sizeof(struct GNUNET_MessageHeader) + sizeof(struct
929  + sizeof(struct GNUNET_TUN_IPv4Header))
930  {
931  /* non-IP packet received on TUN!? */
932  GNUNET_break (0);
933  return GNUNET_OK;
934  }
935  msize -= sizeof(struct GNUNET_MessageHeader);
936  tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
937  msize -= sizeof(struct GNUNET_TUN_Layer2PacketHeader);
938  switch (ntohs (tun->proto))
939  {
940  case ETH_P_IPV4:
941  ip4 = (const struct GNUNET_TUN_IPv4Header *) &tun[1];
942  ip6 = NULL; /* make compiler happy */
943  if ((msize < sizeof(struct GNUNET_TUN_IPv4Header)) ||
944  (ip4->version != 4) ||
945  (ip4->header_length != sizeof(struct GNUNET_TUN_IPv4Header) / 4) ||
946  (ntohs (ip4->total_length) != msize) ||
947  (ip4->protocol != IPPROTO_UDP))
948  {
949  /* non-IP/UDP packet received on TUN (or with options) */
951  _ ("Received malformed IPv4-UDP packet on TUN interface.\n"));
952  return GNUNET_OK;
953  }
954  udp = (const struct GNUNET_TUN_UdpHeader*) &ip4[1];
955  msize -= sizeof(struct GNUNET_TUN_IPv4Header);
956  break;
957 
958  case ETH_P_IPV6:
959  ip4 = NULL; /* make compiler happy */
960  ip6 = (const struct GNUNET_TUN_IPv6Header *) &tun[1];
961  if ((msize < sizeof(struct GNUNET_TUN_IPv6Header)) ||
962  (ip6->version != 6) ||
963  (ntohs (ip6->payload_length) != msize - sizeof(struct
965  ||
966  (ip6->next_header != IPPROTO_UDP))
967  {
968  /* non-IP/UDP packet received on TUN (or with extensions) */
970  _ ("Received malformed IPv6-UDP packet on TUN interface.\n"));
971  return GNUNET_OK;
972  }
973  udp = (const struct GNUNET_TUN_UdpHeader *) &ip6[1];
974  msize -= sizeof(struct GNUNET_TUN_IPv6Header);
975  break;
976 
977  default:
978  /* non-IP packet received on TUN!? */
980  _ (
981  "Got non-IP packet with %u bytes and protocol %u from TUN\n"),
982  (unsigned int) msize,
983  ntohs (tun->proto));
984  return GNUNET_OK;
985  }
986  if ((msize <= sizeof(struct GNUNET_TUN_UdpHeader) + sizeof(struct
988  ||
989  (DNS_PORT != ntohs (udp->destination_port)))
990  {
991  /* non-DNS packet received on TUN, ignore */
993  _ ("DNS interceptor got non-DNS packet (dropped)\n"));
995  gettext_noop (
996  "# Non-DNS UDP packet received via TUN interface"),
997  1, GNUNET_NO);
998  return GNUNET_OK;
999  }
1000  msize -= sizeof(struct GNUNET_TUN_UdpHeader);
1001  dns = (const struct GNUNET_TUN_DnsHeader*) &udp[1];
1002  rr = &requests[dns->id];
1003 
1004  /* clean up from previous request */
1005  GNUNET_free (rr->payload);
1006  rr->payload = NULL;
1009  0);
1010 
1011  /* setup new request */
1012  rr->phase = RP_INIT;
1013  switch (ntohs (tun->proto))
1014  {
1015  case ETH_P_IPV4:
1016  {
1017  srca4 = (struct sockaddr_in*) &rr->src_addr;
1018  dsta4 = (struct sockaddr_in*) &rr->dst_addr;
1019  memset (srca4, 0, sizeof(struct sockaddr_in));
1020  memset (dsta4, 0, sizeof(struct sockaddr_in));
1021  srca4->sin_family = AF_INET;
1022  dsta4->sin_family = AF_INET;
1023  srca4->sin_addr = ip4->source_address;
1024  dsta4->sin_addr = ip4->destination_address;
1025  srca4->sin_port = udp->source_port;
1026  dsta4->sin_port = udp->destination_port;
1027 #if HAVE_SOCKADDR_IN_SIN_LEN
1028  srca4->sin_len = sizeof(struct sockaddr_in);
1029  dsta4->sin_len = sizeof(struct sockaddr_in);
1030 #endif
1031  }
1032  break;
1033 
1034  case ETH_P_IPV6:
1035  {
1036  srca6 = (struct sockaddr_in6*) &rr->src_addr;
1037  dsta6 = (struct sockaddr_in6*) &rr->dst_addr;
1038  memset (srca6, 0, sizeof(struct sockaddr_in6));
1039  memset (dsta6, 0, sizeof(struct sockaddr_in6));
1040  srca6->sin6_family = AF_INET6;
1041  dsta6->sin6_family = AF_INET6;
1042  srca6->sin6_addr = ip6->source_address;
1043  dsta6->sin6_addr = ip6->destination_address;
1044  srca6->sin6_port = udp->source_port;
1045  dsta6->sin6_port = udp->destination_port;
1046 #if HAVE_SOCKADDR_IN_SIN_LEN
1047  srca6->sin6_len = sizeof(struct sockaddr_in6);
1048  dsta6->sin6_len = sizeof(struct sockaddr_in6);
1049 #endif
1050  }
1051  break;
1052 
1053  default:
1054  GNUNET_assert (0);
1055  }
1056  rr->payload = GNUNET_malloc (msize);
1057  rr->payload_length = msize;
1058  GNUNET_memcpy (rr->payload, dns, msize);
1059  rr->request_id = dns->id | (request_id_gen << 16);
1060  request_id_gen++;
1062  "Creating new DNS request %llu\n",
1063  (unsigned long long) rr->request_id);
1065  gettext_noop (
1066  "# DNS requests received via TUN interface"),
1067  1, GNUNET_NO);
1068  /* start request processing state machine */
1069  next_phase (rr);
1070  return GNUNET_OK;
1071 }
static uint64_t request_id_gen
Generator for unique request IDs.
#define DNS_PORT
Port number for DNS.
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_INFO
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
uint16_t total_length
Length of the packet, including this header.
uint8_t protocol
L4-protocol, for example, IPPROTO_UDP or IPPROTO_TCP.
struct in_addr source_address
Origin of the packet.
struct in_addr destination_address
Destination of the packet.
unsigned int header_length
struct in6_addr source_address
Origin of the packet.
uint8_t next_header
For example, IPPROTO_UDP or IPPROTO_TCP.
struct in6_addr destination_address
Destination of the packet.
uint16_t payload_length
Length of the payload, excluding this header.
uint16_t proto
Here we get an ETH_P_-number.

References _, RequestRecord::client_wait_list, RequestRecord::client_wait_list_length, GNUNET_TUN_IPv4Header::destination_address, GNUNET_TUN_IPv6Header::destination_address, DNS_PORT, RequestRecord::dst_addr, ETH_P_IPV4, ETH_P_IPV6, gettext_noop, GNUNET_array_grow, GNUNET_assert, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_log, GNUNET_malloc, GNUNET_memcpy, GNUNET_NO, GNUNET_OK, GNUNET_STATISTICS_update(), GNUNET_TUN_IPv4Header::header_length, GNUNET_TUN_DnsHeader::id, LOG, GNUNET_TUN_IPv6Header::next_header, next_phase(), RequestRecord::payload, RequestRecord::payload_length, GNUNET_TUN_IPv6Header::payload_length, RequestRecord::phase, GNUNET_TUN_Layer2PacketHeader::proto, GNUNET_TUN_IPv4Header::protocol, RequestRecord::request_id, request_id_gen, requests, RP_INIT, GNUNET_MessageHeader::size, GNUNET_TUN_IPv4Header::source_address, GNUNET_TUN_IPv6Header::source_address, RequestRecord::src_addr, stats, GNUNET_TUN_IPv4Header::total_length, udp, GNUNET_TUN_IPv4Header::version, and GNUNET_TUN_IPv6Header::version.

Referenced by run().

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

◆ run()

static void run ( void *  cls,
const struct GNUNET_CONFIGURATION_Handle cfg_,
struct GNUNET_SERVICE_Handle service 
)
static
Parameters
clsclosure
cfg_configuration to use
servicethe initialized service

Definition at line 1080 of file gnunet-service-dns.c.

1083 {
1084  char *ifc_name;
1085  char *ipv4addr;
1086  char *ipv4mask;
1087  char *ipv6addr;
1088  char *ipv6prefix;
1089  char *dns_exit;
1090  char *binary;
1091  int nortsetup;
1092 
1093  cfg = cfg_;
1094  stats = GNUNET_STATISTICS_create ("dns", cfg);
1096  cls);
1097  dnsstub = GNUNET_DNSSTUB_start (128);
1098  /* TODO: support multiple DNS_EXIT servers being configured */
1099  /* TODO: see above TODO on using DNS server from original packet.
1100  Not sure which is best... */
1101  dns_exit = NULL;
1102  if ((GNUNET_OK !=
1104  "dns",
1105  "DNS_EXIT",
1106  &dns_exit)) ||
1107  (GNUNET_OK !=
1109  dns_exit)))
1110  {
1112  "dns",
1113  "DNS_EXIT",
1114  _ ("need a valid IPv4 or IPv6 address\n"));
1115  GNUNET_free (dns_exit);
1116  }
1117  binary = GNUNET_OS_get_suid_binary_path (cfg, "gnunet-helper-dns");
1118 
1119  if (GNUNET_YES !=
1121  GNUNET_YES,
1122  NULL)) // TODO: once we have a windows-testcase, add test parameters here
1123  {
1125  _ ("`%s' is not SUID or the path is invalid, "
1126  "will not run DNS interceptor\n"),
1127  binary);
1128  global_ret = 1;
1129  GNUNET_free (binary);
1130  return;
1131  }
1132  GNUNET_free (binary);
1133 
1134  helper_argv[0] = GNUNET_strdup ("gnunet-dns");
1135  if (GNUNET_SYSERR ==
1137  "dns",
1138  "IFNAME",
1139  &ifc_name))
1140  {
1142  "No entry 'IFNAME' in configuration!\n");
1143  GNUNET_free (binary);
1145  return;
1146  }
1147  helper_argv[1] = ifc_name;
1148  if ((GNUNET_SYSERR ==
1150  "dns",
1151  "IPV6ADDR",
1152  &ipv6addr)))
1153  {
1155  "No entry 'IPV6ADDR' in configuration!\n");
1156  GNUNET_free (binary);
1158  return;
1159  }
1160  helper_argv[2] = ipv6addr;
1161  if (GNUNET_SYSERR ==
1163  "dns",
1164  "IPV6PREFIX",
1165  &ipv6prefix))
1166  {
1168  "No entry 'IPV6PREFIX' in configuration!\n");
1169  GNUNET_free (binary);
1171  return;
1172  }
1173  helper_argv[3] = ipv6prefix;
1174 
1175  if (GNUNET_SYSERR ==
1177  "dns",
1178  "IPV4ADDR",
1179  &ipv4addr))
1180  {
1182  "No entry 'IPV4ADDR' in configuration!\n");
1183  GNUNET_free (binary);
1185  return;
1186  }
1187  helper_argv[4] = ipv4addr;
1188  if (GNUNET_SYSERR ==
1189  GNUNET_CONFIGURATION_get_value_string (cfg, "dns", "IPV4MASK",
1190  &ipv4mask))
1191  {
1193  "No entry 'IPV4MASK' in configuration!\n");
1194  GNUNET_free (binary);
1196  return;
1197  }
1198  helper_argv[5] = ipv4mask;
1199 
1200  nortsetup = GNUNET_CONFIGURATION_get_value_yesno (cfg, "dns",
1201  "SKIP_ROUTING_SETUP");
1202  if (GNUNET_YES == nortsetup)
1203  helper_argv[6] = GNUNET_strdup ("1");
1204  else
1205  helper_argv[6] = GNUNET_strdup ("0");
1206 
1207  helper_argv[7] = NULL;
1209  binary,
1210  helper_argv,
1212  NULL, NULL);
1213  GNUNET_free (binary);
1214 }
static unsigned long long ipv6prefix
IPv6 prefix (0..127) from configuration file.
static int process_helper_messages(void *cls, const struct GNUNET_MessageHeader *message)
Functions with this signature are called whenever a complete message is received by the tokenizer fro...
static int global_ret
Global return value from 'main'.
static const struct GNUNET_CONFIGURATION_Handle * cfg
The configuration to use.
static void cleanup_task(void *cls)
Task run during shutdown.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
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.
int GNUNET_DNSSTUB_add_dns_ip(struct GNUNET_DNSSTUB_Context *ctx, const char *dns_ip)
Add nameserver for use by the DNSSTUB.
Definition: dnsstub.c:613
struct GNUNET_DNSSTUB_Context * GNUNET_DNSSTUB_start(unsigned int num_sockets)
Start a DNS stub resolver.
Definition: dnsstub.c:586
struct GNUNET_HELPER_Handle * GNUNET_HELPER_start(int with_control_pipe, const char *binary_name, char *const binary_argv[], GNUNET_MessageTokenizerCallback cb, GNUNET_HELPER_ExceptionCallback exp_cb, void *cb_cls)
Starts a helper and begins reading from it.
Definition: helper.c:462
@ GNUNET_SYSERR
void GNUNET_log_config_invalid(enum GNUNET_ErrorType kind, const char *section, const char *option, const char *required)
Log error message about invalid configuration option value.
@ GNUNET_ERROR_TYPE_ERROR
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
char * GNUNET_OS_get_suid_binary_path(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *progname)
Given the name of a helper, service or daemon binary construct the full path to the binary using the ...
enum GNUNET_GenericReturnValue GNUNET_OS_check_helper_binary(const char *binary, bool check_suid, const char *params)
Check whether an executable exists and possibly if the suid bit is set on the file.
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:562
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received,...
Definition: scheduler.c:1334
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.

References _, cfg, cleanup_task(), dnsstub, global_ret, GNUNET_CONFIGURATION_get_value_string(), GNUNET_CONFIGURATION_get_value_yesno(), GNUNET_DNSSTUB_add_dns_ip(), GNUNET_DNSSTUB_start(), GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_HELPER_start(), GNUNET_log, GNUNET_log_config_invalid(), GNUNET_NO, GNUNET_OK, GNUNET_OS_check_helper_binary(), GNUNET_OS_get_suid_binary_path(), GNUNET_SCHEDULER_add_shutdown(), GNUNET_SCHEDULER_shutdown(), GNUNET_STATISTICS_create(), GNUNET_strdup, GNUNET_SYSERR, GNUNET_YES, helper_argv, hijacker, ipv6prefix, process_helper_messages(), and stats.

Here is the call graph for this function:

◆ GNUNET_SERVICE_MAIN()

GNUNET_SERVICE_MAIN ( "dns"  ,
GNUNET_SERVICE_OPTION_NONE  ,
run,
client_connect_cb,
client_disconnect_cb,
NULL  ,
GNUNET_MQ_hd_fixed_size(client_init, GNUNET_MESSAGE_TYPE_DNS_CLIENT_INIT, struct GNUNET_DNS_Register, NULL)  ,
GNUNET_MQ_hd_var_size(client_response, GNUNET_MESSAGE_TYPE_DNS_CLIENT_RESPONSE, struct GNUNET_DNS_Response, NULL)  ,
GNUNET_MQ_handler_end()   
)

Define "main" method using service macro.

Variable Documentation

◆ global_ret

int global_ret
static

Global return value from 'main'.

Definition at line 201 of file gnunet-service-dns.c.

Referenced by run().

◆ cfg

const struct GNUNET_CONFIGURATION_Handle* cfg
static

The configuration to use.

Definition at line 206 of file gnunet-service-dns.c.

Referenced by run().

◆ stats

◆ hijacker

struct GNUNET_HELPER_Handle* hijacker
static

Handle to DNS hijacker helper process ("gnunet-helper-dns").

Definition at line 216 of file gnunet-service-dns.c.

Referenced by cleanup_task(), request_done(), and run().

◆ helper_argv

char* helper_argv[8]
static

Command-line arguments we are giving to the hijacker process.

Definition at line 221 of file gnunet-service-dns.c.

Referenced by cleanup_task(), and run().

◆ clients_head

struct ClientRecord* clients_head
static

Head of DLL of clients we consult.

Definition at line 226 of file gnunet-service-dns.c.

Referenced by client_connect_cb(), client_disconnect_cb(), and next_phase().

◆ clients_tail

struct ClientRecord* clients_tail
static

Tail of DLL of clients we consult.

Definition at line 231 of file gnunet-service-dns.c.

Referenced by client_connect_cb(), and client_disconnect_cb().

◆ requests

struct RequestRecord requests[UINT16_MAX+1]
static

Array of all open requests.

Definition at line 231 of file gnunet-service-dns.c.

Referenced by cleanup_task(), client_disconnect_cb(), handle_client_response(), process_dns_result(), and process_helper_messages().

◆ request_id_gen

uint64_t request_id_gen
static

Generator for unique request IDs.

Definition at line 241 of file gnunet-service-dns.c.

Referenced by process_helper_messages().

◆ dnsstub

struct GNUNET_DNSSTUB_Context* dnsstub
static

Handle to the DNS Stub resolver.

Definition at line 246 of file gnunet-service-dns.c.

Referenced by cleanup_task(), next_phase(), and run().