mirror of
https://github.com/yarrick/iodine.git
synced 2025-04-04 05:43:33 +03:00
Merge 0e9d1bd328
into 9a45c4aa66
This commit is contained in:
commit
2e8df17917
34 changed files with 5867 additions and 6323 deletions
|
@ -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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
COMMONOBJS = tun.o dns.o read.o encoding.o login.o base32.o base64.o base64u.o base128.o md5.o common.o
|
||||
COMMONOBJS = tun.o dns.o read.o encoding.o login.o base32.o base64.o base64u.o base128.o common.o
|
||||
CLIENTOBJS = iodine.o client.o util.o
|
||||
CLIENT = ../bin/iodine
|
||||
SERVEROBJS = iodined.o user.o fw_query.o
|
||||
|
@ -9,7 +9,7 @@ ARCH = `uname -m`
|
|||
HEAD_COMMIT = `git rev-parse --short HEAD`
|
||||
|
||||
LIBPATH = -L.
|
||||
LDFLAGS += -lz `sh osflags $(TARGETOS) link` $(LIBPATH)
|
||||
LDFLAGS += -lssl -lz `sh osflags $(TARGETOS) link` $(LIBPATH)
|
||||
CFLAGS += -std=c99 -c -g -Wall -D$(OS) -pedantic `sh osflags $(TARGETOS) cflags` -DGITREVISION=\"$(HEAD_COMMIT)\"
|
||||
|
||||
all: stateos $(CLIENT) $(SERVER)
|
||||
|
|
|
@ -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 = 0,
|
||||
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
57
src/login.c
57
src/login.c
|
@ -25,7 +25,27 @@
|
|||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include "md5.h"
|
||||
#if defined( __APPLE__ )
|
||||
|
||||
#include <CommonCrypto/CommonDigest.h>
|
||||
|
||||
#ifdef MD5_DIGEST_LENGTH
|
||||
|
||||
#undef MD5_DIGEST_LENGTH
|
||||
|
||||
#endif
|
||||
|
||||
#define MD5_Init CC_MD5_Init
|
||||
#define MD5_Update CC_MD5_Update
|
||||
#define MD5_Final CC_MD5_Final
|
||||
#define MD5_DIGEST_LENGTH CC_MD5_DIGEST_LENGTH
|
||||
#define MD5_CTX CC_MD5_CTX
|
||||
|
||||
#else
|
||||
|
||||
#include <openssl/md5.h>
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Needs a 16byte array for output, and 32 bytes password
|
||||
|
@ -33,27 +53,26 @@
|
|||
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];
|
||||
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);
|
||||
}
|
||||
|
||||
md5_init(&ctx);
|
||||
md5_append(&ctx, temp, 32);
|
||||
md5_finish(&ctx, (unsigned char *) buf);
|
||||
for (i = 0; i < 8; i++) {
|
||||
k = ntohl(*ix);
|
||||
k ^= seed;
|
||||
*ix++ = htonl(k);
|
||||
}
|
||||
|
||||
MD5_CTX md5;
|
||||
MD5_Init(&md5);
|
||||
MD5_Update(&md5, temp, sizeof(temp));
|
||||
MD5_Final((unsigned char *)buf, &md5);
|
||||
}
|
||||
|
||||
|
|
384
src/md5.c
384
src/md5.c
|
@ -1,384 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
L. Peter Deutsch
|
||||
ghost@aladdin.com
|
||||
|
||||
*/
|
||||
/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */
|
||||
/*
|
||||
Independent implementation of MD5 (RFC 1321).
|
||||
|
||||
This code implements the MD5 Algorithm defined in RFC 1321, whose
|
||||
text is available at
|
||||
http://www.ietf.org/rfc/rfc1321.txt
|
||||
The code is derived from the text of the RFC, including the test suite
|
||||
(section A.5) but excluding the rest of Appendix A. It does not include
|
||||
any code or documentation that is identified in the RFC as being
|
||||
copyrighted.
|
||||
|
||||
The original and principal author of md5.c is L. Peter Deutsch
|
||||
<ghost@aladdin.com>. Other authors are noted in the change history
|
||||
that follows (in reverse chronological order):
|
||||
|
||||
2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
|
||||
either statically or dynamically; added missing #include <string.h>
|
||||
in library.
|
||||
2002-03-11 lpd Corrected argument list for main(), and added int return
|
||||
type, in test program and T value program.
|
||||
2002-02-21 lpd Added missing #include <stdio.h> in test program.
|
||||
2000-07-03 lpd Patched to eliminate warnings about "constant is
|
||||
unsigned in ANSI C, signed in traditional"; made test program
|
||||
self-checking.
|
||||
1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
|
||||
1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
|
||||
1999-05-03 lpd Original version.
|
||||
*/
|
||||
|
||||
#include "md5.h"
|
||||
#include <string.h>
|
||||
|
||||
#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
|
||||
#ifdef ARCH_IS_BIG_ENDIAN
|
||||
# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
|
||||
#else
|
||||
# define BYTE_ORDER 0
|
||||
#endif
|
||||
|
||||
#define T_MASK ((md5_word_t)~0)
|
||||
#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
|
||||
#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
|
||||
#define T3 0x242070db
|
||||
#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
|
||||
#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
|
||||
#define T6 0x4787c62a
|
||||
#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
|
||||
#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
|
||||
#define T9 0x698098d8
|
||||
#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
|
||||
#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
|
||||
#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
|
||||
#define T13 0x6b901122
|
||||
#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
|
||||
#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
|
||||
#define T16 0x49b40821
|
||||
#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
|
||||
#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
|
||||
#define T19 0x265e5a51
|
||||
#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
|
||||
#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
|
||||
#define T22 0x02441453
|
||||
#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
|
||||
#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
|
||||
#define T25 0x21e1cde6
|
||||
#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
|
||||
#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
|
||||
#define T28 0x455a14ed
|
||||
#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
|
||||
#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
|
||||
#define T31 0x676f02d9
|
||||
#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
|
||||
#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
|
||||
#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
|
||||
#define T35 0x6d9d6122
|
||||
#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
|
||||
#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
|
||||
#define T38 0x4bdecfa9
|
||||
#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
|
||||
#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
|
||||
#define T41 0x289b7ec6
|
||||
#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
|
||||
#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
|
||||
#define T44 0x04881d05
|
||||
#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
|
||||
#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
|
||||
#define T47 0x1fa27cf8
|
||||
#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
|
||||
#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
|
||||
#define T50 0x432aff97
|
||||
#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
|
||||
#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
|
||||
#define T53 0x655b59c3
|
||||
#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
|
||||
#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
|
||||
#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
|
||||
#define T57 0x6fa87e4f
|
||||
#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
|
||||
#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
|
||||
#define T60 0x4e0811a1
|
||||
#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
|
||||
#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
|
||||
#define T63 0x2ad7d2bb
|
||||
#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
|
||||
|
||||
|
||||
static void
|
||||
md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
|
||||
{
|
||||
md5_word_t
|
||||
a = pms->abcd[0], b = pms->abcd[1],
|
||||
c = pms->abcd[2], d = pms->abcd[3];
|
||||
md5_word_t t;
|
||||
#if BYTE_ORDER > 0
|
||||
/* Define storage only for big-endian CPUs. */
|
||||
md5_word_t X[16];
|
||||
#else
|
||||
/* Define storage for little-endian or both types of CPUs. */
|
||||
md5_word_t xbuf[16];
|
||||
const md5_word_t *X;
|
||||
#endif
|
||||
|
||||
{
|
||||
#if BYTE_ORDER == 0
|
||||
/*
|
||||
* Determine dynamically whether this is a big-endian or
|
||||
* little-endian machine, since we can use a more efficient
|
||||
* algorithm on the latter.
|
||||
*/
|
||||
static const int w = 1;
|
||||
|
||||
if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
|
||||
#endif
|
||||
#if BYTE_ORDER <= 0 /* little-endian */
|
||||
{
|
||||
/*
|
||||
* On little-endian machines, we can process properly aligned
|
||||
* data without copying it.
|
||||
*/
|
||||
if (!((data - (const md5_byte_t *)0) & 3)) {
|
||||
/* data are properly aligned */
|
||||
X = (const md5_word_t *)data;
|
||||
} else {
|
||||
/* not aligned */
|
||||
memcpy(xbuf, data, 64);
|
||||
X = xbuf;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if BYTE_ORDER == 0
|
||||
else /* dynamic big-endian */
|
||||
#endif
|
||||
#if BYTE_ORDER >= 0 /* big-endian */
|
||||
{
|
||||
/*
|
||||
* On big-endian machines, we must arrange the bytes in the
|
||||
* right order.
|
||||
*/
|
||||
const md5_byte_t *xp = data;
|
||||
int i;
|
||||
|
||||
# if BYTE_ORDER == 0
|
||||
X = xbuf; /* (dynamic only) */
|
||||
# else
|
||||
# define xbuf X /* (static only) */
|
||||
# endif
|
||||
for (i = 0; i < 16; ++i, xp += 4)
|
||||
xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
|
||||
|
||||
/* Round 1. */
|
||||
/* Let [abcd k s i] denote the operation
|
||||
a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + F(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 0, 7, T1);
|
||||
SET(d, a, b, c, 1, 12, T2);
|
||||
SET(c, d, a, b, 2, 17, T3);
|
||||
SET(b, c, d, a, 3, 22, T4);
|
||||
SET(a, b, c, d, 4, 7, T5);
|
||||
SET(d, a, b, c, 5, 12, T6);
|
||||
SET(c, d, a, b, 6, 17, T7);
|
||||
SET(b, c, d, a, 7, 22, T8);
|
||||
SET(a, b, c, d, 8, 7, T9);
|
||||
SET(d, a, b, c, 9, 12, T10);
|
||||
SET(c, d, a, b, 10, 17, T11);
|
||||
SET(b, c, d, a, 11, 22, T12);
|
||||
SET(a, b, c, d, 12, 7, T13);
|
||||
SET(d, a, b, c, 13, 12, T14);
|
||||
SET(c, d, a, b, 14, 17, T15);
|
||||
SET(b, c, d, a, 15, 22, T16);
|
||||
#undef SET
|
||||
|
||||
/* Round 2. */
|
||||
/* Let [abcd k s i] denote the operation
|
||||
a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + G(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 1, 5, T17);
|
||||
SET(d, a, b, c, 6, 9, T18);
|
||||
SET(c, d, a, b, 11, 14, T19);
|
||||
SET(b, c, d, a, 0, 20, T20);
|
||||
SET(a, b, c, d, 5, 5, T21);
|
||||
SET(d, a, b, c, 10, 9, T22);
|
||||
SET(c, d, a, b, 15, 14, T23);
|
||||
SET(b, c, d, a, 4, 20, T24);
|
||||
SET(a, b, c, d, 9, 5, T25);
|
||||
SET(d, a, b, c, 14, 9, T26);
|
||||
SET(c, d, a, b, 3, 14, T27);
|
||||
SET(b, c, d, a, 8, 20, T28);
|
||||
SET(a, b, c, d, 13, 5, T29);
|
||||
SET(d, a, b, c, 2, 9, T30);
|
||||
SET(c, d, a, b, 7, 14, T31);
|
||||
SET(b, c, d, a, 12, 20, T32);
|
||||
#undef SET
|
||||
|
||||
/* Round 3. */
|
||||
/* Let [abcd k s t] denote the operation
|
||||
a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define H(x, y, z) ((x) ^ (y) ^ (z))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + H(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 5, 4, T33);
|
||||
SET(d, a, b, c, 8, 11, T34);
|
||||
SET(c, d, a, b, 11, 16, T35);
|
||||
SET(b, c, d, a, 14, 23, T36);
|
||||
SET(a, b, c, d, 1, 4, T37);
|
||||
SET(d, a, b, c, 4, 11, T38);
|
||||
SET(c, d, a, b, 7, 16, T39);
|
||||
SET(b, c, d, a, 10, 23, T40);
|
||||
SET(a, b, c, d, 13, 4, T41);
|
||||
SET(d, a, b, c, 0, 11, T42);
|
||||
SET(c, d, a, b, 3, 16, T43);
|
||||
SET(b, c, d, a, 6, 23, T44);
|
||||
SET(a, b, c, d, 9, 4, T45);
|
||||
SET(d, a, b, c, 12, 11, T46);
|
||||
SET(c, d, a, b, 15, 16, T47);
|
||||
SET(b, c, d, a, 2, 23, T48);
|
||||
#undef SET
|
||||
|
||||
/* Round 4. */
|
||||
/* Let [abcd k s t] denote the operation
|
||||
a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + I(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 0, 6, T49);
|
||||
SET(d, a, b, c, 7, 10, T50);
|
||||
SET(c, d, a, b, 14, 15, T51);
|
||||
SET(b, c, d, a, 5, 21, T52);
|
||||
SET(a, b, c, d, 12, 6, T53);
|
||||
SET(d, a, b, c, 3, 10, T54);
|
||||
SET(c, d, a, b, 10, 15, T55);
|
||||
SET(b, c, d, a, 1, 21, T56);
|
||||
SET(a, b, c, d, 8, 6, T57);
|
||||
SET(d, a, b, c, 15, 10, T58);
|
||||
SET(c, d, a, b, 6, 15, T59);
|
||||
SET(b, c, d, a, 13, 21, T60);
|
||||
SET(a, b, c, d, 4, 6, T61);
|
||||
SET(d, a, b, c, 11, 10, T62);
|
||||
SET(c, d, a, b, 2, 15, T63);
|
||||
SET(b, c, d, a, 9, 21, T64);
|
||||
#undef SET
|
||||
|
||||
/* Then perform the following additions. (That is increment each
|
||||
of the four registers by the value it had before this block
|
||||
was started.) */
|
||||
pms->abcd[0] += a;
|
||||
pms->abcd[1] += b;
|
||||
pms->abcd[2] += c;
|
||||
pms->abcd[3] += d;
|
||||
}
|
||||
|
||||
void
|
||||
md5_init(md5_state_t *pms)
|
||||
{
|
||||
pms->count[0] = pms->count[1] = 0;
|
||||
pms->abcd[0] = 0x67452301;
|
||||
pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
|
||||
pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
|
||||
pms->abcd[3] = 0x10325476;
|
||||
}
|
||||
|
||||
void
|
||||
md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
|
||||
{
|
||||
const md5_byte_t *p = data;
|
||||
int left = nbytes;
|
||||
int offset = (pms->count[0] >> 3) & 63;
|
||||
md5_word_t nbits = (md5_word_t)(nbytes << 3);
|
||||
|
||||
if (nbytes <= 0)
|
||||
return;
|
||||
|
||||
/* Update the message length. */
|
||||
pms->count[1] += nbytes >> 29;
|
||||
pms->count[0] += nbits;
|
||||
if (pms->count[0] < nbits)
|
||||
pms->count[1]++;
|
||||
|
||||
/* Process an initial partial block. */
|
||||
if (offset) {
|
||||
int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
|
||||
|
||||
memcpy(pms->buf + offset, p, copy);
|
||||
if (offset + copy < 64)
|
||||
return;
|
||||
p += copy;
|
||||
left -= copy;
|
||||
md5_process(pms, pms->buf);
|
||||
}
|
||||
|
||||
/* Process full blocks. */
|
||||
for (; left >= 64; p += 64, left -= 64)
|
||||
md5_process(pms, p);
|
||||
|
||||
/* Process a final partial block. */
|
||||
if (left)
|
||||
memcpy(pms->buf, p, left);
|
||||
}
|
||||
|
||||
void
|
||||
md5_finish(md5_state_t *pms, md5_byte_t digest[16])
|
||||
{
|
||||
static const md5_byte_t pad[64] = {
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
md5_byte_t data[8];
|
||||
int i;
|
||||
|
||||
/* Save the length before padding. */
|
||||
for (i = 0; i < 8; ++i)
|
||||
data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
|
||||
/* Pad to 56 bytes mod 64. */
|
||||
md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
|
||||
/* Append the length. */
|
||||
md5_append(pms, data, 8);
|
||||
for (i = 0; i < 16; ++i)
|
||||
digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
|
||||
}
|
||||
|
||||
|
||||
|
91
src/md5.h
91
src/md5.h
|
@ -1,91 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved.
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
L. Peter Deutsch
|
||||
ghost@aladdin.com
|
||||
|
||||
*/
|
||||
/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */
|
||||
/*
|
||||
Independent implementation of MD5 (RFC 1321).
|
||||
|
||||
This code implements the MD5 Algorithm defined in RFC 1321, whose
|
||||
text is available at
|
||||
http://www.ietf.org/rfc/rfc1321.txt
|
||||
The code is derived from the text of the RFC, including the test suite
|
||||
(section A.5) but excluding the rest of Appendix A. It does not include
|
||||
any code or documentation that is identified in the RFC as being
|
||||
copyrighted.
|
||||
|
||||
The original and principal author of md5.h is L. Peter Deutsch
|
||||
<ghost@aladdin.com>. Other authors are noted in the change history
|
||||
that follows (in reverse chronological order):
|
||||
|
||||
2002-04-13 lpd Removed support for non-ANSI compilers; removed
|
||||
references to Ghostscript; clarified derivation from RFC 1321;
|
||||
now handles byte order either statically or dynamically.
|
||||
1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
|
||||
1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
|
||||
added conditionalization for C++ compilation from Martin
|
||||
Purschke <purschke@bnl.gov>.
|
||||
1999-05-03 lpd Original version.
|
||||
*/
|
||||
|
||||
#ifndef md5_INCLUDED
|
||||
# define md5_INCLUDED
|
||||
|
||||
/*
|
||||
* This package supports both compile-time and run-time determination of CPU
|
||||
* byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
|
||||
* compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
|
||||
* defined as non-zero, the code will be compiled to run only on big-endian
|
||||
* CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
|
||||
* run on either big- or little-endian CPUs, but will run slightly less
|
||||
* efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
|
||||
*/
|
||||
|
||||
typedef unsigned char md5_byte_t; /* 8-bit byte */
|
||||
typedef unsigned int md5_word_t; /* 32-bit word */
|
||||
|
||||
/* Define the state of the MD5 Algorithm. */
|
||||
typedef struct md5_state_s {
|
||||
md5_word_t count[2]; /* message length in bits, lsw first */
|
||||
md5_word_t abcd[4]; /* digest buffer */
|
||||
md5_byte_t buf[64]; /* accumulate block */
|
||||
} md5_state_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/* Initialize the algorithm. */
|
||||
void md5_init(md5_state_t *pms);
|
||||
|
||||
/* Append a string to the message. */
|
||||
void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
|
||||
|
||||
/* Finish the message and return the digest. */
|
||||
void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* md5_INCLUDED */
|
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 < CONN_RAW_UDP || 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…
Add table
Reference in a new issue