summaryrefslogtreecommitdiff
path: root/jni/iodine/src
diff options
context:
space:
mode:
Diffstat (limited to 'jni/iodine/src')
-rw-r--r--jni/iodine/src/Android.mk22
-rw-r--r--jni/iodine/src/Makefile5
-rw-r--r--jni/iodine/src/android_dns.h39
-rw-r--r--jni/iodine/src/base128.c12
-rw-r--r--jni/iodine/src/base32.c21
-rw-r--r--jni/iodine/src/base32.h3
-rw-r--r--jni/iodine/src/base64.c15
-rw-r--r--jni/iodine/src/base64.h3
-rw-r--r--jni/iodine/src/client.c463
-rw-r--r--jni/iodine/src/client.h11
-rw-r--r--jni/iodine/src/common.c262
-rw-r--r--jni/iodine/src/common.h53
-rw-r--r--jni/iodine/src/dns.c86
-rw-r--r--jni/iodine/src/dns.h7
-rw-r--r--jni/iodine/src/dns_android.h625
-rw-r--r--jni/iodine/src/encoding.c22
-rw-r--r--jni/iodine/src/encoding.h3
-rw-r--r--jni/iodine/src/fw_query.c6
-rw-r--r--jni/iodine/src/fw_query.h4
-rw-r--r--jni/iodine/src/iodine.c106
-rw-r--r--jni/iodine/src/iodined.c477
-rw-r--r--jni/iodine/src/login.c14
-rw-r--r--jni/iodine/src/login.h3
-rw-r--r--jni/iodine/src/md5.h2
-rwxr-xr-xjni/iodine/src/osflags13
-rw-r--r--jni/iodine/src/read.c25
-rw-r--r--jni/iodine/src/read.h5
-rw-r--r--jni/iodine/src/tun.c285
-rw-r--r--jni/iodine/src/tun.h3
-rw-r--r--jni/iodine/src/user.c59
-rw-r--r--jni/iodine/src/user.h9
-rw-r--r--jni/iodine/src/util.c34
-rw-r--r--jni/iodine/src/util.h1
-rw-r--r--jni/iodine/src/version.h3
-rw-r--r--jni/iodine/src/windows.h8
35 files changed, 1235 insertions, 1474 deletions
diff --git a/jni/iodine/src/Android.mk b/jni/iodine/src/Android.mk
new file mode 100644
index 0000000..8f7c729
--- /dev/null
+++ b/jni/iodine/src/Android.mk
@@ -0,0 +1,22 @@
+#
+# iodine for Android
+#
+# by Marcel Bokhorst
+# http://blog.bokhorst.biz/5123/computers-en-internet/iodine-for-android/
+#
+# cd iodine-0.6.0-rc1/src
+# make base64u.h base64u.c
+# .../ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=Android.mk
+#
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := iodine
+LOCAL_SRC_FILES := tun.c dns.c read.c encoding.c login.c base32.c base64.c base64u.c base128.c md5.c common.c iodine.c client.c util.c
+LOCAL_CFLAGS := -c -DANDROID -DLINUX -DIFCONFIGPATH=\"/system/bin/\" -Wall
+LOCAL_LDLIBS := -lz
+
+include $(BUILD_EXECUTABLE)
+
diff --git a/jni/iodine/src/Makefile b/jni/iodine/src/Makefile
index a5b9838..80bd345 100644
--- a/jni/iodine/src/Makefile
+++ b/jni/iodine/src/Makefile
@@ -9,7 +9,7 @@ ARCH = `uname -m`
LIBPATH = -L.
LDFLAGS += -lz `sh osflags $(TARGETOS) link` $(LIBPATH)
-CFLAGS += -c -g -Wall -D$(OS) -pedantic `sh osflags $(TARGETOS) cflags`
+CFLAGS += -std=c99 -c -g -Wall -D$(OS) -pedantic `sh osflags $(TARGETOS) cflags`
all: stateos $(CLIENT) $(SERVER)
@@ -26,7 +26,7 @@ $(SERVER): $(COMMONOBJS) $(SERVEROBJS)
@mkdir -p ../bin
@$(CC) $(COMMONOBJS) $(SERVEROBJS) -o $(SERVER) $(LDFLAGS)
-.c.o:
+.c.o:
@echo CC $<
@$(CC) $(CFLAGS) $< -o $@
@@ -43,4 +43,5 @@ base64u.h: base64.h
clean:
@echo "Cleaning src/"
@rm -f $(CLIENT){,.exe} $(SERVER){,.exe} *~ *.o *.core base64u.*
+ @rm -rf obj libs #android stuff
diff --git a/jni/iodine/src/android_dns.h b/jni/iodine/src/android_dns.h
new file mode 100644
index 0000000..dafd8ec
--- /dev/null
+++ b/jni/iodine/src/android_dns.h
@@ -0,0 +1,39 @@
+
+#ifndef __FIX_ANDROID_H__
+#define __FIX_ANDROID_H__
+
+typedef struct {
+ unsigned id :16;
+ unsigned rd :1;
+ unsigned tc :1;
+ unsigned aa :1;
+ unsigned opcode :4;
+ unsigned qr :1;
+ unsigned rcode :4;
+ unsigned cd: 1;
+ unsigned ad: 1;
+ unsigned unused :1;
+ unsigned ra :1;
+ unsigned qdcount :16;
+ unsigned ancount :16;
+ unsigned nscount :16;
+ unsigned arcount :16;
+} HEADER;
+
+#define NOERROR 0
+#define FORMERR 1
+#define SERVFAIL 2
+#define NXDOMAIN 3
+#define NOTIMP 4
+#define REFUSED 5
+
+#define C_IN 1
+
+#define T_A 1
+#define T_CNAME 5
+#define T_NULL 10
+#define T_MX 15
+#define T_TXT 16
+#define T_SRV 33
+
+#endif
diff --git a/jni/iodine/src/base128.c b/jni/iodine/src/base128.c
index 32a29f8..7ddc38c 100644
--- a/jni/iodine/src/base128.c
+++ b/jni/iodine/src/base128.c
@@ -42,7 +42,7 @@
* accent chars since they might readily be entered in normal use,
* don't use 254-255 because of possible function overloading in DNS systems.
*/
-static const unsigned char cb128[] =
+static const unsigned char cb128[] =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
"\274\275\276\277"
"\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"
@@ -75,19 +75,19 @@ struct encoder
return &base128_encoder;
}
-static int
+static int
base128_handles_dots()
{
return 0;
}
-static int
+static int
base128_blksize_raw()
{
return BLKSIZE_RAW;
}
-static int
+static int
base128_blksize_enc()
{
return BLKSIZE_ENC;
@@ -109,7 +109,7 @@ base128_reverse_init()
}
}
-static int
+static int
base128_encode(char *buf, size_t *buflen, const void *data, size_t size)
/*
* Fills *buf with max. *buflen characters, encoding size bytes of *data.
@@ -231,7 +231,7 @@ base128_decode(void *buf, size_t *buflen, const char *str, size_t slen)
if (iout >= *buflen || iin + 1 >= slen ||
str[iin] == '\0' || str[iin + 1] == '\0')
break;
- ubuf[iout] = ((REV128(ustr[iin]) & 0x7f) << 1) |
+ ubuf[iout] = ((REV128(ustr[iin]) & 0x7f) << 1) |
((REV128(ustr[iin + 1]) & 0x40) >> 6);
iin++; /* 0 used up, iin=1 */
iout++;
diff --git a/jni/iodine/src/base32.c b/jni/iodine/src/base32.c
index 8731a92..d971ce2 100644
--- a/jni/iodine/src/base32.c
+++ b/jni/iodine/src/base32.c
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
+ * Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
+ * 2006-2009 Bjorn Andersson <flex@kryo.se>
* Mostly rewritten 2009 J.A.Bezemer@opensourcepartners.nl
*
* Permission to use, copy, modify, and distribute this software for any
@@ -25,9 +26,9 @@
#define BLKSIZE_RAW 5
#define BLKSIZE_ENC 8
-static const char cb32[] =
+static const char cb32[] =
"abcdefghijklmnopqrstuvwxyz012345";
-static const char cb32_ucase[] =
+static const char cb32_ucase[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ012345";
static unsigned char rev32[256];
static int reverse_init = 0;
@@ -55,19 +56,19 @@ struct encoder
return &base32_encoder;
}
-static int
+static int
base32_handles_dots()
{
return 0;
}
-static int
+static int
base32_blksize_raw()
{
return BLKSIZE_RAW;
}
-static int
+static int
base32_blksize_enc()
{
return BLKSIZE_ENC;
@@ -104,7 +105,7 @@ b32_8to5(int in)
return rev32[in];
}
-static int
+static int
base32_encode(char *buf, size_t *buflen, const void *data, size_t size)
/*
* Fills *buf with max. *buflen characters, encoding size bytes of *data.
@@ -222,7 +223,7 @@ base32_decode(void *buf, size_t *buflen, const char *str, size_t slen)
if (iout >= *buflen || iin + 1 >= slen ||
str[iin] == '\0' || str[iin + 1] == '\0')
break;
- ubuf[iout] = ((REV32(str[iin]) & 0x1f) << 3) |
+ ubuf[iout] = ((REV32(str[iin]) & 0x1f) << 3) |
((REV32(str[iin + 1]) & 0x1c) >> 2);
iin++; /* 0 used up, iin=1 */
iout++;
@@ -231,8 +232,8 @@ base32_decode(void *buf, size_t *buflen, const char *str, size_t slen)
str[iin] == '\0' || str[iin + 1] == '\0' ||
str[iin + 2] == '\0')
break;
- ubuf[iout] = ((REV32(str[iin]) & 0x03) << 6) |
- ((REV32(str[iin + 1]) & 0x1f) << 1) |
+ ubuf[iout] = ((REV32(str[iin]) & 0x03) << 6) |
+ ((REV32(str[iin + 1]) & 0x1f) << 1) |
((REV32(str[iin + 2]) & 0x10) >> 4);
iin += 2; /* 1,2 used up, iin=3 */
iout++;
diff --git a/jni/iodine/src/base32.h b/jni/iodine/src/base32.h
index 497ca33..53975c5 100644
--- a/jni/iodine/src/base32.h
+++ b/jni/iodine/src/base32.h
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
+ * Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
+ * 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
diff --git a/jni/iodine/src/base64.c b/jni/iodine/src/base64.c
index 5218c09..00a84fc 100644
--- a/jni/iodine/src/base64.c
+++ b/jni/iodine/src/base64.c
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
+ * Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
+ * 2006-2009 Bjorn Andersson <flex@kryo.se>
* Mostly rewritten 2009 J.A.Bezemer@opensourcepartners.nl
*
* Permission to use, copy, modify, and distribute this software for any
@@ -27,7 +28,7 @@
/* Note: the "unofficial" char is last here, which means that the \377 pattern
in DOWNCODECCHECK1 ('Y' request) will properly test it. */
-static const char cb64[] =
+static const char cb64[] =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789+";
static unsigned char rev64[256];
static int reverse_init = 0;
@@ -55,19 +56,19 @@ struct encoder
return &base64_encoder;
}
-static int
+static int
base64_handles_dots()
{
return 0;
}
-static int
+static int
base64_blksize_raw()
{
return BLKSIZE_RAW;
}
-static int
+static int
base64_blksize_enc()
{
return BLKSIZE_ENC;
@@ -177,7 +178,7 @@ base64_decode(void *buf, size_t *buflen, const char *str, size_t slen)
if (iout >= *buflen || iin + 1 >= slen ||
str[iin] == '\0' || str[iin + 1] == '\0')
break;
- ubuf[iout] = ((REV64(str[iin]) & 0x3f) << 2) |
+ ubuf[iout] = ((REV64(str[iin]) & 0x3f) << 2) |
((REV64(str[iin + 1]) & 0x30) >> 4);
iin++; /* 0 used up, iin=1 */
iout++;
@@ -185,7 +186,7 @@ base64_decode(void *buf, size_t *buflen, const char *str, size_t slen)
if (iout >= *buflen || iin + 1 >= slen ||
str[iin] == '\0' || str[iin + 1] == '\0')
break;
- ubuf[iout] = ((REV64(str[iin]) & 0x0f) << 4) |
+ ubuf[iout] = ((REV64(str[iin]) & 0x0f) << 4) |
((REV64(str[iin + 1]) & 0x3c) >> 2);
iin++; /* 1 used up, iin=2 */
iout++;
diff --git a/jni/iodine/src/base64.h b/jni/iodine/src/base64.h
index d550cf3..662175e 100644
--- a/jni/iodine/src/base64.h
+++ b/jni/iodine/src/base64.h
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
+ * Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
+ * 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
diff --git a/jni/iodine/src/client.c b/jni/iodine/src/client.c
index 552344b..979f668 100644
--- a/jni/iodine/src/client.c
+++ b/jni/iodine/src/client.c
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
+ * Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
+ * 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -19,6 +20,7 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+#include <strings.h>
#include <signal.h>
#include <unistd.h>
#include <sys/param.h>
@@ -31,6 +33,9 @@
#include "windows.h"
#include <winsock2.h>
#else
+#ifdef ANDROID
+#include "android_dns.h"
+#endif
#include <arpa/nameser.h>
#ifdef DARWIN
#define BIND_8_COMPAT
@@ -58,7 +63,8 @@ static void handshake_lazyoff(int dns_fd);
static int running;
static const char *password;
-static struct sockaddr_in nameserv;
+static struct sockaddr_storage nameserv;
+static int nameserv_len;
static struct sockaddr_in raw_serv;
static const char *topdomain;
@@ -89,10 +95,10 @@ static struct encoder *b128;
/* The encoder used for data packets
* Defaults to Base32, can be changed after handshake */
static struct encoder *dataenc;
-
+
/* The encoder to use for downstream data */
static char downenc = ' ';
-
+
/* set query type to send */
static unsigned short do_qtype = T_UNSET;
@@ -146,49 +152,10 @@ client_get_conn()
}
void
-client_set_nameserver(const char *cp, int port)
+client_set_nameserver(struct sockaddr_storage *addr, int addrlen)
{
- struct in_addr addr;
-
- if (inet_aton(cp, &addr) != 1) {
- /* try resolving if a domain is given */
- struct hostent *host;
- const char *err;
- host = gethostbyname(cp);
- if (host != NULL && h_errno > 0) {
- int i = 0;
- while (host->h_addr_list[i] != 0) {
- addr = *(struct in_addr *) host->h_addr_list[i++];
- fprintf(stderr, "Resolved %s to %s\n", cp, inet_ntoa(addr));
- goto setaddr;
- }
- }
-#ifndef WINDOWS32
- err = hstrerror(h_errno);
-#else
- {
- DWORD wserr = WSAGetLastError();
- switch (wserr) {
- case WSAHOST_NOT_FOUND:
- err = "Host not found";
- break;
- case WSANO_DATA:
- err = "No data record found";
- break;
- default:
- err = "Unknown error";
- break;
- }
- }
-#endif /* !WINDOWS32 */
- errx(1, "error resolving nameserver '%s': %s", cp, err);
- }
-
-setaddr:
- memset(&nameserv, 0, sizeof(nameserv));
- nameserv.sin_family = AF_INET;
- nameserv.sin_port = htons(port);
- nameserv.sin_addr = addr;
+ memcpy(&nameserv, addr, addrlen);
+ nameserv_len = addrlen;
}
void
@@ -203,11 +170,13 @@ client_set_password(const char *cp)
password = cp;
}
-void
-set_qtype(char *qtype)
+int
+client_set_qtype(char *qtype)
{
if (!strcasecmp(qtype, "NULL"))
do_qtype = T_NULL;
+ else if (!strcasecmp(qtype, "PRIVATE"))
+ do_qtype = T_PRIVATE;
else if (!strcasecmp(qtype, "CNAME"))
do_qtype = T_CNAME;
else if (!strcasecmp(qtype, "A"))
@@ -218,14 +187,16 @@ set_qtype(char *qtype)
do_qtype = T_SRV;
else if (!strcasecmp(qtype, "TXT"))
do_qtype = T_TXT;
+ return (do_qtype == T_UNSET);
}
char *
-get_qtype()
+client_get_qtype()
{
char *c = "UNDEFINED";
if (do_qtype == T_NULL) c = "NULL";
+ else if (do_qtype == T_PRIVATE) c = "PRIVATE";
else if (do_qtype == T_CNAME) c = "CNAME";
else if (do_qtype == T_A) c = "A";
else if (do_qtype == T_MX) c = "MX";
@@ -236,7 +207,7 @@ get_qtype()
}
void
-set_downenc(char *encoding)
+client_set_downenc(char *encoding)
{
if (!strcasecmp(encoding, "base32"))
downenc = 'T';
@@ -250,7 +221,7 @@ set_downenc(char *encoding)
downenc = 'R';
}
-void
+void
client_set_selecttimeout(int select_timeout)
{
selecttimeout = select_timeout;
@@ -302,7 +273,7 @@ send_query(int fd, char *hostname)
fprintf(stderr, " Sendquery: id %5d name[0] '%c'\n", q.id, hostname[0]);
#endif
- sendto(fd, packet, len, 0, (struct sockaddr*)&nameserv, sizeof(nameserv));
+ sendto(fd, packet, len, 0, (struct sockaddr*)&nameserv, nameserv_len);
/* There are DNS relays that time out quickly but don't send anything
back on timeout.
@@ -369,7 +340,7 @@ send_packet(int fd, char cmd, const char *data, const size_t datalen)
char buf[4096];
buf[0] = cmd;
-
+
build_hostname(buf + 1, sizeof(buf) - 1, data, datalen, topdomain,
b32, hostname_maxlen);
send_query(fd, buf);
@@ -402,7 +373,7 @@ send_chunk(int fd)
/* Build upstream data header (see doc/proto_xxxxxxxx.txt) */
buf[0] = userid_char; /* First byte is hex userid */
-
+
code = ((outpkt.seqno & 7) << 2) | ((outpkt.fragment & 15) >> 2);
buf[1] = b32_5to8(code); /* Second byte is 3 bits seqno, 2 upper bits fragment count */
@@ -416,7 +387,7 @@ send_chunk(int fd)
datacmc++;
if (datacmc >= 36)
datacmc = 0;
-
+
#if 0
fprintf(stderr, " Send: down %d/%d up %d/%d, %d bytes\n",
inpkt.seqno, inpkt.fragment, outpkt.seqno, outpkt.fragment,
@@ -431,12 +402,12 @@ send_ping(int fd)
{
if (conn == CONN_DNS_NULL) {
char data[4];
-
+
data[0] = userid;
data[1] = ((inpkt.seqno & 7) << 4) | (inpkt.fragment & 15);
data[2] = (rand_seed >> 8) & 0xff;
data[3] = (rand_seed >> 0) & 0xff;
-
+
rand_seed++;
#if 0
@@ -596,13 +567,13 @@ read_dns_withq(int dns_fd, int tun_fd, char *buf, int buflen, struct query *q)
Returns >0 on correct replies; value is #valid bytes in *buf.
*/
{
- struct sockaddr_in from;
+ struct sockaddr_storage from;
char data[64*1024];
socklen_t addrlen;
int r;
- addrlen = sizeof(struct sockaddr);
- if ((r = recvfrom(dns_fd, data, sizeof(data), 0,
+ addrlen = sizeof(from);
+ if ((r = recvfrom(dns_fd, data, sizeof(data), 0,
(struct sockaddr*)&from, &addrlen)) < 0) {
warn("recvfrom");
return -1;
@@ -624,9 +595,9 @@ read_dns_withq(int dns_fd, int tun_fd, char *buf, int buflen, struct query *q)
/*
* buf is a hostname or txt stream that we still need to
* decode to binary
- *
+ *
* also update rv with the number of valid bytes
- *
+ *
* data is unused here, and will certainly hold the smaller binary
*/
@@ -1180,11 +1151,11 @@ client_tunnel_cb(int tun_fd, int dns_fd, int
warnx("No downstream data received in 60 seconds, shutting down.");
running = 0;
}
-
+
if (running == 0)
break;
- if (i < 0)
+ if (i < 0)
err(1, "select");
if (i == 0) {
@@ -1227,7 +1198,7 @@ client_tunnel_cb(int tun_fd, int dns_fd, int
if (FD_ISSET(dns_fd, &fds)) {
if (tunnel_dns(tun_fd, dns_fd) <= 0)
continue;
- }
+ }
}
}
@@ -1245,7 +1216,7 @@ send_login(int fd, char *login, int len)
data[17] = (rand_seed >> 8) & 0xff;
data[18] = (rand_seed >> 0) & 0xff;
-
+
rand_seed++;
send_packet(fd, 'l', data, sizeof(data));
@@ -1284,23 +1255,23 @@ static void
send_set_downstream_fragsize(int fd, int fragsize)
{
char data[5];
-
+
data[0] = userid;
data[1] = (fragsize & 0xff00) >> 8;
data[2] = (fragsize & 0x00ff);
data[3] = (rand_seed >> 8) & 0xff;
data[4] = (rand_seed >> 0) & 0xff;
-
+
rand_seed++;
send_packet(fd, 'n', data, sizeof(data));
}
-static void
+static void
send_version(int fd, uint32_t version)
{
char data[6];
-
+
data[0] = (version >> 24) & 0xff;
data[1] = (version >> 16) & 0xff;
data[2] = (version >> 8) & 0xff;
@@ -1308,7 +1279,7 @@ send_version(int fd, uint32_t version)
data[4] = (rand_seed >> 8) & 0xff;
data[5] = (rand_seed >> 0) & 0xff;
-
+
rand_seed++;
send_packet(fd, 'v', data, sizeof(data));
@@ -1319,7 +1290,7 @@ send_ip_request(int fd, int userid)
{
char buf[512] = "i____.";
buf[1] = b32_5to8(userid);
-
+
buf[2] = b32_5to8((rand_seed >> 10) & 0x1f);
buf[3] = b32_5to8((rand_seed >> 5) & 0x1f);
buf[4] = b32_5to8((rand_seed ) & 0x1f);
@@ -1343,7 +1314,7 @@ send_upenctest(int fd, char *s)
/* NOTE: String may be at most 63-4=59 chars to fit in 1 dns chunk. */
{
char buf[512] = "z___";
-
+
buf[1] = b32_5to8((rand_seed >> 10) & 0x1f);
buf[2] = b32_5to8((rand_seed >> 5) & 0x1f);
buf[3] = b32_5to8((rand_seed ) & 0x1f);
@@ -1379,7 +1350,7 @@ send_codec_switch(int fd, int userid, int bits)
char buf[512] = "s_____.";
buf[1] = b32_5to8(userid);
buf[2] = b32_5to8(bits);
-
+
buf[3] = b32_5to8((rand_seed >> 10) & 0x1f);
buf[4] = b32_5to8((rand_seed >> 5) & 0x1f);
buf[5] = b32_5to8((rand_seed ) & 0x1f);
@@ -1442,33 +1413,31 @@ handshake_version(int dns_fd, int *seed)
read = handshake_waitdns(dns_fd, in, sizeof(in), 'v', 'V', i+1);
- /*XXX START adjust indent 1 tab back*/
- if (read >= 9) {
- payload = (((in[4] & 0xff) << 24) |
- ((in[5] & 0xff) << 16) |
- ((in[6] & 0xff) << 8) |
- ((in[7] & 0xff)));
-
- if (strncmp("VACK", in, 4) == 0) {
- *seed = payload;
- userid = in[8];
- userid_char = hex[userid & 15];
- userid_char2 = hex2[userid & 15];
+ if (read >= 9) {
+ payload = (((in[4] & 0xff) << 24) |
+ ((in[5] & 0xff) << 16) |
+ ((in[6] & 0xff) << 8) |
+ ((in[7] & 0xff)));
+
+ if (strncmp("VACK", in, 4) == 0) {
+ *seed = payload;
+ userid = in[8];
+ userid_char = hex[userid & 15];
+ userid_char2 = hex2[userid & 15];
+
+ fprintf(stderr, "Version ok, both using protocol v 0x%08x. You are user #%d\n", VERSION, userid);
+ return 0;
+ } else if (strncmp("VNAK", in, 4) == 0) {
+ warnx("You use protocol v 0x%08x, server uses v 0x%08x. Giving up",
+ VERSION, payload);
+ return 1;
+ } else if (strncmp("VFUL", in, 4) == 0) {
+ warnx("Server full, all %d slots are taken. Try again later", payload);
+ return 1;
+ }
+ } else if (read > 0)
+ warnx("did not receive proper login challenge");
- fprintf(stderr, "Version ok, both using protocol v 0x%08x. You are user #%d\n", VERSION, userid);
- return 0;
- } else if (strncmp("VNAK", in, 4) == 0) {
- warnx("You use protocol v 0x%08x, server uses v 0x%08x. Giving up",
- VERSION, payload);
- return 1;
- } else if (strncmp("VFUL", in, 4) == 0) {
- warnx("Server full, all %d slots are taken. Try again later", payload);
- return 1;
- }
- } else if (read > 0)
- warnx("did not receive proper login challenge");
- /*XXX END adjust indent 1 tab back*/
-
fprintf(stderr, "Retrying version check...\n");
}
warnx("couldn't connect to server (maybe other -T options will work)");
@@ -1487,37 +1456,35 @@ handshake_login(int dns_fd, int seed)
int read;
login_calculate(login, 16, password, seed);
-
+
for (i=0; running && i<5 ;i++) {
send_login(dns_fd, login, 16);
read = handshake_waitdns(dns_fd, in, sizeof(in), 'l', 'L', i+1);
- /*XXX START adjust indent 1 tab back*/
- if (read > 0) {
- int netmask;
- if (strncmp("LNAK", in, 4) == 0) {
- fprintf(stderr, "Bad password\n");
- return 1;
- } else if (sscanf(in, "%64[^-]-%64[^-]-%d-%d",
- server, client, &mtu, &netmask) == 4) {
-
- server[64] = 0;
- client[64] = 0;
- if (tun_setip(client, server, netmask) == 0 &&
- tun_setmtu(mtu) == 0) {
-
- fprintf(stderr, "Server tunnel IP is %s\n", server);
- return 0;
- } else {
- errx(4, "Failed to set IP and MTU");
- }
+ if (read > 0) {
+ int netmask;
+ if (strncmp("LNAK", in, 4) == 0) {
+ fprintf(stderr, "Bad password\n");
+ return 1;
+ } else if (sscanf(in, "%64[^-]-%64[^-]-%d-%d",
+ server, client, &mtu, &netmask) == 4) {
+
+ server[64] = 0;
+ client[64] = 0;
+ if (tun_setip(client, server, netmask) == 0 &&
+ tun_setmtu(mtu) == 0) {
+
+ fprintf(stderr, "Server tunnel IP is %s\n", server);
+ return 0;
} else {
- fprintf(stderr, "Received bad handshake\n");
+ errx(4, "Failed to set IP and MTU");
}
+ } else {
+ fprintf(stderr, "Received bad handshake\n");
}
- /*XXX END adjust indent 1 tab back*/
+ }
fprintf(stderr, "Retrying login...\n");
}
@@ -1544,20 +1511,18 @@ handshake_raw_udp(int dns_fd, int seed)
len = handshake_waitdns(dns_fd, in, sizeof(in), 'i', 'I', i+1);
- /*XXX START adjust indent 1 tab back*/
- if (len == 5 && in[0] == 'I') {
- /* Received IP address */
- remoteaddr = (in[1] & 0xff);
- remoteaddr <<= 8;
- remoteaddr |= (in[2] & 0xff);
- remoteaddr <<= 8;
- remoteaddr |= (in[3] & 0xff);
- remoteaddr <<= 8;
- remoteaddr |= (in[4] & 0xff);
- server.s_addr = ntohl(remoteaddr);
- break;
- }
- /*XXX END adjust indent 1 tab back*/
+ if (len == 5 && in[0] == 'I') {
+ /* Received IP address */
+ remoteaddr = (in[1] & 0xff);
+ remoteaddr <<= 8;
+ remoteaddr |= (in[2] & 0xff);
+ remoteaddr <<= 8;
+ remoteaddr |= (in[3] & 0xff);
+ remoteaddr <<= 8;
+ remoteaddr |= (in[4] & 0xff);
+ server.s_addr = ntohl(remoteaddr);
+ break;
+ }
fprintf(stderr, ".");
fflush(stderr);
@@ -1565,7 +1530,7 @@ handshake_raw_udp(int dns_fd, int seed)
fprintf(stderr, "\n");
if (!running)
return 0;
-
+
if (!remoteaddr) {
fprintf(stderr, "Failed to get raw server IP, will use DNS mode.\n");
return 0;
@@ -1579,7 +1544,7 @@ handshake_raw_udp(int dns_fd, int seed)
raw_serv.sin_port = htons(53);
raw_serv.sin_addr = server;
- /* do login against port 53 on remote server
+ /* do login against port 53 on remote server
* based on the old seed. If reply received,
* switch to raw udp mode */
for (i=0; running && i<4 ;i++) {
@@ -1587,7 +1552,7 @@ handshake_raw_udp(int dns_fd, int seed)
tv.tv_usec = 0;
send_raw_udp_login(dns_fd, userid, seed);
-
+
FD_ZERO(&fds);
FD_SET(dns_fd, &fds);
@@ -1600,7 +1565,7 @@ handshake_raw_udp(int dns_fd, int seed)
char hash[16];
login_calculate(hash, 16, password, seed - 1);
if (memcmp(in, raw_header, RAW_HDR_IDENT_LEN) == 0
- && RAW_HDR_GET_CMD(in) == RAW_HDR_CMD_LOGIN
+ && RAW_HDR_GET_CMD(in) == RAW_HDR_CMD_LOGIN
&& memcmp(&in[RAW_HDR_LEN], hash, sizeof(hash)) == 0) {
fprintf(stderr, "OK\n");
@@ -1611,7 +1576,7 @@ handshake_raw_udp(int dns_fd, int seed)
fprintf(stderr, ".");
fflush(stderr);
}
-
+
fprintf(stderr, "failed\n");
return 0;
}
@@ -1840,7 +1805,7 @@ handshake_downenc_autodetect(int dns_fd)
int base64uok = 0;
int base128ok = 0;
- if (do_qtype == T_NULL) {
+ if (do_qtype == T_NULL || do_qtype == T_PRIVATE) {
/* no other choice than raw */
fprintf(stderr, "No alternative downstream codec available, using default (Raw)\n");
return ' ';
@@ -1894,13 +1859,14 @@ handshake_qtypetest(int dns_fd, int timeout)
int trycodec;
int k;
- if (do_qtype == T_NULL)
+ if (do_qtype == T_NULL || do_qtype == T_PRIVATE)
trycodec = 'R';
else
trycodec = 'T';
/* We could use 'Z' bouncing here, but 'Y' also tests that 0-255
- byte values can be returned, which is needed for NULL to work. */
+ byte values can be returned, which is needed for NULL/PRIVATE
+ to work. */
send_downenctest(dns_fd, trycodec, 1, NULL, 0);
@@ -1925,11 +1891,12 @@ handshake_qtype_numcvt(int num)
{
switch (num) {
case 0: return T_NULL;
- case 1: return T_TXT;
- case 2: return T_SRV;
- case 3: return T_MX;
- case 4: return T_CNAME;
- case 5: return T_A;
+ case 1: return T_PRIVATE;
+ case 2: return T_TXT;
+ case 3: return T_SRV;
+ case 4: return T_MX;
+ case 5: return T_CNAME;
+ case 6: return T_A;
}
return T_UNSET;
}
@@ -1972,7 +1939,7 @@ handshake_qtype_autodetect(int dns_fd)
highestworking = qtypenum;
#if 0
fprintf(stderr, " Type %s timeout %d works\n",
- get_qtype(), timeout);
+ client_get_qtype(), timeout);
#endif
break;
/* try others with longer timeout */
@@ -2079,27 +2046,25 @@ handshake_switch_codec(int dns_fd, int bits)
for (i=0; running && i<5 ;i++) {
send_codec_switch(dns_fd, userid, bits);
-
+
read = handshake_waitdns(dns_fd, in, sizeof(in), 's', 'S', i+1);
- /*XXX START adjust indent 1 tab back*/
- if (read > 0) {
- if (strncmp("BADLEN", in, 6) == 0) {
- fprintf(stderr, "Server got bad message length. ");
- goto codec_revert;
- } else if (strncmp("BADIP", in, 5) == 0) {
- fprintf(stderr, "Server rejected sender IP address. ");
- goto codec_revert;
- } else if (strncmp("BADCODEC", in, 8) == 0) {
- fprintf(stderr, "Server rejected the selected codec. ");
- goto codec_revert;
- }
- in[read] = 0; /* zero terminate */
- fprintf(stderr, "Server switched upstream to codec %s\n", in);
- dataenc = tempenc;
- return;
+ if (read > 0) {
+ if (strncmp("BADLEN", in, 6) == 0) {
+ fprintf(stderr, "Server got bad message length. ");
+ goto codec_revert;
+ } else if (strncmp("BADIP", in, 5) == 0) {
+ fprintf(stderr, "Server rejected sender IP address. ");
+ goto codec_revert;
+ } else if (strncmp("BADCODEC", in, 8) == 0) {
+ fprintf(stderr, "Server rejected the selected codec. ");
+ goto codec_revert;
}
- /*XXX END adjust indent 1 tab back*/
+ in[read] = 0; /* zero terminate */
+ fprintf(stderr, "Server switched upstream to codec %s\n", in);
+ dataenc = tempenc;
+ return;
+ }
fprintf(stderr, "Retrying codec switch...\n");
}
@@ -2108,7 +2073,7 @@ handshake_switch_codec(int dns_fd, int bits)
fprintf(stderr, "No reply from server on codec switch. ");
-codec_revert:
+codec_revert:
fprintf(stderr, "Falling back to upstream codec %s\n", dataenc->name);
}
@@ -2137,23 +2102,21 @@ handshake_switch_downenc(int dns_fd)
read = handshake_waitdns(dns_fd, in, sizeof(in), 'o', 'O', i+1);
- /*XXX START adjust indent 1 tab back*/
- if (read > 0) {
- if (strncmp("BADLEN", in, 6) == 0) {
- fprintf(stderr, "Server got bad message length. ");
- goto codec_revert;
- } else if (strncmp("BADIP", in, 5) == 0) {
- fprintf(stderr, "Server rejected sender IP address. ");
- goto codec_revert;
- } else if (strncmp("BADCODEC", in, 8) == 0) {
- fprintf(stderr, "Server rejected the selected codec. ");
- goto codec_revert;
- }
- in[read] = 0; /* zero terminate */
- fprintf(stderr, "Server switched downstream to codec %s\n", in);
- return;
+ if (read > 0) {
+ if (strncmp("BADLEN", in, 6) == 0) {
+ fprintf(stderr, "Server got bad message length. ");
+ goto codec_revert;
+ } else if (strncmp("BADIP", in, 5) == 0) {
+ fprintf(stderr, "Server rejected sender IP address. ");
+ goto codec_revert;
+ } else if (strncmp("BADCODEC", in, 8) == 0) {
+ fprintf(stderr, "Server rejected the selected codec. ");
+ goto codec_revert;
}
- /*XXX END adjust indent 1 tab back*/
+ in[read] = 0; /* zero terminate */
+ fprintf(stderr, "Server switched downstream to codec %s\n", in);
+ return;
+ }
fprintf(stderr, "Retrying codec switch...\n");
}
@@ -2162,7 +2125,7 @@ handshake_switch_downenc(int dns_fd)
fprintf(stderr, "No reply from server on codec switch. ");
-codec_revert:
+codec_revert:
fprintf(stderr, "Falling back to downstream codec Base32\n");
}
@@ -2180,24 +2143,22 @@ handshake_try_lazy(int dns_fd)
read = handshake_waitdns(dns_fd, in, sizeof(in), 'o', 'O', i+1);
- /*XXX START adjust indent 1 tab back*/
- if (read > 0) {
- if (strncmp("BADLEN", in, 6) == 0) {
- fprintf(stderr, "Server got bad message length. ");
- goto codec_revert;
- } else if (strncmp("BADIP", in, 5) == 0) {
- fprintf(stderr, "Server rejected sender IP address. ");
- goto codec_revert;
- } else if (strncmp("BADCODEC", in, 8) == 0) {
- fprintf(stderr, "Server rejected lazy mode. ");
- goto codec_revert;
- } else if (strncmp("Lazy", in, 4) == 0) {
- fprintf(stderr, "Server switched to lazy mode\n");
- lazymode = 1;
- return;
- }
+ if (read > 0) {
+ if (strncmp("BADLEN", in, 6) == 0) {
+ fprintf(stderr, "Server got bad message length. ");
+ goto codec_revert;
+ } else if (strncmp("BADIP", in, 5) == 0) {
+ fprintf(stderr, "Server rejected sender IP address. ");
+ goto codec_revert;
+ } else if (strncmp("BADCODEC", in, 8) == 0) {
+ fprintf(stderr, "Server rejected lazy mode. ");
+ goto codec_revert;
+ } else if (strncmp("Lazy", in, 4) == 0) {
+ fprintf(stderr, "Server switched to lazy mode\n");
+ lazymode = 1;
+ return;
}
- /*XXX END adjust indent 1 tab back*/
+ }
fprintf(stderr, "Retrying lazy mode switch...\n");
}
@@ -2206,7 +2167,7 @@ handshake_try_lazy(int dns_fd)
fprintf(stderr, "No reply from server on lazy switch. ");
-codec_revert:
+codec_revert:
fprintf(stderr, "Falling back to legacy mode\n");
lazymode = 0;
selecttimeout = 1;
@@ -2226,14 +2187,12 @@ handshake_lazyoff(int dns_fd)
read = handshake_waitdns(dns_fd, in, sizeof(in), 'o', 'O', 1);
- /*XXX START adjust indent 2 tabs back*/
- if (read == 9 && strncmp("Immediate", in, 9) == 0) {
- warnx("Server switched back to legacy mode.\n");
- lazymode = 0;
- selecttimeout = 1;
- return;
- }
- /*XXX END adjust indent 2 tabs back*/
+ if (read == 9 && strncmp("Immediate", in, 9) == 0) {
+ warnx("Server switched back to legacy mode.\n");
+ lazymode = 0;
+ selecttimeout = 1;
+ return;
+ }
}
if (!running)
return;
@@ -2288,28 +2247,26 @@ fragsize_check(char *in, int read, int proposed_fragsize, int *max_fragsize)
okay = 1;
v = in[3] & 0xff;
- /*XXX START adjust indent 1 tab back*/
- for (i = 3; i < read; i++, v = (v + 107) & 0xff)
- if ((in[i] & 0xff) != v) {
- okay = 0;
- break;
- }
+ for (i = 3; i < read; i++, v = (v + 107) & 0xff)
+ if ((in[i] & 0xff) != v) {
+ okay = 0;
+ break;
+ }
- if (okay) {
- fprintf(stderr, "%d ok.. ", acked_fragsize);
- fflush(stderr);
- *max_fragsize = acked_fragsize;
- return 1;
+ if (okay) {
+ fprintf(stderr, "%d ok.. ", acked_fragsize);
+ fflush(stderr);
+ *max_fragsize = acked_fragsize;
+ return 1;
+ } else {
+ if (downenc != ' ' && downenc != 'T') {
+ fprintf(stderr, "%d corrupted at %d.. (Try -O Base32)\n", acked_fragsize, i);
} else {
- if (downenc != ' ' && downenc != 'T') {
- fprintf(stderr, "%d corrupted at %d.. (Try -O Base32)\n", acked_fragsize, i);
- } else {
- fprintf(stderr, "%d corrupted at %d.. ", acked_fragsize, i);
- }
- fflush(stderr);
- return 1;
+ fprintf(stderr, "%d corrupted at %d.. ", acked_fragsize, i);
}
- /*XXX END adjust indent 1 tab back*/
+ fflush(stderr);
+ return 1;
+ }
/* notreached */
return 1;
@@ -2327,7 +2284,7 @@ handshake_autoprobe_fragsize(int dns_fd)
int max_fragsize;
max_fragsize = 0;
- fprintf(stderr, "Autoprobing max downstream fragment size... (skip with -m fragsize)\n");
+ fprintf(stderr, "Autoprobing max downstream fragment size... (skip with -m fragsize)\n");
while (running && range > 0 && (range >= 8 || max_fragsize < 300)) {
/* stop the slow probing early when we have enough bytes anyway */
for (i=0; running && i<3 ;i++) {
@@ -2335,14 +2292,12 @@ handshake_autoprobe_fragsize(int dns_fd)
send_fragsize_probe(dns_fd, proposed_fragsize);
read = handshake_waitdns(dns_fd, in, sizeof(in), 'r', 'R', 1);
-
- /*XXX START adjust indent 1 tab back*/
- if (read > 0) {
- /* We got a reply */
- if (fragsize_check(in, read, proposed_fragsize, &max_fragsize) == 1)
- break;
- }
- /*XXX END adjust indent 1 tab back*/
+
+ if (read > 0) {
+ /* We got a reply */
+ if (fragsize_check(in, read, proposed_fragsize, &max_fragsize) == 1)
+ break;
+ }
fprintf(stderr, ".");
fflush(stderr);
@@ -2383,7 +2338,7 @@ handshake_autoprobe_fragsize(int dns_fd)
fprintf(stderr, "Note: this probably won't work well.\n");
fprintf(stderr, "Try setting -M to 200 or lower, or try other DNS types (-T option).\n");
} else if (max_fragsize < 202 &&
- (do_qtype == T_NULL || do_qtype == T_TXT ||
+ (do_qtype == T_NULL || do_qtype == T_PRIVATE || do_qtype == T_TXT ||
do_qtype == T_SRV || do_qtype == T_MX)) {
fprintf(stderr, "Note: this isn't very much.\n");
fprintf(stderr, "Try setting -M to 200 or lower, or try other DNS types (-T option).\n");
@@ -2406,22 +2361,20 @@ handshake_set_fragsize(int dns_fd, int fragsize)
read = handshake_waitdns(dns_fd, in, sizeof(in), 'n', 'N', i+1);
- /*XXX START adjust indent 1 tab back*/
- if (read > 0) {
- int accepted_fragsize;
-
- if (strncmp("BADFRAG", in, 7) == 0) {
- fprintf(stderr, "Server rejected fragsize. Keeping default.");
- return;
- } else if (strncmp("BADIP", in, 5) == 0) {
- fprintf(stderr, "Server rejected sender IP address.\n");
- return;
- }
+ if (read > 0) {
- accepted_fragsize = ((in[0] & 0xff) << 8) | (in[1] & 0xff);
+ if (strncmp("BADFRAG", in, 7) == 0) {
+ fprintf(stderr, "Server rejected fragsize. Keeping default.");
+ return;
+ } else if (strncmp("BADIP", in, 5) == 0) {
+ fprintf(stderr, "Server rejected sender IP address.\n");
return;
}
- /*XXX END adjust indent 1 tab back*/
+
+ /* The server returns the accepted fragsize:
+ accepted_fragsize = ((in[0] & 0xff) << 8) | (in[1] & 0xff) */
+ return;
+ }
fprintf(stderr, "Retrying set fragsize...\n");
}
@@ -2448,7 +2401,7 @@ client_handshake(int dns_fd, int raw_mode, int autodetect_frag_size, int fragsiz
}
}
- fprintf(stderr, "Using DNS type %s queries\n", get_qtype());
+ fprintf(stderr, "Using DNS type %s queries\n", client_get_qtype());
r = handshake_version(dns_fd, &seed);
if (r) {
diff --git a/jni/iodine/src/client.h b/jni/iodine/src/client.h
index e2d9501..79598fb 100644
--- a/jni/iodine/src/client.h
+++ b/jni/iodine/src/client.h
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
+ * Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
+ * 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -23,12 +24,12 @@ void client_stop();
enum connection client_get_conn();
const char *client_get_raw_addr();
-void client_set_nameserver(const char *cp, int port);
+void client_set_nameserver(struct sockaddr_storage *, int);
void client_set_topdomain(const char *cp);
void client_set_password(const char *cp);
-void set_qtype(char *qtype);
-char *get_qtype();
-void set_downenc(char *encoding);
+int client_set_qtype(char *qtype);
+char *client_get_qtype();
+void client_set_downenc(char *encoding);
void client_set_selecttimeout(int select_timeout);
void client_set_lazymode(int lazy_mode);
void client_set_hostname_maxlen(int i);
diff --git a/jni/iodine/src/common.c b/jni/iodine/src/common.c
index 7a57a8a..6707a14 100644
--- a/jni/iodine/src/common.c
+++ b/jni/iodine/src/common.c
@@ -1,4 +1,5 @@
-/* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
+/* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
+ * 2006-2009 Bjorn Andersson <flex@kryo.se>
* Copyright (c) 2007 Albert Lee <trisk@acm.jhu.edu>.
*
* Permission to use, copy, modify, and distribute this software for any
@@ -39,9 +40,11 @@
#endif
#include <termios.h>
#include <err.h>
-#include <arpa/inet.h>
#include <netinet/in.h>
+#include <arpa/inet.h>
#include <syslog.h>
+#include <sys/socket.h>
+#include <netdb.h>
#endif
#ifdef HAVE_SETCON
@@ -54,11 +57,11 @@
const unsigned char raw_header[RAW_HDR_LEN] = { 0x10, 0xd1, 0x9e, 0x00 };
/* daemon(3) exists only in 4.4BSD or later, and in GNU libc */
-#if !defined(WINDOWS32) && !(defined(BSD) && (BSD >= 199306)) && !defined(__GLIBC__) && !defined(__ANDROID__)
+#if !defined(ANDROID) && !defined(WINDOWS32) && !(defined(BSD) && (BSD >= 199306)) && !defined(__GLIBC__)
static int daemon(int nochdir, int noclose)
{
int fd, i;
-
+
switch (fork()) {
case 0:
break;
@@ -67,15 +70,15 @@ static int daemon(int nochdir, int noclose)
default:
_exit(0);
}
-
+
if (!nochdir) {
chdir("/");
}
-
+
if (setsid() < 0) {
return -1;
}
-
+
if (!noclose) {
if ((fd = open("/dev/null", O_RDWR)) >= 0) {
for (i = 0; i < 3; i++) {
@@ -111,21 +114,69 @@ check_superuser(void (*usage_fn)(void))
#endif
}
-int
-open_dns(int localport, in_addr_t listen_ip)
+char *
+format_addr(struct sockaddr_storage *sockaddr, int sockaddr_len)
+{
+ static char dst[INET6_ADDRSTRLEN + 1];
+
+ memset(dst, 0, sizeof(dst));
+ if (sockaddr->ss_family == AF_INET && sockaddr_len >= sizeof(struct sockaddr_in)) {
+ getnameinfo((struct sockaddr *)sockaddr, sockaddr_len, dst, sizeof(dst) - 1, NULL, 0, NI_NUMERICHOST);
+ } else if (sockaddr->ss_family == AF_INET6 && sockaddr_len >= sizeof(struct sockaddr_in6)) {
+ struct sockaddr_in6 *addr = (struct sockaddr_in6 *) sockaddr;
+ if (IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr)) {
+ struct in_addr ia;
+ /* Get mapped v4 addr from last 32bit field */
+ memcpy(&ia.s_addr, &addr->sin6_addr.s6_addr[12], sizeof(ia));
+ strcpy(dst, inet_ntoa(ia));
+ } else {
+ getnameinfo((struct sockaddr *)sockaddr, sockaddr_len, dst, sizeof(dst) - 1, NULL, 0, NI_NUMERICHOST);
+ }
+ } else {
+ dst[0] = '?';
+ }
+ return dst;
+}
+
+int
+get_addr(char *host, int port, int addr_family, int flags, struct sockaddr_storage *out)
+{
+ struct addrinfo hints, *addr;
+ int res;
+ char portnum[8];
+
+ memset(portnum, 0, sizeof(portnum));
+ snprintf(portnum, sizeof(portnum) - 1, "%d", port);
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = addr_family;
+#if defined(WINDOWS32) || defined(OPENBSD)
+ /* AI_ADDRCONFIG misbehaves on windows, and does not exist in OpenBSD */
+ hints.ai_flags = flags;
+#else
+ hints.ai_flags = AI_ADDRCONFIG | flags;
+#endif
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = IPPROTO_UDP;
+
+ res = getaddrinfo(host, portnum, &hints, &addr);
+ if (res == 0) {
+ int addrlen = addr->ai_addrlen;
+ /* Grab first result */
+ memcpy(out, addr->ai_addr, addr->ai_addrlen);
+ freeaddrinfo(addr);
+ return addrlen;
+ }
+ return res;
+}
+
+int
+open_dns(struct sockaddr_storage *sockaddr, size_t sockaddr_len)
{
- struct sockaddr_in addr;
int flag = 1;
int fd;
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_port = htons(localport);
- /* listen_ip already in network byte order from inet_addr, or 0 */
- addr.sin_addr.s_addr = listen_ip;
-
- if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
- fprintf(stderr, "got fd %d\n", fd);
+ if ((fd = socket(sockaddr->ss_family, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
err(1, "socket");
}
@@ -138,6 +189,8 @@ open_dns(int localport, in_addr_t listen_ip)
#ifndef WINDOWS32
/* To get destination address from each UDP datagram, see iodined.c:read_dns() */
setsockopt(fd, IPPROTO_IP, DSTADDR_SOCKOPT, (const void*) &flag, sizeof(flag));
+
+ fd_set_close_on_exec(fd);
#endif
#ifdef IP_OPT_DONT_FRAG
@@ -146,14 +199,27 @@ open_dns(int localport, in_addr_t listen_ip)
setsockopt(fd, IPPROTO_IP, IP_OPT_DONT_FRAG, (const void*) &flag, sizeof(flag));
#endif
- if(bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0)
+ if(bind(fd, (struct sockaddr*) sockaddr, sockaddr_len) < 0)
err(1, "bind");
- fprintf(stderr, "Opened UDP socket\n");
+ fprintf(stderr, "Opened IPv%d UDP socket\n", sockaddr->ss_family == AF_INET6 ? 6 : 4);
return fd;
}
+int
+open_dns_from_host(char *host, int port, int addr_family, int flags)
+{
+ struct sockaddr_storage addr;
+ int addrlen;
+
+ addrlen = get_addr(host, port, addr_family, flags, &addr);
+ if (addrlen < 0)
+ return addrlen;
+
+ return open_dns(&addr, addrlen);
+}
+
void
close_dns(int fd)
{
@@ -167,8 +233,9 @@ do_chroot(char *newroot)
if (chroot(newroot) != 0 || chdir("/") != 0)
err(1, "%s", newroot);
- seteuid(geteuid());
- setuid(getuid());
+ if (seteuid(geteuid()) != 0 || setuid(getuid()) != 0) {
+ err(1, "set[e]uid()");
+ }
#else
warnx("chroot not available");
#endif
@@ -219,14 +286,14 @@ do_detach()
void
read_password(char *buf, size_t len)
{
- char pwd[80];
+ char pwd[80] = {0};
#ifndef WINDOWS32
struct termios old;
struct termios tp;
tcgetattr(0, &tp);
old = tp;
-
+
tp.c_lflag &= (~ECHO);
tcsetattr(0, TCSANOW, &tp);
#else
@@ -236,7 +303,7 @@ read_password(char *buf, size_t len)
fprintf(stderr, "Enter password: ");
fflush(stderr);
#ifndef WINDOWS32
- scanf("%79s", pwd);
+ fscanf(stdin, "%79[^\n]", pwd);
#else
for (i = 0; i < sizeof(pwd); i++) {
pwd[i] = getch();
@@ -252,7 +319,7 @@ read_password(char *buf, size_t len)
fprintf(stderr, "\n");
#ifndef WINDOWS32
- tcsetattr(0, TCSANOW, &old);
+ tcsetattr(0, TCSANOW, &old);
#endif
strncpy(buf, pwd, len);
@@ -260,29 +327,75 @@ read_password(char *buf, size_t len)
}
int
-check_topdomain(char *str)
+check_topdomain(char *str, char **errormsg)
{
- int i;
-
- if(str[0] == '.') /* special case */
- return 1;
-
- for( i = 0; i < strlen(str); i++) {
- if( isalpha(str[i]) || isdigit(str[i]) || str[i] == '-' || str[i] == '.' )
- continue;
- else
- return 1;
- }
- return 0;
+ int i;
+ int dots = 0;
+ int chunklen = 0;
+
+ if (strlen(str) < 3) {
+ if (errormsg) *errormsg = "Too short (< 3)";
+ return 1;
+ }
+ if (strlen(str) > 128) {
+ if (errormsg) *errormsg = "Too long (> 128)";
+ return 1;
+ }
+
+ if (str[0] == '.') {
+ if (errormsg) *errormsg = "Starts with a dot";
+ return 1;
+ }
+
+ for( i = 0; i < strlen(str); i++) {
+ if(str[i] == '.') {
+ dots++;
+ if (chunklen == 0) {
+ if (errormsg) *errormsg = "Consecutive dots";
+ return 1;
+ }
+ if (chunklen > 63) {
+ if (errormsg) *errormsg = "Too long domain part (> 63)";
+ return 1;
+ }
+ chunklen = 0;
+ } else {
+ chunklen++;
+ }
+ if( (str[i] >= 'a' && str[i] <= 'z') || (str[i] >= 'A' && str[i] <= 'Z') ||
+ isdigit(str[i]) || str[i] == '-' || str[i] == '.' ) {
+ continue;
+ } else {
+ if (errormsg) *errormsg = "Contains illegal character (allowed: [a-zA-Z0-9-.])";
+ return 1;
+ }
+ }
+
+ if (dots == 0) {
+ if (errormsg) *errormsg = "No dots";
+ return 1;
+ }
+ if (chunklen == 0) {
+ if (errormsg) *errormsg = "Ends with a dot";
+ return 1;
+ }
+ if (chunklen > 63) {
+ if (errormsg) *errormsg = "Too long domain part (> 63)";
+ return 1;
+ }
+
+ return 0;
}
-#if defined(WINDOWS32)
+#if defined(WINDOWS32) || defined(ANDROID)
+#ifndef ANDROID
int
inet_aton(const char *cp, struct in_addr *inp)
{
inp->s_addr = inet_addr(cp);
return inp->s_addr != INADDR_ANY;
}
+#endif
void
warn(const char *fmt, ...)
@@ -291,45 +404,16 @@ warn(const char *fmt, ...)
va_start(list, fmt);
if (fmt) fprintf(stderr, fmt, list);
+#ifndef ANDROID
if (errno == 0) {
- fprintf(stderr, ": WSA error %d\n", WSAGetLastError());
+ fprintf(stderr, ": WSA error %d\n", WSAGetLastError());
} else {
fprintf(stderr, ": %s\n", strerror(errno));
}
- va_end(list);
-}
#endif
-
-#ifdef __ANDROID__
-
-void android_printf(const char *fmt, ...)
-{
- static char buf[1024];
- va_list list;
- va_start(list, fmt);
-
- snprintf(buf,1024,fmt,list);
-
- android_log_callback(buf);
-
va_end(list);
}
-
-void
-warn(const char *fmt, ...)
-{
- va_list list;
-
- va_start(list, fmt);
- if (fmt) fprintf(stderr, fmt, list);
- if (errno != 0)
- fprintf(stderr, ": %s\n", strerror(errno));
- va_end(list);
-}
-#endif
-
-#if defined(WINDOWS32) || defined(__ANDROID__)
void
warnx(const char *fmt, ...)
{
@@ -364,6 +448,23 @@ errx(int eval, const char *fmt, ...)
}
#endif
+#if defined(__ANDROID__)
+void android_log_callback(const char *);
+static char printf_buf[1024];;
+void android_printf(const char *fmt, ...)
+{
+ va_list list;
+ va_start(list, fmt);
+
+ vsnprintf(printf_buf,1024,fmt,list);
+ android_log_callback(printf_buf);
+
+ __android_log_vprint(ANDROID_LOG_INFO, "Iodine",
+ fmt, list);
+ va_end(list);
+}
+#endif
+
int recent_seqno(int ourseqno, int gotseqno)
/* Return 1 if we've seen gotseqno recently (current or up to 3 back).
@@ -379,3 +480,22 @@ int recent_seqno(int ourseqno, int gotseqno)
}
return 0;
}
+
+#ifndef WINDOWS32
+/* Set FD_CLOEXEC flag on file descriptor.
+ * This stops it from being inherited by system() calls.
+ */
+void
+fd_set_close_on_exec(int fd)
+{
+ int flags;
+
+ flags = fcntl(fd, F_GETFD);
+ if (flags == -1)
+ err(4, "Failed to get fd flags");
+ flags |= FD_CLOEXEC;
+ if (fcntl(fd, F_SETFD, flags) == -1)
+ err(4, "Failed to set fd flags");
+}
+#endif
+
diff --git a/jni/iodine/src/common.h b/jni/iodine/src/common.h
index 0b0efb8..26800f6 100644
--- a/jni/iodine/src/common.h
+++ b/jni/iodine/src/common.h
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
+ * Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
+ * 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -37,8 +38,8 @@ extern const unsigned char raw_header[RAW_HDR_LEN];
#include <sys/types.h>
#include <sys/socket.h>
#include <err.h>
-#include <arpa/inet.h>
#include <netinet/in.h>
+#include <arpa/inet.h>
#endif
#define DNS_PORT 53
@@ -52,12 +53,12 @@ extern const unsigned char raw_header[RAW_HDR_LEN];
#define QUERY_NAME_SIZE 256
-#if defined IP_RECVDSTADDR
-# define DSTADDR_SOCKOPT IP_RECVDSTADDR
-# define dstaddr(x) ((struct in_addr *) CMSG_DATA(x))
-#elif defined IP_PKTINFO
-# define DSTADDR_SOCKOPT IP_PKTINFO
-# define dstaddr(x) (&(((struct in_pktinfo *)(CMSG_DATA(x)))->ipi_addr))
+#if defined IP_RECVDSTADDR
+# define DSTADDR_SOCKOPT IP_RECVDSTADDR
+# define dstaddr(x) ((struct in_addr *) CMSG_DATA(x))
+#elif defined IP_PKTINFO
+# define DSTADDR_SOCKOPT IP_PKTINFO
+# define dstaddr(x) (&(((struct in_pktinfo *)(CMSG_DATA(x)))->ipi_addr))
#endif
#if defined IP_MTU_DISCOVER
@@ -74,10 +75,12 @@ extern const unsigned char raw_header[RAW_HDR_LEN];
# define DONT_FRAG_VALUE 1
#endif
+#define T_PRIVATE 65399
+/* Undefined RR type; "private use" range, see http://www.bind9.net/dns-parameters */
#define T_UNSET 65432
-/* Unused RR type; "private use" range, see http://www.bind9.net/dns-parameters */
+/* Unused RR type, never actually sent */
-struct packet
+struct packet
{
int len; /* Total packet length */
int sentlen; /* Length of chunk currently transmitted */
@@ -93,7 +96,7 @@ struct query {
unsigned short rcode;
unsigned short id;
struct in_addr destination;
- struct sockaddr from;
+ struct sockaddr_storage from;
int fromlen;
unsigned short id2;
struct sockaddr from2;
@@ -107,7 +110,10 @@ enum connection {
};
void check_superuser(void (*usage_fn)(void));
-int open_dns(int, in_addr_t);
+char *format_addr(struct sockaddr_storage *sockaddr, int sockaddr_len);
+int get_addr(char *, int, int, int, struct sockaddr_storage *);
+int open_dns(struct sockaddr_storage *, size_t);
+int open_dns_from_host(char *host, int port, int addr_family, int flags);
void close_dns(int);
void do_chroot(char *);
@@ -117,24 +123,21 @@ void do_pidfile(char *);
void read_password(char*, size_t);
-int check_topdomain(char *);
+int check_topdomain(char *, char **);
#ifdef __ANDROID__
-//#define printf(...) __android_log_print(ANDROID_LOG_DEBUG, "iodine", __VA_ARGS__)
+#include <android/log.h>
+
#define printf(...) android_printf(__VA_ARGS__)
+#define fprintf(egal,...) android_printf(__VA_ARGS__)
void android_printf(const char *fmt, ...);
+#endif
-
-#define fprintf(__fd_unused, ...) printf(__VA_ARGS__)
-
-#include <android/log.h>
-void err(int eval, const char *fmt, ...);
-void warn(const char *fmt, ...);
-void errx(int eval, const char *fmt, ...);
-void warnx(const char *fmt, ...);
-#elif WINDOWS32
+#if defined(WINDOWS32) || defined(ANDROID)
+#ifndef ANDROID
int inet_aton(const char *cp, struct in_addr *inp);
+#endif
void err(int eval, const char *fmt, ...);
void warn(const char *fmt, ...);
@@ -144,4 +147,8 @@ void warnx(const char *fmt, ...);
int recent_seqno(int , int);
+#ifndef WINDOWS32
+void fd_set_close_on_exec(int fd);
+#endif
+
#endif
diff --git a/jni/iodine/src/dns.c b/jni/iodine/src/dns.c
index fb2bcaf..946fe83 100644
--- a/jni/iodine/src/dns.c
+++ b/jni/iodine/src/dns.c
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
+ * Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
+ * 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -20,16 +21,21 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
+#include <strings.h>
#include <ctype.h>
#ifdef WINDOWS32
#include "windows.h"
#else
+#if defined(ANDROID) || defined(__ANDROID__)
+#include "android_dns.h"
+#endif
#include <arpa/nameser.h>
#ifdef DARWIN
#define BIND_8_COMPAT
#include <arpa/nameser_compat.h>
#endif
+#include <netinet/in.h>
#include <arpa/inet.h>
#include <err.h>
#endif
@@ -41,7 +47,7 @@
int dnsc_use_edns0 = 1;
-#define CHECKLEN(x) if (buflen - (p-buf) < (x)) return 0
+#define CHECKLEN(x) if (buflen < (x) + (unsigned)(p-buf)) return 0
int
dns_encode(char *buf, size_t buflen, struct query *q, qr_t qr, char *data, size_t datalen)
@@ -56,9 +62,9 @@ dns_encode(char *buf, size_t buflen, struct query *q, qr_t qr, char *data, size_
return 0;
memset(buf, 0, buflen);
-
+
header = (HEADER*)buf;
-
+
header->id = htons(q->id);
header->qr = (qr == QR_ANSWER);
header->opcode = 0;
@@ -72,7 +78,7 @@ dns_encode(char *buf, size_t buflen, struct query *q, qr_t qr, char *data, size_
switch (qr) {
case QR_ANSWER:
header->qdcount = htons(1);
-
+
name = 0xc000 | ((p - buf) & 0x3fff);
/* Question section */
@@ -91,7 +97,7 @@ dns_encode(char *buf, size_t buflen, struct query *q, qr_t qr, char *data, size_
int namelen;
CHECKLEN(10);
- putshort(&p, name);
+ putshort(&p, name);
if (q->type == T_A)
/* answer CNAME to A question */
putshort(&p, T_CNAME);
@@ -121,7 +127,7 @@ dns_encode(char *buf, size_t buflen, struct query *q, qr_t qr, char *data, size_
ancnt = 1;
while (1) {
CHECKLEN(10);
- putshort(&p, name);
+ putshort(&p, name);
putshort(&p, q->type);
putshort(&p, C_IN);
putlong(&p, 0); /* TTL */
@@ -156,7 +162,7 @@ dns_encode(char *buf, size_t buflen, struct query *q, qr_t qr, char *data, size_
int txtlen;
CHECKLEN(10);
- putshort(&p, name);
+ putshort(&p, name);
putshort(&p, q->type);
putshort(&p, C_IN);
putlong(&p, 0); /* TTL */
@@ -173,7 +179,7 @@ dns_encode(char *buf, size_t buflen, struct query *q, qr_t qr, char *data, size_
/* NULL has raw binary data */
CHECKLEN(10);
- putshort(&p, name);
+ putshort(&p, name);
putshort(&p, q->type);
putshort(&p, C_IN);
putlong(&p, 0); /* TTL */
@@ -192,7 +198,7 @@ dns_encode(char *buf, size_t buflen, struct query *q, qr_t qr, char *data, size_
/* Note that iodined also uses this for forward queries */
header->qdcount = htons(1);
-
+
datalen = MIN(datalen, buflen - (p - buf));
putname(&p, datalen, data);
@@ -204,20 +210,18 @@ dns_encode(char *buf, size_t buflen, struct query *q, qr_t qr, char *data, size_
(even CNAME/A/MX, 255+255+header would be >512) */
if (dnsc_use_edns0) {
header->arcount = htons(1);
- /*XXX START adjust indent 1 tab forward*/
- CHECKLEN(11);
- putbyte(&p, 0x00); /* Root */
- putshort(&p, 0x0029); /* OPT */
- putshort(&p, 0x1000); /* Payload size: 4096 */
- putshort(&p, 0x0000); /* Higher bits/edns version */
- putshort(&p, 0x8000); /* Z */
- putshort(&p, 0x0000); /* Data length */
- /*XXX END adjust indent 1 tab forward*/
+ CHECKLEN(11);
+ putbyte(&p, 0x00); /* Root */
+ putshort(&p, 0x0029); /* OPT */
+ putshort(&p, 0x1000); /* Payload size: 4096 */
+ putshort(&p, 0x0000); /* Higher bits/edns version */
+ putshort(&p, 0x8000); /* Z */
+ putshort(&p, 0x0000); /* Data length */
}
break;
}
-
+
len = p - buf;
return len;
@@ -241,9 +245,9 @@ dns_encode_ns_response(char *buf, size_t buflen, struct query *q, char *topdomai
return 0;
memset(buf, 0, buflen);
-
+
header = (HEADER*)buf;
-
+
header->id = htons(q->id);
header->qr = 1;
header->opcode = 0;
@@ -330,9 +334,9 @@ dns_encode_a_response(char *buf, size_t buflen, struct query *q)
return 0;
memset(buf, 0, buflen);
-
+
header = (HEADER*)buf;
-
+
header->id = htons(q->id);
header->qr = 1;
header->opcode = 0;
@@ -389,7 +393,7 @@ dns_get_id(char *packet, size_t packetlen)
return ntohs(header->id);
}
-#define CHECKLEN(x) if (packetlen - (data-packet) < (x)) return 0
+#define CHECKLEN(x) if (packetlen < (x) + (unsigned)(data-packet)) return 0
int
dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, size_t packetlen)
@@ -400,11 +404,11 @@ dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, siz
short qdcount;
short ancount;
uint32_t ttl;
- short class;
- short type;
+ unsigned short class;
+ unsigned short type;
char *data;
- short rlen;
- int id;
+ unsigned short rlen;
+ int id;
int rv;
q->id2 = 0;
@@ -412,9 +416,9 @@ dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, siz
header = (HEADER*)packet;
/* Reject short packets */
- if (packetlen < sizeof(HEADER))
+ if (packetlen < sizeof(HEADER))
return 0;
-
+
if (header->qr != qr) {
warnx("header->qr does not match the requested qr");
return -1;
@@ -423,13 +427,13 @@ dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, siz
data = packet + sizeof(HEADER);
qdcount = ntohs(header->qdcount);
ancount = ntohs(header->ancount);
-
+
id = ntohs(header->id);
id = id & 0xFFFF; /* Kill any sign extension */
-
+
rlen = 0;
- if (q != NULL)
+ if (q != NULL)
q->rcode = header->rcode;
switch (qr) {
@@ -439,7 +443,7 @@ dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, siz
return -1;
}
- if (q != NULL)
+ if (q != NULL)
q->id = id;
/* Read name even if no answer, to give better error message */
@@ -447,14 +451,14 @@ dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, siz
CHECKLEN(4);
readshort(packet, &data, &type);
readshort(packet, &data, &class);
-
+
/* if CHECKLEN okay, then we're sure to have a proper name */
if (q != NULL) {
/* We only need the first char to check it */
q->name[0] = name[0];
q->name[1] = '\0';
- }
-
+ }
+
if (ancount < 1) {
/* DNS errors like NXDOMAIN have ancount=0 and
stop here. CNAME may also have A; MX/SRV may have
@@ -463,7 +467,7 @@ dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, siz
}
/* Here type is still the question type */
- if (type == T_NULL) {
+ if (type == T_NULL || type == T_PRIVATE) {
/* Assume that first answer is what we wanted */
readname(packet, packetlen, &data, name, sizeof(name));
CHECKLEN(10);
@@ -505,7 +509,7 @@ dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, siz
*/
char names[250][QUERY_NAME_SIZE];
char *rdatastart;
- short pref;
+ unsigned short pref;
int i;
int offset;
@@ -535,7 +539,7 @@ dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, siz
names[pref / 10 - 1][QUERY_NAME_SIZE-1] = '\0';
}
- /* always trust rlen, not name encoding */
+ /* always trust rlen, not name encoding */
data = rdatastart + rlen;
CHECKLEN(0);
}
diff --git a/jni/iodine/src/dns.h b/jni/iodine/src/dns.h
index be8b940..7c1faff 100644
--- a/jni/iodine/src/dns.h
+++ b/jni/iodine/src/dns.h
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
+ * Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
+ * 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -32,8 +33,4 @@ int dns_encode_a_response(char *buf, size_t buflen, struct query *q);
unsigned short dns_get_id(char *packet, size_t packetlen);
int dns_decode(char *, size_t, struct query *, qr_t, char *, size_t);
-#ifdef __ANDROID__
-#include "dns_android.h"
-#endif
-
#endif /* _DNS_H_ */
diff --git a/jni/iodine/src/dns_android.h b/jni/iodine/src/dns_android.h
deleted file mode 100644
index f8addf7..0000000
--- a/jni/iodine/src/dns_android.h
+++ /dev/null
@@ -1,625 +0,0 @@
-/* This file is modified to serve minimal requirements of iodine */
-
-
-/*
- * Copyright (c) 1983, 1989, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
- * Copyright (c) 1996-1999 by Internet Software Consortium.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
- * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
- * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES 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.
- */
-
-/*
- * $BINDId: nameser.h,v 8.37 2000/03/30 21:16:49 vixie Exp $
- */
-
-#ifndef _ARPA_NAMESER_H_
-#define _ARPA_NAMESER_H_
-
-/*%
- * Revision information. This is the release date in YYYYMMDD format.
- * It can change every day so the right thing to do with it is use it
- * in preprocessor commands such as "#if (__NAMESER > 19931104)". Do not
- * compare for equality; rather, use it to determine whether your libbind.a
- * contains a new enough lib/nameser/ to support the feature you need.
- */
-
-#define __NAMESER 19991006 /*%< New interface version stamp. */
-/*
- * Define constants based on RFC 883, RFC 1034, RFC 1035
- */
-#define NS_PACKETSZ 512 /*%< default UDP packet size */
-#define NS_MAXDNAME 1025 /*%< maximum domain name */
-#define NS_MAXMSG 65535 /*%< maximum message size */
-#define NS_MAXCDNAME 255 /*%< maximum compressed domain name */
-#define NS_MAXLABEL 63 /*%< maximum length of domain label */
-#define NS_HFIXEDSZ 12 /*%< #/bytes of fixed data in header */
-#define NS_QFIXEDSZ 4 /*%< #/bytes of fixed data in query */
-#define NS_RRFIXEDSZ 10 /*%< #/bytes of fixed data in r record */
-#define NS_INT32SZ 4 /*%< #/bytes of data in a u_int32_t */
-#define NS_INT16SZ 2 /*%< #/bytes of data in a u_int16_t */
-#define NS_INT8SZ 1 /*%< #/bytes of data in a u_int8_t */
-#define NS_INADDRSZ 4 /*%< IPv4 T_A */
-#define NS_IN6ADDRSZ 16 /*%< IPv6 T_AAAA */
-#define NS_CMPRSFLGS 0xc0 /*%< Flag bits indicating name compression. */
-#define NS_DEFAULTPORT 53 /*%< For both TCP and UDP. */
-/*
- * These can be expanded with synonyms, just keep ns_parse.c:ns_parserecord()
- * in synch with it.
- */
-typedef enum __ns_sect {
- ns_s_qd = 0, /*%< Query: Question. */
- ns_s_zn = 0, /*%< Update: Zone. */
- ns_s_an = 1, /*%< Query: Answer. */
- ns_s_pr = 1, /*%< Update: Prerequisites. */
- ns_s_ns = 2, /*%< Query: Name servers. */
- ns_s_ud = 2, /*%< Update: Update. */
- ns_s_ar = 3, /*%< Query|Update: Additional records. */
- ns_s_max = 4
-} ns_sect;
-
-/*%
- * This is a message handle. It is caller allocated and has no dynamic data.
- * This structure is intended to be opaque to all but ns_parse.c, thus the
- * leading _'s on the member names. Use the accessor functions, not the _'s.
- */
-typedef struct __ns_msg {
- const u_char *_msg, *_eom;
- u_int16_t _id, _flags, _counts[ns_s_max];
- const u_char *_sections[ns_s_max];
- ns_sect _sect;
- int _rrnum;
- const u_char *_msg_ptr;
-} ns_msg;
-
-/* Private data structure - do not use from outside library. */
-struct _ns_flagdata { int mask, shift; };
-extern const struct _ns_flagdata _ns_flagdata[];
-
-/* Accessor macros - this is part of the public interface. */
-
-#define ns_msg_id(handle) ((handle)._id + 0)
-#define ns_msg_base(handle) ((handle)._msg + 0)
-#define ns_msg_end(handle) ((handle)._eom + 0)
-#define ns_msg_size(handle) ((handle)._eom - (handle)._msg)
-#define ns_msg_count(handle, section) ((handle)._counts[section] + 0)
-
-/*%
- * This is a parsed record. It is caller allocated and has no dynamic data.
- */
-typedef struct __ns_rr {
- char name[NS_MAXDNAME];
- u_int16_t type;
- u_int16_t rr_class;
- u_int32_t ttl;
- u_int16_t rdlength;
- const u_char * rdata;
-} ns_rr;
-
-/* Accessor macros - this is part of the public interface. */
-#define ns_rr_name(rr) (((rr).name[0] != '\0') ? (rr).name : ".")
-#define ns_rr_type(rr) ((ns_type)((rr).type + 0))
-#define ns_rr_class(rr) ((ns_class)((rr).rr_class + 0))
-#define ns_rr_ttl(rr) ((rr).ttl + 0)
-#define ns_rr_rdlen(rr) ((rr).rdlength + 0)
-#define ns_rr_rdata(rr) ((rr).rdata + 0)
-
-/*%
- * These don't have to be in the same order as in the packet flags word,
- * and they can even overlap in some cases, but they will need to be kept
- * in synch with ns_parse.c:ns_flagdata[].
- */
-typedef enum __ns_flag {
- ns_f_qr, /*%< Question/Response. */
- ns_f_opcode, /*%< Operation code. */
- ns_f_aa, /*%< Authoritative Answer. */
- ns_f_tc, /*%< Truncation occurred. */
- ns_f_rd, /*%< Recursion Desired. */
- ns_f_ra, /*%< Recursion Available. */
- ns_f_z, /*%< MBZ. */
- ns_f_ad, /*%< Authentic Data (DNSSEC). */
- ns_f_cd, /*%< Checking Disabled (DNSSEC). */
- ns_f_rcode, /*%< Response code. */
- ns_f_max
-} ns_flag;
-
-/*%
- * Currently defined opcodes.
- */
-typedef enum __ns_opcode {
- ns_o_query = 0, /*%< Standard query. */
- ns_o_iquery = 1, /*%< Inverse query (deprecated/unsupported). */
- ns_o_status = 2, /*%< Name server status query (unsupported). */
- /* Opcode 3 is undefined/reserved. */
- ns_o_notify = 4, /*%< Zone change notification. */
- ns_o_update = 5, /*%< Zone update message. */
- ns_o_max = 6
-} ns_opcode;
-
-/*%
- * Currently defined response codes.
- */
-typedef enum __ns_rcode {
- ns_r_noerror = 0, /*%< No error occurred. */
- ns_r_formerr = 1, /*%< Format error. */
- ns_r_servfail = 2, /*%< Server failure. */
- ns_r_nxdomain = 3, /*%< Name error. */
- ns_r_notimpl = 4, /*%< Unimplemented. */
- ns_r_refused = 5, /*%< Operation refused. */
- /* these are for BIND_UPDATE */
- ns_r_yxdomain = 6, /*%< Name exists */
- ns_r_yxrrset = 7, /*%< RRset exists */
- ns_r_nxrrset = 8, /*%< RRset does not exist */
- ns_r_notauth = 9, /*%< Not authoritative for zone */
- ns_r_notzone = 10, /*%< Zone of record different from zone section */
- ns_r_max = 11,
- /* The following are EDNS extended rcodes */
- ns_r_badvers = 16,
- /* The following are TSIG errors */
- ns_r_badsig = 16,
- ns_r_badkey = 17,
- ns_r_badtime = 18
-} ns_rcode;
-
-/* BIND_UPDATE */
-typedef enum __ns_update_operation {
- ns_uop_delete = 0,
- ns_uop_add = 1,
- ns_uop_max = 2
-} ns_update_operation;
-
-/*%
- * This structure is used for TSIG authenticated messages
- */
-struct ns_tsig_key {
- char name[NS_MAXDNAME], alg[NS_MAXDNAME];
- unsigned char *data;
- int len;
-};
-typedef struct ns_tsig_key ns_tsig_key;
-
-/*%
- * This structure is used for TSIG authenticated TCP messages
- */
-struct ns_tcp_tsig_state {
- int counter;
- struct dst_key *key;
- void *ctx;
- unsigned char sig[NS_PACKETSZ];
- int siglen;
-};
-typedef struct ns_tcp_tsig_state ns_tcp_tsig_state;
-
-#define NS_TSIG_FUDGE 300
-#define NS_TSIG_TCP_COUNT 100
-#define NS_TSIG_ALG_HMAC_MD5 "HMAC-MD5.SIG-ALG.REG.INT"
-
-#define NS_TSIG_ERROR_NO_TSIG -10
-#define NS_TSIG_ERROR_NO_SPACE -11
-#define NS_TSIG_ERROR_FORMERR -12
-
-/*%
- * Currently defined type values for resources and queries.
- */
-typedef enum __ns_type {
- ns_t_invalid = 0, /*%< Cookie. */
- ns_t_a = 1, /*%< Host address. */
- ns_t_ns = 2, /*%< Authoritative server. */
- ns_t_md = 3, /*%< Mail destination. */
- ns_t_mf = 4, /*%< Mail forwarder. */
- ns_t_cname = 5, /*%< Canonical name. */
- ns_t_soa = 6, /*%< Start of authority zone. */
- ns_t_mb = 7, /*%< Mailbox domain name. */
- ns_t_mg = 8, /*%< Mail group member. */
- ns_t_mr = 9, /*%< Mail rename name. */
- ns_t_null = 10, /*%< Null resource record. */
- ns_t_wks = 11, /*%< Well known service. */
- ns_t_ptr = 12, /*%< Domain name pointer. */
- ns_t_hinfo = 13, /*%< Host information. */
- ns_t_minfo = 14, /*%< Mailbox information. */
- ns_t_mx = 15, /*%< Mail routing information. */
- ns_t_txt = 16, /*%< Text strings. */
- ns_t_rp = 17, /*%< Responsible person. */
- ns_t_afsdb = 18, /*%< AFS cell database. */
- ns_t_x25 = 19, /*%< X_25 calling address. */
- ns_t_isdn = 20, /*%< ISDN calling address. */
- ns_t_rt = 21, /*%< Router. */
- ns_t_nsap = 22, /*%< NSAP address. */
- ns_t_nsap_ptr = 23, /*%< Reverse NSAP lookup (deprecated). */
- ns_t_sig = 24, /*%< Security signature. */
- ns_t_key = 25, /*%< Security key. */
- ns_t_px = 26, /*%< X.400 mail mapping. */
- ns_t_gpos = 27, /*%< Geographical position (withdrawn). */
- ns_t_aaaa = 28, /*%< Ip6 Address. */
- ns_t_loc = 29, /*%< Location Information. */
- ns_t_nxt = 30, /*%< Next domain (security). */
- ns_t_eid = 31, /*%< Endpoint identifier. */
- ns_t_nimloc = 32, /*%< Nimrod Locator. */
- ns_t_srv = 33, /*%< Server Selection. */
- ns_t_atma = 34, /*%< ATM Address */
- ns_t_naptr = 35, /*%< Naming Authority PoinTeR */
- ns_t_kx = 36, /*%< Key Exchange */
- ns_t_cert = 37, /*%< Certification record */
- ns_t_a6 = 38, /*%< IPv6 address (deprecated, use ns_t_aaaa) */
- ns_t_dname = 39, /*%< Non-terminal DNAME (for IPv6) */
- ns_t_sink = 40, /*%< Kitchen sink (experimentatl) */
- ns_t_opt = 41, /*%< EDNS0 option (meta-RR) */
- ns_t_apl = 42, /*%< Address prefix list (RFC3123) */
- ns_t_tkey = 249, /*%< Transaction key */
- ns_t_tsig = 250, /*%< Transaction signature. */
- ns_t_ixfr = 251, /*%< Incremental zone transfer. */
- ns_t_axfr = 252, /*%< Transfer zone of authority. */
- ns_t_mailb = 253, /*%< Transfer mailbox records. */
- ns_t_maila = 254, /*%< Transfer mail agent records. */
- ns_t_any = 255, /*%< Wildcard match. */
- ns_t_zxfr = 256, /*%< BIND-specific, nonstandard. */
- ns_t_max = 65536
-} ns_type;
-
-/* Exclusively a QTYPE? (not also an RTYPE) */
-#define ns_t_qt_p(t) (ns_t_xfr_p(t) || (t) == ns_t_any || \
- (t) == ns_t_mailb || (t) == ns_t_maila)
-/* Some kind of meta-RR? (not a QTYPE, but also not an RTYPE) */
-#define ns_t_mrr_p(t) ((t) == ns_t_tsig || (t) == ns_t_opt)
-/* Exclusively an RTYPE? (not also a QTYPE or a meta-RR) */
-#define ns_t_rr_p(t) (!ns_t_qt_p(t) && !ns_t_mrr_p(t))
-#define ns_t_udp_p(t) ((t) != ns_t_axfr && (t) != ns_t_zxfr)
-#define ns_t_xfr_p(t) ((t) == ns_t_axfr || (t) == ns_t_ixfr || \
- (t) == ns_t_zxfr)
-
-/*%
- * Values for class field
- */
-typedef enum __ns_class {
- ns_c_invalid = 0, /*%< Cookie. */
- ns_c_in = 1, /*%< Internet. */
- ns_c_2 = 2, /*%< unallocated/unsupported. */
- ns_c_chaos = 3, /*%< MIT Chaos-net. */
- ns_c_hs = 4, /*%< MIT Hesiod. */
- /* Query class values which do not appear in resource records */
- ns_c_none = 254, /*%< for prereq. sections in update requests */
- ns_c_any = 255, /*%< Wildcard match. */
- ns_c_max = 65536
-} ns_class;
-
-/* DNSSEC constants. */
-
-typedef enum __ns_key_types {
- ns_kt_rsa = 1, /*%< key type RSA/MD5 */
- ns_kt_dh = 2, /*%< Diffie Hellman */
- ns_kt_dsa = 3, /*%< Digital Signature Standard (MANDATORY) */
- ns_kt_private = 254 /*%< Private key type starts with OID */
-} ns_key_types;
-
-typedef enum __ns_cert_types {
- cert_t_pkix = 1, /*%< PKIX (X.509v3) */
- cert_t_spki = 2, /*%< SPKI */
- cert_t_pgp = 3, /*%< PGP */
- cert_t_url = 253, /*%< URL private type */
- cert_t_oid = 254 /*%< OID private type */
-} ns_cert_types;
-
-/* Flags field of the KEY RR rdata. */
-#define NS_KEY_TYPEMASK 0xC000 /*%< Mask for "type" bits */
-#define NS_KEY_TYPE_AUTH_CONF 0x0000 /*%< Key usable for both */
-#define NS_KEY_TYPE_CONF_ONLY 0x8000 /*%< Key usable for confidentiality */
-#define NS_KEY_TYPE_AUTH_ONLY 0x4000 /*%< Key usable for authentication */
-#define NS_KEY_TYPE_NO_KEY 0xC000 /*%< No key usable for either; no key */
-/* The type bits can also be interpreted independently, as single bits: */
-#define NS_KEY_NO_AUTH 0x8000 /*%< Key unusable for authentication */
-#define NS_KEY_NO_CONF 0x4000 /*%< Key unusable for confidentiality */
-#define NS_KEY_RESERVED2 0x2000 /* Security is *mandatory* if bit=0 */
-#define NS_KEY_EXTENDED_FLAGS 0x1000 /*%< reserved - must be zero */
-#define NS_KEY_RESERVED4 0x0800 /*%< reserved - must be zero */
-#define NS_KEY_RESERVED5 0x0400 /*%< reserved - must be zero */
-#define NS_KEY_NAME_TYPE 0x0300 /*%< these bits determine the type */
-#define NS_KEY_NAME_USER 0x0000 /*%< key is assoc. with user */
-#define NS_KEY_NAME_ENTITY 0x0200 /*%< key is assoc. with entity eg host */
-#define NS_KEY_NAME_ZONE 0x0100 /*%< key is zone key */
-#define NS_KEY_NAME_RESERVED 0x0300 /*%< reserved meaning */
-#define NS_KEY_RESERVED8 0x0080 /*%< reserved - must be zero */
-#define NS_KEY_RESERVED9 0x0040 /*%< reserved - must be zero */
-#define NS_KEY_RESERVED10 0x0020 /*%< reserved - must be zero */
-#define NS_KEY_RESERVED11 0x0010 /*%< reserved - must be zero */
-#define NS_KEY_SIGNATORYMASK 0x000F /*%< key can sign RR's of same name */
-#define NS_KEY_RESERVED_BITMASK ( NS_KEY_RESERVED2 | \
- NS_KEY_RESERVED4 | \
- NS_KEY_RESERVED5 | \
- NS_KEY_RESERVED8 | \
- NS_KEY_RESERVED9 | \
- NS_KEY_RESERVED10 | \
- NS_KEY_RESERVED11 )
-#define NS_KEY_RESERVED_BITMASK2 0xFFFF /*%< no bits defined here */
-/* The Algorithm field of the KEY and SIG RR's is an integer, {1..254} */
-#define NS_ALG_MD5RSA 1 /*%< MD5 with RSA */
-#define NS_ALG_DH 2 /*%< Diffie Hellman KEY */
-#define NS_ALG_DSA 3 /*%< DSA KEY */
-#define NS_ALG_DSS NS_ALG_DSA
-#define NS_ALG_EXPIRE_ONLY 253 /*%< No alg, no security */
-#define NS_ALG_PRIVATE_OID 254 /*%< Key begins with OID giving alg */
-/* Protocol values */
-/* value 0 is reserved */
-#define NS_KEY_PROT_TLS 1
-#define NS_KEY_PROT_EMAIL 2
-#define NS_KEY_PROT_DNSSEC 3
-#define NS_KEY_PROT_IPSEC 4
-#define NS_KEY_PROT_ANY 255
-
-/* Signatures */
-#define NS_MD5RSA_MIN_BITS 512 /*%< Size of a mod or exp in bits */
-#define NS_MD5RSA_MAX_BITS 4096
- /* Total of binary mod and exp */
-#define NS_MD5RSA_MAX_BYTES ((NS_MD5RSA_MAX_BITS+7/8)*2+3)
- /* Max length of text sig block */
-#define NS_MD5RSA_MAX_BASE64 (((NS_MD5RSA_MAX_BYTES+2)/3)*4)
-#define NS_MD5RSA_MIN_SIZE ((NS_MD5RSA_MIN_BITS+7)/8)
-#define NS_MD5RSA_MAX_SIZE ((NS_MD5RSA_MAX_BITS+7)/8)
-
-#define NS_DSA_SIG_SIZE 41
-#define NS_DSA_MIN_SIZE 213
-#define NS_DSA_MAX_BYTES 405
-
-/* Offsets into SIG record rdata to find various values */
-#define NS_SIG_TYPE 0 /*%< Type flags */
-#define NS_SIG_ALG 2 /*%< Algorithm */
-#define NS_SIG_LABELS 3 /*%< How many labels in name */
-#define NS_SIG_OTTL 4 /*%< Original TTL */
-#define NS_SIG_EXPIR 8 /*%< Expiration time */
-#define NS_SIG_SIGNED 12 /*%< Signature time */
-#define NS_SIG_FOOT 16 /*%< Key footprint */
-#define NS_SIG_SIGNER 18 /*%< Domain name of who signed it */
-/* How RR types are represented as bit-flags in NXT records */
-#define NS_NXT_BITS 8
-#define NS_NXT_BIT_SET( n,p) (p[(n)/NS_NXT_BITS] |= (0x80>>((n)%NS_NXT_BITS)))
-#define NS_NXT_BIT_CLEAR(n,p) (p[(n)/NS_NXT_BITS] &= ~(0x80>>((n)%NS_NXT_BITS)))
-#define NS_NXT_BIT_ISSET(n,p) (p[(n)/NS_NXT_BITS] & (0x80>>((n)%NS_NXT_BITS)))
-#define NS_NXT_MAX 127
-
-/*%
- * EDNS0 extended flags and option codes, host order.
- */
-#define NS_OPT_DNSSEC_OK 0x8000U
-#define NS_OPT_NSID 3
-
-/*%
- * Inline versions of get/put short/long. Pointer is advanced.
- */
-#define NS_GET16(s, cp) do { \
- register const u_char *t_cp = (const u_char *)(cp); \
- (s) = ((u_int16_t)t_cp[0] << 8) \
- | ((u_int16_t)t_cp[1]) \
- ; \
- (cp) += NS_INT16SZ; \
-} while (0)
-
-#define NS_GET32(l, cp) do { \
- register const u_char *t_cp = (const u_char *)(cp); \
- (l) = ((u_int32_t)t_cp[0] << 24) \
- | ((u_int32_t)t_cp[1] << 16) \
- | ((u_int32_t)t_cp[2] << 8) \
- | ((u_int32_t)t_cp[3]) \
- ; \
- (cp) += NS_INT32SZ; \
-} while (0)
-
-#define NS_PUT16(s, cp) do { \
- register u_int16_t t_s = (u_int16_t)(s); \
- register u_char *t_cp = (u_char *)(cp); \
- *t_cp++ = t_s >> 8; \
- *t_cp = t_s; \
- (cp) += NS_INT16SZ; \
-} while (0)
-
-#define NS_PUT32(l, cp) do { \
- register u_int32_t t_l = (u_int32_t)(l); \
- register u_char *t_cp = (u_char *)(cp); \
- *t_cp++ = t_l >> 24; \
- *t_cp++ = t_l >> 16; \
- *t_cp++ = t_l >> 8; \
- *t_cp = t_l; \
- (cp) += NS_INT32SZ; \
-} while (0)
-
-#endif /* !_ARPA_NAMESER_H_ */
-/*! \file */
-
-
-
-/*%
- * from nameser.h 8.1 (Berkeley) 6/2/93
- * $BINDId: nameser_compat.h,v 8.11 1999/01/02 08:00:58 vixie Exp $
- */
-
-#ifndef _ARPA_NAMESER_COMPAT_
-#define _ARPA_NAMESER_COMPAT_
-
-#define __BIND 19950621 /*%< (DEAD) interface version stamp. */
-
-#include <endian.h>
-
-/*%
- * Structure for query header. The order of the fields is machine- and
- * compiler-dependent, depending on the byte/bit order and the layout
- * of bit fields. We use bit fields only in int variables, as this
- * is all ANSI requires. This requires a somewhat confusing rearrangement.
- */
-
-typedef struct {
- unsigned id :16; /*%< query identification number */
-#if BYTE_ORDER == BIG_ENDIAN
- /* fields in third byte */
- unsigned qr: 1; /*%< response flag */
- unsigned opcode: 4; /*%< purpose of message */
- unsigned aa: 1; /*%< authoritive answer */
- unsigned tc: 1; /*%< truncated message */
- unsigned rd: 1; /*%< recursion desired */
- /* fields in fourth byte */
- unsigned ra: 1; /*%< recursion available */
- unsigned unused :1; /*%< unused bits (MBZ as of 4.9.3a3) */
- unsigned ad: 1; /*%< authentic data from named */
- unsigned cd: 1; /*%< checking disabled by resolver */
- unsigned rcode :4; /*%< response code */
-#endif
-#if BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN
- /* fields in third byte */
- unsigned rd :1; /*%< recursion desired */
- unsigned tc :1; /*%< truncated message */
- unsigned aa :1; /*%< authoritive answer */
- unsigned opcode :4; /*%< purpose of message */
- unsigned qr :1; /*%< response flag */
- /* fields in fourth byte */
- unsigned rcode :4; /*%< response code */
- unsigned cd: 1; /*%< checking disabled by resolver */
- unsigned ad: 1; /*%< authentic data from named */
- unsigned unused :1; /*%< unused bits (MBZ as of 4.9.3a3) */
- unsigned ra :1; /*%< recursion available */
-#endif
- /* remaining bytes */
- unsigned qdcount :16; /*%< number of question entries */
- unsigned ancount :16; /*%< number of answer entries */
- unsigned nscount :16; /*%< number of authority entries */
- unsigned arcount :16; /*%< number of resource entries */
-} HEADER;
-
-#define PACKETSZ NS_PACKETSZ
-#define MAXDNAME NS_MAXDNAME
-#define MAXCDNAME NS_MAXCDNAME
-#define MAXLABEL NS_MAXLABEL
-#define HFIXEDSZ NS_HFIXEDSZ
-#define QFIXEDSZ NS_QFIXEDSZ
-#define RRFIXEDSZ NS_RRFIXEDSZ
-#define INT32SZ NS_INT32SZ
-#define INT16SZ NS_INT16SZ
-#define INT8SZ NS_INT8SZ
-#define INADDRSZ NS_INADDRSZ
-#define IN6ADDRSZ NS_IN6ADDRSZ
-#define INDIR_MASK NS_CMPRSFLGS
-#define NAMESERVER_PORT NS_DEFAULTPORT
-
-#define S_ZONE ns_s_zn
-#define S_PREREQ ns_s_pr
-#define S_UPDATE ns_s_ud
-#define S_ADDT ns_s_ar
-
-#define QUERY ns_o_query
-#define IQUERY ns_o_iquery
-#define STATUS ns_o_status
-#define NS_NOTIFY_OP ns_o_notify
-#define NS_UPDATE_OP ns_o_update
-
-#define NOERROR ns_r_noerror
-#define FORMERR ns_r_formerr
-#define SERVFAIL ns_r_servfail
-#define NXDOMAIN ns_r_nxdomain
-#define NOTIMP ns_r_notimpl
-#define REFUSED ns_r_refused
-#define YXDOMAIN ns_r_yxdomain
-#define YXRRSET ns_r_yxrrset
-#define NXRRSET ns_r_nxrrset
-#define NOTAUTH ns_r_notauth
-#define NOTZONE ns_r_notzone
-/*#define BADSIG ns_r_badsig*/
-/*#define BADKEY ns_r_badkey*/
-/*#define BADTIME ns_r_badtime*/
-
-
-#define DELETE ns_uop_delete
-#define ADD ns_uop_add
-
-#define T_A ns_t_a
-#define T_NS ns_t_ns
-#define T_MD ns_t_md
-#define T_MF ns_t_mf
-#define T_CNAME ns_t_cname
-#define T_SOA ns_t_soa
-#define T_MB ns_t_mb
-#define T_MG ns_t_mg
-#define T_MR ns_t_mr
-#define T_NULL ns_t_null
-#define T_WKS ns_t_wks
-#define T_PTR ns_t_ptr
-#define T_HINFO ns_t_hinfo
-#define T_MINFO ns_t_minfo
-#define T_MX ns_t_mx
-#define T_TXT ns_t_txt
-#define T_RP ns_t_rp
-#define T_AFSDB ns_t_afsdb
-#define T_X25 ns_t_x25
-#define T_ISDN ns_t_isdn
-#define T_RT ns_t_rt
-#define T_NSAP ns_t_nsap
-#define T_NSAP_PTR ns_t_nsap_ptr
-#define T_SIG ns_t_sig
-#define T_KEY ns_t_key
-#define T_PX ns_t_px
-#define T_GPOS ns_t_gpos
-#define T_AAAA ns_t_aaaa
-#define T_LOC ns_t_loc
-#define T_NXT ns_t_nxt
-#define T_EID ns_t_eid
-#define T_NIMLOC ns_t_nimloc
-#define T_SRV ns_t_srv
-#define T_ATMA ns_t_atma
-#define T_NAPTR ns_t_naptr
-#define T_A6 ns_t_a6
-#define T_DNAME ns_t_dname
-#define T_TSIG ns_t_tsig
-#define T_IXFR ns_t_ixfr
-#define T_AXFR ns_t_axfr
-#define T_MAILB ns_t_mailb
-#define T_MAILA ns_t_maila
-#define T_ANY ns_t_any
-
-#define C_IN ns_c_in
-#define C_CHAOS ns_c_chaos
-#define C_HS ns_c_hs
-/* BIND_UPDATE */
-#define C_NONE ns_c_none
-#define C_ANY ns_c_any
-
-#define GETSHORT NS_GET16
-#define GETLONG NS_GET32
-#define PUTSHORT NS_PUT16
-#define PUTLONG NS_PUT32
-
-#endif /* _ARPA_NAMESER_COMPAT_ */
-/*! \file */
diff --git a/jni/iodine/src/encoding.c b/jni/iodine/src/encoding.c
index 896d67d..af7620e 100644
--- a/jni/iodine/src/encoding.c
+++ b/jni/iodine/src/encoding.c
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
+ * Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
+ * 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -19,23 +20,22 @@
#include "encoding.h"
int
-build_hostname(char *buf, size_t buflen,
- const char *data, const size_t datalen,
+build_hostname(char *buf, size_t buflen,
+ const char *data, const size_t datalen,
const char *topdomain, struct encoder *encoder, int maxlen)
{
- int encsize;
size_t space;
char *b;
- space = MIN(maxlen, buflen) - strlen(topdomain) - 8;
+ space = MIN((size_t)maxlen, buflen) - strlen(topdomain) - 8;
/* 8 = 5 max header length + 1 dot before topdomain + 2 safety */
if (!encoder->places_dots())
space -= (space / 57); /* space for dots */
memset(buf, 0, buflen);
-
- encsize = encoder->encode(buf, &space, data, datalen);
+
+ encoder->encode(buf, &space, data, datalen);
if (!encoder->places_dots())
inline_dotify(buf, buflen);
@@ -45,7 +45,7 @@ build_hostname(char *buf, size_t buflen,
/* move b back one step to see if the dot is there */
b--;
- if (*b != '.')
+ if (*b != '.')
*++b = '.';
b++;
/* move b ahead of the string so we can copy to it */
@@ -63,7 +63,7 @@ unpack_data(char *buf, size_t buflen, char *data, size_t datalen, struct encoder
return enc->decode(buf, &buflen, data, datalen);
}
-int
+int
inline_dotify(char *buf, size_t buflen)
{
unsigned dots;
@@ -101,7 +101,7 @@ inline_dotify(char *buf, size_t buflen)
return total;
}
-int
+int
inline_undotify(char *buf, size_t len)
{
unsigned pos;
@@ -124,7 +124,7 @@ inline_undotify(char *buf, size_t len)
*writer++ = *reader++;
pos++;
}
-
+
/* return new length of string */
return len - dots;
}
diff --git a/jni/iodine/src/encoding.h b/jni/iodine/src/encoding.h
index 7ddf6e0..ab22279 100644
--- a/jni/iodine/src/encoding.h
+++ b/jni/iodine/src/encoding.h
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
+ * Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
+ * 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
diff --git a/jni/iodine/src/fw_query.c b/jni/iodine/src/fw_query.c
index 3727f08..4f7d8c4 100644
--- a/jni/iodine/src/fw_query.c
+++ b/jni/iodine/src/fw_query.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008 Erik Ekman <yarrick@kryo.se>
+ * Copyright (c) 2008-2014 Erik Ekman <yarrick@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -29,9 +29,9 @@ void fw_query_init()
void fw_query_put(struct fw_query *fw_query)
{
memcpy(&(fwq[fwq_ix]), fw_query, sizeof(struct fw_query));
-
+
++fwq_ix;
- if (fwq_ix >= FW_QUERY_CACHE_SIZE)
+ if (fwq_ix >= FW_QUERY_CACHE_SIZE)
fwq_ix = 0;
}
diff --git a/jni/iodine/src/fw_query.h b/jni/iodine/src/fw_query.h
index 7568a5f..f8f0de6 100644
--- a/jni/iodine/src/fw_query.h
+++ b/jni/iodine/src/fw_query.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008 Erik Ekman <yarrick@kryo.se>
+ * Copyright (c) 2008-2014 Erik Ekman <yarrick@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -28,7 +28,7 @@
#define FW_QUERY_CACHE_SIZE 16
struct fw_query {
- struct sockaddr addr;
+ struct sockaddr_storage addr;
int addrlen;
unsigned short id;
};
diff --git a/jni/iodine/src/iodine.c b/jni/iodine/src/iodine.c
index 03efb18..5c19576 100644
--- a/jni/iodine/src/iodine.c
+++ b/jni/iodine/src/iodine.c
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
+ * Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
+ * 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -32,6 +33,7 @@
#else
#include <grp.h>
#include <pwd.h>
+#include <netdb.h>
#endif
#include "common.h"
@@ -51,11 +53,17 @@ static char *__progname;
#define PASSWORD_ENV_VAR "IODINE_PASS"
static void
-sighandler(int sig)
+sighandler(int sig)
{
client_stop();
}
+#if defined(__GNUC__) || defined(__clang__)
+/* mark as no return to help some compilers to avoid warnings
+ * about use of uninitialized variables */
+static void usage() __attribute__((noreturn));
+#endif
+
static void
usage() {
extern char *__progname;
@@ -75,7 +83,7 @@ help() {
"[-P password] [-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");
+ fprintf(stderr, " -T force dns type: NULL, PRIVATE, TXT, SRV, MX, CNAME, A (default: autodetect)\n");
fprintf(stderr, " -O force downstream encoding for -T other than NULL: Base32, Base64, Base64u,\n");
fprintf(stderr, " Base128, or (only for TXT:) Raw (default: autodetect)\n");
fprintf(stderr, " -I max interval between requests (default 4 sec) to prevent DNS timeouts\n");
@@ -101,8 +109,9 @@ help() {
static void
version() {
+
fprintf(stderr, "iodine IP over DNS tunneling client\n");
- fprintf(stderr, "version: 0.6.0-rc1 from 2010-02-13\n");
+ fprintf(stderr, "version: 0.7.0 from 2014-06-16\n");
exit(0);
}
@@ -110,8 +119,9 @@ version() {
int
main(int argc, char **argv)
{
- char *nameserv_addr;
+ char *nameserv_host;
char *topdomain;
+ char *errormsg;
#ifndef WINDOWS32
struct passwd *pw;
#endif
@@ -132,9 +142,16 @@ main(int argc, char **argv)
int lazymode;
int selecttimeout;
int hostname_maxlen;
+#ifdef OPENBSD
+ int rtable = 0;
+#endif
+ struct sockaddr_storage nameservaddr;
+ int nameservaddr_len;
+ int nameserv_family;
- nameserv_addr = NULL;
+ nameserv_host = NULL;
topdomain = NULL;
+ errormsg = NULL;
#ifndef WINDOWS32
pw = NULL;
#endif
@@ -154,6 +171,7 @@ main(int argc, char **argv)
lazymode = 1;
selecttimeout = 4;
hostname_maxlen = 0xFF;
+ nameserv_family = AF_UNSPEC;
#ifdef WINDOWS32
WSAStartup(req_version, &wsa_data);
@@ -161,7 +179,7 @@ main(int argc, char **argv)
srand((unsigned) time(NULL));
client_init();
-
+
#if !defined(BSD) && !defined(__GLIBC__)
__progname = strrchr(argv[0], '/');
if (__progname == NULL)
@@ -170,8 +188,14 @@ main(int argc, char **argv)
__progname++;
#endif
- while ((choice = getopt(argc, argv, "vfhru:t:d: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:")) != -1) {
switch(choice) {
+ case '4':
+ nameserv_family = AF_INET;
+ break;
+ case '6':
+ nameserv_family = AF_INET6;
+ break;
case 'v':
version();
/* NOTREACHED */
@@ -185,6 +209,7 @@ main(int argc, char **argv)
break;
case 'r':
raw_mode = 0;
+ break;
case 'u':
username = optarg;
break;
@@ -194,12 +219,17 @@ main(int argc, char **argv)
case 'd':
device = optarg;
break;
+#ifdef OPENBSD
+ case 'R':
+ rtable = atoi(optarg);
+ break;
+#endif
case 'P':
strncpy(password, optarg, sizeof(password));
password[sizeof(password)-1] = 0;
-
+
/* XXX: find better way of cleaning up ps(1) */
- memset(optarg, 0, strlen(optarg));
+ memset(optarg, 0, strlen(optarg));
break;
case 'm':
autodetect_frag_size = 0;
@@ -217,12 +247,13 @@ main(int argc, char **argv)
break;
case 'F':
pidfile = optarg;
- break;
+ break;
case 'T':
- set_qtype(optarg);
+ if (client_set_qtype(optarg))
+ errx(5, "Invalid query type '%s'", optarg);
break;
case 'O': /* not -D, is Debug in server */
- set_downenc(optarg);
+ client_set_downenc(optarg);
break;
case 'L':
lazymode = atoi(optarg);
@@ -243,7 +274,7 @@ main(int argc, char **argv)
/* NOTREACHED */
}
}
-
+
check_superuser(usage);
argc -= optind;
@@ -251,11 +282,11 @@ main(int argc, char **argv)
switch (argc) {
case 1:
- nameserv_addr = get_resolvconf_addr();
+ nameserv_host = get_resolvconf_addr();
topdomain = strdup(argv[0]);
break;
case 2:
- nameserv_addr = argv[0];
+ nameserv_host = argv[0];
topdomain = strdup(argv[1]);
break;
default:
@@ -269,22 +300,21 @@ main(int argc, char **argv)
/* NOTREACHED */
}
- if (nameserv_addr) {
- client_set_nameserver(nameserv_addr, DNS_PORT);
+ if (nameserv_host) {
+ nameservaddr_len = get_addr(nameserv_host, DNS_PORT, nameserv_family, 0, &nameservaddr);
+ if (nameservaddr_len < 0) {
+ errx(1, "Cannot lookup nameserver '%s': %s ",
+ nameserv_host, gai_strerror(nameservaddr_len));
+ }
+ client_set_nameserver(&nameservaddr, nameservaddr_len);
} else {
warnx("No nameserver found - not connected to any network?\n");
usage();
/* NOTREACHED */
- }
+ }
- if (strlen(topdomain) <= 128) {
- if(check_topdomain(topdomain)) {
- warnx("Topdomain contains invalid characters.\n");
- usage();
- /* NOTREACHED */
- }
- } else {
- warnx("Use a topdomain max 128 chars long.\n");
+ if(check_topdomain(topdomain, &errormsg)) {
+ warnx("Invalid topdomain: %s", errormsg);
usage();
/* NOTREACHED */
}
@@ -293,7 +323,7 @@ main(int argc, char **argv)
client_set_lazymode(lazymode);
client_set_topdomain(topdomain);
client_set_hostname_maxlen(hostname_maxlen);
-
+
if (username != NULL) {
#ifndef WINDOWS32
if ((pw = getpwnam(username)) == NULL) {
@@ -303,51 +333,55 @@ main(int argc, char **argv)
}
#endif
}
-
+
if (strlen(password) == 0) {
if (NULL != getenv(PASSWORD_ENV_VAR))
snprintf(password, sizeof(password), "%s", getenv(PASSWORD_ENV_VAR));
else
read_password(password, sizeof(password));
}
-
+
client_set_password(password);
if ((tun_fd = open_tun(device)) == -1) {
retval = 1;
goto cleanup1;
}
- if ((dns_fd = open_dns(0, INADDR_ANY)) == -1) {
+ if ((dns_fd = open_dns_from_host(NULL, 0, nameservaddr.ss_family, AI_PASSIVE)) < 0) {
retval = 1;
goto cleanup2;
}
+#ifdef OPENBSD
+ if (rtable > 0)
+ socket_setrtable(dns_fd, rtable);
+#endif
signal(SIGINT, sighandler);
signal(SIGTERM, sighandler);
fprintf(stderr, "Sending DNS queries for %s to %s\n",
- topdomain, nameserv_addr);
+ topdomain, format_addr(&nameservaddr, nameservaddr_len));
if (client_handshake(dns_fd, raw_mode, autodetect_frag_size, max_downstream_frag_size)) {
retval = 1;
goto cleanup2;
}
-
+
if (client_get_conn() == CONN_RAW_UDP) {
fprintf(stderr, "Sending raw traffic directly to %s\n", client_get_raw_addr());
}
fprintf(stderr, "Connection setup complete, transmitting data.\n");
- if (foreground == 0)
+ if (foreground == 0)
do_detach();
-
+
if (pidfile != NULL)
do_pidfile(pidfile);
if (newroot != NULL)
do_chroot(newroot);
-
+
if (username != NULL) {
#ifndef WINDOWS32
gid_t gids[1];
diff --git a/jni/iodine/src/iodined.c b/jni/iodine/src/iodined.c
index 3681084..1065c33 100644
--- a/jni/iodine/src/iodined.c
+++ b/jni/iodine/src/iodined.c
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
+ * Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
+ * 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -18,6 +19,7 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+#include <strings.h>
#include <signal.h>
#include <unistd.h>
#include <sys/param.h>
@@ -59,6 +61,10 @@
#include "fw_query.h"
#include "version.h"
+#ifdef HAVE_SYSTEMD
+# include <systemd/sd-daemon.h>
+#endif
+
#ifdef WINDOWS32
WORD req_version = MAKEWORD(2, 2);
WSADATA wsa_data;
@@ -93,8 +99,60 @@ static int read_dns(int, int, struct query *);
static void write_dns(int, struct query *, char *, int, char);
static void handle_full_packet(int, int, int);
+/* Ask externalip.net webservice to get external ip */
+static int get_external_ip(struct in_addr *ip)
+{
+ int sock;
+ struct addrinfo *addr;
+ int res;
+ const char *getstr = "GET /ip/ HTTP/1.0\r\n"
+ /* HTTP 1.0 to avoid chunked transfer coding */
+ "Host: api.externalip.net\r\n\r\n";
+ char buf[512];
+ char *b;
+ int len;
+
+ res = getaddrinfo("api.externalip.net", "80", NULL, &addr);
+ if (res < 0) return 1;
+
+ sock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
+ if (sock < 0) {
+ freeaddrinfo(addr);
+ return 2;
+ }
+
+ res = connect(sock, addr->ai_addr, addr->ai_addrlen);
+ freeaddrinfo(addr);
+ if (res < 0) return 3;
+
+ res = write(sock, getstr, strlen(getstr));
+ if (res != strlen(getstr)) return 4;
+
+ /* Zero buf before receiving, leave at least one zero at the end */
+ memset(buf, 0, sizeof(buf));
+ res = read(sock, buf, sizeof(buf) - 1);
+ if (res < 0) return 5;
+ len = res;
+
+ res = close(sock);
+ if (res < 0) return 6;
+
+ b = buf;
+ while (len > 9) {
+ /* Look for split between headers and data */
+ if (strncmp("\r\n\r\n", b, 4) == 0) break;
+ b++;
+ len--;
+ }
+ if (len < 10) return 7;
+ b += 4;
+
+ res = inet_aton(b, ip);
+ return (res == 0);
+}
+
static void
-sigint(int sig)
+sigint(int sig)
{
running = 0;
}
@@ -116,6 +174,7 @@ syslog(int a, const char *str, ...)
}
#endif
+/* This will not check that user has passed login challenge */
static int
check_user_and_ip(int userid, struct query *q)
{
@@ -124,7 +183,7 @@ check_user_and_ip(int userid, struct query *q)
/* Note: duplicate in handle_raw_login() except IP-address check */
if (userid < 0 || userid >= created_users ) {
- return 1;
+ return 1;
}
if (!users[userid].active || users[userid].disabled) {
return 1;
@@ -142,6 +201,20 @@ check_user_and_ip(int userid, struct query *q)
return memcmp(&(users[userid].host), &(tempin->sin_addr), sizeof(struct in_addr));
}
+/* This checks that user has passed normal (non-raw) login challenge */
+static int
+check_authenticated_user_and_ip(int userid, struct query *q)
+{
+ int res = check_user_and_ip(userid, q);
+ if (res)
+ return res;
+
+ if (!users[userid].authenticated)
+ return 1;
+
+ return 0;
+}
+
static void
send_raw(int fd, char *buf, int buflen, int user, int cmd, struct query *q)
{
@@ -159,13 +232,11 @@ send_raw(int fd, char *buf, int buflen, int user, int cmd, struct query *q)
packet[RAW_HDR_CMD] = cmd | (user & 0x0F);
if (debug >= 2) {
- struct sockaddr_in *tempin;
- tempin = (struct sockaddr_in *) &(q->from);
- fprintf(stderr, "TX-raw: client %s, cmd %d, %d bytes\n",
- inet_ntoa(tempin->sin_addr), cmd, len);
+ fprintf(stderr, "TX-raw: client %s, cmd %d, %d bytes\n",
+ format_addr(&q->from, q->fromlen), cmd, len);
}
- sendto(fd, packet, len, 0, &q->from, q->fromlen);
+ sendto(fd, packet, len, 0, (struct sockaddr *) &q->from, q->fromlen);
}
@@ -496,12 +567,12 @@ send_chunk_or_dataless(int dns_fd, int userid, struct query *q)
pkt[0] = (1<<7) | ((users[userid].inpacket.seqno & 7) << 4) |
(users[userid].inpacket.fragment & 15);
/* Second byte is 3 bits downstream seqno, 4 bits downstream fragment, 1 bit last flag */
- pkt[1] = ((users[userid].outpacket.seqno & 7) << 5) |
+ pkt[1] = ((users[userid].outpacket.seqno & 7) << 5) |
((users[userid].outpacket.fragment & 15) << 1) | (last & 1);
if (debug >= 1) {
fprintf(stderr, "OUT pkt seq# %d, frag %d (last=%d), offset %d, fragsize %d, total %d, to user %d\n",
- users[userid].outpacket.seqno & 7, users[userid].outpacket.fragment & 15,
+ users[userid].outpacket.seqno & 7, users[userid].outpacket.fragment & 15,
last, users[userid].outpacket.offset, datalen, users[userid].outpacket.len, userid);
}
write_dns(dns_fd, q, pkt, datalen + 2, users[userid].downenc);
@@ -555,7 +626,7 @@ tunnel_tun(int tun_fd, int dns_fd)
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);
@@ -601,7 +672,7 @@ static void
send_version_response(int fd, version_ack_t ack, uint32_t payload, int userid, struct query *q)
{
char out[9];
-
+
switch (ack) {
case VERSION_ACK:
strncpy(out, "VACK", sizeof(out));
@@ -613,7 +684,7 @@ send_version_response(int fd, version_ack_t ack, uint32_t payload, int userid, s
strncpy(out, "VFUL", sizeof(out));
break;
}
-
+
out[4] = ((payload >> 24) & 0xff);
out[5] = ((payload >> 16) & 0xff);
out[6] = ((payload >> 8) & 0xff);
@@ -686,7 +757,7 @@ handle_null_request(int tun_fd, int dns_fd, struct query *q, int domain_len)
read = unpack_data(unpacked, sizeof(unpacked), &(in[1]), domain_len - 1, b32);
/* Version greeting, compare and send ack/nak */
- if (read > 4) {
+ if (read > 4) {
/* Received V + 32bits version */
version = (((unpacked[0] & 0xff) << 24) |
((unpacked[1] & 0xff) << 16) |
@@ -704,13 +775,13 @@ handle_null_request(int tun_fd, int dns_fd, struct query *q, int domain_len)
/* Store remote IP number */
tempin = (struct sockaddr_in *) &(q->from);
memcpy(&(users[userid].host), &(tempin->sin_addr), sizeof(struct in_addr));
-
+
memcpy(&(users[userid].q), q, sizeof(struct query));
users[userid].encoder = get_base32_encoder();
users[userid].downenc = 'T';
send_version_response(dns_fd, VERSION_ACK, users[userid].seed, userid, q);
syslog(LOG_INFO, "accepted version for user #%d from %s",
- userid, inet_ntoa(tempin->sin_addr));
+ userid, format_addr(&q->from, q->fromlen));
users[userid].q.id = 0;
users[userid].q.id2 = 0;
users[userid].q_sendrealsoon.id = 0;
@@ -751,13 +822,13 @@ handle_null_request(int tun_fd, int dns_fd, struct query *q, int domain_len)
} else {
/* No space for another user */
send_version_response(dns_fd, VERSION_FULL, created_users, 0, q);
- syslog(LOG_INFO, "dropped user from %s, server full",
- inet_ntoa(((struct sockaddr_in *) &q->from)->sin_addr));
+ syslog(LOG_INFO, "dropped user from %s, server full",
+ format_addr(&q->from, q->fromlen));
}
} else {
send_version_response(dns_fd, VERSION_NACK, VERSION, 0, q);
- syslog(LOG_INFO, "dropped user from %s, sent bad version %08X",
- inet_ntoa(((struct sockaddr_in *) &q->from)->sin_addr), version);
+ syslog(LOG_INFO, "dropped user from %s, sent bad version %08X",
+ format_addr(&q->from, q->fromlen), version);
}
return;
} else if(in[0] == 'L' || in[0] == 'l') {
@@ -773,21 +844,23 @@ handle_null_request(int tun_fd, int dns_fd, struct query *q, int domain_len)
if (check_user_and_ip(userid, q) != 0) {
write_dns(dns_fd, q, "BADIP", 5, 'T');
syslog(LOG_WARNING, "dropped login request from user #%d from unexpected source %s",
- userid, inet_ntoa(((struct sockaddr_in *) &q->from)->sin_addr));
+ userid, format_addr(&q->from, q->fromlen));
return;
} else {
users[userid].last_pkt = time(NULL);
login_calculate(logindata, 16, password, users[userid].seed);
if (read >= 18 && (memcmp(logindata, unpacked+1, 16) == 0)) {
- /* Login ok, send ip/mtu/netmask info */
+ /* Store login ok */
+ users[userid].authenticated = 1;
+ /* Send ip/mtu/netmask info */
tempip.s_addr = my_ip;
tmp[0] = strdup(inet_ntoa(tempip));
tempip.s_addr = users[userid].tun_ip;
tmp[1] = strdup(inet_ntoa(tempip));
- read = snprintf(out, sizeof(out), "%s-%s-%d-%d",
+ read = snprintf(out, sizeof(out), "%s-%s-%d-%d",
tmp[0], tmp[1], my_mtu, netmask);
write_dns(dns_fd, q, out, read, users[userid].downenc);
@@ -799,7 +872,7 @@ handle_null_request(int tun_fd, int dns_fd, struct query *q, int domain_len)
} else {
write_dns(dns_fd, q, "LNAK", 4, 'T');
syslog(LOG_WARNING, "rejected login request from user #%d from %s, bad password",
- userid, inet_ntoa(((struct sockaddr_in *) &q->from)->sin_addr));
+ userid, format_addr(&q->from, q->fromlen));
}
}
return;
@@ -808,9 +881,9 @@ handle_null_request(int tun_fd, int dns_fd, struct query *q, int domain_len)
in_addr_t replyaddr;
unsigned addr;
char reply[5];
-
+
userid = b32_8to5(in[1]);
- if (check_user_and_ip(userid, q) != 0) {
+ if (check_authenticated_user_and_ip(userid, q) != 0) {
write_dns(dns_fd, q, "BADIP", 5, 'T');
return; /* illegal id */
}
@@ -846,12 +919,12 @@ handle_null_request(int tun_fd, int dns_fd, struct query *q, int domain_len)
}
userid = b32_8to5(in[1]);
-
- if (check_user_and_ip(userid, q) != 0) {
+
+ if (check_authenticated_user_and_ip(userid, q) != 0) {
write_dns(dns_fd, q, "BADIP", 5, 'T');
return; /* illegal id */
}
-
+
codec = b32_8to5(in[2]);
switch (codec) {
@@ -888,7 +961,7 @@ handle_null_request(int tun_fd, int dns_fd, struct query *q, int domain_len)
userid = b32_8to5(in[1]);
- if (check_user_and_ip(userid, q) != 0) {
+ if (check_authenticated_user_and_ip(userid, q) != 0) {
write_dns(dns_fd, q, "BADIP", 5, 'T');
return; /* illegal id */
}
@@ -1016,13 +1089,13 @@ handle_null_request(int tun_fd, int dns_fd, struct query *q, int domain_len)
/* Downstream fragsize probe packet */
userid = (b32_8to5(in[1]) >> 1) & 15;
- if (check_user_and_ip(userid, q) != 0) {
+ if (check_authenticated_user_and_ip(userid, q) != 0) {
write_dns(dns_fd, q, "BADIP", 5, 'T');
return; /* illegal id */
}
-
+
req_frag_size = ((b32_8to5(in[1]) & 1) << 10) | ((b32_8to5(in[2]) & 31) << 5) | (b32_8to5(in[3]) & 31);
- if (req_frag_size < 2 || req_frag_size > 2047) {
+ if (req_frag_size < 2 || req_frag_size > 2047) {
write_dns(dns_fd, q, "BADFRAG", 7, users[userid].downenc);
} else {
char buf[2048];
@@ -1051,13 +1124,13 @@ handle_null_request(int tun_fd, int dns_fd, struct query *q, int domain_len)
/* Downstream fragsize packet */
userid = unpacked[0];
- if (check_user_and_ip(userid, q) != 0) {
+ if (check_authenticated_user_and_ip(userid, q) != 0) {
write_dns(dns_fd, q, "BADIP", 5, 'T');
return; /* illegal id */
}
-
+
max_frag_size = ((unpacked[1] & 0xff) << 8) | (unpacked[2] & 0xff);
- if (max_frag_size < 2) {
+ if (max_frag_size < 2) {
write_dns(dns_fd, q, "BADFRAG", 7, users[userid].downenc);
} else {
users[userid].fragsize = max_frag_size;
@@ -1084,7 +1157,7 @@ handle_null_request(int tun_fd, int dns_fd, struct query *q, int domain_len)
/* Ping packet, store userid */
userid = unpacked[0];
- if (check_user_and_ip(userid, q) != 0) {
+ if (check_authenticated_user_and_ip(userid, q) != 0) {
write_dns(dns_fd, q, "BADIP", 5, 'T');
return; /* illegal id */
}
@@ -1122,7 +1195,7 @@ handle_null_request(int tun_fd, int dns_fd, struct query *q, int domain_len)
memcpy(&(users[userid].q.from2), &(q->from), q->fromlen);
return;
}
-
+
if (users[userid].q_sendrealsoon.id != 0 &&
q->type == users[userid].q_sendrealsoon.type &&
!strcmp(q->name, users[userid].q_sendrealsoon.name)) {
@@ -1138,7 +1211,7 @@ handle_null_request(int tun_fd, int dns_fd, struct query *q, int domain_len)
&(q->from), q->fromlen);
return;
}
-
+
dn_seq = unpacked[1] >> 4;
dn_frag = unpacked[1] & 15;
@@ -1214,7 +1287,7 @@ handle_null_request(int tun_fd, int dns_fd, struct query *q, int domain_len)
userid = code;
/* Check user and sending ip number */
- if (check_user_and_ip(userid, q) != 0) {
+ if (check_authenticated_user_and_ip(userid, q) != 0) {
write_dns(dns_fd, q, "BADIP", 5, 'T');
return; /* illegal id */
}
@@ -1233,7 +1306,7 @@ handle_null_request(int tun_fd, int dns_fd, struct query *q, int domain_len)
like to re-try early and often (with _different_ .id!) */
if (users[userid].q.id != 0 &&
q->type == users[userid].q.type &&
- !strcmp(q->name, users[userid].q.name) &&
+ !strcmp(q->name, users[userid].q.name) &&
users[userid].lazy) {
/* We have this packet already, and it's waiting to be
answered. Always keep the last duplicate, since the
@@ -1250,7 +1323,7 @@ handle_null_request(int tun_fd, int dns_fd, struct query *q, int domain_len)
memcpy(&(users[userid].q.from2), &(q->from), q->fromlen);
return;
}
-
+
if (users[userid].q_sendrealsoon.id != 0 &&
q->type == users[userid].q_sendrealsoon.type &&
!strcmp(q->name, users[userid].q_sendrealsoon.name)) {
@@ -1266,7 +1339,7 @@ handle_null_request(int tun_fd, int dns_fd, struct query *q, int domain_len)
&(q->from), q->fromlen);
return;
}
-
+
/* Decode data header */
up_seq = (b32_8to5(in[1]) >> 2) & 7;
@@ -1277,7 +1350,7 @@ handle_null_request(int tun_fd, int dns_fd, struct query *q, int domain_len)
process_downstream_ack(userid, dn_seq, dn_frag);
- if (up_seq == users[userid].inpacket.seqno &&
+ if (up_seq == users[userid].inpacket.seqno &&
up_frag <= users[userid].inpacket.fragment) {
/* Got repeated old packet _with data_, probably
because client didn't receive our ack. So re-send
@@ -1435,12 +1508,10 @@ handle_ns_request(int dns_fd, struct query *q)
warnx("dns_encode_ns_response doesn't fit");
return;
}
-
+
if (debug >= 2) {
- struct sockaddr_in *tempin;
- tempin = (struct sockaddr_in *) &(q->from);
- fprintf(stderr, "TX: client %s, type %d, name %s, %d bytes NS reply\n",
- inet_ntoa(tempin->sin_addr), q->type, q->name, len);
+ fprintf(stderr, "TX: client %s, type %d, name %s, %d bytes NS reply\n",
+ format_addr(&q->from, q->fromlen), q->type, q->name, len);
}
if (sendto(dns_fd, buf, len, 0, (struct sockaddr*)&q->from, q->fromlen) <= 0) {
warn("ns reply send error");
@@ -1469,12 +1540,10 @@ handle_a_request(int dns_fd, struct query *q, int fakeip)
warnx("dns_encode_a_response doesn't fit");
return;
}
-
+
if (debug >= 2) {
- struct sockaddr_in *tempin;
- tempin = (struct sockaddr_in *) &(q->from);
fprintf(stderr, "TX: client %s, type %d, name %s, %d bytes A reply\n",
- inet_ntoa(tempin->sin_addr), q->type, q->name, len);
+ format_addr(&q->from, q->fromlen), q->type, q->name, len);
}
if (sendto(dns_fd, buf, len, 0, (struct sockaddr*)&q->from, q->fromlen) <= 0) {
warn("a reply send error");
@@ -1506,7 +1575,7 @@ forward_query(int bind_fd, struct query *q)
myaddr = (struct sockaddr_in *) &(q->from);
memcpy(&(myaddr->sin_addr), &newaddr, sizeof(in_addr_t));
myaddr->sin_port = htons(bind_port);
-
+
if (debug >= 2) {
fprintf(stderr, "TX: NS reply \n");
}
@@ -1515,45 +1584,45 @@ forward_query(int bind_fd, struct query *q)
warn("forward query error");
}
}
-
+
static int
tunnel_bind(int bind_fd, int dns_fd)
{
char packet[64*1024];
- struct sockaddr_in from;
+ struct sockaddr_storage from;
socklen_t fromlen;
struct fw_query *query;
unsigned short id;
int r;
fromlen = sizeof(struct sockaddr);
- r = recvfrom(bind_fd, packet, sizeof(packet), 0,
+ r = recvfrom(bind_fd, packet, sizeof(packet), 0,
(struct sockaddr*)&from, &fromlen);
if (r <= 0)
return 0;
id = dns_get_id(packet, r);
-
+
if (debug >= 2) {
fprintf(stderr, "RX: Got response on query %u from DNS\n", (id & 0xFFFF));
}
/* Get sockaddr from id */
fw_query_get(id, &query);
- if (!query && debug >= 2) {
- fprintf(stderr, "Lost sender of id %u, dropping reply\n", (id & 0xFFFF));
+ if (!query) {
+ if (debug >= 2) {
+ fprintf(stderr, "Lost sender of id %u, dropping reply\n", (id & 0xFFFF));
+ }
return 0;
}
if (debug >= 2) {
- struct sockaddr_in *in;
- in = (struct sockaddr_in *) &(query->addr);
fprintf(stderr, "TX: client %s id %u, %d bytes\n",
- inet_ntoa(in->sin_addr), (id & 0xffff), r);
+ format_addr(&query->addr, query->addrlen), (id & 0xffff), r);
}
-
- if (sendto(dns_fd, packet, r, 0, (const struct sockaddr *) &(query->addr),
+
+ if (sendto(dns_fd, packet, r, 0, (const struct sockaddr *) &(query->addr),
query->addrlen) <= 0) {
warn("forward reply error");
}
@@ -1567,16 +1636,14 @@ tunnel_dns(int tun_fd, int dns_fd, int bind_fd)
struct query q;
int read;
int domain_len;
- int inside_topdomain;
+ int inside_topdomain = 0;
if ((read = read_dns(dns_fd, tun_fd, &q)) <= 0)
return 0;
if (debug >= 2) {
- struct sockaddr_in *tempin;
- tempin = (struct sockaddr_in *) &(q.from);
- fprintf(stderr, "RX: client %s, type %d, name %s\n",
- inet_ntoa(tempin->sin_addr), q.type, q.name);
+ fprintf(stderr, "RX: client %s, type %d, name %s\n",
+ format_addr(&q.from, q.fromlen), q.type, q.name);
}
domain_len = strlen(q.name) - strlen(topdomain);
@@ -1612,6 +1679,7 @@ tunnel_dns(int tun_fd, int dns_fd, int bind_fd)
switch (q.type) {
case T_NULL:
+ case T_PRIVATE:
case T_CNAME:
case T_A:
case T_MX:
@@ -1636,12 +1704,13 @@ tunnel_dns(int tun_fd, int dns_fd, int bind_fd)
}
static int
-tunnel(int tun_fd, int dns_fd, int bind_fd)
+tunnel(int tun_fd, int dns_fd, int bind_fd, int max_idle_time)
{
struct timeval tv;
fd_set fds;
int i;
int userid;
+ time_t last_action = time(NULL);
while (running) {
int maxfd;
@@ -1655,7 +1724,7 @@ tunnel(int tun_fd, int dns_fd, int bind_fd)
requests during heavy upstream traffic.
20msec: ~8 packs every 1/50sec = ~400 DNSreq/sec,
or ~1200bytes every 1/50sec = ~0.5 Mbit/sec upstream */
- for (userid = 0; userid < USERS; userid++) {
+ for (userid = 0; userid < created_users; userid++) {
if (users[userid].active && !users[userid].disabled &&
users[userid].last_pkt + 60 > time(NULL)) {
users[userid].q_sendrealsoon_new = 0;
@@ -1685,29 +1754,41 @@ tunnel(int tun_fd, int dns_fd, int bind_fd)
}
i = select(maxfd + 1, &fds, NULL, NULL, &tv);
-
+
if(i < 0) {
- if (running)
+ if (running)
warn("select");
return 1;
}
- if (i==0) {
- /* timeout; whatever; doesn't matter anymore */
+ if (i==0) {
+ if (max_idle_time) {
+ /* only trigger the check if that's worth ( ie, no need to loop over if there
+ is something to send */
+ if (last_action + max_idle_time < time(NULL)) {
+ for (userid = 0; userid < created_users; userid++) {
+ last_action = ( users[userid].last_pkt > last_action ) ? users[userid].last_pkt : last_action;
+ }
+ if (last_action + max_idle_time < time(NULL)) {
+ fprintf(stderr, "Idling since too long, shutting down...\n");
+ running = 0;
+ }
+ }
+ }
} else {
if (FD_ISSET(tun_fd, &fds)) {
tunnel_tun(tun_fd, dns_fd);
}
if (FD_ISSET(dns_fd, &fds)) {
tunnel_dns(tun_fd, dns_fd, bind_fd);
- }
+ }
if (FD_ISSET(bind_fd, &fds)) {
tunnel_bind(bind_fd, dns_fd);
}
}
/* Send realsoon's if tun or dns didn't already */
- for (userid = 0; userid < USERS; userid++)
+ for (userid = 0; userid < created_users; userid++)
if (users[userid].active && !users[userid].disabled &&
users[userid].last_pkt + 60 > time(NULL) &&
users[userid].q_sendrealsoon.id != 0 &&
@@ -1728,7 +1809,7 @@ handle_full_packet(int tun_fd, int dns_fd, int userid)
int ret;
outlen = sizeof(out);
- ret = uncompress((uint8_t*)out, &outlen,
+ ret = uncompress((uint8_t*)out, &outlen,
(uint8_t*)users[userid].inpacket.data, users[userid].inpacket.len);
if (ret == Z_OK) {
@@ -1742,31 +1823,29 @@ handle_full_packet(int tun_fd, int dns_fd, int userid)
write_tun(tun_fd, out, outlen);
} else {
/* send the compressed(!) packet to other client */
- /*XXX START adjust indent 1 tab forward*/
- if (users[touser].conn == CONN_DNS_NULL) {
- if (users[touser].outpacket.len == 0) {
- start_new_outpacket(touser,
- users[userid].inpacket.data,
- users[userid].inpacket.len);
-
- /* Start sending immediately if query is waiting */
- if (users[touser].q_sendrealsoon.id != 0)
- send_chunk_or_dataless(dns_fd, touser, &users[touser].q_sendrealsoon);
- else if (users[touser].q.id != 0)
- send_chunk_or_dataless(dns_fd, touser, &users[touser].q);
+ if (users[touser].conn == CONN_DNS_NULL) {
+ if (users[touser].outpacket.len == 0) {
+ start_new_outpacket(touser,
+ users[userid].inpacket.data,
+ users[userid].inpacket.len);
+
+ /* Start sending immediately if query is waiting */
+ if (users[touser].q_sendrealsoon.id != 0)
+ send_chunk_or_dataless(dns_fd, touser, &users[touser].q_sendrealsoon);
+ else if (users[touser].q.id != 0)
+ send_chunk_or_dataless(dns_fd, touser, &users[touser].q);
#ifdef OUTPACKETQ_LEN
- } else {
- save_to_outpacketq(touser,
- users[userid].inpacket.data,
- users[userid].inpacket.len);
+ } else {
+ save_to_outpacketq(touser,
+ users[userid].inpacket.data,
+ users[userid].inpacket.len);
#endif
+ }
+ } else{ /* CONN_RAW_UDP */
+ send_raw(dns_fd, users[userid].inpacket.data,
+ users[userid].inpacket.len, touser,
+ RAW_HDR_CMD_DATA, &users[touser].q);
}
- } else{ /* CONN_RAW_UDP */
- send_raw(dns_fd, users[userid].inpacket.data,
- users[userid].inpacket.len, touser,
- RAW_HDR_CMD_DATA, &users[touser].q);
- }
- /*XXX END adjust indent 1 tab forward*/
}
} else {
if (debug >= 1)
@@ -1782,13 +1861,14 @@ static void
handle_raw_login(char *packet, int len, struct query *q, int fd, int userid)
{
char myhash[16];
-
+
if (len < 16) return;
- /* can't use check_user_and_ip() since IP address will be different,
+ /* can't use check_authenticated_user_and_ip() since IP address will be different,
so duplicate here except IP address */
if (userid < 0 || userid >= created_users) return;
if (!users[userid].active || users[userid].disabled) return;
+ if (!users[userid].authenticated) return;
if (users[userid].last_pkt + 60 < time(NULL)) return;
if (debug >= 1) {
@@ -1808,20 +1888,23 @@ handle_raw_login(char *packet, int len, struct query *q, int fd, int userid)
/* Store remote IP number */
tempin = (struct sockaddr_in *) &(q->from);
memcpy(&(users[userid].host), &(tempin->sin_addr), sizeof(struct in_addr));
-
+
/* Correct hash, reply with hash of seed - 1 */
user_set_conn_type(userid, CONN_RAW_UDP);
login_calculate(myhash, 16, password, users[userid].seed - 1);
send_raw(fd, myhash, 16, userid, RAW_HDR_CMD_LOGIN, q);
+
+ users[userid].authenticated_raw = 1;
}
}
static void
handle_raw_data(char *packet, int len, struct query *q, int dns_fd, int tun_fd, int userid)
{
- if (check_user_and_ip(userid, q) != 0) {
+ if (check_authenticated_user_and_ip(userid, q) != 0) {
return;
}
+ if (!users[userid].authenticated_raw) return;
/* Update query and time info for user */
users[userid].last_pkt = time(NULL);
@@ -1843,9 +1926,10 @@ handle_raw_data(char *packet, int len, struct query *q, int dns_fd, int tun_fd,
static void
handle_raw_ping(struct query *q, int dns_fd, int userid)
{
- if (check_user_and_ip(userid, q) != 0) {
+ if (check_authenticated_user_and_ip(userid, q) != 0) {
return;
}
+ if (!users[userid].authenticated_raw) return;
/* Update query and time info for user */
users[userid].last_pkt = time(NULL);
@@ -1914,7 +1998,7 @@ read_dns(int fd, int tun_fd, struct query *q) /* FIXME: tun_fd is because of raw
msg.msg_control = address;
msg.msg_controllen = sizeof(address);
msg.msg_flags = 0;
-
+
r = recvmsg(fd, &msg, 0);
#else
addrlen = sizeof(struct sockaddr);
@@ -1932,22 +2016,22 @@ read_dns(int fd, int tun_fd, struct query *q) /* FIXME: tun_fd is because of raw
if (dns_decode(NULL, 0, q, QR_QUERY, packet, r) < 0) {
return 0;
}
-
+
#ifndef WINDOWS32
- for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
- cmsg = CMSG_NXTHDR(&msg, cmsg)) {
-
- if (cmsg->cmsg_level == IPPROTO_IP &&
- cmsg->cmsg_type == DSTADDR_SOCKOPT) {
-
- q->destination = *dstaddr(cmsg);
+ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
+ cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+
+ if (cmsg->cmsg_level == IPPROTO_IP &&
+ cmsg->cmsg_type == DSTADDR_SOCKOPT) {
+
+ q->destination = *dstaddr(cmsg);
break;
- }
+ }
}
#endif
return strlen(q->name);
- } else if (r < 0) {
+ } else if (r < 0) {
/* Error */
warn("read dns");
}
@@ -1977,7 +2061,7 @@ write_dns_nameenc(char *buf, size_t buflen, char *data, int datalen, char downen
space = MIN(0xFF, buflen) - 4 - 2;
/* -1 encoding type, -3 ".xy", -2 for safety */
- memset(buf, 0, sizeof(buf));
+ memset(buf, 0, buflen);
if (downenc == 'S') {
buf[0] = 'i';
@@ -2012,7 +2096,7 @@ write_dns_nameenc(char *buf, size_t buflen, char *data, int datalen, char downen
/* Add dot (if it wasn't there already) and topdomain */
b = buf;
b += strlen(buf) - 1;
- if (*b != '.')
+ if (*b != '.')
*++b = '.';
b++;
@@ -2104,12 +2188,10 @@ write_dns(int fd, struct query *q, char *data, int datalen, char downenc)
warnx("dns_encode doesn't fit");
return;
}
-
+
if (debug >= 2) {
- struct sockaddr_in *tempin;
- tempin = (struct sockaddr_in *) &(q->from);
- fprintf(stderr, "TX: client %s, type %d, name %s, %d bytes data\n",
- inet_ntoa(tempin->sin_addr), q->type, q->name, datalen);
+ fprintf(stderr, "TX: client %s, type %d, name %s, %d bytes data\n",
+ format_addr(&q->from, q->fromlen), q->type, q->name, datalen);
}
sendto(fd, buf, len, 0, (struct sockaddr*)&q->from, q->fromlen);
@@ -2122,7 +2204,7 @@ usage() {
fprintf(stderr, "Usage: %s [-v] [-h] [-c] [-s] [-f] [-D] [-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] "
+ "[-b dnsport] [-P password] [-F pidfile] [-i max idle time] "
"tunnel_ip[/netmask] topdomain\n", __progname);
exit(2);
}
@@ -2156,6 +2238,7 @@ help() {
fprintf(stderr, " -b port to forward normal DNS queries to (on localhost)\n");
fprintf(stderr, " -P password used for authentication (max 32 chars will be used)\n");
fprintf(stderr, " -F pidfile to write pid to a file\n");
+ fprintf(stderr, " -i maximum idle time before shutting down\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, "topdomain is the FQDN that is delegated to this server.\n");
@@ -2165,7 +2248,7 @@ help() {
static void
version() {
fprintf(stderr, "iodine IP over DNS tunneling server\n");
- fprintf(stderr, "version: 0.6.0-rc1 from 2010-02-13\n");
+ fprintf(stderr, "version: 0.7.0 from 2014-06-16\n");
exit(0);
}
@@ -2173,7 +2256,8 @@ int
main(int argc, char **argv)
{
extern char *__progname;
- in_addr_t listen_ip;
+ char *listen_ip;
+ char *errormsg;
#ifndef WINDOWS32
struct passwd *pw;
#endif
@@ -2186,21 +2270,29 @@ main(int argc, char **argv)
int dnsd_fd;
int tun_fd;
- /* settings for forwarding normal DNS to
+ /* settings for forwarding normal DNS to
* local real DNS server */
int bind_fd;
int bind_enable;
-
+
int choice;
int port;
int mtu;
int skipipconfig;
char *netsize;
+ int ns_get_externalip;
int retval;
+ int max_idle_time = 0;
+ struct sockaddr_storage dnsaddr;
+ int dnsaddr_len;
+#ifdef HAVE_SYSTEMD
+ int nb_fds;
+#endif
#ifndef WINDOWS32
pw = NULL;
#endif
+ errormsg = NULL;
username = NULL;
newroot = NULL;
context = NULL;
@@ -2210,9 +2302,10 @@ main(int argc, char **argv)
bind_fd = 0;
mtu = 1130; /* Very many relays give fragsize 1150 or slightly
higher for NULL; tun/zlib adds ~17 bytes. */
- listen_ip = INADDR_ANY;
+ listen_ip = NULL;
port = 53;
ns_ip = INADDR_ANY;
+ ns_get_externalip = 0;
check_ip = 1;
skipipconfig = 0;
debug = 0;
@@ -2223,7 +2316,7 @@ main(int argc, char **argv)
b64 = get_base64_encoder();
b64u = get_base64u_encoder();
b128 = get_base128_encoder();
-
+
retval = 0;
#ifdef WINDOWS32
@@ -2241,8 +2334,8 @@ main(int argc, char **argv)
memset(password, 0, sizeof(password));
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, "vcsfhDu:t:d:m:l:p:n:b:P:z:F:i:")) != -1) {
switch(choice) {
case 'v':
version();
@@ -2275,13 +2368,17 @@ main(int argc, char **argv)
mtu = atoi(optarg);
break;
case 'l':
- listen_ip = inet_addr(optarg);
+ listen_ip = optarg;
break;
case 'p':
port = atoi(optarg);
break;
case 'n':
- ns_ip = inet_addr(optarg);
+ if (optarg && strcmp("auto", optarg) == 0) {
+ ns_get_externalip = 1;
+ } else {
+ ns_ip = inet_addr(optarg);
+ }
break;
case 'b':
bind_enable = 1;
@@ -2289,13 +2386,16 @@ main(int argc, char **argv)
break;
case 'F':
pidfile = optarg;
- break;
+ break;
+ case 'i':
+ max_idle_time = atoi(optarg);
+ break;
case 'P':
strncpy(password, optarg, sizeof(password));
password[sizeof(password)-1] = 0;
-
+
/* XXX: find better way of cleaning up ps(1) */
- memset(optarg, 0, strlen(optarg));
+ memset(optarg, 0, strlen(optarg));
break;
case 'z':
context = optarg;
@@ -2311,9 +2411,9 @@ main(int argc, char **argv)
check_superuser(usage);
- if (argc != 2)
+ if (argc != 2)
usage();
-
+
netsize = strchr(argv[0], '/');
if (netsize) {
*netsize = 0;
@@ -2322,21 +2422,17 @@ main(int argc, char **argv)
}
my_ip = inet_addr(argv[0]);
-
+
if (my_ip == INADDR_NONE) {
warnx("Bad IP address to use inside tunnel.");
usage();
}
topdomain = strdup(argv[1]);
- if (strlen(topdomain) <= 128) {
- if(check_topdomain(topdomain)) {
- warnx("Topdomain contains invalid characters.");
- usage();
- }
- } else {
- warnx("Use a topdomain max 128 chars long.");
+ if(check_topdomain(topdomain, &errormsg)) {
+ warnx("Invalid topdomain: %s", errormsg);
usage();
+ /* NOTREACHED */
}
if (username != NULL) {
@@ -2352,20 +2448,38 @@ main(int argc, char **argv)
warnx("Bad MTU given.");
usage();
}
-
+
if(port < 1 || port > 65535) {
warnx("Bad port number given.");
usage();
}
-
+
+ if (port != 53) {
+ fprintf(stderr, "ALERT! Other dns servers expect you to run on port 53.\n");
+ fprintf(stderr, "You must manually forward port 53 to port %d for things to work.\n", port);
+ }
+
+ if (debug) {
+ fprintf(stderr, "Debug level %d enabled, will stay in foreground.\n", debug);
+ fprintf(stderr, "Add more -D switches to set higher debug level.\n");
+ foreground = 1;
+ }
+
+ dnsaddr_len = get_addr(listen_ip, port, AF_INET, AI_PASSIVE | AI_NUMERICHOST, &dnsaddr);
+ if (dnsaddr_len < 0) {
+ warnx("Bad IP address to listen on.");
+ usage();
+ }
+
if(bind_enable) {
+ in_addr_t dns_ip = ((struct sockaddr_in *) &dnsaddr)->sin_addr.s_addr;
if (bind_port < 1 || bind_port > 65535) {
warnx("Bad DNS server port number given.");
usage();
/* NOTREACHED */
}
/* Avoid forwarding loops */
- if (bind_port == port && (listen_ip == INADDR_ANY || listen_ip == htonl(0x7f000001L))) {
+ if (bind_port == port && (dns_ip == INADDR_ANY || dns_ip == htonl(0x7f000001L))) {
warnx("Forward port is same as listen port (%d), will create a loop!", bind_port);
fprintf(stderr, "Use -l to set listen ip to avoid this.\n");
usage();
@@ -2374,23 +2488,18 @@ main(int argc, char **argv)
fprintf(stderr, "Requests for domains outside of %s will be forwarded to port %d\n",
topdomain, bind_port);
}
-
- if (port != 53) {
- fprintf(stderr, "ALERT! Other dns servers expect you to run on port 53.\n");
- fprintf(stderr, "You must manually forward port 53 to port %d for things to work.\n", port);
- }
- if (debug) {
- fprintf(stderr, "Debug level %d enabled, will stay in foreground.\n", debug);
- fprintf(stderr, "Add more -D switches to set higher debug level.\n");
- foreground = 1;
+ if (ns_get_externalip) {
+ struct in_addr extip;
+ int res = get_external_ip(&extip);
+ if (res) {
+ fprintf(stderr, "Failed to get external IP via web service.\n");
+ exit(3);
+ }
+ ns_ip = extip.s_addr;
+ fprintf(stderr, "Using %s as external IP.\n", inet_ntoa(extip));
}
- if (listen_ip == INADDR_NONE) {
- warnx("Bad IP address to listen on.");
- usage();
- }
-
if (ns_ip == INADDR_NONE) {
warnx("Bad IP address to return as nameserver.");
usage();
@@ -2399,7 +2508,7 @@ main(int argc, char **argv)
warnx("Bad netmask (%d bits). Use 8-30 bits.", netmask);
usage();
}
-
+
if (strlen(password) == 0) {
if (NULL != getenv(PASSWORD_ENV_VAR))
snprintf(password, sizeof(password), "%s", getenv(PASSWORD_ENV_VAR));
@@ -2414,33 +2523,49 @@ main(int argc, char **argv)
goto cleanup0;
}
if (!skipipconfig) {
- if (tun_setip(argv[0], users_get_first_ip(), netmask) != 0 || tun_setmtu(mtu) != 0) {
+ const char *other_ip = users_get_first_ip();
+ if (tun_setip(argv[0], other_ip, netmask) != 0 || tun_setmtu(mtu) != 0) {
retval = 1;
+ free((void*) other_ip);
goto cleanup1;
}
+ free((void*) other_ip);
}
- if ((dnsd_fd = open_dns(port, listen_ip)) == -1) {
+#ifdef HAVE_SYSTEMD
+ nb_fds = sd_listen_fds(0);
+ if (nb_fds > 1) {
retval = 1;
- goto cleanup2;
+ warnx("Too many file descriptors received!\n");
+ goto cleanup1;
+ } else if (nb_fds == 1) {
+ dnsd_fd = SD_LISTEN_FDS_START;
+ } else {
+#endif
+ if ((dnsd_fd = open_dns(&dnsaddr, dnsaddr_len)) < 0) {
+ retval = 1;
+ goto cleanup2;
+ }
+#ifdef HAVE_SYSTEMD
}
+#endif
if (bind_enable) {
- if ((bind_fd = open_dns(0, INADDR_ANY)) == -1) {
+ if ((bind_fd = open_dns_from_host(NULL, 0, AF_INET, 0)) < 0) {
retval = 1;
goto cleanup3;
}
}
my_mtu = mtu;
-
+
if (created_users < USERS) {
fprintf(stderr, "Limiting to %d simultaneous users because of netmask /%d\n",
created_users, netmask);
}
fprintf(stderr, "Listening to dns for domain %s\n", topdomain);
- if (foreground == 0)
+ if (foreground == 0)
do_detach();
-
+
if (pidfile != NULL)
do_pidfile(pidfile);
@@ -2470,8 +2595,8 @@ main(int argc, char **argv)
do_setcon(context);
syslog(LOG_INFO, "started, listening on port %d", port);
-
- tunnel(tun_fd, dnsd_fd, bind_fd);
+
+ tunnel(tun_fd, dnsd_fd, bind_fd, max_idle_time);
syslog(LOG_INFO, "stopping");
cleanup3:
@@ -2479,7 +2604,7 @@ cleanup3:
cleanup2:
close_dns(dnsd_fd);
cleanup1:
- close_tun(tun_fd);
+ close_tun(tun_fd);
cleanup0:
return retval;
diff --git a/jni/iodine/src/login.c b/jni/iodine/src/login.c
index c8827c3..a809998 100644
--- a/jni/iodine/src/login.c
+++ b/jni/iodine/src/login.c
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
+ * Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
+ * 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -20,16 +21,17 @@
#ifdef WINDOWS32
#include "windows.h"
#else
+#include <netinet/in.h>
#include <arpa/inet.h>
#endif
#include "md5.h"
-/*
- * Needs a 16byte array for output, and 32 bytes password
+/*
+ * Needs a 16byte array for output, and 32 bytes password
*/
-void
-login_calculate(char *buf, int buflen, const char *pass, int seed)
+void
+login_calculate(char *buf, int buflen, const char *pass, int seed)
{
unsigned char temp[32];
md5_state_t ctx;
@@ -37,7 +39,7 @@ login_calculate(char *buf, int buflen, const char *pass, int seed)
int i;
int k;
- if (buflen < 16)
+ if (buflen < 16)
return;
memcpy(temp, pass, 32);
diff --git a/jni/iodine/src/login.h b/jni/iodine/src/login.h
index 840c920..ebea25c 100644
--- a/jni/iodine/src/login.h
+++ b/jni/iodine/src/login.h
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
+ * Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
+ * 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
diff --git a/jni/iodine/src/md5.h b/jni/iodine/src/md5.h
index 698c995..3baa4dc 100644
--- a/jni/iodine/src/md5.h
+++ b/jni/iodine/src/md5.h
@@ -71,7 +71,7 @@ typedef struct md5_state_s {
} md5_state_t;
#ifdef __cplusplus
-extern "C"
+extern "C"
{
#endif
diff --git a/jni/iodine/src/osflags b/jni/iodine/src/osflags
index 787ffaa..9eda8f0 100755
--- a/jni/iodine/src/osflags
+++ b/jni/iodine/src/osflags
@@ -17,17 +17,26 @@ link)
echo '-lws2_32 -liphlpapi';
;;
Linux)
- [ -e /usr/include/selinux/selinux.h ] && echo '-lselinux';
+ FLAGS="";
+ [ -e /usr/include/selinux/selinux.h ] && FLAGS="$FLAGS -lselinux";
+ [ -e /usr/include/systemd/sd-daemon.h ] && FLAGS="$FLAGS -lsystemd-daemon";
+ echo $FLAGS;
;;
esac
;;
cflags)
case $1 in
+ windows32)
+ echo '-DWINVER=0x0501';
+ ;;
BeOS)
echo '-Dsocklen_t=int';
;;
Linux)
- [ -e /usr/include/selinux/selinux.h ] && echo '-DHAVE_SETCON';
+ FLAGS="-D_GNU_SOURCE"
+ [ -e /usr/include/selinux/selinux.h ] && FLAGS="$FLAGS -DHAVE_SETCON";
+ [ -e /usr/include/systemd/sd-daemon.h ] && FLAGS="$FLAGS -DHAVE_SYSTEMD";
+ echo $FLAGS;
;;
esac
;;
diff --git a/jni/iodine/src/read.c b/jni/iodine/src/read.c
index ff40382..a2dcd96 100644
--- a/jni/iodine/src/read.c
+++ b/jni/iodine/src/read.c
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
+ * Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
+ * 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -60,7 +61,7 @@ readname_loop(char *packet, int packetlen, char **src, char *dst, size_t length,
c--;
}
-
+
if (len >= length - 1) {
break; /* We used up all space */
}
@@ -84,15 +85,15 @@ readname(char *packet, int packetlen, char **src, char *dst, size_t length)
}
int
-readshort(char *packet, char **src, short *dst)
+readshort(char *packet, char **src, unsigned short *dst)
{
unsigned char *p;
p = (unsigned char *) *src;
*dst = (p[0] << 8) | p[1];
- (*src) += sizeof(short);
- return sizeof(short);
+ (*src) += sizeof(unsigned short);
+ return sizeof(unsigned short);
}
int
@@ -103,8 +104,8 @@ readlong(char *packet, char **src, uint32_t *dst)
p = (unsigned char *) *src;
- *dst = ((uint32_t)p[0] << 24)
- | ((uint32_t)p[1] << 16)
+ *dst = ((uint32_t)p[0] << 24)
+ | ((uint32_t)p[1] << 16)
| ((uint32_t)p[2] << 8)
| ((uint32_t)p[3]);
@@ -115,9 +116,6 @@ readlong(char *packet, char **src, uint32_t *dst)
int
readdata(char *packet, char **src, char *dst, size_t len)
{
- if (len < 0)
- return 0;
-
memcpy(dst, *src, len);
(*src) += len;
@@ -165,7 +163,7 @@ putname(char **buf, size_t buflen, const char *host)
h = strdup(host);
left = buflen;
p = *buf;
-
+
word = strtok(h, ".");
while(word) {
if (strlen(word) > 63 || strlen(word) > left) {
@@ -232,11 +230,8 @@ putlong(char **dst, uint32_t value)
int
putdata(char **dst, char *data, size_t len)
{
- if (len < 0)
- return 0;
-
memcpy(*dst, data, len);
-
+
(*dst) += len;
return len;
}
diff --git a/jni/iodine/src/read.h b/jni/iodine/src/read.h
index b33f3bb..2aac355 100644
--- a/jni/iodine/src/read.h
+++ b/jni/iodine/src/read.h
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
+ * Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
+ * 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -18,7 +19,7 @@
#define _READ_H_
int readname(char *, int, char **, char *, size_t);
-int readshort(char *, char **, short *);
+int readshort(char *, char **, unsigned short *);
int readlong(char *, char **, uint32_t *);
int readdata(char *, char **, char *, size_t);
int readtxtbin(char *, char **, size_t, char *, size_t);
diff --git a/jni/iodine/src/tun.c b/jni/iodine/src/tun.c
index eb52959..f8a2fd4 100644
--- a/jni/iodine/src/tun.c
+++ b/jni/iodine/src/tun.c
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
+ * Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
+ * 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -24,13 +25,16 @@
#include <sys/stat.h>
#include <fcntl.h>
+#ifndef IFCONFIGPATH
+#define IFCONFIGPATH "PATH=/sbin:/bin "
+#endif
+
#ifdef WINDOWS32
-#include <winsock2.h>
-#include <winioctl.h>
#include "windows.h"
+#include <winioctl.h>
-HANDLE dev_handle;
-struct tun_data data;
+static HANDLE dev_handle;
+static struct tun_data data;
static void get_name(char *ifname, int namelen, char *dev_name);
@@ -47,8 +51,8 @@ static void get_name(char *ifname, int namelen, char *dev_name);
#define NET_CFG_INST_ID "NetCfgInstanceId"
#else
#include <err.h>
-#include <arpa/inet.h>
#include <netinet/in.h>
+#include <arpa/inet.h>
#define TUN_MAX_TRY 50
#endif
@@ -56,22 +60,25 @@ static void get_name(char *ifname, int namelen, char *dev_name);
#include "tun.h"
#include "common.h"
-char if_name[250];
+static char if_name[250];
-#ifndef WINDOWS32
#ifdef LINUX
#include <sys/ioctl.h>
#include <net/if.h>
#include <linux/if_tun.h>
-int
-open_tun(const char *tun_device)
+int
+open_tun(const char *tun_device)
{
int i;
int tun_fd;
struct ifreq ifreq;
+#ifdef ANDROID
+ char *tunnel = "/dev/tun";
+#else
char *tunnel = "/dev/net/tun";
+#endif
if ((tun_fd = open(tunnel, O_RDWR)) < 0) {
warn("open_tun: %s: %s", tunnel, strerror(errno));
@@ -80,7 +87,7 @@ open_tun(const char *tun_device)
memset(&ifreq, 0, sizeof(ifreq));
- ifreq.ifr_flags = IFF_TUN;
+ ifreq.ifr_flags = IFF_TUN;
if (tun_device != NULL) {
strncpy(ifreq.ifr_name, tun_device, IFNAMSIZ);
@@ -90,6 +97,7 @@ open_tun(const char *tun_device)
if (ioctl(tun_fd, TUNSETIFF, (void *) &ifreq) != -1) {
fprintf(stderr, "Opened %s\n", ifreq.ifr_name);
+ fd_set_close_on_exec(tun_fd);
return tun_fd;
}
@@ -104,6 +112,7 @@ open_tun(const char *tun_device)
if (ioctl(tun_fd, TUNSETIFF, (void *) &ifreq) != -1) {
fprintf(stderr, "Opened %s\n", ifreq.ifr_name);
snprintf(if_name, sizeof(if_name), "dns%d", i);
+ fd_set_close_on_exec(tun_fd);
return tun_fd;
}
@@ -119,49 +128,8 @@ open_tun(const char *tun_device)
return -1;
}
-#else /* BSD */
-
-int
-open_tun(const char *tun_device)
-{
- int i;
- int tun_fd;
- char tun_name[50];
-
- if (tun_device != NULL) {
- snprintf(tun_name, sizeof(tun_name), "/dev/%s", tun_device);
- strncpy(if_name, tun_device, sizeof(if_name));
- if_name[sizeof(if_name)-1] = '\0';
-
- if ((tun_fd = open(tun_name, O_RDWR)) < 0) {
- warn("open_tun: %s: %s", tun_name, strerror(errno));
- return -1;
- }
-
- fprintf(stderr, "Opened %s\n", tun_name);
- return tun_fd;
- } else {
- for (i = 0; i < TUN_MAX_TRY; i++) {
- 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);
- snprintf(if_name, sizeof(if_name), "tun%d", i);
- return tun_fd;
- }
-
- if (errno == ENOENT)
- break;
- }
-
- warn("open_tun: Failed to open tunneling device");
- }
-
- return -1;
-}
+#elif WINDOWS32
-#endif /* !LINUX */
-#else /* WINDOWS32 */
static void
get_device(char *device, int device_len, const char *wanted_dev)
{
@@ -176,7 +144,7 @@ get_device(char *device, int device_len, const char *wanted_dev)
warnx("Error opening registry key " TAP_ADAPTER_KEY );
return;
}
-
+
while (TRUE) {
char name[256];
char unit[256];
@@ -214,7 +182,7 @@ get_device(char *device, int device_len, const char *wanted_dev)
strncmp(TAP_VERSION_ID_0901, component, strlen(TAP_VERSION_ID_0901)) == 0) {
/* We found a TAP32 device, get its NetCfgInstanceId */
char iid_string[256] = NET_CFG_INST_ID;
-
+
status = RegQueryValueEx(device_key, iid_string, NULL, &datatype, (LPBYTE) device, (DWORD *) &device_len);
if (status != ERROR_SUCCESS || datatype != REG_SZ) {
warnx("Error reading registry key %s\\%s on TAP device", unit, iid_string);
@@ -280,7 +248,7 @@ DWORD WINAPI tun_reader(LPVOID arg)
OVERLAPPED olpd;
int sock;
- sock = open_dns(0, INADDR_ANY);
+ sock = open_dns_from_host("127.0.0.1", 0, AF_INET, 0);
olpd.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
@@ -291,21 +259,22 @@ DWORD WINAPI tun_reader(LPVOID arg)
if (!res) {
WaitForSingleObject(olpd.hEvent, INFINITE);
res = GetOverlappedResult(dev_handle, &olpd, (LPDWORD) &len, FALSE);
- res = sendto(sock, buf, len, 0, (struct sockaddr*) &(tun->addr),
- sizeof(struct sockaddr_in));
+ res = sendto(sock, buf, len, 0, (struct sockaddr*) &(tun->addr),
+ tun->addrlen);
}
}
return 0;
}
-int
-open_tun(const char *tun_device)
+int
+open_tun(const char *tun_device)
{
char adapter[256];
char tapfile[512];
int tunfd;
- in_addr_t local;
+ struct sockaddr_storage localsock;
+ int localsock_len;
memset(adapter, 0, sizeof(adapter));
memset(if_name, 0, sizeof(if_name));
@@ -319,7 +288,7 @@ open_tun(const char *tun_device)
}
return -1;
}
-
+
fprintf(stderr, "Opening device %s\n", if_name);
snprintf(tapfile, sizeof(tapfile), "%s%s.tap", TAP_DEVICE_SPACE, adapter);
dev_handle = CreateFile(tapfile, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, NULL);
@@ -330,34 +299,115 @@ open_tun(const char *tun_device)
/* Use a UDP connection to forward packets from tun,
* so we can still use select() in main code.
- * A thread does blocking reads on tun device and
+ * A thread does blocking reads on tun device and
* sends data as udp to this socket */
-
- local = htonl(0x7f000001); /* 127.0.0.1 */
- tunfd = open_dns(55353, local);
+
+ localsock_len = get_addr("127.0.0.1", 55353, AF_INET, 0, &localsock);
+ tunfd = open_dns(&localsock, localsock_len);
data.tun = dev_handle;
- memset(&(data.addr), 0, sizeof(data.addr));
- data.addr.sin_family = AF_INET;
- data.addr.sin_port = htons(55353);
- data.addr.sin_addr.s_addr = local;
+ memcpy(&(data.addr), &localsock, localsock_len);
+ data.addrlen = localsock_len;
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)tun_reader, &data, 0, NULL);
-
+
return tunfd;
}
-#endif
-void
-close_tun(int tun_fd)
+#else /* BSD and friends */
+
+int
+open_tun(const char *tun_device)
+{
+ int i;
+ int tun_fd;
+ char tun_name[50];
+
+ if (tun_device != NULL) {
+ snprintf(tun_name, sizeof(tun_name), "/dev/%s", tun_device);
+ strncpy(if_name, tun_device, sizeof(if_name));
+ if_name[sizeof(if_name)-1] = '\0';
+
+ if ((tun_fd = open(tun_name, O_RDWR)) < 0) {
+ warn("open_tun: %s: %s", tun_name, strerror(errno));
+ return -1;
+ }
+
+ fprintf(stderr, "Opened %s\n", tun_name);
+ fd_set_close_on_exec(tun_fd);
+ return tun_fd;
+ } else {
+ for (i = 0; i < TUN_MAX_TRY; i++) {
+ 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);
+ snprintf(if_name, sizeof(if_name), "tun%d", i);
+ fd_set_close_on_exec(tun_fd);
+ return tun_fd;
+ }
+
+ if (errno == ENOENT)
+ break;
+ }
+
+ warn("open_tun: Failed to open tunneling device");
+ }
+
+ return -1;
+}
+
+#endif
+
+void
+close_tun(int tun_fd)
{
if (tun_fd >= 0)
close(tun_fd);
}
-int
-write_tun(int tun_fd, char *data, size_t len)
+#ifdef WINDOWS32
+int
+write_tun(int tun_fd, char *data, size_t len)
{
-#if defined (FREEBSD) || defined (DARWIN) || defined(NETBSD) || defined(WINDOWS32) || defined(__ANDROID__)
+ DWORD written;
+ DWORD res;
+ OVERLAPPED olpd;
+
+ data += 4;
+ len -= 4;
+
+ olpd.Offset = 0;
+ olpd.OffsetHigh = 0;
+ olpd.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ res = WriteFile(dev_handle, data, len, &written, &olpd);
+ if (!res && GetLastError() == ERROR_IO_PENDING) {
+ WaitForSingleObject(olpd.hEvent, INFINITE);
+ res = GetOverlappedResult(dev_handle, &olpd, &written, FALSE);
+ if (written != len) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+ssize_t
+read_tun(int tun_fd, char *buf, size_t len)
+{
+ int bytes;
+ memset(buf, 0, 4);
+
+ bytes = recv(tun_fd, buf + 4, len - 4, 0);
+ if (bytes < 0) {
+ return bytes;
+ } else {
+ return bytes + 4;
+ }
+}
+#else
+int
+write_tun(int tun_fd, char *data, size_t len)
+{
+#if defined (FREEBSD) || defined (DARWIN) || defined(NETBSD) || defined(__ANDROID__)
data += 4;
len -= 4;
#else /* !FREEBSD/DARWIN */
@@ -374,47 +424,22 @@ write_tun(int tun_fd, char *data, size_t len)
#endif /* !LINUX */
#endif /* FREEBSD */
-#ifndef WINDOWS32
if (write(tun_fd, data, len) != len) {
warn("write_tun");
return 1;
}
-#else /* WINDOWS32 */
- {
- DWORD written;
- DWORD res;
- OVERLAPPED olpd;
-
- olpd.Offset = 0;
- olpd.OffsetHigh = 0;
- olpd.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- res = WriteFile(dev_handle, data, len, &written, &olpd);
- if (!res && GetLastError() == ERROR_IO_PENDING) {
- WaitForSingleObject(olpd.hEvent, INFINITE);
- res = GetOverlappedResult(dev_handle, &olpd, &written, FALSE);
- if (written != len) {
- return -1;
- }
- }
- }
-#endif
return 0;
}
ssize_t
-read_tun(int tun_fd, char *buf, size_t len)
+read_tun(int tun_fd, char *buf, size_t len)
{
-#if defined (FREEBSD) || defined (DARWIN) || defined(NETBSD) || defined(WINDOWS32) || defined(__ANDROID__)
- /* FreeBSD/Darwin/NetBSD/Android-VPN has no header */
+#if defined (FREEBSD) || defined (DARWIN) || defined(NETBSD) || defined(__ANDROID__)
+ /* FreeBSD/Darwin/NetBSD/Android-SDK has no header */
int bytes;
memset(buf, 0, 4);
-#ifdef WINDOWS32
- /* Windows needs recv() since it is local UDP socket */
- bytes = recv(tun_fd, buf + 4, len - 4, 0);
-#else
- /* The other need read() because fd is not a socket */
+
bytes = read(tun_fd, buf + 4, len - 4);
-#endif /*WINDOWS32*/
if (bytes < 0) {
return bytes;
} else {
@@ -424,9 +449,10 @@ read_tun(int tun_fd, char *buf, size_t len)
return read(tun_fd, buf, len);
#endif /* !FREEBSD */
}
+#endif
int
-tun_setip(const char *ip, const char *remoteip, int netbits)
+tun_setip(const char *ip, const char *other_ip, int netbits)
{
char cmdline[512];
int netmask;
@@ -440,6 +466,11 @@ tun_setip(const char *ip, const char *remoteip, int netbits)
DWORD ipdata[3];
struct in_addr addr;
DWORD len;
+#else
+ const char *display_ip;
+#ifndef LINUX
+ struct in_addr netip;
+#endif
#endif
netmask = 0;
@@ -461,32 +492,36 @@ tun_setip(const char *ip, const char *remoteip, int netbits)
free(tun_config_android.remoteip);
}
tun_config_android.ip = strdup(ip);
- tun_config_android.remoteip = strdup(remoteip);
+ tun_config_android.remoteip = strdup(other_ip);
tun_config_android.netbits = netbits;
return 0;
#elif !defined(WINDOWS32)
- snprintf(cmdline, sizeof(cmdline),
- "/sbin/ifconfig %s %s %s netmask %s",
+# ifdef FREEBSD
+ display_ip = other_ip; /* FreeBSD wants other IP as second IP */
+# else
+ display_ip = ip;
+# endif
+ snprintf(cmdline, sizeof(cmdline),
+ IFCONFIGPATH "ifconfig %s %s %s netmask %s",
if_name,
ip,
-#ifdef FREEBSD
- remoteip, /* FreeBSD wants other IP as second IP */
-#else
- ip,
-#endif
+ display_ip,
inet_ntoa(net));
-
+
fprintf(stderr, "Setting IP of %s to %s\n", if_name, ip);
#ifndef LINUX
+ netip.s_addr = inet_addr(ip);
+ netip.s_addr = netip.s_addr & net.s_addr;
r = system(cmdline);
if(r != 0) {
return r;
} else {
+
snprintf(cmdline, sizeof(cmdline),
"/sbin/route add %s/%d %s",
- ip, netbits, ip);
+ inet_ntoa(netip), netbits, ip);
}
- fprintf(stderr, "Adding route %s/%d to %s\n", ip, netbits, ip);
+ fprintf(stderr, "Adding route %s/%d to %s\n", inet_ntoa(netip), netbits, ip);
#endif
return system(cmdline);
#else /* WINDOWS32 */
@@ -494,13 +529,13 @@ tun_setip(const char *ip, const char *remoteip, int netbits)
/* Set device as connected */
fprintf(stderr, "Enabling interface '%s'\n", if_name);
status = 1;
- r = DeviceIoControl(dev_handle, TAP_IOCTL_SET_MEDIA_STATUS, &status,
+ 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 */
@@ -510,7 +545,7 @@ tun_setip(const char *ip, const char *remoteip, int netbits)
}
/* Tell ip/networkaddr/netmask to device for arp use */
- r = DeviceIoControl(dev_handle, TAP_IOCTL_CONFIG_TUN, &ipdata,
+ 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");
@@ -525,7 +560,7 @@ tun_setip(const char *ip, const char *remoteip, int netbits)
#endif
}
-int
+int
tun_setmtu(const unsigned mtu)
{
#ifdef __ANDROID__
@@ -535,11 +570,11 @@ tun_setmtu(const unsigned mtu)
char cmdline[512];
if (mtu > 200 && mtu <= 1500) {
- snprintf(cmdline, sizeof(cmdline),
- "/sbin/ifconfig %s mtu %u",
+ snprintf(cmdline, sizeof(cmdline),
+ IFCONFIGPATH "ifconfig %s mtu %u",
if_name,
mtu);
-
+
fprintf(stderr, "Setting MTU of %s to %u\n", if_name, mtu);
return system(cmdline);
} else {
diff --git a/jni/iodine/src/tun.h b/jni/iodine/src/tun.h
index 397e7a9..83a6171 100644
--- a/jni/iodine/src/tun.h
+++ b/jni/iodine/src/tun.h
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
+ * Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
+ * 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
diff --git a/jni/iodine/src/user.c b/jni/iodine/src/user.c
index dfe9c36..0dc95db 100644
--- a/jni/iodine/src/user.c
+++ b/jni/iodine/src/user.c
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
+ * Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
+ * 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -33,7 +34,8 @@
#include "encoding.h"
#include "user.h"
-struct user users[USERS];
+struct tun_user *users;
+unsigned usercount;
int
init_users(in_addr_t my_ip, int netbits)
@@ -41,7 +43,6 @@ init_users(in_addr_t my_ip, int netbits)
int i;
int skip = 0;
char newip[16];
- int created_users = 0;
int maxusers;
@@ -57,9 +58,10 @@ init_users(in_addr_t my_ip, int netbits)
ipstart.s_addr = my_ip & net.s_addr;
maxusers = (1 << (32-netbits)) - 3; /* 3: Net addr, broadcast addr, iodined addr */
-
- memset(users, 0, USERS * sizeof(struct user));
- for (i = 0; i < USERS; i++) {
+ usercount = MIN(maxusers, USERS);
+
+ users = calloc(usercount, sizeof(struct tun_user));
+ 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);
@@ -72,17 +74,14 @@ init_users(in_addr_t my_ip, int netbits)
}
users[i].tun_ip = ip;
net.s_addr = ip;
- if (maxusers-- < 1) {
- users[i].disabled = 1;
- } else {
- users[i].disabled = 0;
- created_users++;
- }
+ users[i].disabled = 0;
+ users[i].authenticated = 0;
+ users[i].authenticated_raw = 0;
users[i].active = 0;
/* Rest is reset on login ('V' packet) */
}
- return created_users;
+ return usercount;
}
const char*
@@ -90,7 +89,7 @@ users_get_first_ip()
{
struct in_addr ip;
ip.s_addr = users[0].tun_ip;
- return inet_ntoa(ip);
+ return strdup(inet_ntoa(ip));
}
int
@@ -100,14 +99,14 @@ users_waiting_on_reply()
int i;
ret = 0;
- for (i = 0; i < USERS; i++) {
- if (users[i].active && !users[i].disabled &&
+ for (i = 0; i < usercount; i++) {
+ if (users[i].active && !users[i].disabled &&
users[i].last_pkt + 60 > time(NULL) &&
users[i].q.id != 0 && users[i].conn == CONN_DNS_NULL) {
ret++;
}
}
-
+
return ret;
}
@@ -118,8 +117,10 @@ find_user_by_ip(uint32_t ip)
int i;
ret = -1;
- for (i = 0; i < USERS; i++) {
- if (users[i].active && !users[i].disabled &&
+ for (i = 0; i < usercount; i++) {
+ if (users[i].active &&
+ users[i].authenticated &&
+ !users[i].disabled &&
users[i].last_pkt + 60 > time(NULL) &&
ip == users[i].tun_ip) {
ret = i;
@@ -143,11 +144,11 @@ all_users_waiting_to_send()
ret = 1;
now = time(NULL);
- for (i = 0; i < USERS; i++) {
+ for (i = 0; i < usercount; i++) {
if (users[i].active && !users[i].disabled &&
users[i].last_pkt + 60 > now &&
- ((users[i].conn == CONN_RAW_UDP) ||
- ((users[i].conn == CONN_DNS_NULL)
+ ((users[i].conn == CONN_RAW_UDP) ||
+ ((users[i].conn == CONN_DNS_NULL)
#ifdef OUTPACKETQ_LEN
&& users[i].outpacketq_filled < 1
#else
@@ -167,10 +168,12 @@ find_available_user()
{
int ret = -1;
int i;
- for (i = 0; i < USERS; i++) {
+ for (i = 0; i < usercount; i++) {
/* Not used at all or not used in one minute */
if ((!users[i].active || users[i].last_pkt + 60 < time(NULL)) && !users[i].disabled) {
users[i].active = 1;
+ users[i].authenticated = 0;
+ users[i].authenticated_raw = 0;
users[i].last_pkt = time(NULL);
users[i].fragsize = 4096;
users[i].conn = CONN_DNS_NULL;
@@ -184,21 +187,21 @@ find_available_user()
void
user_switch_codec(int userid, struct encoder *enc)
{
- if (userid < 0 || userid >= USERS)
+ if (userid < 0 || userid >= usercount)
return;
-
+
users[userid].encoder = enc;
}
void
user_set_conn_type(int userid, enum connection c)
{
- if (userid < 0 || userid >= USERS)
+ if (userid < 0 || userid >= usercount)
return;
if (c < 0 || c >= CONN_MAX)
return;
-
+
users[userid].conn = c;
}
-
+
diff --git a/jni/iodine/src/user.h b/jni/iodine/src/user.h
index 51a6092..76fc54b 100644
--- a/jni/iodine/src/user.h
+++ b/jni/iodine/src/user.h
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
+ * Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
+ * 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -33,9 +34,11 @@
#define QMEMDATA_LEN 15
/* Max advisable: 36/2 = 18. Total mem usage: QMEMDATA_LEN * USERS * 6 bytes */
-struct user {
+struct tun_user {
char id;
int active;
+ int authenticated;
+ int authenticated_raw;
int disabled;
time_t last_pkt;
int seed;
@@ -73,7 +76,7 @@ struct user {
#endif
};
-extern struct user users[USERS];
+extern struct tun_user *users;
int init_users(in_addr_t, int);
const char* users_get_first_ip();
diff --git a/jni/iodine/src/util.c b/jni/iodine/src/util.c
index bc5fc8d..f4a538e 100644
--- a/jni/iodine/src/util.c
+++ b/jni/iodine/src/util.c
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
+ * Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
+ * 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -25,12 +26,22 @@ get_resolvconf_addr()
#ifndef WINDOWS32
char buf[80];
FILE *fp;
-
+#ifdef ANDROID
+ fp = popen("getprop net.dns1", "r");
+ if (fp == NULL)
+ err(1, "getprop net.dns1 failed");
+ if (fgets(buf, sizeof(buf), fp) == NULL)
+ err(1, "read getprop net.dns1 failed");
+ if (sscanf(buf, "%15s", addr) == 1)
+ rv = addr;
+ pclose(fp);
+#else
+
rv = NULL;
- if ((fp = fopen("/etc/resolv.conf", "r")) == NULL)
+ if ((fp = fopen("/etc/resolv.conf", "r")) == NULL)
err(1, "/etc/resolv.conf");
-
+
while (feof(fp) == 0) {
fgets(buf, sizeof(buf), fp);
@@ -39,8 +50,9 @@ get_resolvconf_addr()
break;
}
}
-
+
fclose(fp);
+#endif
#else /* !WINDOWS32 */
FIXED_INFO *fixed_info;
ULONG buflen;
@@ -67,3 +79,15 @@ get_resolvconf_addr()
return rv;
}
+#ifdef OPENBSD
+void
+socket_setrtable(int fd, int rtable)
+{
+#ifdef SO_RTABLE
+ if (setsockopt (fd, IPPROTO_IP, SO_RTABLE, &rtable, sizeof(rtable)) == -1)
+ err(1, "Failed to set routing table %d", rtable);
+#else
+ fprintf(stderr, "Routing domain support was not available at compile time.\n");
+#endif
+}
+#endif
diff --git a/jni/iodine/src/util.h b/jni/iodine/src/util.h
index f514139..6872077 100644
--- a/jni/iodine/src/util.h
+++ b/jni/iodine/src/util.h
@@ -2,5 +2,6 @@
#define __UTIL_H__
char *get_resolvconf_addr();
+void socket_setrtable(int fd, int rtable);
#endif
diff --git a/jni/iodine/src/version.h b/jni/iodine/src/version.h
index 1561b9e..2ab00ff 100644
--- a/jni/iodine/src/version.h
+++ b/jni/iodine/src/version.h
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
+ * Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
+ * 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
diff --git a/jni/iodine/src/windows.h b/jni/iodine/src/windows.h
index 7e0e16c..c665a60 100644
--- a/jni/iodine/src/windows.h
+++ b/jni/iodine/src/windows.h
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
+ * Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
+ * 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -19,9 +20,9 @@
typedef unsigned int in_addr_t;
+#include <winsock2.h>
#include <windows.h>
#include <windns.h>
-#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
@@ -94,7 +95,8 @@ DWORD WINAPI tun_reader(LPVOID arg);
struct tun_data {
HANDLE tun;
int sock;
- struct sockaddr_in addr;
+ struct sockaddr_storage addr;
+ int addrlen;
};
#endif