GNUnet  0.10.x
Data Structures | Functions | Variables
gnunet-service-gns_interceptor.c File Reference

GNUnet GNS interceptor logic. More...

#include "platform.h"
#include "gnunet_util_lib.h"
#include "gnunet_dns_service.h"
#include "gnunet_dnsparser_lib.h"
#include "gnunet-service-gns.h"
#include "gnunet-service-gns_resolver.h"
#include "gnunet-service-gns_interceptor.h"
#include "gns.h"
Include dependency graph for gnunet-service-gns_interceptor.c:

Go to the source code of this file.

Data Structures

struct  InterceptLookupHandle
 Handle to a DNS intercepted reslution request. More...
 

Functions

static void reply_to_dns (void *cls, uint32_t rd_count, const struct GNUNET_GNSRECORD_Data *rd)
 Reply to dns request with the result from our lookup. More...
 
static void handle_dns_request (void *cls, struct GNUNET_DNS_RequestHandle *rh, size_t request_length, const char *request)
 The DNS request handler. More...
 
int GNS_interceptor_init (const struct GNUNET_CONFIGURATION_Handle *c)
 Initialized the interceptor. More...
 
void GNS_interceptor_done ()
 Disconnect from interceptor. More...
 

Variables

static struct GNUNET_DNS_Handledns_handle
 Our handle to the DNS handler library. More...
 
static struct InterceptLookupHandleilh_head
 Head of the DLL. More...
 
static struct InterceptLookupHandleilh_tail
 Tail of the DLL. More...
 

Detailed Description

GNUnet GNS interceptor logic.

Author
Martin Schanzenbach
Christian Grothoff

Definition in file gnunet-service-gns_interceptor.c.

Function Documentation

◆ reply_to_dns()

static void reply_to_dns ( void *  cls,
uint32_t  rd_count,
const struct GNUNET_GNSRECORD_Data rd 
)
static

Reply to dns request with the result from our lookup.

Parameters
clsthe closure to the request (an InterceptLookupHandle)
rd_countthe number of records to return
rdthe record data

Definition at line 92 of file gnunet-service-gns_interceptor.c.

References _, GNUNET_TIME_Absolute::abs_value_us, GNUNET_DNSPARSER_Packet::additional_records, GNUNET_DNSPARSER_Packet::answers, GNUNET_TUN_DnsFlags::authoritative_answer, buf, data, GNUNET_DNSPARSER_RawRecord::data, GNUNET_DNSPARSER_Record::data, GNUNET_DNSPARSER_RawRecord::data_len, data_size, GNUNET_GNSRECORD_Data::data_size, GNUNET_DNSPARSER_Record::dns_traffic_class, GNUNET_GNSRECORD_Data::expiration_time, GNUNET_DNSPARSER_Record::expiration_time, GNUNET_DNSPARSER_Packet::flags, GNUNET_break, GNUNET_break_op, GNUNET_CONTAINER_DLL_remove, GNUNET_DNS_request_answer(), GNUNET_DNSPARSER_free_packet(), GNUNET_DNSPARSER_pack(), GNUNET_DNSPARSER_parse_mx(), GNUNET_DNSPARSER_parse_name(), GNUNET_DNSPARSER_parse_soa(), GNUNET_DNSPARSER_TYPE_CNAME, GNUNET_DNSPARSER_TYPE_MX, GNUNET_DNSPARSER_TYPE_NS, GNUNET_DNSPARSER_TYPE_PTR, GNUNET_DNSPARSER_TYPE_SOA, GNUNET_DNSPARSER_TYPE_SRV, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION, GNUNET_log, GNUNET_NO, GNUNET_OK, GNUNET_TUN_DNS_CLASS_INTERNET, GNUNET_TUN_DNS_RETURN_CODE_NAME_ERROR, GNUNET_TUN_DNS_RETURN_CODE_NO_ERROR, GNUNET_DNSPARSER_Record::hostname, len, GNUNET_DNSPARSER_Record::mx, GNUNET_DNSPARSER_Query::name, GNUNET_DNSPARSER_Record::name, GNUNET_DNSPARSER_Packet::num_additional_records, GNUNET_DNSPARSER_Packet::num_answers, InterceptLookupHandle::packet, GNUNET_DNSPARSER_Packet::queries, GNUNET_TUN_DnsFlags::query_or_response, GNUNET_DNSPARSER_Record::raw, GNUNET_GNSRECORD_Data::record_type, InterceptLookupHandle::request_handle, ret, GNUNET_TUN_DnsFlags::return_code, GNUNET_DNSPARSER_Record::soa, GNUNET_DNSPARSER_Query::type, and GNUNET_DNSPARSER_Record::type.

