GNUnet 0.28.0-dev.3-20-gf1136b0b8
 
Loading...
Searching...
No Matches
dnsstub.c File Reference
#include "platform.h"
#include "gnunet_util_lib.h"
Include dependency graph for dnsstub.c:

Go to the source code of this file.

Data Structures

struct  GNUNET_DNSSTUB_RequestSocket
 UDP socket we are using for sending DNS requests to the Internet. More...
 
struct  DnsServer
 DNS Server used for resolution. More...
 
struct  GNUNET_DNSSTUB_Context
 Handle to the stub resolver. More...
 

Macros

#define DNS_RETRANSMIT_DELAY    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 250)
 Timeout for retrying DNS queries.
 

Functions

static void cleanup_rs (struct GNUNET_DNSSTUB_RequestSocket *rs)
 We're done with a struct GNUNET_DNSSTUB_RequestSocket, close it for now.
 
static struct GNUNET_NETWORK_Handleopen_socket (int af)
 Open source port for sending DNS requests.
 
static struct GNUNET_DNSSTUB_RequestSocketget_request_socket (struct GNUNET_DNSSTUB_Context *ctx)
 Get a socket of the specified address family to send out a UDP DNS request to the Internet.
 
static int do_dns_read (struct GNUNET_DNSSTUB_RequestSocket *rs, struct GNUNET_NETWORK_Handle *dnsout)
 Actually do the reading of a DNS packet from our UDP socket and see if we have a valid, matching, pending request.
 
static void read_response (void *cls)
 Read a DNS response from the (unhindered) UDP-Socket.
 
static void schedule_read (struct GNUNET_DNSSTUB_RequestSocket *rs)
 Schedule read_response() task for rs.
 
static void transmit_query (void *cls)
 Task to (re)transmit the DNS query, possibly repeatedly until we succeed.
 
struct GNUNET_DNSSTUB_RequestSocketGNUNET_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.
 
void GNUNET_DNSSTUB_resolve_cancel (struct GNUNET_DNSSTUB_RequestSocket *rs)
 Cancel DNS resolution.
 
struct GNUNET_DNSSTUB_ContextGNUNET_DNSSTUB_start (unsigned int num_sockets)
 Start a DNS stub resolver.
 
int GNUNET_DNSSTUB_add_dns_ip (struct GNUNET_DNSSTUB_Context *ctx, const char *dns_ip)
 Add nameserver for use by the DNSSTUB.
 
int GNUNET_DNSSTUB_add_dns_sa (struct GNUNET_DNSSTUB_Context *ctx, const struct sockaddr *sa)
 Add nameserver for use by the DNSSTUB.
 
void GNUNET_DNSSTUB_set_retry (struct GNUNET_DNSSTUB_Context *ctx, struct GNUNET_TIME_Relative retry_freq)
 How long should we try requests before timing out? Only effective for requests issued after this call.
 
void GNUNET_DNSSTUB_stop (struct GNUNET_DNSSTUB_Context *ctx)
 Cleanup DNSSTUB resolver.
 

Macro Definition Documentation

◆ DNS_RETRANSMIT_DELAY

#define DNS_RETRANSMIT_DELAY    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 250)

Timeout for retrying DNS queries.

Definition at line 32 of file dnsstub.c.

