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;
59 * Creates a tun-interface called dev;
60 * @param dev is asumed to point to a char[IFNAMSIZ]
61 * if *dev == '\\0', uses the name supplied by the kernel
62 * @return the fd to the tun or -1 on error
76 if (-1 == (fd = open ("/dev/net/tun", O_RDWR)))
79 "Error opening `%s': %s\n", "/dev/net/tun", strerror (errno));
85 fprintf (stderr, "Filedescriptor to large: %d", fd);
89 memset (&ifr, 0, sizeof (ifr));
90 ifr.ifr_flags = IFF_TUN;
93 strncpy (ifr.ifr_name, dev, IFNAMSIZ);
95 if (-1 == ioctl (fd, TUNSETIFF, (void *) &ifr))
98 "Error with ioctl on `%s': %s\n",
99 "/dev/net/tun", strerror (errno));
103 strcpy (dev, ifr.ifr_name);
109 * @brief Sets the IPv6-Address given in address on the interface dev
111 * @param dev the interface to configure
112 * @param address the IPv6-Address
113 * @param prefix_len the length of the network-prefix
116 set_address6 (const char *dev, const char *address, unsigned long prefix_len)
119 struct in6_ifreq ifr6;
120 struct sockaddr_in6 sa6;
123 if (-1 == (fd = socket (PF_INET6, SOCK_DGRAM, 0)))
125 fprintf (stderr, "Error creating socket: %s\n", strerror (errno));
128 memset (&sa6, 0, sizeof (struct sockaddr_in6));
129 sa6.sin6_family = AF_INET6;
132 * parse the new address
134 if (1 != inet_pton (AF_INET6, address, sa6.sin6_addr.s6_addr))
137 "Failed to parse address `%s': %s\n",
138 address, strerror (errno));
141 memcpy (&ifr6.ifr6_addr, &sa6.sin6_addr, sizeof (struct in6_addr));
145 * Get the index of the if
147 strncpy (ifr.ifr_name, dev, IFNAMSIZ);
148 if (-1 == ioctl (fd, SIOGIFINDEX, &ifr))
151 "ioctl failed at %d: %s\n", __LINE__, strerror (errno));
154 ifr6.ifr6_ifindex = ifr.ifr_ifindex;
156 ifr6.ifr6_prefixlen = prefix_len;
161 if (-1 == ioctl (fd, SIOCSIFADDR, &ifr6))
164 "ioctl failed at line %d: %s\n", __LINE__, strerror (errno));
171 if (-1 == ioctl (fd, SIOCGIFFLAGS, &ifr))
174 "ioctl failed at line %d: %s\n", __LINE__, strerror (errno));
179 * Add the UP and RUNNING flags
181 ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
182 if (-1 == ioctl (fd, SIOCSIFFLAGS, &ifr))
185 "ioctl failed at line %d: %s\n", __LINE__, strerror (errno));
191 fprintf (stderr, "close failed: %s\n", strerror (errno));
198 * @brief Sets the IPv4-Address given in address on the interface dev
200 * @param dev the interface to configure
201 * @param address the IPv4-Address
202 * @param mask the netmask
205 set_address4 (char *dev, char *address, char *mask)
208 struct sockaddr_in *addr;
211 memset (&ifr, 0, sizeof (struct ifreq));
212 addr = (struct sockaddr_in *) &(ifr.ifr_addr);
213 memset (addr, 0, sizeof (struct sockaddr_in));
214 addr->sin_family = AF_INET;
215 addr->sin_addr.s_addr = inet_addr (address);
220 int r = inet_pton (AF_INET, address, &addr->sin_addr.s_addr);
223 fprintf (stderr, "error at inet_pton: %m\n");
227 fd = socket (PF_INET, SOCK_DGRAM, 0);
234 strncpy (ifr.ifr_name, dev, IFNAMSIZ);
239 if (ioctl (fd, SIOCSIFADDR, &ifr) != 0)
241 perror ("SIOCSIFADDR");
249 addr = (struct sockaddr_in *) &(ifr.ifr_netmask);
250 r = inet_pton (AF_INET, mask, &addr->sin_addr.s_addr);
253 fprintf (stderr, "error at inet_pton: %m\n");
260 if (ioctl (fd, SIOCSIFNETMASK, &ifr) != 0)
262 perror ("SIOCSIFNETMASK");
270 if (-1 == ioctl (fd, SIOCGIFFLAGS, &ifr))
273 "ioctl failed at line %d: %s\n", __LINE__, strerror (errno));
278 * Add the UP and RUNNING flags
280 ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
281 if (-1 == ioctl (fd, SIOCSIFFLAGS, &ifr))
284 "ioctl failed at line %d: %s\n", __LINE__, strerror (errno));
290 fprintf (stderr, "close failed: %s\n", strerror (errno));
300 * The buffer filled by reading from fd_tun
302 unsigned char buftun[MAX_SIZE];
303 ssize_t buftun_size = 0;
304 unsigned char *buftun_read;
307 * The buffer filled by reading from stdin
309 unsigned char bufin[MAX_SIZE];
310 ssize_t bufin_size = 0;
311 unsigned char *bufin_write;
319 while ((1 == rea) || (1 == wri))
325 * We are supposed to read and the buffer is empty
326 * -> select on read from tun
328 if (rea && (0 == buftun_size))
330 FD_SET (fd_tun, &fds_r);
334 * We are supposed to read and the buffer is not empty
335 * -> select on write to stdout
337 if (rea && (0 != buftun_size))
343 * We are supposed to write and the buffer is empty
344 * -> select on read from stdin
346 if (wri && (0 == bufin_size))
352 * We are supposed to write and the buffer is not empty
353 * -> select on write to tun
355 if (wri && (0 != bufin_size))
357 FD_SET (fd_tun, &fds_w);
360 int r = select (fd_tun + 1, &fds_r, &fds_w, NULL, NULL);
363 fprintf (stderr, "select failed: %s\n", strerror (errno));
369 if (FD_ISSET (fd_tun, &fds_r))
372 read (fd_tun, buftun + sizeof (struct GNUNET_MessageHeader),
373 MAX_SIZE - sizeof (struct GNUNET_MessageHeader)) +
374 sizeof (struct GNUNET_MessageHeader);
375 if (-1 == buftun_size)
377 fprintf (stderr, "read-error: %s\n", strerror (errno));
378 shutdown (fd_tun, SHUT_RD);
379 shutdown (1, SHUT_WR);
383 else if (0 == buftun_size)
385 fprintf (stderr, "eof on tun\n");
386 shutdown (fd_tun, SHUT_RD);
387 shutdown (1, SHUT_WR);
393 buftun_read = buftun;
394 struct GNUNET_MessageHeader *hdr =
395 (struct GNUNET_MessageHeader *) buftun;
396 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
397 hdr->size = htons (buftun_size);
400 else if (FD_ISSET (1, &fds_w))
402 ssize_t written = write (1, buftun_read, buftun_size);
405 fprintf (stderr, "write-error to stdout: %s\n",
407 shutdown (fd_tun, SHUT_RD);
408 shutdown (1, SHUT_WR);
412 buftun_size -= written;
413 buftun_read += written;
416 if (FD_ISSET (0, &fds_r))
418 bufin_size = read (0, bufin, MAX_SIZE);
419 if (-1 == bufin_size)
421 fprintf (stderr, "read-error: %s\n", strerror (errno));
422 shutdown (0, SHUT_RD);
423 shutdown (fd_tun, SHUT_WR);
427 else if (0 == bufin_size)
429 fprintf (stderr, "eof on stdin\n");
430 shutdown (0, SHUT_RD);
431 shutdown (fd_tun, SHUT_WR);
437 struct GNUNET_MessageHeader *hdr =
438 (struct GNUNET_MessageHeader *) bufin;
439 if ((bufin_size < sizeof (struct GNUNET_MessageHeader))
440 || (ntohs (hdr->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER)
441 || (ntohs (hdr->size) != bufin_size))
443 fprintf (stderr, "protocol violation!\n");
446 bufin_write = bufin + sizeof (struct GNUNET_MessageHeader);
447 bufin_size -= sizeof (struct GNUNET_MessageHeader);
450 else if (FD_ISSET (fd_tun, &fds_w))
452 ssize_t written = write (fd_tun, bufin_write, bufin_size);
455 fprintf (stderr, "write-error to tun: %s\n",
457 shutdown (0, SHUT_RD);
458 shutdown (fd_tun, SHUT_WR);
462 bufin_size -= written;
463 bufin_write += written;
471 main (int argc, char **argv)
476 memset (dev, 0, IFNAMSIZ);
477 if (-1 == (fd_tun = init_tun (dev)))
479 fprintf (stderr, "Fatal: could not initialize tun-interface\n");
485 fprintf(stderr, "Fatal: must supply 4 arguments!\n");
490 char *address = argv[1];
491 long prefix_len = atol(argv[2]);
493 if (prefix_len < 1 || prefix_len > 127)
495 fprintf(stderr, "Fatal: prefix_len out of range\n");
499 set_address6 (dev, address, prefix_len);
503 char *address = argv[3];
504 char *mask = argv[4];
506 set_address4 (dev, address, mask);
509 uid_t uid = getuid ();
510 if (0 != setresuid (uid, uid, uid))
511 fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno));