From 24e3e47f702d9a3eedb086f19fa7751ef4335885 Mon Sep 17 00:00:00 2001 From: Julian Kranz Date: Fri, 6 Jan 2012 16:22:17 +0100 Subject: [PATCH] Iodine: Added IPv6 command line options --- src/client.c | 2 -- src/common.c | 35 +++++++++++++++++++++++++---- src/common.h | 6 +++-- src/iodine.c | 6 ++--- src/iodined.c | 62 ++++++++++++++++++++++++++++++--------------------- src/user.c | 6 ++--- 6 files changed, 78 insertions(+), 39 deletions(-) diff --git a/src/client.c b/src/client.c index df09e05..f7f745c 100644 --- a/src/client.c +++ b/src/client.c @@ -1412,7 +1412,6 @@ send_codec_switch(int fd, int userid, int bits) send_query(fd, buf); } - static void send_downenc_switch(int fd, int userid) { @@ -2348,7 +2347,6 @@ fragsize_check(char *in, int read, int proposed_fragsize, int *max_fragsize) return 1; } - static int handshake_autoprobe_fragsize(int dns_fd) { diff --git a/src/common.c b/src/common.c index 71eebe3..3a027ed 100644 --- a/src/common.c +++ b/src/common.c @@ -353,8 +353,8 @@ int recent_seqno(int ourseqno, int gotseqno) return 0; } -void inet6_addr_add(struct in6_addr *addr, uint8_t amount) { - char i; +void ipv6_addr_add(struct in6_addr *addr, uint8_t amount) { + int i; for (i = 15; i >= 0; --i) { uint16_t next = addr->__in6_u.__u6_addr8[i]; next = next + amount; @@ -366,11 +366,38 @@ void inet6_addr_add(struct in6_addr *addr, uint8_t amount) { } } -char inet6_addr_equals(struct in6_addr *a, struct in6_addr *b) { - char i; +char ipv6_addr_equals(struct in6_addr *a, struct in6_addr *b) { + int i; for (i = 3; i >= 0; --i) if(a->__in6_u.__u6_addr32[i] != b->__in6_u.__u6_addr32[i]) return 0; return 1; } + +char ipv6_net_check(struct in6_addr *net, char netmask) { + uint32_t netmask_full[4]; + int i; + + for (i = 0; i < 4; ++i) + if(32*(i + 1) <= netmask) + netmask_full[i] = 0xffffffff; + else if(32*i >= netmask) + netmask_full[i] = 0x00000000; + else + netmask_full[i] = ~((1 << (netmask - 32*i)) - 1); + + for (i = 3; i >= 0; --i) + if((net->__in6_u.__u6_addr32[i] & netmask_full[i]) != net->__in6_u.__u6_addr32[i]) + return 0; + + return 1; +} + +void ipv6_print(struct in6_addr *ip, char netmask6) { + int i; + for (i = 0; i < 8; ++i) + fprintf(stderr, "%04x%s", ntohs(ip->__in6_u.__u6_addr16[i]), i < 7 ? ":" + : "/"); + printf("%d\n", netmask6); +} diff --git a/src/common.h b/src/common.h index 2bfaf7d..5cf45e7 100644 --- a/src/common.h +++ b/src/common.h @@ -133,7 +133,9 @@ void warnx(const char *fmt, ...); int recent_seqno(int , int); -void inet6_addr_add(struct in6_addr *addr, uint8_t amount); -char inet6_addr_equals(struct in6_addr *a, struct in6_addr *b); +void ipv6_addr_add(struct in6_addr *addr, uint8_t amount); +char ipv6_addr_equals(struct in6_addr *a, struct in6_addr *b); +char ipv6_net_check(struct in6_addr *net, char netmask); +void ipv6_print(struct in6_addr *ip, char netmask6); #endif diff --git a/src/iodine.c b/src/iodine.c index 3ea9f50..1f373f7 100644 --- a/src/iodine.c +++ b/src/iodine.c @@ -61,7 +61,7 @@ usage() { extern char *__progname; fprintf(stderr, "Usage: %s [-v] [-h] [-f] [-r] [-u user] [-t chrootdir] [-d device] " - "[-P password] [-m maxfragsize] [-M maxlen] [-T type] [-O enc] [-L 0|1] [-I sec] " + "[-P password] [-6] [-m maxfragsize] [-M maxlen] [-T type] [-O enc] [-L 0|1] [-I sec] " "[-z context] [-F pidfile] [nameserver] topdomain\n", __progname); exit(2); } @@ -72,7 +72,7 @@ help() { fprintf(stderr, "iodine IP over DNS tunneling client\n"); fprintf(stderr, "Usage: %s [-v] [-h] [-f] [-r] [-u user] [-t chrootdir] [-d device] " - "[-P password] [-m maxfragsize] [-M maxlen] [-T type] [-O enc] [-L 0|1] [-I sec] " + "[-P password] [-6] [-m maxfragsize] [-M maxlen] [-T type] [-O enc] [-L 0|1] [-I sec] " "[-z context] [-F pidfile] [nameserver] topdomain\n", __progname); fprintf(stderr, "Options to try if connection doesn't work:\n"); fprintf(stderr, " -T force dns type: NULL, TXT, SRV, MX, CNAME, A (default: autodetect)\n"); @@ -84,6 +84,7 @@ help() { fprintf(stderr, " -M max size of upstream hostnames (~100-255, default: 255)\n"); fprintf(stderr, " -r to skip raw UDP mode attempt\n"); fprintf(stderr, " -P password used for authentication (max 32 chars will be used)\n"); + fprintf(stderr, " -6 use IPv6 (make sure to use this option consistently on client and server)\n"); fprintf(stderr, "Other options:\n"); fprintf(stderr, " -v to print version info and exit\n"); fprintf(stderr, " -h to print this help and exit\n"); @@ -139,7 +140,6 @@ main(int argc, char **argv) int rtable = 0; printf("***MODIFIED***\n"); - fflush(stdout); nameserv_addr = NULL; topdomain = NULL; diff --git a/src/iodined.c b/src/iodined.c index 83f48cd..c44f258 100644 --- a/src/iodined.c +++ b/src/iodined.c @@ -810,7 +810,7 @@ handle_null_request(int tun_fd, int dns_fd, struct query *q, int domain_len) struct in6_addr ip6; memcpy(&ip6, &my_net6, sizeof(my_net6)); - inet6_addr_add(&ip6, 1); + ipv6_addr_add(&ip6, 1); char server6[41]; inet_ntop(AF_INET6, &ip6, server6, sizeof(server6)); @@ -2168,11 +2168,11 @@ static void usage() { extern char *__progname; - fprintf(stderr, "Usage: %s [-v] [-h] [-c] [-s] [-f] [-D] [-u user] " + fprintf(stderr, "Usage: %s [-v] [-h] [-c] [-s] [-f] [-D] [-6] [-u user] " "[-t chrootdir] [-d device] [-m mtu] [-z context] " "[-l ip address to listen on] [-p port] [-n external ip] " "[-b dnsport] [-P password] [-F pidfile] " - "tunnel_ip[/netmask] topdomain\n", __progname); + "tunnel_ip[/netmask] [tunnel_net6/netmask6] topdomain\n", __progname); exit(2); } @@ -2181,10 +2181,10 @@ help() { extern char *__progname; fprintf(stderr, "iodine IP over DNS tunneling server\n"); - fprintf(stderr, "Usage: %s [-v] [-h] [-c] [-s] [-f] [-D] [-u user] " + fprintf(stderr, "Usage: %s [-v] [-h] [-c] [-s] [-f] [-D] [-6] [-u user] " "[-t chrootdir] [-d device] [-m mtu] [-z context] " "[-l ip address to listen on] [-p port] [-n external ip] [-b dnsport] [-P password] " - "[-F pidfile] tunnel_ip[/netmask] topdomain\n", __progname); + "[-F pidfile] tunnel_ip[/netmask] [tunnel_net6/netmask6] topdomain\n", __progname); fprintf(stderr, " -v to print version info and exit\n"); fprintf(stderr, " -h to print this help and exit\n"); fprintf(stderr, " -c to disable check of client IP/port on each request\n"); @@ -2193,6 +2193,7 @@ help() { fprintf(stderr, " -f to keep running in foreground\n"); fprintf(stderr, " -D to increase debug level\n"); fprintf(stderr, " (using -DD in UTF-8 terminal: \"LC_ALL=C luit iodined -DD ...\")\n"); + fprintf(stderr, " -6 use IPv6 (make sure to use this option consistently on client and server)\n"); fprintf(stderr, " -u name to drop privileges and run as user 'name'\n"); fprintf(stderr, " -t dir to chroot to directory dir\n"); fprintf(stderr, " -d device to set tunnel device name\n"); @@ -2207,6 +2208,8 @@ help() { fprintf(stderr, " -F pidfile to write pid to a file\n"); fprintf(stderr, "tunnel_ip is the IP number of the local tunnel interface.\n"); fprintf(stderr, " /netmask sets the size of the tunnel network.\n"); + fprintf(stderr, "tunnel_net6 is the IPv6 network for the tunnel (2001:4242:: for example).\n"); + fprintf(stderr, " /netmask6 sets the size of the tunnel IPv6 network.\n"); fprintf(stderr, "topdomain is the FQDN that is delegated to this server.\n"); exit(0); } @@ -2249,10 +2252,7 @@ main(int argc, char **argv) char *netsize; int retval; - /** - * Todo: fix - */ - char v6 = 1; + char v6; #ifndef WINDOWS32 pw = NULL; @@ -2274,6 +2274,7 @@ main(int argc, char **argv) debug = 0; netmask = 27; pidfile = NULL; + v6 = 0; b32 = get_base32_encoder(); b64 = get_base64_encoder(); @@ -2298,7 +2299,7 @@ main(int argc, char **argv) srand(time(NULL)); fw_query_init(); - while ((choice = getopt(argc, argv, "vcsfhDu:t:d:m:l:p:n:b:P:z:F:")) != -1) { + while ((choice = getopt(argc, argv, "vcsfhD6u:t:d:m:l:p:n:b:P:z:F:")) != -1) { switch(choice) { case 'v': version(); @@ -2356,6 +2357,9 @@ main(int argc, char **argv) case 'z': context = optarg; break; + case '6': + v6 = 1; + break; default: usage(); break; @@ -2365,7 +2369,10 @@ main(int argc, char **argv) argc -= optind; argv += optind; - check_superuser(usage); + /* + * Todo: Uncomment + */ +// check_superuser(usage); if (argc != 2) usage(); @@ -2379,27 +2386,32 @@ main(int argc, char **argv) my_ip = inet_addr(argv[0]); - /** - * Todo: Fix ;-) - */ + if (my_ip == INADDR_NONE) { + warnx("Bad IP address to use inside tunnel."); + usage(); + } + if (v6) { - if (inet_pton(AF_INET6, "2001:4242:4242:4242:4242:4242:4242:0000", &my_net6) + netsize = strchr(argv[1], '/'); + if (netsize) { + *netsize = 0; + netsize++; + netmask6 = atoi(netsize); + } + + if (inet_pton(AF_INET6, argv[1], &my_net6) != 1) { warnx("Bad IPv6 address to use inside tunnel."); usage(); } - netmask6 = 112; - printf("IPv6 net: "); - char i; - for (i = 0; i < 8; ++i) - printf("%04x%s", ntohs(my_net6.__in6_u.__u6_addr16[i]), i < 7 ? ":" - : "\n"); - - if (my_ip == INADDR_NONE) { - warnx("Bad IP address to use inside tunnel."); + if (!ipv6_net_check(&my_net6, netmask6)) { + warnx("Bad IPv6 network and netmask6 combination."); usage(); } + + fprintf(stderr, "IPv6 network: "); + ipv6_print(&my_net6, netmask6); } topdomain = strdup(argv[1]); @@ -2497,7 +2509,7 @@ main(int argc, char **argv) if (v6) { struct in6_addr my_ip6; memcpy(&my_ip6, &my_net6, sizeof(my_net6)); - inet6_addr_add(&my_ip6, 1); + ipv6_addr_add(&my_ip6, 1); char buf[41]; inet_ntop(AF_INET6, &my_ip6, buf, sizeof(buf)); diff --git a/src/user.c b/src/user.c index af6e675..ee54914 100644 --- a/src/user.c +++ b/src/user.c @@ -51,7 +51,7 @@ init_users(in_addr_t my_ip, int netbits, struct in6_addr my_net6) struct in6_addr next_v6; memcpy(&next_v6, &my_net6, sizeof(my_net6)); - inet6_addr_add(&next_v6, 1); + ipv6_addr_add(&next_v6, 1); for (i = 0; i < netbits; i++) { netmask = (netmask << 1) | 1; @@ -80,7 +80,7 @@ init_users(in_addr_t my_ip, int netbits, struct in6_addr my_net6) users[i].disabled = 0; users[i].active = 0; - inet6_addr_add(&next_v6, 1); + ipv6_addr_add(&next_v6, 1); memcpy(&(users[i].tun_ip6), &next_v6, sizeof(struct in6_addr)); /* Rest is reset on login ('V' packet) */ @@ -143,7 +143,7 @@ find_user_by_ip6(struct in6_addr ip) for (i = 0; i < usercount; i++) { if (users[i].active && !users[i].disabled && users[i].last_pkt + 60 > time(NULL) && - inet6_addr_equals(&ip, &(users[i].tun_ip6))) { + ipv6_addr_equals(&ip, &(users[i].tun_ip6))) { ret = i; break; }