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
24 * @author Philipp Tölke
28 #include "gnunet-vpn-tun.h"
29 #include "gnunet_common.h"
30 #include "gnunet_protocols.h"
31 #include "gnunet-vpn-helper-p.h"
34 // This is in linux/include/net/ipv6.h.
36 #define MAX_SIZE (65535 - sizeof(struct GNUNET_MessageHeader))
39 struct in6_addr ifr6_addr;
40 uint32_t ifr6_prefixlen;
41 unsigned int ifr6_ifindex;
49 fprintf(stderr, "Got SIGTERM...\n");
54 static void set_address6(char* dev, char* address, unsigned long prefix_len) { /* {{{ */
55 int fd = socket(AF_INET6, SOCK_DGRAM, 0);
59 fprintf(stderr, "error creating socket: %m\n");
64 struct in6_ifreq ifr6;
66 struct sockaddr_in6 sa6;
67 memset(&sa6, 0, sizeof(struct sockaddr_in6));
69 sa6.sin6_family = AF_INET6;
71 int r = inet_pton(AF_INET6, address, sa6.sin6_addr.s6_addr);
74 fprintf(stderr, "error at inet_pton: %m\n");
78 memcpy((char *) &ifr6.ifr6_addr, (char *) &sa6.sin6_addr, sizeof(struct in6_addr));
80 strncpy(ifr.ifr_name, dev, IFNAMSIZ);
82 if (ioctl(fd, SIOGIFINDEX, &ifr) < 0) {
83 perror("SIOGIFINDEX");
86 ifr6.ifr6_ifindex = ifr.ifr_ifindex;
87 ifr6.ifr6_prefixlen = prefix_len;
89 if (ioctl(fd, SIOCSIFADDR, &ifr6) < 0) {
90 perror("SIOCSIFADDR");
93 (void)ioctl(fd, SIOCGIFFLAGS, &ifr);
94 ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
95 (void)ioctl(fd, SIOCSIFFLAGS, &ifr);
99 static void set_address4(char* dev, char* address, char* mask) { /* {{{ */
101 struct sockaddr_in* addr;
104 memset(&ifr, 0, sizeof(struct ifreq));
105 addr = (struct sockaddr_in *)&(ifr.ifr_addr);
106 memset(addr, 0, sizeof(struct sockaddr_in));
107 addr->sin_family = AF_INET;
108 addr->sin_addr.s_addr = inet_addr(address);
110 int r = inet_pton(AF_INET, address, &addr->sin_addr.s_addr);
113 fprintf(stderr, "error at inet_pton: %m\n");
117 fd = socket(PF_INET, SOCK_DGRAM, 0);
123 strncpy(ifr.ifr_name, dev, IFNAMSIZ);
125 if(ioctl(fd, SIOCSIFADDR, &ifr) != 0 ) {
126 perror("SIOCSIFADDR");
131 addr = (struct sockaddr_in*)&(ifr.ifr_netmask);
132 r = inet_pton(AF_INET, mask, &addr->sin_addr.s_addr);
135 fprintf(stderr, "error at inet_pton: %m\n");
139 if(ioctl(fd, SIOCSIFNETMASK, &ifr) != 0 ) {
140 perror("SIOCSIFNETMASK");
145 (void)ioctl(fd, SIOCGIFFLAGS, &ifr);
146 ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
147 (void)ioctl(fd, SIOCSIFFLAGS, &ifr);
151 void setnonblocking(int fd) {/*{{{*/
154 opts = fcntl(fd,F_GETFL);
156 perror("fcntl(F_GETFL)");
158 opts = (opts | O_NONBLOCK);
159 if (fcntl(fd,F_SETFL,opts) < 0) {
160 perror("fcntl(F_SETFL)");
165 int main(int argc, char** argv) {
166 unsigned char buf[MAX_SIZE];
169 memset(dev, 0, IFNAMSIZ);
171 signal(SIGTERM, &term);
173 int fd_tun = init_tun(dev);
176 fprintf(stderr, "Could not initialize tun-interface: %s\n", strerror(errno));
181 // TODO: get this out of argv
182 char address[] = "1234::1";
183 unsigned long prefix_len = 16;
185 set_address6(dev, address, prefix_len);
189 char address[] = "10.10.10.1";
190 char mask[] = "255.255.255.252";
192 set_address4(dev, address, mask);
195 uid_t uid = getuid ();
196 if (setresuid (uid, uid, uid) != 0 )
197 fprintf (stderr, "Failed to setresuid: %s\n", strerror(errno));
201 setnonblocking(fd_tun);
209 int write_fd_possible = 0;
210 int write_stdout_possible = 0;
212 while((rea == 1 || wri == 1) && running == 1) {
217 FD_SET(fd_tun, &fds_r);
218 if (!write_stdout_possible)
224 if (!write_fd_possible)
225 FD_SET(fd_tun, &fds_w);
228 int r = select(fd_tun+1, &fds_r, &fds_w, (fd_set*)0, 0);
231 if (FD_ISSET(fd_tun, &fds_w)) write_fd_possible = 1;
232 if (FD_ISSET(1, &fds_w)) write_stdout_possible = 1;
234 if (FD_ISSET(0, &fds_r) && write_fd_possible) {
235 write_fd_possible = 0;
236 struct suid_packet *pkt = (struct suid_packet*) buf;
237 r = read(0, buf, sizeof(struct GNUNET_MessageHeader));
239 fprintf(stderr, "read-error: %s\n", strerror (errno));
240 shutdown(fd_tun, SHUT_WR);
241 shutdown(0, SHUT_RD);
245 if(pkt->hdr.type != ntohs(GNUNET_MESSAGE_TYPE_VPN_HELPER)) abort();
246 while (r < ntohs(pkt->hdr.size)) {
247 int t = read(0, buf + r, ntohs(pkt->hdr.size) - r);
249 fprintf(stderr, "read-error: %s\n", strerror (errno));
250 shutdown(fd_tun, SHUT_WR);
251 shutdown(0, SHUT_RD);
258 while (r < ntohs(pkt->hdr.size) - sizeof(struct GNUNET_MessageHeader)) {
259 int t = write(fd_tun, pkt->data, ntohs(pkt->hdr.size) - sizeof(struct GNUNET_MessageHeader) - r);
261 fprintf(stderr, "write-error 3: %s\n", strerror (errno));
262 shutdown(fd_tun, SHUT_WR);
263 shutdown(0, SHUT_RD);
269 } else if (write_stdout_possible && FD_ISSET(fd_tun, &fds_r)) {
270 write_stdout_possible = 0;
271 r = read(fd_tun, buf, MAX_SIZE);
273 fprintf(stderr, "read-error: %s\n", strerror (errno));
274 shutdown(fd_tun, SHUT_RD);
275 shutdown(1, SHUT_WR);
279 struct GNUNET_MessageHeader hdr = { .size = htons(r + sizeof(struct GNUNET_MessageHeader)), .type = htons(GNUNET_MESSAGE_TYPE_VPN_HELPER) };
281 while(r < sizeof(struct GNUNET_MessageHeader)) {
282 int t = write(1, &hdr, sizeof(struct GNUNET_MessageHeader) - r);
284 fprintf(stderr, "write-error 2: %s\n", strerror (errno));
285 shutdown(fd_tun, SHUT_RD);
286 shutdown(1, SHUT_WR);
292 while(r < ntohs(hdr.size)) {
293 int t = write(1, buf, ntohs(hdr.size) - r);
295 fprintf(stderr, "write-error 1: %s, written %d/%d\n", strerror(errno), r, ntohs(hdr.size));
296 shutdown(fd_tun, SHUT_RD);
297 shutdown(1, SHUT_WR);