45{
49 struct GNUNET_NETWORK_Handle *dnsout4;
50
54 struct GNUNET_NETWORK_Handle *dnsout6;
55
60
64 void *rc_cls;
65
70
75
79 struct DnsServer *ds_pos;
80
85
89 void *request;
90
94 size_t request_len;
95};
96
97
101struct DnsServer
102{
106 struct DnsServer *next;
107
111 struct DnsServer *prev;
112
116 struct sockaddr_storage ss;
117};
118
119
124{
129
133 struct DnsServer *dns_head;
134
138 struct DnsServer *dns_tail;
139
144
148 unsigned int num_sockets;
149};
150
151
157static void
159{
160 if (NULL != rs->dnsout4)
161 {
163 rs->dnsout4 = NULL;
164 }
165 if (NULL != rs->dnsout6)
166 {
168 rs->dnsout6 = NULL;
169 }
170 if (NULL != rs->read_task)
171 {
173 rs->read_task = NULL;
174 }
175 if (NULL != rs->retry_task)
176 {
178 rs->retry_task = NULL;
179 }
180 if (NULL != rs->request)
181 {
182 GNUNET_free (rs->request);
183 rs->request = NULL;
184 }
185}
186
187
194static struct GNUNET_NETWORK_Handle *
195open_socket (int af)
196{
197 struct sockaddr_in a4;
198 struct sockaddr_in6 a6;
199 struct sockaddr *sa;
200 socklen_t alen;
202
203 ret = GNUNET_NETWORK_socket_create (af, SOCK_DGRAM, 0);
204 if (NULL == ret)
205 return NULL;
206 switch (af)
207 {
208 case AF_INET:
209 memset (&a4, 0, alen = sizeof(struct sockaddr_in));
210 sa = (struct sockaddr *) &a4;
211 break;
212
213 case AF_INET6:
214 memset (&a6, 0, alen = sizeof(struct sockaddr_in6));
215 sa = (struct sockaddr *) &a6;
216 break;
217
218 default:
219 GNUNET_break (0);
221 return NULL;
222 }
223 sa->sa_family = af;
224 if (GNUNET_OK != GNUNET_NETWORK_socket_bind (ret, sa, alen))
225 {
227 _ ("Could not bind to any port: %s\n"),
228 strerror (errno));
230 return NULL;
231 }
232 return ret;
233}
234
235
243static struct GNUNET_DNSSTUB_RequestSocket *
245{
247
248 for (unsigned int i = 0; i < 256; i++)
249 {
250 rs = &ctx->sockets[GNUNET_CRYPTO_random_u32 (ctx->num_sockets)];
251 if (NULL == rs->rc)
252 break;
253 }
254 if (NULL != rs->rc)
255 {
256 /* signal "failure" */
257 rs->rc (rs->rc_cls, NULL, 0);
258 rs->rc = NULL;
259 }
260 if (NULL != rs->read_task)
261 {
263 rs->read_task = NULL;
264 }
265 if (NULL != rs->retry_task)
266 {
268 rs->retry_task = NULL;
269 }
270 if (NULL != rs->request)
271 {
272 GNUNET_free (rs->request);
273 rs->request = NULL;
274 }
275 rs->ctx = ctx;
276 return rs;
277}
278
279
288static int
290 struct GNUNET_NETWORK_Handle *dnsout)
291{
292 struct GNUNET_DNSSTUB_Context *ctx = rs->ctx;
293 ssize_t r;
294 int len;
295
296 if (0 != ioctl (GNUNET_NETWORK_get_fd (dnsout), FIONREAD, &len))
297 {
298 /* conservative choice: */
299 len = UINT16_MAX;
300 }
301
302 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Receiving %d byte DNS reply\n", len);
303 {
304 unsigned char buf[len] GNUNET_ALIGN;
305 int found;
306 struct sockaddr_storage addr;
307 socklen_t addrlen;
308 struct GNUNET_TUN_DnsHeader *dns;
309
310 addrlen = sizeof(addr);
311 memset (&addr, 0, sizeof(addr));
313 buf,
314 sizeof(buf),
315 (struct sockaddr *) &addr,
316 &addrlen);
317 if (-1 == r)
318 {
321 return GNUNET_SYSERR;
322 }
323 found = GNUNET_NO;
324 for (struct DnsServer *ds = ctx->dns_head; NULL != ds; ds = ds->next)
325 {
326 if (ds->ss.ss_family != addr.ss_family)
327 continue;
328 if (addr.ss_family == AF_INET)
329 {
330 struct sockaddr_in *v4 = (struct sockaddr_in *) &addr;
331 struct sockaddr_in *ds_v4 = (struct sockaddr_in *) &ds->ss;
332
333
334 if ((0 == memcmp (&v4->sin_addr,
335 &ds_v4->sin_addr,
336 sizeof(struct sockaddr_in))) &&
337 (v4->sin_port == ds_v4->sin_port))
338 {
339 found = GNUNET_YES;
340 break;
341 }
342 }
343 else
344 {
345 struct sockaddr_in6 *v6 = (struct sockaddr_in6 *) &addr;
346 struct sockaddr_in6 *ds_v6 = (struct sockaddr_in6 *) &ds->ss;
347
348 if (0 == memcmp (&v6->sin6_addr,
349 &ds_v6->sin6_addr,
350 sizeof (v6->sin6_addr)) &&
351 (v6->sin6_port == ds_v6->sin6_port))
352 {
353 found = GNUNET_YES;
354 break;
355 }
356
357 }
358 }
359 if (GNUNET_NO == found)
360 {
362 "Received DNS response from server we never asked (ignored)\n");
363
364 return GNUNET_NO;
365 }
366 if (sizeof(struct GNUNET_TUN_DnsHeader) > (size_t) r)
367 {
369 _ ("Received DNS response that is too small (%u bytes)\n"),
370 (unsigned int) r);
371 return GNUNET_NO;
372 }
373 dns = (struct GNUNET_TUN_DnsHeader *) buf;
374 if (NULL == rs->rc)
375 {
377 "Request timeout or cancelled; ignoring reply\n");
378 return GNUNET_NO;
379 }
380 rs->rc (rs->rc_cls, dns, r);
381 }
382 return GNUNET_OK;
383}
384
385
391static void
392read_response (void *cls);
393
394
400static void
402{
403 struct GNUNET_NETWORK_FDSet *rset;
404
405 if (NULL != rs->read_task)
408 if (NULL != rs->dnsout4)
410 if (NULL != rs->dnsout6)
412 rs->read_task =
415 rset,
416 NULL,
418 rs);
420}
421
422
423static void
424read_response (void *cls)
425{
426 struct GNUNET_DNSSTUB_RequestSocket *rs = cls;
427 const struct GNUNET_SCHEDULER_TaskContext *tc;
428
429 rs->read_task = NULL;
431 /* read and process ready sockets */
432 if ((NULL != rs->dnsout4) &&
434 (GNUNET_SYSERR == do_dns_read (rs, rs->dnsout4)))
435 rs->dnsout4 = NULL;
436 if ((NULL != rs->dnsout6) &&
438 (GNUNET_SYSERR == do_dns_read (rs, rs->dnsout6)))
439 rs->dnsout6 = NULL;
440 /* re-schedule read task */
441 schedule_read (rs);
442}
443
444
451static void
452transmit_query (void *cls)
453{
454 struct GNUNET_DNSSTUB_RequestSocket *rs = cls;
455 struct GNUNET_DNSSTUB_Context *ctx = rs->ctx;
456 const struct sockaddr *sa;
457 socklen_t salen;
458 struct DnsServer *ds;
459 struct GNUNET_NETWORK_Handle *dnsout;
460
461 rs->retry_task =
463 ds = rs->ds_pos;
464 rs->ds_pos = ds->next;
465 if (NULL == rs->ds_pos)
466 rs->ds_pos = ctx->dns_head;
467 GNUNET_assert (NULL != ds);
468 dnsout = NULL;
469 switch (ds->ss.ss_family)
470 {
471 case AF_INET:
472 if (NULL == rs->dnsout4)
473 rs->dnsout4 = open_socket (AF_INET);
474 dnsout = rs->dnsout4;
475 sa = (const struct sockaddr *) &ds->ss;
476 salen = sizeof(struct sockaddr_in);
477 break;
478
479 case AF_INET6:
480 if (NULL == rs->dnsout6)
481 rs->dnsout6 = open_socket (AF_INET6);
482 dnsout = rs->dnsout6;
483 sa = (const struct sockaddr *) &ds->ss;
484 salen = sizeof(struct sockaddr_in6);
485 break;
486
487 default:
488 return;
489 }
490 if (NULL == dnsout)
491 {
493 "Unable to use configure DNS server, skipping\n");
494 return;
495 }
497 rs->request,
498 rs->request_len,
499 sa,
500 salen))
502 _ ("Failed to send DNS request to %s: %s\n"),
503 GNUNET_a2s (sa, salen),
504 strerror (errno));
505 else
507 _ ("Sent DNS request to %s\n"),
508 GNUNET_a2s (sa, salen));
509 schedule_read (rs);
510}
511
512
525 const void *request,
526 size_t request_len,
528 void *rc_cls)
529{
531
532 if (NULL == ctx->dns_head)
533 {
535 "No DNS server configured for resolution\n");
536 return NULL;
537 }
538 if (NULL == (rs = get_request_socket (ctx)))
539 {
541 "No request socket available for DNS resolution\n");
542 return NULL;
543 }
544 rs->ds_pos = ctx->dns_head;
545 rs->rc = rc;
546 rs->rc_cls = rc_cls;
550 return rs;
551}
552
553
559void
561{
562 rs->rc = NULL;
563 if (NULL != rs->retry_task)
564 {
566 rs->retry_task = NULL;
567 }
568 if (NULL != rs->read_task)
569 {
571 rs->read_task = NULL;
572 }
573}
574
575
585{
587
588 if (0 == num_sockets)
589 {
590 GNUNET_break (0);
591 return NULL;
592 }
594 ctx->num_sockets = num_sockets;
595 ctx->sockets =
597 ctx->retry_freq = DNS_RETRANSMIT_DELAY;
598 return ctx;
599}
600
601
610int
612 const char *dns_ip)
613{
614 struct DnsServer *ds;
615 struct in_addr i4;
616 struct in6_addr i6;
617
618 ds = GNUNET_new (struct DnsServer);
619 if (1 == inet_pton (AF_INET, dns_ip, &i4))
620 {
621 struct sockaddr_in *s4 = (struct sockaddr_in *) &ds->ss;
622
623 s4->sin_family = AF_INET;
624 s4->sin_port = htons (53);
625 s4->sin_addr = i4;
626#if HAVE_SOCKADDR_IN_SIN_LEN
627 s4->sin_len = (u_char) sizeof(struct sockaddr_in);
628#endif
629 }
630 else if (1 == inet_pton (AF_INET6, dns_ip, &i6))
631 {
632 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) &ds->ss;
633
634 s6->sin6_family = AF_INET6;
635 s6->sin6_port = htons (53);
636 s6->sin6_addr = i6;
637#if HAVE_SOCKADDR_IN_SIN_LEN
638 s6->sin6_len = (u_char) sizeof(struct sockaddr_in6);
639#endif
640 }
641 else
642 {
644 "Malformed IP address `%s' for DNS server\n",
645 dns_ip);
646 GNUNET_free (ds);
647 return GNUNET_SYSERR;
648 }
649 GNUNET_CONTAINER_DLL_insert (ctx->dns_head, ctx->dns_tail, ds);
650 return GNUNET_OK;
651}
652
653
662int
664 const struct sockaddr *sa)
665{
666 struct DnsServer *ds;
667
668 ds = GNUNET_new (struct DnsServer);
669 switch (sa->sa_family)
670 {
671 case AF_INET:
672 GNUNET_memcpy (&ds->ss, sa, sizeof(struct sockaddr_in));
673 break;
674
675 case AF_INET6:
676 GNUNET_memcpy (&ds->ss, sa, sizeof(struct sockaddr_in6));
677 break;
678
679 default:
680 GNUNET_break (0);
681 GNUNET_free (ds);
682 return GNUNET_SYSERR;
683 }
684 GNUNET_CONTAINER_DLL_insert (ctx->dns_head, ctx->dns_tail, ds);
685 return GNUNET_OK;
686}
687
688
689void
691 struct GNUNET_TIME_Relative retry_freq)
692{
693 ctx->retry_freq = retry_freq;
694}
695
696
702void
704{
705 struct DnsServer *ds;
706
707 while (NULL != (ds = ctx->dns_head))
708 {
709 GNUNET_CONTAINER_DLL_remove (ctx->dns_head, ctx->dns_tail, ds);
710 GNUNET_free (ds);
711 }
712 for (unsigned int i = 0; i < ctx->num_sockets; i++)
713 cleanup_rs (&ctx->sockets[i]);
714 GNUNET_free (ctx->sockets);
716}
717
718
719/* end of dnsstub.c */
static void transmit_query(void *cls)
Task to (re)transmit the DNS query, possibly repeatedly until we succeed.
Definition dnsstub.c:453
static struct GNUNET_DNSSTUB_RequestSocket * get_request_socket(struct GNUNET_DNSSTUB_Context *ctx)
Get a socket of the specified address family to send out a UDP DNS request to the Internet.
Definition dnsstub.c:245
static void read_response(void *cls)
Read a DNS response from the (unhindered) UDP-Socket.
Definition dnsstub.c:425
static int do_dns_read(struct GNUNET_DNSSTUB_RequestSocket *rs, struct GNUNET_NETWORK_Handle *dnsout)
Actually do the reading of a DNS packet from our UDP socket and see if we have a valid,...
Definition dnsstub.c:290
static void schedule_read(struct GNUNET_DNSSTUB_RequestSocket *rs)
Schedule read_response() task for rs.
Definition dnsstub.c:402
static struct GNUNET_NETWORK_Handle * open_socket(int af)
Open source port for sending DNS requests.
Definition dnsstub.c:196
static void cleanup_rs(struct GNUNET_DNSSTUB_RequestSocket *rs)
We're done with a struct GNUNET_DNSSTUB_RequestSocket, close it for now.
Definition dnsstub.c:159
#define DNS_RETRANSMIT_DELAY
Timeout for retrying DNS queries.
Definition dnsstub.c:32
static int ret
Final status code.
Definition gnunet-arm.c:93
static char * dns_ip
IP of DNS server.
static struct GNUNET_FS_Handle * ctx
struct GNUNET_SCHEDULER_Task * read_task
static struct GNUNET_FS_DirScanner * ds
Handle to the directory scanner (for recursive insertions).
static struct GNUNET_SCHEDULER_Task * retry_task
Task that re-transmits requests (using retry_heap).
static struct GNUNET_VPN_RedirectionRequest * request
Opaque redirection request handle.
Definition gnunet-vpn.c:40
uint32_t GNUNET_CRYPTO_random_u32(uint32_t i)
Produce a random value.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
struct GNUNET_DNSSTUB_Context * GNUNET_DNSSTUB_start(unsigned int num_sockets)
Start a DNS stub resolver.
Definition dnsstub.c:585
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:612
void(* GNUNET_DNSSTUB_ResultCallback)(void *cls, const struct GNUNET_TUN_DnsHeader *dns, size_t dns_len)
Function called with the result of a DNS resolution.
void GNUNET_DNSSTUB_stop(struct GNUNET_DNSSTUB_Context *ctx)
Cleanup DNSSTUB resolver.
Definition dnsstub.c:704
void GNUNET_DNSSTUB_set_retry(struct GNUNET_DNSSTUB_Context *ctx, struct GNUNET_TIME_Relative retry_freq)
How long should we try requests before timing out? Only effective for requests issued after this call...
Definition dnsstub.c:691
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:525
void GNUNET_DNSSTUB_resolve_cancel(struct GNUNET_DNSSTUB_RequestSocket *rs)
Cancel DNS resolution.
Definition dnsstub.c:561
int GNUNET_DNSSTUB_add_dns_sa(struct GNUNET_DNSSTUB_Context *ctx, const struct sockaddr *sa)
Add nameserver for use by the DNSSTUB.
Definition dnsstub.c:664
#define GNUNET_log(kind,...)
#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_SCHEDULER_PRIORITY_DEFAULT
Run with the default priority (normal P2P operations).
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#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.
const char * GNUNET_a2s(const struct sockaddr *addr, socklen_t addrlen)
Convert a "struct sockaddr*" (IPv4 or IPv6 address) to a string (for printing debug messages).
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
#define GNUNET_free(ptr)
Wrapper around free.
#define GNUNET_memdup(buf, size)
Allocate and initialize a block of memory.
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition network.c:508
void GNUNET_NETWORK_fdset_destroy(struct GNUNET_NETWORK_FDSet *fds)
Releases the associated memory of an fd set.
Definition network.c:1184
int GNUNET_NETWORK_get_fd(const struct GNUNET_NETWORK_Handle *desc)
Return file descriptor for this network handle.
Definition network.c:1000
ssize_t GNUNET_NETWORK_socket_recvfrom(const struct GNUNET_NETWORK_Handle *desc, void *buffer, size_t length, struct sockaddr *src_addr, socklen_t *addrlen)
Read data from a socket (always non-blocking).
Definition network.c:687
struct GNUNET_NETWORK_FDSet * GNUNET_NETWORK_fdset_create(void)
Creates an fd set.
Definition network.c:1168
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition network.c:832
void GNUNET_NETWORK_fdset_set(struct GNUNET_NETWORK_FDSet *fds, const struct GNUNET_NETWORK_Handle *desc)
Add a socket to the FD set.
Definition network.c:931
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_bind(struct GNUNET_NETWORK_Handle *desc, const struct sockaddr *address, socklen_t address_len)
Bind a socket to a particular address.
Definition network.c:439
ssize_t GNUNET_NETWORK_socket_sendto(const struct GNUNET_NETWORK_Handle *desc, const void *message, size_t length, const struct sockaddr *dest_addr, socklen_t dest_len)
Send data to a particular destination (always non-blocking).
Definition network.c:771
int GNUNET_NETWORK_fdset_isset(const struct GNUNET_NETWORK_FDSet *fds, const struct GNUNET_NETWORK_Handle *desc)
Check whether a socket is part of the fd set.
Definition network.c:949
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_select(enum GNUNET_SCHEDULER_Priority prio, struct GNUNET_TIME_Relative delay, const struct GNUNET_NETWORK_FDSet *rs, const struct GNUNET_NETWORK_FDSet *ws, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when any of the specified file descriptor set...
Definition scheduler.c:1841
const struct GNUNET_SCHEDULER_TaskContext * GNUNET_SCHEDULER_get_task_context(void)
Obtain the reasoning why the current task was started.
Definition scheduler.c:764
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition scheduler.c:986
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition scheduler.c:1310
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition scheduler.c:1283
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
#define _(String)
GNU gettext support macro.
Definition platform.h:179
static struct GNUNET_SCHEDULER_TaskContext tc
Task context of the current task.
Definition scheduler.c:436
DNS Server used for resolution.
Definition dnsstub.c:103
struct DnsServer * next
Kept in a DLL.
Definition dnsstub.c:107
struct DnsServer * prev
Kept in a DLL.
Definition dnsstub.c:112
struct sockaddr_storage ss
IP address of the DNS resolver.
Definition dnsstub.c:117
Handle to the stub resolver.
Definition dnsstub.c:125
struct DnsServer * dns_tail
DLL of DNS resolvers we use.
Definition dnsstub.c:139
unsigned int num_sockets
Length of sockets array.
Definition dnsstub.c:149
struct GNUNET_DNSSTUB_RequestSocket * sockets
Array of all open sockets for DNS requests.
Definition dnsstub.c:129
struct DnsServer * dns_head
DLL of DNS resolvers we use.
Definition dnsstub.c:134
struct GNUNET_TIME_Relative retry_freq
How frequently do we retry requests?
Definition dnsstub.c:144
UDP socket we are using for sending DNS requests to the Internet.
Definition dnsstub.c:46
void * request
Query we sent to addr.
Definition dnsstub.c:90
struct GNUNET_DNSSTUB_Context * ctx
Context this request executes in.
Definition dnsstub.c:85
struct GNUNET_NETWORK_Handle * dnsout4
UDP socket we use for this request for IPv4.
Definition dnsstub.c:50
struct GNUNET_SCHEDULER_Task * read_task
Task for reading from dnsout4 and dnsout6.
Definition dnsstub.c:70
GNUNET_DNSSTUB_ResultCallback rc
Function to call with result.
Definition dnsstub.c:60
struct GNUNET_SCHEDULER_Task * retry_task
Task for retrying transmission of the query.
Definition dnsstub.c:75
struct GNUNET_NETWORK_Handle * dnsout6
UDP socket we use for this request for IPv6.
Definition dnsstub.c:55
size_t request_len
Number of bytes in request.
Definition dnsstub.c:95
void * rc_cls
Closure for rc.
Definition dnsstub.c:65
struct DnsServer * ds_pos
Next address we sent the DNS request to.
Definition dnsstub.c:80
collection of IO descriptors
handle to a socket
Definition network.c:53
int af
Address family / domain.
Definition network.c:59
Context information passed to each scheduler task.
const struct GNUNET_NETWORK_FDSet * read_ready
Set of file descriptors ready for reading; note that additional bits may be set that were not in the ...
Entry in list of pending tasks.
Definition scheduler.c:141
Time for relative time used by GNUnet, in microseconds.

Function Documentation

◆ cleanup_rs()

static void cleanup_rs ( struct GNUNET_DNSSTUB_RequestSocket rs)
static

We're done with a struct GNUNET_DNSSTUB_RequestSocket, close it for now.

Parameters
rsrequest socket to clean up

Definition at line 159 of file dnsstub.c.

160{
161 if (NULL != rs->dnsout4)
162 {
164 rs->dnsout4 = NULL;
165 }
166 if (NULL != rs->dnsout6)
167 {
169 rs->dnsout6 = NULL;
170 }
171 if (NULL != rs->read_task)
172 {
174 rs->read_task = NULL;
175 }
176 if (NULL != rs->retry_task)
177 {
179 rs->retry_task = NULL;
180 }
181 if (NULL != rs->request)
182 {
183 GNUNET_free (rs->request);
184 rs->request = NULL;
185 }
186}

References GNUNET_DNSSTUB_RequestSocket::dnsout4, GNUNET_DNSSTUB_RequestSocket::dnsout6, GNUNET_free, GNUNET_NETWORK_socket_close(), GNUNET_SCHEDULER_cancel(), GNUNET_DNSSTUB_RequestSocket::read_task, GNUNET_DNSSTUB_RequestSocket::request, and GNUNET_DNSSTUB_RequestSocket::retry_task.

Referenced by GNUNET_DNSSTUB_stop().

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

◆ open_socket()

static struct GNUNET_NETWORK_Handle * open_socket ( int  af)
static

Open source port for sending DNS requests.

Parameters
afAF_INET or AF_INET6
Returns
GNUNET_OK on success

Definition at line 196 of file dnsstub.c.

197{
198 struct sockaddr_in a4;
199 struct sockaddr_in6 a6;
200 struct sockaddr *sa;
201 socklen_t alen;
203
204 ret = GNUNET_NETWORK_socket_create (af, SOCK_DGRAM, 0);
205 if (NULL == ret)
206 return NULL;
207 switch (af)
208 {
209 case AF_INET:
210 memset (&a4, 0, alen = sizeof(struct sockaddr_in));
211 sa = (struct sockaddr *) &a4;
212 break;
213
214 case AF_INET6:
215 memset (&a6, 0, alen = sizeof(struct sockaddr_in6));
216 sa = (struct sockaddr *) &a6;
217 break;
218
219 default:
220 GNUNET_break (0);
222 return NULL;
223 }
224 sa->sa_family = af;
225 if (GNUNET_OK != GNUNET_NETWORK_socket_bind (ret, sa, alen))
226 {
228 _ ("Could not bind to any port: %s\n"),
229 strerror (errno));
231 return NULL;
232 }
233 return ret;
234}

