GNUnet 0.22.0
gnunet-service-gns_interceptor.c File Reference

GNUnet GNS interceptor logic. More...

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 resolution request. More...
 

Macros

#define MAX_RECURSION   256
 How deep do we allow recursions to go before we abort? 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)
 Initialize DNS 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.

Macro Definition Documentation

◆ MAX_RECURSION

#define MAX_RECURSION   256

How deep do we allow recursions to go before we abort?

Definition at line 38 of 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 98 of file gnunet-service-gns_interceptor.c.

100{
101 struct InterceptLookupHandle *ilh = cls;
102 struct GNUNET_DNSPARSER_Packet *packet = ilh->packet;
103 struct GNUNET_DNSPARSER_Query *query = &packet->queries[0];
104 uint32_t i;
105 size_t len;
106 int ret;
107 char *buf;
108 unsigned int num_answers;
109 unsigned int skip_answers;
110 unsigned int skip_additional;
111 size_t off = 0;
112
113 /* Put records in the DNS packet */
114 num_answers = 0;
115 for (i = 0; i < rd_count; i++)
116 if (rd[i].record_type == query->type)
117 num_answers++;
118 skip_answers = 0;
119 skip_additional = 0;
120
121 {
122 struct GNUNET_DNSPARSER_Record answer_records[num_answers];
123 struct GNUNET_DNSPARSER_Record additional_records[rd_count - num_answers];
124
125 packet->answers = answer_records;
126 packet->additional_records = additional_records;
127 /* FIXME: need to handle #GNUNET_GNSRECORD_RF_SHADOW_RECORD option
128 (by ignoring records where this flag is set if there is any
129 other record of that type in the result set) */
130 for (i = 0; i < rd_count; i++)
131 {
132 if (rd[i].record_type == query->type)
133 {
134 answer_records[i - skip_answers].name = query->name;
135 answer_records[i - skip_answers].type = rd[i].record_type;
136 switch (rd[i].record_type)
137 {
141 answer_records[i - skip_answers].data.hostname
143 rd[i].data_size,
144 &off);
145 if ((off != rd[i].data_size) ||
146 (NULL == answer_records[i].data.hostname))
147 {
148 GNUNET_break_op (0);
149 skip_answers++;
150 }
151 break;
152
154 answer_records[i - skip_answers].data.soa
156 rd[i].data_size,
157 &off);
158 if ((off != rd[i].data_size) ||
159 (NULL == answer_records[i].data.soa))
160 {
161 GNUNET_break_op (0);
162 skip_answers++;
163 }
164 break;
165
167 /* FIXME: SRV is not yet supported */
168 skip_answers++;
169 break;
170
172 /* FIXME: URI is not yet supported */
173 skip_answers++;
174 break;
175
177 answer_records[i - skip_answers].data.mx
179 rd[i].data_size,
180 &off);
181 if ((off != rd[i].data_size) ||
182 (NULL == answer_records[i].data.hostname))
183 {
184 GNUNET_break_op (0);
185 skip_answers++;
186 }
187 break;
188
189 default:
190 answer_records[i - skip_answers].data.raw.data_len = rd[i].data_size;
191 answer_records[i - skip_answers].data.raw.data = (char *) rd[i].data;
192 break;
193 }
194 GNUNET_break (0 == (rd[i - skip_answers].flags
196 answer_records[i - skip_answers].expiration_time.abs_value_us =
198 answer_records[i - skip_answers].dns_traffic_class =
200 }
201 else
202 {
203 additional_records[i - skip_additional].name = query->name;
204 additional_records[i - skip_additional].type = rd[i].record_type;
205 switch (rd[i].record_type)
206 {
210 additional_records[i - skip_additional].data.hostname
212 rd[i].data_size,
213 &off);
214 if ((off != rd[i].data_size) ||
215 (NULL == additional_records[i].data.hostname))
216 {
217 GNUNET_break_op (0);
218 skip_additional++;
219 }
220 break;
221
223 additional_records[i - skip_additional].data.soa
225 rd[i].data_size,
226 &off);
227 if ((off != rd[i].data_size) ||
228 (NULL == additional_records[i].data.hostname))
229 {
230 GNUNET_break_op (0);
231 skip_additional++;
232 }
233 break;
234
236 additional_records[i - skip_additional].data.mx
238 rd[i].data_size,
239 &off);
240 if ((off != rd[i].data_size) ||
241 (NULL == additional_records[i].data.hostname))
242 {
243 GNUNET_break_op (0);
244 skip_additional++;
245 }
246 break;
247
249 /* FIXME: SRV is not yet supported */
250 skip_answers++;
251 break;
252
254 additional_records[i - skip_additional].data.uri
256 rd[i].data_size,
257 &off);
258 if ((off != rd[i].data_size) ||
259 (NULL == additional_records[i].data.uri))
260 {
261 GNUNET_break_op (0);
262 skip_additional++;
263 }
264 break;
265
266 default:
267 additional_records[i - skip_additional].data.raw.data_len =
268 rd[i].data_size;
269 additional_records[i - skip_additional].data.raw.data =
270 (char *) rd[i].data;
271 break;
272 }
273 GNUNET_break (0 == (rd[i - skip_additional].flags
275 additional_records[i - skip_additional].expiration_time.abs_value_us =
277 additional_records[i - skip_additional].dns_traffic_class =
279 }
280 }
281 packet->num_answers = num_answers - skip_answers;
282 packet->num_additional_records = rd_count - num_answers - skip_additional;
283 packet->flags.authoritative_answer = 1;
284 if (NULL == rd)
286 else
288 packet->flags.query_or_response = 1;
289 ret = GNUNET_DNSPARSER_pack (packet,
290 1024, /* maximum allowed size for DNS reply */
291 &buf,
292 &len);
293 if (GNUNET_OK != ret)
294 {
296 _ ("Error converting GNS response to DNS response!\n"));
297 if (GNUNET_NO == ret)
298 GNUNET_free (buf);
299 }
300 else
301 {
303 len,
304 buf);
305 GNUNET_free (buf);
306 }
307 packet->num_answers = 0;
308 packet->answers = NULL;
309 packet->num_additional_records = 0;
310 packet->additional_records = NULL;
312 }
314 GNUNET_free (ilh);
315}
static int ret
Final status code.
Definition: gnunet-arm.c:93
static char * data
The data to insert into the dht.
static unsigned int rd_count
Number of records for currently parsed set.
static struct GNUNET_GNSRECORD_Data rd[50]
The record data under a single label.
static size_t data_size
Number of bytes in data.
static struct InterceptLookupHandle * ilh_head
Head of the DLL.
static struct InterceptLookupHandle * ilh_tail
Tail of the DLL.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_DNSPARSER_TYPE_URI
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:455
void GNUNET_DNSPARSER_free_packet(struct GNUNET_DNSPARSER_Packet *p)
Free memory taken by a packet.
Definition: dnsparser.c:949
#define GNUNET_DNSPARSER_TYPE_SRV
#define GNUNET_DNSPARSER_TYPE_SOA
#define GNUNET_DNSPARSER_TYPE_PTR
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:410
#define GNUNET_DNSPARSER_TYPE_NS
#define GNUNET_DNSPARSER_TYPE_CNAME
struct GNUNET_DNSPARSER_UriRecord * GNUNET_DNSPARSER_parse_uri(const char *udp_payload, size_t udp_payload_length, size_t *off)
Parse a DNS URI record.
Definition: dnsparser.c:537
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:353
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:1394
#define GNUNET_DNSPARSER_TYPE_MX
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:296
@ GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION
This expiration time of the record is a relative time (not an absolute time).
#define GNUNET_log(kind,...)
@ GNUNET_OK
@ GNUNET_NO
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
@ GNUNET_ERROR_TYPE_WARNING
#define GNUNET_free(ptr)
Wrapper around free.
#define GNUNET_TUN_DNS_RETURN_CODE_NAME_ERROR
#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'r...
#define GNUNET_TUN_DNS_RETURN_CODE_NO_ERROR
RFC 1035 codes.
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
Easy-to-process, parsed version of a DNS packet.
struct GNUNET_DNSPARSER_Query * queries
Array of all queries in the packet, must contain "num_queries" entries.
unsigned int num_answers
Number of answers in the packet, should be 0 for queries.
struct GNUNET_TUN_DnsFlags flags
Bitfield of DNS flags.
struct GNUNET_DNSPARSER_Record * answers
Array of all answers in the packet, must contain "num_answers" entries.
unsigned int num_additional_records
Number of additional records in the packet, should be 0 for queries.
struct GNUNET_DNSPARSER_Record * additional_records
Array of all additional answers in the packet, must contain "num_additional_records" entries.
uint16_t type
See GNUNET_DNSPARSER_TYPE_*.
char * name
Name of the record that the query is for (0-terminated).
A DNS response record.
char * name
Name of the record that the query is for (0-terminated).
uint32_t record_type
Type of the GNS/DNS record.
size_t data_size
Number of bytes in data.
uint64_t expiration_time
Expiration time for the DNS record.
unsigned int query_or_response
query:0, response:1
unsigned int return_code
See GNUNET_TUN_DNS_RETURN_CODE_ defines.
unsigned int authoritative_answer
Set to 1 if this is an authoritative answer.
Handle to a DNS intercepted resolution request.
struct GNUNET_DNSPARSER_Packet * packet
the dns parser packet received
struct GNUNET_DNS_RequestHandle * request_handle
the request handle to reply to

