GNUnet 0.21.1
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
83
88
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:536
@ 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;
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 {
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,
460 NULL, NULL);
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 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:613
#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.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
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 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, GNUNET_MessageHeader::type, 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);
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 */
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);
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
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
609 rr->payload,
610 rr->payload_length,
612 NULL);
613 if (NULL == rr->rs)
614 {
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 {
644 cr);
645 }
646 next_phase (rr);
647 return;
648
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, next_phase(), 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(), next_phase(), 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;
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
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:2408
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 {
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
880 payload)->flags))->
881 query_or_response == 1) )
882 {
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:2489
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"));
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);
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, GNUNET_TUN_IPv6Header::payload_length, RequestRecord::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_;
1096 cls);
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 }
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,
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.
struct GNUNET_DNSSTUB_Context * GNUNET_DNSSTUB_start(unsigned int num_sockets)
Start a DNS stub resolver.
Definition: dnsstub.c:586
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_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:460
@ 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:567
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:1340
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 236 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().