From 515bfb00a6dd7d9e71bb6bb0eefa81c028f45693 Mon Sep 17 00:00:00 2001 From: Ryan Welton Date: Fri, 8 Aug 2014 21:48:41 -0400 Subject: [PATCH] Tabz -> Spaces + whitespace --- doc/iodine.te | 16 +- doc/proto_00000402.txt | 62 +- doc/proto_00000500.txt | 122 +- doc/proto_00000502.txt | 286 +-- src/android_dns.h | 56 +- src/client.c | 3270 +++++++++++++++++----------------- src/common.c | 470 ++--- src/common.h | 38 +- src/dns.h | 4 +- src/encoding.c | 142 +- src/encoding.h | 14 +- src/fw_query.c | 28 +- src/fw_query.h | 6 +- src/iodine.c | 542 +++--- src/iodined.c | 3816 ++++++++++++++++++++-------------------- src/login.c | 34 +- src/read.c | 306 ++-- src/tun.c | 698 ++++---- src/user.c | 212 +-- src/user.h | 72 +- src/util.c | 90 +- tests/base32.c | 136 +- tests/base64.c | 170 +- tests/common.c | 266 +-- tests/encoding.c | 92 +- tests/fw_query.c | 80 +- tests/login.c | 54 +- tests/read.c | 344 ++-- tests/test.c | 56 +- tests/test.h | 4 +- tests/user.c | 202 +-- 31 files changed, 5844 insertions(+), 5844 deletions(-) diff --git a/doc/iodine.te b/doc/iodine.te index 9749f03..7a0075a 100644 --- a/doc/iodine.te +++ b/doc/iodine.te @@ -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; diff --git a/doc/proto_00000402.txt b/doc/proto_00000402.txt index da36919..9174bd2 100644 --- a/doc/proto_00000402.txt +++ b/doc/proto_00000402.txt @@ -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. diff --git a/doc/proto_00000500.txt b/doc/proto_00000500.txt index 05f100c..1945b09 100644 --- a/doc/proto_00000500.txt +++ b/doc/proto_00000500.txt @@ -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. diff --git a/doc/proto_00000502.txt b/doc/proto_00000502.txt index 831824d..2dcf6ab 100644 --- a/doc/proto_00000502.txt +++ b/doc/proto_00000502.txt @@ -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 diff --git a/src/android_dns.h b/src/android_dns.h index 0085af6..ef63d12 100644 --- a/src/android_dns.h +++ b/src/android_dns.h @@ -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 diff --git a/src/client.c b/src/client.c index b0bb68c..5fae09a 100644 --- a/src/client.c +++ b/src/client.c @@ -76,8 +76,8 @@ int outchunkresent = 0; /* My userid at the server */ static char userid; -static char userid_char; /* used when sending (lowercase) */ -static char userid_char2; /* also accepted when receiving (uppercase) */ +static char userid_char; /* used when sending (lowercase) */ +static char userid_char2; /* also accepted when receiving (uppercase) */ /* DNS id for next packet */ static uint16_t chunkid; @@ -104,7 +104,7 @@ static unsigned short do_qtype = T_UNSET; /* My connection mode */ static enum connection conn; -static int selecttimeout; /* RFC says timeout minimum 5sec */ +static int selecttimeout; /* RFC says timeout minimum 5sec */ static int lazymode; static long send_ping_soon; static time_t lastdownstreamtime; @@ -115,309 +115,309 @@ static int hostname_maxlen = 0xFF; void client_init() { - running = 1; - b32 = get_base32_encoder(); - b64 = get_base64_encoder(); - b64u = get_base64u_encoder(); - b128 = get_base128_encoder(); - dataenc = get_base32_encoder(); - rand_seed = ((unsigned int) rand()) & 0xFFFF; - send_ping_soon = 1; /* send ping immediately after startup */ - conn = CONN_DNS_NULL; + running = 1; + b32 = get_base32_encoder(); + b64 = get_base64_encoder(); + b64u = get_base64u_encoder(); + b128 = get_base128_encoder(); + dataenc = get_base32_encoder(); + rand_seed = ((unsigned int) rand()) & 0xFFFF; + send_ping_soon = 1; /* send ping immediately after startup */ + conn = CONN_DNS_NULL; - chunkid = ((unsigned int) rand()) & 0xFFFF; - chunkid_prev = 0; - chunkid_prev2 = 0; + chunkid = ((unsigned int) rand()) & 0xFFFF; + chunkid_prev = 0; + chunkid_prev2 = 0; - outpkt.len = 0; - outpkt.seqno = 0; - outpkt.fragment = 0; - outchunkresent = 0; - inpkt.len = 0; - inpkt.seqno = 0; - inpkt.fragment = 0; + outpkt.len = 0; + outpkt.seqno = 0; + outpkt.fragment = 0; + outchunkresent = 0; + inpkt.len = 0; + inpkt.seqno = 0; + inpkt.fragment = 0; } void client_stop() { - running = 0; + running = 0; } enum connection client_get_conn() { - return conn; + return conn; } void client_set_nameserver(struct sockaddr_storage *addr, int addrlen) { - memcpy(&nameserv, addr, addrlen); - nameserv_len = addrlen; + memcpy(&nameserv, addr, addrlen); + nameserv_len = addrlen; } void client_set_topdomain(const char *cp) { - topdomain = cp; + topdomain = cp; } void client_set_password(const char *cp) { - password = cp; + password = cp; } int client_set_qtype(char *qtype) { - if (!strcasecmp(qtype, "NULL")) - do_qtype = T_NULL; - else if (!strcasecmp(qtype, "PRIVATE")) - do_qtype = T_PRIVATE; - else if (!strcasecmp(qtype, "CNAME")) - do_qtype = T_CNAME; - else if (!strcasecmp(qtype, "A")) - do_qtype = T_A; - else if (!strcasecmp(qtype, "MX")) - do_qtype = T_MX; - else if (!strcasecmp(qtype, "SRV")) - do_qtype = T_SRV; - else if (!strcasecmp(qtype, "TXT")) - do_qtype = T_TXT; - return (do_qtype == T_UNSET); + if (!strcasecmp(qtype, "NULL")) + do_qtype = T_NULL; + else if (!strcasecmp(qtype, "PRIVATE")) + do_qtype = T_PRIVATE; + else if (!strcasecmp(qtype, "CNAME")) + do_qtype = T_CNAME; + else if (!strcasecmp(qtype, "A")) + do_qtype = T_A; + else if (!strcasecmp(qtype, "MX")) + do_qtype = T_MX; + else if (!strcasecmp(qtype, "SRV")) + do_qtype = T_SRV; + else if (!strcasecmp(qtype, "TXT")) + do_qtype = T_TXT; + return (do_qtype == T_UNSET); } char * client_get_qtype() { - char *c = "UNDEFINED"; + char *c = "UNDEFINED"; - if (do_qtype == T_NULL) c = "NULL"; - else if (do_qtype == T_PRIVATE) c = "PRIVATE"; - else if (do_qtype == T_CNAME) c = "CNAME"; - else if (do_qtype == T_A) c = "A"; - else if (do_qtype == T_MX) c = "MX"; - else if (do_qtype == T_SRV) c = "SRV"; - else if (do_qtype == T_TXT) c = "TXT"; + if (do_qtype == T_NULL) c = "NULL"; + else if (do_qtype == T_PRIVATE) c = "PRIVATE"; + else if (do_qtype == T_CNAME) c = "CNAME"; + else if (do_qtype == T_A) c = "A"; + else if (do_qtype == T_MX) c = "MX"; + else if (do_qtype == T_SRV) c = "SRV"; + else if (do_qtype == T_TXT) c = "TXT"; - return c; + return c; } void client_set_downenc(char *encoding) { - if (!strcasecmp(encoding, "base32")) - downenc = 'T'; - else if (!strcasecmp(encoding, "base64")) - downenc = 'S'; - else if (!strcasecmp(encoding, "base64u")) - downenc = 'U'; - else if (!strcasecmp(encoding, "base128")) - downenc = 'V'; - else if (!strcasecmp(encoding, "raw")) - downenc = 'R'; + if (!strcasecmp(encoding, "base32")) + downenc = 'T'; + else if (!strcasecmp(encoding, "base64")) + downenc = 'S'; + else if (!strcasecmp(encoding, "base64u")) + downenc = 'U'; + else if (!strcasecmp(encoding, "base128")) + downenc = 'V'; + else if (!strcasecmp(encoding, "raw")) + downenc = 'R'; } void client_set_selecttimeout(int select_timeout) { - selecttimeout = select_timeout; + selecttimeout = select_timeout; } void client_set_lazymode(int lazy_mode) { - lazymode = lazy_mode; + lazymode = lazy_mode; } void client_set_hostname_maxlen(int i) { - if (i <= 0xFF) - hostname_maxlen = i; + if (i <= 0xFF) + hostname_maxlen = i; } const char * client_get_raw_addr() { - return inet_ntoa(raw_serv.sin_addr); + return inet_ntoa(raw_serv.sin_addr); } static void send_query(int fd, char *hostname) { - char packet[4096]; - struct query q; - size_t len; + char packet[4096]; + struct query q; + size_t len; - chunkid_prev2 = chunkid_prev; - chunkid_prev = chunkid; - chunkid += 7727; - if (chunkid == 0) - /* 0 is used as "no-query" in iodined.c */ - chunkid = 7727; + chunkid_prev2 = chunkid_prev; + chunkid_prev = chunkid; + chunkid += 7727; + if (chunkid == 0) + /* 0 is used as "no-query" in iodined.c */ + chunkid = 7727; - q.id = chunkid; - q.type = do_qtype; + q.id = chunkid; + q.type = do_qtype; - len = dns_encode(packet, sizeof(packet), &q, QR_QUERY, hostname, strlen(hostname)); - if (len < 1) { - warnx("dns_encode doesn't fit"); - return; - } + len = dns_encode(packet, sizeof(packet), &q, QR_QUERY, hostname, strlen(hostname)); + if (len < 1) { + warnx("dns_encode doesn't fit"); + return; + } #if 0 - fprintf(stderr, " Sendquery: id %5d name[0] '%c'\n", q.id, hostname[0]); + fprintf(stderr, " Sendquery: id %5d name[0] '%c'\n", q.id, hostname[0]); #endif - sendto(fd, packet, len, 0, (struct sockaddr*)&nameserv, nameserv_len); + sendto(fd, packet, len, 0, (struct sockaddr*)&nameserv, nameserv_len); - /* There are DNS relays that time out quickly but don't send anything - back on timeout. - And there are relays where, in lazy mode, our new query apparently - _replaces_ our previous query, and we get no answers at all in - lazy mode while legacy immediate-ping-pong works just fine. - Here we detect and fix these situations. - (Can't very well do this anywhere else; this is the only place - we'll reliably get to in such situations.) - */ + /* There are DNS relays that time out quickly but don't send anything + back on timeout. + And there are relays where, in lazy mode, our new query apparently + _replaces_ our previous query, and we get no answers at all in + lazy mode while legacy immediate-ping-pong works just fine. + Here we detect and fix these situations. + (Can't very well do this anywhere else; this is the only place + we'll reliably get to in such situations.) + */ - if (send_query_sendcnt >= 0 && send_query_sendcnt < 100 && lazymode) { - send_query_sendcnt++; + if (send_query_sendcnt >= 0 && send_query_sendcnt < 100 && lazymode) { + send_query_sendcnt++; - if ((send_query_sendcnt > 6 && send_query_recvcnt <= 0) || - (send_query_sendcnt > 10 && - 4 * send_query_recvcnt < send_query_sendcnt)) { - if (selecttimeout > 1) { - warnx("Receiving too few answers. Setting interval to 1 (-I1)"); - selecttimeout = 1; - /* restart counting */ - send_query_sendcnt = 0; - send_query_recvcnt = 0; - } else if (lazymode) { - warnx("Receiving too few answers. Will try to switch lazy mode off, but that may not always work any more. Start with -L0 next time on this network."); - lazymode = 0; - selecttimeout = 1; - handshake_lazyoff(fd); - } - } - } + if ((send_query_sendcnt > 6 && send_query_recvcnt <= 0) || + (send_query_sendcnt > 10 && + 4 * send_query_recvcnt < send_query_sendcnt)) { + if (selecttimeout > 1) { + warnx("Receiving too few answers. Setting interval to 1 (-I1)"); + selecttimeout = 1; + /* restart counting */ + send_query_sendcnt = 0; + send_query_recvcnt = 0; + } else if (lazymode) { + warnx("Receiving too few answers. Will try to switch lazy mode off, but that may not always work any more. Start with -L0 next time on this network."); + lazymode = 0; + selecttimeout = 1; + handshake_lazyoff(fd); + } + } + } } static void send_raw(int fd, char *buf, int buflen, int user, int cmd) { - char packet[4096]; - int len; + char packet[4096]; + int len; - len = MIN(sizeof(packet) - RAW_HDR_LEN, buflen); + len = MIN(sizeof(packet) - RAW_HDR_LEN, buflen); - memcpy(packet, raw_header, RAW_HDR_LEN); - if (len) { - memcpy(&packet[RAW_HDR_LEN], buf, len); - } + memcpy(packet, raw_header, RAW_HDR_LEN); + if (len) { + memcpy(&packet[RAW_HDR_LEN], buf, len); + } - len += RAW_HDR_LEN; - packet[RAW_HDR_CMD] = cmd | (user & 0x0F); + len += RAW_HDR_LEN; + packet[RAW_HDR_CMD] = cmd | (user & 0x0F); - sendto(fd, packet, len, 0, (struct sockaddr*)&raw_serv, sizeof(raw_serv)); + sendto(fd, packet, len, 0, (struct sockaddr*)&raw_serv, sizeof(raw_serv)); } static void send_raw_data(int dns_fd) { - send_raw(dns_fd, outpkt.data, outpkt.len, userid, RAW_HDR_CMD_DATA); - outpkt.len = 0; + send_raw(dns_fd, outpkt.data, outpkt.len, userid, RAW_HDR_CMD_DATA); + outpkt.len = 0; } static void send_packet(int fd, char cmd, const char *data, const size_t datalen) { - char buf[4096]; + char buf[4096]; - buf[0] = cmd; + buf[0] = cmd; - build_hostname(buf + 1, sizeof(buf) - 1, data, datalen, topdomain, - b32, hostname_maxlen); - send_query(fd, buf); + build_hostname(buf + 1, sizeof(buf) - 1, data, datalen, topdomain, + b32, hostname_maxlen); + send_query(fd, buf); } static inline int is_sending() { - return (outpkt.len != 0); + return (outpkt.len != 0); } static void send_chunk(int fd) { - char buf[4096]; - int avail; - int code; - char *p; - static int datacmc = 0; - char *datacmcchars = "abcdefghijklmnopqrstuvwxyz0123456789"; + char buf[4096]; + int avail; + int code; + char *p; + static int datacmc = 0; + char *datacmcchars = "abcdefghijklmnopqrstuvwxyz0123456789"; - p = outpkt.data; - p += outpkt.offset; - avail = outpkt.len - outpkt.offset; + p = outpkt.data; + p += outpkt.offset; + avail = outpkt.len - outpkt.offset; - /* Note: must be same, or smaller than send_fragsize_probe() */ - outpkt.sentlen = build_hostname(buf + 5, sizeof(buf) - 5, p, avail, - topdomain, dataenc, hostname_maxlen); + /* Note: must be same, or smaller than send_fragsize_probe() */ + outpkt.sentlen = build_hostname(buf + 5, sizeof(buf) - 5, p, avail, + topdomain, dataenc, hostname_maxlen); - /* Build upstream data header (see doc/proto_xxxxxxxx.txt) */ + /* Build upstream data header (see doc/proto_xxxxxxxx.txt) */ - buf[0] = userid_char; /* First byte is hex userid */ + buf[0] = userid_char; /* First byte is hex userid */ - code = ((outpkt.seqno & 7) << 2) | ((outpkt.fragment & 15) >> 2); - buf[1] = b32_5to8(code); /* Second byte is 3 bits seqno, 2 upper bits fragment count */ + code = ((outpkt.seqno & 7) << 2) | ((outpkt.fragment & 15) >> 2); + buf[1] = b32_5to8(code); /* Second byte is 3 bits seqno, 2 upper bits fragment count */ - code = ((outpkt.fragment & 3) << 3) | (inpkt.seqno & 7); - buf[2] = b32_5to8(code); /* Third byte is 2 bits lower fragment count, 3 bits downstream packet seqno */ + code = ((outpkt.fragment & 3) << 3) | (inpkt.seqno & 7); + buf[2] = b32_5to8(code); /* Third byte is 2 bits lower fragment count, 3 bits downstream packet seqno */ - code = ((inpkt.fragment & 15) << 1) | (outpkt.sentlen == avail); - buf[3] = b32_5to8(code); /* Fourth byte is 4 bits downstream fragment count, 1 bit last frag flag */ + code = ((inpkt.fragment & 15) << 1) | (outpkt.sentlen == avail); + buf[3] = b32_5to8(code); /* Fourth byte is 4 bits downstream fragment count, 1 bit last frag flag */ - buf[4] = datacmcchars[datacmc]; /* Fifth byte is data-CMC */ - datacmc++; - if (datacmc >= 36) - datacmc = 0; + buf[4] = datacmcchars[datacmc]; /* Fifth byte is data-CMC */ + datacmc++; + if (datacmc >= 36) + datacmc = 0; #if 0 - fprintf(stderr, " Send: down %d/%d up %d/%d, %d bytes\n", - inpkt.seqno, inpkt.fragment, outpkt.seqno, outpkt.fragment, - outpkt.sentlen); + fprintf(stderr, " Send: down %d/%d up %d/%d, %d bytes\n", + inpkt.seqno, inpkt.fragment, outpkt.seqno, outpkt.fragment, + outpkt.sentlen); #endif - send_query(fd, buf); + send_query(fd, buf); } static void send_ping(int fd) { - if (conn == CONN_DNS_NULL) { - char data[4]; + if (conn == CONN_DNS_NULL) { + char data[4]; - data[0] = userid; - data[1] = ((inpkt.seqno & 7) << 4) | (inpkt.fragment & 15); - data[2] = (rand_seed >> 8) & 0xff; - data[3] = (rand_seed >> 0) & 0xff; + data[0] = userid; + data[1] = ((inpkt.seqno & 7) << 4) | (inpkt.fragment & 15); + data[2] = (rand_seed >> 8) & 0xff; + data[3] = (rand_seed >> 0) & 0xff; - rand_seed++; + rand_seed++; #if 0 - fprintf(stderr, " Send: down %d/%d (ping)\n", - inpkt.seqno, inpkt.fragment); + fprintf(stderr, " Send: down %d/%d (ping)\n", + inpkt.seqno, inpkt.fragment); #endif - send_packet(fd, 'p', data, sizeof(data)); - } else { - send_raw(fd, NULL, 0, userid, RAW_HDR_CMD_PING); - } + send_packet(fd, 'p', data, sizeof(data)); + } else { + send_raw(fd, NULL, 0, userid, RAW_HDR_CMD_PING); + } } static void @@ -431,33 +431,33 @@ write_dns_error(struct query *q, int ignore_some_errors) So ignorable errors are never printed. */ { - if (!q) return; + if (!q) return; - switch (q->rcode) { - case NOERROR: /* 0 */ - if (!ignore_some_errors) - warnx("Got reply without error, but also without question and/or answer"); - break; - case FORMERR: /* 1 */ - warnx("Got FORMERR as reply: server does not understand our request"); - break; - case SERVFAIL: /* 2 */ - if (!ignore_some_errors) - warnx("Got SERVFAIL as reply: server failed or recursion timeout"); - break; - case NXDOMAIN: /* 3 */ - warnx("Got NXDOMAIN as reply: domain does not exist"); - break; - case NOTIMP: /* 4 */ - warnx("Got NOTIMP as reply: server does not support our request"); - break; - case REFUSED: /* 5 */ - warnx("Got REFUSED as reply"); - break; - default: - warnx("Got RCODE %u as reply", q->rcode); - break; - } + switch (q->rcode) { + case NOERROR: /* 0 */ + if (!ignore_some_errors) + warnx("Got reply without error, but also without question and/or answer"); + break; + case FORMERR: /* 1 */ + warnx("Got FORMERR as reply: server does not understand our request"); + break; + case SERVFAIL: /* 2 */ + if (!ignore_some_errors) + warnx("Got SERVFAIL as reply: server failed or recursion timeout"); + break; + case NXDOMAIN: /* 3 */ + warnx("Got NXDOMAIN as reply: domain does not exist"); + break; + case NOTIMP: /* 4 */ + warnx("Got NOTIMP as reply: server does not support our request"); + break; + case REFUSED: /* 5 */ + warnx("Got REFUSED as reply"); + break; + default: + warnx("Got RCODE %u as reply", q->rcode); + break; + } } static int @@ -469,92 +469,92 @@ dns_namedec(char *outdata, int outdatalen, char *buf, int buflen) * Returns #bytes usefully filled in outdata. */ { - size_t outdatalenu = outdatalen; + size_t outdatalenu = outdatalen; - switch (buf[0]) { - case 'h': /* Hostname with base32 */ - case 'H': - /* Need 1 byte H, 3 bytes ".xy", >=1 byte data */ - if (buflen < 5) - return 0; + switch (buf[0]) { + case 'h': /* Hostname with base32 */ + case 'H': + /* Need 1 byte H, 3 bytes ".xy", >=1 byte data */ + if (buflen < 5) + return 0; - /* this also does undotify */ - return unpack_data(outdata, outdatalen, buf + 1, buflen - 4, - b32); + /* this also does undotify */ + return unpack_data(outdata, outdatalen, buf + 1, buflen - 4, + b32); - case 'i': /* Hostname++ with base64 */ - case 'I': - /* Need 1 byte I, 3 bytes ".xy", >=1 byte data */ - if (buflen < 5) - return 0; + case 'i': /* Hostname++ with base64 */ + case 'I': + /* Need 1 byte I, 3 bytes ".xy", >=1 byte data */ + if (buflen < 5) + return 0; - /* this also does undotify */ - return unpack_data(outdata, outdatalen, buf + 1, buflen - 4, - b64); + /* this also does undotify */ + return unpack_data(outdata, outdatalen, buf + 1, buflen - 4, + b64); - case 'j': /* Hostname++ with base64u */ - case 'J': - /* Need 1 byte J, 3 bytes ".xy", >=1 byte data */ - if (buflen < 5) - return 0; + case 'j': /* Hostname++ with base64u */ + case 'J': + /* Need 1 byte J, 3 bytes ".xy", >=1 byte data */ + if (buflen < 5) + return 0; - /* this also does undotify */ - return unpack_data(outdata, outdatalen, buf + 1, buflen - 4, - b64u); + /* this also does undotify */ + return unpack_data(outdata, outdatalen, buf + 1, buflen - 4, + b64u); - case 'k': /* Hostname++ with base128 */ - case 'K': - /* Need 1 byte J, 3 bytes ".xy", >=1 byte data */ - if (buflen < 5) - return 0; + case 'k': /* Hostname++ with base128 */ + case 'K': + /* Need 1 byte J, 3 bytes ".xy", >=1 byte data */ + if (buflen < 5) + return 0; - /* this also does undotify */ - return unpack_data(outdata, outdatalen, buf + 1, buflen - 4, - b128); + /* this also does undotify */ + return unpack_data(outdata, outdatalen, buf + 1, buflen - 4, + b128); - case 't': /* plain base32(Thirty-two) from TXT */ - case 'T': - if (buflen < 2) - return 0; + case 't': /* plain base32(Thirty-two) from TXT */ + case 'T': + if (buflen < 2) + return 0; - return b32->decode(outdata, &outdatalenu, buf + 1, buflen - 1); + return b32->decode(outdata, &outdatalenu, buf + 1, buflen - 1); - case 's': /* plain base64(Sixty-four) from TXT */ - case 'S': - if (buflen < 2) - return 0; + case 's': /* plain base64(Sixty-four) from TXT */ + case 'S': + if (buflen < 2) + return 0; - return b64->decode(outdata, &outdatalenu, buf + 1, buflen - 1); + return b64->decode(outdata, &outdatalenu, buf + 1, buflen - 1); - case 'u': /* plain base64u (Underscore) from TXT */ - case 'U': - if (buflen < 2) - return 0; + case 'u': /* plain base64u (Underscore) from TXT */ + case 'U': + if (buflen < 2) + return 0; - return b64u->decode(outdata, &outdatalenu, buf + 1, buflen - 1); + return b64u->decode(outdata, &outdatalenu, buf + 1, buflen - 1); - case 'v': /* plain base128 from TXT */ - case 'V': - if (buflen < 2) - return 0; + case 'v': /* plain base128 from TXT */ + case 'V': + if (buflen < 2) + return 0; - return b128->decode(outdata, &outdatalenu, buf + 1, buflen - 1); + return b128->decode(outdata, &outdatalenu, buf + 1, buflen - 1); - case 'r': /* Raw binary from TXT */ - case 'R': - /* buflen>=1 already checked */ - buflen--; - buflen = MIN(buflen, outdatalen); - memcpy(outdata, buf + 1, buflen); - return buflen; + case 'r': /* Raw binary from TXT */ + case 'R': + /* buflen>=1 already checked */ + buflen--; + buflen = MIN(buflen, outdatalen); + memcpy(outdata, buf + 1, buflen); + return buflen; - default: - warnx("Received unsupported encoding"); - return 0; - } + default: + warnx("Received unsupported encoding"); + return 0; + } - /* notreached */ - return 0; + /* notreached */ + return 0; } static int @@ -566,102 +566,102 @@ read_dns_withq(int dns_fd, int tun_fd, char *buf, int buflen, struct query *q) Returns >0 on correct replies; value is #valid bytes in *buf. */ { - struct sockaddr_storage from; - char data[64*1024]; - socklen_t addrlen; - int r; + struct sockaddr_storage from; + char data[64*1024]; + socklen_t addrlen; + int r; - addrlen = sizeof(from); - if ((r = recvfrom(dns_fd, data, sizeof(data), 0, - (struct sockaddr*)&from, &addrlen)) < 0) { - warn("recvfrom"); - return -1; - } + addrlen = sizeof(from); + if ((r = recvfrom(dns_fd, data, sizeof(data), 0, + (struct sockaddr*)&from, &addrlen)) < 0) { + warn("recvfrom"); + return -1; + } - if (conn == CONN_DNS_NULL) { - int rv; - if (r <= 0) - /* useless packet */ - return 0; + if (conn == CONN_DNS_NULL) { + int rv; + if (r <= 0) + /* useless packet */ + return 0; - rv = dns_decode(buf, buflen, q, QR_ANSWER, data, r); - if (rv <= 0) - return rv; + rv = dns_decode(buf, buflen, q, QR_ANSWER, data, r); + if (rv <= 0) + return rv; - if (q->type == T_CNAME || q->type == T_TXT) - /* CNAME can also be returned from an A question */ - { - /* - * buf is a hostname or txt stream that we still need to - * decode to binary - * - * also update rv with the number of valid bytes - * - * data is unused here, and will certainly hold the smaller binary - */ + if (q->type == T_CNAME || q->type == T_TXT) + /* CNAME can also be returned from an A question */ + { + /* + * buf is a hostname or txt stream that we still need to + * decode to binary + * + * also update rv with the number of valid bytes + * + * data is unused here, and will certainly hold the smaller binary + */ - rv = dns_namedec(data, sizeof(data), buf, rv); + rv = dns_namedec(data, sizeof(data), buf, rv); - rv = MIN(rv, buflen); - if (rv > 0) - memcpy(buf, data, rv); + rv = MIN(rv, buflen); + if (rv > 0) + memcpy(buf, data, rv); - } else if (q->type == T_MX || q->type == T_SRV) { - /* buf is like "Hname.com\0Hanother.com\0\0" */ - int buftotal = rv; /* idx of last \0 */ - int bufoffset = 0; - int dataoffset = 0; - int thispartlen, dataspace, datanew; + } else if (q->type == T_MX || q->type == T_SRV) { + /* buf is like "Hname.com\0Hanother.com\0\0" */ + int buftotal = rv; /* idx of last \0 */ + int bufoffset = 0; + int dataoffset = 0; + int thispartlen, dataspace, datanew; - while (1) { - thispartlen = strlen(buf); - thispartlen = MIN(thispartlen, buftotal-bufoffset); - dataspace = sizeof(data) - dataoffset; - if (thispartlen <= 0 || dataspace <= 0) - break; + while (1) { + thispartlen = strlen(buf); + thispartlen = MIN(thispartlen, buftotal-bufoffset); + dataspace = sizeof(data) - dataoffset; + if (thispartlen <= 0 || dataspace <= 0) + break; - datanew = dns_namedec(data + dataoffset, dataspace, - buf + bufoffset, thispartlen); - if (datanew <= 0) - break; + datanew = dns_namedec(data + dataoffset, dataspace, + buf + bufoffset, thispartlen); + if (datanew <= 0) + break; - bufoffset += thispartlen + 1; - dataoffset += datanew; - } - rv = dataoffset; - rv = MIN(rv, buflen); - if (rv > 0) - memcpy(buf, data, rv); - } + bufoffset += thispartlen + 1; + dataoffset += datanew; + } + rv = dataoffset; + rv = MIN(rv, buflen); + if (rv > 0) + memcpy(buf, data, rv); + } - return rv; - } else { /* CONN_RAW_UDP */ - unsigned long datalen; - char buf[64*1024]; + return rv; + } else { /* CONN_RAW_UDP */ + unsigned long datalen; + char buf[64*1024]; - /* minimum length */ - if (r < RAW_HDR_LEN) return 0; - /* should start with header */ - if (memcmp(data, raw_header, RAW_HDR_IDENT_LEN)) return 0; - /* should be my user id */ - if (RAW_HDR_GET_USR(data) != userid) return 0; + /* minimum length */ + if (r < RAW_HDR_LEN) return 0; + /* should start with header */ + if (memcmp(data, raw_header, RAW_HDR_IDENT_LEN)) return 0; + /* should be my user id */ + if (RAW_HDR_GET_USR(data) != userid) return 0; - if (RAW_HDR_GET_CMD(data) == RAW_HDR_CMD_DATA || - RAW_HDR_GET_CMD(data) == RAW_HDR_CMD_PING) - lastdownstreamtime = time(NULL); + if (RAW_HDR_GET_CMD(data) == RAW_HDR_CMD_DATA || + RAW_HDR_GET_CMD(data) == RAW_HDR_CMD_PING) + lastdownstreamtime = time(NULL); - /* should be data packet */ - if (RAW_HDR_GET_CMD(data) != RAW_HDR_CMD_DATA) return 0; + /* should be data packet */ + if (RAW_HDR_GET_CMD(data) != RAW_HDR_CMD_DATA) return 0; - r -= RAW_HDR_LEN; - datalen = sizeof(buf); - if (uncompress((uint8_t*)buf, &datalen, (uint8_t*) &data[RAW_HDR_LEN], r) == Z_OK) { - write_tun(tun_fd, buf, datalen); - } + r -= RAW_HDR_LEN; + datalen = sizeof(buf); + if (uncompress((uint8_t*)buf, &datalen, (uint8_t*) &data[RAW_HDR_LEN], r) == Z_OK) { + write_tun(tun_fd, buf, datalen); + } - /* don't process any further */ - return 0; - } + /* don't process any further */ + return 0; + } } static int @@ -678,894 +678,894 @@ handshake_waitdns(int dns_fd, char *buf, int buflen, char c1, char c2, int timeo so effective timeout may be longer than specified. */ { - struct query q; - int r, rv; - fd_set fds; - struct timeval tv; + struct query q; + int r, rv; + fd_set fds; + struct timeval tv; - while (1) { - tv.tv_sec = timeout; - tv.tv_usec = 0; - FD_ZERO(&fds); - FD_SET(dns_fd, &fds); - r = select(dns_fd + 1, &fds, NULL, NULL, &tv); + while (1) { + tv.tv_sec = timeout; + tv.tv_usec = 0; + FD_ZERO(&fds); + FD_SET(dns_fd, &fds); + r = select(dns_fd + 1, &fds, NULL, NULL, &tv); - if (r < 0) - return -1; /* select error */ - if (r == 0) - return -3; /* select timeout */ + if (r < 0) + return -1; /* select error */ + if (r == 0) + return -3; /* select timeout */ - q.id = 0; - q.name[0] = '\0'; - rv = read_dns_withq(dns_fd, 0, buf, buflen, &q); + q.id = 0; + q.name[0] = '\0'; + rv = read_dns_withq(dns_fd, 0, buf, buflen, &q); - if (q.id != chunkid || (q.name[0] != c1 && q.name[0] != c2)) { + if (q.id != chunkid || (q.name[0] != c1 && q.name[0] != c2)) { #if 0 - fprintf(stderr, "Ignoring unfitting reply id %d starting with '%c'\n", q.id, q.name[0]); + fprintf(stderr, "Ignoring unfitting reply id %d starting with '%c'\n", q.id, q.name[0]); #endif - continue; - } + continue; + } - /* if still here: reply matches our latest query */ + /* if still here: reply matches our latest query */ - /* Non-recursive DNS servers (such as [a-m].root-servers.net) - return no answer, but only additional and authority records. - Can't explicitly test for that here, just assume that - NOERROR is such situation. Only trigger on the very first - requests (Y or V, depending if -T given). - */ - if (rv < 0 && q.rcode == NOERROR && - (q.name[0] == 'Y' || q.name[0] == 'y' || - q.name[0] == 'V' || q.name[0] == 'v')) { - fprintf(stderr, "Got empty reply. This nameserver may not be resolving recursively, use another.\n"); - fprintf(stderr, "Try \"iodine [options] ns.%s %s\" first, it might just work.\n", - topdomain, topdomain); - return -2; - } + /* Non-recursive DNS servers (such as [a-m].root-servers.net) + return no answer, but only additional and authority records. + Can't explicitly test for that here, just assume that + NOERROR is such situation. Only trigger on the very first + requests (Y or V, depending if -T given). + */ + if (rv < 0 && q.rcode == NOERROR && + (q.name[0] == 'Y' || q.name[0] == 'y' || + q.name[0] == 'V' || q.name[0] == 'v')) { + fprintf(stderr, "Got empty reply. This nameserver may not be resolving recursively, use another.\n"); + fprintf(stderr, "Try \"iodine [options] ns.%s %s\" first, it might just work.\n", + topdomain, topdomain); + return -2; + } - /* If we get an immediate SERVFAIL on the handshake query - we're waiting for, wait a while before sending the next. - SERVFAIL reliably happens during fragsize autoprobe, but - mostly long after we've moved along to some other queries. - However, some DNS relays, once they throw a SERVFAIL, will - for several seconds apply it immediately to _any_ new query - for the same topdomain. When this happens, waiting a while - is the only option that works. - */ - if (rv < 0 && q.rcode == SERVFAIL) - sleep(1); + /* If we get an immediate SERVFAIL on the handshake query + we're waiting for, wait a while before sending the next. + SERVFAIL reliably happens during fragsize autoprobe, but + mostly long after we've moved along to some other queries. + However, some DNS relays, once they throw a SERVFAIL, will + for several seconds apply it immediately to _any_ new query + for the same topdomain. When this happens, waiting a while + is the only option that works. + */ + if (rv < 0 && q.rcode == SERVFAIL) + sleep(1); - if (rv < 0) { - write_dns_error(&q, 1); - return -2; - } - /* rv either 0 or >0, return it as is. */ - return rv; - } + if (rv < 0) { + write_dns_error(&q, 1); + return -2; + } + /* rv either 0 or >0, return it as is. */ + return rv; + } - /* not reached */ - return -1; + /* not reached */ + return -1; } static int tunnel_tun(int tun_fd, int dns_fd) { - unsigned long outlen; - unsigned long inlen; - char out[64*1024]; - char in[64*1024]; - ssize_t read; + unsigned long outlen; + unsigned long inlen; + char out[64*1024]; + char in[64*1024]; + ssize_t read; - if ((read = read_tun(tun_fd, in, sizeof(in))) <= 0) - return -1; + if ((read = read_tun(tun_fd, in, sizeof(in))) <= 0) + return -1; - /* We may be here only to empty the tun device; then return -1 - to force continue in select loop. */ - if (is_sending()) - return -1; + /* We may be here only to empty the tun device; then return -1 + to force continue in select loop. */ + if (is_sending()) + return -1; - outlen = sizeof(out); - inlen = read; - compress2((uint8_t*)out, &outlen, (uint8_t*)in, inlen, 9); + outlen = sizeof(out); + inlen = read; + compress2((uint8_t*)out, &outlen, (uint8_t*)in, inlen, 9); - memcpy(outpkt.data, out, MIN(outlen, sizeof(outpkt.data))); - outpkt.sentlen = 0; - outpkt.offset = 0; - outpkt.seqno = (outpkt.seqno + 1) & 7; - outpkt.len = outlen; - outpkt.fragment = 0; - outchunkresent = 0; + memcpy(outpkt.data, out, MIN(outlen, sizeof(outpkt.data))); + outpkt.sentlen = 0; + outpkt.offset = 0; + outpkt.seqno = (outpkt.seqno + 1) & 7; + outpkt.len = outlen; + outpkt.fragment = 0; + outchunkresent = 0; - if (conn == CONN_DNS_NULL) { - send_chunk(dns_fd); + if (conn == CONN_DNS_NULL) { + send_chunk(dns_fd); - send_ping_soon = 0; - } else { - send_raw_data(dns_fd); - } + send_ping_soon = 0; + } else { + send_raw_data(dns_fd); + } - return read; + return read; } static int tunnel_dns(int tun_fd, int dns_fd) { - static long packrecv = 0; - static long packrecv_oos = 0; - static long packrecv_servfail = 0; - int up_ack_seqno; - int up_ack_fragment; - int new_down_seqno; - int new_down_fragment; - struct query q; - unsigned long datalen; - char buf[64*1024]; - int read; - int send_something_now = 0; + static long packrecv = 0; + static long packrecv_oos = 0; + static long packrecv_servfail = 0; + int up_ack_seqno; + int up_ack_fragment; + int new_down_seqno; + int new_down_fragment; + struct query q; + unsigned long datalen; + char buf[64*1024]; + int read; + int send_something_now = 0; - memset(q.name, 0, sizeof(q.name)); - read = read_dns_withq(dns_fd, tun_fd, buf, sizeof(buf), &q); + memset(q.name, 0, sizeof(q.name)); + read = read_dns_withq(dns_fd, tun_fd, buf, sizeof(buf), &q); - if (conn != CONN_DNS_NULL) - return 1; /* everything already done */ + if (conn != CONN_DNS_NULL) + return 1; /* everything already done */ #if 0 - fprintf(stderr, " Recv: id %5d name[0]='%c'\n", - q.id, q.name[0]); + fprintf(stderr, " Recv: id %5d name[0]='%c'\n", + q.id, q.name[0]); #endif - /* Don't process anything that isn't data for us; usually error - replies from fragsize probes etc. However a sequence of those, - mostly 1 sec apart, will continuously break the >=2-second select - timeout, which means we won't send a proper ping for a while. - So make select a bit faster, <1sec. */ - if (q.name[0] != 'P' && q.name[0] != 'p' && - q.name[0] != userid_char && q.name[0] != userid_char2) { - send_ping_soon = 700; - return -1; /* nothing done */ - } + /* Don't process anything that isn't data for us; usually error + replies from fragsize probes etc. However a sequence of those, + mostly 1 sec apart, will continuously break the >=2-second select + timeout, which means we won't send a proper ping for a while. + So make select a bit faster, <1sec. */ + if (q.name[0] != 'P' && q.name[0] != 'p' && + q.name[0] != userid_char && q.name[0] != userid_char2) { + send_ping_soon = 700; + return -1; /* nothing done */ + } - if (read < 2) { - /* Maybe SERVFAIL etc. Send ping to get things back in order, - but wait a bit to prevent fast ping-pong loops. */ + if (read < 2) { + /* Maybe SERVFAIL etc. Send ping to get things back in order, + but wait a bit to prevent fast ping-pong loops. */ - if (read < 0) - write_dns_error(&q, 0); + if (read < 0) + write_dns_error(&q, 0); - if (read < 0 && q.rcode == SERVFAIL && lazymode && - selecttimeout > 1) { - if (packrecv < 500 && packrecv_servfail < 4) { - packrecv_servfail++; - warnx("Hmm, that's %ld. Your data should still go through...", packrecv_servfail); - } else if (packrecv < 500 && packrecv_servfail == 4) { - packrecv_servfail++; - warnx("I think %ld is too many. Setting interval to 1 to hopefully reduce SERVFAILs. But just ignore them if data still comes through. (Use -I1 next time on this network.)", packrecv_servfail); - selecttimeout = 1; - send_query_sendcnt = 0; - send_query_recvcnt = 0; - } else if (packrecv >= 500 && packrecv_servfail > 0) { - warnx("(Sorry, stopped counting; try -I1 if you experience hiccups.)"); - packrecv_servfail = 0; - } - } + if (read < 0 && q.rcode == SERVFAIL && lazymode && + selecttimeout > 1) { + if (packrecv < 500 && packrecv_servfail < 4) { + packrecv_servfail++; + warnx("Hmm, that's %ld. Your data should still go through...", packrecv_servfail); + } else if (packrecv < 500 && packrecv_servfail == 4) { + packrecv_servfail++; + warnx("I think %ld is too many. Setting interval to 1 to hopefully reduce SERVFAILs. But just ignore them if data still comes through. (Use -I1 next time on this network.)", packrecv_servfail); + selecttimeout = 1; + send_query_sendcnt = 0; + send_query_recvcnt = 0; + } else if (packrecv >= 500 && packrecv_servfail > 0) { + warnx("(Sorry, stopped counting; try -I1 if you experience hiccups.)"); + packrecv_servfail = 0; + } + } - /* read==1 happens with "QMEM" illegal replies, caused by - heavy reordering, or after short disconnections when - data-CMC has looped around into the "duplicate" values. - All these cases are helped by faster pinging. */ + /* read==1 happens with "QMEM" illegal replies, caused by + heavy reordering, or after short disconnections when + data-CMC has looped around into the "duplicate" values. + All these cases are helped by faster pinging. */ #if 0 - if (read == 1) - fprintf(stderr, " q=%c id %5d 1-byte illegal \"QMEM\" reply\n", q.name[0], q.id); + if (read == 1) + fprintf(stderr, " q=%c id %5d 1-byte illegal \"QMEM\" reply\n", q.name[0], q.id); #endif - send_ping_soon = 900; - return -1; /* nothing done */ - } + send_ping_soon = 900; + return -1; /* nothing done */ + } - if (read == 5 && !strncmp("BADIP", buf, 5)) { - warnx("BADIP: Server rejected sender IP address (maybe iodined -c will help), or server kicked us due to timeout. Will exit if no downstream data is received in 60 seconds."); - return -1; /* nothing done */ - } + if (read == 5 && !strncmp("BADIP", buf, 5)) { + warnx("BADIP: Server rejected sender IP address (maybe iodined -c will help), or server kicked us due to timeout. Will exit if no downstream data is received in 60 seconds."); + return -1; /* nothing done */ + } - if (send_ping_soon) { - send_something_now = 1; - send_ping_soon = 0; - } + if (send_ping_soon) { + send_something_now = 1; + send_ping_soon = 0; + } - /* Decode the data header, update seqno and frag; - already checked read>=2 - Note that buf[] gets overwritten when down-pkt complete */ - new_down_seqno = (buf[1] >> 5) & 7; - new_down_fragment = (buf[1] >> 1) & 15; - up_ack_seqno = (buf[0] >> 4) & 7; - up_ack_fragment = buf[0] & 15; + /* Decode the data header, update seqno and frag; + already checked read>=2 + Note that buf[] gets overwritten when down-pkt complete */ + new_down_seqno = (buf[1] >> 5) & 7; + new_down_fragment = (buf[1] >> 1) & 15; + up_ack_seqno = (buf[0] >> 4) & 7; + up_ack_fragment = buf[0] & 15; #if 0 - fprintf(stderr, " Recv: id %5d down %d/%d up %d/%d, %d bytes\n", - q.id, new_down_seqno, new_down_fragment, up_ack_seqno, - up_ack_fragment, read); + fprintf(stderr, " Recv: id %5d down %d/%d up %d/%d, %d bytes\n", + q.id, new_down_seqno, new_down_fragment, up_ack_seqno, + up_ack_fragment, read); #endif - /* Downstream data traffic */ + /* Downstream data traffic */ - if (read > 2 && new_down_seqno != inpkt.seqno && - recent_seqno(inpkt.seqno, new_down_seqno)) { - /* This is the previous seqno, or a bit earlier. - Probably out-of-sequence dupe due to unreliable - intermediary DNS. Don't get distracted, but send - ping quickly to get things back in order. - Ping will send our current seqno idea. - If it's really a new packet that skipped multiple seqnos - (why??), server will re-send and drop a few times and - eventually everything will work again. */ - read = 2; - send_ping_soon = 500; - /* Still process upstream ack, if any */ - } + if (read > 2 && new_down_seqno != inpkt.seqno && + recent_seqno(inpkt.seqno, new_down_seqno)) { + /* This is the previous seqno, or a bit earlier. + Probably out-of-sequence dupe due to unreliable + intermediary DNS. Don't get distracted, but send + ping quickly to get things back in order. + Ping will send our current seqno idea. + If it's really a new packet that skipped multiple seqnos + (why??), server will re-send and drop a few times and + eventually everything will work again. */ + read = 2; + send_ping_soon = 500; + /* Still process upstream ack, if any */ + } - if (!(packrecv & 0x1000000)) - packrecv++; - send_query_recvcnt++; /* overflow doesn't matter */ + if (!(packrecv & 0x1000000)) + packrecv++; + send_query_recvcnt++; /* overflow doesn't matter */ - /* Don't process any non-recent stuff any further. - No need to remember more than 3 ids: in practice any older replies - arrive after new/current replies, and whatever data the old replies - have, it has become useless in the mean time. - Actually, ever since iodined is replying to both the original query - and the last dupe, this hardly triggers any more. - */ - if (q.id != chunkid && q.id != chunkid_prev && q.id != chunkid_prev2) { - packrecv_oos++; + /* Don't process any non-recent stuff any further. + No need to remember more than 3 ids: in practice any older replies + arrive after new/current replies, and whatever data the old replies + have, it has become useless in the mean time. + Actually, ever since iodined is replying to both the original query + and the last dupe, this hardly triggers any more. + */ + if (q.id != chunkid && q.id != chunkid_prev && q.id != chunkid_prev2) { + packrecv_oos++; #if 0 - fprintf(stderr, " q=%c Packs received = %8ld Out-of-sequence = %8ld\n", q.name[0], packrecv, packrecv_oos); + fprintf(stderr, " q=%c Packs received = %8ld Out-of-sequence = %8ld\n", q.name[0], packrecv, packrecv_oos); #endif - if (lazymode && packrecv < 1000 && packrecv_oos == 5) { - if (selecttimeout > 1) - warnx("Hmm, getting some out-of-sequence DNS replies. Setting interval to 1 (use -I1 next time on this network). If data traffic still has large hiccups, try if -L0 works better."); - else - warnx("Hmm, getting some out-of-sequence DNS replies. If data traffic often has large hiccups, try running with -L0 ."); - selecttimeout = 1; - send_query_sendcnt = 0; - send_query_recvcnt = 0; - } + if (lazymode && packrecv < 1000 && packrecv_oos == 5) { + if (selecttimeout > 1) + warnx("Hmm, getting some out-of-sequence DNS replies. Setting interval to 1 (use -I1 next time on this network). If data traffic still has large hiccups, try if -L0 works better."); + else + warnx("Hmm, getting some out-of-sequence DNS replies. If data traffic often has large hiccups, try running with -L0 ."); + selecttimeout = 1; + send_query_sendcnt = 0; + send_query_recvcnt = 0; + } - if (send_something_now) { - send_ping(dns_fd); - send_ping_soon = 0; - } - return -1; /* nothing done */ - } + if (send_something_now) { + send_ping(dns_fd); + send_ping_soon = 0; + } + return -1; /* nothing done */ + } #if 0 - fprintf(stderr, " q=%c Packs received = %8ld Out-of-sequence = %8ld\n", q.name[0], packrecv, packrecv_oos); + fprintf(stderr, " q=%c Packs received = %8ld Out-of-sequence = %8ld\n", q.name[0], packrecv, packrecv_oos); #endif - /* Okay, we have a recent downstream packet */ - lastdownstreamtime = time(NULL); + /* Okay, we have a recent downstream packet */ + lastdownstreamtime = time(NULL); - /* In lazy mode, we shouldn't get much replies to our most-recent - query, only during heavy data transfer. Since this means the server - doesn't have any packets left, send one relatively fast (but not - too fast, to avoid runaway ping-pong loops..) */ - if (q.id == chunkid && lazymode) { - if (!send_ping_soon || send_ping_soon > 900) - send_ping_soon = 900; - } + /* In lazy mode, we shouldn't get much replies to our most-recent + query, only during heavy data transfer. Since this means the server + doesn't have any packets left, send one relatively fast (but not + too fast, to avoid runaway ping-pong loops..) */ + if (q.id == chunkid && lazymode) { + if (!send_ping_soon || send_ping_soon > 900) + send_ping_soon = 900; + } - if (read == 2 && new_down_seqno != inpkt.seqno && - !recent_seqno(inpkt.seqno, new_down_seqno)) { - /* This is a seqno that we didn't see yet, but it has - no data any more. Possible since iodined will send - fitting packs just once and not wait for ack. - Real data got lost, or will arrive shortly. - Update our idea of the seqno, and drop any waiting - old pack. Send ping to get things back on track. */ - inpkt.seqno = new_down_seqno; - inpkt.fragment = new_down_fragment; - inpkt.len = 0; - send_ping_soon = 500; - } + if (read == 2 && new_down_seqno != inpkt.seqno && + !recent_seqno(inpkt.seqno, new_down_seqno)) { + /* This is a seqno that we didn't see yet, but it has + no data any more. Possible since iodined will send + fitting packs just once and not wait for ack. + Real data got lost, or will arrive shortly. + Update our idea of the seqno, and drop any waiting + old pack. Send ping to get things back on track. */ + inpkt.seqno = new_down_seqno; + inpkt.fragment = new_down_fragment; + inpkt.len = 0; + send_ping_soon = 500; + } - while (read > 2) { - /* "if" with easy exit */ + while (read > 2) { + /* "if" with easy exit */ - if (new_down_seqno != inpkt.seqno) { - /* New packet (and not dupe of recent; checked above) */ - /* Forget any old packet, even if incomplete */ - inpkt.seqno = new_down_seqno; - inpkt.fragment = new_down_fragment; /* hopefully 0 */ - inpkt.len = 0; - } else if (inpkt.fragment == 0 && new_down_fragment == 0 && - inpkt.len == 0) { - /* Weird situation: we probably got a no-data reply - for this seqno (see above), and the actual data - is following now. */ - /* okay, nothing to do here, just so that next else-if - doesn't trigger */ - } else if (new_down_fragment <= inpkt.fragment) { - /* Same packet but duplicate fragment, ignore. - If the server didn't get our ack for it, the next - ping or chunk will do that. */ - send_ping_soon = 500; - break; - } else if (new_down_fragment > inpkt.fragment + 1) { - /* Quite impossible. We missed a fragment, but the - server got our ack for it and is sending the next - fragment already. Don't handle it but let server - re-send and drop. */ - send_ping_soon = 500; - break; - } - inpkt.fragment = new_down_fragment; + if (new_down_seqno != inpkt.seqno) { + /* New packet (and not dupe of recent; checked above) */ + /* Forget any old packet, even if incomplete */ + inpkt.seqno = new_down_seqno; + inpkt.fragment = new_down_fragment; /* hopefully 0 */ + inpkt.len = 0; + } else if (inpkt.fragment == 0 && new_down_fragment == 0 && + inpkt.len == 0) { + /* Weird situation: we probably got a no-data reply + for this seqno (see above), and the actual data + is following now. */ + /* okay, nothing to do here, just so that next else-if + doesn't trigger */ + } else if (new_down_fragment <= inpkt.fragment) { + /* Same packet but duplicate fragment, ignore. + If the server didn't get our ack for it, the next + ping or chunk will do that. */ + send_ping_soon = 500; + break; + } else if (new_down_fragment > inpkt.fragment + 1) { + /* Quite impossible. We missed a fragment, but the + server got our ack for it and is sending the next + fragment already. Don't handle it but let server + re-send and drop. */ + send_ping_soon = 500; + break; + } + inpkt.fragment = new_down_fragment; - datalen = MIN(read - 2, sizeof(inpkt.data) - inpkt.len); + datalen = MIN(read - 2, sizeof(inpkt.data) - inpkt.len); - /* we are here only when read > 2, so datalen "always" >=1 */ + /* we are here only when read > 2, so datalen "always" >=1 */ - /* Skip 2 byte data header and append to packet */ - memcpy(&inpkt.data[inpkt.len], &buf[2], datalen); - inpkt.len += datalen; + /* Skip 2 byte data header and append to packet */ + memcpy(&inpkt.data[inpkt.len], &buf[2], datalen); + inpkt.len += datalen; - if (buf[1] & 1) { /* If last fragment flag is set */ - /* Uncompress packet and send to tun */ - /* RE-USES buf[] */ - datalen = sizeof(buf); - if (uncompress((uint8_t*)buf, &datalen, (uint8_t*) inpkt.data, inpkt.len) == Z_OK) { - write_tun(tun_fd, buf, datalen); - } - inpkt.len = 0; - /* Keep .seqno and .fragment as is, so that we won't - reassemble from duplicate fragments */ - } + if (buf[1] & 1) { /* If last fragment flag is set */ + /* Uncompress packet and send to tun */ + /* RE-USES buf[] */ + datalen = sizeof(buf); + if (uncompress((uint8_t*)buf, &datalen, (uint8_t*) inpkt.data, inpkt.len) == Z_OK) { + write_tun(tun_fd, buf, datalen); + } + inpkt.len = 0; + /* Keep .seqno and .fragment as is, so that we won't + reassemble from duplicate fragments */ + } - /* Send anything to ack the received seqno/frag, and get more */ - if (inpkt.len == 0) { - /* was last frag; wait just a trifle because our - tun will probably return TCP-ack immediately. - 5msec = 200 DNSreq/sec */ - send_ping_soon = 5; - } else { - /* server certainly has more data */ - send_something_now = 1; - } + /* Send anything to ack the received seqno/frag, and get more */ + if (inpkt.len == 0) { + /* was last frag; wait just a trifle because our + tun will probably return TCP-ack immediately. + 5msec = 200 DNSreq/sec */ + send_ping_soon = 5; + } else { + /* server certainly has more data */ + send_something_now = 1; + } - break; - } + break; + } - /* NOTE: buf[] was overwritten when down-packet complete */ + /* NOTE: buf[] was overwritten when down-packet complete */ - /* Upstream data traffic */ + /* Upstream data traffic */ - if (is_sending()) { - /* already checked read>=2 */ + if (is_sending()) { + /* already checked read>=2 */ #if 0 - fprintf(stderr, "Got ack for %d,%d - expecting %d,%d - id=%d cur=%d prev=%d prev2=%d\n", - up_ack_seqno, up_ack_fragment, outpkt.seqno, outpkt.fragment, - q.id, chunkid, chunkid_prev, chunkid_prev2); + fprintf(stderr, "Got ack for %d,%d - expecting %d,%d - id=%d cur=%d prev=%d prev2=%d\n", + up_ack_seqno, up_ack_fragment, outpkt.seqno, outpkt.fragment, + q.id, chunkid, chunkid_prev, chunkid_prev2); #endif - if (up_ack_seqno == outpkt.seqno && - up_ack_fragment == outpkt.fragment) { - /* Okay, previously sent fragment has arrived */ + if (up_ack_seqno == outpkt.seqno && + up_ack_fragment == outpkt.fragment) { + /* Okay, previously sent fragment has arrived */ - outpkt.offset += outpkt.sentlen; - if (outpkt.offset >= outpkt.len) { - /* Packet completed */ - outpkt.offset = 0; - outpkt.len = 0; - outpkt.sentlen = 0; - outchunkresent = 0; + outpkt.offset += outpkt.sentlen; + if (outpkt.offset >= outpkt.len) { + /* Packet completed */ + outpkt.offset = 0; + outpkt.len = 0; + outpkt.sentlen = 0; + outchunkresent = 0; - /* Normally, server still has a query in queue, - but sometimes not. So send a ping. - (Comment this out and you'll see occasional - hiccups.) - But since the server often still has a - query and we can expect a TCP-ack returned - from our tun device quickly in many cases, - don't be too fast. - 20msec still is 50 DNSreq/second... */ - if (!send_ping_soon || send_ping_soon > 20) - send_ping_soon = 20; - } else { - /* More to send */ - outpkt.fragment++; - outchunkresent = 0; - send_chunk(dns_fd); - send_ping_soon = 0; - send_something_now = 0; - } - } - /* else: Some wrong fragment has arrived, or old fragment is - acked again, mostly by ping responses. - Don't resend chunk, usually not needed; select loop will - re-send on timeout (1sec if is_sending()). */ - } + /* Normally, server still has a query in queue, + but sometimes not. So send a ping. + (Comment this out and you'll see occasional + hiccups.) + But since the server often still has a + query and we can expect a TCP-ack returned + from our tun device quickly in many cases, + don't be too fast. + 20msec still is 50 DNSreq/second... */ + if (!send_ping_soon || send_ping_soon > 20) + send_ping_soon = 20; + } else { + /* More to send */ + outpkt.fragment++; + outchunkresent = 0; + send_chunk(dns_fd); + send_ping_soon = 0; + send_something_now = 0; + } + } + /* else: Some wrong fragment has arrived, or old fragment is + acked again, mostly by ping responses. + Don't resend chunk, usually not needed; select loop will + re-send on timeout (1sec if is_sending()). */ + } - /* Send ping if we didn't send anything yet */ - if (send_something_now) { - send_ping(dns_fd); - send_ping_soon = 0; - } + /* Send ping if we didn't send anything yet */ + if (send_something_now) { + send_ping(dns_fd); + send_ping_soon = 0; + } - return read; + return read; } int client_tunnel(int tun_fd, int dns_fd) { - struct timeval tv; - fd_set fds; - int rv; - int i; + struct timeval tv; + fd_set fds; + int rv; + int i; - rv = 0; - lastdownstreamtime = time(NULL); - send_query_sendcnt = 0; /* start counting now */ + rv = 0; + lastdownstreamtime = time(NULL); + send_query_sendcnt = 0; /* start counting now */ - while (running) { - tv.tv_sec = selecttimeout; - tv.tv_usec = 0; + while (running) { + tv.tv_sec = selecttimeout; + tv.tv_usec = 0; - if (is_sending()) { - /* fast timeout for retransmits */ - tv.tv_sec = 1; - tv.tv_usec = 0; - } + if (is_sending()) { + /* fast timeout for retransmits */ + tv.tv_sec = 1; + tv.tv_usec = 0; + } - if (send_ping_soon) { - tv.tv_sec = 0; - tv.tv_usec = send_ping_soon * 1000; - } + if (send_ping_soon) { + tv.tv_sec = 0; + tv.tv_usec = send_ping_soon * 1000; + } - FD_ZERO(&fds); - if (!is_sending() || outchunkresent >= 2) { - /* If re-sending upstream data, chances are that - we're several seconds behind already and TCP - will start filling tun buffer with (useless) - retransmits. - Get up-to-date fast by simply dropping stuff, - that's what TCP is designed to handle. */ - FD_SET(tun_fd, &fds); - } - FD_SET(dns_fd, &fds); + FD_ZERO(&fds); + if (!is_sending() || outchunkresent >= 2) { + /* If re-sending upstream data, chances are that + we're several seconds behind already and TCP + will start filling tun buffer with (useless) + retransmits. + Get up-to-date fast by simply dropping stuff, + that's what TCP is designed to handle. */ + FD_SET(tun_fd, &fds); + } + FD_SET(dns_fd, &fds); - i = select(MAX(tun_fd, dns_fd) + 1, &fds, NULL, NULL, &tv); + i = select(MAX(tun_fd, dns_fd) + 1, &fds, NULL, NULL, &tv); - if (lastdownstreamtime + 60 < time(NULL)) { - warnx("No downstream data received in 60 seconds, shutting down."); - running = 0; - } + if (lastdownstreamtime + 60 < time(NULL)) { + warnx("No downstream data received in 60 seconds, shutting down."); + running = 0; + } - if (running == 0) - break; + if (running == 0) + break; - if (i < 0) - err(1, "select"); + if (i < 0) + err(1, "select"); - if (i == 0) { - /* timeout */ - if (is_sending()) { - /* Re-send current fragment; either frag - or ack probably dropped somewhere. - But problem: no cache-miss-counter, - so hostname will be identical. - Just drop whole packet after 3 retries, - and TCP retransmit will solve it. - NOTE: tun dropping above should be - >=(value_here - 1) */ - if (outchunkresent < 3) { - outchunkresent++; - send_chunk(dns_fd); - } else { - outpkt.offset = 0; - outpkt.len = 0; - outpkt.sentlen = 0; - outchunkresent = 0; + if (i == 0) { + /* timeout */ + if (is_sending()) { + /* Re-send current fragment; either frag + or ack probably dropped somewhere. + But problem: no cache-miss-counter, + so hostname will be identical. + Just drop whole packet after 3 retries, + and TCP retransmit will solve it. + NOTE: tun dropping above should be + >=(value_here - 1) */ + if (outchunkresent < 3) { + outchunkresent++; + send_chunk(dns_fd); + } else { + outpkt.offset = 0; + outpkt.len = 0; + outpkt.sentlen = 0; + outchunkresent = 0; - send_ping(dns_fd); - } - } else { - send_ping(dns_fd); - } - send_ping_soon = 0; + send_ping(dns_fd); + } + } else { + send_ping(dns_fd); + } + send_ping_soon = 0; - } else { + } else { - if (FD_ISSET(tun_fd, &fds)) { - if (tunnel_tun(tun_fd, dns_fd) <= 0) - continue; - /* Returns -1 on error OR when quickly - dropping data in case of DNS congestion; - we need to _not_ do tunnel_dns() then. - If chunk sent, sets send_ping_soon=0. */ - } - if (FD_ISSET(dns_fd, &fds)) { - if (tunnel_dns(tun_fd, dns_fd) <= 0) - continue; - } - } - } + if (FD_ISSET(tun_fd, &fds)) { + if (tunnel_tun(tun_fd, dns_fd) <= 0) + continue; + /* Returns -1 on error OR when quickly + dropping data in case of DNS congestion; + we need to _not_ do tunnel_dns() then. + If chunk sent, sets send_ping_soon=0. */ + } + if (FD_ISSET(dns_fd, &fds)) { + if (tunnel_dns(tun_fd, dns_fd) <= 0) + continue; + } + } + } - return rv; + return rv; } static void send_login(int fd, char *login, int len) { - char data[19]; + char data[19]; - memset(data, 0, sizeof(data)); - data[0] = userid; - memcpy(&data[1], login, MIN(len, 16)); + memset(data, 0, sizeof(data)); + data[0] = userid; + memcpy(&data[1], login, MIN(len, 16)); - data[17] = (rand_seed >> 8) & 0xff; - data[18] = (rand_seed >> 0) & 0xff; + data[17] = (rand_seed >> 8) & 0xff; + data[18] = (rand_seed >> 0) & 0xff; - rand_seed++; + rand_seed++; - send_packet(fd, 'l', data, sizeof(data)); + send_packet(fd, 'l', data, sizeof(data)); } static void send_fragsize_probe(int fd, int fragsize) { - char probedata[256]; - char buf[4096]; + char probedata[256]; + char buf[4096]; - /* - * build a large query domain which is random and maximum size, - * will also take up maximal space in the return packet - */ - memset(probedata, MAX(1, rand_seed & 0xff), sizeof(probedata)); - probedata[1] = MAX(1, (rand_seed >> 8) & 0xff); - rand_seed++; + /* + * build a large query domain which is random and maximum size, + * will also take up maximal space in the return packet + */ + memset(probedata, MAX(1, rand_seed & 0xff), sizeof(probedata)); + probedata[1] = MAX(1, (rand_seed >> 8) & 0xff); + rand_seed++; - /* Note: must either be same, or larger, than send_chunk() */ - build_hostname(buf + 5, sizeof(buf) - 5, probedata, sizeof(probedata), - topdomain, dataenc, hostname_maxlen); + /* Note: must either be same, or larger, than send_chunk() */ + build_hostname(buf + 5, sizeof(buf) - 5, probedata, sizeof(probedata), + topdomain, dataenc, hostname_maxlen); - fragsize &= 2047; + fragsize &= 2047; - buf[0] = 'r'; /* Probe downstream fragsize packet */ - buf[1] = b32_5to8((userid << 1) | ((fragsize >> 10) & 1)); - buf[2] = b32_5to8((fragsize >> 5) & 31); - buf[3] = b32_5to8(fragsize & 31); - buf[4] = 'd'; /* dummy to match send_chunk() */ + buf[0] = 'r'; /* Probe downstream fragsize packet */ + buf[1] = b32_5to8((userid << 1) | ((fragsize >> 10) & 1)); + buf[2] = b32_5to8((fragsize >> 5) & 31); + buf[3] = b32_5to8(fragsize & 31); + buf[4] = 'd'; /* dummy to match send_chunk() */ - send_query(fd, buf); + send_query(fd, buf); } static void send_set_downstream_fragsize(int fd, int fragsize) { - char data[5]; + char data[5]; - data[0] = userid; - data[1] = (fragsize & 0xff00) >> 8; - data[2] = (fragsize & 0x00ff); - data[3] = (rand_seed >> 8) & 0xff; - data[4] = (rand_seed >> 0) & 0xff; + data[0] = userid; + data[1] = (fragsize & 0xff00) >> 8; + data[2] = (fragsize & 0x00ff); + data[3] = (rand_seed >> 8) & 0xff; + data[4] = (rand_seed >> 0) & 0xff; - rand_seed++; + rand_seed++; - send_packet(fd, 'n', data, sizeof(data)); + send_packet(fd, 'n', data, sizeof(data)); } static void send_version(int fd, uint32_t version) { - char data[6]; + char data[6]; - data[0] = (version >> 24) & 0xff; - data[1] = (version >> 16) & 0xff; - data[2] = (version >> 8) & 0xff; - data[3] = (version >> 0) & 0xff; + data[0] = (version >> 24) & 0xff; + data[1] = (version >> 16) & 0xff; + data[2] = (version >> 8) & 0xff; + data[3] = (version >> 0) & 0xff; - data[4] = (rand_seed >> 8) & 0xff; - data[5] = (rand_seed >> 0) & 0xff; + data[4] = (rand_seed >> 8) & 0xff; + data[5] = (rand_seed >> 0) & 0xff; - rand_seed++; + rand_seed++; - send_packet(fd, 'v', data, sizeof(data)); + send_packet(fd, 'v', data, sizeof(data)); } static void send_ip_request(int fd, int userid) { - char buf[512] = "i____."; - buf[1] = b32_5to8(userid); + char buf[512] = "i____."; + buf[1] = b32_5to8(userid); - buf[2] = b32_5to8((rand_seed >> 10) & 0x1f); - buf[3] = b32_5to8((rand_seed >> 5) & 0x1f); - buf[4] = b32_5to8((rand_seed ) & 0x1f); - rand_seed++; + buf[2] = b32_5to8((rand_seed >> 10) & 0x1f); + buf[3] = b32_5to8((rand_seed >> 5) & 0x1f); + buf[4] = b32_5to8((rand_seed ) & 0x1f); + rand_seed++; - strncat(buf, topdomain, 512 - strlen(buf)); - send_query(fd, buf); + strncat(buf, topdomain, 512 - strlen(buf)); + send_query(fd, buf); } static void send_raw_udp_login(int dns_fd, int userid, int seed) { - char buf[16]; - login_calculate(buf, 16, password, seed + 1); + char buf[16]; + login_calculate(buf, 16, password, seed + 1); - send_raw(dns_fd, buf, sizeof(buf), userid, RAW_HDR_CMD_LOGIN); + send_raw(dns_fd, buf, sizeof(buf), userid, RAW_HDR_CMD_LOGIN); } static void send_upenctest(int fd, char *s) /* NOTE: String may be at most 63-4=59 chars to fit in 1 dns chunk. */ { - char buf[512] = "z___"; + char buf[512] = "z___"; - buf[1] = b32_5to8((rand_seed >> 10) & 0x1f); - buf[2] = b32_5to8((rand_seed >> 5) & 0x1f); - buf[3] = b32_5to8((rand_seed ) & 0x1f); - rand_seed++; + buf[1] = b32_5to8((rand_seed >> 10) & 0x1f); + buf[2] = b32_5to8((rand_seed >> 5) & 0x1f); + buf[3] = b32_5to8((rand_seed ) & 0x1f); + rand_seed++; - strncat(buf, s, 512); - strncat(buf, ".", 512); - strncat(buf, topdomain, 512 - strlen(buf)); - send_query(fd, buf); + strncat(buf, s, 512); + strncat(buf, ".", 512); + strncat(buf, topdomain, 512 - strlen(buf)); + send_query(fd, buf); } static void send_downenctest(int fd, char downenc, int variant, char *s, int slen) /* Note: content/handling of s is not defined yet. */ { - char buf[512] = "y_____."; + char buf[512] = "y_____."; - buf[1] = tolower(downenc); - buf[2] = b32_5to8(variant); + buf[1] = tolower(downenc); + buf[2] = b32_5to8(variant); - buf[3] = b32_5to8((rand_seed >> 10) & 0x1f); - buf[4] = b32_5to8((rand_seed >> 5) & 0x1f); - buf[5] = b32_5to8((rand_seed ) & 0x1f); - rand_seed++; + buf[3] = b32_5to8((rand_seed >> 10) & 0x1f); + buf[4] = b32_5to8((rand_seed >> 5) & 0x1f); + buf[5] = b32_5to8((rand_seed ) & 0x1f); + rand_seed++; - strncat(buf, topdomain, 512 - strlen(buf)); - send_query(fd, buf); + strncat(buf, topdomain, 512 - strlen(buf)); + send_query(fd, buf); } static void send_codec_switch(int fd, int userid, int bits) { - char buf[512] = "s_____."; - buf[1] = b32_5to8(userid); - buf[2] = b32_5to8(bits); + char buf[512] = "s_____."; + buf[1] = b32_5to8(userid); + buf[2] = b32_5to8(bits); - buf[3] = b32_5to8((rand_seed >> 10) & 0x1f); - buf[4] = b32_5to8((rand_seed >> 5) & 0x1f); - buf[5] = b32_5to8((rand_seed ) & 0x1f); - rand_seed++; + buf[3] = b32_5to8((rand_seed >> 10) & 0x1f); + buf[4] = b32_5to8((rand_seed >> 5) & 0x1f); + buf[5] = b32_5to8((rand_seed ) & 0x1f); + rand_seed++; - strncat(buf, topdomain, 512 - strlen(buf)); - send_query(fd, buf); + strncat(buf, topdomain, 512 - strlen(buf)); + send_query(fd, buf); } static void send_downenc_switch(int fd, int userid) { - char buf[512] = "o_____."; - buf[1] = b32_5to8(userid); - buf[2] = tolower(downenc); + char buf[512] = "o_____."; + buf[1] = b32_5to8(userid); + buf[2] = tolower(downenc); - buf[3] = b32_5to8((rand_seed >> 10) & 0x1f); - buf[4] = b32_5to8((rand_seed >> 5) & 0x1f); - buf[5] = b32_5to8((rand_seed ) & 0x1f); - rand_seed++; + buf[3] = b32_5to8((rand_seed >> 10) & 0x1f); + buf[4] = b32_5to8((rand_seed >> 5) & 0x1f); + buf[5] = b32_5to8((rand_seed ) & 0x1f); + rand_seed++; - strncat(buf, topdomain, 512 - strlen(buf)); - send_query(fd, buf); + strncat(buf, topdomain, 512 - strlen(buf)); + send_query(fd, buf); } static void send_lazy_switch(int fd, int userid) { - char buf[512] = "o_____."; - buf[1] = b32_5to8(userid); + char buf[512] = "o_____."; + buf[1] = b32_5to8(userid); - if (lazymode) - buf[2] = 'l'; - else - buf[2] = 'i'; + if (lazymode) + buf[2] = 'l'; + else + buf[2] = 'i'; - buf[3] = b32_5to8((rand_seed >> 10) & 0x1f); - buf[4] = b32_5to8((rand_seed >> 5) & 0x1f); - buf[5] = b32_5to8((rand_seed ) & 0x1f); - rand_seed++; + buf[3] = b32_5to8((rand_seed >> 10) & 0x1f); + buf[4] = b32_5to8((rand_seed >> 5) & 0x1f); + buf[5] = b32_5to8((rand_seed ) & 0x1f); + rand_seed++; - strncat(buf, topdomain, 512 - strlen(buf)); - send_query(fd, buf); + strncat(buf, topdomain, 512 - strlen(buf)); + send_query(fd, buf); } static int handshake_version(int dns_fd, int *seed) { - char hex[] = "0123456789abcdef"; - char hex2[] = "0123456789ABCDEF"; - char in[4096]; - uint32_t payload; - int i; - int read; + char hex[] = "0123456789abcdef"; + char hex2[] = "0123456789ABCDEF"; + char in[4096]; + uint32_t payload; + int i; + int read; - for (i = 0; running && i < 5; i++) { + for (i = 0; running && i < 5; i++) { - send_version(dns_fd, PROTOCOL_VERSION); + send_version(dns_fd, PROTOCOL_VERSION); - read = handshake_waitdns(dns_fd, in, sizeof(in), 'v', 'V', i+1); + read = handshake_waitdns(dns_fd, in, sizeof(in), 'v', 'V', i+1); - if (read >= 9) { - payload = (((in[4] & 0xff) << 24) | - ((in[5] & 0xff) << 16) | - ((in[6] & 0xff) << 8) | - ((in[7] & 0xff))); + if (read >= 9) { + payload = (((in[4] & 0xff) << 24) | + ((in[5] & 0xff) << 16) | + ((in[6] & 0xff) << 8) | + ((in[7] & 0xff))); - if (strncmp("VACK", in, 4) == 0) { - *seed = payload; - userid = in[8]; - userid_char = hex[userid & 15]; - userid_char2 = hex2[userid & 15]; + if (strncmp("VACK", in, 4) == 0) { + *seed = payload; + userid = in[8]; + userid_char = hex[userid & 15]; + userid_char2 = hex2[userid & 15]; - fprintf(stderr, "Version ok, both using protocol v 0x%08x. You are user #%d\n", - PROTOCOL_VERSION, userid); - return 0; - } else if (strncmp("VNAK", in, 4) == 0) { - warnx("You use protocol v 0x%08x, server uses v 0x%08x. Giving up", - PROTOCOL_VERSION, payload); - return 1; - } else if (strncmp("VFUL", in, 4) == 0) { - warnx("Server full, all %d slots are taken. Try again later", payload); - return 1; - } - } else if (read > 0) - warnx("did not receive proper login challenge"); + fprintf(stderr, "Version ok, both using protocol v 0x%08x. You are user #%d\n", + PROTOCOL_VERSION, userid); + return 0; + } else if (strncmp("VNAK", in, 4) == 0) { + warnx("You use protocol v 0x%08x, server uses v 0x%08x. Giving up", + PROTOCOL_VERSION, payload); + return 1; + } else if (strncmp("VFUL", in, 4) == 0) { + warnx("Server full, all %d slots are taken. Try again later", payload); + return 1; + } + } else if (read > 0) + warnx("did not receive proper login challenge"); - fprintf(stderr, "Retrying version check...\n"); - } - warnx("couldn't connect to server (maybe other -T options will work)"); - return 1; + fprintf(stderr, "Retrying version check...\n"); + } + warnx("couldn't connect to server (maybe other -T options will work)"); + return 1; } static int handshake_login(int dns_fd, int seed) { - char in[4096]; - char login[16]; - char server[65]; - char client[65]; - int mtu; - int i; - int read; + char in[4096]; + char login[16]; + char server[65]; + char client[65]; + int mtu; + int i; + int read; - login_calculate(login, 16, password, seed); + login_calculate(login, 16, password, seed); - for (i=0; running && i<5 ;i++) { + for (i=0; running && i<5 ;i++) { - send_login(dns_fd, login, 16); + send_login(dns_fd, login, 16); - read = handshake_waitdns(dns_fd, in, sizeof(in), 'l', 'L', i+1); + read = handshake_waitdns(dns_fd, in, sizeof(in), 'l', 'L', i+1); - if (read > 0) { - int netmask; - if (strncmp("LNAK", in, 4) == 0) { - fprintf(stderr, "Bad password\n"); - return 1; - } else if (sscanf(in, "%64[^-]-%64[^-]-%d-%d", - server, client, &mtu, &netmask) == 4) { + if (read > 0) { + int netmask; + if (strncmp("LNAK", in, 4) == 0) { + fprintf(stderr, "Bad password\n"); + return 1; + } else if (sscanf(in, "%64[^-]-%64[^-]-%d-%d", + server, client, &mtu, &netmask) == 4) { - server[64] = 0; - client[64] = 0; - if (tun_setip(client, server, netmask) == 0 && - tun_setmtu(mtu) == 0) { + server[64] = 0; + client[64] = 0; + if (tun_setip(client, server, netmask) == 0 && + tun_setmtu(mtu) == 0) { - fprintf(stderr, "Server tunnel IP is %s\n", server); - return 0; - } else { - errx(4, "Failed to set IP and MTU"); - } - } else { - fprintf(stderr, "Received bad handshake\n"); - } - } + fprintf(stderr, "Server tunnel IP is %s\n", server); + return 0; + } else { + errx(4, "Failed to set IP and MTU"); + } + } else { + fprintf(stderr, "Received bad handshake\n"); + } + } - fprintf(stderr, "Retrying login...\n"); - } - warnx("couldn't login to server"); - return 1; + fprintf(stderr, "Retrying login...\n"); + } + warnx("couldn't login to server"); + return 1; } static int handshake_raw_udp(int dns_fd, int seed) { - struct timeval tv; - char in[4096]; - fd_set fds; - int i; - int r; - int len; - unsigned remoteaddr = 0; - struct in_addr server; + struct timeval tv; + char in[4096]; + fd_set fds; + int i; + int r; + int len; + unsigned remoteaddr = 0; + struct in_addr server; - fprintf(stderr, "Testing raw UDP data to the server (skip with -r)"); - for (i=0; running && i<3 ;i++) { + fprintf(stderr, "Testing raw UDP data to the server (skip with -r)"); + for (i=0; running && i<3 ;i++) { - send_ip_request(dns_fd, userid); + send_ip_request(dns_fd, userid); - len = handshake_waitdns(dns_fd, in, sizeof(in), 'i', 'I', i+1); + len = handshake_waitdns(dns_fd, in, sizeof(in), 'i', 'I', i+1); - if (len == 5 && in[0] == 'I') { - /* Received IP address */ - remoteaddr = (in[1] & 0xff); - remoteaddr <<= 8; - remoteaddr |= (in[2] & 0xff); - remoteaddr <<= 8; - remoteaddr |= (in[3] & 0xff); - remoteaddr <<= 8; - remoteaddr |= (in[4] & 0xff); - server.s_addr = ntohl(remoteaddr); - break; - } + if (len == 5 && in[0] == 'I') { + /* Received IP address */ + remoteaddr = (in[1] & 0xff); + remoteaddr <<= 8; + remoteaddr |= (in[2] & 0xff); + remoteaddr <<= 8; + remoteaddr |= (in[3] & 0xff); + remoteaddr <<= 8; + remoteaddr |= (in[4] & 0xff); + server.s_addr = ntohl(remoteaddr); + break; + } - fprintf(stderr, "."); - fflush(stderr); - } - fprintf(stderr, "\n"); - if (!running) - return 0; + fprintf(stderr, "."); + fflush(stderr); + } + fprintf(stderr, "\n"); + if (!running) + return 0; - if (!remoteaddr) { - fprintf(stderr, "Failed to get raw server IP, will use DNS mode.\n"); - return 0; - } - fprintf(stderr, "Server is at %s, trying raw login: ", inet_ntoa(server)); - fflush(stderr); + if (!remoteaddr) { + fprintf(stderr, "Failed to get raw server IP, will use DNS mode.\n"); + return 0; + } + fprintf(stderr, "Server is at %s, trying raw login: ", inet_ntoa(server)); + fflush(stderr); - /* Store address to iodined server */ - memset(&raw_serv, 0, sizeof(raw_serv)); - raw_serv.sin_family = AF_INET; - raw_serv.sin_port = htons(53); - raw_serv.sin_addr = server; + /* Store address to iodined server */ + memset(&raw_serv, 0, sizeof(raw_serv)); + raw_serv.sin_family = AF_INET; + raw_serv.sin_port = htons(53); + raw_serv.sin_addr = server; - /* do login against port 53 on remote server - * based on the old seed. If reply received, - * switch to raw udp mode */ - for (i=0; running && i<4 ;i++) { - tv.tv_sec = i + 1; - tv.tv_usec = 0; + /* do login against port 53 on remote server + * based on the old seed. If reply received, + * switch to raw udp mode */ + for (i=0; running && i<4 ;i++) { + tv.tv_sec = i + 1; + tv.tv_usec = 0; - send_raw_udp_login(dns_fd, userid, seed); + send_raw_udp_login(dns_fd, userid, seed); - FD_ZERO(&fds); - FD_SET(dns_fd, &fds); + FD_ZERO(&fds); + FD_SET(dns_fd, &fds); - r = select(dns_fd + 1, &fds, NULL, NULL, &tv); + r = select(dns_fd + 1, &fds, NULL, NULL, &tv); - if(r > 0) { - /* recv() needed for windows, dont change to read() */ - len = recv(dns_fd, in, sizeof(in), 0); - if (len >= (16 + RAW_HDR_LEN)) { - char hash[16]; - login_calculate(hash, 16, password, seed - 1); - if (memcmp(in, raw_header, RAW_HDR_IDENT_LEN) == 0 - && RAW_HDR_GET_CMD(in) == RAW_HDR_CMD_LOGIN - && memcmp(&in[RAW_HDR_LEN], hash, sizeof(hash)) == 0) { + if(r > 0) { + /* recv() needed for windows, dont change to read() */ + len = recv(dns_fd, in, sizeof(in), 0); + if (len >= (16 + RAW_HDR_LEN)) { + char hash[16]; + login_calculate(hash, 16, password, seed - 1); + if (memcmp(in, raw_header, RAW_HDR_IDENT_LEN) == 0 + && RAW_HDR_GET_CMD(in) == RAW_HDR_CMD_LOGIN + && memcmp(&in[RAW_HDR_LEN], hash, sizeof(hash)) == 0) { - fprintf(stderr, "OK\n"); - return 1; - } - } - } - fprintf(stderr, "."); - fflush(stderr); - } + fprintf(stderr, "OK\n"); + return 1; + } + } + } + fprintf(stderr, "."); + fflush(stderr); + } - fprintf(stderr, "failed\n"); - return 0; + fprintf(stderr, "failed\n"); + return 0; } static int @@ -1577,72 +1577,72 @@ handshake_upenctest(int dns_fd, char *s) 1: identical string returned */ { - char in[4096]; - unsigned char *uin = (unsigned char *) in; - unsigned char *us = (unsigned char *) s; - int i; - int read; + char in[4096]; + unsigned char *uin = (unsigned char *) in; + unsigned char *us = (unsigned char *) s; + int i; + int read; int slen; - slen = strlen(s); - for (i=0; running && i<3 ;i++) { + slen = strlen(s); + for (i=0; running && i<3 ;i++) { - send_upenctest(dns_fd, s); + send_upenctest(dns_fd, s); - read = handshake_waitdns(dns_fd, in, sizeof(in), 'z', 'Z', i+1); + read = handshake_waitdns(dns_fd, in, sizeof(in), 'z', 'Z', i+1); - if (read == -2) - return 0; /* hard error */ + if (read == -2) + return 0; /* hard error */ - if (read > 0 && read < slen + 4) - return 0; /* reply too short (chars dropped) */ + if (read > 0 && read < slen + 4) + return 0; /* reply too short (chars dropped) */ - if (read > 0) { - int k; + if (read > 0) { + int k; #if 0 - /* in[56] = '@'; */ - /* in[56] = '_'; */ - /* if (in[29] == '\344') in[29] = 'a'; */ - in[read] = '\0'; - fprintf(stderr, "BounceReply: >%s<\n", in); + /* in[56] = '@'; */ + /* in[56] = '_'; */ + /* if (in[29] == '\344') in[29] = 'a'; */ + in[read] = '\0'; + fprintf(stderr, "BounceReply: >%s<\n", in); #endif - /* quick check if case swapped, to give informative error msg */ - if (in[4] == 'A') { - fprintf(stderr, "DNS queries get changed to uppercase, keeping upstream codec Base32\n"); - return -1; - } - if (in[5] == 'a') { - fprintf(stderr, "DNS queries get changed to lowercase, keeping upstream codec Base32\n"); - return -1; - } + /* quick check if case swapped, to give informative error msg */ + if (in[4] == 'A') { + fprintf(stderr, "DNS queries get changed to uppercase, keeping upstream codec Base32\n"); + return -1; + } + if (in[5] == 'a') { + fprintf(stderr, "DNS queries get changed to lowercase, keeping upstream codec Base32\n"); + return -1; + } - for (k = 0; k < slen; k++) { - if (in[k+4] != s[k]) { - /* Definitely not reliable */ - if (in[k+4] >= ' ' && in[k+4] <= '~' && - s[k] >= ' ' && s[k] <= '~') { - fprintf(stderr, "DNS query char '%c' gets changed into '%c'\n", - s[k], in[k+4]); - } else { - fprintf(stderr, "DNS query char 0x%02X gets changed into 0x%02X\n", - (unsigned int) us[k], - (unsigned int) uin[k+4]); - } - return 0; - } - } - /* if still here, then all okay */ - return 1; - } + for (k = 0; k < slen; k++) { + if (in[k+4] != s[k]) { + /* Definitely not reliable */ + if (in[k+4] >= ' ' && in[k+4] <= '~' && + s[k] >= ' ' && s[k] <= '~') { + fprintf(stderr, "DNS query char '%c' gets changed into '%c'\n", + s[k], in[k+4]); + } else { + fprintf(stderr, "DNS query char 0x%02X gets changed into 0x%02X\n", + (unsigned int) us[k], + (unsigned int) uin[k+4]); + } + return 0; + } + } + /* if still here, then all okay */ + return 1; + } - fprintf(stderr, "Retrying upstream codec test...\n"); - } + fprintf(stderr, "Retrying upstream codec test...\n"); + } - if (!running) - return -1; + if (!running) + return -1; - /* timeout */ - return 0; + /* timeout */ + return 0; } static int @@ -1654,90 +1654,90 @@ handshake_upenc_autodetect(int dns_fd) 3: Base128 is okay */ { - /* Note: max 59 chars, must start with "aA". - pat64: If 0129 work, assume 3-8 are okay too. + /* Note: max 59 chars, must start with "aA". + pat64: If 0129 work, assume 3-8 are okay too. - RFC1035 par 2.3.1 states that [A-Z0-9-] allowed, but only - [A-Z] as first, and [A-Z0-9] as last char _per label_. - Test by having '-' as last char. - */ + RFC1035 par 2.3.1 states that [A-Z0-9-] allowed, but only + [A-Z] as first, and [A-Z0-9] as last char _per label_. + Test by having '-' as last char. + */ char *pat64="aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ+0129-"; char *pat64u="aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ_0129-"; char *pat128a="aA-Aaahhh-Drink-mal-ein-J\344germeister-"; char *pat128b="aA-La-fl\373te-na\357ve-fran\347aise-est-retir\351-\340-Cr\350te"; char *pat128c="aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ"; char *pat128d="aA0123456789\274\275\276\277" - "\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"; + "\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"; char *pat128e="aA" - "\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337" - "\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357" - "\360\361\362\363\364\365\366\367\370\371\372\373\374\375"; - int res; + "\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337" + "\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357" + "\360\361\362\363\364\365\366\367\370\371\372\373\374\375"; + int res; - /* Try Base128, starting very gently to not draw attention */ - while (1) { - res = handshake_upenctest(dns_fd, pat128a); - if (res < 0) { - /* DNS swaps case, msg already printed; or Ctrl-C */ - return 0; - } else if (res == 0) { - /* Probably not okay, skip Base128 entirely */ - break; - } + /* Try Base128, starting very gently to not draw attention */ + while (1) { + res = handshake_upenctest(dns_fd, pat128a); + if (res < 0) { + /* DNS swaps case, msg already printed; or Ctrl-C */ + return 0; + } else if (res == 0) { + /* Probably not okay, skip Base128 entirely */ + break; + } - res = handshake_upenctest(dns_fd, pat128b); - if (res < 0) - return 0; - else if (res == 0) - break; + res = handshake_upenctest(dns_fd, pat128b); + if (res < 0) + return 0; + else if (res == 0) + break; - /* if this works, we can test the real stuff */ + /* if this works, we can test the real stuff */ - res = handshake_upenctest(dns_fd, pat128c); - if (res < 0) - return 0; - else if (res == 0) - break; + res = handshake_upenctest(dns_fd, pat128c); + if (res < 0) + return 0; + else if (res == 0) + break; - res = handshake_upenctest(dns_fd, pat128d); - if (res < 0) - return 0; - else if (res == 0) - break; + res = handshake_upenctest(dns_fd, pat128d); + if (res < 0) + return 0; + else if (res == 0) + break; - res = handshake_upenctest(dns_fd, pat128e); - if (res < 0) - return 0; - else if (res == 0) - break; + res = handshake_upenctest(dns_fd, pat128e); + if (res < 0) + return 0; + else if (res == 0) + break; - /* if still here, then base128 works completely */ - return 3; - } + /* if still here, then base128 works completely */ + return 3; + } - /* Try Base64 (with plus sign) */ - res = handshake_upenctest(dns_fd, pat64); - if (res < 0) { - /* DNS swaps case, msg already printed; or Ctrl-C */ - return 0; - } else if (res > 0) { - /* All okay, Base64 msg will be printed later */ - return 1; - } + /* Try Base64 (with plus sign) */ + res = handshake_upenctest(dns_fd, pat64); + if (res < 0) { + /* DNS swaps case, msg already printed; or Ctrl-C */ + return 0; + } else if (res > 0) { + /* All okay, Base64 msg will be printed later */ + return 1; + } - /* Try Base64u (with _u_nderscore) */ - res = handshake_upenctest(dns_fd, pat64u); - if (res < 0) { - /* DNS swaps case, msg already printed; or Ctrl-C */ - return 0; - } else if (res > 0) { - /* All okay, Base64u msg will be printed later */ - return 2; - } + /* Try Base64u (with _u_nderscore) */ + res = handshake_upenctest(dns_fd, pat64u); + if (res < 0) { + /* DNS swaps case, msg already printed; or Ctrl-C */ + return 0; + } else if (res > 0) { + /* All okay, Base64u msg will be printed later */ + return 2; + } - /* if here, then nonthing worked */ - fprintf(stderr, "Keeping upstream codec Base32\n"); - return 0; + /* if here, then nonthing worked */ + fprintf(stderr, "Keeping upstream codec Base32\n"); + return 0; } static int @@ -1747,89 +1747,89 @@ handshake_downenctest(int dns_fd, char trycodec) 1: identical string returned */ { - char in[4096]; - int i; - int read; - char *s = DOWNCODECCHECK1; + char in[4096]; + int i; + int read; + char *s = DOWNCODECCHECK1; int slen = DOWNCODECCHECK1_LEN; - for (i=0; running && i<3 ;i++) { + for (i=0; running && i<3 ;i++) { - send_downenctest(dns_fd, trycodec, 1, NULL, 0); + send_downenctest(dns_fd, trycodec, 1, NULL, 0); - read = handshake_waitdns(dns_fd, in, sizeof(in), 'y', 'Y', i+1); + read = handshake_waitdns(dns_fd, in, sizeof(in), 'y', 'Y', i+1); - if (read == -2) - return 0; /* hard error */ + if (read == -2) + return 0; /* hard error */ - if (read > 0 && read != slen) - return 0; /* reply incorrect = unreliable */ + if (read > 0 && read != slen) + return 0; /* reply incorrect = unreliable */ - if (read > 0) { - int k; - for (k = 0; k < slen; k++) { - if (in[k] != s[k]) { - /* Definitely not reliable */ - return 0; - } - } - /* if still here, then all okay */ - return 1; - } + if (read > 0) { + int k; + for (k = 0; k < slen; k++) { + if (in[k] != s[k]) { + /* Definitely not reliable */ + return 0; + } + } + /* if still here, then all okay */ + return 1; + } - fprintf(stderr, "Retrying downstream codec test...\n"); - } + fprintf(stderr, "Retrying downstream codec test...\n"); + } - /* timeout */ - return 0; + /* timeout */ + return 0; } static char handshake_downenc_autodetect(int dns_fd) /* Returns codec char (or ' ' if no advanced codec works) */ { - int base64ok = 0; - int base64uok = 0; - int base128ok = 0; + int base64ok = 0; + int base64uok = 0; + int base128ok = 0; - if (do_qtype == T_NULL || do_qtype == T_PRIVATE) { - /* no other choice than raw */ - fprintf(stderr, "No alternative downstream codec available, using default (Raw)\n"); - return ' '; - } + if (do_qtype == T_NULL || do_qtype == T_PRIVATE) { + /* no other choice than raw */ + fprintf(stderr, "No alternative downstream codec available, using default (Raw)\n"); + return ' '; + } - fprintf(stderr, "Autodetecting downstream codec (use -O to override)\n"); + fprintf(stderr, "Autodetecting downstream codec (use -O to override)\n"); - /* Try Base64 */ - if (handshake_downenctest(dns_fd, 'S')) - base64ok = 1; - else if (running && handshake_downenctest(dns_fd, 'U')) - base64uok = 1; + /* Try Base64 */ + if (handshake_downenctest(dns_fd, 'S')) + base64ok = 1; + else if (running && handshake_downenctest(dns_fd, 'U')) + base64uok = 1; - /* Try Base128 only if 64 gives us some perspective */ - if (running && (base64ok || base64uok)) { - if (handshake_downenctest(dns_fd, 'V')) - base128ok = 1; - } + /* Try Base128 only if 64 gives us some perspective */ + if (running && (base64ok || base64uok)) { + if (handshake_downenctest(dns_fd, 'V')) + base128ok = 1; + } - /* If 128 works, then TXT may give us Raw as well */ - if (running && (base128ok && do_qtype == T_TXT)) { - if (handshake_downenctest(dns_fd, 'R')) - return 'R'; - } + /* If 128 works, then TXT may give us Raw as well */ + if (running && (base128ok && do_qtype == T_TXT)) { + if (handshake_downenctest(dns_fd, 'R')) + return 'R'; + } - if (!running) - return ' '; + if (!running) + return ' '; - if (base128ok) - return 'V'; - if (base64ok) - return 'S'; - if (base64uok) - return 'U'; + if (base128ok) + return 'V'; + if (base64ok) + return 'S'; + if (base64uok) + return 'U'; - fprintf(stderr, "No advanced downstream codecs seem to work, using default (Base32)\n"); - return ' '; + fprintf(stderr, "No advanced downstream codecs seem to work, using default (Base32)\n"); + return ' '; } static int @@ -1839,53 +1839,53 @@ handshake_qtypetest(int dns_fd, int timeout) 1: works properly */ { - char in[4096]; - int read; - char *s = DOWNCODECCHECK1; + char in[4096]; + int read; + char *s = DOWNCODECCHECK1; int slen = DOWNCODECCHECK1_LEN; - int trycodec; - int k; + int trycodec; + int k; - if (do_qtype == T_NULL || do_qtype == T_PRIVATE) - trycodec = 'R'; - else - trycodec = 'T'; + if (do_qtype == T_NULL || do_qtype == T_PRIVATE) + trycodec = 'R'; + else + trycodec = 'T'; - /* We could use 'Z' bouncing here, but 'Y' also tests that 0-255 - byte values can be returned, which is needed for NULL/PRIVATE - to work. */ + /* We could use 'Z' bouncing here, but 'Y' also tests that 0-255 + byte values can be returned, which is needed for NULL/PRIVATE + to work. */ - send_downenctest(dns_fd, trycodec, 1, NULL, 0); + send_downenctest(dns_fd, trycodec, 1, NULL, 0); - read = handshake_waitdns(dns_fd, in, sizeof(in), 'y', 'Y', timeout); + read = handshake_waitdns(dns_fd, in, sizeof(in), 'y', 'Y', timeout); - if (read != slen) - return 0; /* incorrect */ + if (read != slen) + return 0; /* incorrect */ - for (k = 0; k < slen; k++) { - if (in[k] != s[k]) { - /* corrupted */ - return 0; - } - } + for (k = 0; k < slen; k++) { + if (in[k] != s[k]) { + /* corrupted */ + return 0; + } + } - /* if still here, then all okay */ - return 1; + /* if still here, then all okay */ + return 1; } static int handshake_qtype_numcvt(int num) { - switch (num) { - case 0: return T_NULL; - case 1: return T_PRIVATE; - case 2: return T_TXT; - case 3: return T_SRV; - case 4: return T_MX; - case 5: return T_CNAME; - case 6: return T_A; - } - return T_UNSET; + switch (num) { + case 0: return T_NULL; + case 1: return T_PRIVATE; + case 2: return T_TXT; + case 3: return T_SRV; + case 4: return T_MX; + case 5: return T_CNAME; + case 6: return T_A; + } + return T_UNSET; } static int @@ -1895,69 +1895,69 @@ handshake_qtype_autodetect(int dns_fd) 1: problem, program exit */ { - int highestworking = 100; - int timeout; - int qtypenum; + int highestworking = 100; + int timeout; + int qtypenum; - fprintf(stderr, "Autodetecting DNS query type (use -T to override)"); - fflush(stderr); + fprintf(stderr, "Autodetecting DNS query type (use -T to override)"); + fflush(stderr); - /* Method: try all "interesting" qtypes with a 1-sec timeout, then try - all "still-interesting" qtypes with a 2-sec timeout, etc. - "Interesting" means: qtypes that (are expected to) have higher - bandwidth than what we know is working already (highestworking). + /* Method: try all "interesting" qtypes with a 1-sec timeout, then try + all "still-interesting" qtypes with a 2-sec timeout, etc. + "Interesting" means: qtypes that (are expected to) have higher + bandwidth than what we know is working already (highestworking). - Note that DNS relays may not immediately resolve the first (NULL) - query in 1 sec, due to long recursive lookups, so we keep trying - to see if things will start working after a while. - */ + Note that DNS relays may not immediately resolve the first (NULL) + query in 1 sec, due to long recursive lookups, so we keep trying + to see if things will start working after a while. + */ - for (timeout = 1; running && timeout <= 3; timeout++) { - for (qtypenum = 0; running && qtypenum < highestworking; qtypenum++) { - do_qtype = handshake_qtype_numcvt(qtypenum); - if (do_qtype == T_UNSET) - break; /* this round finished */ + for (timeout = 1; running && timeout <= 3; timeout++) { + for (qtypenum = 0; running && qtypenum < highestworking; qtypenum++) { + do_qtype = handshake_qtype_numcvt(qtypenum); + if (do_qtype == T_UNSET) + break; /* this round finished */ - fprintf(stderr, "."); - fflush(stderr); + fprintf(stderr, "."); + fflush(stderr); - if (handshake_qtypetest(dns_fd, timeout)) { - /* okay */ - highestworking = qtypenum; + if (handshake_qtypetest(dns_fd, timeout)) { + /* okay */ + highestworking = qtypenum; #if 0 - fprintf(stderr, " Type %s timeout %d works\n", - client_get_qtype(), timeout); + fprintf(stderr, " Type %s timeout %d works\n", + client_get_qtype(), timeout); #endif - break; - /* try others with longer timeout */ - } - /* else: try next qtype with same timeout */ - } - if (highestworking == 0) - /* good, we have NULL; abort immediately */ - break; - } + break; + /* try others with longer timeout */ + } + /* else: try next qtype with same timeout */ + } + if (highestworking == 0) + /* good, we have NULL; abort immediately */ + break; + } - fprintf(stderr, "\n"); + fprintf(stderr, "\n"); - if (!running) { - warnx("Stopped while autodetecting DNS query type (try setting manually with -T)"); - return 1; /* problem */ - } + if (!running) { + warnx("Stopped while autodetecting DNS query type (try setting manually with -T)"); + return 1; /* problem */ + } - /* finished */ - do_qtype = handshake_qtype_numcvt(highestworking); + /* finished */ + do_qtype = handshake_qtype_numcvt(highestworking); - if (do_qtype == T_UNSET) { - /* also catches highestworking still 100 */ - warnx("No suitable DNS query type found. Are you connected to a network?"); - warnx("If you expect very long roundtrip delays, use -T explicitly."); - warnx("(Also, connecting to an \"ancient\" version of iodined won't work.)"); - return 1; /* problem */ - } + if (do_qtype == T_UNSET) { + /* also catches highestworking still 100 */ + warnx("No suitable DNS query type found. Are you connected to a network?"); + warnx("If you expect very long roundtrip delays, use -T explicitly."); + warnx("(Also, connecting to an \"ancient\" version of iodined won't work.)"); + return 1; /* problem */ + } - /* "using qtype" message printed in handshake function */ - return 0; /* okay */ + /* "using qtype" message printed in handshake function */ + return 0; /* okay */ } static int @@ -1967,501 +1967,501 @@ handshake_edns0_check(int dns_fd) 1: EDNS0 works */ { - char in[4096]; - int i; - int read; - char *s = DOWNCODECCHECK1; + char in[4096]; + int i; + int read; + char *s = DOWNCODECCHECK1; int slen = DOWNCODECCHECK1_LEN; - char trycodec; + char trycodec; - if (do_qtype == T_NULL) - trycodec = 'R'; - else - trycodec = 'T'; + if (do_qtype == T_NULL) + trycodec = 'R'; + else + trycodec = 'T'; - for (i=0; running && i<3 ;i++) { + for (i=0; running && i<3 ;i++) { - send_downenctest(dns_fd, trycodec, 1, NULL, 0); + send_downenctest(dns_fd, trycodec, 1, NULL, 0); - read = handshake_waitdns(dns_fd, in, sizeof(in), 'y', 'Y', i+1); + read = handshake_waitdns(dns_fd, in, sizeof(in), 'y', 'Y', i+1); - if (read == -2) - return 0; /* hard error */ + if (read == -2) + return 0; /* hard error */ - if (read > 0 && read != slen) - return 0; /* reply incorrect = unreliable */ + if (read > 0 && read != slen) + return 0; /* reply incorrect = unreliable */ - if (read > 0) { - int k; - for (k = 0; k < slen; k++) { - if (in[k] != s[k]) { - /* Definitely not reliable */ - return 0; - } - } - /* if still here, then all okay */ - return 1; - } + if (read > 0) { + int k; + for (k = 0; k < slen; k++) { + if (in[k] != s[k]) { + /* Definitely not reliable */ + return 0; + } + } + /* if still here, then all okay */ + return 1; + } - fprintf(stderr, "Retrying EDNS0 support test...\n"); - } + fprintf(stderr, "Retrying EDNS0 support test...\n"); + } - /* timeout or Ctrl-C */ - return 0; + /* timeout or Ctrl-C */ + return 0; } static void handshake_switch_codec(int dns_fd, int bits) { - char in[4096]; - int i; - int read; - struct encoder *tempenc; + char in[4096]; + int i; + int read; + struct encoder *tempenc; - if (bits == 5) - tempenc = get_base32_encoder(); - else if (bits == 6) - tempenc = get_base64_encoder(); - else if (bits == 26) /* "2nd" 6 bits per byte, with underscore */ - tempenc = get_base64u_encoder(); - else if (bits == 7) - tempenc = get_base128_encoder(); - else return; + if (bits == 5) + tempenc = get_base32_encoder(); + else if (bits == 6) + tempenc = get_base64_encoder(); + else if (bits == 26) /* "2nd" 6 bits per byte, with underscore */ + tempenc = get_base64u_encoder(); + else if (bits == 7) + tempenc = get_base128_encoder(); + else return; - fprintf(stderr, "Switching upstream to codec %s\n", tempenc->name); + fprintf(stderr, "Switching upstream to codec %s\n", tempenc->name); - for (i=0; running && i<5 ;i++) { + for (i=0; running && i<5 ;i++) { - send_codec_switch(dns_fd, userid, bits); + send_codec_switch(dns_fd, userid, bits); - read = handshake_waitdns(dns_fd, in, sizeof(in), 's', 'S', i+1); + read = handshake_waitdns(dns_fd, in, sizeof(in), 's', 'S', i+1); - if (read > 0) { - if (strncmp("BADLEN", in, 6) == 0) { - fprintf(stderr, "Server got bad message length. "); - goto codec_revert; - } else if (strncmp("BADIP", in, 5) == 0) { - fprintf(stderr, "Server rejected sender IP address. "); - goto codec_revert; - } else if (strncmp("BADCODEC", in, 8) == 0) { - fprintf(stderr, "Server rejected the selected codec. "); - goto codec_revert; - } - in[read] = 0; /* zero terminate */ - fprintf(stderr, "Server switched upstream to codec %s\n", in); - dataenc = tempenc; - return; - } + if (read > 0) { + if (strncmp("BADLEN", in, 6) == 0) { + fprintf(stderr, "Server got bad message length. "); + goto codec_revert; + } else if (strncmp("BADIP", in, 5) == 0) { + fprintf(stderr, "Server rejected sender IP address. "); + goto codec_revert; + } else if (strncmp("BADCODEC", in, 8) == 0) { + fprintf(stderr, "Server rejected the selected codec. "); + goto codec_revert; + } + in[read] = 0; /* zero terminate */ + fprintf(stderr, "Server switched upstream to codec %s\n", in); + dataenc = tempenc; + return; + } - fprintf(stderr, "Retrying codec switch...\n"); - } - if (!running) - return; + fprintf(stderr, "Retrying codec switch...\n"); + } + if (!running) + return; - fprintf(stderr, "No reply from server on codec switch. "); + fprintf(stderr, "No reply from server on codec switch. "); codec_revert: - fprintf(stderr, "Falling back to upstream codec %s\n", dataenc->name); + fprintf(stderr, "Falling back to upstream codec %s\n", dataenc->name); } static void handshake_switch_downenc(int dns_fd) { - char in[4096]; - int i; - int read; - char *dname; + char in[4096]; + int i; + int read; + char *dname; - dname = "Base32"; - if (downenc == 'S') - dname = "Base64"; - else if (downenc == 'U') - dname = "Base64u"; - else if (downenc == 'V') - dname = "Base128"; - else if (downenc == 'R') - dname = "Raw"; + dname = "Base32"; + if (downenc == 'S') + dname = "Base64"; + else if (downenc == 'U') + dname = "Base64u"; + else if (downenc == 'V') + dname = "Base128"; + else if (downenc == 'R') + dname = "Raw"; - fprintf(stderr, "Switching downstream to codec %s\n", dname); - for (i=0; running && i<5 ;i++) { + fprintf(stderr, "Switching downstream to codec %s\n", dname); + for (i=0; running && i<5 ;i++) { - send_downenc_switch(dns_fd, userid); + send_downenc_switch(dns_fd, userid); - read = handshake_waitdns(dns_fd, in, sizeof(in), 'o', 'O', i+1); + read = handshake_waitdns(dns_fd, in, sizeof(in), 'o', 'O', i+1); - if (read > 0) { - if (strncmp("BADLEN", in, 6) == 0) { - fprintf(stderr, "Server got bad message length. "); - goto codec_revert; - } else if (strncmp("BADIP", in, 5) == 0) { - fprintf(stderr, "Server rejected sender IP address. "); - goto codec_revert; - } else if (strncmp("BADCODEC", in, 8) == 0) { - fprintf(stderr, "Server rejected the selected codec. "); - goto codec_revert; - } - in[read] = 0; /* zero terminate */ - fprintf(stderr, "Server switched downstream to codec %s\n", in); - return; - } + if (read > 0) { + if (strncmp("BADLEN", in, 6) == 0) { + fprintf(stderr, "Server got bad message length. "); + goto codec_revert; + } else if (strncmp("BADIP", in, 5) == 0) { + fprintf(stderr, "Server rejected sender IP address. "); + goto codec_revert; + } else if (strncmp("BADCODEC", in, 8) == 0) { + fprintf(stderr, "Server rejected the selected codec. "); + goto codec_revert; + } + in[read] = 0; /* zero terminate */ + fprintf(stderr, "Server switched downstream to codec %s\n", in); + return; + } - fprintf(stderr, "Retrying codec switch...\n"); - } - if (!running) - return; + fprintf(stderr, "Retrying codec switch...\n"); + } + if (!running) + return; - fprintf(stderr, "No reply from server on codec switch. "); + fprintf(stderr, "No reply from server on codec switch. "); codec_revert: - fprintf(stderr, "Falling back to downstream codec Base32\n"); + fprintf(stderr, "Falling back to downstream codec Base32\n"); } static void handshake_try_lazy(int dns_fd) { - char in[4096]; - int i; - int read; + char in[4096]; + int i; + int read; - fprintf(stderr, "Switching to lazy mode for low-latency\n"); - for (i=0; running && i<5; i++) { + fprintf(stderr, "Switching to lazy mode for low-latency\n"); + for (i=0; running && i<5; i++) { - send_lazy_switch(dns_fd, userid); + send_lazy_switch(dns_fd, userid); - read = handshake_waitdns(dns_fd, in, sizeof(in), 'o', 'O', i+1); + read = handshake_waitdns(dns_fd, in, sizeof(in), 'o', 'O', i+1); - if (read > 0) { - if (strncmp("BADLEN", in, 6) == 0) { - fprintf(stderr, "Server got bad message length. "); - goto codec_revert; - } else if (strncmp("BADIP", in, 5) == 0) { - fprintf(stderr, "Server rejected sender IP address. "); - goto codec_revert; - } else if (strncmp("BADCODEC", in, 8) == 0) { - fprintf(stderr, "Server rejected lazy mode. "); - goto codec_revert; - } else if (strncmp("Lazy", in, 4) == 0) { - fprintf(stderr, "Server switched to lazy mode\n"); - lazymode = 1; - return; - } - } + if (read > 0) { + if (strncmp("BADLEN", in, 6) == 0) { + fprintf(stderr, "Server got bad message length. "); + goto codec_revert; + } else if (strncmp("BADIP", in, 5) == 0) { + fprintf(stderr, "Server rejected sender IP address. "); + goto codec_revert; + } else if (strncmp("BADCODEC", in, 8) == 0) { + fprintf(stderr, "Server rejected lazy mode. "); + goto codec_revert; + } else if (strncmp("Lazy", in, 4) == 0) { + fprintf(stderr, "Server switched to lazy mode\n"); + lazymode = 1; + return; + } + } - fprintf(stderr, "Retrying lazy mode switch...\n"); - } - if (!running) - return; + fprintf(stderr, "Retrying lazy mode switch...\n"); + } + if (!running) + return; - fprintf(stderr, "No reply from server on lazy switch. "); + fprintf(stderr, "No reply from server on lazy switch. "); codec_revert: - fprintf(stderr, "Falling back to legacy mode\n"); - lazymode = 0; - selecttimeout = 1; + fprintf(stderr, "Falling back to legacy mode\n"); + lazymode = 0; + selecttimeout = 1; } static void handshake_lazyoff(int dns_fd) /* Used in the middle of data transfer, timing is different and no error msgs */ { - char in[4096]; - int i; - int read; + char in[4096]; + int i; + int read; - for (i=0; running && i<5; i++) { + for (i=0; running && i<5; i++) { - send_lazy_switch(dns_fd, userid); + send_lazy_switch(dns_fd, userid); - read = handshake_waitdns(dns_fd, in, sizeof(in), 'o', 'O', 1); + read = handshake_waitdns(dns_fd, in, sizeof(in), 'o', 'O', 1); - if (read == 9 && strncmp("Immediate", in, 9) == 0) { - warnx("Server switched back to legacy mode.\n"); - lazymode = 0; - selecttimeout = 1; - return; - } - } - if (!running) - return; + if (read == 9 && strncmp("Immediate", in, 9) == 0) { + warnx("Server switched back to legacy mode.\n"); + lazymode = 0; + selecttimeout = 1; + return; + } + } + if (!running) + return; - warnx("No reply from server on legacy mode switch.\n"); + warnx("No reply from server on legacy mode switch.\n"); } static int fragsize_check(char *in, int read, int proposed_fragsize, int *max_fragsize) /* Returns: 0: keep checking, 1: break loop (either okay or definitely wrong) */ { - int acked_fragsize = ((in[0] & 0xff) << 8) | (in[1] & 0xff); - int okay; - int i; - unsigned int v; + int acked_fragsize = ((in[0] & 0xff) << 8) | (in[1] & 0xff); + int okay; + int i; + unsigned int v; - if (read >= 5 && strncmp("BADIP", in, 5) == 0) { - fprintf(stderr, "got BADIP (Try iodined -c)..\n"); - fflush(stderr); - return 0; /* maybe temporary error */ - } + if (read >= 5 && strncmp("BADIP", in, 5) == 0) { + fprintf(stderr, "got BADIP (Try iodined -c)..\n"); + fflush(stderr); + return 0; /* maybe temporary error */ + } - if (acked_fragsize != proposed_fragsize) { - /* - * got ack for wrong fragsize, maybe late response for - * earlier query, or ack corrupted - */ - return 0; - } + if (acked_fragsize != proposed_fragsize) { + /* + * got ack for wrong fragsize, maybe late response for + * earlier query, or ack corrupted + */ + return 0; + } - if (read != proposed_fragsize) { - /* - * correctly acked fragsize but read too little (or too - * much): this fragsize is definitely not reliable - */ - return 1; - } + if (read != proposed_fragsize) { + /* + * correctly acked fragsize but read too little (or too + * much): this fragsize is definitely not reliable + */ + return 1; + } - /* here: read == proposed_fragsize == acked_fragsize */ + /* here: read == proposed_fragsize == acked_fragsize */ - /* test: */ - /* in[123] = 123; */ + /* test: */ + /* in[123] = 123; */ - if ((in[2] & 0xff) != 107) { - fprintf(stderr, "\n"); - warnx("corruption at byte 2, this won't work. Try -O Base32, or other -T options."); - *max_fragsize = -1; - return 1; - } + if ((in[2] & 0xff) != 107) { + fprintf(stderr, "\n"); + warnx("corruption at byte 2, this won't work. Try -O Base32, or other -T options."); + *max_fragsize = -1; + return 1; + } - /* Check for corruption */ - okay = 1; - v = in[3] & 0xff; + /* Check for corruption */ + okay = 1; + v = in[3] & 0xff; - for (i = 3; i < read; i++, v = (v + 107) & 0xff) - if ((in[i] & 0xff) != v) { - okay = 0; - break; - } + for (i = 3; i < read; i++, v = (v + 107) & 0xff) + if ((in[i] & 0xff) != v) { + okay = 0; + break; + } - if (okay) { - fprintf(stderr, "%d ok.. ", acked_fragsize); - fflush(stderr); - *max_fragsize = acked_fragsize; - return 1; - } else { - if (downenc != ' ' && downenc != 'T') { - fprintf(stderr, "%d corrupted at %d.. (Try -O Base32)\n", acked_fragsize, i); - } else { - fprintf(stderr, "%d corrupted at %d.. ", acked_fragsize, i); - } - fflush(stderr); - return 1; - } + if (okay) { + fprintf(stderr, "%d ok.. ", acked_fragsize); + fflush(stderr); + *max_fragsize = acked_fragsize; + return 1; + } else { + if (downenc != ' ' && downenc != 'T') { + fprintf(stderr, "%d corrupted at %d.. (Try -O Base32)\n", acked_fragsize, i); + } else { + fprintf(stderr, "%d corrupted at %d.. ", acked_fragsize, i); + } + fflush(stderr); + return 1; + } - /* notreached */ - return 1; + /* notreached */ + return 1; } static int handshake_autoprobe_fragsize(int dns_fd) { - char in[4096]; - int i; - int read; - int proposed_fragsize = 768; - int range = 768; - int max_fragsize; + char in[4096]; + int i; + int read; + int proposed_fragsize = 768; + int range = 768; + int max_fragsize; - max_fragsize = 0; - fprintf(stderr, "Autoprobing max downstream fragment size... (skip with -m fragsize)\n"); - while (running && range > 0 && (range >= 8 || max_fragsize < 300)) { - /* stop the slow probing early when we have enough bytes anyway */ - for (i=0; running && i<3 ;i++) { + max_fragsize = 0; + fprintf(stderr, "Autoprobing max downstream fragment size... (skip with -m fragsize)\n"); + while (running && range > 0 && (range >= 8 || max_fragsize < 300)) { + /* stop the slow probing early when we have enough bytes anyway */ + for (i=0; running && i<3 ;i++) { - send_fragsize_probe(dns_fd, proposed_fragsize); + send_fragsize_probe(dns_fd, proposed_fragsize); - read = handshake_waitdns(dns_fd, in, sizeof(in), 'r', 'R', 1); + read = handshake_waitdns(dns_fd, in, sizeof(in), 'r', 'R', 1); - if (read > 0) { - /* We got a reply */ - if (fragsize_check(in, read, proposed_fragsize, &max_fragsize) == 1) - break; - } + if (read > 0) { + /* We got a reply */ + if (fragsize_check(in, read, proposed_fragsize, &max_fragsize) == 1) + break; + } - fprintf(stderr, "."); - fflush(stderr); - } - if (max_fragsize < 0) - break; + fprintf(stderr, "."); + fflush(stderr); + } + if (max_fragsize < 0) + break; - range >>= 1; - if (max_fragsize == proposed_fragsize) { - /* Try bigger */ - proposed_fragsize += range; - } else { - /* Try smaller */ - fprintf(stderr, "%d not ok.. ", proposed_fragsize); - fflush(stderr); - proposed_fragsize -= range; - } - } - if (!running) { - fprintf(stderr, "\n"); - warnx("stopped while autodetecting fragment size (Try setting manually with -m)"); - return 0; - } - if (max_fragsize <= 2) { - /* Tried all the way down to 2 and found no good size. - But we _did_ do all handshake before this, so there must - be some workable connection. */ - fprintf(stderr, "\n"); - warnx("found no accepted fragment size."); - warnx("try setting -M to 200 or lower, or try other -T or -O options."); - return 0; - } - /* data header adds 2 bytes */ - fprintf(stderr, "will use %d-2=%d\n", max_fragsize, max_fragsize - 2); + range >>= 1; + if (max_fragsize == proposed_fragsize) { + /* Try bigger */ + proposed_fragsize += range; + } else { + /* Try smaller */ + fprintf(stderr, "%d not ok.. ", proposed_fragsize); + fflush(stderr); + proposed_fragsize -= range; + } + } + if (!running) { + fprintf(stderr, "\n"); + warnx("stopped while autodetecting fragment size (Try setting manually with -m)"); + return 0; + } + if (max_fragsize <= 2) { + /* Tried all the way down to 2 and found no good size. + But we _did_ do all handshake before this, so there must + be some workable connection. */ + fprintf(stderr, "\n"); + warnx("found no accepted fragment size."); + warnx("try setting -M to 200 or lower, or try other -T or -O options."); + return 0; + } + /* data header adds 2 bytes */ + fprintf(stderr, "will use %d-2=%d\n", max_fragsize, max_fragsize - 2); - /* need 1200 / 16frags = 75 bytes fragsize */ - if (max_fragsize < 82) { - fprintf(stderr, "Note: this probably won't work well.\n"); - fprintf(stderr, "Try setting -M to 200 or lower, or try other DNS types (-T option).\n"); - } else if (max_fragsize < 202 && - (do_qtype == T_NULL || do_qtype == T_PRIVATE || do_qtype == T_TXT || - do_qtype == T_SRV || do_qtype == T_MX)) { - fprintf(stderr, "Note: this isn't very much.\n"); - fprintf(stderr, "Try setting -M to 200 or lower, or try other DNS types (-T option).\n"); - } + /* need 1200 / 16frags = 75 bytes fragsize */ + if (max_fragsize < 82) { + fprintf(stderr, "Note: this probably won't work well.\n"); + fprintf(stderr, "Try setting -M to 200 or lower, or try other DNS types (-T option).\n"); + } else if (max_fragsize < 202 && + (do_qtype == T_NULL || do_qtype == T_PRIVATE || do_qtype == T_TXT || + do_qtype == T_SRV || do_qtype == T_MX)) { + fprintf(stderr, "Note: this isn't very much.\n"); + fprintf(stderr, "Try setting -M to 200 or lower, or try other DNS types (-T option).\n"); + } - return max_fragsize - 2; + return max_fragsize - 2; } static void handshake_set_fragsize(int dns_fd, int fragsize) { - char in[4096]; - int i; - int read; + char in[4096]; + int i; + int read; - fprintf(stderr, "Setting downstream fragment size to max %d...\n", fragsize); - for (i=0; running && i<5 ;i++) { + fprintf(stderr, "Setting downstream fragment size to max %d...\n", fragsize); + for (i=0; running && i<5 ;i++) { - send_set_downstream_fragsize(dns_fd, fragsize); + send_set_downstream_fragsize(dns_fd, fragsize); - read = handshake_waitdns(dns_fd, in, sizeof(in), 'n', 'N', i+1); + read = handshake_waitdns(dns_fd, in, sizeof(in), 'n', 'N', i+1); - if (read > 0) { + if (read > 0) { - if (strncmp("BADFRAG", in, 7) == 0) { - fprintf(stderr, "Server rejected fragsize. Keeping default."); - return; - } else if (strncmp("BADIP", in, 5) == 0) { - fprintf(stderr, "Server rejected sender IP address.\n"); - return; - } + if (strncmp("BADFRAG", in, 7) == 0) { + fprintf(stderr, "Server rejected fragsize. Keeping default."); + return; + } else if (strncmp("BADIP", in, 5) == 0) { + fprintf(stderr, "Server rejected sender IP address.\n"); + return; + } - /* The server returns the accepted fragsize: - accepted_fragsize = ((in[0] & 0xff) << 8) | (in[1] & 0xff) */ - return; - } + /* The server returns the accepted fragsize: + accepted_fragsize = ((in[0] & 0xff) << 8) | (in[1] & 0xff) */ + return; + } - fprintf(stderr, "Retrying set fragsize...\n"); - } - if (!running) - return; + fprintf(stderr, "Retrying set fragsize...\n"); + } + if (!running) + return; - fprintf(stderr, "No reply from server when setting fragsize. Keeping default.\n"); + fprintf(stderr, "No reply from server when setting fragsize. Keeping default.\n"); } int client_handshake(int dns_fd, int raw_mode, int autodetect_frag_size, int fragsize) { - int seed; - int upcodec; - int r; + int seed; + int upcodec; + int r; - dnsc_use_edns0 = 0; + dnsc_use_edns0 = 0; - /* qtype message printed in handshake function */ - if (do_qtype == T_UNSET) { - r = handshake_qtype_autodetect(dns_fd); - if (r) { - return r; - } - } + /* qtype message printed in handshake function */ + if (do_qtype == T_UNSET) { + r = handshake_qtype_autodetect(dns_fd); + if (r) { + return r; + } + } - fprintf(stderr, "Using DNS type %s queries\n", client_get_qtype()); + fprintf(stderr, "Using DNS type %s queries\n", client_get_qtype()); - r = handshake_version(dns_fd, &seed); - if (r) { - return r; - } + r = handshake_version(dns_fd, &seed); + if (r) { + return r; + } - r = handshake_login(dns_fd, seed); - if (r) { - return r; - } + r = handshake_login(dns_fd, seed); + if (r) { + return r; + } - if (raw_mode && handshake_raw_udp(dns_fd, seed)) { - conn = CONN_RAW_UDP; - selecttimeout = 20; - } else { - if (raw_mode == 0) { - fprintf(stderr, "Skipping raw mode\n"); - } + if (raw_mode && handshake_raw_udp(dns_fd, seed)) { + conn = CONN_RAW_UDP; + selecttimeout = 20; + } else { + if (raw_mode == 0) { + fprintf(stderr, "Skipping raw mode\n"); + } - dnsc_use_edns0 = 1; - if (handshake_edns0_check(dns_fd) && running) { - fprintf(stderr, "Using EDNS0 extension\n"); - } else if (!running) { - return -1; - } else { - fprintf(stderr, "DNS relay does not support EDNS0 extension\n"); - dnsc_use_edns0 = 0; - } + dnsc_use_edns0 = 1; + if (handshake_edns0_check(dns_fd) && running) { + fprintf(stderr, "Using EDNS0 extension\n"); + } else if (!running) { + return -1; + } else { + fprintf(stderr, "DNS relay does not support EDNS0 extension\n"); + dnsc_use_edns0 = 0; + } - upcodec = handshake_upenc_autodetect(dns_fd); - if (!running) - return -1; + upcodec = handshake_upenc_autodetect(dns_fd); + if (!running) + return -1; - if (upcodec == 1) { - handshake_switch_codec(dns_fd, 6); - } else if (upcodec == 2) { - handshake_switch_codec(dns_fd, 26); - } else if (upcodec == 3) { - handshake_switch_codec(dns_fd, 7); - } - if (!running) - return -1; + if (upcodec == 1) { + handshake_switch_codec(dns_fd, 6); + } else if (upcodec == 2) { + handshake_switch_codec(dns_fd, 26); + } else if (upcodec == 3) { + handshake_switch_codec(dns_fd, 7); + } + if (!running) + return -1; - if (downenc == ' ') { - downenc = handshake_downenc_autodetect(dns_fd); - } - if (!running) - return -1; + if (downenc == ' ') { + downenc = handshake_downenc_autodetect(dns_fd); + } + if (!running) + return -1; - if (downenc != ' ') { - handshake_switch_downenc(dns_fd); - } - if (!running) - return -1; + if (downenc != ' ') { + handshake_switch_downenc(dns_fd); + } + if (!running) + return -1; - if (lazymode) { - handshake_try_lazy(dns_fd); - } - if (!running) - return -1; + if (lazymode) { + handshake_try_lazy(dns_fd); + } + if (!running) + return -1; - if (autodetect_frag_size) { - fragsize = handshake_autoprobe_fragsize(dns_fd); - if (!fragsize) { - return 1; - } - } + if (autodetect_frag_size) { + fragsize = handshake_autoprobe_fragsize(dns_fd); + if (!fragsize) { + return 1; + } + } - handshake_set_fragsize(dns_fd, fragsize); - if (!running) - return -1; - } + handshake_set_fragsize(dns_fd, fragsize); + if (!running) + return -1; + } - return 0; + return 0; } diff --git a/src/common.c b/src/common.c index a7f4aa7..95f63af 100644 --- a/src/common.c +++ b/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 diff --git a/src/common.h b/src/common.h index 4f51175..afda500 100644 --- a/src/common.h +++ b/src/common.h @@ -82,31 +82,31 @@ extern const unsigned char raw_header[RAW_HDR_LEN]; struct packet { - int len; /* Total packet length */ - int sentlen; /* Length of chunk currently transmitted */ - int offset; /* Current offset */ - char data[64*1024]; /* The data */ - char seqno; /* The packet sequence number */ - char fragment; /* Fragment index */ + int len; /* Total packet length */ + int sentlen; /* Length of chunk currently transmitted */ + int offset; /* Current offset */ + char data[64*1024]; /* The data */ + char seqno; /* The packet sequence number */ + char fragment; /* Fragment index */ }; struct query { - char name[QUERY_NAME_SIZE]; - unsigned short type; - unsigned short rcode; - unsigned short id; - struct in_addr destination; - struct sockaddr_storage from; - int fromlen; - unsigned short id2; - struct sockaddr from2; - int fromlen2; + char name[QUERY_NAME_SIZE]; + unsigned short type; + unsigned short rcode; + unsigned short id; + struct in_addr destination; + struct sockaddr_storage from; + int fromlen; + unsigned short id2; + struct sockaddr from2; + int fromlen2; }; enum connection { - CONN_RAW_UDP, - CONN_DNS_NULL, - CONN_MAX + CONN_RAW_UDP, + CONN_DNS_NULL, + CONN_MAX }; void check_superuser(void (*usage_fn)(void)); diff --git a/src/dns.h b/src/dns.h index b5d83b2..a0ab4b4 100644 --- a/src/dns.h +++ b/src/dns.h @@ -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; diff --git a/src/encoding.c b/src/encoding.c index 4906a6b..acbdfc4 100644 --- a/src/encoding.c +++ b/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; } diff --git a/src/encoding.h b/src/encoding.h index abb82da..ed13366 100644 --- a/src/encoding.h +++ b/src/encoding.h @@ -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); diff --git a/src/fw_query.c b/src/fw_query.c index 873307a..9c02869 100644 --- a/src/fw_query.c +++ b/src/fw_query.c @@ -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; + } + } } diff --git a/src/fw_query.h b/src/fw_query.h index 0aa8778..77ee6dd 100644 --- a/src/fw_query.h +++ b/src/fw_query.h @@ -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(); diff --git a/src/iodine.c b/src/iodine.c index 2599a6d..779abf6 100644 --- a/src/iodine.c +++ b/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; } diff --git a/src/iodined.c b/src/iodined.c index d7bf363..eb31b94 100644 --- a/src/iodined.c +++ b/src/iodined.c @@ -102,75 +102,75 @@ static void handle_full_packet(int, int, int); /* Ask externalip.net webservice to get external ip */ static int get_external_ip(struct in_addr *ip) { - int sock; - struct addrinfo *addr; - int res; - const char *getstr = "GET /ip/ HTTP/1.0\r\n" - /* HTTP 1.0 to avoid chunked transfer coding */ - "Host: api.externalip.net\r\n\r\n"; - char buf[512]; - char *b; - int len; + int sock; + struct addrinfo *addr; + int res; + const char *getstr = "GET /ip/ HTTP/1.0\r\n" + /* HTTP 1.0 to avoid chunked transfer coding */ + "Host: api.externalip.net\r\n\r\n"; + char buf[512]; + char *b; + int len; - res = getaddrinfo("api.externalip.net", "80", NULL, &addr); - if (res < 0) return 1; + res = getaddrinfo("api.externalip.net", "80", NULL, &addr); + if (res < 0) return 1; - sock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); - if (sock < 0) { - freeaddrinfo(addr); - return 2; - } + sock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); + if (sock < 0) { + freeaddrinfo(addr); + return 2; + } - res = connect(sock, addr->ai_addr, addr->ai_addrlen); - freeaddrinfo(addr); - if (res < 0) return 3; + res = connect(sock, addr->ai_addr, addr->ai_addrlen); + freeaddrinfo(addr); + if (res < 0) return 3; - res = write(sock, getstr, strlen(getstr)); - if (res != strlen(getstr)) return 4; + res = write(sock, getstr, strlen(getstr)); + if (res != strlen(getstr)) return 4; - /* Zero buf before receiving, leave at least one zero at the end */ - memset(buf, 0, sizeof(buf)); - res = read(sock, buf, sizeof(buf) - 1); - if (res < 0) return 5; - len = res; + /* Zero buf before receiving, leave at least one zero at the end */ + memset(buf, 0, sizeof(buf)); + res = read(sock, buf, sizeof(buf) - 1); + if (res < 0) return 5; + len = res; - res = close(sock); - if (res < 0) return 6; + res = close(sock); + if (res < 0) return 6; - b = buf; - while (len > 9) { - /* Look for split between headers and data */ - if (strncmp("\r\n\r\n", b, 4) == 0) break; - b++; - len--; - } - if (len < 10) return 7; - b += 4; + b = buf; + while (len > 9) { + /* Look for split between headers and data */ + if (strncmp("\r\n\r\n", b, 4) == 0) break; + b++; + len--; + } + if (len < 10) return 7; + b += 4; - res = inet_aton(b, ip); - return (res == 0); + res = inet_aton(b, ip); + return (res == 0); } static void sigint(int sig) { - running = 0; + running = 0; } #ifdef WINDOWS32 -#define LOG_EMERG 0 -#define LOG_ALERT 1 -#define LOG_CRIT 2 -#define LOG_ERR 3 -#define LOG_WARNING 4 -#define LOG_NOTICE 5 -#define LOG_INFO 6 -#define LOG_DEBUG 7 +#define LOG_EMERG 0 +#define LOG_ALERT 1 +#define LOG_CRIT 2 +#define LOG_ERR 3 +#define LOG_WARNING 4 +#define LOG_NOTICE 5 +#define LOG_INFO 6 +#define LOG_DEBUG 7 static void syslog(int a, const char *str, ...) { - /* TODO: implement (add to event log), move to common.c */ - ; + /* TODO: implement (add to event log), move to common.c */ + ; } #endif @@ -178,65 +178,65 @@ syslog(int a, const char *str, ...) static int check_user_and_ip(int userid, struct query *q) { - struct sockaddr_in *tempin; + struct sockaddr_in *tempin; - /* Note: duplicate in handle_raw_login() except IP-address check */ + /* Note: duplicate in handle_raw_login() except IP-address check */ - if (userid < 0 || userid >= created_users ) { - return 1; - } - if (!users[userid].active || users[userid].disabled) { - return 1; - } - if (users[userid].last_pkt + 60 < time(NULL)) { - return 1; - } + if (userid < 0 || userid >= created_users ) { + return 1; + } + if (!users[userid].active || users[userid].disabled) { + return 1; + } + if (users[userid].last_pkt + 60 < time(NULL)) { + return 1; + } - /* return early if IP checking is disabled */ - if (!check_ip) { - return 0; - } + /* return early if IP checking is disabled */ + if (!check_ip) { + return 0; + } - tempin = (struct sockaddr_in *) &(q->from); - return memcmp(&(users[userid].host), &(tempin->sin_addr), sizeof(struct in_addr)); + tempin = (struct sockaddr_in *) &(q->from); + return memcmp(&(users[userid].host), &(tempin->sin_addr), sizeof(struct in_addr)); } /* This checks that user has passed normal (non-raw) login challenge */ static int check_authenticated_user_and_ip(int userid, struct query *q) { - int res = check_user_and_ip(userid, q); - if (res) - return res; + int res = check_user_and_ip(userid, q); + if (res) + return res; - if (!users[userid].authenticated) - return 1; + if (!users[userid].authenticated) + return 1; - return 0; + return 0; } static void send_raw(int fd, char *buf, int buflen, int user, int cmd, struct query *q) { - char packet[4096]; - int len; + char packet[4096]; + int len; - len = MIN(sizeof(packet) - RAW_HDR_LEN, buflen); + len = MIN(sizeof(packet) - RAW_HDR_LEN, buflen); - memcpy(packet, raw_header, RAW_HDR_LEN); - if (len) { - memcpy(&packet[RAW_HDR_LEN], buf, len); - } + memcpy(packet, raw_header, RAW_HDR_LEN); + if (len) { + memcpy(&packet[RAW_HDR_LEN], buf, len); + } - len += RAW_HDR_LEN; - packet[RAW_HDR_CMD] = cmd | (user & 0x0F); + len += RAW_HDR_LEN; + packet[RAW_HDR_CMD] = cmd | (user & 0x0F); - if (debug >= 2) { - fprintf(stderr, "TX-raw: client %s, cmd %d, %d bytes\n", - format_addr(&q->from, q->fromlen), cmd, len); - } + if (debug >= 2) { + fprintf(stderr, "TX-raw: client %s, cmd %d, %d bytes\n", + format_addr(&q->from, q->fromlen), cmd, len); + } - sendto(fd, packet, len, 0, (struct sockaddr *) &q->from, q->fromlen); + sendto(fd, packet, len, 0, (struct sockaddr *) &q->from, q->fromlen); } @@ -245,14 +245,14 @@ start_new_outpacket(int userid, char *data, int datalen) /* Copies data to .outpacket and resets all counters. data is expected to be compressed already. */ { - datalen = MIN(datalen, sizeof(users[userid].outpacket.data)); - memcpy(users[userid].outpacket.data, data, datalen); - users[userid].outpacket.len = datalen; - users[userid].outpacket.offset = 0; - users[userid].outpacket.sentlen = 0; - users[userid].outpacket.seqno = (users[userid].outpacket.seqno + 1) & 7; - users[userid].outpacket.fragment = 0; - users[userid].outfragresent = 0; + datalen = MIN(datalen, sizeof(users[userid].outpacket.data)); + memcpy(users[userid].outpacket.data, data, datalen); + users[userid].outpacket.len = datalen; + users[userid].outpacket.offset = 0; + users[userid].outpacket.sentlen = 0; + users[userid].outpacket.seqno = (users[userid].outpacket.seqno + 1) & 7; + users[userid].outpacket.fragment = 0; + users[userid].outfragresent = 0; } #ifdef OUTPACKETQ_LEN @@ -262,28 +262,28 @@ save_to_outpacketq(int userid, char *data, int datalen) /* Find space in outpacket-queue and store data (expected compressed already). Returns: 1 = okay, 0 = no space. */ { - int fill; + int fill; - if (users[userid].outpacketq_filled >= OUTPACKETQ_LEN) - /* no space */ - return 0; + if (users[userid].outpacketq_filled >= OUTPACKETQ_LEN) + /* no space */ + return 0; - fill = users[userid].outpacketq_nexttouse + - users[userid].outpacketq_filled; - if (fill >= OUTPACKETQ_LEN) - fill -= OUTPACKETQ_LEN; + fill = users[userid].outpacketq_nexttouse + + users[userid].outpacketq_filled; + if (fill >= OUTPACKETQ_LEN) + fill -= OUTPACKETQ_LEN; - datalen = MIN(datalen, sizeof(users[userid].outpacketq[fill].data)); - memcpy(users[userid].outpacketq[fill].data, data, datalen); - users[userid].outpacketq[fill].len = datalen; + datalen = MIN(datalen, sizeof(users[userid].outpacketq[fill].data)); + memcpy(users[userid].outpacketq[fill].data, data, datalen); + users[userid].outpacketq[fill].len = datalen; - users[userid].outpacketq_filled++; + users[userid].outpacketq_filled++; - if (debug >= 3) - fprintf(stderr, " Qstore, now %d\n", - users[userid].outpacketq_filled); + if (debug >= 3) + fprintf(stderr, " Qstore, now %d\n", + users[userid].outpacketq_filled); - return 1; + return 1; } static int @@ -291,28 +291,28 @@ get_from_outpacketq(int userid) /* Starts new outpacket from queue, if any. Returns: 1 = okay, 0 = no packets were waiting. */ { - int use; + int use; - if (users[userid].outpacketq_filled <= 0) - /* no packets */ - return 0; + if (users[userid].outpacketq_filled <= 0) + /* no packets */ + return 0; - use = users[userid].outpacketq_nexttouse; + use = users[userid].outpacketq_nexttouse; - start_new_outpacket(userid, users[userid].outpacketq[use].data, - users[userid].outpacketq[use].len); + start_new_outpacket(userid, users[userid].outpacketq[use].data, + users[userid].outpacketq[use].len); - use++; - if (use >= OUTPACKETQ_LEN) - use = 0; - users[userid].outpacketq_nexttouse = use; - users[userid].outpacketq_filled--; + use++; + if (use >= OUTPACKETQ_LEN) + use = 0; + users[userid].outpacketq_nexttouse = use; + users[userid].outpacketq_filled--; - if (debug >= 3) - fprintf(stderr, " Qget, now %d\n", - users[userid].outpacketq_filled); + if (debug >= 3) + fprintf(stderr, " Qget, now %d\n", + users[userid].outpacketq_filled); - return 1; + return 1; } #endif /* OUTPACKETQ_LEN */ @@ -338,20 +338,20 @@ static void save_to_dnscache(int userid, struct query *q, char *answer, int answerlen) /* Store answer in our little DNS cache. */ { - int fill; + int fill; - if (answerlen > sizeof(users[userid].dnscache_answer[fill])) - return; /* can't store this */ + if (answerlen > sizeof(users[userid].dnscache_answer[fill])) + return; /* can't store this */ - fill = users[userid].dnscache_lastfilled + 1; - if (fill >= DNSCACHE_LEN) - fill = 0; + fill = users[userid].dnscache_lastfilled + 1; + if (fill >= DNSCACHE_LEN) + fill = 0; - memcpy(&(users[userid].dnscache_q[fill]), q, sizeof(struct query)); - memcpy(users[userid].dnscache_answer[fill], answer, answerlen); - users[userid].dnscache_answerlen[fill] = answerlen; + memcpy(&(users[userid].dnscache_q[fill]), q, sizeof(struct query)); + memcpy(users[userid].dnscache_answer[fill], answer, answerlen); + users[userid].dnscache_answerlen[fill] = answerlen; - users[userid].dnscache_lastfilled = fill; + users[userid].dnscache_lastfilled = fill; } static int @@ -360,164 +360,164 @@ answer_from_dnscache(int dns_fd, int userid, struct query *q) Returns: 1 = answer sent, drop this query, 0 = no answer sent, this is a new query. */ { - int i; - int use; + int i; + int use; - for (i = 0; i < DNSCACHE_LEN ; i++) { - /* Try cache most-recent-first */ - use = users[userid].dnscache_lastfilled - i; - if (use < 0) - use += DNSCACHE_LEN; + for (i = 0; i < DNSCACHE_LEN ; i++) { + /* Try cache most-recent-first */ + use = users[userid].dnscache_lastfilled - i; + if (use < 0) + use += DNSCACHE_LEN; - if (users[userid].dnscache_q[use].id == 0) - continue; - if (users[userid].dnscache_answerlen[use] <= 0) - continue; + if (users[userid].dnscache_q[use].id == 0) + continue; + if (users[userid].dnscache_answerlen[use] <= 0) + continue; - if (users[userid].dnscache_q[use].type != q->type || - strcmp(users[userid].dnscache_q[use].name, q->name)) - continue; + if (users[userid].dnscache_q[use].type != q->type || + strcmp(users[userid].dnscache_q[use].name, q->name)) + continue; - /* okay, match */ - if (debug >= 1) - fprintf(stderr, "OUT user %d %s from dnscache\n", userid, q->name); + /* okay, match */ + if (debug >= 1) + fprintf(stderr, "OUT user %d %s from dnscache\n", userid, q->name); - write_dns(dns_fd, q, users[userid].dnscache_answer[use], - users[userid].dnscache_answerlen[use], - users[userid].downenc); + write_dns(dns_fd, q, users[userid].dnscache_answer[use], + users[userid].dnscache_answerlen[use], + users[userid].downenc); - q->id = 0; /* this query was used */ - return 1; - } + q->id = 0; /* this query was used */ + return 1; + } - /* here only when no match found */ - return 0; + /* here only when no match found */ + return 0; } #endif /* DNSCACHE_LEN */ static inline void save_to_qmem(unsigned char *qmem_cmc, unsigned short *qmem_type, int qmem_len, - int *qmem_lastfilled, unsigned char *cmc_to_add, - unsigned short type_to_add) + int *qmem_lastfilled, unsigned char *cmc_to_add, + unsigned short type_to_add) /* Remember query to check for duplicates */ { - int fill; + int fill; - fill = *qmem_lastfilled + 1; - if (fill >= qmem_len) - fill = 0; + fill = *qmem_lastfilled + 1; + if (fill >= qmem_len) + fill = 0; - memcpy(qmem_cmc + fill * 4, cmc_to_add, 4); - qmem_type[fill] = type_to_add; - *qmem_lastfilled = fill; + memcpy(qmem_cmc + fill * 4, cmc_to_add, 4); + qmem_type[fill] = type_to_add; + *qmem_lastfilled = fill; } static inline void save_to_qmem_pingordata(int userid, struct query *q) { - /* Our CMC is a bit more than the "official" CMC; we store 4 bytes - just because we can, and because it may prevent some false matches. - For ping, we save the 4 decoded bytes: userid + seq/frag + CMC. - For data, we save the 4 _un_decoded chars in lowercase: seq/frag's - + 1 char CMC; that last char is non-Base32. - */ + /* Our CMC is a bit more than the "official" CMC; we store 4 bytes + just because we can, and because it may prevent some false matches. + For ping, we save the 4 decoded bytes: userid + seq/frag + CMC. + For data, we save the 4 _un_decoded chars in lowercase: seq/frag's + + 1 char CMC; that last char is non-Base32. + */ - char cmc[8]; - int i; + char cmc[8]; + int i; - if (q->name[0] == 'P' || q->name[0] == 'p') { - /* Ping packet */ + if (q->name[0] == 'P' || q->name[0] == 'p') { + /* Ping packet */ - size_t cmcsize = sizeof(cmc); - char *cp = strchr(q->name, '.'); + size_t cmcsize = sizeof(cmc); + char *cp = strchr(q->name, '.'); - if (cp == NULL) - return; /* illegal hostname; shouldn't happen */ + if (cp == NULL) + return; /* illegal hostname; shouldn't happen */ - /* We already unpacked in handle_null_request(), but that's - lost now... Note: b32 directly, we want no undotify here! */ - i = b32->decode(cmc, &cmcsize, q->name + 1, (cp - q->name) - 1); + /* We already unpacked in handle_null_request(), but that's + lost now... Note: b32 directly, we want no undotify here! */ + i = b32->decode(cmc, &cmcsize, q->name + 1, (cp - q->name) - 1); - if (i < 4) - return; /* illegal ping; shouldn't happen */ + if (i < 4) + return; /* illegal ping; shouldn't happen */ - save_to_qmem(users[userid].qmemping_cmc, - users[userid].qmemping_type, QMEMPING_LEN, - &users[userid].qmemping_lastfilled, - (void *) cmc, q->type); - } else { - /* Data packet, hopefully not illegal */ - if (strlen(q->name) < 5) - return; + save_to_qmem(users[userid].qmemping_cmc, + users[userid].qmemping_type, QMEMPING_LEN, + &users[userid].qmemping_lastfilled, + (void *) cmc, q->type); + } else { + /* Data packet, hopefully not illegal */ + if (strlen(q->name) < 5) + return; - /* We store CMC in lowercase; if routing via multiple parallel - DNS servers, one may do case-switch and another may not, - and we still want to detect duplicates. - Data-header is always base32, so case-swap won't hurt. - */ - for (i = 0; i < 4; i++) - if (q->name[i+1] >= 'A' && q->name[i+1] <= 'Z') - cmc[i] = q->name[i+1] + ('a' - 'A'); - else - cmc[i] = q->name[i+1]; + /* We store CMC in lowercase; if routing via multiple parallel + DNS servers, one may do case-switch and another may not, + and we still want to detect duplicates. + Data-header is always base32, so case-swap won't hurt. + */ + for (i = 0; i < 4; i++) + if (q->name[i+1] >= 'A' && q->name[i+1] <= 'Z') + cmc[i] = q->name[i+1] + ('a' - 'A'); + else + cmc[i] = q->name[i+1]; - save_to_qmem(users[userid].qmemdata_cmc, - users[userid].qmemdata_type, QMEMDATA_LEN, - &users[userid].qmemdata_lastfilled, - (void *) cmc, q->type); - } + save_to_qmem(users[userid].qmemdata_cmc, + users[userid].qmemdata_type, QMEMDATA_LEN, + &users[userid].qmemdata_lastfilled, + (void *) cmc, q->type); + } } static int answer_from_qmem(int dns_fd, struct query *q, unsigned char *qmem_cmc, - unsigned short *qmem_type, int qmem_len, - unsigned char *cmc_to_check) + unsigned short *qmem_type, int qmem_len, + unsigned char *cmc_to_check) /* Checks query memory and sends an (illegal) answer if this is a duplicate. Returns: 1 = answer sent, drop this query, 0 = no answer sent, this is not a duplicate. */ { - int i; + int i; - for (i = 0; i < qmem_len ; i++) { + for (i = 0; i < qmem_len ; i++) { - if (qmem_type[i] == T_UNSET) - continue; - if (qmem_type[i] != q->type) - continue; - if (memcmp(qmem_cmc + i * 4, cmc_to_check, 4)) - continue; + if (qmem_type[i] == T_UNSET) + continue; + if (qmem_type[i] != q->type) + continue; + if (memcmp(qmem_cmc + i * 4, cmc_to_check, 4)) + continue; - /* okay, match */ - if (debug >= 1) - fprintf(stderr, "OUT from qmem for %s == duplicate, sending illegal reply\n", q->name); + /* okay, match */ + if (debug >= 1) + fprintf(stderr, "OUT from qmem for %s == duplicate, sending illegal reply\n", q->name); - write_dns(dns_fd, q, "x", 1, 'T'); + write_dns(dns_fd, q, "x", 1, 'T'); - q->id = 0; /* this query was used */ - return 1; - } + q->id = 0; /* this query was used */ + return 1; + } - /* here only when no match found */ - return 0; + /* here only when no match found */ + return 0; } static inline int answer_from_qmem_data(int dns_fd, int userid, struct query *q) /* Quick helper function to keep handle_null_request() clean */ { - char cmc[4]; - int i; + char cmc[4]; + int i; - for (i = 0; i < 4; i++) - if (q->name[i+1] >= 'A' && q->name[i+1] <= 'Z') - cmc[i] = q->name[i+1] + ('a' - 'A'); - else - cmc[i] = q->name[i+1]; + for (i = 0; i < 4; i++) + if (q->name[i+1] >= 'A' && q->name[i+1] <= 'Z') + cmc[i] = q->name[i+1] + ('a' - 'A'); + else + cmc[i] = q->name[i+1]; - return answer_from_qmem(dns_fd, q, users[userid].qmemdata_cmc, - users[userid].qmemdata_type, QMEMDATA_LEN, - (void *) cmc); + return answer_from_qmem(dns_fd, q, users[userid].qmemdata_cmc, + users[userid].qmemdata_type, QMEMDATA_LEN, + (void *) cmc); } static int @@ -532,166 +532,166 @@ send_chunk_or_dataless(int dns_fd, int userid, struct query *q) 0 = don't call us again for now. */ { - char pkt[4096]; - int datalen = 0; - int last = 0; + char pkt[4096]; + int datalen = 0; + int last = 0; - /* If re-sent too many times, drop entire packet */ - if (users[userid].outpacket.len > 0 && - users[userid].outfragresent > 5) { - users[userid].outpacket.len = 0; - users[userid].outpacket.offset = 0; - users[userid].outpacket.sentlen = 0; - users[userid].outfragresent = 0; + /* If re-sent too many times, drop entire packet */ + if (users[userid].outpacket.len > 0 && + users[userid].outfragresent > 5) { + users[userid].outpacket.len = 0; + users[userid].outpacket.offset = 0; + users[userid].outpacket.sentlen = 0; + users[userid].outfragresent = 0; #ifdef OUTPACKETQ_LEN - /* Maybe more in queue, use immediately */ - get_from_outpacketq(userid); + /* Maybe more in queue, use immediately */ + get_from_outpacketq(userid); #endif - } + } - if (users[userid].outpacket.len > 0) { - datalen = MIN(users[userid].fragsize, users[userid].outpacket.len - users[userid].outpacket.offset); - datalen = MIN(datalen, sizeof(pkt)-2); + if (users[userid].outpacket.len > 0) { + datalen = MIN(users[userid].fragsize, users[userid].outpacket.len - users[userid].outpacket.offset); + datalen = MIN(datalen, sizeof(pkt)-2); - memcpy(&pkt[2], users[userid].outpacket.data + users[userid].outpacket.offset, datalen); - users[userid].outpacket.sentlen = datalen; - last = (users[userid].outpacket.len == users[userid].outpacket.offset + datalen); + memcpy(&pkt[2], users[userid].outpacket.data + users[userid].outpacket.offset, datalen); + users[userid].outpacket.sentlen = datalen; + last = (users[userid].outpacket.len == users[userid].outpacket.offset + datalen); - users[userid].outfragresent++; - } + users[userid].outfragresent++; + } - /* Build downstream data header (see doc/proto_xxxxxxxx.txt) */ + /* Build downstream data header (see doc/proto_xxxxxxxx.txt) */ - /* First byte is 1 bit compression flag, 3 bits upstream seqno, 4 bits upstream fragment */ - pkt[0] = (1<<7) | ((users[userid].inpacket.seqno & 7) << 4) | - (users[userid].inpacket.fragment & 15); - /* Second byte is 3 bits downstream seqno, 4 bits downstream fragment, 1 bit last flag */ - pkt[1] = ((users[userid].outpacket.seqno & 7) << 5) | - ((users[userid].outpacket.fragment & 15) << 1) | (last & 1); + /* First byte is 1 bit compression flag, 3 bits upstream seqno, 4 bits upstream fragment */ + pkt[0] = (1<<7) | ((users[userid].inpacket.seqno & 7) << 4) | + (users[userid].inpacket.fragment & 15); + /* Second byte is 3 bits downstream seqno, 4 bits downstream fragment, 1 bit last flag */ + pkt[1] = ((users[userid].outpacket.seqno & 7) << 5) | + ((users[userid].outpacket.fragment & 15) << 1) | (last & 1); - if (debug >= 1) { - fprintf(stderr, "OUT pkt seq# %d, frag %d (last=%d), offset %d, fragsize %d, total %d, to user %d\n", - users[userid].outpacket.seqno & 7, users[userid].outpacket.fragment & 15, - last, users[userid].outpacket.offset, datalen, users[userid].outpacket.len, userid); - } - write_dns(dns_fd, q, pkt, datalen + 2, users[userid].downenc); + if (debug >= 1) { + fprintf(stderr, "OUT pkt seq# %d, frag %d (last=%d), offset %d, fragsize %d, total %d, to user %d\n", + users[userid].outpacket.seqno & 7, users[userid].outpacket.fragment & 15, + last, users[userid].outpacket.offset, datalen, users[userid].outpacket.len, userid); + } + write_dns(dns_fd, q, pkt, datalen + 2, users[userid].downenc); - if (q->id2 != 0) { - q->id = q->id2; - q->fromlen = q->fromlen2; - memcpy(&(q->from), &(q->from2), q->fromlen2); - if (debug >= 1) - fprintf(stderr, "OUT again to last duplicate\n"); - write_dns(dns_fd, q, pkt, datalen + 2, users[userid].downenc); - } + if (q->id2 != 0) { + q->id = q->id2; + q->fromlen = q->fromlen2; + memcpy(&(q->from), &(q->from2), q->fromlen2); + if (debug >= 1) + fprintf(stderr, "OUT again to last duplicate\n"); + write_dns(dns_fd, q, pkt, datalen + 2, users[userid].downenc); + } - save_to_qmem_pingordata(userid, q); + save_to_qmem_pingordata(userid, q); #ifdef DNSCACHE_LEN - save_to_dnscache(userid, q, pkt, datalen + 2); + save_to_dnscache(userid, q, pkt, datalen + 2); #endif - q->id = 0; /* this query is used */ + q->id = 0; /* this query is used */ - if (datalen > 0 && datalen == users[userid].outpacket.len) { - /* Whole packet was sent in one chunk, dont wait for ack */ - users[userid].outpacket.len = 0; - users[userid].outpacket.offset = 0; - users[userid].outpacket.sentlen = 0; - users[userid].outfragresent = 0; + if (datalen > 0 && datalen == users[userid].outpacket.len) { + /* Whole packet was sent in one chunk, dont wait for ack */ + users[userid].outpacket.len = 0; + users[userid].outpacket.offset = 0; + users[userid].outpacket.sentlen = 0; + users[userid].outfragresent = 0; #ifdef OUTPACKETQ_LEN - /* Maybe more in queue, prepare for next time */ - if (get_from_outpacketq(userid) == 1) { - if (debug >= 3) - fprintf(stderr, " Chunk & fromqueue: callagain\n"); - return 1; /* call us again */ - } + /* Maybe more in queue, prepare for next time */ + if (get_from_outpacketq(userid) == 1) { + if (debug >= 3) + fprintf(stderr, " Chunk & fromqueue: callagain\n"); + return 1; /* call us again */ + } #endif - } + } - return 0; /* don't call us again */ + return 0; /* don't call us again */ } static int tunnel_tun(int tun_fd, int dns_fd) { - unsigned long outlen; - struct ip *header; - char out[64*1024]; - char in[64*1024]; - int userid; - int read; + unsigned long outlen; + struct ip *header; + char out[64*1024]; + char in[64*1024]; + int userid; + int read; - if ((read = read_tun(tun_fd, in, sizeof(in))) <= 0) - return 0; + if ((read = read_tun(tun_fd, in, sizeof(in))) <= 0) + return 0; - /* find target ip in packet, in is padded with 4 bytes TUN header */ - header = (struct ip*) (in + 4); - userid = find_user_by_ip(header->ip_dst.s_addr); - if (userid < 0) - return 0; + /* find target ip in packet, in is padded with 4 bytes TUN header */ + header = (struct ip*) (in + 4); + userid = find_user_by_ip(header->ip_dst.s_addr); + if (userid < 0) + return 0; - outlen = sizeof(out); - compress2((uint8_t*)out, &outlen, (uint8_t*)in, read, 9); + outlen = sizeof(out); + compress2((uint8_t*)out, &outlen, (uint8_t*)in, read, 9); - if (users[userid].conn == CONN_DNS_NULL) { + if (users[userid].conn == CONN_DNS_NULL) { #ifdef OUTPACKETQ_LEN - /* If a packet is being sent, try storing the new one in the queue. - If the queue is full, drop the packet. TCP will hopefully notice - and reduce the packet rate. */ - if (users[userid].outpacket.len > 0) { - save_to_outpacketq(userid, out, outlen); - return 0; - } + /* If a packet is being sent, try storing the new one in the queue. + If the queue is full, drop the packet. TCP will hopefully notice + and reduce the packet rate. */ + if (users[userid].outpacket.len > 0) { + save_to_outpacketq(userid, out, outlen); + return 0; + } #endif - start_new_outpacket(userid, out, outlen); + start_new_outpacket(userid, out, outlen); - /* Start sending immediately if query is waiting */ - if (users[userid].q_sendrealsoon.id != 0) - send_chunk_or_dataless(dns_fd, userid, &users[userid].q_sendrealsoon); - else if (users[userid].q.id != 0) - send_chunk_or_dataless(dns_fd, userid, &users[userid].q); + /* Start sending immediately if query is waiting */ + if (users[userid].q_sendrealsoon.id != 0) + send_chunk_or_dataless(dns_fd, userid, &users[userid].q_sendrealsoon); + else if (users[userid].q.id != 0) + send_chunk_or_dataless(dns_fd, userid, &users[userid].q); - return outlen; - } else { /* CONN_RAW_UDP */ - send_raw(dns_fd, out, outlen, userid, RAW_HDR_CMD_DATA, &users[userid].q); - return outlen; - } + return outlen; + } else { /* CONN_RAW_UDP */ + send_raw(dns_fd, out, outlen, userid, RAW_HDR_CMD_DATA, &users[userid].q); + return outlen; + } } typedef enum { - VERSION_ACK, - VERSION_NACK, - VERSION_FULL + VERSION_ACK, + VERSION_NACK, + VERSION_FULL } version_ack_t; static void send_version_response(int fd, version_ack_t ack, uint32_t payload, int userid, struct query *q) { - char out[9]; + char out[9]; - switch (ack) { - case VERSION_ACK: - strncpy(out, "VACK", sizeof(out)); - break; - case VERSION_NACK: - strncpy(out, "VNAK", sizeof(out)); - break; - case VERSION_FULL: - strncpy(out, "VFUL", sizeof(out)); - break; - } + switch (ack) { + case VERSION_ACK: + strncpy(out, "VACK", sizeof(out)); + break; + case VERSION_NACK: + strncpy(out, "VNAK", sizeof(out)); + break; + case VERSION_FULL: + strncpy(out, "VFUL", sizeof(out)); + break; + } - out[4] = ((payload >> 24) & 0xff); - out[5] = ((payload >> 16) & 0xff); - out[6] = ((payload >> 8) & 0xff); - out[7] = ((payload) & 0xff); - out[8] = userid & 0xff; + out[4] = ((payload >> 24) & 0xff); + out[5] = ((payload >> 16) & 0xff); + out[6] = ((payload >> 8) & 0xff); + out[7] = ((payload) & 0xff); + out[8] = userid & 0xff; - write_dns(fd, q, out, sizeof(out), users[userid].downenc); + write_dns(fd, q, out, sizeof(out), users[userid].downenc); } static void @@ -701,1911 +701,1911 @@ process_downstream_ack(int userid, int down_seq, int down_frag) or .len is set to zero when all is done. */ { - if (users[userid].outpacket.len <= 0) - /* No packet to apply acks to */ - return; + if (users[userid].outpacket.len <= 0) + /* No packet to apply acks to */ + return; - if (users[userid].outpacket.seqno != down_seq || - users[userid].outpacket.fragment != down_frag) - /* Not the ack we're waiting for; probably duplicate of old - ack, happens a lot with ping packets */ - return; + if (users[userid].outpacket.seqno != down_seq || + users[userid].outpacket.fragment != down_frag) + /* Not the ack we're waiting for; probably duplicate of old + ack, happens a lot with ping packets */ + return; - /* Received proper ack */ - users[userid].outpacket.offset += users[userid].outpacket.sentlen; - users[userid].outpacket.sentlen = 0; - users[userid].outpacket.fragment++; - users[userid].outfragresent = 0; + /* Received proper ack */ + users[userid].outpacket.offset += users[userid].outpacket.sentlen; + users[userid].outpacket.sentlen = 0; + users[userid].outpacket.fragment++; + users[userid].outfragresent = 0; - /* Is packet done? */ - if (users[userid].outpacket.offset >= users[userid].outpacket.len) { - users[userid].outpacket.len = 0; - users[userid].outpacket.offset = 0; - users[userid].outpacket.fragment--; /* unneeded ++ above */ - /* ^keep last seqno/frag, are always returned on pings */ - /* users[userid].outfragresent = 0; already above */ + /* Is packet done? */ + if (users[userid].outpacket.offset >= users[userid].outpacket.len) { + users[userid].outpacket.len = 0; + users[userid].outpacket.offset = 0; + users[userid].outpacket.fragment--; /* unneeded ++ above */ + /* ^keep last seqno/frag, are always returned on pings */ + /* users[userid].outfragresent = 0; already above */ #ifdef OUTPACKETQ_LEN - /* Possibly get new packet from queue */ - get_from_outpacketq(userid); + /* Possibly get new packet from queue */ + get_from_outpacketq(userid); #endif - } + } } static void handle_null_request(int tun_fd, int dns_fd, struct query *q, int domain_len) { - struct in_addr tempip; - char in[512]; - char logindata[16]; - char out[64*1024]; - char unpacked[64*1024]; - char *tmp[2]; - int userid; - int read; + struct in_addr tempip; + char in[512]; + char logindata[16]; + char out[64*1024]; + char unpacked[64*1024]; + char *tmp[2]; + int userid; + int read; - userid = -1; + userid = -1; - /* Everything here needs at least two chars in the name */ - if (domain_len < 2) - return; + /* Everything here needs at least two chars in the name */ + if (domain_len < 2) + return; - memcpy(in, q->name, MIN(domain_len, sizeof(in))); + memcpy(in, q->name, MIN(domain_len, sizeof(in))); - if(in[0] == 'V' || in[0] == 'v') { - int version = 0; + if(in[0] == 'V' || in[0] == 'v') { + int version = 0; - read = unpack_data(unpacked, sizeof(unpacked), &(in[1]), domain_len - 1, b32); - /* Version greeting, compare and send ack/nak */ - if (read > 4) { - /* Received V + 32bits version */ - version = (((unpacked[0] & 0xff) << 24) | - ((unpacked[1] & 0xff) << 16) | - ((unpacked[2] & 0xff) << 8) | - ((unpacked[3] & 0xff))); - } + read = unpack_data(unpacked, sizeof(unpacked), &(in[1]), domain_len - 1, b32); + /* Version greeting, compare and send ack/nak */ + if (read > 4) { + /* Received V + 32bits version */ + version = (((unpacked[0] & 0xff) << 24) | + ((unpacked[1] & 0xff) << 16) | + ((unpacked[2] & 0xff) << 8) | + ((unpacked[3] & 0xff))); + } - if (version == PROTOCOL_VERSION) { - userid = find_available_user(); - if (userid >= 0) { - int i; - struct sockaddr_in *tempin; + if (version == PROTOCOL_VERSION) { + userid = find_available_user(); + if (userid >= 0) { + int i; + struct sockaddr_in *tempin; - users[userid].seed = rand(); - /* Store remote IP number */ - tempin = (struct sockaddr_in *) &(q->from); - memcpy(&(users[userid].host), &(tempin->sin_addr), sizeof(struct in_addr)); + users[userid].seed = rand(); + /* Store remote IP number */ + tempin = (struct sockaddr_in *) &(q->from); + memcpy(&(users[userid].host), &(tempin->sin_addr), sizeof(struct in_addr)); - memcpy(&(users[userid].q), q, sizeof(struct query)); - users[userid].encoder = get_base32_encoder(); - users[userid].downenc = 'T'; - send_version_response(dns_fd, VERSION_ACK, users[userid].seed, userid, q); - syslog(LOG_INFO, "accepted version for user #%d from %s", - userid, format_addr(&q->from, q->fromlen)); - users[userid].q.id = 0; - users[userid].q.id2 = 0; - users[userid].q_sendrealsoon.id = 0; - users[userid].q_sendrealsoon.id2 = 0; - users[userid].q_sendrealsoon_new = 0; - users[userid].outpacket.len = 0; - users[userid].outpacket.offset = 0; - users[userid].outpacket.sentlen = 0; - users[userid].outpacket.seqno = 0; - users[userid].outpacket.fragment = 0; - users[userid].outfragresent = 0; - users[userid].inpacket.len = 0; - users[userid].inpacket.offset = 0; - users[userid].inpacket.seqno = 0; - users[userid].inpacket.fragment = 0; - users[userid].fragsize = 100; /* very safe */ - users[userid].conn = CONN_DNS_NULL; - users[userid].lazy = 0; + memcpy(&(users[userid].q), q, sizeof(struct query)); + users[userid].encoder = get_base32_encoder(); + users[userid].downenc = 'T'; + send_version_response(dns_fd, VERSION_ACK, users[userid].seed, userid, q); + syslog(LOG_INFO, "accepted version for user #%d from %s", + userid, format_addr(&q->from, q->fromlen)); + users[userid].q.id = 0; + users[userid].q.id2 = 0; + users[userid].q_sendrealsoon.id = 0; + users[userid].q_sendrealsoon.id2 = 0; + users[userid].q_sendrealsoon_new = 0; + users[userid].outpacket.len = 0; + users[userid].outpacket.offset = 0; + users[userid].outpacket.sentlen = 0; + users[userid].outpacket.seqno = 0; + users[userid].outpacket.fragment = 0; + users[userid].outfragresent = 0; + users[userid].inpacket.len = 0; + users[userid].inpacket.offset = 0; + users[userid].inpacket.seqno = 0; + users[userid].inpacket.fragment = 0; + users[userid].fragsize = 100; /* very safe */ + users[userid].conn = CONN_DNS_NULL; + users[userid].lazy = 0; #ifdef OUTPACKETQ_LEN - users[userid].outpacketq_nexttouse = 0; - users[userid].outpacketq_filled = 0; + users[userid].outpacketq_nexttouse = 0; + users[userid].outpacketq_filled = 0; #endif #ifdef DNSCACHE_LEN - { - for (i = 0; i < DNSCACHE_LEN; i++) { - users[userid].dnscache_q[i].id = 0; - users[userid].dnscache_answerlen[i] = 0; - } - } - users[userid].dnscache_lastfilled = 0; + { + for (i = 0; i < DNSCACHE_LEN; i++) { + users[userid].dnscache_q[i].id = 0; + users[userid].dnscache_answerlen[i] = 0; + } + } + users[userid].dnscache_lastfilled = 0; #endif - for (i = 0; i < QMEMPING_LEN; i++) - users[userid].qmemping_type[i] = T_UNSET; - users[userid].qmemping_lastfilled = 0; - for (i = 0; i < QMEMDATA_LEN; i++) - users[userid].qmemdata_type[i] = T_UNSET; - users[userid].qmemdata_lastfilled = 0; - } else { - /* No space for another user */ - send_version_response(dns_fd, VERSION_FULL, created_users, 0, q); - syslog(LOG_INFO, "dropped user from %s, server full", - format_addr(&q->from, q->fromlen)); - } - } else { - send_version_response(dns_fd, VERSION_NACK, PROTOCOL_VERSION, 0, q); - syslog(LOG_INFO, "dropped user from %s, sent bad version %08X", - format_addr(&q->from, q->fromlen), version); - } - return; - } else if(in[0] == 'L' || in[0] == 'l') { - read = unpack_data(unpacked, sizeof(unpacked), &(in[1]), domain_len - 1, b32); - if (read < 17) { - write_dns(dns_fd, q, "BADLEN", 6, 'T'); - return; - } + for (i = 0; i < QMEMPING_LEN; i++) + users[userid].qmemping_type[i] = T_UNSET; + users[userid].qmemping_lastfilled = 0; + for (i = 0; i < QMEMDATA_LEN; i++) + users[userid].qmemdata_type[i] = T_UNSET; + users[userid].qmemdata_lastfilled = 0; + } else { + /* No space for another user */ + send_version_response(dns_fd, VERSION_FULL, created_users, 0, q); + syslog(LOG_INFO, "dropped user from %s, server full", + format_addr(&q->from, q->fromlen)); + } + } else { + send_version_response(dns_fd, VERSION_NACK, PROTOCOL_VERSION, 0, q); + syslog(LOG_INFO, "dropped user from %s, sent bad version %08X", + format_addr(&q->from, q->fromlen), version); + } + return; + } else if(in[0] == 'L' || in[0] == 'l') { + read = unpack_data(unpacked, sizeof(unpacked), &(in[1]), domain_len - 1, b32); + if (read < 17) { + write_dns(dns_fd, q, "BADLEN", 6, 'T'); + return; + } - /* Login phase, handle auth */ - userid = unpacked[0]; + /* Login phase, handle auth */ + userid = unpacked[0]; - if (check_user_and_ip(userid, q) != 0) { - write_dns(dns_fd, q, "BADIP", 5, 'T'); - syslog(LOG_WARNING, "dropped login request from user #%d from unexpected source %s", - userid, format_addr(&q->from, q->fromlen)); - return; - } else { - users[userid].last_pkt = time(NULL); - login_calculate(logindata, 16, password, users[userid].seed); + if (check_user_and_ip(userid, q) != 0) { + write_dns(dns_fd, q, "BADIP", 5, 'T'); + syslog(LOG_WARNING, "dropped login request from user #%d from unexpected source %s", + userid, format_addr(&q->from, q->fromlen)); + return; + } else { + users[userid].last_pkt = time(NULL); + login_calculate(logindata, 16, password, users[userid].seed); - if (read >= 18 && (memcmp(logindata, unpacked+1, 16) == 0)) { - /* Store login ok */ - users[userid].authenticated = 1; + if (read >= 18 && (memcmp(logindata, unpacked+1, 16) == 0)) { + /* Store login ok */ + users[userid].authenticated = 1; - /* Send ip/mtu/netmask info */ - tempip.s_addr = my_ip; - tmp[0] = strdup(inet_ntoa(tempip)); - tempip.s_addr = users[userid].tun_ip; - tmp[1] = strdup(inet_ntoa(tempip)); + /* Send ip/mtu/netmask info */ + tempip.s_addr = my_ip; + tmp[0] = strdup(inet_ntoa(tempip)); + tempip.s_addr = users[userid].tun_ip; + tmp[1] = strdup(inet_ntoa(tempip)); - read = snprintf(out, sizeof(out), "%s-%s-%d-%d", - tmp[0], tmp[1], my_mtu, netmask); + read = snprintf(out, sizeof(out), "%s-%s-%d-%d", + tmp[0], tmp[1], my_mtu, netmask); - write_dns(dns_fd, q, out, read, users[userid].downenc); - q->id = 0; - syslog(LOG_NOTICE, "accepted password from user #%d, given IP %s", userid, tmp[1]); + write_dns(dns_fd, q, out, read, users[userid].downenc); + q->id = 0; + syslog(LOG_NOTICE, "accepted password from user #%d, given IP %s", userid, tmp[1]); - free(tmp[1]); - free(tmp[0]); - } else { - write_dns(dns_fd, q, "LNAK", 4, 'T'); - syslog(LOG_WARNING, "rejected login request from user #%d from %s, bad password", - userid, format_addr(&q->from, q->fromlen)); - } - } - return; - } else if(in[0] == 'I' || in[0] == 'i') { - /* Request for IP number */ - in_addr_t replyaddr; - unsigned addr; - char reply[5]; + free(tmp[1]); + free(tmp[0]); + } else { + write_dns(dns_fd, q, "LNAK", 4, 'T'); + syslog(LOG_WARNING, "rejected login request from user #%d from %s, bad password", + userid, format_addr(&q->from, q->fromlen)); + } + } + return; + } else if(in[0] == 'I' || in[0] == 'i') { + /* Request for IP number */ + in_addr_t replyaddr; + unsigned addr; + char reply[5]; - userid = b32_8to5(in[1]); - if (check_authenticated_user_and_ip(userid, q) != 0) { - write_dns(dns_fd, q, "BADIP", 5, 'T'); - return; /* illegal id */ - } + userid = b32_8to5(in[1]); + if (check_authenticated_user_and_ip(userid, q) != 0) { + write_dns(dns_fd, q, "BADIP", 5, 'T'); + return; /* illegal id */ + } - if (ns_ip != INADDR_ANY) { - /* If set, use assigned external ip (-n option) */ - replyaddr = ns_ip; - } else { - /* otherwise return destination ip from packet */ - memcpy(&replyaddr, &q->destination.s_addr, sizeof(in_addr_t)); - } + if (ns_ip != INADDR_ANY) { + /* If set, use assigned external ip (-n option) */ + replyaddr = ns_ip; + } else { + /* otherwise return destination ip from packet */ + memcpy(&replyaddr, &q->destination.s_addr, sizeof(in_addr_t)); + } - addr = htonl(replyaddr); - reply[0] = 'I'; - reply[1] = (addr >> 24) & 0xFF; - reply[2] = (addr >> 16) & 0xFF; - reply[3] = (addr >> 8) & 0xFF; - reply[4] = (addr >> 0) & 0xFF; - write_dns(dns_fd, q, reply, sizeof(reply), 'T'); - } else if(in[0] == 'Z' || in[0] == 'z') { - /* Check for case conservation and chars not allowed according to RFC */ + addr = htonl(replyaddr); + reply[0] = 'I'; + reply[1] = (addr >> 24) & 0xFF; + reply[2] = (addr >> 16) & 0xFF; + reply[3] = (addr >> 8) & 0xFF; + reply[4] = (addr >> 0) & 0xFF; + write_dns(dns_fd, q, reply, sizeof(reply), 'T'); + } else if(in[0] == 'Z' || in[0] == 'z') { + /* Check for case conservation and chars not allowed according to RFC */ - /* Reply with received hostname as data */ - /* No userid here, reply with lowest-grade downenc */ - write_dns(dns_fd, q, in, domain_len, 'T'); - return; - } else if(in[0] == 'S' || in[0] == 's') { - int codec; - struct encoder *enc; - if (domain_len < 3) { /* len at least 3, example: "S15" */ - write_dns(dns_fd, q, "BADLEN", 6, 'T'); - return; - } + /* Reply with received hostname as data */ + /* No userid here, reply with lowest-grade downenc */ + write_dns(dns_fd, q, in, domain_len, 'T'); + return; + } else if(in[0] == 'S' || in[0] == 's') { + int codec; + struct encoder *enc; + if (domain_len < 3) { /* len at least 3, example: "S15" */ + write_dns(dns_fd, q, "BADLEN", 6, 'T'); + return; + } - userid = b32_8to5(in[1]); + userid = b32_8to5(in[1]); - if (check_authenticated_user_and_ip(userid, q) != 0) { - write_dns(dns_fd, q, "BADIP", 5, 'T'); - return; /* illegal id */ - } + if (check_authenticated_user_and_ip(userid, q) != 0) { + write_dns(dns_fd, q, "BADIP", 5, 'T'); + return; /* illegal id */ + } - codec = b32_8to5(in[2]); + codec = b32_8to5(in[2]); - switch (codec) { - case 5: /* 5 bits per byte = base32 */ - enc = get_base32_encoder(); - user_switch_codec(userid, enc); - write_dns(dns_fd, q, enc->name, strlen(enc->name), users[userid].downenc); - break; - case 6: /* 6 bits per byte = base64 */ - enc = get_base64_encoder(); - user_switch_codec(userid, enc); - write_dns(dns_fd, q, enc->name, strlen(enc->name), users[userid].downenc); - break; - case 26: /* "2nd" 6 bits per byte = base64u, with underscore */ - enc = get_base64u_encoder(); - user_switch_codec(userid, enc); - write_dns(dns_fd, q, enc->name, strlen(enc->name), users[userid].downenc); - break; - case 7: /* 7 bits per byte = base128 */ - enc = get_base128_encoder(); - user_switch_codec(userid, enc); - write_dns(dns_fd, q, enc->name, strlen(enc->name), users[userid].downenc); - break; - default: - write_dns(dns_fd, q, "BADCODEC", 8, users[userid].downenc); - break; - } - return; - } else if(in[0] == 'O' || in[0] == 'o') { - if (domain_len < 3) { /* len at least 3, example: "O1T" */ - write_dns(dns_fd, q, "BADLEN", 6, 'T'); - return; - } + switch (codec) { + case 5: /* 5 bits per byte = base32 */ + enc = get_base32_encoder(); + user_switch_codec(userid, enc); + write_dns(dns_fd, q, enc->name, strlen(enc->name), users[userid].downenc); + break; + case 6: /* 6 bits per byte = base64 */ + enc = get_base64_encoder(); + user_switch_codec(userid, enc); + write_dns(dns_fd, q, enc->name, strlen(enc->name), users[userid].downenc); + break; + case 26: /* "2nd" 6 bits per byte = base64u, with underscore */ + enc = get_base64u_encoder(); + user_switch_codec(userid, enc); + write_dns(dns_fd, q, enc->name, strlen(enc->name), users[userid].downenc); + break; + case 7: /* 7 bits per byte = base128 */ + enc = get_base128_encoder(); + user_switch_codec(userid, enc); + write_dns(dns_fd, q, enc->name, strlen(enc->name), users[userid].downenc); + break; + default: + write_dns(dns_fd, q, "BADCODEC", 8, users[userid].downenc); + break; + } + return; + } else if(in[0] == 'O' || in[0] == 'o') { + if (domain_len < 3) { /* len at least 3, example: "O1T" */ + write_dns(dns_fd, q, "BADLEN", 6, 'T'); + return; + } - userid = b32_8to5(in[1]); + userid = b32_8to5(in[1]); - if (check_authenticated_user_and_ip(userid, q) != 0) { - write_dns(dns_fd, q, "BADIP", 5, 'T'); - return; /* illegal id */ - } + if (check_authenticated_user_and_ip(userid, q) != 0) { + write_dns(dns_fd, q, "BADIP", 5, 'T'); + return; /* illegal id */ + } - switch (in[2]) { - case 'T': - case 't': - users[userid].downenc = 'T'; - write_dns(dns_fd, q, "Base32", 6, users[userid].downenc); - break; - case 'S': - case 's': - users[userid].downenc = 'S'; - write_dns(dns_fd, q, "Base64", 6, users[userid].downenc); - break; - case 'U': - case 'u': - users[userid].downenc = 'U'; - write_dns(dns_fd, q, "Base64u", 7, users[userid].downenc); - break; - case 'V': - case 'v': - users[userid].downenc = 'V'; - write_dns(dns_fd, q, "Base128", 7, users[userid].downenc); - break; - case 'R': - case 'r': - users[userid].downenc = 'R'; - write_dns(dns_fd, q, "Raw", 3, users[userid].downenc); - break; - case 'L': - case 'l': - users[userid].lazy = 1; - write_dns(dns_fd, q, "Lazy", 4, users[userid].downenc); - break; - case 'I': - case 'i': - users[userid].lazy = 0; - write_dns(dns_fd, q, "Immediate", 9, users[userid].downenc); - break; - default: - write_dns(dns_fd, q, "BADCODEC", 8, users[userid].downenc); - break; - } - return; - } else if(in[0] == 'Y' || in[0] == 'y') { - int i; - char *datap; - int datalen; + switch (in[2]) { + case 'T': + case 't': + users[userid].downenc = 'T'; + write_dns(dns_fd, q, "Base32", 6, users[userid].downenc); + break; + case 'S': + case 's': + users[userid].downenc = 'S'; + write_dns(dns_fd, q, "Base64", 6, users[userid].downenc); + break; + case 'U': + case 'u': + users[userid].downenc = 'U'; + write_dns(dns_fd, q, "Base64u", 7, users[userid].downenc); + break; + case 'V': + case 'v': + users[userid].downenc = 'V'; + write_dns(dns_fd, q, "Base128", 7, users[userid].downenc); + break; + case 'R': + case 'r': + users[userid].downenc = 'R'; + write_dns(dns_fd, q, "Raw", 3, users[userid].downenc); + break; + case 'L': + case 'l': + users[userid].lazy = 1; + write_dns(dns_fd, q, "Lazy", 4, users[userid].downenc); + break; + case 'I': + case 'i': + users[userid].lazy = 0; + write_dns(dns_fd, q, "Immediate", 9, users[userid].downenc); + break; + default: + write_dns(dns_fd, q, "BADCODEC", 8, users[userid].downenc); + break; + } + return; + } else if(in[0] == 'Y' || in[0] == 'y') { + int i; + char *datap; + int datalen; - if (domain_len < 6) { /* len at least 6, example: "YTxCMC" */ - write_dns(dns_fd, q, "BADLEN", 6, 'T'); - return; - } + if (domain_len < 6) { /* len at least 6, example: "YTxCMC" */ + write_dns(dns_fd, q, "BADLEN", 6, 'T'); + return; + } - i = b32_8to5(in[2]); /* check variant */ + i = b32_8to5(in[2]); /* check variant */ - switch (i) { - case 1: - datap = DOWNCODECCHECK1; - datalen = DOWNCODECCHECK1_LEN; - break; - default: - write_dns(dns_fd, q, "BADLEN", 6, 'T'); - return; - } + switch (i) { + case 1: + datap = DOWNCODECCHECK1; + datalen = DOWNCODECCHECK1_LEN; + break; + default: + write_dns(dns_fd, q, "BADLEN", 6, 'T'); + return; + } - switch (in[1]) { - case 'T': - case 't': - if (q->type == T_TXT || - q->type == T_SRV || q->type == T_MX || - q->type == T_CNAME || q->type == T_A) { - write_dns(dns_fd, q, datap, datalen, 'T'); - return; - } - break; - case 'S': - case 's': - if (q->type == T_TXT || - q->type == T_SRV || q->type == T_MX || - q->type == T_CNAME || q->type == T_A) { - write_dns(dns_fd, q, datap, datalen, 'S'); - return; - } - break; - case 'U': - case 'u': - if (q->type == T_TXT || - q->type == T_SRV || q->type == T_MX || - q->type == T_CNAME || q->type == T_A) { - write_dns(dns_fd, q, datap, datalen, 'U'); - return; - } - break; - case 'V': - case 'v': - if (q->type == T_TXT || - q->type == T_SRV || q->type == T_MX || - q->type == T_CNAME || q->type == T_A) { - write_dns(dns_fd, q, datap, datalen, 'V'); - return; - } - break; - case 'R': - case 'r': - if (q->type == T_NULL || q->type == T_TXT) { - write_dns(dns_fd, q, datap, datalen, 'R'); - return; - } - break; - } + switch (in[1]) { + case 'T': + case 't': + if (q->type == T_TXT || + q->type == T_SRV || q->type == T_MX || + q->type == T_CNAME || q->type == T_A) { + write_dns(dns_fd, q, datap, datalen, 'T'); + return; + } + break; + case 'S': + case 's': + if (q->type == T_TXT || + q->type == T_SRV || q->type == T_MX || + q->type == T_CNAME || q->type == T_A) { + write_dns(dns_fd, q, datap, datalen, 'S'); + return; + } + break; + case 'U': + case 'u': + if (q->type == T_TXT || + q->type == T_SRV || q->type == T_MX || + q->type == T_CNAME || q->type == T_A) { + write_dns(dns_fd, q, datap, datalen, 'U'); + return; + } + break; + case 'V': + case 'v': + if (q->type == T_TXT || + q->type == T_SRV || q->type == T_MX || + q->type == T_CNAME || q->type == T_A) { + write_dns(dns_fd, q, datap, datalen, 'V'); + return; + } + break; + case 'R': + case 'r': + if (q->type == T_NULL || q->type == T_TXT) { + write_dns(dns_fd, q, datap, datalen, 'R'); + return; + } + break; + } - /* if still here, then codec not available */ - write_dns(dns_fd, q, "BADCODEC", 8, 'T'); - return; + /* if still here, then codec not available */ + write_dns(dns_fd, q, "BADCODEC", 8, 'T'); + return; - } else if(in[0] == 'R' || in[0] == 'r') { - int req_frag_size; + } else if(in[0] == 'R' || in[0] == 'r') { + int req_frag_size; - if (domain_len < 16) { /* we'd better have some chars for data... */ - write_dns(dns_fd, q, "BADLEN", 6, 'T'); - return; - } + if (domain_len < 16) { /* we'd better have some chars for data... */ + write_dns(dns_fd, q, "BADLEN", 6, 'T'); + return; + } - /* Downstream fragsize probe packet */ - userid = (b32_8to5(in[1]) >> 1) & 15; - if (check_authenticated_user_and_ip(userid, q) != 0) { - write_dns(dns_fd, q, "BADIP", 5, 'T'); - return; /* illegal id */ - } + /* Downstream fragsize probe packet */ + userid = (b32_8to5(in[1]) >> 1) & 15; + if (check_authenticated_user_and_ip(userid, q) != 0) { + write_dns(dns_fd, q, "BADIP", 5, 'T'); + return; /* illegal id */ + } - req_frag_size = ((b32_8to5(in[1]) & 1) << 10) | ((b32_8to5(in[2]) & 31) << 5) | (b32_8to5(in[3]) & 31); - if (req_frag_size < 2 || req_frag_size > 2047) { - write_dns(dns_fd, q, "BADFRAG", 7, users[userid].downenc); - } else { - char buf[2048]; - int i; - unsigned int v = ((unsigned int) rand()) & 0xff ; + req_frag_size = ((b32_8to5(in[1]) & 1) << 10) | ((b32_8to5(in[2]) & 31) << 5) | (b32_8to5(in[3]) & 31); + if (req_frag_size < 2 || req_frag_size > 2047) { + write_dns(dns_fd, q, "BADFRAG", 7, users[userid].downenc); + } else { + char buf[2048]; + int i; + unsigned int v = ((unsigned int) rand()) & 0xff ; - memset(buf, 0, sizeof(buf)); - buf[0] = (req_frag_size >> 8) & 0xff; - buf[1] = req_frag_size & 0xff; - /* make checkable pseudo-random sequence */ - buf[2] = 107; - for (i = 3; i < 2048; i++, v = (v + 107) & 0xff) - buf[i] = v; - write_dns(dns_fd, q, buf, req_frag_size, users[userid].downenc); - } - return; - } else if(in[0] == 'N' || in[0] == 'n') { - int max_frag_size; + memset(buf, 0, sizeof(buf)); + buf[0] = (req_frag_size >> 8) & 0xff; + buf[1] = req_frag_size & 0xff; + /* make checkable pseudo-random sequence */ + buf[2] = 107; + for (i = 3; i < 2048; i++, v = (v + 107) & 0xff) + buf[i] = v; + write_dns(dns_fd, q, buf, req_frag_size, users[userid].downenc); + } + return; + } else if(in[0] == 'N' || in[0] == 'n') { + int max_frag_size; - read = unpack_data(unpacked, sizeof(unpacked), &(in[1]), domain_len - 1, b32); + read = unpack_data(unpacked, sizeof(unpacked), &(in[1]), domain_len - 1, b32); - if (read < 3) { - write_dns(dns_fd, q, "BADLEN", 6, 'T'); - return; - } + if (read < 3) { + write_dns(dns_fd, q, "BADLEN", 6, 'T'); + return; + } - /* Downstream fragsize packet */ - userid = unpacked[0]; - if (check_authenticated_user_and_ip(userid, q) != 0) { - write_dns(dns_fd, q, "BADIP", 5, 'T'); - return; /* illegal id */ - } + /* Downstream fragsize packet */ + userid = unpacked[0]; + if (check_authenticated_user_and_ip(userid, q) != 0) { + write_dns(dns_fd, q, "BADIP", 5, 'T'); + return; /* illegal id */ + } - max_frag_size = ((unpacked[1] & 0xff) << 8) | (unpacked[2] & 0xff); - if (max_frag_size < 2) { - write_dns(dns_fd, q, "BADFRAG", 7, users[userid].downenc); - } else { - users[userid].fragsize = max_frag_size; - write_dns(dns_fd, q, &unpacked[1], 2, users[userid].downenc); - } - return; - } else if(in[0] == 'P' || in[0] == 'p') { - int dn_seq; - int dn_frag; - int didsend = 0; + max_frag_size = ((unpacked[1] & 0xff) << 8) | (unpacked[2] & 0xff); + if (max_frag_size < 2) { + write_dns(dns_fd, q, "BADFRAG", 7, users[userid].downenc); + } else { + users[userid].fragsize = max_frag_size; + write_dns(dns_fd, q, &unpacked[1], 2, users[userid].downenc); + } + return; + } else if(in[0] == 'P' || in[0] == 'p') { + int dn_seq; + int dn_frag; + int didsend = 0; - /* We can't handle id=0, that's "no packet" to us. So drop - request completely. Note that DNS servers rewrite the id. - We'll drop 1 in 64k times. If DNS server retransmits with - different id, then all okay. - Else client won't retransmit, and we'll just keep the - previous ping in cache, no problem either. */ - if (q->id == 0) - return; + /* We can't handle id=0, that's "no packet" to us. So drop + request completely. Note that DNS servers rewrite the id. + We'll drop 1 in 64k times. If DNS server retransmits with + different id, then all okay. + Else client won't retransmit, and we'll just keep the + previous ping in cache, no problem either. */ + if (q->id == 0) + return; - read = unpack_data(unpacked, sizeof(unpacked), &(in[1]), domain_len - 1, b32); - if (read < 4) - return; + read = unpack_data(unpacked, sizeof(unpacked), &(in[1]), domain_len - 1, b32); + if (read < 4) + return; - /* Ping packet, store userid */ - userid = unpacked[0]; - if (check_authenticated_user_and_ip(userid, q) != 0) { - write_dns(dns_fd, q, "BADIP", 5, 'T'); - return; /* illegal id */ - } + /* Ping packet, store userid */ + userid = unpacked[0]; + if (check_authenticated_user_and_ip(userid, q) != 0) { + write_dns(dns_fd, q, "BADIP", 5, 'T'); + return; /* illegal id */ + } #ifdef DNSCACHE_LEN - /* Check if cached */ - if (answer_from_dnscache(dns_fd, userid, q)) - return; + /* Check if cached */ + if (answer_from_dnscache(dns_fd, userid, q)) + return; #endif - /* Check if duplicate (and not in full dnscache any more) */ - if (answer_from_qmem(dns_fd, q, users[userid].qmemping_cmc, - users[userid].qmemping_type, QMEMPING_LEN, - (void *) unpacked)) - return; + /* Check if duplicate (and not in full dnscache any more) */ + if (answer_from_qmem(dns_fd, q, users[userid].qmemping_cmc, + users[userid].qmemping_type, QMEMPING_LEN, + (void *) unpacked)) + return; - /* Check if duplicate of waiting queries; impatient DNS relays - like to re-try early and often (with _different_ .id!) */ - if (users[userid].q.id != 0 && - q->type == users[userid].q.type && - !strcmp(q->name, users[userid].q.name) && - users[userid].lazy) { - /* We have this ping already, and it's waiting to be - answered. Always keep the last duplicate, since the - relay may have forgotten its first version already. - Our answer will go to both. - (If we already sent an answer, qmem/cache will - have triggered.) */ - if (debug >= 2) { - fprintf(stderr, "PING pkt from user %d = dupe from impatient DNS server, remembering\n", - userid); - } - users[userid].q.id2 = q->id; - users[userid].q.fromlen2 = q->fromlen; - memcpy(&(users[userid].q.from2), &(q->from), q->fromlen); - return; - } + /* Check if duplicate of waiting queries; impatient DNS relays + like to re-try early and often (with _different_ .id!) */ + if (users[userid].q.id != 0 && + q->type == users[userid].q.type && + !strcmp(q->name, users[userid].q.name) && + users[userid].lazy) { + /* We have this ping already, and it's waiting to be + answered. Always keep the last duplicate, since the + relay may have forgotten its first version already. + Our answer will go to both. + (If we already sent an answer, qmem/cache will + have triggered.) */ + if (debug >= 2) { + fprintf(stderr, "PING pkt from user %d = dupe from impatient DNS server, remembering\n", + userid); + } + users[userid].q.id2 = q->id; + users[userid].q.fromlen2 = q->fromlen; + memcpy(&(users[userid].q.from2), &(q->from), q->fromlen); + return; + } - if (users[userid].q_sendrealsoon.id != 0 && - q->type == users[userid].q_sendrealsoon.type && - !strcmp(q->name, users[userid].q_sendrealsoon.name)) { - /* Outer select loop will send answer immediately, - to both queries. */ - if (debug >= 2) { - fprintf(stderr, "PING pkt from user %d = dupe from impatient DNS server, remembering\n", - userid); - } - users[userid].q_sendrealsoon.id2 = q->id; - users[userid].q_sendrealsoon.fromlen2 = q->fromlen; - memcpy(&(users[userid].q_sendrealsoon.from2), - &(q->from), q->fromlen); - return; - } + if (users[userid].q_sendrealsoon.id != 0 && + q->type == users[userid].q_sendrealsoon.type && + !strcmp(q->name, users[userid].q_sendrealsoon.name)) { + /* Outer select loop will send answer immediately, + to both queries. */ + if (debug >= 2) { + fprintf(stderr, "PING pkt from user %d = dupe from impatient DNS server, remembering\n", + userid); + } + users[userid].q_sendrealsoon.id2 = q->id; + users[userid].q_sendrealsoon.fromlen2 = q->fromlen; + memcpy(&(users[userid].q_sendrealsoon.from2), + &(q->from), q->fromlen); + return; + } - dn_seq = unpacked[1] >> 4; - dn_frag = unpacked[1] & 15; + dn_seq = unpacked[1] >> 4; + dn_frag = unpacked[1] & 15; - if (debug >= 1) { - fprintf(stderr, "PING pkt from user %d, ack for downstream %d/%d\n", - userid, dn_seq, dn_frag); - } + if (debug >= 1) { + fprintf(stderr, "PING pkt from user %d, ack for downstream %d/%d\n", + userid, dn_seq, dn_frag); + } - process_downstream_ack(userid, dn_seq, dn_frag); + process_downstream_ack(userid, dn_seq, dn_frag); - if (debug >= 3) { - fprintf(stderr, "PINGret (if any) will ack upstream %d/%d\n", - users[userid].inpacket.seqno, users[userid].inpacket.fragment); - } + if (debug >= 3) { + fprintf(stderr, "PINGret (if any) will ack upstream %d/%d\n", + users[userid].inpacket.seqno, users[userid].inpacket.fragment); + } - /* If there is a query that must be returned real soon, do it. - May contain new downstream data if the ping had a new ack. - Otherwise, may also be re-sending old data. */ - if (users[userid].q_sendrealsoon.id != 0) { - send_chunk_or_dataless(dns_fd, userid, &users[userid].q_sendrealsoon); - } + /* If there is a query that must be returned real soon, do it. + May contain new downstream data if the ping had a new ack. + Otherwise, may also be re-sending old data. */ + if (users[userid].q_sendrealsoon.id != 0) { + send_chunk_or_dataless(dns_fd, userid, &users[userid].q_sendrealsoon); + } - /* We need to store a new query, so if there still is an - earlier query waiting, always send a reply to finish it. - May contain new downstream data if the ping had a new ack. - Otherwise, may also be re-sending old data. - (This is duplicate data if we had q_sendrealsoon above.) */ - if (users[userid].q.id != 0) { - didsend = 1; - if (send_chunk_or_dataless(dns_fd, userid, &users[userid].q) == 1) - /* new packet from queue, send immediately */ - didsend = 0; - } + /* We need to store a new query, so if there still is an + earlier query waiting, always send a reply to finish it. + May contain new downstream data if the ping had a new ack. + Otherwise, may also be re-sending old data. + (This is duplicate data if we had q_sendrealsoon above.) */ + if (users[userid].q.id != 0) { + didsend = 1; + if (send_chunk_or_dataless(dns_fd, userid, &users[userid].q) == 1) + /* new packet from queue, send immediately */ + didsend = 0; + } - /* Save new query and time info */ - memcpy(&(users[userid].q), q, sizeof(struct query)); - users[userid].last_pkt = time(NULL); + /* Save new query and time info */ + memcpy(&(users[userid].q), q, sizeof(struct query)); + users[userid].last_pkt = time(NULL); - /* If anything waiting and we didn't already send above, send - it now. And always send immediately if we're not lazy - (then above won't have sent at all). */ - if ((!didsend && users[userid].outpacket.len > 0) || - !users[userid].lazy) - send_chunk_or_dataless(dns_fd, userid, &users[userid].q); + /* If anything waiting and we didn't already send above, send + it now. And always send immediately if we're not lazy + (then above won't have sent at all). */ + if ((!didsend && users[userid].outpacket.len > 0) || + !users[userid].lazy) + send_chunk_or_dataless(dns_fd, userid, &users[userid].q); - } else if((in[0] >= '0' && in[0] <= '9') - || (in[0] >= 'a' && in[0] <= 'f') - || (in[0] >= 'A' && in[0] <= 'F')) { - int up_seq, up_frag, dn_seq, dn_frag, lastfrag; - int upstream_ok = 1; - int didsend = 0; - int code = -1; + } else if((in[0] >= '0' && in[0] <= '9') + || (in[0] >= 'a' && in[0] <= 'f') + || (in[0] >= 'A' && in[0] <= 'F')) { + int up_seq, up_frag, dn_seq, dn_frag, lastfrag; + int upstream_ok = 1; + int didsend = 0; + int code = -1; - /* Need 5char header + >=1 char data */ - if (domain_len < 6) - return; + /* Need 5char header + >=1 char data */ + if (domain_len < 6) + return; - /* We can't handle id=0, that's "no packet" to us. So drop - request completely. Note that DNS servers rewrite the id. - We'll drop 1 in 64k times. If DNS server retransmits with - different id, then all okay. - Else client doesn't get our ack, and will retransmit in - 1 second. */ - if (q->id == 0) - return; + /* We can't handle id=0, that's "no packet" to us. So drop + request completely. Note that DNS servers rewrite the id. + We'll drop 1 in 64k times. If DNS server retransmits with + different id, then all okay. + Else client doesn't get our ack, and will retransmit in + 1 second. */ + if (q->id == 0) + return; - if ((in[0] >= '0' && in[0] <= '9')) - code = in[0] - '0'; - if ((in[0] >= 'a' && in[0] <= 'f')) - code = in[0] - 'a' + 10; - if ((in[0] >= 'A' && in[0] <= 'F')) - code = in[0] - 'A' + 10; + if ((in[0] >= '0' && in[0] <= '9')) + code = in[0] - '0'; + if ((in[0] >= 'a' && in[0] <= 'f')) + code = in[0] - 'a' + 10; + if ((in[0] >= 'A' && in[0] <= 'F')) + code = in[0] - 'A' + 10; - userid = code; - /* Check user and sending ip number */ - if (check_authenticated_user_and_ip(userid, q) != 0) { - write_dns(dns_fd, q, "BADIP", 5, 'T'); - return; /* illegal id */ - } + userid = code; + /* Check user and sending ip number */ + if (check_authenticated_user_and_ip(userid, q) != 0) { + write_dns(dns_fd, q, "BADIP", 5, 'T'); + return; /* illegal id */ + } #ifdef DNSCACHE_LEN - /* Check if cached */ - if (answer_from_dnscache(dns_fd, userid, q)) - return; + /* Check if cached */ + if (answer_from_dnscache(dns_fd, userid, q)) + return; #endif - /* Check if duplicate (and not in full dnscache any more) */ - if (answer_from_qmem_data(dns_fd, userid, q)) - return; + /* Check if duplicate (and not in full dnscache any more) */ + if (answer_from_qmem_data(dns_fd, userid, q)) + return; - /* Check if duplicate of waiting queries; impatient DNS relays - like to re-try early and often (with _different_ .id!) */ - if (users[userid].q.id != 0 && - q->type == users[userid].q.type && - !strcmp(q->name, users[userid].q.name) && - users[userid].lazy) { - /* We have this packet already, and it's waiting to be - answered. Always keep the last duplicate, since the - relay may have forgotten its first version already. - Our answer will go to both. - (If we already sent an answer, qmem/cache will - have triggered.) */ - if (debug >= 2) { - fprintf(stderr, "IN pkt from user %d = dupe from impatient DNS server, remembering\n", - userid); - } - users[userid].q.id2 = q->id; - users[userid].q.fromlen2 = q->fromlen; - memcpy(&(users[userid].q.from2), &(q->from), q->fromlen); - return; - } + /* Check if duplicate of waiting queries; impatient DNS relays + like to re-try early and often (with _different_ .id!) */ + if (users[userid].q.id != 0 && + q->type == users[userid].q.type && + !strcmp(q->name, users[userid].q.name) && + users[userid].lazy) { + /* We have this packet already, and it's waiting to be + answered. Always keep the last duplicate, since the + relay may have forgotten its first version already. + Our answer will go to both. + (If we already sent an answer, qmem/cache will + have triggered.) */ + if (debug >= 2) { + fprintf(stderr, "IN pkt from user %d = dupe from impatient DNS server, remembering\n", + userid); + } + users[userid].q.id2 = q->id; + users[userid].q.fromlen2 = q->fromlen; + memcpy(&(users[userid].q.from2), &(q->from), q->fromlen); + return; + } - if (users[userid].q_sendrealsoon.id != 0 && - q->type == users[userid].q_sendrealsoon.type && - !strcmp(q->name, users[userid].q_sendrealsoon.name)) { - /* Outer select loop will send answer immediately, - to both queries. */ - if (debug >= 2) { - fprintf(stderr, "IN pkt from user %d = dupe from impatient DNS server, remembering\n", - userid); - } - users[userid].q_sendrealsoon.id2 = q->id; - users[userid].q_sendrealsoon.fromlen2 = q->fromlen; - memcpy(&(users[userid].q_sendrealsoon.from2), - &(q->from), q->fromlen); - return; - } + if (users[userid].q_sendrealsoon.id != 0 && + q->type == users[userid].q_sendrealsoon.type && + !strcmp(q->name, users[userid].q_sendrealsoon.name)) { + /* Outer select loop will send answer immediately, + to both queries. */ + if (debug >= 2) { + fprintf(stderr, "IN pkt from user %d = dupe from impatient DNS server, remembering\n", + userid); + } + users[userid].q_sendrealsoon.id2 = q->id; + users[userid].q_sendrealsoon.fromlen2 = q->fromlen; + memcpy(&(users[userid].q_sendrealsoon.from2), + &(q->from), q->fromlen); + return; + } - /* Decode data header */ - up_seq = (b32_8to5(in[1]) >> 2) & 7; - up_frag = ((b32_8to5(in[1]) & 3) << 2) | ((b32_8to5(in[2]) >> 3) & 3); - dn_seq = (b32_8to5(in[2]) & 7); - dn_frag = b32_8to5(in[3]) >> 1; - lastfrag = b32_8to5(in[3]) & 1; + /* Decode data header */ + up_seq = (b32_8to5(in[1]) >> 2) & 7; + up_frag = ((b32_8to5(in[1]) & 3) << 2) | ((b32_8to5(in[2]) >> 3) & 3); + dn_seq = (b32_8to5(in[2]) & 7); + dn_frag = b32_8to5(in[3]) >> 1; + lastfrag = b32_8to5(in[3]) & 1; - process_downstream_ack(userid, dn_seq, dn_frag); + process_downstream_ack(userid, dn_seq, dn_frag); - if (up_seq == users[userid].inpacket.seqno && - up_frag <= users[userid].inpacket.fragment) { - /* Got repeated old packet _with data_, probably - because client didn't receive our ack. So re-send - our ack(+data) immediately to keep things flowing - fast. - If it's a _really_ old frag, it's a nameserver - that tries again, and sending our current (non- - matching) fragno won't be a problem. */ - if (debug >= 1) { - fprintf(stderr, "IN pkt seq# %d, frag %d, dropped duplicate frag\n", - up_seq, up_frag); - } - upstream_ok = 0; - } - else if (up_seq != users[userid].inpacket.seqno && - recent_seqno(users[userid].inpacket.seqno, up_seq)) { - /* Duplicate of recent upstream data packet; probably - need to answer this to keep DNS server happy */ - if (debug >= 1) { - fprintf(stderr, "IN pkt seq# %d, frag %d, dropped duplicate recent seqno\n", - up_seq, up_frag); - } - upstream_ok = 0; - } - else if (up_seq != users[userid].inpacket.seqno) { - /* Really new packet has arrived, no recent duplicate */ - /* Forget any old packet, even if incomplete */ - users[userid].inpacket.seqno = up_seq; - users[userid].inpacket.fragment = up_frag; - users[userid].inpacket.len = 0; - users[userid].inpacket.offset = 0; - } else { - /* seq is same, frag is higher; don't care about - missing fragments, TCP checksum will fail */ - users[userid].inpacket.fragment = up_frag; - } + if (up_seq == users[userid].inpacket.seqno && + up_frag <= users[userid].inpacket.fragment) { + /* Got repeated old packet _with data_, probably + because client didn't receive our ack. So re-send + our ack(+data) immediately to keep things flowing + fast. + If it's a _really_ old frag, it's a nameserver + that tries again, and sending our current (non- + matching) fragno won't be a problem. */ + if (debug >= 1) { + fprintf(stderr, "IN pkt seq# %d, frag %d, dropped duplicate frag\n", + up_seq, up_frag); + } + upstream_ok = 0; + } + else if (up_seq != users[userid].inpacket.seqno && + recent_seqno(users[userid].inpacket.seqno, up_seq)) { + /* Duplicate of recent upstream data packet; probably + need to answer this to keep DNS server happy */ + if (debug >= 1) { + fprintf(stderr, "IN pkt seq# %d, frag %d, dropped duplicate recent seqno\n", + up_seq, up_frag); + } + upstream_ok = 0; + } + else if (up_seq != users[userid].inpacket.seqno) { + /* Really new packet has arrived, no recent duplicate */ + /* Forget any old packet, even if incomplete */ + users[userid].inpacket.seqno = up_seq; + users[userid].inpacket.fragment = up_frag; + users[userid].inpacket.len = 0; + users[userid].inpacket.offset = 0; + } else { + /* seq is same, frag is higher; don't care about + missing fragments, TCP checksum will fail */ + users[userid].inpacket.fragment = up_frag; + } - if (debug >= 3) { - fprintf(stderr, "INpack with upstream %d/%d, we are going to ack upstream %d/%d\n", - up_seq, up_frag, - users[userid].inpacket.seqno, users[userid].inpacket.fragment); - } + if (debug >= 3) { + fprintf(stderr, "INpack with upstream %d/%d, we are going to ack upstream %d/%d\n", + up_seq, up_frag, + users[userid].inpacket.seqno, users[userid].inpacket.fragment); + } - if (upstream_ok) { - /* decode with this user's encoding */ - read = unpack_data(unpacked, sizeof(unpacked), &(in[5]), domain_len - 5, - users[userid].encoder); + if (upstream_ok) { + /* decode with this user's encoding */ + read = unpack_data(unpacked, sizeof(unpacked), &(in[5]), domain_len - 5, + users[userid].encoder); - /* copy to packet buffer, update length */ - read = MIN(read, sizeof(users[userid].inpacket.data) - users[userid].inpacket.offset); - memcpy(users[userid].inpacket.data + users[userid].inpacket.offset, unpacked, read); - users[userid].inpacket.len += read; - users[userid].inpacket.offset += read; + /* copy to packet buffer, update length */ + read = MIN(read, sizeof(users[userid].inpacket.data) - users[userid].inpacket.offset); + memcpy(users[userid].inpacket.data + users[userid].inpacket.offset, unpacked, read); + users[userid].inpacket.len += read; + users[userid].inpacket.offset += read; - if (debug >= 1) { - fprintf(stderr, "IN pkt seq# %d, frag %d (last=%d), fragsize %d, total %d, from user %d\n", - up_seq, up_frag, lastfrag, read, users[userid].inpacket.len, userid); - } - } + if (debug >= 1) { + fprintf(stderr, "IN pkt seq# %d, frag %d (last=%d), fragsize %d, total %d, from user %d\n", + up_seq, up_frag, lastfrag, read, users[userid].inpacket.len, userid); + } + } - if (upstream_ok && lastfrag) { /* packet is complete */ - handle_full_packet(tun_fd, dns_fd, userid); - } + if (upstream_ok && lastfrag) { /* packet is complete */ + handle_full_packet(tun_fd, dns_fd, userid); + } - /* If there is a query that must be returned real soon, do it. - Includes an ack of the just received upstream fragment, - may contain new data. */ - if (users[userid].q_sendrealsoon.id != 0) { - didsend = 1; - if (send_chunk_or_dataless(dns_fd, userid, &users[userid].q_sendrealsoon) == 1) - /* new packet from queue, send immediately */ - didsend = 0; - } + /* If there is a query that must be returned real soon, do it. + Includes an ack of the just received upstream fragment, + may contain new data. */ + if (users[userid].q_sendrealsoon.id != 0) { + didsend = 1; + if (send_chunk_or_dataless(dns_fd, userid, &users[userid].q_sendrealsoon) == 1) + /* new packet from queue, send immediately */ + didsend = 0; + } - /* If we already have an earlier query waiting, we need to - get rid of it to store the new query. - - If we have new data waiting and not yet sent above, - send immediately. - - If this wasn't the last upstream fragment, then we expect - more, so ack immediately if we didn't already. - - If we are in non-lazy mode, there should be no query - waiting, but if there is, send immediately. - - In all other cases (mostly the last-fragment cases), - we can afford to wait just a tiny little while for the - TCP ack to arrive from our tun. Note that this works best - when there is only one client. - */ - if (users[userid].q.id != 0) { - if ((users[userid].outpacket.len > 0 && !didsend) || - (upstream_ok && !lastfrag && !didsend) || - (!upstream_ok && !didsend) || - !users[userid].lazy) { - didsend = 1; - if (send_chunk_or_dataless(dns_fd, userid, &users[userid].q) == 1) - /* new packet from queue, send immediately */ - didsend = 0; - } else { - memcpy(&(users[userid].q_sendrealsoon), - &(users[userid].q), - sizeof(struct query)); - users[userid].q_sendrealsoon_new = 1; - users[userid].q.id = 0; /* used */ - didsend = 1; - } - } + /* If we already have an earlier query waiting, we need to + get rid of it to store the new query. + - If we have new data waiting and not yet sent above, + send immediately. + - If this wasn't the last upstream fragment, then we expect + more, so ack immediately if we didn't already. + - If we are in non-lazy mode, there should be no query + waiting, but if there is, send immediately. + - In all other cases (mostly the last-fragment cases), + we can afford to wait just a tiny little while for the + TCP ack to arrive from our tun. Note that this works best + when there is only one client. + */ + if (users[userid].q.id != 0) { + if ((users[userid].outpacket.len > 0 && !didsend) || + (upstream_ok && !lastfrag && !didsend) || + (!upstream_ok && !didsend) || + !users[userid].lazy) { + didsend = 1; + if (send_chunk_or_dataless(dns_fd, userid, &users[userid].q) == 1) + /* new packet from queue, send immediately */ + didsend = 0; + } else { + memcpy(&(users[userid].q_sendrealsoon), + &(users[userid].q), + sizeof(struct query)); + users[userid].q_sendrealsoon_new = 1; + users[userid].q.id = 0; /* used */ + didsend = 1; + } + } - /* Save new query and time info */ - memcpy(&(users[userid].q), q, sizeof(struct query)); - users[userid].last_pkt = time(NULL); + /* Save new query and time info */ + memcpy(&(users[userid].q), q, sizeof(struct query)); + users[userid].last_pkt = time(NULL); - /* If we still need to ack this upstream frag, do it to keep - upstream flowing. - - If we have new data waiting and not yet sent above, - send immediately. - - If this wasn't the last upstream fragment, then we expect - more, so ack immediately if we didn't already or are - in non-lazy mode. - - If this was the last fragment, and we didn't ack already - or are in non-lazy mode, send the ack after just a tiny - little while so that the TCP ack may have arrived from - our tun device. - - In all other cases, don't send anything now. - */ - if (users[userid].outpacket.len > 0 && !didsend) - send_chunk_or_dataless(dns_fd, userid, &users[userid].q); - else if (!didsend || !users[userid].lazy) { - if (upstream_ok && lastfrag) { - memcpy(&(users[userid].q_sendrealsoon), - &(users[userid].q), - sizeof(struct query)); - users[userid].q_sendrealsoon_new = 1; - users[userid].q.id = 0; /* used */ - } else { - send_chunk_or_dataless(dns_fd, userid, &users[userid].q); - } - } - } + /* If we still need to ack this upstream frag, do it to keep + upstream flowing. + - If we have new data waiting and not yet sent above, + send immediately. + - If this wasn't the last upstream fragment, then we expect + more, so ack immediately if we didn't already or are + in non-lazy mode. + - If this was the last fragment, and we didn't ack already + or are in non-lazy mode, send the ack after just a tiny + little while so that the TCP ack may have arrived from + our tun device. + - In all other cases, don't send anything now. + */ + if (users[userid].outpacket.len > 0 && !didsend) + send_chunk_or_dataless(dns_fd, userid, &users[userid].q); + else if (!didsend || !users[userid].lazy) { + if (upstream_ok && lastfrag) { + memcpy(&(users[userid].q_sendrealsoon), + &(users[userid].q), + sizeof(struct query)); + users[userid].q_sendrealsoon_new = 1; + users[userid].q.id = 0; /* used */ + } else { + send_chunk_or_dataless(dns_fd, userid, &users[userid].q); + } + } + } } static void handle_ns_request(int dns_fd, struct query *q) /* Mostly identical to handle_a_request() below */ { - char buf[64*1024]; - int len; + char buf[64*1024]; + int len; - if (ns_ip != INADDR_ANY) { - /* If ns_ip set, overwrite destination addr with it. - * Destination addr will be sent as additional record (A, IN) */ - memcpy(&q->destination.s_addr, &ns_ip, sizeof(in_addr_t)); - } + if (ns_ip != INADDR_ANY) { + /* If ns_ip set, overwrite destination addr with it. + * Destination addr will be sent as additional record (A, IN) */ + memcpy(&q->destination.s_addr, &ns_ip, sizeof(in_addr_t)); + } - len = dns_encode_ns_response(buf, sizeof(buf), q, topdomain); - if (len < 1) { - warnx("dns_encode_ns_response doesn't fit"); - return; - } + len = dns_encode_ns_response(buf, sizeof(buf), q, topdomain); + if (len < 1) { + warnx("dns_encode_ns_response doesn't fit"); + return; + } - if (debug >= 2) { - fprintf(stderr, "TX: client %s, type %d, name %s, %d bytes NS reply\n", - format_addr(&q->from, q->fromlen), q->type, q->name, len); - } - if (sendto(dns_fd, buf, len, 0, (struct sockaddr*)&q->from, q->fromlen) <= 0) { - warn("ns reply send error"); - } + if (debug >= 2) { + fprintf(stderr, "TX: client %s, type %d, name %s, %d bytes NS reply\n", + format_addr(&q->from, q->fromlen), q->type, q->name, len); + } + if (sendto(dns_fd, buf, len, 0, (struct sockaddr*)&q->from, q->fromlen) <= 0) { + warn("ns reply send error"); + } } static void handle_a_request(int dns_fd, struct query *q, int fakeip) /* Mostly identical to handle_ns_request() above */ { - char buf[64*1024]; - int len; + char buf[64*1024]; + int len; - if (fakeip) { - in_addr_t ip = inet_addr("127.0.0.1"); - memcpy(&q->destination.s_addr, &ip, sizeof(in_addr_t)); + if (fakeip) { + in_addr_t ip = inet_addr("127.0.0.1"); + memcpy(&q->destination.s_addr, &ip, sizeof(in_addr_t)); - } else if (ns_ip != INADDR_ANY) { - /* If ns_ip set, overwrite destination addr with it. - * Destination addr will be sent as additional record (A, IN) */ - memcpy(&q->destination.s_addr, &ns_ip, sizeof(in_addr_t)); - } + } else if (ns_ip != INADDR_ANY) { + /* If ns_ip set, overwrite destination addr with it. + * Destination addr will be sent as additional record (A, IN) */ + memcpy(&q->destination.s_addr, &ns_ip, sizeof(in_addr_t)); + } - len = dns_encode_a_response(buf, sizeof(buf), q); - if (len < 1) { - warnx("dns_encode_a_response doesn't fit"); - return; - } + len = dns_encode_a_response(buf, sizeof(buf), q); + if (len < 1) { + warnx("dns_encode_a_response doesn't fit"); + return; + } - if (debug >= 2) { - fprintf(stderr, "TX: client %s, type %d, name %s, %d bytes A reply\n", - format_addr(&q->from, q->fromlen), q->type, q->name, len); - } - if (sendto(dns_fd, buf, len, 0, (struct sockaddr*)&q->from, q->fromlen) <= 0) { - warn("a reply send error"); - } + if (debug >= 2) { + fprintf(stderr, "TX: client %s, type %d, name %s, %d bytes A reply\n", + format_addr(&q->from, q->fromlen), q->type, q->name, len); + } + if (sendto(dns_fd, buf, len, 0, (struct sockaddr*)&q->from, q->fromlen) <= 0) { + warn("a reply send error"); + } } static void forward_query(int bind_fd, struct query *q) { - char buf[64*1024]; - int len; - struct fw_query fwq; - struct sockaddr_in *myaddr; - in_addr_t newaddr; + char buf[64*1024]; + int len; + struct fw_query fwq; + struct sockaddr_in *myaddr; + in_addr_t newaddr; - len = dns_encode(buf, sizeof(buf), q, QR_QUERY, q->name, strlen(q->name)); - if (len < 1) { - warnx("dns_encode doesn't fit"); - return; - } + len = dns_encode(buf, sizeof(buf), q, QR_QUERY, q->name, strlen(q->name)); + if (len < 1) { + warnx("dns_encode doesn't fit"); + return; + } - /* Store sockaddr for q->id */ - memcpy(&(fwq.addr), &(q->from), q->fromlen); - fwq.addrlen = q->fromlen; - fwq.id = q->id; - fw_query_put(&fwq); + /* Store sockaddr for q->id */ + memcpy(&(fwq.addr), &(q->from), q->fromlen); + fwq.addrlen = q->fromlen; + fwq.id = q->id; + fw_query_put(&fwq); - newaddr = inet_addr("127.0.0.1"); - myaddr = (struct sockaddr_in *) &(q->from); - memcpy(&(myaddr->sin_addr), &newaddr, sizeof(in_addr_t)); - myaddr->sin_port = htons(bind_port); + newaddr = inet_addr("127.0.0.1"); + myaddr = (struct sockaddr_in *) &(q->from); + memcpy(&(myaddr->sin_addr), &newaddr, sizeof(in_addr_t)); + myaddr->sin_port = htons(bind_port); - if (debug >= 2) { - fprintf(stderr, "TX: NS reply \n"); - } + if (debug >= 2) { + fprintf(stderr, "TX: NS reply \n"); + } - if (sendto(bind_fd, buf, len, 0, (struct sockaddr*)&q->from, q->fromlen) <= 0) { - warn("forward query error"); - } + if (sendto(bind_fd, buf, len, 0, (struct sockaddr*)&q->from, q->fromlen) <= 0) { + warn("forward query error"); + } } static int tunnel_bind(int bind_fd, int dns_fd) { - char packet[64*1024]; - struct sockaddr_storage from; - socklen_t fromlen; - struct fw_query *query; - unsigned short id; - int r; + char packet[64*1024]; + struct sockaddr_storage from; + socklen_t fromlen; + struct fw_query *query; + unsigned short id; + int r; - fromlen = sizeof(struct sockaddr); - r = recvfrom(bind_fd, packet, sizeof(packet), 0, - (struct sockaddr*)&from, &fromlen); + fromlen = sizeof(struct sockaddr); + r = recvfrom(bind_fd, packet, sizeof(packet), 0, + (struct sockaddr*)&from, &fromlen); - if (r <= 0) - return 0; + if (r <= 0) + return 0; - id = dns_get_id(packet, r); + id = dns_get_id(packet, r); - if (debug >= 2) { - fprintf(stderr, "RX: Got response on query %u from DNS\n", (id & 0xFFFF)); - } + if (debug >= 2) { + fprintf(stderr, "RX: Got response on query %u from DNS\n", (id & 0xFFFF)); + } - /* Get sockaddr from id */ - fw_query_get(id, &query); - if (!query) { - if (debug >= 2) { - fprintf(stderr, "Lost sender of id %u, dropping reply\n", (id & 0xFFFF)); - } - return 0; - } + /* Get sockaddr from id */ + fw_query_get(id, &query); + if (!query) { + if (debug >= 2) { + fprintf(stderr, "Lost sender of id %u, dropping reply\n", (id & 0xFFFF)); + } + return 0; + } - if (debug >= 2) { - fprintf(stderr, "TX: client %s id %u, %d bytes\n", - format_addr(&query->addr, query->addrlen), (id & 0xffff), r); - } + if (debug >= 2) { + fprintf(stderr, "TX: client %s id %u, %d bytes\n", + format_addr(&query->addr, query->addrlen), (id & 0xffff), r); + } - if (sendto(dns_fd, packet, r, 0, (const struct sockaddr *) &(query->addr), - query->addrlen) <= 0) { - warn("forward reply error"); - } + if (sendto(dns_fd, packet, r, 0, (const struct sockaddr *) &(query->addr), + query->addrlen) <= 0) { + warn("forward reply error"); + } - return 0; + return 0; } static int tunnel_dns(int tun_fd, int dns_fd, int bind_fd) { - struct query q; - int read; - int domain_len; - int inside_topdomain = 0; + struct query q; + int read; + int domain_len; + int inside_topdomain = 0; - if ((read = read_dns(dns_fd, tun_fd, &q)) <= 0) - return 0; + if ((read = read_dns(dns_fd, tun_fd, &q)) <= 0) + return 0; - if (debug >= 2) { - fprintf(stderr, "RX: client %s, type %d, name %s\n", - format_addr(&q.from, q.fromlen), q.type, q.name); - } + if (debug >= 2) { + fprintf(stderr, "RX: client %s, type %d, name %s\n", + format_addr(&q.from, q.fromlen), q.type, q.name); + } - domain_len = strlen(q.name) - strlen(topdomain); - if (domain_len >= 0 && !strcasecmp(q.name + domain_len, topdomain)) - inside_topdomain = 1; - /* require dot before topdomain */ - if (domain_len >= 1 && q.name[domain_len - 1] != '.') - inside_topdomain = 0; + domain_len = strlen(q.name) - strlen(topdomain); + if (domain_len >= 0 && !strcasecmp(q.name + domain_len, topdomain)) + inside_topdomain = 1; + /* require dot before topdomain */ + if (domain_len >= 1 && q.name[domain_len - 1] != '.') + inside_topdomain = 0; - if (inside_topdomain) { - /* This is a query we can handle */ + if (inside_topdomain) { + /* This is a query we can handle */ - /* Handle A-type query for ns.topdomain, possibly caused - by our proper response to any NS request */ - if (domain_len == 3 && q.type == T_A && - (q.name[0] == 'n' || q.name[0] == 'N') && - (q.name[1] == 's' || q.name[1] == 'S') && - q.name[2] == '.') { - handle_a_request(dns_fd, &q, 0); - return 0; - } + /* Handle A-type query for ns.topdomain, possibly caused + by our proper response to any NS request */ + if (domain_len == 3 && q.type == T_A && + (q.name[0] == 'n' || q.name[0] == 'N') && + (q.name[1] == 's' || q.name[1] == 'S') && + q.name[2] == '.') { + handle_a_request(dns_fd, &q, 0); + return 0; + } - /* Handle A-type query for www.topdomain, for anyone that's - poking around */ - if (domain_len == 4 && q.type == T_A && - (q.name[0] == 'w' || q.name[0] == 'W') && - (q.name[1] == 'w' || q.name[1] == 'W') && - (q.name[2] == 'w' || q.name[2] == 'W') && - q.name[3] == '.') { - handle_a_request(dns_fd, &q, 1); - return 0; - } + /* Handle A-type query for www.topdomain, for anyone that's + poking around */ + if (domain_len == 4 && q.type == T_A && + (q.name[0] == 'w' || q.name[0] == 'W') && + (q.name[1] == 'w' || q.name[1] == 'W') && + (q.name[2] == 'w' || q.name[2] == 'W') && + q.name[3] == '.') { + handle_a_request(dns_fd, &q, 1); + return 0; + } - switch (q.type) { - case T_NULL: - case T_PRIVATE: - case T_CNAME: - case T_A: - case T_MX: - case T_SRV: - case T_TXT: - /* encoding is "transparent" here */ - handle_null_request(tun_fd, dns_fd, &q, domain_len); - break; - case T_NS: - handle_ns_request(dns_fd, &q); - break; - default: - break; - } - } else { - /* Forward query to other port ? */ - if (bind_fd) { - forward_query(bind_fd, &q); - } - } - return 0; + switch (q.type) { + case T_NULL: + case T_PRIVATE: + case T_CNAME: + case T_A: + case T_MX: + case T_SRV: + case T_TXT: + /* encoding is "transparent" here */ + handle_null_request(tun_fd, dns_fd, &q, domain_len); + break; + case T_NS: + handle_ns_request(dns_fd, &q); + break; + default: + break; + } + } else { + /* Forward query to other port ? */ + if (bind_fd) { + forward_query(bind_fd, &q); + } + } + return 0; } static int tunnel(int tun_fd, int dns_fd, int bind_fd, int max_idle_time) { - struct timeval tv; - fd_set fds; - int i; - int userid; - time_t last_action = time(NULL); + struct timeval tv; + fd_set fds; + int i; + int userid; + time_t last_action = time(NULL); - while (running) { - int maxfd; - tv.tv_sec = 10; /* doesn't really matter */ - tv.tv_usec = 0; + while (running) { + int maxfd; + tv.tv_sec = 10; /* doesn't really matter */ + tv.tv_usec = 0; - /* Adjust timeout if there is anything to send realsoon. - Clients won't be sending new data until we send our ack, - so don't keep them waiting long. This only triggers at - final upstream fragments, which is about once per eight - requests during heavy upstream traffic. - 20msec: ~8 packs every 1/50sec = ~400 DNSreq/sec, - or ~1200bytes every 1/50sec = ~0.5 Mbit/sec upstream */ - for (userid = 0; userid < created_users; userid++) { - if (users[userid].active && !users[userid].disabled && - users[userid].last_pkt + 60 > time(NULL)) { - users[userid].q_sendrealsoon_new = 0; - if (users[userid].q_sendrealsoon.id != 0) { - tv.tv_sec = 0; - tv.tv_usec = 20000; - } - } - } + /* Adjust timeout if there is anything to send realsoon. + Clients won't be sending new data until we send our ack, + so don't keep them waiting long. This only triggers at + final upstream fragments, which is about once per eight + requests during heavy upstream traffic. + 20msec: ~8 packs every 1/50sec = ~400 DNSreq/sec, + or ~1200bytes every 1/50sec = ~0.5 Mbit/sec upstream */ + for (userid = 0; userid < created_users; userid++) { + if (users[userid].active && !users[userid].disabled && + users[userid].last_pkt + 60 > time(NULL)) { + users[userid].q_sendrealsoon_new = 0; + if (users[userid].q_sendrealsoon.id != 0) { + tv.tv_sec = 0; + tv.tv_usec = 20000; + } + } + } - FD_ZERO(&fds); + FD_ZERO(&fds); - FD_SET(dns_fd, &fds); - maxfd = dns_fd; + FD_SET(dns_fd, &fds); + maxfd = dns_fd; - if (bind_fd) { - /* wait for replies from real DNS */ - FD_SET(bind_fd, &fds); - maxfd = MAX(bind_fd, maxfd); - } + if (bind_fd) { + /* wait for replies from real DNS */ + FD_SET(bind_fd, &fds); + maxfd = MAX(bind_fd, maxfd); + } - /* Don't read from tun if no users can accept data anyway; - tun queue/TCP buffers are larger than our outpacket-queues */ - if(!all_users_waiting_to_send()) { - FD_SET(tun_fd, &fds); - maxfd = MAX(tun_fd, maxfd); - } + /* Don't read from tun if no users can accept data anyway; + tun queue/TCP buffers are larger than our outpacket-queues */ + if(!all_users_waiting_to_send()) { + FD_SET(tun_fd, &fds); + maxfd = MAX(tun_fd, maxfd); + } - i = select(maxfd + 1, &fds, NULL, NULL, &tv); + i = select(maxfd + 1, &fds, NULL, NULL, &tv); - if(i < 0) { - if (running) - warn("select"); - return 1; - } + if(i < 0) { + if (running) + warn("select"); + return 1; + } - if (i==0) { - if (max_idle_time) { - /* only trigger the check if that's worth ( ie, no need to loop over if there - is something to send */ - if (last_action + max_idle_time < time(NULL)) { - for (userid = 0; userid < created_users; userid++) { - last_action = ( users[userid].last_pkt > last_action ) ? users[userid].last_pkt : last_action; - } - if (last_action + max_idle_time < time(NULL)) { - fprintf(stderr, "Idling since too long, shutting down...\n"); - running = 0; - } - } - } - } else { - if (FD_ISSET(tun_fd, &fds)) { - tunnel_tun(tun_fd, dns_fd); - } - if (FD_ISSET(dns_fd, &fds)) { - tunnel_dns(tun_fd, dns_fd, bind_fd); - } - if (FD_ISSET(bind_fd, &fds)) { - tunnel_bind(bind_fd, dns_fd); - } - } + if (i==0) { + if (max_idle_time) { + /* only trigger the check if that's worth ( ie, no need to loop over if there + is something to send */ + if (last_action + max_idle_time < time(NULL)) { + for (userid = 0; userid < created_users; userid++) { + last_action = ( users[userid].last_pkt > last_action ) ? users[userid].last_pkt : last_action; + } + if (last_action + max_idle_time < time(NULL)) { + fprintf(stderr, "Idling since too long, shutting down...\n"); + running = 0; + } + } + } + } else { + if (FD_ISSET(tun_fd, &fds)) { + tunnel_tun(tun_fd, dns_fd); + } + if (FD_ISSET(dns_fd, &fds)) { + tunnel_dns(tun_fd, dns_fd, bind_fd); + } + if (FD_ISSET(bind_fd, &fds)) { + tunnel_bind(bind_fd, dns_fd); + } + } - /* Send realsoon's if tun or dns didn't already */ - for (userid = 0; userid < created_users; userid++) - if (users[userid].active && !users[userid].disabled && - users[userid].last_pkt + 60 > time(NULL) && - users[userid].q_sendrealsoon.id != 0 && - users[userid].conn == CONN_DNS_NULL && - !users[userid].q_sendrealsoon_new) - send_chunk_or_dataless(dns_fd, userid, &users[userid].q_sendrealsoon); - } + /* Send realsoon's if tun or dns didn't already */ + for (userid = 0; userid < created_users; userid++) + if (users[userid].active && !users[userid].disabled && + users[userid].last_pkt + 60 > time(NULL) && + users[userid].q_sendrealsoon.id != 0 && + users[userid].conn == CONN_DNS_NULL && + !users[userid].q_sendrealsoon_new) + send_chunk_or_dataless(dns_fd, userid, &users[userid].q_sendrealsoon); + } - return 0; + return 0; } static void handle_full_packet(int tun_fd, int dns_fd, int userid) { - unsigned long outlen; - char out[64*1024]; - int touser; - int ret; + unsigned long outlen; + char out[64*1024]; + int touser; + int ret; - outlen = sizeof(out); - ret = uncompress((uint8_t*)out, &outlen, - (uint8_t*)users[userid].inpacket.data, users[userid].inpacket.len); + outlen = sizeof(out); + ret = uncompress((uint8_t*)out, &outlen, + (uint8_t*)users[userid].inpacket.data, users[userid].inpacket.len); - if (ret == Z_OK) { - struct ip *hdr; + if (ret == Z_OK) { + struct ip *hdr; - hdr = (struct ip*) (out + 4); - touser = find_user_by_ip(hdr->ip_dst.s_addr); + hdr = (struct ip*) (out + 4); + touser = find_user_by_ip(hdr->ip_dst.s_addr); - if (touser == -1) { - /* send the uncompressed packet to tun device */ - write_tun(tun_fd, out, outlen); - } else { - /* send the compressed(!) packet to other client */ - if (users[touser].conn == CONN_DNS_NULL) { - if (users[touser].outpacket.len == 0) { - start_new_outpacket(touser, - users[userid].inpacket.data, - users[userid].inpacket.len); + if (touser == -1) { + /* send the uncompressed packet to tun device */ + write_tun(tun_fd, out, outlen); + } else { + /* send the compressed(!) packet to other client */ + if (users[touser].conn == CONN_DNS_NULL) { + if (users[touser].outpacket.len == 0) { + start_new_outpacket(touser, + users[userid].inpacket.data, + users[userid].inpacket.len); - /* Start sending immediately if query is waiting */ - if (users[touser].q_sendrealsoon.id != 0) - send_chunk_or_dataless(dns_fd, touser, &users[touser].q_sendrealsoon); - else if (users[touser].q.id != 0) - send_chunk_or_dataless(dns_fd, touser, &users[touser].q); + /* Start sending immediately if query is waiting */ + if (users[touser].q_sendrealsoon.id != 0) + send_chunk_or_dataless(dns_fd, touser, &users[touser].q_sendrealsoon); + else if (users[touser].q.id != 0) + send_chunk_or_dataless(dns_fd, touser, &users[touser].q); #ifdef OUTPACKETQ_LEN - } else { - save_to_outpacketq(touser, - users[userid].inpacket.data, - users[userid].inpacket.len); + } else { + save_to_outpacketq(touser, + users[userid].inpacket.data, + users[userid].inpacket.len); #endif - } - } else{ /* CONN_RAW_UDP */ - send_raw(dns_fd, users[userid].inpacket.data, - users[userid].inpacket.len, touser, - RAW_HDR_CMD_DATA, &users[touser].q); - } - } - } else { - if (debug >= 1) - fprintf(stderr, "Discarded data, uncompress() result: %d\n", ret); - } + } + } else{ /* CONN_RAW_UDP */ + send_raw(dns_fd, users[userid].inpacket.data, + users[userid].inpacket.len, touser, + RAW_HDR_CMD_DATA, &users[touser].q); + } + } + } else { + if (debug >= 1) + fprintf(stderr, "Discarded data, uncompress() result: %d\n", ret); + } - /* This packet is done */ - users[userid].inpacket.len = 0; - users[userid].inpacket.offset = 0; + /* This packet is done */ + users[userid].inpacket.len = 0; + users[userid].inpacket.offset = 0; } static void handle_raw_login(char *packet, int len, struct query *q, int fd, int userid) { - char myhash[16]; + char myhash[16]; - if (len < 16) return; + if (len < 16) return; - /* can't use check_authenticated_user_and_ip() since IP address will be different, - so duplicate here except IP address */ - if (userid < 0 || userid >= created_users) return; - if (!users[userid].active || users[userid].disabled) return; - if (!users[userid].authenticated) return; - if (users[userid].last_pkt + 60 < time(NULL)) return; + /* can't use check_authenticated_user_and_ip() since IP address will be different, + so duplicate here except IP address */ + if (userid < 0 || userid >= created_users) return; + if (!users[userid].active || users[userid].disabled) return; + if (!users[userid].authenticated) return; + if (users[userid].last_pkt + 60 < time(NULL)) return; - if (debug >= 1) { - fprintf(stderr, "IN login raw, len %d, from user %d\n", - len, userid); - } + if (debug >= 1) { + fprintf(stderr, "IN login raw, len %d, from user %d\n", + len, userid); + } - /* User sends hash of seed + 1 */ - login_calculate(myhash, 16, password, users[userid].seed + 1); - if (memcmp(packet, myhash, 16) == 0) { - struct sockaddr_in *tempin; + /* User sends hash of seed + 1 */ + login_calculate(myhash, 16, password, users[userid].seed + 1); + if (memcmp(packet, myhash, 16) == 0) { + struct sockaddr_in *tempin; - /* Update query and time info for user */ - users[userid].last_pkt = time(NULL); - memcpy(&(users[userid].q), q, sizeof(struct query)); + /* Update query and time info for user */ + users[userid].last_pkt = time(NULL); + memcpy(&(users[userid].q), q, sizeof(struct query)); - /* Store remote IP number */ - tempin = (struct sockaddr_in *) &(q->from); - memcpy(&(users[userid].host), &(tempin->sin_addr), sizeof(struct in_addr)); + /* Store remote IP number */ + tempin = (struct sockaddr_in *) &(q->from); + memcpy(&(users[userid].host), &(tempin->sin_addr), sizeof(struct in_addr)); - /* Correct hash, reply with hash of seed - 1 */ - user_set_conn_type(userid, CONN_RAW_UDP); - login_calculate(myhash, 16, password, users[userid].seed - 1); - send_raw(fd, myhash, 16, userid, RAW_HDR_CMD_LOGIN, q); + /* Correct hash, reply with hash of seed - 1 */ + user_set_conn_type(userid, CONN_RAW_UDP); + login_calculate(myhash, 16, password, users[userid].seed - 1); + send_raw(fd, myhash, 16, userid, RAW_HDR_CMD_LOGIN, q); - users[userid].authenticated_raw = 1; - } + users[userid].authenticated_raw = 1; + } } static void handle_raw_data(char *packet, int len, struct query *q, int dns_fd, int tun_fd, int userid) { - if (check_authenticated_user_and_ip(userid, q) != 0) { - return; - } - if (!users[userid].authenticated_raw) return; + if (check_authenticated_user_and_ip(userid, q) != 0) { + return; + } + if (!users[userid].authenticated_raw) return; - /* Update query and time info for user */ - users[userid].last_pkt = time(NULL); - memcpy(&(users[userid].q), q, sizeof(struct query)); + /* Update query and time info for user */ + users[userid].last_pkt = time(NULL); + memcpy(&(users[userid].q), q, sizeof(struct query)); - /* copy to packet buffer, update length */ - users[userid].inpacket.offset = 0; - memcpy(users[userid].inpacket.data, packet, len); - users[userid].inpacket.len = len; + /* copy to packet buffer, update length */ + users[userid].inpacket.offset = 0; + memcpy(users[userid].inpacket.data, packet, len); + users[userid].inpacket.len = len; - if (debug >= 1) { - fprintf(stderr, "IN pkt raw, total %d, from user %d\n", - users[userid].inpacket.len, userid); - } + if (debug >= 1) { + fprintf(stderr, "IN pkt raw, total %d, from user %d\n", + users[userid].inpacket.len, userid); + } - handle_full_packet(tun_fd, dns_fd, userid); + handle_full_packet(tun_fd, dns_fd, userid); } static void handle_raw_ping(struct query *q, int dns_fd, int userid) { - if (check_authenticated_user_and_ip(userid, q) != 0) { - return; - } - if (!users[userid].authenticated_raw) return; + if (check_authenticated_user_and_ip(userid, q) != 0) { + return; + } + if (!users[userid].authenticated_raw) return; - /* Update query and time info for user */ - users[userid].last_pkt = time(NULL); - memcpy(&(users[userid].q), q, sizeof(struct query)); + /* Update query and time info for user */ + users[userid].last_pkt = time(NULL); + memcpy(&(users[userid].q), q, sizeof(struct query)); - if (debug >= 1) { - fprintf(stderr, "IN ping raw, from user %d\n", userid); - } + if (debug >= 1) { + fprintf(stderr, "IN ping raw, from user %d\n", userid); + } - /* Send ping reply */ - send_raw(dns_fd, NULL, 0, userid, RAW_HDR_CMD_PING, q); + /* Send ping reply */ + send_raw(dns_fd, NULL, 0, userid, RAW_HDR_CMD_PING, q); } static int raw_decode(char *packet, int len, struct query *q, int dns_fd, int tun_fd) { - int raw_user; + int raw_user; - /* minimum length */ - if (len < RAW_HDR_LEN) return 0; - /* should start with header */ - if (memcmp(packet, raw_header, RAW_HDR_IDENT_LEN)) return 0; + /* minimum length */ + if (len < RAW_HDR_LEN) return 0; + /* should start with header */ + if (memcmp(packet, raw_header, RAW_HDR_IDENT_LEN)) return 0; - raw_user = RAW_HDR_GET_USR(packet); - switch (RAW_HDR_GET_CMD(packet)) { - case RAW_HDR_CMD_LOGIN: - /* Login challenge */ - handle_raw_login(&packet[RAW_HDR_LEN], len - RAW_HDR_LEN, q, dns_fd, raw_user); - break; - case RAW_HDR_CMD_DATA: - /* Data packet */ - handle_raw_data(&packet[RAW_HDR_LEN], len - RAW_HDR_LEN, q, dns_fd, tun_fd, raw_user); - break; - case RAW_HDR_CMD_PING: - /* Keepalive packet */ - handle_raw_ping(q, dns_fd, raw_user); - break; - default: - warnx("Unhandled raw command %02X from user %d", RAW_HDR_GET_CMD(packet), raw_user); - break; - } - return 1; + raw_user = RAW_HDR_GET_USR(packet); + switch (RAW_HDR_GET_CMD(packet)) { + case RAW_HDR_CMD_LOGIN: + /* Login challenge */ + handle_raw_login(&packet[RAW_HDR_LEN], len - RAW_HDR_LEN, q, dns_fd, raw_user); + break; + case RAW_HDR_CMD_DATA: + /* Data packet */ + handle_raw_data(&packet[RAW_HDR_LEN], len - RAW_HDR_LEN, q, dns_fd, tun_fd, raw_user); + break; + case RAW_HDR_CMD_PING: + /* Keepalive packet */ + handle_raw_ping(q, dns_fd, raw_user); + break; + default: + warnx("Unhandled raw command %02X from user %d", RAW_HDR_GET_CMD(packet), raw_user); + break; + } + return 1; } static int read_dns(int fd, int tun_fd, struct query *q) /* FIXME: tun_fd is because of raw_decode() below */ { - struct sockaddr_in from; - socklen_t addrlen; - char packet[64*1024]; - int r; + struct sockaddr_in from; + socklen_t addrlen; + char packet[64*1024]; + int r; #ifndef WINDOWS32 - char address[96]; - struct msghdr msg; - struct iovec iov; - struct cmsghdr *cmsg; + char address[96]; + struct msghdr msg; + struct iovec iov; + struct cmsghdr *cmsg; - addrlen = sizeof(struct sockaddr); - iov.iov_base = packet; - iov.iov_len = sizeof(packet); + addrlen = sizeof(struct sockaddr); + iov.iov_base = packet; + iov.iov_len = sizeof(packet); - msg.msg_name = (caddr_t) &from; - msg.msg_namelen = (unsigned) addrlen; - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_control = address; - msg.msg_controllen = sizeof(address); - msg.msg_flags = 0; + msg.msg_name = (caddr_t) &from; + msg.msg_namelen = (unsigned) addrlen; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = address; + msg.msg_controllen = sizeof(address); + msg.msg_flags = 0; - r = recvmsg(fd, &msg, 0); + r = recvmsg(fd, &msg, 0); #else - addrlen = sizeof(struct sockaddr); - r = recvfrom(fd, packet, sizeof(packet), 0, (struct sockaddr*)&from, &addrlen); + addrlen = sizeof(struct sockaddr); + r = recvfrom(fd, packet, sizeof(packet), 0, (struct sockaddr*)&from, &addrlen); #endif /* !WINDOWS32 */ - if (r > 0) { - memcpy((struct sockaddr*)&q->from, (struct sockaddr*)&from, addrlen); - q->fromlen = addrlen; + if (r > 0) { + memcpy((struct sockaddr*)&q->from, (struct sockaddr*)&from, addrlen); + q->fromlen = addrlen; - /* TODO do not handle raw packets here! */ - if (raw_decode(packet, r, q, fd, tun_fd)) { - return 0; - } - if (dns_decode(NULL, 0, q, QR_QUERY, packet, r) < 0) { - return 0; - } + /* TODO do not handle raw packets here! */ + if (raw_decode(packet, r, q, fd, tun_fd)) { + return 0; + } + if (dns_decode(NULL, 0, q, QR_QUERY, packet, r) < 0) { + return 0; + } #ifndef WINDOWS32 - for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; - cmsg = CMSG_NXTHDR(&msg, cmsg)) { + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; + cmsg = CMSG_NXTHDR(&msg, cmsg)) { - if (cmsg->cmsg_level == IPPROTO_IP && - cmsg->cmsg_type == DSTADDR_SOCKOPT) { + if (cmsg->cmsg_level == IPPROTO_IP && + cmsg->cmsg_type == DSTADDR_SOCKOPT) { - q->destination = *dstaddr(cmsg); - break; - } - } + q->destination = *dstaddr(cmsg); + break; + } + } #endif - return strlen(q->name); - } else if (r < 0) { - /* Error */ - warn("read dns"); - } + return strlen(q->name); + } else if (r < 0) { + /* Error */ + warn("read dns"); + } - return 0; + return 0; } static size_t write_dns_nameenc(char *buf, size_t buflen, char *data, int datalen, char downenc) /* Returns #bytes of data that were encoded */ { - static int td1 = 0; - static int td2 = 0; - size_t space; - char *b; + static int td1 = 0; + static int td2 = 0; + size_t space; + char *b; - /* Make a rotating topdomain to prevent filtering */ - td1+=3; - td2+=7; - if (td1>=26) td1-=26; - if (td2>=25) td2-=25; + /* Make a rotating topdomain to prevent filtering */ + td1+=3; + td2+=7; + if (td1>=26) td1-=26; + if (td2>=25) td2-=25; - /* encode data,datalen to CNAME/MX answer - (adapted from build_hostname() in encoding.c) - */ + /* encode data,datalen to CNAME/MX answer + (adapted from build_hostname() in encoding.c) + */ - space = MIN(0xFF, buflen) - 4 - 2; - /* -1 encoding type, -3 ".xy", -2 for safety */ + space = MIN(0xFF, buflen) - 4 - 2; + /* -1 encoding type, -3 ".xy", -2 for safety */ - memset(buf, 0, buflen); + memset(buf, 0, buflen); - if (downenc == 'S') { - buf[0] = 'i'; - if (!b64->places_dots()) - space -= (space / 57); /* space for dots */ - b64->encode(buf+1, &space, data, datalen); - if (!b64->places_dots()) - inline_dotify(buf, buflen); - } else if (downenc == 'U') { - buf[0] = 'j'; - if (!b64u->places_dots()) - space -= (space / 57); /* space for dots */ - b64u->encode(buf+1, &space, data, datalen); - if (!b64u->places_dots()) - inline_dotify(buf, buflen); - } else if (downenc == 'V') { - buf[0] = 'k'; - if (!b128->places_dots()) - space -= (space / 57); /* space for dots */ - b128->encode(buf+1, &space, data, datalen); - if (!b128->places_dots()) - inline_dotify(buf, buflen); - } else { - buf[0] = 'h'; - if (!b32->places_dots()) - space -= (space / 57); /* space for dots */ - b32->encode(buf+1, &space, data, datalen); - if (!b32->places_dots()) - inline_dotify(buf, buflen); - } + if (downenc == 'S') { + buf[0] = 'i'; + if (!b64->places_dots()) + space -= (space / 57); /* space for dots */ + b64->encode(buf+1, &space, data, datalen); + if (!b64->places_dots()) + inline_dotify(buf, buflen); + } else if (downenc == 'U') { + buf[0] = 'j'; + if (!b64u->places_dots()) + space -= (space / 57); /* space for dots */ + b64u->encode(buf+1, &space, data, datalen); + if (!b64u->places_dots()) + inline_dotify(buf, buflen); + } else if (downenc == 'V') { + buf[0] = 'k'; + if (!b128->places_dots()) + space -= (space / 57); /* space for dots */ + b128->encode(buf+1, &space, data, datalen); + if (!b128->places_dots()) + inline_dotify(buf, buflen); + } else { + buf[0] = 'h'; + if (!b32->places_dots()) + space -= (space / 57); /* space for dots */ + b32->encode(buf+1, &space, data, datalen); + if (!b32->places_dots()) + inline_dotify(buf, buflen); + } - /* Add dot (if it wasn't there already) and topdomain */ - b = buf; - b += strlen(buf) - 1; - if (*b != '.') - *++b = '.'; + /* Add dot (if it wasn't there already) and topdomain */ + b = buf; + b += strlen(buf) - 1; + if (*b != '.') + *++b = '.'; b++; - *b = 'a' + td1; - b++; - *b = 'a' + td2; - b++; - *b = '\0'; + *b = 'a' + td1; + b++; + *b = 'a' + td2; + b++; + *b = '\0'; - return space; + return space; } static void write_dns(int fd, struct query *q, char *data, int datalen, char downenc) { - char buf[64*1024]; - int len = 0; + char buf[64*1024]; + int len = 0; - if (q->type == T_CNAME || q->type == T_A) { - char cnamebuf[1024]; /* max 255 */ + if (q->type == T_CNAME || q->type == T_A) { + char cnamebuf[1024]; /* max 255 */ - write_dns_nameenc(cnamebuf, sizeof(cnamebuf), - data, datalen, downenc); + write_dns_nameenc(cnamebuf, sizeof(cnamebuf), + data, datalen, downenc); - len = dns_encode(buf, sizeof(buf), q, QR_ANSWER, cnamebuf, - sizeof(cnamebuf)); - } else if (q->type == T_MX || q->type == T_SRV) { - char mxbuf[64*1024]; - char *b = mxbuf; - int offset = 0; - int res; + len = dns_encode(buf, sizeof(buf), q, QR_ANSWER, cnamebuf, + sizeof(cnamebuf)); + } else if (q->type == T_MX || q->type == T_SRV) { + char mxbuf[64*1024]; + char *b = mxbuf; + int offset = 0; + int res; - while (1) { - res = write_dns_nameenc(b, sizeof(mxbuf) - (b - mxbuf), - data + offset, - datalen - offset, downenc); - if (res < 1) { - /* nothing encoded */ - b++; /* for final \0 */ - break; - } + while (1) { + res = write_dns_nameenc(b, sizeof(mxbuf) - (b - mxbuf), + data + offset, + datalen - offset, downenc); + if (res < 1) { + /* nothing encoded */ + b++; /* for final \0 */ + break; + } - b = b + strlen(b) + 1; + b = b + strlen(b) + 1; - offset += res; - if (offset >= datalen) - break; - } + offset += res; + if (offset >= datalen) + break; + } - /* Add final \0 */ - *b = '\0'; + /* Add final \0 */ + *b = '\0'; - len = dns_encode(buf, sizeof(buf), q, QR_ANSWER, mxbuf, - sizeof(mxbuf)); - } else if (q->type == T_TXT) { - /* TXT with base32 */ - char txtbuf[64*1024]; - size_t space = sizeof(txtbuf) - 1;; + len = dns_encode(buf, sizeof(buf), q, QR_ANSWER, mxbuf, + sizeof(mxbuf)); + } else if (q->type == T_TXT) { + /* TXT with base32 */ + char txtbuf[64*1024]; + size_t space = sizeof(txtbuf) - 1;; - memset(txtbuf, 0, sizeof(txtbuf)); + memset(txtbuf, 0, sizeof(txtbuf)); - if (downenc == 'S') { - txtbuf[0] = 's'; /* plain base64(Sixty-four) */ - len = b64->encode(txtbuf+1, &space, data, datalen); - } - else if (downenc == 'U') { - txtbuf[0] = 'u'; /* Base64 with Underscore */ - len = b64u->encode(txtbuf+1, &space, data, datalen); - } - else if (downenc == 'V') { - txtbuf[0] = 'v'; /* Base128 */ - len = b128->encode(txtbuf+1, &space, data, datalen); - } - else if (downenc == 'R') { - txtbuf[0] = 'r'; /* Raw binary data */ - len = MIN(datalen, sizeof(txtbuf) - 1); - memcpy(txtbuf + 1, data, len); - } else { - txtbuf[0] = 't'; /* plain base32(Thirty-two) */ - len = b32->encode(txtbuf+1, &space, data, datalen); - } - len = dns_encode(buf, sizeof(buf), q, QR_ANSWER, txtbuf, len+1); - } else { - /* Normal NULL-record encode */ - len = dns_encode(buf, sizeof(buf), q, QR_ANSWER, data, datalen); - } + if (downenc == 'S') { + txtbuf[0] = 's'; /* plain base64(Sixty-four) */ + len = b64->encode(txtbuf+1, &space, data, datalen); + } + else if (downenc == 'U') { + txtbuf[0] = 'u'; /* Base64 with Underscore */ + len = b64u->encode(txtbuf+1, &space, data, datalen); + } + else if (downenc == 'V') { + txtbuf[0] = 'v'; /* Base128 */ + len = b128->encode(txtbuf+1, &space, data, datalen); + } + else if (downenc == 'R') { + txtbuf[0] = 'r'; /* Raw binary data */ + len = MIN(datalen, sizeof(txtbuf) - 1); + memcpy(txtbuf + 1, data, len); + } else { + txtbuf[0] = 't'; /* plain base32(Thirty-two) */ + len = b32->encode(txtbuf+1, &space, data, datalen); + } + len = dns_encode(buf, sizeof(buf), q, QR_ANSWER, txtbuf, len+1); + } else { + /* Normal NULL-record encode */ + len = dns_encode(buf, sizeof(buf), q, QR_ANSWER, data, datalen); + } - if (len < 1) { - warnx("dns_encode doesn't fit"); - return; - } + if (len < 1) { + warnx("dns_encode doesn't fit"); + return; + } - if (debug >= 2) { - fprintf(stderr, "TX: client %s, type %d, name %s, %d bytes data\n", - format_addr(&q->from, q->fromlen), q->type, q->name, datalen); - } + if (debug >= 2) { + fprintf(stderr, "TX: client %s, type %d, name %s, %d bytes data\n", + format_addr(&q->from, q->fromlen), q->type, q->name, datalen); + } - sendto(fd, buf, len, 0, (struct sockaddr*)&q->from, q->fromlen); + sendto(fd, buf, len, 0, (struct sockaddr*)&q->from, q->fromlen); } static void usage() { - extern char *__progname; + extern char *__progname; - fprintf(stderr, "Usage: %s [-v] [-h] [-c] [-s] [-f] [-D] [-u user] " - "[-t chrootdir] [-d device] [-m mtu] [-z context] " - "[-l ip address to listen on] [-p port] [-n external ip] " - "[-b dnsport] [-P password] [-F pidfile] [-i max idle time] " - "tunnel_ip[/netmask] topdomain\n", __progname); - exit(2); + fprintf(stderr, "Usage: %s [-v] [-h] [-c] [-s] [-f] [-D] [-u user] " + "[-t chrootdir] [-d device] [-m mtu] [-z context] " + "[-l ip address to listen on] [-p port] [-n external ip] " + "[-b dnsport] [-P password] [-F pidfile] [-i max idle time] " + "tunnel_ip[/netmask] topdomain\n", __progname); + exit(2); } static void help() { - extern char *__progname; + extern char *__progname; - fprintf(stderr, "iodine IP over DNS tunneling server\n"); - fprintf(stderr, "Usage: %s [-v] [-h] [-c] [-s] [-f] [-D] [-u user] " - "[-t chrootdir] [-d device] [-m mtu] [-z context] " - "[-l ip address to listen on] [-p port] [-n external ip] [-b dnsport] [-P password] " - "[-F pidfile] tunnel_ip[/netmask] topdomain\n", __progname); - fprintf(stderr, " -v to print version info and exit\n"); - fprintf(stderr, " -h to print this help and exit\n"); - fprintf(stderr, " -c to disable check of client IP/port on each request\n"); - fprintf(stderr, " -s to skip creating and configuring the tun device, " - "which then has to be created manually\n"); - fprintf(stderr, " -f to keep running in foreground\n"); - fprintf(stderr, " -D to increase debug level\n"); - fprintf(stderr, " (using -DD in UTF-8 terminal: \"LC_ALL=C luit iodined -DD ...\")\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, " -m mtu to set tunnel device mtu\n"); - fprintf(stderr, " -z context to apply SELinux context after initialization\n"); - fprintf(stderr, " -l ip address to listen on for incoming dns traffic " - "(default 0.0.0.0)\n"); - fprintf(stderr, " -p port to listen on for incoming dns traffic (default 53)\n"); - fprintf(stderr, " -n ip to respond with to NS queries\n"); - fprintf(stderr, " -b port to forward normal DNS queries to (on localhost)\n"); - fprintf(stderr, " -P password used for authentication (max 32 chars will be used)\n"); - fprintf(stderr, " -F pidfile to write pid to a file\n"); - fprintf(stderr, " -i maximum idle time before shutting down\n"); - fprintf(stderr, "tunnel_ip is the IP number of the local tunnel interface.\n"); - fprintf(stderr, " /netmask sets the size of the tunnel network.\n"); - fprintf(stderr, "topdomain is the FQDN that is delegated to this server.\n"); - exit(0); + fprintf(stderr, "iodine IP over DNS tunneling server\n"); + fprintf(stderr, "Usage: %s [-v] [-h] [-c] [-s] [-f] [-D] [-u user] " + "[-t chrootdir] [-d device] [-m mtu] [-z context] " + "[-l ip address to listen on] [-p port] [-n external ip] [-b dnsport] [-P password] " + "[-F pidfile] tunnel_ip[/netmask] topdomain\n", __progname); + fprintf(stderr, " -v to print version info and exit\n"); + fprintf(stderr, " -h to print this help and exit\n"); + fprintf(stderr, " -c to disable check of client IP/port on each request\n"); + fprintf(stderr, " -s to skip creating and configuring the tun device, " + "which then has to be created manually\n"); + fprintf(stderr, " -f to keep running in foreground\n"); + fprintf(stderr, " -D to increase debug level\n"); + fprintf(stderr, " (using -DD in UTF-8 terminal: \"LC_ALL=C luit iodined -DD ...\")\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, " -m mtu to set tunnel device mtu\n"); + fprintf(stderr, " -z context to apply SELinux context after initialization\n"); + fprintf(stderr, " -l ip address to listen on for incoming dns traffic " + "(default 0.0.0.0)\n"); + fprintf(stderr, " -p port to listen on for incoming dns traffic (default 53)\n"); + fprintf(stderr, " -n ip to respond with to NS queries\n"); + fprintf(stderr, " -b port to forward normal DNS queries to (on localhost)\n"); + fprintf(stderr, " -P password used for authentication (max 32 chars will be used)\n"); + fprintf(stderr, " -F pidfile to write pid to a file\n"); + fprintf(stderr, " -i maximum idle time before shutting down\n"); + fprintf(stderr, "tunnel_ip is the IP number of the local tunnel interface.\n"); + fprintf(stderr, " /netmask sets the size of the tunnel network.\n"); + fprintf(stderr, "topdomain is the FQDN that is delegated to this server.\n"); + exit(0); } static void version() { - fprintf(stderr, "iodine IP over DNS tunneling server\n"); - fprintf(stderr, "Git version: %s\n", GITREVISION); - exit(0); + fprintf(stderr, "iodine IP over DNS tunneling server\n"); + fprintf(stderr, "Git version: %s\n", GITREVISION); + exit(0); } int main(int argc, char **argv) { - extern char *__progname; - char *listen_ip; - char *errormsg; + extern char *__progname; + char *listen_ip; + char *errormsg; #ifndef WINDOWS32 - struct passwd *pw; + struct passwd *pw; #endif - int foreground; - char *username; - char *newroot; - char *context; - char *device; - char *pidfile; - int dnsd_fd; - int tun_fd; + int foreground; + char *username; + char *newroot; + char *context; + char *device; + char *pidfile; + int dnsd_fd; + int tun_fd; - /* settings for forwarding normal DNS to - * local real DNS server */ - int bind_fd; - int bind_enable; + /* settings for forwarding normal DNS to + * local real DNS server */ + int bind_fd; + int bind_enable; - int choice; - int port; - int mtu; - int skipipconfig; - char *netsize; - int ns_get_externalip; - int retval; - int max_idle_time = 0; - struct sockaddr_storage dnsaddr; - int dnsaddr_len; + int choice; + int port; + int mtu; + int skipipconfig; + char *netsize; + int ns_get_externalip; + int retval; + int max_idle_time = 0; + struct sockaddr_storage dnsaddr; + int dnsaddr_len; #ifdef HAVE_SYSTEMD - int nb_fds; + int nb_fds; #endif #ifndef WINDOWS32 - pw = NULL; + pw = NULL; #endif - errormsg = NULL; - username = NULL; - newroot = NULL; - context = NULL; - device = NULL; - foreground = 0; - bind_enable = 0; - bind_fd = 0; - mtu = 1130; /* Very many relays give fragsize 1150 or slightly - higher for NULL; tun/zlib adds ~17 bytes. */ - listen_ip = NULL; - port = 53; - ns_ip = INADDR_ANY; - ns_get_externalip = 0; - check_ip = 1; - skipipconfig = 0; - debug = 0; - netmask = 27; - pidfile = NULL; + errormsg = NULL; + username = NULL; + newroot = NULL; + context = NULL; + device = NULL; + foreground = 0; + bind_enable = 0; + bind_fd = 0; + mtu = 1130; /* Very many relays give fragsize 1150 or slightly + higher for NULL; tun/zlib adds ~17 bytes. */ + listen_ip = NULL; + port = 53; + ns_ip = INADDR_ANY; + ns_get_externalip = 0; + check_ip = 1; + skipipconfig = 0; + debug = 0; + netmask = 27; + pidfile = NULL; - b32 = get_base32_encoder(); - b64 = get_base64_encoder(); - b64u = get_base64u_encoder(); - b128 = get_base128_encoder(); + b32 = get_base32_encoder(); + b64 = get_base64_encoder(); + b64u = get_base64u_encoder(); + b128 = get_base128_encoder(); - retval = 0; + retval = 0; #ifdef WINDOWS32 - WSAStartup(req_version, &wsa_data); + WSAStartup(req_version, &wsa_data); #endif #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 - memset(password, 0, sizeof(password)); - srand(time(NULL)); - fw_query_init(); + memset(password, 0, sizeof(password)); + srand(time(NULL)); + fw_query_init(); - while ((choice = getopt(argc, argv, "vcsfhDu:t:d:m:l:p:n:b:P:z:F:i:")) != -1) { - switch(choice) { - case 'v': - version(); - break; - case 'c': - check_ip = 0; - break; - case 's': - skipipconfig = 1; - break; - case 'f': - foreground = 1; - break; - case 'h': - help(); - break; - case 'D': - debug++; - break; - case 'u': - username = optarg; - break; - case 't': - newroot = optarg; - break; - case 'd': - device = optarg; - break; - case 'm': - mtu = atoi(optarg); - break; - case 'l': - listen_ip = optarg; - break; - case 'p': - port = atoi(optarg); - break; - case 'n': - if (optarg && strcmp("auto", optarg) == 0) { - ns_get_externalip = 1; - } else { - ns_ip = inet_addr(optarg); - } - break; - case 'b': - bind_enable = 1; - bind_port = atoi(optarg); - break; - case 'F': - pidfile = optarg; - break; - case 'i': - max_idle_time = atoi(optarg); - break; - case 'P': - strncpy(password, optarg, sizeof(password)); - password[sizeof(password)-1] = 0; + while ((choice = getopt(argc, argv, "vcsfhDu:t:d:m:l:p:n:b:P:z:F:i:")) != -1) { + switch(choice) { + case 'v': + version(); + break; + case 'c': + check_ip = 0; + break; + case 's': + skipipconfig = 1; + break; + case 'f': + foreground = 1; + break; + case 'h': + help(); + break; + case 'D': + debug++; + break; + case 'u': + username = optarg; + break; + case 't': + newroot = optarg; + break; + case 'd': + device = optarg; + break; + case 'm': + mtu = atoi(optarg); + break; + case 'l': + listen_ip = optarg; + break; + case 'p': + port = atoi(optarg); + break; + case 'n': + if (optarg && strcmp("auto", optarg) == 0) { + ns_get_externalip = 1; + } else { + ns_ip = inet_addr(optarg); + } + break; + case 'b': + bind_enable = 1; + bind_port = atoi(optarg); + break; + case 'F': + pidfile = optarg; + break; + case 'i': + max_idle_time = atoi(optarg); + break; + 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 'z': - context = optarg; - break; - default: - usage(); - break; - } - } + /* XXX: find better way of cleaning up ps(1) */ + memset(optarg, 0, strlen(optarg)); + break; + case 'z': + context = optarg; + break; + default: + usage(); + break; + } + } - argc -= optind; - argv += optind; + argc -= optind; + argv += optind; - check_superuser(usage); + check_superuser(usage); - if (argc != 2) - usage(); + if (argc != 2) + usage(); - netsize = strchr(argv[0], '/'); - if (netsize) { - *netsize = 0; - netsize++; - netmask = atoi(netsize); - } + netsize = strchr(argv[0], '/'); + if (netsize) { + *netsize = 0; + netsize++; + netmask = atoi(netsize); + } - my_ip = inet_addr(argv[0]); + my_ip = inet_addr(argv[0]); - if (my_ip == INADDR_NONE) { - warnx("Bad IP address to use inside tunnel."); - usage(); - } + if (my_ip == INADDR_NONE) { + warnx("Bad IP address to use inside tunnel."); + usage(); + } - topdomain = strdup(argv[1]); - if(check_topdomain(topdomain, &errormsg)) { - warnx("Invalid topdomain: %s", errormsg); - usage(); - /* NOTREACHED */ - } + topdomain = strdup(argv[1]); + if(check_topdomain(topdomain, &errormsg)) { + warnx("Invalid topdomain: %s", errormsg); + usage(); + /* NOTREACHED */ + } - if (username != NULL) { + if (username != NULL) { #ifndef WINDOWS32 - if ((pw = getpwnam(username)) == NULL) { - warnx("User %s does not exist!", username); - usage(); - } + if ((pw = getpwnam(username)) == NULL) { + warnx("User %s does not exist!", username); + usage(); + } #endif - } + } - if (mtu <= 0) { - warnx("Bad MTU given."); - usage(); - } + if (mtu <= 0) { + warnx("Bad MTU given."); + usage(); + } - if(port < 1 || port > 65535) { - warnx("Bad port number given."); - usage(); - } + if(port < 1 || port > 65535) { + warnx("Bad port number given."); + usage(); + } - if (port != 53) { - fprintf(stderr, "ALERT! Other dns servers expect you to run on port 53.\n"); - fprintf(stderr, "You must manually forward port 53 to port %d for things to work.\n", port); - } + if (port != 53) { + fprintf(stderr, "ALERT! Other dns servers expect you to run on port 53.\n"); + fprintf(stderr, "You must manually forward port 53 to port %d for things to work.\n", port); + } - if (debug) { - fprintf(stderr, "Debug level %d enabled, will stay in foreground.\n", debug); - fprintf(stderr, "Add more -D switches to set higher debug level.\n"); - foreground = 1; - } + if (debug) { + fprintf(stderr, "Debug level %d enabled, will stay in foreground.\n", debug); + fprintf(stderr, "Add more -D switches to set higher debug level.\n"); + foreground = 1; + } - dnsaddr_len = get_addr(listen_ip, port, AF_INET, AI_PASSIVE | AI_NUMERICHOST, &dnsaddr); - if (dnsaddr_len < 0) { - warnx("Bad IP address to listen on."); - usage(); - } + dnsaddr_len = get_addr(listen_ip, port, AF_INET, AI_PASSIVE | AI_NUMERICHOST, &dnsaddr); + if (dnsaddr_len < 0) { + warnx("Bad IP address to listen on."); + usage(); + } - if(bind_enable) { - in_addr_t dns_ip = ((struct sockaddr_in *) &dnsaddr)->sin_addr.s_addr; - if (bind_port < 1 || bind_port > 65535) { - warnx("Bad DNS server port number given."); - usage(); - /* NOTREACHED */ - } - /* Avoid forwarding loops */ - if (bind_port == port && (dns_ip == INADDR_ANY || dns_ip == htonl(0x7f000001L))) { - warnx("Forward port is same as listen port (%d), will create a loop!", bind_port); - fprintf(stderr, "Use -l to set listen ip to avoid this.\n"); - usage(); - /* NOTREACHED */ - } - fprintf(stderr, "Requests for domains outside of %s will be forwarded to port %d\n", - topdomain, bind_port); - } + if(bind_enable) { + in_addr_t dns_ip = ((struct sockaddr_in *) &dnsaddr)->sin_addr.s_addr; + if (bind_port < 1 || bind_port > 65535) { + warnx("Bad DNS server port number given."); + usage(); + /* NOTREACHED */ + } + /* Avoid forwarding loops */ + if (bind_port == port && (dns_ip == INADDR_ANY || dns_ip == htonl(0x7f000001L))) { + warnx("Forward port is same as listen port (%d), will create a loop!", bind_port); + fprintf(stderr, "Use -l to set listen ip to avoid this.\n"); + usage(); + /* NOTREACHED */ + } + fprintf(stderr, "Requests for domains outside of %s will be forwarded to port %d\n", + topdomain, bind_port); + } - if (ns_get_externalip) { - struct in_addr extip; - int res = get_external_ip(&extip); - if (res) { - fprintf(stderr, "Failed to get external IP via web service.\n"); - exit(3); - } - ns_ip = extip.s_addr; - fprintf(stderr, "Using %s as external IP.\n", inet_ntoa(extip)); - } + if (ns_get_externalip) { + struct in_addr extip; + int res = get_external_ip(&extip); + if (res) { + fprintf(stderr, "Failed to get external IP via web service.\n"); + exit(3); + } + ns_ip = extip.s_addr; + fprintf(stderr, "Using %s as external IP.\n", inet_ntoa(extip)); + } - if (ns_ip == INADDR_NONE) { - warnx("Bad IP address to return as nameserver."); - usage(); - } - if (netmask > 30 || netmask < 8) { - warnx("Bad netmask (%d bits). Use 8-30 bits.", netmask); - usage(); - } + if (ns_ip == INADDR_NONE) { + warnx("Bad IP address to return as nameserver."); + usage(); + } + if (netmask > 30 || netmask < 8) { + warnx("Bad netmask (%d bits). Use 8-30 bits.", netmask); + usage(); + } - 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)); + } - created_users = init_users(my_ip, netmask); + created_users = init_users(my_ip, netmask); - if ((tun_fd = open_tun(device)) == -1) { - retval = 1; - goto cleanup0; - } - if (!skipipconfig) { - const char *other_ip = users_get_first_ip(); - if (tun_setip(argv[0], other_ip, netmask) != 0 || tun_setmtu(mtu) != 0) { - retval = 1; - free((void*) other_ip); - goto cleanup1; - } - free((void*) other_ip); - } + if ((tun_fd = open_tun(device)) == -1) { + retval = 1; + goto cleanup0; + } + if (!skipipconfig) { + const char *other_ip = users_get_first_ip(); + if (tun_setip(argv[0], other_ip, netmask) != 0 || tun_setmtu(mtu) != 0) { + retval = 1; + free((void*) other_ip); + goto cleanup1; + } + free((void*) other_ip); + } #ifdef HAVE_SYSTEMD - nb_fds = sd_listen_fds(0); - if (nb_fds > 1) { - retval = 1; - warnx("Too many file descriptors received!\n"); - goto cleanup1; - } else if (nb_fds == 1) { - dnsd_fd = SD_LISTEN_FDS_START; - } else { + nb_fds = sd_listen_fds(0); + if (nb_fds > 1) { + retval = 1; + warnx("Too many file descriptors received!\n"); + goto cleanup1; + } else if (nb_fds == 1) { + dnsd_fd = SD_LISTEN_FDS_START; + } else { #endif - if ((dnsd_fd = open_dns(&dnsaddr, dnsaddr_len)) < 0) { - retval = 1; - goto cleanup2; - } + if ((dnsd_fd = open_dns(&dnsaddr, dnsaddr_len)) < 0) { + retval = 1; + goto cleanup2; + } #ifdef HAVE_SYSTEMD - } + } #endif - if (bind_enable) { - if ((bind_fd = open_dns_from_host(NULL, 0, AF_INET, 0)) < 0) { - retval = 1; - goto cleanup3; - } - } + if (bind_enable) { + if ((bind_fd = open_dns_from_host(NULL, 0, AF_INET, 0)) < 0) { + retval = 1; + goto cleanup3; + } + } - my_mtu = mtu; + my_mtu = mtu; - if (created_users < USERS) { - fprintf(stderr, "Limiting to %d simultaneous users because of netmask /%d\n", - created_users, netmask); - } - fprintf(stderr, "Listening to dns for domain %s\n", topdomain); + if (created_users < USERS) { + fprintf(stderr, "Limiting to %d simultaneous users because of netmask /%d\n", + created_users, netmask); + } + fprintf(stderr, "Listening to dns for domain %s\n", topdomain); - if (foreground == 0) - do_detach(); + if (foreground == 0) + do_detach(); - if (pidfile != NULL) - do_pidfile(pidfile); + if (pidfile != NULL) + do_pidfile(pidfile); #ifdef FREEBSD - tzsetwall(); + tzsetwall(); #endif #ifndef WINDOWS32 - openlog( __progname, LOG_NDELAY, LOG_DAEMON ); + openlog( __progname, LOG_NDELAY, LOG_DAEMON ); #endif - if (newroot != NULL) - do_chroot(newroot); + if (newroot != NULL) + do_chroot(newroot); - signal(SIGINT, sigint); - if (username != NULL) { + signal(SIGINT, sigint); + 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(); - } + 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(); + } #endif - } + } - if (context != NULL) - do_setcon(context); + if (context != NULL) + do_setcon(context); - syslog(LOG_INFO, "started, listening on port %d", port); + syslog(LOG_INFO, "started, listening on port %d", port); - tunnel(tun_fd, dnsd_fd, bind_fd, max_idle_time); + tunnel(tun_fd, dnsd_fd, bind_fd, max_idle_time); - syslog(LOG_INFO, "stopping"); + syslog(LOG_INFO, "stopping"); cleanup3: - close_dns(bind_fd); + close_dns(bind_fd); cleanup2: - close_dns(dnsd_fd); + close_dns(dnsd_fd); cleanup1: - close_tun(tun_fd); + close_tun(tun_fd); cleanup0: - return retval; + return retval; } diff --git a/src/login.c b/src/login.c index aa817c0..23f8f84 100644 --- a/src/login.c +++ b/src/login.c @@ -33,27 +33,27 @@ void login_calculate(char *buf, int buflen, const char *pass, int seed) { - unsigned char temp[32]; - md5_state_t ctx; - int *ix; - int i; - int k; + unsigned char temp[32]; + md5_state_t ctx; + int *ix; + int i; + int k; - if (buflen < 16) - return; + if (buflen < 16) + return; - memcpy(temp, pass, 32); - ix = (int*) temp; + memcpy(temp, pass, 32); + ix = (int*) temp; - for (i = 0; i < 8; i++) { - k = ntohl(*ix); - k ^= seed; - *ix++ = htonl(k); - } + for (i = 0; i < 8; i++) { + k = ntohl(*ix); + k ^= seed; + *ix++ = htonl(k); + } - md5_init(&ctx); - md5_append(&ctx, temp, 32); - md5_finish(&ctx, (unsigned char *) buf); + md5_init(&ctx); + md5_append(&ctx, temp, 32); + md5_finish(&ctx, (unsigned char *) buf); } diff --git a/src/read.c b/src/read.c index 2c26584..728c08e 100644 --- a/src/read.c +++ b/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; } diff --git a/src/tun.c b/src/tun.c index 1196ce2..f0adf4e 100644 --- a/src/tun.c +++ b/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 } diff --git a/src/user.c b/src/user.c index 61a16e8..9ad41b8 100644 --- a/src/user.c +++ b/src/user.c @@ -40,94 +40,94 @@ unsigned usercount; int init_users(in_addr_t my_ip, int netbits) { - int i; - int skip = 0; - char newip[16]; + int i; + int skip = 0; + char newip[16]; - int maxusers; + int maxusers; - in_addr_t netmask = 0; - struct in_addr net; - struct in_addr ipstart; + in_addr_t netmask = 0; + struct in_addr net; + struct in_addr ipstart; - for (i = 0; i < netbits; i++) { - netmask = (netmask << 1) | 1; - } - netmask <<= (32 - netbits); - net.s_addr = htonl(netmask); - ipstart.s_addr = my_ip & net.s_addr; + for (i = 0; i < netbits; i++) { + netmask = (netmask << 1) | 1; + } + netmask <<= (32 - netbits); + net.s_addr = htonl(netmask); + ipstart.s_addr = my_ip & net.s_addr; - maxusers = (1 << (32-netbits)) - 3; /* 3: Net addr, broadcast addr, iodined addr */ - usercount = MIN(maxusers, USERS); + maxusers = (1 << (32-netbits)) - 3; /* 3: Net addr, broadcast addr, iodined addr */ + usercount = MIN(maxusers, USERS); - users = calloc(usercount, sizeof(struct tun_user)); - for (i = 0; i < usercount; i++) { - in_addr_t ip; - users[i].id = i; - snprintf(newip, sizeof(newip), "0.0.0.%d", i + skip + 1); - ip = ipstart.s_addr + inet_addr(newip); - if (ip == my_ip && skip == 0) { - /* This IP was taken by iodined */ - skip++; - snprintf(newip, sizeof(newip), "0.0.0.%d", i + skip + 1); - ip = ipstart.s_addr + inet_addr(newip); - } - users[i].tun_ip = ip; - net.s_addr = ip; - users[i].disabled = 0; - users[i].authenticated = 0; - users[i].authenticated_raw = 0; - users[i].active = 0; - /* Rest is reset on login ('V' packet) */ - } + users = calloc(usercount, sizeof(struct tun_user)); + for (i = 0; i < usercount; i++) { + in_addr_t ip; + users[i].id = i; + snprintf(newip, sizeof(newip), "0.0.0.%d", i + skip + 1); + ip = ipstart.s_addr + inet_addr(newip); + if (ip == my_ip && skip == 0) { + /* This IP was taken by iodined */ + skip++; + snprintf(newip, sizeof(newip), "0.0.0.%d", i + skip + 1); + ip = ipstart.s_addr + inet_addr(newip); + } + users[i].tun_ip = ip; + net.s_addr = ip; + users[i].disabled = 0; + users[i].authenticated = 0; + users[i].authenticated_raw = 0; + users[i].active = 0; + /* Rest is reset on login ('V' packet) */ + } - return usercount; + return usercount; } const char* users_get_first_ip() { - struct in_addr ip; - ip.s_addr = users[0].tun_ip; - return strdup(inet_ntoa(ip)); + struct in_addr ip; + ip.s_addr = users[0].tun_ip; + return strdup(inet_ntoa(ip)); } int users_waiting_on_reply() { - int ret; - int i; + int ret; + int i; - ret = 0; - for (i = 0; i < usercount; i++) { - if (users[i].active && !users[i].disabled && - users[i].last_pkt + 60 > time(NULL) && - users[i].q.id != 0 && users[i].conn == CONN_DNS_NULL) { - ret++; - } - } + ret = 0; + for (i = 0; i < usercount; i++) { + if (users[i].active && !users[i].disabled && + users[i].last_pkt + 60 > time(NULL) && + users[i].q.id != 0 && users[i].conn == CONN_DNS_NULL) { + ret++; + } + } - return ret; + return ret; } int find_user_by_ip(uint32_t ip) { - int ret; - int i; + int ret; + int i; - ret = -1; - for (i = 0; i < usercount; i++) { - if (users[i].active && - users[i].authenticated && - !users[i].disabled && - users[i].last_pkt + 60 > time(NULL) && - ip == users[i].tun_ip) { - ret = i; - break; - } - } - return ret; + ret = -1; + for (i = 0; i < usercount; i++) { + if (users[i].active && + users[i].authenticated && + !users[i].disabled && + users[i].last_pkt + 60 > time(NULL) && + ip == users[i].tun_ip) { + ret = i; + break; + } + } + return ret; } int @@ -138,70 +138,70 @@ all_users_waiting_to_send() without going through another select loop. */ { - time_t now; - int ret; - int i; + time_t now; + int ret; + int i; - ret = 1; - now = time(NULL); - for (i = 0; i < usercount; i++) { - if (users[i].active && !users[i].disabled && - users[i].last_pkt + 60 > now && - ((users[i].conn == CONN_RAW_UDP) || - ((users[i].conn == CONN_DNS_NULL) + ret = 1; + now = time(NULL); + for (i = 0; i < usercount; i++) { + if (users[i].active && !users[i].disabled && + users[i].last_pkt + 60 > now && + ((users[i].conn == CONN_RAW_UDP) || + ((users[i].conn == CONN_DNS_NULL) #ifdef OUTPACKETQ_LEN - && users[i].outpacketq_filled < 1 + && users[i].outpacketq_filled < 1 #else - && users[i].outpacket.len == 0 + && users[i].outpacket.len == 0 #endif - ))) { + ))) { - ret = 0; - break; - } - } - return ret; + ret = 0; + break; + } + } + return ret; } int find_available_user() { - int ret = -1; - int i; - for (i = 0; i < usercount; i++) { - /* Not used at all or not used in one minute */ - if ((!users[i].active || users[i].last_pkt + 60 < time(NULL)) && !users[i].disabled) { - users[i].active = 1; - users[i].authenticated = 0; - users[i].authenticated_raw = 0; - users[i].last_pkt = time(NULL); - users[i].fragsize = 4096; - users[i].conn = CONN_DNS_NULL; - ret = i; - break; - } - } - return ret; + int ret = -1; + int i; + for (i = 0; i < usercount; i++) { + /* Not used at all or not used in one minute */ + if ((!users[i].active || users[i].last_pkt + 60 < time(NULL)) && !users[i].disabled) { + users[i].active = 1; + users[i].authenticated = 0; + users[i].authenticated_raw = 0; + users[i].last_pkt = time(NULL); + users[i].fragsize = 4096; + users[i].conn = CONN_DNS_NULL; + ret = i; + break; + } + } + return ret; } void user_switch_codec(int userid, struct encoder *enc) { - if (userid < 0 || userid >= usercount) - return; + if (userid < 0 || userid >= usercount) + return; - users[userid].encoder = enc; + users[userid].encoder = enc; } void user_set_conn_type(int userid, enum connection c) { - if (userid < 0 || userid >= usercount) - return; + if (userid < 0 || userid >= usercount) + return; - if (c < 0 || c >= CONN_MAX) - return; + if (c < 0 || c >= CONN_MAX) + return; - users[userid].conn = c; + users[userid].conn = c; } diff --git a/src/user.h b/src/user.h index b5ccaa9..9855f27 100644 --- a/src/user.h +++ b/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 }; diff --git a/src/util.c b/src/util.c index 5cbad72..e3adb78 100644 --- a/src/util.c +++ b/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 diff --git a/tests/base32.c b/tests/base32.c index 4b460e2..d96f14e 100644 --- a/tests/base32.c +++ b/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; } diff --git a/tests/base64.c b/tests/base64.c index bcefc4c..71c991f 100644 --- a/tests/base64.c +++ b/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; } diff --git a/tests/common.c b/tests/common.c index 742c04a..a7bff01 100644 --- a/tests/common.c +++ b/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; } diff --git a/tests/encoding.c b/tests/encoding.c index 0d5f358..34b6eca 100644 --- a/tests/encoding.c +++ b/tests/encoding.c @@ -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; } diff --git a/tests/fw_query.c b/tests/fw_query.c index be8ce10..56481e0 100644 --- a/tests/fw_query.c +++ b/tests/fw_query.c @@ -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; } diff --git a/tests/login.c b/tests/login.c index c814cee..a530d83 100644 --- a/tests/login.c +++ b/tests/login.c @@ -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; } diff --git a/tests/read.c b/tests/read.c index 764e635..7c54adb 100644 --- a/tests/read.c +++ b/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; } diff --git a/tests/test.c b/tests/test.c index eda792b..6ed6a85 100644 --- a/tests/test.c +++ b/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; } diff --git a/tests/test.h b/tests/test.h index d3f7985..10b7207 100644 --- a/tests/test.h +++ b/tests/test.h @@ -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 diff --git a/tests/user.c b/tests/user.c index 7d8804e..425a946 100644 --- a/tests/user.c +++ b/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; }