aboutsummaryrefslogtreecommitdiff
path: root/src/vpn/gnunet-helper-vpn.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-02-02 09:04:42 +0000
committerChristian Grothoff <christian@grothoff.org>2011-02-02 09:04:42 +0000
commit3b3eb36e3a01c7046fe4c9a3c4bb7834d83442d6 (patch)
treee9bc242ae37f3393d5939dbfafaeca32bcc95ebb /src/vpn/gnunet-helper-vpn.c
parentaefe648c889dd71ba942ccb235fe9eec477f2b53 (diff)
downloadgnunet-3b3eb36e3a01c7046fe4c9a3c4bb7834d83442d6.tar.gz
gnunet-3b3eb36e3a01c7046fe4c9a3c4bb7834d83442d6.zip
fixing bugs, declaring safe
Diffstat (limited to 'src/vpn/gnunet-helper-vpn.c')
-rw-r--r--src/vpn/gnunet-helper-vpn.c241
1 files changed, 154 insertions, 87 deletions
diff --git a/src/vpn/gnunet-helper-vpn.c b/src/vpn/gnunet-helper-vpn.c
index 06f07f542..37ec71868 100644
--- a/src/vpn/gnunet-helper-vpn.c
+++ b/src/vpn/gnunet-helper-vpn.c
@@ -24,8 +24,15 @@
24 * sends data received on the if to stdout, sends data received on stdin to the 24 * sends data received on the if to stdout, sends data received on stdin to the
25 * interface 25 * interface
26 * @author Philipp Tölke 26 * @author Philipp Tölke
27 *
28 * The following list of people have reviewed this code and considered
29 * it safe since the last modification (if you reviewed it, please
30 * have your name added to the list):
31 *
32 * - Philipp Tölke
33 * - Christian Grothoff
27 */ 34 */
28#include <platform.h> 35#include "platform.h"
29#include <linux/if_tun.h> 36#include <linux/if_tun.h>
30 37
31/** 38/**
@@ -82,7 +89,7 @@ init_tun (char *dev)
82 89
83 if (fd >= FD_SETSIZE) 90 if (fd >= FD_SETSIZE)
84 { 91 {
85 fprintf (stderr, "Filedescriptor to large: %d", fd); 92 fprintf (stderr, "File descriptor to large: %d", fd);
86 return -1; 93 return -1;
87 } 94 }
88 95
@@ -113,24 +120,19 @@ init_tun (char *dev)
113 * @param prefix_len the length of the network-prefix 120 * @param prefix_len the length of the network-prefix
114 */ 121 */
115static void 122static void
116set_address6 (const char *dev, const char *address, unsigned long prefix_len) 123set_address6 (const char *dev,
124 const char *address,
125 unsigned long prefix_len)
117{ 126{
118 struct ifreq ifr; 127 struct ifreq ifr;
119 struct in6_ifreq ifr6; 128 struct in6_ifreq ifr6;
120 struct sockaddr_in6 sa6; 129 struct sockaddr_in6 sa6;
121 int fd; 130 int fd;
122 131
123 if (-1 == (fd = socket (PF_INET6, SOCK_DGRAM, 0)))
124 {
125 fprintf (stderr, "Error creating socket: %s\n", strerror (errno));
126 exit (1);
127 }
128 memset (&sa6, 0, sizeof (struct sockaddr_in6));
129 sa6.sin6_family = AF_INET6;
130
131 /* 132 /*
132 * parse the new address 133 * parse the new address
133 */ 134 */
135 memset (&sa6, 0, sizeof (struct sockaddr_in6));
134 if (1 != inet_pton (AF_INET6, address, sa6.sin6_addr.s6_addr)) 136 if (1 != inet_pton (AF_INET6, address, sa6.sin6_addr.s6_addr))
135 { 137 {
136 fprintf (stderr, 138 fprintf (stderr,
@@ -138,7 +140,19 @@ set_address6 (const char *dev, const char *address, unsigned long prefix_len)
138 address, strerror (errno)); 140 address, strerror (errno));
139 exit (1); 141 exit (1);
140 } 142 }
141 memcpy (&ifr6.ifr6_addr, &sa6.sin6_addr, sizeof (struct in6_addr)); 143
144 if (-1 == (fd = socket (PF_INET6, SOCK_DGRAM, 0)))
145 {
146 fprintf (stderr,
147 "Error creating socket: %s\n",
148 strerror (errno));
149 exit (1);
150 }
151
152 sa6.sin6_family = AF_INET6;
153 memcpy (&ifr6.ifr6_addr,
154 &sa6.sin6_addr,
155 sizeof (struct in6_addr));
142 156
143 157
144 /* 158 /*
@@ -148,7 +162,9 @@ set_address6 (const char *dev, const char *address, unsigned long prefix_len)
148 if (-1 == ioctl (fd, SIOGIFINDEX, &ifr)) 162 if (-1 == ioctl (fd, SIOGIFINDEX, &ifr))
149 { 163 {
150 fprintf (stderr, 164 fprintf (stderr,
151 "ioctl failed at %d: %s\n", __LINE__, strerror (errno)); 165 "ioctl failed at %d: %s\n",
166 __LINE__,
167 strerror (errno));
152 exit (1); 168 exit (1);
153 } 169 }
154 ifr6.ifr6_ifindex = ifr.ifr_ifindex; 170 ifr6.ifr6_ifindex = ifr.ifr_ifindex;
@@ -202,9 +218,11 @@ set_address6 (const char *dev, const char *address, unsigned long prefix_len)
202 * @param mask the netmask 218 * @param mask the netmask
203 */ 219 */
204static void 220static void
205set_address4 (char *dev, char *address, char *mask) 221set_address4 (const char *dev,
222 const char *address,
223 const char *mask)
206{ 224{
207 int fd = 0; 225 int fd;
208 struct sockaddr_in *addr; 226 struct sockaddr_in *addr;
209 struct ifreq ifr; 227 struct ifreq ifr;
210 228
@@ -217,18 +235,21 @@ set_address4 (char *dev, char *address, char *mask)
217 /* 235 /*
218 * Parse the address 236 * Parse the address
219 */ 237 */
220 int r = inet_pton (AF_INET, address, &addr->sin_addr.s_addr); 238 if (1 != inet_pton (AF_INET, address, &addr->sin_addr.s_addr))
221 if (r < 0)
222 { 239 {
223 fprintf (stderr, "error at inet_pton: %m\n"); 240 fprintf (stderr,
241 "Failed to parse address `%s': %s\n",
242 address, strerror (errno));
224 exit (1); 243 exit (1);
225 } 244 }
226 245
227 fd = socket (PF_INET, SOCK_DGRAM, 0); 246
228 if (fd < 0) 247 if (-1 == (fd = socket (PF_INET, SOCK_DGRAM, 0)))
229 { 248 {
230 perror ("socket()"); 249 fprintf (stderr,
231 return; 250 "Error creating socket: %s\n",
251 strerror (errno));
252 exit (1);
232 } 253 }
233 254
234 strncpy (ifr.ifr_name, dev, IFNAMSIZ); 255 strncpy (ifr.ifr_name, dev, IFNAMSIZ);
@@ -236,32 +257,36 @@ set_address4 (char *dev, char *address, char *mask)
236 /* 257 /*
237 * Set the address 258 * Set the address
238 */ 259 */
239 if (ioctl (fd, SIOCSIFADDR, &ifr) != 0) 260 if (-1 == ioctl (fd, SIOCSIFADDR, &ifr))
240 { 261 {
241 perror ("SIOCSIFADDR"); 262 fprintf (stderr,
242 close (fd); 263 "ioctl failed at %d: %s\n",
243 return; 264 __LINE__,
265 strerror (errno));
266 exit (1);
244 } 267 }
245 268
246 /* 269 /*
247 * Parse the netmask 270 * Parse the netmask
248 */ 271 */
249 addr = (struct sockaddr_in *) &(ifr.ifr_netmask); 272 addr = (struct sockaddr_in *) &(ifr.ifr_netmask);
250 r = inet_pton (AF_INET, mask, &addr->sin_addr.s_addr); 273 if (1 != inet_pton (AF_INET, mask, &addr->sin_addr.s_addr))
251 if (r < 0)
252 { 274 {
253 fprintf (stderr, "error at inet_pton: %m\n"); 275 fprintf (stderr,
276 "Failed to parse address `%s': %s\n",
277 mask,
278 strerror (errno));
254 exit (1); 279 exit (1);
255 } 280 }
256 281
257 /* 282 /*
258 * Set the netmask 283 * Set the netmask
259 */ 284 */
260 if (ioctl (fd, SIOCSIFNETMASK, &ifr) != 0) 285 if (-1 == ioctl (fd, SIOCSIFNETMASK, &ifr))
261 { 286 {
262 perror ("SIOCSIFNETMASK"); 287 fprintf (stderr,
263 close (fd); 288 "ioctl failed at line %d: %s\n", __LINE__, strerror (errno));
264 return; 289 exit (1);
265 } 290 }
266 291
267 /* 292 /*
@@ -301,22 +326,25 @@ run (int fd_tun)
301 */ 326 */
302 unsigned char buftun[MAX_SIZE]; 327 unsigned char buftun[MAX_SIZE];
303 ssize_t buftun_size = 0; 328 ssize_t buftun_size = 0;
304 unsigned char *buftun_read = 0; 329 unsigned char *buftun_read;
305 330
306 /* 331 /*
307 * The buffer filled by reading from stdin 332 * The buffer filled by reading from stdin
308 */ 333 */
309 unsigned char bufin[MAX_SIZE]; 334 unsigned char bufin[MAX_SIZE];
310 ssize_t bufin_size = 0; 335 ssize_t bufin_size = 0;
311 unsigned char *bufin_write = 0; 336 size_t bufin_rpos = 0;
337 unsigned char *bufin_read = NULL;
312 338
313 fd_set fds_w; 339 fd_set fds_w;
314 fd_set fds_r; 340 fd_set fds_r;
315 341
316 int rea = 1; 342 /* read refers to reading from fd_tun, writing to stdout */
317 int wri = 1; 343 int read_open = 1;
344 /* write refers to reading from stdin, writing to fd_tun */
345 int write_open = 1;
318 346
319 while ((1 == rea) || (1 == wri)) 347 while ((1 == read_open) || (1 == write_open))
320 { 348 {
321 FD_ZERO (&fds_w); 349 FD_ZERO (&fds_w);
322 FD_ZERO (&fds_r); 350 FD_ZERO (&fds_r);
@@ -325,41 +353,35 @@ run (int fd_tun)
325 * We are supposed to read and the buffer is empty 353 * We are supposed to read and the buffer is empty
326 * -> select on read from tun 354 * -> select on read from tun
327 */ 355 */
328 if (rea && (0 == buftun_size)) 356 if (read_open && (0 == buftun_size))
329 { 357 FD_SET (fd_tun, &fds_r);
330 FD_SET (fd_tun, &fds_r);
331 }
332 358
333 /* 359 /*
334 * We are supposed to read and the buffer is not empty 360 * We are supposed to read and the buffer is not empty
335 * -> select on write to stdout 361 * -> select on write to stdout
336 */ 362 */
337 if (rea && (0 != buftun_size)) 363 if (read_open && (0 != buftun_size))
338 { 364 FD_SET (1, &fds_w);
339 FD_SET (1, &fds_w);
340 }
341 365
342 /* 366 /*
343 * We are supposed to write and the buffer is empty 367 * We are supposed to write and the buffer is empty
344 * -> select on read from stdin 368 * -> select on read from stdin
345 */ 369 */
346 if (wri && (0 == bufin_size)) 370 if (write_open && (NULL == bufin_read))
347 { 371 FD_SET (0, &fds_r);
348 FD_SET (0, &fds_r);
349 }
350 372
351 /* 373 /*
352 * We are supposed to write and the buffer is not empty 374 * We are supposed to write and the buffer is not empty
353 * -> select on write to tun 375 * -> select on write to tun
354 */ 376 */
355 if (wri && (0 != bufin_size)) 377 if (write_open && (NULL != bufin_read))
356 { 378 FD_SET (fd_tun, &fds_w);
357 FD_SET (fd_tun, &fds_w);
358 }
359 379
360 int r = select (fd_tun + 1, &fds_r, &fds_w, NULL, NULL); 380 int r = select (fd_tun + 1, &fds_r, &fds_w, NULL, NULL);
361 if (-1 == r) 381 if (-1 == r)
362 { 382 {
383 if (EINTR == errno)
384 continue;
363 fprintf (stderr, "select failed: %s\n", strerror (errno)); 385 fprintf (stderr, "select failed: %s\n", strerror (errno));
364 exit (1); 386 exit (1);
365 } 387 }
@@ -370,22 +392,21 @@ run (int fd_tun)
370 { 392 {
371 buftun_size = 393 buftun_size =
372 read (fd_tun, buftun + sizeof (struct GNUNET_MessageHeader), 394 read (fd_tun, buftun + sizeof (struct GNUNET_MessageHeader),
373 MAX_SIZE - sizeof (struct GNUNET_MessageHeader)) + 395 MAX_SIZE - sizeof (struct GNUNET_MessageHeader));
374 sizeof (struct GNUNET_MessageHeader);
375 if (-1 == buftun_size) 396 if (-1 == buftun_size)
376 { 397 {
377 fprintf (stderr, "read-error: %s\n", strerror (errno)); 398 fprintf (stderr, "read-error: %s\n", strerror (errno));
378 shutdown (fd_tun, SHUT_RD); 399 shutdown (fd_tun, SHUT_RD);
379 shutdown (1, SHUT_WR); 400 shutdown (1, SHUT_WR);
380 rea = 0; 401 read_open = 0;
381 buftun_size = 0; 402 buftun_size = 0;
382 } 403 }
383 else if (0 == buftun_size) 404 else if (0 == buftun_size)
384 { 405 {
385 fprintf (stderr, "eof on tun\n"); 406 fprintf (stderr, "EOF on tun\n");
386 shutdown (fd_tun, SHUT_RD); 407 shutdown (fd_tun, SHUT_RD);
387 shutdown (1, SHUT_WR); 408 shutdown (1, SHUT_WR);
388 rea = 0; 409 read_open = 0;
389 buftun_size = 0; 410 buftun_size = 0;
390 } 411 }
391 else 412 else
@@ -393,6 +414,7 @@ run (int fd_tun)
393 buftun_read = buftun; 414 buftun_read = buftun;
394 struct GNUNET_MessageHeader *hdr = 415 struct GNUNET_MessageHeader *hdr =
395 (struct GNUNET_MessageHeader *) buftun; 416 (struct GNUNET_MessageHeader *) buftun;
417 buftun_size += sizeof (struct GNUNET_MessageHeader);
396 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); 418 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
397 hdr->size = htons (buftun_size); 419 hdr->size = htons (buftun_size);
398 } 420 }
@@ -402,65 +424,102 @@ run (int fd_tun)
402 ssize_t written = write (1, buftun_read, buftun_size); 424 ssize_t written = write (1, buftun_read, buftun_size);
403 if (-1 == written) 425 if (-1 == written)
404 { 426 {
405 fprintf (stderr, "write-error to stdout: %s\n", 427 fprintf (stderr,
428 "write-error to stdout: %s\n",
406 strerror (errno)); 429 strerror (errno));
407 shutdown (fd_tun, SHUT_RD); 430 shutdown (fd_tun, SHUT_RD);
408 shutdown (1, SHUT_WR); 431 shutdown (1, SHUT_WR);
409 rea = 0; 432 read_open = 0;
410 buftun_size = 0; 433 buftun_size = 0;
411 } 434 }
412 buftun_size -= written; 435 else if (0 == written)
413 buftun_read += written; 436 {
437 fprintf (stderr,
438 "write returned 0!?\n");
439 exit (1);
440 }
441 else
442 {
443 buftun_size -= written;
444 buftun_read += written;
445 }
414 } 446 }
415 447
416 if (FD_ISSET (0, &fds_r)) 448 if (FD_ISSET (0, &fds_r))
417 { 449 {
418 bufin_size = read (0, bufin, MAX_SIZE); 450 bufin_size = read (0, bufin + bufin_rpos, MAX_SIZE - bufin_rpos);
419 if (-1 == bufin_size) 451 if (-1 == bufin_size)
420 { 452 {
421 fprintf (stderr, "read-error: %s\n", strerror (errno)); 453 fprintf (stderr,
454 "read-error: %s\n",
455 strerror (errno));
422 shutdown (0, SHUT_RD); 456 shutdown (0, SHUT_RD);
423 shutdown (fd_tun, SHUT_WR); 457 shutdown (fd_tun, SHUT_WR);
424 wri = 0; 458 write_open = 0;
425 bufin_size = 0; 459 bufin_size = 0;
426 } 460 }
427 else if (0 == bufin_size) 461 else if (0 == bufin_size)
428 { 462 {
429 fprintf (stderr, "eof on stdin\n"); 463 fprintf (stderr,
464 "EOF on stdin\n");
430 shutdown (0, SHUT_RD); 465 shutdown (0, SHUT_RD);
431 shutdown (fd_tun, SHUT_WR); 466 shutdown (fd_tun, SHUT_WR);
432 wri = 0; 467 write_open = 0;
433 bufin_size = 0; 468 bufin_size = 0;
434 } 469 }
435 else 470 else
436 { 471 {
437 struct GNUNET_MessageHeader *hdr = 472 struct GNUNET_MessageHeader *hdr;
438 (struct GNUNET_MessageHeader *) bufin; 473
439 if ((bufin_size < sizeof (struct GNUNET_MessageHeader)) 474 PROCESS_BUFFER:
440 || (ntohs (hdr->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) 475 bufin_rpos += bufin_size;
441 || (ntohs (hdr->size) != bufin_size)) 476 if (bufin_rpos < sizeof (struct GNUNET_MessageHeader))
477 continue;
478 hdr = (struct GNUNET_MessageHeader *) bufin;
479 if (ntohs (hdr->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER)
442 { 480 {
443 fprintf (stderr, "protocol violation!\n"); 481 fprintf (stderr, "protocol violation!\n");
444 exit (1); 482 exit (1);
445 } 483 }
446 bufin_write = bufin + sizeof (struct GNUNET_MessageHeader); 484 if (ntohs (hdr->size) > bufin_rpos)
447 bufin_size -= sizeof (struct GNUNET_MessageHeader); 485 continue;
486 bufin_read = bufin + sizeof (struct GNUNET_MessageHeader);
487 bufin_size = ntohs (hdr->size) - sizeof (struct GNUNET_MessageHeader);
488 bufin_rpos -= bufin_size + sizeof (struct GNUNET_MessageHeader);
448 } 489 }
449 } 490 }
450 else if (FD_ISSET (fd_tun, &fds_w)) 491 else if (FD_ISSET (fd_tun, &fds_w))
451 { 492 {
452 ssize_t written = write (fd_tun, bufin_write, bufin_size); 493 ssize_t written = write (fd_tun, bufin_read, bufin_size);
453 if (-1 == written) 494 if (-1 == written)
454 { 495 {
455 fprintf (stderr, "write-error to tun: %s\n", 496 fprintf (stderr, "write-error to tun: %s\n",
456 strerror (errno)); 497 strerror (errno));
457 shutdown (0, SHUT_RD); 498 shutdown (0, SHUT_RD);
458 shutdown (fd_tun, SHUT_WR); 499 shutdown (fd_tun, SHUT_WR);
459 wri = 0; 500 write_open = 0;
460 bufin_size = 0; 501 bufin_size = 0;
461 } 502 }
462 bufin_size -= written; 503 else if (0 == written)
463 bufin_write += written; 504 {
505 fprintf (stderr,
506 "write returned 0!?\n");
507 exit (1);
508 }
509 else
510 {
511 bufin_size -= written;
512 bufin_read += written;
513 if (0 == bufin_size)
514 {
515 memmove (bufin,
516 bufin_read,
517 bufin_rpos);
518 bufin_read = NULL; /* start reading again */
519 bufin_size = 0;
520 goto PROCESS_BUFFER;
521 }
522 }
464 } 523 }
465 } 524 }
466 } 525 }
@@ -476,21 +535,23 @@ main (int argc, char **argv)
476 memset (dev, 0, IFNAMSIZ); 535 memset (dev, 0, IFNAMSIZ);
477 if (-1 == (fd_tun = init_tun (dev))) 536 if (-1 == (fd_tun = init_tun (dev)))
478 { 537 {
479 fprintf (stderr, "Fatal: could not initialize tun-interface\n"); 538 fprintf (stderr,
539 "Fatal: could not initialize tun-interface\n");
480 return 1; 540 return 1;
481 } 541 }
482 542
483 if (5 != argc) 543 if (5 != argc)
484 { 544 {
485 fprintf(stderr, "Fatal: must supply 4 arguments!\n"); 545 fprintf (stderr,
546 "Fatal: must supply 4 arguments!\n");
486 return 1; 547 return 1;
487 } 548 }
488 549
489 { 550 {
490 char *address = argv[1]; 551 const char *address = argv[1];
491 long prefix_len = atol(argv[2]); 552 long prefix_len = atol(argv[2]);
492 553
493 if (prefix_len < 1 || prefix_len > 127) 554 if ( (prefix_len < 1) || (prefix_len > 127) )
494 { 555 {
495 fprintf(stderr, "Fatal: prefix_len out of range\n"); 556 fprintf(stderr, "Fatal: prefix_len out of range\n");
496 return 1; 557 return 1;
@@ -498,17 +559,23 @@ main (int argc, char **argv)
498 559
499 set_address6 (dev, address, prefix_len); 560 set_address6 (dev, address, prefix_len);
500 } 561 }
501 562
502 { 563 {
503 char *address = argv[3]; 564 const char *address = argv[3];
504 char *mask = argv[4]; 565 const char *mask = argv[4];
505 566
506 set_address4 (dev, address, mask); 567 set_address4 (dev, address, mask);
507 } 568 }
508 569
509 uid_t uid = getuid (); 570 uid_t uid = getuid ();
510 if (0 != setresuid (uid, uid, uid)) 571 if (0 != setresuid (uid, uid, uid))
511 fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno)); 572 fprintf (stderr,
573 "Failed to setresuid: %s\n",
574 strerror (errno));
575 if (SIG_ERR == signal (SIGPIPE, SIG_IGN))
576 fprintf (stderr,
577 "Failed to protect against SIGPIPE: %s\n",
578 strerror (errno));
512 run (fd_tun); 579 run (fd_tun);
513 close (fd_tun); 580 close (fd_tun);
514 return 0; 581 return 0;