GNUnet 0.22.2
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_protocols.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 (GNUNET_OS_project_data_gnunet(), "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 reuse 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 49 of file gnunet-service-dns.c.

◆ LOG

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

Generic logging shorthand.

Definition at line 55 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 62 of file gnunet-service-dns.c.

63{
67 RP_INIT,
68
74
80
85
92
98
102 RP_DROP
103};
@ 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 252 of file gnunet-service-dns.c.

253{
254 GNUNET_free (rr->payload);
255 rr->payload = NULL;
256 rr->payload_length = 0;
259 0);
260}
#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 269 of file gnunet-service-dns.c.

270{
271 if (NULL != hijacker)
272 {
274 hijacker = NULL;
275 }
276 for (unsigned int i = 0; i < 8; i++)
278 for (unsigned int i = 0; i <= UINT16_MAX; i++)
279 cleanup_rr (&requests[i]);
280 if (NULL != stats)
281 {
283 GNUNET_NO);
284 stats = NULL;
285 }
286 if (NULL != dnsstub)
287 {
289 dnsstub = NULL;
290 }
291}
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 300 of file gnunet-service-dns.c.

301{
302 struct GNUNET_MessageHeader *hdr;
303 size_t reply_len;
304 uint16_t source_port;
305 uint16_t destination_port;
306
309 0);
310 if (RP_RESPONSE_MONITOR != rr->phase)
311 {
312 /* no response, drop */
314 "Got no response for request %llu, dropping\n",
315 (unsigned long long) rr->request_id);
316 cleanup_rr (rr);
317 return;
318 }
319
321 "Transmitting response for request %llu\n",
322 (unsigned long long) rr->request_id);
323 /* send response via hijacker */
324 reply_len = sizeof(struct GNUNET_MessageHeader);
325 reply_len += sizeof(struct GNUNET_TUN_Layer2PacketHeader);
326 switch (rr->src_addr.ss_family)
327 {
328 case AF_INET:
329 reply_len += sizeof(struct GNUNET_TUN_IPv4Header);
330 break;
331
332 case AF_INET6:
333 reply_len += sizeof(struct GNUNET_TUN_IPv6Header);
334 break;
335
336 default:
337 GNUNET_break (0);
338 cleanup_rr (rr);
339 return;
340 }
341 reply_len += sizeof(struct GNUNET_TUN_UdpHeader);
342 reply_len += rr->payload_length;
343 if (reply_len >= GNUNET_MAX_MESSAGE_SIZE)
344 {
345 /* response too big, drop */
346 GNUNET_break (0); /* how can this be? */
347 cleanup_rr (rr);
348 return;
349 }
350 {
351 char buf[reply_len] GNUNET_ALIGN;
352 size_t off;
353 struct GNUNET_TUN_IPv4Header ip4;
354 struct GNUNET_TUN_IPv6Header ip6;
355
356 /* first, GNUnet message header */
357 hdr = (struct GNUNET_MessageHeader*) buf;
359 hdr->size = htons ((uint16_t) reply_len);
360 off = sizeof(struct GNUNET_MessageHeader);
361
362 /* first, TUN header */
363 {
365
366 tun.flags = htons (0);
367 if (rr->src_addr.ss_family == AF_INET)
368 tun.proto = htons (ETH_P_IPV4);
369 else
370 tun.proto = htons (ETH_P_IPV6);
371 GNUNET_memcpy (&buf[off],
372 &tun,
373 sizeof(struct GNUNET_TUN_Layer2PacketHeader));
374 off += sizeof(struct GNUNET_TUN_Layer2PacketHeader);
375 }
376
377 /* now IP header */
378 switch (rr->src_addr.ss_family)
379 {
380 case AF_INET:
381 {
382 struct sockaddr_in *src = (struct sockaddr_in *) &rr->src_addr;
383 struct sockaddr_in *dst = (struct sockaddr_in *) &rr->dst_addr;
384
385 source_port = dst->sin_port;
386 destination_port = src->sin_port;
388 IPPROTO_UDP,
389 reply_len - off - sizeof(struct
391 &dst->sin_addr,
392 &src->sin_addr);
393 GNUNET_memcpy (&buf[off],
394 &ip4,
395 sizeof(ip4));
396 off += sizeof(ip4);
397 }
398 break;
399
400 case AF_INET6:
401 {
402 struct sockaddr_in6 *src = (struct sockaddr_in6 *) &rr->src_addr;
403 struct sockaddr_in6 *dst = (struct sockaddr_in6 *) &rr->dst_addr;
404
405 source_port = dst->sin6_port;
406 destination_port = src->sin6_port;
408 IPPROTO_UDP,
409 reply_len - off - sizeof(struct
411 &dst->sin6_addr,
412 &src->sin6_addr);
413 GNUNET_memcpy (&buf[off],
414 &ip6,
415 sizeof(ip6));
416 off += sizeof(ip6);
417 }
418 break;
419
420 default:
421 GNUNET_assert (0);
422 }
423
424 /* now UDP header */
425 {
427
428 udp.source_port = source_port;
429 udp.destination_port = destination_port;
430 udp.len = htons (reply_len - off);
431 if (AF_INET == rr->src_addr.ss_family)
433 &udp,
434 rr->payload,
435 rr->payload_length);
436 else
438 &udp,
439 rr->payload,
440 rr->payload_length);
441 GNUNET_memcpy (&buf[off],
442 &udp,
443 sizeof(udp));
444 off += sizeof(udp);
445 }
446
447 /* now DNS payload */
448 {
449 GNUNET_memcpy (&buf[off], rr->payload, rr->payload_length);
450 off += rr->payload_length;
451 }
452 /* final checks & sending */
453 GNUNET_assert (off == reply_len);
455 hdr,
457 NULL, NULL);
460 "# DNS requests answered via TUN interface"),
461 1, GNUNET_NO);
462 }
463 /* clean up, we're done */
464 cleanup_rr (rr);
465}
#define gettext_noop(String)
Definition: gettext.h:74
#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, bool can_drop, GNUNET_HELPER_Continuation cont, void *cont_cls)
Send an message to the helper.
Definition: helper.c:615
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
#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:115
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:193
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:80
#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:224
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 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 476 of file gnunet-service-dns.c.

