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
30 #include "gnunet-vpn-tun.h"
31 #include "gnunet_common.h"
32 #include "gnunet_protocols.h"
33 #include "gnunet-vpn-helper-p.h"
37 #define MAX_SIZE (65535 - sizeof(struct GNUNET_MessageHeader))
39 // This is in linux/include/net/ipv6.h.
42 struct in6_addr ifr6_addr;
43 uint32_t ifr6_prefixlen;
44 unsigned int ifr6_ifindex;
49 static int running = 1;
54 fprintf (stderr, "Got SIGTERM...\n");
60 * @brief Sets the IPv6-Address given in address on the interface dev
62 * @param dev the interface to configure
63 * @param address the IPv6-Address
64 * @param prefix_len the length of the network-prefix
67 set_address6 (char *dev, char *address, unsigned long prefix_len)
69 int fd = socket (AF_INET6, SOCK_DGRAM, 0);
73 fprintf (stderr, "error creating socket: %m\n");
78 struct in6_ifreq ifr6;
80 struct sockaddr_in6 sa6;
81 memset (&sa6, 0, sizeof (struct sockaddr_in6));
83 sa6.sin6_family = AF_INET6;
85 int r = inet_pton (AF_INET6, address, sa6.sin6_addr.s6_addr);
88 fprintf (stderr, "error at inet_pton: %m\n");
92 memcpy ((char *) &ifr6.ifr6_addr, (char *) &sa6.sin6_addr,
93 sizeof (struct in6_addr));
95 strncpy (ifr.ifr_name, dev, IFNAMSIZ);
97 if (ioctl (fd, SIOGIFINDEX, &ifr) < 0)
99 perror ("SIOGIFINDEX");
102 ifr6.ifr6_ifindex = ifr.ifr_ifindex;
103 ifr6.ifr6_prefixlen = prefix_len;
105 if (ioctl (fd, SIOCSIFADDR, &ifr6) < 0)
107 perror ("SIOCSIFADDR");
110 (void) ioctl (fd, SIOCGIFFLAGS, &ifr);
111 ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
112 (void) ioctl (fd, SIOCSIFFLAGS, &ifr);
118 * @brief Sets the IPv4-Address given in address on the interface dev
120 * @param dev the interface to configure
121 * @param address the IPv4-Address
122 * @param mask the netmask
124 set_address4 (char *dev, char *address, char *mask)
127 struct sockaddr_in *addr;
130 memset (&ifr, 0, sizeof (struct ifreq));
131 addr = (struct sockaddr_in *) &(ifr.ifr_addr);
132 memset (addr, 0, sizeof (struct sockaddr_in));
133 addr->sin_family = AF_INET;
134 addr->sin_addr.s_addr = inet_addr (address);
136 int r = inet_pton (AF_INET, address, &addr->sin_addr.s_addr);
139 fprintf (stderr, "error at inet_pton: %m\n");
143 fd = socket (PF_INET, SOCK_DGRAM, 0);
150 strncpy (ifr.ifr_name, dev, IFNAMSIZ);
152 if (ioctl (fd, SIOCSIFADDR, &ifr) != 0)
154 perror ("SIOCSIFADDR");
159 addr = (struct sockaddr_in *) &(ifr.ifr_netmask);
160 r = inet_pton (AF_INET, mask, &addr->sin_addr.s_addr);
163 fprintf (stderr, "error at inet_pton: %m\n");
167 if (ioctl (fd, SIOCSIFNETMASK, &ifr) != 0)
169 perror ("SIOCSIFNETMASK");
174 (void) ioctl (fd, SIOCGIFFLAGS, &ifr);
175 ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
176 (void) ioctl (fd, SIOCSIFFLAGS, &ifr);
181 * @brief sets the socket to nonblocking
183 * @param fd the socket
186 setnonblocking (int fd)
190 opts = fcntl (fd, F_GETFL);
193 perror ("fcntl(F_GETFL)");
195 opts = (opts | O_NONBLOCK);
196 if (fcntl (fd, F_SETFL, opts) < 0)
198 perror ("fcntl(F_SETFL)");
204 main (int argc, char **argv)
206 unsigned char buf[MAX_SIZE];
209 memset (dev, 0, IFNAMSIZ);
211 signal (SIGTERM, &term);
213 int fd_tun = init_tun (dev);
217 fprintf (stderr, "Could not initialize tun-interface: %s\n",
223 // TODO: get this out of argv
224 char address[] = "1234::1";
225 unsigned long prefix_len = 16;
227 set_address6 (dev, address, prefix_len);
231 char address[] = "10.10.10.1";
232 char mask[] = "255.255.255.252";
234 set_address4 (dev, address, mask);
237 uid_t uid = getuid ();
238 if (setresuid (uid, uid, uid) != 0)
239 fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno));
243 setnonblocking (fd_tun);
251 int write_fd_possible = 0;
252 int write_stdout_possible = 0;
254 while ((rea == 1 || wri == 1) && running == 1)
261 FD_SET (fd_tun, &fds_r);
262 if (!write_stdout_possible)
269 if (!write_fd_possible)
270 FD_SET (fd_tun, &fds_w);
273 int r = select (fd_tun + 1, &fds_r, &fds_w, (fd_set *) 0, 0);
277 if (FD_ISSET (fd_tun, &fds_w))
278 write_fd_possible = 1;
279 if (FD_ISSET (1, &fds_w))
280 write_stdout_possible = 1;
282 if (FD_ISSET (0, &fds_r) && write_fd_possible)
284 write_fd_possible = 0;
285 struct suid_packet *pkt = (struct suid_packet *) buf;
286 r = read (0, buf, sizeof (struct GNUNET_MessageHeader));
289 fprintf (stderr, "read-error: %s\n", strerror (errno));
290 shutdown (fd_tun, SHUT_WR);
291 shutdown (0, SHUT_RD);
295 if (pkt->hdr.type != ntohs (GNUNET_MESSAGE_TYPE_VPN_HELPER))
297 while (r < ntohs (pkt->hdr.size))
299 int t = read (0, buf + r, ntohs (pkt->hdr.size) - r);
302 fprintf (stderr, "read-error: %s\n", strerror (errno));
303 shutdown (fd_tun, SHUT_WR);
304 shutdown (0, SHUT_RD);
312 ntohs (pkt->hdr.size) -
313 sizeof (struct GNUNET_MessageHeader))
315 int t = write (fd_tun, pkt->data,
316 ntohs (pkt->hdr.size) -
317 sizeof (struct GNUNET_MessageHeader) - r);
320 fprintf (stderr, "write-error 3: %s\n",
322 shutdown (fd_tun, SHUT_WR);
323 shutdown (0, SHUT_RD);
330 else if (write_stdout_possible && FD_ISSET (fd_tun, &fds_r))
332 write_stdout_possible = 0;
333 r = read (fd_tun, buf, MAX_SIZE);
336 fprintf (stderr, "read-error: %s\n", strerror (errno));
337 shutdown (fd_tun, SHUT_RD);
338 shutdown (1, SHUT_WR);
342 struct GNUNET_MessageHeader hdr = {.size =
343 htons (r + sizeof (struct GNUNET_MessageHeader)),.type =
344 htons (GNUNET_MESSAGE_TYPE_VPN_HELPER)
347 while (r < sizeof (struct GNUNET_MessageHeader))
350 write (1, &hdr, sizeof (struct GNUNET_MessageHeader) - r);
353 fprintf (stderr, "write-error 2: %s\n",
355 shutdown (fd_tun, SHUT_RD);
356 shutdown (1, SHUT_WR);
362 while (r < ntohs (hdr.size))
364 int t = write (1, buf, ntohs (hdr.size) - r);
367 fprintf (stderr, "write-error 1: %s, written %d/%d\n",
368 strerror (errno), r, ntohs (hdr.size));
369 shutdown (fd_tun, SHUT_RD);
370 shutdown (1, SHUT_WR);