2 This file is part of GNUnet.
3 (C) 2010 Christian Grothoff
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.
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.
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.
22 * @file vpn/gnunet-daemon-vpn.c
23 * @brief the helper for various vpn-daemons. Opens a virtual network-interface,
24 * sends data received on the if to stdout, sends data received on stdin to the
26 * @author Philipp Tölke
29 #include <linux/if_tun.h>
32 * Need 'struct GNUNET_MessageHeader'.
34 #include "gnunet_common.h"
37 * Need VPN message types.
39 #include "gnunet_protocols.h"
42 * Maximum size of a GNUnet message (GNUNET_SERVER_MAX_MESSAGE_SIZE)
44 #define MAX_SIZE 65536
48 * This is in linux/include/net/ipv6.h, but not always exported...
52 struct in6_addr ifr6_addr;
53 uint32_t ifr6_prefixlen;
54 unsigned int ifr6_ifindex;
60 * Creates a tun-interface called dev;
61 * @param dev is asumed to point to a char[IFNAMSIZ]
62 * if *dev == '\0', uses the name supplied by the kernel
63 * @return the fd to the tun or -1 on error
77 if (-1 == (fd = open("/dev/net/tun", O_RDWR)))
80 "Error opening `%s': %s\n",
86 memset(&ifr, 0, sizeof(ifr));
87 ifr.ifr_flags = IFF_TUN;
90 strncpy(ifr.ifr_name, dev, IFNAMSIZ);
92 if (-1 == ioctl(fd, TUNSETIFF, (void *) &ifr))
95 "Error with ioctl on `%s': %s\n",
101 strcpy(dev, ifr.ifr_name);
107 * @brief Sets the IPv6-Address given in address on the interface dev
109 * @param dev the interface to configure
110 * @param address the IPv6-Address
111 * @param prefix_len the length of the network-prefix
114 set_address6 (const char *dev,
116 unsigned long prefix_len)
119 struct in6_ifreq ifr6;
120 struct sockaddr_in6 sa6;
123 if (-1 == (fd = socket (PF_INET6, SOCK_DGRAM, 0)))
126 "Error creating socket: %s\n",
130 memset (&sa6, 0, sizeof (struct sockaddr_in6));
131 sa6.sin6_family = AF_INET6;
133 if (1 != inet_pton (AF_INET6, address, sa6.sin6_addr.s6_addr))
136 "Failed to parse address `%s': %s\n",
142 memcpy (&ifr6.ifr6_addr,
144 sizeof (struct in6_addr));
145 strncpy (ifr.ifr_name, dev, IFNAMSIZ);
146 if (-1 == ioctl (fd, SIOGIFINDEX, &ifr))
149 "ioctl failed at %d: %s\n",
155 ifr6.ifr6_ifindex = ifr.ifr_ifindex;
156 ifr6.ifr6_prefixlen = prefix_len;
157 if (-1 == ioctl (fd, SIOCSIFADDR, &ifr6))
160 "ioctl failed at line %d: %s\n",
166 if (-1 == ioctl (fd, SIOCGIFFLAGS, &ifr))
169 "ioctl failed at line %d: %s\n",
174 ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
175 if (-1 == ioctl (fd, SIOCSIFFLAGS, &ifr))
178 "ioctl failed at line %d: %s\n",
187 "close failed: %s\n",
195 * @brief Sets the IPv4-Address given in address on the interface dev
197 * @param dev the interface to configure
198 * @param address the IPv4-Address
199 * @param mask the netmask
202 set_address4 (char *dev, char *address, char *mask)
205 struct sockaddr_in *addr;
208 memset (&ifr, 0, sizeof (struct ifreq));
209 addr = (struct sockaddr_in *) &(ifr.ifr_addr);
210 memset (addr, 0, sizeof (struct sockaddr_in));
211 addr->sin_family = AF_INET;
212 addr->sin_addr.s_addr = inet_addr (address);
214 int r = inet_pton (AF_INET, address, &addr->sin_addr.s_addr);
217 fprintf (stderr, "error at inet_pton: %m\n");
221 fd = socket (PF_INET, SOCK_DGRAM, 0);
228 strncpy (ifr.ifr_name, dev, IFNAMSIZ);
230 if (ioctl (fd, SIOCSIFADDR, &ifr) != 0)
232 perror ("SIOCSIFADDR");
237 addr = (struct sockaddr_in *) &(ifr.ifr_netmask);
238 r = inet_pton (AF_INET, mask, &addr->sin_addr.s_addr);
241 fprintf (stderr, "error at inet_pton: %m\n");
245 if (ioctl (fd, SIOCSIFNETMASK, &ifr) != 0)
247 perror ("SIOCSIFNETMASK");
252 (void) ioctl (fd, SIOCGIFFLAGS, &ifr);
253 ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
254 (void) ioctl (fd, SIOCSIFFLAGS, &ifr);
262 unsigned char buf[MAX_SIZE];
267 int write_fd_possible = 0;
268 int write_stdout_possible = 0;
271 while ((1 == rea) || (1 == wri))
278 FD_SET (fd_tun, &fds_r);
279 if (!write_stdout_possible)
286 if (!write_fd_possible)
287 FD_SET (fd_tun, &fds_w);
290 int r = select (fd_tun + 1, &fds_r, &fds_w, NULL, NULL);
291 /* FIXME: if error... */
294 if (FD_ISSET (fd_tun, &fds_w))
295 write_fd_possible = 1;
296 if (FD_ISSET (1, &fds_w))
297 write_stdout_possible = 1;
299 if (FD_ISSET (0, &fds_r) && write_fd_possible)
301 write_fd_possible = 0;
302 struct GNUNET_MessageHeader *pkt = ( struct GNUNET_MessageHeader *) buf;
303 tin = read (0, buf, sizeof (struct GNUNET_MessageHeader));
306 fprintf (stderr, "read-error: %s\n", strerror (errno));
307 shutdown (fd_tun, SHUT_WR);
308 shutdown (0, SHUT_RD);
312 if (pkt->type != ntohs (GNUNET_MESSAGE_TYPE_VPN_HELPER))
314 while (tin < ntohs (pkt->size))
316 ssize_t t = read (0, buf + tin, ntohs (pkt->size) - tin);
319 fprintf (stderr, "read-error: %s\n", strerror (errno));
320 shutdown (fd_tun, SHUT_WR);
321 shutdown (0, SHUT_RD);
330 sizeof (struct GNUNET_MessageHeader))
332 ssize_t t = write (fd_tun, &pkt[1],
334 sizeof (struct GNUNET_MessageHeader) - tin);
337 fprintf (stderr, "write-error 3: %s\n",
339 shutdown (fd_tun, SHUT_WR);
340 shutdown (0, SHUT_RD);
347 else if (write_stdout_possible && FD_ISSET (fd_tun, &fds_r))
349 write_stdout_possible = 0;
350 tin = read (fd_tun, buf, MAX_SIZE);
353 fprintf (stderr, "read-error: %s\n", strerror (errno));
354 shutdown (fd_tun, SHUT_RD);
355 shutdown (1, SHUT_WR);
359 struct GNUNET_MessageHeader hdr = {.size =
360 htons (r + sizeof (struct GNUNET_MessageHeader)),.type =
361 htons (GNUNET_MESSAGE_TYPE_VPN_HELPER)
364 while (tin < sizeof (struct GNUNET_MessageHeader))
367 write (1, &hdr, sizeof (struct GNUNET_MessageHeader) - tin);
370 fprintf (stderr, "write-error 2: %s\n",
372 shutdown (fd_tun, SHUT_RD);
373 shutdown (1, SHUT_WR);
379 while (tin < ntohs (hdr.size))
381 size_t t = write (1, buf, ntohs (hdr.size) - tin);
384 fprintf (stderr, "write-error 1: %s, written %d/%d\n",
385 strerror (errno), r, ntohs (hdr.size));
386 shutdown (fd_tun, SHUT_RD);
387 shutdown (1, SHUT_WR);
406 memset (dev, 0, IFNAMSIZ);
407 if (-1 == (fd_tun = init_tun (dev)))
410 "Fatal: could not initialize tun-interface\n");
415 // TODO: get this out of argv
416 char address[] = "1234::1";
417 unsigned long prefix_len = 16;
419 set_address6 (dev, address, prefix_len);
423 char address[] = "10.10.10.1";
424 char mask[] = "255.255.255.252";
426 set_address4 (dev, address, mask);
429 uid_t uid = getuid ();
430 if (0 != setresuid (uid, uid, uid))
432 "Failed to setresuid: %s\n",