478{
479 struct GNUNET_MQ_Envelope *env;
480 struct GNUNET_DNS_Request *req;
481
482 if (sizeof(struct GNUNET_DNS_Request) + rr->payload_length >=
484 {
485 GNUNET_break (0);
486 cleanup_rr (rr);
487 return;
488 }
490 "Sending information about request %llu to local client\n",
491 (unsigned long long) rr->request_id);
493 rr->payload_length,
495 req->reserved = htonl (0);
496 req->request_id = rr->request_id;
497 GNUNET_memcpy (&req[1],
498 rr->payload,
499 rr->payload_length);
500 GNUNET_MQ_send (cr->mq,
501 env);
502}
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:305
#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:61
#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 732 of file gnunet-service-dns.c.

735{
736 struct RequestRecord *rr;
737
739 "Processing DNS result from stub resolver\n");
740 GNUNET_assert (NULL == cls);
741 if (NULL == dns)
742 return; /* ignore */
743
744 rr = &requests[dns->id];
745 if (rr->phase != RP_INTERNET_DNS)
746 {
747 /* unexpected / bogus reply */
750 "# External DNS response discarded (no matching request)"),
751 1, GNUNET_NO);
753 "Received DNS reply that does not match any pending request. Dropping.\n");
754 return;
755 }
757 "Got a response from the stub resolver for DNS request %llu intercepted locally!\n",
758 (unsigned long long) rr->request_id);
759 GNUNET_free (rr->payload);
760 rr->payload = GNUNET_malloc (r);
762 dns,
763 r);
764 rr->payload_length = r;
765 next_phase (rr);
766}
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 526 of file gnunet-service-dns.c.