References _, GNUNET_NETWORK_Handle::af, GNUNET_break, GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_NETWORK_socket_bind(), GNUNET_NETWORK_socket_close(), GNUNET_NETWORK_socket_create(), GNUNET_OK, and ret.

Referenced by transmit_query().

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

◆ get_request_socket()

static struct GNUNET_DNSSTUB_RequestSocket * get_request_socket ( struct GNUNET_DNSSTUB_Context ctx)
static

Get a socket of the specified address family to send out a UDP DNS request to the Internet.

Parameters
ctxthe DNSSTUB context
Returns
NULL on error

Definition at line 245 of file dnsstub.c.

246{
248
249 for (unsigned int i = 0; i < 256; i++)
250 {
251 rs = &ctx->sockets[GNUNET_CRYPTO_random_u32 (ctx->num_sockets)];
252 if (NULL == rs->rc)
253 break;
254 }
255 if (NULL != rs->rc)
256 {
257 /* signal "failure" */
258 rs->rc (rs->rc_cls, NULL, 0);
259 rs->rc = NULL;
260 }
261 if (NULL != rs->read_task)
262 {
264 rs->read_task = NULL;
265 }
266 if (NULL != rs->retry_task)
267 {
269 rs->retry_task = NULL;
270 }
271 if (NULL != rs->request)
272 {
273 GNUNET_free (rs->request);
274 rs->request = NULL;
275 }
276 rs->ctx = ctx;
277 return rs;
278}

