Compare commits

...

167 Commits

Author SHA1 Message Date
Erik Ekman c501a3903f Merge branch 'master' into iodine-0.5 2009-06-01 18:39:01 +00:00
Erik Ekman 7c4a9c4c7a Merge branch 'master' into iodine-0.5 2009-03-21 13:34:28 +00:00
Erik Ekman 60a864ec52 Merge branch 'master' into iodine-0.5 2009-03-21 13:22:51 +00:00
Erik Ekman 6536fc7c5d Release 0.5.1 2009-03-21 13:07:49 +00:00
Erik Ekman f41c4bb9f3 Release 0.5.0 2009-01-23 18:20:27 +00:00
Erik Ekman 30a3bb9445 Release 0.5.0-rc2 2009-01-17 09:06:33 +00:00
Erik Ekman 134fa90727 updated manpage 2009-01-10 20:56:39 +00:00
Erik Ekman 46293b51b1 prepare version 0.5.0-rc1 2009-01-10 20:40:22 +00:00
Erik Ekman fa9b145af1 Branch 0.5 2009-01-10 20:36:16 +00:00
Erik Ekman 2b7bf00e1a Rename protocol to version 00000500 2009-01-10 20:32:53 +00:00
Erik Ekman 7a1733ae82 Rename protocol to version 00000500 2009-01-10 20:32:32 +00:00
Erik Ekman d7f07d2f1f Enhanced checks on incoming queries, check user exists and is active 2009-01-10 20:23:50 +00:00
Erik Ekman db13d81caf #7 finally done\! Added autoprobing of max downstream fragsize. 2009-01-10 19:30:55 +00:00
Erik Ekman 9a139b7005 #7, add probe fragsize support for server. documented 2009-01-10 16:22:51 +00:00
Erik Ekman 49e448fb19 fix warnings 2009-01-07 18:16:49 +00:00
Erik Ekman 9f3e397475 add osflags for tests 2009-01-06 22:05:15 +00:00
Erik Ekman 3ac090f847 Update readme with new url for osx tuntap driver 2009-01-06 19:58:29 +00:00
Erik Ekman ab75dae208 allow custom check path 2009-01-06 13:41:45 +00:00
Erik Ekman 168b05e3f7 Fix build on OpenBSD 2009-01-06 10:47:01 +00:00
Erik Ekman 9f2730cb9a fix label 2009-01-05 19:52:01 +00:00
Erik Ekman dfd6f9aa90 #7, set max fragsize with -m in the client 2009-01-05 19:47:59 +00:00
Erik Ekman 0ed202dd18 downstream fragsize is now per user 2009-01-05 18:50:46 +00:00
Erik Ekman 78aaf26369 #7, handle special case, remove up to 1 second pause when doing bulk download 2009-01-05 17:08:34 +00:00
Erik Ekman 20cfb002c3 Downstream fragmentation now working. Currently fragment size is hardcoded to 1200. More tweaking left, as well as fragsize auto detection. (#7) 2009-01-05 16:25:54 +00:00
Erik Ekman d5f0dac459 Discard packets which only has data header 2009-01-04 18:59:12 +00:00
Erik Ekman 55d9ddb8dd add downstream data header and basic parsing in client, for #7 2009-01-04 18:56:24 +00:00
Erik Ekman 7dd38fec17 Create send_chunk() on server 2009-01-04 13:53:32 +00:00
Erik Ekman f8eb4c952b Allow setting netmask in iodined, fixes #27. The same netmask will be given to clients as well. Updated docs. 2009-01-04 12:39:28 +00:00
Erik Ekman f5e58e6527 Assign client IPs within the network (fixes #28), also limit number of users depending on netmask (for #27) 2009-01-04 12:03:35 +00:00
Erik Ekman 3f79d948bf updated docs 2009-01-04 10:58:52 +00:00
Erik Ekman c742fe79c3 Happy new year 2009-01-03 23:39:54 +00:00
Erik Ekman 7791035364 Happy new year 2009-01-03 23:27:21 +00:00
Erik Ekman 58f789307b Updated changelog for #37 2009-01-03 23:14:02 +00:00
Erik Ekman d027a60859 Handle trans id >= 0x8000, fix bug #37 2009-01-03 20:13:31 +00:00
Erik Ekman da6eee279a make OUT debug look more like IN debug 2009-01-03 18:29:36 +00:00
Erik Ekman b66dc4ea51 update tests after inline dot function now uses 57 as distance 2008-12-27 00:40:30 +00:00
Erik Ekman 3b4cc0989c Fix for compile error on FreeBSD 2008-12-27 00:30:51 +00:00
Erik Ekman 7335940130 make iodined build on opensolaris 2008-12-25 16:56:13 +00:00
Erik Ekman 18e0042ce4 Detect duplicates in upstream data, start frag at zero 2008-12-14 17:21:27 +00:00
Erik Ekman 89fdbc104b Implemented new protocol for upstream data 2008-12-11 22:39:06 +00:00
Erik Ekman 458b5af003 Added simple 5bits to 8 and reverse encoder, with test 2008-12-11 19:26:11 +00:00
Erik Ekman 9d8e9a7d18 Removing old code 2008-12-11 19:12:51 +00:00
Erik Ekman e06ce0a213 Updated old proto, added new things to latest 2008-12-11 19:12:34 +00:00
Erik Ekman a83164fad8 Added notreached 2008-12-11 19:11:53 +00:00
Erik Ekman c7d1620cad Updated old protocol spec 2008-12-07 09:55:23 +00:00
Erik Ekman fbb874c1ab fix version number in spec 2008-12-07 09:44:55 +00:00
Erik Ekman 48df1d896a Added old protocol spec 2008-12-07 09:42:19 +00:00
Erik Ekman b639436375 updated docs 2008-12-07 09:41:06 +00:00
Erik Ekman 33b5ef9bf9 Reverted new protocol 2008-12-06 22:12:18 +00:00
Erik Ekman 5450372a75 Updated encoding tests 2008-12-06 19:08:14 +00:00
Erik Ekman 900a0e8df7 Added blocksize funcs, made funcs static 2008-12-06 15:31:28 +00:00
Erik Ekman 46f7eccf54 New protocol spec 2008-12-06 13:20:47 +00:00
Erik Ekman 3740894350 Revert client shutdown code, it seems BADIP can arrive even though everything works 2008-12-06 12:25:02 +00:00
Erik Ekman cb0fa56232 updated changelog 2008-09-14 13:37:44 +00:00
Erik Ekman 55176af538 Added -n to set NS ip, updated docs, added checks 2008-09-14 13:21:11 +00:00
Erik Ekman 2eb78f9e8c Reverted [686], [689] and [692]. SSH login now works again. Increased version. 2008-09-14 12:44:55 +00:00
Erik Ekman b4893e8a8b Rename codecs 2008-09-14 12:05:55 +00:00
Erik Ekman 4203f115f5 Use base64 is case is preserved and plus sign is allowed 2008-09-14 11:34:56 +00:00
Erik Ekman e8ee981f97 Print failed tests 2008-09-14 11:33:18 +00:00
Erik Ekman 524522d00a Base64 codec now uses + as 64th char 2008-09-14 11:32:31 +00:00
Erik Ekman de2912c089 rewrote strange message 2008-09-09 21:10:48 +00:00
Erik Ekman 6f097a4cb3 Added debugging 2008-09-09 21:09:06 +00:00
Erik Ekman 4c805fef6a Fix issue #33, respond to NS requests 2008-09-09 20:55:13 +00:00
Erik Ekman d40c464ac1 shorten some lines 2008-09-09 19:55:45 +00:00
Erik Ekman 8eccbf097a Stop client if server is restarted 2008-09-09 19:37:51 +00:00
Erik Ekman 63d65bb30e formatting 2008-09-09 19:36:51 +00:00
Erik Ekman e359f64003 Updated year 2008-09-09 19:07:09 +00:00
Erik Ekman 6ca1b992bb added include for iovec 2008-08-07 22:34:14 +00:00
Erik Ekman d4e1eef6d5 Now fetches destination address from udp packets 2008-08-07 22:12:10 +00:00
Erik Ekman c96b83e3d2 Forward non-tunnel requests to another udp port (fixes #31) 2008-08-07 21:18:15 +00:00
Erik Ekman b619662201 Patch to make it build on BeOS R5-BONE and Haiku from Francois Revol 2008-08-07 16:53:59 +00:00
Erik Ekman fb3fa24edb Implemented filtering based on topdomain 2008-08-07 16:49:22 +00:00
Erik Ekman 6531d5e72b Eliminate extra 'ping' message when server sends data to client which generates a reply 2008-08-07 15:05:51 +00:00
Erik Ekman edf7e5a565 updated documentation 2008-08-07 14:44:02 +00:00
Erik Ekman 2270063464 updated changelog 2008-08-07 14:40:39 +00:00
Erik Ekman 55a689e759 Fix #34, send pings only every 5 seconds 2008-08-07 14:39:43 +00:00
Erik Ekman 188e69aa1f Fixed segfault when sending version rejects: VNAK/VFUL 2008-08-07 14:16:12 +00:00
Erik Ekman 798bbb64db Changed texts 2008-08-07 14:13:33 +00:00
Erik Ekman 9c74eb09a7 Improved latency for traffic initiated from server 2008-08-07 13:22:30 +00:00
Erik Ekman d2b11c44b1 0.4.2 released 2008-08-06 20:51:20 +00:00
Erik Ekman ad8afce8e1 fixed osflags script, updated changelog 2008-08-06 20:02:34 +00:00
Erik Ekman 9019b0639d fix opensolaris warning 2008-08-06 18:59:22 +00:00
Erik Ekman dce8f8352b added -D to usage() and help() 2008-08-06 10:47:44 +00:00
Erik Ekman fc6106153f Named the next release 2008-08-05 22:59:31 +00:00
Erik Ekman 9fa70acc69 Added debug capability on server 2008-08-05 22:37:40 +00:00
Erik Ekman 2ab94a7991 Changes to allow handling of queries of type A, NS etc 2008-08-05 21:53:19 +00:00
Erik Ekman 468bd706cb updated changelog 2008-08-05 14:56:11 +00:00
Erik Ekman 7b90054346 Reworked fix for #21 2008-08-05 14:47:51 +00:00
Erik Ekman 4d79bf6368 Added -c flag to disable IP/port checking in each request 2008-07-12 22:39:29 +00:00
Erik Ekman e4e23275c9 Removed needless va_str() 2008-07-12 20:57:30 +00:00
Erik Ekman d6ec29be4d Remove double warnings 2008-07-12 20:30:35 +00:00
Erik Ekman 6d1a003c1e Add extra ldflags for solaris 2008-07-12 12:42:19 +00:00
Erik Ekman 30014e6433 Applied Open/Solaris patch from Albert Lee 2008-07-12 12:26:41 +00:00
Erik Ekman f2596cef24 Add include for setgroups() on Linux 2008-07-12 12:20:35 +00:00
Erik Ekman 71c5fe99ce updated changelog 2008-07-12 12:06:56 +00:00
Erik Ekman adabd28b46 applied security patch from Andrew Griffiths, limit user groups 2008-07-12 12:05:59 +00:00
Erik Ekman 3f4852edab updated changelog 2008-07-12 11:50:42 +00:00
Erik Ekman bc76b588c9 Applied patch for not configuring the tun interface, debian bug 477692 2008-07-12 11:45:22 +00:00
Erik Ekman e7de432088 reapplied maxims patches 2008-07-12 11:41:01 +00:00
Erik Ekman 321781ad85 removed empty files 2008-07-12 11:37:25 +00:00
Erik Ekman ddaebb0074 reverting the code after 0.4.1, except for some patches 2008-07-12 11:36:39 +00:00
Erik Ekman cb3115865d Fix tests, dotting does not spare a char anymore 2008-01-07 22:24:19 +00:00
Erik Ekman b121f638d0 Added port range check, based on patch from Maxim Bourmistrov 2008-01-07 22:18:27 +00:00
Erik Ekman ac46718c16 Added checks on topdomain name based on patch from Maxim Bourmistrov 2008-01-07 22:06:09 +00:00
Erik Ekman 98061ccc0e Applied patch from Maxim Bourmistrov 2008-01-02 20:40:28 +00:00
Erik Ekman 5460c8eb0a Link test with packet 2007-12-02 10:51:52 +00:00
Erik Ekman 29b2348ca6 Reset sentlen when advancing 2007-12-02 02:28:18 +00:00
Erik Ekman 6fa0d98c99 #7 Actually update server_id 2007-12-02 02:27:36 +00:00
Erik Ekman 9ca4130e9a Always send latest chunk id 2007-12-02 01:22:34 +00:00
Erik Ekman 3eb835afe7 Add two chars from client to server for verification of data delivery 2007-12-02 01:16:53 +00:00
Erik Ekman fd45a20f30 Rewrote strange warning message 2007-12-01 23:48:02 +00:00
Erik Ekman 4c6aae9e90 Use packet functions for packet handling. Prepare for sending fragmented ( #7 ) 2007-12-01 23:33:51 +00:00
Erik Ekman de4a726cb9 Remove useless success warning message 2007-12-01 23:25:44 +00:00
Erik Ekman 317e1efbd6 use packet functions for empty check and fill 2007-12-01 23:05:54 +00:00
Erik Ekman c8726f2c5d revert [607], [608] and parts of [611] 2007-12-01 23:02:06 +00:00
Erik Ekman 3b7927b2dc Fixed packet_empty() 2007-12-01 22:41:27 +00:00
Erik Ekman 9e60b36430 Renamed packet_sending to packet_empty 2007-12-01 22:19:54 +00:00
Erik Ekman fc632e6311 Speling 2007-12-01 22:11:48 +00:00
Erik Ekman d12d0fcff5 Added packet_init 2007-12-01 22:10:48 +00:00
Erik Ekman 7f48d0d99f Extract login handling to function 2007-12-01 21:55:48 +00:00
Erik Ekman 212a3b93e6 Extract version checking to function 2007-12-01 21:46:13 +00:00
Erik Ekman b55c3f432b added license 2007-12-01 21:26:51 +00:00
Erik Ekman c4a2b0c27f #7 Move packet handling out of iodine.c and into packet.c 2007-12-01 21:23:59 +00:00
Erik Ekman 2d8b2655ea packet name collided with global packet 2007-12-01 20:53:29 +00:00
Erik Ekman fe75007109 Add notreached comments 2007-12-01 19:48:17 +00:00
Erik Ekman 509f445c1e Add notreached comments 2007-12-01 19:46:22 +00:00
Erik Ekman f47c750c98 Escape dashes in man page 2007-12-01 10:16:19 +00:00
Erik Ekman f265e4637f Missed one $(MAKE) 2007-12-01 10:12:25 +00:00
Erik Ekman b6340acfb3 0.4.1 release at last 2007-11-30 22:02:21 +00:00
Erik Ekman 3b43db2529 updated changelog 2007-11-27 20:11:55 +00:00
Erik Ekman bd2ed87022 apply patch to detach before chroot/privdrop 2007-11-27 20:11:43 +00:00
Erik Ekman 5adeafddfa Use %d for size_t sprintf 2007-11-27 20:04:13 +00:00
Erik Ekman c22752d1f5 Use 2007-11-27 20:00:45 +00:00
Bjorn Andersson 488412d4e6 buffer overflow in dns.c pointed out by Matus Harvan, also strncpy cleanups 2007-08-26 15:47:32 +00:00
Erik Ekman b0c6924a8e Init variables, fix #26 2007-08-08 06:20:09 +00:00
Bjorn Andersson 32bd132d43 local stuff in iodine made static 2007-07-12 15:50:06 +00:00
Bjorn Andersson 643178b207 stdin-echo fix in server too 2007-07-12 15:48:05 +00:00
Erik Ekman e6286cc03c #21: Reverted [538], reopening 2007-07-12 15:22:32 +00:00
Bjorn Andersson e5ee739537 some cleanup 2007-07-12 15:18:34 +00:00
Bjorn Andersson 0b9a532bbe name the address of the nameserver nameserv instead of peer 2007-07-12 15:18:23 +00:00
Bjorn Andersson d9ca124e18 cleaning commandline on server too 2007-07-12 13:46:58 +00:00
Bjorn Andersson c6f46ebaf9 fixes bad printf after resolv.conf-fix 2007-07-12 13:40:52 +00:00
Bjorn Andersson e889185aca nasty hack hides password on commandline 2007-07-12 13:36:24 +00:00
Bjorn Andersson 1f9a0273db use termios to not echo password when entered on stdin 2007-07-12 13:24:55 +00:00
Erik Ekman 04487efe96 #23 updated manpage and log row 2007-07-12 13:23:44 +00:00
Bjorn Andersson f6735782b1 /etc/resolv.conf is used if no nameserver is given on commandline 2007-07-12 13:01:18 +00:00
Erik Ekman d5ffc25557 #25 Fixed crash on query with bad top domain 2007-07-12 08:38:00 +00:00
Erik Ekman aae94200a5 #16 Do case preservation check after login 2007-07-12 08:31:29 +00:00
Erik Ekman 17c41d87bc #24: Add length check on topdomain, <= 128 chars 2007-07-11 23:25:03 +00:00
Erik Ekman 4e582e98c6 use common send_query function 2007-07-11 23:10:08 +00:00
Erik Ekman 11748b2963 converted iodine.c to use packet struct 2007-07-11 22:39:56 +00:00
Erik Ekman 5f6b7131cc updated log 2007-07-11 22:16:55 +00:00
Erik Ekman ea30edd76f fixed #17: report RCODE error msgs 2007-07-11 22:10:53 +00:00
Erik Ekman a4684f5ebf add check.sf.net note in test target 2007-07-11 21:31:49 +00:00
Erik Ekman 83f2e56426 Updated changelog for #21 2007-07-11 21:19:09 +00:00
Erik Ekman 639fb5f6aa Store only in_addr, not whole sockaddr, fixes #21 2007-07-11 18:27:18 +00:00
Erik Ekman bb74190ed5 Prepare for encoding switching 2007-06-24 10:54:50 +00:00
Erik Ekman acc8b798e3 changes since 0.4.0 2007-06-24 10:34:10 +00:00
Erik Ekman d978ed47bc uninstall in destdir 2007-06-24 10:33:40 +00:00
Erik Ekman d679babb67 updated date 2007-06-24 10:23:17 +00:00
Erik Ekman 63f9098aa0 Add mtu info to manpage 2007-06-24 10:04:02 +00:00
Erik Ekman 42fcc07379 remove last warning on osx 2007-06-18 07:17:55 +00:00
Erik Ekman 9b7863a668 fix sbin dir, add permissions 2007-06-17 12:54:49 +00:00
Erik Ekman 502205f1a1 hopefully more packaging-friendly makefile 2007-06-17 12:32:16 +00:00
Erik Ekman 854c7ed1c1 add patch from decker for osx 2007-06-17 12:19:50 +00:00
Erik Ekman 4d079b95f2 Remove warning for \!LINUX 2007-06-17 12:19:23 +00:00
Erik Ekman 5c9ff9ba06 add sys/time.h for old osx 2007-06-17 11:46:05 +00:00
44 changed files with 3678 additions and 983 deletions

View File

@ -5,6 +5,78 @@ iodine - http://code.kryo.se/iodine
CHANGES: CHANGES:
2009-06-01: 0.5.2 "WifiFree"
- Fixed client segfault on OS X, #57
- Added check that nameserver lookup was successful
- Fixed ENOTSOCK error on OS X and FreeBSD, #58.
2009-03-21: 0.5.1 "Boringo"
- Added initial Windows support, fixes #43.
- Added length check of autoprobe responses
- Refactored and added unit tests
- Added syslog logging for iodined on version and login packets
- Fixed segfault when encoding just one block, fixes #51.
The normal code was never affected by this.
- Added win32 code to read DNS server from system, fixes #45.
- Disabled password echo on win32, fixes #44.
- Fix encoding error making all autoprobing > 1024 bytes fail, #52.
- Increase default interface MTU to 1200.
- Fix autoprobing error making every third probe fail, set IP flag
Dont-Fragment where supported. Fixes #54.
- Added TAP32 version 0901 as accepted (#53).
2009-01-23: 0.5.0 "iPassed"
- Fixed segfault in server when sending version reject.
- Applied patch to make iodine build on BeOS R5-BONE and Haiku,
from Francois Revol. Still work to do to get tun device working.
- Added capability to forward DNS queries outside tunnel domain to
a nameserver on localhost. Use -b port to enable, fixes #31.
- iodined now replies to NS request on its own domain, fixes issue #33.
The destination IP address is sent as reply. Use -n to specify
a specific IP address to return (if behind NAT etc).
- Upstream data is now Base64 encoded if relay server preserves case and
supports the plus (+) character in domain names, fixes #16.
- Fixed problem in client when DNS trans. ID has highest bit set (#37)
- IP addresses are now assigned within the netmask, so iodined can
use any address for itself, fixes #28.
- Netmask size is now adjustable. Setting a small net will reduce the
number of users. Use x.x.x.x/n notation on iodined tunnel ip.
This fixes #27.
- Downstream data is now fragmented, and the fragment size is auto-
probed after login. Fixes #7. It only took a few years :)
- Enhanced the checks that validates incoming packets
- Fixed endless loop in fragment size autodetection, #39.
- Fixed broken hostname dot placing with specific lengths, #40.
2008-08-06: 0.4.2 "Opened Zone"
- Applied a few small patches from Maxim Bourmistrov and Gregor Herrmann
- Applied a patch for not creating and configuring the tun interface,
Debian bug #477692 by Vincent Bernat, controlled by -s switch
- Applied a security patch from Andrew Griffiths, use setgroups() to
limit the groups of the user
- Applied a patch to make iodine build on (Open)Solaris, from Albert Lee
Needs TUN/TAP driver http://www.whiteboard.ne.jp/~admin2/tuntap/
Still needs more code in tun.c for opening/closing the device
- Added option in server (-c) to disable IP/port checking on packets,
will hopefully help when server is behind NAT
- Fixed bug #21, now only IP address part of each packet is checked.
Should remove the need for the -c option and also work with
bugfixed DNS servers worldwide.
- Added -D option on server to enable debugging. Debug level 1 now
prints info about each RX/TX datagram.
2007-11-30: 0.4.1 "Tea Online"
- Introduced encoding API
- Switched to new Base32 implementation
- Added Base64 implementation that only uses 63 chars (not used yet)
- Refined 'install' make target and use $(MAKE) for recursive calls
- All received error messages (RCODE field) are echoed
- Top domain limited to 128 chars
- Case preservation check sent after login to decide codec
- Fixed crash on incoming NULL query in server with bad top domain
- /etc/resolv.conf is consulted if no nameserver is given on commandline
- Applied patch from Matthew W. S. Bell (Detach before chroot/dropping priv)
2007-03-25: 0.4.0 "Run Home" 2007-03-25: 0.4.0 "Run Home"
- Added multiuser support (up to 8 users simultaneously) - Added multiuser support (up to 8 users simultaneously)
- Added authentication (password entered as argument or on stdin) - Added authentication (password entered as argument or on stdin)

View File

@ -1,6 +1,11 @@
PREFIX=/usr/local prefix=/usr/local
sbindir=$(prefix)/sbin
datadir=$(prefix)/share
mandir=$(datadir)/man
INSTALL=/usr/bin/install DESTDIR=
INSTALL=install
INSTALL_FLAGS= INSTALL_FLAGS=
MKDIR=mkdir MKDIR=mkdir
@ -9,27 +14,49 @@ MKDIR_FLAGS=-p
RM=rm RM=rm
RM_FLAGS=-f RM_FLAGS=-f
TARGETOS = `uname`
all: all:
@(cd src; make all) @(cd src; $(MAKE) TARGETOS=$(TARGETOS) all)
cross-mingw:
@(cd src; $(MAKE) TARGETOS=windows32 CC=i686-mingw32-gcc all)
cross-mingw-dist: cross-mingw
@rm -rf iodine-latest-win32*
@mkdir -p iodine-latest-win32/bin
@for i in `ls bin`; do cp bin/$$i iodine-latest-win32/bin/$$i.exe; done
@cp /usr/i686-mingw32/usr/bin/zlib1.dll iodine-latest-win32/bin
@cp README* CH* TO* iodine-latest-win32
@echo "Create date: " > iodine-latest-win32/VERSION
@date >> iodine-latest-win32/VERSION
@echo "SVN version: " >> iodine-latest-win32/VERSION
@svnversion >> iodine-latest-win32/VERSION
@zip -r iodine-latest-win32.zip iodine-latest-win32
install: all install: all
$(MKDIR) $(MKDIR_FLAGS) $(PREFIX)/sbin $(MKDIR) $(MKDIR_FLAGS) $(DESTDIR)$(sbindir)
$(INSTALL) $(INSTALL_FLAGS) bin/iodine $(PREFIX)/sbin/iodine $(INSTALL) $(INSTALL_FLAGS) bin/iodine $(DESTDIR)$(sbindir)/iodine
$(INSTALL) $(INSTALL_FLAGS) bin/iodined $(PREFIX)/sbin/iodined chmod 755 $(DESTDIR)$(sbindir)/iodine
$(MKDIR) $(MKDIR_FLAGS) $(PREFIX)/man/man8 $(INSTALL) $(INSTALL_FLAGS) bin/iodined $(DESTDIR)$(sbindir)/iodined
$(INSTALL) $(INSTALL_FLAGS) man/iodine.8 $(PREFIX)/man/man8/iodine.8 chmod 755 $(DESTDIR)$(sbindir)/iodined
$(MKDIR) $(MKDIR_FLAGS) $(DESTDIR)$(mandir)/man8
$(INSTALL) $(INSTALL_FLAGS) man/iodine.8 $(DESTDIR)$(mandir)/man8/iodine.8
chmod 644 $(DESTDIR)$(mandir)/man8/iodine.8
uninstall: uninstall:
$(RM) $(RM_FLAGS) $(PREFIX)/sbin/iodine $(RM) $(RM_FLAGS) $(DESTDIR)$(sbindir)/iodine
$(RM) $(RM_FLAGS) $(PREFIX)/sbin/iodined $(RM) $(RM_FLAGS) $(DESTDIR)$(sbindir)/iodined
$(RM) $(RM_FLAGS) $(PREFIX)/man/man8/iodine.8 $(RM) $(RM_FLAGS) $(DESTDIR)$(mandir)/man8/iodine.8
test: all test: all
@(cd tests; make all) @echo "!! The check library is required for compiling and running the tests"
@echo "!! Get it at http://check.sf.net"
@(cd tests; $(MAKE) TARGETOS=$(TARGETOS) all)
clean: clean:
@echo "Cleaning..." @echo "Cleaning..."
@(cd src; make clean) @(cd src; $(MAKE) clean)
@(cd tests; make clean) @(cd tests; $(MAKE) clean)
@rm -rf bin @rm -rf bin iodine-latest-win32*

47
README
View File

@ -28,9 +28,11 @@ HOW TO USE:
Server side: Server side:
To use this tunnel, you need control over a real domain (like mytunnel.com), To use this tunnel, you need control over a real domain (like mytunnel.com),
and a server with a public IP number (not behind NAT) that does not yet run and a server with a public IP number. If the server already runs a DNS
a DNS server. Then, delegate a subdomain (say, tunnel1.mytunnel.com) to the server, change the listening port and then use the -b option to let
server. If you use BIND for the domain, add these lines to the zone file: iodined forward the DNS requests. Then, delegate a subdomain
(say, tunnel1.mytunnel.com) to the server. If you use BIND for the domain,
add these lines to the zone file:
tunnel1host IN A 10.15.213.99 tunnel1host IN A 10.15.213.99
tunnel1 IN NS tunnel1host.mytunnel.com. tunnel1 IN NS tunnel1host.mytunnel.com.
@ -50,15 +52,14 @@ password on the commandline (-P pass) or after the server has started. Now
everything is ready for the client. everything is ready for the client.
Client side: Client side:
All the setup is done, just start iodine. It also takes two All the setup is done, just start iodine. It takes up to two arguments, the
arguments, the first is the local relaying DNS server and the second is the first is the local relaying DNS server (optional) and the second is the domain
domain used (tunnel1.mytunnnel.com). If DNS queries are allowed to any used (tunnel1.mytunnnel.com). If DNS queries are allowed to any computer, you
computer, you can use the tunnel endpoint (example: 10.15.213.99 or can use the tunnel endpoint (example: 10.15.213.99 or tunnel1host.mytunnel.com)
tunnel1host.mytunnel.com) as the first argument. The tunnel interface will get as the first argument. The tunnel interface will get an IP close to the servers
an IP close to the servers (in this case 192.168.99.2) and a suitable MTU. (in this case 192.168.99.2) and a suitable MTU. Enter the same password as on
Enter the same password as on the server either by argument or after the client the server either by argument or after the client has started. Now you should
has started. Now you should be able to ping the other end of the tunnel from be able to ping the other end of the tunnel from either side.
either side.
MISC. INFO: MISC. INFO:
@ -73,10 +74,11 @@ If you have problems, try inspecting the traffic with network monitoring tools
and make sure that the relaying DNS server has not cached the response. A 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. cached error message could mean that you started the client before the server.
The upstream data is sent gzipped encoded with Base32. DNS protocol allows The upstream data is sent gzipped encoded with Base32, or Base64 if the relay
one query per packet, and one query can be max 256 chars. Each domain name part server support '+' in domain names. DNS protocol allows one query per packet,
can be max 63 chars. So your domain name and subdomain should be as short as and one query can be max 256 chars. Each domain name part can be max 63 chars.
possible to allow maximum throughput. So your domain name and subdomain should be as short as possible to allow
maximum upstream throughput.
TIPS & TRICKS: TIPS & TRICKS:
@ -90,11 +92,12 @@ iptables -t nat -A PREROUTING -i eth0 -p udp --dport 53 -j DNAT --to :5353
PORTABILITY: PORTABILITY:
iodine has been tested on Linux (arm, ia64, x86, AMD64 and SPARC64), FreeBSD iodine has been tested on Linux (arm, ia64, x86, AMD64 and SPARC64), FreeBSD
(ia64, x86), OpenBSD (x86), NetBSD (x86) and MacOS X (ppc and x86, with (ia64, x86), OpenBSD (x86), NetBSD (x86), MacOS X (ppc and x86, with
http://www-user.rhrk.uni-kl.de/~nissler/tuntap/). It should work on other http://tuntaposx.sourceforge.net/). and Windows (with OpenVPN TAP32 driver, see
unix-like systems as well that has TUN/TAP tunneling support (after some win32 readme file). It should be easy to port to other unix-like systems that
patching). Let us know if you get it to run on other platforms. has TUN/TAP tunneling support. Let us know if you get it to run on other
platforms.
THE NAME: THE NAME:
@ -111,7 +114,7 @@ THANKS:
AUTHORS & LICENSE: AUTHORS & LICENSE:
Copyright (c) 2006-2007 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se> Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
Permission to use, copy, modify, and distribute this software for any purpose 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 with or without fee is hereby granted, provided that the above copyright notice

62
README-win32.txt Normal file
View File

@ -0,0 +1,62 @@
iodine - http://code.kryo.se/iodine
***********************************
Extra README file for Win32 related stuff
== Running iodine on Windows:
1. Install the TAP32 driver
http://openvpn.net/index.php/downloads.html
choose OpenVPN 2.0.9 Windows Installer, when installing you can
select to install only the TAP driver.
2. Have one TAP32 interface installed
3. Name the interface "dns"
4. Make sure the interface does not have a default gateway set
5. Run iodine/iodined as normal.
6. Enjoy!
== Building on Windows:
You need:
MinGW, MSYS, GCC, zlib
Then just run make
== Cross-compiling for MinGW:
You need:
MinGW crosscompiler, crosscompiled zlib
Then run "make cross-mingw"
Note that the binaries will not get a .exe suffix
== Zlib download
You can get zlib for MinGW here (both for native and crosscompile):
http://code.kryo.se/iodine/deps/zlib.zip
Unzip it in your MinGW directory on Windows or in $ROOT/usr for
cross-compile.
== Results of crappy Win32 API:
The following fixable limitations apply:
- Exactly one TAP32 interface must be installed
- The TAP32 interface must be named "dns" and be version 0801 or 0901
- Server cannot read packet destination address
The following (probably) un-fixable limitations apply:
- A password entered as -P argument can be shown in process list
- Priviligies cannot be dropped
- chroot() cannot be used
- Detaching from terminal not possible
- Server on windows must be run with /30 netmask
- Client can only talk to server, not other clients

61
doc/proto_00000402.txt Normal file
View File

@ -0,0 +1,61 @@
Detailed specification of protocol in version 00000402
======================================================
CMC = 2 byte Cache Miss Counter, increased every time it is used
Version:
Client sends:
First byte v or V
Rest encoded with base32:
4 bytes big endian protocol version
CMC
Server replies:
4 chars:
VACK (version ok), followed by login challenge
VNAK (version differs), followed by server protocol version
VFUL (server has no free slots), followed by max users
4 byte value: means login challenge/server protocol version/max users
1 byte userid of the new user, or any byte if not VACK
Login:
Client sends:
First byte l or L
Rest encoded with base32:
1 byte userid
16 bytes MD5 hash of: (first 32 bytes of password) xor (8 repetitions of login challenge)
CMC
Server replies:
LNAK means not accepted
x.x.x.x-y.y.y.y-mtu means accepted (server ip, client ip, mtu)
Case check:
Client sends:
First byte z or Z
Lots of data that should not be decoded
Server replies:
The requested domain copied raw
Data:
Data header:
321 0
+---+-+
|UUU|L|
+---+-+
UUU = Userid
L = Last fragment in packet flag
First byte is the header, 4 bits coded as hex in ASCII.
Followed by data encoded with Base32.
Ping:
Client sends:
First byte p or P
Rest encoded with Base32:
1 byte userid
CMC
The server response to Ping and Data packets is a DNS NULL type response:
If server has nothing to send, data length is 0 bytes.
If server has a packet to send, data length is set and the data is a full raw
unencoded ip packet, prefixed with 32 bits tun data.

112
doc/proto_00000500.txt Normal file
View File

@ -0,0 +1,112 @@
Detailed specification of protocol in version 00000500
======================================================
CMC = 2 byte Cache Miss Counter, increased every time it is used
Version:
Client sends:
First byte v or V
Rest encoded with base32:
4 bytes big endian protocol version
CMC
Server replies:
4 chars:
VACK (version ok), followed by login challenge
VNAK (version differs), followed by server protocol version
VFUL (server has no free slots), followed by max users
4 byte value: means login challenge/server protocol version/max users
1 byte userid of the new user, or any byte if not VACK
Login:
Client sends:
First byte l or L
Rest encoded with base32:
1 byte userid
16 bytes MD5 hash of: (first 32 bytes of password) xor (8 repetitions of login challenge)
CMC
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)
Case check:
Client sends:
First byte z or Z
Lots of data that should not be decoded
Server replies:
The requested domain copied raw
Switch codec:
Client sends:
First byte s or S
5 bits coded as Base32 char, meaning userid
5 bits coded as Base32 char, with value 5 or 6, representing number of raw
bits per encoded byte
Server sends:
Name of codec if accepted. After this all upstream data packets must
be encoded with the new codec.
BADCODEC if not accepted. Client must then revert to Base32
Probe downstream fragment size:
Client sends:
First byte r or R
15 bits coded as 3 Base32 chars: UUUUF FFFFF FFFFF
meaning 4 bits userid, 11 bits fragment size
Then follows a long random query which contents does not matter
Server sends:
Requested number of bytes as a response. The first two bytes contains
the requested length. Rest of message can be any data.
BADFRAG if requested length not accepted.
Set downstream fragment size:
Client sends:
First byte n or N
Rest encoded with base32:
1 byte userid
2 bytes new downstream fragment size
CMC
Server sends:
2 bytes new downstream fragment size. After this all downstream
payloads will be max (fragsize + 2) bytes long.
BADFRAG if not accepted.
Data:
Upstream data header:
3210 432 10 43 210 4321 0
+----+---+--+--+---+----+-+
|UUUU|SSS|FF|FF|DDD|GGGG|L|
+----+---+--+--+---+----+-+
Downstream data header:
7 654 3210 765 4321 0
+-+---+----+---+----+-+
|C|SSS|FFFF|DDD|GGGG|L|
+-+---+----+---+----+-+
UUUU = Userid
L = Last fragment in packet flag
SS = Upstream packet sequence number
FFFF = Upstream fragment number
DDD = Downstream packet sequence number
GGGG = Downstream fragment number
C = Compression enabled for downstream packet
Upstream data packet starts with 1 byte ASCII hex coded user byte, then 3 bytes
Base32 encoded header, then comes the payload data, encoded with chosen codec.
Downstream data starts with 2 byte header. Then payload data, which may be
compressed.
Ping:
Client sends:
First byte p or P
Rest encoded with Base32:
1 byte with 4 bits userid
1 byte with:
3 bits downstream seqno
4 bits downstream fragment
CMC
The server response to Ping and Data packets is a DNS NULL type response:
If server has nothing to send, data length is 0 bytes.
If server has something to send, it will send a downstream data packet,
prefixed with 2 bytes header as shown above.

View File

@ -1,5 +1,5 @@
.\" groff -man -Tascii iodine.8 .\" groff -man -Tascii iodine.8
.TH IODINE 8 "FEB 2007" "User Manuals" .TH IODINE 8 "JUL 2008" "User Manuals"
.SH NAME .SH NAME
iodine, iodined \- tunnel IPv4 over DNS iodine, iodined \- tunnel IPv4 over DNS
.SH SYNOPSIS .SH SYNOPSIS
@ -11,32 +11,47 @@ iodine, iodined \- tunnel IPv4 over DNS
.I user .I user
.B ] [-P .B ] [-P
.I password .I password
.B ] [-m
.I fragsize
.B ] [-t .B ] [-t
.I chrootdir .I chrootdir
.B ] [-d .B ] [-d
.I device .I device
.B ] [-m
.I fragsize
.B ] .B ]
.B [
.I nameserver .I nameserver
.B ]
.I topdomain .I topdomain
.B iodined [-v] .B iodined [-v]
.B iodined [-h] .B iodined [-h]
.B iodined [-f] [-u .B iodined [-c] [-s] [-f] [-D] [-u
.I user .I user
.B ] [-P
.I password
.B ] [-t .B ] [-t
.I chrootdir .I chrootdir
.B ] [-d
.I device
.B ] [-m .B ] [-m
.I mtu .I mtu
.B ] [-l .B ] [-l
.I listen_ip .I listen_ip
.B ] [-d .B ] [-p
.I device .I port
.B ] .B ] [-n
.I external ip
.B ] [-b
.I dnsport
.B ] [-P
.I password
.B ]
.I tunnel_ip .I tunnel_ip
.B [
.I /netmask
.B ]
.I topdomain .I topdomain
.SH DESCRIPTION .SH DESCRIPTION
.B iodine .B iodine
@ -66,16 +81,31 @@ Drop privileges and run as user 'user' after setting up tunnel.
.B -t chrootdir .B -t chrootdir
Chroot to 'chrootdir' after setting up tunnel. Chroot to 'chrootdir' after setting up tunnel.
.TP .TP
.B -d device
Use the TUN device 'device' instead of the normal one, which is dnsX on Linux
and otherwise tunX.
.TP
.B -P password .B -P password
Use 'password' to authenticate. If not used, Use 'password' to authenticate. If not used,
.B stdin .B stdin
will be used as input. Only the first 32 characters will be used. will be used as input. Only the first 32 characters will be used.
.SS Client Options:
.TP .TP
.B -d device .B -m fragsize
Use the TUN device 'device' instead of the normal one, which is dnsX on Linux Maximum downstream fragsize. Not setting this will cause the client to probe
and otherwise tunX. the maximum accepted downstream packet size.
.SS Server Options: .SS Server Options:
.TP .TP
.B -c
Disable checks on client IP on all incoming requests.
.TP
.B -s
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
.B -D
Increase debug level. Level 1 prints info about each RX/TX packet.
.TP
.B -m mtu .B -m mtu
Set 'mtu' as mtu size for the tunnel device. This will be sent to the client Set 'mtu' as mtu size for the tunnel device. This will be sent to the client
on connect, and the client will use the same mtu. on connect, and the client will use the same mtu.
@ -88,12 +118,21 @@ connections.
Make the server listen on 'port' instead of 53 for traffic. Make the server listen on 'port' instead of 53 for traffic.
.B Note: .B Note:
You must make sure the dns requests are forwarded to this port yourself. You must make sure the dns requests are forwarded to this port yourself.
.TP
.B -n external ip
The IP address to return in NS responses. Default is to return the address used
as destination in the query.
.TP
.B -b dnsport
If this port is specified, all incoming requests not inside the tunnel domain
will be forwarded to this port on localhost, to be handled by a real dns.
.SS Client Arguments: .SS Client Arguments:
.TP .TP
.B nameserver .B nameserver
The nameserver to use to relay the dns traffic. This can be any relaying The nameserver to use to relay the dns traffic. This can be any relaying
nameserver or the ip number of the server running iodined if reachable. nameserver or the ip number of the server running iodined if reachable.
Normally, you should specify a nameserver from your This argument is optional, and if not specified a nameserver will be read
from the
.I /etc/resolv.conf .I /etc/resolv.conf
file. file.
.TP .TP
@ -106,10 +145,12 @@ is the iodined server, then the topdomain can be chosen freely. This argument
must be the same on both the client and the server. must be the same on both the client and the server.
.SS Server Arguments: .SS Server Arguments:
.TP .TP
.B tunnel_ip .B tunnel_ip[/netmask]
This is the servers ip address on the tunnel interface. The client will be This is the servers ip address on the tunnel 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/8 or 172.16.0.0/12 ranges. 10.0.0.0 or 172.16.0.0 ranges. The default netmask is /27, can be overriden
by specifying it here. Using a smaller network will limit the number of
concurrent users.
.TP .TP
.B topdomain .B topdomain
The dns traffic will is expected to be sent as querys of type NULL for The dns traffic will is expected to be sent as querys of type NULL for
@ -121,13 +162,13 @@ the same on both the client and the server.
.TP .TP
Try it out within your own LAN! Follow these simple steps: Try it out within your own LAN! Follow these simple steps:
.TP .TP
- On your server, run: ./iodined -f 10.0.0.1 test.asdf - On your server, run: ./iodined \-f 10.0.0.1 test.asdf
(If you already use the 10.0.0.0 network, use another internal net like (If you already use the 10.0.0.0 network, use another internal net like
172.16.0.0) 172.16.0.0)
.TP .TP
- Enter a password - Enter a password
.TP .TP
- On the client, run: ./iodine -f 192.168.0.1 test.asdf - On the client, run: ./iodine \-f 192.168.0.1 test.asdf
(Replace 192.168.0.1 with the server's ip address) (Replace 192.168.0.1 with the server's ip address)
.TP .TP
- Enter the same password - Enter the same password
@ -144,10 +185,11 @@ To actually use it through a relaying nameserver, see below.
.TP .TP
.B Server side: .B Server side:
To use this tunnel, you need control over a real domain (like mytunnel.com), To use this tunnel, you need control over a real domain (like mytunnel.com),
and a server with a static public IP number that does not yet run a DNS and a server with a public IP number. If the server already runs a DNS
server. Then, delegate a subdomain (say, tunnel1.mytunnel.com) to the server. server, change the listening port and then use the \-b option to let
If you use BIND for the domain, add these lines to the zone file (replace iodined forward the DNS requests. Then, delegate a subdomain
10.15.213.99 with your server ip): (say, tunnel1.mytunnel.com) to the server. If you use BIND for the domain,
add these lines to the zone file (replace 10.15.213.99 with your server ip):
.nf .nf
tunnel1host IN A 10.15.213.99 tunnel1host IN A 10.15.213.99
@ -157,10 +199,10 @@ tunnel1 IN NS tunnel1host.mytunnel.com.
Now any DNS querys for domains ending with tunnel1.mytunnnel.com will be sent Now any DNS querys for domains ending with tunnel1.mytunnnel.com will be sent
to your server. Start iodined on the server. The first argument is the tunnel to your server. Start iodined on the server. The first argument is the tunnel
IP address (like 192.168.99.1) and the second is the assigned domain (in this IP address (like 192.168.99.1) and the second is the assigned domain (in this
case tunnel1.mytunnel.com). The -f argument will keep iodined running in the case tunnel1.mytunnel.com). The \-f argument will keep iodined running in the
foreground, which helps when testing. iodined will start a virtual interface, foreground, which helps when testing. iodined will start a virtual interface,
and also start listening for DNS queries on UDP port 53. Either enter a and 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 password on the commandline (\-P pass) or after the server has started. Now
everything is ready for the client. everything is ready for the client.
.TP .TP
.B Client side: .B Client side:
@ -179,6 +221,10 @@ The normal case is to route all traffic through the DNS tunnel. To do this, firs
add a route to the nameserver you use with the default gateway as gateway. Then add a route to the nameserver you use with the default gateway as gateway. Then
replace the default gateway with the servers IP address within the DNS tunnel, replace the default gateway with the servers IP address within the DNS tunnel,
and configure the server to do NAT. and configure the server to do NAT.
.TP
.B MTU issues:
These issues should be solved now, with automatic fragmentation of downstream
packets. There should be no need to set the MTU explicitly on the server.
.SH BUGS .SH BUGS
File bugs at http://dev.kryo.se/iodine/ File bugs at http://dev.kryo.se/iodine/
.SH AUTHORS .SH AUTHORS

View File

@ -2,16 +2,17 @@ CC = gcc
COMMONOBJS = tun.o dns.o read.o encoding.o login.o base32.o base64.o md5.o common.o COMMONOBJS = tun.o dns.o read.o encoding.o login.o base32.o base64.o md5.o common.o
CLIENTOBJS = iodine.o CLIENTOBJS = iodine.o
CLIENT = ../bin/iodine CLIENT = ../bin/iodine
SERVEROBJS = iodined.o user.o SERVEROBJS = iodined.o user.o fw_query.o
SERVER = ../bin/iodined SERVER = ../bin/iodined
OS = `uname | tr "a-z" "A-Z"` OS = `echo $(TARGETOS) | tr "a-z" "A-Z"`
ARCH = `uname -m` ARCH = `uname -m`
LDFLAGS = -lz LIBPATH = -L.
CFLAGS = -c -g -Wall -D$(OS) -pedantic LDFLAGS = -lz `sh osflags $(TARGETOS) link` $(LIBPATH)
CFLAGS = -c -g -Wall -D$(OS) -pedantic `sh osflags $(TARGETOS) cflags`
all: stateos $(CLIENT) $(SERVER) $(TESTSUITE) all: stateos $(CLIENT) $(SERVER)
stateos: stateos:
@echo OS is $(OS), arch is $(ARCH) @echo OS is $(OS), arch is $(ARCH)
@ -32,5 +33,5 @@ $(SERVER): $(COMMONOBJS) $(SERVEROBJS)
clean: clean:
@echo "Cleaning src/" @echo "Cleaning src/"
@rm -f $(CLIENT) $(SERVER) *~ *.o *.core @rm -f $(CLIENT){,.exe} $(SERVER){,.exe} *~ *.o *.core

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2007 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se> * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -21,18 +21,28 @@
#include "encoding.h" #include "encoding.h"
#include "base32.h" #include "base32.h"
#define BLKSIZE_RAW 5
#define BLKSIZE_ENC 8
static const char cb32[] = static const char cb32[] =
"abcdefghijklmnopqrstuvwxyz0123456789"; "abcdefghijklmnopqrstuvwxyz012345";
static unsigned char rev32[128]; static unsigned char rev32[128];
static int reverse_init = 0;
static int base32_decode(void *, size_t *, const char *, size_t);
static int base32_encode(char *, size_t *, const void *, size_t);
static int base32_handles_dots();
static int base32_blksize_raw();
static int base32_blksize_enc();
static struct encoder base32_encoder = static struct encoder base32_encoder =
{ {
"BASE32", "Base32",
base32_encode, base32_encode,
base32_decode, base32_decode,
base32_handles_dots, base32_handles_dots,
base32_handles_dots base32_handles_dots,
base32_blksize_raw,
base32_blksize_enc
}; };
struct encoder struct encoder
@ -41,18 +51,58 @@ struct encoder
return &base32_encoder; return &base32_encoder;
} }
int static int
base32_handles_dots() base32_handles_dots()
{ {
return 0; return 0;
} }
int static int
base32_blksize_raw()
{
return BLKSIZE_RAW;
}
static int
base32_blksize_enc()
{
return BLKSIZE_ENC;
}
static void
base32_reverse_init()
{
int i;
unsigned char c;
static int reverse_init = 0;
if (!reverse_init) {
for (i = 0; i < 32; i++) {
c = cb32[i];
rev32[(int) c] = i;
}
reverse_init = 1;
}
}
int
b32_5to8(int in)
{
return cb32[in & 31];
}
int
b32_8to5(int in)
{
base32_reverse_init();
return rev32[in];
}
static int
base32_encode(char *buf, size_t *buflen, const void *data, size_t size) base32_encode(char *buf, size_t *buflen, const void *data, size_t size)
{ {
size_t newsize; size_t newsize;
size_t maxsize; size_t maxsize;
unsigned char *s;
unsigned char *p; unsigned char *p;
unsigned char *q; unsigned char *q;
int i; int i;
@ -60,18 +110,21 @@ base32_encode(char *buf, size_t *buflen, const void *data, size_t size)
memset(buf, 0, *buflen); memset(buf, 0, *buflen);
/* how many chars can we encode within the buf */ /* how many chars can we encode within the buf */
maxsize = 5 * (*buflen / 8 - 1) - 1; maxsize = BLKSIZE_RAW * (*buflen / BLKSIZE_ENC);
/* how big will the encoded data be */ /* how big will the encoded data be */
newsize = 8 * (size / 5 + 1) + 1; newsize = BLKSIZE_ENC * (size / BLKSIZE_RAW);
if (size % BLKSIZE_RAW) {
newsize += BLKSIZE_ENC;
}
/* if the buffer is too small, eat some of the data */ /* if the buffer is too small, eat some of the data */
if (*buflen < newsize) { if (*buflen < newsize) {
size = maxsize; size = maxsize;
} }
p = s = (unsigned char *) buf; p = (unsigned char *) buf;
q = (unsigned char *)data; q = (unsigned char *)data;
for(i=0;i<size;i+=5) { for(i=0;i<size;i+=BLKSIZE_RAW) {
p[0] = cb32[((q[0] & 0xf8) >> 3)]; p[0] = cb32[((q[0] & 0xf8) >> 3)];
p[1] = cb32[(((q[0] & 0x07) << 2) | ((q[1] & 0xc0) >> 6))]; p[1] = cb32[(((q[0] & 0x07) << 2) | ((q[1] & 0xc0) >> 6))];
p[2] = (i+1 < size) ? cb32[((q[1] & 0x3e) >> 1)] : '\0'; p[2] = (i+1 < size) ? cb32[((q[1] & 0x3e) >> 1)] : '\0';
@ -81,15 +134,15 @@ base32_encode(char *buf, size_t *buflen, const void *data, size_t size)
p[6] = (i+3 < size) ? cb32[((q[3] & 0x03) << 3) | ((q[4] & 0xe0) >> 5)] : '\0'; p[6] = (i+3 < size) ? cb32[((q[3] & 0x03) << 3) | ((q[4] & 0xe0) >> 5)] : '\0';
p[7] = (i+4 < size) ? cb32[((q[4] & 0x1f))] : '\0'; p[7] = (i+4 < size) ? cb32[((q[4] & 0x1f))] : '\0';
q += 5; q += BLKSIZE_RAW;
p += 8; p += BLKSIZE_ENC;
} }
*p = 0; *p = 0;
/* store number of bytes from data that was used */ /* store number of bytes from data that was used */
*buflen = size; *buflen = size;
return strlen(buf) - 1; return strlen(buf);
} }
#define DECODE_ERROR 0xffffffff #define DECODE_ERROR 0xffffffff
@ -133,41 +186,33 @@ decode_token(const unsigned char *t, unsigned char *data, size_t len)
return 5; return 5;
} }
int static int
base32_decode(void *buf, size_t *buflen, const char *str, size_t slen) base32_decode(void *buf, size_t *buflen, const char *str, size_t slen)
{ {
unsigned char *q; unsigned char *q;
size_t newsize; size_t newsize;
size_t maxsize; size_t maxsize;
const char *p; const char *p;
unsigned char c;
int len; int len;
int i;
if (!reverse_init) { base32_reverse_init();
for (i = 0; i < 32; i++) {
c = cb32[i];
rev32[(int) c] = i;
}
reverse_init = 1;
}
/* chars needed to decode slen */ /* chars needed to decode slen */
newsize = 5 * (slen / 8 + 1) + 1; newsize = BLKSIZE_RAW * (slen / BLKSIZE_ENC + 1) + 1;
/* encoded chars that fit in buf */ /* encoded chars that fit in buf */
maxsize = 8 * (*buflen / 5 + 1) + 1; maxsize = BLKSIZE_ENC * (*buflen / BLKSIZE_RAW + 1) + 1;
/* if the buffer is too small, eat some of the data */ /* if the buffer is too small, eat some of the data */
if (*buflen < newsize) { if (*buflen < newsize) {
slen = maxsize; slen = maxsize;
} }
q = buf; q = buf;
for (p = str; *p && strchr(cb32, *p); p += 8) { for (p = str; *p && strchr(cb32, *p); p += BLKSIZE_ENC) {
len = decode_token((unsigned char *) p, (unsigned char *) q, slen); len = decode_token((unsigned char *) p, (unsigned char *) q, slen);
q += len; q += len;
slen -= 8; slen -= BLKSIZE_ENC;
if (len < 5) if (len < BLKSIZE_RAW)
break; break;
} }
*q = '\0'; *q = '\0';

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2007 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se> * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -18,8 +18,7 @@
#define __BASE32_H__ #define __BASE32_H__
struct encoder *get_base32_encoder(void); struct encoder *get_base32_encoder(void);
int base32_handles_dots();
int base32_encode(char *, size_t *, const void *, size_t);
int base32_decode(void *, size_t *, const char *, size_t);
int b32_5to8(int);
int b32_8to5(int);
#endif #endif

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2007 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se> * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -22,23 +22,31 @@
#include "common.h" #include "common.h"
#include "base64.h" #include "base64.h"
#define BLKSIZE_RAW 3
#define BLKSIZE_ENC 4
static const char cb64[] = static const char cb64[] =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789."; "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789+";
static unsigned char rev64[128]; static unsigned char rev64[128];
static int reverse_init = 0; static int reverse_init = 0;
static int base64_encode(char *, size_t *, const void *, size_t);
static int base64_decode(void *, size_t *, const char *, size_t);
static int base64_handles_dots();
static int base64_blksize_raw();
static int base64_blksize_enc();
#define REV64(x) rev64[(int) (x)] #define REV64(x) rev64[(int) (x)]
#define MODE (cb64[62])
#define P62 (cb64[62])
#define P63 (cb64[63])
static struct encoder base64_encoder = static struct encoder base64_encoder =
{ {
"BASE64", "Base64",
base64_encode, base64_encode,
base64_decode, base64_decode,
base64_handles_dots, base64_handles_dots,
base64_handles_dots base64_handles_dots,
base64_blksize_raw,
base64_blksize_enc
}; };
struct encoder struct encoder
@ -47,152 +55,29 @@ struct encoder
return &base64_encoder; return &base64_encoder;
} }
int static int
base64_handles_dots() base64_handles_dots()
{ {
return 0; return 0;
} }
static void static int
findesc(int *count, unsigned char *esc, char c1, char c2, char c3, char c4) base64_blksize_raw()
{ {
int min1 = 0; return BLKSIZE_RAW;
int min2 = 0;
int num1 = 0xFF; /* a very big number */
int num2 = 0xFE; /* a nearly as big number */
int i;
/* check if no more escapes needed */
if (count[62] == 0 && count[63] == 0) {
esc[0] = MODE;
esc[1] = MODE;
return;
}
for (i = 0; i < 62; i++) {
if (i == c1 || i == c2 || i == c3 || i == c4) {
continue;
}
if (count[i] < num1) {
min2 = min1;
num2 = num1;
min1 = i;
num1 = count[i];
} else if (count[i] < num2) {
min2 = i;
num2 = count[i];
}
}
esc[0] = cb64[min1];
esc[1] = cb64[min2];
}
static void
escape_chars(char *buf, size_t buflen)
{
int counter[64];
int escapes;
int reset;
int i;
unsigned char temp[4096];
unsigned char *r;
unsigned char *w;
unsigned char *e;
unsigned char esc[2];
memset(counter, 0, sizeof(counter));
esc[0] = P62;
esc[1] = P63;
/* first, find the number of times each token is used */
r = (unsigned char *) buf;
w = temp;
while (*r) {
counter[REV64(*r)]++;
*w++ = *r++;
}
/* check if work needed */
if (counter[62] == 0 && counter[63] == 0)
return;
r = temp;
w = (unsigned char *) buf;
reset = 1;
escapes = 0;
/* check a block for esc chars */
while (*r) {
if (reset == 0 && escapes == 0 && (
r[0] == esc[0] || r[1] == esc[0] ||r[2] == esc[0] ||r[2] == esc[0] ||
r[0] == esc[1] || r[1] == esc[1] ||r[2] == esc[1] ||r[2] == esc[1])) {
/* last set of escape chars were unused.
* if we reset last escape switch then maybe we dont have to switch now */
/* change the latest escape switch to 999 (RESET) */
e[1] = MODE;
e[2] = MODE;
/* store default esc chars */
esc[0] = P62;
esc[1] = P63;
reset = 1;
}
/* these two if blocks can not be combined because a block can contain both
* char 9 and/or . and the current escape chars. */
if (r[0] == esc[0] || r[1] == esc[0] ||r[2] == esc[0] ||r[2] == esc[0] ||
r[0] == esc[1] || r[1] == esc[1] ||r[2] == esc[1] ||r[2] == esc[1]) {
/* switch escape chars */
escapes = 0;
reset = 0;
/* find 2 suitable escape chars */
findesc(counter, esc, REV64(r[0]), REV64(r[1]), REV64(r[2]), REV64(r[3]));
/* store escape switch position */
e = w;
/* write new escape chars */
*w++ = MODE;
*w++ = esc[0];
*w++ = esc[1];
}
/* update counter on remaining chars */
for (i = 0; i < 4; i++) {
if (r[i])
counter[REV64(r[i])]--;
}
/* do the escaping */
for (i = 0; i < 4; i++) {
if (r[i] == P62) {
r[i] = esc[0];
escapes++;
} else if (r[i] == P63) {
r[i] = esc[1];
escapes++;
}
}
/* copy back to buf */
*w++ = *r++;
*w++ = *r++;
*w++ = *r++;
*w++ = *r++;
}
} }
int static int
base64_blksize_enc()
{
return BLKSIZE_ENC;
}
static int
base64_encode(char *buf, size_t *buflen, const void *data, size_t size) base64_encode(char *buf, size_t *buflen, const void *data, size_t size)
{ {
size_t newsize; size_t newsize;
size_t maxsize; size_t maxsize;
unsigned char c;
unsigned char *s; unsigned char *s;
unsigned char *p; unsigned char *p;
unsigned char *q; unsigned char *q;
@ -200,18 +85,14 @@ base64_encode(char *buf, size_t *buflen, const void *data, size_t size)
memset(buf, 0, *buflen); memset(buf, 0, *buflen);
if (!reverse_init) { /* how many chars can we encode within the buf */
for (i = 0; i < 64; i++) { maxsize = BLKSIZE_RAW * (*buflen / BLKSIZE_ENC);
c = cb64[i]; /* how big will the encoded data be */
rev64[(int) c] = i; newsize = BLKSIZE_ENC * (size / BLKSIZE_RAW);
} if (size % BLKSIZE_RAW) {
reverse_init = 1; newsize += BLKSIZE_ENC;
} }
/* how many chars can we encode within the buf */
maxsize = 3 * (*buflen / 4 - 1) - 1;
/* how big will the encoded data be */
newsize = 4 * (size / 3 + 1) + 1;
/* if the buffer is too small, eat some of the data */ /* if the buffer is too small, eat some of the data */
if (*buflen < newsize) { if (*buflen < newsize) {
size = maxsize; size = maxsize;
@ -220,23 +101,21 @@ base64_encode(char *buf, size_t *buflen, const void *data, size_t size)
p = s = (unsigned char *) buf; p = s = (unsigned char *) buf;
q = (unsigned char *)data; q = (unsigned char *)data;
for(i=0;i<size;i+=3) { for(i=0;i<size;i+=BLKSIZE_RAW) {
p[0] = cb64[((q[0] & 0xfc) >> 2)]; p[0] = cb64[((q[0] & 0xfc) >> 2)];
p[1] = cb64[(((q[0] & 0x03) << 4) | ((q[1] & 0xf0) >> 4))]; p[1] = cb64[(((q[0] & 0x03) << 4) | ((q[1] & 0xf0) >> 4))];
p[2] = (i+1 < size) ? cb64[((q[1] & 0x0f) << 2 ) | ((q[2] & 0xc0) >> 6)] : '\0'; p[2] = (i+1 < size) ? cb64[((q[1] & 0x0f) << 2 ) | ((q[2] & 0xc0) >> 6)] : '\0';
p[3] = (i+2 < size) ? cb64[(q[2] & 0x3f)] : '\0'; p[3] = (i+2 < size) ? cb64[(q[2] & 0x3f)] : '\0';
q += 3; q += BLKSIZE_RAW;
p += 4; p += BLKSIZE_ENC;
} }
*p = 0; *p = 0;
escape_chars(buf, *buflen);
/* store number of bytes from data that was used */ /* store number of bytes from data that was used */
*buflen = size; *buflen = size;
return strlen(buf) - 1; return strlen(buf);
} }
#define DECODE_ERROR 0xffffffff #define DECODE_ERROR 0xffffffff
@ -265,7 +144,7 @@ decode_token(const unsigned char *t, unsigned char *data, size_t len)
return 3; return 3;
} }
int static int
base64_decode(void *buf, size_t *buflen, const char *str, size_t slen) base64_decode(void *buf, size_t *buflen, const char *str, size_t slen)
{ {
unsigned char *q; unsigned char *q;
@ -273,9 +152,7 @@ base64_decode(void *buf, size_t *buflen, const char *str, size_t slen)
size_t maxsize; size_t maxsize;
const char *p; const char *p;
unsigned char c; unsigned char c;
unsigned char block[4]; unsigned char block[BLKSIZE_ENC];
unsigned char prot62;
unsigned char prot63;
int len; int len;
int i; int i;
@ -288,47 +165,26 @@ base64_decode(void *buf, size_t *buflen, const char *str, size_t slen)
} }
/* chars needed to decode slen */ /* chars needed to decode slen */
newsize = 3 * (slen / 4 + 1) + 1; newsize = BLKSIZE_RAW * (slen / BLKSIZE_ENC + 1) + 1;
/* encoded chars that fit in buf */ /* encoded chars that fit in buf */
maxsize = 4 * (*buflen / 3 + 1) + 1; maxsize = BLKSIZE_ENC * (*buflen / BLKSIZE_RAW + 1) + 1;
/* if the buffer is too small, eat some of the data */ /* if the buffer is too small, eat some of the data */
if (*buflen < newsize) { if (*buflen < newsize) {
slen = maxsize; slen = maxsize;
} }
prot62 = P62;
prot63 = P63;
q = buf; q = buf;
for (p = str; *p; p += 4) { for (p = str; *p; p += BLKSIZE_ENC) {
/* handle escape instructions */
if (*p == MODE) {
p++;
if (p[0] == MODE && p[1] == MODE) {
/* reset escape chars */
prot62 = P62;
prot63 = P63;
p += 2;
} else {
prot62 = *p++;
prot63 = *p++;
}
}
/* since the str is const, we unescape in another buf */ /* since the str is const, we unescape in another buf */
for (i = 0; i < 4; i++) { for (i = 0; i < BLKSIZE_ENC; i++) {
block[i] = p[i]; block[i] = p[i];
if (prot62 == block[i]) {
block[i] = P62;
} else if (prot63 == block[i]) {
block[i] = P63;
}
} }
len = decode_token(block, (unsigned char *) q, slen); len = decode_token(block, (unsigned char *) q, slen);
q += len; q += len;
slen -= 4; slen -= BLKSIZE_ENC;
if (len < 3) if (len < BLKSIZE_RAW)
break; break;
} }
*q = '\0'; *q = '\0';

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2007 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se> * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -18,8 +18,5 @@
#define __BASE64_H__ #define __BASE64_H__
struct encoder *get_base64_encoder(void); struct encoder *get_base64_encoder(void);
int base64_handles_dots();
int base64_encode(char *, size_t *, const void *, size_t);
int base64_decode(void *, size_t *, const char *, size_t);
#endif #endif

View File

@ -1,4 +1,5 @@
/* Copyright (c) 2006-2007 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se> /* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@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 distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -13,14 +14,9 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <netinet/in.h>
#ifdef DARWIN
#include <arpa/nameser8_compat.h>
#endif
#include <time.h> #include <time.h>
#include <err.h> #include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
@ -29,14 +25,87 @@
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#include <fcntl.h>
#ifdef WINDOWS32
#include <winsock2.h>
#include <conio.h>
#else
#include <arpa/nameser.h>
#ifdef DARWIN
#include <arpa/nameser8_compat.h>
#endif
#include <termios.h>
#include <err.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#endif
#include "common.h" #include "common.h"
/* daemon(3) exists only in 4.4BSD or later, and in GNU libc */
#if !defined(WINDOWS32) && !(defined(BSD) && (BSD >= 199306)) && !defined(__GLIBC__)
static int daemon(int nochdir, int noclose)
{
int fd, i;
switch (fork()) {
case 0:
break;
case -1:
return -1;
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++) {
dup2(fd, i);
}
if (fd > 2) {
close(fd);
}
}
}
return 0;
}
#endif
#if defined(__BEOS__) && !defined(__HAIKU__)
int setgroups(int count, int *groups)
{
/* errno = ENOSYS; */
return -1;
}
#endif
void
check_superuser(void (*usage_fn)(void))
{
#ifndef WINDOWS32
if (geteuid() != 0) {
warnx("Run as root and you'll be happy.\n");
usage_fn();
/* NOTREACHED */
}
#endif
}
int int
open_dns(int localport, in_addr_t listen_ip) open_dns(int localport, in_addr_t listen_ip)
{ {
struct sockaddr_in addr; struct sockaddr_in addr;
int flag; int flag = 1;
int fd; int fd;
memset(&addr, 0, sizeof(addr)); memset(&addr, 0, sizeof(addr));
@ -45,19 +114,32 @@ open_dns(int localport, in_addr_t listen_ip)
/* listen_ip already in network byte order from inet_addr, or 0 */ /* listen_ip already in network byte order from inet_addr, or 0 */
addr.sin_addr.s_addr = listen_ip; addr.sin_addr.s_addr = listen_ip;
if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
fprintf(stderr, "got fd %d\n", fd);
err(1, "socket"); err(1, "socket");
}
flag = 1; flag = 1;
#ifdef SO_REUSEPORT #ifdef SO_REUSEPORT
setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &flag, sizeof(flag)); setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (const void*) &flag, sizeof(flag));
#endif
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void*) &flag, sizeof(flag));
#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));
#endif
#ifdef IP_OPT_DONT_FRAG
/* Set dont-fragment ip header flag */
flag = DONT_FRAG_VALUE;
setsockopt(fd, IPPROTO_IP, IP_OPT_DONT_FRAG, (const void*) &flag, sizeof(flag));
#endif #endif
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag));
if(bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) if(bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0)
err(1, "bind"); err(1, "bind");
printf("Opened UDP socket\n"); fprintf(stderr, "Opened UDP socket\n");
return fd; return fd;
} }
@ -71,20 +153,144 @@ close_dns(int fd)
void void
do_chroot(char *newroot) do_chroot(char *newroot)
{ {
if (newroot) { #if !(defined(WINDOWS32) || defined(__BEOS__) || defined(__HAIKU__))
if (chroot(newroot) != 0 || chdir("/") != 0) if (chroot(newroot) != 0 || chdir("/") != 0)
err(1, "%s", newroot); err(1, "%s", newroot);
seteuid(geteuid()); seteuid(geteuid());
setuid(getuid()); setuid(getuid());
} #else
warnx("chroot not available");
#endif
} }
void void
do_detach() do_detach()
{ {
printf("Detaching from terminal...\n"); #ifndef WINDOWS32
fprintf(stderr, "Detaching from terminal...\n");
daemon(0, 0); daemon(0, 0);
umask(0); umask(0);
alarm(0); alarm(0);
#else
fprintf(stderr, "Windows version does not support detaching\n");
#endif
} }
void
read_password(char *buf, size_t len)
{
char pwd[80];
#ifndef WINDOWS32
struct termios old;
struct termios tp;
tcgetattr(0, &tp);
old = tp;
tp.c_lflag &= (~ECHO);
tcsetattr(0, TCSANOW, &tp);
#else
int i;
#endif
fprintf(stderr, "Enter password: ");
fflush(stderr);
#ifndef WINDOWS32
scanf("%79s", pwd);
#else
for (i = 0; i < sizeof(pwd); i++) {
pwd[i] = getch();
if (pwd[i] == '\r' || pwd[i] == '\n') {
pwd[i] = 0;
break;
} else if (pwd[i] == '\b') {
i--; /* Remove the \b char */
if (i >=0) i--; /* If not first char, remove one more */
}
}
#endif
fprintf(stderr, "\n");
#ifndef WINDOWS32
tcsetattr(0, TCSANOW, &old);
#endif
strncpy(buf, pwd, len);
buf[len-1] = '\0';
}
int
check_topdomain(char *str)
{
int i;
if(str[0] == '.') /* special case */
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;
}
#ifdef WINDOWS32
int
inet_aton(const char *cp, struct in_addr *inp)
{
inp->s_addr = inet_addr(cp);
return inp->s_addr != INADDR_ANY;
}
void
warn(const char *fmt, ...)
{
va_list list;
va_start(list, fmt);
if (fmt) fprintf(stderr, fmt, list);
if (errno == 0) {
fprintf(stderr, ": WSA error %d\n", WSAGetLastError());
} else {
fprintf(stderr, ": %s\n", strerror(errno));
}
va_end(list);
}
void
warnx(const char *fmt, ...)
{
va_list list;
va_start(list, fmt);
if (fmt) fprintf(stderr, fmt, list);
fprintf(stderr, "\n");
va_end(list);
}
void
err(int eval, const char *fmt, ...)
{
va_list list;
va_start(list, fmt);
warn(fmt, list);
va_end(list);
exit(eval);
}
void
errx(int eval, const char *fmt, ...)
{
va_list list;
va_start(list, fmt);
warnx(fmt, list);
va_end(list);
exit(eval);
}
#endif

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2007 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se> * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -17,9 +17,15 @@
#ifndef __COMMON_H__ #ifndef __COMMON_H__
#define __COMMON_H__ #define __COMMON_H__
#include <arpa/inet.h> #ifdef WINDOWS32
#include <sys/types.h> #include "windows.h"
#else
#include <sys/socket.h> #include <sys/socket.h>
#include <err.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#endif
#ifndef MIN #ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b)) #define MIN(a,b) ((a)<(b)?(a):(b))
@ -28,25 +34,67 @@
#define MAX(a,b) ((a)>(b)?(a):(b)) #define MAX(a,b) ((a)>(b)?(a):(b))
#endif #endif
#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
# define DONT_FRAG_VALUE IP_PMTUDISC_DO
#elif defined IP_DONTFRAG
/* FreeBSD */
# define IP_OPT_DONT_FRAG IP_DONTFRAG
# define DONT_FRAG_VALUE 1
#elif defined IP_DONTFRAGMENT
/* Winsock2 */
# define IP_OPT_DONT_FRAG IP_DONTFRAGMENT
# define DONT_FRAG_VALUE 1
#endif
struct packet struct packet
{ {
int len; int len; /* Total packet length */
int offset; int sentlen; /* Length of chunk currently transmitted */
char data[64*1024]; int offset; /* Current offset */
char data[64*1024]; /* The data */
char seqno; /* The packet sequence number */
char fragment; /* Fragment index */
}; };
struct query { struct query {
char name[258]; char name[QUERY_NAME_SIZE];
short type; unsigned short type;
short id; unsigned short id;
struct in_addr destination;
struct sockaddr from; struct sockaddr from;
int fromlen; int fromlen;
}; };
void check_superuser(void (*usage_fn)(void));
int open_dns(int, in_addr_t); int open_dns(int, in_addr_t);
void close_dns(int); void close_dns(int);
void do_chroot(char *); void do_chroot(char *);
void do_detach(); void do_detach();
void read_password(char*, size_t);
int check_topdomain(char *);
#ifdef WINDOWS32
int inet_aton(const char *cp, struct in_addr *inp);
void err(int eval, const char *fmt, ...);
void warn(const char *fmt, ...);
void errx(int eval, const char *fmt, ...);
void warnx(const char *fmt, ...);
#endif
#endif #endif

