diff options
author | Christian Grothoff <christian@grothoff.org> | 2012-01-16 20:00:28 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2012-01-16 20:00:28 +0000 |
commit | 0ccdd3775b7d005251dc40610d5f92f37f016b4b (patch) | |
tree | a7ba32e743d698830eea534ac9072376148d3070 /src/pt | |
parent | 41f6a12245348e4f6aa482386a8ffc713b51f2eb (diff) | |
download | gnunet-0ccdd3775b7d005251dc40610d5f92f37f016b4b.tar.gz gnunet-0ccdd3775b7d005251dc40610d5f92f37f016b4b.zip |
-finishing first implementation of protocol translation daemon
Diffstat (limited to 'src/pt')
-rw-r--r-- | src/pt/gnunet-daemon-pt.c | 278 |
1 files changed, 277 insertions, 1 deletions
diff --git a/src/pt/gnunet-daemon-pt.c b/src/pt/gnunet-daemon-pt.c index 762df276e..bbe9477a8 100644 --- a/src/pt/gnunet-daemon-pt.c +++ b/src/pt/gnunet-daemon-pt.c | |||
@@ -23,6 +23,10 @@ | |||
23 | * @brief tool to manipulate DNS and VPN services to perform protocol translation (IPvX over GNUnet) | 23 | * @brief tool to manipulate DNS and VPN services to perform protocol translation (IPvX over GNUnet) |
24 | * @author Christian Grothoff | 24 | * @author Christian Grothoff |
25 | * | 25 | * |
26 | * TODO: | ||
27 | * - add statistics | ||
28 | * - add logging? | ||
29 | * - figure out how/where/when/who tunnels DNS over mesh when necessary! | ||
26 | */ | 30 | */ |
27 | #include "platform.h" | 31 | #include "platform.h" |
28 | #include "gnunet_util_lib.h" | 32 | #include "gnunet_util_lib.h" |
@@ -33,6 +37,76 @@ | |||
33 | 37 | ||
34 | 38 | ||
35 | /** | 39 | /** |
40 | * After how long do we time out if we could not get an IP from VPN? | ||
41 | */ | ||
42 | #define TIMEOUT GNUNET_TIME_UNIT_MINUTES | ||
43 | |||
44 | |||
45 | /** | ||
46 | * Which group of DNS records are we currently processing? | ||
47 | */ | ||
48 | enum RequestGroup | ||
49 | { | ||
50 | /** | ||
51 | * DNS answers | ||
52 | */ | ||
53 | ANSWERS = 0, | ||
54 | |||
55 | /** | ||
56 | * DNS authority records | ||
57 | */ | ||
58 | AUTHORITY_RECORDS = 1, | ||
59 | |||
60 | /** | ||
61 | * DNS additional records | ||
62 | */ | ||
63 | ADDITIONAL_RECORDS = 2, | ||
64 | /** | ||
65 | * We're done processing. | ||
66 | */ | ||
67 | END = 3 | ||
68 | }; | ||
69 | |||
70 | |||
71 | /** | ||
72 | * Information tracked per DNS request that we are processing. | ||
73 | */ | ||
74 | struct RequestContext | ||
75 | { | ||
76 | /** | ||
77 | * Handle to submit the final result. | ||
78 | */ | ||
79 | struct GNUNET_DNS_RequestHandle *rh; | ||
80 | |||
81 | /** | ||
82 | * DNS packet that is being modified. | ||
83 | */ | ||
84 | struct GNUNET_DNSPARSER_Packet *dns; | ||
85 | |||
86 | /** | ||
87 | * Active redirection request with the VPN. | ||
88 | */ | ||
89 | struct GNUNET_VPN_RedirectionRequest *rr; | ||
90 | |||
91 | /** | ||
92 | * Record for which we have an active redirection request. | ||
93 | */ | ||
94 | struct GNUNET_DNSPARSER_Record *rec; | ||
95 | |||
96 | /** | ||
97 | * Offset in the current record group that is being modified. | ||
98 | */ | ||
99 | unsigned int offset; | ||
100 | |||
101 | /** | ||
102 | * Group that is being modified | ||
103 | */ | ||
104 | enum RequestGroup group; | ||
105 | |||
106 | }; | ||
107 | |||
108 | |||
109 | /** | ||
36 | * The handle to the configuration used throughout the process | 110 | * The handle to the configuration used throughout the process |
37 | */ | 111 | */ |
38 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | 112 | static const struct GNUNET_CONFIGURATION_Handle *cfg; |
@@ -64,6 +138,202 @@ static int ipv6_pt; | |||
64 | 138 | ||
65 | 139 | ||
66 | /** | 140 | /** |
141 | * We're done modifying all records in the response. Submit the reply | ||
142 | * and free the resources of the rc. | ||
143 | * | ||
144 | * @param rc context to process | ||
145 | */ | ||
146 | static void | ||
147 | finish_request (struct RequestContext *rc) | ||
148 | { | ||
149 | char *buf; | ||
150 | size_t buf_len; | ||
151 | |||
152 | if (GNUNET_SYSERR == | ||
153 | GNUNET_DNSPARSER_pack (rc->dns, | ||
154 | 16 * 1024, | ||
155 | &buf, | ||
156 | &buf_len)) | ||
157 | { | ||
158 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
159 | _("Failed to pack DNS request. Dropping.\n")); | ||
160 | GNUNET_DNS_request_drop (rc->rh); | ||
161 | } | ||
162 | else | ||
163 | { | ||
164 | GNUNET_DNS_request_answer (rc->rh, | ||
165 | buf_len, buf); | ||
166 | GNUNET_free (buf); | ||
167 | } | ||
168 | GNUNET_DNSPARSER_free_packet (rc->dns); | ||
169 | GNUNET_free (rc); | ||
170 | } | ||
171 | |||
172 | |||
173 | /** | ||
174 | * Process the next record of the given request context. | ||
175 | * When done, submit the reply and free the resources of | ||
176 | * the rc. | ||
177 | * | ||
178 | * @param rc context to process | ||
179 | */ | ||
180 | static void | ||
181 | submit_request (struct RequestContext *rc); | ||
182 | |||
183 | |||
184 | /** | ||
185 | * Callback invoked from the VPN service once a redirection is | ||
186 | * available. Provides the IP address that can now be used to | ||
187 | * reach the requested destination. We substitute the active | ||
188 | * record and then continue with 'submit_request' to look at | ||
189 | * the other records. | ||
190 | * | ||
191 | * @param cls our 'struct RequestContext' | ||
192 | * @param af address family, AF_INET or AF_INET6; AF_UNSPEC on error; | ||
193 | * will match 'result_af' from the request | ||
194 | * @param address IP address (struct in_addr or struct in_addr6, depending on 'af') | ||
195 | * that the VPN allocated for the redirection; | ||
196 | * traffic to this IP will now be redirected to the | ||
197 | * specified target peer; NULL on error | ||
198 | */ | ||
199 | static void | ||
200 | vpn_allocation_callback (void *cls, | ||
201 | int af, | ||
202 | const void *address) | ||
203 | { | ||
204 | struct RequestContext *rc = cls; | ||
205 | |||
206 | rc->rr = NULL; | ||
207 | if (af == AF_UNSPEC) | ||
208 | { | ||
209 | GNUNET_DNS_request_drop (rc->rh); | ||
210 | GNUNET_DNSPARSER_free_packet (rc->dns); | ||
211 | GNUNET_free (rc); | ||
212 | return; | ||
213 | } | ||
214 | switch (rc->rec->type) | ||
215 | { | ||
216 | case GNUNET_DNSPARSER_TYPE_A: | ||
217 | GNUNET_assert (AF_INET == af); | ||
218 | memcpy (rc->rec->data.raw.data, address, sizeof (struct in_addr)); | ||
219 | break; | ||
220 | case GNUNET_DNSPARSER_TYPE_AAAA: | ||
221 | GNUNET_assert (AF_INET6 == af); | ||
222 | memcpy (rc->rec->data.raw.data, address, sizeof (struct in6_addr)); | ||
223 | break; | ||
224 | default: | ||
225 | GNUNET_assert (0); | ||
226 | return; | ||
227 | } | ||
228 | rc->rec = NULL; | ||
229 | submit_request (rc); | ||
230 | } | ||
231 | |||
232 | |||
233 | /** | ||
234 | * Modify the given DNS record by asking VPN to create a tunnel | ||
235 | * to the given address. When done, continue with submitting | ||
236 | * other records from the request context ('submit_request' is | ||
237 | * our continuation). | ||
238 | * | ||
239 | * @param rc context to process | ||
240 | * @param rec record to modify | ||
241 | */ | ||
242 | static void | ||
243 | modify_address (struct RequestContext *rc, | ||
244 | struct GNUNET_DNSPARSER_Record *rec) | ||
245 | { | ||
246 | int af; | ||
247 | |||
248 | switch (rec->type) | ||
249 | { | ||
250 | case GNUNET_DNSPARSER_TYPE_A: | ||
251 | af = AF_INET; | ||
252 | GNUNET_assert (rec->data.raw.data_len == sizeof (struct in_addr)); | ||
253 | break; | ||
254 | case GNUNET_DNSPARSER_TYPE_AAAA: | ||
255 | af = AF_INET6; | ||
256 | GNUNET_assert (rec->data.raw.data_len == sizeof (struct in6_addr)); | ||
257 | break; | ||
258 | default: | ||
259 | GNUNET_assert (0); | ||
260 | return; | ||
261 | } | ||
262 | rc->rec = rec; | ||
263 | rc->rr = GNUNET_VPN_redirect_to_ip (vpn_handle, | ||
264 | af, af, | ||
265 | rec->data.raw.data, | ||
266 | GNUNET_NO /* nac */, | ||
267 | GNUNET_TIME_relative_to_absolute (TIMEOUT), | ||
268 | &vpn_allocation_callback, | ||
269 | rc); | ||
270 | } | ||
271 | |||
272 | |||
273 | /** | ||
274 | * Process the next record of the given request context. | ||
275 | * When done, submit the reply and free the resources of | ||
276 | * the rc. | ||
277 | * | ||
278 | * @param rc context to process | ||
279 | */ | ||
280 | static void | ||
281 | submit_request (struct RequestContext *rc) | ||
282 | { | ||
283 | struct GNUNET_DNSPARSER_Record *ra; | ||
284 | unsigned int ra_len; | ||
285 | unsigned int i; | ||
286 | |||
287 | while (1) | ||
288 | { | ||
289 | switch (rc->group) | ||
290 | { | ||
291 | case ANSWERS: | ||
292 | ra = rc->dns->answers; | ||
293 | ra_len = rc->dns->num_answers; | ||
294 | break; | ||
295 | case AUTHORITY_RECORDS: | ||
296 | ra = rc->dns->authority_records; | ||
297 | ra_len = rc->dns->num_authority_records; | ||
298 | break; | ||
299 | case ADDITIONAL_RECORDS: | ||
300 | ra = rc->dns->additional_records; | ||
301 | ra_len = rc->dns->num_additional_records; | ||
302 | break; | ||
303 | case END: | ||
304 | finish_request (rc); | ||
305 | return; | ||
306 | default: | ||
307 | GNUNET_assert (0); | ||
308 | } | ||
309 | for (i=rc->offset;i<ra_len;i++) | ||
310 | { | ||
311 | switch (ra[i].type) | ||
312 | { | ||
313 | case GNUNET_DNSPARSER_TYPE_A: | ||
314 | if (ipv4_pt) | ||
315 | { | ||
316 | rc->offset = i + 1; | ||
317 | modify_address (rc, &ra[i]); | ||
318 | return; | ||
319 | } | ||
320 | break; | ||
321 | case GNUNET_DNSPARSER_TYPE_AAAA: | ||
322 | if (ipv6_pt) | ||
323 | { | ||
324 | rc->offset = i + 1; | ||
325 | modify_address (rc, &ra[i]); | ||
326 | return; | ||
327 | } | ||
328 | break; | ||
329 | } | ||
330 | } | ||
331 | rc->group++; | ||
332 | } | ||
333 | } | ||
334 | |||
335 | |||
336 | /** | ||
67 | * Test if any of the given records need protocol-translation work. | 337 | * Test if any of the given records need protocol-translation work. |
68 | * | 338 | * |
69 | * @param ra array of records | 339 | * @param ra array of records |
@@ -124,6 +394,7 @@ dns_request_handler (void *cls, | |||
124 | const char *request) | 394 | const char *request) |
125 | { | 395 | { |
126 | struct GNUNET_DNSPARSER_Packet *dns; | 396 | struct GNUNET_DNSPARSER_Packet *dns; |
397 | struct RequestContext *rc; | ||
127 | int work; | 398 | int work; |
128 | 399 | ||
129 | dns = GNUNET_DNSPARSER_parse (request, request_length); | 400 | dns = GNUNET_DNSPARSER_parse (request, request_length); |
@@ -143,7 +414,12 @@ dns_request_handler (void *cls, | |||
143 | GNUNET_DNS_request_forward (rh); | 414 | GNUNET_DNS_request_forward (rh); |
144 | return; | 415 | return; |
145 | } | 416 | } |
146 | /* FIXME: translate A/AAAA records using VPN! */ | 417 | rc = GNUNET_malloc (sizeof (struct RequestContext)); |
418 | rc->rh = rh; | ||
419 | rc->dns = dns; | ||
420 | rc->offset = 0; | ||
421 | rc->group = ANSWERS; | ||
422 | submit_request (rc); | ||
147 | } | 423 | } |
148 | 424 | ||
149 | 425 | ||