diff options
author | Christian Grothoff <christian@grothoff.org> | 2012-07-20 20:17:19 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2012-07-20 20:17:19 +0000 |
commit | 2687ea5fca3effa07f9b58aa41dfeac203dfb65f (patch) | |
tree | b5fdf25e7f814e3754ba38c10cabec8f8d80544a /src/gns | |
parent | 7f2aed62fe8506e0f7a2f551875f7eb16326e9ad (diff) | |
download | gnunet-2687ea5fca3effa07f9b58aa41dfeac203dfb65f.tar.gz gnunet-2687ea5fca3effa07f9b58aa41dfeac203dfb65f.zip |
ns2gns
Diffstat (limited to 'src/gns')
-rw-r--r-- | src/gns/Makefile.am | 1 | ||||
-rw-r--r-- | src/gns/gnunet-dns2gns.c | 356 |
2 files changed, 354 insertions, 3 deletions
diff --git a/src/gns/Makefile.am b/src/gns/Makefile.am index 45bacda3c..21c144d5a 100644 --- a/src/gns/Makefile.am +++ b/src/gns/Makefile.am | |||
@@ -293,6 +293,7 @@ gnunet_dns2gns_LDADD = \ | |||
293 | $(top_builddir)/src/gns/libgnunetgns.la \ | 293 | $(top_builddir)/src/gns/libgnunetgns.la \ |
294 | $(top_builddir)/src/util/libgnunetutil.la \ | 294 | $(top_builddir)/src/util/libgnunetutil.la \ |
295 | $(top_builddir)/src/namestore/libgnunetnamestore.la \ | 295 | $(top_builddir)/src/namestore/libgnunetnamestore.la \ |
296 | $(top_builddir)/src/dns/libgnunetdnsparser.la \ | ||
296 | $(GN_LIBINTL) | 297 | $(GN_LIBINTL) |
297 | 298 | ||
298 | gnunet_gns_proxy_SOURCES = \ | 299 | gnunet_gns_proxy_SOURCES = \ |
diff --git a/src/gns/gnunet-dns2gns.c b/src/gns/gnunet-dns2gns.c index a33020f16..cb7abe6ec 100644 --- a/src/gns/gnunet-dns2gns.c +++ b/src/gns/gnunet-dns2gns.c | |||
@@ -24,21 +24,78 @@ | |||
24 | */ | 24 | */ |
25 | #include "platform.h" | 25 | #include "platform.h" |
26 | #include <gnunet_util_lib.h> | 26 | #include <gnunet_util_lib.h> |
27 | #include <gnunet_namestore_service.h> | 27 | #include <gnunet_dnsparser_lib.h> |
28 | #include <gnunet_gns_service.h> | ||
29 | |||
30 | /** | ||
31 | * Timeout for DNS requests. | ||
32 | */ | ||
33 | #define TIMEOUT GNUNET_TIME_UNIT_MINUTES | ||
28 | 34 | ||
29 | /** | 35 | /** |
30 | * Data kept per request. | 36 | * Data kept per request. |
31 | */ | 37 | */ |
32 | struct Request | 38 | struct Request |
33 | { | 39 | { |
40 | /** | ||
41 | * Socket to use for sending the reply. | ||
42 | */ | ||
43 | struct GNUNET_NETWORK_Handle *lsock; | ||
44 | |||
45 | /** | ||
46 | * Destination address to use. | ||
47 | */ | ||
48 | const void *addr; | ||
49 | |||
50 | /** | ||
51 | * Initially, this is the DNS request, it will then be | ||
52 | * converted to the DNS response. | ||
53 | */ | ||
54 | struct GNUNET_DNSPARSER_Packet *packet; | ||
55 | |||
56 | /** | ||
57 | * Our GNS request handle. | ||
58 | */ | ||
59 | struct GNUNET_GNS_LookupRequest *lookup; | ||
60 | |||
61 | /** | ||
62 | * Task run on timeout or shutdown to clean up without | ||
63 | * response. | ||
64 | */ | ||
65 | GNUNET_SCHEDULER_TaskIdentifier timeout_task; | ||
66 | |||
67 | /** | ||
68 | * Number of bytes in 'addr'. | ||
69 | */ | ||
70 | size_t addr_len; | ||
34 | 71 | ||
35 | }; | 72 | }; |
36 | 73 | ||
37 | 74 | ||
38 | /** | 75 | /** |
39 | * Listen socket. | 76 | * Handle to GNS resolver. |
77 | */ | ||
78 | struct GNUNET_GNS_Handle *gns; | ||
79 | |||
80 | /** | ||
81 | * Listen socket for IPv4. | ||
82 | */ | ||
83 | static struct GNUNET_NETWORK_Handle *listen_socket4; | ||
84 | |||
85 | /** | ||
86 | * Listen socket for IPv6. | ||
87 | */ | ||
88 | static struct GNUNET_NETWORK_Handle *listen_socket6; | ||
89 | |||
90 | /** | ||
91 | * Task for IPv4 socket. | ||
92 | */ | ||
93 | static GNUNET_SCHEDULER_TaskIdentifier t4; | ||
94 | |||
95 | /** | ||
96 | * Task for IPv6 socket. | ||
40 | */ | 97 | */ |
41 | static struct GNUNET_NETWORK_Handle *listen_socket; | 98 | static GNUNET_SCHEDULER_TaskIdentifier t6; |
42 | 99 | ||
43 | 100 | ||
44 | /** | 101 | /** |
@@ -51,6 +108,236 @@ static void | |||
51 | do_shutdown (void *cls, | 108 | do_shutdown (void *cls, |
52 | const struct GNUNET_SCHEDULER_TaskContext *tc) | 109 | const struct GNUNET_SCHEDULER_TaskContext *tc) |
53 | { | 110 | { |
111 | if (GNUNET_SCHEDULER_NO_TASK != t4) | ||
112 | GNUNET_SCHEDULER_cancel (t4); | ||
113 | if (GNUNET_SCHEDULER_NO_TASK != t6) | ||
114 | GNUNET_SCHEDULER_cancel (t6); | ||
115 | if (NULL != listen_socket4) | ||
116 | { | ||
117 | GNUNET_NETWORK_socket_close (listen_socket4); | ||
118 | listen_socket4 = NULL; | ||
119 | } | ||
120 | if (NULL != listen_socket6) | ||
121 | { | ||
122 | GNUNET_NETWORK_socket_close (listen_socket6); | ||
123 | listen_socket6 = NULL; | ||
124 | } | ||
125 | GNUNET_GNS_disconnect (gns); | ||
126 | gns = NULL; | ||
127 | } | ||
128 | |||
129 | |||
130 | /** | ||
131 | * Send the response for the given request and clean up. | ||
132 | * | ||
133 | * @param request context for the request. | ||
134 | */ | ||
135 | static void | ||
136 | send_response (struct Request *request) | ||
137 | { | ||
138 | char *buf; | ||
139 | size_t size; | ||
140 | |||
141 | if (GNUNET_SYSERR == | ||
142 | GNUNET_DNSPARSER_pack (request->packet, | ||
143 | UINT16_MAX /* is this not too much? */, | ||
144 | &buf, | ||
145 | &size)) | ||
146 | { | ||
147 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
148 | _("Failed to pack DNS response into UDP packet!\n")); | ||
149 | } | ||
150 | else | ||
151 | { | ||
152 | if (size != | ||
153 | GNUNET_NETWORK_socket_sendto (request->lsock, | ||
154 | buf, size, | ||
155 | request->addr, | ||
156 | request->addr_len)) | ||
157 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "sendto"); | ||
158 | GNUNET_free (buf); | ||
159 | } | ||
160 | GNUNET_SCHEDULER_cancel (request->timeout_task); | ||
161 | GNUNET_DNSPARSER_free_packet (request->packet); | ||
162 | GNUNET_free (request); | ||
163 | } | ||
164 | |||
165 | |||
166 | /** | ||
167 | * Task run on timeout. Cleans up request. | ||
168 | * | ||
169 | * @param cls 'struct Request' of the request to clean up | ||
170 | * @param tc scheduler context | ||
171 | */ | ||
172 | static void | ||
173 | do_timeout (void *cls, | ||
174 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
175 | { | ||
176 | struct Request *request = cls; | ||
177 | |||
178 | GNUNET_DNSPARSER_free_packet (request->packet); | ||
179 | GNUNET_GNS_cancel_lookup_request (request->lookup); | ||
180 | GNUNET_free (request); | ||
181 | } | ||
182 | |||
183 | |||
184 | /** | ||
185 | * Iterator called on obtained result for a GNS | ||
186 | * lookup | ||
187 | * | ||
188 | * @param cls closure | ||
189 | * @param name "name" of the original lookup | ||
190 | * @param rd_count number of records | ||
191 | * @param rd the records in reply | ||
192 | */ | ||
193 | static void | ||
194 | result_processor (void *cls, | ||
195 | uint32_t rd_count, | ||
196 | const struct GNUNET_NAMESTORE_RecordData *rd) | ||
197 | { | ||
198 | struct Request *request = cls; | ||
199 | |||
200 | // FIXME: is 'processor' called only once or | ||
201 | // possibly more than once? | ||
202 | request->lookup = NULL; | ||
203 | GNUNET_break (0); | ||
204 | // FIXME: convert 'rd' to response here... | ||
205 | send_response (request); | ||
206 | } | ||
207 | |||
208 | |||
209 | /** | ||
210 | * Handle DNS request. | ||
211 | * | ||
212 | * @param lsock socket to use for sending the reply | ||
213 | * @param addr address to use for sending the reply | ||
214 | * @param addr_len number of bytes in addr | ||
215 | * @param udp_msg DNS request payload | ||
216 | * @param udp_msg_size number of bytes in udp_msg | ||
217 | */ | ||
218 | static void | ||
219 | handle_request (struct GNUNET_NETWORK_Handle *lsock, | ||
220 | const void *addr, | ||
221 | size_t addr_len, | ||
222 | const char *udp_msg, | ||
223 | size_t udp_msg_size) | ||
224 | { | ||
225 | struct Request *request; | ||
226 | struct GNUNET_DNSPARSER_Packet *packet; | ||
227 | |||
228 | packet = GNUNET_DNSPARSER_parse (udp_msg, udp_msg_size); | ||
229 | if (NULL == packet) | ||
230 | { | ||
231 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
232 | _("Received malformed DNS request from %s\n"), | ||
233 | GNUNET_a2s (addr, addr_len)); | ||
234 | return; | ||
235 | } | ||
236 | request = GNUNET_malloc (sizeof (struct Request) + addr_len); | ||
237 | request->lsock = lsock; | ||
238 | request->packet = packet; | ||
239 | request->addr = &request[1]; | ||
240 | request->addr_len = addr_len; | ||
241 | memcpy (&request[1], addr, addr_len); | ||
242 | request->timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, | ||
243 | &do_timeout, | ||
244 | request); | ||
245 | // FIXME: extract name and type from 'request->packet' | ||
246 | const char *name = "foo"; | ||
247 | enum GNUNET_GNS_RecordType type = GNUNET_GNS_RECORD_A; | ||
248 | request->lookup = GNUNET_GNS_lookup (gns, | ||
249 | name, | ||
250 | type, | ||
251 | GNUNET_NO, | ||
252 | NULL, | ||
253 | &result_processor, | ||
254 | request); | ||
255 | } | ||
256 | |||
257 | |||
258 | /** | ||
259 | * Task to read IPv4 DNS packets. | ||
260 | * | ||
261 | * @param cls the 'listen_socket4' | ||
262 | * @param tc scheduler context | ||
263 | */ | ||
264 | static void | ||
265 | read_dns4 (void *cls, | ||
266 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
267 | { | ||
268 | struct sockaddr_in v4; | ||
269 | socklen_t addrlen; | ||
270 | ssize_t size; | ||
271 | |||
272 | GNUNET_assert (listen_socket4 == cls); | ||
273 | t4 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, | ||
274 | listen_socket4, | ||
275 | &read_dns4, | ||
276 | listen_socket4); | ||
277 | if (0 == (GNUNET_SCHEDULER_REASON_READ_READY & tc->reason)) | ||
278 | return; /* shutdown? */ | ||
279 | size = GNUNET_NETWORK_socket_recvfrom_amount (listen_socket4); | ||
280 | if (0 > size) | ||
281 | { | ||
282 | GNUNET_break (0); | ||
283 | return; /* read error!? */ | ||
284 | } | ||
285 | { | ||
286 | char buf[size]; | ||
287 | |||
288 | addrlen = sizeof (v4); | ||
289 | GNUNET_break (size == | ||
290 | GNUNET_NETWORK_socket_recvfrom (listen_socket4, | ||
291 | buf, | ||
292 | size, | ||
293 | (struct sockaddr *) &v4, | ||
294 | &addrlen)); | ||
295 | handle_request (listen_socket4, &v4, addrlen, | ||
296 | buf, size); | ||
297 | } | ||
298 | } | ||
299 | |||
300 | |||
301 | /** | ||
302 | * Task to read IPv6 DNS packets. | ||
303 | * | ||
304 | * @param cls the 'listen_socket6' | ||
305 | * @param tc scheduler context | ||
306 | */ | ||
307 | static void | ||
308 | read_dns6 (void *cls, | ||
309 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
310 | { | ||
311 | struct sockaddr_in6 v6; | ||
312 | socklen_t addrlen; | ||
313 | ssize_t size; | ||
314 | |||
315 | GNUNET_assert (listen_socket6 == cls); | ||
316 | t6 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, | ||
317 | listen_socket6, | ||
318 | &read_dns6, | ||
319 | listen_socket6); | ||
320 | if (0 == (GNUNET_SCHEDULER_REASON_READ_READY & tc->reason)) | ||
321 | return; /* shutdown? */ | ||
322 | size = GNUNET_NETWORK_socket_recvfrom_amount (listen_socket6); | ||
323 | if (0 > size) | ||
324 | { | ||
325 | GNUNET_break (0); | ||
326 | return; /* read error!? */ | ||
327 | } | ||
328 | { | ||
329 | char buf[size]; | ||
330 | |||
331 | addrlen = sizeof (v6); | ||
332 | GNUNET_break (size == | ||
333 | GNUNET_NETWORK_socket_recvfrom (listen_socket6, | ||
334 | buf, | ||
335 | size, | ||
336 | (struct sockaddr *) &v6, | ||
337 | &addrlen)); | ||
338 | handle_request (listen_socket6, &v6, addrlen, | ||
339 | buf, size); | ||
340 | } | ||
54 | } | 341 | } |
55 | 342 | ||
56 | 343 | ||
@@ -66,6 +353,69 @@ static void | |||
66 | run (void *cls, char *const *args, const char *cfgfile, | 353 | run (void *cls, char *const *args, const char *cfgfile, |
67 | const struct GNUNET_CONFIGURATION_Handle *cfg) | 354 | const struct GNUNET_CONFIGURATION_Handle *cfg) |
68 | { | 355 | { |
356 | gns = GNUNET_GNS_connect (cfg); | ||
357 | if (NULL == gns) | ||
358 | return; | ||
359 | listen_socket4 = GNUNET_NETWORK_socket_create (PF_INET, | ||
360 | SOCK_DGRAM, | ||
361 | IPPROTO_UDP); | ||
362 | if (NULL != listen_socket4) | ||
363 | { | ||
364 | struct sockaddr_in v4; | ||
365 | |||
366 | memset (&v4, 0, sizeof (v4)); | ||
367 | v4.sin_family = AF_INET; | ||
368 | #if HAVE_SOCKADDR_IN_SIN_LEN | ||
369 | v4.sin_len = sizeof (v4); | ||
370 | #endif | ||
371 | v4.sin_port = htons (53); | ||
372 | if (GNUNET_OK != | ||
373 | GNUNET_NETWORK_socket_bind (listen_socket4, | ||
374 | (struct sockaddr *) &v4, | ||
375 | sizeof (v4))) | ||
376 | { | ||
377 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind"); | ||
378 | GNUNET_NETWORK_socket_close (listen_socket4); | ||
379 | listen_socket4 = NULL; | ||
380 | } | ||
381 | } | ||
382 | listen_socket6 = GNUNET_NETWORK_socket_create (PF_INET6, | ||
383 | SOCK_DGRAM, | ||
384 | IPPROTO_UDP); | ||
385 | if (NULL != listen_socket6) | ||
386 | { | ||
387 | struct sockaddr_in6 v6; | ||
388 | |||
389 | memset (&v6, 0, sizeof (v6)); | ||
390 | v6.sin6_family = AF_INET6; | ||
391 | #if HAVE_SOCKADDR_IN_SIN_LEN | ||
392 | v6.sin6_len = sizeof (v6); | ||
393 | #endif | ||
394 | v6.sin6_port = htons (53); | ||
395 | if (GNUNET_OK != | ||
396 | GNUNET_NETWORK_socket_bind (listen_socket6, | ||
397 | (struct sockaddr *) &v6, | ||
398 | sizeof (v6))) | ||
399 | { | ||
400 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind"); | ||
401 | GNUNET_NETWORK_socket_close (listen_socket6); | ||
402 | listen_socket6 = NULL; | ||
403 | } | ||
404 | } | ||
405 | if ( (NULL == listen_socket4) && | ||
406 | (NULL == listen_socket6) ) | ||
407 | return; | ||
408 | if (NULL != listen_socket4) | ||
409 | t4 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, | ||
410 | listen_socket4, | ||
411 | &read_dns4, | ||
412 | listen_socket4); | ||
413 | if (NULL != listen_socket6) | ||
414 | t6 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, | ||
415 | listen_socket6, | ||
416 | &read_dns6, | ||
417 | listen_socket6); | ||
418 | |||
69 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, | 419 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, |
70 | &do_shutdown, NULL); | 420 | &do_shutdown, NULL); |
71 | } | 421 | } |