diff options
author | Philipp Tölke <toelke@in.tum.de> | 2010-11-02 21:40:02 +0000 |
---|---|---|
committer | Philipp Tölke <toelke@in.tum.de> | 2010-11-02 21:40:02 +0000 |
commit | b6ce573cb682686d40f7996247bd6efbd1e8f1d4 (patch) | |
tree | 0f2ce938ae07e81298f2d360404f2f023e938665 | |
parent | 11c2830064ec60af2b84a9b7f885b2f9d31a1b0d (diff) | |
download | gnunet-b6ce573cb682686d40f7996247bd6efbd1e8f1d4.tar.gz gnunet-b6ce573cb682686d40f7996247bd6efbd1e8f1d4.zip |
comment and indent gnunet-daemon-vpn
-rw-r--r-- | src/vpn/gnunet-daemon-vpn.c | 587 |
1 files changed, 340 insertions, 247 deletions
diff --git a/src/vpn/gnunet-daemon-vpn.c b/src/vpn/gnunet-daemon-vpn.c index e84600e4a..f231ed782 100644 --- a/src/vpn/gnunet-daemon-vpn.c +++ b/src/vpn/gnunet-daemon-vpn.c | |||
@@ -119,245 +119,336 @@ static struct answer_packet_list *answer_proc_head; | |||
119 | */ | 119 | */ |
120 | static struct answer_packet_list *answer_proc_tail; | 120 | static struct answer_packet_list *answer_proc_tail; |
121 | 121 | ||
122 | size_t send_query(void* cls, size_t size, void* buf); | ||
123 | |||
124 | static void cleanup(void* cls, const struct GNUNET_SCHEDULER_TaskContext* tskctx) { | ||
125 | GNUNET_assert (0 != (tskctx->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)); | ||
126 | PLIBC_KILL(helper_pid, SIGTERM); | ||
127 | GNUNET_OS_process_wait(helper_pid); | ||
128 | if (dns_connection != NULL) | ||
129 | { | ||
130 | GNUNET_CLIENT_disconnect (dns_connection, GNUNET_NO); | ||
131 | dns_connection = NULL; | ||
132 | } | ||
133 | } | ||
134 | |||
135 | static void helper_read(void* cls, const struct GNUNET_SCHEDULER_TaskContext* tsdkctx); | 122 | static void helper_read(void* cls, const struct GNUNET_SCHEDULER_TaskContext* tsdkctx); |
123 | static void dns_answer_handler(void* cls, const struct GNUNET_MessageHeader *msg); | ||
136 | 124 | ||
137 | static void start_helper_and_schedule(void *cls, | 125 | /** |
138 | const struct GNUNET_SCHEDULER_TaskContext *tc) { | 126 | * Callback called by notify_transmit_ready; sends dns-queries or rehijack-messages |
139 | 127 | * to the service-dns | |
140 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | 128 | */ |
141 | return; | 129 | static size_t |
130 | send_query(void* cls, size_t size, void* buf) { | ||
131 | size_t len; | ||
132 | /* | ||
133 | * Send the rehijack-message | ||
134 | */ | ||
135 | if (restart_hijack == 1) | ||
136 | { | ||
137 | restart_hijack = 0; | ||
138 | /* | ||
139 | * The message is just a header | ||
140 | */ | ||
141 | GNUNET_assert(sizeof(struct GNUNET_MessageHeader) >= size); | ||
142 | struct GNUNET_MessageHeader* hdr = buf; | ||
143 | len = sizeof(struct GNUNET_MessageHeader); | ||
144 | hdr->size = htons(len); | ||
145 | hdr->type = htons(GNUNET_MESSAGE_TYPE_REHIJACK); | ||
146 | } | ||
147 | else | ||
148 | { | ||
149 | struct query_packet_list* query = head; | ||
150 | len = ntohs(query->pkt.hdr.size); | ||
142 | 151 | ||
143 | helper_in = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO); | 152 | GNUNET_assert(len <= size); |
144 | helper_out = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_NO, GNUNET_YES); | ||
145 | 153 | ||
146 | if (helper_in == NULL || helper_out == NULL) return; | 154 | memcpy(buf, &query->pkt.hdr, len); |
147 | 155 | ||
148 | helper_pid = GNUNET_OS_start_process(helper_in, helper_out, "gnunet-helper-vpn", "gnunet-helper-vpn", NULL); | 156 | GNUNET_CONTAINER_DLL_remove (head, tail, query); |
149 | 157 | ||
150 | fh_from_helper = GNUNET_DISK_pipe_handle (helper_out, GNUNET_DISK_PIPE_END_READ); | 158 | GNUNET_free(query); |
151 | fh_to_helper = GNUNET_DISK_pipe_handle (helper_in, GNUNET_DISK_PIPE_END_WRITE); | 159 | } |
152 | 160 | ||
153 | GNUNET_DISK_pipe_close_end(helper_out, GNUNET_DISK_PIPE_END_WRITE); | 161 | /* |
154 | GNUNET_DISK_pipe_close_end(helper_in, GNUNET_DISK_PIPE_END_READ); | 162 | * Check whether more data is to be sent |
163 | */ | ||
164 | if (head != NULL || restart_hijack == 1) | ||
165 | { | ||
166 | GNUNET_CLIENT_notify_transmit_ready(dns_connection, ntohs(head->pkt.hdr.size), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, &send_query, NULL); | ||
167 | } | ||
155 | 168 | ||
156 | GNUNET_SCHEDULER_add_read_file (sched, GNUNET_TIME_UNIT_FOREVER_REL, fh_from_helper, &helper_read, NULL); | 169 | return len; |
157 | } | 170 | } |
158 | 171 | ||
172 | /** | ||
173 | * Function scheduled as very last function, cleans up after us | ||
174 | */ | ||
175 | static void | ||
176 | cleanup(void* cls, const struct GNUNET_SCHEDULER_TaskContext* tskctx) { | ||
177 | GNUNET_assert (0 != (tskctx->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)); | ||
159 | 178 | ||
160 | static void restart_helper(void* cls, const struct GNUNET_SCHEDULER_TaskContext* tskctx) { | 179 | /* stop the helper */ |
161 | // Kill the helper | 180 | PLIBC_KILL(helper_pid, SIGTERM); |
162 | PLIBC_KILL(helper_pid, SIGKILL); | 181 | GNUNET_OS_process_wait(helper_pid); |
163 | GNUNET_OS_process_wait(helper_pid); | ||
164 | |||
165 | /* Tell the dns-service to rehijack the dns-port | ||
166 | * The routing-table gets flushed if an interface disappears. | ||
167 | */ | ||
168 | restart_hijack = 1; | ||
169 | GNUNET_CLIENT_notify_transmit_ready(dns_connection, sizeof(struct GNUNET_MessageHeader), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, &send_query, NULL); | ||
170 | |||
171 | GNUNET_DISK_pipe_close(helper_in); | ||
172 | GNUNET_DISK_pipe_close(helper_out); | ||
173 | |||
174 | // Restart the helper | ||
175 | GNUNET_SCHEDULER_add_delayed (sched, GNUNET_TIME_UNIT_SECONDS, start_helper_and_schedule, NULL); | ||
176 | 182 | ||
183 | /* close the connection to the service-dns */ | ||
184 | if (dns_connection != NULL) | ||
185 | { | ||
186 | GNUNET_CLIENT_disconnect (dns_connection, GNUNET_NO); | ||
187 | dns_connection = NULL; | ||
188 | } | ||
177 | } | 189 | } |
178 | 190 | ||
179 | static void helper_read(void* cls, const struct GNUNET_SCHEDULER_TaskContext* tsdkctx) { | 191 | /** |
180 | char buf[65535]; | 192 | * Start the helper-process |
181 | 193 | */ | |
182 | if (tsdkctx->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) | 194 | static void |
183 | return; | 195 | start_helper_and_schedule(void *cls, |
196 | const struct GNUNET_SCHEDULER_TaskContext *tc) { | ||
197 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | ||
198 | return; | ||
184 | 199 | ||
185 | int t = GNUNET_DISK_file_read(fh_from_helper, &buf, 65535); | 200 | helper_in = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO); |
186 | if (t<=0) { | 201 | helper_out = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_NO, GNUNET_YES); |
187 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Read error for header from vpn-helper: %m\n"); | ||
188 | GNUNET_SCHEDULER_add_now(sched, restart_helper, cls); | ||
189 | return; | ||
190 | } | ||
191 | 202 | ||
192 | /* FIXME */ GNUNET_SERVER_mst_receive(mst, NULL, buf, t, 0, 0); | 203 | if (helper_in == NULL || helper_out == NULL) return; |
193 | 204 | ||
194 | GNUNET_SCHEDULER_add_read_file (sched, GNUNET_TIME_UNIT_FOREVER_REL, fh_from_helper, &helper_read, NULL); | 205 | helper_pid = GNUNET_OS_start_process(helper_in, helper_out, "gnunet-helper-vpn", "gnunet-helper-vpn", NULL); |
195 | } | ||
196 | 206 | ||
197 | static uint16_t calculate_ip_checksum(uint16_t* hdr, short len) { | 207 | fh_from_helper = GNUNET_DISK_pipe_handle (helper_out, GNUNET_DISK_PIPE_END_READ); |
198 | uint32_t sum = 0; | 208 | fh_to_helper = GNUNET_DISK_pipe_handle (helper_in, GNUNET_DISK_PIPE_END_WRITE); |
199 | for(; len >= 2; len -= 2) | ||
200 | sum += *(hdr++); | ||
201 | if (len == 1) | ||
202 | sum += *((unsigned char*)hdr); | ||
203 | 209 | ||
204 | sum = (sum >> 16) + (sum & 0xFFFF); | 210 | GNUNET_DISK_pipe_close_end(helper_out, GNUNET_DISK_PIPE_END_WRITE); |
211 | GNUNET_DISK_pipe_close_end(helper_in, GNUNET_DISK_PIPE_END_READ); | ||
205 | 212 | ||
206 | return ~sum; | 213 | GNUNET_SCHEDULER_add_read_file (sched, GNUNET_TIME_UNIT_FOREVER_REL, fh_from_helper, &helper_read, NULL); |
207 | } | 214 | } |
208 | 215 | ||
209 | static void helper_write(void* cls, const struct GNUNET_SCHEDULER_TaskContext* tsdkctx) { | 216 | /** |
210 | if (tsdkctx->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) | 217 | * Restart the helper-process |
211 | return; | 218 | */ |
212 | struct answer_packet_list* ans = answer_proc_head; | 219 | static void |
213 | size_t len = ntohs(ans->pkt.hdr.size); | 220 | restart_helper(void* cls, const struct GNUNET_SCHEDULER_TaskContext* tskctx) { |
214 | 221 | // Kill the helper | |
215 | GNUNET_assert(ans->pkt.subtype == GNUNET_DNS_ANSWER_TYPE_IP); | 222 | PLIBC_KILL(helper_pid, SIGKILL); |
216 | 223 | GNUNET_OS_process_wait(helper_pid); | |
217 | size_t data_len = len - sizeof(struct answer_packet) + 1; | 224 | |
218 | size_t net_len = sizeof(struct ip_hdr) + sizeof(struct udp_dns) + data_len; | 225 | /* Tell the dns-service to rehijack the dns-port |
219 | size_t pkt_len = sizeof(struct GNUNET_MessageHeader) + sizeof(struct pkt_tun) + net_len; | 226 | * The routing-table gets flushed if an interface disappears. |
220 | 227 | */ | |
221 | struct ip_udp_dns* pkt = alloca(pkt_len); | 228 | restart_hijack = 1; |
222 | memset(pkt, 0, pkt_len); | 229 | GNUNET_CLIENT_notify_transmit_ready(dns_connection, sizeof(struct GNUNET_MessageHeader), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, &send_query, NULL); |
223 | 230 | ||
224 | pkt->shdr.size = htons(pkt_len); | 231 | GNUNET_DISK_pipe_close(helper_in); |
225 | pkt->shdr.type = htons(GNUNET_MESSAGE_TYPE_VPN_HELPER); | 232 | GNUNET_DISK_pipe_close(helper_out); |
226 | 233 | ||
227 | pkt->tun.flags = 0; | 234 | /* Restart the helper */ |
228 | pkt->tun.type = htons(0x0800); | 235 | GNUNET_SCHEDULER_add_delayed (sched, GNUNET_TIME_UNIT_SECONDS, start_helper_and_schedule, NULL); |
236 | } | ||
229 | 237 | ||
230 | pkt->ip_hdr.version = 4; | 238 | /** |
231 | pkt->ip_hdr.hdr_lngth = 5; | 239 | * Read from the helper-process |
232 | pkt->ip_hdr.diff_serv = 0; | 240 | */ |
233 | pkt->ip_hdr.tot_lngth = htons(net_len); | 241 | static void |
234 | pkt->ip_hdr.ident = 0; | 242 | helper_read(void* cls, const struct GNUNET_SCHEDULER_TaskContext* tsdkctx) { |
235 | pkt->ip_hdr.flags = 0; | 243 | /* no message can be bigger then 64k */ |
236 | pkt->ip_hdr.frag_off = 0; | 244 | char buf[65535]; |
237 | pkt->ip_hdr.ttl = 255; | ||
238 | pkt->ip_hdr.proto = 0x11; /* UDP */ | ||
239 | pkt->ip_hdr.chks = 0; /* Will be calculated later*/ | ||
240 | pkt->ip_hdr.sadr = ans->pkt.from; | ||
241 | pkt->ip_hdr.dadr = ans->pkt.to; | ||
242 | 245 | ||
243 | pkt->ip_hdr.chks = calculate_ip_checksum((uint16_t*)&pkt->ip_hdr, 5*4); | 246 | if (tsdkctx->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) |
247 | return; | ||
244 | 248 | ||
245 | pkt->udp_dns.udp_hdr.spt = htons(53); | 249 | int t = GNUNET_DISK_file_read(fh_from_helper, &buf, 65535); |
246 | pkt->udp_dns.udp_hdr.dpt = ans->pkt.dst_port; | ||
247 | pkt->udp_dns.udp_hdr.len = htons(net_len - sizeof(struct ip_hdr)); | ||
248 | pkt->udp_dns.udp_hdr.crc = 0; /* Optional for IPv4 */ | ||
249 | 250 | ||
250 | memcpy(&pkt->udp_dns.data, ans->pkt.data, data_len); | 251 | /* On read-error, restart the helper */ |
251 | 252 | if (t<=0) { | |
252 | GNUNET_CONTAINER_DLL_remove (answer_proc_head, answer_proc_tail, ans); | 253 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Read error for header from vpn-helper: %m\n"); |
253 | GNUNET_free(ans); | 254 | GNUNET_SCHEDULER_add_now(sched, restart_helper, cls); |
255 | return; | ||
256 | } | ||
254 | 257 | ||
255 | /* FIXME */ GNUNET_DISK_file_write(fh_to_helper, pkt, pkt_len); | 258 | /* FIXME */ GNUNET_SERVER_mst_receive(mst, NULL, buf, t, 0, 0); |
256 | 259 | ||
257 | if (answer_proc_head != NULL) | 260 | GNUNET_SCHEDULER_add_read_file (sched, GNUNET_TIME_UNIT_FOREVER_REL, fh_from_helper, &helper_read, NULL); |
258 | GNUNET_SCHEDULER_add_write_file (sched, GNUNET_TIME_UNIT_FOREVER_REL, fh_to_helper, &helper_write, NULL); | ||
259 | } | 261 | } |
260 | 262 | ||
261 | size_t send_query(void* cls, size_t size, void* buf) | 263 | /** |
262 | { | 264 | * Calculate the checksum of an IPv4-Header |
263 | size_t len; | 265 | */ |
264 | if (restart_hijack == 1) | 266 | static uint16_t |
265 | { | 267 | calculate_ip_checksum(uint16_t* hdr, short len) { |
266 | restart_hijack = 0; | 268 | uint32_t sum = 0; |
267 | GNUNET_assert(sizeof(struct GNUNET_MessageHeader) >= size); | 269 | for(; len >= 2; len -= 2) |
268 | struct GNUNET_MessageHeader* hdr = buf; | 270 | sum += *(hdr++); |
269 | len = sizeof(struct GNUNET_MessageHeader); | 271 | if (len == 1) |
270 | hdr->size = htons(len); | 272 | sum += *((unsigned char*)hdr); |
271 | hdr->type = htons(GNUNET_MESSAGE_TYPE_REHIJACK); | ||
272 | } | ||
273 | else | ||
274 | { | ||
275 | struct query_packet_list* query = head; | ||
276 | len = ntohs(query->pkt.hdr.size); | ||
277 | |||
278 | GNUNET_assert(len <= size); | ||
279 | |||
280 | memcpy(buf, &query->pkt.hdr, len); | ||
281 | 273 | ||
282 | GNUNET_CONTAINER_DLL_remove (head, tail, query); | 274 | sum = (sum >> 16) + (sum & 0xFFFF); |
283 | 275 | ||
284 | GNUNET_free(query); | 276 | return ~sum; |
285 | } | 277 | } |
286 | 278 | ||
287 | if (head != NULL || restart_hijack == 1) { | 279 | /** |
288 | GNUNET_CLIENT_notify_transmit_ready(dns_connection, ntohs(head->pkt.hdr.size), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, &send_query, NULL); | 280 | * Send an dns-answer-packet to the helper |
289 | } | 281 | */ |
282 | static void | ||
283 | helper_write(void* cls, const struct GNUNET_SCHEDULER_TaskContext* tsdkctx) { | ||
284 | if (tsdkctx->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) | ||
285 | return; | ||
290 | 286 | ||
291 | return len; | 287 | struct answer_packet_list* ans = answer_proc_head; |
288 | size_t len = ntohs(ans->pkt.hdr.size); | ||
289 | |||
290 | GNUNET_assert(ans->pkt.subtype == GNUNET_DNS_ANSWER_TYPE_IP); | ||
291 | |||
292 | size_t data_len = len - sizeof(struct answer_packet) + 1; | ||
293 | size_t net_len = sizeof(struct ip_hdr) + sizeof(struct udp_dns) + data_len; | ||
294 | size_t pkt_len = sizeof(struct GNUNET_MessageHeader) + sizeof(struct pkt_tun) + net_len; | ||
295 | |||
296 | struct ip_udp_dns* pkt = alloca(pkt_len); | ||
297 | memset(pkt, 0, pkt_len); | ||
298 | |||
299 | /* set the gnunet-header */ | ||
300 | pkt->shdr.size = htons(pkt_len); | ||
301 | pkt->shdr.type = htons(GNUNET_MESSAGE_TYPE_VPN_HELPER); | ||
302 | |||
303 | /* set the tun-header (no flags and ethertype of IPv4) */ | ||
304 | pkt->tun.flags = 0; | ||
305 | pkt->tun.type = htons(0x0800); | ||
306 | |||
307 | /* set the ip-header */ | ||
308 | pkt->ip_hdr.version = 4; | ||
309 | pkt->ip_hdr.hdr_lngth = 5; | ||
310 | pkt->ip_hdr.diff_serv = 0; | ||
311 | pkt->ip_hdr.tot_lngth = htons(net_len); | ||
312 | pkt->ip_hdr.ident = 0; | ||
313 | pkt->ip_hdr.flags = 0; | ||
314 | pkt->ip_hdr.frag_off = 0; | ||
315 | pkt->ip_hdr.ttl = 255; | ||
316 | pkt->ip_hdr.proto = 0x11; /* UDP */ | ||
317 | pkt->ip_hdr.chks = 0; /* Will be calculated later*/ | ||
318 | pkt->ip_hdr.sadr = ans->pkt.from; | ||
319 | pkt->ip_hdr.dadr = ans->pkt.to; | ||
320 | |||
321 | pkt->ip_hdr.chks = calculate_ip_checksum((uint16_t*)&pkt->ip_hdr, 5*4); | ||
322 | |||
323 | /* set the udp-header */ | ||
324 | pkt->udp_dns.udp_hdr.spt = htons(53); | ||
325 | pkt->udp_dns.udp_hdr.dpt = ans->pkt.dst_port; | ||
326 | pkt->udp_dns.udp_hdr.len = htons(net_len - sizeof(struct ip_hdr)); | ||
327 | pkt->udp_dns.udp_hdr.crc = 0; /* Optional for IPv4 */ | ||
328 | |||
329 | memcpy(&pkt->udp_dns.data, ans->pkt.data, data_len); | ||
330 | |||
331 | GNUNET_CONTAINER_DLL_remove (answer_proc_head, answer_proc_tail, ans); | ||
332 | GNUNET_free(ans); | ||
333 | |||
334 | /* FIXME */ GNUNET_DISK_file_write(fh_to_helper, pkt, pkt_len); | ||
335 | |||
336 | /* if more packets are available, reschedule */ | ||
337 | if (answer_proc_head != NULL) | ||
338 | GNUNET_SCHEDULER_add_write_file (sched, | ||
339 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
340 | fh_to_helper, | ||
341 | &helper_write, | ||
342 | NULL); | ||
292 | } | 343 | } |
293 | 344 | ||
294 | static void message_token(void *cls, void *client, const struct GNUNET_MessageHeader *message) { | 345 | /** |
295 | if (ntohs(message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) return; | 346 | * Receive packets from the helper-process |
296 | 347 | */ | |
297 | struct tun_pkt *pkt_tun = (struct tun_pkt*) message; | 348 | static void |
298 | 349 | message_token(void *cls, | |
299 | if (ntohs(pkt_tun->tun.type) == 0x86dd) { | 350 | void *client, |
300 | struct ip6_pkt *pkt6 = (struct ip6_pkt*) message; | 351 | const struct GNUNET_MessageHeader *message) { |
301 | struct ip6_tcp *pkt6_tcp; | 352 | GNUNET_assert(ntohs(message->type) == GNUNET_MESSAGE_TYPE_VPN_HELPER); |
302 | struct ip6_udp *pkt6_udp; | ||
303 | |||
304 | pkt_printf(pkt6); | ||
305 | switch(pkt6->ip6_hdr.nxthdr) { | ||
306 | case 0x06: | ||
307 | pkt6_tcp = (struct ip6_tcp*)pkt6; | ||
308 | pkt_printf_ip6tcp(pkt6_tcp); | ||
309 | break; | ||
310 | case 0x11: | ||
311 | pkt6_udp = (struct ip6_udp*)pkt6; | ||
312 | pkt_printf_ip6udp(pkt6_udp); | ||
313 | if (ntohs(pkt6_udp->udp_hdr.dpt) == 53) { | ||
314 | pkt_printf_ip6dns((struct ip6_udp_dns*)pkt6_udp); | ||
315 | } | ||
316 | break; | ||
317 | } | ||
318 | } else if (ntohs(pkt_tun->tun.type) == 0x0800) { | ||
319 | struct ip_pkt *pkt = (struct ip_pkt*) message; | ||
320 | struct ip_udp *udp = (struct ip_udp*) message; | ||
321 | GNUNET_assert(pkt->ip_hdr.version == 4); | ||
322 | if (pkt->ip_hdr.proto == 0x11 && ntohs(udp->udp_hdr.dpt) == 53 ) { | ||
323 | size_t len = sizeof(struct query_packet) + ntohs(udp->udp_hdr.len) - 9; /* 9 = 8 for the udp-header + 1 for the unsigned char data[1]; */ | ||
324 | struct query_packet_list* query = GNUNET_malloc(len + 2*sizeof(struct query_packet_list*)); | ||
325 | query->pkt.hdr.type = htons(GNUNET_MESSAGE_TYPE_LOCAL_QUERY_DNS); | ||
326 | query->pkt.hdr.size = htons(len); | ||
327 | query->pkt.orig_to = pkt->ip_hdr.dadr; | ||
328 | query->pkt.orig_from = pkt->ip_hdr.sadr; | ||
329 | query->pkt.src_port = udp->udp_hdr.spt; | ||
330 | memcpy(query->pkt.data, udp->data, ntohs(udp->udp_hdr.len) - 8); | ||
331 | |||
332 | GNUNET_CONTAINER_DLL_insert_after(head, tail, tail, query); | ||
333 | |||
334 | if (dns_connection != NULL) | ||
335 | /* struct GNUNET_CLIENT_TransmitHandle* th = */ GNUNET_CLIENT_notify_transmit_ready(dns_connection, len, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, &send_query, NULL); | ||
336 | } | ||
337 | } | ||
338 | 353 | ||
339 | } | 354 | struct tun_pkt *pkt_tun = (struct tun_pkt*) message; |
340 | 355 | ||
341 | static void | 356 | /* ethertype is ipv6 */ |
342 | dns_answer_handler(void* cls, const struct GNUNET_MessageHeader *msg); | 357 | if (ntohs(pkt_tun->tun.type) == 0x86dd) |
358 | { | ||
359 | struct ip6_pkt *pkt6 = (struct ip6_pkt*) message; | ||
360 | struct ip6_tcp *pkt6_tcp; | ||
361 | struct ip6_udp *pkt6_udp; | ||
362 | |||
363 | pkt_printf(pkt6); | ||
364 | switch(pkt6->ip6_hdr.nxthdr) | ||
365 | { | ||
366 | case 0x06: | ||
367 | pkt6_tcp = (struct ip6_tcp*)pkt6; | ||
368 | pkt_printf_ip6tcp(pkt6_tcp); | ||
369 | break; | ||
370 | case 0x11: | ||
371 | pkt6_udp = (struct ip6_udp*)pkt6; | ||
372 | pkt_printf_ip6udp(pkt6_udp); | ||
373 | if (ntohs(pkt6_udp->udp_hdr.dpt) == 53) { | ||
374 | pkt_printf_ip6dns((struct ip6_udp_dns*)pkt6_udp); | ||
375 | } | ||
376 | break; | ||
377 | } | ||
378 | } | ||
379 | /* ethertype is ipv4 */ | ||
380 | else if (ntohs(pkt_tun->tun.type) == 0x0800) | ||
381 | { | ||
382 | struct ip_pkt *pkt = (struct ip_pkt*) message; | ||
383 | struct ip_udp *udp = (struct ip_udp*) message; | ||
384 | GNUNET_assert(pkt->ip_hdr.version == 4); | ||
385 | |||
386 | /* Send dns-packets to the service-dns */ | ||
387 | if (pkt->ip_hdr.proto == 0x11 && ntohs(udp->udp_hdr.dpt) == 53 ) | ||
388 | { | ||
389 | /* 9 = 8 for the udp-header + 1 for the unsigned char data[1]; */ | ||
390 | size_t len = sizeof(struct query_packet) + ntohs(udp->udp_hdr.len) - 9; | ||
391 | |||
392 | struct query_packet_list* query = GNUNET_malloc(len + 2*sizeof(struct query_packet_list*)); | ||
393 | query->pkt.hdr.type = htons(GNUNET_MESSAGE_TYPE_LOCAL_QUERY_DNS); | ||
394 | query->pkt.hdr.size = htons(len); | ||
395 | query->pkt.orig_to = pkt->ip_hdr.dadr; | ||
396 | query->pkt.orig_from = pkt->ip_hdr.sadr; | ||
397 | query->pkt.src_port = udp->udp_hdr.spt; | ||
398 | memcpy(query->pkt.data, udp->data, ntohs(udp->udp_hdr.len) - 8); | ||
399 | |||
400 | GNUNET_CONTAINER_DLL_insert_after(head, tail, tail, query); | ||
401 | |||
402 | if (dns_connection != NULL) | ||
403 | GNUNET_CLIENT_notify_transmit_ready(dns_connection, | ||
404 | len, | ||
405 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
406 | GNUNET_YES, | ||
407 | &send_query, | ||
408 | NULL); | ||
409 | } | ||
410 | } | ||
411 | } | ||
343 | 412 | ||
344 | static void | 413 | /** |
345 | reconnect_to_service_dns (void *cls, | 414 | * Connect to the service-dns |
346 | const struct GNUNET_SCHEDULER_TaskContext *tc) { | 415 | */ |
347 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | 416 | static void |
348 | return; | 417 | connect_to_service_dns (void *cls, |
349 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connecting\n"); | 418 | const struct GNUNET_SCHEDULER_TaskContext *tc) { |
350 | GNUNET_assert (dns_connection == NULL); | 419 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) |
351 | dns_connection = GNUNET_CLIENT_connect (sched, "dns", cfg); | 420 | return; |
352 | GNUNET_CLIENT_receive(dns_connection, &dns_answer_handler, NULL, GNUNET_TIME_UNIT_FOREVER_REL); | 421 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connecting to service-dns\n"); |
353 | if (head != NULL) | 422 | GNUNET_assert (dns_connection == NULL); |
354 | /* struct GNUNET_CLIENT_TransmitHandle* th = */ GNUNET_CLIENT_notify_transmit_ready(dns_connection, ntohs(head->pkt.hdr.size), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, &send_query, NULL); | 423 | dns_connection = GNUNET_CLIENT_connect (sched, "dns", cfg); |
424 | GNUNET_CLIENT_receive(dns_connection, &dns_answer_handler, NULL, GNUNET_TIME_UNIT_FOREVER_REL); | ||
425 | |||
426 | /* If a packet is already in the list, schedule to send it */ | ||
427 | if (head != NULL) | ||
428 | GNUNET_CLIENT_notify_transmit_ready(dns_connection, | ||
429 | ntohs(head->pkt.hdr.size), | ||
430 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
431 | GNUNET_YES, | ||
432 | &send_query, | ||
433 | NULL); | ||
355 | } | 434 | } |
356 | 435 | ||
436 | /** | ||
437 | * This gets scheduled with cls pointing to an answer_packet and does everything | ||
438 | * needed in order to send it to the helper. | ||
439 | * | ||
440 | * At the moment this means "inventing" and IPv6-Address for .gnunet-services and | ||
441 | * doing nothing for "real" services. | ||
442 | */ | ||
357 | static void | 443 | static void |
358 | process_answer(void* cls, const struct GNUNET_SCHEDULER_TaskContext* tc) { | 444 | process_answer(void* cls, const struct GNUNET_SCHEDULER_TaskContext* tc) { |
359 | struct answer_packet* pkt = cls; | 445 | struct answer_packet* pkt = cls; |
360 | 446 | ||
447 | /* This answer is about a .gnunet-service | ||
448 | * | ||
449 | * It contains an almost complete DNS-Response, we have to fill in the ip | ||
450 | * at the offset pkt->addroffset | ||
451 | */ | ||
361 | if (pkt->subtype == GNUNET_DNS_ANSWER_TYPE_SERVICE) | 452 | if (pkt->subtype == GNUNET_DNS_ANSWER_TYPE_SERVICE) |
362 | { | 453 | { |
363 | unsigned char ip6addr[16]; | 454 | unsigned char ip6addr[16]; |
@@ -378,47 +469,52 @@ process_answer(void* cls, const struct GNUNET_SCHEDULER_TaskContext* tc) { | |||
378 | */ | 469 | */ |
379 | } | 470 | } |
380 | 471 | ||
381 | struct answer_packet_list* list = GNUNET_malloc(htons(pkt->hdr.size) + 2*sizeof(struct answer_packet_list*)); | 472 | struct answer_packet_list* list = GNUNET_malloc(htons(pkt->hdr.size) + 2*sizeof(struct answer_packet_list*)); |
382 | 473 | ||
383 | memcpy(&list->pkt, pkt, htons(pkt->hdr.size)); | 474 | memcpy(&list->pkt, pkt, htons(pkt->hdr.size)); |
384 | 475 | ||
385 | GNUNET_CONTAINER_DLL_insert_after(answer_proc_head, answer_proc_tail, answer_proc_tail, list); | 476 | GNUNET_CONTAINER_DLL_insert_after(answer_proc_head, answer_proc_tail, answer_proc_tail, list); |
386 | 477 | ||
387 | GNUNET_SCHEDULER_add_write_file (sched, GNUNET_TIME_UNIT_FOREVER_REL, fh_to_helper, &helper_write, NULL); | 478 | GNUNET_SCHEDULER_add_write_file (sched, GNUNET_TIME_UNIT_FOREVER_REL, fh_to_helper, &helper_write, NULL); |
388 | 479 | ||
389 | return; | 480 | return; |
390 | } | 481 | } |
391 | 482 | ||
483 | /** | ||
484 | * This receives packets from the service-dns and schedules process_answer to | ||
485 | * handle it | ||
486 | */ | ||
392 | static void | 487 | static void |
393 | dns_answer_handler(void* cls, const struct GNUNET_MessageHeader *msg) | 488 | dns_answer_handler(void* cls, const struct GNUNET_MessageHeader *msg) { |
394 | { | 489 | /* the service disconnected, reconnect after short wait */ |
395 | if (msg == NULL) | 490 | if (msg == NULL) |
396 | { | 491 | { |
397 | GNUNET_CLIENT_disconnect(dns_connection, GNUNET_NO); | 492 | GNUNET_CLIENT_disconnect(dns_connection, GNUNET_NO); |
398 | dns_connection = NULL; | 493 | dns_connection = NULL; |
399 | GNUNET_SCHEDULER_add_delayed (sched, | 494 | GNUNET_SCHEDULER_add_delayed (sched, |
400 | GNUNET_TIME_UNIT_SECONDS, | 495 | GNUNET_TIME_UNIT_SECONDS, |
401 | &reconnect_to_service_dns, | 496 | &connect_to_service_dns, |
402 | NULL); | 497 | NULL); |
403 | return; | 498 | return; |
404 | } | 499 | } |
405 | 500 | ||
406 | if (msg->type != htons(GNUNET_MESSAGE_TYPE_LOCAL_RESPONSE_DNS)) | 501 | /* the service did something strange, reconnect immediately */ |
407 | { | 502 | if (msg->type != htons(GNUNET_MESSAGE_TYPE_LOCAL_RESPONSE_DNS)) |
408 | GNUNET_break (0); | 503 | { |
409 | GNUNET_CLIENT_disconnect(dns_connection, GNUNET_NO); | 504 | GNUNET_break (0); |
410 | dns_connection = NULL; | 505 | GNUNET_CLIENT_disconnect(dns_connection, GNUNET_NO); |
411 | GNUNET_SCHEDULER_add_now (sched, | 506 | dns_connection = NULL; |
412 | &reconnect_to_service_dns, | 507 | GNUNET_SCHEDULER_add_now (sched, |
413 | NULL); | 508 | &connect_to_service_dns, |
414 | return; | 509 | NULL); |
415 | } | 510 | return; |
416 | void *pkt = GNUNET_malloc(ntohs(msg->size)); | 511 | } |
512 | void *pkt = GNUNET_malloc(ntohs(msg->size)); | ||
417 | 513 | ||
418 | memcpy(pkt, msg, ntohs(msg->size)); | 514 | memcpy(pkt, msg, ntohs(msg->size)); |
419 | 515 | ||
420 | GNUNET_SCHEDULER_add_now(sched, process_answer, pkt); | 516 | GNUNET_SCHEDULER_add_now(sched, process_answer, pkt); |
421 | GNUNET_CLIENT_receive(dns_connection, &dns_answer_handler, NULL, GNUNET_TIME_UNIT_FOREVER_REL); | 517 | GNUNET_CLIENT_receive(dns_connection, &dns_answer_handler, NULL, GNUNET_TIME_UNIT_FOREVER_REL); |
422 | } | 518 | } |
423 | 519 | ||
424 | /** | 520 | /** |
@@ -435,18 +531,16 @@ run (void *cls, | |||
435 | struct GNUNET_SCHEDULER_Handle *sched_, | 531 | struct GNUNET_SCHEDULER_Handle *sched_, |
436 | char *const *args, | 532 | char *const *args, |
437 | const char *cfgfile, | 533 | const char *cfgfile, |
438 | const struct GNUNET_CONFIGURATION_Handle *cfg_) | 534 | const struct GNUNET_CONFIGURATION_Handle *cfg_) { |
439 | { | 535 | sched = sched_; |
440 | sched = sched_; | 536 | mst = GNUNET_SERVER_mst_create(&message_token, NULL); |
441 | mst = GNUNET_SERVER_mst_create(&message_token, NULL); | 537 | cfg = cfg_; |
442 | cfg = cfg_; | 538 | restart_hijack = 0; |
443 | restart_hijack = 0; | 539 | GNUNET_SCHEDULER_add_now (sched, connect_to_service_dns, NULL); |
444 | GNUNET_SCHEDULER_add_now (sched, &reconnect_to_service_dns, NULL); | 540 | GNUNET_SCHEDULER_add_now (sched, start_helper_and_schedule, NULL); |
445 | GNUNET_SCHEDULER_add_delayed(sched, GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls); | 541 | GNUNET_SCHEDULER_add_delayed(sched, GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls); |
446 | GNUNET_SCHEDULER_add_now (sched, start_helper_and_schedule, NULL); | ||
447 | } | 542 | } |
448 | 543 | ||
449 | |||
450 | /** | 544 | /** |
451 | * The main function to obtain template from gnunetd. | 545 | * The main function to obtain template from gnunetd. |
452 | * | 546 | * |
@@ -455,18 +549,17 @@ run (void *cls, | |||
455 | * @return 0 ok, 1 on error | 549 | * @return 0 ok, 1 on error |
456 | */ | 550 | */ |
457 | int | 551 | int |
458 | main (int argc, char *const *argv) | 552 | main (int argc, char *const *argv) { |
459 | { | 553 | static const struct GNUNET_GETOPT_CommandLineOption options[] = { |
460 | static const struct GNUNET_GETOPT_CommandLineOption options[] = { | 554 | GNUNET_GETOPT_OPTION_END |
461 | GNUNET_GETOPT_OPTION_END | 555 | }; |
462 | }; | 556 | |
463 | 557 | return (GNUNET_OK == | |
464 | return (GNUNET_OK == | 558 | GNUNET_PROGRAM_run (argc, |
465 | GNUNET_PROGRAM_run (argc, | 559 | argv, |
466 | argv, | 560 | "gnunet-daemon-vpn", |
467 | "gnunet-daemon-vpn", | 561 | gettext_noop ("help text"), |
468 | gettext_noop ("help text"), | 562 | options, &run, NULL)) ? ret : 1; |
469 | options, &run, NULL)) ? ret : 1; | ||
470 | } | 563 | } |
471 | 564 | ||
472 | /* end of gnunet-daemon-vpn.c */ | 565 | /* end of gnunet-daemon-vpn.c */ |