1
0
mirror of https://github.com/yarrick/iodine.git synced 2025-02-20 14:23:15 +03:00

Merge remote-tracking branch 'yarrick/master' into autotools

only non-trivial conflict is the CC option -std=c99, which I defer
This commit is contained in:
Barak A. Pearlmutter 2016-12-28 11:15:45 +01:00
commit 11b6da12ff
51 changed files with 1810 additions and 1149 deletions

View File

@ -6,9 +6,23 @@ iodine - http://code.kryo.se/iodine
CHANGES:
master:
- IPv6 support (in progress, #107)
Client can connect to iodined through an IPv6 nameserver.
Server only supports IPv4 for now.
- Mac OS X: Support native utun VPN devices. Patch by
Peter Sagerson, ported from OpenVPN by Catalin Patulea.
- Fix compilation failure on kFreeBSD and Hurd, by Gregor Herrmann
- Patch from Ryan Welton that fixes compilation warning.
- README converted to markdown by Nicolas Braud-Santoni.
- Linux: use pkg-config for systemd support flags.
Patch by Jason A. Donenfeld.
- Change external IP webservice to ipify.org
- Add support for IPv6 in the server.
Raw mode will be with same protocol as used for login.
Traffic inside tunnel is still IPv4.
- Update android build to support 5.0 (Lollipop) and newer.
2014-06-16: 0.7.0 "Kryoptonite"
- Partial IPv6 support (#107)
Client can connect to iodined through an relaying IPv6
nameserver. Server only supports IPv4 for now.
Traffic inside tunnel is IPv4.
- Add socket activation for systemd, by Michael Scherer.
- Add automated lookup of external ip (via -n auto).
@ -20,6 +34,13 @@ master:
Patch by laurent at gouloum fr, fixes #95.
- Add android patches and makefile, from Marcel Bokhorst, fixes #105.
- Added missing break in iodine.c, by Pavel Pergamenshchik, #108.
- A number of minor patches from Frank Denis, Gregor Herrmann and
Barak A. Pearlmutter.
- Testcase compilation fixes for OS X and FreeBSD
- Do not let sockets be inherited by sub-processes, fixes #99.
- Add unspecified RR type (called PRIVATE; id 65399, in private use
range). For servers with RFC3597 support. Fixes #97.
- Fix authentication bypass vulnerability; found by Oscar Reparaz.
2010-02-06: 0.6.0-rc1 "Hotspotify"
- Fixed tunnel not working on Windows.

379
README
View File

@ -1,379 +0,0 @@
iodine - http://code.kryo.se/iodine
***********************************
This is a piece of software that lets you tunnel IPv4 data through a DNS
server. This can be usable in different situations where internet access is
firewalled, but DNS queries are allowed.
COMPILING:
Iodine has no configure script. There are two optional features for Linux
(SELinux and systemd support) that will be enabled automatically if the
relevant header files are found in /usr/include. (See script at ./src/osflags)
Run 'make' to compile the server and client binaries.
Run 'make install' to copy binaries and manpage to the destination directory.
Run 'make test' to compile and run the unit tests. (Requires the check library)
QUICKSTART:
Try it out within your own LAN! Follow these simple steps:
- On your server, run: ./iodined -f 10.0.0.1 test.com
(If you already use the 10.0.0.0 network, use another internal net like
172.16.0.0)
- Enter a password
- On the client, run: ./iodine -f -r 192.168.0.1 test.com
(Replace 192.168.0.1 with your server's ip address)
- Enter the same password
- Now the client has the tunnel ip 10.0.0.2 and the server has 10.0.0.1
- Try pinging each other through the tunnel
- Done! :)
To actually use it through a relaying nameserver, see below.
HOW TO USE:
Note: server and client are required to speak the exact same protocol. In most
cases, this means running the same iodine version. Unfortunately, implementing
backward and forward protocol compatibility is usually not feasible.
Server side:
To use this tunnel, you need control over a real domain (like mydomain.com),
and a server with a public IP address to run iodined on. If this server
already runs a DNS program, change its listening port and then use iodined's
-b option to let iodined forward the DNS requests. (Note that this procedure
is not advised in production environments, because iodined's DNS forwarding
is not completely transparent.)
Then, delegate a subdomain (say, t1.mydomain.com) to the iodined server.
If you use BIND for your domain, add two lines like these to the zone file:
t1 IN NS t1ns.mydomain.com. ; note the dot!
t1ns IN A 10.15.213.99
The "NS" line is all that's needed to route queries for the "t1" subdomain
to the "t1ns" server. We use a short name for the subdomain, to keep as much
space as possible available for the data traffic. At the end of the "NS" line
is the name of your iodined server. This can be any name, pointing anywhere,
but in this case it's easily kept in the same zone file. It must be a name
(not an IP address), and that name itself must have an A record (not a CNAME).
If your iodined server has a dynamic IP, use a dynamic dns provider. Simply
point the "NS" line to it, and leave the "A" line out:
t1 IN NS myname.mydyndnsprovider.com. ; note the dot!
Then reload or restart your nameserver program. Now any DNS queries for
domains ending in t1.mydomain.com will be sent to your iodined server.
Finally start iodined on your server. The first argument is the IP address
inside the tunnel, which can be from any range that you don't use yet (for
example 192.168.99.1), and the second argument is the assigned domain (in this
case t1.mydomain.com). Using the -f option will keep iodined running in the
foreground, which helps when testing. iodined will open a virtual interface
("tun device"), and will also start listening for DNS queries on UDP port 53.
Either enter a password on the commandline (-P pass) or after the server has
started. Now everything is ready for the client.
If there is a chance you'll be using an iodine tunnel from unexpected
environments, start iodined with a -c option.
Resulting commandline in this example situation:
./iodined -f -c -P secretpassword 192.168.99.1 t1.mydomain.com
Client side:
All the setup is done, just start iodine. It takes one or two arguments, the
first is the local relaying DNS server (optional) and the second is the domain
you used (t1.mydomain.com). If you don't specify the first argument, the
system's current DNS setting will be consulted.
If DNS queries are allowed to any computer, you can directly give the iodined
server's address as first argument (in the example: t1ns.mydomain.com or
10.15.213.99). In that case, it may also happen that _any_ traffic is allowed
to the DNS port (53 UDP) of any computer. Iodine will detect this, and switch
to raw UDP tunneling if possible. To force DNS tunneling in any case, use the
-r option (especially useful when testing within your own network).
The client's tunnel interface will get an IP close to the server's (in this
case 192.168.99.2 or .3 etc.) and a suitable MTU. Enter the same password as
on the server either as commandline option or after the client has started.
Using the -f option will keep the iodine client running in the foreground.
Resulting commandline in this example situation:
./iodine -f -P secretpassword t1.mydomain.com
(add -r to force DNS tunneling even if raw UDP tunneling would be possible)
From either side, you should now be able to ping the IP address on the other
end of the tunnel. In this case, ping 192.168.99.1 from the iodine client, and
192.168.99.2 or .3 etc. from the iodine server.
MISC. INFO:
IPv6:
At the moment the iodined server only supports IPv4. The data inside the tunnel
is IPv4 only.
The client can use IPv4 or IPv6 nameservers to connect to iodined. The relay
nameservers will translate between protocols automatically if needed. Use
options -4 or -6 to force the client to use a specific IP version for its DNS
queries. The client has to force IPv4 if it has dual-stack connectivity and
the hostname handling the tunnel domain has both A and AAAA records.
Routing:
It is possible to route all traffic through the DNS tunnel. To do this, first
add a host route to the nameserver used by iodine over the wired/wireless
interface with the default gateway as gateway. Then replace the default
gateway with the iodined server's IP address inside the DNS tunnel, and
configure the server to do NAT.
However, note that the tunneled data traffic is not encrypted at all, and can
be read and changed by external parties relatively easily. For maximum
security, run a VPN through the DNS tunnel (=double tunneling), or use secure
shell (SSH) access, possibly with port forwarding. The latter can also be used
for web browsing, when you run a web proxy (for example Privoxy) on your
server.
Testing:
The iodined server replies to NS requests sent for subdomains of the tunnel
domain. If your iodined subdomain is t1.mydomain.com, send a NS request for
foo123.t1.mydomain.com to see if the delegation works. dig is a good tool
for this:
dig -t NS foo123.t1.mydomain.com
Also, the iodined server will answer requests starting with 'z' for any of the
supported request types, for example:
dig -t TXT z456.t1.mydomain.com
dig -t SRV z456.t1.mydomain.com
dig -t CNAME z456.t1.mydomain.com
The reply should look like garbled text in all these cases.
Operational info:
The DNS-response fragment size is normally autoprobed to get maximum bandwidth.
To force a specific value (and speed things up), use the -m option.
The DNS hostnames are normally used up to their maximum length, 255 characters.
Some DNS relays have been found that answer full-length queries rather
unreliably, giving widely varying (and mostly very bad) results of the
fragment size autoprobe on repeated tries. In these cases, use the -M switch
to reduce the DNS hostname length to for example 200 characters, which makes
these DNS relays much more stable. This is also useful on some "de-optimizing"
DNS relays that stuff the response with two full copies of the query, leaving
very little space for downstream data (also not capable of EDNS0). The -M
switch can trade some upstream bandwidth for downstream bandwidth. Note that
the minimum -M value is about 100, since the protocol can split packets (1200
bytes max) in only 16 fragments, requiring at least 75 real data bytes per
fragment.
The upstream data is sent gzipped encoded with Base32; or Base64 if the relay
server supports mixed case and '+' in domain names; or Base64u if '_' is
supported instead; or Base128 if high-byte-value characters are supported.
This upstream encoding is autodetected. The DNS protocol allows one query per
packet, and one query can be max 256 chars. Each domain name part can be max
63 chars. So your domain name and subdomain should be as short as possible to
allow maximum upstream throughput.
Several DNS request types are supported, with the NULL type expected to provide
the largest downstream bandwidth. Other available types are TXT, SRV, MX,
CNAME and A (returning CNAME), in decreasing bandwidth order. Normally the
"best" request type is autodetected and used. However, DNS relays may impose
limits on for example NULL and TXT, making SRV or MX actually the best choice.
This is not autodetected, but can be forced using the -T option. It is
advisable to try various alternatives especially when the autodetected request
type provides a downstream fragment size of less than 200 bytes.
Note that SRV, MX and A (returning CNAME) queries may/will cause additional
lookups by "smart" caching nameservers to get an actual IP address, which may
either slow down or fail completely.
DNS responses for non-NULL queries can be encoded with the same set of codecs
as upstream data. This is normally also autodetected, but no fully exhaustive
tests are done, so some problems may not be noticed when selecting more
advanced codecs. In that case, you'll see failures/corruption in the fragment
size autoprobe. In particular, several DNS relays have been found that change
replies returning hostnames (SRV, MX, CNAME, A) to lowercase only when that
hostname exceeds ca. 180 characters. In these and similar cases, use the -O
option to try other downstream codecs; Base32 should always work.
Normal operation now is for the server to _not_ answer a DNS request until
the next DNS request has come in, a.k.a. being "lazy". This way, the server
will always have a DNS request handy when new downstream data has to be sent.
This greatly improves (interactive) performance and latency, and allows to
slow down the quiescent ping requests to 4 second intervals by default, and
possibly much slower. In fact, the main purpose of the pings now is to force
a reply to the previous ping, and prevent DNS server timeouts (usually at
least 5-10 seconds per RFC1035). Some DNS servers are more impatient and will
give SERVFAIL errors (timeouts) in periods without tunneled data traffic. All
data should still get through in these cases, but iodine will reduce the ping
interval to 1 second anyway (-I1) to reduce the number of error messages. This
may not help for very impatient DNS relays like dnsadvantage.com (ultradns),
which time out in 1 second or even less. Yet data will still get trough, and
you can ignore the SERVFAIL errors.
If you are running on a local network without any DNS server in-between, try
-I 50 (iodine and iodined close the connection after 60 seconds of silence).
The only time you'll notice a slowdown, is when DNS reply packets go missing;
the iodined server then has to wait for a new ping to re-send the data. You can
speed this up by generating some upstream traffic (keypress, ping). If this
happens often, check your network for bottlenecks and/or run with -I1.
The delayed answering in lazy mode will cause some "carrier grade" commercial
DNS relays to repeatedly re-send the same DNS query to the iodined server.
If the DNS relay is actually implemented as a pool of parallel servers,
duplicate requests may even arrive from multiple sources. This effect will
only be visible in the network traffic at the iodined server, and will not
affect the client's connection. Iodined will notice these duplicates, and send
the same answer (when its time has come) to both the original query and the
latest duplicate. After that, the full answer is cached for a short while.
Delayed duplicates that arrive at the server even later, get a reply that the
iodine client will ignore (if it ever arrives there).
If you have problems, try inspecting the traffic with network monitoring tools
like tcpdump or ethereal/wireshark, and make sure that the relaying DNS server
has not cached the response. A cached error message could mean that you
started the client before the server. The -D (and -DD) option on the server
can also show received and sent queries.
TIPS & TRICKS:
If your port 53 is taken on a specific interface by an application that does
not use it, use -p on iodined to specify an alternate port (like -p 5353) and
use for instance iptables (on Linux) to forward the traffic:
iptables -t nat -A PREROUTING -i eth0 -p udp --dport 53 -j DNAT --to :5353
(Sent in by Tom Schouten)
Iodined will reject data from clients that have not been active (data/pings)
for more than 60 seconds. Similarly, iodine will exit when no downstream
data has been received for 60 seconds. In case of a long network outage or
similar, just restart iodine (re-login), possibly multiple times until you get
your old IP address back. Once that's done, just wait a while, and you'll
eventually see the tunneled TCP traffic continue to flow from where it left
off before the outage.
With the introduction of the downstream packet queue in the server, its memory
usage has increased with several megabytes in the default configuration.
For use in low-memory environments (e.g. running on your DSL router), you can
decrease USERS and undefine OUTPACKETQ_LEN in user.h without any ill conse-
quence, assuming at most one client will be connected at any time. A small
DNSCACHE_LEN is still advised, preferably 2 or higher, however you can also
undefine it to save a few more kilobytes.
For systemd support on Debian, compile with libsystemd-daemon-dev installed.
PERFORMANCE:
This section tabulates some performance measurements. To view properly, use
a fixed-width font like Courier.
Measurements were done in protocol 00000502 in lazy mode; upstream encoding
always Base128; iodine -M255; iodined -m1130. Network conditions were not
extremely favorable; results are not benchmarks but a realistic indication of
real-world performance that can be expected in similar situations.
Upstream/downstream throughput was measured by scp'ing a file previously
read from /dev/urandom (i.e. incompressible), and measuring size with
"ls -l ; sleep 30 ; ls -l" on a separate non-tunneled connection. Given the
large scp block size of 16 kB, this gives a resolution of 4.3 kbit/s, which
explains why some values are exactly equal.
Ping round-trip times measured with "ping -c100", presented are average rtt
and mean deviation (indicating spread around the average), in milliseconds.
Situation 1:
Laptop -> Wifi AP -> Home server -> DSL provider -> Datacenter
iodine DNS "relay" bind9 DNS cache iodined
downstr. upstream downstr. ping-up ping-down
fragsize kbit/s kbit/s avg +/-mdev avg +/-mdev
------------------------------------------------------------------------------
iodine -> Wifi AP :53
-Tnull (= -Oraw) 982 43.6 131.0 28.0 4.6 26.8 3.4
iodine -> Home server :53
-Tnull (= -Oraw) 1174 48.0 305.8 26.6 5.0 26.9 8.4
iodine -> DSL provider :53
-Tnull (= -Oraw) 1174 56.7 367.0 20.6 3.1 21.2 4.4
-Ttxt -Obase32 730 56.7 174.7*
-Ttxt -Obase64 874 56.7 174.7
-Ttxt -Obase128 1018 56.7 174.7
-Ttxt -Oraw 1162 56.7 358.2
-Tsrv -Obase128 910 56.7 174.7
-Tcname -Obase32 151 56.7 43.6
-Tcname -Obase128 212 56.7 52.4
iodine -> DSL provider :53
wired (no Wifi) -Tnull 1174 74.2 585.4 20.2 5.6 19.6 3.4
[174.7* : these all have 2frag/packet]
Situation 2:
Laptop -> Wifi+vpn / wired -> Home server
iodine iodined
downstr. upstream downstr. ping-up ping-down
fragsize kbit/s kbit/s avg +/-mdev avg +/-mdev
------------------------------------------------------------------------------
wifi + openvpn -Tnull 1186 166.0 1022.3 6.3 1.3 6.6 1.6
wired -Tnull 1186 677.2 2464.1 1.3 0.2 1.3 0.1
Performance is strongly coupled to low ping times, as iodine requires
confirmation for every data fragment before moving on to the next. Allowing
multiple fragments in-flight like TCP could possibly increase performance,
but it would likely cause serious overload for the intermediary DNS servers.
The current protocol scales performance with DNS responsivity, since the
DNS servers are on average handling at most one DNS request per client.
PORTABILITY:
iodine has been tested on Linux (arm, ia64, x86, AMD64 and SPARC64), FreeBSD
(ia64, x86), OpenBSD (x86), NetBSD (x86), MacOS X (ppc and x86, with
http://tuntaposx.sourceforge.net/). and Windows (with OpenVPN TAP32 driver, see
win32 readme file). It should be easy to port to other unix-like systems that
has TUN/TAP tunneling support. Let us know if you get it to run on other
platforms.
THE NAME:
The name iodine was chosen since it starts with IOD (IP Over DNS) and since
iodine has atomic number 53, which happens to be the DNS port number.
THANKS:
- To kuxien for FreeBSD and OS X testing
- To poplix for code audit
AUTHORS & LICENSE:
Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
Also major contributions by Anne Bezemer.
Permission to use, copy, modify, and distribute this software for any purpose
with or without fee is hereby granted, provided that the above copyright notice
and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
MD5 implementation by L. Peter Deutsch (license and source in src/md5.[ch])
Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.