References ctx, GNUNET_DNSSTUB_RequestSocket::ctx, GNUNET_CRYPTO_random_u32(), GNUNET_free, GNUNET_SCHEDULER_cancel(), GNUNET_DNSSTUB_RequestSocket::rc, GNUNET_DNSSTUB_RequestSocket::rc_cls, GNUNET_DNSSTUB_RequestSocket::read_task, GNUNET_DNSSTUB_RequestSocket::request, and GNUNET_DNSSTUB_RequestSocket::retry_task.

Referenced by GNUNET_DNSSTUB_resolve().

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

◆ do_dns_read()

static int do_dns_read ( struct GNUNET_DNSSTUB_RequestSocket rs,
struct GNUNET_NETWORK_Handle dnsout 
)
static

Actually do the reading of a DNS packet from our UDP socket and see if we have a valid, matching, pending request.

Parameters
rsrequest socket with callback details
dnsoutsocket to read from
Returns
GNUNET_OK on success, GNUNET_NO on drop, GNUNET_SYSERR on IO-errors (closed socket)

Definition at line 290 of file dnsstub.c.

292{
293 struct GNUNET_DNSSTUB_Context *ctx = rs->ctx;
294 ssize_t r;
295 int len;
296
297 if (0 != ioctl (GNUNET_NETWORK_get_fd (dnsout), FIONREAD, &len))
298 {
299 /* conservative choice: */
300 len = UINT16_MAX;
301 }
302
303 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Receiving %d byte DNS reply\n", len);
304 {
305 unsigned char buf[len] GNUNET_ALIGN;
306 int found;
307 struct sockaddr_storage addr;
308 socklen_t addrlen;
309 struct GNUNET_TUN_DnsHeader *dns;
310
311 addrlen = sizeof(addr);
312 memset (&addr, 0, sizeof(addr));
314 buf,
315 sizeof(buf),
316 (struct sockaddr *) &addr,
317 &addrlen);
318 if (-1 == r)
319 {
322 return GNUNET_SYSERR;
323 }
324 found = GNUNET_NO;
325 for (struct DnsServer *ds = ctx->dns_head; NULL != ds; ds = ds->next)
326 {
327 if (ds->ss.ss_family != addr.ss_family)
328 continue;
329 if (addr.ss_family == AF_INET)
330 {
331 struct sockaddr_in *v4 = (struct sockaddr_in *) &addr;
332 struct sockaddr_in *ds_v4 = (struct sockaddr_in *) &ds->ss;
333
334
335 if ((0 == memcmp (&v4->sin_addr,
336 &ds_v4->sin_addr,
337 sizeof(struct sockaddr_in))) &&
338 (v4->sin_port == ds_v4->sin_port))
339 {
340 found = GNUNET_YES;
341 break;
342 }
343 }
344 else
345 {
346 struct sockaddr_in6 *v6 = (struct sockaddr_in6 *) &addr;
347 struct sockaddr_in6 *ds_v6 = (struct sockaddr_in6 *) &ds->ss;
348
349 if (0 == memcmp (&v6->sin6_addr,
350 &ds_v6->sin6_addr,
351 sizeof (v6->sin6_addr)) &&
352 (v6->sin6_port == ds_v6->sin6_port))
353 {
354 found = GNUNET_YES;
355 break;
356 }
357
358 }
359 }
360 if (GNUNET_NO == found)
361 {
363 "Received DNS response from server we never asked (ignored)\n");
364
365 return GNUNET_NO;
366 }
367 if (sizeof(struct GNUNET_TUN_DnsHeader) > (size_t) r)
368 {
370 _ ("Received DNS response that is too small (%u bytes)\n"),
371 (unsigned int) r);
372 return GNUNET_NO;
373 }
374 dns = (struct GNUNET_TUN_DnsHeader *) buf;
375 if (NULL == rs->rc)
376 {
378 "Request timeout or cancelled; ignoring reply\n");
379 return GNUNET_NO;
380 }
381 rs->rc (rs->rc_cls, dns, r);
382 }
383 return GNUNET_OK;
384}

