Changed the communication between the vpn-helper and the daemon to use GNUNET_Message...
[oweals/gnunet.git] / src / vpn / gnunet-daemon-vpn.c
1 /*
2      This file is part of GNUnet.
3      (C) 2010 Christian Grothoff
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file vpn/gnunet-daemon-vpn.c
23  * @brief 
24  * @author Philipp Tölke
25  */
26 #include "platform.h"
27 #include "gnunet_getopt_lib.h"
28 #include "gnunet_program_lib.h"
29 #include "gnunet_os_lib.h"
30 #include "gnunet-vpn-helper-p.h"
31 #include "gnunet-vpn-packet.h"
32 #include "gnunet-vpn-pretty-print.h"
33 #include "gnunet_common.h"
34 #include "gnunet_protocols.h"
35 /* #include "gnunet_template_service.h" */
36
37 /**
38  * Final status code.
39  */
40 static int ret;
41
42 struct vpn_cls {
43         struct GNUNET_DISK_PipeHandle* helper_in;
44         struct GNUNET_DISK_PipeHandle* helper_out;
45         const struct GNUNET_DISK_FileHandle* fh_from_helper;
46
47         struct GNUNET_SCHEDULER_Handle *sched;
48
49         pid_t helper_pid;
50 };
51
52 static void cleanup(void* cls, const struct GNUNET_SCHEDULER_TaskContext* tskctx) {
53         struct vpn_cls* mycls = (struct vpn_cls*) cls;
54         if (tskctx->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) {
55                 PLIBC_KILL(mycls->helper_pid, SIGTERM);
56                 GNUNET_OS_process_wait(mycls->helper_pid);
57         }
58 }
59
60 static void helper_read(void* cls, const struct GNUNET_SCHEDULER_TaskContext* tsdkctx);
61
62 static void start_helper_and_schedule(struct vpn_cls* mycls) {
63         mycls->helper_in = GNUNET_DISK_pipe(1);
64         mycls->helper_out = GNUNET_DISK_pipe(1);
65
66         mycls->helper_pid = GNUNET_OS_start_process(mycls->helper_in, mycls->helper_out, "gnunet-vpn-helper", "gnunet-vpn-helper", NULL);
67
68         mycls->fh_from_helper = GNUNET_DISK_pipe_handle (mycls->helper_out, GNUNET_DISK_PIPE_END_READ);
69
70         GNUNET_DISK_pipe_close_end(mycls->helper_out, GNUNET_DISK_PIPE_END_WRITE);
71         GNUNET_DISK_pipe_close_end(mycls->helper_in, GNUNET_DISK_PIPE_END_READ);
72
73         GNUNET_SCHEDULER_add_read_file (mycls->sched, GNUNET_TIME_UNIT_FOREVER_REL, mycls->fh_from_helper, &helper_read, mycls);
74 }
75
76
77 static void restart_helper(void* cls, const struct GNUNET_SCHEDULER_TaskContext* tskctx) {
78         struct vpn_cls* mycls = (struct vpn_cls*) cls;
79
80         // Kill the helper
81         PLIBC_KILL(mycls->helper_pid, SIGTERM);
82         GNUNET_OS_process_wait(mycls->helper_pid);
83
84         // Restart the helper
85         start_helper_and_schedule(mycls);
86
87 }
88
89 static void helper_read(void* cls, const struct GNUNET_SCHEDULER_TaskContext* tsdkctx) {
90         struct vpn_cls* mycls = (struct vpn_cls*) cls;
91         struct GNUNET_MessageHeader hdr = { .size = 0, .type = 0 };
92
93         int r = 0;
94
95         if (tsdkctx->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)
96                 return;
97
98         while (r < sizeof(struct GNUNET_MessageHeader)) {
99                 int t = GNUNET_DISK_file_read(mycls->fh_from_helper, &hdr, sizeof(struct GNUNET_MessageHeader));
100                 if (t<=0) {
101                         fprintf(stderr, "Read error for header: %m\n");
102                         GNUNET_SCHEDULER_add_now(mycls->sched, restart_helper, cls);
103                         return;
104                 }
105                 r += t;
106         }
107
108         struct suid_packet *pkt = (struct suid_packet*) GNUNET_malloc(ntohs(hdr.size));
109
110         memcpy(pkt, &hdr, sizeof(struct GNUNET_MessageHeader));
111
112         while (r < ntohs(pkt->hdr.size)) {
113                 int t = GNUNET_DISK_file_read(mycls->fh_from_helper, (unsigned char*)pkt + r, ntohs(pkt->hdr.size) - r);
114                 if (t<=0) {
115                         fprintf(stderr, "Read error for data: %m\n");
116                         GNUNET_SCHEDULER_add_now(mycls->sched, restart_helper, cls);
117                         return;
118                 }
119                 r += t;
120         }
121
122         struct ip6_pkt *pkt6 = (struct ip6_pkt*) pkt;
123         struct ip6_tcp *pkt6_tcp;
124         struct ip6_udp *pkt6_udp;
125
126         pkt_printf(pkt6);
127         switch(pkt6->ip6_hdr.nxthdr) {
128                 case 0x06:
129                         pkt6_tcp = (struct ip6_tcp*)pkt6;
130                         pkt_printf_ip6tcp(pkt6_tcp);
131                         break;
132                 case 0x11:
133                         pkt6_udp = (struct ip6_udp*)pkt6;
134                         pkt_printf_ip6udp(pkt6_udp);
135                         if (ntohs(pkt6_udp->udp_hdr.dpt) == 53) {
136                                 pkt_printf_ip6dns((struct ip6_udp_dns*)pkt6_udp);
137                         }
138                         break;
139         }
140
141         GNUNET_free(pkt);
142
143         GNUNET_SCHEDULER_add_read_file (mycls->sched, GNUNET_TIME_UNIT_FOREVER_REL, mycls->fh_from_helper, &helper_read, mycls);
144 }
145
146 /**
147  * Main function that will be run by the scheduler.
148  *
149  * @param cls closure
150  * @param sched the scheduler to use
151  * @param args remaining command-line arguments
152  * @param cfgfile name of the configuration file used (for saving, can be NULL!)
153  * @param cfg configuration
154  */
155 static void
156 run (void *cls,
157                 struct GNUNET_SCHEDULER_Handle *sched,
158                 char *const *args,
159                 const char *cfgfile,
160                 const struct GNUNET_CONFIGURATION_Handle *cfg) {
161
162         struct vpn_cls* mycls = (struct vpn_cls*) cls;
163
164         mycls->sched = sched;
165
166         GNUNET_SCHEDULER_add_delayed(sched, GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
167
168         start_helper_and_schedule(mycls);
169 }
170
171
172 /**
173  * The main function to obtain template from gnunetd.
174  *
175  * @param argc number of arguments from the command line
176  * @param argv command line arguments
177  * @return 0 ok, 1 on error
178  */
179 int
180 main (int argc, char *const *argv)
181 {
182   static const struct GNUNET_GETOPT_CommandLineOption options[] = {
183     GNUNET_GETOPT_OPTION_END
184   };
185
186   struct vpn_cls* cls = (struct vpn_cls*)malloc(sizeof(struct vpn_cls));
187
188   return (GNUNET_OK ==
189           GNUNET_PROGRAM_run (argc,
190                               argv,
191                               "gnunet-daemon-vpn",
192                               gettext_noop ("help text"),
193                               options, &run, cls)) ? ret : 1;
194 }
195
196 /* end of gnunet-daemon-vpn.c */