View File

@ -13,7 +13,7 @@ Extra README file for Android
2. Find/build a compatible tun.ko for your specific Android kernel
3. Copy tun.ko and the iodine binary to your device:
(Almost all devices need the armeabi binary. Only Intel powered
(Almost all devices need the armeabi binary. Only Intel powered
ones need the x86 build.)
adb push tun.ko /data/local/tmp
@ -35,11 +35,15 @@ For more information: http://blog.bokhorst.biz/5123
2. Download and unpack the iodine sources
3. Build:
cd src
make base64u.h base64u.c
ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=Android.mk
cd src
make base64u.h base64u.c
ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=Android.mk APP_PLATFORM=android-16
or run "make cross-android" in the iodine root directory.
To build for other archs, specify TARGET_ARCH_ABI:
To build for other archs, specify TARGET_ARCH_ABI:
"make cross-android TARGET_ARCH_ABI=x86"
For older android versions (pre-kitkat), build with "make cross-android-old" in the
root directory, or manually like above but with APP_PLATFORM=android-3
The iodine binary ends up in src/libs/<arch>/iodine

View File

@ -11,10 +11,11 @@ Extra README file for Win32 related stuff
0. After iodine 0.6, you need Windows XP or newer to run.
1. Install the TAP32 driver
1. Install the TAP driver
http://openvpn.net/index.php/open-source/downloads.html
Choose OpenVPN 2.0.9 Windows Installer, when installing you can
select to install only the TAP driver.
Download the OpenVPN TAP driver (under section Tap-windows)
Problems has been reported with the NDIS6 version (9.2x.y), use the
NDIS5 version for now if possible.
2. Have at least one TAP32 interface installed. There are scripts for adding
and removing in the OpenVPN bin directory. If you have more than one

408
README.md Normal file
View File

@ -0,0 +1,408 @@
iodine - <http://code.kryo.se/iodine>
=====================================
This is a piece of software that lets you tunnel IPv4 data through a DNS
server. This can be usable in different situations where internet access is
firewalled, but DNS queries are allowed.
COMPILING
---------
Iodine has no configure script. There are two optional features for Linux
(SELinux and systemd support) that will be enabled automatically if the
relevant header files are found in `/usr/include`.
(See script at `./src/osflags`)
Run `make` to compile the server and client binaries.
Run `make install` to copy binaries and manpage to the destination directory.
Run `make test` to compile and run the unit tests. (Requires the `check` library)
QUICKSTART
----------
Try it out within your own LAN! Follow these simple steps:
- On your server, run: `./iodined -f 10.0.0.1 test.com`.
If you already use the `10.0.0.0` network, use another internal net like
`172.16.0.0`.
- Enter a password.
- On the client, run: `./iodine -f -r 192.168.0.1 test.com`.
Replace `192.168.0.1` with your server's ip address.
- Enter the same password.
- Now the client has the tunnel ip `10.0.0.2` and the server has `10.0.0.1`.
- Try pinging each other through the tunnel.
- Done! :)
To actually use it through a relaying nameserver, see below.
HOW TO USE
----------
Note: server and client are required to speak the exact same protocol. In most
cases, this means running the same iodine version. Unfortunately, implementing
backward and forward protocol compatibility is usually not feasible.
### Server side
To use this tunnel, you need control over a real domain (like `mydomain.com`),
and a server with a public IP address to run `iodined` on. If this server
already runs a DNS program, change its listening port and then use `iodined`'s
`-b` option to let `iodined` forward the DNS requests. (Note that this procedure
is not advised in production environments, because `iodined`'s DNS forwarding
is not completely transparent.)
Then, delegate a subdomain (say, `t1.mydomain.com`) to the iodined server.
If you use BIND for your domain, add two lines like these to the zone file:
t1 IN NS t1ns.mydomain.com. ; note the dot!
t1ns IN A 10.15.213.99
The `NS` line is all that's needed to route queries for the `t1` subdomain
to the `t1ns` server. We use a short name for the subdomain, to keep as much
space as possible available for the data traffic. At the end of the `NS` line
is the name of your `iodined` server. This can be any name, pointing anywhere,
but in this case it's easily kept in the same zone file. It must be a name
(not an IP address), and that name itself must have an `A` record
(not a `CNAME`).
If your `iodined` server has a dynamic IP, use a dynamic DNS provider. Simply
point the `NS` line to it, and leave the `A` line out:
t1 IN NS myname.mydyndnsprovider.com. ; note the dot!
Then reload or restart your nameserver program. Now any DNS queries for
domains ending in `t1.mydomain.com` will be sent to your `iodined` server.
Finally start `iodined` on your server. The first argument is the IP address
inside the tunnel, which can be from any range that you don't use yet (for
example `192.168.99.1`), and the second argument is the assigned domain (in this
case `t1.mydomain.com`). Using the `-f` option will keep iodined running in the
foreground, which helps when testing. iodined will open a virtual interface
("tun device"), and will also start listening for DNS queries on UDP port 53.
Either enter a password on the commandline (`-P pass`) or after the server has
started. Now everything is ready for the client.
If there is a chance you'll be using an iodine tunnel from unexpected
environments, start `iodined` with a `-c` option.
Resulting commandline in this example situation:
./iodined -f -c -P secretpassword 192.168.99.1 t1.mydomain.com
### Client side
All the setup is done, just start `iodine`. It takes one or two arguments, the
first is the local relaying DNS server (optional) and the second is the domain
you used (`t1.mydomain.com`). If you don't specify the first argument, the
system's current DNS setting will be consulted.
If DNS queries are allowed to any computer, you can directly give the `iodined`
server's address as first argument (in the example: `t1ns.mydomain.com` or
`10.15.213.99`). In that case, it may also happen that _any_ traffic is allowed
to the DNS port (53 UDP) of any computer. Iodine will detect this, and switch
to raw UDP tunneling if possible. To force DNS tunneling in any case, use the
`-r` option (especially useful when testing within your own network).
The client's tunnel interface will get an IP close to the server's (in this
case `192.168.99.2` or `.3` etc.) and a suitable MTU. Enter the same password as
on the server either as commandline option or after the client has started.
Using the `-f` option will keep the iodine client running in the foreground.
Resulting commandline in this example situation, adding -r forces DNS tunneling
even if raw UDP tunneling would be possible:
./iodine -f -P secretpassword t1.mydomain.com
From either side, you should now be able to ping the IP address on the other
end of the tunnel. In this case, `ping 192.168.99.1` from the iodine client, and
`192.168.99.2` from the iodine server.
### MISC. INFO
#### IPv6
The data inside the tunnel is IPv4 only.
The server listens to both IPv4 and IPv6 for incoming requests by default.
Use options `-4` or `-6` to only listen on one protocol. Raw mode will be
attempted on the same protocol as used for the login.
The client can use IPv4 or IPv6 nameservers to connect to iodined. The relay
nameservers will translate between protocols automatically if needed. Use
options `-4` or `-6` to force the client to use a specific IP version for its DNS
queries.
#### Routing
It is possible to route all traffic through the DNS tunnel. To do this, first
add a host route to the nameserver used by iodine over the wired/wireless
interface with the default gateway as gateway. Then replace the default
gateway with the iodined server's IP address inside the DNS tunnel, and
configure the server to do NAT.
However, note that the tunneled data traffic is not encrypted at all, and can
be read and changed by external parties relatively easily. For maximum
security, run a VPN through the DNS tunnel (=double tunneling), or use secure
shell (SSH) access, possibly with port forwarding. The latter can also be used
for web browsing, when you run a web proxy (for example Privoxy) on your
server.
#### Testing
The `iodined` server replies to `NS` requests sent for subdomains of the tunnel
domain. If your iodined subdomain is `t1.mydomain.com`, send a `NS` request for
`foo123.t1.mydomain.com` to see if the delegation works.
`dig` is a good tool for this:
% dig -t NS foo123.t1.mydomain.com
ns.io.citronna.de.
Also, the iodined server will answer requests starting with 'z' for any of the
supported request types, for example:
dig -t TXT z456.t1.mydomain.com
dig -t SRV z456.t1.mydomain.com
dig -t CNAME z456.t1.mydomain.com
The reply should look like garbled text in all these cases.
#### Mac OS X
On Mac OS X 10.6 and later, iodine supports the native utun devices built into
the OS - use `-d utunX`.
Operational info
----------------
The DNS-response fragment size is normally autoprobed to get maximum bandwidth.
To force a specific value (and speed things up), use the `-m` option.
The DNS hostnames are normally used up to their maximum length, 255 characters.
Some DNS relays have been found that answer full-length queries rather
unreliably, giving widely varying (and mostly very bad) results of the
fragment size autoprobe on repeated tries. In these cases, use the `-M` switch
to reduce the DNS hostname length to, for example 200 characters, which makes
these DNS relays much more stable. This is also useful on some “de-optimizing”
DNS relays that stuff the response with two full copies of the query, leaving
very little space for downstream data (also not capable of EDNS0). The `-M`
switch can trade some upstream bandwidth for downstream bandwidth. Note that
the minimum `-M` value is about 100, since the protocol can split packets (1200
bytes max) in only 16 fragments, requiring at least 75 real data bytes per
fragment.
The upstream data is sent gzipped encoded with Base32; or Base64 if the relay
server supports mixed case and `+` in domain names; or Base64u if `_` is
supported instead; or Base128 if high-byte-value characters are supported.
This upstream encoding is autodetected. The DNS protocol allows one query per
packet, and one query can be max 256 chars. Each domain name part can be max
63 chars. So your domain name and subdomain should be as short as possible to
allow maximum upstream throughput.
Several DNS request types are supported, with the `NULL` and `PRIVATE` types
expected to provide the largest downstream bandwidth. The `PRIVATE` type uses
value 65399 in the private-use range. Other available types are `TXT`, `SRV`,
`MX`, `CNAME` and `A` (returning `CNAME`), in decreasing bandwidth order.
Normally the “best” request type is autodetected and used. However, DNS relays
may impose limits on for example NULL and TXT, making SRV or MX actually the best
choice. This is not autodetected, but can be forced using the `-T` option.
It is advisable to try various alternatives especially when the autodetected
request type provides a downstream fragment size of less than 200 bytes.
Note that `SRV`, `MX` and `A` (returning `CNAME`) queries may/will cause
additional lookups by "smart" caching nameservers to get an actual IP address,
which may either slow down or fail completely.
DNS responses for non-`NULL/PRIVATE` queries can be encoded with the same set of
codecs as upstream data. This is normally also autodetected, but no fully
exhaustive tests are done, so some problems may not be noticed when selecting
more advanced codecs. In that case, you'll see failures/corruption in the
fragment size autoprobe. In particular, several DNS relays have been found that
change replies returning hostnames (`SRV`, `MX`, `CNAME`, `A`) to lowercase only
when that hostname exceeds ca. 180 characters. In these and similar cases, use
the `-O` option to try other downstream codecs; Base32 should always work.
Normal operation now is for the server to _not_ answer a DNS request until
the next DNS request has come in, a.k.a. being “lazy”. This way, the server
will always have a DNS request handy when new downstream data has to be sent.
This greatly improves (interactive) performance and latency, and allows to
slow down the quiescent ping requests to 4 second intervals by default, and
possibly much slower. In fact, the main purpose of the pings now is to force
a reply to the previous ping, and prevent DNS server timeouts (usually at
least 5-10 seconds per RFC1035). Some DNS servers are more impatient and will
give SERVFAIL errors (timeouts) in periods without tunneled data traffic. All
data should still get through in these cases, but `iodine` will reduce the ping
interval to 1 second anyway (-I1) to reduce the number of error messages. This
may not help for very impatient DNS relays like `dnsadvantage.com` (ultradns),
which time out in 1 second or even less. Yet data will still get trough, and
you can ignore the `SERVFAIL` errors.
If you are running on a local network without any DNS server in-between, try
`-I 50` (iodine and iodined close the connection after 60 seconds of silence).
The only time you'll notice a slowdown, is when DNS reply packets go missing;
the `iodined` server then has to wait for a new ping to re-send the data. You can
speed this up by generating some upstream traffic (keypress, ping). If this
happens often, check your network for bottlenecks and/or run with `-I1`.
The delayed answering in lazy mode will cause some “carrier grade” commercial
DNS relays to repeatedly re-send the same DNS query to the iodined server.
If the DNS relay is actually implemented as a pool of parallel servers,
duplicate requests may even arrive from multiple sources. This effect will
only be visible in the network traffic at the `iodined` server, and will not
affect the client's connection. Iodined will notice these duplicates, and send
the same answer (when its time has come) to both the original query and the
latest duplicate. After that, the full answer is cached for a short while.
Delayed duplicates that arrive at the server even later, get a reply that the
iodine client will ignore (if it ever arrives there).
If you have problems, try inspecting the traffic with network monitoring tools
like tcpdump or ethereal/wireshark, and make sure that the relaying DNS server
has not cached the response. A cached error message could mean that you
started the client before the server. The `-D` (and `-DD`) option on the server
can also show received and sent queries.
TIPS & TRICKS
-------------
If your port 53 is taken on a specific interface by an application that does
not use it, use `-p` on iodined to specify an alternate port (like `-p 5353`)
and use for instance iptables (on Linux) to forward the traffic:
iptables -t nat -A PREROUTING -i eth0 -p udp --dport 53 -j DNAT --to :5353
(Sent in by Tom Schouten)
Iodined will reject data from clients that have not been active (data/pings)
for more than 60 seconds. Similarly, iodine will exit when no downstream
data has been received for 60 seconds. In case of a long network outage or
similar, just restart iodine (re-login), possibly multiple times until you get
your old IP address back. Once that's done, just wait a while, and you'll
eventually see the tunneled TCP traffic continue to flow from where it left
off before the outage.
With the introduction of the downstream packet queue in the server, its memory
usage has increased with several megabytes in the default configuration.
For use in low-memory environments (e.g. running on your DSL router), you can
decrease USERS and undefine OUTPACKETQ_LEN in user.h without any ill conse-
quence, assuming at most one client will be connected at any time. A small
DNSCACHE_LEN is still advised, preferably 2 or higher, however you can also
undefine it to save a few more kilobytes.
PERFORMANCE
-----------
This section tabulates some performance measurements. To view properly, use
a fixed-width font like Courier.
Measurements were done in protocol 00000502 in lazy mode; upstream encoding
always Base128; `iodine -M255`; `iodined -m1130`. Network conditions were not
extremely favorable; results are not benchmarks but a realistic indication of
real-world performance that can be expected in similar situations.
Upstream/downstream throughput was measured by `scp`'ing a file previously
read from `/dev/urandom` (i.e. incompressible), and measuring size with
`ls -l ; sleep 30 ; ls -l` on a separate non-tunneled connection. Given the
large `scp` block size of 16 kB, this gives a resolution of 4.3 kbit/s, which
explains why some values are exactly equal.
Ping round-trip times measured with `ping -c100`, presented are average rtt
and mean deviation (indicating spread around the average), in milliseconds.
### Situation 1: `Laptop -> Wifi AP -> Home server -> DSL provider -> Datacenter`
iodine DNS "relay" bind9 DNS cache iodined
downstr. upstream downstr. ping-up ping-down
fragsize kbit/s kbit/s avg +/-mdev avg +/-mdev
-----------------------------------------------------------------------------
iodine -> Wifi AP :53
-Tnull (= -Oraw) 982 43.6 131.0 28.0 4.6 26.8 3.4
iodine -> Home server :53
-Tnull (= -Oraw) 1174 48.0 305.8 26.6 5.0 26.9 8.4
iodine -> DSL provider :53
-Tnull (= -Oraw) 1174 56.7 367.0 20.6 3.1 21.2 4.4
-Ttxt -Obase32 730 56.7 174.7*
-Ttxt -Obase64 874 56.7 174.7
-Ttxt -Obase128 1018 56.7 174.7
-Ttxt -Oraw 1162 56.7 358.2
-Tsrv -Obase128 910 56.7 174.7
-Tcname -Obase32 151 56.7 43.6
-Tcname -Obase128 212 56.7 52.4
iodine -> DSL provider :53
wired (no Wifi) -Tnull 1174 74.2 585.4 20.2 5.6 19.6 3.4
[174.7* : these all have 2frag/packet]
### Situation 2: `Laptop -> Wifi+vpn / wired -> Home server`
iodine iodined
downstr. upstream downstr. ping-up ping-down
fragsize kbit/s kbit/s avg +/-mdev avg +/-mdev
-----------------------------------------------------------------------------
wifi + openvpn -Tnull 1186 166.0 1022.3 6.3 1.3 6.6 1.6
wired -Tnull 1186 677.2 2464.1 1.3 0.2 1.3 0.1
### Notes
Performance is strongly coupled to low ping times, as iodine requires
confirmation for every data fragment before moving on to the next. Allowing
multiple fragments in-flight like TCP could possibly increase performance,
but it would likely cause serious overload for the intermediary DNS servers.
The current protocol scales performance with DNS responsivity, since the
DNS servers are on average handling at most one DNS request per client.
PORTABILITY
-----------
iodine has been tested on Linux (arm, ia64, x86, AMD64 and SPARC64), FreeBSD
(ia64, x86), OpenBSD (x86), NetBSD (x86), MacOS X (ppc and x86, with
<http://tuntaposx.sourceforge.net/>). and Windows (with OpenVPN TAP32 driver, see
win32 readme file). It should be easy to port to other unix-like systems that
have TUN/TAP tunneling support. Let us know if you get it to run on other
platforms.
THE NAME
--------
The name iodine was chosen since it starts with IOD (IP Over DNS) and since
iodine has atomic number 53, which happens to be the DNS port number.
THANKS
------
- To kuxien for FreeBSD and OS X testing
- To poplix for code audit
AUTHORS & LICENSE
-----------------
Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>, 2006-2009 Bjorn
Andersson <flex@kryo.se>. Also major contributions by Anne Bezemer.
Permission to use, copy, modify, and/or distribute this software for any purpose
with or without fee is hereby granted, provided that the above copyright notice
and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
MD5 implementation by L. Peter Deutsch (license and source in `src/md5.[ch]`)
Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.

View File

@ -3,6 +3,8 @@ Description=Iodine socket
[Socket]
ListenDatagram=53
ListenDatagram=0.0.0.0:53
BindIPv6Only=ipv6-only
[Install]
WantedBy=sockets.target

View File

@ -38,7 +38,7 @@ Server replies:
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
@ -50,17 +50,19 @@ 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)
IP Request:
IP Request: (for where to try raw login)
Client sends:
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
First byte I
Then comes external IP address of iodined server
as 4 bytes (IPv4) or 16 bytes (IPv6)
Upstream codec check / bounce:
Client sends:
Client sends:
First byte z or Z
Lots of data that should not be decoded
Server replies:
@ -100,7 +102,7 @@ Client sends:
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
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
@ -122,7 +124,8 @@ Server sends:
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 TXT/NULL (default for NULL)
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
@ -181,15 +184,15 @@ 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.
Downstream data starts with 2 byte header. Then payload data, which may be
compressed.
In NULL responses, downstream data is always raw. In all other response types,
downstream data is encoded (see Options above).
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
@ -224,8 +227,8 @@ 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
=====================
@ -249,7 +252,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).

View File

@ -45,7 +45,7 @@ iodine, iodined \- tunnel IPv4 over DNS
.B iodined [-h]
.B iodined [-c] [-s] [-f] [-D] [-u
.B iodined [-4] [-6] [-c] [-s] [-f] [-D] [-u
.I user
.B ] [-t
.I chrootdir
@ -54,7 +54,9 @@ iodine, iodined \- tunnel IPv4 over DNS
.B ] [-m
.I mtu
.B ] [-l
.I listen_ip
.I listen_ip4
.B ] [-L
.I listen_ip6
.B ] [-p
.I port
.B ] [-n
@ -81,9 +83,9 @@ iodine, iodined \- tunnel IPv4 over DNS
.I topdomain
.SH DESCRIPTION
.B iodine
lets you tunnel IPv4 data through a DNS
lets you tunnel IPv4 data through a DNS
server. This can be useful in situations where Internet access is firewalled,
but DNS queries are allowed. It needs a TUN/TAP device to operate. The
but DNS queries are allowed. It needs a TUN/TAP device to operate. The
bandwidth is asymmetrical,
with a measured maximum of 680 kbit/s upstream and 2.3 Mbit/s
downstream in a wired LAN test network.
@ -110,6 +112,12 @@ Print usage info and exit.
.B -f
Keep running in foreground.
.TP
.B -4
Force/allow only IPv4 DNS queries
.TP
.B -6
Force/allow only IPv6 DNS queries
.TP
.B -u user
Drop privileges and run as user 'user' after setting up tunnel.
.TP
@ -118,10 +126,11 @@ Chroot to 'chrootdir' after setting up tunnel.
.TP
.B -d device
Use the TUN device 'device' instead of the normal one, which is dnsX on Linux
and otherwise tunX.
and otherwise tunX. On Mac OS X 10.6, this can also be utunX, which will attempt
to use an utun device built into the OS.
.TP
.B -P password
Use 'password' to authenticate. If not used,
Use 'password' to authenticate. If not used,
.B stdin
will be used as input. Only the first 32 characters will be used.
.TP
@ -132,12 +141,6 @@ Apply SELinux 'context' after initialization.
Create 'pidfile' and write process id in it.
.SS Client Options:
.TP
.B -4
Force IPv4 DNS queries
.TP
.B -6
Force IPv6 DNS queries
.TP
.B -r
Skip raw UDP mode. If not used, iodine will try getting the public IP address
of the iodined host and test if it is reachable directly. If it is, traffic
@ -169,6 +172,7 @@ more bandwidth.
In that case, use this option to override the autodetection.
In (expected) decreasing bandwidth order, the supported DNS request types are:
.IR NULL ,
.IR PRIVATE ,
.IR TXT ,
.IR SRV ,
.IR MX ,
@ -183,7 +187,10 @@ and
.I A
may/will cause additional lookups by "smart" caching
nameservers to get an actual IP address, which may either slow down or fail
completely.
completely. The
.IR PRIVATE
type uses value 65399 (in the 'private use' range) and requires servers
implementing RFC 3597.
.TP
.B -O downenc
Force downstream encoding type for all query type responses except NULL.
@ -240,7 +247,7 @@ rejected, however this will cause problems when requests are routed
via a cluster of DNS servers.
.TP
.B -s
Don't try to configure IP address or MTU.
Don't try to configure IP address or MTU.
This should only be used if you have already configured the device that will be
used.
.TP
@ -256,18 +263,22 @@ This is easily done with : "LC_ALL=C luit iodined \-DD ..."
(see luit(1)).
.TP
.B -m mtu
Set 'mtu' as mtu size for the tun device.
Set 'mtu' as mtu size for the tun device.
This will be sent to the client on login, and the client will use the same mtu
for its tun device. Default 1130. Note that the DNS traffic will be
automatically fragmented when needed.
.TP
.B -l listen_ip
Make the server listen only on 'listen_ip' for incoming requests.
By default, incoming requests are accepted from all interfaces.
.B -l listen_ip4
Make the server listen only on 'listen_ip4' for incoming IPv4 requests.
By default, incoming requests are accepted from all interfaces (0.0.0.0).
.TP
.B -L listen_ip6
Make the server listen only on 'listen_ip6' for incoming IPv6 requests.
By default, incoming requests are accepted from all interfaces (::)
.TP
.B -p port
Make the server listen on 'port' instead of 53 for traffic.
If 'listen_ip' does not include localhost, this 'port' can be the same
Make the server listen on 'port' instead of 53 for traffic.
If 'listen_ip4' does not include localhost, this 'port' can be the same
as 'dnsport'.
.B Note:
You must make sure the dns requests are forwarded to this port yourself.
@ -275,7 +286,7 @@ You must make sure the dns requests are forwarded to this port yourself.
.B -n auto|external_ip
The IP address to return in NS responses. Default is to return the address used
as destination in the query.
If external_ip is 'auto', iodined will use externalip.net web service to
If external_ip is 'auto', iodined will use ipify.org web service to
retrieve the external IP of the host and use that for NS responses.
.TP
.B -b dnsport
@ -303,7 +314,7 @@ file.
.B topdomain
The dns traffic will be sent as queries for subdomains under
\'topdomain'. This is normally a subdomain to a domain you own. Use a short
domain name to get better throughput. If
domain name to get better throughput. If
.B nameserver
is the iodined server, then the topdomain can be chosen freely. This argument
must be the same on both the client and the server.
@ -311,15 +322,15 @@ must be the same on both the client and the server.
.TP
.B tunnel_ip[/netmask]
This is the server's ip address on the tun interface. The client will be
given the next ip number in the range. It is recommended to use the
given the next ip number in the range. It is recommended to use the
10.0.0.0 or 172.16.0.0 ranges. The default netmask is /27, can be overridden
by specifying it here. Using a smaller network will limit the number of
concurrent users.
.TP
.B topdomain
The dns traffic is expected to arrive as queries for
subdomains under 'topdomain'. This is normally a subdomain to a domain you
own. Use a short domain name to get better throughput. This argument must be
subdomains under 'topdomain'. This is normally a subdomain to a domain you
own. Use a short domain name to get better throughput. This argument must be
the same on both the client and the server. Queries for domains other
than 'topdomain' will be forwarded when the \-b option is given, otherwise
they will be dropped.
@ -344,7 +355,7 @@ except to the used ssh or vpn ports.
If the environment variable
.B IODINE_PASS
is set, iodine will use the value it is set to as password instead of asking
for one. The
for one. The
.B -P
option still has precedence.
.SS IODINED_PASS

View File

@ -1,7 +1,25 @@
/*
* Copyright (c) 2009 Marcel Bokhorst <marcel@bokhorst.biz>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __FIX_ANDROID_H__
#define __FIX_ANDROID_H__
/* Newer android platforms can have this data already */
#ifndef C_IN
typedef struct {
unsigned id :16;
unsigned rd :1;
@ -36,4 +54,6 @@ typedef struct {
#define T_TXT 16
#define T_SRV 33
#endif /* !C_IN */
#endif

View File

@ -1,7 +1,7 @@
/*
* Copyright (C) 2009 J.A.Bezemer@opensourcepartners.nl
*
* Permission to use, copy, modify, and distribute this software for any
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
@ -46,7 +46,7 @@
* accent chars since they might readily be entered in normal use,
* don't use 254-255 because of possible function overloading in DNS systems.
*/
static const unsigned char cb128[] =
static const unsigned char cb128[] =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
"\274\275\276\277"
"\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"
@ -79,19 +79,19 @@ struct encoder
return &base128_encoder;
}
static int
static int
base128_handles_dots()
{
return 0;
}
static int
static int
base128_blksize_raw()
{
return BLKSIZE_RAW;
}
static int
static int
base128_blksize_enc()
{
return BLKSIZE_ENC;
@ -113,7 +113,7 @@ base128_reverse_init()
}
}
static int
static int
base128_encode(char *buf, size_t *buflen, const void *data, size_t size)
/*
* Fills *buf with max. *buflen characters, encoding size bytes of *data.
@ -235,7 +235,7 @@ base128_decode(void *buf, size_t *buflen, const char *str, size_t slen)
if (iout >= *buflen || iin + 1 >= slen ||
str[iin] == '\0' || str[iin + 1] == '\0')
break;
ubuf[iout] = ((REV128(ustr[iin]) & 0x7f) << 1) |
ubuf[iout] = ((REV128(ustr[iin]) & 0x7f) << 1) |
((REV128(ustr[iin + 1]) & 0x40) >> 6);
iin++; /* 0 used up, iin=1 */
iout++;

View File

@ -1,7 +1,7 @@
/*
* Copyright (C) 2009 J.A.Bezemer@opensourcepartners.nl
*
* Permission to use, copy, modify, and distribute this software for any
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*

View File

@ -1,8 +1,9 @@
/*
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
* 2006-2009 Bjorn Andersson <flex@kryo.se>
* Mostly rewritten 2009 J.A.Bezemer@opensourcepartners.nl
*
* Permission to use, copy, modify, and distribute this software for any
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
@ -29,9 +30,9 @@
#define BLKSIZE_RAW 5
#define BLKSIZE_ENC 8
static const char cb32[] =
static const char cb32[] =
"abcdefghijklmnopqrstuvwxyz012345";
static const char cb32_ucase[] =
static const char cb32_ucase[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ012345";
static unsigned char rev32[256];
static int reverse_init = 0;
@ -59,19 +60,19 @@ struct encoder
return &base32_encoder;
}
static int
static int
base32_handles_dots()
{
return 0;
}
static int
static int
base32_blksize_raw()
{
return BLKSIZE_RAW;
}
static int
static int
base32_blksize_enc()
{
return BLKSIZE_ENC;
@ -108,7 +109,7 @@ b32_8to5(int in)
return rev32[in];
}
static int
static int
base32_encode(char *buf, size_t *buflen, const void *data, size_t size)
/*
* Fills *buf with max. *buflen characters, encoding size bytes of *data.
@ -226,7 +227,7 @@ base32_decode(void *buf, size_t *buflen, const char *str, size_t slen)
if (iout >= *buflen || iin + 1 >= slen ||
str[iin] == '\0' || str[iin + 1] == '\0')
break;
ubuf[iout] = ((REV32(str[iin]) & 0x1f) << 3) |
ubuf[iout] = ((REV32(str[iin]) & 0x1f) << 3) |
((REV32(str[iin + 1]) & 0x1c) >> 2);
iin++; /* 0 used up, iin=1 */
iout++;
@ -235,8 +236,8 @@ base32_decode(void *buf, size_t *buflen, const char *str, size_t slen)
str[iin] == '\0' || str[iin + 1] == '\0' ||
str[iin + 2] == '\0')
break;
ubuf[iout] = ((REV32(str[iin]) & 0x03) << 6) |
((REV32(str[iin + 1]) & 0x1f) << 1) |
ubuf[iout] = ((REV32(str[iin]) & 0x03) << 6) |
((REV32(str[iin + 1]) & 0x1f) << 1) |
((REV32(str[iin + 2]) & 0x10) >> 4);
iin += 2; /* 1,2 used up, iin=3 */
iout++;

View File

@ -1,7 +1,8 @@
/*
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
* 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*

View File

@ -1,8 +1,9 @@
/*
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
* 2006-2009 Bjorn Andersson <flex@kryo.se>
* Mostly rewritten 2009 J.A.Bezemer@opensourcepartners.nl
*
* Permission to use, copy, modify, and distribute this software for any
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
@ -31,7 +32,7 @@
/* Note: the "unofficial" char is last here, which means that the \377 pattern
in DOWNCODECCHECK1 ('Y' request) will properly test it. */
static const char cb64[] =
static const char cb64[] =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789+";
static unsigned char rev64[256];
static int reverse_init = 0;
@ -59,19 +60,19 @@ struct encoder
return &base64_encoder;
}
static int
static int
base64_handles_dots()
{
return 0;
}
static int
static int
base64_blksize_raw()
{
return BLKSIZE_RAW;
}
static int
static int
base64_blksize_enc()
{
return BLKSIZE_ENC;
@ -93,7 +94,7 @@ base64_reverse_init()
}
}
static int
static int
base64_encode(char *buf, size_t *buflen, const void *data, size_t size)
/*
* Fills *buf with max. *buflen characters, encoding size bytes of *data.
@ -181,7 +182,7 @@ base64_decode(void *buf, size_t *buflen, const char *str, size_t slen)
if (iout >= *buflen || iin + 1 >= slen ||
str[iin] == '\0' || str[iin + 1] == '\0')
break;
ubuf[iout] = ((REV64(str[iin]) & 0x3f) << 2) |
ubuf[iout] = ((REV64(str[iin]) & 0x3f) << 2) |
((REV64(str[iin + 1]) & 0x30) >> 4);
iin++; /* 0 used up, iin=1 */
iout++;
@ -189,7 +190,7 @@ base64_decode(void *buf, size_t *buflen, const char *str, size_t slen)
if (iout >= *buflen || iin + 1 >= slen ||
str[iin] == '\0' || str[iin + 1] == '\0')
break;
ubuf[iout] = ((REV64(str[iin]) & 0x0f) << 4) |
ubuf[iout] = ((REV64(str[iin]) & 0x0f) << 4) |
((REV64(str[iin + 1]) & 0x3c) >> 2);
iin++; /* 1 used up, iin=2 */
iout++;

