This commit is contained in:
Chris Hellberg 2022-05-09 01:03:38 +00:00 committed by GitHub
commit 98c71c3593
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 508 additions and 29 deletions

View File

@ -1,4 +1,4 @@
Copyright (c) 2006-2020 iodine authors
Copyright (c) 2006-2021 iodine authors
Permission to use, copy, modify, and/or distribute this software for any purpose
with or without fee is hereby granted, provided that the above copyright notice

View File

@ -123,7 +123,7 @@ end of the tunnel. In this case, `ping 192.168.99.1` from the iodine client, and
### MISC. INFO
#### IPv6
The data inside the tunnel is IPv4 only.
The data inside the tunnel may be IPv4 or IPv6.
The server listens to both IPv4 and IPv6 for incoming requests by default.
Use options `-4` or `-6` to only listen on one protocol. Raw mode will be
@ -141,6 +141,14 @@ to your DNS setup. Extending the example above would look like this:
t1ns IN A 10.15.213.99
t1ns IN AAAA 2001:db8::1001:99
On the server, specify -S followed by an IPv6 address that will be the server end
of the IPv6 pool to allocate to clients. The server only supports a /64 subnet
mask, which is assumed and can be omitted. The first 64 bits are the network from
which IPv6 addresses are allocated from.
The client will automatically check for IPv6 capability on the server and
assign the allocated address to its tunnel interface. No flags are needed.
#### Routing
It is possible to route all traffic through the DNS tunnel. To do this, first
add a host route to the nameserver used by iodine over the wired/wireless

View File

@ -9,7 +9,7 @@ ARCH = `uname -m`
HEAD_COMMIT = `git rev-parse --short HEAD`
LIBPATH = -L.
LDFLAGS += -lz `sh osflags $(TARGETOS) link` $(LIBPATH)
LDFLAGS += -lz `sh osflags $(TARGETOS) link` $(LIBPATH) -lm
CFLAGS += -std=c99 -c -g -Wall -D$(OS) -pedantic `sh osflags $(TARGETOS) cflags` -DGITREVISION=\"$(HEAD_COMMIT)\"
CFLAGS += -Wstrict-prototypes -Wtype-limits -Wmissing-declarations -Wmissing-prototypes

View File

@ -28,6 +28,8 @@
#include <fcntl.h>
#include <zlib.h>
#include <time.h>
#include <stdbool.h>
#ifdef WINDOWS32
#include "windows.h"
@ -101,6 +103,7 @@ static time_t lastdownstreamtime;
static long send_query_sendcnt = -1;
static long send_query_recvcnt = 0;
static int hostname_maxlen = 0xFF;
static bool use_v6 = false;
void
client_init()
@ -2414,8 +2417,77 @@ client_handshake(int dns_fd, int raw_mode, int autodetect_frag_size, int fragsiz
handshake_set_fragsize(dns_fd, fragsize);
if (!running)
return -1;
handshake_check_v6(dns_fd);
if (!running)
return -1;
}
return 0;
}
static
void send_v6_probe(int dns_fd)
{
char data[4096];
data[0] = userid;
send_packet(dns_fd, 'g', data, sizeof(data));
}
int
handshake_check_v6(int dns_fd)
{
char in[4096];
char server6[INET6_ADDRSTRLEN];
char client6[INET6_ADDRSTRLEN];
int i;
int read;
int netmask6 = 0;
int length_recieved;
fprintf(stderr, "Autoprobing server IPV6 tunnel support\n");
for (i = 0; running && i < 5; i++) {
send_v6_probe(dns_fd);
read = handshake_waitdns(dns_fd, in, sizeof(in), 'g', 'G', i+1);
if (read > 0) {
/*
* including a terminating dash to allow for future IPv6 options, e.g.
* netmask. Currently assumes /64. MTU is taken from the IPv4 handshake.
* A future IPv6-only implementation would need to pass mtu
* in the IPV6 handshake.
*/
if (sscanf(in, "%512[^-]-%512[^-]-%d", server6, client6, &netmask6) == 3) {
fprintf(stderr, "Server tunnel IPv6 is %s\n", server6);
fprintf(stderr, "Local tunnel IPv6 is %s\n", client6);
length_recieved = strlen(client6);
if (length_recieved > 2) {
if (tun_setip6(client6, server6, netmask6) == 0) {
use_v6 = true;
return 0;
} else {
errx(4, "Failed to set IPv6 tunnel address");
}
} else {
fprintf(stderr, "Received bad IPv6 tunnel handshake\n");
}
}
}
fprintf(stderr, "Retrying IPv6 tunnel handshake...\n");
}
if (!running)
return -1;
return 0;
}

