Tabz -> Spaces + whitespace

This commit is contained in:
Ryan Welton 2014-08-08 21:48:41 -04:00
parent 9a45c4aa66
commit 515bfb00a6
31 changed files with 5844 additions and 5844 deletions

View file

@ -2,14 +2,14 @@
policy_module(iodine, 1.1) policy_module(iodine, 1.1)
require { require {
type init_t; type init_t;
type initrc_t; type initrc_t;
type unconfined_t; type unconfined_t;
type unlabeled_t; type unlabeled_t;
class udp_socket { read write }; class udp_socket { read write };
class rawip_socket { write read }; class rawip_socket { write read };
class association recvfrom; class association recvfrom;
class unix_dgram_socket { create connect }; class unix_dgram_socket { create connect };
} }
type iodine_t; type iodine_t;

View file

@ -5,42 +5,42 @@ CMC = 2 byte Cache Miss Counter, increased every time it is used
Version: Version:
Client sends: Client sends:
First byte v or V First byte v or V
Rest encoded with base32: Rest encoded with base32:
4 bytes big endian protocol version 4 bytes big endian protocol version
CMC CMC
Server replies: Server replies:
4 chars: 4 chars:
VACK (version ok), followed by login challenge VACK (version ok), followed by login challenge
VNAK (version differs), followed by server protocol version VNAK (version differs), followed by server protocol version
VFUL (server has no free slots), followed by max users VFUL (server has no free slots), followed by max users
4 byte value: means login challenge/server protocol version/max users 4 byte value: means login challenge/server protocol version/max users
1 byte userid of the new user, or any byte if not VACK 1 byte userid of the new user, or any byte if not VACK
Login: Login:
Client sends: Client sends:
First byte l or L First byte l or L
Rest encoded with base32: Rest encoded with base32:
1 byte userid 1 byte userid
16 bytes MD5 hash of: (first 32 bytes of password) xor (8 repetitions of login challenge) 16 bytes MD5 hash of: (first 32 bytes of password) xor (8 repetitions of login challenge)
CMC CMC
Server replies: Server replies:
LNAK means not accepted LNAK means not accepted
x.x.x.x-y.y.y.y-mtu means accepted (server ip, client ip, mtu) x.x.x.x-y.y.y.y-mtu means accepted (server ip, client ip, mtu)
Case check: Case check:
Client sends: Client sends:
First byte z or Z First byte z or Z
Lots of data that should not be decoded Lots of data that should not be decoded
Server replies: Server replies:
The requested domain copied raw The requested domain copied raw
Data: Data:
Data header: Data header:
321 0 321 0
+---+-+ +---+-+
|UUU|L| |UUU|L|
+---+-+ +---+-+
UUU = Userid UUU = Userid
L = Last fragment in packet flag L = Last fragment in packet flag
@ -50,10 +50,10 @@ Followed by data encoded with Base32.
Ping: Ping:
Client sends: Client sends:
First byte p or P First byte p or P
Rest encoded with Base32: Rest encoded with Base32:
1 byte userid 1 byte userid
CMC CMC
The server response to Ping and Data packets is a DNS NULL type response: The server response to Ping and Data packets is a DNS NULL type response:
If server has nothing to send, data length is 0 bytes. If server has nothing to send, data length is 0 bytes.

View file

@ -5,82 +5,82 @@ CMC = 2 byte Cache Miss Counter, increased every time it is used
Version: Version:
Client sends: Client sends:
First byte v or V First byte v or V
Rest encoded with base32: Rest encoded with base32:
4 bytes big endian protocol version 4 bytes big endian protocol version
CMC CMC
Server replies: Server replies:
4 chars: 4 chars:
VACK (version ok), followed by login challenge VACK (version ok), followed by login challenge
VNAK (version differs), followed by server protocol version VNAK (version differs), followed by server protocol version
VFUL (server has no free slots), followed by max users VFUL (server has no free slots), followed by max users
4 byte value: means login challenge/server protocol version/max users 4 byte value: means login challenge/server protocol version/max users
1 byte userid of the new user, or any byte if not VACK 1 byte userid of the new user, or any byte if not VACK
Login: Login:
Client sends: Client sends:
First byte l or L First byte l or L
Rest encoded with base32: Rest encoded with base32:
1 byte userid 1 byte userid
16 bytes MD5 hash of: (first 32 bytes of password) xor (8 repetitions of login challenge) 16 bytes MD5 hash of: (first 32 bytes of password) xor (8 repetitions of login challenge)
CMC CMC
Server replies: Server replies:
LNAK means not accepted LNAK means not accepted
x.x.x.x-y.y.y.y-mtu-netmask means accepted (server ip, client ip, mtu, netmask bits) x.x.x.x-y.y.y.y-mtu-netmask means accepted (server ip, client ip, mtu, netmask bits)
Case check: Case check:
Client sends: Client sends:
First byte z or Z First byte z or Z
Lots of data that should not be decoded Lots of data that should not be decoded
Server replies: Server replies:
The requested domain copied raw The requested domain copied raw
Switch codec: Switch codec:
Client sends: Client sends:
First byte s or S First byte s or S
5 bits coded as Base32 char, meaning userid 5 bits coded as Base32 char, meaning userid
5 bits coded as Base32 char, with value 5 or 6, representing number of raw 5 bits coded as Base32 char, with value 5 or 6, representing number of raw
bits per encoded byte bits per encoded byte
Server sends: Server sends:
Name of codec if accepted. After this all upstream data packets must Name of codec if accepted. After this all upstream data packets must
be encoded with the new codec. be encoded with the new codec.
BADCODEC if not accepted. Client must then revert to Base32 BADCODEC if not accepted. Client must then revert to Base32
Probe downstream fragment size: Probe downstream fragment size:
Client sends: Client sends:
First byte r or R First byte r or R
15 bits coded as 3 Base32 chars: UUUUF FFFFF FFFFF 15 bits coded as 3 Base32 chars: UUUUF FFFFF FFFFF
meaning 4 bits userid, 11 bits fragment size meaning 4 bits userid, 11 bits fragment size
Then follows a long random query which contents does not matter Then follows a long random query which contents does not matter
Server sends: Server sends:
Requested number of bytes as a response. The first two bytes contains Requested number of bytes as a response. The first two bytes contains
the requested length. Rest of message can be any data. the requested length. Rest of message can be any data.
BADFRAG if requested length not accepted. BADFRAG if requested length not accepted.
Set downstream fragment size: Set downstream fragment size:
Client sends: Client sends:
First byte n or N First byte n or N
Rest encoded with base32: Rest encoded with base32:
1 byte userid 1 byte userid
2 bytes new downstream fragment size 2 bytes new downstream fragment size
CMC CMC
Server sends: Server sends:
2 bytes new downstream fragment size. After this all downstream 2 bytes new downstream fragment size. After this all downstream
payloads will be max (fragsize + 2) bytes long. payloads will be max (fragsize + 2) bytes long.
BADFRAG if not accepted. BADFRAG if not accepted.
Data: Data:
Upstream data header: Upstream data header:
3210 432 10 43 210 4321 0 3210 432 10 43 210 4321 0
+----+---+--+--+---+----+-+ +----+---+--+--+---+----+-+
|UUUU|SSS|FF|FF|DDD|GGGG|L| |UUUU|SSS|FF|FF|DDD|GGGG|L|
+----+---+--+--+---+----+-+ +----+---+--+--+---+----+-+
Downstream data header: Downstream data header:
7 654 3210 765 4321 0 7 654 3210 765 4321 0
+-+---+----+---+----+-+ +-+---+----+---+----+-+
|C|SSS|FFFF|DDD|GGGG|L| |C|SSS|FFFF|DDD|GGGG|L|
+-+---+----+---+----+-+ +-+---+----+---+----+-+
UUUU = Userid UUUU = Userid
L = Last fragment in packet flag L = Last fragment in packet flag
@ -98,13 +98,13 @@ compressed.
Ping: Ping:
Client sends: Client sends:
First byte p or P First byte p or P
Rest encoded with Base32: Rest encoded with Base32:
1 byte with 4 bits userid 1 byte with 4 bits userid
1 byte with: 1 byte with:
3 bits downstream seqno 3 bits downstream seqno
4 bits downstream fragment 4 bits downstream fragment
CMC CMC
The server response to Ping and Data packets is a DNS NULL type response: The server response to Ping and Data packets is a DNS NULL type response:
If server has nothing to send, data length is 0 bytes. If server has nothing to send, data length is 0 bytes.

View file

@ -8,170 +8,170 @@ Note: work in progress!!
====================================================== ======================================================
Quick alphabetical index / register: Quick alphabetical index / register:
0-9 Data packet 0-9 Data packet
A-F Data packet A-F Data packet
I IP address I IP address
L Login L Login
N Downstream fragsize (NS.topdomain A-type reply) N Downstream fragsize (NS.topdomain A-type reply)
O Options O Options
P Ping P Ping
R Downstream fragsize probe R Downstream fragsize probe
S Switch upstream codec S Switch upstream codec
V Version V Version
W (WWW.topdomain A-type reply) W (WWW.topdomain A-type reply)
Y Downstream codec check Y Downstream codec check
Z Upstream codec check Z Upstream codec check
CMC = 2 byte Cache Miss Counter, increased every time it is used CMC = 2 byte Cache Miss Counter, increased every time it is used
Version: Version:
Client sends: Client sends:
First byte v or V First byte v or V
Rest encoded with base32: Rest encoded with base32:
4 bytes big endian protocol version 4 bytes big endian protocol version
CMC CMC
Server replies: Server replies:
4 chars: 4 chars:
VACK (version ok), followed by login challenge VACK (version ok), followed by login challenge
VNAK (version differs), followed by server protocol version VNAK (version differs), followed by server protocol version
VFUL (server has no free slots), followed by max users VFUL (server has no free slots), followed by max users
4 byte value: means login challenge/server protocol version/max users 4 byte value: means login challenge/server protocol version/max users
1 byte userid of the new user, or any byte if not VACK 1 byte userid of the new user, or any byte if not VACK
Login: Login:
Client sends: Client sends:
First byte l or L First byte l or L
Rest encoded with base32: Rest encoded with base32:
1 byte userid 1 byte userid
16 bytes MD5 hash of: (first 32 bytes of password) xor (8 repetitions of login challenge) 16 bytes MD5 hash of: (first 32 bytes of password) xor (8 repetitions of login challenge)
CMC CMC
Server replies: Server replies:
LNAK means not accepted LNAK means not accepted
x.x.x.x-y.y.y.y-mtu-netmask means accepted (server ip, client ip, mtu, netmask bits) x.x.x.x-y.y.y.y-mtu-netmask means accepted (server ip, client ip, mtu, netmask bits)
IP Request: IP Request:
Client sends: Client sends:
First byte i or I First byte i or I
5 bits coded as Base32 char, meaning userid 5 bits coded as Base32 char, meaning userid
CMC as 3 Base32 chars CMC as 3 Base32 chars
Server replies Server replies
BADIP if bad userid, or BADIP if bad userid, or
I and then 4 bytes network order external IP address of iodined server I and then 4 bytes network order external IP address of iodined server
Upstream codec check / bounce: Upstream codec check / bounce:
Client sends: Client sends:
First byte z or Z First byte z or Z
Lots of data that should not be decoded Lots of data that should not be decoded
Server replies: Server replies:
The requested domain copied raw, in the lowest-grade downstream codec The requested domain copied raw, in the lowest-grade downstream codec
available for the request type. available for the request type.
Downstream codec check: Downstream codec check:
Client sends: Client sends:
First byte y or Y First byte y or Y
1 char, meaning downstream codec to use 1 char, meaning downstream codec to use
5 bits coded as Base32 char, meaning check variant 5 bits coded as Base32 char, meaning check variant
CMC as 3 Base32 chars CMC as 3 Base32 chars
Possibly extra data, depending on check variant Possibly extra data, depending on check variant
Server sends: Server sends:
Data encoded with requested downstream codec; data content depending Data encoded with requested downstream codec; data content depending
on check variant number. on check variant number.
BADCODEC if requested downstream codec not available. BADCODEC if requested downstream codec not available.
BADLEN if check variant is not available, or problem with extra data. BADLEN if check variant is not available, or problem with extra data.
Downstream codec chars are same as in 'O' Option request, below. Downstream codec chars are same as in 'O' Option request, below.
Check variants: Check variants:
1: Send encoded DOWNCODECCHECK1 string as defined in encoding.h 1: Send encoded DOWNCODECCHECK1 string as defined in encoding.h
(Other variants reserved; possibly variant that sends a decoded-encoded (Other variants reserved; possibly variant that sends a decoded-encoded
copy of Base32-encoded extra data in the request) copy of Base32-encoded extra data in the request)
Switch codec: Switch codec:
Client sends: Client sends:
First byte s or S First byte s or S
5 bits coded as Base32 char, meaning userid 5 bits coded as Base32 char, meaning userid
5 bits coded as Base32 char, representing number of raw bits per 5 bits coded as Base32 char, representing number of raw bits per
encoded byte: encoded byte:
5: Base32 (a-z0-5) 5: Base32 (a-z0-5)
6: Base64 (a-zA-Z0-9+-) 6: Base64 (a-zA-Z0-9+-)
26: Base64u (a-zA-Z0-9_-) 26: Base64u (a-zA-Z0-9_-)
7: Base128 (a-zA-Z0-9\274-\375) 7: Base128 (a-zA-Z0-9\274-\375)
CMC as 3 Base32 chars CMC as 3 Base32 chars
Server sends: Server sends:
Name of codec if accepted. After this all upstream data packets must Name of codec if accepted. After this all upstream data packets must
be encoded with the new codec. be encoded with the new codec.
BADCODEC if not accepted. Client must then revert to previous codec BADCODEC if not accepted. Client must then revert to previous codec
BADLEN if length of query is too short BADLEN if length of query is too short
Options: Options:
Client sends: Client sends:
First byte o or O First byte o or O
5 bits coded as Base32 char, meaning userid 5 bits coded as Base32 char, meaning userid
1 char, meaning option 1 char, meaning option
CMC as 3 Base32 chars CMC as 3 Base32 chars
Server sends: Server sends:
Full name of option if accepted. After this, option immediately takes Full name of option if accepted. After this, option immediately takes
effect in server. effect in server.
BADCODEC if not accepted. Previous situation remains. BADCODEC if not accepted. Previous situation remains.
All options affect only the requesting client. All options affect only the requesting client.
Option chars: Option chars:
t or T: Downstream encoding Base32, for TXT/CNAME/A/MX (default) t or T: Downstream encoding Base32, for TXT/CNAME/A/MX (default)
s or S: Downstream encoding Base64, for TXT/CNAME/A/MX s or S: Downstream encoding Base64, for TXT/CNAME/A/MX
u or U: Downstream encoding Base64u, for TXT/CNAME/A/MX u or U: Downstream encoding Base64u, for TXT/CNAME/A/MX
v or V: Downstream encoding Base128, for TXT/CNAME/A/MX v or V: Downstream encoding Base128, for TXT/CNAME/A/MX
r or R: Downstream encoding Raw, for PRIVATE/TXT/NULL (default for r or R: Downstream encoding Raw, for PRIVATE/TXT/NULL (default for
PRIVATE and NULL) PRIVATE and NULL)
If codec unsupported for request type, server will use Base32; note If codec unsupported for request type, server will use Base32; note
that server will answer any mix of request types that a client sends. that server will answer any mix of request types that a client sends.
Server may disregard this option; client must always use the downstream Server may disregard this option; client must always use the downstream
encoding type indicated in every downstream DNS packet. encoding type indicated in every downstream DNS packet.
l or L: Lazy mode, server will keep one request unanswered until the l or L: Lazy mode, server will keep one request unanswered until the
next one comes in. Applies only to data transfer; handshake is always next one comes in. Applies only to data transfer; handshake is always
answered immediately. answered immediately.
i or I: Immediate (non-lazy) mode, server will answer all requests i or I: Immediate (non-lazy) mode, server will answer all requests
(nearly) immediately. (nearly) immediately.
Probe downstream fragment size: Probe downstream fragment size:
Client sends: Client sends:
First byte r or R First byte r or R
15 bits coded as 3 Base32 chars: UUUUF FFFFF FFFFF 15 bits coded as 3 Base32 chars: UUUUF FFFFF FFFFF
meaning 4 bits userid, 11 bits fragment size meaning 4 bits userid, 11 bits fragment size
Then follows a long random query which contents does not matter Then follows a long random query which contents does not matter
Server sends: Server sends:
Requested number of bytes as a response. The first two bytes contain Requested number of bytes as a response. The first two bytes contain
the requested length. The third byte is 107 (0x6B). The fourth byte the requested length. The third byte is 107 (0x6B). The fourth byte
is a random value, and each following byte is incremented with 107. is a random value, and each following byte is incremented with 107.
This is checked by the client to determine corruption. This is checked by the client to determine corruption.
BADFRAG if requested length not accepted. BADFRAG if requested length not accepted.
Set downstream fragment size: Set downstream fragment size:
Client sends: Client sends:
First byte n or N First byte n or N
Rest encoded with base32: Rest encoded with base32:
1 byte userid 1 byte userid
2 bytes new downstream fragment size 2 bytes new downstream fragment size
CMC CMC
Server sends: Server sends:
2 bytes new downstream fragment size. After this all downstream 2 bytes new downstream fragment size. After this all downstream
payloads will be max (fragsize + 2) bytes long. payloads will be max (fragsize + 2) bytes long.
BADFRAG if not accepted. BADFRAG if not accepted.
Data: Data:
Upstream data header: Upstream data header:
3210 432 10 43 210 4321 0 43210 3210 432 10 43 210 4321 0 43210
+----+---+--+--+---+----+-+-----+ +----+---+--+--+---+----+-+-----+
|UUUU|SSS|FF|FF|DDD|GGGG|L|UDCMC| |UUUU|SSS|FF|FF|DDD|GGGG|L|UDCMC|
+----+---+--+--+---+----+-+-----+ +----+---+--+--+---+----+-+-----+
Downstream data header: Downstream data header:
7 654 3210 765 4321 0 7 654 3210 765 4321 0
+-+---+----+---+----+-+ +-+---+----+---+----+-+
|C|SSS|FFFF|DDD|GGGG|L| |C|SSS|FFFF|DDD|GGGG|L|
+-+---+----+---+----+-+ +-+---+----+---+----+-+
UUUU = Userid UUUU = Userid
L = Last fragment in packet flag L = Last fragment in packet flag
@ -193,18 +193,18 @@ In NULL and PRIVATE responses, downstream data is always raw. In all other
response types, downstream data is encoded (see Options above). response types, downstream data is encoded (see Options above).
Encoding type is indicated by 1 prefix char: Encoding type is indicated by 1 prefix char:
TXT: TXT:
End result is always DNS-chopped (series of len-prefixed strings End result is always DNS-chopped (series of len-prefixed strings
<=255 bytes) <=255 bytes)
t or T: Base32 encoded before chop, decoded after un-chop t or T: Base32 encoded before chop, decoded after un-chop
s or S: Base64 encoded before chop, decoded after un-chop s or S: Base64 encoded before chop, decoded after un-chop
u or U: Base64u encoded before chop, decoded after un-chop u or U: Base64u encoded before chop, decoded after un-chop
v or V: Base128 encoded before chop, decoded after un-chop v or V: Base128 encoded before chop, decoded after un-chop
r or R: Raw no encoding, only DNS-chop r or R: Raw no encoding, only DNS-chop
SRV/MX/CNAME/A: SRV/MX/CNAME/A:
h or H: Hostname encoded with Base32 h or H: Hostname encoded with Base32
i or I: Hostname encoded with Base64 i or I: Hostname encoded with Base64
j or J: Hostname encoded with Base64u j or J: Hostname encoded with Base64u
k or K: Hostname encoded with Base128 k or K: Hostname encoded with Base128
SRV and MX may reply with multiple hostnames, each encoded separately. Each SRV and MX may reply with multiple hostnames, each encoded separately. Each
has a 10-multiple priority, and encoding/decoding is done in strictly has a 10-multiple priority, and encoding/decoding is done in strictly
increasing priority sequence 10, 20, 30, etc. without gaps. Note that some DNS increasing priority sequence 10, 20, 30, etc. without gaps. Note that some DNS
@ -212,13 +212,13 @@ relays will shuffle the answer records in the response.
Ping: Ping:
Client sends: Client sends:
First byte p or P First byte p or P
Rest encoded with Base32: Rest encoded with Base32:
1 byte with 4 bits userid 1 byte with 4 bits userid
1 byte with: 1 byte with:
3 bits downstream seqno 3 bits downstream seqno
4 bits downstream fragment 4 bits downstream fragment
CMC CMC
The server response to Ping and Data packets is a DNS NULL/TXT/.. type response, The server response to Ping and Data packets is a DNS NULL/TXT/.. type response,
always starting with the 2 bytes downstream data header as shown above. always starting with the 2 bytes downstream data header as shown above.
@ -268,10 +268,10 @@ All Raw UDP protcol messages start with a 3 byte header: 0x10d19e
This is not the start of a valid DNS message so it is easy to identify. This is not the start of a valid DNS message so it is easy to identify.
The fourth byte contains the command and the user id. The fourth byte contains the command and the user id.
7654 3210 7654 3210
+----+----+ +----+----+
|CCCC|UUUU| |CCCC|UUUU|
+----+----+ +----+----+
Login message (command = 1): Login message (command = 1):
The header is followed by a MD5 hash with the same password as in the DNS The header is followed by a MD5 hash with the same password as in the DNS

View file

@ -18,37 +18,37 @@
#define __FIX_ANDROID_H__ #define __FIX_ANDROID_H__
typedef struct { typedef struct {
unsigned id :16; unsigned id :16;
unsigned rd :1; unsigned rd :1;
unsigned tc :1; unsigned tc :1;
unsigned aa :1; unsigned aa :1;
unsigned opcode :4; unsigned opcode :4;
unsigned qr :1; unsigned qr :1;
unsigned rcode :4; unsigned rcode :4;
unsigned cd: 1; unsigned cd: 1;
unsigned ad: 1; unsigned ad: 1;
unsigned unused :1; unsigned unused :1;
unsigned ra :1; unsigned ra :1;
unsigned qdcount :16; unsigned qdcount :16;
unsigned ancount :16; unsigned ancount :16;
unsigned nscount :16; unsigned nscount :16;
unsigned arcount :16; unsigned arcount :16;
} HEADER; } HEADER;
#define NOERROR 0 #define NOERROR 0
#define FORMERR 1 #define FORMERR 1
#define SERVFAIL 2 #define SERVFAIL 2
#define NXDOMAIN 3 #define NXDOMAIN 3
#define NOTIMP 4 #define NOTIMP 4
#define REFUSED 5 #define REFUSED 5
#define C_IN 1 #define C_IN 1
#define T_A 1 #define T_A 1
#define T_CNAME 5 #define T_CNAME 5
#define T_NULL 10 #define T_NULL 10
#define T_MX 15 #define T_MX 15
#define T_TXT 16 #define T_TXT 16
#define T_SRV 33 #define T_SRV 33
#endif #endif