527{
528 struct ClientRecord *cr;
529 int nz;
530
531 if (rr->phase == RP_DROP)
532 {
533 cleanup_rr (rr);
534 return;
535 }
536 nz = -1;
537 for (unsigned int j = 0; j < rr->client_wait_list_length; j++)
538 {
539 if (NULL != rr->client_wait_list[j])
540 {
541 nz = (int) j;
542 break;
543 }
544 }
545 if (-1 != nz)
546 {
548 rr->client_wait_list[nz]);
549 return;
550 }
551 /* done with current phase, advance! */
553 "Request %llu now in phase %d\n",
554 (unsigned long long) rr->request_id,
555 rr->phase);
556 switch (rr->phase)
557 {
558 case RP_INIT:
560 for (cr = clients_head; NULL != cr; cr = cr->next)
561 {
562 if (0 != (cr->flags & GNUNET_DNS_FLAG_REQUEST_MONITOR))
565 cr);
566 }
567 next_phase (rr);
568 return;
569
571 rr->phase = RP_QUERY;
572 for (cr = clients_head; NULL != cr; cr = cr->next)
573 {
574 if (0 != (cr->flags & GNUNET_DNS_FLAG_PRE_RESOLUTION))
577 cr);
578 }
579 next_phase (rr);
580 return;
581
582 case RP_QUERY:
583#if 0
584 /* TODO: optionally, use this to forward DNS requests to the
585 * original* DNS server instead of the one we have configured...
586 (but then we need to create a fresh dnsstub for each request
587 * and* manage the timeout) */
588 switch (rr->dst_addr.ss_family)
589 {
590 case AF_INET:
591 salen = sizeof(struct sockaddr_in);
592 sa = (const struct sockaddr *) &rr->dst_addr;
593 break;
594
595 case AF_INET6:
596 salen = sizeof(struct sockaddr_in6);
597 sa = (const struct sockaddr *) &rr->dst_addr;
598 break;
599
600 default:
601 GNUNET_assert (0);
602 }
603#endif
606 rr->payload,
607 rr->payload_length,
609 NULL);
610 if (NULL == rr->rs)
611 {
614 "# DNS exit failed (failed to open socket)"),
615 1,
616 GNUNET_NO);
617 cleanup_rr (rr);
618 return;
619 }
620 return;
621
622 case RP_INTERNET_DNS:
623 rr->phase = RP_MODIFY;
624 for (cr = clients_head; NULL != cr; cr = cr->next)
625 {
626 if (0 != (cr->flags & GNUNET_DNS_FLAG_POST_RESOLUTION))
629 cr);
630 }
631 next_phase (rr);
632 return;
633
634 case RP_MODIFY:
636 for (cr = clients_head; NULL != cr; cr = cr->next)
637 {
641 cr);
642 }
643 next_phase (rr);
644 return;
645
647 request_done (rr);
648 break;
649
650 case RP_DROP:
651 cleanup_rr (rr);
652 break;
653
654 default:
655 GNUNET_break (0);
656 cleanup_rr (rr);
657 break;
658 }
659}
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 671 of file gnunet-service-dns.c.

674{
675 struct ClientRecord *cr = cls;
676
677 cr = GNUNET_new (struct ClientRecord);
678 cr->client = client;
679 cr->mq = mq;
682 cr);
683 return cr;
684}
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 695 of file gnunet-service-dns.c.

698{
699 struct ClientRecord *cr = app_ctx;
700 struct RequestRecord *rr;
701
704 cr);
705 for (unsigned int i = 0; i < UINT16_MAX; i++)
706 {
707 rr = &requests[i];
708 if (0 == rr->client_wait_list_length)
709 continue; /* not in use */
710 for (unsigned int j = 0; j < rr->client_wait_list_length; j++)
711 {
712 if (rr->client_wait_list[j] == cr)
713 {
714 rr->client_wait_list[j] = NULL;
715 next_phase (rr);
716 }
717 }
718 }
719 GNUNET_free (cr);
720}
#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 776 of file gnunet-service-dns.c.

778{
779 struct ClientRecord *cr = cls;
780
781 cr->flags = ntohl (reg->flags);
783}
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2389
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 794 of file gnunet-service-dns.c.

796{
797 return GNUNET_OK; /* any payload is acceptable */
798}
@ 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 808 of file gnunet-service-dns.c.

