88#if ! HAVE_DECL_STRUCT_IN6_IFREQ
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))
201 const char *
const cmd[])
224 (void) execv (file, (
char *
const*)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;
541 if (0 == buftun_size)
542 FD_SET (fd_tun, &fds_r);
555 if (NULL == bufin_read)
562 if (NULL != bufin_read)
563 FD_SET (fd_tun, &fds_w);
565 FD_SET (
cpipe[0], &fds_r);
568 r = select (
max + 1, &fds_r, &fds_w, NULL, NULL);
574 fprintf (stderr,
"select failed: %s\n", strerror (errno));
580 if (FD_ISSET (
cpipe[0], &fds_r))
583 if (FD_ISSET (fd_tun, &fds_r))
588 if (-1 == buftun_size)
590 if ((errno == EINTR) ||
596 fprintf (stderr,
"read-error: %s\n", strerror (errno));
599 if (0 == buftun_size)
601 fprintf (stderr,
"EOF on tun\n");
604 buftun_read = buftun;
610 hdr->
size = htons (buftun_size);
613 else if (FD_ISSET (1, &fds_w))
615 ssize_t written = write (1, buftun_read, buftun_size);
619 if ((errno == EINTR) ||
622 fprintf (stderr,
"write-error to stdout: %s\n", strerror (errno));
627 fprintf (stderr,
"write returned 0\n");
630 buftun_size -= written;
631 buftun_read += written;
634 if (FD_ISSET (0, &fds_r))
636 bufin_size = read (0, bufin + bufin_rpos,
MAX_SIZE - bufin_rpos);
637 if (-1 == bufin_size)
640 if ((errno == EINTR) ||
643 fprintf (stderr,
"read-error: %s\n", strerror (errno));
649 fprintf (stderr,
"EOF on stdin\n");
656 bufin_rpos += bufin_size;
662 fprintf (stderr,
"protocol violation!\n");
665 if (ntohs (hdr->
size) > bufin_rpos)
672 else if (FD_ISSET (fd_tun, &fds_w))
674 ssize_t written = write (fd_tun, bufin_read, bufin_size);
678 if ((errno == EINTR) ||
681 fprintf (stderr,
"write-error to tun: %s\n", strerror (errno));
686 fprintf (stderr,
"write returned 0\n");
690 bufin_size -= written;
691 bufin_read += written;
694 memmove (bufin, bufin_read, bufin_rpos);
739main (
int argc,
char *
const*argv)
750 fprintf (stderr,
"Fatal: must supply 6 arguments!\n");
757 if (0 != setresuid (uid, 0, 0))
759 fprintf (stderr,
"Failed to setresuid to root: %s\n", strerror (errno));
763 if (0 != seteuid (0))
765 fprintf (stderr,
"Failed to seteuid back to root: %s\n", strerror (errno));
769 if (0 == strncmp (argv[6],
"1", 2))
776 if (0 == access (IPTABLES, X_OK))
780 if (0 == access (
"/sbin/iptables", X_OK))
782 else if (0 == access (
"/usr/sbin/iptables", X_OK))
787 "Fatal: executable iptables not found in approved directories: %s\n",
792 if (0 == access (IP6TABLES, X_OK))
796 if (0 == access (
"/sbin/ip6tables", X_OK))
798 else if (0 == access (
"/usr/sbin/ip6tables", X_OK))
803 "Fatal: executable ip6tables not found in approved directories: %s\n",
808 if (0 == access (PATH_TO_IP, X_OK))
812 if (0 == access (
"/sbin/ip", X_OK))
814 else if (0 == access (
"/usr/sbin/ip", X_OK))
816 else if (0 == access (
"/bin/ip", X_OK))
821 "Fatal: executable ip not found in approved directories: %s\n",
826 if (0 == access (SYSCTL, X_OK))
830 if (0 == access (
"/sbin/sysctl", X_OK))
832 else if (0 == access (
"/usr/sbin/sysctl", X_OK))
837 "Fatal: executable sysctl not found in approved directories: %s\n",
844 snprintf (mygid,
sizeof(mygid),
"%d", (
int) getegid ());
847 if (SIG_ERR == signal (SIGPIPE, SIG_IGN))
849 fprintf (stderr,
"Failed to protect against SIGPIPE: %s\n",
855 if (0 != pipe (
cpipe))
858 "Fatal: could not setup control pipe: %s\n",
862 if (
cpipe[0] >= FD_SETSIZE)
864 fprintf (stderr,
"Pipe file descriptor to large: %d",
cpipe[0]);
865 (void) close (
cpipe[0]);
866 (void) close (
cpipe[1]);
872 int flags = fcntl (
cpipe[1], F_GETFL);
875 fprintf (stderr,
"Failed to read flags for pipe: %s", strerror (errno));
876 (void) close (
cpipe[0]);
877 (void) close (
cpipe[1]);
881 if (0 != fcntl (
cpipe[1], F_SETFL, flags))
883 fprintf (stderr,
"Failed to make pipe non-blocking: %s", strerror (
885 (void) close (
cpipe[0]);
886 (void) close (
cpipe[1]);
898 "Fatal: could not initialize signal handler: %s\n",
900 (void) close (
cpipe[0]);
901 (void) close (
cpipe[1]);
907 strncpy (dev, argv[1], IFNAMSIZ);
908 dev[IFNAMSIZ - 1] =
'\0';
913 const char *
const sysctl_args[] = {
"sysctl",
"-w",
914 "net.ipv4.conf.all.rp_filter=0", NULL };
915 const char *
const sysctl_args2[] = {
"sysctl",
"-w",
916 "net.ipv4.conf.default.rp_filter=0", NULL };
921 "Failed to disable rp filtering.\n");
928 if (-1 == (fd_tun =
init_tun (dev)))
930 fprintf (stderr,
"Fatal: could not initialize tun-interface\n");
931 (void) signal (SIGTERM, SIG_IGN);
932#if (SIGTERM != GNUNET_TERM_SIG)
935 (void) signal (SIGINT, SIG_IGN);
936 (void) signal (SIGHUP, SIG_IGN);
937 (void) close (
cpipe[0]);
938 (void) close (
cpipe[1]);
945 long prefix_len = atol (argv[3]);
947 if ((prefix_len < 1) || (prefix_len > 127))
949 fprintf (stderr,
"Fatal: prefix_len out of range\n");
950 (void) signal (SIGTERM, SIG_IGN);
951#if (SIGTERM != GNUNET_TERM_SIG)
954 (void) signal (SIGINT, SIG_IGN);
955 (void) signal (SIGHUP, SIG_IGN);
956 (void) close (
cpipe[0]);
957 (void) close (
cpipe[1]);
965 const char *mask = argv[5];
979 const char *
const mangle_args[] = {
980 "iptables",
"-m",
"owner",
"-t",
"mangle",
"-I",
"OUTPUT",
"1",
"-p",
981 "udp",
"--gid-owner", mygid,
"--dport",
DNS_PORT,
"-j",
988 const char *
const mangle_args[] = {
989 "ip6tables",
"-m",
"owner",
"-t",
"mangle",
"-I",
"OUTPUT",
"1",
"-p",
990 "udp",
"--gid-owner", mygid,
"--dport",
DNS_PORT,
"-j",
994 goto cleanup_mangle_1b;
999 const char *
const mark_args[] = {
1000 "iptables",
"-t",
"mangle",
"-I",
"OUTPUT",
"2",
"-p",
1002 "-j",
"MARK",
"--set-mark",
DNS_MARK,
1006 goto cleanup_mangle_1;
1009 const char *
const mark_args[] = {
1010 "ip6tables",
"-t",
"mangle",
"-I",
"OUTPUT",
"2",
"-p",
1012 "!",
"-s",
"fe80::/10",
1013 "-j",
"MARK",
"--set-mark",
DNS_MARK,
1017 goto cleanup_mark_2b;
1021 const char *
const forward_args[] = {
1025 goto cleanup_mark_2;
1028 const char *
const forward_args[] = {
1032 goto cleanup_forward_3b;
1036 const char *
const route_args[] = {
1037 "ip",
"route",
"add",
"default",
"dev", dev,
1041 goto cleanup_forward_3;
1044 const char *
const route_args[] = {
1045 "ip",
"-6",
"route",
"add",
"default",
"dev", dev,
1049 goto cleanup_route_4b;
1055#ifdef HAVE_SETRESUID
1056 if (0 != setresuid (uid, uid, 0))
1058 fprintf (stderr,
"Failed to setresuid: %s\n", strerror (errno));
1060 goto cleanup_route_4;
1064 if (0 != seteuid (uid))
1066 fprintf (stderr,
"Failed to seteuid: %s\n", strerror (errno));
1068 goto cleanup_route_4;
1078#ifdef HAVE_SETRESUID
1079 if (0 != setresuid (uid, 0, 0))
1081 fprintf (stderr,
"Failed to setresuid back to root: %s\n", strerror (
1084 goto cleanup_route_4;
1087 if (0 != seteuid (0))
1089 fprintf (stderr,
"Failed to seteuid back to root: %s\n", strerror (errno));
1091 goto cleanup_route_4;
1100 const char *
const route_clean_args[] = {
1101 "ip",
"-6",
"route",
"del",
"default",
"dev", dev,
1110 const char *
const route_clean_args[] = {
1111 "ip",
"route",
"del",
"default",
"dev", dev,
1120 const char *
const forward_clean_args[] = {
1129 const char *
const forward_clean_args[] = {
1138 const char *
const mark_clean_args[] = {
1139 "ip6tables",
"-t",
"mangle",
"-D",
"OUTPUT",
"-p",
"udp",
1141 "!",
"-s",
"fe80::/10",
1142 "-j",
"MARK",
"--set-mark",
DNS_MARK, NULL
1150 const char *
const mark_clean_args[] = {
1151 "iptables",
"-t",
"mangle",
"-D",
"OUTPUT",
"-p",
"udp",
1160 const char *
const mangle_clean_args[] = {
1161 "ip6tables",
"-m",
"owner",
"-t",
"mangle",
"-D",
"OUTPUT",
"-p",
"udp",
1162 "--gid-owner", mygid,
"--dport",
DNS_PORT,
"-j",
"ACCEPT",
1171 const char *
const mangle_clean_args[] = {
1172 "iptables",
"-m",
"owner",
"-t",
"mangle",
"-D",
"OUTPUT",
"-p",
"udp",
1173 "--gid-owner", mygid,
"--dport",
DNS_PORT,
"-j",
"ACCEPT",
1182 (void) close (fd_tun);
1184 (void) signal (SIGTERM, SIG_IGN);
1185#if (SIGTERM != GNUNET_TERM_SIG)
1188 (void) signal (SIGINT, SIG_IGN);
1189 (void) signal (SIGHUP, SIG_IGN);
1190 (void) close (
cpipe[0]);
1191 (void) close (
cpipe[1]);
static int ret
Final status code.
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.
#define DNS_MARK
Marker we set for our hijacked DNS traffic.
static int fork_and_exec(const char *file, const char *const cmd[])
Run the given command and wait for it to complete.
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.
static int status
The program status; 0 for success.
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.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
#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