File diff suppressed because it is too large Load diff

View file

@ -60,44 +60,44 @@ const unsigned char raw_header[RAW_HDR_LEN] = { 0x10, 0xd1, 0x9e, 0x00 };
#if !defined(ANDROID) && !defined(WINDOWS32) && !(defined(BSD) && (BSD >= 199306)) && !defined(__GLIBC__) #if !defined(ANDROID) && !defined(WINDOWS32) && !(defined(BSD) && (BSD >= 199306)) && !defined(__GLIBC__)
static int daemon(int nochdir, int noclose) static int daemon(int nochdir, int noclose)
{ {
int fd, i; int fd, i;
switch (fork()) { switch (fork()) {
case 0: case 0:
break; break;
case -1: case -1:
return -1; return -1;
default: default:
_exit(0); _exit(0);
} }
if (!nochdir) { if (!nochdir) {
chdir("/"); chdir("/");
} }
if (setsid() < 0) { if (setsid() < 0) {
return -1; return -1;
} }
if (!noclose) { if (!noclose) {
if ((fd = open("/dev/null", O_RDWR)) >= 0) { if ((fd = open("/dev/null", O_RDWR)) >= 0) {
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
dup2(fd, i); dup2(fd, i);
} }
if (fd > 2) { if (fd > 2) {
close(fd); close(fd);
} }
} }
} }
return 0; return 0;
} }
#endif #endif
#if defined(__BEOS__) && !defined(__HAIKU__) #if defined(__BEOS__) && !defined(__HAIKU__)
int setgroups(int count, int *groups) int setgroups(int count, int *groups)
{ {
/* errno = ENOSYS; */ /* errno = ENOSYS; */
return -1; return -1;
} }
#endif #endif
@ -106,138 +106,138 @@ void
check_superuser(void (*usage_fn)(void)) check_superuser(void (*usage_fn)(void))
{ {
#ifndef WINDOWS32 #ifndef WINDOWS32
if (geteuid() != 0) { if (geteuid() != 0) {
warnx("Run as root and you'll be happy.\n"); warnx("Run as root and you'll be happy.\n");
usage_fn(); usage_fn();
/* NOTREACHED */ /* NOTREACHED */
} }
#endif #endif
} }
char * char *
format_addr(struct sockaddr_storage *sockaddr, int sockaddr_len) format_addr(struct sockaddr_storage *sockaddr, int sockaddr_len)
{ {
static char dst[INET6_ADDRSTRLEN + 1]; static char dst[INET6_ADDRSTRLEN + 1];
memset(dst, 0, sizeof(dst)); memset(dst, 0, sizeof(dst));
if (sockaddr->ss_family == AF_INET && sockaddr_len >= sizeof(struct sockaddr_in)) { 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); 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)) { } else if (sockaddr->ss_family == AF_INET6 && sockaddr_len >= sizeof(struct sockaddr_in6)) {
struct sockaddr_in6 *addr = (struct sockaddr_in6 *) sockaddr; struct sockaddr_in6 *addr = (struct sockaddr_in6 *) sockaddr;
if (IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr)) { if (IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr)) {
struct in_addr ia; struct in_addr ia;
/* Get mapped v4 addr from last 32bit field */ /* Get mapped v4 addr from last 32bit field */
memcpy(&ia.s_addr, &addr->sin6_addr.s6_addr[12], sizeof(ia)); memcpy(&ia.s_addr, &addr->sin6_addr.s6_addr[12], sizeof(ia));
strcpy(dst, inet_ntoa(ia)); strcpy(dst, inet_ntoa(ia));
} else { } else {
getnameinfo((struct sockaddr *)sockaddr, sockaddr_len, dst, sizeof(dst) - 1, NULL, 0, NI_NUMERICHOST); getnameinfo((struct sockaddr *)sockaddr, sockaddr_len, dst, sizeof(dst) - 1, NULL, 0, NI_NUMERICHOST);
} }
} else { } else {
dst[0] = '?'; dst[0] = '?';
} }
return dst; return dst;
} }
int int
get_addr(char *host, int port, int addr_family, int flags, struct sockaddr_storage *out) get_addr(char *host, int port, int addr_family, int flags, struct sockaddr_storage *out)
{ {
struct addrinfo hints, *addr; struct addrinfo hints, *addr;
int res; int res;
char portnum[8]; char portnum[8];
memset(portnum, 0, sizeof(portnum)); memset(portnum, 0, sizeof(portnum));
snprintf(portnum, sizeof(portnum) - 1, "%d", port); snprintf(portnum, sizeof(portnum) - 1, "%d", port);
memset(&hints, 0, sizeof(hints)); memset(&hints, 0, sizeof(hints));
hints.ai_family = addr_family; hints.ai_family = addr_family;
#if defined(WINDOWS32) || defined(OPENBSD) #if defined(WINDOWS32) || defined(OPENBSD)
/* AI_ADDRCONFIG misbehaves on windows, and does not exist in OpenBSD */ /* AI_ADDRCONFIG misbehaves on windows, and does not exist in OpenBSD */
hints.ai_flags = flags; hints.ai_flags = flags;
#else #else
hints.ai_flags = AI_ADDRCONFIG | flags; hints.ai_flags = AI_ADDRCONFIG | flags;
#endif #endif
hints.ai_socktype = SOCK_DGRAM; hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP; hints.ai_protocol = IPPROTO_UDP;
res = getaddrinfo(host, portnum, &hints, &addr); res = getaddrinfo(host, portnum, &hints, &addr);
if (res == 0) { if (res == 0) {
int addrlen = addr->ai_addrlen; int addrlen = addr->ai_addrlen;
/* Grab first result */ /* Grab first result */
memcpy(out, addr->ai_addr, addr->ai_addrlen); memcpy(out, addr->ai_addr, addr->ai_addrlen);
freeaddrinfo(addr); freeaddrinfo(addr);
return addrlen; return addrlen;
} }
return res; return res;
} }
int int
open_dns(struct sockaddr_storage *sockaddr, size_t sockaddr_len) open_dns(struct sockaddr_storage *sockaddr, size_t sockaddr_len)
{ {
int flag = 1; int flag = 1;
int fd; int fd;
if ((fd = socket(sockaddr->ss_family, SOCK_DGRAM, IPPROTO_UDP)) < 0) { if ((fd = socket(sockaddr->ss_family, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
err(1, "socket"); err(1, "socket");
} }
flag = 1; flag = 1;
#ifdef SO_REUSEPORT #ifdef SO_REUSEPORT
setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (const void*) &flag, sizeof(flag)); setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (const void*) &flag, sizeof(flag));
#endif #endif
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void*) &flag, sizeof(flag)); setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void*) &flag, sizeof(flag));
#ifndef WINDOWS32 #ifndef WINDOWS32
/* To get destination address from each UDP datagram, see iodined.c:read_dns() */ /* To get destination address from each UDP datagram, see iodined.c:read_dns() */
setsockopt(fd, IPPROTO_IP, DSTADDR_SOCKOPT, (const void*) &flag, sizeof(flag)); setsockopt(fd, IPPROTO_IP, DSTADDR_SOCKOPT, (const void*) &flag, sizeof(flag));
fd_set_close_on_exec(fd); fd_set_close_on_exec(fd);
#endif #endif
#ifdef IP_OPT_DONT_FRAG #ifdef IP_OPT_DONT_FRAG
/* Set dont-fragment ip header flag */ /* Set dont-fragment ip header flag */
flag = DONT_FRAG_VALUE; flag = DONT_FRAG_VALUE;
setsockopt(fd, IPPROTO_IP, IP_OPT_DONT_FRAG, (const void*) &flag, sizeof(flag)); setsockopt(fd, IPPROTO_IP, IP_OPT_DONT_FRAG, (const void*) &flag, sizeof(flag));
#endif #endif
if(bind(fd, (struct sockaddr*) sockaddr, sockaddr_len) < 0) if(bind(fd, (struct sockaddr*) sockaddr, sockaddr_len) < 0)
err(1, "bind"); err(1, "bind");
fprintf(stderr, "Opened IPv%d UDP socket\n", sockaddr->ss_family == AF_INET6 ? 6 : 4); fprintf(stderr, "Opened IPv%d UDP socket\n", sockaddr->ss_family == AF_INET6 ? 6 : 4);
return fd; return fd;
} }
int int
open_dns_from_host(char *host, int port, int addr_family, int flags) open_dns_from_host(char *host, int port, int addr_family, int flags)
{ {
struct sockaddr_storage addr; struct sockaddr_storage addr;
int addrlen; int addrlen;
addrlen = get_addr(host, port, addr_family, flags, &addr); addrlen = get_addr(host, port, addr_family, flags, &addr);
if (addrlen < 0) if (addrlen < 0)
return addrlen; return addrlen;
return open_dns(&addr, addrlen); return open_dns(&addr, addrlen);
} }
void void
close_dns(int fd) close_dns(int fd)
{ {
close(fd); close(fd);
} }
void void
do_chroot(char *newroot) do_chroot(char *newroot)
{ {
#if !(defined(WINDOWS32) || defined(__BEOS__) || defined(__HAIKU__)) #if !(defined(WINDOWS32) || defined(__BEOS__) || defined(__HAIKU__))
if (chroot(newroot) != 0 || chdir("/") != 0) if (chroot(newroot) != 0 || chdir("/") != 0)
err(1, "%s", newroot); err(1, "%s", newroot);
if (seteuid(geteuid()) != 0 || setuid(getuid()) != 0) { if (seteuid(geteuid()) != 0 || setuid(getuid()) != 0) {
err(1, "set[e]uid()"); err(1, "set[e]uid()");
} }
#else #else
warnx("chroot not available"); warnx("chroot not available");
#endif #endif
} }
@ -245,10 +245,10 @@ void
do_setcon(char *context) do_setcon(char *context)
{ {
#ifdef HAVE_SETCON #ifdef HAVE_SETCON
if (-1 == setcon(context)) if (-1 == setcon(context))
err(1, "%s", context); err(1, "%s", context);
#else #else
warnx("No SELinux support built in"); warnx("No SELinux support built in");
#endif #endif
} }
@ -256,17 +256,17 @@ void
do_pidfile(char *pidfile) do_pidfile(char *pidfile)
{ {
#ifndef WINDOWS32 #ifndef WINDOWS32
FILE *file; FILE *file;
if ((file = fopen(pidfile, "w")) == NULL) { if ((file = fopen(pidfile, "w")) == NULL) {
syslog(LOG_ERR, "Cannot write pidfile to %s, exiting", pidfile); syslog(LOG_ERR, "Cannot write pidfile to %s, exiting", pidfile);
err(1, "do_pidfile: Can not write pidfile to %s", pidfile); err(1, "do_pidfile: Can not write pidfile to %s", pidfile);
} else { } else {
fprintf(file, "%d\n", (int)getpid()); fprintf(file, "%d\n", (int)getpid());
fclose(file); fclose(file);
} }
#else #else
fprintf(stderr, "Windows version does not support pid file\n"); fprintf(stderr, "Windows version does not support pid file\n");
#endif #endif
} }
@ -274,117 +274,117 @@ void
do_detach() do_detach()
{ {
#ifndef WINDOWS32 #ifndef WINDOWS32
fprintf(stderr, "Detaching from terminal...\n"); fprintf(stderr, "Detaching from terminal...\n");
daemon(0, 0); daemon(0, 0);
umask(0); umask(0);
alarm(0); alarm(0);
#else #else
fprintf(stderr, "Windows version does not support detaching\n"); fprintf(stderr, "Windows version does not support detaching\n");
#endif #endif
} }
void void
read_password(char *buf, size_t len) read_password(char *buf, size_t len)
{ {
char pwd[80] = {0}; char pwd[80] = {0};
#ifndef WINDOWS32 #ifndef WINDOWS32
struct termios old; struct termios old;
struct termios tp; struct termios tp;
tcgetattr(0, &tp); tcgetattr(0, &tp);
old = tp; old = tp;
tp.c_lflag &= (~ECHO); tp.c_lflag &= (~ECHO);
tcsetattr(0, TCSANOW, &tp); tcsetattr(0, TCSANOW, &tp);
#else #else
int i; int i;
#endif #endif
fprintf(stderr, "Enter password: "); fprintf(stderr, "Enter password: ");
fflush(stderr); fflush(stderr);
#ifndef WINDOWS32 #ifndef WINDOWS32
fscanf(stdin, "%79[^\n]", pwd); fscanf(stdin, "%79[^\n]", pwd);
#else #else
for (i = 0; i < sizeof(pwd); i++) { for (i = 0; i < sizeof(pwd); i++) {
pwd[i] = getch(); pwd[i] = getch();
if (pwd[i] == '\r' || pwd[i] == '\n') { if (pwd[i] == '\r' || pwd[i] == '\n') {
pwd[i] = 0; pwd[i] = 0;
break; break;
} else if (pwd[i] == '\b') { } else if (pwd[i] == '\b') {
i--; /* Remove the \b char */ i--; /* Remove the \b char */
if (i >=0) i--; /* If not first char, remove one more */ if (i >=0) i--; /* If not first char, remove one more */
} }
} }
#endif #endif
fprintf(stderr, "\n"); fprintf(stderr, "\n");
#ifndef WINDOWS32 #ifndef WINDOWS32
tcsetattr(0, TCSANOW, &old); tcsetattr(0, TCSANOW, &old);
#endif #endif
strncpy(buf, pwd, len); strncpy(buf, pwd, len);
buf[len-1] = '\0'; buf[len-1] = '\0';
} }
int int
check_topdomain(char *str, char **errormsg) check_topdomain(char *str, char **errormsg)
{ {
int i; int i;
int dots = 0; int dots = 0;
int chunklen = 0; int chunklen = 0;
if (strlen(str) < 3) { if (strlen(str) < 3) {
if (errormsg) *errormsg = "Too short (< 3)"; if (errormsg) *errormsg = "Too short (< 3)";
return 1; return 1;
} }
if (strlen(str) > 128) { if (strlen(str) > 128) {
if (errormsg) *errormsg = "Too long (> 128)"; if (errormsg) *errormsg = "Too long (> 128)";
return 1; return 1;
} }
if (str[0] == '.') { if (str[0] == '.') {
if (errormsg) *errormsg = "Starts with a dot"; if (errormsg) *errormsg = "Starts with a dot";
return 1; return 1;
} }
for( i = 0; i < strlen(str); i++) { for( i = 0; i < strlen(str); i++) {
if(str[i] == '.') { if(str[i] == '.') {
dots++; dots++;
if (chunklen == 0) { if (chunklen == 0) {
if (errormsg) *errormsg = "Consecutive dots"; if (errormsg) *errormsg = "Consecutive dots";
return 1; return 1;
} }
if (chunklen > 63) { if (chunklen > 63) {
if (errormsg) *errormsg = "Too long domain part (> 63)"; if (errormsg) *errormsg = "Too long domain part (> 63)";
return 1; return 1;
} }
chunklen = 0; chunklen = 0;
} else { } else {
chunklen++; chunklen++;
} }
if( (str[i] >= 'a' && str[i] <= 'z') || (str[i] >= 'A' && str[i] <= 'Z') || if( (str[i] >= 'a' && str[i] <= 'z') || (str[i] >= 'A' && str[i] <= 'Z') ||
isdigit(str[i]) || str[i] == '-' || str[i] == '.' ) { isdigit(str[i]) || str[i] == '-' || str[i] == '.' ) {
continue; continue;
} else { } else {
if (errormsg) *errormsg = "Contains illegal character (allowed: [a-zA-Z0-9-.])"; if (errormsg) *errormsg = "Contains illegal character (allowed: [a-zA-Z0-9-.])";
return 1; return 1;
} }
} }
if (dots == 0) { if (dots == 0) {
if (errormsg) *errormsg = "No dots"; if (errormsg) *errormsg = "No dots";
return 1; return 1;
} }
if (chunklen == 0) { if (chunklen == 0) {
if (errormsg) *errormsg = "Ends with a dot"; if (errormsg) *errormsg = "Ends with a dot";
return 1; return 1;
} }
if (chunklen > 63) { if (chunklen > 63) {
if (errormsg) *errormsg = "Too long domain part (> 63)"; if (errormsg) *errormsg = "Too long domain part (> 63)";
return 1; return 1;
} }
return 0; return 0;
} }
#if defined(WINDOWS32) || defined(ANDROID) #if defined(WINDOWS32) || defined(ANDROID)
@ -400,51 +400,51 @@ inet_aton(const char *cp, struct in_addr *inp)
void void
warn(const char *fmt, ...) warn(const char *fmt, ...)
{ {
va_list list; va_list list;
va_start(list, fmt); va_start(list, fmt);
if (fmt) fprintf(stderr, fmt, list); if (fmt) fprintf(stderr, fmt, list);
#ifndef ANDROID #ifndef ANDROID
if (errno == 0) { if (errno == 0) {
fprintf(stderr, ": WSA error %d\n", WSAGetLastError()); fprintf(stderr, ": WSA error %d\n", WSAGetLastError());
} else { } else {
fprintf(stderr, ": %s\n", strerror(errno)); fprintf(stderr, ": %s\n", strerror(errno));
} }
#endif #endif
va_end(list); va_end(list);
} }
void void
warnx(const char *fmt, ...) warnx(const char *fmt, ...)
{ {
va_list list; va_list list;
va_start(list, fmt); va_start(list, fmt);
if (fmt) fprintf(stderr, fmt, list); if (fmt) fprintf(stderr, fmt, list);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
va_end(list); va_end(list);
} }
void void
err(int eval, const char *fmt, ...) err(int eval, const char *fmt, ...)
{ {
va_list list; va_list list;
va_start(list, fmt); va_start(list, fmt);
warn(fmt, list); warn(fmt, list);
va_end(list); va_end(list);
exit(eval); exit(eval);
} }
void void
errx(int eval, const char *fmt, ...) errx(int eval, const char *fmt, ...)
{ {
va_list list; va_list list;
va_start(list, fmt); va_start(list, fmt);
warnx(fmt, list); warnx(fmt, list);
va_end(list); va_end(list);
exit(eval); exit(eval);
} }
#endif #endif
@ -454,14 +454,14 @@ int recent_seqno(int ourseqno, int gotseqno)
Return 0 if gotseqno is new (or very old). Return 0 if gotseqno is new (or very old).
*/ */
{ {
int i; int i;
for (i = 0; i < 4; i++, ourseqno--) { for (i = 0; i < 4; i++, ourseqno--) {
if (ourseqno < 0) if (ourseqno < 0)
ourseqno = 7; ourseqno = 7;
if (gotseqno == ourseqno) if (gotseqno == ourseqno)
return 1; return 1;
} }
return 0; return 0;
} }
#ifndef WINDOWS32 #ifndef WINDOWS32
@ -471,14 +471,14 @@ int recent_seqno(int ourseqno, int gotseqno)
void void
fd_set_close_on_exec(int fd) fd_set_close_on_exec(int fd)
{ {
int flags; int flags;
flags = fcntl(fd, F_GETFD); flags = fcntl(fd, F_GETFD);
if (flags == -1) if (flags == -1)
err(4, "Failed to get fd flags"); err(4, "Failed to get fd flags");
flags |= FD_CLOEXEC; flags |= FD_CLOEXEC;
if (fcntl(fd, F_SETFD, flags) == -1) if (fcntl(fd, F_SETFD, flags) == -1)
err(4, "Failed to set fd flags"); err(4, "Failed to set fd flags");
} }
#endif #endif

View file

@ -82,31 +82,31 @@ extern const unsigned char raw_header[RAW_HDR_LEN];
struct packet struct packet
{ {
int len; /* Total packet length */ int len; /* Total packet length */
int sentlen; /* Length of chunk currently transmitted */ int sentlen; /* Length of chunk currently transmitted */
int offset; /* Current offset */ int offset; /* Current offset */
char data[64*1024]; /* The data */ char data[64*1024]; /* The data */
char seqno; /* The packet sequence number */ char seqno; /* The packet sequence number */
char fragment; /* Fragment index */ char fragment; /* Fragment index */
}; };
struct query { struct query {
char name[QUERY_NAME_SIZE]; char name[QUERY_NAME_SIZE];
unsigned short type; unsigned short type;
unsigned short rcode; unsigned short rcode;
unsigned short id; unsigned short id;
struct in_addr destination; struct in_addr destination;
struct sockaddr_storage from; struct sockaddr_storage from;
int fromlen; int fromlen;
unsigned short id2; unsigned short id2;
struct sockaddr from2; struct sockaddr from2;
int fromlen2; int fromlen2;
}; };
enum connection { enum connection {
CONN_RAW_UDP, CONN_RAW_UDP,
CONN_DNS_NULL, CONN_DNS_NULL,
CONN_MAX CONN_MAX
}; };
void check_superuser(void (*usage_fn)(void)); void check_superuser(void (*usage_fn)(void));

View file

@ -21,8 +21,8 @@
#include "common.h" #include "common.h"
typedef enum { typedef enum {
QR_QUERY = 0, QR_QUERY = 0,
QR_ANSWER = 1 QR_ANSWER = 1
} qr_t; } qr_t;
extern int dnsc_use_edns0; extern int dnsc_use_edns0;

View file

@ -21,110 +21,110 @@
int int
build_hostname(char *buf, size_t buflen, build_hostname(char *buf, size_t buflen,
const char *data, const size_t datalen, const char *data, const size_t datalen,
const char *topdomain, struct encoder *encoder, int maxlen) const char *topdomain, struct encoder *encoder, int maxlen)
{ {
size_t space; size_t space;
char *b; char *b;
space = MIN((size_t)maxlen, buflen) - strlen(topdomain) - 8; space = MIN((size_t)maxlen, buflen) - strlen(topdomain) - 8;
/* 8 = 5 max header length + 1 dot before topdomain + 2 safety */ /* 8 = 5 max header length + 1 dot before topdomain + 2 safety */
if (!encoder->places_dots()) if (!encoder->places_dots())
space -= (space / 57); /* space for dots */ space -= (space / 57); /* space for dots */
memset(buf, 0, buflen); memset(buf, 0, buflen);
encoder->encode(buf, &space, data, datalen); encoder->encode(buf, &space, data, datalen);
if (!encoder->places_dots()) if (!encoder->places_dots())
inline_dotify(buf, buflen); inline_dotify(buf, buflen);
b = buf; b = buf;
b += strlen(buf); b += strlen(buf);
/* move b back one step to see if the dot is there */ /* move b back one step to see if the dot is there */
b--; b--;
if (*b != '.') if (*b != '.')
*++b = '.'; *++b = '.';
b++; b++;
/* move b ahead of the string so we can copy to it */ /* move b ahead of the string so we can copy to it */
strncpy(b, topdomain, strlen(topdomain)+1); strncpy(b, topdomain, strlen(topdomain)+1);
return space; return space;
} }
int int
unpack_data(char *buf, size_t buflen, char *data, size_t datalen, struct encoder *enc) unpack_data(char *buf, size_t buflen, char *data, size_t datalen, struct encoder *enc)
{ {
if (!enc->eats_dots()) if (!enc->eats_dots())
datalen = inline_undotify(data, datalen); datalen = inline_undotify(data, datalen);
return enc->decode(buf, &buflen, data, datalen); return enc->decode(buf, &buflen, data, datalen);
} }
int int
inline_dotify(char *buf, size_t buflen) inline_dotify(char *buf, size_t buflen)
{ {
unsigned dots; unsigned dots;
unsigned pos; unsigned pos;
unsigned total; unsigned total;
char *reader, *writer; char *reader, *writer;
total = strlen(buf); total = strlen(buf);
dots = total / 57; dots = total / 57;
writer = buf; writer = buf;
writer += total; writer += total;
writer += dots; writer += dots;
total += dots; total += dots;
if (strlen(buf) + dots > buflen) { if (strlen(buf) + dots > buflen) {
writer = buf; writer = buf;
writer += buflen; writer += buflen;
total = buflen; total = buflen;
} }
reader = writer - dots; reader = writer - dots;
pos = (unsigned) (reader - buf) + 1; pos = (unsigned) (reader - buf) + 1;
while (dots) { while (dots) {
*writer-- = *reader--; *writer-- = *reader--;
pos--; pos--;
if (pos % 57 == 0) { if (pos % 57 == 0) {
*writer-- = '.'; *writer-- = '.';
dots--; dots--;
} }
} }
/* return new length of string */ /* return new length of string */
return total; return total;
} }
int int
inline_undotify(char *buf, size_t len) inline_undotify(char *buf, size_t len)
{ {
unsigned pos; unsigned pos;
unsigned dots; unsigned dots;
char *reader, *writer; char *reader, *writer;
writer = buf; writer = buf;
reader = writer; reader = writer;
pos = 0; pos = 0;
dots = 0; dots = 0;
while (pos < len) { while (pos < len) {
if (*reader == '.') { if (*reader == '.') {
reader++; reader++;
pos++; pos++;
dots++; dots++;
continue; continue;
} }
*writer++ = *reader++; *writer++ = *reader++;
pos++; pos++;
} }
/* return new length of string */ /* return new length of string */
return len - dots; return len - dots;
} }

View file

@ -26,13 +26,13 @@
#define DOWNCODECCHECK1_LEN 48 #define DOWNCODECCHECK1_LEN 48
struct encoder { struct encoder {
char name[8]; char name[8];
int (*encode) (char *, size_t *, const void *, size_t); int (*encode) (char *, size_t *, const void *, size_t);
int (*decode) (void *, size_t *, const char *, size_t); int (*decode) (void *, size_t *, const char *, size_t);
int (*places_dots) (void); int (*places_dots) (void);
int (*eats_dots) (void); int (*eats_dots) (void);
int (*blocksize_raw)(void); int (*blocksize_raw)(void);
int (*blocksize_encoded)(void); int (*blocksize_encoded)(void);
}; };
int build_hostname(char *, size_t, const char *, const size_t, const char *, struct encoder *, int); int build_hostname(char *, size_t, const char *, const size_t, const char *, struct encoder *, int);

View file

@ -22,28 +22,28 @@ static int fwq_ix;
void fw_query_init() void fw_query_init()
{ {
memset(fwq, 0, sizeof(struct fw_query) * FW_QUERY_CACHE_SIZE); memset(fwq, 0, sizeof(struct fw_query) * FW_QUERY_CACHE_SIZE);
fwq_ix = 0; fwq_ix = 0;
} }
void fw_query_put(struct fw_query *fw_query) void fw_query_put(struct fw_query *fw_query)
{ {
memcpy(&(fwq[fwq_ix]), fw_query, sizeof(struct fw_query)); memcpy(&(fwq[fwq_ix]), fw_query, sizeof(struct fw_query));
++fwq_ix; ++fwq_ix;
if (fwq_ix >= FW_QUERY_CACHE_SIZE) if (fwq_ix >= FW_QUERY_CACHE_SIZE)
fwq_ix = 0; fwq_ix = 0;
} }
void fw_query_get(unsigned short query_id, struct fw_query **fw_query) void fw_query_get(unsigned short query_id, struct fw_query **fw_query)
{ {
int i; int i;
*fw_query = NULL; *fw_query = NULL;
for (i = 0; i < FW_QUERY_CACHE_SIZE; i++) { for (i = 0; i < FW_QUERY_CACHE_SIZE; i++) {
if (fwq[i].id == query_id) { if (fwq[i].id == query_id) {
*fw_query = &(fwq[i]); *fw_query = &(fwq[i]);
return; return;
} }
} }
} }

View file

@ -28,9 +28,9 @@
#define FW_QUERY_CACHE_SIZE 16 #define FW_QUERY_CACHE_SIZE 16
struct fw_query { struct fw_query {
struct sockaddr_storage addr; struct sockaddr_storage addr;
int addrlen; int addrlen;
unsigned short id; unsigned short id;
}; };
void fw_query_init(); void fw_query_init();

View file

@ -55,7 +55,7 @@ static char *__progname;
static void static void
sighandler(int sig) sighandler(int sig)
{ {
client_stop(); client_stop();
} }
#if defined(__GNUC__) || defined(__clang__) #if defined(__GNUC__) || defined(__clang__)
@ -66,344 +66,344 @@ static void usage() __attribute__((noreturn));
static void static void
usage() { usage() {
extern char *__progname; extern char *__progname;
fprintf(stderr, "Usage: %s [-v] [-h] [-f] [-r] [-u user] [-t chrootdir] [-d device] " fprintf(stderr, "Usage: %s [-v] [-h] [-f] [-r] [-u user] [-t chrootdir] [-d device] "
"[-P password] [-m maxfragsize] [-M maxlen] [-T type] [-O enc] [-L 0|1] [-I sec] " "[-P password] [-m maxfragsize] [-M maxlen] [-T type] [-O enc] [-L 0|1] [-I sec] "
"[-z context] [-F pidfile] [nameserver] topdomain\n", __progname); "[-z context] [-F pidfile] [nameserver] topdomain\n", __progname);
exit(2); exit(2);
} }
static void static void
help() { help() {
extern char *__progname; extern char *__progname;
fprintf(stderr, "iodine IP over DNS tunneling client\n"); fprintf(stderr, "iodine IP over DNS tunneling client\n");
fprintf(stderr, "Usage: %s [-v] [-h] [-f] [-r] [-u user] [-t chrootdir] [-d device] " fprintf(stderr, "Usage: %s [-v] [-h] [-f] [-r] [-u user] [-t chrootdir] [-d device] "
"[-P password] [-m maxfragsize] [-M maxlen] [-T type] [-O enc] [-L 0|1] [-I sec] " "[-P password] [-m maxfragsize] [-M maxlen] [-T type] [-O enc] [-L 0|1] [-I sec] "
"[-z context] [-F pidfile] [nameserver] topdomain\n", __progname); "[-z context] [-F pidfile] [nameserver] topdomain\n", __progname);
fprintf(stderr, "Options to try if connection doesn't work:\n"); fprintf(stderr, "Options to try if connection doesn't work:\n");
fprintf(stderr, " -T force dns type: NULL, PRIVATE, TXT, SRV, MX, CNAME, A (default: autodetect)\n"); fprintf(stderr, " -T force dns type: NULL, PRIVATE, TXT, SRV, MX, CNAME, A (default: autodetect)\n");
fprintf(stderr, " -O force downstream encoding for -T other than NULL: Base32, Base64, Base64u,\n"); fprintf(stderr, " -O force downstream encoding for -T other than NULL: Base32, Base64, Base64u,\n");
fprintf(stderr, " Base128, or (only for TXT:) Raw (default: autodetect)\n"); fprintf(stderr, " Base128, or (only for TXT:) Raw (default: autodetect)\n");
fprintf(stderr, " -I max interval between requests (default 4 sec) to prevent DNS timeouts\n"); fprintf(stderr, " -I max interval between requests (default 4 sec) to prevent DNS timeouts\n");
fprintf(stderr, " -L 1: use lazy mode for low-latency (default). 0: don't (implies -I1)\n"); fprintf(stderr, " -L 1: use lazy mode for low-latency (default). 0: don't (implies -I1)\n");
fprintf(stderr, " -m max size of downstream fragments (default: autodetect)\n"); fprintf(stderr, " -m max size of downstream fragments (default: autodetect)\n");
fprintf(stderr, " -M max size of upstream hostnames (~100-255, default: 255)\n"); fprintf(stderr, " -M max size of upstream hostnames (~100-255, default: 255)\n");
fprintf(stderr, " -r to skip raw UDP mode attempt\n"); fprintf(stderr, " -r to skip raw UDP mode attempt\n");
fprintf(stderr, " -P password used for authentication (max 32 chars will be used)\n"); fprintf(stderr, " -P password used for authentication (max 32 chars will be used)\n");
fprintf(stderr, "Other options:\n"); fprintf(stderr, "Other options:\n");
fprintf(stderr, " -v to print version info and exit\n"); fprintf(stderr, " -v to print version info and exit\n");
fprintf(stderr, " -h to print this help and exit\n"); fprintf(stderr, " -h to print this help and exit\n");
fprintf(stderr, " -f to keep running in foreground\n"); fprintf(stderr, " -f to keep running in foreground\n");
fprintf(stderr, " -u name to drop privileges and run as user 'name'\n"); fprintf(stderr, " -u name to drop privileges and run as user 'name'\n");
fprintf(stderr, " -t dir to chroot to directory dir\n"); fprintf(stderr, " -t dir to chroot to directory dir\n");
fprintf(stderr, " -d device to set tunnel device name\n"); fprintf(stderr, " -d device to set tunnel device name\n");
fprintf(stderr, " -z context, to apply specified SELinux context after initialization\n"); fprintf(stderr, " -z context, to apply specified SELinux context after initialization\n");
fprintf(stderr, " -F pidfile to write pid to a file\n"); fprintf(stderr, " -F pidfile to write pid to a file\n");
fprintf(stderr, "nameserver is the IP number/hostname of the relaying nameserver. if absent, /etc/resolv.conf is used\n"); fprintf(stderr, "nameserver is the IP number/hostname of the relaying nameserver. if absent, /etc/resolv.conf is used\n");
fprintf(stderr, "topdomain is the FQDN that is delegated to the tunnel endpoint.\n"); fprintf(stderr, "topdomain is the FQDN that is delegated to the tunnel endpoint.\n");
exit(0); exit(0);
} }
static void static void
version() { version() {
fprintf(stderr, "iodine IP over DNS tunneling client\n"); fprintf(stderr, "iodine IP over DNS tunneling client\n");
fprintf(stderr, "Git version: %s\n", GITREVISION); fprintf(stderr, "Git version: %s\n", GITREVISION);
exit(0); exit(0);
} }
int int
main(int argc, char **argv) main(int argc, char **argv)
{ {
char *nameserv_host; char *nameserv_host;
char *topdomain; char *topdomain;
char *errormsg; char *errormsg;
#ifndef WINDOWS32 #ifndef WINDOWS32
struct passwd *pw; struct passwd *pw;
#endif #endif
char *username; char *username;
char password[33]; char password[33];
int foreground; int foreground;
char *newroot; char *newroot;
char *context; char *context;
char *device; char *device;
char *pidfile; char *pidfile;
int choice; int choice;
int tun_fd; int tun_fd;
int dns_fd; int dns_fd;
int max_downstream_frag_size; int max_downstream_frag_size;
int autodetect_frag_size; int autodetect_frag_size;
int retval; int retval;
int raw_mode; int raw_mode;
int lazymode; int lazymode;
int selecttimeout; int selecttimeout;
int hostname_maxlen; int hostname_maxlen;
#ifdef OPENBSD #ifdef OPENBSD
int rtable = 0; int rtable = 0;
#endif #endif
struct sockaddr_storage nameservaddr; struct sockaddr_storage nameservaddr;
int nameservaddr_len; int nameservaddr_len;
int nameserv_family; int nameserv_family;
nameserv_host = NULL; nameserv_host = NULL;
topdomain = NULL; topdomain = NULL;
errormsg = NULL; errormsg = NULL;
#ifndef WINDOWS32 #ifndef WINDOWS32
pw = NULL; pw = NULL;
#endif #endif
username = NULL; username = NULL;
memset(password, 0, 33); memset(password, 0, 33);
srand(time(NULL)); srand(time(NULL));
foreground = 0; foreground = 0;
newroot = NULL; newroot = NULL;
context = NULL; context = NULL;
device = NULL; device = NULL;
pidfile = NULL; pidfile = NULL;
autodetect_frag_size = 1; autodetect_frag_size = 1;
max_downstream_frag_size = 3072; max_downstream_frag_size = 3072;
retval = 0; retval = 0;
raw_mode = 1; raw_mode = 1;
lazymode = 1; lazymode = 1;
selecttimeout = 4; selecttimeout = 4;
hostname_maxlen = 0xFF; hostname_maxlen = 0xFF;
nameserv_family = AF_UNSPEC; nameserv_family = AF_UNSPEC;
#ifdef WINDOWS32 #ifdef WINDOWS32
WSAStartup(req_version, &wsa_data); WSAStartup(req_version, &wsa_data);
#endif #endif
srand((unsigned) time(NULL)); srand((unsigned) time(NULL));
client_init(); client_init();
#if !defined(BSD) && !defined(__GLIBC__) #if !defined(BSD) && !defined(__GLIBC__)
__progname = strrchr(argv[0], '/'); __progname = strrchr(argv[0], '/');
if (__progname == NULL) if (__progname == NULL)
__progname = argv[0]; __progname = argv[0];
else else
__progname++; __progname++;
#endif #endif
while ((choice = getopt(argc, argv, "46vfhru:t:d:R:P:m:M:F:T:O:L:I:")) != -1) { while ((choice = getopt(argc, argv, "46vfhru:t:d:R:P:m:M:F:T:O:L:I:")) != -1) {
switch(choice) { switch(choice) {
case '4': case '4':
nameserv_family = AF_INET; nameserv_family = AF_INET;
break; break;
case '6': case '6':
nameserv_family = AF_INET6; nameserv_family = AF_INET6;
break; break;
case 'v': case 'v':
version(); version();
/* NOTREACHED */ /* NOTREACHED */
break; break;
case 'f': case 'f':
foreground = 1; foreground = 1;
break; break;
case 'h': case 'h':
help(); help();
/* NOTREACHED */ /* NOTREACHED */
break; break;
case 'r': case 'r':
raw_mode = 0; raw_mode = 0;
break; break;
case 'u': case 'u':
username = optarg; username = optarg;
break; break;
case 't': case 't':
newroot = optarg; newroot = optarg;
break; break;
case 'd': case 'd':
device = optarg; device = optarg;
break; break;
#ifdef OPENBSD #ifdef OPENBSD
case 'R': case 'R':
rtable = atoi(optarg); rtable = atoi(optarg);
break; break;
#endif #endif
case 'P': case 'P':
strncpy(password, optarg, sizeof(password)); strncpy(password, optarg, sizeof(password));
password[sizeof(password)-1] = 0; password[sizeof(password)-1] = 0;
/* XXX: find better way of cleaning up ps(1) */ /* XXX: find better way of cleaning up ps(1) */
memset(optarg, 0, strlen(optarg)); memset(optarg, 0, strlen(optarg));
break; break;
case 'm': case 'm':
autodetect_frag_size = 0; autodetect_frag_size = 0;
max_downstream_frag_size = atoi(optarg); max_downstream_frag_size = atoi(optarg);
break; break;
case 'M': case 'M':
hostname_maxlen = atoi(optarg); hostname_maxlen = atoi(optarg);
if (hostname_maxlen > 255) if (hostname_maxlen > 255)
hostname_maxlen = 255; hostname_maxlen = 255;
if (hostname_maxlen < 10) if (hostname_maxlen < 10)
hostname_maxlen = 10; hostname_maxlen = 10;
break; break;
case 'z': case 'z':
context = optarg; context = optarg;
break; break;
case 'F': case 'F':
pidfile = optarg; pidfile = optarg;
break; break;
case 'T': case 'T':
if (client_set_qtype(optarg)) if (client_set_qtype(optarg))
errx(5, "Invalid query type '%s'", optarg); errx(5, "Invalid query type '%s'", optarg);
break; break;
case 'O': /* not -D, is Debug in server */ case 'O': /* not -D, is Debug in server */
client_set_downenc(optarg); client_set_downenc(optarg);
break; break;
case 'L': case 'L':
lazymode = atoi(optarg); lazymode = atoi(optarg);
if (lazymode > 1) if (lazymode > 1)
lazymode = 1; lazymode = 1;
if (lazymode < 0) if (lazymode < 0)
lazymode = 0; lazymode = 0;
if (!lazymode) if (!lazymode)
selecttimeout = 1; selecttimeout = 1;
break; break;
case 'I': case 'I':
selecttimeout = atoi(optarg); selecttimeout = atoi(optarg);
if (selecttimeout < 1) if (selecttimeout < 1)
selecttimeout = 1; selecttimeout = 1;
break; break;
default: default:
usage(); usage();
/* NOTREACHED */ /* NOTREACHED */
} }
} }
check_superuser(usage); check_superuser(usage);
argc -= optind; argc -= optind;
argv += optind; argv += optind;
switch (argc) { switch (argc) {
case 1: case 1:
nameserv_host = get_resolvconf_addr(); nameserv_host = get_resolvconf_addr();
topdomain = strdup(argv[0]); topdomain = strdup(argv[0]);
break; break;
case 2: case 2:
nameserv_host = argv[0]; nameserv_host = argv[0];
topdomain = strdup(argv[1]); topdomain = strdup(argv[1]);
break; break;
default: default:
usage(); usage();
/* NOTREACHED */ /* NOTREACHED */
} }
if (max_downstream_frag_size < 1 || max_downstream_frag_size > 0xffff) { if (max_downstream_frag_size < 1 || max_downstream_frag_size > 0xffff) {
warnx("Use a max frag size between 1 and 65535 bytes.\n"); warnx("Use a max frag size between 1 and 65535 bytes.\n");
usage(); usage();
/* NOTREACHED */ /* NOTREACHED */
} }
if (nameserv_host) { if (nameserv_host) {
nameservaddr_len = get_addr(nameserv_host, DNS_PORT, nameserv_family, 0, &nameservaddr); nameservaddr_len = get_addr(nameserv_host, DNS_PORT, nameserv_family, 0, &nameservaddr);
if (nameservaddr_len < 0) { if (nameservaddr_len < 0) {
errx(1, "Cannot lookup nameserver '%s': %s ", errx(1, "Cannot lookup nameserver '%s': %s ",
nameserv_host, gai_strerror(nameservaddr_len)); nameserv_host, gai_strerror(nameservaddr_len));
} }
client_set_nameserver(&nameservaddr, nameservaddr_len); client_set_nameserver(&nameservaddr, nameservaddr_len);
} else { } else {
warnx("No nameserver found - not connected to any network?\n"); warnx("No nameserver found - not connected to any network?\n");
usage(); usage();
/* NOTREACHED */ /* NOTREACHED */
} }
if(check_topdomain(topdomain, &errormsg)) { if(check_topdomain(topdomain, &errormsg)) {
warnx("Invalid topdomain: %s", errormsg); warnx("Invalid topdomain: %s", errormsg);
usage(); usage();
/* NOTREACHED */ /* NOTREACHED */
} }
client_set_selecttimeout(selecttimeout); client_set_selecttimeout(selecttimeout);
client_set_lazymode(lazymode); client_set_lazymode(lazymode);
client_set_topdomain(topdomain); client_set_topdomain(topdomain);
client_set_hostname_maxlen(hostname_maxlen); client_set_hostname_maxlen(hostname_maxlen);
if (username != NULL) { if (username != NULL) {
#ifndef WINDOWS32 #ifndef WINDOWS32
if ((pw = getpwnam(username)) == NULL) { if ((pw = getpwnam(username)) == NULL) {
warnx("User %s does not exist!\n", username); warnx("User %s does not exist!\n", username);
usage(); usage();
/* NOTREACHED */ /* NOTREACHED */
} }
#endif #endif
} }
if (strlen(password) == 0) { if (strlen(password) == 0) {
if (NULL != getenv(PASSWORD_ENV_VAR)) if (NULL != getenv(PASSWORD_ENV_VAR))
snprintf(password, sizeof(password), "%s", getenv(PASSWORD_ENV_VAR)); snprintf(password, sizeof(password), "%s", getenv(PASSWORD_ENV_VAR));
else else
read_password(password, sizeof(password)); read_password(password, sizeof(password));
} }
client_set_password(password); client_set_password(password);
if ((tun_fd = open_tun(device)) == -1) { if ((tun_fd = open_tun(device)) == -1) {
retval = 1; retval = 1;
goto cleanup1; goto cleanup1;
} }
if ((dns_fd = open_dns_from_host(NULL, 0, nameservaddr.ss_family, AI_PASSIVE)) < 0) { if ((dns_fd = open_dns_from_host(NULL, 0, nameservaddr.ss_family, AI_PASSIVE)) < 0) {
retval = 1; retval = 1;
goto cleanup2; goto cleanup2;
} }
#ifdef OPENBSD #ifdef OPENBSD
if (rtable > 0) if (rtable > 0)
socket_setrtable(dns_fd, rtable); socket_setrtable(dns_fd, rtable);
#endif #endif
signal(SIGINT, sighandler); signal(SIGINT, sighandler);
signal(SIGTERM, sighandler); signal(SIGTERM, sighandler);
fprintf(stderr, "Sending DNS queries for %s to %s\n", fprintf(stderr, "Sending DNS queries for %s to %s\n",
topdomain, format_addr(&nameservaddr, nameservaddr_len)); topdomain, format_addr(&nameservaddr, nameservaddr_len));
if (client_handshake(dns_fd, raw_mode, autodetect_frag_size, max_downstream_frag_size)) { if (client_handshake(dns_fd, raw_mode, autodetect_frag_size, max_downstream_frag_size)) {
retval = 1; retval = 1;
goto cleanup2; goto cleanup2;
} }
if (client_get_conn() == CONN_RAW_UDP) { if (client_get_conn() == CONN_RAW_UDP) {
fprintf(stderr, "Sending raw traffic directly to %s\n", client_get_raw_addr()); fprintf(stderr, "Sending raw traffic directly to %s\n", client_get_raw_addr());
} }
fprintf(stderr, "Connection setup complete, transmitting data.\n"); fprintf(stderr, "Connection setup complete, transmitting data.\n");
if (foreground == 0) if (foreground == 0)
do_detach(); do_detach();
if (pidfile != NULL) if (pidfile != NULL)
do_pidfile(pidfile); do_pidfile(pidfile);
if (newroot != NULL) if (newroot != NULL)
do_chroot(newroot); do_chroot(newroot);
if (username != NULL) { if (username != NULL) {
#ifndef WINDOWS32 #ifndef WINDOWS32
gid_t gids[1]; gid_t gids[1];
gids[0] = pw->pw_gid; gids[0] = pw->pw_gid;
if (setgroups(1, gids) < 0 || setgid(pw->pw_gid) < 0 || setuid(pw->pw_uid) < 0) { if (setgroups(1, gids) < 0 || setgid(pw->pw_gid) < 0 || setuid(pw->pw_uid) < 0) {
warnx("Could not switch to user %s!\n", username); warnx("Could not switch to user %s!\n", username);
usage(); usage();
/* NOTREACHED */ /* NOTREACHED */
} }
#endif #endif
} }
if (context != NULL) if (context != NULL)
do_setcon(context); do_setcon(context);
client_tunnel(tun_fd, dns_fd); client_tunnel(tun_fd, dns_fd);
cleanup2: cleanup2:
close_dns(dns_fd); close_dns(dns_fd);
close_tun(tun_fd); close_tun(tun_fd);
cleanup1: cleanup1:
return retval; return retval;
} }

File diff suppressed because it is too large Load diff

View file

@ -33,27 +33,27 @@
void void
login_calculate(char *buf, int buflen, const char *pass, int seed) login_calculate(char *buf, int buflen, const char *pass, int seed)
{ {
unsigned char temp[32]; unsigned char temp[32];
md5_state_t ctx; md5_state_t ctx;
int *ix; int *ix;
int i; int i;
int k; int k;
if (buflen < 16) if (buflen < 16)
return; return;
memcpy(temp, pass, 32); memcpy(temp, pass, 32);
ix = (int*) temp; ix = (int*) temp;
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
k = ntohl(*ix); k = ntohl(*ix);
k ^= seed; k ^= seed;
*ix++ = htonl(k); *ix++ = htonl(k);
} }
md5_init(&ctx); md5_init(&ctx);
md5_append(&ctx, temp, 32); md5_append(&ctx, temp, 32);
md5_finish(&ctx, (unsigned char *) buf); md5_finish(&ctx, (unsigned char *) buf);
} }

View file

@ -22,249 +22,249 @@
static int static int
readname_loop(char *packet, int packetlen, char **src, char *dst, size_t length, size_t loop) readname_loop(char *packet, int packetlen, char **src, char *dst, size_t length, size_t loop)
{ {
char *dummy; char *dummy;
char *s; char *s;
char *d; char *d;
int len; int len;
int offset; int offset;
char c; char c;
if (loop <= 0) if (loop <= 0)
return 0; return 0;
len = 0; len = 0;
s = *src; s = *src;
d = dst; d = dst;
while(*s && len < length - 2) { while(*s && len < length - 2) {
c = *s++; c = *s++;
/* is this a compressed label? */ /* is this a compressed label? */
if((c & 0xc0) == 0xc0) { if((c & 0xc0) == 0xc0) {
offset = (((s[-1] & 0x3f) << 8) | (s[0] & 0xff)); offset = (((s[-1] & 0x3f) << 8) | (s[0] & 0xff));
if (offset > packetlen) { if (offset > packetlen) {
if (len == 0) { if (len == 0) {
/* Bad jump first in packet */ /* Bad jump first in packet */
return 0; return 0;
} else { } else {
/* Bad jump after some data */ /* Bad jump after some data */
break; break;
} }
} }
dummy = packet + offset; dummy = packet + offset;
len += readname_loop(packet, packetlen, &dummy, d, length - len, loop - 1); len += readname_loop(packet, packetlen, &dummy, d, length - len, loop - 1);
goto end; goto end;
} }
while(c && len < length - 1) { while(c && len < length - 1) {
*d++ = *s++; *d++ = *s++;
len++; len++;
c--; c--;
} }
if (len >= length - 1) { if (len >= length - 1) {
break; /* We used up all space */ break; /* We used up all space */
} }
if (*s != 0) { if (*s != 0) {
*d++ = '.'; *d++ = '.';
len++; len++;
} }
} }
dst[len++] = '\0'; dst[len++] = '\0';
end: end:
(*src) = s+1; (*src) = s+1;
return len; return len;
} }
int int
readname(char *packet, int packetlen, char **src, char *dst, size_t length) readname(char *packet, int packetlen, char **src, char *dst, size_t length)
{ {
return readname_loop(packet, packetlen, src, dst, length, 10); return readname_loop(packet, packetlen, src, dst, length, 10);
} }
int int
readshort(char *packet, char **src, unsigned short *dst) readshort(char *packet, char **src, unsigned short *dst)
{ {
unsigned char *p; unsigned char *p;
p = (unsigned char *) *src; p = (unsigned char *) *src;
*dst = (p[0] << 8) | p[1]; *dst = (p[0] << 8) | p[1];
(*src) += sizeof(unsigned short); (*src) += sizeof(unsigned short);
return sizeof(unsigned short); return sizeof(unsigned short);
} }
int int
readlong(char *packet, char **src, uint32_t *dst) readlong(char *packet, char **src, uint32_t *dst)
{ {
/* A long as described in dns protocol is always 32 bits */ /* A long as described in dns protocol is always 32 bits */
unsigned char *p; unsigned char *p;
p = (unsigned char *) *src; p = (unsigned char *) *src;
*dst = ((uint32_t)p[0] << 24) *dst = ((uint32_t)p[0] << 24)
| ((uint32_t)p[1] << 16) | ((uint32_t)p[1] << 16)
| ((uint32_t)p[2] << 8) | ((uint32_t)p[2] << 8)
| ((uint32_t)p[3]); | ((uint32_t)p[3]);
(*src) += sizeof(uint32_t); (*src) += sizeof(uint32_t);
return sizeof(uint32_t); return sizeof(uint32_t);
} }
int int
readdata(char *packet, char **src, char *dst, size_t len) readdata(char *packet, char **src, char *dst, size_t len)
{ {
memcpy(dst, *src, len); memcpy(dst, *src, len);
(*src) += len; (*src) += len;
return len; return len;
} }
int int
readtxtbin(char *packet, char **src, size_t srcremain, char *dst, size_t dstremain) readtxtbin(char *packet, char **src, size_t srcremain, char *dst, size_t dstremain)
{ {
unsigned char *uc; unsigned char *uc;
int tocopy; int tocopy;
int dstused = 0; int dstused = 0;
while (srcremain > 0) while (srcremain > 0)
{ {
uc = (unsigned char*) (*src); uc = (unsigned char*) (*src);
tocopy = *uc; tocopy = *uc;
(*src)++; (*src)++;
srcremain--; srcremain--;
if (tocopy > srcremain) if (tocopy > srcremain)
return 0; /* illegal, better have nothing */ return 0; /* illegal, better have nothing */
if (tocopy > dstremain) if (tocopy > dstremain)
return 0; /* doesn't fit, better have nothing */ return 0; /* doesn't fit, better have nothing */
memcpy(dst, *src, tocopy); memcpy(dst, *src, tocopy);
dst += tocopy; dst += tocopy;
(*src) += tocopy; (*src) += tocopy;
srcremain -= tocopy; srcremain -= tocopy;
dstremain -= tocopy; dstremain -= tocopy;
dstused += tocopy; dstused += tocopy;
} }
return dstused; return dstused;
} }
int int
putname(char **buf, size_t buflen, const char *host) putname(char **buf, size_t buflen, const char *host)
{ {
char *word; char *word;
int left; int left;
char *h; char *h;
char *p; char *p;
h = strdup(host); h = strdup(host);
left = buflen; left = buflen;
p = *buf; p = *buf;
word = strtok(h, "."); word = strtok(h, ".");
while(word) { while(word) {
if (strlen(word) > 63 || strlen(word) > left) { if (strlen(word) > 63 || strlen(word) > left) {
free(h); free(h);
return -1; return -1;
} }
left -= (strlen(word) + 1); left -= (strlen(word) + 1);
*p++ = (char)strlen(word); *p++ = (char)strlen(word);
memcpy(p, word, strlen(word)); memcpy(p, word, strlen(word));
p += strlen(word); p += strlen(word);
word = strtok(NULL, "."); word = strtok(NULL, ".");
} }
*p++ = 0; *p++ = 0;
free(h); free(h);
*buf = p; *buf = p;
return buflen - left; return buflen - left;
} }
int int
putbyte(char **dst, unsigned char value) putbyte(char **dst, unsigned char value)
{ {
**dst = value; **dst = value;
(*dst)++; (*dst)++;
return sizeof(char); return sizeof(char);
} }
int int
putshort(char **dst, unsigned short value) putshort(char **dst, unsigned short value)
{ {
unsigned char *p; unsigned char *p;
p = (unsigned char *) *dst; p = (unsigned char *) *dst;
*p++ = (value >> 8); *p++ = (value >> 8);
*p++ = value; *p++ = value;
(*dst) = (char *) p; (*dst) = (char *) p;
return sizeof(short); return sizeof(short);
} }
int int
putlong(char **dst, uint32_t value) putlong(char **dst, uint32_t value)
{ {
/* A long as described in dns protocol is always 32 bits */ /* A long as described in dns protocol is always 32 bits */
unsigned char *p; unsigned char *p;
p = (unsigned char *) *dst; p = (unsigned char *) *dst;
*p++ = (value >> 24); *p++ = (value >> 24);
*p++ = (value >> 16); *p++ = (value >> 16);
*p++ = (value >> 8); *p++ = (value >> 8);
*p++ = (value); *p++ = (value);
(*dst) = (char *) p; (*dst) = (char *) p;
return sizeof(uint32_t); return sizeof(uint32_t);
} }
int int
putdata(char **dst, char *data, size_t len) putdata(char **dst, char *data, size_t len)
{ {
memcpy(*dst, data, len); memcpy(*dst, data, len);
(*dst) += len; (*dst) += len;
return len; return len;
} }
int int
puttxtbin(char **buf, size_t bufremain, char *from, size_t fromremain) puttxtbin(char **buf, size_t bufremain, char *from, size_t fromremain)
{ {
unsigned char uc; unsigned char uc;
unsigned char *ucp = &uc; unsigned char *ucp = &uc;
char *cp = (char *) ucp; char *cp = (char *) ucp;
int tocopy; int tocopy;
int bufused = 0; int bufused = 0;
while (fromremain > 0) while (fromremain > 0)
{ {
tocopy = fromremain; tocopy = fromremain;
if (tocopy > 252) if (tocopy > 252)
tocopy = 252; /* allow off-by-1s in caches etc */ tocopy = 252; /* allow off-by-1s in caches etc */
if (tocopy + 1 > bufremain) if (tocopy + 1 > bufremain)
return -1; /* doesn't fit, better have nothing */ return -1; /* doesn't fit, better have nothing */
uc = tocopy; uc = tocopy;
**buf = *cp; **buf = *cp;
(*buf)++; (*buf)++;
bufremain--; bufremain--;
bufused++; bufused++;
memcpy(*buf, from, tocopy); memcpy(*buf, from, tocopy);
(*buf) += tocopy; (*buf) += tocopy;
from += tocopy; from += tocopy;
bufremain -= tocopy; bufremain -= tocopy;
fromremain -= tocopy; fromremain -= tocopy;
bufused += tocopy; bufused += tocopy;
} }
return bufused; return bufused;
} }

698
src/tun.c
View file

