diff --git a/src/client.c b/src/client.c index 5f3eb78..a756c75 100644 --- a/src/client.c +++ b/src/client.c @@ -1374,7 +1374,7 @@ handshake_version(int dns_fd, int *seed) } static int -handshake_login(int dns_fd, int seed) +handshake_login(int dns_fd, int seed, int forward_v6) { char in[4096]; char login[16]; @@ -1405,7 +1405,7 @@ handshake_login(int dns_fd, int seed) server[64] = 0; client[64] = 0; - if (tun_setip(client, server, netmask) == 0 && + if (tun_setip(client, server, netmask, forward_v6) == 0 && tun_setmtu(mtu) == 0) { fprintf(stderr, "Server tunnel IP is %s\n", server); @@ -2326,7 +2326,7 @@ handshake_set_fragsize(int dns_fd, int fragsize) } int -client_handshake(int dns_fd, int raw_mode, int autodetect_frag_size, int fragsize) +client_handshake(int dns_fd, int raw_mode, int autodetect_frag_size, int fragsize, int forward_v6) { int seed; int upcodec; @@ -2349,7 +2349,7 @@ client_handshake(int dns_fd, int raw_mode, int autodetect_frag_size, int fragsiz return r; } - r = handshake_login(dns_fd, seed); + r = handshake_login(dns_fd, seed, forward_v6); if (r) { return r; } diff --git a/src/client.h b/src/client.h index 3dab6fb..ac61a83 100644 --- a/src/client.h +++ b/src/client.h @@ -35,7 +35,7 @@ void client_set_lazymode(int lazy_mode); void client_set_hostname_maxlen(int i); int client_handshake(int dns_fd, int raw_mode, int autodetect_frag_size, - int fragsize); + int fragsize, int forward_v6); int client_tunnel(int tun_fd, int dns_fd); #endif diff --git a/src/iodine.c b/src/iodine.c index fbb6481..3f81495 100644 --- a/src/iodine.c +++ b/src/iodine.c @@ -72,7 +72,7 @@ static void help(FILE *stream, bool verbose) { fprintf(stream, "iodine IP over DNS tunneling client\n\n" - "Usage: %s [-46fhrv] [-u user] [-t chrootdir] [-d device] [-P password]\n" + "Usage: %s [-46fhrvS] [-u user] [-t chrootdir] [-d device] [-P password]\n" " [-m maxfragsize] [-M maxlen] [-T type] [-O enc] [-L 0|1] [-I sec]\n" " [-z context] [-F pidfile] [nameserver] topdomain\n", __progname); @@ -100,6 +100,7 @@ static void help(FILE *stream, bool verbose) " -t dir to chroot to directory dir\n" " -d device to set tunnel device name\n" " -z context, to apply specified SELinux context after initialization\n" + " -S enable forwarding of IPv6 packets within the tunnel\n" " -F pidfile to write pid to a file\n\n" "nameserver is the IP number/hostname of the relaying nameserver. If absent,\n" " /etc/resolv.conf is used\n" @@ -152,6 +153,7 @@ int main(int argc, char **argv) struct sockaddr_storage nameservaddr; int nameservaddr_len; int nameserv_family; + int forward_v6; nameserv_host = NULL; topdomain = NULL; @@ -176,6 +178,7 @@ int main(int argc, char **argv) selecttimeout = 4; hostname_maxlen = 0xFF; nameserv_family = AF_UNSPEC; + forward_v6 = 0; #ifdef WINDOWS32 WSAStartup(req_version, &wsa_data); @@ -192,7 +195,7 @@ int main(int argc, char **argv) __progname++; #endif - while ((choice = getopt(argc, argv, "46vfhru:t:d:R:P:m:M:F:T:O:L:I:")) != -1) { + while ((choice = getopt(argc, argv, "46vfhru:t:d:R:P:m:M:F:T:O:L:I:s")) != -1) { switch(choice) { case '4': nameserv_family = AF_INET; @@ -268,6 +271,9 @@ int main(int argc, char **argv) if (!lazymode) selecttimeout = 1; break; + case 'S': + forward_v6 = 1; + break; case 'I': selecttimeout = atoi(optarg); if (selecttimeout < 1) diff --git a/src/iodined.c b/src/iodined.c index f955516..ff405a5 100644 --- a/src/iodined.c +++ b/src/iodined.c @@ -2274,7 +2274,7 @@ write_dns(int fd, struct query *q, const char *data, int datalen, char downenc) static void print_usage(FILE *stream) { fprintf(stream, - "Usage: %s [-46cDfsv] [-u user] [-t chrootdir] [-d device] [-m mtu]\n" + "Usage: %s [-46cDfsvS] [-u user] [-t chrootdir] [-d device] [-m mtu]\n" " [-z context] [-l ipv4 listen address] [-L ipv6 listen address]\n" " [-p port] [-n auto|external_ip] [-b dnsport] [-P password]\n" " [-F pidfile] [-i max idle time] tunnel_ip[/netmask] topdomain\n", @@ -2390,6 +2390,7 @@ main(int argc, char **argv) int dns4addr_len; struct sockaddr_storage dns6addr; int dns6addr_len; + int forward_v6; #ifdef HAVE_SYSTEMD int nb_fds; #endif @@ -2418,7 +2419,7 @@ main(int argc, char **argv) debug = 0; netmask = 27; pidfile = NULL; - + forward_v6 = 0; retval = 0; #ifdef WINDOWS32 @@ -2507,6 +2508,9 @@ main(int argc, char **argv) /* XXX: find better way of cleaning up ps(1) */ memset(optarg, 0, strlen(optarg)); break; + case 'S': + forward_v6 = 1; + break; case 'z': context = optarg; break; @@ -2674,7 +2678,7 @@ main(int argc, char **argv) } if (!skipipconfig) { const char *other_ip = users_get_first_ip(); - if (tun_setip(argv[0], other_ip, netmask) != 0 || tun_setmtu(mtu) != 0) { + if (tun_setip(argv[0], other_ip, netmask, forward_v6) != 0 || tun_setmtu(mtu) != 0) { retval = 1; free((void*) other_ip); goto cleanup; diff --git a/src/tun.c b/src/tun.c index 4c78895..804fad7 100644 --- a/src/tun.c +++ b/src/tun.c @@ -592,7 +592,7 @@ read_tun(int tun_fd, char *buf, size_t len) #endif int -tun_setip(const char *ip, const char *other_ip, int netbits) +tun_setip(const char *ip, const char *other_ip, int netbits, int forward_v6) { char cmdline[512]; int netmask; @@ -687,6 +687,15 @@ tun_setip(const char *ip, const char *other_ip, int netbits) if_name, ip, inet_ntoa(net)); return system(cmdline); #endif + + if (forward_v6) { + snprintf(cmdline, sizeof(cmdline), + IFCONFIGPATH "ifconfig %s inet6 add ::%s/64", + if_name, + ip); + + fprintf(stderr, "Setting IP of %s to %s\n", if_name, ip); + } } int diff --git a/src/tun.h b/src/tun.h index 8982a9f..a57c007 100644 --- a/src/tun.h +++ b/src/tun.h @@ -22,7 +22,7 @@ int open_tun(const char *); void close_tun(int); int write_tun(int, char *, size_t); ssize_t read_tun(int, char *, size_t); -int tun_setip(const char *, const char *, int); +int tun_setip(const char *, const char *, int, int); int tun_setmtu(const unsigned); #endif /* _TUN_H_ */