From ab2bbd987faae55c8a1e50f18e8f1c6a7e860b47 Mon Sep 17 00:00:00 2001 From: Chris Hellberg Date: Thu, 30 Dec 2021 05:09:16 +0000 Subject: [PATCH] further IPv6 commits --- src/iodined.c | 23 ++++++++++++++++++--- src/tun.c | 36 +++++++++++++++++++++++++-------- src/user.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/user.h | 3 +++ 4 files changed, 106 insertions(+), 11 deletions(-) diff --git a/src/iodined.c b/src/iodined.c index 0a02632..b1378ac 100644 --- a/src/iodined.c +++ b/src/iodined.c @@ -649,13 +649,30 @@ static int tunnel_tun(int tun_fd, struct dnsfd *dns_fds) char in[64*1024]; int userid; int read; - + int ip_version; + int c; + struct in6_addr v6Addr; + char v6AddrP[16]; if ((read = read_tun(tun_fd, in, sizeof(in))) <= 0) return 0; /* find target ip in packet, in is padded with 4 bytes TUN header */ header = (struct ip*) (in + 4); - userid = find_user_by_ip(header->ip_dst.s_addr); + ip_version = in[4] & 0xf0; + + if (ip_version == 64) { /* IPv4 */ + header = (struct ip*) (in + 4); + userid = find_user_by_ip(header->ip_dst.s_addr); + } else { /* IPv6 */ + for (c = 0; c < 16; c++) { + v6Addr.s6_addr[c] = in[c + 28]; + printf("adding byte: %i to v6 address\n", in[c+28]); + } + inet_ntop(AF_INET6, &v6Addr, v6AddrP, INET6_ADDRSTRLEN); + printf("read v6Addr from tunnel: %s\n", v6AddrP); + userid = find_user_by_ip6(&v6Addr); + printf("userid: %d\n", userid); + } if (userid < 0) return 0; @@ -2437,7 +2454,7 @@ main(int argc, char **argv) srand(time(NULL)); fw_query_init(); - while ((choice = getopt(argc, argv, "46vcsfhDuS:t:d:m:l:L:p:n:b:P:z:F:i:")) != -1) { + while ((choice = getopt(argc, argv, "46vcsSfhDu:t:d:m:l:L:p:n:b:P:z:F:i:")) != -1) { switch(choice) { case '4': addrfamily = AF_INET; diff --git a/src/tun.c b/src/tun.c index 7c20404..9d2c16d 100644 --- a/src/tun.c +++ b/src/tun.c @@ -549,19 +549,39 @@ write_tun(int tun_fd, char *data, size_t len) len -= 4; } else { #ifdef LINUX + + int i = data[4] & 0xf0; + if (i == 64) { + fprintf(stderr, "IPv4 packet\n"); + // Look at the fifth bype // Linux prefixes with 32 bits ethertype // 0x0800 for IPv4, 0x86DD for IPv6 - data[0] = 0x00; - data[1] = 0x00; - data[2] = 0x08; - data[3] = 0x00; + data[0] = 0x00; + data[1] = 0x00; + data[2] = 0x08; + data[3] = 0x00; + } else { /* 96 for IPV6 */ + fprintf(stderr, "IPv6 packet\n"); + data[0] = 0x00; + data[1] = 0x00; + data[2] = 0x86; + data[3] = 0xDD; + } #else /* OPENBSD and DARWIN(utun) */ // BSDs prefix with 32 bits address family // AF_INET for IPv4, AF_INET6 for IPv6 - data[0] = 0x00; - data[1] = 0x00; - data[2] = 0x00; - data[3] = 0x02; + if (i == 64) { + fprintf(stderr, "IPv4 packet\n"); + data[0] = 0x00; + data[1] = 0x00; + data[2] = 0x00; + data[3] = 0x02; + } else { /* 96 for IPV6 */ + fprintf(stderr, "IPv6 packet\n"); + data[0] = 0x00; + data[1] = 0x00; + data[2] = 0x00; + data[3] = 0x0A; #endif } diff --git a/src/user.c b/src/user.c index b0ecdba..cbe91fe 100644 --- a/src/user.c +++ b/src/user.c @@ -42,12 +42,20 @@ int init_users(in_addr_t my_ip, int netbits) int i; int skip = 0; char newip[16]; + char ip6Tmp[16]; + char ip6Tmp2[18]; + char ipv4Tmp[16]; int maxusers; in_addr_t netmask = 0; struct in_addr net; struct in_addr ipstart; + + /* For IPv6, we take the IPv4 address and simply prepend :: + * and use a 64-bit mask. Reduces the need to parse + * netmasks. + */ for (i = 0; i < netbits; i++) { netmask = (netmask << 1) | 1; @@ -70,6 +78,19 @@ int init_users(in_addr_t my_ip, int netbits) skip++; snprintf(newip, sizeof(newip), "0.0.0.%d", i + skip + 1); ip = ipstart.s_addr + inet_addr(newip); + + inet_ntop(AF_INET, &ip, ip6Tmp, INET_ADDRSTRLEN); + + snprintf(ip6Tmp2, sizeof(ip6Tmp2), "::%s", ip6Tmp); + + inet_pton(AF_INET6, ip6Tmp2, &users[i].tun_ip6); + memset(ip6Tmp2,0,strlen(ip6Tmp2)); + inet_ntop(AF_INET6, &users[i].tun_ip6, ip6Tmp2, INET6_ADDRSTRLEN); + inet_ntop(AF_INET, &ip, ipv4Tmp, INET_ADDRSTRLEN); + printf("storing IPv4 address: %s\n", ipv4Tmp); + printf("storing IPv6 address: %s\n", ip6Tmp2); + memset(ip6Tmp2,0,strlen(ip6Tmp2)); + } users[i].tun_ip = ip; net.s_addr = ip; @@ -91,6 +112,40 @@ const char *users_get_first_ip(void) return strdup(inet_ntoa(ip)); } +int find_user_by_ip6(struct in6_addr *v6Addr) +{ + int i; + char v6AddrOut[32]; + + inet_ntop(AF_INET6, v6Addr, v6AddrOut, INET6_ADDRSTRLEN); + + printf("Going to check address: %s in user list\n", v6AddrOut); + for (i = 0; i < usercount; i++) { + if (users[i].active && + users[i].authenticated && + !users[i].disabled && + users[i].last_pkt + 60 > time(NULL) && + (areV6AddressesEqual(v6Addr, &users[i].tun_ip6) == 0) ) { + return i; + } + } + return -1; +} + +int areV6AddressesEqual(struct in6_addr *v6Struct1, struct in6_addr *v6Struct2) +{ + int i; + + for (i = 0; i < 16; i++) { + printf("byte1 %d: %d byte2 %d: %d\n", i, v6Struct1->s6_addr[i], i, v6Struct2->s6_addr[i]); + if (v6Struct1->s6_addr[i] != v6Struct2->s6_addr[i]) { + return -1; + } + } + return 0; +} + + int find_user_by_ip(uint32_t ip) { int ret; diff --git a/src/user.h b/src/user.h index b2ba704..bf160a6 100644 --- a/src/user.h +++ b/src/user.h @@ -45,6 +45,7 @@ struct tun_user { int seed; in_addr_t tun_ip; struct sockaddr_storage host; + struct in6_addr tun_ip6; socklen_t hostlen; struct query q; struct query q_sendrealsoon; @@ -83,9 +84,11 @@ extern struct tun_user *users; int init_users(in_addr_t, int); const char* users_get_first_ip(void); int find_user_by_ip(uint32_t); +int find_user_by_ip6(struct in6_addr *v6Addr); int all_users_waiting_to_send(void); int find_available_user(void); void user_switch_codec(int userid, const struct encoder *enc); void user_set_conn_type(int userid, enum connection c); +int areV6AddressesEqual(struct in6_addr *, struct in6_addr *); #endif