Compare commits

..

67 Commits

Author SHA1 Message Date
Jan Engelhardt
515dd81d8f doc: add xt_quota2 changelog items
Cherry-picked commit v2.4-1-gfb3e550.
2014-01-18 12:27:11 +01:00
Sam Liddicott
a2d22c427f xt_quota2: remove trailing junk which might have a digit in it
Cherry-pick commit v2.3-6-gbc2bcc3.

Signed-off-by: Sam Liddicott <sam@liddicott.com>
2014-01-18 12:21:49 +01:00
Sam Liddicott
7fcbbe7dee xt_quota2: fix 2 bugs when not in grow mode
Cherry-pick commit v2.3-5-gc6c70ab.

1. XT_QUOTA_NO_CHANGE should not alter quota to zero ever
2. XT_QUOTA_PACKET should not be set to zero based on skb->len

Signed-off-by: Sam Liddicott <sam@liddicott.com>
2014-01-18 12:21:48 +01:00
Jan Engelhardt
b78a309bcc Update .gitignore
Cherry-pick commit v2.3-4-ga0a8fbc.

Looks like GCOV is enabled somewhere.
2014-01-18 12:21:48 +01:00
Jan Engelhardt
c024c6b16e extensions: remove RAWSNAT/RAWDNAT
Cherry-picked commit v2.3-3-g9414a5d.

Remove unmaintained code.
2014-01-18 12:16:28 +01:00
Jan Engelhardt
19b15a5261 extensions: remove STEAL target
Cherry-picked commit v2.3-2-gf28cfff.

There is enough demo code in the "demos" branch.
2014-01-18 12:15:12 +01:00
Jan Engelhardt
df9d3c994e Merge branch 'maint' into gen1 2012-11-12 19:02:14 +01:00
Jan Engelhardt
bcdb7ed4e9 Update my email address
To ... none! Whatever is recent is in the git log.
2012-11-12 19:01:14 +01:00
Jan Engelhardt
8db01220fd Xtables-addons 1.47.1 2012-10-15 21:29:22 +02:00
Jan Engelhardt
95ff9a2de3 build: resolve compiler error
extensions/xt_psd.c:141:2: error: implicit declaration of function
'vmalloc' [-Werror=implicit-function-declaration]
2012-10-15 21:15:25 +02:00
Jan Engelhardt
2f1e094125 Xtables-addons 1.47 2012-10-15 20:03:02 +02:00
Jan Engelhardt
37b000182f xt_psd: replace vzalloc by vmalloc+memset
The lower support boundary is currently 2.6.32, but vzalloc is only
available since 2.6.37.
2012-10-15 20:02:43 +02:00
Jan Engelhardt
255a310536 Merge branch 'psd' 2012-09-18 07:33:00 +02:00
Florian Westphal
3a6e73e986 xt_psd: add IPv6 support
Because most users will probably only use IPv4 psd, allocate most of the
state6 storage when the first IPv6 psd rule is added, and not at module
load time via .bss.
2012-09-18 03:33:37 +02:00
Florian Westphal
0a97126f5b xt_psd: move IPv4 state locking responsibility to caller
The former psd_match function is now < 72 lines.
2012-09-18 02:53:02 +02:00
Florian Westphal
2ba833fe47 xt_psd: move L4 header fetching into helper
Also start splitting psd_match into two functions, one to do initial
sanity checking and header retrieval, one to do the actual work.
2012-09-18 02:47:30 +02:00
Florian Westphal
77240e0918 xt_psd: use tcph->dest directly
This allows us to move more code away from the main match function.
2012-09-18 02:45:17 +02:00
Florian Westphal
651e60f8d7 xt_psd: move table cleanup into helper 2012-09-18 02:43:04 +02:00
Florian Westphal
54ac2a899a xt_psd: split struct host into generic and AF-dependent structure 2012-09-18 02:42:22 +02:00
Florian Westphal
61d2be172d xt_psd: remove unneeded variables, make hash unsigned
- dest port and dest address were only written, never read
- struct inaddr isn't needed either, just look at iph->saddr
2012-09-18 02:41:15 +02:00
Florian Westphal
093f3b0a97 xt_psd: move match functionality to helpers
Reduce line count and to allow code reuse when IPv6 support will be
introduced.
2012-09-17 04:44:29 +02:00
Florian Westphal
57d25f22f1 xt_psd: avoid if (c=h) do {..} while (c = c->next)
It is aquivalent to c=h; while (c) { ..; c = c->next; }
which is a bit easier to read.
2012-09-17 04:42:56 +02:00
Florian Westphal
2f18ab31ec xt_psd: move parts of main match function to helpers
The match function is way too large, start to split this into smaller
chunks.
2012-09-17 00:02:49 +02:00
Florian Westphal
12d0a8702c xt_psd: consider protocol when searching port list
If we saw a TCP packet on port X, and we receive a UDP packet from the
same host to port X, we counted this as "port X", and did not see this
as a new packet.

Change compare to also consider protocol number and move it to a helper
to de-bloat the overlay large match function.

This change makes psd more aggressive with mixed TCP/UDP traffic.
2012-09-17 00:02:45 +02:00
Jan Engelhardt
35ce1adf5e Xtables-addons 1.46 2012-08-23 15:54:21 +02:00
Jan Engelhardt
e5fe0b9c14 doc: update xt_SYSRQ.man to reflect that the full IPv6 address is needed
xt_SYSRQ uses NIP6_FMT, so requires the expanded form for the digest.

Reported-by: Jan Krcmar <honza801@gmail.com>
2012-08-23 15:27:23 +02:00
Arif Hossain
cd7fc84b29 build: remove extraneous closing bracket in configure.ac
Now autogen.sh will work without complaints.
2012-08-02 17:49:40 +02:00
Josh Hunt
4ff5a8fbf6 TARPIT: fix memory leak when tarpit_generic() fails
Currently tarpit_generic() just returns on failure, but this does not
free nskb.

Signed-off-by: Josh Hunt <johunt@akamai.com>
2012-08-02 17:48:05 +02:00
Florian Westphal
37e3a543a9 extensions: fix ipv6_find_hdr upstream change fallout
Upstream commit v3.5-rc1~109^2~138^2~4 ("netfilter: ip6_tables: add
flags parameter to ipv6_find_hdr()") changed the offset parameter of
ipv6_find_hdr() to be an input-output value. Moreover, if it is
non-zero, it MUST point to a valid IPv6 header embedded in the
packet.
2012-07-21 15:42:02 +02:00
Jan Engelhardt
5f6cbbc663 Xtables-addons 1.45 2012-07-16 05:39:32 +02:00
Jan Engelhardt
a2676585da build: avoid use of unexported functions
Fixes: "WARNING 'ipv6_find_hdr' [xt_TARPIT.ko] not found" in
<= linux-2.6.37.
2012-07-16 05:36:41 +02:00
Jan Engelhardt
4a8aab6aed fix: "WARNING 'xtnu_ipv6_find_hdr' [.ko] not found" 2012-07-16 05:34:24 +02:00
Jan Engelhardt
dec7d7fc4d Xtables-addons 1.44 2012-07-15 13:58:51 +02:00
Jan Engelhardt
5c615a3c73 build: do not attempt to build IPv6 parts if CONFIG_IP6_NF_IPTABLES=n
Checking for IPV6 is not sufficient, use IP6_NF_IPTABLES instead.
2012-07-14 23:19:16 +02:00
Jan Engelhardt
0c1375414d build: do not attempt to build IPv6 parts if CONFIG_IPV6=n 2012-07-14 22:55:39 +02:00
Jan Engelhardt
7e5a8b0501 geoip: remove outdated instructions in xt_geoip_build
The manpage contains the authoritative description of options
currently supported.
2012-07-14 02:17:38 +02:00
Jan Engelhardt
cb8050172a SYSRQ: fix double target initialization at module load 2012-07-11 01:42:39 +02:00
Jan Engelhardt
5be4ac8b2b Merge branch 'tarpit6' 2012-07-09 19:07:26 +02:00
Jan Engelhardt
8d5b7c5b7d doc: changelog entry for IPv6 TARPIT 2012-07-09 19:07:24 +02:00
Jan Engelhardt
f9aca7621c compat_xtables: avoid compile abort on <= 2.6.37 2012-07-09 19:06:22 +02:00
Josh Hunt
af940bcbae TARPIT: enable IPv6 userspace support
Signed-off-by: Josh Hunt <johunt@akamai.com>
2012-07-09 18:57:41 +02:00
Josh Hunt
06b82c649d TARPIT: resolve build errors with newer kernels
Adds fragment offset arg to ipv6_skip_exthdr() and also removes usage
of ipv6_addr_copy() in favor or direct assignment.

Signed-off-by: Josh Hunt <johunt@akamai.com>
2012-07-09 18:55:12 +02:00
Jan Engelhardt
e5093b61cd compat_xtables: add xtnu_ipv6_skip_exthdr 2012-07-09 18:54:22 +02:00
Josh Hunt
7cd01e0b14 TARPIT: add IPv6 support
This adds IPv6 support for the tarpit target. It performs the same
functionality as the v4 version, but with IPv6 connections.

Signed-off-by: Josh Hunt <johunt@akamai.com>
2012-07-08 21:22:22 +02:00
Josh Hunt
4eb97c7a01 TARPIT: make tarpit code generic
Creates a generic function to perform the tcp header manipulation in.
Done in preparation for IPv6 support. This allows us to share code
between v4 and v6 processing.

Signed-off-by: Josh Hunt <johunt@akamai.com>
2012-07-08 20:54:35 +02:00
Josh Hunt
48fbc6783e TARPIT: move XTTARPIT_RESET to its own function
Moves XTTARPIT_RESET into its own function.

Signed-off-by: Josh Hunt <johunt@akamai.com>
2012-07-08 20:51:46 +02:00
Josh Hunt
a9f383daf8 TARPIT: move XTTARPIT_HONEYPOT mode into its own function
Moves XTTARPIT_HONEYPOT into its own function.

Signed-off-by: Josh Hunt <johunt@akamai.com>
2012-07-08 20:51:05 +02:00
Josh Hunt
cbe58f55d0 TARPIT: move XTTARPIT_TARPIT mode processing to its own function
Moves the XTTARPIT_TARPIT mode processing to its own function.

Signed-off-by: Josh Hunt <johunt@akamai.com>
2012-07-08 20:51:00 +02:00
Jan Engelhardt
d11218815f TARPIT: mark oldtcphdr const 2012-07-08 20:51:00 +02:00
Kevin Locke
911d3d146a build: include <net/ip6_checksum.h> for csum_ipv6_magic
xt_ECHO fails to build on PPC because csum_ipv6_magic is declared in
<net/ip6_checksum.h>, which is not implicitly included from other
headers on PPC causing build failures due to this function being
undefined. So, include this header explicitly.

Note:  Same cause as <http://bugzilla.netfilter.org/show_bug.cgi?id=307>.
2012-07-03 22:53:57 +02:00
Jan Engelhardt
e2ecff2071 Xtables-addons 1.43 2012-06-30 19:46:21 +02:00
Jan Engelhardt
b2bcedd1ef build: support for Linux 3.5 2012-06-30 18:38:49 +02:00
Jan Engelhardt
36c349054e build: do not fail if AM_PROG_AR is not known 2012-06-30 15:44:44 +02:00
Jan Engelhardt
95da880d39 build: remove empty warning message 2012-06-21 19:13:13 +02:00
Jan Engelhardt
3be26a731b build: add missing include for xt_DNETMAP
xt_DNETMAP.c: In function 'dnetmap_tg_proc_write':
xt_DNETMAP.c:703:3: error: implicit declaration of function 'in4_pton'
[-Werror=implicit-function-declaration]
2012-06-15 15:48:42 +02:00
Jan Engelhardt
38db58adc1 build: automake 1.12 wants me to use AM_PROG_AR 2012-06-15 15:24:29 +02:00
Jan Engelhardt
0f302b7b2f Merge branch 'psd_cleanups' of git://git.breakpoint.cc/fw/xtables-addons 2012-06-15 15:18:57 +02:00
Florian Westphal
d66d07d01d psd: move defines to user/kernelspace part where possible
Some of these defines have no meaning in userspace, so there
is no need to make those available.
2012-06-15 15:17:30 +02:00
Florian Westphal
3736a265d8 psd: reduce size of struct host
We can use u16, saving 8 bytes total (weight cannot exceed
PSD_MAX_RATE, 10000). Also re-format comments & struct initializers.

No functional changes.
2012-06-15 15:17:21 +02:00
Jan Engelhardt
5b2649b1a2 psd: re-format comments 2012-06-15 15:16:31 +02:00
Florian Westphal
f6b8767228 psd: add basic validation of userspace matchinfo data
psd multiplies weight_thresh by HZ, so it could overflow.

Userspace libxt_psd refuses values exceeding PSD_MAX_RATE, so check
that on kernel side, too.

Also, setting 0 weight for both privileged and highports will cause
psd to never match at all.

Reject 0 weight threshold, too because it makes no sense (triggers
match for every initial packet).
2012-06-15 15:11:32 +02:00
Florian Westphal
ac58f2e94b psd: rip out scanlogd leftovers
scanlogd remembers tcp flags and uses the *_CHANGING values in its
logger function to determine the best log format to use (e.g. TTL is
not logged if HF_TTL_CHANGING was set, as TTL values were different).

As psd does not log at all, we do not need track this.

Also get rid of bogus/misleading comments.
2012-06-15 15:09:26 +02:00
Jan Engelhardt
7cc774641a all: remove trailing squatspaces 2012-06-10 22:31:10 +02:00
Marek Kierdelewicz
492236f931 DNETMAP version 2
- new type: static binding
- new persistent flag option for prefix
- add extra information in /proc/net/xt_DNETMAP/prefix_stat that
  includes the count of static bindings and persistent flag
- add proc interface write support (add/del/flush binding)
- updated manual
2012-06-10 22:27:28 +02:00
Jan Engelhardt
1e8da7c31c build: update installation requirements
Versions prior to 2.6.32 are not tested anymore due to make 3.82 being
troubled with an old ambiguous Makefile syntax.
2012-04-21 02:45:10 +02:00
Jan Engelhardt
3f1202c211 build: limit xt_ECHO to kernel 3.x
(Would also work on 2.6.39, but eh.)
2012-04-21 02:44:51 +02:00
Florian Westphal
759546f8d0 xt_psd: avoid crash due to curr->next corruption
curr->ports[] is of size SCAN_MAX_COUNT - 1, so under certain
conditions we wrote past end of array, corrupting ->next pointer
of the adjacent host entry.

Reported-and-tested-by: Serge Leschinsky <serge.leschinsky@gmail.com>
2012-04-18 14:30:22 +02:00
63 changed files with 1459 additions and 1686 deletions

1
.gitignore vendored
View File

@@ -1,3 +1,4 @@
*.gcno
*.la
*.lo
*.loT

View File

@@ -14,7 +14,7 @@ Supported configurations for this release
* iptables >= 1.4.5
* kernel-source >= 2.6.29
* kernel-devel >= 2.6.32
with prepared build/output directory
- CONFIG_NF_CONNTRACK or CONFIG_IP_NF_CONNTRACK
- CONFIG_NF_CONNTRACK_MARK or CONFIG_IP_NF_CONNTRACK_MARK

View File

@@ -1,4 +1,4 @@
AC_INIT([xtables-addons], [1.42])
AC_INIT([xtables-addons], [1.47.1])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])
@@ -6,6 +6,7 @@ AC_PROG_INSTALL
AM_INIT_AUTOMAKE([1.10b -Wall foreign subdir-objects])
AC_PROG_CC
AM_PROG_CC_C_O
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
AC_DISABLE_STATIC
AC_PROG_LIBTOOL
@@ -30,7 +31,7 @@ xtlibdir="$(pkg-config --variable=xtlibdir xtables)"
AC_ARG_WITH([xtlibdir],
AS_HELP_STRING([--with-xtlibdir=PATH],
[Path where to install Xtables extensions [[autodetect]]]]),
[Path where to install Xtables extensions [[autodetect]]]),
[xtlibdir="$withval"])
AC_MSG_CHECKING([Xtables module directory])
AC_MSG_RESULT([$xtlibdir])
@@ -62,8 +63,8 @@ if test -n "$kbuilddir"; 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 4; then
echo "WARNING: You are trying a newer kernel. Results may vary. :-)";
if test "$kmajor" -gt 3 -o "$kmajor" -eq 3 -a "$kminor" -gt 6; then
echo "WARNING: That kernel version is not officially supported.";
elif test "$kmajor" -eq 3; then
:;
elif test "$kmajor" -eq 2 -a "$kminor" -eq 6 -a "$kmicro" -ge 32; then

View File

