diff options
author | Christian Grothoff <christian@grothoff.org> | 2018-03-30 20:55:42 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2018-03-30 20:55:42 +0200 |
commit | 466b556fda9d5b946e0099bfbe53099c52bcb433 (patch) | |
tree | 3fd3de33d608c26ae6526136a134f76e3ecc501f /src/dns | |
parent | d9c9f4dd2f61620d1848c8c32a36341ec1f1e41e (diff) | |
download | gnunet-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.c | 115 |
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 | */ | ||
294 | static void | ||
295 | transmit_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 | ||