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
27 #include <arpa/inet.h>
32 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <sys/ioctl.h>
43 #include "gnunet-vpn-helper-p.h"
44 #include "gnunet-vpn-tun.h"
47 // This is in linux/include/net/ipv6.h.
50 struct in6_addr ifr6_addr;
52 unsigned int ifr6_ifindex;
60 fprintf(stderr, "Got SIGTERM...\n");
65 static void set_address(char* dev, char* address, unsigned long prefix_len) { /* {{{ */
66 int fd = socket(AF_INET6, SOCK_DGRAM, 0);
69 struct in6_ifreq ifr6;
71 struct sockaddr_in6 sa6;
72 memset(&sa6, 0, sizeof(struct sockaddr_in6));
74 sa6.sin6_family = AF_INET6;
76 /* FIXME */ inet_pton(AF_INET6, address, sa6.sin6_addr.s6_addr);
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 /* FIXME */ ioctl(fd, SIOCGIFFLAGS, &ifr);
94 ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
95 /* FIXME */ ioctl(fd, SIOCSIFFLAGS, &ifr);
98 void setnonblocking(int fd) {/*{{{*/
101 opts = fcntl(fd,F_GETFL);
103 perror("fcntl(F_GETFL)");
105 opts = (opts | O_NONBLOCK);
106 if (fcntl(fd,F_SETFL,opts) < 0) {
107 perror("fcntl(F_SETFL)");
112 int main(int argc, char** argv) {
113 unsigned char buf[65600]; // 64k + 64;
116 memset(dev, 0, IFNAMSIZ);
118 signal(SIGTERM, &term);
120 int fd_tun = init_tun(dev);
121 fprintf(stderr, "Initialized the interface %s as %d.\n", dev, fd_tun);
123 // TODO: get this out of argv
124 char address[] = "1234::1";
125 unsigned long prefix_len = 16;
127 set_address(dev, address, prefix_len);
129 uid_t uid = getuid ();
130 if (setresuid (uid, uid, uid) != 0 )
131 fprintf (stderr, "Failed to setresuid: %m\n");
135 setnonblocking(fd_tun);
143 int write_fd_possible = 0;
144 int write_stdout_possible = 0;
146 while((rea == 1 || wri == 1) && running == 1) {
151 FD_SET(fd_tun, &fds_r);
152 if (!write_stdout_possible)
158 if (!write_fd_possible)
159 FD_SET(fd_tun, &fds_w);
162 int r = select(fd_tun+1, &fds_r, &fds_w, (fd_set*)0, 0);
165 if (FD_ISSET(fd_tun, &fds_w)) write_fd_possible = 1;
166 if (FD_ISSET(1, &fds_w)) write_stdout_possible = 1;
168 if (FD_ISSET(0, &fds_r) && write_fd_possible) {
169 write_fd_possible = 0;
170 struct suid_packet *pkt = (struct suid_packet*) buf;
171 r = read(0, buf, sizeof(struct suid_packet_header));
173 fprintf(stderr, "read-error: %m\n");
174 shutdown(fd_tun, SHUT_WR);
175 shutdown(0, SHUT_RD);
179 while (r < ntohl(pkt->hdr.size)) {
180 int t = read(0, buf + r, ntohl(pkt->hdr.size) - r);
182 fprintf(stderr, "read-error: %m\n");
183 shutdown(fd_tun, SHUT_WR);
184 shutdown(0, SHUT_RD);
191 while (r < ntohl(pkt->hdr.size) - sizeof(struct suid_packet_header)) {
192 int t = write(fd_tun, pkt->data, ntohl(pkt->hdr.size) - sizeof(struct suid_packet_header) - r);
194 fprintf(stderr, "write-error 3: %m\n");
195 shutdown(fd_tun, SHUT_WR);
196 shutdown(0, SHUT_RD);
202 } else if (write_stdout_possible && FD_ISSET(fd_tun, &fds_r)) {
203 write_stdout_possible = 0;
204 r = read(fd_tun, buf, 65600);
206 fprintf(stderr, "read-error: %m\n");
207 shutdown(fd_tun, SHUT_RD);
208 shutdown(1, SHUT_WR);
212 struct suid_packet_header hdr = { .size = htonl(r + sizeof(struct suid_packet_header))};
214 while(r < sizeof(struct suid_packet_header)) {
215 int t = write(1, &hdr, sizeof(struct suid_packet_header) - r);
217 fprintf(stderr, "write-error 2: %m\n");
218 shutdown(fd_tun, SHUT_RD);
219 shutdown(1, SHUT_WR);
225 while(r < ntohl(hdr.size)) {
226 int t = write(1, buf, ntohl(hdr.size) - r);
228 fprintf(stderr, "write-error 1: %m, written %d/%d\n", r, ntohl(hdr.size));
229 shutdown(fd_tun, SHUT_RD);
230 shutdown(1, SHUT_WR);
239 fprintf(stderr, "Quitting!\n");