diff options
author | Christian Grothoff <christian@grothoff.org> | 2012-01-15 20:41:40 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2012-01-15 20:41:40 +0000 |
commit | 1574e0f8c2a55363c024a95f440ba7be647efbe1 (patch) | |
tree | 5e4507d9aa404ac983c5774b71b25ec6174ee7cc /src/dns/dns_api.c | |
parent | 5ec7048ed9ffeddbe06e34a31d388080fae143e5 (diff) | |
download | gnunet-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.c | 664 |
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> | 34 | struct 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 | ||
39 | struct query_packet_list | 51 | }; |
52 | |||
53 | |||
54 | /** | ||
55 | * Handle to identify an individual DNS request. | ||
56 | */ | ||
57 | struct 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 | */ | ||
47 | struct GNUNET_DNS_Handle | 81 | struct 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 | */ | ||
69 | size_t | ||
70 | send_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 | */ | ||
153 | static void | ||
154 | queue_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 | */ | ||
164 | static void | ||
165 | reconnect (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 | */ | ||
193 | static void | ||
194 | disconnect (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 | */ |
146 | static void | 226 | static void |
147 | dns_answer_handler (void *cls, | 227 | request_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 | */ |
189 | struct GNUNET_DNS_Handle * | 282 | static size_t |
190 | GNUNET_DNS_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, | 283 | send_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 | */ | ||
343 | static void | ||
344 | queue_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 | */ | ||
227 | void | 377 | void |
228 | GNUNET_DNS_restart_hijack (struct GNUNET_DNS_Handle *h) | 378 | GNUNET_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 | */ |
245 | static void | 408 | void |
246 | queue_request (struct GNUNET_DNS_Handle *h, | 409 | GNUNET_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 | */ |
271 | void | 442 | void |
272 | GNUNET_DNS_queue_request_v4 (struct GNUNET_DNS_Handle *h, | 443 | GNUNET_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 | */ |
305 | void | 485 | struct GNUNET_DNS_Handle * |
306 | GNUNET_DNS_queue_request_v6 (struct GNUNET_DNS_Handle *h, | 486 | GNUNET_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 | */ | ||
331 | void | 508 | void |
332 | GNUNET_DNS_disconnect (struct GNUNET_DNS_Handle *h) | 509 | GNUNET_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 */ |