References _, ctx, GNUNET_DNSSTUB_RequestSocket::ctx, ds, GNUNET_ALIGN, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_log_strerror, GNUNET_NETWORK_get_fd(), GNUNET_NETWORK_socket_close(), GNUNET_NETWORK_socket_recvfrom(), GNUNET_NO, GNUNET_OK, GNUNET_SYSERR, GNUNET_YES, GNUNET_DNSSTUB_RequestSocket::rc, and GNUNET_DNSSTUB_RequestSocket::rc_cls.

Referenced by read_response().

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

◆ read_response()

static void read_response ( void *  cls)
static

Read a DNS response from the (unhindered) UDP-Socket.

Parameters
clsstruct GNUNET_DNSSTUB_RequestSocket to read from

Definition at line 425 of file dnsstub.c.

426{
427 struct GNUNET_DNSSTUB_RequestSocket *rs = cls;
428 const struct GNUNET_SCHEDULER_TaskContext *tc;
429
430 rs->read_task = NULL;
432 /* read and process ready sockets */
433 if ((NULL != rs->dnsout4) &&
435 (GNUNET_SYSERR == do_dns_read (rs, rs->dnsout4)))
436 rs->dnsout4 = NULL;
437 if ((NULL != rs->dnsout6) &&
439 (GNUNET_SYSERR == do_dns_read (rs, rs->dnsout6)))
440 rs->dnsout6 = NULL;
441 /* re-schedule read task */
442 schedule_read (rs);
443}

