86 #define MAX_SIZE 65536
88 #if ! HAVE_DECL_STRUCT_IN6_IFREQ
123 #define DNS_PORT "53"
131 #define DNS_MARK "136708149"
140 #define DNS_TABLE "53"
161 (void) write (
cpipe[1],
"K", 1);
178 fd = open (
"/dev/null", flags);
183 if (-1 == dup2 (fd, target_fd))
224 (void) execv (file, cmd);
227 "exec `%s' failed: %s\n",
239 "waitpid failed: %s\n",
243 if (! (WIFEXITED (
status) && (0 == WEXITSTATUS (
status))))
269 if (-1 == (fd = open (
"/dev/net/tun", O_RDWR)))
271 fprintf (stderr,
"Error opening `%s': %s\n",
"/dev/net/tun",
276 if (fd >= FD_SETSIZE)
278 fprintf (stderr,
"File descriptor to large: %d", fd);
283 memset (&ifr, 0,
sizeof(ifr));
284 ifr.ifr_flags = IFF_TUN;
287 strncpy (ifr.ifr_name, dev, IFNAMSIZ);
289 if (-1 == ioctl (fd, TUNSETIFF, (
void *) &ifr))
291 fprintf (stderr,
"Error with ioctl on `%s': %s\n",
"/dev/net/tun",
296 strcpy (dev, ifr.ifr_name);
313 struct sockaddr_in6 sa6;
319 memset (&sa6, 0,
sizeof(
struct sockaddr_in6));
320 sa6.sin6_family = AF_INET6;
321 if (1 != inet_pton (AF_INET6,
address, sa6.sin6_addr.s6_addr))
324 "Failed to parse IPv6 address `%s': %s\n",
330 if (-1 == (fd = socket (PF_INET6, SOCK_DGRAM, 0)))
333 "Error creating IPv6 socket: %s (ignored)\n",
339 memset (&ifr, 0,
sizeof(
struct ifreq));
343 strncpy (ifr.ifr_name, dev, IFNAMSIZ);
344 if (-1 == ioctl (fd, SIOGIFINDEX, &ifr))
346 fprintf (stderr,
"ioctl failed at %d: %s\n", __LINE__, strerror (errno));
351 memset (&ifr6, 0,
sizeof(
struct in6_ifreq));
359 if (-1 == ioctl (fd, SIOCSIFADDR, &ifr6))
361 fprintf (stderr,
"ioctl failed at line %d: %s\n", __LINE__,
370 if (-1 == ioctl (fd, SIOCGIFFLAGS, &ifr))
372 fprintf (stderr,
"ioctl failed at line %d: %s\n", __LINE__,
381 ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
382 if (-1 == ioctl (fd, SIOCSIFFLAGS, &ifr))
384 fprintf (stderr,
"ioctl failed at line %d: %s\n", __LINE__,
392 fprintf (stderr,
"close failed: %s\n", strerror (errno));
409 struct sockaddr_in *addr;
412 memset (&ifr, 0,
sizeof(
struct ifreq));
413 addr = (
struct sockaddr_in *) &(ifr.ifr_addr);
414 addr->sin_family = AF_INET;
419 if (1 != inet_pton (AF_INET,
address, &addr->sin_addr.s_addr))
422 "Failed to parse IPv4 address `%s': %s\n",
428 if (-1 == (fd = socket (PF_INET, SOCK_DGRAM, 0)))
431 "Error creating IPv4 socket: %s\n",
436 strncpy (ifr.ifr_name, dev, IFNAMSIZ);
441 if (-1 == ioctl (fd, SIOCSIFADDR, &ifr))
443 fprintf (stderr,
"ioctl failed at %d: %s\n", __LINE__, strerror (errno));
451 addr = (
struct sockaddr_in *) &(ifr.ifr_netmask);
452 if (1 != inet_pton (AF_INET, mask, &addr->sin_addr.s_addr))
454 fprintf (stderr,
"Failed to parse address `%s': %s\n", mask,
463 if (-1 == ioctl (fd, SIOCSIFNETMASK, &ifr))
465 fprintf (stderr,
"ioctl failed at line %d: %s\n", __LINE__,
474 if (-1 == ioctl (fd, SIOCGIFFLAGS, &ifr))
476 fprintf (stderr,
"ioctl failed at line %d: %s\n", __LINE__,
485 ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
486 if (-1 == ioctl (fd, SIOCSIFFLAGS, &ifr))
488 fprintf (stderr,
"ioctl failed at line %d: %s\n", __LINE__,
496 fprintf (stderr,
"close failed: %s\n", strerror (errno));
517 ssize_t buftun_size = 0;
518 unsigned char *buftun_read = NULL;
524 ssize_t bufin_size = 0;
525 size_t bufin_rpos = 0;
526 unsigned char *bufin_read = NULL;
540 if (0 == buftun_size)
541 FD_SET (fd_tun, &fds_r);
554 if (NULL == bufin_read)
561 if (NULL != bufin_read)
562 FD_SET (fd_tun, &fds_w);
564 FD_SET (
cpipe[0], &fds_r);
567 int r = select (
max + 1, &fds_r, &fds_w, NULL, NULL);
573 fprintf (stderr,
"select failed: %s\n", strerror (errno));
579 if (FD_ISSET (
cpipe[0], &fds_r))
582 if (FD_ISSET (fd_tun, &fds_r))
587 if (-1 == buftun_size)
589 if ((errno == EINTR) ||
595 fprintf (stderr,
"read-error: %s\n", strerror (errno));
598 if (0 == buftun_size)
600 fprintf (stderr,
"EOF on tun\n");
603 buftun_read = buftun;
609 hdr->
size = htons (buftun_size);
612 else if (FD_ISSET (1, &fds_w))
614 ssize_t written = write (1, buftun_read, buftun_size);
618 if ((errno == EINTR) ||
621 fprintf (stderr,
"write-error to stdout: %s\n", strerror (errno));
626 fprintf (stderr,
"write returned 0\n");
629 buftun_size -= written;
630 buftun_read += written;
633 if (FD_ISSET (0, &fds_r))
635 bufin_size = read (0, bufin + bufin_rpos,
MAX_SIZE - bufin_rpos);
636 if (-1 == bufin_size)
639 if ((errno == EINTR) ||
642 fprintf (stderr,
"read-error: %s\n", strerror (errno));
648 fprintf (stderr,
"EOF on stdin\n");
655 bufin_rpos += bufin_size;
661 fprintf (stderr,
"protocol violation!\n");
664 if (ntohs (hdr->
size) > bufin_rpos)
671 else if (FD_ISSET (fd_tun, &fds_w))
673 ssize_t written = write (fd_tun, bufin_read, bufin_size);
677 if ((errno == EINTR) ||
680 fprintf (stderr,
"write-error to tun: %s\n", strerror (errno));
685 fprintf (stderr,
"write returned 0\n");
689 bufin_size -= written;
690 bufin_read += written;
693 memmove (bufin, bufin_read, bufin_rpos);
738 main (
int argc,
char *
const*argv)
749 fprintf (stderr,
"Fatal: must supply 6 arguments!\n");
755 #ifdef HAVE_SETRESUID
756 if (0 != setresuid (uid, 0, 0))
758 fprintf (stderr,
"Failed to setresuid to root: %s\n", strerror (errno));
762 if (0 != seteuid (0))
764 fprintf (stderr,
"Failed to seteuid back to root: %s\n", strerror (errno));
768 if (0 == strncmp (argv[6],
"1", 2))
775 if (0 == access (IPTABLES, X_OK))
779 if (0 == access (
"/sbin/iptables", X_OK))
781 else if (0 == access (
"/usr/sbin/iptables", X_OK))
786 "Fatal: executable iptables not found in approved directories: %s\n",
791 if (0 == access (IP6TABLES, X_OK))
795 if (0 == access (
"/sbin/ip6tables", X_OK))
797 else if (0 == access (
"/usr/sbin/ip6tables", X_OK))
802 "Fatal: executable ip6tables not found in approved directories: %s\n",
807 if (0 == access (PATH_TO_IP, X_OK))
811 if (0 == access (
"/sbin/ip", X_OK))
813 else if (0 == access (
"/usr/sbin/ip", X_OK))
815 else if (0 == access (
"/bin/ip", X_OK))
820 "Fatal: executable ip not found in approved directories: %s\n",
825 if (0 == access (SYSCTL, X_OK))
829 if (0 == access (
"/sbin/sysctl", X_OK))
831 else if (0 == access (
"/usr/sbin/sysctl", X_OK))
836 "Fatal: executable sysctl not found in approved directories: %s\n",
843 snprintf (mygid,
sizeof(mygid),
"%d", (
int) getegid ());
846 if (SIG_ERR == signal (SIGPIPE, SIG_IGN))
848 fprintf (stderr,
"Failed to protect against SIGPIPE: %s\n",
854 if (0 != pipe (
cpipe))
857 "Fatal: could not setup control pipe: %s\n",
861 if (
cpipe[0] >= FD_SETSIZE)
863 fprintf (stderr,
"Pipe file descriptor to large: %d",
cpipe[0]);
864 (void) close (
cpipe[0]);
865 (void) close (
cpipe[1]);
871 int flags = fcntl (
cpipe[1], F_GETFL);
874 fprintf (stderr,
"Failed to read flags for pipe: %s", strerror (errno));
875 (void) close (
cpipe[0]);
876 (void) close (
cpipe[1]);
880 if (0 != fcntl (
cpipe[1], F_SETFL, flags))
882 fprintf (stderr,
"Failed to make pipe non-blocking: %s", strerror (
884 (void) close (
cpipe[0]);
885 (void) close (
cpipe[1]);
897 "Fatal: could not initialize signal handler: %s\n",
899 (void) close (
cpipe[0]);
900 (void) close (
cpipe[1]);
906 strncpy (dev, argv[1], IFNAMSIZ);
907 dev[IFNAMSIZ - 1] =
'\0';
912 char *
const sysctl_args[] = {
"sysctl",
"-w",
913 "net.ipv4.conf.all.rp_filter=0", NULL };
914 char *
const sysctl_args2[] = {
"sysctl",
"-w",
915 "net.ipv4.conf.default.rp_filter=0", NULL };
920 "Failed to disable rp filtering.\n");
927 if (-1 == (fd_tun =
init_tun (dev)))
929 fprintf (stderr,
"Fatal: could not initialize tun-interface\n");
930 (void) signal (SIGTERM, SIG_IGN);
931 #if (SIGTERM != GNUNET_TERM_SIG)
934 (void) signal (SIGINT, SIG_IGN);
935 (void) signal (SIGHUP, SIG_IGN);
936 (void) close (
cpipe[0]);
937 (void) close (
cpipe[1]);
944 long prefix_len = atol (argv[3]);
946 if ((prefix_len < 1) || (prefix_len > 127))
948 fprintf (stderr,
"Fatal: prefix_len out of range\n");
949 (void) signal (SIGTERM, SIG_IGN);
950 #if (SIGTERM != GNUNET_TERM_SIG)
953 (void) signal (SIGINT, SIG_IGN);
954 (void) signal (SIGHUP, SIG_IGN);
955 (void) close (
cpipe[0]);
956 (void) close (
cpipe[1]);
964 const char *mask = argv[5];
978 char *
const mangle_args[] = {
979 "iptables",
"-m",
"owner",
"-t",
"mangle",
"-I",
"OUTPUT",
"1",
"-p",
980 "udp",
"--gid-owner", mygid,
"--dport",
DNS_PORT,
"-j",
987 char *
const mangle_args[] = {
988 "ip6tables",
"-m",
"owner",
"-t",
"mangle",
"-I",
"OUTPUT",
"1",
"-p",
989 "udp",
"--gid-owner", mygid,
"--dport",
DNS_PORT,
"-j",
993 goto cleanup_mangle_1b;
998 char *
const mark_args[] = {
999 "iptables",
"-t",
"mangle",
"-I",
"OUTPUT",
"2",
"-p",
1001 "-j",
"MARK",
"--set-mark",
DNS_MARK,
1005 goto cleanup_mangle_1;
1008 char *
const mark_args[] = {
1009 "ip6tables",
"-t",
"mangle",
"-I",
"OUTPUT",
"2",
"-p",
1011 "!",
"-s",
"fe80::/10",
1012 "-j",
"MARK",
"--set-mark",
DNS_MARK,
1016 goto cleanup_mark_2b;
1020 char *
const forward_args[] = {
1024 goto cleanup_mark_2;
1027 char *
const forward_args[] = {
1031 goto cleanup_forward_3b;
1035 char *
const route_args[] = {
1036 "ip",
"route",
"add",
"default",
"dev", dev,
1040 goto cleanup_forward_3;
1043 char *
const route_args[] = {
1044 "ip",
"-6",
"route",
"add",
"default",
"dev", dev,
1048 goto cleanup_route_4b;
1054 #ifdef HAVE_SETRESUID
1055 if (0 != setresuid (uid, uid, 0))
1057 fprintf (stderr,
"Failed to setresuid: %s\n", strerror (errno));
1059 goto cleanup_route_4;
1063 if (0 != seteuid (uid))
1065 fprintf (stderr,
"Failed to seteuid: %s\n", strerror (errno));
1067 goto cleanup_route_4;
1077 #ifdef HAVE_SETRESUID
1078 if (0 != setresuid (uid, 0, 0))
1080 fprintf (stderr,
"Failed to setresuid back to root: %s\n", strerror (
1083 goto cleanup_route_4;
1086 if (0 != seteuid (0))
1088 fprintf (stderr,
"Failed to seteuid back to root: %s\n", strerror (errno));
1090 goto cleanup_route_4;
1099 char *
const route_clean_args[] = {
1100 "ip",
"-6",
"route",
"del",
"default",
"dev", dev,
1109 char *
const route_clean_args[] = {
1110 "ip",
"route",
"del",
"default",
"dev", dev,
1119 char *
const forward_clean_args[] = {
1128 char *
const forward_clean_args[] = {
1137 char *
const mark_clean_args[] = {
1138 "ip6tables",
"-t",
"mangle",
"-D",
"OUTPUT",
"-p",
"udp",
1140 "!",
"-s",
"fe80::/10",
1141 "-j",
"MARK",
"--set-mark",
DNS_MARK, NULL
1149 char *
const mark_clean_args[] = {
1150 "iptables",
"-t",
"mangle",
"-D",
"OUTPUT",
"-p",
"udp",
1159 char *
const mangle_clean_args[] = {
1160 "ip6tables",
"-m",
"owner",
"-t",
"mangle",
"-D",
"OUTPUT",
"-p",
"udp",
1161 "--gid-owner", mygid,
"--dport",
DNS_PORT,
"-j",
"ACCEPT",
1170 char *
const mangle_clean_args[] = {
1171 "iptables",
"-m",
"owner",
"-t",
"mangle",
"-D",
"OUTPUT",
"-p",
"udp",
1172 "--gid-owner", mygid,
"--dport",
DNS_PORT,
"-j",
"ACCEPT",
1181 (void) close (fd_tun);
1183 (void) signal (SIGTERM, SIG_IGN);
1184 #if (SIGTERM != GNUNET_TERM_SIG)
1187 (void) signal (SIGINT, SIG_IGN);
1188 (void) signal (SIGHUP, SIG_IGN);
1189 (void) close (
cpipe[0]);
1190 (void) close (
cpipe[1]);
static int ret
Return value of the commandline.
static char * address
GNS address for this phone.
#define DNS_TABLE
Table we use for our DNS rules.
#define MAX_SIZE
Need 'struct GNUNET_MessageHeader'.
static const char * sbin_sysctl
Name and full path of sysctl binary.
static const char * sbin_ip
Name and full path of IPTABLES binary.
static void run(int fd_tun)
Start forwarding to and from the tunnel.
static int fork_and_exec(const char *file, char *const cmd[])
Run the given command and wait for it to complete.
#define DNS_MARK
Marker we set for our hijacked DNS traffic.
static const char * sbin_iptables
Name and full path of IPTABLES binary.
static void signal_handler(int signal)
Signal handler called to initiate "nice" shutdown.
static int init_tun(char *dev)
Creates a tun-interface called dev;.
static void open_dev_null(int target_fd, int flags)
Open '/dev/null' and make the result the given file descriptor.
static void set_address4(const char *dev, const char *address, const char *mask)
Sets the IPv4-Address given in address on the interface dev.
static int cpipe[2]
Control pipe for shutdown via signal.
static const char * sbin_ip6tables
Name and full path of IPTABLES binary.
#define DNS_PORT
Port for DNS traffic.
int main(int argc, char *const *argv)
Main function of "gnunet-helper-dns", which opens a VPN tunnel interface, redirects all outgoing DNS ...
static void set_address6(const char *dev, const char *address, unsigned long prefix_len)
Sets the IPv6-Address given in address on the interface dev.
uint16_t status
See PRISM_STATUS_*-constants.
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
commonly used definitions; globals in this file are exempt from the rule that the module name ("commo...
Constants for network protocols.
#define GNUNET_MESSAGE_TYPE_DNS_HELPER
Type of messages between the gnunet-helper-dns and the service.
This is in linux/include/net/ipv6.h, but not always exported...
struct in6_addr ifr6_addr
unsigned int ifr6_ifindex