References _, GNUNET_TIME_Absolute::abs_value_us, GNUNET_DNSPARSER_Packet::additional_records, GNUNET_DNSPARSER_Packet::answers, GNUNET_TUN_DnsFlags::authoritative_answer, 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_DNSPARSER_Record::expiration_time, GNUNET_GNSRECORD_Data::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_parse_uri(), 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_DNSPARSER_TYPE_URI, 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, ilh_head, ilh_tail, 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, rd, rd_count, GNUNET_GNSRECORD_Data::record_type, InterceptLookupHandle::request_handle, ret, GNUNET_TUN_DnsFlags::return_code, GNUNET_DNSPARSER_Record::soa, GNUNET_DNSPARSER_Query::type, GNUNET_DNSPARSER_Record::type, and GNUNET_DNSPARSER_Record::uri.

Referenced by handle_dns_request().

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 327 of file gnunet-service-gns_interceptor.c.

331{
333 struct InterceptLookupHandle *ilh;
334 struct GNUNET_CRYPTO_PublicKey zone;
335
337 "Hijacked a DNS request. Processing.\n");
338 if (NULL == (p = GNUNET_DNSPARSER_parse (request, request_length)))
339 {
341 "Received malformed DNS packet, leaving it untouched.\n");
343 return;
344 }
345
346 /* Check TLD and decide if we or legacy dns is responsible */
347 if (1 != p->num_queries)
348 {
350 "Not exactly one query in DNS packet. Forwarding untouched.\n");
353 return;
354 }
355
356 /* Check for GNS TLDs. */
357 if (GNUNET_YES ==
358 GNS_find_tld (GNS_get_tld (p->queries[0].name),
359 &zone))
360 {
361 /* Start resolution in GNS */
362 ilh = GNUNET_new (struct InterceptLookupHandle);
364 ilh_tail,
365 ilh);
366 ilh->packet = p;
367 ilh->request_handle = rh;
368 ilh->lookup = GNS_resolver_lookup (&zone,
369 p->queries[0].type,
370 p->queries[0].name,
373 &reply_to_dns, ilh);
374 return;
375 }
376 /* This request does not concern us. Forward to real DNS. */
378 "Request for `%s' is forwarded to DNS untouched.\n",
379 p->queries[0].name);
382}
enum GNUNET_GenericReturnValue GNS_find_tld(const char *tld_str, struct GNUNET_CRYPTO_PublicKey *pkey)
Find GNS zone belonging to TLD tld.
const char * GNS_get_tld(const char *name)
Obtain the TLD of the given name.
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.
#define MAX_RECURSION
How deep do we allow recursions to go before we abort?
struct GNS_ResolverHandle * GNS_resolver_lookup(const struct GNUNET_CRYPTO_PublicKey *zone, uint32_t record_type, const char *name, enum GNUNET_GNS_LocalOptions options, uint16_t recursion_depth_limit, GNS_ResultProcessor proc, void *proc_cls)
Lookup of a record in a specific zone calls lookup result processor on result.
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-uri.c:38
static struct GNUNET_VPN_RedirectionRequest * request
Opaque redirection request handle.
Definition: gnunet-vpn.c:40
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
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:729
void GNUNET_DNS_request_forward(struct GNUNET_DNS_RequestHandle *rh)
If a GNUNET_DNS_RequestHandler calls this function, the client has no desire to interfere with the re...
Definition: dns_api.c:237
@ GNUNET_GNS_LO_DEFAULT
Defaults, look in cache, then in DHT.
@ GNUNET_YES
@ GNUNET_ERROR_TYPE_DEBUG
#define GNUNET_new(type)
Allocate a struct or union of the given type.
An identity key as per LSD0001.
struct GNS_ResolverHandle * lookup
Handle for the lookup operation.

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_GNS_LO_DEFAULT, GNUNET_log, GNUNET_new, GNUNET_YES, ilh_head, ilh_tail, InterceptLookupHandle::lookup, MAX_RECURSION, p, InterceptLookupHandle::packet, reply_to_dns(), request, and InterceptLookupHandle::request_handle.

