mirror of
git://git.code.sf.net/p/xtables-addons/xtables-addons
synced 2025-09-20 19:44:56 +02:00
Compare commits
168 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
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 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,7 +1,10 @@
|
||||
*.gcno
|
||||
*.la
|
||||
*.lo
|
||||
*.loT
|
||||
*.mod
|
||||
*.o
|
||||
.cache.mk
|
||||
.deps/
|
||||
.dirstamp
|
||||
.libs/
|
||||
|
7
INSTALL
7
INSTALL
@@ -12,16 +12,17 @@ in combination with the kernel's Kbuild system.
|
||||
Supported configurations for this release
|
||||
=========================================
|
||||
|
||||
* iptables >= 1.4.5
|
||||
* iptables >= 1.6.0
|
||||
|
||||
* kernel-devel >= 3.7
|
||||
* kernel-devel >= 4.15
|
||||
with prepared build/output directory
|
||||
- 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-1.x if you need support for Linux < 3.7.
|
||||
Use xtables-addons-2.x if you need support for Linux < 4.15.)
|
||||
|
||||
|
||||
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,9 +11,6 @@ FORCE:
|
||||
xtables-addons.8: FORCE
|
||||
${MAKE} -f Makefile.mans all;
|
||||
|
||||
install-exec-hook:
|
||||
depmod -a || :;
|
||||
|
||||
clean-local-mans:
|
||||
${MAKE} -f Makefile.mans clean;
|
||||
|
||||
|
@@ -40,4 +40,4 @@ targets.man: .manpages.lst ${wcman_targets}
|
||||
$(call man_run,${wlist_targets})
|
||||
|
||||
clean:
|
||||
rm -f xtables-addons.8 matches.man targets.man
|
||||
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
|
||||
|
38
configure.ac
38
configure.ac
@@ -1,4 +1,4 @@
|
||||
AC_INIT([xtables-addons], [2.3])
|
||||
AC_INIT([xtables-addons], [3.11])
|
||||
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,29 +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 10; then
|
||||
if test "$kmajor" -gt 5 -o "$kmajor" -eq 5 -a "$kminor" -gt 9; then
|
||||
echo "WARNING: That kernel version is not officially supported yet. Continue at own luck.";
|
||||
elif test "$kmajor" -eq 3 -a "$kminor" -ge 7; then
|
||||
:;
|
||||
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,6 +1,162 @@
|
||||
v3.11 (2020-09-06)
|
||||
==================
|
||||
- Support for up to Linux 5.9
|
||||
|
||||
HEAD
|
||||
====
|
||||
|
||||
v3.10 (2020-07-28)
|
||||
==================
|
||||
- Support for up to Linux 5.8
|
||||
|
||||
|
||||
v3.9 (2020-02-25)
|
||||
=================
|
||||
- Support for Linux 5.6 procfs changes
|
||||
|
||||
|
||||
v3.8 (2020-02-03)
|
||||
=================
|
||||
- Support for Linux 5.5
|
||||
- xt_geoip_build now expects the DBIP format as input,
|
||||
Maxmind is thrown out.
|
||||
|
||||
|
||||
v3.7 (2019-12-01)
|
||||
=================
|
||||
Fixes:
|
||||
- xt_geoip: fix in6_addr little-endian byte swapping
|
||||
|
||||
|
||||
v3.6 (2019-11-20)
|
||||
=================
|
||||
Enhancements:
|
||||
- support for up to Linux 5.4
|
||||
|
||||
|
||||
v3.5 (2019-09-10)
|
||||
=================
|
||||
Enhancements:
|
||||
- xt_DELUDE, xt_TARPIT: added additional code needed to work with
|
||||
bridges from Linux 5.0 onwards.
|
||||
|
||||
|
||||
v3.4 (2019-09-06)
|
||||
=================
|
||||
Enhancements:
|
||||
- support for up to Linux 5.3
|
||||
- xt_PROTO module
|
||||
|
||||
|
||||
v3.3 (2019-03-07)
|
||||
=================
|
||||
Enhancements:
|
||||
- support for Linux 5.0
|
||||
|
||||
|
||||
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+.
|
||||
|
||||
|
||||
v3.1 (2018-08-14)
|
||||
=================
|
||||
Enhancements:
|
||||
- support for Linux 4.17, 4.18
|
||||
|
||||
|
||||
v3.0 (2018-02-12)
|
||||
=================
|
||||
Enhancements:
|
||||
- support for Linux 4.15, 4.16
|
||||
Changes:
|
||||
- remove support for Linux 3.7--4.14
|
||||
|
||||
|
||||
v2.14 (2017-11-22)
|
||||
==================
|
||||
Enhancements:
|
||||
- support for Linux up to 4.14
|
||||
Fixes:
|
||||
- xt_DNETMAP: fix some reports from PVSStudio (a static checker)
|
||||
|
||||
|
||||
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)
|
||||
@@ -41,514 +197,5 @@ Changes:
|
||||
Enhancements:
|
||||
- Support for Linux 3.7
|
||||
|
||||
If you want to use Xtables-addons with kernels older than 3.7,
|
||||
use the addons 1.x series, which continues to be maintained for
|
||||
the time being.
|
||||
|
||||
|
||||
v1.47.1 (2010-10-15)
|
||||
====================
|
||||
Enhancements:
|
||||
- xt_psd gained IPv6 support
|
||||
Notes for this release:
|
||||
- Linux 3.7+ is expressly unsupported by this release.
|
||||
|
||||
|
||||
v1.46 (2012-08-23)
|
||||
==================
|
||||
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
|
||||
|
||||
|
||||
v1.45 (2012-07-16)
|
||||
==================
|
||||
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)
|
||||
|
||||
|
||||
v1.44 (2012-07-15)
|
||||
==================
|
||||
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
|
||||
|
||||
|
||||
v1.43 (2012-06-30)
|
||||
==================
|
||||
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
|
||||
|
||||
|
||||
v1.42 (2012-04-05)
|
||||
==================
|
||||
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
|
||||
|
||||
|
||||
v1.41 (2012-01-04)
|
||||
==================
|
||||
Changes:
|
||||
- Deactivate build of ipset-genl by default.
|
||||
I think the original ipset package can now take over, given there are
|
||||
a handful of kernels (2.6.39 onwards) that do not need patching.
|
||||
Enhancements:
|
||||
- Support for Linux 3.2
|
||||
|
||||
|
||||
v1.40 (2011-11-30)
|
||||
==================
|
||||
Fixes:
|
||||
- build: the code actually requires at least iptables 1.4.5 (would yield a
|
||||
compile error otherwise), make sure configure checks for it; update INSTALL
|
||||
- xt_ECHO: fix kernel warning about RTAX_HOPLIMIT being used
|
||||
- xt_ipv4options: fix an infinite loop
|
||||
Changes:
|
||||
- xt_ECHO: now calculates UDP checksum
|
||||
- Linux kernel versions below 2.6.32 are no longer officially
|
||||
supported, and will not be part of compilation testing.
|
||||
- update to ipset 6.10
|
||||
Enhancements:
|
||||
- xt_ECHO: IPv6 support
|
||||
|
||||
|
||||
v1.39 (2011-09-21)
|
||||
==================
|
||||
Fixes:
|
||||
- libxt_ACCOUNT: fix compilation after missing libxtables_CFLAGS
|
||||
- build: fix compilation after missing libxtables_CFLAGS in submodules
|
||||
- build: add missing linux/version.h includes where needed
|
||||
Changes:
|
||||
- Remove unsupported ipset 4.x from the Xtables-addons distribution
|
||||
- ipset: move ipset_errcode from src to library to avoid undefined reference
|
||||
- update to ipset 6.9.1
|
||||
|
||||
|
||||
v1.38 (2011-08-20)
|
||||
==================
|
||||
- xt_CHECKSUM: abort build when the feature is already provided by mainline
|
||||
- xt_SYSRQ: fix UDPLITE header lookup in IPv6
|
||||
- xt_TARPIT: fix kernel warning about RTAX_HOPLIMIT being used
|
||||
- xt_TEE: abort build when the feature is already provided by mainline
|
||||
- xt_ipp2p: support UDPLITE
|
||||
- xt_pknock: support UDPLITE
|
||||
- xt_psd: restore functionality with UDP
|
||||
- xt_psd: support UDPLITE
|
||||
- update to ipset 6.8
|
||||
- support for Linux 3.1
|
||||
|
||||
|
||||
v1.37 (2011-06-25)
|
||||
==================
|
||||
Fixes:
|
||||
- xt_SYSRQ: make IPv6 trigger work again
|
||||
- xt_SYSRQ: improve security: include host address in digest
|
||||
- xt_TARPIT: fix a kernel oops in --reset mode
|
||||
|
||||
|
||||
v1.36 (2011-06-03)
|
||||
==================
|
||||
Changes:
|
||||
- xt_geoip: avoid recursive function calls
|
||||
- xt_TARPIT: unlock for use in all tables
|
||||
- xt_TARPIT: honeypot and reset modes
|
||||
- update to ipset 6.7
|
||||
- support for Linux 3.0
|
||||
|
||||
|
||||
v1.35 (2011-04-11)
|
||||
==================
|
||||
Enhancements:
|
||||
- update to ipset 6.3
|
||||
* allow "new" as a commad alias to "create"
|
||||
* resolving IP addresses did not work at listing/saving sets, fixed
|
||||
* check ICMP and ICMPv6 with the set match and target in the testsuite
|
||||
* avoid possible syntax clashing at saving hostnames
|
||||
* fix linking with CONFIG_IPV6=n
|
||||
* sctp, udplite support for the hash:*port* types
|
||||
- ipset-genl: handle EAGAIN return value emitted from autoloader
|
||||
- ipset-genl: resolve nfgenmsg remains and fix spurious protocol abort
|
||||
|
||||
|
||||
v1.34 (2011-04-07)
|
||||
==================
|
||||
Fixes:
|
||||
- xt_pknock: avoid crash when hash TFM could not be allocated
|
||||
- xt_pknock: avoid inversion of rule lookup that led to warnings
|
||||
- xt_DNETMAP: add missing module alias
|
||||
- xt_DNETMAP: support for kernels below 2.6.34
|
||||
Changes:
|
||||
- Linux kernel versions below 2.6.29 are no longer officially
|
||||
supported, and will not be part of compilation testing.
|
||||
|
||||
|
||||
v1.33 (2011-02-02)
|
||||
==================
|
||||
Fixes:
|
||||
- build: restore functionality of `configure --without-kbuild`
|
||||
- build: fix objdir builds for ipset-5 (xt-a specific)
|
||||
- build: fix missing inclusion of dependency rules
|
||||
- xt_LOGMARK: fix detection of untracked connection for Linux >= 2.6.36
|
||||
Enhancements:
|
||||
- IPv6 support for xt_geoip
|
||||
- Update to ipset 5.3
|
||||
* make IPv4 and IPv6 address handling similar
|
||||
* show correct line numbers in restore output for parser errors
|
||||
- Update to ipset 5.4
|
||||
* fixed ICMP and ICMPv6 handling
|
||||
* fixed trailing whitespaces and pr_* messages
|
||||
* fixed module loading at create/header commands
|
||||
- build: support for Linux up to 2.6.38
|
||||
- build: preliminary support for iptables 1.4.11
|
||||
|
||||
|
||||
v1.32 (2011-01-04)
|
||||
==================
|
||||
Fixes:
|
||||
- Update to ipset 4.5
|
||||
* the iptreemap type used wrong gfp flags when deleting entries
|
||||
- Include ipset 5.2 with genetlink patch (beta)
|
||||
* no kernel patch needed, but requires Linux >= 2.6.35
|
||||
and thus needs to be manually enabled in mconfig
|
||||
|
||||
|
||||
v1.31 (2010-11-05)
|
||||
==================
|
||||
Fixes:
|
||||
- build: improve detection of kernel version and error handling
|
||||
Changes:
|
||||
- build: automatically derive Xtables module directory, thus
|
||||
--with-xtlibdir is no longer needed for ./configure in most cases
|
||||
(If I still see a distro using it, I will scold you for not
|
||||
reading this changelog.)
|
||||
Enhancements:
|
||||
- LOGMARK: print remaining lifetime of cts
|
||||
- xt_iface: allow matching against incoming/outgoing interface
|
||||
- libxt_gradm: match packets based on status of grsecurity RBAC
|
||||
(userspace part only - xt_gradm is in the grsec patch)
|
||||
|
||||
|
||||
v1.30 (2010-010-02)
|
||||
===================
|
||||
Fixes:
|
||||
- update to ipset 4.4
|
||||
* ipport{,ip,net}hash did not work with mixed "src" and "dst"
|
||||
destination parameters
|
||||
Changes:
|
||||
- deactivate building xt_TEE and xt_CHECKSUM by default, as these have been
|
||||
merged upstream in Linux 2.6.35 and 2.6.36, respectively.
|
||||
Distros still wishing to build this need to enable it in their build
|
||||
script, e.g. perl -i -pe 's{^build_TEE=.*}{build_TEE=m}' mconfig;
|
||||
|
||||
|
||||
v1.29 (2010-09-29)
|
||||
==================
|
||||
- compat_xtables: return bool for match_check and target_check in 2.6.23..34
|
||||
- ipset: enable building of ip_set_ipport{ip,net}hash.ko
|
||||
- support for Linux 2.6.36
|
||||
- SYSRQ: resolve compile error with Linux 2.6.36
|
||||
- TEE: resolve compile error with Linux 2.6.36
|
||||
- add workaround for broken linux-glibc-devel 2.6.34 userspace headers
|
||||
("implicit declaration of function 'ALIGN'")
|
||||
|
||||
|
||||
v1.28 (2010-07-24)
|
||||
==================
|
||||
- RAWNAT: IPv6 variants erroneously rejected masks /33-/128
|
||||
- new target xt_CHECKSUM
|
||||
- xt_length2: add support for IPv6 jumbograms
|
||||
- xt_geoip: fix possible out-of-bounds access
|
||||
- import xt_geoip database scripts
|
||||
|
||||
|
||||
v1.27 (2010-05-16)
|
||||
==================
|
||||
- further updates for the upcoming 2.6.35 changes
|
||||
|
||||
|
||||
v1.26 (2010-04-30)
|
||||
==================
|
||||
- compat_xtables: fix 2.6.34 compile error due to a typo
|
||||
|
||||
|
||||
v1.25 (2010-04-26)
|
||||
==================
|
||||
- TEE: do rechecksumming in PREROUTING too
|
||||
- TEE: decrease TTL on cloned packet
|
||||
- TEE: set dont-fragment on cloned packets
|
||||
- TEE: free skb when route lookup failed
|
||||
- TEE: do not limit use to mangle table
|
||||
- TEE: do not retain iif and mark on cloned packet
|
||||
- TEE: new loop detection logic
|
||||
- TEE: use less expensive pskb_copy
|
||||
- condition: remove unnecessary RCU protection
|
||||
|
||||
|
||||
v1.24 (2010-03-17)
|
||||
==================
|
||||
- build: fix build of userspace modules against old (pre-2.6.25)
|
||||
headers from linux-glibc-devel (/usr/include/linux)
|
||||
- ipp2p: updated bittorent command recognition
|
||||
- SYSRQ: let module load when crypto is unavailable
|
||||
- SYSRQ: allow processing of UDP-Lite
|
||||
|
||||
|
||||
v1.23 (2010-02-24)
|
||||
==================
|
||||
- build: support for Linux 2.6.34
|
||||
- build: remove unused --with-ksource option
|
||||
- build: remove unneeded --with-xtables option
|
||||
- build: fix compilations in RAWNAT, SYSRQ and length2 when CONFIG_IPV6=n
|
||||
- ipset: update to 4.2
|
||||
- ECHO: fix compilation w.r.t. skb_dst
|
||||
|
||||
|
||||
v1.22 (2010-01-22)
|
||||
==================
|
||||
- compat_xtables: support for 2.6.33 skb_iif changes
|
||||
- geoip: for FHS compliance use /usr/share/xt_geoip instead of /var/geoip
|
||||
- ipset: enable build of ip_set_setlist.ko
|
||||
- quota2: add the --no-change mode
|
||||
|
||||
|
||||
v1.21 (2009-12-09)
|
||||
==================
|
||||
- ACCOUNT: avoid collision with arp_tables setsockopt numbers
|
||||
- doc: fix option mismatch --gw/--gateway in libxt_TEE.man
|
||||
|
||||
|
||||
v1.20 (2009-11-19)
|
||||
==================
|
||||
- ipp2p: add more boundary checks
|
||||
- ipp2p: fix Gnutelle line ending detection
|
||||
- LOGMARK: remove unknown options from manpage
|
||||
- ACCOUNT: endianess-correctness
|
||||
- ipset: install manpage
|
||||
- ipset: fast forward to v4.1
|
||||
|
||||
|
||||
v1.19 (2009-10-12)
|
||||
==================
|
||||
- build: compile fixes for 2.6.31-rt
|
||||
- build: support for Linux 2.6.32
|
||||
- ipp2p: try to address underflows
|
||||
- psd: avoid potential crash when dealing with non-linear skbs
|
||||
- merge xt_ACCOUNT userspace utilities
|
||||
- added reworked xt_pknock module
|
||||
Changes from pknock v0.5:
|
||||
- pknock: "strict" and "checkip" flags were not displayed in `iptables -L`
|
||||
- pknock: the GC expire time's lower bound is now the default gc time
|
||||
(65000 msec) to avoid rendering anti-spoof protection in SPA mode useless
|
||||
- pknock: avoid crash on memory allocation failure and fix memleak
|
||||
- pknock: avoid fillup of peer table during DDoS
|
||||
- pknock: automatic closing of ports
|
||||
- pknock: make non-zero time mandatory for TCP mode
|
||||
- pknock: display only pknock mode and state relevant information in procfs
|
||||
- pknock: check interknock time only for !ST_ALLOWED peers
|
||||
- pknock: preserve time/autoclose values for rules added in
|
||||
reverse/arbitrary order
|
||||
- pknock: add a manpage
|
||||
|
||||
|
||||
v1.18 (2009-09-09)
|
||||
==================
|
||||
- build: support for Linux 2.6.31
|
||||
- ipset: fast forward to v3.2
|
||||
- quota2: support anonymous counters
|
||||
- quota2: reduce memory footprint for anonymous counters
|
||||
- quota2: extend locked period during cleanup (locking bugfix)
|
||||
- quota2: use strtoull instead of strtoul
|
||||
- merged xt_ACCOUNT module
|
||||
- merged xt_psd module
|
||||
|
||||
|
||||
v1.17 (2009-06-16)
|
||||
==================
|
||||
- IPMARK: print missing --shift parameter
|
||||
- build: use readlink -f in extensions/ipset/
|
||||
- build: support for Linux 2.6.30
|
||||
|
||||
|
||||
v1.16 (2009-05-27)
|
||||
==================
|
||||
- RAWNAT: make iptable_rawpost compile with 2.6.30-rc5
|
||||
- ipset: fast forward to 3.0
|
||||
|
||||
|
||||
v1.15 (2009-04-30)
|
||||
==================
|
||||
- build: add kernel version check to configure
|
||||
- condition: compile fix for 2.6.30-rc
|
||||
- condition: fix intrapositional negation sign
|
||||
- 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)
|
||||
=================
|
||||
- add the xt_length2 extension
|
||||
- xt_TEE: remove intrapositional '!' support
|
||||
- ipset: upgrade to ipset 2.4.7
|
||||
|
||||
|
||||
v1.8 (2009-01-10)
|
||||
=================
|
||||
- xt_TEE: IPv6 support
|
||||
- xt_TEE: do not include TOS value in routing decision
|
||||
- xt_TEE: fix switch-case inversion for name/IP display
|
||||
- xt_ipp2p: update manpages and help text
|
||||
- xt_ipp2p: remove log flooding
|
||||
- xt_portscan: update manpage about --grscan option caveats
|
||||
|
||||
|
||||
v1.7 (2008-12-25)
|
||||
=================
|
||||
- xt_ECHO: compile fix
|
||||
- avoid the use of "_init" which led to compile errors on some installations
|
||||
- build: do not unconditionally install ipset
|
||||
- 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
|
||||
|
||||
|
||||
v1.6 (2008-11-18)
|
||||
=================
|
||||
- build: support for Linux 2.6.17
|
||||
- build: compile fixes for 2.6.18 and 2.6.19
|
||||
- xt_ECHO: resolve compile errors in xt_ECHO
|
||||
- xt_ipp2p: parenthesize unaligned-access macros
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
v1.5.4.1 (2008-04-26)
|
||||
=====================
|
||||
- build: fix compile error for 2.6.18-stable
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
v1.5.3 (2008-03-22)
|
||||
===================
|
||||
- support for Linux 2.6.18
|
||||
- add xt_ECHO sample target
|
||||
- add reworked xt_geoip match
|
||||
|
||||
|
||||
v1.5.2 (2008-03-04)
|
||||
===================
|
||||
- build: support for GNU make < 3.81 which does not have $(realpath)
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
v1.5.0 (2008-02-11)
|
||||
===================
|
||||
Initial release with:
|
||||
- extensions: xt_LOGMARK, xt_TARPIT, xt_TEE
|
||||
- support for Linux >= 2.6.19
|
||||
If you want to use Xtables-addons with kernels older than 4.15,
|
||||
use the addons 2.x series.
|
||||
|
@@ -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)
|
||||
|
@@ -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>
|
||||
@@ -27,8 +28,12 @@
|
||||
#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"
|
||||
@@ -38,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
|
||||
@@ -73,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;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -100,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;
|
||||
|
||||
/* 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;
|
||||
struct ipt_acc_net {
|
||||
/* Spinlock used for manipulating the current accounting tables/data */
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -131,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;
|
||||
}
|
||||
|
||||
@@ -139,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;
|
||||
}
|
||||
|
||||
@@ -156,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]);
|
||||
}
|
||||
}
|
||||
free_page((unsigned long)mask_16);
|
||||
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)data);
|
||||
free_pages((unsigned long)data, 2);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -175,7 +182,8 @@ 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;
|
||||
|
||||
@@ -183,7 +191,7 @@ static int ipt_acc_table_insert(const char *name, __be32 ip, __be32 netmask)
|
||||
name, NIPQUAD(ip), NIPQUAD(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 - "
|
||||
@@ -207,7 +215,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;
|
||||
@@ -256,19 +264,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");
|
||||
@@ -283,10 +293,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);
|
||||
@@ -294,32 +305,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,
|
||||
@@ -474,22 +485,25 @@ 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);
|
||||
spin_unlock_bh(&ian->ipt_acc_lock);
|
||||
return XT_CONTINUE;
|
||||
}
|
||||
|
||||
@@ -501,7 +515,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;
|
||||
}
|
||||
|
||||
@@ -512,7 +526,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;
|
||||
}
|
||||
|
||||
@@ -523,7 +537,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;
|
||||
}
|
||||
|
||||
@@ -531,13 +545,13 @@ static unsigned int ipt_acc_target(struct sk_buff **pskb, const struct xt_action
|
||||
"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);
|
||||
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
|
||||
@@ -552,7 +566,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 */
|
||||
@@ -572,7 +586,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:"
|
||||
@@ -588,18 +603,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;
|
||||
@@ -630,18 +646,18 @@ 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 ((network_16->mask_24[b] =
|
||||
ipt_acc_zalloc_page()) == NULL) {
|
||||
printk("ACCOUNT: out of memory during copy of 16 bit "
|
||||
"network in ipt_acc_handle_prepare_read()\n");
|
||||
ipt_acc_data_free(dest->data, depth);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(network_16->mask_24[b], src_16->mask_24[b],
|
||||
sizeof(struct ipt_acc_mask_24));
|
||||
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 "
|
||||
"network in ipt_acc_handle_prepare_read()\n");
|
||||
ipt_acc_data_free(dest->data, depth);
|
||||
return -1;
|
||||
}
|
||||
|
||||
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 =
|
||||
@@ -651,35 +667,35 @@ 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 ((network_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"
|
||||
" in ipt_acc_handle_prepare_read()\n");
|
||||
ipt_acc_data_free(dest->data, depth);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(network_8->mask_16[a], src_8->mask_16[a],
|
||||
sizeof(struct ipt_acc_mask_16));
|
||||
|
||||
src_16 = src_8->mask_16[a];
|
||||
network_16 = network_8->mask_16[a];
|
||||
|
||||
for (b = 0; b <= 255; 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 24 bit network"
|
||||
" in ipt_acc_handle_prepare_read()\n");
|
||||
printk("ACCOUNT: out of memory during copy of 16 bit"
|
||||
" network in ipt_acc_handle_prepare_read()\n");
|
||||
ipt_acc_data_free(dest->data, depth);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(network_8->mask_16[a], src_8->mask_16[a],
|
||||
sizeof(struct ipt_acc_mask_16));
|
||||
|
||||
src_16 = src_8->mask_16[a];
|
||||
network_16 = network_8->mask_16[a];
|
||||
|
||||
for (b = 0; b <= 255; b++) {
|
||||
if (src_16->mask_24[b]) {
|
||||
if ((network_16->mask_24[b] =
|
||||
ipt_acc_zalloc_page()) == NULL) {
|
||||
printk("ACCOUNT: out of memory during copy of 16 bit"
|
||||
" network in ipt_acc_handle_prepare_read()\n");
|
||||
ipt_acc_data_free(dest->data, depth);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(network_16->mask_24[b], src_16->mask_24[b],
|
||||
sizeof(struct ipt_acc_mask_24));
|
||||
}
|
||||
}
|
||||
memcpy(network_16->mask_24[b], src_16->mask_24[b],
|
||||
sizeof(struct ipt_acc_mask_24));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -690,18 +706,19 @@ 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;
|
||||
@@ -731,7 +748,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)
|
||||
@@ -741,25 +759,26 @@ 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.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;
|
||||
handle_ip.dst_bytes = data->ip[i].dst_bytes;
|
||||
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;
|
||||
handle_ip.dst_bytes = data->ip[i].dst_bytes;
|
||||
|
||||
/* 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,
|
||||
*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);
|
||||
*tmpbuf_pos += handle_ip_size;
|
||||
/* Temporary buffer full? Flush to userspace */
|
||||
if (*tmpbuf_pos + handle_ip_size >= PAGE_SIZE) {
|
||||
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(ian->ipt_acc_tmpbuf + *tmpbuf_pos, &handle_ip, handle_ip_size);
|
||||
*tmpbuf_pos += handle_ip_size;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -769,7 +788,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;
|
||||
@@ -781,25 +801,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;
|
||||
@@ -808,13 +828,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;
|
||||
}
|
||||
@@ -822,7 +842,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;
|
||||
@@ -831,7 +851,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]) {
|
||||
@@ -841,7 +861,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;
|
||||
@@ -852,7 +872,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;
|
||||
@@ -862,8 +882,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;
|
||||
|
||||
@@ -879,22 +906,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;
|
||||
}
|
||||
@@ -907,6 +939,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;
|
||||
|
||||
@@ -931,28 +965,28 @@ 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);
|
||||
if ((handle.handle_nr = ipt_acc_handle_find_slot(ian->ipt_acc_handles)) == -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))) {
|
||||
@@ -981,19 +1015,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);
|
||||
@@ -1013,11 +1047,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))) {
|
||||
@@ -1031,38 +1065,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;
|
||||
@@ -1075,6 +1109,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,
|
||||
@@ -1098,63 +1185,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);
|
||||
|
@@ -34,7 +34,6 @@
|
||||
#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
|
||||
|
||||
@@ -59,11 +58,11 @@ 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;
|
||||
uint64_t src_bytes;
|
||||
uint64_t dst_packets;
|
||||
uint64_t dst_bytes;
|
||||
};
|
||||
|
||||
#endif /* _IPT_ACCOUNT_H */
|
||||
|
@@ -10,17 +10,11 @@ obj-${build_CHAOS} += xt_CHAOS.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_condition} += xt_condition.o
|
||||
obj-${build_fuzzy} += xt_fuzzy.o
|
||||
|
@@ -8,8 +8,7 @@ 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_condition} += libxt_condition.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,6 +0,0 @@
|
||||
#ifndef XTA_COMPAT_RAWPOST_H
|
||||
#define XTA_COMPAT_RAWPOST_H 1
|
||||
|
||||
typedef struct sk_buff sk_buff_t;
|
||||
|
||||
#endif /* XTA_COMPAT_RAWPOST_H */
|
@@ -28,118 +28,6 @@
|
||||
# define WITH_IPV6 1
|
||||
#endif
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
ct->checkentry = nt->checkentry;
|
||||
ct->destroy = nt->destroy;
|
||||
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)
|
||||
{
|
||||
return ip_route_me_harder(*pskb, addr_type);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xtnu_ip_route_me_harder);
|
||||
|
||||
int xtnu_skb_make_writable(struct sk_buff **pskb, unsigned int len)
|
||||
{
|
||||
return skb_make_writable(*pskb, len);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xtnu_skb_make_writable);
|
||||
|
||||
void *HX_memmem(const void *space, size_t spacesize,
|
||||
const void *point, size_t pointsize)
|
||||
{
|
||||
|
@@ -8,8 +8,8 @@
|
||||
|
||||
#define DEBUGP Use__pr_debug__instead
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0)
|
||||
# warning Kernels below 3.7 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)
|
||||
@@ -21,9 +21,6 @@
|
||||
# warning You need CONFIG_NF_CONNTRACK.
|
||||
#endif
|
||||
|
||||
#define ipt_unregister_table(tbl) ipt_unregister_table(&init_net, (tbl))
|
||||
#define ip6t_unregister_table(tbl) ip6t_unregister_table(&init_net, (tbl))
|
||||
|
||||
#if !defined(NIP6) && !defined(NIP6_FMT)
|
||||
# define NIP6(addr) \
|
||||
ntohs((addr).s6_addr16[0]), \
|
||||
@@ -34,7 +31,7 @@
|
||||
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"
|
||||
# define NIP6_FMT "%04hx:%04hx:%04hx:%04hx:%04hx:%04hx:%04hx:%04hx"
|
||||
#endif
|
||||
#if !defined(NIPQUAD) && !defined(NIPQUAD_FMT)
|
||||
# define NIPQUAD(addr) \
|
||||
@@ -42,44 +39,25 @@
|
||||
((const unsigned char *)&addr)[1], \
|
||||
((const unsigned char *)&addr)[2], \
|
||||
((const unsigned char *)&addr)[3]
|
||||
# define NIPQUAD_FMT "%u.%u.%u.%u"
|
||||
# define NIPQUAD_FMT "%hhu.%hhu.%hhu.%hhu"
|
||||
#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
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0)
|
||||
static inline struct inode *file_inode(struct file *f)
|
||||
static inline struct net *par_net(const struct xt_action_param *par)
|
||||
{
|
||||
return f->f_path.dentry->d_inode;
|
||||
return par->state->net;
|
||||
}
|
||||
|
||||
#ifndef NF_CT_ASSERT
|
||||
# define NF_CT_ASSERT(x) WARN_ON(!(x))
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
|
||||
static inline void
|
||||
proc_set_user(struct proc_dir_entry *de, kuid_t uid, kgid_t gid)
|
||||
{
|
||||
de->uid = uid;
|
||||
de->gid = gid;
|
||||
}
|
||||
|
||||
static inline void *PDE_DATA(struct inode *inode)
|
||||
{
|
||||
return PDE(inode)->data;
|
||||
}
|
||||
|
||||
static inline void proc_remove(struct proc_dir_entry *de)
|
||||
{
|
||||
if (de != NULL)
|
||||
remove_proc_entry(de->name, de->parent);
|
||||
}
|
||||
#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
|
||||
|
||||
#endif /* _XTABLES_COMPAT_H */
|
||||
|
@@ -1,14 +1,9 @@
|
||||
#ifndef _COMPAT_XTNU_H
|
||||
#define _COMPAT_XTNU_H 1
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
struct flowi;
|
||||
struct module;
|
||||
struct net_device;
|
||||
struct rtable;
|
||||
struct sk_buff;
|
||||
|
||||
struct xtnu_match {
|
||||
@@ -58,11 +53,7 @@ static inline struct xtnu_target *xtcompat_nutarget(const struct xt_target *t)
|
||||
return q;
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -70,14 +61,6 @@ 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 void xtnu_proto_csum_replace4(__u16 __bitwise *, struct sk_buff *,
|
||||
__be32, __be32, bool);
|
||||
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);
|
||||
|
||||
|
@@ -1,93 +0,0 @@
|
||||
/*
|
||||
* rawpost table for ip6_tables
|
||||
* written by Jan Engelhardt, 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 *))
|
||||
{
|
||||
return ip6t_do_table(skb, hook, in, out, rawpost6_ptable);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
rawpost6_ptable = ip6t_register_table(&init_net, &rawpost6_itable,
|
||||
&rawpost6_initial.repl);
|
||||
if (IS_ERR(rawpost6_ptable))
|
||||
return PTR_ERR(rawpost6_ptable);
|
||||
|
||||
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 ");
|
||||
MODULE_LICENSE("GPL");
|
@@ -1,95 +0,0 @@
|
||||
/*
|
||||
* rawpost table for ip_tables
|
||||
* written by Jan Engelhardt, 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 *))
|
||||
{
|
||||
return ipt_do_table(skb, hook, in, out, rawpost4_ptable);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
rawpost4_ptable = ipt_register_table(&init_net, &rawpost4_itable,
|
||||
&rawpost4_initial.repl);
|
||||
if (IS_ERR(rawpost4_ptable))
|
||||
return PTR_ERR(rawpost4_ptable);
|
||||
|
||||
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 ");
|
||||
MODULE_LICENSE("GPL");
|
@@ -46,7 +46,7 @@ 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
|
||||
'\fBS\fR' in case of a static binding.
|
||||
\(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 a given \fIsubnet/mask\fP. The line contains four
|
||||
|
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,177 +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_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_tg4_print(const void *entry, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
printf(" -j RAWDNAT");
|
||||
rawdnat_tg4_save(entry, target);
|
||||
}
|
||||
|
||||
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 void
|
||||
rawdnat_tg6_print(const void *entry, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
printf(" -j RAWDNAT");
|
||||
rawdnat_tg6_save(entry, target);
|
||||
}
|
||||
|
||||
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,11 +0,0 @@
|
||||
.PP
|
||||
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,177 +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_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 void
|
||||
rawsnat_tg4_print(const void *entry, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
printf(" -j RAWSNAT");
|
||||
rawsnat_tg4_save(entry, target);
|
||||
}
|
||||
|
||||
static void
|
||||
rawsnat_tg6_print(const void *entry, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
printf(" -j RAWSNAT");
|
||||
rawsnat_tg6_save(entry, target);
|
||||
}
|
||||
|
||||
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,39 +0,0 @@
|
||||
.PP
|
||||
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,3 +0,0 @@
|
||||
.PP
|
||||
Like the DROP target, but does not throw an error like DROP when used in the
|
||||
\fBOUTPUT\fP chain.
|
@@ -49,6 +49,26 @@ 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)
|
||||
{
|
||||
@@ -56,21 +76,15 @@ geoip_get_subnets(const char *code, uint32_t *count, uint8_t nfproto)
|
||||
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) {
|
||||
fprintf(stderr, "Could not open %s: %s\n", buf, strerror(errno));
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -135,7 +168,7 @@ check_geoip_cc(char *cc, u_int16_t cc_used[], u_int8_t count)
|
||||
cc[i] = toupper(cc[i]);
|
||||
else
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"geoip: invalid country code '%s'", cc);
|
||||
"geoip: invalid country code '%s'", cc);
|
||||
|
||||
/* Convert chars into a single 16 bit integer.
|
||||
* FIXME: This assumes that a country code is
|
||||
|
@@ -5,4 +5,4 @@ AM_CFLAGS = ${regular_CFLAGS} ${libxtables_CFLAGS}
|
||||
|
||||
include ../../Makefile.extra
|
||||
|
||||
noinst_PROGRAMS = pknlusr
|
||||
sbin_PROGRAMS = pknlusr
|
||||
|
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"
|
@@ -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
|
||||
|
@@ -19,16 +19,14 @@
|
||||
#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"
|
||||
|
||||
@@ -111,9 +109,9 @@ static DEFINE_SPINLOCK(list_lock);
|
||||
|
||||
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,
|
||||
@@ -297,12 +295,11 @@ pknock_proc_open(struct inode *inode, struct file *file)
|
||||
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,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -359,11 +356,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;
|
||||
|
||||
@@ -470,11 +466,7 @@ add_rule(struct xt_pknock_mtinfo *info)
|
||||
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;
|
||||
|
||||
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)
|
||||
@@ -621,9 +613,10 @@ 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);
|
||||
kfree(peer);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -700,9 +693,7 @@ msg_to_userspace_nl(const struct xt_pknock_mtinfo *info,
|
||||
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;
|
||||
@@ -740,7 +731,6 @@ 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 *hexresult;
|
||||
unsigned int hexa_size;
|
||||
@@ -771,11 +761,7 @@ has_secret(const unsigned char *secret, unsigned int secret_len, uint32_t ipsrc,
|
||||
|
||||
epoch_min = get_seconds() / 60;
|
||||
|
||||
sg_init_table(sg, ARRAY_SIZE(sg));
|
||||
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;
|
||||
@@ -786,10 +772,10 @@ 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;
|
||||
}
|
||||
|
||||
@@ -1054,9 +1040,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");
|
||||
if (info->option & (XT_PKNOCK_OPENSECRET | XT_PKNOCK_CLOSESECRET))
|
||||
RETURN_ERR("No crypto support available; "
|
||||
"cannot use opensecret/closescret\n");
|
||||
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) {
|
||||
@@ -1132,16 +1115,15 @@ static int __init xt_pknock_mt_init(void)
|
||||
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",
|
||||
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;
|
||||
|
||||
pde = proc_mkdir("xt_pknock", init_net.proc_net);
|
||||
if (pde == NULL) {
|
||||
@@ -1157,7 +1139,7 @@ static void __exit xt_pknock_mt_exit(void)
|
||||
xt_unregister_match(&xt_pknock_mt_reg);
|
||||
kfree(rule_hashtable);
|
||||
if (crypto.tfm != NULL)
|
||||
crypto_free_hash(crypto.tfm);
|
||||
crypto_free_shash(crypto.tfm);
|
||||
}
|
||||
|
||||
module_init(xt_pknock_mt_init);
|
||||
|
@@ -58,8 +58,7 @@ xt_chaos_total(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
|
||||
{
|
||||
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;
|
||||
@@ -68,24 +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;
|
||||
}
|
||||
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;
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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:
|
||||
@@ -96,23 +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 ((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);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
@@ -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 net *net, struct sk_buff *oldskb,
|
||||
unsigned int hook)
|
||||
{
|
||||
struct tcphdr _otcph, *tcph;
|
||||
const struct tcphdr *oth;
|
||||
@@ -78,7 +79,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;
|
||||
@@ -106,8 +107,13 @@ static void delude_send_reset(struct sk_buff *oldskb, unsigned int hook)
|
||||
|
||||
addr_type = RTN_UNSPEC;
|
||||
#ifdef CONFIG_BRIDGE_NETFILTER
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
|
||||
if (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 || (nskb->nf_bridge != NULL &&
|
||||
nskb->nf_bridge->mask & BRNF_BRIDGED))
|
||||
nskb->nf_bridge->physoutdev))
|
||||
#endif
|
||||
#else
|
||||
if (hook != NF_INET_FORWARD)
|
||||
#endif
|
||||
@@ -116,7 +122,7 @@ static void delude_send_reset(struct sk_buff *oldskb, unsigned int hook)
|
||||
/* 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(net, nskb, addr_type))
|
||||
goto free_nskb;
|
||||
else
|
||||
niph = ip_hdr(nskb);
|
||||
@@ -130,7 +136,7 @@ static void delude_send_reset(struct sk_buff *oldskb, unsigned int hook)
|
||||
|
||||
nf_ct_attach(nskb, oldskb);
|
||||
|
||||
ip_local_out(nskb);
|
||||
ip_local_out(net, nskb->sk, nskb);
|
||||
return;
|
||||
|
||||
free_nskb:
|
||||
@@ -138,14 +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)
|
||||
{
|
||||
/*
|
||||
* 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(*pskb, par->hooknum);
|
||||
delude_send_reset(par_net(par), skb, par->state->hook);
|
||||
return NF_DROP;
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -26,6 +26,7 @@
|
||||
#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>
|
||||
@@ -80,7 +81,7 @@ struct dnetmap_entry {
|
||||
|
||||
struct dnetmap_prefix {
|
||||
struct nf_nat_range prefix;
|
||||
char prefix_str[16];
|
||||
char prefix_str[20];
|
||||
#ifdef CONFIG_PROC_FS
|
||||
char proc_str_data[20];
|
||||
char proc_str_stat[25];
|
||||
@@ -114,7 +115,7 @@ static DEFINE_SPINLOCK(dnetmap_lock);
|
||||
static DEFINE_MUTEX(dnetmap_mutex);
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
static const struct file_operations dnetmap_tg_fops, dnetmap_stat_proc_fops;
|
||||
static const struct proc_ops dnetmap_tg_fops, dnetmap_stat_proc_fops;
|
||||
#endif
|
||||
|
||||
static inline unsigned int dnetmap_entry_hash(const __be32 addr)
|
||||
@@ -353,30 +354,30 @@ 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_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);
|
||||
unsigned int hooknum = par->state->hook;
|
||||
ct = nf_ct_get(skb, &ctinfo);
|
||||
|
||||
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);
|
||||
@@ -389,7 +390,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) ) ) {
|
||||
@@ -407,7 +408,7 @@ dnetmap_tg(struct sk_buff **pskb, const struct xt_action_param *par)
|
||||
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;
|
||||
@@ -495,8 +496,7 @@ bind_new_prefix:
|
||||
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->hooknum));
|
||||
|
||||
return nf_nat_setup_info(ct, &newrange, HOOK2MANIP(par->state->hook));
|
||||
no_rev_map:
|
||||
no_free_ip:
|
||||
spin_unlock_bh(&dnetmap_lock);
|
||||
@@ -608,7 +608,6 @@ dnetmap_tg_proc_write(struct file *file, const char __user *input,size_t size, l
|
||||
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];
|
||||
@@ -769,12 +768,11 @@ 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 */
|
||||
@@ -818,11 +816,11 @@ 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 file_operations dnetmap_stat_proc_fops = {
|
||||
.open = dnetmap_stat_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
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)
|
||||
|
@@ -24,9 +24,8 @@
|
||||
#include "compat_xtables.h"
|
||||
|
||||
static unsigned int
|
||||
echo_tg6(struct sk_buff **poldskb, const struct xt_action_param *par)
|
||||
echo_tg6(struct sk_buff *oldskb, const struct xt_action_param *par)
|
||||
{
|
||||
const struct sk_buff *oldskb = *poldskb;
|
||||
const struct udphdr *oldudp;
|
||||
const struct ipv6hdr *oldip;
|
||||
struct udphdr *newudp, oldudp_buf;
|
||||
@@ -36,10 +35,10 @@ echo_tg6(struct sk_buff **poldskb, const struct xt_action_param *par)
|
||||
void *payload;
|
||||
struct flowi6 fl;
|
||||
struct dst_entry *dst = NULL;
|
||||
struct net *net = dev_net((par->in != NULL) ? par->in : par->out);
|
||||
struct net *net = dev_net((par->state->in != NULL) ? par->state->in : par->state->out);
|
||||
|
||||
/* This allows us to do the copy operation in fewer lines of code. */
|
||||
if (skb_linearize(*poldskb) < 0)
|
||||
if (skb_linearize(oldskb) < 0)
|
||||
return NF_DROP;
|
||||
|
||||
oldip = ipv6_hdr(oldskb);
|
||||
@@ -77,6 +76,7 @@ echo_tg6(struct sk_buff **poldskb, const struct xt_action_param *par)
|
||||
payload = skb_header_pointer(oldskb, par->thoff +
|
||||
sizeof(*oldudp), data_len, NULL);
|
||||
memcpy(skb_put(newskb, data_len), payload, data_len);
|
||||
newip->payload_len = htons(newskb->len);
|
||||
|
||||
#if 0
|
||||
/*
|
||||
@@ -112,8 +112,8 @@ echo_tg6(struct sk_buff **poldskb, const struct xt_action_param *par)
|
||||
if (newskb->len > dst_mtu(skb_dst(newskb)))
|
||||
goto free_nskb;
|
||||
|
||||
nf_ct_attach(newskb, *poldskb);
|
||||
ip6_local_out(newskb);
|
||||
nf_ct_attach(newskb, oldskb);
|
||||
ip6_local_out(par_net(par), newskb->sk, newskb);
|
||||
return NF_DROP;
|
||||
|
||||
free_nskb:
|
||||
@@ -122,9 +122,8 @@ echo_tg6(struct sk_buff **poldskb, const struct xt_action_param *par)
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
echo_tg4(struct sk_buff **poldskb, const struct xt_action_param *par)
|
||||
echo_tg4(struct sk_buff *oldskb, const struct xt_action_param *par)
|
||||
{
|
||||
const struct sk_buff *oldskb = *poldskb;
|
||||
const struct udphdr *oldudp;
|
||||
const struct iphdr *oldip;
|
||||
struct udphdr *newudp, oldudp_buf;
|
||||
@@ -134,7 +133,7 @@ echo_tg4(struct sk_buff **poldskb, const struct xt_action_param *par)
|
||||
void *payload;
|
||||
|
||||
/* This allows us to do the copy operation in fewer lines of code. */
|
||||
if (skb_linearize(*poldskb) < 0)
|
||||
if (skb_linearize(oldskb) < 0)
|
||||
return NF_DROP;
|
||||
|
||||
oldip = ip_hdr(oldskb);
|
||||
@@ -158,8 +157,8 @@ echo_tg4(struct sk_buff **poldskb, const struct xt_action_param *par)
|
||||
newip->version = oldip->version;
|
||||
newip->ihl = sizeof(*newip) / 4;
|
||||
newip->tos = oldip->tos;
|
||||
newip->id = 0;
|
||||
newip->frag_off = htons(IP_DF);
|
||||
newip->id = oldip->id;
|
||||
newip->frag_off = 0;
|
||||
newip->protocol = oldip->protocol;
|
||||
newip->check = 0;
|
||||
newip->saddr = oldip->daddr;
|
||||
@@ -175,6 +174,7 @@ echo_tg4(struct sk_buff **poldskb, const struct xt_action_param *par)
|
||||
payload = skb_header_pointer(oldskb, par->thoff +
|
||||
sizeof(*oldudp), data_len, NULL);
|
||||
memcpy(skb_put(newskb, data_len), payload, data_len);
|
||||
newip->tot_len = htons(newskb->len);
|
||||
|
||||
#if 0
|
||||
/*
|
||||
@@ -192,7 +192,7 @@ echo_tg4(struct sk_buff **poldskb, const struct xt_action_param *par)
|
||||
/* ip_route_me_harder expects the skb's dst to be set */
|
||||
skb_dst_set(newskb, dst_clone(skb_dst(oldskb)));
|
||||
|
||||
if (ip_route_me_harder(&newskb, RTN_UNSPEC) != 0)
|
||||
if (ip_route_me_harder(par_net(par), newskb, RTN_UNSPEC) != 0)
|
||||
goto free_nskb;
|
||||
|
||||
newip->ttl = ip4_dst_hoplimit(skb_dst(newskb));
|
||||
@@ -202,8 +202,8 @@ echo_tg4(struct sk_buff **poldskb, const struct xt_action_param *par)
|
||||
if (newskb->len > dst_mtu(skb_dst(newskb)))
|
||||
goto free_nskb;
|
||||
|
||||
nf_ct_attach(newskb, *poldskb);
|
||||
ip_local_out(newskb);
|
||||
nf_ct_attach(newskb, oldskb);
|
||||
ip_local_out(par_net(par), newskb->sk, newskb);
|
||||
return NF_DROP;
|
||||
|
||||
free_nskb:
|
||||
|
@@ -25,10 +25,9 @@ MODULE_ALIAS("ipt_IPMARK");
|
||||
MODULE_ALIAS("ip6t_IPMARK");
|
||||
|
||||
static unsigned int
|
||||
ipmark_tg4(struct sk_buff **pskb, const struct xt_action_param *par)
|
||||
ipmark_tg4(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
{
|
||||
const struct xt_ipmark_tginfo *ipmarkinfo = par->targinfo;
|
||||
const struct sk_buff *skb = *pskb;
|
||||
const struct iphdr *iph = ip_hdr(skb);
|
||||
__u32 mark;
|
||||
|
||||
@@ -61,10 +60,9 @@ static __u32 ipmark_from_ip6(const struct in6_addr *a, unsigned int s)
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
ipmark_tg6(struct sk_buff **pskb, const struct xt_action_param *par)
|
||||
ipmark_tg6(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
{
|
||||
const struct xt_ipmark_tginfo *info = par->targinfo;
|
||||
const struct sk_buff *skb = *pskb;
|
||||
const struct ipv6hdr *iph = ipv6_hdr(skb);
|
||||
__u32 mark;
|
||||
|
||||
|
@@ -52,20 +52,24 @@ static void logmark_ct(const struct nf_conn *ct, enum ip_conntrack_info ctinfo)
|
||||
printk("EXPECTED");
|
||||
prev = true;
|
||||
}
|
||||
if (ct->status & IPS_SEEN_REPLY)
|
||||
printk("%s""SEEN_REPLY", prev++ ? "," : "");
|
||||
if (ct->status & IPS_ASSURED)
|
||||
printk("%s""ASSURED", prev++ ? "," : "");
|
||||
if (ct->status & IPS_CONFIRMED)
|
||||
printk("%s""CONFIRMED", prev++ ? "," : "");
|
||||
printk(" lifetime=%lus",
|
||||
(jiffies - ct->timeout.expires) / HZ);
|
||||
if (ct->status & IPS_SEEN_REPLY) {
|
||||
printk("%s""SEEN_REPLY", prev ? "," : "");
|
||||
prev = true;
|
||||
}
|
||||
if (ct->status & IPS_ASSURED) {
|
||||
printk("%s""ASSURED", prev ? "," : "");
|
||||
prev = true;
|
||||
}
|
||||
if (ct->status & IPS_CONFIRMED) {
|
||||
printk("%s""CONFIRMED", prev ? "," : "");
|
||||
prev = true;
|
||||
}
|
||||
printk(" lifetime=%lus", nf_ct_expires(ct) / HZ);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
logmark_tg(struct sk_buff **pskb, const struct xt_action_param *par)
|
||||
logmark_tg(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
{
|
||||
const struct sk_buff *skb = *pskb;
|
||||
const struct xt_logmark_tginfo *info = par->targinfo;
|
||||
const struct nf_conn *ct;
|
||||
enum ip_conntrack_info ctinfo;
|
||||
@@ -73,15 +77,13 @@ logmark_tg(struct sk_buff **pskb, const struct xt_action_param *par)
|
||||
printk("<%u>%.*s""iif=%d hook=%s nfmark=0x%x "
|
||||
"secmark=0x%x classify=0x%x",
|
||||
info->level, (unsigned int)sizeof(info->prefix), info->prefix,
|
||||
skb_ifindex(skb), hook_names[par->hooknum],
|
||||
skb_ifindex(skb), hook_names[par->state->hook],
|
||||
skb_nfmark(skb), skb_secmark(skb), skb->priority);
|
||||
|
||||
ct = nf_ct_get(skb, &ctinfo);
|
||||
printk(" ctdir=%s", dir_names[ctinfo >= IP_CT_IS_REPLY]);
|
||||
if (ct == NULL)
|
||||
printk(" ct=NULL ctmark=NULL ctstate=INVALID ctstatus=NONE");
|
||||
else if (nf_ct_is_untracked(ct))
|
||||
printk(" ct=UNTRACKED ctmark=NULL ctstate=UNTRACKED ctstatus=NONE");
|
||||
else
|
||||
logmark_ct(ct, ctinfo);
|
||||
|
||||
|
156
extensions/xt_PROTO.c
Normal file
156
extensions/xt_PROTO.c
Normal file
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Protocol modification target for IP tables
|
||||
*
|
||||
* 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/ip.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <net/ipv6.h>
|
||||
#include <net/checksum.h>
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#include "xt_PROTO.h"
|
||||
|
||||
MODULE_AUTHOR("Shanker Wang <i@innull.com>");
|
||||
MODULE_DESCRIPTION("Xtables: Protocol field modification target");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static unsigned int
|
||||
proto_tg(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
{
|
||||
struct iphdr *iph;
|
||||
const struct xt_PROTO_info *info = par->targinfo;
|
||||
int new_proto;
|
||||
|
||||
if (skb_ensure_writable(skb, skb->len))
|
||||
return NF_DROP;
|
||||
|
||||
iph = ip_hdr(skb);
|
||||
new_proto = iph->protocol;
|
||||
if (info->mode & (1 << XT_PROTO_SET))
|
||||
new_proto = info->proto;
|
||||
if (new_proto != iph->protocol) {
|
||||
csum_replace2(&iph->check, htons(iph->protocol & 0xff),
|
||||
htons(new_proto & 0xff));
|
||||
iph->protocol = new_proto;
|
||||
}
|
||||
|
||||
return XT_CONTINUE;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
proto_tg6(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
{
|
||||
struct ipv6hdr *ip6h;
|
||||
const struct xt_PROTO_info *info = par->targinfo;
|
||||
u8 *nexthdr;
|
||||
unsigned int hdr_offset;
|
||||
__be16 *fp;
|
||||
|
||||
if (skb_ensure_writable(skb, skb->len))
|
||||
return NF_DROP;
|
||||
|
||||
ip6h = ipv6_hdr(skb);
|
||||
nexthdr = &ip6h->nexthdr;
|
||||
hdr_offset = sizeof(struct ipv6hdr);
|
||||
|
||||
for (;;) {
|
||||
struct ipv6_opt_hdr _opthdr, *opthp;
|
||||
unsigned int hdrlen;
|
||||
unsigned short _frag_off;
|
||||
if (!ipv6_ext_hdr(*nexthdr) || *nexthdr == NEXTHDR_NONE)
|
||||
break;
|
||||
opthp = skb_header_pointer(skb, skb_network_offset(skb) + hdr_offset, sizeof(_opthdr), &_opthdr);
|
||||
if (!opthp)
|
||||
return NF_DROP;
|
||||
if (*nexthdr == NEXTHDR_FRAGMENT) {
|
||||
if (info->mode & (1 << XT_PROTO_STOP_AT_FRAG))
|
||||
break;
|
||||
fp = skb_header_pointer(skb, skb_network_offset(skb) +
|
||||
hdr_offset + offsetof(struct frag_hdr, frag_off),
|
||||
sizeof(_frag_off), &_frag_off);
|
||||
if (!fp)
|
||||
return NF_DROP;
|
||||
_frag_off = ntohs(*fp) & ~0x7;
|
||||
if (_frag_off) { // if the packet is not the first fragment
|
||||
if (!ipv6_ext_hdr(opthp->nexthdr) || opthp->nexthdr == NEXTHDR_NONE ||
|
||||
(info->mode & (1 << XT_PROTO_STOP_AT_AUTH) && opthp->nexthdr == NEXTHDR_AUTH)) {
|
||||
nexthdr = &((struct ipv6_opt_hdr *)(skb_network_header(skb) + hdr_offset))->nexthdr;
|
||||
break;
|
||||
} else {
|
||||
return XT_CONTINUE;
|
||||
}
|
||||
}
|
||||
hdrlen = 8;
|
||||
} else if(*nexthdr == NEXTHDR_AUTH) {
|
||||
if (info->mode & (1 << XT_PROTO_STOP_AT_AUTH))
|
||||
break;
|
||||
hdrlen = (opthp->hdrlen + 2) << 2;
|
||||
} else {
|
||||
hdrlen = ipv6_optlen(opthp);
|
||||
}
|
||||
nexthdr = &((struct ipv6_opt_hdr *)(skb_network_header(skb) + hdr_offset))->nexthdr;
|
||||
hdr_offset += hdrlen;
|
||||
}
|
||||
|
||||
if (info->mode & (1 << XT_PROTO_SET))
|
||||
*nexthdr = info->proto;
|
||||
return XT_CONTINUE;
|
||||
}
|
||||
|
||||
static int proto_tg_check(const struct xt_tgchk_param *par)
|
||||
{
|
||||
const struct xt_PROTO_info *info = par->targinfo;
|
||||
|
||||
if ((info->mode & (1 << XT_PROTO_SET)) == 0) {
|
||||
pr_info_ratelimited("Did not specify any proto to set\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (par->family != NFPROTO_IPV6 && (info->mode & ((1 << XT_PROTO_STOP_AT_FRAG) | (1 << XT_PROTO_STOP_AT_AUTH))) != 0) {
|
||||
pr_info_ratelimited("Must not specify stop-at-frag and stop-at-auth on non-ipv6 targets\n");
|
||||
return -EPROTOTYPE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct xt_target proto_tg_reg[] __read_mostly = {
|
||||
{
|
||||
.name = "PROTO",
|
||||
.revision = 0,
|
||||
.family = NFPROTO_IPV4,
|
||||
.target = proto_tg,
|
||||
.targetsize = sizeof(struct xt_PROTO_info),
|
||||
.table = "mangle",
|
||||
.checkentry = proto_tg_check,
|
||||
.me = THIS_MODULE,
|
||||
},
|
||||
{
|
||||
.name = "PROTO",
|
||||
.revision = 0,
|
||||
.family = NFPROTO_IPV6,
|
||||
.target = proto_tg6,
|
||||
.targetsize = sizeof(struct xt_PROTO_info),
|
||||
.table = "mangle",
|
||||
.checkentry = proto_tg_check,
|
||||
.me = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init proto_tg_init(void)
|
||||
{
|
||||
return xt_register_targets(proto_tg_reg, ARRAY_SIZE(proto_tg_reg));
|
||||
}
|
||||
|
||||
static void __exit proto_tg_exit(void)
|
||||
{
|
||||
xt_unregister_targets(proto_tg_reg, ARRAY_SIZE(proto_tg_reg));
|
||||
}
|
||||
|
||||
module_init(proto_tg_init);
|
||||
module_exit(proto_tg_exit);
|
||||
MODULE_ALIAS("ipt_PROTO");
|
||||
MODULE_ALIAS("ip6t_PROTO");
|
20
extensions/xt_PROTO.h
Normal file
20
extensions/xt_PROTO.h
Normal file
@@ -0,0 +1,20 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/* Protocol modification module for IP tables */
|
||||
|
||||
#ifndef _XT_PROTO_H
|
||||
#define _XT_PROTO_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
enum {
|
||||
XT_PROTO_SET = 0,
|
||||
XT_PROTO_STOP_AT_FRAG = 1,
|
||||
XT_PROTO_STOP_AT_AUTH = 2
|
||||
};
|
||||
|
||||
struct xt_PROTO_info {
|
||||
__u8 mode;
|
||||
__u8 proto;
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,354 +0,0 @@
|
||||
/*
|
||||
* "RAWNAT" target extension for Xtables - untracked NAT
|
||||
* 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 <linux/ip.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/udp.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netfilter/nf_conntrack_common.h>
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#include <linux/netfilter_ipv6/ip6_tables.h>
|
||||
#include <net/ip.h>
|
||||
#include <net/ipv6.h>
|
||||
#include "compat_xtables.h"
|
||||
#include "xt_RAWNAT.h"
|
||||
#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
|
||||
# define WITH_IPV6 1
|
||||
#endif
|
||||
|
||||
static inline __be32
|
||||
remask(__be32 addr, __be32 repl, unsigned int shift)
|
||||
{
|
||||
uint32_t mask = (shift == 32) ? 0 : (~(uint32_t)0 >> shift);
|
||||
return htonl((ntohl(addr) & mask) | (ntohl(repl) & ~mask));
|
||||
}
|
||||
|
||||
#ifdef WITH_IPV6
|
||||
static void
|
||||
rawnat_ipv6_mask(__be32 *addr, const __be32 *repl, unsigned int mask)
|
||||
{
|
||||
switch (mask) {
|
||||
case 0:
|
||||
break;
|
||||
case 1 ... 31:
|
||||
addr[0] = remask(addr[0], repl[0], mask);
|
||||
break;
|
||||
case 32:
|
||||
addr[0] = repl[0];
|
||||
break;
|
||||
case 33 ... 63:
|
||||
addr[0] = repl[0];
|
||||
addr[1] = remask(addr[1], repl[1], mask - 32);
|
||||
break;
|
||||
case 64:
|
||||
addr[0] = repl[0];
|
||||
addr[1] = repl[1];
|
||||
break;
|
||||
case 65 ... 95:
|
||||
addr[0] = repl[0];
|
||||
addr[1] = repl[1];
|
||||
addr[2] = remask(addr[2], repl[2], mask - 64);
|
||||
case 96:
|
||||
addr[0] = repl[0];
|
||||
addr[1] = repl[1];
|
||||
addr[2] = repl[2];
|
||||
break;
|
||||
case 97 ... 127:
|
||||
addr[0] = repl[0];
|
||||
addr[1] = repl[1];
|
||||
addr[2] = repl[2];
|
||||
addr[3] = remask(addr[3], repl[3], mask - 96);
|
||||
break;
|
||||
case 128:
|
||||
addr[0] = repl[0];
|
||||
addr[1] = repl[1];
|
||||
addr[2] = repl[2];
|
||||
addr[3] = repl[3];
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void rawnat4_update_l4(struct sk_buff *skb, __be32 oldip, __be32 newip)
|
||||
{
|
||||
struct iphdr *iph = ip_hdr(skb);
|
||||
void *transport_hdr = (void *)iph + ip_hdrlen(skb);
|
||||
struct tcphdr *tcph;
|
||||
struct udphdr *udph;
|
||||
bool cond;
|
||||
|
||||
switch (iph->protocol) {
|
||||
case IPPROTO_TCP:
|
||||
tcph = transport_hdr;
|
||||
inet_proto_csum_replace4(&tcph->check, skb, oldip, newip, true);
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_UDPLITE:
|
||||
udph = transport_hdr;
|
||||
cond = udph->check != 0;
|
||||
cond |= skb->ip_summed == CHECKSUM_PARTIAL;
|
||||
if (cond) {
|
||||
inet_proto_csum_replace4(&udph->check, skb,
|
||||
oldip, newip, true);
|
||||
if (udph->check == 0)
|
||||
udph->check = CSUM_MANGLED_0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int rawnat4_writable_part(const struct iphdr *iph)
|
||||
{
|
||||
unsigned int wlen = iph->ihl * 4;
|
||||
|
||||
switch (iph->protocol) {
|
||||
case IPPROTO_TCP:
|
||||
wlen += sizeof(struct tcphdr);
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
wlen += sizeof(struct udphdr);
|
||||
break;
|
||||
}
|
||||
return wlen;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
rawsnat_tg4(struct sk_buff **pskb, const struct xt_action_param *par)
|
||||
{
|
||||
const struct xt_rawnat_tginfo *info = par->targinfo;
|
||||
struct iphdr *iph;
|
||||
__be32 new_addr;
|
||||
|
||||
iph = ip_hdr(*pskb);
|
||||
new_addr = remask(iph->saddr, info->addr.ip, info->mask);
|
||||
if (iph->saddr == new_addr)
|
||||
return XT_CONTINUE;
|
||||
|
||||
if (!skb_make_writable(pskb, rawnat4_writable_part(iph)))
|
||||
return NF_DROP;
|
||||
|
||||
iph = ip_hdr(*pskb);
|
||||
csum_replace4(&iph->check, iph->saddr, new_addr);
|
||||
rawnat4_update_l4(*pskb, iph->saddr, new_addr);
|
||||
iph->saddr = new_addr;
|
||||
return XT_CONTINUE;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
rawdnat_tg4(struct sk_buff **pskb, const struct xt_action_param *par)
|
||||
{
|
||||
const struct xt_rawnat_tginfo *info = par->targinfo;
|
||||
struct iphdr *iph;
|
||||
__be32 new_addr;
|
||||
|
||||
iph = ip_hdr(*pskb);
|
||||
new_addr = remask(iph->daddr, info->addr.ip, info->mask);
|
||||
if (iph->daddr == new_addr)
|
||||
return XT_CONTINUE;
|
||||
|
||||
if (!skb_make_writable(pskb, rawnat4_writable_part(iph)))
|
||||
return NF_DROP;
|
||||
|
||||
iph = ip_hdr(*pskb);
|
||||
csum_replace4(&iph->check, iph->daddr, new_addr);
|
||||
rawnat4_update_l4(*pskb, iph->daddr, new_addr);
|
||||
iph->daddr = new_addr;
|
||||
return XT_CONTINUE;
|
||||
}
|
||||
|
||||
#ifdef WITH_IPV6
|
||||
static bool rawnat6_prepare_l4(struct sk_buff **pskb, unsigned int *l4offset,
|
||||
unsigned int *l4proto)
|
||||
{
|
||||
static const unsigned int types[] =
|
||||
{IPPROTO_TCP, IPPROTO_UDP, IPPROTO_UDPLITE};
|
||||
unsigned int i;
|
||||
int err;
|
||||
|
||||
*l4proto = NEXTHDR_MAX;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(types); ++i) {
|
||||
err = ipv6_find_hdr(*pskb, l4offset, types[i], NULL, NULL);
|
||||
if (err >= 0) {
|
||||
*l4proto = types[i];
|
||||
break;
|
||||
}
|
||||
if (err != -ENOENT)
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (*l4proto) {
|
||||
case IPPROTO_TCP:
|
||||
if (!skb_make_writable(pskb, *l4offset + sizeof(struct tcphdr)))
|
||||
return false;
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_UDPLITE:
|
||||
if (!skb_make_writable(pskb, *l4offset + sizeof(struct udphdr)))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void rawnat6_update_l4(struct sk_buff *skb, unsigned int l4proto,
|
||||
unsigned int l4offset, const struct in6_addr *oldip,
|
||||
const struct in6_addr *newip)
|
||||
{
|
||||
const struct ipv6hdr *iph = ipv6_hdr(skb);
|
||||
struct tcphdr *tcph;
|
||||
struct udphdr *udph;
|
||||
unsigned int i;
|
||||
bool cond;
|
||||
|
||||
switch (l4proto) {
|
||||
case IPPROTO_TCP:
|
||||
tcph = (void *)iph + l4offset;
|
||||
for (i = 0; i < 4; ++i)
|
||||
inet_proto_csum_replace4(&tcph->check, skb,
|
||||
oldip->s6_addr32[i], newip->s6_addr32[i], true);
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_UDPLITE:
|
||||
udph = (void *)iph + l4offset;
|
||||
cond = udph->check;
|
||||
cond |= skb->ip_summed == CHECKSUM_PARTIAL;
|
||||
if (cond) {
|
||||
for (i = 0; i < 4; ++i)
|
||||
inet_proto_csum_replace4(&udph->check, skb,
|
||||
oldip->s6_addr32[i],
|
||||
newip->s6_addr32[i], true);
|
||||
if (udph->check == 0)
|
||||
udph->check = CSUM_MANGLED_0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
rawsnat_tg6(struct sk_buff **pskb, const struct xt_action_param *par)
|
||||
{
|
||||
const struct xt_rawnat_tginfo *info = par->targinfo;
|
||||
unsigned int l4offset = 0, l4proto;
|
||||
struct ipv6hdr *iph;
|
||||
struct in6_addr new_addr;
|
||||
|
||||
iph = ipv6_hdr(*pskb);
|
||||
memcpy(&new_addr, &iph->saddr, sizeof(new_addr));
|
||||
rawnat_ipv6_mask(new_addr.s6_addr32, info->addr.ip6, info->mask);
|
||||
if (ipv6_addr_cmp(&iph->saddr, &new_addr) == 0)
|
||||
return XT_CONTINUE;
|
||||
if (!rawnat6_prepare_l4(pskb, &l4offset, &l4proto))
|
||||
return NF_DROP;
|
||||
iph = ipv6_hdr(*pskb);
|
||||
rawnat6_update_l4(*pskb, l4proto, l4offset, &iph->saddr, &new_addr);
|
||||
memcpy(&iph->saddr, &new_addr, sizeof(new_addr));
|
||||
return XT_CONTINUE;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
rawdnat_tg6(struct sk_buff **pskb, const struct xt_action_param *par)
|
||||
{
|
||||
const struct xt_rawnat_tginfo *info = par->targinfo;
|
||||
unsigned int l4offset = 0, l4proto;
|
||||
struct ipv6hdr *iph;
|
||||
struct in6_addr new_addr;
|
||||
|
||||
iph = ipv6_hdr(*pskb);
|
||||
memcpy(&new_addr, &iph->daddr, sizeof(new_addr));
|
||||
rawnat_ipv6_mask(new_addr.s6_addr32, info->addr.ip6, info->mask);
|
||||
if (ipv6_addr_cmp(&iph->daddr, &new_addr) == 0)
|
||||
return XT_CONTINUE;
|
||||
if (!rawnat6_prepare_l4(pskb, &l4offset, &l4proto))
|
||||
return NF_DROP;
|
||||
iph = ipv6_hdr(*pskb);
|
||||
rawnat6_update_l4(*pskb, l4proto, l4offset, &iph->daddr, &new_addr);
|
||||
memcpy(&iph->daddr, &new_addr, sizeof(new_addr));
|
||||
return XT_CONTINUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int rawnat_tg_check(const struct xt_tgchk_param *par)
|
||||
{
|
||||
if (strcmp(par->table, "raw") == 0 ||
|
||||
strcmp(par->table, "rawpost") == 0)
|
||||
return 0;
|
||||
|
||||
printk(KERN_ERR KBUILD_MODNAME " may only be used in the \"raw\" or "
|
||||
"\"rawpost\" table.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static struct xt_target rawnat_tg_reg[] __read_mostly = {
|
||||
{
|
||||
.name = "RAWSNAT",
|
||||
.revision = 0,
|
||||
.family = NFPROTO_IPV4,
|
||||
.target = rawsnat_tg4,
|
||||
.targetsize = sizeof(struct xt_rawnat_tginfo),
|
||||
.checkentry = rawnat_tg_check,
|
||||
.me = THIS_MODULE,
|
||||
},
|
||||
#ifdef WITH_IPV6
|
||||
{
|
||||
.name = "RAWSNAT",
|
||||
.revision = 0,
|
||||
.family = NFPROTO_IPV6,
|
||||
.target = rawsnat_tg6,
|
||||
.targetsize = sizeof(struct xt_rawnat_tginfo),
|
||||
.checkentry = rawnat_tg_check,
|
||||
.me = THIS_MODULE,
|
||||
},
|
||||
#endif
|
||||
{
|
||||
.name = "RAWDNAT",
|
||||
.revision = 0,
|
||||
.family = NFPROTO_IPV4,
|
||||
.target = rawdnat_tg4,
|
||||
.targetsize = sizeof(struct xt_rawnat_tginfo),
|
||||
.checkentry = rawnat_tg_check,
|
||||
.me = THIS_MODULE,
|
||||
},
|
||||
#ifdef WITH_IPV6
|
||||
{
|
||||
.name = "RAWDNAT",
|
||||
.revision = 0,
|
||||
.family = NFPROTO_IPV6,
|
||||
.target = rawdnat_tg6,
|
||||
.targetsize = sizeof(struct xt_rawnat_tginfo),
|
||||
.checkentry = rawnat_tg_check,
|
||||
.me = THIS_MODULE,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
static int __init rawnat_tg_init(void)
|
||||
{
|
||||
return xt_register_targets(rawnat_tg_reg, ARRAY_SIZE(rawnat_tg_reg));
|
||||
}
|
||||
|
||||
static void __exit rawnat_tg_exit(void)
|
||||
{
|
||||
xt_unregister_targets(rawnat_tg_reg, ARRAY_SIZE(rawnat_tg_reg));
|
||||
}
|
||||
|
||||
module_init(rawnat_tg_init);
|
||||
module_exit(rawnat_tg_exit);
|
||||
MODULE_AUTHOR("Jan Engelhardt ");
|
||||
MODULE_DESCRIPTION("Xtables: conntrack-less raw NAT");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("ipt_RAWSNAT");
|
||||
MODULE_ALIAS("ipt_RAWDNAT");
|
||||
MODULE_ALIAS("ip6t_RAWSNAT");
|
||||
MODULE_ALIAS("ip6t_RAWDNAT");
|
@@ -1,9 +0,0 @@
|
||||
#ifndef _LINUX_NETFILTER_XT_TARGET_RAWNAT
|
||||
#define _LINUX_NETFILTER_XT_TARGET_RAWNAT 1
|
||||
|
||||
struct xt_rawnat_tginfo {
|
||||
union nf_inet_addr addr;
|
||||
__u8 mask;
|
||||
};
|
||||
|
||||
#endif /* _LINUX_NETFILTER_XT_TARGET_RAWNAT */
|
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* "STEAL" demo target extension for Xtables
|
||||
* written by Jan Engelhardt, 2008 - 2009
|
||||
* placed in the Public Domain
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include "compat_xtables.h"
|
||||
|
||||
static unsigned int
|
||||
steal_tg(struct sk_buff **pskb, const struct xt_action_param *par)
|
||||
{
|
||||
kfree_skb(*pskb);
|
||||
return NF_STOLEN;
|
||||
}
|
||||
|
||||
static struct xt_target steal_tg_reg[] __read_mostly = {
|
||||
{
|
||||
.name = "STEAL",
|
||||
.revision = 0,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.target = steal_tg,
|
||||
.me = THIS_MODULE,
|
||||
},
|
||||
{
|
||||
.name = "STEAL",
|
||||
.revision = 0,
|
||||
.family = NFPROTO_IPV6,
|
||||
.target = steal_tg,
|
||||
.me = THIS_MODULE,
|
||||
},
|
||||
{
|
||||
.name = "STEAL",
|
||||
.revision = 0,
|
||||
.family = NFPROTO_ARP,
|
||||
.target = steal_tg,
|
||||
.me = THIS_MODULE,
|
||||
},
|
||||
{
|
||||
.name = "STEAL",
|
||||
.revision = 0,
|
||||
.family = NFPROTO_BRIDGE,
|
||||
.target = steal_tg,
|
||||
.me = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init steal_tg_init(void)
|
||||
{
|
||||
return xt_register_targets(steal_tg_reg, ARRAY_SIZE(steal_tg_reg));
|
||||
}
|
||||
|
||||
static void __exit steal_tg_exit(void)
|
||||
{
|
||||
xt_unregister_targets(steal_tg_reg, ARRAY_SIZE(steal_tg_reg));
|
||||
}
|
||||
|
||||
module_init(steal_tg_init);
|
||||
module_exit(steal_tg_exit);
|
||||
MODULE_AUTHOR("Jan Engelhardt ");
|
||||
MODULE_DESCRIPTION("Xtables: Silently DROP packets on output chain");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("ipt_STEAL");
|
||||
MODULE_ALIAS("ip6t_STEAL");
|
||||
MODULE_ALIAS("arpt_STEAL");
|
||||
MODULE_ALIAS("ebt_STEAL");
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* "SYSRQ" target extension for Xtables
|
||||
* Copyright © Jan Engelhardt, 2008 - 2012
|
||||
* Copyright Jan Engelhardt, 2016
|
||||
*
|
||||
* Based upon the ipt_SYSRQ idea by Marek Zalem <marek [at] terminus sk>
|
||||
*
|
||||
@@ -21,8 +21,7 @@
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
#include <linux/netfilter_ipv6/ip6_tables.h>
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <crypto/hash.h>
|
||||
#include <net/ip.h>
|
||||
#include <net/ipv6.h>
|
||||
#include "compat_xtables.h"
|
||||
@@ -50,7 +49,7 @@ MODULE_PARM_DESC(seqno, "sequence number for remote sysrq");
|
||||
MODULE_PARM_DESC(debug, "debugging: 0=off, 1=on");
|
||||
|
||||
#ifdef WITH_CRYPTO
|
||||
static struct crypto_hash *sysrq_tfm;
|
||||
static struct crypto_shash *sysrq_tfm;
|
||||
static int sysrq_digest_size;
|
||||
static unsigned char *sysrq_digest_password;
|
||||
static unsigned char *sysrq_digest;
|
||||
@@ -75,8 +74,7 @@ static unsigned int sysrq_tg(const void *pdata, uint16_t len)
|
||||
{
|
||||
const char *data = pdata;
|
||||
int i, n;
|
||||
struct scatterlist sg[2];
|
||||
struct hash_desc desc;
|
||||
struct shash_desc desc;
|
||||
int ret;
|
||||
long new_seqno = 0;
|
||||
|
||||
@@ -116,16 +114,15 @@ static unsigned int sysrq_tg(const void *pdata, uint16_t len)
|
||||
}
|
||||
|
||||
desc.tfm = sysrq_tfm;
|
||||
desc.flags = 0;
|
||||
ret = crypto_hash_init(&desc);
|
||||
ret = crypto_shash_init(&desc);
|
||||
if (ret != 0)
|
||||
goto hash_fail;
|
||||
sg_init_table(sg, 2);
|
||||
sg_set_buf(&sg[0], data, n);
|
||||
i = strlen(sysrq_digest_password);
|
||||
sg_set_buf(&sg[1], sysrq_digest_password, i);
|
||||
ret = crypto_hash_digest(&desc, sg, n + i, sysrq_digest);
|
||||
if (ret != 0)
|
||||
if (crypto_shash_update(&desc, data, n) != 0)
|
||||
goto hash_fail;
|
||||
if (crypto_shash_update(&desc, sysrq_digest_password,
|
||||
strlen(sysrq_digest_password)) != 0)
|
||||
goto hash_fail;
|
||||
if (crypto_shash_final(&desc, sysrq_digest) != 0)
|
||||
goto hash_fail;
|
||||
|
||||
for (i = 0; i < sysrq_digest_size; ++i) {
|
||||
@@ -189,9 +186,8 @@ static unsigned int sysrq_tg(const void *pdata, uint16_t len)
|
||||
#endif
|
||||
|
||||
static unsigned int
|
||||
sysrq_tg4(struct sk_buff **pskb, const struct xt_action_param *par)
|
||||
sysrq_tg4(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
{
|
||||
struct sk_buff *skb = *pskb;
|
||||
const struct iphdr *iph;
|
||||
const struct udphdr *udph;
|
||||
uint16_t len;
|
||||
@@ -220,9 +216,8 @@ sysrq_tg4(struct sk_buff **pskb, const struct xt_action_param *par)
|
||||
|
||||
#ifdef WITH_IPV6
|
||||
static unsigned int
|
||||
sysrq_tg6(struct sk_buff **pskb, const struct xt_action_param *par)
|
||||
sysrq_tg6(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
{
|
||||
struct sk_buff *skb = *pskb;
|
||||
const struct ipv6hdr *iph;
|
||||
const struct udphdr *udph;
|
||||
unsigned short frag_off;
|
||||
@@ -305,7 +300,7 @@ static void sysrq_crypto_exit(void)
|
||||
{
|
||||
#ifdef WITH_CRYPTO
|
||||
if (sysrq_tfm)
|
||||
crypto_free_hash(sysrq_tfm);
|
||||
crypto_free_shash(sysrq_tfm);
|
||||
if (sysrq_digest)
|
||||
kfree(sysrq_digest);
|
||||
if (sysrq_hexdigest)
|
||||
@@ -318,10 +313,10 @@ static void sysrq_crypto_exit(void)
|
||||
static int __init sysrq_crypto_init(void)
|
||||
{
|
||||
#if defined(WITH_CRYPTO)
|
||||
struct timeval now;
|
||||
struct timespec64 now;
|
||||
int ret;
|
||||
|
||||
sysrq_tfm = crypto_alloc_hash(sysrq_hash, 0, CRYPTO_ALG_ASYNC);
|
||||
sysrq_tfm = crypto_alloc_shash(sysrq_hash, 0, 0);
|
||||
if (IS_ERR(sysrq_tfm)) {
|
||||
printk(KERN_WARNING KBUILD_MODNAME
|
||||
": Error: Could not find or load %s hash\n",
|
||||
@@ -330,7 +325,7 @@ static int __init sysrq_crypto_init(void)
|
||||
sysrq_tfm = NULL;
|
||||
goto fail;
|
||||
}
|
||||
sysrq_digest_size = crypto_hash_digestsize(sysrq_tfm);
|
||||
sysrq_digest_size = crypto_shash_digestsize(sysrq_tfm);
|
||||
sysrq_digest = kmalloc(sysrq_digest_size, GFP_KERNEL);
|
||||
ret = -ENOMEM;
|
||||
if (sysrq_digest == NULL)
|
||||
@@ -343,7 +338,7 @@ static int __init sysrq_crypto_init(void)
|
||||
sizeof(sysrq_password), GFP_KERNEL);
|
||||
if (sysrq_digest_password == NULL)
|
||||
goto fail;
|
||||
do_gettimeofday(&now);
|
||||
ktime_get_real_ts64(&now);
|
||||
sysrq_seqno = now.tv_sec;
|
||||
return 0;
|
||||
|
||||
@@ -373,7 +368,7 @@ static void __exit sysrq_tg_exit(void)
|
||||
module_init(sysrq_tg_init);
|
||||
module_exit(sysrq_tg_exit);
|
||||
MODULE_DESCRIPTION("Xtables: triggering SYSRQ remotely");
|
||||
MODULE_AUTHOR("Jan Engelhardt ");
|
||||
MODULE_AUTHOR("Jan Engelhardt");
|
||||
MODULE_AUTHOR("John Haxby <john.haxby@oracle.com");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("ipt_SYSRQ");
|
||||
|
@@ -107,8 +107,8 @@ static bool xttarpit_honeypot(struct tcphdr *tcph, const struct tcphdr *oth,
|
||||
tcph->syn = true;
|
||||
tcph->ack = true;
|
||||
tcph->window = oth->window &
|
||||
((net_random() & 0x1f) - 0xf);
|
||||
tcph->seq = htonl(net_random() & ~oth->seq);
|
||||
((prandom_u32() & 0x1f) - 0xf);
|
||||
tcph->seq = htonl(prandom_u32() & ~oth->seq);
|
||||
tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn);
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ static bool xttarpit_honeypot(struct tcphdr *tcph, const struct tcphdr *oth,
|
||||
tcph->syn = false;
|
||||
tcph->ack = true;
|
||||
tcph->window = oth->window &
|
||||
((net_random() & 0x1f) - 0xf);
|
||||
((prandom_u32() & 0x1f) - 0xf);
|
||||
tcph->ack_seq = payload > 100 ?
|
||||
htonl(ntohl(oth->seq) + payload) :
|
||||
oth->seq;
|
||||
@@ -170,8 +170,8 @@ static bool tarpit_generic(struct tcphdr *tcph, const struct tcphdr *oth,
|
||||
return true;
|
||||
}
|
||||
|
||||
static void tarpit_tcp4(struct sk_buff *oldskb, unsigned int hook,
|
||||
unsigned int mode)
|
||||
static void tarpit_tcp4(struct net *net, struct sk_buff *oldskb,
|
||||
unsigned int hook, unsigned int mode)
|
||||
{
|
||||
struct tcphdr _otcph, *tcph;
|
||||
const struct tcphdr *oth;
|
||||
@@ -205,7 +205,11 @@ static void tarpit_tcp4(struct sk_buff *oldskb, unsigned int hook,
|
||||
return;
|
||||
|
||||
/* This packet will not be the same as the other: clear nf fields */
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)
|
||||
nf_reset_ct(nskb);
|
||||
#else
|
||||
nf_reset(nskb);
|
||||
#endif
|
||||
skb_nfmark(nskb) = 0;
|
||||
skb_init_secmark(nskb);
|
||||
skb_shinfo(nskb)->gso_size = 0;
|
||||
@@ -249,14 +253,19 @@ static void tarpit_tcp4(struct sk_buff *oldskb, unsigned int hook,
|
||||
niph->id = ~oldhdr->id + 1;
|
||||
|
||||
#ifdef CONFIG_BRIDGE_NETFILTER
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
|
||||
if (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 || (nskb->nf_bridge != NULL &&
|
||||
nskb->nf_bridge->mask & BRNF_BRIDGED))
|
||||
nskb->nf_bridge->physoutdev != NULL))
|
||||
#endif
|
||||
#else
|
||||
if (hook != NF_INET_FORWARD)
|
||||
#endif
|
||||
addr_type = RTN_LOCAL;
|
||||
|
||||
if (ip_route_me_harder(&nskb, addr_type))
|
||||
if (ip_route_me_harder(net, nskb, addr_type))
|
||||
goto free_nskb;
|
||||
else
|
||||
niph = ip_hdr(nskb);
|
||||
@@ -278,8 +287,7 @@ static void tarpit_tcp4(struct sk_buff *oldskb, unsigned int hook,
|
||||
goto free_nskb;
|
||||
|
||||
nf_ct_attach(nskb, oldskb);
|
||||
|
||||
NF_HOOK(NFPROTO_IPV4, NF_INET_LOCAL_OUT, nskb, NULL,
|
||||
NF_HOOK(NFPROTO_IPV4, NF_INET_LOCAL_OUT, net, nskb->sk, nskb, NULL,
|
||||
skb_dst(nskb)->dev, dst_output);
|
||||
return;
|
||||
|
||||
@@ -288,8 +296,8 @@ static void tarpit_tcp4(struct sk_buff *oldskb, unsigned int hook,
|
||||
}
|
||||
|
||||
#ifdef WITH_IPV6
|
||||
static void tarpit_tcp6(struct sk_buff *oldskb, unsigned int hook,
|
||||
unsigned int mode)
|
||||
static void tarpit_tcp6(struct net *net, struct sk_buff *oldskb,
|
||||
unsigned int hook, unsigned int mode)
|
||||
{
|
||||
struct sk_buff *nskb;
|
||||
struct tcphdr *tcph, oth;
|
||||
@@ -342,7 +350,11 @@ static void tarpit_tcp6(struct sk_buff *oldskb, unsigned int hook,
|
||||
}
|
||||
|
||||
/* This packet will not be the same as the other: clear nf fields */
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)
|
||||
nf_reset_ct(nskb);
|
||||
#else
|
||||
nf_reset(nskb);
|
||||
#endif
|
||||
skb_nfmark(nskb) = 0;
|
||||
skb_init_secmark(nskb);
|
||||
skb_shinfo(nskb)->gso_size = 0;
|
||||
@@ -387,14 +399,13 @@ static void tarpit_tcp6(struct sk_buff *oldskb, unsigned int hook,
|
||||
IPPROTO_TCP,
|
||||
csum_partial(tcph, sizeof(struct tcphdr), 0));
|
||||
|
||||
if (ip6_route_me_harder(nskb))
|
||||
if (ip6_route_me_harder(net, nskb))
|
||||
goto free_nskb;
|
||||
|
||||
nskb->ip_summed = CHECKSUM_NONE;
|
||||
|
||||
nf_ct_attach(nskb, oldskb);
|
||||
|
||||
NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, nskb, NULL,
|
||||
NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, net, nskb->sk, nskb, NULL,
|
||||
skb_dst(nskb)->dev, dst_output);
|
||||
return;
|
||||
|
||||
@@ -404,9 +415,8 @@ static void tarpit_tcp6(struct sk_buff *oldskb, unsigned int hook,
|
||||
#endif
|
||||
|
||||
static unsigned int
|
||||
tarpit_tg4(struct sk_buff **pskb, const struct xt_action_param *par)
|
||||
tarpit_tg4(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
{
|
||||
const struct sk_buff *skb = *pskb;
|
||||
const struct iphdr *iph = ip_hdr(skb);
|
||||
const struct rtable *rt = skb_rtable(skb);
|
||||
const struct xt_tarpit_tginfo *info = par->targinfo;
|
||||
@@ -434,16 +444,14 @@ tarpit_tg4(struct sk_buff **pskb, const struct xt_action_param *par)
|
||||
/* We are not interested in fragments */
|
||||
if (iph->frag_off & htons(IP_OFFSET))
|
||||
return NF_DROP;
|
||||
|
||||
tarpit_tcp4(*pskb, par->hooknum, info->variant);
|
||||
tarpit_tcp4(par_net(par), skb, par->state->hook, info->variant);
|
||||
return NF_DROP;
|
||||
}
|
||||
|
||||
#ifdef WITH_IPV6
|
||||
static unsigned int
|
||||
tarpit_tg6(struct sk_buff **pskb, const struct xt_action_param *par)
|
||||
tarpit_tg6(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
{
|
||||
const struct sk_buff *skb = *pskb;
|
||||
const struct ipv6hdr *iph = ipv6_hdr(skb);
|
||||
const struct rt6_info *rt = (struct rt6_info *)skb_dst(skb);
|
||||
const struct xt_tarpit_tginfo *info = par->targinfo;
|
||||
@@ -477,8 +485,7 @@ tarpit_tg6(struct sk_buff **pskb, const struct xt_action_param *par)
|
||||
pr_debug("addr is not unicast.\n");
|
||||
return NF_DROP;
|
||||
}
|
||||
|
||||
tarpit_tcp6(*pskb, par->hooknum, info->variant);
|
||||
tarpit_tcp6(par_net(par), skb, par->state->hook, info->variant);
|
||||
return NF_DROP;
|
||||
}
|
||||
#endif
|
||||
|
@@ -7,6 +7,7 @@
|
||||
* Authors:
|
||||
* Stephane Ouellette <ouellettes [at] videotron ca>, 2002-10-22
|
||||
* Massimiliano Hofer <max [at] nucleus it>, 2006-05-15
|
||||
* Grzegorz Kuczyński <grzegorz.kuczynski [at] koba pl>, 2017-02-27
|
||||
*
|
||||
* 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
|
||||
@@ -21,6 +22,8 @@
|
||||
#include <linux/version.h>
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <net/net_namespace.h>
|
||||
#include <net/netns/generic.h>
|
||||
#include "xt_condition.h"
|
||||
#include "compat_xtables.h"
|
||||
|
||||
@@ -59,14 +62,25 @@ struct condition_variable {
|
||||
/* to the conditions' list. */
|
||||
static DEFINE_MUTEX(proc_lock);
|
||||
|
||||
static LIST_HEAD(conditions_list);
|
||||
static struct proc_dir_entry *proc_net_condition;
|
||||
struct condition_net {
|
||||
struct list_head conditions_list;
|
||||
struct proc_dir_entry *proc_net_condition;
|
||||
bool after_clear;
|
||||
};
|
||||
|
||||
static int condition_net_id;
|
||||
|
||||
static inline struct condition_net *condition_pernet(struct net *net)
|
||||
{
|
||||
return net_generic(net, condition_net_id);
|
||||
}
|
||||
|
||||
static int condition_proc_show(struct seq_file *m, void *data)
|
||||
{
|
||||
const struct condition_variable *var = m->private;
|
||||
|
||||
return seq_printf(m, var->enabled ? "1\n" : "0\n");
|
||||
seq_printf(m, var->enabled ? "1\n" : "0\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int condition_proc_open(struct inode *inode, struct file *file)
|
||||
@@ -97,12 +111,12 @@ condition_proc_write(struct file *file, const char __user *buffer,
|
||||
return length;
|
||||
}
|
||||
|
||||
static const struct file_operations condition_proc_fops = {
|
||||
.open = condition_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.write = condition_proc_write,
|
||||
.release = single_release,
|
||||
static const struct proc_ops condition_proc_fops = {
|
||||
.proc_open = condition_proc_open,
|
||||
.proc_read = seq_read,
|
||||
.proc_write = condition_proc_write,
|
||||
.proc_lseek = seq_lseek,
|
||||
.proc_release = single_release,
|
||||
};
|
||||
|
||||
static bool
|
||||
@@ -118,6 +132,7 @@ static int condition_mt_check(const struct xt_mtchk_param *par)
|
||||
{
|
||||
struct xt_condition_mtinfo *info = par->matchinfo;
|
||||
struct condition_variable *var;
|
||||
struct condition_net *condition_net = condition_pernet(par->net);
|
||||
|
||||
/* Forbid certain names */
|
||||
if (*info->name == '\0' || *info->name == '.' ||
|
||||
@@ -133,7 +148,7 @@ static int condition_mt_check(const struct xt_mtchk_param *par)
|
||||
* or increase the reference counter.
|
||||
*/
|
||||
mutex_lock(&proc_lock);
|
||||
list_for_each_entry(var, &conditions_list, list) {
|
||||
list_for_each_entry(var, &condition_net->conditions_list, list) {
|
||||
if (strcmp(info->name, var->name) == 0) {
|
||||
var->refcount++;
|
||||
mutex_unlock(&proc_lock);
|
||||
@@ -152,7 +167,7 @@ static int condition_mt_check(const struct xt_mtchk_param *par)
|
||||
memcpy(var->name, info->name, sizeof(info->name));
|
||||
/* Create the condition variable's proc file entry. */
|
||||
var->status_proc = proc_create_data(info->name, condition_list_perms,
|
||||
proc_net_condition, &condition_proc_fops, var);
|
||||
condition_net->proc_net_condition, &condition_proc_fops, var);
|
||||
if (var->status_proc == NULL) {
|
||||
kfree(var);
|
||||
mutex_unlock(&proc_lock);
|
||||
@@ -165,7 +180,7 @@ static int condition_mt_check(const struct xt_mtchk_param *par)
|
||||
var->refcount = 1;
|
||||
var->enabled = false;
|
||||
wmb();
|
||||
list_add(&var->list, &conditions_list);
|
||||
list_add(&var->list, &condition_net->conditions_list);
|
||||
mutex_unlock(&proc_lock);
|
||||
info->condvar = var;
|
||||
return 0;
|
||||
@@ -175,11 +190,15 @@ static void condition_mt_destroy(const struct xt_mtdtor_param *par)
|
||||
{
|
||||
const struct xt_condition_mtinfo *info = par->matchinfo;
|
||||
struct condition_variable *var = info->condvar;
|
||||
struct condition_net *cnet = condition_pernet(par->net);
|
||||
|
||||
if (cnet->after_clear)
|
||||
return;
|
||||
|
||||
mutex_lock(&proc_lock);
|
||||
if (--var->refcount == 0) {
|
||||
list_del(&var->list);
|
||||
proc_remove(var->status_proc);
|
||||
remove_proc_entry(var->name, cnet->proc_net_condition);
|
||||
mutex_unlock(&proc_lock);
|
||||
kfree(var);
|
||||
return;
|
||||
@@ -212,18 +231,54 @@ static struct xt_match condition_mt_reg[] __read_mostly = {
|
||||
|
||||
static const char *const dir_name = "nf_condition";
|
||||
|
||||
static int __net_init condition_net_init(struct net *net)
|
||||
{
|
||||
struct condition_net *condition_net = condition_pernet(net);
|
||||
INIT_LIST_HEAD(&condition_net->conditions_list);
|
||||
condition_net->proc_net_condition = proc_mkdir(dir_name, net->proc_net);
|
||||
if (condition_net->proc_net_condition == NULL)
|
||||
return -EACCES;
|
||||
condition_net->after_clear = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __net_exit condition_net_exit(struct net *net)
|
||||
{
|
||||
struct condition_net *condition_net = condition_pernet(net);
|
||||
struct list_head *pos, *q;
|
||||
struct condition_variable *var = NULL;
|
||||
|
||||
remove_proc_subtree(dir_name, net->proc_net);
|
||||
mutex_lock(&proc_lock);
|
||||
list_for_each_safe(pos, q, &condition_net->conditions_list) {
|
||||
var = list_entry(pos, struct condition_variable, list);
|
||||
list_del(pos);
|
||||
kfree(var);
|
||||
}
|
||||
mutex_unlock(&proc_lock);
|
||||
condition_net->after_clear = true;
|
||||
}
|
||||
|
||||
static struct pernet_operations condition_net_ops = {
|
||||
.init = condition_net_init,
|
||||
.exit = condition_net_exit,
|
||||
.id = &condition_net_id,
|
||||
.size = sizeof(struct condition_net),
|
||||
};
|
||||
|
||||
|
||||
static int __init condition_mt_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mutex_init(&proc_lock);
|
||||
proc_net_condition = proc_mkdir(dir_name, init_net.proc_net);
|
||||
if (proc_net_condition == NULL)
|
||||
return -EACCES;
|
||||
ret = register_pernet_subsys(&condition_net_ops);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
ret = xt_register_matches(condition_mt_reg, ARRAY_SIZE(condition_mt_reg));
|
||||
if (ret < 0) {
|
||||
remove_proc_entry(dir_name, init_net.proc_net);
|
||||
unregister_pernet_subsys(&condition_net_ops);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -233,7 +288,7 @@ static int __init condition_mt_init(void)
|
||||
static void __exit condition_mt_exit(void)
|
||||
{
|
||||
xt_unregister_matches(condition_mt_reg, ARRAY_SIZE(condition_mt_reg));
|
||||
remove_proc_entry(dir_name, init_net.proc_net);
|
||||
unregister_pernet_subsys(&condition_net_ops);
|
||||
}
|
||||
|
||||
module_init(condition_mt_init);
|
||||
|
@@ -75,7 +75,8 @@ geoip_add_node(const struct geoip_country_user __user *umem_ptr,
|
||||
|
||||
if (copy_from_user(&umem, umem_ptr, sizeof(umem)) != 0)
|
||||
return ERR_PTR(-EFAULT);
|
||||
|
||||
if (umem.count > SIZE_MAX / geoproto_size[proto])
|
||||
return ERR_PTR(-E2BIG);
|
||||
p = kmalloc(sizeof(struct geoip_country_kernel), GFP_KERNEL);
|
||||
if (p == NULL)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
@@ -45,9 +45,9 @@ static const struct net_device *iface_get(const struct xt_iface_mtinfo *info,
|
||||
const struct xt_action_param *par, struct net_device **put)
|
||||
{
|
||||
if (info->flags & XT_IFACE_DEV_IN)
|
||||
return par->in;
|
||||
return par->state->in;
|
||||
else if (info->flags & XT_IFACE_DEV_OUT)
|
||||
return par->out;
|
||||
return par->state->out;
|
||||
return *put = dev_get_by_name(&init_net, info->ifname);
|
||||
}
|
||||
|
||||
|
@@ -511,7 +511,7 @@ search_bittorrent(const unsigned char *payload, const unsigned int plen)
|
||||
* but *must have* one (or more) of strings listed below (true for scrape and announce)
|
||||
*/
|
||||
if (memcmp(payload, "GET /", 5) == 0) {
|
||||
if (HX_memmem(payload, plen, "info_hash=", 9) != NULL)
|
||||
if (HX_memmem(payload, plen, "info_hash=", 10) != NULL)
|
||||
return IPP2P_BIT * 100 + 1;
|
||||
if (HX_memmem(payload, plen, "peer_id=", 8) != NULL)
|
||||
return IPP2P_BIT * 100 + 2;
|
||||
|
@@ -204,7 +204,7 @@ lscan_mt(const struct sk_buff *skb, struct xt_action_param *par)
|
||||
unsigned int n;
|
||||
|
||||
n = lscan_mt_full(ctdata->mark & connmark_mask, ctstate,
|
||||
par->in == init_net.loopback_dev, tcph,
|
||||
par->state->in == init_net.loopback_dev, tcph,
|
||||
skb->len - par->thoff - 4 * tcph->doff);
|
||||
|
||||
ctdata->mark = (ctdata->mark & ~connmark_mask) | n;
|
||||
|
@@ -45,12 +45,12 @@ MODULE_ALIAS("ip6t_psd");
|
||||
|
||||
/*
|
||||
* Keep track of up to LIST_SIZE source addresses, using a hash table of
|
||||
* HASH_SIZE entries for faster lookups, but limiting hash collisions to
|
||||
* PSD_HASH_SIZE entries for faster lookups, but limiting hash collisions to
|
||||
* HASH_MAX source addresses per the same hash value.
|
||||
*/
|
||||
#define LIST_SIZE 0x100
|
||||
#define HASH_LOG 9
|
||||
#define HASH_SIZE (1 << HASH_LOG)
|
||||
#define PSD_HASH_SIZE (1 << HASH_LOG)
|
||||
#define HASH_MAX 0x10
|
||||
|
||||
#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
|
||||
@@ -108,7 +108,7 @@ struct host6 {
|
||||
static struct {
|
||||
spinlock_t lock;
|
||||
struct host4 list[LIST_SIZE];
|
||||
struct host *hash[HASH_SIZE];
|
||||
struct host *hash[PSD_HASH_SIZE];
|
||||
int index;
|
||||
} state;
|
||||
|
||||
@@ -143,13 +143,12 @@ static bool state6_alloc_mem(void)
|
||||
if (state6.list == NULL)
|
||||
return false;
|
||||
memset(state6.list, 0, LIST_SIZE * sizeof(struct host6));
|
||||
|
||||
state6.hash = vmalloc(HASH_SIZE * sizeof(struct host*));
|
||||
state6.hash = vmalloc(PSD_HASH_SIZE * sizeof(struct host *));
|
||||
if (state6.hash == NULL) {
|
||||
vfree(state6.list);
|
||||
return false;
|
||||
}
|
||||
memset(state6.hash, 0, HASH_SIZE * sizeof(struct host *));
|
||||
memset(state6.hash, 0, PSD_HASH_SIZE * sizeof(struct host *));
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
@@ -167,8 +166,7 @@ static unsigned int hashfunc(__be32 addr)
|
||||
do {
|
||||
hash ^= value;
|
||||
} while ((value >>= HASH_LOG) != 0);
|
||||
|
||||
return hash & (HASH_SIZE - 1);
|
||||
return hash & (PSD_HASH_SIZE - 1);
|
||||
}
|
||||
|
||||
static inline unsigned int hashfunc6(const struct in6_addr *addr)
|
||||
|
@@ -13,6 +13,7 @@
|
||||
*/
|
||||
#include <linux/list.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/nsproxy.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/skbuff.h>
|
||||
@@ -20,6 +21,9 @@
|
||||
#include <linux/uidgid.h>
|
||||
#include <linux/version.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <net/net_namespace.h>
|
||||
#include <net/netns/generic.h>
|
||||
#include <net/dst.h>
|
||||
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#include "xt_quota2.h"
|
||||
@@ -37,10 +41,19 @@ struct xt_quota_counter {
|
||||
struct proc_dir_entry *procfs_entry;
|
||||
};
|
||||
|
||||
static LIST_HEAD(counter_list);
|
||||
struct quota2_net {
|
||||
struct list_head counter_list;
|
||||
struct proc_dir_entry *proc_xt_quota;
|
||||
};
|
||||
|
||||
static int quota2_net_id;
|
||||
static inline struct quota2_net *quota2_pernet(struct net *net)
|
||||
{
|
||||
return net_generic(net, quota2_net_id);
|
||||
}
|
||||
|
||||
static DEFINE_SPINLOCK(counter_list_lock);
|
||||
|
||||
static struct proc_dir_entry *proc_xt_quota;
|
||||
static unsigned int quota_list_perms = S_IRUGO | S_IWUSR;
|
||||
static unsigned int quota_list_uid = 0;
|
||||
static unsigned int quota_list_gid = 0;
|
||||
@@ -51,12 +64,11 @@ module_param_named(gid, quota_list_gid, uint, S_IRUGO | S_IWUSR);
|
||||
static int quota_proc_show(struct seq_file *m, void *data)
|
||||
{
|
||||
struct xt_quota_counter *e = m->private;
|
||||
int ret;
|
||||
|
||||
spin_lock_bh(&e->lock);
|
||||
ret = seq_printf(m, "%llu\n", e->quota);
|
||||
seq_printf(m, "%llu\n", e->quota);
|
||||
spin_unlock_bh(&e->lock);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int quota_proc_open(struct inode *inode, struct file *file)
|
||||
@@ -69,26 +81,48 @@ quota_proc_write(struct file *file, const char __user *input,
|
||||
size_t size, loff_t *loff)
|
||||
{
|
||||
struct xt_quota_counter *e = PDE_DATA(file_inode(file));
|
||||
char buf[sizeof("18446744073709551616")];
|
||||
char buf[sizeof("+-18446744073709551616")];
|
||||
|
||||
if (size > sizeof(buf))
|
||||
size = sizeof(buf);
|
||||
if (copy_from_user(buf, input, size) != 0)
|
||||
return -EFAULT;
|
||||
buf[sizeof(buf)-1] = '\0';
|
||||
if (size < sizeof(buf))
|
||||
buf[size] = '\0';
|
||||
|
||||
spin_lock_bh(&e->lock);
|
||||
e->quota = simple_strtoull(buf, NULL, 0);
|
||||
spin_unlock_bh(&e->lock);
|
||||
if (*buf == '+') {
|
||||
int64_t temp = simple_strtoll(buf + 1, NULL, 0);
|
||||
spin_lock_bh(&e->lock);
|
||||
/* Do not let quota become negative if @tmp is very negative */
|
||||
if (temp > 0 || -temp < e->quota)
|
||||
e->quota += temp;
|
||||
else
|
||||
e->quota = 0;
|
||||
spin_unlock_bh(&e->lock);
|
||||
} else if (*buf == '-') {
|
||||
int64_t temp = simple_strtoll(buf + 1, NULL, 0);
|
||||
spin_lock_bh(&e->lock);
|
||||
/* Do not let quota become negative if @tmp is very big */
|
||||
if (temp < 0 || temp < e->quota)
|
||||
e->quota -= temp;
|
||||
else
|
||||
e->quota = 0;
|
||||
spin_unlock_bh(&e->lock);
|
||||
} else {
|
||||
spin_lock_bh(&e->lock);
|
||||
e->quota = simple_strtoull(buf, NULL, 0);
|
||||
spin_unlock_bh(&e->lock);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
static const struct file_operations quota_proc_fops = {
|
||||
.open = quota_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.write = quota_proc_write,
|
||||
.release = single_release,
|
||||
static const struct proc_ops quota_proc_fops = {
|
||||
.proc_open = quota_proc_open,
|
||||
.proc_read = seq_read,
|
||||
.proc_write = quota_proc_write,
|
||||
.proc_lseek = seq_lseek,
|
||||
.proc_release = single_release,
|
||||
};
|
||||
|
||||
static struct xt_quota_counter *
|
||||
@@ -118,16 +152,17 @@ q2_new_counter(const struct xt_quota_mtinfo2 *q, bool anon)
|
||||
* @name: name of counter
|
||||
*/
|
||||
static struct xt_quota_counter *
|
||||
q2_get_counter(const struct xt_quota_mtinfo2 *q)
|
||||
q2_get_counter(struct net *net, const struct xt_quota_mtinfo2 *q)
|
||||
{
|
||||
struct proc_dir_entry *p;
|
||||
struct xt_quota_counter *e;
|
||||
struct quota2_net *quota2_net = quota2_pernet(net);
|
||||
|
||||
if (*q->name == '\0')
|
||||
return q2_new_counter(q, true);
|
||||
|
||||
spin_lock_bh(&counter_list_lock);
|
||||
list_for_each_entry(e, &counter_list, list)
|
||||
list_for_each_entry(e, "a2_net->counter_list, list)
|
||||
if (strcmp(e->name, q->name) == 0) {
|
||||
atomic_inc(&e->ref);
|
||||
spin_unlock_bh(&counter_list_lock);
|
||||
@@ -138,7 +173,8 @@ q2_get_counter(const struct xt_quota_mtinfo2 *q)
|
||||
if (e == NULL)
|
||||
goto out;
|
||||
|
||||
p = proc_create_data(e->name, quota_list_perms, proc_xt_quota,
|
||||
p = proc_create_data(e->name, quota_list_perms,
|
||||
quota2_net->proc_xt_quota,
|
||||
"a_proc_fops, e);
|
||||
if (p == NULL || IS_ERR(p))
|
||||
goto out;
|
||||
@@ -146,7 +182,7 @@ q2_get_counter(const struct xt_quota_mtinfo2 *q)
|
||||
e->procfs_entry = p;
|
||||
proc_set_user(p, make_kuid(&init_user_ns, quota_list_uid),
|
||||
make_kgid(&init_user_ns, quota_list_gid));
|
||||
list_add_tail(&e->list, &counter_list);
|
||||
list_add_tail(&e->list, "a2_net->counter_list);
|
||||
spin_unlock_bh(&counter_list_lock);
|
||||
return e;
|
||||
|
||||
@@ -169,7 +205,7 @@ static int quota_mt2_check(const struct xt_mtchk_param *par)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
q->master = q2_get_counter(q);
|
||||
q->master = q2_get_counter(par->net, q);
|
||||
if (q->master == NULL) {
|
||||
printk(KERN_ERR "xt_quota.3: memory alloc failure\n");
|
||||
return -ENOMEM;
|
||||
@@ -182,6 +218,7 @@ static void quota_mt2_destroy(const struct xt_mtdtor_param *par)
|
||||
{
|
||||
struct xt_quota_mtinfo2 *q = par->matchinfo;
|
||||
struct xt_quota_counter *e = q->master;
|
||||
struct quota2_net *quota2_net = quota2_pernet(par->net);
|
||||
|
||||
if (*q->name == '\0') {
|
||||
kfree(e);
|
||||
@@ -195,7 +232,7 @@ static void quota_mt2_destroy(const struct xt_mtdtor_param *par)
|
||||
}
|
||||
|
||||
list_del(&e->list);
|
||||
remove_proc_entry(e->name, proc_xt_quota);
|
||||
remove_proc_entry(e->name, quota2_net->proc_xt_quota);
|
||||
spin_unlock_bh(&counter_list_lock);
|
||||
kfree(e);
|
||||
}
|
||||
@@ -219,13 +256,14 @@ quota_mt2(const struct sk_buff *skb, struct xt_action_param *par)
|
||||
}
|
||||
ret = true;
|
||||
} else {
|
||||
if (e->quota >= skb->len) {
|
||||
if (e->quota >= ((q->flags & XT_QUOTA_PACKET) ? 1 : skb->len)) {
|
||||
if (!(q->flags & XT_QUOTA_NO_CHANGE))
|
||||
e->quota -= (q->flags & XT_QUOTA_PACKET) ? 1 : skb->len;
|
||||
ret = !ret;
|
||||
} else {
|
||||
/* we do not allow even small packets from now on */
|
||||
e->quota = 0;
|
||||
if (!(q->flags & XT_QUOTA_NO_CHANGE))
|
||||
e->quota = 0;
|
||||
}
|
||||
q->quota = e->quota;
|
||||
}
|
||||
@@ -256,24 +294,60 @@ static struct xt_match quota_mt2_reg[] __read_mostly = {
|
||||
},
|
||||
};
|
||||
|
||||
static int __net_init quota2_net_init(struct net *net)
|
||||
{
|
||||
struct quota2_net *quota2_net = quota2_pernet(net);
|
||||
INIT_LIST_HEAD("a2_net->counter_list);
|
||||
|
||||
quota2_net->proc_xt_quota = proc_mkdir("xt_quota", net->proc_net);
|
||||
if (quota2_net->proc_xt_quota == NULL)
|
||||
return -EACCES;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __net_exit quota2_net_exit(struct net *net)
|
||||
{
|
||||
struct quota2_net *quota2_net = quota2_pernet(net);
|
||||
struct xt_quota_counter *e = NULL;
|
||||
struct list_head *pos, *q;
|
||||
|
||||
remove_proc_entry("xt_quota", net->proc_net);
|
||||
|
||||
/* destroy counter_list while freeing it's content */
|
||||
spin_lock_bh(&counter_list_lock);
|
||||
list_for_each_safe(pos, q, "a2_net->counter_list) {
|
||||
e = list_entry(pos, struct xt_quota_counter, list);
|
||||
list_del(pos);
|
||||
kfree(e);
|
||||
}
|
||||
spin_unlock_bh(&counter_list_lock);
|
||||
}
|
||||
|
||||
static struct pernet_operations quota2_net_ops = {
|
||||
.init = quota2_net_init,
|
||||
.exit = quota2_net_exit,
|
||||
.id = "a2_net_id,
|
||||
.size = sizeof(struct quota2_net),
|
||||
};
|
||||
|
||||
static int __init quota_mt2_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
proc_xt_quota = proc_mkdir("xt_quota", init_net.proc_net);
|
||||
if (proc_xt_quota == NULL)
|
||||
return -EACCES;
|
||||
ret = register_pernet_subsys("a2_net_ops);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = xt_register_matches(quota_mt2_reg, ARRAY_SIZE(quota_mt2_reg));
|
||||
if (ret < 0)
|
||||
remove_proc_entry("xt_quota", init_net.proc_net);
|
||||
unregister_pernet_subsys("a2_net_ops);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit quota_mt2_exit(void)
|
||||
{
|
||||
xt_unregister_matches(quota_mt2_reg, ARRAY_SIZE(quota_mt2_reg));
|
||||
remove_proc_entry("xt_quota", init_net.proc_net);
|
||||
unregister_pernet_subsys("a2_net_ops);
|
||||
}
|
||||
|
||||
module_init(quota_mt2_init);
|
||||
|
@@ -1,5 +1,7 @@
|
||||
# -*- Makefile -*-
|
||||
|
||||
bin_SCRIPTS = xt_geoip_fetch
|
||||
|
||||
pkglibexec_SCRIPTS = xt_geoip_build xt_geoip_dl
|
||||
|
||||
man1_MANS = xt_geoip_build.1 xt_geoip_dl.1
|
||||
man1_MANS = xt_geoip_build.1 xt_geoip_dl.1 xt_geoip_fetch.1
|
||||
|
@@ -1,10 +1,14 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# Converter for MaxMind CSV database to binary, for xt_geoip
|
||||
# Copyright © Jan Engelhardt, 2008-2011
|
||||
# Converter for DBIP (Country Lite) CSV database to binary, for xt_geoip
|
||||
# Copyright Jan Engelhardt, 2008-2011
|
||||
# Copyright Philip Prindeville, 2018
|
||||
# Copyright Arjen de Korte, 2020
|
||||
#
|
||||
use Getopt::Long;
|
||||
use IO::Handle;
|
||||
use Net::CIDR::Lite;
|
||||
use Socket qw(AF_INET AF_INET6 inet_pton);
|
||||
use warnings;
|
||||
use Text::CSV_XS; # or trade for Text::CSV
|
||||
use strict;
|
||||
|
||||
@@ -13,52 +17,62 @@ my $csv = Text::CSV_XS->new({
|
||||
binary => 1,
|
||||
eol => $/,
|
||||
}); # or Text::CSV
|
||||
my $quiet = 0;
|
||||
my $input_file = "dbip-country-lite.csv";
|
||||
my $target_dir = ".";
|
||||
|
||||
&Getopt::Long::Configure(qw(bundling));
|
||||
&GetOptions(
|
||||
"D=s" => \$target_dir,
|
||||
"i=s" => \$input_file,
|
||||
"q" => \$quiet,
|
||||
"s" => sub { $target_dir = "/usr/share/xt_geoip"; },
|
||||
);
|
||||
|
||||
if (!-d $target_dir) {
|
||||
print STDERR "Target directory $target_dir does not exist.\n";
|
||||
print STDERR "Target directory \"$target_dir\" does not exist.\n";
|
||||
exit 1;
|
||||
}
|
||||
foreach (qw(LE BE)) {
|
||||
my $dir = "$target_dir/$_";
|
||||
if (!-e $dir && !mkdir($dir)) {
|
||||
print STDERR "Could not mkdir $dir: $!\n";
|
||||
exit 1;
|
||||
}
|
||||
}
|
||||
|
||||
&dump(&collect());
|
||||
|
||||
sub collect
|
||||
{
|
||||
my %country;
|
||||
my ($file, $fh, $row);
|
||||
my (%country);
|
||||
if ($input_file eq "-") {
|
||||
open($fh, "<&STDIN");
|
||||
} else {
|
||||
open($fh, "<", $input_file) || die "Cannot open $input_file: $!\n";
|
||||
}
|
||||
|
||||
while (my $row = $csv->getline(*ARGV)) {
|
||||
if (!defined($country{$row->[4]})) {
|
||||
$country{$row->[4]} = {
|
||||
name => $row->[5],
|
||||
pool_v4 => [],
|
||||
pool_v6 => [],
|
||||
};
|
||||
while ($row = $csv->getline($fh)) {
|
||||
my ($cc, $range);
|
||||
|
||||
$cc = $row->[2];
|
||||
$range = $row->[0] . "-" . $row->[1];
|
||||
|
||||
if (!exists($country{$cc})) {
|
||||
$country{$cc} = { pool_v4 => Net::CIDR::Lite->new(), pool_v6 => Net::CIDR::Lite->new() };
|
||||
}
|
||||
my $c = $country{$row->[4]};
|
||||
if ($row->[0] =~ /:/) {
|
||||
push(@{$c->{pool_v6}},
|
||||
[&ip6_pack($row->[0]), &ip6_pack($row->[1])]);
|
||||
} else {
|
||||
push(@{$c->{pool_v4}}, [$row->[2], $row->[3]]);
|
||||
|
||||
if (index($range, '.') > 0) {
|
||||
$country{$cc}->{pool_v4}->add_range($range);
|
||||
}
|
||||
if ($. % 4096 == 0) {
|
||||
|
||||
if (index($range, ':') > 0) {
|
||||
$country{$cc}->{pool_v6}->add_range($range);
|
||||
}
|
||||
|
||||
if (!$quiet && $. % 4096 == 0) {
|
||||
print STDERR "\r\e[2K$. entries";
|
||||
}
|
||||
}
|
||||
|
||||
print STDERR "\r\e[2K$. entries total\n";
|
||||
print STDERR "\r\e[2K$. entries total\n" unless ($quiet);
|
||||
|
||||
close($fh);
|
||||
|
||||
return \%country;
|
||||
}
|
||||
|
||||
@@ -66,7 +80,7 @@ sub dump
|
||||
{
|
||||
my $country = shift @_;
|
||||
|
||||
foreach my $iso_code (sort keys %$country) {
|
||||
foreach my $iso_code (sort keys %{$country}) {
|
||||
&dump_one($iso_code, $country->{$iso_code});
|
||||
}
|
||||
}
|
||||
@@ -74,68 +88,40 @@ sub dump
|
||||
sub dump_one
|
||||
{
|
||||
my($iso_code, $country) = @_;
|
||||
my($file, $fh_le, $fh_be);
|
||||
my @ranges;
|
||||
|
||||
printf "%5u IPv6 ranges for %s %s\n",
|
||||
scalar(@{$country->{pool_v6}}),
|
||||
$iso_code, $country->{name};
|
||||
@ranges = $country->{pool_v4}->list_range();
|
||||
|
||||
$file = "$target_dir/LE/".uc($iso_code).".iv6";
|
||||
if (!open($fh_le, "> $file")) {
|
||||
print STDERR "Error opening $file: $!\n";
|
||||
exit 1;
|
||||
}
|
||||
$file = "$target_dir/BE/".uc($iso_code).".iv6";
|
||||
if (!open($fh_be, "> $file")) {
|
||||
print STDERR "Error opening $file: $!\n";
|
||||
exit 1;
|
||||
}
|
||||
foreach my $range (@{$country->{pool_v6}}) {
|
||||
print $fh_be $range->[0], $range->[1];
|
||||
print $fh_le &ip6_swap($range->[0]), &ip6_swap($range->[1]);
|
||||
}
|
||||
close $fh_le;
|
||||
close $fh_be;
|
||||
writeCountry($iso_code, AF_INET, @ranges);
|
||||
|
||||
printf "%5u IPv4 ranges for %s %s\n",
|
||||
scalar(@{$country->{pool_v4}}),
|
||||
$iso_code, $country->{name};
|
||||
@ranges = $country->{pool_v6}->list_range();
|
||||
|
||||
$file = "$target_dir/LE/".uc($iso_code).".iv4";
|
||||
if (!open($fh_le, "> $file")) {
|
||||
print STDERR "Error opening $file: $!\n";
|
||||
exit 1;
|
||||
}
|
||||
$file = "$target_dir/BE/".uc($iso_code).".iv4";
|
||||
if (!open($fh_be, "> $file")) {
|
||||
print STDERR "Error opening $file: $!\n";
|
||||
exit 1;
|
||||
}
|
||||
foreach my $range (@{$country->{pool_v4}}) {
|
||||
print $fh_le pack("VV", $range->[0], $range->[1]);
|
||||
print $fh_be pack("NN", $range->[0], $range->[1]);
|
||||
}
|
||||
close $fh_le;
|
||||
close $fh_be;
|
||||
writeCountry($iso_code, AF_INET6, @ranges);
|
||||
}
|
||||
|
||||
sub ip6_pack
|
||||
sub writeCountry
|
||||
{
|
||||
my $addr = shift @_;
|
||||
$addr =~ s{::}{:!:};
|
||||
my @addr = split(/:/, $addr);
|
||||
my @e = (0) x 8;
|
||||
foreach (@addr) {
|
||||
if ($_ eq "!") {
|
||||
$_ = join(':', @e[0..(8-scalar(@addr))]);
|
||||
}
|
||||
}
|
||||
@addr = split(/:/, join(':', @addr));
|
||||
$_ = hex($_) foreach @addr;
|
||||
return pack("n*", @addr);
|
||||
}
|
||||
my ($iso_code, $family, @ranges) = @_;
|
||||
my $fh;
|
||||
|
||||
sub ip6_swap
|
||||
{
|
||||
return pack("V*", unpack("N*", shift @_));
|
||||
printf "%5u IPv%s ranges for %s\n",
|
||||
scalar(@ranges),
|
||||
($family == AF_INET ? '4' : '6'),
|
||||
$iso_code unless ($quiet);
|
||||
|
||||
my $file = "$target_dir/".uc($iso_code).".iv".($family == AF_INET ? '4' : '6');
|
||||
if (!open($fh, '>', $file)) {
|
||||
print STDERR "Error opening $file: $!\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
binmode($fh);
|
||||
|
||||
foreach my $range (@ranges) {
|
||||
my ($start, $end) = split('-', $range);
|
||||
$start = inet_pton($family, $start);
|
||||
$end = inet_pton($family, $end);
|
||||
print $fh $start, $end;
|
||||
}
|
||||
close $fh;
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@ xt_geoip_build \(em convert GeoIP.csv to packed format for xt_geoip
|
||||
.SH Syntax
|
||||
.PP
|
||||
\fI/usr/libexec/xt_geoip/\fP\fBxt_geoip_build\fP [\fB\-D\fP
|
||||
\fItarget_dir\fP] [\fIfile\fP...]
|
||||
\fItarget_dir\fP] [\fB\-i\fP \fIinput_file\fP]
|
||||
.SH Description
|
||||
.PP
|
||||
xt_geoip_build is used to build packed raw representations of the range
|
||||
@@ -16,20 +16,26 @@ required to be loaded into memory. The ranges in the packed database files are
|
||||
also ordered, as xt_geoip relies on this property for its bisection approach to
|
||||
work.
|
||||
.PP
|
||||
Input is processed from the listed files, or if none is given, from stdin.
|
||||
.PP
|
||||
Since the script is usually installed to the libexec directory of the
|
||||
xtables-addons package and this is outside $PATH (on purpose), invoking the
|
||||
script requires it to be called with a path.
|
||||
.PP Options
|
||||
.TP
|
||||
\fB\-D\fP \fItarget_dir\fP
|
||||
Specify a target directory into which the files are to be put.
|
||||
Specifies the target directory into which the files are to be put. Defaults to ".".
|
||||
.TP
|
||||
\fB\-i\fP \fIinput_file\fP
|
||||
Specifies the source location of the DBIP CSV file. Defaults to
|
||||
"dbip-country-lite.csv". Use "-" to read from stdin.
|
||||
.TP
|
||||
\fB\-s\fP
|
||||
"System mode". Equivalent to \fB\-D /usr/share/xt_geoip\fP.
|
||||
.SH Application
|
||||
.PP
|
||||
Shell commands to build the databases and put them to where they are expected:
|
||||
Shell commands to build the databases and put them to where they are expected
|
||||
(usually run as root):
|
||||
.PP
|
||||
xt_geoip_build \-D /usr/share/xt_geoip
|
||||
xt_geoip_build \-s
|
||||
.SH See also
|
||||
.PP
|
||||
xt_geoip_dl(1)
|
||||
|
@@ -1,8 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
rm -f GeoIPv6.csv GeoIPv6.csv.gz GeoIPCountryCSV.zip GeoIPCountryWhois.csv;
|
||||
wget \
|
||||
http://geolite.maxmind.com/download/geoip/database/GeoIPv6.csv.gz \
|
||||
http://geolite.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip;
|
||||
gzip -d GeoIPv6.csv.gz;
|
||||
unzip GeoIPCountryCSV.zip;
|
||||
timestamp=$(date "+%Y-%m")
|
||||
wget -q "https://download.db-ip.com/free/dbip-country-lite-$timestamp.csv.gz" -O- | \
|
||||
gzip -cd >dbip-country-lite.csv
|
||||
|
95
geoip/xt_geoip_fetch
Executable file
95
geoip/xt_geoip_fetch
Executable file
@@ -0,0 +1,95 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# Utility to query GeoIP database
|
||||
# Copyright Philip Prindeville, 2018
|
||||
#
|
||||
use Getopt::Long;
|
||||
use Socket qw(AF_INET AF_INET6 inet_ntop);
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
sub AF_INET_SIZE() { 4 }
|
||||
sub AF_INET6_SIZE() { 16 }
|
||||
|
||||
my $target_dir = ".";
|
||||
my $ipv4 = 0;
|
||||
my $ipv6 = 0;
|
||||
|
||||
&Getopt::Long::Configure(qw(bundling));
|
||||
&GetOptions(
|
||||
"D=s" => \$target_dir,
|
||||
"4" => \$ipv4,
|
||||
"6" => \$ipv6,
|
||||
);
|
||||
|
||||
if (!-d $target_dir) {
|
||||
print STDERR "Target directory $target_dir does not exit.\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
# if neither specified, assume both
|
||||
if (! $ipv4 && ! $ipv6) {
|
||||
$ipv4 = $ipv6 = 1;
|
||||
}
|
||||
|
||||
foreach my $cc (@ARGV) {
|
||||
if ($cc !~ m/^([a-z]{2}|a[12]|o1)$/i) {
|
||||
print STDERR "Invalid country code '$cc'\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
my $file = $target_dir . '/' . uc($cc) . '.iv4';
|
||||
|
||||
if (! -f $file) {
|
||||
printf STDERR "Can't find data for country '$cc'\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
my ($contents, $buffer, $bytes, $fh);
|
||||
|
||||
if ($ipv4) {
|
||||
open($fh, '<', $file) || die "Couldn't open file for '$cc'\n";
|
||||
|
||||
binmode($fh);
|
||||
|
||||
while (($bytes = read($fh, $buffer, AF_INET_SIZE * 2)) == AF_INET_SIZE * 2) {
|
||||
my ($start, $end) = unpack('a4a4', $buffer);
|
||||
$start = inet_ntop(AF_INET, $start);
|
||||
$end = inet_ntop(AF_INET, $end);
|
||||
print $start, '-', $end, "\n";
|
||||
}
|
||||
close($fh);
|
||||
if (! defined $bytes) {
|
||||
printf STDERR "Error reading file for '$cc'\n";
|
||||
exit 1;
|
||||
} elsif ($bytes != 0) {
|
||||
printf STDERR "Short read on file for '$cc'\n";
|
||||
exit 1;
|
||||
}
|
||||
}
|
||||
|
||||
substr($file, -1) = '6';
|
||||
|
||||
if ($ipv6) {
|
||||
open($fh, '<', $file) || die "Couldn't open file for '$cc'\n";
|
||||
|
||||
binmode($fh);
|
||||
|
||||
while (($bytes = read($fh, $buffer, AF_INET6_SIZE * 2)) == AF_INET6_SIZE * 2) {
|
||||
my ($start, $end) = unpack('a16a16', $buffer);
|
||||
$start = inet_ntop(AF_INET6, $start);
|
||||
$end = inet_ntop(AF_INET6, $end);
|
||||
print $start, '-', $end, "\n";
|
||||
}
|
||||
close($fh);
|
||||
if (! defined $bytes) {
|
||||
printf STDERR "Error reading file for '$cc'\n";
|
||||
exit 1;
|
||||
} elsif ($bytes != 0) {
|
||||
printf STDERR "Short read on file for '$cc'\n";
|
||||
exit 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit 0;
|
35
geoip/xt_geoip_fetch.1
Normal file
35
geoip/xt_geoip_fetch.1
Normal file
@@ -0,0 +1,35 @@
|
||||
.TH xt_geoip_fetch 1 "2020-04-30" "xtables-addons" "xtables-addons"
|
||||
.SH Name
|
||||
.PP
|
||||
xt_geoip_fetch \(em dump a country database to stdout
|
||||
.SH Syntax
|
||||
.PP
|
||||
\fBxt_geoip_fetch\fP [\fB\-D\fP
|
||||
\fIdatabase_dir\fP] [\fB-4\fP] [\fB-6\fP] \fIcc\fP [ \fIcc\fP ... ]
|
||||
.SH Description
|
||||
.PP
|
||||
xt_geoip_fetch unpacks a country's IPv4 or IPv6 databases and dumps
|
||||
them to standard output as a sorted, non-overlaping list of ranges (which
|
||||
is how they're represented in the database) suitable for browsing or
|
||||
further processing.
|
||||
.PP Options
|
||||
.TP
|
||||
\fB\-D\fP \fIdatabase_dir\fP
|
||||
Specifies the directory into which the files have been put. Defaults to ".".
|
||||
.TP
|
||||
\fB-4\fP
|
||||
Specifies IPv4 data only.
|
||||
.TP
|
||||
\fB-6\fP
|
||||
Specifies IPv6 data only.
|
||||
.TP
|
||||
\fIcc\fP [ \fIcc\fP ... ]
|
||||
The ISO-3166 country code names of the desired countries' databases.
|
||||
.SH Application
|
||||
.PP
|
||||
Shell command to dump the list of Swiss IPv6 address ranges:
|
||||
.PP
|
||||
xt_geoip_fetch \-D /usr/share/xt_geoip \-6 ch
|
||||
.SH See also
|
||||
.PP
|
||||
xt_geoip_build(1)
|
3
mconfig
3
mconfig
@@ -8,8 +8,7 @@ build_DNETMAP=m
|
||||
build_ECHO=m
|
||||
build_IPMARK=m
|
||||
build_LOGMARK=m
|
||||
build_RAWNAT=m
|
||||
build_STEAL=m
|
||||
build_PROTO=m
|
||||
build_SYSRQ=m
|
||||
build_TARPIT=m
|
||||
build_condition=m
|
||||
|
@@ -1,83 +0,0 @@
|
||||
#!/usr/bin/perl -w
|
||||
|
||||
use HTTP::Request;
|
||||
use LWP::UserAgent;
|
||||
use strict;
|
||||
|
||||
&main(\@ARGV);
|
||||
|
||||
sub main
|
||||
{
|
||||
local *FH;
|
||||
|
||||
if (!-d "downloads") {
|
||||
if (!mkdir("downloads")) {
|
||||
die "Could not create downloads/ directory";
|
||||
}
|
||||
}
|
||||
|
||||
open(FH, "<sources");
|
||||
while (defined($_ = <FH>)) {
|
||||
chomp $_;
|
||||
$_ =~ s/#.*//gs;
|
||||
$_ =~ s/^\s+|\s+$//gs;
|
||||
if (length($_) == 0) {
|
||||
next;
|
||||
}
|
||||
&process_index($_);
|
||||
}
|
||||
|
||||
close FH;
|
||||
}
|
||||
|
||||
sub process_index
|
||||
{
|
||||
my $top = shift @_;
|
||||
my($agent, $res, $url);
|
||||
local *FH;
|
||||
|
||||
$agent = LWP::UserAgent->new();
|
||||
$agent->env_proxy();
|
||||
|
||||
$url = &slash_remove("$top/xa-index.txt");
|
||||
print " GET $url\n";
|
||||
$res = $agent->get($url);
|
||||
if (!$res->is_success()) {
|
||||
print STDERR " `-> ", $res->status_line(), "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
foreach my $ext (split(/\s+/, $res->content())) {
|
||||
my($ex_url, $ex_res);
|
||||
|
||||
$ex_url = &slash_remove("$top/$ext");
|
||||
print " GET $ex_url\n";
|
||||
|
||||
$ex_res = $agent->mirror($ex_url, "downloads/$ext");
|
||||
if ($ex_res->code() == 304) {
|
||||
# "Not modified" = up to date
|
||||
next;
|
||||
}
|
||||
if (!$ex_res->is_success()) {
|
||||
print STDERR " `-> ", $ex_res->status_line(), "\n";
|
||||
next;
|
||||
}
|
||||
|
||||
print " UNPACK downloads/$ext\n";
|
||||
system "tar", "-xjf", "downloads/$ext";
|
||||
}
|
||||
}
|
||||
|
||||
sub slash_remove
|
||||
{
|
||||
my $s = shift @_;
|
||||
$s =~ s{(\w+://)(.*)}{$1.&slash_remove2($2)}eg;
|
||||
return $s;
|
||||
}
|
||||
|
||||
sub slash_remove2
|
||||
{
|
||||
my $s = shift @_;
|
||||
$s =~ s{/+}{/}g;
|
||||
return $s;
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
.TH xtables-addons 8 "African Heat Edition" "" "v2.3 (2013-06-18)"
|
||||
.TH xtables-addons 8 "" "" "v3.11 (2020-09-06)"
|
||||
.SH Name
|
||||
Xtables-addons \(em additional extensions for iptables, ip6tables, etc.
|
||||
.SH Targets
|
||||
|
Reference in New Issue
Block a user