aboutsummaryrefslogtreecommitdiff
path: root/src/vpn
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-01-01 23:00:59 +0000
committerChristian Grothoff <christian@grothoff.org>2012-01-01 23:00:59 +0000
commit66ffc809472f27d69b9ad7361f8ba29c2674f716 (patch)
tree609623cb79291939f9cb81a8858853a202dae2ca /src/vpn
parent131c43b2b18b12e52ff045e51025706802cbd2e2 (diff)
downloadgnunet-66ffc809472f27d69b9ad7361f8ba29c2674f716.tar.gz
gnunet-66ffc809472f27d69b9ad7361f8ba29c2674f716.zip
-moving DNS code into its own directory
Diffstat (limited to 'src/vpn')
-rw-r--r--src/vpn/Makefile.am21
-rw-r--r--src/vpn/gnunet-daemon-vpn-dns.c1
-rw-r--r--src/vpn/gnunet-daemon-vpn-helper.c1
-rw-r--r--src/vpn/gnunet-daemon-vpn.h2
-rw-r--r--src/vpn/gnunet-dns-parser.c301
-rw-r--r--src/vpn/gnunet-dns-parser.h95
-rw-r--r--src/vpn/gnunet-helper-hijack-dns.c156
-rw-r--r--src/vpn/gnunet-service-dns-p.h116
-rw-r--r--src/vpn/gnunet-service-dns.c1731
-rw-r--r--src/vpn/gnunet-vpn-packet.h2
10 files changed, 4 insertions, 2422 deletions
diff --git a/src/vpn/Makefile.am b/src/vpn/Makefile.am
index e69c5643e..dfba44f0a 100644
--- a/src/vpn/Makefile.am
+++ b/src/vpn/Makefile.am
@@ -17,30 +17,23 @@ dist_pkgcfg_DATA = \
17 17
18if LINUX 18if LINUX
19VPNBIN = gnunet-helper-vpn 19VPNBIN = gnunet-helper-vpn
20HIJACKBIN = gnunet-helper-hijack-dns
21install-exec-hook: 20install-exec-hook:
22 $(SUDO_BINARY) chown root:root $(bindir)/gnunet-helper-vpn || true 21 $(SUDO_BINARY) chown root:root $(bindir)/gnunet-helper-vpn || true
23 $(SUDO_BINARY) chmod u+s $(bindir)/gnunet-helper-vpn || true 22 $(SUDO_BINARY) chmod u+s $(bindir)/gnunet-helper-vpn || true
24 $(SUDO_BINARY) chown root:root $(bindir)/gnunet-helper-hijack-dns || true
25 $(SUDO_BINARY) chmod u+s $(bindir)/gnunet-helper-hijack-dns || true
26else 23else
27install-exec-hook: 24install-exec-hook:
28endif 25endif
29 26
30 27
31bin_PROGRAMS = \ 28bin_PROGRAMS = \
32 gnunet-daemon-exit gnunet-daemon-vpn gnunet-service-dns $(VPNBIN) $(HIJACKBIN) 29 gnunet-daemon-exit gnunet-daemon-vpn $(VPNBIN) $(HIJACKBIN)
33 30
34 31
35gnunet_helper_vpn_SOURCES = \ 32gnunet_helper_vpn_SOURCES = \
36 gnunet-helper-vpn.c 33 gnunet-helper-vpn.c
37 34
38gnunet_helper_hijack_dns_SOURCES = \
39 gnunet-helper-hijack-dns.c
40
41gnunet_daemon_vpn_SOURCES = \ 35gnunet_daemon_vpn_SOURCES = \
42 gnunet-daemon-vpn.c gnunet-daemon-vpn.h \ 36 gnunet-daemon-vpn.c gnunet-daemon-vpn.h \
43 gnunet-dns-parser.c gnunet-dns-parser.h \
44 gnunet-daemon-vpn-helper.c gnunet-daemon-vpn-helper.h \ 37 gnunet-daemon-vpn-helper.c gnunet-daemon-vpn-helper.h \
45 gnunet-daemon-vpn-dns.c gnunet-daemon-vpn-dns.h \ 38 gnunet-daemon-vpn-dns.c gnunet-daemon-vpn-dns.h \
46 gnunet-helper-vpn-api.c gnunet-helper-vpn-api.h \ 39 gnunet-helper-vpn-api.c gnunet-helper-vpn-api.h \
@@ -50,17 +43,7 @@ gnunet_daemon_vpn_LDADD = \
50 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 43 $(top_builddir)/src/statistics/libgnunetstatistics.la \
51 $(top_builddir)/src/util/libgnunetutil.la \ 44 $(top_builddir)/src/util/libgnunetutil.la \
52 $(top_builddir)/src/mesh/libgnunetmesh.la \ 45 $(top_builddir)/src/mesh/libgnunetmesh.la \
53 $(GN_LIBINTL) 46 $(top_builddir)/src/dns/libgnunetdnsparser.la \
54
55gnunet_service_dns_SOURCES = \
56 gnunet-service-dns.c gnunet-service-dns-p.h \
57 gnunet-dns-parser.c gnunet-dns-parser.h
58gnunet_service_dns_LDADD = \
59 $(top_builddir)/src/core/libgnunetcore.la \
60 $(top_builddir)/src/statistics/libgnunetstatistics.la \
61 $(top_builddir)/src/util/libgnunetutil.la \
62 $(top_builddir)/src/dht/libgnunetdht.la \
63 $(top_builddir)/src/mesh/libgnunetmesh.la \
64 $(GN_LIBINTL) 47 $(GN_LIBINTL)
65 48
66gnunet_daemon_exit_SOURCES = \ 49gnunet_daemon_exit_SOURCES = \
diff --git a/src/vpn/gnunet-daemon-vpn-dns.c b/src/vpn/gnunet-daemon-vpn-dns.c
index bd65e373f..b24d802f7 100644
--- a/src/vpn/gnunet-daemon-vpn-dns.c
+++ b/src/vpn/gnunet-daemon-vpn-dns.c
@@ -36,7 +36,6 @@
36#include "gnunet-daemon-vpn-dns.h" 36#include "gnunet-daemon-vpn-dns.h"
37#include "gnunet-daemon-vpn.h" 37#include "gnunet-daemon-vpn.h"
38#include "gnunet-daemon-vpn-helper.h" 38#include "gnunet-daemon-vpn-helper.h"
39#include "gnunet-service-dns-p.h"
40#include "gnunet-vpn-packet.h" 39#include "gnunet-vpn-packet.h"
41 40
42struct query_packet_list *head; 41struct query_packet_list *head;
diff --git a/src/vpn/gnunet-daemon-vpn-helper.c b/src/vpn/gnunet-daemon-vpn-helper.c
index d0e36099e..8f295506a 100644
--- a/src/vpn/gnunet-daemon-vpn-helper.c
+++ b/src/vpn/gnunet-daemon-vpn-helper.c
@@ -38,7 +38,6 @@
38#include "gnunet-daemon-vpn-dns.h" 38#include "gnunet-daemon-vpn-dns.h"
39#include "gnunet-daemon-vpn.h" 39#include "gnunet-daemon-vpn.h"
40#include "gnunet-daemon-vpn-helper.h" 40#include "gnunet-daemon-vpn-helper.h"
41#include "gnunet-service-dns-p.h"
42#include "gnunet-vpn-packet.h" 41#include "gnunet-vpn-packet.h"
43#include "gnunet-vpn-checksum.h" 42#include "gnunet-vpn-checksum.h"
44#include "gnunet-helper-vpn-api.h" 43#include "gnunet-helper-vpn-api.h"
diff --git a/src/vpn/gnunet-daemon-vpn.h b/src/vpn/gnunet-daemon-vpn.h
index 95218aa61..c8bf91ebb 100644
--- a/src/vpn/gnunet-daemon-vpn.h
+++ b/src/vpn/gnunet-daemon-vpn.h
@@ -26,7 +26,7 @@
26#ifndef GNUNET_DAEMON_VPN_H 26#ifndef GNUNET_DAEMON_VPN_H
27#define GNUNET_DAEMON_VPN_H 27#define GNUNET_DAEMON_VPN_H
28 28
29#include "gnunet-service-dns-p.h" 29#include "gnunet_dns_service.h"
30 30
31/** 31/**
32 * This gets scheduled with cls pointing to an answer_packet and does everything 32 * This gets scheduled with cls pointing to an answer_packet and does everything
diff --git a/src/vpn/gnunet-dns-parser.c b/src/vpn/gnunet-dns-parser.c
deleted file mode 100644
index e87109e0c..000000000
--- a/src/vpn/gnunet-dns-parser.c
+++ /dev/null
@@ -1,301 +0,0 @@
1#include "platform.h"
2#include "gnunet-dns-parser.h"
3#include "gnunet-vpn-packet.h"
4
5/**
6 * Parse a name from DNS to a normal .-delimited, 0-terminated string.
7 *
8 * @param d The destination of the name. Should have at least 255 bytes allocated.
9 * @param src The DNS-Packet
10 * @param idx The offset inside the Packet from which on the name should be read
11 * @returns The offset of the first unparsed byte (the byte right behind the name)
12 */
13static unsigned int
14parse_dns_name (char *d, const unsigned char *src, unsigned short idx)
15{ /*{{{ */
16 char *dest = d;
17
18 int len = src[idx++];
19
20 while (len != 0)
21 {
22 if (len & 0xC0)
23 { /* Compressed name, offset in this and the next octet */
24 unsigned short offset = ((len & 0x3F) << 8) | src[idx++];
25
26 parse_dns_name (dest, src, offset - 12); /* 12 for the Header of the DNS-Packet, idx starts at 0 which is 12 bytes from the start of the packet */
27 return idx;
28 }
29 memcpy (dest, src + idx, len);
30 idx += len;
31 dest += len;
32 *dest = '.';
33 dest++;
34 len = src[idx++];
35 };
36 *dest = 0;
37
38 return idx;
39}
40
41/*}}}*/
42
43/**
44 * Parse a complete DNS-Record from raw DNS-data to a struct dns_record
45 *
46 * @param data The DNS-data
47 * @param dst Pointer to count pointers; individual pointers will be allocated
48 * @param count Number of records to parse
49 * @param idx The offset inside the Packet from which on the name should be read
50 * @returns The offset of the first unparsed byte (the byte right behind the last record)
51 */
52static unsigned short
53parse_dns_record (unsigned char *data, /*{{{ */
54 struct dns_record **dst, unsigned short count,
55 unsigned short idx)
56{
57 int i;
58 unsigned short _idx;
59
60 for (i = 0; i < count; i++)
61 {
62 dst[i] = GNUNET_malloc (sizeof (struct dns_record));
63 dst[i]->name = alloca (255); // see RFC1035, no name can be longer than this.
64 char *name = dst[i]->name;
65
66 _idx = parse_dns_name (name, data, idx);
67 dst[i]->namelen = _idx - idx;
68
69 dst[i]->name = GNUNET_malloc (dst[i]->namelen);
70 memcpy (dst[i]->name, name, dst[i]->namelen);
71
72 idx = _idx;
73
74 dst[i]->type = *((unsigned short *) (data + idx));
75 idx += 2;
76 dst[i]->class = *((unsigned short *) (data + idx));
77 idx += 2;
78 dst[i]->ttl = *((unsigned int *) (data + idx));
79 idx += 4;
80 dst[i]->data_len = *((unsigned short *) (data + idx));
81 idx += 2;
82 dst[i]->data = GNUNET_malloc (ntohs (dst[i]->data_len));
83 memcpy (dst[i]->data, data + idx, ntohs (dst[i]->data_len));
84 idx += ntohs (dst[i]->data_len);
85 }
86 return idx;
87} /*}}} */
88
89/**
90 * Parse a raw DNS-Packet into an usable struct
91 */
92struct dns_pkt_parsed *
93parse_dns_packet (struct dns_pkt *pkt)
94{ /*{{{ */
95 struct dns_pkt_parsed *ppkt = GNUNET_malloc (sizeof (struct dns_pkt_parsed));
96
97 memcpy (&ppkt->s, &pkt->s, sizeof pkt->s);
98
99 unsigned short qdcount = ntohs (ppkt->s.qdcount);
100 unsigned short ancount = ntohs (ppkt->s.ancount);
101 unsigned short nscount = ntohs (ppkt->s.nscount);
102 unsigned short arcount = ntohs (ppkt->s.arcount);
103
104 ppkt->queries = GNUNET_malloc (qdcount * sizeof (struct dns_query *));
105 ppkt->answers = GNUNET_malloc (ancount * sizeof (struct dns_record *));
106 ppkt->nameservers = GNUNET_malloc (nscount * sizeof (struct dns_record *));
107 ppkt->additional = GNUNET_malloc (arcount * sizeof (struct dns_record *));
108
109 unsigned short idx = 0, _idx; /* This keeps track how far we have parsed the data */
110
111 /* Parse the Query */
112 int i;
113
114 for (i = 0; i < qdcount; i++)
115 { /*{{{ */
116 ppkt->queries[i] = GNUNET_malloc (sizeof (struct dns_query));
117 char *name = alloca (255); /* see RFC1035, it can't be more than this. */
118
119 _idx = parse_dns_name (name, pkt->data, idx);
120 ppkt->queries[i]->namelen = _idx - idx;
121 idx = _idx;
122
123 ppkt->queries[i]->name = GNUNET_malloc (ppkt->queries[i]->namelen);
124 memcpy (ppkt->queries[i]->name, name, ppkt->queries[i]->namelen);
125
126 ppkt->queries[i]->qtype = *((unsigned short *) (pkt->data + idx));
127 idx += 2;
128 ppkt->queries[i]->qclass = *((unsigned short *) (pkt->data + idx));
129 idx += 2;
130 }
131 /*}}} */
132 idx = parse_dns_record (pkt->data, ppkt->answers, ancount, idx);
133 idx = parse_dns_record (pkt->data, ppkt->nameservers, nscount, idx);
134 idx = parse_dns_record (pkt->data, ppkt->additional, arcount, idx);
135 return ppkt;
136} /*}}} */
137
138static void
139unparse_dns_name (char *dest, char *src, size_t len)
140{
141 char *b = dest;
142 char cnt = 0;
143
144 dest++;
145 while (*src != 0)
146 {
147 while (*src != '.' && *src != 0)
148 {
149 *dest = *src;
150 src++;
151 dest++;
152 cnt++;
153 }
154 *b = cnt;
155 cnt = 0;
156 b = dest;
157 dest++;
158 src++;
159 }
160 *b = 0;
161}
162
163struct dns_pkt *
164unparse_dns_packet (struct dns_pkt_parsed *ppkt)
165{
166 size_t size = sizeof (struct dns_pkt) - 1;
167 int i;
168
169 for (i = 0; i < ntohs (ppkt->s.qdcount); i++)
170 size += ppkt->queries[i]->namelen + 1;
171
172 for (i = 0; i < ntohs (ppkt->s.ancount); i++)
173 {
174 size += ppkt->answers[i]->namelen + 1;
175 size += ppkt->answers[i]->data_len;
176 }
177 for (i = 0; i < ntohs (ppkt->s.nscount); i++)
178 {
179 size += ppkt->nameservers[i]->namelen + 1;
180 size += ppkt->nameservers[i]->data_len;
181 }
182 for (i = 0; i < ntohs (ppkt->s.arcount); i++)
183 {
184 size += ppkt->additional[i]->namelen + 1;
185 size += ppkt->additional[i]->data_len;
186 }
187
188 size +=
189 4 * ntohs (ppkt->s.qdcount) + 10 * (ntohs (ppkt->s.ancount) +
190 ntohs (ppkt->s.arcount) +
191 ntohs (ppkt->s.nscount));
192
193 struct dns_pkt *pkt = GNUNET_malloc (size);
194 char *pkt_c = (char *) pkt;
195
196 memcpy (&pkt->s, &ppkt->s, sizeof ppkt->s);
197 size_t idx = sizeof ppkt->s;
198
199 for (i = 0; i < ntohs (ppkt->s.qdcount); i++)
200 {
201 unparse_dns_name (&pkt_c[idx], ppkt->queries[i]->name,
202 ppkt->queries[i]->namelen);
203 idx += ppkt->queries[i]->namelen;
204 struct dns_query_line *d = (struct dns_query_line *) &pkt_c[idx];
205
206 d->class = ppkt->queries[i]->qclass;
207 d->type = ppkt->queries[i]->qtype;
208 idx += sizeof (struct dns_query_line);
209 }
210
211 for (i = 0; i < ntohs (ppkt->s.ancount); i++)
212 {
213 unparse_dns_name (&pkt_c[idx], ppkt->answers[i]->name,
214 ppkt->answers[i]->namelen);
215 idx += ppkt->answers[i]->namelen;
216 struct dns_record_line *r = (struct dns_record_line *) &pkt_c[idx];
217
218 r->type = ppkt->answers[i]->type;
219 r->class = ppkt->answers[i]->class;
220 r->ttl = ppkt->answers[i]->ttl;
221 r->data_len = ppkt->answers[i]->data_len;
222 idx += sizeof (struct dns_record_line);
223 memcpy (&r->data, ppkt->answers[i]->data, ppkt->answers[i]->data_len);
224 idx += ppkt->answers[i]->data_len;
225 }
226
227 for (i = 0; i < ntohs (ppkt->s.nscount); i++)
228 {
229 unparse_dns_name (&pkt_c[idx], ppkt->nameservers[i]->name,
230 ppkt->nameservers[i]->namelen);
231 idx += ppkt->nameservers[i]->namelen;
232 struct dns_record_line *r = (struct dns_record_line *) &pkt_c[idx];
233
234 r->type = ppkt->nameservers[i]->type;
235 r->class = ppkt->nameservers[i]->class;
236 r->ttl = ppkt->nameservers[i]->ttl;
237 r->data_len = ppkt->nameservers[i]->data_len;
238 idx += sizeof (struct dns_record_line);
239 memcpy (&r->data, ppkt->nameservers[i]->data,
240 ppkt->nameservers[i]->data_len);
241 idx += ppkt->nameservers[i]->data_len;
242 }
243
244 for (i = 0; i < ntohs (ppkt->s.arcount); i++)
245 {
246 unparse_dns_name (&pkt_c[idx], ppkt->additional[i]->name,
247 ppkt->additional[i]->namelen);
248 idx += ppkt->additional[i]->namelen;
249 struct dns_record_line *r = (struct dns_record_line *) &pkt_c[idx];
250
251 r->type = ppkt->additional[i]->type;
252 r->class = ppkt->additional[i]->class;
253 r->ttl = ppkt->additional[i]->ttl;
254 r->data_len = ppkt->additional[i]->data_len;
255 idx += sizeof (struct dns_record_line);
256 memcpy (&r->data, ppkt->additional[i]->data, ppkt->additional[i]->data_len);
257 idx += ppkt->additional[i]->data_len;
258 }
259
260 return pkt;
261}
262
263void
264free_parsed_dns_packet (struct dns_pkt_parsed *ppkt)
265{
266 unsigned short qdcount = ntohs (ppkt->s.qdcount);
267 unsigned short ancount = ntohs (ppkt->s.ancount);
268 unsigned short nscount = ntohs (ppkt->s.nscount);
269 unsigned short arcount = ntohs (ppkt->s.arcount);
270
271 int i;
272
273 for (i = 0; i < qdcount; i++)
274 {
275 GNUNET_free (ppkt->queries[i]->name);
276 GNUNET_free (ppkt->queries[i]);
277 }
278 GNUNET_free (ppkt->queries);
279 for (i = 0; i < ancount; i++)
280 {
281 GNUNET_free (ppkt->answers[i]->name);
282 GNUNET_free (ppkt->answers[i]->data);
283 GNUNET_free (ppkt->answers[i]);
284 }
285 GNUNET_free (ppkt->answers);
286 for (i = 0; i < nscount; i++)
287 {
288 GNUNET_free (ppkt->nameservers[i]->name);
289 GNUNET_free (ppkt->nameservers[i]->data);
290 GNUNET_free (ppkt->nameservers[i]);
291 }
292 GNUNET_free (ppkt->nameservers);
293 for (i = 0; i < arcount; i++)
294 {
295 GNUNET_free (ppkt->additional[i]->name);
296 GNUNET_free (ppkt->additional[i]->data);
297 GNUNET_free (ppkt->additional[i]);
298 }
299 GNUNET_free (ppkt->additional);
300 GNUNET_free (ppkt);
301}
diff --git a/src/vpn/gnunet-dns-parser.h b/src/vpn/gnunet-dns-parser.h
deleted file mode 100644
index a9ed5b3b2..000000000
--- a/src/vpn/gnunet-dns-parser.h
+++ /dev/null
@@ -1,95 +0,0 @@
1#ifndef _GNVPN_DNSP_H_
2#define _GNVPN_DNSP_H_
3
4#include "platform.h"
5#include "gnunet_common.h"
6
7// DNS-Stuff
8GNUNET_NETWORK_STRUCT_BEGIN
9
10struct dns_static
11{
12 uint16_t id GNUNET_PACKED;
13
14 unsigned rd:1 GNUNET_PACKED; // recursion desired (client -> server)
15 unsigned tc:1 GNUNET_PACKED; // message is truncated
16 unsigned aa:1 GNUNET_PACKED; // authoritative answer
17 unsigned op:4 GNUNET_PACKED; // query:0, inverse q.:1, status: 2
18 unsigned qr:1 GNUNET_PACKED; // query:0, response:1
19
20 unsigned rcode:4 GNUNET_PACKED; // 0 No error
21 // 1 Format error
22 // 2 Server failure
23 // 3 Name Error
24 // 4 Not Implemented
25 // 5 Refused
26 unsigned z:3 GNUNET_PACKED; // reserved
27 unsigned ra:1 GNUNET_PACKED; // recursion available (server -> client)
28
29 uint16_t qdcount GNUNET_PACKED; // number of questions
30 uint16_t ancount GNUNET_PACKED; // number of answers
31 uint16_t nscount GNUNET_PACKED; // number of authority-records
32 uint16_t arcount GNUNET_PACKED; // number of additional records
33};
34GNUNET_NETWORK_STRUCT_END
35
36struct dns_pkt
37{
38 struct dns_static s;
39 unsigned char data[1];
40};
41
42struct dns_pkt_parsed
43{
44 struct dns_static s;
45 struct dns_query **queries;
46 struct dns_record **answers;
47 struct dns_record **nameservers;
48 struct dns_record **additional;
49};
50
51struct dns_query_line
52{
53 unsigned short type;
54 unsigned short class;
55};
56
57struct dns_query
58{
59 char *name;
60 unsigned char namelen;
61 unsigned short qtype;
62 unsigned short qclass;
63};
64
65struct dns_record_line
66{
67 unsigned short type;
68 unsigned short class;
69 unsigned int ttl;
70 unsigned short data_len;
71 unsigned char data;
72};
73
74struct dns_record
75{
76 char *name;
77 unsigned char namelen;
78 unsigned short type;
79 unsigned short class;
80 unsigned int ttl;
81 unsigned short data_len;
82 unsigned char *data;
83};
84
85
86struct dns_pkt_parsed *
87parse_dns_packet (struct dns_pkt *pkt);
88
89struct dns_pkt *
90unparse_dns_packet (struct dns_pkt_parsed *pkt);
91
92void
93free_parsed_dns_packet (struct dns_pkt_parsed *ppkt);
94
95#endif
diff --git a/src/vpn/gnunet-helper-hijack-dns.c b/src/vpn/gnunet-helper-hijack-dns.c
deleted file mode 100644
index 70da96477..000000000
--- a/src/vpn/gnunet-helper-hijack-dns.c
+++ /dev/null
@@ -1,156 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2010 Christian Grothoff
4
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
7 by the Free Software Foundation; either version 3, or (at your
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 */
20
21/**
22 * @file vpn/gnunet-helper-hijack-dns.c
23 * @brief
24 * @author Philipp Tölke
25 */
26#include <platform.h>
27
28#include "gnunet_common.h"
29
30static int
31fork_and_exec (char *file, char *cmd[])
32{
33 pid_t pid = fork ();
34
35 if (pid < 0)
36 {
37 fprintf (stderr, "could not fork: %s\n", strerror (errno));
38 return GNUNET_SYSERR;
39 }
40
41 int st = 0;
42
43 if (pid == 0)
44 {
45 execv (file, cmd);
46 }
47 else
48 {
49 waitpid (pid, &st, 0);
50 }
51 return WIFEXITED (st) && (WEXITSTATUS (st) == 0);
52}
53
54int
55main (int argc, char **argv)
56{
57 int delete = 0;
58 int port = 0;
59 char *virt_dns;
60
61 if (argc < 3)
62 return GNUNET_SYSERR;
63
64 if (strncmp (argv[1], "-d", 2) == 0)
65 {
66 if (argc < 3)
67 return GNUNET_SYSERR;
68 delete = 1;
69 port = atoi (argv[2]);
70 virt_dns = argv[3];
71 }
72 else
73 {
74 port = atoi (argv[1]);
75 virt_dns = argv[2];
76 }
77
78 if (port == 0)
79 return GNUNET_SYSERR;
80
81 struct stat s;
82
83 if (stat ("/sbin/iptables", &s) < 0)
84 {
85 fprintf (stderr, "stat on /sbin/iptables failed: %s\n", strerror (errno));
86 return GNUNET_SYSERR;
87 }
88 if (stat ("/sbin/ip", &s) < 0)
89 {
90 fprintf (stderr, "stat on /sbin/ip failed: %s\n", strerror (errno));
91 return GNUNET_SYSERR;
92 }
93
94 char localport[7];
95
96 snprintf (localport, 7, "%d", port);
97
98 int r;
99
100 if (delete)
101 {
102e4:
103 r = fork_and_exec ("/sbin/ip", (char *[])
104 {
105 "ip", "route", "del", "default", "via", virt_dns,
106 "table", "2", NULL});
107e3:
108 r = fork_and_exec ("/sbin/ip", (char *[])
109 {
110 "ip", "rule", "del", "fwmark", "3", "table", "2", NULL});
111e2:
112 r = fork_and_exec ("/sbin/iptables", (char *[])
113 {
114 "iptables", "-t", "mangle", "-D", "OUTPUT", "-p", "udp",
115 "--dport", "53", "-j", "MARK", "--set-mark", "3", NULL});
116e1:
117 r = fork_and_exec ("/sbin/iptables", (char *[])
118 {
119 "iptables", "-t", "mangle", "-D", "OUTPUT", "-p", "udp",
120 "--sport", localport, "--dport", "53", "-j", "ACCEPT",
121 NULL});
122 if (!delete)
123 r = 0;
124 }
125 else
126 {
127 r = fork_and_exec ("/sbin/iptables", (char *[])
128 {
129 "iptables", "-t", "mangle", "-I", "OUTPUT", "1", "-p",
130 "udp", "--sport", localport, "--dport", "53", "-j",
131 "ACCEPT", NULL});
132 if (!r)
133 goto e1;
134 r = fork_and_exec ("/sbin/iptables", (char *[])
135 {
136 "iptables", "-t", "mangle", "-I", "OUTPUT", "2", "-p",
137 "udp", "--dport", "53", "-j", "MARK", "--set-mark", "3",
138 NULL});
139 if (!r)
140 goto e2;
141 r = fork_and_exec ("/sbin/ip", (char *[])
142 {
143 "ip", "rule", "add", "fwmark", "3", "table", "2", NULL});
144 if (!r)
145 goto e3;
146 r = fork_and_exec ("/sbin/ip", (char *[])
147 {
148 "ip", "route", "add", "default", "via", virt_dns,
149 "table", "2", NULL});
150 if (!r)
151 goto e4;
152 }
153 if (r)
154 return GNUNET_YES;
155 return GNUNET_SYSERR;
156}
diff --git a/src/vpn/gnunet-service-dns-p.h b/src/vpn/gnunet-service-dns-p.h
deleted file mode 100644
index 632145ae2..000000000
--- a/src/vpn/gnunet-service-dns-p.h
+++ /dev/null
@@ -1,116 +0,0 @@
1#ifndef GN_DNS_SERVICE_P_H
2#define GN_DNS_SERVICE_P_H
3
4#include "gnunet_common.h"
5
6GNUNET_NETWORK_STRUCT_BEGIN
7
8struct query_packet
9{
10 struct GNUNET_MessageHeader hdr;
11
12 /**
13 * The IP-Address this query was originally sent to
14 */
15 char orig_to[16];
16 /**
17 * The IP-Address this query was originally sent from
18 */
19 char orig_from[16];
20 /**
21 * The UDP-Portthis query was originally sent from
22 */
23 char addrlen;
24 uint16_t src_port GNUNET_PACKED;
25
26 unsigned char data[1]; /* The DNS-Packet */
27};
28
29struct query_packet_list
30{
31 struct query_packet_list *next GNUNET_PACKED;
32 struct query_packet_list *prev GNUNET_PACKED;
33 struct query_packet pkt;
34};
35
36enum GNUNET_DNS_ANSWER_Subtype
37{
38 /**
39 * Answers of this type contain a dns-packet that just has to be transmitted
40 */
41 GNUNET_DNS_ANSWER_TYPE_IP,
42
43 /**
44 * Answers of this type contain an incomplete dns-packet. The IP-Address
45 * is all 0s. The addroffset points to it.
46 */
47 GNUNET_DNS_ANSWER_TYPE_SERVICE,
48
49 /**
50 * Answers of this type contain an incomplete dns-packet as answer to a
51 * PTR-Query. The resolved name is not allocated. The addroffset points to it.
52 */
53 GNUNET_DNS_ANSWER_TYPE_REV,
54
55 /**
56 * Answers of this type contains an IP6-Address but traffic to this IP should
57 * be routed through the GNUNet.
58 */
59 GNUNET_DNS_ANSWER_TYPE_REMOTE_AAAA,
60
61 /**
62 * Answers of this type contains an IP4-Address but traffic to this IP should
63 * be routed through the GNUNet.
64 */
65 GNUNET_DNS_ANSWER_TYPE_REMOTE_A
66};
67
68struct GNUNET_vpn_service_descriptor
69{
70 GNUNET_HashCode peer GNUNET_PACKED;
71 GNUNET_HashCode service_descriptor GNUNET_PACKED;
72 uint64_t ports GNUNET_PACKED;
73 uint32_t service_type GNUNET_PACKED;
74};
75
76struct answer_packet
77{
78 /* General data */
79 struct GNUNET_MessageHeader hdr;
80 enum GNUNET_DNS_ANSWER_Subtype subtype GNUNET_PACKED;
81
82 char from[16];
83 char to[16];
84 char addrlen;
85 unsigned dst_port:16 GNUNET_PACKED;
86 /* -- */
87
88 /* Data for GNUNET_DNS_ANSWER_TYPE_SERVICE */
89 struct GNUNET_vpn_service_descriptor service_descr;
90 /* -- */
91
92 /* Data for GNUNET_DNS_ANSWER_TYPE_REV */
93 /* The offsett in octets from the beginning of the struct to the field
94 * in data where the IP-Address has to go. */
95 uint16_t addroffset GNUNET_PACKED;
96 /* -- */
97
98 /* Data for GNUNET_DNS_ANSWER_TYPE_REMOTE */
99 /* either 4 or 16 */
100 char addrsize;
101 unsigned char addr[16];
102 /* -- */
103
104 unsigned char data[1];
105};
106
107struct answer_packet_list
108{
109 struct answer_packet_list *next GNUNET_PACKED;
110 struct answer_packet_list *prev GNUNET_PACKED;
111 struct GNUNET_SERVER_Client *client;
112 struct answer_packet pkt;
113};
114GNUNET_NETWORK_STRUCT_END
115
116#endif
diff --git a/src/vpn/gnunet-service-dns.c b/src/vpn/gnunet-service-dns.c
deleted file mode 100644
index 12d0a93cf..000000000
--- a/src/vpn/gnunet-service-dns.c
+++ /dev/null
@@ -1,1731 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2009 Christian Grothoff (and other contributing authors)
4
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
7 by the Free Software Foundation; either version 3, or (at your
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*/
20
21/**
22 * @file vpn/gnunet-service-dns.c
23 * @author Philipp Toelke
24 */
25#include "platform.h"
26#include "gnunet_getopt_lib.h"
27#include "gnunet_service_lib.h"
28#include <gnunet_constants.h>
29#include "gnunet_network_lib.h"
30#include "gnunet_os_lib.h"
31#include "gnunet-service-dns-p.h"
32#include "gnunet_connection_lib.h"
33#include "gnunet_protocols.h"
34#include "gnunet_applications.h"
35#include "gnunet-vpn-packet.h"
36#include "gnunet_container_lib.h"
37#include "gnunet-dns-parser.h"
38#include "gnunet_dht_service.h"
39#include "gnunet_block_lib.h"
40#include "block_dns.h"
41#include "gnunet_crypto_lib.h"
42#include "gnunet_mesh_service.h"
43#include "gnunet_signatures.h"
44
45struct GNUNET_MESH_Handle *mesh_handle;
46
47struct GNUNET_CONNECTION_TransmitHandle *server_notify;
48
49/**
50 * The UDP-Socket through which DNS-Resolves will be sent if they are not to be
51 * sent through gnunet. The port of this socket will not be hijacked.
52 */
53static struct GNUNET_NETWORK_Handle *dnsout;
54static struct GNUNET_NETWORK_Handle *dnsout6;
55
56/**
57 * The port bound to the socket dnsout
58 */
59static unsigned short dnsoutport;
60
61/**
62 * A handle to the DHT-Service
63 */
64static struct GNUNET_DHT_Handle *dht;
65
66/**
67 * The configuration to use
68 */
69static const struct GNUNET_CONFIGURATION_Handle *cfg;
70
71/**
72 * A list of DNS-Responses that have to be sent to the requesting client
73 */
74static struct answer_packet_list *head;
75
76/**
77 * The tail of the list of DNS-responses
78 */
79static struct answer_packet_list *tail;
80
81/**
82 * A structure containing a mapping from network-byte-ordered DNS-id (16 bit) to
83 * some information needed to handle this query
84 *
85 * It currently allocates at least
86 * (1 + machine-width + machine-width + 32 + 32 + 16 + machine-width + 8) * 65536 bit
87 * = 17 MiB on 64 bit.
88 * = 11 MiB on 32 bit.
89 */
90static struct
91{
92 unsigned valid:1;
93 struct GNUNET_SERVER_Client *client;
94 struct GNUNET_MESH_Tunnel *tunnel;
95 char local_ip[16];
96 char remote_ip[16];
97 char addrlen;
98 uint16_t local_port;
99 char *name;
100 uint8_t namelen;
101 uint16_t qtype;
102} query_states[UINT16_MAX + 1];
103
104/**
105 * A struct used to give more than one value as
106 * closure to receive_dht
107 */
108struct receive_dht_cls
109{
110 uint16_t id;
111 struct GNUNET_DHT_GetHandle *handle;
112};
113
114struct tunnel_notify_queue
115{
116 struct tunnel_notify_queue *next;
117 struct tunnel_notify_queue *prev;
118 void *cls;
119 size_t len;
120 GNUNET_CONNECTION_TransmitReadyNotify cb;
121};
122
123struct tunnel_state
124{
125 struct tunnel_notify_queue *head, *tail;
126 struct GNUNET_MESH_TransmitHandle *th;
127};
128
129static size_t
130send_answer (void *cls, size_t size, void *buf);
131
132static void
133client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
134{
135 if (NULL == head)
136 return;
137
138 if (head->client == client)
139 {
140 GNUNET_CONNECTION_notify_transmit_ready_cancel (server_notify);
141 server_notify =
142 GNUNET_SERVER_notify_transmit_ready (head->next->client,
143 ntohs (head->next->pkt.hdr.size),
144 GNUNET_TIME_UNIT_FOREVER_REL,
145 &send_answer, NULL);
146 }
147
148 struct answer_packet_list *element = head;
149
150 while (element != NULL)
151 {
152 if (element->client == client)
153 {
154 GNUNET_SERVER_client_drop (client);
155 GNUNET_CONTAINER_DLL_remove (head, tail, element);
156 struct answer_packet_list *t = element;
157
158 element = element->next;
159 GNUNET_free (t);
160 }
161 else
162 element = element->next;
163 }
164}
165
166/**
167 * Hijack all outgoing DNS-Traffic but for traffic leaving "our" port.
168 */
169static void
170hijack (void *cls GNUNET_UNUSED, const struct GNUNET_SCHEDULER_TaskContext *tc)
171{
172 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
173 return;
174
175 if (0 == dnsoutport)
176 {
177 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
178 "Delaying the hijacking, port is still %d!\n", dnsoutport);
179 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &hijack, NULL);
180 return;
181 }
182
183 char port_s[6];
184 char *virt_dns;
185 struct GNUNET_OS_Process *proc;
186
187 if (GNUNET_SYSERR ==
188 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "VIRTDNS", &virt_dns))
189 {
190 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
191 "No entry 'VIRTDNS' in configuration!\n");
192 exit (1);
193 }
194
195 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hijacking, port is %d\n", dnsoutport);
196 snprintf (port_s, 6, "%d", dnsoutport);
197 if (NULL !=
198 (proc =
199 GNUNET_OS_start_process (NULL, NULL, "gnunet-helper-hijack-dns",
200 "gnunet-hijack-dns", port_s, virt_dns, NULL)))
201 {
202 GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (proc));
203 GNUNET_OS_process_close (proc);
204 }
205 GNUNET_free (virt_dns);
206}
207
208static void *
209new_tunnel (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
210 const struct GNUNET_PeerIdentity *initiator GNUNET_UNUSED,
211 const struct GNUNET_ATS_Information *ats GNUNET_UNUSED)
212{
213 struct tunnel_state *s = GNUNET_malloc (sizeof *s);
214
215 s->head = NULL;
216 s->tail = NULL;
217 s->th = NULL;
218 return s;
219}
220
221static void
222clean_tunnel (void *cls GNUNET_UNUSED, const struct GNUNET_MESH_Tunnel *tunnel,
223 void *tunnel_ctx)
224{
225 GNUNET_free (tunnel_ctx);
226}
227
228/**
229 * Delete the hijacking-routes
230 */
231static void
232unhijack (unsigned short port)
233{
234 char port_s[6];
235 char *virt_dns;
236 struct GNUNET_OS_Process *proc;
237
238 if (GNUNET_SYSERR ==
239 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "VIRTDNS", &virt_dns))
240 {
241 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
242 "No entry 'VIRTDNS' in configuration!\n");
243 exit (1);
244 }
245
246 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "unHijacking, port is %d\n", port);
247 snprintf (port_s, 6, "%d", port);
248 if (NULL !=
249 (proc =
250 GNUNET_OS_start_process (NULL, NULL, "gnunet-helper-hijack-dns",
251 "gnunet-hijack-dns", "-d", port_s, virt_dns,
252 NULL)))
253 {
254 GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (proc));
255 GNUNET_OS_process_close (proc);
256 }
257 GNUNET_free (virt_dns);
258}
259
260/**
261 * Send the DNS-Response to the client. Gets called via the notify_transmit_ready-
262 * system.
263 */
264static size_t
265send_answer (void *cls, size_t size, void *buf)
266{
267 server_notify = NULL;
268 struct answer_packet_list *query = head;
269 size_t len = ntohs (query->pkt.hdr.size);
270
271 GNUNET_assert (len <= size);
272
273 memcpy (buf, &query->pkt.hdr, len);
274
275 GNUNET_CONTAINER_DLL_remove (head, tail, query);
276
277 /* When more data is to be sent, reschedule */
278 if (head != NULL)
279 server_notify =
280 GNUNET_SERVER_notify_transmit_ready (head->client,
281 ntohs (head->pkt.hdr.size),
282 GNUNET_TIME_UNIT_FOREVER_REL,
283 &send_answer, NULL);
284
285 GNUNET_SERVER_client_drop (query->client);
286 GNUNET_free (query);
287 return len;
288}
289
290GNUNET_NETWORK_STRUCT_BEGIN
291
292struct tunnel_cls
293{
294 struct GNUNET_MESH_Tunnel *tunnel GNUNET_PACKED;
295 struct GNUNET_MessageHeader hdr;
296 struct dns_pkt dns;
297};
298GNUNET_NETWORK_STRUCT_END
299
300struct tunnel_cls *remote_pending[UINT16_MAX];
301
302static size_t
303mesh_send_response (void *cls, size_t size, void *buf)
304{
305 GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader));
306 struct GNUNET_MessageHeader *hdr = buf;
307 uint32_t *sz = cls;
308 struct GNUNET_MESH_Tunnel **tunnel = (struct GNUNET_MESH_Tunnel **) (sz + 1);
309 struct dns_pkt *dns = (struct dns_pkt *) (tunnel + 1);
310
311 GNUNET_MESH_tunnel_set_data (*tunnel, NULL);
312
313 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_ANSWER_DNS);
314 hdr->size = htons (*sz + sizeof (struct GNUNET_MessageHeader));
315
316 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
317 "Sending response, size=%d, sz=%d, sz+hdr=%d\n", size, *sz,
318 *sz + sizeof (struct GNUNET_MessageHeader));
319
320 GNUNET_assert (size >= (*sz + sizeof (struct GNUNET_MessageHeader)));
321
322 memcpy (hdr + 1, dns, *sz);
323 struct tunnel_state *s = GNUNET_MESH_tunnel_get_data (*tunnel);
324
325 if (NULL != s->head)
326 {
327 struct tunnel_notify_queue *element = s->head;
328 struct tunnel_notify_queue *head = s->head;
329 struct tunnel_notify_queue *tail = s->tail;
330
331 GNUNET_CONTAINER_DLL_remove (head, tail, element);
332
333 s->th =
334 GNUNET_MESH_notify_transmit_ready (*tunnel, GNUNET_NO, 42,
335 GNUNET_TIME_relative_divide
336 (GNUNET_CONSTANTS_MAX_CORK_DELAY, 2),
337 (const struct GNUNET_PeerIdentity *)
338 NULL, element->len, element->cb,
339 element->cls);
340 }
341
342 GNUNET_free (cls);
343
344 return ntohs (hdr->size);
345}
346
347static size_t
348mesh_send (void *cls, size_t size, void *buf)
349{
350 struct tunnel_cls *cls_ = (struct tunnel_cls *) cls;
351
352 GNUNET_MESH_tunnel_set_data (cls_->tunnel, NULL);
353
354 GNUNET_assert (cls_->hdr.size <= size);
355
356 size = cls_->hdr.size;
357 cls_->hdr.size = htons (cls_->hdr.size);
358
359 memcpy (buf, &cls_->hdr, size);
360
361 struct tunnel_state *s = GNUNET_MESH_tunnel_get_data (cls_->tunnel);
362
363 if (NULL != s->head)
364 {
365 struct tunnel_notify_queue *element = s->head;
366 struct tunnel_notify_queue *head = s->head;
367 struct tunnel_notify_queue *tail = s->tail;;
368
369 GNUNET_CONTAINER_DLL_remove (head, tail, element);
370
371 s->th =
372 GNUNET_MESH_notify_transmit_ready (cls_->tunnel, GNUNET_NO, 42,
373 GNUNET_TIME_relative_divide
374 (GNUNET_CONSTANTS_MAX_CORK_DELAY, 2),
375 (const struct GNUNET_PeerIdentity *)
376 NULL, element->len, element->cb,
377 element->cls);
378
379 GNUNET_free (element);
380 }
381
382 return size;
383}
384
385
386void
387mesh_connect (void *cls, const struct GNUNET_PeerIdentity *peer,
388 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
389{
390 if (NULL == peer)
391 return;
392 struct tunnel_cls *cls_ = (struct tunnel_cls *) cls;
393
394 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
395 "Connected to peer %s, %x, sending query with id %d\n",
396 GNUNET_i2s (peer), peer, ntohs (cls_->dns.s.id));
397
398 struct tunnel_state *s = GNUNET_MESH_tunnel_get_data (cls_->tunnel);
399
400 if (NULL == s->head)
401 {
402 s->th =
403 GNUNET_MESH_notify_transmit_ready (cls_->tunnel, GNUNET_YES, 42,
404 GNUNET_TIME_UNIT_MINUTES, NULL,
405 cls_->hdr.size, mesh_send, cls);
406
407 }
408 else
409 {
410 struct tunnel_notify_queue *head = s->head;
411 struct tunnel_notify_queue *tail = s->tail;
412
413 struct tunnel_notify_queue *element =
414 GNUNET_malloc (sizeof (struct tunnel_notify_queue));
415 element->cls = cls;
416 element->len = cls_->hdr.size;
417 element->cb = mesh_send;
418
419 GNUNET_CONTAINER_DLL_insert_tail (head, tail, element);
420 }
421}
422
423
424static void
425send_mesh_query (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
426{
427 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
428 return;
429
430 struct tunnel_cls *cls_ = (struct tunnel_cls *) cls;
431
432 struct tunnel_state *s = GNUNET_malloc (sizeof *s);
433
434 s->head = NULL;
435 s->tail = NULL;
436 s->th = NULL;
437
438 cls_->tunnel =
439 GNUNET_MESH_tunnel_create (mesh_handle, s, mesh_connect, NULL, cls_);
440
441 GNUNET_MESH_peer_request_connect_by_type (cls_->tunnel,
442 GNUNET_APPLICATION_TYPE_INTERNET_RESOLVER);
443
444 remote_pending[cls_->dns.s.id] = cls_;
445}
446
447static int
448receive_mesh_query (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
449 void **ctx GNUNET_UNUSED,
450 const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
451 const struct GNUNET_MessageHeader *message,
452 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
453{
454 struct dns_pkt *dns = (struct dns_pkt *) (message + 1);
455
456 struct sockaddr_in dest;
457
458 struct dns_pkt_parsed *pdns = parse_dns_packet (dns);
459
460 memset (&dest, 0, sizeof dest);
461 dest.sin_port = htons (53);
462 char *dns_resolver;
463
464 if (GNUNET_OK !=
465 GNUNET_CONFIGURATION_get_value_string (cfg, "dns", "EXTERNAL_DNS",
466 &dns_resolver) ||
467 1 != inet_pton (AF_INET, dns_resolver, &dest.sin_addr))
468 inet_pton (AF_INET, "8.8.8.8", &dest.sin_addr);
469
470 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Querying for remote, id=%d\n",
471 ntohs (dns->s.id));
472 query_states[dns->s.id].tunnel = tunnel;
473 query_states[dns->s.id].valid = GNUNET_YES;
474
475 int i;
476
477 for (i = 0; i < ntohs (pdns->s.qdcount); i++)
478 {
479 if (pdns->queries[i]->qtype == htons (28) ||
480 pdns->queries[i]->qtype == htons (1))
481 {
482 query_states[dns->s.id].qtype = pdns->queries[i]->qtype;
483 break;
484 }
485 }
486 free_parsed_dns_packet (pdns);
487
488 GNUNET_NETWORK_socket_sendto (dnsout, dns,
489 ntohs (message->size) -
490 sizeof (struct GNUNET_MessageHeader),
491 (struct sockaddr *) &dest, sizeof dest);
492
493 return GNUNET_SYSERR;
494}
495
496static int
497receive_mesh_answer (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
498 void **ctx GNUNET_UNUSED,
499 const struct GNUNET_PeerIdentity *sender,
500 const struct GNUNET_MessageHeader *message,
501 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
502{
503 /* TODo: size check */
504 struct dns_pkt *dns = (struct dns_pkt *) (message + 1);
505
506 /* They sent us a packet we were not waiting for */
507 if (remote_pending[dns->s.id] == NULL ||
508 remote_pending[dns->s.id]->tunnel != tunnel)
509 return GNUNET_OK;
510
511 GNUNET_free (remote_pending[dns->s.id]);
512 remote_pending[dns->s.id] = NULL;
513
514 if (query_states[dns->s.id].valid != GNUNET_YES)
515 return GNUNET_SYSERR;
516 query_states[dns->s.id].valid = GNUNET_NO;
517
518 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
519 "Received answer from peer %s, dns-id %d\n", GNUNET_i2s (sender),
520 ntohs (dns->s.id));
521
522 size_t len = sizeof (struct answer_packet) - 1 + sizeof (struct dns_static) + query_states[dns->s.id].namelen + sizeof (struct dns_query_line) + 2 /* To hold the pointer (as defined in RFC1035) to the name */
523 + sizeof (struct dns_record_line) - 1 + 16; /* To hold the IPv6-Address */
524
525 struct answer_packet_list *answer =
526 GNUNET_malloc (len + sizeof (struct answer_packet_list) -
527 sizeof (struct answer_packet));
528
529 answer->pkt.hdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_DNS_LOCAL_RESPONSE_DNS);
530 answer->pkt.hdr.size = htons (len);
531
532 struct dns_pkt_parsed *pdns = parse_dns_packet (dns);
533
534 if (ntohs (pdns->s.ancount) < 1)
535 {
536 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Answer only contains %d answers.\n",
537 ntohs (pdns->s.ancount));
538 free_parsed_dns_packet (pdns);
539 GNUNET_free (answer);
540 return GNUNET_OK;
541 }
542
543 int i = 0;
544
545 while (i < ntohs (pdns->s.ancount) && ntohs (pdns->answers[i]->type) != 28 &&
546 ntohs (pdns->answers[i]->type) != 1)
547 {
548 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Answer contains %d.\n",
549 ntohs (pdns->answers[i]->type));
550 i++;
551 }
552
553 if (i >= ntohs (pdns->s.ancount))
554 {
555 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
556 "Answer does not contain any usable answers.\n");
557 free_parsed_dns_packet (pdns);
558 GNUNET_free (answer);
559 return GNUNET_OK;
560 }
561
562 answer->pkt.addrsize = ntohs (pdns->answers[i]->data_len);
563 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "The first answer has the addrlen %d\n",
564 answer->pkt.addrsize);
565 memcpy (answer->pkt.addr, pdns->answers[i]->data,
566 ntohs (pdns->answers[i]->data_len));
567
568 memcpy (answer->pkt.from, query_states[dns->s.id].remote_ip,
569 query_states[dns->s.id].addrlen);
570 memcpy (answer->pkt.to, query_states[dns->s.id].local_ip,
571 query_states[dns->s.id].addrlen);
572 answer->pkt.addrlen = query_states[dns->s.id].addrlen;
573 answer->pkt.dst_port = query_states[dns->s.id].local_port;
574
575 struct dns_pkt *dpkt = (struct dns_pkt *) answer->pkt.data;
576
577 dpkt->s.id = dns->s.id;
578 dpkt->s.aa = 1;
579 dpkt->s.qr = 1;
580 dpkt->s.ra = 1;
581 dpkt->s.qdcount = htons (1);
582 dpkt->s.ancount = htons (1);
583
584 memcpy (dpkt->data, query_states[dns->s.id].name,
585 query_states[dns->s.id].namelen);
586 GNUNET_free (query_states[dns->s.id].name);
587 query_states[dns->s.id].name = NULL;
588
589 struct dns_query_line *dque =
590 (struct dns_query_line *) (dpkt->data +
591 (query_states[dns->s.id].namelen));
592
593 struct dns_record_line *drec_data =
594 (struct dns_record_line *) (dpkt->data +
595 (query_states[dns->s.id].namelen) +
596 sizeof (struct dns_query_line) + 2);
597 if (htons (28) == query_states[dns->s.id].qtype)
598 {
599 answer->pkt.subtype = GNUNET_DNS_ANSWER_TYPE_REMOTE_AAAA;
600 dque->type = htons (28); /* AAAA */
601 drec_data->type = htons (28); /* AAAA */
602 drec_data->data_len = htons (16);
603 }
604 else if (htons (1) == query_states[dns->s.id].qtype)
605 {
606 answer->pkt.subtype = GNUNET_DNS_ANSWER_TYPE_REMOTE_A;
607 dque->type = htons (1); /* A */
608 drec_data->type = htons (1); /* A */
609 drec_data->data_len = htons (4);
610 }
611 else
612 {
613 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "dns-answer with pending qtype = %d\n",
614 query_states[dns->s.id].qtype);
615 GNUNET_assert (0);
616 }
617 dque->class = htons (1); /* IN */
618
619 char *anname =
620 (char *) (dpkt->data + (query_states[dns->s.id].namelen) +
621 sizeof (struct dns_query_line));
622 memcpy (anname, "\xc0\x0c", 2);
623 drec_data->class = htons (1); /* IN */
624
625 drec_data->ttl = pdns->answers[i]->ttl;
626
627 /* Calculate at which offset in the packet the IPv6-Address belongs, it is
628 * filled in by the daemon-vpn */
629 answer->pkt.addroffset =
630 htons ((unsigned short) ((unsigned long) (&drec_data->data) -
631 (unsigned long) (&answer->pkt)));
632
633 GNUNET_CONTAINER_DLL_insert_after (head, tail, tail, answer);
634 answer->client = query_states[dns->s.id].client;
635
636 if (server_notify == NULL)
637 server_notify =
638 GNUNET_SERVER_notify_transmit_ready (query_states[dns->s.id].client,
639 len, GNUNET_TIME_UNIT_FOREVER_REL,
640 &send_answer, NULL);
641
642 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
643 "Sent answer of length %d on to client, addroffset = %d\n", len,
644 answer->pkt.addroffset);
645
646 free_parsed_dns_packet (pdns);
647 return GNUNET_OK;
648}
649
650
651static void
652send_rev_query (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
653{
654 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
655 return;
656
657 struct dns_pkt_parsed *pdns = (struct dns_pkt_parsed *) cls;
658
659 unsigned short id = pdns->s.id;
660
661 free_parsed_dns_packet (pdns);
662
663 if (query_states[id].valid != GNUNET_YES)
664 return;
665 query_states[id].valid = GNUNET_NO;
666
667 GNUNET_assert (query_states[id].namelen == 74);
668
669 size_t len = sizeof (struct answer_packet) - 1 + sizeof (struct dns_static) + 74 /* this is the length of a reverse ipv6-lookup */
670 + sizeof (struct dns_query_line) + 2 /* To hold the pointer (as defined in RFC1035) to the name */
671 + sizeof (struct dns_record_line) - 1 -
672 2 /* We do not know the lenght of the answer yet */ ;
673
674 struct answer_packet_list *answer =
675 GNUNET_malloc (len + sizeof (struct answer_packet_list) -
676 sizeof (struct answer_packet));
677
678 answer->pkt.hdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_DNS_LOCAL_RESPONSE_DNS);
679 answer->pkt.hdr.size = htons (len);
680 answer->pkt.subtype = GNUNET_DNS_ANSWER_TYPE_REV;
681
682 memcpy (answer->pkt.from, query_states[id].remote_ip,
683 query_states[id].addrlen);
684 memcpy (answer->pkt.to, query_states[id].local_ip, query_states[id].addrlen);
685
686 answer->pkt.dst_port = query_states[id].local_port;
687
688 struct dns_pkt *dpkt = (struct dns_pkt *) answer->pkt.data;
689
690 dpkt->s.id = id;
691 dpkt->s.aa = 1;
692 dpkt->s.qr = 1;
693 dpkt->s.ra = 1;
694 dpkt->s.qdcount = htons (1);
695 dpkt->s.ancount = htons (1);
696
697 memcpy (dpkt->data, query_states[id].name, query_states[id].namelen);
698 GNUNET_free (query_states[id].name);
699 query_states[id].name = NULL;
700
701 struct dns_query_line *dque =
702 (struct dns_query_line *) (dpkt->data + (query_states[id].namelen));
703 dque->type = htons (12); /* PTR */
704 dque->class = htons (1); /* IN */
705
706 char *anname =
707 (char *) (dpkt->data + (query_states[id].namelen) +
708 sizeof (struct dns_query_line));
709 memcpy (anname, "\xc0\x0c", 2);
710
711 struct dns_record_line *drec_data =
712 (struct dns_record_line *) (dpkt->data + (query_states[id].namelen) +
713 sizeof (struct dns_query_line) + 2);
714 drec_data->type = htons (12); /* AAAA */
715 drec_data->class = htons (1); /* IN */
716 /* FIXME: read the TTL from block:
717 * GNUNET_TIME_absolute_get_remaining(rec->expiration_time)
718 *
719 * But how to get the seconds out of this?
720 */
721 drec_data->ttl = htonl (3600);
722
723 /* Calculate at which offset in the packet the length of the name and the
724 * name, it is filled in by the daemon-vpn */
725 answer->pkt.addroffset =
726 htons ((unsigned short) ((unsigned long) (&drec_data->data_len) -
727 (unsigned long) (&answer->pkt)));
728
729 GNUNET_CONTAINER_DLL_insert_after (head, tail, tail, answer);
730 answer->client = query_states[id].client;
731
732 if (server_notify == NULL)
733 server_notify =
734 GNUNET_SERVER_notify_transmit_ready (query_states[id].client, len,
735 GNUNET_TIME_UNIT_FOREVER_REL,
736 &send_answer, NULL);
737}
738
739/**
740 * Receive a block from the dht.
741 */
742static void
743receive_dht (void *cls, struct GNUNET_TIME_Absolute exp GNUNET_UNUSED,
744 const GNUNET_HashCode * key GNUNET_UNUSED,
745 const struct GNUNET_PeerIdentity *get_path GNUNET_UNUSED,
746 unsigned int get_path_length GNUNET_UNUSED,
747 const struct GNUNET_PeerIdentity *put_path GNUNET_UNUSED,
748 unsigned int put_path_length GNUNET_UNUSED,
749 enum GNUNET_BLOCK_Type type, size_t size, const void *data)
750{
751
752 unsigned short id = ((struct receive_dht_cls *) cls)->id;
753 struct GNUNET_DHT_GetHandle *handle =
754 ((struct receive_dht_cls *) cls)->handle;
755 GNUNET_free (cls);
756
757 GNUNET_DHT_get_stop (handle);
758
759 GNUNET_assert (type == GNUNET_BLOCK_TYPE_DNS);
760
761 /* If no query with this id is pending, ignore the block */
762 if (query_states[id].valid != GNUNET_YES)
763 return;
764 query_states[id].valid = GNUNET_NO;
765
766 const struct GNUNET_DNS_Record *rec = data;
767
768 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
769 "Got block of size %d, peer: %08x, desc: %08x\n", size,
770 *((unsigned int *) &rec->peer),
771 *((unsigned int *) &rec->service_descriptor));
772
773 size_t len = sizeof (struct answer_packet) - 1 + sizeof (struct dns_static) + query_states[id].namelen + sizeof (struct dns_query_line) + 2 /* To hold the pointer (as defined in RFC1035) to the name */
774 + sizeof (struct dns_record_line) - 1 + 16; /* To hold the IPv6-Address */
775
776 struct answer_packet_list *answer =
777 GNUNET_malloc (len + sizeof (struct answer_packet_list) -
778 sizeof (struct answer_packet));
779
780 answer->pkt.hdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_DNS_LOCAL_RESPONSE_DNS);
781 answer->pkt.hdr.size = htons (len);
782 answer->pkt.subtype = GNUNET_DNS_ANSWER_TYPE_SERVICE;
783 answer->client = query_states[id].client;
784
785 GNUNET_CRYPTO_hash (&rec->peer,
786 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
787 &answer->pkt.service_descr.peer);
788
789 memcpy (&answer->pkt.service_descr.service_descriptor,
790 &rec->service_descriptor, sizeof (GNUNET_HashCode));
791 memcpy (&answer->pkt.service_descr.service_type, &rec->service_type,
792 sizeof (answer->pkt.service_descr.service_type));
793 memcpy (&answer->pkt.service_descr.ports, &rec->ports,
794 sizeof (answer->pkt.service_descr.ports));
795
796 memcpy (answer->pkt.from, query_states[id].remote_ip,
797 query_states[id].addrlen);
798 memcpy (answer->pkt.to, query_states[id].local_ip, query_states[id].addrlen);
799 answer->pkt.addrlen = query_states[id].addrlen;
800
801 answer->pkt.dst_port = query_states[id].local_port;
802
803 struct dns_pkt *dpkt = (struct dns_pkt *) answer->pkt.data;
804
805 dpkt->s.id = id;
806 dpkt->s.aa = 1;
807 dpkt->s.qr = 1;
808 dpkt->s.ra = 1;
809 dpkt->s.qdcount = htons (1);
810 dpkt->s.ancount = htons (1);
811
812 memcpy (dpkt->data, query_states[id].name, query_states[id].namelen);
813 GNUNET_free (query_states[id].name);
814 query_states[id].name = NULL;
815
816 struct dns_query_line *dque =
817 (struct dns_query_line *) (dpkt->data + (query_states[id].namelen));
818 dque->type = htons (28); /* AAAA */
819 dque->class = htons (1); /* IN */
820
821 char *anname =
822 (char *) (dpkt->data + (query_states[id].namelen) +
823 sizeof (struct dns_query_line));
824 memcpy (anname, "\xc0\x0c", 2);
825
826 struct dns_record_line *drec_data =
827 (struct dns_record_line *) (dpkt->data + (query_states[id].namelen) +
828 sizeof (struct dns_query_line) + 2);
829 drec_data->type = htons (28); /* AAAA */
830 drec_data->class = htons (1); /* IN */
831
832 /* FIXME: read the TTL from block:
833 * GNUNET_TIME_absolute_get_remaining(rec->expiration_time)
834 *
835 * But how to get the seconds out of this?
836 */
837 drec_data->ttl = htonl (3600);
838 drec_data->data_len = htons (16);
839
840 /* Calculate at which offset in the packet the IPv6-Address belongs, it is
841 * filled in by the daemon-vpn */
842 answer->pkt.addroffset =
843 htons ((unsigned short) ((unsigned long) (&drec_data->data) -
844 (unsigned long) (&answer->pkt)));
845
846 GNUNET_CONTAINER_DLL_insert_after (head, tail, tail, answer);
847
848 if (server_notify == NULL)
849 server_notify =
850 GNUNET_SERVER_notify_transmit_ready (answer->client, len,
851 GNUNET_TIME_UNIT_FOREVER_REL,
852 &send_answer, NULL);
853}
854
855/**
856 * This receives a GNUNET_MESSAGE_TYPE_REHIJACK and rehijacks the DNS
857 */
858static void
859rehijack (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Client *client,
860 const struct GNUNET_MessageHeader *message GNUNET_UNUSED)
861{
862 unhijack (dnsoutport);
863 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &hijack, NULL);
864
865 GNUNET_SERVER_receive_done (client, GNUNET_OK);
866}
867
868/**
869 * This receives the dns-payload from the daemon-vpn and sends it on over the udp-socket
870 */
871static void
872receive_query (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Client *client,
873 const struct GNUNET_MessageHeader *message)
874{
875 struct query_packet *pkt = (struct query_packet *) message;
876 struct dns_pkt *dns = (struct dns_pkt *) pkt->data;
877 struct dns_pkt_parsed *pdns = parse_dns_packet (dns);
878
879 query_states[dns->s.id].valid = GNUNET_YES;
880 query_states[dns->s.id].client = client;
881 GNUNET_SERVER_client_keep (client);
882 memcpy (query_states[dns->s.id].local_ip, pkt->orig_from, pkt->addrlen);
883 query_states[dns->s.id].addrlen = pkt->addrlen;
884 query_states[dns->s.id].local_port = pkt->src_port;
885 memcpy (query_states[dns->s.id].remote_ip, pkt->orig_to, pkt->addrlen);
886 query_states[dns->s.id].namelen = strlen ((char *) dns->data) + 1;
887 if (query_states[dns->s.id].name != NULL)
888 GNUNET_free (query_states[dns->s.id].name);
889 query_states[dns->s.id].name =
890 GNUNET_malloc (query_states[dns->s.id].namelen);
891 memcpy (query_states[dns->s.id].name, dns->data,
892 query_states[dns->s.id].namelen);
893
894 int i;
895
896 for (i = 0; i < ntohs (pdns->s.qdcount); i++)
897 {
898 if (pdns->queries[i]->qtype == htons (28) ||
899 pdns->queries[i]->qtype == htons (1))
900 {
901 query_states[dns->s.id].qtype = pdns->queries[i]->qtype;
902 break;
903 }
904 }
905
906 /* The query is for a .gnunet-address */
907 if (pdns->queries[0]->namelen > 9 &&
908 0 == strncmp (pdns->queries[0]->name + (pdns->queries[0]->namelen - 9),
909 ".gnunet.", 9))
910 {
911 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Query for .gnunet!\n");
912 GNUNET_HashCode key;
913
914 GNUNET_CRYPTO_hash (pdns->queries[0]->name, pdns->queries[0]->namelen,
915 &key);
916
917 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting with key %08x, len is %d\n",
918 *((unsigned int *) &key), pdns->queries[0]->namelen);
919
920 struct receive_dht_cls *cls =
921 GNUNET_malloc (sizeof (struct receive_dht_cls));
922 cls->id = dns->s.id;
923
924 cls->handle =
925 GNUNET_DHT_get_start (dht, GNUNET_TIME_UNIT_MINUTES,
926 GNUNET_BLOCK_TYPE_DNS, &key,
927 5 /* DEFAULT_GET_REPLICATION */ ,
928 GNUNET_DHT_RO_NONE, NULL, 0, &receive_dht, cls);
929
930 goto outfree;
931 }
932
933 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Query for '%s'; namelen=%d\n",
934 pdns->queries[0]->name, pdns->queries[0]->namelen);
935
936 /* This is a PTR-Query. Check if it is for "our" network */
937 if (htons (pdns->queries[0]->qtype) == 12 && 74 == pdns->queries[0]->namelen)
938 {
939 char *ipv6addr;
940 char ipv6[16];
941 char ipv6rev[74] =
942 "X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.ip6.arpa.";
943 unsigned int i;
944 unsigned long long ipv6prefix;
945 unsigned int comparelen;
946
947 GNUNET_assert (GNUNET_OK ==
948 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn",
949 "IPV6ADDR",
950 &ipv6addr));
951 inet_pton (AF_INET6, ipv6addr, ipv6);
952 GNUNET_free (ipv6addr);
953
954 GNUNET_assert (GNUNET_OK ==
955 GNUNET_CONFIGURATION_get_value_number (cfg, "vpn",
956 "IPV6PREFIX",
957 &ipv6prefix));
958 GNUNET_assert (ipv6prefix < 127);
959 ipv6prefix = (ipv6prefix + 7) / 8;
960
961 for (i = ipv6prefix; i < 16; i++)
962 ipv6[i] = 0;
963
964 for (i = 0; i < 16; i++)
965 {
966 unsigned char c1 = ipv6[i] >> 4;
967 unsigned char c2 = ipv6[i] & 0xf;
968
969 if (c1 <= 9)
970 ipv6rev[62 - (4 * i)] = c1 + '0';
971 else
972 ipv6rev[62 - (4 * i)] = c1 + 87; /* 87 is the difference between 'a' and 10 */
973
974 if (c2 <= 9)
975 ipv6rev[62 - ((4 * i) + 2)] = c2 + '0';
976 else
977 ipv6rev[62 - ((4 * i) + 2)] = c2 + 87;
978 }
979 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "My network is %s'.\n", ipv6rev);
980 comparelen = 10 + 4 * ipv6prefix;
981 if (0 ==
982 strncmp (pdns->queries[0]->name +
983 (pdns->queries[0]->namelen - comparelen),
984 ipv6rev + (74 - comparelen), comparelen))
985 {
986 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Reverse-Query for .gnunet!\n");
987
988 GNUNET_SCHEDULER_add_now (send_rev_query, pdns);
989
990 goto out;
991 }
992 }
993
994 unsigned char virt_dns_bytes[16];
995
996 if (pkt->addrlen == 4)
997 {
998 char *virt_dns;
999
1000 if (GNUNET_SYSERR ==
1001 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "VIRTDNS",
1002 &virt_dns))
1003 {
1004 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1005 "No entry 'VIRTDNS' in configuration!\n");
1006 exit (1);
1007 }
1008
1009 if (1 != inet_pton (AF_INET, virt_dns, &virt_dns_bytes))
1010 {
1011 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error parsing 'VIRTDNS': %s; %m!\n",
1012 virt_dns);
1013 exit (1);
1014 }
1015
1016 GNUNET_free (virt_dns);
1017 }
1018 else if (pkt->addrlen == 16)
1019 {
1020 char *virt_dns;
1021
1022 if (GNUNET_SYSERR ==
1023 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "VIRTDNS6",
1024 &virt_dns))
1025 {
1026 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1027 "No entry 'VIRTDNS6' in configuration!\n");
1028 exit (1);
1029 }
1030
1031 if (1 != inet_pton (AF_INET6, virt_dns, &virt_dns_bytes))
1032 {
1033 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1034 "Error parsing 'VIRTDNS6': %s; %m!\n", virt_dns);
1035 exit (1);
1036 }
1037
1038 GNUNET_free (virt_dns);
1039 }
1040 else
1041 {
1042 GNUNET_assert (0);
1043 }
1044
1045 if (memcmp (virt_dns_bytes, pkt->orig_to, pkt->addrlen) == 0)
1046 {
1047 /* This is a packet that was sent directly to the virtual dns-server
1048 *
1049 * This means we have to send this query over gnunet
1050 */
1051
1052 size_t size =
1053 sizeof (struct GNUNET_MESH_Tunnel *) +
1054 sizeof (struct GNUNET_MessageHeader) + (ntohs (message->size) -
1055 sizeof (struct query_packet) +
1056 1);
1057 struct tunnel_cls *cls_ = GNUNET_malloc (size);
1058
1059 cls_->hdr.size = size - sizeof (struct GNUNET_MESH_Tunnel *);
1060
1061 cls_->hdr.type = ntohs (GNUNET_MESSAGE_TYPE_VPN_REMOTE_QUERY_DNS);
1062 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "size: %d\n", size);
1063
1064 memcpy (&cls_->dns, dns,
1065 cls_->hdr.size - sizeof (struct GNUNET_MessageHeader));
1066 GNUNET_SCHEDULER_add_now (send_mesh_query, cls_);
1067
1068 if (ntohs (pdns->s.qdcount) == 1)
1069 {
1070 if (ntohs (pdns->queries[0]->qtype) == 1)
1071 pdns->queries[0]->qtype = htons (28);
1072 else if (ntohs (pdns->queries[0]->qtype) == 28)
1073 pdns->queries[0]->qtype = htons (1);
1074 else
1075 {
1076 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "not sending second packet\n");
1077 goto outfree;
1078 }
1079 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sending second packet\n");
1080 struct dns_pkt *rdns = unparse_dns_packet (pdns);
1081 size_t size =
1082 sizeof (struct GNUNET_MESH_Tunnel *) +
1083 sizeof (struct GNUNET_MessageHeader) + (ntohs (message->size) -
1084 sizeof (struct query_packet) +
1085 1);
1086 struct tunnel_cls *cls_ = GNUNET_malloc (size);
1087
1088 cls_->hdr.size = size - sizeof (struct GNUNET_MESH_Tunnel *);
1089
1090 cls_->hdr.type = ntohs (GNUNET_MESSAGE_TYPE_VPN_REMOTE_QUERY_DNS);
1091 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "size: %d\n", size);
1092
1093 memcpy (&cls_->dns, rdns,
1094 cls_->hdr.size - sizeof (struct GNUNET_MessageHeader));
1095 GNUNET_SCHEDULER_add_now (send_mesh_query, cls_);
1096 GNUNET_free (rdns);
1097 }
1098
1099 goto outfree;
1100 }
1101
1102
1103 /* The query should be sent to the network */
1104 if (pkt->addrlen == 4)
1105 {
1106 struct sockaddr_in dest;
1107
1108 memset (&dest, 0, sizeof dest);
1109 dest.sin_port = htons (53);
1110 memcpy (&dest.sin_addr.s_addr, pkt->orig_to, pkt->addrlen);
1111
1112 GNUNET_NETWORK_socket_sendto (dnsout, dns,
1113 ntohs (pkt->hdr.size) -
1114 sizeof (struct query_packet) + 1,
1115 (struct sockaddr *) &dest, sizeof dest);
1116 }
1117 else if (pkt->addrlen == 16)
1118 {
1119 struct sockaddr_in6 dest;
1120
1121 memset (&dest, 0, sizeof dest);
1122 dest.sin6_port = htons (53);
1123 memcpy (&dest.sin6_addr, pkt->orig_to, pkt->addrlen);
1124
1125 GNUNET_NETWORK_socket_sendto (dnsout6, dns,
1126 ntohs (pkt->hdr.size) -
1127 sizeof (struct query_packet) + 1,
1128 (struct sockaddr *) &dest, sizeof dest);
1129 }
1130
1131outfree:
1132 free_parsed_dns_packet (pdns);
1133 pdns = NULL;
1134out:
1135 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1136}
1137
1138static void
1139read_response (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
1140
1141static void
1142read_response6 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
1143
1144static int
1145open_port6 ()
1146{
1147 struct sockaddr_in6 addr;
1148
1149 dnsout6 = GNUNET_NETWORK_socket_create (AF_INET6, SOCK_DGRAM, 0);
1150 if (dnsout6 == NULL)
1151 {
1152 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not create socket: %m\n");
1153 return GNUNET_SYSERR;
1154 }
1155 memset (&addr, 0, sizeof (struct sockaddr_in6));
1156
1157 addr.sin6_family = AF_INET6;
1158 int err = GNUNET_NETWORK_socket_bind (dnsout6,
1159 (struct sockaddr *) &addr,
1160 sizeof (struct sockaddr_in6));
1161
1162 if (err != GNUNET_OK)
1163 {
1164 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not bind a port: %m\n");
1165 return GNUNET_SYSERR;
1166 }
1167
1168 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, dnsout6,
1169 &read_response6, NULL);
1170
1171 return GNUNET_YES;
1172}
1173
1174static int
1175open_port ()
1176{
1177 struct sockaddr_in addr;
1178
1179 dnsout = GNUNET_NETWORK_socket_create (AF_INET, SOCK_DGRAM, 0);
1180 if (dnsout == NULL)
1181 return GNUNET_SYSERR;
1182 memset (&addr, 0, sizeof (struct sockaddr_in));
1183
1184 addr.sin_family = AF_INET;
1185 int err = GNUNET_NETWORK_socket_bind (dnsout,
1186 (struct sockaddr *) &addr,
1187 sizeof (struct sockaddr_in));
1188
1189 if (err != GNUNET_OK)
1190 {
1191 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not bind a port: %m\n");
1192 return GNUNET_SYSERR;
1193 }
1194
1195 /* Read the port we bound to */
1196 socklen_t addrlen = sizeof (struct sockaddr_in);
1197
1198 err =
1199 getsockname (GNUNET_NETWORK_get_fd (dnsout), (struct sockaddr *) &addr,
1200 &addrlen);
1201
1202 dnsoutport = htons (addr.sin_port);
1203
1204 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Bound to port %d.\n", dnsoutport);
1205
1206 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, dnsout,
1207 &read_response, NULL);
1208
1209 return GNUNET_YES;
1210}
1211
1212void
1213handle_response (struct dns_pkt *dns, struct sockaddr *addr, socklen_t addrlen,
1214 int r);
1215
1216/**
1217 * Read a response-packet of the UDP-Socket
1218 */
1219static void
1220read_response6 (void *cls GNUNET_UNUSED,
1221 const struct GNUNET_SCHEDULER_TaskContext *tc)
1222{
1223 struct sockaddr_in6 addr;
1224 socklen_t addrlen = sizeof (addr);
1225 int r;
1226 int len;
1227
1228 if (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)
1229 return;
1230
1231 memset (&addr, 0, sizeof addr);
1232
1233#ifndef MINGW
1234 if (0 != ioctl (GNUNET_NETWORK_get_fd (dnsout6), FIONREAD, &len))
1235 {
1236 (void) open_port6 ();
1237 return;
1238 }
1239#else
1240 /* port the code above? */
1241 len = 65536;
1242#endif
1243
1244 unsigned char buf[len];
1245 struct dns_pkt *dns = (struct dns_pkt *) buf;
1246
1247 r = GNUNET_NETWORK_socket_recvfrom (dnsout, buf, sizeof (buf),
1248 (struct sockaddr *) &addr, &addrlen);
1249
1250 if (r < 0)
1251 {
1252 (void) open_port6 ();
1253 return;
1254 }
1255
1256 struct sockaddr *addr_ = GNUNET_malloc (sizeof addr);
1257
1258 memcpy (addr_, &addr, sizeof addr);
1259 handle_response (dns, addr_, 4, r);
1260
1261 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, dnsout6,
1262 &read_response6, NULL);
1263}
1264
1265/**
1266 * Read a response-packet of the UDP-Socket
1267 */
1268static void
1269read_response (void *cls GNUNET_UNUSED,
1270 const struct GNUNET_SCHEDULER_TaskContext *tc)
1271{
1272 struct sockaddr_in addr;
1273 socklen_t addrlen = sizeof (addr);
1274 int r;
1275 int len;
1276
1277 if (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)
1278 return;
1279
1280 memset (&addr, 0, sizeof addr);
1281
1282#ifndef MINGW
1283 if (0 != ioctl (GNUNET_NETWORK_get_fd (dnsout), FIONREAD, &len))
1284 {
1285 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "ioctl");
1286 unhijack (dnsoutport);
1287 if (GNUNET_YES == open_port ())
1288 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &hijack, NULL);
1289 return;
1290 }
1291#else
1292 /* port the code above? */
1293 len = 65536;
1294#endif
1295
1296 unsigned char buf[len];
1297 struct dns_pkt *dns = (struct dns_pkt *) buf;
1298
1299 r = GNUNET_NETWORK_socket_recvfrom (dnsout, buf, sizeof (buf),
1300 (struct sockaddr *) &addr, &addrlen);
1301
1302 if (r < 0)
1303 {
1304 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "recvfrom");
1305 unhijack (dnsoutport);
1306 if (GNUNET_YES == open_port ())
1307 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &hijack, NULL);
1308 return;
1309 }
1310
1311 struct sockaddr *addr_ = GNUNET_malloc (sizeof addr);
1312
1313 memcpy (addr_, &addr, sizeof addr);
1314 handle_response (dns, addr_, 4, r);
1315
1316 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, dnsout,
1317 &read_response, NULL);
1318}
1319
1320void
1321handle_response (struct dns_pkt *dns, struct sockaddr *addr, socklen_t addrlen,
1322 int r)
1323{
1324 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Answer to query %d\n",
1325 ntohs (dns->s.id));
1326
1327
1328 if (query_states[dns->s.id].valid == GNUNET_YES)
1329 {
1330 if (query_states[dns->s.id].tunnel != NULL)
1331 {
1332 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1333 "Answer to query %d for a remote peer!\n", ntohs (dns->s.id));
1334 /* This response should go through a tunnel */
1335 uint32_t *c =
1336 GNUNET_malloc (4 + sizeof (struct GNUNET_MESH_Tunnel *) + r);
1337 *c = r;
1338 struct GNUNET_MESH_Tunnel **t = (struct GNUNET_MESH_Tunnel **) (c + 1);
1339
1340 *t = query_states[dns->s.id].tunnel;
1341 memcpy (t + 1, dns, r);
1342 struct tunnel_state *s =
1343 GNUNET_MESH_tunnel_get_data (query_states[dns->s.id].tunnel);
1344 if (NULL == s->th)
1345 {
1346 s->th =
1347 GNUNET_MESH_notify_transmit_ready (query_states[dns->s.id].tunnel,
1348 GNUNET_YES, 32,
1349 GNUNET_TIME_UNIT_MINUTES, NULL,
1350 r +
1351 sizeof (struct
1352 GNUNET_MessageHeader),
1353 mesh_send_response, c);
1354 }
1355 else
1356 {
1357 struct tunnel_notify_queue *element =
1358 GNUNET_malloc (sizeof (struct tunnel_notify_queue));
1359 element->cls = c;
1360 element->len = r + sizeof (struct GNUNET_MessageHeader);
1361 element->cb = mesh_send_response;
1362
1363 GNUNET_CONTAINER_DLL_insert_tail (s->head, s->tail, element);
1364 }
1365 }
1366 else
1367 {
1368 query_states[dns->s.id].valid = GNUNET_NO;
1369
1370 size_t len = sizeof (struct answer_packet) + r - 1; /* 1 for the unsigned char data[1]; */
1371 struct answer_packet_list *answer =
1372 GNUNET_malloc (len + sizeof (struct answer_packet_list) -
1373 (sizeof (struct answer_packet)));
1374 answer->pkt.hdr.type =
1375 htons (GNUNET_MESSAGE_TYPE_VPN_DNS_LOCAL_RESPONSE_DNS);
1376 answer->pkt.hdr.size = htons (len);
1377 answer->pkt.subtype = GNUNET_DNS_ANSWER_TYPE_IP;
1378 answer->pkt.addrlen = addrlen;
1379 if (addrlen == 16)
1380 {
1381 struct sockaddr_in6 *addr_ = (struct sockaddr_in6 *) addr;
1382
1383 memcpy (answer->pkt.from, &addr_->sin6_addr, addrlen);
1384 memcpy (answer->pkt.to, query_states[dns->s.id].local_ip, addrlen);
1385 }
1386 else if (addrlen == 4)
1387 {
1388 struct sockaddr_in *addr_ = (struct sockaddr_in *) addr;
1389
1390 memcpy (answer->pkt.from, &addr_->sin_addr.s_addr, addrlen);
1391 memcpy (answer->pkt.to, query_states[dns->s.id].local_ip, addrlen);
1392 }
1393 else
1394 {
1395 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "addrlen = %d\n", addrlen);
1396 GNUNET_assert (0);
1397 }
1398 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sending answer with addrlen = %d\n",
1399 addrlen);
1400 answer->pkt.dst_port = query_states[dns->s.id].local_port;
1401 memcpy (answer->pkt.data, dns, r);
1402 answer->client = query_states[dns->s.id].client;
1403
1404 GNUNET_CONTAINER_DLL_insert_after (head, tail, tail, answer);
1405
1406 if (server_notify == NULL)
1407 server_notify =
1408 GNUNET_SERVER_notify_transmit_ready (query_states[dns->s.id].client,
1409 len,
1410 GNUNET_TIME_UNIT_FOREVER_REL,
1411 &send_answer, NULL);
1412 }
1413 }
1414 GNUNET_free (addr);
1415}
1416
1417
1418/**
1419 * Task run during shutdown.
1420 *
1421 * @param cls unused
1422 * @param tc unused
1423 */
1424static void
1425cleanup_task (void *cls GNUNET_UNUSED,
1426 const struct GNUNET_SCHEDULER_TaskContext *tc)
1427{
1428 GNUNET_assert (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN));
1429
1430 unhijack (dnsoutport);
1431 GNUNET_DHT_disconnect (dht);
1432 GNUNET_MESH_disconnect (mesh_handle);
1433}
1434
1435/**
1436 * @brief Create a port-map from udp and tcp redirects
1437 *
1438 * @param udp_redirects
1439 * @param tcp_redirects
1440 *
1441 * @return
1442 */
1443static uint64_t
1444get_port_from_redirects (const char *udp_redirects, const char *tcp_redirects)
1445{
1446 uint64_t ret = 0;
1447 char *cpy, *hostname, *redirect;
1448 int local_port;
1449 unsigned int count = 0;
1450
1451 cpy = NULL;
1452 if (NULL != udp_redirects)
1453 {
1454 cpy = GNUNET_strdup (udp_redirects);
1455 for (redirect = strtok (cpy, " "); redirect != NULL;
1456 redirect = strtok (NULL, " "))
1457 {
1458 if (NULL == (hostname = strstr (redirect, ":")))
1459 {
1460 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1461 "Warning: option %s is not formatted correctly!\n",
1462 redirect);
1463 continue;
1464 }
1465 hostname[0] = '\0';
1466 local_port = atoi (redirect);
1467 if (!((local_port > 0) && (local_port < 65536)))
1468 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1469 "Warning: %s is not a correct port.", redirect);
1470
1471 ret |= (0xFFFF & htons (local_port));
1472 ret <<= 16;
1473 count++;
1474
1475 if (count > 4)
1476 {
1477 ret = 0;
1478 goto out;
1479 }
1480 }
1481 GNUNET_free (cpy);
1482 cpy = NULL;
1483 }
1484
1485 if (NULL != tcp_redirects)
1486 {
1487 cpy = GNUNET_strdup (tcp_redirects);
1488 for (redirect = strtok (cpy, " "); redirect != NULL;
1489 redirect = strtok (NULL, " "))
1490 {
1491 if (NULL == (hostname = strstr (redirect, ":")))
1492 {
1493 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1494 "Warning: option %s is not formatted correctly!\n",
1495 redirect);
1496 continue;
1497 }
1498 hostname[0] = '\0';
1499 local_port = atoi (redirect);
1500 if (!((local_port > 0) && (local_port < 65536)))
1501 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1502 "Warning: %s is not a correct port.", redirect);
1503
1504 ret |= (0xFFFF & htons (local_port));
1505 ret <<= 16;
1506 count++;
1507
1508 if (count > 4)
1509 {
1510 ret = 0;
1511 goto out;
1512 }
1513 }
1514 GNUNET_free (cpy);
1515 cpy = NULL;
1516 }
1517
1518out:
1519 GNUNET_free_non_null (cpy);
1520 return ret;
1521}
1522
1523static void
1524publish_name (const char *name, uint64_t ports, uint32_t service_type,
1525 struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key)
1526{
1527 size_t size = sizeof (struct GNUNET_DNS_Record);
1528 struct GNUNET_DNS_Record data;
1529
1530 memset (&data, 0, size);
1531
1532 data.purpose.size = htonl (size - sizeof (struct GNUNET_CRYPTO_RsaSignature));
1533 data.purpose.purpose = GNUNET_SIGNATURE_PURPOSE_DNS_RECORD;
1534
1535 GNUNET_CRYPTO_hash (name, strlen (name) + 1, &data.service_descriptor);
1536 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Store with key1 %x\n",
1537 *((unsigned long long *) &data.service_descriptor));
1538
1539 data.service_type = service_type;
1540 data.ports = ports;
1541
1542 GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &data.peer);
1543
1544 data.expiration_time =
1545 GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute
1546 (GNUNET_TIME_relative_multiply
1547 (GNUNET_TIME_UNIT_HOURS, 2)));
1548
1549 /* Sign the block */
1550 if (GNUNET_OK !=
1551 GNUNET_CRYPTO_rsa_sign (my_private_key, &data.purpose, &data.signature))
1552 {
1553 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "could not sign DNS_Record\n");
1554 return;
1555 }
1556
1557 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Putting with key %08x, size = %d\n",
1558 *((unsigned int *) &data.service_descriptor), size);
1559
1560 GNUNET_DHT_put (dht, &data.service_descriptor,
1561 5 /* DEFAULT_PUT_REPLICATION */ ,
1562 GNUNET_DHT_RO_NONE, GNUNET_BLOCK_TYPE_DNS, size,
1563 (char *) &data,
1564 GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS),
1565 GNUNET_TIME_UNIT_MINUTES, NULL, NULL);
1566}
1567
1568
1569/**
1570 * @brief Publishes the record defined by the section section
1571 *
1572 * @param cls closure
1573 * @param section the current section
1574 */
1575static void
1576publish_iterate (void *cls GNUNET_UNUSED, const char *section)
1577{
1578 char *udp_redirects;
1579 char *tcp_redirects;
1580 char *alternative_names;
1581 char *alternative_name;
1582 char *keyfile;
1583
1584 if ((strlen (section) < 8) ||
1585 (0 != strcmp (".gnunet.", section + (strlen (section) - 8))))
1586 return;
1587 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Parsing dns-name %s\n", section);
1588 if (GNUNET_OK !=
1589 GNUNET_CONFIGURATION_get_value_string (cfg, section, "UDP_REDIRECTS",
1590 &udp_redirects))
1591 udp_redirects = NULL;
1592 if (GNUNET_OK !=
1593 GNUNET_CONFIGURATION_get_value_string (cfg, section, "TCP_REDIRECTS",
1594 &tcp_redirects))
1595 tcp_redirects = NULL;
1596
1597 if (GNUNET_OK !=
1598 GNUNET_CONFIGURATION_get_value_filename (cfg, "GNUNETD", "HOSTKEY",
1599 &keyfile))
1600 {
1601 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "could not read keyfile-value\n");
1602 if (keyfile != NULL)
1603 GNUNET_free (keyfile);
1604 return;
1605 }
1606
1607 struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key =
1608 GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
1609 GNUNET_free (keyfile);
1610 GNUNET_assert (my_private_key != NULL);
1611
1612 uint64_t ports = get_port_from_redirects (udp_redirects, tcp_redirects);
1613 uint32_t service_type = 0;
1614
1615 if (NULL != udp_redirects)
1616 service_type = GNUNET_DNS_SERVICE_TYPE_UDP;
1617
1618 if (NULL != tcp_redirects)
1619 service_type |= GNUNET_DNS_SERVICE_TYPE_TCP;
1620
1621 service_type = htonl (service_type);
1622
1623
1624 publish_name (section, ports, service_type, my_private_key);
1625 if (GNUNET_OK ==
1626 GNUNET_CONFIGURATION_get_value_string (cfg, section, "ALTERNATIVE_NAMES",
1627 &alternative_names))
1628 {
1629 for (alternative_name = strtok (alternative_names, " ");
1630 alternative_name != NULL; alternative_name = strtok (NULL, " "))
1631 {
1632 char *altname =
1633 alloca (strlen (alternative_name) + strlen (section) + 1 + 1);
1634 strcpy (altname, alternative_name);
1635 strcpy (altname + strlen (alternative_name) + 1, section);
1636 altname[strlen (alternative_name)] = '.';
1637
1638 publish_name (altname, ports, service_type, my_private_key);
1639 }
1640 GNUNET_free (alternative_names);
1641 }
1642 GNUNET_CRYPTO_rsa_key_free (my_private_key);
1643 GNUNET_free_non_null (udp_redirects);
1644 GNUNET_free_non_null (tcp_redirects);
1645}
1646
1647/**
1648 * Publish a DNS-record in the DHT.
1649 */
1650static void
1651publish_names (void *cls GNUNET_UNUSED,
1652 const struct GNUNET_SCHEDULER_TaskContext *tc)
1653{
1654 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1655 return;
1656
1657 GNUNET_CONFIGURATION_iterate_sections (cfg, &publish_iterate, NULL);
1658
1659 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_HOURS, &publish_names, NULL);
1660}
1661
1662/**
1663 * @param cls closure
1664 * @param server the initialized server
1665 * @param cfg_ configuration to use
1666 */
1667static void
1668run (void *cls, struct GNUNET_SERVER_Handle *server,
1669 const struct GNUNET_CONFIGURATION_Handle *cfg_)
1670{
1671 static const struct GNUNET_SERVER_MessageHandler handlers[] = {
1672 /* callback, cls, type, size */
1673 {&receive_query, NULL, GNUNET_MESSAGE_TYPE_VPN_DNS_LOCAL_QUERY_DNS, 0},
1674 {&rehijack, NULL, GNUNET_MESSAGE_TYPE_REHIJACK,
1675 sizeof (struct GNUNET_MessageHeader)},
1676 {NULL, NULL, 0, 0}
1677 };
1678
1679 static const struct GNUNET_MESH_MessageHandler mesh_handlers[] = {
1680 {receive_mesh_query, GNUNET_MESSAGE_TYPE_VPN_REMOTE_QUERY_DNS, 0},
1681 {receive_mesh_answer, GNUNET_MESSAGE_TYPE_VPN_REMOTE_ANSWER_DNS, 0},
1682 {NULL, 0, 0}
1683 };
1684
1685 static GNUNET_MESH_ApplicationType apptypes[] = {
1686 GNUNET_APPLICATION_TYPE_END,
1687 GNUNET_APPLICATION_TYPE_END
1688 };
1689
1690 if (GNUNET_YES != open_port6 ())
1691 {
1692 GNUNET_SCHEDULER_shutdown ();
1693 return;
1694 }
1695
1696 if (GNUNET_YES != open_port ())
1697 {
1698 GNUNET_SCHEDULER_shutdown ();
1699 return;
1700 }
1701
1702 if (GNUNET_YES ==
1703 GNUNET_CONFIGURATION_get_value_yesno (cfg_, "dns", "PROVIDE_EXIT"))
1704 apptypes[0] = GNUNET_APPLICATION_TYPE_INTERNET_RESOLVER;
1705 mesh_handle =
1706 GNUNET_MESH_connect (cfg_, 42, NULL, new_tunnel, clean_tunnel,
1707 mesh_handlers, apptypes);
1708
1709 cfg = cfg_;
1710 dht = GNUNET_DHT_connect (cfg, 1024);
1711 GNUNET_SCHEDULER_add_now (publish_names, NULL);
1712 GNUNET_SERVER_add_handlers (server, handlers);
1713 GNUNET_SERVER_disconnect_notify (server, &client_disconnect, NULL);
1714 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
1715 cls);
1716}
1717
1718/**
1719 * The main function for the dns service.
1720 *
1721 * @param argc number of arguments from the command line
1722 * @param argv command line arguments
1723 * @return 0 ok, 1 on error
1724 */
1725int
1726main (int argc, char *const *argv)
1727{
1728 return (GNUNET_OK ==
1729 GNUNET_SERVICE_run (argc, argv, "dns", GNUNET_SERVICE_OPTION_NONE,
1730 &run, NULL)) ? 0 : 1;
1731}
diff --git a/src/vpn/gnunet-vpn-packet.h b/src/vpn/gnunet-vpn-packet.h
index 19b2c8d7b..ddbfba730 100644
--- a/src/vpn/gnunet-vpn-packet.h
+++ b/src/vpn/gnunet-vpn-packet.h
@@ -3,7 +3,7 @@
3 3
4#include "platform.h" 4#include "platform.h"
5#include "gnunet_common.h" 5#include "gnunet_common.h"
6#include "gnunet-dns-parser.h" 6#include "gnunet_dnsparser_lib.h"
7 7
8GNUNET_NETWORK_STRUCT_BEGIN 8GNUNET_NETWORK_STRUCT_BEGIN
9 9