aboutsummaryrefslogtreecommitdiff
path: root/src/dns
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2018-03-30 20:55:42 +0200
committerChristian Grothoff <christian@grothoff.org>2018-03-30 20:55:42 +0200
commit466b556fda9d5b946e0099bfbe53099c52bcb433 (patch)
tree3fd3de33d608c26ae6526136a134f76e3ecc501f /src/dns
parentd9c9f4dd2f61620d1848c8c32a36341ec1f1e41e (diff)
downloadgnunet-466b556fda9d5b946e0099bfbe53099c52bcb433.tar.gz
gnunet-466b556fda9d5b946e0099bfbe53099c52bcb433.zip
retry DNS queries, as DNS is UDP-based and hence unreliable
Diffstat (limited to 'src/dns')
-rw-r--r--src/dns/dnsstub.c115
1 files changed, 88 insertions, 27 deletions
diff --git a/src/dns/dnsstub.c b/src/dns/dnsstub.c
index 68cd55275..364b6fe28 100644
--- a/src/dns/dnsstub.c
+++ b/src/dns/dnsstub.c
@@ -33,6 +33,11 @@
33#define REQUEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) 33#define REQUEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
34 34
35/** 35/**
36 * Timeout for retrying DNS queries.
37 */
38#define DNS_RETRANSMIT_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 250)
39
40/**
36 * How many DNS sockets do we open at most at the same time? 41 * How many DNS sockets do we open at most at the same time?
37 * (technical socket maximum is this number x2 for IPv4+IPv6) 42 * (technical socket maximum is this number x2 for IPv4+IPv6)
38 */ 43 */
@@ -68,7 +73,12 @@ struct GNUNET_DNSSTUB_RequestSocket
68 /** 73 /**
69 * Task for reading from dnsout4 and dnsout6. 74 * Task for reading from dnsout4 and dnsout6.
70 */ 75 */
71 struct GNUNET_SCHEDULER_Task * read_task; 76 struct GNUNET_SCHEDULER_Task *read_task;
77
78 /**
79 * Task for retrying transmission of the query.
80 */
81 struct GNUNET_SCHEDULER_Task *retry_task;
72 82
73 /** 83 /**
74 * When should this request time out? 84 * When should this request time out?
@@ -85,6 +95,16 @@ struct GNUNET_DNSSTUB_RequestSocket
85 */ 95 */
86 socklen_t addrlen; 96 socklen_t addrlen;
87 97
98 /**
99 * Query we sent to @e addr.
100 */
101 void *request;
102
103 /**
104 * Number of bytes in @a request.
105 */
106 size_t request_len;
107
88}; 108};
89 109
90 110
@@ -107,7 +127,6 @@ struct GNUNET_DNSSTUB_Context
107}; 127};
108 128
109 129
110
111/** 130/**
112 * We're done with a `struct GNUNET_DNSSTUB_RequestSocket`, close it for now. 131 * We're done with a `struct GNUNET_DNSSTUB_RequestSocket`, close it for now.
113 * 132 *
@@ -131,6 +150,16 @@ cleanup_rs (struct GNUNET_DNSSTUB_RequestSocket *rs)
131 GNUNET_SCHEDULER_cancel (rs->read_task); 150 GNUNET_SCHEDULER_cancel (rs->read_task);
132 rs->read_task = NULL; 151 rs->read_task = NULL;
133 } 152 }
153 if (NULL != rs->retry_task)
154 {
155 GNUNET_SCHEDULER_cancel (rs->retry_task);
156 rs->retry_task = NULL;
157 }
158 if (NULL != rs->request)
159 {
160 GNUNET_free (rs->request);
161 rs->request = NULL;
162 }
134} 163}
135 164
136 165
@@ -227,6 +256,16 @@ get_request_socket (struct GNUNET_DNSSTUB_Context *ctx,
227 GNUNET_SCHEDULER_cancel (rs->read_task); 256 GNUNET_SCHEDULER_cancel (rs->read_task);
228 rs->read_task = NULL; 257 rs->read_task = NULL;
229 } 258 }
259 if (NULL != rs->retry_task)
260 {
261 GNUNET_SCHEDULER_cancel (rs->retry_task);
262 rs->retry_task = NULL;
263 }
264 if (NULL != rs->request)
265 {
266 GNUNET_free (rs->request);
267 rs->request = NULL;
268 }
230 if ( (NULL == rs->dnsout4) && 269 if ( (NULL == rs->dnsout4) &&
231 (NULL == rs->dnsout6) ) 270 (NULL == rs->dnsout6) )
232 return NULL; 271 return NULL;
@@ -239,13 +278,50 @@ get_request_socket (struct GNUNET_DNSSTUB_Context *ctx,
239 REQUEST_TIMEOUT, 278 REQUEST_TIMEOUT,
240 rset, 279 rset,
241 NULL, 280 NULL,
242 &read_response, rs); 281 &read_response,
282 rs);
243 GNUNET_NETWORK_fdset_destroy (rset); 283 GNUNET_NETWORK_fdset_destroy (rset);
244 return rs; 284 return rs;
245} 285}
246 286
247 287
248/** 288/**
289 * Task to (re)transmit the DNS query, possibly repeatedly until
290 * we succeed.
291 *
292 * @param cls our `struct GNUNET_DNSSTUB_RequestSocket *`
293 */
294static void
295transmit_query (void *cls)
296{
297 struct GNUNET_DNSSTUB_RequestSocket *rs = cls;
298 struct GNUNET_NETWORK_Handle *ret;
299
300 rs->retry_task = NULL;
301 ret = (NULL != rs->dnsout4) ? rs->dnsout4 : rs->dnsout6;
302 GNUNET_assert (NULL != ret);
303 if (GNUNET_SYSERR ==
304 GNUNET_NETWORK_socket_sendto (ret,
305 rs->request,
306 rs->request_len,
307 (struct sockaddr *) &rs->addr,
308 rs->addrlen))
309 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
310 _("Failed to send DNS request to %s\n"),
311 GNUNET_a2s ((struct sockaddr *) &rs->addr,
312 rs->addrlen));
313 else
314 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
315 _("Sent DNS request to %s\n"),
316 GNUNET_a2s ((struct sockaddr *) &rs->addr,
317 rs->addrlen));
318 rs->retry_task = GNUNET_SCHEDULER_add_delayed (DNS_RETRANSMIT_DELAY,
319 &transmit_query,
320 rs);
321}
322
323
324/**
249 * Perform DNS resolution. 325 * Perform DNS resolution.
250 * 326 *
251 * @param ctx stub resolver to use 327 * @param ctx stub resolver to use
@@ -267,36 +343,21 @@ GNUNET_DNSSTUB_resolve (struct GNUNET_DNSSTUB_Context *ctx,
267 void *rc_cls) 343 void *rc_cls)
268{ 344{
269 struct GNUNET_DNSSTUB_RequestSocket *rs; 345 struct GNUNET_DNSSTUB_RequestSocket *rs;
270 struct GNUNET_NETWORK_Handle *ret;
271 int af;
272 346
273 af = sa->sa_family; 347 if (NULL == (rs = get_request_socket (ctx,
274 if (NULL == (rs = get_request_socket (ctx, af))) 348 sa->sa_family)))
275 return NULL; 349 return NULL;
276 if (NULL != rs->dnsout4)
277 ret = rs->dnsout4;
278 else
279 ret = rs->dnsout6;
280 GNUNET_assert (NULL != ret);
281 GNUNET_memcpy (&rs->addr, 350 GNUNET_memcpy (&rs->addr,
282 sa, 351 sa,
283 sa_len); 352 sa_len);
284 rs->addrlen = sa_len; 353 rs->addrlen = sa_len;
285 rs->rc = rc; 354 rs->rc = rc;
286 rs->rc_cls = rc_cls; 355 rs->rc_cls = rc_cls;
287 if (GNUNET_SYSERR == 356 rs->request = GNUNET_memdup (request,
288 GNUNET_NETWORK_socket_sendto (ret, 357 request_len);
289 request, 358 rs->request_len = request_len;
290 request_len, 359 rs->retry_task = GNUNET_SCHEDULER_add_now (&transmit_query,
291 sa, 360 rs);
292 sa_len))
293 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
294 _("Failed to send DNS request to %s\n"),
295 GNUNET_a2s (sa, sa_len));
296 else
297 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
298 _("Sent DNS request to %s\n"),
299 GNUNET_a2s (sa, sa_len));
300 return rs; 361 return rs;
301} 362}
302 363