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)
require {
type init_t;
type initrc_t;
type unconfined_t;
type unlabeled_t;
class udp_socket { read write };
class rawip_socket { write read };
class association recvfrom;
class unix_dgram_socket { create connect };
type init_t;
type initrc_t;
type unconfined_t;
type unlabeled_t;
class udp_socket { read write };
class rawip_socket { write read };
class association recvfrom;
class unix_dgram_socket { create connect };
}
type iodine_t;

View File

@ -5,55 +5,55 @@ CMC = 2 byte Cache Miss Counter, increased every time it is used
Version:
Client sends:
First byte v or V
Rest encoded with base32:
4 bytes big endian protocol version
CMC
First byte v or V
Rest encoded with base32:
4 bytes big endian protocol version
CMC
Server replies:
4 chars:
VACK (version ok), followed by login challenge
VNAK (version differs), followed by server protocol version
VFUL (server has no free slots), followed by 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
4 chars:
VACK (version ok), followed by login challenge
VNAK (version differs), followed by server protocol version
VFUL (server has no free slots), followed by 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
Login:
Client sends:
First byte l or L
Rest encoded with base32:
1 byte userid
16 bytes MD5 hash of: (first 32 bytes of password) xor (8 repetitions of login challenge)
CMC
First byte l or L
Rest encoded with base32:
1 byte userid
16 bytes MD5 hash of: (first 32 bytes of password) xor (8 repetitions of login challenge)
CMC
Server replies:
LNAK means not accepted
x.x.x.x-y.y.y.y-mtu means accepted (server ip, client ip, mtu)
LNAK means not accepted
x.x.x.x-y.y.y.y-mtu means accepted (server ip, client ip, mtu)
Case check:
Client sends:
First byte z or Z
Lots of data that should not be decoded
Client sends:
First byte z or Z
Lots of data that should not be decoded
Server replies:
The requested domain copied raw
The requested domain copied raw
Data:
Data header:
321 0
+---+-+
|UUU|L|
+---+-+
321 0
+---+-+
|UUU|L|
+---+-+
UUU = Userid
L = Last fragment in packet flag
First byte is the header, 4 bits coded as hex in ASCII.
First byte is the header, 4 bits coded as hex in ASCII.
Followed by data encoded with Base32.
Ping:
Client sends:
First byte p or P
Rest encoded with Base32:
1 byte userid
CMC
First byte p or P
Rest encoded with Base32:
1 byte userid
CMC
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.

View File

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

View File

@ -8,170 +8,170 @@ Note: work in progress!!
======================================================
Quick alphabetical index / register:
0-9 Data packet
A-F Data packet
I IP address
L Login
N Downstream fragsize (NS.topdomain A-type reply)
O Options
P Ping
R Downstream fragsize probe
S Switch upstream codec
V Version
W (WWW.topdomain A-type reply)
Y Downstream codec check
Z Upstream codec check
0-9 Data packet
A-F Data packet
I IP address
L Login
N Downstream fragsize (NS.topdomain A-type reply)
O Options
P Ping
R Downstream fragsize probe
S Switch upstream codec
V Version
W (WWW.topdomain A-type reply)
Y Downstream codec check
Z Upstream codec check
CMC = 2 byte Cache Miss Counter, increased every time it is used
Version:
Client sends:
First byte v or V
Rest encoded with base32:
4 bytes big endian protocol version
CMC
First byte v or V
Rest encoded with base32:
4 bytes big endian protocol version
CMC
Server replies:
4 chars:
VACK (version ok), followed by login challenge
VNAK (version differs), followed by server protocol version
VFUL (server has no free slots), followed by 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
4 chars:
VACK (version ok), followed by login challenge
VNAK (version differs), followed by server protocol version
VFUL (server has no free slots), followed by 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
Login:
Client sends:
First byte l or L
Rest encoded with base32:
1 byte userid
16 bytes MD5 hash of: (first 32 bytes of password) xor (8 repetitions of login challenge)
CMC
First byte l or L
Rest encoded with base32:
1 byte userid
16 bytes MD5 hash of: (first 32 bytes of password) xor (8 repetitions of login challenge)
CMC
Server replies:
LNAK means not accepted
x.x.x.x-y.y.y.y-mtu-netmask means accepted (server ip, client ip, mtu, netmask bits)
LNAK means not accepted
x.x.x.x-y.y.y.y-mtu-netmask means accepted (server ip, client ip, mtu, netmask bits)
IP Request:
Client sends:
First byte i or I
5 bits coded as Base32 char, meaning userid
CMC as 3 Base32 chars
First byte i or I
5 bits coded as Base32 char, meaning userid
CMC as 3 Base32 chars
Server replies
BADIP if bad userid, or
I and then 4 bytes network order external IP address of iodined server
BADIP if bad userid, or
I and then 4 bytes network order external IP address of iodined server
Upstream codec check / bounce:
Client sends:
First byte z or Z
Lots of data that should not be decoded
Client sends:
First byte z or Z
Lots of data that should not be decoded
Server replies:
The requested domain copied raw, in the lowest-grade downstream codec
available for the request type.
The requested domain copied raw, in the lowest-grade downstream codec
available for the request type.
Downstream codec check:
Client sends:
First byte y or Y
1 char, meaning downstream codec to use
5 bits coded as Base32 char, meaning check variant
CMC as 3 Base32 chars
Possibly extra data, depending on check variant
First byte y or Y
1 char, meaning downstream codec to use
5 bits coded as Base32 char, meaning check variant
CMC as 3 Base32 chars
Possibly extra data, depending on check variant
Server sends:
Data encoded with requested downstream codec; data content depending
on check variant number.
BADCODEC if requested downstream codec not available.
BADLEN if check variant is not available, or problem with extra data.
Data encoded with requested downstream codec; data content depending
on check variant number.
BADCODEC if requested downstream codec not available.
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:
1: Send encoded DOWNCODECCHECK1 string as defined in encoding.h
Check variants:
1: Send encoded DOWNCODECCHECK1 string as defined in encoding.h
(Other variants reserved; possibly variant that sends a decoded-encoded
copy of Base32-encoded extra data in the request)
(Other variants reserved; possibly variant that sends a decoded-encoded
copy of Base32-encoded extra data in the request)
Switch codec:
Client sends:
First byte s or S
5 bits coded as Base32 char, meaning userid
5 bits coded as Base32 char, representing number of raw bits per
encoded byte:
5: Base32 (a-z0-5)
6: Base64 (a-zA-Z0-9+-)
26: Base64u (a-zA-Z0-9_-)
7: Base128 (a-zA-Z0-9\274-\375)
CMC as 3 Base32 chars
First byte s or S
5 bits coded as Base32 char, meaning userid
5 bits coded as Base32 char, representing number of raw bits per
encoded byte:
5: Base32 (a-z0-5)
6: Base64 (a-zA-Z0-9+-)
26: Base64u (a-zA-Z0-9_-)
7: Base128 (a-zA-Z0-9\274-\375)
CMC as 3 Base32 chars
Server sends:
Name of codec if accepted. After this all upstream data packets must
be encoded with the new codec.
BADCODEC if not accepted. Client must then revert to previous codec
BADLEN if length of query is too short
Name of codec if accepted. After this all upstream data packets must
be encoded with the new codec.
BADCODEC if not accepted. Client must then revert to previous codec
BADLEN if length of query is too short
Options:
Client sends:
First byte o or O
5 bits coded as Base32 char, meaning userid
1 char, meaning option
CMC as 3 Base32 chars
First byte o or O
5 bits coded as Base32 char, meaning userid
1 char, meaning option
CMC as 3 Base32 chars
Server sends:
Full name of option if accepted. After this, option immediately takes
effect in server.
BADCODEC if not accepted. Previous situation remains.
All options affect only the requesting client.
Full name of option if accepted. After this, option immediately takes
effect in server.
BADCODEC if not accepted. Previous situation remains.
All options affect only the requesting client.
Option chars:
t or T: Downstream encoding Base32, for TXT/CNAME/A/MX (default)
s or S: Downstream encoding Base64, 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
r or R: Downstream encoding Raw, for PRIVATE/TXT/NULL (default for
PRIVATE and NULL)
If codec unsupported for request type, server will use Base32; note
that server will answer any mix of request types that a client sends.
Server may disregard this option; client must always use the downstream
encoding type indicated in every downstream DNS packet.
Option chars:
t or T: Downstream encoding Base32, for TXT/CNAME/A/MX (default)
s or S: Downstream encoding Base64, 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
r or R: Downstream encoding Raw, for PRIVATE/TXT/NULL (default for
PRIVATE and NULL)
If codec unsupported for request type, server will use Base32; note
that server will answer any mix of request types that a client sends.
Server may disregard this option; client must always use the downstream
encoding type indicated in every downstream DNS packet.
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
answered immediately.
i or I: Immediate (non-lazy) mode, server will answer all requests
(nearly) immediately.
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
answered immediately.
i or I: Immediate (non-lazy) mode, server will answer all requests
(nearly) immediately.
Probe downstream fragment size:
Client sends:
First byte r or R
15 bits coded as 3 Base32 chars: UUUUF FFFFF FFFFF
meaning 4 bits userid, 11 bits fragment size
Then follows a long random query which contents does not matter
First byte r or R
15 bits coded as 3 Base32 chars: UUUUF FFFFF FFFFF
meaning 4 bits userid, 11 bits fragment size
Then follows a long random query which contents does not matter
Server sends:
Requested number of bytes as a response. The first two bytes contain
the requested length. The third byte is 107 (0x6B). The fourth byte
is a random value, and each following byte is incremented with 107.
This is checked by the client to determine corruption.
BADFRAG if requested length not accepted.
Requested number of bytes as a response. The first two bytes contain
the requested length. The third byte is 107 (0x6B). The fourth byte
is a random value, and each following byte is incremented with 107.
This is checked by the client to determine corruption.
BADFRAG if requested length not accepted.
Set downstream fragment size:
Client sends:
First byte n or N
Rest encoded with base32:
1 byte userid
2 bytes new downstream fragment size
CMC
First byte n or N
Rest encoded with base32:
1 byte userid
2 bytes new downstream fragment size
CMC
Server sends:
2 bytes new downstream fragment size. After this all downstream
payloads will be max (fragsize + 2) bytes long.
BADFRAG if not accepted.
2 bytes new downstream fragment size. After this all downstream
payloads will be max (fragsize + 2) bytes long.
BADFRAG if not accepted.
Data:
Upstream data header:
3210 432 10 43 210 4321 0 43210
+----+---+--+--+---+----+-+-----+
|UUUU|SSS|FF|FF|DDD|GGGG|L|UDCMC|
+----+---+--+--+---+----+-+-----+
3210 432 10 43 210 4321 0 43210
+----+---+--+--+---+----+-+-----+
|UUUU|SSS|FF|FF|DDD|GGGG|L|UDCMC|
+----+---+--+--+---+----+-+-----+
Downstream data header:
7 654 3210 765 4321 0
+-+---+----+---+----+-+
|C|SSS|FFFF|DDD|GGGG|L|
+-+---+----+---+----+-+
7 654 3210 765 4321 0
+-+---+----+---+----+-+
|C|SSS|FFFF|DDD|GGGG|L|
+-+---+----+---+----+-+
UUUU = Userid
L = Last fragment in packet flag
@ -182,7 +182,7 @@ GGGG = Downstream fragment number
C = Compression enabled for downstream packet
UDCMC = Upstream Data CMC, 36 steps a-z0-9, case-insensitive
Upstream data packet starts with 1 byte ASCII hex coded user byte; then 3 bytes
Upstream data packet starts with 1 byte ASCII hex coded user byte; then 3 bytes
Base32 encoded header; then 1 char data-CMC; then comes the payload data,
encoded with the chosen upstream codec.
@ -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).
Encoding type is indicated by 1 prefix char:
TXT:
End result is always DNS-chopped (series of len-prefixed strings
<=255 bytes)
t or T: Base32 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
v or V: Base128 encoded before chop, decoded after un-chop
r or R: Raw no encoding, only DNS-chop
End result is always DNS-chopped (series of len-prefixed strings
<=255 bytes)
t or T: Base32 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
v or V: Base128 encoded before chop, decoded after un-chop
r or R: Raw no encoding, only DNS-chop
SRV/MX/CNAME/A:
h or H: Hostname encoded with Base32
i or I: Hostname encoded with Base64
j or J: Hostname encoded with Base64u
k or K: Hostname encoded with Base128
h or H: Hostname encoded with Base32
i or I: Hostname encoded with Base64
j or J: Hostname encoded with Base64u
k or K: Hostname encoded with Base128
SRV and MX may reply with multiple hostnames, each encoded separately. Each
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
@ -212,21 +212,21 @@ relays will shuffle the answer records in the response.
Ping:
Client sends:
First byte p or P
Rest encoded with Base32:
1 byte with 4 bits userid
1 byte with:
3 bits downstream seqno
4 bits downstream fragment
CMC
First byte p or P
Rest encoded with Base32:
1 byte with 4 bits userid
1 byte with:
3 bits downstream seqno
4 bits downstream fragment
CMC
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.
If server has nothing to send, no data is added after the header.
If server has something to send, it will add the downstream data packet
(or some fragment of it) after the header.
"Lazy-mode" operation
=====================
@ -250,7 +250,7 @@ downstream data has to be sent.
*: upstream data ack is usually done as reply on the previous ping packet,
and the upstream-data packet itself is kept in queue.
Client:
Downstream data is acked immediately, to keep it flowing fast (includes a
ping after last downstream frag).
@ -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.
The fourth byte contains the command and the user id.
7654 3210
+----+----+
|CCCC|UUUU|
+----+----+
7654 3210
+----+----+
|CCCC|UUUU|
+----+----+
Login message (command = 1):
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__
typedef struct {
unsigned id :16;
unsigned rd :1;
unsigned tc :1;
unsigned aa :1;
unsigned opcode :4;
unsigned qr :1;
unsigned rcode :4;
unsigned cd: 1;
unsigned ad: 1;
unsigned unused :1;
unsigned ra :1;
unsigned qdcount :16;
unsigned ancount :16;
unsigned nscount :16;
unsigned arcount :16;
unsigned id :16;
unsigned rd :1;
unsigned tc :1;
unsigned aa :1;
unsigned opcode :4;
unsigned qr :1;
unsigned rcode :4;
unsigned cd: 1;
unsigned ad: 1;
unsigned unused :1;
unsigned ra :1;
unsigned qdcount :16;
unsigned ancount :16;
unsigned nscount :16;
unsigned arcount :16;
} HEADER;
#define NOERROR 0
#define FORMERR 1
#define SERVFAIL 2
#define NXDOMAIN 3
#define NOTIMP 4
#define REFUSED 5
#define NOERROR 0
#define FORMERR 1
#define SERVFAIL 2
#define NXDOMAIN 3
#define NOTIMP 4
#define REFUSED 5
#define C_IN 1
#define C_IN 1
#define T_A 1
#define T_CNAME 5
#define T_NULL 10
#define T_MX 15
#define T_TXT 16
#define T_SRV 33
#define T_A 1
#define T_CNAME 5
#define T_NULL 10
#define T_MX 15
#define T_TXT 16
#define T_SRV 33
#endif

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