References GNUNET_DNSSTUB_RequestSocket::dnsout4, GNUNET_DNSSTUB_RequestSocket::dnsout6, do_dns_read(), GNUNET_NETWORK_fdset_isset(), GNUNET_SCHEDULER_get_task_context(), GNUNET_SYSERR, GNUNET_SCHEDULER_TaskContext::read_ready, GNUNET_DNSSTUB_RequestSocket::read_task, schedule_read(), and tc.

Referenced by schedule_read().

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

◆ schedule_read()

static void schedule_read ( struct GNUNET_DNSSTUB_RequestSocket rs)
static

Schedule read_response() task for rs.

Parameters
rsrequest to schedule read operation for

Definition at line 402 of file dnsstub.c.

403{
404 struct GNUNET_NETWORK_FDSet *rset;
405
406 if (NULL != rs->read_task)
409 if (NULL != rs->dnsout4)
411 if (NULL != rs->dnsout6)
413 rs->read_task =
416 rset,
417 NULL,
419 rs);
421}

References GNUNET_DNSSTUB_RequestSocket::dnsout4, GNUNET_DNSSTUB_RequestSocket::dnsout6, GNUNET_NETWORK_fdset_create(), GNUNET_NETWORK_fdset_destroy(), GNUNET_NETWORK_fdset_set(), GNUNET_SCHEDULER_add_select(), GNUNET_SCHEDULER_cancel(), GNUNET_SCHEDULER_PRIORITY_DEFAULT, GNUNET_TIME_UNIT_FOREVER_REL, read_response(), and GNUNET_DNSSTUB_RequestSocket::read_task.