@@ -1,6 +1,106 @@
HEAD
====
Changes
- remove unmaintained RAWSNAT/RAWDNAT code
Fixes:
- xt_quota2: --no-change should not alter quota to zero ever
- xt_quota2: --packet should not be set to zero based on skb->len
v2.3 (2013-06-18)
=================
Enhancements:
- Support for Linux 3.10
Fixes:
- xt_DNETMAP, xt_condition, xt_quota2: resolve compile error when
CONFIG_UIDGID_STRICT_TYPE_CHECKS=y
- xt_RAWNAT: ensure correct operation in the presence of IPv4 options
- xt_geoip: do not throw a warnings when country database is size 0
- xt_quota2: print "!" at the correct position during iptables-save
Changes:
- Make print (iptables -L) output the same as save (-S)
v2.2 (2013-03-31)
=================
Enhancements:
- Support for Linux 3.9
- iptaccount: fix entire program being erroneously optimized away on PPC
v2.1 (2012-11-27)
=================
Fixes:
- DNETMAP: fix compile error with Linux 3.7
Enhancements:
- Support for Linux 3.8
v2.0 (2012-11-12)
=================
Changes:
- remove support for Linux 2.6.173.6
- remove xt_TEE (this is available upstream since 2.6.35)
- remove xt_CHECKSUM (this is available upstream since 2.6.36)
Enhancements:
- Support for Linux 3.7
If you want to use Xtables-addons with kernels older than 3.7,
use the addons 1.x series, which continues to be maintained for
the time being.
>>>>>>> fb3e550... doc: add xt_quota2 changelog items
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)

View File

@@ -11,15 +11,12 @@ obj-${build_CHECKSUM} += xt_CHECKSUM.o
obj-${build_DELUDE} += xt_DELUDE.o
obj-${build_DHCPMAC} += xt_DHCPMAC.o
obj-${build_DNETMAP} += xt_DNETMAP.o
ifeq (${VERSION},3)
obj-${build_ECHO} += xt_ECHO.o
endif
obj-${build_IPMARK} += xt_IPMARK.o
obj-${build_LOGMARK} += xt_LOGMARK.o
obj-${build_RAWNAT} += xt_RAWNAT.o iptable_rawpost.o
ifneq (${CONFIG_IPV6},)
obj-${build_RAWNAT} += ip6table_rawpost.o
endif
obj-${build_SYSRQ} += xt_SYSRQ.o
obj-${build_STEAL} += xt_STEAL.o
obj-${build_TARPIT} += xt_TARPIT.o
obj-${build_TEE} += xt_TEE.o
obj-${build_condition} += xt_condition.o

View File

@@ -9,8 +9,6 @@ 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_SYSRQ} += libxt_SYSRQ.so
obj-${build_TARPIT} += libxt_TARPIT.so
obj-${build_TEE} += libxt_TEE.so

View File

@@ -1,87 +0,0 @@
#ifndef XTA_COMPAT_RAWPOST_H
#define XTA_COMPAT_RAWPOST_H 1
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
typedef struct sk_buff sk_buff_t;
#else
typedef struct sk_buff *sk_buff_t;
#endif
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 21)
#define XT_TARGET_INIT(__name, __size) \
{ \
.target.u.user = { \
.target_size = XT_ALIGN(__size), \
.name = __name, \
}, \
}
#define IPT_ENTRY_INIT(__size) \
{ \
.target_offset = sizeof(struct ipt_entry), \
.next_offset = (__size), \
}
#define IPT_STANDARD_INIT(__verdict) \
{ \
.entry = IPT_ENTRY_INIT(sizeof(struct ipt_standard)), \
.target = XT_TARGET_INIT(IPT_STANDARD_TARGET, \
sizeof(struct xt_standard_target)), \
.target.verdict = -(__verdict) - 1, \
}
#define IPT_ERROR_INIT \
{ \
.entry = IPT_ENTRY_INIT(sizeof(struct ipt_error)), \
.target = XT_TARGET_INIT(IPT_ERROR_TARGET, \
sizeof(struct ipt_error_target)), \
.target.errorname = "ERROR", \
}
#define IP6T_ENTRY_INIT(__size) \
{ \
.target_offset = sizeof(struct ip6t_entry), \
.next_offset = (__size), \
}
#define IP6T_STANDARD_INIT(__verdict) \
{ \
.entry = IP6T_ENTRY_INIT(sizeof(struct ip6t_standard)), \
.target = XT_TARGET_INIT(IP6T_STANDARD_TARGET, \
sizeof(struct ip6t_standard_target)), \
.target.verdict = -(__verdict) - 1, \
}
#define IP6T_ERROR_INIT \
{ \
.entry = IP6T_ENTRY_INIT(sizeof(struct ip6t_error)), \
.target = XT_TARGET_INIT(IP6T_ERROR_TARGET, \
sizeof(struct ip6t_error_target)), \
.target.errorname = "ERROR", \
}
#endif /* 2.6.21 */
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 20)
# include <linux/netfilter_ipv6/ip6_tables.h>
/* Standard entry */
struct ip6t_standard
{
struct ip6t_entry entry;
struct ip6t_standard_target target;
};
struct ip6t_error_target
{
struct ip6t_entry_target target;
char errorname[IP6T_FUNCTION_MAXNAMELEN];
};
struct ip6t_error
{
struct ip6t_entry entry;
struct ip6t_error_target target;
};
#endif /* 2.6.20 */
#endif /* XTA_COMPAT_RAWPOST_H */

View File

@@ -1,6 +1,6 @@
/*
* API compat layer
* written by Jan Engelhardt <jengelh [at] medozas de>, 2008 - 2010
* written by Jan Engelhardt, 2008 - 2010
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License, either
@@ -16,14 +16,19 @@
#include <linux/version.h>
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter_ipv6/ip6_tables.h>
#include <linux/netfilter_arp.h>
#include <net/ip.h>
#include <net/ipv6.h>
#include <net/route.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
# include <linux/export.h>
#endif
#include "compat_skbuff.h"
#include "compat_xtnu.h"
#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
# define WITH_IPV6 1
#endif
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 22)
static int xtnu_match_run(const struct sk_buff *skb,
@@ -612,4 +617,22 @@ void *HX_memmem(const void *space, size_t spacesize,
}
EXPORT_SYMBOL_GPL(HX_memmem);
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0) && defined(WITH_IPV6)
int xtnu_ipv6_skip_exthdr(const struct sk_buff *skb, int start,
uint8_t *nexthdrp, __be16 *fragoffp)
{
return ipv6_skip_exthdr(skb, start, nexthdrp);
}
EXPORT_SYMBOL_GPL(xtnu_ipv6_skip_exthdr);
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0) && defined(WITH_IPV6)
int xtnu_ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
int target, unsigned short *fragoff, int *fragflg)
{
return ipv6_find_hdr(skb, offset, target, fragoff);
}
EXPORT_SYMBOL_GPL(xtnu_ipv6_find_hdr);
#endif
MODULE_LICENSE("GPL");

View File

@@ -96,6 +96,7 @@
# define nf_nat_ipv4_multi_range_compat nf_nat_multi_range_compat
# define nf_nat_ipv4_range nf_nat_range
# define NF_NAT_RANGE_MAP_IPS IP_NAT_RANGE_MAP_IPS
# define ipv6_skip_exthdr xtnu_ipv6_skip_exthdr
#endif
#if !defined(NIP6) && !defined(NIP6_FMT)
@@ -119,6 +120,10 @@
# define NIPQUAD_FMT "%u.%u.%u.%u"
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
# define ipv6_find_hdr xtnu_ipv6_find_hdr
#endif
#define ip_route_me_harder xtnu_ip_route_me_harder
#define skb_make_writable xtnu_skb_make_writable
#define xt_target xtnu_target

View File

@@ -162,6 +162,10 @@ extern void xtnu_csum_replace4(__u16 __bitwise *, __be32, __be32);
extern void xtnu_proto_csum_replace4(__u16 __bitwise *, struct sk_buff *,
__be32, __be32, bool);
extern int xtnu_skb_linearize(struct sk_buff *);
extern int xtnu_ipv6_skip_exthdr(const struct sk_buff *, int,
uint8_t *, __be16 *);
extern int xtnu_ipv6_find_hdr(const struct sk_buff *, unsigned int *,
int, unsigned short *, int *);
extern void *HX_memmem(const void *, size_t, const void *, size_t);

View File

@@ -1,107 +0,0 @@
/*
* rawpost table for ip6_tables
* written by Jan Engelhardt <jengelh [at] medozas de>, 2008 - 2009
* placed in the Public Domain
*/
#include <linux/module.h>
#include <linux/netfilter_ipv6/ip6_tables.h>
#include <net/ip.h>
#include "compat_xtables.h"
#include "compat_rawpost.h"
enum {
RAWPOST_VALID_HOOKS = 1 << NF_INET_POST_ROUTING,
};
static struct {
struct ip6t_replace repl;
struct ip6t_standard entries[1];
struct ip6t_error term;
} rawpost6_initial __initdata = {
.repl = {
.name = "rawpost",
.valid_hooks = RAWPOST_VALID_HOOKS,
.num_entries = 2,
.size = sizeof(struct ip6t_standard) +
sizeof(struct ip6t_error),
.hook_entry = {
[NF_INET_POST_ROUTING] = 0,
},
.underflow = {
[NF_INET_POST_ROUTING] = 0,
},
},
.entries = {
IP6T_STANDARD_INIT(NF_ACCEPT), /* POST_ROUTING */
},
.term = IP6T_ERROR_INIT, /* ERROR */
};
static struct xt_table *rawpost6_ptable;
static struct xt_table rawpost6_itable = {
.name = "rawpost",
.af = NFPROTO_IPV6,
.valid_hooks = RAWPOST_VALID_HOOKS,
.me = THIS_MODULE,
};
static unsigned int rawpost6_hook_fn(unsigned int hook, sk_buff_t *skb,
const struct net_device *in, const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
return ip6t_do_table(skb, hook, in, out, rawpost6_ptable);
#else
return ip6t_do_table(skb, hook, in, out, rawpost6_ptable, NULL);
#endif
}
static struct nf_hook_ops rawpost6_hook_ops __read_mostly = {
.hook = rawpost6_hook_fn,
.pf = NFPROTO_IPV6,
.hooknum = NF_INET_POST_ROUTING,
.priority = NF_IP6_PRI_LAST,
.owner = THIS_MODULE,
};
static int __init rawpost6_table_init(void)
{
int ret;
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 29)
rwlock_init(&rawpost6_itable.lock);
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
rawpost6_ptable = ip6t_register_table(&init_net, &rawpost6_itable,
&rawpost6_initial.repl);
if (IS_ERR(rawpost6_ptable))
return PTR_ERR(rawpost6_ptable);
#else
ret = ip6t_register_table(&rawpost6_itable, &rawpost6_initial.repl);
if (ret < 0)
return ret;
rawpost6_ptable = &rawpost6_itable;
#endif
ret = nf_register_hook(&rawpost6_hook_ops);
if (ret < 0)
goto out;
return ret;
out:
ip6t_unregister_table(rawpost6_ptable);
return ret;
}
static void __exit rawpost6_table_exit(void)
{
nf_unregister_hook(&rawpost6_hook_ops);
ip6t_unregister_table(rawpost6_ptable);
}
module_init(rawpost6_table_init);
module_exit(rawpost6_table_exit);
MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>");
MODULE_LICENSE("GPL");

View File

@@ -1,109 +0,0 @@
/*
* rawpost table for ip_tables
* written by Jan Engelhardt <jengelh [at] medozas de>, 2008 - 2009
* placed in the Public Domain
*/
#include <linux/module.h>
#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/version.h>
#include <net/ip.h>
#include "compat_xtables.h"
#include "compat_rawpost.h"
enum {
RAWPOST_VALID_HOOKS = 1 << NF_INET_POST_ROUTING,
};
static struct {
struct ipt_replace repl;
struct ipt_standard entries[1];
struct ipt_error term;
} rawpost4_initial __initdata = {
.repl = {
.name = "rawpost",
.valid_hooks = RAWPOST_VALID_HOOKS,
.num_entries = 2,
.size = sizeof(struct ipt_standard) +
sizeof(struct ipt_error),
.hook_entry = {
[NF_INET_POST_ROUTING] = 0,
},
.underflow = {
[NF_INET_POST_ROUTING] = 0,
},
},
.entries = {
IPT_STANDARD_INIT(NF_ACCEPT), /* POST_ROUTING */
},
.term = IPT_ERROR_INIT, /* ERROR */
};
static struct xt_table *rawpost4_ptable;
static struct xt_table rawpost4_itable = {
.name = "rawpost",
.af = NFPROTO_IPV4,
.valid_hooks = RAWPOST_VALID_HOOKS,
.me = THIS_MODULE,
};
static unsigned int rawpost4_hook_fn(unsigned int hook, sk_buff_t *skb,
const struct net_device *in, const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
return ipt_do_table(skb, hook, in, out, rawpost4_ptable);
#else
return ipt_do_table(skb, hook, in, out, rawpost4_ptable, NULL);
#endif
}
static struct nf_hook_ops rawpost4_hook_ops __read_mostly = {
.hook = rawpost4_hook_fn,
.pf = NFPROTO_IPV4,
.hooknum = NF_INET_POST_ROUTING,
.priority = NF_IP_PRI_LAST,
.owner = THIS_MODULE,
};
static int __init rawpost4_table_init(void)
{
int ret;
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 29)
rwlock_init(&rawpost4_itable.lock);
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
rawpost4_ptable = ipt_register_table(&init_net, &rawpost4_itable,
&rawpost4_initial.repl);
if (IS_ERR(rawpost4_ptable))
return PTR_ERR(rawpost4_ptable);
#else
ret = ipt_register_table(&rawpost4_itable, &rawpost4_initial.repl);
if (ret < 0)
return ret;
rawpost4_ptable = &rawpost4_itable;
#endif
ret = nf_register_hook(&rawpost4_hook_ops);
if (ret < 0)
goto out;
return ret;
out:
ipt_unregister_table(rawpost4_ptable);
return ret;
}
static void __exit rawpost4_table_exit(void)
{
nf_unregister_hook(&rawpost4_hook_ops);
ipt_unregister_table(rawpost4_ptable);
}
module_init(rawpost4_table_init);
module_exit(rawpost4_table_exit);
MODULE_DESCRIPTION("Xtables: rawpost table for use with RAWNAT");
MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>");
MODULE_LICENSE("GPL");

View File

@@ -1,6 +1,6 @@
/*
* "CHAOS" target extension for iptables
* Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2006 - 2008
* Copyright © Jan Engelhardt, 2006 - 2008
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License; either

View File

@@ -17,5 +17,5 @@ connections than they can.
The randomness factor of not replying vs. replying can be set during load-time
of the xt_CHAOS module or during runtime in /sys/modules/xt_CHAOS/parameters.
.PP
See http://jengelh.medozas.de/projects/chaostables/ for more information
See http://inai.de/projects/chaostables/ for more information
about CHAOS, DELUDE and lscan.

View File

@@ -1,6 +1,6 @@
/*
* "DELUDE" target extension for iptables
* Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2006 - 2008
* Copyright © Jan Engelhardt, 2006 - 2008
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License; either

View File

@@ -1,6 +1,6 @@
/*
* "DHCPMAC" target extension for iptables
* Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2008
* Copyright © Jan Engelhardt, 2008
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License; either

View File

@@ -20,6 +20,8 @@ static const struct option DNETMAP_opts[] = {
{"prefix", 1, NULL, 'p'},
{"reuse", 0, NULL, 'r'},
{"ttl", 1, NULL, 't'},
{"static", 0, NULL, 's'},
{"persistent", 0, NULL, 'e'},
{.name = NULL}
};
@@ -33,9 +35,14 @@ static void DNETMAP_help(void)
" --%s seconds\n"
" Regenerate bindings ttl value to seconds. If negative value is specified,\n"
" bindings ttl is kept unchanged. If not specified then default ttl value (600s)\n"
" is used.\n\n",
DNETMAP_opts[0].name, DNETMAP_opts[1].name,
DNETMAP_opts[2].name);
" is used\n"
" --%s\n"
" Match only static entries for this rule. Dynamic entries won't be created.\n"
" --%s\n"
" Set prefix persistent. It won't be removed after deleting last iptables rule.\n\n",
DNETMAP_opts[0].name, DNETMAP_opts[1].name,
DNETMAP_opts[2].name, DNETMAP_opts[3].name,
DNETMAP_opts[4].name);
}
static u_int32_t bits2netmask(int bits)
@@ -151,6 +158,20 @@ static int DNETMAP_parse(int c, char **argv, int invert, unsigned int *flags,
*flags |= XT_DNETMAP_REUSE;
tginfo->flags |= XT_DNETMAP_REUSE;
return 1;
case 's':
xtables_param_act(XTF_ONLY_ONCE, MODULENAME, "--static",
*flags & XT_DNETMAP_STATIC);
xtables_param_act(XTF_NO_INVERT, MODULENAME, "--static", invert);
*flags |= XT_DNETMAP_STATIC;
tginfo->flags |= XT_DNETMAP_STATIC;
return 1;
case 'e':
xtables_param_act(XTF_ONLY_ONCE, MODULENAME, "--persistent",
*flags & XT_DNETMAP_PERSISTENT);
xtables_param_act(XTF_NO_INVERT, MODULENAME, "--persistent", invert);
*flags |= XT_DNETMAP_PERSISTENT;
tginfo->flags |= XT_DNETMAP_PERSISTENT;
return 1;
case 't':
xtables_param_act(XTF_ONLY_ONCE, MODULENAME, "--ttl",
*flags & XT_DNETMAP_TTL);
@@ -198,7 +219,15 @@ static void DNETMAP_print(const void *ip, const struct xt_entry_target *target,
else
printf("any");
printf(" reuse %i", (*flags & XT_DNETMAP_REUSE) > 0);
if (*flags & XT_DNETMAP_REUSE)
printf(" reuse");
if (*flags & XT_DNETMAP_STATIC)
printf(" static");
if (*flags & XT_DNETMAP_PERSISTENT)
printf(" persistent");
if (*flags & XT_DNETMAP_TTL)
printf(" ttl %i", tginfo->ttl);
else
@@ -214,7 +243,15 @@ static void DNETMAP_save(const void *ip, const struct xt_entry_target *target)
printf(" --%s ", DNETMAP_opts[0].name);
DNETMAP_print_addr(ip, target, 0);
}
printf(" --reuse %i ", *flags & XT_DNETMAP_REUSE);
if (*flags & XT_DNETMAP_REUSE)
printf(" --reuse ");
if (*flags & XT_DNETMAP_STATIC)
printf(" --static ");
if (*flags & XT_DNETMAP_PERSISTENT)
printf(" --persistent ");
/* ommited because default value can change as kernel mod param */
if (*flags & XT_DNETMAP_TTL)

