diff options
author | Philipp Tölke <toelke@in.tum.de> | 2010-07-30 23:34:42 +0000 |
---|---|---|
committer | Philipp Tölke <toelke@in.tum.de> | 2010-07-30 23:34:42 +0000 |
commit | 1aa2bb86a17b273e373cb58155488cdb9eed93c7 (patch) | |
tree | 0afde4426f22ad90c71a3cf03185c3c976209046 /src/vpn/gnunet-helper-vpn.c | |
parent | af0af530e6800e0c8f49d95931676506ab587830 (diff) | |
download | gnunet-1aa2bb86a17b273e373cb58155488cdb9eed93c7.tar.gz gnunet-1aa2bb86a17b273e373cb58155488cdb9eed93c7.zip |
renamed the vpn-helper to fit into the scheme gnunet-FUNCTION-SUBSYSTEM
Diffstat (limited to 'src/vpn/gnunet-helper-vpn.c')
-rw-r--r-- | src/vpn/gnunet-helper-vpn.c | 246 |
1 files changed, 246 insertions, 0 deletions
diff --git a/src/vpn/gnunet-helper-vpn.c b/src/vpn/gnunet-helper-vpn.c new file mode 100644 index 000000000..4a75182f9 --- /dev/null +++ b/src/vpn/gnunet-helper-vpn.c | |||
@@ -0,0 +1,246 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2010 Christian Grothoff | ||
4 | |||
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. | ||
9 | |||
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. | ||
14 | |||
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. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file vpn/gnunet-daemon-vpn.c | ||
23 | * @brief | ||
24 | * @author Philipp Tölke | ||
25 | */ | ||
26 | #define _GNU_SOURCE | ||
27 | #include <arpa/inet.h> | ||
28 | #include <linux/if.h> | ||
29 | |||
30 | #include <fcntl.h> | ||
31 | |||
32 | #include <sys/types.h> | ||
33 | #include <sys/socket.h> | ||
34 | #include <sys/ioctl.h> | ||
35 | |||
36 | #include <string.h> | ||
37 | |||
38 | #include <signal.h> | ||
39 | |||
40 | #include <stdio.h> | ||
41 | #include <unistd.h> | ||
42 | |||
43 | #include "gnunet-vpn-tun.h" | ||
44 | #include "gnunet_common.h" | ||
45 | #include "gnunet_protocols.h" | ||
46 | #include "gnunet-vpn-helper-p.h" | ||
47 | |||
48 | #ifndef _LINUX_IN6_H | ||
49 | // This is in linux/include/net/ipv6.h. | ||
50 | |||
51 | #define MAX_SIZE (65535 - sizeof(struct GNUNET_MessageHeader)) | ||
52 | |||
53 | struct in6_ifreq { | ||
54 | struct in6_addr ifr6_addr; | ||
55 | __u32 ifr6_prefixlen; | ||
56 | unsigned int ifr6_ifindex; | ||
57 | }; | ||
58 | |||
59 | #endif | ||
60 | |||
61 | int running = 1; | ||
62 | |||
63 | void term(int sig) { | ||
64 | fprintf(stderr, "Got SIGTERM...\n"); | ||
65 | if (sig == SIGTERM) | ||
66 | running = 0; | ||
67 | } | ||
68 | |||
69 | static void set_address(char* dev, char* address, unsigned long prefix_len) { /* {{{ */ | ||
70 | int fd = socket(AF_INET6, SOCK_DGRAM, 0); | ||
71 | |||
72 | struct ifreq ifr; | ||
73 | struct in6_ifreq ifr6; | ||
74 | |||
75 | struct sockaddr_in6 sa6; | ||
76 | memset(&sa6, 0, sizeof(struct sockaddr_in6)); | ||
77 | |||
78 | sa6.sin6_family = AF_INET6; | ||
79 | |||
80 | /* FIXME */ inet_pton(AF_INET6, address, sa6.sin6_addr.s6_addr); | ||
81 | |||
82 | memcpy((char *) &ifr6.ifr6_addr, (char *) &sa6.sin6_addr, sizeof(struct in6_addr)); | ||
83 | |||
84 | strncpy(ifr.ifr_name, dev, IFNAMSIZ); | ||
85 | |||
86 | if (ioctl(fd, SIOGIFINDEX, &ifr) < 0) { | ||
87 | perror("SIOGIFINDEX"); | ||
88 | } | ||
89 | |||
90 | ifr6.ifr6_ifindex = ifr.ifr_ifindex; | ||
91 | ifr6.ifr6_prefixlen = prefix_len; | ||
92 | |||
93 | if (ioctl(fd, SIOCSIFADDR, &ifr6) < 0) { | ||
94 | perror("SIOCSIFADDR"); | ||
95 | } | ||
96 | |||
97 | /* FIXME */ ioctl(fd, SIOCGIFFLAGS, &ifr); | ||
98 | ifr.ifr_flags |= IFF_UP | IFF_RUNNING; | ||
99 | /* FIXME */ ioctl(fd, SIOCSIFFLAGS, &ifr); | ||
100 | } /* }}} */ | ||
101 | |||
102 | void setnonblocking(int fd) {/*{{{*/ | ||
103 | int opts; | ||
104 | |||
105 | opts = fcntl(fd,F_GETFL); | ||
106 | if (opts < 0) { | ||
107 | perror("fcntl(F_GETFL)"); | ||
108 | } | ||
109 | opts = (opts | O_NONBLOCK); | ||
110 | if (fcntl(fd,F_SETFL,opts) < 0) { | ||
111 | perror("fcntl(F_SETFL)"); | ||
112 | } | ||
113 | return; | ||
114 | }/*}}}*/ | ||
115 | |||
116 | int main(int argc, char** argv) { | ||
117 | unsigned char buf[MAX_SIZE]; | ||
118 | |||
119 | char dev[IFNAMSIZ]; | ||
120 | memset(dev, 0, IFNAMSIZ); | ||
121 | |||
122 | signal(SIGTERM, &term); | ||
123 | |||
124 | int fd_tun = init_tun(dev); | ||
125 | fprintf(stderr, "Initialized the interface %s as %d.\n", dev, fd_tun); | ||
126 | |||
127 | // TODO: get this out of argv | ||
128 | char address[] = "1234::1"; | ||
129 | unsigned long prefix_len = 16; | ||
130 | |||
131 | set_address(dev, address, prefix_len); | ||
132 | |||
133 | uid_t uid = getuid (); | ||
134 | if (setresuid (uid, uid, uid) != 0 ) | ||
135 | fprintf (stderr, "Failed to setresuid: %m\n"); | ||
136 | |||
137 | setnonblocking(0); | ||
138 | setnonblocking(1); | ||
139 | setnonblocking(fd_tun); | ||
140 | |||
141 | fd_set fds_w; | ||
142 | fd_set fds_r; | ||
143 | |||
144 | int rea = 1; | ||
145 | int wri = 1; | ||
146 | |||
147 | int write_fd_possible = 0; | ||
148 | int write_stdout_possible = 0; | ||
149 | outer: | ||
150 | while((rea == 1 || wri == 1) && running == 1) { | ||
151 | FD_ZERO(&fds_w); | ||
152 | FD_ZERO(&fds_r); | ||
153 | |||
154 | if (rea) { | ||
155 | FD_SET(fd_tun, &fds_r); | ||
156 | if (!write_stdout_possible) | ||
157 | FD_SET(1, &fds_w); | ||
158 | } | ||
159 | |||
160 | if (wri) { | ||
161 | FD_SET(0, &fds_r); | ||
162 | if (!write_fd_possible) | ||
163 | FD_SET(fd_tun, &fds_w); | ||
164 | } | ||
165 | |||
166 | int r = select(fd_tun+1, &fds_r, &fds_w, (fd_set*)0, 0); | ||
167 | |||
168 | if(r > 0) { | ||
169 | if (FD_ISSET(fd_tun, &fds_w)) write_fd_possible = 1; | ||
170 | if (FD_ISSET(1, &fds_w)) write_stdout_possible = 1; | ||
171 | |||
172 | if (FD_ISSET(0, &fds_r) && write_fd_possible) { | ||
173 | write_fd_possible = 0; | ||
174 | struct suid_packet *pkt = (struct suid_packet*) buf; | ||
175 | r = read(0, buf, sizeof(struct GNUNET_MessageHeader)); | ||
176 | if (r <= 0) { | ||
177 | fprintf(stderr, "read-error: %m\n"); | ||
178 | shutdown(fd_tun, SHUT_WR); | ||
179 | shutdown(0, SHUT_RD); | ||
180 | wri=0; | ||
181 | goto outer; | ||
182 | } | ||
183 | while (r < ntohs(pkt->hdr.size)) { | ||
184 | int t = read(0, buf + r, ntohs(pkt->hdr.size) - r); | ||
185 | if (r < 0) { | ||
186 | fprintf(stderr, "read-error: %m\n"); | ||
187 | shutdown(fd_tun, SHUT_WR); | ||
188 | shutdown(0, SHUT_RD); | ||
189 | wri=0; | ||
190 | goto outer; | ||
191 | } | ||
192 | r += t; | ||
193 | } | ||
194 | r = 0; | ||
195 | while (r < ntohs(pkt->hdr.size) - sizeof(struct GNUNET_MessageHeader)) { | ||
196 | int t = write(fd_tun, pkt->data, ntohs(pkt->hdr.size) - sizeof(struct GNUNET_MessageHeader) - r); | ||
197 | if (t < 0) { | ||
198 | fprintf(stderr, "write-error 3: %m\n"); | ||
199 | shutdown(fd_tun, SHUT_WR); | ||
200 | shutdown(0, SHUT_RD); | ||
201 | wri = 0; | ||
202 | goto outer; | ||
203 | } | ||
204 | r += t; | ||
205 | } | ||
206 | } else if (write_stdout_possible && FD_ISSET(fd_tun, &fds_r)) { | ||
207 | write_stdout_possible = 0; | ||
208 | r = read(fd_tun, buf, MAX_SIZE); | ||
209 | if (r <= 0) { | ||
210 | fprintf(stderr, "read-error: %m\n"); | ||
211 | shutdown(fd_tun, SHUT_RD); | ||
212 | shutdown(1, SHUT_WR); | ||
213 | rea = 0; | ||
214 | goto outer; | ||
215 | } | ||
216 | struct GNUNET_MessageHeader hdr = { .size = htons(r + sizeof(struct GNUNET_MessageHeader)), .type = htons(GNUNET_MESSAGE_TYPE_VPN_HELPER) }; | ||
217 | r = 0; | ||
218 | while(r < sizeof(struct GNUNET_MessageHeader)) { | ||
219 | int t = write(1, &hdr, sizeof(struct GNUNET_MessageHeader) - r); | ||
220 | if (t < 0) { | ||
221 | fprintf(stderr, "write-error 2: %m\n"); | ||
222 | shutdown(fd_tun, SHUT_RD); | ||
223 | shutdown(1, SHUT_WR); | ||
224 | rea = 0; | ||
225 | goto outer; | ||
226 | } | ||
227 | r += t; | ||
228 | } | ||
229 | while(r < ntohs(hdr.size)) { | ||
230 | int t = write(1, buf, ntohs(hdr.size) - r); | ||
231 | if (t < 0) { | ||
232 | fprintf(stderr, "write-error 1: %m, written %d/%d\n", r, ntohs(hdr.size)); | ||
233 | shutdown(fd_tun, SHUT_RD); | ||
234 | shutdown(1, SHUT_WR); | ||
235 | rea = 0; | ||
236 | goto outer; | ||
237 | } | ||
238 | r += t; | ||
239 | } | ||
240 | } | ||
241 | } | ||
242 | } | ||
243 | fprintf(stderr, "Quitting!\n"); | ||
244 | |||
245 | return 0; | ||
246 | } | ||