aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Tölke <toelke@in.tum.de>2010-11-02 21:40:02 +0000
committerPhilipp Tölke <toelke@in.tum.de>2010-11-02 21:40:02 +0000
commitb6ce573cb682686d40f7996247bd6efbd1e8f1d4 (patch)
tree0f2ce938ae07e81298f2d360404f2f023e938665
parent11c2830064ec60af2b84a9b7f885b2f9d31a1b0d (diff)
downloadgnunet-b6ce573cb682686d40f7996247bd6efbd1e8f1d4.tar.gz
gnunet-b6ce573cb682686d40f7996247bd6efbd1e8f1d4.zip
comment and indent gnunet-daemon-vpn
-rw-r--r--src/vpn/gnunet-daemon-vpn.c587
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 */
120static struct answer_packet_list *answer_proc_tail; 120static struct answer_packet_list *answer_proc_tail;
121 121
122size_t send_query(void* cls, size_t size, void* buf);
123
124static 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
135static void helper_read(void* cls, const struct GNUNET_SCHEDULER_TaskContext* tsdkctx); 122static void helper_read(void* cls, const struct GNUNET_SCHEDULER_TaskContext* tsdkctx);
123static void dns_answer_handler(void* cls, const struct GNUNET_MessageHeader *msg);
136 124
137static 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; 129static size_t
130send_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 */
175static void
176cleanup(void* cls, const struct GNUNET_SCHEDULER_TaskContext* tskctx) {
177 GNUNET_assert (0 != (tskctx->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN));
159 178
160static 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
179static 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) 194static void
183 return; 195start_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
197static 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
209static 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; 219static void
213 size_t len = ntohs(ans->pkt.hdr.size); 220restart_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); 241static void
234 pkt->ip_hdr.ident = 0; 242helper_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
261size_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) 266static uint16_t
265 { 267calculate_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 */
282static void
283helper_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
294static 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; 348static void
298 349message_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
341static void 356 /* ethertype is ipv6 */
342dns_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
344static void 413/**
345reconnect_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)) 416static void
348 return; 417connect_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 */
357static void 443static void
358process_answer(void* cls, const struct GNUNET_SCHEDULER_TaskContext* tc) { 444process_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 */
392static void 487static void
393dns_answer_handler(void* cls, const struct GNUNET_MessageHeader *msg) 488dns_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 */
457int 551int
458main (int argc, char *const *argv) 552main (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 */