diff options
Diffstat (limited to 'src/vpn')
-rw-r--r-- | src/vpn/Makefile.am | 21 | ||||
-rw-r--r-- | src/vpn/gnunet-daemon-vpn-dns.c | 1 | ||||
-rw-r--r-- | src/vpn/gnunet-daemon-vpn-helper.c | 1 | ||||
-rw-r--r-- | src/vpn/gnunet-daemon-vpn.h | 2 | ||||
-rw-r--r-- | src/vpn/gnunet-dns-parser.c | 301 | ||||
-rw-r--r-- | src/vpn/gnunet-dns-parser.h | 95 | ||||
-rw-r--r-- | src/vpn/gnunet-helper-hijack-dns.c | 156 | ||||
-rw-r--r-- | src/vpn/gnunet-service-dns-p.h | 116 | ||||
-rw-r--r-- | src/vpn/gnunet-service-dns.c | 1731 | ||||
-rw-r--r-- | src/vpn/gnunet-vpn-packet.h | 2 |
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 | ||
18 | if LINUX | 18 | if LINUX |
19 | VPNBIN = gnunet-helper-vpn | 19 | VPNBIN = gnunet-helper-vpn |
20 | HIJACKBIN = gnunet-helper-hijack-dns | ||
21 | install-exec-hook: | 20 | install-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 | ||
26 | else | 23 | else |
27 | install-exec-hook: | 24 | install-exec-hook: |
28 | endif | 25 | endif |
29 | 26 | ||
30 | 27 | ||
31 | bin_PROGRAMS = \ | 28 | bin_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 | ||
35 | gnunet_helper_vpn_SOURCES = \ | 32 | gnunet_helper_vpn_SOURCES = \ |
36 | gnunet-helper-vpn.c | 33 | gnunet-helper-vpn.c |
37 | 34 | ||
38 | gnunet_helper_hijack_dns_SOURCES = \ | ||
39 | gnunet-helper-hijack-dns.c | ||
40 | |||
41 | gnunet_daemon_vpn_SOURCES = \ | 35 | gnunet_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 | |||
55 | gnunet_service_dns_SOURCES = \ | ||
56 | gnunet-service-dns.c gnunet-service-dns-p.h \ | ||
57 | gnunet-dns-parser.c gnunet-dns-parser.h | ||
58 | gnunet_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 | ||
66 | gnunet_daemon_exit_SOURCES = \ | 49 | gnunet_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 | ||
42 | struct query_packet_list *head; | 41 | struct 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 | */ | ||
13 | static unsigned int | ||
14 | parse_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 | */ | ||
52 | static unsigned short | ||
53 | parse_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 | */ | ||
92 | struct dns_pkt_parsed * | ||
93 | parse_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 | |||
138 | static void | ||
139 | unparse_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 | |||
163 | struct dns_pkt * | ||
164 | unparse_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 | |||
263 | void | ||
264 | free_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 | ||
8 | GNUNET_NETWORK_STRUCT_BEGIN | ||
9 | |||
10 | struct 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 | }; | ||
34 | GNUNET_NETWORK_STRUCT_END | ||
35 | |||
36 | struct dns_pkt | ||
37 | { | ||
38 | struct dns_static s; | ||
39 | unsigned char data[1]; | ||
40 | }; | ||
41 | |||
42 | struct 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 | |||
51 | struct dns_query_line | ||
52 | { | ||
53 | unsigned short type; | ||
54 | unsigned short class; | ||
55 | }; | ||
56 | |||
57 | struct dns_query | ||
58 | { | ||
59 | char *name; | ||
60 | unsigned char namelen; | ||
61 | unsigned short qtype; | ||
62 | unsigned short qclass; | ||
63 | }; | ||
64 | |||
65 | struct 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 | |||
74 | struct 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 | |||
86 | struct dns_pkt_parsed * | ||
87 | parse_dns_packet (struct dns_pkt *pkt); | ||
88 | |||
89 | struct dns_pkt * | ||
90 | unparse_dns_packet (struct dns_pkt_parsed *pkt); | ||
91 | |||
92 | void | ||
93 | free_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 | |||
30 | static int | ||
31 | fork_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 | |||
54 | int | ||
55 | main (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 | { | ||
102 | e4: | ||
103 | r = fork_and_exec ("/sbin/ip", (char *[]) | ||
104 | { | ||
105 | "ip", "route", "del", "default", "via", virt_dns, | ||
106 | "table", "2", NULL}); | ||
107 | e3: | ||
108 | r = fork_and_exec ("/sbin/ip", (char *[]) | ||
109 | { | ||
110 | "ip", "rule", "del", "fwmark", "3", "table", "2", NULL}); | ||
111 | e2: | ||
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}); | ||
116 | e1: | ||
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 | |||
6 | GNUNET_NETWORK_STRUCT_BEGIN | ||
7 | |||
8 | struct 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 | |||
29 | struct 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 | |||
36 | enum 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 | |||
68 | struct 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 | |||
76 | struct 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 | |||
107 | struct 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 | }; | ||
114 | GNUNET_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 | |||
45 | struct GNUNET_MESH_Handle *mesh_handle; | ||
46 | |||
47 | struct 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 | */ | ||
53 | static struct GNUNET_NETWORK_Handle *dnsout; | ||
54 | static struct GNUNET_NETWORK_Handle *dnsout6; | ||
55 | |||
56 | /** | ||
57 | * The port bound to the socket dnsout | ||
58 | */ | ||
59 | static unsigned short dnsoutport; | ||
60 | |||
61 | /** | ||
62 | * A handle to the DHT-Service | ||
63 | */ | ||
64 | static struct GNUNET_DHT_Handle *dht; | ||
65 | |||
66 | /** | ||
67 | * The configuration to use | ||
68 | */ | ||
69 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
70 | |||
71 | /** | ||
72 | * A list of DNS-Responses that have to be sent to the requesting client | ||
73 | */ | ||
74 | static struct answer_packet_list *head; | ||
75 | |||
76 | /** | ||
77 | * The tail of the list of DNS-responses | ||
78 | */ | ||
79 | static 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 | */ | ||
90 | static 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 | */ | ||
108 | struct receive_dht_cls | ||
109 | { | ||
110 | uint16_t id; | ||
111 | struct GNUNET_DHT_GetHandle *handle; | ||
112 | }; | ||
113 | |||
114 | struct 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 | |||
123 | struct tunnel_state | ||
124 | { | ||
125 | struct tunnel_notify_queue *head, *tail; | ||
126 | struct GNUNET_MESH_TransmitHandle *th; | ||
127 | }; | ||
128 | |||
129 | static size_t | ||
130 | send_answer (void *cls, size_t size, void *buf); | ||
131 | |||
132 | static void | ||
133 | client_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 | */ | ||
169 | static void | ||
170 | hijack (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 | |||
208 | static void * | ||
209 | new_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 | |||
221 | static void | ||
222 | clean_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 | */ | ||
231 | static void | ||
232 | unhijack (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 | */ | ||
264 | static size_t | ||
265 | send_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 | |||
290 | GNUNET_NETWORK_STRUCT_BEGIN | ||
291 | |||
292 | struct tunnel_cls | ||
293 | { | ||
294 | struct GNUNET_MESH_Tunnel *tunnel GNUNET_PACKED; | ||
295 | struct GNUNET_MessageHeader hdr; | ||
296 | struct dns_pkt dns; | ||
297 | }; | ||
298 | GNUNET_NETWORK_STRUCT_END | ||
299 | |||
300 | struct tunnel_cls *remote_pending[UINT16_MAX]; | ||
301 | |||
302 | static size_t | ||
303 | mesh_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 | |||
347 | static size_t | ||
348 | mesh_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 | |||
386 | void | ||
387 | mesh_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 | |||
424 | static void | ||
425 | send_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 | |||
447 | static int | ||
448 | receive_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 | |||
496 | static int | ||
497 | receive_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 | |||
651 | static void | ||
652 | send_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 | */ | ||
742 | static void | ||
743 | receive_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 | */ | ||
858 | static void | ||
859 | rehijack (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 | */ | ||
871 | static void | ||
872 | receive_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 | |||
1131 | outfree: | ||
1132 | free_parsed_dns_packet (pdns); | ||
1133 | pdns = NULL; | ||
1134 | out: | ||
1135 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
1136 | } | ||
1137 | |||
1138 | static void | ||
1139 | read_response (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | ||
1140 | |||
1141 | static void | ||
1142 | read_response6 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | ||
1143 | |||
1144 | static int | ||
1145 | open_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 | |||
1174 | static int | ||
1175 | open_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 | |||
1212 | void | ||
1213 | handle_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 | */ | ||
1219 | static void | ||
1220 | read_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 | */ | ||
1268 | static void | ||
1269 | read_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 | |||
1320 | void | ||
1321 | handle_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 | */ | ||
1424 | static void | ||
1425 | cleanup_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 | */ | ||
1443 | static uint64_t | ||
1444 | get_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 | |||
1518 | out: | ||
1519 | GNUNET_free_non_null (cpy); | ||
1520 | return ret; | ||
1521 | } | ||
1522 | |||
1523 | static void | ||
1524 | publish_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 | */ | ||
1575 | static void | ||
1576 | publish_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 | */ | ||
1650 | static void | ||
1651 | publish_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 | */ | ||
1667 | static void | ||
1668 | run (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 | */ | ||
1725 | int | ||
1726 | main (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 | ||
8 | GNUNET_NETWORK_STRUCT_BEGIN | 8 | GNUNET_NETWORK_STRUCT_BEGIN |
9 | 9 | ||