Referenced by GNS_interceptor_init().

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)

Initialize DNS interceptor.

Parameters
cthe configuration
Returns
GNUNET_YES on success GNUNET_SYSERR on error

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

387{
389 "DNS hijacking enabled. Connecting to DNS service.\n");
393 NULL);
394 if (NULL == dns_handle)
395 {
397 _ ("Failed to connect to the DNS service!\n"));
398 return GNUNET_SYSERR;
399 }
400 return GNUNET_YES;
401}
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.
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:340
@ 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_SYSERR
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_INFO

References _, dns_handle, 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().

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 408 of file gnunet-service-gns_interceptor.c.

409{
410 struct InterceptLookupHandle *ilh;
411
412 while (NULL != (ilh = ilh_head))
413 {
415 ilh_tail,
416 ilh);
420 GNUNET_free (ilh);
421 }
422 if (NULL != dns_handle)
423 {
425 dns_handle = NULL;
426 }
427}
void GNS_resolver_lookup_cancel(struct GNS_ResolverHandle *rh)
Cancel active resolution (i.e.
void GNUNET_DNS_disconnect(struct GNUNET_DNS_Handle *dh)
Disconnect from the DNS service.
Definition: dns_api.c:363
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:265

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

Referenced by shutdown_task().

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 77 of file gnunet-service-gns_interceptor.c.

Referenced by GNS_interceptor_done(), and GNS_interceptor_init().

◆ ilh_head

struct InterceptLookupHandle* ilh_head
static

Head of the DLL.

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

Referenced by GNS_interceptor_done(), handle_dns_request(), and reply_to_dns().

◆ ilh_tail

struct InterceptLookupHandle* ilh_tail
static

Tail of the DLL.

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

Referenced by GNS_interceptor_done(), handle_dns_request(), and reply_to_dns().