View File

@@ -18,6 +18,17 @@ Network subnet to map to. If not specified, all existing prefixes are used.
\fB\-\-reuse\fR
Reuse entry for given prenat-ip from any prefix despite bindings ttl < 0.
.TP
\fB\-\-persistent\fR
Set prefix persistent. It won't be removed after deleting last iptables rule.
Option is effective only in the first rule for a given prefix. If you
need to change persistency for existing prefix, please use proc interface
described below.
.TP
\fB\-\-static\fR
Don't create dynamic mappings using this rule. Use static mappings only. Note
that you need to create static mappings via proc interface for this rule with
this option to have any effect.
.TP
\fB\-\-ttl\fR \fIseconds\fR
Regenerate bindings ttl value to \fIseconds\fR. If negative value is specified,
bindings ttl is kept unchanged. If not specified then default ttl value (600s)
@@ -30,16 +41,45 @@ Module creates following entries for each new specified subnet:
\fB/proc/net/xt_DNETMAP/\fR\fIsubnet\fR\fB_\fR\fImask\fR
Contains binding table for subnet/mask. Each line contains \fBprenat-ip\fR,
\fBpostnat-ip\fR,\fBttl\fR (seconds till entry times out), \fBlasthit\fR (last
entry hit in seconds relative to system boot time).
entry hit in seconds relative to system boot time). Please note that \fBttl\fR
and \fBlasthit\fR entries contain \fBS\fR in case of static binding.
.TP
\fB/proc/net/xt_DNETMAP/\fR\fIsubnet\fR\fB_\fR\fImask\fR\fB_stat\fR
Contains statistics for given subnet/mask. Line contains contains three
Contains statistics for given subnet/mask. Line contains contains four
numerical values separated by spaces. First one is number of currently used
addresses (bindings with negative ttl excluded), second one is number of all
usable addresses in subnet and third one is mean \fBttl\fR value for all active
entries.
dynamic addresses (bindings with negative ttl excluded), second one is number
static assignments, third one is number of all usable addresses in subnet and
the fourth one is mean \fBttl\fR value for all active entries. If prefix has
persistent flag set it'll be noted as fifth entry.
.PP
Following write operations are supported via proc interface:
.TP
echo "+\fIprenatIP\fR:\fIpostnatIP\fR" > \fB/proc/net/xt_DNETMAP/subnet_mask\fR
Adds static binding between prenatIP nad postnatIP. If postnatIP is already
bound, previous binding will be timedout immediatelly. Static binding is never
timedout.
.TP
echo "-\fIIP\fR" > \fB/proc/net/xt_DNETMAP/subnet_mask\fR
Removes binding with \fIIP\fR as prenat or postnat address. If removed binding
is currently static, it'll make entry available for dynamic allocation.
.TP
echo "+persistent" > \fB/proc/net/xt_DNETMAP/subnet_mask\fR
Sets persistent flag for prefix. It's usefull if you don't want bindings to get
flushed when firewall is restarted. You can check if prefix is persistent by
printing \fB/proc/net/xt_DNETMAP/\fR\fIsubnet\fR\fB_\fR\fImask\fR\fB_stat\fR
contents.
.TP
echo "-persistent" > \fB/proc/net/xt_DNETMAP/subnet_mask\fR
Unsets persistent flag for prefix. In this mode prefix will be deleted if the
last iptables rule for that prefix is removed.
.TP
echo "flush" > \fB/proc/net/xt_DNETMAP/subnet_mask\fR
Flushes all bindings for specific prefix. All static entries are also flushed
and are available for dynamic bindings.
.PP
Note! Entries are removed if the last iptables rule for a specific prefix is
deleted unless there's persistent flag set.
.PP
Entries are removed if the last iptables rule for a specific subnet is deleted.
\fB* Logging\fR
@@ -88,4 +128,45 @@ specify \fB\-\-prefix\fR parameter in PREROUTING rule, because this way it DNATs
traffic to all active prefixes. You could specify prefix it you'd like to make
DNAT work for specific prefix only.
\fB4.\fR Map 192.168.0.0/24 to subnets 20.0.0.0/26 with static assignments only:
iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -j DNETMAP --prefix 20.0.0.0/26
--static
echo "+192.168.0.10:20.0.0.1" > /proc/net/xt_DNETMAP/20.0.0.0_26
.br
echo "+192.168.0.11:20.0.0.2" > /proc/net/xt_DNETMAP/20.0.0.0_26
.br
echo "+192.168.0.51:20.0.0.3" > /proc/net/xt_DNETMAP/20.0.0.0_26
This configuration will allow only preconfigured static bindings to work due to
\fBstatic\fR rule option. Without this flag dynamic bindings would be created
using non-static entries.
\fB5.\fR Persistent prefix:
iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -j DNETMAP --prefix 20.0.0.0/26
--persistent
.br
\fBor\fR
.br
iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -j DNETMAP --prefix 20.0.0.0/26
.br
echo "+persistent" > /proc/net/xt_DNETMAP/20.0.0.0_26
Now we can check persistent flag of the prefix:
.br
cat /proc/net/xt_DNETMAP/20.0.0.0_26
.br
0 0 64 0 \fBpersistent\fR
Flush iptables nat table and see that prefix is still in existence:
.br
iptables -F -t nat
.br
ls -l /proc/net/xt_DNETMAP
.br
-rw-r--r-- 1 root root 0 06-10 09:01 20.0.0.0_26
.br
-rw-r--r-- 1 root root 0 06-10 09:01 20.0.0.0_26_stat
.

View File

@@ -1,6 +1,6 @@
/*
* "ECHO" target extension for iptables
* Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2008
* Copyright © Jan Engelhardt, 2008
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License; either

View File

@@ -1,7 +1,7 @@
/*
* "IPMARK" target extension for iptables
* Copyright © Grzegorz Janoszka <Grzegorz.Janoszka@pro.onet.pl>, 2003
* Jan Engelhardt <jengelh [at] medozas de>, 2008
* Jan Engelhardt, 2008
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License; either

View File

@@ -1,6 +1,6 @@
/*
* "LOGMARK" target extension for iptables
* Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2008
* Copyright © Jan Engelhardt, 2008
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License; either

View File

@@ -1,189 +0,0 @@
/*
* "RAWNAT" target extension for iptables
* Copyright © Jan Engelhardt, 2008 - 2009
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License; either
* version 2 of the License, or any later version, as published by the
* Free Software Foundation.
*/
#include <netinet/in.h>
#include <getopt.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <xtables.h>
#include <linux/netfilter.h>
#include "xt_RAWNAT.h"
#include "compat_user.h"
enum {
FLAGS_TO = 1 << 0,
};
static const struct option rawdnat_tg_opts[] = {
{.name = "to-destination", .has_arg = true, .val = 't'},
{},
};
static void rawdnat_tg_help(void)
{
printf(
"RAWDNAT target options:\n"
" --to-destination addr[/mask] Address or network to map to\n"
);
}
static int
rawdnat_tg4_parse(int c, char **argv, int invert, unsigned int *flags,
const void *entry, struct xt_entry_target **target)
{
struct xt_rawnat_tginfo *info = (void *)(*target)->data;
struct in_addr *a;
unsigned int mask;
char *end;
switch (c) {
case 't':
info->mask = 32;
end = strchr(optarg, '/');
if (end != NULL) {
*end++ = '\0';
if (!xtables_strtoui(end, NULL, &mask, 0, 32))
xtables_param_act(XTF_BAD_VALUE, "RAWDNAT",
"--to-destination", optarg);
info->mask = mask;
}
a = xtables_numeric_to_ipaddr(optarg);
if (a == NULL)
xtables_param_act(XTF_BAD_VALUE, "RAWDNAT",
"--to-destination", optarg);
memcpy(&info->addr.in, a, sizeof(*a));
*flags |= FLAGS_TO;
return true;
}
return false;
}
static int
rawdnat_tg6_parse(int c, char **argv, int invert, unsigned int *flags,
const void *entry, struct xt_entry_target **target)
{
struct xt_rawnat_tginfo *info = (void *)(*target)->data;
struct in6_addr *a;
unsigned int mask;
char *end;
switch (c) {
case 't':
info->mask = 128;
end = strchr(optarg, '/');
if (end != NULL) {
*end++ = '\0';
if (!xtables_strtoui(end, NULL, &mask, 0, 128))
xtables_param_act(XTF_BAD_VALUE, "RAWDNAT",
"--to-destination", optarg);
info->mask = mask;
}
a = xtables_numeric_to_ip6addr(optarg);
if (a == NULL)
xtables_param_act(XTF_BAD_VALUE, "RAWDNAT",
"--to-destination", optarg);
memcpy(&info->addr.in6, a, sizeof(*a));
*flags |= FLAGS_TO;
return true;
}
return false;
}
static void rawdnat_tg_check(unsigned int flags)
{
if (!(flags & FLAGS_TO))
xtables_error(PARAMETER_PROBLEM, "RAWDNAT: "
"\"--to-destination\" is required.");
}
static void
rawdnat_tg4_print(const void *entry, const struct xt_entry_target *target,
int numeric)
{
const struct xt_rawnat_tginfo *info = (const void *)target->data;
if (!numeric && info->mask == 32)
printf(" to-destination %s ",
xtables_ipaddr_to_anyname(&info->addr.in));
else
printf(" to-destination %s/%u ",
xtables_ipaddr_to_numeric(&info->addr.in), info->mask);
}
static void
rawdnat_tg6_print(const void *entry, const struct xt_entry_target *target,
int numeric)
{
const struct xt_rawnat_tginfo *info = (const void *)target->data;
if (!numeric && info->mask == 128)
printf(" to-destination %s ",
xtables_ip6addr_to_anyname(&info->addr.in6));
else
printf(" to-destination %s/%u ",
xtables_ip6addr_to_numeric(&info->addr.in6), info->mask);
}
static void
rawdnat_tg4_save(const void *entry, const struct xt_entry_target *target)
{
const struct xt_rawnat_tginfo *info = (const void *)target->data;
printf(" --to-destination %s/%u ",
xtables_ipaddr_to_numeric(&info->addr.in),
info->mask);
}
static void
rawdnat_tg6_save(const void *entry, const struct xt_entry_target *target)
{
const struct xt_rawnat_tginfo *info = (const void *)target->data;
printf(" --to-destination %s/%u ",
xtables_ip6addr_to_numeric(&info->addr.in6),
info->mask);
}
static struct xtables_target rawdnat_tg_reg[] = {
{
.version = XTABLES_VERSION,
.name = "RAWDNAT",
.revision = 0,
.family = NFPROTO_IPV4,
.size = XT_ALIGN(sizeof(struct xt_rawnat_tginfo)),
.userspacesize = XT_ALIGN(sizeof(struct xt_rawnat_tginfo)),
.help = rawdnat_tg_help,
.parse = rawdnat_tg4_parse,
.final_check = rawdnat_tg_check,
.print = rawdnat_tg4_print,
.save = rawdnat_tg4_save,
.extra_opts = rawdnat_tg_opts,
},
{
.version = XTABLES_VERSION,
.name = "RAWDNAT",
.revision = 0,
.family = NFPROTO_IPV6,
.size = XT_ALIGN(sizeof(struct xt_rawnat_tginfo)),
.userspacesize = XT_ALIGN(sizeof(struct xt_rawnat_tginfo)),
.help = rawdnat_tg_help,
.parse = rawdnat_tg6_parse,
.final_check = rawdnat_tg_check,
.print = rawdnat_tg6_print,
.save = rawdnat_tg6_save,
.extra_opts = rawdnat_tg_opts,
},
};
static void _init(void)
{
xtables_register_targets(rawdnat_tg_reg,
sizeof(rawdnat_tg_reg) / sizeof(*rawdnat_tg_reg));
}

View File

@@ -1,10 +0,0 @@
The \fBRAWDNAT\fR target will rewrite the destination address in the IP header,
much like the \fBNETMAP\fR target.
.TP
\fB\-\-to\-destination\fR \fIaddr\fR[\fB/\fR\fImask\fR]
Network address to map to. The resulting address will be constructed the
following way: All 'one' bits in the \fImask\fR are filled in from the new
\fIaddress\fR. All bits that are zero in the mask are filled in from the
original address.
.PP
See the \fBRAWSNAT\fR help entry for examples and constraints.

View File

@@ -1,189 +0,0 @@
/*
* "RAWNAT" target extension for iptables
* Copyright © Jan Engelhardt, 2008 - 2009
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License; either
* version 2 of the License, or any later version, as published by the
* Free Software Foundation.
*/
#include <netinet/in.h>
#include <getopt.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <xtables.h>
#include <linux/netfilter.h>
#include "xt_RAWNAT.h"
#include "compat_user.h"
enum {
FLAGS_TO = 1 << 0,
};
static const struct option rawsnat_tg_opts[] = {
{.name = "to-source", .has_arg = true, .val = 't'},
{},
};
static void rawsnat_tg_help(void)
{
printf(
"RAWSNAT target options:\n"
" --to-source addr[/mask] Address or network to map to\n"
);
}
static int
rawsnat_tg4_parse(int c, char **argv, int invert, unsigned int *flags,
const void *entry, struct xt_entry_target **target)
{
struct xt_rawnat_tginfo *info = (void *)(*target)->data;
struct in_addr *a;
unsigned int mask;
char *end;
switch (c) {
case 't':
info->mask = 32;
end = strchr(optarg, '/');
if (end != NULL) {
*end++ = '\0';
if (!xtables_strtoui(end, NULL, &mask, 0, 32))
xtables_param_act(XTF_BAD_VALUE, "RAWSNAT",
"--to-source", optarg);
info->mask = mask;
}
a = xtables_numeric_to_ipaddr(optarg);
if (a == NULL)
xtables_param_act(XTF_BAD_VALUE, "RAWSNAT",
"--to-source", optarg);
memcpy(&info->addr.in, a, sizeof(*a));
*flags |= FLAGS_TO;
return true;
}
return false;
}
static int
rawsnat_tg6_parse(int c, char **argv, int invert, unsigned int *flags,
const void *entry, struct xt_entry_target **target)
{
struct xt_rawnat_tginfo *info = (void *)(*target)->data;
struct in6_addr *a;
unsigned int mask;
char *end;
switch (c) {
case 't':
info->mask = 128;
end = strchr(optarg, '/');
if (end != NULL) {
*end++ = '\0';
if (!xtables_strtoui(end, NULL, &mask, 0, 128))
xtables_param_act(XTF_BAD_VALUE, "RAWSNAT",
"--to-source", optarg);
info->mask = mask;
}
a = xtables_numeric_to_ip6addr(optarg);
if (a == NULL)
xtables_param_act(XTF_BAD_VALUE, "RAWSNAT",
"--to-source", optarg);
memcpy(&info->addr.in6, a, sizeof(*a));
*flags |= FLAGS_TO;
return true;
}
return false;
}
static void rawsnat_tg_check(unsigned int flags)
{
if (!(flags & FLAGS_TO))
xtables_error(PARAMETER_PROBLEM, "RAWSNAT: "
"\"--to-source\" is required.");
}
static void
rawsnat_tg4_print(const void *entry, const struct xt_entry_target *target,
int numeric)
{
const struct xt_rawnat_tginfo *info = (const void *)target->data;
if (!numeric && info->mask == 32)
printf(" to-source %s ",
xtables_ipaddr_to_anyname(&info->addr.in));
else
printf(" to-source %s/%u ",
xtables_ipaddr_to_numeric(&info->addr.in), info->mask);
}
static void
rawsnat_tg6_print(const void *entry, const struct xt_entry_target *target,
int numeric)
{
const struct xt_rawnat_tginfo *info = (const void *)target->data;
if (!numeric && info->mask == 128)
printf(" to-source %s ",
xtables_ip6addr_to_anyname(&info->addr.in6));
else
printf(" to-source %s/%u ",
xtables_ip6addr_to_numeric(&info->addr.in6), info->mask);
}
static void
rawsnat_tg4_save(const void *entry, const struct xt_entry_target *target)
{
const struct xt_rawnat_tginfo *info = (const void *)target->data;
printf(" --to-source %s/%u ",
xtables_ipaddr_to_numeric(&info->addr.in),
info->mask);
}
static void
rawsnat_tg6_save(const void *entry, const struct xt_entry_target *target)
{
const struct xt_rawnat_tginfo *info = (const void *)target->data;
printf(" --to-source %s/%u ",
xtables_ip6addr_to_numeric(&info->addr.in6),
info->mask);
}
static struct xtables_target rawsnat_tg_reg[] = {
{
.version = XTABLES_VERSION,
.name = "RAWSNAT",
.revision = 0,
.family = NFPROTO_IPV4,
.size = XT_ALIGN(sizeof(struct xt_rawnat_tginfo)),
.userspacesize = XT_ALIGN(sizeof(struct xt_rawnat_tginfo)),
.help = rawsnat_tg_help,
.parse = rawsnat_tg4_parse,
.final_check = rawsnat_tg_check,
.print = rawsnat_tg4_print,
.save = rawsnat_tg4_save,
.extra_opts = rawsnat_tg_opts,
},
{
.version = XTABLES_VERSION,
.name = "RAWSNAT",
.revision = 0,
.family = NFPROTO_IPV6,
.size = XT_ALIGN(sizeof(struct xt_rawnat_tginfo)),
.userspacesize = XT_ALIGN(sizeof(struct xt_rawnat_tginfo)),
.help = rawsnat_tg_help,
.parse = rawsnat_tg6_parse,
.final_check = rawsnat_tg_check,
.print = rawsnat_tg6_print,
.save = rawsnat_tg6_save,
.extra_opts = rawsnat_tg_opts,
},
};
static void _init(void)
{
xtables_register_targets(rawsnat_tg_reg,
sizeof(rawsnat_tg_reg) / sizeof(*rawsnat_tg_reg));
}

