diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/vpn/gnunet-helper-vpn.c | 275 |
1 files changed, 151 insertions, 124 deletions
diff --git a/src/vpn/gnunet-helper-vpn.c b/src/vpn/gnunet-helper-vpn.c index 25a9492eb..6dc858f97 100644 --- a/src/vpn/gnunet-helper-vpn.c +++ b/src/vpn/gnunet-helper-vpn.c | |||
@@ -62,17 +62,6 @@ struct suid_packet | |||
62 | unsigned char data[1]; | 62 | unsigned char data[1]; |
63 | } | 63 | } |
64 | 64 | ||
65 | static int running = 1; | ||
66 | |||
67 | static void | ||
68 | term (int sig) | ||
69 | { | ||
70 | fprintf (stderr, | ||
71 | "Got SIGTERM...\n"); | ||
72 | if (sig == SIGTERM) | ||
73 | running = 0; | ||
74 | } | ||
75 | |||
76 | 65 | ||
77 | /** | 66 | /** |
78 | * Creates a tun-interface called dev; | 67 | * Creates a tun-interface called dev; |
@@ -113,13 +102,14 @@ init_tun (char *dev) | |||
113 | "Error with ioctl on `%s': %s\n", | 102 | "Error with ioctl on `%s': %s\n", |
114 | "/dev/net/tun", | 103 | "/dev/net/tun", |
115 | strerror(errno)); | 104 | strerror(errno)); |
116 | close(fd); | 105 | close (fd); |
117 | return -1; | 106 | return -1; |
118 | } | 107 | } |
119 | strcpy(dev, ifr.ifr_name); | 108 | strcpy(dev, ifr.ifr_name); |
120 | return fd; | 109 | return fd; |
121 | } | 110 | } |
122 | 111 | ||
112 | |||
123 | /** | 113 | /** |
124 | * @brief Sets the IPv6-Address given in address on the interface dev | 114 | * @brief Sets the IPv6-Address given in address on the interface dev |
125 | * | 115 | * |
@@ -128,53 +118,83 @@ init_tun (char *dev) | |||
128 | * @param prefix_len the length of the network-prefix | 118 | * @param prefix_len the length of the network-prefix |
129 | */ | 119 | */ |
130 | static void | 120 | static void |
131 | set_address6 (char *dev, char *address, unsigned long prefix_len) | 121 | set_address6 (const char *dev, |
122 | const char *address, | ||
123 | unsigned long prefix_len) | ||
132 | { | 124 | { |
133 | int fd = socket (AF_INET6, SOCK_DGRAM, 0); | 125 | struct ifreq ifr; |
126 | struct in6_ifreq ifr6; | ||
127 | struct sockaddr_in6 sa6; | ||
128 | int fd; | ||
134 | 129 | ||
135 | if (fd < 0) | 130 | if (-1 == (fd = socket (PF_INET6, SOCK_DGRAM, 0))) |
136 | { | 131 | { |
137 | fprintf (stderr, "error creating socket: %m\n"); | 132 | fprintf (stderr, |
133 | "Error creating socket: %s\n", | ||
134 | strerror (errno)); | ||
138 | exit (1); | 135 | exit (1); |
139 | } | 136 | } |
140 | |||
141 | struct ifreq ifr; | ||
142 | struct in6_ifreq ifr6; | ||
143 | |||
144 | struct sockaddr_in6 sa6; | ||
145 | memset (&sa6, 0, sizeof (struct sockaddr_in6)); | 137 | memset (&sa6, 0, sizeof (struct sockaddr_in6)); |
146 | |||
147 | sa6.sin6_family = AF_INET6; | 138 | sa6.sin6_family = AF_INET6; |
148 | 139 | ||
149 | int r = inet_pton (AF_INET6, address, sa6.sin6_addr.s6_addr); | 140 | if (1 != inet_pton (AF_INET6, address, sa6.sin6_addr.s6_addr)) |
150 | if (r < 0) | ||
151 | { | 141 | { |
152 | fprintf (stderr, "error at inet_pton: %m\n"); | 142 | fprintf (stderr, |
143 | "Failed to parse address `%s': %s\n", | ||
144 | address, | ||
145 | strerror (errno)); | ||
153 | exit (1); | 146 | exit (1); |
154 | } | 147 | } |
155 | 148 | ||
156 | memcpy ((char *) &ifr6.ifr6_addr, (char *) &sa6.sin6_addr, | 149 | memcpy (&ifr6.ifr6_addr, |
150 | &sa6.sin6_addr, | ||
157 | sizeof (struct in6_addr)); | 151 | sizeof (struct in6_addr)); |
158 | |||
159 | strncpy (ifr.ifr_name, dev, IFNAMSIZ); | 152 | strncpy (ifr.ifr_name, dev, IFNAMSIZ); |
160 | 153 | if (-1 == ioctl (fd, SIOGIFINDEX, &ifr)) | |
161 | if (ioctl (fd, SIOGIFINDEX, &ifr) < 0) | ||
162 | { | 154 | { |
163 | perror ("SIOGIFINDEX"); | 155 | fprintf (stderr, |
156 | "ioctl failed at %d: %s\n", | ||
157 | __LINE__, | ||
158 | strerror (errno)); | ||
159 | exit (1); | ||
164 | } | 160 | } |
165 | 161 | ||
166 | ifr6.ifr6_ifindex = ifr.ifr_ifindex; | 162 | ifr6.ifr6_ifindex = ifr.ifr_ifindex; |
167 | ifr6.ifr6_prefixlen = prefix_len; | 163 | ifr6.ifr6_prefixlen = prefix_len; |
168 | 164 | if (-1 == ioctl (fd, SIOCSIFADDR, &ifr6)) | |
169 | if (ioctl (fd, SIOCSIFADDR, &ifr6) < 0) | ||
170 | { | 165 | { |
171 | perror ("SIOCSIFADDR"); | 166 | fprintf (stderr, |
167 | "ioctl failed at line %d: %s\n", | ||
168 | __LINE__, | ||
169 | strerror (errno)); | ||
170 | exit (1); | ||
172 | } | 171 | } |
173 | 172 | ||
174 | (void) ioctl (fd, SIOCGIFFLAGS, &ifr); | 173 | if (-1 == ioctl (fd, SIOCGIFFLAGS, &ifr)) |
174 | { | ||
175 | fprintf (stderr, | ||
176 | "ioctl failed at line %d: %s\n", | ||
177 | __LINE__, | ||
178 | strerror (errno)); | ||
179 | exit (1); | ||
180 | } | ||
175 | ifr.ifr_flags |= IFF_UP | IFF_RUNNING; | 181 | ifr.ifr_flags |= IFF_UP | IFF_RUNNING; |
176 | (void) ioctl (fd, SIOCSIFFLAGS, &ifr); | 182 | if (-1 == ioctl (fd, SIOCSIFFLAGS, &ifr)) |
177 | close (fd); | 183 | { |
184 | fprintf (stderr, | ||
185 | "ioctl failed at line %d: %s\n", | ||
186 | __LINE__, | ||
187 | strerror (errno)); | ||
188 | exit (1); | ||
189 | } | ||
190 | |||
191 | if (0 != close (fd)) | ||
192 | { | ||
193 | fprintf (stderr, | ||
194 | "close failed: %s\n", | ||
195 | strerror (errno)); | ||
196 | exit (1); | ||
197 | } | ||
178 | } | 198 | } |
179 | 199 | ||
180 | 200 | ||
@@ -243,79 +263,19 @@ set_address4 (char *dev, char *address, char *mask) | |||
243 | } | 263 | } |
244 | 264 | ||
245 | 265 | ||
246 | /** | ||
247 | * @brief sets the socket to nonblocking | ||
248 | * | ||
249 | * @param fd the socket | ||
250 | */ | ||
251 | static void | 266 | static void |
252 | setnonblocking (int fd) | 267 | run (int fd_tun) |
253 | { /*{{{ */ | ||
254 | int opts; | ||
255 | opts = fcntl(fd,F_GETFL); | ||
256 | if (opts < 0) { | ||
257 | perror("fcntl(F_GETFL)"); | ||
258 | } | ||
259 | opts = (opts | O_NONBLOCK); | ||
260 | if (fcntl(fd,F_SETFL,opts) < 0) { | ||
261 | perror("fcntl(F_SETFL)"); | ||
262 | } | ||
263 | return; | ||
264 | } | ||
265 | |||
266 | |||
267 | int | ||
268 | main(int argc, char** argv) | ||
269 | { | 268 | { |
270 | unsigned char buf[MAX_SIZE]; | 269 | unsigned char buf[MAX_SIZE]; |
271 | |||
272 | char dev[IFNAMSIZ]; | ||
273 | memset (dev, 0, IFNAMSIZ); | ||
274 | |||
275 | signal (SIGTERM, &term); | ||
276 | |||
277 | int fd_tun = init_tun (dev); | ||
278 | |||
279 | if (fd_tun < 0) | ||
280 | { | ||
281 | fprintf (stderr, "Could not initialize tun-interface: %s\n", | ||
282 | strerror (errno)); | ||
283 | exit (1); | ||
284 | } | ||
285 | |||
286 | { | ||
287 | // TODO: get this out of argv | ||
288 | char address[] = "1234::1"; | ||
289 | unsigned long prefix_len = 16; | ||
290 | |||
291 | set_address6 (dev, address, prefix_len); | ||
292 | } | ||
293 | |||
294 | { | ||
295 | char address[] = "10.10.10.1"; | ||
296 | char mask[] = "255.255.255.252"; | ||
297 | |||
298 | set_address4 (dev, address, mask); | ||
299 | } | ||
300 | |||
301 | uid_t uid = getuid (); | ||
302 | if (setresuid (uid, uid, uid) != 0) | ||
303 | fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno)); | ||
304 | |||
305 | setnonblocking (0); | ||
306 | setnonblocking (1); | ||
307 | setnonblocking (fd_tun); | ||
308 | |||
309 | fd_set fds_w; | 270 | fd_set fds_w; |
310 | fd_set fds_r; | 271 | fd_set fds_r; |
311 | |||
312 | int rea = 1; | 272 | int rea = 1; |
313 | int wri = 1; | 273 | int wri = 1; |
314 | |||
315 | int write_fd_possible = 0; | 274 | int write_fd_possible = 0; |
316 | int write_stdout_possible = 0; | 275 | int write_stdout_possible = 0; |
276 | ssize_t tin; | ||
317 | outer: | 277 | outer: |
318 | while ((rea == 1 || wri == 1) && running == 1) | 278 | while ((1 == rea) || (1 == wri)) |
319 | { | 279 | { |
320 | FD_ZERO (&fds_w); | 280 | FD_ZERO (&fds_w); |
321 | FD_ZERO (&fds_r); | 281 | FD_ZERO (&fds_r); |
@@ -334,8 +294,7 @@ outer: | |||
334 | FD_SET (fd_tun, &fds_w); | 294 | FD_SET (fd_tun, &fds_w); |
335 | } | 295 | } |
336 | 296 | ||
337 | int r = select (fd_tun + 1, &fds_r, &fds_w, (fd_set *) 0, 0); | 297 | int r = select (fd_tun + 1, &fds_r, &fds_w, NULL, NULL); |
338 | |||
339 | if (r > 0) | 298 | if (r > 0) |
340 | { | 299 | { |
341 | if (FD_ISSET (fd_tun, &fds_w)) | 300 | if (FD_ISSET (fd_tun, &fds_w)) |
@@ -347,8 +306,8 @@ outer: | |||
347 | { | 306 | { |
348 | write_fd_possible = 0; | 307 | write_fd_possible = 0; |
349 | struct suid_packet *pkt = (struct suid_packet *) buf; | 308 | struct suid_packet *pkt = (struct suid_packet *) buf; |
350 | r = read (0, buf, sizeof (struct GNUNET_MessageHeader)); | 309 | tin = read (0, buf, sizeof (struct GNUNET_MessageHeader)); |
351 | if (r <= 0) | 310 | if (tin <= 0) |
352 | { | 311 | { |
353 | fprintf (stderr, "read-error: %s\n", strerror (errno)); | 312 | fprintf (stderr, "read-error: %s\n", strerror (errno)); |
354 | shutdown (fd_tun, SHUT_WR); | 313 | shutdown (fd_tun, SHUT_WR); |
@@ -358,10 +317,10 @@ outer: | |||
358 | } | 317 | } |
359 | if (pkt->hdr.type != ntohs (GNUNET_MESSAGE_TYPE_VPN_HELPER)) | 318 | if (pkt->hdr.type != ntohs (GNUNET_MESSAGE_TYPE_VPN_HELPER)) |
360 | abort (); | 319 | abort (); |
361 | while (r < ntohs (pkt->hdr.size)) | 320 | while (tin < ntohs (pkt->hdr.size)) |
362 | { | 321 | { |
363 | int t = read (0, buf + r, ntohs (pkt->hdr.size) - r); | 322 | ssize_t t = read (0, buf + tin, ntohs (pkt->hdr.size) - tin); |
364 | if (r < 0) | 323 | if (t <= 0) |
365 | { | 324 | { |
366 | fprintf (stderr, "read-error: %s\n", strerror (errno)); | 325 | fprintf (stderr, "read-error: %s\n", strerror (errno)); |
367 | shutdown (fd_tun, SHUT_WR); | 326 | shutdown (fd_tun, SHUT_WR); |
@@ -369,17 +328,17 @@ outer: | |||
369 | wri = 0; | 328 | wri = 0; |
370 | goto outer; | 329 | goto outer; |
371 | } | 330 | } |
372 | r += t; | 331 | tin += t; |
373 | } | 332 | } |
374 | r = 0; | 333 | tin = 0; |
375 | while (r < | 334 | while (tin < |
376 | ntohs (pkt->hdr.size) - | 335 | ntohs (pkt->hdr.size) - |
377 | sizeof (struct GNUNET_MessageHeader)) | 336 | sizeof (struct GNUNET_MessageHeader)) |
378 | { | 337 | { |
379 | int t = write (fd_tun, pkt->data, | 338 | ssize_t t = write (fd_tun, pkt->data, |
380 | ntohs (pkt->hdr.size) - | 339 | ntohs (pkt->hdr.size) - |
381 | sizeof (struct GNUNET_MessageHeader) - r); | 340 | sizeof (struct GNUNET_MessageHeader) - tin); |
382 | if (t < 0) | 341 | if (t <= 0) |
383 | { | 342 | { |
384 | fprintf (stderr, "write-error 3: %s\n", | 343 | fprintf (stderr, "write-error 3: %s\n", |
385 | strerror (errno)); | 344 | strerror (errno)); |
@@ -388,14 +347,14 @@ outer: | |||
388 | wri = 0; | 347 | wri = 0; |
389 | goto outer; | 348 | goto outer; |
390 | } | 349 | } |
391 | r += t; | 350 | tin += t; |
392 | } | 351 | } |
393 | } | 352 | } |
394 | else if (write_stdout_possible && FD_ISSET (fd_tun, &fds_r)) | 353 | else if (write_stdout_possible && FD_ISSET (fd_tun, &fds_r)) |
395 | { | 354 | { |
396 | write_stdout_possible = 0; | 355 | write_stdout_possible = 0; |
397 | r = read (fd_tun, buf, MAX_SIZE); | 356 | tin = read (fd_tun, buf, MAX_SIZE); |
398 | if (r <= 0) | 357 | if (tin <= 0) |
399 | { | 358 | { |
400 | fprintf (stderr, "read-error: %s\n", strerror (errno)); | 359 | fprintf (stderr, "read-error: %s\n", strerror (errno)); |
401 | shutdown (fd_tun, SHUT_RD); | 360 | shutdown (fd_tun, SHUT_RD); |
@@ -407,11 +366,11 @@ outer: | |||
407 | htons (r + sizeof (struct GNUNET_MessageHeader)),.type = | 366 | htons (r + sizeof (struct GNUNET_MessageHeader)),.type = |
408 | htons (GNUNET_MESSAGE_TYPE_VPN_HELPER) | 367 | htons (GNUNET_MESSAGE_TYPE_VPN_HELPER) |
409 | }; | 368 | }; |
410 | r = 0; | 369 | tin = 0; |
411 | while (r < sizeof (struct GNUNET_MessageHeader)) | 370 | while (tin < sizeof (struct GNUNET_MessageHeader)) |
412 | { | 371 | { |
413 | int t = | 372 | ssize_t t = |
414 | write (1, &hdr, sizeof (struct GNUNET_MessageHeader) - r); | 373 | write (1, &hdr, sizeof (struct GNUNET_MessageHeader) - tin); |
415 | if (t < 0) | 374 | if (t < 0) |
416 | { | 375 | { |
417 | fprintf (stderr, "write-error 2: %s\n", | 376 | fprintf (stderr, "write-error 2: %s\n", |
@@ -421,11 +380,11 @@ outer: | |||
421 | rea = 0; | 380 | rea = 0; |
422 | goto outer; | 381 | goto outer; |
423 | } | 382 | } |
424 | r += t; | 383 | tin += t; |
425 | } | 384 | } |
426 | while (r < ntohs (hdr.size)) | 385 | while (tin < ntohs (hdr.size)) |
427 | { | 386 | { |
428 | int t = write (1, buf, ntohs (hdr.size) - r); | 387 | size_t t = write (1, buf, ntohs (hdr.size) - tin); |
429 | if (t < 0) | 388 | if (t < 0) |
430 | { | 389 | { |
431 | fprintf (stderr, "write-error 1: %s, written %d/%d\n", | 390 | fprintf (stderr, "write-error 1: %s, written %d/%d\n", |
@@ -435,13 +394,81 @@ outer: | |||
435 | rea = 0; | 394 | rea = 0; |
436 | goto outer; | 395 | goto outer; |
437 | } | 396 | } |
438 | r += t; | 397 | tin += t; |
439 | } | 398 | } |
440 | } | 399 | } |
441 | } | 400 | } |
442 | } | 401 | } |
402 | } | ||
403 | |||
443 | 404 | ||
444 | close (fd_tun); | ||
445 | 405 | ||
406 | /** | ||
407 | * @brief sets the socket to nonblocking | ||
408 | * | ||
409 | * @param fd the socket | ||
410 | */ | ||
411 | static void | ||
412 | setnonblocking (int fd) | ||
413 | { | ||
414 | int opts; | ||
415 | |||
416 | if (-1 == (opts = fcntl (fd, F_GETFL))) | ||
417 | { | ||
418 | fprintf (stderr, | ||
419 | "Error in fcntl at line %d: %s\n", | ||
420 | __LINE__, | ||
421 | strerror (errno)); | ||
422 | exit (1); | ||
423 | } | ||
424 | opts |= O_NONBLOCK; | ||
425 | if (-1 == fcntl (fd, F_SETFL, opts)) | ||
426 | { | ||
427 | fprintf (stderr, | ||
428 | "Error in fcntl at line %d: %s\n", | ||
429 | __LINE__, | ||
430 | strerror (errno)); | ||
431 | exit (1); | ||
432 | } | ||
433 | } | ||
434 | |||
435 | |||
436 | int | ||
437 | main (int argc, | ||
438 | char** argv) | ||
439 | { | ||
440 | char dev[IFNAMSIZ]; | ||
441 | int fd_tun; | ||
442 | |||
443 | memset (dev, 0, IFNAMSIZ); | ||
444 | if (-1 == (fd_tun = init_tun (dev))) | ||
445 | { | ||
446 | fprintf (stderr, | ||
447 | "Fatal: could not initialize tun-interface\n"); | ||
448 | return 1; | ||
449 | } | ||
450 | |||
451 | { | ||
452 | // TODO: get this out of argv | ||
453 | char address[] = "1234::1"; | ||
454 | unsigned long prefix_len = 16; | ||
455 | |||
456 | set_address6 (dev, address, prefix_len); | ||
457 | } | ||
458 | |||
459 | { | ||
460 | char address[] = "10.10.10.1"; | ||
461 | char mask[] = "255.255.255.252"; | ||
462 | |||
463 | set_address4 (dev, address, mask); | ||
464 | } | ||
465 | |||
466 | uid_t uid = getuid (); | ||
467 | if (0 != setresuid (uid, uid, uid)) | ||
468 | fprintf (stderr, | ||
469 | "Failed to setresuid: %s\n", | ||
470 | strerror (errno)); | ||
471 | run (fd_tun); | ||
472 | close (fd_tun); | ||
446 | return 0; | 473 | return 0; |
447 | } | 474 | } |