View File

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

View File

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

View File

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

View File

@ -26,13 +26,13 @@
#define DOWNCODECCHECK1_LEN 48
struct encoder {
char name[8];
int (*encode) (char *, size_t *, const void *, size_t);
int (*decode) (void *, size_t *, const char *, size_t);
int (*places_dots) (void);
int (*eats_dots) (void);
int (*blocksize_raw)(void);
int (*blocksize_encoded)(void);
char name[8];
int (*encode) (char *, size_t *, const void *, size_t);
int (*decode) (void *, size_t *, const char *, size_t);
int (*places_dots) (void);
int (*eats_dots) (void);
int (*blocksize_raw)(void);
int (*blocksize_encoded)(void);
};
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()
{
memset(fwq, 0, sizeof(struct fw_query) * FW_QUERY_CACHE_SIZE);
fwq_ix = 0;
memset(fwq, 0, sizeof(struct fw_query) * FW_QUERY_CACHE_SIZE);
fwq_ix = 0;
}
void fw_query_put(struct fw_query *fw_query)
{
memcpy(&(fwq[fwq_ix]), fw_query, sizeof(struct fw_query));
memcpy(&(fwq[fwq_ix]), fw_query, sizeof(struct fw_query));
++fwq_ix;
if (fwq_ix >= FW_QUERY_CACHE_SIZE)
fwq_ix = 0;
++fwq_ix;
if (fwq_ix >= FW_QUERY_CACHE_SIZE)
fwq_ix = 0;
}
void fw_query_get(unsigned short query_id, struct fw_query **fw_query)
{
int i;
int i;
*fw_query = NULL;
for (i = 0; i < FW_QUERY_CACHE_SIZE; i++) {
if (fwq[i].id == query_id) {
*fw_query = &(fwq[i]);
return;
}
}
*fw_query = NULL;
for (i = 0; i < FW_QUERY_CACHE_SIZE; i++) {
if (fwq[i].id == query_id) {
*fw_query = &(fwq[i]);
return;
}
}
}

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

698
src/tun.c
View File

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

View File

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

View File

@ -20,7 +20,7 @@
#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
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 */
struct tun_user {
char id;
int active;
int authenticated;
int authenticated_raw;
int disabled;
time_t last_pkt;
int seed;
in_addr_t tun_ip;
struct in_addr host;
struct query q;
struct query q_sendrealsoon;
int q_sendrealsoon_new;
struct packet inpacket;
struct packet outpacket;
int outfragresent;
struct encoder *encoder;
char downenc;
int out_acked_seqno;
int out_acked_fragment;
int fragsize;
enum connection conn;
int lazy;
unsigned char qmemping_cmc[QMEMPING_LEN * 4];
unsigned short qmemping_type[QMEMPING_LEN];
int qmemping_lastfilled;
unsigned char qmemdata_cmc[QMEMDATA_LEN * 4];
unsigned short qmemdata_type[QMEMDATA_LEN];
int qmemdata_lastfilled;
char id;
int active;
int authenticated;
int authenticated_raw;
int disabled;
time_t last_pkt;
int seed;
in_addr_t tun_ip;
struct in_addr host;
struct query q;
struct query q_sendrealsoon;
int q_sendrealsoon_new;
struct packet inpacket;
struct packet outpacket;
int outfragresent;
struct encoder *encoder;
char downenc;
int out_acked_seqno;
int out_acked_fragment;
int fragsize;
enum connection conn;
int lazy;
unsigned char qmemping_cmc[QMEMPING_LEN * 4];
unsigned short qmemping_type[QMEMPING_LEN];
int qmemping_lastfilled;
unsigned char qmemdata_cmc[QMEMDATA_LEN * 4];
unsigned short qmemdata_type[QMEMDATA_LEN];
int qmemdata_lastfilled;
#ifdef OUTPACKETQ_LEN
struct packet outpacketq[OUTPACKETQ_LEN];
int outpacketq_nexttouse;
int outpacketq_filled;
struct packet outpacketq[OUTPACKETQ_LEN];
int outpacketq_nexttouse;
int outpacketq_filled;
#endif
#ifdef DNSCACHE_LEN
struct query dnscache_q[DNSCACHE_LEN];
char dnscache_answer[DNSCACHE_LEN][4096];
int dnscache_answerlen[DNSCACHE_LEN];
int dnscache_lastfilled;
struct query dnscache_q[DNSCACHE_LEN];
char dnscache_answer[DNSCACHE_LEN][4096];
int dnscache_answerlen[DNSCACHE_LEN];
int dnscache_lastfilled;
#endif
};

View File

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

View File

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

View File

@ -29,129 +29,129 @@
static struct tuple
{
char *a;
char *b;
char *a;
char *b;
} testpairs[TUPLES] = {
{ "iodinetestingtesting", "Aw8KAw4LDgvZDgLUz2rLC2rPBMC" },
{ "abc1231", "ywjJmtiZmq" },
{
"\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"
"\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"
"\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"
"\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",
{ "iodinetestingtesting", "Aw8KAw4LDgvZDgLUz2rLC2rPBMC" },
{ "abc1231", "ywjJmtiZmq" },
{
"\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"
"\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"
"\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"
"\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",
"+9876543210-ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcbapZ"
"776543210-ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba+987654"
"3210-ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba"
},
{
"\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"
"\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"
"\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"
"\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",
"+9876543210-ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcbapZ"
"776543210-ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba+987654"
"3210-ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba"
},
{
"\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"
"\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"
"\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"
"\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",
"+9876543210-ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcbapZ"
"776543210-ZYXWVUTSRQfHKwfHGsHGFEDCBAzyxwvutsrqponmlkjihgfedcba+987654321"
"0-ZYXWVUTSRQfHKwfHGsHGFEDCBAzyxwvutsrqponmlkjihgfedcba"
},
{ "", "" }
"+9876543210-ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcbapZ"
"776543210-ZYXWVUTSRQfHKwfHGsHGFEDCBAzyxwvutsrqponmlkjihgfedcba+987654321"
"0-ZYXWVUTSRQfHKwfHGsHGFEDCBAzyxwvutsrqponmlkjihgfedcba"
},
{ "", "" }
};
START_TEST(test_base64_encode)
{
size_t len;
char buf[4096];
struct encoder *b64;
int val;
size_t len;
char buf[4096];
struct encoder *b64;
int val;
b64 = get_base64_encoder();
b64 = get_base64_encoder();
len = sizeof(buf);
val = b64->encode(buf, &len, testpairs[_i].a, strlen(testpairs[_i].a));
len = sizeof(buf);
val = b64->encode(buf, &len, testpairs[_i].a, strlen(testpairs[_i].a));
fail_unless(val == strlen(testpairs[_i].b));
fail_unless(strcmp(buf, testpairs[_i].b) == 0,
"'%s' != '%s'", buf, testpairs[_i].b);
fail_unless(val == strlen(testpairs[_i].b));
fail_unless(strcmp(buf, testpairs[_i].b) == 0,
"'%s' != '%s'", buf, testpairs[_i].b);
}
END_TEST
START_TEST(test_base64_decode)
{
size_t len;
char buf[4096];
struct encoder *b64;
int val;
size_t len;
char buf[4096];
struct encoder *b64;
int val;
b64 = get_base64_encoder();
b64 = get_base64_encoder();
len = sizeof(buf);
val = b64->decode(buf, &len, testpairs[_i].b, strlen(testpairs[_i].b));
len = sizeof(buf);
val = b64->decode(buf, &len, testpairs[_i].b, strlen(testpairs[_i].b));
fail_unless(val == strlen(testpairs[_i].a));
fail_unless(strcmp(buf, testpairs[_i].a) == 0,
"'%s' != '%s'", buf, testpairs[_i].a);
fail_unless(val == strlen(testpairs[_i].a));
fail_unless(strcmp(buf, testpairs[_i].a) == 0,
"'%s' != '%s'", buf, testpairs[_i].a);
}
END_TEST
START_TEST(test_base64_blksize)
{
size_t rawlen;
size_t enclen;
char *rawbuf;
char *encbuf;
struct encoder *b64;
int i;
int val;
size_t rawlen;
size_t enclen;
char *rawbuf;
char *encbuf;
struct encoder *b64;
int i;
int val;
b64 = get_base64_encoder();
b64 = get_base64_encoder();
rawlen = b64->blocksize_raw();
enclen = b64->blocksize_encoded();
rawlen = b64->blocksize_raw();
enclen = b64->blocksize_encoded();
rawbuf = malloc(rawlen + 16);
encbuf = malloc(enclen + 16);
rawbuf = malloc(rawlen + 16);
encbuf = malloc(enclen + 16);
for (i = 0; i < rawlen; i++) {
rawbuf[i] = 'A';
}
rawbuf[i] = 0;
for (i = 0; i < rawlen; i++) {
rawbuf[i] = 'A';
}
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(enclen == 3, "encoded %d bytes, not 3", enclen);
fail_unless(val == 4, "encoded string %s was length %d", encbuf, val);
fail_unless(rawlen == 3, "raw length was %d not 3", rawlen);
fail_unless(enclen == 3, "encoded %d bytes, not 3", enclen);
fail_unless(val == 4, "encoded string %s was length %d", encbuf, val);
memset(rawbuf, 0, rawlen + 16);
memset(rawbuf, 0, rawlen + 16);
enclen = val;
val = b64->decode(rawbuf, &rawlen, encbuf, enclen);
enclen = val;
val = b64->decode(rawbuf, &rawlen, encbuf, enclen);
fail_unless(rawlen == 3, "raw length was %d not 3", rawlen);
fail_unless(val == 3);
for (i = 0; i < rawlen; i++) {
fail_unless(rawbuf[i] == 'A');
}
fail_unless(rawlen == 3, "raw length was %d not 3", rawlen);
fail_unless(val == 3);
for (i = 0; i < rawlen; i++) {
fail_unless(rawbuf[i] == 'A');
}
}
END_TEST
TCase *
test_base64_create_tests()
{
TCase *tc;
TCase *tc;
tc = tcase_create("Base64");
tcase_add_loop_test(tc, test_base64_encode, 0, TUPLES);
tcase_add_loop_test(tc, test_base64_decode, 0, TUPLES);
tcase_add_test(tc, test_base64_blksize);
tc = tcase_create("Base64");
tcase_add_loop_test(tc, test_base64_encode, 0, TUPLES);
tcase_add_loop_test(tc, test_base64_decode, 0, TUPLES);
tcase_add_test(tc, test_base64_blksize);
return tc;
return tc;
}