View File

@ -1,7 +1,8 @@
/*
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
* 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*

View File

@ -1,7 +1,8 @@
/*
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
* 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
@ -23,6 +24,7 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <signal.h>
#include <unistd.h>
#include <sys/param.h>
@ -34,10 +36,10 @@
#ifdef WINDOWS32
#include "windows.h"
#else
#include <arpa/nameser.h>
#ifdef ANDROID
#include "android_dns.h"
#endif
#include <arpa/nameser.h>
#ifdef DARWIN
#define BIND_8_COMPAT
#include <arpa/nameser_compat.h>
@ -65,7 +67,9 @@ static int running;
static const char *password;
static struct sockaddr_storage nameserv;
static struct sockaddr_in raw_serv;
static int nameserv_len;
static struct sockaddr_storage raw_serv;
static int raw_serv_len;
static const char *topdomain;
static uint16_t rand_seed;
@ -95,10 +99,10 @@ static struct encoder *b128;
/* The encoder used for data packets
* Defaults to Base32, can be changed after handshake */
static struct encoder *dataenc;
/* The encoder to use for downstream data */
static char downenc = ' ';
/* set query type to send */
static unsigned short do_qtype = T_UNSET;
@ -155,6 +159,7 @@ void
client_set_nameserver(struct sockaddr_storage *addr, int addrlen)
{
memcpy(&nameserv, addr, addrlen);
nameserv_len = addrlen;
}
void
@ -169,11 +174,13 @@ client_set_password(const char *cp)
password = cp;
}
void
set_qtype(char *qtype)
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"))
@ -184,14 +191,16 @@ set_qtype(char *qtype)
do_qtype = T_SRV;
else if (!strcasecmp(qtype, "TXT"))
do_qtype = T_TXT;
return (do_qtype == T_UNSET);
}
char *
get_qtype()
client_get_qtype()
{
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";
@ -202,7 +211,7 @@ get_qtype()
}
void
set_downenc(char *encoding)
client_set_downenc(char *encoding)
{
if (!strcasecmp(encoding, "base32"))
downenc = 'T';
@ -216,7 +225,7 @@ set_downenc(char *encoding)
downenc = 'R';
}
void
void
client_set_selecttimeout(int select_timeout)
{
selecttimeout = select_timeout;
@ -238,7 +247,7 @@ client_set_hostname_maxlen(int i)
const char *
client_get_raw_addr()
{
return inet_ntoa(raw_serv.sin_addr);
return format_addr(&raw_serv, raw_serv_len);
}
static void
@ -268,7 +277,7 @@ send_query(int fd, char *hostname)
fprintf(stderr, " Sendquery: id %5d name[0] '%c'\n", q.id, hostname[0]);
#endif
sendto(fd, packet, len, 0, (struct sockaddr*)&nameserv, sizeof(nameserv));
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.
@ -335,7 +344,7 @@ send_packet(int fd, char cmd, const char *data, const size_t datalen)
char buf[4096];
buf[0] = cmd;
build_hostname(buf + 1, sizeof(buf) - 1, data, datalen, topdomain,
b32, hostname_maxlen);
send_query(fd, buf);
@ -368,7 +377,7 @@ send_chunk(int fd)
/* Build upstream data header (see doc/proto_xxxxxxxx.txt) */
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 */
@ -382,7 +391,7 @@ send_chunk(int fd)
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,
@ -397,12 +406,12 @@ send_ping(int fd)
{
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;
rand_seed++;
#if 0
@ -568,7 +577,7 @@ read_dns_withq(int dns_fd, int tun_fd, char *buf, int buflen, struct query *q)
int r;
addrlen = sizeof(from);
if ((r = recvfrom(dns_fd, data, sizeof(data), 0,
if ((r = recvfrom(dns_fd, data, sizeof(data), 0,
(struct sockaddr*)&from, &addrlen)) < 0) {
warn("recvfrom");
return -1;
@ -590,9 +599,9 @@ read_dns_withq(int dns_fd, int tun_fd, char *buf, int buflen, struct query *q)
/*
* 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
*/
@ -1133,11 +1142,11 @@ client_tunnel(int tun_fd, int dns_fd)
warnx("No downstream data received in 60 seconds, shutting down.");
running = 0;
}
if (running == 0)
break;
if (i < 0)
if (i < 0)
err(1, "select");
if (i == 0) {
@ -1180,7 +1189,7 @@ client_tunnel(int tun_fd, int dns_fd)
if (FD_ISSET(dns_fd, &fds)) {
if (tunnel_dns(tun_fd, dns_fd) <= 0)
continue;
}
}
}
}
@ -1198,7 +1207,7 @@ send_login(int fd, char *login, int len)
data[17] = (rand_seed >> 8) & 0xff;
data[18] = (rand_seed >> 0) & 0xff;
rand_seed++;
send_packet(fd, 'l', data, sizeof(data));
@ -1237,23 +1246,23 @@ static void
send_set_downstream_fragsize(int fd, int fragsize)
{
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;
rand_seed++;
send_packet(fd, 'n', data, sizeof(data));
}
static void
static void
send_version(int fd, uint32_t version)
{
char data[6];
data[0] = (version >> 24) & 0xff;
data[1] = (version >> 16) & 0xff;
data[2] = (version >> 8) & 0xff;
@ -1261,7 +1270,7 @@ send_version(int fd, uint32_t version)
data[4] = (rand_seed >> 8) & 0xff;
data[5] = (rand_seed >> 0) & 0xff;
rand_seed++;
send_packet(fd, 'v', data, sizeof(data));
@ -1272,7 +1281,7 @@ send_ip_request(int fd, int 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);
@ -1296,7 +1305,7 @@ 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___";
buf[1] = b32_5to8((rand_seed >> 10) & 0x1f);
buf[2] = b32_5to8((rand_seed >> 5) & 0x1f);
buf[3] = b32_5to8((rand_seed ) & 0x1f);
@ -1332,7 +1341,7 @@ send_codec_switch(int fd, int userid, int 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);
@ -1411,7 +1420,7 @@ handshake_version(int dns_fd, int *seed)
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",
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) {
@ -1420,7 +1429,7 @@ handshake_version(int dns_fd, int *seed)
}
} 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)");
@ -1439,7 +1448,7 @@ handshake_login(int dns_fd, int seed)
int read;
login_calculate(login, 16, password, seed);
for (i=0; running && i<5 ;i++) {
send_login(dns_fd, login, 16);
@ -1484,8 +1493,10 @@ handshake_raw_udp(int dns_fd, int seed)
int i;
int r;
int len;
unsigned remoteaddr = 0;
struct in_addr server;
int got_addr;
memset(&raw_serv, 0, sizeof(raw_serv));
got_addr = 0;
fprintf(stderr, "Testing raw UDP data to the server (skip with -r)");
for (i=0; running && i<3 ;i++) {
@ -1495,15 +1506,23 @@ handshake_raw_udp(int dns_fd, int seed)
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);
/* Received IPv4 address */
struct sockaddr_in *raw4_serv = (struct sockaddr_in *) &raw_serv;
raw4_serv->sin_family = AF_INET;
memcpy(&raw4_serv->sin_addr, &in[1], sizeof(struct in_addr));
raw4_serv->sin_port = htons(53);
raw_serv_len = sizeof(struct sockaddr_in);
got_addr = 1;
break;
}
if (len == 17 && in[0] == 'I') {
/* Received IPv6 address */
struct sockaddr_in6 *raw6_serv = (struct sockaddr_in6 *) &raw_serv;
raw6_serv->sin6_family = AF_INET6;
memcpy(&raw6_serv->sin6_addr, &in[1], sizeof(struct in6_addr));
raw6_serv->sin6_port = htons(53);
raw_serv_len = sizeof(struct sockaddr_in6);
got_addr = 1;
break;
}
@ -1513,21 +1532,15 @@ handshake_raw_udp(int dns_fd, int seed)
fprintf(stderr, "\n");
if (!running)
return 0;
if (!remoteaddr) {
if (!got_addr) {
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));
fprintf(stderr, "Server is at %s, trying raw login: ", format_addr(&raw_serv, raw_serv_len));
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;
/* do login against port 53 on remote 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++) {
@ -1535,7 +1548,7 @@ handshake_raw_udp(int dns_fd, int seed)
tv.tv_usec = 0;
send_raw_udp_login(dns_fd, userid, seed);
FD_ZERO(&fds);
FD_SET(dns_fd, &fds);
@ -1548,7 +1561,7 @@ handshake_raw_udp(int dns_fd, int seed)
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
&& RAW_HDR_GET_CMD(in) == RAW_HDR_CMD_LOGIN
&& memcmp(&in[RAW_HDR_LEN], hash, sizeof(hash)) == 0) {
fprintf(stderr, "OK\n");
@ -1559,7 +1572,7 @@ handshake_raw_udp(int dns_fd, int seed)
fprintf(stderr, ".");
fflush(stderr);
}
fprintf(stderr, "failed\n");
return 0;
}
@ -1788,7 +1801,7 @@ handshake_downenc_autodetect(int dns_fd)
int base64uok = 0;
int base128ok = 0;
if (do_qtype == T_NULL) {
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 ' ';
@ -1842,13 +1855,14 @@ handshake_qtypetest(int dns_fd, int timeout)
int trycodec;
int k;
if (do_qtype == T_NULL)
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 to work. */
byte values can be returned, which is needed for NULL/PRIVATE
to work. */
send_downenctest(dns_fd, trycodec, 1, NULL, 0);
@ -1873,11 +1887,12 @@ handshake_qtype_numcvt(int num)
{
switch (num) {
case 0: return T_NULL;
case 1: return T_TXT;
case 2: return T_SRV;
case 3: return T_MX;
case 4: return T_CNAME;
case 5: return T_A;
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;
}
@ -1920,7 +1935,7 @@ handshake_qtype_autodetect(int dns_fd)
highestworking = qtypenum;
#if 0
fprintf(stderr, " Type %s timeout %d works\n",
get_qtype(), timeout);
client_get_qtype(), timeout);
#endif
break;
/* try others with longer timeout */
@ -2027,7 +2042,7 @@ handshake_switch_codec(int dns_fd, int bits)
for (i=0; running && i<5 ;i++) {
send_codec_switch(dns_fd, userid, bits);
read = handshake_waitdns(dns_fd, in, sizeof(in), 's', 'S', i+1);
if (read > 0) {
@ -2054,7 +2069,7 @@ handshake_switch_codec(int dns_fd, int bits)
fprintf(stderr, "No reply from server on codec switch. ");
codec_revert:
codec_revert:
fprintf(stderr, "Falling back to upstream codec %s\n", dataenc->name);
}
@ -2106,7 +2121,7 @@ handshake_switch_downenc(int dns_fd)
fprintf(stderr, "No reply from server on codec switch. ");
codec_revert:
codec_revert:
fprintf(stderr, "Falling back to downstream codec Base32\n");
}
@ -2148,7 +2163,7 @@ handshake_try_lazy(int dns_fd)
fprintf(stderr, "No reply from server on lazy switch. ");
codec_revert:
codec_revert:
fprintf(stderr, "Falling back to legacy mode\n");
lazymode = 0;
selecttimeout = 1;
@ -2265,7 +2280,7 @@ handshake_autoprobe_fragsize(int dns_fd)
int max_fragsize;
max_fragsize = 0;
fprintf(stderr, "Autoprobing max downstream fragment size... (skip with -m fragsize)\n");
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++) {
@ -2273,7 +2288,7 @@ handshake_autoprobe_fragsize(int dns_fd)
send_fragsize_probe(dns_fd, proposed_fragsize);
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)
@ -2319,7 +2334,7 @@ handshake_autoprobe_fragsize(int dns_fd)
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_TXT ||
(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");
@ -2382,7 +2397,7 @@ client_handshake(int dns_fd, int raw_mode, int autodetect_frag_size, int fragsiz
}
}
fprintf(stderr, "Using DNS type %s queries\n", get_qtype());
fprintf(stderr, "Using DNS type %s queries\n", client_get_qtype());
r = handshake_version(dns_fd, &seed);
if (r) {

View File

@ -1,7 +1,8 @@
/*
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
* 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
@ -26,9 +27,9 @@ const char *client_get_raw_addr();
void client_set_nameserver(struct sockaddr_storage *, int);
void client_set_topdomain(const char *cp);
void client_set_password(const char *cp);
void set_qtype(char *qtype);
char *get_qtype();
void set_downenc(char *encoding);
int client_set_qtype(char *qtype);
char *client_get_qtype();
void client_set_downenc(char *encoding);
void client_set_selecttimeout(int select_timeout);
void client_set_lazymode(int lazy_mode);
void client_set_hostname_maxlen(int i);

View File

@ -1,7 +1,8 @@
/* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
/* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
* 2006-2009 Bjorn Andersson <flex@kryo.se>
* Copyright (c) 2007 Albert Lee <trisk@acm.jhu.edu>.
*
* Permission to use, copy, modify, and distribute this software for any
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
@ -64,7 +65,7 @@ const unsigned char raw_header[RAW_HDR_LEN] = { 0x10, 0xd1, 0x9e, 0x00 };
static int daemon(int nochdir, int noclose)
{
int fd, i;
switch (fork()) {
case 0:
break;
@ -73,15 +74,15 @@ static int daemon(int nochdir, int noclose)
default:
_exit(0);
}
if (!nochdir) {
chdir("/");
}
if (setsid() < 0) {
return -1;
}
if (!noclose) {
if ((fd = open("/dev/null", O_RDWR)) >= 0) {
for (i = 0; i < 3; i++) {
@ -153,8 +154,8 @@ get_addr(char *host, int port, int addr_family, int flags, struct sockaddr_stora
memset(&hints, 0, sizeof(hints));
hints.ai_family = addr_family;
#ifdef WINDOWS32
/* AI_ADDRCONFIG misbehaves on windows */
#if defined(WINDOWS32) || defined(OPENBSD)
/* AI_ADDRCONFIG misbehaves on windows, and does not exist in OpenBSD */
hints.ai_flags = flags;
#else
hints.ai_flags = AI_ADDRCONFIG | flags;
@ -173,10 +174,16 @@ get_addr(char *host, int port, int addr_family, int flags, struct sockaddr_stora
return res;
}
int
int
open_dns(struct sockaddr_storage *sockaddr, size_t sockaddr_len)
{
int flag = 1;
return open_dns_opt(sockaddr, sockaddr_len, -1);
}
int
open_dns_opt(struct sockaddr_storage *sockaddr, size_t sockaddr_len, int v6only)
{
int flag;
int fd;
if ((fd = socket(sockaddr->ss_family, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
@ -190,10 +197,13 @@ open_dns(struct sockaddr_storage *sockaddr, size_t sockaddr_len)
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));
fd_set_close_on_exec(fd);
#endif
if (sockaddr->ss_family == AF_INET6 && v6only >= 0) {
setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (const void*) &v6only, sizeof(v6only));
}
#ifdef IP_OPT_DONT_FRAG
/* Set dont-fragment ip header flag */
flag = DONT_FRAG_VALUE;
@ -294,7 +304,7 @@ read_password(char *buf, size_t len)
tcgetattr(0, &tp);
old = tp;
tp.c_lflag &= (~ECHO);
tcsetattr(0, TCSANOW, &tp);
#else
@ -320,7 +330,7 @@ read_password(char *buf, size_t len)
fprintf(stderr, "\n");
#ifndef WINDOWS32
tcsetattr(0, TCSANOW, &old);
tcsetattr(0, TCSANOW, &old);
#endif
strncpy(buf, pwd, len);
@ -328,20 +338,64 @@ read_password(char *buf, size_t len)
}
int
check_topdomain(char *str)
check_topdomain(char *str, char **errormsg)
{
int i;
int i;
int dots = 0;
int chunklen = 0;
if(str[0] == '.') /* special case */
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;
}
for( i = 0; i < strlen(str); i++) {
if( isalpha(str[i]) || isdigit(str[i]) || str[i] == '-' || str[i] == '.' )
continue;
else
return 1;
}
return 0;
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;
}
}
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;
}
#if defined(WINDOWS32) || defined(ANDROID)
@ -354,31 +408,43 @@ inet_aton(const char *cp, struct in_addr *inp)
}
#endif
void
vwarn(const char *fmt, va_list list)
{
if (fmt) vfprintf(stderr, fmt, list);
#ifndef ANDROID
if (errno == 0) {
fprintf(stderr, ": WSA error %d\n", WSAGetLastError());
} else {
fprintf(stderr, ": %s\n", strerror(errno));
}
#endif
}
void
warn(const char *fmt, ...)
{
va_list 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));
}
#endif
vwarn(fmt, list);
va_end(list);
}
void
vwarnx(const char *fmt, va_list list)
{
if (fmt) vfprintf(stderr, fmt, list);
fprintf(stderr, "\n");
}
void
warnx(const char *fmt, ...)
{
va_list list;
va_start(list, fmt);
if (fmt) fprintf(stderr, fmt, list);
fprintf(stderr, "\n");
vwarnx(fmt, list);
va_end(list);
}
@ -388,7 +454,7 @@ err(int eval, const char *fmt, ...)
va_list list;
va_start(list, fmt);
warn(fmt, list);
vwarn(fmt, list);
va_end(list);
exit(eval);
}
@ -399,7 +465,7 @@ errx(int eval, const char *fmt, ...)
va_list list;
va_start(list, fmt);
warnx(fmt, list);
vwarnx(fmt, list);
va_end(list);
exit(eval);
}
@ -420,3 +486,22 @@ int recent_seqno(int ourseqno, int gotseqno)
}
return 0;
}
#ifndef WINDOWS32
/* Set FD_CLOEXEC flag on file descriptor.
* This stops it from being inherited by system() calls.
*/
void
fd_set_close_on_exec(int fd)
{
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");
}
#endif

View File

@ -1,7 +1,8 @@
/*
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* Copyright (c) 2006-2015 Erik Ekman <yarrick@kryo.se>,
* 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
@ -52,14 +53,6 @@ extern const unsigned char raw_header[RAW_HDR_LEN];
#define QUERY_NAME_SIZE 256
#if defined IP_RECVDSTADDR
# define DSTADDR_SOCKOPT IP_RECVDSTADDR
# define dstaddr(x) ((struct in_addr *) CMSG_DATA(x))
#elif defined IP_PKTINFO
# define DSTADDR_SOCKOPT IP_PKTINFO
# define dstaddr(x) (&(((struct in_pktinfo *)(CMSG_DATA(x)))->ipi_addr))
#endif
#if defined IP_MTU_DISCOVER
/* Linux */
# define IP_OPT_DONT_FRAG IP_MTU_DISCOVER
@ -74,10 +67,12 @@ extern const unsigned char raw_header[RAW_HDR_LEN];
# define DONT_FRAG_VALUE 1
#endif
#define T_PRIVATE 65399
/* Undefined RR type; "private use" range, see http://www.bind9.net/dns-parameters */
#define T_UNSET 65432
/* Unused RR type; "private use" range, see http://www.bind9.net/dns-parameters */
/* Unused RR type, never actually sent */
struct packet
struct packet
{
int len; /* Total packet length */
int sentlen; /* Length of chunk currently transmitted */
@ -92,16 +87,17 @@ struct query {
unsigned short type;
unsigned short rcode;
unsigned short id;
struct in_addr destination;
struct sockaddr_storage destination;
socklen_t dest_len;
struct sockaddr_storage from;
int fromlen;
socklen_t fromlen;
unsigned short id2;
struct sockaddr from2;
int fromlen2;
struct sockaddr_storage from2;
socklen_t fromlen2;
};
enum connection {
CONN_RAW_UDP,
CONN_RAW_UDP = 0,
CONN_DNS_NULL,
CONN_MAX
};
@ -110,6 +106,7 @@ void check_superuser(void (*usage_fn)(void));
char *format_addr(struct sockaddr_storage *sockaddr, int sockaddr_len);
int get_addr(char *, int, int, int, struct sockaddr_storage *);
int open_dns(struct sockaddr_storage *, size_t);
int open_dns_opt(struct sockaddr_storage *sockaddr, size_t sockaddr_len, int v6only);
int open_dns_from_host(char *host, int port, int addr_family, int flags);
void close_dns(int);
@ -120,7 +117,7 @@ void do_pidfile(char *);
void read_password(char*, size_t);
int check_topdomain(char *);
int check_topdomain(char *, char **);
#if defined(WINDOWS32) || defined(ANDROID)
#ifndef ANDROID
@ -135,4 +132,8 @@ void warnx(const char *fmt, ...);
int recent_seqno(int , int);
#ifndef WINDOWS32
void fd_set_close_on_exec(int fd);
#endif
#endif

View File

@ -1,7 +1,8 @@
/*
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
* 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
@ -24,14 +25,12 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <strings.h>
#include <ctype.h>
#ifdef WINDOWS32
#include "windows.h"
#else
#ifdef ANDROID
#include "android_dns.h"
#endif
#include <arpa/nameser.h>
#ifdef DARWIN
#define BIND_8_COMPAT
@ -40,6 +39,9 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <err.h>
#ifdef ANDROID
#include "android_dns.h"
#endif
#endif
@ -64,9 +66,9 @@ dns_encode(char *buf, size_t buflen, struct query *q, qr_t qr, char *data, size_
return 0;
memset(buf, 0, buflen);
header = (HEADER*)buf;
header->id = htons(q->id);
header->qr = (qr == QR_ANSWER);
header->opcode = 0;
@ -80,7 +82,7 @@ dns_encode(char *buf, size_t buflen, struct query *q, qr_t qr, char *data, size_
switch (qr) {
case QR_ANSWER:
header->qdcount = htons(1);
name = 0xc000 | ((p - buf) & 0x3fff);
/* Question section */
@ -99,7 +101,7 @@ dns_encode(char *buf, size_t buflen, struct query *q, qr_t qr, char *data, size_
int namelen;
CHECKLEN(10);
putshort(&p, name);
putshort(&p, name);
if (q->type == T_A)
/* answer CNAME to A question */
putshort(&p, T_CNAME);
@ -129,7 +131,7 @@ dns_encode(char *buf, size_t buflen, struct query *q, qr_t qr, char *data, size_
ancnt = 1;
while (1) {
CHECKLEN(10);
putshort(&p, name);
putshort(&p, name);
putshort(&p, q->type);
putshort(&p, C_IN);
putlong(&p, 0); /* TTL */
@ -164,7 +166,7 @@ dns_encode(char *buf, size_t buflen, struct query *q, qr_t qr, char *data, size_
int txtlen;
CHECKLEN(10);
putshort(&p, name);
putshort(&p, name);
putshort(&p, q->type);
putshort(&p, C_IN);
putlong(&p, 0); /* TTL */
@ -181,7 +183,7 @@ dns_encode(char *buf, size_t buflen, struct query *q, qr_t qr, char *data, size_
/* NULL has raw binary data */
CHECKLEN(10);
putshort(&p, name);
putshort(&p, name);
putshort(&p, q->type);
putshort(&p, C_IN);
putlong(&p, 0); /* TTL */
@ -200,7 +202,7 @@ dns_encode(char *buf, size_t buflen, struct query *q, qr_t qr, char *data, size_
/* Note that iodined also uses this for forward queries */
header->qdcount = htons(1);
datalen = MIN(datalen, buflen - (p - buf));
putname(&p, datalen, data);
@ -223,7 +225,7 @@ dns_encode(char *buf, size_t buflen, struct query *q, qr_t qr, char *data, size_
break;
}
len = p - buf;
return len;
@ -247,9 +249,9 @@ dns_encode_ns_response(char *buf, size_t buflen, struct query *q, char *topdomai
return 0;
memset(buf, 0, buflen);
header = (HEADER*)buf;
header->id = htons(q->id);
header->qr = 1;
header->opcode = 0;
@ -336,9 +338,9 @@ dns_encode_a_response(char *buf, size_t buflen, struct query *q)
return 0;
memset(buf, 0, buflen);
header = (HEADER*)buf;
header->id = htons(q->id);
header->qr = 1;
header->opcode = 0;
@ -406,11 +408,11 @@ dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, siz
short qdcount;
short ancount;
uint32_t ttl;
short class;
short type;
unsigned short class;
unsigned short type;
char *data;
short rlen;
int id;
unsigned short rlen;
int id;
int rv;
q->id2 = 0;
@ -418,9 +420,9 @@ dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, siz
header = (HEADER*)packet;
/* Reject short packets */
if (packetlen < sizeof(HEADER))
if (packetlen < sizeof(HEADER))
return 0;
if (header->qr != qr) {
warnx("header->qr does not match the requested qr");
return -1;
@ -429,13 +431,13 @@ dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, siz
data = packet + sizeof(HEADER);
qdcount = ntohs(header->qdcount);
ancount = ntohs(header->ancount);
id = ntohs(header->id);
id = id & 0xFFFF; /* Kill any sign extension */
rlen = 0;
if (q != NULL)
if (q != NULL)
q->rcode = header->rcode;
switch (qr) {
@ -445,7 +447,7 @@ dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, siz
return -1;
}
if (q != NULL)
if (q != NULL)
q->id = id;
/* Read name even if no answer, to give better error message */
@ -453,14 +455,14 @@ dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, siz
CHECKLEN(4);
readshort(packet, &data, &type);
readshort(packet, &data, &class);
/* if CHECKLEN okay, then we're sure to have a proper name */
if (q != NULL) {
/* We only need the first char to check it */
q->name[0] = name[0];
q->name[1] = '\0';
}
}
if (ancount < 1) {
/* DNS errors like NXDOMAIN have ancount=0 and
stop here. CNAME may also have A; MX/SRV may have
@ -469,7 +471,7 @@ dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, siz
}
/* Here type is still the question type */
if (type == T_NULL) {
if (type == T_NULL || type == T_PRIVATE) {
/* Assume that first answer is what we wanted */
readname(packet, packetlen, &data, name, sizeof(name));
CHECKLEN(10);
@ -511,7 +513,7 @@ dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, siz
*/
char names[250][QUERY_NAME_SIZE];
char *rdatastart;
short pref;
unsigned short pref;
int i;
int offset;
@ -541,7 +543,7 @@ dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, siz
names[pref / 10 - 1][QUERY_NAME_SIZE-1] = '\0';
}
/* always trust rlen, not name encoding */
/* always trust rlen, not name encoding */
data = rdatastart + rlen;
CHECKLEN(0);
}

View File

@ -1,7 +1,8 @@
/*
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
* 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*

View File

@ -1,7 +1,8 @@
/*
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
* 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
@ -23,8 +24,8 @@
#include "encoding.h"
int
build_hostname(char *buf, size_t buflen,
const char *data, const size_t datalen,
build_hostname(char *buf, size_t buflen,
const char *data, const size_t datalen,
const char *topdomain, struct encoder *encoder, int maxlen)
{
size_t space;
@ -37,7 +38,7 @@ build_hostname(char *buf, size_t buflen,
space -= (space / 57); /* space for dots */
memset(buf, 0, buflen);
encoder->encode(buf, &space, data, datalen);
if (!encoder->places_dots())
@ -48,7 +49,7 @@ build_hostname(char *buf, size_t buflen,
/* move b back one step to see if the dot is there */
b--;
if (*b != '.')
if (*b != '.')
*++b = '.';
b++;
/* move b ahead of the string so we can copy to it */
@ -66,7 +67,7 @@ unpack_data(char *buf, size_t buflen, char *data, size_t datalen, struct encoder
return enc->decode(buf, &buflen, data, datalen);
}
int
int
inline_dotify(char *buf, size_t buflen)
{
unsigned dots;
@ -104,7 +105,7 @@ inline_dotify(char *buf, size_t buflen)
return total;
}
int
int
inline_undotify(char *buf, size_t len)
{
unsigned pos;
@ -127,7 +128,7 @@ inline_undotify(char *buf, size_t len)
*writer++ = *reader++;
pos++;
}
/* return new length of string */
return len - dots;
}

View File

@ -1,7 +1,8 @@
/*
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
* 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*

View File

@ -1,7 +1,7 @@
/*
* Copyright (c) 2008 Erik Ekman <yarrick@kryo.se>
* Copyright (c) 2008-2014 Erik Ekman <yarrick@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
@ -33,9 +33,9 @@ void fw_query_init()
void fw_query_put(struct fw_query *fw_query)
{
memcpy(&(fwq[fwq_ix]), fw_query, sizeof(struct fw_query));
++fwq_ix;
if (fwq_ix >= FW_QUERY_CACHE_SIZE)
if (fwq_ix >= FW_QUERY_CACHE_SIZE)
fwq_ix = 0;
}

View File

@ -1,7 +1,7 @@
/*
* Copyright (c) 2008 Erik Ekman <yarrick@kryo.se>
* Copyright (c) 2008-2014 Erik Ekman <yarrick@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*

View File

@ -1,7 +1,8 @@
/*
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
* 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
@ -56,11 +57,17 @@ static char *__progname;
#define PASSWORD_ENV_VAR "IODINE_PASS"
static void
sighandler(int sig)
sighandler(int sig)
{
client_stop();
}
#if defined(__GNUC__) || defined(__clang__)
/* mark as no return to help some compilers to avoid warnings
* about use of uninitialized variables */
static void usage() __attribute__((noreturn));
#endif
static void
usage() {
extern char *__progname;
@ -80,7 +87,7 @@ help() {
"[-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, TXT, SRV, MX, CNAME, A (default: autodetect)\n");
fprintf(stderr, " -T force dns type: NULL, PRIVATE, TXT, SRV, MX, CNAME, A (default: autodetect)\n");
fprintf(stderr, " -O force downstream encoding for -T other than NULL: Base32, Base64, Base64u,\n");
fprintf(stderr, " Base128, or (only for TXT:) Raw (default: autodetect)\n");
fprintf(stderr, " -I max interval between requests (default 4 sec) to prevent DNS timeouts\n");
@ -118,6 +125,7 @@ main(int argc, char **argv)
{
char *nameserv_host;
char *topdomain;
char *errormsg;
#ifndef WINDOWS32
struct passwd *pw;
#endif
@ -147,6 +155,7 @@ main(int argc, char **argv)
nameserv_host = NULL;
topdomain = NULL;
errormsg = NULL;
#ifndef WINDOWS32
pw = NULL;
#endif
@ -174,7 +183,7 @@ main(int argc, char **argv)
srand((unsigned) time(NULL));
client_init();
#if !defined(BSD) && !defined(__GLIBC__)
__progname = strrchr(argv[0], '/');
if (__progname == NULL)
@ -222,9 +231,9 @@ main(int argc, char **argv)
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));
memset(optarg, 0, strlen(optarg));
break;
case 'm':
autodetect_frag_size = 0;
@ -242,12 +251,13 @@ main(int argc, char **argv)
break;
case 'F':
pidfile = optarg;
break;
break;
case 'T':
set_qtype(optarg);
if (client_set_qtype(optarg))
errx(5, "Invalid query type '%s'", optarg);
break;
case 'O': /* not -D, is Debug in server */
set_downenc(optarg);
client_set_downenc(optarg);
break;
case 'L':
lazymode = atoi(optarg);
@ -268,7 +278,7 @@ main(int argc, char **argv)
/* NOTREACHED */
}
}
check_superuser(usage);
argc -= optind;
@ -305,16 +315,10 @@ main(int argc, char **argv)
warnx("No nameserver found - not connected to any network?\n");
usage();
/* NOTREACHED */
}
}
if (strlen(topdomain) <= 128) {
if(check_topdomain(topdomain)) {
warnx("Topdomain contains invalid characters.\n");
usage();
/* NOTREACHED */
}
} else {
warnx("Use a topdomain max 128 chars long.\n");
if(check_topdomain(topdomain, &errormsg)) {
warnx("Invalid topdomain: %s", errormsg);
usage();
/* NOTREACHED */
}
@ -323,7 +327,7 @@ main(int argc, char **argv)
client_set_lazymode(lazymode);
client_set_topdomain(topdomain);
client_set_hostname_maxlen(hostname_maxlen);
if (username != NULL) {
#ifndef WINDOWS32
if ((pw = getpwnam(username)) == NULL) {
@ -333,21 +337,21 @@ main(int argc, char **argv)
}
#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));
}
client_set_password(password);
if ((tun_fd = open_tun(device)) == -1) {
retval = 1;
goto cleanup1;
}
if ((dns_fd = open_dns_from_host(NULL, 53, nameservaddr.ss_family, AI_PASSIVE)) < 0) {
if ((dns_fd = open_dns_from_host(NULL, 0, nameservaddr.ss_family, AI_PASSIVE)) < 0) {
retval = 1;
goto cleanup2;
}
@ -366,22 +370,22 @@ main(int argc, char **argv)
retval = 1;
goto cleanup2;
}
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");
if (foreground == 0)
if (foreground == 0)
do_detach();
if (pidfile != NULL)
do_pidfile(pidfile);
if (newroot != NULL)
do_chroot(newroot);
if (username != NULL) {
#ifndef WINDOWS32
gid_t gids[1];

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,8 @@
/*
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
* 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
@ -30,11 +31,11 @@
#include "md5.h"
/*
* Needs a 16byte array for output, and 32 bytes password
/*
* Needs a 16byte array for output, and 32 bytes password
*/
void
login_calculate(char *buf, int buflen, const char *pass, int seed)
void
login_calculate(char *buf, int buflen, const char *pass, int seed)
{
unsigned char temp[32];
md5_state_t ctx;
@ -42,7 +43,7 @@ login_calculate(char *buf, int buflen, const char *pass, int seed)
int i;
int k;
if (buflen < 16)
if (buflen < 16)
return;
memcpy(temp, pass, 32);

View File

@ -1,7 +1,8 @@
/*
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
* 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*

View File

@ -71,7 +71,7 @@ typedef struct md5_state_s {
} md5_state_t;
#ifdef __cplusplus
extern "C"
extern "C"
{
#endif

View File

@ -1,7 +1,8 @@
/*
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
* 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
@ -64,7 +65,7 @@ readname_loop(char *packet, int packetlen, char **src, char *dst, size_t length,
c--;
}
if (len >= length - 1) {
break; /* We used up all space */
}
@ -88,15 +89,15 @@ readname(char *packet, int packetlen, char **src, char *dst, size_t length)
}
int
readshort(char *packet, char **src, short *dst)
readshort(char *packet, char **src, unsigned short *dst)
{
unsigned char *p;
p = (unsigned char *) *src;
*dst = (p[0] << 8) | p[1];
(*src) += sizeof(short);
return sizeof(short);
(*src) += sizeof(unsigned short);
return sizeof(unsigned short);
}
int
@ -107,8 +108,8 @@ readlong(char *packet, char **src, uint32_t *dst)
p = (unsigned char *) *src;
*dst = ((uint32_t)p[0] << 24)
| ((uint32_t)p[1] << 16)
*dst = ((uint32_t)p[0] << 24)
| ((uint32_t)p[1] << 16)
| ((uint32_t)p[2] << 8)
| ((uint32_t)p[3]);
@ -166,7 +167,7 @@ putname(char **buf, size_t buflen, const char *host)
h = strdup(host);
left = buflen;
p = *buf;
word = strtok(h, ".");
while(word) {
if (strlen(word) > 63 || strlen(word) > left) {
@ -234,7 +235,7 @@ int
putdata(char **dst, char *data, size_t len)
{
memcpy(*dst, data, len);
(*dst) += len;
return len;
}

View File

@ -1,7 +1,8 @@
/*
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
* 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
@ -18,7 +19,7 @@
#define _READ_H_
int readname(char *, int, char **, char *, size_t);
int readshort(char *, char **, short *);
int readshort(char *, char **, unsigned short *);
int readlong(char *, char **, uint32_t *);
int readdata(char *, char **, char *, size_t);
int readtxtbin(char *, char **, size_t, char *, size_t);

401
src/tun.c
View File

@ -1,7 +1,9 @@
/*
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
* 2006-2009 Bjorn Andersson <flex@kryo.se>
* 2013 Peter Sagerson <psagers.github@ignorare.net>
*
* Permission to use, copy, modify, and distribute this software for any
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
@ -28,6 +30,15 @@
#include <sys/stat.h>
#include <fcntl.h>
#ifdef DARWIN
#include <ctype.h>
#include <sys/kern_control.h>
#include <sys/sys_domain.h>
#include <sys/ioctl.h>
#include <net/if_utun.h>
#include <netinet/ip.h>
#endif
#ifndef IFCONFIGPATH
#define IFCONFIGPATH "PATH=/sbin:/bin "
#endif
@ -36,8 +47,8 @@
#include "windows.h"
#include <winioctl.h>
HANDLE dev_handle;
struct tun_data data;
static HANDLE dev_handle;
static struct tun_data data;
static void get_name(char *ifname, int namelen, char *dev_name);
@ -63,17 +74,16 @@ static void get_name(char *ifname, int namelen, char *dev_name);
#include "tun.h"
#include "common.h"
char if_name[250];
static char if_name[250];
#ifndef WINDOWS32
#ifdef LINUX
#include <sys/ioctl.h>
#include <net/if.h>
#include <linux/if_tun.h>
int
open_tun(const char *tun_device)
int
open_tun(const char *tun_device)
{
int i;
int tun_fd;
@ -85,13 +95,13 @@ open_tun(const char *tun_device)
#endif
if ((tun_fd = open(tunnel, O_RDWR)) < 0) {
warn("open_tun: %s: %s", tunnel, strerror(errno));
warn("open_tun: %s", tunnel);
return -1;
}
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);
@ -101,11 +111,12 @@ open_tun(const char *tun_device)
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]: %s", strerror(errno));
warn("open_tun: ioctl[TUNSETIFF]");
return -1;
}
} else {
@ -115,11 +126,12 @@ open_tun(const char *tun_device)
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]: %s", strerror(errno));
warn("open_tun: ioctl[TUNSETIFF]");
return -1;
}
}
@ -130,49 +142,8 @@ open_tun(const char *tun_device)
return -1;
}
#else /* BSD */
#elif WINDOWS32
int
open_tun(const char *tun_device)
{
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_fd = open(tun_name, O_RDWR)) < 0) {
warn("open_tun: %s: %s", tun_name, strerror(errno));
return -1;
}
fprintf(stderr, "Opened %s\n", tun_name);
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);
return tun_fd;
}
if (errno == ENOENT)
break;
}
warn("open_tun: Failed to open tunneling device");
}
return -1;
}
#endif /* !LINUX */
#else /* WINDOWS32 */
static void
get_device(char *device, int device_len, const char *wanted_dev)
{
@ -187,7 +158,7 @@ get_device(char *device, int device_len, const char *wanted_dev)
warnx("Error opening registry key " TAP_ADAPTER_KEY );
return;
}
while (TRUE) {
char name[256];
char unit[256];
@ -225,7 +196,7 @@ get_device(char *device, int device_len, const char *wanted_dev)
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);
@ -291,7 +262,7 @@ DWORD WINAPI tun_reader(LPVOID arg)
OVERLAPPED olpd;
int sock;
sock = open_dns(0, INADDR_ANY);
sock = open_dns_from_host("127.0.0.1", 0, AF_INET, 0);
olpd.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
@ -302,7 +273,7 @@ DWORD WINAPI tun_reader(LPVOID arg)
if (!res) {
WaitForSingleObject(olpd.hEvent, INFINITE);
res = GetOverlappedResult(dev_handle, &olpd, (LPDWORD) &len, FALSE);
res = sendto(sock, buf, len, 0, (struct sockaddr*) &(tun->addr),
res = sendto(sock, buf, len, 0, (struct sockaddr*) &(tun->addr),
tun->addrlen);
}
}
@ -310,8 +281,8 @@ DWORD WINAPI tun_reader(LPVOID arg)
return 0;
}
int
open_tun(const char *tun_device)
int
open_tun(const char *tun_device)
{
char adapter[256];
char tapfile[512];
@ -331,7 +302,7 @@ open_tun(const char *tun_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);
@ -342,9 +313,9 @@ open_tun(const char *tun_device)
/* 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
* 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);
@ -352,88 +323,259 @@ open_tun(const char *tun_device)
memcpy(&(data.addr), &localsock, localsock_len);
data.addrlen = localsock_len;
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)tun_reader, &data, 0, NULL);
return tunfd;
}
#endif
void
close_tun(int tun_fd)
#else /* BSD and friends */
#ifdef DARWIN
/* Extract the device number from the name, if given. The value returned will
* be suitable for sockaddr_ctl.sc_unit, which means 0 for auto-assign, or
* (n + 1) for manual.
*/
static int
utun_unit(const char *dev)
{
const char *unit_str = dev;
int unit = 0;
while (*unit_str != '\0' && !isdigit(*unit_str))
unit_str++;
if (isdigit(*unit_str))
unit = strtol(unit_str, NULL, 10) + 1;
return unit;
}
static int
open_utun(const char *dev)
{
struct sockaddr_ctl addr;
struct ctl_info info;
char ifname[10];
socklen_t ifname_len = sizeof(ifname);
int fd = -1;
int err = 0;
fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL);
if (fd < 0) {
warn("open_utun: socket(PF_SYSTEM)");
return -1;
}
/* Look up the kernel controller ID for utun devices. */
bzero(&info, sizeof(info));
strncpy(info.ctl_name, UTUN_CONTROL_NAME, MAX_KCTL_NAME);
err = ioctl(fd, CTLIOCGINFO, &info);
if (err != 0) {
warn("open_utun: ioctl(CTLIOCGINFO)");
close(fd);
return -1;
}
/* Connecting to the socket creates the utun device. */
addr.sc_len = sizeof(addr);
addr.sc_family = AF_SYSTEM;
addr.ss_sysaddr = AF_SYS_CONTROL;
addr.sc_id = info.ctl_id;
addr.sc_unit = utun_unit(dev);
err = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
if (err != 0) {
warn("open_utun: connect");
close(fd);
return -1;
}
/* Retrieve the assigned interface name. */
err = getsockopt(fd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME, ifname, &ifname_len);
if (err != 0) {
warn("open_utun: getsockopt(UTUN_OPT_IFNAME)");
close(fd);
return -1;
}
strncpy(if_name, ifname, sizeof(if_name));
fprintf(stderr, "Opened %s\n", ifname);
fd_set_close_on_exec(fd);
return fd;
}
#endif
int
open_tun(const char *tun_device)
{
int i;
int tun_fd;
char tun_name[50];
#ifdef DARWIN
if (!strncmp(tun_device, "utun", 4)) {
tun_fd = open_utun(tun_device);
if (tun_fd >= 0) {
return tun_fd;
}
}
#endif
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;
}
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 (errno == ENOENT)
break;
}
warn("open_tun: Failed to open tunneling device");
}
return -1;
}
#endif
void
close_tun(int tun_fd)
{
if (tun_fd >= 0)
close(tun_fd);
}
int
write_tun(int tun_fd, char *data, size_t len)
#ifdef WINDOWS32
int
write_tun(int tun_fd, char *data, size_t len)
{
#if defined (FREEBSD) || defined (DARWIN) || defined(NETBSD) || defined(WINDOWS32)
DWORD written;
DWORD res;
OVERLAPPED olpd;
data += 4;
len -= 4;
#else /* !FREEBSD/DARWIN */
#ifdef LINUX
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;
#endif /* !LINUX */
#endif /* FREEBSD */
#ifndef WINDOWS32
if (write(tun_fd, data, len) != len) {
warn("write_tun");
return 1;
}
#else /* WINDOWS32 */
{
DWORD written;
DWORD res;
OVERLAPPED olpd;
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;
}
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;
}
}
#endif
return 0;
}
ssize_t
read_tun(int tun_fd, char *buf, size_t len)
read_tun(int tun_fd, char *buf, size_t len)
{
#if defined (FREEBSD) || defined (DARWIN) || defined(NETBSD) || defined(WINDOWS32)
/* FreeBSD/Darwin/NetBSD has no header */
int bytes;
memset(buf, 0, 4);
#ifdef WINDOWS32
/* Windows needs recv() since it is local UDP socket */
bytes = recv(tun_fd, buf + 4, len - 4, 0);
#else
/* The other need read() because fd is not a socket */
bytes = read(tun_fd, buf + 4, len - 4);
#endif /*WINDOWS32*/
if (bytes < 0) {
return bytes;
} else {
return bytes + 4;
}
#else /* !FREEBSD */
return read(tun_fd, buf, len);
#endif /* !FREEBSD */
}
#else
int
write_tun(int tun_fd, char *data, size_t len)
{
#if defined (FREEBSD) || defined (NETBSD)
/* FreeBSD/NetBSD has no header */
int header = 0;
#elif defined (DARWIN)
/* Darwin tun has no header, Darwin utun does */
int header = !strncmp(if_name, "utun", 4);
#else /* LINUX/OPENBSD */
int header = 1;
#endif
if (!header) {
data += 4;
len -= 4;
} else {
#ifdef LINUX
// Linux prefixes with 32 bits ethertype
// 0x0800 for IPv4, 0x86DD for IPv6
data[0] = 0x00;
data[1] = 0x00;
data[2] = 0x08;
data[3] = 0x00;
#else /* OPENBSD and DARWIN(utun) */
// BSDs prefix with 32 bits address family
// AF_INET for IPv4, AF_INET6 for IPv6
data[0] = 0x00;
data[1] = 0x00;
data[2] = 0x00;
data[3] = 0x02;
#endif
}
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 (NETBSD)
/* FreeBSD/NetBSD has no header */
int header = 0;
#elif defined (DARWIN)
/* Darwin tun has no header, Darwin utun does */
int header = !strncmp(if_name, "utun", 4);
#else /* LINUX/OPENBSD */
int header = 1;
#endif
if (!header) {
int bytes;
memset(buf, 0, 4);
bytes = read(tun_fd, buf + 4, len - 4);
if (bytes < 0) {
return bytes;
} else {
return bytes + 4;
}
} else {
return read(tun_fd, buf, len);
}
}
#endif
int
tun_setip(const char *ip, const char *other_ip, int netbits)
@ -450,8 +592,12 @@ tun_setip(const char *ip, const char *other_ip, int netbits)
DWORD ipdata[3];
struct in_addr addr;
DWORD len;
#endif
#else
const char *display_ip;
#ifndef LINUX
struct in_addr netip;
#endif
#endif
netmask = 0;
for (i = 0; i < netbits; i++) {
@ -470,23 +616,22 @@ tun_setip(const char *ip, const char *other_ip, int netbits)
# else
display_ip = ip;
# endif
snprintf(cmdline, sizeof(cmdline),
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);
#ifndef LINUX
struct in_addr netip;
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);
@ -499,13 +644,13 @@ tun_setip(const char *ip, const char *other_ip, int netbits)
/* Set device as connected */
fprintf(stderr, "Enabling interface '%s'\n", if_name);
status = 1;
r = DeviceIoControl(dev_handle, TAP_IOCTL_SET_MEDIA_STATUS, &status,
r = DeviceIoControl(dev_handle, TAP_IOCTL_SET_MEDIA_STATUS, &status,
sizeof(status), &status, sizeof(status), &len, NULL);
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 */
@ -515,7 +660,7 @@ tun_setip(const char *ip, const char *other_ip, int netbits)
}
/* Tell ip/networkaddr/netmask to device for arp use */
r = DeviceIoControl(dev_handle, TAP_IOCTL_CONFIG_TUN, &ipdata,
r = DeviceIoControl(dev_handle, TAP_IOCTL_CONFIG_TUN, &ipdata,
sizeof(ipdata), &ipdata, sizeof(ipdata), &len, NULL);
if (!r) {
fprintf(stderr, "Failed to set interface in TUN mode\n");
@ -530,18 +675,18 @@ tun_setip(const char *ip, const char *other_ip, int netbits)
#endif
}
int
int
tun_setmtu(const unsigned mtu)
{
#ifndef WINDOWS32
char cmdline[512];
if (mtu > 200 && mtu <= 1500) {
snprintf(cmdline, sizeof(cmdline),
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 {

View File

@ -1,7 +1,8 @@
/*
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
* 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*

View File

@ -1,7 +1,8 @@
/*
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
* 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
@ -62,7 +63,7 @@ init_users(in_addr_t my_ip, int netbits)
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;
@ -78,6 +79,8 @@ init_users(in_addr_t my_ip, int netbits)
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) */
}
@ -93,24 +96,6 @@ users_get_first_ip()
return strdup(inet_ntoa(ip));
}
int
users_waiting_on_reply()
{
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++;
}
}
return ret;
}
int
find_user_by_ip(uint32_t ip)
{
@ -119,7 +104,9 @@ find_user_by_ip(uint32_t ip)
ret = -1;
for (i = 0; i < usercount; i++) {
if (users[i].active && !users[i].disabled &&
if (users[i].active &&
users[i].authenticated &&
!users[i].disabled &&
users[i].last_pkt + 60 > time(NULL) &&
ip == users[i].tun_ip) {
ret = i;
@ -146,8 +133,8 @@ all_users_waiting_to_send()
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)
((users[i].conn == CONN_RAW_UDP) ||
((users[i].conn == CONN_DNS_NULL)
#ifdef OUTPACKETQ_LEN
&& users[i].outpacketq_filled < 1
#else
@ -171,6 +158,8 @@ find_available_user()
/* 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;
@ -186,7 +175,7 @@ user_switch_codec(int userid, struct encoder *enc)
{
if (userid < 0 || userid >= usercount)
return;
users[userid].encoder = enc;
}
@ -196,9 +185,9 @@ user_set_conn_type(int userid, enum connection c)
if (userid < 0 || userid >= usercount)
return;
if (c < 0 || c >= CONN_MAX)
if (c < CONN_RAW_UDP || c >= CONN_MAX)
return;
users[userid].conn = c;
}

View File

@ -1,7 +1,8 @@
/*
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
* 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
@ -36,11 +37,14 @@
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 sockaddr_storage host;
socklen_t hostlen;
struct query q;
struct query q_sendrealsoon;
int q_sendrealsoon_new;
@ -77,7 +81,6 @@ extern struct tun_user *users;
int init_users(in_addr_t, int);
const char* users_get_first_ip();
int users_waiting_on_reply();
int find_user_by_ip(uint32_t);
int all_users_waiting_to_send();
int find_available_user();

View File

@ -1,7 +1,8 @@
/*
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
* 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
@ -39,12 +40,12 @@ get_resolvconf_addr()
rv = addr;
pclose(fp);
#else
rv = NULL;
if ((fp = fopen("/etc/resolv.conf", "r")) == NULL)
if ((fp = fopen("/etc/resolv.conf", "r")) == NULL)
err(1, "/etc/resolv.conf");
while (feof(fp) == 0) {
fgets(buf, sizeof(buf), fp);
@ -53,7 +54,7 @@ get_resolvconf_addr()
break;
}
}
fclose(fp);
#endif
#else /* !WINDOWS32 */

View File

@ -1,3 +1,20 @@
/*
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
* 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __UTIL_H__
#define __UTIL_H__

View File

@ -1,7 +1,8 @@
/*
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
* 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*

View File

@ -1,7 +1,8 @@
/*
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
* 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*

View File

@ -1,7 +1,8 @@
/*
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
* 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
@ -66,7 +67,7 @@ START_TEST(test_base32_decode)
char buf[4096];
struct encoder *b32;
int val;
b32 = get_base32_encoder();
len = sizeof(buf);
@ -84,7 +85,7 @@ START_TEST(test_base32_5to8_8to5)
int c;
for (i = 0; i < 32; i++) {
c = b32_5to8(i);
c = b32_5to8(i);
fail_unless(b32_8to5(c) == i);
}
}

View File

@ -1,7 +1,8 @@
/*
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
* 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*

View File

@ -1,13 +1,113 @@
/*
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
* 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <check.h>
#include <common.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netdb.h>
START_TEST(test_topdomain_ok)
{
char *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));
/* Test missing error msg ptr */
fail_unless(check_topdomain(".foo", NULL));
}
END_TEST
START_TEST(test_topdomain_length)
{
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 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;
/* 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 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));
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));
}
END_TEST
START_TEST(test_parse_format_ipv4)
{
char *host = "192.168.2.10";
@ -106,6 +206,9 @@ test_common_create_tests()
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);

View File

@ -1,7 +1,8 @@
/*
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
* 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*

View File

@ -1,7 +1,8 @@
/*
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
* 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
@ -88,7 +89,7 @@ START_TEST(test_build_hostname)
}
buflen = sizeof(buf);
for (i = 1; i < sizeof(data); i++) {
int len = build_hostname(buf, buflen, data, i, topdomain, get_base32_encoder(), sizeof(buf));

View File

@ -1,7 +1,7 @@
/*
* Copyright (c) 2006-2009 Erik Ekman <yarrick@kryo.se>
* Copyright (c) 2009-2014 Erik Ekman <yarrick@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
@ -32,7 +32,7 @@ START_TEST(test_fw_query_simple)
q.id = 0x848A;
fw_query_init();
/* Test empty cache */
fw_query_get(0x848A, &qp);
fail_unless(qp == NULL);
@ -53,7 +53,7 @@ START_TEST(test_fw_query_edge)
int i;
fw_query_init();
q.addrlen = 33;
q.id = 0x848A;
fw_query_put(&q);
@ -68,7 +68,7 @@ START_TEST(test_fw_query_edge)
fw_query_get(0x848A, &qp);
fail_unless(qp->addrlen == 33);
fail_unless(qp->id == 0x848A);
q.addrlen++;
q.id++;
fw_query_put(&q);

View File

@ -1,7 +1,8 @@
/*
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
* 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*

View File

@ -1,7 +1,8 @@
/*
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
* 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
@ -54,7 +55,7 @@ START_TEST(test_read_putshort)
i, ntohs(k), i);
p = (char*)&k;
readshort(NULL, &p, (short *) &l);
readshort(NULL, &p, &l);
fail_unless(l == i,
"Bad value on readshort for %d: %d != %d",
i, l, i);

View File

@ -1,7 +1,8 @@
/*
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
* 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*

View File

@ -1,7 +1,8 @@
/*
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
* 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
@ -28,11 +29,11 @@ TCase *test_user_create_tests();
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)))
#define tcase_set_timeout(...)
#define tcase_set_timeout(...)
#endif
#endif

View File

@ -1,7 +1,8 @@
/*
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
* 2006-2009 Bjorn Andersson <flex@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
@ -51,30 +52,6 @@ START_TEST(test_init_users)
}
END_TEST
START_TEST(test_users_waiting)
{
in_addr_t ip;
ip = inet_addr("127.0.0.1");
init_users(ip, 27);
fail_unless(users_waiting_on_reply() == 0);
users[3].active = 1;
fail_unless(users_waiting_on_reply() == 0);
users[3].last_pkt = time(NULL);
fail_unless(users_waiting_on_reply() == 0);
users[3].conn = CONN_DNS_NULL;
users[3].q.id = 1;
fail_unless(users_waiting_on_reply() == 1);
}
END_TEST
START_TEST(test_find_user_by_ip)
{
in_addr_t ip;
@ -86,17 +63,22 @@ START_TEST(test_find_user_by_ip)
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);
users[0].active = 1;
testip = (unsigned int) inet_addr("127.0.0.2");
fail_unless(find_user_by_ip(testip) == -1);
users[0].last_pkt = time(NULL);
testip = (unsigned int) inet_addr("127.0.0.2");
fail_unless(find_user_by_ip(testip) == -1);
users[0].authenticated = 1;
testip = (unsigned int) inet_addr("127.0.0.2");
fail_unless(find_user_by_ip(testip) == 0);
}
@ -110,15 +92,15 @@ START_TEST(test_all_users_waiting_to_send)
init_users(ip, 27);
fail_unless(all_users_waiting_to_send() == 1);
users[0].conn = CONN_DNS_NULL;
users[0].active = 1;
fail_unless(all_users_waiting_to_send() == 1);
users[0].last_pkt = time(NULL);
users[0].outpacket.len = 0;
fail_unless(all_users_waiting_to_send() == 0);
#ifdef OUTPACKETQ_LEN
@ -126,7 +108,7 @@ START_TEST(test_all_users_waiting_to_send)
#else
users[0].outpacket.len = 44;
#endif
fail_unless(all_users_waiting_to_send() == 1);
}
END_TEST
@ -140,7 +122,11 @@ START_TEST(test_find_available_user)
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++) {
@ -153,7 +139,7 @@ START_TEST(test_find_available_user)
fail_unless(find_available_user() == -1);
users[3].last_pkt = 55;
fail_unless(find_available_user() == 3);
fail_unless(find_available_user() == -1);
}
@ -181,7 +167,7 @@ START_TEST(test_find_available_user_small_net)
fail_unless(find_available_user() == -1);
users[3].last_pkt = 55;
fail_unless(find_available_user() == 3);
fail_unless(find_available_user() == -1);
}
@ -194,7 +180,6 @@ test_user_create_tests()
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);