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