View File

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

View File

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

View File

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

View File

@ -23,49 +23,49 @@
START_TEST(test_login_hash)
{
char ans[16];
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";
int len;
int seed;
char ans[16];
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";
int len;
int seed;
len = sizeof(ans);
seed = 15;
len = sizeof(ans);
seed = 15;
memset(ans, 0, sizeof(ans));
login_calculate(ans, len, pass, seed);
fail_unless(strncmp(ans, good, len) == 0, NULL);
memset(ans, 0, sizeof(ans));
login_calculate(ans, len, pass, seed);
fail_unless(strncmp(ans, good, len) == 0, NULL);
}
END_TEST
START_TEST(test_login_hash_short)
{
char ans[8];
char check[sizeof(ans)];
char pass[32] = "iodine is the shit";
int len;
int seed;
char ans[8];
char check[sizeof(ans)];
char pass[32] = "iodine is the shit";
int len;
int seed;
len = sizeof(ans);
seed = 15;
len = sizeof(ans);
seed = 15;
memset(ans, 0, sizeof(ans));
memset(check, 0, sizeof(check));
memset(ans, 0, sizeof(ans));
memset(check, 0, sizeof(check));
/* If len < 16, it should do nothing */
login_calculate(ans, len, pass, seed);
fail_if(memcmp(ans, check, sizeof(ans)));
/* If len < 16, it should do nothing */
login_calculate(ans, len, pass, seed);
fail_if(memcmp(ans, check, sizeof(ans)));
}
END_TEST
TCase *
test_login_create_tests()
{
TCase *tc;
TCase *tc;
tc = tcase_create("Login");
tcase_add_test(tc, test_login_hash);
tcase_add_test(tc, test_login_hash_short);
tc = tcase_create("Login");
tcase_add_test(tc, test_login_hash);
tcase_add_test(tc, test_login_hash_short);
return tc;
return tc;
}

