aboutsummaryrefslogtreecommitdiff
path: root/src/vpn/gnunet-helper-vpn.c
diff options
context:
space:
mode:
authorPhilipp Tölke <toelke@in.tum.de>2010-07-30 23:34:42 +0000
committerPhilipp Tölke <toelke@in.tum.de>2010-07-30 23:34:42 +0000
commit1aa2bb86a17b273e373cb58155488cdb9eed93c7 (patch)
tree0afde4426f22ad90c71a3cf03185c3c976209046 /src/vpn/gnunet-helper-vpn.c
parentaf0af530e6800e0c8f49d95931676506ab587830 (diff)
downloadgnunet-1aa2bb86a17b273e373cb58155488cdb9eed93c7.tar.gz
gnunet-1aa2bb86a17b273e373cb58155488cdb9eed93c7.zip
renamed the vpn-helper to fit into the scheme gnunet-FUNCTION-SUBSYSTEM
Diffstat (limited to 'src/vpn/gnunet-helper-vpn.c')
-rw-r--r--src/vpn/gnunet-helper-vpn.c246
1 files changed, 246 insertions, 0 deletions
diff --git a/src/vpn/gnunet-helper-vpn.c b/src/vpn/gnunet-helper-vpn.c
new file mode 100644
index 000000000..4a75182f9
--- /dev/null
+++ b/src/vpn/gnunet-helper-vpn.c
@@ -0,0 +1,246 @@
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#define _GNU_SOURCE
27#include <arpa/inet.h>
28#include <linux/if.h>
29
30#include <fcntl.h>
31
32#include <sys/types.h>
33#include <sys/socket.h>
34#include <sys/ioctl.h>
35
36#include <string.h>
37
38#include <signal.h>
39
40#include <stdio.h>
41#include <unistd.h>
42
43#include "gnunet-vpn-tun.h"
44#include "gnunet_common.h"
45#include "gnunet_protocols.h"
46#include "gnunet-vpn-helper-p.h"
47
48#ifndef _LINUX_IN6_H
49// This is in linux/include/net/ipv6.h.
50
51#define MAX_SIZE (65535 - sizeof(struct GNUNET_MessageHeader))
52
53struct in6_ifreq {
54 struct in6_addr ifr6_addr;
55 __u32 ifr6_prefixlen;
56 unsigned int ifr6_ifindex;
57};
58
59#endif
60
61int running = 1;
62
63void term(int sig) {
64 fprintf(stderr, "Got SIGTERM...\n");
65 if (sig == SIGTERM)
66 running = 0;
67}
68
69static void set_address(char* dev, char* address, unsigned long prefix_len) { /* {{{ */
70 int fd = socket(AF_INET6, SOCK_DGRAM, 0);
71
72 struct ifreq ifr;
73 struct in6_ifreq ifr6;
74
75 struct sockaddr_in6 sa6;
76 memset(&sa6, 0, sizeof(struct sockaddr_in6));
77
78 sa6.sin6_family = AF_INET6;
79
80 /* FIXME */ inet_pton(AF_INET6, address, sa6.sin6_addr.s6_addr);
81
82 memcpy((char *) &ifr6.ifr6_addr, (char *) &sa6.sin6_addr, sizeof(struct in6_addr));
83
84 strncpy(ifr.ifr_name, dev, IFNAMSIZ);
85
86 if (ioctl(fd, SIOGIFINDEX, &ifr) < 0) {
87 perror("SIOGIFINDEX");
88 }
89
90 ifr6.ifr6_ifindex = ifr.ifr_ifindex;
91 ifr6.ifr6_prefixlen = prefix_len;
92
93 if (ioctl(fd, SIOCSIFADDR, &ifr6) < 0) {
94 perror("SIOCSIFADDR");
95 }
96
97 /* FIXME */ ioctl(fd, SIOCGIFFLAGS, &ifr);
98 ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
99 /* FIXME */ ioctl(fd, SIOCSIFFLAGS, &ifr);
100} /* }}} */
101
102void setnonblocking(int fd) {/*{{{*/
103 int opts;
104
105 opts = fcntl(fd,F_GETFL);
106 if (opts < 0) {
107 perror("fcntl(F_GETFL)");
108 }
109 opts = (opts | O_NONBLOCK);
110 if (fcntl(fd,F_SETFL,opts) < 0) {
111 perror("fcntl(F_SETFL)");
112 }
113 return;
114}/*}}}*/
115
116int main(int argc, char** argv) {
117 unsigned char buf[MAX_SIZE];
118
119 char dev[IFNAMSIZ];
120 memset(dev, 0, IFNAMSIZ);
121
122 signal(SIGTERM, &term);
123
124 int fd_tun = init_tun(dev);
125 fprintf(stderr, "Initialized the interface %s as %d.\n", dev, fd_tun);
126
127 // TODO: get this out of argv
128 char address[] = "1234::1";
129 unsigned long prefix_len = 16;
130
131 set_address(dev, address, prefix_len);
132
133 uid_t uid = getuid ();
134 if (setresuid (uid, uid, uid) != 0 )
135 fprintf (stderr, "Failed to setresuid: %m\n");
136
137 setnonblocking(0);
138 setnonblocking(1);
139 setnonblocking(fd_tun);
140
141 fd_set fds_w;
142 fd_set fds_r;
143
144 int rea = 1;
145 int wri = 1;
146
147 int write_fd_possible = 0;
148 int write_stdout_possible = 0;
149outer:
150 while((rea == 1 || wri == 1) && running == 1) {
151 FD_ZERO(&fds_w);
152 FD_ZERO(&fds_r);
153
154 if (rea) {
155 FD_SET(fd_tun, &fds_r);
156 if (!write_stdout_possible)
157 FD_SET(1, &fds_w);
158 }
159
160 if (wri) {
161 FD_SET(0, &fds_r);
162 if (!write_fd_possible)
163 FD_SET(fd_tun, &fds_w);
164 }
165
166 int r = select(fd_tun+1, &fds_r, &fds_w, (fd_set*)0, 0);
167
168 if(r > 0) {
169 if (FD_ISSET(fd_tun, &fds_w)) write_fd_possible = 1;
170 if (FD_ISSET(1, &fds_w)) write_stdout_possible = 1;
171
172 if (FD_ISSET(0, &fds_r) && write_fd_possible) {
173 write_fd_possible = 0;
174 struct suid_packet *pkt = (struct suid_packet*) buf;
175 r = read(0, buf, sizeof(struct GNUNET_MessageHeader));
176 if (r <= 0) {
177 fprintf(stderr, "read-error: %m\n");
178 shutdown(fd_tun, SHUT_WR);
179 shutdown(0, SHUT_RD);
180 wri=0;
181 goto outer;
182 }
183 while (r < ntohs(pkt->hdr.size)) {
184 int t = read(0, buf + r, ntohs(pkt->hdr.size) - r);
185 if (r < 0) {
186 fprintf(stderr, "read-error: %m\n");
187 shutdown(fd_tun, SHUT_WR);
188 shutdown(0, SHUT_RD);
189 wri=0;
190 goto outer;
191 }
192 r += t;
193 }
194 r = 0;
195 while (r < ntohs(pkt->hdr.size) - sizeof(struct GNUNET_MessageHeader)) {
196 int t = write(fd_tun, pkt->data, ntohs(pkt->hdr.size) - sizeof(struct GNUNET_MessageHeader) - r);
197 if (t < 0) {
198 fprintf(stderr, "write-error 3: %m\n");
199 shutdown(fd_tun, SHUT_WR);
200 shutdown(0, SHUT_RD);
201 wri = 0;
202 goto outer;
203 }
204 r += t;
205 }
206 } else if (write_stdout_possible && FD_ISSET(fd_tun, &fds_r)) {
207 write_stdout_possible = 0;
208 r = read(fd_tun, buf, MAX_SIZE);
209 if (r <= 0) {
210 fprintf(stderr, "read-error: %m\n");
211 shutdown(fd_tun, SHUT_RD);
212 shutdown(1, SHUT_WR);
213 rea = 0;
214 goto outer;
215 }
216 struct GNUNET_MessageHeader hdr = { .size = htons(r + sizeof(struct GNUNET_MessageHeader)), .type = htons(GNUNET_MESSAGE_TYPE_VPN_HELPER) };
217 r = 0;
218 while(r < sizeof(struct GNUNET_MessageHeader)) {
219 int t = write(1, &hdr, sizeof(struct GNUNET_MessageHeader) - r);
220 if (t < 0) {
221 fprintf(stderr, "write-error 2: %m\n");
222 shutdown(fd_tun, SHUT_RD);
223 shutdown(1, SHUT_WR);
224 rea = 0;
225 goto outer;
226 }
227 r += t;
228 }
229 while(r < ntohs(hdr.size)) {
230 int t = write(1, buf, ntohs(hdr.size) - r);
231 if (t < 0) {
232 fprintf(stderr, "write-error 1: %m, written %d/%d\n", r, ntohs(hdr.size));
233 shutdown(fd_tun, SHUT_RD);
234 shutdown(1, SHUT_WR);
235 rea = 0;
236 goto outer;
237 }
238 r += t;
239 }
240 }
241 }
242 }
243 fprintf(stderr, "Quitting!\n");
244
245 return 0;
246}