810{
811 struct ClientRecord *cr = cls;
812 struct RequestRecord *rr;
813 uint16_t msize;
814 uint16_t off;
815
816 msize = ntohs (resp->header.size);
817 off = (uint16_t) resp->request_id;
818 rr = &requests[off];
820 "Received DNS response with ID %llu from local client!\n",
821 (unsigned long long) resp->request_id);
822 if (rr->request_id != resp->request_id)
823 {
826 "# Client response discarded (no matching request)"),
827 1,
828 GNUNET_NO);
830 return;
831 }
832 for (unsigned int i = 0; i < rr->client_wait_list_length; i++)
833 {
834 if (NULL == rr->client_wait_list[i])
835 continue;
836 if (rr->client_wait_list[i] != cr)
837 continue;
838 rr->client_wait_list[i] = NULL;
839 switch (ntohl (resp->drop_flag))
840 {
841 case 0: /* drop */
842 rr->phase = RP_DROP;
843 break;
844
845 case 1: /* no change */
846 break;
847
848 case 2: /* update */
849 msize -= sizeof(struct GNUNET_DNS_Response);
850 if ((sizeof(struct GNUNET_TUN_DnsHeader) > msize) ||
851 (RP_REQUEST_MONITOR == rr->phase) ||
852 (RP_RESPONSE_MONITOR == rr->phase))
853 {
854 GNUNET_break (0);
856 next_phase (rr);
857 return;
858 }
859 GNUNET_free (rr->payload);
861 "Changing DNS reply according to client specifications\n");
862 rr->payload = GNUNET_malloc (msize);
863 rr->payload_length = msize;
864 GNUNET_memcpy (rr->payload, &resp[1], msize);
865 if (rr->phase == RP_QUERY)
866 {
867 /* clear wait list, we're moving to MODIFY phase next */
870 0);
871 }
872 /* if query changed to answer, move past DNS resolution phase... */
873 if ((RP_QUERY == rr->phase) &&
874 (rr->payload_length > sizeof(struct GNUNET_TUN_DnsHeader)) &&
875 ( ((struct GNUNET_TUN_DnsFlags*) &(((struct
877 payload)->flags))->
878 query_or_response == 1) )
879 {
883 0);
884 }
885 break;
886 }
887 next_phase (rr);
889 return;
890 }
891 /* odd, client was not on our list for the request, that ought
892 to be an error */
893 GNUNET_break (0);
895}
static unsigned long long payload
How much data are we currently storing in the database?
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2418
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
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 906 of file gnunet-service-dns.c.

