aboutsummaryrefslogtreecommitdiff
path: root/src/dns/dns_api.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-01-15 20:41:40 +0000
committerChristian Grothoff <christian@grothoff.org>2012-01-15 20:41:40 +0000
commit1574e0f8c2a55363c024a95f440ba7be647efbe1 (patch)
tree5e4507d9aa404ac983c5774b71b25ec6174ee7cc /src/dns/dns_api.c
parent5ec7048ed9ffeddbe06e34a31d388080fae143e5 (diff)
downloadgnunet-1574e0f8c2a55363c024a95f440ba7be647efbe1.tar.gz
gnunet-1574e0f8c2a55363c024a95f440ba7be647efbe1.zip
-removing legacy dns/vpn/exit code and renaming -new versions to current
Diffstat (limited to 'src/dns/dns_api.c')
-rw-r--r--src/dns/dns_api.c664
1 files changed, 422 insertions, 242 deletions
diff --git a/src/dns/dns_api.c b/src/dns/dns_api.c
index b434fc1e7..dfce0af1b 100644
--- a/src/dns/dns_api.c
+++ b/src/dns/dns_api.c
@@ -1,342 +1,522 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet
3 (C) 2010 Christian Grothoff 3 (C) 2012 Christian Grothoff (and other contributing authors)
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your 7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version. 8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
9 20
10 GNUnet is distributed in the hope that it will be useful, but 21/**
11 WITHOUT ANY WARRANTY; without even the implied warranty of 22 * @file dns/dns_api_new.c
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23 * @brief API to access the DNS service.
13 General Public License for more details. 24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_dns_service.h"
28#include "dns.h"
14 29
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20 30
21/** 31/**
22 * @file dns/dns_api.c 32 * Reply to send to service.
23 * @brief
24 * @author Philipp Toelke
25 */ 33 */
26#include <platform.h> 34struct ReplyQueueEntry
27#include <gnunet_common.h> 35{
28#include <gnunet_client_lib.h> 36 /**
29#include <gnunet_os_lib.h> 37 * Kept in DLL.
30#include <gnunet_mesh_service.h> 38 */
31#include <gnunet_protocols.h> 39 struct ReplyQueueEntry *next;
32#include <gnunet_server_lib.h>
33#include <gnunet_container_lib.h>
34#include <block_dns.h>
35 40
36#include "gnunet_dns_service.h" 41 /**
37#include "dns.h" 42 * Kept in DLL.
43 */
44 struct ReplyQueueEntry *prev;
45
46 /**
47 * Message to transmit, allocated at the end of this struct.
48 */
49 const struct GNUNET_MessageHeader *msg;
38 50
39struct query_packet_list 51};
52
53
54/**
55 * Handle to identify an individual DNS request.
56 */
57struct GNUNET_DNS_RequestHandle
40{ 58{
41 struct query_packet_list *next; 59
42 struct query_packet_list *prev; 60 /**
43 struct query_packet pkt; 61 * Handle to DNS API.
62 */
63 struct GNUNET_DNS_Handle *dh;
64
65 /**
66 * Stored in network byte order (as for us, it is just a random number).
67 */
68 uint64_t request_id;
69
70 /**
71 * Re-connect counter, to make sure we did not reconnect in the meantime.
72 */
73 uint32_t generation;
74
44}; 75};
45 76
46 77
78/**
79 * DNS handle
80 */
47struct GNUNET_DNS_Handle 81struct GNUNET_DNS_Handle
48{ 82{
49 struct query_packet_list *head; 83
50 struct query_packet_list *tail; 84 /**
85 * Connection to DNS service, or NULL.
86 */
51 struct GNUNET_CLIENT_Connection *dns_connection; 87 struct GNUNET_CLIENT_Connection *dns_connection;
52 unsigned char restart_hijack;
53 88
89 /**
90 * Handle to active transmission request, or NULL.
91 */
54 struct GNUNET_CLIENT_TransmitHandle *dns_transmit_handle; 92 struct GNUNET_CLIENT_TransmitHandle *dns_transmit_handle;
55 93
94 /**
95 * Configuration to use.
96 */
56 const struct GNUNET_CONFIGURATION_Handle *cfg; 97 const struct GNUNET_CONFIGURATION_Handle *cfg;
57 98
58 GNUNET_DNS_ResponseCallback process_answer_cb; 99 /**
100 * Function to call to get replies.
101 */
102 GNUNET_DNS_RequestHandler rh;
59 103
60 void *process_answer_cb_cls; 104 /**
61}; 105 * Closure for 'rh'.
106 */
107 void *rh_cls;
62 108
109 /**
110 * Head of replies to transmit.
111 */
112 struct ReplyQueueEntry *rq_head;
63 113
64/** 114 /**
65 * Callback called by notify_transmit_ready; sends dns-queries or rehijack-messages 115 * Tail of replies to transmit.
66 * to the service-dns 116 */
67 * {{{ 117 struct ReplyQueueEntry *rq_tail;
68 */
69size_t
70send_query (void *cls GNUNET_UNUSED, size_t size, void *buf)
71{
72 struct GNUNET_DNS_Handle *h = cls;
73 118
74 size_t len; 119 /**
120 * Task to reconnect to the service.
121 */
122 GNUNET_SCHEDULER_TaskIdentifier reconnect_task;
75 123
76 h->dns_transmit_handle = NULL; 124 /**
125 * Re-connect counter, to make sure we did not reconnect in the meantime.
126 */
127 uint32_t generation;
128
129 /**
130 * Flags for events we care about.
131 */
132 enum GNUNET_DNS_Flags flags;
77 133
78 /* 134 /**
79 * Send the rehijack-message 135 * Did we start the receive loop yet?
80 */ 136 */
81 if (h->restart_hijack == 1) 137 int in_receive;
82 { 138
83 h->restart_hijack = 0; 139 /**
84 /* 140 * Number of GNUNET_DNS_RequestHandles we have outstanding. Must be 0 before
85 * The message is just a header 141 * we can be disconnected.
86 */ 142 */
87 GNUNET_assert (sizeof (struct GNUNET_MessageHeader) <= size); 143 unsigned int pending_requests;
88 struct GNUNET_MessageHeader *hdr = buf; 144};
89 145
90 len = sizeof (struct GNUNET_MessageHeader);
91 hdr->size = htons (len);
92 hdr->type = htons (GNUNET_MESSAGE_TYPE_REHIJACK);
93 }
94 else if (h->head != NULL)
95 {
96 struct query_packet_list *query = h->head;
97 146
98 len = ntohs (query->pkt.hdr.size); 147/**
148 * Add the given reply to our transmission queue and trigger sending if needed.
149 *
150 * @param dh handle with the connection
151 * @param qe reply to queue
152 */
153static void
154queue_reply (struct GNUNET_DNS_Handle *dh,
155 struct ReplyQueueEntry *qe);
99 156
100 GNUNET_assert (len <= size);
101 157
102 memcpy (buf, &query->pkt.hdr, len); 158/**
159 * Reconnect to the DNS service.
160 *
161 * @param cls handle with the connection to connect
162 * @param tc scheduler context (unused)
163 */
164static void
165reconnect (void *cls,
166 const struct GNUNET_SCHEDULER_TaskContext *tc)
167{
168 struct GNUNET_DNS_Handle *dh = cls;
169 struct ReplyQueueEntry *qe;
170 struct GNUNET_DNS_Register *msg;
103 171
104 GNUNET_CONTAINER_DLL_remove (h->head, h->tail, query); 172 dh->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
173 dh->dns_connection = GNUNET_CLIENT_connect ("dns", dh->cfg);
174 if (NULL == dh->dns_connection)
175 return;
176 dh->generation++;
177 qe = GNUNET_malloc (sizeof (struct ReplyQueueEntry) +
178 sizeof (struct GNUNET_DNS_Register));
179 msg = (struct GNUNET_DNS_Register*) &qe[1];
180 qe->msg = &msg->header;
181 msg->header.size = htons (sizeof (struct GNUNET_DNS_Register));
182 msg->header.type = htons (GNUNET_MESSAGE_TYPE_DNS_CLIENT_INIT);
183 msg->flags = htonl (dh->flags);
184 queue_reply (dh, qe);
185}
105 186
106 GNUNET_free (query); 187
107 } 188/**
108 else 189 * Disconnect from the DNS service.
190 *
191 * @param dh handle with the connection to disconnect
192 */
193static void
194disconnect (struct GNUNET_DNS_Handle *dh)
195{
196 struct ReplyQueueEntry *qe;
197
198 if (NULL != dh->dns_transmit_handle)
109 { 199 {
110 GNUNET_break (0); 200 GNUNET_CLIENT_notify_transmit_ready_cancel (dh->dns_transmit_handle);
111 len = 0; 201 dh->dns_transmit_handle = NULL;
112 } 202 }
113 203 if (NULL != dh->dns_connection)
114 /*
115 * Check whether more data is to be sent
116 */
117 if (h->head != NULL)
118 { 204 {
119 h->dns_transmit_handle = 205 GNUNET_CLIENT_disconnect (dh->dns_connection, GNUNET_NO);
120 GNUNET_CLIENT_notify_transmit_ready (h->dns_connection, 206 dh->dns_connection = NULL;
121 ntohs (h->head->pkt.hdr.size),
122 GNUNET_TIME_UNIT_FOREVER_REL,
123 GNUNET_YES, &send_query, h);
124 } 207 }
125 else if (h->restart_hijack == 1) 208 while (NULL != (qe = dh->rq_head))
126 { 209 {
127 h->dns_transmit_handle = 210 GNUNET_CONTAINER_DLL_remove (dh->rq_head,
128 GNUNET_CLIENT_notify_transmit_ready (h->dns_connection, 211 dh->rq_tail,
129 sizeof (struct 212 qe);
130 GNUNET_MessageHeader), 213 GNUNET_free (qe);
131 GNUNET_TIME_UNIT_FOREVER_REL,
132 GNUNET_YES, &send_query, h);
133 } 214 }
134 215 dh->in_receive = GNUNET_NO;
135 return len;
136} 216}
137 217
138/* }}} */
139
140
141 218
142/** 219/**
143 * This receives packets from the service-dns and schedules process_answer to 220 * This receives packets from the DNS service and calls the application to
144 * handle it 221 * handle it.
222 *
223 * @param cls the struct GNUNET_DNS_Handle
224 * @param msg message from the service (request)
145 */ 225 */
146static void 226static void
147dns_answer_handler (void *cls, 227request_handler (void *cls,
148 const struct GNUNET_MessageHeader *msg) 228 const struct GNUNET_MessageHeader *msg)
149{ 229{
150 struct GNUNET_DNS_Handle *h = cls; 230 struct GNUNET_DNS_Handle *dh = cls;
231 const struct GNUNET_DNS_Request *req;
232 struct GNUNET_DNS_RequestHandle *rh;
233 size_t payload_length;
151 234
152 /* the service disconnected, reconnect after short wait */ 235 /* the service disconnected, reconnect after short wait */
153 if (msg == NULL) 236 if (msg == NULL)
154 { 237 {
155 if (h->dns_transmit_handle != NULL) 238 disconnect (dh);
156 GNUNET_CLIENT_notify_transmit_ready_cancel (h->dns_transmit_handle); 239 dh->reconnect_task =
157 h->dns_transmit_handle = NULL;
158 GNUNET_CLIENT_disconnect (h->dns_connection, GNUNET_NO);
159 h->dns_connection = NULL;
160#if 0
161 h->conn_task =
162 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, 240 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
163 &connect_to_service_dns, h); 241 &reconnect, dh);
164#endif
165 return; 242 return;
166 } 243 }
167 244 if ( (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_DNS_CLIENT_REQUEST) ||
168 /* the service did something strange, reconnect immediately */ 245 (ntohs (msg->size) < sizeof (struct GNUNET_DNS_Request)) )
169 if (msg->type != htons (GNUNET_MESSAGE_TYPE_VPN_DNS_LOCAL_RESPONSE_DNS))
170 { 246 {
247 /* the service did something strange, reconnect immediately */
171 GNUNET_break (0); 248 GNUNET_break (0);
172 GNUNET_CLIENT_disconnect (h->dns_connection, GNUNET_NO); 249 disconnect (dh);
173 h->dns_connection = NULL; 250 dh->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect, dh);
174#if 0
175 conn_task = GNUNET_SCHEDULER_add_now (&connect_to_service_dns, NULL);
176#endif
177 return; 251 return;
178 } 252 }
179 h->process_answer_cb (h->process_answer_cb_cls, 253 req = (const struct GNUNET_DNS_Request *) msg;
180 (const struct answer_packet*) msg); 254 GNUNET_break (ntohl (req->reserved) == 0);
181 GNUNET_CLIENT_receive (h->dns_connection, &dns_answer_handler, h, 255 payload_length = ntohs (req->header.size) - sizeof (struct GNUNET_DNS_Request);
256 GNUNET_CLIENT_receive (dh->dns_connection,
257 &request_handler, dh,
182 GNUNET_TIME_UNIT_FOREVER_REL); 258 GNUNET_TIME_UNIT_FOREVER_REL);
259
260 /* finally, pass request to callback for answers */
261 rh = GNUNET_malloc (sizeof (struct GNUNET_DNS_RequestHandle));
262 rh->dh =dh;
263 rh->request_id = req->request_id;
264 rh->generation = dh->generation;
265 dh->pending_requests++;
266 dh->rh (dh->rh_cls,
267 rh,
268 payload_length,
269 (const char*) &req[1]);
183} 270}
184 271
185 272
186/** 273/**
187 * Connect to the service-dns 274 * Callback called by notify_transmit_ready; sends DNS replies
275 * to the DNS service.
276 *
277 * @param cls the struct GNUNET_DNS_Handle
278 * @param size number of bytes available in buf
279 * @param buf where to copy the message for transmission
280 * @return number of bytes copied to buf
188 */ 281 */
189struct GNUNET_DNS_Handle * 282static size_t
190GNUNET_DNS_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, 283send_response (void *cls, size_t size, void *buf)
191 GNUNET_DNS_ResponseCallback cb,
192 void *cb_cls)
193{ 284{
194 struct GNUNET_DNS_Handle *h; 285 struct GNUNET_DNS_Handle *dh = cls;
195 286 struct ReplyQueueEntry *qe;
196 h = GNUNET_malloc (sizeof (struct GNUNET_DNS_Handle)); 287 size_t len;
197 h->cfg = cfg; 288
198 h->process_answer_cb = cb; 289 dh->dns_transmit_handle = NULL;
199 h->process_answer_cb_cls = cb_cls; 290 if (NULL == buf)
200 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting to service-dns\n"); 291 {
201 h->dns_connection = GNUNET_CLIENT_connect ("dns", h->cfg); 292 disconnect (dh);
202 /* This would most likely be a misconfiguration */ 293 dh->reconnect_task =
203 GNUNET_assert (NULL != h->dns_connection); 294 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
204 GNUNET_CLIENT_receive (h->dns_connection, 295 &reconnect, dh);
205 &dns_answer_handler, NULL, 296 return 0;
206 GNUNET_TIME_UNIT_FOREVER_REL); 297 }
207 /* If a packet is already in the list, schedule to send it */ 298 qe = dh->rq_head;
208 if (h->dns_transmit_handle == NULL && h->head != NULL) 299 if (NULL == qe)
209 h->dns_transmit_handle = 300 return 0;
210 GNUNET_CLIENT_notify_transmit_ready (h->dns_connection, 301 len = ntohs (qe->msg->size);
211 ntohs (h->head->pkt.hdr.size), 302 if (len > size)
212 GNUNET_TIME_UNIT_FOREVER_REL, 303 {
213 GNUNET_YES, &send_query, h); 304 dh->dns_transmit_handle =
214 else if (h->dns_transmit_handle == NULL && h->restart_hijack == 1) 305 GNUNET_CLIENT_notify_transmit_ready (dh->dns_connection,
306 len,
307 GNUNET_TIME_UNIT_FOREVER_REL,
308 GNUNET_NO,
309 &send_response, dh);
310 return 0;
311 }
312 memcpy (buf, qe->msg, len);
313 GNUNET_CONTAINER_DLL_remove (dh->rq_head,
314 dh->rq_tail,
315 qe);
316 GNUNET_free (qe);
317 if (GNUNET_NO == dh->in_receive)
215 { 318 {
216 h->dns_transmit_handle = 319 dh->in_receive = GNUNET_YES;
217 GNUNET_CLIENT_notify_transmit_ready (h->dns_connection, 320 GNUNET_CLIENT_receive (dh->dns_connection,
218 sizeof (struct 321 &request_handler, dh,
219 GNUNET_MessageHeader), 322 GNUNET_TIME_UNIT_FOREVER_REL);
220 GNUNET_TIME_UNIT_FOREVER_REL,
221 GNUNET_YES, &send_query, NULL);
222 } 323 }
223 return h; 324 if (NULL != (qe = dh->rq_head))
325 {
326 dh->dns_transmit_handle =
327 GNUNET_CLIENT_notify_transmit_ready (dh->dns_connection,
328 ntohs (qe->msg->size),
329 GNUNET_TIME_UNIT_FOREVER_REL,
330 GNUNET_NO,
331 &send_response, dh);
332 }
333 return len;
334}
335
336
337/**
338 * Add the given reply to our transmission queue and trigger sending if needed.
339 *
340 * @param dh handle with the connection
341 * @param qe reply to queue
342 */
343static void
344queue_reply (struct GNUNET_DNS_Handle *dh,
345 struct ReplyQueueEntry *qe)
346{
347 if (NULL == dh->dns_connection)
348 {
349 GNUNET_free (qe);
350 return;
351 }
352 GNUNET_CONTAINER_DLL_insert_tail (dh->rq_head,
353 dh->rq_tail,
354 qe);
355 if (NULL != dh->dns_transmit_handle)
356 return;
357 /* trigger sending */
358 dh->dns_transmit_handle =
359 GNUNET_CLIENT_notify_transmit_ready (dh->dns_connection,
360 ntohs (dh->rq_head->msg->size),
361 GNUNET_TIME_UNIT_FOREVER_REL,
362 GNUNET_NO,
363 &send_response, dh);
224} 364}
225 365
226 366
367/**
368 * If a GNUNET_DNS_RequestHandler calls this function, the request is
369 * given to other clients or the global DNS for resolution. Once a
370 * global response has been obtained, the request handler is AGAIN
371 * called to give it a chance to observe and modify the response after
372 * the "normal" resolution. It is not legal for the request handler
373 * to call this function if a response is already present.
374 *
375 * @param rh request that should now be forwarded
376 */
227void 377void
228GNUNET_DNS_restart_hijack (struct GNUNET_DNS_Handle *h) 378GNUNET_DNS_request_forward (struct GNUNET_DNS_RequestHandle *rh)
229{ 379{
230 h->restart_hijack = 1; 380 struct ReplyQueueEntry *qe;
231 if (NULL != h->dns_connection && h->dns_transmit_handle == NULL) 381 struct GNUNET_DNS_Response *resp;
232 h->dns_transmit_handle = 382
233 GNUNET_CLIENT_notify_transmit_ready (h->dns_connection, 383 GNUNET_assert (0 < rh->dh->pending_requests--);
234 sizeof (struct 384 if (rh->generation != rh->dh->generation)
235 GNUNET_MessageHeader), 385 {
236 GNUNET_TIME_UNIT_FOREVER_REL, 386 GNUNET_free (rh);
237 GNUNET_YES, &send_query, h); 387 return;
388 }
389 qe = GNUNET_malloc (sizeof (struct ReplyQueueEntry) +
390 sizeof (struct GNUNET_DNS_Response));
391 resp = (struct GNUNET_DNS_Response*) &qe[1];
392 qe->msg = &resp->header;
393 resp->header.size = htons (sizeof (struct GNUNET_DNS_Response));
394 resp->header.type = htons (GNUNET_MESSAGE_TYPE_DNS_CLIENT_RESPONSE);
395 resp->drop_flag = htonl (1);
396 resp->request_id = rh->request_id;
397 queue_reply (rh->dh, qe);
398 GNUNET_free (rh);
238} 399}
239 400
240 401
241/** 402/**
242 * FIXME: we should not expost our internal structures like this. 403 * If a GNUNET_DNS_RequestHandler calls this function, the request is
243 * Just a quick initial hack. 404 * to be dropped and no response should be generated.
405 *
406 * @param rh request that should now be dropped
244 */ 407 */
245static void 408void
246queue_request (struct GNUNET_DNS_Handle *h, 409GNUNET_DNS_request_drop (struct GNUNET_DNS_RequestHandle *rh)
247 struct query_packet_list *q)
248{ 410{
249 GNUNET_CONTAINER_DLL_insert_tail (h->head, h->tail, q); 411 struct ReplyQueueEntry *qe;
250 if (h->dns_connection != NULL && h->dns_transmit_handle == NULL) 412 struct GNUNET_DNS_Response *resp;
251 h->dns_transmit_handle =
252 GNUNET_CLIENT_notify_transmit_ready (h->dns_connection, ntohs(q->pkt.hdr.size),
253 GNUNET_TIME_UNIT_FOREVER_REL,
254 GNUNET_YES, &send_query,
255 h);
256}
257 413
414 GNUNET_assert (0 < rh->dh->pending_requests--);
415 if (rh->generation != rh->dh->generation)
416 {
417 GNUNET_free (rh);
418 return;
419 }
420 qe = GNUNET_malloc (sizeof (struct ReplyQueueEntry) +
421 sizeof (struct GNUNET_DNS_Response));
422 resp = (struct GNUNET_DNS_Response*) &qe[1];
423 qe->msg = &resp->header;
424 resp->header.size = htons (sizeof (struct GNUNET_DNS_Response));
425 resp->header.type = htons (GNUNET_MESSAGE_TYPE_DNS_CLIENT_RESPONSE);
426 resp->request_id = rh->request_id;
427 resp->drop_flag = htonl (0);
428 queue_reply (rh->dh, qe);
429 GNUNET_free (rh);
430}
258 431
259 432
260/** 433/**
261 * Process a DNS request sent to an IPv4 resolver. Pass it 434 * If a GNUNET_DNS_RequestHandler calls this function, the request is
262 * to the DNS service for resolution. 435 * supposed to be answered with the data provided to this call (with
436 * the modifications the function might have made).
263 * 437 *
264 * @param h DNS handle 438 * @param rh request that should now be answered
265 * @param dst_ip destination IPv4 address 439 * @param reply_length size of reply (uint16_t to force sane size)
266 * @param src_ip source IPv4 address (usually local machine) 440 * @param reply reply data
267 * @param src_port source port (to be used for reply)
268 * @param udp_packet_len length of the UDP payload in bytes
269 * @param udp_packet UDP payload
270 */ 441 */
271void 442void
272GNUNET_DNS_queue_request_v4 (struct GNUNET_DNS_Handle *h, 443GNUNET_DNS_request_answer (struct GNUNET_DNS_RequestHandle *rh,
273 const struct in_addr *dst_ip, 444 uint16_t reply_length,
274 const struct in_addr *src_ip, 445 const char *reply)
275 uint16_t src_port,
276 size_t udp_packet_len,
277 const char *udp_packet)
278{ 446{
279 size_t len = sizeof (struct query_packet) + udp_packet_len - 1; 447 struct ReplyQueueEntry *qe;
280 struct query_packet_list *query = 448 struct GNUNET_DNS_Response *resp;
281 GNUNET_malloc (len + sizeof (struct query_packet_list) - 449
282 sizeof (struct query_packet)); 450 GNUNET_assert (0 < rh->dh->pending_requests--);
283 query->pkt.hdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_DNS_LOCAL_QUERY_DNS); 451 if (rh->generation != rh->dh->generation)
284 query->pkt.hdr.size = htons (len); 452 {
285 memcpy (query->pkt.orig_to, dst_ip, 4); 453 GNUNET_free (rh);
286 memcpy (query->pkt.orig_from, src_ip, 4); 454 return;
287 query->pkt.addrlen = 4; 455 }
288 query->pkt.src_port = htons (src_port); 456 if (reply_length + sizeof (struct GNUNET_DNS_Response) >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
289 memcpy (query->pkt.data, udp_packet, udp_packet_len); 457 {
290 queue_request (h, query); 458 GNUNET_break (0);
459 GNUNET_free (rh);
460 return;
461 }
462 qe = GNUNET_malloc (sizeof (struct ReplyQueueEntry) +
463 sizeof (struct GNUNET_DNS_Response) + reply_length);
464 resp = (struct GNUNET_DNS_Response*) &qe[1];
465 qe->msg = &resp->header;
466 resp->header.size = htons (sizeof (struct GNUNET_DNS_Response) + reply_length);
467 resp->header.type = htons (GNUNET_MESSAGE_TYPE_DNS_CLIENT_RESPONSE);
468 resp->drop_flag = htonl (2);
469 resp->request_id = rh->request_id;
470 memcpy (&resp[1], reply, reply_length);
471 queue_reply (rh->dh, qe);
472 GNUNET_free (rh);
291} 473}
292 474
293 475
294/** 476/**
295 * Process a DNS request sent to an IPv6 resolver. Pass it 477 * Connect to the service-dns
296 * to the DNS service for resolution.
297 * 478 *
298 * @param h DNS handle 479 * @param cfg configuration to use
299 * @param dst_ip destination IPv6 address 480 * @param flags when to call rh
300 * @param src_ip source IPv6 address (usually local machine) 481 * @param rh function to call with DNS requests
301 * @param src_port source port (to be used for reply) 482 * @param rh_cls closure to pass to rh
302 * @param udp_packet_len length of the UDP payload in bytes 483 * @return DNS handle
303 * @param udp_packet UDP payload
304 */ 484 */
305void 485struct GNUNET_DNS_Handle *
306GNUNET_DNS_queue_request_v6 (struct GNUNET_DNS_Handle *h, 486GNUNET_DNS_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
307 const struct in6_addr *dst_ip, 487 enum GNUNET_DNS_Flags flags,
308 const struct in6_addr *src_ip, 488 GNUNET_DNS_RequestHandler rh,
309 uint16_t src_port, 489 void *rh_cls)
310 size_t udp_packet_len,
311 const char *udp_packet)
312{ 490{
313 size_t len = 491 struct GNUNET_DNS_Handle *dh;
314 sizeof (struct query_packet) + udp_packet_len - 1; 492
315 struct query_packet_list *query = 493 dh = GNUNET_malloc (sizeof (struct GNUNET_DNS_Handle));
316 GNUNET_malloc (len + sizeof (struct query_packet_list) - 494 dh->cfg = cfg;
317 sizeof (struct answer_packet)); 495 dh->flags = flags;
318 query->pkt.hdr.type = 496 dh->rh = rh;
319 htons (GNUNET_MESSAGE_TYPE_VPN_DNS_LOCAL_QUERY_DNS); 497 dh->rh_cls = rh_cls;
320 query->pkt.hdr.size = htons (len); 498 dh->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect, dh);
321 memcpy (query->pkt.orig_to, dst_ip, 16); 499 return dh;
322 memcpy (query->pkt.orig_from, src_ip, 16);
323 query->pkt.addrlen = 16;
324 query->pkt.src_port = htons (src_port);
325 memcpy (query->pkt.data, udp_packet,
326 udp_packet_len);
327 queue_request (h, query);
328} 500}
329 501
330 502
503/**
504 * Disconnect from the DNS service.
505 *
506 * @param dh DNS handle
507 */
331void 508void
332GNUNET_DNS_disconnect (struct GNUNET_DNS_Handle *h) 509GNUNET_DNS_disconnect (struct GNUNET_DNS_Handle *dh)
333{ 510{
334 if (h->dns_connection != NULL) 511 if (GNUNET_SCHEDULER_NO_TASK != dh->reconnect_task)
335 { 512 {
336 GNUNET_CLIENT_disconnect (h->dns_connection, GNUNET_NO); 513 GNUNET_SCHEDULER_cancel (dh->reconnect_task);
337 h->dns_connection = NULL; 514 dh->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
338 } 515 }
339 GNUNET_free (h); 516 disconnect (dh);
517 /* make sure client has no pending requests left over! */
518 GNUNET_assert (0 == dh->pending_requests);
519 GNUNET_free (dh);
340} 520}
341 521
342/* end of dns_api.c */ 522/* end of dns_api_new.c */