mirror of
git://git.code.sf.net/p/xtables-addons/xtables-addons
synced 2026-04-21 03:19:40 +02:00
Compare commits
484 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aee5aedc63 | ||
|
|
54d784ffdf | ||
|
|
076610e3af | ||
|
|
7a1ad32d1a | ||
|
|
40094379dd | ||
|
|
ce37dd6984 | ||
|
|
31fdd86247 | ||
|
|
36df60c940 | ||
|
|
2b671829d8 | ||
|
|
9ab6a0ee0d | ||
|
|
365d5edfb3 | ||
|
|
75cd1d7d6a | ||
|
|
b0dc0e6f4c | ||
|
|
bc1c37618a | ||
|
|
d7aeb7da4b | ||
|
|
487da26146 | ||
|
|
434dea2b53 | ||
|
|
30d227135b | ||
|
|
a508ec048c | ||
|
|
3069c9a3a2 | ||
|
|
5245220246 | ||
|
|
ec97cd6d89 | ||
|
|
dc58126e37 | ||
|
|
d509951fcf | ||
|
|
6ef91897b2 | ||
|
|
c7f60a33c5 | ||
|
|
65b75fc19c | ||
|
|
bac406bff5 | ||
|
|
aa53733851 | ||
|
|
9ccd32d840 | ||
|
|
939d3c8b27 | ||
|
|
c2d93e16fd | ||
|
|
04aed87cb6 | ||
|
|
5ef3a7c436 | ||
|
|
27a77b62f5 | ||
|
|
c10e974bd6 | ||
|
|
01d864f4fc | ||
|
|
071c95b750 | ||
|
|
a141cc311c | ||
|
|
7e92ce7ce6 | ||
|
|
21da1dfea5 | ||
|
|
6c17eb46b5 | ||
|
|
74ea647303 | ||
|
|
e0154bfa4c | ||
|
|
cd18e2479c | ||
|
|
d2f3541cda | ||
|
|
1fed8bbf09 | ||
|
|
6e8fb7f231 | ||
|
|
eceaee3431 | ||
|
|
77b29a62ee | ||
|
|
33db992c39 | ||
|
|
85d8f98dd7 | ||
|
|
e84391ce66 | ||
|
|
ef7fb0db7f | ||
|
|
4203259e5a | ||
|
|
e3956498ac | ||
|
|
6f730f3ab2 | ||
|
|
2b590a35fd | ||
|
|
3dd33dfe93 | ||
|
|
d417077816 | ||
|
|
d057f6d6f0 | ||
|
|
b2fc85c589 | ||
|
|
fa1348455d | ||
|
|
1a5c079e6b | ||
|
|
75b3762ef4 | ||
|
|
cfb72bf468 | ||
|
|
1b0790d151 | ||
|
|
a5355e74ea | ||
|
|
757bf0e993 | ||
|
|
cea4817a46 | ||
|
|
2dc79fe008 | ||
|
|
b60f8f1de2 | ||
|
|
499c6db75e | ||
|
|
509953daec | ||
|
|
c53a86874d | ||
|
|
309b960012 | ||
|
|
f4882ca029 | ||
|
|
8fd3eb56eb | ||
|
|
94574fb829 | ||
|
|
32871bad39 | ||
|
|
0ba44bd461 | ||
|
|
d4e6e3d155 | ||
|
|
18043f3e3a | ||
|
|
ff27f61477 | ||
|
|
9f59f21614 | ||
|
|
7a8bfed52c | ||
|
|
1edc9b943b | ||
|
|
ebfa77795a | ||
|
|
4a8aa505c4 | ||
|
|
4654ee127f | ||
|
|
a7a77d7146 | ||
|
|
2a61ca7d4b | ||
|
|
39de351a91 | ||
|
|
07bf41a294 | ||
|
|
07cd29d9ce | ||
|
|
eb9634aee6 | ||
|
|
19f241a09c | ||
|
|
0a29c1d32f | ||
|
|
93a17fdde0 | ||
|
|
80444b0d31 | ||
|
|
f180c0e5c6 | ||
|
|
ca8ebe4467 | ||
|
|
e82410735a | ||
|
|
89e72bb0f4 | ||
|
|
77b9f2024c | ||
|
|
0edb572f6e | ||
|
|
8b1ff64b8b | ||
|
|
ebb61aa3c9 | ||
|
|
bd2e6108f3 | ||
|
|
288492c820 | ||
|
|
e425c8f277 | ||
|
|
e3e88827fb | ||
|
|
6c709fd682 | ||
|
|
1b53724a61 | ||
|
|
983b28fe8e | ||
|
|
3141b2ff86 | ||
|
|
980a53348f | ||
|
|
8ea781e257 | ||
|
|
7e39ee66e0 | ||
|
|
65e97a66e6 | ||
|
|
d82b20ead7 | ||
|
|
c5d4dd0bcf | ||
|
|
0168f8e8a2 | ||
|
|
dc22ec7bd1 | ||
|
|
80ded69d77 | ||
|
|
af1bfd7684 | ||
|
|
b05712a14d | ||
|
|
7d8ffffd85 | ||
|
|
75212f3972 | ||
|
|
77027ff8d3 | ||
|
|
e9a70bbf15 | ||
|
|
25bf680ead | ||
|
|
4d547c2bfc | ||
|
|
f7c7264a65 | ||
|
|
0f42828fd6 | ||
|
|
e2da87230a | ||
|
|
1dc1ae3ec5 | ||
|
|
3bbea41b30 | ||
|
|
549508499c | ||
|
|
748498038a | ||
|
|
3ee2b5fb93 | ||
|
|
5bcdf7f10e | ||
|
|
6599996ccc | ||
|
|
bf8d44cca4 | ||
|
|
1721b76a0f | ||
|
|
81ad2519a9 | ||
|
|
f65ea59795 | ||
|
|
baf7b1091a | ||
|
|
2ae0413e31 | ||
|
|
db76ea9a5c | ||
|
|
3ed1a3cbf0 | ||
|
|
9c4c76f9e2 | ||
|
|
7f33590df8 | ||
|
|
6733265358 | ||
|
|
f757049112 | ||
|
|
21cdf786f7 | ||
|
|
7c248871f8 | ||
|
|
3500a38767 | ||
|
|
cf9b60a57e | ||
|
|
e5eedb25c2 | ||
|
|
e3ae8dcb81 | ||
|
|
aca381d3b6 | ||
|
|
bb15becc88 | ||
|
|
14458b3a7e | ||
|
|
2d36632d4a | ||
|
|
b5e2c7255a | ||
|
|
376a89e7d1 | ||
|
|
03ec8a7696 | ||
|
|
442982f04e | ||
|
|
98b853cea3 | ||
|
|
59401339b8 | ||
|
|
121836ce80 | ||
|
|
c23df41f6e | ||
|
|
fb2eea69af | ||
|
|
4815e3a8a6 | ||
|
|
f9922c6f85 | ||
|
|
24491d55d7 | ||
|
|
7ab69a17fa | ||
|
|
d2339410b2 | ||
|
|
649caf61e8 | ||
|
|
922a9be87d | ||
|
|
4d48511f01 | ||
|
|
6dedbef3d4 | ||
|
|
fe49f9b6a4 | ||
|
|
283974cbbe | ||
|
|
7deca86132 | ||
|
|
7d6435f422 | ||
|
|
748f5cfdd0 | ||
|
|
d402cec807 | ||
|
|
b42190c04b | ||
|
|
4dcefe4b95 | ||
|
|
a2662b0121 | ||
|
|
03354eed44 | ||
|
|
ddda6972a4 | ||
|
|
8e7359bb92 | ||
|
|
40786af1c0 | ||
|
|
f6e2fb815e | ||
|
|
f171a0f07e | ||
|
|
d17ddb9c94 | ||
|
|
54d80a73b4 | ||
|
|
43921c5834 | ||
|
|
9a18a05d02 | ||
|
|
5b472be9bb | ||
|
|
4dd35fb564 | ||
|
|
b32d6dad90 | ||
|
|
5b2cb97c06 | ||
|
|
ca894d6687 | ||
|
|
db717ec479 | ||
|
|
a46ca95078 | ||
|
|
8b2a266db0 | ||
|
|
03e10ff544 | ||
|
|
37986fd785 | ||
|
|
8ff64f4ef4 | ||
|
|
93f6c1a312 | ||
|
|
b535abce2e | ||
|
|
5db988626f | ||
|
|
c6f8f72bf1 | ||
|
|
47cbb07162 | ||
|
|
79c55ab325 | ||
|
|
11ab4d0acc | ||
|
|
8ae9ac5433 | ||
|
|
2060a58912 | ||
|
|
e1eed2b05e | ||
|
|
7b077c7459 | ||
|
|
ad146dbeef | ||
|
|
fb4c49d794 | ||
|
|
a17203e036 | ||
|
|
987402dc61 | ||
|
|
295b6b6d73 | ||
|
|
7338a2a400 | ||
|
|
ba35636718 | ||
|
|
fd19a40dbe | ||
|
|
937571bb9d | ||
|
|
346fc1a376 | ||
|
|
56535551b3 | ||
|
|
dd8fdd09c8 | ||
|
|
beb3358297 | ||
|
|
02d8bdc3d9 | ||
|
|
42b77a386a | ||
|
|
6340363394 | ||
|
|
c9b4e9c518 | ||
|
|
8dd316ed56 | ||
|
|
48327605c6 | ||
|
|
414e95ffb1 | ||
|
|
749e0b788a | ||
|
|
7512101bca | ||
|
|
1a17ed6a45 | ||
|
|
1aeaadd740 | ||
|
|
0acbe528ac | ||
|
|
f5fe2dc801 | ||
|
|
524201adcc | ||
|
|
7cfd3b1dbb | ||
|
|
ab13e58f96 | ||
|
|
548922388c | ||
|
|
43864ac6f1 | ||
|
|
2ef714cc93 | ||
|
|
8b71d90002 | ||
|
|
457e86b908 | ||
|
|
9b99211326 | ||
|
|
c96845a311 | ||
|
|
01e4bace4d | ||
|
|
84704346e7 | ||
|
|
77bd7953fb | ||
|
|
8c02b00a33 | ||
|
|
1f8b91ce53 | ||
|
|
dac1b7d506 | ||
|
|
40d0345f1e | ||
|
|
3e70d6289d | ||
|
|
d99c8570f3 | ||
|
|
cf7a40fbe7 | ||
|
|
0de9f38412 | ||
|
|
b4b0ab9ef4 | ||
|
|
b20e02869e | ||
|
|
ebd603b8fb | ||
|
|
1945c545dd | ||
|
|
7952a7d253 | ||
|
|
c82da14d2b | ||
|
|
9f1af79901 | ||
|
|
50c4ee1a5e | ||
|
|
351b040f4a | ||
|
|
6ed735a810 | ||
|
|
d643fc4b6c | ||
|
|
0fe32e7443 | ||
|
|
3c0397867b | ||
|
|
16e4968343 | ||
|
|
8c910aa82b | ||
|
|
6340d999d7 | ||
|
|
11af976e8b | ||
|
|
a4afc4159e | ||
|
|
24bb655130 | ||
|
|
2eaa5c5606 | ||
|
|
0593b96c2c | ||
|
|
6f1c1ef0ce | ||
|
|
d5ff452ea5 | ||
|
|
c012379e0b | ||
|
|
15de3beb63 | ||
|
|
160e04d13e | ||
|
|
359ecc7a8c | ||
|
|
6ee71ed485 | ||
|
|
7bd0157a9a | ||
|
|
6f8582eb5e | ||
|
|
df7168bb4d | ||
|
|
0aa7be2f1d | ||
|
|
d9cd40e9fa | ||
|
|
8bd6ef78f9 | ||
|
|
578af6f726 | ||
|
|
22edc7a24d | ||
|
|
304e5e52ca | ||
|
|
3f7288abfe | ||
|
|
aad0cafd19 | ||
|
|
17a0312848 | ||
|
|
c66d291eb8 | ||
|
|
cb407ce7c4 | ||
|
|
3f426f3b43 | ||
|
|
0b3ae22673 | ||
|
|
bc5a7d8e3a | ||
|
|
0628857068 | ||
|
|
de4f6e8994 | ||
|
|
439dd913f1 | ||
|
|
9568747d94 | ||
|
|
20365cf762 | ||
|
|
fa601c0fa7 | ||
|
|
00573d0172 | ||
|
|
c7036a88f1 | ||
|
|
af21c1d369 | ||
|
|
b132101b63 | ||
|
|
71beab548d | ||
|
|
6de54e5fcd | ||
|
|
a921427746 | ||
|
|
2b2b6246f0 | ||
|
|
98e5dfd6ef | ||
|
|
9e5c2e7ee9 | ||
|
|
284c0e9493 | ||
|
|
5284b5db92 | ||
|
|
36035d52d3 | ||
|
|
4d94687c15 | ||
|
|
7070678ab4 | ||
|
|
f6281d498c | ||
|
|
2cab32596a | ||
|
|
08f6a82bdc | ||
|
|
82a8524f1a | ||
|
|
6bb354d3f0 | ||
|
|
5184176c3b | ||
|
|
430723ece1 | ||
|
|
f1dc7f960c | ||
|
|
370f47b000 | ||
|
|
8e812620f0 | ||
|
|
204b612e23 | ||
|
|
c2c86f4b3d | ||
|
|
379e685b0f | ||
|
|
69dd0686e2 | ||
|
|
48325a209e | ||
|
|
96f501ab89 | ||
|
|
3c1bf73e8e | ||
|
|
e0276b4875 | ||
|
|
1bc7f1be67 | ||
|
|
3c3adcbd07 | ||
|
|
da6a9b932c | ||
|
|
5f290cd4a0 | ||
|
|
181a9cab43 | ||
|
|
a819458cba | ||
|
|
654862af21 | ||
|
|
0d8ae29a60 | ||
|
|
e05a4d9586 | ||
|
|
0541154a5e | ||
|
|
00199427ac | ||
|
|
35b00f8c3f | ||
|
|
1f3150bdf9 | ||
|
|
13c73af796 | ||
|
|
ba9a3efec1 | ||
|
|
f474c7d4d4 | ||
|
|
4a350ddd03 | ||
|
|
628d137f12 | ||
|
|
28ecf45548 | ||
|
|
58839b9b86 | ||
|
|
e436948ebd | ||
|
|
79d54ebd7c | ||
|
|
0b64b27172 | ||
|
|
d116000784 | ||
|
|
4b5f0b12d9 | ||
|
|
c8dde526f2 | ||
|
|
3058e42a21 | ||
|
|
40b30f7f27 | ||
|
|
aaad5f53ac | ||
|
|
db1057158f | ||
|
|
713c31e8f7 | ||
|
|
e5ffb39750 | ||
|
|
19067393b6 | ||
|
|
1de82a88a1 | ||
|
|
9928c864ab | ||
|
|
45515a0afd | ||
|
|
75f80fa8f8 | ||
|
|
d8dc72d151 | ||
|
|
cee3d25d49 | ||
|
|
afbeb2fb47 | ||
|
|
c0dc0858de | ||
|
|
b04317576b | ||
|
|
af2bbf0352 | ||
|
|
db9bb2778d | ||
|
|
674560d2d9 | ||
|
|
7ab033e64c | ||
|
|
3131448443 | ||
|
|
71322e614c | ||
|
|
d3fdfe08dd | ||
|
|
46f9ddbf59 | ||
|
|
e37985b527 | ||
|
|
0ccd55abd9 | ||
|
|
60123a8c07 | ||
|
|
504f1089fb | ||
|
|
e119350000 | ||
|
|
a260e3349f | ||
|
|
5cb36ed213 | ||
|
|
1a5b9f0e02 | ||
|
|
2c53605084 | ||
|
|
537f25dbad | ||
|
|
63a1e5329f | ||
|
|
b0a6111054 | ||
|
|
b07434386b | ||
|
|
0c963dee06 | ||
|
|
09bfb8496e | ||
|
|
9d1afc4268 | ||
|
|
342ccf62b2 | ||
|
|
adabd647b1 | ||
|
|
26f25a43a9 | ||
|
|
bcda21a2b0 | ||
|
|
4e6bc8af95 | ||
|
|
bd4be0d991 | ||
|
|
1f736c8203 | ||
|
|
90fa3ab9e2 | ||
|
|
fd82a312d6 | ||
|
|
27c1676821 | ||
|
|
3e26335cbd | ||
|
|
f4b96672ef | ||
|
|
c3d080f21a | ||
|
|
cb268031b7 | ||
|
|
ac44a5a1fe | ||
|
|
a3baa78ae2 | ||
|
|
47e002127c | ||
|
|
03363a528a | ||
|
|
58b016f0af | ||
|
|
8d64e7bd50 | ||
|
|
dd6cb27da4 | ||
|
|
06c01131e8 | ||
|
|
a44c4e4b1d | ||
|
|
1fb6f187d3 | ||
|
|
83e474f9ab | ||
|
|
efd4c91557 | ||
|
|
65a257a67d | ||
|
|
5b07e04600 | ||
|
|
6b175b40cb | ||
|
|
0887365f8b | ||
|
|
cebadbfcd7 | ||
|
|
380b1b6997 | ||
|
|
8e5219636a | ||
|
|
760edd3db6 | ||
|
|
502c1c05aa | ||
|
|
a7ceccc0f4 | ||
|
|
10bd08d0f3 | ||
|
|
1e5315d338 | ||
|
|
579484ed70 | ||
|
|
2aa32d4bce | ||
|
|
5aee8738ed | ||
|
|
1111edfd85 | ||
|
|
0d47cb8b37 | ||
|
|
1c55aec64a | ||
|
|
dd26ab476c | ||
|
|
4bf667d8eb | ||
|
|
0a88bd3435 | ||
|
|
62fb261265 | ||
|
|
d97f77a8f5 | ||
|
|
822c6bebe2 | ||
|
|
fdf42a3a50 | ||
|
|
6b2ca78af7 | ||
|
|
ee24cd1ac1 | ||
|
|
71812a2053 | ||
|
|
31e4e18998 | ||
|
|
9fb2ffe1d3 | ||
|
|
23e83aa04c | ||
|
|
77ee63ba8b | ||
|
|
49e59a6dce | ||
|
|
137ecb9814 | ||
|
|
7e25254e93 | ||
|
|
0c9ae3cb1b | ||
|
|
471e747fc0 |
20
.gitignore
vendored
20
.gitignore
vendored
@@ -2,23 +2,25 @@
|
||||
*.lo
|
||||
*.loT
|
||||
*.o
|
||||
.deps
|
||||
.libs
|
||||
.deps/
|
||||
.dirstamp
|
||||
.libs/
|
||||
Makefile
|
||||
Makefile.in
|
||||
GNUmakefile
|
||||
|
||||
/downloads
|
||||
|
||||
/Makefile.iptrules
|
||||
/Makefile.mans
|
||||
/.*.lst
|
||||
/matches.man
|
||||
/targets.man
|
||||
|
||||
/aclocal.m4
|
||||
/autom4te*.cache
|
||||
/compile
|
||||
/autom4te.cache/
|
||||
/build-aux/
|
||||
/config.*
|
||||
/configure
|
||||
/depcomp
|
||||
/install-sh
|
||||
/libtool
|
||||
/ltmain.sh
|
||||
/missing
|
||||
/stamp-h1
|
||||
/xtables-addons.8
|
||||
|
||||
67
INSTALL
67
INSTALL
@@ -12,19 +12,21 @@ in combination with the kernel's Kbuild system.
|
||||
Supported configurations for this release
|
||||
=========================================
|
||||
|
||||
* iptables >= 1.4.3
|
||||
* iptables >= 1.4.5
|
||||
|
||||
* kernel-source >= 2.6.17, no upper bound known
|
||||
* kernel-source >= 2.6.29
|
||||
with prepared build/output directory
|
||||
- CONFIG_NF_CONNTRACK or CONFIG_IP_NF_CONNTRACK
|
||||
- CONFIG_NF_CONNTRACK_MARK or CONFIG_IP_NF_CONNTRACK_MARK
|
||||
enabled =y or as module (=m)
|
||||
- CONFIG_CONNECTOR y/m if you wish to receive userspace
|
||||
notifications from pknock through netlink/connector
|
||||
|
||||
Extra notes:
|
||||
Compilation of ipset-genl-6.x is disabled by default. It has
|
||||
additional requirements.
|
||||
|
||||
* in the kernel 2.6.18.x series, >= 2.6.18.5 is required
|
||||
|
||||
* requires that no vendor backports interfere
|
||||
* libmnl
|
||||
* Linux kernel >= 2.6.35
|
||||
|
||||
|
||||
Selecting extensions
|
||||
@@ -39,6 +41,10 @@ Configuring and compiling
|
||||
|
||||
./configure [options]
|
||||
|
||||
--without-kbuild
|
||||
|
||||
Deactivate building kernel modules, and just do userspace parts.
|
||||
|
||||
--with-kbuild=
|
||||
|
||||
Specifies the path to the kernel build output directory. We need
|
||||
@@ -46,20 +52,18 @@ Configuring and compiling
|
||||
/lib/modules/$(running version)/build, which usually points to
|
||||
the right directory. (If not, you need to install something.)
|
||||
|
||||
--with-xtables=
|
||||
For RPM building, it should be /usr/src/linux-obj/...
|
||||
or whatever location the distro makes use of.
|
||||
|
||||
Specifies the path to the directory where we may find
|
||||
xtables.h, should it not be within the standard C compiler
|
||||
include path (/usr/include), or if you want to override it.
|
||||
The directory will be checked for xtables.h and
|
||||
include/xtables.h. (The latter to support both standard
|
||||
/usr/include and the iptables source root.)
|
||||
|
||||
--with-libxtdir=
|
||||
--with-xtlibdir=
|
||||
|
||||
Specifies the path to where the newly built extensions should
|
||||
be installed when `make install` is run. It uses the same
|
||||
default as the Xtables package, ${libexecdir}/xtables.
|
||||
be installed when `make install` is run. The default is to
|
||||
use the same path that Xtables/iptables modules use, as
|
||||
determined by `pkg-config xtables --variable xtlibdir`.
|
||||
Thus, this option normally does NOT need to be specified
|
||||
anymore, even if your distribution put modules in a strange
|
||||
location.
|
||||
|
||||
If you want to enable debugging, use
|
||||
|
||||
@@ -68,19 +72,33 @@ If you want to enable debugging, use
|
||||
(-O0 is used to turn off instruction reordering, which makes debugging
|
||||
much easier.)
|
||||
|
||||
To make use of a libxtables that is not in the default path, either
|
||||
|
||||
a) append the location of the pkg-config files like:
|
||||
|
||||
PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
|
||||
|
||||
(Assuming that files have been installed)
|
||||
or,
|
||||
|
||||
b) override the pkg-config variables, for example:
|
||||
|
||||
./configure libxtables_CFLAGS="-I../iptables/include" \
|
||||
libxtables_LIBS="-L../iptables/.libs \
|
||||
-Wl,-rpath,../iptables/.libs -lxtables"
|
||||
|
||||
(Use this in case you wish to use it without having to
|
||||
run `make install`. This is because the libxtables.pc pkgconfig
|
||||
file in ../iptables would already point to e.g. /usr/local.)
|
||||
|
||||
|
||||
Build-time options
|
||||
==================
|
||||
|
||||
V= controls the kernel's make verbosity.
|
||||
V= controls the verbosity of make commands.
|
||||
V=0 "silent" (output filename)
|
||||
V=1 "verbose" (entire gcc command line)
|
||||
|
||||
VU= controls the Xt-a make verbosity.
|
||||
VU=0 output filename
|
||||
VU=1 output filename and source file
|
||||
VU=2 entire gcc command line
|
||||
|
||||
|
||||
Note to distribution packagers
|
||||
==============================
|
||||
@@ -89,4 +107,5 @@ Except for --with-kbuild, distributions should not have a need to
|
||||
supply any other flags (besides --prefix=/usr and perhaps
|
||||
--libdir=/usr/lib64, etc.) to configure when all prerequired packages
|
||||
are installed. If iptables-devel is installed, necessary headers should
|
||||
be in /usr/include, so --with-xtables is not needed.
|
||||
already be in /usr/include, so that overriding PKG_CONFIG_PATH,
|
||||
libxtables_CFLAGS and libxtables_LIBS variables should not be needed.
|
||||
|
||||
29
Makefile.am
29
Makefile.am
@@ -1,25 +1,30 @@
|
||||
# -*- Makefile -*-
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
SUBDIRS = extensions
|
||||
SUBDIRS = extensions geoip
|
||||
|
||||
man_MANS := xtables-addons.8
|
||||
|
||||
xtables-addons.8: ${srcdir}/xtables-addons.8.in extensions/matches.man extensions/targets.man
|
||||
${am__verbose_GEN}sed -e '/@MATCHES@/ r extensions/matches.man' -e '/@TARGET@/ r extensions/targets.man' $< >$@;
|
||||
.PHONY: FORCE
|
||||
FORCE:
|
||||
|
||||
extensions/%:
|
||||
${MAKE} ${AM_MAKEFLAGS} -C $(@D) $(@F)
|
||||
xtables-addons.8: FORCE
|
||||
${MAKE} -f Makefile.mans all;
|
||||
|
||||
install-exec-local:
|
||||
install-exec-hook:
|
||||
depmod -a || :;
|
||||
|
||||
config.status: extensions/GNUmakefile.in
|
||||
config.status: Makefile.iptrules.in
|
||||
|
||||
tmpdir := $(shell mktemp -dtu)
|
||||
packer = xz
|
||||
packext = .tar.xz
|
||||
|
||||
.PHONY: tarball
|
||||
tarball:
|
||||
rm -Rf /tmp/xtables-addons-${PACKAGE_VERSION};
|
||||
pushd ${top_srcdir} && git archive --prefix=xtables-addons-${PACKAGE_VERSION}/ HEAD | tar -C /tmp -x && popd;
|
||||
pushd /tmp/xtables-addons-${PACKAGE_VERSION} && ./autogen.sh && popd;
|
||||
tar -C /tmp -cjf xtables-addons-${PACKAGE_VERSION}.tar.bz2 --owner=root --group=root xtables-addons-${PACKAGE_VERSION}/;
|
||||
rm -Rf /tmp/xtables-addons-${PACKAGE_VERSION};
|
||||
# do not use mkdir_p here.
|
||||
mkdir ${tmpdir}
|
||||
pushd ${top_srcdir} && git archive --prefix=${PACKAGE_NAME}-${PACKAGE_VERSION}/ HEAD | tar -C ${tmpdir} -x && popd;
|
||||
pushd ${tmpdir}/${PACKAGE_NAME}-${PACKAGE_VERSION} && ./autogen.sh && popd;
|
||||
tar --use=${packer} -C ${tmpdir} -cf ${PACKAGE_NAME}-${PACKAGE_VERSION}${packext} --owner=root --group=root ${PACKAGE_NAME}-${PACKAGE_VERSION}/;
|
||||
rm -Rf ${tmpdir};
|
||||
|
||||
31
Makefile.extra
Normal file
31
Makefile.extra
Normal file
@@ -0,0 +1,31 @@
|
||||
# -*- Makefile -*-
|
||||
# AUTOMAKE
|
||||
|
||||
export AM_CPPFLAGS
|
||||
export AM_CFLAGS
|
||||
XA_SRCDIR = ${srcdir}
|
||||
XA_TOPSRCDIR = ${top_srcdir}
|
||||
XA_ABSTOPSRCDIR = ${abs_top_srcdir}
|
||||
export XA_SRCDIR
|
||||
export XA_TOPSRCDIR
|
||||
export XA_ABSTOPSRCDIR
|
||||
|
||||
_mcall = -f ${top_builddir}/Makefile.iptrules
|
||||
|
||||
all-local: user-all-local
|
||||
|
||||
install-exec-local: user-install-local
|
||||
|
||||
clean-local: user-clean-local
|
||||
|
||||
user-all-local:
|
||||
${MAKE} ${_mcall} all;
|
||||
|
||||
# Have no user-install-data-local ATM
|
||||
user-install-local: user-install-exec-local
|
||||
|
||||
user-install-exec-local:
|
||||
${MAKE} ${_mcall} install;
|
||||
|
||||
user-clean-local:
|
||||
${MAKE} ${_mcall} clean;
|
||||
62
Makefile.iptrules.in
Normal file
62
Makefile.iptrules.in
Normal file
@@ -0,0 +1,62 @@
|
||||
# -*- Makefile -*-
|
||||
# MANUAL
|
||||
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
libexecdir = @libexecdir@
|
||||
xtlibdir = @xtlibdir@
|
||||
|
||||
CC = @CC@
|
||||
CCLD = ${CC}
|
||||
CFLAGS = @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
libxtables_CFLAGS = @libxtables_CFLAGS@
|
||||
libxtables_LIBS = @libxtables_LIBS@
|
||||
AM_DEPFLAGS = -Wp,-MMD,$(@D)/.$(@F).d,-MT,$@
|
||||
|
||||
AM_DEFAULT_VERBOSITY = 0
|
||||
am__v_CC_0 = @echo " CC " $@;
|
||||
am__v_CCLD_0 = @echo " CCLD " $@;
|
||||
am__v_GEN_0 = @echo " GEN " $@;
|
||||
am__v_SILENT_0 = @
|
||||
am__v_CC_ = ${am__v_CC_${AM_DEFAULT_VERBOSITY}}
|
||||
am__v_CCLD_ = ${am__v_CCLD_${AM_DEFAULT_VERBOSITY}}
|
||||
am__v_GEN_ = ${am__v_GEN_${AM_DEFAULT_VERBOSITY}}
|
||||
am__v_SILENT_ = ${am__v_SILENT_${AM_DEFAULT_VERBOSITY}}
|
||||
AM_V_CC = ${am__v_CC_${V}}
|
||||
AM_V_CCLD = ${am__v_CCLD_${V}}
|
||||
AM_V_GEN = ${am__v_GEN_${V}}
|
||||
AM_V_silent = ${am__v_GEN_${V}}
|
||||
|
||||
include ${XA_TOPSRCDIR}/mconfig
|
||||
-include ${XA_TOPSRCDIR}/mconfig.*
|
||||
include ${XA_SRCDIR}/Mbuild
|
||||
-include ${XA_SRCDIR}/Mbuild.*
|
||||
|
||||
targets := $(filter-out %/,${obj-m})
|
||||
subdirs_list := $(filter %/,${obj-m})
|
||||
|
||||
.SECONDARY:
|
||||
|
||||
.PHONY: all install clean
|
||||
|
||||
all: ${targets}
|
||||
@for i in ${subdirs_list}; do ${MAKE} -C $$i || exit $$?; done;
|
||||
|
||||
install: ${targets}
|
||||
@for i in ${subdirs_list}; do ${MAKE} -C $$i $@ || exit $$?; done;
|
||||
install -dm0755 "${DESTDIR}/${xtlibdir}";
|
||||
@for i in $^; do install -pm0755 $$i "${DESTDIR}/${xtlibdir}"; done;
|
||||
|
||||
clean:
|
||||
@for i in ${subdirs_list}; do ${MAKE} -C $$i $@ || exit $$?; done;
|
||||
rm -f *.oo *.so;
|
||||
|
||||
lib%.so: lib%.oo
|
||||
${AM_V_CCLD}${CCLD} ${AM_LDFLAGS} -shared ${LDFLAGS} -o $@ $< ${libxtables_LIBS} ${LDLIBS};
|
||||
|
||||
%.oo: ${XA_SRCDIR}/%.c
|
||||
${AM_V_CC}${CC} ${AM_DEPFLAGS} ${AM_CPPFLAGS} ${AM_CFLAGS} -DPIC -fPIC ${CPPFLAGS} ${CFLAGS} -o $@ -c $<;
|
||||
40
Makefile.mans.in
Normal file
40
Makefile.mans.in
Normal file
@@ -0,0 +1,40 @@
|
||||
# -*- Makefile -*-
|
||||
# MANUAL
|
||||
|
||||
srcdir := @srcdir@
|
||||
|
||||
wcman_matches := $(shell find "${srcdir}" -name 'libxt_[a-z]*.man' | sort)
|
||||
wcman_targets := $(shell find "${srcdir}" -name 'libxt_[A-Z]*.man' | sort)
|
||||
wlist_matches := $(patsubst ${srcdir}/libxt_%.man,%,${wcman_matches})
|
||||
wlist_targets := $(patsubst ${srcdir}/libxt_%.man,%,${wcman_targets})
|
||||
|
||||
.PHONY: FORCE
|
||||
|
||||
FORCE:
|
||||
|
||||
.manpages.lst: FORCE
|
||||
@echo "${wlist_targets} ${wlist_matches}" >$@.tmp; \
|
||||
cmp -s $@ $@.tmp || mv $@.tmp $@; \
|
||||
rm -f $@.tmp;
|
||||
|
||||
man_run = \
|
||||
${AM_V_GEN}for ext in $(1); do \
|
||||
name="$${ext%.man}"; \
|
||||
name="$${name\#\#*/libxt_}"; \
|
||||
if [ -f "$$ext" ]; then \
|
||||
echo ".SS $$name"; \
|
||||
cat "$$ext" || exit $$?; \
|
||||
continue; \
|
||||
fi; \
|
||||
done >$@;
|
||||
|
||||
all: xtables-addons.8
|
||||
|
||||
xtables-addons.8: ${srcdir}/xtables-addons.8.in matches.man targets.man
|
||||
${AM_V_GEN}sed -e '/@MATCHES@/ r matches.man' -e '/@TARGET@/ r targets.man' $< >$@;
|
||||
|
||||
matches.man: .manpages.lst ${wcman_matches}
|
||||
$(call man_run,${wlist_matches})
|
||||
|
||||
targets.man: .manpages.lst ${wcman_targets}
|
||||
$(call man_run,${wlist_targets})
|
||||
6
README
6
README
@@ -16,6 +16,12 @@ sanity checks and incorrect endianess handling have been fixed,
|
||||
simplified, and sped up.
|
||||
|
||||
|
||||
Included in this package
|
||||
========================
|
||||
- ipset 6.10-genl
|
||||
- xt_ACCOUNT 1.16, libxt_ACCOUNT 1.3
|
||||
|
||||
|
||||
Inclusion into a kernel tree
|
||||
============================
|
||||
|
||||
|
||||
146
configure.ac
146
configure.ac
@@ -1,104 +1,86 @@
|
||||
|
||||
AC_INIT([xtables-addons], [1.15])
|
||||
AC_INIT([xtables-addons], [1.41])
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_PROG_INSTALL
|
||||
AM_INIT_AUTOMAKE([-Wall foreign subdir-objects])
|
||||
AM_INIT_AUTOMAKE([1.10b -Wall foreign subdir-objects])
|
||||
AC_PROG_CC
|
||||
AM_PROG_CC_C_O
|
||||
AC_DISABLE_STATIC
|
||||
AC_PROG_LIBTOOL
|
||||
|
||||
kbuilddir="/lib/modules/$(uname -r)/build";
|
||||
AC_ARG_WITH([kbuild],
|
||||
AS_HELP_STRING([--with-kbuild=PATH],
|
||||
[Path to kernel build directory [[/lib/modules/CURRENT/build]]]),
|
||||
[kbuilddir="$withval"])
|
||||
AC_ARG_WITH([ksource],
|
||||
AS_HELP_STRING([--with-ksource=PATH],
|
||||
[Path to kernel source directory [[/lib/modules/CURRENT/source]]]),
|
||||
[ksourcedir="$withval"])
|
||||
AC_ARG_WITH([xtables],
|
||||
AS_HELP_STRING([--with-xtables=PATH],
|
||||
[Path to the Xtables includes [[none]]]),
|
||||
[xtables_location="$withval"])
|
||||
[Path to kernel build directory [[/lib/modules/CURRENT/build]]])
|
||||
AS_HELP_STRING([--without-kbuild],
|
||||
[Build only userspace tools]),
|
||||
[kbuilddir="$withval"],
|
||||
[kbuilddir="/lib/modules/$(uname -r)/build"])
|
||||
#
|
||||
# check for --without-kbuild
|
||||
#
|
||||
if [[ "$kbuilddir" == no ]]; then
|
||||
kbuilddir="";
|
||||
fi
|
||||
|
||||
AC_CHECK_HEADERS([linux/netfilter/x_tables.h], [],
|
||||
[AC_MSG_ERROR([You need to have linux/netfilter/x_tables.h, see INSTALL file for details])])
|
||||
PKG_CHECK_MODULES([libxtables], [xtables >= 1.4.5])
|
||||
xtlibdir="$(pkg-config --variable=xtlibdir xtables)"
|
||||
PKG_CHECK_MODULES([libmnl], [libmnl >= 1], [:], [:])
|
||||
|
||||
AC_ARG_WITH([xtlibdir],
|
||||
AS_HELP_STRING([--with-xtlibdir=PATH],
|
||||
[Path where to install Xtables extensions [[LIBEXECDIR/xtables]]]),
|
||||
[xtlibdir="$withval"],
|
||||
[xtlibdir='${libexecdir}/xtables'])
|
||||
[Path where to install Xtables extensions [[autodetect]]]]),
|
||||
[xtlibdir="$withval"])
|
||||
AC_MSG_CHECKING([Xtables module directory])
|
||||
AC_MSG_RESULT([$xtlibdir])
|
||||
|
||||
#
|
||||
# --with-xtables= overrides a possibly installed pkgconfig file.
|
||||
#
|
||||
if [[ -n "$xtables_location" ]]; then
|
||||
AC_MSG_CHECKING([xtables.h presence])
|
||||
if [[ -f "$xtables_location/xtables.h" ]]; then
|
||||
AC_MSG_RESULT([$xtables_location/xtables.h])
|
||||
xtables_CFLAGS="-I $xtables_location";
|
||||
elif [[ -f "$xtables_location/include/xtables.h" ]]; then
|
||||
AC_MSG_RESULT([$xtables_location/include/xtables.h])
|
||||
xtables_CFLAGS="-I $xtables_location/include";
|
||||
fi;
|
||||
if [[ -z "$xtables_CFLAGS" ]]; then
|
||||
if [[ -f "$includedir/xtables.h" ]]; then
|
||||
AC_MSG_RESULT([$includedir/xtables.h])
|
||||
regular_CPPFLAGS="-D_LARGEFILE_SOURCE=1 -D_LARGE_FILES -D_FILE_OFFSET_BITS=64 \
|
||||
-D_REENTRANT -I\${XA_TOPSRCDIR}/include"
|
||||
regular_CFLAGS="-Wall -Waggregate-return -Wmissing-declarations \
|
||||
-Wmissing-prototypes -Wredundant-decls -Wshadow -Wstrict-prototypes \
|
||||
-Winline -pipe";
|
||||
|
||||
if test -n "$kbuilddir"; then
|
||||
AC_MSG_CHECKING([kernel version that we will build against])
|
||||
krel="$(make -sC "$kbuilddir" M=$PWD kernelrelease)";
|
||||
kmajor="${krel%%[[^0-9]]*}";
|
||||
kmajor="$(($kmajor+0))";
|
||||
krel="${krel:${#kmajor}}";
|
||||
krel="${krel#.}";
|
||||
kminor="${krel%%[[^0-9]]*}";
|
||||
kminor="$(($kminor+0))";
|
||||
krel="${krel:${#kminor}}";
|
||||
krel="${krel#.}";
|
||||
kmicro="${krel%%[[^0-9]]*}";
|
||||
kmicro="$(($kmicro+0))";
|
||||
krel="${krel:${#kmicro}}";
|
||||
krel="${krel#.}";
|
||||
kstable="${krel%%[[^0-9]]*}";
|
||||
kstable="$(($kstable+0))";
|
||||
if test -z "$kmajor" -o -z "$kminor" -o -z "$kmicro"; then
|
||||
echo "WARNING: Version detection did not succeed. Continue at own luck.";
|
||||
else
|
||||
echo "$kmajor.$kminor.$kmicro.$kstable in $kbuilddir";
|
||||
if test "$kmajor" -gt 3 -o "$kmajor" -eq 3 -a "$kminor" -gt 2; then
|
||||
echo "WARNING: You are trying a newer kernel. Results may vary. :-)";
|
||||
elif test "$kmajor" -eq 3; then
|
||||
:;
|
||||
elif test "$kmajor" -eq 2 -a "$kminor" -eq 6 -a "$kmicro" -ge 32; then
|
||||
:;
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
echo "WARNING: That kernel version is not officially supported.";
|
||||
fi;
|
||||
fi;
|
||||
else
|
||||
PKG_CHECK_MODULES([libxtables], [xtables >= 1.4.3])
|
||||
fi;
|
||||
|
||||
regular_CFLAGS="-D_LARGEFILE_SOURCE=1 -D_LARGE_FILES -D_FILE_OFFSET_BITS=64 \
|
||||
-D_REENTRANT -Wall -Waggregate-return -Wmissing-declarations \
|
||||
-Wmissing-prototypes -Wredundant-decls -Wshadow -Wstrict-prototypes \
|
||||
-Winline -pipe -DXTABLES_LIBDIR=\\\"\${xtlibdir}\\\"";
|
||||
kinclude_CFLAGS="";
|
||||
if [[ -n "$kbuilddir" ]]; then
|
||||
kinclude_CFLAGS="$kinclude_CFLAGS -I $kbuilddir/include";
|
||||
fi;
|
||||
if [[ -n "$ksourcedir" ]]; then
|
||||
kinclude_CFLAGS="$kinclude_CFLAGS -I $ksourcedir/include";
|
||||
fi;
|
||||
|
||||
#
|
||||
# check kernel version
|
||||
#
|
||||
if grep -q "CentOS release 5\." /etc/redhat-release 2>/dev/null ||
|
||||
grep -q "Red Hat Enterprise Linux Server release 5" /etc/redhat-release 2>/dev/null; then
|
||||
# しまった!
|
||||
# Well, just a warning. Maybe the admin updated the kernel.
|
||||
echo "WARNING: This distribution's shipped kernel is not supported.";
|
||||
fi;
|
||||
krel="$(make -sC ${kbuilddir} kernelrelease)";
|
||||
krel="${krel%%-*}";
|
||||
kmajor="${krel%%.*}";
|
||||
krel="${krel#*.}";
|
||||
kminor="${krel%%.*}";
|
||||
krel="${krel#*.}";
|
||||
kmicro="${krel%%.*}";
|
||||
krel="${krel#*.}";
|
||||
kstable="${krel%%.*}";
|
||||
if test -z "$kstable"; then
|
||||
kstable=0;
|
||||
fi;
|
||||
echo "Found kernel version $kmajor.$kminor.$kmicro.$kstable in $kbuilddir";
|
||||
if test "$kmajor" -gt 2 -o "$kminor" -gt 6 -o "$kmicro" -gt 30; then
|
||||
echo "WARNING: You are trying a newer kernel. Results may vary. :-)";
|
||||
elif test \( "$kmajor" -lt 2 -o "$kminor" -lt 6 -o "$kmicro" -lt 17 \) -o \
|
||||
\( "$kmajor" -eq 2 -a "$kminor" -eq 6 -a "$kmicro" -eq 18 -a \
|
||||
"$kstable" -lt 5 \); then
|
||||
echo "ERROR: That kernel version is not supported. Please see INSTALL for minimum configuration.";
|
||||
exit 1;
|
||||
fi;
|
||||
|
||||
AC_SUBST([regular_CPPFLAGS])
|
||||
AC_SUBST([regular_CFLAGS])
|
||||
AC_SUBST([xtables_CFLAGS])
|
||||
AC_SUBST([kinclude_CFLAGS])
|
||||
AC_SUBST([kbuilddir])
|
||||
AC_SUBST([ksourcedir])
|
||||
AC_SUBST([xtlibdir])
|
||||
AC_CONFIG_FILES([Makefile extensions/GNUmakefile extensions/ipset/GNUmakefile])
|
||||
AC_CONFIG_FILES([Makefile Makefile.iptrules Makefile.mans geoip/Makefile
|
||||
extensions/Makefile extensions/ACCOUNT/Makefile
|
||||
extensions/ipset-6/Makefile
|
||||
extensions/pknock/Makefile])
|
||||
AC_OUTPUT
|
||||
|
||||
4
doc/README.psd
Normal file
4
doc/README.psd
Normal file
@@ -0,0 +1,4 @@
|
||||
PSD (Portscan Detection) External extensions for Xtables-addons
|
||||
|
||||
Example:
|
||||
iptables -A INPUT -m psd --psd-weight-threshold 21 --psd-delay-threshold 300 --psd-lo-ports-weight 1 --psd-hi-ports-weight 10 -j LOG --log-prefix "PSD: "
|
||||
64
doc/api/2.6.17.c
Normal file
64
doc/api/2.6.17.c
Normal file
@@ -0,0 +1,64 @@
|
||||
match:
|
||||
|
||||
/* true/false */
|
||||
int
|
||||
(*match)(
|
||||
const struct sk_buff *skb,
|
||||
const struct net_device *in,
|
||||
const struct net_device *out,
|
||||
const struct xt_match *match,
|
||||
const void *matchinfo,
|
||||
int offset,
|
||||
unsigned int protoff,
|
||||
int *hotdrop,
|
||||
);
|
||||
|
||||
/* error code */
|
||||
int
|
||||
(*checkentry)(
|
||||
const char *tablename,
|
||||
const void *ip,
|
||||
const struct xt_match *match,
|
||||
void *matchinfo,
|
||||
unsigned int matchinfosize,
|
||||
unsigned int hook_mask,
|
||||
);
|
||||
|
||||
void
|
||||
(*destroy)(
|
||||
const struct xt_match *match,
|
||||
void *matchinfo,
|
||||
unsigned int matchinfosize,
|
||||
);
|
||||
|
||||
target:
|
||||
|
||||
/* verdict */
|
||||
unsigned int
|
||||
(*target)(
|
||||
struct sk_buff **pskb,
|
||||
const struct net_device *in,
|
||||
const struct net_device *out,
|
||||
unsigned int hooknum,
|
||||
const struct xt_target *target,
|
||||
const void *targinfo,
|
||||
void *userdata,
|
||||
);
|
||||
|
||||
/* error code */
|
||||
int
|
||||
(*checkentry)(
|
||||
const char *tablename,
|
||||
const void *entry,
|
||||
const struct xt_target *target,
|
||||
void *targinfo,
|
||||
unsigned int targinfosize,
|
||||
unsigned int hook_mask,
|
||||
);
|
||||
|
||||
void
|
||||
(*destroy)(
|
||||
const struct xt_target *target,
|
||||
void *targinfo,
|
||||
unsigned int targinfosize,
|
||||
);
|
||||
59
doc/api/2.6.19.c
Normal file
59
doc/api/2.6.19.c
Normal file
@@ -0,0 +1,59 @@
|
||||
match:
|
||||
|
||||
/* true/false */
|
||||
int
|
||||
(*match)(
|
||||
const struct sk_buff *skb,
|
||||
const struct net_device *in,
|
||||
const struct net_device *out,
|
||||
const struct xt_match *match,
|
||||
const void *matchinfo,
|
||||
int offset,
|
||||
unsigned int protoff,
|
||||
int *hotdrop,
|
||||
);
|
||||
|
||||
/* error code */
|
||||
int
|
||||
(*checkentry)(
|
||||
const char *tablename,
|
||||
const void *ip,
|
||||
const struct xt_match *match,
|
||||
void *matchinfo,
|
||||
unsigned int hook_mask,
|
||||
);
|
||||
|
||||
void
|
||||
(*destroy)(
|
||||
const struct xt_match *match,
|
||||
void *matchinfo,
|
||||
);
|
||||
|
||||
target:
|
||||
|
||||
/* verdict */
|
||||
unsigned int
|
||||
(*target)(
|
||||
struct sk_buff **pskb,
|
||||
const struct net_device *in,
|
||||
const struct net_device *out,
|
||||
unsigned int hooknum,
|
||||
const struct xt_target *target,
|
||||
const void *targinfo,
|
||||
);
|
||||
|
||||
/* error code */
|
||||
int
|
||||
(*checkentry)(
|
||||
const char *tablename,
|
||||
const void *entry,
|
||||
const struct xt_target *target,
|
||||
void *targinfo,
|
||||
unsigned int hook_mask,
|
||||
);
|
||||
|
||||
void
|
||||
(*destroy)(
|
||||
const struct xt_target *target,
|
||||
void *targinfo,
|
||||
);
|
||||
59
doc/api/2.6.23.c
Normal file
59
doc/api/2.6.23.c
Normal file
@@ -0,0 +1,59 @@
|
||||
match:
|
||||
|
||||
/* true/false */
|
||||
bool
|
||||
(*match)(
|
||||
const struct sk_buff *skb,
|
||||
const struct net_device *in,
|
||||
const struct net_device *out,
|
||||
const struct xt_match *match,
|
||||
const void *matchinfo,
|
||||
int offset,
|
||||
unsigned int protoff,
|
||||
bool *hotdrop,
|
||||
);
|
||||
|
||||
/* true/false */
|
||||
bool
|
||||
(*checkentry)(
|
||||
const char *tablename,
|
||||
const void *ip,
|
||||
const struct xt_match *match,
|
||||
void *matchinfo,
|
||||
unsigned int hook_mask,
|
||||
);
|
||||
|
||||
void
|
||||
(*destroy)(
|
||||
const struct xt_match *match,
|
||||
void *matchinfo,
|
||||
);
|
||||
|
||||
target:
|
||||
|
||||
/* verdict */
|
||||
unsigned int
|
||||
(*target)(
|
||||
struct sk_buff **pskb,
|
||||
const struct net_device *in,
|
||||
const struct net_device *out,
|
||||
unsigned int hooknum,
|
||||
const struct xt_target *target,
|
||||
const void *targinfo,
|
||||
);
|
||||
|
||||
/* true/false */
|
||||
bool
|
||||
(*checkentry)(
|
||||
const char *tablename,
|
||||
const void *entry,
|
||||
const struct xt_target *target,
|
||||
void *targinfo,
|
||||
unsigned int hook_mask,
|
||||
);
|
||||
|
||||
void
|
||||
(*destroy)(
|
||||
const struct xt_target *target,
|
||||
void *targinfo,
|
||||
);
|
||||
59
doc/api/2.6.24.c
Normal file
59
doc/api/2.6.24.c
Normal file
@@ -0,0 +1,59 @@
|
||||
match:
|
||||
|
||||
/* true/false */
|
||||
bool
|
||||
(*match)(
|
||||
const struct sk_buff *skb,
|
||||
const struct net_device *in,
|
||||
const struct net_device *out,
|
||||
const struct xt_match *match,
|
||||
const void *matchinfo,
|
||||
int offset,
|
||||
unsigned int protoff,
|
||||
bool *hotdrop,
|
||||
);
|
||||
|
||||
/* true/false */
|
||||
bool
|
||||
(*checkentry)(
|
||||
const char *tablename,
|
||||
const void *ip,
|
||||
const struct xt_match *match,
|
||||
void *matchinfo,
|
||||
unsigned int hook_mask,
|
||||
);
|
||||
|
||||
void
|
||||
(*destroy)(
|
||||
const struct xt_match *match,
|
||||
void *matchinfo,
|
||||
);
|
||||
|
||||
target:
|
||||
|
||||
/* verdict */
|
||||
unsigned int
|
||||
(*target)(
|
||||
struct sk_buff *skb,
|
||||
const struct net_device *in,
|
||||
const struct net_device *out,
|
||||
unsigned int hooknum,
|
||||
const struct xt_target *target,
|
||||
const void *targinfo,
|
||||
);
|
||||
|
||||
/* true/false */
|
||||
bool
|
||||
(*checkentry)(
|
||||
const char *tablename,
|
||||
const void *entry,
|
||||
const struct xt_target *target,
|
||||
void *targinfo,
|
||||
unsigned int hook_mask,
|
||||
);
|
||||
|
||||
void
|
||||
(*destroy)(
|
||||
const struct xt_target *target,
|
||||
void *targinfo,
|
||||
);
|
||||
39
doc/api/2.6.28.c
Normal file
39
doc/api/2.6.28.c
Normal file
@@ -0,0 +1,39 @@
|
||||
match:
|
||||
|
||||
/* true/false */
|
||||
bool
|
||||
(*match)(
|
||||
const struct sk_buff *skb,
|
||||
const struct xt_match_param *,
|
||||
);
|
||||
|
||||
/* true/false */
|
||||
bool
|
||||
(*checkentry)(
|
||||
const struct xt_mtchk_param *,
|
||||
);
|
||||
|
||||
void
|
||||
(*destroy)(
|
||||
const struct xt_mtdtor_param *,
|
||||
);
|
||||
|
||||
target:
|
||||
|
||||
/* verdict */
|
||||
unsigned int
|
||||
(*target)(
|
||||
struct sk_buff *skb,
|
||||
const struct xt_target_param *,
|
||||
);
|
||||
|
||||
/* true/false */
|
||||
bool
|
||||
(*checkentry)(
|
||||
const struct xt_tgchk_param *,
|
||||
);
|
||||
|
||||
void
|
||||
(*destroy)(
|
||||
const struct xt_tgdtor_param *,
|
||||
);
|
||||
38
doc/api/2.6.31.c
Normal file
38
doc/api/2.6.31.c
Normal file
@@ -0,0 +1,38 @@
|
||||
match:
|
||||
|
||||
/* true/false */
|
||||
bool
|
||||
(*match)(
|
||||
const struct sk_buff *skb,
|
||||
const struct xt_match_param *,
|
||||
);
|
||||
|
||||
/* true/false */
|
||||
bool
|
||||
(*checkentry)(
|
||||
const struct xt_mtchk_param *,
|
||||
);
|
||||
|
||||
void
|
||||
(*destroy)(
|
||||
const struct xt_mtdtor_param *,
|
||||
);
|
||||
|
||||
target:
|
||||
|
||||
unsigned int
|
||||
(*target)(
|
||||
struct sk_buff *skb,
|
||||
const struct xt_target_param *,
|
||||
);
|
||||
|
||||
/* true/false */
|
||||
bool
|
||||
(*checkentry)(
|
||||
const struct xt_tgchk_param *,
|
||||
);
|
||||
|
||||
void
|
||||
(*destroy)(
|
||||
const struct xt_tgdtor_param *,
|
||||
);
|
||||
39
doc/api/2.6.32.c
Normal file
39
doc/api/2.6.32.c
Normal file
@@ -0,0 +1,39 @@
|
||||
match:
|
||||
|
||||
/* true/false */
|
||||
bool
|
||||
(*match)(
|
||||
const struct sk_buff *skb,
|
||||
const struct xt_match_param *,
|
||||
);
|
||||
|
||||
/* true/false */
|
||||
bool
|
||||
(*checkentry)(
|
||||
const struct xt_mtchk_param *,
|
||||
);
|
||||
|
||||
void
|
||||
(*destroy)(
|
||||
const struct xt_mtdtor_param *,
|
||||
);
|
||||
|
||||
target:
|
||||
|
||||
/* verdict */
|
||||
unsigned int
|
||||
(*target)(
|
||||
struct sk_buff *skb,
|
||||
const struct xt_target_param *,
|
||||
);
|
||||
|
||||
/* true/false */
|
||||
bool
|
||||
(*checkentry)(
|
||||
const struct xt_tgchk_param *,
|
||||
);
|
||||
|
||||
void
|
||||
(*destroy)(
|
||||
const struct xt_tgdtor_param *,
|
||||
);
|
||||
39
doc/api/2.6.35.c
Normal file
39
doc/api/2.6.35.c
Normal file
@@ -0,0 +1,39 @@
|
||||
match:
|
||||
|
||||
/* true/false */
|
||||
bool
|
||||
(*match)(
|
||||
const struct sk_buff *skb,
|
||||
struct xt_action_param *,
|
||||
);
|
||||
|
||||
/* error code */
|
||||
int
|
||||
(*checkentry)(
|
||||
const struct xt_mtchk_param *,
|
||||
);
|
||||
|
||||
void
|
||||
(*destroy)(
|
||||
const struct xt_mtdtor_param *,
|
||||
);
|
||||
|
||||
target:
|
||||
|
||||
/* verdict */
|
||||
unsigned int
|
||||
(*target)(
|
||||
struct sk_buff *skb,
|
||||
const struct xt_action_param *,
|
||||
);
|
||||
|
||||
/* error code */
|
||||
int
|
||||
(*checkentry)(
|
||||
const struct xt_tgchk_param *,
|
||||
);
|
||||
|
||||
void
|
||||
(*destroy)(
|
||||
const struct xt_tgdtor_param *,
|
||||
);
|
||||
39
doc/api/xt-a.c
Normal file
39
doc/api/xt-a.c
Normal file
@@ -0,0 +1,39 @@
|
||||
match:
|
||||
|
||||
/* true/false */
|
||||
bool
|
||||
(*match)(
|
||||
const struct sk_buff *skb,
|
||||
struct xt_action_param *,
|
||||
);
|
||||
|
||||
/* error code */
|
||||
int
|
||||
(*checkentry)(
|
||||
const struct xt_mtchk_param *,
|
||||
);
|
||||
|
||||
void
|
||||
(*destroy)(
|
||||
const struct xt_mtdtor_param *,
|
||||
);
|
||||
|
||||
target:
|
||||
|
||||
/* verdict */
|
||||
unsigned int
|
||||
(*target)(
|
||||
struct sk_buff **pskb,
|
||||
const struct xt_action_param *,
|
||||
);
|
||||
|
||||
/* error code */
|
||||
int
|
||||
(*checkentry)(
|
||||
const struct xt_tgchk_param *,
|
||||
);
|
||||
|
||||
void
|
||||
(*destroy)(
|
||||
const struct xt_tgdtor_param *,
|
||||
);
|
||||
@@ -1,7 +1,299 @@
|
||||
|
||||
HEAD
|
||||
====
|
||||
|
||||
|
||||
Xtables-addons 1.15 (April 30 2009)
|
||||
===================================
|
||||
v1.41 (2012-01-04)
|
||||
==================
|
||||
Changes:
|
||||
- Deactivate build of ipset-genl by default.
|
||||
I think the original ipset package can now take over, given there are
|
||||
a handful of kernels (2.6.39 onwards) that do not need patching.
|
||||
Enhancements:
|
||||
- Support for Linux 3.2
|
||||
|
||||
|
||||
v1.40 (2011-11-30)
|
||||
==================
|
||||
Fixes:
|
||||
- build: the code actually requires at least iptables 1.4.5 (would yield a
|
||||
compile error otherwise), make sure configure checks for it; update INSTALL
|
||||
- xt_ECHO: fix kernel warning about RTAX_HOPLIMIT being used
|
||||
- xt_ipv4options: fix an infinite loop
|
||||
Changes:
|
||||
- xt_ECHO: now calculates UDP checksum
|
||||
- Linux kernel versions below 2.6.32 are no longer officially
|
||||
supported, and will not be part of compilation testing.
|
||||
- update to ipset 6.10
|
||||
Enhancements:
|
||||
- xt_ECHO: IPv6 support
|
||||
|
||||
|
||||
v1.39 (2011-09-21)
|
||||
==================
|
||||
Fixes:
|
||||
- libxt_ACCOUNT: fix compilation after missing libxtables_CFLAGS
|
||||
- build: fix compilation after missing libxtables_CFLAGS in submodules
|
||||
- build: add missing linux/version.h includes where needed
|
||||
Changes:
|
||||
- Remove unsupported ipset 4.x from the Xtables-addons distribution
|
||||
- ipset: move ipset_errcode from src to library to avoid undefined reference
|
||||
- update to ipset 6.9.1
|
||||
|
||||
|
||||
v1.38 (2011-08-20)
|
||||
==================
|
||||
- xt_CHECKSUM: abort build when the feature is already provided by mainline
|
||||
- xt_SYSRQ: fix UDPLITE header lookup in IPv6
|
||||
- xt_TARPIT: fix kernel warning about RTAX_HOPLIMIT being used
|
||||
- xt_TEE: abort build when the feature is already provided by mainline
|
||||
- xt_ipp2p: support UDPLITE
|
||||
- xt_pknock: support UDPLITE
|
||||
- xt_psd: restore functionality with UDP
|
||||
- xt_psd: support UDPLITE
|
||||
- update to ipset 6.8
|
||||
- support for Linux 3.1
|
||||
|
||||
|
||||
v1.37 (2011-06-25)
|
||||
==================
|
||||
Fixes:
|
||||
- xt_SYSRQ: make IPv6 trigger work again
|
||||
- xt_SYSRQ: improve security: include host address in digest
|
||||
- xt_TARPIT: fix a kernel oops in --reset mode
|
||||
|
||||
|
||||
v1.36 (2011-06-03)
|
||||
==================
|
||||
Changes:
|
||||
- xt_geoip: avoid recursive function calls
|
||||
- xt_TARPIT: unlock for use in all tables
|
||||
- xt_TARPIT: honeypot and reset modes
|
||||
- update to ipset 6.7
|
||||
- support for Linux 3.0
|
||||
|
||||
|
||||
v1.35 (2011-04-11)
|
||||
==================
|
||||
Enhancements:
|
||||
- update to ipset 6.3
|
||||
* allow "new" as a commad alias to "create"
|
||||
* resolving IP addresses did not work at listing/saving sets, fixed
|
||||
* check ICMP and ICMPv6 with the set match and target in the testsuite
|
||||
* avoid possible syntax clashing at saving hostnames
|
||||
* fix linking with CONFIG_IPV6=n
|
||||
* sctp, udplite support for the hash:*port* types
|
||||
- ipset-genl: handle EAGAIN return value emitted from autoloader
|
||||
- ipset-genl: resolve nfgenmsg remains and fix spurious protocol abort
|
||||
|
||||
|
||||
v1.34 (2011-04-07)
|
||||
==================
|
||||
Fixes:
|
||||
- xt_pknock: avoid crash when hash TFM could not be allocated
|
||||
- xt_pknock: avoid inversion of rule lookup that led to warnings
|
||||
- xt_DNETMAP: add missing module alias
|
||||
- xt_DNETMAP: support for kernels below 2.6.34
|
||||
Changes:
|
||||
- Linux kernel versions below 2.6.29 are no longer officially
|
||||
supported, and will not be part of compilation testing.
|
||||
|
||||
|
||||
v1.33 (2011-02-02)
|
||||
==================
|
||||
Fixes:
|
||||
- build: restore functionality of `configure --without-kbuild`
|
||||
- build: fix objdir builds for ipset-5 (xt-a specific)
|
||||
- build: fix missing inclusion of dependency rules
|
||||
- xt_LOGMARK: fix detection of untracked connection for Linux >= 2.6.36
|
||||
Enhancements:
|
||||
- IPv6 support for xt_geoip
|
||||
- Update to ipset 5.3
|
||||
* make IPv4 and IPv6 address handling similar
|
||||
* show correct line numbers in restore output for parser errors
|
||||
- Update to ipset 5.4
|
||||
* fixed ICMP and ICMPv6 handling
|
||||
* fixed trailing whitespaces and pr_* messages
|
||||
* fixed module loading at create/header commands
|
||||
- build: support for Linux up to 2.6.38
|
||||
- build: preliminary support for iptables 1.4.11
|
||||
|
||||
|
||||
v1.32 (2011-01-04)
|
||||
==================
|
||||
Fixes:
|
||||
- Update to ipset 4.5
|
||||
* the iptreemap type used wrong gfp flags when deleting entries
|
||||
- Include ipset 5.2 with genetlink patch (beta)
|
||||
* no kernel patch needed, but requires Linux >= 2.6.35
|
||||
and thus needs to be manually enabled in mconfig
|
||||
|
||||
|
||||
v1.31 (2010-11-05)
|
||||
==================
|
||||
Fixes:
|
||||
- build: improve detection of kernel version and error handling
|
||||
Changes:
|
||||
- build: automatically derive Xtables module directory, thus
|
||||
--with-xtlibdir is no longer needed for ./configure in most cases
|
||||
(If I still see a distro using it, I will scold you for not
|
||||
reading this changelog.)
|
||||
Enhancements:
|
||||
- LOGMARK: print remaining lifetime of cts
|
||||
- xt_iface: allow matching against incoming/outgoing interface
|
||||
- libxt_gradm: match packets based on status of grsecurity RBAC
|
||||
(userspace part only - xt_gradm is in the grsec patch)
|
||||
|
||||
|
||||
v1.30 (2010-010-02)
|
||||
===================
|
||||
Fixes:
|
||||
- update to ipset 4.4
|
||||
* ipport{,ip,net}hash did not work with mixed "src" and "dst"
|
||||
destination parameters
|
||||
Changes:
|
||||
- deactivate building xt_TEE and xt_CHECKSUM by default, as these have been
|
||||
merged upstream in Linux 2.6.35 and 2.6.36, respectively.
|
||||
Distros still wishing to build this need to enable it in their build
|
||||
script, e.g. perl -i -pe 's{^build_TEE=.*}{build_TEE=m}' mconfig;
|
||||
|
||||
|
||||
v1.29 (2010-09-29)
|
||||
==================
|
||||
- compat_xtables: return bool for match_check and target_check in 2.6.23..34
|
||||
- ipset: enable building of ip_set_ipport{ip,net}hash.ko
|
||||
- support for Linux 2.6.36
|
||||
- SYSRQ: resolve compile error with Linux 2.6.36
|
||||
- TEE: resolve compile error with Linux 2.6.36
|
||||
- add workaround for broken linux-glibc-devel 2.6.34 userspace headers
|
||||
("implicit declaration of function 'ALIGN'")
|
||||
|
||||
|
||||
v1.28 (2010-07-24)
|
||||
==================
|
||||
- RAWNAT: IPv6 variants erroneously rejected masks /33-/128
|
||||
- new target xt_CHECKSUM
|
||||
- xt_length2: add support for IPv6 jumbograms
|
||||
- xt_geoip: fix possible out-of-bounds access
|
||||
- import xt_geoip database scripts
|
||||
|
||||
|
||||
v1.27 (2010-05-16)
|
||||
==================
|
||||
- further updates for the upcoming 2.6.35 changes
|
||||
|
||||
|
||||
v1.26 (2010-04-30)
|
||||
==================
|
||||
- compat_xtables: fix 2.6.34 compile error due to a typo
|
||||
|
||||
|
||||
v1.25 (2010-04-26)
|
||||
==================
|
||||
- TEE: do rechecksumming in PREROUTING too
|
||||
- TEE: decrease TTL on cloned packet
|
||||
- TEE: set dont-fragment on cloned packets
|
||||
- TEE: free skb when route lookup failed
|
||||
- TEE: do not limit use to mangle table
|
||||
- TEE: do not retain iif and mark on cloned packet
|
||||
- TEE: new loop detection logic
|
||||
- TEE: use less expensive pskb_copy
|
||||
- condition: remove unnecessary RCU protection
|
||||
|
||||
|
||||
v1.24 (2010-03-17)
|
||||
==================
|
||||
- build: fix build of userspace modules against old (pre-2.6.25)
|
||||
headers from linux-glibc-devel (/usr/include/linux)
|
||||
- ipp2p: updated bittorent command recognition
|
||||
- SYSRQ: let module load when crypto is unavailable
|
||||
- SYSRQ: allow processing of UDP-Lite
|
||||
|
||||
|
||||
v1.23 (2010-02-24)
|
||||
==================
|
||||
- build: support for Linux 2.6.34
|
||||
- build: remove unused --with-ksource option
|
||||
- build: remove unneeded --with-xtables option
|
||||
- build: fix compilations in RAWNAT, SYSRQ and length2 when CONFIG_IPV6=n
|
||||
- ipset: update to 4.2
|
||||
- ECHO: fix compilation w.r.t. skb_dst
|
||||
|
||||
|
||||
v1.22 (2010-01-22)
|
||||
==================
|
||||
- compat_xtables: support for 2.6.33 skb_iif changes
|
||||
- geoip: for FHS compliance use /usr/share/xt_geoip instead of /var/geoip
|
||||
- ipset: enable build of ip_set_setlist.ko
|
||||
- quota2: add the --no-change mode
|
||||
|
||||
|
||||
v1.21 (2009-12-09)
|
||||
==================
|
||||
- ACCOUNT: avoid collision with arp_tables setsockopt numbers
|
||||
- doc: fix option mismatch --gw/--gateway in libxt_TEE.man
|
||||
|
||||
|
||||
v1.20 (2009-11-19)
|
||||
==================
|
||||
- ipp2p: add more boundary checks
|
||||
- ipp2p: fix Gnutelle line ending detection
|
||||
- LOGMARK: remove unknown options from manpage
|
||||
- ACCOUNT: endianess-correctness
|
||||
- ipset: install manpage
|
||||
- ipset: fast forward to v4.1
|
||||
|
||||
|
||||
v1.19 (2009-10-12)
|
||||
==================
|
||||
- build: compile fixes for 2.6.31-rt
|
||||
- build: support for Linux 2.6.32
|
||||
- ipp2p: try to address underflows
|
||||
- psd: avoid potential crash when dealing with non-linear skbs
|
||||
- merge xt_ACCOUNT userspace utilities
|
||||
- added reworked xt_pknock module
|
||||
Changes from pknock v0.5:
|
||||
- pknock: "strict" and "checkip" flags were not displayed in `iptables -L`
|
||||
- pknock: the GC expire time's lower bound is now the default gc time
|
||||
(65000 msec) to avoid rendering anti-spoof protection in SPA mode useless
|
||||
- pknock: avoid crash on memory allocation failure and fix memleak
|
||||
- pknock: avoid fillup of peer table during DDoS
|
||||
- pknock: automatic closing of ports
|
||||
- pknock: make non-zero time mandatory for TCP mode
|
||||
- pknock: display only pknock mode and state relevant information in procfs
|
||||
- pknock: check interknock time only for !ST_ALLOWED peers
|
||||
- pknock: preserve time/autoclose values for rules added in
|
||||
reverse/arbitrary order
|
||||
- pknock: add a manpage
|
||||
|
||||
|
||||
v1.18 (2009-09-09)
|
||||
==================
|
||||
- build: support for Linux 2.6.31
|
||||
- ipset: fast forward to v3.2
|
||||
- quota2: support anonymous counters
|
||||
- quota2: reduce memory footprint for anonymous counters
|
||||
- quota2: extend locked period during cleanup (locking bugfix)
|
||||
- quota2: use strtoull instead of strtoul
|
||||
- merged xt_ACCOUNT module
|
||||
- merged xt_psd module
|
||||
|
||||
|
||||
v1.17 (2009-06-16)
|
||||
==================
|
||||
- IPMARK: print missing --shift parameter
|
||||
- build: use readlink -f in extensions/ipset/
|
||||
- build: support for Linux 2.6.30
|
||||
|
||||
|
||||
v1.16 (2009-05-27)
|
||||
==================
|
||||
- RAWNAT: make iptable_rawpost compile with 2.6.30-rc5
|
||||
- ipset: fast forward to 3.0
|
||||
|
||||
|
||||
v1.15 (2009-04-30)
|
||||
==================
|
||||
- build: add kernel version check to configure
|
||||
- condition: compile fix for 2.6.30-rc
|
||||
- condition: fix intrapositional negation sign
|
||||
@@ -13,8 +305,8 @@ Xtables-addons 1.15 (April 30 2009)
|
||||
- added RAWSNAT/RAWDNAT targets
|
||||
|
||||
|
||||
Xtables-addons 1.14 (March 31 2009)
|
||||
===================================
|
||||
v1.14 (2009-03-31)
|
||||
==================
|
||||
- fuzzy: need to account for kernel-level modified variables in .userspacesize
|
||||
- geoip: remove XT_ALIGN from .userspacesize when used with offsetof
|
||||
- SYSRQ: ignore non-UDP packets
|
||||
@@ -24,14 +316,14 @@ Xtables-addons 1.14 (March 31 2009)
|
||||
- dhcpmac: rename from dhcpaddr
|
||||
|
||||
|
||||
Xtables-addons 1.13 (March 23 2009)
|
||||
===================================
|
||||
v1.13 (2009-03-23)
|
||||
==================
|
||||
- added a reworked ipv4options match
|
||||
- upgrade to iptables 1.4.3 API
|
||||
|
||||
|
||||
Xtables-addons 1.12 (March 07 2009)
|
||||
===================================
|
||||
v1.12 (2009-03-07)
|
||||
==================
|
||||
- ipset: fix for compilation with 2.6.29-rt
|
||||
- ipset: fast forward to 2.5.0
|
||||
- rename xt_portscan to xt_lscan ("low-level scan") because
|
||||
@@ -42,21 +334,21 @@ Xtables-addons 1.12 (March 07 2009)
|
||||
- xt_TEE: enable routing by iif, nfmark and flowlabel
|
||||
|
||||
|
||||
Xtables-addons 1.10 (February 18 2009)
|
||||
======================================
|
||||
v1.10 (2009-02-18)
|
||||
==================
|
||||
- compat: compile fixes for 2.6.29
|
||||
- ipset: upgrade to ipset 2.4.9
|
||||
|
||||
|
||||
Xtables-addons 1.9 (January 30 2009)
|
||||
====================================
|
||||
v1.9 (2009-01-30)
|
||||
=================
|
||||
- add the xt_length2 extension
|
||||
- xt_TEE: remove intrapositional '!' support
|
||||
- ipset: upgrade to ipset 2.4.7
|
||||
|
||||
|
||||
Xtables-addons 1.8 (January 10 2009)
|
||||
====================================
|
||||
v1.8 (2009-01-10)
|
||||
=================
|
||||
- xt_TEE: IPv6 support
|
||||
- xt_TEE: do not include TOS value in routing decision
|
||||
- xt_TEE: fix switch-case inversion for name/IP display
|
||||
@@ -65,8 +357,8 @@ Xtables-addons 1.8 (January 10 2009)
|
||||
- xt_portscan: update manpage about --grscan option caveats
|
||||
|
||||
|
||||
Xtables-addons 1.7 (December 25 2008)
|
||||
=====================================
|
||||
v1.7 (2008-12-25)
|
||||
=================
|
||||
- xt_ECHO: compile fix
|
||||
- avoid the use of "_init" which led to compile errors on some installations
|
||||
- build: do not unconditionally install ipset
|
||||
@@ -77,16 +369,16 @@ Xtables-addons 1.7 (December 25 2008)
|
||||
- xt_SYSRQ: improve security by hashing password
|
||||
|
||||
|
||||
Xtables-addons 1.6 (November 18 2008)
|
||||
=====================================
|
||||
v1.6 (2008-11-18)
|
||||
=================
|
||||
- build: support for Linux 2.6.17
|
||||
- build: compile fixes for 2.6.18 and 2.6.19
|
||||
- xt_ECHO: resolve compile errors in xt_ECHO
|
||||
- xt_ipp2p: parenthesize unaligned-access macros
|
||||
|
||||
|
||||
Xtables-addons 1.5.7 (September 01 2008)
|
||||
========================================
|
||||
v1.5.7 (2008-09-01)
|
||||
===================
|
||||
- API layer: fix use of uninitialized 'hotdrop' variable
|
||||
- API layer: move to pskb-based signatures
|
||||
- xt_SYSRQ: compile fixes for Linux <= 2.6.19
|
||||
@@ -98,8 +390,8 @@ Xtables-addons 1.5.7 (September 01 2008)
|
||||
- xt_SYSRQ: add missing module aliases
|
||||
|
||||
|
||||
Xtables-addons 1.5.5 (August 03 2008)
|
||||
=====================================
|
||||
v1.5.5 (2008-08-03)
|
||||
===================
|
||||
- manpage updates for xt_CHAOS, xt_IPMARK; README updates
|
||||
- build: properly recognize external Kbuild/Mbuild files
|
||||
- build: remove dependency on CONFIG_NETWORK_SECMARK
|
||||
@@ -108,13 +400,13 @@ Xtables-addons 1.5.5 (August 03 2008)
|
||||
- import ipset extension group
|
||||
|
||||
|
||||
Xtables-addons 1.5.4.1 (April 26 2008)
|
||||
======================================
|
||||
v1.5.4.1 (2008-04-26)
|
||||
=====================
|
||||
- build: fix compile error for 2.6.18-stable
|
||||
|
||||
|
||||
Xtables-addons 1.5.4 (April 09 2008)
|
||||
====================================
|
||||
v1.5.4 (2008-04-09)
|
||||
===================
|
||||
- build: support building multiple files with one config option
|
||||
- API layer: add check for pskb relocation
|
||||
- doc: generate manpages
|
||||
@@ -128,28 +420,28 @@ Xtables-addons 1.5.4 (April 09 2008)
|
||||
- add reworked xt_IPMARK target
|
||||
|
||||
|
||||
Xtables-addons 1.5.3 (March 22 2008)
|
||||
====================================
|
||||
v1.5.3 (2008-03-22)
|
||||
===================
|
||||
- support for Linux 2.6.18
|
||||
- add xt_ECHO sample target
|
||||
- add reworked xt_geoip match
|
||||
|
||||
|
||||
Xtables-addons 1.5.2 (March 04 2008)
|
||||
====================================
|
||||
v1.5.2 (2008-03-04)
|
||||
===================
|
||||
- build: support for GNU make < 3.81 which does not have $(realpath)
|
||||
|
||||
|
||||
Xtables-addons 1.5.1 (February 21 2008)
|
||||
=======================================
|
||||
v1.5.1 (2008-02-21)
|
||||
===================
|
||||
- build: allow user to select what extensions to compile and install
|
||||
- build: allow external proejcts to be downloaded into the tree
|
||||
- xt_LOGMARK: dump classify mark, ctstate and ctstatus
|
||||
- add xt_CHAOS, xt_DELUDE and xt_portscan from Chaostables
|
||||
|
||||
|
||||
Xtables-addons 1.5.0 (February 11 2008)
|
||||
=======================================
|
||||
v1.5.0 (2008-02-11)
|
||||
===================
|
||||
Initial release with:
|
||||
- extensions: xt_LOGMARK, xt_TARPIT, xt_TEE
|
||||
- support for Linux >= 2.6.19
|
||||
|
||||
9
extensions/.gitignore
vendored
9
extensions/.gitignore
vendored
@@ -1,6 +1,6 @@
|
||||
.*.cmd
|
||||
.*.d
|
||||
.tmp_versions
|
||||
.tmp_versions/
|
||||
*.ko
|
||||
*.mod.c
|
||||
Module.markers
|
||||
@@ -8,8 +8,5 @@ Module.symvers
|
||||
Modules.symvers
|
||||
modules.order
|
||||
|
||||
/*.so
|
||||
/*.oo
|
||||
/matches.man
|
||||
/targets.man
|
||||
/.manpages.lst
|
||||
*.so
|
||||
*.oo
|
||||
|
||||
1
extensions/ACCOUNT/.gitignore
vendored
Normal file
1
extensions/ACCOUNT/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/iptaccount
|
||||
5
extensions/ACCOUNT/Kbuild
Normal file
5
extensions/ACCOUNT/Kbuild
Normal file
@@ -0,0 +1,5 @@
|
||||
# -*- Makefile -*-
|
||||
|
||||
EXTRA_CFLAGS = -I${src}/..
|
||||
|
||||
obj-m += xt_ACCOUNT.o
|
||||
13
extensions/ACCOUNT/Makefile.am
Normal file
13
extensions/ACCOUNT/Makefile.am
Normal file
@@ -0,0 +1,13 @@
|
||||
# -*- Makefile -*-
|
||||
|
||||
AM_CPPFLAGS = ${regular_CPPFLAGS} -I${abs_top_srcdir}/extensions
|
||||
AM_CFLAGS = ${regular_CFLAGS} ${libxtables_CFLAGS}
|
||||
|
||||
include ../../Makefile.extra
|
||||
|
||||
sbin_PROGRAMS = iptaccount
|
||||
iptaccount_LDADD = libxt_ACCOUNT_cl.la
|
||||
|
||||
lib_LTLIBRARIES = libxt_ACCOUNT_cl.la
|
||||
|
||||
man_MANS = iptaccount.8
|
||||
3
extensions/ACCOUNT/Mbuild
Normal file
3
extensions/ACCOUNT/Mbuild
Normal file
@@ -0,0 +1,3 @@
|
||||
# -*- Makefile -*-
|
||||
|
||||
obj-${build_ACCOUNT} += libxt_ACCOUNT.so
|
||||
1
extensions/ACCOUNT/VERSION.txt
Normal file
1
extensions/ACCOUNT/VERSION.txt
Normal file
@@ -0,0 +1 @@
|
||||
1.16
|
||||
26
extensions/ACCOUNT/iptaccount.8
Normal file
26
extensions/ACCOUNT/iptaccount.8
Normal file
@@ -0,0 +1,26 @@
|
||||
.TH iptaccount 8 "v1.16" "" "v1.16"
|
||||
.SH Name
|
||||
iptaccount \(em administrative utility to access xt_ACCOUNT statistics
|
||||
.SH Syntax
|
||||
\fBiptaccount\fP [\fB\-acfhu\fP] [\fB\-l\fP \fIname\fP]
|
||||
.SH Options
|
||||
.PP
|
||||
\fB\-a\fP
|
||||
List all (accounting) table names.
|
||||
.PP
|
||||
\fB\-c\fP
|
||||
Loop every second (abort with CTRL+C).
|
||||
.PP
|
||||
\fB\-f\fP
|
||||
Flush data after display.
|
||||
.PP
|
||||
\fB\-h\fP
|
||||
Free all kernel handles. (Experts only!)
|
||||
.PP
|
||||
\fB\-l\fP \fIname\fP
|
||||
Show data in accounting table called by \fIname\fP.
|
||||
.TP
|
||||
\fB\-u\fP
|
||||
Show kernel handle usage.
|
||||
.SH "See also"
|
||||
\fBxtables-addons\fP(8)
|
||||
224
extensions/ACCOUNT/iptaccount.c
Normal file
224
extensions/ACCOUNT/iptaccount.c
Normal file
@@ -0,0 +1,224 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2004-2006 by Intra2net AG *
|
||||
* opensource@intra2net.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License *
|
||||
* version 2.1 as published by the Free Software Foundation; *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <linux/types.h>
|
||||
#include <libxt_ACCOUNT_cl.h>
|
||||
|
||||
bool exit_now;
|
||||
static void sig_term(int signr)
|
||||
{
|
||||
signal(SIGINT, SIG_IGN);
|
||||
signal(SIGQUIT, SIG_IGN);
|
||||
signal(SIGTERM, SIG_IGN);
|
||||
|
||||
exit_now = true;
|
||||
}
|
||||
|
||||
static char *addr_to_dotted(unsigned int addr)
|
||||
{
|
||||
static char buf[16];
|
||||
const unsigned char *bytep;
|
||||
|
||||
addr = htonl(addr);
|
||||
bytep = (const unsigned char *)&addr;
|
||||
snprintf(buf, sizeof(buf), "%u.%u.%u.%u", bytep[0], bytep[1], bytep[2], bytep[3]);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void show_usage(void)
|
||||
{
|
||||
printf("Unknown command line option. Try: [-u] [-h] [-a] [-f] [-c] [-s] [-l name]\n");
|
||||
printf("[-u] show kernel handle usage\n");
|
||||
printf("[-h] free all kernel handles (experts only!)\n\n");
|
||||
printf("[-a] list all table names\n");
|
||||
printf("[-l name] show data in table <name>\n");
|
||||
printf("[-f] flush data after showing\n");
|
||||
printf("[-c] loop every second (abort with CTRL+C)\n");
|
||||
printf("[-s] CSV output (for spreadsheet import)\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct ipt_ACCOUNT_context ctx;
|
||||
struct ipt_acc_handle_ip *entry;
|
||||
int i;
|
||||
char optchar;
|
||||
bool doHandleUsage = false, doHandleFree = false, doTableNames = false;
|
||||
bool doFlush = false, doContinue = false, doCSV = false;
|
||||
|
||||
char *table_name = NULL;
|
||||
const char *name;
|
||||
|
||||
printf("\nlibxt_ACCOUNT_cl userspace accounting tool v%s\n\n",
|
||||
LIBXT_ACCOUNT_VERSION);
|
||||
|
||||
if (argc == 1)
|
||||
{
|
||||
show_usage();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
while ((optchar = getopt(argc, argv, "uhacfsl:")) != -1)
|
||||
{
|
||||
switch (optchar)
|
||||
{
|
||||
case 'u':
|
||||
doHandleUsage = true;
|
||||
break;
|
||||
case 'h':
|
||||
doHandleFree = true;
|
||||
break;
|
||||
case 'a':
|
||||
doTableNames = true;
|
||||
break;
|
||||
case 'f':
|
||||
doFlush = true;
|
||||
break;
|
||||
case 'c':
|
||||
doContinue = true;
|
||||
break;
|
||||
case 's':
|
||||
doCSV = true;
|
||||
break;
|
||||
case 'l':
|
||||
table_name = strdup(optarg);
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
show_usage();
|
||||
exit(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// install exit handler
|
||||
if (signal(SIGTERM, sig_term) == SIG_ERR)
|
||||
{
|
||||
printf("can't install signal handler for SIGTERM\n");
|
||||
exit(-1);
|
||||
}
|
||||
if (signal(SIGINT, sig_term) == SIG_ERR)
|
||||
{
|
||||
printf("can't install signal handler for SIGINT\n");
|
||||
exit(-1);
|
||||
}
|
||||
if (signal(SIGQUIT, sig_term) == SIG_ERR)
|
||||
{
|
||||
printf("can't install signal handler for SIGQUIT\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (ipt_ACCOUNT_init(&ctx))
|
||||
{
|
||||
printf("Init failed: %s\n", ctx.error_str);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// Get handle usage?
|
||||
if (doHandleUsage)
|
||||
{
|
||||
int rtn = ipt_ACCOUNT_get_handle_usage(&ctx);
|
||||
if (rtn < 0)
|
||||
{
|
||||
printf("get_handle_usage failed: %s\n", ctx.error_str);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
printf("Current kernel handle usage: %d\n", ctx.handle.itemcount);
|
||||
}
|
||||
|
||||
if (doHandleFree)
|
||||
{
|
||||
int rtn = ipt_ACCOUNT_free_all_handles(&ctx);
|
||||
if (rtn < 0)
|
||||
{
|
||||
printf("handle_free_all failed: %s\n", ctx.error_str);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
printf("Freed all handles in kernel space\n");
|
||||
}
|
||||
|
||||
if (doTableNames)
|
||||
{
|
||||
int rtn = ipt_ACCOUNT_get_table_names(&ctx);
|
||||
if (rtn < 0)
|
||||
{
|
||||
printf("get_table_names failed: %s\n", ctx.error_str);
|
||||
exit(-1);
|
||||
}
|
||||
while ((name = ipt_ACCOUNT_get_next_name(&ctx)) != 0)
|
||||
printf("Found table: %s\n", name);
|
||||
}
|
||||
|
||||
if (table_name)
|
||||
{
|
||||
// Read out data
|
||||
if (doCSV)
|
||||
printf("IP;SRC packets;SRC bytes;DST packets;DST bytes\n");
|
||||
else
|
||||
printf("Showing table: %s\n", table_name);
|
||||
|
||||
i = 0;
|
||||
while (!exit_now)
|
||||
{
|
||||
// Get entries from table test
|
||||
if (ipt_ACCOUNT_read_entries(&ctx, table_name, !doFlush))
|
||||
{
|
||||
printf("Read failed: %s\n", ctx.error_str);
|
||||
ipt_ACCOUNT_deinit(&ctx);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (!doCSV)
|
||||
printf("Run #%d - %u %s found\n", i, ctx.handle.itemcount,
|
||||
ctx.handle.itemcount == 1 ? "item" : "items");
|
||||
|
||||
// Output and free entries
|
||||
while ((entry = ipt_ACCOUNT_get_next_entry(&ctx)) != NULL)
|
||||
{
|
||||
if (doCSV)
|
||||
printf("%s;%u;%u;%u;%u\n",
|
||||
addr_to_dotted(entry->ip), entry->src_packets, entry->src_bytes,
|
||||
entry->dst_packets, entry->dst_bytes);
|
||||
else
|
||||
printf("IP: %s SRC packets: %u bytes: %u DST packets: %u bytes: %u\n",
|
||||
addr_to_dotted(entry->ip), entry->src_packets, entry->src_bytes,
|
||||
entry->dst_packets, entry->dst_bytes);
|
||||
}
|
||||
|
||||
if (doContinue)
|
||||
{
|
||||
sleep(1);
|
||||
i++;
|
||||
} else
|
||||
exit_now = true;
|
||||
}
|
||||
}
|
||||
|
||||
printf("Finished.\n");
|
||||
ipt_ACCOUNT_deinit(&ctx);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
162
extensions/ACCOUNT/libxt_ACCOUNT.c
Normal file
162
extensions/ACCOUNT/libxt_ACCOUNT.c
Normal file
@@ -0,0 +1,162 @@
|
||||
/* Shared library add-on to iptables to add ACCOUNT(ing) support.
|
||||
Author: Intra2net AG <opensource@intra2net.com>
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <netdb.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <syslog.h>
|
||||
#include <getopt.h>
|
||||
#include <stddef.h>
|
||||
#include <xtables.h>
|
||||
#include "xt_ACCOUNT.h"
|
||||
#include "compat_user.h"
|
||||
|
||||
static struct option account_tg_opts[] = {
|
||||
{.name = "addr", .has_arg = true, .val = 'a'},
|
||||
{.name = "tname", .has_arg = true, .val = 't'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
/* Function which prints out usage message. */
|
||||
static void account_tg_help(void)
|
||||
{
|
||||
printf(
|
||||
"ACCOUNT target options:\n"
|
||||
" --%s ip/netmask\t\tBase network IP and netmask used for this table\n"
|
||||
" --%s name\t\t\tTable name for the userspace library\n",
|
||||
account_tg_opts[0].name, account_tg_opts[1].name);
|
||||
}
|
||||
|
||||
/* Initialize the target. */
|
||||
static void
|
||||
account_tg_init(struct xt_entry_target *t)
|
||||
{
|
||||
struct ipt_acc_info *accountinfo = (struct ipt_acc_info *)t->data;
|
||||
|
||||
accountinfo->table_nr = -1;
|
||||
}
|
||||
|
||||
#define IPT_ACCOUNT_OPT_ADDR 0x01
|
||||
#define IPT_ACCOUNT_OPT_TABLE 0x02
|
||||
|
||||
/* Function which parses command options; returns true if it
|
||||
ate an option */
|
||||
|
||||
static int account_tg_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
const void *entry, struct xt_entry_target **target)
|
||||
{
|
||||
struct ipt_acc_info *accountinfo = (struct ipt_acc_info *)(*target)->data;
|
||||
struct in_addr *addrs = NULL, mask;
|
||||
unsigned int naddrs = 0;
|
||||
|
||||
switch (c) {
|
||||
case 'a':
|
||||
if (*flags & IPT_ACCOUNT_OPT_ADDR)
|
||||
xtables_error(PARAMETER_PROBLEM, "Can't specify --%s twice",
|
||||
account_tg_opts[0].name);
|
||||
|
||||
xtables_ipparse_any(optarg, &addrs, &mask, &naddrs);
|
||||
if (naddrs > 1)
|
||||
xtables_error(PARAMETER_PROBLEM, "multiple IP addresses not allowed");
|
||||
|
||||
accountinfo->net_ip = addrs[0].s_addr;
|
||||
accountinfo->net_mask = mask.s_addr;
|
||||
|
||||
*flags |= IPT_ACCOUNT_OPT_ADDR;
|
||||
break;
|
||||
|
||||
case 't':
|
||||
if (*flags & IPT_ACCOUNT_OPT_TABLE)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Can't specify --%s twice",
|
||||
account_tg_opts[1].name);
|
||||
|
||||
if (strlen(optarg) > ACCOUNT_TABLE_NAME_LEN - 1)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Maximum table name length %u for --%s",
|
||||
ACCOUNT_TABLE_NAME_LEN - 1,
|
||||
account_tg_opts[1].name);
|
||||
|
||||
strcpy(accountinfo->table_name, optarg);
|
||||
*flags |= IPT_ACCOUNT_OPT_TABLE;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void account_tg_check(unsigned int flags)
|
||||
{
|
||||
if (!(flags & IPT_ACCOUNT_OPT_ADDR) || !(flags & IPT_ACCOUNT_OPT_TABLE))
|
||||
xtables_error(PARAMETER_PROBLEM, "ACCOUNT: needs --%s and --%s",
|
||||
account_tg_opts[0].name, account_tg_opts[1].name);
|
||||
}
|
||||
|
||||
static void account_tg_print_it(const void *ip,
|
||||
const struct xt_entry_target *target, bool do_prefix)
|
||||
{
|
||||
const struct ipt_acc_info *accountinfo
|
||||
= (const struct ipt_acc_info *)target->data;
|
||||
struct in_addr a;
|
||||
|
||||
if (!do_prefix)
|
||||
printf(" ACCOUNT ");
|
||||
|
||||
// Network information
|
||||
if (do_prefix)
|
||||
printf(" --");
|
||||
printf("%s ", account_tg_opts[0].name);
|
||||
|
||||
a.s_addr = accountinfo->net_ip;
|
||||
printf("%s", xtables_ipaddr_to_numeric(&a));
|
||||
a.s_addr = accountinfo->net_mask;
|
||||
printf("%s", xtables_ipmask_to_numeric(&a));
|
||||
|
||||
printf(" ");
|
||||
if (do_prefix)
|
||||
printf(" --");
|
||||
|
||||
printf("%s %s", account_tg_opts[1].name, accountinfo->table_name);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
account_tg_print(const void *ip,
|
||||
const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
account_tg_print_it(ip, target, false);
|
||||
}
|
||||
|
||||
/* Saves the union ipt_targinfo in parsable form to stdout. */
|
||||
static void
|
||||
account_tg_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
account_tg_print_it(ip, target, true);
|
||||
}
|
||||
|
||||
static struct xtables_target account_tg_reg = {
|
||||
.name = "ACCOUNT",
|
||||
.revision = 1,
|
||||
.family = NFPROTO_IPV4,
|
||||
.version = XTABLES_VERSION,
|
||||
.size = XT_ALIGN(sizeof(struct ipt_acc_info)),
|
||||
.userspacesize = offsetof(struct ipt_acc_info, table_nr),
|
||||
.help = account_tg_help,
|
||||
.init = account_tg_init,
|
||||
.parse = account_tg_parse,
|
||||
.final_check = account_tg_check,
|
||||
.print = account_tg_print,
|
||||
.save = account_tg_save,
|
||||
.extra_opts = account_tg_opts,
|
||||
};
|
||||
|
||||
static __attribute__((constructor)) void account_tg_ldr(void)
|
||||
{
|
||||
xtables_register_target(&account_tg_reg);
|
||||
}
|
||||
60
extensions/ACCOUNT/libxt_ACCOUNT.man
Normal file
60
extensions/ACCOUNT/libxt_ACCOUNT.man
Normal file
@@ -0,0 +1,60 @@
|
||||
The ACCOUNT target is a high performance accounting system for large
|
||||
local networks. It allows per-IP accounting in whole prefixes of IPv4
|
||||
addresses with size of up to /8 without the need to add individual
|
||||
accouting rule for each IP address.
|
||||
.PP
|
||||
The ACCOUNT is designed to be queried for data every second or at
|
||||
least every ten seconds. It is written as kernel module to handle high
|
||||
bandwidths without packet loss.
|
||||
.PP
|
||||
The largest possible subnet size is 24 bit, meaning for example 10.0.0.0/8
|
||||
network. ACCOUNT uses fixed internal data structures
|
||||
which speeds up the processing of each packet. Furthermore,
|
||||
accounting data for one complete 192.168.1.X/24 network takes 4 KB of
|
||||
memory. Memory for 16 or 24 bit networks is only allocated when
|
||||
needed.
|
||||
.PP
|
||||
To optimize the kernel<->userspace data transfer a bit more, the
|
||||
kernel module only transfers information about IPs, where the src/dst
|
||||
packet counter is not 0. This saves precious kernel time.
|
||||
.PP
|
||||
There is no /proc interface as it would be too slow for continuous access.
|
||||
The read-and-flush query operation is the fastest, as no internal data
|
||||
snapshot needs to be created&copied for all data. Use the "read"
|
||||
operation without flush only for debugging purposes!
|
||||
.PP
|
||||
Usage:
|
||||
.PP
|
||||
ACCOUNT takes two mandatory parameters:
|
||||
.TP
|
||||
\fB\-\-addr\fR \fInetwork\fP\fB/\fP\fInetmask\fR
|
||||
where \fInetwork\fP\fB/\fP\fInetmask\fP is the subnet to account for, in CIDR syntax
|
||||
.TP
|
||||
\fB\-\-tname\fP \fINAME\fP
|
||||
where \fINAME\fP is the name of the table where the accounting information
|
||||
should be stored
|
||||
.PP
|
||||
The subnet 0.0.0.0/0 is a special case: all data are then stored in the src_bytes
|
||||
and src_packets structure of slot "0". This is useful if you want
|
||||
to account the overall traffic to/from your internet provider.
|
||||
.PP
|
||||
The data can be queried using the userspace libxt_ACCOUNT_cl library,
|
||||
and by the reference implementation to show usage of this library,
|
||||
the \fBiptaccount\fP(8) tool.
|
||||
.PP
|
||||
Here is an example of use:
|
||||
.PP
|
||||
iptables \-A FORWARD \-j ACCOUNT \-\-addr 0.0.0.0/0 \-\-tname all_outgoing;
|
||||
iptables \-A FORWARD \-j ACCOUNT \-\-addr 192.168.1.0/24 \-\-tname sales;
|
||||
.PP
|
||||
This creates two tables called "all_outgoing" and "sales" which can be
|
||||
queried using the userspace library/iptaccount tool.
|
||||
.PP
|
||||
Note that this target is non-terminating \(em the packet destined to it
|
||||
will continue traversing the chain in which it has been used.
|
||||
.PP
|
||||
Also note that once a table has been defined for specific CIDR address/netmask
|
||||
block, it can be referenced multiple times using \-j ACCOUNT, provided
|
||||
that both the original table name and address/netmask block are specified.
|
||||
.PP
|
||||
For more information go to http://www.intra2net.com/en/developer/ipt_ACCOUNT/
|
||||
199
extensions/ACCOUNT/libxt_ACCOUNT_cl.c
Normal file
199
extensions/ACCOUNT/libxt_ACCOUNT_cl.c
Normal file
@@ -0,0 +1,199 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2004 by Intra2net AG *
|
||||
* opensource@intra2net.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License *
|
||||
* version 2.1 as published by the Free Software Foundation; *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <linux/if.h>
|
||||
|
||||
#include <libxt_ACCOUNT_cl.h>
|
||||
|
||||
int ipt_ACCOUNT_init(struct ipt_ACCOUNT_context *ctx)
|
||||
{
|
||||
memset(ctx, 0, sizeof(struct ipt_ACCOUNT_context));
|
||||
ctx->handle.handle_nr = -1;
|
||||
|
||||
ctx->sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
|
||||
if (ctx->sockfd < 0) {
|
||||
ctx->sockfd = -1;
|
||||
ctx->error_str = "Can't open socket to kernel. "
|
||||
"Permission denied or ipt_ACCOUNT module not loaded";
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 4096 bytes default buffer should save us from reallocations
|
||||
// as it fits 200 concurrent active clients
|
||||
if ((ctx->data = malloc(IPT_ACCOUNT_MIN_BUFSIZE)) == NULL) {
|
||||
close(ctx->sockfd);
|
||||
ctx->sockfd = -1;
|
||||
ctx->error_str = "Out of memory for data buffer";
|
||||
return -1;
|
||||
}
|
||||
ctx->data_size = IPT_ACCOUNT_MIN_BUFSIZE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ipt_ACCOUNT_free_entries(struct ipt_ACCOUNT_context *ctx)
|
||||
{
|
||||
if (ctx->handle.handle_nr != -1) {
|
||||
setsockopt(ctx->sockfd, IPPROTO_IP, IPT_SO_SET_ACCOUNT_HANDLE_FREE,
|
||||
&ctx->handle, sizeof(struct ipt_acc_handle_sockopt));
|
||||
ctx->handle.handle_nr = -1;
|
||||
}
|
||||
|
||||
ctx->handle.itemcount = 0;
|
||||
ctx->pos = 0;
|
||||
}
|
||||
|
||||
void ipt_ACCOUNT_deinit(struct ipt_ACCOUNT_context *ctx)
|
||||
{
|
||||
free(ctx->data);
|
||||
ctx->data = NULL;
|
||||
|
||||
ipt_ACCOUNT_free_entries(ctx);
|
||||
|
||||
close(ctx->sockfd);
|
||||
ctx->sockfd = -1;
|
||||
}
|
||||
|
||||
int ipt_ACCOUNT_read_entries(struct ipt_ACCOUNT_context *ctx,
|
||||
const char *table, char dont_flush)
|
||||
{
|
||||
unsigned int s = sizeof(struct ipt_acc_handle_sockopt);
|
||||
unsigned int new_size;
|
||||
int rtn;
|
||||
|
||||
strncpy(ctx->handle.name, table, ACCOUNT_TABLE_NAME_LEN-1);
|
||||
|
||||
// Get table information
|
||||
if (!dont_flush)
|
||||
rtn = getsockopt(ctx->sockfd, IPPROTO_IP,
|
||||
IPT_SO_GET_ACCOUNT_PREPARE_READ_FLUSH, &ctx->handle, &s);
|
||||
else
|
||||
rtn = getsockopt(ctx->sockfd, IPPROTO_IP, IPT_SO_GET_ACCOUNT_PREPARE_READ,
|
||||
&ctx->handle, &s);
|
||||
|
||||
if (rtn < 0) {
|
||||
ctx->error_str = "Can't get table information from kernel. "
|
||||
"Does it exist?";
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Check data buffer size
|
||||
ctx->pos = 0;
|
||||
new_size = ctx->handle.itemcount * sizeof(struct ipt_acc_handle_ip);
|
||||
// We want to prevent reallocations all the time
|
||||
if (new_size < IPT_ACCOUNT_MIN_BUFSIZE)
|
||||
new_size = IPT_ACCOUNT_MIN_BUFSIZE;
|
||||
|
||||
// Reallocate if it's too small or twice as big
|
||||
if (ctx->data_size < new_size || ctx->data_size > new_size * 2) {
|
||||
// Free old buffer
|
||||
free(ctx->data);
|
||||
ctx->data_size = 0;
|
||||
|
||||
if ((ctx->data = malloc(new_size)) == NULL) {
|
||||
ctx->error_str = "Out of memory for data buffer";
|
||||
ipt_ACCOUNT_free_entries(ctx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->data_size = new_size;
|
||||
}
|
||||
|
||||
// Copy data from kernel
|
||||
memcpy(ctx->data, &ctx->handle, sizeof(struct ipt_acc_handle_sockopt));
|
||||
rtn = getsockopt(ctx->sockfd, IPPROTO_IP, IPT_SO_GET_ACCOUNT_GET_DATA,
|
||||
ctx->data, &ctx->data_size);
|
||||
if (rtn < 0) {
|
||||
ctx->error_str = "Can't get data from kernel. "
|
||||
"Check /var/log/messages for details.";
|
||||
ipt_ACCOUNT_free_entries(ctx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Free kernel handle but don't reset pos/itemcount
|
||||
setsockopt(ctx->sockfd, IPPROTO_IP, IPT_SO_SET_ACCOUNT_HANDLE_FREE,
|
||||
&ctx->handle, sizeof(struct ipt_acc_handle_sockopt));
|
||||
ctx->handle.handle_nr = -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ipt_acc_handle_ip *ipt_ACCOUNT_get_next_entry(struct ipt_ACCOUNT_context *ctx)
|
||||
{
|
||||
struct ipt_acc_handle_ip *rtn;
|
||||
|
||||
// Empty or no more items left to return?
|
||||
if (!ctx->handle.itemcount || ctx->pos >= ctx->handle.itemcount)
|
||||
return NULL;
|
||||
|
||||
// Get next entry
|
||||
rtn = (struct ipt_acc_handle_ip *)(ctx->data + ctx->pos
|
||||
* sizeof(struct ipt_acc_handle_ip));
|
||||
ctx->pos++;
|
||||
|
||||
return rtn;
|
||||
}
|
||||
|
||||
int ipt_ACCOUNT_get_handle_usage(struct ipt_ACCOUNT_context *ctx)
|
||||
{
|
||||
unsigned int s = sizeof(struct ipt_acc_handle_sockopt);
|
||||
if (getsockopt(ctx->sockfd, IPPROTO_IP,
|
||||
IPT_SO_GET_ACCOUNT_GET_HANDLE_USAGE, &ctx->handle, &s) < 0) {
|
||||
ctx->error_str = "Can't get handle usage information from kernel";
|
||||
return -1;
|
||||
}
|
||||
ctx->handle.handle_nr = -1;
|
||||
|
||||
return ctx->handle.itemcount;
|
||||
}
|
||||
|
||||
int ipt_ACCOUNT_free_all_handles(struct ipt_ACCOUNT_context *ctx)
|
||||
{
|
||||
if (setsockopt(ctx->sockfd, IPPROTO_IP,
|
||||
IPT_SO_SET_ACCOUNT_HANDLE_FREE_ALL, NULL, 0) < 0) {
|
||||
ctx->error_str = "Can't free all kernel handles";
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ipt_ACCOUNT_get_table_names(struct ipt_ACCOUNT_context *ctx)
|
||||
{
|
||||
int rtn = getsockopt(ctx->sockfd, IPPROTO_IP,
|
||||
IPT_SO_GET_ACCOUNT_GET_TABLE_NAMES,
|
||||
ctx->data, &ctx->data_size);
|
||||
if (rtn < 0) {
|
||||
ctx->error_str = "Can't get table names from kernel. Out of memory, "
|
||||
"MINBUFISZE too small?";
|
||||
return -1;
|
||||
}
|
||||
ctx->pos = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *ipt_ACCOUNT_get_next_name(struct ipt_ACCOUNT_context *ctx)
|
||||
{
|
||||
const char *rtn;
|
||||
if (((char *)ctx->data)[ctx->pos] == 0)
|
||||
return 0;
|
||||
|
||||
rtn = ctx->data + ctx->pos;
|
||||
ctx->pos += strlen(ctx->data + ctx->pos) + 1;
|
||||
|
||||
return rtn;
|
||||
}
|
||||
60
extensions/ACCOUNT/libxt_ACCOUNT_cl.h
Normal file
60
extensions/ACCOUNT/libxt_ACCOUNT_cl.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2004 by Intra2net AG *
|
||||
* opensource@intra2net.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License *
|
||||
* version 2.1 as published by the Free Software Foundation; *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef _xt_ACCOUNT_cl_H
|
||||
#define _xt_ACCOUNT_cl_H
|
||||
|
||||
#include <xt_ACCOUNT.h>
|
||||
|
||||
#define LIBXT_ACCOUNT_VERSION "1.3"
|
||||
|
||||
/* Don't set this below the size of struct ipt_account_handle_sockopt */
|
||||
#define IPT_ACCOUNT_MIN_BUFSIZE 4096
|
||||
|
||||
struct ipt_ACCOUNT_context
|
||||
{
|
||||
int sockfd;
|
||||
struct ipt_acc_handle_sockopt handle;
|
||||
|
||||
unsigned int data_size;
|
||||
void *data;
|
||||
unsigned int pos;
|
||||
|
||||
char *error_str;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int ipt_ACCOUNT_init(struct ipt_ACCOUNT_context *ctx);
|
||||
void ipt_ACCOUNT_deinit(struct ipt_ACCOUNT_context *ctx);
|
||||
|
||||
void ipt_ACCOUNT_free_entries(struct ipt_ACCOUNT_context *ctx);
|
||||
int ipt_ACCOUNT_read_entries(struct ipt_ACCOUNT_context *ctx,
|
||||
const char *table, char dont_flush);
|
||||
struct ipt_acc_handle_ip *ipt_ACCOUNT_get_next_entry(
|
||||
struct ipt_ACCOUNT_context *ctx);
|
||||
|
||||
/* ipt_ACCOUNT_free_entries is for internal use only function as this library
|
||||
is constructed to be used in a loop -> Don't allocate memory all the time.
|
||||
The data buffer is freed on deinit() */
|
||||
|
||||
int ipt_ACCOUNT_get_handle_usage(struct ipt_ACCOUNT_context *ctx);
|
||||
int ipt_ACCOUNT_free_all_handles(struct ipt_ACCOUNT_context *ctx);
|
||||
int ipt_ACCOUNT_get_table_names(struct ipt_ACCOUNT_context *ctx);
|
||||
const char *ipt_ACCOUNT_get_next_name(struct ipt_ACCOUNT_context *ctx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
13
extensions/ACCOUNT/xt_ACCOUNT.Kconfig
Normal file
13
extensions/ACCOUNT/xt_ACCOUNT.Kconfig
Normal file
@@ -0,0 +1,13 @@
|
||||
config NETFILTER_XT_TARGET_ACCOUNT
|
||||
tristate "ACCOUNT target support"
|
||||
depends on NETFILTER_XTABLES
|
||||
---help---
|
||||
This module implements an ACCOUNT target
|
||||
|
||||
The ACCOUNT target is a high performance accounting system for large
|
||||
local networks. It allows per-IP accounting in whole prefixes of IPv4
|
||||
addresses with size of up to /8 without the need to add individual
|
||||
accouting rule for each IP address.
|
||||
|
||||
For more information go to:
|
||||
http://www.intra2net.com/de/produkte/opensource/ipt_account/
|
||||
1169
extensions/ACCOUNT/xt_ACCOUNT.c
Normal file
1169
extensions/ACCOUNT/xt_ACCOUNT.c
Normal file
File diff suppressed because it is too large
Load Diff
69
extensions/ACCOUNT/xt_ACCOUNT.h
Normal file
69
extensions/ACCOUNT/xt_ACCOUNT.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2004-2006 by Intra2net AG *
|
||||
* opensource@intra2net.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License *
|
||||
* version 2 as published by the Free Software Foundation; *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef _IPT_ACCOUNT_H
|
||||
#define _IPT_ACCOUNT_H
|
||||
|
||||
/*
|
||||
* Socket option interface shared between kernel (xt_ACCOUNT) and userspace
|
||||
* library (libxt_ACCOUNT_cl). Hopefully we are unique at least within our
|
||||
* kernel & xtables-addons space.
|
||||
*
|
||||
* Turned out often enough we are not.
|
||||
* 64-67 used by ip_tables, ip6_tables
|
||||
* 96-100 used by arp_tables
|
||||
* 128-131 used by ebtables
|
||||
*/
|
||||
#define SO_ACCOUNT_BASE_CTL 70
|
||||
|
||||
#define IPT_SO_SET_ACCOUNT_HANDLE_FREE (SO_ACCOUNT_BASE_CTL + 1)
|
||||
#define IPT_SO_SET_ACCOUNT_HANDLE_FREE_ALL (SO_ACCOUNT_BASE_CTL + 2)
|
||||
#define IPT_SO_SET_ACCOUNT_MAX IPT_SO_SET_ACCOUNT_HANDLE_FREE_ALL
|
||||
|
||||
#define IPT_SO_GET_ACCOUNT_PREPARE_READ (SO_ACCOUNT_BASE_CTL + 4)
|
||||
#define IPT_SO_GET_ACCOUNT_PREPARE_READ_FLUSH (SO_ACCOUNT_BASE_CTL + 5)
|
||||
#define IPT_SO_GET_ACCOUNT_GET_DATA (SO_ACCOUNT_BASE_CTL + 6)
|
||||
#define IPT_SO_GET_ACCOUNT_GET_HANDLE_USAGE (SO_ACCOUNT_BASE_CTL + 7)
|
||||
#define IPT_SO_GET_ACCOUNT_GET_TABLE_NAMES (SO_ACCOUNT_BASE_CTL + 8)
|
||||
#define IPT_SO_GET_ACCOUNT_MAX IPT_SO_GET_ACCOUNT_GET_TABLE_NAMES
|
||||
|
||||
#define ACCOUNT_MAX_TABLES 128
|
||||
#define ACCOUNT_TABLE_NAME_LEN 32
|
||||
#define ACCOUNT_MAX_HANDLES 10
|
||||
|
||||
/* Structure for the userspace part of ipt_ACCOUNT */
|
||||
struct ipt_acc_info {
|
||||
__be32 net_ip;
|
||||
__be32 net_mask;
|
||||
char table_name[ACCOUNT_TABLE_NAME_LEN];
|
||||
int32_t table_nr;
|
||||
};
|
||||
|
||||
/* Handle structure for communication with the userspace library */
|
||||
struct ipt_acc_handle_sockopt {
|
||||
uint32_t handle_nr; /* Used for HANDLE_FREE */
|
||||
char name[ACCOUNT_TABLE_NAME_LEN]; /* Used for HANDLE_PREPARE_READ/
|
||||
HANDLE_READ_FLUSH */
|
||||
uint32_t itemcount; /* Used for HANDLE_PREPARE_READ/
|
||||
HANDLE_READ_FLUSH */
|
||||
};
|
||||
|
||||
/*
|
||||
Used for every IP when returning data
|
||||
*/
|
||||
struct ipt_acc_handle_ip {
|
||||
__be32 ip;
|
||||
uint32_t src_packets;
|
||||
uint32_t src_bytes;
|
||||
uint32_t dst_packets;
|
||||
uint32_t dst_bytes;
|
||||
};
|
||||
|
||||
#endif /* _IPT_ACCOUNT_H */
|
||||
@@ -1,144 +0,0 @@
|
||||
# -*- Makefile -*-
|
||||
|
||||
top_srcdir := @top_srcdir@
|
||||
srcdir := @srcdir@
|
||||
abstop_srcdir := $(shell readlink -f ${top_srcdir})
|
||||
abssrcdir := $(shell readlink -f ${srcdir})
|
||||
|
||||
ifeq (${abstop_srcdir},)
|
||||
$(error Path resolution of ${top_srcdir} failed)
|
||||
endif
|
||||
ifeq (${abssrcdir},)
|
||||
$(error Path resolution of ${srcdir} failed)
|
||||
endif
|
||||
|
||||
prefix := @prefix@
|
||||
exec_prefix := @exec_prefix@
|
||||
libdir := @libdir@
|
||||
libexecdir := @libexecdir@
|
||||
xtlibdir := @xtlibdir@
|
||||
kbuilddir := @kbuilddir@
|
||||
|
||||
CC := @CC@
|
||||
CCLD := ${CC}
|
||||
CFLAGS := @CFLAGS@
|
||||
LDFLAGS := @LDFLAGS@
|
||||
regular_CFLAGS := @regular_CFLAGS@
|
||||
kinclude_CFLAGS := @kinclude_CFLAGS@
|
||||
xtables_CFLAGS := @xtables_CFLAGS@
|
||||
|
||||
AM_CFLAGS := ${regular_CFLAGS} -I${top_srcdir}/include ${xtables_CFLAGS} ${kinclude_CFLAGS}
|
||||
AM_DEPFLAGS = -Wp,-MMD,$(@D)/.$(@F).d,-MT,$@
|
||||
|
||||
VU := 0
|
||||
am__1verbose_CC_0 = @echo " CC " $@;
|
||||
am__1verbose_CCLD_0 = @echo " CCLD " $@;
|
||||
am__1verbose_GEN_0 = @echo " GEN " $@;
|
||||
am__1verbose_SILENT_0 = @
|
||||
am__1verbose_CC_1 = @echo " CC " $@ "<-" $<;
|
||||
am__1verbose_CCLD_1 = @echo " CCLD " $@ "<-" $^;
|
||||
am__1verbose_GEN_1 = @echo " GEN " $@ "<-" $<;
|
||||
am__verbose_CC = ${am__1verbose_CC_${VU}}
|
||||
am__verbose_CCLD = ${am__1verbose_CCLD_${VU}}
|
||||
am__verbose_GEN = ${am__1verbose_GEN_${VU}}
|
||||
am__verbose_SILENT = ${am__1verbose_GEN_${VU}}
|
||||
|
||||
|
||||
#
|
||||
# Wildcard module list
|
||||
#
|
||||
include ${top_srcdir}/mconfig
|
||||
-include ${top_srcdir}/mconfig.*
|
||||
include ${srcdir}/Mbuild
|
||||
-include ${srcdir}/Mbuild.*
|
||||
-include ${srcdir}/*.Mbuild
|
||||
|
||||
|
||||
#
|
||||
# Building blocks
|
||||
#
|
||||
targets := $(filter-out %/,${obj-m})
|
||||
targets_install := ${targets}
|
||||
subdirs_list := $(filter %/,${obj-m})
|
||||
|
||||
.SECONDARY:
|
||||
|
||||
.PHONY: all install clean distclean FORCE
|
||||
|
||||
all: subdirs modules user matches.man targets.man
|
||||
|
||||
subdirs:
|
||||
@for i in ${subdirs_list}; do ${MAKE} -C $$i; done;
|
||||
|
||||
subdirs-install:
|
||||
@for i in ${subdirs_list}; do ${MAKE} -C $$i install; done;
|
||||
|
||||
user: ${targets}
|
||||
|
||||
install: modules_install subdirs-install ${targets_install}
|
||||
@mkdir -p "${DESTDIR}${xtlibdir}";
|
||||
install -pm0755 ${targets_install} "${DESTDIR}${xtlibdir}/";
|
||||
|
||||
clean: clean_modules
|
||||
@for i in ${subdirs_list}; do make -C $$i clean; done;
|
||||
rm -f *.oo *.so;
|
||||
|
||||
distclean: clean
|
||||
rm -f .*.d .manpages.lst;
|
||||
|
||||
-include .*.d
|
||||
|
||||
|
||||
#
|
||||
# Call out to kbuild
|
||||
#
|
||||
.PHONY: modules modules_install clean_modules
|
||||
|
||||
modules:
|
||||
${am__verbose_SILENT}if [ -n "${kbuilddir}" ]; then make -C ${kbuilddir} M=${abssrcdir} XA_TOPSRCDIR=${abstop_srcdir} modules; fi;
|
||||
|
||||
modules_install:
|
||||
${am__verbose_SILENT}if [ -n "${kbuilddir}" ]; then make -C ${kbuilddir} M=${abssrcdir} XA_TOPSRCDIR=${abstop_srcdir} INSTALL_MOD_PATH=${DESTDIR} modules_install; fi;
|
||||
|
||||
clean_modules:
|
||||
${am__verbose_SILENT}if [ -n "${kbuilddir}" ]; then make -C ${kbuilddir} M=${abssrcdir} XA_TOPSRCDIR=${abstop_srcdir} clean; fi;
|
||||
|
||||
|
||||
#
|
||||
# Shared libraries
|
||||
#
|
||||
lib%.so: lib%.oo
|
||||
${am__verbose_CCLD}${CCLD} ${AM_LDFLAGS} -shared ${LDFLAGS} -o $@ $<;
|
||||
|
||||
lib%.oo: ${srcdir}/lib%.c
|
||||
${am__verbose_CC}${CC} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=lib$*_init -DPIC -fPIC ${CFLAGS} -o $@ -c $<;
|
||||
|
||||
|
||||
#
|
||||
# Manpages
|
||||
#
|
||||
wcman_matches := $(wildcard ${srcdir}/libxt_[a-z]*.man)
|
||||
wcman_targets := $(wildcard ${srcdir}/libxt_[A-Z]*.man)
|
||||
wlist_matches := $(patsubst ${srcdir}/libxt_%.man,%,${wcman_matches})
|
||||
wlist_targets := $(patsubst ${srcdir}/libxt_%.man,%,${wcman_targets})
|
||||
|
||||
.manpages.lst: FORCE
|
||||
@echo "${wlist_targets} ${wlist_matches}" >$@.tmp; \
|
||||
cmp -s $@ $@.tmp || mv $@.tmp $@; \
|
||||
rm -f $@.tmp;
|
||||
|
||||
man_run = \
|
||||
${am__verbose_GEN}for ext in $(1); do \
|
||||
f="${srcdir}/libxt_$$ext.man"; \
|
||||
if [ -f "$$f" ]; then \
|
||||
echo ".SS $$ext"; \
|
||||
cat "$$f"; \
|
||||
continue; \
|
||||
fi; \
|
||||
done >$@;
|
||||
|
||||
matches.man: .manpages.lst ${wcman_matches}
|
||||
$(call man_run,${wlist_matches})
|
||||
|
||||
targets.man: .manpages.lst ${wcman_targets}
|
||||
$(call man_run,${wlist_targets})
|
||||
@@ -1,17 +1,23 @@
|
||||
# -*- Makefile -*-
|
||||
|
||||
include ${XA_TOPSRCDIR}/mconfig
|
||||
-include ${XA_TOPSRCDIR}/mconfig.*
|
||||
include ${XA_ABSTOPSRCDIR}/mconfig
|
||||
-include ${XA_ABSTOPSRCDIR}/mconfig.*
|
||||
|
||||
obj-m += compat_xtables.o
|
||||
|
||||
obj-${build_ACCOUNT} += ACCOUNT/
|
||||
obj-${build_CHAOS} += xt_CHAOS.o
|
||||
obj-${build_CHECKSUM} += xt_CHECKSUM.o
|
||||
obj-${build_DELUDE} += xt_DELUDE.o
|
||||
obj-${build_DHCPMAC} += xt_DHCPMAC.o
|
||||
obj-${build_DNETMAP} += xt_DNETMAP.o
|
||||
obj-${build_ECHO} += xt_ECHO.o
|
||||
obj-${build_IPMARK} += xt_IPMARK.o
|
||||
obj-${build_LOGMARK} += xt_LOGMARK.o
|
||||
obj-${build_RAWNAT} += xt_RAWNAT.o iptable_rawpost.o ip6table_rawpost.o
|
||||
obj-${build_RAWNAT} += xt_RAWNAT.o iptable_rawpost.o
|
||||
ifneq (${CONFIG_IPV6},)
|
||||
obj-${build_RAWNAT} += ip6table_rawpost.o
|
||||
endif
|
||||
obj-${build_SYSRQ} += xt_SYSRQ.o
|
||||
obj-${build_STEAL} += xt_STEAL.o
|
||||
obj-${build_TARPIT} += xt_TARPIT.o
|
||||
@@ -21,10 +27,12 @@ obj-${build_fuzzy} += xt_fuzzy.o
|
||||
obj-${build_geoip} += xt_geoip.o
|
||||
obj-${build_iface} += xt_iface.o
|
||||
obj-${build_ipp2p} += xt_ipp2p.o
|
||||
obj-${build_ipset} += ipset/
|
||||
obj-${build_ipset6} += ipset-6/
|
||||
obj-${build_ipv4options} += xt_ipv4options.o
|
||||
obj-${build_length2} += xt_length2.o
|
||||
obj-${build_lscan} += xt_lscan.o
|
||||
obj-${build_pknock} += pknock/
|
||||
obj-${build_psd} += xt_psd.o
|
||||
obj-${build_quota2} += xt_quota2.o
|
||||
|
||||
-include ${M}/*.Kbuild
|
||||
|
||||
29
extensions/Makefile.am
Normal file
29
extensions/Makefile.am
Normal file
@@ -0,0 +1,29 @@
|
||||
# -*- Makefile -*-
|
||||
# AUTOMAKE
|
||||
|
||||
AM_CPPFLAGS = ${regular_CPPFLAGS} -I${abs_top_srcdir}/extensions
|
||||
AM_CFLAGS = ${regular_CFLAGS} ${libxtables_CFLAGS}
|
||||
|
||||
# Not having Kbuild in Makefile.extra because it will already recurse
|
||||
.PHONY: modules modules_install clean_modules
|
||||
|
||||
_kcall = -C ${kbuilddir} M=${abs_srcdir}
|
||||
|
||||
modules:
|
||||
@echo -n "Xtables-addons ${PACKAGE_VERSION} - Linux "
|
||||
@if [ -n "${kbuilddir}" ]; then ${MAKE} ${_kcall} --no-print-directory -s kernelrelease; fi;
|
||||
${AM_V_silent}if [ -n "${kbuilddir}" ]; then ${MAKE} ${_kcall} modules; fi;
|
||||
|
||||
modules_install:
|
||||
${AM_V_silent}if [ -n "${kbuilddir}" ]; then ${MAKE} ${_kcall} INSTALL_MOD_PATH=${DESTDIR} ext-mod-dir='$${INSTALL_MOD_DIR}' modules_install; fi;
|
||||
|
||||
clean_modules:
|
||||
${AM_V_silent}if [ -n "${kbuilddir}" ]; then ${MAKE} ${_kcall} clean; fi;
|
||||
|
||||
all-local: modules
|
||||
|
||||
install-exec-local: modules_install
|
||||
|
||||
clean-local: clean_modules
|
||||
|
||||
include ../Makefile.extra
|
||||
@@ -1,6 +1,11 @@
|
||||
# -*- Makefile -*-
|
||||
|
||||
obj-${build_ACCOUNT} += ACCOUNT/
|
||||
obj-${build_CHAOS} += libxt_CHAOS.so
|
||||
obj-${build_CHECKSUM} += libxt_CHECKSUM.so
|
||||
obj-${build_DELUDE} += libxt_DELUDE.so
|
||||
obj-${build_DHCPMAC} += libxt_DHCPMAC.so libxt_dhcpmac.so
|
||||
obj-${build_DNETMAP} += libxt_DNETMAP.so
|
||||
obj-${build_ECHO} += libxt_ECHO.so
|
||||
obj-${build_IPMARK} += libxt_IPMARK.so
|
||||
obj-${build_LOGMARK} += libxt_LOGMARK.so
|
||||
@@ -14,8 +19,11 @@ obj-${build_fuzzy} += libxt_fuzzy.so
|
||||
obj-${build_geoip} += libxt_geoip.so
|
||||
obj-${build_iface} += libxt_iface.so
|
||||
obj-${build_ipp2p} += libxt_ipp2p.so
|
||||
obj-${build_ipset} += ipset/
|
||||
obj-${build_ipset6} += ipset-6/
|
||||
obj-${build_ipv4options} += libxt_ipv4options.so
|
||||
obj-${build_length2} += libxt_length2.so
|
||||
obj-${build_lscan} += libxt_lscan.so
|
||||
obj-${build_pknock} += pknock/
|
||||
obj-${build_psd} += libxt_psd.so
|
||||
obj-${build_quota2} += libxt_quota2.so
|
||||
obj-${build_gradm} += libxt_gradm.so
|
||||
|
||||
@@ -4,13 +4,33 @@
|
||||
struct tcphdr;
|
||||
struct udphdr;
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 30)
|
||||
static inline void skb_dst_set(struct sk_buff *skb, struct dst_entry *dst)
|
||||
{
|
||||
skb->dst = dst;
|
||||
}
|
||||
|
||||
static inline struct dst_entry *skb_dst(const struct sk_buff *skb)
|
||||
{
|
||||
return skb->dst;
|
||||
}
|
||||
|
||||
static inline struct rtable *skb_rtable(const struct sk_buff *skb)
|
||||
{
|
||||
return (void *)skb->dst;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 19)
|
||||
# define skb_ifindex(skb) \
|
||||
(((skb)->input_dev != NULL) ? (skb)->input_dev->ifindex : 0)
|
||||
# define skb_nfmark(skb) (((struct sk_buff *)(skb))->nfmark)
|
||||
#else
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32)
|
||||
# define skb_ifindex(skb) (skb)->iif
|
||||
# define skb_nfmark(skb) (((struct sk_buff *)(skb))->mark)
|
||||
#else
|
||||
# define skb_ifindex(skb) (skb)->skb_iif
|
||||
# define skb_nfmark(skb) (((struct sk_buff *)(skb))->mark)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NETWORK_SECMARK
|
||||
|
||||
12
extensions/compat_user.h
Normal file
12
extensions/compat_user.h
Normal file
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Userspace-level compat hacks
|
||||
*/
|
||||
#ifndef _XTABLES_COMPAT_USER_H
|
||||
#define _XTABLES_COMPAT_USER_H 1
|
||||
|
||||
/* linux-glibc-devel 2.6.34 header screwup */
|
||||
#ifndef ALIGN
|
||||
# define ALIGN(s, n) (((s) + ((n) - 1)) & ~((n) - 1))
|
||||
#endif
|
||||
|
||||
#endif /* _XTABLES_COMPAT_USER_H */
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* API compat layer
|
||||
* written by Jan Engelhardt <jengelh [at] medozas de>, 2008
|
||||
* written by Jan Engelhardt <jengelh [at] medozas de>, 2008 - 2010
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License, either
|
||||
@@ -8,7 +8,9 @@
|
||||
*/
|
||||
#include <linux/ip.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kmod.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/version.h>
|
||||
@@ -17,6 +19,9 @@
|
||||
#include <linux/netfilter_arp.h>
|
||||
#include <net/ip.h>
|
||||
#include <net/route.h>
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
|
||||
# include <linux/export.h>
|
||||
#endif
|
||||
#include "compat_skbuff.h"
|
||||
#include "compat_xtnu.h"
|
||||
|
||||
@@ -34,25 +39,49 @@ static bool xtnu_match_run(const struct sk_buff *skb,
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
{
|
||||
struct xtnu_match *nm = xtcompat_numatch(cm);
|
||||
bool lo_drop = false, lo_ret;
|
||||
struct xt_match_param local_par = {
|
||||
.in = in,
|
||||
.out = out,
|
||||
.match = cm,
|
||||
.matchinfo = matchinfo,
|
||||
.fragoff = offset,
|
||||
.thoff = protoff,
|
||||
.hotdrop = &lo_drop,
|
||||
.family = NFPROTO_UNSPEC, /* don't have that info */
|
||||
};
|
||||
bool lo_ret;
|
||||
struct xt_action_param local_par;
|
||||
local_par.in = in;
|
||||
local_par.out = out;
|
||||
local_par.match = cm;
|
||||
local_par.matchinfo = matchinfo;
|
||||
local_par.fragoff = offset;
|
||||
local_par.thoff = protoff;
|
||||
local_par.hotdrop = false;
|
||||
local_par.family = NFPROTO_UNSPEC; /* don't have that info */
|
||||
|
||||
if (nm == NULL || nm->match == NULL)
|
||||
return false;
|
||||
lo_ret = nm->match(skb, &local_par);
|
||||
*hotdrop = lo_drop;
|
||||
*hotdrop = local_par.hotdrop;
|
||||
return lo_ret;
|
||||
}
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) && \
|
||||
LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 34)
|
||||
static bool xtnu_match_run(const struct sk_buff *skb,
|
||||
const struct xt_match_param *par)
|
||||
{
|
||||
struct xtnu_match *nm = xtcompat_numatch(par->match);
|
||||
struct xt_action_param local_par;
|
||||
bool ret;
|
||||
|
||||
local_par.in = par->in;
|
||||
local_par.out = par->out;
|
||||
local_par.match = par->match;
|
||||
local_par.matchinfo = par->matchinfo;
|
||||
local_par.fragoff = par->fragoff;
|
||||
local_par.thoff = par->thoff;
|
||||
local_par.hotdrop = false;
|
||||
local_par.family = par->family;
|
||||
|
||||
if (nm == NULL || nm->match == NULL)
|
||||
return false;
|
||||
ret = nm->match(skb, &local_par);
|
||||
*par->hotdrop = local_par.hotdrop;
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
|
||||
static int xtnu_match_check(const char *table, const void *entry,
|
||||
@@ -81,7 +110,24 @@ static bool xtnu_match_check(const char *table, const void *entry,
|
||||
return false;
|
||||
if (nm->checkentry == NULL)
|
||||
return true;
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23)
|
||||
return nm->checkentry(&local_par);
|
||||
#else
|
||||
return nm->checkentry(&local_par) == 0;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) && \
|
||||
LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 34)
|
||||
static bool xtnu_match_check(const struct xt_mtchk_param *par)
|
||||
{
|
||||
struct xtnu_match *nm = xtcompat_numatch(par->match);
|
||||
|
||||
if (nm == NULL)
|
||||
return false;
|
||||
if (nm->checkentry == NULL)
|
||||
return true;
|
||||
return nm->checkentry(par) == 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -105,7 +151,7 @@ static void xtnu_match_destroy(const struct xt_match *cm, void *matchinfo)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 34)
|
||||
int xtnu_register_match(struct xtnu_match *nt)
|
||||
{
|
||||
struct xt_match *ct;
|
||||
@@ -127,9 +173,19 @@ int xtnu_register_match(struct xtnu_match *nt)
|
||||
ct->table = (char *)nt->table;
|
||||
ct->hooks = nt->hooks;
|
||||
ct->proto = nt->proto;
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
ct->match = xtnu_match_run;
|
||||
ct->checkentry = xtnu_match_check;
|
||||
ct->destroy = xtnu_match_destroy;
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 34)
|
||||
ct->match = xtnu_match_run;
|
||||
ct->checkentry = xtnu_match_check;
|
||||
ct->destroy = nt->destroy;
|
||||
#else
|
||||
ct->match = nt->match;
|
||||
ct->checkentry = xtnu_match_check;
|
||||
ct->destroy = nt->destroy;
|
||||
#endif
|
||||
ct->matchsize = nt->matchsize;
|
||||
ct->me = nt->me;
|
||||
|
||||
@@ -188,35 +244,55 @@ static unsigned int xtnu_target_run(struct sk_buff **pskb,
|
||||
static unsigned int xtnu_target_run(struct sk_buff *skb,
|
||||
const struct net_device *in, const struct net_device *out,
|
||||
unsigned int hooknum, const struct xt_target *ct, const void *targinfo)
|
||||
#else
|
||||
static unsigned int
|
||||
xtnu_target_run(struct sk_buff *skb, const struct xt_target_param *par)
|
||||
#endif
|
||||
{
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
{
|
||||
struct xtnu_target *nt = xtcompat_nutarget(ct);
|
||||
struct xt_target_param local_par = {
|
||||
.in = in,
|
||||
.out = out,
|
||||
.hooknum = hooknum,
|
||||
.target = ct,
|
||||
.targinfo = targinfo,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
};
|
||||
#else
|
||||
struct xtnu_target *nt = xtcompat_nutarget(par->target);
|
||||
#endif
|
||||
struct xt_action_param local_par;
|
||||
|
||||
local_par.in = in;
|
||||
local_par.out = out;
|
||||
local_par.hooknum = hooknum;
|
||||
local_par.target = ct;
|
||||
local_par.targinfo = targinfo;
|
||||
local_par.family = NFPROTO_UNSPEC;
|
||||
|
||||
if (nt != NULL && nt->target != NULL)
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
|
||||
return nt->target(pskb, &local_par);
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
return nt->target(&skb, &local_par);
|
||||
#else
|
||||
return nt->target(&skb, par);
|
||||
#endif
|
||||
return XT_CONTINUE;
|
||||
}
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) && \
|
||||
LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 34)
|
||||
static unsigned int
|
||||
xtnu_target_run(struct sk_buff *skb, const struct xt_target_param *par)
|
||||
{
|
||||
struct xtnu_target *nt = xtcompat_nutarget(par->target);
|
||||
struct xt_action_param local_par;
|
||||
|
||||
local_par.in = par->in;
|
||||
local_par.out = par->out;
|
||||
local_par.hooknum = par->hooknum;
|
||||
local_par.target = par->target;
|
||||
local_par.targinfo = par->targinfo;
|
||||
local_par.family = par->family;
|
||||
|
||||
return nt->target(&skb, &local_par);
|
||||
}
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
|
||||
static unsigned int
|
||||
xtnu_target_run(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
{
|
||||
struct xtnu_target *nt = xtcompat_nutarget(par->target);
|
||||
|
||||
return nt->target(&skb, par);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
|
||||
static int xtnu_target_check(const char *table, const void *entry,
|
||||
@@ -246,7 +322,25 @@ static bool xtnu_target_check(const char *table, const void *entry,
|
||||
if (nt->checkentry == NULL)
|
||||
/* this is valid, just like if there was no function */
|
||||
return true;
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23)
|
||||
return nt->checkentry(&local_par);
|
||||
#else
|
||||
return nt->checkentry(&local_par) == 0;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) && \
|
||||
LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 34)
|
||||
static bool xtnu_target_check(const struct xt_tgchk_param *par)
|
||||
{
|
||||
struct xtnu_target *nt = xtcompat_nutarget(par->target);
|
||||
|
||||
if (nt == NULL)
|
||||
return false;
|
||||
if (nt->checkentry == NULL)
|
||||
return true;
|
||||
return nt->checkentry(par) == 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -295,6 +389,9 @@ int xtnu_register_target(struct xtnu_target *nt)
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
ct->checkentry = xtnu_target_check;
|
||||
ct->destroy = xtnu_target_destroy;
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 34)
|
||||
ct->checkentry = xtnu_target_check;
|
||||
ct->destroy = nt->destroy;
|
||||
#else
|
||||
ct->checkentry = nt->checkentry;
|
||||
ct->destroy = nt->destroy;
|
||||
@@ -509,4 +606,18 @@ int xtnu_skb_linearize(struct sk_buff *skb)
|
||||
EXPORT_SYMBOL_GPL(xtnu_skb_linearize);
|
||||
#endif
|
||||
|
||||
void *HX_memmem(const void *space, size_t spacesize,
|
||||
const void *point, size_t pointsize)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (pointsize > spacesize)
|
||||
return NULL;
|
||||
for (i = 0; i <= spacesize - pointsize; ++i)
|
||||
if (memcmp(space + i, point, pointsize) == 0)
|
||||
return (void *)space + i;
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(HX_memmem);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
# define init_net__proc_net init_net.proc_net
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 34)
|
||||
# define xt_match xtnu_match
|
||||
# define xt_register_match xtnu_register_match
|
||||
# define xt_unregister_match xtnu_unregister_match
|
||||
@@ -78,6 +78,26 @@
|
||||
# define inet_proto_csum_replace4 xtnu_proto_csum_replace4
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)
|
||||
# define ipt_unregister_table(tbl) ipt_unregister_table(&init_net, (tbl))
|
||||
# define ip6t_unregister_table(tbl) ip6t_unregister_table(&init_net, (tbl))
|
||||
#else
|
||||
# define ipt_unregister_table(tbl) ipt_unregister_table(tbl)
|
||||
# define ip6t_unregister_table(tbl) ip6t_unregister_table(tbl)
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
|
||||
# define rt_dst(rt) (&(rt)->dst)
|
||||
#else
|
||||
# define rt_dst(rt) (&(rt)->u.dst)
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
|
||||
# define nf_nat_ipv4_multi_range_compat nf_nat_multi_range_compat
|
||||
# define nf_nat_ipv4_range nf_nat_range
|
||||
# define NF_NAT_RANGE_MAP_IPS IP_NAT_RANGE_MAP_IPS
|
||||
#endif
|
||||
|
||||
#if !defined(NIP6) && !defined(NIP6_FMT)
|
||||
# define NIP6(addr) \
|
||||
ntohs((addr).s6_addr16[0]), \
|
||||
|
||||
@@ -32,16 +32,6 @@ enum {
|
||||
NFPROTO_NUMPROTO,
|
||||
};
|
||||
|
||||
struct xt_match_param {
|
||||
const struct net_device *in, *out;
|
||||
const struct xt_match *match;
|
||||
const void *matchinfo;
|
||||
int fragoff;
|
||||
unsigned int thoff;
|
||||
bool *hotdrop;
|
||||
u_int8_t family;
|
||||
};
|
||||
|
||||
struct xt_mtchk_param {
|
||||
const char *table;
|
||||
const void *entryinfo;
|
||||
@@ -81,33 +71,52 @@ struct xt_tgdtor_param {
|
||||
};
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 34)
|
||||
struct xt_action_param {
|
||||
union {
|
||||
const struct xt_match *match;
|
||||
const struct xt_target *target;
|
||||
};
|
||||
union {
|
||||
const void *matchinfo, *targinfo;
|
||||
};
|
||||
const struct net_device *in, *out;
|
||||
int fragoff;
|
||||
unsigned int thoff, hooknum;
|
||||
u_int8_t family;
|
||||
bool hotdrop;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct xtnu_match {
|
||||
struct list_head list;
|
||||
char name[XT_FUNCTION_MAXNAMELEN - 1 - sizeof(void *)];
|
||||
bool (*match)(const struct sk_buff *, const struct xt_match_param *);
|
||||
bool (*checkentry)(const struct xt_mtchk_param *);
|
||||
/*
|
||||
* Making it smaller by sizeof(void *) on purpose to catch
|
||||
* lossy translation, if any.
|
||||
*/
|
||||
char name[sizeof(((struct xt_match *)NULL)->name) - 1 - sizeof(void *)];
|
||||
uint8_t revision;
|
||||
bool (*match)(const struct sk_buff *, struct xt_action_param *);
|
||||
int (*checkentry)(const struct xt_mtchk_param *);
|
||||
void (*destroy)(const struct xt_mtdtor_param *);
|
||||
struct module *me;
|
||||
const char *table;
|
||||
unsigned int matchsize, hooks;
|
||||
unsigned short proto, family;
|
||||
uint8_t revision;
|
||||
|
||||
void *__compat_match;
|
||||
};
|
||||
|
||||
struct xtnu_target {
|
||||
struct list_head list;
|
||||
char name[XT_FUNCTION_MAXNAMELEN - 1 - sizeof(void *)];
|
||||
char name[sizeof(((struct xt_target *)NULL)->name) - 1 - sizeof(void *)];
|
||||
uint8_t revision;
|
||||
unsigned int (*target)(struct sk_buff **,
|
||||
const struct xt_target_param *);
|
||||
bool (*checkentry)(const struct xt_tgchk_param *);
|
||||
const struct xt_action_param *);
|
||||
int (*checkentry)(const struct xt_tgchk_param *);
|
||||
void (*destroy)(const struct xt_tgdtor_param *);
|
||||
struct module *me;
|
||||
const char *table;
|
||||
unsigned int targetsize, hooks;
|
||||
unsigned short proto, family;
|
||||
uint8_t revision;
|
||||
|
||||
void *__compat_target;
|
||||
};
|
||||
@@ -154,4 +163,6 @@ extern void xtnu_proto_csum_replace4(__u16 __bitwise *, struct sk_buff *,
|
||||
__be32, __be32, bool);
|
||||
extern int xtnu_skb_linearize(struct sk_buff *);
|
||||
|
||||
extern void *HX_memmem(const void *, size_t, const void *, size_t);
|
||||
|
||||
#endif /* _COMPAT_XTNU_H */
|
||||
|
||||
@@ -69,7 +69,9 @@ static int __init rawpost6_table_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 29)
|
||||
rwlock_init(&rawpost6_itable.lock);
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
|
||||
rawpost6_ptable = ip6t_register_table(&init_net, &rawpost6_itable,
|
||||
&rawpost6_initial.repl);
|
||||
|
||||
1
extensions/ipset-6/.gitignore
vendored
Normal file
1
extensions/ipset-6/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/ipset
|
||||
11
extensions/ipset-6/Kbuild
Normal file
11
extensions/ipset-6/Kbuild
Normal file
@@ -0,0 +1,11 @@
|
||||
# -*- Makefile -*-
|
||||
|
||||
obj-m += xt_set.o
|
||||
obj-m += ip_set.o ip_set_bitmap_ip.o ip_set_bitmap_ipmac.o
|
||||
obj-m += ip_set_bitmap_port.o ip_set_hash_ip.o ip_set_hash_ipport.o
|
||||
obj-m += ip_set_hash_ipportip.o ip_set_hash_ipportnet.o ip_set_hash_net.o
|
||||
obj-m += ip_set_hash_netiface.o ip_set_hash_netport.o ip_set_list_set.o
|
||||
|
||||
ip_set-y := ip_set_core.o ip_set_getport.o pfxlen.o
|
||||
|
||||
EXTRA_CFLAGS += -DLCONFIG_IP_SET_MAX=256
|
||||
25
extensions/ipset-6/Makefile.am
Normal file
25
extensions/ipset-6/Makefile.am
Normal file
@@ -0,0 +1,25 @@
|
||||
# -*- Makefile -*-
|
||||
|
||||
AM_CPPFLAGS = -I${srcdir}/include -DNDEBUG
|
||||
AM_CFLAGS = ${regular_CFLAGS} ${libmnl_CFLAGS}
|
||||
|
||||
include ../../Makefile.extra
|
||||
|
||||
lib_LTLIBRARIES = libipset.la
|
||||
libipset_la_SOURCES = libipset/data.c libipset/icmp.c libipset/icmpv6.c \
|
||||
libipset/mnl.c libipset/parse.c libipset/print.c \
|
||||
libipset/session.c libipset/types.c libipset/errcode.c
|
||||
libipset_la_LIBADD = ${libmnl_LIBS}
|
||||
libipset_la_LDFLAGS = -version-info 1:0:0
|
||||
|
||||
sbin_PROGRAMS = ipset
|
||||
ipset_SOURCES = src/ipset.c src/ui.c src/ipset_bitmap_ip.c \
|
||||
src/ipset_bitmap_ipmac.c src/ipset_bitmap_port.c \
|
||||
src/ipset_hash_ip.c src/ipset_hash_ipport.c \
|
||||
src/ipset_hash_ipportip.c src/ipset_hash_ipportnet.c \
|
||||
src/ipset_hash_net.c src/ipset_hash_netiface.c \
|
||||
src/ipset_hash_netport.c \
|
||||
src/ipset_list_set.c
|
||||
ipset_LDADD = libipset.la
|
||||
|
||||
man_MANS = src/ipset.8
|
||||
2
extensions/ipset-6/Mbuild
Normal file
2
extensions/ipset-6/Mbuild
Normal file
@@ -0,0 +1,2 @@
|
||||
# -*- Makefile -*-
|
||||
|
||||
88
extensions/ipset-6/README
Normal file
88
extensions/ipset-6/README
Normal file
@@ -0,0 +1,88 @@
|
||||
This is the ipset source tree. Follow the next steps to install ipset.
|
||||
If you upgrade from an earlier 5.x release, please read the UPGRADE
|
||||
instructions too.
|
||||
|
||||
0. You need the source tree of your kernel (version >= 2.6.34)
|
||||
and it have to be configured with ip6tables support enabled,
|
||||
modules compiled. Please apply the netlink.patch against your kernel
|
||||
tree, which adds the new subsystem identifier for ipset.
|
||||
|
||||
Recompile and install the patched kernel and its modules. Please note,
|
||||
you have to run the patched kernel for ipset to work.
|
||||
|
||||
The ipset source code depends on the libmnl library so the library
|
||||
must be installed. You can download the libmnl library from
|
||||
|
||||
git://git.netfilter.org/libmnl.git
|
||||
|
||||
1. Initialize the compiling environment for ipset. The packages automake,
|
||||
autoconf and libtool are required.
|
||||
|
||||
% ./autogen.sh
|
||||
|
||||
2. Run `./configure` and then compile the ipset binary and the kernel
|
||||
modules.
|
||||
|
||||
Configure parameters can be used to to override the default path
|
||||
to the kernel source tree (/lib/modules/`uname -r`/build),
|
||||
the maximum number of sets (256), the default hash sizes (1024).
|
||||
See `./configure --help`.
|
||||
|
||||
% ./configure
|
||||
% make
|
||||
% make modules
|
||||
|
||||
3. Install the binary and the kernel modules
|
||||
|
||||
# make install
|
||||
# make modules_install
|
||||
|
||||
After installing the modules, you can run the testsuite as well.
|
||||
Please note, several assumptions must be met for the testsuite:
|
||||
|
||||
- no sets defined
|
||||
- iptables/ip6tables rules are not set up
|
||||
- the destination for kernel logs is /var/log/kern.log
|
||||
- the networks 10.255.255.0/24 and 1002:1002:1002:1002::/64
|
||||
are not in use
|
||||
- sendip utility is installed
|
||||
|
||||
# make tests
|
||||
|
||||
4. Cleanup the source tree
|
||||
|
||||
% make clean
|
||||
% make modules_clean
|
||||
|
||||
That's it!
|
||||
|
||||
Read the ipset(8) and iptables(8), ip6tables(8) manpages on how to use
|
||||
ipset and its match and target from iptables.
|
||||
|
||||
Compatibilities and incompatibilities:
|
||||
|
||||
- The ipset 6.x userspace utility contains a backward compatibility
|
||||
interface to support the commandline syntax of ipset 4.x.
|
||||
The commandline syntax of ipset 6.x is fully compatible with 5.x.
|
||||
- The ipset 6.x userspace utility can't talk to the kernel part of ipset 5.x
|
||||
or 4.x.
|
||||
- The ipset 6.x kernel part can't talk to the userspace utility from
|
||||
ipset 5.x or 4.x.
|
||||
- The ipset 6.x kernel part can work together with the set match and SET
|
||||
target from iptables 1.4.7 and below, however if you need the IPv6 support
|
||||
from ipset 6.x, then you have to use iptables 1.4.8 or above.
|
||||
|
||||
The ipset 6.x can interpret the commandline syntax of ipset 4.x, however
|
||||
some internal changes mean different behaviour:
|
||||
|
||||
- The "--matchunset" flag for the macipmap type is ignored and not used
|
||||
anymore.
|
||||
- The "--probes" and "--resize" parameters of the hash types are ignored
|
||||
and not used anymore.
|
||||
- The "--from", "--to" and "--network" parameters of the ipporthash,
|
||||
ipportiphash and ipportnethash types are ignored and not used anymore.
|
||||
- The hash types are not resized when new entries are added by the SET
|
||||
target. If you use a set together with the SET target, create it with
|
||||
the proper size because it won't be resized automatically.
|
||||
- The iptree, iptreemap types are not implemented in ipset 6.x. The types
|
||||
are automatically substituted with the hash:ip type.
|
||||
1
extensions/ipset-6/VERSION.txt
Normal file
1
extensions/ipset-6/VERSION.txt
Normal file
@@ -0,0 +1 @@
|
||||
5.4.1-genl
|
||||
138
extensions/ipset-6/include/libipset/data.h
Normal file
138
extensions/ipset-6/include/libipset/data.h
Normal file
@@ -0,0 +1,138 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_DATA_H
|
||||
#define LIBIPSET_DATA_H
|
||||
|
||||
#include <stdbool.h> /* bool */
|
||||
#include <libipset/nf_inet_addr.h> /* union nf_inet_addr */
|
||||
|
||||
/* Data options */
|
||||
enum ipset_opt {
|
||||
IPSET_OPT_NONE = 0,
|
||||
/* Common ones */
|
||||
IPSET_SETNAME,
|
||||
IPSET_OPT_TYPENAME,
|
||||
IPSET_OPT_FAMILY,
|
||||
/* CADT options */
|
||||
IPSET_OPT_IP,
|
||||
IPSET_OPT_IP_FROM = IPSET_OPT_IP,
|
||||
IPSET_OPT_IP_TO,
|
||||
IPSET_OPT_CIDR,
|
||||
IPSET_OPT_PORT,
|
||||
IPSET_OPT_PORT_FROM = IPSET_OPT_PORT,
|
||||
IPSET_OPT_PORT_TO,
|
||||
IPSET_OPT_TIMEOUT,
|
||||
/* Create-specific options */
|
||||
IPSET_OPT_GC,
|
||||
IPSET_OPT_HASHSIZE,
|
||||
IPSET_OPT_MAXELEM,
|
||||
IPSET_OPT_NETMASK,
|
||||
IPSET_OPT_PROBES,
|
||||
IPSET_OPT_RESIZE,
|
||||
IPSET_OPT_SIZE,
|
||||
/* Create-specific options, filled out by the kernel */
|
||||
IPSET_OPT_ELEMENTS,
|
||||
IPSET_OPT_REFERENCES,
|
||||
IPSET_OPT_MEMSIZE,
|
||||
/* ADT-specific options */
|
||||
IPSET_OPT_ETHER,
|
||||
IPSET_OPT_NAME,
|
||||
IPSET_OPT_NAMEREF,
|
||||
IPSET_OPT_IP2,
|
||||
IPSET_OPT_CIDR2,
|
||||
IPSET_OPT_IP2_TO,
|
||||
IPSET_OPT_PROTO,
|
||||
IPSET_OPT_IFACE,
|
||||
/* Swap/rename to */
|
||||
IPSET_OPT_SETNAME2,
|
||||
/* Flags */
|
||||
IPSET_OPT_EXIST,
|
||||
IPSET_OPT_BEFORE,
|
||||
IPSET_OPT_PHYSDEV,
|
||||
/* Internal options */
|
||||
IPSET_OPT_FLAGS = 48, /* IPSET_FLAG_EXIST| */
|
||||
IPSET_OPT_CADT_FLAGS, /* IPSET_FLAG_BEFORE| */
|
||||
IPSET_OPT_ELEM,
|
||||
IPSET_OPT_TYPE,
|
||||
IPSET_OPT_LINENO,
|
||||
IPSET_OPT_REVISION,
|
||||
IPSET_OPT_REVISION_MIN,
|
||||
IPSET_OPT_MAX,
|
||||
};
|
||||
|
||||
#define IPSET_FLAG(opt) (1LL << (opt))
|
||||
#define IPSET_FLAGS_ALL (~0LL)
|
||||
|
||||
#define IPSET_CREATE_FLAGS \
|
||||
(IPSET_FLAG(IPSET_OPT_FAMILY) \
|
||||
| IPSET_FLAG(IPSET_OPT_TYPENAME)\
|
||||
| IPSET_FLAG(IPSET_OPT_TYPE) \
|
||||
| IPSET_FLAG(IPSET_OPT_IP) \
|
||||
| IPSET_FLAG(IPSET_OPT_IP_TO) \
|
||||
| IPSET_FLAG(IPSET_OPT_CIDR) \
|
||||
| IPSET_FLAG(IPSET_OPT_PORT) \
|
||||
| IPSET_FLAG(IPSET_OPT_PORT_TO) \
|
||||
| IPSET_FLAG(IPSET_OPT_TIMEOUT) \
|
||||
| IPSET_FLAG(IPSET_OPT_GC) \
|
||||
| IPSET_FLAG(IPSET_OPT_HASHSIZE)\
|
||||
| IPSET_FLAG(IPSET_OPT_MAXELEM) \
|
||||
| IPSET_FLAG(IPSET_OPT_NETMASK) \
|
||||
| IPSET_FLAG(IPSET_OPT_PROBES) \
|
||||
| IPSET_FLAG(IPSET_OPT_RESIZE) \
|
||||
| IPSET_FLAG(IPSET_OPT_SIZE))
|
||||
|
||||
#define IPSET_ADT_FLAGS \
|
||||
(IPSET_FLAG(IPSET_OPT_IP) \
|
||||
| IPSET_FLAG(IPSET_OPT_IP_TO) \
|
||||
| IPSET_FLAG(IPSET_OPT_CIDR) \
|
||||
| IPSET_FLAG(IPSET_OPT_PORT) \
|
||||
| IPSET_FLAG(IPSET_OPT_PORT_TO) \
|
||||
| IPSET_FLAG(IPSET_OPT_TIMEOUT) \
|
||||
| IPSET_FLAG(IPSET_OPT_ETHER) \
|
||||
| IPSET_FLAG(IPSET_OPT_NAME) \
|
||||
| IPSET_FLAG(IPSET_OPT_NAMEREF) \
|
||||
| IPSET_FLAG(IPSET_OPT_IP2) \
|
||||
| IPSET_FLAG(IPSET_OPT_CIDR2) \
|
||||
| IPSET_FLAG(IPSET_OPT_PROTO) \
|
||||
| IPSET_FLAG(IPSET_OPT_IFACE) \
|
||||
| IPSET_FLAG(IPSET_OPT_CADT_FLAGS)\
|
||||
| IPSET_FLAG(IPSET_OPT_BEFORE) \
|
||||
| IPSET_FLAG(IPSET_OPT_PHYSDEV))
|
||||
|
||||
struct ipset_data;
|
||||
|
||||
extern void ipset_strlcpy(char *dst, const char *src, size_t len);
|
||||
extern bool ipset_data_flags_test(const struct ipset_data *data,
|
||||
uint64_t flags);
|
||||
extern void ipset_data_flags_set(struct ipset_data *data, uint64_t flags);
|
||||
extern void ipset_data_flags_unset(struct ipset_data *data, uint64_t flags);
|
||||
extern bool ipset_data_ignored(struct ipset_data *data, enum ipset_opt opt);
|
||||
|
||||
extern int ipset_data_set(struct ipset_data *data, enum ipset_opt opt,
|
||||
const void *value);
|
||||
extern const void *ipset_data_get(const struct ipset_data *data,
|
||||
enum ipset_opt opt);
|
||||
|
||||
static inline bool
|
||||
ipset_data_test(const struct ipset_data *data, enum ipset_opt opt)
|
||||
{
|
||||
return ipset_data_flags_test(data, IPSET_FLAG(opt));
|
||||
}
|
||||
|
||||
/* Shortcuts */
|
||||
extern const char *ipset_data_setname(const struct ipset_data *data);
|
||||
extern uint8_t ipset_data_family(const struct ipset_data *data);
|
||||
extern uint8_t ipset_data_cidr(const struct ipset_data *data);
|
||||
extern uint64_t ipset_data_flags(const struct ipset_data *data);
|
||||
|
||||
extern void ipset_data_reset(struct ipset_data *data);
|
||||
extern struct ipset_data *ipset_data_init(void);
|
||||
extern void ipset_data_fini(struct ipset_data *data);
|
||||
|
||||
extern size_t ipset_data_sizeof(enum ipset_opt opt, uint8_t family);
|
||||
|
||||
#endif /* LIBIPSET_DATA_H */
|
||||
33
extensions/ipset-6/include/libipset/debug.h
Normal file
33
extensions/ipset-6/include/libipset/debug.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_DEBUG_H
|
||||
#define LIBIPSET_DEBUG_H
|
||||
|
||||
#ifdef IPSET_DEBUG
|
||||
#include <stdio.h>
|
||||
#include <sys/socket.h>
|
||||
#include <linux/netlink.h>
|
||||
#define D(fmt, args...) \
|
||||
fprintf(stderr, "%s: %s: " fmt "\n", __FILE__, __func__ , ## args)
|
||||
#define IF_D(test, fmt, args...) \
|
||||
if (test) \
|
||||
D(fmt , ## args)
|
||||
|
||||
static inline void
|
||||
dump_nla(struct nlattr *nla[], int maxlen)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < maxlen; i++)
|
||||
D("nla[%u] does%s exist", i, nla[i] ? "" : " NOT");
|
||||
}
|
||||
#else
|
||||
#define D(fmt, args...)
|
||||
#define IF_D(test, fmt, args...)
|
||||
#define dump_nla(nla, maxlen)
|
||||
#endif
|
||||
|
||||
#endif /* LIBIPSET_DEBUG_H */
|
||||
24
extensions/ipset-6/include/libipset/errcode.h
Normal file
24
extensions/ipset-6/include/libipset/errcode.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/* Copyright 2007-2008 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_ERRCODE_H
|
||||
#define LIBIPSET_ERRCODE_H
|
||||
|
||||
#include <libipset/linux_ip_set.h> /* enum ipset_cmd */
|
||||
|
||||
struct ipset_session;
|
||||
|
||||
/* Kernel error code to message table */
|
||||
struct ipset_errcode_table {
|
||||
int errcode; /* error code returned by the kernel */
|
||||
enum ipset_cmd cmd; /* issued command */
|
||||
const char *message; /* error message the code translated to */
|
||||
};
|
||||
|
||||
extern int ipset_errcode(struct ipset_session *session, enum ipset_cmd cmd,
|
||||
int errcode);
|
||||
|
||||
#endif /* LIBIPSET_ERRCODE_H */
|
||||
16
extensions/ipset-6/include/libipset/icmp.h
Normal file
16
extensions/ipset-6/include/libipset/icmp.h
Normal file
@@ -0,0 +1,16 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_ICMP_H
|
||||
#define LIBIPSET_ICMP_H
|
||||
|
||||
#include <stdint.h> /* uintxx_t */
|
||||
|
||||
extern const char *id_to_icmp(uint8_t id);
|
||||
extern const char *icmp_to_name(uint8_t type, uint8_t code);
|
||||
extern int name_to_icmp(const char *str, uint16_t *typecode);
|
||||
|
||||
#endif /* LIBIPSET_ICMP_H */
|
||||
16
extensions/ipset-6/include/libipset/icmpv6.h
Normal file
16
extensions/ipset-6/include/libipset/icmpv6.h
Normal file
@@ -0,0 +1,16 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_ICMPV6_H
|
||||
#define LIBIPSET_ICMPV6_H
|
||||
|
||||
#include <stdint.h> /* uintxx_t */
|
||||
|
||||
extern const char *id_to_icmpv6(uint8_t id);
|
||||
extern const char *icmpv6_to_name(uint8_t type, uint8_t code);
|
||||
extern int name_to_icmpv6(const char *str, uint16_t *typecode);
|
||||
|
||||
#endif /* LIBIPSET_ICMPV6_H */
|
||||
199
extensions/ipset-6/include/libipset/linux_ip_set.h
Normal file
199
extensions/ipset-6/include/libipset/linux_ip_set.h
Normal file
@@ -0,0 +1,199 @@
|
||||
#ifndef _IP_SET_H
|
||||
#define _IP_SET_H
|
||||
|
||||
/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
|
||||
* Patrick Schaaf <bof@bof.de>
|
||||
* Martin Josefsson <gandalf@wlug.westbo.se>
|
||||
* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/* The protocol version */
|
||||
#define IPSET_PROTOCOL 0x60
|
||||
|
||||
/* The max length of strings including NUL: set and type identifiers */
|
||||
#define IPSET_MAXNAMELEN 32
|
||||
|
||||
/* Message types and commands */
|
||||
enum ipset_cmd {
|
||||
IPSET_CMD_NONE,
|
||||
IPSET_CMD_PROTOCOL, /* 1: Return protocol version */
|
||||
IPSET_CMD_CREATE, /* 2: Create a new (empty) set */
|
||||
IPSET_CMD_DESTROY, /* 3: Destroy a (empty) set */
|
||||
IPSET_CMD_FLUSH, /* 4: Remove all elements from a set */
|
||||
IPSET_CMD_RENAME, /* 5: Rename a set */
|
||||
IPSET_CMD_SWAP, /* 6: Swap two sets */
|
||||
IPSET_CMD_LIST, /* 7: List sets */
|
||||
IPSET_CMD_SAVE, /* 8: Save sets */
|
||||
IPSET_CMD_ADD, /* 9: Add an element to a set */
|
||||
IPSET_CMD_DEL, /* 10: Delete an element from a set */
|
||||
IPSET_CMD_TEST, /* 11: Test an element in a set */
|
||||
IPSET_CMD_HEADER, /* 12: Get set header data only */
|
||||
IPSET_CMD_TYPE, /* 13: Get set type */
|
||||
IPSET_MSG_MAX, /* Netlink message commands */
|
||||
|
||||
/* Commands in userspace: */
|
||||
IPSET_CMD_RESTORE = IPSET_MSG_MAX, /* 14: Enter restore mode */
|
||||
IPSET_CMD_HELP, /* 15: Get help */
|
||||
IPSET_CMD_VERSION, /* 16: Get program version */
|
||||
IPSET_CMD_QUIT, /* 17: Quit from interactive mode */
|
||||
|
||||
IPSET_CMD_MAX,
|
||||
|
||||
IPSET_CMD_COMMIT = IPSET_CMD_MAX, /* 18: Commit buffered commands */
|
||||
};
|
||||
|
||||
/* Attributes at command level */
|
||||
enum {
|
||||
IPSET_ATTR_UNSPEC,
|
||||
IPSET_ATTR_PROTOCOL, /* 1: Protocol version */
|
||||
IPSET_ATTR_SETNAME, /* 2: Name of the set */
|
||||
IPSET_ATTR_TYPENAME, /* 3: Typename */
|
||||
IPSET_ATTR_SETNAME2 = IPSET_ATTR_TYPENAME, /* Setname at rename/swap */
|
||||
IPSET_ATTR_REVISION, /* 4: Settype revision */
|
||||
IPSET_ATTR_FAMILY, /* 5: Settype family */
|
||||
IPSET_ATTR_FLAGS, /* 6: Flags at command level */
|
||||
IPSET_ATTR_DATA, /* 7: Nested attributes */
|
||||
IPSET_ATTR_ADT, /* 8: Multiple data containers */
|
||||
IPSET_ATTR_LINENO, /* 9: Restore lineno */
|
||||
IPSET_ATTR_PROTOCOL_MIN, /* 10: Minimal supported version number */
|
||||
IPSET_ATTR_REVISION_MIN = IPSET_ATTR_PROTOCOL_MIN, /* type rev min */
|
||||
__IPSET_ATTR_CMD_MAX,
|
||||
};
|
||||
#define IPSET_ATTR_CMD_MAX (__IPSET_ATTR_CMD_MAX - 1)
|
||||
|
||||
/* CADT specific attributes */
|
||||
enum {
|
||||
IPSET_ATTR_IP = IPSET_ATTR_UNSPEC + 1,
|
||||
IPSET_ATTR_IP_FROM = IPSET_ATTR_IP,
|
||||
IPSET_ATTR_IP_TO, /* 2 */
|
||||
IPSET_ATTR_CIDR, /* 3 */
|
||||
IPSET_ATTR_PORT, /* 4 */
|
||||
IPSET_ATTR_PORT_FROM = IPSET_ATTR_PORT,
|
||||
IPSET_ATTR_PORT_TO, /* 5 */
|
||||
IPSET_ATTR_TIMEOUT, /* 6 */
|
||||
IPSET_ATTR_PROTO, /* 7 */
|
||||
IPSET_ATTR_CADT_FLAGS, /* 8 */
|
||||
IPSET_ATTR_CADT_LINENO = IPSET_ATTR_LINENO, /* 9 */
|
||||
/* Reserve empty slots */
|
||||
IPSET_ATTR_CADT_MAX = 16,
|
||||
/* Create-only specific attributes */
|
||||
IPSET_ATTR_GC,
|
||||
IPSET_ATTR_HASHSIZE,
|
||||
IPSET_ATTR_MAXELEM,
|
||||
IPSET_ATTR_NETMASK,
|
||||
IPSET_ATTR_PROBES,
|
||||
IPSET_ATTR_RESIZE,
|
||||
IPSET_ATTR_SIZE,
|
||||
/* Kernel-only */
|
||||
IPSET_ATTR_ELEMENTS,
|
||||
IPSET_ATTR_REFERENCES,
|
||||
IPSET_ATTR_MEMSIZE,
|
||||
|
||||
__IPSET_ATTR_CREATE_MAX,
|
||||
};
|
||||
#define IPSET_ATTR_CREATE_MAX (__IPSET_ATTR_CREATE_MAX - 1)
|
||||
|
||||
/* ADT specific attributes */
|
||||
enum {
|
||||
IPSET_ATTR_ETHER = IPSET_ATTR_CADT_MAX + 1,
|
||||
IPSET_ATTR_NAME,
|
||||
IPSET_ATTR_NAMEREF,
|
||||
IPSET_ATTR_IP2,
|
||||
IPSET_ATTR_CIDR2,
|
||||
IPSET_ATTR_IP2_TO,
|
||||
IPSET_ATTR_IFACE,
|
||||
__IPSET_ATTR_ADT_MAX,
|
||||
};
|
||||
#define IPSET_ATTR_ADT_MAX (__IPSET_ATTR_ADT_MAX - 1)
|
||||
|
||||
/* IP specific attributes */
|
||||
enum {
|
||||
IPSET_ATTR_IPADDR_IPV4 = IPSET_ATTR_UNSPEC + 1,
|
||||
IPSET_ATTR_IPADDR_IPV6,
|
||||
__IPSET_ATTR_IPADDR_MAX,
|
||||
};
|
||||
#define IPSET_ATTR_IPADDR_MAX (__IPSET_ATTR_IPADDR_MAX - 1)
|
||||
|
||||
/* Error codes */
|
||||
enum ipset_errno {
|
||||
IPSET_ERR_PRIVATE = 4096,
|
||||
IPSET_ERR_PROTOCOL,
|
||||
IPSET_ERR_FIND_TYPE,
|
||||
IPSET_ERR_MAX_SETS,
|
||||
IPSET_ERR_BUSY,
|
||||
IPSET_ERR_EXIST_SETNAME2,
|
||||
IPSET_ERR_TYPE_MISMATCH,
|
||||
IPSET_ERR_EXIST,
|
||||
IPSET_ERR_INVALID_CIDR,
|
||||
IPSET_ERR_INVALID_NETMASK,
|
||||
IPSET_ERR_INVALID_FAMILY,
|
||||
IPSET_ERR_TIMEOUT,
|
||||
IPSET_ERR_REFERENCED,
|
||||
IPSET_ERR_IPADDR_IPV4,
|
||||
IPSET_ERR_IPADDR_IPV6,
|
||||
|
||||
/* Type specific error codes */
|
||||
IPSET_ERR_TYPE_SPECIFIC = 4352,
|
||||
};
|
||||
|
||||
/* Flags at command level */
|
||||
enum ipset_cmd_flags {
|
||||
IPSET_FLAG_BIT_EXIST = 0,
|
||||
IPSET_FLAG_EXIST = (1 << IPSET_FLAG_BIT_EXIST),
|
||||
IPSET_FLAG_BIT_LIST_SETNAME = 1,
|
||||
IPSET_FLAG_LIST_SETNAME = (1 << IPSET_FLAG_BIT_LIST_SETNAME),
|
||||
IPSET_FLAG_BIT_LIST_HEADER = 2,
|
||||
IPSET_FLAG_LIST_HEADER = (1 << IPSET_FLAG_BIT_LIST_HEADER),
|
||||
};
|
||||
|
||||
/* Flags at CADT attribute level */
|
||||
enum ipset_cadt_flags {
|
||||
IPSET_FLAG_BIT_BEFORE = 0,
|
||||
IPSET_FLAG_BEFORE = (1 << IPSET_FLAG_BIT_BEFORE),
|
||||
IPSET_FLAG_BIT_PHYSDEV = 1,
|
||||
IPSET_FLAG_PHYSDEV = (1 << IPSET_FLAG_BIT_PHYSDEV),
|
||||
};
|
||||
|
||||
/* Commands with settype-specific attributes */
|
||||
enum ipset_adt {
|
||||
IPSET_ADD,
|
||||
IPSET_DEL,
|
||||
IPSET_TEST,
|
||||
IPSET_ADT_MAX,
|
||||
IPSET_CREATE = IPSET_ADT_MAX,
|
||||
IPSET_CADT_MAX,
|
||||
};
|
||||
|
||||
/* Sets are identified by an index in kernel space. Tweak with ip_set_id_t
|
||||
* and IPSET_INVALID_ID if you want to increase the max number of sets.
|
||||
*/
|
||||
typedef __u16 ip_set_id_t;
|
||||
|
||||
#define IPSET_INVALID_ID 65535
|
||||
|
||||
enum ip_set_dim {
|
||||
IPSET_DIM_ZERO = 0,
|
||||
IPSET_DIM_ONE,
|
||||
IPSET_DIM_TWO,
|
||||
IPSET_DIM_THREE,
|
||||
/* Max dimension in elements.
|
||||
* If changed, new revision of iptables match/target is required.
|
||||
*/
|
||||
IPSET_DIM_MAX = 6,
|
||||
};
|
||||
|
||||
/* Option flags for kernel operations */
|
||||
enum ip_set_kopt {
|
||||
IPSET_INV_MATCH = (1 << IPSET_DIM_ZERO),
|
||||
IPSET_DIM_ONE_SRC = (1 << IPSET_DIM_ONE),
|
||||
IPSET_DIM_TWO_SRC = (1 << IPSET_DIM_TWO),
|
||||
IPSET_DIM_THREE_SRC = (1 << IPSET_DIM_THREE),
|
||||
};
|
||||
|
||||
#endif /* __IP_SET_H */
|
||||
12
extensions/ipset-6/include/libipset/linux_ip_set_bitmap.h
Normal file
12
extensions/ipset-6/include/libipset/linux_ip_set_bitmap.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef __IP_SET_BITMAP_H
|
||||
#define __IP_SET_BITMAP_H
|
||||
|
||||
/* Bitmap type specific error codes */
|
||||
enum {
|
||||
/* The element is out of the range of the set */
|
||||
IPSET_ERR_BITMAP_RANGE = IPSET_ERR_TYPE_SPECIFIC,
|
||||
/* The range exceeds the size limit of the set type */
|
||||
IPSET_ERR_BITMAP_RANGE_SIZE,
|
||||
};
|
||||
|
||||
#endif /* __IP_SET_BITMAP_H */
|
||||
20
extensions/ipset-6/include/libipset/linux_ip_set_hash.h
Normal file
20
extensions/ipset-6/include/libipset/linux_ip_set_hash.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef __IP_SET_HASH_H
|
||||
#define __IP_SET_HASH_H
|
||||
|
||||
/* Hash type specific error codes */
|
||||
enum {
|
||||
/* Hash is full */
|
||||
IPSET_ERR_HASH_FULL = IPSET_ERR_TYPE_SPECIFIC,
|
||||
/* Null-valued element */
|
||||
IPSET_ERR_HASH_ELEM,
|
||||
/* Invalid protocol */
|
||||
IPSET_ERR_INVALID_PROTO,
|
||||
/* Protocol missing but must be specified */
|
||||
IPSET_ERR_MISSING_PROTO,
|
||||
/* Range not supported */
|
||||
IPSET_ERR_HASH_RANGE_UNSUPPORTED,
|
||||
/* Invalid range */
|
||||
IPSET_ERR_HASH_RANGE,
|
||||
};
|
||||
|
||||
#endif /* __IP_SET_HASH_H */
|
||||
20
extensions/ipset-6/include/libipset/linux_ip_set_list.h
Normal file
20
extensions/ipset-6/include/libipset/linux_ip_set_list.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef __IP_SET_LIST_H
|
||||
#define __IP_SET_LIST_H
|
||||
|
||||
/* List type specific error codes */
|
||||
enum {
|
||||
/* Set name to be added/deleted/tested does not exist. */
|
||||
IPSET_ERR_NAME = IPSET_ERR_TYPE_SPECIFIC,
|
||||
/* list:set type is not permitted to add */
|
||||
IPSET_ERR_LOOP,
|
||||
/* Missing reference set */
|
||||
IPSET_ERR_BEFORE,
|
||||
/* Reference set does not exist */
|
||||
IPSET_ERR_NAMEREF,
|
||||
/* Set is full */
|
||||
IPSET_ERR_LIST_FULL,
|
||||
/* Reference set is not added to the set */
|
||||
IPSET_ERR_REF_EXIST,
|
||||
};
|
||||
|
||||
#endif /* __IP_SET_LIST_H */
|
||||
29
extensions/ipset-6/include/libipset/mnl.h
Normal file
29
extensions/ipset-6/include/libipset/mnl.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_MNL_H
|
||||
#define LIBIPSET_MNL_H
|
||||
|
||||
#include <stdint.h> /* uintxx_t */
|
||||
#include <libmnl/libmnl.h> /* libmnl backend */
|
||||
|
||||
#include <libipset/transport.h> /* struct ipset_transport */
|
||||
|
||||
#ifndef NFNETLINK_V0
|
||||
#define NFNETLINK_V0 0
|
||||
|
||||
struct nfgenmsg {
|
||||
uint8_t nfgen_family;
|
||||
uint8_t version;
|
||||
uint16_t res_id;
|
||||
};
|
||||
#endif
|
||||
|
||||
extern int ipset_get_nlmsg_type(const struct nlmsghdr *nlh);
|
||||
|
||||
extern const struct ipset_transport ipset_mnl_transport;
|
||||
|
||||
#endif /* LIBIPSET_MNL_H */
|
||||
22
extensions/ipset-6/include/libipset/nf_inet_addr.h
Normal file
22
extensions/ipset-6/include/libipset/nf_inet_addr.h
Normal file
@@ -0,0 +1,22 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_NF_INET_ADDR_H
|
||||
#define LIBIPSET_NF_INET_ADDR_H
|
||||
|
||||
#include <stdint.h> /* uint32_t */
|
||||
#include <netinet/in.h> /* struct in[6]_addr */
|
||||
|
||||
/* The structure to hold IP addresses, same as in linux/netfilter.h */
|
||||
union nf_inet_addr {
|
||||
uint32_t all[4];
|
||||
uint32_t ip;
|
||||
uint32_t ip6[4];
|
||||
struct in_addr in;
|
||||
struct in6_addr in6;
|
||||
};
|
||||
|
||||
#endif /* LIBIPSET_NF_INET_ADDR_H */
|
||||
19
extensions/ipset-6/include/libipset/nfproto.h
Normal file
19
extensions/ipset-6/include/libipset/nfproto.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef LIBIPSET_NFPROTO_H
|
||||
#define LIBIPSET_NFPROTO_H
|
||||
|
||||
/*
|
||||
* The constants to select, same as in linux/netfilter.h.
|
||||
* Like nf_inet_addr.h, this is just here so that we need not to rely on
|
||||
* the presence of a recent-enough netfilter.h.
|
||||
*/
|
||||
enum {
|
||||
NFPROTO_UNSPEC = 0,
|
||||
NFPROTO_IPV4 = 2,
|
||||
NFPROTO_ARP = 3,
|
||||
NFPROTO_BRIDGE = 7,
|
||||
NFPROTO_IPV6 = 10,
|
||||
NFPROTO_DECNET = 12,
|
||||
NFPROTO_NUMPROTO,
|
||||
};
|
||||
|
||||
#endif /* LIBIPSET_NFPROTO_H */
|
||||
101
extensions/ipset-6/include/libipset/parse.h
Normal file
101
extensions/ipset-6/include/libipset/parse.h
Normal file
@@ -0,0 +1,101 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_PARSE_H
|
||||
#define LIBIPSET_PARSE_H
|
||||
|
||||
#include <libipset/data.h> /* enum ipset_opt */
|
||||
|
||||
/* For parsing/printing data */
|
||||
#define IPSET_CIDR_SEPARATOR "/"
|
||||
#define IPSET_RANGE_SEPARATOR "-"
|
||||
#define IPSET_ELEM_SEPARATOR ","
|
||||
#define IPSET_NAME_SEPARATOR ","
|
||||
#define IPSET_PROTO_SEPARATOR ":"
|
||||
|
||||
struct ipset_session;
|
||||
struct ipset_arg;
|
||||
|
||||
typedef int (*ipset_parsefn)(struct ipset_session *s,
|
||||
enum ipset_opt opt, const char *str);
|
||||
|
||||
extern int ipset_parse_ether(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_port(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str,
|
||||
const char *proto);
|
||||
extern int ipset_parse_tcpudp_port(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str,
|
||||
const char *proto);
|
||||
extern int ipset_parse_tcp_port(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_single_tcp_port(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_proto(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_icmp(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_icmpv6(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_proto_port(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_family(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_ip(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_single_ip(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_net(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_range(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_netrange(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_iprange(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_ipnet(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_ip4_single6(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_ip4_net6(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_name(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_before(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_after(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_setname(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_uint32(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_uint8(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_netmask(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_flag(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_typename(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_iface(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_output(struct ipset_session *session,
|
||||
int opt, const char *str);
|
||||
extern int ipset_parse_ignored(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_elem(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_call_parser(struct ipset_session *session,
|
||||
const struct ipset_arg *arg,
|
||||
const char *str);
|
||||
|
||||
/* Compatibility parser functions */
|
||||
extern int ipset_parse_iptimeout(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_name_compat(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
|
||||
#endif /* LIBIPSET_PARSE_H */
|
||||
157
extensions/ipset-6/include/libipset/pfxlen.h
Normal file
157
extensions/ipset-6/include/libipset/pfxlen.h
Normal file
@@ -0,0 +1,157 @@
|
||||
#ifndef _NET_PFXLEN_H
|
||||
#define _NET_PFXLEN_H 1
|
||||
|
||||
#include <asm/byteorder.h>
|
||||
#ifdef HAVE_PFXLEN_H
|
||||
#include <linux/netfilter/pfxlen.h>
|
||||
#else
|
||||
|
||||
#include <libipset/nf_inet_addr.h> /* union nf_inet_addr */
|
||||
|
||||
#define E(a, b, c, d) \
|
||||
{.ip6 = { \
|
||||
__constant_htonl(a), __constant_htonl(b), \
|
||||
__constant_htonl(c), __constant_htonl(d), \
|
||||
} }
|
||||
|
||||
/*
|
||||
* This table works for both IPv4 and IPv6;
|
||||
* just use prefixlen_netmask_map[prefixlength].ip.
|
||||
*/
|
||||
const union nf_inet_addr prefixlen_netmask_map[] = {
|
||||
E(0x00000000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0x80000000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xC0000000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xE0000000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xF0000000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xF8000000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFC000000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFE000000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFF000000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFF800000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFC00000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFE00000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFF00000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFF80000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFC0000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFE0000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFF0000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFF8000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFC000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFE000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFF000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFF800, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFC00, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFE00, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFF00, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFF80, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFC0, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFE0, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFF0, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFF8, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFC, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFE, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0x80000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xC0000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xE0000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xF0000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xF8000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFC000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFE000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFF000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFF800000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFC00000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFE00000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFF00000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFF80000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFC0000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFE0000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFF0000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFF8000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFC000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFE000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFF000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFF800, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFC00, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFE00, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFF00, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFF80, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFC0, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFE0, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFF0, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFF8, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFC, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFE, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0x80000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xC0000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xE0000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xF0000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xF8000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFC000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFE000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFF800000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFC00000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFE00000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFF00000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFF80000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFC0000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFE0000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF0000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF8000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFC000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF800, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFC00, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFE00, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF00, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF80, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFC0, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFE0, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF0, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF8, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFC, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x80000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xC0000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xE0000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xF0000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xF8000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFC000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFE000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF800000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFC00000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFE00000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFF00000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFF80000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFC0000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFE0000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF0000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF8000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFC000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF800),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFC00),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFE00),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF00),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF80),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFC0),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFE0),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF0),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF8),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFC),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF),
|
||||
};
|
||||
#endif /* !HAVE_PFXLEN_H */
|
||||
|
||||
#define PFXLEN(n) prefixlen_netmask_map[n].ip
|
||||
#define PFXLEN6(n) prefixlen_netmask_map[n].ip6
|
||||
|
||||
#endif
|
||||
68
extensions/ipset-6/include/libipset/print.h
Normal file
68
extensions/ipset-6/include/libipset/print.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_PRINT_H
|
||||
#define LIBIPSET_PRINT_H
|
||||
|
||||
#include <libipset/data.h> /* enum ipset_opt */
|
||||
|
||||
typedef int (*ipset_printfn)(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
|
||||
extern int ipset_print_ether(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_family(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_type(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_ip(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_ipaddr(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_number(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_name(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_port(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_iface(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_proto(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_icmp(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_icmpv6(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_proto_port(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_flag(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_elem(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
|
||||
#define ipset_print_portnum ipset_print_number
|
||||
|
||||
extern int ipset_print_data(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
|
||||
#endif /* LIBIPSET_PRINT_H */
|
||||
105
extensions/ipset-6/include/libipset/session.h
Normal file
105
extensions/ipset-6/include/libipset/session.h
Normal file
@@ -0,0 +1,105 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_SESSION_H
|
||||
#define LIBIPSET_SESSION_H
|
||||
|
||||
#include <stdbool.h> /* bool */
|
||||
#include <stdint.h> /* uintxx_t */
|
||||
#include <stdio.h> /* printf */
|
||||
|
||||
#include <libipset/linux_ip_set.h> /* enum ipset_cmd */
|
||||
|
||||
/* Report and output buffer sizes */
|
||||
#define IPSET_ERRORBUFLEN 1024
|
||||
#define IPSET_OUTBUFLEN 8192
|
||||
|
||||
struct ipset_session;
|
||||
struct ipset_data;
|
||||
struct ipset_handle;
|
||||
|
||||
extern struct ipset_data *
|
||||
ipset_session_data(const struct ipset_session *session);
|
||||
extern struct ipset_handle *
|
||||
ipset_session_handle(const struct ipset_session *session);
|
||||
extern const struct ipset_type *
|
||||
ipset_saved_type(const struct ipset_session *session);
|
||||
extern void ipset_session_lineno(struct ipset_session *session,
|
||||
uint32_t lineno);
|
||||
|
||||
enum ipset_err_type {
|
||||
IPSET_ERROR,
|
||||
IPSET_WARNING,
|
||||
};
|
||||
|
||||
extern int ipset_session_report(struct ipset_session *session,
|
||||
enum ipset_err_type type,
|
||||
const char *fmt, ...);
|
||||
|
||||
#define ipset_err(session, fmt, args...) \
|
||||
ipset_session_report(session, IPSET_ERROR, fmt , ## args)
|
||||
|
||||
#define ipset_warn(session, fmt, args...) \
|
||||
ipset_session_report(session, IPSET_WARNING, fmt , ## args)
|
||||
|
||||
#define ipset_errptr(session, fmt, args...) ({ \
|
||||
ipset_session_report(session, IPSET_ERROR, fmt , ## args); \
|
||||
NULL; \
|
||||
})
|
||||
|
||||
extern void ipset_session_report_reset(struct ipset_session *session);
|
||||
extern const char *ipset_session_error(const struct ipset_session *session);
|
||||
extern const char *ipset_session_warning(const struct ipset_session *session);
|
||||
|
||||
#define ipset_session_data_set(session, opt, value) \
|
||||
ipset_data_set(ipset_session_data(session), opt, value)
|
||||
#define ipset_session_data_get(session, opt) \
|
||||
ipset_data_get(ipset_session_data(session), opt)
|
||||
|
||||
/* Environment option flags */
|
||||
enum ipset_envopt {
|
||||
IPSET_ENV_BIT_SORTED = 0,
|
||||
IPSET_ENV_SORTED = (1 << IPSET_ENV_BIT_SORTED),
|
||||
IPSET_ENV_BIT_QUIET = 1,
|
||||
IPSET_ENV_QUIET = (1 << IPSET_ENV_BIT_QUIET),
|
||||
IPSET_ENV_BIT_RESOLVE = 2,
|
||||
IPSET_ENV_RESOLVE = (1 << IPSET_ENV_BIT_RESOLVE),
|
||||
IPSET_ENV_BIT_EXIST = 3,
|
||||
IPSET_ENV_EXIST = (1 << IPSET_ENV_BIT_EXIST),
|
||||
IPSET_ENV_BIT_LIST_SETNAME = 4,
|
||||
IPSET_ENV_LIST_SETNAME = (1 << IPSET_ENV_BIT_LIST_SETNAME),
|
||||
IPSET_ENV_BIT_LIST_HEADER = 5,
|
||||
IPSET_ENV_LIST_HEADER = (1 << IPSET_ENV_BIT_LIST_HEADER),
|
||||
};
|
||||
|
||||
extern int ipset_envopt_parse(struct ipset_session *session,
|
||||
int env, const char *str);
|
||||
extern bool ipset_envopt_test(struct ipset_session *session,
|
||||
enum ipset_envopt env);
|
||||
|
||||
enum ipset_output_mode {
|
||||
IPSET_LIST_NONE,
|
||||
IPSET_LIST_PLAIN,
|
||||
IPSET_LIST_SAVE,
|
||||
IPSET_LIST_XML,
|
||||
};
|
||||
|
||||
extern int ipset_session_output(struct ipset_session *session,
|
||||
enum ipset_output_mode mode);
|
||||
|
||||
extern int ipset_commit(struct ipset_session *session);
|
||||
extern int ipset_cmd(struct ipset_session *session, enum ipset_cmd cmd,
|
||||
uint32_t lineno);
|
||||
|
||||
typedef int (*ipset_outfn)(const char *fmt, ...)
|
||||
__attribute__ ((format (printf, 1, 2)));
|
||||
|
||||
extern struct ipset_session *ipset_session_init(ipset_outfn outfn);
|
||||
extern int ipset_session_fini(struct ipset_session *session);
|
||||
|
||||
extern void ipset_debug_msg(const char *dir, void *buffer, int len);
|
||||
|
||||
#endif /* LIBIPSET_SESSION_H */
|
||||
27
extensions/ipset-6/include/libipset/transport.h
Normal file
27
extensions/ipset-6/include/libipset/transport.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_TRANSPORT_H
|
||||
#define LIBIPSET_TRANSPORT_H
|
||||
|
||||
#include <stdint.h> /* uintxx_t */
|
||||
#include <linux/netlink.h> /* struct nlmsghdr */
|
||||
|
||||
#include <libmnl/libmnl.h> /* mnl_cb_t */
|
||||
|
||||
#include <libipset/linux_ip_set.h> /* enum ipset_cmd */
|
||||
|
||||
struct ipset_handle;
|
||||
|
||||
struct ipset_transport {
|
||||
struct ipset_handle * (*init)(mnl_cb_t *cb_ctl, void *data);
|
||||
int (*fini)(struct ipset_handle *handle);
|
||||
void (*fill_hdr)(struct ipset_handle *handle, enum ipset_cmd cmd,
|
||||
void *buffer, size_t len, uint8_t envflags);
|
||||
int (*query)(struct ipset_handle *handle, void *buffer, size_t len);
|
||||
};
|
||||
|
||||
#endif /* LIBIPSET_TRANSPORT_H */
|
||||
109
extensions/ipset-6/include/libipset/types.h
Normal file
109
extensions/ipset-6/include/libipset/types.h
Normal file
@@ -0,0 +1,109 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_TYPES_H
|
||||
#define LIBIPSET_TYPES_H
|
||||
|
||||
#include <stddef.h> /* NULL */
|
||||
#include <stdint.h> /* uintxx_t */
|
||||
|
||||
#include <libipset/data.h> /* enum ipset_opt */
|
||||
#include <libipset/parse.h> /* ipset_parsefn */
|
||||
#include <libipset/print.h> /* ipset_printfn */
|
||||
#include <libipset/linux_ip_set.h> /* IPSET_MAXNAMELEN */
|
||||
#include <libipset/nfproto.h> /* for NFPROTO_ */
|
||||
|
||||
/* Family rules:
|
||||
* - NFPROTO_UNSPEC: type is family-neutral
|
||||
* - NFPROTO_IPV4: type supports IPv4 only
|
||||
* - NFPROTO_IPV6: type supports IPv6 only
|
||||
* Special (userspace) ipset-only extra value:
|
||||
* - NFPROTO_IPSET_IPV46: type supports both IPv4 and IPv6
|
||||
*/
|
||||
enum {
|
||||
NFPROTO_IPSET_IPV46 = 255,
|
||||
};
|
||||
|
||||
/* The maximal type dimension userspace supports */
|
||||
#define IPSET_DIM_UMAX 3
|
||||
|
||||
/* Parser options */
|
||||
enum {
|
||||
IPSET_NO_ARG = -1,
|
||||
IPSET_OPTIONAL_ARG,
|
||||
IPSET_MANDATORY_ARG,
|
||||
IPSET_MANDATORY_ARG2,
|
||||
};
|
||||
|
||||
struct ipset_session;
|
||||
|
||||
/* Parse and print type-specific arguments */
|
||||
struct ipset_arg {
|
||||
const char *name[2]; /* option names */
|
||||
int has_arg; /* mandatory/optional/no arg */
|
||||
enum ipset_opt opt; /* argumentum type */
|
||||
ipset_parsefn parse; /* parser function */
|
||||
ipset_printfn print; /* printing function */
|
||||
};
|
||||
|
||||
/* Type check against the kernel */
|
||||
enum {
|
||||
IPSET_KERNEL_MISMATCH = -1,
|
||||
IPSET_KERNEL_CHECK_NEEDED,
|
||||
IPSET_KERNEL_OK,
|
||||
};
|
||||
|
||||
/* How element parts are parsed */
|
||||
struct ipset_elem {
|
||||
ipset_parsefn parse; /* elem parser function */
|
||||
ipset_printfn print; /* elem print function */
|
||||
enum ipset_opt opt; /* elem option */
|
||||
};
|
||||
|
||||
/* The set types in userspace
|
||||
* we could collapse 'args' and 'mandatory' to two-element lists
|
||||
* but for the readability the full list is supported.
|
||||
*/
|
||||
struct ipset_type {
|
||||
const char *name;
|
||||
uint8_t revision; /* revision number */
|
||||
uint8_t family; /* supported family */
|
||||
uint8_t dimension; /* elem dimension */
|
||||
int8_t kernel_check; /* kernel check */
|
||||
bool last_elem_optional; /* last element optional */
|
||||
struct ipset_elem elem[IPSET_DIM_UMAX]; /* parse elem */
|
||||
ipset_parsefn compat_parse_elem; /* compatibility parser */
|
||||
const struct ipset_arg *args[IPSET_CADT_MAX]; /* create/ADT args besides elem */
|
||||
uint64_t mandatory[IPSET_CADT_MAX]; /* create/ADT mandatory flags */
|
||||
uint64_t full[IPSET_CADT_MAX]; /* full args flags */
|
||||
const char *usage; /* terse usage */
|
||||
void (*usagefn)(void); /* additional usage */
|
||||
|
||||
struct ipset_type *next;
|
||||
const char *alias[]; /* name alias(es) */
|
||||
};
|
||||
|
||||
extern int ipset_cache_add(const char *name, const struct ipset_type *type,
|
||||
uint8_t family);
|
||||
extern int ipset_cache_del(const char *name);
|
||||
extern int ipset_cache_rename(const char *from, const char *to);
|
||||
extern int ipset_cache_swap(const char *from, const char *to);
|
||||
|
||||
extern int ipset_cache_init(void);
|
||||
extern void ipset_cache_fini(void);
|
||||
|
||||
extern const struct ipset_type *
|
||||
ipset_type_get(struct ipset_session *session, enum ipset_cmd cmd);
|
||||
extern const struct ipset_type *
|
||||
ipset_type_check(struct ipset_session *session);
|
||||
|
||||
extern int ipset_type_add(struct ipset_type *type);
|
||||
extern const struct ipset_type *ipset_types(void);
|
||||
extern const char *ipset_typename_resolve(const char *str);
|
||||
extern bool ipset_match_typename(const char *str,
|
||||
const struct ipset_type *t);
|
||||
|
||||
#endif /* LIBIPSET_TYPES_H */
|
||||
44
extensions/ipset-6/include/libipset/ui.h
Normal file
44
extensions/ipset-6/include/libipset/ui.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_UI_H
|
||||
#define LIBIPSET_UI_H
|
||||
|
||||
#include <libipset/linux_ip_set.h> /* enum ipset_cmd */
|
||||
|
||||
/* Commands in userspace */
|
||||
struct ipset_commands {
|
||||
enum ipset_cmd cmd;
|
||||
int has_arg;
|
||||
const char *name[2];
|
||||
const char *help;
|
||||
};
|
||||
|
||||
extern const struct ipset_commands ipset_commands[];
|
||||
|
||||
struct ipset_session;
|
||||
struct ipset_data;
|
||||
|
||||
/* Environment options */
|
||||
struct ipset_envopts {
|
||||
int flag;
|
||||
int has_arg;
|
||||
const char *name[2];
|
||||
const char *help;
|
||||
int (*parse)(struct ipset_session *s, int flag, const char *str);
|
||||
int (*print)(char *buf, unsigned int len,
|
||||
const struct ipset_data *data, int flag, uint8_t env);
|
||||
};
|
||||
|
||||
extern const struct ipset_envopts ipset_envopts[];
|
||||
|
||||
extern bool ipset_match_cmd(const char *arg, const char * const name[]);
|
||||
extern bool ipset_match_option(const char *arg, const char * const name[]);
|
||||
extern bool ipset_match_envopt(const char *arg, const char * const name[]);
|
||||
extern void ipset_shift_argv(int *argc, char *argv[], int from);
|
||||
extern void ipset_port_usage(void);
|
||||
|
||||
#endif /* LIBIPSET_UI_H */
|
||||
50
extensions/ipset-6/include/libipset/utils.h
Normal file
50
extensions/ipset-6/include/libipset/utils.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_UTILS_H
|
||||
#define LIBIPSET_UTILS_H
|
||||
|
||||
#include <string.h> /* strcmp */
|
||||
#include <netinet/in.h> /* struct in[6]_addr */
|
||||
|
||||
/* String equality tests */
|
||||
#define STREQ(a, b) (strcmp(a, b) == 0)
|
||||
#define STRNEQ(a, b, n) (strncmp(a, b, n) == 0)
|
||||
#define STRCASEQ(a, b) (strcasecmp(a, b) == 0)
|
||||
#define STRNCASEQ(a, b, n) (strncasecmp(a, b, n) == 0)
|
||||
|
||||
/* Stringify tokens */
|
||||
#define _STR(c) #c
|
||||
#define STR(c) _STR(c)
|
||||
|
||||
/* Min/max */
|
||||
#define MIN(a, b) (a < b ? a : b)
|
||||
#define MAX(a, b) (a > b ? a : b)
|
||||
|
||||
#define UNUSED __attribute__ ((unused))
|
||||
#ifdef NDEBUG
|
||||
#define ASSERT_UNUSED UNUSED
|
||||
#else
|
||||
#define ASSERT_UNUSED
|
||||
#endif
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
|
||||
#endif
|
||||
|
||||
static inline void
|
||||
in4cpy(struct in_addr *dest, const struct in_addr *src)
|
||||
{
|
||||
dest->s_addr = src->s_addr;
|
||||
}
|
||||
|
||||
static inline void
|
||||
in6cpy(struct in6_addr *dest, const struct in6_addr *src)
|
||||
{
|
||||
memcpy(dest, src, sizeof(struct in6_addr));
|
||||
}
|
||||
|
||||
#endif /* LIBIPSET_UTILS_H */
|
||||
499
extensions/ipset-6/ip_set.h
Normal file
499
extensions/ipset-6/ip_set.h
Normal file
@@ -0,0 +1,499 @@
|
||||
#ifndef _IP_SET_H
|
||||
#define _IP_SET_H
|
||||
|
||||
/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
|
||||
* Patrick Schaaf <bof@bof.de>
|
||||
* Martin Josefsson <gandalf@wlug.westbo.se>
|
||||
* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/netlink.h>
|
||||
|
||||
/* The protocol version */
|
||||
#define IPSET_PROTOCOL 0x60
|
||||
|
||||
/* The max length of strings including NUL: set and type identifiers */
|
||||
#define IPSET_MAXNAMELEN 32
|
||||
|
||||
/* Message types and commands */
|
||||
enum ipset_cmd {
|
||||
IPSET_CMD_NONE,
|
||||
IPSET_CMD_PROTOCOL, /* 1: Return protocol version */
|
||||
IPSET_CMD_CREATE, /* 2: Create a new (empty) set */
|
||||
IPSET_CMD_DESTROY, /* 3: Destroy a (empty) set */
|
||||
IPSET_CMD_FLUSH, /* 4: Remove all elements from a set */
|
||||
IPSET_CMD_RENAME, /* 5: Rename a set */
|
||||
IPSET_CMD_SWAP, /* 6: Swap two sets */
|
||||
IPSET_CMD_LIST, /* 7: List sets */
|
||||
IPSET_CMD_SAVE, /* 8: Save sets */
|
||||
IPSET_CMD_ADD, /* 9: Add an element to a set */
|
||||
IPSET_CMD_DEL, /* 10: Delete an element from a set */
|
||||
IPSET_CMD_TEST, /* 11: Test an element in a set */
|
||||
IPSET_CMD_HEADER, /* 12: Get set header data only */
|
||||
IPSET_CMD_TYPE, /* 13: Get set type */
|
||||
IPSET_MSG_MAX, /* Netlink message commands */
|
||||
|
||||
/* Commands in userspace: */
|
||||
IPSET_CMD_RESTORE = IPSET_MSG_MAX, /* 14: Enter restore mode */
|
||||
IPSET_CMD_HELP, /* 15: Get help */
|
||||
IPSET_CMD_VERSION, /* 16: Get program version */
|
||||
IPSET_CMD_QUIT, /* 17: Quit from interactive mode */
|
||||
|
||||
IPSET_CMD_MAX,
|
||||
|
||||
IPSET_CMD_COMMIT = IPSET_CMD_MAX, /* 18: Commit buffered commands */
|
||||
};
|
||||
|
||||
/* Attributes at command level */
|
||||
enum {
|
||||
IPSET_ATTR_UNSPEC,
|
||||
IPSET_ATTR_PROTOCOL, /* 1: Protocol version */
|
||||
IPSET_ATTR_SETNAME, /* 2: Name of the set */
|
||||
IPSET_ATTR_TYPENAME, /* 3: Typename */
|
||||
IPSET_ATTR_SETNAME2 = IPSET_ATTR_TYPENAME, /* Setname at rename/swap */
|
||||
IPSET_ATTR_REVISION, /* 4: Settype revision */
|
||||
IPSET_ATTR_FAMILY, /* 5: Settype family */
|
||||
IPSET_ATTR_FLAGS, /* 6: Flags at command level */
|
||||
IPSET_ATTR_DATA, /* 7: Nested attributes */
|
||||
IPSET_ATTR_ADT, /* 8: Multiple data containers */
|
||||
IPSET_ATTR_LINENO, /* 9: Restore lineno */
|
||||
IPSET_ATTR_PROTOCOL_MIN, /* 10: Minimal supported version number */
|
||||
IPSET_ATTR_REVISION_MIN = IPSET_ATTR_PROTOCOL_MIN, /* type rev min */
|
||||
__IPSET_ATTR_CMD_MAX,
|
||||
};
|
||||
#define IPSET_ATTR_CMD_MAX (__IPSET_ATTR_CMD_MAX - 1)
|
||||
|
||||
/* CADT specific attributes */
|
||||
enum {
|
||||
IPSET_ATTR_IP = IPSET_ATTR_UNSPEC + 1,
|
||||
IPSET_ATTR_IP_FROM = IPSET_ATTR_IP,
|
||||
IPSET_ATTR_IP_TO, /* 2 */
|
||||
IPSET_ATTR_CIDR, /* 3 */
|
||||
IPSET_ATTR_PORT, /* 4 */
|
||||
IPSET_ATTR_PORT_FROM = IPSET_ATTR_PORT,
|
||||
IPSET_ATTR_PORT_TO, /* 5 */
|
||||
IPSET_ATTR_TIMEOUT, /* 6 */
|
||||
IPSET_ATTR_PROTO, /* 7 */
|
||||
IPSET_ATTR_CADT_FLAGS, /* 8 */
|
||||
IPSET_ATTR_CADT_LINENO = IPSET_ATTR_LINENO, /* 9 */
|
||||
/* Reserve empty slots */
|
||||
IPSET_ATTR_CADT_MAX = 16,
|
||||
/* Create-only specific attributes */
|
||||
IPSET_ATTR_GC,
|
||||
IPSET_ATTR_HASHSIZE,
|
||||
IPSET_ATTR_MAXELEM,
|
||||
IPSET_ATTR_NETMASK,
|
||||
IPSET_ATTR_PROBES,
|
||||
IPSET_ATTR_RESIZE,
|
||||
IPSET_ATTR_SIZE,
|
||||
/* Kernel-only */
|
||||
IPSET_ATTR_ELEMENTS,
|
||||
IPSET_ATTR_REFERENCES,
|
||||
IPSET_ATTR_MEMSIZE,
|
||||
|
||||
__IPSET_ATTR_CREATE_MAX,
|
||||
};
|
||||
#define IPSET_ATTR_CREATE_MAX (__IPSET_ATTR_CREATE_MAX - 1)
|
||||
|
||||
/* ADT specific attributes */
|
||||
enum {
|
||||
IPSET_ATTR_ETHER = IPSET_ATTR_CADT_MAX + 1,
|
||||
IPSET_ATTR_NAME,
|
||||
IPSET_ATTR_NAMEREF,
|
||||
IPSET_ATTR_IP2,
|
||||
IPSET_ATTR_CIDR2,
|
||||
IPSET_ATTR_IP2_TO,
|
||||
IPSET_ATTR_IFACE,
|
||||
__IPSET_ATTR_ADT_MAX,
|
||||
};
|
||||
#define IPSET_ATTR_ADT_MAX (__IPSET_ATTR_ADT_MAX - 1)
|
||||
|
||||
/* IP specific attributes */
|
||||
enum {
|
||||
IPSET_ATTR_IPADDR_IPV4 = IPSET_ATTR_UNSPEC + 1,
|
||||
IPSET_ATTR_IPADDR_IPV6,
|
||||
__IPSET_ATTR_IPADDR_MAX,
|
||||
};
|
||||
#define IPSET_ATTR_IPADDR_MAX (__IPSET_ATTR_IPADDR_MAX - 1)
|
||||
|
||||
/* Error codes */
|
||||
enum ipset_errno {
|
||||
IPSET_ERR_PRIVATE = 4096,
|
||||
IPSET_ERR_PROTOCOL,
|
||||
IPSET_ERR_FIND_TYPE,
|
||||
IPSET_ERR_MAX_SETS,
|
||||
IPSET_ERR_BUSY,
|
||||
IPSET_ERR_EXIST_SETNAME2,
|
||||
IPSET_ERR_TYPE_MISMATCH,
|
||||
IPSET_ERR_EXIST,
|
||||
IPSET_ERR_INVALID_CIDR,
|
||||
IPSET_ERR_INVALID_NETMASK,
|
||||
IPSET_ERR_INVALID_FAMILY,
|
||||
IPSET_ERR_TIMEOUT,
|
||||
IPSET_ERR_REFERENCED,
|
||||
IPSET_ERR_IPADDR_IPV4,
|
||||
IPSET_ERR_IPADDR_IPV6,
|
||||
|
||||
/* Type specific error codes */
|
||||
IPSET_ERR_TYPE_SPECIFIC = 4352,
|
||||
};
|
||||
|
||||
/* Flags at command level */
|
||||
enum ipset_cmd_flags {
|
||||
IPSET_FLAG_BIT_EXIST = 0,
|
||||
IPSET_FLAG_EXIST = (1 << IPSET_FLAG_BIT_EXIST),
|
||||
IPSET_FLAG_BIT_LIST_SETNAME = 1,
|
||||
IPSET_FLAG_LIST_SETNAME = (1 << IPSET_FLAG_BIT_LIST_SETNAME),
|
||||
IPSET_FLAG_BIT_LIST_HEADER = 2,
|
||||
IPSET_FLAG_LIST_HEADER = (1 << IPSET_FLAG_BIT_LIST_HEADER),
|
||||
};
|
||||
|
||||
/* Flags at CADT attribute level */
|
||||
enum ipset_cadt_flags {
|
||||
IPSET_FLAG_BIT_BEFORE = 0,
|
||||
IPSET_FLAG_BEFORE = (1 << IPSET_FLAG_BIT_BEFORE),
|
||||
IPSET_FLAG_BIT_PHYSDEV = 1,
|
||||
IPSET_FLAG_PHYSDEV = (1 << IPSET_FLAG_BIT_PHYSDEV),
|
||||
};
|
||||
|
||||
/* Commands with settype-specific attributes */
|
||||
enum ipset_adt {
|
||||
IPSET_ADD,
|
||||
IPSET_DEL,
|
||||
IPSET_TEST,
|
||||
IPSET_ADT_MAX,
|
||||
IPSET_CREATE = IPSET_ADT_MAX,
|
||||
IPSET_CADT_MAX,
|
||||
};
|
||||
|
||||
/* Sets are identified by an index in kernel space. Tweak with ip_set_id_t
|
||||
* and IPSET_INVALID_ID if you want to increase the max number of sets.
|
||||
*/
|
||||
typedef __u16 ip_set_id_t;
|
||||
|
||||
#define IPSET_INVALID_ID 65535
|
||||
|
||||
enum ip_set_dim {
|
||||
IPSET_DIM_ZERO = 0,
|
||||
IPSET_DIM_ONE,
|
||||
IPSET_DIM_TWO,
|
||||
IPSET_DIM_THREE,
|
||||
/* Max dimension in elements.
|
||||
* If changed, new revision of iptables match/target is required.
|
||||
*/
|
||||
IPSET_DIM_MAX = 6,
|
||||
};
|
||||
|
||||
/* Option flags for kernel operations */
|
||||
enum ip_set_kopt {
|
||||
IPSET_INV_MATCH = (1 << IPSET_DIM_ZERO),
|
||||
IPSET_DIM_ONE_SRC = (1 << IPSET_DIM_ONE),
|
||||
IPSET_DIM_TWO_SRC = (1 << IPSET_DIM_TWO),
|
||||
IPSET_DIM_THREE_SRC = (1 << IPSET_DIM_THREE),
|
||||
};
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#include <linux/ip.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <net/netlink.h>
|
||||
|
||||
/* Set features */
|
||||
enum ip_set_feature {
|
||||
IPSET_TYPE_IP_FLAG = 0,
|
||||
IPSET_TYPE_IP = (1 << IPSET_TYPE_IP_FLAG),
|
||||
IPSET_TYPE_PORT_FLAG = 1,
|
||||
IPSET_TYPE_PORT = (1 << IPSET_TYPE_PORT_FLAG),
|
||||
IPSET_TYPE_MAC_FLAG = 2,
|
||||
IPSET_TYPE_MAC = (1 << IPSET_TYPE_MAC_FLAG),
|
||||
IPSET_TYPE_IP2_FLAG = 3,
|
||||
IPSET_TYPE_IP2 = (1 << IPSET_TYPE_IP2_FLAG),
|
||||
IPSET_TYPE_NAME_FLAG = 4,
|
||||
IPSET_TYPE_NAME = (1 << IPSET_TYPE_NAME_FLAG),
|
||||
IPSET_TYPE_IFACE_FLAG = 5,
|
||||
IPSET_TYPE_IFACE = (1 << IPSET_TYPE_IFACE_FLAG),
|
||||
/* Strictly speaking not a feature, but a flag for dumping:
|
||||
* this settype must be dumped last */
|
||||
IPSET_DUMP_LAST_FLAG = 7,
|
||||
IPSET_DUMP_LAST = (1 << IPSET_DUMP_LAST_FLAG),
|
||||
};
|
||||
|
||||
struct ip_set;
|
||||
|
||||
typedef int (*ipset_adtfn)(struct ip_set *set, void *value,
|
||||
u32 timeout, u32 flags);
|
||||
|
||||
/* Kernel API function options */
|
||||
struct ip_set_adt_opt {
|
||||
u8 family; /* Actual protocol family */
|
||||
u8 dim; /* Dimension of match/target */
|
||||
u8 flags; /* Direction and negation flags */
|
||||
u32 cmdflags; /* Command-like flags */
|
||||
u32 timeout; /* Timeout value */
|
||||
};
|
||||
|
||||
/* Set type, variant-specific part */
|
||||
struct ip_set_type_variant {
|
||||
/* Kernelspace: test/add/del entries
|
||||
* returns negative error code,
|
||||
* zero for no match/success to add/delete
|
||||
* positive for matching element */
|
||||
int (*kadt)(struct ip_set *set, const struct sk_buff * skb,
|
||||
const struct xt_action_param *par,
|
||||
enum ipset_adt adt, const struct ip_set_adt_opt *opt);
|
||||
|
||||
/* Userspace: test/add/del entries
|
||||
* returns negative error code,
|
||||
* zero for no match/success to add/delete
|
||||
* positive for matching element */
|
||||
int (*uadt)(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried);
|
||||
|
||||
/* Low level add/del/test functions */
|
||||
ipset_adtfn adt[IPSET_ADT_MAX];
|
||||
|
||||
/* When adding entries and set is full, try to resize the set */
|
||||
int (*resize)(struct ip_set *set, bool retried);
|
||||
/* Destroy the set */
|
||||
void (*destroy)(struct ip_set *set);
|
||||
/* Flush the elements */
|
||||
void (*flush)(struct ip_set *set);
|
||||
/* Expire entries before listing */
|
||||
void (*expire)(struct ip_set *set);
|
||||
/* List set header data */
|
||||
int (*head)(struct ip_set *set, struct sk_buff *skb);
|
||||
/* List elements */
|
||||
int (*list)(const struct ip_set *set, struct sk_buff *skb,
|
||||
struct netlink_callback *cb);
|
||||
|
||||
/* Return true if "b" set is the same as "a"
|
||||
* according to the create set parameters */
|
||||
bool (*same_set)(const struct ip_set *a, const struct ip_set *b);
|
||||
};
|
||||
|
||||
/* The core set type structure */
|
||||
struct ip_set_type {
|
||||
struct list_head list;
|
||||
|
||||
/* Typename */
|
||||
char name[IPSET_MAXNAMELEN];
|
||||
/* Protocol version */
|
||||
u8 protocol;
|
||||
/* Set features to control swapping */
|
||||
u8 features;
|
||||
/* Set type dimension */
|
||||
u8 dimension;
|
||||
/*
|
||||
* Supported family: may be NFPROTO_UNSPEC for both
|
||||
* NFPROTO_IPV4/NFPROTO_IPV6.
|
||||
*/
|
||||
u8 family;
|
||||
/* Type revisions */
|
||||
u8 revision_min, revision_max;
|
||||
|
||||
/* Create set */
|
||||
int (*create)(struct ip_set *set, struct nlattr *tb[], u32 flags);
|
||||
|
||||
/* Attribute policies */
|
||||
const struct nla_policy create_policy[IPSET_ATTR_CREATE_MAX + 1];
|
||||
const struct nla_policy adt_policy[IPSET_ATTR_ADT_MAX + 1];
|
||||
|
||||
/* Set this to THIS_MODULE if you are a module, otherwise NULL */
|
||||
struct module *me;
|
||||
};
|
||||
|
||||
/* register and unregister set type */
|
||||
extern int ip_set_type_register(struct ip_set_type *set_type);
|
||||
extern void ip_set_type_unregister(struct ip_set_type *set_type);
|
||||
|
||||
/* A generic IP set */
|
||||
struct ip_set {
|
||||
/* The name of the set */
|
||||
char name[IPSET_MAXNAMELEN];
|
||||
/* Lock protecting the set data */
|
||||
rwlock_t lock;
|
||||
/* References to the set */
|
||||
u32 ref;
|
||||
/* The core set type */
|
||||
struct ip_set_type *type;
|
||||
/* The type variant doing the real job */
|
||||
const struct ip_set_type_variant *variant;
|
||||
/* The actual INET family of the set */
|
||||
u8 family;
|
||||
/* The type revision */
|
||||
u8 revision;
|
||||
/* The type specific data */
|
||||
void *data;
|
||||
};
|
||||
|
||||
/* register and unregister set references */
|
||||
extern ip_set_id_t ip_set_get_byname(const char *name, struct ip_set **set);
|
||||
extern void ip_set_put_byindex(ip_set_id_t index);
|
||||
extern const char *ip_set_name_byindex(ip_set_id_t index);
|
||||
extern ip_set_id_t ip_set_nfnl_get(const char *name);
|
||||
extern ip_set_id_t ip_set_nfnl_get_byindex(ip_set_id_t index);
|
||||
extern void ip_set_nfnl_put(ip_set_id_t index);
|
||||
|
||||
/* API for iptables set match, and SET target */
|
||||
|
||||
extern int ip_set_add(ip_set_id_t id, const struct sk_buff *skb,
|
||||
const struct xt_action_param *par,
|
||||
const struct ip_set_adt_opt *opt);
|
||||
extern int ip_set_del(ip_set_id_t id, const struct sk_buff *skb,
|
||||
const struct xt_action_param *par,
|
||||
const struct ip_set_adt_opt *opt);
|
||||
extern int ip_set_test(ip_set_id_t id, const struct sk_buff *skb,
|
||||
const struct xt_action_param *par,
|
||||
const struct ip_set_adt_opt *opt);
|
||||
|
||||
/* Utility functions */
|
||||
extern void *ip_set_alloc(size_t size);
|
||||
extern void ip_set_free(void *members);
|
||||
extern int ip_set_get_ipaddr4(struct nlattr *nla, __be32 *ipaddr);
|
||||
extern int ip_set_get_ipaddr6(struct nlattr *nla, union nf_inet_addr *ipaddr);
|
||||
|
||||
static inline int
|
||||
ip_set_get_hostipaddr4(struct nlattr *nla, u32 *ipaddr)
|
||||
{
|
||||
__be32 ip;
|
||||
int ret = ip_set_get_ipaddr4(nla, &ip);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
*ipaddr = ntohl(ip);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Ignore IPSET_ERR_EXIST errors if asked to do so? */
|
||||
static inline bool
|
||||
ip_set_eexist(int ret, u32 flags)
|
||||
{
|
||||
return ret == -IPSET_ERR_EXIST && (flags & IPSET_FLAG_EXIST);
|
||||
}
|
||||
|
||||
/* Check the NLA_F_NET_BYTEORDER flag */
|
||||
static inline bool
|
||||
ip_set_attr_netorder(struct nlattr *tb[], int type)
|
||||
{
|
||||
return tb[type] && (tb[type]->nla_type & NLA_F_NET_BYTEORDER);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
ip_set_optattr_netorder(struct nlattr *tb[], int type)
|
||||
{
|
||||
return !tb[type] || (tb[type]->nla_type & NLA_F_NET_BYTEORDER);
|
||||
}
|
||||
|
||||
/* Useful converters */
|
||||
static inline u32
|
||||
ip_set_get_h32(const struct nlattr *attr)
|
||||
{
|
||||
return ntohl(nla_get_be32(attr));
|
||||
}
|
||||
|
||||
static inline u16
|
||||
ip_set_get_h16(const struct nlattr *attr)
|
||||
{
|
||||
return ntohs(nla_get_be16(attr));
|
||||
}
|
||||
|
||||
#define ipset_nest_start(skb, attr) nla_nest_start(skb, attr | NLA_F_NESTED)
|
||||
#define ipset_nest_end(skb, start) nla_nest_end(skb, start)
|
||||
|
||||
#ifndef NLA_PUT_NET16
|
||||
#define NLA_PUT_NET16(skb, attrtype, value) \
|
||||
NLA_PUT_BE16(skb, attrtype | NLA_F_NET_BYTEORDER, value)
|
||||
#endif
|
||||
#ifndef NLA_PUT_NET32
|
||||
#define NLA_PUT_NET32(skb, attrtype, value) \
|
||||
NLA_PUT_BE32(skb, attrtype | NLA_F_NET_BYTEORDER, value)
|
||||
#endif
|
||||
#ifndef NLA_PUT_NET64
|
||||
#define NLA_PUT_NET64(skb, attrtype, value) \
|
||||
NLA_PUT_BE64(skb, attrtype | NLA_F_NET_BYTEORDER, value)
|
||||
#endif
|
||||
|
||||
#define NLA_PUT_IPADDR4(skb, type, ipaddr) \
|
||||
do { \
|
||||
struct nlattr *__nested = ipset_nest_start(skb, type); \
|
||||
\
|
||||
if (!__nested) \
|
||||
goto nla_put_failure; \
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_IPADDR_IPV4, ipaddr); \
|
||||
ipset_nest_end(skb, __nested); \
|
||||
} while (0)
|
||||
|
||||
#define NLA_PUT_IPADDR6(skb, type, ipaddrptr) \
|
||||
do { \
|
||||
struct nlattr *__nested = ipset_nest_start(skb, type); \
|
||||
\
|
||||
if (!__nested) \
|
||||
goto nla_put_failure; \
|
||||
NLA_PUT(skb, IPSET_ATTR_IPADDR_IPV6, \
|
||||
sizeof(struct in6_addr), ipaddrptr); \
|
||||
ipset_nest_end(skb, __nested); \
|
||||
} while (0)
|
||||
|
||||
/* Get address from skbuff */
|
||||
static inline __be32
|
||||
ip4addr(const struct sk_buff *skb, bool src)
|
||||
{
|
||||
return src ? ip_hdr(skb)->saddr : ip_hdr(skb)->daddr;
|
||||
}
|
||||
|
||||
static inline void
|
||||
ip4addrptr(const struct sk_buff *skb, bool src, __be32 *addr)
|
||||
{
|
||||
*addr = src ? ip_hdr(skb)->saddr : ip_hdr(skb)->daddr;
|
||||
}
|
||||
|
||||
static inline void
|
||||
ip6addrptr(const struct sk_buff *skb, bool src, struct in6_addr *addr)
|
||||
{
|
||||
memcpy(addr, src ? &ipv6_hdr(skb)->saddr : &ipv6_hdr(skb)->daddr,
|
||||
sizeof(*addr));
|
||||
}
|
||||
|
||||
/* Calculate the bytes required to store the inclusive range of a-b */
|
||||
static inline int
|
||||
bitmap_bytes(u32 a, u32 b)
|
||||
{
|
||||
return 4 * ((((b - a + 8) / 8) + 3) / 4);
|
||||
}
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
/* Interface to iptables/ip6tables */
|
||||
|
||||
#define SO_IP_SET 83
|
||||
|
||||
union ip_set_name_index {
|
||||
char name[IPSET_MAXNAMELEN];
|
||||
ip_set_id_t index;
|
||||
};
|
||||
|
||||
#define IP_SET_OP_GET_BYNAME 0x00000006 /* Get set index by name */
|
||||
struct ip_set_req_get_set {
|
||||
unsigned op;
|
||||
unsigned version;
|
||||
union ip_set_name_index set;
|
||||
};
|
||||
|
||||
#define IP_SET_OP_GET_BYINDEX 0x00000007 /* Get set name by index */
|
||||
/* Uses ip_set_req_get_set */
|
||||
|
||||
#define IP_SET_OP_VERSION 0x00000100 /* Ask kernel version */
|
||||
struct ip_set_req_version {
|
||||
unsigned op;
|
||||
unsigned version;
|
||||
};
|
||||
|
||||
#endif /*_IP_SET_H */
|
||||
1133
extensions/ipset-6/ip_set_ahash.h
Normal file
1133
extensions/ipset-6/ip_set_ahash.h
Normal file
File diff suppressed because it is too large
Load Diff
31
extensions/ipset-6/ip_set_bitmap.h
Normal file
31
extensions/ipset-6/ip_set_bitmap.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef __IP_SET_BITMAP_H
|
||||
#define __IP_SET_BITMAP_H
|
||||
|
||||
/* Bitmap type specific error codes */
|
||||
enum {
|
||||
/* The element is out of the range of the set */
|
||||
IPSET_ERR_BITMAP_RANGE = IPSET_ERR_TYPE_SPECIFIC,
|
||||
/* The range exceeds the size limit of the set type */
|
||||
IPSET_ERR_BITMAP_RANGE_SIZE,
|
||||
};
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#define IPSET_BITMAP_MAX_RANGE 0x0000FFFF
|
||||
|
||||
/* Common functions */
|
||||
|
||||
static inline u32
|
||||
range_to_mask(u32 from, u32 to, u8 *bits)
|
||||
{
|
||||
u32 mask = 0xFFFFFFFE;
|
||||
|
||||
*bits = 32;
|
||||
while (--(*bits) > 0 && mask && (to & mask) != from)
|
||||
mask <<= 1;
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* __IP_SET_BITMAP_H */
|
||||
587
extensions/ipset-6/ip_set_bitmap_ip.c
Normal file
587
extensions/ipset-6/ip_set_bitmap_ip.c
Normal file
@@ -0,0 +1,587 @@
|
||||
/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
|
||||
* Patrick Schaaf <bof@bof.de>
|
||||
* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an IP set type: the bitmap:ip type */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/timer.h>
|
||||
#include <net/netlink.h>
|
||||
#include <net/tcp.h>
|
||||
|
||||
#include "pfxlen.h"
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_bitmap.h"
|
||||
#define IP_SET_BITMAP_TIMEOUT
|
||||
#include "ip_set_timeout.h"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("bitmap:ip type of IP sets");
|
||||
MODULE_ALIAS("ip_set_bitmap:ip");
|
||||
|
||||
/* Type structure */
|
||||
struct bitmap_ip {
|
||||
void *members; /* the set members */
|
||||
u32 first_ip; /* host byte order, included in range */
|
||||
u32 last_ip; /* host byte order, included in range */
|
||||
u32 elements; /* number of max elements in the set */
|
||||
u32 hosts; /* number of hosts in a subnet */
|
||||
size_t memsize; /* members size */
|
||||
u8 netmask; /* subnet netmask */
|
||||
u32 timeout; /* timeout parameter */
|
||||
struct timer_list gc; /* garbage collection */
|
||||
};
|
||||
|
||||
/* Base variant */
|
||||
|
||||
static inline u32
|
||||
ip_to_id(const struct bitmap_ip *m, u32 ip)
|
||||
{
|
||||
return ((ip & ip_set_hostmask(m->netmask)) - m->first_ip)/m->hosts;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_test(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
const struct bitmap_ip *map = set->data;
|
||||
u16 id = *(u16 *)value;
|
||||
|
||||
return !!test_bit(id, map->members);
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_add(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
struct bitmap_ip *map = set->data;
|
||||
u16 id = *(u16 *)value;
|
||||
|
||||
if (test_and_set_bit(id, map->members))
|
||||
return -IPSET_ERR_EXIST;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_del(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
struct bitmap_ip *map = set->data;
|
||||
u16 id = *(u16 *)value;
|
||||
|
||||
if (!test_and_clear_bit(id, map->members))
|
||||
return -IPSET_ERR_EXIST;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_list(const struct ip_set *set,
|
||||
struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
const struct bitmap_ip *map = set->data;
|
||||
struct nlattr *atd, *nested;
|
||||
u32 id, first = cb->args[2];
|
||||
|
||||
atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
|
||||
if (!atd)
|
||||
return -EMSGSIZE;
|
||||
for (; cb->args[2] < map->elements; cb->args[2]++) {
|
||||
id = cb->args[2];
|
||||
if (!test_bit(id, map->members))
|
||||
continue;
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested) {
|
||||
if (id == first) {
|
||||
nla_nest_cancel(skb, atd);
|
||||
return -EMSGSIZE;
|
||||
} else
|
||||
goto nla_put_failure;
|
||||
}
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP,
|
||||
htonl(map->first_ip + id * map->hosts));
|
||||
ipset_nest_end(skb, nested);
|
||||
}
|
||||
ipset_nest_end(skb, atd);
|
||||
/* Set listing finished */
|
||||
cb->args[2] = 0;
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
nla_nest_cancel(skb, nested);
|
||||
ipset_nest_end(skb, atd);
|
||||
if (unlikely(id == first)) {
|
||||
cb->args[2] = 0;
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Timeout variant */
|
||||
|
||||
static int
|
||||
bitmap_ip_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
const struct bitmap_ip *map = set->data;
|
||||
const unsigned long *members = map->members;
|
||||
u16 id = *(u16 *)value;
|
||||
|
||||
return ip_set_timeout_test(members[id]);
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
struct bitmap_ip *map = set->data;
|
||||
unsigned long *members = map->members;
|
||||
u16 id = *(u16 *)value;
|
||||
|
||||
if (ip_set_timeout_test(members[id]) && !(flags & IPSET_FLAG_EXIST))
|
||||
return -IPSET_ERR_EXIST;
|
||||
|
||||
members[id] = ip_set_timeout_set(timeout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
struct bitmap_ip *map = set->data;
|
||||
unsigned long *members = map->members;
|
||||
u16 id = *(u16 *)value;
|
||||
int ret = -IPSET_ERR_EXIST;
|
||||
|
||||
if (ip_set_timeout_test(members[id]))
|
||||
ret = 0;
|
||||
|
||||
members[id] = IPSET_ELEM_UNSET;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_tlist(const struct ip_set *set,
|
||||
struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
const struct bitmap_ip *map = set->data;
|
||||
struct nlattr *adt, *nested;
|
||||
u32 id, first = cb->args[2];
|
||||
const unsigned long *members = map->members;
|
||||
|
||||
adt = ipset_nest_start(skb, IPSET_ATTR_ADT);
|
||||
if (!adt)
|
||||
return -EMSGSIZE;
|
||||
for (; cb->args[2] < map->elements; cb->args[2]++) {
|
||||
id = cb->args[2];
|
||||
if (!ip_set_timeout_test(members[id]))
|
||||
continue;
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested) {
|
||||
if (id == first) {
|
||||
nla_nest_cancel(skb, adt);
|
||||
return -EMSGSIZE;
|
||||
} else
|
||||
goto nla_put_failure;
|
||||
}
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP,
|
||||
htonl(map->first_ip + id * map->hosts));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
|
||||
htonl(ip_set_timeout_get(members[id])));
|
||||
ipset_nest_end(skb, nested);
|
||||
}
|
||||
ipset_nest_end(skb, adt);
|
||||
|
||||
/* Set listing finished */
|
||||
cb->args[2] = 0;
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
nla_nest_cancel(skb, nested);
|
||||
ipset_nest_end(skb, adt);
|
||||
if (unlikely(id == first)) {
|
||||
cb->args[2] = 0;
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
const struct xt_action_param *par,
|
||||
enum ipset_adt adt, const struct ip_set_adt_opt *opt)
|
||||
{
|
||||
struct bitmap_ip *map = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
u32 ip;
|
||||
|
||||
ip = ntohl(ip4addr(skb, opt->flags & IPSET_DIM_ONE_SRC));
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
ip = ip_to_id(map, ip);
|
||||
|
||||
return adtfn(set, &ip, opt_timeout(opt, map), opt->cmdflags);
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
|
||||
{
|
||||
struct bitmap_ip *map = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
u32 timeout = map->timeout;
|
||||
u32 ip, ip_to, id;
|
||||
int ret = 0;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(map->timeout))
|
||||
return -IPSET_ERR_TIMEOUT;
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
if (adt == IPSET_TEST) {
|
||||
id = ip_to_id(map, ip);
|
||||
return adtfn(set, &id, timeout, flags);
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_IP_TO]) {
|
||||
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (ip > ip_to) {
|
||||
swap(ip, ip_to);
|
||||
if (ip < map->first_ip)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
}
|
||||
} else if (tb[IPSET_ATTR_CIDR]) {
|
||||
u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
|
||||
|
||||
if (cidr > 32)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
ip_set_mask_from_to(ip, ip_to, cidr);
|
||||
} else
|
||||
ip_to = ip;
|
||||
|
||||
if (ip_to > map->last_ip)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
for (; !before(ip_to, ip); ip += map->hosts) {
|
||||
id = ip_to_id(map, ip);
|
||||
ret = adtfn(set, &id, timeout, flags);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
bitmap_ip_destroy(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_ip *map = set->data;
|
||||
|
||||
if (with_timeout(map->timeout))
|
||||
del_timer_sync(&map->gc);
|
||||
|
||||
ip_set_free(map->members);
|
||||
kfree(map);
|
||||
|
||||
set->data = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
bitmap_ip_flush(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_ip *map = set->data;
|
||||
|
||||
memset(map->members, 0, map->memsize);
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_head(struct ip_set *set, struct sk_buff *skb)
|
||||
{
|
||||
const struct bitmap_ip *map = set->data;
|
||||
struct nlattr *nested;
|
||||
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested)
|
||||
goto nla_put_failure;
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, htonl(map->first_ip));
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip));
|
||||
if (map->netmask != 32)
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_NETMASK, map->netmask);
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
|
||||
htonl(sizeof(*map) + map->memsize));
|
||||
if (with_timeout(map->timeout))
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout));
|
||||
ipset_nest_end(skb, nested);
|
||||
|
||||
return 0;
|
||||
nla_put_failure:
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static bool
|
||||
bitmap_ip_same_set(const struct ip_set *a, const struct ip_set *b)
|
||||
{
|
||||
const struct bitmap_ip *x = a->data;
|
||||
const struct bitmap_ip *y = b->data;
|
||||
|
||||
return x->first_ip == y->first_ip &&
|
||||
x->last_ip == y->last_ip &&
|
||||
x->netmask == y->netmask &&
|
||||
x->timeout == y->timeout;
|
||||
}
|
||||
|
||||
static const struct ip_set_type_variant bitmap_ip = {
|
||||
.kadt = bitmap_ip_kadt,
|
||||
.uadt = bitmap_ip_uadt,
|
||||
.adt = {
|
||||
[IPSET_ADD] = bitmap_ip_add,
|
||||
[IPSET_DEL] = bitmap_ip_del,
|
||||
[IPSET_TEST] = bitmap_ip_test,
|
||||
},
|
||||
.destroy = bitmap_ip_destroy,
|
||||
.flush = bitmap_ip_flush,
|
||||
.head = bitmap_ip_head,
|
||||
.list = bitmap_ip_list,
|
||||
.same_set = bitmap_ip_same_set,
|
||||
};
|
||||
|
||||
static const struct ip_set_type_variant bitmap_tip = {
|
||||
.kadt = bitmap_ip_kadt,
|
||||
.uadt = bitmap_ip_uadt,
|
||||
.adt = {
|
||||
[IPSET_ADD] = bitmap_ip_tadd,
|
||||
[IPSET_DEL] = bitmap_ip_tdel,
|
||||
[IPSET_TEST] = bitmap_ip_ttest,
|
||||
},
|
||||
.destroy = bitmap_ip_destroy,
|
||||
.flush = bitmap_ip_flush,
|
||||
.head = bitmap_ip_head,
|
||||
.list = bitmap_ip_tlist,
|
||||
.same_set = bitmap_ip_same_set,
|
||||
};
|
||||
|
||||
static void
|
||||
bitmap_ip_gc(unsigned long ul_set)
|
||||
{
|
||||
struct ip_set *set = (struct ip_set *) ul_set;
|
||||
struct bitmap_ip *map = set->data;
|
||||
unsigned long *table = map->members;
|
||||
u32 id;
|
||||
|
||||
/* We run parallel with other readers (test element)
|
||||
* but adding/deleting new entries is locked out */
|
||||
read_lock_bh(&set->lock);
|
||||
for (id = 0; id < map->elements; id++)
|
||||
if (ip_set_timeout_expired(table[id]))
|
||||
table[id] = IPSET_ELEM_UNSET;
|
||||
read_unlock_bh(&set->lock);
|
||||
|
||||
map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
|
||||
add_timer(&map->gc);
|
||||
}
|
||||
|
||||
static void
|
||||
bitmap_ip_gc_init(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_ip *map = set->data;
|
||||
|
||||
init_timer(&map->gc);
|
||||
map->gc.data = (unsigned long) set;
|
||||
map->gc.function = bitmap_ip_gc;
|
||||
map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
|
||||
add_timer(&map->gc);
|
||||
}
|
||||
|
||||
/* Create bitmap:ip type of sets */
|
||||
|
||||
static bool
|
||||
init_map_ip(struct ip_set *set, struct bitmap_ip *map,
|
||||
u32 first_ip, u32 last_ip,
|
||||
u32 elements, u32 hosts, u8 netmask)
|
||||
{
|
||||
map->members = ip_set_alloc(map->memsize);
|
||||
if (!map->members)
|
||||
return false;
|
||||
map->first_ip = first_ip;
|
||||
map->last_ip = last_ip;
|
||||
map->elements = elements;
|
||||
map->hosts = hosts;
|
||||
map->netmask = netmask;
|
||||
map->timeout = IPSET_NO_TIMEOUT;
|
||||
|
||||
set->data = map;
|
||||
set->family = NFPROTO_IPV4;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
|
||||
{
|
||||
struct bitmap_ip *map;
|
||||
u32 first_ip, last_ip, hosts, elements;
|
||||
u8 netmask = 32;
|
||||
int ret;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &first_ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (tb[IPSET_ATTR_IP_TO]) {
|
||||
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &last_ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (first_ip > last_ip) {
|
||||
u32 tmp = first_ip;
|
||||
|
||||
first_ip = last_ip;
|
||||
last_ip = tmp;
|
||||
}
|
||||
} else if (tb[IPSET_ATTR_CIDR]) {
|
||||
u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
|
||||
|
||||
if (cidr >= 32)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
ip_set_mask_from_to(first_ip, last_ip, cidr);
|
||||
} else
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_NETMASK]) {
|
||||
netmask = nla_get_u8(tb[IPSET_ATTR_NETMASK]);
|
||||
|
||||
if (netmask > 32)
|
||||
return -IPSET_ERR_INVALID_NETMASK;
|
||||
|
||||
first_ip &= ip_set_hostmask(netmask);
|
||||
last_ip |= ~ip_set_hostmask(netmask);
|
||||
}
|
||||
|
||||
if (netmask == 32) {
|
||||
hosts = 1;
|
||||
elements = last_ip - first_ip + 1;
|
||||
} else {
|
||||
u8 mask_bits;
|
||||
u32 mask;
|
||||
|
||||
mask = range_to_mask(first_ip, last_ip, &mask_bits);
|
||||
|
||||
if ((!mask && (first_ip || last_ip != 0xFFFFFFFF)) ||
|
||||
netmask <= mask_bits)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
pr_debug("mask_bits %u, netmask %u\n", mask_bits, netmask);
|
||||
hosts = 2 << (32 - netmask - 1);
|
||||
elements = 2 << (netmask - mask_bits - 1);
|
||||
}
|
||||
if (elements > IPSET_BITMAP_MAX_RANGE + 1)
|
||||
return -IPSET_ERR_BITMAP_RANGE_SIZE;
|
||||
|
||||
pr_debug("hosts %u, elements %u\n", hosts, elements);
|
||||
|
||||
map = kzalloc(sizeof(*map), GFP_KERNEL);
|
||||
if (!map)
|
||||
return -ENOMEM;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
map->memsize = elements * sizeof(unsigned long);
|
||||
|
||||
if (!init_map_ip(set, map, first_ip, last_ip,
|
||||
elements, hosts, netmask)) {
|
||||
kfree(map);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
map->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
set->variant = &bitmap_tip;
|
||||
|
||||
bitmap_ip_gc_init(set);
|
||||
} else {
|
||||
map->memsize = bitmap_bytes(0, elements - 1);
|
||||
|
||||
if (!init_map_ip(set, map, first_ip, last_ip,
|
||||
elements, hosts, netmask)) {
|
||||
kfree(map);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
set->variant = &bitmap_ip;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ip_set_type bitmap_ip_type __read_mostly = {
|
||||
.name = "bitmap:ip",
|
||||
.protocol = IPSET_PROTOCOL,
|
||||
.features = IPSET_TYPE_IP,
|
||||
.dimension = IPSET_DIM_ONE,
|
||||
.family = NFPROTO_IPV4,
|
||||
.revision_min = 0,
|
||||
.revision_max = 0,
|
||||
.create = bitmap_ip_create,
|
||||
.create_policy = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_CIDR] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_NETMASK] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
},
|
||||
.adt_policy = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_CIDR] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
},
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init
|
||||
bitmap_ip_init(void)
|
||||
{
|
||||
return ip_set_type_register(&bitmap_ip_type);
|
||||
}
|
||||
|
||||
static void __exit
|
||||
bitmap_ip_fini(void)
|
||||
{
|
||||
ip_set_type_unregister(&bitmap_ip_type);
|
||||
}
|
||||
|
||||
module_init(bitmap_ip_init);
|
||||
module_exit(bitmap_ip_fini);
|
||||
659
extensions/ipset-6/ip_set_bitmap_ipmac.c
Normal file
659
extensions/ipset-6/ip_set_bitmap_ipmac.c
Normal file
@@ -0,0 +1,659 @@
|
||||
/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
|
||||
* Patrick Schaaf <bof@bof.de>
|
||||
* Martin Josefsson <gandalf@wlug.westbo.se>
|
||||
* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an IP set type: the bitmap:ip,mac type */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/timer.h>
|
||||
#include <net/netlink.h>
|
||||
|
||||
#include "pfxlen.h"
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_timeout.h"
|
||||
#include "ip_set_bitmap.h"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("bitmap:ip,mac type of IP sets");
|
||||
MODULE_ALIAS("ip_set_bitmap:ip,mac");
|
||||
|
||||
enum {
|
||||
MAC_EMPTY, /* element is not set */
|
||||
MAC_FILLED, /* element is set with MAC */
|
||||
MAC_UNSET, /* element is set, without MAC */
|
||||
};
|
||||
|
||||
/* Type structure */
|
||||
struct bitmap_ipmac {
|
||||
void *members; /* the set members */
|
||||
u32 first_ip; /* host byte order, included in range */
|
||||
u32 last_ip; /* host byte order, included in range */
|
||||
u32 timeout; /* timeout value */
|
||||
struct timer_list gc; /* garbage collector */
|
||||
size_t dsize; /* size of element */
|
||||
};
|
||||
|
||||
/* ADT structure for generic function args */
|
||||
struct ipmac {
|
||||
u32 id; /* id in array */
|
||||
unsigned char *ether; /* ethernet address */
|
||||
};
|
||||
|
||||
/* Member element without and with timeout */
|
||||
|
||||
struct ipmac_elem {
|
||||
unsigned char ether[ETH_ALEN];
|
||||
unsigned char match;
|
||||
} __attribute__ ((aligned));
|
||||
|
||||
struct ipmac_telem {
|
||||
unsigned char ether[ETH_ALEN];
|
||||
unsigned char match;
|
||||
unsigned long timeout;
|
||||
} __attribute__ ((aligned));
|
||||
|
||||
static inline void *
|
||||
bitmap_ipmac_elem(const struct bitmap_ipmac *map, u32 id)
|
||||
{
|
||||
return (void *)((char *)map->members + id * map->dsize);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
bitmap_timeout(const struct bitmap_ipmac *map, u32 id)
|
||||
{
|
||||
const struct ipmac_telem *elem = bitmap_ipmac_elem(map, id);
|
||||
|
||||
return ip_set_timeout_test(elem->timeout);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
bitmap_expired(const struct bitmap_ipmac *map, u32 id)
|
||||
{
|
||||
const struct ipmac_telem *elem = bitmap_ipmac_elem(map, id);
|
||||
|
||||
return ip_set_timeout_expired(elem->timeout);
|
||||
}
|
||||
|
||||
static inline int
|
||||
bitmap_ipmac_exist(const struct ipmac_telem *elem)
|
||||
{
|
||||
return elem->match == MAC_UNSET ||
|
||||
(elem->match == MAC_FILLED &&
|
||||
!ip_set_timeout_expired(elem->timeout));
|
||||
}
|
||||
|
||||
/* Base variant */
|
||||
|
||||
static int
|
||||
bitmap_ipmac_test(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
const struct bitmap_ipmac *map = set->data;
|
||||
const struct ipmac *data = value;
|
||||
const struct ipmac_elem *elem = bitmap_ipmac_elem(map, data->id);
|
||||
|
||||
switch (elem->match) {
|
||||
case MAC_UNSET:
|
||||
/* Trigger kernel to fill out the ethernet address */
|
||||
return -EAGAIN;
|
||||
case MAC_FILLED:
|
||||
return data->ether == NULL ||
|
||||
compare_ether_addr(data->ether, elem->ether) == 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ipmac_add(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
struct bitmap_ipmac *map = set->data;
|
||||
const struct ipmac *data = value;
|
||||
struct ipmac_elem *elem = bitmap_ipmac_elem(map, data->id);
|
||||
|
||||
switch (elem->match) {
|
||||
case MAC_UNSET:
|
||||
if (!data->ether)
|
||||
/* Already added without ethernet address */
|
||||
return -IPSET_ERR_EXIST;
|
||||
/* Fill the MAC address */
|
||||
memcpy(elem->ether, data->ether, ETH_ALEN);
|
||||
elem->match = MAC_FILLED;
|
||||
break;
|
||||
case MAC_FILLED:
|
||||
return -IPSET_ERR_EXIST;
|
||||
case MAC_EMPTY:
|
||||
if (data->ether) {
|
||||
memcpy(elem->ether, data->ether, ETH_ALEN);
|
||||
elem->match = MAC_FILLED;
|
||||
} else
|
||||
elem->match = MAC_UNSET;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ipmac_del(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
struct bitmap_ipmac *map = set->data;
|
||||
const struct ipmac *data = value;
|
||||
struct ipmac_elem *elem = bitmap_ipmac_elem(map, data->id);
|
||||
|
||||
if (elem->match == MAC_EMPTY)
|
||||
return -IPSET_ERR_EXIST;
|
||||
|
||||
elem->match = MAC_EMPTY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ipmac_list(const struct ip_set *set,
|
||||
struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
const struct bitmap_ipmac *map = set->data;
|
||||
const struct ipmac_elem *elem;
|
||||
struct nlattr *atd, *nested;
|
||||
u32 id, first = cb->args[2];
|
||||
u32 last = map->last_ip - map->first_ip;
|
||||
|
||||
atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
|
||||
if (!atd)
|
||||
return -EMSGSIZE;
|
||||
for (; cb->args[2] <= last; cb->args[2]++) {
|
||||
id = cb->args[2];
|
||||
elem = bitmap_ipmac_elem(map, id);
|
||||
if (elem->match == MAC_EMPTY)
|
||||
continue;
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested) {
|
||||
if (id == first) {
|
||||
nla_nest_cancel(skb, atd);
|
||||
return -EMSGSIZE;
|
||||
} else
|
||||
goto nla_put_failure;
|
||||
}
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP,
|
||||
htonl(map->first_ip + id));
|
||||
if (elem->match == MAC_FILLED)
|
||||
NLA_PUT(skb, IPSET_ATTR_ETHER, ETH_ALEN,
|
||||
elem->ether);
|
||||
ipset_nest_end(skb, nested);
|
||||
}
|
||||
ipset_nest_end(skb, atd);
|
||||
/* Set listing finished */
|
||||
cb->args[2] = 0;
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
nla_nest_cancel(skb, nested);
|
||||
ipset_nest_end(skb, atd);
|
||||
if (unlikely(id == first)) {
|
||||
cb->args[2] = 0;
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Timeout variant */
|
||||
|
||||
static int
|
||||
bitmap_ipmac_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
const struct bitmap_ipmac *map = set->data;
|
||||
const struct ipmac *data = value;
|
||||
const struct ipmac_elem *elem = bitmap_ipmac_elem(map, data->id);
|
||||
|
||||
switch (elem->match) {
|
||||
case MAC_UNSET:
|
||||
/* Trigger kernel to fill out the ethernet address */
|
||||
return -EAGAIN;
|
||||
case MAC_FILLED:
|
||||
return (data->ether == NULL ||
|
||||
compare_ether_addr(data->ether, elem->ether) == 0) &&
|
||||
!bitmap_expired(map, data->id);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ipmac_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
struct bitmap_ipmac *map = set->data;
|
||||
const struct ipmac *data = value;
|
||||
struct ipmac_telem *elem = bitmap_ipmac_elem(map, data->id);
|
||||
bool flag_exist = flags & IPSET_FLAG_EXIST;
|
||||
|
||||
switch (elem->match) {
|
||||
case MAC_UNSET:
|
||||
if (!(data->ether || flag_exist))
|
||||
/* Already added without ethernet address */
|
||||
return -IPSET_ERR_EXIST;
|
||||
/* Fill the MAC address and activate the timer */
|
||||
memcpy(elem->ether, data->ether, ETH_ALEN);
|
||||
elem->match = MAC_FILLED;
|
||||
if (timeout == map->timeout)
|
||||
/* Timeout was not specified, get stored one */
|
||||
timeout = elem->timeout;
|
||||
elem->timeout = ip_set_timeout_set(timeout);
|
||||
break;
|
||||
case MAC_FILLED:
|
||||
if (!(bitmap_expired(map, data->id) || flag_exist))
|
||||
return -IPSET_ERR_EXIST;
|
||||
/* Fall through */
|
||||
case MAC_EMPTY:
|
||||
if (data->ether) {
|
||||
memcpy(elem->ether, data->ether, ETH_ALEN);
|
||||
elem->match = MAC_FILLED;
|
||||
} else
|
||||
elem->match = MAC_UNSET;
|
||||
/* If MAC is unset yet, we store plain timeout value
|
||||
* because the timer is not activated yet
|
||||
* and we can reuse it later when MAC is filled out,
|
||||
* possibly by the kernel */
|
||||
elem->timeout = data->ether ? ip_set_timeout_set(timeout)
|
||||
: timeout;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ipmac_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
struct bitmap_ipmac *map = set->data;
|
||||
const struct ipmac *data = value;
|
||||
struct ipmac_telem *elem = bitmap_ipmac_elem(map, data->id);
|
||||
|
||||
if (elem->match == MAC_EMPTY || bitmap_expired(map, data->id))
|
||||
return -IPSET_ERR_EXIST;
|
||||
|
||||
elem->match = MAC_EMPTY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ipmac_tlist(const struct ip_set *set,
|
||||
struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
const struct bitmap_ipmac *map = set->data;
|
||||
const struct ipmac_telem *elem;
|
||||
struct nlattr *atd, *nested;
|
||||
u32 id, first = cb->args[2];
|
||||
u32 timeout, last = map->last_ip - map->first_ip;
|
||||
|
||||
atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
|
||||
if (!atd)
|
||||
return -EMSGSIZE;
|
||||
for (; cb->args[2] <= last; cb->args[2]++) {
|
||||
id = cb->args[2];
|
||||
elem = bitmap_ipmac_elem(map, id);
|
||||
if (!bitmap_ipmac_exist(elem))
|
||||
continue;
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested) {
|
||||
if (id == first) {
|
||||
nla_nest_cancel(skb, atd);
|
||||
return -EMSGSIZE;
|
||||
} else
|
||||
goto nla_put_failure;
|
||||
}
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP,
|
||||
htonl(map->first_ip + id));
|
||||
if (elem->match == MAC_FILLED)
|
||||
NLA_PUT(skb, IPSET_ATTR_ETHER, ETH_ALEN,
|
||||
elem->ether);
|
||||
timeout = elem->match == MAC_UNSET ? elem->timeout
|
||||
: ip_set_timeout_get(elem->timeout);
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(timeout));
|
||||
ipset_nest_end(skb, nested);
|
||||
}
|
||||
ipset_nest_end(skb, atd);
|
||||
/* Set listing finished */
|
||||
cb->args[2] = 0;
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
nla_nest_cancel(skb, nested);
|
||||
ipset_nest_end(skb, atd);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
const struct xt_action_param *par,
|
||||
enum ipset_adt adt, const struct ip_set_adt_opt *opt)
|
||||
{
|
||||
struct bitmap_ipmac *map = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct ipmac data;
|
||||
|
||||
/* MAC can be src only */
|
||||
if (!(opt->flags & IPSET_DIM_TWO_SRC))
|
||||
return 0;
|
||||
|
||||
data.id = ntohl(ip4addr(skb, opt->flags & IPSET_DIM_ONE_SRC));
|
||||
if (data.id < map->first_ip || data.id > map->last_ip)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
/* Backward compatibility: we don't check the second flag */
|
||||
if (skb_mac_header(skb) < skb->head ||
|
||||
(skb_mac_header(skb) + ETH_HLEN) > skb->data)
|
||||
return -EINVAL;
|
||||
|
||||
data.id -= map->first_ip;
|
||||
data.ether = eth_hdr(skb)->h_source;
|
||||
|
||||
return adtfn(set, &data, opt_timeout(opt, map), opt->cmdflags);
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
|
||||
{
|
||||
const struct bitmap_ipmac *map = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct ipmac data;
|
||||
u32 timeout = map->timeout;
|
||||
int ret = 0;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &data.id);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (data.id < map->first_ip || data.id > map->last_ip)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
if (tb[IPSET_ATTR_ETHER])
|
||||
data.ether = nla_data(tb[IPSET_ATTR_ETHER]);
|
||||
else
|
||||
data.ether = NULL;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(map->timeout))
|
||||
return -IPSET_ERR_TIMEOUT;
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
data.id -= map->first_ip;
|
||||
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
static void
|
||||
bitmap_ipmac_destroy(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_ipmac *map = set->data;
|
||||
|
||||
if (with_timeout(map->timeout))
|
||||
del_timer_sync(&map->gc);
|
||||
|
||||
ip_set_free(map->members);
|
||||
kfree(map);
|
||||
|
||||
set->data = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
bitmap_ipmac_flush(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_ipmac *map = set->data;
|
||||
|
||||
memset(map->members, 0,
|
||||
(map->last_ip - map->first_ip + 1) * map->dsize);
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ipmac_head(struct ip_set *set, struct sk_buff *skb)
|
||||
{
|
||||
const struct bitmap_ipmac *map = set->data;
|
||||
struct nlattr *nested;
|
||||
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested)
|
||||
goto nla_put_failure;
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, htonl(map->first_ip));
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
|
||||
htonl(sizeof(*map)
|
||||
+ (map->last_ip - map->first_ip + 1) * map->dsize));
|
||||
if (with_timeout(map->timeout))
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout));
|
||||
ipset_nest_end(skb, nested);
|
||||
|
||||
return 0;
|
||||
nla_put_failure:
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static bool
|
||||
bitmap_ipmac_same_set(const struct ip_set *a, const struct ip_set *b)
|
||||
{
|
||||
const struct bitmap_ipmac *x = a->data;
|
||||
const struct bitmap_ipmac *y = b->data;
|
||||
|
||||
return x->first_ip == y->first_ip &&
|
||||
x->last_ip == y->last_ip &&
|
||||
x->timeout == y->timeout;
|
||||
}
|
||||
|
||||
static const struct ip_set_type_variant bitmap_ipmac = {
|
||||
.kadt = bitmap_ipmac_kadt,
|
||||
.uadt = bitmap_ipmac_uadt,
|
||||
.adt = {
|
||||
[IPSET_ADD] = bitmap_ipmac_add,
|
||||
[IPSET_DEL] = bitmap_ipmac_del,
|
||||
[IPSET_TEST] = bitmap_ipmac_test,
|
||||
},
|
||||
.destroy = bitmap_ipmac_destroy,
|
||||
.flush = bitmap_ipmac_flush,
|
||||
.head = bitmap_ipmac_head,
|
||||
.list = bitmap_ipmac_list,
|
||||
.same_set = bitmap_ipmac_same_set,
|
||||
};
|
||||
|
||||
static const struct ip_set_type_variant bitmap_tipmac = {
|
||||
.kadt = bitmap_ipmac_kadt,
|
||||
.uadt = bitmap_ipmac_uadt,
|
||||
.adt = {
|
||||
[IPSET_ADD] = bitmap_ipmac_tadd,
|
||||
[IPSET_DEL] = bitmap_ipmac_tdel,
|
||||
[IPSET_TEST] = bitmap_ipmac_ttest,
|
||||
},
|
||||
.destroy = bitmap_ipmac_destroy,
|
||||
.flush = bitmap_ipmac_flush,
|
||||
.head = bitmap_ipmac_head,
|
||||
.list = bitmap_ipmac_tlist,
|
||||
.same_set = bitmap_ipmac_same_set,
|
||||
};
|
||||
|
||||
static void
|
||||
bitmap_ipmac_gc(unsigned long ul_set)
|
||||
{
|
||||
struct ip_set *set = (struct ip_set *) ul_set;
|
||||
struct bitmap_ipmac *map = set->data;
|
||||
struct ipmac_telem *elem;
|
||||
u32 id, last = map->last_ip - map->first_ip;
|
||||
|
||||
/* We run parallel with other readers (test element)
|
||||
* but adding/deleting new entries is locked out */
|
||||
read_lock_bh(&set->lock);
|
||||
for (id = 0; id <= last; id++) {
|
||||
elem = bitmap_ipmac_elem(map, id);
|
||||
if (elem->match == MAC_FILLED &&
|
||||
ip_set_timeout_expired(elem->timeout))
|
||||
elem->match = MAC_EMPTY;
|
||||
}
|
||||
read_unlock_bh(&set->lock);
|
||||
|
||||
map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
|
||||
add_timer(&map->gc);
|
||||
}
|
||||
|
||||
static void
|
||||
bitmap_ipmac_gc_init(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_ipmac *map = set->data;
|
||||
|
||||
init_timer(&map->gc);
|
||||
map->gc.data = (unsigned long) set;
|
||||
map->gc.function = bitmap_ipmac_gc;
|
||||
map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
|
||||
add_timer(&map->gc);
|
||||
}
|
||||
|
||||
/* Create bitmap:ip,mac type of sets */
|
||||
|
||||
static bool
|
||||
init_map_ipmac(struct ip_set *set, struct bitmap_ipmac *map,
|
||||
u32 first_ip, u32 last_ip)
|
||||
{
|
||||
map->members = ip_set_alloc((last_ip - first_ip + 1) * map->dsize);
|
||||
if (!map->members)
|
||||
return false;
|
||||
map->first_ip = first_ip;
|
||||
map->last_ip = last_ip;
|
||||
map->timeout = IPSET_NO_TIMEOUT;
|
||||
|
||||
set->data = map;
|
||||
set->family = NFPROTO_IPV4;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ipmac_create(struct ip_set *set, struct nlattr *tb[],
|
||||
u32 flags)
|
||||
{
|
||||
u32 first_ip, last_ip, elements;
|
||||
struct bitmap_ipmac *map;
|
||||
int ret;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &first_ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (tb[IPSET_ATTR_IP_TO]) {
|
||||
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &last_ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (first_ip > last_ip) {
|
||||
u32 tmp = first_ip;
|
||||
|
||||
first_ip = last_ip;
|
||||
last_ip = tmp;
|
||||
}
|
||||
} else if (tb[IPSET_ATTR_CIDR]) {
|
||||
u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
|
||||
|
||||
if (cidr >= 32)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
ip_set_mask_from_to(first_ip, last_ip, cidr);
|
||||
} else
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
elements = last_ip - first_ip + 1;
|
||||
|
||||
if (elements > IPSET_BITMAP_MAX_RANGE + 1)
|
||||
return -IPSET_ERR_BITMAP_RANGE_SIZE;
|
||||
|
||||
map = kzalloc(sizeof(*map), GFP_KERNEL);
|
||||
if (!map)
|
||||
return -ENOMEM;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
map->dsize = sizeof(struct ipmac_telem);
|
||||
|
||||
if (!init_map_ipmac(set, map, first_ip, last_ip)) {
|
||||
kfree(map);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
map->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
|
||||
set->variant = &bitmap_tipmac;
|
||||
|
||||
bitmap_ipmac_gc_init(set);
|
||||
} else {
|
||||
map->dsize = sizeof(struct ipmac_elem);
|
||||
|
||||
if (!init_map_ipmac(set, map, first_ip, last_ip)) {
|
||||
kfree(map);
|
||||
return -ENOMEM;
|
||||
}
|
||||
set->variant = &bitmap_ipmac;
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ip_set_type bitmap_ipmac_type = {
|
||||
.name = "bitmap:ip,mac",
|
||||
.protocol = IPSET_PROTOCOL,
|
||||
.features = IPSET_TYPE_IP | IPSET_TYPE_MAC,
|
||||
.dimension = IPSET_DIM_TWO,
|
||||
.family = NFPROTO_IPV4,
|
||||
.revision_min = 0,
|
||||
.revision_max = 0,
|
||||
.create = bitmap_ipmac_create,
|
||||
.create_policy = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_CIDR] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
},
|
||||
.adt_policy = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_ETHER] = { .type = NLA_BINARY,
|
||||
.len = ETH_ALEN },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
},
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init
|
||||
bitmap_ipmac_init(void)
|
||||
{
|
||||
return ip_set_type_register(&bitmap_ipmac_type);
|
||||
}
|
||||
|
||||
static void __exit
|
||||
bitmap_ipmac_fini(void)
|
||||
{
|
||||
ip_set_type_unregister(&bitmap_ipmac_type);
|
||||
}
|
||||
|
||||
module_init(bitmap_ipmac_init);
|
||||
module_exit(bitmap_ipmac_fini);
|
||||
517
extensions/ipset-6/ip_set_bitmap_port.c
Normal file
517
extensions/ipset-6/ip_set_bitmap_port.c
Normal file
@@ -0,0 +1,517 @@
|
||||
/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an IP set type: the bitmap:port type */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/timer.h>
|
||||
#include <net/netlink.h>
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_bitmap.h"
|
||||
#include "ip_set_getport.h"
|
||||
#define IP_SET_BITMAP_TIMEOUT
|
||||
#include "ip_set_timeout.h"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("bitmap:port type of IP sets");
|
||||
MODULE_ALIAS("ip_set_bitmap:port");
|
||||
|
||||
/* Type structure */
|
||||
struct bitmap_port {
|
||||
void *members; /* the set members */
|
||||
u16 first_port; /* host byte order, included in range */
|
||||
u16 last_port; /* host byte order, included in range */
|
||||
size_t memsize; /* members size */
|
||||
u32 timeout; /* timeout parameter */
|
||||
struct timer_list gc; /* garbage collection */
|
||||
};
|
||||
|
||||
/* Base variant */
|
||||
|
||||
static int
|
||||
bitmap_port_test(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
const struct bitmap_port *map = set->data;
|
||||
u16 id = *(u16 *)value;
|
||||
|
||||
return !!test_bit(id, map->members);
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_add(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
struct bitmap_port *map = set->data;
|
||||
u16 id = *(u16 *)value;
|
||||
|
||||
if (test_and_set_bit(id, map->members))
|
||||
return -IPSET_ERR_EXIST;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_del(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
struct bitmap_port *map = set->data;
|
||||
u16 id = *(u16 *)value;
|
||||
|
||||
if (!test_and_clear_bit(id, map->members))
|
||||
return -IPSET_ERR_EXIST;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_list(const struct ip_set *set,
|
||||
struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
const struct bitmap_port *map = set->data;
|
||||
struct nlattr *atd, *nested;
|
||||
u16 id, first = cb->args[2];
|
||||
u16 last = map->last_port - map->first_port;
|
||||
|
||||
atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
|
||||
if (!atd)
|
||||
return -EMSGSIZE;
|
||||
for (; cb->args[2] <= last; cb->args[2]++) {
|
||||
id = cb->args[2];
|
||||
if (!test_bit(id, map->members))
|
||||
continue;
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested) {
|
||||
if (id == first) {
|
||||
nla_nest_cancel(skb, atd);
|
||||
return -EMSGSIZE;
|
||||
} else
|
||||
goto nla_put_failure;
|
||||
}
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT,
|
||||
htons(map->first_port + id));
|
||||
ipset_nest_end(skb, nested);
|
||||
}
|
||||
ipset_nest_end(skb, atd);
|
||||
/* Set listing finished */
|
||||
cb->args[2] = 0;
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
nla_nest_cancel(skb, nested);
|
||||
ipset_nest_end(skb, atd);
|
||||
if (unlikely(id == first)) {
|
||||
cb->args[2] = 0;
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Timeout variant */
|
||||
|
||||
static int
|
||||
bitmap_port_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
const struct bitmap_port *map = set->data;
|
||||
const unsigned long *members = map->members;
|
||||
u16 id = *(u16 *)value;
|
||||
|
||||
return ip_set_timeout_test(members[id]);
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
struct bitmap_port *map = set->data;
|
||||
unsigned long *members = map->members;
|
||||
u16 id = *(u16 *)value;
|
||||
|
||||
if (ip_set_timeout_test(members[id]) && !(flags & IPSET_FLAG_EXIST))
|
||||
return -IPSET_ERR_EXIST;
|
||||
|
||||
members[id] = ip_set_timeout_set(timeout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
struct bitmap_port *map = set->data;
|
||||
unsigned long *members = map->members;
|
||||
u16 id = *(u16 *)value;
|
||||
int ret = -IPSET_ERR_EXIST;
|
||||
|
||||
if (ip_set_timeout_test(members[id]))
|
||||
ret = 0;
|
||||
|
||||
members[id] = IPSET_ELEM_UNSET;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_tlist(const struct ip_set *set,
|
||||
struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
const struct bitmap_port *map = set->data;
|
||||
struct nlattr *adt, *nested;
|
||||
u16 id, first = cb->args[2];
|
||||
u16 last = map->last_port - map->first_port;
|
||||
const unsigned long *members = map->members;
|
||||
|
||||
adt = ipset_nest_start(skb, IPSET_ATTR_ADT);
|
||||
if (!adt)
|
||||
return -EMSGSIZE;
|
||||
for (; cb->args[2] <= last; cb->args[2]++) {
|
||||
id = cb->args[2];
|
||||
if (!ip_set_timeout_test(members[id]))
|
||||
continue;
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested) {
|
||||
if (id == first) {
|
||||
nla_nest_cancel(skb, adt);
|
||||
return -EMSGSIZE;
|
||||
} else
|
||||
goto nla_put_failure;
|
||||
}
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT,
|
||||
htons(map->first_port + id));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
|
||||
htonl(ip_set_timeout_get(members[id])));
|
||||
ipset_nest_end(skb, nested);
|
||||
}
|
||||
ipset_nest_end(skb, adt);
|
||||
|
||||
/* Set listing finished */
|
||||
cb->args[2] = 0;
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
nla_nest_cancel(skb, nested);
|
||||
ipset_nest_end(skb, adt);
|
||||
if (unlikely(id == first)) {
|
||||
cb->args[2] = 0;
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
const struct xt_action_param *par,
|
||||
enum ipset_adt adt, const struct ip_set_adt_opt *opt)
|
||||
{
|
||||
struct bitmap_port *map = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
__be16 __port;
|
||||
u16 port = 0;
|
||||
|
||||
if (!ip_set_get_ip_port(skb, opt->family,
|
||||
opt->flags & IPSET_DIM_ONE_SRC, &__port))
|
||||
return -EINVAL;
|
||||
|
||||
port = ntohs(__port);
|
||||
|
||||
if (port < map->first_port || port > map->last_port)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
port -= map->first_port;
|
||||
|
||||
return adtfn(set, &port, opt_timeout(opt, map), opt->cmdflags);
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
|
||||
{
|
||||
struct bitmap_port *map = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
u32 timeout = map->timeout;
|
||||
u32 port; /* wraparound */
|
||||
u16 id, port_to;
|
||||
int ret = 0;
|
||||
|
||||
if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
port = ip_set_get_h16(tb[IPSET_ATTR_PORT]);
|
||||
if (port < map->first_port || port > map->last_port)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(map->timeout))
|
||||
return -IPSET_ERR_TIMEOUT;
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
if (adt == IPSET_TEST) {
|
||||
id = port - map->first_port;
|
||||
return adtfn(set, &id, timeout, flags);
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_PORT_TO]) {
|
||||
port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
|
||||
if (port > port_to) {
|
||||
swap(port, port_to);
|
||||
if (port < map->first_port)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
}
|
||||
} else
|
||||
port_to = port;
|
||||
|
||||
if (port_to > map->last_port)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
for (; port <= port_to; port++) {
|
||||
id = port - map->first_port;
|
||||
ret = adtfn(set, &id, timeout, flags);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
bitmap_port_destroy(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_port *map = set->data;
|
||||
|
||||
if (with_timeout(map->timeout))
|
||||
del_timer_sync(&map->gc);
|
||||
|
||||
ip_set_free(map->members);
|
||||
kfree(map);
|
||||
|
||||
set->data = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
bitmap_port_flush(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_port *map = set->data;
|
||||
|
||||
memset(map->members, 0, map->memsize);
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_head(struct ip_set *set, struct sk_buff *skb)
|
||||
{
|
||||
const struct bitmap_port *map = set->data;
|
||||
struct nlattr *nested;
|
||||
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested)
|
||||
goto nla_put_failure;
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, htons(map->first_port));
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT_TO, htons(map->last_port));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
|
||||
htonl(sizeof(*map) + map->memsize));
|
||||
if (with_timeout(map->timeout))
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout));
|
||||
ipset_nest_end(skb, nested);
|
||||
|
||||
return 0;
|
||||
nla_put_failure:
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static bool
|
||||
bitmap_port_same_set(const struct ip_set *a, const struct ip_set *b)
|
||||
{
|
||||
const struct bitmap_port *x = a->data;
|
||||
const struct bitmap_port *y = b->data;
|
||||
|
||||
return x->first_port == y->first_port &&
|
||||
x->last_port == y->last_port &&
|
||||
x->timeout == y->timeout;
|
||||
}
|
||||
|
||||
static const struct ip_set_type_variant bitmap_port = {
|
||||
.kadt = bitmap_port_kadt,
|
||||
.uadt = bitmap_port_uadt,
|
||||
.adt = {
|
||||
[IPSET_ADD] = bitmap_port_add,
|
||||
[IPSET_DEL] = bitmap_port_del,
|
||||
[IPSET_TEST] = bitmap_port_test,
|
||||
},
|
||||
.destroy = bitmap_port_destroy,
|
||||
.flush = bitmap_port_flush,
|
||||
.head = bitmap_port_head,
|
||||
.list = bitmap_port_list,
|
||||
.same_set = bitmap_port_same_set,
|
||||
};
|
||||
|
||||
static const struct ip_set_type_variant bitmap_tport = {
|
||||
.kadt = bitmap_port_kadt,
|
||||
.uadt = bitmap_port_uadt,
|
||||
.adt = {
|
||||
[IPSET_ADD] = bitmap_port_tadd,
|
||||
[IPSET_DEL] = bitmap_port_tdel,
|
||||
[IPSET_TEST] = bitmap_port_ttest,
|
||||
},
|
||||
.destroy = bitmap_port_destroy,
|
||||
.flush = bitmap_port_flush,
|
||||
.head = bitmap_port_head,
|
||||
.list = bitmap_port_tlist,
|
||||
.same_set = bitmap_port_same_set,
|
||||
};
|
||||
|
||||
static void
|
||||
bitmap_port_gc(unsigned long ul_set)
|
||||
{
|
||||
struct ip_set *set = (struct ip_set *) ul_set;
|
||||
struct bitmap_port *map = set->data;
|
||||
unsigned long *table = map->members;
|
||||
u32 id; /* wraparound */
|
||||
u16 last = map->last_port - map->first_port;
|
||||
|
||||
/* We run parallel with other readers (test element)
|
||||
* but adding/deleting new entries is locked out */
|
||||
read_lock_bh(&set->lock);
|
||||
for (id = 0; id <= last; id++)
|
||||
if (ip_set_timeout_expired(table[id]))
|
||||
table[id] = IPSET_ELEM_UNSET;
|
||||
read_unlock_bh(&set->lock);
|
||||
|
||||
map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
|
||||
add_timer(&map->gc);
|
||||
}
|
||||
|
||||
static void
|
||||
bitmap_port_gc_init(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_port *map = set->data;
|
||||
|
||||
init_timer(&map->gc);
|
||||
map->gc.data = (unsigned long) set;
|
||||
map->gc.function = bitmap_port_gc;
|
||||
map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
|
||||
add_timer(&map->gc);
|
||||
}
|
||||
|
||||
/* Create bitmap:ip type of sets */
|
||||
|
||||
static bool
|
||||
init_map_port(struct ip_set *set, struct bitmap_port *map,
|
||||
u16 first_port, u16 last_port)
|
||||
{
|
||||
map->members = ip_set_alloc(map->memsize);
|
||||
if (!map->members)
|
||||
return false;
|
||||
map->first_port = first_port;
|
||||
map->last_port = last_port;
|
||||
map->timeout = IPSET_NO_TIMEOUT;
|
||||
|
||||
set->data = map;
|
||||
set->family = NFPROTO_UNSPEC;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_create(struct ip_set *set, struct nlattr *tb[],
|
||||
u32 flags)
|
||||
{
|
||||
struct bitmap_port *map;
|
||||
u16 first_port, last_port;
|
||||
|
||||
if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
|
||||
!ip_set_attr_netorder(tb, IPSET_ATTR_PORT_TO) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
first_port = ip_set_get_h16(tb[IPSET_ATTR_PORT]);
|
||||
last_port = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
|
||||
if (first_port > last_port) {
|
||||
u16 tmp = first_port;
|
||||
|
||||
first_port = last_port;
|
||||
last_port = tmp;
|
||||
}
|
||||
|
||||
map = kzalloc(sizeof(*map), GFP_KERNEL);
|
||||
if (!map)
|
||||
return -ENOMEM;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
map->memsize = (last_port - first_port + 1)
|
||||
* sizeof(unsigned long);
|
||||
|
||||
if (!init_map_port(set, map, first_port, last_port)) {
|
||||
kfree(map);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
map->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
set->variant = &bitmap_tport;
|
||||
|
||||
bitmap_port_gc_init(set);
|
||||
} else {
|
||||
map->memsize = bitmap_bytes(0, last_port - first_port);
|
||||
pr_debug("memsize: %zu\n", map->memsize);
|
||||
if (!init_map_port(set, map, first_port, last_port)) {
|
||||
kfree(map);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
set->variant = &bitmap_port;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ip_set_type bitmap_port_type = {
|
||||
.name = "bitmap:port",
|
||||
.protocol = IPSET_PROTOCOL,
|
||||
.features = IPSET_TYPE_PORT,
|
||||
.dimension = IPSET_DIM_ONE,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.revision_min = 0,
|
||||
.revision_max = 0,
|
||||
.create = bitmap_port_create,
|
||||
.create_policy = {
|
||||
[IPSET_ATTR_PORT] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_PORT_TO] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
},
|
||||
.adt_policy = {
|
||||
[IPSET_ATTR_PORT] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_PORT_TO] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
},
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init
|
||||
bitmap_port_init(void)
|
||||
{
|
||||
return ip_set_type_register(&bitmap_port_type);
|
||||
}
|
||||
|
||||
static void __exit
|
||||
bitmap_port_fini(void)
|
||||
{
|
||||
ip_set_type_unregister(&bitmap_port_type);
|
||||
}
|
||||
|
||||
module_init(bitmap_port_init);
|
||||
module_exit(bitmap_port_fini);
|
||||
1782
extensions/ipset-6/ip_set_core.c
Normal file
1782
extensions/ipset-6/ip_set_core.c
Normal file
File diff suppressed because it is too large
Load Diff
161
extensions/ipset-6/ip_set_getport.c
Normal file
161
extensions/ipset-6/ip_set_getport.c
Normal file
@@ -0,0 +1,161 @@
|
||||
/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* Get Layer-4 data from the packets */
|
||||
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/icmp.h>
|
||||
#include <linux/icmpv6.h>
|
||||
#include <linux/sctp.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/netfilter_ipv6/ip6_tables.h>
|
||||
#include <net/ip.h>
|
||||
#include <net/ipv6.h>
|
||||
|
||||
#include "ip_set_getport.h"
|
||||
|
||||
/* We must handle non-linear skbs */
|
||||
static bool
|
||||
get_port(const struct sk_buff *skb, int protocol, unsigned int protooff,
|
||||
bool src, __be16 *port, u8 *proto)
|
||||
{
|
||||
switch (protocol) {
|
||||
case IPPROTO_TCP: {
|
||||
struct tcphdr _tcph;
|
||||
const struct tcphdr *th;
|
||||
|
||||
th = skb_header_pointer(skb, protooff, sizeof(_tcph), &_tcph);
|
||||
if (th == NULL)
|
||||
/* No choice either */
|
||||
return false;
|
||||
|
||||
*port = src ? th->source : th->dest;
|
||||
break;
|
||||
}
|
||||
case IPPROTO_SCTP: {
|
||||
sctp_sctphdr_t _sh;
|
||||
const sctp_sctphdr_t *sh;
|
||||
|
||||
sh = skb_header_pointer(skb, protooff, sizeof(_sh), &_sh);
|
||||
if (sh == NULL)
|
||||
/* No choice either */
|
||||
return false;
|
||||
|
||||
*port = src ? sh->source : sh->dest;
|
||||
break;
|
||||
}
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_UDPLITE: {
|
||||
struct udphdr _udph;
|
||||
const struct udphdr *uh;
|
||||
|
||||
uh = skb_header_pointer(skb, protooff, sizeof(_udph), &_udph);
|
||||
if (uh == NULL)
|
||||
/* No choice either */
|
||||
return false;
|
||||
|
||||
*port = src ? uh->source : uh->dest;
|
||||
break;
|
||||
}
|
||||
case IPPROTO_ICMP: {
|
||||
struct icmphdr _ich;
|
||||
const struct icmphdr *ic;
|
||||
|
||||
ic = skb_header_pointer(skb, protooff, sizeof(_ich), &_ich);
|
||||
if (ic == NULL)
|
||||
return false;
|
||||
|
||||
*port = (__force __be16)htons((ic->type << 8) | ic->code);
|
||||
break;
|
||||
}
|
||||
case IPPROTO_ICMPV6: {
|
||||
struct icmp6hdr _ich;
|
||||
const struct icmp6hdr *ic;
|
||||
|
||||
ic = skb_header_pointer(skb, protooff, sizeof(_ich), &_ich);
|
||||
if (ic == NULL)
|
||||
return false;
|
||||
|
||||
*port = (__force __be16)
|
||||
htons((ic->icmp6_type << 8) | ic->icmp6_code);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
*proto = protocol;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ip_set_get_ip4_port(const struct sk_buff *skb, bool src,
|
||||
__be16 *port, u8 *proto)
|
||||
{
|
||||
const struct iphdr *iph = ip_hdr(skb);
|
||||
unsigned int protooff = ip_hdrlen(skb);
|
||||
int protocol = iph->protocol;
|
||||
|
||||
/* See comments at tcp_match in ip_tables.c */
|
||||
if (protocol <= 0 || (ntohs(iph->frag_off) & IP_OFFSET))
|
||||
return false;
|
||||
|
||||
return get_port(skb, protocol, protooff, src, port, proto);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ip_set_get_ip4_port);
|
||||
|
||||
#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
|
||||
bool
|
||||
ip_set_get_ip6_port(const struct sk_buff *skb, bool src,
|
||||
__be16 *port, u8 *proto)
|
||||
{
|
||||
int protoff;
|
||||
u8 nexthdr;
|
||||
__be16 frag_off;
|
||||
|
||||
nexthdr = ipv6_hdr(skb)->nexthdr;
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)
|
||||
protoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr);
|
||||
#else
|
||||
protoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr, &frag_off);
|
||||
#endif
|
||||
if (protoff < 0)
|
||||
return false;
|
||||
|
||||
return get_port(skb, nexthdr, protoff, src, port, proto);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ip_set_get_ip6_port);
|
||||
#endif
|
||||
|
||||
bool
|
||||
ip_set_get_ip_port(const struct sk_buff *skb, u8 pf, bool src, __be16 *port)
|
||||
{
|
||||
bool ret;
|
||||
u8 proto;
|
||||
|
||||
switch (pf) {
|
||||
case NFPROTO_IPV4:
|
||||
ret = ip_set_get_ip4_port(skb, src, port, &proto);
|
||||
break;
|
||||
case NFPROTO_IPV6:
|
||||
ret = ip_set_get_ip6_port(skb, src, port, &proto);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
if (!ret)
|
||||
return ret;
|
||||
switch (proto) {
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_UDP:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ip_set_get_ip_port);
|
||||
33
extensions/ipset-6/ip_set_getport.h
Normal file
33
extensions/ipset-6/ip_set_getport.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef _IP_SET_GETPORT_H
|
||||
#define _IP_SET_GETPORT_H
|
||||
|
||||
extern bool ip_set_get_ip4_port(const struct sk_buff *skb, bool src,
|
||||
__be16 *port, u8 *proto);
|
||||
|
||||
#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
|
||||
extern bool ip_set_get_ip6_port(const struct sk_buff *skb, bool src,
|
||||
__be16 *port, u8 *proto);
|
||||
#else
|
||||
static inline bool ip_set_get_ip6_port(const struct sk_buff *skb, bool src,
|
||||
__be16 *port, u8 *proto)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
extern bool ip_set_get_ip_port(const struct sk_buff *skb, u8 pf, bool src,
|
||||
__be16 *port);
|
||||
|
||||
static inline bool ip_set_proto_with_ports(u8 proto)
|
||||
{
|
||||
switch (proto) {
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_SCTP:
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_UDPLITE:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif /*_IP_SET_GETPORT_H*/
|
||||
30
extensions/ipset-6/ip_set_hash.h
Normal file
30
extensions/ipset-6/ip_set_hash.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef __IP_SET_HASH_H
|
||||
#define __IP_SET_HASH_H
|
||||
|
||||
/* Hash type specific error codes */
|
||||
enum {
|
||||
/* Hash is full */
|
||||
IPSET_ERR_HASH_FULL = IPSET_ERR_TYPE_SPECIFIC,
|
||||
/* Null-valued element */
|
||||
IPSET_ERR_HASH_ELEM,
|
||||
/* Invalid protocol */
|
||||
IPSET_ERR_INVALID_PROTO,
|
||||
/* Protocol missing but must be specified */
|
||||
IPSET_ERR_MISSING_PROTO,
|
||||
/* Range not supported */
|
||||
IPSET_ERR_HASH_RANGE_UNSUPPORTED,
|
||||
/* Invalid range */
|
||||
IPSET_ERR_HASH_RANGE,
|
||||
};
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#define IPSET_DEFAULT_HASHSIZE 1024
|
||||
#define IPSET_MIMINAL_HASHSIZE 64
|
||||
#define IPSET_DEFAULT_MAXELEM 65536
|
||||
#define IPSET_DEFAULT_PROBES 4
|
||||
#define IPSET_DEFAULT_RESIZE 100
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* __IP_SET_HASH_H */
|
||||
481
extensions/ipset-6/ip_set_hash_ip.c
Normal file
481
extensions/ipset-6/ip_set_hash_ip.c
Normal file
@@ -0,0 +1,481 @@
|
||||
/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an IP set type: the hash:ip type */
|
||||
|
||||
#include "jhash.h"
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/random.h>
|
||||
#include <net/ip.h>
|
||||
#include <net/ipv6.h>
|
||||
#include <net/netlink.h>
|
||||
#include <net/tcp.h>
|
||||
|
||||
#include <linux/netfilter.h>
|
||||
#include "pfxlen.h"
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_timeout.h"
|
||||
#include "ip_set_hash.h"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("hash:ip type of IP sets");
|
||||
MODULE_ALIAS("ip_set_hash:ip");
|
||||
|
||||
/* Type specific function prefix */
|
||||
#define TYPE hash_ip
|
||||
|
||||
static bool
|
||||
hash_ip_same_set(const struct ip_set *a, const struct ip_set *b);
|
||||
|
||||
#define hash_ip4_same_set hash_ip_same_set
|
||||
#define hash_ip6_same_set hash_ip_same_set
|
||||
|
||||
/* The type variant functions: IPv4 */
|
||||
|
||||
/* Member elements without timeout */
|
||||
struct hash_ip4_elem {
|
||||
__be32 ip;
|
||||
};
|
||||
|
||||
/* Member elements with timeout support */
|
||||
struct hash_ip4_telem {
|
||||
__be32 ip;
|
||||
unsigned long timeout;
|
||||
};
|
||||
|
||||
static inline bool
|
||||
hash_ip4_data_equal(const struct hash_ip4_elem *ip1,
|
||||
const struct hash_ip4_elem *ip2,
|
||||
u32 *multi)
|
||||
{
|
||||
return ip1->ip == ip2->ip;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_ip4_data_isnull(const struct hash_ip4_elem *elem)
|
||||
{
|
||||
return elem->ip == 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ip4_data_copy(struct hash_ip4_elem *dst, const struct hash_ip4_elem *src)
|
||||
{
|
||||
dst->ip = src->ip;
|
||||
}
|
||||
|
||||
/* Zero valued IP addresses cannot be stored */
|
||||
static inline void
|
||||
hash_ip4_data_zero_out(struct hash_ip4_elem *elem)
|
||||
{
|
||||
elem->ip = 0;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_ip4_data_list(struct sk_buff *skb, const struct hash_ip4_elem *data)
|
||||
{
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_ip4_data_tlist(struct sk_buff *skb, const struct hash_ip4_elem *data)
|
||||
{
|
||||
const struct hash_ip4_telem *tdata =
|
||||
(const struct hash_ip4_telem *)data;
|
||||
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip);
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
|
||||
htonl(ip_set_timeout_get(tdata->timeout)));
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define IP_SET_HASH_WITH_NETMASK
|
||||
#define PF 4
|
||||
#define HOST_MASK 32
|
||||
#include "ip_set_ahash.h"
|
||||
|
||||
static inline void
|
||||
hash_ip4_data_next(struct ip_set_hash *h, const struct hash_ip4_elem *d)
|
||||
{
|
||||
h->next.ip = ntohl(d->ip);
|
||||
}
|
||||
|
||||
static int
|
||||
hash_ip4_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
const struct xt_action_param *par,
|
||||
enum ipset_adt adt, const struct ip_set_adt_opt *opt)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
__be32 ip;
|
||||
|
||||
ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &ip);
|
||||
ip &= ip_set_netmask(h->netmask);
|
||||
if (ip == 0)
|
||||
return -EINVAL;
|
||||
|
||||
return adtfn(set, &ip, opt_timeout(opt, h), opt->cmdflags);
|
||||
}
|
||||
|
||||
static int
|
||||
hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
u32 ip, ip_to, hosts, timeout = h->timeout;
|
||||
__be32 nip;
|
||||
int ret = 0;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ip &= ip_set_hostmask(h->netmask);
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
return -IPSET_ERR_TIMEOUT;
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
if (adt == IPSET_TEST) {
|
||||
nip = htonl(ip);
|
||||
if (nip == 0)
|
||||
return -IPSET_ERR_HASH_ELEM;
|
||||
return adtfn(set, &nip, timeout, flags);
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_IP_TO]) {
|
||||
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (ip > ip_to)
|
||||
swap(ip, ip_to);
|
||||
} else if (tb[IPSET_ATTR_CIDR]) {
|
||||
u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
|
||||
|
||||
if (cidr > 32)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
ip_set_mask_from_to(ip, ip_to, cidr);
|
||||
} else
|
||||
ip_to = ip;
|
||||
|
||||
hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1);
|
||||
|
||||
if (retried)
|
||||
ip = h->next.ip;
|
||||
for (; !before(ip_to, ip); ip += hosts) {
|
||||
nip = htonl(ip);
|
||||
if (nip == 0)
|
||||
return -IPSET_ERR_HASH_ELEM;
|
||||
ret = adtfn(set, &nip, timeout, flags);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_ip_same_set(const struct ip_set *a, const struct ip_set *b)
|
||||
{
|
||||
const struct ip_set_hash *x = a->data;
|
||||
const struct ip_set_hash *y = b->data;
|
||||
|
||||
/* Resizing changes htable_bits, so we ignore it */
|
||||
return x->maxelem == y->maxelem &&
|
||||
x->timeout == y->timeout &&
|
||||
x->netmask == y->netmask;
|
||||
}
|
||||
|
||||
/* The type variant functions: IPv6 */
|
||||
|
||||
struct hash_ip6_elem {
|
||||
union nf_inet_addr ip;
|
||||
};
|
||||
|
||||
struct hash_ip6_telem {
|
||||
union nf_inet_addr ip;
|
||||
unsigned long timeout;
|
||||
};
|
||||
|
||||
static inline bool
|
||||
hash_ip6_data_equal(const struct hash_ip6_elem *ip1,
|
||||
const struct hash_ip6_elem *ip2,
|
||||
u32 *multi)
|
||||
{
|
||||
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_ip6_data_isnull(const struct hash_ip6_elem *elem)
|
||||
{
|
||||
return ipv6_addr_any(&elem->ip.in6);
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ip6_data_copy(struct hash_ip6_elem *dst, const struct hash_ip6_elem *src)
|
||||
{
|
||||
dst->ip.in6 = src->ip.in6;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ip6_data_zero_out(struct hash_ip6_elem *elem)
|
||||
{
|
||||
ipv6_addr_set(&elem->ip.in6, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ip6_netmask(union nf_inet_addr *ip, u8 prefix)
|
||||
{
|
||||
ip->ip6[0] &= ip_set_netmask6(prefix)[0];
|
||||
ip->ip6[1] &= ip_set_netmask6(prefix)[1];
|
||||
ip->ip6[2] &= ip_set_netmask6(prefix)[2];
|
||||
ip->ip6[3] &= ip_set_netmask6(prefix)[3];
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_ip6_data_list(struct sk_buff *skb, const struct hash_ip6_elem *data)
|
||||
{
|
||||
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_ip6_data_tlist(struct sk_buff *skb, const struct hash_ip6_elem *data)
|
||||
{
|
||||
const struct hash_ip6_telem *e =
|
||||
(const struct hash_ip6_telem *)data;
|
||||
|
||||
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
|
||||
htonl(ip_set_timeout_get(e->timeout)));
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
#undef PF
|
||||
#undef HOST_MASK
|
||||
|
||||
#define PF 6
|
||||
#define HOST_MASK 128
|
||||
#include "ip_set_ahash.h"
|
||||
|
||||
static inline void
|
||||
hash_ip6_data_next(struct ip_set_hash *h, const struct hash_ip6_elem *d)
|
||||
{
|
||||
}
|
||||
|
||||
static int
|
||||
hash_ip6_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
const struct xt_action_param *par,
|
||||
enum ipset_adt adt, const struct ip_set_adt_opt *opt)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
union nf_inet_addr ip;
|
||||
|
||||
ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &ip.in6);
|
||||
ip6_netmask(&ip, h->netmask);
|
||||
if (ipv6_addr_any(&ip.in6))
|
||||
return -EINVAL;
|
||||
|
||||
return adtfn(set, &ip, opt_timeout(opt, h), opt->cmdflags);
|
||||
}
|
||||
|
||||
static const struct nla_policy hash_ip6_adt_policy[IPSET_ATTR_ADT_MAX + 1] = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int
|
||||
hash_ip6_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
union nf_inet_addr ip;
|
||||
u32 timeout = h->timeout;
|
||||
int ret;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
|
||||
tb[IPSET_ATTR_IP_TO] ||
|
||||
tb[IPSET_ATTR_CIDR]))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ip6_netmask(&ip, h->netmask);
|
||||
if (ipv6_addr_any(&ip.in6))
|
||||
return -IPSET_ERR_HASH_ELEM;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
return -IPSET_ERR_TIMEOUT;
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
ret = adtfn(set, &ip, timeout, flags);
|
||||
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
/* Create hash:ip type of sets */
|
||||
|
||||
static int
|
||||
hash_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
|
||||
{
|
||||
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
|
||||
u8 netmask, hbits;
|
||||
struct ip_set_hash *h;
|
||||
|
||||
if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
|
||||
return -IPSET_ERR_INVALID_FAMILY;
|
||||
netmask = set->family == NFPROTO_IPV4 ? 32 : 128;
|
||||
pr_debug("Create set %s with family %s\n",
|
||||
set->name, set->family == NFPROTO_IPV4 ? "inet" : "inet6");
|
||||
|
||||
if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_HASHSIZE]) {
|
||||
hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
|
||||
if (hashsize < IPSET_MIMINAL_HASHSIZE)
|
||||
hashsize = IPSET_MIMINAL_HASHSIZE;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_MAXELEM])
|
||||
maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
|
||||
|
||||
if (tb[IPSET_ATTR_NETMASK]) {
|
||||
netmask = nla_get_u8(tb[IPSET_ATTR_NETMASK]);
|
||||
|
||||
if ((set->family == NFPROTO_IPV4 && netmask > 32) ||
|
||||
(set->family == NFPROTO_IPV6 && netmask > 128) ||
|
||||
netmask == 0)
|
||||
return -IPSET_ERR_INVALID_NETMASK;
|
||||
}
|
||||
|
||||
h = kzalloc(sizeof(*h), GFP_KERNEL);
|
||||
if (!h)
|
||||
return -ENOMEM;
|
||||
|
||||
h->maxelem = maxelem;
|
||||
h->netmask = netmask;
|
||||
get_random_bytes(&h->initval, sizeof(h->initval));
|
||||
h->timeout = IPSET_NO_TIMEOUT;
|
||||
|
||||
hbits = htable_bits(hashsize);
|
||||
h->table = ip_set_alloc(
|
||||
sizeof(struct htable)
|
||||
+ jhash_size(hbits) * sizeof(struct hbucket));
|
||||
if (!h->table) {
|
||||
kfree(h);
|
||||
return -ENOMEM;
|
||||
}
|
||||
h->table->htable_bits = hbits;
|
||||
|
||||
set->data = h;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
|
||||
set->variant = set->family == NFPROTO_IPV4
|
||||
? &hash_ip4_tvariant : &hash_ip6_tvariant;
|
||||
|
||||
if (set->family == NFPROTO_IPV4)
|
||||
hash_ip4_gc_init(set);
|
||||
else
|
||||
hash_ip6_gc_init(set);
|
||||
} else {
|
||||
set->variant = set->family == NFPROTO_IPV4
|
||||
? &hash_ip4_variant : &hash_ip6_variant;
|
||||
}
|
||||
|
||||
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
|
||||
set->name, jhash_size(h->table->htable_bits),
|
||||
h->table->htable_bits, h->maxelem, set->data, h->table);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ip_set_type hash_ip_type __read_mostly = {
|
||||
.name = "hash:ip",
|
||||
.protocol = IPSET_PROTOCOL,
|
||||
.features = IPSET_TYPE_IP,
|
||||
.dimension = IPSET_DIM_ONE,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.revision_min = 0,
|
||||
.revision_max = 0,
|
||||
.create = hash_ip_create,
|
||||
.create_policy = {
|
||||
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_PROBES] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_NETMASK] = { .type = NLA_U8 },
|
||||
},
|
||||
.adt_policy = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_CIDR] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
},
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init
|
||||
hash_ip_init(void)
|
||||
{
|
||||
return ip_set_type_register(&hash_ip_type);
|
||||
}
|
||||
|
||||
static void __exit
|
||||
hash_ip_fini(void)
|
||||
{
|
||||
ip_set_type_unregister(&hash_ip_type);
|
||||
}
|
||||
|
||||
module_init(hash_ip_init);
|
||||
module_exit(hash_ip_fini);
|
||||
555
extensions/ipset-6/ip_set_hash_ipport.c
Normal file
555
extensions/ipset-6/ip_set_hash_ipport.c
Normal file
@@ -0,0 +1,555 @@
|
||||
/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an IP set type: the hash:ip,port type */
|
||||
|
||||
#include "jhash.h"
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/random.h>
|
||||
#include <net/ip.h>
|
||||
#include <net/ipv6.h>
|
||||
#include <net/netlink.h>
|
||||
#include <net/tcp.h>
|
||||
|
||||
#include <linux/netfilter.h>
|
||||
#include "pfxlen.h"
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_timeout.h"
|
||||
#include "ip_set_getport.h"
|
||||
#include "ip_set_hash.h"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("hash:ip,port type of IP sets");
|
||||
MODULE_ALIAS("ip_set_hash:ip,port");
|
||||
|
||||
/* Type specific function prefix */
|
||||
#define TYPE hash_ipport
|
||||
|
||||
static bool
|
||||
hash_ipport_same_set(const struct ip_set *a, const struct ip_set *b);
|
||||
|
||||
#define hash_ipport4_same_set hash_ipport_same_set
|
||||
#define hash_ipport6_same_set hash_ipport_same_set
|
||||
|
||||
/* The type variant functions: IPv4 */
|
||||
|
||||
/* Member elements without timeout */
|
||||
struct hash_ipport4_elem {
|
||||
__be32 ip;
|
||||
__be16 port;
|
||||
u8 proto;
|
||||
u8 padding;
|
||||
};
|
||||
|
||||
/* Member elements with timeout support */
|
||||
struct hash_ipport4_telem {
|
||||
__be32 ip;
|
||||
__be16 port;
|
||||
u8 proto;
|
||||
u8 padding;
|
||||
unsigned long timeout;
|
||||
};
|
||||
|
||||
static inline bool
|
||||
hash_ipport4_data_equal(const struct hash_ipport4_elem *ip1,
|
||||
const struct hash_ipport4_elem *ip2,
|
||||
u32 *multi)
|
||||
{
|
||||
return ip1->ip == ip2->ip &&
|
||||
ip1->port == ip2->port &&
|
||||
ip1->proto == ip2->proto;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_ipport4_data_isnull(const struct hash_ipport4_elem *elem)
|
||||
{
|
||||
return elem->proto == 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ipport4_data_copy(struct hash_ipport4_elem *dst,
|
||||
const struct hash_ipport4_elem *src)
|
||||
{
|
||||
dst->ip = src->ip;
|
||||
dst->port = src->port;
|
||||
dst->proto = src->proto;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ipport4_data_zero_out(struct hash_ipport4_elem *elem)
|
||||
{
|
||||
elem->proto = 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_ipport4_data_list(struct sk_buff *skb,
|
||||
const struct hash_ipport4_elem *data)
|
||||
{
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_ipport4_data_tlist(struct sk_buff *skb,
|
||||
const struct hash_ipport4_elem *data)
|
||||
{
|
||||
const struct hash_ipport4_telem *tdata =
|
||||
(const struct hash_ipport4_telem *)data;
|
||||
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip);
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, tdata->port);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
|
||||
htonl(ip_set_timeout_get(tdata->timeout)));
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define PF 4
|
||||
#define HOST_MASK 32
|
||||
#include "ip_set_ahash.h"
|
||||
|
||||
static inline void
|
||||
hash_ipport4_data_next(struct ip_set_hash *h,
|
||||
const struct hash_ipport4_elem *d)
|
||||
{
|
||||
h->next.ip = ntohl(d->ip);
|
||||
h->next.port = ntohs(d->port);
|
||||
}
|
||||
|
||||
static int
|
||||
hash_ipport4_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
const struct xt_action_param *par,
|
||||
enum ipset_adt adt, const struct ip_set_adt_opt *opt)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_ipport4_elem data = { };
|
||||
|
||||
if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
|
||||
&data.port, &data.proto))
|
||||
return -EINVAL;
|
||||
|
||||
ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip);
|
||||
|
||||
return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
|
||||
}
|
||||
|
||||
static int
|
||||
hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_ipport4_elem data = { };
|
||||
u32 ip, ip_to = 0, p = 0, port, port_to;
|
||||
u32 timeout = h->timeout;
|
||||
bool with_ports = false;
|
||||
int ret;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] ||
|
||||
!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (tb[IPSET_ATTR_PORT])
|
||||
data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
|
||||
else
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_PROTO]) {
|
||||
data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
|
||||
with_ports = ip_set_proto_with_ports(data.proto);
|
||||
|
||||
if (data.proto == 0)
|
||||
return -IPSET_ERR_INVALID_PROTO;
|
||||
} else
|
||||
return -IPSET_ERR_MISSING_PROTO;
|
||||
|
||||
if (!(with_ports || data.proto == IPPROTO_ICMP))
|
||||
data.port = 0;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
return -IPSET_ERR_TIMEOUT;
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
if (adt == IPSET_TEST ||
|
||||
!(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
|
||||
tb[IPSET_ATTR_PORT_TO])) {
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
ip = ntohl(data.ip);
|
||||
if (tb[IPSET_ATTR_IP_TO]) {
|
||||
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (ip > ip_to)
|
||||
swap(ip, ip_to);
|
||||
} else if (tb[IPSET_ATTR_CIDR]) {
|
||||
u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
|
||||
|
||||
if (cidr > 32)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
ip_set_mask_from_to(ip, ip_to, cidr);
|
||||
} else
|
||||
ip_to = ip;
|
||||
|
||||
port_to = port = ntohs(data.port);
|
||||
if (with_ports && tb[IPSET_ATTR_PORT_TO]) {
|
||||
port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
|
||||
if (port > port_to)
|
||||
swap(port, port_to);
|
||||
}
|
||||
|
||||
if (retried)
|
||||
ip = h->next.ip;
|
||||
for (; !before(ip_to, ip); ip++) {
|
||||
p = retried && ip == h->next.ip ? h->next.port : port;
|
||||
for (; p <= port_to; p++) {
|
||||
data.ip = htonl(ip);
|
||||
data.port = htons(p);
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_ipport_same_set(const struct ip_set *a, const struct ip_set *b)
|
||||
{
|
||||
const struct ip_set_hash *x = a->data;
|
||||
const struct ip_set_hash *y = b->data;
|
||||
|
||||
/* Resizing changes htable_bits, so we ignore it */
|
||||
return x->maxelem == y->maxelem &&
|
||||
x->timeout == y->timeout;
|
||||
}
|
||||
|
||||
/* The type variant functions: IPv6 */
|
||||
|
||||
struct hash_ipport6_elem {
|
||||
union nf_inet_addr ip;
|
||||
__be16 port;
|
||||
u8 proto;
|
||||
u8 padding;
|
||||
};
|
||||
|
||||
struct hash_ipport6_telem {
|
||||
union nf_inet_addr ip;
|
||||
__be16 port;
|
||||
u8 proto;
|
||||
u8 padding;
|
||||
unsigned long timeout;
|
||||
};
|
||||
|
||||
static inline bool
|
||||
hash_ipport6_data_equal(const struct hash_ipport6_elem *ip1,
|
||||
const struct hash_ipport6_elem *ip2,
|
||||
u32 *multi)
|
||||
{
|
||||
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
|
||||
ip1->port == ip2->port &&
|
||||
ip1->proto == ip2->proto;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_ipport6_data_isnull(const struct hash_ipport6_elem *elem)
|
||||
{
|
||||
return elem->proto == 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ipport6_data_copy(struct hash_ipport6_elem *dst,
|
||||
const struct hash_ipport6_elem *src)
|
||||
{
|
||||
memcpy(dst, src, sizeof(*dst));
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ipport6_data_zero_out(struct hash_ipport6_elem *elem)
|
||||
{
|
||||
elem->proto = 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_ipport6_data_list(struct sk_buff *skb,
|
||||
const struct hash_ipport6_elem *data)
|
||||
{
|
||||
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_ipport6_data_tlist(struct sk_buff *skb,
|
||||
const struct hash_ipport6_elem *data)
|
||||
{
|
||||
const struct hash_ipport6_telem *e =
|
||||
(const struct hash_ipport6_telem *)data;
|
||||
|
||||
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
|
||||
htonl(ip_set_timeout_get(e->timeout)));
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
#undef PF
|
||||
#undef HOST_MASK
|
||||
|
||||
#define PF 6
|
||||
#define HOST_MASK 128
|
||||
#include "ip_set_ahash.h"
|
||||
|
||||
static inline void
|
||||
hash_ipport6_data_next(struct ip_set_hash *h,
|
||||
const struct hash_ipport6_elem *d)
|
||||
{
|
||||
h->next.port = ntohs(d->port);
|
||||
}
|
||||
|
||||
static int
|
||||
hash_ipport6_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
const struct xt_action_param *par,
|
||||
enum ipset_adt adt, const struct ip_set_adt_opt *opt)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_ipport6_elem data = { };
|
||||
|
||||
if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
|
||||
&data.port, &data.proto))
|
||||
return -EINVAL;
|
||||
|
||||
ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
|
||||
|
||||
return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
|
||||
}
|
||||
|
||||
static int
|
||||
hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_ipport6_elem data = { };
|
||||
u32 port, port_to;
|
||||
u32 timeout = h->timeout;
|
||||
bool with_ports = false;
|
||||
int ret;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] ||
|
||||
!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
|
||||
tb[IPSET_ATTR_IP_TO] ||
|
||||
tb[IPSET_ATTR_CIDR]))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (tb[IPSET_ATTR_PORT])
|
||||
data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
|
||||
else
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_PROTO]) {
|
||||
data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
|
||||
with_ports = ip_set_proto_with_ports(data.proto);
|
||||
|
||||
if (data.proto == 0)
|
||||
return -IPSET_ERR_INVALID_PROTO;
|
||||
} else
|
||||
return -IPSET_ERR_MISSING_PROTO;
|
||||
|
||||
if (!(with_ports || data.proto == IPPROTO_ICMPV6))
|
||||
data.port = 0;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
return -IPSET_ERR_TIMEOUT;
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
port = ntohs(data.port);
|
||||
port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
|
||||
if (port > port_to)
|
||||
swap(port, port_to);
|
||||
|
||||
if (retried)
|
||||
port = h->next.port;
|
||||
for (; port <= port_to; port++) {
|
||||
data.port = htons(port);
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Create hash:ip type of sets */
|
||||
|
||||
static int
|
||||
hash_ipport_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
|
||||
{
|
||||
struct ip_set_hash *h;
|
||||
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
|
||||
u8 hbits;
|
||||
|
||||
if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
|
||||
return -IPSET_ERR_INVALID_FAMILY;
|
||||
|
||||
if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_HASHSIZE]) {
|
||||
hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
|
||||
if (hashsize < IPSET_MIMINAL_HASHSIZE)
|
||||
hashsize = IPSET_MIMINAL_HASHSIZE;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_MAXELEM])
|
||||
maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
|
||||
|
||||
h = kzalloc(sizeof(*h), GFP_KERNEL);
|
||||
if (!h)
|
||||
return -ENOMEM;
|
||||
|
||||
h->maxelem = maxelem;
|
||||
get_random_bytes(&h->initval, sizeof(h->initval));
|
||||
h->timeout = IPSET_NO_TIMEOUT;
|
||||
|
||||
hbits = htable_bits(hashsize);
|
||||
h->table = ip_set_alloc(
|
||||
sizeof(struct htable)
|
||||
+ jhash_size(hbits) * sizeof(struct hbucket));
|
||||
if (!h->table) {
|
||||
kfree(h);
|
||||
return -ENOMEM;
|
||||
}
|
||||
h->table->htable_bits = hbits;
|
||||
|
||||
set->data = h;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
|
||||
set->variant = set->family == NFPROTO_IPV4
|
||||
? &hash_ipport4_tvariant : &hash_ipport6_tvariant;
|
||||
|
||||
if (set->family == NFPROTO_IPV4)
|
||||
hash_ipport4_gc_init(set);
|
||||
else
|
||||
hash_ipport6_gc_init(set);
|
||||
} else {
|
||||
set->variant = set->family == NFPROTO_IPV4
|
||||
? &hash_ipport4_variant : &hash_ipport6_variant;
|
||||
}
|
||||
|
||||
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
|
||||
set->name, jhash_size(h->table->htable_bits),
|
||||
h->table->htable_bits, h->maxelem, set->data, h->table);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ip_set_type hash_ipport_type __read_mostly = {
|
||||
.name = "hash:ip,port",
|
||||
.protocol = IPSET_PROTOCOL,
|
||||
.features = IPSET_TYPE_IP | IPSET_TYPE_PORT,
|
||||
.dimension = IPSET_DIM_TWO,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.revision_min = 0,
|
||||
.revision_max = 1, /* SCTP and UDPLITE support added */
|
||||
.create = hash_ipport_create,
|
||||
.create_policy = {
|
||||
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_PROBES] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_PROTO] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
},
|
||||
.adt_policy = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_PORT] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_PORT_TO] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_CIDR] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_PROTO] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
},
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init
|
||||
hash_ipport_init(void)
|
||||
{
|
||||
return ip_set_type_register(&hash_ipport_type);
|
||||
}
|
||||
|
||||
static void __exit
|
||||
hash_ipport_fini(void)
|
||||
{
|
||||
ip_set_type_unregister(&hash_ipport_type);
|
||||
}
|
||||
|
||||
module_init(hash_ipport_init);
|
||||
module_exit(hash_ipport_fini);
|
||||
573
extensions/ipset-6/ip_set_hash_ipportip.c
Normal file
573
extensions/ipset-6/ip_set_hash_ipportip.c
Normal file
@@ -0,0 +1,573 @@
|
||||
/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an IP set type: the hash:ip,port,ip type */
|
||||
|
||||
#include "jhash.h"
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/random.h>
|
||||
#include <net/ip.h>
|
||||
#include <net/ipv6.h>
|
||||
#include <net/netlink.h>
|
||||
#include <net/tcp.h>
|
||||
|
||||
#include <linux/netfilter.h>
|
||||
#include "pfxlen.h"
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_timeout.h"
|
||||
#include "ip_set_getport.h"
|
||||
#include "ip_set_hash.h"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("hash:ip,port,ip type of IP sets");
|
||||
MODULE_ALIAS("ip_set_hash:ip,port,ip");
|
||||
|
||||
/* Type specific function prefix */
|
||||
#define TYPE hash_ipportip
|
||||
|
||||
static bool
|
||||
hash_ipportip_same_set(const struct ip_set *a, const struct ip_set *b);
|
||||
|
||||
#define hash_ipportip4_same_set hash_ipportip_same_set
|
||||
#define hash_ipportip6_same_set hash_ipportip_same_set
|
||||
|
||||
/* The type variant functions: IPv4 */
|
||||
|
||||
/* Member elements without timeout */
|
||||
struct hash_ipportip4_elem {
|
||||
__be32 ip;
|
||||
__be32 ip2;
|
||||
__be16 port;
|
||||
u8 proto;
|
||||
u8 padding;
|
||||
};
|
||||
|
||||
/* Member elements with timeout support */
|
||||
struct hash_ipportip4_telem {
|
||||
__be32 ip;
|
||||
__be32 ip2;
|
||||
__be16 port;
|
||||
u8 proto;
|
||||
u8 padding;
|
||||
unsigned long timeout;
|
||||
};
|
||||
|
||||
static inline bool
|
||||
hash_ipportip4_data_equal(const struct hash_ipportip4_elem *ip1,
|
||||
const struct hash_ipportip4_elem *ip2,
|
||||
u32 *multi)
|
||||
{
|
||||
return ip1->ip == ip2->ip &&
|
||||
ip1->ip2 == ip2->ip2 &&
|
||||
ip1->port == ip2->port &&
|
||||
ip1->proto == ip2->proto;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_ipportip4_data_isnull(const struct hash_ipportip4_elem *elem)
|
||||
{
|
||||
return elem->proto == 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ipportip4_data_copy(struct hash_ipportip4_elem *dst,
|
||||
const struct hash_ipportip4_elem *src)
|
||||
{
|
||||
memcpy(dst, src, sizeof(*dst));
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ipportip4_data_zero_out(struct hash_ipportip4_elem *elem)
|
||||
{
|
||||
elem->proto = 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_ipportip4_data_list(struct sk_buff *skb,
|
||||
const struct hash_ipportip4_elem *data)
|
||||
{
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP2, data->ip2);
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_ipportip4_data_tlist(struct sk_buff *skb,
|
||||
const struct hash_ipportip4_elem *data)
|
||||
{
|
||||
const struct hash_ipportip4_telem *tdata =
|
||||
(const struct hash_ipportip4_telem *)data;
|
||||
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip);
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP2, tdata->ip2);
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, tdata->port);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
|
||||
htonl(ip_set_timeout_get(tdata->timeout)));
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define PF 4
|
||||
#define HOST_MASK 32
|
||||
#include "ip_set_ahash.h"
|
||||
|
||||
static inline void
|
||||
hash_ipportip4_data_next(struct ip_set_hash *h,
|
||||
const struct hash_ipportip4_elem *d)
|
||||
{
|
||||
h->next.ip = ntohl(d->ip);
|
||||
h->next.port = ntohs(d->port);
|
||||
}
|
||||
|
||||
static int
|
||||
hash_ipportip4_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
const struct xt_action_param *par,
|
||||
enum ipset_adt adt, const struct ip_set_adt_opt *opt)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_ipportip4_elem data = { };
|
||||
|
||||
if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
|
||||
&data.port, &data.proto))
|
||||
return -EINVAL;
|
||||
|
||||
ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip);
|
||||
ip4addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &data.ip2);
|
||||
|
||||
return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
|
||||
}
|
||||
|
||||
static int
|
||||
hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_ipportip4_elem data = { };
|
||||
u32 ip, ip_to = 0, p = 0, port, port_to;
|
||||
u32 timeout = h->timeout;
|
||||
bool with_ports = false;
|
||||
int ret;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
|
||||
!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP2], &data.ip2);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (tb[IPSET_ATTR_PORT])
|
||||
data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
|
||||
else
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_PROTO]) {
|
||||
data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
|
||||
with_ports = ip_set_proto_with_ports(data.proto);
|
||||
|
||||
if (data.proto == 0)
|
||||
return -IPSET_ERR_INVALID_PROTO;
|
||||
} else
|
||||
return -IPSET_ERR_MISSING_PROTO;
|
||||
|
||||
if (!(with_ports || data.proto == IPPROTO_ICMP))
|
||||
data.port = 0;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
return -IPSET_ERR_TIMEOUT;
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
if (adt == IPSET_TEST ||
|
||||
!(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
|
||||
tb[IPSET_ATTR_PORT_TO])) {
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
ip = ntohl(data.ip);
|
||||
if (tb[IPSET_ATTR_IP_TO]) {
|
||||
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (ip > ip_to)
|
||||
swap(ip, ip_to);
|
||||
} else if (tb[IPSET_ATTR_CIDR]) {
|
||||
u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
|
||||
|
||||
if (cidr > 32)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
ip_set_mask_from_to(ip, ip_to, cidr);
|
||||
} else
|
||||
ip_to = ip;
|
||||
|
||||
port_to = port = ntohs(data.port);
|
||||
if (with_ports && tb[IPSET_ATTR_PORT_TO]) {
|
||||
port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
|
||||
if (port > port_to)
|
||||
swap(port, port_to);
|
||||
}
|
||||
|
||||
if (retried)
|
||||
ip = h->next.ip;
|
||||
for (; !before(ip_to, ip); ip++) {
|
||||
p = retried && ip == h->next.ip ? h->next.port : port;
|
||||
for (; p <= port_to; p++) {
|
||||
data.ip = htonl(ip);
|
||||
data.port = htons(p);
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_ipportip_same_set(const struct ip_set *a, const struct ip_set *b)
|
||||
{
|
||||
const struct ip_set_hash *x = a->data;
|
||||
const struct ip_set_hash *y = b->data;
|
||||
|
||||
/* Resizing changes htable_bits, so we ignore it */
|
||||
return x->maxelem == y->maxelem &&
|
||||
x->timeout == y->timeout;
|
||||
}
|
||||
|
||||
/* The type variant functions: IPv6 */
|
||||
|
||||
struct hash_ipportip6_elem {
|
||||
union nf_inet_addr ip;
|
||||
union nf_inet_addr ip2;
|
||||
__be16 port;
|
||||
u8 proto;
|
||||
u8 padding;
|
||||
};
|
||||
|
||||
struct hash_ipportip6_telem {
|
||||
union nf_inet_addr ip;
|
||||
union nf_inet_addr ip2;
|
||||
__be16 port;
|
||||
u8 proto;
|
||||
u8 padding;
|
||||
unsigned long timeout;
|
||||
};
|
||||
|
||||
static inline bool
|
||||
hash_ipportip6_data_equal(const struct hash_ipportip6_elem *ip1,
|
||||
const struct hash_ipportip6_elem *ip2,
|
||||
u32 *multi)
|
||||
{
|
||||
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
|
||||
ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 &&
|
||||
ip1->port == ip2->port &&
|
||||
ip1->proto == ip2->proto;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_ipportip6_data_isnull(const struct hash_ipportip6_elem *elem)
|
||||
{
|
||||
return elem->proto == 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ipportip6_data_copy(struct hash_ipportip6_elem *dst,
|
||||
const struct hash_ipportip6_elem *src)
|
||||
{
|
||||
memcpy(dst, src, sizeof(*dst));
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ipportip6_data_zero_out(struct hash_ipportip6_elem *elem)
|
||||
{
|
||||
elem->proto = 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_ipportip6_data_list(struct sk_buff *skb,
|
||||
const struct hash_ipportip6_elem *data)
|
||||
{
|
||||
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
|
||||
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2);
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_ipportip6_data_tlist(struct sk_buff *skb,
|
||||
const struct hash_ipportip6_elem *data)
|
||||
{
|
||||
const struct hash_ipportip6_telem *e =
|
||||
(const struct hash_ipportip6_telem *)data;
|
||||
|
||||
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
|
||||
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2);
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
|
||||
htonl(ip_set_timeout_get(e->timeout)));
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
#undef PF
|
||||
#undef HOST_MASK
|
||||
|
||||
#define PF 6
|
||||
#define HOST_MASK 128
|
||||
#include "ip_set_ahash.h"
|
||||
|
||||
static inline void
|
||||
hash_ipportip6_data_next(struct ip_set_hash *h,
|
||||
const struct hash_ipportip6_elem *d)
|
||||
{
|
||||
h->next.port = ntohs(d->port);
|
||||
}
|
||||
|
||||
static int
|
||||
hash_ipportip6_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
const struct xt_action_param *par,
|
||||
enum ipset_adt adt, const struct ip_set_adt_opt *opt)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_ipportip6_elem data = { };
|
||||
|
||||
if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
|
||||
&data.port, &data.proto))
|
||||
return -EINVAL;
|
||||
|
||||
ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
|
||||
ip6addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &data.ip2.in6);
|
||||
|
||||
return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
|
||||
}
|
||||
|
||||
static int
|
||||
hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_ipportip6_elem data = { };
|
||||
u32 port, port_to;
|
||||
u32 timeout = h->timeout;
|
||||
bool with_ports = false;
|
||||
int ret;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
|
||||
!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
|
||||
tb[IPSET_ATTR_IP_TO] ||
|
||||
tb[IPSET_ATTR_CIDR]))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP2], &data.ip2);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (tb[IPSET_ATTR_PORT])
|
||||
data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
|
||||
else
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_PROTO]) {
|
||||
data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
|
||||
with_ports = ip_set_proto_with_ports(data.proto);
|
||||
|
||||
if (data.proto == 0)
|
||||
return -IPSET_ERR_INVALID_PROTO;
|
||||
} else
|
||||
return -IPSET_ERR_MISSING_PROTO;
|
||||
|
||||
if (!(with_ports || data.proto == IPPROTO_ICMPV6))
|
||||
data.port = 0;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
return -IPSET_ERR_TIMEOUT;
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
port = ntohs(data.port);
|
||||
port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
|
||||
if (port > port_to)
|
||||
swap(port, port_to);
|
||||
|
||||
if (retried)
|
||||
port = h->next.port;
|
||||
for (; port <= port_to; port++) {
|
||||
data.port = htons(port);
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Create hash:ip type of sets */
|
||||
|
||||
static int
|
||||
hash_ipportip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
|
||||
{
|
||||
struct ip_set_hash *h;
|
||||
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
|
||||
u8 hbits;
|
||||
|
||||
if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
|
||||
return -IPSET_ERR_INVALID_FAMILY;
|
||||
|
||||
if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_HASHSIZE]) {
|
||||
hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
|
||||
if (hashsize < IPSET_MIMINAL_HASHSIZE)
|
||||
hashsize = IPSET_MIMINAL_HASHSIZE;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_MAXELEM])
|
||||
maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
|
||||
|
||||
h = kzalloc(sizeof(*h), GFP_KERNEL);
|
||||
if (!h)
|
||||
return -ENOMEM;
|
||||
|
||||
h->maxelem = maxelem;
|
||||
get_random_bytes(&h->initval, sizeof(h->initval));
|
||||
h->timeout = IPSET_NO_TIMEOUT;
|
||||
|
||||
hbits = htable_bits(hashsize);
|
||||
h->table = ip_set_alloc(
|
||||
sizeof(struct htable)
|
||||
+ jhash_size(hbits) * sizeof(struct hbucket));
|
||||
if (!h->table) {
|
||||
kfree(h);
|
||||
return -ENOMEM;
|
||||
}
|
||||
h->table->htable_bits = hbits;
|
||||
|
||||
set->data = h;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
|
||||
set->variant = set->family == NFPROTO_IPV4
|
||||
? &hash_ipportip4_tvariant : &hash_ipportip6_tvariant;
|
||||
|
||||
if (set->family == NFPROTO_IPV4)
|
||||
hash_ipportip4_gc_init(set);
|
||||
else
|
||||
hash_ipportip6_gc_init(set);
|
||||
} else {
|
||||
set->variant = set->family == NFPROTO_IPV4
|
||||
? &hash_ipportip4_variant : &hash_ipportip6_variant;
|
||||
}
|
||||
|
||||
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
|
||||
set->name, jhash_size(h->table->htable_bits),
|
||||
h->table->htable_bits, h->maxelem, set->data, h->table);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ip_set_type hash_ipportip_type __read_mostly = {
|
||||
.name = "hash:ip,port,ip",
|
||||
.protocol = IPSET_PROTOCOL,
|
||||
.features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2,
|
||||
.dimension = IPSET_DIM_THREE,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.revision_min = 0,
|
||||
.revision_max = 1, /* SCTP and UDPLITE support added */
|
||||
.create = hash_ipportip_create,
|
||||
.create_policy = {
|
||||
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_PROBES] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
},
|
||||
.adt_policy = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_IP2] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_PORT] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_PORT_TO] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_CIDR] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_PROTO] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
},
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init
|
||||
hash_ipportip_init(void)
|
||||
{
|
||||
return ip_set_type_register(&hash_ipportip_type);
|
||||
}
|
||||
|
||||
static void __exit
|
||||
hash_ipportip_fini(void)
|
||||
{
|
||||
ip_set_type_unregister(&hash_ipportip_type);
|
||||
}
|
||||
|
||||
module_init(hash_ipportip_init);
|
||||
module_exit(hash_ipportip_fini);
|
||||
665
extensions/ipset-6/ip_set_hash_ipportnet.c
Normal file
665
extensions/ipset-6/ip_set_hash_ipportnet.c
Normal file
@@ -0,0 +1,665 @@
|
||||
/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an IP set type: the hash:ip,port,net type */
|
||||
|
||||
#include "jhash.h"
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/random.h>
|
||||
#include <net/ip.h>
|
||||
#include <net/ipv6.h>
|
||||
#include <net/netlink.h>
|
||||
#include <net/tcp.h>
|
||||
|
||||
#include <linux/netfilter.h>
|
||||
#include "pfxlen.h"
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_timeout.h"
|
||||
#include "ip_set_getport.h"
|
||||
#include "ip_set_hash.h"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("hash:ip,port,net type of IP sets");
|
||||
MODULE_ALIAS("ip_set_hash:ip,port,net");
|
||||
|
||||
/* Type specific function prefix */
|
||||
#define TYPE hash_ipportnet
|
||||
|
||||
static bool
|
||||
hash_ipportnet_same_set(const struct ip_set *a, const struct ip_set *b);
|
||||
|
||||
#define hash_ipportnet4_same_set hash_ipportnet_same_set
|
||||
#define hash_ipportnet6_same_set hash_ipportnet_same_set
|
||||
|
||||
/* The type variant functions: IPv4 */
|
||||
|
||||
/* Member elements without timeout */
|
||||
struct hash_ipportnet4_elem {
|
||||
__be32 ip;
|
||||
__be32 ip2;
|
||||
__be16 port;
|
||||
u8 cidr;
|
||||
u8 proto;
|
||||
};
|
||||
|
||||
/* Member elements with timeout support */
|
||||
struct hash_ipportnet4_telem {
|
||||
__be32 ip;
|
||||
__be32 ip2;
|
||||
__be16 port;
|
||||
u8 cidr;
|
||||
u8 proto;
|
||||
unsigned long timeout;
|
||||
};
|
||||
|
||||
static inline bool
|
||||
hash_ipportnet4_data_equal(const struct hash_ipportnet4_elem *ip1,
|
||||
const struct hash_ipportnet4_elem *ip2,
|
||||
u32 *multi)
|
||||
{
|
||||
return ip1->ip == ip2->ip &&
|
||||
ip1->ip2 == ip2->ip2 &&
|
||||
ip1->cidr == ip2->cidr &&
|
||||
ip1->port == ip2->port &&
|
||||
ip1->proto == ip2->proto;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_ipportnet4_data_isnull(const struct hash_ipportnet4_elem *elem)
|
||||
{
|
||||
return elem->proto == 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ipportnet4_data_copy(struct hash_ipportnet4_elem *dst,
|
||||
const struct hash_ipportnet4_elem *src)
|
||||
{
|
||||
memcpy(dst, src, sizeof(*dst));
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ipportnet4_data_netmask(struct hash_ipportnet4_elem *elem, u8 cidr)
|
||||
{
|
||||
elem->ip2 &= ip_set_netmask(cidr);
|
||||
elem->cidr = cidr;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ipportnet4_data_zero_out(struct hash_ipportnet4_elem *elem)
|
||||
{
|
||||
elem->proto = 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_ipportnet4_data_list(struct sk_buff *skb,
|
||||
const struct hash_ipportnet4_elem *data)
|
||||
{
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP2, data->ip2);
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_ipportnet4_data_tlist(struct sk_buff *skb,
|
||||
const struct hash_ipportnet4_elem *data)
|
||||
{
|
||||
const struct hash_ipportnet4_telem *tdata =
|
||||
(const struct hash_ipportnet4_telem *)data;
|
||||
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip);
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP2, tdata->ip2);
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, tdata->port);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
|
||||
htonl(ip_set_timeout_get(tdata->timeout)));
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define IP_SET_HASH_WITH_PROTO
|
||||
#define IP_SET_HASH_WITH_NETS
|
||||
|
||||
#define PF 4
|
||||
#define HOST_MASK 32
|
||||
#include "ip_set_ahash.h"
|
||||
|
||||
static inline void
|
||||
hash_ipportnet4_data_next(struct ip_set_hash *h,
|
||||
const struct hash_ipportnet4_elem *d)
|
||||
{
|
||||
h->next.ip = ntohl(d->ip);
|
||||
h->next.port = ntohs(d->port);
|
||||
h->next.ip2 = ntohl(d->ip2);
|
||||
}
|
||||
|
||||
static int
|
||||
hash_ipportnet4_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
const struct xt_action_param *par,
|
||||
enum ipset_adt adt, const struct ip_set_adt_opt *opt)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_ipportnet4_elem data = {
|
||||
.cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK
|
||||
};
|
||||
|
||||
if (data.cidr == 0)
|
||||
return -EINVAL;
|
||||
if (adt == IPSET_TEST)
|
||||
data.cidr = HOST_MASK;
|
||||
|
||||
if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
|
||||
&data.port, &data.proto))
|
||||
return -EINVAL;
|
||||
|
||||
ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip);
|
||||
ip4addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &data.ip2);
|
||||
data.ip2 &= ip_set_netmask(data.cidr);
|
||||
|
||||
return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
|
||||
}
|
||||
|
||||
static int
|
||||
hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_ipportnet4_elem data = { .cidr = HOST_MASK };
|
||||
u32 ip, ip_to = 0, p = 0, port, port_to;
|
||||
u32 ip2_from = 0, ip2_to, ip2_last, ip2;
|
||||
u32 timeout = h->timeout;
|
||||
bool with_ports = false;
|
||||
int ret;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
|
||||
!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2], &ip2_from);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (tb[IPSET_ATTR_CIDR2]) {
|
||||
data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR2]);
|
||||
if (!data.cidr)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_PORT])
|
||||
data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
|
||||
else
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_PROTO]) {
|
||||
data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
|
||||
with_ports = ip_set_proto_with_ports(data.proto);
|
||||
|
||||
if (data.proto == 0)
|
||||
return -IPSET_ERR_INVALID_PROTO;
|
||||
} else
|
||||
return -IPSET_ERR_MISSING_PROTO;
|
||||
|
||||
if (!(with_ports || data.proto == IPPROTO_ICMP))
|
||||
data.port = 0;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
return -IPSET_ERR_TIMEOUT;
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
with_ports = with_ports && tb[IPSET_ATTR_PORT_TO];
|
||||
if (adt == IPSET_TEST ||
|
||||
!(tb[IPSET_ATTR_CIDR] || tb[IPSET_ATTR_IP_TO] || with_ports ||
|
||||
tb[IPSET_ATTR_IP2_TO])) {
|
||||
data.ip = htonl(ip);
|
||||
data.ip2 = htonl(ip2_from & ip_set_hostmask(data.cidr));
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_IP_TO]) {
|
||||
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (ip > ip_to)
|
||||
swap(ip, ip_to);
|
||||
} else if (tb[IPSET_ATTR_CIDR]) {
|
||||
u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
|
||||
|
||||
if (cidr > 32)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
ip_set_mask_from_to(ip, ip_to, cidr);
|
||||
}
|
||||
|
||||
port_to = port = ntohs(data.port);
|
||||
if (tb[IPSET_ATTR_PORT_TO]) {
|
||||
port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
|
||||
if (port > port_to)
|
||||
swap(port, port_to);
|
||||
}
|
||||
if (tb[IPSET_ATTR_IP2_TO]) {
|
||||
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2_TO], &ip2_to);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (ip2_from > ip2_to)
|
||||
swap(ip2_from, ip2_to);
|
||||
if (ip2_from + UINT_MAX == ip2_to)
|
||||
return -IPSET_ERR_HASH_RANGE;
|
||||
} else {
|
||||
ip_set_mask_from_to(ip2_from, ip2_to, data.cidr);
|
||||
}
|
||||
|
||||
if (retried)
|
||||
ip = h->next.ip;
|
||||
for (; !before(ip_to, ip); ip++) {
|
||||
data.ip = htonl(ip);
|
||||
p = retried && ip == h->next.ip ? h->next.port : port;
|
||||
for (; p <= port_to; p++) {
|
||||
data.port = htons(p);
|
||||
ip2 = retried && ip == h->next.ip && p == h->next.port
|
||||
? h->next.ip2 : ip2_from;
|
||||
while (!after(ip2, ip2_to)) {
|
||||
data.ip2 = htonl(ip2);
|
||||
ip2_last = ip_set_range_to_cidr(ip2, ip2_to,
|
||||
&data.cidr);
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
else
|
||||
ret = 0;
|
||||
ip2 = ip2_last + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_ipportnet_same_set(const struct ip_set *a, const struct ip_set *b)
|
||||
{
|
||||
const struct ip_set_hash *x = a->data;
|
||||
const struct ip_set_hash *y = b->data;
|
||||
|
||||
/* Resizing changes htable_bits, so we ignore it */
|
||||
return x->maxelem == y->maxelem &&
|
||||
x->timeout == y->timeout;
|
||||
}
|
||||
|
||||
/* The type variant functions: IPv6 */
|
||||
|
||||
struct hash_ipportnet6_elem {
|
||||
union nf_inet_addr ip;
|
||||
union nf_inet_addr ip2;
|
||||
__be16 port;
|
||||
u8 cidr;
|
||||
u8 proto;
|
||||
};
|
||||
|
||||
struct hash_ipportnet6_telem {
|
||||
union nf_inet_addr ip;
|
||||
union nf_inet_addr ip2;
|
||||
__be16 port;
|
||||
u8 cidr;
|
||||
u8 proto;
|
||||
unsigned long timeout;
|
||||
};
|
||||
|
||||
static inline bool
|
||||
hash_ipportnet6_data_equal(const struct hash_ipportnet6_elem *ip1,
|
||||
const struct hash_ipportnet6_elem *ip2,
|
||||
u32 *multi)
|
||||
{
|
||||
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
|
||||
ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 &&
|
||||
ip1->cidr == ip2->cidr &&
|
||||
ip1->port == ip2->port &&
|
||||
ip1->proto == ip2->proto;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_ipportnet6_data_isnull(const struct hash_ipportnet6_elem *elem)
|
||||
{
|
||||
return elem->proto == 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ipportnet6_data_copy(struct hash_ipportnet6_elem *dst,
|
||||
const struct hash_ipportnet6_elem *src)
|
||||
{
|
||||
memcpy(dst, src, sizeof(*dst));
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ipportnet6_data_zero_out(struct hash_ipportnet6_elem *elem)
|
||||
{
|
||||
elem->proto = 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
ip6_netmask(union nf_inet_addr *ip, u8 prefix)
|
||||
{
|
||||
ip->ip6[0] &= ip_set_netmask6(prefix)[0];
|
||||
ip->ip6[1] &= ip_set_netmask6(prefix)[1];
|
||||
ip->ip6[2] &= ip_set_netmask6(prefix)[2];
|
||||
ip->ip6[3] &= ip_set_netmask6(prefix)[3];
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ipportnet6_data_netmask(struct hash_ipportnet6_elem *elem, u8 cidr)
|
||||
{
|
||||
ip6_netmask(&elem->ip2, cidr);
|
||||
elem->cidr = cidr;
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_ipportnet6_data_list(struct sk_buff *skb,
|
||||
const struct hash_ipportnet6_elem *data)
|
||||
{
|
||||
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
|
||||
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2);
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_ipportnet6_data_tlist(struct sk_buff *skb,
|
||||
const struct hash_ipportnet6_elem *data)
|
||||
{
|
||||
const struct hash_ipportnet6_telem *e =
|
||||
(const struct hash_ipportnet6_telem *)data;
|
||||
|
||||
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
|
||||
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2);
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
|
||||
htonl(ip_set_timeout_get(e->timeout)));
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
#undef PF
|
||||
#undef HOST_MASK
|
||||
|
||||
#define PF 6
|
||||
#define HOST_MASK 128
|
||||
#include "ip_set_ahash.h"
|
||||
|
||||
static inline void
|
||||
hash_ipportnet6_data_next(struct ip_set_hash *h,
|
||||
const struct hash_ipportnet6_elem *d)
|
||||
{
|
||||
h->next.port = ntohs(d->port);
|
||||
}
|
||||
|
||||
static int
|
||||
hash_ipportnet6_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
const struct xt_action_param *par,
|
||||
enum ipset_adt adt, const struct ip_set_adt_opt *opt)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_ipportnet6_elem data = {
|
||||
.cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK
|
||||
};
|
||||
|
||||
if (data.cidr == 0)
|
||||
return -EINVAL;
|
||||
if (adt == IPSET_TEST)
|
||||
data.cidr = HOST_MASK;
|
||||
|
||||
if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
|
||||
&data.port, &data.proto))
|
||||
return -EINVAL;
|
||||
|
||||
ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
|
||||
ip6addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &data.ip2.in6);
|
||||
ip6_netmask(&data.ip2, data.cidr);
|
||||
|
||||
return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
|
||||
}
|
||||
|
||||
static int
|
||||
hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_ipportnet6_elem data = { .cidr = HOST_MASK };
|
||||
u32 port, port_to;
|
||||
u32 timeout = h->timeout;
|
||||
bool with_ports = false;
|
||||
int ret;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
|
||||
!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
|
||||
tb[IPSET_ATTR_IP_TO] ||
|
||||
tb[IPSET_ATTR_CIDR]))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
if (unlikely(tb[IPSET_ATTR_IP_TO]))
|
||||
return -IPSET_ERR_HASH_RANGE_UNSUPPORTED;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP2], &data.ip2);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (tb[IPSET_ATTR_CIDR2])
|
||||
data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR2]);
|
||||
|
||||
if (!data.cidr)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
|
||||
ip6_netmask(&data.ip2, data.cidr);
|
||||
|
||||
if (tb[IPSET_ATTR_PORT])
|
||||
data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
|
||||
else
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_PROTO]) {
|
||||
data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
|
||||
with_ports = ip_set_proto_with_ports(data.proto);
|
||||
|
||||
if (data.proto == 0)
|
||||
return -IPSET_ERR_INVALID_PROTO;
|
||||
} else
|
||||
return -IPSET_ERR_MISSING_PROTO;
|
||||
|
||||
if (!(with_ports || data.proto == IPPROTO_ICMPV6))
|
||||
data.port = 0;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
return -IPSET_ERR_TIMEOUT;
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
port = ntohs(data.port);
|
||||
port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
|
||||
if (port > port_to)
|
||||
swap(port, port_to);
|
||||
|
||||
if (retried)
|
||||
port = h->next.port;
|
||||
for (; port <= port_to; port++) {
|
||||
data.port = htons(port);
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Create hash:ip type of sets */
|
||||
|
||||
static int
|
||||
hash_ipportnet_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
|
||||
{
|
||||
struct ip_set_hash *h;
|
||||
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
|
||||
u8 hbits;
|
||||
|
||||
if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
|
||||
return -IPSET_ERR_INVALID_FAMILY;
|
||||
|
||||
if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_HASHSIZE]) {
|
||||
hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
|
||||
if (hashsize < IPSET_MIMINAL_HASHSIZE)
|
||||
hashsize = IPSET_MIMINAL_HASHSIZE;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_MAXELEM])
|
||||
maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
|
||||
|
||||
h = kzalloc(sizeof(*h)
|
||||
+ sizeof(struct ip_set_hash_nets)
|
||||
* (set->family == NFPROTO_IPV4 ? 32 : 128), GFP_KERNEL);
|
||||
if (!h)
|
||||
return -ENOMEM;
|
||||
|
||||
h->maxelem = maxelem;
|
||||
get_random_bytes(&h->initval, sizeof(h->initval));
|
||||
h->timeout = IPSET_NO_TIMEOUT;
|
||||
|
||||
hbits = htable_bits(hashsize);
|
||||
h->table = ip_set_alloc(
|
||||
sizeof(struct htable)
|
||||
+ jhash_size(hbits) * sizeof(struct hbucket));
|
||||
if (!h->table) {
|
||||
kfree(h);
|
||||
return -ENOMEM;
|
||||
}
|
||||
h->table->htable_bits = hbits;
|
||||
|
||||
set->data = h;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
|
||||
set->variant = set->family == NFPROTO_IPV4
|
||||
? &hash_ipportnet4_tvariant
|
||||
: &hash_ipportnet6_tvariant;
|
||||
|
||||
if (set->family == NFPROTO_IPV4)
|
||||
hash_ipportnet4_gc_init(set);
|
||||
else
|
||||
hash_ipportnet6_gc_init(set);
|
||||
} else {
|
||||
set->variant = set->family == NFPROTO_IPV4
|
||||
? &hash_ipportnet4_variant : &hash_ipportnet6_variant;
|
||||
}
|
||||
|
||||
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
|
||||
set->name, jhash_size(h->table->htable_bits),
|
||||
h->table->htable_bits, h->maxelem, set->data, h->table);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ip_set_type hash_ipportnet_type __read_mostly = {
|
||||
.name = "hash:ip,port,net",
|
||||
.protocol = IPSET_PROTOCOL,
|
||||
.features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2,
|
||||
.dimension = IPSET_DIM_THREE,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.revision_min = 0,
|
||||
/* 1 SCTP and UDPLITE support added */
|
||||
.revision_max = 2, /* Range as input support for IPv4 added */
|
||||
.create = hash_ipportnet_create,
|
||||
.create_policy = {
|
||||
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_PROBES] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
},
|
||||
.adt_policy = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_IP2] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_IP2_TO] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_PORT] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_PORT_TO] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_CIDR] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_CIDR2] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_PROTO] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
},
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init
|
||||
hash_ipportnet_init(void)
|
||||
{
|
||||
return ip_set_type_register(&hash_ipportnet_type);
|
||||
}
|
||||
|
||||
static void __exit
|
||||
hash_ipportnet_fini(void)
|
||||
{
|
||||
ip_set_type_unregister(&hash_ipportnet_type);
|
||||
}
|
||||
|
||||
module_init(hash_ipportnet_init);
|
||||
module_exit(hash_ipportnet_fini);
|
||||
508
extensions/ipset-6/ip_set_hash_net.c
Normal file
508
extensions/ipset-6/ip_set_hash_net.c
Normal file
@@ -0,0 +1,508 @@
|
||||
/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an IP set type: the hash:net type */
|
||||
|
||||
#include "jhash.h"
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/random.h>
|
||||
#include <net/ip.h>
|
||||
#include <net/ipv6.h>
|
||||
#include <net/netlink.h>
|
||||
|
||||
#include <linux/netfilter.h>
|
||||
#include "pfxlen.h"
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_timeout.h"
|
||||
#include "ip_set_hash.h"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("hash:net type of IP sets");
|
||||
MODULE_ALIAS("ip_set_hash:net");
|
||||
|
||||
/* Type specific function prefix */
|
||||
#define TYPE hash_net
|
||||
|
||||
static bool
|
||||
hash_net_same_set(const struct ip_set *a, const struct ip_set *b);
|
||||
|
||||
#define hash_net4_same_set hash_net_same_set
|
||||
#define hash_net6_same_set hash_net_same_set
|
||||
|
||||
/* The type variant functions: IPv4 */
|
||||
|
||||
/* Member elements without timeout */
|
||||
struct hash_net4_elem {
|
||||
__be32 ip;
|
||||
u16 padding0;
|
||||
u8 padding1;
|
||||
u8 cidr;
|
||||
};
|
||||
|
||||
/* Member elements with timeout support */
|
||||
struct hash_net4_telem {
|
||||
__be32 ip;
|
||||
u16 padding0;
|
||||
u8 padding1;
|
||||
u8 cidr;
|
||||
unsigned long timeout;
|
||||
};
|
||||
|
||||
static inline bool
|
||||
hash_net4_data_equal(const struct hash_net4_elem *ip1,
|
||||
const struct hash_net4_elem *ip2,
|
||||
u32 *multi)
|
||||
{
|
||||
return ip1->ip == ip2->ip && ip1->cidr == ip2->cidr;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_net4_data_isnull(const struct hash_net4_elem *elem)
|
||||
{
|
||||
return elem->cidr == 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_net4_data_copy(struct hash_net4_elem *dst,
|
||||
const struct hash_net4_elem *src)
|
||||
{
|
||||
dst->ip = src->ip;
|
||||
dst->cidr = src->cidr;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_net4_data_netmask(struct hash_net4_elem *elem, u8 cidr)
|
||||
{
|
||||
elem->ip &= ip_set_netmask(cidr);
|
||||
elem->cidr = cidr;
|
||||
}
|
||||
|
||||
/* Zero CIDR values cannot be stored */
|
||||
static inline void
|
||||
hash_net4_data_zero_out(struct hash_net4_elem *elem)
|
||||
{
|
||||
elem->cidr = 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_net4_data_list(struct sk_buff *skb, const struct hash_net4_elem *data)
|
||||
{
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_net4_data_tlist(struct sk_buff *skb, const struct hash_net4_elem *data)
|
||||
{
|
||||
const struct hash_net4_telem *tdata =
|
||||
(const struct hash_net4_telem *)data;
|
||||
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_CIDR, tdata->cidr);
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
|
||||
htonl(ip_set_timeout_get(tdata->timeout)));
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define IP_SET_HASH_WITH_NETS
|
||||
|
||||
#define PF 4
|
||||
#define HOST_MASK 32
|
||||
#include "ip_set_ahash.h"
|
||||
|
||||
static inline void
|
||||
hash_net4_data_next(struct ip_set_hash *h,
|
||||
const struct hash_net4_elem *d)
|
||||
{
|
||||
h->next.ip = ntohl(d->ip);
|
||||
}
|
||||
|
||||
static int
|
||||
hash_net4_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
const struct xt_action_param *par,
|
||||
enum ipset_adt adt, const struct ip_set_adt_opt *opt)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_net4_elem data = {
|
||||
.cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK
|
||||
};
|
||||
|
||||
if (data.cidr == 0)
|
||||
return -EINVAL;
|
||||
if (adt == IPSET_TEST)
|
||||
data.cidr = HOST_MASK;
|
||||
|
||||
ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip);
|
||||
data.ip &= ip_set_netmask(data.cidr);
|
||||
|
||||
return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
|
||||
}
|
||||
|
||||
static int
|
||||
hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_net4_elem data = { .cidr = HOST_MASK };
|
||||
u32 timeout = h->timeout;
|
||||
u32 ip = 0, ip_to, last;
|
||||
int ret;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (tb[IPSET_ATTR_CIDR]) {
|
||||
data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
|
||||
if (!data.cidr)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
return -IPSET_ERR_TIMEOUT;
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) {
|
||||
data.ip = htonl(ip & ip_set_hostmask(data.cidr));
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
ip_to = ip;
|
||||
if (tb[IPSET_ATTR_IP_TO]) {
|
||||
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (ip_to < ip)
|
||||
swap(ip, ip_to);
|
||||
if (ip + UINT_MAX == ip_to)
|
||||
return -IPSET_ERR_HASH_RANGE;
|
||||
}
|
||||
if (retried)
|
||||
ip = h->next.ip;
|
||||
while (!after(ip, ip_to)) {
|
||||
data.ip = htonl(ip);
|
||||
last = ip_set_range_to_cidr(ip, ip_to, &data.cidr);
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
else
|
||||
ret = 0;
|
||||
ip = last + 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_net_same_set(const struct ip_set *a, const struct ip_set *b)
|
||||
{
|
||||
const struct ip_set_hash *x = a->data;
|
||||
const struct ip_set_hash *y = b->data;
|
||||
|
||||
/* Resizing changes htable_bits, so we ignore it */
|
||||
return x->maxelem == y->maxelem &&
|
||||
x->timeout == y->timeout;
|
||||
}
|
||||
|
||||
/* The type variant functions: IPv6 */
|
||||
|
||||
struct hash_net6_elem {
|
||||
union nf_inet_addr ip;
|
||||
u16 padding0;
|
||||
u8 padding1;
|
||||
u8 cidr;
|
||||
};
|
||||
|
||||
struct hash_net6_telem {
|
||||
union nf_inet_addr ip;
|
||||
u16 padding0;
|
||||
u8 padding1;
|
||||
u8 cidr;
|
||||
unsigned long timeout;
|
||||
};
|
||||
|
||||
static inline bool
|
||||
hash_net6_data_equal(const struct hash_net6_elem *ip1,
|
||||
const struct hash_net6_elem *ip2,
|
||||
u32 *multi)
|
||||
{
|
||||
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
|
||||
ip1->cidr == ip2->cidr;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_net6_data_isnull(const struct hash_net6_elem *elem)
|
||||
{
|
||||
return elem->cidr == 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_net6_data_copy(struct hash_net6_elem *dst,
|
||||
const struct hash_net6_elem *src)
|
||||
{
|
||||
dst->ip.in6 = src->ip.in6;
|
||||
dst->cidr = src->cidr;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_net6_data_zero_out(struct hash_net6_elem *elem)
|
||||
{
|
||||
elem->cidr = 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
ip6_netmask(union nf_inet_addr *ip, u8 prefix)
|
||||
{
|
||||
ip->ip6[0] &= ip_set_netmask6(prefix)[0];
|
||||
ip->ip6[1] &= ip_set_netmask6(prefix)[1];
|
||||
ip->ip6[2] &= ip_set_netmask6(prefix)[2];
|
||||
ip->ip6[3] &= ip_set_netmask6(prefix)[3];
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_net6_data_netmask(struct hash_net6_elem *elem, u8 cidr)
|
||||
{
|
||||
ip6_netmask(&elem->ip, cidr);
|
||||
elem->cidr = cidr;
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_net6_data_list(struct sk_buff *skb, const struct hash_net6_elem *data)
|
||||
{
|
||||
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_net6_data_tlist(struct sk_buff *skb, const struct hash_net6_elem *data)
|
||||
{
|
||||
const struct hash_net6_telem *e =
|
||||
(const struct hash_net6_telem *)data;
|
||||
|
||||
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_CIDR, e->cidr);
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
|
||||
htonl(ip_set_timeout_get(e->timeout)));
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
#undef PF
|
||||
#undef HOST_MASK
|
||||
|
||||
#define PF 6
|
||||
#define HOST_MASK 128
|
||||
#include "ip_set_ahash.h"
|
||||
|
||||
static inline void
|
||||
hash_net6_data_next(struct ip_set_hash *h,
|
||||
const struct hash_net6_elem *d)
|
||||
{
|
||||
}
|
||||
|
||||
static int
|
||||
hash_net6_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
const struct xt_action_param *par,
|
||||
enum ipset_adt adt, const struct ip_set_adt_opt *opt)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_net6_elem data = {
|
||||
.cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK
|
||||
};
|
||||
|
||||
if (data.cidr == 0)
|
||||
return -EINVAL;
|
||||
if (adt == IPSET_TEST)
|
||||
data.cidr = HOST_MASK;
|
||||
|
||||
ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
|
||||
ip6_netmask(&data.ip, data.cidr);
|
||||
|
||||
return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
|
||||
}
|
||||
|
||||
static int
|
||||
hash_net6_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_net6_elem data = { .cidr = HOST_MASK };
|
||||
u32 timeout = h->timeout;
|
||||
int ret;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
if (unlikely(tb[IPSET_ATTR_IP_TO]))
|
||||
return -IPSET_ERR_HASH_RANGE_UNSUPPORTED;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (tb[IPSET_ATTR_CIDR])
|
||||
data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
|
||||
|
||||
if (!data.cidr)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
|
||||
ip6_netmask(&data.ip, data.cidr);
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
return -IPSET_ERR_TIMEOUT;
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
/* Create hash:ip type of sets */
|
||||
|
||||
static int
|
||||
hash_net_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
|
||||
{
|
||||
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
|
||||
struct ip_set_hash *h;
|
||||
u8 hbits;
|
||||
|
||||
if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
|
||||
return -IPSET_ERR_INVALID_FAMILY;
|
||||
|
||||
if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_HASHSIZE]) {
|
||||
hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
|
||||
if (hashsize < IPSET_MIMINAL_HASHSIZE)
|
||||
hashsize = IPSET_MIMINAL_HASHSIZE;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_MAXELEM])
|
||||
maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
|
||||
|
||||
h = kzalloc(sizeof(*h)
|
||||
+ sizeof(struct ip_set_hash_nets)
|
||||
* (set->family == NFPROTO_IPV4 ? 32 : 128), GFP_KERNEL);
|
||||
if (!h)
|
||||
return -ENOMEM;
|
||||
|
||||
h->maxelem = maxelem;
|
||||
get_random_bytes(&h->initval, sizeof(h->initval));
|
||||
h->timeout = IPSET_NO_TIMEOUT;
|
||||
|
||||
hbits = htable_bits(hashsize);
|
||||
h->table = ip_set_alloc(
|
||||
sizeof(struct htable)
|
||||
+ jhash_size(hbits) * sizeof(struct hbucket));
|
||||
if (!h->table) {
|
||||
kfree(h);
|
||||
return -ENOMEM;
|
||||
}
|
||||
h->table->htable_bits = hbits;
|
||||
|
||||
set->data = h;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
|
||||
set->variant = set->family == NFPROTO_IPV4
|
||||
? &hash_net4_tvariant : &hash_net6_tvariant;
|
||||
|
||||
if (set->family == NFPROTO_IPV4)
|
||||
hash_net4_gc_init(set);
|
||||
else
|
||||
hash_net6_gc_init(set);
|
||||
} else {
|
||||
set->variant = set->family == NFPROTO_IPV4
|
||||
? &hash_net4_variant : &hash_net6_variant;
|
||||
}
|
||||
|
||||
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
|
||||
set->name, jhash_size(h->table->htable_bits),
|
||||
h->table->htable_bits, h->maxelem, set->data, h->table);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ip_set_type hash_net_type __read_mostly = {
|
||||
.name = "hash:net",
|
||||
.protocol = IPSET_PROTOCOL,
|
||||
.features = IPSET_TYPE_IP,
|
||||
.dimension = IPSET_DIM_ONE,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.revision_min = 0,
|
||||
.revision_max = 1, /* Range as input support for IPv4 added */
|
||||
.create = hash_net_create,
|
||||
.create_policy = {
|
||||
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_PROBES] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
},
|
||||
.adt_policy = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_CIDR] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
},
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init
|
||||
hash_net_init(void)
|
||||
{
|
||||
return ip_set_type_register(&hash_net_type);
|
||||
}
|
||||
|
||||
static void __exit
|
||||
hash_net_fini(void)
|
||||
{
|
||||
ip_set_type_unregister(&hash_net_type);
|
||||
}
|
||||
|
||||
module_init(hash_net_init);
|
||||
module_exit(hash_net_fini);
|
||||
786
extensions/ipset-6/ip_set_hash_netiface.c
Normal file
786
extensions/ipset-6/ip_set_hash_netiface.c
Normal file
@@ -0,0 +1,786 @@
|
||||
/* Copyright (C) 2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an IP set type: the hash:net,iface type */
|
||||
|
||||
#include "jhash.h"
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/rbtree.h>
|
||||
#include <net/ip.h>
|
||||
#include <net/ipv6.h>
|
||||
#include <net/netlink.h>
|
||||
|
||||
#include <linux/netfilter.h>
|
||||
#include "pfxlen.h"
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_timeout.h"
|
||||
#include "ip_set_hash.h"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("hash:net,iface type of IP sets");
|
||||
MODULE_ALIAS("ip_set_hash:net,iface");
|
||||
|
||||
/* Interface name rbtree */
|
||||
|
||||
struct iface_node {
|
||||
struct rb_node node;
|
||||
char iface[IFNAMSIZ];
|
||||
};
|
||||
|
||||
#define iface_data(n) (rb_entry(n, struct iface_node, node)->iface)
|
||||
|
||||
static inline long
|
||||
ifname_compare(const char *_a, const char *_b)
|
||||
{
|
||||
const long *a = (const long *)_a;
|
||||
const long *b = (const long *)_b;
|
||||
|
||||
BUILD_BUG_ON(IFNAMSIZ > 4 * sizeof(unsigned long));
|
||||
if (a[0] != b[0])
|
||||
return a[0] - b[0];
|
||||
if (IFNAMSIZ > sizeof(long)) {
|
||||
if (a[1] != b[1])
|
||||
return a[1] - b[1];
|
||||
}
|
||||
if (IFNAMSIZ > 2 * sizeof(long)) {
|
||||
if (a[2] != b[2])
|
||||
return a[2] - b[2];
|
||||
}
|
||||
if (IFNAMSIZ > 3 * sizeof(long)) {
|
||||
if (a[3] != b[3])
|
||||
return a[3] - b[3];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
rbtree_destroy(struct rb_root *root)
|
||||
{
|
||||
struct rb_node *p, *n = root->rb_node;
|
||||
struct iface_node *node;
|
||||
|
||||
/* Non-recursive destroy, like in ext3 */
|
||||
while (n) {
|
||||
if (n->rb_left) {
|
||||
n = n->rb_left;
|
||||
continue;
|
||||
}
|
||||
if (n->rb_right) {
|
||||
n = n->rb_right;
|
||||
continue;
|
||||
}
|
||||
p = rb_parent(n);
|
||||
node = rb_entry(n, struct iface_node, node);
|
||||
if (!p)
|
||||
*root = RB_ROOT;
|
||||
else if (p->rb_left == n)
|
||||
p->rb_left = NULL;
|
||||
else if (p->rb_right == n)
|
||||
p->rb_right = NULL;
|
||||
|
||||
kfree(node);
|
||||
n = p;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
iface_test(struct rb_root *root, const char **iface)
|
||||
{
|
||||
struct rb_node *n = root->rb_node;
|
||||
|
||||
while (n) {
|
||||
const char *d = iface_data(n);
|
||||
long res = ifname_compare(*iface, d);
|
||||
|
||||
if (res < 0)
|
||||
n = n->rb_left;
|
||||
else if (res > 0)
|
||||
n = n->rb_right;
|
||||
else {
|
||||
*iface = d;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
iface_add(struct rb_root *root, const char **iface)
|
||||
{
|
||||
struct rb_node **n = &(root->rb_node), *p = NULL;
|
||||
struct iface_node *d;
|
||||
|
||||
while (*n) {
|
||||
char *ifname = iface_data(*n);
|
||||
long res = ifname_compare(*iface, ifname);
|
||||
|
||||
p = *n;
|
||||
if (res < 0)
|
||||
n = &((*n)->rb_left);
|
||||
else if (res > 0)
|
||||
n = &((*n)->rb_right);
|
||||
else {
|
||||
*iface = ifname;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
d = kzalloc(sizeof(*d), GFP_ATOMIC);
|
||||
if (!d)
|
||||
return -ENOMEM;
|
||||
strcpy(d->iface, *iface);
|
||||
|
||||
rb_link_node(&d->node, p, n);
|
||||
rb_insert_color(&d->node, root);
|
||||
|
||||
*iface = d->iface;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Type specific function prefix */
|
||||
#define TYPE hash_netiface
|
||||
|
||||
static bool
|
||||
hash_netiface_same_set(const struct ip_set *a, const struct ip_set *b);
|
||||
|
||||
#define hash_netiface4_same_set hash_netiface_same_set
|
||||
#define hash_netiface6_same_set hash_netiface_same_set
|
||||
|
||||
#define STREQ(a, b) (strcmp(a, b) == 0)
|
||||
|
||||
/* The type variant functions: IPv4 */
|
||||
|
||||
struct hash_netiface4_elem_hashed {
|
||||
__be32 ip;
|
||||
u8 physdev;
|
||||
u8 cidr;
|
||||
u16 padding;
|
||||
};
|
||||
|
||||
#define HKEY_DATALEN sizeof(struct hash_netiface4_elem_hashed)
|
||||
|
||||
/* Member elements without timeout */
|
||||
struct hash_netiface4_elem {
|
||||
__be32 ip;
|
||||
u8 physdev;
|
||||
u8 cidr;
|
||||
u16 padding;
|
||||
const char *iface;
|
||||
};
|
||||
|
||||
/* Member elements with timeout support */
|
||||
struct hash_netiface4_telem {
|
||||
__be32 ip;
|
||||
u8 physdev;
|
||||
u8 cidr;
|
||||
u16 padding;
|
||||
const char *iface;
|
||||
unsigned long timeout;
|
||||
};
|
||||
|
||||
static inline bool
|
||||
hash_netiface4_data_equal(const struct hash_netiface4_elem *ip1,
|
||||
const struct hash_netiface4_elem *ip2,
|
||||
u32 *multi)
|
||||
{
|
||||
return ip1->ip == ip2->ip &&
|
||||
ip1->cidr == ip2->cidr &&
|
||||
(++*multi) &&
|
||||
ip1->physdev == ip2->physdev &&
|
||||
ip1->iface == ip2->iface;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_netiface4_data_isnull(const struct hash_netiface4_elem *elem)
|
||||
{
|
||||
return elem->cidr == 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_netiface4_data_copy(struct hash_netiface4_elem *dst,
|
||||
const struct hash_netiface4_elem *src) {
|
||||
dst->ip = src->ip;
|
||||
dst->cidr = src->cidr;
|
||||
dst->physdev = src->physdev;
|
||||
dst->iface = src->iface;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_netiface4_data_netmask(struct hash_netiface4_elem *elem, u8 cidr)
|
||||
{
|
||||
elem->ip &= ip_set_netmask(cidr);
|
||||
elem->cidr = cidr;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_netiface4_data_zero_out(struct hash_netiface4_elem *elem)
|
||||
{
|
||||
elem->cidr = 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_netiface4_data_list(struct sk_buff *skb,
|
||||
const struct hash_netiface4_elem *data)
|
||||
{
|
||||
u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
|
||||
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
|
||||
NLA_PUT_STRING(skb, IPSET_ATTR_IFACE, data->iface);
|
||||
if (flags)
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, flags);
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_netiface4_data_tlist(struct sk_buff *skb,
|
||||
const struct hash_netiface4_elem *data)
|
||||
{
|
||||
const struct hash_netiface4_telem *tdata =
|
||||
(const struct hash_netiface4_telem *)data;
|
||||
u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
|
||||
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
|
||||
NLA_PUT_STRING(skb, IPSET_ATTR_IFACE, data->iface);
|
||||
if (flags)
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, flags);
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
|
||||
htonl(ip_set_timeout_get(tdata->timeout)));
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define IP_SET_HASH_WITH_NETS
|
||||
#define IP_SET_HASH_WITH_RBTREE
|
||||
#define IP_SET_HASH_WITH_MULTI
|
||||
|
||||
#define PF 4
|
||||
#define HOST_MASK 32
|
||||
#include "ip_set_ahash.h"
|
||||
|
||||
static inline void
|
||||
hash_netiface4_data_next(struct ip_set_hash *h,
|
||||
const struct hash_netiface4_elem *d)
|
||||
{
|
||||
h->next.ip = ntohl(d->ip);
|
||||
}
|
||||
|
||||
static int
|
||||
hash_netiface4_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
const struct xt_action_param *par,
|
||||
enum ipset_adt adt, const struct ip_set_adt_opt *opt)
|
||||
{
|
||||
struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_netiface4_elem data = {
|
||||
.cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK
|
||||
};
|
||||
int ret;
|
||||
|
||||
if (data.cidr == 0)
|
||||
return -EINVAL;
|
||||
if (adt == IPSET_TEST)
|
||||
data.cidr = HOST_MASK;
|
||||
|
||||
ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip);
|
||||
data.ip &= ip_set_netmask(data.cidr);
|
||||
|
||||
#define IFACE(dir) (par->dir ? par->dir->name : NULL)
|
||||
#define PHYSDEV(dir) (nf_bridge->dir ? nf_bridge->dir->name : NULL)
|
||||
#define SRCDIR (opt->flags & IPSET_DIM_TWO_SRC)
|
||||
|
||||
if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
|
||||
#ifdef CONFIG_BRIDGE_NETFILTER
|
||||
const struct nf_bridge_info *nf_bridge = skb->nf_bridge;
|
||||
|
||||
if (!nf_bridge)
|
||||
return -EINVAL;
|
||||
data.iface = SRCDIR ? PHYSDEV(physindev) : PHYSDEV(physoutdev);
|
||||
data.physdev = 1;
|
||||
#else
|
||||
data.iface = NULL;
|
||||
#endif
|
||||
} else
|
||||
data.iface = SRCDIR ? IFACE(in) : IFACE(out);
|
||||
|
||||
if (!data.iface)
|
||||
return -EINVAL;
|
||||
ret = iface_test(&h->rbtree, &data.iface);
|
||||
if (adt == IPSET_ADD) {
|
||||
if (!ret) {
|
||||
ret = iface_add(&h->rbtree, &data.iface);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
} else if (!ret)
|
||||
return ret;
|
||||
|
||||
return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
|
||||
}
|
||||
|
||||
static int
|
||||
hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
|
||||
{
|
||||
struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_netiface4_elem data = { .cidr = HOST_MASK };
|
||||
u32 ip = 0, ip_to, last;
|
||||
u32 timeout = h->timeout;
|
||||
char iface[IFNAMSIZ] = {};
|
||||
int ret;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] ||
|
||||
!tb[IPSET_ATTR_IFACE] ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (tb[IPSET_ATTR_CIDR]) {
|
||||
data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
|
||||
if (!data.cidr)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
return -IPSET_ERR_TIMEOUT;
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
strcpy(iface, nla_data(tb[IPSET_ATTR_IFACE]));
|
||||
data.iface = iface;
|
||||
ret = iface_test(&h->rbtree, &data.iface);
|
||||
if (adt == IPSET_ADD) {
|
||||
if (!ret) {
|
||||
ret = iface_add(&h->rbtree, &data.iface);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
} else if (!ret)
|
||||
return ret;
|
||||
|
||||
if (tb[IPSET_ATTR_CADT_FLAGS]) {
|
||||
u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
|
||||
if (cadt_flags & IPSET_FLAG_PHYSDEV)
|
||||
data.physdev = 1;
|
||||
}
|
||||
|
||||
if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) {
|
||||
data.ip = htonl(ip & ip_set_hostmask(data.cidr));
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_IP_TO]) {
|
||||
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (ip_to < ip)
|
||||
swap(ip, ip_to);
|
||||
if (ip + UINT_MAX == ip_to)
|
||||
return -IPSET_ERR_HASH_RANGE;
|
||||
} else {
|
||||
ip_set_mask_from_to(ip, ip_to, data.cidr);
|
||||
}
|
||||
|
||||
if (retried)
|
||||
ip = h->next.ip;
|
||||
while (!after(ip, ip_to)) {
|
||||
data.ip = htonl(ip);
|
||||
last = ip_set_range_to_cidr(ip, ip_to, &data.cidr);
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
else
|
||||
ret = 0;
|
||||
ip = last + 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_netiface_same_set(const struct ip_set *a, const struct ip_set *b)
|
||||
{
|
||||
const struct ip_set_hash *x = a->data;
|
||||
const struct ip_set_hash *y = b->data;
|
||||
|
||||
/* Resizing changes htable_bits, so we ignore it */
|
||||
return x->maxelem == y->maxelem &&
|
||||
x->timeout == y->timeout;
|
||||
}
|
||||
|
||||
/* The type variant functions: IPv6 */
|
||||
|
||||
struct hash_netiface6_elem_hashed {
|
||||
union nf_inet_addr ip;
|
||||
u8 physdev;
|
||||
u8 cidr;
|
||||
u16 padding;
|
||||
};
|
||||
|
||||
#define HKEY_DATALEN sizeof(struct hash_netiface6_elem_hashed)
|
||||
|
||||
struct hash_netiface6_elem {
|
||||
union nf_inet_addr ip;
|
||||
u8 physdev;
|
||||
u8 cidr;
|
||||
u16 padding;
|
||||
const char *iface;
|
||||
};
|
||||
|
||||
struct hash_netiface6_telem {
|
||||
union nf_inet_addr ip;
|
||||
u8 physdev;
|
||||
u8 cidr;
|
||||
u16 padding;
|
||||
const char *iface;
|
||||
unsigned long timeout;
|
||||
};
|
||||
|
||||
static inline bool
|
||||
hash_netiface6_data_equal(const struct hash_netiface6_elem *ip1,
|
||||
const struct hash_netiface6_elem *ip2,
|
||||
u32 *multi)
|
||||
{
|
||||
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
|
||||
ip1->cidr == ip2->cidr &&
|
||||
(++*multi) &&
|
||||
ip1->physdev == ip2->physdev &&
|
||||
ip1->iface == ip2->iface;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_netiface6_data_isnull(const struct hash_netiface6_elem *elem)
|
||||
{
|
||||
return elem->cidr == 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_netiface6_data_copy(struct hash_netiface6_elem *dst,
|
||||
const struct hash_netiface6_elem *src)
|
||||
{
|
||||
memcpy(dst, src, sizeof(*dst));
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_netiface6_data_zero_out(struct hash_netiface6_elem *elem)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
ip6_netmask(union nf_inet_addr *ip, u8 prefix)
|
||||
{
|
||||
ip->ip6[0] &= ip_set_netmask6(prefix)[0];
|
||||
ip->ip6[1] &= ip_set_netmask6(prefix)[1];
|
||||
ip->ip6[2] &= ip_set_netmask6(prefix)[2];
|
||||
ip->ip6[3] &= ip_set_netmask6(prefix)[3];
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_netiface6_data_netmask(struct hash_netiface6_elem *elem, u8 cidr)
|
||||
{
|
||||
ip6_netmask(&elem->ip, cidr);
|
||||
elem->cidr = cidr;
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_netiface6_data_list(struct sk_buff *skb,
|
||||
const struct hash_netiface6_elem *data)
|
||||
{
|
||||
u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
|
||||
|
||||
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
|
||||
NLA_PUT_STRING(skb, IPSET_ATTR_IFACE, data->iface);
|
||||
if (flags)
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, flags);
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_netiface6_data_tlist(struct sk_buff *skb,
|
||||
const struct hash_netiface6_elem *data)
|
||||
{
|
||||
const struct hash_netiface6_telem *e =
|
||||
(const struct hash_netiface6_telem *)data;
|
||||
u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
|
||||
|
||||
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
|
||||
NLA_PUT_STRING(skb, IPSET_ATTR_IFACE, data->iface);
|
||||
if (flags)
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, flags);
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
|
||||
htonl(ip_set_timeout_get(e->timeout)));
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
#undef PF
|
||||
#undef HOST_MASK
|
||||
|
||||
#define PF 6
|
||||
#define HOST_MASK 128
|
||||
#include "ip_set_ahash.h"
|
||||
|
||||
static inline void
|
||||
hash_netiface6_data_next(struct ip_set_hash *h,
|
||||
const struct hash_netiface6_elem *d)
|
||||
{
|
||||
}
|
||||
|
||||
static int
|
||||
hash_netiface6_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
const struct xt_action_param *par,
|
||||
enum ipset_adt adt, const struct ip_set_adt_opt *opt)
|
||||
{
|
||||
struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_netiface6_elem data = {
|
||||
.cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK
|
||||
};
|
||||
int ret;
|
||||
|
||||
if (data.cidr == 0)
|
||||
return -EINVAL;
|
||||
if (adt == IPSET_TEST)
|
||||
data.cidr = HOST_MASK;
|
||||
|
||||
ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
|
||||
ip6_netmask(&data.ip, data.cidr);
|
||||
|
||||
if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
|
||||
#ifdef CONFIG_BRIDGE_NETFILTER
|
||||
const struct nf_bridge_info *nf_bridge = skb->nf_bridge;
|
||||
|
||||
if (!nf_bridge)
|
||||
return -EINVAL;
|
||||
data.iface = SRCDIR ? PHYSDEV(physindev) : PHYSDEV(physoutdev);
|
||||
data.physdev = 1;
|
||||
#else
|
||||
data.iface = NULL;
|
||||
#endif
|
||||
} else
|
||||
data.iface = SRCDIR ? IFACE(in) : IFACE(out);
|
||||
|
||||
if (!data.iface)
|
||||
return -EINVAL;
|
||||
ret = iface_test(&h->rbtree, &data.iface);
|
||||
if (adt == IPSET_ADD) {
|
||||
if (!ret) {
|
||||
ret = iface_add(&h->rbtree, &data.iface);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
} else if (!ret)
|
||||
return ret;
|
||||
|
||||
return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
|
||||
}
|
||||
|
||||
static int
|
||||
hash_netiface6_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
|
||||
{
|
||||
struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_netiface6_elem data = { .cidr = HOST_MASK };
|
||||
u32 timeout = h->timeout;
|
||||
char iface[IFNAMSIZ] = {};
|
||||
int ret;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] ||
|
||||
!tb[IPSET_ATTR_IFACE] ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
if (unlikely(tb[IPSET_ATTR_IP_TO]))
|
||||
return -IPSET_ERR_HASH_RANGE_UNSUPPORTED;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (tb[IPSET_ATTR_CIDR])
|
||||
data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
|
||||
if (!data.cidr)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
ip6_netmask(&data.ip, data.cidr);
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
return -IPSET_ERR_TIMEOUT;
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
strcpy(iface, nla_data(tb[IPSET_ATTR_IFACE]));
|
||||
data.iface = iface;
|
||||
ret = iface_test(&h->rbtree, &data.iface);
|
||||
if (adt == IPSET_ADD) {
|
||||
if (!ret) {
|
||||
ret = iface_add(&h->rbtree, &data.iface);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
} else if (!ret)
|
||||
return ret;
|
||||
|
||||
if (tb[IPSET_ATTR_CADT_FLAGS]) {
|
||||
u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
|
||||
if (cadt_flags & IPSET_FLAG_PHYSDEV)
|
||||
data.physdev = 1;
|
||||
}
|
||||
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
/* Create hash:ip type of sets */
|
||||
|
||||
static int
|
||||
hash_netiface_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
|
||||
{
|
||||
struct ip_set_hash *h;
|
||||
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
|
||||
u8 hbits;
|
||||
|
||||
if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
|
||||
return -IPSET_ERR_INVALID_FAMILY;
|
||||
|
||||
if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_HASHSIZE]) {
|
||||
hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
|
||||
if (hashsize < IPSET_MIMINAL_HASHSIZE)
|
||||
hashsize = IPSET_MIMINAL_HASHSIZE;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_MAXELEM])
|
||||
maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
|
||||
|
||||
h = kzalloc(sizeof(*h)
|
||||
+ sizeof(struct ip_set_hash_nets)
|
||||
* (set->family == NFPROTO_IPV4 ? 32 : 128), GFP_KERNEL);
|
||||
if (!h)
|
||||
return -ENOMEM;
|
||||
|
||||
h->maxelem = maxelem;
|
||||
get_random_bytes(&h->initval, sizeof(h->initval));
|
||||
h->timeout = IPSET_NO_TIMEOUT;
|
||||
h->ahash_max = AHASH_MAX_SIZE;
|
||||
|
||||
hbits = htable_bits(hashsize);
|
||||
h->table = ip_set_alloc(
|
||||
sizeof(struct htable)
|
||||
+ jhash_size(hbits) * sizeof(struct hbucket));
|
||||
if (!h->table) {
|
||||
kfree(h);
|
||||
return -ENOMEM;
|
||||
}
|
||||
h->table->htable_bits = hbits;
|
||||
h->rbtree = RB_ROOT;
|
||||
|
||||
set->data = h;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
|
||||
set->variant = set->family == NFPROTO_IPV4
|
||||
? &hash_netiface4_tvariant : &hash_netiface6_tvariant;
|
||||
|
||||
if (set->family == NFPROTO_IPV4)
|
||||
hash_netiface4_gc_init(set);
|
||||
else
|
||||
hash_netiface6_gc_init(set);
|
||||
} else {
|
||||
set->variant = set->family == NFPROTO_IPV4
|
||||
? &hash_netiface4_variant : &hash_netiface6_variant;
|
||||
}
|
||||
|
||||
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
|
||||
set->name, jhash_size(h->table->htable_bits),
|
||||
h->table->htable_bits, h->maxelem, set->data, h->table);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ip_set_type hash_netiface_type __read_mostly = {
|
||||
.name = "hash:net,iface",
|
||||
.protocol = IPSET_PROTOCOL,
|
||||
.features = IPSET_TYPE_IP | IPSET_TYPE_IFACE,
|
||||
.dimension = IPSET_DIM_TWO,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.revision_min = 0,
|
||||
.create = hash_netiface_create,
|
||||
.create_policy = {
|
||||
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_PROBES] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_PROTO] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
},
|
||||
.adt_policy = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_IFACE] = { .type = NLA_NUL_STRING,
|
||||
.len = IPSET_MAXNAMELEN - 1 },
|
||||
[IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_CIDR] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
},
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init
|
||||
hash_netiface_init(void)
|
||||
{
|
||||
return ip_set_type_register(&hash_netiface_type);
|
||||
}
|
||||
|
||||
static void __exit
|
||||
hash_netiface_fini(void)
|
||||
{
|
||||
ip_set_type_unregister(&hash_netiface_type);
|
||||
}
|
||||
|
||||
module_init(hash_netiface_init);
|
||||
module_exit(hash_netiface_fini);
|
||||
615
extensions/ipset-6/ip_set_hash_netport.c
Normal file
615
extensions/ipset-6/ip_set_hash_netport.c
Normal file
@@ -0,0 +1,615 @@
|
||||
/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an IP set type: the hash:net,port type */
|
||||
|
||||
#include "jhash.h"
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/random.h>
|
||||
#include <net/ip.h>
|
||||
#include <net/ipv6.h>
|
||||
#include <net/netlink.h>
|
||||
|
||||
#include <linux/netfilter.h>
|
||||
#include "pfxlen.h"
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_timeout.h"
|
||||
#include "ip_set_getport.h"
|
||||
#include "ip_set_hash.h"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("hash:net,port type of IP sets");
|
||||
MODULE_ALIAS("ip_set_hash:net,port");
|
||||
|
||||
/* Type specific function prefix */
|
||||
#define TYPE hash_netport
|
||||
|
||||
static bool
|
||||
hash_netport_same_set(const struct ip_set *a, const struct ip_set *b);
|
||||
|
||||
#define hash_netport4_same_set hash_netport_same_set
|
||||
#define hash_netport6_same_set hash_netport_same_set
|
||||
|
||||
/* The type variant functions: IPv4 */
|
||||
|
||||
/* Member elements without timeout */
|
||||
struct hash_netport4_elem {
|
||||
__be32 ip;
|
||||
__be16 port;
|
||||
u8 proto;
|
||||
u8 cidr;
|
||||
};
|
||||
|
||||
/* Member elements with timeout support */
|
||||
struct hash_netport4_telem {
|
||||
__be32 ip;
|
||||
__be16 port;
|
||||
u8 proto;
|
||||
u8 cidr;
|
||||
unsigned long timeout;
|
||||
};
|
||||
|
||||
static inline bool
|
||||
hash_netport4_data_equal(const struct hash_netport4_elem *ip1,
|
||||
const struct hash_netport4_elem *ip2,
|
||||
u32 *multi)
|
||||
{
|
||||
return ip1->ip == ip2->ip &&
|
||||
ip1->port == ip2->port &&
|
||||
ip1->proto == ip2->proto &&
|
||||
ip1->cidr == ip2->cidr;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_netport4_data_isnull(const struct hash_netport4_elem *elem)
|
||||
{
|
||||
return elem->proto == 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_netport4_data_copy(struct hash_netport4_elem *dst,
|
||||
const struct hash_netport4_elem *src)
|
||||
{
|
||||
dst->ip = src->ip;
|
||||
dst->port = src->port;
|
||||
dst->proto = src->proto;
|
||||
dst->cidr = src->cidr;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_netport4_data_netmask(struct hash_netport4_elem *elem, u8 cidr)
|
||||
{
|
||||
elem->ip &= ip_set_netmask(cidr);
|
||||
elem->cidr = cidr;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_netport4_data_zero_out(struct hash_netport4_elem *elem)
|
||||
{
|
||||
elem->proto = 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_netport4_data_list(struct sk_buff *skb,
|
||||
const struct hash_netport4_elem *data)
|
||||
{
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_netport4_data_tlist(struct sk_buff *skb,
|
||||
const struct hash_netport4_elem *data)
|
||||
{
|
||||
const struct hash_netport4_telem *tdata =
|
||||
(const struct hash_netport4_telem *)data;
|
||||
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip);
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, tdata->port);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
|
||||
htonl(ip_set_timeout_get(tdata->timeout)));
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define IP_SET_HASH_WITH_PROTO
|
||||
#define IP_SET_HASH_WITH_NETS
|
||||
|
||||
#define PF 4
|
||||
#define HOST_MASK 32
|
||||
#include "ip_set_ahash.h"
|
||||
|
||||
static inline void
|
||||
hash_netport4_data_next(struct ip_set_hash *h,
|
||||
const struct hash_netport4_elem *d)
|
||||
{
|
||||
h->next.ip = ntohl(d->ip);
|
||||
h->next.port = ntohs(d->port);
|
||||
}
|
||||
|
||||
static int
|
||||
hash_netport4_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
const struct xt_action_param *par,
|
||||
enum ipset_adt adt, const struct ip_set_adt_opt *opt)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_netport4_elem data = {
|
||||
.cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK
|
||||
};
|
||||
|
||||
if (data.cidr == 0)
|
||||
return -EINVAL;
|
||||
if (adt == IPSET_TEST)
|
||||
data.cidr = HOST_MASK;
|
||||
|
||||
if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
|
||||
&data.port, &data.proto))
|
||||
return -EINVAL;
|
||||
|
||||
ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip);
|
||||
data.ip &= ip_set_netmask(data.cidr);
|
||||
|
||||
return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
|
||||
}
|
||||
|
||||
static int
|
||||
hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_netport4_elem data = { .cidr = HOST_MASK };
|
||||
u32 port, port_to, p = 0, ip = 0, ip_to, last;
|
||||
u32 timeout = h->timeout;
|
||||
bool with_ports = false;
|
||||
int ret;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] ||
|
||||
!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (tb[IPSET_ATTR_CIDR]) {
|
||||
data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
|
||||
if (!data.cidr)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_PORT])
|
||||
data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
|
||||
else
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_PROTO]) {
|
||||
data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
|
||||
with_ports = ip_set_proto_with_ports(data.proto);
|
||||
|
||||
if (data.proto == 0)
|
||||
return -IPSET_ERR_INVALID_PROTO;
|
||||
} else
|
||||
return -IPSET_ERR_MISSING_PROTO;
|
||||
|
||||
if (!(with_ports || data.proto == IPPROTO_ICMP))
|
||||
data.port = 0;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
return -IPSET_ERR_TIMEOUT;
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
with_ports = with_ports && tb[IPSET_ATTR_PORT_TO];
|
||||
if (adt == IPSET_TEST || !(with_ports || tb[IPSET_ATTR_IP_TO])) {
|
||||
data.ip = htonl(ip & ip_set_hostmask(data.cidr));
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
port = port_to = ntohs(data.port);
|
||||
if (tb[IPSET_ATTR_PORT_TO]) {
|
||||
port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
|
||||
if (port_to < port)
|
||||
swap(port, port_to);
|
||||
}
|
||||
if (tb[IPSET_ATTR_IP_TO]) {
|
||||
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (ip_to < ip)
|
||||
swap(ip, ip_to);
|
||||
if (ip + UINT_MAX == ip_to)
|
||||
return -IPSET_ERR_HASH_RANGE;
|
||||
} else {
|
||||
ip_set_mask_from_to(ip, ip_to, data.cidr);
|
||||
}
|
||||
|
||||
if (retried)
|
||||
ip = h->next.ip;
|
||||
while (!after(ip, ip_to)) {
|
||||
data.ip = htonl(ip);
|
||||
last = ip_set_range_to_cidr(ip, ip_to, &data.cidr);
|
||||
p = retried && ip == h->next.ip ? h->next.port : port;
|
||||
for (; p <= port_to; p++) {
|
||||
data.port = htons(p);
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
ip = last + 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_netport_same_set(const struct ip_set *a, const struct ip_set *b)
|
||||
{
|
||||
const struct ip_set_hash *x = a->data;
|
||||
const struct ip_set_hash *y = b->data;
|
||||
|
||||
/* Resizing changes htable_bits, so we ignore it */
|
||||
return x->maxelem == y->maxelem &&
|
||||
x->timeout == y->timeout;
|
||||
}
|
||||
|
||||
/* The type variant functions: IPv6 */
|
||||
|
||||
struct hash_netport6_elem {
|
||||
union nf_inet_addr ip;
|
||||
__be16 port;
|
||||
u8 proto;
|
||||
u8 cidr;
|
||||
};
|
||||
|
||||
struct hash_netport6_telem {
|
||||
union nf_inet_addr ip;
|
||||
__be16 port;
|
||||
u8 proto;
|
||||
u8 cidr;
|
||||
unsigned long timeout;
|
||||
};
|
||||
|
||||
static inline bool
|
||||
hash_netport6_data_equal(const struct hash_netport6_elem *ip1,
|
||||
const struct hash_netport6_elem *ip2,
|
||||
u32 *multi)
|
||||
{
|
||||
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
|
||||
ip1->port == ip2->port &&
|
||||
ip1->proto == ip2->proto &&
|
||||
ip1->cidr == ip2->cidr;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_netport6_data_isnull(const struct hash_netport6_elem *elem)
|
||||
{
|
||||
return elem->proto == 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_netport6_data_copy(struct hash_netport6_elem *dst,
|
||||
const struct hash_netport6_elem *src)
|
||||
{
|
||||
memcpy(dst, src, sizeof(*dst));
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_netport6_data_zero_out(struct hash_netport6_elem *elem)
|
||||
{
|
||||
elem->proto = 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
ip6_netmask(union nf_inet_addr *ip, u8 prefix)
|
||||
{
|
||||
ip->ip6[0] &= ip_set_netmask6(prefix)[0];
|
||||
ip->ip6[1] &= ip_set_netmask6(prefix)[1];
|
||||
ip->ip6[2] &= ip_set_netmask6(prefix)[2];
|
||||
ip->ip6[3] &= ip_set_netmask6(prefix)[3];
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_netport6_data_netmask(struct hash_netport6_elem *elem, u8 cidr)
|
||||
{
|
||||
ip6_netmask(&elem->ip, cidr);
|
||||
elem->cidr = cidr;
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_netport6_data_list(struct sk_buff *skb,
|
||||
const struct hash_netport6_elem *data)
|
||||
{
|
||||
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_netport6_data_tlist(struct sk_buff *skb,
|
||||
const struct hash_netport6_elem *data)
|
||||
{
|
||||
const struct hash_netport6_telem *e =
|
||||
(const struct hash_netport6_telem *)data;
|
||||
|
||||
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
|
||||
htonl(ip_set_timeout_get(e->timeout)));
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
#undef PF
|
||||
#undef HOST_MASK
|
||||
|
||||
#define PF 6
|
||||
#define HOST_MASK 128
|
||||
#include "ip_set_ahash.h"
|
||||
|
||||
static inline void
|
||||
hash_netport6_data_next(struct ip_set_hash *h,
|
||||
const struct hash_netport6_elem *d)
|
||||
{
|
||||
h->next.port = ntohs(d->port);
|
||||
}
|
||||
|
||||
static int
|
||||
hash_netport6_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
const struct xt_action_param *par,
|
||||
enum ipset_adt adt, const struct ip_set_adt_opt *opt)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_netport6_elem data = {
|
||||
.cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK
|
||||
};
|
||||
|
||||
if (data.cidr == 0)
|
||||
return -EINVAL;
|
||||
if (adt == IPSET_TEST)
|
||||
data.cidr = HOST_MASK;
|
||||
|
||||
if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
|
||||
&data.port, &data.proto))
|
||||
return -EINVAL;
|
||||
|
||||
ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
|
||||
ip6_netmask(&data.ip, data.cidr);
|
||||
|
||||
return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
|
||||
}
|
||||
|
||||
static int
|
||||
hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_netport6_elem data = { .cidr = HOST_MASK };
|
||||
u32 port, port_to;
|
||||
u32 timeout = h->timeout;
|
||||
bool with_ports = false;
|
||||
int ret;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] ||
|
||||
!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
if (unlikely(tb[IPSET_ATTR_IP_TO]))
|
||||
return -IPSET_ERR_HASH_RANGE_UNSUPPORTED;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (tb[IPSET_ATTR_CIDR])
|
||||
data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
|
||||
if (!data.cidr)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
ip6_netmask(&data.ip, data.cidr);
|
||||
|
||||
if (tb[IPSET_ATTR_PORT])
|
||||
data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
|
||||
else
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_PROTO]) {
|
||||
data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
|
||||
with_ports = ip_set_proto_with_ports(data.proto);
|
||||
|
||||
if (data.proto == 0)
|
||||
return -IPSET_ERR_INVALID_PROTO;
|
||||
} else
|
||||
return -IPSET_ERR_MISSING_PROTO;
|
||||
|
||||
if (!(with_ports || data.proto == IPPROTO_ICMPV6))
|
||||
data.port = 0;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
return -IPSET_ERR_TIMEOUT;
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
port = ntohs(data.port);
|
||||
port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
|
||||
if (port > port_to)
|
||||
swap(port, port_to);
|
||||
|
||||
if (retried)
|
||||
port = h->next.port;
|
||||
for (; port <= port_to; port++) {
|
||||
data.port = htons(port);
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Create hash:ip type of sets */
|
||||
|
||||
static int
|
||||
hash_netport_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
|
||||
{
|
||||
struct ip_set_hash *h;
|
||||
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
|
||||
u8 hbits;
|
||||
|
||||
if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
|
||||
return -IPSET_ERR_INVALID_FAMILY;
|
||||
|
||||
if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_HASHSIZE]) {
|
||||
hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
|
||||
if (hashsize < IPSET_MIMINAL_HASHSIZE)
|
||||
hashsize = IPSET_MIMINAL_HASHSIZE;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_MAXELEM])
|
||||
maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
|
||||
|
||||
h = kzalloc(sizeof(*h)
|
||||
+ sizeof(struct ip_set_hash_nets)
|
||||
* (set->family == NFPROTO_IPV4 ? 32 : 128), GFP_KERNEL);
|
||||
if (!h)
|
||||
return -ENOMEM;
|
||||
|
||||
h->maxelem = maxelem;
|
||||
get_random_bytes(&h->initval, sizeof(h->initval));
|
||||
h->timeout = IPSET_NO_TIMEOUT;
|
||||
|
||||
hbits = htable_bits(hashsize);
|
||||
h->table = ip_set_alloc(
|
||||
sizeof(struct htable)
|
||||
+ jhash_size(hbits) * sizeof(struct hbucket));
|
||||
if (!h->table) {
|
||||
kfree(h);
|
||||
return -ENOMEM;
|
||||
}
|
||||
h->table->htable_bits = hbits;
|
||||
|
||||
set->data = h;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
|
||||
set->variant = set->family == NFPROTO_IPV4
|
||||
? &hash_netport4_tvariant : &hash_netport6_tvariant;
|
||||
|
||||
if (set->family == NFPROTO_IPV4)
|
||||
hash_netport4_gc_init(set);
|
||||
else
|
||||
hash_netport6_gc_init(set);
|
||||
} else {
|
||||
set->variant = set->family == NFPROTO_IPV4
|
||||
? &hash_netport4_variant : &hash_netport6_variant;
|
||||
}
|
||||
|
||||
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
|
||||
set->name, jhash_size(h->table->htable_bits),
|
||||
h->table->htable_bits, h->maxelem, set->data, h->table);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ip_set_type hash_netport_type __read_mostly = {
|
||||
.name = "hash:net,port",
|
||||
.protocol = IPSET_PROTOCOL,
|
||||
.features = IPSET_TYPE_IP | IPSET_TYPE_PORT,
|
||||
.dimension = IPSET_DIM_TWO,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.revision_min = 0,
|
||||
/* 1 SCTP and UDPLITE support added */
|
||||
.revision_max = 2, /* Range as input support for IPv4 added */
|
||||
.create = hash_netport_create,
|
||||
.create_policy = {
|
||||
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_PROBES] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_PROTO] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
},
|
||||
.adt_policy = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_PORT] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_PORT_TO] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_PROTO] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_CIDR] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
},
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init
|
||||
hash_netport_init(void)
|
||||
{
|
||||
return ip_set_type_register(&hash_netport_type);
|
||||
}
|
||||
|
||||
static void __exit
|
||||
hash_netport_fini(void)
|
||||
{
|
||||
ip_set_type_unregister(&hash_netport_type);
|
||||
}
|
||||
|
||||
module_init(hash_netport_init);
|
||||
module_exit(hash_netport_fini);
|
||||
27
extensions/ipset-6/ip_set_list.h
Normal file
27
extensions/ipset-6/ip_set_list.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef __IP_SET_LIST_H
|
||||
#define __IP_SET_LIST_H
|
||||
|
||||
/* List type specific error codes */
|
||||
enum {
|
||||
/* Set name to be added/deleted/tested does not exist. */
|
||||
IPSET_ERR_NAME = IPSET_ERR_TYPE_SPECIFIC,
|
||||
/* list:set type is not permitted to add */
|
||||
IPSET_ERR_LOOP,
|
||||
/* Missing reference set */
|
||||
IPSET_ERR_BEFORE,
|
||||
/* Reference set does not exist */
|
||||
IPSET_ERR_NAMEREF,
|
||||
/* Set is full */
|
||||
IPSET_ERR_LIST_FULL,
|
||||
/* Reference set is not added to the set */
|
||||
IPSET_ERR_REF_EXIST,
|
||||
};
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#define IP_SET_LIST_DEFAULT_SIZE 8
|
||||
#define IP_SET_LIST_MIN_SIZE 4
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* __IP_SET_LIST_H */
|
||||
611
extensions/ipset-6/ip_set_list_set.c
Normal file
611
extensions/ipset-6/ip_set_list_set.c
Normal file
@@ -0,0 +1,611 @@
|
||||
/* Copyright (C) 2008-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an IP set type: the list:set type */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_timeout.h"
|
||||
#include "ip_set_list.h"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("list:set type of IP sets");
|
||||
MODULE_ALIAS("ip_set_list:set");
|
||||
|
||||
/* Member elements without and with timeout */
|
||||
struct set_elem {
|
||||
ip_set_id_t id;
|
||||
};
|
||||
|
||||
struct set_telem {
|
||||
ip_set_id_t id;
|
||||
unsigned long timeout;
|
||||
};
|
||||
|
||||
/* Type structure */
|
||||
struct list_set {
|
||||
size_t dsize; /* element size */
|
||||
u32 size; /* size of set list array */
|
||||
u32 timeout; /* timeout value */
|
||||
struct timer_list gc; /* garbage collection */
|
||||
struct set_elem members[0]; /* the set members */
|
||||
};
|
||||
|
||||
static inline struct set_elem *
|
||||
list_set_elem(const struct list_set *map, u32 id)
|
||||
{
|
||||
return (struct set_elem *)((void *)map->members + id * map->dsize);
|
||||
}
|
||||
|
||||
static inline struct set_telem *
|
||||
list_set_telem(const struct list_set *map, u32 id)
|
||||
{
|
||||
return (struct set_telem *)((void *)map->members + id * map->dsize);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
list_set_timeout(const struct list_set *map, u32 id)
|
||||
{
|
||||
const struct set_telem *elem = list_set_telem(map, id);
|
||||
|
||||
return ip_set_timeout_test(elem->timeout);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
list_set_expired(const struct list_set *map, u32 id)
|
||||
{
|
||||
const struct set_telem *elem = list_set_telem(map, id);
|
||||
|
||||
return ip_set_timeout_expired(elem->timeout);
|
||||
}
|
||||
|
||||
/* Set list without and with timeout */
|
||||
|
||||
static int
|
||||
list_set_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
const struct xt_action_param *par,
|
||||
enum ipset_adt adt, const struct ip_set_adt_opt *opt)
|
||||
{
|
||||
struct list_set *map = set->data;
|
||||
struct set_elem *elem;
|
||||
u32 i;
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < map->size; i++) {
|
||||
elem = list_set_elem(map, i);
|
||||
if (elem->id == IPSET_INVALID_ID)
|
||||
return 0;
|
||||
if (with_timeout(map->timeout) && list_set_expired(map, i))
|
||||
continue;
|
||||
switch (adt) {
|
||||
case IPSET_TEST:
|
||||
ret = ip_set_test(elem->id, skb, par, opt);
|
||||
if (ret > 0)
|
||||
return ret;
|
||||
break;
|
||||
case IPSET_ADD:
|
||||
ret = ip_set_add(elem->id, skb, par, opt);
|
||||
if (ret == 0)
|
||||
return ret;
|
||||
break;
|
||||
case IPSET_DEL:
|
||||
ret = ip_set_del(elem->id, skb, par, opt);
|
||||
if (ret == 0)
|
||||
return ret;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static bool
|
||||
id_eq(const struct list_set *map, u32 i, ip_set_id_t id)
|
||||
{
|
||||
const struct set_elem *elem;
|
||||
|
||||
if (i < map->size) {
|
||||
elem = list_set_elem(map, i);
|
||||
return elem->id == id;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
id_eq_timeout(const struct list_set *map, u32 i, ip_set_id_t id)
|
||||
{
|
||||
const struct set_elem *elem;
|
||||
|
||||
if (i < map->size) {
|
||||
elem = list_set_elem(map, i);
|
||||
return !!(elem->id == id &&
|
||||
!(with_timeout(map->timeout) &&
|
||||
list_set_expired(map, i)));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
list_elem_add(struct list_set *map, u32 i, ip_set_id_t id)
|
||||
{
|
||||
struct set_elem *e;
|
||||
|
||||
for (; i < map->size; i++) {
|
||||
e = list_set_elem(map, i);
|
||||
swap(e->id, id);
|
||||
if (e->id == IPSET_INVALID_ID)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
list_elem_tadd(struct list_set *map, u32 i, ip_set_id_t id,
|
||||
unsigned long timeout)
|
||||
{
|
||||
struct set_telem *e;
|
||||
|
||||
for (; i < map->size; i++) {
|
||||
e = list_set_telem(map, i);
|
||||
swap(e->id, id);
|
||||
swap(e->timeout, timeout);
|
||||
if (e->id == IPSET_INVALID_ID)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
list_set_add(struct list_set *map, u32 i, ip_set_id_t id,
|
||||
unsigned long timeout)
|
||||
{
|
||||
const struct set_elem *e = list_set_elem(map, i);
|
||||
|
||||
if (i == map->size - 1 && e->id != IPSET_INVALID_ID)
|
||||
/* Last element replaced: e.g. add new,before,last */
|
||||
ip_set_put_byindex(e->id);
|
||||
if (with_timeout(map->timeout))
|
||||
list_elem_tadd(map, i, id, ip_set_timeout_set(timeout));
|
||||
else
|
||||
list_elem_add(map, i, id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
list_set_del(struct list_set *map, u32 i)
|
||||
{
|
||||
struct set_elem *a = list_set_elem(map, i), *b;
|
||||
|
||||
ip_set_put_byindex(a->id);
|
||||
|
||||
for (; i < map->size - 1; i++) {
|
||||
b = list_set_elem(map, i + 1);
|
||||
a->id = b->id;
|
||||
if (with_timeout(map->timeout))
|
||||
((struct set_telem *)a)->timeout =
|
||||
((struct set_telem *)b)->timeout;
|
||||
a = b;
|
||||
if (a->id == IPSET_INVALID_ID)
|
||||
break;
|
||||
}
|
||||
/* Last element */
|
||||
a->id = IPSET_INVALID_ID;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
cleanup_entries(struct list_set *map)
|
||||
{
|
||||
struct set_telem *e;
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < map->size; i++) {
|
||||
e = list_set_telem(map, i);
|
||||
if (e->id != IPSET_INVALID_ID && list_set_expired(map, i))
|
||||
list_set_del(map, i);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
list_set_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
|
||||
{
|
||||
struct list_set *map = set->data;
|
||||
bool with_timeout = with_timeout(map->timeout);
|
||||
bool flag_exist = flags & IPSET_FLAG_EXIST;
|
||||
int before = 0;
|
||||
u32 timeout = map->timeout;
|
||||
ip_set_id_t id, refid = IPSET_INVALID_ID;
|
||||
const struct set_elem *elem;
|
||||
struct ip_set *s;
|
||||
u32 i;
|
||||
int ret = 0;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_NAME] ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
id = ip_set_get_byname(nla_data(tb[IPSET_ATTR_NAME]), &s);
|
||||
if (id == IPSET_INVALID_ID)
|
||||
return -IPSET_ERR_NAME;
|
||||
/* "Loop detection" */
|
||||
if (s->type->features & IPSET_TYPE_NAME) {
|
||||
ret = -IPSET_ERR_LOOP;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_CADT_FLAGS]) {
|
||||
u32 f = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
|
||||
before = f & IPSET_FLAG_BEFORE;
|
||||
}
|
||||
|
||||
if (before && !tb[IPSET_ATTR_NAMEREF]) {
|
||||
ret = -IPSET_ERR_BEFORE;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_NAMEREF]) {
|
||||
refid = ip_set_get_byname(nla_data(tb[IPSET_ATTR_NAMEREF]),
|
||||
&s);
|
||||
if (refid == IPSET_INVALID_ID) {
|
||||
ret = -IPSET_ERR_NAMEREF;
|
||||
goto finish;
|
||||
}
|
||||
if (!before)
|
||||
before = -1;
|
||||
}
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout) {
|
||||
ret = -IPSET_ERR_TIMEOUT;
|
||||
goto finish;
|
||||
}
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
if (with_timeout && adt != IPSET_TEST)
|
||||
cleanup_entries(map);
|
||||
|
||||
switch (adt) {
|
||||
case IPSET_TEST:
|
||||
for (i = 0; i < map->size && !ret; i++) {
|
||||
elem = list_set_elem(map, i);
|
||||
if (elem->id == IPSET_INVALID_ID ||
|
||||
(before != 0 && i + 1 >= map->size))
|
||||
break;
|
||||
else if (with_timeout && list_set_expired(map, i))
|
||||
continue;
|
||||
else if (before > 0 && elem->id == id)
|
||||
ret = id_eq_timeout(map, i + 1, refid);
|
||||
else if (before < 0 && elem->id == refid)
|
||||
ret = id_eq_timeout(map, i + 1, id);
|
||||
else if (before == 0 && elem->id == id)
|
||||
ret = 1;
|
||||
}
|
||||
break;
|
||||
case IPSET_ADD:
|
||||
for (i = 0; i < map->size; i++) {
|
||||
elem = list_set_elem(map, i);
|
||||
if (elem->id != id)
|
||||
continue;
|
||||
if (!(with_timeout && flag_exist)) {
|
||||
ret = -IPSET_ERR_EXIST;
|
||||
goto finish;
|
||||
} else {
|
||||
struct set_telem *e = list_set_telem(map, i);
|
||||
|
||||
if ((before > 1 &&
|
||||
!id_eq(map, i + 1, refid)) ||
|
||||
(before < 0 &&
|
||||
(i == 0 || !id_eq(map, i - 1, refid)))) {
|
||||
ret = -IPSET_ERR_EXIST;
|
||||
goto finish;
|
||||
}
|
||||
e->timeout = ip_set_timeout_set(timeout);
|
||||
ip_set_put_byindex(id);
|
||||
ret = 0;
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
ret = -IPSET_ERR_LIST_FULL;
|
||||
for (i = 0; i < map->size && ret == -IPSET_ERR_LIST_FULL; i++) {
|
||||
elem = list_set_elem(map, i);
|
||||
if (elem->id == IPSET_INVALID_ID)
|
||||
ret = before != 0 ? -IPSET_ERR_REF_EXIST
|
||||
: list_set_add(map, i, id, timeout);
|
||||
else if (elem->id != refid)
|
||||
continue;
|
||||
else if (before > 0)
|
||||
ret = list_set_add(map, i, id, timeout);
|
||||
else if (i + 1 < map->size)
|
||||
ret = list_set_add(map, i + 1, id, timeout);
|
||||
}
|
||||
break;
|
||||
case IPSET_DEL:
|
||||
ret = -IPSET_ERR_EXIST;
|
||||
for (i = 0; i < map->size && ret == -IPSET_ERR_EXIST; i++) {
|
||||
elem = list_set_elem(map, i);
|
||||
if (elem->id == IPSET_INVALID_ID) {
|
||||
ret = before != 0 ? -IPSET_ERR_REF_EXIST
|
||||
: -IPSET_ERR_EXIST;
|
||||
break;
|
||||
} else if (elem->id == id &&
|
||||
(before == 0 ||
|
||||
(before > 0 && id_eq(map, i + 1, refid))))
|
||||
ret = list_set_del(map, i);
|
||||
else if (elem->id == refid &&
|
||||
before < 0 && id_eq(map, i + 1, id))
|
||||
ret = list_set_del(map, i + 1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
finish:
|
||||
if (refid != IPSET_INVALID_ID)
|
||||
ip_set_put_byindex(refid);
|
||||
if (adt != IPSET_ADD || ret)
|
||||
ip_set_put_byindex(id);
|
||||
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
static void
|
||||
list_set_flush(struct ip_set *set)
|
||||
{
|
||||
struct list_set *map = set->data;
|
||||
struct set_elem *elem;
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < map->size; i++) {
|
||||
elem = list_set_elem(map, i);
|
||||
if (elem->id != IPSET_INVALID_ID) {
|
||||
ip_set_put_byindex(elem->id);
|
||||
elem->id = IPSET_INVALID_ID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
list_set_destroy(struct ip_set *set)
|
||||
{
|
||||
struct list_set *map = set->data;
|
||||
|
||||
if (with_timeout(map->timeout))
|
||||
del_timer_sync(&map->gc);
|
||||
list_set_flush(set);
|
||||
kfree(map);
|
||||
|
||||
set->data = NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
list_set_head(struct ip_set *set, struct sk_buff *skb)
|
||||
{
|
||||
const struct list_set *map = set->data;
|
||||
struct nlattr *nested;
|
||||
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested)
|
||||
goto nla_put_failure;
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_SIZE, htonl(map->size));
|
||||
if (with_timeout(map->timeout))
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
|
||||
htonl(sizeof(*map) + map->size * map->dsize));
|
||||
ipset_nest_end(skb, nested);
|
||||
|
||||
return 0;
|
||||
nla_put_failure:
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static int
|
||||
list_set_list(const struct ip_set *set,
|
||||
struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
const struct list_set *map = set->data;
|
||||
struct nlattr *atd, *nested;
|
||||
u32 i, first = cb->args[2];
|
||||
const struct set_elem *e;
|
||||
|
||||
atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
|
||||
if (!atd)
|
||||
return -EMSGSIZE;
|
||||
for (; cb->args[2] < map->size; cb->args[2]++) {
|
||||
i = cb->args[2];
|
||||
e = list_set_elem(map, i);
|
||||
if (e->id == IPSET_INVALID_ID)
|
||||
goto finish;
|
||||
if (with_timeout(map->timeout) && list_set_expired(map, i))
|
||||
continue;
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested) {
|
||||
if (i == first) {
|
||||
nla_nest_cancel(skb, atd);
|
||||
return -EMSGSIZE;
|
||||
} else
|
||||
goto nla_put_failure;
|
||||
}
|
||||
NLA_PUT_STRING(skb, IPSET_ATTR_NAME,
|
||||
ip_set_name_byindex(e->id));
|
||||
if (with_timeout(map->timeout)) {
|
||||
const struct set_telem *te =
|
||||
(const struct set_telem *) e;
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
|
||||
htonl(ip_set_timeout_get(te->timeout)));
|
||||
}
|
||||
ipset_nest_end(skb, nested);
|
||||
}
|
||||
finish:
|
||||
ipset_nest_end(skb, atd);
|
||||
/* Set listing finished */
|
||||
cb->args[2] = 0;
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
nla_nest_cancel(skb, nested);
|
||||
ipset_nest_end(skb, atd);
|
||||
if (unlikely(i == first)) {
|
||||
cb->args[2] = 0;
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
list_set_same_set(const struct ip_set *a, const struct ip_set *b)
|
||||
{
|
||||
const struct list_set *x = a->data;
|
||||
const struct list_set *y = b->data;
|
||||
|
||||
return x->size == y->size &&
|
||||
x->timeout == y->timeout;
|
||||
}
|
||||
|
||||
static const struct ip_set_type_variant list_set = {
|
||||
.kadt = list_set_kadt,
|
||||
.uadt = list_set_uadt,
|
||||
.destroy = list_set_destroy,
|
||||
.flush = list_set_flush,
|
||||
.head = list_set_head,
|
||||
.list = list_set_list,
|
||||
.same_set = list_set_same_set,
|
||||
};
|
||||
|
||||
static void
|
||||
list_set_gc(unsigned long ul_set)
|
||||
{
|
||||
struct ip_set *set = (struct ip_set *) ul_set;
|
||||
struct list_set *map = set->data;
|
||||
|
||||
write_lock_bh(&set->lock);
|
||||
cleanup_entries(map);
|
||||
write_unlock_bh(&set->lock);
|
||||
|
||||
map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
|
||||
add_timer(&map->gc);
|
||||
}
|
||||
|
||||
static void
|
||||
list_set_gc_init(struct ip_set *set)
|
||||
{
|
||||
struct list_set *map = set->data;
|
||||
|
||||
init_timer(&map->gc);
|
||||
map->gc.data = (unsigned long) set;
|
||||
map->gc.function = list_set_gc;
|
||||
map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
|
||||
add_timer(&map->gc);
|
||||
}
|
||||
|
||||
/* Create list:set type of sets */
|
||||
|
||||
static bool
|
||||
init_list_set(struct ip_set *set, u32 size, size_t dsize,
|
||||
unsigned long timeout)
|
||||
{
|
||||
struct list_set *map;
|
||||
struct set_elem *e;
|
||||
u32 i;
|
||||
|
||||
map = kzalloc(sizeof(*map) + size * dsize, GFP_KERNEL);
|
||||
if (!map)
|
||||
return false;
|
||||
|
||||
map->size = size;
|
||||
map->dsize = dsize;
|
||||
map->timeout = timeout;
|
||||
set->data = map;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
e = list_set_elem(map, i);
|
||||
e->id = IPSET_INVALID_ID;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
list_set_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
|
||||
{
|
||||
u32 size = IP_SET_LIST_DEFAULT_SIZE;
|
||||
|
||||
if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_SIZE) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_SIZE])
|
||||
size = ip_set_get_h32(tb[IPSET_ATTR_SIZE]);
|
||||
if (size < IP_SET_LIST_MIN_SIZE)
|
||||
size = IP_SET_LIST_MIN_SIZE;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!init_list_set(set, size, sizeof(struct set_telem),
|
||||
ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT])))
|
||||
return -ENOMEM;
|
||||
|
||||
list_set_gc_init(set);
|
||||
} else {
|
||||
if (!init_list_set(set, size, sizeof(struct set_elem),
|
||||
IPSET_NO_TIMEOUT))
|
||||
return -ENOMEM;
|
||||
}
|
||||
set->variant = &list_set;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ip_set_type list_set_type __read_mostly = {
|
||||
.name = "list:set",
|
||||
.protocol = IPSET_PROTOCOL,
|
||||
.features = IPSET_TYPE_NAME | IPSET_DUMP_LAST,
|
||||
.dimension = IPSET_DIM_ONE,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.revision_min = 0,
|
||||
.revision_max = 0,
|
||||
.create = list_set_create,
|
||||
.create_policy = {
|
||||
[IPSET_ATTR_SIZE] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
},
|
||||
.adt_policy = {
|
||||
[IPSET_ATTR_NAME] = { .type = NLA_STRING,
|
||||
.len = IPSET_MAXNAMELEN },
|
||||
[IPSET_ATTR_NAMEREF] = { .type = NLA_STRING,
|
||||
.len = IPSET_MAXNAMELEN },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
|
||||
},
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init
|
||||
list_set_init(void)
|
||||
{
|
||||
return ip_set_type_register(&list_set_type);
|
||||
}
|
||||
|
||||
static void __exit
|
||||
list_set_fini(void)
|
||||
{
|
||||
ip_set_type_unregister(&list_set_type);
|
||||
}
|
||||
|
||||
module_init(list_set_init);
|
||||
module_exit(list_set_fini);
|
||||
132
extensions/ipset-6/ip_set_timeout.h
Normal file
132
extensions/ipset-6/ip_set_timeout.h
Normal file
@@ -0,0 +1,132 @@
|
||||
#ifndef _IP_SET_TIMEOUT_H
|
||||
#define _IP_SET_TIMEOUT_H
|
||||
|
||||
/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
/* How often should the gc be run by default */
|
||||
#define IPSET_GC_TIME (3 * 60)
|
||||
|
||||
/* Timeout period depending on the timeout value of the given set */
|
||||
#define IPSET_GC_PERIOD(timeout) \
|
||||
((timeout/3) ? min_t(u32, (timeout)/3, IPSET_GC_TIME) : 1)
|
||||
|
||||
/* Set is defined without timeout support: timeout value may be 0 */
|
||||
#define IPSET_NO_TIMEOUT UINT_MAX
|
||||
|
||||
#define with_timeout(timeout) ((timeout) != IPSET_NO_TIMEOUT)
|
||||
|
||||
#define opt_timeout(opt, map) \
|
||||
(with_timeout((opt)->timeout) ? (opt)->timeout : (map)->timeout)
|
||||
|
||||
static inline unsigned int
|
||||
ip_set_timeout_uget(struct nlattr *tb)
|
||||
{
|
||||
unsigned int timeout = ip_set_get_h32(tb);
|
||||
|
||||
/* Userspace supplied TIMEOUT parameter: adjust crazy size */
|
||||
return timeout == IPSET_NO_TIMEOUT ? IPSET_NO_TIMEOUT - 1 : timeout;
|
||||
}
|
||||
|
||||
#ifdef IP_SET_BITMAP_TIMEOUT
|
||||
|
||||
/* Bitmap specific timeout constants and macros for the entries */
|
||||
|
||||
/* Bitmap entry is unset */
|
||||
#define IPSET_ELEM_UNSET 0
|
||||
/* Bitmap entry is set with no timeout value */
|
||||
#define IPSET_ELEM_PERMANENT (UINT_MAX/2)
|
||||
|
||||
static inline bool
|
||||
ip_set_timeout_test(unsigned long timeout)
|
||||
{
|
||||
return timeout != IPSET_ELEM_UNSET &&
|
||||
(timeout == IPSET_ELEM_PERMANENT ||
|
||||
time_is_after_jiffies(timeout));
|
||||
}
|
||||
|
||||
static inline bool
|
||||
ip_set_timeout_expired(unsigned long timeout)
|
||||
{
|
||||
return timeout != IPSET_ELEM_UNSET &&
|
||||
timeout != IPSET_ELEM_PERMANENT &&
|
||||
time_is_before_jiffies(timeout);
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
ip_set_timeout_set(u32 timeout)
|
||||
{
|
||||
unsigned long t;
|
||||
|
||||
if (!timeout)
|
||||
return IPSET_ELEM_PERMANENT;
|
||||
|
||||
t = msecs_to_jiffies(timeout * 1000) + jiffies;
|
||||
if (t == IPSET_ELEM_UNSET || t == IPSET_ELEM_PERMANENT)
|
||||
/* Bingo! */
|
||||
t++;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static inline u32
|
||||
ip_set_timeout_get(unsigned long timeout)
|
||||
{
|
||||
return timeout == IPSET_ELEM_PERMANENT ? 0 :
|
||||
jiffies_to_msecs(timeout - jiffies)/1000;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* Hash specific timeout constants and macros for the entries */
|
||||
|
||||
/* Hash entry is set with no timeout value */
|
||||
#define IPSET_ELEM_PERMANENT 0
|
||||
|
||||
static inline bool
|
||||
ip_set_timeout_test(unsigned long timeout)
|
||||
{
|
||||
return timeout == IPSET_ELEM_PERMANENT ||
|
||||
time_is_after_jiffies(timeout);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
ip_set_timeout_expired(unsigned long timeout)
|
||||
{
|
||||
return timeout != IPSET_ELEM_PERMANENT &&
|
||||
time_is_before_jiffies(timeout);
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
ip_set_timeout_set(u32 timeout)
|
||||
{
|
||||
unsigned long t;
|
||||
|
||||
if (!timeout)
|
||||
return IPSET_ELEM_PERMANENT;
|
||||
|
||||
t = msecs_to_jiffies(timeout * 1000) + jiffies;
|
||||
if (t == IPSET_ELEM_PERMANENT)
|
||||
/* Bingo! :-) */
|
||||
t++;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static inline u32
|
||||
ip_set_timeout_get(unsigned long timeout)
|
||||
{
|
||||
return timeout == IPSET_ELEM_PERMANENT ? 0 :
|
||||
jiffies_to_msecs(timeout - jiffies)/1000;
|
||||
}
|
||||
#endif /* ! IP_SET_BITMAP_TIMEOUT */
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* _IP_SET_TIMEOUT_H */
|
||||
169
extensions/ipset-6/jhash.h
Normal file
169
extensions/ipset-6/jhash.h
Normal file
@@ -0,0 +1,169 @@
|
||||
#ifndef _LINUX_JHASH_H
|
||||
#define _LINUX_JHASH_H
|
||||
|
||||
/* jhash.h: Jenkins hash support.
|
||||
*
|
||||
* Copyright (C) 2006. Bob Jenkins (bob_jenkins@burtleburtle.net)
|
||||
*
|
||||
* http://burtleburtle.net/bob/hash/
|
||||
*
|
||||
* These are the credits from Bob's sources:
|
||||
*
|
||||
* lookup3.c, by Bob Jenkins, May 2006, Public Domain.
|
||||
*
|
||||
* These are functions for producing 32-bit hashes for hash table lookup.
|
||||
* hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final()
|
||||
* are externally useful functions. Routines to test the hash are included
|
||||
* if SELF_TEST is defined. You can use this free for any purpose. It's in
|
||||
* the public domain. It has no warranty.
|
||||
*
|
||||
* Copyright (C) 2009-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* I've modified Bob's hash to be useful in the Linux kernel, and
|
||||
* any bugs present are my fault.
|
||||
* Jozsef
|
||||
*/
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/unaligned/packed_struct.h>
|
||||
|
||||
/* Best hash sizes are of power of two */
|
||||
#define jhash_size(n) ((u32)1<<(n))
|
||||
/* Mask the hash value, i.e (value & jhash_mask(n)) instead of (value % n) */
|
||||
#define jhash_mask(n) (jhash_size(n)-1)
|
||||
|
||||
/* __jhash_mix -- mix 3 32-bit values reversibly. */
|
||||
#define __jhash_mix(a, b, c) \
|
||||
{ \
|
||||
a -= c; a ^= rol32(c, 4); c += b; \
|
||||
b -= a; b ^= rol32(a, 6); a += c; \
|
||||
c -= b; c ^= rol32(b, 8); b += a; \
|
||||
a -= c; a ^= rol32(c, 16); c += b; \
|
||||
b -= a; b ^= rol32(a, 19); a += c; \
|
||||
c -= b; c ^= rol32(b, 4); b += a; \
|
||||
}
|
||||
|
||||
/* __jhash_final - final mixing of 3 32-bit values (a,b,c) into c */
|
||||
#define __jhash_final(a, b, c) \
|
||||
{ \
|
||||
c ^= b; c -= rol32(b, 14); \
|
||||
a ^= c; a -= rol32(c, 11); \
|
||||
b ^= a; b -= rol32(a, 25); \
|
||||
c ^= b; c -= rol32(b, 16); \
|
||||
a ^= c; a -= rol32(c, 4); \
|
||||
b ^= a; b -= rol32(a, 14); \
|
||||
c ^= b; c -= rol32(b, 24); \
|
||||
}
|
||||
|
||||
/* An arbitrary initial parameter */
|
||||
#define JHASH_INITVAL 0xdeadbeef
|
||||
|
||||
/* jhash - hash an arbitrary key
|
||||
* @k: sequence of bytes as key
|
||||
* @length: the length of the key
|
||||
* @initval: the previous hash, or an arbitray value
|
||||
*
|
||||
* The generic version, hashes an arbitrary sequence of bytes.
|
||||
* No alignment or length assumptions are made about the input key.
|
||||
*
|
||||
* Returns the hash value of the key. The result depends on endianness.
|
||||
*/
|
||||
static inline u32 jhash(const void *key, u32 length, u32 initval)
|
||||
{
|
||||
u32 a, b, c;
|
||||
const u8 *k = key;
|
||||
|
||||
/* Set up the internal state */
|
||||
a = b = c = JHASH_INITVAL + length + initval;
|
||||
|
||||
/* All but the last block: affect some 32 bits of (a,b,c) */
|
||||
while (length > 12) {
|
||||
a += __get_unaligned_cpu32(k);
|
||||
b += __get_unaligned_cpu32(k + 4);
|
||||
c += __get_unaligned_cpu32(k + 8);
|
||||
__jhash_mix(a, b, c);
|
||||
length -= 12;
|
||||
k += 12;
|
||||
}
|
||||
/* Last block: affect all 32 bits of (c) */
|
||||
/* All the case statements fall through */
|
||||
switch (length) {
|
||||
case 12: c += (u32)k[11]<<24;
|
||||
case 11: c += (u32)k[10]<<16;
|
||||
case 10: c += (u32)k[9]<<8;
|
||||
case 9: c += k[8];
|
||||
case 8: b += (u32)k[7]<<24;
|
||||
case 7: b += (u32)k[6]<<16;
|
||||
case 6: b += (u32)k[5]<<8;
|
||||
case 5: b += k[4];
|
||||
case 4: a += (u32)k[3]<<24;
|
||||
case 3: a += (u32)k[2]<<16;
|
||||
case 2: a += (u32)k[1]<<8;
|
||||
case 1: a += k[0];
|
||||
__jhash_final(a, b, c);
|
||||
case 0: /* Nothing left to add */
|
||||
break;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/* jhash2 - hash an array of u32's
|
||||
* @k: the key which must be an array of u32's
|
||||
* @length: the number of u32's in the key
|
||||
* @initval: the previous hash, or an arbitray value
|
||||
*
|
||||
* Returns the hash value of the key.
|
||||
*/
|
||||
static inline u32 jhash2(const u32 *k, u32 length, u32 initval)
|
||||
{
|
||||
u32 a, b, c;
|
||||
|
||||
/* Set up the internal state */
|
||||
a = b = c = JHASH_INITVAL + (length<<2) + initval;
|
||||
|
||||
/* Handle most of the key */
|
||||
while (length > 3) {
|
||||
a += k[0];
|
||||
b += k[1];
|
||||
c += k[2];
|
||||
__jhash_mix(a, b, c);
|
||||
length -= 3;
|
||||
k += 3;
|
||||
}
|
||||
|
||||
/* Handle the last 3 u32's: all the case statements fall through */
|
||||
switch (length) {
|
||||
case 3: c += k[2];
|
||||
case 2: b += k[1];
|
||||
case 1: a += k[0];
|
||||
__jhash_final(a, b, c);
|
||||
case 0: /* Nothing left to add */
|
||||
break;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/* jhash_3words - hash exactly 3, 2 or 1 word(s) */
|
||||
static inline u32 jhash_3words(u32 a, u32 b, u32 c, u32 initval)
|
||||
{
|
||||
a += JHASH_INITVAL;
|
||||
b += JHASH_INITVAL;
|
||||
c += initval;
|
||||
|
||||
__jhash_final(a, b, c);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static inline u32 jhash_2words(u32 a, u32 b, u32 initval)
|
||||
{
|
||||
return jhash_3words(a, b, 0, initval);
|
||||
}
|
||||
|
||||
static inline u32 jhash_1word(u32 a, u32 initval)
|
||||
{
|
||||
return jhash_3words(a, 0, 0, initval);
|
||||
}
|
||||
|
||||
#endif /* _LINUX_JHASH_H */
|
||||
588
extensions/ipset-6/libipset/data.c
Normal file
588
extensions/ipset-6/libipset/data.c
Normal file
@@ -0,0 +1,588 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <assert.h> /* assert */
|
||||
#include <arpa/inet.h> /* ntoh* */
|
||||
#include <net/ethernet.h> /* ETH_ALEN */
|
||||
#include <net/if.h> /* IFNAMSIZ */
|
||||
#include <stdlib.h> /* malloc, free */
|
||||
#include <string.h> /* memset */
|
||||
|
||||
#include <libipset/linux_ip_set.h> /* IPSET_MAXNAMELEN */
|
||||
#include <libipset/debug.h> /* D() */
|
||||
#include <libipset/types.h> /* struct ipset_type */
|
||||
#include <libipset/utils.h> /* inXcpy */
|
||||
#include <libipset/data.h> /* prototypes */
|
||||
|
||||
/* Internal data structure to hold
|
||||
* a) input data entered by the user or
|
||||
* b) data received from kernel
|
||||
*
|
||||
* We always store the data in host order, *except* IP addresses.
|
||||
*/
|
||||
|
||||
struct ipset_data {
|
||||
/* Option bits: which fields are set */
|
||||
uint64_t bits;
|
||||
/* Option bits: which options are ignored */
|
||||
uint64_t ignored;
|
||||
/* Setname */
|
||||
char setname[IPSET_MAXNAMELEN];
|
||||
/* Set type */
|
||||
const struct ipset_type *type;
|
||||
/* Common CADT options */
|
||||
uint8_t cidr;
|
||||
uint8_t family;
|
||||
uint32_t flags; /* command level flags */
|
||||
uint32_t cadt_flags; /* data level flags */
|
||||
uint32_t timeout;
|
||||
union nf_inet_addr ip;
|
||||
union nf_inet_addr ip_to;
|
||||
uint16_t port;
|
||||
uint16_t port_to;
|
||||
union {
|
||||
/* RENAME/SWAP */
|
||||
char setname2[IPSET_MAXNAMELEN];
|
||||
/* CREATE/LIST/SAVE */
|
||||
struct {
|
||||
uint8_t probes;
|
||||
uint8_t resize;
|
||||
uint8_t netmask;
|
||||
uint32_t hashsize;
|
||||
uint32_t maxelem;
|
||||
uint32_t gc;
|
||||
uint32_t size;
|
||||
/* Filled out by kernel */
|
||||
uint32_t references;
|
||||
uint32_t elements;
|
||||
uint32_t memsize;
|
||||
char typename[IPSET_MAXNAMELEN];
|
||||
uint8_t revision_min;
|
||||
uint8_t revision;
|
||||
} create;
|
||||
/* ADT/LIST/SAVE */
|
||||
struct {
|
||||
union nf_inet_addr ip2;
|
||||
union nf_inet_addr ip2_to;
|
||||
uint8_t cidr2;
|
||||
uint8_t proto;
|
||||
char ether[ETH_ALEN];
|
||||
char name[IPSET_MAXNAMELEN];
|
||||
char nameref[IPSET_MAXNAMELEN];
|
||||
char iface[IFNAMSIZ];
|
||||
} adt;
|
||||
};
|
||||
};
|
||||
|
||||
static void
|
||||
copy_addr(uint8_t family, union nf_inet_addr *ip, const void *value)
|
||||
{
|
||||
if (family == NFPROTO_IPV4)
|
||||
in4cpy(&ip->in, value);
|
||||
else
|
||||
in6cpy(&ip->in6, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_strlcpy - copy the string from src to dst
|
||||
* @dst: the target string buffer
|
||||
* @src: the source string buffer
|
||||
* @len: the length of bytes to copy, including the terminating null byte.
|
||||
*
|
||||
* Copy the string from src to destination, but at most len bytes are
|
||||
* copied. The target is unconditionally terminated by the null byte.
|
||||
*/
|
||||
void
|
||||
ipset_strlcpy(char *dst, const char *src, size_t len)
|
||||
{
|
||||
assert(dst);
|
||||
assert(src);
|
||||
|
||||
strncpy(dst, src, len);
|
||||
dst[len - 1] = '\0';
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_data_flags_test - test option bits in the data blob
|
||||
* @data: data blob
|
||||
* @flags: the option flags to test
|
||||
*
|
||||
* Returns true if the options are already set in the data blob.
|
||||
*/
|
||||
bool
|
||||
ipset_data_flags_test(const struct ipset_data *data, uint64_t flags)
|
||||
{
|
||||
assert(data);
|
||||
return !!(data->bits & flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_data_flags_set - set option bits in the data blob
|
||||
* @data: data blob
|
||||
* @flags: the option flags to set
|
||||
*
|
||||
* The function sets the flags in the data blob so that
|
||||
* the corresponding fields are regarded as if filled with proper data.
|
||||
*/
|
||||
void
|
||||
ipset_data_flags_set(struct ipset_data *data, uint64_t flags)
|
||||
{
|
||||
assert(data);
|
||||
data->bits |= flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_data_flags_unset - unset option bits in the data blob
|
||||
* @data: data blob
|
||||
* @flags: the option flags to unset
|
||||
*
|
||||
* The function unsets the flags in the data blob.
|
||||
* This is the quick way to clear specific fields.
|
||||
*/
|
||||
void
|
||||
ipset_data_flags_unset(struct ipset_data *data, uint64_t flags)
|
||||
{
|
||||
assert(data);
|
||||
data->bits &= ~flags;
|
||||
}
|
||||
|
||||
#define flag_type_attr(data, opt, flag) \
|
||||
do { \
|
||||
data->flags |= flag; \
|
||||
opt = IPSET_OPT_FLAGS; \
|
||||
} while (0)
|
||||
|
||||
#define cadt_flag_type_attr(data, opt, flag) \
|
||||
do { \
|
||||
data->cadt_flags |= flag; \
|
||||
opt = IPSET_OPT_CADT_FLAGS; \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* ipset_data_ignored - test and set ignored bits in the data blob
|
||||
* @data: data blob
|
||||
* @flags: the option flag to be ignored
|
||||
*
|
||||
* Returns true if the option was not already ignored.
|
||||
*/
|
||||
bool
|
||||
ipset_data_ignored(struct ipset_data *data, enum ipset_opt opt)
|
||||
{
|
||||
bool ignored;
|
||||
assert(data);
|
||||
|
||||
ignored = data->ignored & IPSET_FLAG(opt);
|
||||
data->ignored |= IPSET_FLAG(opt);
|
||||
|
||||
return ignored;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_data_set - put data into the data blob
|
||||
* @data: data blob
|
||||
* @opt: the option kind of the data
|
||||
* @value: the value of the data
|
||||
*
|
||||
* Put a given kind of data into the data blob and mark the
|
||||
* option kind as already set in the blob.
|
||||
*
|
||||
* Returns 0 on success or a negative error code.
|
||||
*/
|
||||
int
|
||||
ipset_data_set(struct ipset_data *data, enum ipset_opt opt, const void *value)
|
||||
{
|
||||
assert(data);
|
||||
assert(opt != IPSET_OPT_NONE);
|
||||
assert(value);
|
||||
|
||||
switch (opt) {
|
||||
/* Common ones */
|
||||
case IPSET_SETNAME:
|
||||
ipset_strlcpy(data->setname, value, IPSET_MAXNAMELEN);
|
||||
break;
|
||||
case IPSET_OPT_TYPE:
|
||||
data->type = value;
|
||||
break;
|
||||
case IPSET_OPT_FAMILY:
|
||||
data->family = *(const uint8_t *) value;
|
||||
D("family set to %u", data->family);
|
||||
break;
|
||||
/* CADT options */
|
||||
case IPSET_OPT_IP:
|
||||
if (!(data->family == NFPROTO_IPV4 || data->family == NFPROTO_IPV6))
|
||||
return -1;
|
||||
copy_addr(data->family, &data->ip, value);
|
||||
break;
|
||||
case IPSET_OPT_IP_TO:
|
||||
if (!(data->family == NFPROTO_IPV4 || data->family == NFPROTO_IPV6))
|
||||
return -1;
|
||||
copy_addr(data->family, &data->ip_to, value);
|
||||
break;
|
||||
case IPSET_OPT_CIDR:
|
||||
data->cidr = *(const uint8_t *) value;
|
||||
break;
|
||||
case IPSET_OPT_PORT:
|
||||
data->port = *(const uint16_t *) value;
|
||||
break;
|
||||
case IPSET_OPT_PORT_TO:
|
||||
data->port_to = *(const uint16_t *) value;
|
||||
break;
|
||||
case IPSET_OPT_TIMEOUT:
|
||||
data->timeout = *(const uint32_t *) value;
|
||||
break;
|
||||
/* Create-specific options */
|
||||
case IPSET_OPT_GC:
|
||||
data->create.gc = *(const uint32_t *) value;
|
||||
break;
|
||||
case IPSET_OPT_HASHSIZE:
|
||||
data->create.hashsize = *(const uint32_t *) value;
|
||||
break;
|
||||
case IPSET_OPT_MAXELEM:
|
||||
data->create.maxelem = *(const uint32_t *) value;
|
||||
break;
|
||||
case IPSET_OPT_NETMASK:
|
||||
data->create.netmask = *(const uint8_t *) value;
|
||||
break;
|
||||
case IPSET_OPT_PROBES:
|
||||
data->create.probes = *(const uint8_t *) value;
|
||||
break;
|
||||
case IPSET_OPT_RESIZE:
|
||||
data->create.resize = *(const uint8_t *) value;
|
||||
break;
|
||||
case IPSET_OPT_SIZE:
|
||||
data->create.size = *(const uint32_t *) value;
|
||||
break;
|
||||
/* Create-specific options, filled out by the kernel */
|
||||
case IPSET_OPT_ELEMENTS:
|
||||
data->create.elements = *(const uint32_t *) value;
|
||||
break;
|
||||
case IPSET_OPT_REFERENCES:
|
||||
data->create.references = *(const uint32_t *) value;
|
||||
break;
|
||||
case IPSET_OPT_MEMSIZE:
|
||||
data->create.memsize = *(const uint32_t *) value;
|
||||
break;
|
||||
/* Create-specific options, type */
|
||||
case IPSET_OPT_TYPENAME:
|
||||
ipset_strlcpy(data->create.typename, value,
|
||||
IPSET_MAXNAMELEN);
|
||||
break;
|
||||
case IPSET_OPT_REVISION:
|
||||
data->create.revision = *(const uint8_t *) value;
|
||||
break;
|
||||
case IPSET_OPT_REVISION_MIN:
|
||||
data->create.revision_min = *(const uint8_t *) value;
|
||||
break;
|
||||
/* ADT-specific options */
|
||||
case IPSET_OPT_ETHER:
|
||||
memcpy(data->adt.ether, value, ETH_ALEN);
|
||||
break;
|
||||
case IPSET_OPT_NAME:
|
||||
ipset_strlcpy(data->adt.name, value, IPSET_MAXNAMELEN);
|
||||
break;
|
||||
case IPSET_OPT_NAMEREF:
|
||||
ipset_strlcpy(data->adt.nameref, value, IPSET_MAXNAMELEN);
|
||||
break;
|
||||
case IPSET_OPT_IP2:
|
||||
if (!(data->family == NFPROTO_IPV4 || data->family == NFPROTO_IPV6))
|
||||
return -1;
|
||||
copy_addr(data->family, &data->adt.ip2, value);
|
||||
break;
|
||||
case IPSET_OPT_IP2_TO:
|
||||
if (!(data->family == NFPROTO_IPV4 || data->family == NFPROTO_IPV6))
|
||||
return -1;
|
||||
copy_addr(data->family, &data->adt.ip2_to, value);
|
||||
break;
|
||||
case IPSET_OPT_CIDR2:
|
||||
data->adt.cidr2 = *(const uint8_t *) value;
|
||||
break;
|
||||
case IPSET_OPT_PROTO:
|
||||
data->adt.proto = *(const uint8_t *) value;
|
||||
break;
|
||||
case IPSET_OPT_IFACE:
|
||||
ipset_strlcpy(data->adt.iface, value, IFNAMSIZ);
|
||||
break;
|
||||
/* Swap/rename */
|
||||
case IPSET_OPT_SETNAME2:
|
||||
ipset_strlcpy(data->setname2, value, IPSET_MAXNAMELEN);
|
||||
break;
|
||||
/* flags */
|
||||
case IPSET_OPT_EXIST:
|
||||
flag_type_attr(data, opt, IPSET_FLAG_EXIST);
|
||||
break;
|
||||
case IPSET_OPT_BEFORE:
|
||||
cadt_flag_type_attr(data, opt, IPSET_FLAG_BEFORE);
|
||||
break;
|
||||
case IPSET_OPT_PHYSDEV:
|
||||
cadt_flag_type_attr(data, opt, IPSET_FLAG_PHYSDEV);
|
||||
break;
|
||||
case IPSET_OPT_FLAGS:
|
||||
data->flags = *(const uint32_t *)value;
|
||||
break;
|
||||
case IPSET_OPT_CADT_FLAGS:
|
||||
data->cadt_flags = *(const uint32_t *)value;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
};
|
||||
|
||||
ipset_data_flags_set(data, IPSET_FLAG(opt));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_data_get - get data from the data blob
|
||||
* @data: data blob
|
||||
* @opt: option kind of the requested data
|
||||
*
|
||||
* Returns the pointer to the requested kind of data from the data blob
|
||||
* if it is set. If the option kind is not set or is an unkown type,
|
||||
* NULL is returned.
|
||||
*/
|
||||
const void *
|
||||
ipset_data_get(const struct ipset_data *data, enum ipset_opt opt)
|
||||
{
|
||||
assert(data);
|
||||
assert(opt != IPSET_OPT_NONE);
|
||||
|
||||
if (!(opt == IPSET_OPT_TYPENAME || ipset_data_test(data, opt)))
|
||||
return NULL;
|
||||
|
||||
switch (opt) {
|
||||
/* Common ones */
|
||||
case IPSET_SETNAME:
|
||||
return data->setname;
|
||||
case IPSET_OPT_TYPE:
|
||||
return data->type;
|
||||
case IPSET_OPT_TYPENAME:
|
||||
if (ipset_data_test(data, IPSET_OPT_TYPE))
|
||||
return data->type->name;
|
||||
else if (ipset_data_test(data, IPSET_OPT_TYPENAME))
|
||||
return data->create.typename;
|
||||
return NULL;
|
||||
case IPSET_OPT_FAMILY:
|
||||
return &data->family;
|
||||
/* CADT options */
|
||||
case IPSET_OPT_IP:
|
||||
return &data->ip;
|
||||
case IPSET_OPT_IP_TO:
|
||||
return &data->ip_to;
|
||||
case IPSET_OPT_CIDR:
|
||||
return &data->cidr;
|
||||
case IPSET_OPT_PORT:
|
||||
return &data->port;
|
||||
case IPSET_OPT_PORT_TO:
|
||||
return &data->port_to;
|
||||
case IPSET_OPT_TIMEOUT:
|
||||
return &data->timeout;
|
||||
/* Create-specific options */
|
||||
case IPSET_OPT_GC:
|
||||
return &data->create.gc;
|
||||
case IPSET_OPT_HASHSIZE:
|
||||
return &data->create.hashsize;
|
||||
case IPSET_OPT_MAXELEM:
|
||||
return &data->create.maxelem;
|
||||
case IPSET_OPT_NETMASK:
|
||||
return &data->create.netmask;
|
||||
case IPSET_OPT_PROBES:
|
||||
return &data->create.probes;
|
||||
case IPSET_OPT_RESIZE:
|
||||
return &data->create.resize;
|
||||
case IPSET_OPT_SIZE:
|
||||
return &data->create.size;
|
||||
/* Create-specific options, filled out by the kernel */
|
||||
case IPSET_OPT_ELEMENTS:
|
||||
return &data->create.elements;
|
||||
case IPSET_OPT_REFERENCES:
|
||||
return &data->create.references;
|
||||
case IPSET_OPT_MEMSIZE:
|
||||
return &data->create.memsize;
|
||||
/* Create-specific options, TYPE */
|
||||
case IPSET_OPT_REVISION:
|
||||
return &data->create.revision;
|
||||
case IPSET_OPT_REVISION_MIN:
|
||||
return &data->create.revision_min;
|
||||
/* ADT-specific options */
|
||||
case IPSET_OPT_ETHER:
|
||||
return data->adt.ether;
|
||||
case IPSET_OPT_NAME:
|
||||
return data->adt.name;
|
||||
case IPSET_OPT_NAMEREF:
|
||||
return data->adt.nameref;
|
||||
case IPSET_OPT_IP2:
|
||||
return &data->adt.ip2;
|
||||
case IPSET_OPT_IP2_TO:
|
||||
return &data->adt.ip2_to;
|
||||
case IPSET_OPT_CIDR2:
|
||||
return &data->adt.cidr2;
|
||||
case IPSET_OPT_PROTO:
|
||||
return &data->adt.proto;
|
||||
case IPSET_OPT_IFACE:
|
||||
return &data->adt.iface;
|
||||
/* Swap/rename */
|
||||
case IPSET_OPT_SETNAME2:
|
||||
return data->setname2;
|
||||
/* flags */
|
||||
case IPSET_OPT_FLAGS:
|
||||
case IPSET_OPT_EXIST:
|
||||
return &data->flags;
|
||||
case IPSET_OPT_CADT_FLAGS:
|
||||
case IPSET_OPT_BEFORE:
|
||||
case IPSET_OPT_PHYSDEV:
|
||||
return &data->cadt_flags;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_data_sizeof - calculates the size of the data type
|
||||
* @opt: option kind of the data
|
||||
* @family: INET family
|
||||
*
|
||||
* Returns the size required to store the given data type.
|
||||
*/
|
||||
size_t
|
||||
ipset_data_sizeof(enum ipset_opt opt, uint8_t family)
|
||||
{
|
||||
assert(opt != IPSET_OPT_NONE);
|
||||
|
||||
switch (opt) {
|
||||
case IPSET_OPT_IP:
|
||||
case IPSET_OPT_IP_TO:
|
||||
case IPSET_OPT_IP2:
|
||||
case IPSET_OPT_IP2_TO:
|
||||
return family == NFPROTO_IPV4 ? sizeof(uint32_t)
|
||||
: sizeof(struct in6_addr);
|
||||
case IPSET_OPT_PORT:
|
||||
case IPSET_OPT_PORT_TO:
|
||||
return sizeof(uint16_t);
|
||||
case IPSET_SETNAME:
|
||||
case IPSET_OPT_NAME:
|
||||
case IPSET_OPT_NAMEREF:
|
||||
return IPSET_MAXNAMELEN;
|
||||
case IPSET_OPT_TIMEOUT:
|
||||
case IPSET_OPT_GC:
|
||||
case IPSET_OPT_HASHSIZE:
|
||||
case IPSET_OPT_MAXELEM:
|
||||
case IPSET_OPT_SIZE:
|
||||
case IPSET_OPT_ELEMENTS:
|
||||
case IPSET_OPT_REFERENCES:
|
||||
case IPSET_OPT_MEMSIZE:
|
||||
return sizeof(uint32_t);
|
||||
case IPSET_OPT_CIDR:
|
||||
case IPSET_OPT_CIDR2:
|
||||
case IPSET_OPT_NETMASK:
|
||||
case IPSET_OPT_PROBES:
|
||||
case IPSET_OPT_RESIZE:
|
||||
case IPSET_OPT_PROTO:
|
||||
return sizeof(uint8_t);
|
||||
case IPSET_OPT_ETHER:
|
||||
return ETH_ALEN;
|
||||
/* Flags doesn't counted once :-( */
|
||||
case IPSET_OPT_BEFORE:
|
||||
case IPSET_OPT_PHYSDEV:
|
||||
return sizeof(uint32_t);
|
||||
default:
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_setname - return the name of the set from the data blob
|
||||
* @data: data blob
|
||||
*
|
||||
* Return the name of the set from the data blob or NULL if the
|
||||
* name not set yet.
|
||||
*/
|
||||
const char *
|
||||
ipset_data_setname(const struct ipset_data *data)
|
||||
{
|
||||
assert(data);
|
||||
return ipset_data_test(data, IPSET_SETNAME) ? data->setname : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_family - return the INET family of the set from the data blob
|
||||
* @data: data blob
|
||||
*
|
||||
* Return the INET family supported by the set from the data blob.
|
||||
* If the family is not set yet, NFPROTO_UNSPEC is returned.
|
||||
*/
|
||||
uint8_t
|
||||
ipset_data_family(const struct ipset_data *data)
|
||||
{
|
||||
assert(data);
|
||||
return ipset_data_test(data, IPSET_OPT_FAMILY)
|
||||
? data->family : NFPROTO_UNSPEC;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_data_cidr - return the value of IPSET_OPT_CIDR
|
||||
* @data: data blob
|
||||
*
|
||||
* Return the value of IPSET_OPT_CIDR stored in the data blob.
|
||||
* If it is not set, then the returned value corresponds to
|
||||
* the default one according to the family type or zero.
|
||||
*/
|
||||
uint8_t
|
||||
ipset_data_cidr(const struct ipset_data *data)
|
||||
{
|
||||
assert(data);
|
||||
return ipset_data_test(data, IPSET_OPT_CIDR) ? data->cidr :
|
||||
data->family == NFPROTO_IPV4 ? 32 :
|
||||
data->family == NFPROTO_IPV6 ? 128 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_flags - return which fields are set in the data blob
|
||||
* @data: data blob
|
||||
*
|
||||
* Returns the value of the bit field which elements are set.
|
||||
*/
|
||||
uint64_t
|
||||
ipset_data_flags(const struct ipset_data *data)
|
||||
{
|
||||
assert(data);
|
||||
return data->bits;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_data_reset - reset the data blob to unset
|
||||
* @data: data blob
|
||||
*
|
||||
* Resets the data blob to the unset state for every field.
|
||||
*/
|
||||
void
|
||||
ipset_data_reset(struct ipset_data *data)
|
||||
{
|
||||
assert(data);
|
||||
memset(data, 0, sizeof(*data));
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_data_init - create a new data blob
|
||||
*
|
||||
* Return the new data blob initialized to empty. In case of
|
||||
* an error, NULL is retured.
|
||||
*/
|
||||
struct ipset_data *
|
||||
ipset_data_init(void)
|
||||
{
|
||||
return calloc(1, sizeof(struct ipset_data));
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_data_fini - release a data blob created by ipset_data_init
|
||||
*
|
||||
* Release the data blob created by ipset_data_init previously.
|
||||
*/
|
||||
void
|
||||
ipset_data_fini(struct ipset_data *data)
|
||||
{
|
||||
assert(data);
|
||||
free(data);
|
||||
}
|
||||
288
extensions/ipset-6/libipset/debug.c
Normal file
288
extensions/ipset-6/libipset/debug.c
Normal file
@@ -0,0 +1,288 @@
|
||||
/* Copyright 2011 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <arpa/inet.h> /* inet_ntop */
|
||||
#include <libmnl/libmnl.h> /* libmnl backend */
|
||||
|
||||
struct ipset_attrname {
|
||||
const char *name;
|
||||
};
|
||||
|
||||
static const struct ipset_attrname cmdattr2name[] = {
|
||||
[IPSET_ATTR_PROTOCOL] = { .name = "PROTOCOL" },
|
||||
[IPSET_ATTR_SETNAME] = { .name = "SETNAME" },
|
||||
[IPSET_ATTR_TYPENAME] = { .name = "TYPENAME" },
|
||||
[IPSET_ATTR_REVISION] = { .name = "REVISION" },
|
||||
[IPSET_ATTR_FAMILY] = { .name = "FAMILY" },
|
||||
[IPSET_ATTR_FLAGS] = { .name = "FLAGS" },
|
||||
[IPSET_ATTR_DATA] = { .name = "DATA" },
|
||||
[IPSET_ATTR_ADT] = { .name = "ADT" },
|
||||
[IPSET_ATTR_LINENO] = { .name = "LINENO" },
|
||||
[IPSET_ATTR_PROTOCOL_MIN] = { .name = "PROTO_MIN" },
|
||||
};
|
||||
|
||||
static const struct ipset_attrname createattr2name[] = {
|
||||
[IPSET_ATTR_IP] = { .name = "IP" },
|
||||
[IPSET_ATTR_IP_TO] = { .name = "IP_TO" },
|
||||
[IPSET_ATTR_CIDR] = { .name = "CIDR" },
|
||||
[IPSET_ATTR_PORT] = { .name = "PORT" },
|
||||
[IPSET_ATTR_PORT_TO] = { .name = "PORT_TO" },
|
||||
[IPSET_ATTR_TIMEOUT] = { .name = "TIMEOUT" },
|
||||
[IPSET_ATTR_PROTO] = { .name = "PROTO" },
|
||||
[IPSET_ATTR_CADT_FLAGS] = { .name = "CADT_FLAGS" },
|
||||
[IPSET_ATTR_CADT_LINENO] = { .name = "CADT_LINENO" },
|
||||
[IPSET_ATTR_GC] = { .name = "GC" },
|
||||
[IPSET_ATTR_HASHSIZE] = { .name = "HASHSIZE" },
|
||||
[IPSET_ATTR_MAXELEM] = { .name = "MAXELEM" },
|
||||
[IPSET_ATTR_NETMASK] = { .name = "NETMASK" },
|
||||
[IPSET_ATTR_PROBES] = { .name = "PROBES" },
|
||||
[IPSET_ATTR_RESIZE] = { .name = "RESIZE" },
|
||||
[IPSET_ATTR_SIZE] = { .name = "SIZE" },
|
||||
[IPSET_ATTR_ELEMENTS] = { .name = "ELEMENTS" },
|
||||
[IPSET_ATTR_REFERENCES] = { .name = "REFERENCES" },
|
||||
[IPSET_ATTR_MEMSIZE] = { .name = "MEMSIZE" },
|
||||
};
|
||||
|
||||
static const struct ipset_attrname adtattr2name[] = {
|
||||
[IPSET_ATTR_IP] = { .name = "IP" },
|
||||
[IPSET_ATTR_IP_TO] = { .name = "IP_TO" },
|
||||
[IPSET_ATTR_CIDR] = { .name = "CIDR" },
|
||||
[IPSET_ATTR_PORT] = { .name = "PORT" },
|
||||
[IPSET_ATTR_PORT_TO] = { .name = "PORT_TO" },
|
||||
[IPSET_ATTR_TIMEOUT] = { .name = "TIMEOUT" },
|
||||
[IPSET_ATTR_PROTO] = { .name = "PROTO" },
|
||||
[IPSET_ATTR_CADT_FLAGS] = { .name = "CADT_FLAGS" },
|
||||
[IPSET_ATTR_CADT_LINENO] = { .name = "CADT_LINENO" },
|
||||
[IPSET_ATTR_ETHER] = { .name = "ETHER" },
|
||||
[IPSET_ATTR_NAME] = { .name = "NAME" },
|
||||
[IPSET_ATTR_NAMEREF] = { .name = "NAMEREF" },
|
||||
[IPSET_ATTR_IP2] = { .name = "IP2" },
|
||||
[IPSET_ATTR_CIDR2] = { .name = "CIDR2" },
|
||||
[IPSET_ATTR_IP2_TO] = { .name = "IP2_TO" },
|
||||
[IPSET_ATTR_IFACE] = { .name = "IFACE" },
|
||||
};
|
||||
|
||||
static void
|
||||
debug_cadt_attrs(int max, const struct ipset_attr_policy *policy,
|
||||
const struct ipset_attrname attr2name[],
|
||||
struct nlattr *nla[])
|
||||
{
|
||||
uint32_t v;
|
||||
int i;
|
||||
|
||||
fprintf(stderr, "\t\t%s attributes:\n",
|
||||
policy == create_attrs ? "CREATE" : "ADT");
|
||||
for (i = IPSET_ATTR_UNSPEC + 1; i <= max; i++) {
|
||||
if (!nla[i])
|
||||
continue;
|
||||
switch (policy[i].type) {
|
||||
case MNL_TYPE_U8:
|
||||
v = *(uint8_t *) mnl_attr_get_payload(nla[i]);
|
||||
fprintf(stderr, "\t\t%s: %u\n",
|
||||
attr2name[i].name, v);
|
||||
break;
|
||||
case MNL_TYPE_U16:
|
||||
v = *(uint16_t *) mnl_attr_get_payload(nla[i]);
|
||||
fprintf(stderr, "\t\t%s: %u\n",
|
||||
attr2name[i].name, ntohs(v));
|
||||
break;
|
||||
case MNL_TYPE_U32:
|
||||
v = *(uint32_t *) mnl_attr_get_payload(nla[i]);
|
||||
fprintf(stderr, "\t\t%s: %u\n",
|
||||
attr2name[i].name, ntohl(v));
|
||||
break;
|
||||
case MNL_TYPE_NUL_STRING:
|
||||
fprintf(stderr, "\t\t%s: %s\n",
|
||||
attr2name[i].name,
|
||||
(const char *) mnl_attr_get_payload(nla[i]));
|
||||
break;
|
||||
case MNL_TYPE_NESTED: {
|
||||
struct nlattr *ipattr[IPSET_ATTR_IPADDR_MAX+1] = {};
|
||||
char addr[INET6_ADDRSTRLEN];
|
||||
void *d;
|
||||
|
||||
if (mnl_attr_parse_nested(nla[i], ipaddr_attr_cb,
|
||||
ipattr) < 0) {
|
||||
fprintf(stderr,
|
||||
"\t\tIPADDR: cannot validate "
|
||||
"and parse attributes\n");
|
||||
continue;
|
||||
}
|
||||
if (ipattr[IPSET_ATTR_IPADDR_IPV4]) {
|
||||
d = mnl_attr_get_payload(
|
||||
ipattr[IPSET_ATTR_IPADDR_IPV4]);
|
||||
|
||||
inet_ntop(NFPROTO_IPV4, d, addr, INET6_ADDRSTRLEN);
|
||||
fprintf(stderr, "\t\t%s: %s\n",
|
||||
attr2name[i].name, addr);
|
||||
} else if (ipattr[IPSET_ATTR_IPADDR_IPV6]) {
|
||||
d = mnl_attr_get_payload(
|
||||
ipattr[IPSET_ATTR_IPADDR_IPV6]);
|
||||
|
||||
inet_ntop(NFPROTO_IPV6, d, addr, INET6_ADDRSTRLEN);
|
||||
fprintf(stderr, "\t\t%s: %s\n",
|
||||
attr2name[i].name, addr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
fprintf(stderr, "\t\t%s: unresolved!\n",
|
||||
attr2name[i].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
debug_cmd_attrs(int cmd, struct nlattr *nla[])
|
||||
{
|
||||
struct nlattr *adt[IPSET_ATTR_ADT_MAX+1] = {};
|
||||
struct nlattr *cattr[IPSET_ATTR_CREATE_MAX+1] = {};
|
||||
uint32_t v;
|
||||
int i;
|
||||
|
||||
fprintf(stderr, "\tCommand attributes:\n");
|
||||
for (i = IPSET_ATTR_UNSPEC + 1; i <= IPSET_ATTR_CMD_MAX; i++) {
|
||||
if (!nla[i])
|
||||
continue;
|
||||
switch (cmd_attrs[i].type) {
|
||||
case MNL_TYPE_U8:
|
||||
v = *(uint8_t *) mnl_attr_get_payload(nla[i]);
|
||||
fprintf(stderr, "\t%s: %u\n",
|
||||
cmdattr2name[i].name, v);
|
||||
break;
|
||||
case MNL_TYPE_U16:
|
||||
v = *(uint16_t *) mnl_attr_get_payload(nla[i]);
|
||||
fprintf(stderr, "\t%s: %u\n",
|
||||
cmdattr2name[i].name, ntohs(v));
|
||||
break;
|
||||
case MNL_TYPE_U32:
|
||||
v = *(uint32_t *) mnl_attr_get_payload(nla[i]);
|
||||
fprintf(stderr, "\t%s: %u\n",
|
||||
cmdattr2name[i].name, ntohl(v));
|
||||
break;
|
||||
case MNL_TYPE_NUL_STRING:
|
||||
fprintf(stderr, "\t%s: %s\n",
|
||||
cmdattr2name[i].name,
|
||||
(const char *) mnl_attr_get_payload(nla[i]));
|
||||
break;
|
||||
case MNL_TYPE_NESTED:
|
||||
if (i == IPSET_ATTR_DATA) {
|
||||
switch (cmd) {
|
||||
case IPSET_CMD_ADD:
|
||||
case IPSET_CMD_DEL:
|
||||
case IPSET_CMD_TEST:
|
||||
if (mnl_attr_parse_nested(nla[i],
|
||||
adt_attr_cb, adt) < 0) {
|
||||
fprintf(stderr,
|
||||
"\tADT: cannot validate "
|
||||
"and parse attributes\n");
|
||||
continue;
|
||||
}
|
||||
debug_cadt_attrs(IPSET_ATTR_ADT_MAX,
|
||||
adt_attrs,
|
||||
adtattr2name,
|
||||
adt);
|
||||
break;
|
||||
default:
|
||||
if (mnl_attr_parse_nested(nla[i],
|
||||
create_attr_cb,
|
||||
cattr) < 0) {
|
||||
fprintf(stderr,
|
||||
"\tCREATE: cannot validate "
|
||||
"and parse attributes\n");
|
||||
continue;
|
||||
}
|
||||
debug_cadt_attrs(IPSET_ATTR_CREATE_MAX,
|
||||
create_attrs,
|
||||
createattr2name,
|
||||
cattr);
|
||||
}
|
||||
} else {
|
||||
struct nlattr *tb;
|
||||
mnl_attr_for_each_nested(tb, nla[i]) {
|
||||
memset(adt, 0, sizeof(adt));
|
||||
if (mnl_attr_parse_nested(tb,
|
||||
adt_attr_cb, adt) < 0) {
|
||||
fprintf(stderr,
|
||||
"\tADT: cannot validate "
|
||||
"and parse attributes\n");
|
||||
continue;
|
||||
}
|
||||
debug_cadt_attrs(IPSET_ATTR_ADT_MAX,
|
||||
adt_attrs,
|
||||
adtattr2name,
|
||||
adt);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "\t%s: unresolved!\n",
|
||||
cmdattr2name[i].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ipset_debug_msg(const char *dir, void *buffer, int len)
|
||||
{
|
||||
const struct nlmsghdr *nlh = buffer;
|
||||
struct nlattr *nla[IPSET_ATTR_CMD_MAX+1] = {};
|
||||
int cmd, nfmsglen = MNL_ALIGN(sizeof(struct nfgenmsg));
|
||||
|
||||
debug = 0;
|
||||
while (mnl_nlmsg_ok(nlh, len)) {
|
||||
switch (nlh->nlmsg_type) {
|
||||
case NLMSG_NOOP:
|
||||
case NLMSG_DONE:
|
||||
case NLMSG_OVERRUN:
|
||||
fprintf(stderr, "Message header: %s msg %s\n"
|
||||
"\tlen %d\n"
|
||||
"\tseq %u\n",
|
||||
dir,
|
||||
nlh->nlmsg_type == NLMSG_NOOP ? "NOOP" :
|
||||
nlh->nlmsg_type == NLMSG_DONE ? "DONE" :
|
||||
"OVERRUN",
|
||||
len, nlh->nlmsg_seq);
|
||||
goto next_msg;
|
||||
case NLMSG_ERROR: {
|
||||
const struct nlmsgerr *err = mnl_nlmsg_get_payload(nlh);
|
||||
fprintf(stderr, "Message header: %s msg ERROR\n"
|
||||
"\tlen %d\n"
|
||||
"\terrcode %d\n"
|
||||
"\tseq %u\n",
|
||||
dir, len, err->error, nlh->nlmsg_seq);
|
||||
goto next_msg;
|
||||
}
|
||||
default:
|
||||
;
|
||||
}
|
||||
cmd = ipset_get_nlmsg_type(nlh);
|
||||
fprintf(stderr, "Message header: %s cmd %s (%d)\n"
|
||||
"\tlen %d\n"
|
||||
"\tflag %s\n"
|
||||
"\tseq %u\n",
|
||||
dir,
|
||||
cmd <= IPSET_CMD_NONE ? "NONE!" :
|
||||
cmd >= IPSET_CMD_MAX ? "MAX!" : cmd2name[cmd], cmd,
|
||||
len,
|
||||
!(nlh->nlmsg_flags & NLM_F_EXCL) ? "EXIST" : "none",
|
||||
nlh->nlmsg_seq);
|
||||
if (cmd <= IPSET_CMD_NONE || cmd >= IPSET_CMD_MAX)
|
||||
goto next_msg;
|
||||
memset(nla, 0, sizeof(nla));
|
||||
if (mnl_attr_parse(nlh, nfmsglen,
|
||||
cmd_attr_cb, nla) < MNL_CB_STOP) {
|
||||
fprintf(stderr, "\tcannot validate "
|
||||
"and parse attributes\n");
|
||||
goto next_msg;
|
||||
}
|
||||
debug_cmd_attrs(cmd, nla);
|
||||
next_msg:
|
||||
nlh = mnl_nlmsg_next(nlh, &len);
|
||||
}
|
||||
debug = 1;
|
||||
}
|
||||
200
extensions/ipset-6/libipset/errcode.c
Normal file
200
extensions/ipset-6/libipset/errcode.c
Normal file
@@ -0,0 +1,200 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <assert.h> /* assert */
|
||||
#include <errno.h> /* errno */
|
||||
#include <string.h> /* strerror */
|
||||
|
||||
#include <libipset/debug.h> /* D() */
|
||||
#include <libipset/data.h> /* ipset_data_get */
|
||||
#include <libipset/session.h> /* ipset_err */
|
||||
#include <libipset/types.h> /* struct ipset_type */
|
||||
#include <libipset/utils.h> /* STRNEQ */
|
||||
#include <libipset/errcode.h> /* prototypes */
|
||||
#include <libipset/linux_ip_set_bitmap.h> /* bitmap specific errcodes */
|
||||
#include <libipset/linux_ip_set_hash.h> /* hash specific errcodes */
|
||||
#include <libipset/linux_ip_set_list.h> /* list specific errcodes */
|
||||
|
||||
/* Core kernel error codes */
|
||||
static const struct ipset_errcode_table core_errcode_table[] = {
|
||||
/* Generic error codes */
|
||||
{ ENOENT, 0,
|
||||
"The set with the given name does not exist" },
|
||||
{ EMSGSIZE, 0,
|
||||
"Kernel error received: message could not be created" },
|
||||
{ IPSET_ERR_PROTOCOL, 0,
|
||||
"Kernel error received: ipset protocol error" },
|
||||
|
||||
/* CREATE specific error codes */
|
||||
{ EEXIST, IPSET_CMD_CREATE,
|
||||
"Set cannot be created: set with the same name already exists" },
|
||||
{ IPSET_ERR_FIND_TYPE, 0,
|
||||
"Kernel error received: set type not supported" },
|
||||
{ IPSET_ERR_MAX_SETS, 0,
|
||||
"Kernel error received: maximal number of sets reached, "
|
||||
"cannot create more." },
|
||||
{ IPSET_ERR_INVALID_NETMASK, 0,
|
||||
"The value of the netmask parameter is invalid" },
|
||||
{ IPSET_ERR_INVALID_FAMILY, 0,
|
||||
"Protocol family not supported by the set type" },
|
||||
|
||||
/* DESTROY specific error codes */
|
||||
{ IPSET_ERR_BUSY, IPSET_CMD_DESTROY,
|
||||
"Set cannot be destroyed: it is in use by a kernel component" },
|
||||
|
||||
/* FLUSH specific error codes */
|
||||
|
||||
/* RENAME specific error codes */
|
||||
{ IPSET_ERR_EXIST_SETNAME2, IPSET_CMD_RENAME,
|
||||
"Set cannot be renamed: a set with the new name already exists" },
|
||||
{ IPSET_ERR_REFERENCED, IPSET_CMD_RENAME,
|
||||
"Set cannot be renamed: it is in use by another system" },
|
||||
|
||||
/* SWAP specific error codes */
|
||||
{ IPSET_ERR_EXIST_SETNAME2, IPSET_CMD_SWAP,
|
||||
"Sets cannot be swapped: the second set does not exist" },
|
||||
{ IPSET_ERR_TYPE_MISMATCH, IPSET_CMD_SWAP,
|
||||
"The sets cannot be swapped: they type does not match" },
|
||||
|
||||
/* LIST/SAVE specific error codes */
|
||||
|
||||
/* Generic (CADT) error codes */
|
||||
{ IPSET_ERR_INVALID_CIDR, 0,
|
||||
"The value of the CIDR parameter of the IP address is invalid" },
|
||||
{ IPSET_ERR_TIMEOUT, 0,
|
||||
"Timeout cannot be used: set was created without timeout support" },
|
||||
{ IPSET_ERR_IPADDR_IPV4, 0,
|
||||
"An IPv4 address is expected, but not received" },
|
||||
{ IPSET_ERR_IPADDR_IPV6, 0,
|
||||
"An IPv6 address is expected, but not received" },
|
||||
|
||||
/* ADD specific error codes */
|
||||
{ IPSET_ERR_EXIST, IPSET_CMD_ADD,
|
||||
"Element cannot be added to the set: it's already added" },
|
||||
|
||||
/* DEL specific error codes */
|
||||
{ IPSET_ERR_EXIST, IPSET_CMD_DEL,
|
||||
"Element cannot be deleted from the set: it's not added" },
|
||||
|
||||
/* TEST specific error codes */
|
||||
|
||||
/* HEADER specific error codes */
|
||||
|
||||
/* TYPE specific error codes */
|
||||
{ EEXIST, IPSET_CMD_TYPE,
|
||||
"Kernel error received: set type does not supported" },
|
||||
|
||||
/* PROTOCOL specific error codes */
|
||||
|
||||
{ },
|
||||
};
|
||||
|
||||
/* Bitmap type-specific error codes */
|
||||
static const struct ipset_errcode_table bitmap_errcode_table[] = {
|
||||
/* Generic (CADT) error codes */
|
||||
{ IPSET_ERR_BITMAP_RANGE, 0,
|
||||
"Element is out of the range of the set" },
|
||||
{ IPSET_ERR_BITMAP_RANGE_SIZE, IPSET_CMD_CREATE,
|
||||
"The range you specified exceeds the size limit of the set type" },
|
||||
{ },
|
||||
};
|
||||
|
||||
/* Hash type-specific error codes */
|
||||
static const struct ipset_errcode_table hash_errcode_table[] = {
|
||||
/* Generic (CADT) error codes */
|
||||
{ IPSET_ERR_HASH_FULL, 0,
|
||||
"Hash is full, cannot add more elements" },
|
||||
{ IPSET_ERR_HASH_ELEM, 0,
|
||||
"Null-valued element, cannot be stored in a hash type of set" },
|
||||
{ IPSET_ERR_INVALID_PROTO, 0,
|
||||
"Invalid protocol specified" },
|
||||
{ IPSET_ERR_MISSING_PROTO, 0,
|
||||
"Protocol missing, but must be specified" },
|
||||
{ IPSET_ERR_HASH_RANGE_UNSUPPORTED, 0,
|
||||
"Range is not supported in the \"net\" component of the element" },
|
||||
{ IPSET_ERR_HASH_RANGE, 0,
|
||||
"Invalid range, covers the whole address space" },
|
||||
{ },
|
||||
};
|
||||
|
||||
/* List type-specific error codes */
|
||||
static const struct ipset_errcode_table list_errcode_table[] = {
|
||||
/* Generic (CADT) error codes */
|
||||
{ IPSET_ERR_NAME, 0,
|
||||
"Set to be added/deleted/tested as element does not exist." },
|
||||
{ IPSET_ERR_LOOP, 0,
|
||||
"Sets with list:set type cannot be added to the set." },
|
||||
{ IPSET_ERR_BEFORE, 0,
|
||||
"No reference set specified." },
|
||||
{ IPSET_ERR_NAMEREF, 0,
|
||||
"The set to which you referred with 'before' or 'after' "
|
||||
"does not exist." },
|
||||
{ IPSET_ERR_LIST_FULL, 0,
|
||||
"The set is full, more elements cannot be added." },
|
||||
{ IPSET_ERR_REF_EXIST, 0,
|
||||
"The set to which you referred with 'before' or 'after' "
|
||||
"is not added to the set." },
|
||||
{ },
|
||||
};
|
||||
|
||||
#define MATCH_TYPENAME(a, b) STRNEQ(a, b, strlen(b))
|
||||
|
||||
/**
|
||||
* ipset_errcode - interpret a kernel error code
|
||||
* @session: session structure
|
||||
* @errcode: errcode
|
||||
*
|
||||
* Find the error code and print the appropriate
|
||||
* error message into the error buffer.
|
||||
*
|
||||
* Returns -1.
|
||||
*/
|
||||
int
|
||||
ipset_errcode(struct ipset_session *session, enum ipset_cmd cmd, int errcode)
|
||||
{
|
||||
const struct ipset_errcode_table *table = core_errcode_table;
|
||||
int i, generic;
|
||||
|
||||
if (errcode >= IPSET_ERR_TYPE_SPECIFIC) {
|
||||
const struct ipset_type *type;
|
||||
|
||||
type = ipset_saved_type(session);
|
||||
if (type) {
|
||||
if (MATCH_TYPENAME(type->name, "bitmap:"))
|
||||
table = bitmap_errcode_table;
|
||||
else if (MATCH_TYPENAME(type->name, "hash:"))
|
||||
table = hash_errcode_table;
|
||||
else if (MATCH_TYPENAME(type->name, "list:"))
|
||||
table = list_errcode_table;
|
||||
}
|
||||
}
|
||||
|
||||
retry:
|
||||
for (i = 0, generic = -1; table[i].errcode; i++) {
|
||||
if (table[i].errcode == errcode &&
|
||||
(table[i].cmd == cmd || table[i].cmd == 0)) {
|
||||
if (table[i].cmd == 0) {
|
||||
generic = i;
|
||||
continue;
|
||||
}
|
||||
return ipset_err(session, table[i].message);
|
||||
}
|
||||
}
|
||||
if (generic != -1)
|
||||
return ipset_err(session, table[generic].message);
|
||||
/* Fall back to the core table */
|
||||
if (table != core_errcode_table) {
|
||||
table = core_errcode_table;
|
||||
goto retry;
|
||||
}
|
||||
if (errcode < IPSET_ERR_PRIVATE)
|
||||
return ipset_err(session, "Kernel error received: %s",
|
||||
strerror(errcode));
|
||||
else
|
||||
return ipset_err(session,
|
||||
"Undecoded error %u received from kernel",
|
||||
errcode);
|
||||
}
|
||||
81
extensions/ipset-6/libipset/icmp.c
Normal file
81
extensions/ipset-6/libipset/icmp.c
Normal file
@@ -0,0 +1,81 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <libipset/utils.h> /* STRNEQ */
|
||||
#include <libipset/icmp.h> /* prototypes */
|
||||
|
||||
struct icmp_names {
|
||||
const char *name;
|
||||
uint8_t type, code;
|
||||
};
|
||||
|
||||
static const struct icmp_names icmp_typecodes[] = {
|
||||
{ "echo-reply", 0, 0 },
|
||||
{ "pong", 0, 0 },
|
||||
{ "network-unreachable", 3, 0 },
|
||||
{ "host-unreachable", 3, 1 },
|
||||
{ "protocol-unreachable", 3, 2 },
|
||||
{ "port-unreachable", 3, 3 },
|
||||
{ "fragmentation-needed", 3, 4 },
|
||||
{ "source-route-failed", 3, 5 },
|
||||
{ "network-unknown", 3, 6 },
|
||||
{ "host-unknown", 3, 7 },
|
||||
{ "network-prohibited", 3, 9 },
|
||||
{ "host-prohibited", 3, 10 },
|
||||
{ "TOS-network-unreachable", 3, 11 },
|
||||
{ "TOS-host-unreachable", 3, 12 },
|
||||
{ "communication-prohibited", 3, 13 },
|
||||
{ "host-precedence-violation", 3, 14 },
|
||||
{ "precedence-cutoff", 3, 15 },
|
||||
{ "source-quench", 4, 0 },
|
||||
{ "network-redirect", 5, 0 },
|
||||
{ "host-redirect", 5, 1 },
|
||||
{ "TOS-network-redirect", 5, 2 },
|
||||
{ "TOS-host-redirect", 5, 3 },
|
||||
{ "echo-request", 8, 0 },
|
||||
{ "ping", 8, 0 },
|
||||
{ "router-advertisement", 9, 0 },
|
||||
{ "router-solicitation", 10, 0 },
|
||||
{ "ttl-zero-during-transit", 11, 0 },
|
||||
{ "ttl-zero-during-reassembly", 11, 1 },
|
||||
{ "ip-header-bad", 12, 0 },
|
||||
{ "required-option-missing", 12, 1 },
|
||||
{ "timestamp-request", 13, 0 },
|
||||
{ "timestamp-reply", 14, 0 },
|
||||
{ "address-mask-request", 17, 0 },
|
||||
{ "address-mask-reply", 18, 0 },
|
||||
};
|
||||
|
||||
const char *id_to_icmp(uint8_t id)
|
||||
{
|
||||
return id < ARRAY_SIZE(icmp_typecodes) ? icmp_typecodes[id].name : NULL;
|
||||
}
|
||||
|
||||
const char *icmp_to_name(uint8_t type, uint8_t code)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(icmp_typecodes); i++)
|
||||
if (icmp_typecodes[i].type == type &&
|
||||
icmp_typecodes[i].code == code)
|
||||
return icmp_typecodes[i].name;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int name_to_icmp(const char *str, uint16_t *typecode)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(icmp_typecodes); i++)
|
||||
if (STRNCASEQ(icmp_typecodes[i].name, str, strlen(str))) {
|
||||
*typecode = (icmp_typecodes[i].type << 8) |
|
||||
icmp_typecodes[i].code;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
69
extensions/ipset-6/libipset/icmpv6.c
Normal file
69
extensions/ipset-6/libipset/icmpv6.c
Normal file
@@ -0,0 +1,69 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <libipset/utils.h> /* STRNEQ */
|
||||
#include <libipset/icmpv6.h> /* prototypes */
|
||||
|
||||
struct icmpv6_names {
|
||||
const char *name;
|
||||
uint8_t type, code;
|
||||
};
|
||||
|
||||
static const struct icmpv6_names icmpv6_typecodes[] = {
|
||||
{ "no-route", 1, 0 },
|
||||
{ "communication-prohibited", 1, 1 },
|
||||
{ "address-unreachable", 1, 3 },
|
||||
{ "port-unreachable", 1, 4 },
|
||||
{ "packet-too-big", 2, 0 },
|
||||
{ "ttl-zero-during-transit", 3, 0 },
|
||||
{ "ttl-zero-during-reassembly", 3, 1 },
|
||||
{ "bad-header", 4, 0 },
|
||||
{ "unknown-header-type", 4, 1 },
|
||||
{ "unknown-option", 4, 2 },
|
||||
{ "echo-request", 128, 0 },
|
||||
{ "ping", 128, 0 },
|
||||
{ "echo-reply", 129, 0 },
|
||||
{ "pong", 129, 0 },
|
||||
{ "router-solicitation", 133, 0 },
|
||||
{ "router-advertisement", 134, 0 },
|
||||
{ "neighbour-solicitation", 135, 0 },
|
||||
{ "neigbour-solicitation", 135, 0 },
|
||||
{ "neighbour-advertisement", 136, 0 },
|
||||
{ "neigbour-advertisement", 136, 0 },
|
||||
{ "redirect", 137, 0 },
|
||||
};
|
||||
|
||||
const char *id_to_icmpv6(uint8_t id)
|
||||
{
|
||||
return id < ARRAY_SIZE(icmpv6_typecodes) ?
|
||||
icmpv6_typecodes[id].name : NULL;
|
||||
}
|
||||
|
||||
const char *icmpv6_to_name(uint8_t type, uint8_t code)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(icmpv6_typecodes); i++)
|
||||
if (icmpv6_typecodes[i].type == type &&
|
||||
icmpv6_typecodes[i].code == code)
|
||||
return icmpv6_typecodes[i].name;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int name_to_icmpv6(const char *str, uint16_t *typecode)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(icmpv6_typecodes); i++)
|
||||
if (STRNCASEQ(icmpv6_typecodes[i].name, str, strlen(str))) {
|
||||
*typecode = (icmpv6_typecodes[i].type << 8) |
|
||||
icmpv6_typecodes[i].code;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
264
extensions/ipset-6/libipset/mnl.c
Normal file
264
extensions/ipset-6/libipset/mnl.c
Normal file
@@ -0,0 +1,264 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <assert.h> /* assert */
|
||||
#include <errno.h> /* errno */
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h> /* calloc, free */
|
||||
#include <time.h> /* time */
|
||||
#include <arpa/inet.h> /* hto* */
|
||||
|
||||
#include <libipset/linux_ip_set.h> /* enum ipset_cmd */
|
||||
#include <libipset/debug.h> /* D() */
|
||||
#include <libipset/session.h> /* ipset_session_handle */
|
||||
#include <libipset/ui.h> /* IPSET_ENV_EXIST */
|
||||
#include <libipset/utils.h> /* UNUSED */
|
||||
#include <libipset/mnl.h> /* prototypes */
|
||||
|
||||
#include <libmnl/libmnl.h>
|
||||
#include <linux/genetlink.h>
|
||||
#include <linux/netlink.h>
|
||||
|
||||
#ifndef NFNL_SUBSYS_IPSET
|
||||
#define NFNL_SUBSYS_IPSET 6
|
||||
#endif
|
||||
|
||||
/* Internal data structure for the kernel-userspace communication parameters */
|
||||
struct ipset_handle {
|
||||
struct mnl_socket *h; /* the mnl socket */
|
||||
unsigned int seq; /* netlink message sequence number */
|
||||
unsigned int portid; /* the socket port identifier */
|
||||
mnl_cb_t *cb_ctl; /* control block callbacks */
|
||||
void *data; /* data pointer */
|
||||
unsigned int genl_id; /* genetlink ID of ip_set */
|
||||
};
|
||||
|
||||
/* Netlink flags of the commands */
|
||||
static const uint16_t cmdflags[] = {
|
||||
[IPSET_CMD_CREATE-1] = NLM_F_REQUEST|NLM_F_ACK|
|
||||
NLM_F_CREATE|NLM_F_EXCL,
|
||||
[IPSET_CMD_DESTROY-1] = NLM_F_REQUEST|NLM_F_ACK,
|
||||
[IPSET_CMD_FLUSH-1] = NLM_F_REQUEST|NLM_F_ACK,
|
||||
[IPSET_CMD_RENAME-1] = NLM_F_REQUEST|NLM_F_ACK,
|
||||
[IPSET_CMD_SWAP-1] = NLM_F_REQUEST|NLM_F_ACK,
|
||||
[IPSET_CMD_LIST-1] = NLM_F_REQUEST|NLM_F_ACK,
|
||||
[IPSET_CMD_SAVE-1] = NLM_F_REQUEST|NLM_F_ACK,
|
||||
[IPSET_CMD_ADD-1] = NLM_F_REQUEST|NLM_F_ACK|NLM_F_EXCL,
|
||||
[IPSET_CMD_DEL-1] = NLM_F_REQUEST|NLM_F_ACK|NLM_F_EXCL,
|
||||
[IPSET_CMD_TEST-1] = NLM_F_REQUEST|NLM_F_ACK,
|
||||
[IPSET_CMD_HEADER-1] = NLM_F_REQUEST,
|
||||
[IPSET_CMD_TYPE-1] = NLM_F_REQUEST,
|
||||
[IPSET_CMD_PROTOCOL-1] = NLM_F_REQUEST,
|
||||
};
|
||||
|
||||
/**
|
||||
* ipset_get_nlmsg_type - get ipset netlink message type
|
||||
* @nlh: pointer to the netlink message header
|
||||
*
|
||||
* Returns the ipset netlink message type, i.e. the ipset command.
|
||||
*/
|
||||
int
|
||||
ipset_get_nlmsg_type(const struct nlmsghdr *nlh)
|
||||
{
|
||||
const struct genlmsghdr *ghdr = mnl_nlmsg_get_payload(nlh);
|
||||
|
||||
return ghdr->cmd;
|
||||
}
|
||||
|
||||
static void
|
||||
ipset_mnl_fill_hdr(struct ipset_handle *handle, enum ipset_cmd cmd,
|
||||
void *buffer, size_t len UNUSED, uint8_t envflags)
|
||||
{
|
||||
struct nlmsghdr *nlh;
|
||||
struct genlmsghdr *ghdr;
|
||||
|
||||
assert(handle);
|
||||
assert(buffer);
|
||||
assert(cmd > IPSET_CMD_NONE && cmd < IPSET_MSG_MAX);
|
||||
|
||||
nlh = mnl_nlmsg_put_header(buffer);
|
||||
nlh->nlmsg_type = handle->genl_id;
|
||||
nlh->nlmsg_flags = NLM_F_REQUEST;
|
||||
if (cmdflags[cmd-1] & NLM_F_ACK)
|
||||
nlh->nlmsg_flags |= NLM_F_ACK;
|
||||
|
||||
ghdr = mnl_nlmsg_put_extra_header(nlh, sizeof(struct genlmsghdr));
|
||||
ghdr->cmd = cmd;
|
||||
/* (ge)netlink is dumb, NLM_F_CREATE and NLM_F_DUMP overlap, get misinterpreted. */
|
||||
ghdr->reserved = cmdflags[cmd-1];
|
||||
if (envflags & IPSET_ENV_EXIST)
|
||||
ghdr->reserved &= ~NLM_F_EXCL;
|
||||
}
|
||||
|
||||
static int
|
||||
ipset_mnl_query(struct ipset_handle *handle, void *buffer, size_t len)
|
||||
{
|
||||
struct nlmsghdr *nlh = buffer;
|
||||
int ret;
|
||||
|
||||
assert(handle);
|
||||
assert(buffer);
|
||||
|
||||
nlh->nlmsg_seq = ++handle->seq;
|
||||
#ifdef IPSET_DEBUG
|
||||
ipset_debug_msg("sent", nlh, nlh->nlmsg_len);
|
||||
#endif
|
||||
if (mnl_socket_sendto(handle->h, nlh, nlh->nlmsg_len) < 0)
|
||||
return -ECOMM;
|
||||
|
||||
ret = mnl_socket_recvfrom(handle->h, buffer, len);
|
||||
#ifdef IPSET_DEBUG
|
||||
ipset_debug_msg("received", buffer, ret);
|
||||
#endif
|
||||
while (ret > 0) {
|
||||
ret = mnl_cb_run2(buffer, ret,
|
||||
handle->seq, handle->portid,
|
||||
handle->cb_ctl[NLMSG_MIN_TYPE],
|
||||
handle->data,
|
||||
handle->cb_ctl, NLMSG_MIN_TYPE);
|
||||
D("nfln_cb_run2, ret: %d, errno %d", ret, errno);
|
||||
if (ret <= 0)
|
||||
break;
|
||||
ret = mnl_socket_recvfrom(handle->h, buffer, len);
|
||||
D("message received, ret: %d", ret);
|
||||
}
|
||||
return ret > 0 ? 0 : ret;
|
||||
}
|
||||
|
||||
static int ipset_mnl_getid_acb(const struct nlattr *attr, void *datap)
|
||||
{
|
||||
const struct nlattr **tb = datap;
|
||||
uint16_t type = mnl_attr_get_type(attr);
|
||||
|
||||
if (mnl_attr_type_valid(attr, CTRL_ATTR_MAX) < 0)
|
||||
return MNL_CB_OK;
|
||||
tb[type] = attr;
|
||||
return MNL_CB_OK;
|
||||
}
|
||||
|
||||
static int ipset_mnl_getid_cb(const struct nlmsghdr *nlhdr, void *datap)
|
||||
{
|
||||
struct ipset_handle *h = datap;
|
||||
const struct nlattr *tb[CTRL_ATTR_MAX+1] = {0};
|
||||
const struct genlmsghdr *ghdr = mnl_nlmsg_get_payload(nlhdr);
|
||||
int ret;
|
||||
|
||||
ret = mnl_attr_parse(nlhdr, sizeof(*ghdr), ipset_mnl_getid_acb, tb);
|
||||
if (ret != MNL_CB_OK)
|
||||
return ret;
|
||||
if (tb[CTRL_ATTR_FAMILY_ID] != NULL)
|
||||
h->genl_id = mnl_attr_get_u16(tb[CTRL_ATTR_FAMILY_ID]);
|
||||
return MNL_CB_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up the GENL identifier for the ip_set subsystem, and store it in
|
||||
* @h->genl_id. On success, 0 is returned, otherwise error encoded as
|
||||
* negative number.
|
||||
*/
|
||||
static int ipset_mnl_getid(struct ipset_handle *h, bool modprobe)
|
||||
{
|
||||
size_t buf_size = 8192; //MNL_SOCKET_BUFFER_SIZE;
|
||||
struct nlmsghdr *nlhdr;
|
||||
struct genlmsghdr *ghdr;
|
||||
char *buf;
|
||||
int ret = -ENOENT;
|
||||
|
||||
h->genl_id = 0;
|
||||
|
||||
if (modprobe) {
|
||||
/* genetlink has no autoloading like nfnetlink... */
|
||||
system("/sbin/modprobe -q ip_set");
|
||||
}
|
||||
|
||||
buf = malloc(buf_size);
|
||||
if (buf == NULL)
|
||||
return -errno;
|
||||
|
||||
nlhdr = mnl_nlmsg_put_header(buf);
|
||||
nlhdr->nlmsg_type = GENL_ID_CTRL;
|
||||
nlhdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||
ghdr = mnl_nlmsg_put_extra_header(nlhdr, sizeof(struct genlmsghdr));
|
||||
ghdr->cmd = CTRL_CMD_GETFAMILY;
|
||||
ghdr->version = 2;
|
||||
if (!mnl_attr_put_strz_check(nlhdr, buf_size,
|
||||
CTRL_ATTR_FAMILY_NAME, "ip_set"))
|
||||
goto out;
|
||||
|
||||
ret = mnl_socket_sendto(h->h, buf, nlhdr->nlmsg_len);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
ret = mnl_socket_recvfrom(h->h, buf, buf_size);
|
||||
while (ret > 0) {
|
||||
ret = mnl_cb_run(buf, ret, 0, 0, ipset_mnl_getid_cb, h);
|
||||
if (ret <= 0)
|
||||
break;
|
||||
ret = mnl_socket_recvfrom(h->h, buf, buf_size);
|
||||
}
|
||||
if (h->genl_id == 0 && !modprobe)
|
||||
/* Redo, with modprobe this time. */
|
||||
ret = ipset_mnl_getid(h, true);
|
||||
if (h->genl_id > 0)
|
||||
ret = 0;
|
||||
out:
|
||||
free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct ipset_handle *
|
||||
ipset_mnl_init(mnl_cb_t *cb_ctl, void *data)
|
||||
{
|
||||
struct ipset_handle *handle;
|
||||
|
||||
assert(cb_ctl);
|
||||
assert(data);
|
||||
|
||||
handle = calloc(1, sizeof(*handle));
|
||||
if (!handle)
|
||||
return NULL;
|
||||
|
||||
handle->h = mnl_socket_open(NETLINK_GENERIC);
|
||||
if (!handle->h)
|
||||
goto free_handle;
|
||||
|
||||
if (mnl_socket_bind(handle->h, 0, MNL_SOCKET_AUTOPID) < 0)
|
||||
goto close_nl;
|
||||
|
||||
handle->portid = mnl_socket_get_portid(handle->h);
|
||||
handle->cb_ctl = cb_ctl;
|
||||
handle->data = data;
|
||||
handle->seq = time(NULL);
|
||||
|
||||
if (ipset_mnl_getid(handle, false) < 0)
|
||||
goto close_nl;
|
||||
return handle;
|
||||
|
||||
close_nl:
|
||||
mnl_socket_close(handle->h);
|
||||
free_handle:
|
||||
free(handle);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
ipset_mnl_fini(struct ipset_handle *handle)
|
||||
{
|
||||
assert(handle);
|
||||
|
||||
if (handle->h)
|
||||
mnl_socket_close(handle->h);
|
||||
|
||||
free(handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct ipset_transport ipset_mnl_transport = {
|
||||
.init = ipset_mnl_init,
|
||||
.fini = ipset_mnl_fini,
|
||||
.fill_hdr = ipset_mnl_fill_hdr,
|
||||
.query = ipset_mnl_query,
|
||||
};
|
||||
1631
extensions/ipset-6/libipset/parse.c
Normal file
1631
extensions/ipset-6/libipset/parse.c
Normal file
File diff suppressed because it is too large
Load Diff
820
extensions/ipset-6/libipset/print.c
Normal file
820
extensions/ipset-6/libipset/print.c
Normal file
@@ -0,0 +1,820 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <assert.h> /* assert */
|
||||
#include <errno.h> /* errno */
|
||||
#include <stdio.h> /* snprintf */
|
||||
#include <netdb.h> /* getservbyport */
|
||||
#include <sys/types.h> /* inet_ntop */
|
||||
#include <sys/socket.h> /* inet_ntop */
|
||||
#include <arpa/inet.h> /* inet_ntop */
|
||||
#include <net/ethernet.h> /* ETH_ALEN */
|
||||
#include <net/if.h> /* IFNAMSIZ */
|
||||
|
||||
#include <libipset/debug.h> /* D() */
|
||||
#include <libipset/data.h> /* ipset_data_* */
|
||||
#include <libipset/icmp.h> /* icmp_to_name */
|
||||
#include <libipset/icmpv6.h> /* icmpv6_to_name */
|
||||
#include <libipset/parse.h> /* IPSET_*_SEPARATOR */
|
||||
#include <libipset/types.h> /* ipset set types */
|
||||
#include <libipset/session.h> /* IPSET_FLAG_ */
|
||||
#include <libipset/utils.h> /* UNUSED */
|
||||
#include <libipset/ui.h> /* IPSET_ENV_* */
|
||||
#include <libipset/print.h> /* prototypes */
|
||||
|
||||
/* Print data (to output buffer). All function must follow snprintf. */
|
||||
|
||||
#define SNPRINTF_FAILURE(size, len, offset) \
|
||||
do { \
|
||||
if (size < 0 || (unsigned int) size >= len) \
|
||||
return size; \
|
||||
offset += size; \
|
||||
len -= size; \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* ipset_print_ether - print ethernet address to string
|
||||
* @buf: printing buffer
|
||||
* @len: length of available buffer space
|
||||
* @data: data blob
|
||||
* @opt: the option kind
|
||||
* @env: environment flags
|
||||
*
|
||||
* Print Ethernet address to output buffer.
|
||||
*
|
||||
* Return lenght of printed string or error size.
|
||||
*/
|
||||
int
|
||||
ipset_print_ether(char *buf, unsigned int len,
|
||||
const struct ipset_data *data, enum ipset_opt opt,
|
||||
uint8_t env UNUSED)
|
||||
{
|
||||
const unsigned char *ether;
|
||||
int i, size, offset = 0;
|
||||
|
||||
assert(buf);
|
||||
assert(len > 0);
|
||||
assert(data);
|
||||
assert(opt == IPSET_OPT_ETHER);
|
||||
|
||||
if (len < ETH_ALEN*3)
|
||||
return -1;
|
||||
|
||||
ether = ipset_data_get(data, opt);
|
||||
assert(ether);
|
||||
|
||||
size = snprintf(buf, len, "%02X", ether[0]);
|
||||
SNPRINTF_FAILURE(size, len, offset);
|
||||
for (i = 1; i < ETH_ALEN; i++) {
|
||||
size = snprintf(buf + offset, len, ":%02X", ether[i]);
|
||||
SNPRINTF_FAILURE(size, len, offset);
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_print_family - print INET family
|
||||
* @buf: printing buffer
|
||||
* @len: length of available buffer space
|
||||
* @data: data blob
|
||||
* @opt: the option kind
|
||||
* @env: environment flags
|
||||
*
|
||||
* Print INET family string to output buffer.
|
||||
*
|
||||
* Return lenght of printed string or error size.
|
||||
*/
|
||||
int
|
||||
ipset_print_family(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt ASSERT_UNUSED,
|
||||
uint8_t env UNUSED)
|
||||
{
|
||||
uint8_t family;
|
||||
|
||||
assert(buf);
|
||||
assert(len > 0);
|
||||
assert(data);
|
||||
assert(opt == IPSET_OPT_FAMILY);
|
||||
|
||||
if (len < strlen("inet6") + 1)
|
||||
return -1;
|
||||
|
||||
family = ipset_data_family(data);
|
||||
|
||||
return snprintf(buf, len, "%s",
|
||||
family == AF_INET ? "inet" :
|
||||
family == AF_INET6 ? "inet6" : "any");
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_print_type - print ipset type string
|
||||
* @buf: printing buffer
|
||||
* @len: length of available buffer space
|
||||
* @data: data blob
|
||||
* @opt: the option kind
|
||||
* @env: environment flags
|
||||
*
|
||||
* Print ipset module string identifier to output buffer.
|
||||
*
|
||||
* Return lenght of printed string or error size.
|
||||
*/
|
||||
int
|
||||
ipset_print_type(char *buf, unsigned int len,
|
||||
const struct ipset_data *data, enum ipset_opt opt,
|
||||
uint8_t env UNUSED)
|
||||
{
|
||||
const struct ipset_type *type;
|
||||
|
||||
assert(buf);
|
||||
assert(len > 0);
|
||||
assert(data);
|
||||
assert(opt == IPSET_OPT_TYPE);
|
||||
|
||||
type = ipset_data_get(data, opt);
|
||||
assert(type);
|
||||
if (len < strlen(type->name) + 1)
|
||||
return -1;
|
||||
|
||||
return snprintf(buf, len, "%s", type->name);
|
||||
}
|
||||
|
||||
static inline int
|
||||
__getnameinfo4(char *buf, unsigned int len,
|
||||
int flags, const union nf_inet_addr *addr)
|
||||
{
|
||||
struct sockaddr_in saddr;
|
||||
int err;
|
||||
|
||||
memset(&saddr, 0, sizeof(saddr));
|
||||
in4cpy(&saddr.sin_addr, &addr->in);
|
||||
saddr.sin_family = NFPROTO_IPV4;
|
||||
|
||||
err = getnameinfo((const struct sockaddr *)&saddr,
|
||||
sizeof(saddr),
|
||||
buf, len, NULL, 0, flags);
|
||||
|
||||
if (!(flags & NI_NUMERICHOST) &&
|
||||
(err == EAI_AGAIN || (err == 0 && strchr(buf, '-') != NULL)))
|
||||
err = getnameinfo((const struct sockaddr *)&saddr,
|
||||
sizeof(saddr),
|
||||
buf, len, NULL, 0,
|
||||
flags | NI_NUMERICHOST);
|
||||
D("getnameinfo err: %i, errno %i", err, errno);
|
||||
return (err == 0 ? (int)strlen(buf) :
|
||||
(err == EAI_OVERFLOW || err == EAI_SYSTEM) ? (int)len : -1);
|
||||
}
|
||||
|
||||
static inline int
|
||||
__getnameinfo6(char *buf, unsigned int len,
|
||||
int flags, const union nf_inet_addr *addr)
|
||||
{
|
||||
struct sockaddr_in6 saddr;
|
||||
int err;
|
||||
|
||||
memset(&saddr, 0, sizeof(saddr));
|
||||
in6cpy(&saddr.sin6_addr, &addr->in6);
|
||||
saddr.sin6_family = NFPROTO_IPV6;
|
||||
|
||||
err = getnameinfo((const struct sockaddr *)&saddr,
|
||||
sizeof(saddr),
|
||||
buf, len, NULL, 0, flags);
|
||||
|
||||
if (!(flags & NI_NUMERICHOST) &&
|
||||
(err == EAI_AGAIN || (err == 0 && strchr(buf, '-') != NULL)))
|
||||
err = getnameinfo((const struct sockaddr *)&saddr,
|
||||
sizeof(saddr),
|
||||
buf, len, NULL, 0,
|
||||
flags | NI_NUMERICHOST);
|
||||
D("getnameinfo err: %i, errno %i", err, errno);
|
||||
return (err == 0 ? (int)strlen(buf) :
|
||||
(err == EAI_OVERFLOW || err == EAI_SYSTEM) ? (int)len : -1);
|
||||
}
|
||||
|
||||
#define SNPRINTF_IP(mask, f) \
|
||||
static int \
|
||||
snprintf_ipv##f(char *buf, unsigned int len, int flags, \
|
||||
const union nf_inet_addr *ip, uint8_t cidr) \
|
||||
{ \
|
||||
int size, offset = 0; \
|
||||
\
|
||||
size = __getnameinfo##f(buf, len, flags, ip); \
|
||||
SNPRINTF_FAILURE(size, len, offset); \
|
||||
\
|
||||
D("cidr %u mask %u", cidr, mask); \
|
||||
if (cidr == mask) \
|
||||
return offset; \
|
||||
D("print cidr"); \
|
||||
size = snprintf(buf + offset, len, \
|
||||
"%s%u", IPSET_CIDR_SEPARATOR, cidr); \
|
||||
SNPRINTF_FAILURE(size, len, offset); \
|
||||
return offset; \
|
||||
}
|
||||
|
||||
SNPRINTF_IP(32, 4)
|
||||
|
||||
SNPRINTF_IP(128, 6)
|
||||
|
||||
/**
|
||||
* ipset_print_ip - print IPv4|IPv6 address to string
|
||||
* @buf: printing buffer
|
||||
* @len: length of available buffer space
|
||||
* @data: data blob
|
||||
* @opt: the option kind
|
||||
* @env: environment flags
|
||||
*
|
||||
* Print IPv4|IPv6 address, address/cidr or address range to output buffer.
|
||||
*
|
||||
* Return lenght of printed string or error size.
|
||||
*/
|
||||
int
|
||||
ipset_print_ip(char *buf, unsigned int len,
|
||||
const struct ipset_data *data, enum ipset_opt opt,
|
||||
uint8_t env)
|
||||
{
|
||||
const union nf_inet_addr *ip;
|
||||
uint8_t family, cidr;
|
||||
int flags, size, offset = 0;
|
||||
enum ipset_opt cidropt;
|
||||
|
||||
assert(buf);
|
||||
assert(len > 0);
|
||||
assert(data);
|
||||
assert(opt == IPSET_OPT_IP || opt == IPSET_OPT_IP2);
|
||||
|
||||
D("len: %u", len);
|
||||
family = ipset_data_family(data);
|
||||
cidropt = opt == IPSET_OPT_IP ? IPSET_OPT_CIDR : IPSET_OPT_CIDR2;
|
||||
if (ipset_data_test(data, cidropt)) {
|
||||
cidr = *(const uint8_t *) ipset_data_get(data, cidropt);
|
||||
D("CIDR: %u", cidr);
|
||||
} else
|
||||
cidr = family == NFPROTO_IPV6 ? 128 : 32;
|
||||
flags = (env & IPSET_ENV_RESOLVE) ? 0 : NI_NUMERICHOST;
|
||||
|
||||
ip = ipset_data_get(data, opt);
|
||||
assert(ip);
|
||||
if (family == NFPROTO_IPV4)
|
||||
size = snprintf_ipv4(buf, len, flags, ip, cidr);
|
||||
else if (family == NFPROTO_IPV6)
|
||||
size = snprintf_ipv6(buf, len, flags, ip, cidr);
|
||||
else
|
||||
return -1;
|
||||
D("size %i, len %u", size, len);
|
||||
SNPRINTF_FAILURE(size, len, offset);
|
||||
|
||||
D("len: %u, offset %u", len, offset);
|
||||
if (!ipset_data_test(data, IPSET_OPT_IP_TO))
|
||||
return offset;
|
||||
|
||||
size = snprintf(buf + offset, len, "%s", IPSET_RANGE_SEPARATOR);
|
||||
SNPRINTF_FAILURE(size, len, offset);
|
||||
|
||||
ip = ipset_data_get(data, IPSET_OPT_IP_TO);
|
||||
if (family == NFPROTO_IPV4)
|
||||
size = snprintf_ipv4(buf + offset, len, flags, ip, cidr);
|
||||
else if (family == NFPROTO_IPV6)
|
||||
size = snprintf_ipv6(buf + offset, len, flags, ip, cidr);
|
||||
else
|
||||
return -1;
|
||||
|
||||
SNPRINTF_FAILURE(size, len, offset);
|
||||
return offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_print_ipaddr - print IPv4|IPv6 address to string
|
||||
* @buf: printing buffer
|
||||
* @len: length of available buffer space
|
||||
* @data: data blob
|
||||
* @opt: the option kind
|
||||
* @env: environment flags
|
||||
*
|
||||
* Print IPv4|IPv6 address or address/cidr to output buffer.
|
||||
*
|
||||
* Return lenght of printed string or error size.
|
||||
*/
|
||||
int
|
||||
ipset_print_ipaddr(char *buf, unsigned int len,
|
||||
const struct ipset_data *data, enum ipset_opt opt,
|
||||
uint8_t env)
|
||||
{
|
||||
const union nf_inet_addr *ip;
|
||||
uint8_t family, cidr;
|
||||
enum ipset_opt cidropt;
|
||||
int flags;
|
||||
|
||||
assert(buf);
|
||||
assert(len > 0);
|
||||
assert(data);
|
||||
assert(opt == IPSET_OPT_IP ||
|
||||
opt == IPSET_OPT_IP_TO ||
|
||||
opt == IPSET_OPT_IP2);
|
||||
|
||||
family = ipset_data_family(data);
|
||||
cidropt = opt == IPSET_OPT_IP ? IPSET_OPT_CIDR : IPSET_OPT_CIDR2;
|
||||
if (ipset_data_test(data, cidropt))
|
||||
cidr = *(const uint8_t *) ipset_data_get(data, cidropt);
|
||||
else
|
||||
cidr = family == NFPROTO_IPV6 ? 128 : 32;
|
||||
flags = (env & IPSET_ENV_RESOLVE) ? 0 : NI_NUMERICHOST;
|
||||
|
||||
ip = ipset_data_get(data, opt);
|
||||
assert(ip);
|
||||
if (family == NFPROTO_IPV4)
|
||||
return snprintf_ipv4(buf, len, flags, ip, cidr);
|
||||
else if (family == NFPROTO_IPV6)
|
||||
return snprintf_ipv6(buf, len, flags, ip, cidr);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_print_number - print number to string
|
||||
* @buf: printing buffer
|
||||
* @len: length of available buffer space
|
||||
* @data: data blob
|
||||
* @opt: the option kind
|
||||
* @env: environment flags
|
||||
*
|
||||
* Print number to output buffer.
|
||||
*
|
||||
* Return lenght of printed string or error size.
|
||||
*/
|
||||
int
|
||||
ipset_print_number(char *buf, unsigned int len,
|
||||
const struct ipset_data *data, enum ipset_opt opt,
|
||||
uint8_t env UNUSED)
|
||||
{
|
||||
size_t maxsize;
|
||||
const void *number;
|
||||
|
||||
assert(buf);
|
||||
assert(len > 0);
|
||||
assert(data);
|
||||
|
||||
number = ipset_data_get(data, opt);
|
||||
maxsize = ipset_data_sizeof(opt, AF_INET);
|
||||
D("opt: %u, maxsize %zu", opt, maxsize);
|
||||
if (maxsize == sizeof(uint8_t))
|
||||
return snprintf(buf, len, "%u", *(const uint8_t *) number);
|
||||
else if (maxsize == sizeof(uint16_t))
|
||||
return snprintf(buf, len, "%u", *(const uint16_t *) number);
|
||||
else if (maxsize == sizeof(uint32_t))
|
||||
return snprintf(buf, len, "%lu",
|
||||
(long unsigned) *(const uint32_t *) number);
|
||||
else
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_print_name - print setname element string
|
||||
* @buf: printing buffer
|
||||
* @len: length of available buffer space
|
||||
* @data: data blob
|
||||
* @opt: the option kind
|
||||
* @env: environment flags
|
||||
*
|
||||
* Print setname element string to output buffer.
|
||||
*
|
||||
* Return lenght of printed string or error size.
|
||||
*/
|
||||
int
|
||||
ipset_print_name(char *buf, unsigned int len,
|
||||
const struct ipset_data *data, enum ipset_opt opt,
|
||||
uint8_t env UNUSED)
|
||||
{
|
||||
const char *name;
|
||||
int size, offset = 0;
|
||||
|
||||
assert(buf);
|
||||
assert(len > 0);
|
||||
assert(data);
|
||||
assert(opt == IPSET_OPT_NAME);
|
||||
|
||||
if (len < 2*IPSET_MAXNAMELEN + 2 + strlen("before"))
|
||||
return -1;
|
||||
|
||||
name = ipset_data_get(data, opt);
|
||||
assert(name);
|
||||
size = snprintf(buf, len, "%s", name);
|
||||
SNPRINTF_FAILURE(size, len, offset);
|
||||
|
||||
if (ipset_data_test(data, IPSET_OPT_NAMEREF)) {
|
||||
bool before = false;
|
||||
if (ipset_data_flags_test(data, IPSET_FLAG(IPSET_OPT_FLAGS))) {
|
||||
const uint32_t *flags =
|
||||
ipset_data_get(data, IPSET_OPT_FLAGS);
|
||||
before = (*flags) & IPSET_FLAG_BEFORE;
|
||||
}
|
||||
size = snprintf(buf + offset, len,
|
||||
" %s %s", before ? "before" : "after",
|
||||
(const char *) ipset_data_get(data,
|
||||
IPSET_OPT_NAMEREF));
|
||||
SNPRINTF_FAILURE(size, len, offset);
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_print_port - print port or port range
|
||||
* @buf: printing buffer
|
||||
* @len: length of available buffer space
|
||||
* @data: data blob
|
||||
* @opt: the option kind
|
||||
* @env: environment flags
|
||||
*
|
||||
* Print port or port range to output buffer.
|
||||
*
|
||||
* Return lenght of printed string or error size.
|
||||
*/
|
||||
int
|
||||
ipset_print_port(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt ASSERT_UNUSED,
|
||||
uint8_t env UNUSED)
|
||||
{
|
||||
const uint16_t *port;
|
||||
int size, offset = 0;
|
||||
|
||||
assert(buf);
|
||||
assert(len > 0);
|
||||
assert(data);
|
||||
assert(opt == IPSET_OPT_PORT);
|
||||
|
||||
if (len < 2*strlen("65535") + 2)
|
||||
return -1;
|
||||
|
||||
port = ipset_data_get(data, IPSET_OPT_PORT);
|
||||
assert(port);
|
||||
size = snprintf(buf, len, "%u", *port);
|
||||
SNPRINTF_FAILURE(size, len, offset);
|
||||
|
||||
if (ipset_data_test(data, IPSET_OPT_PORT_TO)) {
|
||||
port = ipset_data_get(data, IPSET_OPT_PORT_TO);
|
||||
size = snprintf(buf + offset, len,
|
||||
"%s%u",
|
||||
IPSET_RANGE_SEPARATOR, *port);
|
||||
SNPRINTF_FAILURE(size, len, offset);
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_print_iface - print interface element string
|
||||
* @buf: printing buffer
|
||||
* @len: length of available buffer space
|
||||
* @data: data blob
|
||||
* @opt: the option kind
|
||||
* @env: environment flags
|
||||
*
|
||||
* Print interface element string to output buffer.
|
||||
*
|
||||
* Return lenght of printed string or error size.
|
||||
*/
|
||||
int
|
||||
ipset_print_iface(char *buf, unsigned int len,
|
||||
const struct ipset_data *data, enum ipset_opt opt,
|
||||
uint8_t env UNUSED)
|
||||
{
|
||||
const char *name;
|
||||
int size, offset = 0;
|
||||
|
||||
assert(buf);
|
||||
assert(len > 0);
|
||||
assert(data);
|
||||
assert(opt == IPSET_OPT_IFACE);
|
||||
|
||||
if (len < IFNAMSIZ + strlen("physdev:"))
|
||||
return -1;
|
||||
|
||||
if (ipset_data_test(data, IPSET_OPT_PHYSDEV)) {
|
||||
size = snprintf(buf, len, "physdev:");
|
||||
SNPRINTF_FAILURE(size, len, offset);
|
||||
}
|
||||
name = ipset_data_get(data, opt);
|
||||
assert(name);
|
||||
size = snprintf(buf, len, "%s", name);
|
||||
SNPRINTF_FAILURE(size, len, offset);
|
||||
return offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_print_proto - print protocol name
|
||||
* @buf: printing buffer
|
||||
* @len: length of available buffer space
|
||||
* @data: data blob
|
||||
* @opt: the option kind
|
||||
* @env: environment flags
|
||||
*
|
||||
* Print protocol name to output buffer.
|
||||
*
|
||||
* Return lenght of printed string or error size.
|
||||
*/
|
||||
int
|
||||
ipset_print_proto(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt ASSERT_UNUSED,
|
||||
uint8_t env UNUSED)
|
||||
{
|
||||
const struct protoent *protoent;
|
||||
uint8_t proto;
|
||||
|
||||
assert(buf);
|
||||
assert(len > 0);
|
||||
assert(data);
|
||||
assert(opt == IPSET_OPT_PROTO);
|
||||
|
||||
proto = *(const uint8_t *) ipset_data_get(data, IPSET_OPT_PROTO);
|
||||
assert(proto);
|
||||
|
||||
protoent = getprotobynumber(proto);
|
||||
if (protoent)
|
||||
return snprintf(buf, len, "%s", protoent->p_name);
|
||||
|
||||
/* Should not happen */
|
||||
return snprintf(buf, len, "%u", proto);
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_print_icmp - print ICMP code name or type/code
|
||||
* @buf: printing buffer
|
||||
* @len: length of available buffer space
|
||||
* @data: data blob
|
||||
* @opt: the option kind
|
||||
* @env: environment flags
|
||||
*
|
||||
* Print ICMP code name or type/code name to output buffer.
|
||||
*
|
||||
* Return lenght of printed string or error size.
|
||||
*/
|
||||
int
|
||||
ipset_print_icmp(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt ASSERT_UNUSED,
|
||||
uint8_t env UNUSED)
|
||||
{
|
||||
const char *name;
|
||||
uint16_t typecode;
|
||||
|
||||
assert(buf);
|
||||
assert(len > 0);
|
||||
assert(data);
|
||||
assert(opt == IPSET_OPT_PORT);
|
||||
|
||||
typecode = *(const uint16_t *) ipset_data_get(data, IPSET_OPT_PORT);
|
||||
name = icmp_to_name(typecode >> 8, typecode & 0xFF);
|
||||
if (name != NULL)
|
||||
return snprintf(buf, len, "%s", name);
|
||||
else
|
||||
return snprintf(buf, len, "%u/%u",
|
||||
typecode >> 8, typecode & 0xFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_print_icmpv6 - print ICMPv6 code name or type/code
|
||||
* @buf: printing buffer
|
||||
* @len: length of available buffer space
|
||||
* @data: data blob
|
||||
* @opt: the option kind
|
||||
* @env: environment flags
|
||||
*
|
||||
* Print ICMPv6 code name or type/code name to output buffer.
|
||||
*
|
||||
* Return lenght of printed string or error size.
|
||||
*/
|
||||
int
|
||||
ipset_print_icmpv6(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt ASSERT_UNUSED,
|
||||
uint8_t env UNUSED)
|
||||
{
|
||||
const char *name;
|
||||
uint16_t typecode;
|
||||
|
||||
assert(buf);
|
||||
assert(len > 0);
|
||||
assert(data);
|
||||
assert(opt == IPSET_OPT_PORT);
|
||||
|
||||
typecode = *(const uint16_t *) ipset_data_get(data, IPSET_OPT_PORT);
|
||||
name = icmpv6_to_name(typecode >> 8, typecode & 0xFF);
|
||||
if (name != NULL)
|
||||
return snprintf(buf, len, "%s", name);
|
||||
else
|
||||
return snprintf(buf, len, "%u/%u",
|
||||
typecode >> 8, typecode & 0xFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_print_proto_port - print proto:port
|
||||
* @buf: printing buffer
|
||||
* @len: length of available buffer space
|
||||
* @data: data blob
|
||||
* @opt: the option kind
|
||||
* @env: environment flags
|
||||
*
|
||||
* Print protocol and port to output buffer.
|
||||
*
|
||||
* Return lenght of printed string or error size.
|
||||
*/
|
||||
int
|
||||
ipset_print_proto_port(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt ASSERT_UNUSED,
|
||||
uint8_t env UNUSED)
|
||||
{
|
||||
int size, offset = 0;
|
||||
|
||||
assert(buf);
|
||||
assert(len > 0);
|
||||
assert(data);
|
||||
assert(opt == IPSET_OPT_PORT);
|
||||
|
||||
if (ipset_data_flags_test(data, IPSET_FLAG(IPSET_OPT_PROTO))) {
|
||||
uint8_t proto = *(const uint8_t *) ipset_data_get(data,
|
||||
IPSET_OPT_PROTO);
|
||||
size = ipset_print_proto(buf, len, data, IPSET_OPT_PROTO, env);
|
||||
SNPRINTF_FAILURE(size, len, offset);
|
||||
if (len < 2)
|
||||
return -ENOSPC;
|
||||
size = snprintf(buf + offset, len, IPSET_PROTO_SEPARATOR);
|
||||
SNPRINTF_FAILURE(size, len, offset);
|
||||
|
||||
switch (proto) {
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_SCTP:
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_UDPLITE:
|
||||
break;
|
||||
case IPPROTO_ICMP:
|
||||
return ipset_print_icmp(buf + offset, len, data,
|
||||
IPSET_OPT_PORT, env);
|
||||
case IPPROTO_ICMPV6:
|
||||
return ipset_print_icmpv6(buf + offset, len, data,
|
||||
IPSET_OPT_PORT, env);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
size = ipset_print_port(buf + offset, len, data, IPSET_OPT_PORT, env);
|
||||
SNPRINTF_FAILURE(size, len, offset);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
#define print_second(data) \
|
||||
ipset_data_flags_test(data, \
|
||||
IPSET_FLAG(IPSET_OPT_PORT)|IPSET_FLAG(IPSET_OPT_ETHER))
|
||||
|
||||
#define print_third(data) \
|
||||
ipset_data_flags_test(data, IPSET_FLAG(IPSET_OPT_IP2))
|
||||
|
||||
/**
|
||||
* ipset_print_elem - print ADT elem according to settype
|
||||
* @buf: printing buffer
|
||||
* @len: length of available buffer space
|
||||
* @data: data blob
|
||||
* @opt: the option kind
|
||||
* @env: environment flags
|
||||
*
|
||||
* Print (multipart) element according to settype
|
||||
*
|
||||
* Return lenght of printed string or error size.
|
||||
*/
|
||||
int
|
||||
ipset_print_elem(char *buf, unsigned int len,
|
||||
const struct ipset_data *data, enum ipset_opt opt UNUSED,
|
||||
uint8_t env)
|
||||
{
|
||||
const struct ipset_type *type;
|
||||
int size, offset = 0;
|
||||
|
||||
assert(buf);
|
||||
assert(len > 0);
|
||||
assert(data);
|
||||
|
||||
type = ipset_data_get(data, IPSET_OPT_TYPE);
|
||||
if (!type)
|
||||
return -1;
|
||||
|
||||
size = type->elem[IPSET_DIM_ONE - 1].print(buf, len, data,
|
||||
type->elem[IPSET_DIM_ONE - 1].opt, env);
|
||||
SNPRINTF_FAILURE(size, len, offset);
|
||||
IF_D(ipset_data_test(data, type->elem[IPSET_DIM_TWO - 1].opt),
|
||||
"print second elem");
|
||||
if (type->dimension == IPSET_DIM_ONE ||
|
||||
(type->last_elem_optional &&
|
||||
!ipset_data_test(data, type->elem[IPSET_DIM_TWO - 1].opt)))
|
||||
return offset;
|
||||
|
||||
size = snprintf(buf + offset, len, IPSET_ELEM_SEPARATOR);
|
||||
SNPRINTF_FAILURE(size, len, offset);
|
||||
size = type->elem[IPSET_DIM_TWO - 1].print(buf + offset, len, data,
|
||||
type->elem[IPSET_DIM_TWO - 1].opt, env);
|
||||
SNPRINTF_FAILURE(size, len, offset);
|
||||
if (type->dimension == IPSET_DIM_TWO ||
|
||||
(type->last_elem_optional &&
|
||||
!ipset_data_test(data, type->elem[IPSET_DIM_THREE - 1].opt)))
|
||||
return offset;
|
||||
|
||||
size = snprintf(buf + offset, len, IPSET_ELEM_SEPARATOR);
|
||||
SNPRINTF_FAILURE(size, len, offset);
|
||||
size = type->elem[IPSET_DIM_THREE - 1].print(buf + offset, len, data,
|
||||
type->elem[IPSET_DIM_THREE - 1].opt, env);
|
||||
SNPRINTF_FAILURE(size, len, offset);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_print_flag - print a flag
|
||||
* @buf: printing buffer
|
||||
* @len: length of available buffer space
|
||||
* @data: data blob
|
||||
* @opt: the option kind
|
||||
* @env: environment flags
|
||||
*
|
||||
* Print a flag, i.e. option without value
|
||||
*
|
||||
* Return lenght of printed string or error size.
|
||||
*/
|
||||
int
|
||||
ipset_print_flag(char *buf UNUSED, unsigned int len UNUSED,
|
||||
const struct ipset_data *data UNUSED,
|
||||
enum ipset_opt opt UNUSED, uint8_t env UNUSED)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_print_data - print data, generic fuction
|
||||
* @buf: printing buffer
|
||||
* @len: length of available buffer space
|
||||
* @data: data blob
|
||||
* @opt: the option kind
|
||||
* @env: environment flags
|
||||
*
|
||||
* Generic wrapper of the printing functions.
|
||||
*
|
||||
* Return lenght of printed string or error size.
|
||||
*/
|
||||
int
|
||||
ipset_print_data(char *buf, unsigned int len,
|
||||
const struct ipset_data *data, enum ipset_opt opt,
|
||||
uint8_t env)
|
||||
{
|
||||
int size = 0, offset = 0;
|
||||
|
||||
assert(buf);
|
||||
assert(len > 0);
|
||||
assert(data);
|
||||
|
||||
switch (opt) {
|
||||
case IPSET_OPT_FAMILY:
|
||||
size = ipset_print_family(buf, len, data, opt, env);
|
||||
break;
|
||||
case IPSET_OPT_TYPE:
|
||||
size = ipset_print_type(buf, len, data, opt, env);
|
||||
break;
|
||||
case IPSET_SETNAME:
|
||||
size = snprintf(buf, len, "%s", ipset_data_setname(data));
|
||||
break;
|
||||
case IPSET_OPT_ELEM:
|
||||
size = ipset_print_elem(buf, len, data, opt, env);
|
||||
break;
|
||||
case IPSET_OPT_IP:
|
||||
size = ipset_print_ip(buf, len, data, opt, env);
|
||||
break;
|
||||
case IPSET_OPT_PORT:
|
||||
size = ipset_print_port(buf, len, data, opt, env);
|
||||
break;
|
||||
case IPSET_OPT_IFACE:
|
||||
size = ipset_print_iface(buf, len, data, opt, env);
|
||||
break;
|
||||
case IPSET_OPT_GC:
|
||||
case IPSET_OPT_HASHSIZE:
|
||||
case IPSET_OPT_MAXELEM:
|
||||
case IPSET_OPT_NETMASK:
|
||||
case IPSET_OPT_PROBES:
|
||||
case IPSET_OPT_RESIZE:
|
||||
case IPSET_OPT_TIMEOUT:
|
||||
case IPSET_OPT_REFERENCES:
|
||||
case IPSET_OPT_ELEMENTS:
|
||||
case IPSET_OPT_SIZE:
|
||||
size = ipset_print_number(buf, len, data, opt, env);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
SNPRINTF_FAILURE(size, len, offset);
|
||||
|
||||
return offset;
|
||||
}
|
||||
2013
extensions/ipset-6/libipset/session.c
Normal file
2013
extensions/ipset-6/libipset/session.c
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user