@ -71,61 +71,61 @@ static char if_name[250];
int int
open_tun(const char *tun_device) open_tun(const char *tun_device)
{ {
int i; int i;
int tun_fd; int tun_fd;
struct ifreq ifreq; struct ifreq ifreq;
#ifdef ANDROID #ifdef ANDROID
char *tunnel = "/dev/tun"; char *tunnel = "/dev/tun";
#else #else
char *tunnel = "/dev/net/tun"; char *tunnel = "/dev/net/tun";
#endif #endif
if ((tun_fd = open(tunnel, O_RDWR)) < 0) { if ((tun_fd = open(tunnel, O_RDWR)) < 0) {
warn("open_tun: %s", tunnel); warn("open_tun: %s", tunnel);
return -1; return -1;
} }
memset(&ifreq, 0, sizeof(ifreq)); memset(&ifreq, 0, sizeof(ifreq));
ifreq.ifr_flags = IFF_TUN; ifreq.ifr_flags = IFF_TUN;
if (tun_device != NULL) { if (tun_device != NULL) {
strncpy(ifreq.ifr_name, tun_device, IFNAMSIZ); strncpy(ifreq.ifr_name, tun_device, IFNAMSIZ);
ifreq.ifr_name[IFNAMSIZ-1] = '\0'; ifreq.ifr_name[IFNAMSIZ-1] = '\0';
strncpy(if_name, tun_device, sizeof(if_name)); strncpy(if_name, tun_device, sizeof(if_name));
if_name[sizeof(if_name)-1] = '\0'; if_name[sizeof(if_name)-1] = '\0';
if (ioctl(tun_fd, TUNSETIFF, (void *) &ifreq) != -1) { if (ioctl(tun_fd, TUNSETIFF, (void *) &ifreq) != -1) {
fprintf(stderr, "Opened %s\n", ifreq.ifr_name); fprintf(stderr, "Opened %s\n", ifreq.ifr_name);
fd_set_close_on_exec(tun_fd); fd_set_close_on_exec(tun_fd);
return tun_fd; return tun_fd;
} }
if (errno != EBUSY) { if (errno != EBUSY) {
warn("open_tun: ioctl[TUNSETIFF]"); warn("open_tun: ioctl[TUNSETIFF]");
return -1; return -1;
} }
} else { } else {
for (i = 0; i < TUN_MAX_TRY; i++) { for (i = 0; i < TUN_MAX_TRY; i++) {
snprintf(ifreq.ifr_name, IFNAMSIZ, "dns%d", i); snprintf(ifreq.ifr_name, IFNAMSIZ, "dns%d", i);
if (ioctl(tun_fd, TUNSETIFF, (void *) &ifreq) != -1) { if (ioctl(tun_fd, TUNSETIFF, (void *) &ifreq) != -1) {
fprintf(stderr, "Opened %s\n", ifreq.ifr_name); fprintf(stderr, "Opened %s\n", ifreq.ifr_name);
snprintf(if_name, sizeof(if_name), "dns%d", i); snprintf(if_name, sizeof(if_name), "dns%d", i);
fd_set_close_on_exec(tun_fd); fd_set_close_on_exec(tun_fd);
return tun_fd; return tun_fd;
} }
if (errno != EBUSY) { if (errno != EBUSY) {
warn("open_tun: ioctl[TUNSETIFF]"); warn("open_tun: ioctl[TUNSETIFF]");
return -1; return -1;
} }
} }
warn("open_tun: Couldn't set interface name"); warn("open_tun: Couldn't set interface name");
} }
warn("error when opening tun"); warn("error when opening tun");
return -1; return -1;
} }
#elif WINDOWS32 #elif WINDOWS32
@ -133,184 +133,184 @@ open_tun(const char *tun_device)
static void static void
get_device(char *device, int device_len, const char *wanted_dev) get_device(char *device, int device_len, const char *wanted_dev)
{ {
LONG status; LONG status;
HKEY adapter_key; HKEY adapter_key;
int index; int index;
index = 0; index = 0;
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TAP_ADAPTER_KEY, 0, KEY_READ, &adapter_key); status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TAP_ADAPTER_KEY, 0, KEY_READ, &adapter_key);
if (status != ERROR_SUCCESS) { if (status != ERROR_SUCCESS) {
warnx("Error opening registry key " TAP_ADAPTER_KEY ); warnx("Error opening registry key " TAP_ADAPTER_KEY );
return; return;
} }
while (TRUE) { while (TRUE) {
char name[256]; char name[256];
char unit[256]; char unit[256];
char component[256]; char component[256];
char cid_string[256] = KEY_COMPONENT_ID; char cid_string[256] = KEY_COMPONENT_ID;
HKEY device_key; HKEY device_key;
DWORD datatype; DWORD datatype;
DWORD len; DWORD len;
/* Iterate through all adapter of this kind */ /* Iterate through all adapter of this kind */
len = sizeof(name); len = sizeof(name);
status = RegEnumKeyEx(adapter_key, index, name, &len, NULL, NULL, NULL, NULL); status = RegEnumKeyEx(adapter_key, index, name, &len, NULL, NULL, NULL, NULL);
if (status == ERROR_NO_MORE_ITEMS) { if (status == ERROR_NO_MORE_ITEMS) {
break; break;
} else if (status != ERROR_SUCCESS) { } else if (status != ERROR_SUCCESS) {
warnx("Error enumerating subkeys of registry key " TAP_ADAPTER_KEY ); warnx("Error enumerating subkeys of registry key " TAP_ADAPTER_KEY );
break; break;
} }
snprintf(unit, sizeof(unit), TAP_ADAPTER_KEY "\\%s", name); snprintf(unit, sizeof(unit), TAP_ADAPTER_KEY "\\%s", name);
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, unit, 0, KEY_READ, &device_key); status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, unit, 0, KEY_READ, &device_key);
if (status != ERROR_SUCCESS) { if (status != ERROR_SUCCESS) {
warnx("Error opening registry key %s", unit); warnx("Error opening registry key %s", unit);
goto next; goto next;
} }
/* Check component id */ /* Check component id */
len = sizeof(component); len = sizeof(component);
status = RegQueryValueEx(device_key, cid_string, NULL, &datatype, (LPBYTE)component, &len); status = RegQueryValueEx(device_key, cid_string, NULL, &datatype, (LPBYTE)component, &len);
if (status != ERROR_SUCCESS || datatype != REG_SZ) { if (status != ERROR_SUCCESS || datatype != REG_SZ) {
goto next; goto next;
} }
if (strncmp(TAP_VERSION_ID_0801, component, strlen(TAP_VERSION_ID_0801)) == 0 || 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, component, strlen(TAP_VERSION_ID_0901)) == 0) {
/* We found a TAP32 device, get its NetCfgInstanceId */ /* We found a TAP32 device, get its NetCfgInstanceId */
char iid_string[256] = NET_CFG_INST_ID; char iid_string[256] = NET_CFG_INST_ID;
status = RegQueryValueEx(device_key, iid_string, NULL, &datatype, (LPBYTE) device, (DWORD *) &device_len); status = RegQueryValueEx(device_key, iid_string, NULL, &datatype, (LPBYTE) device, (DWORD *) &device_len);
if (status != ERROR_SUCCESS || datatype != REG_SZ) { if (status != ERROR_SUCCESS || datatype != REG_SZ) {
warnx("Error reading registry key %s\\%s on TAP device", unit, iid_string); warnx("Error reading registry key %s\\%s on TAP device", unit, iid_string);
} else { } else {
/* Done getting GUID of TAP device, /* Done getting GUID of TAP device,
* now check if the name is the requested one */ * now check if the name is the requested one */
if (wanted_dev) { if (wanted_dev) {
char name[250]; char name[250];
get_name(name, sizeof(name), device); get_name(name, sizeof(name), device);
if (strncmp(name, wanted_dev, strlen(wanted_dev))) { if (strncmp(name, wanted_dev, strlen(wanted_dev))) {
/* Skip if name mismatch */ /* Skip if name mismatch */
goto next; goto next;
} }
} }
/* Get the if name */ /* Get the if name */
get_name(if_name, sizeof(if_name), device); get_name(if_name, sizeof(if_name), device);
RegCloseKey(device_key); RegCloseKey(device_key);
return; return;
} }
} }
next: next:
RegCloseKey(device_key); RegCloseKey(device_key);
index++; index++;
} }
RegCloseKey(adapter_key); RegCloseKey(adapter_key);
} }
static void static void
get_name(char *ifname, int namelen, char *dev_name) get_name(char *ifname, int namelen, char *dev_name)
{ {
char path[256]; char path[256];
char name_str[256] = "Name"; char name_str[256] = "Name";
LONG status; LONG status;
HKEY conn_key; HKEY conn_key;
DWORD len; DWORD len;
DWORD datatype; DWORD datatype;
memset(ifname, 0, namelen); memset(ifname, 0, namelen);
snprintf(path, sizeof(path), NETWORK_KEY "\\%s\\Connection", dev_name); snprintf(path, sizeof(path), NETWORK_KEY "\\%s\\Connection", dev_name);
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, path, 0, KEY_READ, &conn_key); status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, path, 0, KEY_READ, &conn_key);
if (status != ERROR_SUCCESS) { if (status != ERROR_SUCCESS) {
fprintf(stderr, "Could not look up name of interface %s: error opening key\n", dev_name); fprintf(stderr, "Could not look up name of interface %s: error opening key\n", dev_name);
RegCloseKey(conn_key); RegCloseKey(conn_key);
return; return;
} }
len = namelen; len = namelen;
status = RegQueryValueEx(conn_key, name_str, NULL, &datatype, (LPBYTE)ifname, &len); status = RegQueryValueEx(conn_key, name_str, NULL, &datatype, (LPBYTE)ifname, &len);
if (status != ERROR_SUCCESS || datatype != REG_SZ) { if (status != ERROR_SUCCESS || datatype != REG_SZ) {
fprintf(stderr, "Could not look up name of interface %s: error reading value\n", dev_name); fprintf(stderr, "Could not look up name of interface %s: error reading value\n", dev_name);
RegCloseKey(conn_key); RegCloseKey(conn_key);
return; return;
} }
RegCloseKey(conn_key); RegCloseKey(conn_key);
} }
DWORD WINAPI tun_reader(LPVOID arg) DWORD WINAPI tun_reader(LPVOID arg)
{ {
struct tun_data *tun = arg; struct tun_data *tun = arg;
char buf[64*1024]; char buf[64*1024];
int len; int len;
int res; int res;
OVERLAPPED olpd; OVERLAPPED olpd;
int sock; int sock;
sock = open_dns_from_host("127.0.0.1", 0, AF_INET, 0); sock = open_dns_from_host("127.0.0.1", 0, AF_INET, 0);
olpd.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); olpd.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
while(TRUE) { while(TRUE) {
olpd.Offset = 0; olpd.Offset = 0;
olpd.OffsetHigh = 0; olpd.OffsetHigh = 0;
res = ReadFile(tun->tun, buf, sizeof(buf), (LPDWORD) &len, &olpd); res = ReadFile(tun->tun, buf, sizeof(buf), (LPDWORD) &len, &olpd);
if (!res) { if (!res) {
WaitForSingleObject(olpd.hEvent, INFINITE); WaitForSingleObject(olpd.hEvent, INFINITE);
res = GetOverlappedResult(dev_handle, &olpd, (LPDWORD) &len, FALSE); res = GetOverlappedResult(dev_handle, &olpd, (LPDWORD) &len, FALSE);
res = sendto(sock, buf, len, 0, (struct sockaddr*) &(tun->addr), res = sendto(sock, buf, len, 0, (struct sockaddr*) &(tun->addr),
tun->addrlen); tun->addrlen);
} }
} }
return 0; return 0;
} }
int int
open_tun(const char *tun_device) open_tun(const char *tun_device)
{ {
char adapter[256]; char adapter[256];
char tapfile[512]; char tapfile[512];
int tunfd; int tunfd;
struct sockaddr_storage localsock; struct sockaddr_storage localsock;
int localsock_len; int localsock_len;
memset(adapter, 0, sizeof(adapter)); memset(adapter, 0, sizeof(adapter));
memset(if_name, 0, sizeof(if_name)); memset(if_name, 0, sizeof(if_name));
get_device(adapter, sizeof(adapter), tun_device); get_device(adapter, sizeof(adapter), tun_device);
if (strlen(adapter) == 0 || strlen(if_name) == 0) { if (strlen(adapter) == 0 || strlen(if_name) == 0) {
if (tun_device) { if (tun_device) {
warnx("No TAP adapters found. Try without -d."); warnx("No TAP adapters found. Try without -d.");
} else { } else {
warnx("No TAP adapters found. Version 0801 and 0901 are supported."); warnx("No TAP adapters found. Version 0801 and 0901 are supported.");
} }
return -1; return -1;
} }
fprintf(stderr, "Opening device %s\n", if_name); fprintf(stderr, "Opening device %s\n", if_name);
snprintf(tapfile, sizeof(tapfile), "%s%s.tap", TAP_DEVICE_SPACE, adapter); 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); 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) { if (dev_handle == INVALID_HANDLE_VALUE) {
warnx("Could not open device!"); warnx("Could not open device!");
return -1; return -1;
} }
/* Use a UDP connection to forward packets from tun, /* Use a UDP connection to forward packets from tun,
* so we can still use select() in main code. * so we can still use select() in main code.
* A thread does blocking reads on tun device and * A thread does blocking reads on tun device and
* sends data as udp to this socket */ * sends data as udp to this socket */
localsock_len = get_addr("127.0.0.1", 55353, AF_INET, 0, &localsock); localsock_len = get_addr("127.0.0.1", 55353, AF_INET, 0, &localsock);
tunfd = open_dns(&localsock, localsock_len); tunfd = open_dns(&localsock, localsock_len);
data.tun = dev_handle; data.tun = dev_handle;
memcpy(&(data.addr), &localsock, localsock_len); memcpy(&(data.addr), &localsock, localsock_len);
data.addrlen = localsock_len; data.addrlen = localsock_len;
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)tun_reader, &data, 0, NULL); CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)tun_reader, &data, 0, NULL);
return tunfd; return tunfd;
} }
#else /* BSD and friends */ #else /* BSD and friends */
@ -318,42 +318,42 @@ open_tun(const char *tun_device)
int int
open_tun(const char *tun_device) open_tun(const char *tun_device)
{ {
int i; int i;
int tun_fd; int tun_fd;
char tun_name[50]; char tun_name[50];
if (tun_device != NULL) { if (tun_device != NULL) {
snprintf(tun_name, sizeof(tun_name), "/dev/%s", tun_device); snprintf(tun_name, sizeof(tun_name), "/dev/%s", tun_device);
strncpy(if_name, tun_device, sizeof(if_name)); strncpy(if_name, tun_device, sizeof(if_name));
if_name[sizeof(if_name)-1] = '\0'; if_name[sizeof(if_name)-1] = '\0';
if ((tun_fd = open(tun_name, O_RDWR)) < 0) { if ((tun_fd = open(tun_name, O_RDWR)) < 0) {
warn("open_tun: %s", tun_name); warn("open_tun: %s", tun_name);
return -1; return -1;
} }
fprintf(stderr, "Opened %s\n", tun_name); fprintf(stderr, "Opened %s\n", tun_name);
fd_set_close_on_exec(tun_fd); fd_set_close_on_exec(tun_fd);
return tun_fd; return tun_fd;
} else { } else {
for (i = 0; i < TUN_MAX_TRY; i++) { for (i = 0; i < TUN_MAX_TRY; i++) {
snprintf(tun_name, sizeof(tun_name), "/dev/tun%d", i); snprintf(tun_name, sizeof(tun_name), "/dev/tun%d", i);
if ((tun_fd = open(tun_name, O_RDWR)) >= 0) { if ((tun_fd = open(tun_name, O_RDWR)) >= 0) {
fprintf(stderr, "Opened %s\n", tun_name); fprintf(stderr, "Opened %s\n", tun_name);
snprintf(if_name, sizeof(if_name), "tun%d", i); snprintf(if_name, sizeof(if_name), "tun%d", i);
fd_set_close_on_exec(tun_fd); fd_set_close_on_exec(tun_fd);
return tun_fd; return tun_fd;
} }
if (errno == ENOENT) if (errno == ENOENT)
break; break;
} }
warn("open_tun: Failed to open tunneling device"); warn("open_tun: Failed to open tunneling device");
} }
return -1; return -1;
} }
#endif #endif
@ -361,92 +361,92 @@ open_tun(const char *tun_device)
void void
close_tun(int tun_fd) close_tun(int tun_fd)
{ {
if (tun_fd >= 0) if (tun_fd >= 0)
close(tun_fd); close(tun_fd);
} }
#ifdef WINDOWS32 #ifdef WINDOWS32
int int
write_tun(int tun_fd, char *data, size_t len) write_tun(int tun_fd, char *data, size_t len)
{ {
DWORD written; DWORD written;
DWORD res; DWORD res;
OVERLAPPED olpd; OVERLAPPED olpd;
data += 4; data += 4;
len -= 4; len -= 4;
olpd.Offset = 0; olpd.Offset = 0;
olpd.OffsetHigh = 0; olpd.OffsetHigh = 0;
olpd.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); olpd.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
res = WriteFile(dev_handle, data, len, &written, &olpd); res = WriteFile(dev_handle, data, len, &written, &olpd);
if (!res && GetLastError() == ERROR_IO_PENDING) { if (!res && GetLastError() == ERROR_IO_PENDING) {
WaitForSingleObject(olpd.hEvent, INFINITE); WaitForSingleObject(olpd.hEvent, INFINITE);
res = GetOverlappedResult(dev_handle, &olpd, &written, FALSE); res = GetOverlappedResult(dev_handle, &olpd, &written, FALSE);
if (written != len) { if (written != len) {
return -1; return -1;
} }
} }
return 0; return 0;
} }
ssize_t ssize_t
read_tun(int tun_fd, char *buf, size_t len) read_tun(int tun_fd, char *buf, size_t len)
{ {
int bytes; int bytes;
memset(buf, 0, 4); memset(buf, 0, 4);
bytes = recv(tun_fd, buf + 4, len - 4, 0); bytes = recv(tun_fd, buf + 4, len - 4, 0);
if (bytes < 0) { if (bytes < 0) {
return bytes; return bytes;
} else { } else {
return bytes + 4; return bytes + 4;
} }
} }
#else #else
int int
write_tun(int tun_fd, char *data, size_t len) write_tun(int tun_fd, char *data, size_t len)
{ {
#if defined (FREEBSD) || defined (DARWIN) || defined(NETBSD) #if defined (FREEBSD) || defined (DARWIN) || defined(NETBSD)
data += 4; data += 4;
len -= 4; len -= 4;
#else /* !FREEBSD/DARWIN */ #else /* !FREEBSD/DARWIN */
#ifdef LINUX #ifdef LINUX
data[0] = 0x00; data[0] = 0x00;
data[1] = 0x00; data[1] = 0x00;
data[2] = 0x08; data[2] = 0x08;
data[3] = 0x00; data[3] = 0x00;
#else /* OPENBSD */ #else /* OPENBSD */
data[0] = 0x00; data[0] = 0x00;
data[1] = 0x00; data[1] = 0x00;
data[2] = 0x00; data[2] = 0x00;
data[3] = 0x02; data[3] = 0x02;
#endif /* !LINUX */ #endif /* !LINUX */
#endif /* FREEBSD */ #endif /* FREEBSD */
if (write(tun_fd, data, len) != len) { if (write(tun_fd, data, len) != len) {
warn("write_tun"); warn("write_tun");
return 1; return 1;
} }
return 0; return 0;
} }
ssize_t ssize_t
read_tun(int tun_fd, char *buf, size_t len) read_tun(int tun_fd, char *buf, size_t len)
{ {
#if defined (FREEBSD) || defined (DARWIN) || defined(NETBSD) #if defined (FREEBSD) || defined (DARWIN) || defined(NETBSD)
/* FreeBSD/Darwin/NetBSD has no header */ /* FreeBSD/Darwin/NetBSD has no header */
int bytes; int bytes;
memset(buf, 0, 4); memset(buf, 0, 4);
bytes = read(tun_fd, buf + 4, len - 4); bytes = read(tun_fd, buf + 4, len - 4);
if (bytes < 0) { if (bytes < 0) {
return bytes; return bytes;
} else { } else {
return bytes + 4; return bytes + 4;
} }
#else /* !FREEBSD */ #else /* !FREEBSD */
return read(tun_fd, buf, len); return read(tun_fd, buf, len);
#endif /* !FREEBSD */ #endif /* !FREEBSD */
} }
#endif #endif
@ -454,98 +454,98 @@ read_tun(int tun_fd, char *buf, size_t len)
int int
tun_setip(const char *ip, const char *other_ip, int netbits) tun_setip(const char *ip, const char *other_ip, int netbits)
{ {
char cmdline[512]; char cmdline[512];
int netmask; int netmask;
struct in_addr net; struct in_addr net;
int i; int i;
#ifndef LINUX #ifndef LINUX
int r; int r;
#endif #endif
#ifdef WINDOWS32 #ifdef WINDOWS32
DWORD status; DWORD status;
DWORD ipdata[3]; DWORD ipdata[3];
struct in_addr addr; struct in_addr addr;
DWORD len; DWORD len;
#else #else
const char *display_ip; const char *display_ip;
#ifndef LINUX #ifndef LINUX
struct in_addr netip; struct in_addr netip;
#endif #endif
#endif #endif
netmask = 0; netmask = 0;
for (i = 0; i < netbits; i++) { for (i = 0; i < netbits; i++) {
netmask = (netmask << 1) | 1; netmask = (netmask << 1) | 1;
} }
netmask <<= (32 - netbits); netmask <<= (32 - netbits);
net.s_addr = htonl(netmask); net.s_addr = htonl(netmask);
if (inet_addr(ip) == INADDR_NONE) { if (inet_addr(ip) == INADDR_NONE) {
fprintf(stderr, "Invalid IP: %s!\n", ip); fprintf(stderr, "Invalid IP: %s!\n", ip);
return 1; return 1;
} }
#ifndef WINDOWS32 #ifndef WINDOWS32
# ifdef FREEBSD # ifdef FREEBSD
display_ip = other_ip; /* FreeBSD wants other IP as second IP */ display_ip = other_ip; /* FreeBSD wants other IP as second IP */
# else # else
display_ip = ip; display_ip = ip;
# endif # endif
snprintf(cmdline, sizeof(cmdline), snprintf(cmdline, sizeof(cmdline),
IFCONFIGPATH "ifconfig %s %s %s netmask %s", IFCONFIGPATH "ifconfig %s %s %s netmask %s",
if_name, if_name,
ip, ip,
display_ip, display_ip,
inet_ntoa(net)); inet_ntoa(net));
fprintf(stderr, "Setting IP of %s to %s\n", if_name, ip); fprintf(stderr, "Setting IP of %s to %s\n", if_name, ip);
#ifndef LINUX #ifndef LINUX
netip.s_addr = inet_addr(ip); netip.s_addr = inet_addr(ip);
netip.s_addr = netip.s_addr & net.s_addr; netip.s_addr = netip.s_addr & net.s_addr;
r = system(cmdline); r = system(cmdline);
if(r != 0) { if(r != 0) {
return r; return r;
} else { } else {
snprintf(cmdline, sizeof(cmdline), snprintf(cmdline, sizeof(cmdline),
"/sbin/route add %s/%d %s", "/sbin/route add %s/%d %s",
inet_ntoa(netip), netbits, ip); inet_ntoa(netip), netbits, ip);
} }
fprintf(stderr, "Adding route %s/%d to %s\n", inet_ntoa(netip), netbits, ip); fprintf(stderr, "Adding route %s/%d to %s\n", inet_ntoa(netip), netbits, ip);
#endif #endif
return system(cmdline); return system(cmdline);
#else /* WINDOWS32 */ #else /* WINDOWS32 */
/* Set device as connected */ /* Set device as connected */
fprintf(stderr, "Enabling interface '%s'\n", if_name); fprintf(stderr, "Enabling interface '%s'\n", if_name);
status = 1; status = 1;
r = DeviceIoControl(dev_handle, TAP_IOCTL_SET_MEDIA_STATUS, &status, r = DeviceIoControl(dev_handle, TAP_IOCTL_SET_MEDIA_STATUS, &status,
sizeof(status), &status, sizeof(status), &len, NULL); sizeof(status), &status, sizeof(status), &len, NULL);
if (!r) { if (!r) {
fprintf(stderr, "Failed to enable interface\n"); fprintf(stderr, "Failed to enable interface\n");
return -1; return -1;
} }
if (inet_aton(ip, &addr)) { if (inet_aton(ip, &addr)) {
ipdata[0] = (DWORD) addr.s_addr; /* local ip addr */ ipdata[0] = (DWORD) addr.s_addr; /* local ip addr */
ipdata[1] = net.s_addr & ipdata[0]; /* network addr */ ipdata[1] = net.s_addr & ipdata[0]; /* network addr */
ipdata[2] = (DWORD) net.s_addr; /* netmask */ ipdata[2] = (DWORD) net.s_addr; /* netmask */
} else { } else {
return -1; return -1;
} }
/* Tell ip/networkaddr/netmask to device for arp use */ /* Tell ip/networkaddr/netmask to device for arp use */
r = DeviceIoControl(dev_handle, TAP_IOCTL_CONFIG_TUN, &ipdata, r = DeviceIoControl(dev_handle, TAP_IOCTL_CONFIG_TUN, &ipdata,
sizeof(ipdata), &ipdata, sizeof(ipdata), &len, NULL); sizeof(ipdata), &ipdata, sizeof(ipdata), &len, NULL);
if (!r) { if (!r) {
fprintf(stderr, "Failed to set interface in TUN mode\n"); fprintf(stderr, "Failed to set interface in TUN mode\n");
return -1; return -1;
} }
/* use netsh to set ip address */ /* use netsh to set ip address */
fprintf(stderr, "Setting IP of interface '%s' to %s (can take a few seconds)...\n", if_name, ip); 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", snprintf(cmdline, sizeof(cmdline), "netsh interface ip set address \"%s\" static %s %s",
if_name, ip, inet_ntoa(net)); if_name, ip, inet_ntoa(net));
return system(cmdline); return system(cmdline);
#endif #endif
} }
@ -553,24 +553,24 @@ int
tun_setmtu(const unsigned mtu) tun_setmtu(const unsigned mtu)
{ {
#ifndef WINDOWS32 #ifndef WINDOWS32
char cmdline[512]; char cmdline[512];
if (mtu > 200 && mtu <= 1500) { if (mtu > 200 && mtu <= 1500) {
snprintf(cmdline, sizeof(cmdline), snprintf(cmdline, sizeof(cmdline),
IFCONFIGPATH "ifconfig %s mtu %u", IFCONFIGPATH "ifconfig %s mtu %u",
if_name, if_name,
mtu); mtu);
fprintf(stderr, "Setting MTU of %s to %u\n", if_name, mtu); fprintf(stderr, "Setting MTU of %s to %u\n", if_name, mtu);
return system(cmdline); return system(cmdline);
} else { } else {
warn("MTU out of range: %u\n", mtu); warn("MTU out of range: %u\n", mtu);
} }
return 1; return 1;
#else /* WINDOWS32 */ #else /* WINDOWS32 */
return 0; return 0;
#endif #endif
} }

View file

@ -40,94 +40,94 @@ unsigned usercount;
int int
init_users(in_addr_t my_ip, int netbits) init_users(in_addr_t my_ip, int netbits)
{ {
int i; int i;
int skip = 0; int skip = 0;
char newip[16]; char newip[16];
int maxusers; int maxusers;
in_addr_t netmask = 0; in_addr_t netmask = 0;
struct in_addr net; struct in_addr net;
struct in_addr ipstart; struct in_addr ipstart;
for (i = 0; i < netbits; i++) { for (i = 0; i < netbits; i++) {
netmask = (netmask << 1) | 1; netmask = (netmask << 1) | 1;
} }
netmask <<= (32 - netbits); netmask <<= (32 - netbits);
net.s_addr = htonl(netmask); net.s_addr = htonl(netmask);
ipstart.s_addr = my_ip & net.s_addr; ipstart.s_addr = my_ip & net.s_addr;
maxusers = (1 << (32-netbits)) - 3; /* 3: Net addr, broadcast addr, iodined addr */ maxusers = (1 << (32-netbits)) - 3; /* 3: Net addr, broadcast addr, iodined addr */
usercount = MIN(maxusers, USERS); usercount = MIN(maxusers, USERS);
users = calloc(usercount, sizeof(struct tun_user)); users = calloc(usercount, sizeof(struct tun_user));
for (i = 0; i < usercount; i++) { for (i = 0; i < usercount; i++) {
in_addr_t ip; in_addr_t ip;
users[i].id = i; users[i].id = i;
snprintf(newip, sizeof(newip), "0.0.0.%d", i + skip + 1); snprintf(newip, sizeof(newip), "0.0.0.%d", i + skip + 1);
ip = ipstart.s_addr + inet_addr(newip); ip = ipstart.s_addr + inet_addr(newip);
if (ip == my_ip && skip == 0) { if (ip == my_ip && skip == 0) {
/* This IP was taken by iodined */ /* This IP was taken by iodined */
skip++; skip++;
snprintf(newip, sizeof(newip), "0.0.0.%d", i + skip + 1); snprintf(newip, sizeof(newip), "0.0.0.%d", i + skip + 1);
ip = ipstart.s_addr + inet_addr(newip); ip = ipstart.s_addr + inet_addr(newip);
} }
users[i].tun_ip = ip; users[i].tun_ip = ip;
net.s_addr = ip; net.s_addr = ip;
users[i].disabled = 0; users[i].disabled = 0;
users[i].authenticated = 0; users[i].authenticated = 0;
users[i].authenticated_raw = 0; users[i].authenticated_raw = 0;
users[i].active = 0; users[i].active = 0;
/* Rest is reset on login ('V' packet) */ /* Rest is reset on login ('V' packet) */
} }
return usercount; return usercount;
} }
const char* const char*
users_get_first_ip() users_get_first_ip()
{ {
struct in_addr ip; struct in_addr ip;
ip.s_addr = users[0].tun_ip; ip.s_addr = users[0].tun_ip;
return strdup(inet_ntoa(ip)); return strdup(inet_ntoa(ip));
} }
int int
users_waiting_on_reply() users_waiting_on_reply()
{ {
int ret; int ret;
int i; int i;
ret = 0; ret = 0;
for (i = 0; i < usercount; i++) { for (i = 0; i < usercount; i++) {
if (users[i].active && !users[i].disabled && if (users[i].active && !users[i].disabled &&
users[i].last_pkt + 60 > time(NULL) && users[i].last_pkt + 60 > time(NULL) &&
users[i].q.id != 0 && users[i].conn == CONN_DNS_NULL) { users[i].q.id != 0 && users[i].conn == CONN_DNS_NULL) {
ret++; ret++;
} }
} }
return ret; return ret;
} }
int int
find_user_by_ip(uint32_t ip) find_user_by_ip(uint32_t ip)
{ {
int ret; int ret;
int i; int i;
ret = -1; ret = -1;
for (i = 0; i < usercount; i++) { for (i = 0; i < usercount; i++) {
if (users[i].active && if (users[i].active &&
users[i].authenticated && users[i].authenticated &&
!users[i].disabled && !users[i].disabled &&
users[i].last_pkt + 60 > time(NULL) && users[i].last_pkt + 60 > time(NULL) &&
ip == users[i].tun_ip) { ip == users[i].tun_ip) {
ret = i; ret = i;
break; break;
} }
} }
return ret; return ret;
} }
int int
@ -138,70 +138,70 @@ all_users_waiting_to_send()
without going through another select loop. without going through another select loop.
*/ */
{ {
time_t now; time_t now;
int ret; int ret;
int i; int i;
ret = 1; ret = 1;
now = time(NULL); now = time(NULL);
for (i = 0; i < usercount; i++) { for (i = 0; i < usercount; i++) {
if (users[i].active && !users[i].disabled && if (users[i].active && !users[i].disabled &&
users[i].last_pkt + 60 > now && users[i].last_pkt + 60 > now &&
((users[i].conn == CONN_RAW_UDP) || ((users[i].conn == CONN_RAW_UDP) ||
((users[i].conn == CONN_DNS_NULL) ((users[i].conn == CONN_DNS_NULL)
#ifdef OUTPACKETQ_LEN #ifdef OUTPACKETQ_LEN
&& users[i].outpacketq_filled < 1 && users[i].outpacketq_filled < 1
#else #else
&& users[i].outpacket.len == 0 && users[i].outpacket.len == 0
#endif #endif
))) { ))) {
ret = 0; ret = 0;
break; break;
} }
} }
return ret; return ret;
} }
int int
find_available_user() find_available_user()
{ {
int ret = -1; int ret = -1;
int i; int i;
for (i = 0; i < usercount; i++) { for (i = 0; i < usercount; i++) {
/* Not used at all or not used in one minute */ /* Not used at all or not used in one minute */
if ((!users[i].active || users[i].last_pkt + 60 < time(NULL)) && !users[i].disabled) { if ((!users[i].active || users[i].last_pkt + 60 < time(NULL)) && !users[i].disabled) {
users[i].active = 1; users[i].active = 1;
users[i].authenticated = 0; users[i].authenticated = 0;
users[i].authenticated_raw = 0; users[i].authenticated_raw = 0;
users[i].last_pkt = time(NULL); users[i].last_pkt = time(NULL);
users[i].fragsize = 4096; users[i].fragsize = 4096;
users[i].conn = CONN_DNS_NULL; users[i].conn = CONN_DNS_NULL;
ret = i; ret = i;
break; break;
} }
} }
return ret; return ret;
} }
void void
user_switch_codec(int userid, struct encoder *enc) user_switch_codec(int userid, struct encoder *enc)
{ {
if (userid < 0 || userid >= usercount) if (userid < 0 || userid >= usercount)
return; return;
users[userid].encoder = enc; users[userid].encoder = enc;
} }
void void
user_set_conn_type(int userid, enum connection c) user_set_conn_type(int userid, enum connection c)
{ {
if (userid < 0 || userid >= usercount) if (userid < 0 || userid >= usercount)
return; return;
if (c < 0 || c >= CONN_MAX) if (c < 0 || c >= CONN_MAX)
return; return;
users[userid].conn = c; users[userid].conn = c;
} }

View file