Referenced by handle_dns_request().

94 {
95  struct InterceptLookupHandle *ilh = cls;
96  struct GNUNET_DNSPARSER_Packet *packet = ilh->packet;
97  struct GNUNET_DNSPARSER_Query *query = &packet->queries[0];
98  uint32_t i;
99  size_t len;
100  int ret;
101  char *buf;
102  unsigned int num_answers;
103  unsigned int skip_answers;
104  unsigned int skip_additional;
105  size_t off = 0;
106 
107  /* Put records in the DNS packet */
108  num_answers = 0;
109  for (i = 0; i < rd_count; i++)
110  if (rd[i].record_type == query->type)
111  num_answers++;
112  skip_answers = 0;
113  skip_additional = 0;
114 
115  {
116  struct GNUNET_DNSPARSER_Record answer_records[num_answers];
117  struct GNUNET_DNSPARSER_Record additional_records[rd_count - num_answers];
118 
119  packet->answers = answer_records;
120  packet->additional_records = additional_records;
121  /* FIXME: need to handle #GNUNET_GNSRECORD_RF_SHADOW_RECORD option
122  (by ignoring records where this flag is set if there is any
123  other record of that type in the result set) */
124  for (i = 0; i < rd_count; i++)
125  {
126  if (rd[i].record_type == query->type)
127  {
128  answer_records[i - skip_answers].name = query->name;
129  answer_records[i - skip_answers].type = rd[i].record_type;
130  switch (rd[i].record_type)
131  {
135  answer_records[i - skip_answers].data.hostname
137  rd[i].data_size,
138  &off);
139  if ((off != rd[i].data_size) ||
140  (NULL == answer_records[i].data.hostname))
141  {
142  GNUNET_break_op(0);
143  skip_answers++;
144  }
145  break;
146 
148  answer_records[i - skip_answers].data.soa
150  rd[i].data_size,
151  &off);
152  if ((off != rd[i].data_size) ||
153  (NULL == answer_records[i].data.soa))
154  {
155  GNUNET_break_op(0);
156  skip_answers++;
157  }
158  break;
159 
161  /* FIXME: SRV is not yet supported */
162  skip_answers++;
163  break;
164 
166  answer_records[i - skip_answers].data.mx
168  rd[i].data_size,
169  &off);
170  if ((off != rd[i].data_size) ||
171  (NULL == answer_records[i].data.hostname))
172  {
173  GNUNET_break_op(0);
174  skip_answers++;
175  }
176  break;
177 
178  default:
179  answer_records[i - skip_answers].data.raw.data_len = rd[i].data_size;
180  answer_records[i - skip_answers].data.raw.data = (char*)rd[i].data;
181  break;
182  }
183  GNUNET_break(0 == (rd[i - skip_answers].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION));
184  answer_records[i - skip_answers].expiration_time.abs_value_us = rd[i].expiration_time;
185  answer_records[i - skip_answers].dns_traffic_class = GNUNET_TUN_DNS_CLASS_INTERNET;
186  }
187  else
188  {
189  additional_records[i - skip_additional].name = query->name;
190  additional_records[i - skip_additional].type = rd[i].record_type;
191  switch (rd[i].record_type)
192  {
196  additional_records[i - skip_additional].data.hostname
198  rd[i].data_size,
199  &off);
200  if ((off != rd[i].data_size) ||
201  (NULL == additional_records[i].data.hostname))
202  {
203  GNUNET_break_op(0);
204  skip_additional++;
205  }
206  break;
207 
209  additional_records[i - skip_additional].data.soa
211  rd[i].data_size,
212  &off);
213  if ((off != rd[i].data_size) ||
214  (NULL == additional_records[i].data.hostname))
215  {
216  GNUNET_break_op(0);
217  skip_additional++;
218  }
219  break;
220 
222  additional_records[i - skip_additional].data.mx
224  rd[i].data_size,
225  &off);
226  if ((off != rd[i].data_size) ||
227  (NULL == additional_records[i].data.hostname))
228  {
229  GNUNET_break_op(0);
230  skip_additional++;
231  }
232  break;
233 
235  /* FIXME: SRV is not yet supported */
236  skip_answers++;
237  break;
238 
239  default:
240  additional_records[i - skip_additional].data.raw.data_len = rd[i].data_size;
241  additional_records[i - skip_additional].data.raw.data = (char*)rd[i].data;
242  break;
243  }
244  GNUNET_break(0 == (rd[i - skip_additional].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION));
245  additional_records[i - skip_additional].expiration_time.abs_value_us = rd[i].expiration_time;
246  additional_records[i - skip_additional].dns_traffic_class = GNUNET_TUN_DNS_CLASS_INTERNET;
247  }
248  }
249  packet->num_answers = num_answers - skip_answers;
250  packet->num_additional_records = rd_count - num_answers - skip_additional;
251  packet->flags.authoritative_answer = 1;
252  if (NULL == rd)
254  else
256  packet->flags.query_or_response = 1;
257  ret = GNUNET_DNSPARSER_pack(packet,
258  1024, /* maximum allowed size for DNS reply */
259  &buf,
260  &len);
261  if (GNUNET_OK != ret)
262  {
264  _("Error converting GNS response to DNS response!\n"));
265  if (GNUNET_NO == ret)
266  GNUNET_free(buf);
267  }
268  else
269  {
271  len,
272  buf);
273  GNUNET_free(buf);
274  }
275  packet->num_answers = 0;
276  packet->answers = NULL;
277  packet->num_additional_records = 0;
278  packet->additional_records = NULL;
280  }
282  GNUNET_free(ilh);
283 }
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
struct GNUNET_DNSPARSER_Record * answers
Array of all answers in the packet, must contain "num_answers" entries.
uint16_t type
See GNUNET_DNSPARSER_TYPE_*.
char * GNUNET_DNSPARSER_parse_name(const char *udp_payload, size_t udp_payload_length, size_t *off)
Parse name inside of a DNS query or record.
Definition: dnsparser.c:334
struct GNUNET_DNSPARSER_Packet * packet
the dns parser packet received
#define GNUNET_DNSPARSER_TYPE_CNAME
static struct InterceptLookupHandle * ilh_tail
Tail of the DLL.
unsigned int return_code
See GNUNET_TUN_DNS_RETURN_CODE_ defines.
int GNUNET_DNSPARSER_pack(const struct GNUNET_DNSPARSER_Packet *p, uint16_t max, char **buf, size_t *buf_length)
Given a DNS packet p, generate the corresponding UDP payload.
Definition: dnsparser.c:1256
Handle to a DNS intercepted reslution request.
void GNUNET_DNSPARSER_free_packet(struct GNUNET_DNSPARSER_Packet *p)
Free memory taken by a packet.
Definition: dnsparser.c:853
#define GNUNET_NO
Definition: gnunet_common.h:78
struct GNUNET_DNSPARSER_SoaRecord * GNUNET_DNSPARSER_parse_soa(const char *udp_payload, size_t udp_payload_length, size_t *off)
Parse a DNS SOA record.
Definition: dnsparser.c:391
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
size_t data_size
Number of bytes in data.
struct GNUNET_DNSPARSER_Record * additional_records
Array of all additional answers in the packet, must contain "num_additional_records" entries...
static int ret
Final status code.
Definition: gnunet-arm.c:89
#define GNUNET_DNSPARSER_TYPE_MX
unsigned int num_answers
Number of answers in the packet, should be 0 for queries.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
unsigned int authoritative_answer
Set to 1 if this is an authoritative answer.
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
#define GNUNET_DNSPARSER_TYPE_PTR
unsigned int query_or_response
query:0, response:1
#define GNUNET_DNSPARSER_TYPE_SOA
char * name
Name of the record that the query is for (0-terminated).
unsigned int num_additional_records
Number of additional records in the packet, should be 0 for queries.
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
uint64_t expiration_time
Expiration time for the DNS record.
static struct InterceptLookupHandle * ilh_head
Head of the DLL.
#define GNUNET_TUN_DNS_RETURN_CODE_NO_ERROR
RFC 1035 codes.
static char buf[2048]
A DNS response record.
struct GNUNET_DNSPARSER_Query * queries
Array of all queries in the packet, must contain "num_queries" entries.
struct GNUNET_DNSPARSER_MxRecord * GNUNET_DNSPARSER_parse_mx(const char *udp_payload, size_t udp_payload_length, size_t *off)
Parse a DNS MX record.
Definition: dnsparser.c:436
struct GNUNET_DNS_RequestHandle * request_handle
the request handle to reply to
#define GNUNET_TUN_DNS_CLASS_INTERNET
A few common DNS classes (ok, only one is common, but I list a couple more to make it clear what we&#39;r...
void GNUNET_DNS_request_answer(struct GNUNET_DNS_RequestHandle *rh, uint16_t reply_length, const char *reply)
If a GNUNET_DNS_RequestHandler calls this function, the request is supposed to be answered with the d...
Definition: dns_api.c:301
#define GNUNET_TUN_DNS_RETURN_CODE_NAME_ERROR
uint32_t record_type
Type of the GNS/DNS record.
#define GNUNET_DNSPARSER_TYPE_NS
Easy-to-process, parsed version of a DNS packet.
#define GNUNET_log(kind,...)
char * name
Name of the record that the query is for (0-terminated).
This flag is currently unused; former RF_PENDING flag.
struct GNUNET_TUN_DnsFlags flags
Bitfield of DNS flags.
#define GNUNET_DNSPARSER_TYPE_SRV
uint32_t data
The data value.
static size_t data_size
Number of bytes in data.
#define GNUNET_free(ptr)
Wrapper around free.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_dns_request()

static void handle_dns_request ( void *  cls,
struct GNUNET_DNS_RequestHandle rh,
size_t  request_length,
const char *  request 
)
static

The DNS request handler.

Called for every incoming DNS request.

Parameters
clsclosure, unused
rhrequest handle to user for reply
request_lengthnumber of bytes in request
requestUDP payload of the DNS request

Definition at line 295 of file gnunet-service-gns_interceptor.c.

References GNS_find_tld(), GNS_get_tld(), GNS_resolver_lookup(), GNUNET_CONTAINER_DLL_insert, GNUNET_DNS_request_forward(), GNUNET_DNSPARSER_free_packet(), GNUNET_DNSPARSER_parse(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, GNUNET_new, GNUNET_NO, GNUNET_YES, InterceptLookupHandle::lookup, GNUNET_DNSPARSER_Query::name, GNUNET_DNSPARSER_Packet::num_queries, p, InterceptLookupHandle::packet, GNUNET_DNSPARSER_Packet::queries, reply_to_dns(), InterceptLookupHandle::request_handle, and GNUNET_DNSPARSER_Query::type.

Referenced by GNS_interceptor_init().

299 {
300  struct GNUNET_DNSPARSER_Packet *p;
301  struct InterceptLookupHandle *ilh;
303 
305  "Hijacked a DNS request. Processing.\n");
306  if (NULL == (p = GNUNET_DNSPARSER_parse(request, request_length)))
307  {
309  "Received malformed DNS packet, leaving it untouched.\n");
312  return;
313  }
314 
315  /* Check TLD and decide if we or legacy dns is responsible */
316  if (1 != p->num_queries)
317  {
319  "Not exactly one query in DNS packet. Forwarding untouched.\n");
322  return;
323  }
324 
325  /* Check for GNS TLDs. */
326  if (GNUNET_YES ==
328  &zone))
329  {
330  /* Start resolution in GNS */
331  ilh = GNUNET_new(struct InterceptLookupHandle);
333  ilh_tail,
334  ilh);
335  ilh->packet = p;
336  ilh->request_handle = rh;
338  p->queries[0].type,
339  p->queries[0].name,
340  GNUNET_NO,
341  &reply_to_dns, ilh);
342  return;
343  }
344  /* This request does not concern us. Forward to real DNS. */
346  "Request for `%s' is forwarded to DNS untouched.\n",
347  p->queries[0].name);
350 }
uint16_t type
See GNUNET_DNSPARSER_TYPE_*.
static struct GNUNET_VPN_RedirectionRequest * request
Opaque redirection request handle.
Definition: gnunet-vpn.c:41
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
struct GNUNET_DNSPARSER_Packet * packet
the dns parser packet received
static struct InterceptLookupHandle * ilh_tail
Tail of the DLL.
const char * GNS_get_tld(const char *name)
Obtain the TLD of the given name.
Handle to a DNS intercepted reslution request.
void GNUNET_DNSPARSER_free_packet(struct GNUNET_DNSPARSER_Packet *p)
Free memory taken by a packet.
Definition: dnsparser.c:853
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_new(type)
Allocate a struct or union of the given type.
static char * zone
Name of the zone we manage.
struct GNS_ResolverHandle * lookup
Handle for the lookup operation.
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-qr.c:59
struct GNUNET_DNSPARSER_Packet * GNUNET_DNSPARSER_parse(const char *udp_payload, size_t udp_payload_length)
Parse a UDP payload of a DNS packet in to a nice struct for further processing and manipulation...
Definition: dnsparser.c:656
static struct InterceptLookupHandle * ilh_head
Head of the DLL.
struct GNUNET_DNSPARSER_Query * queries
Array of all queries in the packet, must contain "num_queries" entries.
struct GNUNET_DNS_RequestHandle * request_handle
the request handle to reply to
struct GNS_ResolverHandle * GNS_resolver_lookup(const struct GNUNET_CRYPTO_EcdsaPublicKey *zone, uint32_t record_type, const char *name, enum GNUNET_GNS_LocalOptions options, GNS_ResultProcessor proc, void *proc_cls)
Lookup of a record in a specific zone calls lookup result processor on result.
void GNUNET_DNS_request_forward(struct GNUNET_DNS_RequestHandle *rh)
If a GNUNET_DNS_RequestHandler calls this function, the request is given to other clients or the glob...
Definition: dns_api.c:242
int GNS_find_tld(const char *tld_str, struct GNUNET_CRYPTO_EcdsaPublicKey *pkey)
Find GNS zone belonging to TLD tld.
Easy-to-process, parsed version of a DNS packet.
Public ECC key (always for Curve25519) encoded in a format suitable for network transmission and ECDS...
#define GNUNET_log(kind,...)
char * name
Name of the record that the query is for (0-terminated).
unsigned int num_queries
Number of queries in the packet.
#define GNUNET_YES
Definition: gnunet_common.h:77
static void reply_to_dns(void *cls, uint32_t rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Reply to dns request with the result from our lookup.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ GNS_interceptor_init()

int GNS_interceptor_init ( const struct GNUNET_CONFIGURATION_Handle c)

Initialized the interceptor.

Initialize DNS interceptor.

Parameters
cthe configuration
Returns
GNUNET_OK on success

Definition at line 360 of file gnunet-service-gns_interceptor.c.

References _, GNUNET_DNS_connect(), GNUNET_DNS_FLAG_PRE_RESOLUTION, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_INFO, GNUNET_log, GNUNET_SYSERR, GNUNET_YES, and handle_dns_request().

Referenced by run().

361 {
363  "DNS hijacking enabled. Connecting to DNS service.\n");
367  NULL);
368  if (NULL == dns_handle)
369  {
371  _("Failed to connect to the DNS service!\n"));
372  return GNUNET_SYSERR;
373  }
374  return GNUNET_YES;
375 }
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
static void handle_dns_request(void *cls, struct GNUNET_DNS_RequestHandle *rh, size_t request_length, const char *request)
The DNS request handler.
static struct GNUNET_DNS_Handle * dns_handle
Our handle to the DNS handler library.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
struct GNUNET_DNS_Handle * GNUNET_DNS_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, enum GNUNET_DNS_Flags flags, GNUNET_DNS_RequestHandler rh, void *rh_cls)
Connect to the service-dns.
Definition: dns_api.c:345
#define GNUNET_log(kind,...)
This client should be called on requests that have not yet been resolved as this client provides a re...
#define GNUNET_YES
Definition: gnunet_common.h:77
Here is the call graph for this function:
Here is the caller graph for this function:

