aboutsummaryrefslogtreecommitdiff
path: root/src/exit/gnunet-helper-exit.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-01-14 20:58:36 +0000
committerChristian Grothoff <christian@grothoff.org>2012-01-14 20:58:36 +0000
commit4f285bb38af149f35a1bd3e730ac6bac7b14fd53 (patch)
tree690774a9d24d61f7713f38ca3574d0b620ff661b /src/exit/gnunet-helper-exit.c
parentc1e66b2a4e2ccf3fc4f3396d97254fa058c6ae73 (diff)
downloadgnunet-4f285bb38af149f35a1bd3e730ac6bac7b14fd53.tar.gz
gnunet-4f285bb38af149f35a1bd3e730ac6bac7b14fd53.zip
changing exit helper code to automatically do the network configuration for an exit node (by running sysctl/iptables commands as necessary)
Diffstat (limited to 'src/exit/gnunet-helper-exit.c')
-rw-r--r--src/exit/gnunet-helper-exit.c175
1 files changed, 147 insertions, 28 deletions
diff --git a/src/exit/gnunet-helper-exit.c b/src/exit/gnunet-helper-exit.c
index 84b6e6e65..d1db2a6e6 100644
--- a/src/exit/gnunet-helper-exit.c
+++ b/src/exit/gnunet-helper-exit.c
@@ -19,16 +19,21 @@
19*/ 19*/
20 20
21/** 21/**
22 * @file exit/gnunet-helper-exit.c 22 * @file exit/gnunet-helper-exit.c
23 * @brief the helper for exit nodes. Opens a virtual network-interface, 23 *
24 * sends data received on the if to stdout, sends data received on stdin to the 24 * @brief the helper for exit nodes. Opens a virtual
25 * interface 25 * network-interface, sends data received on the if to stdout, sends
26 * @author Philipp Tölke 26 * data received on stdin to the interface. The code also enables
27 * IPv4/IPv6 forwarding and NAT on the current system (the latter on
28 * an interface specified on the command-line); these changes to the
29 * network configuration are NOT automatically undone when the program
30 * is stopped (this is because we cannot be sure that some other
31 * application didn't enable them before or after us; also, these
32 * changes should be mostly harmless as it simply turns the system
33 * into a router).
27 * 34 *
28 * TODO: 35 * @author Philipp Tölke
29 * - need to add code to setup ip_forwarding and NAT (for IPv4) so that 36 * @author Christian Grothoff
30 * users don't need to ALSO do admin work; this is what will set
31 * gnunet-helper-exit.c apart from gnunet-helper-vpn.c
32 * 37 *
33 * The following list of people have reviewed this code and considered 38 * The following list of people have reviewed this code and considered
34 * it safe since the last modification (if you reviewed it, please 39 * it safe since the last modification (if you reviewed it, please
@@ -54,6 +59,17 @@
54 */ 59 */
55#define MAX_SIZE 65536 60#define MAX_SIZE 65536
56 61
62/**
63 * Path to 'sysctl' binary.
64 */
65#define SBIN_SYSCTL "/sbin/sysctl"
66
67/**
68 * Path to 'iptables' binary.
69 */
70#define SBIN_IPTABLES "/sbin/iptables"
71
72
57#ifndef _LINUX_IN6_H 73#ifndef _LINUX_IN6_H
58/** 74/**
59 * This is in linux/include/net/ipv6.h, but not always exported... 75 * This is in linux/include/net/ipv6.h, but not always exported...
@@ -67,6 +83,58 @@ struct in6_ifreq
67#endif 83#endif
68 84
69 85
86
87/**
88 * Run the given command and wait for it to complete.
89 *
90 * @param file name of the binary to run
91 * @param cmd command line arguments (as given to 'execv')
92 * @return 0 on success, 1 on any error
93 */
94static int
95fork_and_exec (const char *file,
96 char *const cmd[])
97{
98 int status;
99 pid_t pid;
100 pid_t ret;
101
102 pid = fork ();
103 if (-1 == pid)
104 {
105 fprintf (stderr,
106 "fork failed: %s\n",
107 strerror (errno));
108 return 1;
109 }
110 if (0 == pid)
111 {
112 /* we are the child process */
113 (void) execv (file, cmd);
114 /* can only get here on error */
115 fprintf (stderr,
116 "exec `%s' failed: %s\n",
117 file,
118 strerror (errno));
119 _exit (1);
120 }
121 /* keep running waitpid as long as the only error we get is 'EINTR' */
122 while ( (-1 == (ret = waitpid (pid, &status, 0))) &&
123 (errno == EINTR) );
124 if (-1 == ret)
125 {
126 fprintf (stderr,
127 "waitpid failed: %s\n",
128 strerror (errno));
129 return 1;
130 }
131 if (! (WIFEXITED (status) && (0 == WEXITSTATUS (status))))
132 return 1;
133 /* child process completed and returned success, we're happy */
134 return 0;
135}
136
137
70/** 138/**
71 * Creates a tun-interface called dev; 139 * Creates a tun-interface called dev;
72 * 140 *
@@ -521,12 +589,13 @@ PROCESS_BUFFER:
521 * Open VPN tunnel interface. 589 * Open VPN tunnel interface.
522 * 590 *
523 * @param argc must be 6 591 * @param argc must be 6
524 * @param argv 0: binary name (gnunet-helper-vpn) 592 * @param argv 0: binary name ("gnunet-helper-vpn")
525 * 1: tunnel interface name (gnunet-vpn) 593 * 1: tunnel interface name ("gnunet-vpn")
526 * 2: IPv6 address (::1) 594 * 2: IPv4 "physical" interface name ("eth0"), or "%" to not do IPv4 NAT
527 * 3: IPv6 netmask length in bits (64) 595 * 3: IPv6 address ("::1"), or "-" to skip IPv6
528 * 4: IPv4 address (1.2.3.4) 596 * 4: IPv6 netmask length in bits ("64") [ignored if #4 is "-"]
529 * 5: IPv4 netmask (255.255.0.0) 597 * 5: IPv4 address ("1.2.3.4"), or "-" to skip IPv4
598 * 6: IPv4 netmask ("255.255.0.0") [ignored if #4 is "-"]
530 */ 599 */
531int 600int
532main (int argc, char **argv) 601main (int argc, char **argv)
@@ -535,11 +604,17 @@ main (int argc, char **argv)
535 int fd_tun; 604 int fd_tun;
536 int global_ret; 605 int global_ret;
537 606
538 if (6 != argc) 607 if (7 != argc)
539 { 608 {
540 fprintf (stderr, "Fatal: must supply 5 arguments!\n"); 609 fprintf (stderr, "Fatal: must supply 5 arguments!\n");
541 return 1; 610 return 1;
542 } 611 }
612 if ( (0 == strcmp (argv[3], "-")) &&
613 (0 == strcmp (argv[5], "-")) )
614 {
615 fprintf (stderr, "Fatal: disabling both IPv4 and IPv6 makes no sense.\n");
616 return 1;
617 }
543 618
544 strncpy (dev, argv[1], IFNAMSIZ); 619 strncpy (dev, argv[1], IFNAMSIZ);
545 dev[IFNAMSIZ - 1] = '\0'; 620 dev[IFNAMSIZ - 1] = '\0';
@@ -550,24 +625,66 @@ main (int argc, char **argv)
550 return 1; 625 return 1;
551 } 626 }
552 627
628 if (0 != strcmp (argv[3], "-"))
553 { 629 {
554 const char *address = argv[2];
555 long prefix_len = atol (argv[3]);
556
557 if ((prefix_len < 1) || (prefix_len > 127))
558 { 630 {
559 fprintf (stderr, "Fatal: prefix_len out of range\n"); 631 const char *address = argv[3];
560 return 1; 632 long prefix_len = atol (argv[4]);
633
634 if ((prefix_len < 1) || (prefix_len > 127))
635 {
636 fprintf (stderr, "Fatal: prefix_len out of range\n");
637 return 1;
638 }
639 set_address6 (dev, address, prefix_len);
640 }
641 {
642 char *const sysctl_args[] =
643 {
644 "sysctl", "-w", "net.ipv6.conf.all.forwarding=1", NULL
645 };
646 if (0 != fork_and_exec (SBIN_SYSCTL,
647 sysctl_args))
648 {
649 fprintf (stderr,
650 "Failed to enable IPv6 forwarding. Will continue anyway.\n");
651 }
561 } 652 }
562
563 set_address6 (dev, address, prefix_len);
564 } 653 }
565 654
655 if (0 != strcmp (argv[5], "-"))
566 { 656 {
567 const char *address = argv[4]; 657 {
568 const char *mask = argv[5]; 658 const char *address = argv[5];
569 659 const char *mask = argv[6];
570 set_address4 (dev, address, mask); 660
661 set_address4 (dev, address, mask);
662 }
663 {
664 char *const sysctl_args[] =
665 {
666 "sysctl", "-w", "net.ipv4.ip_forward=1", NULL
667 };
668 if (0 != fork_and_exec (SBIN_SYSCTL,
669 sysctl_args))
670 {
671 fprintf (stderr,
672 "Failed to enable IPv4 forwarding. Will continue anyway.\n");
673 }
674 }
675 if (0 != strcmp (argv[2], "%"))
676 {
677 char *const iptables_args[] =
678 {
679 "iptables", "-t", "nat", "-A", "POSTROUTING", "-o", argv[2], "-j", "MASQUERADE", NULL
680 };
681 if (0 != fork_and_exec (SBIN_IPTABLES,
682 iptables_args))
683 {
684 fprintf (stderr,
685 "Failed to enable IPv4 masquerading (NAT). Will continue anyway.\n");
686 }
687 }
571 } 688 }
572 689
573 uid_t uid = getuid (); 690 uid_t uid = getuid ();
@@ -599,3 +716,5 @@ main (int argc, char **argv)
599 close (fd_tun); 716 close (fd_tun);
600 return global_ret; 717 return global_ret;
601} 718}
719
720/* end of gnunet-helper-exit.c */