View File

@@ -1,38 +0,0 @@
The \fBRAWSNAT\fR and \fBRAWDNAT\fP targets provide stateless network address
translation.
.PP
The \fBRAWSNAT\fR target will rewrite the source address in the IP header, much
like the \fBNETMAP\fP target. \fBRAWSNAT\fP (and \fBRAWDNAT\fP) may only be
used in the \fBraw\fP or \fBrawpost\fP tables, but can be used in all chains,
which makes it possible to change the source address either when the packet
enters the machine or when it leaves it. The reason for this table constraint
is that RAWNAT must happen outside of connection tracking.
.TP
\fB\-\-to\-source\fR \fIaddr\fR[\fB/\fR\fImask\fR]
Network address to map to. The resulting address will be constructed the
following way: All 'one' bits in the \fImask\fR are filled in from the new
\fIaddress\fR. All bits that are zero in the mask are filled in from the
original address.
.PP
As an example, changing the destination for packets forwarded from an internal
LAN to the internet:
.IP
\-t raw \-A PREROUTING \-i lan0 \-d 212.201.100.135 \-j RAWDNAT \-\-to\-destination 199.181.132.250;
\-t rawpost \-A POSTROUTING \-o lan0 \-s 199.181.132.250 \-j RAWSNAT \-\-to\-source 212.201.100.135;
.PP
Note that changing addresses may influence the route selection! Specifically,
it statically NATs packets, not connections, like the normal DNAT/SNAT targets
would do. Also note that it can transform already-NATed connections \(em as
said, it is completely external to Netfilter's connection tracking/NAT.
.PP
If the machine itself generates packets that are to be rawnat'ed, you need a
rule in the OUTPUT chain instead, just like you would with the stateful NAT
targets.
.PP
It may be necessary that in doing so, you also need an extra RAWSNAT rule, to
override the automatic source address selection that the routing code does
before passing packets to iptables. If the connecting socket has not been
explicitly bound to an address, as is the common mode of operation, the address
that will be chosen is the primary address of the device through which the
packet would be routed with its initial destination address - the address as
seen before any RAWNAT takes place.

View File

@@ -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);
}

View File

@@ -1,2 +0,0 @@
Like the DROP target, but does not throw an error like DROP when used in the
\fBOUTPUT\fP chain.

View File

@@ -62,7 +62,7 @@ password="password"
seqno="$(date +%s)"
salt="$(dd bs=12 count=1 if=/dev/urandom 2>/dev/null |
openssl enc \-base64)"
ipaddr=10.10.25.7
ipaddr="2001:0db8:0000:0000:0000:ff00:0042:8329"
req="$sysrq_key,$seqno,$salt"
req="$req,$(echo \-n "$req,$ipaddr,$password" | sha1sum | cut \-c1\-40)"
@@ -75,8 +75,8 @@ sysrq key can be used at once, but bear in mind that, for example, a sync may
not complete before a subsequent reboot or poweroff.
.PP
An IPv4 address should have no leading zeros, an IPv6 address should
be in the form recommended by RFC 5952. The debug option will log the
correct form of the address.
be in the full expanded form (as shown above). The debug option will cause
output to be emitted in the same form.
.PP
The hashing scheme should be enough to prevent mis-use of SYSRQ in many
environments, but it is not perfect: take reasonable precautions to

View File