@ -20,7 +20,7 @@
#define USERS 16 #define USERS 16
#define OUTPACKETQ_LEN 4 /* Note: 16 users * 1 packet = 1MB */ #define OUTPACKETQ_LEN 4 /* Note: 16 users * 1 packet = 1MB */
/* Undefine to have no queue for packets coming in from tun device, which may /* 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. */ lead to massive dropping in multi-user situations with high traffic. */
@ -35,44 +35,44 @@
/* Max advisable: 36/2 = 18. Total mem usage: QMEMDATA_LEN * USERS * 6 bytes */ /* Max advisable: 36/2 = 18. Total mem usage: QMEMDATA_LEN * USERS * 6 bytes */
struct tun_user { struct tun_user {
char id; char id;
int active; int active;
int authenticated; int authenticated;
int authenticated_raw; int authenticated_raw;
int disabled; int disabled;
time_t last_pkt; time_t last_pkt;
int seed; int seed;
in_addr_t tun_ip; in_addr_t tun_ip;
struct in_addr host; struct in_addr host;
struct query q; struct query q;
struct query q_sendrealsoon; struct query q_sendrealsoon;
int q_sendrealsoon_new; int q_sendrealsoon_new;
struct packet inpacket; struct packet inpacket;
struct packet outpacket; struct packet outpacket;
int outfragresent; int outfragresent;
struct encoder *encoder; struct encoder *encoder;
char downenc; char downenc;
int out_acked_seqno; int out_acked_seqno;
int out_acked_fragment; int out_acked_fragment;
int fragsize; int fragsize;
enum connection conn; enum connection conn;
int lazy; int lazy;
unsigned char qmemping_cmc[QMEMPING_LEN * 4]; unsigned char qmemping_cmc[QMEMPING_LEN * 4];
unsigned short qmemping_type[QMEMPING_LEN]; unsigned short qmemping_type[QMEMPING_LEN];
int qmemping_lastfilled; int qmemping_lastfilled;
unsigned char qmemdata_cmc[QMEMDATA_LEN * 4]; unsigned char qmemdata_cmc[QMEMDATA_LEN * 4];
unsigned short qmemdata_type[QMEMDATA_LEN]; unsigned short qmemdata_type[QMEMDATA_LEN];
int qmemdata_lastfilled; int qmemdata_lastfilled;
#ifdef OUTPACKETQ_LEN #ifdef OUTPACKETQ_LEN
struct packet outpacketq[OUTPACKETQ_LEN]; struct packet outpacketq[OUTPACKETQ_LEN];
int outpacketq_nexttouse; int outpacketq_nexttouse;
int outpacketq_filled; int outpacketq_filled;
#endif #endif
#ifdef DNSCACHE_LEN #ifdef DNSCACHE_LEN
struct query dnscache_q[DNSCACHE_LEN]; struct query dnscache_q[DNSCACHE_LEN];
char dnscache_answer[DNSCACHE_LEN][4096]; char dnscache_answer[DNSCACHE_LEN][4096];
int dnscache_answerlen[DNSCACHE_LEN]; int dnscache_answerlen[DNSCACHE_LEN];
int dnscache_lastfilled; int dnscache_lastfilled;
#endif #endif
}; };

View file

@ -21,62 +21,62 @@
char * char *
get_resolvconf_addr() get_resolvconf_addr()
{ {
static char addr[16]; static char addr[16];
char *rv; char *rv;
#ifndef WINDOWS32 #ifndef WINDOWS32
char buf[80]; char buf[80];
FILE *fp; FILE *fp;
#ifdef ANDROID #ifdef ANDROID
fp = popen("getprop net.dns1", "r"); fp = popen("getprop net.dns1", "r");
if (fp == NULL) if (fp == NULL)
err(1, "getprop net.dns1 failed"); err(1, "getprop net.dns1 failed");
if (fgets(buf, sizeof(buf), fp) == NULL) if (fgets(buf, sizeof(buf), fp) == NULL)
err(1, "read getprop net.dns1 failed"); err(1, "read getprop net.dns1 failed");
if (sscanf(buf, "%15s", addr) == 1) if (sscanf(buf, "%15s", addr) == 1)
rv = addr; rv = addr;
pclose(fp); pclose(fp);
#else #else
rv = NULL; rv = NULL;
if ((fp = fopen("/etc/resolv.conf", "r")) == NULL) if ((fp = fopen("/etc/resolv.conf", "r")) == NULL)
err(1, "/etc/resolv.conf"); err(1, "/etc/resolv.conf");
while (feof(fp) == 0) { while (feof(fp) == 0) {
fgets(buf, sizeof(buf), fp); fgets(buf, sizeof(buf), fp);
if (sscanf(buf, "nameserver %15s", addr) == 1) { if (sscanf(buf, "nameserver %15s", addr) == 1) {
rv = addr; rv = addr;
break; break;
} }
} }
fclose(fp); fclose(fp);
#endif #endif
#else /* !WINDOWS32 */ #else /* !WINDOWS32 */
FIXED_INFO *fixed_info; FIXED_INFO *fixed_info;
ULONG buflen; ULONG buflen;
DWORD ret; DWORD ret;
rv = NULL; rv = NULL;
fixed_info = malloc(sizeof(FIXED_INFO)); fixed_info = malloc(sizeof(FIXED_INFO));
buflen = sizeof(FIXED_INFO); buflen = sizeof(FIXED_INFO);
if (GetNetworkParams(fixed_info, &buflen) == ERROR_BUFFER_OVERFLOW) { if (GetNetworkParams(fixed_info, &buflen) == ERROR_BUFFER_OVERFLOW) {
/* official ugly api workaround */ /* official ugly api workaround */
free(fixed_info); free(fixed_info);
fixed_info = malloc(buflen); fixed_info = malloc(buflen);
} }
ret = GetNetworkParams(fixed_info, &buflen); ret = GetNetworkParams(fixed_info, &buflen);
if (ret == NO_ERROR) { if (ret == NO_ERROR) {
strncpy(addr, fixed_info->DnsServerList.IpAddress.String, sizeof(addr)); strncpy(addr, fixed_info->DnsServerList.IpAddress.String, sizeof(addr));
addr[15] = 0; addr[15] = 0;
rv = addr; rv = addr;
} }
free(fixed_info); free(fixed_info);
#endif #endif
return rv; return rv;
} }
#ifdef OPENBSD #ifdef OPENBSD
@ -84,10 +84,10 @@ void
socket_setrtable(int fd, int rtable) socket_setrtable(int fd, int rtable)
{ {
#ifdef SO_RTABLE #ifdef SO_RTABLE
if (setsockopt (fd, IPPROTO_IP, SO_RTABLE, &rtable, sizeof(rtable)) == -1) if (setsockopt (fd, IPPROTO_IP, SO_RTABLE, &rtable, sizeof(rtable)) == -1)
err(1, "Failed to set routing table %d", rtable); err(1, "Failed to set routing table %d", rtable);
#else #else
fprintf(stderr, "Routing domain support was not available at compile time.\n"); fprintf(stderr, "Routing domain support was not available at compile time.\n");
#endif #endif
} }
#endif #endif

View file

@ -29,116 +29,116 @@
static struct tuple static struct tuple
{ {
char *a; char *a;
char *b; char *b;
} testpairs[TUPLES] = { } testpairs[TUPLES] = {
{ "iodinetestingtesting", "nfxwi0lomv0gk21unfxgo3dfon0gs1th" }, { "iodinetestingtesting", "nfxwi0lomv0gk21unfxgo3dfon0gs1th" },
{ "abc123", "mfrggmjsgm" }, { "abc123", "mfrggmjsgm" },
{ "test", "orsxg3a" }, { "test", "orsxg3a" },
{ "tst", "orzxi" }, { "tst", "orzxi" },
{ "", "" }, { "", "" },
}; };
START_TEST(test_base32_encode) START_TEST(test_base32_encode)
{ {
size_t len; size_t len;
char buf[4096]; char buf[4096];
struct encoder *b32; struct encoder *b32;
int val; int val;
b32 = get_base32_encoder(); b32 = get_base32_encoder();
len = sizeof(buf); len = sizeof(buf);
val = b32->encode(buf, &len, testpairs[_i].a, strlen(testpairs[_i].a)); val = b32->encode(buf, &len, testpairs[_i].a, strlen(testpairs[_i].a));
fail_unless(val == strlen(testpairs[_i].b)); fail_unless(val == strlen(testpairs[_i].b));
fail_unless(strcmp(buf, testpairs[_i].b) == 0, fail_unless(strcmp(buf, testpairs[_i].b) == 0,
"'%s' != '%s'", buf, testpairs[_i].b); "'%s' != '%s'", buf, testpairs[_i].b);
} }
END_TEST END_TEST
START_TEST(test_base32_decode) START_TEST(test_base32_decode)
{ {
size_t len; size_t len;
char buf[4096]; char buf[4096];
struct encoder *b32; struct encoder *b32;
int val; int val;
b32 = get_base32_encoder(); b32 = get_base32_encoder();
len = sizeof(buf); len = sizeof(buf);
val = b32->decode(buf, &len, testpairs[_i].b, strlen(testpairs[_i].b)); val = b32->decode(buf, &len, testpairs[_i].b, strlen(testpairs[_i].b));
fail_unless(val == strlen(testpairs[_i].a)); fail_unless(val == strlen(testpairs[_i].a));
fail_unless(strcmp(buf, testpairs[_i].a) == 0, fail_unless(strcmp(buf, testpairs[_i].a) == 0,
"'%s' != '%s'", buf, testpairs[_i].a); "'%s' != '%s'", buf, testpairs[_i].a);
} }
END_TEST END_TEST
START_TEST(test_base32_5to8_8to5) START_TEST(test_base32_5to8_8to5)
{ {
int i; int i;
int c; int c;
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
c = b32_5to8(i); c = b32_5to8(i);
fail_unless(b32_8to5(c) == i); fail_unless(b32_8to5(c) == i);
} }
} }
END_TEST END_TEST
START_TEST(test_base32_blksize) START_TEST(test_base32_blksize)
{ {
size_t rawlen; size_t rawlen;
size_t enclen; size_t enclen;
char *rawbuf; char *rawbuf;
char *encbuf; char *encbuf;
struct encoder *b32; struct encoder *b32;
int i; int i;
int val; int val;
b32 = get_base32_encoder(); b32 = get_base32_encoder();
rawlen = b32->blocksize_raw(); rawlen = b32->blocksize_raw();
enclen = b32->blocksize_encoded(); enclen = b32->blocksize_encoded();
rawbuf = malloc(rawlen + 16); rawbuf = malloc(rawlen + 16);
encbuf = malloc(enclen + 16); encbuf = malloc(enclen + 16);
for (i = 0; i < rawlen; i++) { for (i = 0; i < rawlen; i++) {
rawbuf[i] = 'A'; rawbuf[i] = 'A';
} }
rawbuf[i] = 0; rawbuf[i] = 0;
val = b32->encode(encbuf, &enclen, rawbuf, rawlen); val = b32->encode(encbuf, &enclen, rawbuf, rawlen);
fail_unless(rawlen == 5, "raw length was %d not 5", rawlen); fail_unless(rawlen == 5, "raw length was %d not 5", rawlen);
fail_unless(enclen == 5, "encoded %d bytes, not 5", enclen); fail_unless(enclen == 5, "encoded %d bytes, not 5", enclen);
fail_unless(val == 8, "encoded string %s was length %d", encbuf, val); fail_unless(val == 8, "encoded string %s was length %d", encbuf, val);
memset(rawbuf, 0, rawlen + 16); memset(rawbuf, 0, rawlen + 16);
enclen = val; enclen = val;
val = b32->decode(rawbuf, &rawlen, encbuf, enclen); val = b32->decode(rawbuf, &rawlen, encbuf, enclen);
fail_unless(rawlen == 5, "raw length was %d not 5", rawlen); fail_unless(rawlen == 5, "raw length was %d not 5", rawlen);
fail_unless(val == 5, "val was not 5 but %d", val); fail_unless(val == 5, "val was not 5 but %d", val);
for (i = 0; i < rawlen; i++) { for (i = 0; i < rawlen; i++) {
fail_unless(rawbuf[i] == 'A'); fail_unless(rawbuf[i] == 'A');
} }
} }
END_TEST END_TEST
TCase * TCase *
test_base32_create_tests() test_base32_create_tests()
{ {
TCase *tc; TCase *tc;
tc = tcase_create("Base32"); tc = tcase_create("Base32");
tcase_add_loop_test(tc, test_base32_encode, 0, TUPLES); tcase_add_loop_test(tc, test_base32_encode, 0, TUPLES);
tcase_add_loop_test(tc, test_base32_decode, 0, TUPLES); tcase_add_loop_test(tc, test_base32_decode, 0, TUPLES);
tcase_add_test(tc, test_base32_5to8_8to5); tcase_add_test(tc, test_base32_5to8_8to5);
tcase_add_test(tc, test_base32_blksize); tcase_add_test(tc, test_base32_blksize);
return tc; return tc;
} }

View file

@ -29,129 +29,129 @@
static struct tuple static struct tuple
{ {
char *a; char *a;
char *b; char *b;
} testpairs[TUPLES] = { } testpairs[TUPLES] = {
{ "iodinetestingtesting", "Aw8KAw4LDgvZDgLUz2rLC2rPBMC" }, { "iodinetestingtesting", "Aw8KAw4LDgvZDgLUz2rLC2rPBMC" },
{ "abc1231", "ywjJmtiZmq" }, { "abc1231", "ywjJmtiZmq" },
{ {
"\xFF\xEF\x7C\xEF\xAE\x78\xDF\x6D\x74\xCF\x2C\x70\xBE\xEB\x6C\xAE\xAA\x68" "\xFF\xEF\x7C\xEF\xAE\x78\xDF\x6D\x74\xCF\x2C\x70\xBE\xEB\x6C\xAE\xAA\x68"
"\x9E\x69\x64\x8E\x28\x60\x7D\xE7\x5C\x6D\xA6\x58\x5D\x65\x54\x4D\x24\x50" "\x9E\x69\x64\x8E\x28\x60\x7D\xE7\x5C\x6D\xA6\x58\x5D\x65\x54\x4D\x24\x50"
"\x3C\xE3\x4C\x2C\xA2\x48\x1C\x61\x44\x0C\x20\x40\x3F\x3F\x3C\xEF\xAE\x78" "\x3C\xE3\x4C\x2C\xA2\x48\x1C\x61\x44\x0C\x20\x40\x3F\x3F\x3C\xEF\xAE\x78"
"\xDF\x6D\x74\xCF\x2C\x70\xBE\xEB\x6C\xAE\xAA\x68\x9E\x69\x64\x8E\x28\x60" "\xDF\x6D\x74\xCF\x2C\x70\xBE\xEB\x6C\xAE\xAA\x68\x9E\x69\x64\x8E\x28\x60"
"\x7D\xE7\x5C\x6D\xA6\x58\x5D\x65\x54\x4D\x24\x50\x3C\xE3\x4C\x2C\xA2\x48" "\x7D\xE7\x5C\x6D\xA6\x58\x5D\x65\x54\x4D\x24\x50\x3C\xE3\x4C\x2C\xA2\x48"
"\x1C\x61\x44\x0C\x20\x40\xFF\xEF\x7C\xEF\xAE\x78\xDF\x6D\x74\xCF\x2C\x70" "\x1C\x61\x44\x0C\x20\x40\xFF\xEF\x7C\xEF\xAE\x78\xDF\x6D\x74\xCF\x2C\x70"
"\xBE\xEB\x6C\xAE\xAA\x68\x9E\x69\x64\x8E\x28\x60\x7D\xE7\x5C\x6D\xA6\x58" "\xBE\xEB\x6C\xAE\xAA\x68\x9E\x69\x64\x8E\x28\x60\x7D\xE7\x5C\x6D\xA6\x58"
"\x5D\x65\x54\x4D\x24\x50\x3C\xE3\x4C\x2C\xA2\x48\x1C\x61\x44\x0C\x20\x40", "\x5D\x65\x54\x4D\x24\x50\x3C\xE3\x4C\x2C\xA2\x48\x1C\x61\x44\x0C\x20\x40",
"+9876543210-ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcbapZ" "+9876543210-ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcbapZ"
"776543210-ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba+987654" "776543210-ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba+987654"
"3210-ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba" "3210-ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba"
}, },
{ {
"\xFF\xEF\x7C\xEF\xAE\x78\xDF\x6D\x74\xCF\x2C\x70\xBE\xEB\x6C\xAE\xAA\x68" "\xFF\xEF\x7C\xEF\xAE\x78\xDF\x6D\x74\xCF\x2C\x70\xBE\xEB\x6C\xAE\xAA\x68"
"\x9E\x69\x64\x8E\x28\x60\x7D\xE7\x5C\x6D\xA6\x58\x5D\x65\x54\x4D\x24\x50" "\x9E\x69\x64\x8E\x28\x60\x7D\xE7\x5C\x6D\xA6\x58\x5D\x65\x54\x4D\x24\x50"
"\x3C\xE3\x4C\x2C\xA2\x48\x1C\x61\x44\x0C\x20\x40\x3F\x3F\x3C\xEF\xAE\x78" "\x3C\xE3\x4C\x2C\xA2\x48\x1C\x61\x44\x0C\x20\x40\x3F\x3F\x3C\xEF\xAE\x78"
"\xDF\x6D\x74\xCF\x2C\x70\xBE\xEB\x6C\xAE\xA1\x61\x91\x61\x61\x81\x28\x60" "\xDF\x6D\x74\xCF\x2C\x70\xBE\xEB\x6C\xAE\xA1\x61\x91\x61\x61\x81\x28\x60"
"\x7D\xE7\x5C\x6D\xA6\x58\x5D\x65\x54\x4D\x24\x50\x3C\xE3\x4C\x2C\xA2\x48" "\x7D\xE7\x5C\x6D\xA6\x58\x5D\x65\x54\x4D\x24\x50\x3C\xE3\x4C\x2C\xA2\x48"
"\x1C\x61\x44\x0C\x20\x40\xFF\xEF\x7C\xEF\xAE\x78\xDF\x6D\x74\xCF\x2C\x70" "\x1C\x61\x44\x0C\x20\x40\xFF\xEF\x7C\xEF\xAE\x78\xDF\x6D\x74\xCF\x2C\x70"
"\xBE\xEB\x6C\xAE\xA1\x61\x91\x61\x61\x81\x28\x60\x7D\xE7\x5C\x6D\xA6\x58" "\xBE\xEB\x6C\xAE\xA1\x61\x91\x61\x61\x81\x28\x60\x7D\xE7\x5C\x6D\xA6\x58"
"\x5D\x65\x54\x4D\x24\x50\x3C\xE3\x4C\x2C\xA2\x48\x1C\x61\x44\x0C\x20\x40", "\x5D\x65\x54\x4D\x24\x50\x3C\xE3\x4C\x2C\xA2\x48\x1C\x61\x44\x0C\x20\x40",
"+9876543210-ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcbapZ" "+9876543210-ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcbapZ"
"776543210-ZYXWVUTSRQfHKwfHGsHGFEDCBAzyxwvutsrqponmlkjihgfedcba+987654321" "776543210-ZYXWVUTSRQfHKwfHGsHGFEDCBAzyxwvutsrqponmlkjihgfedcba+987654321"
"0-ZYXWVUTSRQfHKwfHGsHGFEDCBAzyxwvutsrqponmlkjihgfedcba" "0-ZYXWVUTSRQfHKwfHGsHGFEDCBAzyxwvutsrqponmlkjihgfedcba"
}, },
{ "", "" } { "", "" }
}; };
START_TEST(test_base64_encode) START_TEST(test_base64_encode)
{ {
size_t len; size_t len;
char buf[4096]; char buf[4096];
struct encoder *b64; struct encoder *b64;
int val; int val;
b64 = get_base64_encoder(); b64 = get_base64_encoder();
len = sizeof(buf); len = sizeof(buf);
val = b64->encode(buf, &len, testpairs[_i].a, strlen(testpairs[_i].a)); val = b64->encode(buf, &len, testpairs[_i].a, strlen(testpairs[_i].a));
fail_unless(val == strlen(testpairs[_i].b)); fail_unless(val == strlen(testpairs[_i].b));
fail_unless(strcmp(buf, testpairs[_i].b) == 0, fail_unless(strcmp(buf, testpairs[_i].b) == 0,
"'%s' != '%s'", buf, testpairs[_i].b); "'%s' != '%s'", buf, testpairs[_i].b);
} }
END_TEST END_TEST
START_TEST(test_base64_decode) START_TEST(test_base64_decode)
{ {
size_t len; size_t len;
char buf[4096]; char buf[4096];
struct encoder *b64; struct encoder *b64;
int val; int val;
b64 = get_base64_encoder(); b64 = get_base64_encoder();
len = sizeof(buf); len = sizeof(buf);
val = b64->decode(buf, &len, testpairs[_i].b, strlen(testpairs[_i].b)); val = b64->decode(buf, &len, testpairs[_i].b, strlen(testpairs[_i].b));
fail_unless(val == strlen(testpairs[_i].a)); fail_unless(val == strlen(testpairs[_i].a));
fail_unless(strcmp(buf, testpairs[_i].a) == 0, fail_unless(strcmp(buf, testpairs[_i].a) == 0,
"'%s' != '%s'", buf, testpairs[_i].a); "'%s' != '%s'", buf, testpairs[_i].a);
} }
END_TEST END_TEST
START_TEST(test_base64_blksize) START_TEST(test_base64_blksize)
{ {
size_t rawlen; size_t rawlen;
size_t enclen; size_t enclen;
char *rawbuf; char *rawbuf;
char *encbuf; char *encbuf;
struct encoder *b64; struct encoder *b64;
int i; int i;
int val; int val;
b64 = get_base64_encoder(); b64 = get_base64_encoder();
rawlen = b64->blocksize_raw(); rawlen = b64->blocksize_raw();
enclen = b64->blocksize_encoded(); enclen = b64->blocksize_encoded();
rawbuf = malloc(rawlen + 16); rawbuf = malloc(rawlen + 16);
encbuf = malloc(enclen + 16); encbuf = malloc(enclen + 16);
for (i = 0; i < rawlen; i++) { for (i = 0; i < rawlen; i++) {
rawbuf[i] = 'A'; rawbuf[i] = 'A';
} }
rawbuf[i] = 0; rawbuf[i] = 0;
val = b64->encode(encbuf, &enclen, rawbuf, rawlen); val = b64->encode(encbuf, &enclen, rawbuf, rawlen);
fail_unless(rawlen == 3, "raw length was %d not 3", rawlen); fail_unless(rawlen == 3, "raw length was %d not 3", rawlen);
fail_unless(enclen == 3, "encoded %d bytes, not 3", enclen); fail_unless(enclen == 3, "encoded %d bytes, not 3", enclen);
fail_unless(val == 4, "encoded string %s was length %d", encbuf, val); fail_unless(val == 4, "encoded string %s was length %d", encbuf, val);
memset(rawbuf, 0, rawlen + 16); memset(rawbuf, 0, rawlen + 16);
enclen = val; enclen = val;
val = b64->decode(rawbuf, &rawlen, encbuf, enclen); val = b64->decode(rawbuf, &rawlen, encbuf, enclen);
fail_unless(rawlen == 3, "raw length was %d not 3", rawlen); fail_unless(rawlen == 3, "raw length was %d not 3", rawlen);
fail_unless(val == 3); fail_unless(val == 3);
for (i = 0; i < rawlen; i++) { for (i = 0; i < rawlen; i++) {
fail_unless(rawbuf[i] == 'A'); fail_unless(rawbuf[i] == 'A');
} }
} }
END_TEST END_TEST
TCase * TCase *
test_base64_create_tests() test_base64_create_tests()
{ {
TCase *tc; TCase *tc;
tc = tcase_create("Base64"); tc = tcase_create("Base64");
tcase_add_loop_test(tc, test_base64_encode, 0, TUPLES); tcase_add_loop_test(tc, test_base64_encode, 0, TUPLES);
tcase_add_loop_test(tc, test_base64_decode, 0, TUPLES); tcase_add_loop_test(tc, test_base64_decode, 0, TUPLES);
tcase_add_test(tc, test_base64_blksize); tcase_add_test(tc, test_base64_blksize);
return tc; return tc;
} }

