mirror of
https://github.com/yarrick/iodine.git
synced 2025-04-11 04:50:55 +00:00
Compare commits
612 commits
v0.6.0-rc1
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
50caf2c45f | ||
|
405a38ca93 | ||
|
2b65972693 | ||
|
ae43de2a8c | ||
|
6299bdbf04 | ||
|
68b0a7b16e | ||
|
55640a0e9a | ||
|
7ec5efeb55 | ||
|
fb7081aba4 | ||
|
2c7940cf77 | ||
|
6be47466f2 | ||
|
ec5c89a368 | ||
|
fc174d5e37 | ||
|
3b1d3a5d4c | ||
|
39c3154a77 | ||
|
8ba813f08e | ||
|
a5d71d0761 | ||
|
b82bc776b3 | ||
|
057be6ce64 | ||
|
3a4a69f50d | ||
|
ba3f0cacb5 | ||
|
d28e8f76ae | ||
|
b20b4f6fae | ||
|
8b78300e99 | ||
|
9262863cae | ||
|
6145eeab73 | ||
|
309a1371e8 | ||
|
a7ba8ed0b3 | ||
|
df49fd6f3d | ||
|
3cb6a1eec2 | ||
|
17169e3444 | ||
|
1df7d235f5 | ||
|
c74618ae9e | ||
|
25867f20b4 | ||
|
b004723a28 | ||
|
0032ffa055 | ||
|
3818a59541 | ||
|
853d5f3764 | ||
|
95fde8b3ee | ||
|
f1e7823a3d | ||
|
589027568b | ||
|
f09dadb1ed | ||
|
5388eae1df | ||
|
6e4107a93b | ||
|
f5a82afe29 | ||
|
cfd0b07e1f | ||
|
569a86a140 | ||
|
cb6cbecba1 | ||
|
348aee839a | ||
|
d00eba8df2 | ||
|
8afcf4fb8d | ||
|
f19948b6cf | ||
|
aa5819fe35 | ||
|
1684aa3806 | ||
|
ee623a2d84 | ||
|
43a82ef6be | ||
|
559dafb030 | ||
|
3c7169fcf5 | ||
|
f2b619faad | ||
|
a6d82b1a44 | ||
|
8041e0368c | ||
|
d02f1b4f41 | ||
|
4c46580e43 | ||
|
02173b8352 | ||
|
25e4caa105 | ||
|
dc307b7183 | ||
|
6a7763c210 | ||
|
cc51ee6f02 | ||
|
4b3d6e2962 | ||
|
9faaa44787 | ||
|
a9045705ba | ||
|
39356163d9 | ||
|
9a041683be | ||
|
8d2c86c73d | ||
|
b7b1082dc6 | ||
|
c399f915b7 | ||
|
bbb604db06 | ||
|
ba90706429 | ||
|
9cba3299c4 | ||
|
5de13805d8 | ||
|
d74939d323 | ||
|
a8a20f570e | ||
|
aeacfbc2c0 | ||
|
15f12d0693 | ||
|
19d0d1be64 | ||
|
310aedac8e | ||
|
13d081f5ed | ||
|
cde0b7632d | ||
|
ec6a1ac308 | ||
|
d09c3e4f0b | ||
|
c77b875e89 | ||
|
07beeca580 | ||
|
ed78f1b43f | ||
|
d8f3ac8971 | ||
|
07b2978326 | ||
|
814a1fd7b0 | ||
|
aae23e2482 | ||
|
db65eed2c3 | ||
|
2032b44949 | ||
|
e8a4c66719 | ||
|
b213d56eb4 | ||
|
ff91879ae1 | ||
|
8379384d37 | ||
|
25323f6839 | ||
|
721b7f0d9b | ||
|
78d64f3cb0 | ||
|
be0735d7c7 | ||
|
8e14f18282 | ||
|
d2f671bdc7 | ||
|
67643ee996 | ||
|
37960ab9dd | ||
|
d37ebdaca7 | ||
|
024481c94b | ||
|
b406009c6d | ||
|
27e5d6fadd | ||
|
05dc792d86 | ||
|
99c0efc467 | ||
|
72bdf7f20e | ||
|
31bfe9ff3e | ||
|
cd5bedca74 | ||
|
9f48fc01a5 | ||
|
122ac1a25d | ||
|
006ffa619e | ||
|
79455c380d | ||
|
8d4b43e178 | ||
|
8c5127b375 | ||
|
119d1b2da1 | ||
|
4591cafd27 | ||
|
0eb3b65158 | ||
|
317511e3ca | ||
|
844a2798eb | ||
|
6b438e7517 | ||
|
b517121f1c | ||
|
d05923d2b1 | ||
|
52c4940523 | ||
|
ccc49f16f7 | ||
|
ac6db12ddb | ||
|
f8f87e3a54 | ||
|
84ded018cf | ||
|
5fd0874aba | ||
|
43dad946c6 | ||
|
b884bfecfb | ||
|
829a822de3 | ||
|
fe0dbccbc5 | ||
|
2efa4dfb35 | ||
|
1c86bf347f | ||
|
c83d2ae03c | ||
|
77dd915ad5 | ||
|
68443abd60 | ||
|
52e9b3479f | ||
|
1ad7c05b92 | ||
|
a96e2e7a69 | ||
|
8e15a73a77 | ||
|
2edb879845 | ||
|
4987aa536d | ||
|
36df8dc16b | ||
|
7b1df75e3a | ||
|
482d005d11 | ||
|
9c8a941729 | ||
|
a8a5fbbf0d | ||
|
e5843a9143 | ||
|
c269a00344 | ||
|
d8bf5cc85b | ||
|
f61ed01a3c | ||
|
7d915500b7 | ||
|
fc1611fc40 | ||
|
4d03ee7786 | ||
|
e7d253b1c1 | ||
|
b4e9148df8 | ||
|
7a51b22909 | ||
|
ec0e3f2e51 | ||
|
7a117bd71e | ||
|
07c2fd4068 | ||
|
3069665646 | ||
|
987a21a0d8 | ||
|
69a91d5421 | ||
|
582a818f2a | ||
|
778d29825d | ||
|
5233d1e858 | ||
|
840155ca9a | ||
|
1f51bab2a3 | ||
|
9e105d21d4 | ||
|
b559806a8e | ||
|
b38b2ca7c5 | ||
|
33abc0ca26 | ||
|
1160649794 | ||
|
434a023afe | ||
|
9a45c4aa66 | ||
|
7433423836 | ||
|
46532539c2 | ||
|
b9a1f14e86 | ||
|
81d932703b | ||
|
cea498e710 | ||
|
cc4bc22447 | ||
|
b4c3656c3c | ||
|
eec0a868d9 | ||
|
b715be5cf3 | ||
|
bf658b0c59 | ||
|
3ebcd29b13 | ||
|
2466cd184a | ||
|
1f4b9250cf | ||
|
4d7678dc5b | ||
|
fbb5a49cf3 | ||
|
3fadbfb580 | ||
|
a23899513d | ||
|
388afe3845 | ||
|
b7e05e0b9a | ||
|
ac931e65e7 | ||
|
95dedf51db | ||
|
d0fb85e8cf | ||
|
5b71224def | ||
|
c52ba7f606 | ||
|
00268bc160 | ||
|
3914d37c99 | ||
|
9bb2323f84 | ||
|
bacb69e4f0 | ||
|
c1b24abf3a | ||
|
d6c3426b84 | ||
|
b3f8e7118a | ||
|
b079b0eda5 | ||
|
031953e295 | ||
|
4aa078ddd9 | ||
|
50d7865967 | ||
|
17de589e7d | ||
|
27f2504cda | ||
|
97b7c604d1 | ||
|
5079d8bf5e | ||
|
9f2e06c525 | ||
|
38216474b0 | ||
|
88590bcaaf | ||
|
f73fb9f8d0 | ||
|
ee1c49a383 | ||
|
06d45682b7 | ||
|
acd6c37ac1 | ||
|
eca80f769b | ||
|
619ede5da8 | ||
|
b827a632ad | ||
|
f249ee3b5d | ||
|
d57aebacdc | ||
|
540d3795a9 | ||
|
7fd8f9854b | ||
|
f02339b3b2 | ||
|
a737d6ea7f | ||
|
400f45c793 | ||
|
a1d88c4f0a | ||
|
8baad91156 | ||
|
f11328306d | ||
|
b0e41e82e4 | ||
|
46a3d82639 | ||
|
9ee78b6f4d | ||
|
c352286deb | ||
|
967276f3ba | ||
|
fb9e930fee | ||
|
0f7c3782b8 | ||
|
97b5e688ef | ||
|
a7f491f808 | ||
|
4f02f7d0aa | ||
|
abb2d6cb87 | ||
|
900647fa0c | ||
|
0903f6d72e | ||
|
b3a12a36d7 | ||
|
bded6a015b | ||
|
abd276ed9e | ||
|
717f1d5d26 | ||
|
27fb4c75cd | ||
|
64ff684754 | ||
|
28ceecba37 | ||
|
1523a4f035 | ||
|
b31e66343a | ||
|
58dac78bd8 | ||
|
2d90aaaf30 | ||
|
ac7cbd4435 | ||
|
59dbaf2b50 | ||
|
ade78ac8a2 | ||
|
3a852a51e2 | ||
|
c99f381719 | ||
|
43e4fb5448 | ||
|
9443f3bbe9 | ||
|
dfbd3e0e0e | ||
|
e1e438497a | ||
|
d9d4c1dba6 | ||
|
01416bbca5 | ||
|
b30abea6b0 | ||
|
45a5d80c49 | ||
|
24241666fa | ||
|
24f1959bab | ||
|
423cbec41d | ||
|
85be9b07d1 | ||
|
a569030bb7 | ||
|
66d9428dff | ||
|
d4849a5dbf | ||
|
9c3343e6ac | ||
|
0a968a5144 | ||
|
dd13d8bba4 | ||
|
0be4332193 | ||
|
b22e3da5a0 | ||
|
465cfe54a3 | ||
|
7ae8d04955 | ||
|
244a47efb8 | ||
|
6e2cf70587 | ||
|
79f0092c70 | ||
|
a96e7db6ae | ||
|
aa818c58bb | ||
|
b177901d38 | ||
|
1a26a91db3 | ||
|
c5bdf07070 | ||
|
365aab1d29 | ||
|
acd264b435 | ||
|
269499ba43 | ||
|
8daba65a03 | ||
|
326da432c9 | ||
|
85104a4088 | ||
|
3c48602747 | ||
|
d597330ecf | ||
|
d87432ec18 | ||
|
60dfbf1b34 | ||
|
05e99c7a3f | ||
|
92b160a416 | ||
|
342b5787be | ||
|
8f2c210019 | ||
|
5951166b36 | ||
|
d4d88d2ad0 | ||
|
40167437d3 | ||
|
55cfed9956 | ||
|
2c2dd6f06e | ||
|
90e25e3a2c | ||
|
aaac632d16 | ||
|
6b78b3a9bd | ||
|
c2bc500cba | ||
|
1fcab767cd | ||
|
05a23a544d | ||
|
4c0fe80ba8 | ||
|
fb17474438 | ||
|
b6eb8d75d4 | ||
|
f9c2257ba9 | ||
|
379ca540ef | ||
|
93a313b130 | ||
|
a1a2e3cefe | ||
|
7e9ce2716b | ||
|
3879f96a80 | ||
|
0cdd537819 | ||
|
01e558022e | ||
|
8074696a14 | ||
|
27fdc23433 | ||
|
a3757a07aa | ||
|
1137ac6ac9 | ||
|
7efdd01ae2 | ||
|
2482a42d01 | ||
|
ef8e3b7ea4 | ||
|
cb926cf0c9 | ||
|
24871faa99 | ||
|
0e81cd78bc | ||
|
473bb93951 | ||
|
7e4ee6c470 | ||
|
ebc1b2f7f8 | ||
|
e5370ad95b | ||
|
58d9615160 | ||
|
02c06d742f | ||
|
3a2f66fb44 | ||
|
293796fcf6 | ||
|
938c2458b9 | ||
|
f86182ced1 | ||
|
72aedb9638 | ||
|
23dc3f0844 | ||
|
a62ae8e562 | ||
|
d5acb508bc | ||
|
17105a26db | ||
|
cf78fdca85 | ||
|
196b37c402 | ||
|
da50020f5b | ||
|
e84b317e0e | ||
|
16e15237cb | ||
|
8fc8ce587c | ||
|
e59aaa523e | ||
|
f20b3c9511 | ||
|
de976d0558 | ||
|
1235cb3e4a | ||
|
c92ed9bad8 | ||
|
950c0870b2 | ||
|
3eef144fce | ||
|
27fc039700 | ||
|
894ca25968 | ||
|
6ac35cfedc | ||
|
7196e97377 | ||
|
96ee6f9630 | ||
|
e51af14bcc | ||
|
5addc77102 | ||
|
3c38a9a307 | ||
|
8b95bded10 | ||
|
4bbf4ecd14 | ||
|
5dccfbecf6 | ||
|
da0de37483 | ||
|
ff86ef15f7 | ||
|
b6c8ea50e5 | ||
|
a3a20a2b09 | ||
|
7d140addae | ||
|
addd798712 | ||
|
3db5cd24b7 | ||
|
1bddcd33aa | ||
|
789d8f3450 | ||
|
54195968c7 | ||
|
bc18afcc83 | ||
|
7b30a2e504 | ||
|
84f5965825 | ||
|
751f672a27 | ||
|
3e07afd13b | ||
|
a5b3c6d63e | ||
|
9c738bbc81 | ||
|
990a03e93d | ||
|
13a5b7c2db | ||
|
af1380f29d | ||
|
4ae304a9b7 | ||
|
0b280bec2b | ||
|
c7b21b7d84 | ||
|
444299b86e | ||
|
eed52b783f | ||
|
aad34d941a | ||
|
9e6ae4ff1d | ||
|
bf46666fe8 | ||
|
1cdba385ef | ||
|
95513517ee | ||
|
b6fc3fc0ef | ||
|
3ee49377e8 | ||
|
0f7ce5d086 | ||
|
1b7e9bed43 | ||
|
df17fdcd28 | ||
|
7473fab9ca | ||
|
eac764705c | ||
|
b3e8cf0554 | ||
|
10fd388bb7 | ||
|
3ad63f8791 | ||
|
b43e97aeb0 | ||
|
adc80adff7 | ||
|
c879d0e194 | ||
|
42cc4ecc3a | ||
|
80ae712a6f | ||
|
ead9c5da8a | ||
|
4734bd0ee0 | ||
|
94f412a8d8 | ||
|
de617fb026 | ||
|
937eaa8007 | ||
|
568c4b18f4 | ||
|
540f411474 | ||
|
e4e38c9593 | ||
|
155f0c6f37 | ||
|
0836ad0a5b | ||
|
6de3368f39 | ||
|
97bf71e944 | ||
|
352d75131f | ||
|
03f4fb11d2 | ||
|
b1bf20d3c8 | ||
|
dc17bc69fe | ||
|
13497b1df6 | ||
|
b5eda882a1 | ||
|
8906264a0a | ||
|
8463d2b2fd | ||
|
78d324a6b4 | ||
|
bd1a8443d1 | ||
|
df93da00c6 | ||
|
9383c84479 | ||
|
3ba81894fc | ||
|
d4fe412b42 | ||
|
c164b8ea54 | ||
|
9be3ef639c | ||
|
2bccb33214 | ||
|
9ababcaa96 | ||
|
d4e077aff4 | ||
|
d2b019a6df | ||
|
23fad5b628 | ||
|
78ae87ebc8 | ||
|
cc17083222 | ||
|
3ed5f7e674 | ||
|
43c438971b | ||
|
c7fa4ddde2 | ||
|
67252cda16 | ||
|
7b76616015 | ||
|
a5031ee9dd | ||
|
268275b8c4 | ||
|
62824e92ed | ||
|
09c904f0c1 | ||
|
7fafac62e7 | ||
|
45d0708306 | ||
|
85e75cadea | ||
|
cc075124fa | ||
|
8d27febc7d | ||
|
2c4c5ec1ba | ||
|
9ff6683119 | ||
|
9facdf281f | ||
|
37b7a9fade | ||
|
05fdfb348e | ||
|
5bf58d6a7e | ||
|
082029e079 | ||
|
25018c9b15 | ||
|
8a093efa59 | ||
|
7eb7c02e5f | ||
|
e5f8b28813 | ||
|
6f19de9ac4 | ||
|
ae942ac542 | ||
|
bc6945527e | ||
|
b36ed27117 | ||
|
e7fdb0a5f5 | ||
|
3f579d2d39 | ||
|
d7f2d60d56 | ||
|
612d142819 | ||
|
33c1efb9ca | ||
|
8769d14cde | ||
|
b5cdb09011 | ||
|
9d3f87ddcc | ||
|
f4cd876ace | ||
|
b38293c11b | ||
|
bd45e6ccb2 | ||
|
49695a4cb4 | ||
|
26cc53e3fa | ||
|
35a8ffe46d | ||
|
02d40c1a7b | ||
|
ec2d6657a0 | ||
|
d24dae882a | ||
|
a07187a629 | ||
|
b1bab9c3dc | ||
|
945467f103 | ||
|
c82280c600 | ||
|
166fb4b6c7 | ||
|
fbaccb2f53 | ||
|
3fc9eaeaa3 | ||
|
5776562339 | ||
|
110866d76b | ||
|
c01f42fd0f | ||
|
21ad2ef5ae | ||
|
284bd8c090 | ||
|
025fb1bf1f | ||
|
539ebb27d9 | ||
|
3a67dfd7ce | ||
|
f06b208f3e | ||
|
0d3494ae78 | ||
|
06f60e2a3b | ||
|
3c3cddee67 | ||
|
081b5b3330 | ||
|
cd91d675ae | ||
|
03a0ccbca0 | ||
|
f70d16403e | ||
|
00c910e247 | ||
|
090c5fdbc1 | ||
|
a36ce9eaaf | ||
|
791c3de84c | ||
|
11c53199cf | ||
|
07e98f181c | ||
|
70d4843166 | ||
|
ccdee286ad | ||
|
7565a2d554 | ||
|
db58f8de20 | ||
|
124c83b7f5 | ||
|
1f69a1b61e | ||
|
dcfa910d1c | ||
|
052fc83bdc | ||
|
924f4b3759 | ||
|
d50533e26e | ||
|
8613f815c9 | ||
|
5b07cdd057 | ||
|
b67819ac81 | ||
|
a114ab3ff9 | ||
|
468844b0a9 | ||
|
3c644e9a88 | ||
|
f23badc9bf | ||
|
3748056240 | ||
|
3c7d3c6a35 | ||
|
998b944225 | ||
|
bebdb6086b | ||
|
bc5f0a7fb7 | ||
|
dc5138bc55 | ||
|
5ebc9ee668 | ||
|
2df8875fcb | ||
|
86a9f52f36 | ||
|
b3c1b3e990 | ||
|
6aefed2666 | ||
|
8fad9a9789 | ||
|
fcec74b3dc | ||
|
1188572a12 | ||
|
59e6239f5a | ||
|
4a16503ea5 | ||
|
91178e7066 | ||
|
63fa76e182 | ||
|
879e73a4c2 | ||
|
71973f13ef | ||
|
89232bcaa6 | ||
|
060c2e3faa | ||
|
1965b0af32 | ||
|
3d07361678 | ||
|
49ad0dbc86 | ||
|
13df3ca856 | ||
|
810bb39899 | ||
|
e16a852fa4 | ||
|
f932e57ce6 | ||
|
285a412563 | ||
|
861da5d022 | ||
|
25e51c666a | ||
|
e8b2310fae | ||
|
60e00a629a | ||
|
fc3de73f85 | ||
|
829e236cba | ||
|
8e2465252d | ||
|
fe4f24a729 | ||
|
1e895fa713 | ||
|
f8e9b0449e | ||
|
f0b4f00883 | ||
|
e9b9ab388b | ||
|
641ae4076f | ||
|
9cd33b53c7 | ||
|
774b7167df | ||
|
56f0a0c6a0 | ||
|
df926094a5 | ||
|
d62b1562ed | ||
|
2146575090 |
68 changed files with 3944 additions and 2476 deletions
28
.github/workflows/freebsd.yml
vendored
Normal file
28
.github/workflows/freebsd.yml
vendored
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
name: freebsd
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: make
|
||||||
|
uses: vmactions/freebsd-vm@v1.0.8
|
||||||
|
with:
|
||||||
|
prepare: |
|
||||||
|
pkg install -y \
|
||||||
|
devel/check \
|
||||||
|
devel/git \
|
||||||
|
devel/pkgconf
|
||||||
|
run: |
|
||||||
|
make
|
||||||
|
make test
|
24
.github/workflows/macos.yml
vendored
Normal file
24
.github/workflows/macos.yml
vendored
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
name: macos
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: macos-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: make
|
||||||
|
run: make
|
||||||
|
- name: install check
|
||||||
|
run: brew install check
|
||||||
|
- name: run tests
|
||||||
|
run: make test
|
28
.github/workflows/openbsd.yml
vendored
Normal file
28
.github/workflows/openbsd.yml
vendored
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
name: openbsd
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: make
|
||||||
|
uses: vmactions/openbsd-vm@v1.0.8
|
||||||
|
with:
|
||||||
|
prepare: |
|
||||||
|
pkg_add \
|
||||||
|
check \
|
||||||
|
git \
|
||||||
|
pkgconf
|
||||||
|
run: |
|
||||||
|
make
|
||||||
|
make test
|
36
.github/workflows/ubuntu.yml
vendored
Normal file
36
.github/workflows/ubuntu.yml
vendored
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
name: ubuntu
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: make
|
||||||
|
run: make
|
||||||
|
- name: install check
|
||||||
|
run: sudo apt install check
|
||||||
|
- name: run tests
|
||||||
|
run: make test
|
||||||
|
|
||||||
|
build-android:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: nttld/setup-ndk@v1
|
||||||
|
with:
|
||||||
|
ndk-version: r21e
|
||||||
|
- name: make
|
||||||
|
run: make cross-android
|
28
.github/workflows/windows.yml
vendored
Normal file
28
.github/workflows/windows.yml
vendored
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
name: windows
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: windows-latest
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: msys2 {0}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: msys2/setup-msys2@v2
|
||||||
|
with:
|
||||||
|
msystem: MINGW64
|
||||||
|
update: false
|
||||||
|
install: git make mingw-w64-x86_64-toolchain mingw-w64-x86_64-zlib
|
||||||
|
- name: make
|
||||||
|
run: make TARGETOS=windows32
|
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
/bin/
|
||||||
|
*.o
|
||||||
|
/src/base64u.c
|
||||||
|
/src/base64u.h
|
||||||
|
/tests/test
|
||||||
|
*.o.d
|
||||||
|
/src/obj/local/*/iodine
|
||||||
|
/src/libs/*/iodine
|
4
.vimrc
Normal file
4
.vimrc
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
set noexpandtab
|
||||||
|
set tabstop=8
|
||||||
|
set softtabstop=8
|
||||||
|
set shiftwidth=8
|
56
CHANGELOG
56
CHANGELOG
|
@ -1,11 +1,56 @@
|
||||||
|
|
||||||
iodine - http://code.kryo.se/iodine
|
iodine - https://code.kryo.se/iodine
|
||||||
|
|
||||||
***********************************
|
************************************
|
||||||
|
|
||||||
CHANGES:
|
CHANGES:
|
||||||
|
|
||||||
2010-02-13: 0.6.0-rc1 "Hotspotify"
|
master:
|
||||||
|
- Changed deprecated tzsetwall() to tzset() (only used by FreeBSD),
|
||||||
|
patch by Pouria Mousavizadeh Tehrani.
|
||||||
|
- Now builds on macOS even without if_utun.h (pre 10.6).
|
||||||
|
|
||||||
|
2023-04-17: 0.8.0 "Burning Snowman"
|
||||||
|
- Mac OS X: Support native utun VPN devices. Patch by
|
||||||
|
Peter Sagerson, ported from OpenVPN by Catalin Patulea.
|
||||||
|
- Fix compilation failure on kFreeBSD and Hurd, by Gregor Herrmann
|
||||||
|
- Patch from Ryan Welton that fixes compilation warning.
|
||||||
|
- README converted to markdown by Nicolas Braud-Santoni.
|
||||||
|
- Linux: use pkg-config for systemd support flags.
|
||||||
|
Patch by Jason A. Donenfeld.
|
||||||
|
- Add support for IPv6 in the server.
|
||||||
|
Raw mode will be with same protocol as used for login.
|
||||||
|
Traffic inside tunnel is still IPv4.
|
||||||
|
- Update android build to try to support 5.0 (Lollipop) and newer.
|
||||||
|
- Change external IP lookup to using myip.opendns.com via DNS.
|
||||||
|
- Add option to choose IPv4 listen address from external IP lookup.
|
||||||
|
- Add server support for handling multiple domains via wildcard.
|
||||||
|
- Recognize tap device component id 'root' prefix on Windows.
|
||||||
|
|
||||||
|
2014-06-16: 0.7.0 "Kryoptonite"
|
||||||
|
- Partial IPv6 support (#107)
|
||||||
|
Client can connect to iodined through an relaying IPv6
|
||||||
|
nameserver. Server only supports IPv4 for now.
|
||||||
|
Traffic inside tunnel is IPv4.
|
||||||
|
- Add socket activation for systemd, by Michael Scherer.
|
||||||
|
- Add automated lookup of external ip (via -n auto).
|
||||||
|
- Bugfix for OS X (Can't assign requested address)
|
||||||
|
- Fix DNS tunneling bug caused by uninitialized variable, #94
|
||||||
|
- Handle spaces when entering password interactively, fixes #93.
|
||||||
|
Patch by Hagar.
|
||||||
|
- Add -R option to set OpenBSD routing domain for the DNS socket.
|
||||||
|
Patch by laurent at gouloum fr, fixes #95.
|
||||||
|
- Add android patches and makefile, from Marcel Bokhorst, fixes #105.
|
||||||
|
- Added missing break in iodine.c, by Pavel Pergamenshchik, #108.
|
||||||
|
- A number of minor patches from Frank Denis, Gregor Herrmann and
|
||||||
|
Barak A. Pearlmutter.
|
||||||
|
- Testcase compilation fixes for OS X and FreeBSD
|
||||||
|
- Do not let sockets be inherited by sub-processes, fixes #99.
|
||||||
|
- Add unspecified RR type (called PRIVATE; id 65399, in private use
|
||||||
|
range). For servers with RFC3597 support. Fixes #97.
|
||||||
|
- Fix authentication bypass vulnerability; found by Oscar Reparaz.
|
||||||
|
|
||||||
|
2010-02-06: 0.6.0-rc1 "Hotspotify"
|
||||||
- Fixed tunnel not working on Windows.
|
- Fixed tunnel not working on Windows.
|
||||||
- Any device name is now supported on Windows, fixes #47.
|
- Any device name is now supported on Windows, fixes #47.
|
||||||
- Multiple installed TAP32 interfaces are now supported, fixes #46.
|
- Multiple installed TAP32 interfaces are now supported, fixes #46.
|
||||||
|
@ -30,6 +75,7 @@ CHANGES:
|
||||||
- Merged low-latency patch from Anne Bezemer, fixes #76.
|
- Merged low-latency patch from Anne Bezemer, fixes #76.
|
||||||
- Resolve client nameserver argument if given as hostname, fixes #82.
|
- Resolve client nameserver argument if given as hostname, fixes #82.
|
||||||
- Open log before chroot, fixes #86: logging on FreeBSD.
|
- Open log before chroot, fixes #86: logging on FreeBSD.
|
||||||
|
- Merged big bugfix patch from Anne Bezemer, #88.
|
||||||
|
|
||||||
2009-06-01: 0.5.2 "WifiFree"
|
2009-06-01: 0.5.2 "WifiFree"
|
||||||
- Fixed client segfault on OS X, #57
|
- Fixed client segfault on OS X, #57
|
||||||
|
@ -131,10 +177,10 @@ CHANGES:
|
||||||
- New encoding, 25% more peak upstream throughput
|
- New encoding, 25% more peak upstream throughput
|
||||||
- New -l option to set local ip to listen to on server
|
- New -l option to set local ip to listen to on server
|
||||||
|
|
||||||
2006-07-11: 0.3.1
|
2006-07-11: 0.3.1
|
||||||
- Add Mac OSX support
|
- Add Mac OSX support
|
||||||
- Add setting device name
|
- Add setting device name
|
||||||
- Use compression of domain name in reply (should allow setting MTU
|
- Use compression of domain name in reply (should allow setting MTU
|
||||||
approx 200 bytes higher)
|
approx 200 bytes higher)
|
||||||
|
|
||||||
2006-06-24: 0.3.0
|
2006-06-24: 0.3.0
|
||||||
|
|
13
LICENSE
Normal file
13
LICENSE
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
Copyright (c) 2006-2020 iodine authors
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any purpose
|
||||||
|
with or without fee is hereby granted, provided that the above copyright notice
|
||||||
|
and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||||
|
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
PERFORMANCE OF THIS SOFTWARE.
|
99
Makefile
99
Makefile
|
@ -1,7 +1,8 @@
|
||||||
prefix=/usr/local
|
prefix?=/usr/local
|
||||||
sbindir=$(prefix)/sbin
|
sbindir=$(prefix)/sbin
|
||||||
datadir=$(prefix)/share
|
datadir=$(prefix)/share
|
||||||
mandir=$(datadir)/man
|
mandir=$(datadir)/man
|
||||||
|
docdir=$(datadir)/doc
|
||||||
|
|
||||||
DESTDIR=
|
DESTDIR=
|
||||||
|
|
||||||
|
@ -16,23 +17,8 @@ RM_FLAGS=-f
|
||||||
|
|
||||||
TARGETOS = `uname`
|
TARGETOS = `uname`
|
||||||
|
|
||||||
all:
|
all:
|
||||||
@(cd src; $(MAKE) TARGETOS=$(TARGETOS) all)
|
@$(MAKE) -C src 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) $(DESTDIR)$(sbindir)
|
$(MKDIR) $(MKDIR_FLAGS) $(DESTDIR)$(sbindir)
|
||||||
|
@ -43,20 +29,85 @@ install: all
|
||||||
$(MKDIR) $(MKDIR_FLAGS) $(DESTDIR)$(mandir)/man8
|
$(MKDIR) $(MKDIR_FLAGS) $(DESTDIR)$(mandir)/man8
|
||||||
$(INSTALL) $(INSTALL_FLAGS) man/iodine.8 $(DESTDIR)$(mandir)/man8/iodine.8
|
$(INSTALL) $(INSTALL_FLAGS) man/iodine.8 $(DESTDIR)$(mandir)/man8/iodine.8
|
||||||
chmod 644 $(DESTDIR)$(mandir)/man8/iodine.8
|
chmod 644 $(DESTDIR)$(mandir)/man8/iodine.8
|
||||||
|
$(MKDIR) $(MKDIR_FLAGS) $(DESTDIR)$(docdir)/iodine
|
||||||
|
$(INSTALL) $(INSTALL_FLAGS) README.md $(DESTDIR)$(docdir)/iodine/README.md
|
||||||
|
chmod 644 $(DESTDIR)$(docdir)/iodine/README.md
|
||||||
|
|
||||||
uninstall:
|
uninstall:
|
||||||
$(RM) $(RM_FLAGS) $(DESTDIR)$(sbindir)/iodine
|
$(RM) $(RM_FLAGS) $(DESTDIR)$(sbindir)/iodine
|
||||||
$(RM) $(RM_FLAGS) $(DESTDIR)$(sbindir)/iodined
|
$(RM) $(RM_FLAGS) $(DESTDIR)$(sbindir)/iodined
|
||||||
$(RM) $(RM_FLAGS) $(DESTDIR)$(mandir)/man8/iodine.8
|
$(RM) $(RM_FLAGS) $(DESTDIR)$(mandir)/man8/iodine.8
|
||||||
|
|
||||||
test: all
|
test: all
|
||||||
@echo "!! The check library is required for compiling and running the tests"
|
@echo "!! The check library is required for compiling and running the tests"
|
||||||
@echo "!! Get it at http://check.sf.net"
|
@echo "!! Get it at https://libcheck.github.io/check/"
|
||||||
@(cd tests; $(MAKE) TARGETOS=$(TARGETOS) all)
|
@$(MAKE) -C tests TARGETOS=$(TARGETOS) all
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@echo "Cleaning..."
|
@echo "Cleaning..."
|
||||||
@(cd src; $(MAKE) clean)
|
@$(MAKE) -C src clean
|
||||||
@(cd tests; $(MAKE) clean)
|
@$(MAKE) -C tests clean
|
||||||
@rm -rf bin iodine-latest-win32*
|
@rm -rf bin iodine-latest*
|
||||||
|
|
||||||
|
#Helper target for windows/android zipfiles
|
||||||
|
iodine-latest:
|
||||||
|
@rm -rf iodine-latest*
|
||||||
|
@mkdir -p iodine-latest
|
||||||
|
@echo "Create date: " > iodine-latest/VERSION.txt
|
||||||
|
@LANG=en_US date >> iodine-latest/VERSION.txt
|
||||||
|
@echo "Git version: " >> iodine-latest/VERSION.txt
|
||||||
|
@git rev-parse HEAD >> iodine-latest/VERSION.txt
|
||||||
|
@for i in README.md CHANGELOG; do cp $$i iodine-latest/$$i.txt; done
|
||||||
|
@unix2dos iodine-latest/*
|
||||||
|
|
||||||
|
#non-PIE build for old android
|
||||||
|
cross-android-old:
|
||||||
|
@$(MAKE) -C src base64u.c
|
||||||
|
@(cd src && ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=Android.mk APP_PLATFORM=android-3)
|
||||||
|
|
||||||
|
#Position-indepedent build for modern android
|
||||||
|
cross-android:
|
||||||
|
@$(MAKE) -C src base64u.c
|
||||||
|
@(cd src && ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=Android.16.mk APP_PLATFORM=android-16)
|
||||||
|
|
||||||
|
iodine-latest-android.zip: iodine-latest
|
||||||
|
@mv iodine-latest iodine-latest-android
|
||||||
|
@mkdir -p iodine-latest-android/pre-kitkat/armeabi
|
||||||
|
@mkdir -p iodine-latest-android/pre-kitkat/x86
|
||||||
|
@$(MAKE) cross-android-old TARGET_ARCH_ABI=armeabi
|
||||||
|
@cp src/libs/armeabi/* iodine-latest-android/pre-kitkat/armeabi
|
||||||
|
@$(MAKE) cross-android-old TARGET_ARCH_ABI=x86
|
||||||
|
@cp src/libs/x86/* iodine-latest-android/pre-kitkat/x86
|
||||||
|
@rm -rf src/libs src/obj
|
||||||
|
@mkdir -p iodine-latest-android/armeabi
|
||||||
|
@mkdir -p iodine-latest-android/arm64-v8a
|
||||||
|
@mkdir -p iodine-latest-android/x86
|
||||||
|
@$(MAKE) cross-android TARGET_ARCH_ABI=armeabi
|
||||||
|
@cp src/libs/armeabi/* iodine-latest-android/armeabi
|
||||||
|
@$(MAKE) cross-android TARGET_ARCH_ABI=arm64-v8a
|
||||||
|
@cp src/libs/arm64-v8a/* iodine-latest-android/arm64-v8a
|
||||||
|
@$(MAKE) cross-android TARGET_ARCH_ABI=x86
|
||||||
|
@cp src/libs/x86/* iodine-latest-android/x86
|
||||||
|
@cp README-android.txt iodine-latest-android
|
||||||
|
@zip -r iodine-latest-android.zip iodine-latest-android
|
||||||
|
|
||||||
|
cross-mingw32:
|
||||||
|
@$(MAKE) -C src TARGETOS=windows32 CC=i686-w64-mingw32-gcc all
|
||||||
|
|
||||||
|
cross-mingw64:
|
||||||
|
@$(MAKE) -C src TARGETOS=windows32 CC=x86_64-w64-mingw32-gcc all
|
||||||
|
|
||||||
|
iodine-latest-windows.zip: iodine-latest
|
||||||
|
@mv iodine-latest iodine-latest-windows
|
||||||
|
@mkdir -p iodine-latest-windows/64bit iodine-latest-windows/32bit
|
||||||
|
@$(MAKE) -C src TARGETOS=windows32 CC=i686-w64-mingw32-gcc clean all
|
||||||
|
@i686-w64-mingw32-strip bin/iodine*
|
||||||
|
@for i in `ls bin`; do cp bin/$$i iodine-latest-windows/32bit/$$i.exe; done
|
||||||
|
@cp /usr/i686-w64-mingw32/sys-root/mingw/bin/zlib1.dll iodine-latest-windows/32bit
|
||||||
|
@$(MAKE) -C src TARGETOS=windows32 CC=x86_64-w64-mingw32-gcc clean all
|
||||||
|
@x86_64-w64-mingw32-strip bin/iodine*
|
||||||
|
@for i in `ls bin`; do cp bin/$$i iodine-latest-windows/64bit/$$i.exe; done
|
||||||
|
@cp /usr/x86_64-w64-mingw32/sys-root/mingw/bin/zlib1.dll iodine-latest-windows/64bit
|
||||||
|
@cp README-win32.txt iodine-latest-windows
|
||||||
|
@zip -r iodine-latest-windows.zip iodine-latest-windows
|
||||||
|
|
||||||
|
|
357
README
357
README
|
@ -1,357 +0,0 @@
|
||||||
|
|
||||||
iodine - http://code.kryo.se/iodine
|
|
||||||
|
|
||||||
***********************************
|
|
||||||
|
|
||||||
This is a piece of software that lets you tunnel IPv4 data through a DNS
|
|
||||||
server. This can be usable in different situations where internet access is
|
|
||||||
firewalled, but DNS queries are allowed.
|
|
||||||
|
|
||||||
|
|
||||||
QUICKSTART:
|
|
||||||
|
|
||||||
Try it out within your own LAN! Follow these simple steps:
|
|
||||||
- On your server, run: ./iodined -f 10.0.0.1 test.com
|
|
||||||
(If you already use the 10.0.0.0 network, use another internal net like
|
|
||||||
172.16.0.0)
|
|
||||||
- Enter a password
|
|
||||||
- On the client, run: ./iodine -f -r 192.168.0.1 test.com
|
|
||||||
(Replace 192.168.0.1 with your server's ip address)
|
|
||||||
- Enter the same password
|
|
||||||
- Now the client has the tunnel ip 10.0.0.2 and the server has 10.0.0.1
|
|
||||||
- Try pinging each other through the tunnel
|
|
||||||
- Done! :)
|
|
||||||
To actually use it through a relaying nameserver, see below.
|
|
||||||
|
|
||||||
|
|
||||||
HOW TO USE:
|
|
||||||
|
|
||||||
Note: server and client are required to speak the exact same protocol. In most
|
|
||||||
cases, this means running the same iodine version. Unfortunately, implementing
|
|
||||||
backward and forward protocol compatibility is usually not feasible.
|
|
||||||
|
|
||||||
Server side:
|
|
||||||
To use this tunnel, you need control over a real domain (like mydomain.com),
|
|
||||||
and a server with a public IP address to run iodined on. If this server
|
|
||||||
already runs a DNS program, change its listening port and then use iodined's
|
|
||||||
-b option to let iodined forward the DNS requests. (Note that this procedure
|
|
||||||
is not advised in production environments, because iodined's DNS forwarding
|
|
||||||
is not completely transparent.)
|
|
||||||
|
|
||||||
Then, delegate a subdomain (say, t1.mydomain.com) to the iodined server.
|
|
||||||
If you use BIND for your domain, add two lines like these to the zone file:
|
|
||||||
|
|
||||||
t1 IN NS t1ns.mydomain.com. ; note the dot!
|
|
||||||
t1ns IN A 10.15.213.99
|
|
||||||
|
|
||||||
The "NS" line is all that's needed to route queries for the "t1" subdomain
|
|
||||||
to the "t1ns" server. We use a short name for the subdomain, to keep as much
|
|
||||||
space as possible available for the data traffic. At the end of the "NS" line
|
|
||||||
is the name of your iodined server. This can be any name, pointing anywhere,
|
|
||||||
but in this case it's easily kept in the same zone file. It must be a name
|
|
||||||
(not an IP address), and that name itself must have an A record (not a CNAME).
|
|
||||||
|
|
||||||
If your iodined server has a dynamic IP, use a dynamic dns provider. Simply
|
|
||||||
point the "NS" line to it, and leave the "A" line out:
|
|
||||||
|
|
||||||
t1 IN NS myname.mydyndnsprovider.com. ; note the dot!
|
|
||||||
|
|
||||||
Then reload or restart your nameserver program. Now any DNS queries for
|
|
||||||
domains ending in t1.mydomain.com will be sent to your iodined server.
|
|
||||||
|
|
||||||
Finally start iodined on your server. The first argument is the IP address
|
|
||||||
inside the tunnel, which can be from any range that you don't use yet (for
|
|
||||||
example 192.168.99.1), and the second argument is the assigned domain (in this
|
|
||||||
case t1.mydomain.com). Using the -f option will keep iodined running in the
|
|
||||||
foreground, which helps when testing. iodined will open a virtual interface
|
|
||||||
("tun device"), and will also start listening for DNS queries on UDP port 53.
|
|
||||||
Either enter a password on the commandline (-P pass) or after the server has
|
|
||||||
started. Now everything is ready for the client.
|
|
||||||
|
|
||||||
If there is a chance you'll be using an iodine tunnel from unexpected
|
|
||||||
environments, start iodined with a -c option.
|
|
||||||
|
|
||||||
Resulting commandline in this example situation:
|
|
||||||
./iodined -f -c -P secretpassword 192.168.99.1 t1.mydomain.com
|
|
||||||
|
|
||||||
Client side:
|
|
||||||
All the setup is done, just start iodine. It takes one or two arguments, the
|
|
||||||
first is the local relaying DNS server (optional) and the second is the domain
|
|
||||||
you used (t1.mydomain.com). If you don't specify the first argument, the
|
|
||||||
system's current DNS setting will be consulted.
|
|
||||||
|
|
||||||
If DNS queries are allowed to any computer, you can directly give the iodined
|
|
||||||
server's address as first argument (in the example: t1ns.mydomain.com or
|
|
||||||
10.15.213.99). In that case, it may also happen that _any_ traffic is allowed
|
|
||||||
to the DNS port (53 UDP) of any computer. Iodine will detect this, and switch
|
|
||||||
to raw UDP tunneling if possible. To force DNS tunneling in any case, use the
|
|
||||||
-r option (especially useful when testing within your own network).
|
|
||||||
|
|
||||||
The client's tunnel interface will get an IP close to the server's (in this
|
|
||||||
case 192.168.99.2 or .3 etc.) and a suitable MTU. Enter the same password as
|
|
||||||
on the server either as commandline option or after the client has started.
|
|
||||||
Using the -f option will keep the iodine client running in the foreground.
|
|
||||||
|
|
||||||
Resulting commandline in this example situation:
|
|
||||||
./iodine -f -P secretpassword t1.mydomain.com
|
|
||||||
(add -r to force DNS tunneling even if raw UDP tunneling would be possible)
|
|
||||||
|
|
||||||
From either side, you should now be able to ping the IP address on the other
|
|
||||||
end of the tunnel. In this case, ping 192.168.99.1 from the iodine client, and
|
|
||||||
192.168.99.2 or .3 etc. from the iodine server.
|
|
||||||
|
|
||||||
|
|
||||||
MISC. INFO:
|
|
||||||
|
|
||||||
Routing:
|
|
||||||
It is possible to route all traffic through the DNS tunnel. To do this, first
|
|
||||||
add a host route to the nameserver used by iodine over the wired/wireless
|
|
||||||
interface with the default gateway as gateway. Then replace the default
|
|
||||||
gateway with the iodined server's IP address inside the DNS tunnel, and
|
|
||||||
configure the server to do NAT.
|
|
||||||
|
|
||||||
However, note that the tunneled data traffic is not encrypted at all, and can
|
|
||||||
be read and changed by external parties relatively easily. For maximum
|
|
||||||
security, run a VPN through the DNS tunnel (=double tunneling), or use secure
|
|
||||||
shell (SSH) access, possibly with port forwarding. The latter can also be used
|
|
||||||
for web browsing, when you run a web proxy (for example Privoxy) on your
|
|
||||||
server.
|
|
||||||
|
|
||||||
Testing:
|
|
||||||
The iodined server replies to NS requests sent for subdomains of the tunnel
|
|
||||||
domain. If your iodined subdomain is t1.mydomain.com, send a NS request for
|
|
||||||
foo123.t1.mydomain.com to see if the delegation works. dig is a good tool
|
|
||||||
for this:
|
|
||||||
dig -t NS foo123.t1.mydomain.com
|
|
||||||
|
|
||||||
Also, the iodined server will answer requests starting with 'z' for any of the
|
|
||||||
supported request types, for example:
|
|
||||||
dig -t TXT z456.t1.mydomain.com
|
|
||||||
dig -t SRV z456.t1.mydomain.com
|
|
||||||
dig -t CNAME z456.t1.mydomain.com
|
|
||||||
The reply should look like garbled text in all these cases.
|
|
||||||
|
|
||||||
Operational info:
|
|
||||||
The DNS-response fragment size is normally autoprobed to get maximum bandwidth.
|
|
||||||
To force a specific value (and speed things up), use the -m option.
|
|
||||||
|
|
||||||
The DNS hostnames are normally used up to their maximum length, 255 characters.
|
|
||||||
Some DNS relays have been found that answer full-length queries rather
|
|
||||||
unreliably, giving widely varying (and mostly very bad) results of the
|
|
||||||
fragment size autoprobe on repeated tries. In these cases, use the -M switch
|
|
||||||
to reduce the DNS hostname length to for example 200 characters, which makes
|
|
||||||
these DNS relays much more stable. This is also useful on some "de-optimizing"
|
|
||||||
DNS relays that stuff the response with two full copies of the query, leaving
|
|
||||||
very little space for downstream data (also not capable of EDNS0). The -M
|
|
||||||
switch can trade some upstream bandwidth for downstream bandwidth. Note that
|
|
||||||
the minimum -M value is about 100, since the protocol can split packets (1200
|
|
||||||
bytes max) in only 16 fragments, requiring at least 75 real data bytes per
|
|
||||||
fragment.
|
|
||||||
|
|
||||||
The upstream data is sent gzipped encoded with Base32; or Base64 if the relay
|
|
||||||
server supports mixed case and '+' in domain names; or Base64u if '_' is
|
|
||||||
supported instead; or Base128 if high-byte-value characters are supported.
|
|
||||||
This upstream encoding is autodetected. The DNS protocol allows one query per
|
|
||||||
packet, and one query can be max 256 chars. Each domain name part can be max
|
|
||||||
63 chars. So your domain name and subdomain should be as short as possible to
|
|
||||||
allow maximum upstream throughput.
|
|
||||||
|
|
||||||
Several DNS request types are supported, with the NULL type expected to provide
|
|
||||||
the largest downstream bandwidth. Other available types are TXT, SRV, MX,
|
|
||||||
CNAME and A (returning CNAME), in decreasing bandwidth order. Normally the
|
|
||||||
"best" request type is autodetected and used. However, DNS relays may impose
|
|
||||||
limits on for example NULL and TXT, making SRV or MX actually the best choice.
|
|
||||||
This is not autodetected, but can be forced using the -T option. It is
|
|
||||||
advisable to try various alternatives especially when the autodetected request
|
|
||||||
type provides a downstream fragment size of less than 200 bytes.
|
|
||||||
|
|
||||||
Note that SRV, MX and A (returning CNAME) queries may/will cause additional
|
|
||||||
lookups by "smart" caching nameservers to get an actual IP address, which may
|
|
||||||
either slow down or fail completely.
|
|
||||||
|
|
||||||
DNS responses for non-NULL queries can be encoded with the same set of codecs
|
|
||||||
as upstream data. This is normally also autodetected, but no fully exhaustive
|
|
||||||
tests are done, so some problems may not be noticed when selecting more
|
|
||||||
advanced codecs. In that case, you'll see failures/corruption in the fragment
|
|
||||||
size autoprobe. In particular, several DNS relays have been found that change
|
|
||||||
replies returning hostnames (SRV, MX, CNAME, A) to lowercase only when that
|
|
||||||
hostname exceeds ca. 180 characters. In these and similar cases, use the -O
|
|
||||||
option to try other downstream codecs; Base32 should always work.
|
|
||||||
|
|
||||||
Normal operation now is for the server to _not_ answer a DNS request until
|
|
||||||
the next DNS request has come in, a.k.a. being "lazy". This way, the server
|
|
||||||
will always have a DNS request handy when new downstream data has to be sent.
|
|
||||||
This greatly improves (interactive) performance and latency, and allows to
|
|
||||||
slow down the quiescent ping requests to 4 second intervals by default, and
|
|
||||||
possibly much slower. In fact, the main purpose of the pings now is to force
|
|
||||||
a reply to the previous ping, and prevent DNS server timeouts (usually at
|
|
||||||
least 5-10 seconds per RFC1035). Some DNS servers are more impatient and will
|
|
||||||
give SERVFAIL errors (timeouts) in periods without tunneled data traffic. All
|
|
||||||
data should still get through in these cases, but iodine will reduce the ping
|
|
||||||
interval to 1 second anyway (-I1) to reduce the number of error messages. This
|
|
||||||
may not help for very impatient DNS relays like dnsadvantage.com (ultradns),
|
|
||||||
which time out in 1 second or even less. Yet data will still get trough, and
|
|
||||||
you can ignore the SERVFAIL errors.
|
|
||||||
|
|
||||||
If you are running on a local network without any DNS server in-between, try
|
|
||||||
-I 50 (iodine and iodined close the connection after 60 seconds of silence).
|
|
||||||
The only time you'll notice a slowdown, is when DNS reply packets go missing;
|
|
||||||
the iodined server then has to wait for a new ping to re-send the data. You can
|
|
||||||
speed this up by generating some upstream traffic (keypress, ping). If this
|
|
||||||
happens often, check your network for bottlenecks and/or run with -I1.
|
|
||||||
|
|
||||||
The delayed answering in lazy mode will cause some "carrier grade" commercial
|
|
||||||
DNS relays to repeatedly re-send the same DNS query to the iodined server.
|
|
||||||
If the DNS relay is actually implemented as a pool of parallel servers,
|
|
||||||
duplicate requests may even arrive from multiple sources. This effect will
|
|
||||||
only be visible in the network traffic at the iodined server, and will not
|
|
||||||
affect the client's connection. Iodined will notice these duplicates, and send
|
|
||||||
the same answer (when its time has come) to both the original query and the
|
|
||||||
latest duplicate. After that, the full answer is cached for a short while.
|
|
||||||
Delayed duplicates that arrive at the server even later, get a reply that the
|
|
||||||
iodine client will ignore (if it ever arrives there).
|
|
||||||
|
|
||||||
If you have problems, try inspecting the traffic with network monitoring tools
|
|
||||||
like tcpdump or ethereal/wireshark, and make sure that the relaying DNS server
|
|
||||||
has not cached the response. A cached error message could mean that you
|
|
||||||
started the client before the server. The -D (and -DD) option on the server
|
|
||||||
can also show received and sent queries.
|
|
||||||
|
|
||||||
|
|
||||||
TIPS & TRICKS:
|
|
||||||
|
|
||||||
If your port 53 is taken on a specific interface by an application that does
|
|
||||||
not use it, use -p on iodined to specify an alternate port (like -p 5353) and
|
|
||||||
use for instance iptables (on Linux) to forward the traffic:
|
|
||||||
iptables -t nat -A PREROUTING -i eth0 -p udp --dport 53 -j DNAT --to :5353
|
|
||||||
(Sent in by Tom Schouten)
|
|
||||||
|
|
||||||
Iodined will reject data from clients that have not been active (data/pings)
|
|
||||||
for more than 60 seconds. Similarly, iodine will exit when no downstream
|
|
||||||
data has been received for 60 seconds. In case of a long network outage or
|
|
||||||
similar, just restart iodine (re-login), possibly multiple times until you get
|
|
||||||
your old IP address back. Once that's done, just wait a while, and you'll
|
|
||||||
eventually see the tunneled TCP traffic continue to flow from where it left
|
|
||||||
off before the outage.
|
|
||||||
|
|
||||||
With the introduction of the downstream packet queue in the server, its memory
|
|
||||||
usage has increased with several megabytes in the default configuration.
|
|
||||||
For use in low-memory environments (e.g. running on your DSL router), you can
|
|
||||||
decrease USERS and undefine OUTPACKETQ_LEN in user.h without any ill conse-
|
|
||||||
quence, assuming at most one client will be connected at any time. A small
|
|
||||||
DNSCACHE_LEN is still advised, preferably 2 or higher, however you can also
|
|
||||||
undefine it to save a few more kilobytes.
|
|
||||||
|
|
||||||
|
|
||||||
PERFORMANCE:
|
|
||||||
|
|
||||||
This section tabulates some performance measurements. To view properly, use
|
|
||||||
a fixed-width font like Courier.
|
|
||||||
|
|
||||||
Measurements were done in protocol 00000502 in lazy mode; upstream encoding
|
|
||||||
always Base128; iodine -M255; iodined -m1130. Network conditions were not
|
|
||||||
extremely favorable; results are not benchmarks but a realistic indication of
|
|
||||||
real-world performance that can be expected in similar situations.
|
|
||||||
|
|
||||||
Upstream/downstream throughput was measured by scp'ing a file previously
|
|
||||||
read from /dev/urandom (i.e. incompressible), and measuring size with
|
|
||||||
"ls -l ; sleep 30 ; ls -l" on a separate non-tunneled connection. Given the
|
|
||||||
large scp block size of 16 kB, this gives a resolution of 4.3 kbit/s, which
|
|
||||||
explains why some values are exactly equal.
|
|
||||||
Ping round-trip times measured with "ping -c100", presented are average rtt
|
|
||||||
and mean deviation (indicating spread around the average), in milliseconds.
|
|
||||||
|
|
||||||
|
|
||||||
Situation 1:
|
|
||||||
Laptop -> Wifi AP -> Home server -> DSL provider -> Datacenter
|
|
||||||
iodine DNS "relay" bind9 DNS cache iodined
|
|
||||||
|
|
||||||
downstr. upstream downstr. ping-up ping-down
|
|
||||||
fragsize kbit/s kbit/s avg +/-mdev avg +/-mdev
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
iodine -> Wifi AP :53
|
|
||||||
-Tnull (= -Oraw) 982 43.6 131.0 28.0 4.6 26.8 3.4
|
|
||||||
|
|
||||||
iodine -> Home server :53
|
|
||||||
-Tnull (= -Oraw) 1174 48.0 305.8 26.6 5.0 26.9 8.4
|
|
||||||
|
|
||||||
iodine -> DSL provider :53
|
|
||||||
-Tnull (= -Oraw) 1174 56.7 367.0 20.6 3.1 21.2 4.4
|
|
||||||
-Ttxt -Obase32 730 56.7 174.7*
|
|
||||||
-Ttxt -Obase64 874 56.7 174.7
|
|
||||||
-Ttxt -Obase128 1018 56.7 174.7
|
|
||||||
-Ttxt -Oraw 1162 56.7 358.2
|
|
||||||
-Tsrv -Obase128 910 56.7 174.7
|
|
||||||
-Tcname -Obase32 151 56.7 43.6
|
|
||||||
-Tcname -Obase128 212 56.7 52.4
|
|
||||||
|
|
||||||
iodine -> DSL provider :53
|
|
||||||
wired (no Wifi) -Tnull 1174 74.2 585.4 20.2 5.6 19.6 3.4
|
|
||||||
|
|
||||||
[174.7* : these all have 2frag/packet]
|
|
||||||
|
|
||||||
|
|
||||||
Situation 2:
|
|
||||||
Laptop -> Wifi+vpn / wired -> Home server
|
|
||||||
iodine iodined
|
|
||||||
|
|
||||||
downstr. upstream downstr. ping-up ping-down
|
|
||||||
fragsize kbit/s kbit/s avg +/-mdev avg +/-mdev
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
wifi + openvpn -Tnull 1186 166.0 1022.3 6.3 1.3 6.6 1.6
|
|
||||||
|
|
||||||
wired -Tnull 1186 677.2 2464.1 1.3 0.2 1.3 0.1
|
|
||||||
|
|
||||||
|
|
||||||
Performance is strongly coupled to low ping times, as iodine requires
|
|
||||||
confirmation for every data fragment before moving on to the next. Allowing
|
|
||||||
multiple fragments in-flight like TCP could possibly increase performance,
|
|
||||||
but it would likely cause serious overload for the intermediary DNS servers.
|
|
||||||
The current protocol scales performance with DNS responsivity, since the
|
|
||||||
DNS servers are on average handling at most one DNS request per client.
|
|
||||||
|
|
||||||
|
|
||||||
PORTABILITY:
|
|
||||||
|
|
||||||
iodine has been tested on Linux (arm, ia64, x86, AMD64 and SPARC64), FreeBSD
|
|
||||||
(ia64, x86), OpenBSD (x86), NetBSD (x86), MacOS X (ppc and x86, with
|
|
||||||
http://tuntaposx.sourceforge.net/). and Windows (with OpenVPN TAP32 driver, see
|
|
||||||
win32 readme file). It should be easy to port to other unix-like systems that
|
|
||||||
has TUN/TAP tunneling support. Let us know if you get it to run on other
|
|
||||||
platforms.
|
|
||||||
|
|
||||||
|
|
||||||
THE NAME:
|
|
||||||
|
|
||||||
The name iodine was chosen since it starts with IOD (IP Over DNS) and since
|
|
||||||
iodine has atomic number 53, which happens to be the DNS port number.
|
|
||||||
|
|
||||||
|
|
||||||
THANKS:
|
|
||||||
|
|
||||||
- To kuxien for FreeBSD and OS X testing
|
|
||||||
- To poplix for code audit
|
|
||||||
|
|
||||||
|
|
||||||
AUTHORS & LICENSE:
|
|
||||||
|
|
||||||
Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
|
|
||||||
Also major contributions by Anne Bezemer.
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and distribute this software for any purpose
|
|
||||||
with or without fee is hereby granted, provided that the above copyright notice
|
|
||||||
and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
||||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
||||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
||||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
||||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
||||||
PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
|
|
||||||
|
|
||||||
MD5 implementation by L. Peter Deutsch (license and source in src/md5.[ch])
|
|
||||||
Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
|
|
50
README-android.txt
Normal file
50
README-android.txt
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
|
||||||
|
|
||||||
|
iodine - https://code.kryo.se/iodine
|
||||||
|
|
||||||
|
***********************************
|
||||||
|
|
||||||
|
Extra README file for Android
|
||||||
|
|
||||||
|
|
||||||
|
== Running iodine on Android:
|
||||||
|
1. Get root access on your android device
|
||||||
|
|
||||||
|
2. Find/build a compatible tun.ko for your specific Android kernel
|
||||||
|
|
||||||
|
3. Copy tun.ko and the iodine binary to your device:
|
||||||
|
(Almost all devices need the armeabi binary. Only Intel powered
|
||||||
|
ones need the x86 build.)
|
||||||
|
|
||||||
|
adb push tun.ko /data/local/tmp
|
||||||
|
adb push iodine /data/local/tmp
|
||||||
|
adb shell
|
||||||
|
su
|
||||||
|
cd /data/local/tmp
|
||||||
|
chmod 777 iodine
|
||||||
|
|
||||||
|
4. Run iodine (see the man page for parameters)
|
||||||
|
|
||||||
|
./iodine ...
|
||||||
|
|
||||||
|
For more information: http://blog.bokhorst.biz/5123
|
||||||
|
|
||||||
|
== Building iodine for Android:
|
||||||
|
1. Download and install the Android SDK and NDK
|
||||||
|
|
||||||
|
2. Download and unpack the iodine sources
|
||||||
|
|
||||||
|
3. Build:
|
||||||
|
cd src
|
||||||
|
make base64u.h base64u.c
|
||||||
|
ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=Android.16.mk APP_PLATFORM=android-16
|
||||||
|
|
||||||
|
or run "make cross-android" in the iodine root directory.
|
||||||
|
To build for other archs, specify TARGET_ARCH_ABI:
|
||||||
|
"make cross-android TARGET_ARCH_ABI=x86"
|
||||||
|
|
||||||
|
For older android versions (pre-kitkat), build with "make cross-android-old" in the
|
||||||
|
root directory, or manually like above but with APP_PLATFORM=android-3 and with
|
||||||
|
APP_BUILD_SCRIPT=Android.mk
|
||||||
|
|
||||||
|
The iodine binary ends up in src/libs/<arch>/iodine
|
|
@ -1,6 +1,6 @@
|
||||||
|
|
||||||
|
|
||||||
iodine - http://code.kryo.se/iodine
|
iodine - https://code.kryo.se/iodine
|
||||||
|
|
||||||
***********************************
|
***********************************
|
||||||
|
|
||||||
|
@ -8,10 +8,14 @@ Extra README file for Win32 related stuff
|
||||||
|
|
||||||
|
|
||||||
== Running iodine on Windows:
|
== Running iodine on Windows:
|
||||||
1. Install the TAP32 driver
|
|
||||||
http://openvpn.net/index.php/open-source/downloads.html
|
0. After iodine 0.6, you need Windows XP or newer to run.
|
||||||
Choose OpenVPN 2.0.9 Windows Installer, when installing you can
|
|
||||||
select to install only the TAP driver.
|
1. Install the TAP driver
|
||||||
|
https://openvpn.net/index.php/open-source/downloads.html
|
||||||
|
Download the OpenVPN TAP driver (under section Tap-windows)
|
||||||
|
Problems has been reported with the NDIS6 version (9.2x.y), use the
|
||||||
|
NDIS5 version for now if possible.
|
||||||
|
|
||||||
2. Have at least one TAP32 interface installed. There are scripts for adding
|
2. Have at least one TAP32 interface installed. There are scripts for adding
|
||||||
and removing in the OpenVPN bin directory. If you have more than one
|
and removing in the OpenVPN bin directory. If you have more than one
|
||||||
|
@ -43,7 +47,7 @@ Note that the binaries will not get a .exe suffix
|
||||||
|
|
||||||
== Zlib download
|
== Zlib download
|
||||||
You can get zlib for MinGW here (both for native and crosscompile):
|
You can get zlib for MinGW here (both for native and crosscompile):
|
||||||
http://code.kryo.se/iodine/deps/zlib.zip
|
https://code.kryo.se/iodine/deps/zlib.zip
|
||||||
Unzip it in your MinGW directory on Windows or in $ROOT/usr for
|
Unzip it in your MinGW directory on Windows or in $ROOT/usr for
|
||||||
cross-compile.
|
cross-compile.
|
||||||
|
|
||||||
|
|
423
README.md
Normal file
423
README.md
Normal file
|
@ -0,0 +1,423 @@
|
||||||
|
iodine - <https://code.kryo.se/iodine>
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
|
||||||
|
This is a piece of software that lets you tunnel IPv4 data through a DNS
|
||||||
|
server. This can be usable in different situations where internet access is
|
||||||
|
firewalled, but DNS queries are allowed.
|
||||||
|
|
||||||
|
|
||||||
|
COMPILING
|
||||||
|
---------
|
||||||
|
|
||||||
|
Iodine has no configure script. There are two optional features for Linux
|
||||||
|
(SELinux and systemd support) that will be enabled automatically if the
|
||||||
|
relevant header files are found in `/usr/include`.
|
||||||
|
(See script at `./src/osflags`)
|
||||||
|
|
||||||
|
Run `make` to compile the server and client binaries.
|
||||||
|
Run `make install` to copy binaries and manpage to the destination directory.
|
||||||
|
Run `make test` to compile and run the unit tests. (Requires the `check` library)
|
||||||
|
|
||||||
|
|
||||||
|
QUICKSTART
|
||||||
|
----------
|
||||||
|
|
||||||
|
Try it out within your own LAN! Follow these simple steps:
|
||||||
|
- On your server, run: `./iodined -f 10.0.0.1 test.com`.
|
||||||
|
If you already use the `10.0.0.0` network, use another internal net like
|
||||||
|
`172.16.0.0`.
|
||||||
|
- Enter a password.
|
||||||
|
- On the client, run: `./iodine -f -r 192.168.0.1 test.com`.
|
||||||
|
Replace `192.168.0.1` with your server's ip address.
|
||||||
|
- Enter the same password.
|
||||||
|
- Now the client has the tunnel ip `10.0.0.2` and the server has `10.0.0.1`.
|
||||||
|
- Try pinging each other through the tunnel.
|
||||||
|
- Done! :)
|
||||||
|
|
||||||
|
To actually use it through a relaying nameserver, see below.
|
||||||
|
|
||||||
|
|
||||||
|
HOW TO USE
|
||||||
|
----------
|
||||||
|
|
||||||
|
Note: server and client are required to speak the exact same protocol. In most
|
||||||
|
cases, this means running the same iodine version. Unfortunately, implementing
|
||||||
|
backward and forward protocol compatibility is usually not feasible.
|
||||||
|
|
||||||
|
### Server side
|
||||||
|
To use this tunnel, you need control over a real domain (like `mydomain.com`),
|
||||||
|
and a server with a public IP address to run `iodined` on. If this server
|
||||||
|
already runs a DNS program, change its listening port and then use `iodined`'s
|
||||||
|
`-b` option to let `iodined` forward the DNS requests. (Note that this procedure
|
||||||
|
is not advised in production environments, because `iodined`'s DNS forwarding
|
||||||
|
is not completely transparent, for example zone transfers will not work.)
|
||||||
|
Alternatively you can forward the subdomain from your DNS server to `iodined`
|
||||||
|
which must then run on a different port (`-p`).
|
||||||
|
|
||||||
|
Then, delegate a subdomain (say, `t1.mydomain.com`) to the iodined server.
|
||||||
|
If you use BIND for your domain, add two lines like these to the zone file:
|
||||||
|
|
||||||
|
t1 IN NS t1ns.mydomain.com. ; note the dot!
|
||||||
|
t1ns IN A 10.15.213.99
|
||||||
|
|
||||||
|
The `NS` line is all that's needed to route queries for the `t1` subdomain
|
||||||
|
to the `t1ns` server. We use a short name for the subdomain, to keep as much
|
||||||
|
space as possible available for the data traffic. At the end of the `NS` line
|
||||||
|
is the name of your `iodined` server. This can be any name, pointing anywhere,
|
||||||
|
but in this case it's easily kept in the same zone file. It must be a name
|
||||||
|
(not an IP address), and that name itself must have an `A` record
|
||||||
|
(not a `CNAME`).
|
||||||
|
|
||||||
|
If your `iodined` server has a dynamic IP, use a dynamic DNS provider. Simply
|
||||||
|
point the `NS` line to it, and leave the `A` line out:
|
||||||
|
|
||||||
|
t1 IN NS myname.mydyndnsprovider.com. ; note the dot!
|
||||||
|
|
||||||
|
Then reload or restart your nameserver program. Now any DNS queries for
|
||||||
|
domains ending in `t1.mydomain.com` will be sent to your `iodined` server.
|
||||||
|
|
||||||
|
Finally start `iodined` on your server. The first argument is the IP address
|
||||||
|
inside the tunnel, which can be from any range that you don't use yet (for
|
||||||
|
example `192.168.99.1`), and the second argument is the assigned domain (in this
|
||||||
|
case `t1.mydomain.com`). Using the `-f` option will keep iodined running in the
|
||||||
|
foreground, which helps when testing. iodined will open a virtual interface
|
||||||
|
("tun device"), and will also start listening for DNS queries on UDP port 53.
|
||||||
|
Either enter a password on the commandline (`-P pass`) or after the server has
|
||||||
|
started. Now everything is ready for the client.
|
||||||
|
|
||||||
|
If there is a chance you'll be using an iodine tunnel from unexpected
|
||||||
|
environments, start `iodined` with a `-c` option.
|
||||||
|
Resulting commandline in this example situation:
|
||||||
|
|
||||||
|
./iodined -f -c -P secretpassword 192.168.99.1 t1.mydomain.com
|
||||||
|
|
||||||
|
### Client side
|
||||||
|
All the setup is done, just start `iodine`. It takes one or two arguments, the
|
||||||
|
first is the local relaying DNS server (optional) and the second is the domain
|
||||||
|
you used (`t1.mydomain.com`). If you don't specify the first argument, the
|
||||||
|
system's current DNS setting will be consulted.
|
||||||
|
|
||||||
|
If DNS queries are allowed to any computer, you can directly give the `iodined`
|
||||||
|
server's address as first argument (in the example: `t1ns.mydomain.com` or
|
||||||
|
`10.15.213.99`). In that case, it may also happen that _any_ traffic is allowed
|
||||||
|
to the DNS port (53 UDP) of any computer. Iodine will detect this, and switch
|
||||||
|
to raw UDP tunneling if possible. To force DNS tunneling in any case, use the
|
||||||
|
`-r` option (especially useful when testing within your own network).
|
||||||
|
|
||||||
|
The client's tunnel interface will get an IP close to the server's (in this
|
||||||
|
case `192.168.99.2` or `.3` etc.) and a suitable MTU. Enter the same password as
|
||||||
|
on the server either as commandline option or after the client has started.
|
||||||
|
Using the `-f` option will keep the iodine client running in the foreground.
|
||||||
|
|
||||||
|
Resulting commandline in this example situation, adding -r forces DNS tunneling
|
||||||
|
even if raw UDP tunneling would be possible:
|
||||||
|
|
||||||
|
./iodine -f -P secretpassword t1.mydomain.com
|
||||||
|
|
||||||
|
From either side, you should now be able to ping the IP address on the other
|
||||||
|
end of the tunnel. In this case, `ping 192.168.99.1` from the iodine client, and
|
||||||
|
`192.168.99.2` from the iodine server.
|
||||||
|
|
||||||
|
|
||||||
|
### MISC. INFO
|
||||||
|
|
||||||
|
#### IPv6
|
||||||
|
The data inside the tunnel is IPv4 only.
|
||||||
|
|
||||||
|
The server listens to both IPv4 and IPv6 for incoming requests by default.
|
||||||
|
Use options `-4` or `-6` to only listen on one protocol. Raw mode will be
|
||||||
|
attempted on the same protocol as used for the login.
|
||||||
|
|
||||||
|
The client can use IPv4 or IPv6 nameservers to connect to iodined. The relay
|
||||||
|
nameservers will translate between protocols automatically if needed. Use
|
||||||
|
options `-4` or `-6` to force the client to use a specific IP version for its DNS
|
||||||
|
queries.
|
||||||
|
|
||||||
|
If your server is listening on IPv6 and is reachable, add an AAAA record for it
|
||||||
|
to your DNS setup. Extending the example above would look like this:
|
||||||
|
|
||||||
|
t1 IN NS t1ns.mydomain.com. ; note the dot!
|
||||||
|
t1ns IN A 10.15.213.99
|
||||||
|
t1ns IN AAAA 2001:db8::1001:99
|
||||||
|
|
||||||
|
#### Routing
|
||||||
|
It is possible to route all traffic through the DNS tunnel. To do this, first
|
||||||
|
add a host route to the nameserver used by iodine over the wired/wireless
|
||||||
|
interface with the default gateway as gateway. Then replace the default
|
||||||
|
gateway with the iodined server's IP address inside the DNS tunnel, and
|
||||||
|
configure the server to do NAT.
|
||||||
|
|
||||||
|
However, note that the tunneled data traffic is not encrypted at all, and can
|
||||||
|
be read and changed by external parties relatively easily. For maximum
|
||||||
|
security, run a VPN through the DNS tunnel (=double tunneling), or use secure
|
||||||
|
shell (SSH) access, possibly with port forwarding. The latter can also be used
|
||||||
|
for web browsing, when you run a web proxy (for example Privoxy) on your
|
||||||
|
server.
|
||||||
|
|
||||||
|
#### Testing
|
||||||
|
The `iodined` server replies to `NS` requests sent for subdomains of the tunnel
|
||||||
|
domain. If your iodined subdomain is `t1.mydomain.com`, send a `NS` request for
|
||||||
|
`foo123.t1.mydomain.com` to see if the delegation works.
|
||||||
|
`dig` is a good tool for this:
|
||||||
|
|
||||||
|
% dig -t NS foo123.t1.mydomain.com
|
||||||
|
ns.io.citronna.de.
|
||||||
|
|
||||||
|
Also, the iodined server will answer requests starting with 'z' for any of the
|
||||||
|
supported request types, for example:
|
||||||
|
|
||||||
|
dig -t TXT z456.t1.mydomain.com
|
||||||
|
dig -t SRV z456.t1.mydomain.com
|
||||||
|
dig -t CNAME z456.t1.mydomain.com
|
||||||
|
|
||||||
|
The reply should look like garbled text in all these cases.
|
||||||
|
|
||||||
|
#### Mac OS X
|
||||||
|
On Mac OS X 10.6 and later, iodine supports the native utun devices built into
|
||||||
|
the OS - use `-d utunX`.
|
||||||
|
|
||||||
|
|
||||||
|
Operational info
|
||||||
|
----------------
|
||||||
|
|
||||||
|
The DNS-response fragment size is normally autoprobed to get maximum bandwidth.
|
||||||
|
To force a specific value (and speed things up), use the `-m` option.
|
||||||
|
|
||||||
|
The DNS hostnames are normally used up to their maximum length, 255 characters.
|
||||||
|
Some DNS relays have been found that answer full-length queries rather
|
||||||
|
unreliably, giving widely varying (and mostly very bad) results of the
|
||||||
|
fragment size autoprobe on repeated tries. In these cases, use the `-M` switch
|
||||||
|
to reduce the DNS hostname length to, for example 200 characters, which makes
|
||||||
|
these DNS relays much more stable. This is also useful on some “de-optimizing”
|
||||||
|
DNS relays that stuff the response with two full copies of the query, leaving
|
||||||
|
very little space for downstream data (also not capable of EDNS0). The `-M`
|
||||||
|
switch can trade some upstream bandwidth for downstream bandwidth. Note that
|
||||||
|
the minimum `-M` value is about 100, since the protocol can split packets (1200
|
||||||
|
bytes max) in only 16 fragments, requiring at least 75 real data bytes per
|
||||||
|
fragment.
|
||||||
|
|
||||||
|
The upstream data is sent gzipped encoded with Base32; or Base64 if the relay
|
||||||
|
server supports mixed case and `+` in domain names; or Base64u if `_` is
|
||||||
|
supported instead; or Base128 if high-byte-value characters are supported.
|
||||||
|
This upstream encoding is autodetected. The DNS protocol allows one query per
|
||||||
|
packet, and one query can be max 256 chars. Each domain name part can be max
|
||||||
|
63 chars. So your domain name and subdomain should be as short as possible to
|
||||||
|
allow maximum upstream throughput.
|
||||||
|
|
||||||
|
Several DNS request types are supported, with the `NULL` and `PRIVATE` types
|
||||||
|
expected to provide the largest downstream bandwidth. The `PRIVATE` type uses
|
||||||
|
value 65399 in the private-use range. Other available types are `TXT`, `SRV`,
|
||||||
|
`MX`, `CNAME` and `A` (returning `CNAME`), in decreasing bandwidth order.
|
||||||
|
Normally the “best” request type is autodetected and used. However, DNS relays
|
||||||
|
may impose limits on for example NULL and TXT, making SRV or MX actually the best
|
||||||
|
choice. This is not autodetected, but can be forced using the `-T` option.
|
||||||
|
It is advisable to try various alternatives especially when the autodetected
|
||||||
|
request type provides a downstream fragment size of less than 200 bytes.
|
||||||
|
|
||||||
|
Note that `SRV`, `MX` and `A` (returning `CNAME`) queries may/will cause
|
||||||
|
additional lookups by "smart" caching nameservers to get an actual IP address,
|
||||||
|
which may either slow down or fail completely.
|
||||||
|
|
||||||
|
DNS responses for non-`NULL/PRIVATE` queries can be encoded with the same set of
|
||||||
|
codecs as upstream data. This is normally also autodetected, but no fully
|
||||||
|
exhaustive tests are done, so some problems may not be noticed when selecting
|
||||||
|
more advanced codecs. In that case, you'll see failures/corruption in the
|
||||||
|
fragment size autoprobe. In particular, several DNS relays have been found that
|
||||||
|
change replies returning hostnames (`SRV`, `MX`, `CNAME`, `A`) to lowercase only
|
||||||
|
when that hostname exceeds ca. 180 characters. In these and similar cases, use
|
||||||
|
the `-O` option to try other downstream codecs; Base32 should always work.
|
||||||
|
|
||||||
|
Normal operation now is for the server to _not_ answer a DNS request until
|
||||||
|
the next DNS request has come in, a.k.a. being “lazy”. This way, the server
|
||||||
|
will always have a DNS request handy when new downstream data has to be sent.
|
||||||
|
This greatly improves (interactive) performance and latency, and allows to
|
||||||
|
slow down the quiescent ping requests to 4 second intervals by default, and
|
||||||
|
possibly much slower. In fact, the main purpose of the pings now is to force
|
||||||
|
a reply to the previous ping, and prevent DNS server timeouts (usually at
|
||||||
|
least 5-10 seconds per RFC1035). Some DNS servers are more impatient and will
|
||||||
|
give SERVFAIL errors (timeouts) in periods without tunneled data traffic. All
|
||||||
|
data should still get through in these cases, but `iodine` will reduce the ping
|
||||||
|
interval to 1 second anyway (-I1) to reduce the number of error messages. This
|
||||||
|
may not help for very impatient DNS relays like `dnsadvantage.com` (ultradns),
|
||||||
|
which time out in 1 second or even less. Yet data will still get trough, and
|
||||||
|
you can ignore the `SERVFAIL` errors.
|
||||||
|
|
||||||
|
If you are running on a local network without any DNS server in-between, try
|
||||||
|
`-I 50` (iodine and iodined close the connection after 60 seconds of silence).
|
||||||
|
The only time you'll notice a slowdown, is when DNS reply packets go missing;
|
||||||
|
the `iodined` server then has to wait for a new ping to re-send the data. You can
|
||||||
|
speed this up by generating some upstream traffic (keypress, ping). If this
|
||||||
|
happens often, check your network for bottlenecks and/or run with `-I1`.
|
||||||
|
|
||||||
|
The delayed answering in lazy mode will cause some “carrier grade” commercial
|
||||||
|
DNS relays to repeatedly re-send the same DNS query to the iodined server.
|
||||||
|
If the DNS relay is actually implemented as a pool of parallel servers,
|
||||||
|
duplicate requests may even arrive from multiple sources. This effect will
|
||||||
|
only be visible in the network traffic at the `iodined` server, and will not
|
||||||
|
affect the client's connection. Iodined will notice these duplicates, and send
|
||||||
|
the same answer (when its time has come) to both the original query and the
|
||||||
|
latest duplicate. After that, the full answer is cached for a short while.
|
||||||
|
Delayed duplicates that arrive at the server even later, get a reply that the
|
||||||
|
iodine client will ignore (if it ever arrives there).
|
||||||
|
|
||||||
|
If you have problems, try inspecting the traffic with network monitoring tools
|
||||||
|
like tcpdump or ethereal/wireshark, and make sure that the relaying DNS server
|
||||||
|
has not cached the response. A cached error message could mean that you
|
||||||
|
started the client before the server. The `-D` (and `-DD`) option on the server
|
||||||
|
can also show received and sent queries.
|
||||||
|
|
||||||
|
|
||||||
|
TIPS & TRICKS
|
||||||
|
-------------
|
||||||
|
|
||||||
|
If your port 53 is taken on a specific interface by an application that does
|
||||||
|
not use it, use `-p` on iodined to specify an alternate port (like `-p 5353`)
|
||||||
|
and use for instance iptables (on Linux) to forward the traffic:
|
||||||
|
|
||||||
|
iptables -t nat -A PREROUTING -i eth0 -p udp --dport 53 -j DNAT --to :5353
|
||||||
|
|
||||||
|
(Sent in by Tom Schouten)
|
||||||
|
|
||||||
|
Iodined will reject data from clients that have not been active (data/pings)
|
||||||
|
for more than 60 seconds. Similarly, iodine will exit when no downstream
|
||||||
|
data has been received for 60 seconds. In case of a long network outage or
|
||||||
|
similar, just restart iodine (re-login), possibly multiple times until you get
|
||||||
|
your old IP address back. Once that's done, just wait a while, and you'll
|
||||||
|
eventually see the tunneled TCP traffic continue to flow from where it left
|
||||||
|
off before the outage.
|
||||||
|
|
||||||
|
With the introduction of the downstream packet queue in the server, its memory
|
||||||
|
usage has increased with several megabytes in the default configuration.
|
||||||
|
For use in low-memory environments (e.g. running on your DSL router), you can
|
||||||
|
decrease USERS and undefine OUTPACKETQ_LEN in user.h without any ill conse-
|
||||||
|
quence, assuming at most one client will be connected at any time. A small
|
||||||
|
DNSCACHE_LEN is still advised, preferably 2 or higher, however you can also
|
||||||
|
undefine it to save a few more kilobytes.
|
||||||
|
|
||||||
|
One iodine server can handle multiple domains. Set up different NS records
|
||||||
|
on the same domain all pointing to the same host, and use a wildcard
|
||||||
|
at the start of the topdomain argument (example `*.mydomain.com`). iodine
|
||||||
|
will accept tunnel traffic for all domains matching that pattern. The wildcard
|
||||||
|
has to be at the start of the topdomain argument and be followed by a dot.
|
||||||
|
|
||||||
|
|
||||||
|
PERFORMANCE
|
||||||
|
-----------
|
||||||
|
|
||||||
|
This section tabulates some performance measurements. To view properly, use
|
||||||
|
a fixed-width font like Courier.
|
||||||
|
|
||||||
|
Measurements were done in protocol 00000502 in lazy mode; upstream encoding
|
||||||
|
always Base128; `iodine -M255`; `iodined -m1130`. Network conditions were not
|
||||||
|
extremely favorable; results are not benchmarks but a realistic indication of
|
||||||
|
real-world performance that can be expected in similar situations.
|
||||||
|
|
||||||
|
Upstream/downstream throughput was measured by `scp`'ing a file previously
|
||||||
|
read from `/dev/urandom` (i.e. incompressible), and measuring size with
|
||||||
|
`ls -l ; sleep 30 ; ls -l` on a separate non-tunneled connection. Given the
|
||||||
|
large `scp` block size of 16 kB, this gives a resolution of 4.3 kbit/s, which
|
||||||
|
explains why some values are exactly equal.
|
||||||
|
Ping round-trip times measured with `ping -c100`, presented are average rtt
|
||||||
|
and mean deviation (indicating spread around the average), in milliseconds.
|
||||||
|
|
||||||
|
|
||||||
|
### Situation 1: `Laptop -> Wifi AP -> Home server -> DSL provider -> Datacenter`
|
||||||
|
|
||||||
|
iodine DNS "relay" bind9 DNS cache iodined
|
||||||
|
|
||||||
|
downstr. upstream downstr. ping-up ping-down
|
||||||
|
fragsize kbit/s kbit/s avg +/-mdev avg +/-mdev
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
iodine -> Wifi AP :53
|
||||||
|
-Tnull (= -Oraw) 982 43.6 131.0 28.0 4.6 26.8 3.4
|
||||||
|
|
||||||
|
iodine -> Home server :53
|
||||||
|
-Tnull (= -Oraw) 1174 48.0 305.8 26.6 5.0 26.9 8.4
|
||||||
|
|
||||||
|
iodine -> DSL provider :53
|
||||||
|
-Tnull (= -Oraw) 1174 56.7 367.0 20.6 3.1 21.2 4.4
|
||||||
|
-Ttxt -Obase32 730 56.7 174.7*
|
||||||
|
-Ttxt -Obase64 874 56.7 174.7
|
||||||
|
-Ttxt -Obase128 1018 56.7 174.7
|
||||||
|
-Ttxt -Oraw 1162 56.7 358.2
|
||||||
|
-Tsrv -Obase128 910 56.7 174.7
|
||||||
|
-Tcname -Obase32 151 56.7 43.6
|
||||||
|
-Tcname -Obase128 212 56.7 52.4
|
||||||
|
|
||||||
|
iodine -> DSL provider :53
|
||||||
|
wired (no Wifi) -Tnull 1174 74.2 585.4 20.2 5.6 19.6 3.4
|
||||||
|
|
||||||
|
[174.7* : these all have 2frag/packet]
|
||||||
|
|
||||||
|
|
||||||
|
### Situation 2: `Laptop -> Wifi+vpn / wired -> Home server`
|
||||||
|
|
||||||
|
iodine iodined
|
||||||
|
|
||||||
|
downstr. upstream downstr. ping-up ping-down
|
||||||
|
fragsize kbit/s kbit/s avg +/-mdev avg +/-mdev
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
wifi + openvpn -Tnull 1186 166.0 1022.3 6.3 1.3 6.6 1.6
|
||||||
|
|
||||||
|
wired -Tnull 1186 677.2 2464.1 1.3 0.2 1.3 0.1
|
||||||
|
|
||||||
|
|
||||||
|
### Notes
|
||||||
|
|
||||||
|
Performance is strongly coupled to low ping times, as iodine requires
|
||||||
|
confirmation for every data fragment before moving on to the next. Allowing
|
||||||
|
multiple fragments in-flight like TCP could possibly increase performance,
|
||||||
|
but it would likely cause serious overload for the intermediary DNS servers.
|
||||||
|
The current protocol scales performance with DNS responsivity, since the
|
||||||
|
DNS servers are on average handling at most one DNS request per client.
|
||||||
|
|
||||||
|
|
||||||
|
PORTABILITY
|
||||||
|
-----------
|
||||||
|
|
||||||
|
iodine has been tested on Linux (arm, ia64, x86, AMD64 and SPARC64), FreeBSD
|
||||||
|
(ia64, x86), OpenBSD (x86), NetBSD (x86), MacOS X (ppc and x86, with
|
||||||
|
<http://tuntaposx.sourceforge.net/>). and Windows (with OpenVPN TAP32 driver, see
|
||||||
|
win32 readme file). It should be easy to port to other unix-like systems that
|
||||||
|
have TUN/TAP tunneling support. Let us know if you get it to run on other
|
||||||
|
platforms.
|
||||||
|
|
||||||
|
|
||||||
|
THE NAME
|
||||||
|
--------
|
||||||
|
|
||||||
|
The name iodine was chosen since it starts with IOD (IP Over DNS) and since
|
||||||
|
iodine has atomic number 53, which happens to be the DNS port number.
|
||||||
|
|
||||||
|
|
||||||
|
THANKS
|
||||||
|
------
|
||||||
|
|
||||||
|
- To kuxien for FreeBSD and OS X testing
|
||||||
|
- To poplix for code audit
|
||||||
|
|
||||||
|
|
||||||
|
AUTHORS & LICENSE
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>, 2006-2009 Bjorn
|
||||||
|
Andersson <flex@kryo.se>. Also major contributions by Anne Bezemer.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any purpose
|
||||||
|
with or without fee is hereby granted, provided that the above copyright notice
|
||||||
|
and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||||
|
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
|
||||||
|
MD5 implementation by L. Peter Deutsch (license and source in `src/md5.[ch]`)
|
||||||
|
Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
|
12
TODO
12
TODO
|
@ -1,12 +0,0 @@
|
||||||
|
|
||||||
iodine - http://code.kryo.se/iodine
|
|
||||||
|
|
||||||
***********************************
|
|
||||||
|
|
||||||
The TODO list is now located at
|
|
||||||
|
|
||||||
http://dev.kryo.se/iodine/
|
|
||||||
|
|
||||||
The list is under the "View tickets" page
|
|
||||||
|
|
||||||
Feel free to add your own wishes and bug reports
|
|
11
doc/iodine-server.service
Normal file
11
doc/iodine-server.service
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Iodine Server
|
||||||
|
After=local-fs.target network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
EnvironmentFile=-/etc/sysconfig/iodine-server
|
||||||
|
ExecStart=/usr/local/bin/iodined -i 30 -f $OPTIONS
|
||||||
|
StandardOutput=syslog
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
10
doc/iodine-server.socket
Normal file
10
doc/iodine-server.socket
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Iodine socket
|
||||||
|
|
||||||
|
[Socket]
|
||||||
|
ListenDatagram=53
|
||||||
|
ListenDatagram=0.0.0.0:53
|
||||||
|
BindIPv6Only=ipv6-only
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=sockets.target
|
|
@ -38,7 +38,7 @@ Server replies:
|
||||||
VFUL (server has no free slots), followed by max users
|
VFUL (server has no free slots), followed by max users
|
||||||
4 byte value: means login challenge/server protocol version/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
|
1 byte userid of the new user, or any byte if not VACK
|
||||||
|
|
||||||
Login:
|
Login:
|
||||||
Client sends:
|
Client sends:
|
||||||
First byte l or L
|
First byte l or L
|
||||||
|
@ -50,17 +50,19 @@ Server replies:
|
||||||
LNAK means not accepted
|
LNAK means not accepted
|
||||||
x.x.x.x-y.y.y.y-mtu-netmask means accepted (server ip, client ip, mtu, netmask bits)
|
x.x.x.x-y.y.y.y-mtu-netmask means accepted (server ip, client ip, mtu, netmask bits)
|
||||||
|
|
||||||
IP Request:
|
IP Request: (for where to try raw login)
|
||||||
Client sends:
|
Client sends:
|
||||||
First byte i or I
|
First byte i or I
|
||||||
5 bits coded as Base32 char, meaning userid
|
5 bits coded as Base32 char, meaning userid
|
||||||
CMC as 3 Base32 chars
|
CMC as 3 Base32 chars
|
||||||
Server replies
|
Server replies
|
||||||
BADIP if bad userid, or
|
BADIP if bad userid
|
||||||
I and then 4 bytes network order external IP address of iodined server
|
First byte I
|
||||||
|
Then comes external IP address of iodined server
|
||||||
|
as 4 bytes (IPv4) or 16 bytes (IPv6)
|
||||||
|
|
||||||
Upstream codec check / bounce:
|
Upstream codec check / bounce:
|
||||||
Client sends:
|
Client sends:
|
||||||
First byte z or Z
|
First byte z or Z
|
||||||
Lots of data that should not be decoded
|
Lots of data that should not be decoded
|
||||||
Server replies:
|
Server replies:
|
||||||
|
@ -100,7 +102,7 @@ Client sends:
|
||||||
7: Base128 (a-zA-Z0-9\274-\375)
|
7: Base128 (a-zA-Z0-9\274-\375)
|
||||||
CMC as 3 Base32 chars
|
CMC as 3 Base32 chars
|
||||||
Server sends:
|
Server sends:
|
||||||
Name of codec if accepted. After this all upstream data packets must
|
Name of codec if accepted. After this all upstream data packets must
|
||||||
be encoded with the new codec.
|
be encoded with the new codec.
|
||||||
BADCODEC if not accepted. Client must then revert to previous codec
|
BADCODEC if not accepted. Client must then revert to previous codec
|
||||||
BADLEN if length of query is too short
|
BADLEN if length of query is too short
|
||||||
|
@ -122,7 +124,8 @@ Server sends:
|
||||||
s or S: Downstream encoding Base64, for TXT/CNAME/A/MX
|
s or S: Downstream encoding Base64, for TXT/CNAME/A/MX
|
||||||
u or U: Downstream encoding Base64u, for TXT/CNAME/A/MX
|
u or U: Downstream encoding Base64u, for TXT/CNAME/A/MX
|
||||||
v or V: Downstream encoding Base128, for TXT/CNAME/A/MX
|
v or V: Downstream encoding Base128, for TXT/CNAME/A/MX
|
||||||
r or R: Downstream encoding Raw, for TXT/NULL (default for NULL)
|
r or R: Downstream encoding Raw, for PRIVATE/TXT/NULL (default for
|
||||||
|
PRIVATE and NULL)
|
||||||
If codec unsupported for request type, server will use Base32; note
|
If codec unsupported for request type, server will use Base32; note
|
||||||
that server will answer any mix of request types that a client sends.
|
that server will answer any mix of request types that a client sends.
|
||||||
Server may disregard this option; client must always use the downstream
|
Server may disregard this option; client must always use the downstream
|
||||||
|
@ -181,15 +184,15 @@ GGGG = Downstream fragment number
|
||||||
C = Compression enabled for downstream packet
|
C = Compression enabled for downstream packet
|
||||||
UDCMC = Upstream Data CMC, 36 steps a-z0-9, case-insensitive
|
UDCMC = Upstream Data CMC, 36 steps a-z0-9, case-insensitive
|
||||||
|
|
||||||
Upstream data packet starts with 1 byte ASCII hex coded user byte; then 3 bytes
|
Upstream data packet starts with 1 byte ASCII hex coded user byte; then 3 bytes
|
||||||
Base32 encoded header; then 1 char data-CMC; then comes the payload data,
|
Base32 encoded header; then 1 char data-CMC; then comes the payload data,
|
||||||
encoded with the chosen upstream codec.
|
encoded with the chosen upstream codec.
|
||||||
|
|
||||||
Downstream data starts with 2 byte header. Then payload data, which may be
|
Downstream data starts with 2 byte header. Then payload data, which may be
|
||||||
compressed.
|
compressed.
|
||||||
|
|
||||||
In NULL responses, downstream data is always raw. In all other response types,
|
In NULL and PRIVATE responses, downstream data is always raw. In all other
|
||||||
downstream data is encoded (see Options above).
|
response types, downstream data is encoded (see Options above).
|
||||||
Encoding type is indicated by 1 prefix char:
|
Encoding type is indicated by 1 prefix char:
|
||||||
TXT:
|
TXT:
|
||||||
End result is always DNS-chopped (series of len-prefixed strings
|
End result is always DNS-chopped (series of len-prefixed strings
|
||||||
|
@ -224,8 +227,8 @@ always starting with the 2 bytes downstream data header as shown above.
|
||||||
If server has nothing to send, no data is added after the header.
|
If server has nothing to send, no data is added after the header.
|
||||||
If server has something to send, it will add the downstream data packet
|
If server has something to send, it will add the downstream data packet
|
||||||
(or some fragment of it) after the header.
|
(or some fragment of it) after the header.
|
||||||
|
|
||||||
|
|
||||||
"Lazy-mode" operation
|
"Lazy-mode" operation
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
|
@ -249,7 +252,7 @@ downstream data has to be sent.
|
||||||
|
|
||||||
*: upstream data ack is usually done as reply on the previous ping packet,
|
*: upstream data ack is usually done as reply on the previous ping packet,
|
||||||
and the upstream-data packet itself is kept in queue.
|
and the upstream-data packet itself is kept in queue.
|
||||||
|
|
||||||
Client:
|
Client:
|
||||||
Downstream data is acked immediately, to keep it flowing fast (includes a
|
Downstream data is acked immediately, to keep it flowing fast (includes a
|
||||||
ping after last downstream frag).
|
ping after last downstream frag).
|
||||||
|
|
104
man/iodine.8
104
man/iodine.8
|
@ -1,5 +1,5 @@
|
||||||
.\" groff -man -Tascii iodine.8
|
.\" groff -man -Tascii iodine.8
|
||||||
.TH IODINE 8 "DEC 2009" "User Manuals"
|
.TH IODINE 8 "APR 2023" "User Manuals"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
iodine, iodined \- tunnel IPv4 over DNS
|
iodine, iodined \- tunnel IPv4 over DNS
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
|
@ -7,7 +7,7 @@ iodine, iodined \- tunnel IPv4 over DNS
|
||||||
|
|
||||||
.B iodine [-h]
|
.B iodine [-h]
|
||||||
|
|
||||||
.B iodine [-f] [-r] [-u
|
.B iodine [-4] [-6] [-f] [-r] [-u
|
||||||
.I user
|
.I user
|
||||||
.B ] [-P
|
.B ] [-P
|
||||||
.I password
|
.I password
|
||||||
|
@ -17,6 +17,8 @@ iodine, iodined \- tunnel IPv4 over DNS
|
||||||
.I chrootdir
|
.I chrootdir
|
||||||
.B ] [-d
|
.B ] [-d
|
||||||
.I device
|
.I device
|
||||||
|
.B ] [-R
|
||||||
|
.I rdomain
|
||||||
.B ] [-m
|
.B ] [-m
|
||||||
.I fragsize
|
.I fragsize
|
||||||
.B ] [-M
|
.B ] [-M
|
||||||
|
@ -43,7 +45,7 @@ iodine, iodined \- tunnel IPv4 over DNS
|
||||||
|
|
||||||
.B iodined [-h]
|
.B iodined [-h]
|
||||||
|
|
||||||
.B iodined [-c] [-s] [-f] [-D] [-u
|
.B iodined [-4] [-6] [-c] [-s] [-f] [-D] [-u
|
||||||
.I user
|
.I user
|
||||||
.B ] [-t
|
.B ] [-t
|
||||||
.I chrootdir
|
.I chrootdir
|
||||||
|
@ -52,11 +54,17 @@ iodine, iodined \- tunnel IPv4 over DNS
|
||||||
.B ] [-m
|
.B ] [-m
|
||||||
.I mtu
|
.I mtu
|
||||||
.B ] [-l
|
.B ] [-l
|
||||||
.I listen_ip
|
.I listen_ip4
|
||||||
|
.B ] [-L
|
||||||
|
.I listen_ip6
|
||||||
.B ] [-p
|
.B ] [-p
|
||||||
.I port
|
.I port
|
||||||
.B ] [-n
|
.B ] [-n
|
||||||
|
(
|
||||||
|
.B auto
|
||||||
|
|
|
||||||
.I external_ip
|
.I external_ip
|
||||||
|
)
|
||||||
.B ] [-b
|
.B ] [-b
|
||||||
.I dnsport
|
.I dnsport
|
||||||
.B ] [-P
|
.B ] [-P
|
||||||
|
@ -65,6 +73,8 @@ iodine, iodined \- tunnel IPv4 over DNS
|
||||||
.I context
|
.I context
|
||||||
.B ] [-F
|
.B ] [-F
|
||||||
.I pidfile
|
.I pidfile
|
||||||
|
.B ] [-i
|
||||||
|
.I max_idle_time
|
||||||
.B ]
|
.B ]
|
||||||
.I tunnel_ip
|
.I tunnel_ip
|
||||||
.B [
|
.B [
|
||||||
|
@ -73,9 +83,9 @@ iodine, iodined \- tunnel IPv4 over DNS
|
||||||
.I topdomain
|
.I topdomain
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
.B iodine
|
.B iodine
|
||||||
lets you tunnel IPv4 data through a DNS
|
lets you tunnel IPv4 data through a DNS
|
||||||
server. This can be useful in situations where Internet access is firewalled,
|
server. This can be useful in situations where Internet access is firewalled,
|
||||||
but DNS queries are allowed. It needs a TUN/TAP device to operate. The
|
but DNS queries are allowed. It needs a TUN/TAP device to operate. The
|
||||||
bandwidth is asymmetrical,
|
bandwidth is asymmetrical,
|
||||||
with a measured maximum of 680 kbit/s upstream and 2.3 Mbit/s
|
with a measured maximum of 680 kbit/s upstream and 2.3 Mbit/s
|
||||||
downstream in a wired LAN test network.
|
downstream in a wired LAN test network.
|
||||||
|
@ -102,6 +112,12 @@ Print usage info and exit.
|
||||||
.B -f
|
.B -f
|
||||||
Keep running in foreground.
|
Keep running in foreground.
|
||||||
.TP
|
.TP
|
||||||
|
.B -4
|
||||||
|
Force/allow only IPv4 DNS queries
|
||||||
|
.TP
|
||||||
|
.B -6
|
||||||
|
Force/allow only IPv6 DNS queries
|
||||||
|
.TP
|
||||||
.B -u user
|
.B -u user
|
||||||
Drop privileges and run as user 'user' after setting up tunnel.
|
Drop privileges and run as user 'user' after setting up tunnel.
|
||||||
.TP
|
.TP
|
||||||
|
@ -110,10 +126,11 @@ Chroot to 'chrootdir' after setting up tunnel.
|
||||||
.TP
|
.TP
|
||||||
.B -d device
|
.B -d device
|
||||||
Use the TUN device 'device' instead of the normal one, which is dnsX on Linux
|
Use the TUN device 'device' instead of the normal one, which is dnsX on Linux
|
||||||
and otherwise tunX.
|
and otherwise tunX. On Mac OS X 10.6, this can also be utunX, which will attempt
|
||||||
|
to use an utun device built into the OS.
|
||||||
.TP
|
.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.
|
||||||
.TP
|
.TP
|
||||||
|
@ -129,6 +146,9 @@ Skip raw UDP mode. If not used, iodine will try getting the public IP address
|
||||||
of the iodined host and test if it is reachable directly. If it is, traffic
|
of the iodined host and test if it is reachable directly. If it is, traffic
|
||||||
will be sent to the server instead of the DNS relay.
|
will be sent to the server instead of the DNS relay.
|
||||||
.TP
|
.TP
|
||||||
|
.B -R rdomain
|
||||||
|
Use OpenBSD routing domain 'rdomain' for the DNS connection.
|
||||||
|
.TP
|
||||||
.B -m fragsize
|
.B -m fragsize
|
||||||
Force maximum downstream fragment size. Not setting this will cause the
|
Force maximum downstream fragment size. Not setting this will cause the
|
||||||
client to automatically probe the maximum accepted downstream fragment size.
|
client to automatically probe the maximum accepted downstream fragment size.
|
||||||
|
@ -139,7 +159,7 @@ Usable range ca. 100 to 255.
|
||||||
Use this option to scale back upstream bandwidth in favor of downstream
|
Use this option to scale back upstream bandwidth in favor of downstream
|
||||||
bandwidth.
|
bandwidth.
|
||||||
Also useful for DNS servers that perform unreliably when using full-length
|
Also useful for DNS servers that perform unreliably when using full-length
|
||||||
hostnames, noticable when fragment size autoprobe returns very
|
hostnames, noticeable when fragment size autoprobe returns very
|
||||||
different results each time.
|
different results each time.
|
||||||
.TP
|
.TP
|
||||||
.B -T dnstype
|
.B -T dnstype
|
||||||
|
@ -152,6 +172,7 @@ more bandwidth.
|
||||||
In that case, use this option to override the autodetection.
|
In that case, use this option to override the autodetection.
|
||||||
In (expected) decreasing bandwidth order, the supported DNS request types are:
|
In (expected) decreasing bandwidth order, the supported DNS request types are:
|
||||||
.IR NULL ,
|
.IR NULL ,
|
||||||
|
.IR PRIVATE ,
|
||||||
.IR TXT ,
|
.IR TXT ,
|
||||||
.IR SRV ,
|
.IR SRV ,
|
||||||
.IR MX ,
|
.IR MX ,
|
||||||
|
@ -166,7 +187,10 @@ and
|
||||||
.I A
|
.I A
|
||||||
may/will cause additional lookups by "smart" caching
|
may/will cause additional lookups by "smart" caching
|
||||||
nameservers to get an actual IP address, which may either slow down or fail
|
nameservers to get an actual IP address, which may either slow down or fail
|
||||||
completely.
|
completely. The
|
||||||
|
.IR PRIVATE
|
||||||
|
type uses value 65399 (in the 'private use' range) and requires servers
|
||||||
|
implementing RFC 3597.
|
||||||
.TP
|
.TP
|
||||||
.B -O downenc
|
.B -O downenc
|
||||||
Force downstream encoding type for all query type responses except NULL.
|
Force downstream encoding type for all query type responses except NULL.
|
||||||
|
@ -218,12 +242,12 @@ connection after 60 seconds of inactivity.
|
||||||
.TP
|
.TP
|
||||||
.B -c
|
.B -c
|
||||||
Disable checking the client IP address on all incoming requests.
|
Disable checking the client IP address on all incoming requests.
|
||||||
By default, requests originating from non-matching IP adresses will be
|
By default, requests originating from non-matching IP addresses will be
|
||||||
rejected, however this will cause problems when requests are routed
|
rejected, however this will cause problems when requests are routed
|
||||||
via a cluster of DNS servers.
|
via a cluster of DNS servers.
|
||||||
.TP
|
.TP
|
||||||
.B -s
|
.B -s
|
||||||
Don't try to configure IP address or MTU.
|
Don't try to configure IP address or MTU.
|
||||||
This should only be used if you have already configured the device that will be
|
This should only be used if you have already configured the device that will be
|
||||||
used.
|
used.
|
||||||
.TP
|
.TP
|
||||||
|
@ -232,51 +256,69 @@ Increase debug level. Level 1 prints info about each RX/TX packet.
|
||||||
Implies the
|
Implies the
|
||||||
.B -f
|
.B -f
|
||||||
option.
|
option.
|
||||||
On level 2 (-DD) or higher, DNS queries will be printed literally.
|
On level 2 (\-DD) or higher, DNS queries will be printed literally.
|
||||||
When using Base128 upstream encoding, this is best viewed as
|
When using Base128 upstream encoding, this is best viewed as
|
||||||
ISO Latin-1 text instead of (illegal) UTF-8.
|
ISO Latin-1 text instead of (illegal) UTF-8.
|
||||||
This is easily done with : "LC_ALL=C luit iodined -DD ..."
|
This is easily done with : "LC_ALL=C luit iodined \-DD ..."
|
||||||
(see luit(1)).
|
(see luit(1)).
|
||||||
.TP
|
.TP
|
||||||
.B -m mtu
|
.B -m mtu
|
||||||
Set 'mtu' as mtu size for the tun device.
|
Set 'mtu' as mtu size for the tun device.
|
||||||
This will be sent to the client on login, and the client will use the same mtu
|
This will be sent to the client on login, and the client will use the same mtu
|
||||||
for its tun device. Default 1130. Note that the DNS traffic will be
|
for its tun device. Default 1130. Note that the DNS traffic will be
|
||||||
automatically fragmented when needed.
|
automatically fragmented when needed.
|
||||||
.TP
|
.TP
|
||||||
.B -l listen_ip
|
.B -l external|listen_ip4
|
||||||
Make the server listen only on 'listen_ip' for incoming requests.
|
Make the server listen only on 'listen_ip4' for incoming IPv4 requests.
|
||||||
By default, incoming requests are accepted from all interfaces.
|
By default, incoming requests are accepted from all interfaces (0.0.0.0).
|
||||||
|
A domain name can be used as argument - use one with only one A record.
|
||||||
|
If listen_ip4 is 'external', iodined will use the opendns.com DNS service to
|
||||||
|
retrieve the external IP of the host and use that as listen address.
|
||||||
|
.TP
|
||||||
|
.B -L listen_ip6
|
||||||
|
Make the server listen only on 'listen_ip6' for incoming IPv6 requests.
|
||||||
|
By default, incoming requests are accepted from all interfaces (::).
|
||||||
|
A domain name can be used as argument - use one with only one AAAA record.
|
||||||
.TP
|
.TP
|
||||||
.B -p port
|
.B -p port
|
||||||
Make the server listen on 'port' instead of 53 for traffic.
|
Make the server listen on 'port' instead of 53 for traffic.
|
||||||
|
If 'listen_ip4' does not include localhost, this 'port' can be the same
|
||||||
|
as 'dnsport'.
|
||||||
.B Note:
|
.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
|
.TP
|
||||||
.B -n external_ip
|
.B -n auto|external_ip
|
||||||
The IP address to return in NS responses. Default is to return the address used
|
The IP address to return in NS responses. Default is to return the address used
|
||||||
as destination in the query.
|
as destination in the query.
|
||||||
|
If external_ip is 'auto', iodined will use the opendns.com DNS service to
|
||||||
|
retrieve the external IP of the host and use that for NS responses.
|
||||||
.TP
|
.TP
|
||||||
.B -b dnsport
|
.B -b dnsport
|
||||||
If this port is specified, all incoming requests not inside the tunnel domain
|
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.
|
will be forwarded to this port on localhost, to be handled by a real dns.
|
||||||
|
If 'listen_ip' does not include localhost, this 'dnsport' can be the
|
||||||
|
same as 'port'.
|
||||||
.B Note:
|
.B Note:
|
||||||
The forwarding is not fully transparent, and not advised for use
|
The forwarding is not fully transparent, and not advised for use
|
||||||
in production environments.
|
in production environments.
|
||||||
|
.TP
|
||||||
|
.B -i max_idle_time
|
||||||
|
Make the server stop itself after max_idle_time seconds if no traffic have been received.
|
||||||
|
This should be combined with systemd or upstart on demand activation for being effective.
|
||||||
.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 server running iodined if reachable. This field can be
|
nameserver or the server running iodined if reachable. This field can be
|
||||||
given as an IP address, or as a hostname. This argument is optional, and
|
given as an IPv4/IPv6 address or as a hostname. This argument is optional,
|
||||||
if not specified a nameserver will be read from the
|
and if not specified a nameserver will be read from the
|
||||||
.I /etc/resolv.conf
|
.I /etc/resolv.conf
|
||||||
file.
|
file.
|
||||||
.TP
|
.TP
|
||||||
.B topdomain
|
.B topdomain
|
||||||
The dns traffic will be sent as queries for subdomains under
|
The dns traffic will be sent as queries for subdomains under
|
||||||
\'topdomain'. This is normally a subdomain to a domain you own. Use a short
|
\'topdomain'. This is normally a subdomain to a domain you own. Use a short
|
||||||
domain name to get better throughput. If
|
domain name to get better throughput. If
|
||||||
.B nameserver
|
.B nameserver
|
||||||
is the iodined server, then the topdomain can be chosen freely. This argument
|
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.
|
||||||
|
@ -284,18 +326,19 @@ must be the same on both the client and the server.
|
||||||
.TP
|
.TP
|
||||||
.B tunnel_ip[/netmask]
|
.B tunnel_ip[/netmask]
|
||||||
This is the server's ip address on the tun interface. The client will be
|
This is the server's ip address on the tun interface. The client will be
|
||||||
given the next ip number in the range. It is recommended to use the
|
given the next ip number in the range. It is recommended to use the
|
||||||
10.0.0.0 or 172.16.0.0 ranges. The default netmask is /27, can be overriden
|
10.0.0.0 or 172.16.0.0 ranges. The default netmask is /27, can be overridden
|
||||||
by specifying it here. Using a smaller network will limit the number of
|
by specifying it here. Using a smaller network will limit the number of
|
||||||
concurrent users.
|
concurrent users.
|
||||||
.TP
|
.TP
|
||||||
.B topdomain
|
.B topdomain
|
||||||
The dns traffic is expected to arrive as queries for
|
The dns traffic is expected to arrive as queries for
|
||||||
subdomains under 'topdomain'. This is normally a subdomain to a domain you
|
subdomains under 'topdomain'. This is normally a subdomain to a domain you
|
||||||
own. Use a short domain name to get better throughput. This argument must be
|
own. Use a short domain name to get better throughput. This argument must be
|
||||||
the same on both the client and the server. Queries for domains other
|
the same on both the client and the server. Queries for domains other
|
||||||
than 'topdomain' will be forwarded when the \-b option is given, otherwise
|
than 'topdomain' will be forwarded when the \-b option is given, otherwise
|
||||||
they will be dropped.
|
they will be dropped. The topdomain can start with '*' which will allow all
|
||||||
|
domains ending with the same suffix.
|
||||||
.SH EXAMPLES
|
.SH EXAMPLES
|
||||||
See the README file for both a quick test scenario, and a detailed description
|
See the README file for both a quick test scenario, and a detailed description
|
||||||
of real-world deployment.
|
of real-world deployment.
|
||||||
|
@ -317,7 +360,7 @@ except to the used ssh or vpn ports.
|
||||||
If the environment variable
|
If the environment variable
|
||||||
.B IODINE_PASS
|
.B IODINE_PASS
|
||||||
is set, iodine will use the value it is set to as password instead of asking
|
is set, iodine will use the value it is set to as password instead of asking
|
||||||
for one. The
|
for one. The
|
||||||
.B -P
|
.B -P
|
||||||
option still has precedence.
|
option still has precedence.
|
||||||
.SS IODINED_PASS
|
.SS IODINED_PASS
|
||||||
|
@ -327,12 +370,11 @@ is set, iodined will use the value it is set to as password instead of asking
|
||||||
for one. The
|
for one. The
|
||||||
.B -P
|
.B -P
|
||||||
option still has precedence.
|
option still has precedence.
|
||||||
.El
|
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
The README file in the source distribution contains some more elaborate
|
The README file in the source distribution contains some more elaborate
|
||||||
information.
|
information.
|
||||||
.SH BUGS
|
.SH BUGS
|
||||||
File bugs at http://dev.kryo.se/iodine/
|
File bugs at https://github.com/yarrick/iodine
|
||||||
.SH AUTHORS
|
.SH AUTHORS
|
||||||
Erik Ekman <yarrick@kryo.se> and Bjorn Andersson <flex@kryo.se>. Major
|
Erik Ekman <yarrick@kryo.se> and Bjorn Andersson <flex@kryo.se>. Major
|
||||||
contributions by Anne Bezemer.
|
contributions by Anne Bezemer.
|
||||||
|
|
26
src/Android.16.mk
Normal file
26
src/Android.16.mk
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#
|
||||||
|
# iodine for Android
|
||||||
|
#
|
||||||
|
# by Marcel Bokhorst
|
||||||
|
# http://blog.bokhorst.biz/5123/computers-en-internet/iodine-for-android/
|
||||||
|
#
|
||||||
|
# cd iodine-0.6.0-rc1/src
|
||||||
|
# make base64u.h base64u.c
|
||||||
|
# .../ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=Android.mk
|
||||||
|
#
|
||||||
|
|
||||||
|
LOCAL_PATH:= $(call my-dir)
|
||||||
|
|
||||||
|
HEAD_COMMIT = `git rev-parse --short HEAD`
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_MODULE := iodine
|
||||||
|
LOCAL_SRC_FILES := tun.c dns.c read.c encoding.c login.c base32.c base64.c base64u.c base128.c md5.c common.c iodine.c client.c util.c
|
||||||
|
LOCAL_CFLAGS := -c -DANDROID -DLINUX -DIFCONFIGPATH=\"/system/bin/\" -Wall -DGITREVISION=\"$(HEAD_COMMIT)\"
|
||||||
|
LOCAL_LDLIBS := -lz
|
||||||
|
LOCAL_CFLAGS += -fPIE
|
||||||
|
LOCAL_LDFLAGS += -fPIE -pie
|
||||||
|
|
||||||
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
24
src/Android.mk
Normal file
24
src/Android.mk
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#
|
||||||
|
# iodine for Android
|
||||||
|
#
|
||||||
|
# by Marcel Bokhorst
|
||||||
|
# http://blog.bokhorst.biz/5123/computers-en-internet/iodine-for-android/
|
||||||
|
#
|
||||||
|
# cd iodine-0.6.0-rc1/src
|
||||||
|
# make base64u.h base64u.c
|
||||||
|
# .../ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=Android.mk
|
||||||
|
#
|
||||||
|
|
||||||
|
LOCAL_PATH:= $(call my-dir)
|
||||||
|
|
||||||
|
HEAD_COMMIT = `git rev-parse --short HEAD`
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_MODULE := iodine
|
||||||
|
LOCAL_SRC_FILES := tun.c dns.c read.c encoding.c login.c base32.c base64.c base64u.c base128.c md5.c common.c iodine.c client.c util.c
|
||||||
|
LOCAL_CFLAGS := -c -DANDROID -DLINUX -DIFCONFIGPATH=\"/system/bin/\" -Wall -DGITREVISION=\"$(HEAD_COMMIT)\"
|
||||||
|
LOCAL_LDLIBS := -lz
|
||||||
|
|
||||||
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
12
src/Makefile
12
src/Makefile
|
@ -6,10 +6,12 @@ SERVER = ../bin/iodined
|
||||||
|
|
||||||
OS = `echo $(TARGETOS) | tr "a-z" "A-Z"`
|
OS = `echo $(TARGETOS) | tr "a-z" "A-Z"`
|
||||||
ARCH = `uname -m`
|
ARCH = `uname -m`
|
||||||
|
HEAD_COMMIT = `git rev-parse --short HEAD`
|
||||||
|
|
||||||
LIBPATH = -L.
|
LIBPATH = -L.
|
||||||
LDFLAGS += -lz `sh osflags $(TARGETOS) link` $(LIBPATH)
|
LDFLAGS += -lz `sh osflags $(TARGETOS) link` $(LIBPATH)
|
||||||
CFLAGS += -c -g -Wall -D$(OS) -pedantic `sh osflags $(TARGETOS) cflags`
|
CFLAGS += -std=c99 -c -g -Wall -D$(OS) -pedantic `sh osflags $(TARGETOS) cflags` -DGITREVISION=\"$(HEAD_COMMIT)\"
|
||||||
|
CFLAGS += -Wstrict-prototypes -Wtype-limits -Wmissing-declarations -Wmissing-prototypes
|
||||||
|
|
||||||
all: stateos $(CLIENT) $(SERVER)
|
all: stateos $(CLIENT) $(SERVER)
|
||||||
|
|
||||||
|
@ -26,21 +28,17 @@ $(SERVER): $(COMMONOBJS) $(SERVEROBJS)
|
||||||
@mkdir -p ../bin
|
@mkdir -p ../bin
|
||||||
@$(CC) $(COMMONOBJS) $(SERVEROBJS) -o $(SERVER) $(LDFLAGS)
|
@$(CC) $(COMMONOBJS) $(SERVEROBJS) -o $(SERVER) $(LDFLAGS)
|
||||||
|
|
||||||
.c.o:
|
.c.o:
|
||||||
@echo CC $<
|
@echo CC $<
|
||||||
@$(CC) $(CFLAGS) $< -o $@
|
@$(CC) $(CFLAGS) $< -o $@
|
||||||
|
|
||||||
base64u.o client.o iodined.o: base64u.h
|
|
||||||
base64u.c: base64.c
|
base64u.c: base64.c
|
||||||
@echo Making $@
|
@echo Making $@
|
||||||
@echo '/* No use in editing, produced by Makefile! */' > $@
|
@echo '/* No use in editing, produced by Makefile! */' > $@
|
||||||
@sed -e 's/\([Bb][Aa][Ss][Ee]64\)/\1u/g ; s/0123456789+/0123456789_/' < base64.c >> $@
|
@sed -e 's/\([Bb][Aa][Ss][Ee]64\)/\1u/g ; s/0123456789+/0123456789_/' < base64.c >> $@
|
||||||
base64u.h: base64.h
|
|
||||||
@echo Making $@
|
|
||||||
@echo '/* No use in editing, produced by Makefile! */' > $@
|
|
||||||
@sed -e 's/\([Bb][Aa][Ss][Ee]64\)/\1u/g ; s/0123456789+/0123456789_/' < base64.h >> $@
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@echo "Cleaning src/"
|
@echo "Cleaning src/"
|
||||||
@rm -f $(CLIENT){,.exe} $(SERVER){,.exe} *~ *.o *.core base64u.*
|
@rm -f $(CLIENT){,.exe} $(SERVER){,.exe} *~ *.o *.core base64u.*
|
||||||
|
@rm -rf obj libs #android stuff
|
||||||
|
|
||||||
|
|
59
src/android_dns.h
Normal file
59
src/android_dns.h
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2009 Marcel Bokhorst <marcel@bokhorst.biz>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __FIX_ANDROID_H__
|
||||||
|
#define __FIX_ANDROID_H__
|
||||||
|
|
||||||
|
/* Newer android platforms can have this data already */
|
||||||
|
#ifndef C_IN
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned id :16;
|
||||||
|
unsigned rd :1;
|
||||||
|
unsigned tc :1;
|
||||||
|
unsigned aa :1;
|
||||||
|
unsigned opcode :4;
|
||||||
|
unsigned qr :1;
|
||||||
|
unsigned rcode :4;
|
||||||
|
unsigned cd: 1;
|
||||||
|
unsigned ad: 1;
|
||||||
|
unsigned unused :1;
|
||||||
|
unsigned ra :1;
|
||||||
|
unsigned qdcount :16;
|
||||||
|
unsigned ancount :16;
|
||||||
|
unsigned nscount :16;
|
||||||
|
unsigned arcount :16;
|
||||||
|
} HEADER;
|
||||||
|
|
||||||
|
#define NOERROR 0
|
||||||
|
#define FORMERR 1
|
||||||
|
#define SERVFAIL 2
|
||||||
|
#define NXDOMAIN 3
|
||||||
|
#define NOTIMP 4
|
||||||
|
#define REFUSED 5
|
||||||
|
|
||||||
|
#define C_IN 1
|
||||||
|
|
||||||
|
#define T_A 1
|
||||||
|
#define T_CNAME 5
|
||||||
|
#define T_NULL 10
|
||||||
|
#define T_MX 15
|
||||||
|
#define T_TXT 16
|
||||||
|
#define T_SRV 33
|
||||||
|
|
||||||
|
#endif /* !C_IN */
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2009 J.A.Bezemer@opensourcepartners.nl
|
* Copyright (C) 2009 J.A.Bezemer@opensourcepartners.nl
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
* copyright notice and this permission notice appear in all copies.
|
* copyright notice and this permission notice appear in all copies.
|
||||||
*
|
*
|
||||||
|
@ -33,16 +33,15 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "encoding.h"
|
#include "encoding.h"
|
||||||
#include "base128.h"
|
|
||||||
|
|
||||||
#define BLKSIZE_RAW 7
|
#define BASE128_BLKSIZE_RAW 7
|
||||||
#define BLKSIZE_ENC 8
|
#define BASE128_BLKSIZE_ENC 8
|
||||||
|
|
||||||
/* Don't use '-' (restricted to middle of labels), prefer iso_8859-1
|
/* Don't use '-' (restricted to middle of labels), prefer iso_8859-1
|
||||||
* accent chars since they might readily be entered in normal use,
|
* accent chars since they might readily be entered in normal use,
|
||||||
* don't use 254-255 because of possible function overloading in DNS systems.
|
* don't use 254-255 because of possible function overloading in DNS systems.
|
||||||
*/
|
*/
|
||||||
static const unsigned char cb128[] =
|
static const unsigned char cb128[] =
|
||||||
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||||
"\274\275\276\277"
|
"\274\275\276\277"
|
||||||
"\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"
|
"\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"
|
||||||
|
@ -52,55 +51,13 @@ static const unsigned char cb128[] =
|
||||||
static unsigned char rev128[256];
|
static unsigned char rev128[256];
|
||||||
static int reverse_init = 0;
|
static int reverse_init = 0;
|
||||||
|
|
||||||
static int base128_encode(char *, size_t *, const void *, size_t);
|
inline static void base128_reverse_init(void)
|
||||||
static int base128_decode(void *, size_t *, const char *, size_t);
|
|
||||||
static int base128_handles_dots();
|
|
||||||
static int base128_blksize_raw();
|
|
||||||
static int base128_blksize_enc();
|
|
||||||
|
|
||||||
static struct encoder base128_encoder =
|
|
||||||
{
|
|
||||||
"Base128",
|
|
||||||
base128_encode,
|
|
||||||
base128_decode,
|
|
||||||
base128_handles_dots,
|
|
||||||
base128_handles_dots,
|
|
||||||
base128_blksize_raw,
|
|
||||||
base128_blksize_enc
|
|
||||||
};
|
|
||||||
|
|
||||||
struct encoder
|
|
||||||
*get_base128_encoder()
|
|
||||||
{
|
|
||||||
return &base128_encoder;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
base128_handles_dots()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
base128_blksize_raw()
|
|
||||||
{
|
|
||||||
return BLKSIZE_RAW;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
base128_blksize_enc()
|
|
||||||
{
|
|
||||||
return BLKSIZE_ENC;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static void
|
|
||||||
base128_reverse_init()
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
unsigned char c;
|
unsigned char c;
|
||||||
|
|
||||||
if (!reverse_init) {
|
if (!reverse_init) {
|
||||||
memset (rev128, 0, 256);
|
memset(rev128, 0, 256);
|
||||||
for (i = 0; i < 128; i++) {
|
for (i = 0; i < 128; i++) {
|
||||||
c = cb128[i];
|
c = cb128[i];
|
||||||
rev128[(int) c] = i;
|
rev128[(int) c] = i;
|
||||||
|
@ -109,8 +66,6 @@ base128_reverse_init()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
base128_encode(char *buf, size_t *buflen, const void *data, size_t size)
|
|
||||||
/*
|
/*
|
||||||
* Fills *buf with max. *buflen characters, encoding size bytes of *data.
|
* Fills *buf with max. *buflen characters, encoding size bytes of *data.
|
||||||
*
|
*
|
||||||
|
@ -120,6 +75,8 @@ base128_encode(char *buf, size_t *buflen, const void *data, size_t size)
|
||||||
* return value : #bytes filled in buf (excluding \0)
|
* return value : #bytes filled in buf (excluding \0)
|
||||||
* sets *buflen to : #bytes encoded from data
|
* sets *buflen to : #bytes encoded from data
|
||||||
*/
|
*/
|
||||||
|
static int base128_encode(char *buf, size_t *buflen, const void *data,
|
||||||
|
size_t size)
|
||||||
{
|
{
|
||||||
unsigned char *ubuf = (unsigned char *) buf;
|
unsigned char *ubuf = (unsigned char *) buf;
|
||||||
unsigned char *udata = (unsigned char *) data;
|
unsigned char *udata = (unsigned char *) data;
|
||||||
|
@ -203,8 +160,6 @@ base128_encode(char *buf, size_t *buflen, const void *data, size_t size)
|
||||||
|
|
||||||
#define REV128(x) rev128[(int) (x)]
|
#define REV128(x) rev128[(int) (x)]
|
||||||
|
|
||||||
static int
|
|
||||||
base128_decode(void *buf, size_t *buflen, const char *str, size_t slen)
|
|
||||||
/*
|
/*
|
||||||
* Fills *buf with max. *buflen bytes, decoded from slen chars in *str.
|
* Fills *buf with max. *buflen bytes, decoded from slen chars in *str.
|
||||||
* Decoding stops early when *str contains \0.
|
* Decoding stops early when *str contains \0.
|
||||||
|
@ -216,13 +171,15 @@ base128_decode(void *buf, size_t *buflen, const char *str, size_t slen)
|
||||||
*
|
*
|
||||||
* return value : #bytes filled in buf (excluding \0)
|
* return value : #bytes filled in buf (excluding \0)
|
||||||
*/
|
*/
|
||||||
|
static int base128_decode(void *buf, size_t *buflen, const char *str,
|
||||||
|
size_t slen)
|
||||||
{
|
{
|
||||||
unsigned char *ustr = (unsigned char *) str;
|
unsigned char *ustr = (unsigned char *) str;
|
||||||
unsigned char *ubuf = (unsigned char *) buf;
|
unsigned char *ubuf = (unsigned char *) buf;
|
||||||
int iout = 0; /* to-be-filled output byte */
|
int iout = 0; /* to-be-filled output byte */
|
||||||
int iin = 0; /* next input char to use in decoding */
|
int iin = 0; /* next input char to use in decoding */
|
||||||
|
|
||||||
base128_reverse_init ();
|
base128_reverse_init();
|
||||||
|
|
||||||
/* Note: Don't bother to optimize manually. GCC optimizes
|
/* Note: Don't bother to optimize manually. GCC optimizes
|
||||||
better(!) when using simplistic array indexing. */
|
better(!) when using simplistic array indexing. */
|
||||||
|
@ -231,7 +188,7 @@ base128_decode(void *buf, size_t *buflen, const char *str, size_t slen)
|
||||||
if (iout >= *buflen || iin + 1 >= slen ||
|
if (iout >= *buflen || iin + 1 >= slen ||
|
||||||
str[iin] == '\0' || str[iin + 1] == '\0')
|
str[iin] == '\0' || str[iin + 1] == '\0')
|
||||||
break;
|
break;
|
||||||
ubuf[iout] = ((REV128(ustr[iin]) & 0x7f) << 1) |
|
ubuf[iout] = ((REV128(ustr[iin]) & 0x7f) << 1) |
|
||||||
((REV128(ustr[iin + 1]) & 0x40) >> 6);
|
((REV128(ustr[iin + 1]) & 0x40) >> 6);
|
||||||
iin++; /* 0 used up, iin=1 */
|
iin++; /* 0 used up, iin=1 */
|
||||||
iout++;
|
iout++;
|
||||||
|
@ -289,3 +246,16 @@ base128_decode(void *buf, size_t *buflen, const char *str, size_t slen)
|
||||||
|
|
||||||
return iout;
|
return iout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const struct encoder base128_ops = {
|
||||||
|
.name = "Base128",
|
||||||
|
|
||||||
|
.encode = base128_encode,
|
||||||
|
.decode = base128_decode,
|
||||||
|
|
||||||
|
.places_dots = false,
|
||||||
|
.eats_dots = false,
|
||||||
|
|
||||||
|
.blocksize_raw = BASE128_BLKSIZE_RAW,
|
||||||
|
.blocksize_encoded = BASE128_BLKSIZE_ENC,
|
||||||
|
};
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2009 J.A.Bezemer@opensourcepartners.nl
|
|
||||||
*
|
|
||||||
* 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 __BASE128_H__
|
|
||||||
#define __BASE128_H__
|
|
||||||
|
|
||||||
struct encoder *get_base128_encoder(void);
|
|
||||||
|
|
||||||
#endif
|
|
94
src/base32.c
94
src/base32.c
|
@ -1,8 +1,9 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
|
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||||
|
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||||
* Mostly rewritten 2009 J.A.Bezemer@opensourcepartners.nl
|
* Mostly rewritten 2009 J.A.Bezemer@opensourcepartners.nl
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
* copyright notice and this permission notice appear in all copies.
|
* copyright notice and this permission notice appear in all copies.
|
||||||
*
|
*
|
||||||
|
@ -20,67 +21,24 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "encoding.h"
|
#include "encoding.h"
|
||||||
#include "base32.h"
|
|
||||||
|
|
||||||
#define BLKSIZE_RAW 5
|
#define BASE32_BLKSIZE_RAW 5
|
||||||
#define BLKSIZE_ENC 8
|
#define BASE32_BLKSIZE_ENC 8
|
||||||
|
|
||||||
static const char cb32[] =
|
static const char cb32[] =
|
||||||
"abcdefghijklmnopqrstuvwxyz012345";
|
"abcdefghijklmnopqrstuvwxyz012345";
|
||||||
static const char cb32_ucase[] =
|
static const char cb32_ucase[] =
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ012345";
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ012345";
|
||||||
static unsigned char rev32[256];
|
static unsigned char rev32[256];
|
||||||
static int reverse_init = 0;
|
static int reverse_init = 0;
|
||||||
|
|
||||||
static int base32_encode(char *, size_t *, const void *, size_t);
|
inline static void base32_reverse_init(void)
|
||||||
static int base32_decode(void *, size_t *, const char *, size_t);
|
|
||||||
static int base32_handles_dots();
|
|
||||||
static int base32_blksize_raw();
|
|
||||||
static int base32_blksize_enc();
|
|
||||||
|
|
||||||
static struct encoder base32_encoder =
|
|
||||||
{
|
|
||||||
"Base32",
|
|
||||||
base32_encode,
|
|
||||||
base32_decode,
|
|
||||||
base32_handles_dots,
|
|
||||||
base32_handles_dots,
|
|
||||||
base32_blksize_raw,
|
|
||||||
base32_blksize_enc
|
|
||||||
};
|
|
||||||
|
|
||||||
struct encoder
|
|
||||||
*get_base32_encoder()
|
|
||||||
{
|
|
||||||
return &base32_encoder;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
base32_handles_dots()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
base32_blksize_raw()
|
|
||||||
{
|
|
||||||
return BLKSIZE_RAW;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
base32_blksize_enc()
|
|
||||||
{
|
|
||||||
return BLKSIZE_ENC;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static void
|
|
||||||
base32_reverse_init()
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
unsigned char c;
|
unsigned char c;
|
||||||
|
|
||||||
if (!reverse_init) {
|
if (!reverse_init) {
|
||||||
memset (rev32, 0, 256);
|
memset(rev32, 0, 256);
|
||||||
for (i = 0; i < 32; i++) {
|
for (i = 0; i < 32; i++) {
|
||||||
c = cb32[i];
|
c = cb32[i];
|
||||||
rev32[(int) c] = i;
|
rev32[(int) c] = i;
|
||||||
|
@ -91,21 +49,17 @@ base32_reverse_init()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int b32_5to8(int in)
|
||||||
b32_5to8(int in)
|
|
||||||
{
|
{
|
||||||
return cb32[in & 31];
|
return cb32[in & 31];
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int b32_8to5(int in)
|
||||||
b32_8to5(int in)
|
|
||||||
{
|
{
|
||||||
base32_reverse_init();
|
base32_reverse_init();
|
||||||
return rev32[in];
|
return rev32[in];
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
base32_encode(char *buf, size_t *buflen, const void *data, size_t size)
|
|
||||||
/*
|
/*
|
||||||
* Fills *buf with max. *buflen characters, encoding size bytes of *data.
|
* Fills *buf with max. *buflen characters, encoding size bytes of *data.
|
||||||
*
|
*
|
||||||
|
@ -115,6 +69,7 @@ base32_encode(char *buf, size_t *buflen, const void *data, size_t size)
|
||||||
* return value : #bytes filled in buf (excluding \0)
|
* return value : #bytes filled in buf (excluding \0)
|
||||||
* sets *buflen to : #bytes encoded from data
|
* sets *buflen to : #bytes encoded from data
|
||||||
*/
|
*/
|
||||||
|
static int base32_encode(char *buf, size_t *buflen, const void *data, size_t size)
|
||||||
{
|
{
|
||||||
unsigned char *udata = (unsigned char *) data;
|
unsigned char *udata = (unsigned char *) data;
|
||||||
int iout = 0; /* to-be-filled output char */
|
int iout = 0; /* to-be-filled output char */
|
||||||
|
@ -195,8 +150,6 @@ base32_encode(char *buf, size_t *buflen, const void *data, size_t size)
|
||||||
|
|
||||||
#define REV32(x) rev32[(int) (x)]
|
#define REV32(x) rev32[(int) (x)]
|
||||||
|
|
||||||
static int
|
|
||||||
base32_decode(void *buf, size_t *buflen, const char *str, size_t slen)
|
|
||||||
/*
|
/*
|
||||||
* Fills *buf with max. *buflen bytes, decoded from slen chars in *str.
|
* Fills *buf with max. *buflen bytes, decoded from slen chars in *str.
|
||||||
* Decoding stops early when *str contains \0.
|
* Decoding stops early when *str contains \0.
|
||||||
|
@ -208,12 +161,14 @@ base32_decode(void *buf, size_t *buflen, const char *str, size_t slen)
|
||||||
*
|
*
|
||||||
* return value : #bytes filled in buf (excluding \0)
|
* return value : #bytes filled in buf (excluding \0)
|
||||||
*/
|
*/
|
||||||
|
static int base32_decode(void *buf, size_t *buflen, const char *str,
|
||||||
|
size_t slen)
|
||||||
{
|
{
|
||||||
unsigned char *ubuf = (unsigned char *) buf;
|
unsigned char *ubuf = (unsigned char *) buf;
|
||||||
int iout = 0; /* to-be-filled output byte */
|
int iout = 0; /* to-be-filled output byte */
|
||||||
int iin = 0; /* next input char to use in decoding */
|
int iin = 0; /* next input char to use in decoding */
|
||||||
|
|
||||||
base32_reverse_init ();
|
base32_reverse_init();
|
||||||
|
|
||||||
/* Note: Don't bother to optimize manually. GCC optimizes
|
/* Note: Don't bother to optimize manually. GCC optimizes
|
||||||
better(!) when using simplistic array indexing. */
|
better(!) when using simplistic array indexing. */
|
||||||
|
@ -222,7 +177,7 @@ base32_decode(void *buf, size_t *buflen, const char *str, size_t slen)
|
||||||
if (iout >= *buflen || iin + 1 >= slen ||
|
if (iout >= *buflen || iin + 1 >= slen ||
|
||||||
str[iin] == '\0' || str[iin + 1] == '\0')
|
str[iin] == '\0' || str[iin + 1] == '\0')
|
||||||
break;
|
break;
|
||||||
ubuf[iout] = ((REV32(str[iin]) & 0x1f) << 3) |
|
ubuf[iout] = ((REV32(str[iin]) & 0x1f) << 3) |
|
||||||
((REV32(str[iin + 1]) & 0x1c) >> 2);
|
((REV32(str[iin + 1]) & 0x1c) >> 2);
|
||||||
iin++; /* 0 used up, iin=1 */
|
iin++; /* 0 used up, iin=1 */
|
||||||
iout++;
|
iout++;
|
||||||
|
@ -231,8 +186,8 @@ base32_decode(void *buf, size_t *buflen, const char *str, size_t slen)
|
||||||
str[iin] == '\0' || str[iin + 1] == '\0' ||
|
str[iin] == '\0' || str[iin + 1] == '\0' ||
|
||||||
str[iin + 2] == '\0')
|
str[iin + 2] == '\0')
|
||||||
break;
|
break;
|
||||||
ubuf[iout] = ((REV32(str[iin]) & 0x03) << 6) |
|
ubuf[iout] = ((REV32(str[iin]) & 0x03) << 6) |
|
||||||
((REV32(str[iin + 1]) & 0x1f) << 1) |
|
((REV32(str[iin + 1]) & 0x1f) << 1) |
|
||||||
((REV32(str[iin + 2]) & 0x10) >> 4);
|
((REV32(str[iin + 2]) & 0x10) >> 4);
|
||||||
iin += 2; /* 1,2 used up, iin=3 */
|
iin += 2; /* 1,2 used up, iin=3 */
|
||||||
iout++;
|
iout++;
|
||||||
|
@ -268,3 +223,16 @@ base32_decode(void *buf, size_t *buflen, const char *str, size_t slen)
|
||||||
|
|
||||||
return iout;
|
return iout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const struct encoder base32_ops = {
|
||||||
|
.name = "Base32",
|
||||||
|
|
||||||
|
.encode = base32_encode,
|
||||||
|
.decode = base32_decode,
|
||||||
|
|
||||||
|
.places_dots = false,
|
||||||
|
.eats_dots = false,
|
||||||
|
|
||||||
|
.blocksize_raw = BASE32_BLKSIZE_RAW,
|
||||||
|
.blocksize_encoded = BASE32_BLKSIZE_ENC,
|
||||||
|
};
|
||||||
|
|
24
src/base32.h
24
src/base32.h
|
@ -1,24 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 __BASE32_H__
|
|
||||||
#define __BASE32_H__
|
|
||||||
|
|
||||||
struct encoder *get_base32_encoder(void);
|
|
||||||
|
|
||||||
int b32_5to8(int);
|
|
||||||
int b32_8to5(int);
|
|
||||||
#endif
|
|
87
src/base64.c
87
src/base64.c
|
@ -1,8 +1,9 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
|
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||||
|
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||||
* Mostly rewritten 2009 J.A.Bezemer@opensourcepartners.nl
|
* Mostly rewritten 2009 J.A.Bezemer@opensourcepartners.nl
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
* copyright notice and this permission notice appear in all copies.
|
* copyright notice and this permission notice appear in all copies.
|
||||||
*
|
*
|
||||||
|
@ -20,67 +21,24 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "encoding.h"
|
#include "encoding.h"
|
||||||
#include "base64.h"
|
|
||||||
|
|
||||||
#define BLKSIZE_RAW 3
|
#define BASE64_BLKSIZE_RAW 3
|
||||||
#define BLKSIZE_ENC 4
|
#define BASE64_BLKSIZE_ENC 4
|
||||||
|
|
||||||
/* Note: the "unofficial" char is last here, which means that the \377 pattern
|
/* Note: the "unofficial" char is last here, which means that the \377 pattern
|
||||||
in DOWNCODECCHECK1 ('Y' request) will properly test it. */
|
in DOWNCODECCHECK1 ('Y' request) will properly test it. */
|
||||||
static const char cb64[] =
|
static const char cb64[] =
|
||||||
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789+";
|
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789+";
|
||||||
static unsigned char rev64[256];
|
static unsigned char rev64[256];
|
||||||
static int reverse_init = 0;
|
static int reverse_init = 0;
|
||||||
|
|
||||||
static int base64_encode(char *, size_t *, const void *, size_t);
|
inline static void base64_reverse_init(void)
|
||||||
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();
|
|
||||||
|
|
||||||
static struct encoder base64_encoder =
|
|
||||||
{
|
|
||||||
"Base64",
|
|
||||||
base64_encode,
|
|
||||||
base64_decode,
|
|
||||||
base64_handles_dots,
|
|
||||||
base64_handles_dots,
|
|
||||||
base64_blksize_raw,
|
|
||||||
base64_blksize_enc
|
|
||||||
};
|
|
||||||
|
|
||||||
struct encoder
|
|
||||||
*get_base64_encoder()
|
|
||||||
{
|
|
||||||
return &base64_encoder;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
base64_handles_dots()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
base64_blksize_raw()
|
|
||||||
{
|
|
||||||
return BLKSIZE_RAW;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
base64_blksize_enc()
|
|
||||||
{
|
|
||||||
return BLKSIZE_ENC;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static void
|
|
||||||
base64_reverse_init()
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
unsigned char c;
|
unsigned char c;
|
||||||
|
|
||||||
if (!reverse_init) {
|
if (!reverse_init) {
|
||||||
memset (rev64, 0, 256);
|
memset(rev64, 0, 256);
|
||||||
for (i = 0; i < 64; i++) {
|
for (i = 0; i < 64; i++) {
|
||||||
c = cb64[i];
|
c = cb64[i];
|
||||||
rev64[(int) c] = i;
|
rev64[(int) c] = i;
|
||||||
|
@ -89,8 +47,6 @@ base64_reverse_init()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
base64_encode(char *buf, size_t *buflen, const void *data, size_t size)
|
|
||||||
/*
|
/*
|
||||||
* Fills *buf with max. *buflen characters, encoding size bytes of *data.
|
* Fills *buf with max. *buflen characters, encoding size bytes of *data.
|
||||||
*
|
*
|
||||||
|
@ -100,6 +56,8 @@ base64_encode(char *buf, size_t *buflen, const void *data, size_t size)
|
||||||
* return value : #bytes filled in buf (excluding \0)
|
* return value : #bytes filled in buf (excluding \0)
|
||||||
* sets *buflen to : #bytes encoded from data
|
* sets *buflen to : #bytes encoded from data
|
||||||
*/
|
*/
|
||||||
|
static int base64_encode(char *buf, size_t *buflen, const void *data,
|
||||||
|
size_t size)
|
||||||
{
|
{
|
||||||
unsigned char *udata = (unsigned char *) data;
|
unsigned char *udata = (unsigned char *) data;
|
||||||
int iout = 0; /* to-be-filled output char */
|
int iout = 0; /* to-be-filled output char */
|
||||||
|
@ -127,7 +85,7 @@ base64_encode(char *buf, size_t *buflen, const void *data, size_t size)
|
||||||
|
|
||||||
if (iout >= *buflen || iin >= size)
|
if (iout >= *buflen || iin >= size)
|
||||||
break;
|
break;
|
||||||
buf[iout] = cb64[((udata[iin] & 0x0f) << 2 ) |
|
buf[iout] = cb64[((udata[iin] & 0x0f) << 2) |
|
||||||
((iin + 1 < size) ?
|
((iin + 1 < size) ?
|
||||||
((udata[iin + 1] & 0xc0) >> 6) : 0)];
|
((udata[iin + 1] & 0xc0) >> 6) : 0)];
|
||||||
iin++; /* 1 complete, iin=2 */
|
iin++; /* 1 complete, iin=2 */
|
||||||
|
@ -150,8 +108,6 @@ base64_encode(char *buf, size_t *buflen, const void *data, size_t size)
|
||||||
|
|
||||||
#define REV64(x) rev64[(int) (x)]
|
#define REV64(x) rev64[(int) (x)]
|
||||||
|
|
||||||
static int
|
|
||||||
base64_decode(void *buf, size_t *buflen, const char *str, size_t slen)
|
|
||||||
/*
|
/*
|
||||||
* Fills *buf with max. *buflen bytes, decoded from slen chars in *str.
|
* Fills *buf with max. *buflen bytes, decoded from slen chars in *str.
|
||||||
* Decoding stops early when *str contains \0.
|
* Decoding stops early when *str contains \0.
|
||||||
|
@ -163,12 +119,14 @@ base64_decode(void *buf, size_t *buflen, const char *str, size_t slen)
|
||||||
*
|
*
|
||||||
* return value : #bytes filled in buf (excluding \0)
|
* return value : #bytes filled in buf (excluding \0)
|
||||||
*/
|
*/
|
||||||
|
static int base64_decode(void *buf, size_t *buflen, const char *str,
|
||||||
|
size_t slen)
|
||||||
{
|
{
|
||||||
unsigned char *ubuf = (unsigned char *) buf;
|
unsigned char *ubuf = (unsigned char *) buf;
|
||||||
int iout = 0; /* to-be-filled output byte */
|
int iout = 0; /* to-be-filled output byte */
|
||||||
int iin = 0; /* next input char to use in decoding */
|
int iin = 0; /* next input char to use in decoding */
|
||||||
|
|
||||||
base64_reverse_init ();
|
base64_reverse_init();
|
||||||
|
|
||||||
/* Note: Don't bother to optimize manually. GCC optimizes
|
/* Note: Don't bother to optimize manually. GCC optimizes
|
||||||
better(!) when using simplistic array indexing. */
|
better(!) when using simplistic array indexing. */
|
||||||
|
@ -177,7 +135,7 @@ base64_decode(void *buf, size_t *buflen, const char *str, size_t slen)
|
||||||
if (iout >= *buflen || iin + 1 >= slen ||
|
if (iout >= *buflen || iin + 1 >= slen ||
|
||||||
str[iin] == '\0' || str[iin + 1] == '\0')
|
str[iin] == '\0' || str[iin + 1] == '\0')
|
||||||
break;
|
break;
|
||||||
ubuf[iout] = ((REV64(str[iin]) & 0x3f) << 2) |
|
ubuf[iout] = ((REV64(str[iin]) & 0x3f) << 2) |
|
||||||
((REV64(str[iin + 1]) & 0x30) >> 4);
|
((REV64(str[iin + 1]) & 0x30) >> 4);
|
||||||
iin++; /* 0 used up, iin=1 */
|
iin++; /* 0 used up, iin=1 */
|
||||||
iout++;
|
iout++;
|
||||||
|
@ -185,7 +143,7 @@ base64_decode(void *buf, size_t *buflen, const char *str, size_t slen)
|
||||||
if (iout >= *buflen || iin + 1 >= slen ||
|
if (iout >= *buflen || iin + 1 >= slen ||
|
||||||
str[iin] == '\0' || str[iin + 1] == '\0')
|
str[iin] == '\0' || str[iin + 1] == '\0')
|
||||||
break;
|
break;
|
||||||
ubuf[iout] = ((REV64(str[iin]) & 0x0f) << 4) |
|
ubuf[iout] = ((REV64(str[iin]) & 0x0f) << 4) |
|
||||||
((REV64(str[iin + 1]) & 0x3c) >> 2);
|
((REV64(str[iin + 1]) & 0x3c) >> 2);
|
||||||
iin++; /* 1 used up, iin=2 */
|
iin++; /* 1 used up, iin=2 */
|
||||||
iout++;
|
iout++;
|
||||||
|
@ -203,3 +161,16 @@ base64_decode(void *buf, size_t *buflen, const char *str, size_t slen)
|
||||||
|
|
||||||
return iout;
|
return iout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const struct encoder base64_ops = {
|
||||||
|
.name = "Base64",
|
||||||
|
|
||||||
|
.encode = base64_encode,
|
||||||
|
.decode = base64_decode,
|
||||||
|
|
||||||
|
.places_dots = false,
|
||||||
|
.eats_dots = false,
|
||||||
|
|
||||||
|
.blocksize_raw = BASE64_BLKSIZE_RAW,
|
||||||
|
.blocksize_encoded = BASE64_BLKSIZE_ENC,
|
||||||
|
};
|
||||||
|
|
22
src/base64.h
22
src/base64.h
|
@ -1,22 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 __BASE64_H__
|
|
||||||
#define __BASE64_H__
|
|
||||||
|
|
||||||
struct encoder *get_base64_encoder(void);
|
|
||||||
|
|
||||||
#endif
|
|
757
src/client.c
757
src/client.c
File diff suppressed because it is too large
Load diff
24
src/client.h
24
src/client.h
|
@ -1,7 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
|
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||||
|
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
* copyright notice and this permission notice appear in all copies.
|
* copyright notice and this permission notice appear in all copies.
|
||||||
*
|
*
|
||||||
|
@ -17,23 +18,24 @@
|
||||||
#ifndef __CLIENT_H__
|
#ifndef __CLIENT_H__
|
||||||
#define __CLIENT_H__
|
#define __CLIENT_H__
|
||||||
|
|
||||||
void client_init();
|
void client_init(void);
|
||||||
void client_stop();
|
void client_stop(void);
|
||||||
|
|
||||||
enum connection client_get_conn();
|
enum connection client_get_conn(void);
|
||||||
const char *client_get_raw_addr();
|
const char *client_get_raw_addr(void);
|
||||||
|
|
||||||
void client_set_nameserver(const char *cp, int port);
|
void client_set_nameserver(struct sockaddr_storage *, int);
|
||||||
void client_set_topdomain(const char *cp);
|
void client_set_topdomain(const char *cp);
|
||||||
void client_set_password(const char *cp);
|
void client_set_password(const char *cp);
|
||||||
void set_qtype(char *qtype);
|
int client_set_qtype(char *qtype);
|
||||||
char *get_qtype();
|
char *client_get_qtype(void);
|
||||||
void set_downenc(char *encoding);
|
void client_set_downenc(char *encoding);
|
||||||
void client_set_selecttimeout(int select_timeout);
|
void client_set_selecttimeout(int select_timeout);
|
||||||
void client_set_lazymode(int lazy_mode);
|
void client_set_lazymode(int lazy_mode);
|
||||||
void client_set_hostname_maxlen(int i);
|
void client_set_hostname_maxlen(int i);
|
||||||
|
|
||||||
int client_handshake(int dns_fd, int raw_mode, int autodetect_frag_size, int fragsize);
|
int client_handshake(int dns_fd, int raw_mode, int autodetect_frag_size,
|
||||||
|
int fragsize);
|
||||||
int client_tunnel(int tun_fd, int dns_fd);
|
int client_tunnel(int tun_fd, int dns_fd);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
353
src/common.c
353
src/common.c
|
@ -1,7 +1,8 @@
|
||||||
/* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
|
/* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||||
|
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||||
* Copyright (c) 2007 Albert Lee <trisk@acm.jhu.edu>.
|
* Copyright (c) 2007 Albert Lee <trisk@acm.jhu.edu>.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
* copyright notice and this permission notice appear in all copies.
|
* copyright notice and this permission notice appear in all copies.
|
||||||
*
|
*
|
||||||
|
@ -39,9 +40,11 @@
|
||||||
#endif
|
#endif
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netdb.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_SETCON
|
#ifdef HAVE_SETCON
|
||||||
|
@ -54,11 +57,11 @@
|
||||||
const unsigned char raw_header[RAW_HDR_LEN] = { 0x10, 0xd1, 0x9e, 0x00 };
|
const unsigned char raw_header[RAW_HDR_LEN] = { 0x10, 0xd1, 0x9e, 0x00 };
|
||||||
|
|
||||||
/* daemon(3) exists only in 4.4BSD or later, and in GNU libc */
|
/* daemon(3) exists only in 4.4BSD or later, and in GNU libc */
|
||||||
#if !defined(WINDOWS32) && !(defined(BSD) && (BSD >= 199306)) && !defined(__GLIBC__)
|
#if !defined(ANDROID) && !defined(WINDOWS32) && !(defined(BSD) && (BSD >= 199306)) && !defined(__GLIBC__) && !defined(__HAIKU__)
|
||||||
static int daemon(int nochdir, int noclose)
|
static int daemon(int nochdir, int noclose)
|
||||||
{
|
{
|
||||||
int fd, i;
|
int fd, i;
|
||||||
|
|
||||||
switch (fork()) {
|
switch (fork()) {
|
||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
|
@ -67,15 +70,15 @@ static int daemon(int nochdir, int noclose)
|
||||||
default:
|
default:
|
||||||
_exit(0);
|
_exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!nochdir) {
|
if (!nochdir) {
|
||||||
chdir("/");
|
chdir("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setsid() < 0) {
|
if (setsid() < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!noclose) {
|
if (!noclose) {
|
||||||
if ((fd = open("/dev/null", O_RDWR)) >= 0) {
|
if ((fd = open("/dev/null", O_RDWR)) >= 0) {
|
||||||
for (i = 0; i < 3; i++) {
|
for (i = 0; i < 3; i++) {
|
||||||
|
@ -98,34 +101,88 @@ int setgroups(int count, int *groups)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
check_superuser(void (*usage_fn)(void))
|
|
||||||
{
|
|
||||||
#ifndef WINDOWS32
|
#ifndef WINDOWS32
|
||||||
|
void
|
||||||
|
check_superuser(void)
|
||||||
|
{
|
||||||
if (geteuid() != 0) {
|
if (geteuid() != 0) {
|
||||||
warnx("Run as root and you'll be happy.\n");
|
warnx("Run as root and you'll be happy.");
|
||||||
usage_fn();
|
exit(-1);
|
||||||
/* NOTREACHED */
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
char *
|
||||||
|
format_addr(struct sockaddr_storage *sockaddr, int sockaddr_len)
|
||||||
|
{
|
||||||
|
static char dst[INET6_ADDRSTRLEN + 1];
|
||||||
|
|
||||||
|
memset(dst, 0, sizeof(dst));
|
||||||
|
if (sockaddr->ss_family == AF_INET && sockaddr_len >= sizeof(struct sockaddr_in)) {
|
||||||
|
getnameinfo((struct sockaddr *)sockaddr, sockaddr_len, dst, sizeof(dst) - 1, NULL, 0, NI_NUMERICHOST);
|
||||||
|
} else if (sockaddr->ss_family == AF_INET6 && sockaddr_len >= sizeof(struct sockaddr_in6)) {
|
||||||
|
struct sockaddr_in6 *addr = (struct sockaddr_in6 *) sockaddr;
|
||||||
|
if (IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr)) {
|
||||||
|
struct in_addr ia;
|
||||||
|
/* Get mapped v4 addr from last 32bit field */
|
||||||
|
memcpy(&ia.s_addr, &addr->sin6_addr.s6_addr[12], sizeof(ia));
|
||||||
|
strcpy(dst, inet_ntoa(ia));
|
||||||
|
} else {
|
||||||
|
getnameinfo((struct sockaddr *)sockaddr, sockaddr_len, dst, sizeof(dst) - 1, NULL, 0, NI_NUMERICHOST);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dst[0] = '?';
|
||||||
|
}
|
||||||
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
open_dns(int localport, in_addr_t listen_ip)
|
get_addr(char *host, int port, int addr_family, int flags, struct sockaddr_storage *out)
|
||||||
{
|
{
|
||||||
struct sockaddr_in addr;
|
struct addrinfo hints, *addr;
|
||||||
int flag = 1;
|
int res;
|
||||||
|
char portnum[8];
|
||||||
|
int addrlen;
|
||||||
|
|
||||||
|
memset(portnum, 0, sizeof(portnum));
|
||||||
|
snprintf(portnum, sizeof(portnum) - 1, "%d", port);
|
||||||
|
|
||||||
|
memset(&hints, 0, sizeof(hints));
|
||||||
|
hints.ai_family = addr_family;
|
||||||
|
#if defined(WINDOWS32) || defined(OPENBSD)
|
||||||
|
/* AI_ADDRCONFIG misbehaves on windows, and does not exist in OpenBSD */
|
||||||
|
hints.ai_flags = flags;
|
||||||
|
#else
|
||||||
|
hints.ai_flags = AI_ADDRCONFIG | flags;
|
||||||
|
#endif
|
||||||
|
hints.ai_socktype = SOCK_DGRAM;
|
||||||
|
hints.ai_protocol = IPPROTO_UDP;
|
||||||
|
|
||||||
|
res = getaddrinfo(host, portnum, &hints, &addr);
|
||||||
|
if (res != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
addrlen = addr->ai_addrlen;
|
||||||
|
/* Grab first result */
|
||||||
|
memcpy(out, addr->ai_addr, addr->ai_addrlen);
|
||||||
|
freeaddrinfo(addr);
|
||||||
|
return addrlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
open_dns(struct sockaddr_storage *sockaddr, size_t sockaddr_len)
|
||||||
|
{
|
||||||
|
return open_dns_opt(sockaddr, sockaddr_len, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
open_dns_opt(struct sockaddr_storage *sockaddr, size_t sockaddr_len, int v6only)
|
||||||
|
{
|
||||||
|
int flag;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
memset(&addr, 0, sizeof(addr));
|
if ((fd = socket(sockaddr->ss_family, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
|
||||||
addr.sin_family = AF_INET;
|
|
||||||
addr.sin_port = htons(localport);
|
|
||||||
/* listen_ip already in network byte order from inet_addr, or 0 */
|
|
||||||
addr.sin_addr.s_addr = listen_ip;
|
|
||||||
|
|
||||||
if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
|
|
||||||
fprintf(stderr, "got fd %d\n", fd);
|
|
||||||
err(1, "socket");
|
err(1, "socket");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,24 +193,40 @@ open_dns(int localport, in_addr_t listen_ip)
|
||||||
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void*) &flag, sizeof(flag));
|
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void*) &flag, sizeof(flag));
|
||||||
|
|
||||||
#ifndef WINDOWS32
|
#ifndef WINDOWS32
|
||||||
/* To get destination address from each UDP datagram, see iodined.c:read_dns() */
|
fd_set_close_on_exec(fd);
|
||||||
setsockopt(fd, IPPROTO_IP, DSTADDR_SOCKOPT, (const void*) &flag, sizeof(flag));
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (sockaddr->ss_family == AF_INET6 && v6only >= 0) {
|
||||||
|
setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (const void*) &v6only, sizeof(v6only));
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef IP_OPT_DONT_FRAG
|
#ifdef IP_OPT_DONT_FRAG
|
||||||
/* Set dont-fragment ip header flag */
|
/* Set dont-fragment ip header flag */
|
||||||
flag = DONT_FRAG_VALUE;
|
flag = DONT_FRAG_VALUE;
|
||||||
setsockopt(fd, IPPROTO_IP, IP_OPT_DONT_FRAG, (const void*) &flag, sizeof(flag));
|
setsockopt(fd, IPPROTO_IP, IP_OPT_DONT_FRAG, (const void*) &flag, sizeof(flag));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0)
|
if (bind(fd, (struct sockaddr*) sockaddr, sockaddr_len) < 0)
|
||||||
err(1, "bind");
|
err(1, "bind() to %s", format_addr(sockaddr, sockaddr_len));
|
||||||
|
|
||||||
fprintf(stderr, "Opened UDP socket\n");
|
fprintf(stderr, "Opened IPv%d UDP socket\n", sockaddr->ss_family == AF_INET6 ? 6 : 4);
|
||||||
|
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
open_dns_from_host(char *host, int port, int addr_family, int flags)
|
||||||
|
{
|
||||||
|
struct sockaddr_storage addr;
|
||||||
|
int addrlen;
|
||||||
|
|
||||||
|
addrlen = get_addr(host, port, addr_family, flags, &addr);
|
||||||
|
if (addrlen < 0)
|
||||||
|
return addrlen;
|
||||||
|
|
||||||
|
return open_dns(&addr, addrlen);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
close_dns(int fd)
|
close_dns(int fd)
|
||||||
{
|
{
|
||||||
|
@ -167,8 +240,9 @@ do_chroot(char *newroot)
|
||||||
if (chroot(newroot) != 0 || chdir("/") != 0)
|
if (chroot(newroot) != 0 || chdir("/") != 0)
|
||||||
err(1, "%s", newroot);
|
err(1, "%s", newroot);
|
||||||
|
|
||||||
seteuid(geteuid());
|
if (seteuid(geteuid()) != 0 || setuid(getuid()) != 0) {
|
||||||
setuid(getuid());
|
err(1, "set[e]uid()");
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
warnx("chroot not available");
|
warnx("chroot not available");
|
||||||
#endif
|
#endif
|
||||||
|
@ -204,7 +278,7 @@ do_pidfile(char *pidfile)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
do_detach()
|
do_detach(void)
|
||||||
{
|
{
|
||||||
#ifndef WINDOWS32
|
#ifndef WINDOWS32
|
||||||
fprintf(stderr, "Detaching from terminal...\n");
|
fprintf(stderr, "Detaching from terminal...\n");
|
||||||
|
@ -219,24 +293,24 @@ do_detach()
|
||||||
void
|
void
|
||||||
read_password(char *buf, size_t len)
|
read_password(char *buf, size_t len)
|
||||||
{
|
{
|
||||||
char pwd[80];
|
char pwd[80] = {0};
|
||||||
#ifndef WINDOWS32
|
#ifndef WINDOWS32
|
||||||
struct termios old;
|
struct termios old;
|
||||||
struct termios tp;
|
struct termios tp;
|
||||||
|
|
||||||
tcgetattr(0, &tp);
|
tcgetattr(0, &tp);
|
||||||
old = tp;
|
old = tp;
|
||||||
|
|
||||||
tp.c_lflag &= (~ECHO);
|
tp.c_lflag &= (~ECHO);
|
||||||
tcsetattr(0, TCSANOW, &tp);
|
tcsetattr(0, TCSANOW, &tp);
|
||||||
#else
|
#else
|
||||||
int i;
|
int i;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
fprintf(stderr, "Enter password: ");
|
fprintf(stderr, "Enter tunnel password: ");
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
#ifndef WINDOWS32
|
#ifndef WINDOWS32
|
||||||
scanf("%79s", pwd);
|
fscanf(stdin, "%79[^\n]", pwd);
|
||||||
#else
|
#else
|
||||||
for (i = 0; i < sizeof(pwd); i++) {
|
for (i = 0; i < sizeof(pwd); i++) {
|
||||||
pwd[i] = getch();
|
pwd[i] = getch();
|
||||||
|
@ -252,7 +326,7 @@ read_password(char *buf, size_t len)
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
|
|
||||||
#ifndef WINDOWS32
|
#ifndef WINDOWS32
|
||||||
tcsetattr(0, TCSANOW, &old);
|
tcsetattr(0, TCSANOW, &old);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
strncpy(buf, pwd, len);
|
strncpy(buf, pwd, len);
|
||||||
|
@ -260,29 +334,146 @@ read_password(char *buf, size_t len)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
check_topdomain(char *str)
|
check_topdomain(char *str, int allow_wildcard, char **errormsg)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
int dots = 0;
|
||||||
|
int chunklen = 0;
|
||||||
|
|
||||||
if(str[0] == '.') /* special case */
|
if (strlen(str) < 3) {
|
||||||
return 1;
|
if (errormsg) *errormsg = "Too short (< 3)";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (strlen(str) > 128) {
|
||||||
|
if (errormsg) *errormsg = "Too long (> 128)";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
for( i = 0; i < strlen(str); i++) {
|
if (str[0] == '.') {
|
||||||
if( isalpha(str[i]) || isdigit(str[i]) || str[i] == '-' || str[i] == '.' )
|
if (errormsg) *errormsg = "Starts with a dot";
|
||||||
continue;
|
return 1;
|
||||||
else
|
}
|
||||||
return 1;
|
|
||||||
}
|
for (i = 0; i < strlen(str); i++) {
|
||||||
return 0;
|
if (str[i] == '.') {
|
||||||
|
dots++;
|
||||||
|
if (chunklen == 0) {
|
||||||
|
if (errormsg) *errormsg = "Consecutive dots";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (chunklen > 63) {
|
||||||
|
if (errormsg) *errormsg = "Too long domain part (> 63)";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
chunklen = 0;
|
||||||
|
} else {
|
||||||
|
chunklen++;
|
||||||
|
}
|
||||||
|
if ((str[i] >= 'a' && str[i] <= 'z') || (str[i] >= 'A' && str[i] <= 'Z') ||
|
||||||
|
isdigit(str[i]) || str[i] == '-' || str[i] == '.') {
|
||||||
|
continue;
|
||||||
|
} else if (allow_wildcard && str[i] == '*') {
|
||||||
|
/* First char allowed to be wildcard, if followed by dot */
|
||||||
|
if (i == 0) {
|
||||||
|
if (str[i+1] == '.') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (errormsg) *errormsg = "Wildcard (*) must be followed by dot";
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
if (errormsg) *errormsg = "Wildcard (*) only allowed as first char";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (errormsg) *errormsg = "Contains illegal character (allowed: [a-zA-Z0-9-.])";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dots == 0) {
|
||||||
|
if (errormsg) *errormsg = "No dots";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (chunklen == 0) {
|
||||||
|
if (errormsg) *errormsg = "Ends with a dot";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (chunklen > 63) {
|
||||||
|
if (errormsg) *errormsg = "Too long domain part (> 63)";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WINDOWS32
|
int
|
||||||
|
query_datalen(const char *qname, const char *topdomain)
|
||||||
|
{
|
||||||
|
/* Return number of data bytes embedded in DNS query name,
|
||||||
|
* or -1 if domains do not match.
|
||||||
|
*/
|
||||||
|
int qpos = strlen(qname);
|
||||||
|
int tpos = strlen(topdomain);
|
||||||
|
if (tpos < 3 || qpos < tpos) {
|
||||||
|
/* Domain or query name too short */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* Backward string compare */
|
||||||
|
qpos--;
|
||||||
|
tpos--;
|
||||||
|
while (qpos >= 0) {
|
||||||
|
if (topdomain[tpos] == '*') {
|
||||||
|
/* Wild match, is first in topdomain */
|
||||||
|
if (qname[qpos] == '*') {
|
||||||
|
/* Don't match against stars in query name */
|
||||||
|
return -1;
|
||||||
|
} else if (qpos == 0 || qname[qpos-1] == '.') {
|
||||||
|
/* Reached start of query name or chunk separator */
|
||||||
|
return qpos;
|
||||||
|
}
|
||||||
|
qpos--;
|
||||||
|
} else if (tolower(qname[qpos]) == tolower(topdomain[tpos])) {
|
||||||
|
/* Matching char, exclude wildcard in query name */
|
||||||
|
if (tpos == 0) {
|
||||||
|
/* Fully matched domain */
|
||||||
|
if (qpos == 0 || qname[qpos-1] == '.') {
|
||||||
|
/* Start of name or has dot before matching topdomain */
|
||||||
|
return qpos;
|
||||||
|
}
|
||||||
|
/* Query name has longer chunk than topdomain */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
tpos--;
|
||||||
|
qpos--;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(WINDOWS32) || defined(ANDROID)
|
||||||
|
#ifndef ANDROID
|
||||||
int
|
int
|
||||||
inet_aton(const char *cp, struct in_addr *inp)
|
inet_aton(const char *cp, struct in_addr *inp)
|
||||||
{
|
{
|
||||||
inp->s_addr = inet_addr(cp);
|
inp->s_addr = inet_addr(cp);
|
||||||
return inp->s_addr != INADDR_ANY;
|
return inp->s_addr != INADDR_ANY;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void
|
||||||
|
vwarn(const char *fmt, va_list list)
|
||||||
|
{
|
||||||
|
if (fmt) vfprintf(stderr, fmt, list);
|
||||||
|
#ifndef ANDROID
|
||||||
|
if (errno == 0) {
|
||||||
|
fprintf(stderr, ": WSA error %d\n", WSAGetLastError());
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, ": %s\n", strerror(errno));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
warn(const char *fmt, ...)
|
warn(const char *fmt, ...)
|
||||||
|
@ -290,23 +481,7 @@ warn(const char *fmt, ...)
|
||||||
va_list list;
|
va_list list;
|
||||||
|
|
||||||
va_start(list, fmt);
|
va_start(list, fmt);
|
||||||
if (fmt) fprintf(stderr, fmt, list);
|
vwarn(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);
|
va_end(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,18 +491,35 @@ err(int eval, const char *fmt, ...)
|
||||||
va_list list;
|
va_list list;
|
||||||
|
|
||||||
va_start(list, fmt);
|
va_start(list, fmt);
|
||||||
warn(fmt, list);
|
vwarn(fmt, list);
|
||||||
va_end(list);
|
va_end(list);
|
||||||
exit(eval);
|
exit(eval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vwarnx(const char *fmt, va_list list)
|
||||||
|
{
|
||||||
|
if (fmt) vfprintf(stderr, fmt, list);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
warnx(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list list;
|
||||||
|
|
||||||
|
va_start(list, fmt);
|
||||||
|
vwarnx(fmt, list);
|
||||||
|
va_end(list);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
errx(int eval, const char *fmt, ...)
|
errx(int eval, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list list;
|
va_list list;
|
||||||
|
|
||||||
va_start(list, fmt);
|
va_start(list, fmt);
|
||||||
warnx(fmt, list);
|
vwarnx(fmt, list);
|
||||||
va_end(list);
|
va_end(list);
|
||||||
exit(eval);
|
exit(eval);
|
||||||
}
|
}
|
||||||
|
@ -348,3 +540,22 @@ int recent_seqno(int ourseqno, int gotseqno)
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef WINDOWS32
|
||||||
|
/* Set FD_CLOEXEC flag on file descriptor.
|
||||||
|
* This stops it from being inherited by system() calls.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
fd_set_close_on_exec(int fd)
|
||||||
|
{
|
||||||
|
int flags;
|
||||||
|
|
||||||
|
flags = fcntl(fd, F_GETFD);
|
||||||
|
if (flags == -1)
|
||||||
|
err(4, "Failed to get fd flags");
|
||||||
|
flags |= FD_CLOEXEC;
|
||||||
|
if (fcntl(fd, F_SETFD, flags) == -1)
|
||||||
|
err(4, "Failed to set fd flags");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
71
src/common.h
71
src/common.h
|
@ -1,7 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
|
* Copyright (c) 2006-2015 Erik Ekman <yarrick@kryo.se>,
|
||||||
|
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
* copyright notice and this permission notice appear in all copies.
|
* copyright notice and this permission notice appear in all copies.
|
||||||
*
|
*
|
||||||
|
@ -31,14 +32,15 @@
|
||||||
#define RAW_HDR_GET_USR(x) ((x)[RAW_HDR_CMD] & RAW_HDR_USR_MASK)
|
#define RAW_HDR_GET_USR(x) ((x)[RAW_HDR_CMD] & RAW_HDR_USR_MASK)
|
||||||
extern const unsigned char raw_header[RAW_HDR_LEN];
|
extern const unsigned char raw_header[RAW_HDR_LEN];
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
#ifdef WINDOWS32
|
#ifdef WINDOWS32
|
||||||
#include "windows.h"
|
#include "windows.h"
|
||||||
#else
|
#else
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define DNS_PORT 53
|
#define DNS_PORT 53
|
||||||
|
@ -52,14 +54,6 @@ extern const unsigned char raw_header[RAW_HDR_LEN];
|
||||||
|
|
||||||
#define QUERY_NAME_SIZE 256
|
#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
|
#if defined IP_MTU_DISCOVER
|
||||||
/* Linux */
|
/* Linux */
|
||||||
# define IP_OPT_DONT_FRAG IP_MTU_DISCOVER
|
# define IP_OPT_DONT_FRAG IP_MTU_DISCOVER
|
||||||
|
@ -74,10 +68,13 @@ extern const unsigned char raw_header[RAW_HDR_LEN];
|
||||||
# define DONT_FRAG_VALUE 1
|
# define DONT_FRAG_VALUE 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define T_PRIVATE 65399
|
||||||
|
/* Undefined RR type; "private use" range, see
|
||||||
|
* http://www.bind9.net/dns-parameters */
|
||||||
#define T_UNSET 65432
|
#define T_UNSET 65432
|
||||||
/* Unused RR type; "private use" range, see http://www.bind9.net/dns-parameters */
|
/* Unused RR type, never actually sent */
|
||||||
|
|
||||||
struct packet
|
struct packet
|
||||||
{
|
{
|
||||||
int len; /* Total packet length */
|
int len; /* Total packet length */
|
||||||
int sentlen; /* Length of chunk currently transmitted */
|
int sentlen; /* Length of chunk currently transmitted */
|
||||||
|
@ -92,42 +89,64 @@ struct query {
|
||||||
unsigned short type;
|
unsigned short type;
|
||||||
unsigned short rcode;
|
unsigned short rcode;
|
||||||
unsigned short id;
|
unsigned short id;
|
||||||
struct in_addr destination;
|
struct sockaddr_storage destination;
|
||||||
struct sockaddr from;
|
socklen_t dest_len;
|
||||||
int fromlen;
|
struct sockaddr_storage from;
|
||||||
|
socklen_t fromlen;
|
||||||
unsigned short id2;
|
unsigned short id2;
|
||||||
struct sockaddr from2;
|
struct sockaddr_storage from2;
|
||||||
int fromlen2;
|
socklen_t fromlen2;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum connection {
|
enum connection {
|
||||||
CONN_RAW_UDP,
|
CONN_RAW_UDP = 0,
|
||||||
CONN_DNS_NULL,
|
CONN_DNS_NULL,
|
||||||
CONN_MAX
|
CONN_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
void check_superuser(void (*usage_fn)(void));
|
#ifdef WINDOWS32
|
||||||
int open_dns(int, in_addr_t);
|
static inline void check_superuser(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void check_superuser(void);
|
||||||
|
#endif
|
||||||
|
char *format_addr(struct sockaddr_storage *sockaddr, int sockaddr_len);
|
||||||
|
int get_addr(char *, int, int, int, struct sockaddr_storage *);
|
||||||
|
int open_dns(struct sockaddr_storage *, size_t);
|
||||||
|
int open_dns_opt(struct sockaddr_storage *sockaddr, size_t sockaddr_len,
|
||||||
|
int v6only);
|
||||||
|
int open_dns_from_host(char *host, int port, int addr_family, int flags);
|
||||||
void close_dns(int);
|
void close_dns(int);
|
||||||
|
|
||||||
void do_chroot(char *);
|
void do_chroot(char *);
|
||||||
void do_setcon(char *);
|
void do_setcon(char *);
|
||||||
void do_detach();
|
void do_detach(void);
|
||||||
void do_pidfile(char *);
|
void do_pidfile(char *);
|
||||||
|
|
||||||
void read_password(char*, size_t);
|
void read_password(char*, size_t);
|
||||||
|
|
||||||
int check_topdomain(char *);
|
int check_topdomain(char *, int, char **);
|
||||||
|
|
||||||
#ifdef WINDOWS32
|
int query_datalen(const char *qname, const char *topdomain);
|
||||||
|
|
||||||
|
#if defined(WINDOWS32) || defined(ANDROID)
|
||||||
|
#ifndef ANDROID
|
||||||
int inet_aton(const char *cp, struct in_addr *inp);
|
int inet_aton(const char *cp, struct in_addr *inp);
|
||||||
|
#endif
|
||||||
|
|
||||||
void err(int eval, const char *fmt, ...);
|
void vwarn(const char *fmt, va_list list);
|
||||||
void warn(const char *fmt, ...);
|
void warn(const char *fmt, ...);
|
||||||
void errx(int eval, const char *fmt, ...);
|
void err(int eval, const char *fmt, ...);
|
||||||
|
void vwarnx(const char *fmt, va_list list);
|
||||||
void warnx(const char *fmt, ...);
|
void warnx(const char *fmt, ...);
|
||||||
|
void errx(int eval, const char *fmt, ...);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int recent_seqno(int , int);
|
int recent_seqno(int , int);
|
||||||
|
|
||||||
|
#ifndef WINDOWS32
|
||||||
|
void fd_set_close_on_exec(int fd);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
225
src/dns.c
225
src/dns.c
|
@ -1,7 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
|
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||||
|
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
* copyright notice and this permission notice appear in all copies.
|
* copyright notice and this permission notice appear in all copies.
|
||||||
*
|
*
|
||||||
|
@ -20,6 +21,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <strings.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
#ifdef WINDOWS32
|
#ifdef WINDOWS32
|
||||||
|
@ -30,8 +32,12 @@
|
||||||
#define BIND_8_COMPAT
|
#define BIND_8_COMPAT
|
||||||
#include <arpa/nameser_compat.h>
|
#include <arpa/nameser_compat.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
|
#ifdef ANDROID
|
||||||
|
#include "android_dns.h"
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -41,10 +47,10 @@
|
||||||
|
|
||||||
int dnsc_use_edns0 = 1;
|
int dnsc_use_edns0 = 1;
|
||||||
|
|
||||||
#define CHECKLEN(x) if (buflen - (p-buf) < (x)) return 0
|
#define CHECKLEN(x) if (buflen < (x) + (size_t)(p-buf)) return 0
|
||||||
|
|
||||||
int
|
int dns_encode(char *buf, size_t buflen, struct query *q, qr_t qr,
|
||||||
dns_encode(char *buf, size_t buflen, struct query *q, qr_t qr, char *data, size_t datalen)
|
const char *data, size_t datalen)
|
||||||
{
|
{
|
||||||
HEADER *header;
|
HEADER *header;
|
||||||
short name;
|
short name;
|
||||||
|
@ -56,9 +62,9 @@ dns_encode(char *buf, size_t buflen, struct query *q, qr_t qr, char *data, size_
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
memset(buf, 0, buflen);
|
memset(buf, 0, buflen);
|
||||||
|
|
||||||
header = (HEADER*)buf;
|
header = (HEADER*)buf;
|
||||||
|
|
||||||
header->id = htons(q->id);
|
header->id = htons(q->id);
|
||||||
header->qr = (qr == QR_ANSWER);
|
header->qr = (qr == QR_ANSWER);
|
||||||
header->opcode = 0;
|
header->opcode = 0;
|
||||||
|
@ -72,7 +78,7 @@ dns_encode(char *buf, size_t buflen, struct query *q, qr_t qr, char *data, size_
|
||||||
switch (qr) {
|
switch (qr) {
|
||||||
case QR_ANSWER:
|
case QR_ANSWER:
|
||||||
header->qdcount = htons(1);
|
header->qdcount = htons(1);
|
||||||
|
|
||||||
name = 0xc000 | ((p - buf) & 0x3fff);
|
name = 0xc000 | ((p - buf) & 0x3fff);
|
||||||
|
|
||||||
/* Question section */
|
/* Question section */
|
||||||
|
@ -85,13 +91,14 @@ dns_encode(char *buf, size_t buflen, struct query *q, qr_t qr, char *data, size_
|
||||||
/* Answer section */
|
/* Answer section */
|
||||||
|
|
||||||
if (q->type == T_CNAME || q->type == T_A) {
|
if (q->type == T_CNAME || q->type == T_A) {
|
||||||
/* data is expected to be like "Hblabla.host.name.com\0" */
|
/* data is expected to be like
|
||||||
|
* "Hblabla.host.name.com\0" */
|
||||||
|
|
||||||
char *startp;
|
char *startp;
|
||||||
int namelen;
|
int namelen;
|
||||||
|
|
||||||
CHECKLEN(10);
|
CHECKLEN(10);
|
||||||
putshort(&p, name);
|
putshort(&p, name);
|
||||||
if (q->type == T_A)
|
if (q->type == T_A)
|
||||||
/* answer CNAME to A question */
|
/* answer CNAME to A question */
|
||||||
putshort(&p, T_CNAME);
|
putshort(&p, T_CNAME);
|
||||||
|
@ -114,22 +121,22 @@ dns_encode(char *buf, size_t buflen, struct query *q, qr_t qr, char *data, size_
|
||||||
For SRV, see RFC2782.
|
For SRV, see RFC2782.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char *mxdata = data;
|
const char *mxdata = data;
|
||||||
char *startp;
|
char *startp;
|
||||||
int namelen;
|
int namelen;
|
||||||
|
|
||||||
ancnt = 1;
|
ancnt = 1;
|
||||||
while (1) {
|
while (1) {
|
||||||
CHECKLEN(10);
|
CHECKLEN(10);
|
||||||
putshort(&p, name);
|
putshort(&p, name);
|
||||||
putshort(&p, q->type);
|
putshort(&p, q->type);
|
||||||
putshort(&p, C_IN);
|
putshort(&p, C_IN);
|
||||||
putlong(&p, 0); /* TTL */
|
putlong(&p, 0); /* TTL */
|
||||||
|
|
||||||
startp = p;
|
startp = p;
|
||||||
p += 2; /* skip 2 bytes length */
|
p += 2; /* skip 2 bytes length */
|
||||||
CHECKLEN(2);
|
CHECKLEN(2);
|
||||||
putshort(&p, 10 * ancnt); /* preference */
|
putshort(&p, 10 * ancnt); /* preference */
|
||||||
|
|
||||||
if (q->type == T_SRV) {
|
if (q->type == T_SRV) {
|
||||||
/* weight, port (5060 = SIP) */
|
/* weight, port (5060 = SIP) */
|
||||||
|
@ -156,13 +163,13 @@ dns_encode(char *buf, size_t buflen, struct query *q, qr_t qr, char *data, size_
|
||||||
int txtlen;
|
int txtlen;
|
||||||
|
|
||||||
CHECKLEN(10);
|
CHECKLEN(10);
|
||||||
putshort(&p, name);
|
putshort(&p, name);
|
||||||
putshort(&p, q->type);
|
putshort(&p, q->type);
|
||||||
putshort(&p, C_IN);
|
putshort(&p, C_IN);
|
||||||
putlong(&p, 0); /* TTL */
|
putlong(&p, 0); /* TTL */
|
||||||
|
|
||||||
startp = p;
|
startp = p;
|
||||||
p += 2; /* skip 2 bytes length */
|
p += 2; /* skip 2 bytes length */
|
||||||
puttxtbin(&p, buflen - (p - buf), data, datalen);
|
puttxtbin(&p, buflen - (p - buf), data, datalen);
|
||||||
CHECKLEN(0);
|
CHECKLEN(0);
|
||||||
txtlen = p - startp;
|
txtlen = p - startp;
|
||||||
|
@ -171,12 +178,11 @@ dns_encode(char *buf, size_t buflen, struct query *q, qr_t qr, char *data, size_
|
||||||
ancnt = 1;
|
ancnt = 1;
|
||||||
} else {
|
} else {
|
||||||
/* NULL has raw binary data */
|
/* NULL has raw binary data */
|
||||||
|
|
||||||
CHECKLEN(10);
|
CHECKLEN(10);
|
||||||
putshort(&p, name);
|
putshort(&p, name);
|
||||||
putshort(&p, q->type);
|
putshort(&p, q->type);
|
||||||
putshort(&p, C_IN);
|
putshort(&p, C_IN);
|
||||||
putlong(&p, 0); /* TTL */
|
putlong(&p, 0); /* TTL */
|
||||||
|
|
||||||
datalen = MIN(datalen, buflen - (p - buf));
|
datalen = MIN(datalen, buflen - (p - buf));
|
||||||
CHECKLEN(2);
|
CHECKLEN(2);
|
||||||
|
@ -192,7 +198,7 @@ dns_encode(char *buf, size_t buflen, struct query *q, qr_t qr, char *data, size_
|
||||||
/* Note that iodined also uses this for forward queries */
|
/* Note that iodined also uses this for forward queries */
|
||||||
|
|
||||||
header->qdcount = htons(1);
|
header->qdcount = htons(1);
|
||||||
|
|
||||||
datalen = MIN(datalen, buflen - (p - buf));
|
datalen = MIN(datalen, buflen - (p - buf));
|
||||||
putname(&p, datalen, data);
|
putname(&p, datalen, data);
|
||||||
|
|
||||||
|
@ -204,29 +210,27 @@ dns_encode(char *buf, size_t buflen, struct query *q, qr_t qr, char *data, size_
|
||||||
(even CNAME/A/MX, 255+255+header would be >512) */
|
(even CNAME/A/MX, 255+255+header would be >512) */
|
||||||
if (dnsc_use_edns0) {
|
if (dnsc_use_edns0) {
|
||||||
header->arcount = htons(1);
|
header->arcount = htons(1);
|
||||||
/*XXX START adjust indent 1 tab forward*/
|
CHECKLEN(11);
|
||||||
CHECKLEN(11);
|
putbyte(&p, 0x00); /* Root */
|
||||||
putbyte(&p, 0x00); /* Root */
|
putshort(&p, 0x0029); /* OPT */
|
||||||
putshort(&p, 0x0029); /* OPT */
|
putshort(&p, 0x1000); /* Payload size: 4096 */
|
||||||
putshort(&p, 0x1000); /* Payload size: 4096 */
|
putshort(&p, 0x0000); /* Higher bits/edns version */
|
||||||
putshort(&p, 0x0000); /* Higher bits/edns version */
|
putshort(&p, 0x8000); /* Z */
|
||||||
putshort(&p, 0x8000); /* Z */
|
putshort(&p, 0x0000); /* Data length */
|
||||||
putshort(&p, 0x0000); /* Data length */
|
|
||||||
/*XXX END adjust indent 1 tab forward*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = p - buf;
|
len = p - buf;
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
dns_encode_ns_response(char *buf, size_t buflen, struct query *q, char *topdomain)
|
|
||||||
/* Only used when iodined gets an NS type query */
|
/* Only used when iodined gets an NS type query */
|
||||||
/* Mostly same as dns_encode_a_response() below */
|
/* Mostly same as dns_encode_a_response() below */
|
||||||
|
int dns_encode_ns_response(char *buf, size_t buflen, struct query *q,
|
||||||
|
char *topdomain)
|
||||||
{
|
{
|
||||||
HEADER *header;
|
HEADER *header;
|
||||||
int len;
|
int len;
|
||||||
|
@ -241,9 +245,9 @@ dns_encode_ns_response(char *buf, size_t buflen, struct query *q, char *topdomai
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
memset(buf, 0, buflen);
|
memset(buf, 0, buflen);
|
||||||
|
|
||||||
header = (HEADER*)buf;
|
header = (HEADER*)buf;
|
||||||
|
|
||||||
header->id = htons(q->id);
|
header->id = htons(q->id);
|
||||||
header->qr = 1;
|
header->qr = 1;
|
||||||
header->opcode = 0;
|
header->opcode = 0;
|
||||||
|
@ -256,7 +260,6 @@ dns_encode_ns_response(char *buf, size_t buflen, struct query *q, char *topdomai
|
||||||
|
|
||||||
header->qdcount = htons(1);
|
header->qdcount = htons(1);
|
||||||
header->ancount = htons(1);
|
header->ancount = htons(1);
|
||||||
header->arcount = htons(1);
|
|
||||||
|
|
||||||
/* pointer to start of name */
|
/* pointer to start of name */
|
||||||
name = 0xc000 | ((p - buf) & 0x3fff);
|
name = 0xc000 | ((p - buf) & 0x3fff);
|
||||||
|
@ -295,44 +298,56 @@ dns_encode_ns_response(char *buf, size_t buflen, struct query *q, char *topdomai
|
||||||
putbyte(&p, 's');
|
putbyte(&p, 's');
|
||||||
putshort(&p, topname); /* Name Server */
|
putshort(&p, topname); /* Name Server */
|
||||||
|
|
||||||
/* Additional data (A-record of NS server) */
|
/* Do we have an IPv4 address to send? */
|
||||||
CHECKLEN(12);
|
if (q->destination.ss_family == AF_INET) {
|
||||||
putshort(&p, nsname); /* Name Server */
|
struct sockaddr_in *dest = (struct sockaddr_in *) &q->destination;
|
||||||
putshort(&p, T_A); /* Type */
|
|
||||||
putshort(&p, C_IN); /* Class */
|
|
||||||
putlong(&p, 3600); /* TTL */
|
|
||||||
putshort(&p, 4); /* Data length */
|
|
||||||
|
|
||||||
/* ugly hack to output IP address */
|
/* One additional record coming */
|
||||||
ipp = (char *) &q->destination;
|
header->arcount = htons(1);
|
||||||
CHECKLEN(4);
|
|
||||||
putbyte(&p, *(ipp++));
|
/* Additional data (A-record of NS server) */
|
||||||
putbyte(&p, *(ipp++));
|
CHECKLEN(12);
|
||||||
putbyte(&p, *(ipp++));
|
putshort(&p, nsname); /* Name Server */
|
||||||
putbyte(&p, *ipp);
|
putshort(&p, T_A); /* Type */
|
||||||
|
putshort(&p, C_IN); /* Class */
|
||||||
|
putlong(&p, 3600); /* TTL */
|
||||||
|
putshort(&p, 4); /* Data length */
|
||||||
|
|
||||||
|
/* ugly hack to output IP address */
|
||||||
|
ipp = (char *) &dest->sin_addr.s_addr;
|
||||||
|
CHECKLEN(4);
|
||||||
|
putbyte(&p, *(ipp++));
|
||||||
|
putbyte(&p, *(ipp++));
|
||||||
|
putbyte(&p, *(ipp++));
|
||||||
|
putbyte(&p, *ipp);
|
||||||
|
}
|
||||||
|
|
||||||
len = p - buf;
|
len = p - buf;
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
/* Only used when iodined gets an A type query for ns.topdomain or
|
||||||
dns_encode_a_response(char *buf, size_t buflen, struct query *q)
|
* www.topdomain . Mostly same as dns_encode_ns_response() above */
|
||||||
/* Only used when iodined gets an A type query for ns.topdomain or www.topdomain */
|
int dns_encode_a_response(char *buf, size_t buflen, struct query *q)
|
||||||
/* Mostly same as dns_encode_ns_response() above */
|
|
||||||
{
|
{
|
||||||
|
struct sockaddr_in *dest = (struct sockaddr_in *) &q->destination;
|
||||||
HEADER *header;
|
HEADER *header;
|
||||||
int len;
|
int len;
|
||||||
short name;
|
short name;
|
||||||
char *ipp;
|
char *ipp;
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
|
/* Check if we have an IPv4 address to send */
|
||||||
|
if (q->destination.ss_family != AF_INET)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (buflen < sizeof(HEADER))
|
if (buflen < sizeof(HEADER))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
memset(buf, 0, buflen);
|
memset(buf, 0, buflen);
|
||||||
|
|
||||||
header = (HEADER*)buf;
|
header = (HEADER*)buf;
|
||||||
|
|
||||||
header->id = htons(q->id);
|
header->id = htons(q->id);
|
||||||
header->qr = 1;
|
header->qr = 1;
|
||||||
header->opcode = 0;
|
header->opcode = 0;
|
||||||
|
@ -350,21 +365,21 @@ dns_encode_a_response(char *buf, size_t buflen, struct query *q)
|
||||||
name = 0xc000 | ((p - buf) & 0x3fff);
|
name = 0xc000 | ((p - buf) & 0x3fff);
|
||||||
|
|
||||||
/* Query section */
|
/* Query section */
|
||||||
putname(&p, buflen - (p - buf), q->name); /* Name */
|
putname(&p, buflen - (p - buf), q->name); /* Name */
|
||||||
CHECKLEN(4);
|
CHECKLEN(4);
|
||||||
putshort(&p, q->type); /* Type */
|
putshort(&p, q->type); /* Type */
|
||||||
putshort(&p, C_IN); /* Class */
|
putshort(&p, C_IN); /* Class */
|
||||||
|
|
||||||
/* Answer section */
|
/* Answer section */
|
||||||
CHECKLEN(12);
|
CHECKLEN(12);
|
||||||
putshort(&p, name); /* Name */
|
putshort(&p, name); /* Name */
|
||||||
putshort(&p, q->type); /* Type */
|
putshort(&p, q->type); /* Type */
|
||||||
putshort(&p, C_IN); /* Class */
|
putshort(&p, C_IN); /* Class */
|
||||||
putlong(&p, 3600); /* TTL */
|
putlong(&p, 3600); /* TTL */
|
||||||
putshort(&p, 4); /* Data length */
|
putshort(&p, 4); /* Data length */
|
||||||
|
|
||||||
/* ugly hack to output IP address */
|
/* ugly hack to output IP address */
|
||||||
ipp = (char *) &q->destination;
|
ipp = (char *) &dest->sin_addr.s_addr;
|
||||||
CHECKLEN(4);
|
CHECKLEN(4);
|
||||||
putbyte(&p, *(ipp++));
|
putbyte(&p, *(ipp++));
|
||||||
putbyte(&p, *(ipp++));
|
putbyte(&p, *(ipp++));
|
||||||
|
@ -377,8 +392,7 @@ dns_encode_a_response(char *buf, size_t buflen, struct query *q)
|
||||||
|
|
||||||
#undef CHECKLEN
|
#undef CHECKLEN
|
||||||
|
|
||||||
unsigned short
|
unsigned short dns_get_id(char *packet, size_t packetlen)
|
||||||
dns_get_id(char *packet, size_t packetlen)
|
|
||||||
{
|
{
|
||||||
HEADER *header;
|
HEADER *header;
|
||||||
header = (HEADER*)packet;
|
header = (HEADER*)packet;
|
||||||
|
@ -389,10 +403,10 @@ dns_get_id(char *packet, size_t packetlen)
|
||||||
return ntohs(header->id);
|
return ntohs(header->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CHECKLEN(x) if (packetlen - (data-packet) < (x)) return 0
|
#define CHECKLEN(x) if (packetlen < (x) + (size_t)(data-packet)) return 0
|
||||||
|
|
||||||
int
|
int dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet,
|
||||||
dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, size_t packetlen)
|
size_t packetlen)
|
||||||
{
|
{
|
||||||
char name[QUERY_NAME_SIZE];
|
char name[QUERY_NAME_SIZE];
|
||||||
char rdata[4*1024];
|
char rdata[4*1024];
|
||||||
|
@ -400,11 +414,11 @@ dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, siz
|
||||||
short qdcount;
|
short qdcount;
|
||||||
short ancount;
|
short ancount;
|
||||||
uint32_t ttl;
|
uint32_t ttl;
|
||||||
short class;
|
unsigned short class;
|
||||||
short type;
|
unsigned short type;
|
||||||
char *data;
|
char *data;
|
||||||
short rlen;
|
unsigned short rlen;
|
||||||
int id;
|
int id;
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
q->id2 = 0;
|
q->id2 = 0;
|
||||||
|
@ -412,9 +426,9 @@ dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, siz
|
||||||
header = (HEADER*)packet;
|
header = (HEADER*)packet;
|
||||||
|
|
||||||
/* Reject short packets */
|
/* Reject short packets */
|
||||||
if (packetlen < sizeof(HEADER))
|
if (packetlen < sizeof(HEADER))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (header->qr != qr) {
|
if (header->qr != qr) {
|
||||||
warnx("header->qr does not match the requested qr");
|
warnx("header->qr does not match the requested qr");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -423,23 +437,23 @@ dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, siz
|
||||||
data = packet + sizeof(HEADER);
|
data = packet + sizeof(HEADER);
|
||||||
qdcount = ntohs(header->qdcount);
|
qdcount = ntohs(header->qdcount);
|
||||||
ancount = ntohs(header->ancount);
|
ancount = ntohs(header->ancount);
|
||||||
|
|
||||||
id = ntohs(header->id);
|
id = ntohs(header->id);
|
||||||
id = id & 0xFFFF; /* Kill any sign extension */
|
id = id & 0xFFFF; /* Kill any sign extension */
|
||||||
|
|
||||||
rlen = 0;
|
rlen = 0;
|
||||||
|
|
||||||
if (q != NULL)
|
if (q != NULL)
|
||||||
q->rcode = header->rcode;
|
q->rcode = header->rcode;
|
||||||
|
|
||||||
switch (qr) {
|
switch (qr) {
|
||||||
case QR_ANSWER:
|
case QR_ANSWER:
|
||||||
if(qdcount < 1) {
|
if (qdcount < 1) {
|
||||||
/* We need a question */
|
/* We need a question */
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (q != NULL)
|
if (q != NULL)
|
||||||
q->id = id;
|
q->id = id;
|
||||||
|
|
||||||
/* Read name even if no answer, to give better error message */
|
/* Read name even if no answer, to give better error message */
|
||||||
|
@ -447,14 +461,14 @@ dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, siz
|
||||||
CHECKLEN(4);
|
CHECKLEN(4);
|
||||||
readshort(packet, &data, &type);
|
readshort(packet, &data, &type);
|
||||||
readshort(packet, &data, &class);
|
readshort(packet, &data, &class);
|
||||||
|
|
||||||
/* if CHECKLEN okay, then we're sure to have a proper name */
|
/* if CHECKLEN okay, then we're sure to have a proper name */
|
||||||
if (q != NULL) {
|
if (q != NULL) {
|
||||||
/* We only need the first char to check it */
|
/* We only need the first char to check it */
|
||||||
q->name[0] = name[0];
|
q->name[0] = name[0];
|
||||||
q->name[1] = '\0';
|
q->name[1] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ancount < 1) {
|
if (ancount < 1) {
|
||||||
/* DNS errors like NXDOMAIN have ancount=0 and
|
/* DNS errors like NXDOMAIN have ancount=0 and
|
||||||
stop here. CNAME may also have A; MX/SRV may have
|
stop here. CNAME may also have A; MX/SRV may have
|
||||||
|
@ -463,7 +477,7 @@ dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, siz
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Here type is still the question type */
|
/* Here type is still the question type */
|
||||||
if (type == T_NULL) {
|
if (type == T_NULL || type == T_PRIVATE) {
|
||||||
/* Assume that first answer is what we wanted */
|
/* Assume that first answer is what we wanted */
|
||||||
readname(packet, packetlen, &data, name, sizeof(name));
|
readname(packet, packetlen, &data, name, sizeof(name));
|
||||||
CHECKLEN(10);
|
CHECKLEN(10);
|
||||||
|
@ -490,12 +504,27 @@ dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, siz
|
||||||
readlong(packet, &data, &ttl);
|
readlong(packet, &data, &ttl);
|
||||||
readshort(packet, &data, &rlen);
|
readshort(packet, &data, &rlen);
|
||||||
|
|
||||||
memset(name, 0, sizeof(name));
|
if (type == T_CNAME) {
|
||||||
readname(packet, packetlen, &data, name, sizeof(name) - 1);
|
/* For tunnels, query type A has CNAME type answer */
|
||||||
name[sizeof(name)-1] = '\0';
|
memset(name, 0, sizeof(name));
|
||||||
strncpy(buf, name, buflen);
|
readname(packet, packetlen, &data, name, sizeof(name) - 1);
|
||||||
buf[buflen - 1] = '\0';
|
name[sizeof(name)-1] = '\0';
|
||||||
rv = strlen(buf);
|
strncpy(buf, name, buflen);
|
||||||
|
buf[buflen - 1] = '\0';
|
||||||
|
rv = strlen(buf);
|
||||||
|
}
|
||||||
|
if (type == T_A) {
|
||||||
|
/* Answer type A includes only 4 bytes.
|
||||||
|
Not used for tunneling. */
|
||||||
|
rv = MIN(rlen, sizeof(rdata));
|
||||||
|
rv = readdata(packet, &data, rdata, rv);
|
||||||
|
if (rv >= 2 && buf) {
|
||||||
|
rv = MIN(rv, buflen);
|
||||||
|
memcpy(buf, rdata, rv);
|
||||||
|
} else {
|
||||||
|
rv = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if ((type == T_MX || type == T_SRV) && buf) {
|
else if ((type == T_MX || type == T_SRV) && buf) {
|
||||||
/* We support 250 records, 250*(255+header) ~= 64kB.
|
/* We support 250 records, 250*(255+header) ~= 64kB.
|
||||||
|
@ -505,13 +534,13 @@ dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, siz
|
||||||
*/
|
*/
|
||||||
char names[250][QUERY_NAME_SIZE];
|
char names[250][QUERY_NAME_SIZE];
|
||||||
char *rdatastart;
|
char *rdatastart;
|
||||||
short pref;
|
unsigned short pref;
|
||||||
int i;
|
int i;
|
||||||
int offset;
|
int offset;
|
||||||
|
|
||||||
memset(names, 0, sizeof(names));
|
memset(names, 0, sizeof(names));
|
||||||
|
|
||||||
for (i=0; i < ancount; i++) {
|
for (i = 0; i < ancount; i++) {
|
||||||
readname(packet, packetlen, &data, name, sizeof(name));
|
readname(packet, packetlen, &data, name, sizeof(name));
|
||||||
CHECKLEN(12);
|
CHECKLEN(12);
|
||||||
readshort(packet, &data, &type);
|
readshort(packet, &data, &type);
|
||||||
|
@ -532,10 +561,11 @@ dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, siz
|
||||||
readname(packet, packetlen, &data,
|
readname(packet, packetlen, &data,
|
||||||
names[pref / 10 - 1],
|
names[pref / 10 - 1],
|
||||||
QUERY_NAME_SIZE - 1);
|
QUERY_NAME_SIZE - 1);
|
||||||
names[pref / 10 - 1][QUERY_NAME_SIZE-1] = '\0';
|
names[pref / 10 - 1]
|
||||||
|
[QUERY_NAME_SIZE-1] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
/* always trust rlen, not name encoding */
|
/* always trust rlen, not name encoding */
|
||||||
data = rdatastart + rlen;
|
data = rdatastart + rlen;
|
||||||
CHECKLEN(0);
|
CHECKLEN(0);
|
||||||
}
|
}
|
||||||
|
@ -565,7 +595,8 @@ dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, siz
|
||||||
readlong(packet, &data, &ttl);
|
readlong(packet, &data, &ttl);
|
||||||
readshort(packet, &data, &rlen);
|
readshort(packet, &data, &rlen);
|
||||||
|
|
||||||
rv = readtxtbin(packet, &data, rlen, rdata, sizeof(rdata));
|
rv = readtxtbin(packet, &data, rlen, rdata,
|
||||||
|
sizeof(rdata));
|
||||||
if (rv >= 1) {
|
if (rv >= 1) {
|
||||||
rv = MIN(rv, buflen);
|
rv = MIN(rv, buflen);
|
||||||
memcpy(buf, rdata, rv);
|
memcpy(buf, rdata, rv);
|
||||||
|
|
10
src/dns.h
10
src/dns.h
|
@ -1,7 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
|
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||||
|
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
* copyright notice and this permission notice appear in all copies.
|
* copyright notice and this permission notice appear in all copies.
|
||||||
*
|
*
|
||||||
|
@ -26,8 +27,9 @@ typedef enum {
|
||||||
|
|
||||||
extern int dnsc_use_edns0;
|
extern int dnsc_use_edns0;
|
||||||
|
|
||||||
int dns_encode(char *, size_t, struct query *, qr_t, char *, size_t);
|
int dns_encode(char *, size_t, struct query *, qr_t, const char *, size_t);
|
||||||
int dns_encode_ns_response(char *buf, size_t buflen, struct query *q, char *topdomain);
|
int dns_encode_ns_response(char *buf, size_t buflen, struct query *q,
|
||||||
|
char *topdomain);
|
||||||
int dns_encode_a_response(char *buf, size_t buflen, struct query *q);
|
int dns_encode_a_response(char *buf, size_t buflen, struct query *q);
|
||||||
unsigned short dns_get_id(char *packet, size_t packetlen);
|
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);
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
|
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||||
|
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
* copyright notice and this permission notice appear in all copies.
|
* copyright notice and this permission notice appear in all copies.
|
||||||
*
|
*
|
||||||
|
@ -18,26 +19,24 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "encoding.h"
|
#include "encoding.h"
|
||||||
|
|
||||||
int
|
int build_hostname(char *buf, size_t buflen, const char *data,
|
||||||
build_hostname(char *buf, size_t buflen,
|
const size_t datalen, const char *topdomain,
|
||||||
const char *data, const size_t datalen,
|
const struct encoder *encoder, int maxlen)
|
||||||
const char *topdomain, struct encoder *encoder, int maxlen)
|
|
||||||
{
|
{
|
||||||
int encsize;
|
|
||||||
size_t space;
|
size_t space;
|
||||||
char *b;
|
char *b;
|
||||||
|
|
||||||
space = MIN(maxlen, buflen) - strlen(topdomain) - 8;
|
space = MIN((size_t)maxlen, buflen) - strlen(topdomain) - 8;
|
||||||
/* 8 = 5 max header length + 1 dot before topdomain + 2 safety */
|
/* 8 = 5 max header length + 1 dot before topdomain + 2 safety */
|
||||||
|
|
||||||
if (!encoder->places_dots())
|
if (!encoder->places_dots)
|
||||||
space -= (space / 57); /* space for dots */
|
space -= (space / 57); /* space for dots */
|
||||||
|
|
||||||
memset(buf, 0, buflen);
|
memset(buf, 0, buflen);
|
||||||
|
|
||||||
encsize = encoder->encode(buf, &space, data, datalen);
|
|
||||||
|
|
||||||
if (!encoder->places_dots())
|
encoder->encode(buf, &space, data, datalen);
|
||||||
|
|
||||||
|
if (!encoder->places_dots)
|
||||||
inline_dotify(buf, buflen);
|
inline_dotify(buf, buflen);
|
||||||
|
|
||||||
b = buf;
|
b = buf;
|
||||||
|
@ -45,7 +44,7 @@ build_hostname(char *buf, size_t buflen,
|
||||||
|
|
||||||
/* move b back one step to see if the dot is there */
|
/* move b back one step to see if the dot is there */
|
||||||
b--;
|
b--;
|
||||||
if (*b != '.')
|
if (*b != '.')
|
||||||
*++b = '.';
|
*++b = '.';
|
||||||
b++;
|
b++;
|
||||||
/* move b ahead of the string so we can copy to it */
|
/* move b ahead of the string so we can copy to it */
|
||||||
|
@ -55,16 +54,15 @@ build_hostname(char *buf, size_t buflen,
|
||||||
return space;
|
return space;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int unpack_data(char *buf, size_t buflen, char *data, size_t datalen,
|
||||||
unpack_data(char *buf, size_t buflen, char *data, size_t datalen, struct encoder *enc)
|
const struct encoder *enc)
|
||||||
{
|
{
|
||||||
if (!enc->eats_dots())
|
if (!enc->eats_dots)
|
||||||
datalen = inline_undotify(data, datalen);
|
datalen = inline_undotify(data, datalen);
|
||||||
return enc->decode(buf, &buflen, data, datalen);
|
return enc->decode(buf, &buflen, data, datalen);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int inline_dotify(char *buf, size_t buflen)
|
||||||
inline_dotify(char *buf, size_t buflen)
|
|
||||||
{
|
{
|
||||||
unsigned dots;
|
unsigned dots;
|
||||||
unsigned pos;
|
unsigned pos;
|
||||||
|
@ -101,8 +99,7 @@ inline_dotify(char *buf, size_t buflen)
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int inline_undotify(char *buf, size_t len)
|
||||||
inline_undotify(char *buf, size_t len)
|
|
||||||
{
|
{
|
||||||
unsigned pos;
|
unsigned pos;
|
||||||
unsigned dots;
|
unsigned dots;
|
||||||
|
@ -124,7 +121,7 @@ inline_undotify(char *buf, size_t len)
|
||||||
*writer++ = *reader++;
|
*writer++ = *reader++;
|
||||||
pos++;
|
pos++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return new length of string */
|
/* return new length of string */
|
||||||
return len - dots;
|
return len - dots;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,14 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
|
* Copyright (c) 2006-2014 Erik Ekman
|
||||||
|
* 2006-2009 Bjorn Andersson
|
||||||
|
* Copyright (c) 2017 Ralf Ramsauer
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Authors:
|
||||||
|
* Bjorn Andersson <flex@kryo.se>
|
||||||
|
* Erok Ekman <yarrick@kryo.se>,
|
||||||
|
* Ralf Ramsauer <ralf@ramses-pyramidenbau.de>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or 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
|
||||||
* copyright notice and this permission notice appear in all copies.
|
* copyright notice and this permission notice appear in all copies.
|
||||||
*
|
*
|
||||||
|
@ -17,27 +24,42 @@
|
||||||
#ifndef _ENCODING_H_
|
#ifndef _ENCODING_H_
|
||||||
#define _ENCODING_H_
|
#define _ENCODING_H_
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
/* All-0, all-1, 01010101, 10101010: each 4 times to make sure the pattern
|
/* All-0, all-1, 01010101, 10101010: each 4 times to make sure the pattern
|
||||||
spreads across multiple encoded chars -> 16 bytes total.
|
spreads across multiple encoded chars -> 16 bytes total.
|
||||||
Followed by 32 bytes from my /dev/random; should be enough.
|
Followed by 32 bytes from my /dev/random; should be enough.
|
||||||
*/
|
*/
|
||||||
#define DOWNCODECCHECK1 "\000\000\000\000\377\377\377\377\125\125\125\125\252\252\252\252\201\143\310\322\307\174\262\027\137\117\316\311\111\055\122\041\141\251\161\040\045\263\006\163\346\330\104\060\171\120\127\277"
|
#define DOWNCODECCHECK1 \
|
||||||
|
"\000\000\000\000\377\377\377\377\125\125\125\125\252\252\252\252" \
|
||||||
|
"\201\143\310\322\307\174\262\027\137\117\316\311\111\055\122\041" \
|
||||||
|
"\141\251\161\040\045\263\006\163\346\330\104\060\171\120\127\277"
|
||||||
#define DOWNCODECCHECK1_LEN 48
|
#define DOWNCODECCHECK1_LEN 48
|
||||||
|
|
||||||
struct encoder {
|
struct encoder {
|
||||||
char name[8];
|
const char name[8];
|
||||||
int (*encode) (char *, size_t *, const void *, size_t);
|
int (*encode)(char *dst, size_t *dstlen, const void *src, size_t srclen);
|
||||||
int (*decode) (void *, size_t *, const char *, size_t);
|
int (*decode)(void *dst, size_t *dstlen, const char *src, size_t srclen);
|
||||||
int (*places_dots) (void);
|
|
||||||
int (*eats_dots) (void);
|
const bool places_dots;
|
||||||
int (*blocksize_raw)(void);
|
const bool eats_dots;
|
||||||
int (*blocksize_encoded)(void);
|
|
||||||
|
const int blocksize_raw;
|
||||||
|
const int blocksize_encoded;
|
||||||
};
|
};
|
||||||
|
|
||||||
int build_hostname(char *, size_t, const char *, const size_t, const char *, struct encoder *, int);
|
int build_hostname(char *, size_t, const char *, const size_t, const char *,
|
||||||
int unpack_data(char *, size_t, char *, size_t, struct encoder *);
|
const struct encoder *, int);
|
||||||
|
int unpack_data(char *, size_t, char *, size_t, const struct encoder *);
|
||||||
int inline_dotify(char *, size_t);
|
int inline_dotify(char *, size_t);
|
||||||
int inline_undotify(char *, size_t);
|
int inline_undotify(char *, size_t);
|
||||||
|
|
||||||
|
extern const struct encoder base32_ops;
|
||||||
|
extern const struct encoder base64_ops;
|
||||||
|
extern const struct encoder base64u_ops;
|
||||||
|
extern const struct encoder base128_ops;
|
||||||
|
|
||||||
#endif /* _ENCODING_H_ */
|
int b32_5to8(int);
|
||||||
|
int b32_8to5(int);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Erik Ekman <yarrick@kryo.se>
|
* Copyright (c) 2008-2014 Erik Ekman <yarrick@kryo.se>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
* copyright notice and this permission notice appear in all copies.
|
* copyright notice and this permission notice appear in all copies.
|
||||||
*
|
*
|
||||||
|
@ -20,7 +20,7 @@
|
||||||
static struct fw_query fwq[FW_QUERY_CACHE_SIZE];
|
static struct fw_query fwq[FW_QUERY_CACHE_SIZE];
|
||||||
static int fwq_ix;
|
static int fwq_ix;
|
||||||
|
|
||||||
void fw_query_init()
|
void fw_query_init(void)
|
||||||
{
|
{
|
||||||
memset(fwq, 0, sizeof(struct fw_query) * FW_QUERY_CACHE_SIZE);
|
memset(fwq, 0, sizeof(struct fw_query) * FW_QUERY_CACHE_SIZE);
|
||||||
fwq_ix = 0;
|
fwq_ix = 0;
|
||||||
|
@ -29,9 +29,9 @@ void fw_query_init()
|
||||||
void fw_query_put(struct fw_query *fw_query)
|
void fw_query_put(struct fw_query *fw_query)
|
||||||
{
|
{
|
||||||
memcpy(&(fwq[fwq_ix]), fw_query, sizeof(struct fw_query));
|
memcpy(&(fwq[fwq_ix]), fw_query, sizeof(struct fw_query));
|
||||||
|
|
||||||
++fwq_ix;
|
++fwq_ix;
|
||||||
if (fwq_ix >= FW_QUERY_CACHE_SIZE)
|
if (fwq_ix >= FW_QUERY_CACHE_SIZE)
|
||||||
fwq_ix = 0;
|
fwq_ix = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Erik Ekman <yarrick@kryo.se>
|
* Copyright (c) 2008-2014 Erik Ekman <yarrick@kryo.se>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
* copyright notice and this permission notice appear in all copies.
|
* copyright notice and this permission notice appear in all copies.
|
||||||
*
|
*
|
||||||
|
@ -28,12 +28,12 @@
|
||||||
#define FW_QUERY_CACHE_SIZE 16
|
#define FW_QUERY_CACHE_SIZE 16
|
||||||
|
|
||||||
struct fw_query {
|
struct fw_query {
|
||||||
struct sockaddr addr;
|
struct sockaddr_storage addr;
|
||||||
int addrlen;
|
int addrlen;
|
||||||
unsigned short id;
|
unsigned short id;
|
||||||
};
|
};
|
||||||
|
|
||||||
void fw_query_init();
|
void fw_query_init(void);
|
||||||
void fw_query_put(struct fw_query *fw_query);
|
void fw_query_put(struct fw_query *fw_query);
|
||||||
void fw_query_get(unsigned short query_id, struct fw_query **fw_query);
|
void fw_query_get(unsigned short query_id, struct fw_query **fw_query);
|
||||||
|
|
||||||
|
|
216
src/iodine.c
216
src/iodine.c
|
@ -1,7 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
|
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||||
|
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
* copyright notice and this permission notice appear in all copies.
|
* copyright notice and this permission notice appear in all copies.
|
||||||
*
|
*
|
||||||
|
@ -14,6 +15,7 @@
|
||||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -32,6 +34,7 @@
|
||||||
#else
|
#else
|
||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
|
#include <netdb.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
@ -46,72 +49,83 @@ WSADATA wsa_data;
|
||||||
|
|
||||||
#if !defined(BSD) && !defined(__GLIBC__)
|
#if !defined(BSD) && !defined(__GLIBC__)
|
||||||
static char *__progname;
|
static char *__progname;
|
||||||
|
#else
|
||||||
|
extern char *__progname;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define PASSWORD_ENV_VAR "IODINE_PASS"
|
#define PASSWORD_ENV_VAR "IODINE_PASS"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sighandler(int sig)
|
sighandler(int sig)
|
||||||
{
|
{
|
||||||
client_stop();
|
client_stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
usage() {
|
/* mark as no return to help some compilers to avoid warnings
|
||||||
extern char *__progname;
|
* about use of uninitialized variables */
|
||||||
|
static inline void usage(void) __attribute__((noreturn));
|
||||||
|
static inline void help(FILE * stream, bool verbose) __attribute__((noreturn));
|
||||||
|
#endif
|
||||||
|
|
||||||
fprintf(stderr, "Usage: %s [-v] [-h] [-f] [-r] [-u user] [-t chrootdir] [-d device] "
|
static void help(FILE *stream, bool verbose)
|
||||||
"[-P password] [-m maxfragsize] [-M maxlen] [-T type] [-O enc] [-L 0|1] [-I sec] "
|
|
||||||
"[-z context] [-F pidfile] [nameserver] topdomain\n", __progname);
|
|
||||||
exit(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
help() {
|
|
||||||
extern char *__progname;
|
|
||||||
|
|
||||||
fprintf(stderr, "iodine IP over DNS tunneling client\n");
|
|
||||||
fprintf(stderr, "Usage: %s [-v] [-h] [-f] [-r] [-u user] [-t chrootdir] [-d device] "
|
|
||||||
"[-P password] [-m maxfragsize] [-M maxlen] [-T type] [-O enc] [-L 0|1] [-I sec] "
|
|
||||||
"[-z context] [-F pidfile] [nameserver] topdomain\n", __progname);
|
|
||||||
fprintf(stderr, "Options to try if connection doesn't work:\n");
|
|
||||||
fprintf(stderr, " -T force dns type: NULL, TXT, SRV, MX, CNAME, A (default: autodetect)\n");
|
|
||||||
fprintf(stderr, " -O force downstream encoding for -T other than NULL: Base32, Base64, Base64u,\n");
|
|
||||||
fprintf(stderr, " Base128, or (only for TXT:) Raw (default: autodetect)\n");
|
|
||||||
fprintf(stderr, " -I max interval between requests (default 4 sec) to prevent DNS timeouts\n");
|
|
||||||
fprintf(stderr, " -L 1: use lazy mode for low-latency (default). 0: don't (implies -I1)\n");
|
|
||||||
fprintf(stderr, " -m max size of downstream fragments (default: autodetect)\n");
|
|
||||||
fprintf(stderr, " -M max size of upstream hostnames (~100-255, default: 255)\n");
|
|
||||||
fprintf(stderr, " -r to skip raw UDP mode attempt\n");
|
|
||||||
fprintf(stderr, " -P password used for authentication (max 32 chars will be used)\n");
|
|
||||||
fprintf(stderr, "Other options:\n");
|
|
||||||
fprintf(stderr, " -v to print version info and exit\n");
|
|
||||||
fprintf(stderr, " -h to print this help and exit\n");
|
|
||||||
fprintf(stderr, " -f to keep running in foreground\n");
|
|
||||||
fprintf(stderr, " -u name to drop privileges and run as user 'name'\n");
|
|
||||||
fprintf(stderr, " -t dir to chroot to directory dir\n");
|
|
||||||
fprintf(stderr, " -d device to set tunnel device name\n");
|
|
||||||
fprintf(stderr, " -z context, to apply specified SELinux context after initialization\n");
|
|
||||||
fprintf(stderr, " -F pidfile to write pid to a file\n");
|
|
||||||
fprintf(stderr, "nameserver is the IP number/hostname of the relaying nameserver. if absent, /etc/resolv.conf is used\n");
|
|
||||||
fprintf(stderr, "topdomain is the FQDN that is delegated to the tunnel endpoint.\n");
|
|
||||||
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
version() {
|
|
||||||
fprintf(stderr, "iodine IP over DNS tunneling client\n");
|
|
||||||
fprintf(stderr, "version: 0.6.0-rc1 from 2010-02-13\n");
|
|
||||||
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char **argv)
|
|
||||||
{
|
{
|
||||||
char *nameserv_addr;
|
fprintf(stream,
|
||||||
|
"iodine IP over DNS tunneling client\n\n"
|
||||||
|
"Usage: %s [-46fhrv] [-u user] [-t chrootdir] [-d device] [-P password]\n"
|
||||||
|
" [-m maxfragsize] [-M maxlen] [-T type] [-O enc] [-L 0|1] [-I sec]\n"
|
||||||
|
" [-z context] [-F pidfile] [nameserver] topdomain\n", __progname);
|
||||||
|
|
||||||
|
if (!verbose)
|
||||||
|
exit(2);
|
||||||
|
|
||||||
|
fprintf(stream,
|
||||||
|
"\nOptions to try if connection doesn't work:\n"
|
||||||
|
" -4 to connect only to IPv4\n"
|
||||||
|
" -6 to connect only to IPv6\n"
|
||||||
|
" -T force dns type: NULL, PRIVATE, TXT, SRV, MX, CNAME, A (default: autodetect)\n"
|
||||||
|
" -O force downstream encoding for -T other than NULL: Base32, Base64, Base64u,\n"
|
||||||
|
" Base128, or (only for TXT:) Raw (default: autodetect)\n"
|
||||||
|
" -I max interval between requests (default 4 sec) to prevent DNS timeouts\n"
|
||||||
|
" -L 1: use lazy mode for low-latency (default). 0: don't (implies -I1)\n"
|
||||||
|
" -m max size of downstream fragments (default: autodetect)\n"
|
||||||
|
" -M max size of upstream hostnames (~100-255, default: 255)\n"
|
||||||
|
" -r to skip raw UDP mode attempt\n"
|
||||||
|
" -P password used for authentication (max 32 chars will be used)\n\n"
|
||||||
|
"Other options:\n"
|
||||||
|
" -v to print version info and exit\n"
|
||||||
|
" -h to print this help and exit\n"
|
||||||
|
" -f to keep running in foreground\n"
|
||||||
|
" -u name to drop privileges and run as user 'name'\n"
|
||||||
|
" -t dir to chroot to directory dir\n"
|
||||||
|
" -d device to set tunnel device name\n"
|
||||||
|
" -z context, to apply specified SELinux context after initialization\n"
|
||||||
|
" -F pidfile to write pid to a file\n\n"
|
||||||
|
"nameserver is the IP number/hostname of the relaying nameserver. If absent,\n"
|
||||||
|
" /etc/resolv.conf is used\n"
|
||||||
|
"topdomain is the FQDN that is delegated to the tunnel endpoint.\n");
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void usage(void)
|
||||||
|
{
|
||||||
|
help(stderr, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void version(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "iodine IP over DNS tunneling client\n"
|
||||||
|
"Git version: %s\n", GITREVISION);
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
char *nameserv_host;
|
||||||
char *topdomain;
|
char *topdomain;
|
||||||
|
char *errormsg;
|
||||||
#ifndef WINDOWS32
|
#ifndef WINDOWS32
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
#endif
|
#endif
|
||||||
|
@ -132,9 +146,16 @@ main(int argc, char **argv)
|
||||||
int lazymode;
|
int lazymode;
|
||||||
int selecttimeout;
|
int selecttimeout;
|
||||||
int hostname_maxlen;
|
int hostname_maxlen;
|
||||||
|
#ifdef OPENBSD
|
||||||
|
int rtable = 0;
|
||||||
|
#endif
|
||||||
|
struct sockaddr_storage nameservaddr;
|
||||||
|
int nameservaddr_len;
|
||||||
|
int nameserv_family;
|
||||||
|
|
||||||
nameserv_addr = NULL;
|
nameserv_host = NULL;
|
||||||
topdomain = NULL;
|
topdomain = NULL;
|
||||||
|
errormsg = NULL;
|
||||||
#ifndef WINDOWS32
|
#ifndef WINDOWS32
|
||||||
pw = NULL;
|
pw = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
@ -154,6 +175,7 @@ main(int argc, char **argv)
|
||||||
lazymode = 1;
|
lazymode = 1;
|
||||||
selecttimeout = 4;
|
selecttimeout = 4;
|
||||||
hostname_maxlen = 0xFF;
|
hostname_maxlen = 0xFF;
|
||||||
|
nameserv_family = AF_UNSPEC;
|
||||||
|
|
||||||
#ifdef WINDOWS32
|
#ifdef WINDOWS32
|
||||||
WSAStartup(req_version, &wsa_data);
|
WSAStartup(req_version, &wsa_data);
|
||||||
|
@ -161,7 +183,7 @@ main(int argc, char **argv)
|
||||||
|
|
||||||
srand((unsigned) time(NULL));
|
srand((unsigned) time(NULL));
|
||||||
client_init();
|
client_init();
|
||||||
|
|
||||||
#if !defined(BSD) && !defined(__GLIBC__)
|
#if !defined(BSD) && !defined(__GLIBC__)
|
||||||
__progname = strrchr(argv[0], '/');
|
__progname = strrchr(argv[0], '/');
|
||||||
if (__progname == NULL)
|
if (__progname == NULL)
|
||||||
|
@ -170,8 +192,14 @@ main(int argc, char **argv)
|
||||||
__progname++;
|
__progname++;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while ((choice = getopt(argc, argv, "vfhru:t:d:P:m:M:F:T:O:L:I:")) != -1) {
|
while ((choice = getopt(argc, argv, "46vfhru:t:d:R:P:m:M:F:T:O:L:I:")) != -1) {
|
||||||
switch(choice) {
|
switch(choice) {
|
||||||
|
case '4':
|
||||||
|
nameserv_family = AF_INET;
|
||||||
|
break;
|
||||||
|
case '6':
|
||||||
|
nameserv_family = AF_INET6;
|
||||||
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
version();
|
version();
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
|
@ -180,11 +208,12 @@ main(int argc, char **argv)
|
||||||
foreground = 1;
|
foreground = 1;
|
||||||
break;
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
help();
|
help(stdout, true);
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
raw_mode = 0;
|
raw_mode = 0;
|
||||||
|
break;
|
||||||
case 'u':
|
case 'u':
|
||||||
username = optarg;
|
username = optarg;
|
||||||
break;
|
break;
|
||||||
|
@ -194,12 +223,17 @@ main(int argc, char **argv)
|
||||||
case 'd':
|
case 'd':
|
||||||
device = optarg;
|
device = optarg;
|
||||||
break;
|
break;
|
||||||
|
#ifdef OPENBSD
|
||||||
|
case 'R':
|
||||||
|
rtable = atoi(optarg);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
case 'P':
|
case 'P':
|
||||||
strncpy(password, optarg, sizeof(password));
|
strncpy(password, optarg, sizeof(password));
|
||||||
password[sizeof(password)-1] = 0;
|
password[sizeof(password)-1] = 0;
|
||||||
|
|
||||||
/* XXX: find better way of cleaning up ps(1) */
|
/* XXX: find better way of cleaning up ps(1) */
|
||||||
memset(optarg, 0, strlen(optarg));
|
memset(optarg, 0, strlen(optarg));
|
||||||
break;
|
break;
|
||||||
case 'm':
|
case 'm':
|
||||||
autodetect_frag_size = 0;
|
autodetect_frag_size = 0;
|
||||||
|
@ -217,12 +251,13 @@ main(int argc, char **argv)
|
||||||
break;
|
break;
|
||||||
case 'F':
|
case 'F':
|
||||||
pidfile = optarg;
|
pidfile = optarg;
|
||||||
break;
|
break;
|
||||||
case 'T':
|
case 'T':
|
||||||
set_qtype(optarg);
|
if (client_set_qtype(optarg))
|
||||||
|
errx(5, "Invalid query type '%s'", optarg);
|
||||||
break;
|
break;
|
||||||
case 'O': /* not -D, is Debug in server */
|
case 'O': /* not -D, is Debug in server */
|
||||||
set_downenc(optarg);
|
client_set_downenc(optarg);
|
||||||
break;
|
break;
|
||||||
case 'L':
|
case 'L':
|
||||||
lazymode = atoi(optarg);
|
lazymode = atoi(optarg);
|
||||||
|
@ -243,19 +278,19 @@ main(int argc, char **argv)
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
check_superuser(usage);
|
check_superuser();
|
||||||
|
|
||||||
argc -= optind;
|
argc -= optind;
|
||||||
argv += optind;
|
argv += optind;
|
||||||
|
|
||||||
switch (argc) {
|
switch (argc) {
|
||||||
case 1:
|
case 1:
|
||||||
nameserv_addr = get_resolvconf_addr();
|
nameserv_host = get_resolvconf_addr();
|
||||||
topdomain = strdup(argv[0]);
|
topdomain = strdup(argv[0]);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
nameserv_addr = argv[0];
|
nameserv_host = argv[0];
|
||||||
topdomain = strdup(argv[1]);
|
topdomain = strdup(argv[1]);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -269,22 +304,21 @@ main(int argc, char **argv)
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nameserv_addr) {
|
if (nameserv_host) {
|
||||||
client_set_nameserver(nameserv_addr, DNS_PORT);
|
nameservaddr_len = get_addr(nameserv_host, DNS_PORT, nameserv_family, 0, &nameservaddr);
|
||||||
|
if (nameservaddr_len < 0) {
|
||||||
|
errx(1, "Cannot lookup nameserver '%s': %s ",
|
||||||
|
nameserv_host, gai_strerror(nameservaddr_len));
|
||||||
|
}
|
||||||
|
client_set_nameserver(&nameservaddr, nameservaddr_len);
|
||||||
} else {
|
} else {
|
||||||
warnx("No nameserver found - not connected to any network?\n");
|
warnx("No nameserver found - not connected to any network?\n");
|
||||||
usage();
|
usage();
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen(topdomain) <= 128) {
|
if (check_topdomain(topdomain, 0, &errormsg)) {
|
||||||
if(check_topdomain(topdomain)) {
|
warnx("Invalid topdomain: %s", errormsg);
|
||||||
warnx("Topdomain contains invalid characters.\n");
|
|
||||||
usage();
|
|
||||||
/* NOTREACHED */
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
warnx("Use a topdomain max 128 chars long.\n");
|
|
||||||
usage();
|
usage();
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
@ -293,7 +327,7 @@ main(int argc, char **argv)
|
||||||
client_set_lazymode(lazymode);
|
client_set_lazymode(lazymode);
|
||||||
client_set_topdomain(topdomain);
|
client_set_topdomain(topdomain);
|
||||||
client_set_hostname_maxlen(hostname_maxlen);
|
client_set_hostname_maxlen(hostname_maxlen);
|
||||||
|
|
||||||
if (username != NULL) {
|
if (username != NULL) {
|
||||||
#ifndef WINDOWS32
|
#ifndef WINDOWS32
|
||||||
if ((pw = getpwnam(username)) == NULL) {
|
if ((pw = getpwnam(username)) == NULL) {
|
||||||
|
@ -303,51 +337,55 @@ main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen(password) == 0) {
|
if (strlen(password) == 0) {
|
||||||
if (NULL != getenv(PASSWORD_ENV_VAR))
|
if (NULL != getenv(PASSWORD_ENV_VAR))
|
||||||
snprintf(password, sizeof(password), "%s", getenv(PASSWORD_ENV_VAR));
|
snprintf(password, sizeof(password), "%s", getenv(PASSWORD_ENV_VAR));
|
||||||
else
|
else
|
||||||
read_password(password, sizeof(password));
|
read_password(password, sizeof(password));
|
||||||
}
|
}
|
||||||
|
|
||||||
client_set_password(password);
|
client_set_password(password);
|
||||||
|
|
||||||
if ((tun_fd = open_tun(device)) == -1) {
|
if ((tun_fd = open_tun(device)) == -1) {
|
||||||
retval = 1;
|
retval = 1;
|
||||||
goto cleanup1;
|
goto cleanup1;
|
||||||
}
|
}
|
||||||
if ((dns_fd = open_dns(0, INADDR_ANY)) == -1) {
|
if ((dns_fd = open_dns_from_host(NULL, 0, nameservaddr.ss_family, AI_PASSIVE)) < 0) {
|
||||||
retval = 1;
|
retval = 1;
|
||||||
goto cleanup2;
|
goto cleanup2;
|
||||||
}
|
}
|
||||||
|
#ifdef OPENBSD
|
||||||
|
if (rtable > 0)
|
||||||
|
socket_setrtable(dns_fd, rtable);
|
||||||
|
#endif
|
||||||
|
|
||||||
signal(SIGINT, sighandler);
|
signal(SIGINT, sighandler);
|
||||||
signal(SIGTERM, sighandler);
|
signal(SIGTERM, sighandler);
|
||||||
|
|
||||||
fprintf(stderr, "Sending DNS queries for %s to %s\n",
|
fprintf(stderr, "Sending DNS queries for %s to %s\n",
|
||||||
topdomain, nameserv_addr);
|
topdomain, format_addr(&nameservaddr, nameservaddr_len));
|
||||||
|
|
||||||
if (client_handshake(dns_fd, raw_mode, autodetect_frag_size, max_downstream_frag_size)) {
|
if (client_handshake(dns_fd, raw_mode, autodetect_frag_size, max_downstream_frag_size)) {
|
||||||
retval = 1;
|
retval = 1;
|
||||||
goto cleanup2;
|
goto cleanup2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (client_get_conn() == CONN_RAW_UDP) {
|
if (client_get_conn() == CONN_RAW_UDP) {
|
||||||
fprintf(stderr, "Sending raw traffic directly to %s\n", client_get_raw_addr());
|
fprintf(stderr, "Sending raw traffic directly to %s\n", client_get_raw_addr());
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "Connection setup complete, transmitting data.\n");
|
fprintf(stderr, "Connection setup complete, transmitting data.\n");
|
||||||
|
|
||||||
if (foreground == 0)
|
if (foreground == 0)
|
||||||
do_detach();
|
do_detach();
|
||||||
|
|
||||||
if (pidfile != NULL)
|
if (pidfile != NULL)
|
||||||
do_pidfile(pidfile);
|
do_pidfile(pidfile);
|
||||||
|
|
||||||
if (newroot != NULL)
|
if (newroot != NULL)
|
||||||
do_chroot(newroot);
|
do_chroot(newroot);
|
||||||
|
|
||||||
if (username != NULL) {
|
if (username != NULL) {
|
||||||
#ifndef WINDOWS32
|
#ifndef WINDOWS32
|
||||||
gid_t gids[1];
|
gid_t gids[1];
|
||||||
|
|
1173
src/iodined.c
1173
src/iodined.c
File diff suppressed because it is too large
Load diff
17
src/login.c
17
src/login.c
|
@ -1,7 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
|
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||||
|
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
* copyright notice and this permission notice appear in all copies.
|
* copyright notice and this permission notice appear in all copies.
|
||||||
*
|
*
|
||||||
|
@ -20,16 +21,18 @@
|
||||||
#ifdef WINDOWS32
|
#ifdef WINDOWS32
|
||||||
#include "windows.h"
|
#include "windows.h"
|
||||||
#else
|
#else
|
||||||
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "login.h"
|
||||||
#include "md5.h"
|
#include "md5.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Needs a 16byte array for output, and 32 bytes password
|
* Needs a 16byte array for output, and 32 bytes password
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
login_calculate(char *buf, int buflen, const char *pass, int seed)
|
login_calculate(char *buf, int buflen, const char *pass, int seed)
|
||||||
{
|
{
|
||||||
unsigned char temp[32];
|
unsigned char temp[32];
|
||||||
md5_state_t ctx;
|
md5_state_t ctx;
|
||||||
|
@ -37,7 +40,7 @@ login_calculate(char *buf, int buflen, const char *pass, int seed)
|
||||||
int i;
|
int i;
|
||||||
int k;
|
int k;
|
||||||
|
|
||||||
if (buflen < 16)
|
if (buflen < 16)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
memcpy(temp, pass, 32);
|
memcpy(temp, pass, 32);
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
|
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||||
|
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
* copyright notice and this permission notice appear in all copies.
|
* copyright notice and this permission notice appear in all copies.
|
||||||
*
|
*
|
||||||
|
|
44
src/md5.c
44
src/md5.c
|
@ -157,18 +157,18 @@ md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
|
||||||
#endif
|
#endif
|
||||||
#if BYTE_ORDER <= 0 /* little-endian */
|
#if BYTE_ORDER <= 0 /* little-endian */
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* On little-endian machines, we can process properly aligned
|
* On little-endian machines, we can process properly aligned
|
||||||
* data without copying it.
|
* data without copying it.
|
||||||
*/
|
*/
|
||||||
if (!((data - (const md5_byte_t *)0) & 3)) {
|
if (!((data - (const md5_byte_t *)0) & 3)) {
|
||||||
/* data are properly aligned */
|
/* data are properly aligned */
|
||||||
X = (const md5_word_t *)data;
|
X = (const md5_word_t *)data;
|
||||||
} else {
|
} else {
|
||||||
/* not aligned */
|
/* not aligned */
|
||||||
memcpy(xbuf, data, 64);
|
memcpy(xbuf, data, 64);
|
||||||
X = xbuf;
|
X = xbuf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if BYTE_ORDER == 0
|
#if BYTE_ORDER == 0
|
||||||
|
@ -176,20 +176,20 @@ md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
|
||||||
#endif
|
#endif
|
||||||
#if BYTE_ORDER >= 0 /* big-endian */
|
#if BYTE_ORDER >= 0 /* big-endian */
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* On big-endian machines, we must arrange the bytes in the
|
* On big-endian machines, we must arrange the bytes in the
|
||||||
* right order.
|
* right order.
|
||||||
*/
|
*/
|
||||||
const md5_byte_t *xp = data;
|
const md5_byte_t *xp = data;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
# if BYTE_ORDER == 0
|
# if BYTE_ORDER == 0
|
||||||
X = xbuf; /* (dynamic only) */
|
X = xbuf; /* (dynamic only) */
|
||||||
# else
|
# else
|
||||||
# define xbuf X /* (static only) */
|
# define xbuf X /* (static only) */
|
||||||
# endif
|
# endif
|
||||||
for (i = 0; i < 16; ++i, xp += 4)
|
for (i = 0; i < 16; ++i, xp += 4)
|
||||||
xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
|
xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -342,7 +342,7 @@ md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
|
||||||
|
|
||||||
memcpy(pms->buf + offset, p, copy);
|
memcpy(pms->buf + offset, p, copy);
|
||||||
if (offset + copy < 64)
|
if (offset + copy < 64)
|
||||||
return;
|
return;
|
||||||
p += copy;
|
p += copy;
|
||||||
left -= copy;
|
left -= copy;
|
||||||
md5_process(pms, pms->buf);
|
md5_process(pms, pms->buf);
|
||||||
|
|
|
@ -71,7 +71,7 @@ typedef struct md5_state_s {
|
||||||
} md5_state_t;
|
} md5_state_t;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
28
src/osflags
28
src/osflags
|
@ -1,5 +1,7 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
|
: "${PKG_CONFIG:=pkg-config}"
|
||||||
|
|
||||||
case $2 in
|
case $2 in
|
||||||
link)
|
link)
|
||||||
|
|
||||||
|
@ -11,23 +13,43 @@ link)
|
||||||
echo '-lsocket -lbind -lbsd';
|
echo '-lsocket -lbind -lbsd';
|
||||||
;;
|
;;
|
||||||
Haiku)
|
Haiku)
|
||||||
echo '-lnetwork';
|
echo '-lnetwork -lbsd';
|
||||||
;;
|
;;
|
||||||
windows32)
|
windows32)
|
||||||
echo '-lws2_32 -liphlpapi';
|
echo '-lws2_32 -liphlpapi';
|
||||||
;;
|
;;
|
||||||
Linux)
|
Linux)
|
||||||
[ -e /usr/include/selinux/selinux.h ] && echo '-lselinux';
|
FLAGS="";
|
||||||
|
"$PKG_CONFIG" --exists libselinux && FLAGS="$FLAGS $($PKG_CONFIG --libs libselinux)";
|
||||||
|
"$PKG_CONFIG" --exists libsystemd-daemon && FLAGS="$FLAGS $($PKG_CONFIG --libs libsystemd-daemon)";
|
||||||
|
"$PKG_CONFIG" --exists libsystemd && FLAGS="$FLAGS $($PKG_CONFIG --libs libsystemd)";
|
||||||
|
echo $FLAGS;
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
cflags)
|
cflags)
|
||||||
case $1 in
|
case $1 in
|
||||||
|
windows32)
|
||||||
|
echo '-DWINVER=0x0501';
|
||||||
|
;;
|
||||||
BeOS)
|
BeOS)
|
||||||
echo '-Dsocklen_t=int';
|
echo '-Dsocklen_t=int';
|
||||||
;;
|
;;
|
||||||
|
Haiku)
|
||||||
|
echo '-D_DEFAULT_SOURCE';
|
||||||
|
;;
|
||||||
|
Darwin)
|
||||||
|
echo '-D__APPLE_USE_RFC_3542';
|
||||||
|
;;
|
||||||
Linux)
|
Linux)
|
||||||
[ -e /usr/include/selinux/selinux.h ] && echo '-DHAVE_SETCON';
|
FLAGS="-D_GNU_SOURCE"
|
||||||
|
"$PKG_CONFIG" --exists libselinux && FLAGS="$FLAGS -DHAVE_SETCON";
|
||||||
|
"$PKG_CONFIG" --exists libsystemd-daemon && FLAGS="$FLAGS -DHAVE_SYSTEMD";
|
||||||
|
"$PKG_CONFIG" --exists libsystemd && FLAGS="$FLAGS -DHAVE_SYSTEMD";
|
||||||
|
echo $FLAGS;
|
||||||
|
;;
|
||||||
|
GNU/kFreeBSD|GNU)
|
||||||
|
echo '-D_GNU_SOURCE'
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
|
|
35
src/read.c
35
src/read.c
|
@ -1,7 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
|
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||||
|
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
* copyright notice and this permission notice appear in all copies.
|
* copyright notice and this permission notice appear in all copies.
|
||||||
*
|
*
|
||||||
|
@ -18,6 +19,8 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "read.h"
|
||||||
|
|
||||||
static int
|
static int
|
||||||
readname_loop(char *packet, int packetlen, char **src, char *dst, size_t length, size_t loop)
|
readname_loop(char *packet, int packetlen, char **src, char *dst, size_t length, size_t loop)
|
||||||
{
|
{
|
||||||
|
@ -38,7 +41,7 @@ readname_loop(char *packet, int packetlen, char **src, char *dst, size_t length,
|
||||||
c = *s++;
|
c = *s++;
|
||||||
|
|
||||||
/* is this a compressed label? */
|
/* is this a compressed label? */
|
||||||
if((c & 0xc0) == 0xc0) {
|
if ((c & 0xc0) == 0xc0) {
|
||||||
offset = (((s[-1] & 0x3f) << 8) | (s[0] & 0xff));
|
offset = (((s[-1] & 0x3f) << 8) | (s[0] & 0xff));
|
||||||
if (offset > packetlen) {
|
if (offset > packetlen) {
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
|
@ -60,7 +63,7 @@ readname_loop(char *packet, int packetlen, char **src, char *dst, size_t length,
|
||||||
|
|
||||||
c--;
|
c--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len >= length - 1) {
|
if (len >= length - 1) {
|
||||||
break; /* We used up all space */
|
break; /* We used up all space */
|
||||||
}
|
}
|
||||||
|
@ -84,15 +87,15 @@ readname(char *packet, int packetlen, char **src, char *dst, size_t length)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
readshort(char *packet, char **src, short *dst)
|
readshort(char *packet, char **src, unsigned short *dst)
|
||||||
{
|
{
|
||||||
unsigned char *p;
|
unsigned char *p;
|
||||||
|
|
||||||
p = (unsigned char *) *src;
|
p = (unsigned char *) *src;
|
||||||
*dst = (p[0] << 8) | p[1];
|
*dst = (p[0] << 8) | p[1];
|
||||||
|
|
||||||
(*src) += sizeof(short);
|
(*src) += sizeof(unsigned short);
|
||||||
return sizeof(short);
|
return sizeof(unsigned short);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -103,8 +106,8 @@ readlong(char *packet, char **src, uint32_t *dst)
|
||||||
|
|
||||||
p = (unsigned char *) *src;
|
p = (unsigned char *) *src;
|
||||||
|
|
||||||
*dst = ((uint32_t)p[0] << 24)
|
*dst = ((uint32_t)p[0] << 24)
|
||||||
| ((uint32_t)p[1] << 16)
|
| ((uint32_t)p[1] << 16)
|
||||||
| ((uint32_t)p[2] << 8)
|
| ((uint32_t)p[2] << 8)
|
||||||
| ((uint32_t)p[3]);
|
| ((uint32_t)p[3]);
|
||||||
|
|
||||||
|
@ -115,9 +118,6 @@ readlong(char *packet, char **src, uint32_t *dst)
|
||||||
int
|
int
|
||||||
readdata(char *packet, char **src, char *dst, size_t len)
|
readdata(char *packet, char **src, char *dst, size_t len)
|
||||||
{
|
{
|
||||||
if (len < 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
memcpy(dst, *src, len);
|
memcpy(dst, *src, len);
|
||||||
|
|
||||||
(*src) += len;
|
(*src) += len;
|
||||||
|
@ -165,7 +165,7 @@ putname(char **buf, size_t buflen, const char *host)
|
||||||
h = strdup(host);
|
h = strdup(host);
|
||||||
left = buflen;
|
left = buflen;
|
||||||
p = *buf;
|
p = *buf;
|
||||||
|
|
||||||
word = strtok(h, ".");
|
word = strtok(h, ".");
|
||||||
while(word) {
|
while(word) {
|
||||||
if (strlen(word) > 63 || strlen(word) > left) {
|
if (strlen(word) > 63 || strlen(word) > left) {
|
||||||
|
@ -230,19 +230,16 @@ putlong(char **dst, uint32_t value)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
putdata(char **dst, char *data, size_t len)
|
putdata(char **dst, const char *data, size_t len)
|
||||||
{
|
{
|
||||||
if (len < 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
memcpy(*dst, data, len);
|
memcpy(*dst, data, len);
|
||||||
|
|
||||||
(*dst) += len;
|
(*dst) += len;
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
puttxtbin(char **buf, size_t bufremain, char *from, size_t fromremain)
|
puttxtbin(char **buf, size_t bufremain, const char *from, size_t fromremain)
|
||||||
{
|
{
|
||||||
unsigned char uc;
|
unsigned char uc;
|
||||||
unsigned char *ucp = &uc;
|
unsigned char *ucp = &uc;
|
||||||
|
|
11
src/read.h
11
src/read.h
|
@ -1,7 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
|
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||||
|
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
* copyright notice and this permission notice appear in all copies.
|
* copyright notice and this permission notice appear in all copies.
|
||||||
*
|
*
|
||||||
|
@ -18,7 +19,7 @@
|
||||||
#define _READ_H_
|
#define _READ_H_
|
||||||
|
|
||||||
int readname(char *, int, char **, char *, size_t);
|
int readname(char *, int, char **, char *, size_t);
|
||||||
int readshort(char *, char **, short *);
|
int readshort(char *, char **, unsigned short *);
|
||||||
int readlong(char *, char **, uint32_t *);
|
int readlong(char *, char **, uint32_t *);
|
||||||
int readdata(char *, char **, char *, size_t);
|
int readdata(char *, char **, char *, size_t);
|
||||||
int readtxtbin(char *, char **, size_t, char *, size_t);
|
int readtxtbin(char *, char **, size_t, char *, size_t);
|
||||||
|
@ -27,7 +28,7 @@ int putname(char **, size_t, const char *);
|
||||||
int putbyte(char **, unsigned char);
|
int putbyte(char **, unsigned char);
|
||||||
int putshort(char **, unsigned short);
|
int putshort(char **, unsigned short);
|
||||||
int putlong(char **, uint32_t);
|
int putlong(char **, uint32_t);
|
||||||
int putdata(char **, char *, size_t);
|
int putdata(char **, const char *, size_t);
|
||||||
int puttxtbin(char **, size_t, char *, size_t);
|
int puttxtbin(char **, size_t, const char *, size_t);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
485
src/tun.c
485
src/tun.c
|
@ -1,7 +1,9 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
|
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||||
|
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||||
|
* 2013 Peter Sagerson <psagers.github@ignorare.net>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
* copyright notice and this permission notice appear in all copies.
|
* copyright notice and this permission notice appear in all copies.
|
||||||
*
|
*
|
||||||
|
@ -24,13 +26,31 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
#ifdef WINDOWS32
|
#ifdef DARWIN
|
||||||
#include <winsock2.h>
|
#include <ctype.h>
|
||||||
#include <winioctl.h>
|
#include <sys/kern_control.h>
|
||||||
#include "windows.h"
|
#include <sys/sys_domain.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
/* Inline used parts of if_utun.h to compile without it. */
|
||||||
|
#define UTUN_CONTROL_NAME "com.apple.net.utun_control"
|
||||||
|
#define UTUN_OPT_IFNAME 2
|
||||||
|
#include <netinet/ip.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
HANDLE dev_handle;
|
#ifndef IFCONFIGPATH
|
||||||
struct tun_data data;
|
#define IFCONFIGPATH "PATH=/sbin:/bin "
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ROUTEPATH
|
||||||
|
#define ROUTEPATH "PATH=/sbin:/bin "
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WINDOWS32
|
||||||
|
#include "windows.h"
|
||||||
|
#include <winioctl.h>
|
||||||
|
|
||||||
|
static HANDLE dev_handle;
|
||||||
|
static struct tun_data data;
|
||||||
|
|
||||||
static void get_name(char *ifname, int namelen, char *dev_name);
|
static void get_name(char *ifname, int namelen, char *dev_name);
|
||||||
|
|
||||||
|
@ -43,12 +63,13 @@ static void get_name(char *ifname, int namelen, char *dev_name);
|
||||||
#define TAP_DEVICE_SPACE "\\\\.\\Global\\"
|
#define TAP_DEVICE_SPACE "\\\\.\\Global\\"
|
||||||
#define TAP_VERSION_ID_0801 "tap0801"
|
#define TAP_VERSION_ID_0801 "tap0801"
|
||||||
#define TAP_VERSION_ID_0901 "tap0901"
|
#define TAP_VERSION_ID_0901 "tap0901"
|
||||||
|
#define TAP_VERSION_ID_0901_ROOT "root\\tap0901"
|
||||||
#define KEY_COMPONENT_ID "ComponentId"
|
#define KEY_COMPONENT_ID "ComponentId"
|
||||||
#define NET_CFG_INST_ID "NetCfgInstanceId"
|
#define NET_CFG_INST_ID "NetCfgInstanceId"
|
||||||
#else
|
#else
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
#define TUN_MAX_TRY 50
|
#define TUN_MAX_TRY 50
|
||||||
#endif
|
#endif
|
||||||
|
@ -56,31 +77,34 @@ static void get_name(char *ifname, int namelen, char *dev_name);
|
||||||
#include "tun.h"
|
#include "tun.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
char if_name[250];
|
static char if_name[250];
|
||||||
|
|
||||||
#ifndef WINDOWS32
|
|
||||||
#ifdef LINUX
|
#ifdef LINUX
|
||||||
|
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <linux/if_tun.h>
|
#include <linux/if_tun.h>
|
||||||
|
|
||||||
int
|
int
|
||||||
open_tun(const char *tun_device)
|
open_tun(const char *tun_device)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int tun_fd;
|
int tun_fd;
|
||||||
struct ifreq ifreq;
|
struct ifreq ifreq;
|
||||||
|
#ifdef ANDROID
|
||||||
|
char *tunnel = "/dev/tun";
|
||||||
|
#else
|
||||||
char *tunnel = "/dev/net/tun";
|
char *tunnel = "/dev/net/tun";
|
||||||
|
#endif
|
||||||
|
|
||||||
if ((tun_fd = open(tunnel, O_RDWR)) < 0) {
|
if ((tun_fd = open(tunnel, O_RDWR)) < 0) {
|
||||||
warn("open_tun: %s: %s", tunnel, strerror(errno));
|
warn("open_tun: %s", tunnel);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&ifreq, 0, sizeof(ifreq));
|
memset(&ifreq, 0, sizeof(ifreq));
|
||||||
|
|
||||||
ifreq.ifr_flags = IFF_TUN;
|
ifreq.ifr_flags = IFF_TUN;
|
||||||
|
|
||||||
if (tun_device != NULL) {
|
if (tun_device != NULL) {
|
||||||
strncpy(ifreq.ifr_name, tun_device, IFNAMSIZ);
|
strncpy(ifreq.ifr_name, tun_device, IFNAMSIZ);
|
||||||
|
@ -90,11 +114,12 @@ open_tun(const char *tun_device)
|
||||||
|
|
||||||
if (ioctl(tun_fd, TUNSETIFF, (void *) &ifreq) != -1) {
|
if (ioctl(tun_fd, TUNSETIFF, (void *) &ifreq) != -1) {
|
||||||
fprintf(stderr, "Opened %s\n", ifreq.ifr_name);
|
fprintf(stderr, "Opened %s\n", ifreq.ifr_name);
|
||||||
|
fd_set_close_on_exec(tun_fd);
|
||||||
return tun_fd;
|
return tun_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (errno != EBUSY) {
|
if (errno != EBUSY) {
|
||||||
warn("open_tun: ioctl[TUNSETIFF]: %s", strerror(errno));
|
warn("open_tun: ioctl[TUNSETIFF]");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -104,11 +129,12 @@ open_tun(const char *tun_device)
|
||||||
if (ioctl(tun_fd, TUNSETIFF, (void *) &ifreq) != -1) {
|
if (ioctl(tun_fd, TUNSETIFF, (void *) &ifreq) != -1) {
|
||||||
fprintf(stderr, "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);
|
||||||
|
fd_set_close_on_exec(tun_fd);
|
||||||
return tun_fd;
|
return tun_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (errno != EBUSY) {
|
if (errno != EBUSY) {
|
||||||
warn("open_tun: ioctl[TUNSETIFF]: %s", strerror(errno));
|
warn("open_tun: ioctl[TUNSETIFF]");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -119,49 +145,8 @@ open_tun(const char *tun_device)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* BSD */
|
#elif WINDOWS32
|
||||||
|
|
||||||
int
|
|
||||||
open_tun(const char *tun_device)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int tun_fd;
|
|
||||||
char tun_name[50];
|
|
||||||
|
|
||||||
if (tun_device != NULL) {
|
|
||||||
snprintf(tun_name, sizeof(tun_name), "/dev/%s", tun_device);
|
|
||||||
strncpy(if_name, tun_device, sizeof(if_name));
|
|
||||||
if_name[sizeof(if_name)-1] = '\0';
|
|
||||||
|
|
||||||
if ((tun_fd = open(tun_name, O_RDWR)) < 0) {
|
|
||||||
warn("open_tun: %s: %s", tun_name, strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stderr, "Opened %s\n", tun_name);
|
|
||||||
return tun_fd;
|
|
||||||
} else {
|
|
||||||
for (i = 0; i < TUN_MAX_TRY; i++) {
|
|
||||||
snprintf(tun_name, sizeof(tun_name), "/dev/tun%d", i);
|
|
||||||
|
|
||||||
if ((tun_fd = open(tun_name, O_RDWR)) >= 0) {
|
|
||||||
fprintf(stderr, "Opened %s\n", tun_name);
|
|
||||||
snprintf(if_name, sizeof(if_name), "tun%d", i);
|
|
||||||
return tun_fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (errno == ENOENT)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
warn("open_tun: Failed to open tunneling device");
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* !LINUX */
|
|
||||||
#else /* WINDOWS32 */
|
|
||||||
static void
|
static void
|
||||||
get_device(char *device, int device_len, const char *wanted_dev)
|
get_device(char *device, int device_len, const char *wanted_dev)
|
||||||
{
|
{
|
||||||
|
@ -173,10 +158,10 @@ get_device(char *device, int device_len, const char *wanted_dev)
|
||||||
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TAP_ADAPTER_KEY, 0, KEY_READ, &adapter_key);
|
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TAP_ADAPTER_KEY, 0, KEY_READ, &adapter_key);
|
||||||
|
|
||||||
if (status != ERROR_SUCCESS) {
|
if (status != ERROR_SUCCESS) {
|
||||||
warnx("Error opening registry key " TAP_ADAPTER_KEY );
|
warnx("Error opening registry key " TAP_ADAPTER_KEY);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (TRUE) {
|
while (TRUE) {
|
||||||
char name[256];
|
char name[256];
|
||||||
char unit[256];
|
char unit[256];
|
||||||
|
@ -193,7 +178,7 @@ get_device(char *device, int device_len, const char *wanted_dev)
|
||||||
if (status == ERROR_NO_MORE_ITEMS) {
|
if (status == ERROR_NO_MORE_ITEMS) {
|
||||||
break;
|
break;
|
||||||
} else if (status != ERROR_SUCCESS) {
|
} else if (status != ERROR_SUCCESS) {
|
||||||
warnx("Error enumerating subkeys of registry key " TAP_ADAPTER_KEY );
|
warnx("Error enumerating subkeys of registry key " TAP_ADAPTER_KEY);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,10 +196,11 @@ get_device(char *device, int device_len, const char *wanted_dev)
|
||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
if (strncmp(TAP_VERSION_ID_0801, component, strlen(TAP_VERSION_ID_0801)) == 0 ||
|
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) {
|
strncmp(TAP_VERSION_ID_0901, component, strlen(TAP_VERSION_ID_0901)) == 0 ||
|
||||||
|
strncmp(TAP_VERSION_ID_0901_ROOT, component, strlen(TAP_VERSION_ID_0901_ROOT)) == 0) {
|
||||||
/* We found a TAP32 device, get its NetCfgInstanceId */
|
/* We found a TAP32 device, get its NetCfgInstanceId */
|
||||||
char iid_string[256] = NET_CFG_INST_ID;
|
char iid_string[256] = NET_CFG_INST_ID;
|
||||||
|
|
||||||
status = RegQueryValueEx(device_key, iid_string, NULL, &datatype, (LPBYTE) device, (DWORD *) &device_len);
|
status = RegQueryValueEx(device_key, iid_string, NULL, &datatype, (LPBYTE) device, (DWORD *) &device_len);
|
||||||
if (status != ERROR_SUCCESS || datatype != REG_SZ) {
|
if (status != ERROR_SUCCESS || datatype != REG_SZ) {
|
||||||
warnx("Error reading registry key %s\\%s on TAP device", unit, iid_string);
|
warnx("Error reading registry key %s\\%s on TAP device", unit, iid_string);
|
||||||
|
@ -280,7 +266,7 @@ DWORD WINAPI tun_reader(LPVOID arg)
|
||||||
OVERLAPPED olpd;
|
OVERLAPPED olpd;
|
||||||
int sock;
|
int sock;
|
||||||
|
|
||||||
sock = open_dns(0, INADDR_ANY);
|
sock = open_dns_from_host("127.0.0.1", 0, AF_INET, 0);
|
||||||
|
|
||||||
olpd.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
olpd.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||||
|
|
||||||
|
@ -291,21 +277,22 @@ DWORD WINAPI tun_reader(LPVOID arg)
|
||||||
if (!res) {
|
if (!res) {
|
||||||
WaitForSingleObject(olpd.hEvent, INFINITE);
|
WaitForSingleObject(olpd.hEvent, INFINITE);
|
||||||
res = GetOverlappedResult(dev_handle, &olpd, (LPDWORD) &len, FALSE);
|
res = GetOverlappedResult(dev_handle, &olpd, (LPDWORD) &len, FALSE);
|
||||||
res = sendto(sock, buf, len, 0, (struct sockaddr*) &(tun->addr),
|
res = sendto(sock, buf, len, 0, (struct sockaddr*) &(tun->addr),
|
||||||
sizeof(struct sockaddr_in));
|
tun->addrlen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
open_tun(const char *tun_device)
|
open_tun(const char *tun_device)
|
||||||
{
|
{
|
||||||
char adapter[256];
|
char adapter[256];
|
||||||
char tapfile[512];
|
char tapfile[512];
|
||||||
int tunfd;
|
int tunfd;
|
||||||
in_addr_t local;
|
struct sockaddr_storage localsock;
|
||||||
|
int localsock_len;
|
||||||
|
|
||||||
memset(adapter, 0, sizeof(adapter));
|
memset(adapter, 0, sizeof(adapter));
|
||||||
memset(if_name, 0, sizeof(if_name));
|
memset(if_name, 0, sizeof(if_name));
|
||||||
|
@ -319,7 +306,7 @@ open_tun(const char *tun_device)
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "Opening device %s\n", if_name);
|
fprintf(stderr, "Opening device %s\n", if_name);
|
||||||
snprintf(tapfile, sizeof(tapfile), "%s%s.tap", TAP_DEVICE_SPACE, adapter);
|
snprintf(tapfile, sizeof(tapfile), "%s%s.tap", TAP_DEVICE_SPACE, adapter);
|
||||||
dev_handle = CreateFile(tapfile, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, NULL);
|
dev_handle = CreateFile(tapfile, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, NULL);
|
||||||
|
@ -330,103 +317,286 @@ open_tun(const char *tun_device)
|
||||||
|
|
||||||
/* Use a UDP connection to forward packets from tun,
|
/* Use a UDP connection to forward packets from tun,
|
||||||
* so we can still use select() in main code.
|
* so we can still use select() in main code.
|
||||||
* A thread does blocking reads on tun device and
|
* A thread does blocking reads on tun device and
|
||||||
* sends data as udp to this socket */
|
* sends data as udp to this socket */
|
||||||
|
|
||||||
local = htonl(0x7f000001); /* 127.0.0.1 */
|
localsock_len = get_addr("127.0.0.1", 55353, AF_INET, 0, &localsock);
|
||||||
tunfd = open_dns(55353, local);
|
tunfd = open_dns(&localsock, localsock_len);
|
||||||
|
|
||||||
data.tun = dev_handle;
|
data.tun = dev_handle;
|
||||||
memset(&(data.addr), 0, sizeof(data.addr));
|
memcpy(&(data.addr), &localsock, localsock_len);
|
||||||
data.addr.sin_family = AF_INET;
|
data.addrlen = localsock_len;
|
||||||
data.addr.sin_port = htons(55353);
|
|
||||||
data.addr.sin_addr.s_addr = local;
|
|
||||||
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)tun_reader, &data, 0, NULL);
|
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)tun_reader, &data, 0, NULL);
|
||||||
|
|
||||||
return tunfd;
|
return tunfd;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void
|
#else /* BSD and friends */
|
||||||
close_tun(int tun_fd)
|
|
||||||
|
#ifdef DARWIN
|
||||||
|
|
||||||
|
/* Extract the device number from the name, if given. The value returned will
|
||||||
|
* be suitable for sockaddr_ctl.sc_unit, which means 0 for auto-assign, or
|
||||||
|
* (n + 1) for manual.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
utun_unit(const char *dev)
|
||||||
|
{
|
||||||
|
const char *unit_str = dev;
|
||||||
|
int unit = 0;
|
||||||
|
|
||||||
|
if (!dev)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
while (*unit_str != '\0' && !isdigit(*unit_str))
|
||||||
|
unit_str++;
|
||||||
|
|
||||||
|
if (isdigit(*unit_str))
|
||||||
|
unit = strtol(unit_str, NULL, 10) + 1;
|
||||||
|
|
||||||
|
return unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
open_utun(const char *dev)
|
||||||
|
{
|
||||||
|
struct sockaddr_ctl addr;
|
||||||
|
struct ctl_info info;
|
||||||
|
char ifname[10];
|
||||||
|
socklen_t ifname_len = sizeof(ifname);
|
||||||
|
int unit;
|
||||||
|
int fd = -1;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL);
|
||||||
|
if (fd < 0) {
|
||||||
|
warn("open_utun: socket(PF_SYSTEM)");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Look up the kernel controller ID for utun devices. */
|
||||||
|
bzero(&info, sizeof(info));
|
||||||
|
strncpy(info.ctl_name, UTUN_CONTROL_NAME, MAX_KCTL_NAME);
|
||||||
|
|
||||||
|
err = ioctl(fd, CTLIOCGINFO, &info);
|
||||||
|
if (err != 0) {
|
||||||
|
warn("open_utun: ioctl(CTLIOCGINFO)");
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Connecting to the socket creates the utun device. */
|
||||||
|
addr.sc_len = sizeof(addr);
|
||||||
|
addr.sc_family = AF_SYSTEM;
|
||||||
|
addr.ss_sysaddr = AF_SYS_CONTROL;
|
||||||
|
addr.sc_id = info.ctl_id;
|
||||||
|
unit = utun_unit(dev);
|
||||||
|
if (unit < 0) {
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
addr.sc_unit = unit;
|
||||||
|
|
||||||
|
err = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
|
||||||
|
if (err != 0) {
|
||||||
|
warn("open_utun: connect");
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Retrieve the assigned interface name. */
|
||||||
|
err = getsockopt(fd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME, ifname, &ifname_len);
|
||||||
|
if (err != 0) {
|
||||||
|
warn("open_utun: getsockopt(UTUN_OPT_IFNAME)");
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(if_name, ifname, sizeof(if_name));
|
||||||
|
|
||||||
|
fprintf(stderr, "Opened %s\n", ifname);
|
||||||
|
fd_set_close_on_exec(fd);
|
||||||
|
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int
|
||||||
|
open_tun(const char *tun_device)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int tun_fd;
|
||||||
|
char tun_name[50];
|
||||||
|
|
||||||
|
if (tun_device != NULL) {
|
||||||
|
#ifdef DARWIN
|
||||||
|
if (!strncmp(tun_device, "utun", 4)) {
|
||||||
|
tun_fd = open_utun(tun_device);
|
||||||
|
if (tun_fd >= 0) {
|
||||||
|
return tun_fd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
snprintf(tun_name, sizeof(tun_name), "/dev/%s", tun_device);
|
||||||
|
strncpy(if_name, tun_device, sizeof(if_name));
|
||||||
|
if_name[sizeof(if_name)-1] = '\0';
|
||||||
|
|
||||||
|
if ((tun_fd = open(tun_name, O_RDWR)) < 0) {
|
||||||
|
warn("open_tun: %s", tun_name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "Opened %s\n", tun_name);
|
||||||
|
fd_set_close_on_exec(tun_fd);
|
||||||
|
return tun_fd;
|
||||||
|
} else {
|
||||||
|
for (i = 0; i < TUN_MAX_TRY; i++) {
|
||||||
|
snprintf(tun_name, sizeof(tun_name), "/dev/tun%d", i);
|
||||||
|
|
||||||
|
if ((tun_fd = open(tun_name, O_RDWR)) >= 0) {
|
||||||
|
fprintf(stderr, "Opened %s\n", tun_name);
|
||||||
|
snprintf(if_name, sizeof(if_name), "tun%d", i);
|
||||||
|
fd_set_close_on_exec(tun_fd);
|
||||||
|
return tun_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errno == ENOENT)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DARWIN
|
||||||
|
fprintf(stderr, "No tun devices found, trying utun\n");
|
||||||
|
for (i = 0; i < TUN_MAX_TRY; i++) {
|
||||||
|
snprintf(tun_name, sizeof(tun_name), "utun%d", i);
|
||||||
|
tun_fd = open_utun(tun_name);
|
||||||
|
if (tun_fd >= 0) {
|
||||||
|
return tun_fd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
warn("open_tun: Failed to open tunneling device");
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void
|
||||||
|
close_tun(int tun_fd)
|
||||||
{
|
{
|
||||||
if (tun_fd >= 0)
|
if (tun_fd >= 0)
|
||||||
close(tun_fd);
|
close(tun_fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
#ifdef WINDOWS32
|
||||||
write_tun(int tun_fd, char *data, size_t len)
|
int
|
||||||
|
write_tun(int tun_fd, char *data, size_t len)
|
||||||
{
|
{
|
||||||
#if defined (FREEBSD) || defined (DARWIN) || defined(NETBSD) || defined(WINDOWS32)
|
DWORD written;
|
||||||
|
DWORD res;
|
||||||
|
OVERLAPPED olpd;
|
||||||
|
|
||||||
data += 4;
|
data += 4;
|
||||||
len -= 4;
|
len -= 4;
|
||||||
#else /* !FREEBSD/DARWIN */
|
|
||||||
#ifdef LINUX
|
|
||||||
data[0] = 0x00;
|
|
||||||
data[1] = 0x00;
|
|
||||||
data[2] = 0x08;
|
|
||||||
data[3] = 0x00;
|
|
||||||
#else /* OPENBSD */
|
|
||||||
data[0] = 0x00;
|
|
||||||
data[1] = 0x00;
|
|
||||||
data[2] = 0x00;
|
|
||||||
data[3] = 0x02;
|
|
||||||
#endif /* !LINUX */
|
|
||||||
#endif /* FREEBSD */
|
|
||||||
|
|
||||||
#ifndef WINDOWS32
|
olpd.Offset = 0;
|
||||||
if (write(tun_fd, data, len) != len) {
|
olpd.OffsetHigh = 0;
|
||||||
warn("write_tun");
|
olpd.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||||
return 1;
|
res = WriteFile(dev_handle, data, len, &written, &olpd);
|
||||||
}
|
if (!res && GetLastError() == ERROR_IO_PENDING) {
|
||||||
#else /* WINDOWS32 */
|
WaitForSingleObject(olpd.hEvent, INFINITE);
|
||||||
{
|
res = GetOverlappedResult(dev_handle, &olpd, &written, FALSE);
|
||||||
DWORD written;
|
if (written != len) {
|
||||||
DWORD res;
|
return -1;
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t
|
ssize_t
|
||||||
read_tun(int tun_fd, char *buf, size_t len)
|
read_tun(int tun_fd, char *buf, size_t len)
|
||||||
{
|
{
|
||||||
#if defined (FREEBSD) || defined (DARWIN) || defined(NETBSD) || defined(WINDOWS32)
|
|
||||||
/* FreeBSD/Darwin/NetBSD has no header */
|
|
||||||
int bytes;
|
int bytes;
|
||||||
memset(buf, 0, 4);
|
memset(buf, 0, 4);
|
||||||
#ifdef WINDOWS32
|
|
||||||
/* Windows needs recv() since it is local UDP socket */
|
|
||||||
bytes = recv(tun_fd, buf + 4, len - 4, 0);
|
bytes = recv(tun_fd, buf + 4, len - 4, 0);
|
||||||
#else
|
|
||||||
/* The other need read() because fd is not a socket */
|
|
||||||
bytes = read(tun_fd, buf + 4, len - 4);
|
|
||||||
#endif /*WINDOWS32*/
|
|
||||||
if (bytes < 0) {
|
if (bytes < 0) {
|
||||||
return bytes;
|
return bytes;
|
||||||
} else {
|
} else {
|
||||||
return bytes + 4;
|
return bytes + 4;
|
||||||
}
|
}
|
||||||
#else /* !FREEBSD */
|
}
|
||||||
return read(tun_fd, buf, len);
|
#else
|
||||||
#endif /* !FREEBSD */
|
static int
|
||||||
|
tun_uses_header(void)
|
||||||
|
{
|
||||||
|
#if defined (FREEBSD) || defined (NETBSD)
|
||||||
|
/* FreeBSD/NetBSD has no header */
|
||||||
|
return 0;
|
||||||
|
#elif defined (DARWIN)
|
||||||
|
/* Darwin tun has no header, Darwin utun does */
|
||||||
|
return !strncmp(if_name, "utun", 4);
|
||||||
|
#else /* LINUX/OPENBSD */
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
tun_setip(const char *ip, const char *remoteip, int netbits)
|
write_tun(int tun_fd, char *data, size_t len)
|
||||||
|
{
|
||||||
|
if (!tun_uses_header()) {
|
||||||
|
data += 4;
|
||||||
|
len -= 4;
|
||||||
|
} else {
|
||||||
|
#ifdef LINUX
|
||||||
|
// Linux prefixes with 32 bits ethertype
|
||||||
|
// 0x0800 for IPv4, 0x86DD for IPv6
|
||||||
|
data[0] = 0x00;
|
||||||
|
data[1] = 0x00;
|
||||||
|
data[2] = 0x08;
|
||||||
|
data[3] = 0x00;
|
||||||
|
#else /* OPENBSD and DARWIN(utun) */
|
||||||
|
// BSDs prefix with 32 bits address family
|
||||||
|
// AF_INET for IPv4, AF_INET6 for IPv6
|
||||||
|
data[0] = 0x00;
|
||||||
|
data[1] = 0x00;
|
||||||
|
data[2] = 0x00;
|
||||||
|
data[3] = 0x02;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (write(tun_fd, data, len) != len) {
|
||||||
|
warn("write_tun");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
read_tun(int tun_fd, char *buf, size_t len)
|
||||||
|
{
|
||||||
|
if (!tun_uses_header()) {
|
||||||
|
int bytes;
|
||||||
|
memset(buf, 0, 4);
|
||||||
|
|
||||||
|
bytes = read(tun_fd, buf + 4, len - 4);
|
||||||
|
if (bytes < 0) {
|
||||||
|
return bytes;
|
||||||
|
} else {
|
||||||
|
return bytes + 4;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return read(tun_fd, buf, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int
|
||||||
|
tun_setip(const char *ip, const char *other_ip, int netbits)
|
||||||
{
|
{
|
||||||
char cmdline[512];
|
char cmdline[512];
|
||||||
int netmask;
|
int netmask;
|
||||||
|
@ -440,6 +610,11 @@ tun_setip(const char *ip, const char *remoteip, int netbits)
|
||||||
DWORD ipdata[3];
|
DWORD ipdata[3];
|
||||||
struct in_addr addr;
|
struct in_addr addr;
|
||||||
DWORD len;
|
DWORD len;
|
||||||
|
#else
|
||||||
|
const char *display_ip;
|
||||||
|
#ifndef LINUX
|
||||||
|
struct in_addr netip;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
netmask = 0;
|
netmask = 0;
|
||||||
|
@ -454,28 +629,32 @@ tun_setip(const char *ip, const char *remoteip, int netbits)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#ifndef WINDOWS32
|
#ifndef WINDOWS32
|
||||||
snprintf(cmdline, sizeof(cmdline),
|
# ifdef FREEBSD
|
||||||
"/sbin/ifconfig %s %s %s netmask %s",
|
display_ip = other_ip; /* FreeBSD wants other IP as second IP */
|
||||||
|
# else
|
||||||
|
display_ip = ip;
|
||||||
|
# endif
|
||||||
|
snprintf(cmdline, sizeof(cmdline),
|
||||||
|
IFCONFIGPATH "ifconfig %s %s %s netmask %s",
|
||||||
if_name,
|
if_name,
|
||||||
ip,
|
ip,
|
||||||
#ifdef FREEBSD
|
display_ip,
|
||||||
remoteip, /* FreeBSD wants other IP as second IP */
|
|
||||||
#else
|
|
||||||
ip,
|
|
||||||
#endif
|
|
||||||
inet_ntoa(net));
|
inet_ntoa(net));
|
||||||
|
|
||||||
fprintf(stderr, "Setting IP of %s to %s\n", if_name, ip);
|
fprintf(stderr, "Setting IP of %s to %s\n", if_name, ip);
|
||||||
#ifndef LINUX
|
#ifndef LINUX
|
||||||
|
netip.s_addr = inet_addr(ip);
|
||||||
|
netip.s_addr = netip.s_addr & net.s_addr;
|
||||||
r = system(cmdline);
|
r = system(cmdline);
|
||||||
if(r != 0) {
|
if (r != 0) {
|
||||||
return r;
|
return r;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
snprintf(cmdline, sizeof(cmdline),
|
snprintf(cmdline, sizeof(cmdline),
|
||||||
"/sbin/route add %s/%d %s",
|
ROUTEPATH "route add %s/%d %s",
|
||||||
ip, netbits, ip);
|
inet_ntoa(netip), netbits, ip);
|
||||||
}
|
}
|
||||||
fprintf(stderr, "Adding route %s/%d to %s\n", ip, netbits, ip);
|
fprintf(stderr, "Adding route %s/%d to %s\n", inet_ntoa(netip), netbits, ip);
|
||||||
#endif
|
#endif
|
||||||
return system(cmdline);
|
return system(cmdline);
|
||||||
#else /* WINDOWS32 */
|
#else /* WINDOWS32 */
|
||||||
|
@ -483,13 +662,13 @@ tun_setip(const char *ip, const char *remoteip, int netbits)
|
||||||
/* Set device as connected */
|
/* Set device as connected */
|
||||||
fprintf(stderr, "Enabling interface '%s'\n", if_name);
|
fprintf(stderr, "Enabling interface '%s'\n", if_name);
|
||||||
status = 1;
|
status = 1;
|
||||||
r = DeviceIoControl(dev_handle, TAP_IOCTL_SET_MEDIA_STATUS, &status,
|
r = DeviceIoControl(dev_handle, TAP_IOCTL_SET_MEDIA_STATUS, &status,
|
||||||
sizeof(status), &status, sizeof(status), &len, NULL);
|
sizeof(status), &status, sizeof(status), &len, NULL);
|
||||||
if (!r) {
|
if (!r) {
|
||||||
fprintf(stderr, "Failed to enable interface\n");
|
fprintf(stderr, "Failed to enable interface\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inet_aton(ip, &addr)) {
|
if (inet_aton(ip, &addr)) {
|
||||||
ipdata[0] = (DWORD) addr.s_addr; /* local ip addr */
|
ipdata[0] = (DWORD) addr.s_addr; /* local ip addr */
|
||||||
ipdata[1] = net.s_addr & ipdata[0]; /* network addr */
|
ipdata[1] = net.s_addr & ipdata[0]; /* network addr */
|
||||||
|
@ -499,7 +678,7 @@ tun_setip(const char *ip, const char *remoteip, int netbits)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Tell ip/networkaddr/netmask to device for arp use */
|
/* Tell ip/networkaddr/netmask to device for arp use */
|
||||||
r = DeviceIoControl(dev_handle, TAP_IOCTL_CONFIG_TUN, &ipdata,
|
r = DeviceIoControl(dev_handle, TAP_IOCTL_CONFIG_TUN, &ipdata,
|
||||||
sizeof(ipdata), &ipdata, sizeof(ipdata), &len, NULL);
|
sizeof(ipdata), &ipdata, sizeof(ipdata), &len, NULL);
|
||||||
if (!r) {
|
if (!r) {
|
||||||
fprintf(stderr, "Failed to set interface in TUN mode\n");
|
fprintf(stderr, "Failed to set interface in TUN mode\n");
|
||||||
|
@ -514,18 +693,18 @@ tun_setip(const char *ip, const char *remoteip, int netbits)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
tun_setmtu(const unsigned mtu)
|
tun_setmtu(const unsigned mtu)
|
||||||
{
|
{
|
||||||
#ifndef WINDOWS32
|
#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 %u",
|
IFCONFIGPATH "ifconfig %s mtu %u",
|
||||||
if_name,
|
if_name,
|
||||||
mtu);
|
mtu);
|
||||||
|
|
||||||
fprintf(stderr, "Setting MTU of %s to %u\n", if_name, mtu);
|
fprintf(stderr, "Setting MTU of %s to %u\n", if_name, mtu);
|
||||||
return system(cmdline);
|
return system(cmdline);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
|
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||||
|
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
* copyright notice and this permission notice appear in all copies.
|
* copyright notice and this permission notice appear in all copies.
|
||||||
*
|
*
|
||||||
|
|
100
src/user.c
100
src/user.c
|
@ -1,7 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
|
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||||
|
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
* copyright notice and this permission notice appear in all copies.
|
* copyright notice and this permission notice appear in all copies.
|
||||||
*
|
*
|
||||||
|
@ -33,15 +34,14 @@
|
||||||
#include "encoding.h"
|
#include "encoding.h"
|
||||||
#include "user.h"
|
#include "user.h"
|
||||||
|
|
||||||
struct user users[USERS];
|
struct tun_user *users;
|
||||||
|
unsigned usercount;
|
||||||
|
|
||||||
int
|
int init_users(in_addr_t my_ip, int netbits)
|
||||||
init_users(in_addr_t my_ip, int netbits)
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int skip = 0;
|
int skip = 0;
|
||||||
char newip[16];
|
char newip[32];
|
||||||
int created_users = 0;
|
|
||||||
|
|
||||||
int maxusers;
|
int maxusers;
|
||||||
|
|
||||||
|
@ -57,9 +57,10 @@ init_users(in_addr_t my_ip, int netbits)
|
||||||
ipstart.s_addr = my_ip & net.s_addr;
|
ipstart.s_addr = my_ip & net.s_addr;
|
||||||
|
|
||||||
maxusers = (1 << (32-netbits)) - 3; /* 3: Net addr, broadcast addr, iodined addr */
|
maxusers = (1 << (32-netbits)) - 3; /* 3: Net addr, broadcast addr, iodined addr */
|
||||||
|
usercount = MIN(maxusers, USERS);
|
||||||
memset(users, 0, USERS * sizeof(struct user));
|
|
||||||
for (i = 0; i < USERS; i++) {
|
users = calloc(usercount, sizeof(struct tun_user));
|
||||||
|
for (i = 0; i < usercount; i++) {
|
||||||
in_addr_t ip;
|
in_addr_t ip;
|
||||||
users[i].id = i;
|
users[i].id = i;
|
||||||
snprintf(newip, sizeof(newip), "0.0.0.%d", i + skip + 1);
|
snprintf(newip, sizeof(newip), "0.0.0.%d", i + skip + 1);
|
||||||
|
@ -72,54 +73,34 @@ init_users(in_addr_t my_ip, int netbits)
|
||||||
}
|
}
|
||||||
users[i].tun_ip = ip;
|
users[i].tun_ip = ip;
|
||||||
net.s_addr = ip;
|
net.s_addr = ip;
|
||||||
if (maxusers-- < 1) {
|
users[i].disabled = 0;
|
||||||
users[i].disabled = 1;
|
users[i].authenticated = 0;
|
||||||
} else {
|
users[i].authenticated_raw = 0;
|
||||||
users[i].disabled = 0;
|
users[i].options_locked = 0;
|
||||||
created_users++;
|
|
||||||
}
|
|
||||||
users[i].active = 0;
|
users[i].active = 0;
|
||||||
/* Rest is reset on login ('V' packet) */
|
/* Rest is reset on login ('V' packet) */
|
||||||
}
|
}
|
||||||
|
|
||||||
return created_users;
|
return usercount;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char*
|
const char *users_get_first_ip(void)
|
||||||
users_get_first_ip()
|
|
||||||
{
|
{
|
||||||
struct in_addr ip;
|
struct in_addr ip;
|
||||||
ip.s_addr = users[0].tun_ip;
|
ip.s_addr = users[0].tun_ip;
|
||||||
return inet_ntoa(ip);
|
return strdup(inet_ntoa(ip));
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int find_user_by_ip(uint32_t ip)
|
||||||
users_waiting_on_reply()
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
for (i = 0; i < USERS; i++) {
|
|
||||||
if (users[i].active && !users[i].disabled &&
|
|
||||||
users[i].last_pkt + 60 > time(NULL) &&
|
|
||||||
users[i].q.id != 0 && users[i].conn == CONN_DNS_NULL) {
|
|
||||||
ret++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
find_user_by_ip(uint32_t ip)
|
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
ret = -1;
|
ret = -1;
|
||||||
for (i = 0; i < USERS; i++) {
|
for (i = 0; i < usercount; i++) {
|
||||||
if (users[i].active && !users[i].disabled &&
|
if (users[i].active &&
|
||||||
|
users[i].authenticated &&
|
||||||
|
!users[i].disabled &&
|
||||||
users[i].last_pkt + 60 > time(NULL) &&
|
users[i].last_pkt + 60 > time(NULL) &&
|
||||||
ip == users[i].tun_ip) {
|
ip == users[i].tun_ip) {
|
||||||
ret = i;
|
ret = i;
|
||||||
|
@ -129,13 +110,12 @@ find_user_by_ip(uint32_t ip)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
all_users_waiting_to_send()
|
|
||||||
/* If this returns true, then reading from tun device is blocked.
|
/* If this returns true, then reading from tun device is blocked.
|
||||||
So only return true when all clients have at least one packet in
|
So only return true when all clients have at least one packet in
|
||||||
the outpacket-queue, so that sending back-to-back is possible
|
the outpacket-queue, so that sending back-to-back is possible
|
||||||
without going through another select loop.
|
without going through another select loop.
|
||||||
*/
|
*/
|
||||||
|
int all_users_waiting_to_send(void)
|
||||||
{
|
{
|
||||||
time_t now;
|
time_t now;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -143,11 +123,11 @@ 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 < usercount; i++) {
|
||||||
if (users[i].active && !users[i].disabled &&
|
if (users[i].active && !users[i].disabled &&
|
||||||
users[i].last_pkt + 60 > now &&
|
users[i].last_pkt + 60 > now &&
|
||||||
((users[i].conn == CONN_RAW_UDP) ||
|
((users[i].conn == CONN_RAW_UDP) ||
|
||||||
((users[i].conn == CONN_DNS_NULL)
|
((users[i].conn == CONN_DNS_NULL)
|
||||||
#ifdef OUTPACKETQ_LEN
|
#ifdef OUTPACKETQ_LEN
|
||||||
&& users[i].outpacketq_filled < 1
|
&& users[i].outpacketq_filled < 1
|
||||||
#else
|
#else
|
||||||
|
@ -162,15 +142,17 @@ all_users_waiting_to_send()
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int find_available_user(void)
|
||||||
find_available_user()
|
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < USERS; i++) {
|
for (i = 0; i < usercount; 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)) && !users[i].disabled) {
|
if ((!users[i].active || users[i].last_pkt + 60 < time(NULL)) && !users[i].disabled) {
|
||||||
users[i].active = 1;
|
users[i].active = 1;
|
||||||
|
users[i].authenticated = 0;
|
||||||
|
users[i].authenticated_raw = 0;
|
||||||
|
users[i].options_locked = 0;
|
||||||
users[i].last_pkt = time(NULL);
|
users[i].last_pkt = time(NULL);
|
||||||
users[i].fragsize = 4096;
|
users[i].fragsize = 4096;
|
||||||
users[i].conn = CONN_DNS_NULL;
|
users[i].conn = CONN_DNS_NULL;
|
||||||
|
@ -181,24 +163,22 @@ find_available_user()
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void user_switch_codec(int userid, const struct encoder *enc)
|
||||||
user_switch_codec(int userid, struct encoder *enc)
|
|
||||||
{
|
{
|
||||||
if (userid < 0 || userid >= USERS)
|
if (userid < 0 || userid >= usercount)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
users[userid].encoder = enc;
|
users[userid].encoder = enc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void user_set_conn_type(int userid, enum connection c)
|
||||||
user_set_conn_type(int userid, enum connection c)
|
|
||||||
{
|
{
|
||||||
if (userid < 0 || userid >= USERS)
|
if (userid < 0 || userid >= usercount)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (c < 0 || c >= CONN_MAX)
|
if (c < CONN_RAW_UDP || c >= CONN_MAX)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
users[userid].conn = c;
|
users[userid].conn = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
26
src/user.h
26
src/user.h
|
@ -1,7 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
|
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||||
|
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
* copyright notice and this permission notice appear in all copies.
|
* copyright notice and this permission notice appear in all copies.
|
||||||
*
|
*
|
||||||
|
@ -33,21 +34,25 @@
|
||||||
#define QMEMDATA_LEN 15
|
#define QMEMDATA_LEN 15
|
||||||
/* Max advisable: 36/2 = 18. Total mem usage: QMEMDATA_LEN * USERS * 6 bytes */
|
/* Max advisable: 36/2 = 18. Total mem usage: QMEMDATA_LEN * USERS * 6 bytes */
|
||||||
|
|
||||||
struct user {
|
struct tun_user {
|
||||||
char id;
|
char id;
|
||||||
int active;
|
int active;
|
||||||
|
int authenticated;
|
||||||
|
int authenticated_raw;
|
||||||
|
int options_locked;
|
||||||
int disabled;
|
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 in_addr host;
|
struct sockaddr_storage host;
|
||||||
|
socklen_t hostlen;
|
||||||
struct query q;
|
struct query q;
|
||||||
struct query q_sendrealsoon;
|
struct query q_sendrealsoon;
|
||||||
int q_sendrealsoon_new;
|
int q_sendrealsoon_new;
|
||||||
struct packet inpacket;
|
struct packet inpacket;
|
||||||
struct packet outpacket;
|
struct packet outpacket;
|
||||||
int outfragresent;
|
int outfragresent;
|
||||||
struct encoder *encoder;
|
const struct encoder *encoder;
|
||||||
char downenc;
|
char downenc;
|
||||||
int out_acked_seqno;
|
int out_acked_seqno;
|
||||||
int out_acked_fragment;
|
int out_acked_fragment;
|
||||||
|
@ -73,15 +78,14 @@ struct user {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct user users[USERS];
|
extern struct tun_user *users;
|
||||||
|
|
||||||
int init_users(in_addr_t, int);
|
int init_users(in_addr_t, int);
|
||||||
const char* users_get_first_ip();
|
const char* users_get_first_ip(void);
|
||||||
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(void);
|
||||||
int find_available_user();
|
int find_available_user(void);
|
||||||
void user_switch_codec(int userid, struct encoder *enc);
|
void user_switch_codec(int userid, const struct encoder *enc);
|
||||||
void user_set_conn_type(int userid, enum connection c);
|
void user_set_conn_type(int userid, enum connection c);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
44
src/util.c
44
src/util.c
|
@ -1,7 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
|
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||||
|
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
* copyright notice and this permission notice appear in all copies.
|
* copyright notice and this permission notice appear in all copies.
|
||||||
*
|
*
|
||||||
|
@ -16,21 +17,28 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
char *
|
char *get_resolvconf_addr(void)
|
||||||
get_resolvconf_addr()
|
|
||||||
{
|
{
|
||||||
static char addr[16];
|
static char addr[16];
|
||||||
char *rv;
|
char *rv = NULL;
|
||||||
#ifndef WINDOWS32
|
#ifndef WINDOWS32
|
||||||
char buf[80];
|
char buf[80];
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
#ifdef ANDROID
|
||||||
rv = NULL;
|
fp = popen("getprop net.dns1", "r");
|
||||||
|
if (fp == NULL)
|
||||||
if ((fp = fopen("/etc/resolv.conf", "r")) == NULL)
|
err(1, "getprop net.dns1 failed");
|
||||||
|
if (fgets(buf, sizeof(buf), fp) == NULL)
|
||||||
|
err(1, "read getprop net.dns1 failed");
|
||||||
|
if (sscanf(buf, "%15s", addr) == 1)
|
||||||
|
rv = addr;
|
||||||
|
pclose(fp);
|
||||||
|
#else
|
||||||
|
if ((fp = fopen("/etc/resolv.conf", "r")) == NULL)
|
||||||
err(1, "/etc/resolv.conf");
|
err(1, "/etc/resolv.conf");
|
||||||
|
|
||||||
while (feof(fp) == 0) {
|
while (feof(fp) == 0) {
|
||||||
fgets(buf, sizeof(buf), fp);
|
fgets(buf, sizeof(buf), fp);
|
||||||
|
|
||||||
|
@ -39,14 +47,14 @@ get_resolvconf_addr()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
#endif
|
||||||
#else /* !WINDOWS32 */
|
#else /* !WINDOWS32 */
|
||||||
FIXED_INFO *fixed_info;
|
FIXED_INFO *fixed_info;
|
||||||
ULONG buflen;
|
ULONG buflen;
|
||||||
DWORD ret;
|
DWORD ret;
|
||||||
|
|
||||||
rv = NULL;
|
|
||||||
fixed_info = malloc(sizeof(FIXED_INFO));
|
fixed_info = malloc(sizeof(FIXED_INFO));
|
||||||
buflen = sizeof(FIXED_INFO);
|
buflen = sizeof(FIXED_INFO);
|
||||||
|
|
||||||
|
@ -67,3 +75,15 @@ get_resolvconf_addr()
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef OPENBSD
|
||||||
|
void
|
||||||
|
socket_setrtable(int fd, int rtable)
|
||||||
|
{
|
||||||
|
#ifdef SO_RTABLE
|
||||||
|
if (setsockopt (fd, IPPROTO_IP, SO_RTABLE, &rtable, sizeof(rtable)) == -1)
|
||||||
|
err(1, "Failed to set routing table %d", rtable);
|
||||||
|
#else
|
||||||
|
fprintf(stderr, "Routing domain support was not available at compile time.\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
20
src/util.h
20
src/util.h
|
@ -1,6 +1,24 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||||
|
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef __UTIL_H__
|
#ifndef __UTIL_H__
|
||||||
#define __UTIL_H__
|
#define __UTIL_H__
|
||||||
|
|
||||||
char *get_resolvconf_addr();
|
char *get_resolvconf_addr(void);
|
||||||
|
void socket_setrtable(int fd, int rtable);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
|
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||||
|
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
* copyright notice and this permission notice appear in all copies.
|
* copyright notice and this permission notice appear in all copies.
|
||||||
*
|
*
|
||||||
|
@ -19,7 +20,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 0x00000502
|
#define PROTOCOL_VERSION 0x00000502
|
||||||
|
|
||||||
#endif /* _VERSION_H_ */
|
#endif /* _VERSION_H_ */
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
|
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||||
|
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
* copyright notice and this permission notice appear in all copies.
|
* copyright notice and this permission notice appear in all copies.
|
||||||
*
|
*
|
||||||
|
@ -19,9 +20,9 @@
|
||||||
|
|
||||||
typedef unsigned int in_addr_t;
|
typedef unsigned int in_addr_t;
|
||||||
|
|
||||||
|
#include <winsock2.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <windns.h>
|
#include <windns.h>
|
||||||
#include <winsock2.h>
|
|
||||||
#include <ws2tcpip.h>
|
#include <ws2tcpip.h>
|
||||||
#include <iphlpapi.h>
|
#include <iphlpapi.h>
|
||||||
|
|
||||||
|
@ -52,49 +53,52 @@ typedef unsigned int in_addr_t;
|
||||||
#define sleep(seconds) Sleep((seconds)*1000)
|
#define sleep(seconds) Sleep((seconds)*1000)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned id :16; /* query identification number */
|
unsigned id :16; /* query identification number */
|
||||||
/* fields in third byte */
|
/* fields in third byte */
|
||||||
unsigned rd :1; /* recursion desired */
|
unsigned rd :1; /* recursion desired */
|
||||||
unsigned tc :1; /* truncated message */
|
unsigned tc :1; /* truncated message */
|
||||||
unsigned aa :1; /* authoritive answer */
|
unsigned aa :1; /* authoritive answer */
|
||||||
unsigned opcode :4; /* purpose of message */
|
unsigned opcode :4; /* purpose of message */
|
||||||
unsigned qr :1; /* response flag */
|
unsigned qr :1; /* response flag */
|
||||||
/* fields in fourth byte */
|
/* fields in fourth byte */
|
||||||
unsigned rcode :4; /* response code */
|
unsigned rcode :4; /* response code */
|
||||||
unsigned cd: 1; /* checking disabled by resolver */
|
unsigned cd: 1; /* checking disabled by resolver */
|
||||||
unsigned ad: 1; /* authentic data from named */
|
unsigned ad: 1; /* authentic data from named */
|
||||||
unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */
|
unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */
|
||||||
unsigned ra :1; /* recursion available */
|
unsigned ra :1; /* recursion available */
|
||||||
/* remaining bytes */
|
/* remaining bytes */
|
||||||
unsigned qdcount :16; /* number of question entries */
|
unsigned qdcount :16; /* number of question entries */
|
||||||
unsigned ancount :16; /* number of answer entries */
|
unsigned ancount :16; /* number of answer entries */
|
||||||
unsigned nscount :16; /* number of authority entries */
|
unsigned nscount :16; /* number of authority entries */
|
||||||
unsigned arcount :16; /* number of resource entries */
|
unsigned arcount :16; /* number of resource entries */
|
||||||
} HEADER;
|
} HEADER;
|
||||||
|
|
||||||
struct ip
|
struct ip {
|
||||||
{
|
unsigned int ip_hl:4; /* header length */
|
||||||
unsigned int ip_hl:4; /* header length */
|
unsigned int ip_v:4; /* version */
|
||||||
unsigned int ip_v:4; /* version */
|
u_char ip_tos; /* type of service */
|
||||||
u_char ip_tos; /* type of service */
|
u_short ip_len; /* total length */
|
||||||
u_short ip_len; /* total length */
|
u_short ip_id; /* identification */
|
||||||
u_short ip_id; /* identification */
|
u_short ip_off; /* fragment offset field */
|
||||||
u_short ip_off; /* fragment offset field */
|
#define IP_RF 0x8000 /* reserved fragment flag */
|
||||||
#define IP_RF 0x8000 /* reserved fragment flag */
|
#define IP_DF 0x4000 /* dont fragment flag */
|
||||||
#define IP_DF 0x4000 /* dont fragment flag */
|
#define IP_MF 0x2000 /* more fragments flag */
|
||||||
#define IP_MF 0x2000 /* more fragments flag */
|
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
|
||||||
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
|
u_char ip_ttl; /* time to live */
|
||||||
u_char ip_ttl; /* time to live */
|
u_char ip_p; /* protocol */
|
||||||
u_char ip_p; /* protocol */
|
u_short ip_sum; /* checksum */
|
||||||
u_short ip_sum; /* checksum */
|
struct in_addr ip_src, ip_dst; /* source and dest address */
|
||||||
struct in_addr ip_src, ip_dst; /* source and dest address */
|
};
|
||||||
};
|
|
||||||
|
|
||||||
DWORD WINAPI tun_reader(LPVOID arg);
|
DWORD WINAPI tun_reader(LPVOID arg);
|
||||||
struct tun_data {
|
struct tun_data {
|
||||||
HANDLE tun;
|
HANDLE tun;
|
||||||
int sock;
|
int sock;
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_storage addr;
|
||||||
|
int addrlen;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* No-op for now. */
|
||||||
|
#define syslog(...)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,26 +1,24 @@
|
||||||
CC = gcc
|
|
||||||
TEST = test
|
TEST = test
|
||||||
OBJS = test.o base32.o base64.o read.o dns.o encoding.o login.o user.o fw_query.o
|
OBJS = test.o base32.o base64.o common.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 ../src/fw_query.o
|
SRCOBJS = ../src/base32.o ../src/base64.o ../src/common.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"`
|
||||||
|
|
||||||
CHECK_PATH = /usr/local
|
CHECK_PATH = /usr/local
|
||||||
LDFLAGS = -L$(CHECK_PATH)/lib -lcheck `../src/osflags link`
|
LDFLAGS = -L$(CHECK_PATH)/lib `pkg-config check --libs` -lpthread `sh ../src/osflags $(TARGETOS) link`
|
||||||
CFLAGS = -g -Wall -D$(OS) -I../src -I$(CHECK_PATH)/include -pedantic `../src/osflags cflags`
|
CFLAGS = -std=c99 -g -Wall -D$(OS) `pkg-config check --cflags` -I../src -I$(CHECK_PATH)/include -pedantic `sh ../src/osflags $(TARGETOS) cflags`
|
||||||
|
|
||||||
all: $(TEST)
|
all: $(TEST)
|
||||||
@LD_LIBRARY_PATH=${CHECK_PATH}/lib ./$(TEST)
|
@LD_LIBRARY_PATH=${CHECK_PATH}/lib ./$(TEST)
|
||||||
|
|
||||||
$(TEST): $(OBJS) $(SRCOBJS)
|
$(TEST): $(OBJS) $(SRCOBJS)
|
||||||
@echo LD $(TEST)
|
@echo LD $(TEST)
|
||||||
@$(CC) -o $@ $(SRCOBJS) $(OBJS) $(LDFLAGS)
|
@$(CC) -o $@ $(SRCOBJS) $(OBJS) $(LDFLAGS)
|
||||||
|
|
||||||
.c.o:
|
.c.o:
|
||||||
@echo CC $<
|
@echo CC $<
|
||||||
@$(CC) $(CFLAGS) -c $<
|
@$(CC) $(CFLAGS) -c $<
|
||||||
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@echo "Cleaning tests/"
|
@echo "Cleaning tests/"
|
||||||
@rm -f *~ *.core $(TEST) $(OBJS)
|
@rm -f *~ *.core $(TEST) $(OBJS)
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
|
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||||
|
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
* copyright notice and this permission notice appear in all copies.
|
* copyright notice and this permission notice appear in all copies.
|
||||||
*
|
*
|
||||||
|
@ -21,7 +22,6 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#include "encoding.h"
|
#include "encoding.h"
|
||||||
#include "base32.h"
|
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
#define TUPLES 5
|
#define TUPLES 5
|
||||||
|
@ -42,16 +42,14 @@ START_TEST(test_base32_encode)
|
||||||
{
|
{
|
||||||
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);
|
len = sizeof(buf);
|
||||||
val = b32->encode(buf, &len, testpairs[_i].a, strlen(testpairs[_i].a));
|
val = base32_ops.encode(buf, &len, testpairs[_i].a, strlen(testpairs[_i].a));
|
||||||
|
|
||||||
fail_unless(strcmp(buf, testpairs[_i].b) == 0,
|
ck_assert(val == strlen(testpairs[_i].b));
|
||||||
"'%s' != '%s'", buf, testpairs[_i].b);
|
ck_assert_str_eq(buf, testpairs[_i].b);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
@ -59,17 +57,13 @@ 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);
|
len = sizeof(buf);
|
||||||
val = b32->decode(buf, &len, testpairs[_i].b, strlen(testpairs[_i].b));
|
val = base32_ops.decode(buf, &len, testpairs[_i].b, strlen(testpairs[_i].b));
|
||||||
|
|
||||||
fail_unless(buf != NULL, "buf == NULL");
|
ck_assert(val == strlen(testpairs[_i].a));
|
||||||
fail_unless(strcmp(buf, testpairs[_i].a) == 0,
|
ck_assert_str_eq(buf, testpairs[_i].a);
|
||||||
"'%s' != '%s'", buf, testpairs[_i].a);
|
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
@ -79,8 +73,8 @@ START_TEST(test_base32_5to8_8to5)
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
for (i = 0; i < 32; i++) {
|
for (i = 0; i < 32; i++) {
|
||||||
c = b32_5to8(i);
|
c = b32_5to8(i);
|
||||||
fail_unless(b32_8to5(c) == i);
|
ck_assert(b32_8to5(c) == i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
@ -91,14 +85,11 @@ START_TEST(test_base32_blksize)
|
||||||
size_t enclen;
|
size_t enclen;
|
||||||
char *rawbuf;
|
char *rawbuf;
|
||||||
char *encbuf;
|
char *encbuf;
|
||||||
struct encoder *b32;
|
|
||||||
int i;
|
int i;
|
||||||
int val;
|
int val;
|
||||||
|
|
||||||
b32 = get_base32_encoder();
|
rawlen = base32_ops.blocksize_raw;
|
||||||
|
enclen = base32_ops.blocksize_encoded;
|
||||||
rawlen = b32->blocksize_raw();
|
|
||||||
enclen = b32->blocksize_encoded();
|
|
||||||
|
|
||||||
rawbuf = malloc(rawlen + 16);
|
rawbuf = malloc(rawlen + 16);
|
||||||
encbuf = malloc(enclen + 16);
|
encbuf = malloc(enclen + 16);
|
||||||
|
@ -108,27 +99,27 @@ START_TEST(test_base32_blksize)
|
||||||
}
|
}
|
||||||
rawbuf[i] = 0;
|
rawbuf[i] = 0;
|
||||||
|
|
||||||
val = b32->encode(encbuf, &enclen, rawbuf, rawlen);
|
val = base32_ops.encode(encbuf, &enclen, rawbuf, rawlen);
|
||||||
|
|
||||||
fail_unless(rawlen == 5, "raw length was %d not 5", rawlen);
|
ck_assert_msg(rawlen == 5, "raw length was %zu not 5", rawlen);
|
||||||
fail_unless(enclen == 5, "encoded %d bytes, not 5", enclen);
|
ck_assert_msg(enclen == 5, "encoded %zu bytes, not 5", enclen);
|
||||||
fail_unless(val == 8, "encoded string %s was length %d", encbuf, val);
|
ck_assert_msg(val == 8, "encoded string %s was length %d", encbuf, val);
|
||||||
|
|
||||||
memset(rawbuf, 0, rawlen + 16);
|
memset(rawbuf, 0, rawlen + 16);
|
||||||
|
|
||||||
enclen = val;
|
enclen = val;
|
||||||
val = b32->decode(rawbuf, &rawlen, encbuf, enclen);
|
val = base32_ops.decode(rawbuf, &rawlen, encbuf, enclen);
|
||||||
|
|
||||||
fail_unless(rawlen == 5, "raw length was %d not 5", rawlen);
|
ck_assert_msg(rawlen == 5, "raw length was %zu not 5", rawlen);
|
||||||
fail_unless(val == 5, "val was not 5 but %d", val);
|
ck_assert_msg(val == 5, "val was not 5 but %d", val);
|
||||||
for (i = 0; i < rawlen; i++) {
|
for (i = 0; i < rawlen; i++) {
|
||||||
fail_unless(rawbuf[i] == 'A');
|
ck_assert(rawbuf[i] == 'A');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
TCase *
|
TCase *
|
||||||
test_base32_create_tests()
|
test_base32_create_tests(void)
|
||||||
{
|
{
|
||||||
TCase *tc;
|
TCase *tc;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
|
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||||
|
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
* copyright notice and this permission notice appear in all copies.
|
* copyright notice and this permission notice appear in all copies.
|
||||||
*
|
*
|
||||||
|
@ -21,7 +22,6 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#include "encoding.h"
|
#include "encoding.h"
|
||||||
#include "base64.h"
|
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
#define TUPLES 5
|
#define TUPLES 5
|
||||||
|
@ -68,16 +68,13 @@ START_TEST(test_base64_encode)
|
||||||
{
|
{
|
||||||
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);
|
len = sizeof(buf);
|
||||||
val = b64->encode(buf, &len, testpairs[_i].a, strlen(testpairs[_i].a));
|
val = base64_ops.encode(buf, &len, testpairs[_i].a, strlen(testpairs[_i].a));
|
||||||
|
|
||||||
fail_unless(strcmp(buf, testpairs[_i].b) == 0,
|
ck_assert(val == strlen(testpairs[_i].b));
|
||||||
"'%s' != '%s'", buf, testpairs[_i].b);
|
ck_assert_str_eq(buf, testpairs[_i].b);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
@ -85,17 +82,13 @@ 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);
|
len = sizeof(buf);
|
||||||
val = b64->decode(buf, &len, testpairs[_i].b, strlen(testpairs[_i].b));
|
val = base64_ops.decode(buf, &len, testpairs[_i].b, strlen(testpairs[_i].b));
|
||||||
|
|
||||||
fail_unless(buf != NULL, "buf == NULL");
|
ck_assert(val == strlen(testpairs[_i].a));
|
||||||
fail_unless(strcmp(buf, testpairs[_i].a) == 0,
|
ck_assert_str_eq(buf, testpairs[_i].a);
|
||||||
"'%s' != '%s'", buf, testpairs[_i].a);
|
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
@ -105,14 +98,11 @@ START_TEST(test_base64_blksize)
|
||||||
size_t enclen;
|
size_t enclen;
|
||||||
char *rawbuf;
|
char *rawbuf;
|
||||||
char *encbuf;
|
char *encbuf;
|
||||||
struct encoder *b64;
|
|
||||||
int i;
|
int i;
|
||||||
int val;
|
int val;
|
||||||
|
|
||||||
b64 = get_base64_encoder();
|
rawlen = base64_ops.blocksize_raw;
|
||||||
|
enclen = base64_ops.blocksize_encoded;
|
||||||
rawlen = b64->blocksize_raw();
|
|
||||||
enclen = b64->blocksize_encoded();
|
|
||||||
|
|
||||||
rawbuf = malloc(rawlen + 16);
|
rawbuf = malloc(rawlen + 16);
|
||||||
encbuf = malloc(enclen + 16);
|
encbuf = malloc(enclen + 16);
|
||||||
|
@ -122,27 +112,27 @@ START_TEST(test_base64_blksize)
|
||||||
}
|
}
|
||||||
rawbuf[i] = 0;
|
rawbuf[i] = 0;
|
||||||
|
|
||||||
val = b64->encode(encbuf, &enclen, rawbuf, rawlen);
|
val = base64_ops.encode(encbuf, &enclen, rawbuf, rawlen);
|
||||||
|
|
||||||
fail_unless(rawlen == 3, "raw length was %d not 3", rawlen);
|
ck_assert_msg(rawlen == 3, "raw length was %zu not 3", rawlen);
|
||||||
fail_unless(enclen == 3, "encoded %d bytes, not 3", enclen);
|
ck_assert_msg(enclen == 3, "encoded %zu bytes, not 3", enclen);
|
||||||
fail_unless(val == 4, "encoded string %s was length %d", encbuf, val);
|
ck_assert_msg(val == 4, "encoded string %s was length %d", encbuf, val);
|
||||||
|
|
||||||
memset(rawbuf, 0, rawlen + 16);
|
memset(rawbuf, 0, rawlen + 16);
|
||||||
|
|
||||||
enclen = val;
|
enclen = val;
|
||||||
val = b64->decode(rawbuf, &rawlen, encbuf, enclen);
|
val = base64_ops.decode(rawbuf, &rawlen, encbuf, enclen);
|
||||||
|
|
||||||
fail_unless(rawlen == 3, "raw length was %d not 3", rawlen);
|
ck_assert_msg(rawlen == 3, "raw length was %zu not 3", rawlen);
|
||||||
fail_unless(val == 3);
|
ck_assert(val == 3);
|
||||||
for (i = 0; i < rawlen; i++) {
|
for (i = 0; i < rawlen; i++) {
|
||||||
fail_unless(rawbuf[i] == 'A');
|
ck_assert(rawbuf[i] == 'A');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
TCase *
|
TCase *
|
||||||
test_base64_create_tests()
|
test_base64_create_tests(void)
|
||||||
{
|
{
|
||||||
TCase *tc;
|
TCase *tc;
|
||||||
|
|
||||||
|
|
330
tests/common.c
Normal file
330
tests/common.c
Normal file
|
@ -0,0 +1,330 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||||
|
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <check.h>
|
||||||
|
#include <common.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
|
||||||
|
START_TEST(test_topdomain_ok)
|
||||||
|
{
|
||||||
|
char *error = NULL;
|
||||||
|
|
||||||
|
ck_assert(check_topdomain("foo.0123456789.qwertyuiop.asdfghjkl.zxcvbnm.com", 0, &error) == 0);
|
||||||
|
ck_assert(error == NULL);
|
||||||
|
/* Allowing wildcard */
|
||||||
|
ck_assert(check_topdomain("foo.0123456789.qwertyuiop.asdfghjkl.zxcvbnm.com", 1, &error) == 0);
|
||||||
|
ck_assert(error == NULL);
|
||||||
|
|
||||||
|
/* Not allowed to start with dot */
|
||||||
|
ck_assert(check_topdomain(".foo.0123456789.qwertyuiop.asdfghjkl.zxcvbnm.com", 0, &error));
|
||||||
|
ck_assert_str_eq("Starts with a dot", error);
|
||||||
|
|
||||||
|
/* Test missing error msg ptr */
|
||||||
|
ck_assert(check_topdomain(".foo", 0, NULL));
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_topdomain_length)
|
||||||
|
{
|
||||||
|
char *error;
|
||||||
|
|
||||||
|
/* Test empty and too short */
|
||||||
|
ck_assert(check_topdomain("", 0, &error));
|
||||||
|
ck_assert_str_eq("Too short (< 3)", error);
|
||||||
|
error = NULL;
|
||||||
|
ck_assert(check_topdomain("a", 0, &error));
|
||||||
|
ck_assert_str_eq("Too short (< 3)", error);
|
||||||
|
error = NULL;
|
||||||
|
ck_assert(check_topdomain(".a", 0, &error));
|
||||||
|
ck_assert_str_eq("Too short (< 3)", error);
|
||||||
|
error = NULL;
|
||||||
|
ck_assert(check_topdomain("a.", 0, &error));
|
||||||
|
ck_assert_str_eq("Too short (< 3)", error);
|
||||||
|
error = NULL;
|
||||||
|
ck_assert(check_topdomain("ab", 0, &error));
|
||||||
|
ck_assert_str_eq("Too short (< 3)", error);
|
||||||
|
error = NULL;
|
||||||
|
ck_assert(check_topdomain("a.b", 0, &error) == 0);
|
||||||
|
|
||||||
|
/* Test too long (over 128, need rest of space for data) */
|
||||||
|
ck_assert(check_topdomain(
|
||||||
|
"abcd12345.abcd12345.abcd12345.abcd12345.abcd12345."
|
||||||
|
"abcd12345.abcd12345.abcd12345.abcd12345.abcd12345."
|
||||||
|
"abcd12345.abcd12345.foo129xxx", 0, &error));
|
||||||
|
ck_assert_str_eq("Too long (> 128)", error);
|
||||||
|
ck_assert(check_topdomain(
|
||||||
|
"abcd12345.abcd12345.abcd12345.abcd12345.abcd12345."
|
||||||
|
"abcd12345.abcd12345.abcd12345.abcd12345.abcd12345."
|
||||||
|
"abcd12345.abcd12345.foo128xx", 0, &error) == 0);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_topdomain_chunks)
|
||||||
|
{
|
||||||
|
char *error;
|
||||||
|
|
||||||
|
/* Must have at least one dot */
|
||||||
|
ck_assert(check_topdomain("abcde.gh", 0, &error) == 0);
|
||||||
|
ck_assert(check_topdomain("abcdefgh", 0, &error));
|
||||||
|
ck_assert_str_eq("No dots", error);
|
||||||
|
|
||||||
|
/* Not two consecutive dots */
|
||||||
|
ck_assert(check_topdomain("abc..defgh", 0, &error));
|
||||||
|
ck_assert_str_eq("Consecutive dots", error);
|
||||||
|
|
||||||
|
/* Not end with a dots */
|
||||||
|
ck_assert(check_topdomain("abc.defgh.", 0, &error));
|
||||||
|
ck_assert_str_eq("Ends with a dot", error);
|
||||||
|
|
||||||
|
/* No chunk longer than 63 chars */
|
||||||
|
ck_assert(check_topdomain("123456789012345678901234567890"
|
||||||
|
"123456789012345678901234567890333.com", 0, &error) == 0);
|
||||||
|
ck_assert(check_topdomain("123456789012345678901234567890"
|
||||||
|
"1234567890123456789012345678904444.com", 0, &error));
|
||||||
|
ck_assert_str_eq("Too long domain part (> 63)", error);
|
||||||
|
|
||||||
|
ck_assert(check_topdomain("abc.123456789012345678901234567890"
|
||||||
|
"123456789012345678901234567890333.com", 0, &error) == 0);
|
||||||
|
ck_assert(check_topdomain("abc.123456789012345678901234567890"
|
||||||
|
"1234567890123456789012345678904444.com", 0, &error));
|
||||||
|
ck_assert_str_eq("Too long domain part (> 63)", error);
|
||||||
|
|
||||||
|
ck_assert(check_topdomain("abc.123456789012345678901234567890"
|
||||||
|
"123456789012345678901234567890333", 0, &error) == 0);
|
||||||
|
ck_assert(check_topdomain("abc.123456789012345678901234567890"
|
||||||
|
"1234567890123456789012345678904444", 0, &error));
|
||||||
|
ck_assert_str_eq("Too long domain part (> 63)", error);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_topdomain_wild)
|
||||||
|
{
|
||||||
|
char *error = NULL;
|
||||||
|
|
||||||
|
ck_assert(check_topdomain("*.a", 0, &error) == 1);
|
||||||
|
ck_assert_str_eq("Contains illegal character (allowed: [a-zA-Z0-9-.])", error);
|
||||||
|
error = NULL;
|
||||||
|
ck_assert(check_topdomain("*.a", 1, &error) == 0);
|
||||||
|
ck_assert(error == NULL);
|
||||||
|
|
||||||
|
ck_assert(check_topdomain("b*.a", 0, &error) == 1);
|
||||||
|
ck_assert_str_eq("Contains illegal character (allowed: [a-zA-Z0-9-.])", error);
|
||||||
|
error = NULL;
|
||||||
|
ck_assert(check_topdomain("b*.a", 1, &error) == 1);
|
||||||
|
ck_assert_str_eq("Wildcard (*) only allowed as first char", error);
|
||||||
|
|
||||||
|
ck_assert(check_topdomain("*b.a", 0, &error) == 1);
|
||||||
|
ck_assert_str_eq("Contains illegal character (allowed: [a-zA-Z0-9-.])", error);
|
||||||
|
error = NULL;
|
||||||
|
ck_assert(check_topdomain("*b.a", 1, &error) == 1);
|
||||||
|
ck_assert_str_eq("Wildcard (*) must be followed by dot", error);
|
||||||
|
|
||||||
|
ck_assert(check_topdomain("*.*.a", 0, &error) == 1);
|
||||||
|
ck_assert_str_eq("Contains illegal character (allowed: [a-zA-Z0-9-.])", error);
|
||||||
|
error = NULL;
|
||||||
|
ck_assert(check_topdomain("*.*.a", 1, &error) == 1);
|
||||||
|
ck_assert_str_eq("Wildcard (*) only allowed as first char", error);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_query_datalen)
|
||||||
|
{
|
||||||
|
char *topdomain = "r.foo.com";
|
||||||
|
/* With data */
|
||||||
|
ck_assert(query_datalen("foobar.r.foo.com", topdomain) == 7);
|
||||||
|
ck_assert(query_datalen("foobar.r.FoO.Com", topdomain) == 7);
|
||||||
|
ck_assert(query_datalen("foo.bar.r.FoO.Com", topdomain) == 8);
|
||||||
|
ck_assert(query_datalen(".r.foo.com", topdomain) == 1);
|
||||||
|
/* Without data */
|
||||||
|
ck_assert(query_datalen("r.foo.com", topdomain) == 0);
|
||||||
|
ck_assert(query_datalen("R.foo.com", topdomain) == 0);
|
||||||
|
/* Shorter query name */
|
||||||
|
ck_assert(query_datalen("foo.com", topdomain) == -1);
|
||||||
|
/* Mismatched query name */
|
||||||
|
ck_assert(query_datalen("b.foo.com", topdomain) == -1);
|
||||||
|
ck_assert(query_datalen("*.foo.com", topdomain) == -1);
|
||||||
|
/* Query name overlaps topdomain, but is longer */
|
||||||
|
ck_assert(query_datalen("bar.foo.com", topdomain) == -1);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_query_datalen_wild)
|
||||||
|
{
|
||||||
|
char *topdomain = "*.foo.com";
|
||||||
|
/* With data */
|
||||||
|
ck_assert(query_datalen("foobar.a.foo.com", topdomain) == 7);
|
||||||
|
ck_assert(query_datalen("foobar.r.FoO.Com", topdomain) == 7);
|
||||||
|
ck_assert(query_datalen("foo.bar.r.FoO.Com", topdomain) == 8);
|
||||||
|
ck_assert(query_datalen("foo.Ab.foo.cOm", topdomain) == 4);
|
||||||
|
ck_assert(query_datalen("foo.Abcd.Foo.com", topdomain) == 4);
|
||||||
|
ck_assert(query_datalen("***.STARs.foo.com", topdomain) == 4);
|
||||||
|
ck_assert(query_datalen(".a.foo.com", topdomain) == 1);
|
||||||
|
ck_assert(query_datalen(".ab.foo.com", topdomain) == 1);
|
||||||
|
/* Without data */
|
||||||
|
ck_assert(query_datalen("rr.foo.com", topdomain) == 0);
|
||||||
|
ck_assert(query_datalen("b.foo.com", topdomain) == 0);
|
||||||
|
ck_assert(query_datalen("B.foo.com", topdomain) == 0);
|
||||||
|
/* Shorter query name */
|
||||||
|
ck_assert(query_datalen("foo.com", topdomain) == -1);
|
||||||
|
/* Wildcard part of query name matching topdomain */
|
||||||
|
ck_assert(query_datalen("aa.*.foo.com", topdomain) == -1);
|
||||||
|
/* Mismatched query name */
|
||||||
|
ck_assert(query_datalen("bar.r.boo.com", topdomain) == -1);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_parse_format_ipv4)
|
||||||
|
{
|
||||||
|
char *host = "192.168.2.10";
|
||||||
|
char *formatted;
|
||||||
|
struct sockaddr_storage addr;
|
||||||
|
struct sockaddr_in *v4addr;
|
||||||
|
int addr_len;
|
||||||
|
|
||||||
|
addr_len = get_addr(host, 53, AF_INET, 0, &addr);
|
||||||
|
ck_assert(addr_len == sizeof(struct sockaddr_in));
|
||||||
|
|
||||||
|
v4addr = (struct sockaddr_in *) &addr;
|
||||||
|
ck_assert(v4addr->sin_addr.s_addr == htonl(0xc0a8020a));
|
||||||
|
ck_assert(v4addr->sin_port == htons(53));
|
||||||
|
|
||||||
|
formatted = format_addr(&addr, addr_len);
|
||||||
|
ck_assert_str_eq(host, formatted);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_parse_format_ipv4_listen_all)
|
||||||
|
{
|
||||||
|
char *host = "0.0.0.0";
|
||||||
|
char *formatted;
|
||||||
|
struct sockaddr_storage addr;
|
||||||
|
struct sockaddr_in *v4addr;
|
||||||
|
int addr_len;
|
||||||
|
|
||||||
|
addr_len = get_addr(NULL, 53, AF_INET, AI_PASSIVE, &addr);
|
||||||
|
ck_assert(addr_len == sizeof(struct sockaddr_in));
|
||||||
|
|
||||||
|
v4addr = (struct sockaddr_in *) &addr;
|
||||||
|
ck_assert(v4addr->sin_addr.s_addr == htonl(0x00000000));
|
||||||
|
ck_assert(v4addr->sin_port == htons(53));
|
||||||
|
|
||||||
|
formatted = format_addr(&addr, addr_len);
|
||||||
|
ck_assert_str_eq(host, formatted);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_parse_format_ipv6)
|
||||||
|
{
|
||||||
|
char *host = "2001:0db8:0505:0::123:0abc";
|
||||||
|
char *compact = "2001:db8:505::123:abc";
|
||||||
|
unsigned char v6_bits[] = {
|
||||||
|
0x20, 0x01, 0x0d, 0xb8, 0x05, 0x05, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x01, 0x23, 0x0a, 0xbc,
|
||||||
|
};
|
||||||
|
char *formatted;
|
||||||
|
struct sockaddr_storage addr;
|
||||||
|
struct sockaddr_in6 *v6addr;
|
||||||
|
int addr_len;
|
||||||
|
|
||||||
|
addr_len = get_addr(host, 53, AF_UNSPEC, 0, &addr);
|
||||||
|
ck_assert(addr_len == sizeof(struct sockaddr_in6));
|
||||||
|
|
||||||
|
v6addr = (struct sockaddr_in6 *) &addr;
|
||||||
|
ck_assert(memcmp(&v6addr->sin6_addr, v6_bits, sizeof(v6_bits)) == 0);
|
||||||
|
ck_assert(v6addr->sin6_port == htons(53));
|
||||||
|
|
||||||
|
formatted = format_addr(&addr, addr_len);
|
||||||
|
ck_assert_str_eq(compact, formatted);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_parse_format_ipv4_mapped_ipv6)
|
||||||
|
{
|
||||||
|
char *v4mapped = "::FFFF:192.168.2.10";
|
||||||
|
char *host = "192.168.2.10";
|
||||||
|
unsigned char v6_bits[] = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0xff, 0xff, 0xc0, 0xa8, 0x02, 0x0a,
|
||||||
|
};
|
||||||
|
char *formatted;
|
||||||
|
struct sockaddr_storage addr;
|
||||||
|
struct sockaddr_in6 *v6addr;
|
||||||
|
int addr_len;
|
||||||
|
|
||||||
|
addr_len = get_addr(v4mapped, 53, AF_INET6, 0, &addr);
|
||||||
|
ck_assert(addr_len == sizeof(struct sockaddr_in6));
|
||||||
|
|
||||||
|
v6addr = (struct sockaddr_in6 *) &addr;
|
||||||
|
ck_assert(memcmp(&v6addr->sin6_addr, v6_bits, sizeof(v6_bits)) == 0);
|
||||||
|
ck_assert(v6addr->sin6_port == htons(53));
|
||||||
|
|
||||||
|
/* Format as IPv4 address */
|
||||||
|
formatted = format_addr(&addr, addr_len);
|
||||||
|
ck_assert_str_eq(host, formatted);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_get_addr_err)
|
||||||
|
{
|
||||||
|
char *host = "192.168.2.10";
|
||||||
|
struct sockaddr_storage addr;
|
||||||
|
int addr_len;
|
||||||
|
int flags = AI_PASSIVE;
|
||||||
|
|
||||||
|
/* Invalid host */
|
||||||
|
addr_len = get_addr(NULL, -1, flags, 0, &addr);
|
||||||
|
ck_assert(addr_len == -1);
|
||||||
|
/* Invalid port */
|
||||||
|
addr_len = get_addr(host, -1, flags, 0, &addr);
|
||||||
|
ck_assert(addr_len == -1);
|
||||||
|
/* Invalid flag */
|
||||||
|
addr_len = get_addr(host, 53, flags | 0xFFF, 0, &addr);
|
||||||
|
ck_assert(addr_len == -1);
|
||||||
|
/* Invalid addr */
|
||||||
|
addr_len = get_addr(host, 53, flags, 0, (struct sockaddr_storage *)NULL);
|
||||||
|
ck_assert(addr_len == -1);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
TCase *
|
||||||
|
test_common_create_tests(void)
|
||||||
|
{
|
||||||
|
TCase *tc;
|
||||||
|
int sock;
|
||||||
|
|
||||||
|
tc = tcase_create("Common");
|
||||||
|
tcase_add_test(tc, test_topdomain_ok);
|
||||||
|
tcase_add_test(tc, test_topdomain_length);
|
||||||
|
tcase_add_test(tc, test_topdomain_chunks);
|
||||||
|
tcase_add_test(tc, test_topdomain_wild);
|
||||||
|
tcase_add_test(tc, test_query_datalen);
|
||||||
|
tcase_add_test(tc, test_query_datalen_wild);
|
||||||
|
tcase_add_test(tc, test_parse_format_ipv4);
|
||||||
|
tcase_add_test(tc, test_parse_format_ipv4_listen_all);
|
||||||
|
tcase_add_test(tc, test_get_addr_err);
|
||||||
|
|
||||||
|
/* Tests require IPv6 support */
|
||||||
|
sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
|
if (sock >= 0) {
|
||||||
|
close(sock);
|
||||||
|
tcase_add_test(tc, test_parse_format_ipv6);
|
||||||
|
tcase_add_test(tc, test_parse_format_ipv4_mapped_ipv6);
|
||||||
|
}
|
||||||
|
return tc;
|
||||||
|
}
|
62
tests/dns.c
62
tests/dns.c
|
@ -1,7 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
|
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||||
|
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
* copyright notice and this permission notice appear in all copies.
|
* copyright notice and this permission notice appear in all copies.
|
||||||
*
|
*
|
||||||
|
@ -24,11 +25,14 @@
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <arpa/nameser.h>
|
#include <arpa/nameser.h>
|
||||||
|
#ifdef DARWIN
|
||||||
|
#define BIND_8_COMPAT
|
||||||
|
#include <arpa/nameser_compat.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "dns.h"
|
#include "dns.h"
|
||||||
#include "encoding.h"
|
#include "encoding.h"
|
||||||
#include "base32.h"
|
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
static void dump_packet(char *, size_t);
|
static void dump_packet(char *, size_t);
|
||||||
|
@ -65,7 +69,7 @@ START_TEST(test_encode_query)
|
||||||
char buf[512];
|
char buf[512];
|
||||||
char resolv[512];
|
char resolv[512];
|
||||||
struct query q;
|
struct query q;
|
||||||
struct encoder *enc;
|
const struct encoder *enc;
|
||||||
char *d;
|
char *d;
|
||||||
size_t len;
|
size_t len;
|
||||||
size_t enclen;
|
size_t enclen;
|
||||||
|
@ -78,7 +82,7 @@ START_TEST(test_encode_query)
|
||||||
q.type = T_NULL;
|
q.type = T_NULL;
|
||||||
q.id = 1337;
|
q.id = 1337;
|
||||||
d = resolv;
|
d = resolv;
|
||||||
enc = get_base32_encoder();
|
enc = &base32_ops;
|
||||||
|
|
||||||
*d++ = 'A';
|
*d++ = 'A';
|
||||||
enc->encode(d, &enclen, innerData, strlen(innerData));
|
enc->encode(d, &enclen, innerData, strlen(innerData));
|
||||||
|
@ -96,8 +100,10 @@ START_TEST(test_encode_query)
|
||||||
dump_packet(query_packet, len);
|
dump_packet(query_packet, len);
|
||||||
dump_packet(buf, ret);
|
dump_packet(buf, ret);
|
||||||
}
|
}
|
||||||
fail_unless(strncmp(query_packet, buf, sizeof(query_packet)) == 0, "Did not compile expected packet");
|
ck_assert_msg(strncmp(query_packet, buf, sizeof(query_packet)) == 0,
|
||||||
fail_unless(ret == len, "Bad packet length: %d, expected %d", ret, len);
|
"Did not compile expected packet");
|
||||||
|
ck_assert_msg(ret == len,
|
||||||
|
"Bad packet length: %d, expected %zu", ret, len);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
@ -106,22 +112,25 @@ START_TEST(test_decode_query)
|
||||||
char buf[512];
|
char buf[512];
|
||||||
char *domain;
|
char *domain;
|
||||||
struct query q;
|
struct query q;
|
||||||
struct encoder *enc;
|
const struct encoder *enc;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
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(query_packet) - 1;
|
len = sizeof(query_packet) - 1;
|
||||||
enc = get_base32_encoder();
|
enc = &base32_ops;
|
||||||
|
|
||||||
dns_decode(buf, sizeof(buf), &q, QR_QUERY, query_packet, 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);
|
ck_assert_msg(strncmp(buf, innerData, strlen(innerData)) == 0,
|
||||||
fail_unless(strlen(buf) == strlen(innerData), "Bad host length: %d, expected %d: '%s'", strlen(buf), strlen(innerData), buf);
|
"Did not extract expected host: '%s'", buf);
|
||||||
|
ck_assert_msg(strlen(buf) == strlen(innerData),
|
||||||
|
"Bad host length: %zu, expected %zu: '%s'",
|
||||||
|
strlen(buf), strlen(innerData), buf);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
@ -143,8 +152,10 @@ START_TEST(test_encode_response)
|
||||||
ret = dns_encode(buf, len, &q, QR_ANSWER, msgData, strlen(msgData));
|
ret = dns_encode(buf, len, &q, QR_ANSWER, msgData, strlen(msgData));
|
||||||
len = sizeof(answer_packet) - 1; /* Skip extra null character */
|
len = sizeof(answer_packet) - 1; /* Skip extra null character */
|
||||||
|
|
||||||
fail_unless(strncmp(answer_packet, buf, sizeof(answer_packet)) == 0, "Did not compile expected packet");
|
ck_assert_msg(strncmp(answer_packet, buf, sizeof(answer_packet)) == 0,
|
||||||
fail_unless(ret == len, "Bad packet length: %d, expected %d", ret, len);
|
"Did not compile expected packet");
|
||||||
|
ck_assert_msg(ret == len,
|
||||||
|
"Bad packet length: %d, expected %d", ret, len);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
@ -159,9 +170,11 @@ START_TEST(test_decode_response)
|
||||||
memset(&buf, 0, sizeof(buf));
|
memset(&buf, 0, sizeof(buf));
|
||||||
|
|
||||||
ret = dns_decode(buf, len, &q, QR_ANSWER, answer_packet, sizeof(answer_packet)-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");
|
ck_assert_msg(ret == strlen(msgData),
|
||||||
fail_unless(ret == strlen(msgData), "Bad data length: %d, expected %d", ret, strlen(msgData));
|
"Bad data length: %d, expected %zu", ret, strlen(msgData));
|
||||||
fail_unless(q.id == 0x0539);
|
ck_assert_msg(strncmp(msgData, buf, strlen(msgData)) == 0,
|
||||||
|
"Did not extract expected data");
|
||||||
|
ck_assert(q.id == 0x0539);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
@ -176,9 +189,12 @@ START_TEST(test_decode_response_with_high_trans_id)
|
||||||
memset(&buf, 0, 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);
|
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");
|
ck_assert_msg(ret == strlen(msgData),
|
||||||
fail_unless(ret == strlen(msgData), "Bad data length: %d, expected %d", ret, strlen(msgData));
|
"Bad data length: %d, expected %zu", ret, strlen(msgData));
|
||||||
fail_unless(q.id == 0x8539, "q.id was %08X instead of %08X!", q.id, 0x8539);
|
ck_assert_msg(strncmp(msgData, buf, strlen(msgData)) == 0,
|
||||||
|
"Did not extract expected data");
|
||||||
|
ck_assert_msg(q.id == 0x8539,
|
||||||
|
"q.id was %08X instead of %08X!", q.id, 0x8539);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
@ -192,7 +208,7 @@ START_TEST(test_get_id_short_packet)
|
||||||
memset(&buf, 5, sizeof(buf));
|
memset(&buf, 5, sizeof(buf));
|
||||||
|
|
||||||
id = dns_get_id(buf, len);
|
id = dns_get_id(buf, len);
|
||||||
fail_unless(id == 0);
|
ck_assert(id == 0);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
@ -201,7 +217,7 @@ START_TEST(test_get_id_low)
|
||||||
unsigned short id;
|
unsigned short id;
|
||||||
|
|
||||||
id = dns_get_id(answer_packet, sizeof(answer_packet));
|
id = dns_get_id(answer_packet, sizeof(answer_packet));
|
||||||
fail_unless(id == 1337);
|
ck_assert(id == 1337);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
@ -210,7 +226,7 @@ START_TEST(test_get_id_high)
|
||||||
unsigned short id;
|
unsigned short id;
|
||||||
|
|
||||||
id = dns_get_id(answer_packet_high_trans_id, sizeof(answer_packet_high_trans_id));
|
id = dns_get_id(answer_packet_high_trans_id, sizeof(answer_packet_high_trans_id));
|
||||||
fail_unless(id == 0x8539);
|
ck_assert(id == 0x8539);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
@ -234,7 +250,7 @@ dump_packet(char *buf, size_t len)
|
||||||
}
|
}
|
||||||
|
|
||||||
TCase *
|
TCase *
|
||||||
test_dns_create_tests()
|
test_dns_create_tests(void)
|
||||||
{
|
{
|
||||||
TCase *tc;
|
TCase *tc;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
|
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||||
|
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
* copyright notice and this permission notice appear in all copies.
|
* copyright notice and this permission notice appear in all copies.
|
||||||
*
|
*
|
||||||
|
@ -21,8 +22,6 @@
|
||||||
|
|
||||||
#include "encoding.h"
|
#include "encoding.h"
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
#include "base32.h"
|
|
||||||
#include "base64.h"
|
|
||||||
|
|
||||||
#define TUPLES 4
|
#define TUPLES 4
|
||||||
|
|
||||||
|
@ -51,8 +50,7 @@ START_TEST(test_inline_dotify)
|
||||||
b = temp;
|
b = temp;
|
||||||
inline_dotify(b, sizeof(temp));
|
inline_dotify(b, sizeof(temp));
|
||||||
|
|
||||||
fail_unless(strcmp(dottests[_i].b, temp) == 0,
|
ck_assert_str_eq(dottests[_i].b, temp);
|
||||||
"'%s' != '%s'", temp, dottests[_i].b);
|
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
@ -66,8 +64,7 @@ START_TEST(test_inline_undotify)
|
||||||
b = temp;
|
b = temp;
|
||||||
inline_undotify(b, sizeof(temp));
|
inline_undotify(b, sizeof(temp));
|
||||||
|
|
||||||
fail_unless(strcmp(dottests[_i].a, temp) == 0,
|
ck_assert_str_eq(dottests[_i].a, temp);
|
||||||
"'%s' != '%s'", temp, dottests[_i].a);
|
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
@ -84,18 +81,19 @@ START_TEST(test_build_hostname)
|
||||||
}
|
}
|
||||||
|
|
||||||
buflen = sizeof(buf);
|
buflen = sizeof(buf);
|
||||||
|
|
||||||
for (i = 1; i < sizeof(data); i++) {
|
|
||||||
int len = build_hostname(buf, buflen, data, i, topdomain, get_base32_encoder(), sizeof(buf));
|
|
||||||
|
|
||||||
fail_if(len > i);
|
for (i = 1; i < sizeof(data); i++) {
|
||||||
fail_if(strstr(buf, ".."), "Found double dots when encoding data len %d! buf: %s", i, buf);
|
int len = build_hostname(buf, buflen, data, i, topdomain, &base32_ops, sizeof(buf));
|
||||||
|
|
||||||
|
ck_assert(len <= i);
|
||||||
|
ck_assert_msg(strstr(buf, "..") == NULL,
|
||||||
|
"Found double dots when encoding data len %d! buf: %s", i, buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
TCase *
|
TCase *
|
||||||
test_encoding_create_tests()
|
test_encoding_create_tests(void)
|
||||||
{
|
{
|
||||||
TCase *tc;
|
TCase *tc;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2009 Erik Ekman <yarrick@kryo.se>
|
* Copyright (c) 2009-2014 Erik Ekman <yarrick@kryo.se>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
* copyright notice and this permission notice appear in all copies.
|
* copyright notice and this permission notice appear in all copies.
|
||||||
*
|
*
|
||||||
|
@ -28,17 +28,17 @@ START_TEST(test_fw_query_simple)
|
||||||
q.id = 0x848A;
|
q.id = 0x848A;
|
||||||
|
|
||||||
fw_query_init();
|
fw_query_init();
|
||||||
|
|
||||||
/* Test empty cache */
|
/* Test empty cache */
|
||||||
fw_query_get(0x848A, &qp);
|
fw_query_get(0x848A, &qp);
|
||||||
fail_unless(qp == NULL);
|
ck_assert(qp == NULL);
|
||||||
|
|
||||||
fw_query_put(&q);
|
fw_query_put(&q);
|
||||||
|
|
||||||
/* Test cache with one entry */
|
/* Test cache with one entry */
|
||||||
fw_query_get(0x848A, &qp);
|
fw_query_get(0x848A, &qp);
|
||||||
fail_unless(qp->addrlen == q.addrlen);
|
ck_assert(qp->addrlen == q.addrlen);
|
||||||
fail_unless(qp->id == q.id);
|
ck_assert(qp->id == q.id);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ START_TEST(test_fw_query_edge)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
fw_query_init();
|
fw_query_init();
|
||||||
|
|
||||||
q.addrlen = 33;
|
q.addrlen = 33;
|
||||||
q.id = 0x848A;
|
q.id = 0x848A;
|
||||||
fw_query_put(&q);
|
fw_query_put(&q);
|
||||||
|
@ -62,21 +62,21 @@ START_TEST(test_fw_query_edge)
|
||||||
|
|
||||||
/* The query should still be cached */
|
/* The query should still be cached */
|
||||||
fw_query_get(0x848A, &qp);
|
fw_query_get(0x848A, &qp);
|
||||||
fail_unless(qp->addrlen == 33);
|
ck_assert(qp->addrlen == 33);
|
||||||
fail_unless(qp->id == 0x848A);
|
ck_assert(qp->id == 0x848A);
|
||||||
|
|
||||||
q.addrlen++;
|
q.addrlen++;
|
||||||
q.id++;
|
q.id++;
|
||||||
fw_query_put(&q);
|
fw_query_put(&q);
|
||||||
|
|
||||||
/* but now it is overwritten */
|
/* but now it is overwritten */
|
||||||
fw_query_get(0x848A, &qp);
|
fw_query_get(0x848A, &qp);
|
||||||
fail_unless(qp == NULL);
|
ck_assert(qp == NULL);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
TCase *
|
TCase *
|
||||||
test_fw_query_create_tests()
|
test_fw_query_create_tests(void)
|
||||||
{
|
{
|
||||||
TCase *tc;
|
TCase *tc;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
|
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||||
|
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
* copyright notice and this permission notice appear in all copies.
|
* copyright notice and this permission notice appear in all copies.
|
||||||
*
|
*
|
||||||
|
@ -33,7 +34,7 @@ START_TEST(test_login_hash)
|
||||||
|
|
||||||
memset(ans, 0, sizeof(ans));
|
memset(ans, 0, sizeof(ans));
|
||||||
login_calculate(ans, len, pass, seed);
|
login_calculate(ans, len, pass, seed);
|
||||||
fail_unless(strncmp(ans, good, len) == 0, NULL);
|
ck_assert(strncmp(ans, good, len) == 0);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
@ -53,12 +54,12 @@ START_TEST(test_login_hash_short)
|
||||||
|
|
||||||
/* If len < 16, it should do nothing */
|
/* If len < 16, it should do nothing */
|
||||||
login_calculate(ans, len, pass, seed);
|
login_calculate(ans, len, pass, seed);
|
||||||
fail_if(memcmp(ans, check, sizeof(ans)));
|
ck_assert(memcmp(ans, check, sizeof(ans)) == 0);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
TCase *
|
TCase *
|
||||||
test_login_create_tests()
|
test_login_create_tests(void)
|
||||||
{
|
{
|
||||||
TCase *tc;
|
TCase *tc;
|
||||||
|
|
||||||
|
|
61
tests/read.c
61
tests/read.c
|
@ -1,7 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
|
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||||
|
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
* copyright notice and this permission notice appear in all copies.
|
* copyright notice and this permission notice appear in all copies.
|
||||||
*
|
*
|
||||||
|
@ -20,7 +21,8 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <arpa/nameser.h>
|
#include <arpa/nameser.h>
|
||||||
#ifdef DARWIN
|
#ifdef DARWIN
|
||||||
#include <arpa/nameser8_compat.h>
|
#define BIND_8_COMPAT
|
||||||
|
#include <arpa/nameser_compat.h>
|
||||||
#endif
|
#endif
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
@ -44,13 +46,13 @@ 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,
|
ck_assert_msg(ntohs(k) == i,
|
||||||
"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, &l);
|
||||||
fail_unless(l == i,
|
ck_assert_msg(l == i,
|
||||||
"Bad value on readshort for %d: %d != %d",
|
"Bad value on readshort for %d: %d != %d",
|
||||||
i, l, i);
|
i, l, i);
|
||||||
}
|
}
|
||||||
|
@ -71,13 +73,13 @@ START_TEST(test_read_putlong)
|
||||||
|
|
||||||
putlong(&p, j);
|
putlong(&p, j);
|
||||||
|
|
||||||
fail_unless(ntohl(k) == j,
|
ck_assert_msg(ntohl(k) == j,
|
||||||
"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,
|
ck_assert_msg(l == j,
|
||||||
"Bad value on readlong for %d: %d != %d", i, l, j);
|
"Bad value on readlong for %d: %d != %d", i, l, j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,7 +98,8 @@ START_TEST(test_read_name_empty_loop)
|
||||||
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');
|
ck_assert(rv == 0);
|
||||||
|
ck_assert(buf[1023] == 'A');
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
@ -113,7 +116,8 @@ START_TEST(test_read_name_inf_loop)
|
||||||
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');
|
ck_assert(rv == 3);
|
||||||
|
ck_assert(buf[4] == '\a');
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
@ -136,7 +140,8 @@ START_TEST(test_read_name_longname)
|
||||||
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');
|
ck_assert(rv == 256);
|
||||||
|
ck_assert(buf[256] == '\a');
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
@ -152,7 +157,7 @@ START_TEST(test_read_name_onejump)
|
||||||
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);
|
ck_assert(rv == 9);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
@ -174,8 +179,8 @@ START_TEST(test_read_name_badjump_start)
|
||||||
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);
|
ck_assert(rv == 0);
|
||||||
fail_unless(buf[0] == 0);
|
ck_assert(buf[0] == 0);
|
||||||
}
|
}
|
||||||
free(jumper);
|
free(jumper);
|
||||||
}
|
}
|
||||||
|
@ -199,9 +204,8 @@ START_TEST(test_read_name_badjump_second)
|
||||||
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);
|
ck_assert(rv == 4);
|
||||||
fail_unless(strcmp("BA.", buf) == 0,
|
ck_assert_str_eq("BA.", buf);
|
||||||
"buf is not BA: %s", buf);
|
|
||||||
}
|
}
|
||||||
free(jumper);
|
free(jumper);
|
||||||
}
|
}
|
||||||
|
@ -213,17 +217,14 @@ START_TEST(test_putname)
|
||||||
char buf[256];
|
char buf[256];
|
||||||
char *domain = "BADGER.BADGER.KRYO.SE";
|
char *domain = "BADGER.BADGER.KRYO.SE";
|
||||||
char *b;
|
char *b;
|
||||||
int len;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
len = 256;
|
|
||||||
|
|
||||||
memset(buf, 0, 256);
|
memset(buf, 0, 256);
|
||||||
b = buf;
|
b = buf;
|
||||||
ret = putname(&b, 256, domain);
|
ret = putname(&b, 256, domain);
|
||||||
|
|
||||||
fail_unless(ret == strlen(domain) + 1);
|
ck_assert(ret == strlen(domain) + 1);
|
||||||
fail_unless(strncmp(buf, out, ret) == 0, "Happy flow failed");
|
ck_assert_msg(strncmp(buf, out, ret) == 0, "Happy flow failed");
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
@ -234,17 +235,14 @@ START_TEST(test_putname_nodot)
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||||
char *b;
|
char *b;
|
||||||
int len;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
len = 256;
|
|
||||||
|
|
||||||
memset(buf, 0, 256);
|
memset(buf, 0, 256);
|
||||||
b = buf;
|
b = buf;
|
||||||
ret = putname(&b, 256, nodot);
|
ret = putname(&b, 256, nodot);
|
||||||
|
|
||||||
fail_unless(ret == -1);
|
ck_assert(ret == -1);
|
||||||
fail_unless(b == buf);
|
ck_assert(b == buf);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
@ -259,23 +257,20 @@ START_TEST(test_putname_toolong)
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ."
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ."
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ.";
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ.";
|
||||||
char *b;
|
char *b;
|
||||||
int len;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
len = 256;
|
|
||||||
|
|
||||||
memset(buf, 0, 256);
|
memset(buf, 0, 256);
|
||||||
b = buf;
|
b = buf;
|
||||||
ret = putname(&b, 256, toolong);
|
ret = putname(&b, 256, toolong);
|
||||||
|
|
||||||
fail_unless(ret == -1);
|
ck_assert(ret == -1);
|
||||||
fail_unless(b == buf);
|
ck_assert(b == buf);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
|
||||||
TCase *
|
TCase *
|
||||||
test_read_create_tests()
|
test_read_create_tests(void)
|
||||||
{
|
{
|
||||||
TCase *tc;
|
TCase *tc;
|
||||||
|
|
||||||
|
|
10
tests/test.c
10
tests/test.c
|
@ -1,7 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
|
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||||
|
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
* copyright notice and this permission notice appear in all copies.
|
* copyright notice and this permission notice appear in all copies.
|
||||||
*
|
*
|
||||||
|
@ -23,7 +24,7 @@
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
int
|
int
|
||||||
main()
|
main(void)
|
||||||
{
|
{
|
||||||
SRunner *runner;
|
SRunner *runner;
|
||||||
Suite *iodine;
|
Suite *iodine;
|
||||||
|
@ -38,6 +39,9 @@ main()
|
||||||
test = test_base64_create_tests();
|
test = test_base64_create_tests();
|
||||||
suite_add_tcase(iodine, test);
|
suite_add_tcase(iodine, test);
|
||||||
|
|
||||||
|
test = test_common_create_tests();
|
||||||
|
suite_add_tcase(iodine, test);
|
||||||
|
|
||||||
test = test_dns_create_tests();
|
test = test_dns_create_tests();
|
||||||
suite_add_tcase(iodine, test);
|
suite_add_tcase(iodine, test);
|
||||||
|
|
||||||
|
|
26
tests/test.h
26
tests/test.h
|
@ -1,7 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
|
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||||
|
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
* copyright notice and this permission notice appear in all copies.
|
* copyright notice and this permission notice appear in all copies.
|
||||||
*
|
*
|
||||||
|
@ -17,21 +18,22 @@
|
||||||
#ifndef __TEST_H__
|
#ifndef __TEST_H__
|
||||||
#define __TEST_H__
|
#define __TEST_H__
|
||||||
|
|
||||||
TCase *test_base32_create_tests();
|
TCase *test_base32_create_tests(void);
|
||||||
TCase *test_base64_create_tests();
|
TCase *test_base64_create_tests(void);
|
||||||
TCase *test_dns_create_tests();
|
TCase *test_common_create_tests(void);
|
||||||
TCase *test_encoding_create_tests();
|
TCase *test_dns_create_tests(void);
|
||||||
TCase *test_read_create_tests();
|
TCase *test_encoding_create_tests(void);
|
||||||
TCase *test_login_create_tests();
|
TCase *test_read_create_tests(void);
|
||||||
TCase *test_user_create_tests();
|
TCase *test_login_create_tests(void);
|
||||||
TCase *test_fw_query_create_tests();
|
TCase *test_user_create_tests(void);
|
||||||
|
TCase *test_fw_query_create_tests(void);
|
||||||
|
|
||||||
char *va_str(const char *, ...);
|
char *va_str(const char *, ...);
|
||||||
|
|
||||||
#if (CHECK_MAJOR_VERSION == 0 && \
|
#if (CHECK_MAJOR_VERSION == 0 && \
|
||||||
((CHECK_MINOR_VERSION == 9 && CHECK_MICRO_VERSION < 2) || \
|
((CHECK_MINOR_VERSION == 9 && CHECK_MICRO_VERSION < 2) || \
|
||||||
(CHECK_MINOR_VERSION < 9)))
|
(CHECK_MINOR_VERSION < 9)))
|
||||||
#define tcase_set_timeout(...)
|
#define tcase_set_timeout(...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
122
tests/user.c
122
tests/user.c
|
@ -1,7 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
|
* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
|
||||||
|
* 2006-2009 Bjorn Andersson <flex@kryo.se>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
* copyright notice and this permission notice appear in all copies.
|
* copyright notice and this permission notice appear in all copies.
|
||||||
*
|
*
|
||||||
|
@ -19,8 +20,8 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "encoding.h"
|
#include "encoding.h"
|
||||||
|
@ -32,44 +33,21 @@ START_TEST(test_init_users)
|
||||||
in_addr_t ip;
|
in_addr_t ip;
|
||||||
char givenip[16];
|
char givenip[16];
|
||||||
int i;
|
int i;
|
||||||
|
int count;
|
||||||
|
|
||||||
ip = inet_addr("127.0.0.1");
|
ip = inet_addr("127.0.0.1");
|
||||||
init_users(ip, 27);
|
count = init_users(ip, 27);
|
||||||
for (i = 0; i < USERS; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
fail_unless(users[i].id == i);
|
ck_assert(users[i].id == i);
|
||||||
fail_unless(users[i].q.id == 0);
|
ck_assert(users[i].q.id == 0);
|
||||||
fail_unless(users[i].inpacket.len == 0);
|
ck_assert(users[i].inpacket.len == 0);
|
||||||
fail_unless(users[i].outpacket.len == 0);
|
ck_assert(users[i].outpacket.len == 0);
|
||||||
snprintf(givenip, sizeof(givenip), "127.0.0.%d", i + 2);
|
snprintf(givenip, sizeof(givenip), "127.0.0.%d", i + 2);
|
||||||
fail_unless(users[i].tun_ip == inet_addr(givenip));
|
ck_assert(users[i].tun_ip == inet_addr(givenip));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_users_waiting)
|
|
||||||
{
|
|
||||||
in_addr_t ip;
|
|
||||||
|
|
||||||
ip = inet_addr("127.0.0.1");
|
|
||||||
init_users(ip, 27);
|
|
||||||
|
|
||||||
fail_unless(users_waiting_on_reply() == 0);
|
|
||||||
|
|
||||||
users[3].active = 1;
|
|
||||||
|
|
||||||
fail_unless(users_waiting_on_reply() == 0);
|
|
||||||
|
|
||||||
users[3].last_pkt = time(NULL);
|
|
||||||
|
|
||||||
fail_unless(users_waiting_on_reply() == 0);
|
|
||||||
|
|
||||||
users[3].conn = CONN_DNS_NULL;
|
|
||||||
users[3].q.id = 1;
|
|
||||||
|
|
||||||
fail_unless(users_waiting_on_reply() == 1);
|
|
||||||
}
|
|
||||||
END_TEST
|
|
||||||
|
|
||||||
START_TEST(test_find_user_by_ip)
|
START_TEST(test_find_user_by_ip)
|
||||||
{
|
{
|
||||||
in_addr_t ip;
|
in_addr_t ip;
|
||||||
|
@ -80,20 +58,25 @@ START_TEST(test_find_user_by_ip)
|
||||||
users[0].conn = CONN_DNS_NULL;
|
users[0].conn = CONN_DNS_NULL;
|
||||||
|
|
||||||
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);
|
ck_assert(find_user_by_ip(testip) == -1);
|
||||||
|
|
||||||
testip = (unsigned int) inet_addr("127.0.0.2");
|
testip = (unsigned int) inet_addr("127.0.0.2");
|
||||||
fail_unless(find_user_by_ip(testip) == -1);
|
ck_assert(find_user_by_ip(testip) == -1);
|
||||||
|
|
||||||
users[0].active = 1;
|
users[0].active = 1;
|
||||||
|
|
||||||
testip = (unsigned int) inet_addr("127.0.0.2");
|
testip = (unsigned int) inet_addr("127.0.0.2");
|
||||||
fail_unless(find_user_by_ip(testip) == -1);
|
ck_assert(find_user_by_ip(testip) == -1);
|
||||||
|
|
||||||
users[0].last_pkt = time(NULL);
|
users[0].last_pkt = time(NULL);
|
||||||
|
|
||||||
testip = (unsigned int) inet_addr("127.0.0.2");
|
testip = (unsigned int) inet_addr("127.0.0.2");
|
||||||
fail_unless(find_user_by_ip(testip) == 0);
|
ck_assert(find_user_by_ip(testip) == -1);
|
||||||
|
|
||||||
|
users[0].authenticated = 1;
|
||||||
|
|
||||||
|
testip = (unsigned int) inet_addr("127.0.0.2");
|
||||||
|
ck_assert(find_user_by_ip(testip) == 0);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
@ -104,25 +87,25 @@ START_TEST(test_all_users_waiting_to_send)
|
||||||
ip = inet_addr("127.0.0.1");
|
ip = inet_addr("127.0.0.1");
|
||||||
init_users(ip, 27);
|
init_users(ip, 27);
|
||||||
|
|
||||||
fail_unless(all_users_waiting_to_send() == 1);
|
ck_assert(all_users_waiting_to_send() == 1);
|
||||||
|
|
||||||
users[0].conn = CONN_DNS_NULL;
|
users[0].conn = CONN_DNS_NULL;
|
||||||
users[0].active = 1;
|
users[0].active = 1;
|
||||||
|
|
||||||
fail_unless(all_users_waiting_to_send() == 1);
|
ck_assert(all_users_waiting_to_send() == 1);
|
||||||
|
|
||||||
users[0].last_pkt = time(NULL);
|
users[0].last_pkt = time(NULL);
|
||||||
users[0].outpacket.len = 0;
|
users[0].outpacket.len = 0;
|
||||||
|
|
||||||
fail_unless(all_users_waiting_to_send() == 0);
|
ck_assert(all_users_waiting_to_send() == 0);
|
||||||
|
|
||||||
#ifdef OUTPACKETQ_LEN
|
#ifdef OUTPACKETQ_LEN
|
||||||
users[0].outpacketq_filled = 1;
|
users[0].outpacketq_filled = 1;
|
||||||
#else
|
#else
|
||||||
users[0].outpacket.len = 44;
|
users[0].outpacket.len = 44;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
fail_unless(all_users_waiting_to_send() == 1);
|
ck_assert(all_users_waiting_to_send() == 1);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
@ -135,22 +118,26 @@ START_TEST(test_find_available_user)
|
||||||
init_users(ip, 27);
|
init_users(ip, 27);
|
||||||
|
|
||||||
for (i = 0; i < USERS; i++) {
|
for (i = 0; i < USERS; i++) {
|
||||||
fail_unless(find_available_user() == i);
|
users[i].authenticated = 1;
|
||||||
|
users[i].authenticated_raw = 1;
|
||||||
|
ck_assert(find_available_user() == i);
|
||||||
|
ck_assert(users[i].authenticated == 0);
|
||||||
|
ck_assert(users[i].authenticated_raw == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < USERS; i++) {
|
for (i = 0; i < USERS; i++) {
|
||||||
fail_unless(find_available_user() == -1);
|
ck_assert(find_available_user() == -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
users[3].active = 0;
|
users[3].active = 0;
|
||||||
|
|
||||||
fail_unless(find_available_user() == 3);
|
ck_assert(find_available_user() == 3);
|
||||||
fail_unless(find_available_user() == -1);
|
ck_assert(find_available_user() == -1);
|
||||||
|
|
||||||
users[3].last_pkt = 55;
|
users[3].last_pkt = 55;
|
||||||
|
|
||||||
fail_unless(find_available_user() == 3);
|
ck_assert(find_available_user() == 3);
|
||||||
fail_unless(find_available_user() == -1);
|
ck_assert(find_available_user() == -1);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
@ -163,33 +150,32 @@ START_TEST(test_find_available_user_small_net)
|
||||||
init_users(ip, 29); /* this should result in 5 enabled users */
|
init_users(ip, 29); /* this should result in 5 enabled users */
|
||||||
|
|
||||||
for (i = 0; i < 5; i++) {
|
for (i = 0; i < 5; i++) {
|
||||||
fail_unless(find_available_user() == i);
|
ck_assert(find_available_user() == i);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < USERS; i++) {
|
for (i = 0; i < USERS; i++) {
|
||||||
fail_unless(find_available_user() == -1);
|
ck_assert(find_available_user() == -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
users[3].active = 0;
|
users[3].active = 0;
|
||||||
|
|
||||||
fail_unless(find_available_user() == 3);
|
ck_assert(find_available_user() == 3);
|
||||||
fail_unless(find_available_user() == -1);
|
ck_assert(find_available_user() == -1);
|
||||||
|
|
||||||
users[3].last_pkt = 55;
|
users[3].last_pkt = 55;
|
||||||
|
|
||||||
fail_unless(find_available_user() == 3);
|
ck_assert(find_available_user() == 3);
|
||||||
fail_unless(find_available_user() == -1);
|
ck_assert(find_available_user() == -1);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
TCase *
|
TCase *
|
||||||
test_user_create_tests()
|
test_user_create_tests(void)
|
||||||
{
|
{
|
||||||
TCase *tc;
|
TCase *tc;
|
||||||
|
|
||||||
tc = tcase_create("User");
|
tc = tcase_create("User");
|
||||||
tcase_add_test(tc, test_init_users);
|
tcase_add_test(tc, test_init_users);
|
||||||
tcase_add_test(tc, test_users_waiting);
|
|
||||||
tcase_add_test(tc, test_find_user_by_ip);
|
tcase_add_test(tc, test_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);
|
||||||
|
|
Loading…
Add table
Reference in a new issue