further IPv6 changes
This commit is contained in:
parent
3eb959c8fe
commit
846082f13e
|
@ -9,7 +9,7 @@ ARCH = `uname -m`
|
||||||
HEAD_COMMIT = `git rev-parse --short HEAD`
|
HEAD_COMMIT = `git rev-parse --short HEAD`
|
||||||
|
|
||||||
LIBPATH = -L.
|
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 += -std=c99 -c -g -Wall -D$(OS) -pedantic `sh osflags $(TARGETOS) cflags` -DGITREVISION=\"$(HEAD_COMMIT)\"
|
||||||
CFLAGS += -Wstrict-prototypes -Wtype-limits -Wmissing-declarations -Wmissing-prototypes
|
CFLAGS += -Wstrict-prototypes -Wtype-limits -Wmissing-declarations -Wmissing-prototypes
|
||||||
|
|
||||||
|
|
75
src/client.c
75
src/client.c
|
@ -28,6 +28,8 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
|
||||||
#ifdef WINDOWS32
|
#ifdef WINDOWS32
|
||||||
#include "windows.h"
|
#include "windows.h"
|
||||||
|
@ -101,6 +103,7 @@ static time_t lastdownstreamtime;
|
||||||
static long send_query_sendcnt = -1;
|
static long send_query_sendcnt = -1;
|
||||||
static long send_query_recvcnt = 0;
|
static long send_query_recvcnt = 0;
|
||||||
static int hostname_maxlen = 0xFF;
|
static int hostname_maxlen = 0xFF;
|
||||||
|
static bool use_v6 = false;
|
||||||
|
|
||||||
void
|
void
|
||||||
client_init()
|
client_init()
|
||||||
|
@ -1374,7 +1377,7 @@ handshake_version(int dns_fd, int *seed)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
handshake_login(int dns_fd, int seed, int forward_v6)
|
handshake_login(int dns_fd, int seed)
|
||||||
{
|
{
|
||||||
char in[4096];
|
char in[4096];
|
||||||
char login[16];
|
char login[16];
|
||||||
|
@ -1405,7 +1408,7 @@ handshake_login(int dns_fd, int seed, int forward_v6)
|
||||||
|
|
||||||
server[64] = 0;
|
server[64] = 0;
|
||||||
client[64] = 0;
|
client[64] = 0;
|
||||||
if (tun_setip(client, server, netmask, forward_v6) == 0 &&
|
if (tun_setip(client, server, netmask) == 0 &&
|
||||||
tun_setmtu(mtu) == 0) {
|
tun_setmtu(mtu) == 0) {
|
||||||
|
|
||||||
fprintf(stderr, "Server tunnel IP is %s\n", server);
|
fprintf(stderr, "Server tunnel IP is %s\n", server);
|
||||||
|
@ -2326,7 +2329,7 @@ handshake_set_fragsize(int dns_fd, int fragsize)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
client_handshake(int dns_fd, int raw_mode, int autodetect_frag_size, int fragsize, int forward_v6)
|
client_handshake(int dns_fd, int raw_mode, int autodetect_frag_size, int fragsize)
|
||||||
{
|
{
|
||||||
int seed;
|
int seed;
|
||||||
int upcodec;
|
int upcodec;
|
||||||
|
@ -2349,7 +2352,7 @@ client_handshake(int dns_fd, int raw_mode, int autodetect_frag_size, int fragsiz
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = handshake_login(dns_fd, seed, forward_v6);
|
r = handshake_login(dns_fd, seed);
|
||||||
if (r) {
|
if (r) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -2414,8 +2417,72 @@ client_handshake(int dns_fd, int raw_mode, int autodetect_frag_size, int fragsiz
|
||||||
handshake_set_fragsize(dns_fd, fragsize);
|
handshake_set_fragsize(dns_fd, fragsize);
|
||||||
if (!running)
|
if (!running)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
handshake_check_v6(dns_fd);
|
||||||
|
if (!running)
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
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[1024];
|
||||||
|
char client6[1024];
|
||||||
|
int i;
|
||||||
|
int read;
|
||||||
|
int netmask6 = 0;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ void client_set_lazymode(int lazy_mode);
|
||||||
void client_set_hostname_maxlen(int i);
|
void client_set_hostname_maxlen(int i);
|
||||||
|
|
||||||
int client_handshake(int dns_fd, int raw_mode, int autodetect_frag_size,
|
int client_handshake(int dns_fd, int raw_mode, int autodetect_frag_size,
|
||||||
int fragsize, int forward_v6);
|
int fragsize);
|
||||||
int client_tunnel(int tun_fd, int dns_fd);
|
int client_tunnel(int tun_fd, int dns_fd);
|
||||||
|
int handshake_check_v6(int tun_fd);
|
||||||
#endif
|
#endif
|
||||||
|
|
16
src/common.c
16
src/common.c
|
@ -13,6 +13,8 @@
|
||||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
@ -557,3 +559,17 @@ fd_set_close_on_exec(int fd)
|
||||||
}
|
}
|
||||||
#endif
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
extern const unsigned char raw_header[RAW_HDR_LEN];
|
extern const unsigned char raw_header[RAW_HDR_LEN];
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#ifdef WINDOWS32
|
#ifdef WINDOWS32
|
||||||
#include "windows.h"
|
#include "windows.h"
|
||||||
#else
|
#else
|
||||||
|
@ -129,6 +130,7 @@ void read_password(char*, size_t);
|
||||||
int check_topdomain(char *, int, char **);
|
int check_topdomain(char *, int, char **);
|
||||||
|
|
||||||
int query_datalen(const char *qname, const char *topdomain);
|
int query_datalen(const char *qname, const char *topdomain);
|
||||||
|
bool isV6AddrSet(struct in6_addr *);
|
||||||
|
|
||||||
#if defined(WINDOWS32) || defined(ANDROID)
|
#if defined(WINDOWS32) || defined(ANDROID)
|
||||||
#ifndef ANDROID
|
#ifndef ANDROID
|
||||||
|
|
13
src/iodine.c
13
src/iodine.c
|
@ -72,7 +72,7 @@ static void help(FILE *stream, bool verbose)
|
||||||
{
|
{
|
||||||
fprintf(stream,
|
fprintf(stream,
|
||||||
"iodine IP over DNS tunneling client\n\n"
|
"iodine IP over DNS tunneling client\n\n"
|
||||||
"Usage: %s [-46fhrvS] [-u user] [-t chrootdir] [-d device] [-P password]\n"
|
"Usage: %s [-46fhrv] [-u user] [-t chrootdir] [-d device] [-P password]\n"
|
||||||
" [-m maxfragsize] [-M maxlen] [-T type] [-O enc] [-L 0|1] [-I sec]\n"
|
" [-m maxfragsize] [-M maxlen] [-T type] [-O enc] [-L 0|1] [-I sec]\n"
|
||||||
" [-z context] [-F pidfile] [nameserver] topdomain\n", __progname);
|
" [-z context] [-F pidfile] [nameserver] topdomain\n", __progname);
|
||||||
|
|
||||||
|
@ -100,7 +100,6 @@ static void help(FILE *stream, bool verbose)
|
||||||
" -t dir to chroot to directory dir\n"
|
" -t dir to chroot to directory dir\n"
|
||||||
" -d device to set tunnel device name\n"
|
" -d device to set tunnel device name\n"
|
||||||
" -z context, to apply specified SELinux context after initialization\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"
|
" -F pidfile to write pid to a file\n\n"
|
||||||
"nameserver is the IP number/hostname of the relaying nameserver. If absent,\n"
|
"nameserver is the IP number/hostname of the relaying nameserver. If absent,\n"
|
||||||
" /etc/resolv.conf is used\n"
|
" /etc/resolv.conf is used\n"
|
||||||
|
@ -153,7 +152,6 @@ int main(int argc, char **argv)
|
||||||
struct sockaddr_storage nameservaddr;
|
struct sockaddr_storage nameservaddr;
|
||||||
int nameservaddr_len;
|
int nameservaddr_len;
|
||||||
int nameserv_family;
|
int nameserv_family;
|
||||||
int forward_v6;
|
|
||||||
|
|
||||||
nameserv_host = NULL;
|
nameserv_host = NULL;
|
||||||
topdomain = NULL;
|
topdomain = NULL;
|
||||||
|
@ -178,7 +176,6 @@ int main(int argc, char **argv)
|
||||||
selecttimeout = 4;
|
selecttimeout = 4;
|
||||||
hostname_maxlen = 0xFF;
|
hostname_maxlen = 0xFF;
|
||||||
nameserv_family = AF_UNSPEC;
|
nameserv_family = AF_UNSPEC;
|
||||||
forward_v6 = 0;
|
|
||||||
|
|
||||||
#ifdef WINDOWS32
|
#ifdef WINDOWS32
|
||||||
WSAStartup(req_version, &wsa_data);
|
WSAStartup(req_version, &wsa_data);
|
||||||
|
@ -195,7 +192,8 @@ int main(int argc, char **argv)
|
||||||
__progname++;
|
__progname++;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while ((choice = getopt(argc, argv, "t:d:R:P:m:M:z:F:T:O:L:I:46vfhruS")) != -1) {
|
while ((choice = getopt(argc, argv, "46vfhru:t:d:R:P:m:M:F:T:O:L:I:")) != -1) {
|
||||||
|
|
||||||
switch(choice) {
|
switch(choice) {
|
||||||
case '4':
|
case '4':
|
||||||
nameserv_family = AF_INET;
|
nameserv_family = AF_INET;
|
||||||
|
@ -220,9 +218,6 @@ int main(int argc, char **argv)
|
||||||
case 'u':
|
case 'u':
|
||||||
username = optarg;
|
username = optarg;
|
||||||
break;
|
break;
|
||||||
case 'S':
|
|
||||||
forward_v6 = 1;
|
|
||||||
break;
|
|
||||||
case 't':
|
case 't':
|
||||||
newroot = optarg;
|
newroot = optarg;
|
||||||
break;
|
break;
|
||||||
|
@ -372,7 +367,7 @@ int main(int argc, char **argv)
|
||||||
fprintf(stderr, "Sending DNS queries for %s to %s\n",
|
fprintf(stderr, "Sending DNS queries for %s to %s\n",
|
||||||
topdomain, format_addr(&nameservaddr, nameservaddr_len));
|
topdomain, format_addr(&nameservaddr, nameservaddr_len));
|
||||||
|
|
||||||
if (client_handshake(dns_fd, raw_mode, autodetect_frag_size, max_downstream_frag_size, forward_v6)) {
|
if (client_handshake(dns_fd, raw_mode, autodetect_frag_size, max_downstream_frag_size)) {
|
||||||
retval = 1;
|
retval = 1;
|
||||||
goto cleanup2;
|
goto cleanup2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,10 +88,16 @@ static int created_users;
|
||||||
static int check_ip;
|
static int check_ip;
|
||||||
static int my_mtu;
|
static int my_mtu;
|
||||||
static in_addr_t my_ip;
|
static in_addr_t my_ip;
|
||||||
|
|
||||||
|
char display_ip6[INET6_ADDRSTRLEN];
|
||||||
|
char *display_ip6_buffer;
|
||||||
|
char *ip6_netmask_buffer;
|
||||||
|
|
||||||
|
static struct in6_addr my_ip6;
|
||||||
static int netmask;
|
static int netmask;
|
||||||
|
static int ip6_netmask = 64;
|
||||||
|
|
||||||
static in_addr_t ns_ip;
|
static in_addr_t ns_ip;
|
||||||
|
|
||||||
static int bind_port;
|
static int bind_port;
|
||||||
static int debug;
|
static int debug;
|
||||||
|
|
||||||
|
@ -658,9 +664,9 @@ static int tunnel_tun(int tun_fd, struct dnsfd *dns_fds)
|
||||||
|
|
||||||
/* find target ip in packet, in is padded with 4 bytes TUN header */
|
/* find target ip in packet, in is padded with 4 bytes TUN header */
|
||||||
header = (struct ip*) (in + 4);
|
header = (struct ip*) (in + 4);
|
||||||
ip_version = in[4] & 0xf0;
|
ip_version = get_ipversion(in[4]);
|
||||||
|
|
||||||
if (ip_version == 64) { /* IPv4 */
|
if (ip_version == 4) { /* IPv4 */
|
||||||
header = (struct ip*) (in + 4);
|
header = (struct ip*) (in + 4);
|
||||||
userid = find_user_by_ip(header->ip_dst.s_addr);
|
userid = find_user_by_ip(header->ip_dst.s_addr);
|
||||||
} else { /* IPv6 */
|
} else { /* IPv6 */
|
||||||
|
@ -674,6 +680,7 @@ static int tunnel_tun(int tun_fd, struct dnsfd *dns_fds)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
outlen = sizeof(out);
|
outlen = sizeof(out);
|
||||||
|
|
||||||
compress2((uint8_t*)out, &outlen, (uint8_t*)in, read, 9);
|
compress2((uint8_t*)out, &outlen, (uint8_t*)in, read, 9);
|
||||||
|
|
||||||
if (users[userid].conn == CONN_DNS_NULL) {
|
if (users[userid].conn == CONN_DNS_NULL) {
|
||||||
|
@ -1303,6 +1310,32 @@ handle_null_request(int tun_fd, int dns_fd, struct dnsfd *dns_fds, struct query
|
||||||
!users[userid].lazy)
|
!users[userid].lazy)
|
||||||
send_chunk_or_dataless(dns_fd, userid, &users[userid].q);
|
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')
|
} else if ((in[0] >= '0' && in[0] <= '9')
|
||||||
|| (in[0] >= 'a' && in[0] <= 'f')
|
|| (in[0] >= 'a' && in[0] <= 'f')
|
||||||
|| (in[0] >= 'A' && in[0] <= 'F')) {
|
|| (in[0] >= 'A' && in[0] <= 'F')) {
|
||||||
|
@ -2288,10 +2321,10 @@ write_dns(int fd, struct query *q, const char *data, int datalen, char downenc)
|
||||||
static void print_usage(FILE *stream)
|
static void print_usage(FILE *stream)
|
||||||
{
|
{
|
||||||
fprintf(stream,
|
fprintf(stream,
|
||||||
"Usage: %s [-46cDfsvS] [-u user] [-t chrootdir] [-d device] [-m mtu]\n"
|
"Usage: %s [-46cDfsv] [-u user] [-t chrootdir] [-d device] [-m mtu]\n"
|
||||||
" [-z context] [-l ipv4 listen address] [-L ipv6 listen address]\n"
|
" [-z context] [-l ipv4 listen address] [-L ipv6 listen address]\n"
|
||||||
" [-p port] [-n auto|external_ip] [-b dnsport] [-P password]\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);
|
__progname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2333,7 +2366,7 @@ static void help(FILE *stream)
|
||||||
" -b port to forward normal DNS queries to (on localhost)\n"
|
" -b port to forward normal DNS queries to (on localhost)\n"
|
||||||
" -P password used for authentication (max 32 chars will be used)\n"
|
" -P password used for authentication (max 32 chars will be used)\n"
|
||||||
" -F pidfile to write pid to a file\n"
|
" -F pidfile to write pid to a file\n"
|
||||||
" -S enable forwarding of IPv6 packets within the tunnel\n"
|
" -S IPv6 server address within the tunnel. Netmask fixed at /64\n"
|
||||||
" -i maximum idle time before shutting down\n\n"
|
" -i maximum idle time before shutting down\n\n"
|
||||||
"tunnel_ip is the IP number of the local tunnel interface.\n"
|
"tunnel_ip is the IP number of the local tunnel interface.\n"
|
||||||
" /netmask sets the size of the tunnel network.\n"
|
" /netmask sets the size of the tunnel network.\n"
|
||||||
|
@ -2405,7 +2438,6 @@ main(int argc, char **argv)
|
||||||
int dns4addr_len;
|
int dns4addr_len;
|
||||||
struct sockaddr_storage dns6addr;
|
struct sockaddr_storage dns6addr;
|
||||||
int dns6addr_len;
|
int dns6addr_len;
|
||||||
int forward_v6;
|
|
||||||
#ifdef HAVE_SYSTEMD
|
#ifdef HAVE_SYSTEMD
|
||||||
int nb_fds;
|
int nb_fds;
|
||||||
#endif
|
#endif
|
||||||
|
@ -2434,7 +2466,6 @@ main(int argc, char **argv)
|
||||||
debug = 0;
|
debug = 0;
|
||||||
netmask = 27;
|
netmask = 27;
|
||||||
pidfile = NULL;
|
pidfile = NULL;
|
||||||
forward_v6 = 0;
|
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
||||||
#ifdef WINDOWS32
|
#ifdef WINDOWS32
|
||||||
|
@ -2452,7 +2483,8 @@ main(int argc, char **argv)
|
||||||
srand(time(NULL));
|
srand(time(NULL));
|
||||||
fw_query_init();
|
fw_query_init();
|
||||||
|
|
||||||
while ((choice = getopt(argc, argv, "t:d:m:l:L:p:n:b:P:z:F:i:46vcsSfhDu")) != -1) {
|
while ((choice = getopt(argc, argv, "46vcsfhDuS:t:d:m:l:L:p:n:b:P:z:F:i:")) != -1) {
|
||||||
|
|
||||||
switch(choice) {
|
switch(choice) {
|
||||||
case '4':
|
case '4':
|
||||||
addrfamily = AF_INET;
|
addrfamily = AF_INET;
|
||||||
|
@ -2524,7 +2556,7 @@ main(int argc, char **argv)
|
||||||
memset(optarg, 0, strlen(optarg));
|
memset(optarg, 0, strlen(optarg));
|
||||||
break;
|
break;
|
||||||
case 'S':
|
case 'S':
|
||||||
forward_v6 = 1;
|
display_ip6_buffer = optarg;
|
||||||
break;
|
break;
|
||||||
case 'z':
|
case 'z':
|
||||||
context = optarg;
|
context = optarg;
|
||||||
|
@ -2553,10 +2585,28 @@ main(int argc, char **argv)
|
||||||
my_ip = inet_addr(argv[0]);
|
my_ip = inet_addr(argv[0]);
|
||||||
|
|
||||||
if (my_ip == INADDR_NONE) {
|
if (my_ip == INADDR_NONE) {
|
||||||
warnx("Bad IP address to use inside tunnel.");
|
warnx("Bad IP address to use inside tunnel.");
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ip6_netmask_buffer = strchr(display_ip6_buffer, '/');
|
||||||
|
if (ip6_netmask_buffer) {
|
||||||
|
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]);
|
topdomain = strdup(argv[1]);
|
||||||
if (check_topdomain(topdomain, 1, &errormsg)) {
|
if (check_topdomain(topdomain, 1, &errormsg)) {
|
||||||
warnx("Invalid topdomain: %s", errormsg);
|
warnx("Invalid topdomain: %s", errormsg);
|
||||||
|
@ -2685,7 +2735,7 @@ main(int argc, char **argv)
|
||||||
dns_fds.v4fd = -1;
|
dns_fds.v4fd = -1;
|
||||||
dns_fds.v6fd = -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) {
|
if ((tun_fd = open_tun(device)) == -1) {
|
||||||
/* nothing to clean up, just return */
|
/* nothing to clean up, just return */
|
||||||
|
@ -2693,16 +2743,26 @@ main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
if (!skipipconfig) {
|
if (!skipipconfig) {
|
||||||
const char *other_ip = users_get_first_ip();
|
const char *other_ip = users_get_first_ip();
|
||||||
if (tun_setip(argv[0], other_ip, netmask, forward_v6) != 0 || tun_setmtu(mtu) != 0) {
|
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);
|
free((void*) other_ip);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
}
|
}
|
||||||
if ((mtu < 1280) && (forward_v6)) {
|
|
||||||
warnx("Interface mtu of %d below the 1280 threshold needed for IPv6 tunneling.\n", mtu);
|
if (tun_setip6(display_ip6, display_other_ip6, ip6_netmask) != 0 ) {
|
||||||
warnx("Proceeding without IPv6 tunneling\n");
|
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);
|
free((void*) other_ip);
|
||||||
}
|
}
|
||||||
|
|
205
src/tun.c
205
src/tun.c
|
@ -35,6 +35,11 @@
|
||||||
#include <netinet/ip.h>
|
#include <netinet/ip.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined FREEBSD || defined NETBSD
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <net/if_tun.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef IFCONFIGPATH
|
#ifndef IFCONFIGPATH
|
||||||
#define IFCONFIGPATH "PATH=/sbin:/bin "
|
#define IFCONFIGPATH "PATH=/sbin:/bin "
|
||||||
#endif
|
#endif
|
||||||
|
@ -82,6 +87,7 @@ static char if_name[250];
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <linux/if_tun.h>
|
#include <linux/if_tun.h>
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
open_tun(const char *tun_device)
|
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);
|
snprintf(tun_name, sizeof(tun_name), "/dev/tun%d", i);
|
||||||
|
|
||||||
if ((tun_fd = open(tun_name, O_RDWR)) >= 0) {
|
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);
|
snprintf(if_name, sizeof(if_name), "tun%d", i);
|
||||||
fd_set_close_on_exec(tun_fd);
|
fd_set_close_on_exec(tun_fd);
|
||||||
return tun_fd;
|
return tun_fd;
|
||||||
|
@ -530,9 +544,12 @@ read_tun(int tun_fd, char *buf, size_t len)
|
||||||
static int
|
static int
|
||||||
tun_uses_header(void)
|
tun_uses_header(void)
|
||||||
{
|
{
|
||||||
#if defined (FREEBSD) || defined (NETBSD)
|
#if defined FREEBSD || defined NETBSD || defined OPENBSD
|
||||||
/* FreeBSD/NetBSD has no header */
|
/* To enable IPv6 in FreeBSD tunnels, tunnel
|
||||||
return 0;
|
* headers now enabled for that platform
|
||||||
|
*/
|
||||||
|
return 1;
|
||||||
|
|
||||||
#elif defined (DARWIN)
|
#elif defined (DARWIN)
|
||||||
/* Darwin tun has no header, Darwin utun does */
|
/* Darwin tun has no header, Darwin utun does */
|
||||||
return !strncmp(if_name, "utun", 4);
|
return !strncmp(if_name, "utun", 4);
|
||||||
|
@ -544,41 +561,82 @@ tun_uses_header(void)
|
||||||
int
|
int
|
||||||
write_tun(int tun_fd, char *data, size_t len)
|
write_tun(int tun_fd, char *data, size_t len)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
int ip_version = 0;
|
||||||
|
|
||||||
if (!tun_uses_header()) {
|
if (!tun_uses_header()) {
|
||||||
data += 4;
|
data += 4;
|
||||||
len -= 4;
|
len -= 4;
|
||||||
} else {
|
} else {
|
||||||
int i = data[4] & 0xf0;
|
|
||||||
|
ip_version = get_ipversion(data[4]);
|
||||||
|
|
||||||
|
if (ip_version < 0) {
|
||||||
|
return 1; /* Cannot read IP version number from packet */
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef LINUX
|
#ifdef LINUX
|
||||||
|
|
||||||
if (i == 64) {
|
if (ip_version == 4) {
|
||||||
// Look at the fifth bype
|
|
||||||
// Linux prefixes with 32 bits ethertype
|
// Linux prefixes with 32 bits ethertype
|
||||||
// 0x0800 for IPv4, 0x86DD for IPv6
|
// 0x0800 for IPv4, 0x86DD for IPv6
|
||||||
data[0] = 0x00;
|
data[0] = 0x00;
|
||||||
data[1] = 0x00;
|
data[1] = 0x00;
|
||||||
data[2] = 0x08;
|
data[2] = 0x08;
|
||||||
data[3] = 0x00;
|
data[3] = 0x00;
|
||||||
} else { /* 96 for IPV6 */
|
} else { /* IPV6 */
|
||||||
data[0] = 0x00;
|
data[0] = 0x00;
|
||||||
data[1] = 0x00;
|
data[1] = 0x00;
|
||||||
data[2] = 0x86;
|
data[2] = 0x86;
|
||||||
data[3] = 0xDD;
|
data[3] = 0xDD;
|
||||||
}
|
}
|
||||||
#else /* OPENBSD and DARWIN(utun) */
|
#elif defined (FREEBSD) || defined (OPENBSD)
|
||||||
|
|
||||||
// BSDs prefix with 32 bits address family
|
// BSDs prefix with 32 bits address family
|
||||||
// AF_INET for IPv4, AF_INET6 for IPv6
|
// AF_INET for IPv4, AF_INET6 for IPv6
|
||||||
if (i == 64) {
|
if (ip_version == 4) {
|
||||||
data[0] = 0x00;
|
data[0] = 0x00;
|
||||||
data[1] = 0x00;
|
data[1] = 0x00;
|
||||||
data[2] = 0x00;
|
data[2] = 0x00;
|
||||||
data[3] = 0x02;
|
data[3] = 0x02;
|
||||||
} else { /* 96 for IPV6 */
|
} 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[0] = 0x00;
|
||||||
data[1] = 0x00;
|
data[1] = 0x00;
|
||||||
data[2] = 0x00;
|
data[2] = 0x00;
|
||||||
data[3] = 0x1E;
|
data[3] = 0x1E;
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -610,14 +668,12 @@ read_tun(int tun_fd, char *buf, size_t len)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int
|
int
|
||||||
tun_setip(const char *ip, const char *other_ip, int netbits, int forward_v6)
|
tun_setip(const char *ip, const char *other_ip, int netbits)
|
||||||
{
|
{
|
||||||
char cmdline[512];
|
char cmdline[512];
|
||||||
char v6_cmdline[512];
|
|
||||||
int netmask;
|
int netmask;
|
||||||
struct in_addr net;
|
struct in_addr net;
|
||||||
int i;
|
int i;
|
||||||
int v6_r;
|
|
||||||
#ifndef LINUX
|
#ifndef LINUX
|
||||||
int r;
|
int r;
|
||||||
#endif
|
#endif
|
||||||
|
@ -650,20 +706,7 @@ tun_setip(const char *ip, const char *other_ip, int netbits, int forward_v6)
|
||||||
# else
|
# else
|
||||||
display_ip = ip;
|
display_ip = ip;
|
||||||
# endif
|
# endif
|
||||||
if (forward_v6) {
|
|
||||||
fprintf(stderr, "Setting IPv6 of %s to ::%s\n", if_name, ip);
|
|
||||||
|
|
||||||
snprintf(v6_cmdline, sizeof(cmdline),
|
|
||||||
IFCONFIGPATH "ifconfig %s inet6 add ::%s/64",
|
|
||||||
if_name,
|
|
||||||
display_ip);
|
|
||||||
|
|
||||||
v6_r = system(v6_cmdline);
|
|
||||||
|
|
||||||
if (v6_r != 0) {
|
|
||||||
return v6_r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
snprintf(cmdline, sizeof(cmdline),
|
snprintf(cmdline, sizeof(cmdline),
|
||||||
IFCONFIGPATH "ifconfig %s %s %s netmask %s",
|
IFCONFIGPATH "ifconfig %s %s %s netmask %s",
|
||||||
if_name,
|
if_name,
|
||||||
|
@ -722,14 +765,89 @@ tun_setip(const char *ip, const char *other_ip, int netbits, int forward_v6)
|
||||||
return system(cmdline);
|
return system(cmdline);
|
||||||
#endif
|
#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
|
||||||
|
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
|
int
|
||||||
|
@ -757,3 +875,18 @@ tun_setmtu(const unsigned mtu)
|
||||||
#endif
|
#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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -22,7 +22,9 @@ int open_tun(const char *);
|
||||||
void close_tun(int);
|
void close_tun(int);
|
||||||
int write_tun(int, char *, size_t);
|
int write_tun(int, char *, size_t);
|
||||||
ssize_t read_tun(int, char *, size_t);
|
ssize_t read_tun(int, char *, size_t);
|
||||||
int tun_setip(const char *, const char *, int, int);
|
int tun_setip(const char *, const char *, int);
|
||||||
|
int tun_setip6(char *, const char *, int);
|
||||||
int tun_setmtu(const unsigned);
|
int tun_setmtu(const unsigned);
|
||||||
|
int get_ipversion(char);
|
||||||
|
|
||||||
#endif /* _TUN_H_ */
|
#endif /* _TUN_H_ */
|
||||||
|
|
99
src/user.c
99
src/user.c
|
@ -23,6 +23,7 @@
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
#ifdef WINDOWS32
|
#ifdef WINDOWS32
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
|
@ -37,25 +38,26 @@
|
||||||
struct tun_user *users;
|
struct tun_user *users;
|
||||||
unsigned usercount;
|
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 i;
|
||||||
|
int i6;
|
||||||
int skip = 0;
|
int skip = 0;
|
||||||
|
int skip6 = 0;
|
||||||
char newip[16];
|
char newip[16];
|
||||||
char ip6Tmp[16];
|
|
||||||
char ip6Tmp2[18];
|
|
||||||
|
|
||||||
int maxusers;
|
int maxusers;
|
||||||
|
|
||||||
in_addr_t netmask = 0;
|
in_addr_t netmask = 0;
|
||||||
struct in_addr net;
|
struct in_addr net;
|
||||||
struct in_addr ipstart;
|
struct in_addr ipstart;
|
||||||
|
struct in6_addr ip6start;
|
||||||
/* For IPv6, we take the IPv4 address and simply prepend ::
|
unsigned ip6_netmask[16];
|
||||||
* and use a 64-bit mask. Reduces the need to parse
|
|
||||||
* netmasks.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
bool ip6_enabled;
|
||||||
|
|
||||||
|
ip6_enabled = isV6AddrSet(&my_ip6);
|
||||||
|
|
||||||
for (i = 0; i < netbits; i++) {
|
for (i = 0; i < netbits; i++) {
|
||||||
netmask = (netmask << 1) | 1;
|
netmask = (netmask << 1) | 1;
|
||||||
}
|
}
|
||||||
|
@ -63,17 +65,39 @@ int init_users(in_addr_t my_ip, int netbits)
|
||||||
net.s_addr = htonl(netmask);
|
net.s_addr = htonl(netmask);
|
||||||
ipstart.s_addr = my_ip & net.s_addr;
|
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 */
|
maxusers = (1 << (32-netbits)) - 3; /* 3: Net addr, broadcast addr, iodined addr */
|
||||||
usercount = MIN(maxusers, USERS);
|
usercount = MIN(maxusers, USERS);
|
||||||
|
|
||||||
users = calloc(usercount, sizeof(struct tun_user));
|
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++) {
|
for (i = 0; i < usercount; i++) {
|
||||||
in_addr_t ip;
|
in_addr_t ip;
|
||||||
users[i].id = i;
|
users[i].id = i;
|
||||||
|
|
||||||
memset(ip6Tmp,0,strlen(ip6Tmp));
|
|
||||||
memset(ip6Tmp2,0,strlen(ip6Tmp2));
|
|
||||||
|
|
||||||
snprintf(newip, sizeof(newip), "0.0.0.%d", i + skip + 1);
|
snprintf(newip, sizeof(newip), "0.0.0.%d", i + skip + 1);
|
||||||
|
|
||||||
ip = ipstart.s_addr + inet_addr(newip);
|
ip = ipstart.s_addr + inet_addr(newip);
|
||||||
|
@ -82,15 +106,36 @@ int init_users(in_addr_t my_ip, int netbits)
|
||||||
skip++;
|
skip++;
|
||||||
snprintf(newip, sizeof(newip), "0.0.0.%d", i + skip + 1);
|
snprintf(newip, sizeof(newip), "0.0.0.%d", i + skip + 1);
|
||||||
ip = ipstart.s_addr + inet_addr(newip);
|
ip = ipstart.s_addr + inet_addr(newip);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
users[i].tun_ip = ip;
|
users[i].tun_ip = ip;
|
||||||
|
|
||||||
inet_ntop(AF_INET, &ip, ip6Tmp, INET_ADDRSTRLEN);
|
if (ip6_enabled == true) {
|
||||||
snprintf(ip6Tmp2, sizeof(ip6Tmp2), "::%s", ip6Tmp);
|
struct in6_addr temp_ip6;
|
||||||
inet_pton(AF_INET6, ip6Tmp2, &users[i].tun_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;
|
net.s_addr = ip;
|
||||||
users[i].disabled = 0;
|
users[i].disabled = 0;
|
||||||
users[i].authenticated = 0;
|
users[i].authenticated = 0;
|
||||||
|
@ -110,6 +155,18 @@ const char *users_get_first_ip(void)
|
||||||
return strdup(inet_ntoa(ip));
|
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 find_user_by_ip6(struct in6_addr *v6Addr)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -122,23 +179,23 @@ int find_user_by_ip6(struct in6_addr *v6Addr)
|
||||||
users[i].authenticated &&
|
users[i].authenticated &&
|
||||||
!users[i].disabled &&
|
!users[i].disabled &&
|
||||||
users[i].last_pkt + 60 > time(NULL) &&
|
users[i].last_pkt + 60 > time(NULL) &&
|
||||||
(areV6AddressesEqual(v6Addr, &users[i].tun_ip6) == 0) ) {
|
v6AddressesEqual(v6Addr, &users[i].tun_ip6) == true) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int areV6AddressesEqual(struct in6_addr *v6Struct1, struct in6_addr *v6Struct2)
|
bool v6AddressesEqual(struct in6_addr *v6Struct1, struct in6_addr *v6Struct2)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < 16; i++) {
|
for (i = 0; i < 16; i++) {
|
||||||
if (v6Struct1->s6_addr[i] != v6Struct2->s6_addr[i]) {
|
if (v6Struct1->s6_addr[i] != v6Struct2->s6_addr[i]) {
|
||||||
return -1;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -81,14 +81,15 @@ struct tun_user {
|
||||||
|
|
||||||
extern struct tun_user *users;
|
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_ip(void);
|
||||||
|
const char* users_get_first_ip6(void);
|
||||||
int find_user_by_ip(uint32_t);
|
int find_user_by_ip(uint32_t);
|
||||||
int find_user_by_ip6(struct in6_addr *v6Addr);
|
int find_user_by_ip6(struct in6_addr *v6Addr);
|
||||||
int all_users_waiting_to_send(void);
|
int all_users_waiting_to_send(void);
|
||||||
int find_available_user(void);
|
int find_available_user(void);
|
||||||
void user_switch_codec(int userid, const struct encoder *enc);
|
void user_switch_codec(int userid, const struct encoder *enc);
|
||||||
void user_set_conn_type(int userid, enum connection c);
|
void user_set_conn_type(int userid, enum connection c);
|
||||||
int areV6AddressesEqual(struct in6_addr *, struct in6_addr *);
|
bool v6AddressesEqual(struct in6_addr *, struct in6_addr *);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue