mirror of
git://f0xx.org/ac/ac-mobile-android
synced 2026-07-29 06:38:00 +03:00
Implement native iodine client and fix RA heartbeat URL resolution.
Bundle iodine 0.7.0 with JNI TUN bridge; apply BE iodine credentials on connect; canonical heartbeat URL fallback. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
26
third-party/iodine/src/Android.16.mk
vendored
Normal file
26
third-party/iodine/src/Android.16.mk
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
#
|
||||
# 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)
|
||||
|
||||
HEAD_COMMIT = `git rev-parse --short HEAD`
|
||||
|
||||
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 -DGITREVISION=\"$(HEAD_COMMIT)\"
|
||||
LOCAL_LDLIBS := -lz
|
||||
LOCAL_CFLAGS += -fPIE
|
||||
LOCAL_LDFLAGS += -fPIE -pie
|
||||
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
24
third-party/iodine/src/Android.mk
vendored
Normal file
24
third-party/iodine/src/Android.mk
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
#
|
||||
# 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)
|
||||
|
||||
HEAD_COMMIT = `git rev-parse --short HEAD`
|
||||
|
||||
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 -DGITREVISION=\"$(HEAD_COMMIT)\"
|
||||
LOCAL_LDLIBS := -lz
|
||||
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
44
third-party/iodine/src/Makefile
vendored
Normal file
44
third-party/iodine/src/Makefile
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
COMMONOBJS = tun.o dns.o read.o encoding.o login.o base32.o base64.o base64u.o base128.o md5.o common.o
|
||||
CLIENTOBJS = iodine.o client.o util.o
|
||||
CLIENT = ../bin/iodine
|
||||
SERVEROBJS = iodined.o user.o fw_query.o
|
||||
SERVER = ../bin/iodined
|
||||
|
||||
OS = `echo $(TARGETOS) | tr "a-z" "A-Z"`
|
||||
ARCH = `uname -m`
|
||||
HEAD_COMMIT = `git rev-parse --short HEAD`
|
||||
|
||||
LIBPATH = -L.
|
||||
LDFLAGS += -lz `sh osflags $(TARGETOS) link` $(LIBPATH)
|
||||
CFLAGS += -std=c99 -c -g -Wall -D$(OS) -pedantic `sh osflags $(TARGETOS) cflags` -DGITREVISION=\"$(HEAD_COMMIT)\"
|
||||
CFLAGS += -Wstrict-prototypes -Wtype-limits -Wmissing-declarations -Wmissing-prototypes
|
||||
|
||||
all: stateos $(CLIENT) $(SERVER)
|
||||
|
||||
stateos:
|
||||
@echo OS is $(OS), arch is $(ARCH)
|
||||
|
||||
$(CLIENT): $(COMMONOBJS) $(CLIENTOBJS)
|
||||
@echo LD $@
|
||||
@mkdir -p ../bin
|
||||
@$(CC) $(COMMONOBJS) $(CLIENTOBJS) -o $(CLIENT) $(LDFLAGS)
|
||||
|
||||
$(SERVER): $(COMMONOBJS) $(SERVEROBJS)
|
||||
@echo LD $@
|
||||
@mkdir -p ../bin
|
||||
@$(CC) $(COMMONOBJS) $(SERVEROBJS) -o $(SERVER) $(LDFLAGS)
|
||||
|
||||
.c.o:
|
||||
@echo CC $<
|
||||
@$(CC) $(CFLAGS) $< -o $@
|
||||
|
||||
base64u.c: base64.c
|
||||
@echo Making $@
|
||||
@echo '/* No use in editing, produced by Makefile! */' > $@
|
||||
@sed -e 's/\([Bb][Aa][Ss][Ee]64\)/\1u/g ; s/0123456789+/0123456789_/' < base64.c >> $@
|
||||
|
||||
clean:
|
||||
@echo "Cleaning src/"
|
||||
@rm -f $(CLIENT){,.exe} $(SERVER){,.exe} *~ *.o *.core base64u.*
|
||||
@rm -rf obj libs #android stuff
|
||||
|
||||
59
third-party/iodine/src/android_dns.h
vendored
Normal file
59
third-party/iodine/src/android_dns.h
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Marcel Bokhorst <marcel@bokhorst.biz>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
|
||||
*/
|
||||
|
||||
#ifndef __FIX_ANDROID_H__
|
||||
#define __FIX_ANDROID_H__
|
||||
|
||||
/* Newer android platforms can have this data already */
|
||||
#ifndef C_IN
|
||||
|
||||
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 /* !C_IN */
|
||||
|
||||
#endif
|
||||
261
third-party/iodine/src/base128.c
vendored
Normal file
261
third-party/iodine/src/base128.c
vendored
Normal file
@@ -0,0 +1,261 @@
|
||||
/*
|
||||
* Copyright (C) 2009 J.A.Bezemer@opensourcepartners.nl
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* raw 76543210 76543210 76543210 76543210 76543210 76543210 76543210
|
||||
* enc 65432106 54321065 43210654 32106543 21065432 10654321 06543210
|
||||
* ^ ^ ^ ^ ^ ^ ^ ^
|
||||
*
|
||||
* 0001 1 0001 1
|
||||
* 0011 3 0011 3
|
||||
* 0111 7 0111 7
|
||||
* 1111 f 0110 6
|
||||
* 1110 e 0100 4
|
||||
* 1100 c
|
||||
* 1000 8
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "encoding.h"
|
||||
|
||||
#define BASE128_BLKSIZE_RAW 7
|
||||
#define BASE128_BLKSIZE_ENC 8
|
||||
|
||||
/* Don't use '-' (restricted to middle of labels), prefer iso_8859-1
|
||||
* 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[] =
|
||||
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||
"\274\275\276\277"
|
||||
"\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"
|
||||
"\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337"
|
||||
"\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357"
|
||||
"\360\361\362\363\364\365\366\367\370\371\372\373\374\375";
|
||||
static unsigned char rev128[256];
|
||||
static int reverse_init = 0;
|
||||
|
||||
inline static void base128_reverse_init(void)
|
||||
{
|
||||
int i;
|
||||
unsigned char c;
|
||||
|
||||
if (!reverse_init) {
|
||||
memset(rev128, 0, 256);
|
||||
for (i = 0; i < 128; i++) {
|
||||
c = cb128[i];
|
||||
rev128[(int) c] = i;
|
||||
}
|
||||
reverse_init = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Fills *buf with max. *buflen characters, encoding size bytes of *data.
|
||||
*
|
||||
* NOTE: *buf space should be at least 1 byte _more_ than *buflen
|
||||
* to hold the trailing '\0'.
|
||||
*
|
||||
* return value : #bytes filled in buf (excluding \0)
|
||||
* sets *buflen to : #bytes encoded from data
|
||||
*/
|
||||
static int base128_encode(char *buf, size_t *buflen, const void *data,
|
||||
size_t size)
|
||||
{
|
||||
unsigned char *ubuf = (unsigned char *) buf;
|
||||
unsigned char *udata = (unsigned char *) data;
|
||||
int iout = 0; /* to-be-filled output char */
|
||||
int iin = 0; /* one more than last input byte that can be
|
||||
successfully decoded */
|
||||
|
||||
/* Note: Don't bother to optimize manually. GCC optimizes
|
||||
better(!) when using simplistic array indexing. */
|
||||
|
||||
while (1) {
|
||||
if (iout >= *buflen || iin >= size)
|
||||
break;
|
||||
ubuf[iout] = cb128[((udata[iin] & 0xfe) >> 1)];
|
||||
iout++;
|
||||
|
||||
if (iout >= *buflen || iin >= size) {
|
||||
iout--; /* previous char is useless */
|
||||
break;
|
||||
}
|
||||
ubuf[iout] = cb128[((udata[iin] & 0x01) << 6) |
|
||||
((iin + 1 < size) ?
|
||||
((udata[iin + 1] & 0xfc) >> 2) : 0)];
|
||||
iin++; /* 0 complete, iin=1 */
|
||||
iout++;
|
||||
|
||||
if (iout >= *buflen || iin >= size)
|
||||
break;
|
||||
ubuf[iout] = cb128[((udata[iin] & 0x03) << 5) |
|
||||
((iin + 1 < size) ?
|
||||
((udata[iin + 1] & 0xf8) >> 3) : 0)];
|
||||
iin++; /* 1 complete, iin=2 */
|
||||
iout++;
|
||||
|
||||
if (iout >= *buflen || iin >= size)
|
||||
break;
|
||||
ubuf[iout] = cb128[((udata[iin] & 0x07) << 4) |
|
||||
((iin + 1 < size) ?
|
||||
((udata[iin + 1] & 0xf0) >> 4) : 0)];
|
||||
iin++; /* 2 complete, iin=3 */
|
||||
iout++;
|
||||
|
||||
if (iout >= *buflen || iin >= size)
|
||||
break;
|
||||
ubuf[iout] = cb128[((udata[iin] & 0x0f) << 3) |
|
||||
((iin + 1 < size) ?
|
||||
((udata[iin + 1] & 0xe0) >> 5) : 0)];
|
||||
iin++; /* 3 complete, iin=4 */
|
||||
iout++;
|
||||
|
||||
if (iout >= *buflen || iin >= size)
|
||||
break;
|
||||
ubuf[iout] = cb128[((udata[iin] & 0x1f) << 2) |
|
||||
((iin + 1 < size) ?
|
||||
((udata[iin + 1] & 0xc0) >> 6) : 0)];
|
||||
iin++; /* 4 complete, iin=5 */
|
||||
iout++;
|
||||
|
||||
if (iout >= *buflen || iin >= size)
|
||||
break;
|
||||
ubuf[iout] = cb128[((udata[iin] & 0x3f) << 1) |
|
||||
((iin + 1 < size) ?
|
||||
((udata[iin + 1] & 0x80) >> 7) : 0)];
|
||||
iin++; /* 5 complete, iin=6 */
|
||||
iout++;
|
||||
|
||||
if (iout >= *buflen || iin >= size)
|
||||
break;
|
||||
ubuf[iout] = cb128[(udata[iin] & 0x7f)];
|
||||
iin++; /* 6 complete, iin=7 */
|
||||
iout++;
|
||||
}
|
||||
|
||||
ubuf[iout] = '\0';
|
||||
|
||||
/* store number of bytes from data that was used */
|
||||
*buflen = iin;
|
||||
|
||||
return iout;
|
||||
}
|
||||
|
||||
#define REV128(x) rev128[(int) (x)]
|
||||
|
||||
/*
|
||||
* Fills *buf with max. *buflen bytes, decoded from slen chars in *str.
|
||||
* Decoding stops early when *str contains \0.
|
||||
* Illegal encoded chars are assumed to decode to zero.
|
||||
*
|
||||
* NOTE: *buf space should be at least 1 byte _more_ than *buflen
|
||||
* to hold a trailing '\0' that is added (though *buf will usually
|
||||
* contain full-binary data).
|
||||
*
|
||||
* return value : #bytes filled in buf (excluding \0)
|
||||
*/
|
||||
static int base128_decode(void *buf, size_t *buflen, const char *str,
|
||||
size_t slen)
|
||||
{
|
||||
unsigned char *ustr = (unsigned char *) str;
|
||||
unsigned char *ubuf = (unsigned char *) buf;
|
||||
int iout = 0; /* to-be-filled output byte */
|
||||
int iin = 0; /* next input char to use in decoding */
|
||||
|
||||
base128_reverse_init();
|
||||
|
||||
/* Note: Don't bother to optimize manually. GCC optimizes
|
||||
better(!) when using simplistic array indexing. */
|
||||
|
||||
while (1) {
|
||||
if (iout >= *buflen || iin + 1 >= slen ||
|
||||
str[iin] == '\0' || str[iin + 1] == '\0')
|
||||
break;
|
||||
ubuf[iout] = ((REV128(ustr[iin]) & 0x7f) << 1) |
|
||||
((REV128(ustr[iin + 1]) & 0x40) >> 6);
|
||||
iin++; /* 0 used up, iin=1 */
|
||||
iout++;
|
||||
|
||||
if (iout >= *buflen || iin + 1 >= slen ||
|
||||
str[iin] == '\0' || str[iin + 1] == '\0')
|
||||
break;
|
||||
ubuf[iout] = ((REV128(ustr[iin]) & 0x3f) << 2) |
|
||||
((REV128(ustr[iin + 1]) & 0x60) >> 5);
|
||||
iin++; /* 1 used up, iin=2 */
|
||||
iout++;
|
||||
|
||||
if (iout >= *buflen || iin + 1 >= slen ||
|
||||
str[iin] == '\0' || str[iin + 1] == '\0')
|
||||
break;
|
||||
ubuf[iout] = ((REV128(ustr[iin]) & 0x1f) << 3) |
|
||||
((REV128(ustr[iin + 1]) & 0x70) >> 4);
|
||||
iin++; /* 2 used up, iin=3 */
|
||||
iout++;
|
||||
|
||||
if (iout >= *buflen || iin + 1 >= slen ||
|
||||
str[iin] == '\0' || str[iin + 1] == '\0')
|
||||
break;
|
||||
ubuf[iout] = ((REV128(ustr[iin]) & 0x0f) << 4) |
|
||||
((REV128(ustr[iin + 1]) & 0x78) >> 3);
|
||||
iin++; /* 3 used up, iin=4 */
|
||||
iout++;
|
||||
|
||||
if (iout >= *buflen || iin + 1 >= slen ||
|
||||
str[iin] == '\0' || str[iin + 1] == '\0')
|
||||
break;
|
||||
ubuf[iout] = ((REV128(ustr[iin]) & 0x07) << 5) |
|
||||
((REV128(ustr[iin + 1]) & 0x7c) >> 2);
|
||||
iin++; /* 4 used up, iin=5 */
|
||||
iout++;
|
||||
|
||||
if (iout >= *buflen || iin + 1 >= slen ||
|
||||
str[iin] == '\0' || str[iin + 1] == '\0')
|
||||
break;
|
||||
ubuf[iout] = ((REV128(ustr[iin]) & 0x03) << 6) |
|
||||
((REV128(ustr[iin + 1]) & 0x7e) >> 1);
|
||||
iin++; /* 5 used up, iin=6 */
|
||||
iout++;
|
||||
|
||||
if (iout >= *buflen || iin + 1 >= slen ||
|
||||
str[iin] == '\0' || str[iin + 1] == '\0')
|
||||
break;
|
||||
ubuf[iout] = ((REV128(ustr[iin]) & 0x01) << 7) |
|
||||
((REV128(ustr[iin + 1]) & 0x7f));
|
||||
iin += 2; /* 6,7 used up, iin=8 */
|
||||
iout++;
|
||||
}
|
||||
|
||||
ubuf[iout] = '\0';
|
||||
|
||||
return iout;
|
||||
}
|
||||
|
||||
const struct encoder base128_ops = {
|
||||
.name = "Base128",
|
||||
|
||||
.encode = base128_encode,
|
||||
.decode = base128_decode,
|
||||
|
||||
.places_dots = false,
|
||||
.eats_dots = false,
|
||||
|
||||
.blocksize_raw = BASE128_BLKSIZE_RAW,
|
||||
.blocksize_encoded = BASE128_BLKSIZE_ENC,
|
||||
};
|
||||
238
third-party/iodine/src/base32.c
vendored
Normal file
238
third-party/iodine/src/base32.c
vendored
Normal file
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
* 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/or 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 THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "encoding.h"
|
||||
|
||||
#define BASE32_BLKSIZE_RAW 5
|
||||
#define BASE32_BLKSIZE_ENC 8
|
||||
|
||||
static const char cb32[] =
|
||||
"abcdefghijklmnopqrstuvwxyz012345";
|
||||
static const char cb32_ucase[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ012345";
|
||||
static unsigned char rev32[256];
|
||||
static int reverse_init = 0;
|
||||
|
||||
inline static void base32_reverse_init(void)
|
||||
{
|
||||
int i;
|
||||
unsigned char c;
|
||||
|
||||
if (!reverse_init) {
|
||||
memset(rev32, 0, 256);
|
||||
for (i = 0; i < 32; i++) {
|
||||
c = cb32[i];
|
||||
rev32[(int) c] = i;
|
||||
c = cb32_ucase[i];
|
||||
rev32[(int) c] = i;
|
||||
}
|
||||
reverse_init = 1;
|
||||
}
|
||||
}
|
||||
|
||||
int b32_5to8(int in)
|
||||
{
|
||||
return cb32[in & 31];
|
||||
}
|
||||
|
||||
int b32_8to5(int in)
|
||||
{
|
||||
base32_reverse_init();
|
||||
return rev32[in];
|
||||
}
|
||||
|
||||
/*
|
||||
* Fills *buf with max. *buflen characters, encoding size bytes of *data.
|
||||
*
|
||||
* NOTE: *buf space should be at least 1 byte _more_ than *buflen
|
||||
* to hold the trailing '\0'.
|
||||
*
|
||||
* return value : #bytes filled in buf (excluding \0)
|
||||
* sets *buflen to : #bytes encoded from data
|
||||
*/
|
||||
static int base32_encode(char *buf, size_t *buflen, const void *data, size_t size)
|
||||
{
|
||||
unsigned char *udata = (unsigned char *) data;
|
||||
int iout = 0; /* to-be-filled output char */
|
||||
int iin = 0; /* one more than last input byte that can be
|
||||
successfully decoded */
|
||||
|
||||
/* Note: Don't bother to optimize manually. GCC optimizes
|
||||
better(!) when using simplistic array indexing. */
|
||||
|
||||
while (1) {
|
||||
if (iout >= *buflen || iin >= size)
|
||||
break;
|
||||
buf[iout] = cb32[((udata[iin] & 0xf8) >> 3)];
|
||||
iout++;
|
||||
|
||||
if (iout >= *buflen || iin >= size) {
|
||||
iout--; /* previous char is useless */
|
||||
break;
|
||||
}
|
||||
buf[iout] = cb32[((udata[iin] & 0x07) << 2) |
|
||||
((iin + 1 < size) ?
|
||||
((udata[iin + 1] & 0xc0) >> 6) : 0)];
|
||||
iin++; /* 0 complete, iin=1 */
|
||||
iout++;
|
||||
|
||||
if (iout >= *buflen || iin >= size)
|
||||
break;
|
||||
buf[iout] = cb32[((udata[iin] & 0x3e) >> 1)];
|
||||
iout++;
|
||||
|
||||
if (iout >= *buflen || iin >= size) {
|
||||
iout--; /* previous char is useless */
|
||||
break;
|
||||
}
|
||||
buf[iout] = cb32[((udata[iin] & 0x01) << 4) |
|
||||
((iin + 1 < size) ?
|
||||
((udata[iin + 1] & 0xf0) >> 4) : 0)];
|
||||
iin++; /* 1 complete, iin=2 */
|
||||
iout++;
|
||||
|
||||
if (iout >= *buflen || iin >= size)
|
||||
break;
|
||||
buf[iout] = cb32[((udata[iin] & 0x0f) << 1) |
|
||||
((iin + 1 < size) ?
|
||||
((udata[iin + 1] & 0x80) >> 7) : 0)];
|
||||
iin++; /* 2 complete, iin=3 */
|
||||
iout++;
|
||||
|
||||
if (iout >= *buflen || iin >= size)
|
||||
break;
|
||||
buf[iout] = cb32[((udata[iin] & 0x7c) >> 2)];
|
||||
iout++;
|
||||
|
||||
if (iout >= *buflen || iin >= size) {
|
||||
iout--; /* previous char is useless */
|
||||
break;
|
||||
}
|
||||
buf[iout] = cb32[((udata[iin] & 0x03) << 3) |
|
||||
((iin + 1 < size) ?
|
||||
((udata[iin + 1] & 0xe0) >> 5) : 0)];
|
||||
iin++; /* 3 complete, iin=4 */
|
||||
iout++;
|
||||
|
||||
if (iout >= *buflen || iin >= size)
|
||||
break;
|
||||
buf[iout] = cb32[((udata[iin] & 0x1f))];
|
||||
iin++; /* 4 complete, iin=5 */
|
||||
iout++;
|
||||
}
|
||||
|
||||
buf[iout] = '\0';
|
||||
|
||||
/* store number of bytes from data that was used */
|
||||
*buflen = iin;
|
||||
|
||||
return iout;
|
||||
}
|
||||
|
||||
#define REV32(x) rev32[(int) (x)]
|
||||
|
||||
/*
|
||||
* Fills *buf with max. *buflen bytes, decoded from slen chars in *str.
|
||||
* Decoding stops early when *str contains \0.
|
||||
* Illegal encoded chars are assumed to decode to zero.
|
||||
*
|
||||
* NOTE: *buf space should be at least 1 byte _more_ than *buflen
|
||||
* to hold a trailing '\0' that is added (though *buf will usually
|
||||
* contain full-binary data).
|
||||
*
|
||||
* return value : #bytes filled in buf (excluding \0)
|
||||
*/
|
||||
static int base32_decode(void *buf, size_t *buflen, const char *str,
|
||||
size_t slen)
|
||||
{
|
||||
unsigned char *ubuf = (unsigned char *) buf;
|
||||
int iout = 0; /* to-be-filled output byte */
|
||||
int iin = 0; /* next input char to use in decoding */
|
||||
|
||||
base32_reverse_init();
|
||||
|
||||
/* Note: Don't bother to optimize manually. GCC optimizes
|
||||
better(!) when using simplistic array indexing. */
|
||||
|
||||
while (1) {
|
||||
if (iout >= *buflen || iin + 1 >= slen ||
|
||||
str[iin] == '\0' || str[iin + 1] == '\0')
|
||||
break;
|
||||
ubuf[iout] = ((REV32(str[iin]) & 0x1f) << 3) |
|
||||
((REV32(str[iin + 1]) & 0x1c) >> 2);
|
||||
iin++; /* 0 used up, iin=1 */
|
||||
iout++;
|
||||
|
||||
if (iout >= *buflen || iin + 2 >= 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) |
|
||||
((REV32(str[iin + 2]) & 0x10) >> 4);
|
||||
iin += 2; /* 1,2 used up, iin=3 */
|
||||
iout++;
|
||||
|
||||
if (iout >= *buflen || iin + 1 >= slen ||
|
||||
str[iin] == '\0' || str[iin + 1] == '\0')
|
||||
break;
|
||||
ubuf[iout] = ((REV32(str[iin]) & 0x0f) << 4) |
|
||||
((REV32(str[iin + 1]) & 0x1e) >> 1);
|
||||
iin++; /* 3 used up, iin=4 */
|
||||
iout++;
|
||||
|
||||
if (iout >= *buflen || iin + 2 >= slen ||
|
||||
str[iin] == '\0' || str[iin + 1] == '\0' ||
|
||||
str[iin + 2] == '\0')
|
||||
break;
|
||||
ubuf[iout] = ((REV32(str[iin]) & 0x01) << 7) |
|
||||
((REV32(str[iin + 1]) & 0x1f) << 2) |
|
||||
((REV32(str[iin + 2]) & 0x18) >> 3);
|
||||
iin += 2; /* 4,5 used up, iin=6 */
|
||||
iout++;
|
||||
|
||||
if (iout >= *buflen || iin + 1 >= slen ||
|
||||
str[iin] == '\0' || str[iin + 1] == '\0')
|
||||
break;
|
||||
ubuf[iout] = ((REV32(str[iin]) & 0x07) << 5) |
|
||||
((REV32(str[iin + 1]) & 0x1f));
|
||||
iin += 2; /* 6,7 used up, iin=8 */
|
||||
iout++;
|
||||
}
|
||||
|
||||
ubuf[iout] = '\0';
|
||||
|
||||
return iout;
|
||||
}
|
||||
|
||||
const struct encoder base32_ops = {
|
||||
.name = "Base32",
|
||||
|
||||
.encode = base32_encode,
|
||||
.decode = base32_decode,
|
||||
|
||||
.places_dots = false,
|
||||
.eats_dots = false,
|
||||
|
||||
.blocksize_raw = BASE32_BLKSIZE_RAW,
|
||||
.blocksize_encoded = BASE32_BLKSIZE_ENC,
|
||||
};
|
||||
176
third-party/iodine/src/base64.c
vendored
Normal file
176
third-party/iodine/src/base64.c
vendored
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* 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/or 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 THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "encoding.h"
|
||||
|
||||
#define BASE64_BLKSIZE_RAW 3
|
||||
#define BASE64_BLKSIZE_ENC 4
|
||||
|
||||
/* 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[] =
|
||||
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789+";
|
||||
static unsigned char rev64[256];
|
||||
static int reverse_init = 0;
|
||||
|
||||
inline static void base64_reverse_init(void)
|
||||
{
|
||||
int i;
|
||||
unsigned char c;
|
||||
|
||||
if (!reverse_init) {
|
||||
memset(rev64, 0, 256);
|
||||
for (i = 0; i < 64; i++) {
|
||||
c = cb64[i];
|
||||
rev64[(int) c] = i;
|
||||
}
|
||||
reverse_init = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Fills *buf with max. *buflen characters, encoding size bytes of *data.
|
||||
*
|
||||
* NOTE: *buf space should be at least 1 byte _more_ than *buflen
|
||||
* to hold the trailing '\0'.
|
||||
*
|
||||
* return value : #bytes filled in buf (excluding \0)
|
||||
* sets *buflen to : #bytes encoded from data
|
||||
*/
|
||||
static int base64_encode(char *buf, size_t *buflen, const void *data,
|
||||
size_t size)
|
||||
{
|
||||
unsigned char *udata = (unsigned char *) data;
|
||||
int iout = 0; /* to-be-filled output char */
|
||||
int iin = 0; /* one more than last input byte that can be
|
||||
successfully decoded */
|
||||
|
||||
/* Note: Don't bother to optimize manually. GCC optimizes
|
||||
better(!) when using simplistic array indexing. */
|
||||
|
||||
while (1) {
|
||||
if (iout >= *buflen || iin >= size)
|
||||
break;
|
||||
buf[iout] = cb64[((udata[iin] & 0xfc) >> 2)];
|
||||
iout++;
|
||||
|
||||
if (iout >= *buflen || iin >= size) {
|
||||
iout--; /* previous char is useless */
|
||||
break;
|
||||
}
|
||||
buf[iout] = cb64[((udata[iin] & 0x03) << 4) |
|
||||
((iin + 1 < size) ?
|
||||
((udata[iin + 1] & 0xf0) >> 4) : 0)];
|
||||
iin++; /* 0 complete, iin=1 */
|
||||
iout++;
|
||||
|
||||
if (iout >= *buflen || iin >= size)
|
||||
break;
|
||||
buf[iout] = cb64[((udata[iin] & 0x0f) << 2) |
|
||||
((iin + 1 < size) ?
|
||||
((udata[iin + 1] & 0xc0) >> 6) : 0)];
|
||||
iin++; /* 1 complete, iin=2 */
|
||||
iout++;
|
||||
|
||||
if (iout >= *buflen || iin >= size)
|
||||
break;
|
||||
buf[iout] = cb64[(udata[iin] & 0x3f)];
|
||||
iin++; /* 2 complete, iin=3 */
|
||||
iout++;
|
||||
}
|
||||
|
||||
buf[iout] = '\0';
|
||||
|
||||
/* store number of bytes from data that was used */
|
||||
*buflen = iin;
|
||||
|
||||
return iout;
|
||||
}
|
||||
|
||||
#define REV64(x) rev64[(int) (x)]
|
||||
|
||||
/*
|
||||
* Fills *buf with max. *buflen bytes, decoded from slen chars in *str.
|
||||
* Decoding stops early when *str contains \0.
|
||||
* Illegal encoded chars are assumed to decode to zero.
|
||||
*
|
||||
* NOTE: *buf space should be at least 1 byte _more_ than *buflen
|
||||
* to hold a trailing '\0' that is added (though *buf will usually
|
||||
* contain full-binary data).
|
||||
*
|
||||
* return value : #bytes filled in buf (excluding \0)
|
||||
*/
|
||||
static int base64_decode(void *buf, size_t *buflen, const char *str,
|
||||
size_t slen)
|
||||
{
|
||||
unsigned char *ubuf = (unsigned char *) buf;
|
||||
int iout = 0; /* to-be-filled output byte */
|
||||
int iin = 0; /* next input char to use in decoding */
|
||||
|
||||
base64_reverse_init();
|
||||
|
||||
/* Note: Don't bother to optimize manually. GCC optimizes
|
||||
better(!) when using simplistic array indexing. */
|
||||
|
||||
while (1) {
|
||||
if (iout >= *buflen || iin + 1 >= slen ||
|
||||
str[iin] == '\0' || str[iin + 1] == '\0')
|
||||
break;
|
||||
ubuf[iout] = ((REV64(str[iin]) & 0x3f) << 2) |
|
||||
((REV64(str[iin + 1]) & 0x30) >> 4);
|
||||
iin++; /* 0 used up, iin=1 */
|
||||
iout++;
|
||||
|
||||
if (iout >= *buflen || iin + 1 >= slen ||
|
||||
str[iin] == '\0' || str[iin + 1] == '\0')
|
||||
break;
|
||||
ubuf[iout] = ((REV64(str[iin]) & 0x0f) << 4) |
|
||||
((REV64(str[iin + 1]) & 0x3c) >> 2);
|
||||
iin++; /* 1 used up, iin=2 */
|
||||
iout++;
|
||||
|
||||
if (iout >= *buflen || iin + 1 >= slen ||
|
||||
str[iin] == '\0' || str[iin + 1] == '\0')
|
||||
break;
|
||||
ubuf[iout] = ((REV64(str[iin]) & 0x03) << 6) |
|
||||
(REV64(str[iin + 1]) & 0x3f);
|
||||
iin += 2; /* 2,3 used up, iin=4 */
|
||||
iout++;
|
||||
}
|
||||
|
||||
ubuf[iout] = '\0';
|
||||
|
||||
return iout;
|
||||
}
|
||||
|
||||
const struct encoder base64_ops = {
|
||||
.name = "Base64",
|
||||
|
||||
.encode = base64_encode,
|
||||
.decode = base64_decode,
|
||||
|
||||
.places_dots = false,
|
||||
.eats_dots = false,
|
||||
|
||||
.blocksize_raw = BASE64_BLKSIZE_RAW,
|
||||
.blocksize_encoded = BASE64_BLKSIZE_ENC,
|
||||
};
|
||||
2421
third-party/iodine/src/client.c
vendored
Normal file
2421
third-party/iodine/src/client.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
41
third-party/iodine/src/client.h
vendored
Normal file
41
third-party/iodine/src/client.h
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
|
||||
*/
|
||||
|
||||
#ifndef __CLIENT_H__
|
||||
#define __CLIENT_H__
|
||||
|
||||
void client_init(void);
|
||||
void client_stop(void);
|
||||
|
||||
enum connection client_get_conn(void);
|
||||
const char *client_get_raw_addr(void);
|
||||
|
||||
void client_set_nameserver(struct sockaddr_storage *, int);
|
||||
void client_set_topdomain(const char *cp);
|
||||
void client_set_password(const char *cp);
|
||||
int client_set_qtype(char *qtype);
|
||||
char *client_get_qtype(void);
|
||||
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);
|
||||
|
||||
int client_handshake(int dns_fd, int raw_mode, int autodetect_frag_size,
|
||||
int fragsize);
|
||||
int client_tunnel(int tun_fd, int dns_fd);
|
||||
|
||||
#endif
|
||||
561
third-party/iodine/src/common.c
vendored
Normal file
561
third-party/iodine/src/common.c
vendored
Normal file
@@ -0,0 +1,561 @@
|
||||
/* 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/or 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 THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
|
||||
*/
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef WINDOWS32
|
||||
#include <winsock2.h>
|
||||
#include <conio.h>
|
||||
#else
|
||||
#include <arpa/nameser.h>
|
||||
#ifdef DARWIN
|
||||
#define BIND_8_COMPAT
|
||||
#include <arpa/nameser_compat.h>
|
||||
#endif
|
||||
#include <termios.h>
|
||||
#include <err.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <syslog.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SETCON
|
||||
# include <selinux/selinux.h>
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/* The raw header used when not using DNS protocol */
|
||||
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(ANDROID) && !defined(WINDOWS32) && !(defined(BSD) && (BSD >= 199306)) && !defined(__GLIBC__) && !defined(__HAIKU__)
|
||||
static int daemon(int nochdir, int noclose)
|
||||
{
|
||||
int fd, i;
|
||||
|
||||
switch (fork()) {
|
||||
case 0:
|
||||
break;
|
||||
case -1:
|
||||
return -1;
|
||||
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++) {
|
||||
dup2(fd, i);
|
||||
}
|
||||
if (fd > 2) {
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__BEOS__) && !defined(__HAIKU__)
|
||||
int setgroups(int count, int *groups)
|
||||
{
|
||||
/* errno = ENOSYS; */
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef WINDOWS32
|
||||
void
|
||||
check_superuser(void)
|
||||
{
|
||||
if (geteuid() != 0) {
|
||||
warnx("Run as root and you'll be happy.");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
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];
|
||||
int addrlen;
|
||||
|
||||
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) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
addrlen = addr->ai_addrlen;
|
||||
/* Grab first result */
|
||||
memcpy(out, addr->ai_addr, addr->ai_addrlen);
|
||||
freeaddrinfo(addr);
|
||||
return addrlen;
|
||||
}
|
||||
|
||||
int
|
||||
open_dns(struct sockaddr_storage *sockaddr, size_t sockaddr_len)
|
||||
{
|
||||
return open_dns_opt(sockaddr, sockaddr_len, -1);
|
||||
}
|
||||
|
||||
int
|
||||
open_dns_opt(struct sockaddr_storage *sockaddr, size_t sockaddr_len, int v6only)
|
||||
{
|
||||
int flag;
|
||||
int fd;
|
||||
|
||||
if ((fd = socket(sockaddr->ss_family, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
|
||||
err(1, "socket");
|
||||
}
|
||||
|
||||
flag = 1;
|
||||
#ifdef SO_REUSEPORT
|
||||
setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (const void*) &flag, sizeof(flag));
|
||||
#endif
|
||||
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void*) &flag, sizeof(flag));
|
||||
|
||||
#ifndef WINDOWS32
|
||||
fd_set_close_on_exec(fd);
|
||||
#endif
|
||||
|
||||
if (sockaddr->ss_family == AF_INET6 && v6only >= 0) {
|
||||
setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (const void*) &v6only, sizeof(v6only));
|
||||
}
|
||||
|
||||
#ifdef IP_OPT_DONT_FRAG
|
||||
/* Set dont-fragment ip header flag */
|
||||
flag = DONT_FRAG_VALUE;
|
||||
setsockopt(fd, IPPROTO_IP, IP_OPT_DONT_FRAG, (const void*) &flag, sizeof(flag));
|
||||
#endif
|
||||
|
||||
if (bind(fd, (struct sockaddr*) sockaddr, sockaddr_len) < 0)
|
||||
err(1, "bind() to %s", format_addr(sockaddr, sockaddr_len));
|
||||
|
||||
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)
|
||||
{
|
||||
close(fd);
|
||||
}
|
||||
|
||||
void
|
||||
do_chroot(char *newroot)
|
||||
{
|
||||
#if !(defined(WINDOWS32) || defined(__BEOS__) || defined(__HAIKU__))
|
||||
if (chroot(newroot) != 0 || chdir("/") != 0)
|
||||
err(1, "%s", newroot);
|
||||
|
||||
if (seteuid(geteuid()) != 0 || setuid(getuid()) != 0) {
|
||||
err(1, "set[e]uid()");
|
||||
}
|
||||
#else
|
||||
warnx("chroot not available");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
do_setcon(char *context)
|
||||
{
|
||||
#ifdef HAVE_SETCON
|
||||
if (-1 == setcon(context))
|
||||
err(1, "%s", context);
|
||||
#else
|
||||
warnx("No SELinux support built in");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
do_pidfile(char *pidfile)
|
||||
{
|
||||
#ifndef WINDOWS32
|
||||
FILE *file;
|
||||
|
||||
if ((file = fopen(pidfile, "w")) == NULL) {
|
||||
syslog(LOG_ERR, "Cannot write pidfile to %s, exiting", pidfile);
|
||||
err(1, "do_pidfile: Can not write pidfile to %s", pidfile);
|
||||
} else {
|
||||
fprintf(file, "%d\n", (int)getpid());
|
||||
fclose(file);
|
||||
}
|
||||
#else
|
||||
fprintf(stderr, "Windows version does not support pid file\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
do_detach(void)
|
||||
{
|
||||
#ifndef WINDOWS32
|
||||
fprintf(stderr, "Detaching from terminal...\n");
|
||||
daemon(0, 0);
|
||||
umask(0);
|
||||
alarm(0);
|
||||
#else
|
||||
fprintf(stderr, "Windows version does not support detaching\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
read_password(char *buf, size_t len)
|
||||
{
|
||||
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
|
||||
int i;
|
||||
#endif
|
||||
|
||||
fprintf(stderr, "Enter tunnel password: ");
|
||||
fflush(stderr);
|
||||
#ifndef WINDOWS32
|
||||
fscanf(stdin, "%79[^\n]", pwd);
|
||||
#else
|
||||
for (i = 0; i < sizeof(pwd); i++) {
|
||||
pwd[i] = getch();
|
||||
if (pwd[i] == '\r' || pwd[i] == '\n') {
|
||||
pwd[i] = 0;
|
||||
break;
|
||||
} else if (pwd[i] == '\b') {
|
||||
i--; /* Remove the \b char */
|
||||
if (i >=0) i--; /* If not first char, remove one more */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
#ifndef WINDOWS32
|
||||
tcsetattr(0, TCSANOW, &old);
|
||||
#endif
|
||||
|
||||
strncpy(buf, pwd, len);
|
||||
buf[len-1] = '\0';
|
||||
}
|
||||
|
||||
int
|
||||
check_topdomain(char *str, int allow_wildcard, char **errormsg)
|
||||
{
|
||||
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 (allow_wildcard && str[i] == '*') {
|
||||
/* First char allowed to be wildcard, if followed by dot */
|
||||
if (i == 0) {
|
||||
if (str[i+1] == '.') {
|
||||
continue;
|
||||
}
|
||||
if (errormsg) *errormsg = "Wildcard (*) must be followed by dot";
|
||||
return 1;
|
||||
} else {
|
||||
if (errormsg) *errormsg = "Wildcard (*) only allowed as first char";
|
||||
return 1;
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
|
||||
int
|
||||
query_datalen(const char *qname, const char *topdomain)
|
||||
{
|
||||
/* Return number of data bytes embedded in DNS query name,
|
||||
* or -1 if domains do not match.
|
||||
*/
|
||||
int qpos = strlen(qname);
|
||||
int tpos = strlen(topdomain);
|
||||
if (tpos < 3 || qpos < tpos) {
|
||||
/* Domain or query name too short */
|
||||
return -1;
|
||||
}
|
||||
/* Backward string compare */
|
||||
qpos--;
|
||||
tpos--;
|
||||
while (qpos >= 0) {
|
||||
if (topdomain[tpos] == '*') {
|
||||
/* Wild match, is first in topdomain */
|
||||
if (qname[qpos] == '*') {
|
||||
/* Don't match against stars in query name */
|
||||
return -1;
|
||||
} else if (qpos == 0 || qname[qpos-1] == '.') {
|
||||
/* Reached start of query name or chunk separator */
|
||||
return qpos;
|
||||
}
|
||||
qpos--;
|
||||
} else if (tolower(qname[qpos]) == tolower(topdomain[tpos])) {
|
||||
/* Matching char, exclude wildcard in query name */
|
||||
if (tpos == 0) {
|
||||
/* Fully matched domain */
|
||||
if (qpos == 0 || qname[qpos-1] == '.') {
|
||||
/* Start of name or has dot before matching topdomain */
|
||||
return qpos;
|
||||
}
|
||||
/* Query name has longer chunk than topdomain */
|
||||
return -1;
|
||||
}
|
||||
tpos--;
|
||||
qpos--;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#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
|
||||
vwarn(const char *fmt, va_list list)
|
||||
{
|
||||
if (fmt) vfprintf(stderr, fmt, list);
|
||||
#ifndef ANDROID
|
||||
if (errno == 0) {
|
||||
fprintf(stderr, ": WSA error %d\n", WSAGetLastError());
|
||||
} else {
|
||||
fprintf(stderr, ": %s\n", strerror(errno));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
warn(const char *fmt, ...)
|
||||
{
|
||||
va_list list;
|
||||
|
||||
va_start(list, fmt);
|
||||
vwarn(fmt, list);
|
||||
va_end(list);
|
||||
}
|
||||
|
||||
void
|
||||
err(int eval, const char *fmt, ...)
|
||||
{
|
||||
va_list list;
|
||||
|
||||
va_start(list, fmt);
|
||||
vwarn(fmt, list);
|
||||
va_end(list);
|
||||
exit(eval);
|
||||
}
|
||||
|
||||
void
|
||||
vwarnx(const char *fmt, va_list list)
|
||||
{
|
||||
if (fmt) vfprintf(stderr, fmt, list);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
void
|
||||
warnx(const char *fmt, ...)
|
||||
{
|
||||
va_list list;
|
||||
|
||||
va_start(list, fmt);
|
||||
vwarnx(fmt, list);
|
||||
va_end(list);
|
||||
}
|
||||
|
||||
void
|
||||
errx(int eval, const char *fmt, ...)
|
||||
{
|
||||
va_list list;
|
||||
|
||||
va_start(list, fmt);
|
||||
vwarnx(fmt, list);
|
||||
va_end(list);
|
||||
exit(eval);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int recent_seqno(int ourseqno, int gotseqno)
|
||||
/* Return 1 if we've seen gotseqno recently (current or up to 3 back).
|
||||
Return 0 if gotseqno is new (or very old).
|
||||
*/
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 4; i++, ourseqno--) {
|
||||
if (ourseqno < 0)
|
||||
ourseqno = 7;
|
||||
if (gotseqno == ourseqno)
|
||||
return 1;
|
||||
}
|
||||
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
|
||||
|
||||
152
third-party/iodine/src/common.h
vendored
Normal file
152
third-party/iodine/src/common.h
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2015 Erik Ekman <yarrick@kryo.se>,
|
||||
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
|
||||
*/
|
||||
|
||||
#ifndef __COMMON_H__
|
||||
#define __COMMON_H__
|
||||
|
||||
/* Last byte of raw header is the command */
|
||||
#define RAW_HDR_LEN 4
|
||||
#define RAW_HDR_IDENT_LEN 3
|
||||
#define RAW_HDR_CMD 3
|
||||
#define RAW_HDR_CMD_LOGIN 0x10
|
||||
#define RAW_HDR_CMD_DATA 0x20
|
||||
#define RAW_HDR_CMD_PING 0x30
|
||||
|
||||
#define RAW_HDR_CMD_MASK 0xF0
|
||||
#define RAW_HDR_USR_MASK 0x0F
|
||||
#define RAW_HDR_GET_CMD(x) ((x)[RAW_HDR_CMD] & RAW_HDR_CMD_MASK)
|
||||
#define RAW_HDR_GET_USR(x) ((x)[RAW_HDR_CMD] & RAW_HDR_USR_MASK)
|
||||
extern const unsigned char raw_header[RAW_HDR_LEN];
|
||||
|
||||
#include <stdarg.h>
|
||||
#ifdef WINDOWS32
|
||||
#include "windows.h"
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <err.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#define DNS_PORT 53
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) ((a)<(b)?(a):(b))
|
||||
#endif
|
||||
#ifndef MAX
|
||||
#define MAX(a,b) ((a)>(b)?(a):(b))
|
||||
#endif
|
||||
|
||||
#define QUERY_NAME_SIZE 256
|
||||
|
||||
#if defined IP_MTU_DISCOVER
|
||||
/* Linux */
|
||||
# define IP_OPT_DONT_FRAG IP_MTU_DISCOVER
|
||||
# define DONT_FRAG_VALUE IP_PMTUDISC_DO
|
||||
#elif defined IP_DONTFRAG
|
||||
/* FreeBSD */
|
||||
# define IP_OPT_DONT_FRAG IP_DONTFRAG
|
||||
# define DONT_FRAG_VALUE 1
|
||||
#elif defined IP_DONTFRAGMENT
|
||||
/* Winsock2 */
|
||||
# define IP_OPT_DONT_FRAG IP_DONTFRAGMENT
|
||||
# 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, never actually sent */
|
||||
|
||||
struct packet
|
||||
{
|
||||
int len; /* Total packet length */
|
||||
int sentlen; /* Length of chunk currently transmitted */
|
||||
int offset; /* Current offset */
|
||||
char data[64*1024]; /* The data */
|
||||
char seqno; /* The packet sequence number */
|
||||
char fragment; /* Fragment index */
|
||||
};
|
||||
|
||||
struct query {
|
||||
char name[QUERY_NAME_SIZE];
|
||||
unsigned short type;
|
||||
unsigned short rcode;
|
||||
unsigned short id;
|
||||
struct sockaddr_storage destination;
|
||||
socklen_t dest_len;
|
||||
struct sockaddr_storage from;
|
||||
socklen_t fromlen;
|
||||
unsigned short id2;
|
||||
struct sockaddr_storage from2;
|
||||
socklen_t fromlen2;
|
||||
};
|
||||
|
||||
enum connection {
|
||||
CONN_RAW_UDP = 0,
|
||||
CONN_DNS_NULL,
|
||||
CONN_MAX
|
||||
};
|
||||
|
||||
#ifdef WINDOWS32
|
||||
static inline void check_superuser(void)
|
||||
{
|
||||
}
|
||||
#else
|
||||
void check_superuser(void);
|
||||
#endif
|
||||
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_opt(struct sockaddr_storage *sockaddr, size_t sockaddr_len,
|
||||
int v6only);
|
||||
int open_dns_from_host(char *host, int port, int addr_family, int flags);
|
||||
void close_dns(int);
|
||||
|
||||
void do_chroot(char *);
|
||||
void do_setcon(char *);
|
||||
void do_detach(void);
|
||||
void do_pidfile(char *);
|
||||
|
||||
void read_password(char*, size_t);
|
||||
|
||||
int check_topdomain(char *, int, char **);
|
||||
|
||||
int query_datalen(const char *qname, const char *topdomain);
|
||||
|
||||
#if defined(WINDOWS32) || defined(ANDROID)
|
||||
#ifndef ANDROID
|
||||
int inet_aton(const char *cp, struct in_addr *inp);
|
||||
#endif
|
||||
|
||||
void vwarn(const char *fmt, va_list list);
|
||||
void warn(const char *fmt, ...);
|
||||
void err(int eval, const char *fmt, ...);
|
||||
void vwarnx(const char *fmt, va_list list);
|
||||
void warnx(const char *fmt, ...);
|
||||
void errx(int eval, const char *fmt, ...);
|
||||
#endif
|
||||
|
||||
int recent_seqno(int , int);
|
||||
|
||||
#ifndef WINDOWS32
|
||||
void fd_set_close_on_exec(int fd);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
706
third-party/iodine/src/dns.c
vendored
Normal file
706
third-party/iodine/src/dns.c
vendored
Normal file
@@ -0,0 +1,706 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
|
||||
*/
|
||||
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#ifdef WINDOWS32
|
||||
#include "windows.h"
|
||||
#else
|
||||
#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>
|
||||
#ifdef ANDROID
|
||||
#include "android_dns.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#include "dns.h"
|
||||
#include "encoding.h"
|
||||
#include "read.h"
|
||||
|
||||
int dnsc_use_edns0 = 1;
|
||||
|
||||
#define CHECKLEN(x) if (buflen < (x) + (size_t)(p-buf)) return 0
|
||||
|
||||
int dns_encode(char *buf, size_t buflen, struct query *q, qr_t qr,
|
||||
const char *data, size_t datalen)
|
||||
{
|
||||
HEADER *header;
|
||||
short name;
|
||||
char *p;
|
||||
int len;
|
||||
int ancnt;
|
||||
|
||||
if (buflen < sizeof(HEADER))
|
||||
return 0;
|
||||
|
||||
memset(buf, 0, buflen);
|
||||
|
||||
header = (HEADER*)buf;
|
||||
|
||||
header->id = htons(q->id);
|
||||
header->qr = (qr == QR_ANSWER);
|
||||
header->opcode = 0;
|
||||
header->aa = (qr == QR_ANSWER);
|
||||
header->tc = 0;
|
||||
header->rd = (qr == QR_QUERY);
|
||||
header->ra = 0;
|
||||
|
||||
p = buf + sizeof(HEADER);
|
||||
|
||||
switch (qr) {
|
||||
case QR_ANSWER:
|
||||
header->qdcount = htons(1);
|
||||
|
||||
name = 0xc000 | ((p - buf) & 0x3fff);
|
||||
|
||||
/* Question section */
|
||||
putname(&p, buflen - (p - buf), q->name);
|
||||
|
||||
CHECKLEN(4);
|
||||
putshort(&p, q->type);
|
||||
putshort(&p, C_IN);
|
||||
|
||||
/* Answer section */
|
||||
|
||||
if (q->type == T_CNAME || q->type == T_A) {
|
||||
/* data is expected to be like
|
||||
* "Hblabla.host.name.com\0" */
|
||||
|
||||
char *startp;
|
||||
int namelen;
|
||||
|
||||
CHECKLEN(10);
|
||||
putshort(&p, name);
|
||||
if (q->type == T_A)
|
||||
/* answer CNAME to A question */
|
||||
putshort(&p, T_CNAME);
|
||||
else
|
||||
putshort(&p, q->type);
|
||||
putshort(&p, C_IN);
|
||||
putlong(&p, 0); /* TTL */
|
||||
|
||||
startp = p;
|
||||
p += 2; /* skip 2 bytes length */
|
||||
putname(&p, buflen - (p - buf), data);
|
||||
CHECKLEN(0);
|
||||
namelen = p - startp;
|
||||
namelen -= 2;
|
||||
putshort(&startp, namelen);
|
||||
ancnt = 1;
|
||||
} else if (q->type == T_MX || q->type == T_SRV) {
|
||||
/* Data is expected to be like
|
||||
"Hblabla.host.name.com\0Hanother.com\0\0"
|
||||
For SRV, see RFC2782.
|
||||
*/
|
||||
|
||||
const char *mxdata = data;
|
||||
char *startp;
|
||||
int namelen;
|
||||
|
||||
ancnt = 1;
|
||||
while (1) {
|
||||
CHECKLEN(10);
|
||||
putshort(&p, name);
|
||||
putshort(&p, q->type);
|
||||
putshort(&p, C_IN);
|
||||
putlong(&p, 0); /* TTL */
|
||||
|
||||
startp = p;
|
||||
p += 2; /* skip 2 bytes length */
|
||||
CHECKLEN(2);
|
||||
putshort(&p, 10 * ancnt); /* preference */
|
||||
|
||||
if (q->type == T_SRV) {
|
||||
/* weight, port (5060 = SIP) */
|
||||
CHECKLEN(4);
|
||||
putshort(&p, 10);
|
||||
putshort(&p, 5060);
|
||||
}
|
||||
|
||||
putname(&p, buflen - (p - buf), mxdata);
|
||||
CHECKLEN(0);
|
||||
namelen = p - startp;
|
||||
namelen -= 2;
|
||||
putshort(&startp, namelen);
|
||||
|
||||
mxdata = mxdata + strlen(mxdata) + 1;
|
||||
if (*mxdata == '\0')
|
||||
break;
|
||||
|
||||
ancnt++;
|
||||
}
|
||||
} else if (q->type == T_TXT) {
|
||||
/* TXT has binary or base-X data */
|
||||
char *startp;
|
||||
int txtlen;
|
||||
|
||||
CHECKLEN(10);
|
||||
putshort(&p, name);
|
||||
putshort(&p, q->type);
|
||||
putshort(&p, C_IN);
|
||||
putlong(&p, 0); /* TTL */
|
||||
|
||||
startp = p;
|
||||
p += 2; /* skip 2 bytes length */
|
||||
puttxtbin(&p, buflen - (p - buf), data, datalen);
|
||||
CHECKLEN(0);
|
||||
txtlen = p - startp;
|
||||
txtlen -= 2;
|
||||
putshort(&startp, txtlen);
|
||||
ancnt = 1;
|
||||
} else {
|
||||
/* NULL has raw binary data */
|
||||
CHECKLEN(10);
|
||||
putshort(&p, name);
|
||||
putshort(&p, q->type);
|
||||
putshort(&p, C_IN);
|
||||
putlong(&p, 0); /* TTL */
|
||||
|
||||
datalen = MIN(datalen, buflen - (p - buf));
|
||||
CHECKLEN(2);
|
||||
putshort(&p, datalen);
|
||||
CHECKLEN(datalen);
|
||||
putdata(&p, data, datalen);
|
||||
CHECKLEN(0);
|
||||
ancnt = 1;
|
||||
}
|
||||
header->ancount = htons(ancnt);
|
||||
break;
|
||||
case QR_QUERY:
|
||||
/* Note that iodined also uses this for forward queries */
|
||||
|
||||
header->qdcount = htons(1);
|
||||
|
||||
datalen = MIN(datalen, buflen - (p - buf));
|
||||
putname(&p, datalen, data);
|
||||
|
||||
CHECKLEN(4);
|
||||
putshort(&p, q->type);
|
||||
putshort(&p, C_IN);
|
||||
|
||||
/* EDNS0 to advertise maximum response length
|
||||
(even CNAME/A/MX, 255+255+header would be >512) */
|
||||
if (dnsc_use_edns0) {
|
||||
header->arcount = htons(1);
|
||||
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;
|
||||
}
|
||||
|
||||
/* Only used when iodined gets an NS type query */
|
||||
/* Mostly same as dns_encode_a_response() below */
|
||||
int dns_encode_ns_response(char *buf, size_t buflen, struct query *q,
|
||||
char *topdomain)
|
||||
{
|
||||
HEADER *header;
|
||||
int len;
|
||||
short name;
|
||||
short topname;
|
||||
short nsname;
|
||||
char *ipp;
|
||||
int domain_len;
|
||||
char *p;
|
||||
|
||||
if (buflen < sizeof(HEADER))
|
||||
return 0;
|
||||
|
||||
memset(buf, 0, buflen);
|
||||
|
||||
header = (HEADER*)buf;
|
||||
|
||||
header->id = htons(q->id);
|
||||
header->qr = 1;
|
||||
header->opcode = 0;
|
||||
header->aa = 1;
|
||||
header->tc = 0;
|
||||
header->rd = 0;
|
||||
header->ra = 0;
|
||||
|
||||
p = buf + sizeof(HEADER);
|
||||
|
||||
header->qdcount = htons(1);
|
||||
header->ancount = htons(1);
|
||||
|
||||
/* pointer to start of name */
|
||||
name = 0xc000 | ((p - buf) & 0x3fff);
|
||||
|
||||
domain_len = strlen(q->name) - strlen(topdomain);
|
||||
if (domain_len < 0 || domain_len == 1)
|
||||
return -1;
|
||||
if (strcasecmp(q->name + domain_len, topdomain))
|
||||
return -1;
|
||||
if (domain_len >= 1 && q->name[domain_len - 1] != '.')
|
||||
return -1;
|
||||
|
||||
/* pointer to start of topdomain; instead of dots at the end
|
||||
we have length-bytes in front, so total length is the same */
|
||||
topname = 0xc000 | ((p - buf + domain_len) & 0x3fff);
|
||||
|
||||
/* Query section */
|
||||
putname(&p, buflen - (p - buf), q->name); /* Name */
|
||||
CHECKLEN(4);
|
||||
putshort(&p, q->type); /* Type */
|
||||
putshort(&p, C_IN); /* Class */
|
||||
|
||||
/* Answer section */
|
||||
CHECKLEN(12);
|
||||
putshort(&p, name); /* Name */
|
||||
putshort(&p, q->type); /* Type */
|
||||
putshort(&p, C_IN); /* Class */
|
||||
putlong(&p, 3600); /* TTL */
|
||||
putshort(&p, 5); /* Data length */
|
||||
|
||||
/* pointer to ns.topdomain */
|
||||
nsname = 0xc000 | ((p - buf) & 0x3fff);
|
||||
CHECKLEN(5);
|
||||
putbyte(&p, 2);
|
||||
putbyte(&p, 'n');
|
||||
putbyte(&p, 's');
|
||||
putshort(&p, topname); /* Name Server */
|
||||
|
||||
/* Do we have an IPv4 address to send? */
|
||||
if (q->destination.ss_family == AF_INET) {
|
||||
struct sockaddr_in *dest = (struct sockaddr_in *) &q->destination;
|
||||
|
||||
/* One additional record coming */
|
||||
header->arcount = htons(1);
|
||||
|
||||
/* Additional data (A-record of NS server) */
|
||||
CHECKLEN(12);
|
||||
putshort(&p, nsname); /* Name Server */
|
||||
putshort(&p, T_A); /* Type */
|
||||
putshort(&p, C_IN); /* Class */
|
||||
putlong(&p, 3600); /* TTL */
|
||||
putshort(&p, 4); /* Data length */
|
||||
|
||||
/* ugly hack to output IP address */
|
||||
ipp = (char *) &dest->sin_addr.s_addr;
|
||||
CHECKLEN(4);
|
||||
putbyte(&p, *(ipp++));
|
||||
putbyte(&p, *(ipp++));
|
||||
putbyte(&p, *(ipp++));
|
||||
putbyte(&p, *ipp);
|
||||
}
|
||||
|
||||
len = p - buf;
|
||||
return len;
|
||||
}
|
||||
|
||||
/* Only used when iodined gets an A type query for ns.topdomain or
|
||||
* www.topdomain . Mostly same as dns_encode_ns_response() above */
|
||||
int dns_encode_a_response(char *buf, size_t buflen, struct query *q)
|
||||
{
|
||||
struct sockaddr_in *dest = (struct sockaddr_in *) &q->destination;
|
||||
HEADER *header;
|
||||
int len;
|
||||
short name;
|
||||
char *ipp;
|
||||
char *p;
|
||||
|
||||
/* Check if we have an IPv4 address to send */
|
||||
if (q->destination.ss_family != AF_INET)
|
||||
return -1;
|
||||
|
||||
if (buflen < sizeof(HEADER))
|
||||
return 0;
|
||||
|
||||
memset(buf, 0, buflen);
|
||||
|
||||
header = (HEADER*)buf;
|
||||
|
||||
header->id = htons(q->id);
|
||||
header->qr = 1;
|
||||
header->opcode = 0;
|
||||
header->aa = 1;
|
||||
header->tc = 0;
|
||||
header->rd = 0;
|
||||
header->ra = 0;
|
||||
|
||||
p = buf + sizeof(HEADER);
|
||||
|
||||
header->qdcount = htons(1);
|
||||
header->ancount = htons(1);
|
||||
|
||||
/* pointer to start of name */
|
||||
name = 0xc000 | ((p - buf) & 0x3fff);
|
||||
|
||||
/* Query section */
|
||||
putname(&p, buflen - (p - buf), q->name); /* Name */
|
||||
CHECKLEN(4);
|
||||
putshort(&p, q->type); /* Type */
|
||||
putshort(&p, C_IN); /* Class */
|
||||
|
||||
/* Answer section */
|
||||
CHECKLEN(12);
|
||||
putshort(&p, name); /* Name */
|
||||
putshort(&p, q->type); /* Type */
|
||||
putshort(&p, C_IN); /* Class */
|
||||
putlong(&p, 3600); /* TTL */
|
||||
putshort(&p, 4); /* Data length */
|
||||
|
||||
/* ugly hack to output IP address */
|
||||
ipp = (char *) &dest->sin_addr.s_addr;
|
||||
CHECKLEN(4);
|
||||
putbyte(&p, *(ipp++));
|
||||
putbyte(&p, *(ipp++));
|
||||
putbyte(&p, *(ipp++));
|
||||
putbyte(&p, *ipp);
|
||||
|
||||
len = p - buf;
|
||||
return len;
|
||||
}
|
||||
|
||||
int dns_encode_nxdomain(char *buf, size_t buflen, struct query *q, const char *zone)
|
||||
{
|
||||
char rnamebuf[256];
|
||||
char nsbuf[256];
|
||||
HEADER *header;
|
||||
char *soa_start;
|
||||
char *p;
|
||||
|
||||
if (buflen < sizeof(HEADER))
|
||||
return 0;
|
||||
|
||||
memset(buf, 0, buflen);
|
||||
header = (HEADER*)buf;
|
||||
|
||||
header->id = htons(q->id);
|
||||
header->qr = 1; // response
|
||||
header->opcode = 0;
|
||||
header->aa = 1; // authoritative
|
||||
header->tc = 0;
|
||||
header->rd = 0;
|
||||
header->ra = 0;
|
||||
header->rcode = 3; // NXDOMAIN
|
||||
|
||||
header->qdcount = htons(1);
|
||||
header->ancount = htons(0);
|
||||
header->nscount = htons(1); // We'll include SOA
|
||||
header->arcount = htons(0);
|
||||
|
||||
p = buf + sizeof(HEADER);
|
||||
|
||||
// Question section
|
||||
putname(&p, buflen - (p - buf), q->name);
|
||||
CHECKLEN(4);
|
||||
putshort(&p, q->type);
|
||||
putshort(&p, C_IN);
|
||||
|
||||
// Authority section (SOA)
|
||||
CHECKLEN(10);
|
||||
putname(&p, buflen - (p - buf), zone); // zone name (owner of SOA)
|
||||
putshort(&p, T_SOA);
|
||||
putshort(&p, C_IN);
|
||||
putlong(&p, 60); // TTL
|
||||
|
||||
soa_start = p;
|
||||
p += 2; // skip rdlength (to be filled later)
|
||||
|
||||
// Primary NS and responsible mailbox
|
||||
snprintf(nsbuf, sizeof(nsbuf), "ns.%s", zone);
|
||||
putname(&p, buflen - (p - buf), nsbuf);
|
||||
snprintf(rnamebuf, sizeof(rnamebuf), "hostmaster.%s", zone);
|
||||
putname(&p, buflen - (p - buf), rnamebuf);
|
||||
|
||||
// SOA fields: serial, refresh, retry, expire, minimum
|
||||
putlong(&p, 1); // serial
|
||||
putlong(&p, 3600); // refresh
|
||||
putlong(&p, 1800); // retry
|
||||
putlong(&p, 604800); // expire
|
||||
putlong(&p, 60); // minimum
|
||||
|
||||
int soalen = p - soa_start - 2;
|
||||
putshort(&soa_start, soalen); // fill in rdlength
|
||||
|
||||
return p - buf;
|
||||
}
|
||||
|
||||
#undef CHECKLEN
|
||||
|
||||
unsigned short dns_get_id(char *packet, size_t packetlen)
|
||||
{
|
||||
HEADER *header;
|
||||
header = (HEADER*)packet;
|
||||
|
||||
if (packetlen < sizeof(HEADER))
|
||||
return 0;
|
||||
|
||||
return ntohs(header->id);
|
||||
}
|
||||
|
||||
#define CHECKLEN(x) if (packetlen < (x) + (size_t)(data-packet)) return 0
|
||||
|
||||
int dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet,
|
||||
size_t packetlen)
|
||||
{
|
||||
char name[QUERY_NAME_SIZE];
|
||||
char rdata[4*1024];
|
||||
HEADER *header;
|
||||
short qdcount;
|
||||
short ancount;
|
||||
uint32_t ttl;
|
||||
unsigned short class;
|
||||
unsigned short type;
|
||||
char *data;
|
||||
unsigned short rlen;
|
||||
int id;
|
||||
int rv;
|
||||
|
||||
q->id2 = 0;
|
||||
rv = 0;
|
||||
header = (HEADER*)packet;
|
||||
|
||||
/* Reject short packets */
|
||||
if (packetlen < sizeof(HEADER))
|
||||
return 0;
|
||||
|
||||
if (header->qr != qr) {
|
||||
warnx("header->qr does not match the requested qr");
|
||||
return -1;
|
||||
}
|
||||
|
||||
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)
|
||||
q->rcode = header->rcode;
|
||||
|
||||
switch (qr) {
|
||||
case QR_ANSWER:
|
||||
if (qdcount < 1) {
|
||||
/* We need a question */
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (q != NULL)
|
||||
q->id = id;
|
||||
|
||||
/* Read name even if no answer, to give better error message */
|
||||
readname(packet, packetlen, &data, name, sizeof(name));
|
||||
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
|
||||
multiple results. */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Here type is still the question type */
|
||||
if (type == T_NULL || type == T_PRIVATE) {
|
||||
/* Assume that first answer is what we wanted */
|
||||
readname(packet, packetlen, &data, name, sizeof(name));
|
||||
CHECKLEN(10);
|
||||
readshort(packet, &data, &type);
|
||||
readshort(packet, &data, &class);
|
||||
readlong(packet, &data, &ttl);
|
||||
readshort(packet, &data, &rlen);
|
||||
|
||||
rv = MIN(rlen, sizeof(rdata));
|
||||
rv = readdata(packet, &data, rdata, rv);
|
||||
if (rv >= 2 && buf) {
|
||||
rv = MIN(rv, buflen);
|
||||
memcpy(buf, rdata, rv);
|
||||
} else {
|
||||
rv = 0;
|
||||
}
|
||||
}
|
||||
else if ((type == T_A || type == T_CNAME) && buf) {
|
||||
/* Assume that first answer is what we wanted */
|
||||
readname(packet, packetlen, &data, name, sizeof(name));
|
||||
CHECKLEN(10);
|
||||
readshort(packet, &data, &type);
|
||||
readshort(packet, &data, &class);
|
||||
readlong(packet, &data, &ttl);
|
||||
readshort(packet, &data, &rlen);
|
||||
|
||||
if (type == T_CNAME) {
|
||||
/* For tunnels, query type A has CNAME type answer */
|
||||
memset(name, 0, sizeof(name));
|
||||
readname(packet, packetlen, &data, name, sizeof(name) - 1);
|
||||
name[sizeof(name)-1] = '\0';
|
||||
strncpy(buf, name, buflen);
|
||||
buf[buflen - 1] = '\0';
|
||||
rv = strlen(buf);
|
||||
}
|
||||
if (type == T_A) {
|
||||
/* Answer type A includes only 4 bytes.
|
||||
Not used for tunneling. */
|
||||
rv = MIN(rlen, sizeof(rdata));
|
||||
rv = readdata(packet, &data, rdata, rv);
|
||||
if (rv >= 2 && buf) {
|
||||
rv = MIN(rv, buflen);
|
||||
memcpy(buf, rdata, rv);
|
||||
} else {
|
||||
rv = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((type == T_MX || type == T_SRV) && buf) {
|
||||
/* We support 250 records, 250*(255+header) ~= 64kB.
|
||||
Only exact 10-multiples are accepted, and gaps in
|
||||
numbering are not jumped over (->truncated).
|
||||
Hopefully DNS servers won't mess around too much.
|
||||
*/
|
||||
char names[250][QUERY_NAME_SIZE];
|
||||
char *rdatastart;
|
||||
unsigned short pref;
|
||||
int i;
|
||||
int offset;
|
||||
|
||||
memset(names, 0, sizeof(names));
|
||||
|
||||
for (i = 0; i < ancount; i++) {
|
||||
readname(packet, packetlen, &data, name, sizeof(name));
|
||||
CHECKLEN(12);
|
||||
readshort(packet, &data, &type);
|
||||
readshort(packet, &data, &class);
|
||||
readlong(packet, &data, &ttl);
|
||||
readshort(packet, &data, &rlen);
|
||||
rdatastart = data;
|
||||
readshort(packet, &data, &pref);
|
||||
|
||||
if (type == T_SRV) {
|
||||
/* skip weight, port */
|
||||
data += 4;
|
||||
CHECKLEN(0);
|
||||
}
|
||||
|
||||
if (pref % 10 == 0 && pref >= 10 &&
|
||||
pref < 2500) {
|
||||
readname(packet, packetlen, &data,
|
||||
names[pref / 10 - 1],
|
||||
QUERY_NAME_SIZE - 1);
|
||||
names[pref / 10 - 1]
|
||||
[QUERY_NAME_SIZE-1] = '\0';
|
||||
}
|
||||
|
||||
/* always trust rlen, not name encoding */
|
||||
data = rdatastart + rlen;
|
||||
CHECKLEN(0);
|
||||
}
|
||||
|
||||
/* output is like Hname10.com\0Hname20.com\0\0 */
|
||||
offset = 0;
|
||||
i = 0;
|
||||
while (names[i][0] != '\0') {
|
||||
int l = MIN(strlen(names[i]), buflen-offset-2);
|
||||
if (l <= 0)
|
||||
break;
|
||||
memcpy(buf + offset, names[i], l);
|
||||
offset += l;
|
||||
*(buf + offset) = '\0';
|
||||
offset++;
|
||||
i++;
|
||||
}
|
||||
*(buf + offset) = '\0';
|
||||
rv = offset;
|
||||
}
|
||||
else if (type == T_TXT && buf) {
|
||||
/* Assume that first answer is what we wanted */
|
||||
readname(packet, packetlen, &data, name, sizeof(name));
|
||||
CHECKLEN(10);
|
||||
readshort(packet, &data, &type);
|
||||
readshort(packet, &data, &class);
|
||||
readlong(packet, &data, &ttl);
|
||||
readshort(packet, &data, &rlen);
|
||||
|
||||
rv = readtxtbin(packet, &data, rlen, rdata,
|
||||
sizeof(rdata));
|
||||
if (rv >= 1) {
|
||||
rv = MIN(rv, buflen);
|
||||
memcpy(buf, rdata, rv);
|
||||
} else {
|
||||
rv = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Here type is the answer type (note A->CNAME) */
|
||||
if (q != NULL)
|
||||
q->type = type;
|
||||
break;
|
||||
case QR_QUERY:
|
||||
if (qdcount < 1) {
|
||||
warnx("no question section in name query");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(name, 0, sizeof(name));
|
||||
readname(packet, packetlen, &data, name, sizeof(name) - 1);
|
||||
name[sizeof(name)-1] = '\0';
|
||||
CHECKLEN(4);
|
||||
readshort(packet, &data, &type);
|
||||
readshort(packet, &data, &class);
|
||||
|
||||
if (q == NULL) {
|
||||
rv = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
strncpy(q->name, name, sizeof(q->name));
|
||||
q->name[sizeof(q->name) - 1] = '\0';
|
||||
q->type = type;
|
||||
q->id = id;
|
||||
|
||||
rv = strlen(q->name);
|
||||
break;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
38
third-party/iodine/src/dns.h
vendored
Normal file
38
third-party/iodine/src/dns.h
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
|
||||
*/
|
||||
|
||||
#ifndef __DNS_H__
|
||||
#define __DNS_H__
|
||||
|
||||
#include "common.h"
|
||||
|
||||
typedef enum {
|
||||
QR_QUERY = 0,
|
||||
QR_ANSWER = 1
|
||||
} qr_t;
|
||||
|
||||
extern int dnsc_use_edns0;
|
||||
|
||||
int dns_encode(char *, size_t, struct query *, qr_t, const char *, size_t);
|
||||
int dns_encode_ns_response(char *buf, size_t buflen, struct query *q,
|
||||
char *topdomain);
|
||||
int dns_encode_a_response(char *buf, size_t buflen, struct query *q);
|
||||
int dns_encode_nxdomain(char *buf, size_t buflen, struct query *q, const char *zone);
|
||||
unsigned short dns_get_id(char *packet, size_t packetlen);
|
||||
int dns_decode(char *, size_t, struct query *, qr_t, char *, size_t);
|
||||
|
||||
#endif /* _DNS_H_ */
|
||||
127
third-party/iodine/src/encoding.c
vendored
Normal file
127
third-party/iodine/src/encoding.c
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "common.h"
|
||||
#include "encoding.h"
|
||||
|
||||
int build_hostname(char *buf, size_t buflen, const char *data,
|
||||
const size_t datalen, const char *topdomain,
|
||||
const struct encoder *encoder, int maxlen)
|
||||
{
|
||||
size_t space;
|
||||
char *b;
|
||||
|
||||
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);
|
||||
|
||||
encoder->encode(buf, &space, data, datalen);
|
||||
|
||||
if (!encoder->places_dots)
|
||||
inline_dotify(buf, buflen);
|
||||
|
||||
b = buf;
|
||||
b += strlen(buf);
|
||||
|
||||
/* move b back one step to see if the dot is there */
|
||||
b--;
|
||||
if (*b != '.')
|
||||
*++b = '.';
|
||||
b++;
|
||||
/* move b ahead of the string so we can copy to it */
|
||||
|
||||
strncpy(b, topdomain, strlen(topdomain)+1);
|
||||
|
||||
return space;
|
||||
}
|
||||
|
||||
int unpack_data(char *buf, size_t buflen, char *data, size_t datalen,
|
||||
const struct encoder *enc)
|
||||
{
|
||||
if (!enc->eats_dots)
|
||||
datalen = inline_undotify(data, datalen);
|
||||
return enc->decode(buf, &buflen, data, datalen);
|
||||
}
|
||||
|
||||
int inline_dotify(char *buf, size_t buflen)
|
||||
{
|
||||
unsigned dots;
|
||||
unsigned pos;
|
||||
unsigned total;
|
||||
char *reader, *writer;
|
||||
|
||||
total = strlen(buf);
|
||||
dots = total / 57;
|
||||
|
||||
writer = buf;
|
||||
writer += total;
|
||||
writer += dots;
|
||||
|
||||
total += dots;
|
||||
if (strlen(buf) + dots > buflen) {
|
||||
writer = buf;
|
||||
writer += buflen;
|
||||
total = buflen;
|
||||
}
|
||||
|
||||
reader = writer - dots;
|
||||
pos = (unsigned) (reader - buf) + 1;
|
||||
|
||||
while (dots) {
|
||||
*writer-- = *reader--;
|
||||
pos--;
|
||||
if (pos % 57 == 0) {
|
||||
*writer-- = '.';
|
||||
dots--;
|
||||
}
|
||||
}
|
||||
|
||||
/* return new length of string */
|
||||
return total;
|
||||
}
|
||||
|
||||
int inline_undotify(char *buf, size_t len)
|
||||
{
|
||||
unsigned pos;
|
||||
unsigned dots;
|
||||
char *reader, *writer;
|
||||
|
||||
writer = buf;
|
||||
reader = writer;
|
||||
|
||||
pos = 0;
|
||||
dots = 0;
|
||||
|
||||
while (pos < len) {
|
||||
if (*reader == '.') {
|
||||
reader++;
|
||||
pos++;
|
||||
dots++;
|
||||
continue;
|
||||
}
|
||||
*writer++ = *reader++;
|
||||
pos++;
|
||||
}
|
||||
|
||||
/* return new length of string */
|
||||
return len - dots;
|
||||
}
|
||||
65
third-party/iodine/src/encoding.h
vendored
Normal file
65
third-party/iodine/src/encoding.h
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2014 Erik Ekman
|
||||
* 2006-2009 Bjorn Andersson
|
||||
* Copyright (c) 2017 Ralf Ramsauer
|
||||
*
|
||||
* Authors:
|
||||
* Bjorn Andersson <flex@kryo.se>
|
||||
* Erok Ekman <yarrick@kryo.se>,
|
||||
* Ralf Ramsauer <ralf@ramses-pyramidenbau.de>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
|
||||
*/
|
||||
|
||||
#ifndef _ENCODING_H_
|
||||
#define _ENCODING_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
/* All-0, all-1, 01010101, 10101010: each 4 times to make sure the pattern
|
||||
spreads across multiple encoded chars -> 16 bytes total.
|
||||
Followed by 32 bytes from my /dev/random; should be enough.
|
||||
*/
|
||||
#define DOWNCODECCHECK1 \
|
||||
"\000\000\000\000\377\377\377\377\125\125\125\125\252\252\252\252" \
|
||||
"\201\143\310\322\307\174\262\027\137\117\316\311\111\055\122\041" \
|
||||
"\141\251\161\040\045\263\006\163\346\330\104\060\171\120\127\277"
|
||||
#define DOWNCODECCHECK1_LEN 48
|
||||
|
||||
struct encoder {
|
||||
const char name[8];
|
||||
int (*encode)(char *dst, size_t *dstlen, const void *src, size_t srclen);
|
||||
int (*decode)(void *dst, size_t *dstlen, const char *src, size_t srclen);
|
||||
|
||||
const bool places_dots;
|
||||
const bool eats_dots;
|
||||
|
||||
const int blocksize_raw;
|
||||
const int blocksize_encoded;
|
||||
};
|
||||
|
||||
int build_hostname(char *, size_t, const char *, const size_t, const char *,
|
||||
const struct encoder *, int);
|
||||
int unpack_data(char *, size_t, char *, size_t, const struct encoder *);
|
||||
int inline_dotify(char *, size_t);
|
||||
int inline_undotify(char *, size_t);
|
||||
|
||||
extern const struct encoder base32_ops;
|
||||
extern const struct encoder base64_ops;
|
||||
extern const struct encoder base64u_ops;
|
||||
extern const struct encoder base128_ops;
|
||||
|
||||
int b32_5to8(int);
|
||||
int b32_8to5(int);
|
||||
|
||||
#endif
|
||||
49
third-party/iodine/src/fw_query.c
vendored
Normal file
49
third-party/iodine/src/fw_query.c
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 Erik Ekman <yarrick@kryo.se>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "fw_query.h"
|
||||
|
||||
static struct fw_query fwq[FW_QUERY_CACHE_SIZE];
|
||||
static int fwq_ix;
|
||||
|
||||
void fw_query_init(void)
|
||||
{
|
||||
memset(fwq, 0, sizeof(struct fw_query) * FW_QUERY_CACHE_SIZE);
|
||||
fwq_ix = 0;
|
||||
}
|
||||
|
||||
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)
|
||||
fwq_ix = 0;
|
||||
}
|
||||
|
||||
void fw_query_get(unsigned short query_id, struct fw_query **fw_query)
|
||||
{
|
||||
int i;
|
||||
|
||||
*fw_query = NULL;
|
||||
for (i = 0; i < FW_QUERY_CACHE_SIZE; i++) {
|
||||
if (fwq[i].id == query_id) {
|
||||
*fw_query = &(fwq[i]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
41
third-party/iodine/src/fw_query.h
vendored
Normal file
41
third-party/iodine/src/fw_query.h
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 Erik Ekman <yarrick@kryo.se>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
|
||||
*/
|
||||
|
||||
#ifndef __FW_QUERY_H__
|
||||
#define __FW_QUERY_H__
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifdef WINDOWS32
|
||||
#include "windows.h"
|
||||
#include <winsock2.h>
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#define FW_QUERY_CACHE_SIZE 16
|
||||
|
||||
struct fw_query {
|
||||
struct sockaddr_storage addr;
|
||||
int addrlen;
|
||||
unsigned short id;
|
||||
};
|
||||
|
||||
void fw_query_init(void);
|
||||
void fw_query_put(struct fw_query *fw_query);
|
||||
void fw_query_get(unsigned short query_id, struct fw_query **fw_query);
|
||||
|
||||
#endif /*__FW_QUERY_H__*/
|
||||
|
||||
413
third-party/iodine/src/iodine.c
vendored
Normal file
413
third-party/iodine/src/iodine.c
vendored
Normal file
@@ -0,0 +1,413 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef WINDOWS32
|
||||
#include "windows.h"
|
||||
#include <winsock2.h>
|
||||
#else
|
||||
#include <grp.h>
|
||||
#include <pwd.h>
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
#include "tun.h"
|
||||
#include "client.h"
|
||||
#include "util.h"
|
||||
|
||||
#ifdef WINDOWS32
|
||||
WORD req_version = MAKEWORD(2, 2);
|
||||
WSADATA wsa_data;
|
||||
#endif
|
||||
|
||||
#if !defined(BSD) && !defined(__GLIBC__)
|
||||
static char *__progname;
|
||||
#else
|
||||
extern char *__progname;
|
||||
#endif
|
||||
|
||||
#define PASSWORD_ENV_VAR "IODINE_PASS"
|
||||
|
||||
static void
|
||||
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 inline void usage(void) __attribute__((noreturn));
|
||||
static inline void help(FILE * stream, bool verbose) __attribute__((noreturn));
|
||||
#endif
|
||||
|
||||
static void help(FILE *stream, bool verbose)
|
||||
{
|
||||
fprintf(stream,
|
||||
"iodine IP over DNS tunneling client\n\n"
|
||||
"Usage: %s [-46fhrv] [-u user] [-t chrootdir] [-d device] [-P password]\n"
|
||||
" [-m maxfragsize] [-M maxlen] [-T type] [-O enc] [-L 0|1] [-I sec]\n"
|
||||
" [-z context] [-F pidfile] [nameserver] topdomain\n", __progname);
|
||||
|
||||
if (!verbose)
|
||||
exit(2);
|
||||
|
||||
fprintf(stream,
|
||||
"\nOptions to try if connection doesn't work:\n"
|
||||
" -4 to connect only to IPv4\n"
|
||||
" -6 to connect only to IPv6\n"
|
||||
" -T force dns type: NULL, PRIVATE, TXT, SRV, MX, CNAME, A (default: autodetect)\n"
|
||||
" -O force downstream encoding for -T other than NULL: Base32, Base64, Base64u,\n"
|
||||
" Base128, or (only for TXT:) Raw (default: autodetect)\n"
|
||||
" -I max interval between requests (default 4 sec) to prevent DNS timeouts\n"
|
||||
" -L 1: use lazy mode for low-latency (default). 0: don't (implies -I1)\n"
|
||||
" -m max size of downstream fragments (default: autodetect)\n"
|
||||
" -M max size of upstream hostnames (~100-255, default: 255)\n"
|
||||
" -r to skip raw UDP mode attempt\n"
|
||||
" -P password used for authentication (max 32 chars will be used)\n\n"
|
||||
"Other options:\n"
|
||||
" -v to print version info and exit\n"
|
||||
" -h to print this help and exit\n"
|
||||
" -f to keep running in foreground\n"
|
||||
" -u name to drop privileges and run as user 'name'\n"
|
||||
" -t dir to chroot to directory dir\n"
|
||||
" -d device to set tunnel device name\n"
|
||||
" -z context, to apply specified SELinux context after initialization\n"
|
||||
" -F pidfile to write pid to a file\n\n"
|
||||
"nameserver is the IP number/hostname of the relaying nameserver. If absent,\n"
|
||||
" /etc/resolv.conf is used\n"
|
||||
"topdomain is the FQDN that is delegated to the tunnel endpoint.\n");
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static inline void usage(void)
|
||||
{
|
||||
help(stderr, false);
|
||||
}
|
||||
|
||||
static void version(void)
|
||||
{
|
||||
fprintf(stderr, "iodine IP over DNS tunneling client\n"
|
||||
"Git version: %s\n", GITREVISION);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char *nameserv_host;
|
||||
char *topdomain;
|
||||
char *errormsg;
|
||||
#ifndef WINDOWS32
|
||||
struct passwd *pw;
|
||||
#endif
|
||||
char *username;
|
||||
char password[33];
|
||||
int foreground;
|
||||
char *newroot;
|
||||
char *context;
|
||||
char *device;
|
||||
char *pidfile;
|
||||
int choice;
|
||||
int tun_fd;
|
||||
int dns_fd;
|
||||
int max_downstream_frag_size;
|
||||
int autodetect_frag_size;
|
||||
int retval;
|
||||
int raw_mode;
|
||||
int lazymode;
|
||||
int selecttimeout;
|
||||
int hostname_maxlen;
|
||||
#ifdef OPENBSD
|
||||
int rtable = 0;
|
||||
#endif
|
||||
struct sockaddr_storage nameservaddr;
|
||||
int nameservaddr_len;
|
||||
int nameserv_family;
|
||||
|
||||
nameserv_host = NULL;
|
||||
topdomain = NULL;
|
||||
errormsg = NULL;
|
||||
#ifndef WINDOWS32
|
||||
pw = NULL;
|
||||
#endif
|
||||
username = NULL;
|
||||
memset(password, 0, 33);
|
||||
srand(time(NULL));
|
||||
foreground = 0;
|
||||
newroot = NULL;
|
||||
context = NULL;
|
||||
device = NULL;
|
||||
pidfile = NULL;
|
||||
|
||||
autodetect_frag_size = 1;
|
||||
max_downstream_frag_size = 3072;
|
||||
retval = 0;
|
||||
raw_mode = 1;
|
||||
lazymode = 1;
|
||||
selecttimeout = 4;
|
||||
hostname_maxlen = 0xFF;
|
||||
nameserv_family = AF_UNSPEC;
|
||||
|
||||
#ifdef WINDOWS32
|
||||
WSAStartup(req_version, &wsa_data);
|
||||
#endif
|
||||
|
||||
srand((unsigned) time(NULL));
|
||||
client_init();
|
||||
|
||||
#if !defined(BSD) && !defined(__GLIBC__)
|
||||
__progname = strrchr(argv[0], '/');
|
||||
if (__progname == NULL)
|
||||
__progname = argv[0];
|
||||
else
|
||||
__progname++;
|
||||
#endif
|
||||
|
||||
while ((choice = getopt(argc, argv, "46vfhru:t:d:R:P:m:M:F:T:O:L:I:")) != -1) {
|
||||
switch(choice) {
|
||||
case '4':
|
||||
nameserv_family = AF_INET;
|
||||
break;
|
||||
case '6':
|
||||
nameserv_family = AF_INET6;
|
||||
break;
|
||||
case 'v':
|
||||
version();
|
||||
/* NOTREACHED */
|
||||
break;
|
||||
case 'f':
|
||||
foreground = 1;
|
||||
break;
|
||||
case 'h':
|
||||
help(stdout, true);
|
||||
/* NOTREACHED */
|
||||
break;
|
||||
case 'r':
|
||||
raw_mode = 0;
|
||||
break;
|
||||
case 'u':
|
||||
username = optarg;
|
||||
break;
|
||||
case 't':
|
||||
newroot = optarg;
|
||||
break;
|
||||
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));
|
||||
break;
|
||||
case 'm':
|
||||
autodetect_frag_size = 0;
|
||||
max_downstream_frag_size = atoi(optarg);
|
||||
break;
|
||||
case 'M':
|
||||
hostname_maxlen = atoi(optarg);
|
||||
if (hostname_maxlen > 255)
|
||||
hostname_maxlen = 255;
|
||||
if (hostname_maxlen < 10)
|
||||
hostname_maxlen = 10;
|
||||
break;
|
||||
case 'z':
|
||||
context = optarg;
|
||||
break;
|
||||
case 'F':
|
||||
pidfile = optarg;
|
||||
break;
|
||||
case 'T':
|
||||
if (client_set_qtype(optarg))
|
||||
errx(5, "Invalid query type '%s'", optarg);
|
||||
break;
|
||||
case 'O': /* not -D, is Debug in server */
|
||||
client_set_downenc(optarg);
|
||||
break;
|
||||
case 'L':
|
||||
lazymode = atoi(optarg);
|
||||
if (lazymode > 1)
|
||||
lazymode = 1;
|
||||
if (lazymode < 0)
|
||||
lazymode = 0;
|
||||
if (!lazymode)
|
||||
selecttimeout = 1;
|
||||
break;
|
||||
case 'I':
|
||||
selecttimeout = atoi(optarg);
|
||||
if (selecttimeout < 1)
|
||||
selecttimeout = 1;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
|
||||
check_superuser();
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
switch (argc) {
|
||||
case 1:
|
||||
nameserv_host = get_resolvconf_addr();
|
||||
topdomain = strdup(argv[0]);
|
||||
break;
|
||||
case 2:
|
||||
nameserv_host = argv[0];
|
||||
topdomain = strdup(argv[1]);
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
if (max_downstream_frag_size < 1 || max_downstream_frag_size > 0xffff) {
|
||||
warnx("Use a max frag size between 1 and 65535 bytes.\n");
|
||||
usage();
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
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 (check_topdomain(topdomain, 0, &errormsg)) {
|
||||
warnx("Invalid topdomain: %s", errormsg);
|
||||
usage();
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
client_set_selecttimeout(selecttimeout);
|
||||
client_set_lazymode(lazymode);
|
||||
client_set_topdomain(topdomain);
|
||||
client_set_hostname_maxlen(hostname_maxlen);
|
||||
|
||||
if (username != NULL) {
|
||||
#ifndef WINDOWS32
|
||||
if ((pw = getpwnam(username)) == NULL) {
|
||||
warnx("User %s does not exist!\n", username);
|
||||
usage();
|
||||
/* NOTREACHED */
|
||||
}
|
||||
#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_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, 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)
|
||||
do_detach();
|
||||
|
||||
if (pidfile != NULL)
|
||||
do_pidfile(pidfile);
|
||||
|
||||
if (newroot != NULL)
|
||||
do_chroot(newroot);
|
||||
|
||||
if (username != NULL) {
|
||||
#ifndef WINDOWS32
|
||||
gid_t gids[1];
|
||||
gids[0] = pw->pw_gid;
|
||||
if (setgroups(1, gids) < 0 || setgid(pw->pw_gid) < 0 || setuid(pw->pw_uid) < 0) {
|
||||
warnx("Could not switch to user %s!\n", username);
|
||||
usage();
|
||||
/* NOTREACHED */
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (context != NULL)
|
||||
do_setcon(context);
|
||||
|
||||
client_tunnel(tun_fd, dns_fd);
|
||||
|
||||
cleanup2:
|
||||
close_dns(dns_fd);
|
||||
close_tun(tun_fd);
|
||||
cleanup1:
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
2828
third-party/iodine/src/iodined.c
vendored
Normal file
2828
third-party/iodine/src/iodined.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
60
third-party/iodine/src/login.c
vendored
Normal file
60
third-party/iodine/src/login.c
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef WINDOWS32
|
||||
#include "windows.h"
|
||||
#else
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include "login.h"
|
||||
#include "md5.h"
|
||||
|
||||
/*
|
||||
* Needs a 16byte array for output, and 32 bytes password
|
||||
*/
|
||||
void
|
||||
login_calculate(char *buf, int buflen, const char *pass, int seed)
|
||||
{
|
||||
unsigned char temp[32];
|
||||
md5_state_t ctx;
|
||||
int *ix;
|
||||
int i;
|
||||
int k;
|
||||
|
||||
if (buflen < 16)
|
||||
return;
|
||||
|
||||
memcpy(temp, pass, 32);
|
||||
ix = (int*) temp;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
k = ntohl(*ix);
|
||||
k ^= seed;
|
||||
*ix++ = htonl(k);
|
||||
}
|
||||
|
||||
md5_init(&ctx);
|
||||
md5_append(&ctx, temp, 32);
|
||||
md5_finish(&ctx, (unsigned char *) buf);
|
||||
|
||||
}
|
||||
|
||||
24
third-party/iodine/src/login.h
vendored
Normal file
24
third-party/iodine/src/login.h
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
|
||||
*/
|
||||
|
||||
#ifndef __LOGIN_H__
|
||||
#define __LOGIN_H__
|
||||
|
||||
void login_calculate(char *, int, const char *, int);
|
||||
|
||||
#endif
|
||||
|
||||
384
third-party/iodine/src/md5.c
vendored
Normal file
384
third-party/iodine/src/md5.c
vendored
Normal file
@@ -0,0 +1,384 @@
|
||||
/*
|
||||
Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
L. Peter Deutsch
|
||||
ghost@aladdin.com
|
||||
|
||||
*/
|
||||
/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */
|
||||
/*
|
||||
Independent implementation of MD5 (RFC 1321).
|
||||
|
||||
This code implements the MD5 Algorithm defined in RFC 1321, whose
|
||||
text is available at
|
||||
http://www.ietf.org/rfc/rfc1321.txt
|
||||
The code is derived from the text of the RFC, including the test suite
|
||||
(section A.5) but excluding the rest of Appendix A. It does not include
|
||||
any code or documentation that is identified in the RFC as being
|
||||
copyrighted.
|
||||
|
||||
The original and principal author of md5.c is L. Peter Deutsch
|
||||
<ghost@aladdin.com>. Other authors are noted in the change history
|
||||
that follows (in reverse chronological order):
|
||||
|
||||
2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
|
||||
either statically or dynamically; added missing #include <string.h>
|
||||
in library.
|
||||
2002-03-11 lpd Corrected argument list for main(), and added int return
|
||||
type, in test program and T value program.
|
||||
2002-02-21 lpd Added missing #include <stdio.h> in test program.
|
||||
2000-07-03 lpd Patched to eliminate warnings about "constant is
|
||||
unsigned in ANSI C, signed in traditional"; made test program
|
||||
self-checking.
|
||||
1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
|
||||
1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
|
||||
1999-05-03 lpd Original version.
|
||||
*/
|
||||
|
||||
#include "md5.h"
|
||||
#include <string.h>
|
||||
|
||||
#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
|
||||
#ifdef ARCH_IS_BIG_ENDIAN
|
||||
# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
|
||||
#else
|
||||
# define BYTE_ORDER 0
|
||||
#endif
|
||||
|
||||
#define T_MASK ((md5_word_t)~0)
|
||||
#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
|
||||
#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
|
||||
#define T3 0x242070db
|
||||
#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
|
||||
#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
|
||||
#define T6 0x4787c62a
|
||||
#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
|
||||
#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
|
||||
#define T9 0x698098d8
|
||||
#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
|
||||
#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
|
||||
#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
|
||||
#define T13 0x6b901122
|
||||
#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
|
||||
#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
|
||||
#define T16 0x49b40821
|
||||
#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
|
||||
#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
|
||||
#define T19 0x265e5a51
|
||||
#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
|
||||
#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
|
||||
#define T22 0x02441453
|
||||
#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
|
||||
#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
|
||||
#define T25 0x21e1cde6
|
||||
#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
|
||||
#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
|
||||
#define T28 0x455a14ed
|
||||
#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
|
||||
#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
|
||||
#define T31 0x676f02d9
|
||||
#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
|
||||
#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
|
||||
#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
|
||||
#define T35 0x6d9d6122
|
||||
#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
|
||||
#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
|
||||
#define T38 0x4bdecfa9
|
||||
#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
|
||||
#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
|
||||
#define T41 0x289b7ec6
|
||||
#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
|
||||
#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
|
||||
#define T44 0x04881d05
|
||||
#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
|
||||
#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
|
||||
#define T47 0x1fa27cf8
|
||||
#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
|
||||
#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
|
||||
#define T50 0x432aff97
|
||||
#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
|
||||
#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
|
||||
#define T53 0x655b59c3
|
||||
#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
|
||||
#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
|
||||
#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
|
||||
#define T57 0x6fa87e4f
|
||||
#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
|
||||
#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
|
||||
#define T60 0x4e0811a1
|
||||
#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
|
||||
#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
|
||||
#define T63 0x2ad7d2bb
|
||||
#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
|
||||
|
||||
|
||||
static void
|
||||
md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
|
||||
{
|
||||
md5_word_t
|
||||
a = pms->abcd[0], b = pms->abcd[1],
|
||||
c = pms->abcd[2], d = pms->abcd[3];
|
||||
md5_word_t t;
|
||||
#if BYTE_ORDER > 0
|
||||
/* Define storage only for big-endian CPUs. */
|
||||
md5_word_t X[16];
|
||||
#else
|
||||
/* Define storage for little-endian or both types of CPUs. */
|
||||
md5_word_t xbuf[16];
|
||||
const md5_word_t *X;
|
||||
#endif
|
||||
|
||||
{
|
||||
#if BYTE_ORDER == 0
|
||||
/*
|
||||
* Determine dynamically whether this is a big-endian or
|
||||
* little-endian machine, since we can use a more efficient
|
||||
* algorithm on the latter.
|
||||
*/
|
||||
static const int w = 1;
|
||||
|
||||
if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
|
||||
#endif
|
||||
#if BYTE_ORDER <= 0 /* little-endian */
|
||||
{
|
||||
/*
|
||||
* On little-endian machines, we can process properly aligned
|
||||
* data without copying it.
|
||||
*/
|
||||
if (!((data - (const md5_byte_t *)0) & 3)) {
|
||||
/* data are properly aligned */
|
||||
X = (const md5_word_t *)data;
|
||||
} else {
|
||||
/* not aligned */
|
||||
memcpy(xbuf, data, 64);
|
||||
X = xbuf;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if BYTE_ORDER == 0
|
||||
else /* dynamic big-endian */
|
||||
#endif
|
||||
#if BYTE_ORDER >= 0 /* big-endian */
|
||||
{
|
||||
/*
|
||||
* On big-endian machines, we must arrange the bytes in the
|
||||
* right order.
|
||||
*/
|
||||
const md5_byte_t *xp = data;
|
||||
int i;
|
||||
|
||||
# if BYTE_ORDER == 0
|
||||
X = xbuf; /* (dynamic only) */
|
||||
# else
|
||||
# define xbuf X /* (static only) */
|
||||
# endif
|
||||
for (i = 0; i < 16; ++i, xp += 4)
|
||||
xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
|
||||
|
||||
/* Round 1. */
|
||||
/* Let [abcd k s i] denote the operation
|
||||
a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + F(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 0, 7, T1);
|
||||
SET(d, a, b, c, 1, 12, T2);
|
||||
SET(c, d, a, b, 2, 17, T3);
|
||||
SET(b, c, d, a, 3, 22, T4);
|
||||
SET(a, b, c, d, 4, 7, T5);
|
||||
SET(d, a, b, c, 5, 12, T6);
|
||||
SET(c, d, a, b, 6, 17, T7);
|
||||
SET(b, c, d, a, 7, 22, T8);
|
||||
SET(a, b, c, d, 8, 7, T9);
|
||||
SET(d, a, b, c, 9, 12, T10);
|
||||
SET(c, d, a, b, 10, 17, T11);
|
||||
SET(b, c, d, a, 11, 22, T12);
|
||||
SET(a, b, c, d, 12, 7, T13);
|
||||
SET(d, a, b, c, 13, 12, T14);
|
||||
SET(c, d, a, b, 14, 17, T15);
|
||||
SET(b, c, d, a, 15, 22, T16);
|
||||
#undef SET
|
||||
|
||||
/* Round 2. */
|
||||
/* Let [abcd k s i] denote the operation
|
||||
a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + G(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 1, 5, T17);
|
||||
SET(d, a, b, c, 6, 9, T18);
|
||||
SET(c, d, a, b, 11, 14, T19);
|
||||
SET(b, c, d, a, 0, 20, T20);
|
||||
SET(a, b, c, d, 5, 5, T21);
|
||||
SET(d, a, b, c, 10, 9, T22);
|
||||
SET(c, d, a, b, 15, 14, T23);
|
||||
SET(b, c, d, a, 4, 20, T24);
|
||||
SET(a, b, c, d, 9, 5, T25);
|
||||
SET(d, a, b, c, 14, 9, T26);
|
||||
SET(c, d, a, b, 3, 14, T27);
|
||||
SET(b, c, d, a, 8, 20, T28);
|
||||
SET(a, b, c, d, 13, 5, T29);
|
||||
SET(d, a, b, c, 2, 9, T30);
|
||||
SET(c, d, a, b, 7, 14, T31);
|
||||
SET(b, c, d, a, 12, 20, T32);
|
||||
#undef SET
|
||||
|
||||
/* Round 3. */
|
||||
/* Let [abcd k s t] denote the operation
|
||||
a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define H(x, y, z) ((x) ^ (y) ^ (z))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + H(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 5, 4, T33);
|
||||
SET(d, a, b, c, 8, 11, T34);
|
||||
SET(c, d, a, b, 11, 16, T35);
|
||||
SET(b, c, d, a, 14, 23, T36);
|
||||
SET(a, b, c, d, 1, 4, T37);
|
||||
SET(d, a, b, c, 4, 11, T38);
|
||||
SET(c, d, a, b, 7, 16, T39);
|
||||
SET(b, c, d, a, 10, 23, T40);
|
||||
SET(a, b, c, d, 13, 4, T41);
|
||||
SET(d, a, b, c, 0, 11, T42);
|
||||
SET(c, d, a, b, 3, 16, T43);
|
||||
SET(b, c, d, a, 6, 23, T44);
|
||||
SET(a, b, c, d, 9, 4, T45);
|
||||
SET(d, a, b, c, 12, 11, T46);
|
||||
SET(c, d, a, b, 15, 16, T47);
|
||||
SET(b, c, d, a, 2, 23, T48);
|
||||
#undef SET
|
||||
|
||||
/* Round 4. */
|
||||
/* Let [abcd k s t] denote the operation
|
||||
a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + I(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 0, 6, T49);
|
||||
SET(d, a, b, c, 7, 10, T50);
|
||||
SET(c, d, a, b, 14, 15, T51);
|
||||
SET(b, c, d, a, 5, 21, T52);
|
||||
SET(a, b, c, d, 12, 6, T53);
|
||||
SET(d, a, b, c, 3, 10, T54);
|
||||
SET(c, d, a, b, 10, 15, T55);
|
||||
SET(b, c, d, a, 1, 21, T56);
|
||||
SET(a, b, c, d, 8, 6, T57);
|
||||
SET(d, a, b, c, 15, 10, T58);
|
||||
SET(c, d, a, b, 6, 15, T59);
|
||||
SET(b, c, d, a, 13, 21, T60);
|
||||
SET(a, b, c, d, 4, 6, T61);
|
||||
SET(d, a, b, c, 11, 10, T62);
|
||||
SET(c, d, a, b, 2, 15, T63);
|
||||
SET(b, c, d, a, 9, 21, T64);
|
||||
#undef SET
|
||||
|
||||
/* Then perform the following additions. (That is increment each
|
||||
of the four registers by the value it had before this block
|
||||
was started.) */
|
||||
pms->abcd[0] += a;
|
||||
pms->abcd[1] += b;
|
||||
pms->abcd[2] += c;
|
||||
pms->abcd[3] += d;
|
||||
}
|
||||
|
||||
void
|
||||
md5_init(md5_state_t *pms)
|
||||
{
|
||||
pms->count[0] = pms->count[1] = 0;
|
||||
pms->abcd[0] = 0x67452301;
|
||||
pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
|
||||
pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
|
||||
pms->abcd[3] = 0x10325476;
|
||||
}
|
||||
|
||||
void
|
||||
md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
|
||||
{
|
||||
const md5_byte_t *p = data;
|
||||
int left = nbytes;
|
||||
int offset = (pms->count[0] >> 3) & 63;
|
||||
md5_word_t nbits = (md5_word_t)(nbytes << 3);
|
||||
|
||||
if (nbytes <= 0)
|
||||
return;
|
||||
|
||||
/* Update the message length. */
|
||||
pms->count[1] += nbytes >> 29;
|
||||
pms->count[0] += nbits;
|
||||
if (pms->count[0] < nbits)
|
||||
pms->count[1]++;
|
||||
|
||||
/* Process an initial partial block. */
|
||||
if (offset) {
|
||||
int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
|
||||
|
||||
memcpy(pms->buf + offset, p, copy);
|
||||
if (offset + copy < 64)
|
||||
return;
|
||||
p += copy;
|
||||
left -= copy;
|
||||
md5_process(pms, pms->buf);
|
||||
}
|
||||
|
||||
/* Process full blocks. */
|
||||
for (; left >= 64; p += 64, left -= 64)
|
||||
md5_process(pms, p);
|
||||
|
||||
/* Process a final partial block. */
|
||||
if (left)
|
||||
memcpy(pms->buf, p, left);
|
||||
}
|
||||
|
||||
void
|
||||
md5_finish(md5_state_t *pms, md5_byte_t digest[16])
|
||||
{
|
||||
static const md5_byte_t pad[64] = {
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
md5_byte_t data[8];
|
||||
int i;
|
||||
|
||||
/* Save the length before padding. */
|
||||
for (i = 0; i < 8; ++i)
|
||||
data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
|
||||
/* Pad to 56 bytes mod 64. */
|
||||
md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
|
||||
/* Append the length. */
|
||||
md5_append(pms, data, 8);
|
||||
for (i = 0; i < 16; ++i)
|
||||
digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
|
||||
}
|
||||
|
||||
|
||||
|
||||
91
third-party/iodine/src/md5.h
vendored
Normal file
91
third-party/iodine/src/md5.h
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved.
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
L. Peter Deutsch
|
||||
ghost@aladdin.com
|
||||
|
||||
*/
|
||||
/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */
|
||||
/*
|
||||
Independent implementation of MD5 (RFC 1321).
|
||||
|
||||
This code implements the MD5 Algorithm defined in RFC 1321, whose
|
||||
text is available at
|
||||
http://www.ietf.org/rfc/rfc1321.txt
|
||||
The code is derived from the text of the RFC, including the test suite
|
||||
(section A.5) but excluding the rest of Appendix A. It does not include
|
||||
any code or documentation that is identified in the RFC as being
|
||||
copyrighted.
|
||||
|
||||
The original and principal author of md5.h is L. Peter Deutsch
|
||||
<ghost@aladdin.com>. Other authors are noted in the change history
|
||||
that follows (in reverse chronological order):
|
||||
|
||||
2002-04-13 lpd Removed support for non-ANSI compilers; removed
|
||||
references to Ghostscript; clarified derivation from RFC 1321;
|
||||
now handles byte order either statically or dynamically.
|
||||
1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
|
||||
1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
|
||||
added conditionalization for C++ compilation from Martin
|
||||
Purschke <purschke@bnl.gov>.
|
||||
1999-05-03 lpd Original version.
|
||||
*/
|
||||
|
||||
#ifndef md5_INCLUDED
|
||||
# define md5_INCLUDED
|
||||
|
||||
/*
|
||||
* This package supports both compile-time and run-time determination of CPU
|
||||
* byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
|
||||
* compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
|
||||
* defined as non-zero, the code will be compiled to run only on big-endian
|
||||
* CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
|
||||
* run on either big- or little-endian CPUs, but will run slightly less
|
||||
* efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
|
||||
*/
|
||||
|
||||
typedef unsigned char md5_byte_t; /* 8-bit byte */
|
||||
typedef unsigned int md5_word_t; /* 32-bit word */
|
||||
|
||||
/* Define the state of the MD5 Algorithm. */
|
||||
typedef struct md5_state_s {
|
||||
md5_word_t count[2]; /* message length in bits, lsw first */
|
||||
md5_word_t abcd[4]; /* digest buffer */
|
||||
md5_byte_t buf[64]; /* accumulate block */
|
||||
} md5_state_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/* Initialize the algorithm. */
|
||||
void md5_init(md5_state_t *pms);
|
||||
|
||||
/* Append a string to the message. */
|
||||
void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
|
||||
|
||||
/* Finish the message and return the digest. */
|
||||
void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* md5_INCLUDED */
|
||||
58
third-party/iodine/src/osflags
vendored
Executable file
58
third-party/iodine/src/osflags
vendored
Executable file
@@ -0,0 +1,58 @@
|
||||
#!/bin/sh
|
||||
|
||||
: "${PKG_CONFIG:=pkg-config}"
|
||||
|
||||
case $2 in
|
||||
link)
|
||||
|
||||
case $1 in
|
||||
SunOS | solaris)
|
||||
echo '-lsocket -lnsl';
|
||||
;;
|
||||
BeOS)
|
||||
echo '-lsocket -lbind -lbsd';
|
||||
;;
|
||||
Haiku)
|
||||
echo '-lnetwork -lbsd';
|
||||
;;
|
||||
windows32)
|
||||
echo '-lws2_32 -liphlpapi';
|
||||
;;
|
||||
Linux)
|
||||
FLAGS="";
|
||||
"$PKG_CONFIG" --exists libselinux && FLAGS="$FLAGS $($PKG_CONFIG --libs libselinux)";
|
||||
"$PKG_CONFIG" --exists libsystemd-daemon && FLAGS="$FLAGS $($PKG_CONFIG --libs libsystemd-daemon)";
|
||||
"$PKG_CONFIG" --exists libsystemd && FLAGS="$FLAGS $($PKG_CONFIG --libs libsystemd)";
|
||||
echo $FLAGS;
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
cflags)
|
||||
case $1 in
|
||||
windows32)
|
||||
echo '-DWINVER=0x0501';
|
||||
;;
|
||||
BeOS)
|
||||
echo '-Dsocklen_t=int';
|
||||
;;
|
||||
Haiku)
|
||||
echo '-D_DEFAULT_SOURCE';
|
||||
;;
|
||||
Darwin)
|
||||
echo '-D__APPLE_USE_RFC_3542';
|
||||
;;
|
||||
Linux)
|
||||
FLAGS="-D_GNU_SOURCE"
|
||||
"$PKG_CONFIG" --exists libselinux && FLAGS="$FLAGS -DHAVE_SETCON";
|
||||
"$PKG_CONFIG" --exists libsystemd-daemon && FLAGS="$FLAGS -DHAVE_SYSTEMD";
|
||||
"$PKG_CONFIG" --exists libsystemd && FLAGS="$FLAGS -DHAVE_SYSTEMD";
|
||||
echo $FLAGS;
|
||||
;;
|
||||
GNU/kFreeBSD|GNU)
|
||||
echo '-D_GNU_SOURCE'
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
273
third-party/iodine/src/read.c
vendored
Normal file
273
third-party/iodine/src/read.c
vendored
Normal file
@@ -0,0 +1,273 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "read.h"
|
||||
|
||||
static int
|
||||
readname_loop(char *packet, int packetlen, char **src, char *dst, size_t length, size_t loop)
|
||||
{
|
||||
char *dummy;
|
||||
char *s;
|
||||
char *d;
|
||||
int len;
|
||||
int offset;
|
||||
char c;
|
||||
|
||||
if (loop <= 0)
|
||||
return 0;
|
||||
|
||||
len = 0;
|
||||
s = *src;
|
||||
d = dst;
|
||||
while(*s && len < length - 2) {
|
||||
c = *s++;
|
||||
|
||||
/* is this a compressed label? */
|
||||
if ((c & 0xc0) == 0xc0) {
|
||||
offset = (((s[-1] & 0x3f) << 8) | (s[0] & 0xff));
|
||||
if (offset > packetlen) {
|
||||
if (len == 0) {
|
||||
/* Bad jump first in packet */
|
||||
return 0;
|
||||
} else {
|
||||
/* Bad jump after some data */
|
||||
break;
|
||||
}
|
||||
}
|
||||
dummy = packet + offset;
|
||||
len += readname_loop(packet, packetlen, &dummy, d, length - len, loop - 1);
|
||||
goto end;
|
||||
}
|
||||
|
||||
while(c && len < length - 1) {
|
||||
*d++ = *s++;
|
||||
len++;
|
||||
|
||||
c--;
|
||||
}
|
||||
|
||||
if (len >= length - 1) {
|
||||
break; /* We used up all space */
|
||||
}
|
||||
|
||||
if (*s != 0) {
|
||||
*d++ = '.';
|
||||
len++;
|
||||
}
|
||||
}
|
||||
dst[len++] = '\0';
|
||||
|
||||
end:
|
||||
(*src) = s+1;
|
||||
return len;
|
||||
}
|
||||
|
||||
int
|
||||
readname(char *packet, int packetlen, char **src, char *dst, size_t length)
|
||||
{
|
||||
return readname_loop(packet, packetlen, src, dst, length, 10);
|
||||
}
|
||||
|
||||
int
|
||||
readshort(char *packet, char **src, unsigned short *dst)
|
||||
{
|
||||
unsigned char *p;
|
||||
|
||||
p = (unsigned char *) *src;
|
||||
*dst = (p[0] << 8) | p[1];
|
||||
|
||||
(*src) += sizeof(unsigned short);
|
||||
return sizeof(unsigned short);
|
||||
}
|
||||
|
||||
int
|
||||
readlong(char *packet, char **src, uint32_t *dst)
|
||||
{
|
||||
/* A long as described in dns protocol is always 32 bits */
|
||||
unsigned char *p;
|
||||
|
||||
p = (unsigned char *) *src;
|
||||
|
||||
*dst = ((uint32_t)p[0] << 24)
|
||||
| ((uint32_t)p[1] << 16)
|
||||
| ((uint32_t)p[2] << 8)
|
||||
| ((uint32_t)p[3]);
|
||||
|
||||
(*src) += sizeof(uint32_t);
|
||||
return sizeof(uint32_t);
|
||||
}
|
||||
|
||||
int
|
||||
readdata(char *packet, char **src, char *dst, size_t len)
|
||||
{
|
||||
memcpy(dst, *src, len);
|
||||
|
||||
(*src) += len;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int
|
||||
readtxtbin(char *packet, char **src, size_t srcremain, char *dst, size_t dstremain)
|
||||
{
|
||||
unsigned char *uc;
|
||||
int tocopy;
|
||||
int dstused = 0;
|
||||
|
||||
while (srcremain > 0)
|
||||
{
|
||||
uc = (unsigned char*) (*src);
|
||||
tocopy = *uc;
|
||||
(*src)++;
|
||||
srcremain--;
|
||||
|
||||
if (tocopy > srcremain)
|
||||
return 0; /* illegal, better have nothing */
|
||||
if (tocopy > dstremain)
|
||||
return 0; /* doesn't fit, better have nothing */
|
||||
|
||||
memcpy(dst, *src, tocopy);
|
||||
dst += tocopy;
|
||||
(*src) += tocopy;
|
||||
srcremain -= tocopy;
|
||||
dstremain -= tocopy;
|
||||
dstused += tocopy;
|
||||
}
|
||||
return dstused;
|
||||
}
|
||||
|
||||
int
|
||||
putname(char **buf, size_t buflen, const char *host)
|
||||
{
|
||||
char *word;
|
||||
int left;
|
||||
char *h;
|
||||
char *p;
|
||||
|
||||
h = strdup(host);
|
||||
left = buflen;
|
||||
p = *buf;
|
||||
|
||||
word = strtok(h, ".");
|
||||
while(word) {
|
||||
size_t word_len = strlen(word);
|
||||
if (word_len > 63 || word_len > left) {
|
||||
free(h);
|
||||
return -1;
|
||||
}
|
||||
|
||||
left -= (word_len + 1);
|
||||
*p++ = (char)word_len;
|
||||
memcpy(p, word, word_len);
|
||||
p += word_len;
|
||||
|
||||
word = strtok(NULL, ".");
|
||||
}
|
||||
|
||||
*p++ = 0;
|
||||
|
||||
free(h);
|
||||
|
||||
*buf = p;
|
||||
return buflen - left;
|
||||
}
|
||||
|
||||
int
|
||||
putbyte(char **dst, unsigned char value)
|
||||
{
|
||||
**dst = value;
|
||||
(*dst)++;
|
||||
|
||||
return sizeof(char);
|
||||
}
|
||||
|
||||
int
|
||||
putshort(char **dst, unsigned short value)
|
||||
{
|
||||
unsigned char *p;
|
||||
|
||||
p = (unsigned char *) *dst;
|
||||
|
||||
*p++ = (value >> 8);
|
||||
*p++ = value;
|
||||
|
||||
(*dst) = (char *) p;
|
||||
return sizeof(short);
|
||||
}
|
||||
|
||||
int
|
||||
putlong(char **dst, uint32_t value)
|
||||
{
|
||||
/* A long as described in dns protocol is always 32 bits */
|
||||
unsigned char *p;
|
||||
|
||||
p = (unsigned char *) *dst;
|
||||
|
||||
*p++ = (value >> 24);
|
||||
*p++ = (value >> 16);
|
||||
*p++ = (value >> 8);
|
||||
*p++ = (value);
|
||||
|
||||
(*dst) = (char *) p;
|
||||
return sizeof(uint32_t);
|
||||
}
|
||||
|
||||
int
|
||||
putdata(char **dst, const char *data, size_t len)
|
||||
{
|
||||
memcpy(*dst, data, len);
|
||||
|
||||
(*dst) += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
int
|
||||
puttxtbin(char **buf, size_t bufremain, const char *from, size_t fromremain)
|
||||
{
|
||||
unsigned char uc;
|
||||
unsigned char *ucp = &uc;
|
||||
char *cp = (char *) ucp;
|
||||
int tocopy;
|
||||
int bufused = 0;
|
||||
|
||||
while (fromremain > 0)
|
||||
{
|
||||
tocopy = fromremain;
|
||||
if (tocopy > 252)
|
||||
tocopy = 252; /* allow off-by-1s in caches etc */
|
||||
if (tocopy + 1 > bufremain)
|
||||
return -1; /* doesn't fit, better have nothing */
|
||||
|
||||
uc = tocopy;
|
||||
**buf = *cp;
|
||||
(*buf)++;
|
||||
bufremain--;
|
||||
bufused++;
|
||||
|
||||
memcpy(*buf, from, tocopy);
|
||||
(*buf) += tocopy;
|
||||
from += tocopy;
|
||||
bufremain -= tocopy;
|
||||
fromremain -= tocopy;
|
||||
bufused += tocopy;
|
||||
}
|
||||
return bufused;
|
||||
}
|
||||
34
third-party/iodine/src/read.h
vendored
Normal file
34
third-party/iodine/src/read.h
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
|
||||
*/
|
||||
|
||||
#ifndef _READ_H_
|
||||
#define _READ_H_
|
||||
|
||||
int readname(char *, int, char **, char *, size_t);
|
||||
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);
|
||||
|
||||
int putname(char **, size_t, const char *);
|
||||
int putbyte(char **, unsigned char);
|
||||
int putshort(char **, unsigned short);
|
||||
int putlong(char **, uint32_t);
|
||||
int putdata(char **, const char *, size_t);
|
||||
int puttxtbin(char **, size_t, const char *, size_t);
|
||||
|
||||
#endif
|
||||
720
third-party/iodine/src/tun.c
vendored
Normal file
720
third-party/iodine/src/tun.c
vendored
Normal file
@@ -0,0 +1,720 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||
* 2013 Peter Sagerson <psagers.github@ignorare.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifdef DARWIN
|
||||
#include <ctype.h>
|
||||
#include <sys/kern_control.h>
|
||||
#include <sys/sys_domain.h>
|
||||
#include <sys/ioctl.h>
|
||||
/* Inline used parts of if_utun.h to compile without it. */
|
||||
#define UTUN_CONTROL_NAME "com.apple.net.utun_control"
|
||||
#define UTUN_OPT_IFNAME 2
|
||||
#include <netinet/ip.h>
|
||||
#endif
|
||||
|
||||
#ifndef IFCONFIGPATH
|
||||
#define IFCONFIGPATH "PATH=/sbin:/bin "
|
||||
#endif
|
||||
|
||||
#ifndef ROUTEPATH
|
||||
#define ROUTEPATH "PATH=/sbin:/bin "
|
||||
#endif
|
||||
|
||||
#ifdef WINDOWS32
|
||||
#include "windows.h"
|
||||
#include <winioctl.h>
|
||||
|
||||
static HANDLE dev_handle;
|
||||
static struct tun_data data;
|
||||
|
||||
static void get_name(char *ifname, int namelen, char *dev_name);
|
||||
|
||||
#define TAP_CONTROL_CODE(request,method) CTL_CODE(FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS)
|
||||
#define TAP_IOCTL_CONFIG_TUN TAP_CONTROL_CODE(10, METHOD_BUFFERED)
|
||||
#define TAP_IOCTL_SET_MEDIA_STATUS TAP_CONTROL_CODE(6, METHOD_BUFFERED)
|
||||
|
||||
#define TAP_ADAPTER_KEY "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
|
||||
#define NETWORK_KEY "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
|
||||
#define TAP_DEVICE_SPACE "\\\\.\\Global\\"
|
||||
#define TAP_VERSION_ID_0801 "tap0801"
|
||||
#define TAP_VERSION_ID_0901 "tap0901"
|
||||
#define TAP_VERSION_ID_0901_ROOT "root\\tap0901"
|
||||
#define KEY_COMPONENT_ID "ComponentId"
|
||||
#define NET_CFG_INST_ID "NetCfgInstanceId"
|
||||
#else
|
||||
#include <err.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#define TUN_MAX_TRY 50
|
||||
#endif
|
||||
|
||||
#include "tun.h"
|
||||
#include "common.h"
|
||||
|
||||
static char if_name[250];
|
||||
|
||||
#ifdef LINUX
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <net/if.h>
|
||||
#include <linux/if_tun.h>
|
||||
|
||||
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", tunnel);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&ifreq, 0, sizeof(ifreq));
|
||||
|
||||
ifreq.ifr_flags = IFF_TUN;
|
||||
|
||||
if (tun_device != NULL) {
|
||||
strncpy(ifreq.ifr_name, tun_device, IFNAMSIZ);
|
||||
ifreq.ifr_name[IFNAMSIZ-1] = '\0';
|
||||
strncpy(if_name, tun_device, sizeof(if_name));
|
||||
if_name[sizeof(if_name)-1] = '\0';
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (errno != EBUSY) {
|
||||
warn("open_tun: ioctl[TUNSETIFF]");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < TUN_MAX_TRY; i++) {
|
||||
snprintf(ifreq.ifr_name, IFNAMSIZ, "dns%d", i);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (errno != EBUSY) {
|
||||
warn("open_tun: ioctl[TUNSETIFF]");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
warn("open_tun: Couldn't set interface name");
|
||||
}
|
||||
warn("error when opening tun");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#elif WINDOWS32
|
||||
|
||||
static void
|
||||
get_device(char *device, int device_len, const char *wanted_dev)
|
||||
{
|
||||
LONG status;
|
||||
HKEY adapter_key;
|
||||
int index;
|
||||
|
||||
index = 0;
|
||||
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TAP_ADAPTER_KEY, 0, KEY_READ, &adapter_key);
|
||||
|
||||
if (status != ERROR_SUCCESS) {
|
||||
warnx("Error opening registry key " TAP_ADAPTER_KEY);
|
||||
return;
|
||||
}
|
||||
|
||||
while (TRUE) {
|
||||
char name[256];
|
||||
char unit[256];
|
||||
char component[256];
|
||||
|
||||
char cid_string[256] = KEY_COMPONENT_ID;
|
||||
HKEY device_key;
|
||||
DWORD datatype;
|
||||
DWORD len;
|
||||
|
||||
/* Iterate through all adapter of this kind */
|
||||
len = sizeof(name);
|
||||
status = RegEnumKeyEx(adapter_key, index, name, &len, NULL, NULL, NULL, NULL);
|
||||
if (status == ERROR_NO_MORE_ITEMS) {
|
||||
break;
|
||||
} else if (status != ERROR_SUCCESS) {
|
||||
warnx("Error enumerating subkeys of registry key " TAP_ADAPTER_KEY);
|
||||
break;
|
||||
}
|
||||
|
||||
snprintf(unit, sizeof(unit), TAP_ADAPTER_KEY "\\%s", name);
|
||||
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, unit, 0, KEY_READ, &device_key);
|
||||
if (status != ERROR_SUCCESS) {
|
||||
warnx("Error opening registry key %s", unit);
|
||||
goto next;
|
||||
}
|
||||
|
||||
/* Check component id */
|
||||
len = sizeof(component);
|
||||
status = RegQueryValueEx(device_key, cid_string, NULL, &datatype, (LPBYTE)component, &len);
|
||||
if (status != ERROR_SUCCESS || datatype != REG_SZ) {
|
||||
goto next;
|
||||
}
|
||||
if (strncmp(TAP_VERSION_ID_0801, component, strlen(TAP_VERSION_ID_0801)) == 0 ||
|
||||
strncmp(TAP_VERSION_ID_0901, component, strlen(TAP_VERSION_ID_0901)) == 0 ||
|
||||
strncmp(TAP_VERSION_ID_0901_ROOT, component, strlen(TAP_VERSION_ID_0901_ROOT)) == 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);
|
||||
} else {
|
||||
/* Done getting GUID of TAP device,
|
||||
* now check if the name is the requested one */
|
||||
if (wanted_dev) {
|
||||
char name[250];
|
||||
get_name(name, sizeof(name), device);
|
||||
if (strncmp(name, wanted_dev, strlen(wanted_dev))) {
|
||||
/* Skip if name mismatch */
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
/* Get the if name */
|
||||
get_name(if_name, sizeof(if_name), device);
|
||||
RegCloseKey(device_key);
|
||||
return;
|
||||
}
|
||||
}
|
||||
next:
|
||||
RegCloseKey(device_key);
|
||||
index++;
|
||||
}
|
||||
RegCloseKey(adapter_key);
|
||||
}
|
||||
|
||||
static void
|
||||
get_name(char *ifname, int namelen, char *dev_name)
|
||||
{
|
||||
char path[256];
|
||||
char name_str[256] = "Name";
|
||||
LONG status;
|
||||
HKEY conn_key;
|
||||
DWORD len;
|
||||
DWORD datatype;
|
||||
|
||||
memset(ifname, 0, namelen);
|
||||
|
||||
snprintf(path, sizeof(path), NETWORK_KEY "\\%s\\Connection", dev_name);
|
||||
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, path, 0, KEY_READ, &conn_key);
|
||||
if (status != ERROR_SUCCESS) {
|
||||
fprintf(stderr, "Could not look up name of interface %s: error opening key\n", dev_name);
|
||||
RegCloseKey(conn_key);
|
||||
return;
|
||||
}
|
||||
len = namelen;
|
||||
status = RegQueryValueEx(conn_key, name_str, NULL, &datatype, (LPBYTE)ifname, &len);
|
||||
if (status != ERROR_SUCCESS || datatype != REG_SZ) {
|
||||
fprintf(stderr, "Could not look up name of interface %s: error reading value\n", dev_name);
|
||||
RegCloseKey(conn_key);
|
||||
return;
|
||||
}
|
||||
RegCloseKey(conn_key);
|
||||
}
|
||||
|
||||
DWORD WINAPI tun_reader(LPVOID arg)
|
||||
{
|
||||
struct tun_data *tun = arg;
|
||||
char buf[64*1024];
|
||||
int len;
|
||||
int res;
|
||||
OVERLAPPED olpd;
|
||||
int sock;
|
||||
|
||||
sock = open_dns_from_host("127.0.0.1", 0, AF_INET, 0);
|
||||
|
||||
olpd.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
while(TRUE) {
|
||||
olpd.Offset = 0;
|
||||
olpd.OffsetHigh = 0;
|
||||
res = ReadFile(tun->tun, buf, sizeof(buf), (LPDWORD) &len, &olpd);
|
||||
if (!res) {
|
||||
WaitForSingleObject(olpd.hEvent, INFINITE);
|
||||
res = GetOverlappedResult(dev_handle, &olpd, (LPDWORD) &len, FALSE);
|
||||
res = sendto(sock, buf, len, 0, (struct sockaddr*) &(tun->addr),
|
||||
tun->addrlen);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
open_tun(const char *tun_device)
|
||||
{
|
||||
char adapter[256];
|
||||
char tapfile[512];
|
||||
int tunfd;
|
||||
struct sockaddr_storage localsock;
|
||||
int localsock_len;
|
||||
|
||||
memset(adapter, 0, sizeof(adapter));
|
||||
memset(if_name, 0, sizeof(if_name));
|
||||
get_device(adapter, sizeof(adapter), tun_device);
|
||||
|
||||
if (strlen(adapter) == 0 || strlen(if_name) == 0) {
|
||||
if (tun_device) {
|
||||
warnx("No TAP adapters found. Try without -d.");
|
||||
} else {
|
||||
warnx("No TAP adapters found. Version 0801 and 0901 are supported.");
|
||||
}
|
||||
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);
|
||||
if (dev_handle == INVALID_HANDLE_VALUE) {
|
||||
warnx("Could not open device!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 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
|
||||
* sends data as udp to this socket */
|
||||
|
||||
localsock_len = get_addr("127.0.0.1", 55353, AF_INET, 0, &localsock);
|
||||
tunfd = open_dns(&localsock, localsock_len);
|
||||
|
||||
data.tun = dev_handle;
|
||||
memcpy(&(data.addr), &localsock, localsock_len);
|
||||
data.addrlen = localsock_len;
|
||||
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)tun_reader, &data, 0, NULL);
|
||||
|
||||
return tunfd;
|
||||
}
|
||||
|
||||
#else /* BSD and friends */
|
||||
|
||||
#ifdef DARWIN
|
||||
|
||||
/* Extract the device number from the name, if given. The value returned will
|
||||
* be suitable for sockaddr_ctl.sc_unit, which means 0 for auto-assign, or
|
||||
* (n + 1) for manual.
|
||||
*/
|
||||
static int
|
||||
utun_unit(const char *dev)
|
||||
{
|
||||
const char *unit_str = dev;
|
||||
int unit = 0;
|
||||
|
||||
if (!dev)
|
||||
return -1;
|
||||
|
||||
while (*unit_str != '\0' && !isdigit(*unit_str))
|
||||
unit_str++;
|
||||
|
||||
if (isdigit(*unit_str))
|
||||
unit = strtol(unit_str, NULL, 10) + 1;
|
||||
|
||||
return unit;
|
||||
}
|
||||
|
||||
static int
|
||||
open_utun(const char *dev)
|
||||
{
|
||||
struct sockaddr_ctl addr;
|
||||
struct ctl_info info;
|
||||
char ifname[10];
|
||||
socklen_t ifname_len = sizeof(ifname);
|
||||
int unit;
|
||||
int fd = -1;
|
||||
int err = 0;
|
||||
|
||||
fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL);
|
||||
if (fd < 0) {
|
||||
warn("open_utun: socket(PF_SYSTEM)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Look up the kernel controller ID for utun devices. */
|
||||
bzero(&info, sizeof(info));
|
||||
strncpy(info.ctl_name, UTUN_CONTROL_NAME, MAX_KCTL_NAME);
|
||||
|
||||
err = ioctl(fd, CTLIOCGINFO, &info);
|
||||
if (err != 0) {
|
||||
warn("open_utun: ioctl(CTLIOCGINFO)");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Connecting to the socket creates the utun device. */
|
||||
addr.sc_len = sizeof(addr);
|
||||
addr.sc_family = AF_SYSTEM;
|
||||
addr.ss_sysaddr = AF_SYS_CONTROL;
|
||||
addr.sc_id = info.ctl_id;
|
||||
unit = utun_unit(dev);
|
||||
if (unit < 0) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
addr.sc_unit = unit;
|
||||
|
||||
err = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
|
||||
if (err != 0) {
|
||||
warn("open_utun: connect");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Retrieve the assigned interface name. */
|
||||
err = getsockopt(fd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME, ifname, &ifname_len);
|
||||
if (err != 0) {
|
||||
warn("open_utun: getsockopt(UTUN_OPT_IFNAME)");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
strncpy(if_name, ifname, sizeof(if_name));
|
||||
|
||||
fprintf(stderr, "Opened %s\n", ifname);
|
||||
fd_set_close_on_exec(fd);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int
|
||||
open_tun(const char *tun_device)
|
||||
{
|
||||
int i;
|
||||
int tun_fd;
|
||||
char tun_name[50];
|
||||
|
||||
if (tun_device != NULL) {
|
||||
#ifdef DARWIN
|
||||
if (!strncmp(tun_device, "utun", 4)) {
|
||||
tun_fd = open_utun(tun_device);
|
||||
if (tun_fd >= 0) {
|
||||
return tun_fd;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
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", tun_name);
|
||||
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;
|
||||
}
|
||||
|
||||
#ifdef DARWIN
|
||||
fprintf(stderr, "No tun devices found, trying utun\n");
|
||||
for (i = 0; i < TUN_MAX_TRY; i++) {
|
||||
snprintf(tun_name, sizeof(tun_name), "utun%d", i);
|
||||
tun_fd = open_utun(tun_name);
|
||||
if (tun_fd >= 0) {
|
||||
return tun_fd;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
warn("open_tun: Failed to open tunneling device");
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
close_tun(int tun_fd)
|
||||
{
|
||||
if (tun_fd >= 0)
|
||||
close(tun_fd);
|
||||
}
|
||||
|
||||
#ifdef WINDOWS32
|
||||
int
|
||||
write_tun(int tun_fd, char *data, size_t len)
|
||||
{
|
||||
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
|
||||
static int
|
||||
tun_uses_header(void)
|
||||
{
|
||||
#if defined (FREEBSD) || defined (NETBSD)
|
||||
/* FreeBSD/NetBSD has no header */
|
||||
return 0;
|
||||
#elif defined (DARWIN)
|
||||
/* Darwin tun has no header, Darwin utun does */
|
||||
return !strncmp(if_name, "utun", 4);
|
||||
#else /* LINUX/OPENBSD */
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
write_tun(int tun_fd, char *data, size_t len)
|
||||
{
|
||||
if (!tun_uses_header()) {
|
||||
data += 4;
|
||||
len -= 4;
|
||||
} else {
|
||||
#ifdef LINUX
|
||||
// Linux prefixes with 32 bits ethertype
|
||||
// 0x0800 for IPv4, 0x86DD for IPv6
|
||||
data[0] = 0x00;
|
||||
data[1] = 0x00;
|
||||
data[2] = 0x08;
|
||||
data[3] = 0x00;
|
||||
#else /* OPENBSD and DARWIN(utun) */
|
||||
// BSDs prefix with 32 bits address family
|
||||
// AF_INET for IPv4, AF_INET6 for IPv6
|
||||
data[0] = 0x00;
|
||||
data[1] = 0x00;
|
||||
data[2] = 0x00;
|
||||
data[3] = 0x02;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (write(tun_fd, data, len) != len) {
|
||||
warn("write_tun");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
read_tun(int tun_fd, char *buf, size_t len)
|
||||
{
|
||||
if (!tun_uses_header()) {
|
||||
int bytes;
|
||||
memset(buf, 0, 4);
|
||||
|
||||
bytes = read(tun_fd, buf + 4, len - 4);
|
||||
if (bytes < 0) {
|
||||
return bytes;
|
||||
} else {
|
||||
return bytes + 4;
|
||||
}
|
||||
} else {
|
||||
return read(tun_fd, buf, len);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
tun_setip(const char *ip, const char *other_ip, int netbits)
|
||||
{
|
||||
char cmdline[512];
|
||||
int netmask;
|
||||
struct in_addr net;
|
||||
int i;
|
||||
#ifndef LINUX
|
||||
int r;
|
||||
#endif
|
||||
#ifdef WINDOWS32
|
||||
DWORD status;
|
||||
DWORD ipdata[3];
|
||||
struct in_addr addr;
|
||||
DWORD len;
|
||||
#else
|
||||
const char *display_ip;
|
||||
#ifndef LINUX
|
||||
struct in_addr netip;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
netmask = 0;
|
||||
for (i = 0; i < netbits; i++) {
|
||||
netmask = (netmask << 1) | 1;
|
||||
}
|
||||
netmask <<= (32 - netbits);
|
||||
net.s_addr = htonl(netmask);
|
||||
|
||||
if (inet_addr(ip) == INADDR_NONE) {
|
||||
fprintf(stderr, "Invalid IP: %s!\n", ip);
|
||||
return 1;
|
||||
}
|
||||
#ifndef WINDOWS32
|
||||
# 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,
|
||||
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),
|
||||
ROUTEPATH "route add %s/%d %s",
|
||||
inet_ntoa(netip), netbits, ip);
|
||||
}
|
||||
fprintf(stderr, "Adding route %s/%d to %s\n", inet_ntoa(netip), netbits, ip);
|
||||
#endif
|
||||
return system(cmdline);
|
||||
#else /* WINDOWS32 */
|
||||
|
||||
/* Set device as connected */
|
||||
fprintf(stderr, "Enabling interface '%s'\n", if_name);
|
||||
status = 1;
|
||||
r = DeviceIoControl(dev_handle, TAP_IOCTL_SET_MEDIA_STATUS, &status,
|
||||
sizeof(status), &status, sizeof(status), &len, NULL);
|
||||
if (!r) {
|
||||
fprintf(stderr, "Failed to enable interface\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (inet_aton(ip, &addr)) {
|
||||
ipdata[0] = (DWORD) addr.s_addr; /* local ip addr */
|
||||
ipdata[1] = net.s_addr & ipdata[0]; /* network addr */
|
||||
ipdata[2] = (DWORD) net.s_addr; /* netmask */
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Tell ip/networkaddr/netmask to device for arp use */
|
||||
r = DeviceIoControl(dev_handle, TAP_IOCTL_CONFIG_TUN, &ipdata,
|
||||
sizeof(ipdata), &ipdata, sizeof(ipdata), &len, NULL);
|
||||
if (!r) {
|
||||
fprintf(stderr, "Failed to set interface in TUN mode\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* use netsh to set ip address */
|
||||
fprintf(stderr, "Setting IP of interface '%s' to %s (can take a few seconds)...\n", if_name, ip);
|
||||
snprintf(cmdline, sizeof(cmdline), "netsh interface ip set address \"%s\" static %s %s",
|
||||
if_name, ip, inet_ntoa(net));
|
||||
return system(cmdline);
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
tun_setmtu(const unsigned mtu)
|
||||
{
|
||||
#ifndef WINDOWS32
|
||||
char cmdline[512];
|
||||
|
||||
if (mtu > 200 && mtu <= 1500) {
|
||||
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 {
|
||||
warn("MTU out of range: %u\n", mtu);
|
||||
}
|
||||
|
||||
return 1;
|
||||
#else /* WINDOWS32 */
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
28
third-party/iodine/src/tun.h
vendored
Normal file
28
third-party/iodine/src/tun.h
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
|
||||
*/
|
||||
|
||||
#ifndef _TUN_H_
|
||||
#define _TUN_H_
|
||||
|
||||
int open_tun(const char *);
|
||||
void close_tun(int);
|
||||
int write_tun(int, char *, size_t);
|
||||
ssize_t read_tun(int, char *, size_t);
|
||||
int tun_setip(const char *, const char *, int);
|
||||
int tun_setmtu(const unsigned);
|
||||
|
||||
#endif /* _TUN_H_ */
|
||||
184
third-party/iodine/src/user.c
vendored
Normal file
184
third-party/iodine/src/user.c
vendored
Normal file
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifdef WINDOWS32
|
||||
#include <winsock2.h>
|
||||
#else
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
#include "encoding.h"
|
||||
#include "user.h"
|
||||
|
||||
struct tun_user *users;
|
||||
unsigned usercount;
|
||||
|
||||
int init_users(in_addr_t my_ip, int netbits)
|
||||
{
|
||||
int i;
|
||||
int skip = 0;
|
||||
char newip[32];
|
||||
|
||||
int maxusers;
|
||||
|
||||
in_addr_t netmask = 0;
|
||||
struct in_addr net;
|
||||
struct in_addr ipstart;
|
||||
|
||||
for (i = 0; i < netbits; i++) {
|
||||
netmask = (netmask << 1) | 1;
|
||||
}
|
||||
netmask <<= (32 - netbits);
|
||||
net.s_addr = htonl(netmask);
|
||||
ipstart.s_addr = my_ip & net.s_addr;
|
||||
|
||||
maxusers = (1 << (32-netbits)) - 3; /* 3: Net addr, broadcast addr, iodined addr */
|
||||
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);
|
||||
ip = ipstart.s_addr + inet_addr(newip);
|
||||
if (ip == my_ip && skip == 0) {
|
||||
/* This IP was taken by iodined */
|
||||
skip++;
|
||||
snprintf(newip, sizeof(newip), "0.0.0.%d", i + skip + 1);
|
||||
ip = ipstart.s_addr + inet_addr(newip);
|
||||
}
|
||||
users[i].tun_ip = ip;
|
||||
net.s_addr = ip;
|
||||
users[i].disabled = 0;
|
||||
users[i].authenticated = 0;
|
||||
users[i].authenticated_raw = 0;
|
||||
users[i].options_locked = 0;
|
||||
users[i].active = 0;
|
||||
/* Rest is reset on login ('V' packet) */
|
||||
}
|
||||
|
||||
return usercount;
|
||||
}
|
||||
|
||||
const char *users_get_first_ip(void)
|
||||
{
|
||||
struct in_addr ip;
|
||||
ip.s_addr = users[0].tun_ip;
|
||||
return strdup(inet_ntoa(ip));
|
||||
}
|
||||
|
||||
int find_user_by_ip(uint32_t ip)
|
||||
{
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
ret = -1;
|
||||
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;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* If this returns true, then reading from tun device is blocked.
|
||||
So only return true when all clients have at least one packet in
|
||||
the outpacket-queue, so that sending back-to-back is possible
|
||||
without going through another select loop.
|
||||
*/
|
||||
int all_users_waiting_to_send(void)
|
||||
{
|
||||
time_t now;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
ret = 1;
|
||||
now = time(NULL);
|
||||
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)
|
||||
#ifdef OUTPACKETQ_LEN
|
||||
&& users[i].outpacketq_filled < 1
|
||||
#else
|
||||
&& users[i].outpacket.len == 0
|
||||
#endif
|
||||
))) {
|
||||
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int find_available_user(void)
|
||||
{
|
||||
int ret = -1;
|
||||
int 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].options_locked = 0;
|
||||
users[i].last_pkt = time(NULL);
|
||||
users[i].fragsize = 4096;
|
||||
users[i].conn = CONN_DNS_NULL;
|
||||
ret = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void user_switch_codec(int userid, const struct encoder *enc)
|
||||
{
|
||||
if (userid < 0 || userid >= usercount)
|
||||
return;
|
||||
|
||||
users[userid].encoder = enc;
|
||||
}
|
||||
|
||||
void user_set_conn_type(int userid, enum connection c)
|
||||
{
|
||||
if (userid < 0 || userid >= usercount)
|
||||
return;
|
||||
|
||||
if (c < CONN_RAW_UDP || c >= CONN_MAX)
|
||||
return;
|
||||
|
||||
users[userid].conn = c;
|
||||
}
|
||||
|
||||
91
third-party/iodine/src/user.h
vendored
Normal file
91
third-party/iodine/src/user.h
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
|
||||
*/
|
||||
|
||||
#ifndef __USER_H__
|
||||
#define __USER_H__
|
||||
|
||||
#define USERS 16
|
||||
|
||||
#define OUTPACKETQ_LEN 4 /* Note: 16 users * 1 packet = 1MB */
|
||||
/* Undefine to have no queue for packets coming in from tun device, which may
|
||||
lead to massive dropping in multi-user situations with high traffic. */
|
||||
|
||||
#define DNSCACHE_LEN 4
|
||||
/* Undefine to disable. Should be less than 18; also see comments in iodined.c */
|
||||
|
||||
|
||||
#define QMEMPING_LEN 30
|
||||
/* Max advisable: 64k/2 = 32000. Total mem usage: QMEMPING_LEN * USERS * 6 bytes */
|
||||
|
||||
#define QMEMDATA_LEN 15
|
||||
/* Max advisable: 36/2 = 18. Total mem usage: QMEMDATA_LEN * USERS * 6 bytes */
|
||||
|
||||
struct tun_user {
|
||||
char id;
|
||||
int active;
|
||||
int authenticated;
|
||||
int authenticated_raw;
|
||||
int options_locked;
|
||||
int disabled;
|
||||
time_t last_pkt;
|
||||
int seed;
|
||||
in_addr_t tun_ip;
|
||||
struct sockaddr_storage host;
|
||||
socklen_t hostlen;
|
||||
struct query q;
|
||||
struct query q_sendrealsoon;
|
||||
int q_sendrealsoon_new;
|
||||
struct packet inpacket;
|
||||
struct packet outpacket;
|
||||
int outfragresent;
|
||||
const struct encoder *encoder;
|
||||
char downenc;
|
||||
int out_acked_seqno;
|
||||
int out_acked_fragment;
|
||||
int fragsize;
|
||||
enum connection conn;
|
||||
int lazy;
|
||||
unsigned char qmemping_cmc[QMEMPING_LEN * 4];
|
||||
unsigned short qmemping_type[QMEMPING_LEN];
|
||||
int qmemping_lastfilled;
|
||||
unsigned char qmemdata_cmc[QMEMDATA_LEN * 4];
|
||||
unsigned short qmemdata_type[QMEMDATA_LEN];
|
||||
int qmemdata_lastfilled;
|
||||
#ifdef OUTPACKETQ_LEN
|
||||
struct packet outpacketq[OUTPACKETQ_LEN];
|
||||
int outpacketq_nexttouse;
|
||||
int outpacketq_filled;
|
||||
#endif
|
||||
#ifdef DNSCACHE_LEN
|
||||
struct query dnscache_q[DNSCACHE_LEN];
|
||||
char dnscache_answer[DNSCACHE_LEN][4096];
|
||||
int dnscache_answerlen[DNSCACHE_LEN];
|
||||
int dnscache_lastfilled;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern struct tun_user *users;
|
||||
|
||||
int init_users(in_addr_t, int);
|
||||
const char* users_get_first_ip(void);
|
||||
int find_user_by_ip(uint32_t);
|
||||
int all_users_waiting_to_send(void);
|
||||
int find_available_user(void);
|
||||
void user_switch_codec(int userid, const struct encoder *enc);
|
||||
void user_set_conn_type(int userid, enum connection c);
|
||||
|
||||
#endif
|
||||
89
third-party/iodine/src/util.c
vendored
Normal file
89
third-party/iodine/src/util.c
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "common.h"
|
||||
#include "util.h"
|
||||
|
||||
char *get_resolvconf_addr(void)
|
||||
{
|
||||
static char addr[257];
|
||||
char *rv = NULL;
|
||||
#ifndef WINDOWS32
|
||||
char buf[257];
|
||||
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, "%256s", addr) == 1)
|
||||
rv = addr;
|
||||
pclose(fp);
|
||||
#else
|
||||
if ((fp = fopen("/etc/resolv.conf", "r")) == NULL)
|
||||
err(1, "/etc/resolv.conf");
|
||||
|
||||
while (feof(fp) == 0) {
|
||||
fgets(buf, sizeof(buf), fp);
|
||||
|
||||
if (sscanf(buf, "nameserver %256s", addr) == 1) {
|
||||
rv = addr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
#endif
|
||||
#else /* !WINDOWS32 */
|
||||
FIXED_INFO *fixed_info;
|
||||
ULONG buflen;
|
||||
DWORD ret;
|
||||
|
||||
fixed_info = malloc(sizeof(FIXED_INFO));
|
||||
buflen = sizeof(FIXED_INFO);
|
||||
|
||||
if (GetNetworkParams(fixed_info, &buflen) == ERROR_BUFFER_OVERFLOW) {
|
||||
/* official ugly api workaround */
|
||||
free(fixed_info);
|
||||
fixed_info = malloc(buflen);
|
||||
}
|
||||
|
||||
ret = GetNetworkParams(fixed_info, &buflen);
|
||||
if (ret == NO_ERROR) {
|
||||
strncpy(addr, fixed_info->DnsServerList.IpAddress.String, sizeof(addr));
|
||||
addr[15] = 0;
|
||||
rv = addr;
|
||||
}
|
||||
free(fixed_info);
|
||||
#endif
|
||||
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
|
||||
24
third-party/iodine/src/util.h
vendored
Normal file
24
third-party/iodine/src/util.h
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
|
||||
*/
|
||||
|
||||
#ifndef __UTIL_H__
|
||||
#define __UTIL_H__
|
||||
|
||||
char *get_resolvconf_addr(void);
|
||||
void socket_setrtable(int fd, int rtable);
|
||||
|
||||
#endif
|
||||
26
third-party/iodine/src/version.h
vendored
Normal file
26
third-party/iodine/src/version.h
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
|
||||
*/
|
||||
|
||||
#ifndef _VERSION_H_
|
||||
#define _VERSION_H_
|
||||
|
||||
/* This is the version of the network protocol
|
||||
It is usually equal to the latest iodine version number */
|
||||
#define PROTOCOL_VERSION 0x00000502
|
||||
|
||||
#endif /* _VERSION_H_ */
|
||||
|
||||
105
third-party/iodine/src/windows.h
vendored
Normal file
105
third-party/iodine/src/windows.h
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
|
||||
*/
|
||||
|
||||
#ifndef __FIX_WINDOWS_H__
|
||||
#define __FIX_WINDOWS_H__
|
||||
|
||||
typedef unsigned int in_addr_t;
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include <windns.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <iphlpapi.h>
|
||||
|
||||
/* Missing from the mingw headers */
|
||||
#ifndef DNS_TYPE_SRV
|
||||
# define DNS_TYPE_SRV 33
|
||||
#endif
|
||||
#ifndef DNS_TYPE_TXT
|
||||
# define DNS_TYPE_TXT 16
|
||||
#endif
|
||||
|
||||
#define T_A DNS_TYPE_A
|
||||
#define T_NS DNS_TYPE_NS
|
||||
#define T_NULL DNS_TYPE_NULL
|
||||
#define T_CNAME DNS_TYPE_CNAME
|
||||
#define T_MX DNS_TYPE_MX
|
||||
#define T_TXT DNS_TYPE_TXT
|
||||
#define T_SOA DNS_TYPE_SOA
|
||||
#define T_SRV DNS_TYPE_SRV
|
||||
|
||||
#define C_IN 1
|
||||
|
||||
#define FORMERR 1
|
||||
#define SERVFAIL 2
|
||||
#define NXDOMAIN 3
|
||||
#define NOTIMP 4
|
||||
#define REFUSED 5
|
||||
|
||||
#define sleep(seconds) Sleep((seconds)*1000)
|
||||
|
||||
typedef struct {
|
||||
unsigned id :16; /* query identification number */
|
||||
/* 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 */
|
||||
/* 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;
|
||||
|
||||
struct ip {
|
||||
unsigned int ip_hl:4; /* header length */
|
||||
unsigned int ip_v:4; /* version */
|
||||
u_char ip_tos; /* type of service */
|
||||
u_short ip_len; /* total length */
|
||||
u_short ip_id; /* identification */
|
||||
u_short ip_off; /* fragment offset field */
|
||||
#define IP_RF 0x8000 /* reserved fragment flag */
|
||||
#define IP_DF 0x4000 /* dont fragment flag */
|
||||
#define IP_MF 0x2000 /* more fragments flag */
|
||||
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
|
||||
u_char ip_ttl; /* time to live */
|
||||
u_char ip_p; /* protocol */
|
||||
u_short ip_sum; /* checksum */
|
||||
struct in_addr ip_src, ip_dst; /* source and dest address */
|
||||
};
|
||||
|
||||
DWORD WINAPI tun_reader(LPVOID arg);
|
||||
struct tun_data {
|
||||
HANDLE tun;
|
||||
int sock;
|
||||
struct sockaddr_storage addr;
|
||||
int addrlen;
|
||||
};
|
||||
|
||||
/* No-op for now. */
|
||||
#define syslog(...)
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user