fix
[oweals/gnunet.git] / src / vpn / gnunet-daemon-vpn-helper.c
index 8c4eb593d21474425d5542185d474322b1c980e2..a270600145eb11ba7650a288f940ab05e431dc58 100644 (file)
 #include <gnunet_common.h>
 #include <gnunet_client_lib.h>
 #include <gnunet_os_lib.h>
-#include <gnunet_core_service.h>
+#include <gnunet_mesh_service.h>
 #include <gnunet_protocols.h>
 #include <gnunet_server_lib.h>
 #include <gnunet_container_lib.h>
 #include <block_dns.h>
+#include <gnunet_configuration_lib.h>
 
 #include "gnunet-daemon-vpn-dns.h"
 #include "gnunet-daemon-vpn.h"
 #include "gnunet-service-dns-p.h"
 #include "gnunet-vpn-packet.h"
 
-/**
- * PipeHandle to receive data from the helper
- */
-static struct GNUNET_DISK_PipeHandle* helper_in;
-
-/**
- * PipeHandle to send data to the helper
- */
-static struct GNUNET_DISK_PipeHandle* helper_out;
-
-/**
- * FileHandle to receive data from the helper
- */
-static const struct GNUNET_DISK_FileHandle* fh_from_helper;
-
-/**
- * FileHandle to send data to the helper
- */
-static const struct GNUNET_DISK_FileHandle* fh_to_helper;
+struct GNUNET_VPN_HELPER_Handle *helper_handle;
 
 /**
  * Start the helper-process
+ *
+ * If cls != NULL it is assumed that this function is called as a result of a dying
+ * helper. cls is then taken as handle to the old helper and is cleaned up.
  * {{{
  */
 void
@@ -69,72 +55,73 @@ start_helper_and_schedule(void *cls,
     if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
       return;
 
-    helper_in = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO);
-    helper_out = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_NO, GNUNET_YES);
+    if (cls != NULL)
+      cleanup_helper(cls);
+    cls = NULL;
+
+    char* ifname;
+    char* ipv6addr;
+    char* ipv6prefix;
+    char* ipv4addr;
+    char* ipv4mask;
 
-    if (helper_in == NULL || helper_out == NULL) return;
+    if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, "vpn", "IFNAME", &ifname))
+      {
+       GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "No entry 'IFNAME' in configuration!\n");
+       exit(1);
+      }
+
+    if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, "vpn", "IPV6ADDR", &ipv6addr))
+      {
+       GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "No entry 'IPV6ADDR' in configuration!\n");
+       exit(1);
+      }
+
+    if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, "vpn", "IPV6PREFIX", &ipv6prefix))
+      {
+       GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "No entry 'IPV6PREFIX' in configuration!\n");
+       exit(1);
+      }
 
-    helper_proc = GNUNET_OS_start_process(helper_in, helper_out, "gnunet-helper-vpn", "gnunet-helper-vpn", NULL);
+    if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, "vpn", "IPV4ADDR", &ipv4addr))
+      {
+       GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "No entry 'IPV4ADDR' in configuration!\n");
+       exit(1);
+      }
 
-    fh_from_helper = GNUNET_DISK_pipe_handle (helper_out, GNUNET_DISK_PIPE_END_READ);
-    fh_to_helper = GNUNET_DISK_pipe_handle (helper_in, GNUNET_DISK_PIPE_END_WRITE);
+    if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, "vpn", "IPV4MASK", &ipv4mask))
+      {
+       GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "No entry 'IPV4MASK' in configuration!\n");
+       exit(1);
+      }
 
-    GNUNET_DISK_pipe_close_end(helper_out, GNUNET_DISK_PIPE_END_WRITE);
-    GNUNET_DISK_pipe_close_end(helper_in, GNUNET_DISK_PIPE_END_READ);
+    /* Start the helper
+     * Messages get passed to the function message_token
+     * When the helper dies, this function will be called again with the
+     * helper_handle as cls.
+     */
+    helper_handle = start_helper(ifname,
+                                ipv6addr,
+                                ipv6prefix,
+                                ipv4addr,
+                                ipv4mask,
+                                "vpn-gnunet",
+                                start_helper_and_schedule,
+                                message_token,
+                                NULL,
+                                NULL);
+
+    GNUNET_free(ipv6addr);
+    GNUNET_free(ipv6prefix);
+    GNUNET_free(ipv4addr);
+    GNUNET_free(ipv4mask);
+    GNUNET_free(ifname);
 
     /* Tell the dns-service to rehijack the dns-port
      * The routing-table gets flushed if an interface disappears.
      */
     restart_hijack = 1;
     GNUNET_CLIENT_notify_transmit_ready(dns_connection, sizeof(struct GNUNET_MessageHeader), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, &send_query, NULL);
