[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] [gnunet] branch master updated: support multiple DNS resolv
From: |
gnunet |
Subject: |
[GNUnet-SVN] [gnunet] branch master updated: support multiple DNS resolvers for queries (in DNSSTUB and GNS2DNS resolution for now) |
Date: |
Thu, 19 Apr 2018 18:38:52 +0200 |
This is an automated email from the git hooks/post-receive script.
grothoff pushed a commit to branch master
in repository gnunet.
The following commit(s) were added to refs/heads/master by this push:
new ff4d7b51f support multiple DNS resolvers for queries (in DNSSTUB and
GNS2DNS resolution for now)
ff4d7b51f is described below
commit ff4d7b51f37f61633766664647e9b148af1e4f0a
Author: Christian Grothoff <address@hidden>
AuthorDate: Thu Apr 19 18:38:41 2018 +0200
support multiple DNS resolvers for queries (in DNSSTUB and GNS2DNS
resolution for now)
---
src/dns/dnsstub.c | 683 +++++++++++----------
src/dns/gnunet-service-dns.c | 43 +-
src/dns/gnunet-zoneimport.c | 24 +-
src/exit/gnunet-daemon-exit.c | 29 +-
src/gns/gnunet-dns2gns.c | 19 +-
src/gns/gnunet-service-gns_resolver.c | 1072 ++++++++++++++++++---------------
src/gns/test_gns_lookup.conf | 2 +-
src/include/gnunet_dnsstub_lib.h | 85 +--
src/namestore/gnunet-zoneimport.c | 35 +-
9 files changed, 1107 insertions(+), 885 deletions(-)
diff --git a/src/dns/dnsstub.c b/src/dns/dnsstub.c
index 6aa2d7b8f..6eb3612c2 100644
--- a/src/dns/dnsstub.c
+++ b/src/dns/dnsstub.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- Copyright (C) 2012 GNUnet e.V.
+ Copyright (C) 2012, 2018 GNUnet e.V.
GNUnet is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
@@ -28,20 +28,15 @@
#include "gnunet_dnsstub_lib.h"
/**
- * Timeout for an external (Internet-DNS) DNS resolution
- */
-#define REQUEST_TIMEOUT GNUNET_TIME_relative_multiply
(GNUNET_TIME_UNIT_SECONDS, 5)
-
-/**
* Timeout for retrying DNS queries.
*/
#define DNS_RETRANSMIT_DELAY GNUNET_TIME_relative_multiply
(GNUNET_TIME_UNIT_MILLISECONDS, 250)
+
/**
- * How many DNS sockets do we open at most at the same time?
- * (technical socket maximum is this number x2 for IPv4+IPv6)
+ * DNS Server used for resolution.
*/
-#define DNS_SOCKET_MAX 128
+struct DnsServer;
/**
@@ -81,19 +76,14 @@ struct GNUNET_DNSSTUB_RequestSocket
struct GNUNET_SCHEDULER_Task *retry_task;
/**
- * When should this request time out?
- */
- struct GNUNET_TIME_Absolute timeout;
-
- /**
- * Address we sent the DNS request to.
+ * Next address we sent the DNS request to.
*/
- struct sockaddr_storage addr;
+ struct DnsServer *ds_pos;
/**
- * Number of bytes in @e addr.
+ * Context this request executes in.
*/
- socklen_t addrlen;
+ struct GNUNET_DNSSTUB_Context *ctx;
/**
* Query we sent to @e addr.
@@ -109,6 +99,29 @@ struct GNUNET_DNSSTUB_RequestSocket
/**
+ * DNS Server used for resolution.
+ */
+struct DnsServer
+{
+
+ /**
+ * Kept in a DLL.
+ */
+ struct DnsServer *next;
+
+ /**
+ * Kept in a DLL.
+ */
+ struct DnsServer *prev;
+
+ /**
+ * IP address of the DNS resolver.
+ */
+ struct sockaddr_storage ss;
+};
+
+
+/**
* Handle to the stub resolver.
*/
struct GNUNET_DNSSTUB_Context
@@ -117,13 +130,28 @@ struct GNUNET_DNSSTUB_Context
/**
* Array of all open sockets for DNS requests.
*/
- struct GNUNET_DNSSTUB_RequestSocket sockets[DNS_SOCKET_MAX];
+ struct GNUNET_DNSSTUB_RequestSocket *sockets;
+
+ /**
+ * DLL of DNS resolvers we use.
+ */
+ struct DnsServer *dns_head;
+
+ /**
+ * DLL of DNS resolvers we use.
+ */
+ struct DnsServer *dns_tail;
+
+ /**
+ * How frequently do we retry requests?
+ */
+ struct GNUNET_TIME_Relative retry_freq;
/**
- * IP address to use for the DNS server if we are a DNS exit service
- * (for VPN via cadet); otherwise NULL.
+ * Length of @e sockets array.
*/
- char *dns_exit;
+ unsigned int num_sockets;
+
};
@@ -212,33 +240,21 @@ open_socket (int af)
/**
- * Read a DNS response from the (unhindered) UDP-Socket
- *
- * @param cls socket to read from
- */
-static void
-read_response (void *cls);
-
-
-/**
* Get a socket of the specified address family to send out a
* UDP DNS request to the Internet.
*
* @param ctx the DNSSTUB context
- * @param af desired address family
- * @return NULL on error (given AF not "supported")
+ * @return NULL on error
*/
static struct GNUNET_DNSSTUB_RequestSocket *
-get_request_socket (struct GNUNET_DNSSTUB_Context *ctx,
- int af)
+get_request_socket (struct GNUNET_DNSSTUB_Context *ctx)
{
struct GNUNET_DNSSTUB_RequestSocket *rs;
- struct GNUNET_NETWORK_FDSet *rset;
for (unsigned int i=0;i<256;i++)
{
rs = &ctx->sockets[GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
- DNS_SOCKET_MAX)];
+ ctx->num_sockets)];
if (NULL == rs->rc)
break;
}
@@ -246,25 +262,10 @@ get_request_socket (struct GNUNET_DNSSTUB_Context *ctx,
{
/* signal "failure" */
rs->rc (rs->rc_cls,
- rs,
NULL,
0);
rs->rc = NULL;
}
- rs->timeout = GNUNET_TIME_relative_to_absolute (REQUEST_TIMEOUT);
- switch (af)
- {
- case AF_INET:
- if (NULL == rs->dnsout4)
- rs->dnsout4 = open_socket (AF_INET);
- break;
- case AF_INET6:
- if (NULL == rs->dnsout6)
- rs->dnsout6 = open_socket (AF_INET6);
- break;
- default:
- return NULL;
- }
if (NULL != rs->read_task)
{
GNUNET_SCHEDULER_cancel (rs->read_task);
@@ -280,194 +281,7 @@ get_request_socket (struct GNUNET_DNSSTUB_Context *ctx,
GNUNET_free (rs->request);
rs->request = NULL;
}
- if ( (NULL == rs->dnsout4) &&
- (NULL == rs->dnsout6) )
- return NULL;
- rset = GNUNET_NETWORK_fdset_create ();
- if (NULL != rs->dnsout4)
- GNUNET_NETWORK_fdset_set (rset,
- rs->dnsout4);
- if (NULL != rs->dnsout6)
- GNUNET_NETWORK_fdset_set (rset,
- rs->dnsout6);
- rs->read_task = GNUNET_SCHEDULER_add_select
(GNUNET_SCHEDULER_PRIORITY_DEFAULT,
- REQUEST_TIMEOUT,
- rset,
- NULL,
- &read_response,
- rs);
- GNUNET_NETWORK_fdset_destroy (rset);
- return rs;
-}
-
-
-/**
- * Task to (re)transmit the DNS query, possibly repeatedly until
- * we succeed.
- *
- * @param cls our `struct GNUNET_DNSSTUB_RequestSocket *`
- */
-static void
-transmit_query (void *cls)
-{
- struct GNUNET_DNSSTUB_RequestSocket *rs = cls;
- struct GNUNET_NETWORK_Handle *ret;
-
- rs->retry_task = NULL;
- ret = (NULL != rs->dnsout4) ? rs->dnsout4 : rs->dnsout6;
- GNUNET_assert (NULL != ret);
- if (GNUNET_SYSERR ==
- GNUNET_NETWORK_socket_sendto (ret,
- rs->request,
- rs->request_len,
- (struct sockaddr *) &rs->addr,
- rs->addrlen))
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _("Failed to send DNS request to %s\n"),
- GNUNET_a2s ((struct sockaddr *) &rs->addr,
- rs->addrlen));
- else
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- _("Sent DNS request to %s\n"),
- GNUNET_a2s ((struct sockaddr *) &rs->addr,
- rs->addrlen));
- rs->retry_task = GNUNET_SCHEDULER_add_delayed (DNS_RETRANSMIT_DELAY,
- &transmit_query,
- rs);
-}
-
-
-/**
- * Perform DNS resolution.
- *
- * @param ctx stub resolver to use
- * @param sa the socket address
- * @param sa_len the length of @a sa
- * @param request DNS request to transmit
- * @param request_len number of bytes in @a request
- * @param rc function to call with result
- * @param rc_cls closure for @a rc
- * @return socket used for the request, NULL on error
- */
-struct GNUNET_DNSSTUB_RequestSocket *
-GNUNET_DNSSTUB_resolve (struct GNUNET_DNSSTUB_Context *ctx,
- const struct sockaddr *sa,
- socklen_t sa_len,
- const void *request,
- size_t request_len,
- GNUNET_DNSSTUB_ResultCallback rc,
- void *rc_cls)
-{
- struct GNUNET_DNSSTUB_RequestSocket *rs;
-
- if (NULL == (rs = get_request_socket (ctx,
- sa->sa_family)))
- return NULL;
- GNUNET_assert (NULL == rs->rc);
- GNUNET_memcpy (&rs->addr,
- sa,
- sa_len);
- rs->addrlen = sa_len;
- rs->rc = rc;
- rs->rc_cls = rc_cls;
- rs->request = GNUNET_memdup (request,
- request_len);
- rs->request_len = request_len;
- rs->retry_task = GNUNET_SCHEDULER_add_now (&transmit_query,
- rs);
- return rs;
-}
-
-
-/**
- * Perform DNS resolution using our default IP from init.
- *
- * @param ctx stub resolver to use
- * @param request DNS request to transmit
- * @param request_len number of bytes in msg
- * @param rc function to call with result
- * @param rc_cls closure for 'rc'
- * @return socket used for the request, NULL on error
- */
-struct GNUNET_DNSSTUB_RequestSocket *
-GNUNET_DNSSTUB_resolve2 (struct GNUNET_DNSSTUB_Context *ctx,
- const void *request,
- size_t request_len,
- GNUNET_DNSSTUB_ResultCallback rc,
- void *rc_cls)
-{
- int af;
- struct sockaddr_in v4;
- struct sockaddr_in6 v6;
- struct sockaddr *sa;
- socklen_t salen;
- struct GNUNET_NETWORK_Handle *dnsout;
- struct GNUNET_DNSSTUB_RequestSocket *rs;
-
- memset (&v4, 0, sizeof (v4));
- memset (&v6, 0, sizeof (v6));
- if (1 == inet_pton (AF_INET,
- ctx->dns_exit,
- &v4.sin_addr))
- {
- salen = sizeof (v4);
- v4.sin_family = AF_INET;
- v4.sin_port = htons (53);
-#if HAVE_SOCKADDR_IN_SIN_LEN
- v4.sin_len = (u_char) salen;
-#endif
- sa = (struct sockaddr *) &v4;
- af = AF_INET;
- }
- else if (1 == inet_pton (AF_INET6,
- ctx->dns_exit,
- &v6.sin6_addr))
- {
- salen = sizeof (v6);
- v6.sin6_family = AF_INET6;
- v6.sin6_port = htons (53);
-#if HAVE_SOCKADDR_IN_SIN_LEN
- v6.sin6_len = (u_char) salen;
-#endif
- sa = (struct sockaddr *) &v6;
- af = AF_INET6;
- }
- else
- {
- GNUNET_break (0);
- return NULL;
- }
- if (NULL == (rs = get_request_socket (ctx,
- af)))
- return NULL;
- GNUNET_assert (NULL == rs->rc);
- if (NULL != rs->dnsout4)
- dnsout = rs->dnsout4;
- else
- dnsout = rs->dnsout6;
- if (NULL == dnsout)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Configured DNS exit `%s' is not working / valid.\n"),
- ctx->dns_exit);
- return NULL;
- }
- GNUNET_memcpy (&rs->addr,
- sa,
- salen);
- rs->addrlen = salen;
- rs->rc = rc;
- rs->rc_cls = rc_cls;
- if (GNUNET_SYSERR ==
- GNUNET_NETWORK_socket_sendto (dnsout,
- request,
- request_len,
- sa,
- salen))
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _("Failed to send DNS request to %s\n"),
- GNUNET_a2s (sa, salen));
- rs->timeout = GNUNET_TIME_relative_to_absolute (REQUEST_TIMEOUT);
+ rs->ctx = ctx;
return rs;
}
@@ -484,9 +298,7 @@ static int
do_dns_read (struct GNUNET_DNSSTUB_RequestSocket *rs,
struct GNUNET_NETWORK_Handle *dnsout)
{
- struct sockaddr_storage addr;
- socklen_t addrlen;
- struct GNUNET_TUN_DnsHeader *dns;
+ struct GNUNET_DNSSTUB_Context *ctx = rs->ctx;
ssize_t r;
int len;
@@ -507,9 +319,15 @@ do_dns_read (struct GNUNET_DNSSTUB_RequestSocket *rs,
len);
{
unsigned char buf[len] GNUNET_ALIGN;
+ int found;
+ struct sockaddr_storage addr;
+ socklen_t addrlen;
+ struct GNUNET_TUN_DnsHeader *dns;
addrlen = sizeof (addr);
- memset (&addr, 0, sizeof (addr));
+ memset (&addr,
+ 0,
+ sizeof (addr));
r = GNUNET_NETWORK_socket_recvfrom (dnsout,
buf,
sizeof (buf),
@@ -522,6 +340,24 @@ do_dns_read (struct GNUNET_DNSSTUB_RequestSocket *rs,
GNUNET_NETWORK_socket_close (dnsout);
return GNUNET_SYSERR;
}
+ found = GNUNET_NO;
+ for (struct DnsServer *ds = ctx->dns_head; NULL != ds; ds = ds->next)
+ {
+ if (0 == memcmp (&addr,
+ &ds->ss,
+ GNUNET_MIN (sizeof (struct sockaddr_storage),
+ addrlen)))
+ {
+ found = GNUNET_YES;
+ break;
+ }
+ }
+ if (GNUNET_NO == found)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received DNS response from server we never asked (ignored)");
+ return GNUNET_NO;
+ }
if (sizeof (struct GNUNET_TUN_DnsHeader) > r)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -530,22 +366,15 @@ do_dns_read (struct GNUNET_DNSSTUB_RequestSocket *rs,
return GNUNET_NO;
}
dns = (struct GNUNET_TUN_DnsHeader *) buf;
- if ( (addrlen != rs->addrlen) ||
- (GNUNET_YES !=
- GNUNET_TUN_sockaddr_cmp ((struct sockaddr *) &rs->addr,
- (struct sockaddr *) &addr,
- GNUNET_YES)) ||
- (0 == GNUNET_TIME_absolute_get_remaining (rs->timeout).rel_value_us) )
+ if (NULL == rs->rc)
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Request timeout or invalid sender address; ignoring
reply\n");
+ "Request timeout or cancelled; ignoring reply\n");
return GNUNET_NO;
}
- if (NULL != rs->rc)
- rs->rc (rs->rc_cls,
- rs,
- dns,
- r);
+ rs->rc (rs->rc_cls,
+ dns,
+ r);
}
return GNUNET_OK;
}
@@ -557,44 +386,21 @@ do_dns_read (struct GNUNET_DNSSTUB_RequestSocket *rs,
* @param cls socket to read from
*/
static void
-read_response (void *cls)
+read_response (void *cls);
+
+
+/**
+ * Schedule #read_response() task for @a rs.
+ *
+ * @param rs request to schedule read operation for
+ */
+static void
+schedule_read (struct GNUNET_DNSSTUB_RequestSocket *rs)
{
- struct GNUNET_DNSSTUB_RequestSocket *rs = cls;
struct GNUNET_NETWORK_FDSet *rset;
- const struct GNUNET_SCHEDULER_TaskContext *tc;
-
- rs->read_task = NULL;
- tc = GNUNET_SCHEDULER_get_task_context ();
- if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY))
- {
- /* signal "failure" (from timeout) */
- if (NULL != rs->rc)
- {
- rs->rc (rs->rc_cls,
- rs,
- NULL,
- 0);
- rs->rc = NULL;
- }
- /* timeout */
- cleanup_rs (rs);
- return;
- }
- /* read and process ready sockets */
- if ((NULL != rs->dnsout4) &&
- (GNUNET_NETWORK_fdset_isset (tc->read_ready,
- rs->dnsout4)) &&
- (GNUNET_SYSERR == do_dns_read (rs,
- rs->dnsout4)))
- rs->dnsout4 = NULL;
- if ((NULL != rs->dnsout6) &&
- (GNUNET_NETWORK_fdset_isset (tc->read_ready,
- rs->dnsout6)) &&
- (GNUNET_SYSERR == do_dns_read (rs,
- rs->dnsout6)))
- rs->dnsout6 = NULL;
- /* re-schedule read task */
+ if (NULL != rs->read_task)
+ GNUNET_SCHEDULER_cancel (rs->read_task);
rset = GNUNET_NETWORK_fdset_create ();
if (NULL != rs->dnsout4)
GNUNET_NETWORK_fdset_set (rset,
@@ -603,7 +409,7 @@ read_response (void *cls)
GNUNET_NETWORK_fdset_set (rset,
rs->dnsout6);
rs->read_task = GNUNET_SCHEDULER_add_select
(GNUNET_SCHEDULER_PRIORITY_DEFAULT,
-
GNUNET_TIME_absolute_get_remaining (rs->timeout),
+ GNUNET_TIME_UNIT_FOREVER_REL,
rset,
NULL,
&read_response,
@@ -613,6 +419,151 @@ read_response (void *cls)
/**
+ * Read a DNS response from the (unhindered) UDP-Socket
+ *
+ * @param cls `struct GNUNET_DNSSTUB_RequestSocket` to read from
+ */
+static void
+read_response (void *cls)
+{
+ struct GNUNET_DNSSTUB_RequestSocket *rs = cls;
+ const struct GNUNET_SCHEDULER_TaskContext *tc;
+
+ rs->read_task = NULL;
+ tc = GNUNET_SCHEDULER_get_task_context ();
+ /* read and process ready sockets */
+ if ( (NULL != rs->dnsout4) &&
+ (GNUNET_NETWORK_fdset_isset (tc->read_ready,
+ rs->dnsout4)) &&
+ (GNUNET_SYSERR ==
+ do_dns_read (rs,
+ rs->dnsout4)) )
+ rs->dnsout4 = NULL;
+ if ( (NULL != rs->dnsout6) &&
+ (GNUNET_NETWORK_fdset_isset (tc->read_ready,
+ rs->dnsout6)) &&
+ (GNUNET_SYSERR ==
+ do_dns_read (rs,
+ rs->dnsout6)) )
+ rs->dnsout6 = NULL;
+ /* re-schedule read task */
+ schedule_read (rs);
+}
+
+
+/**
+ * Task to (re)transmit the DNS query, possibly repeatedly until
+ * we succeed.
+ *
+ * @param cls our `struct GNUNET_DNSSTUB_RequestSocket *`
+ */
+static void
+transmit_query (void *cls)
+{
+ struct GNUNET_DNSSTUB_RequestSocket *rs = cls;
+ struct GNUNET_DNSSTUB_Context *ctx = rs->ctx;
+ const struct sockaddr *sa;
+ socklen_t salen;
+ struct DnsServer *ds;
+ struct GNUNET_NETWORK_Handle *dnsout;
+
+ rs->retry_task = GNUNET_SCHEDULER_add_delayed (ctx->retry_freq,
+ &transmit_query,
+ rs);
+ ds = rs->ds_pos;
+ rs->ds_pos = ds->next;
+ if (NULL == rs->ds_pos)
+ rs->ds_pos = ctx->dns_head;
+ GNUNET_assert (NULL != ds);
+ dnsout = NULL;
+ switch (ds->ss.ss_family)
+ {
+ case AF_INET:
+ if (NULL == rs->dnsout4)
+ rs->dnsout4 = open_socket (AF_INET);
+ dnsout = rs->dnsout4;
+ sa = (const struct sockaddr *) &ds->ss;
+ salen = sizeof (struct sockaddr_in);
+ break;
+ case AF_INET6:
+ if (NULL == rs->dnsout6)
+ rs->dnsout6 = open_socket (AF_INET6);
+ dnsout = rs->dnsout6;
+ sa = (const struct sockaddr *) &ds->ss;
+ salen = sizeof (struct sockaddr_in6);
+ break;
+ default:
+ return;
+ }
+ if (NULL == dnsout)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unable to use configure DNS server, skipping\n");
+ return;
+ }
+ if (GNUNET_SYSERR ==
+ GNUNET_NETWORK_socket_sendto (dnsout,
+ rs->request,
+ rs->request_len,
+ sa,
+ salen))
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("Failed to send DNS request to %s\n"),
+ GNUNET_a2s (sa,
+ salen));
+ else
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ _("Sent DNS request to %s\n"),
+ GNUNET_a2s (sa,
+ salen));
+ schedule_read (rs);
+}
+
+
+/**
+ * Perform DNS resolution using our default IP from init.
+ *
+ * @param ctx stub resolver to use
+ * @param request DNS request to transmit
+ * @param request_len number of bytes in msg
+ * @param rc function to call with result
+ * @param rc_cls closure for 'rc'
+ * @return socket used for the request, NULL on error
+ */
+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)
+{
+ struct GNUNET_DNSSTUB_RequestSocket *rs;
+
+ if (NULL == ctx->dns_head)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "No DNS server configured for resolution\n");
+ return NULL;
+ }
+ if (NULL == (rs = get_request_socket (ctx)))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "No request socket available for DNS resolution\n");
+ return NULL;
+ }
+ rs->ds_pos = ctx->dns_head;
+ rs->rc = rc;
+ rs->rc_cls = rc_cls;
+ rs->request = GNUNET_memdup (request,
+ request_len);
+ rs->request_len = request_len;
+ rs->retry_task = GNUNET_SCHEDULER_add_now (&transmit_query,
+ rs);
+ return rs;
+}
+
+
+/**
* Cancel DNS resolution.
*
* @param rs resolution to cancel
@@ -626,28 +577,153 @@ GNUNET_DNSSTUB_resolve_cancel (struct
GNUNET_DNSSTUB_RequestSocket *rs)
GNUNET_SCHEDULER_cancel (rs->retry_task);
rs->retry_task = NULL;
}
+ if (NULL != rs->read_task)
+ {
+ GNUNET_SCHEDULER_cancel (rs->read_task);
+ rs->read_task = NULL;
+ }
}
/**
* Start a DNS stub resolver.
*
- * @param dns_ip target IP address to use
+ * @param num_sockets how many sockets should we open
+ * in parallel for DNS queries for this stub?
* @return NULL on error
*/
struct GNUNET_DNSSTUB_Context *
-GNUNET_DNSSTUB_start (const char *dns_ip)
+GNUNET_DNSSTUB_start (unsigned int num_sockets)
{
struct GNUNET_DNSSTUB_Context *ctx;
+ if (0 == num_sockets)
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
ctx = GNUNET_new (struct GNUNET_DNSSTUB_Context);
- if (NULL != dns_ip)
- ctx->dns_exit = GNUNET_strdup (dns_ip);
+ ctx->num_sockets = num_sockets;
+ ctx->sockets = GNUNET_new_array (num_sockets,
+ struct GNUNET_DNSSTUB_RequestSocket);
+ ctx->retry_freq = DNS_RETRANSMIT_DELAY;
return ctx;
}
/**
+ * Add nameserver for use by the DNSSTUB. We will use
+ * all provided nameservers for resolution (round-robin).
+ *
+ * @param ctx resolver context to modify
+ * @param dns_ip target IP address to use (as string)
+ * @return #GNUNET_OK on success
+ */
+int
+GNUNET_DNSSTUB_add_dns_ip (struct GNUNET_DNSSTUB_Context *ctx,
+ const char *dns_ip)
+{
+ struct DnsServer *ds;
+ struct in_addr i4;
+ struct in6_addr i6;
+
+ ds = GNUNET_new (struct DnsServer);
+ if (1 == inet_pton (AF_INET,
+ dns_ip,
+ &i4))
+ {
+ struct sockaddr_in *s4 = (struct sockaddr_in *) &ds->ss;
+
+ s4->sin_family = AF_INET;
+ s4->sin_port = htons (53);
+ s4->sin_addr = i4;
+#if HAVE_SOCKADDR_IN_SIN_LEN
+ s4->sin_len = (u_char) sizeof (struct sockaddr_in);
+#endif
+ }
+ else if (1 == inet_pton (AF_INET6,
+ dns_ip,
+ &i6))
+ {
+ struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) &ds->ss;
+
+ s6->sin6_family = AF_INET6;
+ s6->sin6_port = htons (53);
+ s6->sin6_addr = i6;
+#if HAVE_SOCKADDR_IN_SIN_LEN
+ s6->sin6_len = (u_char) sizeof (struct sockaddr_in6);
+#endif
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Malformed IP address `%s' for DNS server\n",
+ dns_ip);
+ GNUNET_free (ds);
+ return GNUNET_SYSERR;
+ }
+ GNUNET_CONTAINER_DLL_insert (ctx->dns_head,
+ ctx->dns_tail,
+ ds);
+ return GNUNET_OK;
+}
+
+
+/**
+ * Add nameserver for use by the DNSSTUB. We will use
+ * all provided nameservers for resolution (round-robin).
+ *
+ * @param ctx resolver context to modify
+ * @param sa socket address of DNS resolver to use
+ * @return #GNUNET_OK on success
+ */
+int
+GNUNET_DNSSTUB_add_dns_sa (struct GNUNET_DNSSTUB_Context *ctx,
+ const struct sockaddr *sa)
+{
+ struct DnsServer *ds;
+
+ ds = GNUNET_new (struct DnsServer);
+ switch (sa->sa_family)
+ {
+ case AF_INET:
+ memcpy (&ds->ss,
+ sa,
+ sizeof (struct sockaddr_in));
+ break;
+ case AF_INET6:
+ memcpy (&ds->ss,
+ sa,
+ sizeof (struct sockaddr_in6));
+ break;
+ default:
+ GNUNET_break (0);
+ GNUNET_free (ds);
+ return GNUNET_SYSERR;
+ }
+ GNUNET_CONTAINER_DLL_insert (ctx->dns_head,
+ ctx->dns_tail,
+ ds);
+ return GNUNET_OK;
+}
+
+
+/**
+ * How long should we try requests before timing out?
+ * Only effective for requests issued after this call.
+ *
+ * @param ctx resolver context to modify
+ * @param retry_freq how long to wait between retries
+ */
+void
+GNUNET_DNSSTUB_set_retry (struct GNUNET_DNSSTUB_Context *ctx,
+ struct GNUNET_TIME_Relative retry_freq)
+{
+ ctx->retry_freq = retry_freq;
+}
+
+
+/**
* Cleanup DNSSTUB resolver.
*
* @param ctx stub resolver to clean up
@@ -655,15 +731,18 @@ GNUNET_DNSSTUB_start (const char *dns_ip)
void
GNUNET_DNSSTUB_stop (struct GNUNET_DNSSTUB_Context *ctx)
{
- unsigned int i;
+ struct DnsServer *ds;
- for (i=0;i<DNS_SOCKET_MAX;i++)
- cleanup_rs (&ctx->sockets[i]);
- if (NULL != ctx->dns_exit)
+ while (NULL != (ds = ctx->dns_head))
{
- GNUNET_free (ctx->dns_exit);
- ctx->dns_exit = NULL;
+ GNUNET_CONTAINER_DLL_remove (ctx->dns_head,
+ ctx->dns_tail,
+ ds);
+ GNUNET_free (ds);
}
+ for (unsigned int i=0;i<ctx->num_sockets;i++)
+ cleanup_rs (&ctx->sockets[i]);
+ GNUNET_free (ctx->sockets);
GNUNET_free (ctx);
}
diff --git a/src/dns/gnunet-service-dns.c b/src/dns/gnunet-service-dns.c
index 9feaa8413..39ce7f6e5 100644
--- a/src/dns/gnunet-service-dns.c
+++ b/src/dns/gnunet-service-dns.c
@@ -508,13 +508,11 @@ send_request_to_client (struct RequestRecord *rr,
* succeeded.
*
* @param cls NULL
- * @param rs the socket that received the response
* @param dns the response itself
* @param r number of bytes in dns
*/
static void
process_dns_result (void *cls,
- struct GNUNET_DNSSTUB_RequestSocket *rs,
const struct GNUNET_TUN_DnsHeader *dns,
size_t r);
@@ -530,7 +528,6 @@ next_phase (struct RequestRecord *rr)
{
struct ClientRecord *cr;
int nz;
- socklen_t salen;
if (rr->phase == RP_DROP)
{
@@ -582,22 +579,27 @@ next_phase (struct RequestRecord *rr)
next_phase (rr);
return;
case RP_QUERY:
+#if 0
+ /* TODO: optionally, use this to forward DNS requests to the
+ *original* DNS server instead of the one we have configured...
+ (but then we need to create a fresh dnsstub for each request
+ *and* manage the timeout) */
switch (rr->dst_addr.ss_family)
{
case AF_INET:
salen = sizeof (struct sockaddr_in);
+ sa = (const struct sockaddr *) &rr->dst_addr;
break;
case AF_INET6:
salen = sizeof (struct sockaddr_in6);
+ sa = (const struct sockaddr *) &rr->dst_addr;
break;
default:
GNUNET_assert (0);
}
-
+#endif
rr->phase = RP_INTERNET_DNS;
rr->rs = GNUNET_DNSSTUB_resolve (dnsstub,
- (struct sockaddr*) &rr->dst_addr,
- salen,
rr->payload,
rr->payload_length,
&process_dns_result,
@@ -714,13 +716,11 @@ client_disconnect_cb (void *cls,
* succeeded.
*
* @param cls NULL
- * @param rs the socket that received the response
* @param dns the response itself
* @param r number of bytes in dns
*/
static void
process_dns_result (void *cls,
- struct GNUNET_DNSSTUB_RequestSocket *rs,
const struct GNUNET_TUN_DnsHeader *dns,
size_t r)
{
@@ -733,8 +733,7 @@ process_dns_result (void *cls,
return; /* ignore */
rr = &requests[dns->id];
- if ( (rr->phase != RP_INTERNET_DNS) ||
- (rr->rs != rs) )
+ if (rr->phase != RP_INTERNET_DNS)
{
/* unexpected / bogus reply */
GNUNET_STATISTICS_update (stats,
@@ -1055,8 +1054,6 @@ run (void *cls,
char *ipv4mask;
char *ipv6addr;
char *ipv6prefix;
- struct in_addr dns_exit4;
- struct in6_addr dns_exit6;
char *dns_exit;
char *binary;
int nortsetup;
@@ -1065,24 +1062,26 @@ run (void *cls,
stats = GNUNET_STATISTICS_create ("dns", cfg);
GNUNET_SCHEDULER_add_shutdown (&cleanup_task,
cls);
+ dnsstub = GNUNET_DNSSTUB_start (128);
+ /* TODO: support multiple DNS_EXIT servers being configured */
+ /* TODO: see above TODO on using DNS server from original packet.
+ Not sure which is best... */
dns_exit = NULL;
- if ( ( (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (cfg,
- "dns",
- "DNS_EXIT",
- &dns_exit)) ||
- ( (1 != inet_pton (AF_INET, dns_exit, &dns_exit4)) &&
- (1 != inet_pton (AF_INET6, dns_exit, &dns_exit6)) ) ) )
+ if ( (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_string (cfg,
+ "dns",
+ "DNS_EXIT",
+ &dns_exit)) ||
+ (GNUNET_OK !=
+ GNUNET_DNSSTUB_add_dns_ip (dnsstub,
+ dns_exit)) )
{
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
"dns",
"DNS_EXIT",
_("need a valid IPv4 or IPv6 address\n"));
GNUNET_free_non_null (dns_exit);
- dns_exit = NULL;
}
- dnsstub = GNUNET_DNSSTUB_start (dns_exit);
- GNUNET_free_non_null (dns_exit);
binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-dns");
if (GNUNET_YES !=
GNUNET_OS_check_helper_binary (binary,
diff --git a/src/dns/gnunet-zoneimport.c b/src/dns/gnunet-zoneimport.c
index 914868af4..860672e7a 100644
--- a/src/dns/gnunet-zoneimport.c
+++ b/src/dns/gnunet-zoneimport.c
@@ -290,13 +290,11 @@ process_record (struct Request *req,
* Function called with the result of a DNS resolution.
*
* @param cls closure with the `struct Request`
- * @param rs socket that received the response
* @param dns dns response, never NULL
* @param dns_len number of bytes in @a dns
*/
static void
process_result (void *cls,
- struct GNUNET_DNSSTUB_RequestSocket *rs,
const struct GNUNET_TUN_DnsHeader *dns,
size_t dns_len)
{
@@ -407,11 +405,11 @@ submit_req (struct Request *req)
(pending >= THRESH) )
return GNUNET_SYSERR;
GNUNET_assert (NULL == req->rs);
- req->rs = GNUNET_DNSSTUB_resolve2 (ctx,
- req->raw,
- req->raw_len,
- &process_result,
- req);
+ req->rs = GNUNET_DNSSTUB_resolve (ctx,
+ req->raw,
+ req->raw_len,
+ &process_result,
+ req);
GNUNET_assert (NULL != req->rs);
req->issue_num++;
last_request = now;
@@ -561,13 +559,23 @@ main (int argc,
"Missing required configuration argument\n");
return -1;
}
- ctx = GNUNET_DNSSTUB_start (argv[1]);
+ ctx = GNUNET_DNSSTUB_start (256);
if (NULL == ctx)
{
fprintf (stderr,
"Failed to initialize GNUnet DNS STUB\n");
return 1;
}
+ if (GNUNET_OK !=
+ GNUNET_DNSSTUB_add_dns_ip (ctx,
+ argv[1]))
+ {
+ fprintf (stderr,
+ "Failed to use `%s' for DNS resolver\n",
+ argv[1]);
+ return 1;
+ }
+
while (NULL !=
fgets (hn,
sizeof (hn),
diff --git a/src/exit/gnunet-daemon-exit.c b/src/exit/gnunet-daemon-exit.c
index 0b3cc505a..5cb1ebfd9 100644
--- a/src/exit/gnunet-daemon-exit.c
+++ b/src/exit/gnunet-daemon-exit.c
@@ -458,13 +458,11 @@ GNUNET_NETWORK_STRUCT_END
* succeeded.
*
* @param cls NULL
- * @param rs the socket that received the response
* @param dns the response itself
* @param r number of bytes in @a dns
*/
static void
process_dns_result (void *cls,
- struct GNUNET_DNSSTUB_RequestSocket *rs,
const struct GNUNET_TUN_DnsHeader *dns,
size_t r)
{
@@ -479,8 +477,7 @@ process_dns_result (void *cls,
return;
/* Handle case that this is a reply to a request from a CADET DNS channel */
ts = channels[dns->id];
- if ( (NULL == ts) ||
- (ts->specifics.dns.rs != rs) )
+ if (NULL == ts)
return;
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Got a response from the stub resolver for DNS request received via
CADET!\n");
@@ -557,11 +554,11 @@ handle_dns_request (void *cls,
dlen);
dout = (struct GNUNET_TUN_DnsHeader *) buf;
dout->id = ts->specifics.dns.my_id;
- ts->specifics.dns.rs = GNUNET_DNSSTUB_resolve2 (dnsstub,
- buf,
- dlen,
- &process_dns_result,
- NULL);
+ ts->specifics.dns.rs = GNUNET_DNSSTUB_resolve (dnsstub,
+ buf,
+ dlen,
+ &process_dns_result,
+ NULL);
if (NULL == ts->specifics.dns.rs)
{
GNUNET_break_op (0);
@@ -3545,25 +3542,23 @@ advertise_dns_exit ()
};
char *dns_exit;
struct GNUNET_HashCode port;
- struct in_addr dns_exit4;
- struct in6_addr dns_exit6;
if (GNUNET_YES !=
GNUNET_CONFIGURATION_get_value_yesno (cfg,
"exit",
"EXIT_DNS"))
return;
+ GNUNET_assert (NULL != (dnsstub = GNUNET_DNSSTUB_start (128)));
+ dns_exit = NULL;
+ /* TODO: support using multiple DNS resolvers */
if ( (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_string (cfg,
"exit",
"DNS_RESOLVER",
&dns_exit)) ||
- ( (1 != inet_pton (AF_INET,
- dns_exit,
- &dns_exit4)) &&
- (1 != inet_pton (AF_INET6,
- dns_exit,
- &dns_exit6)) ) )
+ (GNUNET_OK !=
+ GNUNET_DNSSTUB_add_dns_ip (dnsstub,
+ dns_exit)) )
{
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
"dns",
diff --git a/src/gns/gnunet-dns2gns.c b/src/gns/gnunet-dns2gns.c
index 47cc6dde0..bc66f1325 100644
--- a/src/gns/gnunet-dns2gns.c
+++ b/src/gns/gnunet-dns2gns.c
@@ -247,19 +247,16 @@ do_timeout (void *cls)
* Iterator called on obtained result for a DNS lookup
*
* @param cls closure
- * @param rs the request socket
* @param dns the DNS udp payload
* @param r size of the DNS payload
*/
static void
dns_result_processor (void *cls,
- struct GNUNET_DNSSTUB_RequestSocket *rs,
const struct GNUNET_TUN_DnsHeader *dns,
size_t r)
{
struct Request *request = cls;
- (void) rs;
if (NULL == dns)
{
/* DNSSTUB gave up, so we trigger timeout early */
@@ -307,11 +304,11 @@ result_processor (void *cls,
request->original_request_id = request->packet->id;
GNUNET_DNSPARSER_free_packet (request->packet);
request->packet = NULL;
- request->dns_lookup = GNUNET_DNSSTUB_resolve2 (dns_stub,
- request->udp_msg,
- request->udp_msg_size,
- &dns_result_processor,
- request);
+ request->dns_lookup = GNUNET_DNSSTUB_resolve (dns_stub,
+ request->udp_msg,
+ request->udp_msg_size,
+ &dns_result_processor,
+ request);
return;
}
packet = request->packet;
@@ -594,8 +591,12 @@ run (void *cls,
NULL);
if (NULL == (gns = GNUNET_GNS_connect (cfg)))
return;
- if (NULL == (dns_stub = GNUNET_DNSSTUB_start (dns_ip)))
+ GNUNET_assert (NULL != (dns_stub = GNUNET_DNSSTUB_start (128)));
+ if (GNUNET_OK !=
+ GNUNET_DNSSTUB_add_dns_ip (dns_stub,
+ dns_ip))
{
+ GNUNET_DNSSTUB_stop (dns_stub);
GNUNET_GNS_disconnect (gns);
gns = NULL;
return;
diff --git a/src/gns/gnunet-service-gns_resolver.c
b/src/gns/gnunet-service-gns_resolver.c
index 94819b040..74eb47f29 100644
--- a/src/gns/gnunet-service-gns_resolver.c
+++ b/src/gns/gnunet-service-gns_resolver.c
@@ -72,6 +72,57 @@
* DLL to hold the authority chain we had to pass in the resolution
* process.
*/
+struct AuthorityChain;
+
+
+/**
+ * Element of a resolution process for looking up the
+ * responsible DNS server hostname in a GNS2DNS recursive
+ * resolution.
+ */
+struct Gns2DnsPending
+{
+
+ /**
+ * Kept in a DLL.
+ */
+ struct Gns2DnsPending *next;
+
+ /**
+ * Kept in a DLL.
+ */
+ struct Gns2DnsPending *prev;
+
+ /**
+ * Context this activity belongs with.
+ */
+ struct AuthorityChain *ac;
+
+ /**
+ * Handle for the resolution of the IP part of the
+ * GNS2DNS record. Will return to us the addresses
+ * of the DNS resolver to use.
+ */
+ struct GNS_ResolverHandle *rh;
+
+ /**
+ * Handle for DNS resolution of the DNS nameserver.
+ */
+ struct GNUNET_RESOLVER_RequestHandle *dns_rh;
+};
+
+
+/**
+ * Handle to a currenty pending resolution. On result (positive or
+ * negative) the #GNS_ResultProcessor is called.
+ */
+struct GNS_ResolverHandle;
+
+
+/**
+ * DLL to hold the authority chain we had to pass in the resolution
+ * process.
+ */
struct AuthorityChain
{
/**
@@ -131,11 +182,32 @@ struct AuthorityChain
char name[GNUNET_DNSPARSER_MAX_NAME_LENGTH + 1];
/**
- * IP address of the DNS resolver that is authoritative.
- * (this implementation currently only supports one
- * IP at a time).
+ * List of resolutions of the 'ip' of the name server that
+ * are still pending.
+ */
+ struct Gns2DnsPending *gp_head;
+
+ /**
+ * Tail of list of resolutions of the 'ip' of the name server that
+ * are still pending.
+ */
+ struct Gns2DnsPending *gp_tail;
+
+ /**
+ * Handle to perform DNS lookups with this authority (in GNS2DNS
handling).
+ */
+ struct GNUNET_DNSSTUB_Context *dns_handle;
+
+ /**
+ * Did we succeed in getting an IP address for *any* of the DNS servers
listed?
+ * Once we do, we can start with DNS queries.
+ */
+ int found;
+
+ /**
+ * Did we start the recursive resolution via DNS?
*/
- struct sockaddr_storage dns_ip;
+ int launched;
} dns_authority;
@@ -218,34 +290,6 @@ struct VpnContext
/**
- * Information we keep during the resolution of an
- * IP address for a DNS server while handling a
- * GNS2DNS record.
- */
-struct Gns2DnsContext
-{
-
- /**
- * DNS domain in which the resolution will continue
- * (first part of the GNS2DNS record).
- */
- char *ns;
-
- /**
- * Handle for the resolution of the IP part of the
- * GNS2DNS record. Will return to us the addresses
- * of the DNS resolver to use.
- */
- struct GNS_ResolverHandle *rh;
-
- /**
- * Handle for DNS resolution of the DNS nameserver.
- */
- struct GNUNET_RESOLVER_RequestHandle *dns_rh;
-};
-
-
-/**
* Handle to a currenty pending resolution. On result (positive or
* negative) the #GNS_ResultProcessor is called.
*/
@@ -278,12 +322,6 @@ struct GNS_ResolverHandle
void* proc_cls;
/**
- * Handle used during GNS2DNS resolution for looking up the
- * IP address of the DNS server.
- */
- struct Gns2DnsContext *g2dc;
-
- /**
* Handle for DHT lookups. should be NULL if no lookups are in progress
*/
struct GNUNET_DHT_GetHandle *get_handle;
@@ -431,11 +469,6 @@ static struct GNUNET_VPN_Handle *vpn_handle;
static struct GNUNET_DHT_Handle *dht_handle;
/**
- * Handle to perform DNS lookups.
- */
-static struct GNUNET_DNSSTUB_Context *dns_handle;
-
-/**
* Heap for limiting parallel DHT lookups
*/
static struct GNUNET_CONTAINER_Heap *dht_lookup_heap;
@@ -543,21 +576,53 @@ translate_dot_plus (struct GNS_ResolverHandle *rh,
/**
- * Task scheduled to asynchronously fail a resolution.
+ * Wrapper around #GNS_resolver_lookup_cancel() as a task.
+ * Used for delayed cleanup so we can unwind the stack first.
*
- * @param cls the 'struct GNS_ResolverHandle' of the resolution to fail
+ * @param cls the `struct GNS_ResolverHandle`
*/
static void
-fail_resolution (void *cls)
+GNS_resolver_lookup_cancel_ (void *cls)
{
struct GNS_ResolverHandle *rh = cls;
rh->task_id = NULL;
- rh->proc (rh->proc_cls, 0, NULL);
GNS_resolver_lookup_cancel (rh);
}
+/**
+ * Function called to asynchronously fail a resolution.
+ *
+ * @param rh the resolution to fail
+ */
+static void
+fail_resolution (struct GNS_ResolverHandle *rh)
+{
+ rh->proc (rh->proc_cls,
+ 0,
+ NULL);
+ GNUNET_assert (NULL == rh->task_id);
+ rh->task_id = GNUNET_SCHEDULER_add_now (&GNS_resolver_lookup_cancel_,
+ rh);
+}
+
+
+/**
+ * Function called when a resolution times out.
+ *
+ * @param cls the `struct GNS_ResolverHandle`
+ */
+static void
+timeout_resolution (void *cls)
+{
+ struct GNS_ResolverHandle *rh = cls;
+
+ rh->task_id = NULL;
+ fail_resolution (rh);
+}
+
+
#if (defined WINDOWS) || (defined DARWIN)
/* Don't have this on W32, here's a naive implementation
* Was somehow removed on OS X ... */
@@ -831,13 +896,11 @@ start_resolver_lookup (void *cls);
*
* @param cls the request handle of the resolution that
* we were attempting to make
- * @param rs socket that received the response
* @param dns dns response, never NULL
* @param dns_len number of bytes in @a dns
*/
static void
dns_result_parser (void *cls,
- struct GNUNET_DNSSTUB_RequestSocket *rs,
const struct GNUNET_TUN_DnsHeader *dns,
size_t dns_len)
{
@@ -845,18 +908,13 @@ dns_result_parser (void *cls,
struct GNUNET_DNSPARSER_Packet *p;
const struct GNUNET_DNSPARSER_Record *rec;
unsigned int rd_count;
- unsigned int i;
- (void) rs;
if (NULL == dns)
{
rh->dns_request = NULL;
GNUNET_SCHEDULER_cancel (rh->task_id);
rh->task_id = NULL;
- rh->proc (rh->proc_cls,
- 0,
- NULL);
- GNS_resolver_lookup_cancel (rh);
+ fail_resolution (rh);
return;
}
if (rh->original_dns_id != dns->id)
@@ -872,6 +930,8 @@ dns_result_parser (void *cls,
_("Failed to parse DNS response\n"));
return;
}
+
+ /* We got a result from DNS */
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Received DNS response for `%s' with %u answers\n",
rh->ac_tail->label,
@@ -920,8 +980,10 @@ dns_result_parser (void *cls,
buf_off = 0;
skip = 0;
- memset (rd, 0, sizeof (rd));
- for (i=0;i<rd_count;i++)
+ memset (rd,
+ 0,
+ sizeof (rd));
+ for (unsigned int i=0;i<rd_count;i++)
{
if (i < p->num_answers)
rec = &p->answers[i];
@@ -1043,9 +1105,12 @@ dns_result_parser (void *cls,
rh->proc (rh->proc_cls,
rd_count - skip,
rd);
- GNS_resolver_lookup_cancel (rh);
}
GNUNET_DNSPARSER_free_packet (p);
+ if (NULL != rh->task_id)
+ GNUNET_SCHEDULER_cancel (rh->task_id); /* should be timeout task */
+ rh->task_id = GNUNET_SCHEDULER_add_now (&GNS_resolver_lookup_cancel_,
+ rh);
}
@@ -1061,7 +1126,6 @@ static void
recursive_dns_resolution (struct GNS_ResolverHandle *rh)
{
struct AuthorityChain *ac;
- socklen_t sa_len;
struct GNUNET_DNSPARSER_Query *query;
struct GNUNET_DNSPARSER_Packet *p;
char *dns_request;
@@ -1074,20 +1138,6 @@ recursive_dns_resolution (struct GNS_ResolverHandle *rh)
"Starting DNS lookup for `%s'\n",
ac->label);
GNUNET_assert (GNUNET_NO == ac->gns_authority);
- switch (((const struct sockaddr *)
&ac->authority_info.dns_authority.dns_ip)->sa_family)
- {
- case AF_INET:
- sa_len = sizeof (struct sockaddr_in);
- break;
- case AF_INET6:
- sa_len = sizeof (struct sockaddr_in6);
- break;
- default:
- GNUNET_break (0);
- rh->proc (rh->proc_cls, 0, NULL);
- GNS_resolver_lookup_cancel (rh);
- return;
- }
query = GNUNET_new (struct GNUNET_DNSPARSER_Query);
query->name = GNUNET_strdup (ac->label);
query->type = rh->record_type;
@@ -1109,20 +1159,22 @@ recursive_dns_resolution (struct GNS_ResolverHandle *rh)
rh->proc (rh->proc_cls,
0,
NULL);
- GNS_resolver_lookup_cancel (rh);
+ GNUNET_assert (NULL == rh->task_id);
+ rh->task_id = GNUNET_SCHEDULER_add_now (&GNS_resolver_lookup_cancel_,
+ rh);
}
else
{
rh->original_dns_id = p->id;
- rh->dns_request = GNUNET_DNSSTUB_resolve (dns_handle,
- (const struct sockaddr *)
&ac->authority_info.dns_authority.dns_ip,
- sa_len,
+ GNUNET_assert (NULL != ac->authority_info.dns_authority.dns_handle);
+ GNUNET_assert (NULL == rh->dns_request);
+ rh->dns_request = GNUNET_DNSSTUB_resolve
(ac->authority_info.dns_authority.dns_handle,
dns_request,
dns_request_length,
&dns_result_parser,
rh);
rh->task_id = GNUNET_SCHEDULER_add_delayed (DNS_LOOKUP_TIMEOUT,
- &fail_resolution,
+ &timeout_resolution,
rh);
}
if (GNUNET_SYSERR != ret)
@@ -1293,15 +1345,47 @@ vpn_allocation_cb (void *cls,
/**
+ * We have resolved one or more of the nameservers for a
+ * GNS2DNS lookup. Once we have some of them, begin using
+ * the DNSSTUB resolver.
+ *
+ * @param ac context for GNS2DNS resolution
+ */
+static void
+continue_with_gns2dns (struct AuthorityChain *ac)
+{
+ struct GNS_ResolverHandle *rh = ac->rh;
+
+ if ( (NULL != ac->authority_info.dns_authority.gp_head) &&
+ (GNUNET_NO == ac->authority_info.dns_authority.found) )
+ return; /* more pending and none found yet */
+ if (GNUNET_NO == ac->authority_info.dns_authority.found)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Failed to resolve DNS server for `%s' in GNS2DNS
resolution\n",
+ ac->authority_info.dns_authority.name);
+ fail_resolution (rh);
+ return;
+ }
+ if (GNUNET_NO != ac->authority_info.dns_authority.launched)
+ return; /* already running, do not launch again! */
+ /* recurse */
+ ac->authority_info.dns_authority.launched = GNUNET_YES;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Will continue resolution using DNS to resolve `%s'\n",
+ ac->label);
+ GNUNET_assert (NULL == rh->task_id);
+ rh->task_id = GNUNET_SCHEDULER_add_now (&recursive_resolution,
+ rh);
+
+}
+
+
+/**
* We've resolved the IP address for the DNS resolver to use
* after encountering a GNS2DNS record.
*
- * TODO: Right now we only foward the request to ONE DNS resolver,
- * even if we get multiple IP addresses back; a correct implementation
- * should try all DNS resolvers.
- *
- * @param cls the `struct GNS_ResolverHandle` where we encountered
- * the GNS2DNS record
+ * @param cls the `struct Gns2DnsPending` used for this request
* @param rd_count number of records in @a rd
* @param rd addresses for the DNS resolver (presumably)
*/
@@ -1310,136 +1394,96 @@ handle_gns2dns_result (void *cls,
unsigned int rd_count,
const struct GNUNET_GNSRECORD_Data *rd)
{
- struct GNS_ResolverHandle *rh = cls;
- struct AuthorityChain *ac;
- struct sockaddr *sa;
- struct sockaddr_in v4;
- struct sockaddr_in6 v6;
- size_t sa_len;
-
- /* find suitable A/AAAA record */
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Received %u results for IP address of DNS server for GNS2DNS
transition\n",
- rd_count);
- /* enable cleanup of 'rh' handle that comes next... */
- if (NULL != rh->g2dc->rh)
+ struct Gns2DnsPending *gp = cls;
+ struct AuthorityChain *ac = gp->ac;
+
+ GNUNET_CONTAINER_DLL_remove (ac->authority_info.dns_authority.gp_head,
+ ac->authority_info.dns_authority.gp_tail,
+ gp);
+ /* enable cleanup of 'rh' handle that automatically comes after we return,
+ and which expects 'rh' to be in the #rlh_head DLL. */
+ if (NULL != gp->rh)
{
GNUNET_CONTAINER_DLL_insert (rlh_head,
rlh_tail,
- rh->g2dc->rh);
- rh->g2dc->rh = NULL;
+ gp->rh);
+ gp->rh = NULL;
}
- sa = NULL;
- sa_len = 0;
+ GNUNET_free (gp);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received %u results for IP address of DNS server for GNS2DNS
transition\n",
+ rd_count);
+ /* find suitable A/AAAA record */
for (unsigned int j=0;j<rd_count;j++)
{
switch (rd[j].record_type)
{
case GNUNET_DNSPARSER_TYPE_A:
- if (sizeof (struct in_addr) != rd[j].data_size)
{
- GNUNET_break_op (0);
- rh->proc (rh->proc_cls, 0, NULL);
- GNS_resolver_lookup_cancel (rh);
- return;
- }
- /* FIXME: might want to check if we support IPv4 here,
- and otherwise skip this one and hope we find another */
- memset (&v4, 0, sizeof (v4));
- sa_len = sizeof (v4);
- v4.sin_family = AF_INET;
- v4.sin_port = htons (53);
+ struct sockaddr_in v4;
+
+ if (sizeof (struct in_addr) != rd[j].data_size)
+ {
+ GNUNET_break_op (0);
+ continue;
+ }
+ memset (&v4,
+ 0,
+ sizeof (v4));
+ v4.sin_family = AF_INET;
+ v4.sin_port = htons (53);
#if HAVE_SOCKADDR_IN_SIN_LEN
- v4.sin_len = (u_char) sa_len;
+ v4.sin_len = (u_char) sizeof (v4);
#endif
- GNUNET_memcpy (&v4.sin_addr,
- rd[j].data,
- sizeof (struct in_addr));
- sa = (struct sockaddr *) &v4;
- break;
+ GNUNET_memcpy (&v4.sin_addr,
+ rd[j].data,
+ sizeof (struct in_addr));
+ if (GNUNET_OK ==
+ GNUNET_DNSSTUB_add_dns_sa
(ac->authority_info.dns_authority.dns_handle,
+ (const struct sockaddr *) &v4))
+ ac->authority_info.dns_authority.found = GNUNET_YES;
+ break;
+ }
case GNUNET_DNSPARSER_TYPE_AAAA:
- if (sizeof (struct in6_addr) != rd[j].data_size)
{
- GNUNET_break_op (0);
- rh->proc (rh->proc_cls, 0, NULL);
- GNS_resolver_lookup_cancel (rh);
- return;
- }
- /* FIXME: might want to check if we support IPv6 here,
- and otherwise skip this one and hope we find another */
- memset (&v6, 0, sizeof (v6));
- sa_len = sizeof (v6);
- v6.sin6_family = AF_INET6;
- v6.sin6_port = htons (53);
+ struct sockaddr_in6 v6;
+
+ if (sizeof (struct in6_addr) != rd[j].data_size)
+ {
+ GNUNET_break_op (0);
+ continue;
+ }
+ /* FIXME: might want to check if we support IPv6 here,
+ and otherwise skip this one and hope we find another */
+ memset (&v6,
+ 0,
+ sizeof (v6));
+ v6.sin6_family = AF_INET6;
+ v6.sin6_port = htons (53);
#if HAVE_SOCKADDR_IN_SIN_LEN
- v6.sin6_len = (u_char) sa_len;
+ v6.sin6_len = (u_char) sizeof (v6);
#endif
- GNUNET_memcpy (&v6.sin6_addr,
- rd[j].data,
- sizeof (struct in6_addr));
- sa = (struct sockaddr *) &v6;
- break;
+ GNUNET_memcpy (&v6.sin6_addr,
+ rd[j].data,
+ sizeof (struct in6_addr));
+ if (GNUNET_OK ==
+ GNUNET_DNSSTUB_add_dns_sa
(ac->authority_info.dns_authority.dns_handle,
+ (const struct sockaddr *) &v6))
+ ac->authority_info.dns_authority.found = GNUNET_YES;
+ break;
+ }
default:
break;
}
- if (NULL != sa)
- break;
- }
- if (NULL == sa)
- {
- /* we cannot continue; NS without A/AAAA */
- rh->proc (rh->proc_cls, 0, NULL);
- GNS_resolver_lookup_cancel (rh);
- return;
- }
- /* expand authority chain */
- ac = GNUNET_new (struct AuthorityChain);
- ac->rh = rh;
- GNUNET_assert (strlen (rh->g2dc->ns) <= GNUNET_DNSPARSER_MAX_NAME_LENGTH);
- strcpy (ac->authority_info.dns_authority.name,
- rh->g2dc->ns);
- GNUNET_memcpy (&ac->authority_info.dns_authority.dns_ip,
- sa,
- sa_len);
- /* for DNS recursion, the label is the full DNS name,
- created from the remainder of the GNS name and the
- name in the NS record */
- GNUNET_asprintf (&ac->label,
- "%.*s%s%s",
- (int) rh->name_resolution_pos,
- rh->name,
- (0 != rh->name_resolution_pos) ? "." : "",
- rh->g2dc->ns);
- GNUNET_free (rh->g2dc->ns);
- GNUNET_free (rh->g2dc);
- rh->g2dc = NULL;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Will continue resolution using DNS server `%s' to resolve
`%s'\n",
- GNUNET_a2s (sa,
- sa_len),
- ac->label);
- GNUNET_CONTAINER_DLL_insert_tail (rh->ac_head,
- rh->ac_tail,
- ac);
- if (strlen (ac->label) > GNUNET_DNSPARSER_MAX_NAME_LENGTH)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _("GNS lookup resulted in DNS name that is too long (`%s')\n"),
- ac->label);
- rh->proc (rh->proc_cls, 0, NULL);
- GNS_resolver_lookup_cancel (rh);
- return;
}
- /* recurse */
- rh->task_id = GNUNET_SCHEDULER_add_now (&recursive_resolution,
- rh);
+ continue_with_gns2dns (ac);
}
/**
* Function called by the resolver for each address obtained from DNS.
*
- * @param cls closure, a `struct Gns2DnsContext *`
+ * @param cls closure, a `struct Gns2DnsPending *`
* @param addr one of the addresses of the host, NULL for the last address
* @param addrlen length of @a addr
*/
@@ -1448,57 +1492,270 @@ handle_gns2dns_ip (void *cls,
const struct sockaddr *addr,
socklen_t addrlen)
{
- struct Gns2DnsContext *g2dc = cls;
- struct GNUNET_GNSRECORD_Data rd;
-
+ struct Gns2DnsPending *gp = cls;
+ struct AuthorityChain *ac = gp->ac;
+
+ GNUNET_RESOLVER_request_cancel (gp->dns_rh);
+ GNUNET_CONTAINER_DLL_remove (ac->authority_info.dns_authority.gp_head,
+ ac->authority_info.dns_authority.gp_tail,
+ gp);
+ GNUNET_free (gp);
if (NULL == addr)
{
/* DNS resolution failed */
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Failed to use DNS to resolve name of DNS resolver\n");
- g2dc->rh->g2dc = NULL;
- fail_resolution (g2dc->rh);
- GNUNET_free (g2dc);
}
- switch (addr->sa_family)
+ else
{
- case AF_INET:
+ if (GNUNET_OK ==
+ GNUNET_DNSSTUB_add_dns_sa (ac->authority_info.dns_authority.dns_handle,
+ addr))
+ ac->authority_info.dns_authority.found = GNUNET_YES;
+ }
+ continue_with_gns2dns (ac);
+}
+
+
+/**
+ * We found a CNAME record, perform recursive resolution on it.
+ *
+ * @param rh resolution handle
+ * @param rd record with CNAME to resolve recursively
+ */
+static void
+recursive_cname_resolution (struct GNS_ResolverHandle *rh,
+ const struct GNUNET_GNSRECORD_Data *rd)
+{
+ char *cname;
+ size_t off;
+
+ off = 0;
+ cname = GNUNET_DNSPARSER_parse_name (rd->data,
+ rd->data_size,
+ &off);
+ if ( (NULL == cname) ||
+ (off != rd->data_size) )
+ {
+ GNUNET_break_op (0); /* record not well-formed */
+ GNUNET_free_non_null (cname);
+ fail_resolution (rh);
+ return;
+ }
+ handle_gns_cname_result (rh,
+ cname);
+ GNUNET_free (cname);
+}
+
+
+/**
+ * We found a PKEY record, perform recursive resolution on it.
+ *
+ * @param rh resolution handle
+ * @param rd record with PKEY to resolve recursively
+ */
+static void
+recursive_pkey_resolution (struct GNS_ResolverHandle *rh,
+ const struct GNUNET_GNSRECORD_Data *rd)
+{
+ struct AuthorityChain *ac;
+
+ /* delegation to another zone */
+ if (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) !=
+ rd->data_size)
+ {
+ GNUNET_break_op (0);
+ fail_resolution (rh);
+ return;
+ }
+ /* expand authority chain */
+ ac = GNUNET_new (struct AuthorityChain);
+ ac->rh = rh;
+ ac->gns_authority = GNUNET_YES;
+ ac->suggested_shortening_label = NULL;
+ ac->shortening_started = GNUNET_NO;
+ GNUNET_memcpy (&ac->authority_info.gns_authority,
+ rd->data,
+ sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+ ac->label = resolver_lookup_get_next_label (rh);
+ /* add AC to tail */
+ GNUNET_CONTAINER_DLL_insert_tail (rh->ac_head,
+ rh->ac_tail,
+ ac);
+ /* recurse */
+ rh->task_id = GNUNET_SCHEDULER_add_now (&recursive_resolution,
+ rh);
+}
+
+
+/**
+ * We found one or more GNS2DNS records, perform recursive resolution on it.
+ * (to be precise, one or more records in @a rd is GNS2DNS, there may be
others,
+ * so this function still needs to check which ones are GNS2DNS).
+ *
+ * @param rh resolution handle
+ * @param rd_count length of the @a rd array
+ * @param rd record with PKEY to resolve recursively
+ * @return #GNUNET_OK if this worked, #GNUNET_SYSERR if no GNS2DNS records
were in @a rd
+ */
+static int
+recursive_gns2dns_resolution (struct GNS_ResolverHandle *rh,
+ unsigned int rd_count,
+ const struct GNUNET_GNSRECORD_Data *rd)
+{
+ struct AuthorityChain *ac;
+ const char *tld;
+ char *ns;
+
+ ns = NULL;
+ /* expand authority chain */
+ ac = GNUNET_new (struct AuthorityChain);
+ ac->rh = rh;
+ ac->authority_info.dns_authority.dns_handle = GNUNET_DNSSTUB_start (4);
+
+ for (unsigned int i=0;i<rd_count;i++)
+ {
+ char *ip;
+ char *n;
+ size_t off;
+ struct Gns2DnsPending *gp;
+ struct GNUNET_CRYPTO_EcdsaPublicKey zone;
+
+ if (GNUNET_GNSRECORD_TYPE_GNS2DNS != rd[i].record_type)
+ continue;
+ off = 0;
+ n = GNUNET_DNSPARSER_parse_name (rd[i].data,
+ rd[i].data_size,
+ &off);
+ ip = GNUNET_DNSPARSER_parse_name (rd[i].data,
+ rd[i].data_size,
+ &off);
+ if ( (NULL == n) ||
+ (NULL == ip) ||
+ (off != rd[i].data_size) )
{
- const struct sockaddr_in *v4 = (const struct sockaddr_in *) addr;
-
- GNUNET_assert (sizeof (*v4) == addrlen);
- rd.data = v4;
- rd.data_size = sizeof (*v4);
- rd.expiration_time = UINT64_MAX;
- rd.record_type = GNUNET_DNSPARSER_TYPE_A;
- rd.flags = 0;
- break;
+ GNUNET_break_op (0);
+ GNUNET_free_non_null (n);
+ GNUNET_free_non_null (ip);
+ continue;
}
- case AF_INET6:
+ /* resolve 'ip' to determine the IP(s) of the DNS
+ resolver to use for lookup of 'ns' */
+ if (NULL != ns)
{
- const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *) addr;
-
- GNUNET_assert (sizeof (*v6) == addrlen);
- rd.data = v6;
- rd.data_size = sizeof (v6);
- rd.expiration_time = UINT64_MAX;
- rd.record_type = GNUNET_DNSPARSER_TYPE_AAAA;
- rd.flags = 0;
- break;
+ if (0 != strcasecmp (ns,
+ n))
+ {
+ /* NS values must all be the same for all GNS2DNS records,
+ anything else leads to insanity */
+ GNUNET_break_op (0);
+ GNUNET_free (n);
+ GNUNET_free (ip);
+ continue;
+ }
+ GNUNET_free (n);
+ }
+ else
+ {
+ ns = n;
}
- default:
- return;
- }
- GNUNET_RESOLVER_request_cancel (g2dc->dns_rh);
- g2dc->dns_rh = NULL;
- handle_gns2dns_result (g2dc->rh,
- 1,
- &rd);
+ /* check if 'ip' is already an IPv4/IPv6 address */
+ if (GNUNET_OK ==
+ GNUNET_DNSSTUB_add_dns_ip (ac->authority_info.dns_authority.dns_handle,
+ ip))
+ {
+ ac->authority_info.dns_authority.found = GNUNET_YES;
+ GNUNET_free (ip);
+ continue;
+ }
+ tld = GNS_get_tld (ip);
+ if (0 != strcmp (tld,
+ "+"))
+ {
+ /* 'ip' is a DNS name */
+ gp = GNUNET_new (struct Gns2DnsPending);
+ gp->ac = ac;
+ GNUNET_CONTAINER_DLL_insert (ac->authority_info.dns_authority.gp_head,
+ ac->authority_info.dns_authority.gp_tail,
+ gp);
+ gp->dns_rh = GNUNET_RESOLVER_ip_get (ip,
+ AF_UNSPEC,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ &handle_gns2dns_ip,
+ gp);
+ GNUNET_free (ip);
+ continue;
+ }
+ /* 'ip' should be a GNS name */
+ gp = GNUNET_new (struct Gns2DnsPending);
+ gp->ac = ac;
+ GNUNET_CONTAINER_DLL_insert (ac->authority_info.dns_authority.gp_head,
+ ac->authority_info.dns_authority.gp_tail,
+ gp);
+ gp->rh = GNUNET_new (struct GNS_ResolverHandle);
+ ip = translate_dot_plus (rh,
+ ip);
+ tld = GNS_get_tld (ip);
+ if (GNUNET_OK !=
+ GNUNET_GNSRECORD_zkey_to_pkey (tld,
+ &zone))
+ {
+ GNUNET_break_op (0);
+ GNUNET_free (ip);
+ continue;
+ }
+ gp->rh->authority_zone = zone;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Resolving `%s' to determine IP address of DNS server for
GNS2DNS transition for `%s'\n",
+ ip,
+ ns);
+ gp->rh->name = ip;
+ gp->rh->name_resolution_pos = strlen (ip) - strlen (tld) - 1;
+ gp->rh->proc = &handle_gns2dns_result;
+ gp->rh->proc_cls = gp;
+ gp->rh->record_type = GNUNET_GNSRECORD_TYPE_ANY;
+ gp->rh->options = GNUNET_GNS_LO_DEFAULT;
+ gp->rh->loop_limiter = rh->loop_limiter + 1;
+ gp->rh->task_id
+ = GNUNET_SCHEDULER_add_now (&start_resolver_lookup,
+ gp->rh);
+ } /* end 'for all records' */
+
+ if (NULL == ns)
+ {
+ /* not a single GNS2DNS record found */
+ GNUNET_free (ac);
+ return GNUNET_SYSERR;
+ }
+ GNUNET_assert (strlen (ns) <= GNUNET_DNSPARSER_MAX_NAME_LENGTH);
+ strcpy (ac->authority_info.dns_authority.name,
+ ns);
+ /* for DNS recursion, the label is the full DNS name,
+ created from the remainder of the GNS name and the
+ name in the NS record */
+ GNUNET_asprintf (&ac->label,
+ "%.*s%s%s",
+ (int) rh->name_resolution_pos,
+ rh->name,
+ (0 != rh->name_resolution_pos) ? "." : "",
+ ns);
+ GNUNET_free (ns);
+ GNUNET_CONTAINER_DLL_insert_tail (rh->ac_head,
+ rh->ac_tail,
+ ac);
+ if (strlen (ac->label) > GNUNET_DNSPARSER_MAX_NAME_LENGTH)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("GNS lookup resulted in DNS name that is too long (`%s')\n"),
+ ac->label);
+ return GNUNET_SYSERR;
+ }
+ continue_with_gns2dns (ac);
+ return GNUNET_OK;
}
-
/**
* Process a records that were decrypted from a block.
*
@@ -1512,7 +1769,6 @@ handle_gns_resolution_result (void *cls,
const struct GNUNET_GNSRECORD_Data *rd)
{
struct GNS_ResolverHandle *rh = cls;
- struct AuthorityChain *ac;
struct AuthorityChain *shorten_ac;
char *cname;
struct VpnContext *vpn_ctx;
@@ -1532,6 +1788,14 @@ handle_gns_resolution_result (void *cls,
rh->ac_tail->label,
GNUNET_GNSRECORD_z2s (&rh->ac_tail->authority_info.gns_authority),
rd_count);
+ if (0 == rd_count)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("GNS lookup failed (zero records found)\n"));
+ fail_resolution (rh);
+ return;
+ }
+
if (0 == rh->name_resolution_pos)
{
/* top-level match, are we done yet? */
@@ -1547,9 +1811,8 @@ handle_gns_resolution_result (void *cls,
(off != rd[0].data_size) )
{
GNUNET_break_op (0);
- rh->proc (rh->proc_cls, 0, NULL);
- GNS_resolver_lookup_cancel (rh);
GNUNET_free_non_null (cname);
+ fail_resolution (rh);
return;
}
handle_gns_cname_result (rh,
@@ -1573,8 +1836,7 @@ handle_gns_resolution_result (void *cls,
rd[i].data_size)
{
GNUNET_break_op (0);
- rh->proc (rh->proc_cls, 0, NULL);
- GNS_resolver_lookup_cancel (rh);
+ fail_resolution (rh);
return;
}
vpn = (const struct GNUNET_TUN_GnsVpnRecord *) rd[i].data;
@@ -1582,8 +1844,7 @@ handle_gns_resolution_result (void *cls,
if ('\0' != vname[rd[i].data_size - 1 - sizeof (struct
GNUNET_TUN_GnsVpnRecord)])
{
GNUNET_break_op (0);
- rh->proc (rh->proc_cls, 0, NULL);
- GNS_resolver_lookup_cancel (rh);
+ fail_resolution (rh);
return;
}
GNUNET_TUN_service_name_to_hash (vname,
@@ -1621,7 +1882,13 @@ handle_gns_resolution_result (void *cls,
/* delegation to DNS */
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Found GNS2DNS record, delegating to DNS!\n");
- goto do_recurse;
+ if (GNUNET_OK ==
+ recursive_gns2dns_resolution (rh,
+ rd_count,
+ rd))
+ return;
+ else
+ goto fail;
}
default:
break;
@@ -1823,7 +2090,9 @@ handle_gns_resolution_result (void *cls,
GNUNET_break_op (0);
break;
}
- GNUNET_memcpy (&pub, rd[i].data, rd[i].data_size);
+ GNUNET_memcpy (&pub,
+ rd[i].data,
+ rd[i].data_size);
rd_off++;
if (GNUNET_GNSRECORD_TYPE_PKEY != rh->record_type)
{
@@ -1856,7 +2125,13 @@ handle_gns_resolution_result (void *cls,
}
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Found GNS2DNS record, delegating to DNS!\n");
- goto do_recurse;
+ if (GNUNET_OK ==
+ recursive_gns2dns_resolution (rh,
+ rd_count,
+ rd))
+ return;
+ else
+ goto fail;
}
case GNUNET_GNSRECORD_TYPE_BOX:
{
@@ -1901,200 +2176,35 @@ handle_gns_resolution_result (void *cls,
rh->proc (rh->proc_cls,
rd_off,
rd_new);
- GNS_resolver_lookup_cancel (rh);
+ rh->task_id = GNUNET_SCHEDULER_add_now (&GNS_resolver_lookup_cancel_,
+ rh);
return;
}
- do_recurse:
- /* need to recurse, check if we can */
- for (unsigned int i=0;i<rd_count;i++)
+
+ switch (rd[0].record_type)
{
- switch (rd[i].record_type)
- {
- case GNUNET_GNSRECORD_TYPE_PKEY:
- /* delegation to another zone */
- if (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) !=
- rd[i].data_size)
- {
- GNUNET_break_op (0);
- rh->proc (rh->proc_cls, 0, NULL);
- GNS_resolver_lookup_cancel (rh);
- return;
- }
- /* expand authority chain */
- ac = GNUNET_new (struct AuthorityChain);
- ac->rh = rh;
- ac->gns_authority = GNUNET_YES;
- ac->suggested_shortening_label = NULL;
- ac->shortening_started = GNUNET_NO;
- GNUNET_memcpy (&ac->authority_info.gns_authority,
- rd[i].data,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
- ac->label = resolver_lookup_get_next_label (rh);
- /* add AC to tail */
- GNUNET_CONTAINER_DLL_insert_tail (rh->ac_head,
- rh->ac_tail,
- ac);
- /* recurse */
- rh->task_id = GNUNET_SCHEDULER_add_now (&recursive_resolution,
- rh);
+ case GNUNET_DNSPARSER_TYPE_CNAME:
+ GNUNET_break_op (1 == rd_count); /* CNAME should be unique */
+ recursive_cname_resolution (rh,
+ &rd[0]);
+ return;
+ case GNUNET_GNSRECORD_TYPE_PKEY:
+ GNUNET_break_op (1 == rd_count); /* PKEY should be unique */
+ recursive_pkey_resolution (rh,
+ &rd[0]);
+ return;
+ default:
+ if (GNUNET_OK ==
+ recursive_gns2dns_resolution (rh,
+ rd_count,
+ rd))
return;
- case GNUNET_GNSRECORD_TYPE_GNS2DNS:
- {
- /* TODO: Right now we only foward the request to ONE DNS resolver,
- even if we get multiple IP addresses back; a correct implementation
- should try all DNS resolvers. */
- /* resolution continues within DNS */
- struct Gns2DnsContext *g2dc;
- char *ip;
- char *ns;
- const char *tld;
- struct GNUNET_CRYPTO_EcdsaPublicKey zone;
- struct in_addr v4;
- struct in6_addr v6;
-
- off = 0;
- ns = GNUNET_DNSPARSER_parse_name (rd[i].data,
- rd[i].data_size,
- &off);
- ip = GNUNET_DNSPARSER_parse_name (rd[i].data,
- rd[i].data_size,
- &off);
- if ( (NULL == ns) ||
- (NULL == ip) ||
- (off != rd[i].data_size) )
- {
- GNUNET_break_op (0);
- GNUNET_free_non_null (ns);
- GNUNET_free_non_null (ip);
- fail_resolution (rh);
- return;
- }
- /* resolve 'ip' to determine the IP(s) of the DNS
- resolver to use for lookup of 'ns' */
- g2dc = GNUNET_new (struct Gns2DnsContext);
- g2dc->ns = ns;
- rh->g2dc = g2dc;
-
- /* check if 'ip' is already an IPv4/IPv6 address */
- if (1 == inet_pton (AF_INET,
- ip,
- &v4))
- {
- /* name is IPv4 address, pretend it's an A record */
- struct GNUNET_GNSRECORD_Data rd;
-
- GNUNET_free (ip);
- rd.data = &v4;
- rd.data_size = sizeof (v4);
- rd.expiration_time = UINT64_MAX;
- rd.record_type = GNUNET_DNSPARSER_TYPE_A;
- rd.flags = 0;
- handle_gns2dns_result (rh,
- 1,
- &rd);
- return;
- }
- if (1 == inet_pton (AF_INET6,
- ip,
- &v6))
- {
- /* name is IPv6 address, pretend it's an AAAA record */
- struct GNUNET_GNSRECORD_Data rd;
-
- GNUNET_free (ip);
- rd.data = &v6;
- rd.data_size = sizeof (v6);
- rd.expiration_time = UINT64_MAX;
- rd.record_type = GNUNET_DNSPARSER_TYPE_AAAA;
- rd.flags = 0;
- handle_gns2dns_result (rh,
- 1,
- &rd);
- return;
- }
-
- tld = GNS_get_tld (ip);
- if (0 != strcmp (tld,
- "+"))
- {
- /* 'ip' is a DNS name */
- g2dc->dns_rh = GNUNET_RESOLVER_ip_get (ip,
- AF_UNSPEC,
- GNUNET_TIME_UNIT_FOREVER_REL,
- &handle_gns2dns_ip,
- g2dc);
- GNUNET_free (ip);
- return;
- }
-
- /* 'ip' should be a GNS name */
- g2dc->rh = GNUNET_new (struct GNS_ResolverHandle);
-
- ip = translate_dot_plus (rh,
- ip);
- tld = GNS_get_tld (ip);
- if (GNUNET_OK !=
- GNUNET_GNSRECORD_zkey_to_pkey (tld,
- &zone))
- {
- GNUNET_break_op (0);
- GNUNET_free_non_null (ns);
- GNUNET_free_non_null (ip);
- GNUNET_free (g2dc);
- fail_resolution (rh);
- return;
- }
- g2dc->rh->authority_zone = zone;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Resolving `%s' to determine IP address of DNS server for
GNS2DNS transition for `%s'\n",
- ip,
- ns);
- g2dc->rh->name = ip;
- g2dc->rh->name_resolution_pos = strlen (ip) - strlen (tld) - 1;
- g2dc->rh->proc = &handle_gns2dns_result;
- g2dc->rh->proc_cls = rh;
- g2dc->rh->record_type = GNUNET_GNSRECORD_TYPE_ANY;
- g2dc->rh->options = GNUNET_GNS_LO_DEFAULT;
- g2dc->rh->loop_limiter = rh->loop_limiter + 1;
- g2dc->rh->task_id
- = GNUNET_SCHEDULER_add_now (&start_resolver_lookup,
- g2dc->rh);
- return;
- }
- case GNUNET_DNSPARSER_TYPE_CNAME:
- {
- char *cname;
-
- off = 0;
- cname = GNUNET_DNSPARSER_parse_name (rd[i].data,
- rd[i].data_size,
- &off);
- if ( (NULL == cname) ||
- (off != rd[i].data_size) )
- {
- GNUNET_break_op (0); /* record not well-formed */
- rh->proc (rh->proc_cls, 0, NULL);
- GNS_resolver_lookup_cancel (rh);
- GNUNET_free_non_null (cname);
- return;
- }
- handle_gns_cname_result (rh,
- cname);
- GNUNET_free (cname);
- return;
- }
- /* FIXME: handle DNAME */
- default:
- /* skip */
- break;
- }
+ break;
}
+ fail:
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
_("GNS lookup recursion failed (no delegation record found)\n"));
- rh->proc (rh->proc_cls,
- 0,
- NULL);
- GNS_resolver_lookup_cancel (rh);
+ fail_resolution (rh);
}
@@ -2176,8 +2286,7 @@ handle_dht_response (void *cls,
{
/* how did this pass DHT block validation!? */
GNUNET_break (0);
- rh->proc (rh->proc_cls, 0, NULL);
- GNS_resolver_lookup_cancel (rh);
+ fail_resolution (rh);
return;
}
block = data;
@@ -2188,8 +2297,7 @@ handle_dht_response (void *cls,
{
/* how did this pass DHT block validation!? */
GNUNET_break (0);
- rh->proc (rh->proc_cls, 0, NULL);
- GNS_resolver_lookup_cancel (rh);
+ fail_resolution (rh);
return;
}
if (GNUNET_OK !=
@@ -2200,8 +2308,7 @@ handle_dht_response (void *cls,
rh))
{
GNUNET_break_op (0); /* block was ill-formed */
- rh->proc (rh->proc_cls, 0, NULL);
- GNS_resolver_lookup_cancel (rh);
+ fail_resolution (rh);
return;
}
if (0 == GNUNET_TIME_absolute_get_remaining (GNUNET_TIME_absolute_ntoh
(block->expiration_time)).rel_value_us)
@@ -2252,8 +2359,7 @@ start_dht_request (struct GNS_ResolverHandle *rh,
/* fail longest-standing DHT request */
rx = GNUNET_CONTAINER_heap_peek (dht_lookup_heap);
GNUNET_assert (NULL != rx);
- rx->proc (rx->proc_cls, 0, NULL);
- GNS_resolver_lookup_cancel (rx);
+ fail_resolution (rx);
}
}
@@ -2324,8 +2430,7 @@ handle_namecache_block_response (void *cls,
"Resolution failed for `%s' in zone %s (DHT lookup not
permitted by configuration)\n",
ac->label,
GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority));
- rh->proc (rh->proc_cls, 0, NULL);
- GNS_resolver_lookup_cancel (rh);
+ fail_resolution (rh);
return;
}
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -2408,8 +2513,7 @@ handle_revocation_result (void *cls,
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
_("Zone %s was revoked, resolution fails\n"),
GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority));
- rh->proc (rh->proc_cls, 0, NULL);
- GNS_resolver_lookup_cancel (rh);
+ fail_resolution (rh);
return;
}
recursive_gns_resolution_namecache (rh);
@@ -2453,8 +2557,7 @@ recursive_resolution (void *cls)
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Encountered unbounded recursion resolving `%s'\n",
rh->name);
- rh->proc (rh->proc_cls, 0, NULL);
- GNS_resolver_lookup_cancel (rh);
+ fail_resolution (rh);
return;
}
if (GNUNET_YES == rh->ac_tail->gns_authority)
@@ -2491,8 +2594,12 @@ start_resolver_lookup (void *cls)
rd.expiration_time = UINT64_MAX;
rd.record_type = GNUNET_DNSPARSER_TYPE_A;
rd.flags = 0;
- rh->proc (rh->proc_cls, 1, &rd);
- GNS_resolver_lookup_cancel (rh);
+ rh->proc (rh->proc_cls,
+ 1,
+ &rd);
+ GNUNET_assert (NULL == rh->task_id);
+ rh->task_id = GNUNET_SCHEDULER_add_now (&GNS_resolver_lookup_cancel_,
+ rh);
return;
}
if (1 == inet_pton (AF_INET6,
@@ -2507,8 +2614,12 @@ start_resolver_lookup (void *cls)
rd.expiration_time = UINT64_MAX;
rd.record_type = GNUNET_DNSPARSER_TYPE_AAAA;
rd.flags = 0;
- rh->proc (rh->proc_cls, 1, &rd);
- GNS_resolver_lookup_cancel (rh);
+ rh->proc (rh->proc_cls,
+ 1,
+ &rd);
+ GNUNET_assert (NULL == rh->task_id);
+ rh->task_id = GNUNET_SCHEDULER_add_now (&GNS_resolver_lookup_cancel_,
+ rh);
return;
}
@@ -2587,37 +2698,51 @@ GNS_resolver_lookup_cancel (struct GNS_ResolverHandle
*rh)
GNUNET_CONTAINER_DLL_remove (rlh_head,
rlh_tail,
rh);
+ if (NULL != rh->dns_request)
+ {
+ GNUNET_DNSSTUB_resolve_cancel (rh->dns_request);
+ rh->dns_request = NULL;
+ }
while (NULL != (ac = rh->ac_head))
{
GNUNET_CONTAINER_DLL_remove (rh->ac_head,
rh->ac_tail,
ac);
+ if (GNUNET_NO == ac->gns_authority)
+ {
+ struct Gns2DnsPending *gp;
+
+ while (NULL != (gp = ac->authority_info.dns_authority.gp_head))
+ {
+ GNUNET_CONTAINER_DLL_remove (ac->authority_info.dns_authority.gp_head,
+ ac->authority_info.dns_authority.gp_tail,
+ gp);
+ if (NULL != gp->rh)
+ {
+ /* rh->g2dc->rh is NOT in the DLL yet, so to enable us
+ using GNS_resolver_lookup_cancel here, we need to
+ add it first... */
+ GNUNET_CONTAINER_DLL_insert (rlh_head,
+ rlh_tail,
+ gp->rh);
+ GNUNET_assert (NULL == gp->rh->task_id);
+ gp->rh->task_id = GNUNET_SCHEDULER_add_now
(&GNS_resolver_lookup_cancel_,
+ gp->rh);
+ gp->rh = NULL;
+ }
+ if (NULL != gp->dns_rh)
+ {
+ GNUNET_RESOLVER_request_cancel (gp->dns_rh);
+ gp->dns_rh = NULL;
+ }
+ GNUNET_free (gp);
+ }
+ GNUNET_DNSSTUB_stop (ac->authority_info.dns_authority.dns_handle);
+ }
GNUNET_free (ac->label);
GNUNET_free_non_null (ac->suggested_shortening_label);
GNUNET_free (ac);
}
- if (NULL != rh->g2dc)
- {
- /* rh->g2dc->rh is NOT in the DLL yet, so to enable us
- using GNS_resolver_lookup_cancel here, we need to
- add it first... */
- if (NULL != rh->g2dc->rh)
- {
- GNUNET_CONTAINER_DLL_insert (rlh_head,
- rlh_tail,
- rh->g2dc->rh);
- GNS_resolver_lookup_cancel (rh->g2dc->rh);
- rh->g2dc->rh = NULL;
- }
- if (NULL != rh->g2dc->dns_rh)
- {
- GNUNET_RESOLVER_request_cancel (rh->g2dc->dns_rh);
- rh->g2dc->rh = NULL;
- }
- GNUNET_free (rh->g2dc->ns);
- GNUNET_free (rh->g2dc);
- rh->g2dc = NULL;
- }
if (NULL != rh->task_id)
{
GNUNET_SCHEDULER_cancel (rh->task_id);
@@ -2639,11 +2764,6 @@ GNS_resolver_lookup_cancel (struct GNS_ResolverHandle
*rh)
GNUNET_free (vpn_ctx->rd_data);
GNUNET_free (vpn_ctx);
}
- if (NULL != rh->dns_request)
- {
- GNUNET_DNSSTUB_resolve_cancel (rh->dns_request);
- rh->dns_request = NULL;
- }
if (NULL != rh->namecache_qe)
{
GNUNET_NAMECACHE_cancel (rh->namecache_qe);
@@ -2690,8 +2810,6 @@ GNS_resolver_init (struct GNUNET_NAMECACHE_Handle *nc,
const struct GNUNET_CONFIGURATION_Handle *c,
unsigned long long max_bg_queries)
{
- char *dns_ip;
-
cfg = c;
namecache_handle = nc;
dht_handle = dht;
@@ -2706,18 +2824,6 @@ GNS_resolver_init (struct GNUNET_NAMECACHE_Handle *nc,
if (GNUNET_NO == use_cache)
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Namecache disabled\n");
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (c,
- "gns",
- "DNS_RESOLVER",
- &dns_ip))
- {
- /* user did not specify DNS resolver, use 8.8.8.8 */
- dns_ip = GNUNET_strdup ("8.8.8.8");
- }
- dns_handle = GNUNET_DNSSTUB_start (dns_ip);
- GNUNET_free (dns_ip);
vpn_handle = GNUNET_VPN_connect (cfg);
}
@@ -2734,7 +2840,9 @@ GNS_resolver_done ()
/* abort active resolutions */
while (NULL != (rh = rlh_head))
{
- rh->proc (rh->proc_cls, 0, NULL);
+ rh->proc (rh->proc_cls,
+ 0,
+ NULL);
GNS_resolver_lookup_cancel (rh);
}
while (NULL != (co = co_head))
@@ -2747,8 +2855,6 @@ GNS_resolver_done ()
}
GNUNET_CONTAINER_heap_destroy (dht_lookup_heap);
dht_lookup_heap = NULL;
- GNUNET_DNSSTUB_stop (dns_handle);
- dns_handle = NULL;
GNUNET_VPN_disconnect (vpn_handle);
vpn_handle = NULL;
dht_handle = NULL;
diff --git a/src/gns/test_gns_lookup.conf b/src/gns/test_gns_lookup.conf
index ea8c7c3fc..a9a2345c7 100644
--- a/src/gns/test_gns_lookup.conf
+++ b/src/gns/test_gns_lookup.conf
@@ -10,7 +10,7 @@ AUTOSTART = YES
PLUGINS =
[gns]
-#PREFIX = valgrind --leak-check=full --track-origins=yes
+# PREFIX = valgrind --leak-check=full --track-origins=yes
AUTOSTART = YES
AUTO_IMPORT_PKEY = YES
MAX_PARALLEL_BACKGROUND_QUERIES = 10
diff --git a/src/include/gnunet_dnsstub_lib.h b/src/include/gnunet_dnsstub_lib.h
index 1c3305f7b..41e30d044 100644
--- a/src/include/gnunet_dnsstub_lib.h
+++ b/src/include/gnunet_dnsstub_lib.h
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet
- Copyright (C) 2012 GNUnet e.V.
+ Copyright (C) 2012, 2018 GNUnet e.V.
GNUnet is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
@@ -48,14 +48,52 @@ struct GNUNET_DNSSTUB_RequestSocket;
/**
* Start a DNS stub resolver.
*
- * @param dns_ip target IP address to use
+ * @param num_sockets how many sockets should we open
+ * in parallel for DNS queries for this stub?
* @return NULL on error
*/
struct GNUNET_DNSSTUB_Context *
-GNUNET_DNSSTUB_start (const char *dns_ip);
+GNUNET_DNSSTUB_start (unsigned int num_sockets);
/**
+ * Add nameserver for use by the DNSSTUB. We will use
+ * all provided nameservers for resolution (round-robin).
+ *
+ * @param ctx resolver context to modify
+ * @param dns_ip target IP address to use (as string)
+ * @return #GNUNET_OK on success
+ */
+int
+GNUNET_DNSSTUB_add_dns_ip (struct GNUNET_DNSSTUB_Context *ctx,
+ const char *dns_ip);
+
+
+/**
+ * Add nameserver for use by the DNSSTUB. We will use
+ * all provided nameservers for resolution (round-robin).
+ *
+ * @param ctx resolver context to modify
+ * @param sa socket address of DNS resolver to use
+ * @return #GNUNET_OK on success
+ */
+int
+GNUNET_DNSSTUB_add_dns_sa (struct GNUNET_DNSSTUB_Context *ctx,
+ const struct sockaddr *sa);
+
+
+/**
+ * How long should we try requests before timing out?
+ * Only effective for requests issued after this call.
+ *
+ * @param ctx resolver context to modify
+ * @param retry_frequ how long to wait between retries
+ */
+void
+GNUNET_DNSSTUB_set_retry (struct GNUNET_DNSSTUB_Context *ctx,
+ struct GNUNET_TIME_Relative retry_freq);
+
+/**
* Cleanup DNSSTUB resolver.
*
* @param ctx stub resolver to clean up
@@ -66,57 +104,36 @@ GNUNET_DNSSTUB_stop (struct GNUNET_DNSSTUB_Context *ctx);
/**
* Function called with the result of a DNS resolution.
+ * Once this function is called, the resolution request
+ * is automatically cancelled / cleaned up. In particular,
+ * the function will only be called once.
*
* @param cls closure
- * @param rs socket that received the response
- * @param dns dns response, never NULL
+ * @param dns dns response, NULL on hard error (i.e. timeout)
* @param dns_len number of bytes in @a dns
*/
typedef void
(*GNUNET_DNSSTUB_ResultCallback)(void *cls,
- struct GNUNET_DNSSTUB_RequestSocket *rs,
const struct GNUNET_TUN_DnsHeader *dns,
size_t dns_len);
/**
- * Perform DNS resolution using given address.
- *
- * @param ctx stub resolver to use
- * @param sa the socket address
- * @param sa_len the socket length
- * @param request DNS request to transmit
- * @param request_len number of bytes in msg
- * @param rc function to call with result
- * @param rc_cls closure for @a rc
- * @return socket used for the request, NULL on error
- */
-struct GNUNET_DNSSTUB_RequestSocket *
-GNUNET_DNSSTUB_resolve (struct GNUNET_DNSSTUB_Context *ctx,
- const struct sockaddr *sa,
- socklen_t sa_len,
- const void *request,
- size_t request_len,
- GNUNET_DNSSTUB_ResultCallback rc,
- void *rc_cls);
-
-
-/**
* Perform DNS resolution using our default IP from init.
*
* @param ctx stub resolver to use
* @param request DNS request to transmit
* @param request_len number of bytes in msg
- * @param rc function to call with result
+ * @param rc function to call with result (once)
* @param rc_cls closure for @a rc
* @return socket used for the request, NULL on error
*/
struct GNUNET_DNSSTUB_RequestSocket *
-GNUNET_DNSSTUB_resolve2 (struct GNUNET_DNSSTUB_Context *ctx,
- const void *request,
- size_t request_len,
- GNUNET_DNSSTUB_ResultCallback rc,
- void *rc_cls);
+GNUNET_DNSSTUB_resolve (struct GNUNET_DNSSTUB_Context *ctx,
+ const void *request,
+ size_t request_len,
+ GNUNET_DNSSTUB_ResultCallback rc,
+ void *rc_cls);
/**
diff --git a/src/namestore/gnunet-zoneimport.c
b/src/namestore/gnunet-zoneimport.c
index 4f4151c94..279bfddea 100644
--- a/src/namestore/gnunet-zoneimport.c
+++ b/src/namestore/gnunet-zoneimport.c
@@ -818,13 +818,11 @@ store_completed_cb (void *cls,
* Function called with the result of a DNS resolution.
*
* @param cls closure with the `struct Request`
- * @param rs socket that received the response
* @param dns dns response, never NULL
* @param dns_len number of bytes in @a dns
*/
static void
process_result (void *cls,
- struct GNUNET_DNSSTUB_RequestSocket *rs,
const struct GNUNET_TUN_DnsHeader *dns,
size_t dns_len)
{
@@ -833,7 +831,6 @@ process_result (void *cls,
struct GNUNET_DNSPARSER_Packet *p;
unsigned int rd_count;
- (void) rs;
GNUNET_assert (NULL == req->hn);
if (NULL == dns)
{
@@ -970,11 +967,11 @@ submit_req (struct Request *req)
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Requesting resolution for `%s'\n",
req->hostname);
- req->rs = GNUNET_DNSSTUB_resolve2 (ctx,
- req->raw,
- req->raw_len,
- &process_result,
- req);
+ req->rs = GNUNET_DNSSTUB_resolve (ctx,
+ req->raw,
+ req->raw_len,
+ &process_result,
+ req);
GNUNET_assert (NULL != req->rs);
req->issue_num++;
last_request = now;
@@ -1396,13 +1393,33 @@ run (void *cls,
(void) args;
(void) cfgfile;
req_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
- ctx = GNUNET_DNSSTUB_start (dns_server);
+ ctx = GNUNET_DNSSTUB_start (256);
if (NULL == ctx)
{
fprintf (stderr,
"Failed to initialize GNUnet DNS STUB\n");
return;
}
+ if (NULL == args[1])
+ {
+ fprintf (stderr,
+ "You must provide a list of DNS resolvers on the command line\n");
+ return;
+ }
+ for (unsigned int i=1;NULL != args[i];i++)
+ {
+ if (GNUNET_OK !=
+ GNUNET_DNSSTUB_add_dns_ip (ctx,
+ args[1]))
+ {
+ fprintf (stderr,
+ "Failed to use `%s' for DNS resolver\n",
+ args[i]);
+ return;
+ }
+ }
+
+
GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
NULL);
ns = GNUNET_NAMESTORE_connect (cfg);
--
To stop receiving notification emails like this one, please contact
address@hidden
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] [gnunet] branch master updated: support multiple DNS resolvers for queries (in DNSSTUB and GNS2DNS resolution for now),
gnunet <=