View File

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

View File

@ -26,45 +26,45 @@
int
main()
{
SRunner *runner;
Suite *iodine;
TCase *test;
int failed;
SRunner *runner;
Suite *iodine;
TCase *test;
int failed;
iodine = suite_create("iodine");
iodine = suite_create("iodine");
test = test_base32_create_tests();
suite_add_tcase(iodine, test);
test = test_base32_create_tests();
suite_add_tcase(iodine, test);
test = test_base64_create_tests();
suite_add_tcase(iodine, test);
test = test_base64_create_tests();
suite_add_tcase(iodine, test);
test = test_common_create_tests();
suite_add_tcase(iodine, test);
test = test_common_create_tests();
suite_add_tcase(iodine, test);
test = test_dns_create_tests();
suite_add_tcase(iodine, test);
test = test_dns_create_tests();
suite_add_tcase(iodine, test);
test = test_encoding_create_tests();
suite_add_tcase(iodine, test);
test = test_encoding_create_tests();
suite_add_tcase(iodine, test);
test = test_read_create_tests();
suite_add_tcase(iodine, test);
test = test_read_create_tests();
suite_add_tcase(iodine, test);
test = test_login_create_tests();
suite_add_tcase(iodine, test);
test = test_login_create_tests();
suite_add_tcase(iodine, test);
test = test_user_create_tests();
suite_add_tcase(iodine, test);
test = test_user_create_tests();
suite_add_tcase(iodine, test);
test = test_fw_query_create_tests();
suite_add_tcase(iodine, test);
test = test_fw_query_create_tests();
suite_add_tcase(iodine, test);
runner = srunner_create(iodine);
srunner_run_all(runner, CK_NORMAL);
failed = srunner_ntests_failed(runner);
runner = srunner_create(iodine);
srunner_run_all(runner, CK_NORMAL);
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 *, ...);
#if (CHECK_MAJOR_VERSION == 0 && \
((CHECK_MINOR_VERSION == 9 && CHECK_MICRO_VERSION < 2) || \
(CHECK_MINOR_VERSION < 9)))
((CHECK_MINOR_VERSION == 9 && CHECK_MICRO_VERSION < 2) || \
(CHECK_MINOR_VERSION < 9)))
#define tcase_set_timeout(...)
#endif

View File

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