908{
909 uint16_t msize;
910 const struct GNUNET_TUN_Layer2PacketHeader *tun;
911 const struct GNUNET_TUN_IPv4Header *ip4;
912 const struct GNUNET_TUN_IPv6Header *ip6;
913 const struct GNUNET_TUN_UdpHeader *udp;
914 const struct GNUNET_TUN_DnsHeader *dns;
915 struct RequestRecord *rr;
916 struct sockaddr_in *srca4;
917 struct sockaddr_in6 *srca6;
918 struct sockaddr_in *dsta4;
919 struct sockaddr_in6 *dsta6;
920
922 "Intercepted message via DNS hijacker\n");
923 msize = ntohs (message->size);
924 if (msize < sizeof(struct GNUNET_MessageHeader) + sizeof(struct
926 + sizeof(struct GNUNET_TUN_IPv4Header))
927 {
928 /* non-IP packet received on TUN!? */
929 GNUNET_break (0);
930 return GNUNET_OK;
931 }
932 msize -= sizeof(struct GNUNET_MessageHeader);
933 tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
934 msize -= sizeof(struct GNUNET_TUN_Layer2PacketHeader);
935 switch (ntohs (tun->proto))
936 {
937 case ETH_P_IPV4:
938 ip4 = (const struct GNUNET_TUN_IPv4Header *) &tun[1];
939 ip6 = NULL; /* make compiler happy */
940 if ((msize < sizeof(struct GNUNET_TUN_IPv4Header)) ||
941 (ip4->version != 4) ||
942 (ip4->header_length != sizeof(struct GNUNET_TUN_IPv4Header) / 4) ||
943 (ntohs (ip4->total_length) != msize) ||
944 (ip4->protocol != IPPROTO_UDP))
945 {
946 /* non-IP/UDP packet received on TUN (or with options) */
948 _ ("Received malformed IPv4-UDP packet on TUN interface.\n"));
949 return GNUNET_OK;
950 }
951 udp = (const struct GNUNET_TUN_UdpHeader*) &ip4[1];
952 msize -= sizeof(struct GNUNET_TUN_IPv4Header);
953 break;
954
955 case ETH_P_IPV6:
956 ip4 = NULL; /* make compiler happy */
957 ip6 = (const struct GNUNET_TUN_IPv6Header *) &tun[1];
958 if ((msize < sizeof(struct GNUNET_TUN_IPv6Header)) ||
959 (ip6->version != 6) ||
960 (ntohs (ip6->payload_length) != msize - sizeof(struct
962 ||
963 (ip6->next_header != IPPROTO_UDP))
964 {
965 /* non-IP/UDP packet received on TUN (or with extensions) */
967 _ ("Received malformed IPv6-UDP packet on TUN interface.\n"));
968 return GNUNET_OK;
969 }
970 udp = (const struct GNUNET_TUN_UdpHeader *) &ip6[1];
971 msize -= sizeof(struct GNUNET_TUN_IPv6Header);
972 break;
973
974 default:
975 /* non-IP packet received on TUN!? */
977 _ (
978 "Got non-IP packet with %u bytes and protocol %u from TUN\n"),
979 (unsigned int) msize,
980 ntohs (tun->proto));
981 return GNUNET_OK;
982 }
983 if ((msize <= sizeof(struct GNUNET_TUN_UdpHeader) + sizeof(struct
985 ||
986 (DNS_PORT != ntohs (udp->destination_port)))
987 {
988 /* non-DNS packet received on TUN, ignore */
990 _ ("DNS interceptor got non-DNS packet (dropped)\n"));
993 "# Non-DNS UDP packet received via TUN interface"),
994 1, GNUNET_NO);
995 return GNUNET_OK;
996 }
997 msize -= sizeof(struct GNUNET_TUN_UdpHeader);
998 dns = (const struct GNUNET_TUN_DnsHeader*) &udp[1];
999 rr = &requests[dns->id];
1000
1001 /* clean up from previous request */
1002 GNUNET_free (rr->payload);
1003 rr->payload = NULL;
1006 0);
1007
1008 /* setup new request */
1009 rr->phase = RP_INIT;
1010 switch (ntohs (tun->proto))
1011 {
1012 case ETH_P_IPV4:
1013 {
1014 srca4 = (struct sockaddr_in*) &rr->src_addr;
1015 dsta4 = (struct sockaddr_in*) &rr->dst_addr;
1016 memset (srca4, 0, sizeof(struct sockaddr_in));
1017 memset (dsta4, 0, sizeof(struct sockaddr_in));
1018 srca4->sin_family = AF_INET;
1019 dsta4->sin_family = AF_INET;
1020 srca4->sin_addr = ip4->source_address;
1021 dsta4->sin_addr = ip4->destination_address;
1022 srca4->sin_port = udp->source_port;
1023 dsta4->sin_port = udp->destination_port;
1024#if HAVE_SOCKADDR_IN_SIN_LEN
1025 srca4->sin_len = sizeof(struct sockaddr_in);
1026 dsta4->sin_len = sizeof(struct sockaddr_in);
1027#endif
1028 }
1029 break;
1030
1031 case ETH_P_IPV6:
1032 {
1033 srca6 = (struct sockaddr_in6*) &rr->src_addr;
1034 dsta6 = (struct sockaddr_in6*) &rr->dst_addr;
1035 memset (srca6, 0, sizeof(struct sockaddr_in6));
1036 memset (dsta6, 0, sizeof(struct sockaddr_in6));
1037 srca6->sin6_family = AF_INET6;
1038 dsta6->sin6_family = AF_INET6;
1039 srca6->sin6_addr = ip6->source_address;
1040 dsta6->sin6_addr = ip6->destination_address;
1041 srca6->sin6_port = udp->source_port;
1042 dsta6->sin6_port = udp->destination_port;
1043#if HAVE_SOCKADDR_IN_SIN_LEN
1044 srca6->sin6_len = sizeof(struct sockaddr_in6);
1045 dsta6->sin6_len = sizeof(struct sockaddr_in6);
1046#endif
1047 }
1048 break;
1049
1050 default:
1051 GNUNET_assert (0);
1052 }
1053 rr->payload = GNUNET_malloc (msize);
1054 rr->payload_length = msize;
1055 GNUNET_memcpy (rr->payload, dns, msize);
1056 rr->request_id = dns->id | (request_id_gen << 16);
1059 "Creating new DNS request %llu\n",
1060 (unsigned long long) rr->request_id);
1062 gettext_noop (
1063 "# DNS requests received via TUN interface"),
1064 1, GNUNET_NO);
1065 /* start request processing state machine */
1066 next_phase (rr);
1067 return GNUNET_OK;
1068}
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:179
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 1077 of file gnunet-service-dns.c.