View File

@ -37,5 +37,5 @@ void client_set_hostname_maxlen(int i);
int client_handshake(int dns_fd, int raw_mode, int autodetect_frag_size,
int fragsize);
int client_tunnel(int tun_fd, int dns_fd);
int handshake_check_v6(int tun_fd);
#endif

View File

@ -13,6 +13,8 @@
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*
*/
#include <time.h>
@ -557,3 +559,17 @@ fd_set_close_on_exec(int fd)
}
#endif
bool
isV6AddrSet(struct in6_addr *ip6)
{
int i;
for (i = 0; i < sizeof(ip6->s6_addr); i++) {
if (ip6->s6_addr[i] != 0) {
return true;
}
}
return false;
}

View File

@ -33,6 +33,7 @@
extern const unsigned char raw_header[RAW_HDR_LEN];
#include <stdarg.h>
#include <stdbool.h>
#ifdef WINDOWS32
#include "windows.h"
#else
@ -129,6 +130,7 @@ void read_password(char*, size_t);
int check_topdomain(char *, int, char **);
int query_datalen(const char *qname, const char *topdomain);
bool isV6AddrSet(struct in6_addr *);
#if defined(WINDOWS32) || defined(ANDROID)
#ifndef ANDROID

View File

@ -193,6 +193,7 @@ int main(int argc, char **argv)
#endif
while ((choice = getopt(argc, argv, "46vfhru:t:d:R:P:m:M:F:T:O:L:I:")) != -1) {
switch(choice) {
case '4':
nameserv_family = AF_INET;

View File

@ -88,10 +88,16 @@ static int created_users;
static int check_ip;
static int my_mtu;
static in_addr_t my_ip;
char display_ip6[INET6_ADDRSTRLEN];
char *display_ip6_buffer = NULL;
char *ip6_netmask_buffer = NULL;
static struct in6_addr my_ip6;
static int netmask;
static int ip6_netmask = 64;
static in_addr_t ns_ip;
static int bind_port;
static int debug;
@ -649,17 +655,32 @@ 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 = get_ipversion(in[4]);
if (ip_version == 4) { /* 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];
}
inet_ntop(AF_INET6, &v6Addr, v6AddrP, INET6_ADDRSTRLEN);
userid = find_user_by_ip6(&v6Addr);
}
if (userid < 0)
return 0;
outlen = sizeof(out);
compress2((uint8_t*)out, &outlen, (uint8_t*)in, read, 9);
if (users[userid].conn == CONN_DNS_NULL) {
@ -1289,6 +1310,32 @@ handle_null_request(int tun_fd, int dns_fd, struct dnsfd *dns_fds, struct query
!users[userid].lazy)
send_chunk_or_dataless(dns_fd, userid, &users[userid].q);
/* IPv6 tunnel address probe */
} else if (in[0] == 'G' || in[0] == 'g') {
char client_ip6[INET6_ADDRSTRLEN];
char display_my_ip6[INET6_ADDRSTRLEN];
read = unpack_data(unpacked, sizeof(unpacked), &(in[1]), domain_len - 1, &base32_ops);
if (read < 1) {
write_dns(dns_fd, q, "BADLEN", 6, 'T');
return;
}
/* Ping packet, store userid */
userid = unpacked[0];
if (check_authenticated_user_and_ip(userid, q) != 0) {
write_dns(dns_fd, q, "BADIP", 5, 'T');
return; /* illegal id */
}
inet_ntop(AF_INET6, &users[userid].tun_ip6, client_ip6, INET6_ADDRSTRLEN);
inet_ntop(AF_INET6, &my_ip6, display_my_ip6, INET6_ADDRSTRLEN);
read = snprintf(out, sizeof(out), "%s-%s-%d-",
display_my_ip6, client_ip6, ip6_netmask);
write_dns(dns_fd, q, out, read, users[userid].downenc);
return;
} else if ((in[0] >= '0' && in[0] <= '9')
|| (in[0] >= 'a' && in[0] <= 'f')
|| (in[0] >= 'A' && in[0] <= 'F')) {
@ -2277,7 +2324,7 @@ static void print_usage(FILE *stream)
"Usage: %s [-46cDfsv] [-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",
" [-F pidfile] [-S ipv6 tunnel address] [-i max idle time] tunnel_ip[/netmask] topdomain\n",
__progname);
}
@ -2319,6 +2366,7 @@ static void help(FILE *stream)
" -b port to forward normal DNS queries to (on localhost)\n"
" -P password used for authentication (max 32 chars will be used)\n"
" -F pidfile to write pid to a file\n"
" -S IPv6 server address within the tunnel. Netmask fixed at /64\n"
" -i maximum idle time before shutting down\n\n"
"tunnel_ip is the IP number of the local tunnel interface.\n"
" /netmask sets the size of the tunnel network.\n"
@ -2418,7 +2466,6 @@ main(int argc, char **argv)
debug = 0;
netmask = 27;
pidfile = NULL;
retval = 0;
#ifdef WINDOWS32
@ -2436,7 +2483,8 @@ main(int argc, char **argv)
srand(time(NULL));
fw_query_init();
while ((choice = getopt(argc, argv, "46vcsfhDu:t:d:m:l:L:p:n:b:P:z:F:i:")) != -1) {
while ((choice = getopt(argc, argv, "46vcsfhDuS:t:d:m:l:L:p:n:b:P:z:F:i:")) != -1) {
switch(choice) {
case '4':
addrfamily = AF_INET;
@ -2507,6 +2555,9 @@ main(int argc, char **argv)
/* XXX: find better way of cleaning up ps(1) */
memset(optarg, 0, strlen(optarg));
break;
case 'S':
display_ip6_buffer = optarg;
break;
case 'z':
context = optarg;
break;
@ -2534,10 +2585,32 @@ main(int argc, char **argv)
my_ip = inet_addr(argv[0]);
if (my_ip == INADDR_NONE) {
warnx("Bad IP address to use inside tunnel.");
warnx("Bad IP address to use inside tunnel.");
usage();
}
if (display_ip6_buffer != NULL) {
ip6_netmask_buffer = strchr(display_ip6_buffer, '/');
if (ip6_netmask_buffer != NULL) {
if (atoi(ip6_netmask_buffer+1) != ip6_netmask) {
warnx("IPv6 address must be a 64-bit mask.");
usage();
}
/* remove masklen */
memcpy(display_ip6, display_ip6_buffer, strlen(display_ip6_buffer) - strlen(ip6_netmask_buffer));
display_ip6[strlen(display_ip6)+1] = '\0';
}
/* IPV6 address sanity check */
if (inet_pton(AF_INET6, display_ip6, &my_ip6) != 1) {
warnx("Bad IPv6 address to use inside tunnel.");
usage();
}
}
topdomain = strdup(argv[1]);
if (check_topdomain(topdomain, 1, &errormsg)) {
warnx("Invalid topdomain: %s", errormsg);
@ -2666,7 +2739,7 @@ main(int argc, char **argv)
dns_fds.v4fd = -1;
dns_fds.v6fd = -1;
created_users = init_users(my_ip, netmask);
created_users = init_users(my_ip, netmask, my_ip6, ip6_netmask);
if ((tun_fd = open_tun(device)) == -1) {
/* nothing to clean up, just return */
@ -2674,11 +2747,28 @@ main(int argc, char **argv)
}
if (!skipipconfig) {
const char *other_ip = users_get_first_ip();
const char *display_other_ip6 = users_get_first_ip6();
if (tun_setip(argv[0], other_ip, netmask) != 0 || tun_setmtu(mtu) != 0) {
retval = 1;
retval = 1;
free((void*) other_ip);
goto cleanup;
goto cleanup;
}
if (display_ip6_buffer != NULL) {
if (tun_setip6(display_ip6, display_other_ip6, ip6_netmask) != 0 ) {
retval = 1;
goto cleanup;
}
}
if ((mtu < 1280) && (sizeof(display_ip6)) != 0) {
warnx("Interface mtu of %d below the 1280 threshold needed for IPv6 tunneling.\n", mtu);
warnx("Proceeding without IPv6 tunneling\n");
}
free((void*) other_ip);
}

202
src/tun.c
View File

@ -35,6 +35,11 @@
#include <netinet/ip.h>
#endif
#if defined FREEBSD || defined NETBSD
#include <sys/ioctl.h>
#include <net/if_tun.h>
#endif
#ifndef IFCONFIGPATH
#define IFCONFIGPATH "PATH=/sbin:/bin "
#endif
@ -82,6 +87,7 @@ static char if_name[250];
#include <net/if.h>
#include <linux/if_tun.h>
int
open_tun(const char *tun_device)
{
@ -452,7 +458,15 @@ open_tun(const char *tun_device)
snprintf(tun_name, sizeof(tun_name), "/dev/tun%d", i);
if ((tun_fd = open(tun_name, O_RDWR)) >= 0) {
fprintf(stderr, "Opened %s\n", tun_name);
#if defined FREEBSD || defined NETBSD
/* FreeBSD requires a packet header for
* IPv6 traffic
*/
if (ioctl(tun_fd, TUNSIFHEAD, &(int){1}) != 0) {
fprintf(stderr, "Not able to enable TUNSIFHEAD\n");
break;
}
#endif /* LINUX */
snprintf(if_name, sizeof(if_name), "tun%d", i);
fd_set_close_on_exec(tun_fd);
return tun_fd;
@ -530,9 +544,12 @@ read_tun(int tun_fd, char *buf, size_t len)
static int
tun_uses_header(void)
{
#if defined (FREEBSD) || defined (NETBSD)
/* FreeBSD/NetBSD has no header */
return 0;
#if defined FREEBSD || defined NETBSD || defined OPENBSD
/* To enable IPv6 in FreeBSD tunnels, tunnel
* headers now enabled for that platform
*/
return 1;
#elif defined (DARWIN)
/* Darwin tun has no header, Darwin utun does */
return !strncmp(if_name, "utun", 4);
@ -544,24 +561,83 @@ tun_uses_header(void)
int
write_tun(int tun_fd, char *data, size_t len)
{
int ip_version = 0;
if (!tun_uses_header()) {
data += 4;
len -= 4;
} else {
ip_version = get_ipversion(data[4]);
if (ip_version < 0) {
return 1; /* Cannot read IP version number from packet */
}
#ifdef LINUX
if (ip_version == 4) {
// Linux prefixes with 32 bits ethertype
// 0x0800 for IPv4, 0x86DD for IPv6
data[0] = 0x00;
data[1] = 0x00;
data[2] = 0x08;
data[3] = 0x00;
#else /* OPENBSD and DARWIN(utun) */
data[0] = 0x00;
data[1] = 0x00;
data[2] = 0x08;
data[3] = 0x00;
} else { /* IPV6 */
data[0] = 0x00;
data[1] = 0x00;
data[2] = 0x86;
data[3] = 0xDD;
}
#elif defined (FREEBSD) || defined (OPENBSD)
// 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 (ip_version == 4) {
data[0] = 0x00;
data[1] = 0x00;
data[2] = 0x00;
data[3] = 0x02;
} else { /* IPV6 */
data[0] = 0x00;
data[1] = 0x00;
data[2] = 0x00;
data[3] = 0x1C;
}
#elif defined NETBSD
// BSDs prefix with 32 bits address family
// AF_INET for IPv4, AF_INET6 for IPv6
if (ip_version == 4) {
data[0] = 0x00;
data[1] = 0x00;
data[2] = 0x00;
data[3] = 0x02;
} else { /* IPV6 */
data[0] = 0x00;
data[1] = 0x00;
data[2] = 0x00;
data[3] = 0x18;
}
#else /* DARWIN(utun) and all others */
// BSDs prefix with 32 bits address family
// AF_INET for IPv4, AF_INET6 for IPv6
if (ip_version == 4) {
data[0] = 0x00;
data[1] = 0x00;
data[2] = 0x00;
data[3] = 0x02;
} else { /* IPV6 */
data[0] = 0x00;
data[1] = 0x00;
data[2] = 0x00;
data[3] = 0x1E;
}
#endif
}
@ -630,6 +706,7 @@ tun_setip(const char *ip, const char *other_ip, int netbits)
# else
display_ip = ip;
# endif
snprintf(cmdline, sizeof(cmdline),
IFCONFIGPATH "ifconfig %s %s %s netmask %s",
if_name,
@ -687,6 +764,90 @@ tun_setip(const char *ip, const char *other_ip, int netbits)
if_name, ip, inet_ntoa(net));
return system(cmdline);
#endif
}
int
tun_setip6(char *display_ip6, const char *display_other_ip6, int netbits6)
{
int v6_r;
struct in6_addr ip6;
char v6_cmdline[512];
if (inet_pton(AF_INET6, display_ip6, &ip6) < 1){
warnx("Error in IPv6 address");
}
#ifdef WINDOWS32
/*
DWORD status;
DWORD ipdata[3];
struct in_addr addr;
DWORD len;
*/
#endif
if (netbits6 > 0) {
fprintf(stderr, "Setting IPv6 of %s to %s\n", if_name, display_ip6);
#if defined LINUX
snprintf(v6_cmdline, sizeof(v6_cmdline),
IFCONFIGPATH "ifconfig %s inet6 add %s/%d",
if_name,
display_ip6, netbits6);
#else
snprintf(v6_cmdline, sizeof(v6_cmdline),
IFCONFIGPATH "ifconfig %s inet6 %s/%d",
if_name,
display_ip6, netbits6);
#endif
v6_r = system(v6_cmdline);
if (v6_r != 0) {
return v6_r;
} else {
return 0;
}
}
#ifdef WINDOWS32 /* WINDOWS32 */
/* Set device as connected */
fprintf(stderr, "Enabling interface '%s'\n", if_name);
status = 1;
r = DeviceIoControl(dev_handle, TAP_IOCTL_SET_MEDIA_STATUS, &status,
sizeof(status), &status, sizeof(status), &len, NULL);
if (!r) {
fprintf(stderr, "Failed to enable interface\n");
return -1;
}
if (inet_aton(ip, &addr)) {
ipdata[0] = (DWORD) addr.s_addr; /* local ip addr */
ipdata[1] = net.s_addr & ipdata[0]; /* network addr */
ipdata[2] = (DWORD) net.s_addr; /* netmask */
} else {
return -1;
}
/* Tell ip/networkaddr/netmask to device for arp use */
r = DeviceIoControl(dev_handle, TAP_IOCTL_CONFIG_TUN, &ipdata,
sizeof(ipdata), &ipdata, sizeof(ipdata), &len, NULL);
if (!r) {
fprintf(stderr, "Failed to set interface in TUN mode\n");
return -1;
}
/* use netsh to set ip address */
fprintf(stderr, "Setting IP of interface '%s' to %s (can take a few seconds)...\n", if_name, ip);
snprintf(cmdline, sizeof(cmdline), "netsh interface ip set address \"%s\" static %s %s",
if_name, ip, inet_ntoa(net));
return system(cmdline);
#endif
return 0;
}
int
@ -714,3 +875,18 @@ tun_setmtu(const unsigned mtu)
#endif
}
int get_ipversion(char first_byte)
{
int v;
v = first_byte & 0xf0;
if (v == 64) {
return 4;
} else if (v == 96) {
return 6;
} else {
return -1;
}
}

View File

@ -23,6 +23,8 @@ 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_setip6(char *, const char *, int);
int tun_setmtu(const unsigned);
int get_ipversion(char);
#endif /* _TUN_H_ */

View File

@ -23,6 +23,7 @@
#include <signal.h>
#include <unistd.h>
#include <fcntl.h>
#include <math.h>
#ifdef WINDOWS32
#include <winsock2.h>
@ -37,10 +38,12 @@
struct tun_user *users;
unsigned usercount;
int init_users(in_addr_t my_ip, int netbits)
int init_users(in_addr_t my_ip, int netbits, struct in6_addr my_ip6, int netbits6)
{
int i;
int i6;
int skip = 0;
int skip6 = 0;
char newip[16];
int maxusers;
@ -48,7 +51,13 @@ int init_users(in_addr_t my_ip, int netbits)
in_addr_t netmask = 0;
struct in_addr net;
struct in_addr ipstart;
struct in6_addr ip6start;
unsigned ip6_netmask[16];
bool ip6_enabled;
ip6_enabled = isV6AddrSet(&my_ip6);
for (i = 0; i < netbits; i++) {
netmask = (netmask << 1) | 1;
}
@ -56,22 +65,77 @@ int init_users(in_addr_t my_ip, int netbits)
net.s_addr = htonl(netmask);
ipstart.s_addr = my_ip & net.s_addr;
/* Covert IPv6 netbits to IPv6 netmask and work
* out the network address from my IP address. Start
* assigning IPv6 address from the network address + 1
*/
if (ip6_enabled == true) {
for (i6 = 0; i6 < netbits6 / 8; i6++) {
ip6_netmask[i6] |= 0xFF;
}
ip6_netmask[netbits6 / 8] = pow(2, (netbits6 % 8 )) - 1;
ip6_netmask[netbits6 / 8] <<= (8-(netbits6 % 8));
for (i6 = 0; i6 < 16; i6++) {
ip6start.s6_addr[i6] = my_ip6.s6_addr[i6] & ip6_netmask[i6];
}
}
maxusers = (1 << (32-netbits)) - 3; /* 3: Net addr, broadcast addr, iodined addr */
usercount = MIN(maxusers, USERS);
users = calloc(usercount, sizeof(struct tun_user));
/*
* IPv6 note: Current behavior is to populate the users structure
* with the IPv4 addresses that are expected to be used.
* In the future with IPv6-only tunnel transport, we should not be
* populating a /64 (or whatever mask) in the users structure
* and should shift to an on-demand scheme. For now
* we expect dual-stack and pre-allocate IPv6 addresses into the
* users struct as we do with IPv4.
*/
for (i = 0; i < usercount; i++) {
in_addr_t ip;
users[i].id = i;
snprintf(newip, sizeof(newip), "0.0.0.%d", i + skip + 1);
ip = ipstart.s_addr + inet_addr(newip);
if (ip == my_ip && skip == 0) {
/* This IP was taken by iodined */
skip++;
snprintf(newip, sizeof(newip), "0.0.0.%d", i + skip + 1);
ip = ipstart.s_addr + inet_addr(newip);
}
users[i].tun_ip = ip;
if (ip6_enabled == true) {
struct in6_addr temp_ip6;
/*
* start assigning host addresses from the network address + 1
* unless that is my_ip, in which case, use the following address.
*/
memcpy(temp_ip6.s6_addr, ip6start.s6_addr, sizeof(ip6start.s6_addr));
temp_ip6.s6_addr[15] = ip6start.s6_addr[15] + skip + 1 + i;
if (v6AddressesEqual(&temp_ip6, &my_ip6) == true &&
skip6 == 0) {
/* This IPv6 was taken by iodined */
skip6++;
/*
* We expect to start assigning addresses at the network address + 1 and
* to not worry about assigning more than 254 host addresses. If we did, we have to
* iterate through lower order bytes of ip6. This plus a few other corner cases
* is why we enourage/force/assume the user to specify a /64 V6 address
*/
temp_ip6.s6_addr[15] = ip6start.s6_addr[15] + skip + 1 + i;
}
memcpy(users[i].tun_ip6.s6_addr, temp_ip6.s6_addr, sizeof(temp_ip6.s6_addr));
}
net.s_addr = ip;
users[i].disabled = 0;
users[i].authenticated = 0;
@ -91,6 +155,50 @@ const char *users_get_first_ip(void)
return strdup(inet_ntoa(ip));
}
const char *users_get_first_ip6(void)
{
struct in6_addr ip6;
char display_ip6[INET6_ADDRSTRLEN];
memcpy(&ip6, &users[0].tun_ip6, sizeof(struct in6_addr));
inet_ntop(AF_INET6, &ip6, display_ip6, INET6_ADDRSTRLEN);
return strdup(display_ip6);
}
int find_user_by_ip6(struct in6_addr *v6Addr)
{
int i;
char v6AddrOut[32];
inet_ntop(AF_INET6, v6Addr, v6AddrOut, INET6_ADDRSTRLEN);
for (i = 0; i < usercount; i++) {
if (users[i].active &&
users[i].authenticated &&
!users[i].disabled &&
users[i].last_pkt + 60 > time(NULL) &&
v6AddressesEqual(v6Addr, &users[i].tun_ip6) == true) {
return i;
}
}
return -1;
}
bool v6AddressesEqual(struct in6_addr *v6Struct1, struct in6_addr *v6Struct2)
{
int i;
for (i = 0; i < 16; i++) {
if (v6Struct1->s6_addr[i] != v6Struct2->s6_addr[i]) {
return false;
}
}
return true;
}
int find_user_by_ip(uint32_t ip)
{
int ret;

View File

@ -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;
@ -80,12 +81,15 @@ struct tun_user {
extern struct tun_user *users;
int init_users(in_addr_t, int);
int init_users(in_addr_t, int, struct in6_addr, int);
const char* users_get_first_ip(void);
const char* users_get_first_ip6(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);
bool v6AddressesEqual(struct in6_addr *, struct in6_addr *);
#endif