157
src/dns.c
View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2007 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se> * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -14,13 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <arpa/inet.h>
#include <arpa/nameser.h>
#ifdef DARWIN
#include <arpa/nameser8_compat.h>
#endif
#include <time.h> #include <time.h>
#include <err.h>
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
@ -28,6 +22,18 @@
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#ifdef WINDOWS32
#include "windows.h"
#else
#include <arpa/nameser.h>
#ifdef DARWIN
#include <arpa/nameser8_compat.h>
#endif
#include <arpa/inet.h>
#include <err.h>
#endif
#include "dns.h" #include "dns.h"
#include "encoding.h" #include "encoding.h"
#include "read.h" #include "read.h"
@ -61,7 +67,7 @@ dns_encode(char *buf, size_t buflen, struct query *q, qr_t qr, char *data, size_
name = 0xc000 | ((p - buf) & 0x3fff); name = 0xc000 | ((p - buf) & 0x3fff);
putname(&p, 256, q->name); putname(&p, sizeof(q->name), q->name);
putshort(&p, q->type); putshort(&p, q->type);
putshort(&p, C_IN); putshort(&p, C_IN);
@ -78,7 +84,7 @@ dns_encode(char *buf, size_t buflen, struct query *q, qr_t qr, char *data, size_
header->qdcount = htons(1); header->qdcount = htons(1);
header->arcount = htons(1); header->arcount = htons(1);
putname(&p, 256, data); putname(&p, datalen, data);
putshort(&p, q->type); putshort(&p, q->type);
putshort(&p, C_IN); putshort(&p, C_IN);
@ -98,14 +104,105 @@ dns_encode(char *buf, size_t buflen, struct query *q, qr_t qr, char *data, size_
return len; return len;
} }
int
dns_encode_ns_response(char *buf, size_t buflen, struct query *q, char *topdomain)
{
HEADER *header;
int len;
short name;
short topname;
short nsname;
char *domain;
int domain_len;
char *p;
memset(buf, 0, buflen);
header = (HEADER*)buf;
header->id = htons(q->id);
header->qr = 1;
header->opcode = 0;
header->aa = 1;
header->tc = 0;
header->rd = 0;
header->ra = 0;
p = buf + sizeof(HEADER);
header->qdcount = htons(1);
header->ancount = htons(1);
header->arcount = htons(1);
/* pointer to start of name */
name = 0xc000 | ((p - buf) & 0x3fff);
domain = strstr(q->name, topdomain);
if (domain) {
domain_len = (int) (domain - q->name);
} else {
return -1;
}
/* pointer to start of topdomain */
topname = 0xc000 | ((p - buf + domain_len) & 0x3fff);
/* Query section */
putname(&p, sizeof(q->name), q->name); /* Name */
putshort(&p, q->type); /* Type */
putshort(&p, C_IN); /* Class */
/* Answer section */
putshort(&p, name); /* Name */
putshort(&p, q->type); /* Type */
putshort(&p, C_IN); /* Class */
putlong(&p, 0x3ea7d011); /* TTL */
putshort(&p, 5); /* Data length */
/* pointer to ns.topdomain */
nsname = 0xc000 | ((p - buf) & 0x3fff);
putbyte(&p, 2);
putbyte(&p, 'n');
putbyte(&p, 's');
putshort(&p, topname); /* Name Server */
/* Additional data (A-record of NS server) */
putshort(&p, nsname); /* Name Server */
putshort(&p, T_A); /* Type */
putshort(&p, C_IN); /* Class */
putlong(&p, 0x3ea7d011); /* TTL */
putshort(&p, 4); /* Data length */
/* ugly hack to output IP address */
domain = (char *) &q->destination;
putbyte(&p, *domain++);
putbyte(&p, *domain++);
putbyte(&p, *domain++);
putbyte(&p, *domain);
len = p - buf;
return len;
}
unsigned short
dns_get_id(char *packet, size_t packetlen)
{
HEADER *header;
header = (HEADER*)packet;
if (packetlen < sizeof(HEADER))
return 0;
return ntohs(header->id);
}
int int
dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, size_t packetlen) dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, size_t packetlen)
{ {
char name[QUERY_NAME_SIZE];
char rdata[4*1024]; char rdata[4*1024];
HEADER *header; HEADER *header;
short qdcount; short qdcount;
short ancount; short ancount;
char name[255];
uint32_t ttl; uint32_t ttl;
short class; short class;
short type; short type;
@ -131,13 +228,35 @@ dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, siz
ancount = ntohs(header->ancount); ancount = ntohs(header->ancount);
id = ntohs(header->id); id = ntohs(header->id);
id = id & 0xFFFF; /* Kill any sign extension */
rlen = 0; rlen = 0;
switch (qr) { switch (qr) {
case QR_ANSWER: case QR_ANSWER:
if(qdcount != 1 || ancount != 1) { if(qdcount != 1 || ancount != 1) {
warnx("no query or answer in answer"); switch (header->rcode) {
case REFUSED:
warnx("Got REFUSED as reply");
break;
case NOTIMP:
warnx("Got NOTIMP as reply");
break;
case NXDOMAIN:
warnx("Got NXDOMAIN as reply");
break;
case SERVFAIL:
warnx("Got SERVFAIL as reply");
break;
case NOERROR:
default:
warnx("no query or answer in reply packet");
break;
}
return -1; return -1;
} }
@ -156,28 +275,24 @@ dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, siz
rv = MIN(rlen, sizeof(rdata)); rv = MIN(rlen, sizeof(rdata));
rv = readdata(packet, &data, rdata, rv); rv = readdata(packet, &data, rdata, rv);
if(type == T_NULL && rv > 2) { if(type == T_NULL && rv >= 2 && buf) {
rv = MIN(rv, buflen); rv = MIN(rv, buflen);
memcpy(buf, rdata, rv); memcpy(buf, rdata, rv);
} }
break; break;
case QR_QUERY: case QR_QUERY:
if (qdcount != 1) { if (qdcount != 1) {
warnx("no query on query"); warnx("no question section in name query");
return -1; return -1;
} }
readname(packet, packetlen, &data, name, sizeof(name) -1); readname(packet, packetlen, &data, name, sizeof(name) - 1);
name[256] = 0; name[sizeof(name)-1] = '\0';
readshort(packet, &data, &type); readshort(packet, &data, &type);
readshort(packet, &data, &class); readshort(packet, &data, &class);
if(type != T_NULL) { strncpy(q->name, name, sizeof(q->name));
rv = 0; q->name[sizeof(q->name) - 1] = '\0';
break;
}
strncpy(q->name, name, 257);
q->type = type; q->type = type;
q->id = id; q->id = id;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2007 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se> * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -25,6 +25,8 @@ typedef enum {
} qr_t; } qr_t;
int dns_encode(char *, size_t, struct query *, qr_t, char *, size_t); int dns_encode(char *, size_t, struct query *, qr_t, char *, size_t);
int dns_encode_ns_response(char *buf, size_t buflen, struct query *q, char *topdomain);
unsigned short dns_get_id(char *packet, size_t packetlen);
int dns_decode(char *, size_t, struct query *, qr_t, char *, size_t); int dns_decode(char *, size_t, struct query *, qr_t, char *, size_t);
#endif /* _DNS_H_ */ #endif /* _DNS_H_ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2007 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se> * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -35,7 +35,7 @@ inline_dotify(char *buf, size_t buflen)
char *reader, *writer; char *reader, *writer;
total = strlen(buf); total = strlen(buf);
dots = total / 62; dots = total / 57;
writer = buf; writer = buf;
writer += total; writer += total;
@ -52,12 +52,12 @@ inline_dotify(char *buf, size_t buflen)
pos = (unsigned) (reader - buf) + 1; pos = (unsigned) (reader - buf) + 1;
while (dots) { while (dots) {
if (pos % 62 == 0) { *writer-- = *reader--;
pos--;
if (pos % 57 == 0) {
*writer-- = '.'; *writer-- = '.';
dots--; dots--;
} }
*writer-- = *reader--;
pos--;
} }
/* return new length of string */ /* return new length of string */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2007 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se> * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -23,6 +23,8 @@ struct encoder {
int (*decode) (void *, size_t *, const char *, size_t); int (*decode) (void *, size_t *, const char *, size_t);
int (*places_dots) (void); int (*places_dots) (void);
int (*eats_dots) (void); int (*eats_dots) (void);
int (*blocksize_raw)(void);
int (*blocksize_encoded)(void);
}; };
int unpack_data(char *, size_t, char *, size_t, struct encoder *); int unpack_data(char *, size_t, char *, size_t, struct encoder *);

49
src/fw_query.c Normal file
View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2008 Erik Ekman <yarrick@kryo.se>
*
* 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.
*/
#include <string.h>
#include "fw_query.h"
static struct fw_query fwq[FW_QUERY_CACHE_SIZE];
static int fwq_ix;
void fw_query_init()
{
memset(fwq, 0, sizeof(struct fw_query) * FW_QUERY_CACHE_SIZE);
fwq_ix = 0;
}
void fw_query_put(struct fw_query *fw_query)
{
memcpy(&(fwq[fwq_ix]), fw_query, sizeof(struct fw_query));
++fwq_ix;
if (fwq_ix >= FW_QUERY_CACHE_SIZE)
fwq_ix = 0;
}
void fw_query_get(unsigned short query_id, struct fw_query **fw_query)
{
int i;
*fw_query = NULL;
for (i = 0; i < FW_QUERY_CACHE_SIZE; i++) {
if (fwq[i].id == query_id) {
*fw_query = &(fwq[i]);
return;
}
}
}

41
src/fw_query.h Normal file
View File

@ -0,0 +1,41 @@
/*
* Copyright (c) 2008 Erik Ekman <yarrick@kryo.se>
*
* 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.
*/
#ifndef __FW_QUERY_H__
#define __FW_QUERY_H__
#include <sys/types.h>
#ifdef WINDOWS32
#include "windows.h"
#include <winsock2.h>
#else
#include <sys/socket.h>
#endif
#define FW_QUERY_CACHE_SIZE 16
struct fw_query {
struct sockaddr addr;
int addrlen;
unsigned short id;
};
void fw_query_init();
void fw_query_put(struct fw_query *fw_query);
void fw_query_get(unsigned short query_id, struct fw_query **fw_query);
#endif /*__FW_QUERY_H__*/

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2007 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se> * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -15,9 +15,14 @@
*/ */
#include <string.h> #include <string.h>
#include <arpa/inet.h>
#include <sys/types.h> #include <sys/types.h>
#ifdef WINDOWS32
#include "windows.h"
#else
#include <arpa/inet.h>
#endif
#include "md5.h" #include "md5.h"
/* /*

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2007 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se> * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above

30
src/osflags Executable file
View File

@ -0,0 +1,30 @@
#!/bin/sh
case $2 in
link)
case $1 in
SunOS | solaris)
echo '-lsocket -lnsl';
;;
BeOS)
echo '-lsocket -lbind -lbsd';
;;
Haiku)
echo '-lnetwork';
;;
windows32)
echo '-lws2_32 -liphlpapi';
;;
esac
;;
cflags)
case $1 in
BeOS)
echo '-Dsocklen_t=int';
;;
esac
;;
*)
;;
esac

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2007 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se> * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2007 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se> * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above

335
src/tun.c
View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2007 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se> * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -23,16 +23,39 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
#ifdef WINDOWS32
#include <winsock2.h>
#include <winioctl.h>
#include "windows.h"
HANDLE dev_handle;
struct tun_data data;
#define TAP_CONTROL_CODE(request,method) CTL_CODE(FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS)
#define TAP_IOCTL_CONFIG_TUN TAP_CONTROL_CODE(10, METHOD_BUFFERED)
#define TAP_IOCTL_SET_MEDIA_STATUS TAP_CONTROL_CODE(6, METHOD_BUFFERED)
#define TAP_ADAPTER_KEY "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
#define TAP_DEVICE_SPACE "\\\\.\\Global\\"
#define TAP_VERSION_ID_0801 "tap0801"
#define TAP_VERSION_ID_0901 "tap0901"
#define KEY_COMPONENT_ID "ComponentId"
#define NET_CFG_INST_ID "NetCfgInstanceId"
#else
#include <err.h> #include <err.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netinet/in.h> #include <netinet/in.h>
#include "tun.h"
#define TUN_MAX_TRY 50 #define TUN_MAX_TRY 50
#endif
#include "tun.h"
#include "common.h"
char if_name[50]; char if_name[50];
#ifndef WINDOWS32
#ifdef LINUX #ifdef LINUX
#include <sys/ioctl.h> #include <sys/ioctl.h>
@ -58,10 +81,12 @@ open_tun(const char *tun_device)
if (tun_device != NULL) { if (tun_device != NULL) {
strncpy(ifreq.ifr_name, tun_device, IFNAMSIZ); strncpy(ifreq.ifr_name, tun_device, IFNAMSIZ);
ifreq.ifr_name[IFNAMSIZ-1] = '\0';
strncpy(if_name, tun_device, sizeof(if_name)); strncpy(if_name, tun_device, sizeof(if_name));
if_name[sizeof(if_name)-1] = '\0';
if (ioctl(tun_fd, TUNSETIFF, (void *) &ifreq) != -1) { if (ioctl(tun_fd, TUNSETIFF, (void *) &ifreq) != -1) {
printf("Opened %s\n", ifreq.ifr_name); fprintf(stderr, "Opened %s\n", ifreq.ifr_name);
return tun_fd; return tun_fd;
} }
@ -74,7 +99,7 @@ open_tun(const char *tun_device)
snprintf(ifreq.ifr_name, IFNAMSIZ, "dns%d", i); snprintf(ifreq.ifr_name, IFNAMSIZ, "dns%d", i);
if (ioctl(tun_fd, TUNSETIFF, (void *) &ifreq) != -1) { if (ioctl(tun_fd, TUNSETIFF, (void *) &ifreq) != -1) {
printf("Opened %s\n", ifreq.ifr_name); fprintf(stderr, "Opened %s\n", ifreq.ifr_name);
snprintf(if_name, sizeof(if_name), "dns%d", i); snprintf(if_name, sizeof(if_name), "dns%d", i);
return tun_fd; return tun_fd;
} }
@ -102,20 +127,21 @@ open_tun(const char *tun_device)
if (tun_device != NULL) { if (tun_device != NULL) {
snprintf(tun_name, sizeof(tun_name), "/dev/%s", tun_device); snprintf(tun_name, sizeof(tun_name), "/dev/%s", tun_device);
strncpy(if_name, tun_device, sizeof(if_name)); strncpy(if_name, tun_device, sizeof(if_name));
if_name[sizeof(if_name)-1] = '\0';
if ((tun_fd = open(tun_name, O_RDWR)) < 0) { if ((tun_fd = open(tun_name, O_RDWR)) < 0) {
warn("open_tun: %s: %s", tun_name, strerror(errno)); warn("open_tun: %s: %s", tun_name, strerror(errno));
return -1; return -1;
} }
printf("Opened %s\n", tun_name); fprintf(stderr, "Opened %s\n", tun_name);
return tun_fd; return tun_fd;
} else { } else {
for (i = 0; i < TUN_MAX_TRY; i++) { for (i = 0; i < TUN_MAX_TRY; i++) {
snprintf(tun_name, sizeof(tun_name), "/dev/tun%d", i); snprintf(tun_name, sizeof(tun_name), "/dev/tun%d", i);
if ((tun_fd = open(tun_name, O_RDWR)) >= 0) { if ((tun_fd = open(tun_name, O_RDWR)) >= 0) {
printf("Opened %s\n", tun_name); fprintf(stderr, "Opened %s\n", tun_name);
snprintf(if_name, sizeof(if_name), "tun%d", i); snprintf(if_name, sizeof(if_name), "tun%d", i);
return tun_fd; return tun_fd;
} }
@ -131,6 +157,148 @@ open_tun(const char *tun_device)
} }
#endif /* !LINUX */ #endif /* !LINUX */
#else /* WINDOWS32 */
static void
get_device(char *device, int device_len)
{
LONG status;
HKEY adapter_key;
int index;
index = 0;
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TAP_ADAPTER_KEY, 0, KEY_READ, &adapter_key);
if (status != ERROR_SUCCESS) {
warnx("Error opening registry key " TAP_ADAPTER_KEY );
return;
}
while (TRUE) {
char name[256];
char unit[256];
char component[256];
char cid_string[256] = KEY_COMPONENT_ID;
HKEY device_key;
DWORD datatype;
DWORD len;
/* Iterate through all adapter of this kind */
len = sizeof(name);
status = RegEnumKeyEx(adapter_key, index, name, &len, NULL, NULL, NULL, NULL);
if (status == ERROR_NO_MORE_ITEMS) {
break;
} else if (status != ERROR_SUCCESS) {
warnx("Error enumerating subkeys of registry key " TAP_ADAPTER_KEY );
break;
}
snprintf(unit, sizeof(unit), TAP_ADAPTER_KEY "\\%s", name);
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, unit, 0, KEY_READ, &device_key);
if (status != ERROR_SUCCESS) {
warnx("Error opening registry key %s", unit);
goto next;
}
/* Check component id */
len = sizeof(component);
status = RegQueryValueEx(device_key, cid_string, NULL, &datatype, (LPBYTE)component, &len);
if (status != ERROR_SUCCESS || datatype != REG_SZ) {
goto next;
}
if (strncmp(TAP_VERSION_ID_0801, component, strlen(TAP_VERSION_ID_0801)) == 0 ||
strncmp(TAP_VERSION_ID_0901, component, strlen(TAP_VERSION_ID_0901)) == 0) {
/* We found a TAP32 device, get its NetCfgInstanceId */
char iid_string[256] = NET_CFG_INST_ID;
status = RegQueryValueEx(device_key, iid_string, NULL, &datatype, (LPBYTE) device, (DWORD *) &device_len);
if (status != ERROR_SUCCESS || datatype != REG_SZ) {
warnx("Error reading registry key %s\\%s on TAP device", unit, iid_string);
} else {
/* Done getting name of TAP device */
RegCloseKey(device_key);
return;
}
}
next:
RegCloseKey(device_key);
index++;
}
RegCloseKey(adapter_key);
}
DWORD WINAPI tun_reader(LPVOID arg)
{
struct tun_data *tun = arg;
char buf[64*1024];
int len;
int res;
OVERLAPPED olpd;
int sock;
sock = open_dns(0, INADDR_ANY);
olpd.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
while(TRUE) {
olpd.Offset = 0;
olpd.OffsetHigh = 0;
res = ReadFile(tun->tun, buf, sizeof(buf), (LPDWORD) &len, &olpd);
if (!res) {
WaitForSingleObject(olpd.hEvent, INFINITE);
res = GetOverlappedResult(dev_handle, &olpd, (LPDWORD) &len, FALSE);
res = sendto(sock, buf, len, 0, (struct sockaddr*) &(tun->addr),
sizeof(struct sockaddr_in));
}
}
return 0;
}
int
open_tun(const char *tun_device)
{
char adapter[256];
char tapfile[512];
int tunfd;
in_addr_t local;
memset(adapter, 0, sizeof(adapter));
get_device(adapter, sizeof(adapter));
if (strlen(adapter) == 0) {
warnx("No TAP adapters found. See README-win32.txt for help.\n");
return -1;
}
snprintf(tapfile, sizeof(tapfile), "%s%s.tap", TAP_DEVICE_SPACE, adapter);
fprintf(stderr, "Opening device %s\n", tapfile);
dev_handle = CreateFile(tapfile, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, NULL);
if (dev_handle == INVALID_HANDLE_VALUE) {
return -1;
}
/* TODO get name of interface */
strncpy(if_name, "dns", MIN(4, sizeof(if_name)));
/* Use a UDP connection to forward packets from tun,
* so we can still use select() in main code.
* A thread does blocking reads on tun device and
* sends data as udp to this socket */
local = htonl(0x7f000001); /* 127.0.0.1 */
tunfd = open_dns(55353, local);
data.tun = dev_handle;
memset(&(data.addr), 0, sizeof(data.addr));
data.addr.sin_family = AF_INET;
data.addr.sin_port = htons(55353);
data.addr.sin_addr.s_addr = local;
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)tun_reader, &data, 0, NULL);
return tunfd;
}
#endif
void void
close_tun(int tun_fd) close_tun(int tun_fd)
@ -140,9 +308,9 @@ close_tun(int tun_fd)
} }
int int
write_tun(int tun_fd, char *data, int len) write_tun(int tun_fd, char *data, size_t len)
{ {
#if defined (FREEBSD) || defined (DARWIN) || defined(NETBSD) #if defined (FREEBSD) || defined (DARWIN) || defined(NETBSD) || defined(WINDOWS32)
data += 4; data += 4;
len -= 4; len -= 4;
#else /* !FREEBSD/DARWIN */ #else /* !FREEBSD/DARWIN */
@ -159,75 +327,158 @@ write_tun(int tun_fd, char *data, int len)
#endif /* !LINUX */ #endif /* !LINUX */
#endif /* FREEBSD */ #endif /* FREEBSD */
#ifndef WINDOWS32
if (write(tun_fd, data, len) != len) { if (write(tun_fd, data, len) != len) {
warn("write_tun"); warn("write_tun");
return 1; 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;
}
}
}
#endif
return 0; return 0;
} }
int ssize_t
read_tun(int tun_fd, char *buf, int len) read_tun(int tun_fd, char *buf, size_t len)
{ {
#if defined (FREEBSD) || defined (DARWIN) || defined(NETBSD) #if defined (FREEBSD) || defined (DARWIN) || defined(NETBSD) || defined(WINDOWS32)
/* FreeBSD/Darwin/NetBSD has no header */ /* FreeBSD/Darwin/NetBSD has no header */
return read(tun_fd, buf + 4, len - 4) + 4; int bytes;
memset(buf, 0, 4);
bytes = read(tun_fd, buf + 4, len - 4);
if (bytes < 0) {
return bytes;
} else {
return bytes + 4;
}
#else /* !FREEBSD */ #else /* !FREEBSD */
return read(tun_fd, buf, len); return read(tun_fd, buf, len);
#endif /* !FREEBSD */ #endif /* !FREEBSD */
} }
int int
tun_setip(const char *ip) tun_setip(const char *ip, int netbits)
{ {
char cmdline[512]; char cmdline[512];
int netmask;
if (inet_addr(ip) != INADDR_NONE) { struct in_addr net;
snprintf(cmdline, sizeof(cmdline), int i;
"/sbin/ifconfig %s %s %s netmask 255.255.255.0",
if_name,
ip,
ip);
printf("Setting IP of %s to %s\n", if_name, ip);
#ifndef LINUX #ifndef LINUX
int r; int r;
r = system(cmdline);
if(r != 0) {
return r;
} else {
snprintf(cmdline, sizeof(cmdline),
"/sbin/route add %s/24 %s",
ip, ip);
}
printf("Adding route %s/24 to %s\n", ip, ip);
#endif #endif
return system(cmdline); #ifdef WINDOWS32
DWORD status;
DWORD ipdata[3];
struct in_addr addr;
DWORD len;
#endif
netmask = 0;
for (i = 0; i < netbits; i++) {
netmask = (netmask << 1) | 1;
}
netmask <<= (32 - netbits);
net.s_addr = htonl(netmask);
if (inet_addr(ip) == INADDR_NONE) {
fprintf(stderr, "Invalid IP: %s!\n", ip);
return 1;
}
#ifndef WINDOWS32
snprintf(cmdline, sizeof(cmdline),
"/sbin/ifconfig %s %s %s netmask %s",
if_name,
ip,
ip,
inet_ntoa(net));
fprintf(stderr, "Setting IP of %s to %s\n", if_name, ip);
#ifndef LINUX
r = system(cmdline);
if(r != 0) {
return r;
} else { } else {
printf("Invalid IP: %s!\n", ip); snprintf(cmdline, sizeof(cmdline),
"/sbin/route add %s/%d %s",
ip, netbits, ip);
}
fprintf(stderr, "Adding route %s/%d to %s\n", ip, netbits, ip);
#endif
return system(cmdline);
#else /* WINDOWS32 */
/* Set device as connected */
fprintf(stderr, "Enabling interface '%s'\n", if_name);
status = 1;
r = DeviceIoControl(dev_handle, TAP_IOCTL_SET_MEDIA_STATUS, &status,
sizeof(status), &status, sizeof(status), &len, NULL);
if (!r) {
fprintf(stderr, "Failed to enable interface\n");
return -1;
}
if (inet_aton(ip, &addr)) {
ipdata[0] = (DWORD) addr.s_addr; /* local ip addr */
ipdata[1] = net.s_addr & ipdata[0]; /* network addr */
ipdata[2] = (DWORD) net.s_addr; /* netmask */
} else {
return -1;
} }
return 1; /* Tell ip/networkaddr/netmask to device for arp use */
r = DeviceIoControl(dev_handle, TAP_IOCTL_CONFIG_TUN, &ipdata,
sizeof(ipdata), &ipdata, sizeof(ipdata), &len, NULL);
if (!r) {
fprintf(stderr, "Failed to set interface in TUN mode\n");
return -1;
}
/* use netsh to set ip address */
fprintf(stderr, "Setting IP of interface '%s' to %s (can take a few seconds)...\n", if_name, ip);
snprintf(cmdline, sizeof(cmdline), "netsh interface ip set address \"%s\" static %s %s",
if_name, ip, inet_ntoa(net));
return system(cmdline);
#endif
} }
int int
tun_setmtu(const int mtu) tun_setmtu(const unsigned mtu)
{ {
#ifndef WINDOWS32
char cmdline[512]; char cmdline[512];
if (mtu > 200 && mtu < 1500) { if (mtu > 200 && mtu <= 1500) {
snprintf(cmdline, sizeof(cmdline), snprintf(cmdline, sizeof(cmdline),
"/sbin/ifconfig %s mtu %d", "/sbin/ifconfig %s mtu %u",
if_name, if_name,
mtu); mtu);
printf("Setting MTU of %s to %d\n", if_name, mtu); fprintf(stderr, "Setting MTU of %s to %u\n", if_name, mtu);
return system(cmdline); return system(cmdline);
} else { } else {
warn("MTU out of range: %d\n", mtu); warn("MTU out of range: %u\n", mtu);
} }
return 1; return 1;
#else /* WINDOWS32 */
return 0;
#endif
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2007 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se> * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -19,9 +19,9 @@
int open_tun(const char *); int open_tun(const char *);
void close_tun(int); void close_tun(int);
int write_tun(int, char *, int); int write_tun(int, char *, size_t);
int read_tun(int, char *, int); ssize_t read_tun(int, char *, size_t);
int tun_setip(const char *); int tun_setip(const char *, int);
int tun_setmtu(const int); int tun_setmtu(const unsigned);
#endif /* _TUN_H_ */ #endif /* _TUN_H_ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2007 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se> * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -14,13 +14,25 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <string.h>
#include <stdio.h> #include <stdio.h>
#include <stdint.h>
#include <time.h> #include <time.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <fcntl.h>
#ifdef WINDOWS32
#include <winsock2.h>
#else
#include <err.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <sys/socket.h>
#include <netdb.h>
#endif
#include "common.h" #include "common.h"
#include "encoding.h" #include "encoding.h"
@ -28,22 +40,59 @@
struct user users[USERS]; struct user users[USERS];
void int
init_users(in_addr_t my_ip) init_users(in_addr_t my_ip, int netbits)
{ {
int i; int i;
int skip = 0;
char newip[16]; char newip[16];
int created_users = 0;
int maxusers;
in_addr_t netmask = 0;
struct in_addr net;
struct in_addr ipstart;
for (i = 0; i < netbits; i++) {
netmask = (netmask << 1) | 1;
}
netmask <<= (32 - netbits);
net.s_addr = htonl(netmask);
ipstart.s_addr = my_ip & net.s_addr;
maxusers = (1 << (32-netbits)) - 3; /* 3: Net addr, broadcast addr, iodined addr */
memset(users, 0, USERS * sizeof(struct user)); memset(users, 0, USERS * sizeof(struct user));
for (i = 0; i < USERS; i++) { for (i = 0; i < USERS; i++) {
in_addr_t ip;
users[i].id = i; users[i].id = i;
snprintf(newip, sizeof(newip), "0.0.0.%d", i + 1); snprintf(newip, sizeof(newip), "0.0.0.%d", i + skip + 1);
users[i].tun_ip = my_ip + inet_addr(newip);; ip = ipstart.s_addr + inet_addr(newip);
if (ip == my_ip && skip == 0) {
/* This IP was taken by iodined */
skip++;
snprintf(newip, sizeof(newip), "0.0.0.%d", i + skip + 1);
ip = ipstart.s_addr + inet_addr(newip);
}
users[i].tun_ip = ip;
net.s_addr = ip;
if (maxusers-- < 1) {
users[i].disabled = 1;
} else {
users[i].disabled = 0;
created_users++;
}
users[i].inpacket.len = 0; users[i].inpacket.len = 0;
users[i].inpacket.offset = 0; users[i].inpacket.offset = 0;
users[i].outpacket.len = 0; users[i].outpacket.len = 0;
users[i].q.id = 0; users[i].q.id = 0;
users[i].out_acked_seqno = 0;
users[i].out_acked_fragment = 0;
users[i].fragsize = 4096;
} }
return created_users;
} }
int int
@ -54,7 +103,8 @@ users_waiting_on_reply()
ret = 0; ret = 0;
for (i = 0; i < USERS; i++) { for (i = 0; i < USERS; i++) {
if (users[i].active && users[i].last_pkt + 60 > time(NULL) && if (users[i].active && !users[i].disabled &&
users[i].last_pkt + 60 > time(NULL) &&
users[i].q.id != 0) { users[i].q.id != 0) {
ret++; ret++;
} }
@ -71,7 +121,8 @@ find_user_by_ip(uint32_t ip)
ret = -1; ret = -1;
for (i = 0; i < USERS; i++) { for (i = 0; i < USERS; i++) {
if (users[i].active && users[i].last_pkt + 60 > time(NULL) && if (users[i].active && !users[i].disabled &&
users[i].last_pkt + 60 > time(NULL) &&
ip == users[i].tun_ip) { ip == users[i].tun_ip) {
ret = i; ret = i;
break; break;
@ -90,7 +141,8 @@ all_users_waiting_to_send()
ret = 1; ret = 1;
now = time(NULL); now = time(NULL);
for (i = 0; i < USERS; i++) { for (i = 0; i < USERS; i++) {
if (users[i].active && users[i].last_pkt + 60 > now && if (users[i].active && !users[i].disabled &&
users[i].last_pkt + 60 > now &&
users[i].outpacket.len == 0) { users[i].outpacket.len == 0) {
ret = 0; ret = 0;
break; break;
@ -106,7 +158,7 @@ find_available_user()
int i; int i;
for (i = 0; i < USERS; i++) { for (i = 0; i < USERS; i++) {
/* Not used at all or not used in one minute */ /* Not used at all or not used in one minute */
if (!users[i].active || users[i].last_pkt + 60 < time(NULL)) { if ((!users[i].active || users[i].last_pkt + 60 < time(NULL)) && !users[i].disabled) {
users[i].active = 1; users[i].active = 1;
users[i].last_pkt = time(NULL); users[i].last_pkt = time(NULL);
ret = i; ret = i;
@ -116,3 +168,11 @@ find_available_user()
return ret; return ret;
} }
void
user_switch_codec(int userid, struct encoder *enc)
{
if (userid < 0 || userid >= USERS)
return;
users[userid].encoder = enc;
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2007 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se> * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -17,28 +17,32 @@
#ifndef __USER_H__ #ifndef __USER_H__
#define __USER_H__ #define __USER_H__
#define USERS 8 #define USERS 16
struct user { struct user {
char id; char id;
int active; int active;
int disabled;
time_t last_pkt; time_t last_pkt;
int seed; int seed;
in_addr_t tun_ip; in_addr_t tun_ip;
struct sockaddr host; struct in_addr host;
int addrlen;
struct query q; struct query q;
struct packet inpacket; struct packet inpacket;
struct packet outpacket; struct packet outpacket;
struct encoder *encoder; struct encoder *encoder;
int out_acked_seqno;
int out_acked_fragment;
int fragsize;
}; };
extern struct user users[USERS]; extern struct user users[USERS];
void init_users(in_addr_t); int init_users(in_addr_t, int);
int users_waiting_on_reply(); int users_waiting_on_reply();
int find_user_by_ip(uint32_t); int find_user_by_ip(uint32_t);
int all_users_waiting_to_send(); int all_users_waiting_to_send();
int find_available_user(); int find_available_user();
void user_switch_codec(int userid, struct encoder *enc);
#endif #endif

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2007 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se> * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -19,7 +19,7 @@
/* This is the version of the network protocol /* This is the version of the network protocol
It is usually equal to the latest iodine version number */ It is usually equal to the latest iodine version number */
#define VERSION 0x00000401 #define VERSION 0x00000500
#endif /* _VERSION_H_ */ #endif /* _VERSION_H_ */

85
src/windows.h Normal file
View File

@ -0,0 +1,85 @@
/*
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
*
* 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.
*/
#ifndef __FIX_WINDOWS_H__
#define __FIX_WINDOWS_H__
typedef unsigned int in_addr_t;
#include <windows.h>
#include <windns.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#define T_A DNS_TYPE_A
#define T_NS DNS_TYPE_NS
#define T_NULL DNS_TYPE_NULL
#define C_IN 1
#define SERVFAIL 2
#define NXDOMAIN 3
#define NOTIMP 4
#define REFUSED 5
typedef struct {
unsigned id :16; /* query identification number */
/* fields in third byte */
unsigned rd :1; /* recursion desired */
unsigned tc :1; /* truncated message */
unsigned aa :1; /* authoritive answer */
unsigned opcode :4; /* purpose of message */
unsigned qr :1; /* response flag */
/* fields in fourth byte */
unsigned rcode :4; /* response code */
unsigned cd: 1; /* checking disabled by resolver */
unsigned ad: 1; /* authentic data from named */
unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */
unsigned ra :1; /* recursion available */
/* remaining bytes */
unsigned qdcount :16; /* number of question entries */
unsigned ancount :16; /* number of answer entries */
unsigned nscount :16; /* number of authority entries */
unsigned arcount :16; /* number of resource entries */
} HEADER;
struct ip
{
unsigned int ip_hl:4; /* header length */
unsigned int ip_v:4; /* version */
u_char ip_tos; /* type of service */
u_short ip_len; /* total length */
u_short ip_id; /* identification */
u_short ip_off; /* fragment offset field */
#define IP_RF 0x8000 /* reserved fragment flag */
#define IP_DF 0x4000 /* dont fragment flag */
#define IP_MF 0x2000 /* more fragments flag */
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
u_char ip_ttl; /* time to live */
u_char ip_p; /* protocol */
u_short ip_sum; /* checksum */
struct in_addr ip_src, ip_dst; /* source and dest address */
};
DWORD WINAPI tun_reader(LPVOID arg);
struct tun_data {
HANDLE tun;
int sock;
struct sockaddr_in addr;
};
#endif

View File

@ -1,15 +1,16 @@
CC = gcc CC = gcc
TEST = test TEST = test
OBJS = test.o base32.o base64.o read.o dns.o encoding.o login.o user.o OBJS = test.o base32.o base64.o read.o dns.o encoding.o login.o user.o fw_query.o
SRCOBJS = ../src/base32.o ../src/base64.o ../src/read.o ../src/dns.o ../src/encoding.o ../src/login.o ../src/md5.o ../src/user.o SRCOBJS = ../src/base32.o ../src/base64.o ../src/read.o ../src/dns.o ../src/encoding.o ../src/login.o ../src/md5.o ../src/user.o ../src/fw_query.o
OS = `uname | tr "a-z" "A-Z"` OS = `uname | tr "a-z" "A-Z"`
LDFLAGS = -L/usr/local/lib -lcheck CHECK_PATH = /usr/local
CFLAGS = -g -Wall -D$(OS) -I../src -I/usr/local/include -pedantic LDFLAGS = -L$(CHECK_PATH)/lib -lcheck `../src/osflags link`
CFLAGS = -g -Wall -D$(OS) -I../src -I$(CHECK_PATH)/include -pedantic `../src/osflags cflags`
all: $(TEST) all: $(TEST)
@./$(TEST) @LD_LIBRARY_PATH=${CHECK_PATH}/lib ./$(TEST)
$(TEST): $(OBJS) $(SRCOBJS) $(TEST): $(OBJS) $(SRCOBJS)
@echo LD $(TEST) @echo LD $(TEST)
@ -21,6 +22,6 @@ $(TEST): $(OBJS) $(SRCOBJS)
clean: clean:
@echo "Cleaning..." @echo "Cleaning tests/"
@rm -f *~ *.core $(TEST) $(OBJS) @rm -f *~ *.core $(TEST) $(OBJS)

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2007 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se> * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -24,31 +24,34 @@
#include "base32.h" #include "base32.h"
#include "test.h" #include "test.h"
#define TUPLES 5
static struct tuple static struct tuple
{ {
char *a; char *a;
char *b; char *b;
} testpairs[] = { } testpairs[TUPLES] = {
{ "iodinetestingtesting", "nfxwi0lomv0gk21unfxgo3dfon0gs1th" }, { "iodinetestingtesting", "nfxwi0lomv0gk21unfxgo3dfon0gs1th" },
{ "abc123", "mfrggmjsgm" }, { "abc123", "mfrggmjsgm" },
{ NULL, NULL } { "test", "orsxg3a" },
{ "tst", "orzxi" },
{ "", "" },
}; };
START_TEST(test_base32_encode) START_TEST(test_base32_encode)
{ {
size_t len; size_t len;
char buf[4096]; char buf[4096];
struct encoder *b32;
int val; int val;
int i;
for (i = 0; testpairs[i].a != NULL; i++) { b32 = get_base32_encoder();
len = sizeof(buf);
val = base32_encode(buf, &len, testpairs[i].a, strlen(testpairs[i].a));
fail_unless(val > 0, strerror(errno)); len = sizeof(buf);
fail_unless(strcmp(buf, testpairs[i].b) == 0, val = b32->encode(buf, &len, testpairs[_i].a, strlen(testpairs[_i].a));
va_str("'%s' != '%s'", buf, testpairs[i].b));
} fail_unless(strcmp(buf, testpairs[_i].b) == 0,
"'%s' != '%s'", buf, testpairs[_i].b);
} }
END_TEST END_TEST
@ -56,17 +59,70 @@ START_TEST(test_base32_decode)
{ {
size_t len; size_t len;
char buf[4096]; char buf[4096];
struct encoder *b32;
int val; int val;
b32 = get_base32_encoder();
len = sizeof(buf);
val = b32->decode(buf, &len, testpairs[_i].b, strlen(testpairs[_i].b));
fail_unless(buf != NULL, "buf == NULL");
fail_unless(strcmp(buf, testpairs[_i].a) == 0,
"'%s' != '%s'", buf, testpairs[_i].a);
}
END_TEST
START_TEST(test_base32_5to8_8to5)
{
int i; int i;
int c;
for (i = 0; testpairs[i].a != NULL; i++) { for (i = 0; i < 32; i++) {
len = sizeof(buf); c = b32_5to8(i);
val = base32_decode(buf, &len, testpairs[i].b, strlen(testpairs[i].b)); fail_unless(b32_8to5(c) == i);
}
}
END_TEST
fail_unless(val > 0, strerror(errno)); START_TEST(test_base32_blksize)
fail_unless(buf != NULL, "buf == NULL"); {
fail_unless(strcmp(buf, testpairs[i].a) == 0, size_t rawlen;
va_str("'%s' != '%s'", buf, testpairs[i].a)); size_t enclen;
char *rawbuf;
char *encbuf;
struct encoder *b32;
int i;
int val;
b32 = get_base32_encoder();
rawlen = b32->blocksize_raw();
enclen = b32->blocksize_encoded();
rawbuf = malloc(rawlen + 16);
encbuf = malloc(enclen + 16);
for (i = 0; i < rawlen; i++) {
rawbuf[i] = 'A';
}
rawbuf[i] = 0;
val = b32->encode(encbuf, &enclen, rawbuf, rawlen);
fail_unless(rawlen == 5, "raw length was %d not 5", rawlen);
fail_unless(enclen == 5, "encoded %d bytes, not 5", enclen);
fail_unless(val == 8, "encoded string %s was length %d", encbuf, val);
memset(rawbuf, 0, rawlen + 16);
enclen = val;
val = b32->decode(rawbuf, &rawlen, encbuf, enclen);
fail_unless(rawlen == 5, "raw length was %d not 5", rawlen);
fail_unless(val == 5, "val was not 5 but %d", val);
for (i = 0; i < rawlen; i++) {
fail_unless(rawbuf[i] == 'A');
} }
} }
END_TEST END_TEST
@ -77,8 +133,10 @@ test_base32_create_tests()
TCase *tc; TCase *tc;
tc = tcase_create("Base32"); tc = tcase_create("Base32");
tcase_add_test(tc, test_base32_encode); tcase_add_loop_test(tc, test_base32_encode, 0, TUPLES);
tcase_add_test(tc, test_base32_decode); tcase_add_loop_test(tc, test_base32_decode, 0, TUPLES);
tcase_add_test(tc, test_base32_5to8_8to5);
tcase_add_test(tc, test_base32_blksize);
return tc; return tc;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2007 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se> * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -24,14 +24,16 @@
#include "base64.h" #include "base64.h"
#include "test.h" #include "test.h"
#define TUPLES 5
static struct tuple static struct tuple
{ {
char *a; char *a;
char *b; char *b;
} testpairs[] = { } testpairs[TUPLES] = {
{ "iodinetestingtesting", "Aw8KAw4LDgvZDgLUz2rLC2rPBMC" }, { "iodinetestingtesting", "Aw8KAw4LDgvZDgLUz2rLC2rPBMC" },
{ "abc123", "ywjJmtiZ" }, { "abc1231", "ywjJmtiZmq" },
{ {
"\xFF\xEF\x7C\xEF\xAE\x78\xDF\x6D\x74\xCF\x2C\x70\xBE\xEB\x6C\xAE\xAA\x68" "\xFF\xEF\x7C\xEF\xAE\x78\xDF\x6D\x74\xCF\x2C\x70\xBE\xEB\x6C\xAE\xAA\x68"
"\x9E\x69\x64\x8E\x28\x60\x7D\xE7\x5C\x6D\xA6\x58\x5D\x65\x54\x4D\x24\x50" "\x9E\x69\x64\x8E\x28\x60\x7D\xE7\x5C\x6D\xA6\x58\x5D\x65\x54\x4D\x24\x50"
"\x3C\xE3\x4C\x2C\xA2\x48\x1C\x61\x44\x0C\x20\x40\x3F\x3F\x3C\xEF\xAE\x78" "\x3C\xE3\x4C\x2C\xA2\x48\x1C\x61\x44\x0C\x20\x40\x3F\x3F\x3C\xEF\xAE\x78"
@ -41,11 +43,11 @@ static struct tuple
"\xBE\xEB\x6C\xAE\xAA\x68\x9E\x69\x64\x8E\x28\x60\x7D\xE7\x5C\x6D\xA6\x58" "\xBE\xEB\x6C\xAE\xAA\x68\x9E\x69\x64\x8E\x28\x60\x7D\xE7\x5C\x6D\xA6\x58"
"\x5D\x65\x54\x4D\x24\x50\x3C\xE3\x4C\x2C\xA2\x48\x1C\x61\x44\x0C\x20\x40", "\x5D\x65\x54\x4D\x24\x50\x3C\xE3\x4C\x2C\xA2\x48\x1C\x61\x44\x0C\x20\x40",
"9abba876543210-ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfe999dcbapZ" "+9876543210-ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcbapZ"
"776543210-ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba9abba87654" "776543210-ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba+987654"
"3210-ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfe999dcba" "3210-ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba"
}, },
{ {
"\xFF\xEF\x7C\xEF\xAE\x78\xDF\x6D\x74\xCF\x2C\x70\xBE\xEB\x6C\xAE\xAA\x68" "\xFF\xEF\x7C\xEF\xAE\x78\xDF\x6D\x74\xCF\x2C\x70\xBE\xEB\x6C\xAE\xAA\x68"
"\x9E\x69\x64\x8E\x28\x60\x7D\xE7\x5C\x6D\xA6\x58\x5D\x65\x54\x4D\x24\x50" "\x9E\x69\x64\x8E\x28\x60\x7D\xE7\x5C\x6D\xA6\x58\x5D\x65\x54\x4D\x24\x50"
"\x3C\xE3\x4C\x2C\xA2\x48\x1C\x61\x44\x0C\x20\x40\x3F\x3F\x3C\xEF\xAE\x78" "\x3C\xE3\x4C\x2C\xA2\x48\x1C\x61\x44\x0C\x20\x40\x3F\x3F\x3C\xEF\xAE\x78"
@ -55,28 +57,27 @@ static struct tuple
"\xBE\xEB\x6C\xAE\xA1\x61\x91\x61\x61\x81\x28\x60\x7D\xE7\x5C\x6D\xA6\x58" "\xBE\xEB\x6C\xAE\xA1\x61\x91\x61\x61\x81\x28\x60\x7D\xE7\x5C\x6D\xA6\x58"
"\x5D\x65\x54\x4D\x24\x50\x3C\xE3\x4C\x2C\xA2\x48\x1C\x61\x44\x0C\x20\x40", "\x5D\x65\x54\x4D\x24\x50\x3C\xE3\x4C\x2C\xA2\x48\x1C\x61\x44\x0C\x20\x40",
"9IJJI876543210-ZYXWVUTSRQPONMLK9LMJIHGFEDCBAzyxwvutsrqponmlkjihgfedcbapZ" "+9876543210-ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcbapZ"
"776543210-ZYXWVUTSRQfHKwfHGsHGFEDCBAzyxwvutsrqponmlkjihgfedcbaML87654321" "776543210-ZYXWVUTSRQfHKwfHGsHGFEDCBAzyxwvutsrqponmlkjihgfedcba+987654321"
"0-ZYXWVUTSRQfHKwfHGsHGFEDCBAzyxwvutsrqponmlkjihgfedcba" "0-ZYXWVUTSRQfHKwfHGsHGFEDCBAzyxwvutsrqponmlkjihgfedcba"
}, },
{ NULL, NULL } { "", "" }
}; };
START_TEST(test_base64_encode) START_TEST(test_base64_encode)
{ {
size_t len; size_t len;
char buf[4096]; char buf[4096];
struct encoder *b64;
int val; int val;
int i;
for (i = 0; testpairs[i].a != NULL; i++) { b64 = get_base64_encoder();
len = sizeof(buf);
val = base64_encode(buf, &len, testpairs[i].a, strlen(testpairs[i].a));
fail_unless(val > 0, strerror(errno)); len = sizeof(buf);
fail_unless(strcmp(buf, testpairs[i].b) == 0, val = b64->encode(buf, &len, testpairs[_i].a, strlen(testpairs[_i].a));
va_str("'%s' != '%s'", buf, testpairs[i].b));
} fail_unless(strcmp(buf, testpairs[_i].b) == 0,
"'%s' != '%s'", buf, testpairs[_i].b);
} }
END_TEST END_TEST
@ -84,17 +85,58 @@ START_TEST(test_base64_decode)
{ {
size_t len; size_t len;
char buf[4096]; char buf[4096];
struct encoder *b64;
int val; int val;
b64 = get_base64_encoder();
len = sizeof(buf);
val = b64->decode(buf, &len, testpairs[_i].b, strlen(testpairs[_i].b));
fail_unless(buf != NULL, "buf == NULL");
fail_unless(strcmp(buf, testpairs[_i].a) == 0,
"'%s' != '%s'", buf, testpairs[_i].a);
}
END_TEST
START_TEST(test_base64_blksize)
{
size_t rawlen;
size_t enclen;
char *rawbuf;
char *encbuf;
struct encoder *b64;
int i; int i;
int val;
for (i = 0; testpairs[i].a != NULL; i++) { b64 = get_base64_encoder();
len = sizeof(buf);
val = base64_decode(buf, &len, testpairs[i].b, strlen(testpairs[i].b));
fail_unless(val > 0, strerror(errno)); rawlen = b64->blocksize_raw();
fail_unless(buf != NULL, "buf == NULL"); enclen = b64->blocksize_encoded();
fail_unless(strcmp(buf, testpairs[i].a) == 0,
va_str("'%s' != '%s'", buf, testpairs[i].a)); rawbuf = malloc(rawlen + 16);
encbuf = malloc(enclen + 16);
for (i = 0; i < rawlen; i++) {
rawbuf[i] = 'A';
}
rawbuf[i] = 0;
val = b64->encode(encbuf, &enclen, rawbuf, rawlen);
fail_unless(rawlen == 3, "raw length was %d not 3", rawlen);
fail_unless(enclen == 3, "encoded %d bytes, not 3", enclen);
fail_unless(val == 4, "encoded string %s was length %d", encbuf, val);
memset(rawbuf, 0, rawlen + 16);
enclen = val;
val = b64->decode(rawbuf, &rawlen, encbuf, enclen);
fail_unless(rawlen == 3, "raw length was %d not 3", rawlen);
fail_unless(val == 3);
for (i = 0; i < rawlen; i++) {
fail_unless(rawbuf[i] == 'A');
} }
} }
END_TEST END_TEST
@ -105,8 +147,9 @@ test_base64_create_tests()
TCase *tc; TCase *tc;
tc = tcase_create("Base64"); tc = tcase_create("Base64");
tcase_add_test(tc, test_base64_encode); tcase_add_loop_test(tc, test_base64_encode, 0, TUPLES);
tcase_add_test(tc, test_base64_decode); tcase_add_loop_test(tc, test_base64_decode, 0, TUPLES);
tcase_add_test(tc, test_base64_blksize);
return tc; return tc;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2007 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se> * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -33,24 +33,31 @@
static void dump_packet(char *, size_t); static void dump_packet(char *, size_t);
static char queryPacket[] = static char query_packet[] =
"\x05\x39\x01\x00\x00\x01\x00\x00\x00\x00\x00\x01\x2D\x41\x6A\x62\x63" "\x05\x39\x01\x00\x00\x01\x00\x00\x00\x00\x00\x01\x2D\x41\x6A\x62\x63"
"\x75\x79\x74\x63\x70\x65\x62\x30\x67\x71\x30\x6C\x74\x65\x62\x75\x78" "\x75\x79\x74\x63\x70\x65\x62\x30\x67\x71\x30\x6C\x74\x65\x62\x75\x78"
"\x67\x69\x64\x75\x6E\x62\x73\x73\x61\x33\x64\x66\x6F\x6E\x30\x63\x61" "\x67\x69\x64\x75\x6E\x62\x73\x73\x61\x33\x64\x66\x6F\x6E\x30\x63\x61"
"\x7A\x64\x62\x6F\x72\x71\x71\x04\x6B\x72\x79\x6F\x02\x73\x65\x00\x00" "\x7A\x64\x62\x6F\x72\x71\x71\x04\x6B\x72\x79\x6F\x02\x73\x65\x00\x00"
"\x0A\x00\x01\x00\x00\x29\x10\x00\x00\x00\x80\x00\x00\x00"; "\x0A\x00\x01\x00\x00\x29\x10\x00\x00\x00\x80\x00\x00\x00";
static char answerPacket[] = static char answer_packet[] =
"\x05\x39\x84\x00\x00\x01\x00\x01\x00\x00\x00\x00\x05\x73\x69\x6C\x6C" "\x05\x39\x84\x00\x00\x01\x00\x01\x00\x00\x00\x00\x05\x73\x69\x6C\x6C"
"\x79\x04\x68\x6F\x73\x74\x02\x6F\x66\x06\x69\x6F\x64\x69\x6E\x65\x04" "\x79\x04\x68\x6F\x73\x74\x02\x6F\x66\x06\x69\x6F\x64\x69\x6E\x65\x04"
"\x63\x6F\x64\x65\x04\x6B\x72\x79\x6F\x02\x73\x65\x00\x00\x0A\x00\x01" "\x63\x6F\x64\x65\x04\x6B\x72\x79\x6F\x02\x73\x65\x00\x00\x0A\x00\x01"
"\xC0\x0C\x00\x0A\x00\x01\x00\x00\x00\x00\x00\x23\x74\x68\x69\x73\x20" "\xC0\x0C\x00\x0A\x00\x01\x00\x00\x00\x00\x00\x23\x74\x68\x69\x73\x20"
"\x69\x73\x20\x74\x68\x65\x20\x6D\x65\x73\x73\x61\x67\x65\x20\x74\x6F" "\x69\x73\x20\x74\x68\x65\x20\x6D\x65\x73\x73\x61\x67\x65\x20\x74\x6F"
"\x20\x62\x65\x20\x64\x65\x6C\x69\x76\x65\x72\x65\x64"; "\x20\x62\x65\x20\x64\x65\x6C\x69\x76\x65\x72\x65\x64";
static char answer_packet_high_trans_id[] =
"\x85\x39\x84\x00\x00\x01\x00\x01\x00\x00\x00\x00\x05\x73\x69\x6C\x6C"
"\x79\x04\x68\x6F\x73\x74\x02\x6F\x66\x06\x69\x6F\x64\x69\x6E\x65\x04"
"\x63\x6F\x64\x65\x04\x6B\x72\x79\x6F\x02\x73\x65\x00\x00\x0A\x00\x01"
"\xC0\x0C\x00\x0A\x00\x01\x00\x00\x00\x00\x00\x23\x74\x68\x69\x73\x20"
"\x69\x73\x20\x74\x68\x65\x20\x6D\x65\x73\x73\x61\x67\x65\x20\x74\x6F"
"\x20\x62\x65\x20\x64\x65\x6C\x69\x76\x65\x72\x65\x64";
static char *msgData = "this is the message to be delivered"; static char *msgData = "this is the message to be delivered";
static char *topdomain = "kryo.se"; static char *topdomain = "kryo.se";
static char *innerData = "HELLO this is the test data"; static char *innerData = "HELLO this is the test data";
START_TEST(test_encode_query) START_TEST(test_encode_query)
@ -80,15 +87,15 @@ START_TEST(test_encode_query)
} }
strcpy(d, topdomain); strcpy(d, topdomain);
ret = dns_encode(buf, len, &q, QR_QUERY, resolv, strlen(resolv)); ret = dns_encode(buf, len, &q, QR_QUERY, resolv, strlen(resolv));
len = sizeof(queryPacket) - 1; /* Skip extra null character */ len = sizeof(query_packet) - 1; /* Skip extra null character */
if (strncmp(queryPacket, buf, sizeof(queryPacket)) || ret != len) { if (strncmp(query_packet, buf, sizeof(query_packet)) || ret != len) {
printf("\n"); printf("\n");
dump_packet(queryPacket, len); dump_packet(query_packet, len);
dump_packet(buf, ret); dump_packet(buf, ret);
} }
fail_unless(strncmp(queryPacket, buf, sizeof(queryPacket)) == 0, "Did not compile expected packet"); fail_unless(strncmp(query_packet, buf, sizeof(query_packet)) == 0, "Did not compile expected packet");
fail_unless(ret == len, va_str("Bad packet length: %d, expected %d", ret, len)); fail_unless(ret == len, "Bad packet length: %d, expected %d", ret, len);
} }
END_TEST END_TEST
@ -103,16 +110,16 @@ START_TEST(test_decode_query)
memset(&q, 0, sizeof(struct query)); memset(&q, 0, sizeof(struct query));
memset(&buf, 0, sizeof(buf)); memset(&buf, 0, sizeof(buf));
q.id = 0; q.id = 0;
len = sizeof(queryPacket) - 1; len = sizeof(query_packet) - 1;
enc = get_base32_encoder(); enc = get_base32_encoder();
dns_decode(buf, sizeof(buf), &q, QR_QUERY, queryPacket, len); dns_decode(buf, sizeof(buf), &q, QR_QUERY, query_packet, len);
domain = strstr(q.name, topdomain); domain = strstr(q.name, topdomain);
len = sizeof(buf); len = sizeof(buf);
unpack_data(buf, len, &(q.name[1]), (int) (domain - q.name) - 1, enc); unpack_data(buf, len, &(q.name[1]), (int) (domain - q.name) - 1, enc);
fail_unless(strncmp(buf, innerData, strlen(innerData)) == 0, "Did not extract expected host: '%s'", buf); fail_unless(strncmp(buf, innerData, strlen(innerData)) == 0, "Did not extract expected host: '%s'", buf);
fail_unless(strlen(buf) == strlen(innerData), va_str("Bad host length: %d, expected %d: '%s'", strlen(buf), strlen(innerData), buf)); fail_unless(strlen(buf) == strlen(innerData), "Bad host length: %d, expected %d: '%s'", strlen(buf), strlen(innerData), buf);
} }
END_TEST END_TEST
@ -132,25 +139,76 @@ START_TEST(test_encode_response)
q.id = 1337; q.id = 1337;
ret = dns_encode(buf, len, &q, QR_ANSWER, msgData, strlen(msgData)); ret = dns_encode(buf, len, &q, QR_ANSWER, msgData, strlen(msgData));
len = sizeof(answerPacket) - 1; /* Skip extra null character */ len = sizeof(answer_packet) - 1; /* Skip extra null character */
fail_unless(strncmp(answerPacket, buf, sizeof(answerPacket)) == 0, "Did not compile expected packet"); fail_unless(strncmp(answer_packet, buf, sizeof(answer_packet)) == 0, "Did not compile expected packet");
fail_unless(ret == len, va_str("Bad packet length: %d, expected %d", ret, len)); fail_unless(ret == len, "Bad packet length: %d, expected %d", ret, len);
} }
END_TEST END_TEST
START_TEST(test_decode_response) START_TEST(test_decode_response)
{ {
char buf[512]; char buf[512];
struct query q;
int len; int len;
int ret; int ret;
len = sizeof(buf); len = sizeof(buf);
memset(&buf, 0, sizeof(buf)); memset(&buf, 0, sizeof(buf));
ret = dns_decode(buf, len, NULL, QR_ANSWER, answerPacket, sizeof(answerPacket)-1); ret = dns_decode(buf, len, &q, QR_ANSWER, answer_packet, sizeof(answer_packet)-1);
fail_unless(strncmp(msgData, buf, sizeof(msgData)) == 0, "Did not extract expected data"); fail_unless(strncmp(msgData, buf, sizeof(msgData)) == 0, "Did not extract expected data");
fail_unless(ret == strlen(msgData), va_str("Bad data length: %d, expected %d", ret, strlen(msgData))); fail_unless(ret == strlen(msgData), "Bad data length: %d, expected %d", ret, strlen(msgData));
fail_unless(q.id == 0x0539);
}
END_TEST
START_TEST(test_decode_response_with_high_trans_id)
{
char buf[512];
struct query q;
int len;
int ret;
len = sizeof(buf);
memset(&buf, 0, sizeof(buf));
ret = dns_decode(buf, len, &q, QR_ANSWER, answer_packet_high_trans_id, sizeof(answer_packet_high_trans_id)-1);
fail_unless(strncmp(msgData, buf, sizeof(msgData)) == 0, "Did not extract expected data");
fail_unless(ret == strlen(msgData), "Bad data length: %d, expected %d", ret, strlen(msgData));
fail_unless(q.id == 0x8539, "q.id was %08X instead of %08X!", q.id, 0x8539);
}
END_TEST
START_TEST(test_get_id_short_packet)
{
char buf[5];
int len;
unsigned short id;
len = sizeof(buf);
memset(&buf, 5, sizeof(buf));
id = dns_get_id(buf, len);
fail_unless(id == 0);
}
END_TEST
START_TEST(test_get_id_low)
{
unsigned short id;
id = dns_get_id(answer_packet, sizeof(answer_packet));
fail_unless(id == 1337);
}
END_TEST
START_TEST(test_get_id_high)
{
unsigned short id;
id = dns_get_id(answer_packet_high_trans_id, sizeof(answer_packet_high_trans_id));
fail_unless(id == 0x8539);
} }
END_TEST END_TEST
@ -183,6 +241,10 @@ test_dns_create_tests()
tcase_add_test(tc, test_decode_query); tcase_add_test(tc, test_decode_query);
tcase_add_test(tc, test_encode_response); tcase_add_test(tc, test_encode_response);
tcase_add_test(tc, test_decode_response); tcase_add_test(tc, test_decode_response);
tcase_add_test(tc, test_decode_response_with_high_trans_id);
tcase_add_test(tc, test_get_id_short_packet);
tcase_add_test(tc, test_get_id_low);
tcase_add_test(tc, test_get_id_high);
return tc; return tc;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2007 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se> * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -27,10 +27,12 @@ struct tuple
char *a; char *a;
char *b; char *b;
} dottests[] = { } dottests[] = {
{ "aaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", { "aaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"aaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.a"}, "aaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaa"},
{ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", { "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."}, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."},
{ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"},
{ "abc123", "abc123" }, { "abc123", "abc123" },
{ NULL, NULL } { NULL, NULL }
}; };
@ -41,6 +43,7 @@ START_TEST(test_inline_dotify)
char temp[1024]; char temp[1024];
char *b; char *b;
i = 0;
while (dottests[i].a) { while (dottests[i].a) {
memset(temp, 0, sizeof(temp)); memset(temp, 0, sizeof(temp));
strcpy(temp, dottests[i].a); strcpy(temp, dottests[i].a);
@ -48,7 +51,7 @@ START_TEST(test_inline_dotify)
inline_dotify(b, sizeof(temp)); inline_dotify(b, sizeof(temp));
fail_unless(strcmp(dottests[i].b, temp) == 0, fail_unless(strcmp(dottests[i].b, temp) == 0,
va_str("'%s' != '%s'", temp, dottests[i].b)); "'%s' != '%s'", temp, dottests[i].b);
i++; i++;
} }
} }
@ -60,6 +63,7 @@ START_TEST(test_inline_undotify)
char temp[1024]; char temp[1024];
char *b; char *b;
i = 0;
while (dottests[i].a) { while (dottests[i].a) {
memset(temp, 0, sizeof(temp)); memset(temp, 0, sizeof(temp));
strcpy(temp, dottests[i].b); strcpy(temp, dottests[i].b);
@ -67,7 +71,7 @@ START_TEST(test_inline_undotify)
inline_undotify(b, sizeof(temp)); inline_undotify(b, sizeof(temp));
fail_unless(strcmp(dottests[i].a, temp) == 0, fail_unless(strcmp(dottests[i].a, temp) == 0,
va_str("'%s' != '%s'", temp, dottests[i].a)); "'%s' != '%s'", temp, dottests[i].a);
i++; i++;
} }
} }

88
tests/fw_query.c Normal file
View File

@ -0,0 +1,88 @@
/*
* Copyright (c) 2006-2009 Erik Ekman <yarrick@kryo.se>
*
* 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.
*/
#include <check.h>
#include "fw_query.h"
#include "test.h"
START_TEST(test_fw_query_simple)
{
struct fw_query q;
struct fw_query *qp;
q.addrlen = 33;
q.id = 0x848A;
fw_query_init();
/* Test empty cache */
fw_query_get(0x848A, &qp);
fail_unless(qp == NULL);
fw_query_put(&q);
/* Test cache with one entry */
fw_query_get(0x848A, &qp);
fail_unless(qp->addrlen == q.addrlen);
fail_unless(qp->id == q.id);
}
END_TEST
START_TEST(test_fw_query_edge)
{
struct fw_query q;
struct fw_query *qp;
int i;
fw_query_init();
q.addrlen = 33;
q.id = 0x848A;
fw_query_put(&q);
for (i = 1; i < FW_QUERY_CACHE_SIZE; i++) {
q.addrlen++;
q.id++;
fw_query_put(&q);
}
/* The query should still be cached */
fw_query_get(0x848A, &qp);
fail_unless(qp->addrlen == 33);
fail_unless(qp->id == 0x848A);
q.addrlen++;
q.id++;
fw_query_put(&q);
/* but now it is overwritten */
fw_query_get(0x848A, &qp);
fail_unless(qp == NULL);
}
END_TEST
TCase *
test_fw_query_create_tests()
{
TCase *tc;
tc = tcase_create("Forwarded query");
tcase_add_test(tc, test_fw_query_simple);
tcase_add_test(tc, test_fw_query_edge);
return tc;
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2007 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se> * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -28,7 +28,7 @@ START_TEST(test_login_hash)
int len; int len;
int seed; int seed;
len = 16; len = sizeof(ans);
seed = 15; seed = 15;
memset(ans, 0, sizeof(ans)); memset(ans, 0, sizeof(ans));
@ -37,6 +37,26 @@ START_TEST(test_login_hash)
} }
END_TEST END_TEST
START_TEST(test_login_hash_short)
{
char ans[8];
char check[sizeof(ans)];
char pass[32] = "iodine is the shit";
int len;
int seed;
len = sizeof(ans);
seed = 15;
memset(ans, 0, sizeof(ans));
memset(check, 0, sizeof(check));
/* If len < 16, it should do nothing */
login_calculate(ans, len, pass, seed);
fail_if(memcmp(ans, check, sizeof(ans)));
}
END_TEST
TCase * TCase *
test_login_create_tests() test_login_create_tests()
{ {
@ -44,6 +64,7 @@ test_login_create_tests()
tc = tcase_create("Login"); tc = tcase_create("Login");
tcase_add_test(tc, test_login_hash); tcase_add_test(tc, test_login_hash);
tcase_add_test(tc, test_login_hash_short);
return tc; return tc;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2007 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se> * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -33,7 +33,7 @@
#include "dns.h" #include "dns.h"
#include "read.h" #include "read.h"
#include "test.h" #include "test.h"
START_TEST(test_read_putshort) START_TEST(test_read_putshort)
{ {
unsigned short k; unsigned short k;
@ -44,15 +44,15 @@ START_TEST(test_read_putshort)
for (i = 0; i < 65536; i++) { for (i = 0; i < 65536; i++) {
p = (char*)&k; p = (char*)&k;
putshort(&p, i); putshort(&p, i);
fail_unless(ntohs(k) == i, fail_unless(ntohs(k) == i,
va_str("Bad value on putshort for %d: %d != %d", "Bad value on putshort for %d: %d != %d",
i, ntohs(k), i)); i, ntohs(k), i);
p = (char*)&k; p = (char*)&k;
readshort(NULL, &p, (short *) &l); readshort(NULL, &p, (short *) &l);
fail_unless(l == i, fail_unless(l == i,
va_str("Bad value on readshort for %d: %d != %d", "Bad value on readshort for %d: %d != %d",
i, l, i)); i, l, i);
} }
} }
END_TEST END_TEST
@ -71,45 +71,23 @@ START_TEST(test_read_putlong)
putlong(&p, j); putlong(&p, j);
fail_unless(ntohl(k) == j, fail_unless(ntohl(k) == j,
va_str("Bad value on putlong for %d: %d != %d", i, ntohl(j), j)); "Bad value on putlong for %d: %d != %d", i, ntohl(j), j);
p = (char*)&k; p = (char*)&k;
readlong(NULL, &p, &l); readlong(NULL, &p, &l);
fail_unless(l == j, fail_unless(l == j,
va_str("Bad value on readlong for %d: %d != %d", i, l, j)); "Bad value on readlong for %d: %d != %d", i, l, j);
} }
} }
END_TEST END_TEST
START_TEST(test_read_name) START_TEST(test_read_name_empty_loop)
{ {
unsigned char emptyloop[] = { unsigned char emptyloop[] = {
'A', 'A', 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 'A', 'A', 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01 }; 0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01 };
unsigned char infloop[] = {
'A', 'A', 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 'A', 0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01 };
unsigned char longname[] =
"AA\x81\x80\x00\x01\x00\x00\x00\x00\x00\x00"
"\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA"
"\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA"
"\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA"
"\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA"
"\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA"
"\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA"
"\x00\x00\x01\x00\x01";
unsigned char onejump[] =
"AA\x81\x80\x00\x01\x00\x00\x00\x00\x00\x00"
"\x02hh\xc0\x15\x00\x01\x00\x01\x05zBCDE\x00";
unsigned char badjump[] = {
'A', 'A', 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xfe, 0xcc, 0x00, 0x01, 0x00, 0x01 };
unsigned char badjump2[] = {
'A', 'A', 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 'B', 'A', 0xfe, 0xcc, 0x00, 0x01, 0x00, 0x01 };
unsigned char *jumper;
char buf[1024]; char buf[1024];
char *data; char *data;
int rv; int rv;
@ -118,26 +96,77 @@ START_TEST(test_read_name)
data = (char*) emptyloop + sizeof(HEADER); data = (char*) emptyloop + sizeof(HEADER);
buf[1023] = 'A'; buf[1023] = 'A';
rv = readname((char *) emptyloop, sizeof(emptyloop), &data, buf, 1023); rv = readname((char *) emptyloop, sizeof(emptyloop), &data, buf, 1023);
fail_unless(buf[1023] == 'A', NULL); fail_unless(buf[1023] == 'A');
}
END_TEST
START_TEST(test_read_name_inf_loop)
{
unsigned char infloop[] = {
'A', 'A', 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 'A', 0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01 };
char buf[1024];
char *data;
int rv;
memset(buf, 0, sizeof(buf)); memset(buf, 0, sizeof(buf));
data = (char*) infloop + sizeof(HEADER); data = (char*) infloop + sizeof(HEADER);
buf[4] = '\a'; buf[4] = '\a';
rv = readname((char*) infloop, sizeof(infloop), &data, buf, 4); rv = readname((char*) infloop, sizeof(infloop), &data, buf, 4);
fail_unless(buf[4] == '\a', NULL); fail_unless(buf[4] == '\a');
}
END_TEST
START_TEST(test_read_name_longname)
{
unsigned char longname[] =
"AA\x81\x80\x00\x01\x00\x00\x00\x00\x00\x00"
"\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA"
"\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA"
"\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA"
"\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA"
"\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA"
"\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA"
"\x00\x00\x01\x00\x01";
char buf[1024];
char *data;
int rv;
memset(buf, 0, sizeof(buf)); memset(buf, 0, sizeof(buf));
data = (char*) longname + sizeof(HEADER); data = (char*) longname + sizeof(HEADER);
buf[256] = '\a'; buf[256] = '\a';
rv = readname((char*) longname, sizeof(longname), &data, buf, 256); rv = readname((char*) longname, sizeof(longname), &data, buf, 256);
fail_unless(buf[256] == '\a', NULL); fail_unless(buf[256] == '\a');
}
END_TEST
START_TEST(test_read_name_onejump)
{
unsigned char onejump[] =
"AA\x81\x80\x00\x01\x00\x00\x00\x00\x00\x00"
"\x02hh\xc0\x15\x00\x01\x00\x01\x05zBCDE\x00";
char buf[1024];
char *data;
int rv;
memset(buf, 0, sizeof(buf)); memset(buf, 0, sizeof(buf));
data = (char*) onejump + sizeof(HEADER); data = (char*) onejump + sizeof(HEADER);
rv = readname((char*) onejump, sizeof(onejump), &data, buf, 256); rv = readname((char*) onejump, sizeof(onejump), &data, buf, 256);
fail_unless(rv == 9, NULL); fail_unless(rv == 9);
}
/* These two tests use malloc to cause segfault if jump is executed */ END_TEST
START_TEST(test_read_name_badjump_start)
{
unsigned char badjump[] = {
'A', 'A', 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xfe, 0xcc, 0x00, 0x01, 0x00, 0x01 };
unsigned char *jumper;
char buf[1024];
char *data;
int rv;
/* This test uses malloc to cause segfault if jump is executed */
memset(buf, 0, sizeof(buf)); memset(buf, 0, sizeof(buf));
jumper = malloc(sizeof(badjump)); jumper = malloc(sizeof(badjump));
if (jumper) { if (jumper) {
@ -145,11 +174,24 @@ START_TEST(test_read_name)
data = (char*) jumper + sizeof(HEADER); data = (char*) jumper + sizeof(HEADER);
rv = readname((char*) jumper, sizeof(badjump), &data, buf, 256); rv = readname((char*) jumper, sizeof(badjump), &data, buf, 256);
fail_unless(rv == 0, NULL); fail_unless(rv == 0);
fail_unless(buf[0] == 0, NULL); fail_unless(buf[0] == 0);
} }
free(jumper); free(jumper);
}
END_TEST
START_TEST(test_read_name_badjump_second)
{
unsigned char badjump2[] = {
'A', 'A', 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 'B', 'A', 0xfe, 0xcc, 0x00, 0x01, 0x00, 0x01 };
unsigned char *jumper;
char buf[1024];
char *data;
int rv;
/* This test uses malloc to cause segfault if jump is executed */
memset(buf, 0, sizeof(buf)); memset(buf, 0, sizeof(buf));
jumper = malloc(sizeof(badjump2)); jumper = malloc(sizeof(badjump2));
if (jumper) { if (jumper) {
@ -157,9 +199,9 @@ START_TEST(test_read_name)
data = (char*) jumper + sizeof(HEADER); data = (char*) jumper + sizeof(HEADER);
rv = readname((char*) jumper, sizeof(badjump2), &data, buf, 256); rv = readname((char*) jumper, sizeof(badjump2), &data, buf, 256);
fail_unless(rv == 4, NULL); fail_unless(rv == 4);
fail_unless(strcmp("BA.", buf) == 0, fail_unless(strcmp("BA.", buf) == 0,
va_str("buf is not BA: %s", buf)); "buf is not BA: %s", buf);
} }
free(jumper); free(jumper);
} }
@ -180,15 +222,15 @@ START_TEST(test_putname)
b = buf; b = buf;
ret = putname(&b, 256, domain); ret = putname(&b, 256, domain);
fail_unless(ret == strlen(domain) + 1, NULL); fail_unless(ret == strlen(domain) + 1);
fail_unless(strncmp(buf, out, ret) == 0, "Happy flow failed"); fail_unless(strncmp(buf, out, ret) == 0, "Happy flow failed");
} }
END_TEST END_TEST
START_TEST(test_putname_nodot) START_TEST(test_putname_nodot)
{ {
char buf[256]; char buf[256];
char *nodot = char *nodot =
"ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ" "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"
"ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"; "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ";
char *b; char *b;
@ -201,15 +243,15 @@ START_TEST(test_putname_nodot)
b = buf; b = buf;
ret = putname(&b, 256, nodot); ret = putname(&b, 256, nodot);
fail_unless(ret == -1, NULL); fail_unless(ret == -1);
fail_unless(b == buf, NULL); fail_unless(b == buf);
} }
END_TEST END_TEST
START_TEST(test_putname_toolong) START_TEST(test_putname_toolong)
{ {
char buf[256]; char buf[256];
char *toolong = char *toolong =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ." "ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ."
"ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ." "ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ."
"ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ." "ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ."
@ -226,8 +268,8 @@ START_TEST(test_putname_toolong)
b = buf; b = buf;
ret = putname(&b, 256, toolong); ret = putname(&b, 256, toolong);
fail_unless(ret == -1, NULL); fail_unless(ret == -1);
fail_unless(b == buf, NULL); fail_unless(b == buf);
} }
END_TEST END_TEST
@ -241,7 +283,12 @@ test_read_create_tests()
tcase_set_timeout(tc, 60); tcase_set_timeout(tc, 60);
tcase_add_test(tc, test_read_putshort); tcase_add_test(tc, test_read_putshort);
tcase_add_test(tc, test_read_putlong); tcase_add_test(tc, test_read_putlong);
tcase_add_test(tc, test_read_name); tcase_add_test(tc, test_read_name_empty_loop);
tcase_add_test(tc, test_read_name_inf_loop);
tcase_add_test(tc, test_read_name_longname);
tcase_add_test(tc, test_read_name_onejump);
tcase_add_test(tc, test_read_name_badjump_start);
tcase_add_test(tc, test_read_name_badjump_second);
tcase_add_test(tc, test_putname); tcase_add_test(tc, test_putname);
tcase_add_test(tc, test_putname_nodot); tcase_add_test(tc, test_putname_nodot);
tcase_add_test(tc, test_putname_toolong); tcase_add_test(tc, test_putname_toolong);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2007 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se> * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -22,20 +22,6 @@
#include "test.h" #include "test.h"
char *
va_str(const char *fmt, ...)
{
static char buf[512];
va_list ap;
memset(buf, 0, sizeof(buf));
va_start(ap, fmt);
vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
return buf;
}
int int
main() main()
{ {
@ -67,8 +53,11 @@ main()
test = test_user_create_tests(); test = test_user_create_tests();
suite_add_tcase(iodine, test); suite_add_tcase(iodine, test);
test = test_fw_query_create_tests();
suite_add_tcase(iodine, test);
runner = srunner_create(iodine); runner = srunner_create(iodine);
srunner_run_all(runner, CK_VERBOSE); srunner_run_all(runner, CK_NORMAL);
failed = srunner_ntests_failed(runner); failed = srunner_ntests_failed(runner);
srunner_free(runner); srunner_free(runner);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2007 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se> * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -24,6 +24,7 @@ TCase *test_encoding_create_tests();
TCase *test_read_create_tests(); TCase *test_read_create_tests();
TCase *test_login_create_tests(); TCase *test_login_create_tests();
TCase *test_user_create_tests(); TCase *test_user_create_tests();
TCase *test_fw_query_create_tests();
char *va_str(const char *, ...); char *va_str(const char *, ...);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2007 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se> * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -34,7 +34,7 @@ START_TEST(test_init_users)
int i; int i;
ip = inet_addr("127.0.0.1"); ip = inet_addr("127.0.0.1");
init_users(ip); init_users(ip, 27);
for (i = 0; i < USERS; i++) { for (i = 0; i < USERS; i++) {
fail_unless(users[i].id == i); fail_unless(users[i].id == i);
fail_unless(users[i].q.id == 0); fail_unless(users[i].q.id == 0);
@ -51,7 +51,7 @@ START_TEST(test_users_waiting)
in_addr_t ip; in_addr_t ip;
ip = inet_addr("127.0.0.1"); ip = inet_addr("127.0.0.1");
init_users(ip); init_users(ip, 27);
fail_unless(users_waiting_on_reply() == 0); fail_unless(users_waiting_on_reply() == 0);
@ -75,7 +75,7 @@ START_TEST(test_find_user_by_ip)
unsigned int testip; unsigned int testip;
ip = inet_addr("127.0.0.1"); ip = inet_addr("127.0.0.1");
init_users(ip); init_users(ip, 27);
testip = (unsigned int) inet_addr("10.0.0.1"); testip = (unsigned int) inet_addr("10.0.0.1");
fail_unless(find_user_by_ip(testip) == -1); fail_unless(find_user_by_ip(testip) == -1);
@ -100,7 +100,7 @@ START_TEST(test_all_users_waiting_to_send)
in_addr_t ip; in_addr_t ip;
ip = inet_addr("127.0.0.1"); ip = inet_addr("127.0.0.1");
init_users(ip); init_users(ip, 27);
fail_unless(all_users_waiting_to_send() == 1); fail_unless(all_users_waiting_to_send() == 1);
@ -124,7 +124,7 @@ START_TEST(test_find_available_user)
int i; int i;
ip = inet_addr("127.0.0.1"); ip = inet_addr("127.0.0.1");
init_users(ip); init_users(ip, 27);
for (i = 0; i < USERS; i++) { for (i = 0; i < USERS; i++) {
fail_unless(find_available_user() == i); fail_unless(find_available_user() == i);
@ -146,6 +146,34 @@ START_TEST(test_find_available_user)
} }
END_TEST END_TEST
START_TEST(test_find_available_user_small_net)
{
in_addr_t ip;
int i;
ip = inet_addr("127.0.0.1");
init_users(ip, 29); /* this should result in 5 enabled users */
for (i = 0; i < 5; i++) {
fail_unless(find_available_user() == i);
}
for (i = 0; i < USERS; i++) {
fail_unless(find_available_user() == -1);
}
users[3].active = 0;
fail_unless(find_available_user() == 3);
fail_unless(find_available_user() == -1);
users[3].last_pkt = 55;
fail_unless(find_available_user() == 3);
fail_unless(find_available_user() == -1);
}
END_TEST
TCase * TCase *
test_user_create_tests() test_user_create_tests()
{ {
@ -157,6 +185,7 @@ test_user_create_tests()
tcase_add_test(tc, test_find_user_by_ip); tcase_add_test(tc, test_find_user_by_ip);
tcase_add_test(tc, test_all_users_waiting_to_send); tcase_add_test(tc, test_all_users_waiting_to_send);
tcase_add_test(tc, test_find_available_user); tcase_add_test(tc, test_find_available_user);
tcase_add_test(tc, test_find_available_user_small_net);
return tc; return tc;
} }