mirror of
git://git.code.sf.net/p/xtables-addons/xtables-addons
synced 2025-09-20 19:44:56 +02:00
Compare commits
289 Commits
v1.47
...
e3ae438e2e
Author | SHA1 | Date | |
---|---|---|---|
![]() |
e3ae438e2e | ||
![]() |
c90ecf4320 | ||
![]() |
1abcd731c0 | ||
![]() |
af10045c75 | ||
![]() |
6d74a85f70 | ||
![]() |
b9893b9505 | ||
![]() |
714998176a | ||
![]() |
81ab0b9586 | ||
![]() |
1f308c7262 | ||
![]() |
87189b0051 | ||
![]() |
d3fb275c03 | ||
![]() |
9faa3085bb | ||
![]() |
947a677ddb | ||
![]() |
42a9b5c6c3 | ||
![]() |
3233a0ed2c | ||
![]() |
97808473f9 | ||
![]() |
3aa4ca3eaf | ||
![]() |
5104269605 | ||
![]() |
4ee209416f | ||
![]() |
43df040e05 | ||
![]() |
f59a4eb9d9 | ||
![]() |
a238253509 | ||
![]() |
4547e4c5cc | ||
![]() |
5d94a36d22 | ||
![]() |
9d5b2e2e0e | ||
![]() |
f973577ec0 | ||
![]() |
a35feefa0f | ||
![]() |
a1b3d81ccb | ||
![]() |
6504f251c6 | ||
![]() |
1c67775d10 | ||
![]() |
7327cd725b | ||
![]() |
5c8aecdd56 | ||
![]() |
5ad9de75d4 | ||
![]() |
9e84e8f13d | ||
![]() |
50153ffdb9 | ||
![]() |
9c4aeea422 | ||
![]() |
c09d0704af | ||
![]() |
0021003dc7 | ||
![]() |
0ab3247900 | ||
![]() |
d3f7dc1f55 | ||
![]() |
87d3aab175 | ||
![]() |
bfb0516c79 | ||
![]() |
939d3ee0d3 | ||
![]() |
5df71f8741 | ||
![]() |
82379e8ec1 | ||
![]() |
b3a3f2e91b | ||
![]() |
63fb5d3490 | ||
![]() |
05cacbe84c | ||
![]() |
3c120ef5f1 | ||
![]() |
b0a1aacd4b | ||
![]() |
c3bd1c61d1 | ||
![]() |
9cd0b44c81 | ||
![]() |
b4faa4de65 | ||
![]() |
b05ea5644c | ||
![]() |
b052ec0f7d | ||
![]() |
249df831b0 | ||
![]() |
86112194da | ||
![]() |
20e1b669fc | ||
![]() |
e4784832ed | ||
![]() |
48e30a0990 | ||
![]() |
ea588d0b9c | ||
![]() |
96460646e9 | ||
![]() |
2cb4b2bec6 | ||
![]() |
37f19c6b96 | ||
![]() |
73b96e25e4 | ||
![]() |
ca84ee8e15 | ||
![]() |
c9ba3507fc | ||
![]() |
b87366bb83 | ||
![]() |
8bbb0cb3eb | ||
![]() |
b4629f46c6 | ||
![]() |
f7f18f0c4f | ||
![]() |
9193adc835 | ||
![]() |
74fcd4a2ae | ||
![]() |
4b43df69f5 | ||
![]() |
4c68c774c8 | ||
![]() |
0888357642 | ||
![]() |
d31067b32e | ||
![]() |
fc44fcb94f | ||
![]() |
26f5bcbdbb | ||
![]() |
061fc794b5 | ||
![]() |
bf1ca298ae | ||
![]() |
6e5edc8372 | ||
![]() |
7ad14b7150 | ||
![]() |
0cc51e6b35 | ||
![]() |
fa7bcbfb9b | ||
![]() |
d86101e470 | ||
![]() |
00114dea3d | ||
![]() |
d4c2aac5f8 | ||
![]() |
5622c5f024 | ||
![]() |
358991306c | ||
![]() |
2bbdcb1d58 | ||
![]() |
b14728691d | ||
![]() |
708f883635 | ||
![]() |
f822b8bc1b | ||
![]() |
4205900d9b | ||
![]() |
266638e41e | ||
![]() |
ebcd176822 | ||
![]() |
6b47d09a36 | ||
![]() |
1849c47ae8 | ||
![]() |
68d895f75c | ||
![]() |
53b6b862cc | ||
![]() |
ed10cb9c17 | ||
![]() |
5903f4bcfc | ||
![]() |
5e19871613 | ||
![]() |
30fb410003 | ||
![]() |
3ea761a1ed | ||
![]() |
4603d3e0f4 | ||
![]() |
b0b2b5a74c | ||
![]() |
082d42fb21 | ||
![]() |
b1f0e118a0 | ||
![]() |
56fba3ecff | ||
![]() |
9057fb48f3 | ||
![]() |
e19f91ddb4 | ||
![]() |
256ac1a4f6 | ||
![]() |
b91dbd03c7 | ||
![]() |
254c6926d3 | ||
![]() |
2e78cf03a4 | ||
![]() |
bf63a25a64 | ||
![]() |
94656621ed | ||
![]() |
95d4f9e113 | ||
![]() |
123e1a14e9 | ||
![]() |
f4f3f98609 | ||
![]() |
9b1c7c1c04 | ||
![]() |
ed8e496750 | ||
![]() |
5339fcc65b | ||
![]() |
2265c1b854 | ||
![]() |
2c574f992d | ||
![]() |
3a24468a68 | ||
![]() |
7682cc8c34 | ||
![]() |
215b3c5b12 | ||
![]() |
4dbb36b723 | ||
![]() |
10f951e61d | ||
![]() |
a4c50ae405 | ||
![]() |
38d89983ca | ||
![]() |
25985650a9 | ||
![]() |
4de9ff1505 | ||
![]() |
46b7cf206b | ||
![]() |
29d10e11fa | ||
![]() |
60a26f1dea | ||
![]() |
cdf90737be | ||
![]() |
5713415014 | ||
![]() |
230bc1f327 | ||
![]() |
d360f5578c | ||
![]() |
dd32060f6a | ||
![]() |
d5eb4e586c | ||
![]() |
1b4b4347c5 | ||
![]() |
2f37af43c5 | ||
![]() |
56e5970c64 | ||
![]() |
2b76b68c65 | ||
![]() |
d2eeac4c32 | ||
![]() |
0e9037b000 | ||
![]() |
0a6091b64a | ||
![]() |
b565a85fb6 | ||
![]() |
425a035959 | ||
![]() |
89c80f5981 | ||
![]() |
8579fd2b3b | ||
![]() |
0a836e9677 | ||
![]() |
90b0f3a51f | ||
![]() |
89d1b808b9 | ||
![]() |
c839e87bbb | ||
![]() |
a587f9526d | ||
![]() |
1874fcd519 | ||
![]() |
21ea7b76ec | ||
![]() |
ee8da2b1ac | ||
![]() |
19a4359368 | ||
![]() |
1b379667d3 | ||
![]() |
cd410aefe7 | ||
![]() |
e4b5cef8f0 | ||
![]() |
a8af97b8fa | ||
![]() |
db234c30cd | ||
![]() |
2e6fb73e85 | ||
![]() |
6024758b28 | ||
![]() |
69f3f21a32 | ||
![]() |
7af1b9737c | ||
![]() |
f5e95f35a7 | ||
![]() |
80bed0655f | ||
![]() |
bc6aaf74d8 | ||
![]() |
192243483a | ||
![]() |
e3114d60d5 | ||
![]() |
e6f20befad | ||
![]() |
5038e160f8 | ||
![]() |
a6289ec3ff | ||
![]() |
01e7128a80 | ||
![]() |
1dc2a1c2de | ||
![]() |
60b6b1dbef | ||
![]() |
fcb19403bc | ||
![]() |
f89f10bbe9 | ||
![]() |
a9358542fe | ||
![]() |
237fe7c660 | ||
![]() |
939fc901c1 | ||
![]() |
a4a077ff86 | ||
![]() |
bccf64d820 | ||
![]() |
7e3e156d92 | ||
![]() |
8f70b9a99d | ||
![]() |
e277360bcd | ||
![]() |
672f12b2a6 | ||
![]() |
8788b6c096 | ||
![]() |
96ce5ec488 | ||
![]() |
5e22c9c592 | ||
![]() |
01f97bfdd1 | ||
![]() |
1324442bce | ||
![]() |
a576f4d43e | ||
![]() |
cc17e1d0fe | ||
![]() |
c08835d65c | ||
![]() |
4c21811919 | ||
![]() |
431062c6ec | ||
![]() |
87adf3461f | ||
![]() |
f2e21e67a5 | ||
![]() |
ae307c0bf3 | ||
![]() |
ec8c6b8732 | ||
![]() |
7916b74a42 | ||
![]() |
7fbbd0401e | ||
![]() |
991c0cf4cf | ||
![]() |
b58e78968e | ||
![]() |
02eb0e5df9 | ||
![]() |
98ea6c538b | ||
![]() |
7cf7250e07 | ||
![]() |
f9b0ee7533 | ||
![]() |
a82d0ba517 | ||
![]() |
bc2bcc383c | ||
![]() |
c6c70ab30b | ||
![]() |
a0a8fbc091 | ||
![]() |
9414a5df34 | ||
![]() |
f28cfff138 | ||
![]() |
a8d7ec5ad6 | ||
![]() |
29f293743a | ||
![]() |
3bf7ebc48c | ||
![]() |
172bc7e306 | ||
![]() |
db45bbcb9e | ||
![]() |
b2cd0ab65b | ||
![]() |
b5a2f9aa14 | ||
![]() |
6fbb35d686 | ||
![]() |
e1d9825475 | ||
![]() |
efa8b9670a | ||
![]() |
2b38d081a5 | ||
![]() |
fda591dba4 | ||
![]() |
9de3027c02 | ||
![]() |
2dc8f21476 | ||
![]() |
e027089782 | ||
![]() |
fe7a30c746 | ||
![]() |
d582cc04df | ||
![]() |
13db8d78c9 | ||
![]() |
6a60b5ab75 | ||
![]() |
d48a5fe0f4 | ||
![]() |
b70905e7cb | ||
![]() |
3f04148501 | ||
![]() |
d96fff8893 | ||
![]() |
aceca54912 | ||
![]() |
cb1cdb190f | ||
![]() |
48ebf55444 | ||
![]() |
57c3cc1722 | ||
![]() |
29141b6e95 | ||
![]() |
cdac8506c3 | ||
![]() |
5494bc40f4 | ||
![]() |
bcdb7ed4e9 | ||
![]() |
1ed86c6bbd | ||
![]() |
2a5f1099c8 | ||
![]() |
c243c78af4 | ||
![]() |
91da2a0dbd | ||
![]() |
a160a2aa36 | ||
![]() |
b25e96fd49 | ||
![]() |
6d74f76a29 | ||
![]() |
78e47758c6 | ||
![]() |
bcdd42f556 | ||
![]() |
acf92ff914 | ||
![]() |
0e845bf23f | ||
![]() |
158e6a26eb | ||
![]() |
693c32f414 | ||
![]() |
3e337562d7 | ||
![]() |
bb25bc08c4 | ||
![]() |
ea3e4b2ed5 | ||
![]() |
557af2177f | ||
![]() |
60f5239630 | ||
![]() |
3ba7d8c3a9 | ||
![]() |
28d12faba8 | ||
![]() |
cf7a3d4342 | ||
![]() |
fabad77f8f | ||
![]() |
5e020d380c | ||
![]() |
a7fbf4f4de | ||
![]() |
4137f6c111 | ||
![]() |
04d8ebe31c | ||
![]() |
6ab4c02a54 | ||
![]() |
a66e4510b8 | ||
![]() |
31aebc134e | ||
![]() |
e640a15ec9 | ||
![]() |
66f213e324 | ||
![]() |
0dcc56bc62 | ||
![]() |
8db01220fd | ||
![]() |
95ff9a2de3 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,7 +1,10 @@
|
||||
*.gcno
|
||||
*.la
|
||||
*.lo
|
||||
*.loT
|
||||
*.mod
|
||||
*.o
|
||||
.cache.mk
|
||||
.deps/
|
||||
.dirstamp
|
||||
.libs/
|
||||
|
15
INSTALL
15
INSTALL
@@ -12,16 +12,21 @@ in combination with the kernel's Kbuild system.
|
||||
Supported configurations for this release
|
||||
=========================================
|
||||
|
||||
* iptables >= 1.4.5
|
||||
* iptables >= 1.6.0
|
||||
|
||||
* kernel-devel >= 2.6.32
|
||||
* kernel-devel >= 4.15
|
||||
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_NF_CONNTRACK
|
||||
- CONFIG_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
|
||||
|
||||
(Use xtables-addons-1.x if you need support for Linux < 3.7.
|
||||
Use xtables-addons-2.x if you need support for Linux < 4.15.)
|
||||
Note: xtables-addons regularly fails to build with patched-to-death
|
||||
kernels like on RHEL or SLES because the API does not match
|
||||
LINUX_KERNEL_VERSION anymore.
|
||||
|
||||
|
||||
Selecting extensions
|
||||
====================
|
||||
|
@@ -1,7 +1,7 @@
|
||||
# -*- Makefile -*-
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
SUBDIRS = extensions geoip
|
||||
SUBDIRS = extensions extensions/ACCOUNT extensions/pknock geoip
|
||||
|
||||
man_MANS := xtables-addons.8
|
||||
|
||||
@@ -11,8 +11,10 @@ FORCE:
|
||||
xtables-addons.8: FORCE
|
||||
${MAKE} -f Makefile.mans all;
|
||||
|
||||
install-exec-hook:
|
||||
depmod -a || :;
|
||||
clean-local-mans:
|
||||
${MAKE} -f Makefile.mans clean;
|
||||
|
||||
clean-local: clean-local-mans
|
||||
|
||||
config.status: Makefile.iptrules.in
|
||||
|
||||
|
@@ -3,8 +3,8 @@
|
||||
|
||||
srcdir := @srcdir@
|
||||
|
||||
wcman_matches := $(shell find "${srcdir}" -name 'libxt_[a-z]*.man' | sort)
|
||||
wcman_targets := $(shell find "${srcdir}" -name 'libxt_[A-Z]*.man' | sort)
|
||||
wcman_matches := $(shell find "${srcdir}/extensions" -name 'libxt_[a-z]*.man' -print | sort)
|
||||
wcman_targets := $(shell find "${srcdir}/extensions" -name 'libxt_[A-Z]*.man' -print | sort)
|
||||
wlist_matches := $(patsubst ${srcdir}/libxt_%.man,%,${wcman_matches})
|
||||
wlist_targets := $(patsubst ${srcdir}/libxt_%.man,%,${wcman_targets})
|
||||
|
||||
@@ -38,3 +38,6 @@ matches.man: .manpages.lst ${wcman_matches}
|
||||
|
||||
targets.man: .manpages.lst ${wcman_targets}
|
||||
$(call man_run,${wlist_targets})
|
||||
|
||||
clean:
|
||||
rm -f xtables-addons.8 matches.man targets.man .manpages.lst
|
||||
|
54
README
54
README
@@ -1,57 +1,15 @@
|
||||
Xtables-addons
|
||||
==============
|
||||
|
||||
Xtables-addons is the proclaimed successor to patch-o-matic(-ng). It
|
||||
contains extensions that were not accepted in the main Xtables
|
||||
package.
|
||||
Xtables-addons is a set of extensions that were not accepted in the
|
||||
Linux kernel and/or main Xtables/iptables package.
|
||||
|
||||
Xtables-addons is different from patch-o-matic in that you do not
|
||||
have to patch or recompile either kernel or Xtables(iptables). But
|
||||
please see the INSTALL file for the minimum requirements of this
|
||||
package.
|
||||
|
||||
All code imported from patch-o-matic has been reviewed and all
|
||||
apparent bugs like binary stability across multiarches, missing
|
||||
sanity checks and incorrect endianess handling have been fixed,
|
||||
simplified, and sped up.
|
||||
It superseded the earlier patch-o-matic(-ng) package in that no
|
||||
patching and/or recompilation of either the kernel or
|
||||
Xtables/iptables is required. However, do see the INSTALL file for
|
||||
the minimum requirements of Xtables-addons.
|
||||
|
||||
|
||||
Included in this package
|
||||
========================
|
||||
- xt_ACCOUNT 1.16, libxt_ACCOUNT 1.3
|
||||
|
||||
|
||||
Inclusion into a kernel tree
|
||||
============================
|
||||
|
||||
|
||||
|
||||
|
||||
External extensions
|
||||
===================
|
||||
|
||||
The program "xa-download-more" can be used to download more
|
||||
extensions from 3rd parties into the source tree. The URLs are listed
|
||||
in the "sources" file. If the "sources" file contains an entry like
|
||||
|
||||
http://foobar.org/xa/
|
||||
|
||||
xa-download-more will inspect http://foobar.org/xa/xa-index.txt for
|
||||
files to download. That file may contain
|
||||
|
||||
foobar.tar.bz2
|
||||
|
||||
and xa-download-more will then retrieve and unpack
|
||||
http://foobar.org/xa/foobar.tar.bz2.
|
||||
|
||||
Files that should be contained in the tarball are an mconfig and
|
||||
Kbuild files to control building the extension, libxt_foobar.c for
|
||||
the userspace extension and xt_foobar.c for the kernel extension.
|
||||
|
||||
mconfig.foobar
|
||||
extensions/Kbuild.foobar
|
||||
extensions/Mbuild.foobar
|
||||
extensions/libxt_foobar.c
|
||||
extensions/libxt_foobar.man
|
||||
extensions/xt_foobar.c
|
||||
extensions/xt_foobar.h
|
||||
|
42
configure.ac
42
configure.ac
@@ -1,4 +1,4 @@
|
||||
AC_INIT([xtables-addons], [1.47])
|
||||
AC_INIT([xtables-addons], [3.18])
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
@@ -26,8 +26,8 @@ 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([libxtables], [xtables >= 1.6.0])
|
||||
xtlibdir="$($PKG_CONFIG --variable=xtlibdir xtables)"
|
||||
|
||||
AC_ARG_WITH([xtlibdir],
|
||||
AS_HELP_STRING([--with-xtlibdir=PATH],
|
||||
@@ -44,31 +44,25 @@ regular_CFLAGS="-Wall -Waggregate-return -Wmissing-declarations \
|
||||
|
||||
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))";
|
||||
krel="$(make -sC "$kbuilddir" M=$PWD kernelrelease | $AWK -v 'FS=[[^0-9.]]' '{print $1; exit}')"
|
||||
save_IFS="$IFS"
|
||||
IFS='.'
|
||||
set x $krel
|
||||
IFS="$save_IFS"
|
||||
kmajor="$(($2+0))"
|
||||
kminor="$(($3+0))"
|
||||
kmicro="$(($4+0))"
|
||||
kstable="$(($5+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 6; then
|
||||
echo "WARNING: That kernel version is not officially supported.";
|
||||
elif test "$kmajor" -eq 3; then
|
||||
:;
|
||||
elif test "$kmajor" -eq 2 -a "$kminor" -eq 6 -a "$kmicro" -ge 32; then
|
||||
:;
|
||||
if test "$kmajor" -gt 5 -o "$kmajor" -eq 5 -a "$kminor" -gt 11; then
|
||||
echo "WARNING: That kernel version is not officially supported yet. Continue at own luck.";
|
||||
elif test "$kmajor" -eq 5 -a "$kminor" -ge 0; then
|
||||
:
|
||||
elif test "$kmajor" -eq 4 -a "$kminor" -ge 15; then
|
||||
:
|
||||
else
|
||||
echo "WARNING: That kernel version is not officially supported.";
|
||||
fi;
|
||||
|
@@ -1,64 +0,0 @@
|
||||
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,
|
||||
);
|
||||
|
||||
/* true/false */
|
||||
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,
|
||||
);
|
||||
|
||||
/* true/false */
|
||||
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,
|
||||
);
|
@@ -1,59 +0,0 @@
|
||||
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,
|
||||
);
|
||||
|
||||
/* true/false */
|
||||
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,
|
||||
);
|
||||
|
||||
/* true/false */
|
||||
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,
|
||||
);
|
@@ -1,59 +0,0 @@
|
||||
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,
|
||||
);
|
@@ -1,59 +0,0 @@
|
||||
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,
|
||||
);
|
@@ -1,39 +0,0 @@
|
||||
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 *,
|
||||
);
|
@@ -1,38 +0,0 @@
|
||||
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 *,
|
||||
);
|
@@ -1,39 +0,0 @@
|
||||
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 *,
|
||||
);
|
@@ -1,511 +1,242 @@
|
||||
|
||||
HEAD
|
||||
====
|
||||
|
||||
|
||||
v1.47 (2010-10-15)
|
||||
v3.18 (2021-03-11)
|
||||
==================
|
||||
Enhancements:
|
||||
- xt_psd gained IPv6 support
|
||||
Notes for this release:
|
||||
- Linux 3.7+ is expressly unsupported by this release.
|
||||
- xt_pknock: fix a build failure on ARM 32-bit
|
||||
|
||||
|
||||
v1.46 (2012-08-23)
|
||||
v3.17 (2021-02-28)
|
||||
==================
|
||||
Fixes:
|
||||
- length2, SYSRQ, RAWNAT: preinitialize values for ipv6_find_hdr
|
||||
- TARPIT: fix memory leak when tarpit_generic() fails
|
||||
- build: remove extraneous closing bracket in configure.ac
|
||||
- doc: update xt_SYSRQ.man to reflect that the full IPv6 address is needed
|
||||
Enhancements:
|
||||
- Support for Linux 3.6
|
||||
- xt_pknock: cure a NULL deref
|
||||
|
||||
|
||||
v1.45 (2012-07-16)
|
||||
v3.16 (2021-02-24)
|
||||
==================
|
||||
Fixes:
|
||||
- build: export missing functions
|
||||
(fixes: "WARNING 'xtnu_ipv6_find_hdr' [xt_TARPIT.ko] not found")
|
||||
- build: avoid use of unexported functions
|
||||
(fixes: "WARNING 'ipv6_find_hdr' [xt_TARPIT.ko] not found"
|
||||
in <= linux-2.6.37)
|
||||
- xt_pknock: build fix for ILP32 targets
|
||||
|
||||
|
||||
v1.44 (2012-07-15)
|
||||
v3.15 (2021-02-05)
|
||||
==================
|
||||
Fixes:
|
||||
- SYSRQ: fix double target initialization at module load
|
||||
- build: do not attempt to build IPv6 parts if CONFIG_IP6_NF_IPTABLES=n
|
||||
Enhancements:
|
||||
- TARPIT gained IPv6 support
|
||||
- xt_ECHO: support new function signature of security_skb_classify_flow
|
||||
- xt_lscan: add --mirai option
|
||||
- Support for Linux 5.11
|
||||
|
||||
|
||||
v1.43 (2012-06-30)
|
||||
v3.14 (2020-11-24)
|
||||
==================
|
||||
Fixes:
|
||||
- xt_psd: avoid crash due to curr->next corruption
|
||||
Changes:
|
||||
- xt_psd: reject invalid match options
|
||||
Enhancements:
|
||||
- Support for Linux 3.5
|
||||
- DNETMAP: new type: static binding
|
||||
- DNETMAP: new persistent flag option for prefix
|
||||
- DNETMAP: add write support to procfs interface
|
||||
- DELUDE, ECHO, TARPIT: use actual tunnel socket (ip_route_me_harder).
|
||||
- geoip: scripts for use with MaxMind DB have been brought back,
|
||||
partly under new names.
|
||||
- Gave xt_geoip_fetch a more fitting name, xt_geoip_query.
|
||||
|
||||
|
||||
v1.42 (2012-04-05)
|
||||
v3.13 (2020-11-20)
|
||||
==================
|
||||
Fixes:
|
||||
- compat_xtables: fixed mistranslation of checkentry return values
|
||||
(affected kernels < 2.6.23)
|
||||
- xt_SYSRQ: fix compile error when crypto is turned off
|
||||
Changes:
|
||||
- ipset6-genl has been dropped from the tree;
|
||||
the libmnl build-time dependency is thus no longer needed
|
||||
Enhancements:
|
||||
- Support for Linux 3.3, 3.4
|
||||
- Support for Linux 4.19.158 and 5.4.78 (ip_route_me_harder)
|
||||
|
||||
|
||||
v1.41 (2012-01-04)
|
||||
v3.12 (2020-11-19)
|
||||
==================
|
||||
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
|
||||
- Support for Linux 5.10 and 5.9.9 API
|
||||
(changes to ip_route_me_harder there)
|
||||
|
||||
|
||||
v1.40 (2011-11-30)
|
||||
v3.11 (2020-09-06)
|
||||
==================
|
||||
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
|
||||
- Support for up to Linux 5.9
|
||||
|
||||
|
||||
v1.39 (2011-09-21)
|
||||
v3.10 (2020-07-28)
|
||||
==================
|
||||
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
|
||||
- Support for up to Linux 5.8
|
||||
|
||||
|
||||
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
|
||||
- fuzzy: fix bogus comparison logic leftover from move to new 1.4.3 API
|
||||
- ipp2p: fix bogus varargs call
|
||||
- ipp2p: fix typo in error message
|
||||
- added "iface" match
|
||||
- added rawpost table (for use with RAWNAT)
|
||||
- added RAWSNAT/RAWDNAT targets
|
||||
|
||||
|
||||
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
|
||||
- SYSRQ: do proper L4 header access in IPv6 code
|
||||
(must not use tcp/udp_hdr in input path)
|
||||
- add "STEAL" target
|
||||
- dhcpmac: rename from dhcpaddr
|
||||
|
||||
|
||||
v1.13 (2009-03-23)
|
||||
==================
|
||||
- added a reworked ipv4options match
|
||||
- upgrade to iptables 1.4.3 API
|
||||
|
||||
|
||||
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
|
||||
"portscan" as a word caused confusion
|
||||
- xt_LOGMARK: print incoming interface index
|
||||
- revert "TEE: do not use TOS for routing"
|
||||
- xt_TEE: resolve unknown symbol error with CONFIG_IPV6=n
|
||||
- xt_TEE: enable routing by iif, nfmark and flowlabel
|
||||
|
||||
|
||||
v1.10 (2009-02-18)
|
||||
==================
|
||||
- compat: compile fixes for 2.6.29
|
||||
- ipset: upgrade to ipset 2.4.9
|
||||
|
||||
|
||||
v1.9 (2009-01-30)
|
||||
v3.9 (2020-02-25)
|
||||
=================
|
||||
- add the xt_length2 extension
|
||||
- xt_TEE: remove intrapositional '!' support
|
||||
- ipset: upgrade to ipset 2.4.7
|
||||
- Support for Linux 5.6 procfs changes
|
||||
|
||||
|
||||
v1.8 (2009-01-10)
|
||||
v3.8 (2020-02-03)
|
||||
=================
|
||||
- xt_TEE: IPv6 support
|
||||
- xt_TEE: do not include TOS value in routing decision
|
||||
- xt_TEE: fix switch-case inversion for name/IP display
|
||||
- xt_ipp2p: update manpages and help text
|
||||
- xt_ipp2p: remove log flooding
|
||||
- xt_portscan: update manpage about --grscan option caveats
|
||||
- Support for Linux 5.5
|
||||
- xt_geoip_build now expects the DBIP format as input,
|
||||
Maxmind is thrown out.
|
||||
|
||||
|
||||
v1.7 (2008-12-25)
|
||||
v3.7 (2019-12-01)
|
||||
=================
|
||||
- xt_ECHO: compile fix
|
||||
- avoid the use of "_init" which led to compile errors on some installations
|
||||
- build: do not unconditionally install ipset
|
||||
- doc: add manpages for xt_ECHO and xt_TEE
|
||||
- xt_ipp2p: kazaa detection code cleanup
|
||||
- xt_ipp2p: fix newline inspection in kazaa detection
|
||||
- xt_ipp2p: ensure better array bounds checking
|
||||
- xt_SYSRQ: improve security by hashing password
|
||||
Fixes:
|
||||
- xt_geoip: fix in6_addr little-endian byte swapping
|
||||
|
||||
|
||||
v1.6 (2008-11-18)
|
||||
v3.6 (2019-11-20)
|
||||
=================
|
||||
- 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
|
||||
Enhancements:
|
||||
- support for up to Linux 5.4
|
||||
|
||||
|
||||
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
|
||||
- ipset: adjust semaphore.h include for Linux >= 2.6.27
|
||||
- build: automatically run `depmod -a` on installation
|
||||
- add reworked xt_fuzzy module
|
||||
- add DHCP address match and mangle module
|
||||
- xt_portscan: IPv6 support
|
||||
- xt_SYSRQ: add missing module aliases
|
||||
v3.5 (2019-09-10)
|
||||
=================
|
||||
Enhancements:
|
||||
- xt_DELUDE, xt_TARPIT: added additional code needed to work with
|
||||
bridges from Linux 5.0 onwards.
|
||||
|
||||
|
||||
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
|
||||
- add the xt_SYSRQ target
|
||||
- add the xt_quota2 extension
|
||||
- import ipset extension group
|
||||
v3.4 (2019-09-06)
|
||||
=================
|
||||
Enhancements:
|
||||
- support for up to Linux 5.3
|
||||
- xt_PROTO module
|
||||
|
||||
|
||||
v1.5.4.1 (2008-04-26)
|
||||
=====================
|
||||
- build: fix compile error for 2.6.18-stable
|
||||
v3.3 (2019-03-07)
|
||||
=================
|
||||
Enhancements:
|
||||
- support for Linux 5.0
|
||||
|
||||
|
||||
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
|
||||
- xt_ECHO: catch skb_linearize out-of-memory condition
|
||||
- xt_LOGMARK: add hook= and ctdir= fields in dump
|
||||
- xt_LOGMARK: fix comma output in ctstatus= list
|
||||
- xt_TEE: fix address copying bug
|
||||
- xt_TEE: make skb writable before attempting checksum update
|
||||
- add reworked xt_condition match
|
||||
- add reworked xt_ipp2p match
|
||||
- add reworked xt_IPMARK target
|
||||
v3.2 (2018-09-07)
|
||||
=================
|
||||
Changes:
|
||||
- rework xt_geoip_build to scan the immediate directory for .csv,
|
||||
not to scan for GeoLite2-Country-CSV_\d+.
|
||||
|
||||
|
||||
v1.5.3 (2008-03-22)
|
||||
===================
|
||||
- support for Linux 2.6.18
|
||||
- add xt_ECHO sample target
|
||||
- add reworked xt_geoip match
|
||||
v3.1 (2018-08-14)
|
||||
=================
|
||||
Enhancements:
|
||||
- support for Linux 4.17, 4.18
|
||||
|
||||
|
||||
v1.5.2 (2008-03-04)
|
||||
===================
|
||||
- build: support for GNU make < 3.81 which does not have $(realpath)
|
||||
v3.0 (2018-02-12)
|
||||
=================
|
||||
Enhancements:
|
||||
- support for Linux 4.15, 4.16
|
||||
Changes:
|
||||
- remove support for Linux 3.7--4.14
|
||||
|
||||
|
||||
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
|
||||
v2.14 (2017-11-22)
|
||||
==================
|
||||
Enhancements:
|
||||
- support for Linux up to 4.14
|
||||
Fixes:
|
||||
- xt_DNETMAP: fix some reports from PVSStudio (a static checker)
|
||||
|
||||
|
||||
v1.5.0 (2008-02-11)
|
||||
===================
|
||||
Initial release with:
|
||||
- extensions: xt_LOGMARK, xt_TARPIT, xt_TEE
|
||||
- support for Linux >= 2.6.19
|
||||
v2.13 (2017-06-29)
|
||||
==================
|
||||
Enhancements:
|
||||
- support for Linux up to 4.12
|
||||
- xt_condition: namespace support
|
||||
Fixes:
|
||||
- xt_geoip: check for allocation overflow
|
||||
- xt_DNETMAP: fix a buffer overflow
|
||||
|
||||
|
||||
v2.12 (2017-01-11)
|
||||
==================
|
||||
Enhancements:
|
||||
- support for Linux up to 4.10
|
||||
|
||||
|
||||
v2.11 (2016-05-20)
|
||||
==================
|
||||
Enhancements:
|
||||
- support for Linux 4.5, 4.6
|
||||
- xt_ECHO: tentatively support responding to fragments
|
||||
|
||||
|
||||
v2.10 (2015-11-20)
|
||||
==================
|
||||
Enhancements:
|
||||
- Support for Linux 4.4
|
||||
Fixes:
|
||||
- xt_ACCOUNT: call free_page with the right amount of pages
|
||||
|
||||
|
||||
v2.9 (2015-10-12)
|
||||
=================
|
||||
Enhancements:
|
||||
- Support for Linux 4.3
|
||||
|
||||
|
||||
v2.8 (2015-08-19)
|
||||
=================
|
||||
Enhancements:
|
||||
- Support for Linux 4.2
|
||||
- Enable xt_ECHO for Linux 4.0+
|
||||
|
||||
|
||||
v2.7 (2015-07-06)
|
||||
=================
|
||||
Enhancements:
|
||||
- Support for Linux up to 4.1
|
||||
|
||||
|
||||
v2.6 (2014-09-29)
|
||||
=================
|
||||
Enhancements:
|
||||
- Support for Linux up to 3.17
|
||||
Fixes:
|
||||
- xt_pknock: UDP SPA mode erroneously returned an error saying
|
||||
crypto was unavailable
|
||||
|
||||
|
||||
v2.5 (2014-04-18)
|
||||
=================
|
||||
Enhancements:
|
||||
- Support for Linux up to 3.15
|
||||
- xt_quota2: introduce support for network namespaces
|
||||
|
||||
|
||||
v2.4 (2014-01-09)
|
||||
=================
|
||||
Enhancements:
|
||||
- Support for Linux up to 3.13
|
||||
Changes:
|
||||
- remove unmaintained RAWSNAT/RAWDNAT code
|
||||
- remove unused parts of compat_xtables that served Linux <3.7
|
||||
Fixes:
|
||||
- xt_quota2: --no-change should not alter quota to zero ever
|
||||
- xt_quota2: --packet should not be set to zero based on skb->len
|
||||
|
||||
|
||||
v2.3 (2013-06-18)
|
||||
=================
|
||||
Enhancements:
|
||||
- Support for Linux 3.10
|
||||
Fixes:
|
||||
- xt_DNETMAP, xt_condition, xt_quota2: resolve compile error when
|
||||
CONFIG_UIDGID_STRICT_TYPE_CHECKS=y
|
||||
- xt_RAWNAT: ensure correct operation in the presence of IPv4 options
|
||||
- xt_geoip: do not throw a warnings when country database is size 0
|
||||
- xt_quota2: print "!" at the correct position during iptables-save
|
||||
Changes:
|
||||
- Make print (iptables -L) output the same as save (-S)
|
||||
|
||||
|
||||
v2.2 (2013-03-31)
|
||||
=================
|
||||
Enhancements:
|
||||
- Support for Linux 3.9
|
||||
- iptaccount: fix entire program being erroneously optimized away on PPC
|
||||
|
||||
|
||||
v2.1 (2012-11-27)
|
||||
=================
|
||||
Fixes:
|
||||
- DNETMAP: fix compile error with Linux 3.7
|
||||
Enhancements:
|
||||
- Support for Linux 3.8
|
||||
|
||||
|
||||
v2.0 (2012-11-12)
|
||||
=================
|
||||
Changes:
|
||||
- remove support for Linux 2.6.17–3.6
|
||||
- remove xt_TEE (this is available upstream since 2.6.35)
|
||||
- remove xt_CHECKSUM (this is available upstream since 2.6.36)
|
||||
Enhancements:
|
||||
- Support for Linux 3.7
|
||||
|
||||
If you want to use Xtables-addons with kernels older than 4.15,
|
||||
use the addons 2.x series.
|
||||
|
@@ -9,5 +9,6 @@ sbin_PROGRAMS = iptaccount
|
||||
iptaccount_LDADD = libxt_ACCOUNT_cl.la
|
||||
|
||||
lib_LTLIBRARIES = libxt_ACCOUNT_cl.la
|
||||
libxt_ACCOUNT_cl_la_LDFLAGS = -version-info 1:0:0
|
||||
|
||||
man_MANS = iptaccount.8
|
||||
|
@@ -64,7 +64,7 @@ int main(int argc, char *argv[])
|
||||
struct ipt_ACCOUNT_context ctx;
|
||||
struct ipt_acc_handle_ip *entry;
|
||||
int i;
|
||||
char optchar;
|
||||
int optchar;
|
||||
bool doHandleUsage = false, doHandleFree = false, doTableNames = false;
|
||||
bool doFlush = false, doContinue = false, doCSV = false;
|
||||
|
||||
@@ -200,13 +200,19 @@ int main(int argc, char *argv[])
|
||||
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);
|
||||
printf("%s;%llu;%llu;%llu;%llu\n",
|
||||
addr_to_dotted(entry->ip),
|
||||
(unsigned long long)entry->src_packets,
|
||||
(unsigned long long)entry->src_bytes,
|
||||
(unsigned long long)entry->dst_packets,
|
||||
(unsigned long long)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);
|
||||
printf("IP: %s SRC packets: %llu bytes: %llu DST packets: %llu bytes: %llu\n",
|
||||
addr_to_dotted(entry->ip),
|
||||
(unsigned long long)entry->src_packets,
|
||||
(unsigned long long)entry->src_bytes,
|
||||
(unsigned long long)entry->dst_packets,
|
||||
(unsigned long long)entry->dst_bytes);
|
||||
}
|
||||
|
||||
if (doContinue)
|
||||
|
@@ -34,7 +34,8 @@ int ipt_ACCOUNT_init(struct ipt_ACCOUNT_context *ctx)
|
||||
|
||||
// 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) {
|
||||
ctx->data = malloc(IPT_ACCOUNT_MIN_BUFSIZE);
|
||||
if (ctx->data == NULL) {
|
||||
close(ctx->sockfd);
|
||||
ctx->sockfd = -1;
|
||||
ctx->error_str = "Out of memory for data buffer";
|
||||
|
@@ -7,10 +7,7 @@
|
||||
* version 2.1 as published by the Free Software Foundation; *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef _xt_ACCOUNT_cl_H
|
||||
#define _xt_ACCOUNT_cl_H
|
||||
|
||||
#pragma once
|
||||
#include <xt_ACCOUNT.h>
|
||||
|
||||
#define LIBXT_ACCOUNT_VERSION "1.3"
|
||||
@@ -23,9 +20,8 @@ struct ipt_ACCOUNT_context
|
||||
int sockfd;
|
||||
struct ipt_acc_handle_sockopt handle;
|
||||
|
||||
unsigned int data_size;
|
||||
unsigned int data_size, pos;
|
||||
void *data;
|
||||
unsigned int pos;
|
||||
|
||||
char *error_str;
|
||||
};
|
||||
@@ -55,6 +51,3 @@ const char *ipt_ACCOUNT_get_next_name(struct ipt_ACCOUNT_context *ctx);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -15,6 +15,7 @@
|
||||
//#define DEBUG 1
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#include <net/net_namespace.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/ip.h>
|
||||
#include <net/icmp.h>
|
||||
@@ -22,17 +23,17 @@
|
||||
#include <net/tcp.h>
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
|
||||
#include <linux/semaphore.h>
|
||||
#else
|
||||
#include <asm/semaphore.h>
|
||||
#endif
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/string.h>
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)
|
||||
#include <linux/sockptr.h>
|
||||
#endif
|
||||
#include <linux/spinlock.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <net/netns/generic.h>
|
||||
|
||||
#include <net/route.h>
|
||||
#include "xt_ACCOUNT.h"
|
||||
@@ -42,6 +43,9 @@
|
||||
#error "ipt_ACCOUNT needs at least a PAGE_SIZE of 4096"
|
||||
#endif
|
||||
|
||||
static unsigned int max_tables_limit = 128;
|
||||
module_param(max_tables_limit, uint, 0);
|
||||
|
||||
/**
|
||||
* Internal table structure, generated by check_entry()
|
||||
* @name: name of the table
|
||||
@@ -77,13 +81,13 @@ struct ipt_acc_handle {
|
||||
};
|
||||
|
||||
/* Used for every IP entry
|
||||
Size is 16 bytes so that 256 (class C network) * 16
|
||||
fits in one kernel (zero) page */
|
||||
Size is 32 bytes so that 256 (class C network) * 16
|
||||
fits in a double kernel (zero) page (two consecutive kernel pages)*/
|
||||
struct ipt_acc_ip {
|
||||
uint32_t src_packets;
|
||||
uint32_t src_bytes;
|
||||
uint32_t dst_packets;
|
||||
uint32_t dst_bytes;
|
||||
uint64_t src_packets;
|
||||
uint64_t src_bytes;
|
||||
uint64_t dst_packets;
|
||||
uint64_t dst_bytes;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -104,25 +108,28 @@ struct ipt_acc_mask_8 {
|
||||
struct ipt_acc_mask_16 *mask_16[256];
|
||||
};
|
||||
|
||||
static struct ipt_acc_table *ipt_acc_tables;
|
||||
static struct ipt_acc_handle *ipt_acc_handles;
|
||||
static void *ipt_acc_tmpbuf;
|
||||
static int ipt_acc_net_id __read_mostly;
|
||||
|
||||
struct ipt_acc_net {
|
||||
/* Spinlock used for manipulating the current accounting tables/data */
|
||||
static DEFINE_SPINLOCK(ipt_acc_lock);
|
||||
/* Mutex (semaphore) used for manipulating userspace handles/snapshot data */
|
||||
static struct semaphore ipt_acc_userspace_mutex;
|
||||
spinlock_t ipt_acc_lock;
|
||||
|
||||
/* Allocates a page and clears it */
|
||||
/* Mutex (semaphore) used for manipulating userspace handles/snapshot data */
|
||||
struct semaphore ipt_acc_userspace_mutex;
|
||||
|
||||
struct ipt_acc_table *ipt_acc_tables;
|
||||
struct ipt_acc_handle *ipt_acc_handles;
|
||||
void *ipt_acc_tmpbuf;
|
||||
};
|
||||
|
||||
/* Allocates a page pair and clears it */
|
||||
static void *ipt_acc_zalloc_page(void)
|
||||
{
|
||||
// Don't use get_zeroed_page until it's fixed in the kernel.
|
||||
// get_zeroed_page(GFP_ATOMIC)
|
||||
void *mem = (void *)__get_free_page(GFP_ATOMIC);
|
||||
if (mem) {
|
||||
memset (mem, 0, PAGE_SIZE);
|
||||
}
|
||||
|
||||
void *mem = (void *)__get_free_pages(GFP_ATOMIC, 2);
|
||||
if (mem != NULL)
|
||||
memset(mem, 0, 2 *PAGE_SIZE);
|
||||
return mem;
|
||||
}
|
||||
|
||||
@@ -135,7 +142,7 @@ static void ipt_acc_data_free(void *data, uint8_t depth)
|
||||
|
||||
/* Free for 8 bit network */
|
||||
if (depth == 0) {
|
||||
free_page((unsigned long)data);
|
||||
free_pages((unsigned long)data, 2);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -143,12 +150,10 @@ static void ipt_acc_data_free(void *data, uint8_t depth)
|
||||
if (depth == 1) {
|
||||
struct ipt_acc_mask_16 *mask_16 = data;
|
||||
unsigned int b;
|
||||
for (b = 0; b <= 255; b++) {
|
||||
if (mask_16->mask_24[b]) {
|
||||
free_page((unsigned long)mask_16->mask_24[b]);
|
||||
}
|
||||
}
|
||||
free_page((unsigned long)data);
|
||||
for (b = 0; b <= 255; ++b)
|
||||
if (mask_16->mask_24[b])
|
||||
free_pages((unsigned long)mask_16->mask_24[b], 2);
|
||||
free_pages((unsigned long)data, 2);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -160,15 +165,13 @@ static void ipt_acc_data_free(void *data, uint8_t depth)
|
||||
struct ipt_acc_mask_16 *mask_16 =
|
||||
((struct ipt_acc_mask_8 *)data)->mask_16[a];
|
||||
|
||||
for (b = 0; b <= 255; b++) {
|
||||
if (mask_16->mask_24[b]) {
|
||||
free_page((unsigned long)mask_16->mask_24[b]);
|
||||
for (b = 0; b <= 255; ++b)
|
||||
if (mask_16->mask_24[b])
|
||||
free_pages((unsigned long)mask_16->mask_24[b], 2);
|
||||
free_pages((unsigned long)mask_16, 2);
|
||||
}
|
||||
}
|
||||
free_page((unsigned long)mask_16);
|
||||
}
|
||||
}
|
||||
free_page((unsigned long)data);
|
||||
free_pages((unsigned long)data, 2);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -179,28 +182,27 @@ static void ipt_acc_data_free(void *data, uint8_t depth)
|
||||
|
||||
/* Look for existing table / insert new one.
|
||||
Return internal ID or -1 on error */
|
||||
static int ipt_acc_table_insert(const char *name, __be32 ip, __be32 netmask)
|
||||
static int ipt_acc_table_insert(struct ipt_acc_table *ipt_acc_tables,
|
||||
const char *name, __be32 ip, __be32 netmask)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
pr_debug("ACCOUNT: ipt_acc_table_insert: %s, %u.%u.%u.%u/%u.%u.%u.%u\n",
|
||||
name, NIPQUAD(ip), NIPQUAD(netmask));
|
||||
pr_debug("ACCOUNT: ipt_acc_table_insert: %s, %pI4/%pI4\n",
|
||||
name, &ip, &netmask);
|
||||
|
||||
/* Look for existing table */
|
||||
for (i = 0; i < ACCOUNT_MAX_TABLES; i++) {
|
||||
for (i = 0; i < max_tables_limit; i++) {
|
||||
if (strncmp(ipt_acc_tables[i].name, name,
|
||||
ACCOUNT_TABLE_NAME_LEN) == 0) {
|
||||
pr_debug("ACCOUNT: Found existing slot: %d - "
|
||||
"%u.%u.%u.%u/%u.%u.%u.%u\n", i,
|
||||
NIPQUAD(ipt_acc_tables[i].ip),
|
||||
NIPQUAD(ipt_acc_tables[i].netmask));
|
||||
pr_debug("ACCOUNT: Found existing slot: %d - %pI4/%pI4\n",
|
||||
i, &ipt_acc_tables[i].ip, &ipt_acc_tables[i].netmask);
|
||||
|
||||
if (ipt_acc_tables[i].ip != ip
|
||||
|| ipt_acc_tables[i].netmask != netmask) {
|
||||
printk("ACCOUNT: Table %s found, but IP/netmask mismatch. "
|
||||
"IP/netmask found: %u.%u.%u.%u/%u.%u.%u.%u\n",
|
||||
name, NIPQUAD(ipt_acc_tables[i].ip),
|
||||
NIPQUAD(ipt_acc_tables[i].netmask));
|
||||
"IP/netmask found: %pI4/%pI4\n",
|
||||
name, &ipt_acc_tables[i].ip,
|
||||
&ipt_acc_tables[i].netmask);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -211,7 +213,7 @@ static int ipt_acc_table_insert(const char *name, __be32 ip, __be32 netmask)
|
||||
}
|
||||
|
||||
/* Insert new table */
|
||||
for (i = 0; i < ACCOUNT_MAX_TABLES; i++) {
|
||||
for (i = 0; i < max_tables_limit; i++) {
|
||||
/* Found free slot */
|
||||
if (ipt_acc_tables[i].name[0] == 0) {
|
||||
unsigned int netsize = 0;
|
||||
@@ -260,19 +262,21 @@ static int ipt_acc_table_insert(const char *name, __be32 ip, __be32 netmask)
|
||||
|
||||
/* No free slot found */
|
||||
printk("ACCOUNT: No free table slot found (max: %d). "
|
||||
"Please increase ACCOUNT_MAX_TABLES.\n", ACCOUNT_MAX_TABLES);
|
||||
"Please increase the \"max_tables_limit\" module parameter.\n", max_tables_limit);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int ipt_acc_checkentry(const struct xt_tgchk_param *par)
|
||||
{
|
||||
struct ipt_acc_net *ian = net_generic(par->net, ipt_acc_net_id);
|
||||
struct ipt_acc_info *info = par->targinfo;
|
||||
int table_nr;
|
||||
|
||||
spin_lock_bh(&ipt_acc_lock);
|
||||
table_nr = ipt_acc_table_insert(info->table_name, info->net_ip,
|
||||
spin_lock_bh(&ian->ipt_acc_lock);
|
||||
table_nr = ipt_acc_table_insert(ian->ipt_acc_tables,
|
||||
info->table_name, info->net_ip,
|
||||
info->net_mask);
|
||||
spin_unlock_bh(&ipt_acc_lock);
|
||||
spin_unlock_bh(&ian->ipt_acc_lock);
|
||||
|
||||
if (table_nr == -1) {
|
||||
printk("ACCOUNT: Table insert problem. Aborting\n");
|
||||
@@ -287,10 +291,11 @@ static int ipt_acc_checkentry(const struct xt_tgchk_param *par)
|
||||
|
||||
static void ipt_acc_destroy(const struct xt_tgdtor_param *par)
|
||||
{
|
||||
struct ipt_acc_net *ian = net_generic(par->net, ipt_acc_net_id);
|
||||
unsigned int i;
|
||||
struct ipt_acc_info *info = par->targinfo;
|
||||
|
||||
spin_lock_bh(&ipt_acc_lock);
|
||||
spin_lock_bh(&ian->ipt_acc_lock);
|
||||
|
||||
pr_debug("ACCOUNT: ipt_acc_deleteentry called for table: %s (#%d)\n",
|
||||
info->table_name, info->table_nr);
|
||||
@@ -298,32 +303,32 @@ static void ipt_acc_destroy(const struct xt_tgdtor_param *par)
|
||||
info->table_nr = -1; /* Set back to original state */
|
||||
|
||||
/* Look for table */
|
||||
for (i = 0; i < ACCOUNT_MAX_TABLES; i++) {
|
||||
if (strncmp(ipt_acc_tables[i].name, info->table_name,
|
||||
for (i = 0; i < max_tables_limit; i++) {
|
||||
if (strncmp(ian->ipt_acc_tables[i].name, info->table_name,
|
||||
ACCOUNT_TABLE_NAME_LEN) == 0) {
|
||||
pr_debug("ACCOUNT: Found table at slot: %d\n", i);
|
||||
|
||||
ipt_acc_tables[i].refcount--;
|
||||
ian->ipt_acc_tables[i].refcount--;
|
||||
pr_debug("ACCOUNT: Refcount left: %d\n",
|
||||
ipt_acc_tables[i].refcount);
|
||||
ian->ipt_acc_tables[i].refcount);
|
||||
|
||||
/* Table not needed anymore? */
|
||||
if (ipt_acc_tables[i].refcount == 0) {
|
||||
if (ian->ipt_acc_tables[i].refcount == 0) {
|
||||
pr_debug("ACCOUNT: Destroying table at slot: %d\n", i);
|
||||
ipt_acc_data_free(ipt_acc_tables[i].data,
|
||||
ipt_acc_tables[i].depth);
|
||||
memset(&ipt_acc_tables[i], 0,
|
||||
ipt_acc_data_free(ian->ipt_acc_tables[i].data,
|
||||
ian->ipt_acc_tables[i].depth);
|
||||
memset(&ian->ipt_acc_tables[i], 0,
|
||||
sizeof(struct ipt_acc_table));
|
||||
}
|
||||
|
||||
spin_unlock_bh(&ipt_acc_lock);
|
||||
spin_unlock_bh(&ian->ipt_acc_lock);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Table not found */
|
||||
printk("ACCOUNT: Table %s not found for destroy\n", info->table_name);
|
||||
spin_unlock_bh(&ipt_acc_lock);
|
||||
spin_unlock_bh(&ian->ipt_acc_lock);
|
||||
}
|
||||
|
||||
static void ipt_acc_depth0_insert(struct ipt_acc_mask_24 *mask_24,
|
||||
@@ -336,9 +341,8 @@ static void ipt_acc_depth0_insert(struct ipt_acc_mask_24 *mask_24,
|
||||
/* Check if this entry is new */
|
||||
bool is_src_new_ip = false, is_dst_new_ip = false;
|
||||
|
||||
pr_debug("ACCOUNT: ipt_acc_depth0_insert: %u.%u.%u.%u/%u.%u.%u.%u "
|
||||
"for net %u.%u.%u.%u/%u.%u.%u.%u, size: %u\n", NIPQUAD(src_ip),
|
||||
NIPQUAD(dst_ip), NIPQUAD(net_ip), NIPQUAD(netmask), size);
|
||||
pr_debug("ACCOUNT: ipt_acc_depth0_insert: %pI4/%pI4 for net %pI4/%pI4,"
|
||||
" size: %u\n", &src_ip, &dst_ip, &net_ip, &netmask, size);
|
||||
|
||||
/* Check if src/dst is inside our network. */
|
||||
/* Special: net_ip = 0.0.0.0/0 gets stored as src in slot 0 */
|
||||
@@ -350,9 +354,8 @@ static void ipt_acc_depth0_insert(struct ipt_acc_mask_24 *mask_24,
|
||||
is_dst = true;
|
||||
|
||||
if (!is_src && !is_dst) {
|
||||
pr_debug("ACCOUNT: Skipping packet %u.%u.%u.%u/%u.%u.%u.%u "
|
||||
"for net %u.%u.%u.%u/%u.%u.%u.%u\n", NIPQUAD(src_ip),
|
||||
NIPQUAD(dst_ip), NIPQUAD(net_ip), NIPQUAD(netmask));
|
||||
pr_debug("ACCOUNT: Skipping packet %pI4/%pI4 for net %pI4/%pI4\n",
|
||||
&src_ip, &dst_ip, &net_ip, &netmask);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -391,11 +394,11 @@ static void ipt_acc_depth0_insert(struct ipt_acc_mask_24 *mask_24,
|
||||
}
|
||||
} else {
|
||||
if (is_src_new_ip) {
|
||||
pr_debug("ACCOUNT: New src_ip: %u.%u.%u.%u\n", NIPQUAD(src_ip));
|
||||
pr_debug("ACCOUNT: New src_ip: %pI4\n", &src_ip);
|
||||
++*itemcount;
|
||||
}
|
||||
if (is_dst_new_ip) {
|
||||
pr_debug("ACCOUNT: New dst_ip: %u.%u.%u.%u\n", NIPQUAD(dst_ip));
|
||||
pr_debug("ACCOUNT: New dst_ip: %pI4\n", &dst_ip);
|
||||
++*itemcount;
|
||||
}
|
||||
}
|
||||
@@ -478,22 +481,24 @@ static void ipt_acc_depth2_insert(struct ipt_acc_mask_8 *mask_8,
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int ipt_acc_target(struct sk_buff **pskb, const struct xt_action_param *par)
|
||||
static unsigned int
|
||||
ipt_acc_target(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
{
|
||||
struct ipt_acc_net *ian = net_generic(par->state->net, ipt_acc_net_id);
|
||||
struct ipt_acc_table *ipt_acc_tables = ian->ipt_acc_tables;
|
||||
const struct ipt_acc_info *info =
|
||||
par->targinfo;
|
||||
|
||||
__be32 src_ip = ip_hdr(*pskb)->saddr;
|
||||
__be32 dst_ip = ip_hdr(*pskb)->daddr;
|
||||
uint32_t size = ntohs(ip_hdr(*pskb)->tot_len);
|
||||
__be32 src_ip = ip_hdr(skb)->saddr;
|
||||
__be32 dst_ip = ip_hdr(skb)->daddr;
|
||||
uint32_t size = ntohs(ip_hdr(skb)->tot_len);
|
||||
|
||||
spin_lock_bh(&ipt_acc_lock);
|
||||
spin_lock_bh(&ian->ipt_acc_lock);
|
||||
|
||||
if (ipt_acc_tables[info->table_nr].name[0] == 0) {
|
||||
printk("ACCOUNT: ipt_acc_target: Invalid table id %u. "
|
||||
"IPs %u.%u.%u.%u/%u.%u.%u.%u\n", info->table_nr,
|
||||
NIPQUAD(src_ip), NIPQUAD(dst_ip));
|
||||
spin_unlock_bh(&ipt_acc_lock);
|
||||
"IPs %pI4/%pI4\n", info->table_nr, &src_ip, &dst_ip);
|
||||
spin_unlock_bh(&ian->ipt_acc_lock);
|
||||
return XT_CONTINUE;
|
||||
}
|
||||
|
||||
@@ -505,7 +510,7 @@ static unsigned int ipt_acc_target(struct sk_buff **pskb, const struct xt_action
|
||||
ipt_acc_tables[info->table_nr].ip,
|
||||
ipt_acc_tables[info->table_nr].netmask,
|
||||
src_ip, dst_ip, size, &ipt_acc_tables[info->table_nr].itemcount);
|
||||
spin_unlock_bh(&ipt_acc_lock);
|
||||
spin_unlock_bh(&ian->ipt_acc_lock);
|
||||
return XT_CONTINUE;
|
||||
}
|
||||
|
||||
@@ -516,7 +521,7 @@ static unsigned int ipt_acc_target(struct sk_buff **pskb, const struct xt_action
|
||||
ipt_acc_tables[info->table_nr].ip,
|
||||
ipt_acc_tables[info->table_nr].netmask,
|
||||
src_ip, dst_ip, size, &ipt_acc_tables[info->table_nr].itemcount);
|
||||
spin_unlock_bh(&ipt_acc_lock);
|
||||
spin_unlock_bh(&ian->ipt_acc_lock);
|
||||
return XT_CONTINUE;
|
||||
}
|
||||
|
||||
@@ -527,21 +532,19 @@ static unsigned int ipt_acc_target(struct sk_buff **pskb, const struct xt_action
|
||||
ipt_acc_tables[info->table_nr].ip,
|
||||
ipt_acc_tables[info->table_nr].netmask,
|
||||
src_ip, dst_ip, size, &ipt_acc_tables[info->table_nr].itemcount);
|
||||
spin_unlock_bh(&ipt_acc_lock);
|
||||
spin_unlock_bh(&ian->ipt_acc_lock);
|
||||
return XT_CONTINUE;
|
||||
}
|
||||
|
||||
printk("ACCOUNT: ipt_acc_target: Unable to process packet. "
|
||||
"Table id %u. IPs %u.%u.%u.%u/%u.%u.%u.%u\n",
|
||||
info->table_nr, NIPQUAD(src_ip), NIPQUAD(dst_ip));
|
||||
|
||||
spin_unlock_bh(&ipt_acc_lock);
|
||||
printk("ACCOUNT: ipt_acc_target: Unable to process packet. Table id "
|
||||
"%u. IPs %pI4/%pI4\n", info->table_nr, &src_ip, &dst_ip);
|
||||
spin_unlock_bh(&ian->ipt_acc_lock);
|
||||
return XT_CONTINUE;
|
||||
}
|
||||
|
||||
/*
|
||||
Functions dealing with "handles":
|
||||
Handles are snapshots of a accounting state.
|
||||
Handles are snapshots of an accounting state.
|
||||
|
||||
read snapshots are only for debugging the code
|
||||
and are very expensive concerning speed/memory
|
||||
@@ -556,7 +559,7 @@ static unsigned int ipt_acc_target(struct sk_buff **pskb, const struct xt_action
|
||||
but there could be two or more applications accessing the data
|
||||
at the same time.
|
||||
*/
|
||||
static int ipt_acc_handle_find_slot(void)
|
||||
static int ipt_acc_handle_find_slot(struct ipt_acc_handle *ipt_acc_handles)
|
||||
{
|
||||
unsigned int i;
|
||||
/* Insert new table */
|
||||
@@ -576,7 +579,8 @@ static int ipt_acc_handle_find_slot(void)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int ipt_acc_handle_free(unsigned int handle)
|
||||
static int ipt_acc_handle_free(struct ipt_acc_handle *ipt_acc_handles,
|
||||
unsigned int handle)
|
||||
{
|
||||
if (handle >= ACCOUNT_MAX_HANDLES) {
|
||||
printk("ACCOUNT: Invalid handle for ipt_acc_handle_free() specified:"
|
||||
@@ -592,18 +596,19 @@ static int ipt_acc_handle_free(unsigned int handle)
|
||||
|
||||
/* Prepare data for read without flush. Use only for debugging!
|
||||
Real applications should use read&flush as it's way more efficent */
|
||||
static int ipt_acc_handle_prepare_read(char *tablename,
|
||||
static int ipt_acc_handle_prepare_read(struct ipt_acc_table *ipt_acc_tables,
|
||||
char *tablename,
|
||||
struct ipt_acc_handle *dest, uint32_t *count)
|
||||
{
|
||||
int table_nr = -1;
|
||||
uint8_t depth;
|
||||
|
||||
for (table_nr = 0; table_nr < ACCOUNT_MAX_TABLES; table_nr++)
|
||||
for (table_nr = 0; table_nr < max_tables_limit; table_nr++)
|
||||
if (strncmp(ipt_acc_tables[table_nr].name, tablename,
|
||||
ACCOUNT_TABLE_NAME_LEN) == 0)
|
||||
break;
|
||||
|
||||
if (table_nr == ACCOUNT_MAX_TABLES) {
|
||||
if (table_nr == max_tables_limit) {
|
||||
printk("ACCOUNT: ipt_acc_handle_prepare_read(): "
|
||||
"Table %s not found\n", tablename);
|
||||
return -1;
|
||||
@@ -615,7 +620,8 @@ static int ipt_acc_handle_prepare_read(char *tablename,
|
||||
dest->itemcount = ipt_acc_tables[table_nr].itemcount;
|
||||
|
||||
/* allocate "root" table */
|
||||
if ((dest->data = ipt_acc_zalloc_page()) == NULL) {
|
||||
dest->data = ipt_acc_zalloc_page();
|
||||
if (dest->data == NULL) {
|
||||
printk("ACCOUNT: out of memory for root table "
|
||||
"in ipt_acc_handle_prepare_read()\n");
|
||||
return -1;
|
||||
@@ -634,7 +640,8 @@ static int ipt_acc_handle_prepare_read(char *tablename,
|
||||
unsigned int b;
|
||||
|
||||
for (b = 0; b <= 255; b++) {
|
||||
if (src_16->mask_24[b]) {
|
||||
if (src_16->mask_24[b] == NULL)
|
||||
continue;
|
||||
if ((network_16->mask_24[b] =
|
||||
ipt_acc_zalloc_page()) == NULL) {
|
||||
printk("ACCOUNT: out of memory during copy of 16 bit "
|
||||
@@ -646,7 +653,6 @@ static int ipt_acc_handle_prepare_read(char *tablename,
|
||||
memcpy(network_16->mask_24[b], src_16->mask_24[b],
|
||||
sizeof(struct ipt_acc_mask_24));
|
||||
}
|
||||
}
|
||||
} else if (depth == 2) {
|
||||
struct ipt_acc_mask_8 *src_8 =
|
||||
ipt_acc_tables[table_nr].data;
|
||||
@@ -655,7 +661,8 @@ static int ipt_acc_handle_prepare_read(char *tablename,
|
||||
unsigned int a, b;
|
||||
|
||||
for (a = 0; a <= 255; a++) {
|
||||
if (src_8->mask_16[a]) {
|
||||
if (src_8->mask_16[a] == NULL)
|
||||
continue;
|
||||
if ((network_8->mask_16[a] =
|
||||
ipt_acc_zalloc_page()) == NULL) {
|
||||
printk("ACCOUNT: out of memory during copy of 24 bit network"
|
||||
@@ -671,7 +678,8 @@ static int ipt_acc_handle_prepare_read(char *tablename,
|
||||
network_16 = network_8->mask_16[a];
|
||||
|
||||
for (b = 0; b <= 255; b++) {
|
||||
if (src_16->mask_24[b]) {
|
||||
if (src_16->mask_24[b] == NULL)
|
||||
continue;
|
||||
if ((network_16->mask_24[b] =
|
||||
ipt_acc_zalloc_page()) == NULL) {
|
||||
printk("ACCOUNT: out of memory during copy of 16 bit"
|
||||
@@ -685,8 +693,6 @@ static int ipt_acc_handle_prepare_read(char *tablename,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*count = ipt_acc_tables[table_nr].itemcount;
|
||||
|
||||
@@ -694,25 +700,27 @@ static int ipt_acc_handle_prepare_read(char *tablename,
|
||||
}
|
||||
|
||||
/* Prepare data for read and flush it */
|
||||
static int ipt_acc_handle_prepare_read_flush(char *tablename,
|
||||
static int ipt_acc_handle_prepare_read_flush(struct ipt_acc_table *ipt_acc_tables,
|
||||
char *tablename,
|
||||
struct ipt_acc_handle *dest, uint32_t *count)
|
||||
{
|
||||
int table_nr;
|
||||
void *new_data_page;
|
||||
|
||||
for (table_nr = 0; table_nr < ACCOUNT_MAX_TABLES; table_nr++)
|
||||
for (table_nr = 0; table_nr < max_tables_limit; table_nr++)
|
||||
if (strncmp(ipt_acc_tables[table_nr].name, tablename,
|
||||
ACCOUNT_TABLE_NAME_LEN) == 0)
|
||||
break;
|
||||
|
||||
if (table_nr == ACCOUNT_MAX_TABLES) {
|
||||
if (table_nr == max_tables_limit) {
|
||||
printk("ACCOUNT: ipt_acc_handle_prepare_read_flush(): "
|
||||
"Table %s not found\n", tablename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Try to allocate memory */
|
||||
if (!(new_data_page = ipt_acc_zalloc_page())) {
|
||||
new_data_page = ipt_acc_zalloc_page();
|
||||
if (new_data_page == NULL) {
|
||||
printk("ACCOUNT: ipt_acc_handle_prepare_read_flush(): "
|
||||
"Out of memory!\n");
|
||||
return -1;
|
||||
@@ -735,7 +743,8 @@ static int ipt_acc_handle_prepare_read_flush(char *tablename,
|
||||
/* Copy 8 bit network data into a prepared buffer.
|
||||
We only copy entries != 0 to increase performance.
|
||||
*/
|
||||
static int ipt_acc_handle_copy_data(void *to_user, unsigned long *to_user_pos,
|
||||
static int ipt_acc_handle_copy_data(struct ipt_acc_net *ian,
|
||||
void *to_user, unsigned long *to_user_pos,
|
||||
unsigned long *tmpbuf_pos,
|
||||
struct ipt_acc_mask_24 *data,
|
||||
uint32_t net_ip, uint32_t net_OR_mask)
|
||||
@@ -745,9 +754,11 @@ static int ipt_acc_handle_copy_data(void *to_user, unsigned long *to_user_pos,
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i <= 255; i++) {
|
||||
if (data->ip[i].src_packets || data->ip[i].dst_packets) {
|
||||
handle_ip.ip = net_ip | net_OR_mask | i;
|
||||
if (data->ip[i].src_packets == 0 &&
|
||||
data->ip[i].dst_packets == 0)
|
||||
continue;
|
||||
|
||||
handle_ip.ip = net_ip | net_OR_mask | i;
|
||||
handle_ip.src_packets = data->ip[i].src_packets;
|
||||
handle_ip.src_bytes = data->ip[i].src_bytes;
|
||||
handle_ip.dst_packets = data->ip[i].dst_packets;
|
||||
@@ -755,16 +766,15 @@ static int ipt_acc_handle_copy_data(void *to_user, unsigned long *to_user_pos,
|
||||
|
||||
/* Temporary buffer full? Flush to userspace */
|
||||
if (*tmpbuf_pos + handle_ip_size >= PAGE_SIZE) {
|
||||
if (copy_to_user(to_user + *to_user_pos, ipt_acc_tmpbuf,
|
||||
if (copy_to_user(to_user + *to_user_pos, ian->ipt_acc_tmpbuf,
|
||||
*tmpbuf_pos))
|
||||
return -EFAULT;
|
||||
*to_user_pos = *to_user_pos + *tmpbuf_pos;
|
||||
*tmpbuf_pos = 0;
|
||||
}
|
||||
memcpy(ipt_acc_tmpbuf + *tmpbuf_pos, &handle_ip, handle_ip_size);
|
||||
memcpy(ian->ipt_acc_tmpbuf + *tmpbuf_pos, &handle_ip, handle_ip_size);
|
||||
*tmpbuf_pos += handle_ip_size;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -773,7 +783,8 @@ static int ipt_acc_handle_copy_data(void *to_user, unsigned long *to_user_pos,
|
||||
We only copy entries != 0 to increase performance.
|
||||
Overwrites ipt_acc_tmpbuf.
|
||||
*/
|
||||
static int ipt_acc_handle_get_data(uint32_t handle, void *to_user)
|
||||
static int ipt_acc_handle_get_data(struct ipt_acc_net *ian,
|
||||
uint32_t handle, void *to_user)
|
||||
{
|
||||
unsigned long to_user_pos = 0, tmpbuf_pos = 0;
|
||||
uint32_t net_ip;
|
||||
@@ -785,25 +796,25 @@ static int ipt_acc_handle_get_data(uint32_t handle, void *to_user)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ipt_acc_handles[handle].data == NULL) {
|
||||
if (ian->ipt_acc_handles[handle].data == NULL) {
|
||||
printk("ACCOUNT: handle %u is BROKEN: Contains no data\n", handle);
|
||||
return -1;
|
||||
}
|
||||
|
||||
net_ip = ntohl(ipt_acc_handles[handle].ip);
|
||||
depth = ipt_acc_handles[handle].depth;
|
||||
net_ip = ntohl(ian->ipt_acc_handles[handle].ip);
|
||||
depth = ian->ipt_acc_handles[handle].depth;
|
||||
|
||||
/* 8 bit network */
|
||||
if (depth == 0) {
|
||||
struct ipt_acc_mask_24 *network =
|
||||
ipt_acc_handles[handle].data;
|
||||
if (ipt_acc_handle_copy_data(to_user, &to_user_pos, &tmpbuf_pos,
|
||||
ian->ipt_acc_handles[handle].data;
|
||||
if (ipt_acc_handle_copy_data(ian, to_user, &to_user_pos, &tmpbuf_pos,
|
||||
network, net_ip, 0))
|
||||
return -1;
|
||||
|
||||
/* Flush remaining data to userspace */
|
||||
if (tmpbuf_pos)
|
||||
if (copy_to_user(to_user + to_user_pos, ipt_acc_tmpbuf, tmpbuf_pos))
|
||||
if (copy_to_user(to_user + to_user_pos, ian->ipt_acc_tmpbuf, tmpbuf_pos))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
@@ -812,13 +823,13 @@ static int ipt_acc_handle_get_data(uint32_t handle, void *to_user)
|
||||
/* 16 bit network */
|
||||
if (depth == 1) {
|
||||
struct ipt_acc_mask_16 *network_16 =
|
||||
ipt_acc_handles[handle].data;
|
||||
ian->ipt_acc_handles[handle].data;
|
||||
unsigned int b;
|
||||
for (b = 0; b <= 255; b++) {
|
||||
if (network_16->mask_24[b]) {
|
||||
struct ipt_acc_mask_24 *network =
|
||||
network_16->mask_24[b];
|
||||
if (ipt_acc_handle_copy_data(to_user, &to_user_pos,
|
||||
if (ipt_acc_handle_copy_data(ian, to_user, &to_user_pos,
|
||||
&tmpbuf_pos, network, net_ip, (b << 8)))
|
||||
return -1;
|
||||
}
|
||||
@@ -826,7 +837,7 @@ static int ipt_acc_handle_get_data(uint32_t handle, void *to_user)
|
||||
|
||||
/* Flush remaining data to userspace */
|
||||
if (tmpbuf_pos)
|
||||
if (copy_to_user(to_user + to_user_pos, ipt_acc_tmpbuf, tmpbuf_pos))
|
||||
if (copy_to_user(to_user + to_user_pos, ian->ipt_acc_tmpbuf, tmpbuf_pos))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
@@ -835,7 +846,7 @@ static int ipt_acc_handle_get_data(uint32_t handle, void *to_user)
|
||||
/* 24 bit network */
|
||||
if (depth == 2) {
|
||||
struct ipt_acc_mask_8 *network_8 =
|
||||
ipt_acc_handles[handle].data;
|
||||
ian->ipt_acc_handles[handle].data;
|
||||
unsigned int a, b;
|
||||
for (a = 0; a <= 255; a++) {
|
||||
if (network_8->mask_16[a]) {
|
||||
@@ -845,7 +856,7 @@ static int ipt_acc_handle_get_data(uint32_t handle, void *to_user)
|
||||
if (network_16->mask_24[b]) {
|
||||
struct ipt_acc_mask_24 *network =
|
||||
network_16->mask_24[b];
|
||||
if (ipt_acc_handle_copy_data(to_user,
|
||||
if (ipt_acc_handle_copy_data(ian, to_user,
|
||||
&to_user_pos, &tmpbuf_pos,
|
||||
network, net_ip, (a << 16) | (b << 8)))
|
||||
return -1;
|
||||
@@ -856,7 +867,7 @@ static int ipt_acc_handle_get_data(uint32_t handle, void *to_user)
|
||||
|
||||
/* Flush remaining data to userspace */
|
||||
if (tmpbuf_pos)
|
||||
if (copy_to_user(to_user + to_user_pos, ipt_acc_tmpbuf, tmpbuf_pos))
|
||||
if (copy_to_user(to_user + to_user_pos, ian->ipt_acc_tmpbuf, tmpbuf_pos))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
@@ -866,8 +877,15 @@ static int ipt_acc_handle_get_data(uint32_t handle, void *to_user)
|
||||
}
|
||||
|
||||
static int ipt_acc_set_ctl(struct sock *sk, int cmd,
|
||||
void *user, unsigned int len)
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0)
|
||||
void *user,
|
||||
#else
|
||||
sockptr_t arg,
|
||||
#endif
|
||||
unsigned int len)
|
||||
{
|
||||
struct net *net = sock_net(sk);
|
||||
struct ipt_acc_net *ian = net_generic(net, ipt_acc_net_id);
|
||||
struct ipt_acc_handle_sockopt handle;
|
||||
int ret = -EINVAL;
|
||||
|
||||
@@ -883,22 +901,27 @@ static int ipt_acc_set_ctl(struct sock *sk, int cmd,
|
||||
break;
|
||||
}
|
||||
|
||||
if (copy_from_user(&handle, user, len)) {
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0)
|
||||
if (copy_from_user(&handle, user, len))
|
||||
#else
|
||||
if (copy_from_sockptr(&handle, arg, len))
|
||||
#endif
|
||||
{
|
||||
printk("ACCOUNT: ipt_acc_set_ctl: copy_from_user failed for "
|
||||
"IPT_SO_SET_HANDLE_FREE\n");
|
||||
break;
|
||||
}
|
||||
|
||||
down(&ipt_acc_userspace_mutex);
|
||||
ret = ipt_acc_handle_free(handle.handle_nr);
|
||||
up(&ipt_acc_userspace_mutex);
|
||||
down(&ian->ipt_acc_userspace_mutex);
|
||||
ret = ipt_acc_handle_free(ian->ipt_acc_handles, handle.handle_nr);
|
||||
up(&ian->ipt_acc_userspace_mutex);
|
||||
break;
|
||||
case IPT_SO_SET_ACCOUNT_HANDLE_FREE_ALL: {
|
||||
unsigned int i;
|
||||
down(&ipt_acc_userspace_mutex);
|
||||
down(&ian->ipt_acc_userspace_mutex);
|
||||
for (i = 0; i < ACCOUNT_MAX_HANDLES; i++)
|
||||
ipt_acc_handle_free(i);
|
||||
up(&ipt_acc_userspace_mutex);
|
||||
ipt_acc_handle_free(ian->ipt_acc_handles, i);
|
||||
up(&ian->ipt_acc_userspace_mutex);
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
@@ -911,6 +934,8 @@ static int ipt_acc_set_ctl(struct sock *sk, int cmd,
|
||||
|
||||
static int ipt_acc_get_ctl(struct sock *sk, int cmd, void *user, int *len)
|
||||
{
|
||||
struct net *net = sock_net(sk);
|
||||
struct ipt_acc_net *ian = net_generic(net, ipt_acc_net_id);
|
||||
struct ipt_acc_handle_sockopt handle;
|
||||
int ret = -EINVAL;
|
||||
|
||||
@@ -935,28 +960,29 @@ static int ipt_acc_get_ctl(struct sock *sk, int cmd, void *user, int *len)
|
||||
break;
|
||||
}
|
||||
|
||||
spin_lock_bh(&ipt_acc_lock);
|
||||
spin_lock_bh(&ian->ipt_acc_lock);
|
||||
if (cmd == IPT_SO_GET_ACCOUNT_PREPARE_READ_FLUSH)
|
||||
ret = ipt_acc_handle_prepare_read_flush(
|
||||
handle.name, &dest, &handle.itemcount);
|
||||
ian->ipt_acc_tables, handle.name, &dest, &handle.itemcount);
|
||||
else
|
||||
ret = ipt_acc_handle_prepare_read(
|
||||
handle.name, &dest, &handle.itemcount);
|
||||
spin_unlock_bh(&ipt_acc_lock);
|
||||
ian->ipt_acc_tables, handle.name, &dest, &handle.itemcount);
|
||||
spin_unlock_bh(&ian->ipt_acc_lock);
|
||||
// Error occured during prepare_read?
|
||||
if (ret == -1)
|
||||
return -EINVAL;
|
||||
|
||||
/* Allocate a userspace handle */
|
||||
down(&ipt_acc_userspace_mutex);
|
||||
if ((handle.handle_nr = ipt_acc_handle_find_slot()) == -1) {
|
||||
down(&ian->ipt_acc_userspace_mutex);
|
||||
handle.handle_nr = ipt_acc_handle_find_slot(ian->ipt_acc_handles);
|
||||
if (handle.handle_nr == -1) {
|
||||
ipt_acc_data_free(dest.data, dest.depth);
|
||||
up(&ipt_acc_userspace_mutex);
|
||||
up(&ian->ipt_acc_userspace_mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
memcpy(&ipt_acc_handles[handle.handle_nr], &dest,
|
||||
memcpy(&ian->ipt_acc_handles[handle.handle_nr], &dest,
|
||||
sizeof(struct ipt_acc_handle));
|
||||
up(&ipt_acc_userspace_mutex);
|
||||
up(&ian->ipt_acc_userspace_mutex);
|
||||
|
||||
if (copy_to_user(user, &handle,
|
||||
sizeof(struct ipt_acc_handle_sockopt))) {
|
||||
@@ -985,19 +1011,19 @@ static int ipt_acc_get_ctl(struct sock *sk, int cmd, void *user, int *len)
|
||||
break;
|
||||
}
|
||||
|
||||
if (*len < ipt_acc_handles[handle.handle_nr].itemcount
|
||||
if (*len < ian->ipt_acc_handles[handle.handle_nr].itemcount
|
||||
* sizeof(struct ipt_acc_handle_ip)) {
|
||||
printk("ACCOUNT: ipt_acc_get_ctl: not enough space (%u < %zu)"
|
||||
" to store data from IPT_SO_GET_ACCOUNT_GET_DATA\n",
|
||||
*len, ipt_acc_handles[handle.handle_nr].itemcount
|
||||
*len, ian->ipt_acc_handles[handle.handle_nr].itemcount
|
||||
* sizeof(struct ipt_acc_handle_ip));
|
||||
ret = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
down(&ipt_acc_userspace_mutex);
|
||||
ret = ipt_acc_handle_get_data(handle.handle_nr, user);
|
||||
up(&ipt_acc_userspace_mutex);
|
||||
down(&ian->ipt_acc_userspace_mutex);
|
||||
ret = ipt_acc_handle_get_data(ian, handle.handle_nr, user);
|
||||
up(&ian->ipt_acc_userspace_mutex);
|
||||
if (ret) {
|
||||
printk("ACCOUNT: ipt_acc_get_ctl: ipt_acc_handle_get_data"
|
||||
" failed for handle %u\n", handle.handle_nr);
|
||||
@@ -1017,11 +1043,11 @@ static int ipt_acc_get_ctl(struct sock *sk, int cmd, void *user, int *len)
|
||||
|
||||
/* Find out how many handles are in use */
|
||||
handle.itemcount = 0;
|
||||
down(&ipt_acc_userspace_mutex);
|
||||
down(&ian->ipt_acc_userspace_mutex);
|
||||
for (i = 0; i < ACCOUNT_MAX_HANDLES; i++)
|
||||
if (ipt_acc_handles[i].data)
|
||||
if (ian->ipt_acc_handles[i].data)
|
||||
handle.itemcount++;
|
||||
up(&ipt_acc_userspace_mutex);
|
||||
up(&ian->ipt_acc_userspace_mutex);
|
||||
|
||||
if (copy_to_user(user, &handle,
|
||||
sizeof(struct ipt_acc_handle_sockopt))) {
|
||||
@@ -1035,38 +1061,38 @@ static int ipt_acc_get_ctl(struct sock *sk, int cmd, void *user, int *len)
|
||||
uint32_t size = 0, i, name_len;
|
||||
char *tnames;
|
||||
|
||||
spin_lock_bh(&ipt_acc_lock);
|
||||
spin_lock_bh(&ian->ipt_acc_lock);
|
||||
|
||||
/* Determine size of table names */
|
||||
for (i = 0; i < ACCOUNT_MAX_TABLES; i++) {
|
||||
if (ipt_acc_tables[i].name[0] != 0)
|
||||
size += strlen(ipt_acc_tables[i].name) + 1;
|
||||
for (i = 0; i < max_tables_limit; i++) {
|
||||
if (ian->ipt_acc_tables[i].name[0] != 0)
|
||||
size += strlen(ian->ipt_acc_tables[i].name) + 1;
|
||||
}
|
||||
size += 1; /* Terminating NULL character */
|
||||
|
||||
if (*len < size || size > PAGE_SIZE) {
|
||||
spin_unlock_bh(&ipt_acc_lock);
|
||||
spin_unlock_bh(&ian->ipt_acc_lock);
|
||||
printk("ACCOUNT: ipt_acc_get_ctl: not enough space (%u < %u < %lu)"
|
||||
" to store table names\n", *len, size, PAGE_SIZE);
|
||||
ret = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
/* Copy table names to userspace */
|
||||
tnames = ipt_acc_tmpbuf;
|
||||
for (i = 0; i < ACCOUNT_MAX_TABLES; i++) {
|
||||
if (ipt_acc_tables[i].name[0] != 0) {
|
||||
name_len = strlen(ipt_acc_tables[i].name) + 1;
|
||||
memcpy(tnames, ipt_acc_tables[i].name, name_len);
|
||||
tnames = ian->ipt_acc_tmpbuf;
|
||||
for (i = 0; i < max_tables_limit; i++) {
|
||||
if (ian->ipt_acc_tables[i].name[0] != 0) {
|
||||
name_len = strlen(ian->ipt_acc_tables[i].name) + 1;
|
||||
memcpy(tnames, ian->ipt_acc_tables[i].name, name_len);
|
||||
tnames += name_len;
|
||||
}
|
||||
}
|
||||
spin_unlock_bh(&ipt_acc_lock);
|
||||
spin_unlock_bh(&ian->ipt_acc_lock);
|
||||
|
||||
/* Terminating NULL character */
|
||||
*tnames = 0;
|
||||
|
||||
/* Transfer to userspace */
|
||||
if (copy_to_user(user, ipt_acc_tmpbuf, size))
|
||||
if (copy_to_user(user, ian->ipt_acc_tmpbuf, size))
|
||||
return -EFAULT;
|
||||
|
||||
ret = 0;
|
||||
@@ -1079,6 +1105,59 @@ static int ipt_acc_get_ctl(struct sock *sk, int cmd, void *user, int *len)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __net_init ipt_acc_net_init(struct net *net)
|
||||
{
|
||||
struct ipt_acc_net *ian = net_generic(net, ipt_acc_net_id);
|
||||
|
||||
memset(ian, 0, sizeof(*ian));
|
||||
sema_init(&ian->ipt_acc_userspace_mutex, 1);
|
||||
|
||||
ian->ipt_acc_tables = kcalloc(max_tables_limit,
|
||||
sizeof(struct ipt_acc_table), GFP_KERNEL);
|
||||
if (ian->ipt_acc_tables == NULL) {
|
||||
printk("ACCOUNT: Out of memory allocating account_tables structure");
|
||||
goto error_cleanup;
|
||||
}
|
||||
ian->ipt_acc_handles = kcalloc(ACCOUNT_MAX_HANDLES,
|
||||
sizeof(struct ipt_acc_handle), GFP_KERNEL);
|
||||
if (ian->ipt_acc_handles == NULL) {
|
||||
printk("ACCOUNT: Out of memory allocating account_handles structure");
|
||||
goto error_cleanup;
|
||||
}
|
||||
|
||||
/* Allocate one page as temporary storage */
|
||||
ian->ipt_acc_tmpbuf = (void *)__get_free_pages(GFP_KERNEL, 2);
|
||||
if (ian->ipt_acc_tmpbuf == NULL) {
|
||||
printk("ACCOUNT: Out of memory for temporary buffer page\n");
|
||||
goto error_cleanup;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_cleanup:
|
||||
kfree(ian->ipt_acc_tables);
|
||||
kfree(ian->ipt_acc_handles);
|
||||
free_pages((unsigned long)ian->ipt_acc_tmpbuf, 2);
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static void __net_exit ipt_acc_net_exit(struct net *net)
|
||||
{
|
||||
struct ipt_acc_net *ian = net_generic(net, ipt_acc_net_id);
|
||||
|
||||
kfree(ian->ipt_acc_tables);
|
||||
kfree(ian->ipt_acc_handles);
|
||||
free_pages((unsigned long)ian->ipt_acc_tmpbuf, 2);
|
||||
}
|
||||
|
||||
static struct pernet_operations ipt_acc_net_ops = {
|
||||
.init = ipt_acc_net_init,
|
||||
.exit = ipt_acc_net_exit,
|
||||
.id = &ipt_acc_net_id,
|
||||
.size = sizeof(struct ipt_acc_net),
|
||||
};
|
||||
|
||||
static struct xt_target xt_acc_reg __read_mostly = {
|
||||
.name = "ACCOUNT",
|
||||
.revision = 1,
|
||||
@@ -1102,63 +1181,41 @@ static struct nf_sockopt_ops ipt_acc_sockopts = {
|
||||
|
||||
static int __init account_tg_init(void)
|
||||
{
|
||||
sema_init(&ipt_acc_userspace_mutex, 1);
|
||||
int ret;
|
||||
|
||||
if ((ipt_acc_tables =
|
||||
kmalloc(ACCOUNT_MAX_TABLES *
|
||||
sizeof(struct ipt_acc_table), GFP_KERNEL)) == NULL) {
|
||||
printk("ACCOUNT: Out of memory allocating account_tables structure");
|
||||
goto error_cleanup;
|
||||
}
|
||||
memset(ipt_acc_tables, 0,
|
||||
ACCOUNT_MAX_TABLES * sizeof(struct ipt_acc_table));
|
||||
|
||||
if ((ipt_acc_handles =
|
||||
kmalloc(ACCOUNT_MAX_HANDLES *
|
||||
sizeof(struct ipt_acc_handle), GFP_KERNEL)) == NULL) {
|
||||
printk("ACCOUNT: Out of memory allocating account_handles structure");
|
||||
goto error_cleanup;
|
||||
}
|
||||
memset(ipt_acc_handles, 0,
|
||||
ACCOUNT_MAX_HANDLES * sizeof(struct ipt_acc_handle));
|
||||
|
||||
/* Allocate one page as temporary storage */
|
||||
if ((ipt_acc_tmpbuf = (void*)__get_free_page(GFP_KERNEL)) == NULL) {
|
||||
printk("ACCOUNT: Out of memory for temporary buffer page\n");
|
||||
goto error_cleanup;
|
||||
ret = register_pernet_subsys(&ipt_acc_net_ops);
|
||||
if (ret < 0) {
|
||||
pr_err("ACCOUNT: cannot register per net operations.\n");
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
/* Register setsockopt */
|
||||
if (nf_register_sockopt(&ipt_acc_sockopts) < 0) {
|
||||
printk("ACCOUNT: Can't register sockopts. Aborting\n");
|
||||
goto error_cleanup;
|
||||
ret = nf_register_sockopt(&ipt_acc_sockopts);
|
||||
if (ret < 0) {
|
||||
pr_err("ACCOUNT: cannot register sockopts.\n");
|
||||
goto unreg_pernet;
|
||||
}
|
||||
|
||||
if (xt_register_target(&xt_acc_reg))
|
||||
goto error_cleanup;
|
||||
|
||||
ret = xt_register_target(&xt_acc_reg);
|
||||
if (ret < 0) {
|
||||
pr_err("ACCOUNT: cannot register sockopts.\n");
|
||||
goto unreg_sockopt;
|
||||
}
|
||||
return 0;
|
||||
|
||||
error_cleanup:
|
||||
if (ipt_acc_tables)
|
||||
kfree(ipt_acc_tables);
|
||||
if (ipt_acc_handles)
|
||||
kfree(ipt_acc_handles);
|
||||
if (ipt_acc_tmpbuf)
|
||||
free_page((unsigned long)ipt_acc_tmpbuf);
|
||||
|
||||
return -EINVAL;
|
||||
unreg_sockopt:
|
||||
nf_unregister_sockopt(&ipt_acc_sockopts);
|
||||
unreg_pernet:
|
||||
unregister_pernet_subsys(&ipt_acc_net_ops);
|
||||
error_out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit account_tg_exit(void)
|
||||
{
|
||||
xt_unregister_target(&xt_acc_reg);
|
||||
|
||||
nf_unregister_sockopt(&ipt_acc_sockopts);
|
||||
|
||||
kfree(ipt_acc_tables);
|
||||
kfree(ipt_acc_handles);
|
||||
free_page((unsigned long)ipt_acc_tmpbuf);
|
||||
unregister_pernet_subsys(&ipt_acc_net_ops);
|
||||
}
|
||||
|
||||
module_init(account_tg_init);
|
||||
|
@@ -7,9 +7,7 @@
|
||||
* version 2 as published by the Free Software Foundation; *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef _IPT_ACCOUNT_H
|
||||
#define _IPT_ACCOUNT_H
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
* Socket option interface shared between kernel (xt_ACCOUNT) and userspace
|
||||
@@ -34,14 +32,12 @@
|
||||
#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;
|
||||
__be32 net_ip, net_mask;
|
||||
char table_name[ACCOUNT_TABLE_NAME_LEN];
|
||||
int32_t table_nr;
|
||||
};
|
||||
@@ -59,11 +55,6 @@ struct ipt_acc_handle_sockopt {
|
||||
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;
|
||||
__be32 ip, __dummy;
|
||||
uint64_t src_packets, src_bytes, dst_packets, dst_bytes;
|
||||
};
|
||||
|
||||
#endif /* _IPT_ACCOUNT_H */
|
||||
|
@@ -7,23 +7,15 @@ 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
|
||||
ifeq (${VERSION},3)
|
||||
obj-${build_ECHO} += xt_ECHO.o
|
||||
endif
|
||||
obj-${build_IPMARK} += xt_IPMARK.o
|
||||
obj-${build_LOGMARK} += xt_LOGMARK.o
|
||||
obj-${build_RAWNAT} += xt_RAWNAT.o iptable_rawpost.o
|
||||
ifneq (${CONFIG_IP6_NF_IPTABLES},)
|
||||
obj-${build_RAWNAT} += ip6table_rawpost.o
|
||||
endif
|
||||
obj-${build_PROTO} += xt_PROTO.o
|
||||
obj-${build_SYSRQ} += xt_SYSRQ.o
|
||||
obj-${build_STEAL} += xt_STEAL.o
|
||||
obj-${build_TARPIT} += xt_TARPIT.o
|
||||
obj-${build_TEE} += xt_TEE.o
|
||||
obj-${build_condition} += xt_condition.o
|
||||
obj-${build_fuzzy} += xt_fuzzy.o
|
||||
obj-${build_geoip} += xt_geoip.o
|
||||
|
@@ -2,18 +2,15 @@
|
||||
|
||||
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
|
||||
obj-${build_RAWNAT} += libxt_RAWDNAT.so libxt_RAWSNAT.so
|
||||
obj-${build_STEAL} += libxt_STEAL.so
|
||||
obj-${build_PROTO} += libxt_PROTO.so
|
||||
obj-${build_SYSRQ} += libxt_SYSRQ.so
|
||||
obj-${build_TARPIT} += libxt_TARPIT.so
|
||||
obj-${build_TEE} += libxt_TEE.so
|
||||
obj-${build_condition} += libxt_condition.so
|
||||
obj-${build_fuzzy} += libxt_fuzzy.so
|
||||
obj-${build_geoip} += libxt_geoip.so
|
||||
|
@@ -1,14 +0,0 @@
|
||||
#ifndef _COMPAT_NFINETADDR_H
|
||||
#define _COMPAT_NFINETADDR_H 1
|
||||
|
||||
#include <linux/in.h>
|
||||
#include <linux/in6.h>
|
||||
|
||||
union nf_inet_addr {
|
||||
__be32 ip;
|
||||
__be32 ip6[4];
|
||||
struct in_addr in;
|
||||
struct in6_addr in6;
|
||||
};
|
||||
|
||||
#endif /* _COMPAT_NFINETADDR_H */
|
@@ -1,87 +0,0 @@
|
||||
#ifndef XTA_COMPAT_RAWPOST_H
|
||||
#define XTA_COMPAT_RAWPOST_H 1
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
|
||||
typedef struct sk_buff sk_buff_t;
|
||||
#else
|
||||
typedef struct sk_buff *sk_buff_t;
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 21)
|
||||
#define XT_TARGET_INIT(__name, __size) \
|
||||
{ \
|
||||
.target.u.user = { \
|
||||
.target_size = XT_ALIGN(__size), \
|
||||
.name = __name, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define IPT_ENTRY_INIT(__size) \
|
||||
{ \
|
||||
.target_offset = sizeof(struct ipt_entry), \
|
||||
.next_offset = (__size), \
|
||||
}
|
||||
|
||||
#define IPT_STANDARD_INIT(__verdict) \
|
||||
{ \
|
||||
.entry = IPT_ENTRY_INIT(sizeof(struct ipt_standard)), \
|
||||
.target = XT_TARGET_INIT(IPT_STANDARD_TARGET, \
|
||||
sizeof(struct xt_standard_target)), \
|
||||
.target.verdict = -(__verdict) - 1, \
|
||||
}
|
||||
|
||||
#define IPT_ERROR_INIT \
|
||||
{ \
|
||||
.entry = IPT_ENTRY_INIT(sizeof(struct ipt_error)), \
|
||||
.target = XT_TARGET_INIT(IPT_ERROR_TARGET, \
|
||||
sizeof(struct ipt_error_target)), \
|
||||
.target.errorname = "ERROR", \
|
||||
}
|
||||
|
||||
#define IP6T_ENTRY_INIT(__size) \
|
||||
{ \
|
||||
.target_offset = sizeof(struct ip6t_entry), \
|
||||
.next_offset = (__size), \
|
||||
}
|
||||
|
||||
#define IP6T_STANDARD_INIT(__verdict) \
|
||||
{ \
|
||||
.entry = IP6T_ENTRY_INIT(sizeof(struct ip6t_standard)), \
|
||||
.target = XT_TARGET_INIT(IP6T_STANDARD_TARGET, \
|
||||
sizeof(struct ip6t_standard_target)), \
|
||||
.target.verdict = -(__verdict) - 1, \
|
||||
}
|
||||
|
||||
#define IP6T_ERROR_INIT \
|
||||
{ \
|
||||
.entry = IP6T_ENTRY_INIT(sizeof(struct ip6t_error)), \
|
||||
.target = XT_TARGET_INIT(IP6T_ERROR_TARGET, \
|
||||
sizeof(struct ip6t_error_target)), \
|
||||
.target.errorname = "ERROR", \
|
||||
}
|
||||
|
||||
#endif /* 2.6.21 */
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 20)
|
||||
# include <linux/netfilter_ipv6/ip6_tables.h>
|
||||
/* Standard entry */
|
||||
struct ip6t_standard
|
||||
{
|
||||
struct ip6t_entry entry;
|
||||
struct ip6t_standard_target target;
|
||||
};
|
||||
|
||||
struct ip6t_error_target
|
||||
{
|
||||
struct ip6t_entry_target target;
|
||||
char errorname[IP6T_FUNCTION_MAXNAMELEN];
|
||||
};
|
||||
|
||||
struct ip6t_error
|
||||
{
|
||||
struct ip6t_entry entry;
|
||||
struct ip6t_error_target target;
|
||||
};
|
||||
#endif /* 2.6.20 */
|
||||
|
||||
#endif /* XTA_COMPAT_RAWPOST_H */
|
@@ -1,62 +1,12 @@
|
||||
#ifndef COMPAT_SKBUFF_H
|
||||
#define COMPAT_SKBUFF_H 1
|
||||
|
||||
#pragma once
|
||||
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)
|
||||
#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
|
||||
# define skb_secmark(skb) ((skb)->secmark)
|
||||
#else
|
||||
# define skb_secmark(skb) 0
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 21)
|
||||
# define ip_hdr(skb) ((skb)->nh.iph)
|
||||
# define ip_hdrlen(skb) (ip_hdr(skb)->ihl * 4)
|
||||
# define ipv6_hdr(skb) ((skb)->nh.ipv6h)
|
||||
# define skb_network_header(skb) ((skb)->nh.raw)
|
||||
# define skb_transport_header(skb) ((skb)->h.raw)
|
||||
static inline void skb_reset_network_header(struct sk_buff *skb)
|
||||
{
|
||||
skb->nh.raw = skb->data;
|
||||
}
|
||||
static inline struct tcphdr *tcp_hdr(const struct sk_buff *skb)
|
||||
{
|
||||
return (void *)skb_transport_header(skb);
|
||||
}
|
||||
static inline struct udphdr *udp_hdr(const struct sk_buff *skb)
|
||||
{
|
||||
return (void *)skb_transport_header(skb);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* COMPAT_SKBUFF_H */
|
||||
|
@@ -1,12 +1,8 @@
|
||||
/*
|
||||
* Userspace-level compat hacks
|
||||
*/
|
||||
#ifndef _XTABLES_COMPAT_USER_H
|
||||
#define _XTABLES_COMPAT_USER_H 1
|
||||
|
||||
#pragma once
|
||||
/* 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 - 2010
|
||||
* written by Jan Engelhardt, 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
|
||||
@@ -21,588 +21,12 @@
|
||||
#include <net/ip.h>
|
||||
#include <net/ipv6.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"
|
||||
#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
|
||||
# define WITH_IPV6 1
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 22)
|
||||
static int xtnu_match_run(const struct sk_buff *skb,
|
||||
const struct net_device *in, const struct net_device *out,
|
||||
const struct xt_match *cm, const void *matchinfo, int offset,
|
||||
unsigned int protoff, int *hotdrop)
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
static bool xtnu_match_run(const struct sk_buff *skb,
|
||||
const struct net_device *in, const struct net_device *out,
|
||||
const struct xt_match *cm, const void *matchinfo, int offset,
|
||||
unsigned int protoff, bool *hotdrop)
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
{
|
||||
struct xtnu_match *nm = xtcompat_numatch(cm);
|
||||
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 = 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,
|
||||
const struct xt_match *cm, void *matchinfo, unsigned int matchinfosize,
|
||||
unsigned int hook_mask)
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 22)
|
||||
static int xtnu_match_check(const char *table, const void *entry,
|
||||
const struct xt_match *cm, void *matchinfo, unsigned int hook_mask)
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
static bool xtnu_match_check(const char *table, const void *entry,
|
||||
const struct xt_match *cm, void *matchinfo, unsigned int hook_mask)
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
{
|
||||
struct xtnu_match *nm = xtcompat_numatch(cm);
|
||||
struct xt_mtchk_param local_par = {
|
||||
.table = table,
|
||||
.entryinfo = entry,
|
||||
.match = cm,
|
||||
.matchinfo = matchinfo,
|
||||
.hook_mask = hook_mask,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
};
|
||||
|
||||
if (nm == NULL)
|
||||
return false;
|
||||
if (nm->checkentry == NULL)
|
||||
return true;
|
||||
return nm->checkentry(&local_par) == 0;
|
||||
}
|
||||
#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
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
|
||||
static void xtnu_match_destroy(const struct xt_match *cm, void *matchinfo,
|
||||
unsigned int matchinfosize)
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
static void xtnu_match_destroy(const struct xt_match *cm, void *matchinfo)
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
{
|
||||
struct xtnu_match *nm = xtcompat_numatch(cm);
|
||||
struct xt_mtdtor_param local_par = {
|
||||
.match = cm,
|
||||
.matchinfo = matchinfo,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
};
|
||||
|
||||
if (nm != NULL && nm->destroy != NULL)
|
||||
nm->destroy(&local_par);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 34)
|
||||
int xtnu_register_match(struct xtnu_match *nt)
|
||||
{
|
||||
struct xt_match *ct;
|
||||
char *tmp;
|
||||
int ret;
|
||||
|
||||
ct = kzalloc(sizeof(struct xt_match), GFP_KERNEL);
|
||||
if (ct == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
tmp = (char *)ct->name;
|
||||
memcpy(tmp, nt->name, sizeof(nt->name));
|
||||
tmp = (char *)(ct->name + sizeof(ct->name) - sizeof(void *));
|
||||
*(tmp-1) = '\0';
|
||||
memcpy(tmp, &nt, sizeof(void *));
|
||||
|
||||
ct->revision = nt->revision;
|
||||
ct->family = nt->family;
|
||||
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;
|
||||
|
||||
nt->__compat_match = ct;
|
||||
ret = xt_register_match(ct);
|
||||
if (ret != 0)
|
||||
kfree(ct);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xtnu_register_match);
|
||||
|
||||
int xtnu_register_matches(struct xtnu_match *nt, unsigned int num)
|
||||
{
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < num; ++i) {
|
||||
ret = xtnu_register_match(&nt[i]);
|
||||
if (ret < 0) {
|
||||
if (i > 0)
|
||||
xtnu_unregister_matches(nt, i);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xtnu_register_matches);
|
||||
|
||||
void xtnu_unregister_match(struct xtnu_match *nt)
|
||||
{
|
||||
xt_unregister_match(nt->__compat_match);
|
||||
kfree(nt->__compat_match);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xtnu_unregister_match);
|
||||
|
||||
void xtnu_unregister_matches(struct xtnu_match *nt, unsigned int num)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < num; ++i)
|
||||
xtnu_unregister_match(&nt[i]);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xtnu_unregister_matches);
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
|
||||
static unsigned int xtnu_target_run(struct sk_buff **pskb,
|
||||
const struct net_device *in, const struct net_device *out,
|
||||
unsigned int hooknum, const struct xt_target *ct, const void *targinfo,
|
||||
void *userdata)
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
|
||||
static unsigned int xtnu_target_run(struct sk_buff **pskb,
|
||||
const struct net_device *in, const struct net_device *out,
|
||||
unsigned int hooknum, const struct xt_target *ct, const void *targinfo)
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
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)
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
{
|
||||
struct xtnu_target *nt = xtcompat_nutarget(ct);
|
||||
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);
|
||||
#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,
|
||||
const struct xt_target *ct, void *targinfo,
|
||||
unsigned int targinfosize, unsigned int hook_mask)
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 22)
|
||||
static int xtnu_target_check(const char *table, const void *entry,
|
||||
const struct xt_target *ct, void *targinfo, unsigned int hook_mask)
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
static bool xtnu_target_check(const char *table, const void *entry,
|
||||
const struct xt_target *ct, void *targinfo, unsigned int hook_mask)
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
{
|
||||
struct xtnu_target *nt = xtcompat_nutarget(ct);
|
||||
struct xt_tgchk_param local_par = {
|
||||
.table = table,
|
||||
.entryinfo = entry,
|
||||
.target = ct,
|
||||
.targinfo = targinfo,
|
||||
.hook_mask = hook_mask,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
};
|
||||
|
||||
if (nt == NULL)
|
||||
return false;
|
||||
if (nt->checkentry == NULL)
|
||||
/* this is valid, just like if there was no function */
|
||||
return true;
|
||||
return nt->checkentry(&local_par) == 0;
|
||||
}
|
||||
#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
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
|
||||
static void xtnu_target_destroy(const struct xt_target *ct, void *targinfo,
|
||||
unsigned int targinfosize)
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
static void xtnu_target_destroy(const struct xt_target *ct, void *targinfo)
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
{
|
||||
struct xtnu_target *nt = xtcompat_nutarget(ct);
|
||||
struct xt_tgdtor_param local_par = {
|
||||
.target = ct,
|
||||
.targinfo = targinfo,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
};
|
||||
|
||||
if (nt != NULL && nt->destroy != NULL)
|
||||
nt->destroy(&local_par);
|
||||
}
|
||||
#endif
|
||||
|
||||
int xtnu_register_target(struct xtnu_target *nt)
|
||||
{
|
||||
struct xt_target *ct;
|
||||
char *tmp;
|
||||
int ret;
|
||||
|
||||
ct = kzalloc(sizeof(struct xt_target), GFP_KERNEL);
|
||||
if (ct == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
tmp = (char *)ct->name;
|
||||
memcpy(tmp, nt->name, sizeof(nt->name));
|
||||
tmp = (char *)(ct->name + sizeof(ct->name) - sizeof(void *));
|
||||
*(tmp-1) = '\0';
|
||||
memcpy(tmp, &nt, sizeof(void *));
|
||||
|
||||
ct->revision = nt->revision;
|
||||
ct->family = nt->family;
|
||||
ct->table = (char *)nt->table;
|
||||
ct->hooks = nt->hooks;
|
||||
ct->proto = nt->proto;
|
||||
ct->target = xtnu_target_run;
|
||||
#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;
|
||||
#endif
|
||||
ct->targetsize = nt->targetsize;
|
||||
ct->me = nt->me;
|
||||
|
||||
nt->__compat_target = ct;
|
||||
ret = xt_register_target(ct);
|
||||
if (ret != 0)
|
||||
kfree(ct);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xtnu_register_target);
|
||||
|
||||
int xtnu_register_targets(struct xtnu_target *nt, unsigned int num)
|
||||
{
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < num; ++i) {
|
||||
ret = xtnu_register_target(&nt[i]);
|
||||
if (ret < 0) {
|
||||
if (i > 0)
|
||||
xtnu_unregister_targets(nt, i);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xtnu_register_targets);
|
||||
|
||||
void xtnu_unregister_target(struct xtnu_target *nt)
|
||||
{
|
||||
xt_unregister_target(nt->__compat_target);
|
||||
kfree(nt->__compat_target);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xtnu_unregister_target);
|
||||
|
||||
void xtnu_unregister_targets(struct xtnu_target *nt, unsigned int num)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < num; ++i)
|
||||
xtnu_unregister_target(&nt[i]);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xtnu_unregister_targets);
|
||||
|
||||
struct xt_match *xtnu_request_find_match(unsigned int af, const char *name,
|
||||
uint8_t revision)
|
||||
{
|
||||
static const char *const xt_prefix[] = {
|
||||
[AF_UNSPEC] = "x",
|
||||
[AF_INET] = "ip",
|
||||
[AF_INET6] = "ip6",
|
||||
#ifdef AF_ARP
|
||||
[AF_ARP] = "arp",
|
||||
#elif defined(NF_ARP) && NF_ARP != AF_UNSPEC
|
||||
[NF_ARP] = "arp",
|
||||
#endif
|
||||
};
|
||||
struct xt_match *match;
|
||||
|
||||
match = try_then_request_module(xt_find_match(af, name, revision),
|
||||
"%st_%s", xt_prefix[af], name);
|
||||
if (IS_ERR(match) || match == NULL)
|
||||
return NULL;
|
||||
|
||||
return match;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xtnu_request_find_match);
|
||||
|
||||
int xtnu_ip_route_me_harder(struct sk_buff **pskb, unsigned int addr_type)
|
||||
{
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 17)
|
||||
/* Actually this one is valid up to 2.6.18.4, but changed in 2.6.18.5 */
|
||||
return ip_route_me_harder(pskb);
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
|
||||
return ip_route_me_harder(pskb, addr_type);
|
||||
#else
|
||||
return ip_route_me_harder(*pskb, addr_type);
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xtnu_ip_route_me_harder);
|
||||
|
||||
int xtnu_skb_make_writable(struct sk_buff **pskb, unsigned int len)
|
||||
{
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
|
||||
return skb_make_writable(pskb, len);
|
||||
#else
|
||||
return skb_make_writable(*pskb, len);
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xtnu_skb_make_writable);
|
||||
|
||||
#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 24)
|
||||
static int __xtnu_ip_local_out(struct sk_buff *skb)
|
||||
{
|
||||
struct iphdr *iph = ip_hdr(skb);
|
||||
|
||||
iph->tot_len = htons(skb->len);
|
||||
ip_send_check(iph);
|
||||
return nf_hook(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
|
||||
skb->dst->dev, dst_output);
|
||||
}
|
||||
|
||||
int xtnu_ip_local_out(struct sk_buff *skb)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = __xtnu_ip_local_out(skb);
|
||||
if (likely(err == 1))
|
||||
err = dst_output(skb);
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xtnu_ip_local_out);
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
|
||||
static int __xtnu_ip_local_out(struct sk_buff **pskb)
|
||||
{
|
||||
struct iphdr *iph = ip_hdr(*pskb);
|
||||
|
||||
iph->tot_len = htons((*pskb)->len);
|
||||
ip_send_check(iph);
|
||||
return nf_hook(PF_INET, NF_IP_LOCAL_OUT, pskb, NULL,
|
||||
(*pskb)->dst->dev, dst_output);
|
||||
}
|
||||
|
||||
int xtnu_ip_local_out(struct sk_buff *skb)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = __xtnu_ip_local_out(&skb);
|
||||
if (likely(err == 1))
|
||||
err = dst_output(skb);
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xtnu_ip_local_out);
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 24)
|
||||
int xtnu_ip_route_output_key(void *net, struct rtable **rp, struct flowi *flp)
|
||||
{
|
||||
return ip_route_output_flow(rp, flp, NULL, 0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xtnu_ip_route_output_key);
|
||||
|
||||
void xtnu_proto_csum_replace4(__sum16 *sum, struct sk_buff *skb,
|
||||
__be32 from, __be32 to, bool pseudohdr)
|
||||
{
|
||||
__be32 diff[] = {~from, to};
|
||||
const void *dv = diff; /* kludge for < v2.6.19-555-g72685fc */
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
|
||||
if (skb->ip_summed != CHECKSUM_PARTIAL) {
|
||||
*sum = csum_fold(csum_partial(dv, sizeof(diff),
|
||||
~csum_unfold(*sum)));
|
||||
if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr)
|
||||
skb->csum = ~csum_partial(dv, sizeof(diff),
|
||||
~skb->csum);
|
||||
} else if (pseudohdr) {
|
||||
*sum = ~csum_fold(csum_partial(dv, sizeof(diff),
|
||||
csum_unfold(*sum)));
|
||||
}
|
||||
#else
|
||||
*sum = csum_fold(csum_partial(dv, sizeof(diff),
|
||||
~csum_unfold(*sum)));
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xtnu_proto_csum_replace4);
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 19)
|
||||
int xtnu_neigh_hh_output(struct hh_cache *hh, struct sk_buff *skb)
|
||||
{
|
||||
unsigned int hh_alen;
|
||||
|
||||
read_lock_bh(&hh->hh_lock);
|
||||
hh_alen = HH_DATA_ALIGN(hh->hh_len);
|
||||
memcpy(skb->data - hh_alen, hh->hh_data, hh_alen);
|
||||
read_unlock_bh(&hh->hh_lock);
|
||||
skb_push(skb, hh->hh_len);
|
||||
return hh->hh_output(skb);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xtnu_neigh_hh_output);
|
||||
|
||||
static inline __wsum xtnu_csum_unfold(__sum16 n)
|
||||
{
|
||||
return (__force __wsum)n;
|
||||
}
|
||||
|
||||
void xtnu_csum_replace4(__sum16 *sum, __be32 from, __be32 to)
|
||||
{
|
||||
__be32 diff[] = {~from, to};
|
||||
*sum = csum_fold(csum_partial((char *)diff, sizeof(diff),
|
||||
~xtnu_csum_unfold(*sum)));
|
||||
}
|
||||
|
||||
void xtnu_csum_replace2(__sum16 *sum, __be16 from, __be16 to)
|
||||
{
|
||||
xtnu_csum_replace4(sum, (__force __be32)from, (__force __be32)to);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xtnu_csum_replace2);
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 17)
|
||||
int xtnu_skb_linearize(struct sk_buff *skb)
|
||||
{
|
||||
return skb_linearize(skb, GFP_ATOMIC);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xtnu_skb_linearize);
|
||||
#endif
|
||||
|
||||
void *HX_memmem(const void *space, size_t spacesize,
|
||||
const void *point, size_t pointsize)
|
||||
{
|
||||
@@ -617,22 +41,4 @@ void *HX_memmem(const void *space, size_t spacesize,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(HX_memmem);
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0) && defined(WITH_IPV6)
|
||||
int xtnu_ipv6_skip_exthdr(const struct sk_buff *skb, int start,
|
||||
uint8_t *nexthdrp, __be16 *fragoffp)
|
||||
{
|
||||
return ipv6_skip_exthdr(skb, start, nexthdrp);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xtnu_ipv6_skip_exthdr);
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0) && defined(WITH_IPV6)
|
||||
int xtnu_ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
|
||||
int target, unsigned short *fragoff, int *fragflg)
|
||||
{
|
||||
return ipv6_find_hdr(skb, offset, target, fragoff);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xtnu_ipv6_find_hdr);
|
||||
#endif
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@@ -1,15 +1,12 @@
|
||||
#ifndef _XTABLES_COMPAT_H
|
||||
#define _XTABLES_COMPAT_H 1
|
||||
|
||||
#pragma once
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/version.h>
|
||||
#include "compat_skbuff.h"
|
||||
#include "compat_xtnu.h"
|
||||
|
||||
#define DEBUGP Use__pr_debug__instead
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 17)
|
||||
# warning Kernels below 2.6.17 not supported.
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
|
||||
# warning Kernels below 4.15 not supported.
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
|
||||
@@ -17,121 +14,35 @@
|
||||
# warning You have CONFIG_NF_CONNTRACK enabled, but CONFIG_NF_CONNTRACK_MARK is not (please enable).
|
||||
# endif
|
||||
# include <net/netfilter/nf_conntrack.h>
|
||||
#elif defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE)
|
||||
# if !defined(CONFIG_IP_NF_CONNTRACK_MARK)
|
||||
# warning You have CONFIG_IP_NF_CONNTRACK enabled, but CONFIG_IP_NF_CONNTRACK_MARK is not (please enable).
|
||||
# endif
|
||||
# include <linux/netfilter_ipv4/ip_conntrack.h>
|
||||
# define nf_conn ip_conntrack
|
||||
# define nf_ct_get ip_conntrack_get
|
||||
# define nf_conntrack_untracked ip_conntrack_untracked
|
||||
#else
|
||||
# warning You need either CONFIG_NF_CONNTRACK or CONFIG_IP_NF_CONNTRACK.
|
||||
# warning You need CONFIG_NF_CONNTRACK.
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 17)
|
||||
# define skb_init_secmark(skb)
|
||||
# define skb_linearize xtnu_skb_linearize
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 19)
|
||||
# define neigh_hh_output xtnu_neigh_hh_output
|
||||
# define IPPROTO_UDPLITE 136
|
||||
# define CSUM_MANGLED_0 ((__force __sum16)0xffff)
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 24)
|
||||
# define NF_INET_PRE_ROUTING NF_IP_PRE_ROUTING
|
||||
# define NF_INET_LOCAL_IN NF_IP_LOCAL_IN
|
||||
# define NF_INET_FORWARD NF_IP_FORWARD
|
||||
# define NF_INET_LOCAL_OUT NF_IP_LOCAL_OUT
|
||||
# define NF_INET_POST_ROUTING NF_IP_POST_ROUTING
|
||||
# define ip_local_out xtnu_ip_local_out
|
||||
# define ip_route_output_key xtnu_ip_route_output_key
|
||||
# include "compat_nfinetaddr.h"
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
|
||||
# define init_net xtnu_ip_route_output_key /* yes */
|
||||
# define init_net__loopback_dev (&loopback_dev)
|
||||
# define init_net__proc_net proc_net
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0) || \
|
||||
LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 9) && LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0) || \
|
||||
LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 78) && LINUX_VERSION_CODE < KERNEL_VERSION(5, 5, 0) || \
|
||||
LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 158) && LINUX_VERSION_CODE < KERNEL_VERSION(4, 20, 0)
|
||||
#else
|
||||
# define init_net__loopback_dev init_net.loopback_dev
|
||||
# define init_net__proc_net init_net.proc_net
|
||||
# define ip_route_me_harder(xnet, xsk, xskb, xaddrtype) ip_route_me_harder((xnet), (xskb), (xaddrtype))
|
||||
# define ip6_route_me_harder(xnet, xsk, xskb) ip6_route_me_harder((xnet), (xskb))
|
||||
#endif
|
||||
|
||||
#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
|
||||
# define xt_register_matches xtnu_register_matches
|
||||
# define xt_unregister_matches xtnu_unregister_matches
|
||||
static inline struct net *par_net(const struct xt_action_param *par)
|
||||
{
|
||||
return par->state->net;
|
||||
}
|
||||
|
||||
#ifndef NF_CT_ASSERT
|
||||
# define NF_CT_ASSERT(x) WARN_ON(!(x))
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 19)
|
||||
# define csum_replace2 xtnu_csum_replace2
|
||||
# define csum_replace4 xtnu_csum_replace4
|
||||
# define inet_proto_csum_replace4 xtnu_proto_csum_replace4
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 24)
|
||||
# define csum_replace2 nf_csum_replace2
|
||||
# define csum_replace4 nf_csum_replace4
|
||||
# define inet_proto_csum_replace4 xtnu_proto_csum_replace4
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 6, 0)
|
||||
# define proc_ops file_operations
|
||||
# define proc_open open
|
||||
# define proc_read read
|
||||
# define proc_write write
|
||||
# define proc_lseek llseek
|
||||
# define proc_release release
|
||||
#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
|
||||
# define ipv6_skip_exthdr xtnu_ipv6_skip_exthdr
|
||||
#endif
|
||||
|
||||
#if !defined(NIP6) && !defined(NIP6_FMT)
|
||||
# define NIP6(addr) \
|
||||
ntohs((addr).s6_addr16[0]), \
|
||||
ntohs((addr).s6_addr16[1]), \
|
||||
ntohs((addr).s6_addr16[2]), \
|
||||
ntohs((addr).s6_addr16[3]), \
|
||||
ntohs((addr).s6_addr16[4]), \
|
||||
ntohs((addr).s6_addr16[5]), \
|
||||
ntohs((addr).s6_addr16[6]), \
|
||||
ntohs((addr).s6_addr16[7])
|
||||
# define NIP6_FMT "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x"
|
||||
#endif
|
||||
#if !defined(NIPQUAD) && !defined(NIPQUAD_FMT)
|
||||
# define NIPQUAD(addr) \
|
||||
((const unsigned char *)&addr)[0], \
|
||||
((const unsigned char *)&addr)[1], \
|
||||
((const unsigned char *)&addr)[2], \
|
||||
((const unsigned char *)&addr)[3]
|
||||
# define NIPQUAD_FMT "%u.%u.%u.%u"
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
|
||||
# define ipv6_find_hdr xtnu_ipv6_find_hdr
|
||||
#endif
|
||||
|
||||
#define ip_route_me_harder xtnu_ip_route_me_harder
|
||||
#define skb_make_writable xtnu_skb_make_writable
|
||||
#define xt_target xtnu_target
|
||||
#define xt_register_target xtnu_register_target
|
||||
#define xt_unregister_target xtnu_unregister_target
|
||||
#define xt_register_targets xtnu_register_targets
|
||||
#define xt_unregister_targets xtnu_unregister_targets
|
||||
|
||||
#define xt_request_find_match xtnu_request_find_match
|
||||
|
||||
#endif /* _XTABLES_COMPAT_H */
|
||||
extern void *HX_memmem(const void *, size_t, const void *, size_t);
|
||||
|
@@ -1,172 +0,0 @@
|
||||
#ifndef _COMPAT_XTNU_H
|
||||
#define _COMPAT_XTNU_H 1
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
|
||||
typedef _Bool bool;
|
||||
enum { false = 0, true = 1, };
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 19)
|
||||
typedef __u16 __bitwise __sum16;
|
||||
typedef __u32 __bitwise __wsum;
|
||||
#endif
|
||||
|
||||
struct flowi;
|
||||
struct hh_cache;
|
||||
struct module;
|
||||
struct net_device;
|
||||
struct rtable;
|
||||
struct sk_buff;
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
enum {
|
||||
NFPROTO_UNSPEC = 0,
|
||||
NFPROTO_IPV4 = 2,
|
||||
NFPROTO_ARP = 3,
|
||||
NFPROTO_BRIDGE = 7,
|
||||
NFPROTO_IPV6 = 10,
|
||||
NFPROTO_DECNET = 12,
|
||||
NFPROTO_NUMPROTO,
|
||||
};
|
||||
|
||||
struct xt_mtchk_param {
|
||||
const char *table;
|
||||
const void *entryinfo;
|
||||
const struct xt_match *match;
|
||||
void *matchinfo;
|
||||
unsigned int hook_mask;
|
||||
u_int8_t family;
|
||||
};
|
||||
|
||||
struct xt_mtdtor_param {
|
||||
const struct xt_match *match;
|
||||
void *matchinfo;
|
||||
u_int8_t family;
|
||||
};
|
||||
|
||||
struct xt_target_param {
|
||||
const struct net_device *in, *out;
|
||||
unsigned int hooknum;
|
||||
const struct xt_target *target;
|
||||
const void *targinfo;
|
||||
u_int8_t family;
|
||||
};
|
||||
|
||||
struct xt_tgchk_param {
|
||||
const char *table;
|
||||
const void *entryinfo;
|
||||
const struct xt_target *target;
|
||||
void *targinfo;
|
||||
unsigned int hook_mask;
|
||||
u_int8_t family;
|
||||
};
|
||||
|
||||
struct xt_tgdtor_param {
|
||||
const struct xt_target *target;
|
||||
void *targinfo;
|
||||
u_int8_t family;
|
||||
};
|
||||
#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 {
|
||||
/*
|
||||
* 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;
|
||||
|
||||
void *__compat_match;
|
||||
};
|
||||
|
||||
struct xtnu_target {
|
||||
char name[sizeof(((struct xt_target *)NULL)->name) - 1 - sizeof(void *)];
|
||||
uint8_t revision;
|
||||
unsigned int (*target)(struct sk_buff **,
|
||||
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;
|
||||
|
||||
void *__compat_target;
|
||||
};
|
||||
|
||||
static inline struct xtnu_match *xtcompat_numatch(const struct xt_match *m)
|
||||
{
|
||||
void *q;
|
||||
memcpy(&q, m->name + sizeof(m->name) - sizeof(void *), sizeof(void *));
|
||||
return q;
|
||||
}
|
||||
|
||||
static inline struct xtnu_target *xtcompat_nutarget(const struct xt_target *t)
|
||||
{
|
||||
void *q;
|
||||
memcpy(&q, t->name + sizeof(t->name) - sizeof(void *), sizeof(void *));
|
||||
return q;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 19)
|
||||
static inline __wsum csum_unfold(__sum16 n)
|
||||
{
|
||||
return (__force __wsum)n;
|
||||
}
|
||||
#endif
|
||||
|
||||
extern int xtnu_ip_local_out(struct sk_buff *);
|
||||
extern int xtnu_ip_route_me_harder(struct sk_buff **, unsigned int);
|
||||
extern int xtnu_skb_make_writable(struct sk_buff **, unsigned int);
|
||||
extern int xtnu_register_match(struct xtnu_match *);
|
||||
extern int xtnu_ip_route_output_key(void *, struct rtable **, struct flowi *);
|
||||
extern void xtnu_unregister_match(struct xtnu_match *);
|
||||
extern int xtnu_register_matches(struct xtnu_match *, unsigned int);
|
||||
extern void xtnu_unregister_matches(struct xtnu_match *, unsigned int);
|
||||
extern int xtnu_register_target(struct xtnu_target *);
|
||||
extern void xtnu_unregister_target(struct xtnu_target *);
|
||||
extern int xtnu_register_targets(struct xtnu_target *, unsigned int);
|
||||
extern void xtnu_unregister_targets(struct xtnu_target *, unsigned int);
|
||||
extern struct xt_match *xtnu_request_find_match(unsigned int,
|
||||
const char *, uint8_t);
|
||||
extern int xtnu_neigh_hh_output(struct hh_cache *, struct sk_buff *);
|
||||
extern void xtnu_csum_replace2(__u16 __bitwise *, __be16, __be16);
|
||||
extern void xtnu_csum_replace4(__u16 __bitwise *, __be32, __be32);
|
||||
extern void xtnu_proto_csum_replace4(__u16 __bitwise *, struct sk_buff *,
|
||||
__be32, __be32, bool);
|
||||
extern int xtnu_skb_linearize(struct sk_buff *);
|
||||
extern int xtnu_ipv6_skip_exthdr(const struct sk_buff *, int,
|
||||
uint8_t *, __be16 *);
|
||||
extern int xtnu_ipv6_find_hdr(const struct sk_buff *, unsigned int *,
|
||||
int, unsigned short *, int *);
|
||||
|
||||
extern void *HX_memmem(const void *, size_t, const void *, size_t);
|
||||
|
||||
#endif /* _COMPAT_XTNU_H */
|
@@ -1,107 +0,0 @@
|
||||
/*
|
||||
* rawpost table for ip6_tables
|
||||
* written by Jan Engelhardt <jengelh [at] medozas de>, 2008 - 2009
|
||||
* placed in the Public Domain
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/netfilter_ipv6/ip6_tables.h>
|
||||
#include <net/ip.h>
|
||||
#include "compat_xtables.h"
|
||||
#include "compat_rawpost.h"
|
||||
|
||||
enum {
|
||||
RAWPOST_VALID_HOOKS = 1 << NF_INET_POST_ROUTING,
|
||||
};
|
||||
|
||||
static struct {
|
||||
struct ip6t_replace repl;
|
||||
struct ip6t_standard entries[1];
|
||||
struct ip6t_error term;
|
||||
} rawpost6_initial __initdata = {
|
||||
.repl = {
|
||||
.name = "rawpost",
|
||||
.valid_hooks = RAWPOST_VALID_HOOKS,
|
||||
.num_entries = 2,
|
||||
.size = sizeof(struct ip6t_standard) +
|
||||
sizeof(struct ip6t_error),
|
||||
.hook_entry = {
|
||||
[NF_INET_POST_ROUTING] = 0,
|
||||
},
|
||||
.underflow = {
|
||||
[NF_INET_POST_ROUTING] = 0,
|
||||
},
|
||||
},
|
||||
.entries = {
|
||||
IP6T_STANDARD_INIT(NF_ACCEPT), /* POST_ROUTING */
|
||||
},
|
||||
.term = IP6T_ERROR_INIT, /* ERROR */
|
||||
};
|
||||
|
||||
static struct xt_table *rawpost6_ptable;
|
||||
|
||||
static struct xt_table rawpost6_itable = {
|
||||
.name = "rawpost",
|
||||
.af = NFPROTO_IPV6,
|
||||
.valid_hooks = RAWPOST_VALID_HOOKS,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static unsigned int rawpost6_hook_fn(unsigned int hook, sk_buff_t *skb,
|
||||
const struct net_device *in, const struct net_device *out,
|
||||
int (*okfn)(struct sk_buff *))
|
||||
{
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
|
||||
return ip6t_do_table(skb, hook, in, out, rawpost6_ptable);
|
||||
#else
|
||||
return ip6t_do_table(skb, hook, in, out, rawpost6_ptable, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
static struct nf_hook_ops rawpost6_hook_ops __read_mostly = {
|
||||
.hook = rawpost6_hook_fn,
|
||||
.pf = NFPROTO_IPV6,
|
||||
.hooknum = NF_INET_POST_ROUTING,
|
||||
.priority = NF_IP6_PRI_LAST,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
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);
|
||||
if (IS_ERR(rawpost6_ptable))
|
||||
return PTR_ERR(rawpost6_ptable);
|
||||
#else
|
||||
ret = ip6t_register_table(&rawpost6_itable, &rawpost6_initial.repl);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
rawpost6_ptable = &rawpost6_itable;
|
||||
#endif
|
||||
|
||||
ret = nf_register_hook(&rawpost6_hook_ops);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
return ret;
|
||||
|
||||
out:
|
||||
ip6t_unregister_table(rawpost6_ptable);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit rawpost6_table_exit(void)
|
||||
{
|
||||
nf_unregister_hook(&rawpost6_hook_ops);
|
||||
ip6t_unregister_table(rawpost6_ptable);
|
||||
}
|
||||
|
||||
module_init(rawpost6_table_init);
|
||||
module_exit(rawpost6_table_exit);
|
||||
MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>");
|
||||
MODULE_LICENSE("GPL");
|
@@ -1,109 +0,0 @@
|
||||
/*
|
||||
* rawpost table for ip_tables
|
||||
* written by Jan Engelhardt <jengelh [at] medozas de>, 2008 - 2009
|
||||
* placed in the Public Domain
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
#include <linux/version.h>
|
||||
#include <net/ip.h>
|
||||
#include "compat_xtables.h"
|
||||
#include "compat_rawpost.h"
|
||||
|
||||
enum {
|
||||
RAWPOST_VALID_HOOKS = 1 << NF_INET_POST_ROUTING,
|
||||
};
|
||||
|
||||
static struct {
|
||||
struct ipt_replace repl;
|
||||
struct ipt_standard entries[1];
|
||||
struct ipt_error term;
|
||||
} rawpost4_initial __initdata = {
|
||||
.repl = {
|
||||
.name = "rawpost",
|
||||
.valid_hooks = RAWPOST_VALID_HOOKS,
|
||||
.num_entries = 2,
|
||||
.size = sizeof(struct ipt_standard) +
|
||||
sizeof(struct ipt_error),
|
||||
.hook_entry = {
|
||||
[NF_INET_POST_ROUTING] = 0,
|
||||
},
|
||||
.underflow = {
|
||||
[NF_INET_POST_ROUTING] = 0,
|
||||
},
|
||||
},
|
||||
.entries = {
|
||||
IPT_STANDARD_INIT(NF_ACCEPT), /* POST_ROUTING */
|
||||
},
|
||||
.term = IPT_ERROR_INIT, /* ERROR */
|
||||
};
|
||||
|
||||
static struct xt_table *rawpost4_ptable;
|
||||
|
||||
static struct xt_table rawpost4_itable = {
|
||||
.name = "rawpost",
|
||||
.af = NFPROTO_IPV4,
|
||||
.valid_hooks = RAWPOST_VALID_HOOKS,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static unsigned int rawpost4_hook_fn(unsigned int hook, sk_buff_t *skb,
|
||||
const struct net_device *in, const struct net_device *out,
|
||||
int (*okfn)(struct sk_buff *))
|
||||
{
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
|
||||
return ipt_do_table(skb, hook, in, out, rawpost4_ptable);
|
||||
#else
|
||||
return ipt_do_table(skb, hook, in, out, rawpost4_ptable, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
static struct nf_hook_ops rawpost4_hook_ops __read_mostly = {
|
||||
.hook = rawpost4_hook_fn,
|
||||
.pf = NFPROTO_IPV4,
|
||||
.hooknum = NF_INET_POST_ROUTING,
|
||||
.priority = NF_IP_PRI_LAST,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init rawpost4_table_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 29)
|
||||
rwlock_init(&rawpost4_itable.lock);
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
|
||||
rawpost4_ptable = ipt_register_table(&init_net, &rawpost4_itable,
|
||||
&rawpost4_initial.repl);
|
||||
if (IS_ERR(rawpost4_ptable))
|
||||
return PTR_ERR(rawpost4_ptable);
|
||||
#else
|
||||
ret = ipt_register_table(&rawpost4_itable, &rawpost4_initial.repl);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
rawpost4_ptable = &rawpost4_itable;
|
||||
#endif
|
||||
|
||||
ret = nf_register_hook(&rawpost4_hook_ops);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
return ret;
|
||||
|
||||
out:
|
||||
ipt_unregister_table(rawpost4_ptable);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit rawpost4_table_exit(void)
|
||||
{
|
||||
nf_unregister_hook(&rawpost4_hook_ops);
|
||||
ipt_unregister_table(rawpost4_ptable);
|
||||
}
|
||||
|
||||
module_init(rawpost4_table_init);
|
||||
module_exit(rawpost4_table_exit);
|
||||
MODULE_DESCRIPTION("Xtables: rawpost table for use with RAWNAT");
|
||||
MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>");
|
||||
MODULE_LICENSE("GPL");
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* "CHAOS" target extension for iptables
|
||||
* Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2006 - 2008
|
||||
* Copyright © Jan Engelhardt, 2006 - 2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License; either
|
||||
@@ -64,21 +64,6 @@ static void chaos_tg_check(unsigned int flags)
|
||||
"may be specified");
|
||||
}
|
||||
|
||||
static void chaos_tg_print(const void *ip,
|
||||
const struct xt_entry_target *target, int numeric)
|
||||
{
|
||||
const struct xt_chaos_tginfo *info = (const void *)target->data;
|
||||
|
||||
switch (info->variant) {
|
||||
case XTCHAOS_DELUDE:
|
||||
printf(" DELUDE ");
|
||||
break;
|
||||
case XTCHAOS_TARPIT:
|
||||
printf(" TARPIT ");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void chaos_tg_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct xt_chaos_tginfo *info = (const void *)target->data;
|
||||
@@ -93,6 +78,13 @@ static void chaos_tg_save(const void *ip, const struct xt_entry_target *target)
|
||||
}
|
||||
}
|
||||
|
||||
static void chaos_tg_print(const void *ip,
|
||||
const struct xt_entry_target *target, int numeric)
|
||||
{
|
||||
printf(" -j CHAOS");
|
||||
chaos_tg_save(ip, target);
|
||||
}
|
||||
|
||||
static struct xtables_target chaos_tg_reg = {
|
||||
.version = XTABLES_VERSION,
|
||||
.name = "CHAOS",
|
||||
|
@@ -1,3 +1,4 @@
|
||||
.PP
|
||||
Causes confusion on the other end by doing odd things with incoming packets.
|
||||
CHAOS will randomly reply (or not) with one of its configurable subtargets:
|
||||
.TP
|
||||
@@ -17,5 +18,5 @@ connections than they can.
|
||||
The randomness factor of not replying vs. replying can be set during load-time
|
||||
of the xt_CHAOS module or during runtime in /sys/modules/xt_CHAOS/parameters.
|
||||
.PP
|
||||
See http://jengelh.medozas.de/projects/chaostables/ for more information
|
||||
See http://inai.de/projects/chaostables/ for more information
|
||||
about CHAOS, DELUDE and lscan.
|
||||
|
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
* (C) 2002 by Harald Welte <laforge@gnumonks.org>
|
||||
* (C) 2010 by Red Hat, Inc
|
||||
* Author: Michael S. Tsirkin <mst@redhat.com>
|
||||
*
|
||||
* This program is distributed under the terms of GNU GPL v2, 1991
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include <xtables.h>
|
||||
#include "xt_CHECKSUM.h"
|
||||
#include "compat_user.h"
|
||||
|
||||
static void CHECKSUM_help(void)
|
||||
{
|
||||
printf(
|
||||
"CHECKSUM target options\n"
|
||||
" --checksum-fill Fill in packet checksum.\n");
|
||||
}
|
||||
|
||||
static const struct option CHECKSUM_opts[] = {
|
||||
{ "checksum-fill", 0, NULL, 'F' },
|
||||
{ .name = NULL }
|
||||
};
|
||||
|
||||
static int CHECKSUM_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
const void *entry, struct xt_entry_target **target)
|
||||
{
|
||||
struct xt_CHECKSUM_info *einfo
|
||||
= (struct xt_CHECKSUM_info *)(*target)->data;
|
||||
|
||||
switch (c) {
|
||||
case 'F':
|
||||
xtables_param_act(XTF_ONLY_ONCE, "CHECKSUM", "--checksum-fill",
|
||||
*flags & XT_CHECKSUM_OP_FILL);
|
||||
einfo->operation = XT_CHECKSUM_OP_FILL;
|
||||
*flags |= XT_CHECKSUM_OP_FILL;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void CHECKSUM_check(unsigned int flags)
|
||||
{
|
||||
if (!flags)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"CHECKSUM target: Parameter --checksum-fill is required");
|
||||
}
|
||||
|
||||
static void CHECKSUM_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct xt_CHECKSUM_info *einfo =
|
||||
(const struct xt_CHECKSUM_info *)target->data;
|
||||
|
||||
printf("CHECKSUM ");
|
||||
|
||||
if (einfo->operation & XT_CHECKSUM_OP_FILL)
|
||||
printf(" fill ");
|
||||
}
|
||||
|
||||
static void CHECKSUM_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct xt_CHECKSUM_info *einfo =
|
||||
(const struct xt_CHECKSUM_info *)target->data;
|
||||
|
||||
if (einfo->operation & XT_CHECKSUM_OP_FILL)
|
||||
printf(" --checksum-fill ");
|
||||
}
|
||||
|
||||
static struct xtables_target checksum_tg_reg = {
|
||||
.name = "CHECKSUM",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.size = XT_ALIGN(sizeof(struct xt_CHECKSUM_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct xt_CHECKSUM_info)),
|
||||
.help = CHECKSUM_help,
|
||||
.parse = CHECKSUM_parse,
|
||||
.final_check = CHECKSUM_check,
|
||||
.print = CHECKSUM_print,
|
||||
.save = CHECKSUM_save,
|
||||
.extra_opts = CHECKSUM_opts,
|
||||
};
|
||||
|
||||
static __attribute__((constructor)) void _init(void)
|
||||
{
|
||||
xtables_register_target(&checksum_tg_reg);
|
||||
}
|
@@ -1,8 +0,0 @@
|
||||
This target allows to selectively work around broken/old applications.
|
||||
It can only be used in the mangle table.
|
||||
.TP
|
||||
\fB\-\-checksum\-fill\fP
|
||||
Compute and fill in the checksum in a packet that lacks a checksum.
|
||||
This is particularly useful, if you need to work around old applications
|
||||
such as dhcp clients, that do not work well with checksum offloads,
|
||||
but don't want to disable checksum offload in your device.
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* "DELUDE" target extension for iptables
|
||||
* Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2006 - 2008
|
||||
* Copyright © Jan Engelhardt, 2006 - 2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License; either
|
||||
|
@@ -1,3 +1,4 @@
|
||||
.PP
|
||||
The DELUDE target will reply to a SYN packet with SYN-ACK, and to all other
|
||||
packets with an RST. This will terminate the connection much like REJECT, but
|
||||
network scanners doing TCP half-open discovery can be spoofed to make them
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* "DHCPMAC" target extension for iptables
|
||||
* Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2008
|
||||
* Copyright © Jan Engelhardt, 2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License; either
|
||||
@@ -61,15 +61,6 @@ static void dhcpmac_tg_check(unsigned int flags)
|
||||
"--set-mac parameter required");
|
||||
}
|
||||
|
||||
static void dhcpmac_tg_print(const void *ip,
|
||||
const struct xt_entry_target *target, int numeric)
|
||||
{
|
||||
const struct dhcpmac_info *info = (void *)target->data;
|
||||
|
||||
printf(" DHCPMAC %s" DH_MAC_FMT "/%u ",
|
||||
info->invert ? "!" : "", DH_MAC_HEX(info->addr), info->mask);
|
||||
}
|
||||
|
||||
static void dhcpmac_tg_save(const void *ip,
|
||||
const struct xt_entry_target *target)
|
||||
{
|
||||
@@ -81,6 +72,13 @@ static void dhcpmac_tg_save(const void *ip,
|
||||
DH_MAC_HEX(info->addr), info->mask);
|
||||
}
|
||||
|
||||
static void dhcpmac_tg_print(const void *ip,
|
||||
const struct xt_entry_target *target, int numeric)
|
||||
{
|
||||
printf(" -j DHCPMAC");
|
||||
dhcpmac_tg_save(ip, target);
|
||||
}
|
||||
|
||||
static struct xtables_target dhcpmac_tg_reg = {
|
||||
.version = XTABLES_VERSION,
|
||||
.name = "DHCPMAC",
|
||||
|
@@ -1,3 +1,4 @@
|
||||
.PP
|
||||
In conjunction with ebtables, DHCPMAC can be used to completely change all MAC
|
||||
addresses from and to a VMware-based virtual machine. This is needed because
|
||||
VMware does not allow to set a non-VMware MAC address before an operating
|
||||
|
@@ -69,19 +69,8 @@ static int netmask2bits(u_int32_t netmask)
|
||||
return bits;
|
||||
}
|
||||
|
||||
static void DNETMAP_init(struct xt_entry_target *t)
|
||||
{
|
||||
struct xt_DNETMAP_tginfo *tginfo = (void *)&t->data;
|
||||
struct nf_nat_ipv4_multi_range_compat *mr = &tginfo->prefix;
|
||||
|
||||
/* Actually, it's 0, but it's ignored at the moment. */
|
||||
mr->rangesize = 1;
|
||||
tginfo->ttl = 0;
|
||||
tginfo->flags = 0;
|
||||
}
|
||||
|
||||
/* Parses network address */
|
||||
static void parse_prefix(char *arg, struct nf_nat_ipv4_range *range)
|
||||
static void parse_prefix(char *arg, struct nf_nat_range *range)
|
||||
{
|
||||
char *slash;
|
||||
const struct in_addr *ip;
|
||||
@@ -97,7 +86,7 @@ static void parse_prefix(char *arg, struct nf_nat_ipv4_range *range)
|
||||
if (ip == NULL)
|
||||
xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
|
||||
arg);
|
||||
range->min_ip = ip->s_addr;
|
||||
range->min_addr.in = *ip;
|
||||
if (slash) {
|
||||
if (strchr(slash + 1, '.')) {
|
||||
ip = xtables_numeric_to_ipmask(slash + 1);
|
||||
@@ -123,20 +112,20 @@ static void parse_prefix(char *arg, struct nf_nat_ipv4_range *range)
|
||||
} else
|
||||
netmask = ~0;
|
||||
|
||||
if (range->min_ip & ~netmask) {
|
||||
if (range->min_addr.ip & ~netmask) {
|
||||
if (slash)
|
||||
*slash = '/';
|
||||
xtables_error(PARAMETER_PROBLEM, "Bad network address \"%s\"\n",
|
||||
arg);
|
||||
}
|
||||
range->max_ip = range->min_ip | ~netmask;
|
||||
range->max_addr.ip = range->min_addr.ip | ~netmask;
|
||||
}
|
||||
|
||||
static int DNETMAP_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
const void *entry, struct xt_entry_target **target)
|
||||
{
|
||||
struct xt_DNETMAP_tginfo *tginfo = (void *)(*target)->data;
|
||||
struct nf_nat_ipv4_multi_range_compat *mr = &tginfo->prefix;
|
||||
struct nf_nat_range *mr = &tginfo->prefix;
|
||||
char *end;
|
||||
|
||||
switch (c) {
|
||||
@@ -147,7 +136,7 @@ static int DNETMAP_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
invert);
|
||||
|
||||
/* TO-DO use xtables_ipparse_any instead? */
|
||||
parse_prefix(optarg, &mr->range[0]);
|
||||
parse_prefix(optarg, mr);
|
||||
*flags |= XT_DNETMAP_PREFIX;
|
||||
tginfo->flags |= XT_DNETMAP_PREFIX;
|
||||
return 1;
|
||||
@@ -192,14 +181,13 @@ static void DNETMAP_print_addr(const void *ip,
|
||||
int numeric)
|
||||
{
|
||||
struct xt_DNETMAP_tginfo *tginfo = (void *)&target->data;
|
||||
const struct nf_nat_ipv4_multi_range_compat *mr = &tginfo->prefix;
|
||||
const struct nf_nat_ipv4_range *r = &mr->range[0];
|
||||
const struct nf_nat_range *r = &tginfo->prefix;
|
||||
struct in_addr a;
|
||||
int bits;
|
||||
|
||||
a.s_addr = r->min_ip;
|
||||
a = r->min_addr.in;
|
||||
printf("%s", xtables_ipaddr_to_numeric(&a));
|
||||
a.s_addr = ~(r->min_ip ^ r->max_ip);
|
||||
a.s_addr = ~(r->min_addr.ip ^ r->max_addr.ip);
|
||||
bits = netmask2bits(a.s_addr);
|
||||
if (bits < 0)
|
||||
printf("/%s", xtables_ipaddr_to_numeric(&a));
|
||||
@@ -207,33 +195,6 @@ static void DNETMAP_print_addr(const void *ip,
|
||||
printf("/%d", bits);
|
||||
}
|
||||
|
||||
static void DNETMAP_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
struct xt_DNETMAP_tginfo *tginfo = (void *)&target->data;
|
||||
const __u8 *flags = &tginfo->flags;
|
||||
|
||||
printf(" prefix ");
|
||||
if (*flags & XT_DNETMAP_PREFIX)
|
||||
DNETMAP_print_addr(ip, target, numeric);
|
||||
else
|
||||
printf("any");
|
||||
|
||||
if (*flags & XT_DNETMAP_REUSE)
|
||||
printf(" reuse");
|
||||
|
||||
if (*flags & XT_DNETMAP_STATIC)
|
||||
printf(" static");
|
||||
|
||||
if (*flags & XT_DNETMAP_PERSISTENT)
|
||||
printf(" persistent");
|
||||
|
||||
if (*flags & XT_DNETMAP_TTL)
|
||||
printf(" ttl %i", tginfo->ttl);
|
||||
else
|
||||
printf(" ttl default");
|
||||
}
|
||||
|
||||
static void DNETMAP_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
struct xt_DNETMAP_tginfo *tginfo = (void *)&target->data;
|
||||
@@ -258,6 +219,13 @@ static void DNETMAP_save(const void *ip, const struct xt_entry_target *target)
|
||||
printf(" --ttl %i ", tginfo->ttl);
|
||||
}
|
||||
|
||||
static void DNETMAP_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
printf(" -j DNETMAP");
|
||||
DNETMAP_save(ip, target);
|
||||
}
|
||||
|
||||
static struct xtables_target dnetmap_tg_reg = {
|
||||
.name = MODULENAME,
|
||||
.version = XTABLES_VERSION,
|
||||
@@ -265,7 +233,6 @@ static struct xtables_target dnetmap_tg_reg = {
|
||||
.size = XT_ALIGN(sizeof(struct xt_DNETMAP_tginfo)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct xt_DNETMAP_tginfo)),
|
||||
.help = DNETMAP_help,
|
||||
.init = DNETMAP_init,
|
||||
.parse = DNETMAP_parse,
|
||||
.print = DNETMAP_print,
|
||||
.save = DNETMAP_save,
|
||||
|
@@ -1,172 +1,179 @@
|
||||
The \fBDNETMAP\fR target allows dynamic two-way 1:1 mapping of IPv4 subnets.
|
||||
Single rule can map private subnet to shorter public subnet creating and
|
||||
maintaining unambigeous private-public ip bindings. Second rule can be used to
|
||||
map new flows to private subnet according to maintained bindings. Target allows
|
||||
efficient public IPv4 space usage and unambigeous NAT at the same time.
|
||||
|
||||
Target can be used only in \fBnat\fR table in \fBPOSTROUTING\fR or \fBOUTPUT\fR
|
||||
chains for SNAT and in \fBPREROUTING\fR for DNAT. Only flows directed to bound
|
||||
IPs will be DNATed. Packet continues chain traversal if there is no free
|
||||
postnat-ip to be assigned to prenat-ip. Default binding \fBttl\fR is \fI10
|
||||
minutes\fR and can be changed using \fBdefault_ttl\fR module option. Default ip
|
||||
hash size is 256 and can be changed using \fBhash_size\fR module option.
|
||||
|
||||
.PP
|
||||
The \fBDNETMAP\fR target allows dynamic two-way 1:1 mapping of IPv4 subnets. A
|
||||
single rule can map a private subnet to a shorter public subnet, creating and
|
||||
maintaining unambiguous private-public IP address bindings. The second rule can
|
||||
be used to map new flows to a private subnet according to maintained bindings.
|
||||
The target allows efficient public IPv4 space usage and unambiguous NAT at the
|
||||
same time.
|
||||
.PP
|
||||
The target can be used only in the \fBnat\fR table in \fBPOSTROUTING\fR or
|
||||
\fBOUTPUT\fR chains for SNAT, and in \fBPREROUTING\fR for DNAT. Only flows
|
||||
directed to bound addresses will be DNATed. The packet continues chain
|
||||
traversal if there is no free postnat address to be assigned to the prenat
|
||||
address. The default binding \fBTTL\fR is \fI10 minutes\fR and can be changed
|
||||
using the \fBdefault_ttl\fR module option. The default address hash size is 256
|
||||
and can be changed using the \fBhash_size\fR module option.
|
||||
.TP
|
||||
\fB\-\-prefix\fR \fIaddr\fR\fB/\fR\fImask\fR
|
||||
Network subnet to map to. If not specified, all existing prefixes are used.
|
||||
The network subnet to map to. If not specified, all existing prefixes are used.
|
||||
.TP
|
||||
\fB\-\-reuse\fR
|
||||
Reuse entry for given prenat-ip from any prefix despite bindings ttl < 0.
|
||||
Reuse the entry for a given prenat address from any prefix even if the
|
||||
binding's TTL is < 0.
|
||||
.TP
|
||||
\fB\-\-persistent\fR
|
||||
Set prefix persistent. It won't be removed after deleting last iptables rule.
|
||||
Option is effective only in the first rule for a given prefix. If you
|
||||
need to change persistency for existing prefix, please use proc interface
|
||||
described below.
|
||||
Set the prefix to be persistent. It will not be removed after deleting the last
|
||||
iptables rule. The option is effective only in the first rule for a given
|
||||
prefix. If you need to change persistency for an existing prefix, please use
|
||||
the procfs interface described below.
|
||||
.TP
|
||||
\fB\-\-static\fR
|
||||
Don't create dynamic mappings using this rule. Use static mappings only. Note
|
||||
that you need to create static mappings via proc interface for this rule with
|
||||
this option to have any effect.
|
||||
Do not create dynamic mappings using this rule. Use static mappings only. Note
|
||||
that you need to create static mappings via the procfs interface for this rule
|
||||
for this option to have any effect.
|
||||
.TP
|
||||
\fB\-\-ttl\fR \fIseconds\fR
|
||||
Regenerate bindings ttl value to \fIseconds\fR. If negative value is specified,
|
||||
bindings ttl is kept unchanged. If not specified then default ttl value (600s)
|
||||
is used.
|
||||
Reset the binding's TTL value to \fIseconds\fR. If a negative value is
|
||||
specified, the binding's TTL is kept unchanged. If this option is not
|
||||
specified, then the default TTL value (600s) is used.
|
||||
.PP
|
||||
\fB* /proc interface\fR
|
||||
|
||||
Module creates following entries for each new specified subnet:
|
||||
.PP
|
||||
The module creates the following entries for each new specified subnet:
|
||||
.TP
|
||||
\fB/proc/net/xt_DNETMAP/\fR\fIsubnet\fR\fB_\fR\fImask\fR
|
||||
Contains binding table for subnet/mask. Each line contains \fBprenat-ip\fR,
|
||||
\fBpostnat-ip\fR,\fBttl\fR (seconds till entry times out), \fBlasthit\fR (last
|
||||
entry hit in seconds relative to system boot time). Please note that \fBttl\fR
|
||||
and \fBlasthit\fR entries contain \fBS\fR in case of static binding.
|
||||
Contains the binding table for the given \fIsubnet/mask\fP. Each line contains
|
||||
\fBprenat address\fR, \fBpostnat address\fR, \fBttl\fR (seconds until the entry
|
||||
times out), \fBlasthit\fR (last hit to the entry in seconds relative to system
|
||||
boot time). Please note that the \fBttl\fR and \fBlasthit\fR entries contain an
|
||||
\(oq\fBS\fR\(cq in case of a static binding.
|
||||
.TP
|
||||
\fB/proc/net/xt_DNETMAP/\fR\fIsubnet\fR\fB_\fR\fImask\fR\fB_stat\fR
|
||||
Contains statistics for given subnet/mask. Line contains contains four
|
||||
numerical values separated by spaces. First one is number of currently used
|
||||
dynamic addresses (bindings with negative ttl excluded), second one is number
|
||||
static assignments, third one is number of all usable addresses in subnet and
|
||||
the fourth one is mean \fBttl\fR value for all active entries. If prefix has
|
||||
persistent flag set it'll be noted as fifth entry.
|
||||
Contains statistics for a given \fIsubnet/mask\fP. The line contains four
|
||||
numerical values separated by spaces. The first one is the number of currently
|
||||
used dynamic addresses (bindings with negative TTL excluded), the second one is
|
||||
the number of static assignments, the third one is the number of all usable
|
||||
addresses in the subnet, and the fourth one is the mean \fBTTL\fR value for all
|
||||
active entries. If the prefix has the persistent flag set, it will be noted as
|
||||
fifth entry.
|
||||
.PP
|
||||
Following write operations are supported via proc interface:
|
||||
The following write operations are supported via the procfs interface:
|
||||
.TP
|
||||
echo "+\fIprenatIP\fR:\fIpostnatIP\fR" > \fB/proc/net/xt_DNETMAP/subnet_mask\fR
|
||||
Adds static binding between prenatIP nad postnatIP. If postnatIP is already
|
||||
bound, previous binding will be timedout immediatelly. Static binding is never
|
||||
timedout.
|
||||
echo "+\fIprenat-address\fR:\fIpostnat-address\fR" >\fB/proc/net/xt_DNETMAP/subnet_mask\fR
|
||||
Adds a static binding between the prenat and postnap address. If
|
||||
postnat_address is already bound, any previous binding will be timed out
|
||||
immediately. A static binding is never timed out.
|
||||
.TP
|
||||
echo "-\fIIP\fR" > \fB/proc/net/xt_DNETMAP/subnet_mask\fR
|
||||
Removes binding with \fIIP\fR as prenat or postnat address. If removed binding
|
||||
is currently static, it'll make entry available for dynamic allocation.
|
||||
echo "\-\fIaddress\fR" >\fB/proc/net/xt_DNETMAP/subnet_mask\fR
|
||||
Removes the binding with \fIaddress\fR as prenat or postnat address. If the
|
||||
removed binding is currently static, it will make the entry available for
|
||||
dynamic allocation.
|
||||
.TP
|
||||
echo "+persistent" >\fB/proc/net/xt_DNETMAP/subnet_mask\fR
|
||||
Sets persistent flag for prefix. It's usefull if you don't want bindings to get
|
||||
flushed when firewall is restarted. You can check if prefix is persistent by
|
||||
printing \fB/proc/net/xt_DNETMAP/\fR\fIsubnet\fR\fB_\fR\fImask\fR\fB_stat\fR
|
||||
contents.
|
||||
Sets the persistent flag for the prefix. It is useful if you do not want
|
||||
bindings to get flushed when the firewall is restarted. You can check if the
|
||||
prefix is persistent by printing the contents of
|
||||
\fB/proc/net/xt_DNETMAP/\fR\fIsubnet\fR\fB_\fR\fImask\fR\fB_stat\fR.
|
||||
.TP
|
||||
echo "-persistent" > \fB/proc/net/xt_DNETMAP/subnet_mask\fR
|
||||
Unsets persistent flag for prefix. In this mode prefix will be deleted if the
|
||||
last iptables rule for that prefix is removed.
|
||||
echo "\-persistent" >\fB/proc/net/xt_DNETMAP/subnet_mask\fR
|
||||
Unsets the persistent flag for the prefix. In this mode, the prefix will be
|
||||
deleted if the last iptables rule for that prefix is removed.
|
||||
.TP
|
||||
echo "flush" >\fB/proc/net/xt_DNETMAP/subnet_mask\fR
|
||||
Flushes all bindings for specific prefix. All static entries are also flushed
|
||||
and are available for dynamic bindings.
|
||||
Flushes all bindings for the specific prefix. All static entries are also
|
||||
flushed and become available for dynamic bindings.
|
||||
.PP
|
||||
Note! Entries are removed if the last iptables rule for a specific prefix is
|
||||
deleted unless there's persistent flag set.
|
||||
deleted unless the persistent flag is set.
|
||||
.PP
|
||||
|
||||
\fB* Logging\fR
|
||||
|
||||
Module logs binding add/timeout events to klog. This behaviour can be disabled
|
||||
using \fBdisable_log\fR module parameter.
|
||||
|
||||
.PP
|
||||
The module logs binding add/timeout events to klog. This behaviour can be
|
||||
disabled using the \fBdisable_log\fR module parameter.
|
||||
.PP
|
||||
\fB* Examples\fR
|
||||
|
||||
.PP
|
||||
\fB1.\fR Map subnet 192.168.0.0/24 to subnets 20.0.0.0/26. SNAT only:
|
||||
|
||||
iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -j DNETMAP --prefix 20.0.0.0/26
|
||||
|
||||
Active hosts from 192.168.0.0/24 subnet are mapped to 20.0.0.0/26. If packet
|
||||
from not yet bound prenat-ip hits the rule and there are no free or timed-out
|
||||
(ttl<0) entries in prefix 20.0.0.0/28, then notice is logged to klog and chain
|
||||
traversal continues. If packet from already bound prenat-ip hits the rule,
|
||||
bindings ttl value is regenerated to default_ttl and SNAT is performed.
|
||||
|
||||
.PP
|
||||
iptables \-t nat \-A POSTROUTING \-s 192.168.0.0/24 \-j DNETMAP \-\-prefix 20.0.0.0/26
|
||||
.PP
|
||||
Active hosts from the 192.168.0.0/24 subnet are mapped to 20.0.0.0/26. If the
|
||||
packet from a not yet bound prenat address hits the rule and there are no free
|
||||
or timed-out (TTL<0) entries in prefix 20.0.0.0/28, then a notice is logged to
|
||||
klog and chain traversal continues. If packet from an already-bound prenat
|
||||
address hits the rule, the binding's TTL value is reset to default_ttl and SNAT
|
||||
is performed.
|
||||
.PP
|
||||
\fB2.\fR Use of \fB\-\-reuse\fR and \fB\-\-ttl\fR switches, multiple rule
|
||||
interaction:
|
||||
|
||||
iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -j DNETMAP --prefix
|
||||
20.0.0.0/26 --reuse --ttl 200
|
||||
|
||||
iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -j DNETMAP --prefix 30.0.0.0/26
|
||||
|
||||
Active hosts from 192.168.0.0/24 subnet are mapped to 20.0.0.0/26 with ttl =
|
||||
200 seconds. If there are no free addresses in first prefix the next one
|
||||
(30.0.0.0/26) is used with default ttl. It's important to note that the first
|
||||
rule SNATs all flows whose source IP is already actively (ttl>0) bound to ANY
|
||||
prefix. Parameter \fB\-\-reuse\fR makes this functionality work even for
|
||||
inactive (ttl<0) entries.
|
||||
|
||||
If both subnets are exhaused, then chain traversal continues.
|
||||
|
||||
\fB3.\fR Map 192.168.0.0/24 to subnets 20.0.0.0/26 bidirectional way:
|
||||
|
||||
iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -j DNETMAP --prefix 20.0.0.0/26
|
||||
|
||||
iptables -t nat -A PREROUTING -j DNETMAP
|
||||
|
||||
If host 192.168.0.10 generates some traffic, it gets bound to first free IP in
|
||||
subnet - 20.0.0.0. Now any traffic directed to 20.0.0.0 gets DNATed to
|
||||
192.168.0.10 as long as there's an active (ttl>0) binding. There's no need to
|
||||
specify \fB\-\-prefix\fR parameter in PREROUTING rule, because this way it DNATs
|
||||
traffic to all active prefixes. You could specify prefix it you'd like to make
|
||||
DNAT work for specific prefix only.
|
||||
|
||||
\fB4.\fR Map 192.168.0.0/24 to subnets 20.0.0.0/26 with static assignments only:
|
||||
|
||||
iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -j DNETMAP --prefix 20.0.0.0/26
|
||||
--static
|
||||
|
||||
.PP
|
||||
iptables \-t nat \-A POSTROUTING \-s 192.168.0.0/24 \-j DNETMAP \-\-prefix
|
||||
20.0.0.0/26 \-\-reuse \-\-ttl 200
|
||||
.PP
|
||||
iptables \-t nat \-A POSTROUTING \-s 192.168.0.0/24 \-j DNETMAP \-\-prefix 30.0.0.0/26
|
||||
.PP
|
||||
Active hosts from 192.168.0.0/24 subnet are mapped to 20.0.0.0/26 with TTL =
|
||||
200 seconds. If there are no free addresses in first prefix, the next one
|
||||
(30.0.0.0/26) is used with the default TTL. It is important to note that the
|
||||
first rule SNATs all flows whose source address is already actively bound
|
||||
(TTL>0) to ANY prefix. The \fB\-\-reuse\fR parameter makes this functionality
|
||||
work even for inactive (TTL<0) entries.
|
||||
.PP
|
||||
If both subnets are exhausted, then chain traversal continues.
|
||||
.PP
|
||||
\fB3.\fR Map 192.168.0.0/24 to subnets 20.0.0.0/26 in a bidirectional way:
|
||||
.PP
|
||||
iptables \-t nat \-A POSTROUTING \-s 192.168.0.0/24 \-j DNETMAP \-\-prefix 20.0.0.0/26
|
||||
.PP
|
||||
iptables \-t nat \-A PREROUTING \-j DNETMAP
|
||||
.PP
|
||||
If the host 192.168.0.10 generates some traffic, it gets bound to first free
|
||||
address in the subnet \(em 20.0.0.0. Now, any traffic directed to 20.0.0.0 gets
|
||||
DNATed to 192.168.0.10 as long as there is an active (TTL>0) binding. There is
|
||||
no need to specify \fB\-\-prefix\fR parameter in a PREROUTING rule, because
|
||||
this way, it DNATs traffic to all active prefixes. You could specify the prefix
|
||||
you would like to make DNAT work for a specific prefix only.
|
||||
.PP
|
||||
\fB4.\fR Map 192.168.0.0/24 to subnets 20.0.0.0/26 with static assignments
|
||||
only:
|
||||
.PP
|
||||
iptables \-t nat \-A POSTROUTING \-s 192.168.0.0/24 \-j DNETMAP \-\-prefix 20.0.0.0/26
|
||||
\-\-static
|
||||
.PP
|
||||
echo "+192.168.0.10:20.0.0.1" >/proc/net/xt_DNETMAP/20.0.0.0_26
|
||||
.br
|
||||
echo "+192.168.0.11:20.0.0.2" >/proc/net/xt_DNETMAP/20.0.0.0_26
|
||||
.br
|
||||
echo "+192.168.0.51:20.0.0.3" >/proc/net/xt_DNETMAP/20.0.0.0_26
|
||||
|
||||
.PP
|
||||
This configuration will allow only preconfigured static bindings to work due to
|
||||
\fBstatic\fR rule option. Without this flag dynamic bindings would be created
|
||||
using non-static entries.
|
||||
|
||||
the \fBstatic\fR rule option. Without this flag, dynamic bindings would be
|
||||
created using non-static entries.
|
||||
.PP
|
||||
\fB5.\fR Persistent prefix:
|
||||
|
||||
iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -j DNETMAP --prefix 20.0.0.0/26
|
||||
--persistent
|
||||
.PP
|
||||
iptables \-t nat \-A POSTROUTING \-s 192.168.0.0/24 \-j DNETMAP \-\-prefix 20.0.0.0/26
|
||||
\-\-persistent
|
||||
.br
|
||||
\fBor\fR
|
||||
.br
|
||||
iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -j DNETMAP --prefix 20.0.0.0/26
|
||||
iptables \-t nat \-A POSTROUTING \-s 192.168.0.0/24 \-j DNETMAP \-\-prefix 20.0.0.0/26
|
||||
.br
|
||||
echo "+persistent" >/proc/net/xt_DNETMAP/20.0.0.0_26
|
||||
|
||||
Now we can check persistent flag of the prefix:
|
||||
.PP
|
||||
Now, we can check the persistent flag of the prefix:
|
||||
.br
|
||||
cat /proc/net/xt_DNETMAP/20.0.0.0_26
|
||||
.br
|
||||
0 0 64 0 \fBpersistent\fR
|
||||
|
||||
Flush iptables nat table and see that prefix is still in existence:
|
||||
.PP
|
||||
Flush the iptables nat table and see that prefix is still in existence:
|
||||
.br
|
||||
iptables -F -t nat
|
||||
iptables \-F \-t nat
|
||||
.br
|
||||
ls -l /proc/net/xt_DNETMAP
|
||||
ls \-l /proc/net/xt_DNETMAP
|
||||
.br
|
||||
-rw-r--r-- 1 root root 0 06-10 09:01 20.0.0.0_26
|
||||
\-rw\-r\-\-r\-\- 1 root root 0 06\-10 09:01 20.0.0.0_26
|
||||
.br
|
||||
-rw-r--r-- 1 root root 0 06-10 09:01 20.0.0.0_26_stat
|
||||
\-rw\-r\-\-r\-\- 1 root root 0 06\-10 09:01 20.0.0.0_26_stat
|
||||
.
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* "ECHO" target extension for iptables
|
||||
* Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2008
|
||||
* Copyright © Jan Engelhardt, 2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License; either
|
||||
|
@@ -1,3 +1,4 @@
|
||||
.PP
|
||||
The \fBECHO\fP target will send back all packets it received. It serves as an
|
||||
examples for an Xtables target.
|
||||
.PP
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* "IPMARK" target extension for iptables
|
||||
* Copyright © Grzegorz Janoszka <Grzegorz.Janoszka@pro.onet.pl>, 2003
|
||||
* Jan Engelhardt <jengelh [at] medozas de>, 2008
|
||||
* Jan Engelhardt, 2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License; either
|
||||
@@ -112,25 +112,6 @@ static void ipmark_tg_check(unsigned int flags)
|
||||
"IPMARK target: Parameter --addr is required");
|
||||
}
|
||||
|
||||
static void
|
||||
ipmark_tg_print(const void *entry, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct xt_ipmark_tginfo *info = (const void *)target->data;
|
||||
|
||||
if (info->selector == XT_IPMARK_SRC)
|
||||
printf(" IPMARK src ip ");
|
||||
else
|
||||
printf(" IPMARK dst ip ");
|
||||
|
||||
if (info->shift != 0)
|
||||
printf(" shift %u ", (unsigned int)info->shift);
|
||||
if (info->andmask != ~0U)
|
||||
printf(" and 0x%x ", (unsigned int)info->andmask);
|
||||
if (info->ormask != 0)
|
||||
printf(" or 0x%x ", (unsigned int)info->ormask);
|
||||
}
|
||||
|
||||
static void
|
||||
ipmark_tg_save(const void *entry, const struct xt_entry_target *target)
|
||||
{
|
||||
@@ -149,6 +130,14 @@ ipmark_tg_save(const void *entry, const struct xt_entry_target *target)
|
||||
printf(" --or-mask 0x%x ", (unsigned int)info->ormask);
|
||||
}
|
||||
|
||||
static void
|
||||
ipmark_tg_print(const void *entry, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
printf(" -j IPMARK");
|
||||
ipmark_tg_save(entry, target);
|
||||
}
|
||||
|
||||
static struct xtables_target ipmark_tg_reg = {
|
||||
.version = XTABLES_VERSION,
|
||||
.name = "IPMARK",
|
||||
|
@@ -1,7 +1,8 @@
|
||||
.PP
|
||||
Allows you to mark a received packet basing on its IP address. This
|
||||
can replace many mangle/mark entries with only one, if you use
|
||||
firewall based classifier.
|
||||
|
||||
.PP
|
||||
This target is to be used inside the \fBmangle\fP table.
|
||||
.TP
|
||||
\fB\-\-addr\fP {\fBsrc\fP|\fBdst\fP}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* "LOGMARK" target extension for iptables
|
||||
* Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2008
|
||||
* Copyright © Jan Engelhardt, 2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License; either
|
||||
@@ -77,15 +77,6 @@ logmark_tg_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
logmark_tg_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct xt_logmark_tginfo *info = (void *)target->data;
|
||||
|
||||
printf(" LOGMARK level %u prefix \"%s\" ", info->level, info->prefix);
|
||||
}
|
||||
|
||||
static void
|
||||
logmark_tg_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
@@ -97,6 +88,14 @@ logmark_tg_save(const void *ip, const struct xt_entry_target *target)
|
||||
printf(" --log-prefix \"%s\" ", info->prefix);
|
||||
}
|
||||
|
||||
static void
|
||||
logmark_tg_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
printf(" -j LOGMARK");
|
||||
logmark_tg_save(ip, target);
|
||||
}
|
||||
|
||||
static struct xtables_target logmark_tg_reg = {
|
||||
.version = XTABLES_VERSION,
|
||||
.name = "LOGMARK",
|
||||
|
@@ -1,3 +1,4 @@
|
||||
.PP
|
||||
The LOGMARK target will log packet and connection marks to syslog.
|
||||
.TP
|
||||
\fB\-\-log\-level\fR \fIlevel\fR
|
||||
|
105
extensions/libxt_PROTO.c
Normal file
105
extensions/libxt_PROTO.c
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* PROTO Target module
|
||||
* This program is distributed under the terms of GNU GPL
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <xtables.h>
|
||||
#include "xt_PROTO.h"
|
||||
|
||||
enum {
|
||||
O_PROTO_SET = 0,
|
||||
O_PROTO_STOP_AT_FRAG = 1,
|
||||
O_PROTO_STOP_AT_AUTH = 2,
|
||||
F_PROTO_SET = 1 << O_PROTO_SET,
|
||||
F_PROTO_STOP_AT_FRAG = 1 << O_PROTO_STOP_AT_FRAG,
|
||||
F_PROTO_STOP_AT_AUTH = 1 << O_PROTO_STOP_AT_AUTH,
|
||||
};
|
||||
|
||||
#define s struct xt_PROTO_info
|
||||
static const struct xt_option_entry PROTO_opts[] = {
|
||||
{.name = "proto-set", .type = XTTYPE_UINT8, .id = O_PROTO_SET,
|
||||
.flags = XTOPT_PUT | XTOPT_MAND, XTOPT_POINTER(s, proto)},
|
||||
{.name = "stop-at-frag", .type = XTTYPE_NONE, .id = O_PROTO_STOP_AT_FRAG},
|
||||
{.name = "stop-at-auth", .type = XTTYPE_NONE, .id = O_PROTO_STOP_AT_AUTH},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
#undef s
|
||||
|
||||
static void PROTO_help(void)
|
||||
{
|
||||
printf(
|
||||
"PROTO target options\n"
|
||||
" --proto-set value Set protocol to <value 0-255>\n"
|
||||
);
|
||||
}
|
||||
|
||||
static void PROTO_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct xt_PROTO_info *info = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
switch (cb->entry->id) {
|
||||
case O_PROTO_SET:
|
||||
info->mode |= 1 << XT_PROTO_SET;
|
||||
break;
|
||||
case O_PROTO_STOP_AT_FRAG:
|
||||
info->mode |= 1 << XT_PROTO_STOP_AT_FRAG;
|
||||
break;
|
||||
case O_PROTO_STOP_AT_AUTH:
|
||||
info->mode |= 1 << XT_PROTO_STOP_AT_AUTH;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void PROTO_check(struct xt_fcheck_call *cb)
|
||||
{
|
||||
if (!(cb->xflags & F_PROTO_SET))
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"PROTO: You must specify the proto to be set");
|
||||
}
|
||||
|
||||
static void PROTO_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct xt_PROTO_info *info = (void *)target->data;
|
||||
|
||||
if (info->mode & (1 << XT_PROTO_SET))
|
||||
printf(" --proto-set %u", info->proto);
|
||||
if (info->mode & (1 << XT_PROTO_STOP_AT_FRAG))
|
||||
printf(" --stop-at-frag");
|
||||
if (info->mode & (1 << XT_PROTO_STOP_AT_AUTH))
|
||||
printf(" --stop-at-auth");
|
||||
}
|
||||
|
||||
static void PROTO_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct xt_PROTO_info *info = (void *)target->data;
|
||||
|
||||
printf(" PROTO ");
|
||||
if (info->mode & (1 << XT_PROTO_SET))
|
||||
printf("set to %u", info->proto);
|
||||
if (info->mode & (1 << XT_PROTO_STOP_AT_FRAG))
|
||||
printf(" stop-at-frag");
|
||||
if (info->mode & (1 << XT_PROTO_STOP_AT_AUTH))
|
||||
printf(" stop-at-auth");
|
||||
}
|
||||
|
||||
static struct xtables_target proto_tg_reg = {
|
||||
.name = "PROTO",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.size = XT_ALIGN(sizeof(struct xt_PROTO_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct xt_PROTO_info)),
|
||||
.help = PROTO_help,
|
||||
.print = PROTO_print,
|
||||
.save = PROTO_save,
|
||||
.x6_parse = PROTO_parse,
|
||||
.x6_fcheck = PROTO_check,
|
||||
.x6_options = PROTO_opts,
|
||||
};
|
||||
|
||||
static __attribute__((constructor)) void _init(void)
|
||||
{
|
||||
xtables_register_target(&proto_tg_reg);
|
||||
|
||||
}
|
30
extensions/libxt_PROTO.man
Normal file
30
extensions/libxt_PROTO.man
Normal file
@@ -0,0 +1,30 @@
|
||||
.PP
|
||||
The PROTO target modifies the protocol number in IP packet header.
|
||||
.TP
|
||||
\fB\-\-proto-set\fP \fIproto_num\fP
|
||||
This option is mandatory. \fIproto_num\fP is the protocol number to which you want to
|
||||
modify the packets.
|
||||
.TP
|
||||
\fB\-\-stop-at-frag\fP
|
||||
This option is only valid for IPv6 rules. When specifying this option, the
|
||||
fragment extension header will be seen as a non-extension header.
|
||||
.TP
|
||||
\fB\-\-stop-at-auth\fP
|
||||
This option is only valid for IPv6 rules. When specifying this option, the
|
||||
authentication extension header will be seen as a non-extension header.
|
||||
.PP
|
||||
For IPv4 packets, the \fBProtocol\fP field is modified and the checksum is
|
||||
re-calculated.
|
||||
.PP
|
||||
For IPv6 packets, the scenario can be more complex due to the introduction of
|
||||
the extension headers mechanism. By default, the PROTO target will scan the IPv6
|
||||
packet, finding the last extension header and modify its \fBNext-header\fP field.
|
||||
Normally, the following headers will be seen as an extension header:
|
||||
\fINEXTHDR_HOP\fP,
|
||||
\fINEXTHDR_ROUTING\fP,
|
||||
\fINEXTHDR_FRAGMENT\fP,
|
||||
\fINEXTHDR_AUTH\fP,
|
||||
\fINEXTHDR_DEST\fP.
|
||||
.PP
|
||||
For fragmented packets, only the first fragment is processed and other fragments
|
||||
are not touched.
|
@@ -1,189 +0,0 @@
|
||||
/*
|
||||
* "RAWNAT" target extension for iptables
|
||||
* Copyright © Jan Engelhardt, 2008 - 2009
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License; either
|
||||
* version 2 of the License, or any later version, as published by the
|
||||
* Free Software Foundation.
|
||||
*/
|
||||
#include <netinet/in.h>
|
||||
#include <getopt.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include "xt_RAWNAT.h"
|
||||
#include "compat_user.h"
|
||||
|
||||
enum {
|
||||
FLAGS_TO = 1 << 0,
|
||||
};
|
||||
|
||||
static const struct option rawdnat_tg_opts[] = {
|
||||
{.name = "to-destination", .has_arg = true, .val = 't'},
|
||||
{},
|
||||
};
|
||||
|
||||
static void rawdnat_tg_help(void)
|
||||
{
|
||||
printf(
|
||||
"RAWDNAT target options:\n"
|
||||
" --to-destination addr[/mask] Address or network to map to\n"
|
||||
);
|
||||
}
|
||||
|
||||
static int
|
||||
rawdnat_tg4_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
const void *entry, struct xt_entry_target **target)
|
||||
{
|
||||
struct xt_rawnat_tginfo *info = (void *)(*target)->data;
|
||||
struct in_addr *a;
|
||||
unsigned int mask;
|
||||
char *end;
|
||||
|
||||
switch (c) {
|
||||
case 't':
|
||||
info->mask = 32;
|
||||
end = strchr(optarg, '/');
|
||||
if (end != NULL) {
|
||||
*end++ = '\0';
|
||||
if (!xtables_strtoui(end, NULL, &mask, 0, 32))
|
||||
xtables_param_act(XTF_BAD_VALUE, "RAWDNAT",
|
||||
"--to-destination", optarg);
|
||||
info->mask = mask;
|
||||
}
|
||||
a = xtables_numeric_to_ipaddr(optarg);
|
||||
if (a == NULL)
|
||||
xtables_param_act(XTF_BAD_VALUE, "RAWDNAT",
|
||||
"--to-destination", optarg);
|
||||
memcpy(&info->addr.in, a, sizeof(*a));
|
||||
*flags |= FLAGS_TO;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int
|
||||
rawdnat_tg6_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
const void *entry, struct xt_entry_target **target)
|
||||
{
|
||||
struct xt_rawnat_tginfo *info = (void *)(*target)->data;
|
||||
struct in6_addr *a;
|
||||
unsigned int mask;
|
||||
char *end;
|
||||
|
||||
switch (c) {
|
||||
case 't':
|
||||
info->mask = 128;
|
||||
end = strchr(optarg, '/');
|
||||
if (end != NULL) {
|
||||
*end++ = '\0';
|
||||
if (!xtables_strtoui(end, NULL, &mask, 0, 128))
|
||||
xtables_param_act(XTF_BAD_VALUE, "RAWDNAT",
|
||||
"--to-destination", optarg);
|
||||
info->mask = mask;
|
||||
}
|
||||
a = xtables_numeric_to_ip6addr(optarg);
|
||||
if (a == NULL)
|
||||
xtables_param_act(XTF_BAD_VALUE, "RAWDNAT",
|
||||
"--to-destination", optarg);
|
||||
memcpy(&info->addr.in6, a, sizeof(*a));
|
||||
*flags |= FLAGS_TO;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void rawdnat_tg_check(unsigned int flags)
|
||||
{
|
||||
if (!(flags & FLAGS_TO))
|
||||
xtables_error(PARAMETER_PROBLEM, "RAWDNAT: "
|
||||
"\"--to-destination\" is required.");
|
||||
}
|
||||
|
||||
static void
|
||||
rawdnat_tg4_print(const void *entry, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct xt_rawnat_tginfo *info = (const void *)target->data;
|
||||
|
||||
if (!numeric && info->mask == 32)
|
||||
printf(" to-destination %s ",
|
||||
xtables_ipaddr_to_anyname(&info->addr.in));
|
||||
else
|
||||
printf(" to-destination %s/%u ",
|
||||
xtables_ipaddr_to_numeric(&info->addr.in), info->mask);
|
||||
}
|
||||
|
||||
static void
|
||||
rawdnat_tg6_print(const void *entry, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct xt_rawnat_tginfo *info = (const void *)target->data;
|
||||
|
||||
if (!numeric && info->mask == 128)
|
||||
printf(" to-destination %s ",
|
||||
xtables_ip6addr_to_anyname(&info->addr.in6));
|
||||
else
|
||||
printf(" to-destination %s/%u ",
|
||||
xtables_ip6addr_to_numeric(&info->addr.in6), info->mask);
|
||||
}
|
||||
|
||||
static void
|
||||
rawdnat_tg4_save(const void *entry, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct xt_rawnat_tginfo *info = (const void *)target->data;
|
||||
|
||||
printf(" --to-destination %s/%u ",
|
||||
xtables_ipaddr_to_numeric(&info->addr.in),
|
||||
info->mask);
|
||||
}
|
||||
|
||||
static void
|
||||
rawdnat_tg6_save(const void *entry, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct xt_rawnat_tginfo *info = (const void *)target->data;
|
||||
|
||||
printf(" --to-destination %s/%u ",
|
||||
xtables_ip6addr_to_numeric(&info->addr.in6),
|
||||
info->mask);
|
||||
}
|
||||
|
||||
static struct xtables_target rawdnat_tg_reg[] = {
|
||||
{
|
||||
.version = XTABLES_VERSION,
|
||||
.name = "RAWDNAT",
|
||||
.revision = 0,
|
||||
.family = NFPROTO_IPV4,
|
||||
.size = XT_ALIGN(sizeof(struct xt_rawnat_tginfo)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct xt_rawnat_tginfo)),
|
||||
.help = rawdnat_tg_help,
|
||||
.parse = rawdnat_tg4_parse,
|
||||
.final_check = rawdnat_tg_check,
|
||||
.print = rawdnat_tg4_print,
|
||||
.save = rawdnat_tg4_save,
|
||||
.extra_opts = rawdnat_tg_opts,
|
||||
},
|
||||
{
|
||||
.version = XTABLES_VERSION,
|
||||
.name = "RAWDNAT",
|
||||
.revision = 0,
|
||||
.family = NFPROTO_IPV6,
|
||||
.size = XT_ALIGN(sizeof(struct xt_rawnat_tginfo)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct xt_rawnat_tginfo)),
|
||||
.help = rawdnat_tg_help,
|
||||
.parse = rawdnat_tg6_parse,
|
||||
.final_check = rawdnat_tg_check,
|
||||
.print = rawdnat_tg6_print,
|
||||
.save = rawdnat_tg6_save,
|
||||
.extra_opts = rawdnat_tg_opts,
|
||||
},
|
||||
};
|
||||
|
||||
static void _init(void)
|
||||
{
|
||||
xtables_register_targets(rawdnat_tg_reg,
|
||||
sizeof(rawdnat_tg_reg) / sizeof(*rawdnat_tg_reg));
|
||||
}
|
@@ -1,10 +0,0 @@
|
||||
The \fBRAWDNAT\fR target will rewrite the destination address in the IP header,
|
||||
much like the \fBNETMAP\fR target.
|
||||
.TP
|
||||
\fB\-\-to\-destination\fR \fIaddr\fR[\fB/\fR\fImask\fR]
|
||||
Network address to map to. The resulting address will be constructed the
|
||||
following way: All 'one' bits in the \fImask\fR are filled in from the new
|
||||
\fIaddress\fR. All bits that are zero in the mask are filled in from the
|
||||
original address.
|
||||
.PP
|
||||
See the \fBRAWSNAT\fR help entry for examples and constraints.
|
@@ -1,189 +0,0 @@
|
||||
/*
|
||||
* "RAWNAT" target extension for iptables
|
||||
* Copyright © Jan Engelhardt, 2008 - 2009
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License; either
|
||||
* version 2 of the License, or any later version, as published by the
|
||||
* Free Software Foundation.
|
||||
*/
|
||||
#include <netinet/in.h>
|
||||
#include <getopt.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include "xt_RAWNAT.h"
|
||||
#include "compat_user.h"
|
||||
|
||||
enum {
|
||||
FLAGS_TO = 1 << 0,
|
||||
};
|
||||
|
||||
static const struct option rawsnat_tg_opts[] = {
|
||||
{.name = "to-source", .has_arg = true, .val = 't'},
|
||||
{},
|
||||
};
|
||||
|
||||
static void rawsnat_tg_help(void)
|
||||
{
|
||||
printf(
|
||||
"RAWSNAT target options:\n"
|
||||
" --to-source addr[/mask] Address or network to map to\n"
|
||||
);
|
||||
}
|
||||
|
||||
static int
|
||||
rawsnat_tg4_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
const void *entry, struct xt_entry_target **target)
|
||||
{
|
||||
struct xt_rawnat_tginfo *info = (void *)(*target)->data;
|
||||
struct in_addr *a;
|
||||
unsigned int mask;
|
||||
char *end;
|
||||
|
||||
switch (c) {
|
||||
case 't':
|
||||
info->mask = 32;
|
||||
end = strchr(optarg, '/');
|
||||
if (end != NULL) {
|
||||
*end++ = '\0';
|
||||
if (!xtables_strtoui(end, NULL, &mask, 0, 32))
|
||||
xtables_param_act(XTF_BAD_VALUE, "RAWSNAT",
|
||||
"--to-source", optarg);
|
||||
info->mask = mask;
|
||||
}
|
||||
a = xtables_numeric_to_ipaddr(optarg);
|
||||
if (a == NULL)
|
||||
xtables_param_act(XTF_BAD_VALUE, "RAWSNAT",
|
||||
"--to-source", optarg);
|
||||
memcpy(&info->addr.in, a, sizeof(*a));
|
||||
*flags |= FLAGS_TO;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int
|
||||
rawsnat_tg6_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
const void *entry, struct xt_entry_target **target)
|
||||
{
|
||||
struct xt_rawnat_tginfo *info = (void *)(*target)->data;
|
||||
struct in6_addr *a;
|
||||
unsigned int mask;
|
||||
char *end;
|
||||
|
||||
switch (c) {
|
||||
case 't':
|
||||
info->mask = 128;
|
||||
end = strchr(optarg, '/');
|
||||
if (end != NULL) {
|
||||
*end++ = '\0';
|
||||
if (!xtables_strtoui(end, NULL, &mask, 0, 128))
|
||||
xtables_param_act(XTF_BAD_VALUE, "RAWSNAT",
|
||||
"--to-source", optarg);
|
||||
info->mask = mask;
|
||||
}
|
||||
a = xtables_numeric_to_ip6addr(optarg);
|
||||
if (a == NULL)
|
||||
xtables_param_act(XTF_BAD_VALUE, "RAWSNAT",
|
||||
"--to-source", optarg);
|
||||
memcpy(&info->addr.in6, a, sizeof(*a));
|
||||
*flags |= FLAGS_TO;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void rawsnat_tg_check(unsigned int flags)
|
||||
{
|
||||
if (!(flags & FLAGS_TO))
|
||||
xtables_error(PARAMETER_PROBLEM, "RAWSNAT: "
|
||||
"\"--to-source\" is required.");
|
||||
}
|
||||
|
||||
static void
|
||||
rawsnat_tg4_print(const void *entry, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct xt_rawnat_tginfo *info = (const void *)target->data;
|
||||
|
||||
if (!numeric && info->mask == 32)
|
||||
printf(" to-source %s ",
|
||||
xtables_ipaddr_to_anyname(&info->addr.in));
|
||||
else
|
||||
printf(" to-source %s/%u ",
|
||||
xtables_ipaddr_to_numeric(&info->addr.in), info->mask);
|
||||
}
|
||||
|
||||
static void
|
||||
rawsnat_tg6_print(const void *entry, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct xt_rawnat_tginfo *info = (const void *)target->data;
|
||||
|
||||
if (!numeric && info->mask == 128)
|
||||
printf(" to-source %s ",
|
||||
xtables_ip6addr_to_anyname(&info->addr.in6));
|
||||
else
|
||||
printf(" to-source %s/%u ",
|
||||
xtables_ip6addr_to_numeric(&info->addr.in6), info->mask);
|
||||
}
|
||||
|
||||
static void
|
||||
rawsnat_tg4_save(const void *entry, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct xt_rawnat_tginfo *info = (const void *)target->data;
|
||||
|
||||
printf(" --to-source %s/%u ",
|
||||
xtables_ipaddr_to_numeric(&info->addr.in),
|
||||
info->mask);
|
||||
}
|
||||
|
||||
static void
|
||||
rawsnat_tg6_save(const void *entry, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct xt_rawnat_tginfo *info = (const void *)target->data;
|
||||
|
||||
printf(" --to-source %s/%u ",
|
||||
xtables_ip6addr_to_numeric(&info->addr.in6),
|
||||
info->mask);
|
||||
}
|
||||
|
||||
static struct xtables_target rawsnat_tg_reg[] = {
|
||||
{
|
||||
.version = XTABLES_VERSION,
|
||||
.name = "RAWSNAT",
|
||||
.revision = 0,
|
||||
.family = NFPROTO_IPV4,
|
||||
.size = XT_ALIGN(sizeof(struct xt_rawnat_tginfo)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct xt_rawnat_tginfo)),
|
||||
.help = rawsnat_tg_help,
|
||||
.parse = rawsnat_tg4_parse,
|
||||
.final_check = rawsnat_tg_check,
|
||||
.print = rawsnat_tg4_print,
|
||||
.save = rawsnat_tg4_save,
|
||||
.extra_opts = rawsnat_tg_opts,
|
||||
},
|
||||
{
|
||||
.version = XTABLES_VERSION,
|
||||
.name = "RAWSNAT",
|
||||
.revision = 0,
|
||||
.family = NFPROTO_IPV6,
|
||||
.size = XT_ALIGN(sizeof(struct xt_rawnat_tginfo)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct xt_rawnat_tginfo)),
|
||||
.help = rawsnat_tg_help,
|
||||
.parse = rawsnat_tg6_parse,
|
||||
.final_check = rawsnat_tg_check,
|
||||
.print = rawsnat_tg6_print,
|
||||
.save = rawsnat_tg6_save,
|
||||
.extra_opts = rawsnat_tg_opts,
|
||||
},
|
||||
};
|
||||
|
||||
static void _init(void)
|
||||
{
|
||||
xtables_register_targets(rawsnat_tg_reg,
|
||||
sizeof(rawsnat_tg_reg) / sizeof(*rawsnat_tg_reg));
|
||||
}
|
@@ -1,38 +0,0 @@
|
||||
The \fBRAWSNAT\fR and \fBRAWDNAT\fP targets provide stateless network address
|
||||
translation.
|
||||
.PP
|
||||
The \fBRAWSNAT\fR target will rewrite the source address in the IP header, much
|
||||
like the \fBNETMAP\fP target. \fBRAWSNAT\fP (and \fBRAWDNAT\fP) may only be
|
||||
used in the \fBraw\fP or \fBrawpost\fP tables, but can be used in all chains,
|
||||
which makes it possible to change the source address either when the packet
|
||||
enters the machine or when it leaves it. The reason for this table constraint
|
||||
is that RAWNAT must happen outside of connection tracking.
|
||||
.TP
|
||||
\fB\-\-to\-source\fR \fIaddr\fR[\fB/\fR\fImask\fR]
|
||||
Network address to map to. The resulting address will be constructed the
|
||||
following way: All 'one' bits in the \fImask\fR are filled in from the new
|
||||
\fIaddress\fR. All bits that are zero in the mask are filled in from the
|
||||
original address.
|
||||
.PP
|
||||
As an example, changing the destination for packets forwarded from an internal
|
||||
LAN to the internet:
|
||||
.IP
|
||||
\-t raw \-A PREROUTING \-i lan0 \-d 212.201.100.135 \-j RAWDNAT \-\-to\-destination 199.181.132.250;
|
||||
\-t rawpost \-A POSTROUTING \-o lan0 \-s 199.181.132.250 \-j RAWSNAT \-\-to\-source 212.201.100.135;
|
||||
.PP
|
||||
Note that changing addresses may influence the route selection! Specifically,
|
||||
it statically NATs packets, not connections, like the normal DNAT/SNAT targets
|
||||
would do. Also note that it can transform already-NATed connections \(em as
|
||||
said, it is completely external to Netfilter's connection tracking/NAT.
|
||||
.PP
|
||||
If the machine itself generates packets that are to be rawnat'ed, you need a
|
||||
rule in the OUTPUT chain instead, just like you would with the stateful NAT
|
||||
targets.
|
||||
.PP
|
||||
It may be necessary that in doing so, you also need an extra RAWSNAT rule, to
|
||||
override the automatic source address selection that the routing code does
|
||||
before passing packets to iptables. If the connecting socket has not been
|
||||
explicitly bound to an address, as is the common mode of operation, the address
|
||||
that will be chosen is the primary address of the device through which the
|
||||
packet would be routed with its initial destination address - the address as
|
||||
seen before any RAWNAT takes place.
|
@@ -1,32 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <xtables.h>
|
||||
#include "compat_user.h"
|
||||
|
||||
static void steal_tg_help(void)
|
||||
{
|
||||
printf("STEAL takes no options\n\n");
|
||||
}
|
||||
|
||||
static int steal_tg_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
const void *entry, struct xt_entry_target **target)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void steal_tg_check(unsigned int flags)
|
||||
{
|
||||
}
|
||||
|
||||
static struct xtables_target steal_tg_reg = {
|
||||
.version = XTABLES_VERSION,
|
||||
.name = "STEAL",
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.help = steal_tg_help,
|
||||
.parse = steal_tg_parse,
|
||||
.final_check = steal_tg_check,
|
||||
};
|
||||
|
||||
static void _init(void)
|
||||
{
|
||||
xtables_register_target(&steal_tg_reg);
|
||||
}
|
@@ -1,2 +0,0 @@
|
||||
Like the DROP target, but does not throw an error like DROP when used in the
|
||||
\fBOUTPUT\fP chain.
|
@@ -1,3 +1,4 @@
|
||||
.PP
|
||||
The SYSRQ target allows to remotely trigger sysrq on the local machine over the
|
||||
network. This can be useful when vital parts of the machine hang, for example
|
||||
an oops in a filesystem causing locks to be not released and processes to get
|
||||
|
@@ -67,24 +67,6 @@ static void tarpit_tg_check(unsigned int flags)
|
||||
"TARPIT: only one action can be used at a time");
|
||||
}
|
||||
|
||||
static void tarpit_tg_print(const void *ip,
|
||||
const struct xt_entry_target *target, int numeric)
|
||||
{
|
||||
const struct xt_tarpit_tginfo *info = (void *)target->data;
|
||||
|
||||
switch (info->variant) {
|
||||
case XTTARPIT_HONEYPOT:
|
||||
printf(" honeypot mode ");
|
||||
break;
|
||||
case XTTARPIT_RESET:
|
||||
printf(" reset mode ");
|
||||
break;
|
||||
default:
|
||||
printf(" tarpit mode ");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void tarpit_tg_save(const void *ip,
|
||||
const struct xt_entry_target *target)
|
||||
{
|
||||
@@ -103,6 +85,13 @@ static void tarpit_tg_save(const void *ip,
|
||||
}
|
||||
}
|
||||
|
||||
static void tarpit_tg_print(const void *ip,
|
||||
const struct xt_entry_target *target, int numeric)
|
||||
{
|
||||
printf(" -j TARPIT");
|
||||
tarpit_tg_save(ip, target);
|
||||
}
|
||||
|
||||
static struct xtables_target tarpit_tg_reg = {
|
||||
.version = XTABLES_VERSION,
|
||||
.name = "TARPIT",
|
||||
|
@@ -1,3 +1,4 @@
|
||||
.PP
|
||||
Captures and holds incoming TCP connections using no local per-connection
|
||||
resources.
|
||||
.PP
|
||||
|
@@ -1,173 +0,0 @@
|
||||
/*
|
||||
* "TEE" target extension for iptables
|
||||
* Copyright © Sebastian Claßen <sebastian.classen [at] freenet.ag>, 2007
|
||||
* Jan Engelhardt <jengelh [at] medozas de>, 2007 - 2009
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License; either
|
||||
* version 2 of the License, or any later version, as published by the
|
||||
* Free Software Foundation.
|
||||
*/
|
||||
#include <sys/socket.h>
|
||||
#include <getopt.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#include "xt_TEE.h"
|
||||
#include "compat_user.h"
|
||||
|
||||
enum {
|
||||
FLAG_GATEWAY = 1 << 0,
|
||||
};
|
||||
|
||||
static const struct option tee_tg_opts[] = {
|
||||
{.name = "gateway", .has_arg = true, .val = 'g'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
static void tee_tg_help(void)
|
||||
{
|
||||
printf(
|
||||
"TEE target options:\n"
|
||||
" --gateway IPADDR Route packet via the gateway given by address\n"
|
||||
"\n");
|
||||
}
|
||||
|
||||
static int tee_tg_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
const void *entry, struct xt_entry_target **target)
|
||||
{
|
||||
struct xt_tee_tginfo *info = (void *)(*target)->data;
|
||||
const struct in_addr *ia;
|
||||
|
||||
switch (c) {
|
||||
case 'g':
|
||||
if (*flags & FLAG_GATEWAY)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Cannot specify --gateway more than once");
|
||||
|
||||
ia = xtables_numeric_to_ipaddr(optarg);
|
||||
if (ia == NULL)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Invalid IP address %s", optarg);
|
||||
|
||||
memcpy(&info->gw, ia, sizeof(*ia));
|
||||
*flags |= FLAG_GATEWAY;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int tee_tg6_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
const void *entry, struct xt_entry_target **target)
|
||||
{
|
||||
struct xt_tee_tginfo *info = (void *)(*target)->data;
|
||||
const struct in6_addr *ia;
|
||||
|
||||
switch (c) {
|
||||
case 'g':
|
||||
if (*flags & FLAG_GATEWAY)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Cannot specify --gateway more than once");
|
||||
|
||||
ia = xtables_numeric_to_ip6addr(optarg);
|
||||
if (ia == NULL)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Invalid IP address %s", optarg);
|
||||
|
||||
memcpy(&info->gw, ia, sizeof(*ia));
|
||||
*flags |= FLAG_GATEWAY;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void tee_tg_check(unsigned int flags)
|
||||
{
|
||||
if (flags == 0)
|
||||
xtables_error(PARAMETER_PROBLEM, "TEE target: "
|
||||
"--gateway parameter required");
|
||||
}
|
||||
|
||||
static void tee_tg_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct xt_tee_tginfo *info = (const void *)target->data;
|
||||
|
||||
if (numeric)
|
||||
printf(" TEE gw:%s ", xtables_ipaddr_to_numeric(&info->gw.in));
|
||||
else
|
||||
printf(" TEE gw:%s ", xtables_ipaddr_to_anyname(&info->gw.in));
|
||||
}
|
||||
|
||||
static void tee_tg6_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct xt_tee_tginfo *info = (const void *)target->data;
|
||||
|
||||
if (numeric)
|
||||
printf(" TEE gw:%s ", xtables_ip6addr_to_numeric(&info->gw.in6));
|
||||
else
|
||||
printf(" TEE gw:%s ", xtables_ip6addr_to_anyname(&info->gw.in6));
|
||||
}
|
||||
|
||||
static void tee_tg_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct xt_tee_tginfo *info = (const void *)target->data;
|
||||
|
||||
printf(" --gateway %s ", xtables_ipaddr_to_numeric(&info->gw.in));
|
||||
}
|
||||
|
||||
static void tee_tg6_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct xt_tee_tginfo *info = (const void *)target->data;
|
||||
|
||||
printf(" --gateway %s ", xtables_ip6addr_to_numeric(&info->gw.in6));
|
||||
}
|
||||
|
||||
static struct xtables_target tee_tg_reg[] = {
|
||||
{
|
||||
.name = "TEE",
|
||||
.version = XTABLES_VERSION,
|
||||
.revision = 0,
|
||||
.family = NFPROTO_IPV4,
|
||||
.size = XT_ALIGN(sizeof(struct xt_tee_tginfo)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct xt_tee_tginfo)),
|
||||
.help = tee_tg_help,
|
||||
.parse = tee_tg_parse,
|
||||
.final_check = tee_tg_check,
|
||||
.print = tee_tg_print,
|
||||
.save = tee_tg_save,
|
||||
.extra_opts = tee_tg_opts,
|
||||
},
|
||||
{
|
||||
.name = "TEE",
|
||||
.version = XTABLES_VERSION,
|
||||
.revision = 0,
|
||||
.family = NFPROTO_IPV6,
|
||||
.size = XT_ALIGN(sizeof(struct xt_tee_tginfo)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct xt_tee_tginfo)),
|
||||
.help = tee_tg_help,
|
||||
.parse = tee_tg6_parse,
|
||||
.final_check = tee_tg_check,
|
||||
.print = tee_tg6_print,
|
||||
.save = tee_tg6_save,
|
||||
.extra_opts = tee_tg_opts,
|
||||
},
|
||||
};
|
||||
|
||||
static __attribute__((constructor)) void tee_tg_ldr(void)
|
||||
{
|
||||
xtables_register_targets(tee_tg_reg,
|
||||
sizeof(tee_tg_reg) / sizeof(*tee_tg_reg));
|
||||
}
|
@@ -1,12 +0,0 @@
|
||||
The \fBTEE\fP target will clone a packet and redirect this clone to another
|
||||
machine on the \fBlocal\fP network segment. In other words, the nexthop
|
||||
must be the target, or you will have to configure the nexthop to forward it
|
||||
further if so desired.
|
||||
.TP
|
||||
\fB\-\-gateway\fP \fIipaddr\fP
|
||||
Send the cloned packet to the host reachable at the given IP address.
|
||||
Use of 0.0.0.0 (for IPv4 packets) or :: (IPv6) is invalid.
|
||||
.PP
|
||||
To forward all incoming traffic on eth0 to an Network Layer logging box:
|
||||
.PP
|
||||
\-t mangle \-A PREROUTING \-i eth0 \-j TEE \-\-gateway 2001:db8::1
|
@@ -2,7 +2,7 @@
|
||||
* "condition" match extension for iptables
|
||||
* Stephane Ouellette <ouellettes [at] videotron ca>, 2002-10-22
|
||||
* Massimiliano Hofer <max [at] nucleus it>, 2006-05-15
|
||||
* Jan Engelhardt <jengelh [at] medozas de>, 2008
|
||||
* Jan Engelhardt, 2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License; either version 2
|
||||
@@ -62,15 +62,6 @@ static void condition_check(unsigned int flags)
|
||||
"Condition match: must specify --condition");
|
||||
}
|
||||
|
||||
static void condition_print(const void *ip, const struct xt_entry_match *match,
|
||||
int numeric)
|
||||
{
|
||||
const struct xt_condition_mtinfo *info = (const void *)match->data;
|
||||
|
||||
printf(" condition %s%s ", (info->invert) ? "!" : "", info->name);
|
||||
}
|
||||
|
||||
|
||||
static void condition_save(const void *ip, const struct xt_entry_match *match)
|
||||
{
|
||||
const struct xt_condition_mtinfo *info = (const void *)match->data;
|
||||
@@ -78,6 +69,13 @@ static void condition_save(const void *ip, const struct xt_entry_match *match)
|
||||
printf("%s --condition \"%s\" ", info->invert ? " !" : "", info->name);
|
||||
}
|
||||
|
||||
static void condition_print(const void *ip, const struct xt_entry_match *match,
|
||||
int numeric)
|
||||
{
|
||||
printf(" -m condition");
|
||||
condition_save(ip, match);
|
||||
}
|
||||
|
||||
static struct xtables_match condition_mt_reg = {
|
||||
.name = "condition",
|
||||
.revision = 1,
|
||||
|
@@ -1,3 +1,4 @@
|
||||
.PP
|
||||
This matches if a specific condition variable is (un)set.
|
||||
.TP
|
||||
[\fB!\fP] \fB\-\-condition\fP \fIname\fP
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* "dhcpmac" match extension for iptables
|
||||
* Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2008
|
||||
* Copyright © Jan Engelhardt, 2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License; either
|
||||
@@ -62,15 +62,6 @@ static void dhcpmac_mt_check(unsigned int flags)
|
||||
"--mac parameter required");
|
||||
}
|
||||
|
||||
static void dhcpmac_mt_print(const void *ip,
|
||||
const struct xt_entry_match *match, int numeric)
|
||||
{
|
||||
const struct dhcpmac_info *info = (void *)match->data;
|
||||
|
||||
printf(" dhcpmac %s" DH_MAC_FMT "/%u ",
|
||||
info->invert ? "!" : "", DH_MAC_HEX(info->addr), info->mask);
|
||||
}
|
||||
|
||||
static void dhcpmac_mt_save(const void *ip,
|
||||
const struct xt_entry_match *match)
|
||||
{
|
||||
@@ -82,6 +73,13 @@ static void dhcpmac_mt_save(const void *ip,
|
||||
DH_MAC_HEX(info->addr), info->mask);
|
||||
}
|
||||
|
||||
static void dhcpmac_mt_print(const void *ip,
|
||||
const struct xt_entry_match *match, int numeric)
|
||||
{
|
||||
printf(" -m dhcpmac");
|
||||
dhcpmac_mt_save(ip, match);
|
||||
}
|
||||
|
||||
static struct xtables_match dhcpmac_mt_reg = {
|
||||
.version = XTABLES_VERSION,
|
||||
.name = "dhcpmac",
|
||||
|
@@ -83,15 +83,6 @@ static void fuzzy_mt_check(unsigned int flags)
|
||||
{
|
||||
}
|
||||
|
||||
static void fuzzy_mt_print(const void *ip, const struct xt_entry_match *match,
|
||||
int numeric)
|
||||
{
|
||||
const struct xt_fuzzy_mtinfo *info = (const void *)match->data;
|
||||
|
||||
printf(" fuzzy: lower limit = %u pps - upper limit = %u pps ",
|
||||
info->minimum_rate, info->maximum_rate);
|
||||
}
|
||||
|
||||
static void fuzzy_mt_save(const void *ip, const struct xt_entry_match *match)
|
||||
{
|
||||
const struct xt_fuzzy_mtinfo *info = (const void *)match->data;
|
||||
@@ -100,6 +91,13 @@ static void fuzzy_mt_save(const void *ip, const struct xt_entry_match *match)
|
||||
printf(" --upper-limit %u ", info->maximum_rate);
|
||||
}
|
||||
|
||||
static void fuzzy_mt_print(const void *ip, const struct xt_entry_match *match,
|
||||
int numeric)
|
||||
{
|
||||
printf(" -m fuzzy");
|
||||
fuzzy_mt_save(ip, match);
|
||||
}
|
||||
|
||||
static struct xtables_match fuzzy_mt_reg = {
|
||||
.name = "fuzzy",
|
||||
.revision = 1,
|
||||
|
@@ -1,3 +1,4 @@
|
||||
.PP
|
||||
This module matches a rate limit based on a fuzzy logic controller (FLC).
|
||||
.TP
|
||||
\fB\-\-lower\-limit\fP \fInumber\fP
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* "geoip" match extension for iptables
|
||||
* Copyright © Samuel Jean <peejix [at] people netfilter org>, 2004 - 2008
|
||||
* Copyright © Nicolas Bouliane <acidfu [at] people netfilter org>, 2004 - 2008
|
||||
* Jan Engelhardt <jengelh [at] medozas de>, 2008-2011
|
||||
* Jan Engelhardt, 2008-2011
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License; either
|
||||
@@ -49,30 +49,44 @@ static struct option geoip_opts[] = {
|
||||
{NULL},
|
||||
};
|
||||
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
static void geoip_swap_le32(uint32_t *buf)
|
||||
{
|
||||
unsigned char *p = (void *)buf;
|
||||
uint32_t n = p[0] + (p[1] << 8) + (p[2] << 16) + (p[3] << 24);
|
||||
p[0] = (n >> 24) & 0xff;
|
||||
p[1] = (n >> 16) & 0xff;
|
||||
p[2] = (n >> 8) & 0xff;
|
||||
p[3] = n & 0xff;
|
||||
}
|
||||
|
||||
static void geoip_swap_in6(struct in6_addr *in6)
|
||||
{
|
||||
geoip_swap_le32(&in6->s6_addr32[0]);
|
||||
geoip_swap_le32(&in6->s6_addr32[1]);
|
||||
geoip_swap_le32(&in6->s6_addr32[2]);
|
||||
geoip_swap_le32(&in6->s6_addr32[3]);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void *
|
||||
geoip_get_subnets(const char *code, uint32_t *count, uint8_t nfproto)
|
||||
{
|
||||
void *subnets;
|
||||
struct stat sb;
|
||||
char buf[256];
|
||||
int fd;
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
unsigned int n;
|
||||
#endif
|
||||
|
||||
/* Use simple integer vector files */
|
||||
if (nfproto == NFPROTO_IPV6) {
|
||||
#if __BYTE_ORDER == _BIG_ENDIAN
|
||||
snprintf(buf, sizeof(buf), GEOIP_DB_DIR "/BE/%s.iv6", code);
|
||||
#else
|
||||
snprintf(buf, sizeof(buf), GEOIP_DB_DIR "/LE/%s.iv6", code);
|
||||
#endif
|
||||
} else {
|
||||
#if __BYTE_ORDER == _BIG_ENDIAN
|
||||
snprintf(buf, sizeof(buf), GEOIP_DB_DIR "/BE/%s.iv4", code);
|
||||
#else
|
||||
snprintf(buf, sizeof(buf), GEOIP_DB_DIR "/LE/%s.iv4", code);
|
||||
#endif
|
||||
}
|
||||
if (nfproto == NFPROTO_IPV6)
|
||||
snprintf(buf, sizeof(buf), GEOIP_DB_DIR "/%s.iv6", code);
|
||||
else
|
||||
snprintf(buf, sizeof(buf), GEOIP_DB_DIR "/%s.iv4", code);
|
||||
|
||||
if ((fd = open(buf, O_RDONLY)) < 0) {
|
||||
int fd = open(buf, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "Could not open %s: %s\n", buf, strerror(errno));
|
||||
xtables_error(OTHER_PROBLEM, "Could not read geoip database");
|
||||
}
|
||||
@@ -98,6 +112,25 @@ geoip_get_subnets(const char *code, uint32_t *count, uint8_t nfproto)
|
||||
xtables_error(OTHER_PROBLEM, "geoip: insufficient memory");
|
||||
read(fd, subnets, sb.st_size);
|
||||
close(fd);
|
||||
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
for (n = 0; n < *count; ++n) {
|
||||
switch (nfproto) {
|
||||
case NFPROTO_IPV6: {
|
||||
struct geoip_subnet6 *gs6 = &(((struct geoip_subnet6 *)subnets)[n]);
|
||||
geoip_swap_in6(&gs6->begin);
|
||||
geoip_swap_in6(&gs6->end);
|
||||
break;
|
||||
}
|
||||
case NFPROTO_IPV4: {
|
||||
struct geoip_subnet4 *gs4 = &(((struct geoip_subnet4 *)subnets)[n]);
|
||||
geoip_swap_le32(&gs4->begin);
|
||||
geoip_swap_le32(&gs4->end);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return subnets;
|
||||
}
|
||||
|
||||
@@ -170,7 +203,8 @@ static unsigned int parse_geoip_cc(const char *ccstr, uint16_t *cc,
|
||||
next = strchr(cp, ',');
|
||||
if (next) *next++ = '\0';
|
||||
|
||||
if ((cctmp = check_geoip_cc(cp, cc, count)) != 0) {
|
||||
cctmp = check_geoip_cc(cp, cc, count);
|
||||
if (cctmp != 0) {
|
||||
if ((mem[count++].user =
|
||||
(unsigned long)geoip_load_cc(cp, cctmp, nfproto)) == 0)
|
||||
xtables_error(OTHER_PROBLEM,
|
||||
@@ -251,31 +285,6 @@ geoip_final_check(unsigned int flags)
|
||||
"geoip: missing arguments");
|
||||
}
|
||||
|
||||
static void
|
||||
geoip_print(const void *ip, const struct xt_entry_match *match, int numeric)
|
||||
{
|
||||
const struct xt_geoip_match_info *info = (void*)match->data;
|
||||
|
||||
u_int8_t i;
|
||||
|
||||
if (info->flags & XT_GEOIP_SRC)
|
||||
printf(" Source ");
|
||||
else
|
||||
printf(" Destination ");
|
||||
|
||||
if (info->count > 1)
|
||||
printf("countries: ");
|
||||
else
|
||||
printf("country: ");
|
||||
|
||||
if (info->flags & XT_GEOIP_INV)
|
||||
printf("! ");
|
||||
|
||||
for (i = 0; i < info->count; i++)
|
||||
printf("%s%c%c", i ? "," : "", COUNTRY(info->cc[i]));
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
static void
|
||||
geoip_save(const void *ip, const struct xt_entry_match *match)
|
||||
{
|
||||
@@ -295,6 +304,13 @@ geoip_save(const void *ip, const struct xt_entry_match *match)
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
static void
|
||||
geoip_print(const void *ip, const struct xt_entry_match *match, int numeric)
|
||||
{
|
||||
printf(" -m geoip");
|
||||
geoip_save(ip, match);
|
||||
}
|
||||
|
||||
static struct xtables_match geoip_match[] = {
|
||||
{
|
||||
.family = NFPROTO_IPV6,
|
||||
|
@@ -1,3 +1,4 @@
|
||||
.PP
|
||||
Match a packet by its source or destination country.
|
||||
.TP
|
||||
[\fB!\fP] \fB\-\-src\-cc\fP, \fB\-\-source\-country\fP \fIcountry\fP[\fB,\fP\fIcountry\fP\fB...\fP]
|
||||
@@ -15,8 +16,8 @@ with the source package, and which should be available in compiled packages in
|
||||
/usr/lib(exec)/xtables-addons/. The first command retrieves CSV files from
|
||||
MaxMind, while the other two build packed bisectable range files:
|
||||
.PP
|
||||
mkdir -p /usr/share/xt_geoip; cd /tmp; $path/to/xt_geoip_dl;
|
||||
mkdir \-p /usr/share/xt_geoip; cd /tmp; $path/to/xt_geoip_dl;
|
||||
.PP
|
||||
$path/to/xt_geoip_build -D /usr/share/xt_geoip GeoIP*.csv;
|
||||
$path/to/xt_geoip_build \-D /usr/share/xt_geoip GeoIP*.csv;
|
||||
.PP
|
||||
The shared library is hardcoded to look in these paths, so use them.
|
||||
|
@@ -57,17 +57,6 @@ static void gradm_mt_check(unsigned int flags)
|
||||
{
|
||||
}
|
||||
|
||||
static void gradm_mt_print(const void *ip, const struct xt_entry_match *match,
|
||||
int numeric)
|
||||
{
|
||||
const struct xt_gradm_mtinfo *info = (const void *)match->data;
|
||||
|
||||
if (info->invflags)
|
||||
printf("gradm: disabled");
|
||||
else
|
||||
printf("gradm: enabled");
|
||||
}
|
||||
|
||||
static void gradm_mt_save(const void *ip, const struct xt_entry_match *match)
|
||||
{
|
||||
const struct xt_gradm_mtinfo *info = (const void *)match->data;
|
||||
@@ -78,6 +67,13 @@ static void gradm_mt_save(const void *ip, const struct xt_entry_match *match)
|
||||
printf(" --enabled ");
|
||||
}
|
||||
|
||||
static void gradm_mt_print(const void *ip, const struct xt_entry_match *match,
|
||||
int numeric)
|
||||
{
|
||||
printf(" -m gradm");
|
||||
gradm_mt_save(ip, match);
|
||||
}
|
||||
|
||||
static struct xtables_match gradm_mt_reg = {
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.name = "gradm",
|
||||
|
@@ -1,3 +1,4 @@
|
||||
.PP
|
||||
This module matches packets based on grsecurity RBAC status.
|
||||
.TP
|
||||
[\fB!\fP] \fB\-\-enabled\fP
|
||||
|
@@ -175,33 +175,6 @@ static void iface_mt_check(unsigned int flags)
|
||||
"iface: You must specify at least one option");
|
||||
}
|
||||
|
||||
static void iface_mt_print(const void *ip, const struct xt_entry_match *match,
|
||||
int numeric)
|
||||
{
|
||||
const struct xt_iface_mtinfo *info = (const void *)match->data;
|
||||
|
||||
printf(" iface: ");
|
||||
if (info->flags & XT_IFACE_DEV_IN)
|
||||
printf("(in)");
|
||||
else if (info->flags & XT_IFACE_DEV_OUT)
|
||||
printf("(out)");
|
||||
else
|
||||
printf("%s", info->ifname);
|
||||
printf(" [state:");
|
||||
iface_print_opt(info, XT_IFACE_UP, "up");
|
||||
iface_print_opt(info, XT_IFACE_BROADCAST, "broadcast");
|
||||
iface_print_opt(info, XT_IFACE_LOOPBACK, "loopback");
|
||||
iface_print_opt(info, XT_IFACE_POINTOPOINT, "pointopoint");
|
||||
iface_print_opt(info, XT_IFACE_RUNNING, "running");
|
||||
iface_print_opt(info, XT_IFACE_NOARP, "noarp");
|
||||
iface_print_opt(info, XT_IFACE_PROMISC, "promisc");
|
||||
iface_print_opt(info, XT_IFACE_MULTICAST, "multicast");
|
||||
iface_print_opt(info, XT_IFACE_DYNAMIC, "dynamic");
|
||||
iface_print_opt(info, XT_IFACE_LOWER_UP, "lower_up");
|
||||
iface_print_opt(info, XT_IFACE_DORMANT, "dormant");
|
||||
printf("] ");
|
||||
}
|
||||
|
||||
static void iface_mt_save(const void *ip, const struct xt_entry_match *match)
|
||||
{
|
||||
const struct xt_iface_mtinfo *info = (const void *)match->data;
|
||||
@@ -226,6 +199,13 @@ static void iface_mt_save(const void *ip, const struct xt_entry_match *match)
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
static void iface_mt_print(const void *ip, const struct xt_entry_match *match,
|
||||
int numeric)
|
||||
{
|
||||
printf(" -m iface");
|
||||
iface_mt_save(ip, match);
|
||||
}
|
||||
|
||||
static struct xtables_match iface_mt_reg = {
|
||||
.version = XTABLES_VERSION,
|
||||
.name = "iface",
|
||||
|
@@ -1,3 +1,4 @@
|
||||
.PP
|
||||
Allows you to check interface states. First, an interface needs to be selected
|
||||
for comparison. Exactly one option of the following three must be specified:
|
||||
.TP
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* "ipp2p" match extension for iptables
|
||||
* Eicke Friedrich/Klaus Degner <ipp2p@ipp2p.org>, 2005 - 2006
|
||||
* Jan Engelhardt <jengelh [at] medozas de>, 2008 - 2009
|
||||
* Jan Engelhardt, 2008 - 2009
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License; either
|
||||
@@ -217,7 +217,7 @@ ipp2p_mt_print1(const void *entry, const struct xt_entry_match *match,
|
||||
static void ipp2p_mt_print(const void *entry,
|
||||
const struct xt_entry_match *match, int numeric)
|
||||
{
|
||||
printf(" ipp2p ");
|
||||
printf(" -m ipp2p ");
|
||||
ipp2p_mt_print1(entry, match, true);
|
||||
}
|
||||
|
||||
|
@@ -1,3 +1,4 @@
|
||||
.PP
|
||||
This module matches certain packets in P2P flows. It is not
|
||||
designed to match all packets belonging to a P2P connection \(em
|
||||
use IPP2P together with CONNMARK for this purpose.
|
||||
|
@@ -133,17 +133,6 @@ static void ipv4options_print_flags(const struct xt_ipv4options_mtinfo1 *info,
|
||||
}
|
||||
}
|
||||
|
||||
static void ipv4options_mt_print(const void *ip,
|
||||
const struct xt_entry_match *match, int numeric)
|
||||
{
|
||||
const struct xt_ipv4options_mtinfo1 *info = (void *)match->data;
|
||||
|
||||
printf(" ipv4options %s ",
|
||||
(info->flags & XT_V4OPTS_ANY) ? "any-of" : "all-of");
|
||||
ipv4options_print_flags(info, numeric);
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
static void ipv4options_mt_save(const void *ip,
|
||||
const struct xt_entry_match *match)
|
||||
{
|
||||
@@ -158,6 +147,13 @@ static void ipv4options_mt_save(const void *ip,
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
static void ipv4options_mt_print(const void *ip,
|
||||
const struct xt_entry_match *match, int numeric)
|
||||
{
|
||||
printf(" -m ipv4options");
|
||||
ipv4options_mt_save(ip, match);
|
||||
}
|
||||
|
||||
static struct xtables_match ipv4options_mt_reg = {
|
||||
.version = XTABLES_VERSION,
|
||||
.name = "ipv4options",
|
||||
|
@@ -1,3 +1,4 @@
|
||||
.PP
|
||||
The "ipv4options" module allows to match against a set of IPv4 header options.
|
||||
.TP
|
||||
\fB\-\-flags\fP [\fB!\fP]\fIsymbol\fP[\fB,\fP[\fB!\fP]\fIsymbol...\fP]
|
||||
|
@@ -107,29 +107,6 @@ static void length_mt_check(unsigned int flags)
|
||||
"--layer3. Consider specifying it explicitly.\n");
|
||||
}
|
||||
|
||||
static void length_mt_print(const void *ip, const struct xt_entry_match *match,
|
||||
int numeric)
|
||||
{
|
||||
const struct xt_length_mtinfo2 *info = (const void *)match->data;
|
||||
|
||||
if (info->flags & XT_LENGTH_LAYER3)
|
||||
printf(" layer3 ");
|
||||
else if (info->flags & XT_LENGTH_LAYER4)
|
||||
printf(" layer4 ");
|
||||
else if (info->flags & XT_LENGTH_LAYER5)
|
||||
printf(" layer5 ");
|
||||
else if (info->flags & XT_LENGTH_LAYER7)
|
||||
printf(" layer7 ");
|
||||
printf(" length ");
|
||||
if (info->flags & XT_LENGTH_INVERT)
|
||||
printf("! ");
|
||||
if (info->min == info->max)
|
||||
printf("%u ", (unsigned int)info->min);
|
||||
else
|
||||
printf("%u-%u ", (unsigned int)info->min,
|
||||
(unsigned int)info->max);
|
||||
}
|
||||
|
||||
static void length_mt_save(const void *ip, const struct xt_entry_match *match)
|
||||
{
|
||||
const struct xt_length_mtinfo2 *info = (const void *)match->data;
|
||||
@@ -152,6 +129,13 @@ static void length_mt_save(const void *ip, const struct xt_entry_match *match)
|
||||
(unsigned int)info->max);
|
||||
}
|
||||
|
||||
static void length_mt_print(const void *ip, const struct xt_entry_match *match,
|
||||
int numeric)
|
||||
{
|
||||
printf(" -m length2");
|
||||
length_mt_save(ip, match);
|
||||
}
|
||||
|
||||
static struct xtables_match length2_mt_reg = {
|
||||
.version = XTABLES_VERSION,
|
||||
.name = "length2",
|
||||
|
@@ -1,3 +1,4 @@
|
||||
.PP
|
||||
This module matches the length of a packet against a specific value or range of
|
||||
values.
|
||||
.TP
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* LSCAN match extension for iptables
|
||||
* Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2006 - 2009
|
||||
* Copyright © Jan Engelhardt, 2006 - 2009
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License; either
|
||||
@@ -24,6 +24,7 @@ static const struct option lscan_mt_opts[] = {
|
||||
{.name = "synscan", .has_arg = false, .val = 's'},
|
||||
{.name = "cnscan", .has_arg = false, .val = 'c'},
|
||||
{.name = "grscan", .has_arg = false, .val = 'g'},
|
||||
{.name = "mirai", .has_arg = false, .val = 'm'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
@@ -35,7 +36,8 @@ static void lscan_mt_help(void)
|
||||
" --stealth Match TCP Stealth packets\n"
|
||||
" --synscan Match TCP SYN scans\n"
|
||||
" --cnscan Match TCP Connect scans\n"
|
||||
" --grscan Match Banner Grabbing scans\n");
|
||||
" --grscan Match Banner Grabbing scans\n"
|
||||
" --mirai Match TCP scan with ISN = dest. IP\n");
|
||||
}
|
||||
|
||||
static int lscan_mt_parse(int c, char **argv, int invert,
|
||||
@@ -45,16 +47,19 @@ static int lscan_mt_parse(int c, char **argv, int invert,
|
||||
|
||||
switch (c) {
|
||||
case 'c':
|
||||
info->match_cn = true;
|
||||
info->match_fl3 |= LSCAN_FL3_CN;
|
||||
return true;
|
||||
case 'g':
|
||||
info->match_gr = true;
|
||||
info->match_fl4 |= LSCAN_FL4_GR;
|
||||
return true;
|
||||
case 'm':
|
||||
info->match_fl1 |= LSCAN_FL1_MIRAI;
|
||||
return true;
|
||||
case 's':
|
||||
info->match_syn = true;
|
||||
info->match_fl2 |= LSCAN_FL2_SYN;
|
||||
return true;
|
||||
case 'x':
|
||||
info->match_stealth = true;
|
||||
info->match_fl1 |= LSCAN_FL1_STEALTH;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -64,42 +69,27 @@ static void lscan_mt_check(unsigned int flags)
|
||||
{
|
||||
}
|
||||
|
||||
static void lscan_mt_print(const void *ip,
|
||||
const struct xt_entry_match *match, int numeric)
|
||||
{
|
||||
const struct xt_lscan_mtinfo *info = (const void *)(match->data);
|
||||
const char *s = "";
|
||||
|
||||
printf(" lscan ");
|
||||
if (info->match_stealth) {
|
||||
printf("STEALTH");
|
||||
s = ",";
|
||||
}
|
||||
if (info->match_syn) {
|
||||
printf("%sSYNSCAN", s);
|
||||
s = ",";
|
||||
}
|
||||
if (info->match_cn) {
|
||||
printf("%sCNSCAN", s);
|
||||
s = ",";
|
||||
}
|
||||
if (info->match_gr)
|
||||
printf("%sGRSCAN", s);
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
static void lscan_mt_save(const void *ip, const struct xt_entry_match *match)
|
||||
{
|
||||
const struct xt_lscan_mtinfo *info = (const void *)(match->data);
|
||||
|
||||
if (info->match_stealth)
|
||||
if (info->match_fl1 & LSCAN_FL1_STEALTH)
|
||||
printf(" --stealth ");
|
||||
if (info->match_syn)
|
||||
if (info->match_fl2 & LSCAN_FL2_SYN)
|
||||
printf(" --synscan ");
|
||||
if (info->match_cn)
|
||||
if (info->match_fl3 & LSCAN_FL3_CN)
|
||||
printf(" --cnscan ");
|
||||
if (info->match_gr)
|
||||
if (info->match_fl4 & LSCAN_FL4_GR)
|
||||
printf(" --grscan ");
|
||||
if (info->match_fl1 & LSCAN_FL1_MIRAI)
|
||||
printf(" --mirai ");
|
||||
}
|
||||
|
||||
static void lscan_mt_print(const void *ip,
|
||||
const struct xt_entry_match *match, int numeric)
|
||||
{
|
||||
printf(" -m lscan");
|
||||
lscan_mt_save(ip, match);
|
||||
}
|
||||
|
||||
static struct xtables_match lscan_mt_reg = {
|
||||
|
@@ -1,4 +1,5 @@
|
||||
Detects simple low-level scan attemps based upon the packet's contents.
|
||||
.PP
|
||||
Detects simple low-level scan attempts based upon the packet's contents.
|
||||
(This is
|
||||
different from other implementations, which also try to match the rate of new
|
||||
connections.) Note that an attempt is only discovered after it has been carried
|
||||
@@ -26,6 +27,11 @@ warranted single-direction data flows, usually bulk data transfers such as
|
||||
FTP DATA connections or IRC DCC. Grab Scan Detection should only be used on
|
||||
ports where a protocol runs that is guaranteed to do a bidirectional exchange
|
||||
of bytes.
|
||||
.TP
|
||||
\fB\-\-mirai\fP
|
||||
Match if the TCP ISN is equal to the IPv4 destination address; this is used
|
||||
by the devices in the Mirai botnet as a form of TCP SYN scan, so you will
|
||||
have to explicitly specify --syn for the rule.
|
||||
.PP
|
||||
NOTE: Some clients (Windows XP for example) may do what looks like a SYN scan,
|
||||
so be advised to carefully use xt_lscan in conjunction with blocking rules,
|
||||
|
@@ -117,18 +117,6 @@ static int psd_mt_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
/* Final check; nothing. */
|
||||
static void psd_mt_final_check(unsigned int flags) {}
|
||||
|
||||
/* Prints out the targinfo. */
|
||||
static void psd_mt_print(const void *ip, const struct xt_entry_match *match, int numeric)
|
||||
{
|
||||
const struct xt_psd_info *psdinfo = (const struct xt_psd_info *)match->data;
|
||||
printf(" psd ");
|
||||
printf("weight-threshold: %u ", psdinfo->weight_threshold);
|
||||
printf("delay-threshold: %u ", psdinfo->delay_threshold);
|
||||
printf("lo-ports-weight: %u ", psdinfo->lo_ports_weight);
|
||||
printf("hi-ports-weight: %u ", psdinfo->hi_ports_weight);
|
||||
}
|
||||
|
||||
/* Saves the union ipt_targinfo in parsable form to stdout. */
|
||||
static void psd_mt_save(const void *ip, const struct xt_entry_match *match)
|
||||
{
|
||||
const struct xt_psd_info *psdinfo = (const struct xt_psd_info *)match->data;
|
||||
@@ -138,6 +126,12 @@ static void psd_mt_save(const void *ip, const struct xt_entry_match *match)
|
||||
printf("--psd-hi-ports-weight %u ", psdinfo->hi_ports_weight);
|
||||
}
|
||||
|
||||
static void psd_mt_print(const void *ip, const struct xt_entry_match *match, int numeric)
|
||||
{
|
||||
printf(" -m psd");
|
||||
psd_mt_save(ip, match);
|
||||
}
|
||||
|
||||
static struct xtables_match psd_mt_reg = {
|
||||
.name = "psd",
|
||||
.version = XTABLES_VERSION,
|
||||
|
@@ -1,3 +1,4 @@
|
||||
.PP
|
||||
Attempt to detect TCP and UDP port scans. This match was derived from
|
||||
Solar Designer's scanlogd.
|
||||
.TP
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* "quota2" match extension for iptables
|
||||
* Sam Johnston <samj [at] samj net>
|
||||
* Jan Engelhardt <jengelh [at] medozas de>, 2008
|
||||
* Jan Engelhardt, 2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License; either
|
||||
@@ -70,7 +70,7 @@ quota_mt2_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
/* zero termination done on behalf of the kernel module */
|
||||
xtables_param_act(XTF_ONLY_ONCE, "quota", "--name", *flags & FL_NAME);
|
||||
xtables_param_act(XTF_NO_INVERT, "quota", "--name", invert);
|
||||
strncpy(info->name, optarg, sizeof(info->name));
|
||||
snprintf(info->name, sizeof(info->name), "%s", optarg);
|
||||
*flags |= FL_NAME;
|
||||
return true;
|
||||
case 'p':
|
||||
@@ -98,8 +98,6 @@ quota_mt2_save(const void *ip, const struct xt_entry_match *match)
|
||||
{
|
||||
const struct xt_quota_mtinfo2 *q = (void *)match->data;
|
||||
|
||||
if (q->flags & XT_QUOTA_INVERT)
|
||||
printf(" !");
|
||||
if (q->flags & XT_QUOTA_GROW)
|
||||
printf(" --grow ");
|
||||
if (q->flags & XT_QUOTA_NO_CHANGE)
|
||||
@@ -108,29 +106,16 @@ quota_mt2_save(const void *ip, const struct xt_entry_match *match)
|
||||
printf(" --packets ");
|
||||
if (*q->name != '\0')
|
||||
printf(" --name %s ", q->name);
|
||||
if (q->flags & XT_QUOTA_INVERT)
|
||||
printf(" !");
|
||||
printf(" --quota %llu ", (unsigned long long)q->quota);
|
||||
}
|
||||
|
||||
static void quota_mt2_print(const void *ip, const struct xt_entry_match *match,
|
||||
int numeric)
|
||||
{
|
||||
const struct xt_quota_mtinfo2 *q = (const void *)match->data;
|
||||
|
||||
if (q->flags & XT_QUOTA_INVERT)
|
||||
printf(" !");
|
||||
if (q->flags & XT_QUOTA_GROW)
|
||||
printf(" counter");
|
||||
else
|
||||
printf(" quota");
|
||||
if (*q->name != '\0')
|
||||
printf(" %s:", q->name);
|
||||
printf(" %llu ", (unsigned long long)q->quota);
|
||||
if (q->flags & XT_QUOTA_PACKET)
|
||||
printf("packets ");
|
||||
else
|
||||
printf("bytes ");
|
||||
if (q->flags & XT_QUOTA_NO_CHANGE)
|
||||
printf("(no-change mode) ");
|
||||
printf(" -m quota");
|
||||
quota_mt2_save(ip, match);
|
||||
}
|
||||
|
||||
static struct xtables_match quota_mt2_reg = {
|
||||
|
@@ -1,3 +1,4 @@
|
||||
.PP
|
||||
The "quota2" implements a named counter which can be increased or decreased
|
||||
on a per-match basis. Available modes are packet counting or byte counting.
|
||||
The value of the counter can be read and reset through procfs, thereby making
|
||||
|
@@ -5,4 +5,5 @@ AM_CFLAGS = ${regular_CFLAGS} ${libxtables_CFLAGS}
|
||||
|
||||
include ../../Makefile.extra
|
||||
|
||||
noinst_PROGRAMS = pknlusr
|
||||
sbin_PROGRAMS = pknlusr
|
||||
dist_man_MANS = pknlusr.8
|
||||
|
17
extensions/pknock/gen_hmac.py
Normal file
17
extensions/pknock/gen_hmac.py
Normal file
@@ -0,0 +1,17 @@
|
||||
from Crypto.Hash import SHA256
|
||||
from Crypto.Hash import MD5
|
||||
import sys
|
||||
import hmac
|
||||
import struct
|
||||
import socket
|
||||
from time import time
|
||||
|
||||
def gen_hmac(secret, ip):
|
||||
epoch_mins = (long)(time()/60)
|
||||
s = hmac.HMAC(secret, digestmod = SHA256)
|
||||
s.update(socket.inet_aton(socket.gethostbyname(ip)))
|
||||
s.update(struct.pack("i", epoch_mins)) # "i" is for integer
|
||||
print s.hexdigest()
|
||||
|
||||
if __name__ == '__main__':
|
||||
gen_hmac(sys.argv[1], sys.argv[2])
|
6
extensions/pknock/knock.sh
Executable file
6
extensions/pknock/knock.sh
Executable file
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
if [ "$#" -ne 4 ]; then
|
||||
echo "usage: $0 <IP src> <IP dst> <PORT dst> <secret>"
|
||||
exit 1
|
||||
fi
|
||||
python gen_hmac.py "$4" "$1" | socat - "udp-sendto:$2:$3,bind=$1"
|
@@ -11,7 +11,6 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
@@ -34,17 +33,22 @@ static const struct option pknock_mt_opts[] = {
|
||||
static void pknock_mt_help(void)
|
||||
{
|
||||
printf("pknock match options:\n"
|
||||
" --knockports port[,port,port,...] "
|
||||
"Matches destination port(s).\n"
|
||||
" --time seconds\n"
|
||||
" --knockports port[,port[,port[,...]]]\n"
|
||||
"\t\t\t\tMatches destination port(s).\n"
|
||||
" --time seconds "
|
||||
"Max allowed time between knocks.\n"
|
||||
" --autoclose minutes\n"
|
||||
" --autoclose minutes "
|
||||
"Time after which to automatically close opened\n"
|
||||
"\t\t\t\t\tport(s).\n"
|
||||
" --strict "
|
||||
"Knocks sequence must be exact.\n"
|
||||
"\t\t\t\tport(s).\n"
|
||||
" --name rule_name "
|
||||
"Rule name.\n"
|
||||
" --opensecret secret "
|
||||
"(UDP only) Secret to activate the rule.\n"
|
||||
" --closesecret secret "
|
||||
"(UDP only) Secret to deactivate the\n"
|
||||
"\t\t\t\trule.\n"
|
||||
" --strict "
|
||||
"Knocks sequence must be exact.\n"
|
||||
" --checkip "
|
||||
"Matches if the source ip is in the list.\n"
|
||||
);
|
||||
@@ -70,7 +74,6 @@ parse_ports(const char *portstring, uint16_t *ports, const char *proto)
|
||||
|
||||
if (cp != NULL)
|
||||
xtables_error(PARAMETER_PROBLEM, "too many ports specified");
|
||||
|
||||
free(buffer);
|
||||
return i;
|
||||
}
|
||||
@@ -91,12 +94,11 @@ proto_to_name(uint8_t proto)
|
||||
static const char *
|
||||
check_proto(uint16_t pnum, uint8_t invflags)
|
||||
{
|
||||
char *proto;
|
||||
|
||||
if (invflags & XT_INV_PROTO)
|
||||
xtables_error(PARAMETER_PROBLEM, PKNOCK "only works with TCP and UDP.");
|
||||
|
||||
if ((proto = proto_to_name(pnum)) != NULL)
|
||||
const char *proto = proto_to_name(pnum);
|
||||
if (proto != NULL)
|
||||
return proto;
|
||||
else if (pnum == 0)
|
||||
xtables_error(PARAMETER_PROBLEM, PKNOCK "needs `-p tcp' or `-p udp'");
|
||||
@@ -123,7 +125,7 @@ __pknock_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
info->ports_count = parse_ports(optarg, info->port, proto);
|
||||
info->option |= XT_PKNOCK_KNOCKPORT;
|
||||
*flags |= XT_PKNOCK_KNOCKPORT;
|
||||
#if DEBUG
|
||||
#ifdef DEBUG
|
||||
printf("ports_count: %d\n", info->ports_count);
|
||||
#endif
|
||||
break;
|
||||
@@ -162,7 +164,7 @@ __pknock_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
info->rule_name_len = strlen(info->rule_name);
|
||||
info->option |= XT_PKNOCK_NAME;
|
||||
*flags |= XT_PKNOCK_NAME;
|
||||
#if DEBUG
|
||||
#ifdef DEBUG
|
||||
printf("info->rule_name: %s\n", info->rule_name);
|
||||
#endif
|
||||
break;
|
||||
@@ -213,7 +215,6 @@ __pknock_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
|
||||
if (invert)
|
||||
xtables_error(PARAMETER_PROBLEM, PKNOCK "does not support invert.");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@@ -15,10 +15,10 @@ modprobe xt_pknock
|
||||
.PP
|
||||
Example 1 (TCP mode, manual closing of opened port not possible):
|
||||
.IP
|
||||
iptables -P INPUT DROP
|
||||
iptables \-P INPUT DROP
|
||||
.IP
|
||||
iptables -A INPUT -p tcp -m pknock --knockports 4002,4001,4004 --strict
|
||||
--name SSH --time 10 --autoclose 60 --dport 22 -j ACCEPT
|
||||
iptables \-A INPUT \-p tcp \-m pknock \-\-knockports 4002,4001,4004 \-\-strict
|
||||
\-\-name SSH \-\-time 10 \-\-autoclose 60 \-\-dport 22 \-j ACCEPT
|
||||
.PP
|
||||
The rule will allow tcp port 22 for the attempting IP address after the successful reception of TCP SYN packets
|
||||
to ports 4002, 4001 and 4004, in this order (a.k.a. port-knocking).
|
||||
@@ -33,10 +33,10 @@ Example 2 (UDP mode \(em non-replayable and non-spoofable, manual closing
|
||||
of opened port possible, secure, also called "SPA" = Secure Port
|
||||
Authorization):
|
||||
.IP
|
||||
iptables -A INPUT -p udp -m pknock --knockports 4000 --name FTP
|
||||
--opensecret foo --closesecret bar --autoclose 240 -j DROP
|
||||
iptables \-A INPUT \-p udp \-m pknock \-\-knockports 4000 \-\-name FTP
|
||||
\-\-opensecret foo \-\-closesecret bar \-\-autoclose 240 \-j DROP
|
||||
.IP
|
||||
iptables -A INPUT -p tcp -m pknock --checkip --name FTP --dport 21 -j ACCEPT
|
||||
iptables \-A INPUT \-p tcp \-m pknock \-\-checkip \-\-name FTP \-\-dport 21 \-j ACCEPT
|
||||
.PP
|
||||
The first rule will create an "ALLOWED" record in /proc/net/xt_pknock/FTP after
|
||||
the successful reception of an UDP packet to port 4000. The packet payload must be
|
||||
@@ -62,8 +62,6 @@ Specifying \fB--autoclose 0\fP means that no automatic close will be performed a
|
||||
xt_pknock is capable of sending information about successful matches
|
||||
via a netlink socket to userspace, should you need to implement your own
|
||||
way of receiving and handling portknock notifications.
|
||||
Be sure to read the documentation in the doc/pknock/ directory,
|
||||
or visit the original site \(em http://portknocko.berlios.de/ .
|
||||
.PP
|
||||
\fBTCP mode\fP:
|
||||
.PP
|
||||
|
18
extensions/pknock/pknlusr.8
Normal file
18
extensions/pknock/pknlusr.8
Normal file
@@ -0,0 +1,18 @@
|
||||
.TH pknlusr 8 "2020-10-22" "xtables-addons" "xtables-addons"
|
||||
.SH NAME
|
||||
.PP
|
||||
pknlusr \(em userspace monitor for successful xt_pknock matches
|
||||
.SH Synopsis
|
||||
.PP
|
||||
\fBpknlusr\fP [\fIgroup-id\fP]
|
||||
.SH Description
|
||||
\fIxt_pknock\fP is an xtables match extension that implements so-called \fIport
|
||||
knocking\fP. It can be configured to send information about each successful
|
||||
match via a netlink socket to userspace. \fBpknluser\fP listens for these
|
||||
notifications.
|
||||
.PP
|
||||
By default, \fBpknlusr\fP listens for messages sent to netlink multicast group
|
||||
1. Another group ID may be passed as a command-line argument.
|
||||
.SH See also
|
||||
.PP
|
||||
xtables-addons(8)
|
@@ -7,85 +7,94 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/connector.h>
|
||||
#include <errno.h>
|
||||
#include <libgen.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "xt_pknock.h"
|
||||
|
||||
#define GROUP 1
|
||||
#define DEFAULT_GROUP_ID 1
|
||||
#define MIN_GROUP_ID DEFAULT_GROUP_ID
|
||||
#define MAX_GROUP_ID \
|
||||
(sizeof((struct sockaddr_nl){0}.nl_groups) * CHAR_BIT)
|
||||
|
||||
static struct sockaddr_nl src_addr, dest_addr;
|
||||
static int sock_fd;
|
||||
|
||||
static unsigned char *buf;
|
||||
|
||||
static struct xt_pknock_nl_msg *nlmsg;
|
||||
|
||||
int main(void)
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
socklen_t addrlen;
|
||||
int status;
|
||||
int group = GROUP;
|
||||
unsigned int group_id = DEFAULT_GROUP_ID;
|
||||
struct sockaddr_nl local_addr = {.nl_family = AF_NETLINK};
|
||||
int sock_fd;
|
||||
size_t nlmsg_size;
|
||||
struct nlmgrhdr *nlmsg;
|
||||
struct cn_msg *cn_msg;
|
||||
struct xt_pknock_nl_msg *pknock_msg;
|
||||
|
||||
int buf_size;
|
||||
if (argc > 2) {
|
||||
char *prog = strdup(argv[0]);
|
||||
if (prog == NULL) {
|
||||
perror("strdup()");
|
||||
} else {
|
||||
fprintf(stderr, "%s [ group-id ]\n", basename(prog));
|
||||
free(prog);
|
||||
}
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
const char *ip;
|
||||
char ipbuf[48];
|
||||
if (argc == 2) {
|
||||
long n;
|
||||
char *end;
|
||||
|
||||
errno = 0;
|
||||
n = strtol(argv[1], &end, 10);
|
||||
if (*end || (errno && (n == LONG_MIN || n == LONG_MAX)) ||
|
||||
n < MIN_GROUP_ID || n > MAX_GROUP_ID) {
|
||||
fputs("Group ID invalid.\n", stderr);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
group_id = n;
|
||||
}
|
||||
|
||||
sock_fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
|
||||
|
||||
if (sock_fd == -1) {
|
||||
perror("socket()");
|
||||
return 1;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
memset(&src_addr, 0, sizeof(src_addr));
|
||||
src_addr.nl_family = AF_NETLINK;
|
||||
src_addr.nl_pid = getpid();
|
||||
src_addr.nl_groups = group;
|
||||
|
||||
status = bind(sock_fd, (struct sockaddr*)&src_addr, sizeof(src_addr));
|
||||
|
||||
local_addr.nl_groups = 1U << (group_id - 1);
|
||||
status = bind(sock_fd, (struct sockaddr *)&local_addr, sizeof(local_addr));
|
||||
if (status == -1) {
|
||||
close(sock_fd);
|
||||
perror("bind()");
|
||||
return 1;
|
||||
goto err_close_sock;
|
||||
}
|
||||
|
||||
memset(&dest_addr, 0, sizeof(dest_addr));
|
||||
dest_addr.nl_family = AF_NETLINK;
|
||||
dest_addr.nl_pid = 0;
|
||||
dest_addr.nl_groups = group;
|
||||
|
||||
buf_size = sizeof(struct xt_pknock_nl_msg) + sizeof(struct cn_msg) + sizeof(struct nlmsghdr);
|
||||
buf = malloc(buf_size);
|
||||
|
||||
if (!buf) {
|
||||
nlmsg_size = NLMSG_SPACE(sizeof(*cn_msg) + sizeof(*pknock_msg));
|
||||
nlmsg = malloc(nlmsg_size);
|
||||
if (!nlmsg) {
|
||||
perror("malloc()");
|
||||
return 1;
|
||||
goto err_close_sock;
|
||||
}
|
||||
|
||||
addrlen = sizeof(dest_addr);
|
||||
|
||||
while(1) {
|
||||
const char *ip;
|
||||
char ipbuf[INET_ADDRSTRLEN];
|
||||
|
||||
memset(buf, 0, buf_size);
|
||||
|
||||
status = recvfrom(sock_fd, buf, buf_size, 0, (struct sockaddr *)&dest_addr, &addrlen);
|
||||
|
||||
if (status <= 0) {
|
||||
perror("recvfrom()");
|
||||
return 1;
|
||||
}
|
||||
|
||||
nlmsg = (struct xt_pknock_nl_msg *) (buf + sizeof(struct cn_msg) + sizeof(struct nlmsghdr));
|
||||
|
||||
ip = inet_ntop(AF_INET, &nlmsg->peer_ip, ipbuf, sizeof(ipbuf));
|
||||
printf("rule_name: %s - ip %s\n", nlmsg->rule_name, ip);
|
||||
|
||||
memset(nlmsg, 0, nlmsg_size);
|
||||
status = recv(sock_fd, nlmsg, nlmsg_size, 0);
|
||||
if (status < 0) {
|
||||
perror("recv()");
|
||||
goto err_free_msg;
|
||||
}
|
||||
if (status == 0)
|
||||
break;
|
||||
cn_msg = NLMSG_DATA(nlmsg);
|
||||
pknock_msg = (struct xt_pknock_nl_msg *)(cn_msg->data);
|
||||
ip = inet_ntop(AF_INET, &pknock_msg->peer_ip, ipbuf, sizeof(ipbuf));
|
||||
printf("rule_name: %s - ip %s\n", pknock_msg->rule_name, ip);
|
||||
}
|
||||
|
||||
err_free_msg:
|
||||
free(nlmsg);
|
||||
err_close_sock:
|
||||
close(sock_fd);
|
||||
|
||||
free(buf);
|
||||
|
||||
return 0;
|
||||
exit(status == -1 ? EXIT_FAILURE : EXIT_SUCCESS);
|
||||
}
|
||||
|
@@ -19,23 +19,17 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/jhash.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/connector.h>
|
||||
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#include <crypto/hash.h>
|
||||
#include "xt_pknock.h"
|
||||
#include "compat_xtables.h"
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
|
||||
# define PK_CRYPTO 1
|
||||
#endif
|
||||
|
||||
enum status {
|
||||
ST_INIT = 1,
|
||||
ST_MATCHING,
|
||||
@@ -96,35 +90,27 @@ enum {
|
||||
#define hashtable_for_each_safe(pos, n, head, size, i) \
|
||||
for ((i) = 0; (i) < (size); ++(i)) \
|
||||
list_for_each_safe((pos), (n), (&head[(i)]))
|
||||
|
||||
#define pk_debug(msg, peer) pr_debug( \
|
||||
"(S) peer: " NIPQUAD_FMT " - %s.\n", \
|
||||
NIPQUAD((peer)->ip), msg)
|
||||
#define pk_debug(msg, peer) pr_debug("(S) peer: %pI4 - %s.\n", &((peer)->ip), msg)
|
||||
|
||||
static uint32_t ipt_pknock_hash_rnd;
|
||||
|
||||
static unsigned int rule_hashsize = DEFAULT_RULE_HASH_SIZE;
|
||||
static unsigned int peer_hashsize = DEFAULT_PEER_HASH_SIZE;
|
||||
static unsigned int gc_expir_time = DEFAULT_GC_EXPIRATION_TIME;
|
||||
static int nl_multicast_group = -1;
|
||||
|
||||
static struct list_head *rule_hashtable;
|
||||
static struct proc_dir_entry *pde;
|
||||
|
||||
static DEFINE_SPINLOCK(list_lock);
|
||||
|
||||
#ifdef PK_CRYPTO
|
||||
static struct {
|
||||
const char *algo;
|
||||
struct crypto_hash *tfm;
|
||||
struct crypto_shash *tfm;
|
||||
unsigned int size;
|
||||
struct hash_desc desc;
|
||||
struct shash_desc desc;
|
||||
} crypto = {
|
||||
.algo = "hmac(sha256)",
|
||||
.tfm = NULL,
|
||||
.size = 0
|
||||
};
|
||||
#endif
|
||||
|
||||
module_param(rule_hashsize, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(rule_hashsize, "Buckets in rule hash table (default: 8)");
|
||||
@@ -167,7 +153,6 @@ alloc_hashtable(unsigned int size)
|
||||
return NULL;
|
||||
for (i = 0; i < size; ++i)
|
||||
INIT_LIST_HEAD(&hash[i]);
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
@@ -196,14 +181,11 @@ status_itoa(enum status status)
|
||||
static void *
|
||||
pknock_seq_start(struct seq_file *s, loff_t *pos)
|
||||
{
|
||||
const struct proc_dir_entry *pde = s->private;
|
||||
const struct xt_pknock_rule *rule = pde->data;
|
||||
const struct xt_pknock_rule *rule = s->private;
|
||||
|
||||
spin_lock_bh(&list_lock);
|
||||
|
||||
if (*pos >= peer_hashsize)
|
||||
return NULL;
|
||||
|
||||
return rule->peer_head + *pos;
|
||||
}
|
||||
|
||||
@@ -216,13 +198,11 @@ pknock_seq_start(struct seq_file *s, loff_t *pos)
|
||||
static void *
|
||||
pknock_seq_next(struct seq_file *s, void *v, loff_t *pos)
|
||||
{
|
||||
const struct proc_dir_entry *pde = s->private;
|
||||
const struct xt_pknock_rule *rule = pde->data;
|
||||
const struct xt_pknock_rule *rule = s->private;
|
||||
|
||||
++*pos;
|
||||
if (*pos >= peer_hashsize)
|
||||
return NULL;
|
||||
|
||||
return rule->peer_head + *pos;
|
||||
}
|
||||
|
||||
@@ -248,14 +228,11 @@ pknock_seq_show(struct seq_file *s, void *v)
|
||||
const struct peer *peer;
|
||||
unsigned long time;
|
||||
const struct list_head *peer_head = v;
|
||||
|
||||
const struct proc_dir_entry *pde = s->private;
|
||||
const struct xt_pknock_rule *rule = pde->data;
|
||||
const struct xt_pknock_rule *rule = s->private;
|
||||
|
||||
list_for_each_safe(pos, n, peer_head) {
|
||||
peer = list_entry(pos, struct peer, head);
|
||||
|
||||
seq_printf(s, "src=" NIPQUAD_FMT " ", NIPQUAD(peer->ip));
|
||||
seq_printf(s, "src=%pI4 ", &peer->ip);
|
||||
seq_printf(s, "proto=%s ", (peer->proto == IPPROTO_TCP) ?
|
||||
"TCP" : "UDP");
|
||||
seq_printf(s, "status=%s ", status_itoa(peer->status));
|
||||
@@ -270,12 +247,11 @@ pknock_seq_show(struct seq_file *s, void *v)
|
||||
seq_printf(s, "expir_time=%lu [secs] ", time);
|
||||
}
|
||||
if (peer->status == ST_ALLOWED && rule->autoclose_time != 0) {
|
||||
unsigned long x = ktime_get_seconds();
|
||||
unsigned long y = peer->login_sec + rule->autoclose_time * 60;
|
||||
time = 0;
|
||||
if (time_before(get_seconds(), peer->login_sec +
|
||||
rule->autoclose_time * 60))
|
||||
time = peer->login_sec +
|
||||
rule->autoclose_time * 60 -
|
||||
get_seconds();
|
||||
if (time_before(x, y))
|
||||
time = y - x;
|
||||
seq_printf(s, "autoclose_time=%lu [secs] ", time);
|
||||
}
|
||||
seq_printf(s, "\n");
|
||||
@@ -301,17 +277,16 @@ pknock_proc_open(struct inode *inode, struct file *file)
|
||||
int ret = seq_open(file, &pknock_seq_ops);
|
||||
if (ret == 0) {
|
||||
struct seq_file *sf = file->private_data;
|
||||
sf->private = PDE(inode);
|
||||
sf->private = PDE_DATA(inode);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct file_operations pknock_proc_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = pknock_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = seq_release
|
||||
static const struct proc_ops pknock_proc_ops = {
|
||||
.proc_open = pknock_proc_open,
|
||||
.proc_read = seq_read,
|
||||
.proc_lseek = seq_lseek,
|
||||
.proc_release = seq_release,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -323,7 +298,6 @@ static void update_rule_gc_timer(struct xt_pknock_rule *rule)
|
||||
{
|
||||
if (timer_pending(&rule->timer))
|
||||
del_timer(&rule->timer);
|
||||
|
||||
rule->timer.expires = jiffies + msecs_to_jiffies(gc_expir_time);
|
||||
add_timer(&rule->timer);
|
||||
}
|
||||
@@ -337,8 +311,12 @@ static void update_rule_gc_timer(struct xt_pknock_rule *rule)
|
||||
static inline bool
|
||||
autoclose_time_passed(const struct peer *peer, unsigned int autoclose_time)
|
||||
{
|
||||
return peer != NULL && autoclose_time != 0 && time_after(get_seconds(),
|
||||
peer->login_sec + autoclose_time * 60);
|
||||
unsigned long x, y;
|
||||
if (peer == NULL || autoclose_time == 0)
|
||||
return false;
|
||||
x = ktime_get_seconds();
|
||||
y = peer->login_sec + autoclose_time * 60;
|
||||
return time_after(x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -360,7 +338,12 @@ is_interknock_time_exceeded(const struct peer *peer, unsigned int max_time)
|
||||
static inline bool
|
||||
has_logged_during_this_minute(const struct peer *peer)
|
||||
{
|
||||
return peer != NULL && peer->login_sec / 60 == get_seconds() / 60;
|
||||
uint64_t x, y;
|
||||
if (peer == NULL)
|
||||
return 0;
|
||||
x = ktime_get_seconds();
|
||||
y = peer->login_sec;
|
||||
return do_div(y, 60) == do_div(x, 60);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -368,11 +351,10 @@ has_logged_during_this_minute(const struct peer *peer)
|
||||
*
|
||||
* @r: rule
|
||||
*/
|
||||
static void
|
||||
peer_gc(unsigned long r)
|
||||
static void peer_gc(struct timer_list *tl)
|
||||
{
|
||||
unsigned int i;
|
||||
struct xt_pknock_rule *rule = (struct xt_pknock_rule *)r;
|
||||
struct xt_pknock_rule *rule = from_timer(rule, tl, timer);
|
||||
struct peer *peer;
|
||||
struct list_head *pos, *n;
|
||||
|
||||
@@ -446,7 +428,6 @@ add_rule(struct xt_pknock_mtinfo *info)
|
||||
|
||||
list_for_each_safe(pos, n, &rule_hashtable[hash]) {
|
||||
rule = list_entry(pos, struct xt_pknock_rule, head);
|
||||
|
||||
if (!rulecmp(info, rule))
|
||||
continue;
|
||||
++rule->ref_count;
|
||||
@@ -455,7 +436,6 @@ add_rule(struct xt_pknock_mtinfo *info)
|
||||
rule->max_time = info->max_time;
|
||||
rule->autoclose_time = info->autoclose_time;
|
||||
}
|
||||
|
||||
if (info->option & XT_PKNOCK_CHECKIP)
|
||||
pr_debug("add_rule() (AC) rule found: %s - "
|
||||
"ref_count: %d\n",
|
||||
@@ -463,34 +443,25 @@ add_rule(struct xt_pknock_mtinfo *info)
|
||||
return true;
|
||||
}
|
||||
|
||||
rule = kmalloc(sizeof(*rule), GFP_KERNEL);
|
||||
rule = kzalloc(sizeof(*rule), GFP_KERNEL);
|
||||
if (rule == NULL)
|
||||
return false;
|
||||
|
||||
INIT_LIST_HEAD(&rule->head);
|
||||
|
||||
memset(rule->rule_name, 0, sizeof(rule->rule_name));
|
||||
strncpy(rule->rule_name, info->rule_name, info->rule_name_len);
|
||||
rule->rule_name_len = info->rule_name_len;
|
||||
|
||||
rule->ref_count = 1;
|
||||
rule->max_time = info->max_time;
|
||||
rule->autoclose_time = info->autoclose_time;
|
||||
rule->peer_head = alloc_hashtable(peer_hashsize);
|
||||
if (rule->peer_head == NULL)
|
||||
goto out;
|
||||
|
||||
init_timer(&rule->timer);
|
||||
rule->timer.function = peer_gc;
|
||||
rule->timer.data = (unsigned long)rule;
|
||||
|
||||
rule->status_proc = create_proc_entry(info->rule_name, 0, pde);
|
||||
timer_setup(&rule->timer, peer_gc, 0);
|
||||
rule->status_proc = proc_create_data(info->rule_name, 0, pde,
|
||||
&pknock_proc_ops, rule);
|
||||
if (rule->status_proc == NULL)
|
||||
goto out;
|
||||
|
||||
rule->status_proc->proc_fops = &pknock_proc_ops;
|
||||
rule->status_proc->data = rule;
|
||||
|
||||
list_add(&rule->head, &rule_hashtable[hash]);
|
||||
pr_debug("(A) rule_name: %s - created.\n", rule->rule_name);
|
||||
return true;
|
||||
@@ -521,7 +492,6 @@ remove_rule(struct xt_pknock_mtinfo *info)
|
||||
|
||||
list_for_each_safe(pos, n, &rule_hashtable[hash]) {
|
||||
rule = list_entry(pos, struct xt_pknock_rule, head);
|
||||
|
||||
if (rulecmp(info, rule)) {
|
||||
found = 1;
|
||||
rule->ref_count--;
|
||||
@@ -547,7 +517,6 @@ remove_rule(struct xt_pknock_mtinfo *info)
|
||||
pr_debug("(D) rule deleted: %s.\n", rule->rule_name);
|
||||
if (timer_pending(&rule->timer))
|
||||
del_timer(&rule->timer);
|
||||
|
||||
list_del(&rule->head);
|
||||
kfree(rule->peer_head);
|
||||
kfree(rule);
|
||||
@@ -567,7 +536,6 @@ static struct peer *get_peer(struct xt_pknock_rule *rule, __be32 ip)
|
||||
unsigned int hash;
|
||||
|
||||
hash = pknock_hash(&ip, sizeof(ip), ipt_pknock_hash_rnd, peer_hashsize);
|
||||
|
||||
list_for_each_safe(pos, n, &rule->peer_head[hash]) {
|
||||
peer = list_entry(pos, struct peer, head);
|
||||
if (peer->ip == ip)
|
||||
@@ -601,14 +569,12 @@ static struct peer *new_peer(__be32 ip, uint8_t proto)
|
||||
|
||||
if (peer == NULL)
|
||||
return NULL;
|
||||
|
||||
INIT_LIST_HEAD(&peer->head);
|
||||
peer->ip = ip;
|
||||
peer->proto = proto;
|
||||
peer->timestamp = jiffies/HZ;
|
||||
peer->login_sec = 0;
|
||||
reset_knock_status(peer);
|
||||
|
||||
return peer;
|
||||
}
|
||||
|
||||
@@ -632,8 +598,9 @@ static void add_peer(struct peer *peer, struct xt_pknock_rule *rule)
|
||||
*/
|
||||
static void remove_peer(struct peer *peer)
|
||||
{
|
||||
if (peer == NULL)
|
||||
return;
|
||||
list_del(&peer->head);
|
||||
if (peer != NULL)
|
||||
kfree(peer);
|
||||
}
|
||||
|
||||
@@ -695,31 +662,24 @@ static bool
|
||||
msg_to_userspace_nl(const struct xt_pknock_mtinfo *info,
|
||||
const struct peer *peer, int multicast_group)
|
||||
{
|
||||
#if defined(CONFIG_CONNECTOR) || defined(CONFIG_CONNECTOR_MODULE)
|
||||
#if IS_ENABLED(CONFIG_CONNECTOR)
|
||||
struct cn_msg *m;
|
||||
struct xt_pknock_nl_msg msg;
|
||||
|
||||
m = kmalloc(sizeof(*m) + sizeof(msg), GFP_ATOMIC);
|
||||
m = kzalloc(sizeof(*m) + sizeof(msg), GFP_ATOMIC);
|
||||
if (m == NULL)
|
||||
return false;
|
||||
|
||||
memset(m, 0, sizeof(*m) + sizeof(msg));
|
||||
m->seq = 0;
|
||||
m->len = sizeof(msg);
|
||||
|
||||
msg.peer_ip = peer->ip;
|
||||
scnprintf(msg.rule_name, info->rule_name_len + 1, info->rule_name);
|
||||
|
||||
memcpy(m + 1, &msg, m->len);
|
||||
|
||||
cn_netlink_send(m, multicast_group, GFP_ATOMIC);
|
||||
|
||||
cn_netlink_send(m, 0, multicast_group, GFP_ATOMIC);
|
||||
kfree(m);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef PK_CRYPTO
|
||||
/**
|
||||
* Transforms a sequence of characters to hexadecimal.
|
||||
*
|
||||
@@ -752,12 +712,12 @@ static bool
|
||||
has_secret(const unsigned char *secret, unsigned int secret_len, uint32_t ipsrc,
|
||||
const unsigned char *payload, unsigned int payload_len)
|
||||
{
|
||||
struct scatterlist sg[2];
|
||||
char result[64]; // 64 bytes * 8 = 512 bits
|
||||
char result[64] = ""; // 64 bytes * 8 = 512 bits
|
||||
char *hexresult;
|
||||
unsigned int hexa_size;
|
||||
int ret;
|
||||
bool fret = false;
|
||||
uint64_t x;
|
||||
unsigned int epoch_min;
|
||||
|
||||
if (payload_len == 0)
|
||||
@@ -773,23 +733,13 @@ has_secret(const unsigned char *secret, unsigned int secret_len, uint32_t ipsrc,
|
||||
/* + 1 cause we MUST add NULL in the payload */
|
||||
if (payload_len != hexa_size + 1)
|
||||
return false;
|
||||
|
||||
hexresult = kmalloc(hexa_size, GFP_ATOMIC);
|
||||
hexresult = kzalloc(hexa_size, GFP_ATOMIC);
|
||||
if (hexresult == NULL)
|
||||
return false;
|
||||
x = ktime_get_seconds();
|
||||
epoch_min = do_div(x, 60);
|
||||
|
||||
memset(result, 0, sizeof(result));
|
||||
memset(hexresult, 0, hexa_size);
|
||||
|
||||
epoch_min = get_seconds() / 60;
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
|
||||
sg_init_table(sg, ARRAY_SIZE(sg));
|
||||
#endif
|
||||
sg_set_buf(&sg[0], &ipsrc, sizeof(ipsrc));
|
||||
sg_set_buf(&sg[1], &epoch_min, sizeof(epoch_min));
|
||||
|
||||
ret = crypto_hash_setkey(crypto.tfm, secret, secret_len);
|
||||
ret = crypto_shash_setkey(crypto.tfm, secret, secret_len);
|
||||
if (ret != 0) {
|
||||
printk("crypto_hash_setkey() failed ret=%d\n", ret);
|
||||
goto out;
|
||||
@@ -800,25 +750,21 @@ has_secret(const unsigned char *secret, unsigned int secret_len, uint32_t ipsrc,
|
||||
* 4 bytes IP (32 bits) +
|
||||
* 4 bytes int epoch_min (32 bits)
|
||||
*/
|
||||
ret = crypto_hash_digest(&crypto.desc, sg,
|
||||
sizeof(ipsrc) + sizeof(epoch_min), result);
|
||||
if (ret != 0) {
|
||||
printk("crypto_hash_digest() failed ret=%d\n", ret);
|
||||
if ((ret = crypto_shash_update(&crypto.desc, (const void *)&ipsrc, sizeof(ipsrc))) != 0 ||
|
||||
(ret = crypto_shash_update(&crypto.desc, (const void *)&epoch_min, sizeof(epoch_min))) != 0 ||
|
||||
(ret = crypto_shash_final(&crypto.desc, result)) != 0) {
|
||||
printk("crypto_shash_update/final() failed ret=%d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
crypt_to_hex(hexresult, result, crypto.size);
|
||||
|
||||
if (memcmp(hexresult, payload, hexa_size) != 0)
|
||||
pr_debug("secret match failed\n");
|
||||
else
|
||||
fret = true;
|
||||
|
||||
out:
|
||||
kfree(hexresult);
|
||||
return fret;
|
||||
}
|
||||
#endif /* PK_CRYPTO */
|
||||
|
||||
/**
|
||||
* If the peer pass the security policy.
|
||||
@@ -841,14 +787,11 @@ pass_security(struct peer *peer, const struct xt_pknock_mtinfo *info,
|
||||
pk_debug("DENIED (anti-spoof protection)", peer);
|
||||
return false;
|
||||
}
|
||||
#ifdef PK_CRYPTO
|
||||
/* Check for OPEN secret */
|
||||
if (has_secret(info->open_secret,
|
||||
info->open_secret_len, peer->ip,
|
||||
payload, payload_len))
|
||||
return true;
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -875,7 +818,6 @@ update_peer(struct peer *peer, const struct xt_pknock_mtinfo *info,
|
||||
/* Peer must start the sequence from scratch. */
|
||||
if (info->option & XT_PKNOCK_STRICT)
|
||||
remove_peer(peer);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -883,25 +825,20 @@ update_peer(struct peer *peer, const struct xt_pknock_mtinfo *info,
|
||||
if (info->option & XT_PKNOCK_OPENSECRET ) {
|
||||
if (hdr->proto != IPPROTO_UDP && hdr->proto != IPPROTO_UDPLITE)
|
||||
return false;
|
||||
|
||||
if (!pass_security(peer, info, hdr->payload, hdr->payload_len))
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Update the gc timer when there is a state change. */
|
||||
update_rule_gc_timer(rule);
|
||||
|
||||
++peer->accepted_knock_count;
|
||||
|
||||
if (is_last_knock(peer, info)) {
|
||||
peer->status = ST_ALLOWED;
|
||||
|
||||
pk_debug("ALLOWED", peer);
|
||||
peer->login_sec = get_seconds();
|
||||
|
||||
peer->login_sec = ktime_get_seconds();
|
||||
if (nl_multicast_group > 0)
|
||||
msg_to_userspace_nl(info, peer, nl_multicast_group);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -939,7 +876,6 @@ static bool
|
||||
is_close_knock(const struct peer *peer, const struct xt_pknock_mtinfo *info,
|
||||
const unsigned char *payload, unsigned int payload_len)
|
||||
{
|
||||
#ifdef PK_CRYPTO
|
||||
/* Check for CLOSE secret. */
|
||||
if (has_secret(info->close_secret,
|
||||
info->close_secret_len, peer->ip,
|
||||
@@ -948,7 +884,6 @@ is_close_knock(const struct peer *peer, const struct xt_pknock_mtinfo *info,
|
||||
pk_debug("BLOCKED", peer);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -980,17 +915,10 @@ static bool pknock_mt(const struct sk_buff *skb,
|
||||
switch (hdr.proto) {
|
||||
case IPPROTO_TCP:
|
||||
break;
|
||||
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_UDPLITE:
|
||||
#ifdef PK_CRYPTO
|
||||
hdr_len = (iph->ihl * 4) + sizeof(struct udphdr);
|
||||
break;
|
||||
#else
|
||||
pr_debug("UDP protocol not supported\n");
|
||||
return false;
|
||||
#endif
|
||||
|
||||
default:
|
||||
pr_debug("IP payload protocol is neither tcp nor udp.\n");
|
||||
return false;
|
||||
@@ -1008,12 +936,10 @@ static bool pknock_mt(const struct sk_buff *skb,
|
||||
|
||||
/* Gives the peer matching status added to rule depending on ip src. */
|
||||
peer = get_peer(rule, iph->saddr);
|
||||
|
||||
if (info->option & XT_PKNOCK_CHECKIP) {
|
||||
ret = is_allowed(peer);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (iph->protocol == IPPROTO_UDP || iph->protocol == IPPROTO_UDPLITE) {
|
||||
hdr.payload = (void *)iph + hdr_len;
|
||||
hdr.payload_len = skb->len - hdr_len;
|
||||
@@ -1021,7 +947,8 @@ static bool pknock_mt(const struct sk_buff *skb,
|
||||
|
||||
/* Sets, updates, removes or checks the peer matching status. */
|
||||
if (info->option & XT_PKNOCK_KNOCKPORT) {
|
||||
if ((ret = is_allowed(peer))) {
|
||||
ret = is_allowed(peer);
|
||||
if (ret != 0) {
|
||||
if (info->option & XT_PKNOCK_CLOSESECRET &&
|
||||
(iph->protocol == IPPROTO_UDP ||
|
||||
iph->protocol == IPPROTO_UDPLITE))
|
||||
@@ -1039,10 +966,8 @@ static bool pknock_mt(const struct sk_buff *skb,
|
||||
peer = new_peer(iph->saddr, iph->protocol);
|
||||
add_peer(peer, rule);
|
||||
}
|
||||
|
||||
if (peer == NULL)
|
||||
goto out;
|
||||
|
||||
update_peer(peer, info, rule, &hdr);
|
||||
}
|
||||
|
||||
@@ -1062,7 +987,7 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define RETURN_ERR(err) do { printk(KERN_ERR PKNOCK err); return -EINVAL; } while (false)
|
||||
#define RETURN_ERR(err) do { pr_err(err); return -EINVAL; } while (false)
|
||||
|
||||
static int pknock_mt_check(const struct xt_mtchk_param *par)
|
||||
{
|
||||
@@ -1079,12 +1004,6 @@ static int pknock_mt_check(const struct xt_mtchk_param *par)
|
||||
|
||||
if (!(info->option & XT_PKNOCK_NAME))
|
||||
RETURN_ERR("You must specify --name option.\n");
|
||||
|
||||
#ifndef PK_CRYPTO
|
||||
if (info->option & (XT_PKNOCK_OPENSECRET | XT_PKNOCK_CLOSESECRET))
|
||||
RETURN_ERR("No crypto support available; "
|
||||
"cannot use opensecret/closescret\n");
|
||||
#endif
|
||||
if (info->option & XT_PKNOCK_OPENSECRET && info->ports_count != 1)
|
||||
RETURN_ERR("--opensecret must have just one knock port\n");
|
||||
if (info->option & XT_PKNOCK_KNOCKPORT) {
|
||||
@@ -1118,11 +1037,9 @@ static int pknock_mt_check(const struct xt_mtchk_param *par)
|
||||
memcmp(info->open_secret, info->close_secret,
|
||||
info->open_secret_len) == 0)
|
||||
RETURN_ERR("opensecret & closesecret cannot be equal.\n");
|
||||
|
||||
if (!add_rule(info))
|
||||
/* should ENOMEM here */
|
||||
RETURN_ERR("add_rule() error in checkentry() function.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1146,7 +1063,7 @@ static struct xt_match xt_pknock_mt_reg __read_mostly = {
|
||||
|
||||
static int __init xt_pknock_mt_init(void)
|
||||
{
|
||||
#if !defined(CONFIG_CONNECTOR) && !defined(CONFIG_CONNECTOR_MODULE)
|
||||
#if !IS_ENABLED(CONFIG_CONNECTOR)
|
||||
if (nl_multicast_group != -1)
|
||||
pr_info("CONFIG_CONNECTOR not present; "
|
||||
"netlink messages disabled\n");
|
||||
@@ -1154,30 +1071,25 @@ static int __init xt_pknock_mt_init(void)
|
||||
|
||||
if (gc_expir_time < DEFAULT_GC_EXPIRATION_TIME)
|
||||
gc_expir_time = DEFAULT_GC_EXPIRATION_TIME;
|
||||
#ifdef PK_CRYPTO
|
||||
if (request_module(crypto.algo) < 0) {
|
||||
printk(KERN_ERR PKNOCK "request_module('%s') error.\n",
|
||||
pr_err("request_module('%s') error.\n",
|
||||
crypto.algo);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
crypto.tfm = crypto_alloc_hash(crypto.algo, 0, CRYPTO_ALG_ASYNC);
|
||||
crypto.tfm = crypto_alloc_shash(crypto.algo, 0, 0);
|
||||
if (IS_ERR(crypto.tfm)) {
|
||||
printk(KERN_ERR PKNOCK "failed to load transform for %s\n",
|
||||
pr_err("failed to load transform for %s\n",
|
||||
crypto.algo);
|
||||
return PTR_ERR(crypto.tfm);
|
||||
}
|
||||
|
||||
crypto.size = crypto_hash_digestsize(crypto.tfm);
|
||||
crypto.size = crypto_shash_digestsize(crypto.tfm);
|
||||
crypto.desc.tfm = crypto.tfm;
|
||||
crypto.desc.flags = 0;
|
||||
#else
|
||||
pr_info("No crypto support for < 2.6.19\n");
|
||||
#endif
|
||||
|
||||
pde = proc_mkdir("xt_pknock", init_net__proc_net);
|
||||
pde = proc_mkdir("xt_pknock", init_net.proc_net);
|
||||
if (pde == NULL) {
|
||||
printk(KERN_ERR PKNOCK "proc_mkdir() error in _init().\n");
|
||||
pr_err("proc_mkdir() error in _init().\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
return xt_register_match(&xt_pknock_mt_reg);
|
||||
@@ -1185,14 +1097,11 @@ static int __init xt_pknock_mt_init(void)
|
||||
|
||||
static void __exit xt_pknock_mt_exit(void)
|
||||
{
|
||||
remove_proc_entry("xt_pknock", init_net__proc_net);
|
||||
remove_proc_entry("xt_pknock", init_net.proc_net);
|
||||
xt_unregister_match(&xt_pknock_mt_reg);
|
||||
kfree(rule_hashtable);
|
||||
|
||||
#ifdef PK_CRYPTO
|
||||
if (crypto.tfm != NULL)
|
||||
crypto_free_hash(crypto.tfm);
|
||||
#endif
|
||||
crypto_free_shash(crypto.tfm);
|
||||
}
|
||||
|
||||
module_init(xt_pknock_mt_init);
|
||||
|
@@ -8,9 +8,7 @@
|
||||
*
|
||||
* This program is released under the terms of GNU GPL version 2.
|
||||
*/
|
||||
#ifndef _XT_PKNOCK_H
|
||||
#define _XT_PKNOCK_H
|
||||
|
||||
#pragma once
|
||||
#define PKNOCK "xt_pknock: "
|
||||
|
||||
enum {
|
||||
@@ -29,8 +27,6 @@ enum {
|
||||
XT_PKNOCK_MAX_PASSWD_LEN = 31,
|
||||
};
|
||||
|
||||
#define DEBUG 1
|
||||
|
||||
struct xt_pknock_mtinfo {
|
||||
char rule_name[XT_PKNOCK_MAX_BUF_LEN+1];
|
||||
uint32_t rule_name_len;
|
||||
@@ -49,5 +45,3 @@ struct xt_pknock_nl_msg {
|
||||
char rule_name[XT_PKNOCK_MAX_BUF_LEN+1];
|
||||
__be32 peer_ip;
|
||||
};
|
||||
|
||||
#endif /* _XT_PKNOCK_H */
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* "CHAOS" target extension for Xtables
|
||||
* Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2006 - 2008
|
||||
* Copyright © Jan Engelhardt, 2006 - 2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License; either
|
||||
@@ -54,33 +54,11 @@ xt_chaos_total(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
const int fragoff = ntohs(iph->frag_off) & IP_OFFSET;
|
||||
typeof(xt_tarpit) destiny;
|
||||
bool ret;
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 22)
|
||||
int hotdrop = false;
|
||||
#else
|
||||
bool hotdrop = false;
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
ret = xm_tcp->match(skb, par->in, par->out, xm_tcp, &tcp_params,
|
||||
fragoff, thoff, &hotdrop);
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 34)
|
||||
{
|
||||
struct xt_match_param local_par = {
|
||||
.in = par->in,
|
||||
.out = par->out,
|
||||
.match = xm_tcp,
|
||||
.matchinfo = &tcp_params,
|
||||
.fragoff = fragoff,
|
||||
.thoff = thoff,
|
||||
.hotdrop = &hotdrop,
|
||||
};
|
||||
ret = xm_tcp->match(skb, &local_par);
|
||||
}
|
||||
#else
|
||||
{
|
||||
struct xt_action_param local_par;
|
||||
local_par.in = par->in,
|
||||
local_par.out = par->out,
|
||||
local_par.state = par->state;
|
||||
local_par.match = xm_tcp;
|
||||
local_par.matchinfo = &tcp_params;
|
||||
local_par.fragoff = fragoff;
|
||||
@@ -89,45 +67,21 @@ xt_chaos_total(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
ret = xm_tcp->match(skb, &local_par);
|
||||
hotdrop = local_par.hotdrop;
|
||||
}
|
||||
#endif
|
||||
if (!ret || hotdrop || (unsigned int)net_random() > delude_percentage)
|
||||
if (!ret || hotdrop || (unsigned int)prandom_u32() > delude_percentage)
|
||||
return;
|
||||
|
||||
destiny = (info->variant == XTCHAOS_TARPIT) ? xt_tarpit : xt_delude;
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
|
||||
destiny->target(&skb, par->in, par->out, par->hooknum, destiny, NULL, NULL);
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
|
||||
destiny->target(&skb, par->in, par->out, par->hooknum, destiny, NULL);
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
destiny->target(skb, par->in, par->out, par->hooknum, destiny, NULL);
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 34)
|
||||
{
|
||||
struct xt_target_param local_par = {
|
||||
.in = par->in,
|
||||
.out = par->out,
|
||||
.hooknum = par->hooknum,
|
||||
.target = destiny,
|
||||
.targinfo = par->targinfo,
|
||||
.family = par->family,
|
||||
};
|
||||
destiny->target(skb, &local_par);
|
||||
}
|
||||
#else
|
||||
{
|
||||
struct xt_action_param local_par;
|
||||
local_par.in = par->in;
|
||||
local_par.out = par->out;
|
||||
local_par.hooknum = par->hooknum;
|
||||
local_par.state = par->state;
|
||||
local_par.target = destiny;
|
||||
local_par.targinfo = par->targinfo;
|
||||
local_par.family = par->family;
|
||||
destiny->target(skb, &local_par);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
chaos_tg(struct sk_buff **pskb, const struct xt_action_param *par)
|
||||
chaos_tg(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
{
|
||||
/*
|
||||
* Equivalent to:
|
||||
@@ -138,43 +92,19 @@ chaos_tg(struct sk_buff **pskb, const struct xt_action_param *par)
|
||||
* -A chaos -j DROP;
|
||||
*/
|
||||
const struct xt_chaos_tginfo *info = par->targinfo;
|
||||
struct sk_buff *skb = *pskb;
|
||||
const struct iphdr *iph = ip_hdr(skb);
|
||||
|
||||
if ((unsigned int)net_random() <= reject_percentage) {
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
|
||||
return xt_reject->target(pskb, par->in, par->out, par->hooknum,
|
||||
xt_reject, &reject_params, NULL);
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
|
||||
return xt_reject->target(pskb, par->in, par->out, par->hooknum,
|
||||
xt_reject, &reject_params);
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
return xt_reject->target(skb, par->in, par->out, par->hooknum,
|
||||
xt_reject, &reject_params);
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 34)
|
||||
struct xt_target_param local_par = {
|
||||
.in = par->in,
|
||||
.out = par->out,
|
||||
.hooknum = par->hooknum,
|
||||
.target = xt_reject,
|
||||
.targinfo = &reject_params,
|
||||
};
|
||||
return xt_reject->target(skb, &local_par);
|
||||
#else
|
||||
if ((unsigned int)prandom_u32() <= reject_percentage) {
|
||||
struct xt_action_param local_par;
|
||||
local_par.in = par->in;
|
||||
local_par.out = par->out;
|
||||
local_par.hooknum = par->hooknum;
|
||||
local_par.state = par->state;
|
||||
local_par.target = xt_reject;
|
||||
local_par.targinfo = &reject_params;
|
||||
return xt_reject->target(skb, &local_par);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* TARPIT/DELUDE may not be called from the OUTPUT chain */
|
||||
if (iph->protocol == IPPROTO_TCP &&
|
||||
info->variant != XTCHAOS_NORMAL &&
|
||||
par->hooknum != NF_INET_LOCAL_OUT)
|
||||
if (iph->protocol == IPPROTO_TCP && info->variant != XTCHAOS_NORMAL &&
|
||||
par->state->hook != NF_INET_LOCAL_OUT)
|
||||
xt_chaos_total(skb, par);
|
||||
|
||||
return NF_DROP;
|
||||
@@ -241,7 +171,8 @@ static int __init chaos_tg_init(void)
|
||||
printk(KERN_WARNING PFX "Warning: Could not find or load "
|
||||
"\"DELUDE\" target\n");
|
||||
|
||||
if ((ret = xt_register_target(&chaos_tg_reg)) != 0) {
|
||||
ret = xt_register_target(&chaos_tg_reg);
|
||||
if (ret != 0) {
|
||||
printk(KERN_WARNING PFX "xt_register_target returned "
|
||||
"error %d\n", ret);
|
||||
goto out3;
|
||||
@@ -274,6 +205,6 @@ static void __exit chaos_tg_exit(void)
|
||||
module_init(chaos_tg_init);
|
||||
module_exit(chaos_tg_exit);
|
||||
MODULE_DESCRIPTION("Xtables: Network scan slowdown with non-deterministic results");
|
||||
MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>");
|
||||
MODULE_AUTHOR("Jan Engelhardt ");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("ipt_CHAOS");
|
||||
|
@@ -1,6 +1,4 @@
|
||||
#ifndef _LINUX_NETFILTER_XT_CHAOS_H
|
||||
#define _LINUX_NETFILTER_XT_CHAOS_H 1
|
||||
|
||||
#pragma once
|
||||
enum xt_chaos_target_variant {
|
||||
XTCHAOS_NORMAL,
|
||||
XTCHAOS_TARPIT,
|
||||
@@ -10,5 +8,3 @@ enum xt_chaos_target_variant {
|
||||
struct xt_chaos_tginfo {
|
||||
uint8_t variant;
|
||||
};
|
||||
|
||||
#endif /* _LINUX_NETFILTER_XT_CHAOS_H */
|
||||
|
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
* (C) 2002 by Harald Welte <laforge@netfilter.org>
|
||||
* (C) 2010 Red Hat, Inc.
|
||||
*
|
||||
* Author: Michael S. Tsirkin <mst@redhat.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.
|
||||
*/
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
#include <linux/module.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
|
||||
# error ----------------------------------------------------------
|
||||
# error This module has been merged into, and is available in the
|
||||
# error mainline since Linux kernel v2.6.36. Please use that.
|
||||
# error ----------------------------------------------------------
|
||||
#endif
|
||||
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#include "xt_CHECKSUM.h"
|
||||
#include "compat_xtables.h"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Michael S. Tsirkin <mst@redhat.com>");
|
||||
MODULE_DESCRIPTION("Xtables: checksum modification");
|
||||
MODULE_ALIAS("ipt_CHECKSUM");
|
||||
MODULE_ALIAS("ip6t_CHECKSUM");
|
||||
|
||||
static unsigned int
|
||||
checksum_tg(struct sk_buff **pskb, const struct xt_action_param *par)
|
||||
{
|
||||
struct sk_buff *skb = *pskb;
|
||||
|
||||
if (skb->ip_summed == CHECKSUM_PARTIAL)
|
||||
skb_checksum_help(skb);
|
||||
|
||||
return XT_CONTINUE;
|
||||
}
|
||||
|
||||
static int checksum_tg_check(const struct xt_tgchk_param *par)
|
||||
{
|
||||
const struct xt_CHECKSUM_info *einfo = par->targinfo;
|
||||
|
||||
if (einfo->operation & ~XT_CHECKSUM_OP_FILL) {
|
||||
pr_info("unsupported CHECKSUM operation %x\n", einfo->operation);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!einfo->operation) {
|
||||
pr_info("no CHECKSUM operation enabled\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct xt_target checksum_tg_reg __read_mostly = {
|
||||
.name = "CHECKSUM",
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.target = checksum_tg,
|
||||
.targetsize = sizeof(struct xt_CHECKSUM_info),
|
||||
.table = "mangle",
|
||||
.checkentry = checksum_tg_check,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init checksum_tg_init(void)
|
||||
{
|
||||
return xt_register_target(&checksum_tg_reg);
|
||||
}
|
||||
|
||||
static void __exit checksum_tg_exit(void)
|
||||
{
|
||||
xt_unregister_target(&checksum_tg_reg);
|
||||
}
|
||||
|
||||
module_init(checksum_tg_init);
|
||||
module_exit(checksum_tg_exit);
|
@@ -1,18 +0,0 @@
|
||||
/* Header file for iptables ipt_CHECKSUM target
|
||||
*
|
||||
* (C) 2002 by Harald Welte <laforge@gnumonks.org>
|
||||
* (C) 2010 Red Hat Inc
|
||||
* Author: Michael S. Tsirkin <mst@redhat.com>
|
||||
*
|
||||
* This software is distributed under GNU GPL v2, 1991
|
||||
*/
|
||||
#ifndef _IPT_CHECKSUM_TARGET_H
|
||||
#define _IPT_CHECKSUM_TARGET_H
|
||||
|
||||
#define XT_CHECKSUM_OP_FILL 0x01 /* fill in checksum in IP header */
|
||||
|
||||
struct xt_CHECKSUM_info {
|
||||
__u8 operation; /* bitset of operations */
|
||||
};
|
||||
|
||||
#endif /* _IPT_CHECKSUM_TARGET_H */
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* "DELUDE" target extension for Xtables
|
||||
* Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2007 - 2008
|
||||
* Copyright © Jan Engelhardt, 2007 - 2008
|
||||
*
|
||||
* Based upon linux-2.6.18.5/net/ipv4/netfilter/ipt_REJECT.c:
|
||||
* (C) 1999-2001 Paul `Rusty' Russell
|
||||
@@ -25,7 +25,8 @@
|
||||
#include "compat_xtables.h"
|
||||
#define PFX KBUILD_MODNAME ": "
|
||||
|
||||
static void delude_send_reset(struct sk_buff *oldskb, unsigned int hook)
|
||||
static void delude_send_reset(struct sk_buff *oldskb,
|
||||
const struct xt_action_param *par)
|
||||
{
|
||||
struct tcphdr _otcph, *tcph;
|
||||
const struct tcphdr *oth;
|
||||
@@ -50,7 +51,8 @@ static void delude_send_reset(struct sk_buff *oldskb, unsigned int hook)
|
||||
return;
|
||||
|
||||
/* Check checksum */
|
||||
if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), IPPROTO_TCP))
|
||||
if (nf_ip_checksum(oldskb, par->state->hook, ip_hdrlen(oldskb),
|
||||
IPPROTO_TCP))
|
||||
return;
|
||||
|
||||
nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct tcphdr) +
|
||||
@@ -78,7 +80,7 @@ static void delude_send_reset(struct sk_buff *oldskb, unsigned int hook)
|
||||
tcph->doff = sizeof(struct tcphdr) / 4;
|
||||
|
||||
/* DELUDE essential part */
|
||||
if (oth->syn && !oth->ack && !oth->rst && !oth->fin) {
|
||||
if (oth->syn && !oth->ack && !oth->fin) {
|
||||
tcph->syn = true;
|
||||
tcph->seq = 0;
|
||||
tcph->ack = true;
|
||||
@@ -100,29 +102,28 @@ static void delude_send_reset(struct sk_buff *oldskb, unsigned int hook)
|
||||
}
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 20)
|
||||
tcph->check = tcp_v4_check(tcph, sizeof(struct tcphdr), niph->saddr,
|
||||
niph->daddr, csum_partial((char *)tcph,
|
||||
sizeof(struct tcphdr), 0));
|
||||
#else
|
||||
tcph->check = tcp_v4_check(sizeof(struct tcphdr), niph->saddr,
|
||||
niph->daddr, csum_partial((char *)tcph,
|
||||
sizeof(struct tcphdr), 0));
|
||||
#endif
|
||||
|
||||
addr_type = RTN_UNSPEC;
|
||||
#ifdef CONFIG_BRIDGE_NETFILTER
|
||||
if (hook != NF_INET_FORWARD || (nskb->nf_bridge != NULL &&
|
||||
nskb->nf_bridge->mask & BRNF_BRIDGED))
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
|
||||
if (par->state->hook != NF_INET_FORWARD ||
|
||||
((struct nf_bridge_info *)skb_ext_find(nskb, SKB_EXT_BRIDGE_NF) != NULL &&
|
||||
((struct nf_bridge_info *)skb_ext_find(nskb, SKB_EXT_BRIDGE_NF))->physoutdev))
|
||||
#else
|
||||
if (hook != NF_INET_FORWARD)
|
||||
if (par->state->hook != NF_INET_FORWARD || (nskb->nf_bridge != NULL &&
|
||||
nskb->nf_bridge->physoutdev))
|
||||
#endif
|
||||
#else
|
||||
if (par->state->hook != NF_INET_FORWARD)
|
||||
#endif
|
||||
addr_type = RTN_LOCAL;
|
||||
|
||||
/* ip_route_me_harder expects skb->dst to be set */
|
||||
skb_dst_set(nskb, dst_clone(skb_dst(oldskb)));
|
||||
|
||||
if (ip_route_me_harder(&nskb, addr_type))
|
||||
if (ip_route_me_harder(par_net(par), par->state->sk, nskb, addr_type))
|
||||
goto free_nskb;
|
||||
else
|
||||
niph = ip_hdr(nskb);
|
||||
@@ -135,8 +136,7 @@ static void delude_send_reset(struct sk_buff *oldskb, unsigned int hook)
|
||||
goto free_nskb;
|
||||
|
||||
nf_ct_attach(nskb, oldskb);
|
||||
|
||||
ip_local_out(nskb);
|
||||
ip_local_out(par_net(par), nskb->sk, nskb);
|
||||
return;
|
||||
|
||||
free_nskb:
|
||||
@@ -144,12 +144,14 @@ static void delude_send_reset(struct sk_buff *oldskb, unsigned int hook)
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
delude_tg(struct sk_buff **pskb, const struct xt_action_param *par)
|
||||
delude_tg(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
{
|
||||
/* WARNING: This code causes reentry within iptables.
|
||||
This means that the iptables jump stack is now crap. We
|
||||
must return an absolute verdict. --RR */
|
||||
delude_send_reset(*pskb, par->hooknum);
|
||||
/*
|
||||
* Sending the reset causes reentrancy within iptables - and should not pose
|
||||
* a problem, as that is supported since Linux 2.6.35. But since we do not
|
||||
* actually want to have a connection open, we are still going to drop it.
|
||||
*/
|
||||
delude_send_reset(skb, par);
|
||||
return NF_DROP;
|
||||
}
|
||||
|
||||
@@ -177,6 +179,6 @@ static void __exit delude_tg_exit(void)
|
||||
module_init(delude_tg_init);
|
||||
module_exit(delude_tg_exit);
|
||||
MODULE_DESCRIPTION("Xtables: Close TCP connections after handshake");
|
||||
MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>");
|
||||
MODULE_AUTHOR("Jan Engelhardt ");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("ipt_DELUDE");
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* "DHCPMAC" extensions for Xtables
|
||||
* Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2008
|
||||
* Copyright © Jan Engelhardt, 2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License; either
|
||||
@@ -34,9 +34,9 @@ static void ether_set(unsigned char *addr, const unsigned char *op,
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ETH_ALEN && mask > 0; ++i) {
|
||||
lo_mask = mask % 8;
|
||||
lo_mask = (mask >= 8) ? 8 : mask;
|
||||
/* FF << 4 >> 4 = 0F */
|
||||
lo_mask = ~(uint8_t)0U << lo_mask >> lo_mask;
|
||||
lo_mask = (uint8_t)(~0U << lo_mask) >> lo_mask;
|
||||
addr[i] &= lo_mask;
|
||||
addr[i] |= op[i] & ~lo_mask;
|
||||
if (mask >= 8)
|
||||
@@ -55,9 +55,9 @@ static bool ether_cmp(const unsigned char *lh, const unsigned char *rh,
|
||||
#define ZMACHEX(s) s[0], s[1], s[2], s[3], s[4], s[5]
|
||||
|
||||
for (i = 0; i < ETH_ALEN && mask > 0; ++i) {
|
||||
lo_mask = mask % 8;
|
||||
lo_mask = (mask >= 8) ? 8 : mask;
|
||||
/* ~(0xFF << 4 >> 4) = ~0x0F = 0xF0 */
|
||||
lo_mask = ~(~(uint8_t)0U << lo_mask >> lo_mask);
|
||||
lo_mask = ~((uint8_t)(~0U << lo_mask) >> lo_mask);
|
||||
if ((lh[i] ^ rh[i]) & lo_mask)
|
||||
return false;
|
||||
if (mask >= 8)
|
||||
@@ -89,15 +89,15 @@ dhcpmac_mt(const struct sk_buff *skb, struct xt_action_param *par)
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
dhcpmac_tg(struct sk_buff **pskb, const struct xt_action_param *par)
|
||||
dhcpmac_tg(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
{
|
||||
const struct dhcpmac_info *info = par->targinfo;
|
||||
struct dhcp_message dhcpbuf, *dh;
|
||||
struct udphdr udpbuf, *udph;
|
||||
struct sk_buff *skb = *pskb;
|
||||
unsigned int i;
|
||||
|
||||
if (!skb_make_writable(pskb, 0))
|
||||
if (skb_ensure_writable(skb, ip_hdrlen(skb) + sizeof(udpbuf) +
|
||||
sizeof(dhcpbuf)))
|
||||
return NF_DROP;
|
||||
|
||||
udph = skb_header_pointer(skb, ip_hdrlen(skb),
|
||||
@@ -111,13 +111,12 @@ dhcpmac_tg(struct sk_buff **pskb, const struct xt_action_param *par)
|
||||
return NF_DROP;
|
||||
|
||||
for (i = 0; i < sizeof(dh->chaddr); i += 2)
|
||||
csum_replace2(&udph->check, *(const __be16 *)dh->chaddr, 0);
|
||||
csum_replace2(&udph->check, *(const __be16 *)(dh->chaddr + i), 0);
|
||||
|
||||
memset(dh->chaddr, 0, sizeof(dh->chaddr));
|
||||
ether_set(dh->chaddr, info->addr, info->mask);
|
||||
|
||||
for (i = 0; i < sizeof(dh->chaddr); i += 2)
|
||||
csum_replace2(&udph->check, 0, *(const __be16 *)dh->chaddr);
|
||||
csum_replace2(&udph->check, 0, *(const __be16 *)(dh->chaddr + i));
|
||||
|
||||
return XT_CONTINUE;
|
||||
}
|
||||
@@ -167,7 +166,7 @@ static void __exit dhcpmac_exit(void)
|
||||
module_init(dhcpmac_init);
|
||||
module_exit(dhcpmac_exit);
|
||||
MODULE_DESCRIPTION("Xtables: Clamp DHCP MAC to packet MAC addresses");
|
||||
MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>");
|
||||
MODULE_AUTHOR("Jan Engelhardt ");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("ipt_DHCPMAC");
|
||||
MODULE_ALIAS("ipt_dhcpmac");
|
||||
|
@@ -1,6 +1,4 @@
|
||||
#ifndef _LINUX_NETFILTER_XT_DHCPMAC_H
|
||||
#define _LINUX_NETFILTER_XT_DHCPMAC_H 1
|
||||
|
||||
#pragma once
|
||||
#define DH_MAC_FMT "%02X:%02X:%02X:%02X:%02X:%02X"
|
||||
#define DH_MAC_HEX(z) z[0], z[1], z[2], z[3], z[4], z[5]
|
||||
|
||||
@@ -8,5 +6,3 @@ struct dhcpmac_info {
|
||||
unsigned char addr[ETH_ALEN];
|
||||
uint8_t mask, invert;
|
||||
};
|
||||
|
||||
#endif /* _LINUX_NETFILTER_XT_DHCPMAC_H */
|
||||
|
@@ -19,33 +19,24 @@
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
#include <linux/module.h>
|
||||
#ifdef CONFIG_NF_NAT
|
||||
#include <linux/inet.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netfilter_ipv4.h>
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/uidgid.h>
|
||||
#include <linux/version.h>
|
||||
#include <net/netfilter/nf_nat_rule.h>
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)
|
||||
#include <net/net_namespace.h>
|
||||
#include <net/netns/generic.h>
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
|
||||
#include <net/netfilter/nf_nat.h>
|
||||
#else
|
||||
# include <linux/netfilter/nf_nat.h>
|
||||
#endif
|
||||
#include "compat_xtables.h"
|
||||
#include "xt_DNETMAP.h"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Marek Kierdelewicz <marek@piasta.pl>");
|
||||
MODULE_DESCRIPTION(
|
||||
"Xtables: dynamic two-way 1:1 NAT mapping of IPv4 addresses");
|
||||
MODULE_ALIAS("ipt_DNETMAP");
|
||||
|
||||
static unsigned int default_ttl = 600;
|
||||
static unsigned int proc_perms = S_IRUGO | S_IWUSR;
|
||||
static unsigned int proc_uid;
|
||||
@@ -70,25 +61,18 @@ MODULE_PARM_DESC(whole_prefix,
|
||||
static unsigned int jtimeout;
|
||||
|
||||
struct dnetmap_entry {
|
||||
struct list_head list;
|
||||
/* priv2entry */
|
||||
struct list_head glist;
|
||||
/* pub2entry */
|
||||
struct list_head grlist;
|
||||
struct list_head lru_list;
|
||||
__be32 prenat_addr;
|
||||
__be32 postnat_addr;
|
||||
struct list_head list, glist, grlist, lru_list;
|
||||
__be32 prenat_addr, postnat_addr;
|
||||
__u8 flags;
|
||||
unsigned long stamp;
|
||||
struct dnetmap_prefix *prefix;
|
||||
};
|
||||
|
||||
struct dnetmap_prefix {
|
||||
struct nf_nat_ipv4_multi_range_compat prefix;
|
||||
char prefix_str[16];
|
||||
struct nf_nat_range prefix;
|
||||
char prefix_str[20];
|
||||
#ifdef CONFIG_PROC_FS
|
||||
char proc_str_data[20];
|
||||
char proc_str_stat[25];
|
||||
char proc_str_data[20], proc_str_stat[25];
|
||||
#endif
|
||||
struct list_head elist; // element list head
|
||||
struct list_head list; // prefix list
|
||||
@@ -109,28 +93,19 @@ struct dnetmap_net {
|
||||
struct list_head *dnetmap_iphash;
|
||||
};
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)
|
||||
static int dnetmap_net_id;
|
||||
static inline struct dnetmap_net *dnetmap_pernet(struct net *net)
|
||||
{
|
||||
return net_generic(net, dnetmap_net_id);
|
||||
}
|
||||
#else
|
||||
struct dnetmap_net *dnetmap;
|
||||
#define dnetmap_pernet(x) dnetmap
|
||||
#endif
|
||||
|
||||
static DEFINE_SPINLOCK(dnetmap_lock);
|
||||
static DEFINE_MUTEX(dnetmap_mutex);
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
static const struct file_operations dnetmap_tg_fops;
|
||||
static const struct proc_ops dnetmap_tg_fops, dnetmap_stat_proc_fops;
|
||||
#endif
|
||||
|
||||
static int dnetmap_stat_proc_read(char __user *buffer, char **start,
|
||||
off_t offset, int length, int *eof,
|
||||
void *data);
|
||||
|
||||
static inline unsigned int dnetmap_entry_hash(const __be32 addr)
|
||||
{
|
||||
return ntohl(addr) & (hash_size - 1);
|
||||
@@ -140,9 +115,7 @@ static struct dnetmap_entry *
|
||||
dnetmap_entry_lookup(struct dnetmap_net *dnetmap_net, const __be32 addr)
|
||||
{
|
||||
struct dnetmap_entry *e;
|
||||
unsigned int h;
|
||||
|
||||
h = dnetmap_entry_hash(addr);
|
||||
unsigned int h = dnetmap_entry_hash(addr);
|
||||
|
||||
list_for_each_entry(e, &dnetmap_net->dnetmap_iphash[h], glist)
|
||||
if (memcmp(&e->prenat_addr, &addr, sizeof(addr)) == 0)
|
||||
@@ -154,9 +127,7 @@ static struct dnetmap_entry *
|
||||
dnetmap_entry_rlookup(struct dnetmap_net *dnetmap_net, const __be32 addr)
|
||||
{
|
||||
struct dnetmap_entry *e;
|
||||
unsigned int h;
|
||||
|
||||
h = dnetmap_entry_hash(addr);
|
||||
unsigned int h = dnetmap_entry_hash(addr);
|
||||
|
||||
list_for_each_entry(e, &dnetmap_net->dnetmap_iphash[hash_size + h],
|
||||
grlist)
|
||||
@@ -179,7 +150,7 @@ dnetmap_addr_in_prefix(struct dnetmap_net *dnetmap_net, const __be32 addr,
|
||||
|
||||
static struct dnetmap_prefix *
|
||||
dnetmap_prefix_lookup(struct dnetmap_net *dnetmap_net,
|
||||
const struct nf_nat_ipv4_multi_range_compat *mr)
|
||||
const struct nf_nat_range *mr)
|
||||
{
|
||||
struct dnetmap_prefix *p;
|
||||
|
||||
@@ -258,7 +229,7 @@ static int dnetmap_tg_check(const struct xt_tgchk_param *par)
|
||||
{
|
||||
struct dnetmap_net *dnetmap_net = dnetmap_pernet(par->net);
|
||||
const struct xt_DNETMAP_tginfo *tginfo = par->targinfo;
|
||||
const struct nf_nat_ipv4_multi_range_compat *mr = &tginfo->prefix;
|
||||
const struct nf_nat_range *mr = &tginfo->prefix;
|
||||
struct dnetmap_prefix *p;
|
||||
struct dnetmap_entry *e;
|
||||
#ifdef CONFIG_PROC_FS
|
||||
@@ -274,14 +245,10 @@ static int dnetmap_tg_check(const struct xt_tgchk_param *par)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!(mr->range[0].flags & NF_NAT_RANGE_MAP_IPS)) {
|
||||
if (!(mr->flags & NF_NAT_RANGE_MAP_IPS)) {
|
||||
pr_debug("DNETMAP:check: bad MAP_IPS.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (mr->rangesize != 1) {
|
||||
pr_debug("DNETMAP:check: bad rangesize %u.\n", mr->rangesize);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&dnetmap_mutex);
|
||||
p = dnetmap_prefix_lookup(dnetmap_net, mr);
|
||||
@@ -307,15 +274,15 @@ static int dnetmap_tg_check(const struct xt_tgchk_param *par)
|
||||
INIT_LIST_HEAD(&p->lru_list);
|
||||
INIT_LIST_HEAD(&p->elist);
|
||||
|
||||
ip_min = ntohl(mr->range[0].min_ip) + (whole_prefix == 0);
|
||||
ip_max = ntohl(mr->range[0].max_ip) - (whole_prefix == 0);
|
||||
ip_min = ntohl(mr->min_addr.ip) + (whole_prefix == 0);
|
||||
ip_max = ntohl(mr->max_addr.ip) - (whole_prefix == 0);
|
||||
|
||||
sprintf(p->prefix_str, NIPQUAD_FMT "/%u", NIPQUAD(mr->range[0].min_ip),
|
||||
sprintf(p->prefix_str, "%pI4/%u", &mr->min_addr.ip,
|
||||
33 - ffs(~(ip_min ^ ip_max)));
|
||||
#ifdef CONFIG_PROC_FS
|
||||
sprintf(p->proc_str_data, NIPQUAD_FMT "_%u", NIPQUAD(mr->range[0].min_ip),
|
||||
sprintf(p->proc_str_data, "%pI4_%u", &mr->min_addr.ip,
|
||||
33 - ffs(~(ip_min ^ ip_max)));
|
||||
sprintf(p->proc_str_stat, NIPQUAD_FMT "_%u_stat", NIPQUAD(mr->range[0].min_ip),
|
||||
sprintf(p->proc_str_stat, "%pI4_%u_stat", &mr->min_addr.ip,
|
||||
33 - ffs(~(ip_min ^ ip_max)));
|
||||
#endif
|
||||
printk(KERN_INFO KBUILD_MODNAME ": new prefix %s\n", p->prefix_str);
|
||||
@@ -344,21 +311,20 @@ static int dnetmap_tg_check(const struct xt_tgchk_param *par)
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
pde_data->uid = proc_uid;
|
||||
pde_data->gid = proc_gid;
|
||||
proc_set_user(pde_data, make_kuid(&init_user_ns, proc_uid),
|
||||
make_kgid(&init_user_ns, proc_gid));
|
||||
|
||||
/* statistics */
|
||||
pde_stat = create_proc_entry(p->proc_str_stat, proc_perms,
|
||||
dnetmap_net->xt_dnetmap);
|
||||
pde_stat = proc_create_data(p->proc_str_stat, proc_perms,
|
||||
dnetmap_net->xt_dnetmap,
|
||||
&dnetmap_stat_proc_fops, p);
|
||||
if (pde_stat == NULL) {
|
||||
kfree(p);
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
pde_stat->data = p;
|
||||
pde_stat->read_proc = dnetmap_stat_proc_read;
|
||||
pde_stat->uid = proc_uid;
|
||||
pde_stat->gid = proc_gid;
|
||||
proc_set_user(pde_stat, make_kuid(&init_user_ns, proc_uid),
|
||||
make_kgid(&init_user_ns, proc_gid));
|
||||
#endif
|
||||
|
||||
spin_lock_bh(&dnetmap_lock);
|
||||
@@ -372,30 +338,27 @@ out:
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
dnetmap_tg(struct sk_buff **pskb, const struct xt_action_param *par)
|
||||
dnetmap_tg(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
{
|
||||
struct sk_buff *skb = *pskb;
|
||||
struct net *net = dev_net(par->in ? par->in : par->out);
|
||||
struct net *net = dev_net(par->state->in ? par->state->in : par->state->out);
|
||||
struct dnetmap_net *dnetmap_net = dnetmap_pernet(net);
|
||||
struct nf_conn *ct;
|
||||
enum ip_conntrack_info ctinfo;
|
||||
__be32 prenat_ip, postnat_ip, prenat_ip_prev;
|
||||
const struct xt_DNETMAP_tginfo *tginfo = par->targinfo;
|
||||
const struct nf_nat_ipv4_multi_range_compat *mr = &tginfo->prefix;
|
||||
struct nf_nat_ipv4_range newrange;
|
||||
const struct nf_nat_range *mr = &tginfo->prefix;
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0)
|
||||
struct nf_nat_range2 newrange;
|
||||
#else
|
||||
struct nf_nat_range newrange;
|
||||
#endif
|
||||
struct dnetmap_entry *e;
|
||||
struct dnetmap_prefix *p;
|
||||
__s32 jttl;
|
||||
|
||||
NF_CT_ASSERT(par->hooknum == NF_INET_POST_ROUTING ||
|
||||
par->hooknum == NF_INET_LOCAL_OUT ||
|
||||
par->hooknum == NF_INET_PRE_ROUTING);
|
||||
ct = nf_ct_get(skb, &ctinfo);
|
||||
|
||||
jttl = tginfo->flags & XT_DNETMAP_TTL ? tginfo->ttl * HZ : jtimeout;
|
||||
unsigned int hooknum = par->state->hook;
|
||||
struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
|
||||
__s32 jttl = tginfo->flags & XT_DNETMAP_TTL ? tginfo->ttl * HZ : jtimeout;
|
||||
|
||||
/* in prerouting we try to map postnat-ip to prenat-ip */
|
||||
if (par->hooknum == NF_INET_PRE_ROUTING) {
|
||||
if (hooknum == NF_INET_PRE_ROUTING) {
|
||||
postnat_ip = ip_hdr(skb)->daddr;
|
||||
|
||||
spin_lock_bh(&dnetmap_lock);
|
||||
@@ -408,7 +371,7 @@ dnetmap_tg(struct sk_buff **pskb, const struct xt_action_param *par)
|
||||
/* if prefix is specified, we check if
|
||||
it matches lookedup entry */
|
||||
if (tginfo->flags & XT_DNETMAP_PREFIX)
|
||||
if (memcmp(mr, &e->prefix, sizeof(*mr)))
|
||||
if (memcmp(mr, &e->prefix->prefix, sizeof(*mr)))
|
||||
goto no_rev_map;
|
||||
/* don't reset ttl if flag is set */
|
||||
if (jttl >= 0 && (! (e->flags & XT_DNETMAP_STATIC) ) ) {
|
||||
@@ -419,15 +382,14 @@ dnetmap_tg(struct sk_buff **pskb, const struct xt_action_param *par)
|
||||
|
||||
spin_unlock_bh(&dnetmap_lock);
|
||||
|
||||
newrange = ((struct nf_nat_ipv4_range) {
|
||||
mr->range[0].flags | NF_NAT_RANGE_MAP_IPS,
|
||||
e->prenat_addr, e->prenat_addr,
|
||||
mr->range[0].min, mr->range[0].max});
|
||||
|
||||
/* Hand modified range to generic setup. */
|
||||
memset(&newrange, 0, sizeof(newrange));
|
||||
newrange.flags = mr->flags | NF_NAT_RANGE_MAP_IPS;
|
||||
newrange.min_addr.ip = e->prenat_addr;
|
||||
newrange.max_addr.ip = e->prenat_addr;
|
||||
newrange.min_proto = mr->min_proto;
|
||||
newrange.max_proto = mr->max_proto;
|
||||
return nf_nat_setup_info(ct, &newrange,
|
||||
HOOK2MANIP(par->hooknum));
|
||||
|
||||
HOOK2MANIP(hooknum));
|
||||
}
|
||||
|
||||
prenat_ip = ip_hdr(skb)->saddr;
|
||||
@@ -448,8 +410,8 @@ bind_new_prefix:
|
||||
if (e->prenat_addr != 0 && time_before(jiffies, e->stamp)) {
|
||||
if (!disable_log && ! (p->flags & XT_DNETMAP_FULL) ){
|
||||
printk(KERN_INFO KBUILD_MODNAME
|
||||
": ip " NIPQUAD_FMT " - no free adresses in prefix %s\n",
|
||||
NIPQUAD(prenat_ip), p->prefix_str);
|
||||
": ip %pI4 - no free adresses in prefix %s\n",
|
||||
&prenat_ip, p->prefix_str);
|
||||
p->flags |= XT_DNETMAP_FULL;
|
||||
}
|
||||
goto no_free_ip;
|
||||
@@ -462,8 +424,8 @@ bind_new_prefix:
|
||||
prenat_ip_prev = e->prenat_addr;
|
||||
if (!disable_log)
|
||||
printk(KERN_INFO KBUILD_MODNAME
|
||||
": timeout binding " NIPQUAD_FMT " -> " NIPQUAD_FMT "\n",
|
||||
NIPQUAD(prenat_ip_prev), NIPQUAD(postnat_ip) );
|
||||
": timeout binding %pI4 -> %pI4\n",
|
||||
&prenat_ip_prev, &postnat_ip);
|
||||
list_del(&e->glist);
|
||||
list_del(&e->grlist);
|
||||
}
|
||||
@@ -480,18 +442,16 @@ bind_new_prefix:
|
||||
(postnat_ip)]);
|
||||
if (!disable_log)
|
||||
printk(KERN_INFO KBUILD_MODNAME
|
||||
": add binding " NIPQUAD_FMT " -> " NIPQUAD_FMT "\n",
|
||||
NIPQUAD(prenat_ip),NIPQUAD(postnat_ip));
|
||||
|
||||
": add binding %pI4 -> %pI4\n",
|
||||
&prenat_ip, &postnat_ip);
|
||||
} else {
|
||||
|
||||
if (!(tginfo->flags & XT_DNETMAP_REUSE) && !(e->flags & XT_DNETMAP_STATIC))
|
||||
if (time_before(e->stamp, jiffies) && p != e->prefix) {
|
||||
if (!disable_log)
|
||||
printk(KERN_INFO KBUILD_MODNAME
|
||||
": timeout binding " NIPQUAD_FMT " -> " NIPQUAD_FMT "\n",
|
||||
NIPQUAD(e->prenat_addr),
|
||||
NIPQUAD(e->postnat_addr));
|
||||
": timeout binding %pI4 -> %pI4\n",
|
||||
&e->prenat_addr, &e->postnat_addr);
|
||||
list_del(&e->glist);
|
||||
list_del(&e->grlist);
|
||||
e->prenat_addr = 0;
|
||||
@@ -509,14 +469,13 @@ bind_new_prefix:
|
||||
|
||||
spin_unlock_bh(&dnetmap_lock);
|
||||
|
||||
newrange = ((struct nf_nat_ipv4_range) {
|
||||
mr->range[0].flags | NF_NAT_RANGE_MAP_IPS,
|
||||
postnat_ip, postnat_ip,
|
||||
mr->range[0].min, mr->range[0].max});
|
||||
|
||||
/* Hand modified range to generic setup. */
|
||||
return nf_nat_setup_info(ct, &newrange, HOOK2MANIP(par->hooknum));
|
||||
|
||||
memset(&newrange, 0, sizeof(newrange));
|
||||
newrange.flags = mr->flags | NF_NAT_RANGE_MAP_IPS;
|
||||
newrange.min_addr.ip = postnat_ip;
|
||||
newrange.max_addr.ip = postnat_ip;
|
||||
newrange.min_proto = mr->min_proto;
|
||||
newrange.max_proto = mr->max_proto;
|
||||
return nf_nat_setup_info(ct, &newrange, HOOK2MANIP(par->state->hook));
|
||||
no_rev_map:
|
||||
no_free_ip:
|
||||
spin_unlock_bh(&dnetmap_lock);
|
||||
@@ -528,7 +487,7 @@ static void dnetmap_tg_destroy(const struct xt_tgdtor_param *par)
|
||||
{
|
||||
struct dnetmap_net *dnetmap_net = dnetmap_pernet(par->net);
|
||||
const struct xt_DNETMAP_tginfo *tginfo = par->targinfo;
|
||||
const struct nf_nat_ipv4_multi_range_compat *mr = &tginfo->prefix;
|
||||
const struct nf_nat_range *mr = &tginfo->prefix;
|
||||
struct dnetmap_prefix *p;
|
||||
|
||||
if (!(tginfo->flags & XT_DNETMAP_PREFIX))
|
||||
@@ -591,12 +550,13 @@ static int dnetmap_seq_show(struct seq_file *seq, void *v)
|
||||
const struct dnetmap_entry *e = v;
|
||||
|
||||
if((e->flags & XT_DNETMAP_STATIC) == 0){
|
||||
seq_printf(seq, NIPQUAD_FMT " -> " NIPQUAD_FMT " --- ttl: %d lasthit: %lu\n",
|
||||
NIPQUAD(e->prenat_addr), NIPQUAD(e->postnat_addr),
|
||||
(int)(e->stamp - jiffies) / HZ, (e->stamp - jtimeout) / HZ);
|
||||
seq_printf(seq, "%pI4 -> %pI4 --- ttl: %d lasthit: %lu\n",
|
||||
&e->prenat_addr, &e->postnat_addr,
|
||||
(int)(e->stamp - jiffies) / HZ,
|
||||
(e->stamp - jtimeout) / HZ);
|
||||
}else{
|
||||
seq_printf(seq, NIPQUAD_FMT " -> " NIPQUAD_FMT " --- ttl: S lasthit: S\n",
|
||||
NIPQUAD(e->prenat_addr), NIPQUAD(e->postnat_addr));
|
||||
seq_printf(seq, "%pI4 -> %pI4 --- ttl: S lasthit: S\n",
|
||||
&e->prenat_addr, &e->postnat_addr);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -610,27 +570,24 @@ static const struct seq_operations dnetmap_seq_ops = {
|
||||
|
||||
static int dnetmap_seq_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct proc_dir_entry *pde = PDE(inode);
|
||||
struct dnetmap_iter_state *st;
|
||||
|
||||
st = __seq_open_private(file, &dnetmap_seq_ops, sizeof(*st));
|
||||
if (st == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
st->p = pde->data;
|
||||
st->p = PDE_DATA(inode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
dnetmap_tg_proc_write(struct file *file, const char __user *input,size_t size, loff_t *loff)
|
||||
{
|
||||
const struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
|
||||
struct dnetmap_prefix *p = pde->data;
|
||||
struct dnetmap_prefix *p = PDE_DATA(file_inode(file));
|
||||
struct dnetmap_entry *e;
|
||||
char buf[sizeof("+192.168.100.100:200.200.200.200")];
|
||||
const char *c = buf;
|
||||
const char *c2;
|
||||
//union nf_inet_addr addr = {};
|
||||
__be32 addr1,addr2;
|
||||
bool add;
|
||||
char str[25];
|
||||
@@ -721,8 +678,8 @@ dnetmap_tg_proc_write(struct file *file, const char __user *input,size_t size, l
|
||||
if(e != NULL){
|
||||
if (!disable_log)
|
||||
printk(KERN_INFO KBUILD_MODNAME
|
||||
": timeout binding " NIPQUAD_FMT " -> " NIPQUAD_FMT "\n",
|
||||
NIPQUAD(e->prenat_addr), NIPQUAD(e->postnat_addr) );
|
||||
": timeout binding %pI4 -> %pI4\n",
|
||||
&e->prenat_addr, &e->postnat_addr);
|
||||
list_del(&e->glist);
|
||||
list_del(&e->grlist);
|
||||
}else{
|
||||
@@ -744,7 +701,7 @@ dnetmap_tg_proc_write(struct file *file, const char __user *input,size_t size, l
|
||||
(e->postnat_addr)]);
|
||||
list_del(&e->lru_list);
|
||||
|
||||
sprintf(str, NIPQUAD_FMT ":" NIPQUAD_FMT, NIPQUAD(addr1),NIPQUAD(addr2));
|
||||
sprintf(str, "%pI4:%pI4", &addr1, &addr2);
|
||||
printk(KERN_INFO KBUILD_MODNAME ": adding static binding %s\n", str);
|
||||
|
||||
// case of removing binding
|
||||
@@ -760,8 +717,8 @@ dnetmap_tg_proc_write(struct file *file, const char __user *input,size_t size, l
|
||||
if(e != NULL){
|
||||
if (!disable_log)
|
||||
printk(KERN_INFO KBUILD_MODNAME
|
||||
": remove binding " NIPQUAD_FMT " -> " NIPQUAD_FMT "\n",
|
||||
NIPQUAD(e->prenat_addr), NIPQUAD(e->postnat_addr) );
|
||||
": remove binding %pI4 -> %pI4\n",
|
||||
&e->prenat_addr, &e->postnat_addr);
|
||||
list_del(&e->glist);
|
||||
list_del(&e->grlist);
|
||||
if(e->flags & XT_DNETMAP_STATIC){
|
||||
@@ -791,20 +748,17 @@ dnetmap_tg_proc_write(struct file *file, const char __user *input,size_t size, l
|
||||
}
|
||||
|
||||
|
||||
static const struct file_operations dnetmap_tg_fops = {
|
||||
.open = dnetmap_seq_open,
|
||||
.read = seq_read,
|
||||
.write = dnetmap_tg_proc_write,
|
||||
.release = seq_release_private,
|
||||
.owner = THIS_MODULE,
|
||||
static const struct proc_ops dnetmap_tg_fops = {
|
||||
.proc_open = dnetmap_seq_open,
|
||||
.proc_read = seq_read,
|
||||
.proc_write = dnetmap_tg_proc_write,
|
||||
.proc_release = seq_release_private,
|
||||
};
|
||||
|
||||
/* for statistics */
|
||||
static int dnetmap_stat_proc_read(char __user *buffer, char **start,
|
||||
off_t offset, int length, int *eof,
|
||||
void *data)
|
||||
static int dnetmap_stat_proc_show(struct seq_file *m, void *data)
|
||||
{
|
||||
const struct dnetmap_prefix *p = data;
|
||||
const struct dnetmap_prefix *p = m->private;
|
||||
struct dnetmap_entry *e;
|
||||
unsigned int used, used_static, all;
|
||||
long int ttl, sum_ttl;
|
||||
@@ -830,16 +784,25 @@ static int dnetmap_stat_proc_read(char __user *buffer, char **start,
|
||||
}
|
||||
|
||||
sum_ttl = used > 0 ? sum_ttl / (used * HZ) : 0;
|
||||
sprintf(buffer, "%u %u %u %ld %s\n", used, used_static, all, sum_ttl,(p->flags & XT_DNETMAP_PERSISTENT ? "persistent" : ""));
|
||||
|
||||
if (length >= strlen(buffer))
|
||||
*eof = true;
|
||||
seq_printf(m, "%u %u %u %ld %s\n", used, used_static, all, sum_ttl,(p->flags & XT_DNETMAP_PERSISTENT ? "persistent" : ""));
|
||||
|
||||
spin_unlock_bh(&dnetmap_lock);
|
||||
|
||||
return strlen(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dnetmap_stat_proc_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, dnetmap_stat_proc_show, PDE_DATA(inode));
|
||||
}
|
||||
|
||||
static const struct proc_ops dnetmap_stat_proc_fops = {
|
||||
.proc_open = dnetmap_stat_proc_open,
|
||||
.proc_read = seq_read,
|
||||
.proc_lseek = seq_lseek,
|
||||
.proc_release = single_release,
|
||||
};
|
||||
|
||||
static int __net_init dnetmap_proc_net_init(struct net *net)
|
||||
{
|
||||
struct dnetmap_net *dnetmap_net = dnetmap_pernet(net);
|
||||
@@ -852,7 +815,7 @@ static int __net_init dnetmap_proc_net_init(struct net *net)
|
||||
|
||||
static void __net_exit dnetmap_proc_net_exit(struct net *net)
|
||||
{
|
||||
proc_net_remove(net, "xt_DNETMAP");
|
||||
remove_proc_entry("xt_DNETMAP", net->proc_net);
|
||||
}
|
||||
|
||||
#else
|
||||
@@ -871,13 +834,6 @@ static int __net_init dnetmap_net_init(struct net *net)
|
||||
struct dnetmap_net *dnetmap_net = dnetmap_pernet(net);
|
||||
int i;
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34)
|
||||
dnetmap = kmalloc(sizeof(struct dnetmap_net),GFP_ATOMIC);
|
||||
if (dnetmap == NULL)
|
||||
return -ENOMEM;
|
||||
dnetmap_net = dnetmap;
|
||||
#endif
|
||||
|
||||
dnetmap_net->dnetmap_iphash = kmalloc(sizeof(struct list_head) *
|
||||
hash_size * 2, GFP_ATOMIC);
|
||||
if (dnetmap_net->dnetmap_iphash == NULL)
|
||||
@@ -906,20 +862,15 @@ static void __net_exit dnetmap_net_exit(struct net *net)
|
||||
mutex_unlock(&dnetmap_mutex);
|
||||
|
||||
kfree(dnetmap_net->dnetmap_iphash);
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34)
|
||||
kfree(dnetmap_net);
|
||||
#endif
|
||||
|
||||
dnetmap_proc_net_exit(net);
|
||||
}
|
||||
|
||||
static struct pernet_operations dnetmap_net_ops = {
|
||||
.init = dnetmap_net_init,
|
||||
.exit = dnetmap_net_exit,
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)
|
||||
.id = &dnetmap_net_id,
|
||||
.size = sizeof(struct dnetmap_net),
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct xt_target dnetmap_tg_reg __read_mostly = {
|
||||
@@ -965,6 +916,18 @@ static void __exit dnetmap_tg_exit(void)
|
||||
xt_unregister_target(&dnetmap_tg_reg);
|
||||
unregister_pernet_subsys(&dnetmap_net_ops);
|
||||
}
|
||||
#else /* CONFIG_NF_NAT */
|
||||
static int __init dnetmap_tg_init(void)
|
||||
{
|
||||
pr_err("CONFIG_NF_NAT is not available in your kernel, hence this module cannot function.");
|
||||
return -EINVAL;
|
||||
}
|
||||
static void __exit dnetmap_tg_exit(void) {}
|
||||
#endif
|
||||
|
||||
module_init(dnetmap_tg_init);
|
||||
module_exit(dnetmap_tg_exit);
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Marek Kierdelewicz <marek@piasta.pl>");
|
||||
MODULE_DESCRIPTION("Xtables: dynamic two-way 1:1 NAT mapping of IPv4 addresses");
|
||||
MODULE_ALIAS("ipt_DNETMAP");
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user