098d8b944530cc713da7b975e64588db2680b924
[oweals/gnunet.git] / src / vpn / gnunet-service-vpn.c
1 /*
2      This file is part of GNUnet.
3      (C) 2010, 2011, 2012 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-service-vpn.c
23  * @brief service that opens a virtual interface and allows its clients
24  *        to allocate IPs on the virtual interface and to then redirect
25  *        IP traffic received on those IPs via the GNUnet mesh 
26  * @author Philipp Toelke
27  */
28 #include "platform.h"
29 #include "gnunet_util_lib.h"
30 #include "gnunet-vpn-packet.h"
31 #include "gnunet_common.h"
32 #include "gnunet_protocols.h"
33 #include "gnunet_applications.h"
34 #include "gnunet_mesh_service.h"
35 #include "gnunet_constants.h"
36
37
38
39 struct map_entry
40 {
41     /** The description of the service (used for service) */
42   GNUNET_HashCode desc;
43
44     /** The real address of the service (used for remote) */
45   char addrlen;
46   char addr[16];
47
48   struct GNUNET_MESH_Tunnel *tunnel;
49   uint16_t namelen;
50   char additional_ports[8192];
51
52   struct GNUNET_CONTAINER_HeapNode *heap_node;
53   GNUNET_HashCode hash;
54
55 };
56
57
58 struct remote_addr
59 {
60   char addrlen;
61   unsigned char addr[16];
62   char proto;
63 };
64
65
66 struct tunnel_notify_queue
67 {
68   struct tunnel_notify_queue *next;
69   struct tunnel_notify_queue *prev;
70   size_t len;
71   void *cls;
72 };
73
74
75 struct tunnel_state
76 {
77   struct GNUNET_MESH_TransmitHandle *th;
78   struct tunnel_notify_queue *head, *tail;
79
80   int addrlen;
81 };
82
83
84
85 /**
86  * Configuration we use.
87  */
88 static const struct GNUNET_CONFIGURATION_Handle *cfg;
89
90 /**
91  * Handle to the mesh service.
92  */
93 static struct GNUNET_MESH_Handle *mesh_handle;
94
95 /**
96  * FIXME
97  */
98 static struct GNUNET_CONTAINER_MultiHashMap *hashmap;
99
100 /**
101  * FIXME
102  */
103 static struct GNUNET_CONTAINER_Heap *heap;
104
105 /**
106  * The handle to the VPN helper process "gnunet-helper-vpn".
107  */
108 static struct GNUNET_HELPER_Handle *helper_handle;
109
110 /**
111  * Arguments to the exit helper.
112  */
113 static char *vpn_argv[7];
114
115 /**
116  * If there are at least this many address-mappings, old ones will be removed
117  */
118 static unsigned long long max_mappings;
119
120
121 /**
122  * @return the hash of the IP-Address if a mapping exists, NULL otherwise
123  */
124 static GNUNET_HashCode *
125 address6_mapping_exists (struct in6_addr *v6addr)
126 {
127   unsigned char *addr = (unsigned char*) v6addr;
128   GNUNET_HashCode *key = GNUNET_malloc (sizeof (GNUNET_HashCode));
129   unsigned char *k = (unsigned char *) key;
130
131   memset (key, 0, sizeof (GNUNET_HashCode));
132   unsigned int i;
133
134   for (i = 0; i < 16; i++)
135     k[15 - i] = addr[i];
136
137   if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (hashmap, key))
138     return key;
139   else
140   {
141     GNUNET_free (key);
142     return NULL;
143   }
144 }
145
146 /**
147  * @return the hash of the IP-Address if a mapping exists, NULL otherwise
148  */
149 static GNUNET_HashCode *
150 address4_mapping_exists (uint32_t addr)
151 {
152   GNUNET_HashCode *key = GNUNET_malloc (sizeof (GNUNET_HashCode));
153
154   memset (key, 0, sizeof (GNUNET_HashCode));
155   unsigned char *c = (unsigned char *) &addr;
156   unsigned char *k = (unsigned char *) key;
157   unsigned int i;
158
159   for (i = 0; i < 4; i++)
160     k[3 - i] = c[i];
161
162   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
163               "a4_m_e: getting with key %08x, addr is %08x, %d.%d.%d.%d\n",
164               *((uint32_t *) (key)), addr, c[0], c[1], c[2], c[3]);
165
166   if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (hashmap, key))
167     return key;
168   else
169   {
170     GNUNET_free (key);
171     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Mapping not found!\n");
172     return NULL;
173   }
174 }
175
176
177 static void *
178 initialize_tunnel_state (int addrlen, struct GNUNET_MESH_TransmitHandle *th)
179 {
180   struct tunnel_state *ts = GNUNET_malloc (sizeof *ts);
181
182   ts->addrlen = addrlen;
183   ts->th = th;
184   return ts;
185 }
186
187
188 static void
189 send_icmp4_response (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
190 {
191   if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
192     return;
193
194   struct ip_icmp *request = cls;
195
196   struct ip_icmp *response = alloca (ntohs (request->shdr.size));
197
198   GNUNET_assert (response != NULL);
199   memset (response, 0, ntohs (request->shdr.size));
200
201   response->shdr.size = request->shdr.size;
202   response->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
203
204   response->tun.flags = 0;
205   response->tun.type = htons (0x0800);
206
207   response->ip_hdr.hdr_lngth = 5;
208   response->ip_hdr.version = 4;
209   response->ip_hdr.proto = 0x01;
210   response->ip_hdr.dadr = request->ip_hdr.sadr;
211   response->ip_hdr.sadr = request->ip_hdr.dadr;
212   response->ip_hdr.tot_lngth = request->ip_hdr.tot_lngth;
213
214   response->ip_hdr.chks =
215       GNUNET_CRYPTO_crc16_n ((uint16_t *) & response->ip_hdr, 20);
216
217   response->icmp_hdr.code = 0;
218   response->icmp_hdr.type = 0x0;
219
220   /* Magic, more Magic! */
221   response->icmp_hdr.chks = request->icmp_hdr.chks + 0x8;
222
223   /* Copy the rest of the packet */
224   memcpy (response + 1, request + 1,
225           ntohs (request->shdr.size) - sizeof (struct ip_icmp));
226
227   (void) GNUNET_HELPER_send (helper_handle,
228                              &response->shdr,
229                              GNUNET_YES,
230                              NULL, NULL);
231   GNUNET_free (request);
232 }
233
234
235 static void
236 send_icmp6_response (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
237 {
238   if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
239     return;
240
241   struct ip6_icmp *request = cls;
242
243   struct ip6_icmp *response = alloca (ntohs (request->shdr.size));
244
245   GNUNET_assert (response != NULL);
246   memset (response, 0, ntohs (request->shdr.size));
247
248   response->shdr.size = request->shdr.size;
249   response->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
250
251   response->tun.flags = 0;
252   response->tun.type = htons (0x86dd);
253
254   response->ip6_hdr.hoplmt = 255;
255   response->ip6_hdr.paylgth = request->ip6_hdr.paylgth;
256   response->ip6_hdr.nxthdr = 0x3a;
257   response->ip6_hdr.version = 6;
258   memcpy (&response->ip6_hdr.sadr, &request->ip6_hdr.dadr, 16);
259   memcpy (&response->ip6_hdr.dadr, &request->ip6_hdr.sadr, 16);
260
261   response->icmp_hdr.code = 0;
262   response->icmp_hdr.type = 0x81;
263
264   /* Magic, more Magic! */
265   response->icmp_hdr.chks = request->icmp_hdr.chks - 0x1;
266
267   /* Copy the rest of the packet */
268   memcpy (response + 1, request + 1,
269           ntohs (request->shdr.size) - sizeof (struct ip6_icmp));
270
271   (void) GNUNET_HELPER_send (helper_handle,
272                              &response->shdr,
273                              GNUNET_YES,
274                              NULL, NULL);
275   GNUNET_free (request);
276 }
277
278
279 /**
280  * cls is the pointer to a GNUNET_MessageHeader that is
281  * followed by the service-descriptor and the packet that should be sent;
282  */
283 static size_t
284 send_pkt_to_peer_notify_callback (void *cls, size_t size, void *buf)
285 {
286   struct GNUNET_MESH_Tunnel **tunnel = cls;
287
288   struct tunnel_state *ts = GNUNET_MESH_tunnel_get_data (*tunnel);
289
290   ts->th = NULL;
291
292   if (NULL != buf)
293   {
294     struct GNUNET_MessageHeader *hdr =
295         (struct GNUNET_MessageHeader *) (tunnel + 1);
296     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
297                 "send_pkt_to_peer_notify_callback: buf = %x; size = %u;\n", buf,
298                 size);
299     GNUNET_assert (size >= ntohs (hdr->size));
300     memcpy (buf, hdr, ntohs (hdr->size));
301     size = ntohs (hdr->size);
302     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sent!\n");
303   }
304   else
305     size = 0;
306
307   if (NULL != ts->head)
308   {
309     struct tunnel_notify_queue *element = ts->head;
310
311     GNUNET_CONTAINER_DLL_remove (ts->head, ts->tail, element);
312
313     ts->th =
314         GNUNET_MESH_notify_transmit_ready (*tunnel, GNUNET_NO, 42,
315                                            GNUNET_TIME_relative_divide
316                                            (GNUNET_CONSTANTS_MAX_CORK_DELAY, 2),
317                                            (const struct GNUNET_PeerIdentity *)
318                                            NULL, element->len,
319                                            send_pkt_to_peer_notify_callback,
320                                            element->cls);
321
322     /* save the handle */
323     GNUNET_free (element);
324   }
325   GNUNET_free (cls);
326
327   return size;
328 }
329
330
331 static void
332 send_pkt_to_peer (void *cls, const struct GNUNET_PeerIdentity *peer,
333                   const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
334 {
335   /* peer == NULL means that all peers in this request are connected */
336   if (peer == NULL)
337     return;
338   struct GNUNET_MESH_Tunnel **tunnel = cls;
339   struct GNUNET_MessageHeader *hdr =
340       (struct GNUNET_MessageHeader *) (tunnel + 1);
341
342   GNUNET_assert (NULL != tunnel);
343   GNUNET_assert (NULL != *tunnel);
344
345   struct tunnel_state *ts = GNUNET_MESH_tunnel_get_data (*tunnel);
346
347   if (NULL == ts->th)
348   {
349     ts->th =
350         GNUNET_MESH_notify_transmit_ready (*tunnel, GNUNET_NO, 42,
351                                            GNUNET_TIME_relative_divide
352                                            (GNUNET_CONSTANTS_MAX_CORK_DELAY, 2),
353                                            (const struct GNUNET_PeerIdentity *)
354                                            NULL, ntohs (hdr->size),
355                                            send_pkt_to_peer_notify_callback,
356                                            cls);
357   }
358   else
359   {
360     struct tunnel_notify_queue *element = GNUNET_malloc (sizeof *element);
361
362     element->cls = cls;
363     element->len = ntohs (hdr->size);
364
365     GNUNET_CONTAINER_DLL_insert_tail (ts->head, ts->tail, element);
366   }
367 }
368
369
370
371
372 /**
373  * Receive packets from the helper-process
374  */
375 static void
376 message_token (void *cls GNUNET_UNUSED, void *client GNUNET_UNUSED,
377                const struct GNUNET_MessageHeader *message)
378 {
379   GNUNET_assert (ntohs (message->type) == GNUNET_MESSAGE_TYPE_VPN_HELPER);
380
381   struct tun_pkt *pkt_tun = (struct tun_pkt *) message;
382   GNUNET_HashCode *key;
383
384   /* ethertype is ipv6 */
385   if (ntohs (pkt_tun->tun.type) == 0x86dd)
386   {
387     struct ip6_pkt *pkt6 = (struct ip6_pkt *) message;
388
389     GNUNET_assert (pkt6->ip6_hdr.version == 6);
390     struct ip6_tcp *pkt6_tcp;
391     struct ip6_udp *pkt6_udp;
392     struct ip6_icmp *pkt6_icmp;
393
394     pkt6_udp = NULL;            /* make compiler happy */
395     switch (pkt6->ip6_hdr.nxthdr)
396     {
397     case IPPROTO_UDP:
398       pkt6_udp = (struct ip6_udp *) pkt6;
399       /* Send dns-packets to the service-dns */
400       /* fall through */
401     case IPPROTO_TCP:
402       pkt6_tcp = (struct ip6_tcp *) pkt6;
403
404       if ((key = address6_mapping_exists (&pkt6->ip6_hdr.dadr)) != NULL)
405       {
406         struct map_entry *me = GNUNET_CONTAINER_multihashmap_get (hashmap, key);
407
408         GNUNET_assert (me != NULL);
409         GNUNET_free (key);
410
411         size_t size =
412             sizeof (struct GNUNET_MESH_Tunnel *) +
413             sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) +
414             ntohs (pkt6->ip6_hdr.paylgth);
415
416         struct GNUNET_MESH_Tunnel **cls = GNUNET_malloc (size);
417         struct GNUNET_MessageHeader *hdr =
418             (struct GNUNET_MessageHeader *) (cls + 1);
419         GNUNET_HashCode *hc = (GNUNET_HashCode *) (hdr + 1);
420
421         hdr->size =
422             htons (sizeof (struct GNUNET_MessageHeader) +
423                    sizeof (GNUNET_HashCode) + ntohs (pkt6->ip6_hdr.paylgth));
424
425         GNUNET_MESH_ApplicationType app_type = 0;       /* fix compiler uninitialized warning... */
426
427         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "me->addrlen is %d\n",
428                     me->addrlen);
429         if (me->addrlen == 0)
430         {
431           /* This is a mapping to a gnunet-service */
432           *hc = me->desc;
433
434           if (me->tunnel == NULL && NULL != cls)
435           {
436             *cls =
437                 GNUNET_MESH_tunnel_create (mesh_handle,
438                                            initialize_tunnel_state (16, NULL),
439                                            &send_pkt_to_peer, NULL, cls);
440
441             GNUNET_MESH_peer_request_connect_add (*cls,
442                                                   (struct GNUNET_PeerIdentity *)
443                                                   &me->desc);
444             me->tunnel = *cls;
445           }
446           else if (NULL != cls)
447           {
448             *cls = me->tunnel;
449             send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL);
450           }
451         }
452         else
453         {
454           /* This is a mapping to a "real" address */
455           struct remote_addr *s = (struct remote_addr *) hc;
456
457           s->addrlen = me->addrlen;
458           memcpy (s->addr, me->addr, me->addrlen);
459           s->proto = pkt6->ip6_hdr.nxthdr;
460           if (s->proto == IPPROTO_UDP)
461           {
462             hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_UDP);
463             memcpy (hc + 1, &pkt6_udp->udp_hdr, ntohs (pkt6_udp->udp_hdr.len));
464             app_type = GNUNET_APPLICATION_TYPE_INTERNET_UDP_GATEWAY;
465           }
466           else if (s->proto == IPPROTO_TCP)
467           {
468             hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP);
469             memcpy (hc + 1, &pkt6_tcp->tcp_hdr, ntohs (pkt6->ip6_hdr.paylgth));
470             app_type = GNUNET_APPLICATION_TYPE_INTERNET_TCP_GATEWAY;
471           }
472           else
473           {
474             GNUNET_assert (0);
475           }
476           if (me->tunnel == NULL && NULL != cls)
477           {
478             *cls =
479                 GNUNET_MESH_tunnel_create (mesh_handle,
480                                            initialize_tunnel_state (16, NULL),
481                                            &send_pkt_to_peer, NULL, cls);
482
483             GNUNET_MESH_peer_request_connect_by_type (*cls, app_type);
484             me->tunnel = *cls;
485           }
486           else if (NULL != cls)
487           {
488             *cls = me->tunnel;
489             send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL);
490           }
491         }
492       }
493       else
494       {
495         char pbuf[INET6_ADDRSTRLEN];
496         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
497                     "Packet to %s, which has no mapping\n",
498                     inet_ntop (AF_INET6,
499                                &pkt6->ip6_hdr.dadr,
500                                pbuf,
501                                sizeof (pbuf)));
502       }
503       break;
504     case 0x3a:
505       /* ICMPv6 */
506       pkt6_icmp = (struct ip6_icmp *) pkt6;
507       /* If this packet is an icmp-echo-request and a mapping exists, answer */
508       if (pkt6_icmp->icmp_hdr.type == 0x80 &&
509           (key = address6_mapping_exists (&pkt6->ip6_hdr.dadr)) != NULL)
510       {
511         GNUNET_free (key);
512         pkt6_icmp = GNUNET_malloc (ntohs (pkt6->shdr.size));
513         memcpy (pkt6_icmp, pkt6, ntohs (pkt6->shdr.size));
514         GNUNET_SCHEDULER_add_now (&send_icmp6_response, pkt6_icmp);
515       }
516       break;
517     }
518   }
519   /* ethertype is ipv4 */
520   else if (ntohs (pkt_tun->tun.type) == 0x0800)
521   {
522     struct ip_pkt *pkt = (struct ip_pkt *) message;
523     //struct ip_udp *udp = (struct ip_udp *) message;
524     struct ip_tcp *pkt_tcp;
525     struct ip_udp *pkt_udp;
526     struct ip_icmp *pkt_icmp;
527
528     GNUNET_assert (pkt->ip_hdr.version == 4);
529
530     {
531       uint32_t dadr = pkt->ip_hdr.dadr.s_addr;
532       unsigned char *c = (unsigned char *) &dadr;
533
534       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Packet to %d.%d.%d.%d, proto %x\n",
535                   c[0], c[1], c[2], c[3], pkt->ip_hdr.proto);
536       switch (pkt->ip_hdr.proto)
537       {
538       case IPPROTO_TCP:
539       case IPPROTO_UDP:
540         pkt_tcp = (struct ip_tcp *) pkt;
541         pkt_udp = (struct ip_udp *) pkt;
542
543         if ((key = address4_mapping_exists (dadr)) != NULL)
544         {
545           struct map_entry *me =
546               GNUNET_CONTAINER_multihashmap_get (hashmap, key);
547           GNUNET_assert (me != NULL);
548           GNUNET_free (key);
549
550           size_t size =
551               sizeof (struct GNUNET_MESH_Tunnel *) +
552               sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) +
553               ntohs (pkt->ip_hdr.tot_lngth) - 4 * pkt->ip_hdr.hdr_lngth;
554
555           struct GNUNET_MESH_Tunnel **cls = GNUNET_malloc (size);
556           struct GNUNET_MessageHeader *hdr =
557               (struct GNUNET_MessageHeader *) (cls + 1);
558           GNUNET_HashCode *hc = (GNUNET_HashCode *) (hdr + 1);
559
560           hdr->size =
561               htons (sizeof (struct GNUNET_MessageHeader) +
562                      sizeof (GNUNET_HashCode) + ntohs (pkt->ip_hdr.tot_lngth) -
563                      4 * pkt->ip_hdr.hdr_lngth);
564
565           GNUNET_MESH_ApplicationType app_type = 0; /* make compiler happy */
566
567           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "me->addrlen is %d\n",
568                       me->addrlen);
569           if (me->addrlen == 0)
570           {
571             /* This is a mapping to a gnunet-service */
572             *hc = me->desc;
573
574             if (me->tunnel == NULL && NULL != cls)
575             {
576               *cls =
577                   GNUNET_MESH_tunnel_create (mesh_handle,
578                                              initialize_tunnel_state (4, NULL),
579                                              send_pkt_to_peer, NULL, cls);
580               GNUNET_MESH_peer_request_connect_add (*cls,
581                                                     (struct GNUNET_PeerIdentity
582                                                      *) &me->desc);
583               me->tunnel = *cls;
584             }
585             else if (NULL != cls)
586             {
587               *cls = me->tunnel;
588               send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL);
589             }
590           }
591           else
592           {
593             /* This is a mapping to a "real" address */
594             struct remote_addr *s = (struct remote_addr *) hc;
595
596             s->addrlen = me->addrlen;
597             memcpy (s->addr, me->addr, me->addrlen);
598             s->proto = pkt->ip_hdr.proto;
599             if (s->proto == IPPROTO_UDP)
600             {
601               hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_UDP);
602               memcpy (hc + 1, &pkt_udp->udp_hdr, ntohs (pkt_udp->udp_hdr.len));
603               app_type = GNUNET_APPLICATION_TYPE_INTERNET_UDP_GATEWAY;
604             }
605             else if (s->proto == IPPROTO_TCP)
606             {
607               hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP);
608               memcpy (hc + 1, &pkt_tcp->tcp_hdr,
609                       ntohs (pkt->ip_hdr.tot_lngth) -
610                       4 * pkt->ip_hdr.hdr_lngth);
611               app_type = GNUNET_APPLICATION_TYPE_INTERNET_TCP_GATEWAY;
612             }
613             else
614               GNUNET_assert (0);
615             if (me->tunnel == NULL && NULL != cls)
616             {
617               *cls =
618                   GNUNET_MESH_tunnel_create (mesh_handle,
619                                              initialize_tunnel_state (4, NULL),
620                                              send_pkt_to_peer, NULL, cls);
621
622               GNUNET_MESH_peer_request_connect_by_type (*cls, app_type);
623               me->tunnel = *cls;
624             }
625             else if (NULL != cls)
626             {
627               *cls = me->tunnel;
628               send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL);
629             }
630           }
631         }
632         else
633         {
634           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
635                       "Packet to %x which has no mapping\n", dadr);
636         }
637         break;
638       case 0x01:
639         /* ICMP */
640         pkt_icmp = (struct ip_icmp *) pkt;
641         if (pkt_icmp->icmp_hdr.type == 0x8 &&
642             (key = address4_mapping_exists (dadr)) != NULL)
643         {
644           GNUNET_free (key);
645           pkt_icmp = GNUNET_malloc (ntohs (pkt->shdr.size));
646           memcpy (pkt_icmp, pkt, ntohs (pkt->shdr.size));
647           GNUNET_SCHEDULER_add_now (&send_icmp4_response, pkt_icmp);
648         }
649         break;
650       }
651     }
652   }
653 }
654
655
656
657
658
659 /**
660  * Create a new Address from an answer-packet
661  */
662 static void
663 new_ip6addr (struct in6_addr *v6addr,
664              const GNUNET_HashCode * peer,
665              const GNUNET_HashCode * service_desc)
666 {                               /* {{{ */
667   unsigned char *buf = (unsigned char*) v6addr;
668   char *ipv6addr;
669   unsigned long long ipv6prefix;
670
671   GNUNET_assert (GNUNET_OK ==
672                  GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6ADDR",
673                                                         &ipv6addr));
674   GNUNET_assert (GNUNET_OK ==
675                  GNUNET_CONFIGURATION_get_value_number (cfg, "vpn",
676                                                         "IPV6PREFIX",
677                                                         &ipv6prefix));
678   GNUNET_assert (ipv6prefix < 127);
679   ipv6prefix = (ipv6prefix + 7) / 8;
680
681   inet_pton (AF_INET6, ipv6addr, buf);
682   GNUNET_free (ipv6addr);
683
684   int peer_length = 16 - ipv6prefix - 6;
685
686   if (peer_length <= 0)
687     peer_length = 0;
688
689   int service_length = 16 - ipv6prefix - peer_length;
690
691   if (service_length <= 0)
692     service_length = 0;
693
694   memcpy (buf + ipv6prefix, service_desc, service_length);
695   memcpy (buf + ipv6prefix + service_length, peer, peer_length);
696 }
697
698 /*}}}*/
699
700
701 /**
702  * Create a new Address from an answer-packet
703  */
704 static void
705 new_ip6addr_remote (struct in6_addr *v6addr,
706                     unsigned char *addr, char addrlen)
707 {                               /* {{{ */
708   unsigned char *buf = (unsigned char*) v6addr;
709   char *ipv6addr;
710   unsigned long long ipv6prefix;
711
712   GNUNET_assert (GNUNET_OK ==
713                  GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6ADDR",
714                                                         &ipv6addr));
715   GNUNET_assert (GNUNET_OK ==
716                  GNUNET_CONFIGURATION_get_value_number (cfg, "vpn",
717                                                         "IPV6PREFIX",
718                                                         &ipv6prefix));
719   GNUNET_assert (ipv6prefix < 127);
720   ipv6prefix = (ipv6prefix + 7) / 8;
721
722   inet_pton (AF_INET6, ipv6addr, buf);
723   GNUNET_free (ipv6addr);
724
725   int local_length = 16 - ipv6prefix;
726
727   memcpy (buf + ipv6prefix, addr, GNUNET_MIN (addrlen, local_length));
728 }
729
730 /*}}}*/
731
732 /**
733  * Create a new Address from an answer-packet
734  */
735 static void
736 new_ip4addr_remote (unsigned char *buf, unsigned char *addr, char addrlen)
737 {                               /* {{{ */
738   char *ipv4addr;
739   char *ipv4mask;
740
741   GNUNET_assert (GNUNET_OK ==
742                  GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR",
743                                                         &ipv4addr));
744   GNUNET_assert (GNUNET_OK ==
745                  GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK",
746                                                         &ipv4mask));
747   uint32_t mask;
748
749   inet_pton (AF_INET, ipv4addr, buf);
750   int r = inet_pton (AF_INET, ipv4mask, &mask);
751
752   mask = htonl (mask);
753   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "inet_pton: %d; %m; mask: %08x\n", r,
754               mask);
755
756   GNUNET_free (ipv4addr);
757
758   int c;
759
760   if (mask)
761   {
762     mask = (mask ^ (mask - 1)) >> 1;
763     for (c = 0; mask; c++)
764     {
765       mask >>= 1;
766     }
767   }
768   else
769   {
770     c = CHAR_BIT * sizeof (mask);
771   }
772
773   c = 32 - c;
774   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "The mask %s has %d leading 1s.\n",
775               ipv4mask, c);
776
777   GNUNET_free (ipv4mask);
778
779   if (c % 8 == 0)
780     c = c / 8;
781   else
782     GNUNET_assert (0);
783
784   memcpy (buf + c, addr, GNUNET_MIN (addrlen, 4 - c));
785 }
786
787 /*}}}*/
788
789
790
791 /**
792  * FIXME: document.
793  */ 
794 static int
795 receive_udp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
796                   void **tunnel_ctx, const struct GNUNET_PeerIdentity *sender,
797                   const struct GNUNET_MessageHeader *message,
798                   const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
799 {
800   GNUNET_HashCode *desc = (GNUNET_HashCode *) (message + 1);
801   struct remote_addr *s = (struct remote_addr *) desc;
802   struct udp_pkt *pkt = (struct udp_pkt *) (desc + 1);
803   const struct GNUNET_PeerIdentity *other = sender;
804   struct tunnel_state *ts = *tunnel_ctx;
805
806   if (16 == ts->addrlen)
807   {
808     size_t size =
809         sizeof (struct ip6_udp) + ntohs (pkt->len) - 1 -
810         sizeof (struct udp_pkt);
811
812     struct ip6_udp *pkt6 = alloca (size);
813
814     GNUNET_assert (pkt6 != NULL);
815
816     if (ntohs (message->type) == GNUNET_MESSAGE_TYPE_VPN_SERVICE_UDP_BACK)
817       new_ip6addr (&pkt6->ip6_hdr.sadr, &other->hashPubKey, desc);
818     else
819       new_ip6addr_remote (&pkt6->ip6_hdr.sadr, s->addr, s->addrlen);
820
821     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
822                 "Relaying calc:%d gnu:%d udp:%d bytes!\n", size,
823                 ntohs (message->size), ntohs (pkt->len));
824
825     pkt6->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
826     pkt6->shdr.size = htons (size);
827
828     pkt6->tun.flags = 0;
829     pkt6->tun.type = htons (0x86dd);
830
831     pkt6->ip6_hdr.version = 6;
832     pkt6->ip6_hdr.tclass_h = 0;
833     pkt6->ip6_hdr.tclass_l = 0;
834     pkt6->ip6_hdr.flowlbl = 0;
835     pkt6->ip6_hdr.paylgth = pkt->len;
836     pkt6->ip6_hdr.nxthdr = IPPROTO_UDP;
837     pkt6->ip6_hdr.hoplmt = 0xff;
838
839     {
840       char *ipv6addr;
841
842       GNUNET_assert (GNUNET_OK ==
843                      GNUNET_CONFIGURATION_get_value_string (cfg, "vpn",
844                                                             "IPV6ADDR",
845                                                             &ipv6addr));
846       inet_pton (AF_INET6, ipv6addr, &pkt6->ip6_hdr.dadr);
847       GNUNET_free (ipv6addr);
848     }
849     memcpy (&pkt6->udp_hdr, pkt, ntohs (pkt->len));
850
851     GNUNET_HashCode *key = address6_mapping_exists (&pkt6->ip6_hdr.sadr);
852
853     GNUNET_assert (key != NULL);
854
855     struct map_entry *me = GNUNET_CONTAINER_multihashmap_get (hashmap, key);
856
857     GNUNET_CONTAINER_heap_update_cost (heap, me->heap_node,
858                                        GNUNET_TIME_absolute_get ().abs_value);
859
860     GNUNET_free (key);
861
862     GNUNET_assert (me != NULL);
863
864     pkt6->udp_hdr.crc = 0;
865     uint32_t sum = 0;
866
867     sum =
868         GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & pkt6->ip6_hdr.sadr, 16);
869     sum =
870         GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & pkt6->ip6_hdr.dadr, 16);
871     uint32_t tmp = (pkt6->udp_hdr.len & 0xffff);
872
873     sum = GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & tmp, 4);
874     tmp = htons (((pkt6->ip6_hdr.nxthdr & 0x00ff)));
875     sum = GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & tmp, 4);
876
877     sum =
878         GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & pkt6->udp_hdr,
879                                    ntohs (pkt->len));
880     pkt6->udp_hdr.crc = GNUNET_CRYPTO_crc16_finish (sum);
881     
882     (void) GNUNET_HELPER_send (helper_handle,
883                                &pkt6->shdr,
884                                GNUNET_YES,
885                                NULL, NULL);
886   }
887   else
888   {
889     size_t size =
890         sizeof (struct ip_udp) + ntohs (pkt->len) - 1 - sizeof (struct udp_pkt);
891
892     struct ip_udp *pkt4 = alloca (size);
893
894     GNUNET_assert (pkt4 != NULL);
895
896     GNUNET_assert (ntohs (message->type) ==
897                    GNUNET_MESSAGE_TYPE_VPN_REMOTE_UDP_BACK);
898     uint32_t sadr;
899
900     new_ip4addr_remote ((unsigned char *) &sadr, s->addr, s->addrlen);
901     pkt4->ip_hdr.sadr.s_addr = sadr;
902
903     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
904                 "Relaying calc:%d gnu:%d udp:%d bytes!\n", size,
905                 ntohs (message->size), ntohs (pkt->len));
906
907     pkt4->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
908     pkt4->shdr.size = htons (size);
909
910     pkt4->tun.flags = 0;
911     pkt4->tun.type = htons (0x0800);
912
913     pkt4->ip_hdr.version = 4;
914     pkt4->ip_hdr.hdr_lngth = 5;
915     pkt4->ip_hdr.diff_serv = 0;
916     pkt4->ip_hdr.tot_lngth = htons (20 + ntohs (pkt->len));
917     pkt4->ip_hdr.ident = 0;
918     pkt4->ip_hdr.flags = 0;
919     pkt4->ip_hdr.frag_off = 0;
920     pkt4->ip_hdr.ttl = 255;
921     pkt4->ip_hdr.proto = IPPROTO_UDP;
922     pkt4->ip_hdr.chks = 0;      /* Will be calculated later */
923
924     {
925       char *ipv4addr;
926       uint32_t dadr;
927
928       GNUNET_assert (GNUNET_OK ==
929                      GNUNET_CONFIGURATION_get_value_string (cfg, "vpn",
930                                                             "IPV4ADDR",
931                                                             &ipv4addr));
932       inet_pton (AF_INET, ipv4addr, &dadr);
933       GNUNET_free (ipv4addr);
934       pkt4->ip_hdr.dadr.s_addr = dadr;
935     }
936     memcpy (&pkt4->udp_hdr, pkt, ntohs (pkt->len));
937
938     GNUNET_HashCode *key = address4_mapping_exists (pkt4->ip_hdr.sadr.s_addr);
939
940     GNUNET_assert (key != NULL);
941
942     struct map_entry *me = GNUNET_CONTAINER_multihashmap_get (hashmap, key);
943
944     GNUNET_CONTAINER_heap_update_cost (heap, me->heap_node,
945                                        GNUNET_TIME_absolute_get ().abs_value);
946
947     GNUNET_free (key);
948
949     GNUNET_assert (me != NULL);
950
951     pkt4->udp_hdr.crc = 0;      /* Optional for IPv4 */
952
953     pkt4->ip_hdr.chks =
954         GNUNET_CRYPTO_crc16_n ((uint16_t *) & pkt4->ip_hdr, 5 * 4);
955
956     (void) GNUNET_HELPER_send (helper_handle,
957                                &pkt4->shdr,
958                                GNUNET_YES,
959                                NULL, NULL);
960   }
961
962   return GNUNET_OK;
963 }
964
965
966 /**
967  * FIXME: document.
968  */ 
969 static int
970 receive_tcp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
971                   void **tunnel_ctx,
972                   const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
973                   const struct GNUNET_MessageHeader *message,
974                   const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
975 {
976   GNUNET_HashCode *desc = (GNUNET_HashCode *) (message + 1);
977   struct remote_addr *s = (struct remote_addr *) desc;
978   struct tcp_pkt *pkt = (struct tcp_pkt *) (desc + 1);
979   const struct GNUNET_PeerIdentity *other = sender;
980   struct tunnel_state *ts = *tunnel_ctx;
981
982   size_t pktlen =
983       ntohs (message->size) - sizeof (struct GNUNET_MessageHeader) -
984       sizeof (GNUNET_HashCode);
985
986   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
987               "Received TCP-Packet back, addrlen = %d\n", s->addrlen);
988
989   if (ntohs (message->type) == GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP_BACK ||
990       ts->addrlen == 16)
991   {
992     size_t size = pktlen + sizeof (struct ip6_tcp) - 1;
993
994     struct ip6_tcp *pkt6 = alloca (size);
995
996     memset (pkt6, 0, size);
997
998     GNUNET_assert (pkt6 != NULL);
999
1000     if (ntohs (message->type) == GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP_BACK)
1001       new_ip6addr (&pkt6->ip6_hdr.sadr, &other->hashPubKey, desc);
1002     else
1003       new_ip6addr_remote (&pkt6->ip6_hdr.sadr, s->addr, s->addrlen);
1004
1005     pkt6->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1006     pkt6->shdr.size = htons (size);
1007
1008     pkt6->tun.flags = 0;
1009     pkt6->tun.type = htons (0x86dd);
1010
1011     pkt6->ip6_hdr.version = 6;
1012     pkt6->ip6_hdr.tclass_h = 0;
1013     pkt6->ip6_hdr.tclass_l = 0;
1014     pkt6->ip6_hdr.flowlbl = 0;
1015     pkt6->ip6_hdr.paylgth = htons (pktlen);
1016     pkt6->ip6_hdr.nxthdr = IPPROTO_TCP;
1017     pkt6->ip6_hdr.hoplmt = 0xff;
1018
1019     {
1020       char *ipv6addr;
1021
1022       GNUNET_assert (GNUNET_OK ==
1023                      GNUNET_CONFIGURATION_get_value_string (cfg, "vpn",
1024                                                             "IPV6ADDR",
1025                                                             &ipv6addr));
1026       inet_pton (AF_INET6, ipv6addr, &pkt6->ip6_hdr.dadr);
1027       GNUNET_free (ipv6addr);
1028     }
1029     memcpy (&pkt6->tcp_hdr, pkt, pktlen);
1030
1031     GNUNET_HashCode *key = address6_mapping_exists (&pkt6->ip6_hdr.sadr);
1032
1033     GNUNET_assert (key != NULL);
1034
1035     struct map_entry *me = GNUNET_CONTAINER_multihashmap_get (hashmap, key);
1036
1037     GNUNET_CONTAINER_heap_update_cost (heap, me->heap_node,
1038                                        GNUNET_TIME_absolute_get ().abs_value);
1039
1040     GNUNET_free (key);
1041
1042     GNUNET_assert (me != NULL);
1043
1044     pkt6->tcp_hdr.crc = 0;
1045     uint32_t sum = 0;
1046     uint32_t tmp;
1047
1048     sum =
1049         GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & pkt6->ip6_hdr.sadr, 16);
1050     sum =
1051         GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & pkt6->ip6_hdr.dadr, 16);
1052     tmp = htonl (pktlen);
1053     sum = GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & tmp, 4);
1054     tmp = htonl (((pkt6->ip6_hdr.nxthdr & 0x000000ff)));
1055     sum = GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & tmp, 4);
1056
1057     sum =
1058         GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & pkt6->tcp_hdr,
1059                                    ntohs (pkt6->ip6_hdr.paylgth));
1060     pkt6->tcp_hdr.crc = GNUNET_CRYPTO_crc16_finish (sum);
1061
1062     (void) GNUNET_HELPER_send (helper_handle,
1063                                &pkt6->shdr,
1064                                GNUNET_YES,
1065                                NULL, NULL);
1066   }
1067   else
1068   {
1069     size_t size = pktlen + sizeof (struct ip_tcp) - 1;
1070
1071     struct ip_tcp *pkt4 = alloca (size);
1072
1073     GNUNET_assert (pkt4 != NULL);
1074     memset (pkt4, 0, size);
1075
1076     GNUNET_assert (ntohs (message->type) ==
1077                    GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP_BACK);
1078     uint32_t sadr;
1079
1080     new_ip4addr_remote ((unsigned char *) &sadr, s->addr, s->addrlen);
1081     pkt4->ip_hdr.sadr.s_addr = sadr;
1082
1083     pkt4->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1084     pkt4->shdr.size = htons (size);
1085
1086     pkt4->tun.flags = 0;
1087     pkt4->tun.type = htons (0x0800);
1088
1089     pkt4->ip_hdr.version = 4;
1090     pkt4->ip_hdr.hdr_lngth = 5;
1091     pkt4->ip_hdr.diff_serv = 0;
1092     pkt4->ip_hdr.tot_lngth = htons (20 + pktlen);
1093     pkt4->ip_hdr.ident = 0;
1094     pkt4->ip_hdr.flags = 0;
1095     pkt4->ip_hdr.frag_off = 0;
1096     pkt4->ip_hdr.ttl = 255;
1097     pkt4->ip_hdr.proto = IPPROTO_TCP;
1098     pkt4->ip_hdr.chks = 0;      /* Will be calculated later */
1099
1100     {
1101       char *ipv4addr;
1102       uint32_t dadr;
1103
1104       GNUNET_assert (GNUNET_OK ==
1105                      GNUNET_CONFIGURATION_get_value_string (cfg, "vpn",
1106                                                             "IPV4ADDR",
1107                                                             &ipv4addr));
1108       inet_pton (AF_INET, ipv4addr, &dadr);
1109       GNUNET_free (ipv4addr);
1110       pkt4->ip_hdr.dadr.s_addr = dadr;
1111     }
1112
1113     memcpy (&pkt4->tcp_hdr, pkt, pktlen);
1114
1115     GNUNET_HashCode *key = address4_mapping_exists (pkt4->ip_hdr.sadr.s_addr);
1116
1117     GNUNET_assert (key != NULL);
1118
1119     struct map_entry *me = GNUNET_CONTAINER_multihashmap_get (hashmap, key);
1120
1121     GNUNET_CONTAINER_heap_update_cost (heap, me->heap_node,
1122                                        GNUNET_TIME_absolute_get ().abs_value);
1123
1124     GNUNET_free (key);
1125
1126     GNUNET_assert (me != NULL);
1127     pkt4->tcp_hdr.crc = 0;
1128     uint32_t sum = 0;
1129     uint32_t tmp;
1130
1131     sum = GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) &pkt4->ip_hdr.sadr, 4);
1132     sum = GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) &pkt4->ip_hdr.dadr, 4);
1133
1134     tmp = (0x06 << 16) | (0xffff & pktlen);     // 0x06 for TCP?
1135
1136     tmp = htonl (tmp);
1137
1138     sum = GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & tmp, 4);
1139
1140     sum = GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & pkt4->tcp_hdr, pktlen);
1141     pkt4->tcp_hdr.crc = GNUNET_CRYPTO_crc16_finish (sum);
1142
1143     pkt4->ip_hdr.chks =
1144         GNUNET_CRYPTO_crc16_n ((uint16_t *) & pkt4->ip_hdr, 5 * 4);
1145
1146     (void) GNUNET_HELPER_send (helper_handle,
1147                                &pkt4->shdr,
1148                                GNUNET_YES,
1149                                NULL, NULL);
1150
1151   }
1152
1153   return GNUNET_OK;
1154 }
1155
1156
1157 /**
1158  * FIXME: document.
1159  */ 
1160 static void *
1161 new_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1162             const struct GNUNET_PeerIdentity *initiator,
1163             const struct GNUNET_ATS_Information *atsi)
1164 {
1165   /* Why should anyone open an inbound tunnel to vpn? */
1166   GNUNET_break (0);
1167   return NULL;
1168 }
1169
1170
1171 /**
1172  * FIXME: document.
1173  */ 
1174 static void
1175 tunnel_cleaner (void *cls, const struct GNUNET_MESH_Tunnel *tunnel, void *tunnel_ctx)
1176 {
1177   /* Why should anyone open an inbound tunnel to vpn? */
1178   /* FIXME: is this not also called for outbound tunnels that go down!? */
1179   GNUNET_break (0);
1180 }
1181
1182
1183 /**
1184  * Function scheduled as very last function, cleans up after us
1185  */
1186 static void
1187 cleanup (void *cls GNUNET_UNUSED,
1188          const struct GNUNET_SCHEDULER_TaskContext *tskctx)
1189 {
1190   unsigned int i;
1191
1192   if (mesh_handle != NULL)
1193   {
1194     GNUNET_MESH_disconnect (mesh_handle);
1195     mesh_handle = NULL;
1196   }
1197   if (helper_handle != NULL)
1198   {
1199     GNUNET_HELPER_stop (helper_handle);
1200     helper_handle = NULL;
1201   }
1202   for (i=0;i<5;i++)
1203     GNUNET_free_non_null (vpn_argv[i]);
1204 }
1205
1206
1207 /**
1208  * Main function that will be run by the scheduler.
1209  *
1210  * @param cls closure
1211  * @param server the initialized server
1212  * @param cfg_ configuration
1213  */
1214 static void
1215 run (void *cls,
1216      struct GNUNET_SERVER_Handle *server,
1217      const struct GNUNET_CONFIGURATION_Handle *cfg_)
1218 {
1219   static const struct GNUNET_MESH_MessageHandler handlers[] = {
1220     {receive_udp_back, GNUNET_MESSAGE_TYPE_VPN_SERVICE_UDP_BACK, 0},
1221     {receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP_BACK, 0},
1222     {receive_udp_back, GNUNET_MESSAGE_TYPE_VPN_REMOTE_UDP_BACK, 0},
1223     {receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP_BACK, 0},
1224     {NULL, 0, 0}
1225   };
1226   static const GNUNET_MESH_ApplicationType types[] = {
1227     GNUNET_APPLICATION_TYPE_END
1228   };
1229   char *ifname;
1230   char *ipv6addr;
1231   char *ipv6prefix_s;
1232   char *ipv4addr;
1233   char *ipv4mask;
1234   struct in_addr v4;
1235   struct in6_addr v6;
1236   unsigned long long ipv6prefix;
1237
1238   cfg = cfg_;
1239   hashmap = GNUNET_CONTAINER_multihashmap_create (65536);
1240   heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
1241
1242   if (GNUNET_OK !=
1243       GNUNET_CONFIGURATION_get_value_number (cfg, "vpn", "MAX_MAPPING",
1244                                              &max_mappings))
1245     max_mappings = 200;
1246
1247   vpn_argv[0] = GNUNET_strdup ("vpn-gnunet");
1248   if (GNUNET_SYSERR ==
1249       GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IFNAME", &ifname))
1250   {
1251     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1252                 "No entry 'IFNAME' in configuration!\n");
1253     GNUNET_SCHEDULER_shutdown ();
1254     return;
1255   }
1256   vpn_argv[1] = ifname;
1257   if ( (GNUNET_SYSERR ==
1258         GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6ADDR",
1259                                                &ipv6addr) ||
1260         (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
1261   {
1262     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1263                 "No valid entry 'IPV6ADDR' in configuration!\n");
1264     GNUNET_SCHEDULER_shutdown ();
1265     return;
1266   }
1267   vpn_argv[2] = ipv6addr;
1268   if (GNUNET_SYSERR ==
1269       GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6PREFIX",
1270                                              &ipv6prefix_s))
1271   {
1272     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1273                 "No entry 'IPV6PREFIX' in configuration!\n");
1274     GNUNET_SCHEDULER_shutdown ();
1275     return;
1276   }
1277   vpn_argv[3] = ipv6prefix_s;
1278   if ( (GNUNET_OK !=
1279         GNUNET_CONFIGURATION_get_value_number (cfg, "vpn",
1280                                                "IPV6PREFIX",
1281                                                &ipv6prefix)) ||
1282        (ipv6prefix >= 127) )
1283   {
1284     GNUNET_SCHEDULER_shutdown ();
1285     return;
1286   }
1287
1288   if ( (GNUNET_SYSERR ==
1289         GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR",
1290                                                &ipv4addr) ||
1291         (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
1292   {
1293     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1294                 "No valid entry for 'IPV4ADDR' in configuration!\n");
1295     GNUNET_SCHEDULER_shutdown ();
1296     return;
1297   }
1298   vpn_argv[4] = ipv4addr;
1299   if ( (GNUNET_SYSERR ==
1300         GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK",
1301                                                &ipv4mask) ||
1302         (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
1303   {
1304     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1305                 "No valid entry 'IPV4MASK' in configuration!\n");
1306     GNUNET_SCHEDULER_shutdown ();
1307     return;
1308   }
1309   vpn_argv[5] = ipv4mask;
1310   vpn_argv[6] = NULL;
1311
1312   mesh_handle =
1313     GNUNET_MESH_connect (cfg_, 42 /* queue length */, NULL, 
1314                          &new_tunnel, 
1315                          &tunnel_cleaner, 
1316                          handlers,
1317                          types);
1318   helper_handle = GNUNET_HELPER_start ("gnunet-helper-vpn", vpn_argv,
1319                                        &message_token, NULL);
1320   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
1321 }
1322
1323
1324 /**
1325  * The main function of the VPN service.
1326  *
1327  * @param argc number of arguments from the command line
1328  * @param argv command line arguments
1329  * @return 0 ok, 1 on error
1330  */
1331 int
1332 main (int argc, char *const *argv)
1333 {
1334   return (GNUNET_OK ==
1335           GNUNET_SERVICE_run (argc, argv, "vpn", 
1336                               GNUNET_SERVICE_OPTION_NONE,
1337                               &run, NULL)) ? 0 : 1;
1338 }
1339
1340 /* end of gnunet-service-vpn.c */