◆ GNS_interceptor_done()

void GNS_interceptor_done ( void  )

Disconnect from interceptor.

Stops the interceptor.

Definition at line 382 of file gnunet-service-gns_interceptor.c.

References GNS_resolver_lookup_cancel(), GNUNET_CONTAINER_DLL_remove, GNUNET_DNS_disconnect(), GNUNET_DNS_request_drop(), GNUNET_DNSPARSER_free_packet(), GNUNET_free, InterceptLookupHandle::lookup, InterceptLookupHandle::packet, and InterceptLookupHandle::request_handle.

Referenced by shutdown_task().

383 {
384  struct InterceptLookupHandle *ilh;
385 
386  while (NULL != (ilh = ilh_head))
387  {
389  ilh_tail,
390  ilh);
394  GNUNET_free(ilh);
395  }
396  if (NULL != dns_handle)
397  {
399  dns_handle = NULL;
400  }
401 }
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
void GNS_resolver_lookup_cancel(struct GNS_ResolverHandle *rh)
Cancel active resolution (i.e.
struct GNUNET_DNSPARSER_Packet * packet
the dns parser packet received
static struct InterceptLookupHandle * ilh_tail
Tail of the DLL.
Handle to a DNS intercepted reslution request.
void GNUNET_DNSPARSER_free_packet(struct GNUNET_DNSPARSER_Packet *p)
Free memory taken by a packet.
Definition: dnsparser.c:853
void GNUNET_DNS_disconnect(struct GNUNET_DNS_Handle *dh)
Disconnect from the DNS service.
Definition: dns_api.c:368
struct GNS_ResolverHandle * lookup
Handle for the lookup operation.
static struct InterceptLookupHandle * ilh_head
Head of the DLL.
static struct GNUNET_DNS_Handle * dns_handle
Our handle to the DNS handler library.
struct GNUNET_DNS_RequestHandle * request_handle
the request handle to reply to
void GNUNET_DNS_request_drop(struct GNUNET_DNS_RequestHandle *rh)
If a GNUNET_DNS_RequestHandler calls this function, the request is to be dropped and no response shou...
Definition: dns_api.c:270
#define GNUNET_free(ptr)
Wrapper around free.
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ dns_handle

struct GNUNET_DNS_Handle* dns_handle
static

Our handle to the DNS handler library.

Definition at line 71 of file gnunet-service-gns_interceptor.c.

◆ ilh_head

struct InterceptLookupHandle* ilh_head
static

Head of the DLL.

Definition at line 76 of file gnunet-service-gns_interceptor.c.

◆ ilh_tail

struct InterceptLookupHandle* ilh_tail
static

Tail of the DLL.

Definition at line 81 of file gnunet-service-gns_interceptor.c.