@@ -106,7 +106,7 @@ static void tarpit_tg_save(const void *ip,
static struct xtables_target tarpit_tg_reg = {
.version = XTABLES_VERSION,
.name = "TARPIT",
.family = NFPROTO_IPV4,
.family = NFPROTO_UNSPEC,
.size = XT_ALIGN(sizeof(struct xt_tarpit_tginfo)),
.userspacesize = XT_ALIGN(sizeof(struct xt_tarpit_tginfo)),
.help = tarpit_tg_help,

View File

@@ -2,7 +2,7 @@
* "condition" match extension for iptables
* Stephane Ouellette <ouellettes [at] videotron ca>, 2002-10-22
* Massimiliano Hofer <max [at] nucleus it>, 2006-05-15
* Jan Engelhardt <jengelh [at] medozas de>, 2008
* Jan Engelhardt, 2008
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License; either version 2

View File

@@ -1,6 +1,6 @@
/*
* "dhcpmac" match extension for iptables
* Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2008
* Copyright © Jan Engelhardt, 2008
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License; either

View File

@@ -100,7 +100,7 @@ static void fuzzy_mt_save(const void *ip, const struct xt_entry_match *match)
printf(" --upper-limit %u ", info->maximum_rate);
}
static struct xtables_match fuzzy_mt_reg = {
static struct xtables_match fuzzy_mt_reg = {
.name = "fuzzy",
.revision = 1,
.version = XTABLES_VERSION,

View File

@@ -2,7 +2,7 @@
* "geoip" match extension for iptables
* Copyright © Samuel Jean <peejix [at] people netfilter org>, 2004 - 2008
* Copyright © Nicolas Bouliane <acidfu [at] people netfilter org>, 2004 - 2008
* Jan Engelhardt <jengelh [at] medozas de>, 2008-2011
* Jan Engelhardt, 2008-2011
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License; either
@@ -100,7 +100,7 @@ geoip_get_subnets(const char *code, uint32_t *count, uint8_t nfproto)
close(fd);
return subnets;
}
static struct geoip_country_user *geoip_load_cc(const char *code,
unsigned short cc, uint8_t nfproto)
{

View File

@@ -78,7 +78,7 @@ static void gradm_mt_save(const void *ip, const struct xt_entry_match *match)
printf(" --enabled ");
}
static struct xtables_match gradm_mt_reg = {
static struct xtables_match gradm_mt_reg = {
.family = NFPROTO_UNSPEC,
.name = "gradm",
.version = XTABLES_VERSION,

View File

@@ -1,7 +1,7 @@
/*
* "ipp2p" match extension for iptables
* Eicke Friedrich/Klaus Degner <ipp2p@ipp2p.org>, 2005 - 2006
* Jan Engelhardt <jengelh [at] medozas de>, 2008 - 2009
* Jan Engelhardt, 2008 - 2009
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License; either

View File

@@ -36,7 +36,7 @@ Matches some WinMX packets. Considered as beta, use careful!
Matches Ares and AresLite packets. Use together with \-j DROP only.
.TP
\fB\-\-debug\fP
Prints some information about each hit into kernel logfile. May
Prints some information about each hit into kernel logfile. May
produce huge logfiles so beware!
.PP
Note that ipp2p may not (and often, does not) identify all packets that are

View File

@@ -1,6 +1,6 @@
/*
* LSCAN match extension for iptables
* Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2006 - 2009
* Copyright © Jan Engelhardt, 2006 - 2009
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License; either

View File

@@ -30,6 +30,8 @@
#include "xt_psd.h"
#include "compat_user.h"
#define SCAN_DELAY_THRESHOLD 300
/* Function which prints out usage message. */
static void psd_mt_help(void) {
printf(
@@ -137,19 +139,19 @@ static void psd_mt_save(const void *ip, const struct xt_entry_match *match)
}
static struct xtables_match psd_mt_reg = {
.name = "psd",
.version = XTABLES_VERSION,
.revision = 1,
.family = NFPROTO_IPV4,
.size = XT_ALIGN(sizeof(struct xt_psd_info)),
.name = "psd",
.version = XTABLES_VERSION,
.revision = 1,
.family = NFPROTO_UNSPEC,
.size = XT_ALIGN(sizeof(struct xt_psd_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_psd_info)),
.help = psd_mt_help,
.init = psd_mt_init,
.parse = psd_mt_parse,
.final_check = psd_mt_final_check,
.print = psd_mt_print,
.save = psd_mt_save,
.extra_opts = psd_mt_opts,
.help = psd_mt_help,
.init = psd_mt_init,
.parse = psd_mt_parse,
.final_check = psd_mt_final_check,
.print = psd_mt_print,
.save = psd_mt_save,
.extra_opts = psd_mt_opts,
};
static __attribute__((constructor)) void psd_mt_ldr(void)

View File

@@ -1,7 +1,7 @@
/*
* "quota2" match extension for iptables
* Sam Johnston <samj [at] samj net>
* Jan Engelhardt <jengelh [at] medozas de>, 2008
* Jan Engelhardt, 2008
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License; either

View File

@@ -1,6 +1,6 @@
/*
* "CHAOS" target extension for Xtables
* Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2006 - 2008
* Copyright © Jan Engelhardt, 2006 - 2008
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License; either
@@ -274,6 +274,6 @@ static void __exit chaos_tg_exit(void)
module_init(chaos_tg_init);
module_exit(chaos_tg_exit);
MODULE_DESCRIPTION("Xtables: Network scan slowdown with non-deterministic results");
MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>");
MODULE_AUTHOR("Jan Engelhardt ");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_CHAOS");

View File

@@ -1,6 +1,6 @@
/*
* "DELUDE" target extension for Xtables
* Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2007 - 2008
* Copyright © Jan Engelhardt, 2007 - 2008
*
* Based upon linux-2.6.18.5/net/ipv4/netfilter/ipt_REJECT.c:
* (C) 1999-2001 Paul `Rusty' Russell
@@ -177,6 +177,6 @@ static void __exit delude_tg_exit(void)
module_init(delude_tg_init);
module_exit(delude_tg_exit);
MODULE_DESCRIPTION("Xtables: Close TCP connections after handshake");
MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>");
MODULE_AUTHOR("Jan Engelhardt ");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_DELUDE");

View File

@@ -1,6 +1,6 @@
/*
* "DHCPMAC" extensions for Xtables
* Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2008
* Copyright © Jan Engelhardt, 2008
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License; either
@@ -167,7 +167,7 @@ static void __exit dhcpmac_exit(void)
module_init(dhcpmac_init);
module_exit(dhcpmac_exit);
MODULE_DESCRIPTION("Xtables: Clamp DHCP MAC to packet MAC addresses");
MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>");
MODULE_AUTHOR("Jan Engelhardt ");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_DHCPMAC");
MODULE_ALIAS("ipt_dhcpmac");

View File

@@ -3,7 +3,7 @@
* or destination (PREROUTING),
*/
/* (C) 2011 Marek Kierdelewicz <marek@koba.pl>
/* (C) 2012 Marek Kierdelewicz <marek@koba.pl>
*
* module is dedicated to my wife Eliza and my daughters Jula and Ola :* :* :*
*
@@ -19,6 +19,7 @@
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/inet.h>
#include <linux/ip.h>
#include <linux/module.h>
#include <linux/netdevice.h>
@@ -40,7 +41,7 @@
#include "xt_DNETMAP.h"
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Marek Kierdelewicz <marek@koba.pl>");
MODULE_AUTHOR("Marek Kierdelewicz <marek@piasta.pl>");
MODULE_DESCRIPTION(
"Xtables: dynamic two-way 1:1 NAT mapping of IPv4 addresses");
MODULE_ALIAS("ipt_DNETMAP");
@@ -77,6 +78,7 @@ struct dnetmap_entry {
struct list_head lru_list;
__be32 prenat_addr;
__be32 postnat_addr;
__u8 flags;
unsigned long stamp;
struct dnetmap_prefix *prefix;
};
@@ -84,12 +86,18 @@ struct dnetmap_entry {
struct dnetmap_prefix {
struct nf_nat_ipv4_multi_range_compat prefix;
char prefix_str[16];
struct list_head list;
#ifdef CONFIG_PROC_FS
char proc_str_data[20];
char proc_str_stat[25];
#endif
struct list_head elist; // element list head
struct list_head list; // prefix list
__u8 flags;
unsigned int refcnt;
/* lru entry list */
struct list_head lru_list;
/* hash based on prenat-ips */
struct list_head iphash[0];
/* pointer do dnetmap_net */
struct dnetmap_net *dnetmap;
};
struct dnetmap_net {
@@ -157,6 +165,18 @@ dnetmap_entry_rlookup(struct dnetmap_net *dnetmap_net, const __be32 addr)
return NULL;
}
static int
dnetmap_addr_in_prefix(struct dnetmap_net *dnetmap_net, const __be32 addr,
struct dnetmap_prefix *p)
{
struct dnetmap_entry *e;
list_for_each_entry(e, &p->elist, list)
if (memcmp(&e->postnat_addr, &addr, sizeof(addr)) == 0)
return 1;
return 0;
}
static struct dnetmap_prefix *
dnetmap_prefix_lookup(struct dnetmap_net *dnetmap_net,
const struct nf_nat_ipv4_multi_range_compat *mr)
@@ -169,12 +189,47 @@ dnetmap_prefix_lookup(struct dnetmap_net *dnetmap_net,
return NULL;
}
static void dnetmap_prefix_flush(struct dnetmap_net *dnetmap_net,
static void dnetmap_prefix_destroy(struct dnetmap_net *dnetmap_net,
struct dnetmap_prefix *p)
{
struct dnetmap_entry *e, *next;
unsigned int i;
#ifdef CONFIG_PROC_FS
remove_proc_entry(p->proc_str_data, dnetmap_net->xt_dnetmap);
remove_proc_entry(p->proc_str_stat, dnetmap_net->xt_dnetmap);
#endif
for (i = 0; i < hash_size; i++) {
list_for_each_entry_safe(e, next,
&dnetmap_net->dnetmap_iphash[i], glist)
if (e->prefix == p)
list_del(&e->glist);
list_for_each_entry_safe(e, next,
&dnetmap_net->
dnetmap_iphash[hash_size + i], grlist)
if (e->prefix == p)
list_del(&e->grlist);
}
list_for_each_entry_safe(e, next, &p->elist, list) {
list_del(&e->list);
if(! (e->flags & XT_DNETMAP_STATIC)) list_del(&e->lru_list);
kfree(e);
}
list_del(&p->list);
kfree(p);
}
/* function clears bindings without destroying prefix */
static void dnetmap_prefix_softflush(struct dnetmap_prefix *p)
{
struct dnetmap_net *dnetmap_net = p->dnetmap;
struct dnetmap_entry *e, *next;
unsigned int i;
for (i = 0; i < hash_size; i++) {
list_for_each_entry_safe(e, next,
&dnetmap_net->dnetmap_iphash[i], glist)
@@ -186,12 +241,16 @@ static void dnetmap_prefix_flush(struct dnetmap_net *dnetmap_net,
dnetmap_iphash[hash_size + i], grlist)
if (e->prefix == p)
list_del(&e->grlist);
}
list_for_each_entry_safe(e, next, &p->elist, list) {
list_for_each_entry_safe(e, next, &p->iphash[i], list) {
list_del(&e->list);
list_del(&e->lru_list);
kfree(e);
/* make dynamic entry of any static entry */
if(e->flags & XT_DNETMAP_STATIC){
list_add_tail(&e->lru_list, &p->lru_list);
e->flags&=~XT_DNETMAP_STATIC;
}
e->stamp=jiffies-1;
e->prenat_addr=0;
}
}
@@ -204,11 +263,8 @@ static int dnetmap_tg_check(const struct xt_tgchk_param *par)
struct dnetmap_entry *e;
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *pde_data, *pde_stat;
char proc_str_data[20];
char proc_str_stat[25];
#endif
int ret = -EINVAL;
int i;
__be32 a;
__u32 ip_min, ip_max, ip;
@@ -243,11 +299,13 @@ static int dnetmap_tg_check(const struct xt_tgchk_param *par)
goto out;
}
p->refcnt = 1;
p->flags = 0;
p->flags |= (tginfo->flags & XT_DNETMAP_PERSISTENT);
p->dnetmap = dnetmap_net;
memcpy(&p->prefix, mr, sizeof(*mr));
INIT_LIST_HEAD(&p->lru_list);
for (i = 0; i < hash_size * 2; i++)
INIT_LIST_HEAD(&p->iphash[i]);
INIT_LIST_HEAD(&p->elist);
ip_min = ntohl(mr->range[0].min_ip) + (whole_prefix == 0);
ip_max = ntohl(mr->range[0].max_ip) - (whole_prefix == 0);
@@ -255,9 +313,9 @@ static int dnetmap_tg_check(const struct xt_tgchk_param *par)
sprintf(p->prefix_str, NIPQUAD_FMT "/%u", NIPQUAD(mr->range[0].min_ip),
33 - ffs(~(ip_min ^ ip_max)));
#ifdef CONFIG_PROC_FS
sprintf(proc_str_data, NIPQUAD_FMT "_%u", NIPQUAD(mr->range[0].min_ip),
sprintf(p->proc_str_data, NIPQUAD_FMT "_%u", NIPQUAD(mr->range[0].min_ip),
33 - ffs(~(ip_min ^ ip_max)));
sprintf(proc_str_stat, NIPQUAD_FMT "_%u_stat", NIPQUAD(mr->range[0].min_ip),
sprintf(p->proc_str_stat, NIPQUAD_FMT "_%u_stat", NIPQUAD(mr->range[0].min_ip),
33 - ffs(~(ip_min ^ ip_max)));
#endif
printk(KERN_INFO KBUILD_MODNAME ": new prefix %s\n", p->prefix_str);
@@ -271,12 +329,14 @@ static int dnetmap_tg_check(const struct xt_tgchk_param *par)
e->prenat_addr = 0;
e->stamp = jiffies;
e->prefix = p;
e->flags = 0;
list_add_tail(&e->lru_list, &p->lru_list);
list_add_tail(&e->list, &p->elist);
}
#ifdef CONFIG_PROC_FS
/* data */
pde_data = proc_create_data(proc_str_data, proc_perms,
pde_data = proc_create_data(p->proc_str_data, proc_perms,
dnetmap_net->xt_dnetmap,
&dnetmap_tg_fops, p);
if (pde_data == NULL) {
@@ -288,7 +348,7 @@ static int dnetmap_tg_check(const struct xt_tgchk_param *par)
pde_data->gid = proc_gid;
/* statistics */
pde_stat = create_proc_entry(proc_str_stat, proc_perms,
pde_stat = create_proc_entry(p->proc_str_stat, proc_perms,
dnetmap_net->xt_dnetmap);
if (pde_stat == NULL) {
kfree(p);
@@ -351,7 +411,7 @@ dnetmap_tg(struct sk_buff **pskb, const struct xt_action_param *par)
if (memcmp(mr, &e->prefix, sizeof(*mr)))
goto no_rev_map;
/* don't reset ttl if flag is set */
if (jttl >= 0) {
if (jttl >= 0 && (! (e->flags & XT_DNETMAP_STATIC) ) ) {
p = e->prefix;
e->stamp = jiffies + jttl;
list_move_tail(&e->lru_list, &p->lru_list);
@@ -378,17 +438,24 @@ dnetmap_tg(struct sk_buff **pskb, const struct xt_action_param *par)
if (e == NULL) { /* need for new binding */
// finish if it's static only rule
if(tginfo->flags & XT_DNETMAP_STATIC)
goto no_free_ip;
bind_new_prefix:
e = list_entry(p->lru_list.next, struct dnetmap_entry,
lru_list);
if (e->prenat_addr != 0 && time_before(jiffies, e->stamp)) {
if (!disable_log)
if (!disable_log && ! (p->flags & XT_DNETMAP_FULL) ){
printk(KERN_INFO KBUILD_MODNAME
": ip " NIPQUAD_FMT " - no free adresses in prefix %s\n",
NIPQUAD(prenat_ip), p->prefix_str);
p->flags |= XT_DNETMAP_FULL;
}
goto no_free_ip;
}
p->flags &= ~XT_DNETMAP_FULL;
postnat_ip = e->postnat_addr;
if (e->prenat_addr != 0) {
@@ -397,7 +464,6 @@ bind_new_prefix:
printk(KERN_INFO KBUILD_MODNAME
": timeout binding " NIPQUAD_FMT " -> " NIPQUAD_FMT "\n",
NIPQUAD(prenat_ip_prev), NIPQUAD(postnat_ip) );
list_del(&e->list);
list_del(&e->glist);
list_del(&e->grlist);
}
@@ -405,8 +471,6 @@ bind_new_prefix:
e->prenat_addr = prenat_ip;
e->stamp = jiffies + jttl;
list_move_tail(&e->lru_list, &p->lru_list);
list_add_tail(&e->list,
&p->iphash[dnetmap_entry_hash(prenat_ip)]);
list_add_tail(&e->glist,
&dnetmap_net->
dnetmap_iphash[dnetmap_entry_hash(prenat_ip)]);
@@ -421,21 +485,21 @@ bind_new_prefix:
} else {
if (!(tginfo->flags & XT_DNETMAP_REUSE))
if (!(tginfo->flags & XT_DNETMAP_REUSE) && !(e->flags & XT_DNETMAP_STATIC))
if (time_before(e->stamp, jiffies) && p != e->prefix) {
if (!disable_log)
printk(KERN_INFO KBUILD_MODNAME
": timeout binding " NIPQUAD_FMT " -> " NIPQUAD_FMT "\n",
NIPQUAD(e->prenat_addr),
NIPQUAD(e->postnat_addr));
list_del(&e->list);
list_del(&e->glist);
list_del(&e->grlist);
e->prenat_addr = 0;
goto bind_new_prefix;
}
/* don't reset ttl if flag is set */
if (jttl >= 0) {
/* don't reset ttl if flag is set
or it is static entry*/
if (jttl >= 0 && ! (e->flags & XT_DNETMAP_STATIC) ) {
e->stamp = jiffies + jttl;
p = e->prefix;
list_move_tail(&e->lru_list, &p->lru_list);
@@ -466,32 +530,17 @@ static void dnetmap_tg_destroy(const struct xt_tgdtor_param *par)
const struct xt_DNETMAP_tginfo *tginfo = par->targinfo;
const struct nf_nat_ipv4_multi_range_compat *mr = &tginfo->prefix;
struct dnetmap_prefix *p;
#ifdef CONFIG_PROC_FS
char str[25];
#endif
if (!(tginfo->flags & XT_DNETMAP_PREFIX))
return;
mutex_lock(&dnetmap_mutex);
spin_lock_bh(&dnetmap_lock);
p = dnetmap_prefix_lookup(dnetmap_net, mr);
if (--p->refcnt == 0) {
spin_lock_bh(&dnetmap_lock);
list_del(&p->list);
spin_unlock_bh(&dnetmap_lock);
#ifdef CONFIG_PROC_FS
sprintf(str, NIPQUAD_FMT "_%u", NIPQUAD(mr->range[0].min_ip),
33 - ffs(~(ntohl(mr->range[0].min_ip ^
mr->range[0].max_ip))));
remove_proc_entry(str, dnetmap_net->xt_dnetmap);
sprintf(str, NIPQUAD_FMT "_%u_stat", NIPQUAD(mr->range[0].min_ip),
33 - ffs(~(ntohl(mr->range[0].min_ip ^
mr->range[0].max_ip))));
remove_proc_entry(str, dnetmap_net->xt_dnetmap);
#endif
dnetmap_prefix_flush(dnetmap_net, p);
kfree(p);
if (--p->refcnt == 0 && (! (p->flags & XT_DNETMAP_PERSISTENT) ) ) {
dnetmap_prefix_destroy(dnetmap_net, p);
}
spin_unlock_bh(&dnetmap_lock);
mutex_unlock(&dnetmap_mutex);
}
@@ -511,7 +560,7 @@ __acquires(dnetmap_lock)
spin_lock_bh(&dnetmap_lock);
list_for_each_entry(e, &prefix->lru_list, lru_list)
list_for_each_entry(e, &prefix->elist, list)
if (p-- == 0)
return e;
return NULL;
@@ -522,13 +571,13 @@ static void *dnetmap_seq_next(struct seq_file *seq, void *v, loff_t * pos)
struct dnetmap_iter_state *st = seq->private;
const struct dnetmap_prefix *prefix = st->p;
const struct dnetmap_entry *e = v;
const struct list_head *head = e->lru_list.next;
const struct list_head *head = e->list.next;
if (head == &prefix->lru_list)
if (head == &prefix->elist)
return NULL;
++*pos;
return list_entry(head, struct dnetmap_entry, lru_list);
return list_entry(head, struct dnetmap_entry, list);
}
static void dnetmap_seq_stop(struct seq_file *s, void *v)
@@ -541,9 +590,14 @@ static int dnetmap_seq_show(struct seq_file *seq, void *v)
{
const struct dnetmap_entry *e = v;
seq_printf(seq, NIPQUAD_FMT " -> " NIPQUAD_FMT " --- ttl: %d lasthit: %lu\n",
NIPQUAD(e->prenat_addr), NIPQUAD(e->postnat_addr),
(int)(e->stamp - jiffies) / HZ, (e->stamp - jtimeout) / HZ);
if((e->flags & XT_DNETMAP_STATIC) == 0){
seq_printf(seq, NIPQUAD_FMT " -> " NIPQUAD_FMT " --- ttl: %d lasthit: %lu\n",
NIPQUAD(e->prenat_addr), NIPQUAD(e->postnat_addr),
(int)(e->stamp - jiffies) / HZ, (e->stamp - jtimeout) / HZ);
}else{
seq_printf(seq, NIPQUAD_FMT " -> " NIPQUAD_FMT " --- ttl: S lasthit: S\n",
NIPQUAD(e->prenat_addr), NIPQUAD(e->postnat_addr));
}
return 0;
}
@@ -567,9 +621,180 @@ static int dnetmap_seq_open(struct inode *inode, struct file *file)
return 0;
}
static ssize_t
dnetmap_tg_proc_write(struct file *file, const char __user *input,size_t size, loff_t *loff)
{
const struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
struct dnetmap_prefix *p = pde->data;
struct dnetmap_entry *e;
char buf[sizeof("+192.168.100.100:200.200.200.200")];
const char *c = buf;
const char *c2;
//union nf_inet_addr addr = {};
__be32 addr1,addr2;
bool add;
char str[25];
if (size == 0)
return 0;
if (size > sizeof(buf))
size = sizeof(buf);
if (copy_from_user(buf, input, size) != 0)
return -EFAULT;
if(strcspn(c,"\n") < size)
buf[strcspn(c,"\n")]='\0';
/* Strict protocol! */
if (*loff != 0)
return -ESPIPE;
switch (*c) {
case 'f': /* flush table */
if( strcmp(c,"flush") != 0 )
goto invalid_arg;
printk(KERN_INFO KBUILD_MODNAME ": flushing prefix %s\n", p->prefix_str);
spin_lock_bh(&dnetmap_lock);
dnetmap_prefix_softflush(p);
spin_unlock_bh(&dnetmap_lock);
return size;
case '-': /* remove address or attribute */
if( strcmp(c,"-persistent") == 0){
/* case if persistent flag is already unset */
if( ! (p->flags & XT_DNETMAP_PERSISTENT) ){
printk(KERN_INFO KBUILD_MODNAME ": prefix %s is not persistent already - doing nothing\n", p->prefix_str);
return size;
}
printk(KERN_INFO KBUILD_MODNAME ": prefix %s is now non-persistent\n", p->prefix_str);
spin_lock_bh(&dnetmap_lock);
p->flags &= ~XT_DNETMAP_PERSISTENT;
spin_unlock_bh(&dnetmap_lock);
return size;
}
add = false;
break;
case '+': /* add address or attribute */
if( strcmp(c,"+persistent") == 0){
/* case if persistent flag is already unset */
if( p->flags & XT_DNETMAP_PERSISTENT ){
printk(KERN_INFO KBUILD_MODNAME ": prefix %s is persistent already - doing nothing\n", p->prefix_str);
return size;
}
printk(KERN_INFO KBUILD_MODNAME ": prefix %s is now persistent\n", p->prefix_str);
spin_lock_bh(&dnetmap_lock);
p->flags |= XT_DNETMAP_PERSISTENT;
spin_unlock_bh(&dnetmap_lock);
return size;
}
add = true;
break;
default:
goto invalid_arg;
}
spin_lock_bh(&dnetmap_lock);
// in case static entry is added we need to parse second ip addresses
if (add){
c2 = strchr(c,':');
if(c2 == NULL)
goto invalid_arg_unlock;
c++;
c2++;
if( ! (in4_pton(c2,strlen(c2),(void *)&addr2, '\0', NULL) &&
in4_pton(c,strlen(c),(void *)&addr1, ':', NULL)))
goto invalid_arg_unlock;
// sanity check - prenat ip can't belong to postnat prefix
if ( dnetmap_addr_in_prefix(p->dnetmap, addr1, p)){
printk(KERN_INFO KBUILD_MODNAME ": add static binding operation failed - prenat ip can't belong to postnat prefix\n");
goto invalid_arg_unlock;
}
// make sure postnat ip belongs to postnat prefix
if ( ! dnetmap_addr_in_prefix(p->dnetmap, addr2, p)){
printk(KERN_INFO KBUILD_MODNAME ": add static binding operation failed - postnat ip must belong to postnat prefix\n");
goto invalid_arg_unlock;
}
e = dnetmap_entry_rlookup(p->dnetmap,addr2);
if(e != NULL){
if (!disable_log)
printk(KERN_INFO KBUILD_MODNAME
": timeout binding " NIPQUAD_FMT " -> " NIPQUAD_FMT "\n",
NIPQUAD(e->prenat_addr), NIPQUAD(e->postnat_addr) );
list_del(&e->glist);
list_del(&e->grlist);
}else{
// find existing entry in prefix elist
list_for_each_entry(e, &p->elist, list)
if (memcmp(&e->postnat_addr, &addr2, sizeof(addr2)) == 0){
break;
}
}
e->prenat_addr=addr1;
e->flags |= XT_DNETMAP_STATIC;
list_add_tail(&e->glist,
&p->dnetmap->
dnetmap_iphash[dnetmap_entry_hash(e->prenat_addr)]);
list_add_tail(&e->grlist,
&p->dnetmap->dnetmap_iphash[hash_size +
dnetmap_entry_hash
(e->postnat_addr)]);
list_del(&e->lru_list);
sprintf(str, NIPQUAD_FMT ":" NIPQUAD_FMT, NIPQUAD(addr1),NIPQUAD(addr2));
printk(KERN_INFO KBUILD_MODNAME ": adding static binding %s\n", str);
// case of removing binding
}else{
c++;
if( ! in4_pton(c,strlen(c),(void *)&addr1, '\0', NULL))
goto invalid_arg_unlock;
e = dnetmap_entry_rlookup(p->dnetmap,addr1);
if(e == NULL) e = dnetmap_entry_lookup(p->dnetmap,addr1);
if(e != NULL){
if (!disable_log)
printk(KERN_INFO KBUILD_MODNAME
": remove binding " NIPQUAD_FMT " -> " NIPQUAD_FMT "\n",
NIPQUAD(e->prenat_addr), NIPQUAD(e->postnat_addr) );
list_del(&e->glist);
list_del(&e->grlist);
if(e->flags & XT_DNETMAP_STATIC){
list_add_tail(&e->lru_list,&p->lru_list);
e->flags &= ~XT_DNETMAP_STATIC;
}
e->prenat_addr=0;
e->stamp=jiffies-1;
}else{
goto invalid_arg_unlock;
}
}
spin_unlock_bh(&dnetmap_lock);
/* Note we removed one above */
*loff += size + 1;
return size + 1;
invalid_arg_unlock:
spin_unlock_bh(&dnetmap_lock);
invalid_arg:
//printk(KERN_INFO KBUILD_MODNAME ": Need \"+prenat_ip:postnat_ip\", \"-ip\" or \"/\"\n");
printk(KERN_INFO KBUILD_MODNAME ": Error! Invalid option passed via procfs.\n");
return -EINVAL;
}
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,
};
@@ -581,27 +806,31 @@ static int dnetmap_stat_proc_read(char __user *buffer, char **start,
{
const struct dnetmap_prefix *p = data;
struct dnetmap_entry *e;
unsigned int used, all;
unsigned int used, used_static, all;
long int ttl, sum_ttl;
used = 0;
all = 0;
sum_ttl = 0;
used=used_static=all=sum_ttl=0;
spin_lock_bh(&dnetmap_lock);
list_for_each_entry(e, &p->lru_list, lru_list) {
list_for_each_entry(e, &p->elist, list) {
ttl = e->stamp - jiffies;
if (e->prenat_addr != 0 && ttl >= 0) {
used++;
sum_ttl += ttl;
if (e->prenat_addr != 0){
if (e->flags & XT_DNETMAP_STATIC){
used_static++;
}else{
ttl = e->stamp - jiffies;
if (e->prenat_addr != 0 && ttl >= 0) {
used++;
sum_ttl += ttl;
}
}
}
all++;
}
sum_ttl = used > 0 ? sum_ttl / (used * HZ) : 0;
sprintf(buffer, "%u %u %ld\n", used, all, sum_ttl);
sprintf(buffer, "%u %u %u %ld %s\n", used, used_static, all, sum_ttl,(p->flags & XT_DNETMAP_PERSISTENT ? "persistent" : ""));
if (length >= strlen(buffer))
*eof = true;
@@ -663,12 +892,24 @@ static int __net_init dnetmap_net_init(struct net *net)
static void __net_exit dnetmap_net_exit(struct net *net)
{
struct dnetmap_net *dnetmap_net = dnetmap_pernet(net);
struct dnetmap_prefix *p,*next;
mutex_lock(&dnetmap_mutex);
spin_lock_bh(&dnetmap_lock);
list_for_each_entry_safe(p, next, &dnetmap_net->prefixes, list){
BUG_ON(p->refcnt != 0);
dnetmap_prefix_destroy(dnetmap_net, p);
}
spin_unlock_bh(&dnetmap_lock);
mutex_unlock(&dnetmap_mutex);
BUG_ON(!list_empty(&dnetmap_net->prefixes));
kfree(dnetmap_net->dnetmap_iphash);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34)
kfree(dnetmap_net);
#endif
dnetmap_proc_net_exit(net);
}
@@ -714,6 +955,8 @@ static int __init dnetmap_tg_init(void)
if (err)
unregister_pernet_subsys(&dnetmap_net_ops);
printk( KERN_INFO KBUILD_MODNAME " INIT successfull (version %d)\n", DNETMAP_VERSION );
return err;
}

View File

@@ -1,16 +1,21 @@
#ifndef _LINUX_NETFILTER_XT_DNETMAP_H
#define _LINUX_NETFILTER_XT_DNETMAP_H 1
#define DNETMAP_VERSION 2
enum {
XT_DNETMAP_TTL = 1 << 0,
XT_DNETMAP_REUSE = 1 << 1,
XT_DNETMAP_PREFIX = 1 << 2,
XT_DNETMAP_TTL = 1 << 0,
XT_DNETMAP_REUSE = 1 << 1,
XT_DNETMAP_PREFIX = 1 << 2,
XT_DNETMAP_STATIC = 1 << 3,
XT_DNETMAP_PERSISTENT = 1 << 4,
XT_DNETMAP_FULL = 1 << 5,
};
struct xt_DNETMAP_tginfo {
struct nf_nat_ipv4_multi_range_compat prefix;
__u8 flags;
__s16 ttl;
__s32 ttl;
};
#endif

View File

@@ -1,7 +1,7 @@
/*
* "ECHO" (RFC 862) target extension for Xtables
* Sample module for "Writing your own Netfilter Modules"
* Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2008-2011
* Copyright © Jan Engelhardt, 2008-2011
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License; either
@@ -18,6 +18,7 @@
# include <linux/netfilter_bridge.h>
#endif
#include <net/ip.h>
#include <net/ip6_checksum.h>
#include <net/ip6_route.h>
#include <net/route.h>
#include "compat_xtables.h"
@@ -251,7 +252,7 @@ static void __exit echo_tg_exit(void)
module_init(echo_tg_init);
module_exit(echo_tg_exit);
MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>");
MODULE_AUTHOR("Jan Engelhardt ");
MODULE_DESCRIPTION("Xtables: ECHO diagnosis target");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ip6t_ECHO");

View File

@@ -1,7 +1,7 @@
/*
* "IPMARK" target extension for Xtables
* Copyright © Grzegorz Janoszka <Grzegorz.Janoszka@pro.onet.pl>, 2003
* Jan Engelhardt <jengelh [at] medozas de>, 2008
* Jan Engelhardt, 2008
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License; either

View File

@@ -2,7 +2,7 @@
* "LOGMARK" target extension to Xtables
* useful for debugging
*
* Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2008-2010
* Copyright © Jan Engelhardt, 2008-2010
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License; either
@@ -141,7 +141,7 @@ static void __exit logmark_tg_exit(void)
module_init(logmark_tg_init);
module_exit(logmark_tg_exit);
MODULE_DESCRIPTION("Xtables: netfilter mark logging to syslog");
MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>");
MODULE_AUTHOR("Jan Engelhardt ");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_LOGMARK");
MODULE_ALIAS("ip6t_LOGMARK");

View File

@@ -1,359 +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_IPV6) || defined(CONFIG_IPV6_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;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
cond |= skb->ip_summed == CHECKSUM_PARTIAL;
#endif
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 = sizeof(*iph);
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);
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;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
cond |= skb->ip_summed == CHECKSUM_PARTIAL;
#endif
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, 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, 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 <jengelh@medozas.de>");
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");

View File

@@ -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 */

View File

@@ -1,67 +0,0 @@
/*
* "STEAL" demo target extension for Xtables
* written by Jan Engelhardt <jengelh [at] medozas de>, 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 <jengelh@medozas.de>");
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");

View File

@@ -1,6 +1,6 @@
/*
* "SYSRQ" target extension for Xtables
* Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2008 - 2010
* Copyright © Jan Engelhardt, 2008 - 2010
*
* Based upon the ipt_SYSRQ idea by Marek Zalem <marek [at] terminus sk>
*
@@ -30,7 +30,7 @@
(defined(CONFIG_CRYPTO) || defined(CONFIG_CRYPTO_MODULE))
# define WITH_CRYPTO 1
#endif
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
# define WITH_IPV6 1
#endif
@@ -240,15 +240,16 @@ sysrq_tg6(struct sk_buff **pskb, const struct xt_action_param *par)
const struct ipv6hdr *iph;
const struct udphdr *udph;
unsigned short frag_off;
unsigned int th_off;
unsigned int th_off = 0;
uint16_t len;
if (skb_linearize(skb) < 0)
return NF_DROP;
iph = ipv6_hdr(skb);
if ((ipv6_find_hdr(skb, &th_off, IPPROTO_UDP, &frag_off) < 0 &&
ipv6_find_hdr(skb, &th_off, IPPROTO_UDPLITE, &frag_off) < 0) ||
/* Should probably be using %IP6T_FH_F_AUTH */
if ((ipv6_find_hdr(skb, &th_off, IPPROTO_UDP, &frag_off, NULL) < 0 &&
ipv6_find_hdr(skb, &th_off, IPPROTO_UDPLITE, &frag_off, NULL) < 0) ||
frag_off > 0)
return NF_DROP;
@@ -358,10 +359,7 @@ static int __init sysrq_crypto_init(void)
goto fail;
do_gettimeofday(&now);
sysrq_seqno = now.tv_sec;
ret = xt_register_targets(sysrq_tg_reg, ARRAY_SIZE(sysrq_tg_reg));
if (ret < 0)
goto fail;
return ret;
return 0;
fail:
sysrq_crypto_exit();
@@ -388,7 +386,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 <jengelh@medozas.de>");
MODULE_AUTHOR("Jan Engelhardt ");
MODULE_AUTHOR("John Haxby <john.haxby@oracle.com");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_SYSRQ");

View File

@@ -42,19 +42,139 @@
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/version.h>
#include <linux/netfilter_ipv6.h>
#include <linux/netfilter/x_tables.h>
#ifdef CONFIG_BRIDGE_NETFILTER
# include <linux/netfilter_bridge.h>
#endif
#include <net/addrconf.h>
#include <net/ip6_checksum.h>
#include <net/ip6_route.h>
#include <net/ipv6.h>
#include <net/route.h>
#include <net/tcp.h>
#include "compat_xtables.h"
#include "xt_TARPIT.h"
#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
# define WITH_IPV6 1
#endif
static void tarpit_tcp(struct sk_buff *oldskb, unsigned int hook,
static bool xttarpit_tarpit(struct tcphdr *tcph, const struct tcphdr *oth)
{
/* No replies for RST, FIN or !SYN,!ACK */
if (oth->rst || oth->fin || (!oth->syn && !oth->ack))
return false;
tcph->seq = oth->ack ? oth->ack_seq : 0;
/* Our SYN-ACKs must have a >0 window */
tcph->window = (oth->syn && !oth->ack) ? htons(5) : 0;
if (oth->syn && oth->ack) {
tcph->rst = true;
tcph->ack_seq = false;
} else {
tcph->syn = oth->syn;
tcph->ack = true;
tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn);
}
#if 0
/* Rate-limit replies to !SYN,ACKs */
if (!oth->syn && oth->ack)
if (!xrlim_allow(rt_dst(ort), HZ))
return false;
#endif
return true;
}
static bool xttarpit_honeypot(struct tcphdr *tcph, const struct tcphdr *oth,
uint16_t payload)
{
/* Do not answer any resets regardless of combination */
if (oth->rst || oth->seq == 0xDEADBEEF)
return false;
/* Send a reset to scanners. They like that. */
if (oth->syn && oth->ack) {
tcph->window = 0;
tcph->ack = false;
tcph->psh = true;
tcph->ack_seq = 0xdeadbeef; /* see if they ack it */
tcph->seq = oth->ack_seq;
tcph->rst = true;
}
/* SYN > SYN-ACK */
if (oth->syn && !oth->ack) {
tcph->syn = true;
tcph->ack = true;
tcph->window = oth->window &
((net_random() & 0x1f) - 0xf);
tcph->seq = htonl(net_random() & ~oth->seq);
tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn);
}
/* ACK > ACK */
if (oth->ack && (!(oth->fin || oth->syn))) {
tcph->syn = false;
tcph->ack = true;
tcph->window = oth->window &
((net_random() & 0x1f) - 0xf);
tcph->ack_seq = payload > 100 ?
htonl(ntohl(oth->seq) + payload) :
oth->seq;
tcph->seq = oth->ack_seq;
}
/*
* FIN > RST.
* We cannot terminate gracefully so just be abrupt.
*/
if (oth->fin) {
tcph->window = 0;
tcph->seq = oth->ack_seq;
tcph->ack_seq = oth->ack_seq;
tcph->fin = false;
tcph->ack = false;
tcph->rst = true;
}
return true;
}
static void xttarpit_reset(struct tcphdr *tcph, const struct tcphdr *oth)
{
tcph->window = 0;
tcph->ack = false;
tcph->syn = false;
tcph->rst = true;
tcph->seq = oth->ack_seq;
tcph->ack_seq = oth->seq;
}
static bool tarpit_generic(struct tcphdr *tcph, const struct tcphdr *oth,
uint16_t payload, unsigned int mode)
{
switch(mode) {
case XTTARPIT_TARPIT:
if (!xttarpit_tarpit(tcph, oth))
return false;
break;
case XTTARPIT_HONEYPOT:
if (!xttarpit_honeypot(tcph, oth, payload))
return false;
break;
case XTTARPIT_RESET:
xttarpit_reset(tcph, oth);
break;
}
return true;
}
static void tarpit_tcp4(struct sk_buff *oldskb, unsigned int hook,
unsigned int mode)
{
struct tcphdr _otcph, *oth, *tcph;
struct tcphdr _otcph, *tcph;
const struct tcphdr *oth;
unsigned int addr_type = RTN_UNSPEC;
struct sk_buff *nskb;
const struct iphdr *oldhdr;
@@ -116,84 +236,8 @@ static void tarpit_tcp(struct sk_buff *oldskb, unsigned int hook,
/* Reset flags */
((u_int8_t *)tcph)[13] = 0;
if (mode == XTTARPIT_TARPIT) {
/* No replies for RST, FIN or !SYN,!ACK */
if (oth->rst || oth->fin || (!oth->syn && !oth->ack))
return;
tcph->seq = oth->ack ? oth->ack_seq : 0;
/* Our SYN-ACKs must have a >0 window */
tcph->window = (oth->syn && !oth->ack) ? htons(5) : 0;
if (oth->syn && oth->ack) {
tcph->rst = true;
tcph->ack_seq = false;
} else {
tcph->syn = oth->syn;
tcph->ack = true;
tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn);
}
#if 0
/* Rate-limit replies to !SYN,ACKs */
if (!oth->syn && oth->ack)
if (!xrlim_allow(rt_dst(ort), HZ))
return;
#endif
} else if (mode == XTTARPIT_HONEYPOT) {
/* Do not answer any resets regardless of combination */
if (oth->rst || oth->seq == 0xDEADBEEF)
return;
/* Send a reset to scanners. They like that. */
if (oth->syn && oth->ack) {
tcph->window = 0;
tcph->ack = false;
tcph->psh = true;
tcph->ack_seq = 0xdeadbeef; /* see if they ack it */
tcph->seq = oth->ack_seq;
tcph->rst = true;
}
/* SYN > SYN-ACK */
if (oth->syn && !oth->ack) {
tcph->syn = true;
tcph->ack = true;
tcph->window = oth->window &
((net_random() & 0x1f) - 0xf);
tcph->seq = htonl(net_random() & ~oth->seq);
tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn);
}
/* ACK > ACK */
if (oth->ack && (!(oth->fin || oth->syn))) {
tcph->syn = false;
tcph->ack = true;
tcph->window = oth->window &
((net_random() & 0x1f) - 0xf);
tcph->ack_seq = payload > 100 ?
htonl(ntohl(oth->seq) + payload) :
oth->seq;
tcph->seq = oth->ack_seq;
}
/*
* FIN > RST.
* We cannot terminate gracefully so just be abrupt.
*/
if (oth->fin) {
tcph->window = 0;
tcph->seq = oth->ack_seq;
tcph->ack_seq = oth->ack_seq;
tcph->fin = false;
tcph->ack = false;
tcph->rst = true;
}
} else if (mode == XTTARPIT_RESET) {
tcph->window = 0;
tcph->ack = false;
tcph->syn = false;
tcph->rst = true;
tcph->seq = oth->ack_seq;
tcph->ack_seq = oth->seq;
}
if (!tarpit_generic(tcph, oth, payload, mode))
goto free_nskb;
/* Adjust TCP checksum */
tcph->check = 0;
@@ -257,8 +301,132 @@ static void tarpit_tcp(struct sk_buff *oldskb, unsigned int hook,
kfree_skb(nskb);
}
#ifdef WITH_IPV6
static void tarpit_tcp6(struct sk_buff *oldskb, unsigned int hook,
unsigned int mode)
{
struct sk_buff *nskb;
struct tcphdr *tcph, oth;
unsigned int otcplen;
int tcphoff;
const struct ipv6hdr *oip6h = ipv6_hdr(oldskb);
struct ipv6hdr *ip6h;
const uint8_t tclass = 0;
uint8_t proto;
uint16_t payload;
__be16 frag_off;
proto = oip6h->nexthdr;
tcphoff = ipv6_skip_exthdr(oldskb,
(uint8_t *)(oip6h + 1) - oldskb->data, &proto, &frag_off);
if (tcphoff < 0 || tcphoff > oldskb->len) {
pr_debug("Cannot get TCP header.\n");
return;
}
otcplen = oldskb->len - tcphoff;
/* IP header checks: fragment, too short. */
if (proto != IPPROTO_TCP || otcplen < sizeof(struct tcphdr)) {
pr_debug("proto(%d) != IPPROTO_TCP, "
"or too short. otcplen = %d\n",
proto, otcplen);
return;
}
if (skb_copy_bits(oldskb, tcphoff, &oth, sizeof(struct tcphdr))) {
WARN_ON(1);
return;
}
/* Check checksum. */
if (csum_ipv6_magic(&oip6h->saddr, &oip6h->daddr, otcplen, IPPROTO_TCP,
skb_checksum(oldskb, tcphoff, otcplen, 0))) {
pr_debug("TCP checksum is invalid\n");
return;
}
nskb = skb_copy_expand(oldskb, LL_MAX_HEADER,
skb_tailroom(oldskb), GFP_ATOMIC);
if (nskb == NULL) {
if (net_ratelimit())
pr_debug("cannot alloc skb\n");
return;
}
/* This packet will not be the same as the other: clear nf fields */
nf_reset(nskb);
skb_nfmark(nskb) = 0;
skb_init_secmark(nskb);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
skb_shinfo(nskb)->gso_size = 0;
skb_shinfo(nskb)->gso_segs = 0;
skb_shinfo(nskb)->gso_type = 0;
#endif
skb_put(nskb, sizeof(struct ipv6hdr));
ip6h = ipv6_hdr(nskb);
*(__be32 *)ip6h = htonl(0x60000000 | (tclass << 20));
ip6h->nexthdr = IPPROTO_TCP;
ip6h->saddr = oip6h->daddr;
ip6h->daddr = oip6h->saddr;
/* Adjust IP TTL */
if (mode == XTTARPIT_HONEYPOT) {
ip6h->hop_limit = 128;
} else {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
ip6h->hop_limit = ip6_dst_hoplimit(skb_dst(nskb));
#else
ip6h->hop_limit = dst_metric(skb_dst(nskb), RTAX_HOPLIMIT);
#endif
}
tcph = (struct tcphdr *)(skb_network_header(nskb) +
sizeof(struct ipv6hdr));
/* Truncate to length (no data) */
skb_trim(nskb, sizeof(struct ipv6hdr) + sizeof(struct tcphdr));
tcph->doff = sizeof(struct tcphdr)/4;
tcph->source = oth.dest;
tcph->dest = oth.source;
tcph->urg_ptr = 0;
/* Reset flags */
((uint8_t *)tcph)[13] = 0;
payload = nskb->len - sizeof(struct ipv6hdr) - sizeof(struct tcphdr);
if (!tarpit_generic(&oth, tcph, payload, mode))
goto free_nskb;
ip6h->payload_len = htons(sizeof(struct tcphdr));
tcph->check = 0;
/* Adjust TCP checksum */
tcph->check = csum_ipv6_magic(&ipv6_hdr(nskb)->saddr,
&ipv6_hdr(nskb)->daddr, sizeof(struct tcphdr),
IPPROTO_TCP,
csum_partial(tcph, sizeof(struct tcphdr), 0));
if (ip6_route_me_harder(nskb))
goto free_nskb;
nskb->ip_summed = CHECKSUM_NONE;
nf_ct_attach(nskb, oldskb);
NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, nskb, NULL,
skb_dst(nskb)->dev, dst_output);
return;
free_nskb:
kfree_skb(nskb);
}
#endif
static unsigned int
tarpit_tg(struct sk_buff **pskb, const struct xt_action_param *par)
tarpit_tg4(struct sk_buff **pskb, const struct xt_action_param *par)
{
const struct sk_buff *skb = *pskb;
const struct iphdr *iph = ip_hdr(skb);
@@ -289,34 +457,93 @@ tarpit_tg(struct sk_buff **pskb, const struct xt_action_param *par)
if (iph->frag_off & htons(IP_OFFSET))
return NF_DROP;
tarpit_tcp(*pskb, par->hooknum, info->variant);
tarpit_tcp4(*pskb, par->hooknum, info->variant);
return NF_DROP;
}
static struct xt_target tarpit_tg_reg __read_mostly = {
.name = "TARPIT",
.revision = 0,
.family = NFPROTO_IPV4,
.hooks = (1 << NF_INET_LOCAL_IN) | (1 << NF_INET_FORWARD),
.proto = IPPROTO_TCP,
.target = tarpit_tg,
.targetsize = sizeof(struct xt_tarpit_tginfo),
.me = THIS_MODULE,
#ifdef WITH_IPV6
static unsigned int
tarpit_tg6(struct sk_buff **pskb, 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;
uint8_t proto;
__be16 frag_off;
/* Do we have an input route cache entry? (Not in PREROUTING.) */
if (rt == NULL) {
pr_debug("Dropping no input route cache entry\n");
return NF_DROP;
}
/* No replies to physical multicast/broadcast */
/* skb != PACKET_OTHERHOST handled by ip_rcv() */
if (skb->pkt_type != PACKET_HOST) {
pr_debug("type != PACKET_HOST");
return NF_DROP;
}
/*
* Our naive response construction does not deal with IP
* options, and probably should not try.
*/
proto = iph->nexthdr;
if (ipv6_skip_exthdr(skb, skb_network_header_len(skb), &proto,
&frag_off) != sizeof(struct ipv6hdr))
return NF_DROP;
if ((!(ipv6_addr_type(&iph->saddr) & IPV6_ADDR_UNICAST)) ||
(!(ipv6_addr_type(&iph->daddr) & IPV6_ADDR_UNICAST))) {
pr_debug("addr is not unicast.\n");
return NF_DROP;
}
tarpit_tcp6(*pskb, par->hooknum, info->variant);
return NF_DROP;
}
#endif
static struct xt_target tarpit_tg_reg[] __read_mostly = {
{
.name = "TARPIT",
.revision = 0,
.family = NFPROTO_IPV4,
.hooks = (1 << NF_INET_LOCAL_IN) | (1 << NF_INET_FORWARD),
.proto = IPPROTO_TCP,
.target = tarpit_tg4,
.targetsize = sizeof(struct xt_tarpit_tginfo),
.me = THIS_MODULE,
},
#ifdef WITH_IPV6
{
.name = "TARPIT",
.revision = 0,
.family = NFPROTO_IPV6,
.hooks = (1 << NF_INET_LOCAL_IN) | (1 << NF_INET_FORWARD),
.proto = IPPROTO_TCP,
.target = tarpit_tg6,
.targetsize = sizeof(struct xt_tarpit_tginfo),
.me = THIS_MODULE,
},
#endif
};
static int __init tarpit_tg_init(void)
{
return xt_register_target(&tarpit_tg_reg);
return xt_register_targets(tarpit_tg_reg, ARRAY_SIZE(tarpit_tg_reg));
}
static void __exit tarpit_tg_exit(void)
{
xt_unregister_target(&tarpit_tg_reg);
xt_unregister_targets(tarpit_tg_reg, ARRAY_SIZE(tarpit_tg_reg));
}
module_init(tarpit_tg_init);
module_exit(tarpit_tg_exit);
MODULE_DESCRIPTION("Xtables: \"TARPIT\", capture and hold TCP connections");
MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>");
MODULE_AUTHOR("Jan Engelhardt ");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_TARPIT");
MODULE_ALIAS("ip6t_TARPIT");

View File

@@ -33,7 +33,7 @@
# define WITH_CONNTRACK 1
# include <net/netfilter/nf_conntrack.h>
#endif
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
# define WITH_IPV6 1
#endif

View File

@@ -35,7 +35,7 @@ static unsigned int condition_gid_perms = 0;
MODULE_AUTHOR("Stephane Ouellette <ouellettes@videotron.ca>");
MODULE_AUTHOR("Massimiliano Hofer <max@nucleus.it>");
MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>");
MODULE_AUTHOR("Jan Engelhardt ");
MODULE_DESCRIPTION("Allows rules to match against condition variables");
MODULE_LICENSE("GPL");
module_param(condition_list_perms, uint, S_IRUSR | S_IWUSR);

View File

@@ -76,7 +76,7 @@ static void __exit ipv4options_mt_exit(void)
}
MODULE_DESCRIPTION("Xatblse: IPv4 option match");
MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>");
MODULE_AUTHOR("Jan Engelhardt ");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_ipv4options");
module_init(ipv4options_mt_init);

View File

@@ -1,6 +1,6 @@
/*
* xt_length - Xtables module to match packet length
* Copyright © Jan Engelhardt <jengelh@medozas.de>, 2007 - 2009
* Copyright © Jan Engelhardt , 2007 - 2009
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License; either
@@ -29,7 +29,7 @@
# define NEXTHDR_IPV4 4
#endif
MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>");
MODULE_AUTHOR("Jan Engelhardt ");
MODULE_DESCRIPTION("Xtables: Packet length (Layer3,4,5) match");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_length2");
@@ -185,7 +185,7 @@ llayer4_proto(const struct sk_buff *skb, unsigned int *offset, bool *hotdrop)
int err;
for (i = 0; i < ARRAY_SIZE(types); ++i) {
err = ipv6_find_hdr(skb, offset, types[i], NULL);
err = ipv6_find_hdr(skb, offset, types[i], NULL, NULL);
if (err >= 0)
return types[i];
if (err != -ENOENT) {
@@ -203,7 +203,8 @@ length2_mt6(const struct sk_buff *skb, struct xt_action_param *par)
const struct xt_length_mtinfo2 *info = par->matchinfo;
const struct ipv6hdr *iph = ipv6_hdr(skb);
unsigned int len = 0, l4proto;
unsigned int thoff = par->thoff;
/* par->thoff would only set if ip6tables -p was used; so just use 0 */
unsigned int thoff = 0;
bool hit = true;
if (info->flags & XT_LENGTH_LAYER3) {

View File

@@ -264,7 +264,7 @@ static void __exit lscan_mt_exit(void)
module_init(lscan_mt_init);
module_exit(lscan_mt_exit);
MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>");
MODULE_AUTHOR("Jan Engelhardt ");
MODULE_DESCRIPTION("Xtables: Low-level scan (e.g. nmap) match");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_lscan");

View File

@@ -22,13 +22,15 @@
#define pr_fmt(x) KBUILD_MODNAME ": " x
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/skbuff.h>
#include <linux/ip.h>
#include <net/tcp.h>
#include <linux/types.h>
#include <linux/tcp.h>
#include <linux/spinlock.h>
#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/vmalloc.h>
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter_ipv6/ip6_tables.h>
#include <net/ip.h>
#include <net/ipv6.h>
#include "xt_psd.h"
#include "compat_xtables.h"
@@ -39,11 +41,21 @@ MODULE_AUTHOR("Jan Rekorajski <baggins@pld.org.pl>");
MODULE_AUTHOR(" Mohd Nawawi Mohamad Jamili <nawawi@tracenetworkcorporation.com>");
MODULE_DESCRIPTION("Xtables: PSD - portscan detection");
MODULE_ALIAS("ipt_psd");
MODULE_ALIAS("ip6t_psd");
#define HF_DADDR_CHANGING 0x01
#define HF_SPORT_CHANGING 0x02
#define HF_TOS_CHANGING 0x04
#define HF_TTL_CHANGING 0x08
/*
* 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
* HASH_MAX source addresses per the same hash value.
*/
#define LIST_SIZE 0x100
#define HASH_LOG 9
#define HASH_SIZE (1 << HASH_LOG)
#define HASH_MAX 0x10
#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
# define WITH_IPV6 1
#endif
/*
* Information we keep per each target port
@@ -51,46 +63,106 @@ MODULE_ALIAS("ipt_psd");
struct port {
u_int16_t number; /* port number */
u_int8_t proto; /* protocol number */
u_int8_t and_flags; /* tcp ANDed flags */
u_int8_t or_flags; /* tcp ORed flags */
};
/*
/**
* Information we keep per each source address.
* @next: next entry with the same hash
* @timestamp: last update time
* @count: number of ports in the list
* @weight: total weight of ports in the list
*/
struct host {
struct host *next; /* Next entry with the same hash */
unsigned long timestamp; /* Last update time */
struct in_addr src_addr; /* Source address */
struct in_addr dest_addr; /* Destination address */
unsigned short src_port; /* Source port */
int count; /* Number of ports in the list */
int weight; /* Total weight of ports in the list */
struct port ports[SCAN_MAX_COUNT - 1]; /* List of ports */
unsigned char tos; /* TOS */
unsigned char ttl; /* TTL */
unsigned char flags; /* HF_ flags bitmask */
struct host *next;
unsigned long timestamp;
__be16 src_port;
uint16_t count;
uint8_t weight;
struct port ports[SCAN_MAX_COUNT-1];
};
/*
* State information.
/**
* Information we keep per ipv4 source address.
*/
struct host4 {
struct host host;
__be32 saddr;
};
static struct host4 *host_to_host4(const struct host *h)
{
return (struct host4 *)h;
}
struct host6 {
struct host host;
struct in6_addr saddr;
};
/**
* State information for IPv4 portscan detection.
* @list: list of source addresses
* @hash: pointers into the list
* @index: oldest entry to be replaced
*/
static struct {
spinlock_t lock;
struct host list[LIST_SIZE]; /* List of source addresses */
struct host *hash[HASH_SIZE]; /* Hash: pointers into the list */
int index; /* Oldest entry to be replaced */
struct host4 list[LIST_SIZE];
struct host *hash[HASH_SIZE];
int index;
} state;
#ifdef WITH_IPV6
/**
* State information for IPv6 portscan detection.
* @list: list of source addresses
* @hash: pointers into the list
* @index: oldest entry to be replaced
*/
static struct {
spinlock_t lock;
struct host6 *list;
struct host **hash;
int index;
} state6;
static struct host6 *host_to_host6(const struct host *h)
{
return (struct host6 *) h;
}
/**
* allocate state6 memory only when needed
*/
static bool state6_alloc_mem(void)
{
if (state6.hash != NULL)
return true;
state6.list = vmalloc(LIST_SIZE * sizeof(struct host6));
if (state6.list == NULL)
return false;
memset(state6.list, 0, LIST_SIZE * sizeof(struct host6));
state6.hash = vmalloc(HASH_SIZE * sizeof(struct host*));
if (state6.hash == NULL) {
vfree(state6.list);
return false;
}
memset(state6.hash, 0, HASH_SIZE * sizeof(struct host *));
return true;
}
#endif
/*
* Convert an IP address into a hash table index.
*/
static inline int hashfunc(struct in_addr addr)
static unsigned int hashfunc(__be32 addr)
{
unsigned int value;
int hash;
unsigned int hash;
value = addr.s_addr;
value = addr;
hash = 0;
do {
hash ^= value;
@@ -99,159 +171,169 @@ static inline int hashfunc(struct in_addr addr)
return hash & (HASH_SIZE - 1);
}
static bool
xt_psd_match(const struct sk_buff *pskb, struct xt_action_param *match)
static inline unsigned int hashfunc6(const struct in6_addr *addr)
{
__be32 h = addr->s6_addr32[0] ^ addr->s6_addr32[1];
return hashfunc(h ^ addr->s6_addr32[2] ^ addr->s6_addr32[3]);
}
static bool port_in_list(struct host *host, uint8_t proto, uint16_t port)
{
unsigned int i;
for (i = 0; i < host->count; ++i) {
if (host->ports[i].proto != proto)
continue;
if (host->ports[i].number == port)
return true;
}
return false;
}
static uint16_t get_port_weight(const struct xt_psd_info *psd, __be16 port)
{
return ntohs(port) < 1024 ? psd->lo_ports_weight : psd->hi_ports_weight;
}
static bool
is_portscan(struct host *host, const struct xt_psd_info *psdinfo,
const struct tcphdr *tcph, uint8_t proto)
{
if (port_in_list(host, proto, tcph->dest))
return false;
/*
* TCP/ACK and/or TCP/RST to a new port? This could be an
* outgoing connection.
*/
if (proto == IPPROTO_TCP && (tcph->ack || tcph->rst))
return false;
host->timestamp = jiffies;
if (host->weight >= psdinfo->weight_threshold) /* already matched */
return true;
/* Update the total weight */
host->weight += get_port_weight(psdinfo, tcph->dest);
/* Got enough destination ports to decide that this is a scan? */
if (host->weight >= psdinfo->weight_threshold)
return true;
/* Remember the new port */
if (host->count < ARRAY_SIZE(host->ports)) {
host->ports[host->count].number = tcph->dest;
host->ports[host->count].proto = proto;
host->count++;
}
return false;
}
static struct host *host_get_next(struct host *h, struct host **last)
{
if (h->next != NULL)
*last = h;
return h->next;
}
static void ht_unlink(struct host **head, struct host *last)
{
if (last != NULL)
last->next = last->next->next;
else if (*head != NULL)
*head = (*head)->next;
}
static bool
entry_is_recent(const struct host *h, unsigned long delay_threshold,
unsigned long now)
{
return now - h->timestamp <= (delay_threshold * HZ) / 100 &&
time_after_eq(now, h->timestamp);
}
static void remove_oldest(struct host **head, struct host *curr)
{
struct host *h, *last = NULL;
/*
* We are going to re-use the oldest list entry, so remove it from the
* hash table first, if it is really already in use.
*/
h = *head;
while (h != NULL) {
if (curr == h)
break;
last = h;
h = h->next;
}
/* Then, remove it */
if (h != NULL)
ht_unlink(head, last);
}
static void *
get_header_pointer4(const struct sk_buff *skb, unsigned int thoff, void *mem)
{
const struct iphdr *iph = ip_hdr(skb);
int hdrlen;
switch (iph->protocol) {
case IPPROTO_TCP:
hdrlen = sizeof(struct tcphdr);
break;
case IPPROTO_UDP:
case IPPROTO_UDPLITE:
hdrlen = sizeof(struct udphdr);
break;
default:
return NULL;
}
return skb_header_pointer(skb, thoff, hdrlen, mem);
}
static bool
handle_packet4(const struct iphdr *iph, const struct tcphdr *tcph,
const struct xt_psd_info *psdinfo, unsigned int hash)
{
const struct iphdr *iph;
const struct tcphdr *tcph = NULL;
const struct udphdr *udph;
union {
struct tcphdr tcph;
struct udphdr udph;
} _buf;
struct in_addr addr;
u_int16_t src_port,dest_port;
u_int8_t tcp_flags, proto;
unsigned long now;
struct host *curr, *last, **head;
int hash, index, count;
/* Parameters from userspace */
const struct xt_psd_info *psdinfo = match->matchinfo;
struct host *curr, *last = NULL, **head;
struct host4 *curr4;
int count = 0;
/* IP header */
iph = ip_hdr(pskb);
/* Sanity check */
if (iph->frag_off & htons(IP_OFFSET)) {
pr_debug("sanity check failed\n");
return false;
}
/* TCP or UDP ? */
proto = iph->protocol;
/* Get the source address, source & destination ports, and TCP flags */
addr.s_addr = iph->saddr;
/* We're using IP address 0.0.0.0 for a special purpose here, so don't let
* them spoof us. [DHCP needs this feature - HW] */
if (addr.s_addr == 0) {
pr_debug("spoofed source address (0.0.0.0)\n");
return false;
}
if (proto == IPPROTO_TCP) {
tcph = skb_header_pointer(pskb, match->thoff,
sizeof(_buf.tcph), &_buf.tcph);
if (tcph == NULL)
return false;
/* Yep, it's dirty */
src_port = tcph->source;
dest_port = tcph->dest;
tcp_flags = *((u_int8_t*)tcph + 13);
} else if (proto == IPPROTO_UDP || proto == IPPROTO_UDPLITE) {
udph = skb_header_pointer(pskb, match->thoff,
sizeof(_buf.udph), &_buf.udph);
if (udph == NULL)
return false;
src_port = udph->source;
dest_port = udph->dest;
tcp_flags = 0;
} else {
pr_debug("protocol not supported\n");
return false;
}
/* Use jiffies here not to depend on someone setting the time while we're
* running; we need to be careful with possible return value overflows. */
now = jiffies;
spin_lock(&state.lock);
head = &state.hash[hash];
/* Do we know this source address already? */
count = 0;
last = NULL;
if ((curr = *(head = &state.hash[hash = hashfunc(addr)])) != NULL)
do {
if (curr->src_addr.s_addr == addr.s_addr)
break;
count++;
if (curr->next != NULL)
last = curr;
} while ((curr = curr->next) != NULL);
curr = *head;
while (curr != NULL) {
curr4 = host_to_host4(curr);
if (curr4->saddr == iph->saddr)
break;
count++;
curr = host_get_next(curr, &last);
}
if (curr != NULL) {
/* We know this address, and the entry isn't too old. Update it. */
if (now - curr->timestamp <= (psdinfo->delay_threshold*HZ)/100 &&
time_after_eq(now, curr->timestamp)) {
/* Just update the appropriate list entry if we've seen this port already */
for (index = 0; index < curr->count; index++) {
if (curr->ports[index].number == dest_port) {
curr->ports[index].proto = proto;
curr->ports[index].and_flags &= tcp_flags;
curr->ports[index].or_flags |= tcp_flags;
goto out_no_match;
}
}
/* TCP/ACK and/or TCP/RST to a new port? This could be an outgoing connection. */
if (proto == IPPROTO_TCP && (tcph->ack || tcph->rst))
goto out_no_match;
/* Packet to a new port, and not TCP/ACK: update the timestamp */
curr->timestamp = now;
/* Logged this scan already? Then drop the packet. */
if (curr->weight >= psdinfo->weight_threshold)
goto out_match;
/* Specify if destination address, source port, TOS or TTL are not fixed */
if (curr->dest_addr.s_addr != iph->daddr)
curr->flags |= HF_DADDR_CHANGING;
if (curr->src_port != src_port)
curr->flags |= HF_SPORT_CHANGING;
if (curr->tos != iph->tos)
curr->flags |= HF_TOS_CHANGING;
if (curr->ttl != iph->ttl)
curr->flags |= HF_TTL_CHANGING;
/* Update the total weight */
curr->weight += (ntohs(dest_port) < 1024) ?
psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
/* Got enough destination ports to decide that this is a scan? */
/* Then log it and drop the packet. */
if (curr->weight >= psdinfo->weight_threshold)
goto out_match;
/* Remember the new port */
if (curr->count < SCAN_MAX_COUNT) {
curr->ports[curr->count].number = dest_port;
curr->ports[curr->count].proto = proto;
curr->ports[curr->count].and_flags = tcp_flags;
curr->ports[curr->count].or_flags = tcp_flags;
curr->count++;
}
goto out_no_match;
}
if (entry_is_recent(curr, psdinfo->delay_threshold, now))
return is_portscan(curr, psdinfo, tcph, iph->protocol);
/* We know this address, but the entry is outdated. Mark it unused, and
* remove from the hash table. We'll allocate a new entry instead since
* this one might get re-used too soon. */
curr->src_addr.s_addr = 0;
if (last != NULL)
last->next = last->next->next;
else if (*head != NULL)
*head = (*head)->next;
curr4 = host_to_host4(curr);
curr4->saddr = 0;
ht_unlink(head, last);
last = NULL;
}
/* We don't need an ACK from a new source address */
if (proto == IPPROTO_TCP && tcph->ack)
goto out_no_match;
if (iph->protocol == IPPROTO_TCP && tcph->ack)
return false;
/* Got too many source addresses with the same hash value? Then remove the
* oldest one from the hash table, so that they can't take too much of our
@@ -259,33 +341,15 @@ xt_psd_match(const struct sk_buff *pskb, struct xt_action_param *match)
if (count >= HASH_MAX && last != NULL)
last->next = NULL;
/* We're going to re-use the oldest list entry, so remove it from the hash
* table first (if it is really already in use, and isn't removed from the
* hash table already because of the HASH_MAX check above). */
/* First, find it */
if (state.list[state.index].src_addr.s_addr != 0)
head = &state.hash[hashfunc(state.list[state.index].src_addr)];
if (state.list[state.index].saddr != 0)
head = &state.hash[hashfunc(state.list[state.index].saddr)];
else
head = &last;
last = NULL;
if ((curr = *head) != NULL)
do {
if (curr == &state.list[state.index])
break;
last = curr;
} while ((curr = curr->next) != NULL);
/* Then, remove it */
if (curr != NULL) {
if (last != NULL)
last->next = last->next->next;
else if (*head != NULL)
*head = (*head)->next;
}
/* Get our list entry */
curr = &state.list[state.index++];
curr4 = &state.list[state.index++];
curr = &curr4->host;
remove_oldest(head, curr);
if (state.index >= LIST_SIZE)
state.index = 0;
@@ -295,46 +359,241 @@ xt_psd_match(const struct sk_buff *pskb, struct xt_action_param *match)
*head = curr;
/* And fill in the fields */
curr4 = host_to_host4(curr);
curr4->saddr = iph->saddr;
curr->timestamp = now;
curr->src_addr = addr;
curr->dest_addr.s_addr = iph->daddr;
curr->src_port = src_port;
curr->count = 1;
curr->weight = (ntohs(dest_port) < 1024) ? psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
curr->ports[0].number = dest_port;
curr->ports[0].proto = proto;
curr->ports[0].and_flags = tcp_flags;
curr->ports[0].or_flags = tcp_flags;
curr->tos = iph->tos;
curr->ttl = iph->ttl;
out_no_match:
spin_unlock(&state.lock);
curr->weight = get_port_weight(psdinfo, tcph->dest);
curr->ports[0].number = tcph->dest;
curr->ports[0].proto = iph->protocol;
return false;
out_match:
spin_unlock(&state.lock);
return true;
}
static struct xt_match xt_psd_reg __read_mostly = {
.name = "psd",
.family = NFPROTO_IPV4,
.revision = 1,
.match = xt_psd_match,
.matchsize = sizeof(struct xt_psd_info),
.me = THIS_MODULE,
static bool
xt_psd_match(const struct sk_buff *pskb, struct xt_action_param *match)
{
struct iphdr *iph = ip_hdr(pskb);
struct tcphdr _tcph;
struct tcphdr *tcph;
bool matched;
unsigned int hash;
/* Parameters from userspace */
const struct xt_psd_info *psdinfo = match->matchinfo;
if (iph->frag_off & htons(IP_OFFSET)) {
pr_debug("sanity check failed\n");
return false;
}
/*
* We are using IP address 0.0.0.0 for a special purpose here, so do
* not let them spoof us. [DHCP needs this feature - HW]
*/
if (iph->saddr == 0) {
pr_debug("spoofed source address (0.0.0.0)\n");
return false;
}
tcph = get_header_pointer4(pskb, match->thoff, &_tcph);
if (tcph == NULL)
return false;
hash = hashfunc(iph->saddr);
spin_lock(&state.lock);
matched = handle_packet4(iph, tcph, psdinfo, hash);
spin_unlock(&state.lock);
return matched;
}
#ifdef WITH_IPV6
static bool
handle_packet6(const struct ipv6hdr *ip6h, const struct tcphdr *tcph,
const struct xt_psd_info *psdinfo, uint8_t proto, int hash)
{
unsigned long now;
struct host *curr, *last = NULL, **head;
struct host6 *curr6;
int count = 0;
now = jiffies;
head = &state6.hash[hash];
curr = *head;
while (curr != NULL) {
curr6 = host_to_host6(curr);
if (ipv6_addr_equal(&curr6->saddr, &ip6h->saddr))
break;
count++;
curr = host_get_next(curr, &last);
}
if (curr != NULL) {
if (entry_is_recent(curr, psdinfo->delay_threshold, now))
return is_portscan(curr, psdinfo, tcph, proto);
curr6 = host_to_host6(curr);
memset(&curr6->saddr, 0, sizeof(curr6->saddr));
ht_unlink(head, last);
last = NULL;
}
if (proto == IPPROTO_TCP && tcph->ack)
return false;
if (count >= HASH_MAX && last != NULL)
last->next = NULL;
if (!ipv6_addr_any(&state6.list[state6.index].saddr))
head = &state6.hash[hashfunc6(&state6.list[state6.index].saddr)];
else
head = &last;
curr6 = &state6.list[state6.index++];
curr = &curr6->host;
remove_oldest(head, curr);
if (state6.index >= LIST_SIZE)
state6.index = 0;
head = &state6.hash[hash];
curr->next = *head;
*head = curr;
curr6 = host_to_host6(curr);
curr6->saddr = ip6h->saddr;
curr->timestamp = now;
curr->count = 1;
curr->weight = get_port_weight(psdinfo, tcph->dest);
curr->ports[0].number = tcph->dest;
curr->ports[0].proto = proto;
return false;
}
static void *
get_header_pointer6(const struct sk_buff *skb, void *mem, uint8_t *proto)
{
static const uint8_t types[] = {IPPROTO_TCP,
IPPROTO_UDP, IPPROTO_UDPLITE};
unsigned int i, offset = 0;
int err;
size_t hdrlen;
for (i = 0; i < ARRAY_SIZE(types); ++i) {
err = ipv6_find_hdr(skb, &offset, types[i], NULL, NULL);
if (err < 0)
continue;
switch (types[i]) {
case IPPROTO_TCP:
hdrlen = sizeof(struct tcphdr);
break;
case IPPROTO_UDP:
case IPPROTO_UDPLITE:
hdrlen = sizeof(struct udphdr);
break;
default:
return NULL;
}
*proto = types[i];
return skb_header_pointer(skb, offset, hdrlen, mem);
}
return NULL;
}
static bool
xt_psd_match6(const struct sk_buff *pskb, struct xt_action_param *match)
{
const struct ipv6hdr *ip6h = ipv6_hdr(pskb);
struct tcphdr _tcph;
struct tcphdr *tcph;
uint8_t proto = 0;
bool matched;
int hash;
const struct xt_psd_info *psdinfo = match->matchinfo;
if (ipv6_addr_any(&ip6h->saddr))
return false;
tcph = get_header_pointer6(pskb, &_tcph, &proto);
if (tcph == NULL)
return false;
hash = hashfunc6(&ip6h->saddr);
spin_lock(&state6.lock);
matched = handle_packet6(ip6h, tcph, psdinfo, proto, hash);
spin_unlock(&state6.lock);
return matched;
}
#endif
static int psd_mt_check(const struct xt_mtchk_param *par)
{
const struct xt_psd_info *info = par->matchinfo;
if (info->weight_threshold == 0)
/* 0 would match on every 1st packet */
return -EINVAL;
if ((info->lo_ports_weight | info->hi_ports_weight) == 0)
/* would never match */
return -EINVAL;
if (info->delay_threshold > PSD_MAX_RATE ||
info->weight_threshold > PSD_MAX_RATE ||
info->lo_ports_weight > PSD_MAX_RATE ||
info->hi_ports_weight > PSD_MAX_RATE)
return -EINVAL;
return 0;
}
#ifdef WITH_IPV6
static int psd_mt_check6(const struct xt_mtchk_param *par)
{
if (!state6_alloc_mem())
return -ENOMEM;
return psd_mt_check(par);
}
#endif
static struct xt_match xt_psd_reg[] __read_mostly = {
{
.name = "psd",
.family = NFPROTO_IPV4,
.revision = 1,
.checkentry = psd_mt_check,
.match = xt_psd_match,
.matchsize = sizeof(struct xt_psd_info),
.me = THIS_MODULE,
#ifdef WITH_IPV6
}, {
.name = "psd",
.family = NFPROTO_IPV6,
.revision = 1,
.checkentry = psd_mt_check6,
.match = xt_psd_match6,
.matchsize = sizeof(struct xt_psd_info),
.me = THIS_MODULE,
#endif
}
};
static int __init xt_psd_init(void)
{
spin_lock_init(&(state.lock));
return xt_register_match(&xt_psd_reg);
#ifdef WITH_IPV6
spin_lock_init(&(state6.lock));
#endif
return xt_register_matches(xt_psd_reg, ARRAY_SIZE(xt_psd_reg));
}
static void __exit xt_psd_exit(void)
{
xt_unregister_match(&xt_psd_reg);
xt_unregister_matches(xt_psd_reg, ARRAY_SIZE(xt_psd_reg));
#ifdef WITH_IPV6
vfree(state6.list);
vfree(state6.hash);
#endif
}
module_init(xt_psd_init);

View File

@@ -19,17 +19,6 @@
#define SCAN_MIN_COUNT 7
#define SCAN_MAX_COUNT (SCAN_MIN_COUNT * PORT_WEIGHT_PRIV)
#define SCAN_WEIGHT_THRESHOLD SCAN_MAX_COUNT
#define SCAN_DELAY_THRESHOLD (300) /* old usage of HZ here was erroneously and broke under uml */
/*
* 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
* HASH_MAX source addresses per the same hash value.
*/
#define LIST_SIZE 0x100
#define HASH_LOG 9
#define HASH_SIZE (1 << HASH_LOG)
#define HASH_MAX 0x10
struct xt_psd_info {
__u32 weight_threshold;

View File

@@ -1,7 +1,7 @@
/*
* xt_quota2 - enhanced xt_quota that can count upwards and in packets
* as a minimal accounting match.
* by Jan Engelhardt <jengelh@medozas.de>, 2008
* by Jan Engelhardt , 2008
*
* Originally based on xt_quota.c:
* Xtables module to enforce network quotas
@@ -69,6 +69,8 @@ static int quota_proc_write(struct file *file, const char __user *input,
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);
@@ -209,13 +211,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;
}
@@ -230,7 +233,7 @@ static struct xt_match quota_mt2_reg[] __read_mostly = {
.family = NFPROTO_IPV4,
.checkentry = quota_mt2_check,
.match = quota_mt2,
.destroy = quota_mt2_destroy,
.destroy = quota_mt2_destroy,
.matchsize = sizeof(struct xt_quota_mtinfo2),
.me = THIS_MODULE,
},
@@ -240,7 +243,7 @@ static struct xt_match quota_mt2_reg[] __read_mostly = {
.family = NFPROTO_IPV6,
.checkentry = quota_mt2_check,
.match = quota_mt2,
.destroy = quota_mt2_destroy,
.destroy = quota_mt2_destroy,
.matchsize = sizeof(struct xt_quota_mtinfo2),
.me = THIS_MODULE,
},
@@ -270,7 +273,7 @@ module_init(quota_mt2_init);
module_exit(quota_mt2_exit);
MODULE_DESCRIPTION("Xtables: countdown quota match; up counter");
MODULE_AUTHOR("Sam Johnston <samj@samj.net>");
MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>");
MODULE_AUTHOR("Jan Engelhardt ");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_quota2");
MODULE_ALIAS("ip6t_quota2");

View File

@@ -1,9 +1,7 @@
#!/usr/bin/perl
#
# Converter for MaxMind CSV database to binary, for xt_geoip
# Copyright © Jan Engelhardt <jengelh@medozas.de>, 2008-2011
#
# Use -b argument to create big-endian tables.
# Copyright © Jan Engelhardt, 2008-2011
#
use Getopt::Long;
use IO::Handle;

View File

@@ -9,8 +9,6 @@ build_DNETMAP=m
build_ECHO=m
build_IPMARK=m
build_LOGMARK=m
build_RAWNAT=m
build_STEAL=m
build_SYSRQ=m
build_TARPIT=m
build_TEE=

View File

@@ -1,4 +1,4 @@
.TH xtables-addons 8 "v1.42 (2012-04-05)" "" "v1.42 (2012-04-05)"
.TH xtables-addons 8 "v1.47.1 (2012-10-15)" "" "v1.47.1 (2012-10-15)"
.SH Name
Xtables-addons \(em additional extensions for iptables, ip6tables, etc.
.SH Targets
@@ -9,5 +9,5 @@ Xtables-addons \(em additional extensions for iptables, ip6tables, etc.
\fBiptables\fP(8), \fBip6tables\fP(8), \fBiptaccount\fP(8)
.PP
For developers, the book "Writing Netfilter modules" at
http://jengelh.medozas.de/documents/Netfilter_Modules.pdf provides detailed
http://inai.de/documents/Netfilter_Modules.pdf provides detailed
information on how to write such modules/extensions.