-
-    GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, fh_from_helper, &helper_read, NULL);
-}
-/*}}}*/
-/**
- * Restart the helper-process
- * {{{
- */
-void
-restart_helper(void* cls, const struct GNUNET_SCHEDULER_TaskContext* tskctx) {
-    // Kill the helper
-    GNUNET_OS_process_kill (helper_proc, SIGKILL);
-    GNUNET_OS_process_wait (helper_proc);
-    GNUNET_OS_process_close (helper_proc);
-    helper_proc = NULL;
-
-    GNUNET_DISK_pipe_close(helper_in);
-    GNUNET_DISK_pipe_close(helper_out);
-
-    /* Restart the helper */
-    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, start_helper_and_schedule, NULL);
-}
-/*}}}*/
-
-/**
- * Read from the helper-process
- * {{{
- */
-void
-helper_read(void* cls, const struct GNUNET_SCHEDULER_TaskContext* tsdkctx) {
-    /* no message can be bigger then 64k */
-    char buf[65535];
-
-    if (tsdkctx->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)
-      return;
-
-    int t = GNUNET_DISK_file_read(fh_from_helper, &buf, 65535);
-
-    /* On read-error, restart the helper */
-    if (t<=0) {
-       GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Read error for header from vpn-helper: %m\n");
-       GNUNET_SCHEDULER_add_now(restart_helper, cls);
-       return;
-    }
-
-    /* FIXME */ GNUNET_SERVER_mst_receive(mst, NULL, buf, t, 0, 0);
-
-    GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, fh_from_helper, &helper_read, NULL);
 }
 /*}}}*/
 
@@ -196,12 +183,12 @@ helper_write(void* cls, const struct GNUNET_SCHEDULER_TaskContext* tsdkctx) {
     GNUNET_CONTAINER_DLL_remove (answer_proc_head, answer_proc_tail, ans);
     GNUNET_free(ans);
 
-    /* FIXME */ GNUNET_DISK_file_write(fh_to_helper, pkt, pkt_len);
+    /* FIXME */ GNUNET_DISK_file_write(helper_handle->fh_to_helper, pkt, pkt_len);
 
     /* if more packets are available, reschedule */
     if (answer_proc_head != NULL)
       GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
-                                      fh_to_helper,
+                                      helper_handle->fh_to_helper,
                                       &helper_write,
                                       NULL);
 }
@@ -243,18 +230,30 @@ message_token(void *cls,
                    (port_in_ports(me->desc.ports, pkt6_udp->udp_hdr.dpt) ||
                     port_in_ports(me->additional_ports, pkt6_udp->udp_hdr.dpt)))
                  {
-                   size_t size = sizeof(struct GNUNET_PeerIdentity) + sizeof(struct GNUNET_MessageHeader) + sizeof(GNUNET_HashCode) + ntohs(pkt6_udp->udp_hdr.len);
-                   struct GNUNET_PeerIdentity *cls = GNUNET_malloc(size);
+                   size_t size = sizeof(struct GNUNET_MESH_Tunnel*) + sizeof(struct GNUNET_MessageHeader) + sizeof(GNUNET_HashCode) + ntohs(pkt6_udp->udp_hdr.len);
+                   struct GNUNET_MESH_Tunnel **cls = GNUNET_malloc(size);
                    struct GNUNET_MessageHeader *hdr = (struct GNUNET_MessageHeader*)(cls+1);
                    GNUNET_HashCode* hc = (GNUNET_HashCode*)(hdr + 1);
-                   memcpy(cls, &me->desc.peer, sizeof(struct GNUNET_PeerIdentity));
+
                    memcpy(hc, &me->desc.service_descriptor, sizeof(GNUNET_HashCode));
                    memcpy(hc+1, &pkt6_udp->udp_hdr, ntohs(pkt6_udp->udp_hdr.len));
-                   GNUNET_CORE_peer_request_connect(core_handle,
-                                       GNUNET_TIME_UNIT_FOREVER_REL,
-                                       (struct GNUNET_PeerIdentity*)&me->desc.peer,
-                                       send_udp_to_peer,
-                                       cls);
+
+                   if (me->tunnel == NULL)
+                     {
+                       *cls = GNUNET_MESH_peer_request_connect_all(mesh_handle,
+                                                                   GNUNET_TIME_UNIT_FOREVER_REL,
+                                                                   1,
+                                                                   (struct GNUNET_PeerIdentity*)&me->desc.peer,
+                                                                   send_udp_to_peer,
+                                                                   NULL,
+                                                                   cls);
+                       me->tunnel = *cls;
+                     }
+                   else
+                     {
+                       *cls = me->tunnel;
+                       send_udp_to_peer(cls, (struct GNUNET_PeerIdentity*)1, NULL);
+                     }
                    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Queued to send to peer %x\n", *((unsigned int*)&me->desc.peer));
                  }
              }
@@ -311,10 +310,10 @@ message_token(void *cls,
 
 void write_to_helper(void* buf, size_t len)
 {
-  (void)GNUNET_DISK_file_write(fh_to_helper, buf, len);
+  (void)GNUNET_DISK_file_write(helper_handle->fh_to_helper, buf, len);
 }
 
 void schedule_helper_write(struct GNUNET_TIME_Relative time, void* cls)
 {
-  GNUNET_SCHEDULER_add_write_file (time, fh_to_helper, &helper_write, cls);
+  GNUNET_SCHEDULER_add_write_file (time, helper_handle->fh_to_helper, &helper_write, cls);
 }