aboutsummaryrefslogtreecommitdiff
path: root/src/pt/gnunet-daemon-pt.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-01-16 20:00:28 +0000
committerChristian Grothoff <christian@grothoff.org>2012-01-16 20:00:28 +0000
commit0ccdd3775b7d005251dc40610d5f92f37f016b4b (patch)
treea7ba32e743d698830eea534ac9072376148d3070 /src/pt/gnunet-daemon-pt.c
parent41f6a12245348e4f6aa482386a8ffc713b51f2eb (diff)
downloadgnunet-0ccdd3775b7d005251dc40610d5f92f37f016b4b.tar.gz
gnunet-0ccdd3775b7d005251dc40610d5f92f37f016b4b.zip
-finishing first implementation of protocol translation daemon
Diffstat (limited to 'src/pt/gnunet-daemon-pt.c')
-rw-r--r--src/pt/gnunet-daemon-pt.c278
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 */
48enum 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 */
74struct 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 */
38static const struct GNUNET_CONFIGURATION_Handle *cfg; 112static 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 */
146static void
147finish_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 */
180static void
181submit_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 */
199static void
200vpn_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 */
242static void
243modify_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 */
280static void
281submit_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