aboutsummaryrefslogtreecommitdiff
path: root/src/dns/dns_api.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dns/dns_api.c')
-rw-r--r--src/dns/dns_api.c387
1 files changed, 0 insertions, 387 deletions
diff --git a/src/dns/dns_api.c b/src/dns/dns_api.c
deleted file mode 100644
index 448d86a17..000000000
--- a/src/dns/dns_api.c
+++ /dev/null
@@ -1,387 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2012, 2016 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file dns/dns_api.c
23 * @brief API to access the DNS service.
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_dns_service.h"
28#include "dns.h"
29
30
31/**
32 * Handle to identify an individual DNS request.
33 */
34struct GNUNET_DNS_RequestHandle
35{
36 /**
37 * Handle to DNS API.
38 */
39 struct GNUNET_DNS_Handle *dh;
40
41 /**
42 * Stored in network byte order (as for us, it is just a random number).
43 */
44 uint64_t request_id;
45
46 /**
47 * Re-connect counter, to make sure we did not reconnect in the meantime.
48 */
49 uint32_t generation;
50};
51
52
53/**
54 * DNS handle
55 */
56struct GNUNET_DNS_Handle
57{
58 /**
59 * Connection to DNS service, or NULL.
60 */
61 struct GNUNET_MQ_Handle *mq;
62
63 /**
64 * Configuration to use.
65 */
66 const struct GNUNET_CONFIGURATION_Handle *cfg;
67
68 /**
69 * Function to call to get replies.
70 */
71 GNUNET_DNS_RequestHandler rh;
72
73 /**
74 * Closure for @e rh.
75 */
76 void *rh_cls;
77
78 /**
79 * Task to reconnect to the service.
80 */
81 struct GNUNET_SCHEDULER_Task *reconnect_task;
82
83 /**
84 * Re-connect counter, to make sure we did not reconnect in the meantime.
85 */
86 uint32_t generation;
87
88 /**
89 * Flags for events we care about.
90 */
91 enum GNUNET_DNS_Flags flags;
92
93 /**
94 * Number of GNUNET_DNS_RequestHandles we have outstanding. Must be 0 before
95 * we can be disconnected.
96 */
97 unsigned int pending_requests;
98};
99
100
101/**
102 * Reconnect to the DNS service.
103 *
104 * @param cls handle with the connection to connect
105 * @param tc scheduler context (unused)
106 */
107static void
108reconnect (void *cls);
109
110
111/**
112 * Drop the existing connection and reconnect to the DNS service.
113 *
114 * @param dh handle with the connection
115 */
116static void
117force_reconnect (struct GNUNET_DNS_Handle *dh)
118{
119 if (NULL != dh->mq)
120 {
121 GNUNET_MQ_destroy (dh->mq);
122 dh->mq = NULL;
123 }
124 dh->reconnect_task =
125 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
126 &reconnect,
127 dh);
128}
129
130
131/**
132 * Generic error handler, called with the appropriate error code and
133 * the same closure specified at the creation of the message queue.
134 * Not every message queue implementation supports an error handler.
135 *
136 * @param cls closure with the `struct GNUNET_DNS_Handle *`
137 * @param error error code
138 */
139static void
140mq_error_handler (void *cls,
141 enum GNUNET_MQ_Error error)
142{
143 struct GNUNET_DNS_Handle *dh = cls;
144
145 force_reconnect (dh);
146}
147
148
149/**
150 * This receives packets from the DNS service and calls the application to
151 * check that the request is well-formed
152 *
153 * @param cls the struct GNUNET_DNS_Handle
154 * @param req message from the service (request)
155 */
156static int
157check_request (void *cls,
158 const struct GNUNET_DNS_Request *req)
159{
160 if (0 != ntohl (req->reserved))
161 {
162 GNUNET_break (0);
163 return GNUNET_SYSERR;
164 }
165 return GNUNET_OK;
166}
167
168
169/**
170 * This receives packets from the DNS service and calls the application to
171 * handle it.
172 *
173 * @param cls the `struct GNUNET_DNS_Handle *`
174 * @param msg message from the service (request)
175 */
176static void
177handle_request (void *cls,
178 const struct GNUNET_DNS_Request *req)
179{
180 struct GNUNET_DNS_Handle *dh = cls;
181 size_t payload_length = ntohs (req->header.size) - sizeof(*req);
182 struct GNUNET_DNS_RequestHandle *rh;
183
184 rh = GNUNET_new (struct GNUNET_DNS_RequestHandle);
185 rh->dh = dh;
186 rh->request_id = req->request_id;
187 rh->generation = dh->generation;
188 dh->pending_requests++;
189 dh->rh (dh->rh_cls,
190 rh,
191 payload_length,
192 (const char *) &req[1]);
193}
194
195
196/**
197 * Reconnect to the DNS service.
198 *
199 * @param cls handle with the connection to connect
200 */
201static void
202reconnect (void *cls)
203{
204 struct GNUNET_DNS_Handle *dh = cls;
205 struct GNUNET_MQ_MessageHandler handlers[] = {
206 GNUNET_MQ_hd_var_size (request,
207 GNUNET_MESSAGE_TYPE_DNS_CLIENT_REQUEST,
208 struct GNUNET_DNS_Request,
209 dh),
210 GNUNET_MQ_handler_end ()
211 };
212 struct GNUNET_MQ_Envelope *env;
213 struct GNUNET_DNS_Register *msg;
214
215 dh->reconnect_task = NULL;
216 dh->mq = GNUNET_CLIENT_connect (dh->cfg,
217 "dns",
218 handlers,
219 &mq_error_handler,
220 dh);
221 if (NULL == dh->mq)
222 return;
223 dh->generation++;
224 env = GNUNET_MQ_msg (msg,
225 GNUNET_MESSAGE_TYPE_DNS_CLIENT_INIT);
226 msg->flags = htonl (dh->flags);
227 GNUNET_MQ_send (dh->mq,
228 env);
229}
230
231
232/**
233 * If a GNUNET_DNS_RequestHandler calls this function, the request is
234 * given to other clients or the global DNS for resolution. Once a
235 * global response has been obtained, the request handler is AGAIN
236 * called to give it a chance to observe and modify the response after
237 * the "normal" resolution. It is not legal for the request handler
238 * to call this function if a response is already present.
239 *
240 * @param rh request that should now be forwarded
241 */
242void
243GNUNET_DNS_request_forward (struct GNUNET_DNS_RequestHandle *rh)
244{
245 struct GNUNET_MQ_Envelope *env;
246 struct GNUNET_DNS_Response *resp;
247
248 GNUNET_assert (0 < rh->dh->pending_requests--);
249 if (rh->generation != rh->dh->generation)
250 {
251 GNUNET_free (rh);
252 return;
253 }
254 env = GNUNET_MQ_msg (resp,
255 GNUNET_MESSAGE_TYPE_DNS_CLIENT_RESPONSE);
256 resp->drop_flag = htonl (1);
257 resp->request_id = rh->request_id;
258 GNUNET_MQ_send (rh->dh->mq,
259 env);
260 GNUNET_free (rh);
261}
262
263
264/**
265 * If a GNUNET_DNS_RequestHandler calls this function, the request is
266 * to be dropped and no response should be generated.
267 *
268 * @param rh request that should now be dropped
269 */
270void
271GNUNET_DNS_request_drop (struct GNUNET_DNS_RequestHandle *rh)
272{
273 struct GNUNET_MQ_Envelope *env;
274 struct GNUNET_DNS_Response *resp;
275
276 GNUNET_assert (0 < rh->dh->pending_requests--);
277 if (rh->generation != rh->dh->generation)
278 {
279 GNUNET_free (rh);
280 return;
281 }
282 env = GNUNET_MQ_msg (resp,
283 GNUNET_MESSAGE_TYPE_DNS_CLIENT_RESPONSE);
284 resp->request_id = rh->request_id;
285 resp->drop_flag = htonl (0);
286 GNUNET_MQ_send (rh->dh->mq,
287 env);
288 GNUNET_free (rh);
289}
290
291
292/**
293 * If a GNUNET_DNS_RequestHandler calls this function, the request is
294 * supposed to be answered with the data provided to this call (with
295 * the modifications the function might have made).
296 *
297 * @param rh request that should now be answered
298 * @param reply_length size of @a reply (uint16_t to force sane size)
299 * @param reply reply data
300 */
301void
302GNUNET_DNS_request_answer (struct GNUNET_DNS_RequestHandle *rh,
303 uint16_t reply_length,
304 const char *reply)
305{
306 struct GNUNET_MQ_Envelope *env;
307 struct GNUNET_DNS_Response *resp;
308
309 GNUNET_assert (0 < rh->dh->pending_requests--);
310 if (rh->generation != rh->dh->generation)
311 {
312 GNUNET_free (rh);
313 return;
314 }
315 if (reply_length + sizeof(struct GNUNET_DNS_Response)
316 >= GNUNET_MAX_MESSAGE_SIZE)
317 {
318 GNUNET_break (0);
319 GNUNET_free (rh);
320 return;
321 }
322 env = GNUNET_MQ_msg_extra (resp,
323 reply_length,
324 GNUNET_MESSAGE_TYPE_DNS_CLIENT_RESPONSE);
325 resp->drop_flag = htonl (2);
326 resp->request_id = rh->request_id;
327 GNUNET_memcpy (&resp[1],
328 reply,
329 reply_length);
330 GNUNET_MQ_send (rh->dh->mq,
331 env);
332 GNUNET_free (rh);
333}
334
335
336/**
337 * Connect to the service-dns
338 *
339 * @param cfg configuration to use
340 * @param flags when to call @a rh
341 * @param rh function to call with DNS requests
342 * @param rh_cls closure to pass to @a rh
343 * @return DNS handle
344 */
345struct GNUNET_DNS_Handle *
346GNUNET_DNS_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
347 enum GNUNET_DNS_Flags flags,
348 GNUNET_DNS_RequestHandler rh,
349 void *rh_cls)
350{
351 struct GNUNET_DNS_Handle *dh;
352
353 dh = GNUNET_new (struct GNUNET_DNS_Handle);
354 dh->cfg = cfg;
355 dh->flags = flags;
356 dh->rh = rh;
357 dh->rh_cls = rh_cls;
358 dh->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect, dh);
359 return dh;
360}
361
362
363/**
364 * Disconnect from the DNS service.
365 *
366 * @param dh DNS handle
367 */
368void
369GNUNET_DNS_disconnect (struct GNUNET_DNS_Handle *dh)
370{
371 if (NULL != dh->mq)
372 {
373 GNUNET_MQ_destroy (dh->mq);
374 dh->mq = NULL;
375 }
376 if (NULL != dh->reconnect_task)
377 {
378 GNUNET_SCHEDULER_cancel (dh->reconnect_task);
379 dh->reconnect_task = NULL;
380 }
381 /* make sure client has no pending requests left over! */
382 GNUNET_break (0 == dh->pending_requests);
383 GNUNET_free (dh);
384}
385
386
387/* end of dns_api.c */