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;
61 struct GNUNET_MessageHeader hdr;
62 unsigned char data[1];
65 static int running = 1;
78 * Creates a tun-interface called dev;
79 * @param dev is asumed to point to a char[IFNAMSIZ]
80 * if *dev == '\0', uses the name supplied by the kernel
81 * @return the fd to the tun or -1 on error
95 if (-1 == (fd = open("/dev/net/tun", O_RDWR)))
98 "Error opening `%s': %s\n",
104 memset(&ifr, 0, sizeof(ifr));
105 ifr.ifr_flags = IFF_TUN;
108 strncpy(ifr.ifr_name, dev, IFNAMSIZ);
110 if (-1 == ioctl(fd, TUNSETIFF, (void *) &ifr))
113 "Error with ioctl on `%s': %s\n",
119 strcpy(dev, ifr.ifr_name);
124 * @brief Sets the IPv6-Address given in address on the interface dev
126 * @param dev the interface to configure
127 * @param address the IPv6-Address
128 * @param prefix_len the length of the network-prefix
131 set_address6 (char *dev, char *address, unsigned long prefix_len)
133 int fd = socket (AF_INET6, SOCK_DGRAM, 0);
137 fprintf (stderr, "error creating socket: %m\n");
142 struct in6_ifreq ifr6;
144 struct sockaddr_in6 sa6;
145 memset (&sa6, 0, sizeof (struct sockaddr_in6));
147 sa6.sin6_family = AF_INET6;
149 int r = inet_pton (AF_INET6, address, sa6.sin6_addr.s6_addr);
152 fprintf (stderr, "error at inet_pton: %m\n");
156 memcpy ((char *) &ifr6.ifr6_addr, (char *) &sa6.sin6_addr,
157 sizeof (struct in6_addr));
159 strncpy (ifr.ifr_name, dev, IFNAMSIZ);
161 if (ioctl (fd, SIOGIFINDEX, &ifr) < 0)
163 perror ("SIOGIFINDEX");
166 ifr6.ifr6_ifindex = ifr.ifr_ifindex;
167 ifr6.ifr6_prefixlen = prefix_len;
169 if (ioctl (fd, SIOCSIFADDR, &ifr6) < 0)
171 perror ("SIOCSIFADDR");
174 (void) ioctl (fd, SIOCGIFFLAGS, &ifr);
175 ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
176 (void) ioctl (fd, SIOCSIFFLAGS, &ifr);
182 * @brief Sets the IPv4-Address given in address on the interface dev
184 * @param dev the interface to configure
185 * @param address the IPv4-Address
186 * @param mask the netmask
189 set_address4 (char *dev, char *address, char *mask)
192 struct sockaddr_in *addr;
195 memset (&ifr, 0, sizeof (struct ifreq));
196 addr = (struct sockaddr_in *) &(ifr.ifr_addr);
197 memset (addr, 0, sizeof (struct sockaddr_in));
198 addr->sin_family = AF_INET;
199 addr->sin_addr.s_addr = inet_addr (address);
201 int r = inet_pton (AF_INET, address, &addr->sin_addr.s_addr);
204 fprintf (stderr, "error at inet_pton: %m\n");
208 fd = socket (PF_INET, SOCK_DGRAM, 0);
215 strncpy (ifr.ifr_name, dev, IFNAMSIZ);
217 if (ioctl (fd, SIOCSIFADDR, &ifr) != 0)
219 perror ("SIOCSIFADDR");
224 addr = (struct sockaddr_in *) &(ifr.ifr_netmask);
225 r = inet_pton (AF_INET, mask, &addr->sin_addr.s_addr);
228 fprintf (stderr, "error at inet_pton: %m\n");
232 if (ioctl (fd, SIOCSIFNETMASK, &ifr) != 0)
234 perror ("SIOCSIFNETMASK");
239 (void) ioctl (fd, SIOCGIFFLAGS, &ifr);
240 ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
241 (void) ioctl (fd, SIOCSIFFLAGS, &ifr);
247 * @brief sets the socket to nonblocking
249 * @param fd the socket
252 setnonblocking (int fd)
255 opts = fcntl(fd,F_GETFL);
257 perror("fcntl(F_GETFL)");
259 opts = (opts | O_NONBLOCK);
260 if (fcntl(fd,F_SETFL,opts) < 0) {
261 perror("fcntl(F_SETFL)");
268 main(int argc, char** argv)
270 unsigned char buf[MAX_SIZE];
273 memset (dev, 0, IFNAMSIZ);
275 signal (SIGTERM, &term);
277 int fd_tun = init_tun (dev);
281 fprintf (stderr, "Could not initialize tun-interface: %s\n",
287 // TODO: get this out of argv
288 char address[] = "1234::1";
289 unsigned long prefix_len = 16;
291 set_address6 (dev, address, prefix_len);
295 char address[] = "10.10.10.1";
296 char mask[] = "255.255.255.252";
298 set_address4 (dev, address, mask);
301 uid_t uid = getuid ();
302 if (setresuid (uid, uid, uid) != 0)
303 fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno));
307 setnonblocking (fd_tun);
315 int write_fd_possible = 0;
316 int write_stdout_possible = 0;
318 while ((rea == 1 || wri == 1) && running == 1)
325 FD_SET (fd_tun, &fds_r);
326 if (!write_stdout_possible)
333 if (!write_fd_possible)
334 FD_SET (fd_tun, &fds_w);
337 int r = select (fd_tun + 1, &fds_r, &fds_w, (fd_set *) 0, 0);
341 if (FD_ISSET (fd_tun, &fds_w))
342 write_fd_possible = 1;
343 if (FD_ISSET (1, &fds_w))
344 write_stdout_possible = 1;
346 if (FD_ISSET (0, &fds_r) && write_fd_possible)
348 write_fd_possible = 0;
349 struct suid_packet *pkt = (struct suid_packet *) buf;
350 r = read (0, buf, sizeof (struct GNUNET_MessageHeader));
353 fprintf (stderr, "read-error: %s\n", strerror (errno));
354 shutdown (fd_tun, SHUT_WR);
355 shutdown (0, SHUT_RD);
359 if (pkt->hdr.type != ntohs (GNUNET_MESSAGE_TYPE_VPN_HELPER))
361 while (r < ntohs (pkt->hdr.size))
363 int t = read (0, buf + r, ntohs (pkt->hdr.size) - r);
366 fprintf (stderr, "read-error: %s\n", strerror (errno));
367 shutdown (fd_tun, SHUT_WR);
368 shutdown (0, SHUT_RD);
376 ntohs (pkt->hdr.size) -
377 sizeof (struct GNUNET_MessageHeader))
379 int t = write (fd_tun, pkt->data,
380 ntohs (pkt->hdr.size) -
381 sizeof (struct GNUNET_MessageHeader) - r);
384 fprintf (stderr, "write-error 3: %s\n",
386 shutdown (fd_tun, SHUT_WR);
387 shutdown (0, SHUT_RD);
394 else if (write_stdout_possible && FD_ISSET (fd_tun, &fds_r))
396 write_stdout_possible = 0;
397 r = read (fd_tun, buf, MAX_SIZE);
400 fprintf (stderr, "read-error: %s\n", strerror (errno));
401 shutdown (fd_tun, SHUT_RD);
402 shutdown (1, SHUT_WR);
406 struct GNUNET_MessageHeader hdr = {.size =
407 htons (r + sizeof (struct GNUNET_MessageHeader)),.type =
408 htons (GNUNET_MESSAGE_TYPE_VPN_HELPER)
411 while (r < sizeof (struct GNUNET_MessageHeader))
414 write (1, &hdr, sizeof (struct GNUNET_MessageHeader) - r);
417 fprintf (stderr, "write-error 2: %s\n",
419 shutdown (fd_tun, SHUT_RD);
420 shutdown (1, SHUT_WR);
426 while (r < ntohs (hdr.size))
428 int t = write (1, buf, ntohs (hdr.size) - r);
431 fprintf (stderr, "write-error 1: %s, written %d/%d\n",
432 strerror (errno), r, ntohs (hdr.size));
433 shutdown (fd_tun, SHUT_RD);
434 shutdown (1, SHUT_WR);