View file

@ -23,198 +23,198 @@
START_TEST(test_topdomain_ok) START_TEST(test_topdomain_ok)
{ {
char *error; char *error;
fail_if(check_topdomain("foo.0123456789.qwertyuiop.asdfghjkl.zxcvbnm.com", &error)); fail_if(check_topdomain("foo.0123456789.qwertyuiop.asdfghjkl.zxcvbnm.com", &error));
/* Not allowed to start with dot */ /* Not allowed to start with dot */
fail_unless(check_topdomain(".foo.0123456789.qwertyuiop.asdfghjkl.zxcvbnm.com", &error)); fail_unless(check_topdomain(".foo.0123456789.qwertyuiop.asdfghjkl.zxcvbnm.com", &error));
fail_if(strcmp("Starts with a dot", error)); fail_if(strcmp("Starts with a dot", error));
/* Test missing error msg ptr */ /* Test missing error msg ptr */
fail_unless(check_topdomain(".foo", NULL)); fail_unless(check_topdomain(".foo", NULL));
} }
END_TEST END_TEST
START_TEST(test_topdomain_length) START_TEST(test_topdomain_length)
{ {
char *error; char *error;
/* Test empty and too short */ /* Test empty and too short */
fail_unless(check_topdomain("", &error)); fail_unless(check_topdomain("", &error));
fail_if(strcmp("Too short (< 3)", error)); fail_if(strcmp("Too short (< 3)", error));
fail_unless(check_topdomain("a", &error)); fail_unless(check_topdomain("a", &error));
fail_if(strcmp("Too short (< 3)", error)); fail_if(strcmp("Too short (< 3)", error));
fail_unless(check_topdomain(".a", &error)); fail_unless(check_topdomain(".a", &error));
fail_if(strcmp("Too short (< 3)", error)); fail_if(strcmp("Too short (< 3)", error));
fail_unless(check_topdomain("a.", &error)); fail_unless(check_topdomain("a.", &error));
fail_if(strcmp("Too short (< 3)", error)); fail_if(strcmp("Too short (< 3)", error));
fail_unless(check_topdomain("ab", &error)); fail_unless(check_topdomain("ab", &error));
fail_if(strcmp("Too short (< 3)", error)); fail_if(strcmp("Too short (< 3)", error));
fail_if(check_topdomain("a.b", &error)); fail_if(check_topdomain("a.b", &error));
fail_if(strcmp("Too short (< 3)", error)); fail_if(strcmp("Too short (< 3)", error));
/* Test too long (over 128, need rest of space for data) */ /* Test too long (over 128, need rest of space for data) */
fail_unless(check_topdomain( fail_unless(check_topdomain(
"abcd12345.abcd12345.abcd12345.abcd12345.abcd12345." "abcd12345.abcd12345.abcd12345.abcd12345.abcd12345."
"abcd12345.abcd12345.abcd12345.abcd12345.abcd12345." "abcd12345.abcd12345.abcd12345.abcd12345.abcd12345."
"abcd12345.abcd12345.foo129xxx", &error)); "abcd12345.abcd12345.foo129xxx", &error));
fail_if(strcmp("Too long (> 128)", error)); fail_if(strcmp("Too long (> 128)", error));
fail_if(check_topdomain( fail_if(check_topdomain(
"abcd12345.abcd12345.abcd12345.abcd12345.abcd12345." "abcd12345.abcd12345.abcd12345.abcd12345.abcd12345."
"abcd12345.abcd12345.abcd12345.abcd12345.abcd12345." "abcd12345.abcd12345.abcd12345.abcd12345.abcd12345."
"abcd12345.abcd12345.foo128xx", &error)); "abcd12345.abcd12345.foo128xx", &error));
} }
END_TEST END_TEST
START_TEST(test_topdomain_chunks) START_TEST(test_topdomain_chunks)
{ {
char *error; char *error;
/* Must have at least one dot */ /* Must have at least one dot */
fail_if(check_topdomain("abcde.gh", &error)); fail_if(check_topdomain("abcde.gh", &error));
fail_unless(check_topdomain("abcdefgh", &error)); fail_unless(check_topdomain("abcdefgh", &error));
fail_if(strcmp("No dots", error)); fail_if(strcmp("No dots", error));
/* Not two consecutive dots */ /* Not two consecutive dots */
fail_unless(check_topdomain("abc..defgh", &error)); fail_unless(check_topdomain("abc..defgh", &error));
fail_if(strcmp("Consecutive dots", error)); fail_if(strcmp("Consecutive dots", error));
/* Not end with a dots */ /* Not end with a dots */
fail_unless(check_topdomain("abc.defgh.", &error)); fail_unless(check_topdomain("abc.defgh.", &error));
fail_if(strcmp("Ends with a dot", error)); fail_if(strcmp("Ends with a dot", error));
/* No chunk longer than 63 chars */ /* No chunk longer than 63 chars */
fail_if(check_topdomain("123456789012345678901234567890" fail_if(check_topdomain("123456789012345678901234567890"
"123456789012345678901234567890333.com", &error)); "123456789012345678901234567890333.com", &error));
fail_unless(check_topdomain("123456789012345678901234567890" fail_unless(check_topdomain("123456789012345678901234567890"
"1234567890123456789012345678904444.com", &error)); "1234567890123456789012345678904444.com", &error));
fail_if(strcmp("Too long domain part (> 63)", error)); fail_if(strcmp("Too long domain part (> 63)", error));
fail_if(check_topdomain("abc.123456789012345678901234567890" fail_if(check_topdomain("abc.123456789012345678901234567890"
"123456789012345678901234567890333.com", &error)); "123456789012345678901234567890333.com", &error));
fail_unless(check_topdomain("abc.123456789012345678901234567890" fail_unless(check_topdomain("abc.123456789012345678901234567890"
"1234567890123456789012345678904444.com", &error)); "1234567890123456789012345678904444.com", &error));
fail_if(strcmp("Too long domain part (> 63)", error)); fail_if(strcmp("Too long domain part (> 63)", error));
fail_if(check_topdomain("abc.123456789012345678901234567890" fail_if(check_topdomain("abc.123456789012345678901234567890"
"123456789012345678901234567890333", &error)); "123456789012345678901234567890333", &error));
fail_unless(check_topdomain("abc.123456789012345678901234567890" fail_unless(check_topdomain("abc.123456789012345678901234567890"
"1234567890123456789012345678904444", &error)); "1234567890123456789012345678904444", &error));
fail_if(strcmp("Too long domain part (> 63)", error)); fail_if(strcmp("Too long domain part (> 63)", error));
} }
END_TEST END_TEST
START_TEST(test_parse_format_ipv4) START_TEST(test_parse_format_ipv4)
{ {
char *host = "192.168.2.10"; char *host = "192.168.2.10";
char *formatted; char *formatted;
struct sockaddr_storage addr; struct sockaddr_storage addr;
struct sockaddr_in *v4addr; struct sockaddr_in *v4addr;
int addr_len; int addr_len;
addr_len = get_addr(host, 53, AF_INET, 0, &addr); addr_len = get_addr(host, 53, AF_INET, 0, &addr);
fail_unless(addr_len == sizeof(struct sockaddr_in)); fail_unless(addr_len == sizeof(struct sockaddr_in));
v4addr = (struct sockaddr_in *) &addr; v4addr = (struct sockaddr_in *) &addr;
fail_unless(v4addr->sin_addr.s_addr == htonl(0xc0a8020a)); fail_unless(v4addr->sin_addr.s_addr == htonl(0xc0a8020a));
fail_unless(v4addr->sin_port == htons(53)); fail_unless(v4addr->sin_port == htons(53));
formatted = format_addr(&addr, addr_len); formatted = format_addr(&addr, addr_len);
fail_if(strcmp(host, formatted)); fail_if(strcmp(host, formatted));
} }
END_TEST END_TEST
START_TEST(test_parse_format_ipv4_listen_all) START_TEST(test_parse_format_ipv4_listen_all)
{ {
char *host = "0.0.0.0"; char *host = "0.0.0.0";
char *formatted; char *formatted;
struct sockaddr_storage addr; struct sockaddr_storage addr;
struct sockaddr_in *v4addr; struct sockaddr_in *v4addr;
int addr_len; int addr_len;
addr_len = get_addr(NULL, 53, AF_INET, AI_PASSIVE, &addr); addr_len = get_addr(NULL, 53, AF_INET, AI_PASSIVE, &addr);
fail_unless(addr_len == sizeof(struct sockaddr_in)); fail_unless(addr_len == sizeof(struct sockaddr_in));
v4addr = (struct sockaddr_in *) &addr; v4addr = (struct sockaddr_in *) &addr;
fail_unless(v4addr->sin_addr.s_addr == htonl(0x00000000)); fail_unless(v4addr->sin_addr.s_addr == htonl(0x00000000));
fail_unless(v4addr->sin_port == htons(53)); fail_unless(v4addr->sin_port == htons(53));
formatted = format_addr(&addr, addr_len); formatted = format_addr(&addr, addr_len);
fail_if(strcmp(host, formatted)); fail_if(strcmp(host, formatted));
} }
END_TEST END_TEST
START_TEST(test_parse_format_ipv6) START_TEST(test_parse_format_ipv6)
{ {
char *host = "2001:0db8:0505:0::123:0abc"; char *host = "2001:0db8:0505:0::123:0abc";
char *compact = "2001:db8:505::123:abc"; char *compact = "2001:db8:505::123:abc";
unsigned char v6_bits[] = { unsigned char v6_bits[] = {
0x20, 0x01, 0x0d, 0xb8, 0x05, 0x05, 0x00, 0x00, 0x20, 0x01, 0x0d, 0xb8, 0x05, 0x05, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x23, 0x0a, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x01, 0x23, 0x0a, 0xbc,
}; };
char *formatted; char *formatted;
struct sockaddr_storage addr; struct sockaddr_storage addr;
struct sockaddr_in6 *v6addr; struct sockaddr_in6 *v6addr;
int addr_len; int addr_len;
addr_len = get_addr(host, 53, AF_UNSPEC, 0, &addr); addr_len = get_addr(host, 53, AF_UNSPEC, 0, &addr);
fail_unless(addr_len == sizeof(struct sockaddr_in6)); fail_unless(addr_len == sizeof(struct sockaddr_in6));
v6addr = (struct sockaddr_in6 *) &addr; v6addr = (struct sockaddr_in6 *) &addr;
fail_if(memcmp(&v6addr->sin6_addr, v6_bits, sizeof(v6_bits))); fail_if(memcmp(&v6addr->sin6_addr, v6_bits, sizeof(v6_bits)));
fail_unless(v6addr->sin6_port == htons(53)); fail_unless(v6addr->sin6_port == htons(53));
formatted = format_addr(&addr, addr_len); formatted = format_addr(&addr, addr_len);
fail_if(strcmp(compact, formatted)); fail_if(strcmp(compact, formatted));
} }
END_TEST END_TEST
START_TEST(test_parse_format_ipv4_mapped_ipv6) START_TEST(test_parse_format_ipv4_mapped_ipv6)
{ {
char *v4mapped = "::FFFF:192.168.2.10"; char *v4mapped = "::FFFF:192.168.2.10";
char *host = "192.168.2.10"; char *host = "192.168.2.10";
unsigned char v6_bits[] = { unsigned char v6_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0xff, 0xc0, 0xa8, 0x02, 0x0a, 0x00, 0x00, 0xff, 0xff, 0xc0, 0xa8, 0x02, 0x0a,
}; };
char *formatted; char *formatted;
struct sockaddr_storage addr; struct sockaddr_storage addr;
struct sockaddr_in6 *v6addr; struct sockaddr_in6 *v6addr;
int addr_len; int addr_len;
addr_len = get_addr(v4mapped, 53, AF_INET6, 0, &addr); addr_len = get_addr(v4mapped, 53, AF_INET6, 0, &addr);
fail_unless(addr_len == sizeof(struct sockaddr_in6)); fail_unless(addr_len == sizeof(struct sockaddr_in6));
v6addr = (struct sockaddr_in6 *) &addr; v6addr = (struct sockaddr_in6 *) &addr;
fail_if(memcmp(&v6addr->sin6_addr, v6_bits, sizeof(v6_bits))); fail_if(memcmp(&v6addr->sin6_addr, v6_bits, sizeof(v6_bits)));
fail_unless(v6addr->sin6_port == htons(53)); fail_unless(v6addr->sin6_port == htons(53));
/* Format as IPv4 address */ /* Format as IPv4 address */
formatted = format_addr(&addr, addr_len); formatted = format_addr(&addr, addr_len);
fail_if(strcmp(host, formatted)); fail_if(strcmp(host, formatted));
} }
END_TEST END_TEST
TCase * TCase *
test_common_create_tests() test_common_create_tests()
{ {
TCase *tc; TCase *tc;
int sock; int sock;
tc = tcase_create("Common"); tc = tcase_create("Common");
tcase_add_test(tc, test_topdomain_ok); tcase_add_test(tc, test_topdomain_ok);
tcase_add_test(tc, test_topdomain_length); tcase_add_test(tc, test_topdomain_length);
tcase_add_test(tc, test_topdomain_chunks); tcase_add_test(tc, test_topdomain_chunks);
tcase_add_test(tc, test_parse_format_ipv4); tcase_add_test(tc, test_parse_format_ipv4);
tcase_add_test(tc, test_parse_format_ipv4_listen_all); tcase_add_test(tc, test_parse_format_ipv4_listen_all);
/* Tests require IPv6 support */ /* Tests require IPv6 support */
sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
if (sock >= 0) { if (sock >= 0) {
close(sock); close(sock);
tcase_add_test(tc, test_parse_format_ipv6); tcase_add_test(tc, test_parse_format_ipv6);
tcase_add_test(tc, test_parse_format_ipv4_mapped_ipv6); tcase_add_test(tc, test_parse_format_ipv4_mapped_ipv6);
} }
return tc; return tc;
} }

View file

