mirror of
https://github.com/yarrick/iodine.git
synced 2025-01-12 19:09:30 +00:00
Tabz -> Spaces + whitespace
This commit is contained in:
parent
9a45c4aa66
commit
515bfb00a6
|
@ -2,14 +2,14 @@
|
||||||
policy_module(iodine, 1.1)
|
policy_module(iodine, 1.1)
|
||||||
|
|
||||||
require {
|
require {
|
||||||
type init_t;
|
type init_t;
|
||||||
type initrc_t;
|
type initrc_t;
|
||||||
type unconfined_t;
|
type unconfined_t;
|
||||||
type unlabeled_t;
|
type unlabeled_t;
|
||||||
class udp_socket { read write };
|
class udp_socket { read write };
|
||||||
class rawip_socket { write read };
|
class rawip_socket { write read };
|
||||||
class association recvfrom;
|
class association recvfrom;
|
||||||
class unix_dgram_socket { create connect };
|
class unix_dgram_socket { create connect };
|
||||||
}
|
}
|
||||||
|
|
||||||
type iodine_t;
|
type iodine_t;
|
||||||
|
|
|
@ -5,42 +5,42 @@ CMC = 2 byte Cache Miss Counter, increased every time it is used
|
||||||
|
|
||||||
Version:
|
Version:
|
||||||
Client sends:
|
Client sends:
|
||||||
First byte v or V
|
First byte v or V
|
||||||
Rest encoded with base32:
|
Rest encoded with base32:
|
||||||
4 bytes big endian protocol version
|
4 bytes big endian protocol version
|
||||||
CMC
|
CMC
|
||||||
Server replies:
|
Server replies:
|
||||||
4 chars:
|
4 chars:
|
||||||
VACK (version ok), followed by login challenge
|
VACK (version ok), followed by login challenge
|
||||||
VNAK (version differs), followed by server protocol version
|
VNAK (version differs), followed by server protocol version
|
||||||
VFUL (server has no free slots), followed by max users
|
VFUL (server has no free slots), followed by max users
|
||||||
4 byte value: means login challenge/server protocol version/max users
|
4 byte value: means login challenge/server protocol version/max users
|
||||||
1 byte userid of the new user, or any byte if not VACK
|
1 byte userid of the new user, or any byte if not VACK
|
||||||
|
|
||||||
Login:
|
Login:
|
||||||
Client sends:
|
Client sends:
|
||||||
First byte l or L
|
First byte l or L
|
||||||
Rest encoded with base32:
|
Rest encoded with base32:
|
||||||
1 byte userid
|
1 byte userid
|
||||||
16 bytes MD5 hash of: (first 32 bytes of password) xor (8 repetitions of login challenge)
|
16 bytes MD5 hash of: (first 32 bytes of password) xor (8 repetitions of login challenge)
|
||||||
CMC
|
CMC
|
||||||
Server replies:
|
Server replies:
|
||||||
LNAK means not accepted
|
LNAK means not accepted
|
||||||
x.x.x.x-y.y.y.y-mtu means accepted (server ip, client ip, mtu)
|
x.x.x.x-y.y.y.y-mtu means accepted (server ip, client ip, mtu)
|
||||||
|
|
||||||
Case check:
|
Case check:
|
||||||
Client sends:
|
Client sends:
|
||||||
First byte z or Z
|
First byte z or Z
|
||||||
Lots of data that should not be decoded
|
Lots of data that should not be decoded
|
||||||
Server replies:
|
Server replies:
|
||||||
The requested domain copied raw
|
The requested domain copied raw
|
||||||
|
|
||||||
Data:
|
Data:
|
||||||
Data header:
|
Data header:
|
||||||
321 0
|
321 0
|
||||||
+---+-+
|
+---+-+
|
||||||
|UUU|L|
|
|UUU|L|
|
||||||
+---+-+
|
+---+-+
|
||||||
|
|
||||||
UUU = Userid
|
UUU = Userid
|
||||||
L = Last fragment in packet flag
|
L = Last fragment in packet flag
|
||||||
|
@ -50,10 +50,10 @@ Followed by data encoded with Base32.
|
||||||
|
|
||||||
Ping:
|
Ping:
|
||||||
Client sends:
|
Client sends:
|
||||||
First byte p or P
|
First byte p or P
|
||||||
Rest encoded with Base32:
|
Rest encoded with Base32:
|
||||||
1 byte userid
|
1 byte userid
|
||||||
CMC
|
CMC
|
||||||
|
|
||||||
The server response to Ping and Data packets is a DNS NULL type response:
|
The server response to Ping and Data packets is a DNS NULL type response:
|
||||||
If server has nothing to send, data length is 0 bytes.
|
If server has nothing to send, data length is 0 bytes.
|
||||||
|
|
|
@ -5,82 +5,82 @@ CMC = 2 byte Cache Miss Counter, increased every time it is used
|
||||||
|
|
||||||
Version:
|
Version:
|
||||||
Client sends:
|
Client sends:
|
||||||
First byte v or V
|
First byte v or V
|
||||||
Rest encoded with base32:
|
Rest encoded with base32:
|
||||||
4 bytes big endian protocol version
|
4 bytes big endian protocol version
|
||||||
CMC
|
CMC
|
||||||
Server replies:
|
Server replies:
|
||||||
4 chars:
|
4 chars:
|
||||||
VACK (version ok), followed by login challenge
|
VACK (version ok), followed by login challenge
|
||||||
VNAK (version differs), followed by server protocol version
|
VNAK (version differs), followed by server protocol version
|
||||||
VFUL (server has no free slots), followed by max users
|
VFUL (server has no free slots), followed by max users
|
||||||
4 byte value: means login challenge/server protocol version/max users
|
4 byte value: means login challenge/server protocol version/max users
|
||||||
1 byte userid of the new user, or any byte if not VACK
|
1 byte userid of the new user, or any byte if not VACK
|
||||||
|
|
||||||
Login:
|
Login:
|
||||||
Client sends:
|
Client sends:
|
||||||
First byte l or L
|
First byte l or L
|
||||||
Rest encoded with base32:
|
Rest encoded with base32:
|
||||||
1 byte userid
|
1 byte userid
|
||||||
16 bytes MD5 hash of: (first 32 bytes of password) xor (8 repetitions of login challenge)
|
16 bytes MD5 hash of: (first 32 bytes of password) xor (8 repetitions of login challenge)
|
||||||
CMC
|
CMC
|
||||||
Server replies:
|
Server replies:
|
||||||
LNAK means not accepted
|
LNAK means not accepted
|
||||||
x.x.x.x-y.y.y.y-mtu-netmask means accepted (server ip, client ip, mtu, netmask bits)
|
x.x.x.x-y.y.y.y-mtu-netmask means accepted (server ip, client ip, mtu, netmask bits)
|
||||||
|
|
||||||
Case check:
|
Case check:
|
||||||
Client sends:
|
Client sends:
|
||||||
First byte z or Z
|
First byte z or Z
|
||||||
Lots of data that should not be decoded
|
Lots of data that should not be decoded
|
||||||
Server replies:
|
Server replies:
|
||||||
The requested domain copied raw
|
The requested domain copied raw
|
||||||
|
|
||||||
Switch codec:
|
Switch codec:
|
||||||
Client sends:
|
Client sends:
|
||||||
First byte s or S
|
First byte s or S
|
||||||
5 bits coded as Base32 char, meaning userid
|
5 bits coded as Base32 char, meaning userid
|
||||||
5 bits coded as Base32 char, with value 5 or 6, representing number of raw
|
5 bits coded as Base32 char, with value 5 or 6, representing number of raw
|
||||||
bits per encoded byte
|
bits per encoded byte
|
||||||
Server sends:
|
Server sends:
|
||||||
Name of codec if accepted. After this all upstream data packets must
|
Name of codec if accepted. After this all upstream data packets must
|
||||||
be encoded with the new codec.
|
be encoded with the new codec.
|
||||||
BADCODEC if not accepted. Client must then revert to Base32
|
BADCODEC if not accepted. Client must then revert to Base32
|
||||||
|
|
||||||
Probe downstream fragment size:
|
Probe downstream fragment size:
|
||||||
Client sends:
|
Client sends:
|
||||||
First byte r or R
|
First byte r or R
|
||||||
15 bits coded as 3 Base32 chars: UUUUF FFFFF FFFFF
|
15 bits coded as 3 Base32 chars: UUUUF FFFFF FFFFF
|
||||||
meaning 4 bits userid, 11 bits fragment size
|
meaning 4 bits userid, 11 bits fragment size
|
||||||
Then follows a long random query which contents does not matter
|
Then follows a long random query which contents does not matter
|
||||||
Server sends:
|
Server sends:
|
||||||
Requested number of bytes as a response. The first two bytes contains
|
Requested number of bytes as a response. The first two bytes contains
|
||||||
the requested length. Rest of message can be any data.
|
the requested length. Rest of message can be any data.
|
||||||
BADFRAG if requested length not accepted.
|
BADFRAG if requested length not accepted.
|
||||||
|
|
||||||
Set downstream fragment size:
|
Set downstream fragment size:
|
||||||
Client sends:
|
Client sends:
|
||||||
First byte n or N
|
First byte n or N
|
||||||
Rest encoded with base32:
|
Rest encoded with base32:
|
||||||
1 byte userid
|
1 byte userid
|
||||||
2 bytes new downstream fragment size
|
2 bytes new downstream fragment size
|
||||||
CMC
|
CMC
|
||||||
Server sends:
|
Server sends:
|
||||||
2 bytes new downstream fragment size. After this all downstream
|
2 bytes new downstream fragment size. After this all downstream
|
||||||
payloads will be max (fragsize + 2) bytes long.
|
payloads will be max (fragsize + 2) bytes long.
|
||||||
BADFRAG if not accepted.
|
BADFRAG if not accepted.
|
||||||
|
|
||||||
Data:
|
Data:
|
||||||
Upstream data header:
|
Upstream data header:
|
||||||
3210 432 10 43 210 4321 0
|
3210 432 10 43 210 4321 0
|
||||||
+----+---+--+--+---+----+-+
|
+----+---+--+--+---+----+-+
|
||||||
|UUUU|SSS|FF|FF|DDD|GGGG|L|
|
|UUUU|SSS|FF|FF|DDD|GGGG|L|
|
||||||
+----+---+--+--+---+----+-+
|
+----+---+--+--+---+----+-+
|
||||||
|
|
||||||
Downstream data header:
|
Downstream data header:
|
||||||
7 654 3210 765 4321 0
|
7 654 3210 765 4321 0
|
||||||
+-+---+----+---+----+-+
|
+-+---+----+---+----+-+
|
||||||
|C|SSS|FFFF|DDD|GGGG|L|
|
|C|SSS|FFFF|DDD|GGGG|L|
|
||||||
+-+---+----+---+----+-+
|
+-+---+----+---+----+-+
|
||||||
|
|
||||||
UUUU = Userid
|
UUUU = Userid
|
||||||
L = Last fragment in packet flag
|
L = Last fragment in packet flag
|
||||||
|
@ -98,13 +98,13 @@ compressed.
|
||||||
|
|
||||||
Ping:
|
Ping:
|
||||||
Client sends:
|
Client sends:
|
||||||
First byte p or P
|
First byte p or P
|
||||||
Rest encoded with Base32:
|
Rest encoded with Base32:
|
||||||
1 byte with 4 bits userid
|
1 byte with 4 bits userid
|
||||||
1 byte with:
|
1 byte with:
|
||||||
3 bits downstream seqno
|
3 bits downstream seqno
|
||||||
4 bits downstream fragment
|
4 bits downstream fragment
|
||||||
CMC
|
CMC
|
||||||
|
|
||||||
The server response to Ping and Data packets is a DNS NULL type response:
|
The server response to Ping and Data packets is a DNS NULL type response:
|
||||||
If server has nothing to send, data length is 0 bytes.
|
If server has nothing to send, data length is 0 bytes.
|
||||||
|
|
|
@ -8,170 +8,170 @@ Note: work in progress!!
|
||||||
======================================================
|
======================================================
|
||||||
|
|
||||||
Quick alphabetical index / register:
|
Quick alphabetical index / register:
|
||||||
0-9 Data packet
|
0-9 Data packet
|
||||||
A-F Data packet
|
A-F Data packet
|
||||||
I IP address
|
I IP address
|
||||||
L Login
|
L Login
|
||||||
N Downstream fragsize (NS.topdomain A-type reply)
|
N Downstream fragsize (NS.topdomain A-type reply)
|
||||||
O Options
|
O Options
|
||||||
P Ping
|
P Ping
|
||||||
R Downstream fragsize probe
|
R Downstream fragsize probe
|
||||||
S Switch upstream codec
|
S Switch upstream codec
|
||||||
V Version
|
V Version
|
||||||
W (WWW.topdomain A-type reply)
|
W (WWW.topdomain A-type reply)
|
||||||
Y Downstream codec check
|
Y Downstream codec check
|
||||||
Z Upstream codec check
|
Z Upstream codec check
|
||||||
|
|
||||||
|
|
||||||
CMC = 2 byte Cache Miss Counter, increased every time it is used
|
CMC = 2 byte Cache Miss Counter, increased every time it is used
|
||||||
|
|
||||||
Version:
|
Version:
|
||||||
Client sends:
|
Client sends:
|
||||||
First byte v or V
|
First byte v or V
|
||||||
Rest encoded with base32:
|
Rest encoded with base32:
|
||||||
4 bytes big endian protocol version
|
4 bytes big endian protocol version
|
||||||
CMC
|
CMC
|
||||||
Server replies:
|
Server replies:
|
||||||
4 chars:
|
4 chars:
|
||||||
VACK (version ok), followed by login challenge
|
VACK (version ok), followed by login challenge
|
||||||
VNAK (version differs), followed by server protocol version
|
VNAK (version differs), followed by server protocol version
|
||||||
VFUL (server has no free slots), followed by max users
|
VFUL (server has no free slots), followed by max users
|
||||||
4 byte value: means login challenge/server protocol version/max users
|
4 byte value: means login challenge/server protocol version/max users
|
||||||
1 byte userid of the new user, or any byte if not VACK
|
1 byte userid of the new user, or any byte if not VACK
|
||||||
|
|
||||||
Login:
|
Login:
|
||||||
Client sends:
|
Client sends:
|
||||||
First byte l or L
|
First byte l or L
|
||||||
Rest encoded with base32:
|
Rest encoded with base32:
|
||||||
1 byte userid
|
1 byte userid
|
||||||
16 bytes MD5 hash of: (first 32 bytes of password) xor (8 repetitions of login challenge)
|
16 bytes MD5 hash of: (first 32 bytes of password) xor (8 repetitions of login challenge)
|
||||||
CMC
|
CMC
|
||||||
Server replies:
|
Server replies:
|
||||||
LNAK means not accepted
|
LNAK means not accepted
|
||||||
x.x.x.x-y.y.y.y-mtu-netmask means accepted (server ip, client ip, mtu, netmask bits)
|
x.x.x.x-y.y.y.y-mtu-netmask means accepted (server ip, client ip, mtu, netmask bits)
|
||||||
|
|
||||||
IP Request:
|
IP Request:
|
||||||
Client sends:
|
Client sends:
|
||||||
First byte i or I
|
First byte i or I
|
||||||
5 bits coded as Base32 char, meaning userid
|
5 bits coded as Base32 char, meaning userid
|
||||||
CMC as 3 Base32 chars
|
CMC as 3 Base32 chars
|
||||||
Server replies
|
Server replies
|
||||||
BADIP if bad userid, or
|
BADIP if bad userid, or
|
||||||
I and then 4 bytes network order external IP address of iodined server
|
I and then 4 bytes network order external IP address of iodined server
|
||||||
|
|
||||||
Upstream codec check / bounce:
|
Upstream codec check / bounce:
|
||||||
Client sends:
|
Client sends:
|
||||||
First byte z or Z
|
First byte z or Z
|
||||||
Lots of data that should not be decoded
|
Lots of data that should not be decoded
|
||||||
Server replies:
|
Server replies:
|
||||||
The requested domain copied raw, in the lowest-grade downstream codec
|
The requested domain copied raw, in the lowest-grade downstream codec
|
||||||
available for the request type.
|
available for the request type.
|
||||||
|
|
||||||
Downstream codec check:
|
Downstream codec check:
|
||||||
Client sends:
|
Client sends:
|
||||||
First byte y or Y
|
First byte y or Y
|
||||||
1 char, meaning downstream codec to use
|
1 char, meaning downstream codec to use
|
||||||
5 bits coded as Base32 char, meaning check variant
|
5 bits coded as Base32 char, meaning check variant
|
||||||
CMC as 3 Base32 chars
|
CMC as 3 Base32 chars
|
||||||
Possibly extra data, depending on check variant
|
Possibly extra data, depending on check variant
|
||||||
Server sends:
|
Server sends:
|
||||||
Data encoded with requested downstream codec; data content depending
|
Data encoded with requested downstream codec; data content depending
|
||||||
on check variant number.
|
on check variant number.
|
||||||
BADCODEC if requested downstream codec not available.
|
BADCODEC if requested downstream codec not available.
|
||||||
BADLEN if check variant is not available, or problem with extra data.
|
BADLEN if check variant is not available, or problem with extra data.
|
||||||
|
|
||||||
Downstream codec chars are same as in 'O' Option request, below.
|
Downstream codec chars are same as in 'O' Option request, below.
|
||||||
|
|
||||||
Check variants:
|
Check variants:
|
||||||
1: Send encoded DOWNCODECCHECK1 string as defined in encoding.h
|
1: Send encoded DOWNCODECCHECK1 string as defined in encoding.h
|
||||||
|
|
||||||
(Other variants reserved; possibly variant that sends a decoded-encoded
|
(Other variants reserved; possibly variant that sends a decoded-encoded
|
||||||
copy of Base32-encoded extra data in the request)
|
copy of Base32-encoded extra data in the request)
|
||||||
|
|
||||||
Switch codec:
|
Switch codec:
|
||||||
Client sends:
|
Client sends:
|
||||||
First byte s or S
|
First byte s or S
|
||||||
5 bits coded as Base32 char, meaning userid
|
5 bits coded as Base32 char, meaning userid
|
||||||
5 bits coded as Base32 char, representing number of raw bits per
|
5 bits coded as Base32 char, representing number of raw bits per
|
||||||
encoded byte:
|
encoded byte:
|
||||||
5: Base32 (a-z0-5)
|
5: Base32 (a-z0-5)
|
||||||
6: Base64 (a-zA-Z0-9+-)
|
6: Base64 (a-zA-Z0-9+-)
|
||||||
26: Base64u (a-zA-Z0-9_-)
|
26: Base64u (a-zA-Z0-9_-)
|
||||||
7: Base128 (a-zA-Z0-9\274-\375)
|
7: Base128 (a-zA-Z0-9\274-\375)
|
||||||
CMC as 3 Base32 chars
|
CMC as 3 Base32 chars
|
||||||
Server sends:
|
Server sends:
|
||||||
Name of codec if accepted. After this all upstream data packets must
|
Name of codec if accepted. After this all upstream data packets must
|
||||||
be encoded with the new codec.
|
be encoded with the new codec.
|
||||||
BADCODEC if not accepted. Client must then revert to previous codec
|
BADCODEC if not accepted. Client must then revert to previous codec
|
||||||
BADLEN if length of query is too short
|
BADLEN if length of query is too short
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
Client sends:
|
Client sends:
|
||||||
First byte o or O
|
First byte o or O
|
||||||
5 bits coded as Base32 char, meaning userid
|
5 bits coded as Base32 char, meaning userid
|
||||||
1 char, meaning option
|
1 char, meaning option
|
||||||
CMC as 3 Base32 chars
|
CMC as 3 Base32 chars
|
||||||
Server sends:
|
Server sends:
|
||||||
Full name of option if accepted. After this, option immediately takes
|
Full name of option if accepted. After this, option immediately takes
|
||||||
effect in server.
|
effect in server.
|
||||||
BADCODEC if not accepted. Previous situation remains.
|
BADCODEC if not accepted. Previous situation remains.
|
||||||
All options affect only the requesting client.
|
All options affect only the requesting client.
|
||||||
|
|
||||||
Option chars:
|
Option chars:
|
||||||
t or T: Downstream encoding Base32, for TXT/CNAME/A/MX (default)
|
t or T: Downstream encoding Base32, for TXT/CNAME/A/MX (default)
|
||||||
s or S: Downstream encoding Base64, for TXT/CNAME/A/MX
|
s or S: Downstream encoding Base64, for TXT/CNAME/A/MX
|
||||||
u or U: Downstream encoding Base64u, for TXT/CNAME/A/MX
|
u or U: Downstream encoding Base64u, for TXT/CNAME/A/MX
|
||||||
v or V: Downstream encoding Base128, for TXT/CNAME/A/MX
|
v or V: Downstream encoding Base128, for TXT/CNAME/A/MX
|
||||||
r or R: Downstream encoding Raw, for PRIVATE/TXT/NULL (default for
|
r or R: Downstream encoding Raw, for PRIVATE/TXT/NULL (default for
|
||||||
PRIVATE and NULL)
|
PRIVATE and NULL)
|
||||||
If codec unsupported for request type, server will use Base32; note
|
If codec unsupported for request type, server will use Base32; note
|
||||||
that server will answer any mix of request types that a client sends.
|
that server will answer any mix of request types that a client sends.
|
||||||
Server may disregard this option; client must always use the downstream
|
Server may disregard this option; client must always use the downstream
|
||||||
encoding type indicated in every downstream DNS packet.
|
encoding type indicated in every downstream DNS packet.
|
||||||
|
|
||||||
l or L: Lazy mode, server will keep one request unanswered until the
|
l or L: Lazy mode, server will keep one request unanswered until the
|
||||||
next one comes in. Applies only to data transfer; handshake is always
|
next one comes in. Applies only to data transfer; handshake is always
|
||||||
answered immediately.
|
answered immediately.
|
||||||
i or I: Immediate (non-lazy) mode, server will answer all requests
|
i or I: Immediate (non-lazy) mode, server will answer all requests
|
||||||
(nearly) immediately.
|
(nearly) immediately.
|
||||||
|
|
||||||
Probe downstream fragment size:
|
Probe downstream fragment size:
|
||||||
Client sends:
|
Client sends:
|
||||||
First byte r or R
|
First byte r or R
|
||||||
15 bits coded as 3 Base32 chars: UUUUF FFFFF FFFFF
|
15 bits coded as 3 Base32 chars: UUUUF FFFFF FFFFF
|
||||||
meaning 4 bits userid, 11 bits fragment size
|
meaning 4 bits userid, 11 bits fragment size
|
||||||
Then follows a long random query which contents does not matter
|
Then follows a long random query which contents does not matter
|
||||||
Server sends:
|
Server sends:
|
||||||
Requested number of bytes as a response. The first two bytes contain
|
Requested number of bytes as a response. The first two bytes contain
|
||||||
the requested length. The third byte is 107 (0x6B). The fourth byte
|
the requested length. The third byte is 107 (0x6B). The fourth byte
|
||||||
is a random value, and each following byte is incremented with 107.
|
is a random value, and each following byte is incremented with 107.
|
||||||
This is checked by the client to determine corruption.
|
This is checked by the client to determine corruption.
|
||||||
BADFRAG if requested length not accepted.
|
BADFRAG if requested length not accepted.
|
||||||
|
|
||||||
Set downstream fragment size:
|
Set downstream fragment size:
|
||||||
Client sends:
|
Client sends:
|
||||||
First byte n or N
|
First byte n or N
|
||||||
Rest encoded with base32:
|
Rest encoded with base32:
|
||||||
1 byte userid
|
1 byte userid
|
||||||
2 bytes new downstream fragment size
|
2 bytes new downstream fragment size
|
||||||
CMC
|
CMC
|
||||||
Server sends:
|
Server sends:
|
||||||
2 bytes new downstream fragment size. After this all downstream
|
2 bytes new downstream fragment size. After this all downstream
|
||||||
payloads will be max (fragsize + 2) bytes long.
|
payloads will be max (fragsize + 2) bytes long.
|
||||||
BADFRAG if not accepted.
|
BADFRAG if not accepted.
|
||||||
|
|
||||||
Data:
|
Data:
|
||||||
Upstream data header:
|
Upstream data header:
|
||||||
3210 432 10 43 210 4321 0 43210
|
3210 432 10 43 210 4321 0 43210
|
||||||
+----+---+--+--+---+----+-+-----+
|
+----+---+--+--+---+----+-+-----+
|
||||||
|UUUU|SSS|FF|FF|DDD|GGGG|L|UDCMC|
|
|UUUU|SSS|FF|FF|DDD|GGGG|L|UDCMC|
|
||||||
+----+---+--+--+---+----+-+-----+
|
+----+---+--+--+---+----+-+-----+
|
||||||
|
|
||||||
Downstream data header:
|
Downstream data header:
|
||||||
7 654 3210 765 4321 0
|
7 654 3210 765 4321 0
|
||||||
+-+---+----+---+----+-+
|
+-+---+----+---+----+-+
|
||||||
|C|SSS|FFFF|DDD|GGGG|L|
|
|C|SSS|FFFF|DDD|GGGG|L|
|
||||||
+-+---+----+---+----+-+
|
+-+---+----+---+----+-+
|
||||||
|
|
||||||
UUUU = Userid
|
UUUU = Userid
|
||||||
L = Last fragment in packet flag
|
L = Last fragment in packet flag
|
||||||
|
@ -193,18 +193,18 @@ In NULL and PRIVATE responses, downstream data is always raw. In all other
|
||||||
response types, downstream data is encoded (see Options above).
|
response types, downstream data is encoded (see Options above).
|
||||||
Encoding type is indicated by 1 prefix char:
|
Encoding type is indicated by 1 prefix char:
|
||||||
TXT:
|
TXT:
|
||||||
End result is always DNS-chopped (series of len-prefixed strings
|
End result is always DNS-chopped (series of len-prefixed strings
|
||||||
<=255 bytes)
|
<=255 bytes)
|
||||||
t or T: Base32 encoded before chop, decoded after un-chop
|
t or T: Base32 encoded before chop, decoded after un-chop
|
||||||
s or S: Base64 encoded before chop, decoded after un-chop
|
s or S: Base64 encoded before chop, decoded after un-chop
|
||||||
u or U: Base64u encoded before chop, decoded after un-chop
|
u or U: Base64u encoded before chop, decoded after un-chop
|
||||||
v or V: Base128 encoded before chop, decoded after un-chop
|
v or V: Base128 encoded before chop, decoded after un-chop
|
||||||
r or R: Raw no encoding, only DNS-chop
|
r or R: Raw no encoding, only DNS-chop
|
||||||
SRV/MX/CNAME/A:
|
SRV/MX/CNAME/A:
|
||||||
h or H: Hostname encoded with Base32
|
h or H: Hostname encoded with Base32
|
||||||
i or I: Hostname encoded with Base64
|
i or I: Hostname encoded with Base64
|
||||||
j or J: Hostname encoded with Base64u
|
j or J: Hostname encoded with Base64u
|
||||||
k or K: Hostname encoded with Base128
|
k or K: Hostname encoded with Base128
|
||||||
SRV and MX may reply with multiple hostnames, each encoded separately. Each
|
SRV and MX may reply with multiple hostnames, each encoded separately. Each
|
||||||
has a 10-multiple priority, and encoding/decoding is done in strictly
|
has a 10-multiple priority, and encoding/decoding is done in strictly
|
||||||
increasing priority sequence 10, 20, 30, etc. without gaps. Note that some DNS
|
increasing priority sequence 10, 20, 30, etc. without gaps. Note that some DNS
|
||||||
|
@ -212,13 +212,13 @@ relays will shuffle the answer records in the response.
|
||||||
|
|
||||||
Ping:
|
Ping:
|
||||||
Client sends:
|
Client sends:
|
||||||
First byte p or P
|
First byte p or P
|
||||||
Rest encoded with Base32:
|
Rest encoded with Base32:
|
||||||
1 byte with 4 bits userid
|
1 byte with 4 bits userid
|
||||||
1 byte with:
|
1 byte with:
|
||||||
3 bits downstream seqno
|
3 bits downstream seqno
|
||||||
4 bits downstream fragment
|
4 bits downstream fragment
|
||||||
CMC
|
CMC
|
||||||
|
|
||||||
The server response to Ping and Data packets is a DNS NULL/TXT/.. type response,
|
The server response to Ping and Data packets is a DNS NULL/TXT/.. type response,
|
||||||
always starting with the 2 bytes downstream data header as shown above.
|
always starting with the 2 bytes downstream data header as shown above.
|
||||||
|
@ -268,10 +268,10 @@ All Raw UDP protcol messages start with a 3 byte header: 0x10d19e
|
||||||
This is not the start of a valid DNS message so it is easy to identify.
|
This is not the start of a valid DNS message so it is easy to identify.
|
||||||
The fourth byte contains the command and the user id.
|
The fourth byte contains the command and the user id.
|
||||||
|
|
||||||
7654 3210
|
7654 3210
|
||||||
+----+----+
|
+----+----+
|
||||||
|CCCC|UUUU|
|
|CCCC|UUUU|
|
||||||
+----+----+
|
+----+----+
|
||||||
|
|
||||||
Login message (command = 1):
|
Login message (command = 1):
|
||||||
The header is followed by a MD5 hash with the same password as in the DNS
|
The header is followed by a MD5 hash with the same password as in the DNS
|
||||||
|
|
|
@ -18,37 +18,37 @@
|
||||||
#define __FIX_ANDROID_H__
|
#define __FIX_ANDROID_H__
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned id :16;
|
unsigned id :16;
|
||||||
unsigned rd :1;
|
unsigned rd :1;
|
||||||
unsigned tc :1;
|
unsigned tc :1;
|
||||||
unsigned aa :1;
|
unsigned aa :1;
|
||||||
unsigned opcode :4;
|
unsigned opcode :4;
|
||||||
unsigned qr :1;
|
unsigned qr :1;
|
||||||
unsigned rcode :4;
|
unsigned rcode :4;
|
||||||
unsigned cd: 1;
|
unsigned cd: 1;
|
||||||
unsigned ad: 1;
|
unsigned ad: 1;
|
||||||
unsigned unused :1;
|
unsigned unused :1;
|
||||||
unsigned ra :1;
|
unsigned ra :1;
|
||||||
unsigned qdcount :16;
|
unsigned qdcount :16;
|
||||||
unsigned ancount :16;
|
unsigned ancount :16;
|
||||||
unsigned nscount :16;
|
unsigned nscount :16;
|
||||||
unsigned arcount :16;
|
unsigned arcount :16;
|
||||||
} HEADER;
|
} HEADER;
|
||||||
|
|
||||||
#define NOERROR 0
|
#define NOERROR 0
|
||||||
#define FORMERR 1
|
#define FORMERR 1
|
||||||
#define SERVFAIL 2
|
#define SERVFAIL 2
|
||||||
#define NXDOMAIN 3
|
#define NXDOMAIN 3
|
||||||
#define NOTIMP 4
|
#define NOTIMP 4
|
||||||
#define REFUSED 5
|
#define REFUSED 5
|
||||||
|
|
||||||
#define C_IN 1
|
#define C_IN 1
|
||||||
|
|
||||||
#define T_A 1
|
#define T_A 1
|
||||||
#define T_CNAME 5
|
#define T_CNAME 5
|
||||||
#define T_NULL 10
|
#define T_NULL 10
|
||||||
#define T_MX 15
|
#define T_MX 15
|
||||||
#define T_TXT 16
|
#define T_TXT 16
|
||||||
#define T_SRV 33
|
#define T_SRV 33
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
3270
src/client.c
3270
src/client.c
File diff suppressed because it is too large
Load diff
470
src/common.c
470
src/common.c
|
@ -60,44 +60,44 @@ const unsigned char raw_header[RAW_HDR_LEN] = { 0x10, 0xd1, 0x9e, 0x00 };
|
||||||
#if !defined(ANDROID) && !defined(WINDOWS32) && !(defined(BSD) && (BSD >= 199306)) && !defined(__GLIBC__)
|
#if !defined(ANDROID) && !defined(WINDOWS32) && !(defined(BSD) && (BSD >= 199306)) && !defined(__GLIBC__)
|
||||||
static int daemon(int nochdir, int noclose)
|
static int daemon(int nochdir, int noclose)
|
||||||
{
|
{
|
||||||
int fd, i;
|
int fd, i;
|
||||||
|
|
||||||
switch (fork()) {
|
switch (fork()) {
|
||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
case -1:
|
case -1:
|
||||||
return -1;
|
return -1;
|
||||||
default:
|
default:
|
||||||
_exit(0);
|
_exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!nochdir) {
|
if (!nochdir) {
|
||||||
chdir("/");
|
chdir("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setsid() < 0) {
|
if (setsid() < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!noclose) {
|
if (!noclose) {
|
||||||
if ((fd = open("/dev/null", O_RDWR)) >= 0) {
|
if ((fd = open("/dev/null", O_RDWR)) >= 0) {
|
||||||
for (i = 0; i < 3; i++) {
|
for (i = 0; i < 3; i++) {
|
||||||
dup2(fd, i);
|
dup2(fd, i);
|
||||||
}
|
}
|
||||||
if (fd > 2) {
|
if (fd > 2) {
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__BEOS__) && !defined(__HAIKU__)
|
#if defined(__BEOS__) && !defined(__HAIKU__)
|
||||||
int setgroups(int count, int *groups)
|
int setgroups(int count, int *groups)
|
||||||
{
|
{
|
||||||
/* errno = ENOSYS; */
|
/* errno = ENOSYS; */
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -106,138 +106,138 @@ void
|
||||||
check_superuser(void (*usage_fn)(void))
|
check_superuser(void (*usage_fn)(void))
|
||||||
{
|
{
|
||||||
#ifndef WINDOWS32
|
#ifndef WINDOWS32
|
||||||
if (geteuid() != 0) {
|
if (geteuid() != 0) {
|
||||||
warnx("Run as root and you'll be happy.\n");
|
warnx("Run as root and you'll be happy.\n");
|
||||||
usage_fn();
|
usage_fn();
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
format_addr(struct sockaddr_storage *sockaddr, int sockaddr_len)
|
format_addr(struct sockaddr_storage *sockaddr, int sockaddr_len)
|
||||||
{
|
{
|
||||||
static char dst[INET6_ADDRSTRLEN + 1];
|
static char dst[INET6_ADDRSTRLEN + 1];
|
||||||
|
|
||||||
memset(dst, 0, sizeof(dst));
|
memset(dst, 0, sizeof(dst));
|
||||||
if (sockaddr->ss_family == AF_INET && sockaddr_len >= sizeof(struct sockaddr_in)) {
|
if (sockaddr->ss_family == AF_INET && sockaddr_len >= sizeof(struct sockaddr_in)) {
|
||||||
getnameinfo((struct sockaddr *)sockaddr, sockaddr_len, dst, sizeof(dst) - 1, NULL, 0, NI_NUMERICHOST);
|
getnameinfo((struct sockaddr *)sockaddr, sockaddr_len, dst, sizeof(dst) - 1, NULL, 0, NI_NUMERICHOST);
|
||||||
} else if (sockaddr->ss_family == AF_INET6 && sockaddr_len >= sizeof(struct sockaddr_in6)) {
|
} else if (sockaddr->ss_family == AF_INET6 && sockaddr_len >= sizeof(struct sockaddr_in6)) {
|
||||||
struct sockaddr_in6 *addr = (struct sockaddr_in6 *) sockaddr;
|
struct sockaddr_in6 *addr = (struct sockaddr_in6 *) sockaddr;
|
||||||
if (IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr)) {
|
if (IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr)) {
|
||||||
struct in_addr ia;
|
struct in_addr ia;
|
||||||
/* Get mapped v4 addr from last 32bit field */
|
/* Get mapped v4 addr from last 32bit field */
|
||||||
memcpy(&ia.s_addr, &addr->sin6_addr.s6_addr[12], sizeof(ia));
|
memcpy(&ia.s_addr, &addr->sin6_addr.s6_addr[12], sizeof(ia));
|
||||||
strcpy(dst, inet_ntoa(ia));
|
strcpy(dst, inet_ntoa(ia));
|
||||||
} else {
|
} else {
|
||||||
getnameinfo((struct sockaddr *)sockaddr, sockaddr_len, dst, sizeof(dst) - 1, NULL, 0, NI_NUMERICHOST);
|
getnameinfo((struct sockaddr *)sockaddr, sockaddr_len, dst, sizeof(dst) - 1, NULL, 0, NI_NUMERICHOST);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dst[0] = '?';
|
dst[0] = '?';
|
||||||
}
|
}
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
get_addr(char *host, int port, int addr_family, int flags, struct sockaddr_storage *out)
|
get_addr(char *host, int port, int addr_family, int flags, struct sockaddr_storage *out)
|
||||||
{
|
{
|
||||||
struct addrinfo hints, *addr;
|
struct addrinfo hints, *addr;
|
||||||
int res;
|
int res;
|
||||||
char portnum[8];
|
char portnum[8];
|
||||||
|
|
||||||
memset(portnum, 0, sizeof(portnum));
|
memset(portnum, 0, sizeof(portnum));
|
||||||
snprintf(portnum, sizeof(portnum) - 1, "%d", port);
|
snprintf(portnum, sizeof(portnum) - 1, "%d", port);
|
||||||
|
|
||||||
memset(&hints, 0, sizeof(hints));
|
memset(&hints, 0, sizeof(hints));
|
||||||
hints.ai_family = addr_family;
|
hints.ai_family = addr_family;
|
||||||
#if defined(WINDOWS32) || defined(OPENBSD)
|
#if defined(WINDOWS32) || defined(OPENBSD)
|
||||||
/* AI_ADDRCONFIG misbehaves on windows, and does not exist in OpenBSD */
|
/* AI_ADDRCONFIG misbehaves on windows, and does not exist in OpenBSD */
|
||||||
hints.ai_flags = flags;
|
hints.ai_flags = flags;
|
||||||
#else
|
#else
|
||||||
hints.ai_flags = AI_ADDRCONFIG | flags;
|
hints.ai_flags = AI_ADDRCONFIG | flags;
|
||||||
#endif
|
#endif
|
||||||
hints.ai_socktype = SOCK_DGRAM;
|
hints.ai_socktype = SOCK_DGRAM;
|
||||||
hints.ai_protocol = IPPROTO_UDP;
|
hints.ai_protocol = IPPROTO_UDP;
|
||||||
|
|
||||||
res = getaddrinfo(host, portnum, &hints, &addr);
|
res = getaddrinfo(host, portnum, &hints, &addr);
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
int addrlen = addr->ai_addrlen;
|
int addrlen = addr->ai_addrlen;
|
||||||
/* Grab first result */
|
/* Grab first result */
|
||||||
memcpy(out, addr->ai_addr, addr->ai_addrlen);
|
memcpy(out, addr->ai_addr, addr->ai_addrlen);
|
||||||
freeaddrinfo(addr);
|
freeaddrinfo(addr);
|
||||||
return addrlen;
|
return addrlen;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
open_dns(struct sockaddr_storage *sockaddr, size_t sockaddr_len)
|
open_dns(struct sockaddr_storage *sockaddr, size_t sockaddr_len)
|
||||||
{
|
{
|
||||||
int flag = 1;
|
int flag = 1;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
if ((fd = socket(sockaddr->ss_family, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
|
if ((fd = socket(sockaddr->ss_family, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
|
||||||
err(1, "socket");
|
err(1, "socket");
|
||||||
}
|
}
|
||||||
|
|
||||||
flag = 1;
|
flag = 1;
|
||||||
#ifdef SO_REUSEPORT
|
#ifdef SO_REUSEPORT
|
||||||
setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (const void*) &flag, sizeof(flag));
|
setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (const void*) &flag, sizeof(flag));
|
||||||
#endif
|
#endif
|
||||||
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void*) &flag, sizeof(flag));
|
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void*) &flag, sizeof(flag));
|
||||||
|
|
||||||
#ifndef WINDOWS32
|
#ifndef WINDOWS32
|
||||||
/* To get destination address from each UDP datagram, see iodined.c:read_dns() */
|
/* To get destination address from each UDP datagram, see iodined.c:read_dns() */
|
||||||
setsockopt(fd, IPPROTO_IP, DSTADDR_SOCKOPT, (const void*) &flag, sizeof(flag));
|
setsockopt(fd, IPPROTO_IP, DSTADDR_SOCKOPT, (const void*) &flag, sizeof(flag));
|
||||||
|
|
||||||
fd_set_close_on_exec(fd);
|
fd_set_close_on_exec(fd);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef IP_OPT_DONT_FRAG
|
#ifdef IP_OPT_DONT_FRAG
|
||||||
/* Set dont-fragment ip header flag */
|
/* Set dont-fragment ip header flag */
|
||||||
flag = DONT_FRAG_VALUE;
|
flag = DONT_FRAG_VALUE;
|
||||||
setsockopt(fd, IPPROTO_IP, IP_OPT_DONT_FRAG, (const void*) &flag, sizeof(flag));
|
setsockopt(fd, IPPROTO_IP, IP_OPT_DONT_FRAG, (const void*) &flag, sizeof(flag));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(bind(fd, (struct sockaddr*) sockaddr, sockaddr_len) < 0)
|
if(bind(fd, (struct sockaddr*) sockaddr, sockaddr_len) < 0)
|
||||||
err(1, "bind");
|
err(1, "bind");
|
||||||
|
|
||||||
fprintf(stderr, "Opened IPv%d UDP socket\n", sockaddr->ss_family == AF_INET6 ? 6 : 4);
|
fprintf(stderr, "Opened IPv%d UDP socket\n", sockaddr->ss_family == AF_INET6 ? 6 : 4);
|
||||||
|
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
open_dns_from_host(char *host, int port, int addr_family, int flags)
|
open_dns_from_host(char *host, int port, int addr_family, int flags)
|
||||||
{
|
{
|
||||||
struct sockaddr_storage addr;
|
struct sockaddr_storage addr;
|
||||||
int addrlen;
|
int addrlen;
|
||||||
|
|
||||||
addrlen = get_addr(host, port, addr_family, flags, &addr);
|
addrlen = get_addr(host, port, addr_family, flags, &addr);
|
||||||
if (addrlen < 0)
|
if (addrlen < 0)
|
||||||
return addrlen;
|
return addrlen;
|
||||||
|
|
||||||
return open_dns(&addr, addrlen);
|
return open_dns(&addr, addrlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
close_dns(int fd)
|
close_dns(int fd)
|
||||||
{
|
{
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
do_chroot(char *newroot)
|
do_chroot(char *newroot)
|
||||||
{
|
{
|
||||||
#if !(defined(WINDOWS32) || defined(__BEOS__) || defined(__HAIKU__))
|
#if !(defined(WINDOWS32) || defined(__BEOS__) || defined(__HAIKU__))
|
||||||
if (chroot(newroot) != 0 || chdir("/") != 0)
|
if (chroot(newroot) != 0 || chdir("/") != 0)
|
||||||
err(1, "%s", newroot);
|
err(1, "%s", newroot);
|
||||||
|
|
||||||
if (seteuid(geteuid()) != 0 || setuid(getuid()) != 0) {
|
if (seteuid(geteuid()) != 0 || setuid(getuid()) != 0) {
|
||||||
err(1, "set[e]uid()");
|
err(1, "set[e]uid()");
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
warnx("chroot not available");
|
warnx("chroot not available");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,10 +245,10 @@ void
|
||||||
do_setcon(char *context)
|
do_setcon(char *context)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_SETCON
|
#ifdef HAVE_SETCON
|
||||||
if (-1 == setcon(context))
|
if (-1 == setcon(context))
|
||||||
err(1, "%s", context);
|
err(1, "%s", context);
|
||||||
#else
|
#else
|
||||||
warnx("No SELinux support built in");
|
warnx("No SELinux support built in");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -256,17 +256,17 @@ void
|
||||||
do_pidfile(char *pidfile)
|
do_pidfile(char *pidfile)
|
||||||
{
|
{
|
||||||
#ifndef WINDOWS32
|
#ifndef WINDOWS32
|
||||||
FILE *file;
|
FILE *file;
|
||||||
|
|
||||||
if ((file = fopen(pidfile, "w")) == NULL) {
|
if ((file = fopen(pidfile, "w")) == NULL) {
|
||||||
syslog(LOG_ERR, "Cannot write pidfile to %s, exiting", pidfile);
|
syslog(LOG_ERR, "Cannot write pidfile to %s, exiting", pidfile);
|
||||||
err(1, "do_pidfile: Can not write pidfile to %s", pidfile);
|
err(1, "do_pidfile: Can not write pidfile to %s", pidfile);
|
||||||
} else {
|
} else {
|
||||||
fprintf(file, "%d\n", (int)getpid());
|
fprintf(file, "%d\n", (int)getpid());
|
||||||
fclose(file);
|
fclose(file);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
fprintf(stderr, "Windows version does not support pid file\n");
|
fprintf(stderr, "Windows version does not support pid file\n");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,117 +274,117 @@ void
|
||||||
do_detach()
|
do_detach()
|
||||||
{
|
{
|
||||||
#ifndef WINDOWS32
|
#ifndef WINDOWS32
|
||||||
fprintf(stderr, "Detaching from terminal...\n");
|
fprintf(stderr, "Detaching from terminal...\n");
|
||||||
daemon(0, 0);
|
daemon(0, 0);
|
||||||
umask(0);
|
umask(0);
|
||||||
alarm(0);
|
alarm(0);
|
||||||
#else
|
#else
|
||||||
fprintf(stderr, "Windows version does not support detaching\n");
|
fprintf(stderr, "Windows version does not support detaching\n");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
read_password(char *buf, size_t len)
|
read_password(char *buf, size_t len)
|
||||||
{
|
{
|
||||||
char pwd[80] = {0};
|
char pwd[80] = {0};
|
||||||
#ifndef WINDOWS32
|
#ifndef WINDOWS32
|
||||||
struct termios old;
|
struct termios old;
|
||||||
struct termios tp;
|
struct termios tp;
|
||||||
|
|
||||||
tcgetattr(0, &tp);
|
tcgetattr(0, &tp);
|
||||||
old = tp;
|
old = tp;
|
||||||
|
|
||||||
tp.c_lflag &= (~ECHO);
|
tp.c_lflag &= (~ECHO);
|
||||||
tcsetattr(0, TCSANOW, &tp);
|
tcsetattr(0, TCSANOW, &tp);
|
||||||
#else
|
#else
|
||||||
int i;
|
int i;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
fprintf(stderr, "Enter password: ");
|
fprintf(stderr, "Enter password: ");
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
#ifndef WINDOWS32
|
#ifndef WINDOWS32
|
||||||
fscanf(stdin, "%79[^\n]", pwd);
|
fscanf(stdin, "%79[^\n]", pwd);
|
||||||
#else
|
#else
|
||||||
for (i = 0; i < sizeof(pwd); i++) {
|
for (i = 0; i < sizeof(pwd); i++) {
|
||||||
pwd[i] = getch();
|
pwd[i] = getch();
|
||||||
if (pwd[i] == '\r' || pwd[i] == '\n') {
|
if (pwd[i] == '\r' || pwd[i] == '\n') {
|
||||||
pwd[i] = 0;
|
pwd[i] = 0;
|
||||||
break;
|
break;
|
||||||
} else if (pwd[i] == '\b') {
|
} else if (pwd[i] == '\b') {
|
||||||
i--; /* Remove the \b char */
|
i--; /* Remove the \b char */
|
||||||
if (i >=0) i--; /* If not first char, remove one more */
|
if (i >=0) i--; /* If not first char, remove one more */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
|
|
||||||
#ifndef WINDOWS32
|
#ifndef WINDOWS32
|
||||||
tcsetattr(0, TCSANOW, &old);
|
tcsetattr(0, TCSANOW, &old);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
strncpy(buf, pwd, len);
|
strncpy(buf, pwd, len);
|
||||||
buf[len-1] = '\0';
|
buf[len-1] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
check_topdomain(char *str, char **errormsg)
|
check_topdomain(char *str, char **errormsg)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int dots = 0;
|
int dots = 0;
|
||||||
int chunklen = 0;
|
int chunklen = 0;
|
||||||
|
|
||||||
if (strlen(str) < 3) {
|
if (strlen(str) < 3) {
|
||||||
if (errormsg) *errormsg = "Too short (< 3)";
|
if (errormsg) *errormsg = "Too short (< 3)";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (strlen(str) > 128) {
|
if (strlen(str) > 128) {
|
||||||
if (errormsg) *errormsg = "Too long (> 128)";
|
if (errormsg) *errormsg = "Too long (> 128)";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (str[0] == '.') {
|
if (str[0] == '.') {
|
||||||
if (errormsg) *errormsg = "Starts with a dot";
|
if (errormsg) *errormsg = "Starts with a dot";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for( i = 0; i < strlen(str); i++) {
|
for( i = 0; i < strlen(str); i++) {
|
||||||
if(str[i] == '.') {
|
if(str[i] == '.') {
|
||||||
dots++;
|
dots++;
|
||||||
if (chunklen == 0) {
|
if (chunklen == 0) {
|
||||||
if (errormsg) *errormsg = "Consecutive dots";
|
if (errormsg) *errormsg = "Consecutive dots";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (chunklen > 63) {
|
if (chunklen > 63) {
|
||||||
if (errormsg) *errormsg = "Too long domain part (> 63)";
|
if (errormsg) *errormsg = "Too long domain part (> 63)";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
chunklen = 0;
|
chunklen = 0;
|
||||||
} else {
|
} else {
|
||||||
chunklen++;
|
chunklen++;
|
||||||
}
|
}
|
||||||
if( (str[i] >= 'a' && str[i] <= 'z') || (str[i] >= 'A' && str[i] <= 'Z') ||
|
if( (str[i] >= 'a' && str[i] <= 'z') || (str[i] >= 'A' && str[i] <= 'Z') ||
|
||||||
isdigit(str[i]) || str[i] == '-' || str[i] == '.' ) {
|
isdigit(str[i]) || str[i] == '-' || str[i] == '.' ) {
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
if (errormsg) *errormsg = "Contains illegal character (allowed: [a-zA-Z0-9-.])";
|
if (errormsg) *errormsg = "Contains illegal character (allowed: [a-zA-Z0-9-.])";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dots == 0) {
|
if (dots == 0) {
|
||||||
if (errormsg) *errormsg = "No dots";
|
if (errormsg) *errormsg = "No dots";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (chunklen == 0) {
|
if (chunklen == 0) {
|
||||||
if (errormsg) *errormsg = "Ends with a dot";
|
if (errormsg) *errormsg = "Ends with a dot";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (chunklen > 63) {
|
if (chunklen > 63) {
|
||||||
if (errormsg) *errormsg = "Too long domain part (> 63)";
|
if (errormsg) *errormsg = "Too long domain part (> 63)";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(WINDOWS32) || defined(ANDROID)
|
#if defined(WINDOWS32) || defined(ANDROID)
|
||||||
|
@ -400,51 +400,51 @@ inet_aton(const char *cp, struct in_addr *inp)
|
||||||
void
|
void
|
||||||
warn(const char *fmt, ...)
|
warn(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list list;
|
va_list list;
|
||||||
|
|
||||||
va_start(list, fmt);
|
va_start(list, fmt);
|
||||||
if (fmt) fprintf(stderr, fmt, list);
|
if (fmt) fprintf(stderr, fmt, list);
|
||||||
#ifndef ANDROID
|
#ifndef ANDROID
|
||||||
if (errno == 0) {
|
if (errno == 0) {
|
||||||
fprintf(stderr, ": WSA error %d\n", WSAGetLastError());
|
fprintf(stderr, ": WSA error %d\n", WSAGetLastError());
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, ": %s\n", strerror(errno));
|
fprintf(stderr, ": %s\n", strerror(errno));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
va_end(list);
|
va_end(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
warnx(const char *fmt, ...)
|
warnx(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list list;
|
va_list list;
|
||||||
|
|
||||||
va_start(list, fmt);
|
va_start(list, fmt);
|
||||||
if (fmt) fprintf(stderr, fmt, list);
|
if (fmt) fprintf(stderr, fmt, list);
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
va_end(list);
|
va_end(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
err(int eval, const char *fmt, ...)
|
err(int eval, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list list;
|
va_list list;
|
||||||
|
|
||||||
va_start(list, fmt);
|
va_start(list, fmt);
|
||||||
warn(fmt, list);
|
warn(fmt, list);
|
||||||
va_end(list);
|
va_end(list);
|
||||||
exit(eval);
|
exit(eval);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
errx(int eval, const char *fmt, ...)
|
errx(int eval, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list list;
|
va_list list;
|
||||||
|
|
||||||
va_start(list, fmt);
|
va_start(list, fmt);
|
||||||
warnx(fmt, list);
|
warnx(fmt, list);
|
||||||
va_end(list);
|
va_end(list);
|
||||||
exit(eval);
|
exit(eval);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -454,14 +454,14 @@ int recent_seqno(int ourseqno, int gotseqno)
|
||||||
Return 0 if gotseqno is new (or very old).
|
Return 0 if gotseqno is new (or very old).
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < 4; i++, ourseqno--) {
|
for (i = 0; i < 4; i++, ourseqno--) {
|
||||||
if (ourseqno < 0)
|
if (ourseqno < 0)
|
||||||
ourseqno = 7;
|
ourseqno = 7;
|
||||||
if (gotseqno == ourseqno)
|
if (gotseqno == ourseqno)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef WINDOWS32
|
#ifndef WINDOWS32
|
||||||
|
@ -471,14 +471,14 @@ int recent_seqno(int ourseqno, int gotseqno)
|
||||||
void
|
void
|
||||||
fd_set_close_on_exec(int fd)
|
fd_set_close_on_exec(int fd)
|
||||||
{
|
{
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
flags = fcntl(fd, F_GETFD);
|
flags = fcntl(fd, F_GETFD);
|
||||||
if (flags == -1)
|
if (flags == -1)
|
||||||
err(4, "Failed to get fd flags");
|
err(4, "Failed to get fd flags");
|
||||||
flags |= FD_CLOEXEC;
|
flags |= FD_CLOEXEC;
|
||||||
if (fcntl(fd, F_SETFD, flags) == -1)
|
if (fcntl(fd, F_SETFD, flags) == -1)
|
||||||
err(4, "Failed to set fd flags");
|
err(4, "Failed to set fd flags");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
38
src/common.h
38
src/common.h
|
@ -82,31 +82,31 @@ extern const unsigned char raw_header[RAW_HDR_LEN];
|
||||||
|
|
||||||
struct packet
|
struct packet
|
||||||
{
|
{
|
||||||
int len; /* Total packet length */
|
int len; /* Total packet length */
|
||||||
int sentlen; /* Length of chunk currently transmitted */
|
int sentlen; /* Length of chunk currently transmitted */
|
||||||
int offset; /* Current offset */
|
int offset; /* Current offset */
|
||||||
char data[64*1024]; /* The data */
|
char data[64*1024]; /* The data */
|
||||||
char seqno; /* The packet sequence number */
|
char seqno; /* The packet sequence number */
|
||||||
char fragment; /* Fragment index */
|
char fragment; /* Fragment index */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct query {
|
struct query {
|
||||||
char name[QUERY_NAME_SIZE];
|
char name[QUERY_NAME_SIZE];
|
||||||
unsigned short type;
|
unsigned short type;
|
||||||
unsigned short rcode;
|
unsigned short rcode;
|
||||||
unsigned short id;
|
unsigned short id;
|
||||||
struct in_addr destination;
|
struct in_addr destination;
|
||||||
struct sockaddr_storage from;
|
struct sockaddr_storage from;
|
||||||
int fromlen;
|
int fromlen;
|
||||||
unsigned short id2;
|
unsigned short id2;
|
||||||
struct sockaddr from2;
|
struct sockaddr from2;
|
||||||
int fromlen2;
|
int fromlen2;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum connection {
|
enum connection {
|
||||||
CONN_RAW_UDP,
|
CONN_RAW_UDP,
|
||||||
CONN_DNS_NULL,
|
CONN_DNS_NULL,
|
||||||
CONN_MAX
|
CONN_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
void check_superuser(void (*usage_fn)(void));
|
void check_superuser(void (*usage_fn)(void));
|
||||||
|
|
|
@ -21,8 +21,8 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
QR_QUERY = 0,
|
QR_QUERY = 0,
|
||||||
QR_ANSWER = 1
|
QR_ANSWER = 1
|
||||||
} qr_t;
|
} qr_t;
|
||||||
|
|
||||||
extern int dnsc_use_edns0;
|
extern int dnsc_use_edns0;
|
||||||
|
|
142
src/encoding.c
142
src/encoding.c
|
@ -21,110 +21,110 @@
|
||||||
|
|
||||||
int
|
int
|
||||||
build_hostname(char *buf, size_t buflen,
|
build_hostname(char *buf, size_t buflen,
|
||||||
const char *data, const size_t datalen,
|
const char *data, const size_t datalen,
|
||||||
const char *topdomain, struct encoder *encoder, int maxlen)
|
const char *topdomain, struct encoder *encoder, int maxlen)
|
||||||
{
|
{
|
||||||
size_t space;
|
size_t space;
|
||||||
char *b;
|
char *b;
|
||||||
|
|
||||||
space = MIN((size_t)maxlen, buflen) - strlen(topdomain) - 8;
|
space = MIN((size_t)maxlen, buflen) - strlen(topdomain) - 8;
|
||||||
/* 8 = 5 max header length + 1 dot before topdomain + 2 safety */
|
/* 8 = 5 max header length + 1 dot before topdomain + 2 safety */
|
||||||
|
|
||||||
if (!encoder->places_dots())
|
if (!encoder->places_dots())
|
||||||
space -= (space / 57); /* space for dots */
|
space -= (space / 57); /* space for dots */
|
||||||
|
|
||||||
memset(buf, 0, buflen);
|
memset(buf, 0, buflen);
|
||||||
|
|
||||||
encoder->encode(buf, &space, data, datalen);
|
encoder->encode(buf, &space, data, datalen);
|
||||||
|
|
||||||
if (!encoder->places_dots())
|
if (!encoder->places_dots())
|
||||||
inline_dotify(buf, buflen);
|
inline_dotify(buf, buflen);
|
||||||
|
|
||||||
b = buf;
|
b = buf;
|
||||||
b += strlen(buf);
|
b += strlen(buf);
|
||||||
|
|
||||||
/* move b back one step to see if the dot is there */
|
/* move b back one step to see if the dot is there */
|
||||||
b--;
|
b--;
|
||||||
if (*b != '.')
|
if (*b != '.')
|
||||||
*++b = '.';
|
*++b = '.';
|
||||||
b++;
|
b++;
|
||||||
/* move b ahead of the string so we can copy to it */
|
/* move b ahead of the string so we can copy to it */
|
||||||
|
|
||||||
strncpy(b, topdomain, strlen(topdomain)+1);
|
strncpy(b, topdomain, strlen(topdomain)+1);
|
||||||
|
|
||||||
return space;
|
return space;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
unpack_data(char *buf, size_t buflen, char *data, size_t datalen, struct encoder *enc)
|
unpack_data(char *buf, size_t buflen, char *data, size_t datalen, struct encoder *enc)
|
||||||
{
|
{
|
||||||
if (!enc->eats_dots())
|
if (!enc->eats_dots())
|
||||||
datalen = inline_undotify(data, datalen);
|
datalen = inline_undotify(data, datalen);
|
||||||
return enc->decode(buf, &buflen, data, datalen);
|
return enc->decode(buf, &buflen, data, datalen);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
inline_dotify(char *buf, size_t buflen)
|
inline_dotify(char *buf, size_t buflen)
|
||||||
{
|
{
|
||||||
unsigned dots;
|
unsigned dots;
|
||||||
unsigned pos;
|
unsigned pos;
|
||||||
unsigned total;
|
unsigned total;
|
||||||
char *reader, *writer;
|
char *reader, *writer;
|
||||||
|
|
||||||
total = strlen(buf);
|
total = strlen(buf);
|
||||||
dots = total / 57;
|
dots = total / 57;
|
||||||
|
|
||||||
writer = buf;
|
writer = buf;
|
||||||
writer += total;
|
writer += total;
|
||||||
writer += dots;
|
writer += dots;
|
||||||
|
|
||||||
total += dots;
|
total += dots;
|
||||||
if (strlen(buf) + dots > buflen) {
|
if (strlen(buf) + dots > buflen) {
|
||||||
writer = buf;
|
writer = buf;
|
||||||
writer += buflen;
|
writer += buflen;
|
||||||
total = buflen;
|
total = buflen;
|
||||||
}
|
}
|
||||||
|
|
||||||
reader = writer - dots;
|
reader = writer - dots;
|
||||||
pos = (unsigned) (reader - buf) + 1;
|
pos = (unsigned) (reader - buf) + 1;
|
||||||
|
|
||||||
while (dots) {
|
while (dots) {
|
||||||
*writer-- = *reader--;
|
*writer-- = *reader--;
|
||||||
pos--;
|
pos--;
|
||||||
if (pos % 57 == 0) {
|
if (pos % 57 == 0) {
|
||||||
*writer-- = '.';
|
*writer-- = '.';
|
||||||
dots--;
|
dots--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return new length of string */
|
/* return new length of string */
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
inline_undotify(char *buf, size_t len)
|
inline_undotify(char *buf, size_t len)
|
||||||
{
|
{
|
||||||
unsigned pos;
|
unsigned pos;
|
||||||
unsigned dots;
|
unsigned dots;
|
||||||
char *reader, *writer;
|
char *reader, *writer;
|
||||||
|
|
||||||
writer = buf;
|
writer = buf;
|
||||||
reader = writer;
|
reader = writer;
|
||||||
|
|
||||||
pos = 0;
|
pos = 0;
|
||||||
dots = 0;
|
dots = 0;
|
||||||
|
|
||||||
while (pos < len) {
|
while (pos < len) {
|
||||||
if (*reader == '.') {
|
if (*reader == '.') {
|
||||||
reader++;
|
reader++;
|
||||||
pos++;
|
pos++;
|
||||||
dots++;
|
dots++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
*writer++ = *reader++;
|
*writer++ = *reader++;
|
||||||
pos++;
|
pos++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return new length of string */
|
/* return new length of string */
|
||||||
return len - dots;
|
return len - dots;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,13 +26,13 @@
|
||||||
#define DOWNCODECCHECK1_LEN 48
|
#define DOWNCODECCHECK1_LEN 48
|
||||||
|
|
||||||
struct encoder {
|
struct encoder {
|
||||||
char name[8];
|
char name[8];
|
||||||
int (*encode) (char *, size_t *, const void *, size_t);
|
int (*encode) (char *, size_t *, const void *, size_t);
|
||||||
int (*decode) (void *, size_t *, const char *, size_t);
|
int (*decode) (void *, size_t *, const char *, size_t);
|
||||||
int (*places_dots) (void);
|
int (*places_dots) (void);
|
||||||
int (*eats_dots) (void);
|
int (*eats_dots) (void);
|
||||||
int (*blocksize_raw)(void);
|
int (*blocksize_raw)(void);
|
||||||
int (*blocksize_encoded)(void);
|
int (*blocksize_encoded)(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
int build_hostname(char *, size_t, const char *, const size_t, const char *, struct encoder *, int);
|
int build_hostname(char *, size_t, const char *, const size_t, const char *, struct encoder *, int);
|
||||||
|
|
|
@ -22,28 +22,28 @@ static int fwq_ix;
|
||||||
|
|
||||||
void fw_query_init()
|
void fw_query_init()
|
||||||
{
|
{
|
||||||
memset(fwq, 0, sizeof(struct fw_query) * FW_QUERY_CACHE_SIZE);
|
memset(fwq, 0, sizeof(struct fw_query) * FW_QUERY_CACHE_SIZE);
|
||||||
fwq_ix = 0;
|
fwq_ix = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fw_query_put(struct fw_query *fw_query)
|
void fw_query_put(struct fw_query *fw_query)
|
||||||
{
|
{
|
||||||
memcpy(&(fwq[fwq_ix]), fw_query, sizeof(struct fw_query));
|
memcpy(&(fwq[fwq_ix]), fw_query, sizeof(struct fw_query));
|
||||||
|
|
||||||
++fwq_ix;
|
++fwq_ix;
|
||||||
if (fwq_ix >= FW_QUERY_CACHE_SIZE)
|
if (fwq_ix >= FW_QUERY_CACHE_SIZE)
|
||||||
fwq_ix = 0;
|
fwq_ix = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fw_query_get(unsigned short query_id, struct fw_query **fw_query)
|
void fw_query_get(unsigned short query_id, struct fw_query **fw_query)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
*fw_query = NULL;
|
*fw_query = NULL;
|
||||||
for (i = 0; i < FW_QUERY_CACHE_SIZE; i++) {
|
for (i = 0; i < FW_QUERY_CACHE_SIZE; i++) {
|
||||||
if (fwq[i].id == query_id) {
|
if (fwq[i].id == query_id) {
|
||||||
*fw_query = &(fwq[i]);
|
*fw_query = &(fwq[i]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,9 +28,9 @@
|
||||||
#define FW_QUERY_CACHE_SIZE 16
|
#define FW_QUERY_CACHE_SIZE 16
|
||||||
|
|
||||||
struct fw_query {
|
struct fw_query {
|
||||||
struct sockaddr_storage addr;
|
struct sockaddr_storage addr;
|
||||||
int addrlen;
|
int addrlen;
|
||||||
unsigned short id;
|
unsigned short id;
|
||||||
};
|
};
|
||||||
|
|
||||||
void fw_query_init();
|
void fw_query_init();
|
||||||
|
|
542
src/iodine.c
542
src/iodine.c
|
@ -55,7 +55,7 @@ static char *__progname;
|
||||||
static void
|
static void
|
||||||
sighandler(int sig)
|
sighandler(int sig)
|
||||||
{
|
{
|
||||||
client_stop();
|
client_stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__GNUC__) || defined(__clang__)
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
|
@ -66,344 +66,344 @@ static void usage() __attribute__((noreturn));
|
||||||
|
|
||||||
static void
|
static void
|
||||||
usage() {
|
usage() {
|
||||||
extern char *__progname;
|
extern char *__progname;
|
||||||
|
|
||||||
fprintf(stderr, "Usage: %s [-v] [-h] [-f] [-r] [-u user] [-t chrootdir] [-d device] "
|
fprintf(stderr, "Usage: %s [-v] [-h] [-f] [-r] [-u user] [-t chrootdir] [-d device] "
|
||||||
"[-P password] [-m maxfragsize] [-M maxlen] [-T type] [-O enc] [-L 0|1] [-I sec] "
|
"[-P password] [-m maxfragsize] [-M maxlen] [-T type] [-O enc] [-L 0|1] [-I sec] "
|
||||||
"[-z context] [-F pidfile] [nameserver] topdomain\n", __progname);
|
"[-z context] [-F pidfile] [nameserver] topdomain\n", __progname);
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
help() {
|
help() {
|
||||||
extern char *__progname;
|
extern char *__progname;
|
||||||
|
|
||||||
fprintf(stderr, "iodine IP over DNS tunneling client\n");
|
fprintf(stderr, "iodine IP over DNS tunneling client\n");
|
||||||
fprintf(stderr, "Usage: %s [-v] [-h] [-f] [-r] [-u user] [-t chrootdir] [-d device] "
|
fprintf(stderr, "Usage: %s [-v] [-h] [-f] [-r] [-u user] [-t chrootdir] [-d device] "
|
||||||
"[-P password] [-m maxfragsize] [-M maxlen] [-T type] [-O enc] [-L 0|1] [-I sec] "
|
"[-P password] [-m maxfragsize] [-M maxlen] [-T type] [-O enc] [-L 0|1] [-I sec] "
|
||||||
"[-z context] [-F pidfile] [nameserver] topdomain\n", __progname);
|
"[-z context] [-F pidfile] [nameserver] topdomain\n", __progname);
|
||||||
fprintf(stderr, "Options to try if connection doesn't work:\n");
|
fprintf(stderr, "Options to try if connection doesn't work:\n");
|
||||||
fprintf(stderr, " -T force dns type: NULL, PRIVATE, TXT, SRV, MX, CNAME, A (default: autodetect)\n");
|
fprintf(stderr, " -T force dns type: NULL, PRIVATE, TXT, SRV, MX, CNAME, A (default: autodetect)\n");
|
||||||
fprintf(stderr, " -O force downstream encoding for -T other than NULL: Base32, Base64, Base64u,\n");
|
fprintf(stderr, " -O force downstream encoding for -T other than NULL: Base32, Base64, Base64u,\n");
|
||||||
fprintf(stderr, " Base128, or (only for TXT:) Raw (default: autodetect)\n");
|
fprintf(stderr, " Base128, or (only for TXT:) Raw (default: autodetect)\n");
|
||||||
fprintf(stderr, " -I max interval between requests (default 4 sec) to prevent DNS timeouts\n");
|
fprintf(stderr, " -I max interval between requests (default 4 sec) to prevent DNS timeouts\n");
|
||||||
fprintf(stderr, " -L 1: use lazy mode for low-latency (default). 0: don't (implies -I1)\n");
|
fprintf(stderr, " -L 1: use lazy mode for low-latency (default). 0: don't (implies -I1)\n");
|
||||||
fprintf(stderr, " -m max size of downstream fragments (default: autodetect)\n");
|
fprintf(stderr, " -m max size of downstream fragments (default: autodetect)\n");
|
||||||
fprintf(stderr, " -M max size of upstream hostnames (~100-255, default: 255)\n");
|
fprintf(stderr, " -M max size of upstream hostnames (~100-255, default: 255)\n");
|
||||||
fprintf(stderr, " -r to skip raw UDP mode attempt\n");
|
fprintf(stderr, " -r to skip raw UDP mode attempt\n");
|
||||||
fprintf(stderr, " -P password used for authentication (max 32 chars will be used)\n");
|
fprintf(stderr, " -P password used for authentication (max 32 chars will be used)\n");
|
||||||
fprintf(stderr, "Other options:\n");
|
fprintf(stderr, "Other options:\n");
|
||||||
fprintf(stderr, " -v to print version info and exit\n");
|
fprintf(stderr, " -v to print version info and exit\n");
|
||||||
fprintf(stderr, " -h to print this help and exit\n");
|
fprintf(stderr, " -h to print this help and exit\n");
|
||||||
fprintf(stderr, " -f to keep running in foreground\n");
|
fprintf(stderr, " -f to keep running in foreground\n");
|
||||||
fprintf(stderr, " -u name to drop privileges and run as user 'name'\n");
|
fprintf(stderr, " -u name to drop privileges and run as user 'name'\n");
|
||||||
fprintf(stderr, " -t dir to chroot to directory dir\n");
|
fprintf(stderr, " -t dir to chroot to directory dir\n");
|
||||||
fprintf(stderr, " -d device to set tunnel device name\n");
|
fprintf(stderr, " -d device to set tunnel device name\n");
|
||||||
fprintf(stderr, " -z context, to apply specified SELinux context after initialization\n");
|
fprintf(stderr, " -z context, to apply specified SELinux context after initialization\n");
|
||||||
fprintf(stderr, " -F pidfile to write pid to a file\n");
|
fprintf(stderr, " -F pidfile to write pid to a file\n");
|
||||||
fprintf(stderr, "nameserver is the IP number/hostname of the relaying nameserver. if absent, /etc/resolv.conf is used\n");
|
fprintf(stderr, "nameserver is the IP number/hostname of the relaying nameserver. if absent, /etc/resolv.conf is used\n");
|
||||||
fprintf(stderr, "topdomain is the FQDN that is delegated to the tunnel endpoint.\n");
|
fprintf(stderr, "topdomain is the FQDN that is delegated to the tunnel endpoint.\n");
|
||||||
|
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
version() {
|
version() {
|
||||||
|
|
||||||
fprintf(stderr, "iodine IP over DNS tunneling client\n");
|
fprintf(stderr, "iodine IP over DNS tunneling client\n");
|
||||||
fprintf(stderr, "Git version: %s\n", GITREVISION);
|
fprintf(stderr, "Git version: %s\n", GITREVISION);
|
||||||
|
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
char *nameserv_host;
|
char *nameserv_host;
|
||||||
char *topdomain;
|
char *topdomain;
|
||||||
char *errormsg;
|
char *errormsg;
|
||||||
#ifndef WINDOWS32
|
#ifndef WINDOWS32
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
#endif
|
#endif
|
||||||
char *username;
|
char *username;
|
||||||
char password[33];
|
char password[33];
|
||||||
int foreground;
|
int foreground;
|
||||||
char *newroot;
|
char *newroot;
|
||||||
char *context;
|
char *context;
|
||||||
char *device;
|
char *device;
|
||||||
char *pidfile;
|
char *pidfile;
|
||||||
int choice;
|
int choice;
|
||||||
int tun_fd;
|
int tun_fd;
|
||||||
int dns_fd;
|
int dns_fd;
|
||||||
int max_downstream_frag_size;
|
int max_downstream_frag_size;
|
||||||
int autodetect_frag_size;
|
int autodetect_frag_size;
|
||||||
int retval;
|
int retval;
|
||||||
int raw_mode;
|
int raw_mode;
|
||||||
int lazymode;
|
int lazymode;
|
||||||
int selecttimeout;
|
int selecttimeout;
|
||||||
int hostname_maxlen;
|
int hostname_maxlen;
|
||||||
#ifdef OPENBSD
|
#ifdef OPENBSD
|
||||||
int rtable = 0;
|
int rtable = 0;
|
||||||
#endif
|
#endif
|
||||||
struct sockaddr_storage nameservaddr;
|
struct sockaddr_storage nameservaddr;
|
||||||
int nameservaddr_len;
|
int nameservaddr_len;
|
||||||
int nameserv_family;
|
int nameserv_family;
|
||||||
|
|
||||||
nameserv_host = NULL;
|
nameserv_host = NULL;
|
||||||
topdomain = NULL;
|
topdomain = NULL;
|
||||||
errormsg = NULL;
|
errormsg = NULL;
|
||||||
#ifndef WINDOWS32
|
#ifndef WINDOWS32
|
||||||
pw = NULL;
|
pw = NULL;
|
||||||
#endif
|
#endif
|
||||||
username = NULL;
|
username = NULL;
|
||||||
memset(password, 0, 33);
|
memset(password, 0, 33);
|
||||||
srand(time(NULL));
|
srand(time(NULL));
|
||||||
foreground = 0;
|
foreground = 0;
|
||||||
newroot = NULL;
|
newroot = NULL;
|
||||||
context = NULL;
|
context = NULL;
|
||||||
device = NULL;
|
device = NULL;
|
||||||
pidfile = NULL;
|
pidfile = NULL;
|
||||||
|
|
||||||
autodetect_frag_size = 1;
|
autodetect_frag_size = 1;
|
||||||
max_downstream_frag_size = 3072;
|
max_downstream_frag_size = 3072;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
raw_mode = 1;
|
raw_mode = 1;
|
||||||
lazymode = 1;
|
lazymode = 1;
|
||||||
selecttimeout = 4;
|
selecttimeout = 4;
|
||||||
hostname_maxlen = 0xFF;
|
hostname_maxlen = 0xFF;
|
||||||
nameserv_family = AF_UNSPEC;
|
nameserv_family = AF_UNSPEC;
|
||||||
|
|
||||||
#ifdef WINDOWS32
|
#ifdef WINDOWS32
|
||||||
WSAStartup(req_version, &wsa_data);
|
WSAStartup(req_version, &wsa_data);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
srand((unsigned) time(NULL));
|
srand((unsigned) time(NULL));
|
||||||
client_init();
|
client_init();
|
||||||
|
|
||||||
#if !defined(BSD) && !defined(__GLIBC__)
|
#if !defined(BSD) && !defined(__GLIBC__)
|
||||||
__progname = strrchr(argv[0], '/');
|
__progname = strrchr(argv[0], '/');
|
||||||
if (__progname == NULL)
|
if (__progname == NULL)
|
||||||
__progname = argv[0];
|
__progname = argv[0];
|
||||||
else
|
else
|
||||||
__progname++;
|
__progname++;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while ((choice = getopt(argc, argv, "46vfhru:t:d:R:P:m:M:F:T:O:L:I:")) != -1) {
|
while ((choice = getopt(argc, argv, "46vfhru:t:d:R:P:m:M:F:T:O:L:I:")) != -1) {
|
||||||
switch(choice) {
|
switch(choice) {
|
||||||
case '4':
|
case '4':
|
||||||
nameserv_family = AF_INET;
|
nameserv_family = AF_INET;
|
||||||
break;
|
break;
|
||||||
case '6':
|
case '6':
|
||||||
nameserv_family = AF_INET6;
|
nameserv_family = AF_INET6;
|
||||||
break;
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
version();
|
version();
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
foreground = 1;
|
foreground = 1;
|
||||||
break;
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
help();
|
help();
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
raw_mode = 0;
|
raw_mode = 0;
|
||||||
break;
|
break;
|
||||||
case 'u':
|
case 'u':
|
||||||
username = optarg;
|
username = optarg;
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
newroot = optarg;
|
newroot = optarg;
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
device = optarg;
|
device = optarg;
|
||||||
break;
|
break;
|
||||||
#ifdef OPENBSD
|
#ifdef OPENBSD
|
||||||
case 'R':
|
case 'R':
|
||||||
rtable = atoi(optarg);
|
rtable = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case 'P':
|
case 'P':
|
||||||
strncpy(password, optarg, sizeof(password));
|
strncpy(password, optarg, sizeof(password));
|
||||||
password[sizeof(password)-1] = 0;
|
password[sizeof(password)-1] = 0;
|
||||||
|
|
||||||
/* XXX: find better way of cleaning up ps(1) */
|
/* XXX: find better way of cleaning up ps(1) */
|
||||||
memset(optarg, 0, strlen(optarg));
|
memset(optarg, 0, strlen(optarg));
|
||||||
break;
|
break;
|
||||||
case 'm':
|
case 'm':
|
||||||
autodetect_frag_size = 0;
|
autodetect_frag_size = 0;
|
||||||
max_downstream_frag_size = atoi(optarg);
|
max_downstream_frag_size = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
case 'M':
|
case 'M':
|
||||||
hostname_maxlen = atoi(optarg);
|
hostname_maxlen = atoi(optarg);
|
||||||
if (hostname_maxlen > 255)
|
if (hostname_maxlen > 255)
|
||||||
hostname_maxlen = 255;
|
hostname_maxlen = 255;
|
||||||
if (hostname_maxlen < 10)
|
if (hostname_maxlen < 10)
|
||||||
hostname_maxlen = 10;
|
hostname_maxlen = 10;
|
||||||
break;
|
break;
|
||||||
case 'z':
|
case 'z':
|
||||||
context = optarg;
|
context = optarg;
|
||||||
break;
|
break;
|
||||||
case 'F':
|
case 'F':
|
||||||
pidfile = optarg;
|
pidfile = optarg;
|
||||||
break;
|
break;
|
||||||
case 'T':
|
case 'T':
|
||||||
if (client_set_qtype(optarg))
|
if (client_set_qtype(optarg))
|
||||||
errx(5, "Invalid query type '%s'", optarg);
|
errx(5, "Invalid query type '%s'", optarg);
|
||||||
break;
|
break;
|
||||||
case 'O': /* not -D, is Debug in server */
|
case 'O': /* not -D, is Debug in server */
|
||||||
client_set_downenc(optarg);
|
client_set_downenc(optarg);
|
||||||
break;
|
break;
|
||||||
case 'L':
|
case 'L':
|
||||||
lazymode = atoi(optarg);
|
lazymode = atoi(optarg);
|
||||||
if (lazymode > 1)
|
if (lazymode > 1)
|
||||||
lazymode = 1;
|
lazymode = 1;
|
||||||
if (lazymode < 0)
|
if (lazymode < 0)
|
||||||
lazymode = 0;
|
lazymode = 0;
|
||||||
if (!lazymode)
|
if (!lazymode)
|
||||||
selecttimeout = 1;
|
selecttimeout = 1;
|
||||||
break;
|
break;
|
||||||
case 'I':
|
case 'I':
|
||||||
selecttimeout = atoi(optarg);
|
selecttimeout = atoi(optarg);
|
||||||
if (selecttimeout < 1)
|
if (selecttimeout < 1)
|
||||||
selecttimeout = 1;
|
selecttimeout = 1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
usage();
|
usage();
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
check_superuser(usage);
|
check_superuser(usage);
|
||||||
|
|
||||||
argc -= optind;
|
argc -= optind;
|
||||||
argv += optind;
|
argv += optind;
|
||||||
|
|
||||||
switch (argc) {
|
switch (argc) {
|
||||||
case 1:
|
case 1:
|
||||||
nameserv_host = get_resolvconf_addr();
|
nameserv_host = get_resolvconf_addr();
|
||||||
topdomain = strdup(argv[0]);
|
topdomain = strdup(argv[0]);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
nameserv_host = argv[0];
|
nameserv_host = argv[0];
|
||||||
topdomain = strdup(argv[1]);
|
topdomain = strdup(argv[1]);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
usage();
|
usage();
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (max_downstream_frag_size < 1 || max_downstream_frag_size > 0xffff) {
|
if (max_downstream_frag_size < 1 || max_downstream_frag_size > 0xffff) {
|
||||||
warnx("Use a max frag size between 1 and 65535 bytes.\n");
|
warnx("Use a max frag size between 1 and 65535 bytes.\n");
|
||||||
usage();
|
usage();
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nameserv_host) {
|
if (nameserv_host) {
|
||||||
nameservaddr_len = get_addr(nameserv_host, DNS_PORT, nameserv_family, 0, &nameservaddr);
|
nameservaddr_len = get_addr(nameserv_host, DNS_PORT, nameserv_family, 0, &nameservaddr);
|
||||||
if (nameservaddr_len < 0) {
|
if (nameservaddr_len < 0) {
|
||||||
errx(1, "Cannot lookup nameserver '%s': %s ",
|
errx(1, "Cannot lookup nameserver '%s': %s ",
|
||||||
nameserv_host, gai_strerror(nameservaddr_len));
|
nameserv_host, gai_strerror(nameservaddr_len));
|
||||||
}
|
}
|
||||||
client_set_nameserver(&nameservaddr, nameservaddr_len);
|
client_set_nameserver(&nameservaddr, nameservaddr_len);
|
||||||
} else {
|
} else {
|
||||||
warnx("No nameserver found - not connected to any network?\n");
|
warnx("No nameserver found - not connected to any network?\n");
|
||||||
usage();
|
usage();
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
|
||||||
if(check_topdomain(topdomain, &errormsg)) {
|
if(check_topdomain(topdomain, &errormsg)) {
|
||||||
warnx("Invalid topdomain: %s", errormsg);
|
warnx("Invalid topdomain: %s", errormsg);
|
||||||
usage();
|
usage();
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
|
||||||
client_set_selecttimeout(selecttimeout);
|
client_set_selecttimeout(selecttimeout);
|
||||||
client_set_lazymode(lazymode);
|
client_set_lazymode(lazymode);
|
||||||
client_set_topdomain(topdomain);
|
client_set_topdomain(topdomain);
|
||||||
client_set_hostname_maxlen(hostname_maxlen);
|
client_set_hostname_maxlen(hostname_maxlen);
|
||||||
|
|
||||||
if (username != NULL) {
|
if (username != NULL) {
|
||||||
#ifndef WINDOWS32
|
#ifndef WINDOWS32
|
||||||
if ((pw = getpwnam(username)) == NULL) {
|
if ((pw = getpwnam(username)) == NULL) {
|
||||||
warnx("User %s does not exist!\n", username);
|
warnx("User %s does not exist!\n", username);
|
||||||
usage();
|
usage();
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen(password) == 0) {
|
if (strlen(password) == 0) {
|
||||||
if (NULL != getenv(PASSWORD_ENV_VAR))
|
if (NULL != getenv(PASSWORD_ENV_VAR))
|
||||||
snprintf(password, sizeof(password), "%s", getenv(PASSWORD_ENV_VAR));
|
snprintf(password, sizeof(password), "%s", getenv(PASSWORD_ENV_VAR));
|
||||||
else
|
else
|
||||||
read_password(password, sizeof(password));
|
read_password(password, sizeof(password));
|
||||||
}
|
}
|
||||||
|
|
||||||
client_set_password(password);
|
client_set_password(password);
|
||||||
|
|
||||||
if ((tun_fd = open_tun(device)) == -1) {
|
if ((tun_fd = open_tun(device)) == -1) {
|
||||||
retval = 1;
|
retval = 1;
|
||||||
goto cleanup1;
|
goto cleanup1;
|
||||||
}
|
}
|
||||||
if ((dns_fd = open_dns_from_host(NULL, 0, nameservaddr.ss_family, AI_PASSIVE)) < 0) {
|
if ((dns_fd = open_dns_from_host(NULL, 0, nameservaddr.ss_family, AI_PASSIVE)) < 0) {
|
||||||
retval = 1;
|
retval = 1;
|
||||||
goto cleanup2;
|
goto cleanup2;
|
||||||
}
|
}
|
||||||
#ifdef OPENBSD
|
#ifdef OPENBSD
|
||||||
if (rtable > 0)
|
if (rtable > 0)
|
||||||
socket_setrtable(dns_fd, rtable);
|
socket_setrtable(dns_fd, rtable);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
signal(SIGINT, sighandler);
|
signal(SIGINT, sighandler);
|
||||||
signal(SIGTERM, sighandler);
|
signal(SIGTERM, sighandler);
|
||||||
|
|
||||||
fprintf(stderr, "Sending DNS queries for %s to %s\n",
|
fprintf(stderr, "Sending DNS queries for %s to %s\n",
|
||||||
topdomain, format_addr(&nameservaddr, nameservaddr_len));
|
topdomain, format_addr(&nameservaddr, nameservaddr_len));
|
||||||
|
|
||||||
if (client_handshake(dns_fd, raw_mode, autodetect_frag_size, max_downstream_frag_size)) {
|
if (client_handshake(dns_fd, raw_mode, autodetect_frag_size, max_downstream_frag_size)) {
|
||||||
retval = 1;
|
retval = 1;
|
||||||
goto cleanup2;
|
goto cleanup2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (client_get_conn() == CONN_RAW_UDP) {
|
if (client_get_conn() == CONN_RAW_UDP) {
|
||||||
fprintf(stderr, "Sending raw traffic directly to %s\n", client_get_raw_addr());
|
fprintf(stderr, "Sending raw traffic directly to %s\n", client_get_raw_addr());
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "Connection setup complete, transmitting data.\n");
|
fprintf(stderr, "Connection setup complete, transmitting data.\n");
|
||||||
|
|
||||||
if (foreground == 0)
|
if (foreground == 0)
|
||||||
do_detach();
|
do_detach();
|
||||||
|
|
||||||
if (pidfile != NULL)
|
if (pidfile != NULL)
|
||||||
do_pidfile(pidfile);
|
do_pidfile(pidfile);
|
||||||
|
|
||||||
if (newroot != NULL)
|
if (newroot != NULL)
|
||||||
do_chroot(newroot);
|
do_chroot(newroot);
|
||||||
|
|
||||||
if (username != NULL) {
|
if (username != NULL) {
|
||||||
#ifndef WINDOWS32
|
#ifndef WINDOWS32
|
||||||
gid_t gids[1];
|
gid_t gids[1];
|
||||||
gids[0] = pw->pw_gid;
|
gids[0] = pw->pw_gid;
|
||||||
if (setgroups(1, gids) < 0 || setgid(pw->pw_gid) < 0 || setuid(pw->pw_uid) < 0) {
|
if (setgroups(1, gids) < 0 || setgid(pw->pw_gid) < 0 || setuid(pw->pw_uid) < 0) {
|
||||||
warnx("Could not switch to user %s!\n", username);
|
warnx("Could not switch to user %s!\n", username);
|
||||||
usage();
|
usage();
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context != NULL)
|
if (context != NULL)
|
||||||
do_setcon(context);
|
do_setcon(context);
|
||||||
|
|
||||||
client_tunnel(tun_fd, dns_fd);
|
client_tunnel(tun_fd, dns_fd);
|
||||||
|
|
||||||
cleanup2:
|
cleanup2:
|
||||||
close_dns(dns_fd);
|
close_dns(dns_fd);
|
||||||
close_tun(tun_fd);
|
close_tun(tun_fd);
|
||||||
cleanup1:
|
cleanup1:
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
3816
src/iodined.c
3816
src/iodined.c
File diff suppressed because it is too large
Load diff
34
src/login.c
34
src/login.c
|
@ -33,27 +33,27 @@
|
||||||
void
|
void
|
||||||
login_calculate(char *buf, int buflen, const char *pass, int seed)
|
login_calculate(char *buf, int buflen, const char *pass, int seed)
|
||||||
{
|
{
|
||||||
unsigned char temp[32];
|
unsigned char temp[32];
|
||||||
md5_state_t ctx;
|
md5_state_t ctx;
|
||||||
int *ix;
|
int *ix;
|
||||||
int i;
|
int i;
|
||||||
int k;
|
int k;
|
||||||
|
|
||||||
if (buflen < 16)
|
if (buflen < 16)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
memcpy(temp, pass, 32);
|
memcpy(temp, pass, 32);
|
||||||
ix = (int*) temp;
|
ix = (int*) temp;
|
||||||
|
|
||||||
for (i = 0; i < 8; i++) {
|
for (i = 0; i < 8; i++) {
|
||||||
k = ntohl(*ix);
|
k = ntohl(*ix);
|
||||||
k ^= seed;
|
k ^= seed;
|
||||||
*ix++ = htonl(k);
|
*ix++ = htonl(k);
|
||||||
}
|
}
|
||||||
|
|
||||||
md5_init(&ctx);
|
md5_init(&ctx);
|
||||||
md5_append(&ctx, temp, 32);
|
md5_append(&ctx, temp, 32);
|
||||||
md5_finish(&ctx, (unsigned char *) buf);
|
md5_finish(&ctx, (unsigned char *) buf);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
306
src/read.c
306
src/read.c
|
@ -22,249 +22,249 @@
|
||||||
static int
|
static int
|
||||||
readname_loop(char *packet, int packetlen, char **src, char *dst, size_t length, size_t loop)
|
readname_loop(char *packet, int packetlen, char **src, char *dst, size_t length, size_t loop)
|
||||||
{
|
{
|
||||||
char *dummy;
|
char *dummy;
|
||||||
char *s;
|
char *s;
|
||||||
char *d;
|
char *d;
|
||||||
int len;
|
int len;
|
||||||
int offset;
|
int offset;
|
||||||
char c;
|
char c;
|
||||||
|
|
||||||
if (loop <= 0)
|
if (loop <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
len = 0;
|
len = 0;
|
||||||
s = *src;
|
s = *src;
|
||||||
d = dst;
|
d = dst;
|
||||||
while(*s && len < length - 2) {
|
while(*s && len < length - 2) {
|
||||||
c = *s++;
|
c = *s++;
|
||||||
|
|
||||||
/* is this a compressed label? */
|
/* is this a compressed label? */
|
||||||
if((c & 0xc0) == 0xc0) {
|
if((c & 0xc0) == 0xc0) {
|
||||||
offset = (((s[-1] & 0x3f) << 8) | (s[0] & 0xff));
|
offset = (((s[-1] & 0x3f) << 8) | (s[0] & 0xff));
|
||||||
if (offset > packetlen) {
|
if (offset > packetlen) {
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
/* Bad jump first in packet */
|
/* Bad jump first in packet */
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
/* Bad jump after some data */
|
/* Bad jump after some data */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dummy = packet + offset;
|
dummy = packet + offset;
|
||||||
len += readname_loop(packet, packetlen, &dummy, d, length - len, loop - 1);
|
len += readname_loop(packet, packetlen, &dummy, d, length - len, loop - 1);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
while(c && len < length - 1) {
|
while(c && len < length - 1) {
|
||||||
*d++ = *s++;
|
*d++ = *s++;
|
||||||
len++;
|
len++;
|
||||||
|
|
||||||
c--;
|
c--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len >= length - 1) {
|
if (len >= length - 1) {
|
||||||
break; /* We used up all space */
|
break; /* We used up all space */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*s != 0) {
|
if (*s != 0) {
|
||||||
*d++ = '.';
|
*d++ = '.';
|
||||||
len++;
|
len++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dst[len++] = '\0';
|
dst[len++] = '\0';
|
||||||
|
|
||||||
end:
|
end:
|
||||||
(*src) = s+1;
|
(*src) = s+1;
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
readname(char *packet, int packetlen, char **src, char *dst, size_t length)
|
readname(char *packet, int packetlen, char **src, char *dst, size_t length)
|
||||||
{
|
{
|
||||||
return readname_loop(packet, packetlen, src, dst, length, 10);
|
return readname_loop(packet, packetlen, src, dst, length, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
readshort(char *packet, char **src, unsigned short *dst)
|
readshort(char *packet, char **src, unsigned short *dst)
|
||||||
{
|
{
|
||||||
unsigned char *p;
|
unsigned char *p;
|
||||||
|
|
||||||
p = (unsigned char *) *src;
|
p = (unsigned char *) *src;
|
||||||
*dst = (p[0] << 8) | p[1];
|
*dst = (p[0] << 8) | p[1];
|
||||||
|
|
||||||
(*src) += sizeof(unsigned short);
|
(*src) += sizeof(unsigned short);
|
||||||
return sizeof(unsigned short);
|
return sizeof(unsigned short);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
readlong(char *packet, char **src, uint32_t *dst)
|
readlong(char *packet, char **src, uint32_t *dst)
|
||||||
{
|
{
|
||||||
/* A long as described in dns protocol is always 32 bits */
|
/* A long as described in dns protocol is always 32 bits */
|
||||||
unsigned char *p;
|
unsigned char *p;
|
||||||
|
|
||||||
p = (unsigned char *) *src;
|
p = (unsigned char *) *src;
|
||||||
|
|
||||||
*dst = ((uint32_t)p[0] << 24)
|
*dst = ((uint32_t)p[0] << 24)
|
||||||
| ((uint32_t)p[1] << 16)
|
| ((uint32_t)p[1] << 16)
|
||||||
| ((uint32_t)p[2] << 8)
|
| ((uint32_t)p[2] << 8)
|
||||||
| ((uint32_t)p[3]);
|
| ((uint32_t)p[3]);
|
||||||
|
|
||||||
(*src) += sizeof(uint32_t);
|
(*src) += sizeof(uint32_t);
|
||||||
return sizeof(uint32_t);
|
return sizeof(uint32_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
readdata(char *packet, char **src, char *dst, size_t len)
|
readdata(char *packet, char **src, char *dst, size_t len)
|
||||||
{
|
{
|
||||||
memcpy(dst, *src, len);
|
memcpy(dst, *src, len);
|
||||||
|
|
||||||
(*src) += len;
|
(*src) += len;
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
readtxtbin(char *packet, char **src, size_t srcremain, char *dst, size_t dstremain)
|
readtxtbin(char *packet, char **src, size_t srcremain, char *dst, size_t dstremain)
|
||||||
{
|
{
|
||||||
unsigned char *uc;
|
unsigned char *uc;
|
||||||
int tocopy;
|
int tocopy;
|
||||||
int dstused = 0;
|
int dstused = 0;
|
||||||
|
|
||||||
while (srcremain > 0)
|
while (srcremain > 0)
|
||||||
{
|
{
|
||||||
uc = (unsigned char*) (*src);
|
uc = (unsigned char*) (*src);
|
||||||
tocopy = *uc;
|
tocopy = *uc;
|
||||||
(*src)++;
|
(*src)++;
|
||||||
srcremain--;
|
srcremain--;
|
||||||
|
|
||||||
if (tocopy > srcremain)
|
if (tocopy > srcremain)
|
||||||
return 0; /* illegal, better have nothing */
|
return 0; /* illegal, better have nothing */
|
||||||
if (tocopy > dstremain)
|
if (tocopy > dstremain)
|
||||||
return 0; /* doesn't fit, better have nothing */
|
return 0; /* doesn't fit, better have nothing */
|
||||||
|
|
||||||
memcpy(dst, *src, tocopy);
|
memcpy(dst, *src, tocopy);
|
||||||
dst += tocopy;
|
dst += tocopy;
|
||||||
(*src) += tocopy;
|
(*src) += tocopy;
|
||||||
srcremain -= tocopy;
|
srcremain -= tocopy;
|
||||||
dstremain -= tocopy;
|
dstremain -= tocopy;
|
||||||
dstused += tocopy;
|
dstused += tocopy;
|
||||||
}
|
}
|
||||||
return dstused;
|
return dstused;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
putname(char **buf, size_t buflen, const char *host)
|
putname(char **buf, size_t buflen, const char *host)
|
||||||
{
|
{
|
||||||
char *word;
|
char *word;
|
||||||
int left;
|
int left;
|
||||||
char *h;
|
char *h;
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
h = strdup(host);
|
h = strdup(host);
|
||||||
left = buflen;
|
left = buflen;
|
||||||
p = *buf;
|
p = *buf;
|
||||||
|
|
||||||
word = strtok(h, ".");
|
word = strtok(h, ".");
|
||||||
while(word) {
|
while(word) {
|
||||||
if (strlen(word) > 63 || strlen(word) > left) {
|
if (strlen(word) > 63 || strlen(word) > left) {
|
||||||
free(h);
|
free(h);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
left -= (strlen(word) + 1);
|
left -= (strlen(word) + 1);
|
||||||
*p++ = (char)strlen(word);
|
*p++ = (char)strlen(word);
|
||||||
memcpy(p, word, strlen(word));
|
memcpy(p, word, strlen(word));
|
||||||
p += strlen(word);
|
p += strlen(word);
|
||||||
|
|
||||||
word = strtok(NULL, ".");
|
word = strtok(NULL, ".");
|
||||||
}
|
}
|
||||||
|
|
||||||
*p++ = 0;
|
*p++ = 0;
|
||||||
|
|
||||||
free(h);
|
free(h);
|
||||||
|
|
||||||
*buf = p;
|
*buf = p;
|
||||||
return buflen - left;
|
return buflen - left;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
putbyte(char **dst, unsigned char value)
|
putbyte(char **dst, unsigned char value)
|
||||||
{
|
{
|
||||||
**dst = value;
|
**dst = value;
|
||||||
(*dst)++;
|
(*dst)++;
|
||||||
|
|
||||||
return sizeof(char);
|
return sizeof(char);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
putshort(char **dst, unsigned short value)
|
putshort(char **dst, unsigned short value)
|
||||||
{
|
{
|
||||||
unsigned char *p;
|
unsigned char *p;
|
||||||
|
|
||||||
p = (unsigned char *) *dst;
|
p = (unsigned char *) *dst;
|
||||||
|
|
||||||
*p++ = (value >> 8);
|
*p++ = (value >> 8);
|
||||||
*p++ = value;
|
*p++ = value;
|
||||||
|
|
||||||
(*dst) = (char *) p;
|
(*dst) = (char *) p;
|
||||||
return sizeof(short);
|
return sizeof(short);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
putlong(char **dst, uint32_t value)
|
putlong(char **dst, uint32_t value)
|
||||||
{
|
{
|
||||||
/* A long as described in dns protocol is always 32 bits */
|
/* A long as described in dns protocol is always 32 bits */
|
||||||
unsigned char *p;
|
unsigned char *p;
|
||||||
|
|
||||||
p = (unsigned char *) *dst;
|
p = (unsigned char *) *dst;
|
||||||
|
|
||||||
*p++ = (value >> 24);
|
*p++ = (value >> 24);
|
||||||
*p++ = (value >> 16);
|
*p++ = (value >> 16);
|
||||||
*p++ = (value >> 8);
|
*p++ = (value >> 8);
|
||||||
*p++ = (value);
|
*p++ = (value);
|
||||||
|
|
||||||
(*dst) = (char *) p;
|
(*dst) = (char *) p;
|
||||||
return sizeof(uint32_t);
|
return sizeof(uint32_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
putdata(char **dst, char *data, size_t len)
|
putdata(char **dst, char *data, size_t len)
|
||||||
{
|
{
|
||||||
memcpy(*dst, data, len);
|
memcpy(*dst, data, len);
|
||||||
|
|
||||||
(*dst) += len;
|
(*dst) += len;
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
puttxtbin(char **buf, size_t bufremain, char *from, size_t fromremain)
|
puttxtbin(char **buf, size_t bufremain, char *from, size_t fromremain)
|
||||||
{
|
{
|
||||||
unsigned char uc;
|
unsigned char uc;
|
||||||
unsigned char *ucp = &uc;
|
unsigned char *ucp = &uc;
|
||||||
char *cp = (char *) ucp;
|
char *cp = (char *) ucp;
|
||||||
int tocopy;
|
int tocopy;
|
||||||
int bufused = 0;
|
int bufused = 0;
|
||||||
|
|
||||||
while (fromremain > 0)
|
while (fromremain > 0)
|
||||||
{
|
{
|
||||||
tocopy = fromremain;
|
tocopy = fromremain;
|
||||||
if (tocopy > 252)
|
if (tocopy > 252)
|
||||||
tocopy = 252; /* allow off-by-1s in caches etc */
|
tocopy = 252; /* allow off-by-1s in caches etc */
|
||||||
if (tocopy + 1 > bufremain)
|
if (tocopy + 1 > bufremain)
|
||||||
return -1; /* doesn't fit, better have nothing */
|
return -1; /* doesn't fit, better have nothing */
|
||||||
|
|
||||||
uc = tocopy;
|
uc = tocopy;
|
||||||
**buf = *cp;
|
**buf = *cp;
|
||||||
(*buf)++;
|
(*buf)++;
|
||||||
bufremain--;
|
bufremain--;
|
||||||
bufused++;
|
bufused++;
|
||||||
|
|
||||||
memcpy(*buf, from, tocopy);
|
memcpy(*buf, from, tocopy);
|
||||||
(*buf) += tocopy;
|
(*buf) += tocopy;
|
||||||
from += tocopy;
|
from += tocopy;
|
||||||
bufremain -= tocopy;
|
bufremain -= tocopy;
|
||||||
fromremain -= tocopy;
|
fromremain -= tocopy;
|
||||||
bufused += tocopy;
|
bufused += tocopy;
|
||||||
}
|
}
|
||||||
return bufused;
|
return bufused;
|
||||||
}
|
}
|
||||||
|
|
698
src/tun.c
698
src/tun.c
|
@ -71,61 +71,61 @@ static char if_name[250];
|
||||||
int
|
int
|
||||||
open_tun(const char *tun_device)
|
open_tun(const char *tun_device)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int tun_fd;
|
int tun_fd;
|
||||||
struct ifreq ifreq;
|
struct ifreq ifreq;
|
||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
char *tunnel = "/dev/tun";
|
char *tunnel = "/dev/tun";
|
||||||
#else
|
#else
|
||||||
char *tunnel = "/dev/net/tun";
|
char *tunnel = "/dev/net/tun";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((tun_fd = open(tunnel, O_RDWR)) < 0) {
|
if ((tun_fd = open(tunnel, O_RDWR)) < 0) {
|
||||||
warn("open_tun: %s", tunnel);
|
warn("open_tun: %s", tunnel);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&ifreq, 0, sizeof(ifreq));
|
memset(&ifreq, 0, sizeof(ifreq));
|
||||||
|
|
||||||
ifreq.ifr_flags = IFF_TUN;
|
ifreq.ifr_flags = IFF_TUN;
|
||||||
|
|
||||||
if (tun_device != NULL) {
|
if (tun_device != NULL) {
|
||||||
strncpy(ifreq.ifr_name, tun_device, IFNAMSIZ);
|
strncpy(ifreq.ifr_name, tun_device, IFNAMSIZ);
|
||||||
ifreq.ifr_name[IFNAMSIZ-1] = '\0';
|
ifreq.ifr_name[IFNAMSIZ-1] = '\0';
|
||||||
strncpy(if_name, tun_device, sizeof(if_name));
|
strncpy(if_name, tun_device, sizeof(if_name));
|
||||||
if_name[sizeof(if_name)-1] = '\0';
|
if_name[sizeof(if_name)-1] = '\0';
|
||||||
|
|
||||||
if (ioctl(tun_fd, TUNSETIFF, (void *) &ifreq) != -1) {
|
if (ioctl(tun_fd, TUNSETIFF, (void *) &ifreq) != -1) {
|
||||||
fprintf(stderr, "Opened %s\n", ifreq.ifr_name);
|
fprintf(stderr, "Opened %s\n", ifreq.ifr_name);
|
||||||
fd_set_close_on_exec(tun_fd);
|
fd_set_close_on_exec(tun_fd);
|
||||||
return tun_fd;
|
return tun_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (errno != EBUSY) {
|
if (errno != EBUSY) {
|
||||||
warn("open_tun: ioctl[TUNSETIFF]");
|
warn("open_tun: ioctl[TUNSETIFF]");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; i < TUN_MAX_TRY; i++) {
|
for (i = 0; i < TUN_MAX_TRY; i++) {
|
||||||
snprintf(ifreq.ifr_name, IFNAMSIZ, "dns%d", i);
|
snprintf(ifreq.ifr_name, IFNAMSIZ, "dns%d", i);
|
||||||
|
|
||||||
if (ioctl(tun_fd, TUNSETIFF, (void *) &ifreq) != -1) {
|
if (ioctl(tun_fd, TUNSETIFF, (void *) &ifreq) != -1) {
|
||||||
fprintf(stderr, "Opened %s\n", ifreq.ifr_name);
|
fprintf(stderr, "Opened %s\n", ifreq.ifr_name);
|
||||||
snprintf(if_name, sizeof(if_name), "dns%d", i);
|
snprintf(if_name, sizeof(if_name), "dns%d", i);
|
||||||
fd_set_close_on_exec(tun_fd);
|
fd_set_close_on_exec(tun_fd);
|
||||||
return tun_fd;
|
return tun_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (errno != EBUSY) {
|
if (errno != EBUSY) {
|
||||||
warn("open_tun: ioctl[TUNSETIFF]");
|
warn("open_tun: ioctl[TUNSETIFF]");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
warn("open_tun: Couldn't set interface name");
|
warn("open_tun: Couldn't set interface name");
|
||||||
}
|
}
|
||||||
warn("error when opening tun");
|
warn("error when opening tun");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif WINDOWS32
|
#elif WINDOWS32
|
||||||
|
@ -133,184 +133,184 @@ open_tun(const char *tun_device)
|
||||||
static void
|
static void
|
||||||
get_device(char *device, int device_len, const char *wanted_dev)
|
get_device(char *device, int device_len, const char *wanted_dev)
|
||||||
{
|
{
|
||||||
LONG status;
|
LONG status;
|
||||||
HKEY adapter_key;
|
HKEY adapter_key;
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
index = 0;
|
index = 0;
|
||||||
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TAP_ADAPTER_KEY, 0, KEY_READ, &adapter_key);
|
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TAP_ADAPTER_KEY, 0, KEY_READ, &adapter_key);
|
||||||
|
|
||||||
if (status != ERROR_SUCCESS) {
|
if (status != ERROR_SUCCESS) {
|
||||||
warnx("Error opening registry key " TAP_ADAPTER_KEY );
|
warnx("Error opening registry key " TAP_ADAPTER_KEY );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (TRUE) {
|
while (TRUE) {
|
||||||
char name[256];
|
char name[256];
|
||||||
char unit[256];
|
char unit[256];
|
||||||
char component[256];
|
char component[256];
|
||||||
|
|
||||||
char cid_string[256] = KEY_COMPONENT_ID;
|
char cid_string[256] = KEY_COMPONENT_ID;
|
||||||
HKEY device_key;
|
HKEY device_key;
|
||||||
DWORD datatype;
|
DWORD datatype;
|
||||||
DWORD len;
|
DWORD len;
|
||||||
|
|
||||||
/* Iterate through all adapter of this kind */
|
/* Iterate through all adapter of this kind */
|
||||||
len = sizeof(name);
|
len = sizeof(name);
|
||||||
status = RegEnumKeyEx(adapter_key, index, name, &len, NULL, NULL, NULL, NULL);
|
status = RegEnumKeyEx(adapter_key, index, name, &len, NULL, NULL, NULL, NULL);
|
||||||
if (status == ERROR_NO_MORE_ITEMS) {
|
if (status == ERROR_NO_MORE_ITEMS) {
|
||||||
break;
|
break;
|
||||||
} else if (status != ERROR_SUCCESS) {
|
} else if (status != ERROR_SUCCESS) {
|
||||||
warnx("Error enumerating subkeys of registry key " TAP_ADAPTER_KEY );
|
warnx("Error enumerating subkeys of registry key " TAP_ADAPTER_KEY );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(unit, sizeof(unit), TAP_ADAPTER_KEY "\\%s", name);
|
snprintf(unit, sizeof(unit), TAP_ADAPTER_KEY "\\%s", name);
|
||||||
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, unit, 0, KEY_READ, &device_key);
|
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, unit, 0, KEY_READ, &device_key);
|
||||||
if (status != ERROR_SUCCESS) {
|
if (status != ERROR_SUCCESS) {
|
||||||
warnx("Error opening registry key %s", unit);
|
warnx("Error opening registry key %s", unit);
|
||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check component id */
|
/* Check component id */
|
||||||
len = sizeof(component);
|
len = sizeof(component);
|
||||||
status = RegQueryValueEx(device_key, cid_string, NULL, &datatype, (LPBYTE)component, &len);
|
status = RegQueryValueEx(device_key, cid_string, NULL, &datatype, (LPBYTE)component, &len);
|
||||||
if (status != ERROR_SUCCESS || datatype != REG_SZ) {
|
if (status != ERROR_SUCCESS || datatype != REG_SZ) {
|
||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
if (strncmp(TAP_VERSION_ID_0801, component, strlen(TAP_VERSION_ID_0801)) == 0 ||
|
if (strncmp(TAP_VERSION_ID_0801, component, strlen(TAP_VERSION_ID_0801)) == 0 ||
|
||||||
strncmp(TAP_VERSION_ID_0901, component, strlen(TAP_VERSION_ID_0901)) == 0) {
|
strncmp(TAP_VERSION_ID_0901, component, strlen(TAP_VERSION_ID_0901)) == 0) {
|
||||||
/* We found a TAP32 device, get its NetCfgInstanceId */
|
/* We found a TAP32 device, get its NetCfgInstanceId */
|
||||||
char iid_string[256] = NET_CFG_INST_ID;
|
char iid_string[256] = NET_CFG_INST_ID;
|
||||||
|
|
||||||
status = RegQueryValueEx(device_key, iid_string, NULL, &datatype, (LPBYTE) device, (DWORD *) &device_len);
|
status = RegQueryValueEx(device_key, iid_string, NULL, &datatype, (LPBYTE) device, (DWORD *) &device_len);
|
||||||
if (status != ERROR_SUCCESS || datatype != REG_SZ) {
|
if (status != ERROR_SUCCESS || datatype != REG_SZ) {
|
||||||
warnx("Error reading registry key %s\\%s on TAP device", unit, iid_string);
|
warnx("Error reading registry key %s\\%s on TAP device", unit, iid_string);
|
||||||
} else {
|
} else {
|
||||||
/* Done getting GUID of TAP device,
|
/* Done getting GUID of TAP device,
|
||||||
* now check if the name is the requested one */
|
* now check if the name is the requested one */
|
||||||
if (wanted_dev) {
|
if (wanted_dev) {
|
||||||
char name[250];
|
char name[250];
|
||||||
get_name(name, sizeof(name), device);
|
get_name(name, sizeof(name), device);
|
||||||
if (strncmp(name, wanted_dev, strlen(wanted_dev))) {
|
if (strncmp(name, wanted_dev, strlen(wanted_dev))) {
|
||||||
/* Skip if name mismatch */
|
/* Skip if name mismatch */
|
||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Get the if name */
|
/* Get the if name */
|
||||||
get_name(if_name, sizeof(if_name), device);
|
get_name(if_name, sizeof(if_name), device);
|
||||||
RegCloseKey(device_key);
|
RegCloseKey(device_key);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
next:
|
next:
|
||||||
RegCloseKey(device_key);
|
RegCloseKey(device_key);
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
RegCloseKey(adapter_key);
|
RegCloseKey(adapter_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
get_name(char *ifname, int namelen, char *dev_name)
|
get_name(char *ifname, int namelen, char *dev_name)
|
||||||
{
|
{
|
||||||
char path[256];
|
char path[256];
|
||||||
char name_str[256] = "Name";
|
char name_str[256] = "Name";
|
||||||
LONG status;
|
LONG status;
|
||||||
HKEY conn_key;
|
HKEY conn_key;
|
||||||
DWORD len;
|
DWORD len;
|
||||||
DWORD datatype;
|
DWORD datatype;
|
||||||
|
|
||||||
memset(ifname, 0, namelen);
|
memset(ifname, 0, namelen);
|
||||||
|
|
||||||
snprintf(path, sizeof(path), NETWORK_KEY "\\%s\\Connection", dev_name);
|
snprintf(path, sizeof(path), NETWORK_KEY "\\%s\\Connection", dev_name);
|
||||||
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, path, 0, KEY_READ, &conn_key);
|
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, path, 0, KEY_READ, &conn_key);
|
||||||
if (status != ERROR_SUCCESS) {
|
if (status != ERROR_SUCCESS) {
|
||||||
fprintf(stderr, "Could not look up name of interface %s: error opening key\n", dev_name);
|
fprintf(stderr, "Could not look up name of interface %s: error opening key\n", dev_name);
|
||||||
RegCloseKey(conn_key);
|
RegCloseKey(conn_key);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
len = namelen;
|
len = namelen;
|
||||||
status = RegQueryValueEx(conn_key, name_str, NULL, &datatype, (LPBYTE)ifname, &len);
|
status = RegQueryValueEx(conn_key, name_str, NULL, &datatype, (LPBYTE)ifname, &len);
|
||||||
if (status != ERROR_SUCCESS || datatype != REG_SZ) {
|
if (status != ERROR_SUCCESS || datatype != REG_SZ) {
|
||||||
fprintf(stderr, "Could not look up name of interface %s: error reading value\n", dev_name);
|
fprintf(stderr, "Could not look up name of interface %s: error reading value\n", dev_name);
|
||||||
RegCloseKey(conn_key);
|
RegCloseKey(conn_key);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
RegCloseKey(conn_key);
|
RegCloseKey(conn_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD WINAPI tun_reader(LPVOID arg)
|
DWORD WINAPI tun_reader(LPVOID arg)
|
||||||
{
|
{
|
||||||
struct tun_data *tun = arg;
|
struct tun_data *tun = arg;
|
||||||
char buf[64*1024];
|
char buf[64*1024];
|
||||||
int len;
|
int len;
|
||||||
int res;
|
int res;
|
||||||
OVERLAPPED olpd;
|
OVERLAPPED olpd;
|
||||||
int sock;
|
int sock;
|
||||||
|
|
||||||
sock = open_dns_from_host("127.0.0.1", 0, AF_INET, 0);
|
sock = open_dns_from_host("127.0.0.1", 0, AF_INET, 0);
|
||||||
|
|
||||||
olpd.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
olpd.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||||
|
|
||||||
while(TRUE) {
|
while(TRUE) {
|
||||||
olpd.Offset = 0;
|
olpd.Offset = 0;
|
||||||
olpd.OffsetHigh = 0;
|
olpd.OffsetHigh = 0;
|
||||||
res = ReadFile(tun->tun, buf, sizeof(buf), (LPDWORD) &len, &olpd);
|
res = ReadFile(tun->tun, buf, sizeof(buf), (LPDWORD) &len, &olpd);
|
||||||
if (!res) {
|
if (!res) {
|
||||||
WaitForSingleObject(olpd.hEvent, INFINITE);
|
WaitForSingleObject(olpd.hEvent, INFINITE);
|
||||||
res = GetOverlappedResult(dev_handle, &olpd, (LPDWORD) &len, FALSE);
|
res = GetOverlappedResult(dev_handle, &olpd, (LPDWORD) &len, FALSE);
|
||||||
res = sendto(sock, buf, len, 0, (struct sockaddr*) &(tun->addr),
|
res = sendto(sock, buf, len, 0, (struct sockaddr*) &(tun->addr),
|
||||||
tun->addrlen);
|
tun->addrlen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
open_tun(const char *tun_device)
|
open_tun(const char *tun_device)
|
||||||
{
|
{
|
||||||
char adapter[256];
|
char adapter[256];
|
||||||
char tapfile[512];
|
char tapfile[512];
|
||||||
int tunfd;
|
int tunfd;
|
||||||
struct sockaddr_storage localsock;
|
struct sockaddr_storage localsock;
|
||||||
int localsock_len;
|
int localsock_len;
|
||||||
|
|
||||||
memset(adapter, 0, sizeof(adapter));
|
memset(adapter, 0, sizeof(adapter));
|
||||||
memset(if_name, 0, sizeof(if_name));
|
memset(if_name, 0, sizeof(if_name));
|
||||||
get_device(adapter, sizeof(adapter), tun_device);
|
get_device(adapter, sizeof(adapter), tun_device);
|
||||||
|
|
||||||
if (strlen(adapter) == 0 || strlen(if_name) == 0) {
|
if (strlen(adapter) == 0 || strlen(if_name) == 0) {
|
||||||
if (tun_device) {
|
if (tun_device) {
|
||||||
warnx("No TAP adapters found. Try without -d.");
|
warnx("No TAP adapters found. Try without -d.");
|
||||||
} else {
|
} else {
|
||||||
warnx("No TAP adapters found. Version 0801 and 0901 are supported.");
|
warnx("No TAP adapters found. Version 0801 and 0901 are supported.");
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "Opening device %s\n", if_name);
|
fprintf(stderr, "Opening device %s\n", if_name);
|
||||||
snprintf(tapfile, sizeof(tapfile), "%s%s.tap", TAP_DEVICE_SPACE, adapter);
|
snprintf(tapfile, sizeof(tapfile), "%s%s.tap", TAP_DEVICE_SPACE, adapter);
|
||||||
dev_handle = CreateFile(tapfile, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, NULL);
|
dev_handle = CreateFile(tapfile, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, NULL);
|
||||||
if (dev_handle == INVALID_HANDLE_VALUE) {
|
if (dev_handle == INVALID_HANDLE_VALUE) {
|
||||||
warnx("Could not open device!");
|
warnx("Could not open device!");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Use a UDP connection to forward packets from tun,
|
/* Use a UDP connection to forward packets from tun,
|
||||||
* so we can still use select() in main code.
|
* so we can still use select() in main code.
|
||||||
* A thread does blocking reads on tun device and
|
* A thread does blocking reads on tun device and
|
||||||
* sends data as udp to this socket */
|
* sends data as udp to this socket */
|
||||||
|
|
||||||
localsock_len = get_addr("127.0.0.1", 55353, AF_INET, 0, &localsock);
|
localsock_len = get_addr("127.0.0.1", 55353, AF_INET, 0, &localsock);
|
||||||
tunfd = open_dns(&localsock, localsock_len);
|
tunfd = open_dns(&localsock, localsock_len);
|
||||||
|
|
||||||
data.tun = dev_handle;
|
data.tun = dev_handle;
|
||||||
memcpy(&(data.addr), &localsock, localsock_len);
|
memcpy(&(data.addr), &localsock, localsock_len);
|
||||||
data.addrlen = localsock_len;
|
data.addrlen = localsock_len;
|
||||||
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)tun_reader, &data, 0, NULL);
|
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)tun_reader, &data, 0, NULL);
|
||||||
|
|
||||||
return tunfd;
|
return tunfd;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* BSD and friends */
|
#else /* BSD and friends */
|
||||||
|
@ -318,42 +318,42 @@ open_tun(const char *tun_device)
|
||||||
int
|
int
|
||||||
open_tun(const char *tun_device)
|
open_tun(const char *tun_device)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int tun_fd;
|
int tun_fd;
|
||||||
char tun_name[50];
|
char tun_name[50];
|
||||||
|
|
||||||
if (tun_device != NULL) {
|
if (tun_device != NULL) {
|
||||||
snprintf(tun_name, sizeof(tun_name), "/dev/%s", tun_device);
|
snprintf(tun_name, sizeof(tun_name), "/dev/%s", tun_device);
|
||||||
strncpy(if_name, tun_device, sizeof(if_name));
|
strncpy(if_name, tun_device, sizeof(if_name));
|
||||||
if_name[sizeof(if_name)-1] = '\0';
|
if_name[sizeof(if_name)-1] = '\0';
|
||||||
|
|
||||||
if ((tun_fd = open(tun_name, O_RDWR)) < 0) {
|
if ((tun_fd = open(tun_name, O_RDWR)) < 0) {
|
||||||
warn("open_tun: %s", tun_name);
|
warn("open_tun: %s", tun_name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "Opened %s\n", tun_name);
|
fprintf(stderr, "Opened %s\n", tun_name);
|
||||||
fd_set_close_on_exec(tun_fd);
|
fd_set_close_on_exec(tun_fd);
|
||||||
return tun_fd;
|
return tun_fd;
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; i < TUN_MAX_TRY; i++) {
|
for (i = 0; i < TUN_MAX_TRY; i++) {
|
||||||
snprintf(tun_name, sizeof(tun_name), "/dev/tun%d", i);
|
snprintf(tun_name, sizeof(tun_name), "/dev/tun%d", i);
|
||||||
|
|
||||||
if ((tun_fd = open(tun_name, O_RDWR)) >= 0) {
|
if ((tun_fd = open(tun_name, O_RDWR)) >= 0) {
|
||||||
fprintf(stderr, "Opened %s\n", tun_name);
|
fprintf(stderr, "Opened %s\n", tun_name);
|
||||||
snprintf(if_name, sizeof(if_name), "tun%d", i);
|
snprintf(if_name, sizeof(if_name), "tun%d", i);
|
||||||
fd_set_close_on_exec(tun_fd);
|
fd_set_close_on_exec(tun_fd);
|
||||||
return tun_fd;
|
return tun_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (errno == ENOENT)
|
if (errno == ENOENT)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
warn("open_tun: Failed to open tunneling device");
|
warn("open_tun: Failed to open tunneling device");
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -361,92 +361,92 @@ open_tun(const char *tun_device)
|
||||||
void
|
void
|
||||||
close_tun(int tun_fd)
|
close_tun(int tun_fd)
|
||||||
{
|
{
|
||||||
if (tun_fd >= 0)
|
if (tun_fd >= 0)
|
||||||
close(tun_fd);
|
close(tun_fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WINDOWS32
|
#ifdef WINDOWS32
|
||||||
int
|
int
|
||||||
write_tun(int tun_fd, char *data, size_t len)
|
write_tun(int tun_fd, char *data, size_t len)
|
||||||
{
|
{
|
||||||
DWORD written;
|
DWORD written;
|
||||||
DWORD res;
|
DWORD res;
|
||||||
OVERLAPPED olpd;
|
OVERLAPPED olpd;
|
||||||
|
|
||||||
data += 4;
|
data += 4;
|
||||||
len -= 4;
|
len -= 4;
|
||||||
|
|
||||||
olpd.Offset = 0;
|
olpd.Offset = 0;
|
||||||
olpd.OffsetHigh = 0;
|
olpd.OffsetHigh = 0;
|
||||||
olpd.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
olpd.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||||
res = WriteFile(dev_handle, data, len, &written, &olpd);
|
res = WriteFile(dev_handle, data, len, &written, &olpd);
|
||||||
if (!res && GetLastError() == ERROR_IO_PENDING) {
|
if (!res && GetLastError() == ERROR_IO_PENDING) {
|
||||||
WaitForSingleObject(olpd.hEvent, INFINITE);
|
WaitForSingleObject(olpd.hEvent, INFINITE);
|
||||||
res = GetOverlappedResult(dev_handle, &olpd, &written, FALSE);
|
res = GetOverlappedResult(dev_handle, &olpd, &written, FALSE);
|
||||||
if (written != len) {
|
if (written != len) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t
|
ssize_t
|
||||||
read_tun(int tun_fd, char *buf, size_t len)
|
read_tun(int tun_fd, char *buf, size_t len)
|
||||||
{
|
{
|
||||||
int bytes;
|
int bytes;
|
||||||
memset(buf, 0, 4);
|
memset(buf, 0, 4);
|
||||||
|
|
||||||
bytes = recv(tun_fd, buf + 4, len - 4, 0);
|
bytes = recv(tun_fd, buf + 4, len - 4, 0);
|
||||||
if (bytes < 0) {
|
if (bytes < 0) {
|
||||||
return bytes;
|
return bytes;
|
||||||
} else {
|
} else {
|
||||||
return bytes + 4;
|
return bytes + 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
int
|
int
|
||||||
write_tun(int tun_fd, char *data, size_t len)
|
write_tun(int tun_fd, char *data, size_t len)
|
||||||
{
|
{
|
||||||
#if defined (FREEBSD) || defined (DARWIN) || defined(NETBSD)
|
#if defined (FREEBSD) || defined (DARWIN) || defined(NETBSD)
|
||||||
data += 4;
|
data += 4;
|
||||||
len -= 4;
|
len -= 4;
|
||||||
#else /* !FREEBSD/DARWIN */
|
#else /* !FREEBSD/DARWIN */
|
||||||
#ifdef LINUX
|
#ifdef LINUX
|
||||||
data[0] = 0x00;
|
data[0] = 0x00;
|
||||||
data[1] = 0x00;
|
data[1] = 0x00;
|
||||||
data[2] = 0x08;
|
data[2] = 0x08;
|
||||||
data[3] = 0x00;
|
data[3] = 0x00;
|
||||||
#else /* OPENBSD */
|
#else /* OPENBSD */
|
||||||
data[0] = 0x00;
|
data[0] = 0x00;
|
||||||
data[1] = 0x00;
|
data[1] = 0x00;
|
||||||
data[2] = 0x00;
|
data[2] = 0x00;
|
||||||
data[3] = 0x02;
|
data[3] = 0x02;
|
||||||
#endif /* !LINUX */
|
#endif /* !LINUX */
|
||||||
#endif /* FREEBSD */
|
#endif /* FREEBSD */
|
||||||
|
|
||||||
if (write(tun_fd, data, len) != len) {
|
if (write(tun_fd, data, len) != len) {
|
||||||
warn("write_tun");
|
warn("write_tun");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t
|
ssize_t
|
||||||
read_tun(int tun_fd, char *buf, size_t len)
|
read_tun(int tun_fd, char *buf, size_t len)
|
||||||
{
|
{
|
||||||
#if defined (FREEBSD) || defined (DARWIN) || defined(NETBSD)
|
#if defined (FREEBSD) || defined (DARWIN) || defined(NETBSD)
|
||||||
/* FreeBSD/Darwin/NetBSD has no header */
|
/* FreeBSD/Darwin/NetBSD has no header */
|
||||||
int bytes;
|
int bytes;
|
||||||
memset(buf, 0, 4);
|
memset(buf, 0, 4);
|
||||||
|
|
||||||
bytes = read(tun_fd, buf + 4, len - 4);
|
bytes = read(tun_fd, buf + 4, len - 4);
|
||||||
if (bytes < 0) {
|
if (bytes < 0) {
|
||||||
return bytes;
|
return bytes;
|
||||||
} else {
|
} else {
|
||||||
return bytes + 4;
|
return bytes + 4;
|
||||||
}
|
}
|
||||||
#else /* !FREEBSD */
|
#else /* !FREEBSD */
|
||||||
return read(tun_fd, buf, len);
|
return read(tun_fd, buf, len);
|
||||||
#endif /* !FREEBSD */
|
#endif /* !FREEBSD */
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -454,98 +454,98 @@ read_tun(int tun_fd, char *buf, size_t len)
|
||||||
int
|
int
|
||||||
tun_setip(const char *ip, const char *other_ip, int netbits)
|
tun_setip(const char *ip, const char *other_ip, int netbits)
|
||||||
{
|
{
|
||||||
char cmdline[512];
|
char cmdline[512];
|
||||||
int netmask;
|
int netmask;
|
||||||
struct in_addr net;
|
struct in_addr net;
|
||||||
int i;
|
int i;
|
||||||
#ifndef LINUX
|
#ifndef LINUX
|
||||||
int r;
|
int r;
|
||||||
#endif
|
#endif
|
||||||
#ifdef WINDOWS32
|
#ifdef WINDOWS32
|
||||||
DWORD status;
|
DWORD status;
|
||||||
DWORD ipdata[3];
|
DWORD ipdata[3];
|
||||||
struct in_addr addr;
|
struct in_addr addr;
|
||||||
DWORD len;
|
DWORD len;
|
||||||
#else
|
#else
|
||||||
const char *display_ip;
|
const char *display_ip;
|
||||||
#ifndef LINUX
|
#ifndef LINUX
|
||||||
struct in_addr netip;
|
struct in_addr netip;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
netmask = 0;
|
netmask = 0;
|
||||||
for (i = 0; i < netbits; i++) {
|
for (i = 0; i < netbits; i++) {
|
||||||
netmask = (netmask << 1) | 1;
|
netmask = (netmask << 1) | 1;
|
||||||
}
|
}
|
||||||
netmask <<= (32 - netbits);
|
netmask <<= (32 - netbits);
|
||||||
net.s_addr = htonl(netmask);
|
net.s_addr = htonl(netmask);
|
||||||
|
|
||||||
if (inet_addr(ip) == INADDR_NONE) {
|
if (inet_addr(ip) == INADDR_NONE) {
|
||||||
fprintf(stderr, "Invalid IP: %s!\n", ip);
|
fprintf(stderr, "Invalid IP: %s!\n", ip);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#ifndef WINDOWS32
|
#ifndef WINDOWS32
|
||||||
# ifdef FREEBSD
|
# ifdef FREEBSD
|
||||||
display_ip = other_ip; /* FreeBSD wants other IP as second IP */
|
display_ip = other_ip; /* FreeBSD wants other IP as second IP */
|
||||||
# else
|
# else
|
||||||
display_ip = ip;
|
display_ip = ip;
|
||||||
# endif
|
# endif
|
||||||
snprintf(cmdline, sizeof(cmdline),
|
snprintf(cmdline, sizeof(cmdline),
|
||||||
IFCONFIGPATH "ifconfig %s %s %s netmask %s",
|
IFCONFIGPATH "ifconfig %s %s %s netmask %s",
|
||||||
if_name,
|
if_name,
|
||||||
ip,
|
ip,
|
||||||
display_ip,
|
display_ip,
|
||||||
inet_ntoa(net));
|
inet_ntoa(net));
|
||||||
|
|
||||||
fprintf(stderr, "Setting IP of %s to %s\n", if_name, ip);
|
fprintf(stderr, "Setting IP of %s to %s\n", if_name, ip);
|
||||||
#ifndef LINUX
|
#ifndef LINUX
|
||||||
netip.s_addr = inet_addr(ip);
|
netip.s_addr = inet_addr(ip);
|
||||||
netip.s_addr = netip.s_addr & net.s_addr;
|
netip.s_addr = netip.s_addr & net.s_addr;
|
||||||
r = system(cmdline);
|
r = system(cmdline);
|
||||||
if(r != 0) {
|
if(r != 0) {
|
||||||
return r;
|
return r;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
snprintf(cmdline, sizeof(cmdline),
|
snprintf(cmdline, sizeof(cmdline),
|
||||||
"/sbin/route add %s/%d %s",
|
"/sbin/route add %s/%d %s",
|
||||||
inet_ntoa(netip), netbits, ip);
|
inet_ntoa(netip), netbits, ip);
|
||||||
}
|
}
|
||||||
fprintf(stderr, "Adding route %s/%d to %s\n", inet_ntoa(netip), netbits, ip);
|
fprintf(stderr, "Adding route %s/%d to %s\n", inet_ntoa(netip), netbits, ip);
|
||||||
#endif
|
#endif
|
||||||
return system(cmdline);
|
return system(cmdline);
|
||||||
#else /* WINDOWS32 */
|
#else /* WINDOWS32 */
|
||||||
|
|
||||||
/* Set device as connected */
|
/* Set device as connected */
|
||||||
fprintf(stderr, "Enabling interface '%s'\n", if_name);
|
fprintf(stderr, "Enabling interface '%s'\n", if_name);
|
||||||
status = 1;
|
status = 1;
|
||||||
r = DeviceIoControl(dev_handle, TAP_IOCTL_SET_MEDIA_STATUS, &status,
|
r = DeviceIoControl(dev_handle, TAP_IOCTL_SET_MEDIA_STATUS, &status,
|
||||||
sizeof(status), &status, sizeof(status), &len, NULL);
|
sizeof(status), &status, sizeof(status), &len, NULL);
|
||||||
if (!r) {
|
if (!r) {
|
||||||
fprintf(stderr, "Failed to enable interface\n");
|
fprintf(stderr, "Failed to enable interface\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inet_aton(ip, &addr)) {
|
if (inet_aton(ip, &addr)) {
|
||||||
ipdata[0] = (DWORD) addr.s_addr; /* local ip addr */
|
ipdata[0] = (DWORD) addr.s_addr; /* local ip addr */
|
||||||
ipdata[1] = net.s_addr & ipdata[0]; /* network addr */
|
ipdata[1] = net.s_addr & ipdata[0]; /* network addr */
|
||||||
ipdata[2] = (DWORD) net.s_addr; /* netmask */
|
ipdata[2] = (DWORD) net.s_addr; /* netmask */
|
||||||
} else {
|
} else {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Tell ip/networkaddr/netmask to device for arp use */
|
/* Tell ip/networkaddr/netmask to device for arp use */
|
||||||
r = DeviceIoControl(dev_handle, TAP_IOCTL_CONFIG_TUN, &ipdata,
|
r = DeviceIoControl(dev_handle, TAP_IOCTL_CONFIG_TUN, &ipdata,
|
||||||
sizeof(ipdata), &ipdata, sizeof(ipdata), &len, NULL);
|
sizeof(ipdata), &ipdata, sizeof(ipdata), &len, NULL);
|
||||||
if (!r) {
|
if (!r) {
|
||||||
fprintf(stderr, "Failed to set interface in TUN mode\n");
|
fprintf(stderr, "Failed to set interface in TUN mode\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* use netsh to set ip address */
|
/* use netsh to set ip address */
|
||||||
fprintf(stderr, "Setting IP of interface '%s' to %s (can take a few seconds)...\n", if_name, ip);
|
fprintf(stderr, "Setting IP of interface '%s' to %s (can take a few seconds)...\n", if_name, ip);
|
||||||
snprintf(cmdline, sizeof(cmdline), "netsh interface ip set address \"%s\" static %s %s",
|
snprintf(cmdline, sizeof(cmdline), "netsh interface ip set address \"%s\" static %s %s",
|
||||||
if_name, ip, inet_ntoa(net));
|
if_name, ip, inet_ntoa(net));
|
||||||
return system(cmdline);
|
return system(cmdline);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -553,24 +553,24 @@ int
|
||||||
tun_setmtu(const unsigned mtu)
|
tun_setmtu(const unsigned mtu)
|
||||||
{
|
{
|
||||||
#ifndef WINDOWS32
|
#ifndef WINDOWS32
|
||||||
char cmdline[512];
|
char cmdline[512];
|
||||||
|
|
||||||
if (mtu > 200 && mtu <= 1500) {
|
if (mtu > 200 && mtu <= 1500) {
|
||||||
snprintf(cmdline, sizeof(cmdline),
|
snprintf(cmdline, sizeof(cmdline),
|
||||||
IFCONFIGPATH "ifconfig %s mtu %u",
|
IFCONFIGPATH "ifconfig %s mtu %u",
|
||||||
if_name,
|
if_name,
|
||||||
mtu);
|
mtu);
|
||||||
|
|
||||||
fprintf(stderr, "Setting MTU of %s to %u\n", if_name, mtu);
|
fprintf(stderr, "Setting MTU of %s to %u\n", if_name, mtu);
|
||||||
return system(cmdline);
|
return system(cmdline);
|
||||||
} else {
|
} else {
|
||||||
warn("MTU out of range: %u\n", mtu);
|
warn("MTU out of range: %u\n", mtu);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
#else /* WINDOWS32 */
|
#else /* WINDOWS32 */
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
212
src/user.c
212
src/user.c
|
@ -40,94 +40,94 @@ unsigned usercount;
|
||||||
int
|
int
|
||||||
init_users(in_addr_t my_ip, int netbits)
|
init_users(in_addr_t my_ip, int netbits)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int skip = 0;
|
int skip = 0;
|
||||||
char newip[16];
|
char newip[16];
|
||||||
|
|
||||||
int maxusers;
|
int maxusers;
|
||||||
|
|
||||||
in_addr_t netmask = 0;
|
in_addr_t netmask = 0;
|
||||||
struct in_addr net;
|
struct in_addr net;
|
||||||
struct in_addr ipstart;
|
struct in_addr ipstart;
|
||||||
|
|
||||||
for (i = 0; i < netbits; i++) {
|
for (i = 0; i < netbits; i++) {
|
||||||
netmask = (netmask << 1) | 1;
|
netmask = (netmask << 1) | 1;
|
||||||
}
|
}
|
||||||
netmask <<= (32 - netbits);
|
netmask <<= (32 - netbits);
|
||||||
net.s_addr = htonl(netmask);
|
net.s_addr = htonl(netmask);
|
||||||
ipstart.s_addr = my_ip & net.s_addr;
|
ipstart.s_addr = my_ip & net.s_addr;
|
||||||
|
|
||||||
maxusers = (1 << (32-netbits)) - 3; /* 3: Net addr, broadcast addr, iodined addr */
|
maxusers = (1 << (32-netbits)) - 3; /* 3: Net addr, broadcast addr, iodined addr */
|
||||||
usercount = MIN(maxusers, USERS);
|
usercount = MIN(maxusers, USERS);
|
||||||
|
|
||||||
users = calloc(usercount, sizeof(struct tun_user));
|
users = calloc(usercount, sizeof(struct tun_user));
|
||||||
for (i = 0; i < usercount; i++) {
|
for (i = 0; i < usercount; i++) {
|
||||||
in_addr_t ip;
|
in_addr_t ip;
|
||||||
users[i].id = i;
|
users[i].id = i;
|
||||||
snprintf(newip, sizeof(newip), "0.0.0.%d", i + skip + 1);
|
snprintf(newip, sizeof(newip), "0.0.0.%d", i + skip + 1);
|
||||||
ip = ipstart.s_addr + inet_addr(newip);
|
ip = ipstart.s_addr + inet_addr(newip);
|
||||||
if (ip == my_ip && skip == 0) {
|
if (ip == my_ip && skip == 0) {
|
||||||
/* This IP was taken by iodined */
|
/* This IP was taken by iodined */
|
||||||
skip++;
|
skip++;
|
||||||
snprintf(newip, sizeof(newip), "0.0.0.%d", i + skip + 1);
|
snprintf(newip, sizeof(newip), "0.0.0.%d", i + skip + 1);
|
||||||
ip = ipstart.s_addr + inet_addr(newip);
|
ip = ipstart.s_addr + inet_addr(newip);
|
||||||
}
|
}
|
||||||
users[i].tun_ip = ip;
|
users[i].tun_ip = ip;
|
||||||
net.s_addr = ip;
|
net.s_addr = ip;
|
||||||
users[i].disabled = 0;
|
users[i].disabled = 0;
|
||||||
users[i].authenticated = 0;
|
users[i].authenticated = 0;
|
||||||
users[i].authenticated_raw = 0;
|
users[i].authenticated_raw = 0;
|
||||||
users[i].active = 0;
|
users[i].active = 0;
|
||||||
/* Rest is reset on login ('V' packet) */
|
/* Rest is reset on login ('V' packet) */
|
||||||
}
|
}
|
||||||
|
|
||||||
return usercount;
|
return usercount;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char*
|
const char*
|
||||||
users_get_first_ip()
|
users_get_first_ip()
|
||||||
{
|
{
|
||||||
struct in_addr ip;
|
struct in_addr ip;
|
||||||
ip.s_addr = users[0].tun_ip;
|
ip.s_addr = users[0].tun_ip;
|
||||||
return strdup(inet_ntoa(ip));
|
return strdup(inet_ntoa(ip));
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
users_waiting_on_reply()
|
users_waiting_on_reply()
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
for (i = 0; i < usercount; i++) {
|
for (i = 0; i < usercount; i++) {
|
||||||
if (users[i].active && !users[i].disabled &&
|
if (users[i].active && !users[i].disabled &&
|
||||||
users[i].last_pkt + 60 > time(NULL) &&
|
users[i].last_pkt + 60 > time(NULL) &&
|
||||||
users[i].q.id != 0 && users[i].conn == CONN_DNS_NULL) {
|
users[i].q.id != 0 && users[i].conn == CONN_DNS_NULL) {
|
||||||
ret++;
|
ret++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
find_user_by_ip(uint32_t ip)
|
find_user_by_ip(uint32_t ip)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
ret = -1;
|
ret = -1;
|
||||||
for (i = 0; i < usercount; i++) {
|
for (i = 0; i < usercount; i++) {
|
||||||
if (users[i].active &&
|
if (users[i].active &&
|
||||||
users[i].authenticated &&
|
users[i].authenticated &&
|
||||||
!users[i].disabled &&
|
!users[i].disabled &&
|
||||||
users[i].last_pkt + 60 > time(NULL) &&
|
users[i].last_pkt + 60 > time(NULL) &&
|
||||||
ip == users[i].tun_ip) {
|
ip == users[i].tun_ip) {
|
||||||
ret = i;
|
ret = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -138,70 +138,70 @@ all_users_waiting_to_send()
|
||||||
without going through another select loop.
|
without going through another select loop.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
time_t now;
|
time_t now;
|
||||||
int ret;
|
int ret;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
ret = 1;
|
ret = 1;
|
||||||
now = time(NULL);
|
now = time(NULL);
|
||||||
for (i = 0; i < usercount; i++) {
|
for (i = 0; i < usercount; i++) {
|
||||||
if (users[i].active && !users[i].disabled &&
|
if (users[i].active && !users[i].disabled &&
|
||||||
users[i].last_pkt + 60 > now &&
|
users[i].last_pkt + 60 > now &&
|
||||||
((users[i].conn == CONN_RAW_UDP) ||
|
((users[i].conn == CONN_RAW_UDP) ||
|
||||||
((users[i].conn == CONN_DNS_NULL)
|
((users[i].conn == CONN_DNS_NULL)
|
||||||
#ifdef OUTPACKETQ_LEN
|
#ifdef OUTPACKETQ_LEN
|
||||||
&& users[i].outpacketq_filled < 1
|
&& users[i].outpacketq_filled < 1
|
||||||
#else
|
#else
|
||||||
&& users[i].outpacket.len == 0
|
&& users[i].outpacket.len == 0
|
||||||
#endif
|
#endif
|
||||||
))) {
|
))) {
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
find_available_user()
|
find_available_user()
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < usercount; i++) {
|
for (i = 0; i < usercount; i++) {
|
||||||
/* Not used at all or not used in one minute */
|
/* Not used at all or not used in one minute */
|
||||||
if ((!users[i].active || users[i].last_pkt + 60 < time(NULL)) && !users[i].disabled) {
|
if ((!users[i].active || users[i].last_pkt + 60 < time(NULL)) && !users[i].disabled) {
|
||||||
users[i].active = 1;
|
users[i].active = 1;
|
||||||
users[i].authenticated = 0;
|
users[i].authenticated = 0;
|
||||||
users[i].authenticated_raw = 0;
|
users[i].authenticated_raw = 0;
|
||||||
users[i].last_pkt = time(NULL);
|
users[i].last_pkt = time(NULL);
|
||||||
users[i].fragsize = 4096;
|
users[i].fragsize = 4096;
|
||||||
users[i].conn = CONN_DNS_NULL;
|
users[i].conn = CONN_DNS_NULL;
|
||||||
ret = i;
|
ret = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
user_switch_codec(int userid, struct encoder *enc)
|
user_switch_codec(int userid, struct encoder *enc)
|
||||||
{
|
{
|
||||||
if (userid < 0 || userid >= usercount)
|
if (userid < 0 || userid >= usercount)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
users[userid].encoder = enc;
|
users[userid].encoder = enc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
user_set_conn_type(int userid, enum connection c)
|
user_set_conn_type(int userid, enum connection c)
|
||||||
{
|
{
|
||||||
if (userid < 0 || userid >= usercount)
|
if (userid < 0 || userid >= usercount)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (c < 0 || c >= CONN_MAX)
|
if (c < 0 || c >= CONN_MAX)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
users[userid].conn = c;
|
users[userid].conn = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
72
src/user.h
72
src/user.h
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
#define USERS 16
|
#define USERS 16
|
||||||
|
|
||||||
#define OUTPACKETQ_LEN 4 /* Note: 16 users * 1 packet = 1MB */
|
#define OUTPACKETQ_LEN 4 /* Note: 16 users * 1 packet = 1MB */
|
||||||
/* Undefine to have no queue for packets coming in from tun device, which may
|
/* Undefine to have no queue for packets coming in from tun device, which may
|
||||||
lead to massive dropping in multi-user situations with high traffic. */
|
lead to massive dropping in multi-user situations with high traffic. */
|
||||||
|
|
||||||
|
@ -35,44 +35,44 @@
|
||||||
/* Max advisable: 36/2 = 18. Total mem usage: QMEMDATA_LEN * USERS * 6 bytes */
|
/* Max advisable: 36/2 = 18. Total mem usage: QMEMDATA_LEN * USERS * 6 bytes */
|
||||||
|
|
||||||
struct tun_user {
|
struct tun_user {
|
||||||
char id;
|
char id;
|
||||||
int active;
|
int active;
|
||||||
int authenticated;
|
int authenticated;
|
||||||
int authenticated_raw;
|
int authenticated_raw;
|
||||||
int disabled;
|
int disabled;
|
||||||
time_t last_pkt;
|
time_t last_pkt;
|
||||||
int seed;
|
int seed;
|
||||||
in_addr_t tun_ip;
|
in_addr_t tun_ip;
|
||||||
struct in_addr host;
|
struct in_addr host;
|
||||||
struct query q;
|
struct query q;
|
||||||
struct query q_sendrealsoon;
|
struct query q_sendrealsoon;
|
||||||
int q_sendrealsoon_new;
|
int q_sendrealsoon_new;
|
||||||
struct packet inpacket;
|
struct packet inpacket;
|
||||||
struct packet outpacket;
|
struct packet outpacket;
|
||||||
int outfragresent;
|
int outfragresent;
|
||||||
struct encoder *encoder;
|
struct encoder *encoder;
|
||||||
char downenc;
|
char downenc;
|
||||||
int out_acked_seqno;
|
int out_acked_seqno;
|
||||||
int out_acked_fragment;
|
int out_acked_fragment;
|
||||||
int fragsize;
|
int fragsize;
|
||||||
enum connection conn;
|
enum connection conn;
|
||||||
int lazy;
|
int lazy;
|
||||||
unsigned char qmemping_cmc[QMEMPING_LEN * 4];
|
unsigned char qmemping_cmc[QMEMPING_LEN * 4];
|
||||||
unsigned short qmemping_type[QMEMPING_LEN];
|
unsigned short qmemping_type[QMEMPING_LEN];
|
||||||
int qmemping_lastfilled;
|
int qmemping_lastfilled;
|
||||||
unsigned char qmemdata_cmc[QMEMDATA_LEN * 4];
|
unsigned char qmemdata_cmc[QMEMDATA_LEN * 4];
|
||||||
unsigned short qmemdata_type[QMEMDATA_LEN];
|
unsigned short qmemdata_type[QMEMDATA_LEN];
|
||||||
int qmemdata_lastfilled;
|
int qmemdata_lastfilled;
|
||||||
#ifdef OUTPACKETQ_LEN
|
#ifdef OUTPACKETQ_LEN
|
||||||
struct packet outpacketq[OUTPACKETQ_LEN];
|
struct packet outpacketq[OUTPACKETQ_LEN];
|
||||||
int outpacketq_nexttouse;
|
int outpacketq_nexttouse;
|
||||||
int outpacketq_filled;
|
int outpacketq_filled;
|
||||||
#endif
|
#endif
|
||||||
#ifdef DNSCACHE_LEN
|
#ifdef DNSCACHE_LEN
|
||||||
struct query dnscache_q[DNSCACHE_LEN];
|
struct query dnscache_q[DNSCACHE_LEN];
|
||||||
char dnscache_answer[DNSCACHE_LEN][4096];
|
char dnscache_answer[DNSCACHE_LEN][4096];
|
||||||
int dnscache_answerlen[DNSCACHE_LEN];
|
int dnscache_answerlen[DNSCACHE_LEN];
|
||||||
int dnscache_lastfilled;
|
int dnscache_lastfilled;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
90
src/util.c
90
src/util.c
|
@ -21,62 +21,62 @@
|
||||||
char *
|
char *
|
||||||
get_resolvconf_addr()
|
get_resolvconf_addr()
|
||||||
{
|
{
|
||||||
static char addr[16];
|
static char addr[16];
|
||||||
char *rv;
|
char *rv;
|
||||||
#ifndef WINDOWS32
|
#ifndef WINDOWS32
|
||||||
char buf[80];
|
char buf[80];
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
fp = popen("getprop net.dns1", "r");
|
fp = popen("getprop net.dns1", "r");
|
||||||
if (fp == NULL)
|
if (fp == NULL)
|
||||||
err(1, "getprop net.dns1 failed");
|
err(1, "getprop net.dns1 failed");
|
||||||
if (fgets(buf, sizeof(buf), fp) == NULL)
|
if (fgets(buf, sizeof(buf), fp) == NULL)
|
||||||
err(1, "read getprop net.dns1 failed");
|
err(1, "read getprop net.dns1 failed");
|
||||||
if (sscanf(buf, "%15s", addr) == 1)
|
if (sscanf(buf, "%15s", addr) == 1)
|
||||||
rv = addr;
|
rv = addr;
|
||||||
pclose(fp);
|
pclose(fp);
|
||||||
#else
|
#else
|
||||||
|
|
||||||
rv = NULL;
|
rv = NULL;
|
||||||
|
|
||||||
if ((fp = fopen("/etc/resolv.conf", "r")) == NULL)
|
if ((fp = fopen("/etc/resolv.conf", "r")) == NULL)
|
||||||
err(1, "/etc/resolv.conf");
|
err(1, "/etc/resolv.conf");
|
||||||
|
|
||||||
while (feof(fp) == 0) {
|
while (feof(fp) == 0) {
|
||||||
fgets(buf, sizeof(buf), fp);
|
fgets(buf, sizeof(buf), fp);
|
||||||
|
|
||||||
if (sscanf(buf, "nameserver %15s", addr) == 1) {
|
if (sscanf(buf, "nameserver %15s", addr) == 1) {
|
||||||
rv = addr;
|
rv = addr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
#endif
|
#endif
|
||||||
#else /* !WINDOWS32 */
|
#else /* !WINDOWS32 */
|
||||||
FIXED_INFO *fixed_info;
|
FIXED_INFO *fixed_info;
|
||||||
ULONG buflen;
|
ULONG buflen;
|
||||||
DWORD ret;
|
DWORD ret;
|
||||||
|
|
||||||
rv = NULL;
|
rv = NULL;
|
||||||
fixed_info = malloc(sizeof(FIXED_INFO));
|
fixed_info = malloc(sizeof(FIXED_INFO));
|
||||||
buflen = sizeof(FIXED_INFO);
|
buflen = sizeof(FIXED_INFO);
|
||||||
|
|
||||||
if (GetNetworkParams(fixed_info, &buflen) == ERROR_BUFFER_OVERFLOW) {
|
if (GetNetworkParams(fixed_info, &buflen) == ERROR_BUFFER_OVERFLOW) {
|
||||||
/* official ugly api workaround */
|
/* official ugly api workaround */
|
||||||
free(fixed_info);
|
free(fixed_info);
|
||||||
fixed_info = malloc(buflen);
|
fixed_info = malloc(buflen);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = GetNetworkParams(fixed_info, &buflen);
|
ret = GetNetworkParams(fixed_info, &buflen);
|
||||||
if (ret == NO_ERROR) {
|
if (ret == NO_ERROR) {
|
||||||
strncpy(addr, fixed_info->DnsServerList.IpAddress.String, sizeof(addr));
|
strncpy(addr, fixed_info->DnsServerList.IpAddress.String, sizeof(addr));
|
||||||
addr[15] = 0;
|
addr[15] = 0;
|
||||||
rv = addr;
|
rv = addr;
|
||||||
}
|
}
|
||||||
free(fixed_info);
|
free(fixed_info);
|
||||||
#endif
|
#endif
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef OPENBSD
|
#ifdef OPENBSD
|
||||||
|
@ -84,10 +84,10 @@ void
|
||||||
socket_setrtable(int fd, int rtable)
|
socket_setrtable(int fd, int rtable)
|
||||||
{
|
{
|
||||||
#ifdef SO_RTABLE
|
#ifdef SO_RTABLE
|
||||||
if (setsockopt (fd, IPPROTO_IP, SO_RTABLE, &rtable, sizeof(rtable)) == -1)
|
if (setsockopt (fd, IPPROTO_IP, SO_RTABLE, &rtable, sizeof(rtable)) == -1)
|
||||||
err(1, "Failed to set routing table %d", rtable);
|
err(1, "Failed to set routing table %d", rtable);
|
||||||
#else
|
#else
|
||||||
fprintf(stderr, "Routing domain support was not available at compile time.\n");
|
fprintf(stderr, "Routing domain support was not available at compile time.\n");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
136
tests/base32.c
136
tests/base32.c
|
@ -29,116 +29,116 @@
|
||||||
|
|
||||||
static struct tuple
|
static struct tuple
|
||||||
{
|
{
|
||||||
char *a;
|
char *a;
|
||||||
char *b;
|
char *b;
|
||||||
} testpairs[TUPLES] = {
|
} testpairs[TUPLES] = {
|
||||||
{ "iodinetestingtesting", "nfxwi0lomv0gk21unfxgo3dfon0gs1th" },
|
{ "iodinetestingtesting", "nfxwi0lomv0gk21unfxgo3dfon0gs1th" },
|
||||||
{ "abc123", "mfrggmjsgm" },
|
{ "abc123", "mfrggmjsgm" },
|
||||||
{ "test", "orsxg3a" },
|
{ "test", "orsxg3a" },
|
||||||
{ "tst", "orzxi" },
|
{ "tst", "orzxi" },
|
||||||
{ "", "" },
|
{ "", "" },
|
||||||
};
|
};
|
||||||
|
|
||||||
START_TEST(test_base32_encode)
|
START_TEST(test_base32_encode)
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
struct encoder *b32;
|
struct encoder *b32;
|
||||||
int val;
|
int val;
|
||||||
|
|
||||||
b32 = get_base32_encoder();
|
b32 = get_base32_encoder();
|
||||||
|
|
||||||
len = sizeof(buf);
|
len = sizeof(buf);
|
||||||
val = b32->encode(buf, &len, testpairs[_i].a, strlen(testpairs[_i].a));
|
val = b32->encode(buf, &len, testpairs[_i].a, strlen(testpairs[_i].a));
|
||||||
|
|
||||||
fail_unless(val == strlen(testpairs[_i].b));
|
fail_unless(val == strlen(testpairs[_i].b));
|
||||||
fail_unless(strcmp(buf, testpairs[_i].b) == 0,
|
fail_unless(strcmp(buf, testpairs[_i].b) == 0,
|
||||||
"'%s' != '%s'", buf, testpairs[_i].b);
|
"'%s' != '%s'", buf, testpairs[_i].b);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_base32_decode)
|
START_TEST(test_base32_decode)
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
struct encoder *b32;
|
struct encoder *b32;
|
||||||
int val;
|
int val;
|
||||||
|
|
||||||
b32 = get_base32_encoder();
|
b32 = get_base32_encoder();
|
||||||
|
|
||||||
len = sizeof(buf);
|
len = sizeof(buf);
|
||||||
val = b32->decode(buf, &len, testpairs[_i].b, strlen(testpairs[_i].b));
|
val = b32->decode(buf, &len, testpairs[_i].b, strlen(testpairs[_i].b));
|
||||||
|
|
||||||
fail_unless(val == strlen(testpairs[_i].a));
|
fail_unless(val == strlen(testpairs[_i].a));
|
||||||
fail_unless(strcmp(buf, testpairs[_i].a) == 0,
|
fail_unless(strcmp(buf, testpairs[_i].a) == 0,
|
||||||
"'%s' != '%s'", buf, testpairs[_i].a);
|
"'%s' != '%s'", buf, testpairs[_i].a);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_base32_5to8_8to5)
|
START_TEST(test_base32_5to8_8to5)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
for (i = 0; i < 32; i++) {
|
for (i = 0; i < 32; i++) {
|
||||||
c = b32_5to8(i);
|
c = b32_5to8(i);
|
||||||
fail_unless(b32_8to5(c) == i);
|
fail_unless(b32_8to5(c) == i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_base32_blksize)
|
START_TEST(test_base32_blksize)
|
||||||
{
|
{
|
||||||
size_t rawlen;
|
size_t rawlen;
|
||||||
size_t enclen;
|
size_t enclen;
|
||||||
char *rawbuf;
|
char *rawbuf;
|
||||||
char *encbuf;
|
char *encbuf;
|
||||||
struct encoder *b32;
|
struct encoder *b32;
|
||||||
int i;
|
int i;
|
||||||
int val;
|
int val;
|
||||||
|
|
||||||
b32 = get_base32_encoder();
|
b32 = get_base32_encoder();
|
||||||
|
|
||||||
rawlen = b32->blocksize_raw();
|
rawlen = b32->blocksize_raw();
|
||||||
enclen = b32->blocksize_encoded();
|
enclen = b32->blocksize_encoded();
|
||||||
|
|
||||||
rawbuf = malloc(rawlen + 16);
|
rawbuf = malloc(rawlen + 16);
|
||||||
encbuf = malloc(enclen + 16);
|
encbuf = malloc(enclen + 16);
|
||||||
|
|
||||||
for (i = 0; i < rawlen; i++) {
|
for (i = 0; i < rawlen; i++) {
|
||||||
rawbuf[i] = 'A';
|
rawbuf[i] = 'A';
|
||||||
}
|
}
|
||||||
rawbuf[i] = 0;
|
rawbuf[i] = 0;
|
||||||
|
|
||||||
val = b32->encode(encbuf, &enclen, rawbuf, rawlen);
|
val = b32->encode(encbuf, &enclen, rawbuf, rawlen);
|
||||||
|
|
||||||
fail_unless(rawlen == 5, "raw length was %d not 5", rawlen);
|
fail_unless(rawlen == 5, "raw length was %d not 5", rawlen);
|
||||||
fail_unless(enclen == 5, "encoded %d bytes, not 5", enclen);
|
fail_unless(enclen == 5, "encoded %d bytes, not 5", enclen);
|
||||||
fail_unless(val == 8, "encoded string %s was length %d", encbuf, val);
|
fail_unless(val == 8, "encoded string %s was length %d", encbuf, val);
|
||||||
|
|
||||||
memset(rawbuf, 0, rawlen + 16);
|
memset(rawbuf, 0, rawlen + 16);
|
||||||
|
|
||||||
enclen = val;
|
enclen = val;
|
||||||
val = b32->decode(rawbuf, &rawlen, encbuf, enclen);
|
val = b32->decode(rawbuf, &rawlen, encbuf, enclen);
|
||||||
|
|
||||||
fail_unless(rawlen == 5, "raw length was %d not 5", rawlen);
|
fail_unless(rawlen == 5, "raw length was %d not 5", rawlen);
|
||||||
fail_unless(val == 5, "val was not 5 but %d", val);
|
fail_unless(val == 5, "val was not 5 but %d", val);
|
||||||
for (i = 0; i < rawlen; i++) {
|
for (i = 0; i < rawlen; i++) {
|
||||||
fail_unless(rawbuf[i] == 'A');
|
fail_unless(rawbuf[i] == 'A');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
TCase *
|
TCase *
|
||||||
test_base32_create_tests()
|
test_base32_create_tests()
|
||||||
{
|
{
|
||||||
TCase *tc;
|
TCase *tc;
|
||||||
|
|
||||||
tc = tcase_create("Base32");
|
tc = tcase_create("Base32");
|
||||||
tcase_add_loop_test(tc, test_base32_encode, 0, TUPLES);
|
tcase_add_loop_test(tc, test_base32_encode, 0, TUPLES);
|
||||||
tcase_add_loop_test(tc, test_base32_decode, 0, TUPLES);
|
tcase_add_loop_test(tc, test_base32_decode, 0, TUPLES);
|
||||||
tcase_add_test(tc, test_base32_5to8_8to5);
|
tcase_add_test(tc, test_base32_5to8_8to5);
|
||||||
tcase_add_test(tc, test_base32_blksize);
|
tcase_add_test(tc, test_base32_blksize);
|
||||||
|
|
||||||
return tc;
|
return tc;
|
||||||
}
|
}
|
||||||
|
|
170
tests/base64.c
170
tests/base64.c
|
@ -29,129 +29,129 @@
|
||||||
|
|
||||||
static struct tuple
|
static struct tuple
|
||||||
{
|
{
|
||||||
char *a;
|
char *a;
|
||||||
char *b;
|
char *b;
|
||||||
} testpairs[TUPLES] = {
|
} testpairs[TUPLES] = {
|
||||||
{ "iodinetestingtesting", "Aw8KAw4LDgvZDgLUz2rLC2rPBMC" },
|
{ "iodinetestingtesting", "Aw8KAw4LDgvZDgLUz2rLC2rPBMC" },
|
||||||
{ "abc1231", "ywjJmtiZmq" },
|
{ "abc1231", "ywjJmtiZmq" },
|
||||||
{
|
{
|
||||||
"\xFF\xEF\x7C\xEF\xAE\x78\xDF\x6D\x74\xCF\x2C\x70\xBE\xEB\x6C\xAE\xAA\x68"
|
"\xFF\xEF\x7C\xEF\xAE\x78\xDF\x6D\x74\xCF\x2C\x70\xBE\xEB\x6C\xAE\xAA\x68"
|
||||||
"\x9E\x69\x64\x8E\x28\x60\x7D\xE7\x5C\x6D\xA6\x58\x5D\x65\x54\x4D\x24\x50"
|
"\x9E\x69\x64\x8E\x28\x60\x7D\xE7\x5C\x6D\xA6\x58\x5D\x65\x54\x4D\x24\x50"
|
||||||
"\x3C\xE3\x4C\x2C\xA2\x48\x1C\x61\x44\x0C\x20\x40\x3F\x3F\x3C\xEF\xAE\x78"
|
"\x3C\xE3\x4C\x2C\xA2\x48\x1C\x61\x44\x0C\x20\x40\x3F\x3F\x3C\xEF\xAE\x78"
|
||||||
"\xDF\x6D\x74\xCF\x2C\x70\xBE\xEB\x6C\xAE\xAA\x68\x9E\x69\x64\x8E\x28\x60"
|
"\xDF\x6D\x74\xCF\x2C\x70\xBE\xEB\x6C\xAE\xAA\x68\x9E\x69\x64\x8E\x28\x60"
|
||||||
"\x7D\xE7\x5C\x6D\xA6\x58\x5D\x65\x54\x4D\x24\x50\x3C\xE3\x4C\x2C\xA2\x48"
|
"\x7D\xE7\x5C\x6D\xA6\x58\x5D\x65\x54\x4D\x24\x50\x3C\xE3\x4C\x2C\xA2\x48"
|
||||||
"\x1C\x61\x44\x0C\x20\x40\xFF\xEF\x7C\xEF\xAE\x78\xDF\x6D\x74\xCF\x2C\x70"
|
"\x1C\x61\x44\x0C\x20\x40\xFF\xEF\x7C\xEF\xAE\x78\xDF\x6D\x74\xCF\x2C\x70"
|
||||||
"\xBE\xEB\x6C\xAE\xAA\x68\x9E\x69\x64\x8E\x28\x60\x7D\xE7\x5C\x6D\xA6\x58"
|
"\xBE\xEB\x6C\xAE\xAA\x68\x9E\x69\x64\x8E\x28\x60\x7D\xE7\x5C\x6D\xA6\x58"
|
||||||
"\x5D\x65\x54\x4D\x24\x50\x3C\xE3\x4C\x2C\xA2\x48\x1C\x61\x44\x0C\x20\x40",
|
"\x5D\x65\x54\x4D\x24\x50\x3C\xE3\x4C\x2C\xA2\x48\x1C\x61\x44\x0C\x20\x40",
|
||||||
|
|
||||||
"+9876543210-ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcbapZ"
|
"+9876543210-ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcbapZ"
|
||||||
"776543210-ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba+987654"
|
"776543210-ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba+987654"
|
||||||
"3210-ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba"
|
"3210-ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"\xFF\xEF\x7C\xEF\xAE\x78\xDF\x6D\x74\xCF\x2C\x70\xBE\xEB\x6C\xAE\xAA\x68"
|
"\xFF\xEF\x7C\xEF\xAE\x78\xDF\x6D\x74\xCF\x2C\x70\xBE\xEB\x6C\xAE\xAA\x68"
|
||||||
"\x9E\x69\x64\x8E\x28\x60\x7D\xE7\x5C\x6D\xA6\x58\x5D\x65\x54\x4D\x24\x50"
|
"\x9E\x69\x64\x8E\x28\x60\x7D\xE7\x5C\x6D\xA6\x58\x5D\x65\x54\x4D\x24\x50"
|
||||||
"\x3C\xE3\x4C\x2C\xA2\x48\x1C\x61\x44\x0C\x20\x40\x3F\x3F\x3C\xEF\xAE\x78"
|
"\x3C\xE3\x4C\x2C\xA2\x48\x1C\x61\x44\x0C\x20\x40\x3F\x3F\x3C\xEF\xAE\x78"
|
||||||
"\xDF\x6D\x74\xCF\x2C\x70\xBE\xEB\x6C\xAE\xA1\x61\x91\x61\x61\x81\x28\x60"
|
"\xDF\x6D\x74\xCF\x2C\x70\xBE\xEB\x6C\xAE\xA1\x61\x91\x61\x61\x81\x28\x60"
|
||||||
"\x7D\xE7\x5C\x6D\xA6\x58\x5D\x65\x54\x4D\x24\x50\x3C\xE3\x4C\x2C\xA2\x48"
|
"\x7D\xE7\x5C\x6D\xA6\x58\x5D\x65\x54\x4D\x24\x50\x3C\xE3\x4C\x2C\xA2\x48"
|
||||||
"\x1C\x61\x44\x0C\x20\x40\xFF\xEF\x7C\xEF\xAE\x78\xDF\x6D\x74\xCF\x2C\x70"
|
"\x1C\x61\x44\x0C\x20\x40\xFF\xEF\x7C\xEF\xAE\x78\xDF\x6D\x74\xCF\x2C\x70"
|
||||||
"\xBE\xEB\x6C\xAE\xA1\x61\x91\x61\x61\x81\x28\x60\x7D\xE7\x5C\x6D\xA6\x58"
|
"\xBE\xEB\x6C\xAE\xA1\x61\x91\x61\x61\x81\x28\x60\x7D\xE7\x5C\x6D\xA6\x58"
|
||||||
"\x5D\x65\x54\x4D\x24\x50\x3C\xE3\x4C\x2C\xA2\x48\x1C\x61\x44\x0C\x20\x40",
|
"\x5D\x65\x54\x4D\x24\x50\x3C\xE3\x4C\x2C\xA2\x48\x1C\x61\x44\x0C\x20\x40",
|
||||||
|
|
||||||
"+9876543210-ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcbapZ"
|
"+9876543210-ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcbapZ"
|
||||||
"776543210-ZYXWVUTSRQfHKwfHGsHGFEDCBAzyxwvutsrqponmlkjihgfedcba+987654321"
|
"776543210-ZYXWVUTSRQfHKwfHGsHGFEDCBAzyxwvutsrqponmlkjihgfedcba+987654321"
|
||||||
"0-ZYXWVUTSRQfHKwfHGsHGFEDCBAzyxwvutsrqponmlkjihgfedcba"
|
"0-ZYXWVUTSRQfHKwfHGsHGFEDCBAzyxwvutsrqponmlkjihgfedcba"
|
||||||
},
|
},
|
||||||
{ "", "" }
|
{ "", "" }
|
||||||
};
|
};
|
||||||
|
|
||||||
START_TEST(test_base64_encode)
|
START_TEST(test_base64_encode)
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
struct encoder *b64;
|
struct encoder *b64;
|
||||||
int val;
|
int val;
|
||||||
|
|
||||||
b64 = get_base64_encoder();
|
b64 = get_base64_encoder();
|
||||||
|
|
||||||
len = sizeof(buf);
|
len = sizeof(buf);
|
||||||
val = b64->encode(buf, &len, testpairs[_i].a, strlen(testpairs[_i].a));
|
val = b64->encode(buf, &len, testpairs[_i].a, strlen(testpairs[_i].a));
|
||||||
|
|
||||||
fail_unless(val == strlen(testpairs[_i].b));
|
fail_unless(val == strlen(testpairs[_i].b));
|
||||||
fail_unless(strcmp(buf, testpairs[_i].b) == 0,
|
fail_unless(strcmp(buf, testpairs[_i].b) == 0,
|
||||||
"'%s' != '%s'", buf, testpairs[_i].b);
|
"'%s' != '%s'", buf, testpairs[_i].b);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_base64_decode)
|
START_TEST(test_base64_decode)
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
struct encoder *b64;
|
struct encoder *b64;
|
||||||
int val;
|
int val;
|
||||||
|
|
||||||
b64 = get_base64_encoder();
|
b64 = get_base64_encoder();
|
||||||
|
|
||||||
len = sizeof(buf);
|
len = sizeof(buf);
|
||||||
val = b64->decode(buf, &len, testpairs[_i].b, strlen(testpairs[_i].b));
|
val = b64->decode(buf, &len, testpairs[_i].b, strlen(testpairs[_i].b));
|
||||||
|
|
||||||
fail_unless(val == strlen(testpairs[_i].a));
|
fail_unless(val == strlen(testpairs[_i].a));
|
||||||
fail_unless(strcmp(buf, testpairs[_i].a) == 0,
|
fail_unless(strcmp(buf, testpairs[_i].a) == 0,
|
||||||
"'%s' != '%s'", buf, testpairs[_i].a);
|
"'%s' != '%s'", buf, testpairs[_i].a);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_base64_blksize)
|
START_TEST(test_base64_blksize)
|
||||||
{
|
{
|
||||||
size_t rawlen;
|
size_t rawlen;
|
||||||
size_t enclen;
|
size_t enclen;
|
||||||
char *rawbuf;
|
char *rawbuf;
|
||||||
char *encbuf;
|
char *encbuf;
|
||||||
struct encoder *b64;
|
struct encoder *b64;
|
||||||
int i;
|
int i;
|
||||||
int val;
|
int val;
|
||||||
|
|
||||||
b64 = get_base64_encoder();
|
b64 = get_base64_encoder();
|
||||||
|
|
||||||
rawlen = b64->blocksize_raw();
|
rawlen = b64->blocksize_raw();
|
||||||
enclen = b64->blocksize_encoded();
|
enclen = b64->blocksize_encoded();
|
||||||
|
|
||||||
rawbuf = malloc(rawlen + 16);
|
rawbuf = malloc(rawlen + 16);
|
||||||
encbuf = malloc(enclen + 16);
|
encbuf = malloc(enclen + 16);
|
||||||
|
|
||||||
for (i = 0; i < rawlen; i++) {
|
for (i = 0; i < rawlen; i++) {
|
||||||
rawbuf[i] = 'A';
|
rawbuf[i] = 'A';
|
||||||
}
|
}
|
||||||
rawbuf[i] = 0;
|
rawbuf[i] = 0;
|
||||||
|
|
||||||
val = b64->encode(encbuf, &enclen, rawbuf, rawlen);
|
val = b64->encode(encbuf, &enclen, rawbuf, rawlen);
|
||||||
|
|
||||||
fail_unless(rawlen == 3, "raw length was %d not 3", rawlen);
|
fail_unless(rawlen == 3, "raw length was %d not 3", rawlen);
|
||||||
fail_unless(enclen == 3, "encoded %d bytes, not 3", enclen);
|
fail_unless(enclen == 3, "encoded %d bytes, not 3", enclen);
|
||||||
fail_unless(val == 4, "encoded string %s was length %d", encbuf, val);
|
fail_unless(val == 4, "encoded string %s was length %d", encbuf, val);
|
||||||
|
|
||||||
memset(rawbuf, 0, rawlen + 16);
|
memset(rawbuf, 0, rawlen + 16);
|
||||||
|
|
||||||
enclen = val;
|
enclen = val;
|
||||||
val = b64->decode(rawbuf, &rawlen, encbuf, enclen);
|
val = b64->decode(rawbuf, &rawlen, encbuf, enclen);
|
||||||
|
|
||||||
fail_unless(rawlen == 3, "raw length was %d not 3", rawlen);
|
fail_unless(rawlen == 3, "raw length was %d not 3", rawlen);
|
||||||
fail_unless(val == 3);
|
fail_unless(val == 3);
|
||||||
for (i = 0; i < rawlen; i++) {
|
for (i = 0; i < rawlen; i++) {
|
||||||
fail_unless(rawbuf[i] == 'A');
|
fail_unless(rawbuf[i] == 'A');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
TCase *
|
TCase *
|
||||||
test_base64_create_tests()
|
test_base64_create_tests()
|
||||||
{
|
{
|
||||||
TCase *tc;
|
TCase *tc;
|
||||||
|
|
||||||
tc = tcase_create("Base64");
|
tc = tcase_create("Base64");
|
||||||
tcase_add_loop_test(tc, test_base64_encode, 0, TUPLES);
|
tcase_add_loop_test(tc, test_base64_encode, 0, TUPLES);
|
||||||
tcase_add_loop_test(tc, test_base64_decode, 0, TUPLES);
|
tcase_add_loop_test(tc, test_base64_decode, 0, TUPLES);
|
||||||
tcase_add_test(tc, test_base64_blksize);
|
tcase_add_test(tc, test_base64_blksize);
|
||||||
|
|
||||||
return tc;
|
return tc;
|
||||||
}
|
}
|
||||||
|
|
266
tests/common.c
266
tests/common.c
|
@ -23,198 +23,198 @@
|
||||||
|
|
||||||
START_TEST(test_topdomain_ok)
|
START_TEST(test_topdomain_ok)
|
||||||
{
|
{
|
||||||
char *error;
|
char *error;
|
||||||
|
|
||||||
fail_if(check_topdomain("foo.0123456789.qwertyuiop.asdfghjkl.zxcvbnm.com", &error));
|
fail_if(check_topdomain("foo.0123456789.qwertyuiop.asdfghjkl.zxcvbnm.com", &error));
|
||||||
|
|
||||||
/* Not allowed to start with dot */
|
/* Not allowed to start with dot */
|
||||||
fail_unless(check_topdomain(".foo.0123456789.qwertyuiop.asdfghjkl.zxcvbnm.com", &error));
|
fail_unless(check_topdomain(".foo.0123456789.qwertyuiop.asdfghjkl.zxcvbnm.com", &error));
|
||||||
fail_if(strcmp("Starts with a dot", error));
|
fail_if(strcmp("Starts with a dot", error));
|
||||||
|
|
||||||
/* Test missing error msg ptr */
|
/* Test missing error msg ptr */
|
||||||
fail_unless(check_topdomain(".foo", NULL));
|
fail_unless(check_topdomain(".foo", NULL));
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_topdomain_length)
|
START_TEST(test_topdomain_length)
|
||||||
{
|
{
|
||||||
char *error;
|
char *error;
|
||||||
|
|
||||||
/* Test empty and too short */
|
/* Test empty and too short */
|
||||||
fail_unless(check_topdomain("", &error));
|
fail_unless(check_topdomain("", &error));
|
||||||
fail_if(strcmp("Too short (< 3)", error));
|
fail_if(strcmp("Too short (< 3)", error));
|
||||||
fail_unless(check_topdomain("a", &error));
|
fail_unless(check_topdomain("a", &error));
|
||||||
fail_if(strcmp("Too short (< 3)", error));
|
fail_if(strcmp("Too short (< 3)", error));
|
||||||
fail_unless(check_topdomain(".a", &error));
|
fail_unless(check_topdomain(".a", &error));
|
||||||
fail_if(strcmp("Too short (< 3)", error));
|
fail_if(strcmp("Too short (< 3)", error));
|
||||||
fail_unless(check_topdomain("a.", &error));
|
fail_unless(check_topdomain("a.", &error));
|
||||||
fail_if(strcmp("Too short (< 3)", error));
|
fail_if(strcmp("Too short (< 3)", error));
|
||||||
fail_unless(check_topdomain("ab", &error));
|
fail_unless(check_topdomain("ab", &error));
|
||||||
fail_if(strcmp("Too short (< 3)", error));
|
fail_if(strcmp("Too short (< 3)", error));
|
||||||
fail_if(check_topdomain("a.b", &error));
|
fail_if(check_topdomain("a.b", &error));
|
||||||
fail_if(strcmp("Too short (< 3)", error));
|
fail_if(strcmp("Too short (< 3)", error));
|
||||||
|
|
||||||
/* Test too long (over 128, need rest of space for data) */
|
/* Test too long (over 128, need rest of space for data) */
|
||||||
fail_unless(check_topdomain(
|
fail_unless(check_topdomain(
|
||||||
"abcd12345.abcd12345.abcd12345.abcd12345.abcd12345."
|
"abcd12345.abcd12345.abcd12345.abcd12345.abcd12345."
|
||||||
"abcd12345.abcd12345.abcd12345.abcd12345.abcd12345."
|
"abcd12345.abcd12345.abcd12345.abcd12345.abcd12345."
|
||||||
"abcd12345.abcd12345.foo129xxx", &error));
|
"abcd12345.abcd12345.foo129xxx", &error));
|
||||||
fail_if(strcmp("Too long (> 128)", error));
|
fail_if(strcmp("Too long (> 128)", error));
|
||||||
fail_if(check_topdomain(
|
fail_if(check_topdomain(
|
||||||
"abcd12345.abcd12345.abcd12345.abcd12345.abcd12345."
|
"abcd12345.abcd12345.abcd12345.abcd12345.abcd12345."
|
||||||
"abcd12345.abcd12345.abcd12345.abcd12345.abcd12345."
|
"abcd12345.abcd12345.abcd12345.abcd12345.abcd12345."
|
||||||
"abcd12345.abcd12345.foo128xx", &error));
|
"abcd12345.abcd12345.foo128xx", &error));
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_topdomain_chunks)
|
START_TEST(test_topdomain_chunks)
|
||||||
{
|
{
|
||||||
char *error;
|
char *error;
|
||||||
|
|
||||||
/* Must have at least one dot */
|
/* Must have at least one dot */
|
||||||
fail_if(check_topdomain("abcde.gh", &error));
|
fail_if(check_topdomain("abcde.gh", &error));
|
||||||
fail_unless(check_topdomain("abcdefgh", &error));
|
fail_unless(check_topdomain("abcdefgh", &error));
|
||||||
fail_if(strcmp("No dots", error));
|
fail_if(strcmp("No dots", error));
|
||||||
|
|
||||||
/* Not two consecutive dots */
|
/* Not two consecutive dots */
|
||||||
fail_unless(check_topdomain("abc..defgh", &error));
|
fail_unless(check_topdomain("abc..defgh", &error));
|
||||||
fail_if(strcmp("Consecutive dots", error));
|
fail_if(strcmp("Consecutive dots", error));
|
||||||
|
|
||||||
/* Not end with a dots */
|
/* Not end with a dots */
|
||||||
fail_unless(check_topdomain("abc.defgh.", &error));
|
fail_unless(check_topdomain("abc.defgh.", &error));
|
||||||
fail_if(strcmp("Ends with a dot", error));
|
fail_if(strcmp("Ends with a dot", error));
|
||||||
|
|
||||||
/* No chunk longer than 63 chars */
|
/* No chunk longer than 63 chars */
|
||||||
fail_if(check_topdomain("123456789012345678901234567890"
|
fail_if(check_topdomain("123456789012345678901234567890"
|
||||||
"123456789012345678901234567890333.com", &error));
|
"123456789012345678901234567890333.com", &error));
|
||||||
fail_unless(check_topdomain("123456789012345678901234567890"
|
fail_unless(check_topdomain("123456789012345678901234567890"
|
||||||
"1234567890123456789012345678904444.com", &error));
|
"1234567890123456789012345678904444.com", &error));
|
||||||
fail_if(strcmp("Too long domain part (> 63)", error));
|
fail_if(strcmp("Too long domain part (> 63)", error));
|
||||||
|
|
||||||
fail_if(check_topdomain("abc.123456789012345678901234567890"
|
fail_if(check_topdomain("abc.123456789012345678901234567890"
|
||||||
"123456789012345678901234567890333.com", &error));
|
"123456789012345678901234567890333.com", &error));
|
||||||
fail_unless(check_topdomain("abc.123456789012345678901234567890"
|
fail_unless(check_topdomain("abc.123456789012345678901234567890"
|
||||||
"1234567890123456789012345678904444.com", &error));
|
"1234567890123456789012345678904444.com", &error));
|
||||||
fail_if(strcmp("Too long domain part (> 63)", error));
|
fail_if(strcmp("Too long domain part (> 63)", error));
|
||||||
|
|
||||||
fail_if(check_topdomain("abc.123456789012345678901234567890"
|
fail_if(check_topdomain("abc.123456789012345678901234567890"
|
||||||
"123456789012345678901234567890333", &error));
|
"123456789012345678901234567890333", &error));
|
||||||
fail_unless(check_topdomain("abc.123456789012345678901234567890"
|
fail_unless(check_topdomain("abc.123456789012345678901234567890"
|
||||||
"1234567890123456789012345678904444", &error));
|
"1234567890123456789012345678904444", &error));
|
||||||
fail_if(strcmp("Too long domain part (> 63)", error));
|
fail_if(strcmp("Too long domain part (> 63)", error));
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_parse_format_ipv4)
|
START_TEST(test_parse_format_ipv4)
|
||||||
{
|
{
|
||||||
char *host = "192.168.2.10";
|
char *host = "192.168.2.10";
|
||||||
char *formatted;
|
char *formatted;
|
||||||
struct sockaddr_storage addr;
|
struct sockaddr_storage addr;
|
||||||
struct sockaddr_in *v4addr;
|
struct sockaddr_in *v4addr;
|
||||||
int addr_len;
|
int addr_len;
|
||||||
|
|
||||||
addr_len = get_addr(host, 53, AF_INET, 0, &addr);
|
addr_len = get_addr(host, 53, AF_INET, 0, &addr);
|
||||||
fail_unless(addr_len == sizeof(struct sockaddr_in));
|
fail_unless(addr_len == sizeof(struct sockaddr_in));
|
||||||
|
|
||||||
v4addr = (struct sockaddr_in *) &addr;
|
v4addr = (struct sockaddr_in *) &addr;
|
||||||
fail_unless(v4addr->sin_addr.s_addr == htonl(0xc0a8020a));
|
fail_unless(v4addr->sin_addr.s_addr == htonl(0xc0a8020a));
|
||||||
fail_unless(v4addr->sin_port == htons(53));
|
fail_unless(v4addr->sin_port == htons(53));
|
||||||
|
|
||||||
formatted = format_addr(&addr, addr_len);
|
formatted = format_addr(&addr, addr_len);
|
||||||
fail_if(strcmp(host, formatted));
|
fail_if(strcmp(host, formatted));
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_parse_format_ipv4_listen_all)
|
START_TEST(test_parse_format_ipv4_listen_all)
|
||||||
{
|
{
|
||||||
char *host = "0.0.0.0";
|
char *host = "0.0.0.0";
|
||||||
char *formatted;
|
char *formatted;
|
||||||
struct sockaddr_storage addr;
|
struct sockaddr_storage addr;
|
||||||
struct sockaddr_in *v4addr;
|
struct sockaddr_in *v4addr;
|
||||||
int addr_len;
|
int addr_len;
|
||||||
|
|
||||||
addr_len = get_addr(NULL, 53, AF_INET, AI_PASSIVE, &addr);
|
addr_len = get_addr(NULL, 53, AF_INET, AI_PASSIVE, &addr);
|
||||||
fail_unless(addr_len == sizeof(struct sockaddr_in));
|
fail_unless(addr_len == sizeof(struct sockaddr_in));
|
||||||
|
|
||||||
v4addr = (struct sockaddr_in *) &addr;
|
v4addr = (struct sockaddr_in *) &addr;
|
||||||
fail_unless(v4addr->sin_addr.s_addr == htonl(0x00000000));
|
fail_unless(v4addr->sin_addr.s_addr == htonl(0x00000000));
|
||||||
fail_unless(v4addr->sin_port == htons(53));
|
fail_unless(v4addr->sin_port == htons(53));
|
||||||
|
|
||||||
formatted = format_addr(&addr, addr_len);
|
formatted = format_addr(&addr, addr_len);
|
||||||
fail_if(strcmp(host, formatted));
|
fail_if(strcmp(host, formatted));
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_parse_format_ipv6)
|
START_TEST(test_parse_format_ipv6)
|
||||||
{
|
{
|
||||||
char *host = "2001:0db8:0505:0::123:0abc";
|
char *host = "2001:0db8:0505:0::123:0abc";
|
||||||
char *compact = "2001:db8:505::123:abc";
|
char *compact = "2001:db8:505::123:abc";
|
||||||
unsigned char v6_bits[] = {
|
unsigned char v6_bits[] = {
|
||||||
0x20, 0x01, 0x0d, 0xb8, 0x05, 0x05, 0x00, 0x00,
|
0x20, 0x01, 0x0d, 0xb8, 0x05, 0x05, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x01, 0x23, 0x0a, 0xbc,
|
0x00, 0x00, 0x00, 0x00, 0x01, 0x23, 0x0a, 0xbc,
|
||||||
};
|
};
|
||||||
char *formatted;
|
char *formatted;
|
||||||
struct sockaddr_storage addr;
|
struct sockaddr_storage addr;
|
||||||
struct sockaddr_in6 *v6addr;
|
struct sockaddr_in6 *v6addr;
|
||||||
int addr_len;
|
int addr_len;
|
||||||
|
|
||||||
addr_len = get_addr(host, 53, AF_UNSPEC, 0, &addr);
|
addr_len = get_addr(host, 53, AF_UNSPEC, 0, &addr);
|
||||||
fail_unless(addr_len == sizeof(struct sockaddr_in6));
|
fail_unless(addr_len == sizeof(struct sockaddr_in6));
|
||||||
|
|
||||||
v6addr = (struct sockaddr_in6 *) &addr;
|
v6addr = (struct sockaddr_in6 *) &addr;
|
||||||
fail_if(memcmp(&v6addr->sin6_addr, v6_bits, sizeof(v6_bits)));
|
fail_if(memcmp(&v6addr->sin6_addr, v6_bits, sizeof(v6_bits)));
|
||||||
fail_unless(v6addr->sin6_port == htons(53));
|
fail_unless(v6addr->sin6_port == htons(53));
|
||||||
|
|
||||||
formatted = format_addr(&addr, addr_len);
|
formatted = format_addr(&addr, addr_len);
|
||||||
fail_if(strcmp(compact, formatted));
|
fail_if(strcmp(compact, formatted));
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_parse_format_ipv4_mapped_ipv6)
|
START_TEST(test_parse_format_ipv4_mapped_ipv6)
|
||||||
{
|
{
|
||||||
char *v4mapped = "::FFFF:192.168.2.10";
|
char *v4mapped = "::FFFF:192.168.2.10";
|
||||||
char *host = "192.168.2.10";
|
char *host = "192.168.2.10";
|
||||||
unsigned char v6_bits[] = {
|
unsigned char v6_bits[] = {
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0xff, 0xff, 0xc0, 0xa8, 0x02, 0x0a,
|
0x00, 0x00, 0xff, 0xff, 0xc0, 0xa8, 0x02, 0x0a,
|
||||||
};
|
};
|
||||||
char *formatted;
|
char *formatted;
|
||||||
struct sockaddr_storage addr;
|
struct sockaddr_storage addr;
|
||||||
struct sockaddr_in6 *v6addr;
|
struct sockaddr_in6 *v6addr;
|
||||||
int addr_len;
|
int addr_len;
|
||||||
|
|
||||||
addr_len = get_addr(v4mapped, 53, AF_INET6, 0, &addr);
|
addr_len = get_addr(v4mapped, 53, AF_INET6, 0, &addr);
|
||||||
fail_unless(addr_len == sizeof(struct sockaddr_in6));
|
fail_unless(addr_len == sizeof(struct sockaddr_in6));
|
||||||
|
|
||||||
v6addr = (struct sockaddr_in6 *) &addr;
|
v6addr = (struct sockaddr_in6 *) &addr;
|
||||||
fail_if(memcmp(&v6addr->sin6_addr, v6_bits, sizeof(v6_bits)));
|
fail_if(memcmp(&v6addr->sin6_addr, v6_bits, sizeof(v6_bits)));
|
||||||
fail_unless(v6addr->sin6_port == htons(53));
|
fail_unless(v6addr->sin6_port == htons(53));
|
||||||
|
|
||||||
/* Format as IPv4 address */
|
/* Format as IPv4 address */
|
||||||
formatted = format_addr(&addr, addr_len);
|
formatted = format_addr(&addr, addr_len);
|
||||||
fail_if(strcmp(host, formatted));
|
fail_if(strcmp(host, formatted));
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
TCase *
|
TCase *
|
||||||
test_common_create_tests()
|
test_common_create_tests()
|
||||||
{
|
{
|
||||||
TCase *tc;
|
TCase *tc;
|
||||||
int sock;
|
int sock;
|
||||||
|
|
||||||
tc = tcase_create("Common");
|
tc = tcase_create("Common");
|
||||||
tcase_add_test(tc, test_topdomain_ok);
|
tcase_add_test(tc, test_topdomain_ok);
|
||||||
tcase_add_test(tc, test_topdomain_length);
|
tcase_add_test(tc, test_topdomain_length);
|
||||||
tcase_add_test(tc, test_topdomain_chunks);
|
tcase_add_test(tc, test_topdomain_chunks);
|
||||||
tcase_add_test(tc, test_parse_format_ipv4);
|
tcase_add_test(tc, test_parse_format_ipv4);
|
||||||
tcase_add_test(tc, test_parse_format_ipv4_listen_all);
|
tcase_add_test(tc, test_parse_format_ipv4_listen_all);
|
||||||
|
|
||||||
/* Tests require IPv6 support */
|
/* Tests require IPv6 support */
|
||||||
sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
|
sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
if (sock >= 0) {
|
if (sock >= 0) {
|
||||||
close(sock);
|
close(sock);
|
||||||
tcase_add_test(tc, test_parse_format_ipv6);
|
tcase_add_test(tc, test_parse_format_ipv6);
|
||||||
tcase_add_test(tc, test_parse_format_ipv4_mapped_ipv6);
|
tcase_add_test(tc, test_parse_format_ipv4_mapped_ipv6);
|
||||||
}
|
}
|
||||||
return tc;
|
return tc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,81 +29,81 @@
|
||||||
|
|
||||||
static struct tuple
|
static struct tuple
|
||||||
{
|
{
|
||||||
char *a;
|
char *a;
|
||||||
char *b;
|
char *b;
|
||||||
} dottests[] = {
|
} dottests[] = {
|
||||||
{ "aaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
{ "aaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||||
"aaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaa"},
|
"aaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaa"},
|
||||||
{ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
{ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."},
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."},
|
||||||
{ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
{ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"},
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"},
|
||||||
{ "abc123", "abc123" },
|
{ "abc123", "abc123" },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
START_TEST(test_inline_dotify)
|
START_TEST(test_inline_dotify)
|
||||||
{
|
{
|
||||||
char temp[1024];
|
char temp[1024];
|
||||||
char *b;
|
char *b;
|
||||||
|
|
||||||
memset(temp, 0, sizeof(temp));
|
memset(temp, 0, sizeof(temp));
|
||||||
strcpy(temp, dottests[_i].a);
|
strcpy(temp, dottests[_i].a);
|
||||||
b = temp;
|
b = temp;
|
||||||
inline_dotify(b, sizeof(temp));
|
inline_dotify(b, sizeof(temp));
|
||||||
|
|
||||||
fail_unless(strcmp(dottests[_i].b, temp) == 0,
|
fail_unless(strcmp(dottests[_i].b, temp) == 0,
|
||||||
"'%s' != '%s'", temp, dottests[_i].b);
|
"'%s' != '%s'", temp, dottests[_i].b);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_inline_undotify)
|
START_TEST(test_inline_undotify)
|
||||||
{
|
{
|
||||||
char temp[1024];
|
char temp[1024];
|
||||||
char *b;
|
char *b;
|
||||||
|
|
||||||
memset(temp, 0, sizeof(temp));
|
memset(temp, 0, sizeof(temp));
|
||||||
strcpy(temp, dottests[_i].b);
|
strcpy(temp, dottests[_i].b);
|
||||||
b = temp;
|
b = temp;
|
||||||
inline_undotify(b, sizeof(temp));
|
inline_undotify(b, sizeof(temp));
|
||||||
|
|
||||||
fail_unless(strcmp(dottests[_i].a, temp) == 0,
|
fail_unless(strcmp(dottests[_i].a, temp) == 0,
|
||||||
"'%s' != '%s'", temp, dottests[_i].a);
|
"'%s' != '%s'", temp, dottests[_i].a);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_build_hostname)
|
START_TEST(test_build_hostname)
|
||||||
{
|
{
|
||||||
char data[256];
|
char data[256];
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
char *topdomain = "a.c";
|
char *topdomain = "a.c";
|
||||||
int buflen;
|
int buflen;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < sizeof(data); i++) {
|
for (i = 0; i < sizeof(data); i++) {
|
||||||
data[i] = i & 0xFF;
|
data[i] = i & 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
buflen = sizeof(buf);
|
buflen = sizeof(buf);
|
||||||
|
|
||||||
for (i = 1; i < sizeof(data); i++) {
|
for (i = 1; i < sizeof(data); i++) {
|
||||||
int len = build_hostname(buf, buflen, data, i, topdomain, get_base32_encoder(), sizeof(buf));
|
int len = build_hostname(buf, buflen, data, i, topdomain, get_base32_encoder(), sizeof(buf));
|
||||||
|
|
||||||
fail_if(len > i);
|
fail_if(len > i);
|
||||||
fail_if(strstr(buf, ".."), "Found double dots when encoding data len %d! buf: %s", i, buf);
|
fail_if(strstr(buf, ".."), "Found double dots when encoding data len %d! buf: %s", i, buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
TCase *
|
TCase *
|
||||||
test_encoding_create_tests()
|
test_encoding_create_tests()
|
||||||
{
|
{
|
||||||
TCase *tc;
|
TCase *tc;
|
||||||
|
|
||||||
tc = tcase_create("Encoding");
|
tc = tcase_create("Encoding");
|
||||||
tcase_add_loop_test(tc, test_inline_dotify, 0, TUPLES);
|
tcase_add_loop_test(tc, test_inline_dotify, 0, TUPLES);
|
||||||
tcase_add_loop_test(tc, test_inline_undotify, 0, TUPLES);
|
tcase_add_loop_test(tc, test_inline_undotify, 0, TUPLES);
|
||||||
tcase_add_test(tc, test_build_hostname);
|
tcase_add_test(tc, test_build_hostname);
|
||||||
|
|
||||||
return tc;
|
return tc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,68 +21,68 @@
|
||||||
|
|
||||||
START_TEST(test_fw_query_simple)
|
START_TEST(test_fw_query_simple)
|
||||||
{
|
{
|
||||||
struct fw_query q;
|
struct fw_query q;
|
||||||
struct fw_query *qp;
|
struct fw_query *qp;
|
||||||
|
|
||||||
q.addrlen = 33;
|
q.addrlen = 33;
|
||||||
q.id = 0x848A;
|
q.id = 0x848A;
|
||||||
|
|
||||||
fw_query_init();
|
fw_query_init();
|
||||||
|
|
||||||
/* Test empty cache */
|
/* Test empty cache */
|
||||||
fw_query_get(0x848A, &qp);
|
fw_query_get(0x848A, &qp);
|
||||||
fail_unless(qp == NULL);
|
fail_unless(qp == NULL);
|
||||||
|
|
||||||
fw_query_put(&q);
|
fw_query_put(&q);
|
||||||
|
|
||||||
/* Test cache with one entry */
|
/* Test cache with one entry */
|
||||||
fw_query_get(0x848A, &qp);
|
fw_query_get(0x848A, &qp);
|
||||||
fail_unless(qp->addrlen == q.addrlen);
|
fail_unless(qp->addrlen == q.addrlen);
|
||||||
fail_unless(qp->id == q.id);
|
fail_unless(qp->id == q.id);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_fw_query_edge)
|
START_TEST(test_fw_query_edge)
|
||||||
{
|
{
|
||||||
struct fw_query q;
|
struct fw_query q;
|
||||||
struct fw_query *qp;
|
struct fw_query *qp;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
fw_query_init();
|
fw_query_init();
|
||||||
|
|
||||||
q.addrlen = 33;
|
q.addrlen = 33;
|
||||||
q.id = 0x848A;
|
q.id = 0x848A;
|
||||||
fw_query_put(&q);
|
fw_query_put(&q);
|
||||||
|
|
||||||
for (i = 1; i < FW_QUERY_CACHE_SIZE; i++) {
|
for (i = 1; i < FW_QUERY_CACHE_SIZE; i++) {
|
||||||
q.addrlen++;
|
q.addrlen++;
|
||||||
q.id++;
|
q.id++;
|
||||||
fw_query_put(&q);
|
fw_query_put(&q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The query should still be cached */
|
/* The query should still be cached */
|
||||||
fw_query_get(0x848A, &qp);
|
fw_query_get(0x848A, &qp);
|
||||||
fail_unless(qp->addrlen == 33);
|
fail_unless(qp->addrlen == 33);
|
||||||
fail_unless(qp->id == 0x848A);
|
fail_unless(qp->id == 0x848A);
|
||||||
|
|
||||||
q.addrlen++;
|
q.addrlen++;
|
||||||
q.id++;
|
q.id++;
|
||||||
fw_query_put(&q);
|
fw_query_put(&q);
|
||||||
|
|
||||||
/* but now it is overwritten */
|
/* but now it is overwritten */
|
||||||
fw_query_get(0x848A, &qp);
|
fw_query_get(0x848A, &qp);
|
||||||
fail_unless(qp == NULL);
|
fail_unless(qp == NULL);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
TCase *
|
TCase *
|
||||||
test_fw_query_create_tests()
|
test_fw_query_create_tests()
|
||||||
{
|
{
|
||||||
TCase *tc;
|
TCase *tc;
|
||||||
|
|
||||||
tc = tcase_create("Forwarded query");
|
tc = tcase_create("Forwarded query");
|
||||||
tcase_add_test(tc, test_fw_query_simple);
|
tcase_add_test(tc, test_fw_query_simple);
|
||||||
tcase_add_test(tc, test_fw_query_edge);
|
tcase_add_test(tc, test_fw_query_edge);
|
||||||
|
|
||||||
return tc;
|
return tc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,49 +23,49 @@
|
||||||
|
|
||||||
START_TEST(test_login_hash)
|
START_TEST(test_login_hash)
|
||||||
{
|
{
|
||||||
char ans[16];
|
char ans[16];
|
||||||
char good[] = "\x2A\x8A\x12\xB4\xE0\x42\xEE\xAB\xD0\x19\x17\x1E\x44\xA0\x88\xCD";
|
char good[] = "\x2A\x8A\x12\xB4\xE0\x42\xEE\xAB\xD0\x19\x17\x1E\x44\xA0\x88\xCD";
|
||||||
char pass[32] = "iodine is the shit";
|
char pass[32] = "iodine is the shit";
|
||||||
int len;
|
int len;
|
||||||
int seed;
|
int seed;
|
||||||
|
|
||||||
len = sizeof(ans);
|
len = sizeof(ans);
|
||||||
seed = 15;
|
seed = 15;
|
||||||
|
|
||||||
memset(ans, 0, sizeof(ans));
|
memset(ans, 0, sizeof(ans));
|
||||||
login_calculate(ans, len, pass, seed);
|
login_calculate(ans, len, pass, seed);
|
||||||
fail_unless(strncmp(ans, good, len) == 0, NULL);
|
fail_unless(strncmp(ans, good, len) == 0, NULL);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_login_hash_short)
|
START_TEST(test_login_hash_short)
|
||||||
{
|
{
|
||||||
char ans[8];
|
char ans[8];
|
||||||
char check[sizeof(ans)];
|
char check[sizeof(ans)];
|
||||||
char pass[32] = "iodine is the shit";
|
char pass[32] = "iodine is the shit";
|
||||||
int len;
|
int len;
|
||||||
int seed;
|
int seed;
|
||||||
|
|
||||||
len = sizeof(ans);
|
len = sizeof(ans);
|
||||||
seed = 15;
|
seed = 15;
|
||||||
|
|
||||||
memset(ans, 0, sizeof(ans));
|
memset(ans, 0, sizeof(ans));
|
||||||
memset(check, 0, sizeof(check));
|
memset(check, 0, sizeof(check));
|
||||||
|
|
||||||
/* If len < 16, it should do nothing */
|
/* If len < 16, it should do nothing */
|
||||||
login_calculate(ans, len, pass, seed);
|
login_calculate(ans, len, pass, seed);
|
||||||
fail_if(memcmp(ans, check, sizeof(ans)));
|
fail_if(memcmp(ans, check, sizeof(ans)));
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
TCase *
|
TCase *
|
||||||
test_login_create_tests()
|
test_login_create_tests()
|
||||||
{
|
{
|
||||||
TCase *tc;
|
TCase *tc;
|
||||||
|
|
||||||
tc = tcase_create("Login");
|
tc = tcase_create("Login");
|
||||||
tcase_add_test(tc, test_login_hash);
|
tcase_add_test(tc, test_login_hash);
|
||||||
tcase_add_test(tc, test_login_hash_short);
|
tcase_add_test(tc, test_login_hash_short);
|
||||||
|
|
||||||
return tc;
|
return tc;
|
||||||
}
|
}
|
||||||
|
|
344
tests/read.c
344
tests/read.c
|
@ -38,234 +38,234 @@
|
||||||
|
|
||||||
START_TEST(test_read_putshort)
|
START_TEST(test_read_putshort)
|
||||||
{
|
{
|
||||||
unsigned short k;
|
unsigned short k;
|
||||||
unsigned short l;
|
unsigned short l;
|
||||||
char* p;
|
char* p;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < 65536; i++) {
|
for (i = 0; i < 65536; i++) {
|
||||||
p = (char*)&k;
|
p = (char*)&k;
|
||||||
putshort(&p, i);
|
putshort(&p, i);
|
||||||
fail_unless(ntohs(k) == i,
|
fail_unless(ntohs(k) == i,
|
||||||
"Bad value on putshort for %d: %d != %d",
|
"Bad value on putshort for %d: %d != %d",
|
||||||
i, ntohs(k), i);
|
i, ntohs(k), i);
|
||||||
|
|
||||||
p = (char*)&k;
|
p = (char*)&k;
|
||||||
readshort(NULL, &p, &l);
|
readshort(NULL, &p, &l);
|
||||||
fail_unless(l == i,
|
fail_unless(l == i,
|
||||||
"Bad value on readshort for %d: %d != %d",
|
"Bad value on readshort for %d: %d != %d",
|
||||||
i, l, i);
|
i, l, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_read_putlong)
|
START_TEST(test_read_putlong)
|
||||||
{
|
{
|
||||||
uint32_t k;
|
uint32_t k;
|
||||||
uint32_t l;
|
uint32_t l;
|
||||||
char* p;
|
char* p;
|
||||||
int i;
|
int i;
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
for (i = 0; i < 32; i++) {
|
for (i = 0; i < 32; i++) {
|
||||||
p = (char*)&k;
|
p = (char*)&k;
|
||||||
j = 0xf << i;
|
j = 0xf << i;
|
||||||
|
|
||||||
putlong(&p, j);
|
putlong(&p, j);
|
||||||
|
|
||||||
fail_unless(ntohl(k) == j,
|
fail_unless(ntohl(k) == j,
|
||||||
"Bad value on putlong for %d: %d != %d", i, ntohl(j), j);
|
"Bad value on putlong for %d: %d != %d", i, ntohl(j), j);
|
||||||
|
|
||||||
p = (char*)&k;
|
p = (char*)&k;
|
||||||
readlong(NULL, &p, &l);
|
readlong(NULL, &p, &l);
|
||||||
|
|
||||||
fail_unless(l == j,
|
fail_unless(l == j,
|
||||||
"Bad value on readlong for %d: %d != %d", i, l, j);
|
"Bad value on readlong for %d: %d != %d", i, l, j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_read_name_empty_loop)
|
START_TEST(test_read_name_empty_loop)
|
||||||
{
|
{
|
||||||
unsigned char emptyloop[] = {
|
unsigned char emptyloop[] = {
|
||||||
'A', 'A', 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
'A', 'A', 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01 };
|
0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01 };
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
char *data;
|
char *data;
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
data = (char*) emptyloop + sizeof(HEADER);
|
data = (char*) emptyloop + sizeof(HEADER);
|
||||||
buf[1023] = 'A';
|
buf[1023] = 'A';
|
||||||
rv = readname((char *) emptyloop, sizeof(emptyloop), &data, buf, 1023);
|
rv = readname((char *) emptyloop, sizeof(emptyloop), &data, buf, 1023);
|
||||||
fail_unless(rv == 0);
|
fail_unless(rv == 0);
|
||||||
fail_unless(buf[1023] == 'A');
|
fail_unless(buf[1023] == 'A');
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_read_name_inf_loop)
|
START_TEST(test_read_name_inf_loop)
|
||||||
{
|
{
|
||||||
unsigned char infloop[] = {
|
unsigned char infloop[] = {
|
||||||
'A', 'A', 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
'A', 'A', 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x01, 'A', 0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01 };
|
0x01, 'A', 0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01 };
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
char *data;
|
char *data;
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
data = (char*) infloop + sizeof(HEADER);
|
data = (char*) infloop + sizeof(HEADER);
|
||||||
buf[4] = '\a';
|
buf[4] = '\a';
|
||||||
rv = readname((char*) infloop, sizeof(infloop), &data, buf, 4);
|
rv = readname((char*) infloop, sizeof(infloop), &data, buf, 4);
|
||||||
fail_unless(rv == 3);
|
fail_unless(rv == 3);
|
||||||
fail_unless(buf[4] == '\a');
|
fail_unless(buf[4] == '\a');
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_read_name_longname)
|
START_TEST(test_read_name_longname)
|
||||||
{
|
{
|
||||||
unsigned char longname[] =
|
unsigned char longname[] =
|
||||||
"AA\x81\x80\x00\x01\x00\x00\x00\x00\x00\x00"
|
"AA\x81\x80\x00\x01\x00\x00\x00\x00\x00\x00"
|
||||||
"\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA"
|
"\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA"
|
||||||
"\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA"
|
"\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA"
|
||||||
"\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA"
|
"\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA"
|
||||||
"\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA"
|
"\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA"
|
||||||
"\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA"
|
"\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA"
|
||||||
"\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA"
|
"\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA"
|
||||||
"\x00\x00\x01\x00\x01";
|
"\x00\x00\x01\x00\x01";
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
char *data;
|
char *data;
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
data = (char*) longname + sizeof(HEADER);
|
data = (char*) longname + sizeof(HEADER);
|
||||||
buf[256] = '\a';
|
buf[256] = '\a';
|
||||||
rv = readname((char*) longname, sizeof(longname), &data, buf, 256);
|
rv = readname((char*) longname, sizeof(longname), &data, buf, 256);
|
||||||
fail_unless(rv == 256);
|
fail_unless(rv == 256);
|
||||||
fail_unless(buf[256] == '\a');
|
fail_unless(buf[256] == '\a');
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_read_name_onejump)
|
START_TEST(test_read_name_onejump)
|
||||||
{
|
{
|
||||||
unsigned char onejump[] =
|
unsigned char onejump[] =
|
||||||
"AA\x81\x80\x00\x01\x00\x00\x00\x00\x00\x00"
|
"AA\x81\x80\x00\x01\x00\x00\x00\x00\x00\x00"
|
||||||
"\x02hh\xc0\x15\x00\x01\x00\x01\x05zBCDE\x00";
|
"\x02hh\xc0\x15\x00\x01\x00\x01\x05zBCDE\x00";
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
char *data;
|
char *data;
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
data = (char*) onejump + sizeof(HEADER);
|
data = (char*) onejump + sizeof(HEADER);
|
||||||
rv = readname((char*) onejump, sizeof(onejump), &data, buf, 256);
|
rv = readname((char*) onejump, sizeof(onejump), &data, buf, 256);
|
||||||
fail_unless(rv == 9);
|
fail_unless(rv == 9);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_read_name_badjump_start)
|
START_TEST(test_read_name_badjump_start)
|
||||||
{
|
{
|
||||||
unsigned char badjump[] = {
|
unsigned char badjump[] = {
|
||||||
'A', 'A', 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
'A', 'A', 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0xfe, 0xcc, 0x00, 0x01, 0x00, 0x01 };
|
0xfe, 0xcc, 0x00, 0x01, 0x00, 0x01 };
|
||||||
unsigned char *jumper;
|
unsigned char *jumper;
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
char *data;
|
char *data;
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
/* This test uses malloc to cause segfault if jump is executed */
|
/* This test uses malloc to cause segfault if jump is executed */
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
jumper = malloc(sizeof(badjump));
|
jumper = malloc(sizeof(badjump));
|
||||||
if (jumper) {
|
if (jumper) {
|
||||||
memcpy(jumper, badjump, sizeof(badjump));
|
memcpy(jumper, badjump, sizeof(badjump));
|
||||||
data = (char*) jumper + sizeof(HEADER);
|
data = (char*) jumper + sizeof(HEADER);
|
||||||
rv = readname((char*) jumper, sizeof(badjump), &data, buf, 256);
|
rv = readname((char*) jumper, sizeof(badjump), &data, buf, 256);
|
||||||
|
|
||||||
fail_unless(rv == 0);
|
fail_unless(rv == 0);
|
||||||
fail_unless(buf[0] == 0);
|
fail_unless(buf[0] == 0);
|
||||||
}
|
}
|
||||||
free(jumper);
|
free(jumper);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_read_name_badjump_second)
|
START_TEST(test_read_name_badjump_second)
|
||||||
{
|
{
|
||||||
unsigned char badjump2[] = {
|
unsigned char badjump2[] = {
|
||||||
'A', 'A', 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
'A', 'A', 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x02, 'B', 'A', 0xfe, 0xcc, 0x00, 0x01, 0x00, 0x01 };
|
0x02, 'B', 'A', 0xfe, 0xcc, 0x00, 0x01, 0x00, 0x01 };
|
||||||
unsigned char *jumper;
|
unsigned char *jumper;
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
char *data;
|
char *data;
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
/* This test uses malloc to cause segfault if jump is executed */
|
/* This test uses malloc to cause segfault if jump is executed */
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
jumper = malloc(sizeof(badjump2));
|
jumper = malloc(sizeof(badjump2));
|
||||||
if (jumper) {
|
if (jumper) {
|
||||||
memcpy(jumper, badjump2, sizeof(badjump2));
|
memcpy(jumper, badjump2, sizeof(badjump2));
|
||||||
data = (char*) jumper + sizeof(HEADER);
|
data = (char*) jumper + sizeof(HEADER);
|
||||||
rv = readname((char*) jumper, sizeof(badjump2), &data, buf, 256);
|
rv = readname((char*) jumper, sizeof(badjump2), &data, buf, 256);
|
||||||
|
|
||||||
fail_unless(rv == 4);
|
fail_unless(rv == 4);
|
||||||
fail_unless(strcmp("BA.", buf) == 0,
|
fail_unless(strcmp("BA.", buf) == 0,
|
||||||
"buf is not BA: %s", buf);
|
"buf is not BA: %s", buf);
|
||||||
}
|
}
|
||||||
free(jumper);
|
free(jumper);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_putname)
|
START_TEST(test_putname)
|
||||||
{
|
{
|
||||||
char out[] = "\x06" "BADGER\x06" "BADGER\x04" "KRYO\x02" "SE\x00";
|
char out[] = "\x06" "BADGER\x06" "BADGER\x04" "KRYO\x02" "SE\x00";
|
||||||
char buf[256];
|
char buf[256];
|
||||||
char *domain = "BADGER.BADGER.KRYO.SE";
|
char *domain = "BADGER.BADGER.KRYO.SE";
|
||||||
char *b;
|
char *b;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
memset(buf, 0, 256);
|
memset(buf, 0, 256);
|
||||||
b = buf;
|
b = buf;
|
||||||
ret = putname(&b, 256, domain);
|
ret = putname(&b, 256, domain);
|
||||||
|
|
||||||
fail_unless(ret == strlen(domain) + 1);
|
fail_unless(ret == strlen(domain) + 1);
|
||||||
fail_unless(strncmp(buf, out, ret) == 0, "Happy flow failed");
|
fail_unless(strncmp(buf, out, ret) == 0, "Happy flow failed");
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_putname_nodot)
|
START_TEST(test_putname_nodot)
|
||||||
{
|
{
|
||||||
char buf[256];
|
char buf[256];
|
||||||
char *nodot =
|
char *nodot =
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||||
char *b;
|
char *b;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
memset(buf, 0, 256);
|
memset(buf, 0, 256);
|
||||||
b = buf;
|
b = buf;
|
||||||
ret = putname(&b, 256, nodot);
|
ret = putname(&b, 256, nodot);
|
||||||
|
|
||||||
fail_unless(ret == -1);
|
fail_unless(ret == -1);
|
||||||
fail_unless(b == buf);
|
fail_unless(b == buf);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_putname_toolong)
|
START_TEST(test_putname_toolong)
|
||||||
{
|
{
|
||||||
char buf[256];
|
char buf[256];
|
||||||
char *toolong =
|
char *toolong =
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ."
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ."
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ."
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ."
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ."
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ."
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ."
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ."
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ."
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ."
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ.";
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ.";
|
||||||
char *b;
|
char *b;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
memset(buf, 0, 256);
|
memset(buf, 0, 256);
|
||||||
b = buf;
|
b = buf;
|
||||||
ret = putname(&b, 256, toolong);
|
ret = putname(&b, 256, toolong);
|
||||||
|
|
||||||
fail_unless(ret == -1);
|
fail_unless(ret == -1);
|
||||||
fail_unless(b == buf);
|
fail_unless(b == buf);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
@ -273,21 +273,21 @@ END_TEST
|
||||||
TCase *
|
TCase *
|
||||||
test_read_create_tests()
|
test_read_create_tests()
|
||||||
{
|
{
|
||||||
TCase *tc;
|
TCase *tc;
|
||||||
|
|
||||||
tc = tcase_create("Read");
|
tc = tcase_create("Read");
|
||||||
tcase_set_timeout(tc, 60);
|
tcase_set_timeout(tc, 60);
|
||||||
tcase_add_test(tc, test_read_putshort);
|
tcase_add_test(tc, test_read_putshort);
|
||||||
tcase_add_test(tc, test_read_putlong);
|
tcase_add_test(tc, test_read_putlong);
|
||||||
tcase_add_test(tc, test_read_name_empty_loop);
|
tcase_add_test(tc, test_read_name_empty_loop);
|
||||||
tcase_add_test(tc, test_read_name_inf_loop);
|
tcase_add_test(tc, test_read_name_inf_loop);
|
||||||
tcase_add_test(tc, test_read_name_longname);
|
tcase_add_test(tc, test_read_name_longname);
|
||||||
tcase_add_test(tc, test_read_name_onejump);
|
tcase_add_test(tc, test_read_name_onejump);
|
||||||
tcase_add_test(tc, test_read_name_badjump_start);
|
tcase_add_test(tc, test_read_name_badjump_start);
|
||||||
tcase_add_test(tc, test_read_name_badjump_second);
|
tcase_add_test(tc, test_read_name_badjump_second);
|
||||||
tcase_add_test(tc, test_putname);
|
tcase_add_test(tc, test_putname);
|
||||||
tcase_add_test(tc, test_putname_nodot);
|
tcase_add_test(tc, test_putname_nodot);
|
||||||
tcase_add_test(tc, test_putname_toolong);
|
tcase_add_test(tc, test_putname_toolong);
|
||||||
|
|
||||||
return tc;
|
return tc;
|
||||||
}
|
}
|
||||||
|
|
56
tests/test.c
56
tests/test.c
|
@ -26,45 +26,45 @@
|
||||||
int
|
int
|
||||||
main()
|
main()
|
||||||
{
|
{
|
||||||
SRunner *runner;
|
SRunner *runner;
|
||||||
Suite *iodine;
|
Suite *iodine;
|
||||||
TCase *test;
|
TCase *test;
|
||||||
int failed;
|
int failed;
|
||||||
|
|
||||||
iodine = suite_create("iodine");
|
iodine = suite_create("iodine");
|
||||||
|
|
||||||
test = test_base32_create_tests();
|
test = test_base32_create_tests();
|
||||||
suite_add_tcase(iodine, test);
|
suite_add_tcase(iodine, test);
|
||||||
|
|
||||||
test = test_base64_create_tests();
|
test = test_base64_create_tests();
|
||||||
suite_add_tcase(iodine, test);
|
suite_add_tcase(iodine, test);
|
||||||
|
|
||||||
test = test_common_create_tests();
|
test = test_common_create_tests();
|
||||||
suite_add_tcase(iodine, test);
|
suite_add_tcase(iodine, test);
|
||||||
|
|
||||||
test = test_dns_create_tests();
|
test = test_dns_create_tests();
|
||||||
suite_add_tcase(iodine, test);
|
suite_add_tcase(iodine, test);
|
||||||
|
|
||||||
test = test_encoding_create_tests();
|
test = test_encoding_create_tests();
|
||||||
suite_add_tcase(iodine, test);
|
suite_add_tcase(iodine, test);
|
||||||
|
|
||||||
test = test_read_create_tests();
|
test = test_read_create_tests();
|
||||||
suite_add_tcase(iodine, test);
|
suite_add_tcase(iodine, test);
|
||||||
|
|
||||||
test = test_login_create_tests();
|
test = test_login_create_tests();
|
||||||
suite_add_tcase(iodine, test);
|
suite_add_tcase(iodine, test);
|
||||||
|
|
||||||
test = test_user_create_tests();
|
test = test_user_create_tests();
|
||||||
suite_add_tcase(iodine, test);
|
suite_add_tcase(iodine, test);
|
||||||
|
|
||||||
test = test_fw_query_create_tests();
|
test = test_fw_query_create_tests();
|
||||||
suite_add_tcase(iodine, test);
|
suite_add_tcase(iodine, test);
|
||||||
|
|
||||||
runner = srunner_create(iodine);
|
runner = srunner_create(iodine);
|
||||||
srunner_run_all(runner, CK_NORMAL);
|
srunner_run_all(runner, CK_NORMAL);
|
||||||
failed = srunner_ntests_failed(runner);
|
failed = srunner_ntests_failed(runner);
|
||||||
|
|
||||||
srunner_free(runner);
|
srunner_free(runner);
|
||||||
|
|
||||||
return (failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
|
return (failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,8 +31,8 @@ TCase *test_fw_query_create_tests();
|
||||||
char *va_str(const char *, ...);
|
char *va_str(const char *, ...);
|
||||||
|
|
||||||
#if (CHECK_MAJOR_VERSION == 0 && \
|
#if (CHECK_MAJOR_VERSION == 0 && \
|
||||||
((CHECK_MINOR_VERSION == 9 && CHECK_MICRO_VERSION < 2) || \
|
((CHECK_MINOR_VERSION == 9 && CHECK_MICRO_VERSION < 2) || \
|
||||||
(CHECK_MINOR_VERSION < 9)))
|
(CHECK_MINOR_VERSION < 9)))
|
||||||
#define tcase_set_timeout(...)
|
#define tcase_set_timeout(...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
202
tests/user.c
202
tests/user.c
|
@ -30,181 +30,181 @@
|
||||||
|
|
||||||
START_TEST(test_init_users)
|
START_TEST(test_init_users)
|
||||||
{
|
{
|
||||||
in_addr_t ip;
|
in_addr_t ip;
|
||||||
char givenip[16];
|
char givenip[16];
|
||||||
int i;
|
int i;
|
||||||
int count;
|
int count;
|
||||||
|
|
||||||
ip = inet_addr("127.0.0.1");
|
ip = inet_addr("127.0.0.1");
|
||||||
count = init_users(ip, 27);
|
count = init_users(ip, 27);
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
fail_unless(users[i].id == i);
|
fail_unless(users[i].id == i);
|
||||||
fail_unless(users[i].q.id == 0);
|
fail_unless(users[i].q.id == 0);
|
||||||
fail_unless(users[i].inpacket.len == 0);
|
fail_unless(users[i].inpacket.len == 0);
|
||||||
fail_unless(users[i].outpacket.len == 0);
|
fail_unless(users[i].outpacket.len == 0);
|
||||||
snprintf(givenip, sizeof(givenip), "127.0.0.%d", i + 2);
|
snprintf(givenip, sizeof(givenip), "127.0.0.%d", i + 2);
|
||||||
fail_unless(users[i].tun_ip == inet_addr(givenip));
|
fail_unless(users[i].tun_ip == inet_addr(givenip));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_users_waiting)
|
START_TEST(test_users_waiting)
|
||||||
{
|
{
|
||||||
in_addr_t ip;
|
in_addr_t ip;
|
||||||
|
|
||||||
ip = inet_addr("127.0.0.1");
|
ip = inet_addr("127.0.0.1");
|
||||||
init_users(ip, 27);
|
init_users(ip, 27);
|
||||||
|
|
||||||
fail_unless(users_waiting_on_reply() == 0);
|
fail_unless(users_waiting_on_reply() == 0);
|
||||||
|
|
||||||
users[3].active = 1;
|
users[3].active = 1;
|
||||||
|
|
||||||
fail_unless(users_waiting_on_reply() == 0);
|
fail_unless(users_waiting_on_reply() == 0);
|
||||||
|
|
||||||
users[3].last_pkt = time(NULL);
|
users[3].last_pkt = time(NULL);
|
||||||
|
|
||||||
fail_unless(users_waiting_on_reply() == 0);
|
fail_unless(users_waiting_on_reply() == 0);
|
||||||
|
|
||||||
users[3].conn = CONN_DNS_NULL;
|
users[3].conn = CONN_DNS_NULL;
|
||||||
users[3].q.id = 1;
|
users[3].q.id = 1;
|
||||||
|
|
||||||
fail_unless(users_waiting_on_reply() == 1);
|
fail_unless(users_waiting_on_reply() == 1);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_find_user_by_ip)
|
START_TEST(test_find_user_by_ip)
|
||||||
{
|
{
|
||||||
in_addr_t ip;
|
in_addr_t ip;
|
||||||
unsigned int testip;
|
unsigned int testip;
|
||||||
|
|
||||||
ip = inet_addr("127.0.0.1");
|
ip = inet_addr("127.0.0.1");
|
||||||
init_users(ip, 27);
|
init_users(ip, 27);
|
||||||
users[0].conn = CONN_DNS_NULL;
|
users[0].conn = CONN_DNS_NULL;
|
||||||
|
|
||||||
testip = (unsigned int) inet_addr("10.0.0.1");
|
testip = (unsigned int) inet_addr("10.0.0.1");
|
||||||
fail_unless(find_user_by_ip(testip) == -1);
|
fail_unless(find_user_by_ip(testip) == -1);
|
||||||
|
|
||||||
testip = (unsigned int) inet_addr("127.0.0.2");
|
testip = (unsigned int) inet_addr("127.0.0.2");
|
||||||
fail_unless(find_user_by_ip(testip) == -1);
|
fail_unless(find_user_by_ip(testip) == -1);
|
||||||
|
|
||||||
users[0].active = 1;
|
users[0].active = 1;
|
||||||
|
|
||||||
testip = (unsigned int) inet_addr("127.0.0.2");
|
testip = (unsigned int) inet_addr("127.0.0.2");
|
||||||
fail_unless(find_user_by_ip(testip) == -1);
|
fail_unless(find_user_by_ip(testip) == -1);
|
||||||
|
|
||||||
users[0].last_pkt = time(NULL);
|
users[0].last_pkt = time(NULL);
|
||||||
|
|
||||||
testip = (unsigned int) inet_addr("127.0.0.2");
|
testip = (unsigned int) inet_addr("127.0.0.2");
|
||||||
fail_unless(find_user_by_ip(testip) == -1);
|
fail_unless(find_user_by_ip(testip) == -1);
|
||||||
|
|
||||||
users[0].authenticated = 1;
|
users[0].authenticated = 1;
|
||||||
|
|
||||||
testip = (unsigned int) inet_addr("127.0.0.2");
|
testip = (unsigned int) inet_addr("127.0.0.2");
|
||||||
fail_unless(find_user_by_ip(testip) == 0);
|
fail_unless(find_user_by_ip(testip) == 0);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_all_users_waiting_to_send)
|
START_TEST(test_all_users_waiting_to_send)
|
||||||
{
|
{
|
||||||
in_addr_t ip;
|
in_addr_t ip;
|
||||||
|
|
||||||
ip = inet_addr("127.0.0.1");
|
ip = inet_addr("127.0.0.1");
|
||||||
init_users(ip, 27);
|
init_users(ip, 27);
|
||||||
|
|
||||||
fail_unless(all_users_waiting_to_send() == 1);
|
fail_unless(all_users_waiting_to_send() == 1);
|
||||||
|
|
||||||
users[0].conn = CONN_DNS_NULL;
|
users[0].conn = CONN_DNS_NULL;
|
||||||
users[0].active = 1;
|
users[0].active = 1;
|
||||||
|
|
||||||
fail_unless(all_users_waiting_to_send() == 1);
|
fail_unless(all_users_waiting_to_send() == 1);
|
||||||
|
|
||||||
users[0].last_pkt = time(NULL);
|
users[0].last_pkt = time(NULL);
|
||||||
users[0].outpacket.len = 0;
|
users[0].outpacket.len = 0;
|
||||||
|
|
||||||
fail_unless(all_users_waiting_to_send() == 0);
|
fail_unless(all_users_waiting_to_send() == 0);
|
||||||
|
|
||||||
#ifdef OUTPACKETQ_LEN
|
#ifdef OUTPACKETQ_LEN
|
||||||
users[0].outpacketq_filled = 1;
|
users[0].outpacketq_filled = 1;
|
||||||
#else
|
#else
|
||||||
users[0].outpacket.len = 44;
|
users[0].outpacket.len = 44;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
fail_unless(all_users_waiting_to_send() == 1);
|
fail_unless(all_users_waiting_to_send() == 1);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_find_available_user)
|
START_TEST(test_find_available_user)
|
||||||
{
|
{
|
||||||
in_addr_t ip;
|
in_addr_t ip;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
ip = inet_addr("127.0.0.1");
|
ip = inet_addr("127.0.0.1");
|
||||||
init_users(ip, 27);
|
init_users(ip, 27);
|
||||||
|
|
||||||
for (i = 0; i < USERS; i++) {
|
for (i = 0; i < USERS; i++) {
|
||||||
users[i].authenticated = 1;
|
users[i].authenticated = 1;
|
||||||
users[i].authenticated_raw = 1;
|
users[i].authenticated_raw = 1;
|
||||||
fail_unless(find_available_user() == i);
|
fail_unless(find_available_user() == i);
|
||||||
fail_if(users[i].authenticated);
|
fail_if(users[i].authenticated);
|
||||||
fail_if(users[i].authenticated_raw);
|
fail_if(users[i].authenticated_raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < USERS; i++) {
|
for (i = 0; i < USERS; i++) {
|
||||||
fail_unless(find_available_user() == -1);
|
fail_unless(find_available_user() == -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
users[3].active = 0;
|
users[3].active = 0;
|
||||||
|
|
||||||
fail_unless(find_available_user() == 3);
|
fail_unless(find_available_user() == 3);
|
||||||
fail_unless(find_available_user() == -1);
|
fail_unless(find_available_user() == -1);
|
||||||
|
|
||||||
users[3].last_pkt = 55;
|
users[3].last_pkt = 55;
|
||||||
|
|
||||||
fail_unless(find_available_user() == 3);
|
fail_unless(find_available_user() == 3);
|
||||||
fail_unless(find_available_user() == -1);
|
fail_unless(find_available_user() == -1);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_find_available_user_small_net)
|
START_TEST(test_find_available_user_small_net)
|
||||||
{
|
{
|
||||||
in_addr_t ip;
|
in_addr_t ip;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
ip = inet_addr("127.0.0.1");
|
ip = inet_addr("127.0.0.1");
|
||||||
init_users(ip, 29); /* this should result in 5 enabled users */
|
init_users(ip, 29); /* this should result in 5 enabled users */
|
||||||
|
|
||||||
for (i = 0; i < 5; i++) {
|
for (i = 0; i < 5; i++) {
|
||||||
fail_unless(find_available_user() == i);
|
fail_unless(find_available_user() == i);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < USERS; i++) {
|
for (i = 0; i < USERS; i++) {
|
||||||
fail_unless(find_available_user() == -1);
|
fail_unless(find_available_user() == -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
users[3].active = 0;
|
users[3].active = 0;
|
||||||
|
|
||||||
fail_unless(find_available_user() == 3);
|
fail_unless(find_available_user() == 3);
|
||||||
fail_unless(find_available_user() == -1);
|
fail_unless(find_available_user() == -1);
|
||||||
|
|
||||||
users[3].last_pkt = 55;
|
users[3].last_pkt = 55;
|
||||||
|
|
||||||
fail_unless(find_available_user() == 3);
|
fail_unless(find_available_user() == 3);
|
||||||
fail_unless(find_available_user() == -1);
|
fail_unless(find_available_user() == -1);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
TCase *
|
TCase *
|
||||||
test_user_create_tests()
|
test_user_create_tests()
|
||||||
{
|
{
|
||||||
TCase *tc;
|
TCase *tc;
|
||||||
|
|
||||||
tc = tcase_create("User");
|
tc = tcase_create("User");
|
||||||
tcase_add_test(tc, test_init_users);
|
tcase_add_test(tc, test_init_users);
|
||||||
tcase_add_test(tc, test_users_waiting);
|
tcase_add_test(tc, test_users_waiting);
|
||||||
tcase_add_test(tc, test_find_user_by_ip);
|
tcase_add_test(tc, test_find_user_by_ip);
|
||||||
tcase_add_test(tc, test_all_users_waiting_to_send);
|
tcase_add_test(tc, test_all_users_waiting_to_send);
|
||||||
tcase_add_test(tc, test_find_available_user);
|
tcase_add_test(tc, test_find_available_user);
|
||||||
tcase_add_test(tc, test_find_available_user_small_net);
|
tcase_add_test(tc, test_find_available_user_small_net);
|
||||||
|
|
||||||
return tc;
|
return tc;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue