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:
commit
11b6da12ff
27
CHANGELOG
27
CHANGELOG
@ -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
379
README
@ -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.
|
@ -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
|
||||
|
@ -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
408
README.md
Normal 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.
|
@ -3,6 +3,8 @@ Description=Iodine socket
|
||||
|
||||
[Socket]
|
||||
ListenDatagram=53
|
||||
ListenDatagram=0.0.0.0:53
|
||||
BindIPv6Only=ipv6-only
|
||||
|
||||
[Install]
|
||||
WantedBy=sockets.target
|
||||
|
@ -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).
|
||||
|
63
man/iodine.8
63
man/iodine.8
@ -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
|
||||
|
@ -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
|
||||
|
@ -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++;
|
||||
|
@ -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.
|
||||
*
|
||||
|
23
src/base32.c
23
src/base32.c
@ -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++;
|
||||
|
@ -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.
|
||||
*
|
||||
|
19
src/base64.c
19
src/base64.c
@ -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++;
|
||||
|
@ -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.
|
||||
*
|
||||
|
169
src/client.c
169
src/client.c
@ -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) {
|
||||
|
11
src/client.h
11
src/client.h
@ -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);
|
||||
|
159
src/common.c
159
src/common.c
@ -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
|
||||
|
||||
|
37
src/common.h
37
src/common.h
@ -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
|
||||
|
70
src/dns.c
70
src/dns.c
@ -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);
|
||||
}
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
*
|
||||
|
60
src/iodine.c
60
src/iodine.c
@ -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];
|
||||
|
613
src/iodined.c
613
src/iodined.c
File diff suppressed because it is too large
Load Diff
15
src/login.c
15
src/login.c
@ -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);
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -71,7 +71,7 @@ typedef struct md5_state_s {
|
||||
} md5_state_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
|
21
src/read.c
21
src/read.c
@ -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;
|
||||
}
|
||||
|
@ -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
401
src/tun.c
@ -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 {
|
||||
|
@ -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.
|
||||
*
|
||||
|
45
src/user.c
45
src/user.c
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
11
src/user.h
11
src/user.h
@ -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();
|
||||
|
13
src/util.c
13
src/util.c
@ -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 */
|
||||
|
17
src/util.h
17
src/util.h
@ -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__
|
||||
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
*
|
||||
|
105
tests/common.c
105
tests/common.c
@ -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);
|
||||
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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
|
||||
|
63
tests/user.c
63
tests/user.c
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user