1080{
1081 char *ifc_name;
1082 char *ipv4addr;
1083 char *ipv4mask;
1084 char *ipv6addr;
1085 char *ipv6prefix;
1086 char *dns_exit;
1087 char *binary;
1088 int nortsetup;
1089
1090 cfg = cfg_;
1093 cls);
1095 /* TODO: support multiple DNS_EXIT servers being configured */
1096 /* TODO: see above TODO on using DNS server from original packet.
1097 Not sure which is best... */
1098 dns_exit = NULL;
1099 if ((GNUNET_OK !=
1101 "dns",
1102 "DNS_EXIT",
1103 &dns_exit)) ||
1104 (GNUNET_OK !=
1106 dns_exit)))
1107 {
1109 "dns",
1110 "DNS_EXIT",
1111 _ ("need a valid IPv4 or IPv6 address\n"));
1112 GNUNET_free (dns_exit);
1113 }
1115 cfg,
1116 "gnunet-helper-dns");
1117
1118 if (GNUNET_YES !=
1120 GNUNET_YES,
1121 NULL)) // TODO: once we have a windows-testcase, add test parameters here
1122 {
1124 _ ("`%s' is not SUID or the path is invalid, "
1125 "will not run DNS interceptor\n"),
1126 binary);
1127 global_ret = 1;
1128 GNUNET_free (binary);
1129 return;
1130 }
1131 GNUNET_free (binary);
1132
1133 helper_argv[0] = GNUNET_strdup ("gnunet-dns");
1134 if (GNUNET_SYSERR ==
1136 "dns",
1137 "IFNAME",
1138 &ifc_name))
1139 {
1141 "No entry 'IFNAME' in configuration!\n");
1142 GNUNET_free (binary);
1144 return;
1145 }
1146 helper_argv[1] = ifc_name;
1147 if ((GNUNET_SYSERR ==
1149 "dns",
1150 "IPV6ADDR",
1151 &ipv6addr)))
1152 {
1154 "No entry 'IPV6ADDR' in configuration!\n");
1155 GNUNET_free (binary);
1157 return;
1158 }
1159 helper_argv[2] = ipv6addr;
1160 if (GNUNET_SYSERR ==
1162 "dns",
1163 "IPV6PREFIX",
1164 &ipv6prefix))
1165 {
1167 "No entry 'IPV6PREFIX' in configuration!\n");
1168 GNUNET_free (binary);
1170 return;
1171 }
1173
1174 if (GNUNET_SYSERR ==
1176 "dns",
1177 "IPV4ADDR",
1178 &ipv4addr))
1179 {
1181 "No entry 'IPV4ADDR' in configuration!\n");
1182 GNUNET_free (binary);
1184 return;
1185 }
1186 helper_argv[4] = ipv4addr;
1187 if (GNUNET_SYSERR ==
1188 GNUNET_CONFIGURATION_get_value_string (cfg, "dns", "IPV4MASK",
1189 &ipv4mask))
1190 {
1192 "No entry 'IPV4MASK' in configuration!\n");
1193 GNUNET_free (binary);
1195 return;
1196 }
1197 helper_argv[5] = ipv4mask;
1198
1199 nortsetup = GNUNET_CONFIGURATION_get_value_yesno (cfg, "dns",
1200 "SKIP_ROUTING_SETUP");
1201 if (GNUNET_YES == nortsetup)
1202 helper_argv[6] = GNUNET_strdup ("1");
1203 else
1204 helper_argv[6] = GNUNET_strdup ("0");
1205
1206 helper_argv[7] = NULL;
1208 GNUNET_NO,
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(const struct GNUNET_OS_ProjectData *pd, 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_.
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_gnunet(void)
Return default project data used by 'libgnunetutil' for GNUnet.
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.
char * GNUNET_OS_get_suid_binary_path(const struct GNUNET_OS_ProjectData *pd, 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 ...
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:1339
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_OS_project_data_gnunet(), 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 ( GNUNET_OS_project_data_gnunet()  ,
"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 198 of file gnunet-service-dns.c.

Referenced by run().

◆ cfg

const struct GNUNET_CONFIGURATION_Handle* cfg
static

The configuration to use.

Definition at line 203 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 213 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 218 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 223 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 228 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 233 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 238 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 243 of file gnunet-service-dns.c.

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