@ -29,81 +29,81 @@
static struct tuple static struct tuple
{ {
char *a; char *a;
char *b; char *b;
} dottests[] = { } dottests[] = {
{ "aaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", { "aaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"aaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaa"}, "aaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaa"},
{ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", { "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."}, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."},
{ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", { "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"},
{ "abc123", "abc123" }, { "abc123", "abc123" },
{ NULL, NULL } { NULL, NULL }
}; };
START_TEST(test_inline_dotify) START_TEST(test_inline_dotify)
{ {
char temp[1024]; char temp[1024];
char *b; char *b;
memset(temp, 0, sizeof(temp)); memset(temp, 0, sizeof(temp));
strcpy(temp, dottests[_i].a); strcpy(temp, dottests[_i].a);
b = temp; b = temp;
inline_dotify(b, sizeof(temp)); inline_dotify(b, sizeof(temp));
fail_unless(strcmp(dottests[_i].b, temp) == 0, fail_unless(strcmp(dottests[_i].b, temp) == 0,
"'%s' != '%s'", temp, dottests[_i].b); "'%s' != '%s'", temp, dottests[_i].b);
} }
END_TEST END_TEST
START_TEST(test_inline_undotify) START_TEST(test_inline_undotify)
{ {
char temp[1024]; char temp[1024];
char *b; char *b;
memset(temp, 0, sizeof(temp)); memset(temp, 0, sizeof(temp));
strcpy(temp, dottests[_i].b); strcpy(temp, dottests[_i].b);
b = temp; b = temp;
inline_undotify(b, sizeof(temp)); inline_undotify(b, sizeof(temp));
fail_unless(strcmp(dottests[_i].a, temp) == 0, fail_unless(strcmp(dottests[_i].a, temp) == 0,
"'%s' != '%s'", temp, dottests[_i].a); "'%s' != '%s'", temp, dottests[_i].a);
} }
END_TEST END_TEST
START_TEST(test_build_hostname) START_TEST(test_build_hostname)
{ {
char data[256]; char data[256];
char buf[1024]; char buf[1024];
char *topdomain = "a.c"; char *topdomain = "a.c";
int buflen; int buflen;
int i; int i;
for (i = 0; i < sizeof(data); i++) { for (i = 0; i < sizeof(data); i++) {
data[i] = i & 0xFF; data[i] = i & 0xFF;
} }
buflen = sizeof(buf); buflen = sizeof(buf);
for (i = 1; i < sizeof(data); i++) { for (i = 1; i < sizeof(data); i++) {
int len = build_hostname(buf, buflen, data, i, topdomain, get_base32_encoder(), sizeof(buf)); int len = build_hostname(buf, buflen, data, i, topdomain, get_base32_encoder(), sizeof(buf));
fail_if(len > i); fail_if(len > i);
fail_if(strstr(buf, ".."), "Found double dots when encoding data len %d! buf: %s", i, buf); fail_if(strstr(buf, ".."), "Found double dots when encoding data len %d! buf: %s", i, buf);
} }
} }
END_TEST END_TEST
TCase * TCase *
test_encoding_create_tests() test_encoding_create_tests()
{ {
TCase *tc; TCase *tc;
tc = tcase_create("Encoding"); tc = tcase_create("Encoding");
tcase_add_loop_test(tc, test_inline_dotify, 0, TUPLES); tcase_add_loop_test(tc, test_inline_dotify, 0, TUPLES);
tcase_add_loop_test(tc, test_inline_undotify, 0, TUPLES); tcase_add_loop_test(tc, test_inline_undotify, 0, TUPLES);
tcase_add_test(tc, test_build_hostname); tcase_add_test(tc, test_build_hostname);
return tc; return tc;
} }

View file

@ -21,68 +21,68 @@
START_TEST(test_fw_query_simple) START_TEST(test_fw_query_simple)
{ {
struct fw_query q; struct fw_query q;
struct fw_query *qp; struct fw_query *qp;
q.addrlen = 33; q.addrlen = 33;
q.id = 0x848A; q.id = 0x848A;
fw_query_init(); fw_query_init();
/* Test empty cache */ /* Test empty cache */
fw_query_get(0x848A, &qp); fw_query_get(0x848A, &qp);
fail_unless(qp == NULL); fail_unless(qp == NULL);
fw_query_put(&q); fw_query_put(&q);
/* Test cache with one entry */ /* Test cache with one entry */
fw_query_get(0x848A, &qp); fw_query_get(0x848A, &qp);
fail_unless(qp->addrlen == q.addrlen); fail_unless(qp->addrlen == q.addrlen);
fail_unless(qp->id == q.id); fail_unless(qp->id == q.id);
} }
END_TEST END_TEST
START_TEST(test_fw_query_edge) START_TEST(test_fw_query_edge)
{ {
struct fw_query q; struct fw_query q;
struct fw_query *qp; struct fw_query *qp;
int i; int i;
fw_query_init(); fw_query_init();
q.addrlen = 33; q.addrlen = 33;
q.id = 0x848A; q.id = 0x848A;
fw_query_put(&q); fw_query_put(&q);
for (i = 1; i < FW_QUERY_CACHE_SIZE; i++) { for (i = 1; i < FW_QUERY_CACHE_SIZE; i++) {
q.addrlen++; q.addrlen++;
q.id++; q.id++;
fw_query_put(&q); fw_query_put(&q);
} }
/* The query should still be cached */ /* The query should still be cached */
fw_query_get(0x848A, &qp); fw_query_get(0x848A, &qp);
fail_unless(qp->addrlen == 33); fail_unless(qp->addrlen == 33);
fail_unless(qp->id == 0x848A); fail_unless(qp->id == 0x848A);
q.addrlen++; q.addrlen++;
q.id++; q.id++;
fw_query_put(&q); fw_query_put(&q);
/* but now it is overwritten */ /* but now it is overwritten */
fw_query_get(0x848A, &qp); fw_query_get(0x848A, &qp);
fail_unless(qp == NULL); fail_unless(qp == NULL);
} }
END_TEST END_TEST
TCase * TCase *
test_fw_query_create_tests() test_fw_query_create_tests()
{ {
TCase *tc; TCase *tc;
tc = tcase_create("Forwarded query"); tc = tcase_create("Forwarded query");
tcase_add_test(tc, test_fw_query_simple); tcase_add_test(tc, test_fw_query_simple);
tcase_add_test(tc, test_fw_query_edge); tcase_add_test(tc, test_fw_query_edge);
return tc; return tc;
} }

View file

@ -23,49 +23,49 @@
START_TEST(test_login_hash) START_TEST(test_login_hash)
{ {
char ans[16]; char ans[16];
char good[] = "\x2A\x8A\x12\xB4\xE0\x42\xEE\xAB\xD0\x19\x17\x1E\x44\xA0\x88\xCD"; char good[] = "\x2A\x8A\x12\xB4\xE0\x42\xEE\xAB\xD0\x19\x17\x1E\x44\xA0\x88\xCD";
char pass[32] = "iodine is the shit"; char pass[32] = "iodine is the shit";
int len; int len;
int seed; int seed;
len = sizeof(ans); len = sizeof(ans);
seed = 15; seed = 15;
memset(ans, 0, sizeof(ans)); memset(ans, 0, sizeof(ans));
login_calculate(ans, len, pass, seed); login_calculate(ans, len, pass, seed);
fail_unless(strncmp(ans, good, len) == 0, NULL); fail_unless(strncmp(ans, good, len) == 0, NULL);
} }
END_TEST END_TEST
START_TEST(test_login_hash_short) START_TEST(test_login_hash_short)
{ {
char ans[8]; char ans[8];
char check[sizeof(ans)]; char check[sizeof(ans)];
char pass[32] = "iodine is the shit"; char pass[32] = "iodine is the shit";
int len; int len;
int seed; int seed;
len = sizeof(ans); len = sizeof(ans);
seed = 15; seed = 15;
memset(ans, 0, sizeof(ans)); memset(ans, 0, sizeof(ans));
memset(check, 0, sizeof(check)); memset(check, 0, sizeof(check));
/* If len < 16, it should do nothing */ /* If len < 16, it should do nothing */
login_calculate(ans, len, pass, seed); login_calculate(ans, len, pass, seed);
fail_if(memcmp(ans, check, sizeof(ans))); fail_if(memcmp(ans, check, sizeof(ans)));
} }
END_TEST END_TEST
TCase * TCase *
test_login_create_tests() test_login_create_tests()
{ {
TCase *tc; TCase *tc;
tc = tcase_create("Login"); tc = tcase_create("Login");
tcase_add_test(tc, test_login_hash); tcase_add_test(tc, test_login_hash);
tcase_add_test(tc, test_login_hash_short); tcase_add_test(tc, test_login_hash_short);
return tc; return tc;
} }

View file

@ -38,234 +38,234 @@
START_TEST(test_read_putshort) START_TEST(test_read_putshort)
{ {
unsigned short k; unsigned short k;
unsigned short l; unsigned short l;
char* p; char* p;
int i; int i;
for (i = 0; i < 65536; i++) { for (i = 0; i < 65536; i++) {
p = (char*)&k; p = (char*)&k;
putshort(&p, i); putshort(&p, i);
fail_unless(ntohs(k) == i, fail_unless(ntohs(k) == i,
"Bad value on putshort for %d: %d != %d", "Bad value on putshort for %d: %d != %d",
i, ntohs(k), i); i, ntohs(k), i);
p = (char*)&k; p = (char*)&k;
readshort(NULL, &p, &l); readshort(NULL, &p, &l);
fail_unless(l == i, fail_unless(l == i,
"Bad value on readshort for %d: %d != %d", "Bad value on readshort for %d: %d != %d",
i, l, i); i, l, i);
} }
} }
END_TEST END_TEST
START_TEST(test_read_putlong) START_TEST(test_read_putlong)
{ {
uint32_t k; uint32_t k;
uint32_t l; uint32_t l;
char* p; char* p;
int i; int i;
int j; int j;
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
p = (char*)&k; p = (char*)&k;
j = 0xf << i; j = 0xf << i;
putlong(&p, j); putlong(&p, j);
fail_unless(ntohl(k) == j, fail_unless(ntohl(k) == j,
"Bad value on putlong for %d: %d != %d", i, ntohl(j), j); "Bad value on putlong for %d: %d != %d", i, ntohl(j), j);
p = (char*)&k; p = (char*)&k;
readlong(NULL, &p, &l); readlong(NULL, &p, &l);
fail_unless(l == j, fail_unless(l == j,
"Bad value on readlong for %d: %d != %d", i, l, j); "Bad value on readlong for %d: %d != %d", i, l, j);
} }
} }
END_TEST END_TEST
START_TEST(test_read_name_empty_loop) START_TEST(test_read_name_empty_loop)
{ {
unsigned char emptyloop[] = { unsigned char emptyloop[] = {
'A', 'A', 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 'A', 'A', 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01 }; 0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01 };
char buf[1024]; char buf[1024];
char *data; char *data;
int rv; int rv;
memset(buf, 0, sizeof(buf)); memset(buf, 0, sizeof(buf));
data = (char*) emptyloop + sizeof(HEADER); data = (char*) emptyloop + sizeof(HEADER);
buf[1023] = 'A'; buf[1023] = 'A';
rv = readname((char *) emptyloop, sizeof(emptyloop), &data, buf, 1023); rv = readname((char *) emptyloop, sizeof(emptyloop), &data, buf, 1023);
fail_unless(rv == 0); fail_unless(rv == 0);
fail_unless(buf[1023] == 'A'); fail_unless(buf[1023] == 'A');
} }
END_TEST END_TEST
START_TEST(test_read_name_inf_loop) START_TEST(test_read_name_inf_loop)
{ {
unsigned char infloop[] = { unsigned char infloop[] = {
'A', 'A', 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 'A', 'A', 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 'A', 0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01 }; 0x01, 'A', 0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01 };
char buf[1024]; char buf[1024];
char *data; char *data;
int rv; int rv;
memset(buf, 0, sizeof(buf)); memset(buf, 0, sizeof(buf));
data = (char*) infloop + sizeof(HEADER); data = (char*) infloop + sizeof(HEADER);
buf[4] = '\a'; buf[4] = '\a';
rv = readname((char*) infloop, sizeof(infloop), &data, buf, 4); rv = readname((char*) infloop, sizeof(infloop), &data, buf, 4);
fail_unless(rv == 3); fail_unless(rv == 3);
fail_unless(buf[4] == '\a'); fail_unless(buf[4] == '\a');
} }
END_TEST END_TEST
START_TEST(test_read_name_longname) START_TEST(test_read_name_longname)
{ {
unsigned char longname[] = unsigned char longname[] =
"AA\x81\x80\x00\x01\x00\x00\x00\x00\x00\x00" "AA\x81\x80\x00\x01\x00\x00\x00\x00\x00\x00"
"\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA" "\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA"
"\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA" "\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA"
"\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA" "\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA"
"\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA" "\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA"
"\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA" "\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA"
"\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA" "\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA"
"\x00\x00\x01\x00\x01"; "\x00\x00\x01\x00\x01";
char buf[1024]; char buf[1024];
char *data; char *data;
int rv; int rv;
memset(buf, 0, sizeof(buf)); memset(buf, 0, sizeof(buf));
data = (char*) longname + sizeof(HEADER); data = (char*) longname + sizeof(HEADER);
buf[256] = '\a'; buf[256] = '\a';
rv = readname((char*) longname, sizeof(longname), &data, buf, 256); rv = readname((char*) longname, sizeof(longname), &data, buf, 256);
fail_unless(rv == 256); fail_unless(rv == 256);
fail_unless(buf[256] == '\a'); fail_unless(buf[256] == '\a');
} }
END_TEST END_TEST
START_TEST(test_read_name_onejump) START_TEST(test_read_name_onejump)
{ {
unsigned char onejump[] = unsigned char onejump[] =
"AA\x81\x80\x00\x01\x00\x00\x00\x00\x00\x00" "AA\x81\x80\x00\x01\x00\x00\x00\x00\x00\x00"
"\x02hh\xc0\x15\x00\x01\x00\x01\x05zBCDE\x00"; "\x02hh\xc0\x15\x00\x01\x00\x01\x05zBCDE\x00";
char buf[1024]; char buf[1024];
char *data; char *data;
int rv; int rv;
memset(buf, 0, sizeof(buf)); memset(buf, 0, sizeof(buf));
data = (char*) onejump + sizeof(HEADER); data = (char*) onejump + sizeof(HEADER);
rv = readname((char*) onejump, sizeof(onejump), &data, buf, 256); rv = readname((char*) onejump, sizeof(onejump), &data, buf, 256);
fail_unless(rv == 9); fail_unless(rv == 9);
} }
END_TEST END_TEST
START_TEST(test_read_name_badjump_start) START_TEST(test_read_name_badjump_start)
{ {
unsigned char badjump[] = { unsigned char badjump[] = {
'A', 'A', 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 'A', 'A', 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xfe, 0xcc, 0x00, 0x01, 0x00, 0x01 }; 0xfe, 0xcc, 0x00, 0x01, 0x00, 0x01 };
unsigned char *jumper; unsigned char *jumper;
char buf[1024]; char buf[1024];
char *data; char *data;
int rv; int rv;
/* This test uses malloc to cause segfault if jump is executed */ /* This test uses malloc to cause segfault if jump is executed */
memset(buf, 0, sizeof(buf)); memset(buf, 0, sizeof(buf));
jumper = malloc(sizeof(badjump)); jumper = malloc(sizeof(badjump));
if (jumper) { if (jumper) {
memcpy(jumper, badjump, sizeof(badjump)); memcpy(jumper, badjump, sizeof(badjump));
data = (char*) jumper + sizeof(HEADER); data = (char*) jumper + sizeof(HEADER);
rv = readname((char*) jumper, sizeof(badjump), &data, buf, 256); rv = readname((char*) jumper, sizeof(badjump), &data, buf, 256);
fail_unless(rv == 0); fail_unless(rv == 0);
fail_unless(buf[0] == 0); fail_unless(buf[0] == 0);
} }
free(jumper); free(jumper);
} }
END_TEST END_TEST
START_TEST(test_read_name_badjump_second) START_TEST(test_read_name_badjump_second)
{ {
unsigned char badjump2[] = { unsigned char badjump2[] = {
'A', 'A', 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 'A', 'A', 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 'B', 'A', 0xfe, 0xcc, 0x00, 0x01, 0x00, 0x01 }; 0x02, 'B', 'A', 0xfe, 0xcc, 0x00, 0x01, 0x00, 0x01 };
unsigned char *jumper; unsigned char *jumper;
char buf[1024]; char buf[1024];
char *data; char *data;
int rv; int rv;
/* This test uses malloc to cause segfault if jump is executed */ /* This test uses malloc to cause segfault if jump is executed */
memset(buf, 0, sizeof(buf)); memset(buf, 0, sizeof(buf));
jumper = malloc(sizeof(badjump2)); jumper = malloc(sizeof(badjump2));
if (jumper) { if (jumper) {
memcpy(jumper, badjump2, sizeof(badjump2)); memcpy(jumper, badjump2, sizeof(badjump2));
data = (char*) jumper + sizeof(HEADER); data = (char*) jumper + sizeof(HEADER);
rv = readname((char*) jumper, sizeof(badjump2), &data, buf, 256); rv = readname((char*) jumper, sizeof(badjump2), &data, buf, 256);
fail_unless(rv == 4); fail_unless(rv == 4);
fail_unless(strcmp("BA.", buf) == 0, fail_unless(strcmp("BA.", buf) == 0,
"buf is not BA: %s", buf); "buf is not BA: %s", buf);
} }
free(jumper); free(jumper);
} }
END_TEST END_TEST
START_TEST(test_putname) START_TEST(test_putname)
{ {
char out[] = "\x06" "BADGER\x06" "BADGER\x04" "KRYO\x02" "SE\x00"; char out[] = "\x06" "BADGER\x06" "BADGER\x04" "KRYO\x02" "SE\x00";
char buf[256]; char buf[256];
char *domain = "BADGER.BADGER.KRYO.SE"; char *domain = "BADGER.BADGER.KRYO.SE";
char *b; char *b;
int ret; int ret;
memset(buf, 0, 256); memset(buf, 0, 256);
b = buf; b = buf;
ret = putname(&b, 256, domain); ret = putname(&b, 256, domain);
fail_unless(ret == strlen(domain) + 1); fail_unless(ret == strlen(domain) + 1);
fail_unless(strncmp(buf, out, ret) == 0, "Happy flow failed"); fail_unless(strncmp(buf, out, ret) == 0, "Happy flow failed");
} }
END_TEST END_TEST
START_TEST(test_putname_nodot) START_TEST(test_putname_nodot)
{ {
char buf[256]; char buf[256];
char *nodot = char *nodot =
"ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ" "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"
"ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"; "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ";
char *b; char *b;
int ret; int ret;
memset(buf, 0, 256); memset(buf, 0, 256);
b = buf; b = buf;
ret = putname(&b, 256, nodot); ret = putname(&b, 256, nodot);
fail_unless(ret == -1); fail_unless(ret == -1);
fail_unless(b == buf); fail_unless(b == buf);
} }
END_TEST END_TEST
START_TEST(test_putname_toolong) START_TEST(test_putname_toolong)
{ {
char buf[256]; char buf[256];
char *toolong = char *toolong =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ." "ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ."
"ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ." "ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ."
"ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ." "ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ."
"ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ." "ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ."
"ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ." "ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ."
"ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ."; "ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ.";
char *b; char *b;
int ret; int ret;
memset(buf, 0, 256); memset(buf, 0, 256);
b = buf; b = buf;
ret = putname(&b, 256, toolong); ret = putname(&b, 256, toolong);
fail_unless(ret == -1); fail_unless(ret == -1);
fail_unless(b == buf); fail_unless(b == buf);
} }
END_TEST END_TEST
@ -273,21 +273,21 @@ END_TEST
TCase * TCase *
test_read_create_tests() test_read_create_tests()
{ {
TCase *tc; TCase *tc;
tc = tcase_create("Read"); tc = tcase_create("Read");
tcase_set_timeout(tc, 60); tcase_set_timeout(tc, 60);
tcase_add_test(tc, test_read_putshort); tcase_add_test(tc, test_read_putshort);
tcase_add_test(tc, test_read_putlong); tcase_add_test(tc, test_read_putlong);
tcase_add_test(tc, test_read_name_empty_loop); tcase_add_test(tc, test_read_name_empty_loop);
tcase_add_test(tc, test_read_name_inf_loop); tcase_add_test(tc, test_read_name_inf_loop);
tcase_add_test(tc, test_read_name_longname); tcase_add_test(tc, test_read_name_longname);
tcase_add_test(tc, test_read_name_onejump); tcase_add_test(tc, test_read_name_onejump);
tcase_add_test(tc, test_read_name_badjump_start); tcase_add_test(tc, test_read_name_badjump_start);
tcase_add_test(tc, test_read_name_badjump_second); tcase_add_test(tc, test_read_name_badjump_second);
tcase_add_test(tc, test_putname); tcase_add_test(tc, test_putname);
tcase_add_test(tc, test_putname_nodot); tcase_add_test(tc, test_putname_nodot);
tcase_add_test(tc, test_putname_toolong); tcase_add_test(tc, test_putname_toolong);
return tc; return tc;
} }

View file

@ -26,45 +26,45 @@
int int
main() main()
{ {
SRunner *runner; SRunner *runner;
Suite *iodine; Suite *iodine;
TCase *test; TCase *test;
int failed; int failed;
iodine = suite_create("iodine"); iodine = suite_create("iodine");
test = test_base32_create_tests(); test = test_base32_create_tests();
suite_add_tcase(iodine, test); suite_add_tcase(iodine, test);
test = test_base64_create_tests(); test = test_base64_create_tests();
suite_add_tcase(iodine, test); suite_add_tcase(iodine, test);
test = test_common_create_tests(); test = test_common_create_tests();
suite_add_tcase(iodine, test); suite_add_tcase(iodine, test);
test = test_dns_create_tests(); test = test_dns_create_tests();
suite_add_tcase(iodine, test); suite_add_tcase(iodine, test);
test = test_encoding_create_tests(); test = test_encoding_create_tests();
suite_add_tcase(iodine, test); suite_add_tcase(iodine, test);
test = test_read_create_tests(); test = test_read_create_tests();
suite_add_tcase(iodine, test); suite_add_tcase(iodine, test);
test = test_login_create_tests(); test = test_login_create_tests();
suite_add_tcase(iodine, test); suite_add_tcase(iodine, test);
test = test_user_create_tests(); test = test_user_create_tests();
suite_add_tcase(iodine, test); suite_add_tcase(iodine, test);
test = test_fw_query_create_tests(); test = test_fw_query_create_tests();
suite_add_tcase(iodine, test); suite_add_tcase(iodine, test);
runner = srunner_create(iodine); runner = srunner_create(iodine);
srunner_run_all(runner, CK_NORMAL); srunner_run_all(runner, CK_NORMAL);
failed = srunner_ntests_failed(runner); failed = srunner_ntests_failed(runner);
srunner_free(runner); srunner_free(runner);
return (failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; return (failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
} }

View file

@ -31,8 +31,8 @@ TCase *test_fw_query_create_tests();
char *va_str(const char *, ...); char *va_str(const char *, ...);
#if (CHECK_MAJOR_VERSION == 0 && \ #if (CHECK_MAJOR_VERSION == 0 && \
((CHECK_MINOR_VERSION == 9 && CHECK_MICRO_VERSION < 2) || \ ((CHECK_MINOR_VERSION == 9 && CHECK_MICRO_VERSION < 2) || \
(CHECK_MINOR_VERSION < 9))) (CHECK_MINOR_VERSION < 9)))
#define tcase_set_timeout(...) #define tcase_set_timeout(...)
#endif #endif

View file

@ -30,181 +30,181 @@
START_TEST(test_init_users) START_TEST(test_init_users)
{ {
in_addr_t ip; in_addr_t ip;
char givenip[16]; char givenip[16];
int i; int i;
int count; int count;
ip = inet_addr("127.0.0.1"); ip = inet_addr("127.0.0.1");
count = init_users(ip, 27); count = init_users(ip, 27);
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
fail_unless(users[i].id == i); fail_unless(users[i].id == i);
fail_unless(users[i].q.id == 0); fail_unless(users[i].q.id == 0);
fail_unless(users[i].inpacket.len == 0); fail_unless(users[i].inpacket.len == 0);
fail_unless(users[i].outpacket.len == 0); fail_unless(users[i].outpacket.len == 0);
snprintf(givenip, sizeof(givenip), "127.0.0.%d", i + 2); snprintf(givenip, sizeof(givenip), "127.0.0.%d", i + 2);
fail_unless(users[i].tun_ip == inet_addr(givenip)); fail_unless(users[i].tun_ip == inet_addr(givenip));
} }
} }
END_TEST END_TEST
START_TEST(test_users_waiting) START_TEST(test_users_waiting)
{ {
in_addr_t ip; in_addr_t ip;
ip = inet_addr("127.0.0.1"); ip = inet_addr("127.0.0.1");
init_users(ip, 27); init_users(ip, 27);
fail_unless(users_waiting_on_reply() == 0); fail_unless(users_waiting_on_reply() == 0);
users[3].active = 1; users[3].active = 1;
fail_unless(users_waiting_on_reply() == 0); fail_unless(users_waiting_on_reply() == 0);
users[3].last_pkt = time(NULL); users[3].last_pkt = time(NULL);
fail_unless(users_waiting_on_reply() == 0); fail_unless(users_waiting_on_reply() == 0);
users[3].conn = CONN_DNS_NULL; users[3].conn = CONN_DNS_NULL;
users[3].q.id = 1; users[3].q.id = 1;
fail_unless(users_waiting_on_reply() == 1); fail_unless(users_waiting_on_reply() == 1);
} }
END_TEST END_TEST
START_TEST(test_find_user_by_ip) START_TEST(test_find_user_by_ip)
{ {
in_addr_t ip; in_addr_t ip;
unsigned int testip; unsigned int testip;
ip = inet_addr("127.0.0.1"); ip = inet_addr("127.0.0.1");
init_users(ip, 27); init_users(ip, 27);
users[0].conn = CONN_DNS_NULL; users[0].conn = CONN_DNS_NULL;
testip = (unsigned int) inet_addr("10.0.0.1"); testip = (unsigned int) inet_addr("10.0.0.1");
fail_unless(find_user_by_ip(testip) == -1); fail_unless(find_user_by_ip(testip) == -1);
testip = (unsigned int) inet_addr("127.0.0.2"); testip = (unsigned int) inet_addr("127.0.0.2");
fail_unless(find_user_by_ip(testip) == -1); fail_unless(find_user_by_ip(testip) == -1);
users[0].active = 1; users[0].active = 1;
testip = (unsigned int) inet_addr("127.0.0.2"); testip = (unsigned int) inet_addr("127.0.0.2");
fail_unless(find_user_by_ip(testip) == -1); fail_unless(find_user_by_ip(testip) == -1);
users[0].last_pkt = time(NULL); users[0].last_pkt = time(NULL);
testip = (unsigned int) inet_addr("127.0.0.2"); testip = (unsigned int) inet_addr("127.0.0.2");
fail_unless(find_user_by_ip(testip) == -1); fail_unless(find_user_by_ip(testip) == -1);
users[0].authenticated = 1; users[0].authenticated = 1;
testip = (unsigned int) inet_addr("127.0.0.2"); testip = (unsigned int) inet_addr("127.0.0.2");
fail_unless(find_user_by_ip(testip) == 0); fail_unless(find_user_by_ip(testip) == 0);
} }
END_TEST END_TEST
START_TEST(test_all_users_waiting_to_send) START_TEST(test_all_users_waiting_to_send)
{ {
in_addr_t ip; in_addr_t ip;
ip = inet_addr("127.0.0.1"); ip = inet_addr("127.0.0.1");
init_users(ip, 27); init_users(ip, 27);
fail_unless(all_users_waiting_to_send() == 1); fail_unless(all_users_waiting_to_send() == 1);
users[0].conn = CONN_DNS_NULL; users[0].conn = CONN_DNS_NULL;
users[0].active = 1; users[0].active = 1;
fail_unless(all_users_waiting_to_send() == 1); fail_unless(all_users_waiting_to_send() == 1);
users[0].last_pkt = time(NULL); users[0].last_pkt = time(NULL);
users[0].outpacket.len = 0; users[0].outpacket.len = 0;
fail_unless(all_users_waiting_to_send() == 0); fail_unless(all_users_waiting_to_send() == 0);
#ifdef OUTPACKETQ_LEN #ifdef OUTPACKETQ_LEN
users[0].outpacketq_filled = 1; users[0].outpacketq_filled = 1;
#else #else
users[0].outpacket.len = 44; users[0].outpacket.len = 44;
#endif #endif
fail_unless(all_users_waiting_to_send() == 1); fail_unless(all_users_waiting_to_send() == 1);
} }
END_TEST END_TEST
START_TEST(test_find_available_user) START_TEST(test_find_available_user)
{ {
in_addr_t ip; in_addr_t ip;
int i; int i;
ip = inet_addr("127.0.0.1"); ip = inet_addr("127.0.0.1");
init_users(ip, 27); init_users(ip, 27);
for (i = 0; i < USERS; i++) { for (i = 0; i < USERS; i++) {
users[i].authenticated = 1; users[i].authenticated = 1;
users[i].authenticated_raw = 1; users[i].authenticated_raw = 1;
fail_unless(find_available_user() == i); fail_unless(find_available_user() == i);
fail_if(users[i].authenticated); fail_if(users[i].authenticated);
fail_if(users[i].authenticated_raw); fail_if(users[i].authenticated_raw);
} }
for (i = 0; i < USERS; i++) { for (i = 0; i < USERS; i++) {
fail_unless(find_available_user() == -1); fail_unless(find_available_user() == -1);
} }
users[3].active = 0; users[3].active = 0;
fail_unless(find_available_user() == 3); fail_unless(find_available_user() == 3);
fail_unless(find_available_user() == -1); fail_unless(find_available_user() == -1);
users[3].last_pkt = 55; users[3].last_pkt = 55;
fail_unless(find_available_user() == 3); fail_unless(find_available_user() == 3);
fail_unless(find_available_user() == -1); fail_unless(find_available_user() == -1);
} }
END_TEST END_TEST
START_TEST(test_find_available_user_small_net) START_TEST(test_find_available_user_small_net)
{ {
in_addr_t ip; in_addr_t ip;
int i; int i;
ip = inet_addr("127.0.0.1"); ip = inet_addr("127.0.0.1");
init_users(ip, 29); /* this should result in 5 enabled users */ init_users(ip, 29); /* this should result in 5 enabled users */
for (i = 0; i < 5; i++) { for (i = 0; i < 5; i++) {
fail_unless(find_available_user() == i); fail_unless(find_available_user() == i);
} }
for (i = 0; i < USERS; i++) { for (i = 0; i < USERS; i++) {
fail_unless(find_available_user() == -1); fail_unless(find_available_user() == -1);
} }
users[3].active = 0; users[3].active = 0;
fail_unless(find_available_user() == 3); fail_unless(find_available_user() == 3);
fail_unless(find_available_user() == -1); fail_unless(find_available_user() == -1);
users[3].last_pkt = 55; users[3].last_pkt = 55;
fail_unless(find_available_user() == 3); fail_unless(find_available_user() == 3);
fail_unless(find_available_user() == -1); fail_unless(find_available_user() == -1);
} }
END_TEST END_TEST
TCase * TCase *
test_user_create_tests() test_user_create_tests()
{ {
TCase *tc; TCase *tc;
tc = tcase_create("User"); tc = tcase_create("User");
tcase_add_test(tc, test_init_users); tcase_add_test(tc, test_init_users);
tcase_add_test(tc, test_users_waiting); tcase_add_test(tc, test_users_waiting);
tcase_add_test(tc, test_find_user_by_ip); tcase_add_test(tc, test_find_user_by_ip);
tcase_add_test(tc, test_all_users_waiting_to_send); tcase_add_test(tc, test_all_users_waiting_to_send);
tcase_add_test(tc, test_find_available_user); tcase_add_test(tc, test_find_available_user);
tcase_add_test(tc, test_find_available_user_small_net); tcase_add_test(tc, test_find_available_user_small_net);
return tc; return tc;
} }