Referenced by read_response(), and transmit_query().

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

◆ transmit_query()

static void transmit_query ( void *  cls)
static

Task to (re)transmit the DNS query, possibly repeatedly until we succeed.

Parameters
clsour struct GNUNET_DNSSTUB_RequestSocket *

Definition at line 453 of file dnsstub.c.

454{
455 struct GNUNET_DNSSTUB_RequestSocket *rs = cls;
456 struct GNUNET_DNSSTUB_Context *ctx = rs->ctx;
457 const struct sockaddr *sa;
458 socklen_t salen;
459 struct DnsServer *ds;
460 struct GNUNET_NETWORK_Handle *dnsout;
461
462 rs->retry_task =
464 ds = rs->ds_pos;
465 rs->ds_pos = ds->next;
466 if (NULL == rs->ds_pos)
467 rs->ds_pos = ctx->dns_head;
468 GNUNET_assert (NULL != ds);
469 dnsout = NULL;
470 switch (ds->ss.ss_family)
471 {
472 case AF_INET:
473 if (NULL == rs->dnsout4)
474 rs->dnsout4 = open_socket (AF_INET);
475 dnsout = rs->dnsout4;
476 sa = (const struct sockaddr *) &ds->ss;
477 salen = sizeof(struct sockaddr_in);
478 break;
479
480 case AF_INET6:
481 if (NULL == rs->dnsout6)
482 rs->dnsout6 = open_socket (AF_INET6);
483 dnsout = rs->dnsout6;
484 sa = (const struct sockaddr *) &ds->ss;
485 salen = sizeof(struct sockaddr_in6);
486 break;
487
488 default:
489 return;
490 }
491 if (NULL == dnsout)
492 {
494 "Unable to use configure DNS server, skipping\n");
495 return;
496 }
498 rs->request,
499 rs->request_len,
500 sa,
501 salen))
503 _ ("Failed to send DNS request to %s: %s\n"),
504 GNUNET_a2s (sa, salen),
505 strerror (errno));
506 else
508 _ ("Sent DNS request to %s\n"),
509 GNUNET_a2s (sa, salen));
510 schedule_read (rs);
511}

References _, ctx, GNUNET_DNSSTUB_RequestSocket::ctx, GNUNET_DNSSTUB_RequestSocket::dnsout4, GNUNET_DNSSTUB_RequestSocket::dnsout6, ds, GNUNET_DNSSTUB_RequestSocket::ds_pos, GNUNET_a2s(), GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, GNUNET_NETWORK_socket_sendto(), GNUNET_SCHEDULER_add_delayed(), GNUNET_SYSERR, open_socket(), GNUNET_DNSSTUB_RequestSocket::request, GNUNET_DNSSTUB_RequestSocket::request_len, GNUNET_DNSSTUB_RequestSocket::retry_task, schedule_read(), and transmit_query().

Referenced by GNUNET_DNSSTUB_resolve(), and transmit_query().

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