mirror of
git://git.code.sf.net/p/xtables-addons/xtables-addons
synced 2026-04-21 03:19:40 +02:00
Compare commits
109 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e2ecff2071 | ||
|
|
b2bcedd1ef | ||
|
|
36c349054e | ||
|
|
95da880d39 | ||
|
|
3be26a731b | ||
|
|
38db58adc1 | ||
|
|
0f302b7b2f | ||
|
|
d66d07d01d | ||
|
|
3736a265d8 | ||
|
|
5b2649b1a2 | ||
|
|
f6b8767228 | ||
|
|
ac58f2e94b | ||
|
|
7cc774641a | ||
|
|
492236f931 | ||
|
|
1e8da7c31c | ||
|
|
3f1202c211 | ||
|
|
759546f8d0 | ||
|
|
72b1421783 | ||
|
|
0b3d1bc4f0 | ||
|
|
3679e0efa6 | ||
|
|
517b8c66b5 | ||
|
|
7ee9feb20e | ||
|
|
f830dbd34e | ||
|
|
916013cd89 | ||
|
|
a6b06502ca | ||
|
|
aee5aedc63 | ||
|
|
54d784ffdf | ||
|
|
076610e3af | ||
|
|
7a1ad32d1a | ||
|
|
40094379dd | ||
|
|
ce37dd6984 | ||
|
|
31fdd86247 | ||
|
|
36df60c940 | ||
|
|
2b671829d8 | ||
|
|
9ab6a0ee0d | ||
|
|
365d5edfb3 | ||
|
|
75cd1d7d6a | ||
|
|
b0dc0e6f4c | ||
|
|
bc1c37618a | ||
|
|
d7aeb7da4b | ||
|
|
487da26146 | ||
|
|
434dea2b53 | ||
|
|
30d227135b | ||
|
|
a508ec048c | ||
|
|
3069c9a3a2 | ||
|
|
5245220246 | ||
|
|
ec97cd6d89 | ||
|
|
dc58126e37 | ||
|
|
d509951fcf | ||
|
|
6ef91897b2 | ||
|
|
c7f60a33c5 | ||
|
|
65b75fc19c | ||
|
|
bac406bff5 | ||
|
|
aa53733851 | ||
|
|
9ccd32d840 | ||
|
|
939d3c8b27 | ||
|
|
c2d93e16fd | ||
|
|
04aed87cb6 | ||
|
|
5ef3a7c436 | ||
|
|
27a77b62f5 | ||
|
|
c10e974bd6 | ||
|
|
01d864f4fc | ||
|
|
071c95b750 | ||
|
|
a141cc311c | ||
|
|
7e92ce7ce6 | ||
|
|
21da1dfea5 | ||
|
|
6c17eb46b5 | ||
|
|
74ea647303 | ||
|
|
e0154bfa4c | ||
|
|
cd18e2479c | ||
|
|
d2f3541cda | ||
|
|
1fed8bbf09 | ||
|
|
6e8fb7f231 | ||
|
|
eceaee3431 | ||
|
|
77b29a62ee | ||
|
|
33db992c39 | ||
|
|
85d8f98dd7 | ||
|
|
e84391ce66 | ||
|
|
ef7fb0db7f | ||
|
|
4203259e5a | ||
|
|
e3956498ac | ||
|
|
6f730f3ab2 | ||
|
|
2b590a35fd | ||
|
|
3dd33dfe93 | ||
|
|
d417077816 | ||
|
|
d057f6d6f0 | ||
|
|
b2fc85c589 | ||
|
|
fa1348455d | ||
|
|
1a5c079e6b | ||
|
|
75b3762ef4 | ||
|
|
cfb72bf468 | ||
|
|
1b0790d151 | ||
|
|
a5355e74ea | ||
|
|
757bf0e993 | ||
|
|
cea4817a46 | ||
|
|
2dc79fe008 | ||
|
|
b60f8f1de2 | ||
|
|
499c6db75e | ||
|
|
509953daec | ||
|
|
c53a86874d | ||
|
|
309b960012 | ||
|
|
f4882ca029 | ||
|
|
8fd3eb56eb | ||
|
|
94574fb829 | ||
|
|
32871bad39 | ||
|
|
0ba44bd461 | ||
|
|
d4e6e3d155 | ||
|
|
18043f3e3a | ||
|
|
ff27f61477 |
12
.gitignore
vendored
12
.gitignore
vendored
@@ -2,9 +2,9 @@
|
||||
*.lo
|
||||
*.loT
|
||||
*.o
|
||||
.deps
|
||||
.deps/
|
||||
.dirstamp
|
||||
.libs
|
||||
.libs/
|
||||
Makefile
|
||||
Makefile.in
|
||||
|
||||
@@ -17,14 +17,10 @@ Makefile.in
|
||||
/targets.man
|
||||
|
||||
/aclocal.m4
|
||||
/autom4te*.cache
|
||||
/compile
|
||||
/autom4te.cache/
|
||||
/build-aux/
|
||||
/config.*
|
||||
/configure
|
||||
/depcomp
|
||||
/install-sh
|
||||
/libtool
|
||||
/ltmain.sh
|
||||
/missing
|
||||
/stamp-h1
|
||||
/xtables-addons.8
|
||||
|
||||
20
INSTALL
20
INSTALL
@@ -12,9 +12,9 @@ in combination with the kernel's Kbuild system.
|
||||
Supported configurations for this release
|
||||
=========================================
|
||||
|
||||
* iptables >= 1.4.3
|
||||
* iptables >= 1.4.5
|
||||
|
||||
* kernel-source >= 2.6.17, no upper bound known
|
||||
* kernel-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
|
||||
@@ -22,18 +22,6 @@ Supported configurations for this release
|
||||
- CONFIG_CONNECTOR y/m if you wish to receive userspace
|
||||
notifications from pknock through netlink/connector
|
||||
|
||||
Extra notes:
|
||||
|
||||
* in the kernel 2.6.18.x series, >= 2.6.18.5 is required
|
||||
|
||||
* requires that no vendor backports interfere
|
||||
|
||||
For ipset-5 you need:
|
||||
|
||||
* libmnl
|
||||
|
||||
* Linux kernel >= 2.6.35
|
||||
|
||||
|
||||
Selecting extensions
|
||||
====================
|
||||
@@ -47,6 +35,10 @@ Configuring and compiling
|
||||
|
||||
./configure [options]
|
||||
|
||||
--without-kbuild
|
||||
|
||||
Deactivate building kernel modules, and just do userspace parts.
|
||||
|
||||
--with-kbuild=
|
||||
|
||||
Specifies the path to the kernel build output directory. We need
|
||||
|
||||
2
README
2
README
@@ -18,8 +18,6 @@ simplified, and sped up.
|
||||
|
||||
Included in this package
|
||||
========================
|
||||
- ipset 4.5
|
||||
- ipset 5.4.1
|
||||
- xt_ACCOUNT 1.16, libxt_ACCOUNT 1.3
|
||||
|
||||
|
||||
|
||||
39
configure.ac
39
configure.ac
@@ -1,17 +1,20 @@
|
||||
|
||||
AC_INIT([xtables-addons], [1.33])
|
||||
AC_INIT([xtables-addons], [1.43])
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
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
|
||||
|
||||
AC_ARG_WITH([kbuild],
|
||||
AS_HELP_STRING([--with-kbuild=PATH],
|
||||
[Path to kernel build directory [[/lib/modules/CURRENT/build]]]),
|
||||
[Path to kernel build directory [[/lib/modules/CURRENT/build]]])
|
||||
AS_HELP_STRING([--without-kbuild],
|
||||
[Build only userspace tools]),
|
||||
[kbuilddir="$withval"],
|
||||
[kbuilddir="/lib/modules/$(uname -r)/build"])
|
||||
#
|
||||
@@ -23,9 +26,8 @@ fi
|
||||
|
||||
AC_CHECK_HEADERS([linux/netfilter/x_tables.h], [],
|
||||
[AC_MSG_ERROR([You need to have linux/netfilter/x_tables.h, see INSTALL file for details])])
|
||||
PKG_CHECK_MODULES([libxtables], [xtables >= 1.4.3])
|
||||
PKG_CHECK_MODULES([libxtables], [xtables >= 1.4.5])
|
||||
xtlibdir="$(pkg-config --variable=xtlibdir xtables)"
|
||||
PKG_CHECK_MODULES([libmnl], [libmnl >= 1], [:], [:])
|
||||
|
||||
AC_ARG_WITH([xtlibdir],
|
||||
AS_HELP_STRING([--with-xtlibdir=PATH],
|
||||
@@ -40,18 +42,9 @@ regular_CFLAGS="-Wall -Waggregate-return -Wmissing-declarations \
|
||||
-Wmissing-prototypes -Wredundant-decls -Wshadow -Wstrict-prototypes \
|
||||
-Winline -pipe";
|
||||
|
||||
#
|
||||
# check kernel version
|
||||
#
|
||||
if grep -q "CentOS release 5\." /etc/redhat-release 2>/dev/null ||
|
||||
grep -q "Red Hat Enterprise Linux Server release 5" /etc/redhat-release 2>/dev/null; then
|
||||
# しまった!
|
||||
# Well, just a warning. Maybe the admin updated the kernel.
|
||||
echo "WARNING: This distribution's shipped kernel is not supported.";
|
||||
fi;
|
||||
if test -n "$kbuilddir"; then
|
||||
AC_MSG_CHECKING([kernel version that we will build against])
|
||||
krel="$(make -sC "$kbuilddir" M=. kernelrelease)";
|
||||
krel="$(make -sC "$kbuilddir" M=$PWD kernelrelease)";
|
||||
kmajor="${krel%%[[^0-9]]*}";
|
||||
kmajor="$(($kmajor+0))";
|
||||
krel="${krel:${#kmajor}}";
|
||||
@@ -70,15 +63,14 @@ 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 2 -o "$kminor" -gt 6 -o "$kmicro" -gt 38; then
|
||||
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. :-)";
|
||||
elif test \( "$kmajor" -lt 2 -o \
|
||||
\( "$kmajor" -eq 2 -a "$kminor" -lt 6 \) -o \
|
||||
\( "$kmajor" -eq 2 -a "$kminor" -eq 0 -a "$kmicro" -lt 17 \) -o \
|
||||
\( "$kmajor" -eq 2 -a "$kminor" -eq 6 -a "$kmicro" -eq 18 -a \
|
||||
"$kstable" -lt 5 \) \); then
|
||||
echo "ERROR: That kernel version is not supported. Please see INSTALL for minimum configuration.";
|
||||
exit 1;
|
||||
elif test "$kmajor" -eq 3; then
|
||||
:;
|
||||
elif test "$kmajor" -eq 2 -a "$kminor" -eq 6 -a "$kmicro" -ge 32; then
|
||||
:;
|
||||
else
|
||||
echo "WARNING: That kernel version is not officially supported.";
|
||||
fi;
|
||||
fi;
|
||||
fi;
|
||||
@@ -89,6 +81,5 @@ AC_SUBST([kbuilddir])
|
||||
AC_SUBST([xtlibdir])
|
||||
AC_CONFIG_FILES([Makefile Makefile.iptrules Makefile.mans geoip/Makefile
|
||||
extensions/Makefile extensions/ACCOUNT/Makefile
|
||||
extensions/ipset-4/Makefile extensions/ipset-5/Makefile
|
||||
extensions/pknock/Makefile])
|
||||
AC_OUTPUT
|
||||
|
||||
@@ -13,7 +13,7 @@ match:
|
||||
int *hotdrop,
|
||||
);
|
||||
|
||||
/* error code */
|
||||
/* true/false */
|
||||
int
|
||||
(*checkentry)(
|
||||
const char *tablename,
|
||||
@@ -45,7 +45,7 @@ target:
|
||||
void *userdata,
|
||||
);
|
||||
|
||||
/* error code */
|
||||
/* true/false */
|
||||
int
|
||||
(*checkentry)(
|
||||
const char *tablename,
|
||||
|
||||
@@ -13,7 +13,7 @@ match:
|
||||
int *hotdrop,
|
||||
);
|
||||
|
||||
/* error code */
|
||||
/* true/false */
|
||||
int
|
||||
(*checkentry)(
|
||||
const char *tablename,
|
||||
@@ -42,7 +42,7 @@ target:
|
||||
const void *targinfo,
|
||||
);
|
||||
|
||||
/* error code */
|
||||
/* true/false */
|
||||
int
|
||||
(*checkentry)(
|
||||
const char *tablename,
|
||||
|
||||
@@ -3,6 +3,128 @@ HEAD
|
||||
====
|
||||
|
||||
|
||||
v1.43 (2012-06-30)
|
||||
==================
|
||||
Fixes:
|
||||
- xt_psd: avoid crash due to curr->next corruption
|
||||
Changes:
|
||||
- xt_psd: reject invalid match options
|
||||
Enhancements:
|
||||
- Support for Linux 3.5
|
||||
- DNETMAP: new type: static binding
|
||||
- DNETMAP: new persistent flag option for prefix
|
||||
- DNETMAP: add write support to procfs interface
|
||||
|
||||
|
||||
v1.42 (2012-04-05)
|
||||
==================
|
||||
Fixes:
|
||||
- compat_xtables: fixed mistranslation of checkentry return values
|
||||
(affected kernels < 2.6.23)
|
||||
- xt_SYSRQ: fix compile error when crypto is turned off
|
||||
Changes:
|
||||
- ipset6-genl has been dropped from the tree;
|
||||
the libmnl build-time dependency is thus no longer needed
|
||||
Enhancements:
|
||||
- Support for Linux 3.3, 3.4
|
||||
|
||||
|
||||
v1.41 (2012-01-04)
|
||||
==================
|
||||
Changes:
|
||||
- Deactivate build of ipset-genl by default.
|
||||
I think the original ipset package can now take over, given there are
|
||||
a handful of kernels (2.6.39 onwards) that do not need patching.
|
||||
Enhancements:
|
||||
- Support for Linux 3.2
|
||||
|
||||
|
||||
v1.40 (2011-11-30)
|
||||
==================
|
||||
Fixes:
|
||||
- build: the code actually requires at least iptables 1.4.5 (would yield a
|
||||
compile error otherwise), make sure configure checks for it; update INSTALL
|
||||
- xt_ECHO: fix kernel warning about RTAX_HOPLIMIT being used
|
||||
- xt_ipv4options: fix an infinite loop
|
||||
Changes:
|
||||
- xt_ECHO: now calculates UDP checksum
|
||||
- Linux kernel versions below 2.6.32 are no longer officially
|
||||
supported, and will not be part of compilation testing.
|
||||
- update to ipset 6.10
|
||||
Enhancements:
|
||||
- xt_ECHO: IPv6 support
|
||||
|
||||
|
||||
v1.39 (2011-09-21)
|
||||
==================
|
||||
Fixes:
|
||||
- libxt_ACCOUNT: fix compilation after missing libxtables_CFLAGS
|
||||
- build: fix compilation after missing libxtables_CFLAGS in submodules
|
||||
- build: add missing linux/version.h includes where needed
|
||||
Changes:
|
||||
- Remove unsupported ipset 4.x from the Xtables-addons distribution
|
||||
- ipset: move ipset_errcode from src to library to avoid undefined reference
|
||||
- update to ipset 6.9.1
|
||||
|
||||
|
||||
v1.38 (2011-08-20)
|
||||
==================
|
||||
- xt_CHECKSUM: abort build when the feature is already provided by mainline
|
||||
- xt_SYSRQ: fix UDPLITE header lookup in IPv6
|
||||
- xt_TARPIT: fix kernel warning about RTAX_HOPLIMIT being used
|
||||
- xt_TEE: abort build when the feature is already provided by mainline
|
||||
- xt_ipp2p: support UDPLITE
|
||||
- xt_pknock: support UDPLITE
|
||||
- xt_psd: restore functionality with UDP
|
||||
- xt_psd: support UDPLITE
|
||||
- update to ipset 6.8
|
||||
- support for Linux 3.1
|
||||
|
||||
|
||||
v1.37 (2011-06-25)
|
||||
==================
|
||||
Fixes:
|
||||
- xt_SYSRQ: make IPv6 trigger work again
|
||||
- xt_SYSRQ: improve security: include host address in digest
|
||||
- xt_TARPIT: fix a kernel oops in --reset mode
|
||||
|
||||
|
||||
v1.36 (2011-06-03)
|
||||
==================
|
||||
Changes:
|
||||
- xt_geoip: avoid recursive function calls
|
||||
- xt_TARPIT: unlock for use in all tables
|
||||
- xt_TARPIT: honeypot and reset modes
|
||||
- update to ipset 6.7
|
||||
- support for Linux 3.0
|
||||
|
||||
|
||||
v1.35 (2011-04-11)
|
||||
==================
|
||||
Enhancements:
|
||||
- update to ipset 6.3
|
||||
* allow "new" as a commad alias to "create"
|
||||
* resolving IP addresses did not work at listing/saving sets, fixed
|
||||
* check ICMP and ICMPv6 with the set match and target in the testsuite
|
||||
* avoid possible syntax clashing at saving hostnames
|
||||
* fix linking with CONFIG_IPV6=n
|
||||
* sctp, udplite support for the hash:*port* types
|
||||
- ipset-genl: handle EAGAIN return value emitted from autoloader
|
||||
- ipset-genl: resolve nfgenmsg remains and fix spurious protocol abort
|
||||
|
||||
|
||||
v1.34 (2011-04-07)
|
||||
==================
|
||||
Fixes:
|
||||
- xt_pknock: avoid crash when hash TFM could not be allocated
|
||||
- xt_pknock: avoid inversion of rule lookup that led to warnings
|
||||
- xt_DNETMAP: add missing module alias
|
||||
- xt_DNETMAP: support for kernels below 2.6.34
|
||||
Changes:
|
||||
- Linux kernel versions below 2.6.29 are no longer officially
|
||||
supported, and will not be part of compilation testing.
|
||||
|
||||
|
||||
v1.33 (2011-02-02)
|
||||
==================
|
||||
Fixes:
|
||||
|
||||
2
extensions/.gitignore
vendored
2
extensions/.gitignore
vendored
@@ -1,6 +1,6 @@
|
||||
.*.cmd
|
||||
.*.d
|
||||
.tmp_versions
|
||||
.tmp_versions/
|
||||
*.ko
|
||||
*.mod.c
|
||||
Module.markers
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# -*- Makefile -*-
|
||||
|
||||
AM_CPPFLAGS = ${regular_CPPFLAGS} -I${abs_top_srcdir}/extensions
|
||||
AM_CFLAGS = ${regular_CFLAGS}
|
||||
AM_CFLAGS = ${regular_CFLAGS} ${libxtables_CFLAGS}
|
||||
|
||||
include ../../Makefile.extra
|
||||
|
||||
@@ -9,3 +9,5 @@ sbin_PROGRAMS = iptaccount
|
||||
iptaccount_LDADD = libxt_ACCOUNT_cl.la
|
||||
|
||||
lib_LTLIBRARIES = libxt_ACCOUNT_cl.la
|
||||
|
||||
man_MANS = iptaccount.8
|
||||
|
||||
26
extensions/ACCOUNT/iptaccount.8
Normal file
26
extensions/ACCOUNT/iptaccount.8
Normal file
@@ -0,0 +1,26 @@
|
||||
.TH iptaccount 8 "v1.16" "" "v1.16"
|
||||
.SH Name
|
||||
iptaccount \(em administrative utility to access xt_ACCOUNT statistics
|
||||
.SH Syntax
|
||||
\fBiptaccount\fP [\fB\-acfhu\fP] [\fB\-l\fP \fIname\fP]
|
||||
.SH Options
|
||||
.PP
|
||||
\fB\-a\fP
|
||||
List all (accounting) table names.
|
||||
.PP
|
||||
\fB\-c\fP
|
||||
Loop every second (abort with CTRL+C).
|
||||
.PP
|
||||
\fB\-f\fP
|
||||
Flush data after display.
|
||||
.PP
|
||||
\fB\-h\fP
|
||||
Free all kernel handles. (Experts only!)
|
||||
.PP
|
||||
\fB\-l\fP \fIname\fP
|
||||
Show data in accounting table called by \fIname\fP.
|
||||
.TP
|
||||
\fB\-u\fP
|
||||
Show kernel handle usage.
|
||||
.SH "See also"
|
||||
\fBxtables-addons\fP(8)
|
||||
@@ -40,19 +40,7 @@ to account the overall traffic to/from your internet provider.
|
||||
.PP
|
||||
The data can be queried using the userspace libxt_ACCOUNT_cl library,
|
||||
and by the reference implementation to show usage of this library,
|
||||
the \fBiptaccount\fP(8) tool, which features following options:
|
||||
.PP
|
||||
[\fB\-u\fP] show kernel handle usage
|
||||
.PP
|
||||
[\fB\-h\fP] free all kernel handles (experts only!)
|
||||
.PP
|
||||
[\fB\-a\fP] list all table names
|
||||
.PP
|
||||
[\fB\-l\fP \fIname\fP] show data in table \fIname\fP
|
||||
.PP
|
||||
[\fB\-f\fP] flush data after showing
|
||||
.PP
|
||||
[\fB\-c\fP] loop every second (abort with CTRL+C)
|
||||
the \fBiptaccount\fP(8) tool.
|
||||
.PP
|
||||
Here is an example of use:
|
||||
.PP
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
config NETFILTER_XT_TARGET_ACCOUNT
|
||||
tristate "ACCOUNT target support"
|
||||
depends on NETFILTER_XTABLES
|
||||
---help---
|
||||
This module implements an ACCOUNT target
|
||||
|
||||
The ACCOUNT target is a high performance accounting system for large
|
||||
local networks. It allows per-IP accounting in whole prefixes of IPv4
|
||||
addresses with size of up to /8 without the need to add individual
|
||||
accouting rule for each IP address.
|
||||
|
||||
For more information go to:
|
||||
http://www.intra2net.com/de/produkte/opensource/ipt_account/
|
||||
@@ -11,7 +11,9 @@ 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
|
||||
@@ -27,8 +29,6 @@ obj-${build_fuzzy} += xt_fuzzy.o
|
||||
obj-${build_geoip} += xt_geoip.o
|
||||
obj-${build_iface} += xt_iface.o
|
||||
obj-${build_ipp2p} += xt_ipp2p.o
|
||||
obj-${build_ipset4} += ipset-4/
|
||||
obj-${build_ipset5} += ipset-5/
|
||||
obj-${build_ipv4options} += xt_ipv4options.o
|
||||
obj-${build_length2} += xt_length2.o
|
||||
obj-${build_lscan} += xt_lscan.o
|
||||
|
||||
@@ -19,8 +19,6 @@ obj-${build_fuzzy} += libxt_fuzzy.so
|
||||
obj-${build_geoip} += libxt_geoip.so
|
||||
obj-${build_iface} += libxt_iface.so
|
||||
obj-${build_ipp2p} += libxt_ipp2p.so
|
||||
obj-${build_ipset4} += ipset-4/
|
||||
obj-${build_ipset5} += ipset-5/
|
||||
obj-${build_ipv4options} += libxt_ipv4options.so
|
||||
obj-${build_length2} += libxt_length2.so
|
||||
obj-${build_lscan} += libxt_lscan.so
|
||||
|
||||
@@ -8,15 +8,21 @@
|
||||
*/
|
||||
#include <linux/ip.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kmod.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/version.h>
|
||||
#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/route.h>
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
|
||||
# include <linux/export.h>
|
||||
#endif
|
||||
#include "compat_skbuff.h"
|
||||
#include "compat_xtnu.h"
|
||||
|
||||
@@ -105,11 +111,7 @@ static bool xtnu_match_check(const char *table, const void *entry,
|
||||
return false;
|
||||
if (nm->checkentry == NULL)
|
||||
return true;
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23)
|
||||
return nm->checkentry(&local_par);
|
||||
#else
|
||||
return nm->checkentry(&local_par) == 0;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) && \
|
||||
@@ -317,11 +319,7 @@ static bool xtnu_target_check(const char *table, const void *entry,
|
||||
if (nt->checkentry == NULL)
|
||||
/* this is valid, just like if there was no function */
|
||||
return true;
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23)
|
||||
return nt->checkentry(&local_par);
|
||||
#else
|
||||
return nt->checkentry(&local_par) == 0;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -615,4 +613,12 @@ void *HX_memmem(const void *space, size_t spacesize,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(HX_memmem);
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
@@ -92,6 +92,12 @@
|
||||
# define rt_dst(rt) (&(rt)->u.dst)
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
|
||||
# define nf_nat_ipv4_multi_range_compat nf_nat_multi_range_compat
|
||||
# define nf_nat_ipv4_range nf_nat_range
|
||||
# define NF_NAT_RANGE_MAP_IPS IP_NAT_RANGE_MAP_IPS
|
||||
#endif
|
||||
|
||||
#if !defined(NIP6) && !defined(NIP6_FMT)
|
||||
# define NIP6(addr) \
|
||||
ntohs((addr).s6_addr16[0]), \
|
||||
@@ -113,6 +119,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
|
||||
|
||||
@@ -162,6 +162,8 @@ 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_find_hdr(const struct sk_buff *, unsigned int *,
|
||||
int, unsigned short *, int *);
|
||||
|
||||
extern void *HX_memmem(const void *, size_t, const void *, size_t);
|
||||
|
||||
|
||||
1
extensions/ipset-4/.gitignore
vendored
1
extensions/ipset-4/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
/ipset
|
||||
@@ -1,7 +0,0 @@
|
||||
# -*- Makefile -*-
|
||||
|
||||
obj-m += ipt_set.o ipt_SET.o
|
||||
obj-m += ip_set.o ip_set_ipmap.o ip_set_portmap.o ip_set_macipmap.o
|
||||
obj-m += ip_set_iphash.o ip_set_nethash.o ip_set_ipporthash.o
|
||||
obj-m += ip_set_ipportiphash.o ip_set_ipportnethash.o
|
||||
obj-m += ip_set_iptree.o ip_set_iptreemap.o ip_set_setlist.o
|
||||
@@ -1,13 +0,0 @@
|
||||
# -*- Makefile -*-
|
||||
|
||||
AM_CPPFLAGS = ${regular_CPPFLAGS} -DIPSET_LIB_DIR=\"${xtlibdir}\" \
|
||||
-DIP_NF_SET_HASHSIZE=1024
|
||||
AM_CFLAGS = ${regular_CFLAGS}
|
||||
|
||||
include ../../Makefile.extra
|
||||
|
||||
sbin_PROGRAMS = ipset
|
||||
ipset_LDADD = -ldl
|
||||
ipset_LDFLAGS = -rdynamic
|
||||
|
||||
man_MANS = ipset.8
|
||||
@@ -1,7 +0,0 @@
|
||||
# -*- Makefile -*-
|
||||
|
||||
obj-m += $(addprefix lib,$(patsubst %.c,%.so,$(notdir \
|
||||
$(wildcard ${XA_SRCDIR}/ipset_*.c))))
|
||||
|
||||
libipset_%.oo: ${XA_SRCDIR}/ipset_%.c
|
||||
${AM_V_CC}${CC} ${AM_DEPFLAGS} ${AM_CPPFLAGS} ${AM_CFLAGS} -DPIC -fPIC ${CPPFLAGS} ${CFLAGS} -o $@ -c $<;
|
||||
@@ -1 +0,0 @@
|
||||
4.5
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,569 +0,0 @@
|
||||
#ifndef _IP_SET_H
|
||||
#define _IP_SET_H
|
||||
|
||||
/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
|
||||
* Patrick Schaaf <bof@bof.de>
|
||||
* Martin Josefsson <gandalf@wlug.westbo.se>
|
||||
* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_IP_NF_SET_MAX
|
||||
/* from 2 to 65534 */
|
||||
# define CONFIG_IP_NF_SET_MAX 256
|
||||
#endif
|
||||
#ifndef CONFIG_IP_NF_SET_HASHSIZE
|
||||
# define CONFIG_IP_NF_SET_HASHSIZE 1024
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#define IP_SET_DEBUG
|
||||
#endif
|
||||
|
||||
/*
|
||||
* A sockopt of such quality has hardly ever been seen before on the open
|
||||
* market! This little beauty, hardly ever used: above 64, so it's
|
||||
* traditionally used for firewalling, not touched (even once!) by the
|
||||
* 2.0, 2.2 and 2.4 kernels!
|
||||
*
|
||||
* Comes with its own certificate of authenticity, valid anywhere in the
|
||||
* Free world!
|
||||
*
|
||||
* Rusty, 19.4.2000
|
||||
*/
|
||||
#define SO_IP_SET 83
|
||||
|
||||
/*
|
||||
* Heavily modify by Joakim Axelsson 08.03.2002
|
||||
* - Made it more modulebased
|
||||
*
|
||||
* Additional heavy modifications by Jozsef Kadlecsik 22.02.2004
|
||||
* - bindings added
|
||||
* - in order to "deal with" backward compatibility, renamed to ipset
|
||||
*/
|
||||
|
||||
/*
|
||||
* Used so that the kernel module and ipset-binary can match their versions
|
||||
*/
|
||||
#define IP_SET_PROTOCOL_UNALIGNED 3
|
||||
#define IP_SET_PROTOCOL_VERSION 4
|
||||
|
||||
#define IP_SET_MAXNAMELEN 32 /* set names and set typenames */
|
||||
|
||||
/* Lets work with our own typedef for representing an IP address.
|
||||
* We hope to make the code more portable, possibly to IPv6...
|
||||
*
|
||||
* The representation works in HOST byte order, because most set types
|
||||
* will perform arithmetic operations and compare operations.
|
||||
*
|
||||
* For now the type is an uint32_t.
|
||||
*
|
||||
* Make sure to ONLY use the functions when translating and parsing
|
||||
* in order to keep the host byte order and make it more portable:
|
||||
* parse_ip()
|
||||
* parse_mask()
|
||||
* parse_ipandmask()
|
||||
* ip_tostring()
|
||||
* (Joakim: where are they???)
|
||||
*/
|
||||
|
||||
typedef uint32_t ip_set_ip_t;
|
||||
|
||||
/* Sets are identified by an id in kernel space. Tweak with ip_set_id_t
|
||||
* and IP_SET_INVALID_ID if you want to increase the max number of sets.
|
||||
*/
|
||||
typedef uint16_t ip_set_id_t;
|
||||
|
||||
#define IP_SET_INVALID_ID 65535
|
||||
|
||||
/* How deep we follow bindings */
|
||||
#define IP_SET_MAX_BINDINGS 6
|
||||
|
||||
/*
|
||||
* Option flags for kernel operations (ipt_set_info)
|
||||
*/
|
||||
#define IPSET_SRC 0x01 /* Source match/add */
|
||||
#define IPSET_DST 0x02 /* Destination match/add */
|
||||
#define IPSET_MATCH_INV 0x04 /* Inverse matching */
|
||||
|
||||
/*
|
||||
* Set features
|
||||
*/
|
||||
#define IPSET_TYPE_IP 0x01 /* IP address type of set */
|
||||
#define IPSET_TYPE_PORT 0x02 /* Port type of set */
|
||||
#define IPSET_DATA_SINGLE 0x04 /* Single data storage */
|
||||
#define IPSET_DATA_DOUBLE 0x08 /* Double data storage */
|
||||
#define IPSET_DATA_TRIPLE 0x10 /* Triple data storage */
|
||||
#define IPSET_TYPE_IP1 0x20 /* IP address type of set */
|
||||
#define IPSET_TYPE_SETNAME 0x40 /* setname type of set */
|
||||
|
||||
/* Reserved keywords */
|
||||
#define IPSET_TOKEN_DEFAULT ":default:"
|
||||
#define IPSET_TOKEN_ALL ":all:"
|
||||
|
||||
/* SO_IP_SET operation constants, and their request struct types.
|
||||
*
|
||||
* Operation ids:
|
||||
* 0-99: commands with version checking
|
||||
* 100-199: add/del/test/bind/unbind
|
||||
* 200-299: list, save, restore
|
||||
*/
|
||||
|
||||
/* Single shot operations:
|
||||
* version, create, destroy, flush, rename and swap
|
||||
*
|
||||
* Sets are identified by name.
|
||||
*/
|
||||
|
||||
#define IP_SET_REQ_STD \
|
||||
unsigned op; \
|
||||
unsigned version; \
|
||||
char name[IP_SET_MAXNAMELEN]
|
||||
|
||||
#define IP_SET_OP_CREATE 0x00000001 /* Create a new (empty) set */
|
||||
struct ip_set_req_create {
|
||||
IP_SET_REQ_STD;
|
||||
char typename[IP_SET_MAXNAMELEN];
|
||||
};
|
||||
|
||||
#define IP_SET_OP_DESTROY 0x00000002 /* Remove a (empty) set */
|
||||
struct ip_set_req_std {
|
||||
IP_SET_REQ_STD;
|
||||
};
|
||||
|
||||
#define IP_SET_OP_FLUSH 0x00000003 /* Remove all IPs in a set */
|
||||
/* Uses ip_set_req_std */
|
||||
|
||||
#define IP_SET_OP_RENAME 0x00000004 /* Rename a set */
|
||||
/* Uses ip_set_req_create */
|
||||
|
||||
#define IP_SET_OP_SWAP 0x00000005 /* Swap two sets */
|
||||
/* Uses ip_set_req_create */
|
||||
|
||||
union ip_set_name_index {
|
||||
char name[IP_SET_MAXNAMELEN];
|
||||
ip_set_id_t index;
|
||||
};
|
||||
|
||||
#define IP_SET_OP_GET_BYNAME 0x00000006 /* Get set index by name */
|
||||
struct ip_set_req_get_set {
|
||||
unsigned op;
|
||||
unsigned version;
|
||||
union ip_set_name_index set;
|
||||
};
|
||||
|
||||
#define IP_SET_OP_GET_BYINDEX 0x00000007 /* Get set name by index */
|
||||
/* Uses ip_set_req_get_set */
|
||||
|
||||
#define IP_SET_OP_VERSION 0x00000100 /* Ask kernel version */
|
||||
struct ip_set_req_version {
|
||||
unsigned op;
|
||||
unsigned version;
|
||||
};
|
||||
|
||||
/* Double shots operations:
|
||||
* add, del, test, bind and unbind.
|
||||
*
|
||||
* First we query the kernel to get the index and type of the target set,
|
||||
* then issue the command. Validity of IP is checked in kernel in order
|
||||
* to minimalize sockopt operations.
|
||||
*/
|
||||
|
||||
/* Get minimal set data for add/del/test/bind/unbind IP */
|
||||
#define IP_SET_OP_ADT_GET 0x00000010 /* Get set and type */
|
||||
struct ip_set_req_adt_get {
|
||||
unsigned op;
|
||||
unsigned version;
|
||||
union ip_set_name_index set;
|
||||
char typename[IP_SET_MAXNAMELEN];
|
||||
};
|
||||
|
||||
#define IP_SET_REQ_BYINDEX \
|
||||
unsigned op; \
|
||||
ip_set_id_t index;
|
||||
|
||||
struct ip_set_req_adt {
|
||||
IP_SET_REQ_BYINDEX;
|
||||
};
|
||||
|
||||
#define IP_SET_OP_ADD_IP 0x00000101 /* Add an IP to a set */
|
||||
/* Uses ip_set_req_adt, with type specific addage */
|
||||
|
||||
#define IP_SET_OP_DEL_IP 0x00000102 /* Remove an IP from a set */
|
||||
/* Uses ip_set_req_adt, with type specific addage */
|
||||
|
||||
#define IP_SET_OP_TEST_IP 0x00000103 /* Test an IP in a set */
|
||||
/* Uses ip_set_req_adt, with type specific addage */
|
||||
|
||||
#define IP_SET_OP_BIND_SET 0x00000104 /* Bind an IP to a set */
|
||||
/* Uses ip_set_req_bind, with type specific addage */
|
||||
struct ip_set_req_bind {
|
||||
IP_SET_REQ_BYINDEX;
|
||||
char binding[IP_SET_MAXNAMELEN];
|
||||
};
|
||||
|
||||
#define IP_SET_OP_UNBIND_SET 0x00000105 /* Unbind an IP from a set */
|
||||
/* Uses ip_set_req_bind, with type speficic addage
|
||||
* index = 0 means unbinding for all sets */
|
||||
|
||||
#define IP_SET_OP_TEST_BIND_SET 0x00000106 /* Test binding an IP to a set */
|
||||
/* Uses ip_set_req_bind, with type specific addage */
|
||||
|
||||
/* Multiple shots operations: list, save, restore.
|
||||
*
|
||||
* - check kernel version and query the max number of sets
|
||||
* - get the basic information on all sets
|
||||
* and size required for the next step
|
||||
* - get actual set data: header, data, bindings
|
||||
*/
|
||||
|
||||
/* Get max_sets and the index of a queried set
|
||||
*/
|
||||
#define IP_SET_OP_MAX_SETS 0x00000020
|
||||
struct ip_set_req_max_sets {
|
||||
unsigned op;
|
||||
unsigned version;
|
||||
ip_set_id_t max_sets; /* max_sets */
|
||||
ip_set_id_t sets; /* real number of sets */
|
||||
union ip_set_name_index set; /* index of set if name used */
|
||||
};
|
||||
|
||||
/* Get the id and name of the sets plus size for next step */
|
||||
#define IP_SET_OP_LIST_SIZE 0x00000201
|
||||
#define IP_SET_OP_SAVE_SIZE 0x00000202
|
||||
struct ip_set_req_setnames {
|
||||
unsigned op;
|
||||
ip_set_id_t index; /* set to list/save */
|
||||
u_int32_t size; /* size to get setdata */
|
||||
/* followed by sets number of struct ip_set_name_list */
|
||||
};
|
||||
|
||||
struct ip_set_name_list {
|
||||
char name[IP_SET_MAXNAMELEN];
|
||||
char typename[IP_SET_MAXNAMELEN];
|
||||
ip_set_id_t index;
|
||||
ip_set_id_t id;
|
||||
};
|
||||
|
||||
/* The actual list operation */
|
||||
#define IP_SET_OP_LIST 0x00000203
|
||||
struct ip_set_req_list {
|
||||
IP_SET_REQ_BYINDEX;
|
||||
/* sets number of struct ip_set_list in reply */
|
||||
};
|
||||
|
||||
struct ip_set_list {
|
||||
ip_set_id_t index;
|
||||
ip_set_id_t binding;
|
||||
u_int32_t ref;
|
||||
u_int32_t header_size; /* Set header data of header_size */
|
||||
u_int32_t members_size; /* Set members data of members_size */
|
||||
u_int32_t bindings_size;/* Set bindings data of bindings_size */
|
||||
};
|
||||
|
||||
struct ip_set_hash_list {
|
||||
ip_set_ip_t ip;
|
||||
ip_set_id_t binding;
|
||||
};
|
||||
|
||||
/* The save operation */
|
||||
#define IP_SET_OP_SAVE 0x00000204
|
||||
/* Uses ip_set_req_list, in the reply replaced by
|
||||
* sets number of struct ip_set_save plus a marker
|
||||
* ip_set_save followed by ip_set_hash_save structures.
|
||||
*/
|
||||
struct ip_set_save {
|
||||
ip_set_id_t index;
|
||||
ip_set_id_t binding;
|
||||
u_int32_t header_size; /* Set header data of header_size */
|
||||
u_int32_t members_size; /* Set members data of members_size */
|
||||
};
|
||||
|
||||
/* At restoring, ip == 0 means default binding for the given set: */
|
||||
struct ip_set_hash_save {
|
||||
ip_set_ip_t ip;
|
||||
ip_set_id_t id;
|
||||
ip_set_id_t binding;
|
||||
};
|
||||
|
||||
/* The restore operation */
|
||||
#define IP_SET_OP_RESTORE 0x00000205
|
||||
/* Uses ip_set_req_setnames followed by ip_set_restore structures
|
||||
* plus a marker ip_set_restore, followed by ip_set_hash_save
|
||||
* structures.
|
||||
*/
|
||||
struct ip_set_restore {
|
||||
char name[IP_SET_MAXNAMELEN];
|
||||
char typename[IP_SET_MAXNAMELEN];
|
||||
ip_set_id_t index;
|
||||
u_int32_t header_size; /* Create data of header_size */
|
||||
u_int32_t members_size; /* Set members data of members_size */
|
||||
};
|
||||
|
||||
static inline int bitmap_bytes(ip_set_ip_t a, ip_set_ip_t b)
|
||||
{
|
||||
return 4 * ((((b - a + 8) / 8) + 3) / 4);
|
||||
}
|
||||
|
||||
/* General limit for the elements in a set */
|
||||
#define MAX_RANGE 0x0000FFFF
|
||||
|
||||
/* Alignment: 'unsigned long' unsupported */
|
||||
#define IPSET_ALIGNTO 4
|
||||
#define IPSET_ALIGN(len) (((len) + IPSET_ALIGNTO - 1) & ~(IPSET_ALIGNTO - 1))
|
||||
#define IPSET_VALIGN(len, old) ((old) ? (len) : IPSET_ALIGN(len))
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#include "ip_set_compat.h"
|
||||
#include "ip_set_malloc.h"
|
||||
|
||||
#define ip_set_printk(format, args...) \
|
||||
do { \
|
||||
printk("%s: %s: ", __FILE__, __FUNCTION__); \
|
||||
printk(format "\n" , ## args); \
|
||||
} while (0)
|
||||
|
||||
#if defined(IP_SET_DEBUG)
|
||||
#define DP(format, args...) \
|
||||
do { \
|
||||
printk("%s: %s (DBG): ", __FILE__, __FUNCTION__);\
|
||||
printk(format "\n" , ## args); \
|
||||
} while (0)
|
||||
#define IP_SET_ASSERT(x) \
|
||||
do { \
|
||||
if (!(x)) \
|
||||
printk("IP_SET_ASSERT: %s:%i(%s)\n", \
|
||||
__FILE__, __LINE__, __FUNCTION__); \
|
||||
} while (0)
|
||||
#else
|
||||
#define DP(format, args...)
|
||||
#define IP_SET_ASSERT(x)
|
||||
#endif
|
||||
|
||||
struct ip_set;
|
||||
|
||||
/*
|
||||
* The ip_set_type definition - one per set type, e.g. "ipmap".
|
||||
*
|
||||
* Each individual set has a pointer, set->type, going to one
|
||||
* of these structures. Function pointers inside the structure implement
|
||||
* the real behaviour of the sets.
|
||||
*
|
||||
* If not mentioned differently, the implementation behind the function
|
||||
* pointers of a set_type, is expected to return 0 if ok, and a negative
|
||||
* errno (e.g. -EINVAL) on error.
|
||||
*/
|
||||
struct ip_set_type {
|
||||
struct list_head list; /* next in list of set types */
|
||||
|
||||
/* test for IP in set (kernel: iptables -m set src|dst)
|
||||
* return 0 if not in set, 1 if in set.
|
||||
*/
|
||||
int (*testip_kernel) (struct ip_set *set,
|
||||
const struct sk_buff * skb,
|
||||
const u_int32_t *flags);
|
||||
|
||||
/* test for IP in set (userspace: ipset -T set IP)
|
||||
* return 0 if not in set, 1 if in set.
|
||||
*/
|
||||
int (*testip) (struct ip_set *set,
|
||||
const void *data, u_int32_t size);
|
||||
|
||||
/*
|
||||
* Size of the data structure passed by when
|
||||
* adding/deletin/testing an entry.
|
||||
*/
|
||||
u_int32_t reqsize;
|
||||
|
||||
/* Add IP into set (userspace: ipset -A set IP)
|
||||
* Return -EEXIST if the address is already in the set,
|
||||
* and -ERANGE if the address lies outside the set bounds.
|
||||
* If the address was not already in the set, 0 is returned.
|
||||
*/
|
||||
int (*addip) (struct ip_set *set,
|
||||
const void *data, u_int32_t size);
|
||||
|
||||
/* Add IP into set (kernel: iptables ... -j SET set src|dst)
|
||||
* Return -EEXIST if the address is already in the set,
|
||||
* and -ERANGE if the address lies outside the set bounds.
|
||||
* If the address was not already in the set, 0 is returned.
|
||||
*/
|
||||
int (*addip_kernel) (struct ip_set *set,
|
||||
const struct sk_buff * skb,
|
||||
const u_int32_t *flags);
|
||||
|
||||
/* remove IP from set (userspace: ipset -D set --entry x)
|
||||
* Return -EEXIST if the address is NOT in the set,
|
||||
* and -ERANGE if the address lies outside the set bounds.
|
||||
* If the address really was in the set, 0 is returned.
|
||||
*/
|
||||
int (*delip) (struct ip_set *set,
|
||||
const void *data, u_int32_t size);
|
||||
|
||||
/* remove IP from set (kernel: iptables ... -j SET --entry x)
|
||||
* Return -EEXIST if the address is NOT in the set,
|
||||
* and -ERANGE if the address lies outside the set bounds.
|
||||
* If the address really was in the set, 0 is returned.
|
||||
*/
|
||||
int (*delip_kernel) (struct ip_set *set,
|
||||
const struct sk_buff * skb,
|
||||
const u_int32_t *flags);
|
||||
|
||||
/* new set creation - allocated type specific items
|
||||
*/
|
||||
int (*create) (struct ip_set *set,
|
||||
const void *data, u_int32_t size);
|
||||
|
||||
/* retry the operation after successfully tweaking the set
|
||||
*/
|
||||
int (*retry) (struct ip_set *set);
|
||||
|
||||
/* set destruction - free type specific items
|
||||
* There is no return value.
|
||||
* Can be called only when child sets are destroyed.
|
||||
*/
|
||||
void (*destroy) (struct ip_set *set);
|
||||
|
||||
/* set flushing - reset all bits in the set, or something similar.
|
||||
* There is no return value.
|
||||
*/
|
||||
void (*flush) (struct ip_set *set);
|
||||
|
||||
/* Listing: size needed for header
|
||||
*/
|
||||
u_int32_t header_size;
|
||||
|
||||
/* Listing: Get the header
|
||||
*
|
||||
* Fill in the information in "data".
|
||||
* This function is always run after list_header_size() under a
|
||||
* writelock on the set. Therefor is the length of "data" always
|
||||
* correct.
|
||||
*/
|
||||
void (*list_header) (const struct ip_set *set,
|
||||
void *data);
|
||||
|
||||
/* Listing: Get the size for the set members
|
||||
*/
|
||||
int (*list_members_size) (const struct ip_set *set, char dont_align);
|
||||
|
||||
/* Listing: Get the set members
|
||||
*
|
||||
* Fill in the information in "data".
|
||||
* This function is always run after list_member_size() under a
|
||||
* writelock on the set. Therefor is the length of "data" always
|
||||
* correct.
|
||||
*/
|
||||
void (*list_members) (const struct ip_set *set,
|
||||
void *data, char dont_align);
|
||||
|
||||
char typename[IP_SET_MAXNAMELEN];
|
||||
unsigned char features;
|
||||
int protocol_version;
|
||||
|
||||
/* Set this to THIS_MODULE if you are a module, otherwise NULL */
|
||||
struct module *me;
|
||||
};
|
||||
|
||||
extern int ip_set_register_set_type(struct ip_set_type *set_type);
|
||||
extern void ip_set_unregister_set_type(struct ip_set_type *set_type);
|
||||
|
||||
/* A generic ipset */
|
||||
struct ip_set {
|
||||
char name[IP_SET_MAXNAMELEN]; /* the name of the set */
|
||||
rwlock_t lock; /* lock for concurrency control */
|
||||
ip_set_id_t id; /* set id for swapping */
|
||||
atomic_t ref; /* in kernel and in hash references */
|
||||
struct ip_set_type *type; /* the set types */
|
||||
void *data; /* pooltype specific data */
|
||||
};
|
||||
|
||||
/* register and unregister set references */
|
||||
extern ip_set_id_t ip_set_get_byname(const char name[IP_SET_MAXNAMELEN]);
|
||||
extern ip_set_id_t ip_set_get_byindex(ip_set_id_t index);
|
||||
extern void ip_set_put_byindex(ip_set_id_t index);
|
||||
extern ip_set_id_t ip_set_id(ip_set_id_t index);
|
||||
extern ip_set_id_t __ip_set_get_byname(const char name[IP_SET_MAXNAMELEN],
|
||||
struct ip_set **set);
|
||||
extern void __ip_set_put_byindex(ip_set_id_t index);
|
||||
|
||||
/* API for iptables set match, and SET target */
|
||||
extern int ip_set_addip_kernel(ip_set_id_t id,
|
||||
const struct sk_buff *skb,
|
||||
const u_int32_t *flags);
|
||||
extern int ip_set_delip_kernel(ip_set_id_t id,
|
||||
const struct sk_buff *skb,
|
||||
const u_int32_t *flags);
|
||||
extern int ip_set_testip_kernel(ip_set_id_t id,
|
||||
const struct sk_buff *skb,
|
||||
const u_int32_t *flags);
|
||||
|
||||
/* Macros to generate functions */
|
||||
|
||||
#define STRUCT(pre, type) CONCAT2(pre, type)
|
||||
#define CONCAT2(pre, type) struct pre##type
|
||||
|
||||
#define FNAME(pre, mid, post) CONCAT3(pre, mid, post)
|
||||
#define CONCAT3(pre, mid, post) pre##mid##post
|
||||
|
||||
#define UADT0(type, adt, args...) \
|
||||
static int \
|
||||
FNAME(type,_u,adt)(struct ip_set *set, const void *data, u_int32_t size)\
|
||||
{ \
|
||||
const STRUCT(ip_set_req_,type) *req = data; \
|
||||
\
|
||||
return FNAME(type,_,adt)(set , ## args); \
|
||||
}
|
||||
|
||||
#define UADT(type, adt, args...) \
|
||||
UADT0(type, adt, req->ip , ## args)
|
||||
|
||||
#define KADT(type, adt, getfn, args...) \
|
||||
static int \
|
||||
FNAME(type,_k,adt)(struct ip_set *set, \
|
||||
const struct sk_buff *skb, \
|
||||
const u_int32_t *flags) \
|
||||
{ \
|
||||
ip_set_ip_t ip = getfn(skb, flags); \
|
||||
\
|
||||
KADT_CONDITION \
|
||||
return FNAME(type,_,adt)(set, ip , ##args); \
|
||||
}
|
||||
|
||||
#define REGISTER_MODULE(type) \
|
||||
static int __init ip_set_##type##_init(void) \
|
||||
{ \
|
||||
init_max_page_size(); \
|
||||
return ip_set_register_set_type(&ip_set_##type); \
|
||||
} \
|
||||
\
|
||||
static void __exit ip_set_##type##_fini(void) \
|
||||
{ \
|
||||
/* FIXME: possible race with ip_set_create() */ \
|
||||
ip_set_unregister_set_type(&ip_set_##type); \
|
||||
} \
|
||||
\
|
||||
module_init(ip_set_##type##_init); \
|
||||
module_exit(ip_set_##type##_fini);
|
||||
|
||||
/* Common functions */
|
||||
|
||||
static inline ip_set_ip_t
|
||||
ipaddr(const struct sk_buff *skb, const u_int32_t *flags)
|
||||
{
|
||||
return ntohl(flags[0] & IPSET_SRC ? ip_hdr(skb)->saddr : ip_hdr(skb)->daddr);
|
||||
}
|
||||
|
||||
#define jhash_ip(map, i, ip) jhash_1word(ip, *(map->initval + i))
|
||||
|
||||
#define pack_ip_port(map, ip, port) \
|
||||
(port + ((ip - ((map)->first_ip)) << 16))
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#define UNUSED __attribute__ ((unused))
|
||||
|
||||
#endif /*_IP_SET_H*/
|
||||
@@ -1,120 +0,0 @@
|
||||
#ifndef __IP_SET_BITMAPS_H
|
||||
#define __IP_SET_BITMAPS_H
|
||||
|
||||
/* Macros to generate functions */
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#define BITMAP_CREATE(type) \
|
||||
static int \
|
||||
type##_create(struct ip_set *set, const void *data, u_int32_t size) \
|
||||
{ \
|
||||
int newbytes; \
|
||||
const struct ip_set_req_##type##_create *req = data; \
|
||||
struct ip_set_##type *map; \
|
||||
\
|
||||
if (req->from > req->to) { \
|
||||
DP("bad range"); \
|
||||
return -ENOEXEC; \
|
||||
} \
|
||||
\
|
||||
map = kmalloc(sizeof(struct ip_set_##type), GFP_KERNEL); \
|
||||
if (!map) { \
|
||||
DP("out of memory for %zu bytes", \
|
||||
sizeof(struct ip_set_##type)); \
|
||||
return -ENOMEM; \
|
||||
} \
|
||||
map->first_ip = req->from; \
|
||||
map->last_ip = req->to; \
|
||||
\
|
||||
newbytes = __##type##_create(req, map); \
|
||||
if (newbytes < 0) { \
|
||||
kfree(map); \
|
||||
return newbytes; \
|
||||
} \
|
||||
\
|
||||
map->size = newbytes; \
|
||||
map->members = ip_set_malloc(newbytes); \
|
||||
if (!map->members) { \
|
||||
DP("out of memory for %i bytes", newbytes); \
|
||||
kfree(map); \
|
||||
return -ENOMEM; \
|
||||
} \
|
||||
memset(map->members, 0, newbytes); \
|
||||
\
|
||||
set->data = map; \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
#define BITMAP_DESTROY(type) \
|
||||
static void \
|
||||
type##_destroy(struct ip_set *set) \
|
||||
{ \
|
||||
struct ip_set_##type *map = set->data; \
|
||||
\
|
||||
ip_set_free(map->members, map->size); \
|
||||
kfree(map); \
|
||||
\
|
||||
set->data = NULL; \
|
||||
}
|
||||
|
||||
#define BITMAP_FLUSH(type) \
|
||||
static void \
|
||||
type##_flush(struct ip_set *set) \
|
||||
{ \
|
||||
struct ip_set_##type *map = set->data; \
|
||||
memset(map->members, 0, map->size); \
|
||||
}
|
||||
|
||||
#define BITMAP_LIST_HEADER(type) \
|
||||
static void \
|
||||
type##_list_header(const struct ip_set *set, void *data) \
|
||||
{ \
|
||||
const struct ip_set_##type *map = set->data; \
|
||||
struct ip_set_req_##type##_create *header = data; \
|
||||
\
|
||||
header->from = map->first_ip; \
|
||||
header->to = map->last_ip; \
|
||||
__##type##_list_header(map, header); \
|
||||
}
|
||||
|
||||
#define BITMAP_LIST_MEMBERS_SIZE(type, dtype, sizeid, testfn) \
|
||||
static int \
|
||||
type##_list_members_size(const struct ip_set *set, char dont_align) \
|
||||
{ \
|
||||
const struct ip_set_##type *map = set->data; \
|
||||
ip_set_ip_t i, elements = 0; \
|
||||
\
|
||||
if (dont_align) \
|
||||
return map->size; \
|
||||
\
|
||||
for (i = 0; i < sizeid; i++) \
|
||||
if (testfn) \
|
||||
elements++; \
|
||||
\
|
||||
return elements * IPSET_ALIGN(sizeof(dtype)); \
|
||||
}
|
||||
|
||||
#define IP_SET_TYPE(type, __features) \
|
||||
struct ip_set_type ip_set_##type = { \
|
||||
.typename = #type, \
|
||||
.features = __features, \
|
||||
.protocol_version = IP_SET_PROTOCOL_VERSION, \
|
||||
.create = &type##_create, \
|
||||
.destroy = &type##_destroy, \
|
||||
.flush = &type##_flush, \
|
||||
.reqsize = sizeof(struct ip_set_req_##type), \
|
||||
.addip = &type##_uadd, \
|
||||
.addip_kernel = &type##_kadd, \
|
||||
.delip = &type##_udel, \
|
||||
.delip_kernel = &type##_kdel, \
|
||||
.testip = &type##_utest, \
|
||||
.testip_kernel = &type##_ktest, \
|
||||
.header_size = sizeof(struct ip_set_req_##type##_create),\
|
||||
.list_header = &type##_list_header, \
|
||||
.list_members_size = &type##_list_members_size, \
|
||||
.list_members = &type##_list_members, \
|
||||
.me = THIS_MODULE, \
|
||||
};
|
||||
#endif /* __KERNEL */
|
||||
|
||||
#endif /* __IP_SET_BITMAPS_H */
|
||||
@@ -1,92 +0,0 @@
|
||||
#ifndef _IP_SET_COMPAT_H
|
||||
#define _IP_SET_COMPAT_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#include <linux/version.h>
|
||||
|
||||
/* Arrgh */
|
||||
#ifdef MODULE
|
||||
#define __MOD_INC(foo) __MOD_INC_USE_COUNT(foo)
|
||||
#define __MOD_DEC(foo) __MOD_DEC_USE_COUNT(foo)
|
||||
#else
|
||||
#define __MOD_INC(foo) 1
|
||||
#define __MOD_DEC(foo)
|
||||
#endif
|
||||
|
||||
/* Backward compatibility */
|
||||
#ifndef __nocast
|
||||
#define __nocast
|
||||
#endif
|
||||
#ifndef __bitwise__
|
||||
#define __bitwise__
|
||||
#endif
|
||||
|
||||
/* Compatibility glue code */
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
|
||||
#include <linux/interrupt.h>
|
||||
#define DEFINE_RWLOCK(x) rwlock_t x = RW_LOCK_UNLOCKED
|
||||
#define try_module_get(x) __MOD_INC(x)
|
||||
#define module_put(x) __MOD_DEC(x)
|
||||
#define __clear_bit(nr, addr) clear_bit(nr, addr)
|
||||
#define __set_bit(nr, addr) set_bit(nr, addr)
|
||||
#define __test_and_set_bit(nr, addr) test_and_set_bit(nr, addr)
|
||||
#define __test_and_clear_bit(nr, addr) test_and_clear_bit(nr, addr)
|
||||
|
||||
typedef unsigned __bitwise__ gfp_t;
|
||||
|
||||
static inline void *kzalloc(size_t size, gfp_t flags)
|
||||
{
|
||||
void *data = kmalloc(size, flags);
|
||||
|
||||
if (data)
|
||||
memset(data, 0, size);
|
||||
|
||||
return data;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
|
||||
#define __KMEM_CACHE_T__ kmem_cache_t
|
||||
#else
|
||||
#define __KMEM_CACHE_T__ struct kmem_cache
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
|
||||
#define ip_hdr(skb) ((skb)->nh.iph)
|
||||
#define skb_mac_header(skb) ((skb)->mac.raw)
|
||||
#define eth_hdr(skb) ((struct ethhdr *)skb_mac_header(skb))
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
|
||||
#include <linux/netfilter.h>
|
||||
#define KMEM_CACHE_CREATE(name, size) \
|
||||
kmem_cache_create(name, size, 0, 0, NULL, NULL)
|
||||
#else
|
||||
#define KMEM_CACHE_CREATE(name, size) \
|
||||
kmem_cache_create(name, size, 0, 0, NULL)
|
||||
#endif
|
||||
|
||||
#ifndef NIPQUAD
|
||||
#define NIPQUAD(addr) \
|
||||
((unsigned char *)&addr)[0], \
|
||||
((unsigned char *)&addr)[1], \
|
||||
((unsigned char *)&addr)[2], \
|
||||
((unsigned char *)&addr)[3]
|
||||
#endif
|
||||
|
||||
#ifndef HIPQUAD
|
||||
#if defined(__LITTLE_ENDIAN)
|
||||
#define HIPQUAD(addr) \
|
||||
((unsigned char *)&addr)[3], \
|
||||
((unsigned char *)&addr)[2], \
|
||||
((unsigned char *)&addr)[1], \
|
||||
((unsigned char *)&addr)[0]
|
||||
#elif defined(__BIG_ENDIAN)
|
||||
#define HIPQUAD NIPQUAD
|
||||
#else
|
||||
#error "Please fix asm/byteorder.h"
|
||||
#endif /* __LITTLE_ENDIAN */
|
||||
#endif
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* _IP_SET_COMPAT_H */
|
||||
@@ -1,48 +0,0 @@
|
||||
#ifndef _IP_SET_GETPORT_H
|
||||
#define _IP_SET_GETPORT_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#define INVALID_PORT (MAX_RANGE + 1)
|
||||
|
||||
/* We must handle non-linear skbs */
|
||||
static inline ip_set_ip_t
|
||||
get_port(const struct sk_buff *skb, const u_int32_t *flags)
|
||||
{
|
||||
struct iphdr *iph = ip_hdr(skb);
|
||||
u_int16_t offset = ntohs(iph->frag_off) & IP_OFFSET;
|
||||
switch (iph->protocol) {
|
||||
case IPPROTO_TCP: {
|
||||
struct tcphdr tcph;
|
||||
|
||||
/* See comments at tcp_match in ip_tables.c */
|
||||
if (offset)
|
||||
return INVALID_PORT;
|
||||
|
||||
if (skb_copy_bits(skb, ip_hdr(skb)->ihl*4, &tcph, sizeof(tcph)) < 0)
|
||||
/* No choice either */
|
||||
return INVALID_PORT;
|
||||
|
||||
return ntohs(flags[0] & IPSET_SRC ?
|
||||
tcph.source : tcph.dest);
|
||||
}
|
||||
case IPPROTO_UDP: {
|
||||
struct udphdr udph;
|
||||
|
||||
if (offset)
|
||||
return INVALID_PORT;
|
||||
|
||||
if (skb_copy_bits(skb, ip_hdr(skb)->ihl*4, &udph, sizeof(udph)) < 0)
|
||||
/* No choice either */
|
||||
return INVALID_PORT;
|
||||
|
||||
return ntohs(flags[0] & IPSET_SRC ?
|
||||
udph.source : udph.dest);
|
||||
}
|
||||
default:
|
||||
return INVALID_PORT;
|
||||
}
|
||||
}
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /*_IP_SET_GETPORT_H*/
|
||||
@@ -1,314 +0,0 @@
|
||||
#ifndef __IP_SET_HASHES_H
|
||||
#define __IP_SET_HASHES_H
|
||||
|
||||
#define initval_t uint32_t
|
||||
|
||||
/* Macros to generate functions */
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#define HASH_RETRY0(type, dtype, cond) \
|
||||
static int \
|
||||
type##_retry(struct ip_set *set) \
|
||||
{ \
|
||||
struct ip_set_##type *map = set->data, *tmp; \
|
||||
dtype *elem; \
|
||||
void *members; \
|
||||
u_int32_t i, hashsize = map->hashsize; \
|
||||
int res; \
|
||||
\
|
||||
if (map->resize == 0) \
|
||||
return -ERANGE; \
|
||||
\
|
||||
again: \
|
||||
res = 0; \
|
||||
\
|
||||
/* Calculate new hash size */ \
|
||||
hashsize += (hashsize * map->resize)/100; \
|
||||
if (hashsize == map->hashsize) \
|
||||
hashsize++; \
|
||||
\
|
||||
ip_set_printk("rehashing of set %s triggered: " \
|
||||
"hashsize grows from %lu to %lu", \
|
||||
set->name, \
|
||||
(long unsigned)map->hashsize, \
|
||||
(long unsigned)hashsize); \
|
||||
\
|
||||
tmp = kmalloc(sizeof(struct ip_set_##type) \
|
||||
+ map->probes * sizeof(initval_t), GFP_ATOMIC); \
|
||||
if (!tmp) { \
|
||||
DP("out of memory for %zu bytes", \
|
||||
sizeof(struct ip_set_##type) \
|
||||
+ map->probes * sizeof(initval_t)); \
|
||||
return -ENOMEM; \
|
||||
} \
|
||||
tmp->members = harray_malloc(hashsize, sizeof(dtype), GFP_ATOMIC);\
|
||||
if (!tmp->members) { \
|
||||
DP("out of memory for %zu bytes", hashsize * sizeof(dtype));\
|
||||
kfree(tmp); \
|
||||
return -ENOMEM; \
|
||||
} \
|
||||
tmp->hashsize = hashsize; \
|
||||
tmp->elements = 0; \
|
||||
tmp->probes = map->probes; \
|
||||
tmp->resize = map->resize; \
|
||||
memcpy(tmp->initval, map->initval, map->probes * sizeof(initval_t));\
|
||||
__##type##_retry(tmp, map); \
|
||||
\
|
||||
write_lock_bh(&set->lock); \
|
||||
map = set->data; /* Play safe */ \
|
||||
for (i = 0; i < map->hashsize && res == 0; i++) { \
|
||||
elem = HARRAY_ELEM(map->members, dtype *, i); \
|
||||
if (cond) \
|
||||
res = __##type##_add(tmp, elem); \
|
||||
} \
|
||||
if (res) { \
|
||||
/* Failure, try again */ \
|
||||
write_unlock_bh(&set->lock); \
|
||||
harray_free(tmp->members); \
|
||||
kfree(tmp); \
|
||||
goto again; \
|
||||
} \
|
||||
\
|
||||
/* Success at resizing! */ \
|
||||
members = map->members; \
|
||||
\
|
||||
map->hashsize = tmp->hashsize; \
|
||||
map->members = tmp->members; \
|
||||
write_unlock_bh(&set->lock); \
|
||||
\
|
||||
harray_free(members); \
|
||||
kfree(tmp); \
|
||||
\
|
||||
return 0; \
|
||||
}
|
||||
|
||||
#define HASH_RETRY(type, dtype) \
|
||||
HASH_RETRY0(type, dtype, *elem)
|
||||
|
||||
#define HASH_RETRY2(type, dtype) \
|
||||
HASH_RETRY0(type, dtype, elem->ip || elem->ip1)
|
||||
|
||||
#define HASH_CREATE(type, dtype) \
|
||||
static int \
|
||||
type##_create(struct ip_set *set, const void *data, u_int32_t size) \
|
||||
{ \
|
||||
const struct ip_set_req_##type##_create *req = data; \
|
||||
struct ip_set_##type *map; \
|
||||
uint16_t i; \
|
||||
\
|
||||
if (req->hashsize < 1) { \
|
||||
ip_set_printk("hashsize too small"); \
|
||||
return -ENOEXEC; \
|
||||
} \
|
||||
\
|
||||
if (req->probes < 1) { \
|
||||
ip_set_printk("probes too small"); \
|
||||
return -ENOEXEC; \
|
||||
} \
|
||||
\
|
||||
map = kmalloc(sizeof(struct ip_set_##type) \
|
||||
+ req->probes * sizeof(initval_t), GFP_KERNEL); \
|
||||
if (!map) { \
|
||||
DP("out of memory for %zu bytes", \
|
||||
sizeof(struct ip_set_##type) \
|
||||
+ req->probes * sizeof(initval_t)); \
|
||||
return -ENOMEM; \
|
||||
} \
|
||||
for (i = 0; i < req->probes; i++) \
|
||||
get_random_bytes(((initval_t *) map->initval)+i, 4); \
|
||||
map->elements = 0; \
|
||||
map->hashsize = req->hashsize; \
|
||||
map->probes = req->probes; \
|
||||
map->resize = req->resize; \
|
||||
if (__##type##_create(req, map)) { \
|
||||
kfree(map); \
|
||||
return -ENOEXEC; \
|
||||
} \
|
||||
map->members = harray_malloc(map->hashsize, sizeof(dtype), GFP_KERNEL);\
|
||||
if (!map->members) { \
|
||||
DP("out of memory for %zu bytes", map->hashsize * sizeof(dtype));\
|
||||
kfree(map); \
|
||||
return -ENOMEM; \
|
||||
} \
|
||||
\
|
||||
set->data = map; \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
#define HASH_DESTROY(type) \
|
||||
static void \
|
||||
type##_destroy(struct ip_set *set) \
|
||||
{ \
|
||||
struct ip_set_##type *map = set->data; \
|
||||
\
|
||||
harray_free(map->members); \
|
||||
kfree(map); \
|
||||
\
|
||||
set->data = NULL; \
|
||||
}
|
||||
|
||||
#define HASH_FLUSH(type, dtype) \
|
||||
static void \
|
||||
type##_flush(struct ip_set *set) \
|
||||
{ \
|
||||
struct ip_set_##type *map = set->data; \
|
||||
harray_flush(map->members, map->hashsize, sizeof(dtype)); \
|
||||
map->elements = 0; \
|
||||
}
|
||||
|
||||
#define HASH_FLUSH_CIDR(type, dtype) \
|
||||
static void \
|
||||
type##_flush(struct ip_set *set) \
|
||||
{ \
|
||||
struct ip_set_##type *map = set->data; \
|
||||
harray_flush(map->members, map->hashsize, sizeof(dtype)); \
|
||||
memset(map->cidr, 0, sizeof(map->cidr)); \
|
||||
memset(map->nets, 0, sizeof(map->nets)); \
|
||||
map->elements = 0; \
|
||||
}
|
||||
|
||||
#define HASH_LIST_HEADER(type) \
|
||||
static void \
|
||||
type##_list_header(const struct ip_set *set, void *data) \
|
||||
{ \
|
||||
const struct ip_set_##type *map = set->data; \
|
||||
struct ip_set_req_##type##_create *header = data; \
|
||||
\
|
||||
header->hashsize = map->hashsize; \
|
||||
header->probes = map->probes; \
|
||||
header->resize = map->resize; \
|
||||
__##type##_list_header(map, header); \
|
||||
}
|
||||
|
||||
#define HASH_LIST_MEMBERS_SIZE(type, dtype) \
|
||||
static int \
|
||||
type##_list_members_size(const struct ip_set *set, char dont_align) \
|
||||
{ \
|
||||
const struct ip_set_##type *map = set->data; \
|
||||
\
|
||||
return (map->elements * IPSET_VALIGN(sizeof(dtype), dont_align));\
|
||||
}
|
||||
|
||||
#define HASH_LIST_MEMBERS(type, dtype) \
|
||||
static void \
|
||||
type##_list_members(const struct ip_set *set, void *data, char dont_align)\
|
||||
{ \
|
||||
const struct ip_set_##type *map = set->data; \
|
||||
dtype *elem, *d; \
|
||||
uint32_t i, n = 0; \
|
||||
\
|
||||
for (i = 0; i < map->hashsize; i++) { \
|
||||
elem = HARRAY_ELEM(map->members, dtype *, i); \
|
||||
if (*elem) { \
|
||||
d = data + n * IPSET_VALIGN(sizeof(dtype), dont_align);\
|
||||
*d = *elem; \
|
||||
n++; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define HASH_LIST_MEMBERS_MEMCPY(type, dtype, nonzero) \
|
||||
static void \
|
||||
type##_list_members(const struct ip_set *set, void *data, char dont_align)\
|
||||
{ \
|
||||
const struct ip_set_##type *map = set->data; \
|
||||
dtype *elem; \
|
||||
uint32_t i, n = 0; \
|
||||
\
|
||||
for (i = 0; i < map->hashsize; i++) { \
|
||||
elem = HARRAY_ELEM(map->members, dtype *, i); \
|
||||
if (nonzero) { \
|
||||
memcpy(data + n * IPSET_VALIGN(sizeof(dtype), dont_align),\
|
||||
elem, sizeof(dtype)); \
|
||||
n++; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define IP_SET_RTYPE(type, __features) \
|
||||
struct ip_set_type ip_set_##type = { \
|
||||
.typename = #type, \
|
||||
.features = __features, \
|
||||
.protocol_version = IP_SET_PROTOCOL_VERSION, \
|
||||
.create = &type##_create, \
|
||||
.retry = &type##_retry, \
|
||||
.destroy = &type##_destroy, \
|
||||
.flush = &type##_flush, \
|
||||
.reqsize = sizeof(struct ip_set_req_##type), \
|
||||
.addip = &type##_uadd, \
|
||||
.addip_kernel = &type##_kadd, \
|
||||
.delip = &type##_udel, \
|
||||
.delip_kernel = &type##_kdel, \
|
||||
.testip = &type##_utest, \
|
||||
.testip_kernel = &type##_ktest, \
|
||||
.header_size = sizeof(struct ip_set_req_##type##_create),\
|
||||
.list_header = &type##_list_header, \
|
||||
.list_members_size = &type##_list_members_size, \
|
||||
.list_members = &type##_list_members, \
|
||||
.me = THIS_MODULE, \
|
||||
};
|
||||
|
||||
/* Helper functions */
|
||||
static inline void
|
||||
add_cidr_size(uint8_t *cidr, uint8_t size)
|
||||
{
|
||||
uint8_t next;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 30 && cidr[i]; i++) {
|
||||
if (cidr[i] < size) {
|
||||
next = cidr[i];
|
||||
cidr[i] = size;
|
||||
size = next;
|
||||
}
|
||||
}
|
||||
if (i < 30)
|
||||
cidr[i] = size;
|
||||
}
|
||||
|
||||
static inline void
|
||||
del_cidr_size(uint8_t *cidr, uint8_t size)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 29 && cidr[i]; i++) {
|
||||
if (cidr[i] == size)
|
||||
cidr[i] = size = cidr[i+1];
|
||||
}
|
||||
cidr[29] = 0;
|
||||
}
|
||||
#else
|
||||
#include <arpa/inet.h>
|
||||
#endif /* __KERNEL */
|
||||
|
||||
#ifndef UINT16_MAX
|
||||
#define UINT16_MAX 65535
|
||||
#endif
|
||||
|
||||
static unsigned char shifts[] = {255, 253, 249, 241, 225, 193, 129, 1};
|
||||
|
||||
static inline ip_set_ip_t
|
||||
pack_ip_cidr(ip_set_ip_t ip, unsigned char cidr)
|
||||
{
|
||||
ip_set_ip_t addr, *paddr = &addr;
|
||||
unsigned char n, t, *a;
|
||||
|
||||
addr = htonl(ip & (0xFFFFFFFF << (32 - (cidr))));
|
||||
#ifdef __KERNEL__
|
||||
DP("ip:%u.%u.%u.%u/%u", NIPQUAD(addr), cidr);
|
||||
#endif
|
||||
n = cidr / 8;
|
||||
t = cidr % 8;
|
||||
a = &((unsigned char *)paddr)[n];
|
||||
*a = *a /(1 << (8 - t)) + shifts[t];
|
||||
#ifdef __KERNEL__
|
||||
DP("n: %u, t: %u, a: %u", n, t, *a);
|
||||
DP("ip:%u.%u.%u.%u/%u, %u.%u.%u.%u",
|
||||
HIPQUAD(ip), cidr, NIPQUAD(addr));
|
||||
#endif
|
||||
|
||||
return ntohl(addr);
|
||||
}
|
||||
|
||||
|
||||
#endif /* __IP_SET_HASHES_H */
|
||||
@@ -1,164 +0,0 @@
|
||||
/* Copyright (C) 2003-2008 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an ip hash set */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include "ip_set_jhash.h"
|
||||
#include <linux/errno.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/random.h>
|
||||
|
||||
#include <net/ip.h>
|
||||
|
||||
#include "ip_set_iphash.h"
|
||||
|
||||
static int limit = MAX_RANGE;
|
||||
|
||||
static inline __u32
|
||||
iphash_id(struct ip_set *set, ip_set_ip_t ip)
|
||||
{
|
||||
struct ip_set_iphash *map = set->data;
|
||||
__u32 id;
|
||||
u_int16_t i;
|
||||
ip_set_ip_t *elem;
|
||||
|
||||
|
||||
ip &= map->netmask;
|
||||
DP("set: %s, ip:%u.%u.%u.%u", set->name, HIPQUAD(ip));
|
||||
for (i = 0; i < map->probes; i++) {
|
||||
id = jhash_ip(map, i, ip) % map->hashsize;
|
||||
DP("hash key: %u", id);
|
||||
elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id);
|
||||
if (*elem == ip)
|
||||
return id;
|
||||
/* No shortcut - there can be deleted entries. */
|
||||
}
|
||||
return UINT_MAX;
|
||||
}
|
||||
|
||||
static inline int
|
||||
iphash_test(struct ip_set *set, ip_set_ip_t ip)
|
||||
{
|
||||
return (ip && iphash_id(set, ip) != UINT_MAX);
|
||||
}
|
||||
|
||||
#define KADT_CONDITION
|
||||
|
||||
UADT(iphash, test)
|
||||
KADT(iphash, test, ipaddr)
|
||||
|
||||
static inline int
|
||||
__iphash_add(struct ip_set_iphash *map, ip_set_ip_t *ip)
|
||||
{
|
||||
__u32 probe;
|
||||
u_int16_t i;
|
||||
ip_set_ip_t *elem, *slot = NULL;
|
||||
|
||||
for (i = 0; i < map->probes; i++) {
|
||||
probe = jhash_ip(map, i, *ip) % map->hashsize;
|
||||
elem = HARRAY_ELEM(map->members, ip_set_ip_t *, probe);
|
||||
if (*elem == *ip)
|
||||
return -EEXIST;
|
||||
if (!(slot || *elem))
|
||||
slot = elem;
|
||||
/* There can be deleted entries, must check all slots */
|
||||
}
|
||||
if (slot) {
|
||||
*slot = *ip;
|
||||
map->elements++;
|
||||
return 0;
|
||||
}
|
||||
/* Trigger rehashing */
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
static inline int
|
||||
iphash_add(struct ip_set *set, ip_set_ip_t ip)
|
||||
{
|
||||
struct ip_set_iphash *map = set->data;
|
||||
|
||||
if (!ip || map->elements >= limit)
|
||||
return -ERANGE;
|
||||
|
||||
ip &= map->netmask;
|
||||
return __iphash_add(map, &ip);
|
||||
}
|
||||
|
||||
UADT(iphash, add)
|
||||
KADT(iphash, add, ipaddr)
|
||||
|
||||
static inline void
|
||||
__iphash_retry(struct ip_set_iphash *tmp, struct ip_set_iphash *map)
|
||||
{
|
||||
tmp->netmask = map->netmask;
|
||||
}
|
||||
|
||||
HASH_RETRY(iphash, ip_set_ip_t)
|
||||
|
||||
static inline int
|
||||
iphash_del(struct ip_set *set, ip_set_ip_t ip)
|
||||
{
|
||||
struct ip_set_iphash *map = set->data;
|
||||
ip_set_ip_t id, *elem;
|
||||
|
||||
if (!ip)
|
||||
return -ERANGE;
|
||||
|
||||
id = iphash_id(set, ip);
|
||||
if (id == UINT_MAX)
|
||||
return -EEXIST;
|
||||
|
||||
elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id);
|
||||
*elem = 0;
|
||||
map->elements--;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
UADT(iphash, del)
|
||||
KADT(iphash, del, ipaddr)
|
||||
|
||||
static inline int
|
||||
__iphash_create(const struct ip_set_req_iphash_create *req,
|
||||
struct ip_set_iphash *map)
|
||||
{
|
||||
map->netmask = req->netmask;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
HASH_CREATE(iphash, ip_set_ip_t)
|
||||
HASH_DESTROY(iphash)
|
||||
|
||||
HASH_FLUSH(iphash, ip_set_ip_t)
|
||||
|
||||
static inline void
|
||||
__iphash_list_header(const struct ip_set_iphash *map,
|
||||
struct ip_set_req_iphash_create *header)
|
||||
{
|
||||
header->netmask = map->netmask;
|
||||
}
|
||||
|
||||
HASH_LIST_HEADER(iphash)
|
||||
HASH_LIST_MEMBERS_SIZE(iphash, ip_set_ip_t)
|
||||
HASH_LIST_MEMBERS(iphash, ip_set_ip_t)
|
||||
|
||||
IP_SET_RTYPE(iphash, IPSET_TYPE_IP | IPSET_DATA_SINGLE)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("iphash type of IP sets");
|
||||
module_param(limit, int, 0600);
|
||||
MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets");
|
||||
|
||||
REGISTER_MODULE(iphash)
|
||||
@@ -1,30 +0,0 @@
|
||||
#ifndef __IP_SET_IPHASH_H
|
||||
#define __IP_SET_IPHASH_H
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_hashes.h"
|
||||
|
||||
#define SETTYPE_NAME "iphash"
|
||||
|
||||
struct ip_set_iphash {
|
||||
ip_set_ip_t *members; /* the iphash proper */
|
||||
uint32_t elements; /* number of elements */
|
||||
uint32_t hashsize; /* hash size */
|
||||
uint16_t probes; /* max number of probes */
|
||||
uint16_t resize; /* resize factor in percent */
|
||||
ip_set_ip_t netmask; /* netmask */
|
||||
initval_t initval[0]; /* initvals for jhash_1word */
|
||||
};
|
||||
|
||||
struct ip_set_req_iphash_create {
|
||||
uint32_t hashsize;
|
||||
uint16_t probes;
|
||||
uint16_t resize;
|
||||
ip_set_ip_t netmask;
|
||||
};
|
||||
|
||||
struct ip_set_req_iphash {
|
||||
ip_set_ip_t ip;
|
||||
};
|
||||
|
||||
#endif /* __IP_SET_IPHASH_H */
|
||||
@@ -1,158 +0,0 @@
|
||||
/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
|
||||
* Patrick Schaaf <bof@bof.de>
|
||||
* Copyright (C) 2003-2008 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an IP set type: the single bitmap type */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include "ip_set_ipmap.h"
|
||||
|
||||
static inline ip_set_ip_t
|
||||
ip_to_id(const struct ip_set_ipmap *map, ip_set_ip_t ip)
|
||||
{
|
||||
return ((ip & map->netmask) - map->first_ip)/map->hosts;
|
||||
}
|
||||
|
||||
static inline int
|
||||
ipmap_test(const struct ip_set *set, ip_set_ip_t ip)
|
||||
{
|
||||
const struct ip_set_ipmap *map = set->data;
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
|
||||
DP("set: %s, ip:%u.%u.%u.%u", set->name, HIPQUAD(ip));
|
||||
return !!test_bit(ip_to_id(map, ip), map->members);
|
||||
}
|
||||
|
||||
#define KADT_CONDITION
|
||||
|
||||
UADT(ipmap, test)
|
||||
KADT(ipmap, test, ipaddr)
|
||||
|
||||
static inline int
|
||||
ipmap_add(struct ip_set *set, ip_set_ip_t ip)
|
||||
{
|
||||
struct ip_set_ipmap *map = set->data;
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
|
||||
DP("set: %s, ip:%u.%u.%u.%u", set->name, HIPQUAD(ip));
|
||||
if (test_and_set_bit(ip_to_id(map, ip), map->members))
|
||||
return -EEXIST;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
UADT(ipmap, add)
|
||||
KADT(ipmap, add, ipaddr)
|
||||
|
||||
static inline int
|
||||
ipmap_del(struct ip_set *set, ip_set_ip_t ip)
|
||||
{
|
||||
struct ip_set_ipmap *map = set->data;
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
|
||||
DP("set: %s, ip:%u.%u.%u.%u", set->name, HIPQUAD(ip));
|
||||
if (!test_and_clear_bit(ip_to_id(map, ip), map->members))
|
||||
return -EEXIST;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
UADT(ipmap, del)
|
||||
KADT(ipmap, del, ipaddr)
|
||||
|
||||
static inline int
|
||||
__ipmap_create(const struct ip_set_req_ipmap_create *req,
|
||||
struct ip_set_ipmap *map)
|
||||
{
|
||||
map->netmask = req->netmask;
|
||||
|
||||
if (req->netmask == 0xFFFFFFFF) {
|
||||
map->hosts = 1;
|
||||
map->sizeid = map->last_ip - map->first_ip + 1;
|
||||
} else {
|
||||
unsigned int mask_bits, netmask_bits;
|
||||
ip_set_ip_t mask;
|
||||
|
||||
map->first_ip &= map->netmask; /* Should we better bark? */
|
||||
|
||||
mask = range_to_mask(map->first_ip, map->last_ip, &mask_bits);
|
||||
netmask_bits = mask_to_bits(map->netmask);
|
||||
|
||||
if ((!mask && (map->first_ip || map->last_ip != 0xFFFFFFFF))
|
||||
|| netmask_bits <= mask_bits)
|
||||
return -ENOEXEC;
|
||||
|
||||
DP("mask_bits %u, netmask_bits %u",
|
||||
mask_bits, netmask_bits);
|
||||
map->hosts = 2 << (32 - netmask_bits - 1);
|
||||
map->sizeid = 2 << (netmask_bits - mask_bits - 1);
|
||||
}
|
||||
if (map->sizeid > MAX_RANGE + 1) {
|
||||
ip_set_printk("range too big, %d elements (max %d)",
|
||||
map->sizeid, MAX_RANGE+1);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
DP("hosts %u, sizeid %u", map->hosts, map->sizeid);
|
||||
return bitmap_bytes(0, map->sizeid - 1);
|
||||
}
|
||||
|
||||
BITMAP_CREATE(ipmap)
|
||||
BITMAP_DESTROY(ipmap)
|
||||
BITMAP_FLUSH(ipmap)
|
||||
|
||||
static inline void
|
||||
__ipmap_list_header(const struct ip_set_ipmap *map,
|
||||
struct ip_set_req_ipmap_create *header)
|
||||
{
|
||||
header->netmask = map->netmask;
|
||||
}
|
||||
|
||||
BITMAP_LIST_HEADER(ipmap)
|
||||
BITMAP_LIST_MEMBERS_SIZE(ipmap, ip_set_ip_t, map->sizeid,
|
||||
test_bit(i, map->members))
|
||||
|
||||
static void
|
||||
ipmap_list_members(const struct ip_set *set, void *data, char dont_align)
|
||||
{
|
||||
const struct ip_set_ipmap *map = set->data;
|
||||
uint32_t i, n = 0;
|
||||
ip_set_ip_t *d;
|
||||
|
||||
if (dont_align) {
|
||||
memcpy(data, map->members, map->size);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < map->sizeid; i++)
|
||||
if (test_bit(i, map->members)) {
|
||||
d = data + n * IPSET_ALIGN(sizeof(ip_set_ip_t));
|
||||
*d = map->first_ip + i * map->hosts;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
IP_SET_TYPE(ipmap, IPSET_TYPE_IP | IPSET_DATA_SINGLE)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("ipmap type of IP sets");
|
||||
|
||||
REGISTER_MODULE(ipmap)
|
||||
@@ -1,57 +0,0 @@
|
||||
#ifndef __IP_SET_IPMAP_H
|
||||
#define __IP_SET_IPMAP_H
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_bitmaps.h"
|
||||
|
||||
#define SETTYPE_NAME "ipmap"
|
||||
|
||||
struct ip_set_ipmap {
|
||||
void *members; /* the ipmap proper */
|
||||
ip_set_ip_t first_ip; /* host byte order, included in range */
|
||||
ip_set_ip_t last_ip; /* host byte order, included in range */
|
||||
ip_set_ip_t netmask; /* subnet netmask */
|
||||
ip_set_ip_t sizeid; /* size of set in IPs */
|
||||
ip_set_ip_t hosts; /* number of hosts in a subnet */
|
||||
u_int32_t size; /* size of the ipmap proper */
|
||||
};
|
||||
|
||||
struct ip_set_req_ipmap_create {
|
||||
ip_set_ip_t from;
|
||||
ip_set_ip_t to;
|
||||
ip_set_ip_t netmask;
|
||||
};
|
||||
|
||||
struct ip_set_req_ipmap {
|
||||
ip_set_ip_t ip;
|
||||
};
|
||||
|
||||
static inline unsigned int
|
||||
mask_to_bits(ip_set_ip_t mask)
|
||||
{
|
||||
unsigned int bits = 32;
|
||||
ip_set_ip_t maskaddr;
|
||||
|
||||
if (mask == 0xFFFFFFFF)
|
||||
return bits;
|
||||
|
||||
maskaddr = 0xFFFFFFFE;
|
||||
while (--bits > 0 && maskaddr != mask)
|
||||
maskaddr <<= 1;
|
||||
|
||||
return bits;
|
||||
}
|
||||
|
||||
static inline ip_set_ip_t
|
||||
range_to_mask(ip_set_ip_t from, ip_set_ip_t to, unsigned int *bits)
|
||||
{
|
||||
ip_set_ip_t mask = 0xFFFFFFFE;
|
||||
|
||||
*bits = 32;
|
||||
while (--(*bits) > 0 && mask && (to & mask) != from)
|
||||
mask <<= 1;
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
#endif /* __IP_SET_IPMAP_H */
|
||||
@@ -1,197 +0,0 @@
|
||||
/* Copyright (C) 2003-2008 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an ip+port hash set */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/udp.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include "ip_set_jhash.h"
|
||||
#include <linux/errno.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/random.h>
|
||||
|
||||
#include <net/ip.h>
|
||||
|
||||
#include "ip_set_ipporthash.h"
|
||||
#include "ip_set_getport.h"
|
||||
|
||||
static int limit = MAX_RANGE;
|
||||
|
||||
static inline __u32
|
||||
ipporthash_id(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port)
|
||||
{
|
||||
struct ip_set_ipporthash *map = set->data;
|
||||
__u32 id;
|
||||
u_int16_t i;
|
||||
ip_set_ip_t *elem;
|
||||
|
||||
ip = pack_ip_port(map, ip, port);
|
||||
|
||||
if (!ip)
|
||||
return UINT_MAX;
|
||||
|
||||
for (i = 0; i < map->probes; i++) {
|
||||
id = jhash_ip(map, i, ip) % map->hashsize;
|
||||
DP("hash key: %u", id);
|
||||
elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id);
|
||||
if (*elem == ip)
|
||||
return id;
|
||||
/* No shortcut - there can be deleted entries. */
|
||||
}
|
||||
return UINT_MAX;
|
||||
}
|
||||
|
||||
static inline int
|
||||
ipporthash_test(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port)
|
||||
{
|
||||
struct ip_set_ipporthash *map = set->data;
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
|
||||
return (ipporthash_id(set, ip, port) != UINT_MAX);
|
||||
}
|
||||
|
||||
#define KADT_CONDITION \
|
||||
ip_set_ip_t port; \
|
||||
\
|
||||
if (flags[1] == 0) \
|
||||
return 0; \
|
||||
\
|
||||
port = get_port(skb, ++flags); \
|
||||
\
|
||||
if (port == INVALID_PORT) \
|
||||
return 0;
|
||||
|
||||
UADT(ipporthash, test, req->port)
|
||||
KADT(ipporthash, test, ipaddr, port)
|
||||
|
||||
static inline int
|
||||
__ipporthash_add(struct ip_set_ipporthash *map, ip_set_ip_t *ip)
|
||||
{
|
||||
__u32 probe;
|
||||
u_int16_t i;
|
||||
ip_set_ip_t *elem, *slot = NULL;
|
||||
|
||||
for (i = 0; i < map->probes; i++) {
|
||||
probe = jhash_ip(map, i, *ip) % map->hashsize;
|
||||
elem = HARRAY_ELEM(map->members, ip_set_ip_t *, probe);
|
||||
if (*elem == *ip)
|
||||
return -EEXIST;
|
||||
if (!(slot || *elem))
|
||||
slot = elem;
|
||||
/* There can be deleted entries, must check all slots */
|
||||
}
|
||||
if (slot) {
|
||||
*slot = *ip;
|
||||
map->elements++;
|
||||
return 0;
|
||||
}
|
||||
/* Trigger rehashing */
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
static inline int
|
||||
ipporthash_add(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port)
|
||||
{
|
||||
struct ip_set_ipporthash *map = set->data;
|
||||
if (map->elements > limit)
|
||||
return -ERANGE;
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
|
||||
ip = pack_ip_port(map, ip, port);
|
||||
|
||||
if (!ip)
|
||||
return -ERANGE;
|
||||
|
||||
return __ipporthash_add(map, &ip);
|
||||
}
|
||||
|
||||
UADT(ipporthash, add, req->port)
|
||||
KADT(ipporthash, add, ipaddr, port)
|
||||
|
||||
static inline void
|
||||
__ipporthash_retry(struct ip_set_ipporthash *tmp,
|
||||
struct ip_set_ipporthash *map)
|
||||
{
|
||||
tmp->first_ip = map->first_ip;
|
||||
tmp->last_ip = map->last_ip;
|
||||
}
|
||||
|
||||
HASH_RETRY(ipporthash, ip_set_ip_t)
|
||||
|
||||
static inline int
|
||||
ipporthash_del(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port)
|
||||
{
|
||||
struct ip_set_ipporthash *map = set->data;
|
||||
ip_set_ip_t id;
|
||||
ip_set_ip_t *elem;
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
|
||||
id = ipporthash_id(set, ip, port);
|
||||
|
||||
if (id == UINT_MAX)
|
||||
return -EEXIST;
|
||||
|
||||
elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id);
|
||||
*elem = 0;
|
||||
map->elements--;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
UADT(ipporthash, del, req->port)
|
||||
KADT(ipporthash, del, ipaddr, port)
|
||||
|
||||
static inline int
|
||||
__ipporthash_create(const struct ip_set_req_ipporthash_create *req,
|
||||
struct ip_set_ipporthash *map)
|
||||
{
|
||||
if (req->to - req->from > MAX_RANGE) {
|
||||
ip_set_printk("range too big, %d elements (max %d)",
|
||||
req->to - req->from + 1, MAX_RANGE+1);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
map->first_ip = req->from;
|
||||
map->last_ip = req->to;
|
||||
return 0;
|
||||
}
|
||||
|
||||
HASH_CREATE(ipporthash, ip_set_ip_t)
|
||||
HASH_DESTROY(ipporthash)
|
||||
HASH_FLUSH(ipporthash, ip_set_ip_t)
|
||||
|
||||
static inline void
|
||||
__ipporthash_list_header(const struct ip_set_ipporthash *map,
|
||||
struct ip_set_req_ipporthash_create *header)
|
||||
{
|
||||
header->from = map->first_ip;
|
||||
header->to = map->last_ip;
|
||||
}
|
||||
|
||||
HASH_LIST_HEADER(ipporthash)
|
||||
HASH_LIST_MEMBERS_SIZE(ipporthash, ip_set_ip_t)
|
||||
HASH_LIST_MEMBERS(ipporthash, ip_set_ip_t)
|
||||
|
||||
IP_SET_RTYPE(ipporthash, IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_DATA_DOUBLE)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("ipporthash type of IP sets");
|
||||
module_param(limit, int, 0600);
|
||||
MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets");
|
||||
|
||||
REGISTER_MODULE(ipporthash)
|
||||
@@ -1,33 +0,0 @@
|
||||
#ifndef __IP_SET_IPPORTHASH_H
|
||||
#define __IP_SET_IPPORTHASH_H
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_hashes.h"
|
||||
|
||||
#define SETTYPE_NAME "ipporthash"
|
||||
|
||||
struct ip_set_ipporthash {
|
||||
ip_set_ip_t *members; /* the ipporthash proper */
|
||||
uint32_t elements; /* number of elements */
|
||||
uint32_t hashsize; /* hash size */
|
||||
uint16_t probes; /* max number of probes */
|
||||
uint16_t resize; /* resize factor in percent */
|
||||
ip_set_ip_t first_ip; /* host byte order, included in range */
|
||||
ip_set_ip_t last_ip; /* host byte order, included in range */
|
||||
initval_t initval[0]; /* initvals for jhash_1word */
|
||||
};
|
||||
|
||||
struct ip_set_req_ipporthash_create {
|
||||
uint32_t hashsize;
|
||||
uint16_t probes;
|
||||
uint16_t resize;
|
||||
ip_set_ip_t from;
|
||||
ip_set_ip_t to;
|
||||
};
|
||||
|
||||
struct ip_set_req_ipporthash {
|
||||
ip_set_ip_t ip;
|
||||
ip_set_ip_t port;
|
||||
};
|
||||
|
||||
#endif /* __IP_SET_IPPORTHASH_H */
|
||||
@@ -1,215 +0,0 @@
|
||||
/* Copyright (C) 2008 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an ip+port+ip hash set */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/udp.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include "ip_set_jhash.h"
|
||||
#include <linux/errno.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/random.h>
|
||||
|
||||
#include <net/ip.h>
|
||||
|
||||
#include "ip_set_ipportiphash.h"
|
||||
#include "ip_set_getport.h"
|
||||
|
||||
static int limit = MAX_RANGE;
|
||||
|
||||
#define jhash_ip2(map, i, ipport, ip1) \
|
||||
jhash_2words(ipport, ip1, *(map->initval + i))
|
||||
|
||||
static inline __u32
|
||||
ipportiphash_id(struct ip_set *set,
|
||||
ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1)
|
||||
{
|
||||
struct ip_set_ipportiphash *map = set->data;
|
||||
__u32 id;
|
||||
u_int16_t i;
|
||||
struct ipportip *elem;
|
||||
|
||||
ip = pack_ip_port(map, ip, port);
|
||||
if (!(ip || ip1))
|
||||
return UINT_MAX;
|
||||
|
||||
for (i = 0; i < map->probes; i++) {
|
||||
id = jhash_ip2(map, i, ip, ip1) % map->hashsize;
|
||||
DP("hash key: %u", id);
|
||||
elem = HARRAY_ELEM(map->members, struct ipportip *, id);
|
||||
if (elem->ip == ip && elem->ip1 == ip1)
|
||||
return id;
|
||||
/* No shortcut - there can be deleted entries. */
|
||||
}
|
||||
return UINT_MAX;
|
||||
}
|
||||
|
||||
static inline int
|
||||
ipportiphash_test(struct ip_set *set,
|
||||
ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1)
|
||||
{
|
||||
struct ip_set_ipportiphash *map = set->data;
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
|
||||
return (ipportiphash_id(set, ip, port, ip1) != UINT_MAX);
|
||||
}
|
||||
|
||||
#define KADT_CONDITION \
|
||||
ip_set_ip_t port, ip1; \
|
||||
\
|
||||
if (flags[2] == 0) \
|
||||
return 0; \
|
||||
\
|
||||
port = get_port(skb, ++flags); \
|
||||
ip1 = ipaddr(skb, ++flags); \
|
||||
\
|
||||
if (port == INVALID_PORT) \
|
||||
return 0;
|
||||
|
||||
UADT(ipportiphash, test, req->port, req->ip1)
|
||||
KADT(ipportiphash, test, ipaddr, port, ip1)
|
||||
|
||||
static inline int
|
||||
__ipportip_add(struct ip_set_ipportiphash *map,
|
||||
ip_set_ip_t ip, ip_set_ip_t ip1)
|
||||
{
|
||||
__u32 probe;
|
||||
u_int16_t i;
|
||||
struct ipportip *elem, *slot = NULL;
|
||||
|
||||
for (i = 0; i < map->probes; i++) {
|
||||
probe = jhash_ip2(map, i, ip, ip1) % map->hashsize;
|
||||
elem = HARRAY_ELEM(map->members, struct ipportip *, probe);
|
||||
if (elem->ip == ip && elem->ip1 == ip1)
|
||||
return -EEXIST;
|
||||
if (!(slot || elem->ip || elem->ip1))
|
||||
slot = elem;
|
||||
/* There can be deleted entries, must check all slots */
|
||||
}
|
||||
if (slot) {
|
||||
slot->ip = ip;
|
||||
slot->ip1 = ip1;
|
||||
map->elements++;
|
||||
return 0;
|
||||
}
|
||||
/* Trigger rehashing */
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
static inline int
|
||||
__ipportiphash_add(struct ip_set_ipportiphash *map,
|
||||
struct ipportip *elem)
|
||||
{
|
||||
return __ipportip_add(map, elem->ip, elem->ip1);
|
||||
}
|
||||
|
||||
static inline int
|
||||
ipportiphash_add(struct ip_set *set,
|
||||
ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1)
|
||||
{
|
||||
struct ip_set_ipportiphash *map = set->data;
|
||||
|
||||
if (map->elements > limit)
|
||||
return -ERANGE;
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
|
||||
ip = pack_ip_port(map, ip, port);
|
||||
if (!(ip || ip1))
|
||||
return -ERANGE;
|
||||
|
||||
return __ipportip_add(map, ip, ip1);
|
||||
}
|
||||
|
||||
UADT(ipportiphash, add, req->port, req->ip1)
|
||||
KADT(ipportiphash, add, ipaddr, port, ip1)
|
||||
|
||||
static inline void
|
||||
__ipportiphash_retry(struct ip_set_ipportiphash *tmp,
|
||||
struct ip_set_ipportiphash *map)
|
||||
{
|
||||
tmp->first_ip = map->first_ip;
|
||||
tmp->last_ip = map->last_ip;
|
||||
}
|
||||
|
||||
HASH_RETRY2(ipportiphash, struct ipportip)
|
||||
|
||||
static inline int
|
||||
ipportiphash_del(struct ip_set *set,
|
||||
ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1)
|
||||
{
|
||||
struct ip_set_ipportiphash *map = set->data;
|
||||
ip_set_ip_t id;
|
||||
struct ipportip *elem;
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
|
||||
id = ipportiphash_id(set, ip, port, ip1);
|
||||
|
||||
if (id == UINT_MAX)
|
||||
return -EEXIST;
|
||||
|
||||
elem = HARRAY_ELEM(map->members, struct ipportip *, id);
|
||||
elem->ip = elem->ip1 = 0;
|
||||
map->elements--;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
UADT(ipportiphash, del, req->port, req->ip1)
|
||||
KADT(ipportiphash, del, ipaddr, port, ip1)
|
||||
|
||||
static inline int
|
||||
__ipportiphash_create(const struct ip_set_req_ipportiphash_create *req,
|
||||
struct ip_set_ipportiphash *map)
|
||||
{
|
||||
if (req->to - req->from > MAX_RANGE) {
|
||||
ip_set_printk("range too big, %d elements (max %d)",
|
||||
req->to - req->from + 1, MAX_RANGE+1);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
map->first_ip = req->from;
|
||||
map->last_ip = req->to;
|
||||
return 0;
|
||||
}
|
||||
|
||||
HASH_CREATE(ipportiphash, struct ipportip)
|
||||
HASH_DESTROY(ipportiphash)
|
||||
HASH_FLUSH(ipportiphash, struct ipportip)
|
||||
|
||||
static inline void
|
||||
__ipportiphash_list_header(const struct ip_set_ipportiphash *map,
|
||||
struct ip_set_req_ipportiphash_create *header)
|
||||
{
|
||||
header->from = map->first_ip;
|
||||
header->to = map->last_ip;
|
||||
}
|
||||
|
||||
HASH_LIST_HEADER(ipportiphash)
|
||||
HASH_LIST_MEMBERS_SIZE(ipportiphash, struct ipportip)
|
||||
HASH_LIST_MEMBERS_MEMCPY(ipportiphash, struct ipportip,
|
||||
(elem->ip || elem->ip1))
|
||||
|
||||
IP_SET_RTYPE(ipportiphash, IPSET_TYPE_IP | IPSET_TYPE_PORT
|
||||
| IPSET_TYPE_IP1 | IPSET_DATA_TRIPLE)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("ipportiphash type of IP sets");
|
||||
module_param(limit, int, 0600);
|
||||
MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets");
|
||||
|
||||
REGISTER_MODULE(ipportiphash)
|
||||
@@ -1,39 +0,0 @@
|
||||
#ifndef __IP_SET_IPPORTIPHASH_H
|
||||
#define __IP_SET_IPPORTIPHASH_H
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_hashes.h"
|
||||
|
||||
#define SETTYPE_NAME "ipportiphash"
|
||||
|
||||
struct ipportip {
|
||||
ip_set_ip_t ip;
|
||||
ip_set_ip_t ip1;
|
||||
};
|
||||
|
||||
struct ip_set_ipportiphash {
|
||||
struct ipportip *members; /* the ipportip proper */
|
||||
uint32_t elements; /* number of elements */
|
||||
uint32_t hashsize; /* hash size */
|
||||
uint16_t probes; /* max number of probes */
|
||||
uint16_t resize; /* resize factor in percent */
|
||||
ip_set_ip_t first_ip; /* host byte order, included in range */
|
||||
ip_set_ip_t last_ip; /* host byte order, included in range */
|
||||
initval_t initval[0]; /* initvals for jhash_1word */
|
||||
};
|
||||
|
||||
struct ip_set_req_ipportiphash_create {
|
||||
uint32_t hashsize;
|
||||
uint16_t probes;
|
||||
uint16_t resize;
|
||||
ip_set_ip_t from;
|
||||
ip_set_ip_t to;
|
||||
};
|
||||
|
||||
struct ip_set_req_ipportiphash {
|
||||
ip_set_ip_t ip;
|
||||
ip_set_ip_t port;
|
||||
ip_set_ip_t ip1;
|
||||
};
|
||||
|
||||
#endif /* __IP_SET_IPPORTIPHASH_H */
|
||||
@@ -1,298 +0,0 @@
|
||||
/* Copyright (C) 2008 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an ip+port+net hash set */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/udp.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include "ip_set_jhash.h"
|
||||
#include <linux/errno.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/random.h>
|
||||
|
||||
#include <net/ip.h>
|
||||
|
||||
#include "ip_set_ipportnethash.h"
|
||||
#include "ip_set_getport.h"
|
||||
|
||||
static int limit = MAX_RANGE;
|
||||
|
||||
#define jhash_ip2(map, i, ipport, ip1) \
|
||||
jhash_2words(ipport, ip1, *(map->initval + i))
|
||||
|
||||
static inline __u32
|
||||
ipportnethash_id_cidr(struct ip_set *set,
|
||||
ip_set_ip_t ip, ip_set_ip_t port,
|
||||
ip_set_ip_t ip1, uint8_t cidr)
|
||||
{
|
||||
struct ip_set_ipportnethash *map = set->data;
|
||||
__u32 id;
|
||||
u_int16_t i;
|
||||
struct ipportip *elem;
|
||||
|
||||
ip = pack_ip_port(map, ip, port);
|
||||
ip1 = pack_ip_cidr(ip1, cidr);
|
||||
if (!(ip || ip1))
|
||||
return UINT_MAX;
|
||||
|
||||
for (i = 0; i < map->probes; i++) {
|
||||
id = jhash_ip2(map, i, ip, ip1) % map->hashsize;
|
||||
DP("hash key: %u", id);
|
||||
elem = HARRAY_ELEM(map->members, struct ipportip *, id);
|
||||
if (elem->ip == ip && elem->ip1 == ip1)
|
||||
return id;
|
||||
/* No shortcut - there can be deleted entries. */
|
||||
}
|
||||
return UINT_MAX;
|
||||
}
|
||||
|
||||
static inline __u32
|
||||
ipportnethash_id(struct ip_set *set,
|
||||
ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1)
|
||||
{
|
||||
struct ip_set_ipportnethash *map = set->data;
|
||||
__u32 id = UINT_MAX;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 30 && map->cidr[i]; i++) {
|
||||
id = ipportnethash_id_cidr(set, ip, port, ip1, map->cidr[i]);
|
||||
if (id != UINT_MAX)
|
||||
break;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
static inline int
|
||||
ipportnethash_test_cidr(struct ip_set *set,
|
||||
ip_set_ip_t ip, ip_set_ip_t port,
|
||||
ip_set_ip_t ip1, uint8_t cidr)
|
||||
{
|
||||
struct ip_set_ipportnethash *map = set->data;
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
|
||||
return (ipportnethash_id_cidr(set, ip, port, ip1, cidr) != UINT_MAX);
|
||||
}
|
||||
|
||||
static inline int
|
||||
ipportnethash_test(struct ip_set *set,
|
||||
ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1)
|
||||
{
|
||||
struct ip_set_ipportnethash *map = set->data;
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
|
||||
return (ipportnethash_id(set, ip, port, ip1) != UINT_MAX);
|
||||
}
|
||||
|
||||
static int
|
||||
ipportnethash_utest(struct ip_set *set, const void *data, u_int32_t size)
|
||||
{
|
||||
const struct ip_set_req_ipportnethash *req = data;
|
||||
|
||||
if (req->cidr <= 0 || req->cidr > 32)
|
||||
return -EINVAL;
|
||||
return (req->cidr == 32
|
||||
? ipportnethash_test(set, req->ip, req->port, req->ip1)
|
||||
: ipportnethash_test_cidr(set, req->ip, req->port,
|
||||
req->ip1, req->cidr));
|
||||
}
|
||||
|
||||
#define KADT_CONDITION \
|
||||
ip_set_ip_t port, ip1; \
|
||||
\
|
||||
if (flags[2] == 0) \
|
||||
return 0; \
|
||||
\
|
||||
port = get_port(skb, ++flags); \
|
||||
ip1 = ipaddr(skb, ++flags); \
|
||||
\
|
||||
if (port == INVALID_PORT) \
|
||||
return 0;
|
||||
|
||||
KADT(ipportnethash, test, ipaddr, port, ip1)
|
||||
|
||||
static inline int
|
||||
__ipportnet_add(struct ip_set_ipportnethash *map,
|
||||
ip_set_ip_t ip, ip_set_ip_t ip1)
|
||||
{
|
||||
__u32 probe;
|
||||
u_int16_t i;
|
||||
struct ipportip *elem, *slot = NULL;
|
||||
|
||||
for (i = 0; i < map->probes; i++) {
|
||||
probe = jhash_ip2(map, i, ip, ip1) % map->hashsize;
|
||||
elem = HARRAY_ELEM(map->members, struct ipportip *, probe);
|
||||
if (elem->ip == ip && elem->ip1 == ip1)
|
||||
return -EEXIST;
|
||||
if (!(slot || elem->ip || elem->ip1))
|
||||
slot = elem;
|
||||
/* There can be deleted entries, must check all slots */
|
||||
}
|
||||
if (slot) {
|
||||
slot->ip = ip;
|
||||
slot->ip1 = ip1;
|
||||
map->elements++;
|
||||
return 0;
|
||||
}
|
||||
/* Trigger rehashing */
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
static inline int
|
||||
__ipportnethash_add(struct ip_set_ipportnethash *map,
|
||||
struct ipportip *elem)
|
||||
{
|
||||
return __ipportnet_add(map, elem->ip, elem->ip1);
|
||||
}
|
||||
|
||||
static inline int
|
||||
ipportnethash_add(struct ip_set *set,
|
||||
ip_set_ip_t ip, ip_set_ip_t port,
|
||||
ip_set_ip_t ip1, uint8_t cidr)
|
||||
{
|
||||
struct ip_set_ipportnethash *map = set->data;
|
||||
struct ipportip;
|
||||
int ret;
|
||||
|
||||
if (map->elements > limit)
|
||||
return -ERANGE;
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
if (cidr <= 0 || cidr >= 32)
|
||||
return -EINVAL;
|
||||
if (map->nets[cidr-1] == UINT16_MAX)
|
||||
return -ERANGE;
|
||||
|
||||
ip = pack_ip_port(map, ip, port);
|
||||
ip1 = pack_ip_cidr(ip1, cidr);
|
||||
if (!(ip || ip1))
|
||||
return -ERANGE;
|
||||
|
||||
ret =__ipportnet_add(map, ip, ip1);
|
||||
if (ret == 0) {
|
||||
if (!map->nets[cidr-1]++)
|
||||
add_cidr_size(map->cidr, cidr);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef KADT_CONDITION
|
||||
#define KADT_CONDITION \
|
||||
struct ip_set_ipportnethash *map = set->data; \
|
||||
uint8_t cidr = map->cidr[0] ? map->cidr[0] : 31; \
|
||||
ip_set_ip_t port, ip1; \
|
||||
\
|
||||
if (flags[2] == 0) \
|
||||
return 0; \
|
||||
\
|
||||
port = get_port(skb, flags++); \
|
||||
ip1 = ipaddr(skb, flags++); \
|
||||
\
|
||||
if (port == INVALID_PORT) \
|
||||
return 0;
|
||||
|
||||
UADT(ipportnethash, add, req->port, req->ip1, req->cidr)
|
||||
KADT(ipportnethash, add, ipaddr, port, ip1, cidr)
|
||||
|
||||
static inline void
|
||||
__ipportnethash_retry(struct ip_set_ipportnethash *tmp,
|
||||
struct ip_set_ipportnethash *map)
|
||||
{
|
||||
tmp->first_ip = map->first_ip;
|
||||
tmp->last_ip = map->last_ip;
|
||||
memcpy(tmp->cidr, map->cidr, sizeof(tmp->cidr));
|
||||
memcpy(tmp->nets, map->nets, sizeof(tmp->nets));
|
||||
}
|
||||
|
||||
HASH_RETRY2(ipportnethash, struct ipportip)
|
||||
|
||||
static inline int
|
||||
ipportnethash_del(struct ip_set *set,
|
||||
ip_set_ip_t ip, ip_set_ip_t port,
|
||||
ip_set_ip_t ip1, uint8_t cidr)
|
||||
{
|
||||
struct ip_set_ipportnethash *map = set->data;
|
||||
ip_set_ip_t id;
|
||||
struct ipportip *elem;
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
if (!ip)
|
||||
return -ERANGE;
|
||||
if (cidr <= 0 || cidr >= 32)
|
||||
return -EINVAL;
|
||||
|
||||
id = ipportnethash_id_cidr(set, ip, port, ip1, cidr);
|
||||
|
||||
if (id == UINT_MAX)
|
||||
return -EEXIST;
|
||||
|
||||
elem = HARRAY_ELEM(map->members, struct ipportip *, id);
|
||||
elem->ip = elem->ip1 = 0;
|
||||
map->elements--;
|
||||
if (!map->nets[cidr-1]--)
|
||||
del_cidr_size(map->cidr, cidr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
UADT(ipportnethash, del, req->port, req->ip1, req->cidr)
|
||||
KADT(ipportnethash, del, ipaddr, port, ip1, cidr)
|
||||
|
||||
static inline int
|
||||
__ipportnethash_create(const struct ip_set_req_ipportnethash_create *req,
|
||||
struct ip_set_ipportnethash *map)
|
||||
{
|
||||
if (req->to - req->from > MAX_RANGE) {
|
||||
ip_set_printk("range too big, %d elements (max %d)",
|
||||
req->to - req->from + 1, MAX_RANGE+1);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
map->first_ip = req->from;
|
||||
map->last_ip = req->to;
|
||||
memset(map->cidr, 0, sizeof(map->cidr));
|
||||
memset(map->nets, 0, sizeof(map->nets));
|
||||
return 0;
|
||||
}
|
||||
|
||||
HASH_CREATE(ipportnethash, struct ipportip)
|
||||
HASH_DESTROY(ipportnethash)
|
||||
HASH_FLUSH_CIDR(ipportnethash, struct ipportip);
|
||||
|
||||
static inline void
|
||||
__ipportnethash_list_header(const struct ip_set_ipportnethash *map,
|
||||
struct ip_set_req_ipportnethash_create *header)
|
||||
{
|
||||
header->from = map->first_ip;
|
||||
header->to = map->last_ip;
|
||||
}
|
||||
|
||||
HASH_LIST_HEADER(ipportnethash)
|
||||
|
||||
HASH_LIST_MEMBERS_SIZE(ipportnethash, struct ipportip)
|
||||
HASH_LIST_MEMBERS_MEMCPY(ipportnethash, struct ipportip,
|
||||
(elem->ip || elem->ip1))
|
||||
|
||||
IP_SET_RTYPE(ipportnethash, IPSET_TYPE_IP | IPSET_TYPE_PORT
|
||||
| IPSET_TYPE_IP1 | IPSET_DATA_TRIPLE)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("ipportnethash type of IP sets");
|
||||
module_param(limit, int, 0600);
|
||||
MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets");
|
||||
|
||||
REGISTER_MODULE(ipportnethash)
|
||||
@@ -1,42 +0,0 @@
|
||||
#ifndef __IP_SET_IPPORTNETHASH_H
|
||||
#define __IP_SET_IPPORTNETHASH_H
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_hashes.h"
|
||||
|
||||
#define SETTYPE_NAME "ipportnethash"
|
||||
|
||||
struct ipportip {
|
||||
ip_set_ip_t ip;
|
||||
ip_set_ip_t ip1;
|
||||
};
|
||||
|
||||
struct ip_set_ipportnethash {
|
||||
struct ipportip *members; /* the ipportip proper */
|
||||
uint32_t elements; /* number of elements */
|
||||
uint32_t hashsize; /* hash size */
|
||||
uint16_t probes; /* max number of probes */
|
||||
uint16_t resize; /* resize factor in percent */
|
||||
ip_set_ip_t first_ip; /* host byte order, included in range */
|
||||
ip_set_ip_t last_ip; /* host byte order, included in range */
|
||||
uint8_t cidr[30]; /* CIDR sizes */
|
||||
uint16_t nets[30]; /* nr of nets by CIDR sizes */
|
||||
initval_t initval[0]; /* initvals for jhash_1word */
|
||||
};
|
||||
|
||||
struct ip_set_req_ipportnethash_create {
|
||||
uint32_t hashsize;
|
||||
uint16_t probes;
|
||||
uint16_t resize;
|
||||
ip_set_ip_t from;
|
||||
ip_set_ip_t to;
|
||||
};
|
||||
|
||||
struct ip_set_req_ipportnethash {
|
||||
ip_set_ip_t ip;
|
||||
ip_set_ip_t port;
|
||||
ip_set_ip_t ip1;
|
||||
uint8_t cidr;
|
||||
};
|
||||
|
||||
#endif /* __IP_SET_IPPORTNETHASH_H */
|
||||
@@ -1,464 +0,0 @@
|
||||
/* Copyright (C) 2005-2008 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an IP set type: the iptree type */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/errno.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/timer.h>
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_bitmaps.h"
|
||||
#include "ip_set_iptree.h"
|
||||
|
||||
static int limit = MAX_RANGE;
|
||||
|
||||
/* Garbage collection interval in seconds: */
|
||||
#define IPTREE_GC_TIME 5*60
|
||||
/* Sleep so many milliseconds before trying again
|
||||
* to delete the gc timer at destroying/flushing a set */
|
||||
#define IPTREE_DESTROY_SLEEP 100
|
||||
|
||||
static __KMEM_CACHE_T__ *branch_cachep;
|
||||
static __KMEM_CACHE_T__ *leaf_cachep;
|
||||
|
||||
|
||||
#if defined(__LITTLE_ENDIAN)
|
||||
#define ABCD(a,b,c,d,addrp) do { \
|
||||
a = ((unsigned char *)addrp)[3]; \
|
||||
b = ((unsigned char *)addrp)[2]; \
|
||||
c = ((unsigned char *)addrp)[1]; \
|
||||
d = ((unsigned char *)addrp)[0]; \
|
||||
} while (0)
|
||||
#elif defined(__BIG_ENDIAN)
|
||||
#define ABCD(a,b,c,d,addrp) do { \
|
||||
a = ((unsigned char *)addrp)[0]; \
|
||||
b = ((unsigned char *)addrp)[1]; \
|
||||
c = ((unsigned char *)addrp)[2]; \
|
||||
d = ((unsigned char *)addrp)[3]; \
|
||||
} while (0)
|
||||
#else
|
||||
#error "Please fix asm/byteorder.h"
|
||||
#endif /* __LITTLE_ENDIAN */
|
||||
|
||||
#define TESTIP_WALK(map, elem, branch) do { \
|
||||
if ((map)->tree[elem]) { \
|
||||
branch = (map)->tree[elem]; \
|
||||
} else \
|
||||
return 0; \
|
||||
} while (0)
|
||||
|
||||
static inline int
|
||||
iptree_test(struct ip_set *set, ip_set_ip_t ip)
|
||||
{
|
||||
struct ip_set_iptree *map = set->data;
|
||||
struct ip_set_iptreeb *btree;
|
||||
struct ip_set_iptreec *ctree;
|
||||
struct ip_set_iptreed *dtree;
|
||||
unsigned char a,b,c,d;
|
||||
|
||||
if (!ip)
|
||||
return -ERANGE;
|
||||
|
||||
ABCD(a, b, c, d, &ip);
|
||||
DP("%u %u %u %u timeout %u", a, b, c, d, map->timeout);
|
||||
TESTIP_WALK(map, a, btree);
|
||||
TESTIP_WALK(btree, b, ctree);
|
||||
TESTIP_WALK(ctree, c, dtree);
|
||||
DP("%lu %lu", dtree->expires[d], jiffies);
|
||||
return dtree->expires[d]
|
||||
&& (!map->timeout
|
||||
|| time_after(dtree->expires[d], jiffies));
|
||||
}
|
||||
|
||||
#define KADT_CONDITION
|
||||
|
||||
UADT(iptree, test)
|
||||
KADT(iptree, test, ipaddr)
|
||||
|
||||
#define ADDIP_WALK(map, elem, branch, type, cachep) do { \
|
||||
if ((map)->tree[elem]) { \
|
||||
DP("found %u", elem); \
|
||||
branch = (map)->tree[elem]; \
|
||||
} else { \
|
||||
branch = (type *) \
|
||||
kmem_cache_alloc(cachep, GFP_ATOMIC); \
|
||||
if (branch == NULL) \
|
||||
return -ENOMEM; \
|
||||
memset(branch, 0, sizeof(*branch)); \
|
||||
(map)->tree[elem] = branch; \
|
||||
DP("alloc %u", elem); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static inline int
|
||||
iptree_add(struct ip_set *set, ip_set_ip_t ip, unsigned int timeout)
|
||||
{
|
||||
struct ip_set_iptree *map = set->data;
|
||||
struct ip_set_iptreeb *btree;
|
||||
struct ip_set_iptreec *ctree;
|
||||
struct ip_set_iptreed *dtree;
|
||||
unsigned char a,b,c,d;
|
||||
int ret = 0;
|
||||
|
||||
if (!ip || map->elements >= limit)
|
||||
/* We could call the garbage collector
|
||||
* but it's probably overkill */
|
||||
return -ERANGE;
|
||||
|
||||
ABCD(a, b, c, d, &ip);
|
||||
DP("%u %u %u %u timeout %u", a, b, c, d, timeout);
|
||||
ADDIP_WALK(map, a, btree, struct ip_set_iptreeb, branch_cachep);
|
||||
ADDIP_WALK(btree, b, ctree, struct ip_set_iptreec, branch_cachep);
|
||||
ADDIP_WALK(ctree, c, dtree, struct ip_set_iptreed, leaf_cachep);
|
||||
if (dtree->expires[d]
|
||||
&& (!map->timeout || time_after(dtree->expires[d], jiffies)))
|
||||
ret = -EEXIST;
|
||||
if (map->timeout && timeout == 0)
|
||||
timeout = map->timeout;
|
||||
dtree->expires[d] = map->timeout ? (timeout * HZ + jiffies) : 1;
|
||||
/* Lottery: I won! */
|
||||
if (dtree->expires[d] == 0)
|
||||
dtree->expires[d] = 1;
|
||||
DP("%u %lu", d, dtree->expires[d]);
|
||||
if (ret == 0)
|
||||
map->elements++;
|
||||
return ret;
|
||||
}
|
||||
|
||||
UADT(iptree, add, req->timeout)
|
||||
KADT(iptree, add, ipaddr, 0)
|
||||
|
||||
#define DELIP_WALK(map, elem, branch) do { \
|
||||
if ((map)->tree[elem]) { \
|
||||
branch = (map)->tree[elem]; \
|
||||
} else \
|
||||
return -EEXIST; \
|
||||
} while (0)
|
||||
|
||||
static inline int
|
||||
iptree_del(struct ip_set *set, ip_set_ip_t ip)
|
||||
{
|
||||
struct ip_set_iptree *map = set->data;
|
||||
struct ip_set_iptreeb *btree;
|
||||
struct ip_set_iptreec *ctree;
|
||||
struct ip_set_iptreed *dtree;
|
||||
unsigned char a,b,c,d;
|
||||
|
||||
if (!ip)
|
||||
return -ERANGE;
|
||||
|
||||
ABCD(a, b, c, d, &ip);
|
||||
DELIP_WALK(map, a, btree);
|
||||
DELIP_WALK(btree, b, ctree);
|
||||
DELIP_WALK(ctree, c, dtree);
|
||||
|
||||
if (dtree->expires[d]) {
|
||||
dtree->expires[d] = 0;
|
||||
map->elements--;
|
||||
return 0;
|
||||
}
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
UADT(iptree, del)
|
||||
KADT(iptree, del, ipaddr)
|
||||
|
||||
#define LOOP_WALK_BEGIN(map, i, branch) \
|
||||
for (i = 0; i < 256; i++) { \
|
||||
if (!(map)->tree[i]) \
|
||||
continue; \
|
||||
branch = (map)->tree[i]
|
||||
|
||||
#define LOOP_WALK_END }
|
||||
|
||||
static void
|
||||
ip_tree_gc(unsigned long ul_set)
|
||||
{
|
||||
struct ip_set *set = (struct ip_set *) ul_set;
|
||||
struct ip_set_iptree *map = set->data;
|
||||
struct ip_set_iptreeb *btree;
|
||||
struct ip_set_iptreec *ctree;
|
||||
struct ip_set_iptreed *dtree;
|
||||
unsigned int a,b,c,d;
|
||||
unsigned char i,j,k;
|
||||
|
||||
i = j = k = 0;
|
||||
DP("gc: %s", set->name);
|
||||
write_lock_bh(&set->lock);
|
||||
LOOP_WALK_BEGIN(map, a, btree);
|
||||
LOOP_WALK_BEGIN(btree, b, ctree);
|
||||
LOOP_WALK_BEGIN(ctree, c, dtree);
|
||||
for (d = 0; d < 256; d++) {
|
||||
if (dtree->expires[d]) {
|
||||
DP("gc: %u %u %u %u: expires %lu jiffies %lu",
|
||||
a, b, c, d,
|
||||
dtree->expires[d], jiffies);
|
||||
if (map->timeout
|
||||
&& time_before(dtree->expires[d], jiffies)) {
|
||||
dtree->expires[d] = 0;
|
||||
map->elements--;
|
||||
} else
|
||||
k = 1;
|
||||
}
|
||||
}
|
||||
if (k == 0) {
|
||||
DP("gc: %s: leaf %u %u %u empty",
|
||||
set->name, a, b, c);
|
||||
kmem_cache_free(leaf_cachep, dtree);
|
||||
ctree->tree[c] = NULL;
|
||||
} else {
|
||||
DP("gc: %s: leaf %u %u %u not empty",
|
||||
set->name, a, b, c);
|
||||
j = 1;
|
||||
k = 0;
|
||||
}
|
||||
LOOP_WALK_END;
|
||||
if (j == 0) {
|
||||
DP("gc: %s: branch %u %u empty",
|
||||
set->name, a, b);
|
||||
kmem_cache_free(branch_cachep, ctree);
|
||||
btree->tree[b] = NULL;
|
||||
} else {
|
||||
DP("gc: %s: branch %u %u not empty",
|
||||
set->name, a, b);
|
||||
i = 1;
|
||||
j = k = 0;
|
||||
}
|
||||
LOOP_WALK_END;
|
||||
if (i == 0) {
|
||||
DP("gc: %s: branch %u empty",
|
||||
set->name, a);
|
||||
kmem_cache_free(branch_cachep, btree);
|
||||
map->tree[a] = NULL;
|
||||
} else {
|
||||
DP("gc: %s: branch %u not empty",
|
||||
set->name, a);
|
||||
i = j = k = 0;
|
||||
}
|
||||
LOOP_WALK_END;
|
||||
write_unlock_bh(&set->lock);
|
||||
|
||||
map->gc.expires = jiffies + map->gc_interval * HZ;
|
||||
add_timer(&map->gc);
|
||||
}
|
||||
|
||||
static inline void
|
||||
init_gc_timer(struct ip_set *set)
|
||||
{
|
||||
struct ip_set_iptree *map = set->data;
|
||||
|
||||
/* Even if there is no timeout for the entries,
|
||||
* we still have to call gc because delete
|
||||
* do not clean up empty branches */
|
||||
map->gc_interval = IPTREE_GC_TIME;
|
||||
init_timer(&map->gc);
|
||||
map->gc.data = (unsigned long) set;
|
||||
map->gc.function = ip_tree_gc;
|
||||
map->gc.expires = jiffies + map->gc_interval * HZ;
|
||||
add_timer(&map->gc);
|
||||
}
|
||||
|
||||
static int
|
||||
iptree_create(struct ip_set *set, const void *data, u_int32_t size)
|
||||
{
|
||||
const struct ip_set_req_iptree_create *req = data;
|
||||
struct ip_set_iptree *map;
|
||||
|
||||
if (size != sizeof(struct ip_set_req_iptree_create)) {
|
||||
ip_set_printk("data length wrong (want %zu, have %lu)",
|
||||
sizeof(struct ip_set_req_iptree_create),
|
||||
(unsigned long)size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
map = kmalloc(sizeof(struct ip_set_iptree), GFP_KERNEL);
|
||||
if (!map) {
|
||||
DP("out of memory for %zu bytes",
|
||||
sizeof(struct ip_set_iptree));
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(map, 0, sizeof(*map));
|
||||
map->timeout = req->timeout;
|
||||
map->elements = 0;
|
||||
set->data = map;
|
||||
|
||||
init_gc_timer(set);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
__flush(struct ip_set_iptree *map)
|
||||
{
|
||||
struct ip_set_iptreeb *btree;
|
||||
struct ip_set_iptreec *ctree;
|
||||
struct ip_set_iptreed *dtree;
|
||||
unsigned int a,b,c;
|
||||
|
||||
LOOP_WALK_BEGIN(map, a, btree);
|
||||
LOOP_WALK_BEGIN(btree, b, ctree);
|
||||
LOOP_WALK_BEGIN(ctree, c, dtree);
|
||||
kmem_cache_free(leaf_cachep, dtree);
|
||||
LOOP_WALK_END;
|
||||
kmem_cache_free(branch_cachep, ctree);
|
||||
LOOP_WALK_END;
|
||||
kmem_cache_free(branch_cachep, btree);
|
||||
LOOP_WALK_END;
|
||||
map->elements = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
iptree_destroy(struct ip_set *set)
|
||||
{
|
||||
struct ip_set_iptree *map = set->data;
|
||||
|
||||
/* gc might be running */
|
||||
while (!del_timer(&map->gc))
|
||||
msleep(IPTREE_DESTROY_SLEEP);
|
||||
__flush(map);
|
||||
kfree(map);
|
||||
set->data = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
iptree_flush(struct ip_set *set)
|
||||
{
|
||||
struct ip_set_iptree *map = set->data;
|
||||
unsigned int timeout = map->timeout;
|
||||
|
||||
/* gc might be running */
|
||||
while (!del_timer(&map->gc))
|
||||
msleep(IPTREE_DESTROY_SLEEP);
|
||||
__flush(map);
|
||||
memset(map, 0, sizeof(*map));
|
||||
map->timeout = timeout;
|
||||
|
||||
init_gc_timer(set);
|
||||
}
|
||||
|
||||
static void
|
||||
iptree_list_header(const struct ip_set *set, void *data)
|
||||
{
|
||||
const struct ip_set_iptree *map = set->data;
|
||||
struct ip_set_req_iptree_create *header = data;
|
||||
|
||||
header->timeout = map->timeout;
|
||||
}
|
||||
|
||||
static int
|
||||
iptree_list_members_size(const struct ip_set *set, char dont_align)
|
||||
{
|
||||
const struct ip_set_iptree *map = set->data;
|
||||
struct ip_set_iptreeb *btree;
|
||||
struct ip_set_iptreec *ctree;
|
||||
struct ip_set_iptreed *dtree;
|
||||
unsigned int a,b,c,d;
|
||||
unsigned int count = 0;
|
||||
|
||||
LOOP_WALK_BEGIN(map, a, btree);
|
||||
LOOP_WALK_BEGIN(btree, b, ctree);
|
||||
LOOP_WALK_BEGIN(ctree, c, dtree);
|
||||
for (d = 0; d < 256; d++) {
|
||||
if (dtree->expires[d]
|
||||
&& (!map->timeout || time_after(dtree->expires[d], jiffies)))
|
||||
count++;
|
||||
}
|
||||
LOOP_WALK_END;
|
||||
LOOP_WALK_END;
|
||||
LOOP_WALK_END;
|
||||
|
||||
DP("members %u", count);
|
||||
return (count * IPSET_VALIGN(sizeof(struct ip_set_req_iptree), dont_align));
|
||||
}
|
||||
|
||||
static void
|
||||
iptree_list_members(const struct ip_set *set, void *data, char dont_align)
|
||||
{
|
||||
const struct ip_set_iptree *map = set->data;
|
||||
struct ip_set_iptreeb *btree;
|
||||
struct ip_set_iptreec *ctree;
|
||||
struct ip_set_iptreed *dtree;
|
||||
unsigned int a,b,c,d;
|
||||
size_t offset = 0, datasize;
|
||||
struct ip_set_req_iptree *entry;
|
||||
|
||||
datasize = IPSET_VALIGN(sizeof(struct ip_set_req_iptree), dont_align);
|
||||
LOOP_WALK_BEGIN(map, a, btree);
|
||||
LOOP_WALK_BEGIN(btree, b, ctree);
|
||||
LOOP_WALK_BEGIN(ctree, c, dtree);
|
||||
for (d = 0; d < 256; d++) {
|
||||
if (dtree->expires[d]
|
||||
&& (!map->timeout || time_after(dtree->expires[d], jiffies))) {
|
||||
entry = data + offset;
|
||||
entry->ip = ((a << 24) | (b << 16) | (c << 8) | d);
|
||||
entry->timeout = !map->timeout ? 0
|
||||
: (dtree->expires[d] - jiffies)/HZ;
|
||||
offset += datasize;
|
||||
}
|
||||
}
|
||||
LOOP_WALK_END;
|
||||
LOOP_WALK_END;
|
||||
LOOP_WALK_END;
|
||||
}
|
||||
|
||||
IP_SET_TYPE(iptree, IPSET_TYPE_IP | IPSET_DATA_SINGLE)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("iptree type of IP sets");
|
||||
module_param(limit, int, 0600);
|
||||
MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets");
|
||||
|
||||
static int __init ip_set_iptree_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
branch_cachep = KMEM_CACHE_CREATE("ip_set_iptreeb",
|
||||
sizeof(struct ip_set_iptreeb));
|
||||
if (!branch_cachep) {
|
||||
printk(KERN_ERR "Unable to create ip_set_iptreeb slab cache\n");
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
leaf_cachep = KMEM_CACHE_CREATE("ip_set_iptreed",
|
||||
sizeof(struct ip_set_iptreed));
|
||||
if (!leaf_cachep) {
|
||||
printk(KERN_ERR "Unable to create ip_set_iptreed slab cache\n");
|
||||
ret = -ENOMEM;
|
||||
goto free_branch;
|
||||
}
|
||||
ret = ip_set_register_set_type(&ip_set_iptree);
|
||||
if (ret == 0)
|
||||
goto out;
|
||||
|
||||
kmem_cache_destroy(leaf_cachep);
|
||||
free_branch:
|
||||
kmem_cache_destroy(branch_cachep);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit ip_set_iptree_fini(void)
|
||||
{
|
||||
/* FIXME: possible race with ip_set_create() */
|
||||
ip_set_unregister_set_type(&ip_set_iptree);
|
||||
kmem_cache_destroy(leaf_cachep);
|
||||
kmem_cache_destroy(branch_cachep);
|
||||
}
|
||||
|
||||
module_init(ip_set_iptree_init);
|
||||
module_exit(ip_set_iptree_fini);
|
||||
@@ -1,39 +0,0 @@
|
||||
#ifndef __IP_SET_IPTREE_H
|
||||
#define __IP_SET_IPTREE_H
|
||||
|
||||
#include "ip_set.h"
|
||||
|
||||
#define SETTYPE_NAME "iptree"
|
||||
|
||||
struct ip_set_iptreed {
|
||||
unsigned long expires[256]; /* x.x.x.ADDR */
|
||||
};
|
||||
|
||||
struct ip_set_iptreec {
|
||||
struct ip_set_iptreed *tree[256]; /* x.x.ADDR.* */
|
||||
};
|
||||
|
||||
struct ip_set_iptreeb {
|
||||
struct ip_set_iptreec *tree[256]; /* x.ADDR.*.* */
|
||||
};
|
||||
|
||||
struct ip_set_iptree {
|
||||
unsigned int timeout;
|
||||
unsigned int gc_interval;
|
||||
#ifdef __KERNEL__
|
||||
uint32_t elements; /* number of elements */
|
||||
struct timer_list gc;
|
||||
struct ip_set_iptreeb *tree[256]; /* ADDR.*.*.* */
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ip_set_req_iptree_create {
|
||||
unsigned int timeout;
|
||||
};
|
||||
|
||||
struct ip_set_req_iptree {
|
||||
ip_set_ip_t ip;
|
||||
unsigned int timeout;
|
||||
};
|
||||
|
||||
#endif /* __IP_SET_IPTREE_H */
|
||||
@@ -1,699 +0,0 @@
|
||||
/* Copyright (C) 2007 Sven Wegener <sven.wegener@stealer.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* This modules implements the iptreemap ipset type. It uses bitmaps to
|
||||
* represent every single IPv4 address as a bit. The bitmaps are managed in a
|
||||
* tree structure, where the first three octets of an address are used as an
|
||||
* index to find the bitmap and the last octet is used as the bit number.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/errno.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/timer.h>
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_bitmaps.h"
|
||||
#include "ip_set_iptreemap.h"
|
||||
|
||||
#define IPTREEMAP_DEFAULT_GC_TIME (5 * 60)
|
||||
#define IPTREEMAP_DESTROY_SLEEP (100)
|
||||
|
||||
static __KMEM_CACHE_T__ *cachep_b;
|
||||
static __KMEM_CACHE_T__ *cachep_c;
|
||||
static __KMEM_CACHE_T__ *cachep_d;
|
||||
|
||||
static struct ip_set_iptreemap_d *fullbitmap_d;
|
||||
static struct ip_set_iptreemap_c *fullbitmap_c;
|
||||
static struct ip_set_iptreemap_b *fullbitmap_b;
|
||||
|
||||
#if defined(__LITTLE_ENDIAN)
|
||||
#define ABCD(a, b, c, d, addr) \
|
||||
do { \
|
||||
a = ((unsigned char *)addr)[3]; \
|
||||
b = ((unsigned char *)addr)[2]; \
|
||||
c = ((unsigned char *)addr)[1]; \
|
||||
d = ((unsigned char *)addr)[0]; \
|
||||
} while (0)
|
||||
#elif defined(__BIG_ENDIAN)
|
||||
#define ABCD(a,b,c,d,addrp) do { \
|
||||
a = ((unsigned char *)addrp)[0]; \
|
||||
b = ((unsigned char *)addrp)[1]; \
|
||||
c = ((unsigned char *)addrp)[2]; \
|
||||
d = ((unsigned char *)addrp)[3]; \
|
||||
} while (0)
|
||||
#else
|
||||
#error "Please fix asm/byteorder.h"
|
||||
#endif /* __LITTLE_ENDIAN */
|
||||
|
||||
#define TESTIP_WALK(map, elem, branch, full) \
|
||||
do { \
|
||||
branch = (map)->tree[elem]; \
|
||||
if (!branch) \
|
||||
return 0; \
|
||||
else if (branch == full) \
|
||||
return 1; \
|
||||
} while (0)
|
||||
|
||||
#define ADDIP_WALK(map, elem, branch, type, cachep, full) \
|
||||
do { \
|
||||
branch = (map)->tree[elem]; \
|
||||
if (!branch) { \
|
||||
branch = (type *) kmem_cache_alloc(cachep, GFP_ATOMIC); \
|
||||
if (!branch) \
|
||||
return -ENOMEM; \
|
||||
memset(branch, 0, sizeof(*branch)); \
|
||||
(map)->tree[elem] = branch; \
|
||||
} else if (branch == full) { \
|
||||
return -EEXIST; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ADDIP_RANGE_LOOP(map, a, a1, a2, hint, branch, full, cachep, free) \
|
||||
for (a = a1; a <= a2; a++) { \
|
||||
branch = (map)->tree[a]; \
|
||||
if (branch != full) { \
|
||||
if ((a > a1 && a < a2) || (hint)) { \
|
||||
if (branch) \
|
||||
free(branch); \
|
||||
(map)->tree[a] = full; \
|
||||
continue; \
|
||||
} else if (!branch) { \
|
||||
branch = kmem_cache_alloc(cachep, GFP_ATOMIC); \
|
||||
if (!branch) \
|
||||
return -ENOMEM; \
|
||||
memset(branch, 0, sizeof(*branch)); \
|
||||
(map)->tree[a] = branch; \
|
||||
}
|
||||
|
||||
#define ADDIP_RANGE_LOOP_END() \
|
||||
} \
|
||||
}
|
||||
|
||||
#define DELIP_WALK(map, elem, branch, cachep, full) \
|
||||
do { \
|
||||
branch = (map)->tree[elem]; \
|
||||
if (!branch) { \
|
||||
return -EEXIST; \
|
||||
} else if (branch == full) { \
|
||||
branch = kmem_cache_alloc(cachep, GFP_ATOMIC); \
|
||||
if (!branch) \
|
||||
return -ENOMEM; \
|
||||
memcpy(branch, full, sizeof(*full)); \
|
||||
(map)->tree[elem] = branch; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DELIP_RANGE_LOOP(map, a, a1, a2, hint, branch, full, cachep, free) \
|
||||
for (a = a1; a <= a2; a++) { \
|
||||
branch = (map)->tree[a]; \
|
||||
if (branch) { \
|
||||
if ((a > a1 && a < a2) || (hint)) { \
|
||||
if (branch != full) \
|
||||
free(branch); \
|
||||
(map)->tree[a] = NULL; \
|
||||
continue; \
|
||||
} else if (branch == full) { \
|
||||
branch = kmem_cache_alloc(cachep, GFP_ATOMIC); \
|
||||
if (!branch) \
|
||||
return -ENOMEM; \
|
||||
memcpy(branch, full, sizeof(*branch)); \
|
||||
(map)->tree[a] = branch; \
|
||||
}
|
||||
|
||||
#define DELIP_RANGE_LOOP_END() \
|
||||
} \
|
||||
}
|
||||
|
||||
#define LOOP_WALK_BEGIN(map, i, branch) \
|
||||
for (i = 0; i < 256; i++) { \
|
||||
branch = (map)->tree[i]; \
|
||||
if (likely(!branch)) \
|
||||
continue;
|
||||
|
||||
#define LOOP_WALK_END() \
|
||||
}
|
||||
|
||||
#define LOOP_WALK_BEGIN_GC(map, i, branch, full, cachep, count) \
|
||||
count = -256; \
|
||||
for (i = 0; i < 256; i++) { \
|
||||
branch = (map)->tree[i]; \
|
||||
if (likely(!branch)) \
|
||||
continue; \
|
||||
count++; \
|
||||
if (branch == full) { \
|
||||
count++; \
|
||||
continue; \
|
||||
}
|
||||
|
||||
#define LOOP_WALK_END_GC(map, i, branch, full, cachep, count) \
|
||||
if (-256 == count) { \
|
||||
kmem_cache_free(cachep, branch); \
|
||||
(map)->tree[i] = NULL; \
|
||||
} else if (256 == count) { \
|
||||
kmem_cache_free(cachep, branch); \
|
||||
(map)->tree[i] = full; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define LOOP_WALK_BEGIN_COUNT(map, i, branch, inrange, count) \
|
||||
for (i = 0; i < 256; i++) { \
|
||||
if (!(map)->tree[i]) { \
|
||||
if (inrange) { \
|
||||
count++; \
|
||||
inrange = 0; \
|
||||
} \
|
||||
continue; \
|
||||
} \
|
||||
branch = (map)->tree[i];
|
||||
|
||||
#define LOOP_WALK_END_COUNT() \
|
||||
}
|
||||
|
||||
#define GETVALUE1(a, a1, b1, r) \
|
||||
(a == a1 ? b1 : r)
|
||||
|
||||
#define GETVALUE2(a, b, a1, b1, c1, r) \
|
||||
(a == a1 && b == b1 ? c1 : r)
|
||||
|
||||
#define GETVALUE3(a, b, c, a1, b1, c1, d1, r) \
|
||||
(a == a1 && b == b1 && c == c1 ? d1 : r)
|
||||
|
||||
#define CHECK1(a, a1, a2, b1, b2, c1, c2, d1, d2) \
|
||||
( \
|
||||
GETVALUE1(a, a1, b1, 0) == 0 \
|
||||
&& GETVALUE1(a, a2, b2, 255) == 255 \
|
||||
&& c1 == 0 \
|
||||
&& c2 == 255 \
|
||||
&& d1 == 0 \
|
||||
&& d2 == 255 \
|
||||
)
|
||||
|
||||
#define CHECK2(a, b, a1, a2, b1, b2, c1, c2, d1, d2) \
|
||||
( \
|
||||
GETVALUE2(a, b, a1, b1, c1, 0) == 0 \
|
||||
&& GETVALUE2(a, b, a2, b2, c2, 255) == 255 \
|
||||
&& d1 == 0 \
|
||||
&& d2 == 255 \
|
||||
)
|
||||
|
||||
#define CHECK3(a, b, c, a1, a2, b1, b2, c1, c2, d1, d2) \
|
||||
( \
|
||||
GETVALUE3(a, b, c, a1, b1, c1, d1, 0) == 0 \
|
||||
&& GETVALUE3(a, b, c, a2, b2, c2, d2, 255) == 255 \
|
||||
)
|
||||
|
||||
|
||||
static inline void
|
||||
free_d(struct ip_set_iptreemap_d *map)
|
||||
{
|
||||
kmem_cache_free(cachep_d, map);
|
||||
}
|
||||
|
||||
static inline void
|
||||
free_c(struct ip_set_iptreemap_c *map)
|
||||
{
|
||||
struct ip_set_iptreemap_d *dtree;
|
||||
unsigned int i;
|
||||
|
||||
LOOP_WALK_BEGIN(map, i, dtree) {
|
||||
if (dtree != fullbitmap_d)
|
||||
free_d(dtree);
|
||||
} LOOP_WALK_END();
|
||||
|
||||
kmem_cache_free(cachep_c, map);
|
||||
}
|
||||
|
||||
static inline void
|
||||
free_b(struct ip_set_iptreemap_b *map)
|
||||
{
|
||||
struct ip_set_iptreemap_c *ctree;
|
||||
unsigned int i;
|
||||
|
||||
LOOP_WALK_BEGIN(map, i, ctree) {
|
||||
if (ctree != fullbitmap_c)
|
||||
free_c(ctree);
|
||||
} LOOP_WALK_END();
|
||||
|
||||
kmem_cache_free(cachep_b, map);
|
||||
}
|
||||
|
||||
static inline int
|
||||
iptreemap_test(struct ip_set *set, ip_set_ip_t ip)
|
||||
{
|
||||
struct ip_set_iptreemap *map = set->data;
|
||||
struct ip_set_iptreemap_b *btree;
|
||||
struct ip_set_iptreemap_c *ctree;
|
||||
struct ip_set_iptreemap_d *dtree;
|
||||
unsigned char a, b, c, d;
|
||||
|
||||
ABCD(a, b, c, d, &ip);
|
||||
|
||||
TESTIP_WALK(map, a, btree, fullbitmap_b);
|
||||
TESTIP_WALK(btree, b, ctree, fullbitmap_c);
|
||||
TESTIP_WALK(ctree, c, dtree, fullbitmap_d);
|
||||
|
||||
return !!test_bit(d, (void *) dtree->bitmap);
|
||||
}
|
||||
|
||||
#define KADT_CONDITION
|
||||
|
||||
UADT(iptreemap, test)
|
||||
KADT(iptreemap, test, ipaddr)
|
||||
|
||||
static inline int
|
||||
__addip_single(struct ip_set *set, ip_set_ip_t ip)
|
||||
{
|
||||
struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->data;
|
||||
struct ip_set_iptreemap_b *btree;
|
||||
struct ip_set_iptreemap_c *ctree;
|
||||
struct ip_set_iptreemap_d *dtree;
|
||||
unsigned char a, b, c, d;
|
||||
|
||||
ABCD(a, b, c, d, &ip);
|
||||
|
||||
ADDIP_WALK(map, a, btree, struct ip_set_iptreemap_b, cachep_b, fullbitmap_b);
|
||||
ADDIP_WALK(btree, b, ctree, struct ip_set_iptreemap_c, cachep_c, fullbitmap_c);
|
||||
ADDIP_WALK(ctree, c, dtree, struct ip_set_iptreemap_d, cachep_d, fullbitmap_d);
|
||||
|
||||
if (__test_and_set_bit(d, (void *) dtree->bitmap))
|
||||
return -EEXIST;
|
||||
|
||||
__set_bit(b, (void *) btree->dirty);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
iptreemap_add(struct ip_set *set, ip_set_ip_t start, ip_set_ip_t end)
|
||||
{
|
||||
struct ip_set_iptreemap *map = set->data;
|
||||
struct ip_set_iptreemap_b *btree;
|
||||
struct ip_set_iptreemap_c *ctree;
|
||||
struct ip_set_iptreemap_d *dtree;
|
||||
unsigned int a, b, c, d;
|
||||
unsigned char a1, b1, c1, d1;
|
||||
unsigned char a2, b2, c2, d2;
|
||||
|
||||
if (start == end)
|
||||
return __addip_single(set, start);
|
||||
|
||||
ABCD(a1, b1, c1, d1, &start);
|
||||
ABCD(a2, b2, c2, d2, &end);
|
||||
|
||||
/* This is sooo ugly... */
|
||||
ADDIP_RANGE_LOOP(map, a, a1, a2, CHECK1(a, a1, a2, b1, b2, c1, c2, d1, d2), btree, fullbitmap_b, cachep_b, free_b) {
|
||||
ADDIP_RANGE_LOOP(btree, b, GETVALUE1(a, a1, b1, 0), GETVALUE1(a, a2, b2, 255), CHECK2(a, b, a1, a2, b1, b2, c1, c2, d1, d2), ctree, fullbitmap_c, cachep_c, free_c) {
|
||||
ADDIP_RANGE_LOOP(ctree, c, GETVALUE2(a, b, a1, b1, c1, 0), GETVALUE2(a, b, a2, b2, c2, 255), CHECK3(a, b, c, a1, a2, b1, b2, c1, c2, d1, d2), dtree, fullbitmap_d, cachep_d, free_d) {
|
||||
for (d = GETVALUE3(a, b, c, a1, b1, c1, d1, 0); d <= GETVALUE3(a, b, c, a2, b2, c2, d2, 255); d++)
|
||||
__set_bit(d, (void *) dtree->bitmap);
|
||||
__set_bit(b, (void *) btree->dirty);
|
||||
} ADDIP_RANGE_LOOP_END();
|
||||
} ADDIP_RANGE_LOOP_END();
|
||||
} ADDIP_RANGE_LOOP_END();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
UADT0(iptreemap, add, min(req->ip, req->end), max(req->ip, req->end))
|
||||
KADT(iptreemap, add, ipaddr, ip)
|
||||
|
||||
static inline int
|
||||
__delip_single(struct ip_set *set, ip_set_ip_t ip)
|
||||
{
|
||||
struct ip_set_iptreemap *map = set->data;
|
||||
struct ip_set_iptreemap_b *btree;
|
||||
struct ip_set_iptreemap_c *ctree;
|
||||
struct ip_set_iptreemap_d *dtree;
|
||||
unsigned char a,b,c,d;
|
||||
|
||||
ABCD(a, b, c, d, &ip);
|
||||
|
||||
DELIP_WALK(map, a, btree, cachep_b, fullbitmap_b);
|
||||
DELIP_WALK(btree, b, ctree, cachep_c, fullbitmap_c);
|
||||
DELIP_WALK(ctree, c, dtree, cachep_d, fullbitmap_d);
|
||||
|
||||
if (!__test_and_clear_bit(d, (void *) dtree->bitmap))
|
||||
return -EEXIST;
|
||||
|
||||
__set_bit(b, (void *) btree->dirty);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
iptreemap_del(struct ip_set *set, ip_set_ip_t start, ip_set_ip_t end)
|
||||
{
|
||||
struct ip_set_iptreemap *map = set->data;
|
||||
struct ip_set_iptreemap_b *btree;
|
||||
struct ip_set_iptreemap_c *ctree;
|
||||
struct ip_set_iptreemap_d *dtree;
|
||||
unsigned int a, b, c, d;
|
||||
unsigned char a1, b1, c1, d1;
|
||||
unsigned char a2, b2, c2, d2;
|
||||
|
||||
if (start == end)
|
||||
return __delip_single(set, start);
|
||||
|
||||
ABCD(a1, b1, c1, d1, &start);
|
||||
ABCD(a2, b2, c2, d2, &end);
|
||||
|
||||
/* This is sooo ugly... */
|
||||
DELIP_RANGE_LOOP(map, a, a1, a2, CHECK1(a, a1, a2, b1, b2, c1, c2, d1, d2), btree, fullbitmap_b, cachep_b, free_b) {
|
||||
DELIP_RANGE_LOOP(btree, b, GETVALUE1(a, a1, b1, 0), GETVALUE1(a, a2, b2, 255), CHECK2(a, b, a1, a2, b1, b2, c1, c2, d1, d2), ctree, fullbitmap_c, cachep_c, free_c) {
|
||||
DELIP_RANGE_LOOP(ctree, c, GETVALUE2(a, b, a1, b1, c1, 0), GETVALUE2(a, b, a2, b2, c2, 255), CHECK3(a, b, c, a1, a2, b1, b2, c1, c2, d1, d2), dtree, fullbitmap_d, cachep_d, free_d) {
|
||||
for (d = GETVALUE3(a, b, c, a1, b1, c1, d1, 0); d <= GETVALUE3(a, b, c, a2, b2, c2, d2, 255); d++)
|
||||
__clear_bit(d, (void *) dtree->bitmap);
|
||||
__set_bit(b, (void *) btree->dirty);
|
||||
} DELIP_RANGE_LOOP_END();
|
||||
} DELIP_RANGE_LOOP_END();
|
||||
} DELIP_RANGE_LOOP_END();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
UADT0(iptreemap, del, min(req->ip, req->end), max(req->ip, req->end))
|
||||
KADT(iptreemap, del, ipaddr, ip)
|
||||
|
||||
/* Check the status of the bitmap
|
||||
* -1 == all bits cleared
|
||||
* 1 == all bits set
|
||||
* 0 == anything else
|
||||
*/
|
||||
static inline int
|
||||
bitmap_status(struct ip_set_iptreemap_d *dtree)
|
||||
{
|
||||
unsigned char first = dtree->bitmap[0];
|
||||
int a;
|
||||
|
||||
for (a = 1; a < 32; a++)
|
||||
if (dtree->bitmap[a] != first)
|
||||
return 0;
|
||||
|
||||
return (first == 0 ? -1 : (first == 255 ? 1 : 0));
|
||||
}
|
||||
|
||||
static void
|
||||
gc(unsigned long addr)
|
||||
{
|
||||
struct ip_set *set = (struct ip_set *) addr;
|
||||
struct ip_set_iptreemap *map = set->data;
|
||||
struct ip_set_iptreemap_b *btree;
|
||||
struct ip_set_iptreemap_c *ctree;
|
||||
struct ip_set_iptreemap_d *dtree;
|
||||
unsigned int a, b, c;
|
||||
int i, j, k;
|
||||
|
||||
write_lock_bh(&set->lock);
|
||||
|
||||
LOOP_WALK_BEGIN_GC(map, a, btree, fullbitmap_b, cachep_b, i) {
|
||||
LOOP_WALK_BEGIN_GC(btree, b, ctree, fullbitmap_c, cachep_c, j) {
|
||||
if (!__test_and_clear_bit(b, (void *) btree->dirty))
|
||||
continue;
|
||||
LOOP_WALK_BEGIN_GC(ctree, c, dtree, fullbitmap_d, cachep_d, k) {
|
||||
switch (bitmap_status(dtree)) {
|
||||
case -1:
|
||||
kmem_cache_free(cachep_d, dtree);
|
||||
ctree->tree[c] = NULL;
|
||||
k--;
|
||||
break;
|
||||
case 1:
|
||||
kmem_cache_free(cachep_d, dtree);
|
||||
ctree->tree[c] = fullbitmap_d;
|
||||
k++;
|
||||
break;
|
||||
}
|
||||
} LOOP_WALK_END();
|
||||
} LOOP_WALK_END_GC(btree, b, ctree, fullbitmap_c, cachep_c, k);
|
||||
} LOOP_WALK_END_GC(map, a, btree, fullbitmap_b, cachep_b, j);
|
||||
|
||||
write_unlock_bh(&set->lock);
|
||||
|
||||
map->gc.expires = jiffies + map->gc_interval * HZ;
|
||||
add_timer(&map->gc);
|
||||
}
|
||||
|
||||
static inline void
|
||||
init_gc_timer(struct ip_set *set)
|
||||
{
|
||||
struct ip_set_iptreemap *map = set->data;
|
||||
|
||||
init_timer(&map->gc);
|
||||
map->gc.data = (unsigned long) set;
|
||||
map->gc.function = gc;
|
||||
map->gc.expires = jiffies + map->gc_interval * HZ;
|
||||
add_timer(&map->gc);
|
||||
}
|
||||
|
||||
static int
|
||||
iptreemap_create(struct ip_set *set, const void *data, u_int32_t size)
|
||||
{
|
||||
const struct ip_set_req_iptreemap_create *req = data;
|
||||
struct ip_set_iptreemap *map;
|
||||
|
||||
map = kzalloc(sizeof(*map), GFP_KERNEL);
|
||||
if (!map)
|
||||
return -ENOMEM;
|
||||
|
||||
map->gc_interval = req->gc_interval ? req->gc_interval : IPTREEMAP_DEFAULT_GC_TIME;
|
||||
set->data = map;
|
||||
|
||||
init_gc_timer(set);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
__flush(struct ip_set_iptreemap *map)
|
||||
{
|
||||
struct ip_set_iptreemap_b *btree;
|
||||
unsigned int a;
|
||||
|
||||
LOOP_WALK_BEGIN(map, a, btree);
|
||||
if (btree != fullbitmap_b)
|
||||
free_b(btree);
|
||||
LOOP_WALK_END();
|
||||
}
|
||||
|
||||
static void
|
||||
iptreemap_destroy(struct ip_set *set)
|
||||
{
|
||||
struct ip_set_iptreemap *map = set->data;
|
||||
|
||||
while (!del_timer(&map->gc))
|
||||
msleep(IPTREEMAP_DESTROY_SLEEP);
|
||||
|
||||
__flush(map);
|
||||
kfree(map);
|
||||
|
||||
set->data = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
iptreemap_flush(struct ip_set *set)
|
||||
{
|
||||
struct ip_set_iptreemap *map = set->data;
|
||||
unsigned int gc_interval = map->gc_interval;
|
||||
|
||||
while (!del_timer(&map->gc))
|
||||
msleep(IPTREEMAP_DESTROY_SLEEP);
|
||||
|
||||
__flush(map);
|
||||
|
||||
memset(map, 0, sizeof(*map));
|
||||
map->gc_interval = gc_interval;
|
||||
|
||||
init_gc_timer(set);
|
||||
}
|
||||
|
||||
static void
|
||||
iptreemap_list_header(const struct ip_set *set, void *data)
|
||||
{
|
||||
struct ip_set_iptreemap *map = set->data;
|
||||
struct ip_set_req_iptreemap_create *header = data;
|
||||
|
||||
header->gc_interval = map->gc_interval;
|
||||
}
|
||||
|
||||
static int
|
||||
iptreemap_list_members_size(const struct ip_set *set, char dont_align)
|
||||
{
|
||||
struct ip_set_iptreemap *map = set->data;
|
||||
struct ip_set_iptreemap_b *btree;
|
||||
struct ip_set_iptreemap_c *ctree;
|
||||
struct ip_set_iptreemap_d *dtree;
|
||||
unsigned int a, b, c, d, inrange = 0, count = 0;
|
||||
|
||||
LOOP_WALK_BEGIN_COUNT(map, a, btree, inrange, count) {
|
||||
LOOP_WALK_BEGIN_COUNT(btree, b, ctree, inrange, count) {
|
||||
LOOP_WALK_BEGIN_COUNT(ctree, c, dtree, inrange, count) {
|
||||
for (d = 0; d < 256; d++) {
|
||||
if (test_bit(d, (void *) dtree->bitmap)) {
|
||||
inrange = 1;
|
||||
} else if (inrange) {
|
||||
count++;
|
||||
inrange = 0;
|
||||
}
|
||||
}
|
||||
} LOOP_WALK_END_COUNT();
|
||||
} LOOP_WALK_END_COUNT();
|
||||
} LOOP_WALK_END_COUNT();
|
||||
|
||||
if (inrange)
|
||||
count++;
|
||||
|
||||
return (count * IPSET_VALIGN(sizeof(struct ip_set_req_iptreemap), dont_align));
|
||||
}
|
||||
|
||||
static inline void
|
||||
add_member(void *data, size_t offset, ip_set_ip_t start, ip_set_ip_t end)
|
||||
{
|
||||
struct ip_set_req_iptreemap *entry = data + offset;
|
||||
|
||||
entry->ip = start;
|
||||
entry->end = end;
|
||||
}
|
||||
|
||||
static void
|
||||
iptreemap_list_members(const struct ip_set *set, void *data, char dont_align)
|
||||
{
|
||||
struct ip_set_iptreemap *map = set->data;
|
||||
struct ip_set_iptreemap_b *btree;
|
||||
struct ip_set_iptreemap_c *ctree;
|
||||
struct ip_set_iptreemap_d *dtree;
|
||||
unsigned int a, b, c, d, inrange = 0;
|
||||
size_t offset = 0, datasize;
|
||||
ip_set_ip_t start = 0, end = 0, ip;
|
||||
|
||||
datasize = IPSET_VALIGN(sizeof(struct ip_set_req_iptreemap), dont_align);
|
||||
LOOP_WALK_BEGIN(map, a, btree) {
|
||||
LOOP_WALK_BEGIN(btree, b, ctree) {
|
||||
LOOP_WALK_BEGIN(ctree, c, dtree) {
|
||||
for (d = 0; d < 256; d++) {
|
||||
if (test_bit(d, (void *) dtree->bitmap)) {
|
||||
ip = ((a << 24) | (b << 16) | (c << 8) | d);
|
||||
if (!inrange) {
|
||||
inrange = 1;
|
||||
start = ip;
|
||||
} else if (end < ip - 1) {
|
||||
add_member(data, offset, start, end);
|
||||
offset += datasize;
|
||||
start = ip;
|
||||
}
|
||||
end = ip;
|
||||
} else if (inrange) {
|
||||
add_member(data, offset, start, end);
|
||||
offset += datasize;
|
||||
inrange = 0;
|
||||
}
|
||||
}
|
||||
} LOOP_WALK_END();
|
||||
} LOOP_WALK_END();
|
||||
} LOOP_WALK_END();
|
||||
|
||||
if (inrange)
|
||||
add_member(data, offset, start, end);
|
||||
}
|
||||
|
||||
IP_SET_TYPE(iptreemap, IPSET_TYPE_IP | IPSET_DATA_SINGLE)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Sven Wegener <sven.wegener@stealer.net>");
|
||||
MODULE_DESCRIPTION("iptreemap type of IP sets");
|
||||
|
||||
static int __init ip_set_iptreemap_init(void)
|
||||
{
|
||||
int ret = -ENOMEM;
|
||||
int a;
|
||||
|
||||
cachep_b = KMEM_CACHE_CREATE("ip_set_iptreemap_b",
|
||||
sizeof(struct ip_set_iptreemap_b));
|
||||
if (!cachep_b) {
|
||||
ip_set_printk("Unable to create ip_set_iptreemap_b slab cache");
|
||||
goto out;
|
||||
}
|
||||
|
||||
cachep_c = KMEM_CACHE_CREATE("ip_set_iptreemap_c",
|
||||
sizeof(struct ip_set_iptreemap_c));
|
||||
if (!cachep_c) {
|
||||
ip_set_printk("Unable to create ip_set_iptreemap_c slab cache");
|
||||
goto outb;
|
||||
}
|
||||
|
||||
cachep_d = KMEM_CACHE_CREATE("ip_set_iptreemap_d",
|
||||
sizeof(struct ip_set_iptreemap_d));
|
||||
if (!cachep_d) {
|
||||
ip_set_printk("Unable to create ip_set_iptreemap_d slab cache");
|
||||
goto outc;
|
||||
}
|
||||
|
||||
fullbitmap_d = kmem_cache_alloc(cachep_d, GFP_KERNEL);
|
||||
if (!fullbitmap_d)
|
||||
goto outd;
|
||||
|
||||
fullbitmap_c = kmem_cache_alloc(cachep_c, GFP_KERNEL);
|
||||
if (!fullbitmap_c)
|
||||
goto outbitmapd;
|
||||
|
||||
fullbitmap_b = kmem_cache_alloc(cachep_b, GFP_KERNEL);
|
||||
if (!fullbitmap_b)
|
||||
goto outbitmapc;
|
||||
|
||||
ret = ip_set_register_set_type(&ip_set_iptreemap);
|
||||
if (0 > ret)
|
||||
goto outbitmapb;
|
||||
|
||||
/* Now init our global bitmaps */
|
||||
memset(fullbitmap_d->bitmap, 0xff, sizeof(fullbitmap_d->bitmap));
|
||||
|
||||
for (a = 0; a < 256; a++)
|
||||
fullbitmap_c->tree[a] = fullbitmap_d;
|
||||
|
||||
for (a = 0; a < 256; a++)
|
||||
fullbitmap_b->tree[a] = fullbitmap_c;
|
||||
memset(fullbitmap_b->dirty, 0, sizeof(fullbitmap_b->dirty));
|
||||
|
||||
return 0;
|
||||
|
||||
outbitmapb:
|
||||
kmem_cache_free(cachep_b, fullbitmap_b);
|
||||
outbitmapc:
|
||||
kmem_cache_free(cachep_c, fullbitmap_c);
|
||||
outbitmapd:
|
||||
kmem_cache_free(cachep_d, fullbitmap_d);
|
||||
outd:
|
||||
kmem_cache_destroy(cachep_d);
|
||||
outc:
|
||||
kmem_cache_destroy(cachep_c);
|
||||
outb:
|
||||
kmem_cache_destroy(cachep_b);
|
||||
out:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit ip_set_iptreemap_fini(void)
|
||||
{
|
||||
ip_set_unregister_set_type(&ip_set_iptreemap);
|
||||
kmem_cache_free(cachep_d, fullbitmap_d);
|
||||
kmem_cache_free(cachep_c, fullbitmap_c);
|
||||
kmem_cache_free(cachep_b, fullbitmap_b);
|
||||
kmem_cache_destroy(cachep_d);
|
||||
kmem_cache_destroy(cachep_c);
|
||||
kmem_cache_destroy(cachep_b);
|
||||
}
|
||||
|
||||
module_init(ip_set_iptreemap_init);
|
||||
module_exit(ip_set_iptreemap_fini);
|
||||
@@ -1,40 +0,0 @@
|
||||
#ifndef __IP_SET_IPTREEMAP_H
|
||||
#define __IP_SET_IPTREEMAP_H
|
||||
|
||||
#include "ip_set.h"
|
||||
|
||||
#define SETTYPE_NAME "iptreemap"
|
||||
|
||||
#ifdef __KERNEL__
|
||||
struct ip_set_iptreemap_d {
|
||||
unsigned char bitmap[32]; /* x.x.x.y */
|
||||
};
|
||||
|
||||
struct ip_set_iptreemap_c {
|
||||
struct ip_set_iptreemap_d *tree[256]; /* x.x.y.x */
|
||||
};
|
||||
|
||||
struct ip_set_iptreemap_b {
|
||||
struct ip_set_iptreemap_c *tree[256]; /* x.y.x.x */
|
||||
unsigned char dirty[32];
|
||||
};
|
||||
#endif
|
||||
|
||||
struct ip_set_iptreemap {
|
||||
unsigned int gc_interval;
|
||||
#ifdef __KERNEL__
|
||||
struct timer_list gc;
|
||||
struct ip_set_iptreemap_b *tree[256]; /* y.x.x.x */
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ip_set_req_iptreemap_create {
|
||||
unsigned int gc_interval;
|
||||
};
|
||||
|
||||
struct ip_set_req_iptreemap {
|
||||
ip_set_ip_t ip;
|
||||
ip_set_ip_t end;
|
||||
};
|
||||
|
||||
#endif /* __IP_SET_IPTREEMAP_H */
|
||||
@@ -1,157 +0,0 @@
|
||||
#ifndef _LINUX_JHASH_H
|
||||
#define _LINUX_JHASH_H
|
||||
|
||||
/* jhash.h: Jenkins hash support.
|
||||
*
|
||||
* Copyright (C) 2006. Bob Jenkins (bob_jenkins@burtleburtle.net)
|
||||
*
|
||||
* http://burtleburtle.net/bob/hash/
|
||||
*
|
||||
* These are the credits from Bob's sources:
|
||||
*
|
||||
* lookup3.c, by Bob Jenkins, May 2006, Public Domain.
|
||||
*
|
||||
* These are functions for producing 32-bit hashes for hash table lookup.
|
||||
* hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final()
|
||||
* are externally useful functions. Routines to test the hash are included
|
||||
* if SELF_TEST is defined. You can use this free for any purpose. It's in
|
||||
* the public domain. It has no warranty.
|
||||
*
|
||||
* Copyright (C) 2009 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* I've modified Bob's hash to be useful in the Linux kernel, and
|
||||
* any bugs present are my fault. Jozsef
|
||||
*/
|
||||
|
||||
#define __rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
|
||||
|
||||
/* __jhash_mix - mix 3 32-bit values reversibly. */
|
||||
#define __jhash_mix(a,b,c) \
|
||||
{ \
|
||||
a -= c; a ^= __rot(c, 4); c += b; \
|
||||
b -= a; b ^= __rot(a, 6); a += c; \
|
||||
c -= b; c ^= __rot(b, 8); b += a; \
|
||||
a -= c; a ^= __rot(c,16); c += b; \
|
||||
b -= a; b ^= __rot(a,19); a += c; \
|
||||
c -= b; c ^= __rot(b, 4); b += a; \
|
||||
}
|
||||
|
||||
/* __jhash_final - final mixing of 3 32-bit values (a,b,c) into c */
|
||||
#define __jhash_final(a,b,c) \
|
||||
{ \
|
||||
c ^= b; c -= __rot(b,14); \
|
||||
a ^= c; a -= __rot(c,11); \
|
||||
b ^= a; b -= __rot(a,25); \
|
||||
c ^= b; c -= __rot(b,16); \
|
||||
a ^= c; a -= __rot(c,4); \
|
||||
b ^= a; b -= __rot(a,14); \
|
||||
c ^= b; c -= __rot(b,24); \
|
||||
}
|
||||
|
||||
/* The golden ration: an arbitrary value */
|
||||
#define JHASH_GOLDEN_RATIO 0xdeadbeef
|
||||
|
||||
/* The most generic version, hashes an arbitrary sequence
|
||||
* of bytes. No alignment or length assumptions are made about
|
||||
* the input key. The result depends on endianness.
|
||||
*/
|
||||
static inline u32 jhash(const void *key, u32 length, u32 initval)
|
||||
{
|
||||
u32 a,b,c;
|
||||
const u8 *k = key;
|
||||
|
||||
/* Set up the internal state */
|
||||
a = b = c = JHASH_GOLDEN_RATIO + length + initval;
|
||||
|
||||
/* all but the last block: affect some 32 bits of (a,b,c) */
|
||||
while (length > 12) {
|
||||
a += (k[0] + ((u32)k[1]<<8) + ((u32)k[2]<<16) + ((u32)k[3]<<24));
|
||||
b += (k[4] + ((u32)k[5]<<8) + ((u32)k[6]<<16) + ((u32)k[7]<<24));
|
||||
c += (k[8] + ((u32)k[9]<<8) + ((u32)k[10]<<16) + ((u32)k[11]<<24));
|
||||
__jhash_mix(a, b, c);
|
||||
length -= 12;
|
||||
k += 12;
|
||||
}
|
||||
|
||||
/* last block: affect all 32 bits of (c) */
|
||||
/* all the case statements fall through */
|
||||
switch (length) {
|
||||
case 12: c += (u32)k[11]<<24;
|
||||
case 11: c += (u32)k[10]<<16;
|
||||
case 10: c += (u32)k[9]<<8;
|
||||
case 9 : c += k[8];
|
||||
case 8 : b += (u32)k[7]<<24;
|
||||
case 7 : b += (u32)k[6]<<16;
|
||||
case 6 : b += (u32)k[5]<<8;
|
||||
case 5 : b += k[4];
|
||||
case 4 : a += (u32)k[3]<<24;
|
||||
case 3 : a += (u32)k[2]<<16;
|
||||
case 2 : a += (u32)k[1]<<8;
|
||||
case 1 : a += k[0];
|
||||
__jhash_final(a, b, c);
|
||||
case 0 :
|
||||
break;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/* A special optimized version that handles 1 or more of u32s.
|
||||
* The length parameter here is the number of u32s in the key.
|
||||
*/
|
||||
static inline u32 jhash2(const u32 *k, u32 length, u32 initval)
|
||||
{
|
||||
u32 a, b, c;
|
||||
|
||||
/* Set up the internal state */
|
||||
a = b = c = JHASH_GOLDEN_RATIO + (length<<2) + initval;
|
||||
|
||||
/* handle most of the key */
|
||||
while (length > 3) {
|
||||
a += k[0];
|
||||
b += k[1];
|
||||
c += k[2];
|
||||
__jhash_mix(a, b, c);
|
||||
length -= 3;
|
||||
k += 3;
|
||||
}
|
||||
|
||||
/* handle the last 3 u32's */
|
||||
/* all the case statements fall through */
|
||||
switch (length) {
|
||||
case 3: c += k[2];
|
||||
case 2: b += k[1];
|
||||
case 1: a += k[0];
|
||||
__jhash_final(a, b, c);
|
||||
case 0: /* case 0: nothing left to add */
|
||||
break;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/* A special ultra-optimized versions that knows they are hashing exactly
|
||||
* 3, 2 or 1 word(s).
|
||||
*/
|
||||
static inline u32 jhash_3words(u32 a, u32 b, u32 c, u32 initval)
|
||||
{
|
||||
a += JHASH_GOLDEN_RATIO + initval;
|
||||
b += JHASH_GOLDEN_RATIO + initval;
|
||||
c += JHASH_GOLDEN_RATIO + initval;
|
||||
|
||||
__jhash_final(a, b, c);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static inline u32 jhash_2words(u32 a, u32 b, u32 initval)
|
||||
{
|
||||
return jhash_3words(0, a, b, initval);
|
||||
}
|
||||
|
||||
static inline u32 jhash_1word(u32 a, u32 initval)
|
||||
{
|
||||
return jhash_3words(0, 0, a, initval);
|
||||
}
|
||||
|
||||
#endif /* _LINUX_JHASH_H */
|
||||
@@ -1,179 +0,0 @@
|
||||
/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
|
||||
* Patrick Schaaf <bof@bof.de>
|
||||
* Martin Josefsson <gandalf@wlug.westbo.se>
|
||||
* Copyright (C) 2003-2008 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an IP set type: the macipmap type */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/if_ether.h>
|
||||
|
||||
#include "ip_set_macipmap.h"
|
||||
|
||||
static int
|
||||
macipmap_utest(struct ip_set *set, const void *data, u_int32_t size)
|
||||
{
|
||||
const struct ip_set_macipmap *map = set->data;
|
||||
const struct ip_set_macip *table = map->members;
|
||||
const struct ip_set_req_macipmap *req = data;
|
||||
|
||||
if (req->ip < map->first_ip || req->ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
|
||||
DP("set: %s, ip:%u.%u.%u.%u", set->name, HIPQUAD(req->ip));
|
||||
if (table[req->ip - map->first_ip].match) {
|
||||
return (memcmp(req->ethernet,
|
||||
&table[req->ip - map->first_ip].ethernet,
|
||||
ETH_ALEN) == 0);
|
||||
} else {
|
||||
return (map->flags & IPSET_MACIP_MATCHUNSET ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
macipmap_ktest(struct ip_set *set,
|
||||
const struct sk_buff *skb,
|
||||
const u_int32_t *flags)
|
||||
{
|
||||
const struct ip_set_macipmap *map = set->data;
|
||||
const struct ip_set_macip *table = map->members;
|
||||
ip_set_ip_t ip;
|
||||
|
||||
ip = ipaddr(skb, flags);
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return 0;
|
||||
|
||||
DP("set: %s, ip:%u.%u.%u.%u", set->name, HIPQUAD(ip));
|
||||
if (table[ip - map->first_ip].match) {
|
||||
/* Is mac pointer valid?
|
||||
* If so, compare... */
|
||||
return (skb_mac_header(skb) >= skb->head
|
||||
&& (skb_mac_header(skb) + ETH_HLEN) <= skb->data
|
||||
&& (memcmp(eth_hdr(skb)->h_source,
|
||||
&table[ip - map->first_ip].ethernet,
|
||||
ETH_ALEN) == 0));
|
||||
} else {
|
||||
return (map->flags & IPSET_MACIP_MATCHUNSET ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* returns 0 on success */
|
||||
static inline int
|
||||
macipmap_add(struct ip_set *set,
|
||||
ip_set_ip_t ip, const unsigned char *ethernet)
|
||||
{
|
||||
struct ip_set_macipmap *map = set->data;
|
||||
struct ip_set_macip *table = map->members;
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
if (table[ip - map->first_ip].match)
|
||||
return -EEXIST;
|
||||
|
||||
DP("set: %s, ip: %u.%u.%u.%u", set->name, HIPQUAD(ip));
|
||||
memcpy(&table[ip - map->first_ip].ethernet, ethernet, ETH_ALEN);
|
||||
table[ip - map->first_ip].match = IPSET_MACIP_ISSET;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define KADT_CONDITION \
|
||||
if (!(skb_mac_header(skb) >= skb->head \
|
||||
&& (skb_mac_header(skb) + ETH_HLEN) <= skb->data))\
|
||||
return -EINVAL;
|
||||
|
||||
UADT(macipmap, add, req->ethernet)
|
||||
KADT(macipmap, add, ipaddr, eth_hdr(skb)->h_source)
|
||||
|
||||
static inline int
|
||||
macipmap_del(struct ip_set *set, ip_set_ip_t ip)
|
||||
{
|
||||
struct ip_set_macipmap *map = set->data;
|
||||
struct ip_set_macip *table = map->members;
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
if (!table[ip - map->first_ip].match)
|
||||
return -EEXIST;
|
||||
|
||||
table[ip - map->first_ip].match = 0;
|
||||
DP("set: %s, ip: %u.%u.%u.%u", set->name, HIPQUAD(ip));
|
||||
return 0;
|
||||
}
|
||||
|
||||
#undef KADT_CONDITION
|
||||
#define KADT_CONDITION
|
||||
|
||||
UADT(macipmap, del)
|
||||
KADT(macipmap, del, ipaddr)
|
||||
|
||||
static inline int
|
||||
__macipmap_create(const struct ip_set_req_macipmap_create *req,
|
||||
struct ip_set_macipmap *map)
|
||||
{
|
||||
if (req->to - req->from > MAX_RANGE) {
|
||||
ip_set_printk("range too big, %d elements (max %d)",
|
||||
req->to - req->from + 1, MAX_RANGE+1);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
map->flags = req->flags;
|
||||
return (req->to - req->from + 1) * sizeof(struct ip_set_macip);
|
||||
}
|
||||
|
||||
BITMAP_CREATE(macipmap)
|
||||
BITMAP_DESTROY(macipmap)
|
||||
BITMAP_FLUSH(macipmap)
|
||||
|
||||
static inline void
|
||||
__macipmap_list_header(const struct ip_set_macipmap *map,
|
||||
struct ip_set_req_macipmap_create *header)
|
||||
{
|
||||
header->flags = map->flags;
|
||||
}
|
||||
|
||||
BITMAP_LIST_HEADER(macipmap)
|
||||
BITMAP_LIST_MEMBERS_SIZE(macipmap, struct ip_set_req_macipmap,
|
||||
(map->last_ip - map->first_ip + 1),
|
||||
((const struct ip_set_macip *)map->members)[i].match)
|
||||
|
||||
|
||||
static void
|
||||
macipmap_list_members(const struct ip_set *set, void *data, char dont_align)
|
||||
{
|
||||
const struct ip_set_macipmap *map = set->data;
|
||||
const struct ip_set_macip *table = map->members;
|
||||
uint32_t i, n = 0;
|
||||
struct ip_set_req_macipmap *d;
|
||||
|
||||
if (dont_align) {
|
||||
memcpy(data, map->members, map->size);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < map->last_ip - map->first_ip + 1; i++)
|
||||
if (table[i].match) {
|
||||
d = data + n * IPSET_ALIGN(sizeof(struct ip_set_req_macipmap));
|
||||
d->ip = map->first_ip + i;
|
||||
memcpy(d->ethernet, &table[i].ethernet, ETH_ALEN);
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
IP_SET_TYPE(macipmap, IPSET_TYPE_IP | IPSET_DATA_SINGLE)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("macipmap type of IP sets");
|
||||
|
||||
REGISTER_MODULE(macipmap)
|
||||
@@ -1,39 +0,0 @@
|
||||
#ifndef __IP_SET_MACIPMAP_H
|
||||
#define __IP_SET_MACIPMAP_H
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_bitmaps.h"
|
||||
|
||||
#define SETTYPE_NAME "macipmap"
|
||||
|
||||
/* general flags */
|
||||
#define IPSET_MACIP_MATCHUNSET 1
|
||||
|
||||
/* per ip flags */
|
||||
#define IPSET_MACIP_ISSET 1
|
||||
|
||||
struct ip_set_macipmap {
|
||||
void *members; /* the macipmap proper */
|
||||
ip_set_ip_t first_ip; /* host byte order, included in range */
|
||||
ip_set_ip_t last_ip; /* host byte order, included in range */
|
||||
u_int32_t flags;
|
||||
u_int32_t size; /* size of the ipmap proper */
|
||||
};
|
||||
|
||||
struct ip_set_req_macipmap_create {
|
||||
ip_set_ip_t from;
|
||||
ip_set_ip_t to;
|
||||
u_int32_t flags;
|
||||
};
|
||||
|
||||
struct ip_set_req_macipmap {
|
||||
ip_set_ip_t ip;
|
||||
unsigned char ethernet[ETH_ALEN];
|
||||
};
|
||||
|
||||
struct ip_set_macip {
|
||||
unsigned short match;
|
||||
unsigned char ethernet[ETH_ALEN];
|
||||
};
|
||||
|
||||
#endif /* __IP_SET_MACIPMAP_H */
|
||||
@@ -1,153 +0,0 @@
|
||||
#ifndef _IP_SET_MALLOC_H
|
||||
#define _IP_SET_MALLOC_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#include <linux/vmalloc.h>
|
||||
|
||||
static size_t max_malloc_size = 0, max_page_size = 0;
|
||||
static size_t default_max_malloc_size = 131072; /* Guaranteed: slab.c */
|
||||
|
||||
static inline int init_max_page_size(void)
|
||||
{
|
||||
/* Compatibility glues to support 2.4.36 */
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
|
||||
#define __GFP_NOWARN 0
|
||||
|
||||
/* Guaranteed: slab.c */
|
||||
max_malloc_size = max_page_size = default_max_malloc_size;
|
||||
#else
|
||||
size_t page_size = 0;
|
||||
|
||||
#define CACHE(x) if (max_page_size == 0 || x < max_page_size) \
|
||||
page_size = x;
|
||||
#include <linux/kmalloc_sizes.h>
|
||||
#undef CACHE
|
||||
if (page_size) {
|
||||
if (max_malloc_size == 0)
|
||||
max_malloc_size = page_size;
|
||||
|
||||
max_page_size = page_size;
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct harray {
|
||||
size_t max_elements;
|
||||
void *arrays[0];
|
||||
};
|
||||
|
||||
static inline void *
|
||||
__harray_malloc(size_t hashsize, size_t typesize, gfp_t flags)
|
||||
{
|
||||
struct harray *harray;
|
||||
size_t max_elements, size, i, j;
|
||||
|
||||
BUG_ON(max_page_size == 0);
|
||||
|
||||
if (typesize > max_page_size)
|
||||
return NULL;
|
||||
|
||||
max_elements = max_page_size/typesize;
|
||||
size = hashsize/max_elements;
|
||||
if (hashsize % max_elements)
|
||||
size++;
|
||||
|
||||
/* Last pointer signals end of arrays */
|
||||
harray = kmalloc(sizeof(struct harray) + (size + 1) * sizeof(void *),
|
||||
flags);
|
||||
|
||||
if (!harray)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < size - 1; i++) {
|
||||
harray->arrays[i] = kmalloc(max_elements * typesize, flags);
|
||||
if (!harray->arrays[i])
|
||||
goto undo;
|
||||
memset(harray->arrays[i], 0, max_elements * typesize);
|
||||
}
|
||||
harray->arrays[i] = kmalloc((hashsize - i * max_elements) * typesize,
|
||||
flags);
|
||||
if (!harray->arrays[i])
|
||||
goto undo;
|
||||
memset(harray->arrays[i], 0, (hashsize - i * max_elements) * typesize);
|
||||
|
||||
harray->max_elements = max_elements;
|
||||
harray->arrays[size] = NULL;
|
||||
|
||||
return (void *)harray;
|
||||
|
||||
undo:
|
||||
for (j = 0; j < i; j++) {
|
||||
kfree(harray->arrays[j]);
|
||||
}
|
||||
kfree(harray);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void *
|
||||
harray_malloc(size_t hashsize, size_t typesize, gfp_t flags)
|
||||
{
|
||||
void *harray;
|
||||
|
||||
do {
|
||||
harray = __harray_malloc(hashsize, typesize, flags|__GFP_NOWARN);
|
||||
} while (harray == NULL && init_max_page_size());
|
||||
|
||||
return harray;
|
||||
}
|
||||
|
||||
static inline void harray_free(void *h)
|
||||
{
|
||||
struct harray *harray = (struct harray *) h;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; harray->arrays[i] != NULL; i++)
|
||||
kfree(harray->arrays[i]);
|
||||
kfree(harray);
|
||||
}
|
||||
|
||||
static inline void harray_flush(void *h, size_t hashsize, size_t typesize)
|
||||
{
|
||||
struct harray *harray = (struct harray *) h;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; harray->arrays[i+1] != NULL; i++)
|
||||
memset(harray->arrays[i], 0, harray->max_elements * typesize);
|
||||
memset(harray->arrays[i], 0,
|
||||
(hashsize - i * harray->max_elements) * typesize);
|
||||
}
|
||||
|
||||
#define HARRAY_ELEM(h, type, which) \
|
||||
({ \
|
||||
struct harray *__h = (struct harray *)(h); \
|
||||
((type)((__h)->arrays[(which)/(__h)->max_elements]) \
|
||||
+ (which)%(__h)->max_elements); \
|
||||
})
|
||||
|
||||
/* General memory allocation and deallocation */
|
||||
static inline void * ip_set_malloc(size_t bytes)
|
||||
{
|
||||
BUG_ON(max_malloc_size == 0);
|
||||
|
||||
if (bytes > default_max_malloc_size)
|
||||
return vmalloc(bytes);
|
||||
else
|
||||
return kmalloc(bytes, GFP_KERNEL | __GFP_NOWARN);
|
||||
}
|
||||
|
||||
static inline void ip_set_free(void * data, size_t bytes)
|
||||
{
|
||||
BUG_ON(max_malloc_size == 0);
|
||||
|
||||
if (bytes > default_max_malloc_size)
|
||||
vfree(data);
|
||||
else
|
||||
kfree(data);
|
||||
}
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /*_IP_SET_MALLOC_H*/
|
||||
@@ -1,218 +0,0 @@
|
||||
/* Copyright (C) 2003-2008 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing a cidr nethash set */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include "ip_set_jhash.h"
|
||||
#include <linux/errno.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/random.h>
|
||||
|
||||
#include <net/ip.h>
|
||||
|
||||
#include "ip_set_nethash.h"
|
||||
|
||||
static int limit = MAX_RANGE;
|
||||
|
||||
static inline __u32
|
||||
nethash_id_cidr(const struct ip_set_nethash *map,
|
||||
ip_set_ip_t ip,
|
||||
uint8_t cidr)
|
||||
{
|
||||
__u32 id;
|
||||
u_int16_t i;
|
||||
ip_set_ip_t *elem;
|
||||
|
||||
ip = pack_ip_cidr(ip, cidr);
|
||||
if (!ip)
|
||||
return MAX_RANGE;
|
||||
|
||||
for (i = 0; i < map->probes; i++) {
|
||||
id = jhash_ip(map, i, ip) % map->hashsize;
|
||||
DP("hash key: %u", id);
|
||||
elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id);
|
||||
if (*elem == ip)
|
||||
return id;
|
||||
/* No shortcut - there can be deleted entries. */
|
||||
}
|
||||
return UINT_MAX;
|
||||
}
|
||||
|
||||
static inline __u32
|
||||
nethash_id(struct ip_set *set, ip_set_ip_t ip)
|
||||
{
|
||||
const struct ip_set_nethash *map = set->data;
|
||||
__u32 id = UINT_MAX;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 30 && map->cidr[i]; i++) {
|
||||
id = nethash_id_cidr(map, ip, map->cidr[i]);
|
||||
if (id != UINT_MAX)
|
||||
break;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
static inline int
|
||||
nethash_test_cidr(struct ip_set *set, ip_set_ip_t ip, uint8_t cidr)
|
||||
{
|
||||
const struct ip_set_nethash *map = set->data;
|
||||
|
||||
return (nethash_id_cidr(map, ip, cidr) != UINT_MAX);
|
||||
}
|
||||
|
||||
static inline int
|
||||
nethash_test(struct ip_set *set, ip_set_ip_t ip)
|
||||
{
|
||||
return (nethash_id(set, ip) != UINT_MAX);
|
||||
}
|
||||
|
||||
static int
|
||||
nethash_utest(struct ip_set *set, const void *data, u_int32_t size)
|
||||
{
|
||||
const struct ip_set_req_nethash *req = data;
|
||||
|
||||
if (req->cidr <= 0 || req->cidr > 32)
|
||||
return -EINVAL;
|
||||
return (req->cidr == 32 ? nethash_test(set, req->ip)
|
||||
: nethash_test_cidr(set, req->ip, req->cidr));
|
||||
}
|
||||
|
||||
#define KADT_CONDITION
|
||||
|
||||
KADT(nethash, test, ipaddr)
|
||||
|
||||
static inline int
|
||||
__nethash_add(struct ip_set_nethash *map, ip_set_ip_t *ip)
|
||||
{
|
||||
__u32 probe;
|
||||
u_int16_t i;
|
||||
ip_set_ip_t *elem, *slot = NULL;
|
||||
|
||||
for (i = 0; i < map->probes; i++) {
|
||||
probe = jhash_ip(map, i, *ip) % map->hashsize;
|
||||
elem = HARRAY_ELEM(map->members, ip_set_ip_t *, probe);
|
||||
if (*elem == *ip)
|
||||
return -EEXIST;
|
||||
if (!(slot || *elem))
|
||||
slot = elem;
|
||||
/* There can be deleted entries, must check all slots */
|
||||
}
|
||||
if (slot) {
|
||||
*slot = *ip;
|
||||
map->elements++;
|
||||
return 0;
|
||||
}
|
||||
/* Trigger rehashing */
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
static inline int
|
||||
nethash_add(struct ip_set *set, ip_set_ip_t ip, uint8_t cidr)
|
||||
{
|
||||
struct ip_set_nethash *map = set->data;
|
||||
int ret;
|
||||
|
||||
if (map->elements >= limit || map->nets[cidr-1] == UINT16_MAX)
|
||||
return -ERANGE;
|
||||
if (cidr <= 0 || cidr >= 32)
|
||||
return -EINVAL;
|
||||
|
||||
ip = pack_ip_cidr(ip, cidr);
|
||||
if (!ip)
|
||||
return -ERANGE;
|
||||
|
||||
ret = __nethash_add(map, &ip);
|
||||
if (ret == 0) {
|
||||
if (!map->nets[cidr-1]++)
|
||||
add_cidr_size(map->cidr, cidr);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef KADT_CONDITION
|
||||
#define KADT_CONDITION \
|
||||
struct ip_set_nethash *map = set->data; \
|
||||
uint8_t cidr = map->cidr[0] ? map->cidr[0] : 31;
|
||||
|
||||
UADT(nethash, add, req->cidr)
|
||||
KADT(nethash, add, ipaddr, cidr)
|
||||
|
||||
static inline void
|
||||
__nethash_retry(struct ip_set_nethash *tmp, struct ip_set_nethash *map)
|
||||
{
|
||||
memcpy(tmp->cidr, map->cidr, sizeof(tmp->cidr));
|
||||
memcpy(tmp->nets, map->nets, sizeof(tmp->nets));
|
||||
}
|
||||
|
||||
HASH_RETRY(nethash, ip_set_ip_t)
|
||||
|
||||
static inline int
|
||||
nethash_del(struct ip_set *set, ip_set_ip_t ip, uint8_t cidr)
|
||||
{
|
||||
struct ip_set_nethash *map = set->data;
|
||||
ip_set_ip_t id, *elem;
|
||||
|
||||
if (cidr <= 0 || cidr >= 32)
|
||||
return -EINVAL;
|
||||
|
||||
id = nethash_id_cidr(map, ip, cidr);
|
||||
if (id == UINT_MAX)
|
||||
return -EEXIST;
|
||||
|
||||
elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id);
|
||||
*elem = 0;
|
||||
map->elements--;
|
||||
if (!map->nets[cidr-1]--)
|
||||
del_cidr_size(map->cidr, cidr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
UADT(nethash, del, req->cidr)
|
||||
KADT(nethash, del, ipaddr, cidr)
|
||||
|
||||
static inline int
|
||||
__nethash_create(const struct ip_set_req_nethash_create *req,
|
||||
struct ip_set_nethash *map)
|
||||
{
|
||||
memset(map->cidr, 0, sizeof(map->cidr));
|
||||
memset(map->nets, 0, sizeof(map->nets));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
HASH_CREATE(nethash, ip_set_ip_t)
|
||||
HASH_DESTROY(nethash)
|
||||
|
||||
HASH_FLUSH_CIDR(nethash, ip_set_ip_t)
|
||||
|
||||
static inline void
|
||||
__nethash_list_header(const struct ip_set_nethash *map,
|
||||
struct ip_set_req_nethash_create *header)
|
||||
{
|
||||
}
|
||||
|
||||
HASH_LIST_HEADER(nethash)
|
||||
HASH_LIST_MEMBERS_SIZE(nethash, ip_set_ip_t)
|
||||
HASH_LIST_MEMBERS(nethash, ip_set_ip_t)
|
||||
|
||||
IP_SET_RTYPE(nethash, IPSET_TYPE_IP | IPSET_DATA_SINGLE)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("nethash type of IP sets");
|
||||
module_param(limit, int, 0600);
|
||||
MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets");
|
||||
|
||||
REGISTER_MODULE(nethash)
|
||||
@@ -1,31 +0,0 @@
|
||||
#ifndef __IP_SET_NETHASH_H
|
||||
#define __IP_SET_NETHASH_H
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_hashes.h"
|
||||
|
||||
#define SETTYPE_NAME "nethash"
|
||||
|
||||
struct ip_set_nethash {
|
||||
ip_set_ip_t *members; /* the nethash proper */
|
||||
uint32_t elements; /* number of elements */
|
||||
uint32_t hashsize; /* hash size */
|
||||
uint16_t probes; /* max number of probes */
|
||||
uint16_t resize; /* resize factor in percent */
|
||||
uint8_t cidr[30]; /* CIDR sizes */
|
||||
uint16_t nets[30]; /* nr of nets by CIDR sizes */
|
||||
initval_t initval[0]; /* initvals for jhash_1word */
|
||||
};
|
||||
|
||||
struct ip_set_req_nethash_create {
|
||||
uint32_t hashsize;
|
||||
uint16_t probes;
|
||||
uint16_t resize;
|
||||
};
|
||||
|
||||
struct ip_set_req_nethash {
|
||||
ip_set_ip_t ip;
|
||||
uint8_t cidr;
|
||||
};
|
||||
|
||||
#endif /* __IP_SET_NETHASH_H */
|
||||
@@ -1,130 +0,0 @@
|
||||
/* Copyright (C) 2003-2008 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing a port set type as a bitmap */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/udp.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include <net/ip.h>
|
||||
|
||||
#include "ip_set_portmap.h"
|
||||
#include "ip_set_getport.h"
|
||||
|
||||
static inline int
|
||||
portmap_test(const struct ip_set *set, ip_set_ip_t port)
|
||||
{
|
||||
const struct ip_set_portmap *map = set->data;
|
||||
|
||||
if (port < map->first_ip || port > map->last_ip)
|
||||
return -ERANGE;
|
||||
|
||||
DP("set: %s, port: %u", set->name, port);
|
||||
return !!test_bit(port - map->first_ip, map->members);
|
||||
}
|
||||
|
||||
#define KADT_CONDITION \
|
||||
if (ip == INVALID_PORT) \
|
||||
return 0;
|
||||
|
||||
UADT(portmap, test)
|
||||
KADT(portmap, test, get_port)
|
||||
|
||||
static inline int
|
||||
portmap_add(struct ip_set *set, ip_set_ip_t port)
|
||||
{
|
||||
struct ip_set_portmap *map = set->data;
|
||||
|
||||
if (port < map->first_ip || port > map->last_ip)
|
||||
return -ERANGE;
|
||||
if (test_and_set_bit(port - map->first_ip, map->members))
|
||||
return -EEXIST;
|
||||
|
||||
DP("set: %s, port %u", set->name, port);
|
||||
return 0;
|
||||
}
|
||||
|
||||
UADT(portmap, add)
|
||||
KADT(portmap, add, get_port)
|
||||
|
||||
static inline int
|
||||
portmap_del(struct ip_set *set, ip_set_ip_t port)
|
||||
{
|
||||
struct ip_set_portmap *map = set->data;
|
||||
|
||||
if (port < map->first_ip || port > map->last_ip)
|
||||
return -ERANGE;
|
||||
if (!test_and_clear_bit(port - map->first_ip, map->members))
|
||||
return -EEXIST;
|
||||
|
||||
DP("set: %s, port %u", set->name, port);
|
||||
return 0;
|
||||
}
|
||||
|
||||
UADT(portmap, del)
|
||||
KADT(portmap, del, get_port)
|
||||
|
||||
static inline int
|
||||
__portmap_create(const struct ip_set_req_portmap_create *req,
|
||||
struct ip_set_portmap *map)
|
||||
{
|
||||
if (req->to - req->from > MAX_RANGE) {
|
||||
ip_set_printk("range too big, %d elements (max %d)",
|
||||
req->to - req->from + 1, MAX_RANGE+1);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
return bitmap_bytes(req->from, req->to);
|
||||
}
|
||||
|
||||
BITMAP_CREATE(portmap)
|
||||
BITMAP_DESTROY(portmap)
|
||||
BITMAP_FLUSH(portmap)
|
||||
|
||||
static inline void
|
||||
__portmap_list_header(const struct ip_set_portmap *map,
|
||||
struct ip_set_req_portmap_create *header)
|
||||
{
|
||||
}
|
||||
|
||||
BITMAP_LIST_HEADER(portmap)
|
||||
BITMAP_LIST_MEMBERS_SIZE(portmap, ip_set_ip_t, (map->last_ip - map->first_ip + 1),
|
||||
test_bit(i, map->members))
|
||||
|
||||
static void
|
||||
portmap_list_members(const struct ip_set *set, void *data, char dont_align)
|
||||
{
|
||||
const struct ip_set_portmap *map = set->data;
|
||||
uint32_t i, n = 0;
|
||||
ip_set_ip_t *d;
|
||||
|
||||
if (dont_align) {
|
||||
memcpy(data, map->members, map->size);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < map->last_ip - map->first_ip + 1; i++)
|
||||
if (test_bit(i, map->members)) {
|
||||
d = data + n * IPSET_ALIGN(sizeof(ip_set_ip_t));
|
||||
*d = map->first_ip + i;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
IP_SET_TYPE(portmap, IPSET_TYPE_PORT | IPSET_DATA_SINGLE)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("portmap type of IP sets");
|
||||
|
||||
REGISTER_MODULE(portmap)
|
||||
@@ -1,25 +0,0 @@
|
||||
#ifndef __IP_SET_PORTMAP_H
|
||||
#define __IP_SET_PORTMAP_H
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_bitmaps.h"
|
||||
|
||||
#define SETTYPE_NAME "portmap"
|
||||
|
||||
struct ip_set_portmap {
|
||||
void *members; /* the portmap proper */
|
||||
ip_set_ip_t first_ip; /* host byte order, included in range */
|
||||
ip_set_ip_t last_ip; /* host byte order, included in range */
|
||||
u_int32_t size; /* size of the ipmap proper */
|
||||
};
|
||||
|
||||
struct ip_set_req_portmap_create {
|
||||
ip_set_ip_t from;
|
||||
ip_set_ip_t to;
|
||||
};
|
||||
|
||||
struct ip_set_req_portmap {
|
||||
ip_set_ip_t ip;
|
||||
};
|
||||
|
||||
#endif /* __IP_SET_PORTMAP_H */
|
||||
@@ -1,324 +0,0 @@
|
||||
/* Copyright (C) 2008 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an IP set type: the setlist type */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_bitmaps.h"
|
||||
#include "ip_set_setlist.h"
|
||||
|
||||
/*
|
||||
* before ==> index, ref
|
||||
* after ==> ref, index
|
||||
*/
|
||||
|
||||
static inline int
|
||||
next_index_eq(const struct ip_set_setlist *map, int i, ip_set_id_t index)
|
||||
{
|
||||
return i < map->size && map->index[i] == index;
|
||||
}
|
||||
|
||||
static int
|
||||
setlist_utest(struct ip_set *set, const void *data, u_int32_t size)
|
||||
{
|
||||
const struct ip_set_setlist *map = set->data;
|
||||
const struct ip_set_req_setlist *req = data;
|
||||
ip_set_id_t index, ref = IP_SET_INVALID_ID;
|
||||
int i, res = 0;
|
||||
struct ip_set *s;
|
||||
|
||||
if (req->before && req->ref[0] == '\0')
|
||||
return 0;
|
||||
|
||||
index = __ip_set_get_byname(req->name, &s);
|
||||
if (index == IP_SET_INVALID_ID)
|
||||
return 0;
|
||||
if (req->ref[0] != '\0') {
|
||||
ref = __ip_set_get_byname(req->ref, &s);
|
||||
if (ref == IP_SET_INVALID_ID)
|
||||
goto finish;
|
||||
}
|
||||
for (i = 0; i < map->size
|
||||
&& map->index[i] != IP_SET_INVALID_ID; i++) {
|
||||
if (req->before && map->index[i] == index) {
|
||||
res = next_index_eq(map, i + 1, ref);
|
||||
break;
|
||||
} else if (!req->before) {
|
||||
if ((ref == IP_SET_INVALID_ID
|
||||
&& map->index[i] == index)
|
||||
|| (map->index[i] == ref
|
||||
&& next_index_eq(map, i + 1, index))) {
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ref != IP_SET_INVALID_ID)
|
||||
__ip_set_put_byindex(ref);
|
||||
finish:
|
||||
__ip_set_put_byindex(index);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
setlist_ktest(struct ip_set *set,
|
||||
const struct sk_buff *skb,
|
||||
const u_int32_t *flags)
|
||||
{
|
||||
struct ip_set_setlist *map = set->data;
|
||||
int i, res = 0;
|
||||
|
||||
for (i = 0; i < map->size
|
||||
&& map->index[i] != IP_SET_INVALID_ID
|
||||
&& res == 0; i++)
|
||||
res = ip_set_testip_kernel(map->index[i], skb, flags);
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline int
|
||||
insert_setlist(struct ip_set_setlist *map, int i, ip_set_id_t index)
|
||||
{
|
||||
ip_set_id_t tmp;
|
||||
int j;
|
||||
|
||||
DP("i: %u, last %u\n", i, map->index[map->size - 1]);
|
||||
if (i >= map->size || map->index[map->size - 1] != IP_SET_INVALID_ID)
|
||||
return -ERANGE;
|
||||
|
||||
for (j = i; j < map->size
|
||||
&& index != IP_SET_INVALID_ID; j++) {
|
||||
tmp = map->index[j];
|
||||
map->index[j] = index;
|
||||
index = tmp;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
setlist_uadd(struct ip_set *set, const void *data, u_int32_t size)
|
||||
{
|
||||
struct ip_set_setlist *map = set->data;
|
||||
const struct ip_set_req_setlist *req = data;
|
||||
ip_set_id_t index, ref = IP_SET_INVALID_ID;
|
||||
int i, res = -ERANGE;
|
||||
struct ip_set *s;
|
||||
|
||||
if (req->before && req->ref[0] == '\0')
|
||||
return -EINVAL;
|
||||
|
||||
index = __ip_set_get_byname(req->name, &s);
|
||||
if (index == IP_SET_INVALID_ID)
|
||||
return -EEXIST;
|
||||
/* "Loop detection" */
|
||||
if (strcmp(s->type->typename, "setlist") == 0)
|
||||
goto finish;
|
||||
|
||||
if (req->ref[0] != '\0') {
|
||||
ref = __ip_set_get_byname(req->ref, &s);
|
||||
if (ref == IP_SET_INVALID_ID) {
|
||||
res = -EEXIST;
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < map->size; i++) {
|
||||
if (map->index[i] != ref)
|
||||
continue;
|
||||
if (req->before)
|
||||
res = insert_setlist(map, i, index);
|
||||
else
|
||||
res = insert_setlist(map,
|
||||
ref == IP_SET_INVALID_ID ? i : i + 1,
|
||||
index);
|
||||
break;
|
||||
}
|
||||
if (ref != IP_SET_INVALID_ID)
|
||||
__ip_set_put_byindex(ref);
|
||||
/* In case of success, we keep the reference to the set */
|
||||
finish:
|
||||
if (res != 0)
|
||||
__ip_set_put_byindex(index);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
setlist_kadd(struct ip_set *set,
|
||||
const struct sk_buff *skb,
|
||||
const u_int32_t *flags)
|
||||
{
|
||||
struct ip_set_setlist *map = set->data;
|
||||
int i, res = -EINVAL;
|
||||
|
||||
for (i = 0; i < map->size
|
||||
&& map->index[i] != IP_SET_INVALID_ID
|
||||
&& res != 0; i++)
|
||||
res = ip_set_addip_kernel(map->index[i], skb, flags);
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline int
|
||||
unshift_setlist(struct ip_set_setlist *map, int i)
|
||||
{
|
||||
int j;
|
||||
|
||||
for (j = i; j < map->size - 1; j++)
|
||||
map->index[j] = map->index[j+1];
|
||||
map->index[map->size-1] = IP_SET_INVALID_ID;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
setlist_udel(struct ip_set *set, const void *data, u_int32_t size)
|
||||
{
|
||||
struct ip_set_setlist *map = set->data;
|
||||
const struct ip_set_req_setlist *req = data;
|
||||
ip_set_id_t index, ref = IP_SET_INVALID_ID;
|
||||
int i, res = -EEXIST;
|
||||
struct ip_set *s;
|
||||
|
||||
if (req->before && req->ref[0] == '\0')
|
||||
return -EINVAL;
|
||||
|
||||
index = __ip_set_get_byname(req->name, &s);
|
||||
if (index == IP_SET_INVALID_ID)
|
||||
return -EEXIST;
|
||||
if (req->ref[0] != '\0') {
|
||||
ref = __ip_set_get_byname(req->ref, &s);
|
||||
if (ref == IP_SET_INVALID_ID)
|
||||
goto finish;
|
||||
}
|
||||
for (i = 0; i < map->size
|
||||
&& map->index[i] != IP_SET_INVALID_ID; i++) {
|
||||
if (req->before) {
|
||||
if (map->index[i] == index
|
||||
&& next_index_eq(map, i + 1, ref)) {
|
||||
res = unshift_setlist(map, i);
|
||||
break;
|
||||
}
|
||||
} else if (ref == IP_SET_INVALID_ID) {
|
||||
if (map->index[i] == index) {
|
||||
res = unshift_setlist(map, i);
|
||||
break;
|
||||
}
|
||||
} else if (map->index[i] == ref
|
||||
&& next_index_eq(map, i + 1, index)) {
|
||||
res = unshift_setlist(map, i + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ref != IP_SET_INVALID_ID)
|
||||
__ip_set_put_byindex(ref);
|
||||
finish:
|
||||
__ip_set_put_byindex(index);
|
||||
/* In case of success, release the reference to the set */
|
||||
if (res == 0)
|
||||
__ip_set_put_byindex(index);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
setlist_kdel(struct ip_set *set,
|
||||
const struct sk_buff *skb,
|
||||
const u_int32_t *flags)
|
||||
{
|
||||
struct ip_set_setlist *map = set->data;
|
||||
int i, res = -EINVAL;
|
||||
|
||||
for (i = 0; i < map->size
|
||||
&& map->index[i] != IP_SET_INVALID_ID
|
||||
&& res != 0; i++)
|
||||
res = ip_set_delip_kernel(map->index[i], skb, flags);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
setlist_create(struct ip_set *set, const void *data, u_int32_t size)
|
||||
{
|
||||
struct ip_set_setlist *map;
|
||||
const struct ip_set_req_setlist_create *req = data;
|
||||
int i;
|
||||
|
||||
map = kmalloc(sizeof(struct ip_set_setlist) +
|
||||
req->size * sizeof(ip_set_id_t), GFP_KERNEL);
|
||||
if (!map)
|
||||
return -ENOMEM;
|
||||
map->size = req->size;
|
||||
for (i = 0; i < map->size; i++)
|
||||
map->index[i] = IP_SET_INVALID_ID;
|
||||
|
||||
set->data = map;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
setlist_destroy(struct ip_set *set)
|
||||
{
|
||||
struct ip_set_setlist *map = set->data;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < map->size
|
||||
&& map->index[i] != IP_SET_INVALID_ID; i++)
|
||||
__ip_set_put_byindex(map->index[i]);
|
||||
|
||||
kfree(map);
|
||||
set->data = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
setlist_flush(struct ip_set *set)
|
||||
{
|
||||
struct ip_set_setlist *map = set->data;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < map->size
|
||||
&& map->index[i] != IP_SET_INVALID_ID; i++) {
|
||||
__ip_set_put_byindex(map->index[i]);
|
||||
map->index[i] = IP_SET_INVALID_ID;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
setlist_list_header(const struct ip_set *set, void *data)
|
||||
{
|
||||
const struct ip_set_setlist *map = set->data;
|
||||
struct ip_set_req_setlist_create *header = data;
|
||||
|
||||
header->size = map->size;
|
||||
}
|
||||
|
||||
static int
|
||||
setlist_list_members_size(const struct ip_set *set, char dont_align)
|
||||
{
|
||||
const struct ip_set_setlist *map = set->data;
|
||||
|
||||
return map->size * IPSET_VALIGN(sizeof(ip_set_id_t), dont_align);
|
||||
}
|
||||
|
||||
static void
|
||||
setlist_list_members(const struct ip_set *set, void *data, char dont_align)
|
||||
{
|
||||
struct ip_set_setlist *map = set->data;
|
||||
ip_set_id_t *d;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < map->size; i++) {
|
||||
d = data + i * IPSET_VALIGN(sizeof(ip_set_id_t), dont_align);
|
||||
*d = ip_set_id(map->index[i]);
|
||||
}
|
||||
}
|
||||
|
||||
IP_SET_TYPE(setlist, IPSET_TYPE_SETNAME | IPSET_DATA_SINGLE)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("setlist type of IP sets");
|
||||
|
||||
REGISTER_MODULE(setlist)
|
||||
@@ -1,26 +0,0 @@
|
||||
#ifndef __IP_SET_SETLIST_H
|
||||
#define __IP_SET_SETLIST_H
|
||||
|
||||
#include "ip_set.h"
|
||||
|
||||
#define SETTYPE_NAME "setlist"
|
||||
|
||||
#define IP_SET_SETLIST_ADD_AFTER 0
|
||||
#define IP_SET_SETLIST_ADD_BEFORE 1
|
||||
|
||||
struct ip_set_setlist {
|
||||
uint8_t size;
|
||||
ip_set_id_t index[0];
|
||||
};
|
||||
|
||||
struct ip_set_req_setlist_create {
|
||||
uint8_t size;
|
||||
};
|
||||
|
||||
struct ip_set_req_setlist {
|
||||
char name[IP_SET_MAXNAMELEN];
|
||||
char ref[IP_SET_MAXNAMELEN];
|
||||
uint8_t before;
|
||||
};
|
||||
|
||||
#endif /* __IP_SET_SETLIST_H */
|
||||
@@ -1,541 +0,0 @@
|
||||
.TH IPSET 8 "Feb 05, 2004" "" ""
|
||||
.\"
|
||||
.\" Man page written by Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
.\"
|
||||
.\" This program is free software; you can redistribute it and/or modify
|
||||
.\" it under the terms of the GNU General Public License as published by
|
||||
.\" the Free Software Foundation; either version 2 of the License, or
|
||||
.\" (at your option) any later version.
|
||||
.\"
|
||||
.\" This program is distributed in the hope that it will be useful,
|
||||
.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
.\" GNU General Public License for more details.
|
||||
.\"
|
||||
.\" You should have received a copy of the GNU General Public License
|
||||
.\" along with this program; if not, write to the Free Software
|
||||
.\" Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
.\"
|
||||
.\"
|
||||
.SH NAME
|
||||
ipset \(em administration tool for IP sets
|
||||
.SH SYNOPSIS
|
||||
.PP
|
||||
\fBipset \-N\fP \fIset\fP \fItype-specification\fP [\fIoptions\fP...]
|
||||
.PP
|
||||
\fBipset\fP {\fB\-F\fP|\fB\-H\fP|\fB\-L\fP|\fB\-S\fP|\fB\-X\fP} [\fIset\fP]
|
||||
[\fIoptions\fP...]
|
||||
.PP
|
||||
\fBipset\fP {\fB\-E\fP|\fB\-W\fP} \fIfrom-set\fP \fIto-set\fP
|
||||
.PP
|
||||
\fBipset\fP {\fB\-A\fP|\fB\-D\fP|\fB\-T\fP} \fIset\fP \fIentry\fP
|
||||
.PP
|
||||
\fBipset \-R\fP
|
||||
.PP
|
||||
\fBipset\fP {\fB-V\fP|\fB\-v\fP}
|
||||
.SH DESCRIPTION
|
||||
.B ipset
|
||||
is used to set up, maintain and inspect so called IP sets in the Linux
|
||||
kernel. Depending on the type, an IP set may store IP addresses, (TCP/UDP)
|
||||
port numbers or additional informations besides IP addresses: the word IP
|
||||
means a general term here. See the set type definitions below.
|
||||
.P
|
||||
Iptables matches and targets referring to sets creates references, which
|
||||
protects the given sets in the kernel. A set cannot be removed (destroyed)
|
||||
while there is a single reference pointing to it.
|
||||
.SH OPTIONS
|
||||
The options that are recognized by
|
||||
.B ipset
|
||||
can be divided into several different groups.
|
||||
.SS COMMANDS
|
||||
These options specify the specific action to perform. Only one of them
|
||||
can be specified on the command line unless otherwise specified
|
||||
below. For all the long versions of the command and option names, you
|
||||
need to use only enough letters to ensure that
|
||||
.B ipset
|
||||
can differentiate it from all other options.
|
||||
.TP
|
||||
\fB\-N\fP, \fB\-\-create\fP \fIsetname\fP \fItype\fP \fItype-specific-options\fP
|
||||
Create a set identified with setname and specified type.
|
||||
Type-specific options must be supplied.
|
||||
.TP
|
||||
\fB\-X\fP, \fB\-\-destroy\fP [\fIsetname\fP]
|
||||
Destroy the specified set or all the sets if none is given.
|
||||
|
||||
If the set has got references, nothing is done.
|
||||
.TP
|
||||
\fB\-F\fP, \fB\-\-flush\fP [\fIsetname\fP]
|
||||
Delete all entries from the specified set or flush
|
||||
all sets if none is given.
|
||||
.TP
|
||||
\fB\-E\fP, \fB\-\-rename\fP \fIfrom-setname\fP \fIto-setname\fP
|
||||
Rename a set. Set identified by to-setname must not exist.
|
||||
.TP
|
||||
\fB\-W\fP, \fB\-\-swap\fP \fIfrom-setname\fP \fIto-setname\fP
|
||||
Swap the content of two sets, or in another words,
|
||||
exchange the name of two sets. The referred sets must exist and
|
||||
identical type of sets can be swapped only.
|
||||
.TP
|
||||
\fB\-L\fP, \fB\-\-list\fP [\fIsetname\fP]
|
||||
List the entries for the specified set, or for
|
||||
all sets if none is given. The
|
||||
\fB\-r\fP/\fB\-\-resolve\fP
|
||||
option can be used to force name lookups (which may be slow). When the
|
||||
\fB\-s\fP/\fB\-\-sorted\fP
|
||||
option is given, the entries are listed sorted (if the given set
|
||||
type supports the operation).
|
||||
.TP
|
||||
\fB\-S\fP, \fB\-\-save\fP [\fIsetname\fP]
|
||||
Save the given set, or all sets if none is given
|
||||
to stdout in a format that \fB\-\-restore\fP can read.
|
||||
.TP
|
||||
\fB\-R\fP, \fB\-\-restore\fP
|
||||
Restore a saved session generated by \fB\-\-save\fP. The saved session
|
||||
can be fed from stdin.
|
||||
|
||||
When generating a session file please note that the supported commands
|
||||
(create set and add element) must appear in a strict order: first create
|
||||
the set, then add all elements. Then create the next set, add all its elements
|
||||
and so on. Also, it is a restore operation, so the sets being restored must
|
||||
not exist.
|
||||
.TP
|
||||
\fB\-A\fP, \fB\-\-add\fP \fIsetname\fP \fIentry\fP
|
||||
Add an entry to a set.
|
||||
.TP
|
||||
\fB\-D\fP, \fB\-\-del\fP \fIsetname\fP \fIentry\fP
|
||||
Delete an entry from a set.
|
||||
.TP
|
||||
\fB-T\fP, \fB\-\-test\fP \fIsetname\fP \fIentry\fP
|
||||
Test wether an entry is in a set or not. Exit status number is zero
|
||||
if the tested entry is in the set and nonzero if it is missing from
|
||||
the set.
|
||||
.TP
|
||||
\fB\-H\fP, \fB\-\-help\fP [\fIsettype\fP]
|
||||
Print help and settype specific help if settype specified.
|
||||
.TP
|
||||
\fB\-V\fP, \fB\-v\fP, \fB\-\-version\fP
|
||||
Print program version and protocol version.
|
||||
.P
|
||||
.SS "OTHER OPTIONS"
|
||||
The following additional options can be specified:
|
||||
.TP
|
||||
\fB\-r\fP, \fB\-\-resolve\fP
|
||||
When listing sets, enforce name lookup. The
|
||||
program will try to display the IP entries resolved to
|
||||
host names or services (whenever applicable), which can trigger
|
||||
.B
|
||||
slow
|
||||
DNS
|
||||
lookups.
|
||||
.TP
|
||||
\fB\-s\fP, \fB\-\-sorted\fP
|
||||
Sorted output. When listing sets, entries are listed sorted.
|
||||
.TP
|
||||
\fB\-n\fP, \fB\-\-numeric\fP
|
||||
Numeric output. When listing sets, IP addresses and
|
||||
port numbers will be printed in numeric format. This is the default.
|
||||
.TP
|
||||
\fB\-q\fP, \fB\-\-quiet\fP
|
||||
Suppress any output to stdout and stderr. ipset will still return
|
||||
possible errors.
|
||||
.SH SET TYPES
|
||||
ipset supports the following set types:
|
||||
.SS ipmap
|
||||
The ipmap set type uses a memory range, where each bit represents
|
||||
one IP address. An ipmap set can store up to 65536 (B-class network)
|
||||
IP addresses. The ipmap set type is very fast and memory cheap, great
|
||||
for use when one want to match certain IPs in a range. If the optional
|
||||
\fB\-\-netmask\fP
|
||||
parameter is specified with a CIDR netmask value between 1-31 then
|
||||
network addresses are stored in the given set: i.e an
|
||||
IP address will be in the set if the network address, which is resulted
|
||||
by masking the address with the specified netmask, can be found in the set.
|
||||
.P
|
||||
Options to use when creating an ipmap set:
|
||||
.TP
|
||||
\fB\-\-from\fP \fIfrom-addr\fP
|
||||
.TP
|
||||
\fB\-\-to\fP \fIto-addr\fP
|
||||
Create an ipmap set from the specified address range.
|
||||
.TP
|
||||
\fB\-\-network\fP \fIaddr\fP\fB/\fP\fImask\fP
|
||||
Create an ipmap set from the specified network.
|
||||
.TP
|
||||
\fB\-\-netmask\fP \fIprefixlen\fP
|
||||
When the optional
|
||||
\fB\-\-netmask\fP
|
||||
parameter specified, network addresses will be
|
||||
stored in the set instead of IP addresses, and the \fIfrom-addr\fP parameter
|
||||
must be a network address. The \fIprefixlen\fP value must be between 1-31.
|
||||
.PP
|
||||
Example:
|
||||
.IP
|
||||
ipset \-N test ipmap \-\-network 192.168.0.0/16
|
||||
.SS macipmap
|
||||
The macipmap set type uses a memory range, where each 8 bytes
|
||||
represents one IP and a MAC addresses. A macipmap set type can store
|
||||
up to 65536 (B-class network) IP addresses with MAC.
|
||||
When adding an entry to a macipmap set, you must specify the entry as
|
||||
"\fIaddress\fP\fB,\fP\fImac\fP".
|
||||
When deleting or testing macipmap entries, the
|
||||
"\fB,\fP\fImac\fP"
|
||||
part is not mandatory.
|
||||
.P
|
||||
Options to use when creating an macipmap set:
|
||||
.TP
|
||||
\fB\-\-from\fP \fIfrom-addr\fP
|
||||
.TP
|
||||
\fB\-\-to\fP \fIto-addr\fP
|
||||
Create a macipmap set from the specified address range.
|
||||
.TP
|
||||
\fB\-\-network\fP \fIaddr\fP\fB/\fP\fImask\fP
|
||||
Create a macipmap set from the specified network.
|
||||
.TP
|
||||
\fB\-\-matchunset\fP
|
||||
When the optional
|
||||
\fB\-\-matchunset\fP
|
||||
parameter specified, IP addresses which could be stored
|
||||
in the set but not set yet, will always match.
|
||||
.P
|
||||
Please note, the
|
||||
"set"
|
||||
and
|
||||
"SET"
|
||||
netfilter kernel modules
|
||||
.B
|
||||
always
|
||||
use the source MAC address from the packet to match, add or delete
|
||||
entries from a macipmap type of set.
|
||||
.SS portmap
|
||||
The portmap set type uses a memory range, where each bit represents
|
||||
one port. A portmap set type can store up to 65536 ports.
|
||||
The portmap set type is very fast and memory cheap.
|
||||
.P
|
||||
Options to use when creating an portmap set:
|
||||
.TP
|
||||
\fB\-\-from\fP \fIfrom-port\fP
|
||||
.TP
|
||||
\fB\-\-to\fP \fIto-port\fP
|
||||
Create a portmap set from the specified port range.
|
||||
.SS iphash
|
||||
The iphash set type uses a hash to store IP addresses.
|
||||
In order to avoid clashes in the hash double-hashing, and as a last
|
||||
resort, dynamic growing of the hash performed. The iphash set type is
|
||||
great to store random addresses. If the optional
|
||||
\fB\-\-netmask\fP
|
||||
parameter is specified with a CIDR prefix length value between 1-31 then
|
||||
network addresses are stored in the given set: i.e an
|
||||
IP address will be in the set if the network address, which is resulted
|
||||
by masking the address with the specified netmask, can be found in the set.
|
||||
.P
|
||||
Options to use when creating an iphash set:
|
||||
.TP
|
||||
\fB\-\-hashsize\fP \fIhashsize\fP
|
||||
The initial hash size (default 1024)
|
||||
.TP
|
||||
\fB\-\-probes\fP \fIprobes\fP
|
||||
How many times try to resolve clashing at adding an IP to the hash
|
||||
by double-hashing (default 8).
|
||||
.TP
|
||||
\fB\-\-resize\fP \fIpercent\fP
|
||||
Increase the hash size by this many percent (default 50) when adding
|
||||
an IP to the hash could not be performed after
|
||||
\fIprobes\fP
|
||||
number of double-hashing.
|
||||
.TP
|
||||
\fB\-\-netmask\fP \fIprefixlen\fP
|
||||
When the optional
|
||||
\fB\-\-netmask\fP
|
||||
parameter specified, network addresses will be
|
||||
stored in the set instead of IP addresses. The \fIprefixlen\fP value must
|
||||
be between 1-31.
|
||||
.P
|
||||
The iphash type of sets can store up to 65536 entries. If a set is full,
|
||||
no new entries can be added to it.
|
||||
.P
|
||||
Sets created by zero valued resize parameter won't be resized at all.
|
||||
The lookup time in an iphash type of set grows approximately linearly with
|
||||
the value of the
|
||||
\fIprobes\fP
|
||||
parameter. In general higher
|
||||
\fIprobes\fP
|
||||
value results better utilized hash while smaller value
|
||||
produces larger, sparser hash.
|
||||
.PP
|
||||
Example:
|
||||
.IP
|
||||
ipset \-N test iphash \-\-probes 2
|
||||
.SS nethash
|
||||
The nethash set type uses a hash to store different size of
|
||||
network addresses. The
|
||||
.I
|
||||
entry
|
||||
used in the ipset commands must be in the form
|
||||
"\fIaddress\fP\fB/\fP\fIprefixlen\fP"
|
||||
where prefixlen must be in the inclusive range of 1-31.
|
||||
In order to avoid clashes in the hash
|
||||
double-hashing, and as a last resort, dynamic growing of the hash performed.
|
||||
.P
|
||||
Options to use when creating an nethash set:
|
||||
.TP
|
||||
\fB\-\-hashsize\fP \fIhashsize\fP
|
||||
The initial hash size (default 1024)
|
||||
.TP
|
||||
\fB\-\-probes\fP \fIprobes\fP
|
||||
How many times try to resolve clashing at adding an IP to the hash
|
||||
by double-hashing (default 4).
|
||||
.TP
|
||||
\fB\-\-resize\fP \fIpercent\fP
|
||||
Increase the hash size by this many percent (default 50) when adding
|
||||
an IP to the hash could not be performed after
|
||||
.P
|
||||
The nethash type of sets can store up to 65536 entries. If a set is full,
|
||||
no new entries can be added to it.
|
||||
.P
|
||||
An IP address will be in a nethash type of set if it belongs to any of the
|
||||
netblocks added to the set. The matching always start from the smallest
|
||||
size of netblock (most specific netmask) to the largest ones (least
|
||||
specific netmasks). When adding/deleting IP addresses
|
||||
to a nethash set by the
|
||||
"SET"
|
||||
netfilter kernel module, it will be added/deleted by the smallest
|
||||
netblock size which can be found in the set, or by /31 if the set is empty.
|
||||
.P
|
||||
The lookup time in a nethash type of set grows approximately linearly
|
||||
with the times of the
|
||||
\fIprobes\fP
|
||||
parameter and the number of different mask parameters in the hash.
|
||||
Otherwise the same speed and memory efficiency comments applies here
|
||||
as at the iphash type.
|
||||
.SS ipporthash
|
||||
The ipporthash set type uses a hash to store IP address and port pairs.
|
||||
In order to avoid clashes in the hash double-hashing, and as a last
|
||||
resort, dynamic growing of the hash performed. An ipporthash set can
|
||||
store up to 65536 (B-class network) IP addresses with all possible port
|
||||
values. When adding, deleting and testing values in an ipporthash type of
|
||||
set, the entries must be specified as
|
||||
"\fIaddress\fP\fB,\fP\fIport\fP".
|
||||
.P
|
||||
The ipporthash types of sets evaluates two src/dst parameters of the
|
||||
"set"
|
||||
match and
|
||||
"SET"
|
||||
target.
|
||||
.P
|
||||
Options to use when creating an ipporthash set:
|
||||
.TP
|
||||
\fB\-\-from\fP \fIfrom-addr\fP
|
||||
.TP
|
||||
\fB\-\-to\fP \fIto-addr\fP
|
||||
Create an ipporthash set from the specified address range.
|
||||
.TP
|
||||
\fB\-\-network\fP \fIaddr\fP\fB/\fP\fImask\fP
|
||||
Create an ipporthash set from the specified network.
|
||||
.TP
|
||||
\fB\-\-hashsize\fP \fIhashsize\fP
|
||||
The initial hash size (default 1024)
|
||||
.TP
|
||||
\fB\-\-probes\fP \fIprobes\fP
|
||||
How many times try to resolve clashing at adding an IP to the hash
|
||||
by double-hashing (default 8).
|
||||
.TP
|
||||
\fB\-\-resize\fP \fIpercent\fP
|
||||
Increase the hash size by this many percent (default 50) when adding
|
||||
an IP to the hash could not be performed after
|
||||
\fIprobes\fP
|
||||
number of double-hashing.
|
||||
.P
|
||||
The same resizing, speed and memory efficiency comments applies here
|
||||
as at the iphash type.
|
||||
.SS ipportiphash
|
||||
The ipportiphash set type uses a hash to store IP address,port and IP
|
||||
address triples. The first IP address must come form a maximum /16
|
||||
sized network or range while the port number and the second IP address
|
||||
parameters are arbitrary. When adding, deleting and testing values in an
|
||||
ipportiphash type of set, the entries must be specified as
|
||||
"\fIaddress\fP\fB,\fP\fIport\fP\fB,\fP\fIaddress\fP".
|
||||
.P
|
||||
The ipportiphash types of sets evaluates three src/dst parameters of the
|
||||
"set"
|
||||
match and
|
||||
"SET"
|
||||
target.
|
||||
.P
|
||||
Options to use when creating an ipportiphash set:
|
||||
.TP
|
||||
\fB\-\-from\fP \fIfrom-addr\fP
|
||||
.TP
|
||||
\fB\-\-to\fP \fIto-addr\fP
|
||||
Create an ipportiphash set from the specified address range.
|
||||
.TP
|
||||
\fB\-\-network\fP \fIaddr\fP\fB/\fP\fImask\fP
|
||||
Create an ipportiphash set from the specified network.
|
||||
.TP
|
||||
\fB\-\-hashsize\fP \fIhashsize\fP
|
||||
The initial hash size (default 1024)
|
||||
.TP
|
||||
\fB\-\-probes\fP \fIprobes\fP
|
||||
How many times try to resolve clashing at adding an IP to the hash
|
||||
by double-hashing (default 8).
|
||||
.TP
|
||||
\fB\-\-resize\fP \fIpercent\fP
|
||||
Increase the hash size by this many percent (default 50) when adding
|
||||
an IP to the hash could not be performed after
|
||||
\fIprobes\fP
|
||||
number of double-hashing.
|
||||
.P
|
||||
The same resizing, speed and memory efficiency comments applies here
|
||||
as at the iphash type.
|
||||
.SS ipportnethash
|
||||
The ipportnethash set type uses a hash to store IP address, port, and
|
||||
network address triples. The IP address must come form a maximum /16
|
||||
sized network or range while the port number and the network address
|
||||
parameters are arbitrary, but the size of the network address must be
|
||||
between /1-/31. When adding, deleting
|
||||
and testing values in an ipportnethash type of set, the entries must be
|
||||
specified as
|
||||
"\fIaddress\fP\fB,\fP\fIport\fP\fB,\fP\fIaddress\fP\fB/\fP\fIprefixlen\fP".
|
||||
.P
|
||||
The ipportnethash types of sets evaluates three src/dst parameters of the
|
||||
"set"
|
||||
match and
|
||||
"SET"
|
||||
target.
|
||||
.P
|
||||
Options to use when creating an ipportnethash set:
|
||||
.TP
|
||||
\fB\-\-from\fP \fIfrom-address\fP
|
||||
.TP
|
||||
\fB\-\-to\fP \fIto-address\fP
|
||||
Create an ipporthash set from the specified range.
|
||||
.TP
|
||||
\fB\-\-network\fP \fIaddress\fP\fB/\fP\fImask\fP
|
||||
Create an ipporthash set from the specified network.
|
||||
.TP
|
||||
\fB\-\-hashsize\fP \fIhashsize\fP
|
||||
The initial hash size (default 1024)
|
||||
.TP
|
||||
\fB\-\-probes\fP \fIprobes\fP
|
||||
How many times try to resolve clashing at adding an IP to the hash
|
||||
by double-hashing (default 8).
|
||||
.TP
|
||||
\fB\-\-resize\fP \fIpercent\fP
|
||||
Increase the hash size by this many percent (default 50) when adding
|
||||
an IP to the hash could not be performed after
|
||||
\fIprobes\fP
|
||||
number of double-hashing.
|
||||
.P
|
||||
The same resizing, speed and memory efficiency comments applies here
|
||||
as at the iphash type.
|
||||
.SS iptree
|
||||
The iptree set type uses a tree to store IP addresses, optionally
|
||||
with timeout values.
|
||||
.P
|
||||
Options to use when creating an iptree set:
|
||||
.TP
|
||||
\fB\-\-timeout\fP \fIvalue\fP
|
||||
The timeout value for the entries in seconds (default 0)
|
||||
.P
|
||||
If a set was created with a nonzero valued
|
||||
\fB\-\-timeout\fP
|
||||
parameter then one may add IP addresses to the set with a specific
|
||||
timeout value using the syntax
|
||||
"\fIaddress\fP\fB,\fP\fItimeout-value\fP".
|
||||
Similarly to the hash types, the iptree type of sets can store up to 65536
|
||||
entries.
|
||||
.SS iptreemap
|
||||
The iptreemap set type uses a tree to store IP addresses or networks,
|
||||
where the last octet of an IP address are stored in a bitmap.
|
||||
As input entry, you can add IP addresses, CIDR blocks or network ranges
|
||||
to the set. Network ranges can be specified in the format
|
||||
"\fIaddress1\fP\fB-\fP\fIaddress2\fP".
|
||||
.P
|
||||
Options to use when creating an iptreemap set:
|
||||
.TP
|
||||
\fB\-\-gc\fP \fIvalue\fP
|
||||
How often the garbage collection should be called, in seconds (default 300)
|
||||
.SS setlist
|
||||
The setlist type uses a simple list in which you can store sets. By the
|
||||
ipset
|
||||
command you can add, delete and test sets in a setlist type of set.
|
||||
You can specify the sets as
|
||||
"\fIsetname\fP[\fB,\fP{\fBafter\fP|\fBbefore\fP},\fIsetname\fP]".
|
||||
By default new sets are added after (appended to) the existing
|
||||
elements. Setlist type of sets cannot be added to a setlist type of set.
|
||||
.P
|
||||
Options to use when creating a setlist type of set:
|
||||
.TP
|
||||
\fB\-\-size\fP \fIsize\fP
|
||||
Create a setlist type of set with the given size (default 8).
|
||||
.PP
|
||||
By the
|
||||
"set"
|
||||
match or
|
||||
"SET"
|
||||
target of
|
||||
\fBiptables\fP(8)
|
||||
you can test, add or delete entries in the sets. The match
|
||||
will try to find a matching IP address/port in the sets and
|
||||
the target will try to add the IP address/port to the first set
|
||||
to which it can be added. The number of src,dst options of
|
||||
the match and target are important: sets which eats more src,dst
|
||||
parameters than specified are skipped, while sets with equal
|
||||
or less parameters are checked, elements added. For example
|
||||
if
|
||||
.I
|
||||
a
|
||||
and
|
||||
.I
|
||||
b
|
||||
are setlist type of sets then in the command
|
||||
.IP
|
||||
iptables \-m set \-\-match\-set a src,dst \-j SET \-\-add-set b src,dst
|
||||
.PP
|
||||
the match and target will skip any set in
|
||||
.I a
|
||||
and
|
||||
.I b
|
||||
which stores
|
||||
data triples, but will check all sets with single or double
|
||||
data storage in
|
||||
.I a
|
||||
set and add src to the first single or src,dst to the first double
|
||||
data storage set in
|
||||
\fIb\fP.
|
||||
You can imagine a setlist type of set as an ordered union of
|
||||
the set elements.
|
||||
.P
|
||||
Please note: by the ipset command you can add, delete and
|
||||
.B test
|
||||
the setnames in a setlist type of set, and not the presence of
|
||||
a set's member (such as an IP address).
|
||||
.SH GENERAL RESTRICTIONS
|
||||
Setnames starting with colon (:) cannot be defined. Zero valued set
|
||||
entries cannot be used with hash type of sets.
|
||||
.SH COMMENTS
|
||||
If you want to store same size subnets from a given network
|
||||
(say /24 blocks from a /8 network), use the ipmap set type.
|
||||
If you want to store random same size networks (say random /24 blocks),
|
||||
use the iphash set type. If you have got random size of netblocks,
|
||||
use nethash.
|
||||
.P
|
||||
Old separator tokens (':' and '%") are still accepted.
|
||||
.P
|
||||
Binding support is removed.
|
||||
.SH DIAGNOSTICS
|
||||
Various error messages are printed to standard error. The exit code
|
||||
is 0 for correct functioning. Errors which appear to be caused by
|
||||
invalid or abused command line parameters cause an exit code of 2, and
|
||||
other errors cause an exit code of 1.
|
||||
.SH BUGS
|
||||
Bugs? No, just funny features. :-)
|
||||
OK, just kidding...
|
||||
.SH SEE ALSO
|
||||
.BR iptables (8),
|
||||
.SH AUTHORS
|
||||
Jozsef Kadlecsik wrote ipset, which is based on ippool by
|
||||
Joakim Axelsson, Patrick Schaaf and Martin Josefsson.
|
||||
.P
|
||||
Sven Wegener wrote the iptreemap type.
|
||||
.SH LAST REMARK
|
||||
.BR "I stand on the shoulders of giants."
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,200 +0,0 @@
|
||||
#ifndef __IPSET_H
|
||||
#define __IPSET_H
|
||||
|
||||
/* Copyright 2000-2004 Joakim Axelsson (gozem@linux.nu)
|
||||
* Patrick Schaaf (bof@bof.de)
|
||||
* Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <getopt.h> /* struct option */
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "ip_set.h"
|
||||
|
||||
#define IPSET_LIB_NAME "/libipset_%s.so"
|
||||
#define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe"
|
||||
|
||||
#define LIST_TRIES 5
|
||||
|
||||
#ifdef IPSET_DEBUG
|
||||
extern int option_debug;
|
||||
#define DP(format, args...) if (option_debug) \
|
||||
do { \
|
||||
fprintf(stderr, "%s: %s (DBG): ", __FILE__, __FUNCTION__);\
|
||||
fprintf(stderr, format "\n" , ## args); \
|
||||
} while (0)
|
||||
#else
|
||||
#define DP(format, args...)
|
||||
#endif
|
||||
|
||||
/* Commands */
|
||||
enum set_commands {
|
||||
CMD_NONE,
|
||||
CMD_CREATE, /* -N */
|
||||
CMD_DESTROY, /* -X */
|
||||
CMD_FLUSH, /* -F */
|
||||
CMD_RENAME, /* -E */
|
||||
CMD_SWAP, /* -W */
|
||||
CMD_LIST, /* -L */
|
||||
CMD_SAVE, /* -S */
|
||||
CMD_RESTORE, /* -R */
|
||||
CMD_ADD, /* -A */
|
||||
CMD_DEL, /* -D */
|
||||
CMD_TEST, /* -T */
|
||||
CMD_HELP, /* -H */
|
||||
CMD_VERSION, /* -V */
|
||||
NUMBER_OF_CMD = CMD_VERSION,
|
||||
/* Internal commands */
|
||||
CMD_MAX_SETS,
|
||||
CMD_LIST_SIZE,
|
||||
CMD_SAVE_SIZE,
|
||||
CMD_ADT_GET,
|
||||
};
|
||||
|
||||
enum exittype {
|
||||
OTHER_PROBLEM = 1,
|
||||
PARAMETER_PROBLEM,
|
||||
VERSION_PROBLEM
|
||||
};
|
||||
|
||||
/* The view of an ipset in userspace */
|
||||
struct set {
|
||||
char name[IP_SET_MAXNAMELEN]; /* Name of the set */
|
||||
ip_set_id_t id; /* Unique set id */
|
||||
ip_set_id_t index; /* Array index */
|
||||
unsigned ref; /* References in kernel */
|
||||
struct settype *settype; /* Pointer to set type functions */
|
||||
};
|
||||
|
||||
struct settype {
|
||||
struct settype *next;
|
||||
|
||||
char typename[IP_SET_MAXNAMELEN];
|
||||
|
||||
int protocol_version;
|
||||
|
||||
/*
|
||||
* Create set
|
||||
*/
|
||||
|
||||
/* Size of create data. Will be sent to kernel */
|
||||
u_int32_t create_size;
|
||||
|
||||
/* Initialize the create. */
|
||||
void (*create_init) (void *data);
|
||||
|
||||
/* Function which parses command options; returns true if it ate an option */
|
||||
int (*create_parse) (int c, char *argv[], void *data,
|
||||
unsigned *flags);
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
void (*create_final) (void *data, unsigned int flags);
|
||||
|
||||
/* Pointer to list of extra command-line options for create */
|
||||
const struct option *create_opts;
|
||||
|
||||
/*
|
||||
* Add/del/test IP
|
||||
*/
|
||||
|
||||
/* Size of data. Will be sent to kernel */
|
||||
u_int32_t adt_size;
|
||||
|
||||
/* Function which parses command options */
|
||||
ip_set_ip_t (*adt_parser) (int cmd, const char *optarg, void *data);
|
||||
|
||||
/*
|
||||
* Printing
|
||||
*/
|
||||
|
||||
/* Size of header. */
|
||||
u_int32_t header_size;
|
||||
|
||||
/* Initialize the type-header */
|
||||
void (*initheader) (struct set *set, const void *data);
|
||||
|
||||
/* Pretty print the type-header */
|
||||
void (*printheader) (struct set *set, unsigned options);
|
||||
|
||||
/* Pretty print all IPs */
|
||||
void (*printips) (struct set *set, void *data, u_int32_t len,
|
||||
unsigned options, char dont_align);
|
||||
|
||||
/* Pretty print all IPs sorted */
|
||||
void (*printips_sorted) (struct set *set, void *data, u_int32_t len,
|
||||
unsigned options, char dont_align);
|
||||
|
||||
/* Print save arguments for creating the set */
|
||||
void (*saveheader) (struct set *set, unsigned options);
|
||||
|
||||
/* Print save for all IPs */
|
||||
void (*saveips) (struct set *set, void *data, u_int32_t len,
|
||||
unsigned options, char dont_align);
|
||||
|
||||
/* Print usage */
|
||||
void (*usage) (void);
|
||||
|
||||
/* Internal data */
|
||||
void *header;
|
||||
void *data;
|
||||
int option_offset;
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
extern void settype_register(struct settype *settype);
|
||||
|
||||
/* extern void unregister_settype(set_type_t *set_type); */
|
||||
|
||||
extern void exit_error(int status, const char *msg, ...);
|
||||
|
||||
extern char *binding_ip_tostring(struct set *set,
|
||||
ip_set_ip_t ip, unsigned options);
|
||||
extern char *ip_tostring(ip_set_ip_t ip, unsigned options);
|
||||
extern char *ip_tostring_numeric(ip_set_ip_t ip);
|
||||
extern void parse_ip(const char *str, ip_set_ip_t * ip);
|
||||
extern void parse_mask(const char *str, ip_set_ip_t * mask);
|
||||
extern void parse_ipandmask(const char *str, ip_set_ip_t * ip,
|
||||
ip_set_ip_t * mask);
|
||||
extern char *port_tostring(ip_set_ip_t port, unsigned options);
|
||||
extern void parse_port(const char *str, ip_set_ip_t * port);
|
||||
extern int string_to_number(const char *str, unsigned int min, unsigned int max,
|
||||
ip_set_ip_t *port);
|
||||
|
||||
extern void *ipset_malloc(size_t size);
|
||||
extern char *ipset_strdup(const char *);
|
||||
extern void ipset_free(void *data);
|
||||
|
||||
extern struct set *set_find_byname(const char *name);
|
||||
extern struct set *set_find_byid(ip_set_id_t id);
|
||||
|
||||
extern unsigned warn_once;
|
||||
|
||||
#define BITS_PER_LONG (8*sizeof(ip_set_ip_t))
|
||||
#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
|
||||
|
||||
static inline int test_bit(int nr, const ip_set_ip_t *addr)
|
||||
{
|
||||
return 1 & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
|
||||
}
|
||||
|
||||
#define UNUSED __attribute__ ((unused))
|
||||
#define CONSTRUCTOR(module) \
|
||||
void __attribute__ ((constructor)) module##_init(void); \
|
||||
void module##_init(void)
|
||||
|
||||
#endif /* __IPSET_H */
|
||||
@@ -1,279 +0,0 @@
|
||||
/* Copyright 2004 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <limits.h> /* UINT_MAX */
|
||||
#include <stdio.h> /* *printf */
|
||||
#include <string.h> /* mem* */
|
||||
|
||||
#include "ipset.h"
|
||||
|
||||
#include "ip_set_iphash.h"
|
||||
|
||||
#define BUFLEN 30;
|
||||
|
||||
#define OPT_CREATE_HASHSIZE 0x01U
|
||||
#define OPT_CREATE_PROBES 0x02U
|
||||
#define OPT_CREATE_RESIZE 0x04U
|
||||
#define OPT_CREATE_NETMASK 0x08U
|
||||
|
||||
/* Initialize the create. */
|
||||
static void
|
||||
iphash_create_init(void *data)
|
||||
{
|
||||
struct ip_set_req_iphash_create *mydata = data;
|
||||
|
||||
DP("create INIT");
|
||||
|
||||
/* Default create parameters */
|
||||
mydata->hashsize = IP_NF_SET_HASHSIZE;
|
||||
mydata->probes = 8;
|
||||
mydata->resize = 50;
|
||||
|
||||
mydata->netmask = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
/* Function which parses command options; returns true if it ate an option */
|
||||
static int
|
||||
iphash_create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags)
|
||||
{
|
||||
struct ip_set_req_iphash_create *mydata =
|
||||
(struct ip_set_req_iphash_create *) data;
|
||||
unsigned int bits;
|
||||
ip_set_ip_t value;
|
||||
|
||||
DP("create_parse");
|
||||
|
||||
switch (c) {
|
||||
case '1':
|
||||
|
||||
if (string_to_number(optarg, 1, UINT_MAX - 1, &mydata->hashsize))
|
||||
exit_error(PARAMETER_PROBLEM, "Invalid hashsize `%s' specified", optarg);
|
||||
|
||||
*flags |= OPT_CREATE_HASHSIZE;
|
||||
|
||||
DP("--hashsize %u", mydata->hashsize);
|
||||
|
||||
break;
|
||||
|
||||
case '2':
|
||||
|
||||
if (string_to_number(optarg, 1, 65535, &value))
|
||||
exit_error(PARAMETER_PROBLEM, "Invalid probes `%s' specified", optarg);
|
||||
|
||||
mydata->probes = value;
|
||||
*flags |= OPT_CREATE_PROBES;
|
||||
|
||||
DP("--probes %u", mydata->probes);
|
||||
|
||||
break;
|
||||
|
||||
case '3':
|
||||
|
||||
if (string_to_number(optarg, 0, 65535, &value))
|
||||
exit_error(PARAMETER_PROBLEM, "Invalid resize `%s' specified", optarg);
|
||||
|
||||
mydata->resize = value;
|
||||
*flags |= OPT_CREATE_RESIZE;
|
||||
|
||||
DP("--resize %u", mydata->resize);
|
||||
|
||||
break;
|
||||
|
||||
case '4':
|
||||
|
||||
if (string_to_number(optarg, 0, 32, &bits))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Invalid netmask `%s' specified", optarg);
|
||||
|
||||
if (bits != 0)
|
||||
mydata->netmask = 0xFFFFFFFF << (32 - bits);
|
||||
|
||||
*flags |= OPT_CREATE_NETMASK;
|
||||
|
||||
DP("--netmask %x", mydata->netmask);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
static void
|
||||
iphash_create_final(void *data UNUSED, unsigned int flags UNUSED)
|
||||
{
|
||||
}
|
||||
|
||||
/* Create commandline options */
|
||||
static const struct option create_opts[] = {
|
||||
{.name = "hashsize", .has_arg = required_argument, .val = '1'},
|
||||
{.name = "probes", .has_arg = required_argument, .val = '2'},
|
||||
{.name = "resize", .has_arg = required_argument, .val = '3'},
|
||||
{.name = "netmask", .has_arg = required_argument, .val = '4'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
/* Add, del, test parser */
|
||||
static ip_set_ip_t
|
||||
iphash_adt_parser(int cmd UNUSED, const char *arg, void *data)
|
||||
{
|
||||
struct ip_set_req_iphash *mydata = data;
|
||||
|
||||
parse_ip(arg, &mydata->ip);
|
||||
if (!mydata->ip)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Zero valued IP address `%s' specified", arg);
|
||||
|
||||
return mydata->ip;
|
||||
};
|
||||
|
||||
/*
|
||||
* Print and save
|
||||
*/
|
||||
|
||||
static void
|
||||
iphash_initheader(struct set *set, const void *data)
|
||||
{
|
||||
const struct ip_set_req_iphash_create *header = data;
|
||||
struct ip_set_iphash *map = set->settype->header;
|
||||
|
||||
memset(map, 0, sizeof(struct ip_set_iphash));
|
||||
map->hashsize = header->hashsize;
|
||||
map->probes = header->probes;
|
||||
map->resize = header->resize;
|
||||
map->netmask = header->netmask;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
mask_to_bits(ip_set_ip_t mask)
|
||||
{
|
||||
unsigned int bits = 32;
|
||||
ip_set_ip_t maskaddr;
|
||||
|
||||
if (mask == 0xFFFFFFFF)
|
||||
return bits;
|
||||
|
||||
maskaddr = 0xFFFFFFFE;
|
||||
while (--bits > 0 && maskaddr != mask)
|
||||
maskaddr <<= 1;
|
||||
|
||||
return bits;
|
||||
}
|
||||
|
||||
static void
|
||||
iphash_printheader(struct set *set, unsigned options UNUSED)
|
||||
{
|
||||
struct ip_set_iphash *mysetdata = set->settype->header;
|
||||
|
||||
printf(" hashsize: %u", mysetdata->hashsize);
|
||||
printf(" probes: %u", mysetdata->probes);
|
||||
printf(" resize: %u", mysetdata->resize);
|
||||
if (mysetdata->netmask == 0xFFFFFFFF)
|
||||
printf("\n");
|
||||
else
|
||||
printf(" netmask: %d\n", mask_to_bits(mysetdata->netmask));
|
||||
}
|
||||
|
||||
static void
|
||||
iphash_printips(struct set *set UNUSED, void *data, u_int32_t len,
|
||||
unsigned options, char dont_align)
|
||||
{
|
||||
size_t offset = 0;
|
||||
ip_set_ip_t *ip;
|
||||
|
||||
while (offset < len) {
|
||||
ip = data + offset;
|
||||
printf("%s\n", ip_tostring(*ip, options));
|
||||
offset += IPSET_VALIGN(sizeof(ip_set_ip_t), dont_align);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
iphash_saveheader(struct set *set, unsigned options UNUSED)
|
||||
{
|
||||
struct ip_set_iphash *mysetdata = set->settype->header;
|
||||
|
||||
printf("-N %s %s --hashsize %u --probes %u --resize %u",
|
||||
set->name, set->settype->typename,
|
||||
mysetdata->hashsize, mysetdata->probes, mysetdata->resize);
|
||||
if (mysetdata->netmask == 0xFFFFFFFF)
|
||||
printf("\n");
|
||||
else
|
||||
printf(" --netmask %d\n", mask_to_bits(mysetdata->netmask));
|
||||
}
|
||||
|
||||
/* Print save for an IP */
|
||||
static void
|
||||
iphash_saveips(struct set *set UNUSED, void *data, u_int32_t len,
|
||||
unsigned options, char dont_align)
|
||||
{
|
||||
size_t offset = 0;
|
||||
ip_set_ip_t *ip;
|
||||
|
||||
while (offset < len) {
|
||||
ip = data + offset;
|
||||
printf("-A %s %s\n", set->name, ip_tostring(*ip, options));
|
||||
offset += IPSET_VALIGN(sizeof(ip_set_ip_t), dont_align);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
iphash_usage(void)
|
||||
{
|
||||
printf
|
||||
("-N set iphash [--hashsize hashsize] [--probes probes ]\n"
|
||||
" [--resize resize] [--netmask CIDR-netmask]\n"
|
||||
"-A set IP\n"
|
||||
"-D set IP\n"
|
||||
"-T set IP\n");
|
||||
}
|
||||
|
||||
static struct settype settype_iphash = {
|
||||
.typename = SETTYPE_NAME,
|
||||
.protocol_version = IP_SET_PROTOCOL_VERSION,
|
||||
|
||||
/* Create */
|
||||
.create_size = sizeof(struct ip_set_req_iphash_create),
|
||||
.create_init = iphash_create_init,
|
||||
.create_parse = iphash_create_parse,
|
||||
.create_final = iphash_create_final,
|
||||
.create_opts = create_opts,
|
||||
|
||||
/* Add/del/test */
|
||||
.adt_size = sizeof(struct ip_set_req_iphash),
|
||||
.adt_parser = iphash_adt_parser,
|
||||
|
||||
/* Printing */
|
||||
.header_size = sizeof(struct ip_set_iphash),
|
||||
.initheader = iphash_initheader,
|
||||
.printheader = iphash_printheader,
|
||||
.printips = iphash_printips,
|
||||
.printips_sorted = iphash_printips,
|
||||
.saveheader = iphash_saveheader,
|
||||
.saveips = iphash_saveips,
|
||||
|
||||
.usage = iphash_usage,
|
||||
};
|
||||
|
||||
CONSTRUCTOR(iphash)
|
||||
{
|
||||
settype_register(&settype_iphash);
|
||||
|
||||
}
|
||||
@@ -1,376 +0,0 @@
|
||||
/* Copyright 2000-2004 Joakim Axelsson (gozem@linux.nu)
|
||||
* Patrick Schaaf (bof@bof.de)
|
||||
* Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h> /* *printf */
|
||||
#include <string.h> /* mem* */
|
||||
|
||||
#include "ipset.h"
|
||||
|
||||
#include "ip_set_ipmap.h"
|
||||
|
||||
#define BUFLEN 30;
|
||||
|
||||
#define OPT_CREATE_FROM 0x01U
|
||||
#define OPT_CREATE_TO 0x02U
|
||||
#define OPT_CREATE_NETWORK 0x04U
|
||||
#define OPT_CREATE_NETMASK 0x08U
|
||||
|
||||
#define OPT_ADDDEL_IP 0x01U
|
||||
|
||||
/* Initialize the create. */
|
||||
static void
|
||||
ipmap_create_init(void *data)
|
||||
{
|
||||
struct ip_set_req_ipmap_create *mydata = data;
|
||||
|
||||
DP("create INIT");
|
||||
mydata->netmask = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
/* Function which parses command options; returns true if it ate an option */
|
||||
static int
|
||||
ipmap_create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags)
|
||||
{
|
||||
struct ip_set_req_ipmap_create *mydata = data;
|
||||
unsigned int bits;
|
||||
|
||||
DP("create_parse");
|
||||
|
||||
switch (c) {
|
||||
case '1':
|
||||
parse_ip(optarg, &mydata->from);
|
||||
|
||||
*flags |= OPT_CREATE_FROM;
|
||||
|
||||
DP("--from %x (%s)", mydata->from,
|
||||
ip_tostring_numeric(mydata->from));
|
||||
|
||||
break;
|
||||
|
||||
case '2':
|
||||
parse_ip(optarg, &mydata->to);
|
||||
|
||||
*flags |= OPT_CREATE_TO;
|
||||
|
||||
DP("--to %x (%s)", mydata->to,
|
||||
ip_tostring_numeric(mydata->to));
|
||||
|
||||
break;
|
||||
|
||||
case '3':
|
||||
parse_ipandmask(optarg, &mydata->from, &mydata->to);
|
||||
|
||||
/* Make to the last of from + mask */
|
||||
if (mydata->to)
|
||||
mydata->to = mydata->from | ~(mydata->to);
|
||||
else {
|
||||
mydata->from = 0x00000000;
|
||||
mydata->to = 0xFFFFFFFF;
|
||||
}
|
||||
*flags |= OPT_CREATE_NETWORK;
|
||||
|
||||
DP("--network from %x (%s)",
|
||||
mydata->from, ip_tostring_numeric(mydata->from));
|
||||
DP("--network to %x (%s)",
|
||||
mydata->to, ip_tostring_numeric(mydata->to));
|
||||
|
||||
break;
|
||||
|
||||
case '4':
|
||||
if (string_to_number(optarg, 0, 32, &bits))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Invalid netmask `%s' specified", optarg);
|
||||
|
||||
if (bits != 0)
|
||||
mydata->netmask = 0xFFFFFFFF << (32 - bits);
|
||||
|
||||
*flags |= OPT_CREATE_NETMASK;
|
||||
|
||||
DP("--netmask %x", mydata->netmask);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
static void
|
||||
ipmap_create_final(void *data, unsigned int flags)
|
||||
{
|
||||
struct ip_set_req_ipmap_create *mydata = data;
|
||||
ip_set_ip_t range;
|
||||
|
||||
if (flags == 0)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Need to specify --from and --to, or --network\n");
|
||||
|
||||
if (flags & OPT_CREATE_NETWORK) {
|
||||
/* --network */
|
||||
if ((flags & OPT_CREATE_FROM) || (flags & OPT_CREATE_TO))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Can't specify --from or --to with --network\n");
|
||||
} else {
|
||||
/* --from --to */
|
||||
if ((flags & OPT_CREATE_FROM) == 0
|
||||
|| (flags & OPT_CREATE_TO) == 0)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Need to specify both --from and --to\n");
|
||||
}
|
||||
|
||||
DP("from : %x to: %x diff: %x",
|
||||
mydata->from, mydata->to,
|
||||
mydata->to - mydata->from);
|
||||
|
||||
if (mydata->from > mydata->to)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"From can't be lower than to.\n");
|
||||
|
||||
if (flags & OPT_CREATE_NETMASK) {
|
||||
unsigned int mask_bits, netmask_bits;
|
||||
ip_set_ip_t mask;
|
||||
|
||||
if ((mydata->from & mydata->netmask) != mydata->from)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"%s is not a network address according to netmask %d\n",
|
||||
ip_tostring_numeric(mydata->from),
|
||||
mask_to_bits(mydata->netmask));
|
||||
|
||||
mask = range_to_mask(mydata->from, mydata->to, &mask_bits);
|
||||
if (!mask
|
||||
&& (mydata->from || mydata->to != 0xFFFFFFFF)) {
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"You have to define a full network with --from"
|
||||
" and --to if you specify the --network option\n");
|
||||
}
|
||||
netmask_bits = mask_to_bits(mydata->netmask);
|
||||
if (netmask_bits <= mask_bits) {
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"%d netmask specifies larger or equal netblock than the network itself\n");
|
||||
}
|
||||
range = (1<<(netmask_bits - mask_bits)) - 1;
|
||||
} else {
|
||||
range = mydata->to - mydata->from;
|
||||
}
|
||||
if (range > MAX_RANGE)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Range too large. Max is %d IPs in range\n",
|
||||
MAX_RANGE+1);
|
||||
}
|
||||
|
||||
/* Create commandline options */
|
||||
static const struct option create_opts[] = {
|
||||
{.name = "from", .has_arg = required_argument, .val = '1'},
|
||||
{.name = "to", .has_arg = required_argument, .val = '2'},
|
||||
{.name = "network", .has_arg = required_argument, .val = '3'},
|
||||
{.name = "netmask", .has_arg = required_argument, .val = '4'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
/* Add, del, test parser */
|
||||
static ip_set_ip_t
|
||||
ipmap_adt_parser(int cmd UNUSED, const char *arg, void *data)
|
||||
{
|
||||
struct ip_set_req_ipmap *mydata = data;
|
||||
|
||||
DP("ipmap: %p %p", arg, data);
|
||||
|
||||
parse_ip(arg, &mydata->ip);
|
||||
DP("%s", ip_tostring_numeric(mydata->ip));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Print and save
|
||||
*/
|
||||
|
||||
static void
|
||||
ipmap_initheader(struct set *set, const void *data)
|
||||
{
|
||||
const struct ip_set_req_ipmap_create *header = data;
|
||||
struct ip_set_ipmap *map = set->settype->header;
|
||||
|
||||
memset(map, 0, sizeof(struct ip_set_ipmap));
|
||||
map->first_ip = header->from;
|
||||
map->last_ip = header->to;
|
||||
map->netmask = header->netmask;
|
||||
|
||||
if (map->netmask == 0xFFFFFFFF) {
|
||||
map->hosts = 1;
|
||||
map->sizeid = map->last_ip - map->first_ip + 1;
|
||||
} else {
|
||||
unsigned int mask_bits, netmask_bits;
|
||||
ip_set_ip_t mask;
|
||||
|
||||
mask = range_to_mask(header->from, header->to, &mask_bits);
|
||||
netmask_bits = mask_to_bits(header->netmask);
|
||||
|
||||
DP("bits: %d %d", mask_bits, netmask_bits);
|
||||
map->hosts = 2 << (32 - netmask_bits - 1);
|
||||
map->sizeid = 2 << (netmask_bits - mask_bits - 1);
|
||||
}
|
||||
|
||||
DP("%d %d", map->hosts, map->sizeid );
|
||||
}
|
||||
|
||||
static void
|
||||
ipmap_printheader(struct set *set, unsigned options)
|
||||
{
|
||||
struct ip_set_ipmap *mysetdata = set->settype->header;
|
||||
|
||||
printf(" from: %s", ip_tostring(mysetdata->first_ip, options));
|
||||
printf(" to: %s", ip_tostring(mysetdata->last_ip, options));
|
||||
if (mysetdata->netmask == 0xFFFFFFFF)
|
||||
printf("\n");
|
||||
else
|
||||
printf(" netmask: %d\n", mask_to_bits(mysetdata->netmask));
|
||||
}
|
||||
|
||||
static inline void
|
||||
__ipmap_printips_sorted(struct set *set, void *data,
|
||||
u_int32_t len UNUSED, unsigned options)
|
||||
{
|
||||
struct ip_set_ipmap *mysetdata = set->settype->header;
|
||||
ip_set_ip_t id;
|
||||
|
||||
for (id = 0; id < mysetdata->sizeid; id++)
|
||||
if (test_bit(id, data))
|
||||
printf("%s\n",
|
||||
ip_tostring(mysetdata->first_ip
|
||||
+ id * mysetdata->hosts,
|
||||
options));
|
||||
}
|
||||
|
||||
static void
|
||||
ipmap_printips_sorted(struct set *set, void *data,
|
||||
u_int32_t len, unsigned options,
|
||||
char dont_align)
|
||||
{
|
||||
ip_set_ip_t *ip;
|
||||
size_t offset = 0;
|
||||
|
||||
if (dont_align)
|
||||
return __ipmap_printips_sorted(set, data, len, options);
|
||||
|
||||
while (offset < len) {
|
||||
DP("offset: %zu, len %u\n", offset, len);
|
||||
ip = data + offset;
|
||||
printf("%s\n", ip_tostring(*ip, options));
|
||||
offset += IPSET_ALIGN(sizeof(ip_set_ip_t));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ipmap_saveheader(struct set *set, unsigned options)
|
||||
{
|
||||
struct ip_set_ipmap *mysetdata = set->settype->header;
|
||||
|
||||
printf("-N %s %s --from %s",
|
||||
set->name, set->settype->typename,
|
||||
ip_tostring(mysetdata->first_ip, options));
|
||||
printf(" --to %s",
|
||||
ip_tostring(mysetdata->last_ip, options));
|
||||
if (mysetdata->netmask == 0xFFFFFFFF)
|
||||
printf("\n");
|
||||
else
|
||||
printf(" --netmask %d\n",
|
||||
mask_to_bits(mysetdata->netmask));
|
||||
}
|
||||
|
||||
static inline void
|
||||
__ipmap_saveips(struct set *set, void *data, u_int32_t len UNUSED,
|
||||
unsigned options)
|
||||
{
|
||||
struct ip_set_ipmap *mysetdata = set->settype->header;
|
||||
ip_set_ip_t id;
|
||||
|
||||
DP("%s", set->name);
|
||||
for (id = 0; id < mysetdata->sizeid; id++)
|
||||
if (test_bit(id, data))
|
||||
printf("-A %s %s\n",
|
||||
set->name,
|
||||
ip_tostring(mysetdata->first_ip
|
||||
+ id * mysetdata->hosts,
|
||||
options));
|
||||
}
|
||||
|
||||
static void
|
||||
ipmap_saveips(struct set *set, void *data, u_int32_t len,
|
||||
unsigned options, char dont_align)
|
||||
{
|
||||
ip_set_ip_t *ip;
|
||||
size_t offset = 0;
|
||||
|
||||
if (dont_align)
|
||||
return __ipmap_saveips(set, data, len, options);
|
||||
|
||||
while (offset < len) {
|
||||
ip = data + offset;
|
||||
printf("-A %s %s\n", set->name, ip_tostring(*ip, options));
|
||||
offset += IPSET_ALIGN(sizeof(ip_set_ip_t));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ipmap_usage(void)
|
||||
{
|
||||
printf
|
||||
("-N set ipmap --from IP --to IP [--netmask CIDR-netmask]\n"
|
||||
"-N set ipmap --network IP/mask [--netmask CIDR-netmask]\n"
|
||||
"-A set IP\n"
|
||||
"-D set IP\n"
|
||||
"-T set IP\n");
|
||||
}
|
||||
|
||||
static struct settype settype_ipmap = {
|
||||
.typename = SETTYPE_NAME,
|
||||
.protocol_version = IP_SET_PROTOCOL_VERSION,
|
||||
|
||||
/* Create */
|
||||
.create_size = sizeof(struct ip_set_req_ipmap_create),
|
||||
.create_init = ipmap_create_init,
|
||||
.create_parse = ipmap_create_parse,
|
||||
.create_final = ipmap_create_final,
|
||||
.create_opts = create_opts,
|
||||
|
||||
/* Add/del/test */
|
||||
.adt_size = sizeof(struct ip_set_req_ipmap),
|
||||
.adt_parser = ipmap_adt_parser,
|
||||
|
||||
/* Printing */
|
||||
.header_size = sizeof(struct ip_set_ipmap),
|
||||
.initheader = ipmap_initheader,
|
||||
.printheader = ipmap_printheader,
|
||||
.printips = ipmap_printips_sorted,
|
||||
.printips_sorted = ipmap_printips_sorted,
|
||||
.saveheader = ipmap_saveheader,
|
||||
.saveips = ipmap_saveips,
|
||||
|
||||
.usage = ipmap_usage,
|
||||
};
|
||||
|
||||
CONSTRUCTOR(ipmap)
|
||||
{
|
||||
settype_register(&settype_ipmap);
|
||||
|
||||
}
|
||||
@@ -1,350 +0,0 @@
|
||||
/* Copyright 2004 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <limits.h> /* UINT_MAX */
|
||||
#include <stdio.h> /* *printf */
|
||||
#include <string.h> /* mem*, str* */
|
||||
|
||||
#include "ipset.h"
|
||||
|
||||
#include "ip_set_ipporthash.h"
|
||||
|
||||
#define OPT_CREATE_HASHSIZE 0x01U
|
||||
#define OPT_CREATE_PROBES 0x02U
|
||||
#define OPT_CREATE_RESIZE 0x04U
|
||||
#define OPT_CREATE_NETWORK 0x08U
|
||||
#define OPT_CREATE_FROM 0x10U
|
||||
#define OPT_CREATE_TO 0x20U
|
||||
|
||||
/* Initialize the create. */
|
||||
static void
|
||||
ipporthash_create_init(void *data)
|
||||
{
|
||||
struct ip_set_req_ipporthash_create *mydata = data;
|
||||
|
||||
DP("create INIT");
|
||||
|
||||
/* Default create parameters */
|
||||
mydata->hashsize = IP_NF_SET_HASHSIZE;
|
||||
mydata->probes = 8;
|
||||
mydata->resize = 50;
|
||||
}
|
||||
|
||||
/* Function which parses command options; returns true if it ate an option */
|
||||
static int
|
||||
ipporthash_create_parse(int c, char *argv[] UNUSED, void *data,
|
||||
unsigned *flags)
|
||||
{
|
||||
struct ip_set_req_ipporthash_create *mydata = data;
|
||||
ip_set_ip_t value;
|
||||
|
||||
DP("create_parse");
|
||||
|
||||
switch (c) {
|
||||
case '1':
|
||||
|
||||
if (string_to_number(optarg, 1, UINT_MAX - 1, &mydata->hashsize))
|
||||
exit_error(PARAMETER_PROBLEM, "Invalid hashsize `%s' specified", optarg);
|
||||
|
||||
*flags |= OPT_CREATE_HASHSIZE;
|
||||
|
||||
DP("--hashsize %u", mydata->hashsize);
|
||||
|
||||
break;
|
||||
|
||||
case '2':
|
||||
|
||||
if (string_to_number(optarg, 1, 65535, &value))
|
||||
exit_error(PARAMETER_PROBLEM, "Invalid probes `%s' specified", optarg);
|
||||
|
||||
mydata->probes = value;
|
||||
*flags |= OPT_CREATE_PROBES;
|
||||
|
||||
DP("--probes %u", mydata->probes);
|
||||
|
||||
break;
|
||||
|
||||
case '3':
|
||||
|
||||
if (string_to_number(optarg, 0, 65535, &value))
|
||||
exit_error(PARAMETER_PROBLEM, "Invalid resize `%s' specified", optarg);
|
||||
|
||||
mydata->resize = value;
|
||||
*flags |= OPT_CREATE_RESIZE;
|
||||
|
||||
DP("--resize %u", mydata->resize);
|
||||
|
||||
break;
|
||||
|
||||
case '4':
|
||||
parse_ip(optarg, &mydata->from);
|
||||
|
||||
*flags |= OPT_CREATE_FROM;
|
||||
|
||||
DP("--from %x (%s)", mydata->from,
|
||||
ip_tostring_numeric(mydata->from));
|
||||
|
||||
break;
|
||||
|
||||
case '5':
|
||||
parse_ip(optarg, &mydata->to);
|
||||
|
||||
*flags |= OPT_CREATE_TO;
|
||||
|
||||
DP("--to %x (%s)", mydata->to,
|
||||
ip_tostring_numeric(mydata->to));
|
||||
|
||||
break;
|
||||
|
||||
case '6':
|
||||
parse_ipandmask(optarg, &mydata->from, &mydata->to);
|
||||
|
||||
/* Make to the last of from + mask */
|
||||
if (mydata->to)
|
||||
mydata->to = mydata->from | ~(mydata->to);
|
||||
else {
|
||||
mydata->from = 0x00000000;
|
||||
mydata->to = 0xFFFFFFFF;
|
||||
}
|
||||
*flags |= OPT_CREATE_NETWORK;
|
||||
|
||||
DP("--network from %x (%s)",
|
||||
mydata->from, ip_tostring_numeric(mydata->from));
|
||||
DP("--network to %x (%s)",
|
||||
mydata->to, ip_tostring_numeric(mydata->to));
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
static void
|
||||
ipporthash_create_final(void *data, unsigned int flags)
|
||||
{
|
||||
struct ip_set_req_ipporthash_create *mydata = data;
|
||||
|
||||
#ifdef IPSET_DEBUG
|
||||
DP("hashsize %u probes %u resize %u",
|
||||
mydata->hashsize, mydata->probes, mydata->resize);
|
||||
#endif
|
||||
|
||||
if (flags & OPT_CREATE_NETWORK) {
|
||||
/* --network */
|
||||
if ((flags & OPT_CREATE_FROM) || (flags & OPT_CREATE_TO))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Can't specify --from or --to with --network\n");
|
||||
} else if (flags & (OPT_CREATE_FROM | OPT_CREATE_TO)) {
|
||||
/* --from --to */
|
||||
if (!(flags & OPT_CREATE_FROM) || !(flags & OPT_CREATE_TO))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Need to specify both --from and --to\n");
|
||||
} else {
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Need to specify --from and --to, or --network\n");
|
||||
|
||||
}
|
||||
|
||||
DP("from : %x to: %x diff: %x",
|
||||
mydata->from, mydata->to,
|
||||
mydata->to - mydata->from);
|
||||
|
||||
if (mydata->from > mydata->to)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"From can't be higher than to.\n");
|
||||
|
||||
if (mydata->to - mydata->from > MAX_RANGE)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Range too large. Max is %d IPs in range\n",
|
||||
MAX_RANGE+1);
|
||||
}
|
||||
|
||||
/* Create commandline options */
|
||||
static const struct option create_opts[] = {
|
||||
{.name = "hashsize", .has_arg = required_argument, .val = '1'},
|
||||
{.name = "probes", .has_arg = required_argument, .val = '2'},
|
||||
{.name = "resize", .has_arg = required_argument, .val = '3'},
|
||||
{.name = "from", .has_arg = required_argument, .val = '4'},
|
||||
{.name = "to", .has_arg = required_argument, .val = '5'},
|
||||
{.name = "network", .has_arg = required_argument, .val = '6'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
/* Add, del, test parser */
|
||||
static ip_set_ip_t
|
||||
ipporthash_adt_parser(int cmd UNUSED, const char *arg, void *data)
|
||||
{
|
||||
struct ip_set_req_ipporthash *mydata = data;
|
||||
char *saved = ipset_strdup(arg);
|
||||
char *ptr, *tmp = saved;
|
||||
|
||||
DP("ipporthash: %p %p", arg, data);
|
||||
|
||||
if (((ptr = strchr(tmp, ':')) || (ptr = strchr(tmp, '%'))) && ++warn_once == 1)
|
||||
fprintf(stderr, "Warning: please use ',' separator token between ip,port.\n"
|
||||
"Next release won't support old separator tokens.\n");
|
||||
|
||||
ptr = strsep(&tmp, ":%,");
|
||||
parse_ip(ptr, &mydata->ip);
|
||||
|
||||
if (tmp)
|
||||
parse_port(tmp, &mydata->port);
|
||||
else
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"IP address and port must be specified: ip,port");
|
||||
|
||||
if (!(mydata->ip || mydata->port))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Zero valued IP address and port `%s' specified", arg);
|
||||
ipset_free(saved);
|
||||
return 1;
|
||||
};
|
||||
|
||||
/*
|
||||
* Print and save
|
||||
*/
|
||||
|
||||
static void
|
||||
ipporthash_initheader(struct set *set, const void *data)
|
||||
{
|
||||
const struct ip_set_req_ipporthash_create *header = data;
|
||||
struct ip_set_ipporthash *map = set->settype->header;
|
||||
|
||||
memset(map, 0, sizeof(struct ip_set_ipporthash));
|
||||
map->hashsize = header->hashsize;
|
||||
map->probes = header->probes;
|
||||
map->resize = header->resize;
|
||||
map->first_ip = header->from;
|
||||
map->last_ip = header->to;
|
||||
}
|
||||
|
||||
static void
|
||||
ipporthash_printheader(struct set *set, unsigned options)
|
||||
{
|
||||
struct ip_set_ipporthash *mysetdata = set->settype->header;
|
||||
|
||||
printf(" from: %s", ip_tostring(mysetdata->first_ip, options));
|
||||
printf(" to: %s", ip_tostring(mysetdata->last_ip, options));
|
||||
printf(" hashsize: %u", mysetdata->hashsize);
|
||||
printf(" probes: %u", mysetdata->probes);
|
||||
printf(" resize: %u\n", mysetdata->resize);
|
||||
}
|
||||
|
||||
static void
|
||||
ipporthash_printips(struct set *set, void *data, u_int32_t len,
|
||||
unsigned options, char dont_align)
|
||||
{
|
||||
struct ip_set_ipporthash *mysetdata = set->settype->header;
|
||||
size_t offset = 0;
|
||||
ip_set_ip_t *ipptr, ip;
|
||||
uint16_t port;
|
||||
|
||||
while (offset < len) {
|
||||
ipptr = data + offset;
|
||||
ip = (*ipptr>>16) + mysetdata->first_ip;
|
||||
port = (uint16_t) *ipptr;
|
||||
printf("%s,%s\n",
|
||||
ip_tostring(ip, options),
|
||||
port_tostring(port, options));
|
||||
offset += IPSET_VALIGN(sizeof(ip_set_ip_t), dont_align);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ipporthash_saveheader(struct set *set, unsigned options)
|
||||
{
|
||||
struct ip_set_ipporthash *mysetdata = set->settype->header;
|
||||
|
||||
printf("-N %s %s --from %s",
|
||||
set->name, set->settype->typename,
|
||||
ip_tostring(mysetdata->first_ip, options));
|
||||
printf(" --to %s",
|
||||
ip_tostring(mysetdata->last_ip, options));
|
||||
printf(" --hashsize %u --probes %u --resize %u\n",
|
||||
mysetdata->hashsize, mysetdata->probes, mysetdata->resize);
|
||||
}
|
||||
|
||||
/* Print save for an IP */
|
||||
static void
|
||||
ipporthash_saveips(struct set *set, void *data, u_int32_t len,
|
||||
unsigned options, char dont_align)
|
||||
{
|
||||
struct ip_set_ipporthash *mysetdata = set->settype->header;
|
||||
size_t offset = 0;
|
||||
ip_set_ip_t *ipptr, ip;
|
||||
uint16_t port;
|
||||
|
||||
while (offset < len) {
|
||||
ipptr = data + offset;
|
||||
ip = (*ipptr>>16) + mysetdata->first_ip;
|
||||
port = (uint16_t) *ipptr;
|
||||
printf("-A %s %s,%s\n", set->name,
|
||||
ip_tostring(ip, options),
|
||||
port_tostring(port, options));
|
||||
offset += IPSET_VALIGN(sizeof(ip_set_ip_t), dont_align);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ipporthash_usage(void)
|
||||
{
|
||||
printf
|
||||
("-N set ipporthash --from IP --to IP\n"
|
||||
" [--hashsize hashsize] [--probes probes ] [--resize resize]\n"
|
||||
"-N set ipporthash --network IP/mask\n"
|
||||
" [--hashsize hashsize] [--probes probes ] [--resize resize]\n"
|
||||
"-A set IP,port\n"
|
||||
"-D set IP,port\n"
|
||||
"-T set IP,port\n");
|
||||
}
|
||||
|
||||
static struct settype settype_ipporthash = {
|
||||
.typename = SETTYPE_NAME,
|
||||
.protocol_version = IP_SET_PROTOCOL_VERSION,
|
||||
|
||||
/* Create */
|
||||
.create_size = sizeof(struct ip_set_req_ipporthash_create),
|
||||
.create_init = ipporthash_create_init,
|
||||
.create_parse = ipporthash_create_parse,
|
||||
.create_final = ipporthash_create_final,
|
||||
.create_opts = create_opts,
|
||||
|
||||
/* Add/del/test */
|
||||
.adt_size = sizeof(struct ip_set_req_ipporthash),
|
||||
.adt_parser = ipporthash_adt_parser,
|
||||
|
||||
/* Printing */
|
||||
.header_size = sizeof(struct ip_set_ipporthash),
|
||||
.initheader = ipporthash_initheader,
|
||||
.printheader = ipporthash_printheader,
|
||||
.printips = ipporthash_printips,
|
||||
.printips_sorted = ipporthash_printips,
|
||||
.saveheader = ipporthash_saveheader,
|
||||
.saveips = ipporthash_saveips,
|
||||
|
||||
.usage = ipporthash_usage,
|
||||
};
|
||||
|
||||
CONSTRUCTOR(ipporthash)
|
||||
{
|
||||
settype_register(&settype_ipporthash);
|
||||
|
||||
}
|
||||
@@ -1,361 +0,0 @@
|
||||
/* Copyright 2008 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <limits.h> /* UINT_MAX */
|
||||
#include <stdio.h> /* *printf */
|
||||
#include <string.h> /* mem*, str* */
|
||||
|
||||
#include "ipset.h"
|
||||
|
||||
#include "ip_set_ipportiphash.h"
|
||||
|
||||
#define OPT_CREATE_HASHSIZE 0x01U
|
||||
#define OPT_CREATE_PROBES 0x02U
|
||||
#define OPT_CREATE_RESIZE 0x04U
|
||||
#define OPT_CREATE_NETWORK 0x08U
|
||||
#define OPT_CREATE_FROM 0x10U
|
||||
#define OPT_CREATE_TO 0x20U
|
||||
|
||||
/* Initialize the create. */
|
||||
static void
|
||||
ipportiphash_create_init(void *data)
|
||||
{
|
||||
struct ip_set_req_ipportiphash_create *mydata = data;
|
||||
|
||||
DP("create INIT");
|
||||
|
||||
/* Default create parameters */
|
||||
mydata->hashsize = IP_NF_SET_HASHSIZE;
|
||||
mydata->probes = 8;
|
||||
mydata->resize = 50;
|
||||
}
|
||||
|
||||
/* Function which parses command options; returns true if it ate an option */
|
||||
static int
|
||||
ipportiphash_create_parse(int c, char *argv[] UNUSED, void *data,
|
||||
unsigned *flags)
|
||||
{
|
||||
struct ip_set_req_ipportiphash_create *mydata = data;
|
||||
ip_set_ip_t value;
|
||||
|
||||
DP("create_parse");
|
||||
|
||||
switch (c) {
|
||||
case '1':
|
||||
|
||||
if (string_to_number(optarg, 1, UINT_MAX - 1, &mydata->hashsize))
|
||||
exit_error(PARAMETER_PROBLEM, "Invalid hashsize `%s' specified", optarg);
|
||||
|
||||
*flags |= OPT_CREATE_HASHSIZE;
|
||||
|
||||
DP("--hashsize %u", mydata->hashsize);
|
||||
|
||||
break;
|
||||
|
||||
case '2':
|
||||
|
||||
if (string_to_number(optarg, 1, 65535, &value))
|
||||
exit_error(PARAMETER_PROBLEM, "Invalid probes `%s' specified", optarg);
|
||||
|
||||
mydata->probes = value;
|
||||
*flags |= OPT_CREATE_PROBES;
|
||||
|
||||
DP("--probes %u", mydata->probes);
|
||||
|
||||
break;
|
||||
|
||||
case '3':
|
||||
|
||||
if (string_to_number(optarg, 0, 65535, &value))
|
||||
exit_error(PARAMETER_PROBLEM, "Invalid resize `%s' specified", optarg);
|
||||
|
||||
mydata->resize = value;
|
||||
*flags |= OPT_CREATE_RESIZE;
|
||||
|
||||
DP("--resize %u", mydata->resize);
|
||||
|
||||
break;
|
||||
|
||||
case '4':
|
||||
parse_ip(optarg, &mydata->from);
|
||||
|
||||
*flags |= OPT_CREATE_FROM;
|
||||
|
||||
DP("--from %x (%s)", mydata->from,
|
||||
ip_tostring_numeric(mydata->from));
|
||||
|
||||
break;
|
||||
|
||||
case '5':
|
||||
parse_ip(optarg, &mydata->to);
|
||||
|
||||
*flags |= OPT_CREATE_TO;
|
||||
|
||||
DP("--to %x (%s)", mydata->to,
|
||||
ip_tostring_numeric(mydata->to));
|
||||
|
||||
break;
|
||||
|
||||
case '6':
|
||||
parse_ipandmask(optarg, &mydata->from, &mydata->to);
|
||||
|
||||
/* Make to the last of from + mask */
|
||||
if (mydata->to)
|
||||
mydata->to = mydata->from | ~(mydata->to);
|
||||
else {
|
||||
mydata->from = 0x00000000;
|
||||
mydata->to = 0xFFFFFFFF;
|
||||
}
|
||||
*flags |= OPT_CREATE_NETWORK;
|
||||
|
||||
DP("--network from %x (%s)",
|
||||
mydata->from, ip_tostring_numeric(mydata->from));
|
||||
DP("--network to %x (%s)",
|
||||
mydata->to, ip_tostring_numeric(mydata->to));
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
static void
|
||||
ipportiphash_create_final(void *data, unsigned int flags)
|
||||
{
|
||||
struct ip_set_req_ipportiphash_create *mydata = data;
|
||||
|
||||
#ifdef IPSET_DEBUG
|
||||
DP("hashsize %u probes %u resize %u",
|
||||
mydata->hashsize, mydata->probes, mydata->resize);
|
||||
#endif
|
||||
|
||||
if (flags & OPT_CREATE_NETWORK) {
|
||||
/* --network */
|
||||
if ((flags & OPT_CREATE_FROM) || (flags & OPT_CREATE_TO))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Can't specify --from or --to with --network\n");
|
||||
} else if (flags & (OPT_CREATE_FROM | OPT_CREATE_TO)) {
|
||||
/* --from --to */
|
||||
if (!(flags & OPT_CREATE_FROM) || !(flags & OPT_CREATE_TO))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Need to specify both --from and --to\n");
|
||||
} else {
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Need to specify --from and --to, or --network\n");
|
||||
|
||||
}
|
||||
|
||||
DP("from : %x to: %x diff: %x",
|
||||
mydata->from, mydata->to,
|
||||
mydata->to - mydata->from);
|
||||
|
||||
if (mydata->from > mydata->to)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"From can't be higher than to.\n");
|
||||
|
||||
if (mydata->to - mydata->from > MAX_RANGE)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Range too large. Max is %d IPs in range\n",
|
||||
MAX_RANGE+1);
|
||||
}
|
||||
|
||||
/* Create commandline options */
|
||||
static const struct option create_opts[] = {
|
||||
{.name = "hashsize", .has_arg = required_argument, .val = '1'},
|
||||
{.name = "probes", .has_arg = required_argument, .val = '2'},
|
||||
{.name = "resize", .has_arg = required_argument, .val = '3'},
|
||||
{.name = "from", .has_arg = required_argument, .val = '4'},
|
||||
{.name = "to", .has_arg = required_argument, .val = '5'},
|
||||
{.name = "network", .has_arg = required_argument, .val = '6'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
/* Add, del, test parser */
|
||||
static ip_set_ip_t
|
||||
ipportiphash_adt_parser(int cmd UNUSED, const char *arg, void *data)
|
||||
{
|
||||
struct ip_set_req_ipportiphash *mydata = data;
|
||||
char *saved = ipset_strdup(arg);
|
||||
char *ptr, *tmp = saved;
|
||||
|
||||
DP("ipportiphash: %p %p", arg, data);
|
||||
|
||||
if (((ptr = strchr(tmp, ':')) || (ptr = strchr(tmp, '%'))) && ++warn_once == 1)
|
||||
fprintf(stderr, "Warning: please use ',' separator token between ip,port,ip.\n"
|
||||
"Next release won't support old separator tokens.\n");
|
||||
|
||||
ptr = strsep(&tmp, ":%,");
|
||||
parse_ip(ptr, &mydata->ip);
|
||||
|
||||
if (!tmp)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"IP address, port and IP address must be specified: ip,port,ip");
|
||||
|
||||
ptr = strsep(&tmp, ":%,");
|
||||
parse_port(ptr, &mydata->port);
|
||||
if (tmp)
|
||||
parse_ip(tmp, &mydata->ip1);
|
||||
else
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"IP address, port and IP address must be specified: ip,port,ip");
|
||||
if (!(mydata->ip || mydata->port || mydata->ip1))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Zero valued IP address, port and IP address `%s' specified", arg);
|
||||
ipset_free(saved);
|
||||
return 1;
|
||||
};
|
||||
|
||||
/*
|
||||
* Print and save
|
||||
*/
|
||||
|
||||
static void
|
||||
ipportiphash_initheader(struct set *set, const void *data)
|
||||
{
|
||||
const struct ip_set_req_ipportiphash_create *header = data;
|
||||
struct ip_set_ipportiphash *map = set->settype->header;
|
||||
|
||||
memset(map, 0, sizeof(struct ip_set_ipportiphash));
|
||||
map->hashsize = header->hashsize;
|
||||
map->probes = header->probes;
|
||||
map->resize = header->resize;
|
||||
map->first_ip = header->from;
|
||||
map->last_ip = header->to;
|
||||
}
|
||||
|
||||
static void
|
||||
ipportiphash_printheader(struct set *set, unsigned options)
|
||||
{
|
||||
struct ip_set_ipportiphash *mysetdata = set->settype->header;
|
||||
|
||||
printf(" from: %s", ip_tostring(mysetdata->first_ip, options));
|
||||
printf(" to: %s", ip_tostring(mysetdata->last_ip, options));
|
||||
printf(" hashsize: %u", mysetdata->hashsize);
|
||||
printf(" probes: %u", mysetdata->probes);
|
||||
printf(" resize: %u\n", mysetdata->resize);
|
||||
}
|
||||
|
||||
static void
|
||||
ipportiphash_printips(struct set *set, void *data, u_int32_t len,
|
||||
unsigned options, char dont_align)
|
||||
{
|
||||
struct ip_set_ipportiphash *mysetdata = set->settype->header;
|
||||
size_t offset = 0;
|
||||
struct ipportip *ipptr;
|
||||
ip_set_ip_t ip;
|
||||
uint16_t port;
|
||||
|
||||
while (offset < len) {
|
||||
ipptr = data + offset;
|
||||
ip = (ipptr->ip>>16) + mysetdata->first_ip;
|
||||
port = (uint16_t) ipptr->ip;
|
||||
printf("%s,%s,",
|
||||
ip_tostring(ip, options),
|
||||
port_tostring(port, options));
|
||||
printf("%s\n",
|
||||
ip_tostring(ipptr->ip1, options));
|
||||
offset += IPSET_VALIGN(sizeof(struct ipportip), dont_align);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ipportiphash_saveheader(struct set *set, unsigned options)
|
||||
{
|
||||
struct ip_set_ipportiphash *mysetdata = set->settype->header;
|
||||
|
||||
printf("-N %s %s --from %s",
|
||||
set->name, set->settype->typename,
|
||||
ip_tostring(mysetdata->first_ip, options));
|
||||
printf(" --to %s",
|
||||
ip_tostring(mysetdata->last_ip, options));
|
||||
printf(" --hashsize %u --probes %u --resize %u\n",
|
||||
mysetdata->hashsize, mysetdata->probes, mysetdata->resize);
|
||||
}
|
||||
|
||||
/* Print save for an IP */
|
||||
static void
|
||||
ipportiphash_saveips(struct set *set, void *data, u_int32_t len,
|
||||
unsigned options, char dont_align)
|
||||
{
|
||||
struct ip_set_ipportiphash *mysetdata = set->settype->header;
|
||||
size_t offset = 0;
|
||||
struct ipportip *ipptr;
|
||||
ip_set_ip_t ip;
|
||||
uint16_t port;
|
||||
|
||||
while (offset < len) {
|
||||
ipptr = data + offset;
|
||||
ip = (ipptr->ip>>16) + mysetdata->first_ip;
|
||||
port = (uint16_t) ipptr->ip;
|
||||
printf("-A %s %s,%s,", set->name,
|
||||
ip_tostring(ip, options),
|
||||
port_tostring(port, options));
|
||||
printf("%s\n",
|
||||
ip_tostring(ipptr->ip1, options));
|
||||
offset += IPSET_VALIGN(sizeof(struct ipportip), dont_align);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ipportiphash_usage(void)
|
||||
{
|
||||
printf
|
||||
("-N set ipportiphash --from IP --to IP\n"
|
||||
" [--hashsize hashsize] [--probes probes ] [--resize resize]\n"
|
||||
"-N set ipportiphash --network IP/mask\n"
|
||||
" [--hashsize hashsize] [--probes probes ] [--resize resize]\n"
|
||||
"-A set IP,port,IP\n"
|
||||
"-D set IP,port,IP\n"
|
||||
"-T set IP,port,IP\n");
|
||||
}
|
||||
|
||||
static struct settype settype_ipportiphash = {
|
||||
.typename = SETTYPE_NAME,
|
||||
.protocol_version = IP_SET_PROTOCOL_VERSION,
|
||||
|
||||
/* Create */
|
||||
.create_size = sizeof(struct ip_set_req_ipportiphash_create),
|
||||
.create_init = ipportiphash_create_init,
|
||||
.create_parse = ipportiphash_create_parse,
|
||||
.create_final = ipportiphash_create_final,
|
||||
.create_opts = create_opts,
|
||||
|
||||
/* Add/del/test */
|
||||
.adt_size = sizeof(struct ip_set_req_ipportiphash),
|
||||
.adt_parser = ipportiphash_adt_parser,
|
||||
|
||||
/* Printing */
|
||||
.header_size = sizeof(struct ip_set_ipportiphash),
|
||||
.initheader = ipportiphash_initheader,
|
||||
.printheader = ipportiphash_printheader,
|
||||
.printips = ipportiphash_printips,
|
||||
.printips_sorted = ipportiphash_printips,
|
||||
.saveheader = ipportiphash_saveheader,
|
||||
.saveips = ipportiphash_saveips,
|
||||
|
||||
.usage = ipportiphash_usage,
|
||||
};
|
||||
|
||||
CONSTRUCTOR(ipportiphash)
|
||||
{
|
||||
settype_register(&settype_ipportiphash);
|
||||
|
||||
}
|
||||
@@ -1,426 +0,0 @@
|
||||
/* Copyright 2008 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <limits.h> /* UINT_MAX */
|
||||
#include <stdio.h> /* *printf */
|
||||
#include <string.h> /* mem*, str* */
|
||||
|
||||
#include "ipset.h"
|
||||
|
||||
#include "ip_set_ipportnethash.h"
|
||||
|
||||
#define OPT_CREATE_HASHSIZE 0x01U
|
||||
#define OPT_CREATE_PROBES 0x02U
|
||||
#define OPT_CREATE_RESIZE 0x04U
|
||||
#define OPT_CREATE_NETWORK 0x08U
|
||||
#define OPT_CREATE_FROM 0x10U
|
||||
#define OPT_CREATE_TO 0x20U
|
||||
|
||||
/* Initialize the create. */
|
||||
static void
|
||||
ipportnethash_create_init(void *data)
|
||||
{
|
||||
struct ip_set_req_ipportnethash_create *mydata = data;
|
||||
|
||||
DP("create INIT");
|
||||
|
||||
/* Default create parameters */
|
||||
mydata->hashsize = IP_NF_SET_HASHSIZE;
|
||||
mydata->probes = 8;
|
||||
mydata->resize = 50;
|
||||
}
|
||||
|
||||
/* Function which parses command options; returns true if it ate an option */
|
||||
static int
|
||||
ipportnethash_create_parse(int c, char *argv[] UNUSED, void *data,
|
||||
unsigned *flags)
|
||||
{
|
||||
struct ip_set_req_ipportnethash_create *mydata = data;
|
||||
ip_set_ip_t value;
|
||||
|
||||
DP("create_parse");
|
||||
|
||||
switch (c) {
|
||||
case '1':
|
||||
|
||||
if (string_to_number(optarg, 1, UINT_MAX - 1, &mydata->hashsize))
|
||||
exit_error(PARAMETER_PROBLEM, "Invalid hashsize `%s' specified", optarg);
|
||||
|
||||
*flags |= OPT_CREATE_HASHSIZE;
|
||||
|
||||
DP("--hashsize %u", mydata->hashsize);
|
||||
|
||||
break;
|
||||
|
||||
case '2':
|
||||
|
||||
if (string_to_number(optarg, 1, 65535, &value))
|
||||
exit_error(PARAMETER_PROBLEM, "Invalid probes `%s' specified", optarg);
|
||||
|
||||
mydata->probes = value;
|
||||
*flags |= OPT_CREATE_PROBES;
|
||||
|
||||
DP("--probes %u", mydata->probes);
|
||||
|
||||
break;
|
||||
|
||||
case '3':
|
||||
|
||||
if (string_to_number(optarg, 0, 65535, &value))
|
||||
exit_error(PARAMETER_PROBLEM, "Invalid resize `%s' specified", optarg);
|
||||
|
||||
mydata->resize = value;
|
||||
*flags |= OPT_CREATE_RESIZE;
|
||||
|
||||
DP("--resize %u", mydata->resize);
|
||||
|
||||
break;
|
||||
|
||||
case '4':
|
||||
parse_ip(optarg, &mydata->from);
|
||||
|
||||
*flags |= OPT_CREATE_FROM;
|
||||
|
||||
DP("--from %x (%s)", mydata->from,
|
||||
ip_tostring_numeric(mydata->from));
|
||||
|
||||
break;
|
||||
|
||||
case '5':
|
||||
parse_ip(optarg, &mydata->to);
|
||||
|
||||
*flags |= OPT_CREATE_TO;
|
||||
|
||||
DP("--to %x (%s)", mydata->to,
|
||||
ip_tostring_numeric(mydata->to));
|
||||
|
||||
break;
|
||||
|
||||
case '6':
|
||||
parse_ipandmask(optarg, &mydata->from, &mydata->to);
|
||||
|
||||
/* Make to the last of from + mask */
|
||||
if (mydata->to)
|
||||
mydata->to = mydata->from | ~(mydata->to);
|
||||
else {
|
||||
mydata->from = 0x00000000;
|
||||
mydata->to = 0xFFFFFFFF;
|
||||
}
|
||||
*flags |= OPT_CREATE_NETWORK;
|
||||
|
||||
DP("--network from %x (%s)",
|
||||
mydata->from, ip_tostring_numeric(mydata->from));
|
||||
DP("--network to %x (%s)",
|
||||
mydata->to, ip_tostring_numeric(mydata->to));
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
static void
|
||||
ipportnethash_create_final(void *data, unsigned int flags)
|
||||
{
|
||||
struct ip_set_req_ipportnethash_create *mydata = data;
|
||||
|
||||
#ifdef IPSET_DEBUG
|
||||
DP("hashsize %u probes %u resize %u",
|
||||
mydata->hashsize, mydata->probes, mydata->resize);
|
||||
#endif
|
||||
|
||||
if (flags & OPT_CREATE_NETWORK) {
|
||||
/* --network */
|
||||
if ((flags & OPT_CREATE_FROM) || (flags & OPT_CREATE_TO))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Can't specify --from or --to with --network\n");
|
||||
} else if (flags & (OPT_CREATE_FROM | OPT_CREATE_TO)) {
|
||||
/* --from --to */
|
||||
if (!(flags & OPT_CREATE_FROM) || !(flags & OPT_CREATE_TO))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Need to specify both --from and --to\n");
|
||||
} else {
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Need to specify --from and --to, or --network\n");
|
||||
|
||||
}
|
||||
|
||||
DP("from : %x to: %x diff: %x",
|
||||
mydata->from, mydata->to,
|
||||
mydata->to - mydata->from);
|
||||
|
||||
if (mydata->from > mydata->to)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"From can't be higher than to.\n");
|
||||
|
||||
if (mydata->to - mydata->from > MAX_RANGE)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Range too large. Max is %d IPs in range\n",
|
||||
MAX_RANGE+1);
|
||||
}
|
||||
|
||||
/* Create commandline options */
|
||||
static const struct option create_opts[] = {
|
||||
{.name = "hashsize", .has_arg = required_argument, .val = '1'},
|
||||
{.name = "probes", .has_arg = required_argument, .val = '2'},
|
||||
{.name = "resize", .has_arg = required_argument, .val = '3'},
|
||||
{.name = "from", .has_arg = required_argument, .val = '4'},
|
||||
{.name = "to", .has_arg = required_argument, .val = '5'},
|
||||
{.name = "network", .has_arg = required_argument, .val = '6'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
/* Add, del, test parser */
|
||||
static ip_set_ip_t
|
||||
ipportnethash_adt_parser(int cmd, const char *arg, void *data)
|
||||
{
|
||||
struct ip_set_req_ipportnethash *mydata = data;
|
||||
char *saved = ipset_strdup(arg);
|
||||
char *ptr, *tmp = saved;
|
||||
ip_set_ip_t cidr;
|
||||
|
||||
DP("ipportnethash: %p %p", arg, data);
|
||||
|
||||
if (((ptr = strchr(tmp, ':')) || (ptr = strchr(tmp, '%'))) && ++warn_once == 1)
|
||||
fprintf(stderr, "Warning: please use ',' separator token between ip,port,net.\n"
|
||||
"Next release won't support old separator tokens.\n");
|
||||
|
||||
ptr = strsep(&tmp, ":%,");
|
||||
parse_ip(ptr, &mydata->ip);
|
||||
if (!tmp)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"IP address, port and network address must be specified: ip,port,net");
|
||||
|
||||
ptr = strsep(&tmp, ":%,");
|
||||
parse_port(ptr, &mydata->port);
|
||||
if (!tmp)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"IP address, port and network address must be specified: ip,port,net");
|
||||
|
||||
ptr = strsep(&tmp, "/");
|
||||
if (tmp == NULL)
|
||||
if (cmd == CMD_TEST)
|
||||
cidr = 32;
|
||||
else
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Missing /cidr from `%s'", arg);
|
||||
else
|
||||
if (string_to_number(tmp, 1, 31, &cidr))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Out of range cidr `%s' specified", arg);
|
||||
|
||||
mydata->cidr = cidr;
|
||||
|
||||
parse_ip(ptr, &mydata->ip1);
|
||||
ipset_free(saved);
|
||||
return 1;
|
||||
};
|
||||
|
||||
/*
|
||||
* Print and save
|
||||
*/
|
||||
|
||||
static void
|
||||
ipportnethash_initheader(struct set *set, const void *data)
|
||||
{
|
||||
const struct ip_set_req_ipportnethash_create *header = data;
|
||||
struct ip_set_ipportnethash *map = set->settype->header;
|
||||
|
||||
memset(map, 0, sizeof(struct ip_set_ipportnethash));
|
||||
map->hashsize = header->hashsize;
|
||||
map->probes = header->probes;
|
||||
map->resize = header->resize;
|
||||
map->first_ip = header->from;
|
||||
map->last_ip = header->to;
|
||||
}
|
||||
|
||||
static void
|
||||
ipportnethash_printheader(struct set *set, unsigned options)
|
||||
{
|
||||
struct ip_set_ipportnethash *mysetdata = set->settype->header;
|
||||
|
||||
printf(" from: %s", ip_tostring(mysetdata->first_ip, options));
|
||||
printf(" to: %s", ip_tostring(mysetdata->last_ip, options));
|
||||
printf(" hashsize: %u", mysetdata->hashsize);
|
||||
printf(" probes: %u", mysetdata->probes);
|
||||
printf(" resize: %u\n", mysetdata->resize);
|
||||
}
|
||||
|
||||
static char buf[20];
|
||||
|
||||
static char *
|
||||
unpack_ip_tostring(ip_set_ip_t ip, unsigned options UNUSED)
|
||||
{
|
||||
int i, j = 3;
|
||||
unsigned char a, b;
|
||||
|
||||
ip = htonl(ip);
|
||||
for (i = 3; i >= 0; i--)
|
||||
if (((unsigned char *)&ip)[i] != 0) {
|
||||
j = i;
|
||||
break;
|
||||
}
|
||||
|
||||
a = ((unsigned char *)&ip)[j];
|
||||
if (a <= 128) {
|
||||
a = (a - 1) * 2;
|
||||
b = 7;
|
||||
} else if (a <= 192) {
|
||||
a = (a - 129) * 4;
|
||||
b = 6;
|
||||
} else if (a <= 224) {
|
||||
a = (a - 193) * 8;
|
||||
b = 5;
|
||||
} else if (a <= 240) {
|
||||
a = (a - 225) * 16;
|
||||
b = 4;
|
||||
} else if (a <= 248) {
|
||||
a = (a - 241) * 32;
|
||||
b = 3;
|
||||
} else if (a <= 252) {
|
||||
a = (a - 249) * 64;
|
||||
b = 2;
|
||||
} else if (a <= 254) {
|
||||
a = (a - 253) * 128;
|
||||
b = 1;
|
||||
} else {
|
||||
a = b = 0;
|
||||
}
|
||||
((unsigned char *)&ip)[j] = a;
|
||||
b += j * 8;
|
||||
|
||||
sprintf(buf, "%u.%u.%u.%u/%u",
|
||||
((unsigned char *)&ip)[0],
|
||||
((unsigned char *)&ip)[1],
|
||||
((unsigned char *)&ip)[2],
|
||||
((unsigned char *)&ip)[3],
|
||||
b);
|
||||
|
||||
DP("%s %s", ip_tostring(ntohl(ip), 0), buf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void
|
||||
ipportnethash_printips(struct set *set, void *data, u_int32_t len,
|
||||
unsigned options, char dont_align)
|
||||
{
|
||||
struct ip_set_ipportnethash *mysetdata = set->settype->header;
|
||||
size_t offset = 0;
|
||||
struct ipportip *ipptr;
|
||||
ip_set_ip_t ip;
|
||||
uint16_t port;
|
||||
|
||||
while (offset < len) {
|
||||
ipptr = data + offset;
|
||||
ip = (ipptr->ip>>16) + mysetdata->first_ip;
|
||||
port = (uint16_t) ipptr->ip;
|
||||
printf("%s,%s,",
|
||||
ip_tostring(ip, options),
|
||||
port_tostring(port, options));
|
||||
printf("%s\n",
|
||||
unpack_ip_tostring(ipptr->ip1, options));
|
||||
offset += IPSET_VALIGN(sizeof(struct ipportip), dont_align);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ipportnethash_saveheader(struct set *set, unsigned options)
|
||||
{
|
||||
struct ip_set_ipportnethash *mysetdata = set->settype->header;
|
||||
|
||||
printf("-N %s %s --from %s",
|
||||
set->name, set->settype->typename,
|
||||
ip_tostring(mysetdata->first_ip, options));
|
||||
printf(" --to %s",
|
||||
ip_tostring(mysetdata->last_ip, options));
|
||||
printf(" --hashsize %u --probes %u --resize %u\n",
|
||||
mysetdata->hashsize, mysetdata->probes, mysetdata->resize);
|
||||
}
|
||||
|
||||
/* Print save for an IP */
|
||||
static void
|
||||
ipportnethash_saveips(struct set *set, void *data, u_int32_t len,
|
||||
unsigned options, char dont_align)
|
||||
{
|
||||
struct ip_set_ipportnethash *mysetdata = set->settype->header;
|
||||
size_t offset = 0;
|
||||
struct ipportip *ipptr;
|
||||
ip_set_ip_t ip;
|
||||
uint16_t port;
|
||||
|
||||
while (offset < len) {
|
||||
ipptr = data + offset;
|
||||
ip = (ipptr->ip>>16) + mysetdata->first_ip;
|
||||
port = (uint16_t) ipptr->ip;
|
||||
printf("-A %s %s,%s,", set->name,
|
||||
ip_tostring(ip, options),
|
||||
port_tostring(port, options));
|
||||
printf("%s\n",
|
||||
unpack_ip_tostring(ipptr->ip, options));
|
||||
offset += IPSET_VALIGN(sizeof(struct ipportip), dont_align);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ipportnethash_usage(void)
|
||||
{
|
||||
printf
|
||||
("-N set ipportnethash --from IP --to IP\n"
|
||||
" [--hashsize hashsize] [--probes probes ] [--resize resize]\n"
|
||||
"-N set ipportnethash --network IP/mask\n"
|
||||
" [--hashsize hashsize] [--probes probes ] [--resize resize]\n"
|
||||
"-A set IP,port,IP/net\n"
|
||||
"-D set IP,port,IP/net\n"
|
||||
"-T set IP,port,IP[/net]\n");
|
||||
}
|
||||
|
||||
static struct settype settype_ipportnethash = {
|
||||
.typename = SETTYPE_NAME,
|
||||
.protocol_version = IP_SET_PROTOCOL_VERSION,
|
||||
|
||||
/* Create */
|
||||
.create_size = sizeof(struct ip_set_req_ipportnethash_create),
|
||||
.create_init = ipportnethash_create_init,
|
||||
.create_parse = ipportnethash_create_parse,
|
||||
.create_final = ipportnethash_create_final,
|
||||
.create_opts = create_opts,
|
||||
|
||||
/* Add/del/test */
|
||||
.adt_size = sizeof(struct ip_set_req_ipportnethash),
|
||||
.adt_parser = ipportnethash_adt_parser,
|
||||
|
||||
/* Printing */
|
||||
.header_size = sizeof(struct ip_set_ipportnethash),
|
||||
.initheader = ipportnethash_initheader,
|
||||
.printheader = ipportnethash_printheader,
|
||||
.printips = ipportnethash_printips,
|
||||
.printips_sorted = ipportnethash_printips,
|
||||
.saveheader = ipportnethash_saveheader,
|
||||
.saveips = ipportnethash_saveips,
|
||||
|
||||
.usage = ipportnethash_usage,
|
||||
};
|
||||
|
||||
CONSTRUCTOR(ipportnethash)
|
||||
{
|
||||
settype_register(&settype_ipportnethash);
|
||||
|
||||
}
|
||||
@@ -1,224 +0,0 @@
|
||||
/* Copyright 2005 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <limits.h> /* UINT_MAX */
|
||||
#include <stdio.h> /* *printf */
|
||||
#include <string.h> /* mem* */
|
||||
|
||||
#include "ipset.h"
|
||||
|
||||
#include "ip_set_iptree.h"
|
||||
|
||||
#define BUFLEN 30;
|
||||
|
||||
#define OPT_CREATE_TIMEOUT 0x01U
|
||||
|
||||
/* Initialize the create. */
|
||||
static void
|
||||
iptree_create_init(void *data)
|
||||
{
|
||||
struct ip_set_req_iptree_create *mydata = data;
|
||||
|
||||
DP("create INIT");
|
||||
mydata->timeout = 0;
|
||||
}
|
||||
|
||||
/* Function which parses command options; returns true if it ate an option */
|
||||
static int
|
||||
iptree_create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags)
|
||||
{
|
||||
struct ip_set_req_iptree_create *mydata = data;
|
||||
|
||||
DP("create_parse");
|
||||
|
||||
switch (c) {
|
||||
case '1':
|
||||
string_to_number(optarg, 0, UINT_MAX, &mydata->timeout);
|
||||
|
||||
*flags |= OPT_CREATE_TIMEOUT;
|
||||
|
||||
DP("--timeout %u", mydata->timeout);
|
||||
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
static void
|
||||
iptree_create_final(void *data UNUSED, unsigned int flags UNUSED)
|
||||
{
|
||||
}
|
||||
|
||||
/* Create commandline options */
|
||||
static const struct option create_opts[] = {
|
||||
{.name = "timeout", .has_arg = required_argument, .val = '1'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
/* Add, del, test parser */
|
||||
static ip_set_ip_t
|
||||
iptree_adt_parser(int cmd UNUSED, const char *arg, void *data)
|
||||
{
|
||||
struct ip_set_req_iptree *mydata = data;
|
||||
char *saved = ipset_strdup(arg);
|
||||
char *ptr, *tmp = saved;
|
||||
|
||||
DP("iptree: %p %p", arg, data);
|
||||
|
||||
if (((ptr = strchr(tmp, ':')) || (ptr = strchr(tmp, '%'))) && ++warn_once == 1)
|
||||
fprintf(stderr, "Warning: please use ',' separator token between ip,timeout.\n"
|
||||
"Next release won't support old separator tokens.\n");
|
||||
|
||||
ptr = strsep(&tmp, ":%,");
|
||||
parse_ip(ptr, &mydata->ip);
|
||||
|
||||
if (tmp)
|
||||
string_to_number(tmp, 0, UINT_MAX, &mydata->timeout);
|
||||
else
|
||||
mydata->timeout = 0;
|
||||
|
||||
ipset_free(saved);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Print and save
|
||||
*/
|
||||
|
||||
static void
|
||||
iptree_initheader(struct set *set, const void *data)
|
||||
{
|
||||
const struct ip_set_req_iptree_create *header = data;
|
||||
struct ip_set_iptree *map = set->settype->header;
|
||||
|
||||
map->timeout = header->timeout;
|
||||
}
|
||||
|
||||
static void
|
||||
iptree_printheader(struct set *set, unsigned options UNUSED)
|
||||
{
|
||||
struct ip_set_iptree *mysetdata = set->settype->header;
|
||||
|
||||
if (mysetdata->timeout)
|
||||
printf(" timeout: %u", mysetdata->timeout);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void
|
||||
iptree_printips_sorted(struct set *set, void *data, u_int32_t len,
|
||||
unsigned options, char dont_align)
|
||||
{
|
||||
struct ip_set_iptree *mysetdata = set->settype->header;
|
||||
struct ip_set_req_iptree *req;
|
||||
size_t offset = 0;
|
||||
|
||||
while (len >= offset + sizeof(struct ip_set_req_iptree)) {
|
||||
req = (struct ip_set_req_iptree *)(data + offset);
|
||||
if (mysetdata->timeout)
|
||||
printf("%s,%u\n", ip_tostring(req->ip, options),
|
||||
req->timeout);
|
||||
else
|
||||
printf("%s\n", ip_tostring(req->ip, options));
|
||||
offset += IPSET_VALIGN(sizeof(struct ip_set_req_iptree), dont_align);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
iptree_saveheader(struct set *set, unsigned options UNUSED)
|
||||
{
|
||||
struct ip_set_iptree *mysetdata = set->settype->header;
|
||||
|
||||
if (mysetdata->timeout)
|
||||
printf("-N %s %s --timeout %u\n",
|
||||
set->name, set->settype->typename,
|
||||
mysetdata->timeout);
|
||||
else
|
||||
printf("-N %s %s\n",
|
||||
set->name, set->settype->typename);
|
||||
}
|
||||
|
||||
static void
|
||||
iptree_saveips(struct set *set, void *data, u_int32_t len,
|
||||
unsigned options, char dont_align)
|
||||
{
|
||||
struct ip_set_iptree *mysetdata = set->settype->header;
|
||||
struct ip_set_req_iptree *req;
|
||||
size_t offset = 0;
|
||||
|
||||
DP("%s", set->name);
|
||||
|
||||
while (len >= offset + sizeof(struct ip_set_req_iptree)) {
|
||||
req = (struct ip_set_req_iptree *)(data + offset);
|
||||
if (mysetdata->timeout)
|
||||
printf("-A %s %s,%u\n",
|
||||
set->name,
|
||||
ip_tostring(req->ip, options),
|
||||
req->timeout);
|
||||
else
|
||||
printf("-A %s %s\n",
|
||||
set->name,
|
||||
ip_tostring(req->ip, options));
|
||||
offset += IPSET_VALIGN(sizeof(struct ip_set_req_iptree), dont_align);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
iptree_usage(void)
|
||||
{
|
||||
printf
|
||||
("-N set iptree [--timeout value]\n"
|
||||
"-A set IP[,timeout]\n"
|
||||
"-D set IP\n"
|
||||
"-T set IP\n");
|
||||
}
|
||||
|
||||
static struct settype settype_iptree = {
|
||||
.typename = SETTYPE_NAME,
|
||||
.protocol_version = IP_SET_PROTOCOL_VERSION,
|
||||
|
||||
/* Create */
|
||||
.create_size = sizeof(struct ip_set_req_iptree_create),
|
||||
.create_init = iptree_create_init,
|
||||
.create_parse = iptree_create_parse,
|
||||
.create_final = iptree_create_final,
|
||||
.create_opts = create_opts,
|
||||
|
||||
/* Add/del/test */
|
||||
.adt_size = sizeof(struct ip_set_req_iptree),
|
||||
.adt_parser = iptree_adt_parser,
|
||||
|
||||
/* Printing */
|
||||
.header_size = sizeof(struct ip_set_iptree),
|
||||
.initheader = iptree_initheader,
|
||||
.printheader = iptree_printheader,
|
||||
.printips = iptree_printips_sorted, /* We only have sorted version */
|
||||
.printips_sorted = iptree_printips_sorted,
|
||||
.saveheader = iptree_saveheader,
|
||||
.saveips = iptree_saveips,
|
||||
|
||||
.usage = iptree_usage,
|
||||
};
|
||||
|
||||
CONSTRUCTOR(iptree)
|
||||
{
|
||||
settype_register(&settype_iptree);
|
||||
|
||||
}
|
||||
@@ -1,208 +0,0 @@
|
||||
/* Copyright 2007 Sven Wegener <sven.wegener@stealer.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
* Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <limits.h> /* UINT_MAX */
|
||||
#include <stdio.h> /* *printf */
|
||||
#include <string.h> /* mem* */
|
||||
|
||||
#include "ipset.h"
|
||||
|
||||
#include "ip_set_iptreemap.h"
|
||||
|
||||
#define OPT_CREATE_GC 0x1
|
||||
|
||||
static void
|
||||
iptreemap_create_init(void *data)
|
||||
{
|
||||
struct ip_set_req_iptreemap_create *mydata = data;
|
||||
|
||||
mydata->gc_interval = 0;
|
||||
}
|
||||
|
||||
static int
|
||||
iptreemap_create_parse(int c, char *argv[] UNUSED, void *data,
|
||||
unsigned int *flags)
|
||||
{
|
||||
struct ip_set_req_iptreemap_create *mydata = data;
|
||||
|
||||
switch (c) {
|
||||
case 'g':
|
||||
string_to_number(optarg, 0, UINT_MAX, &mydata->gc_interval);
|
||||
|
||||
*flags |= OPT_CREATE_GC;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
iptreemap_create_final(void *data UNUSED, unsigned int flags UNUSED)
|
||||
{
|
||||
}
|
||||
|
||||
static const struct option create_opts[] = {
|
||||
{.name = "gc", .has_arg = required_argument, .val = 'g'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
static ip_set_ip_t
|
||||
iptreemap_adt_parser(int cmd UNUSED, const char *arg, void *data)
|
||||
{
|
||||
struct ip_set_req_iptreemap *mydata = data;
|
||||
ip_set_ip_t mask;
|
||||
|
||||
char *saved = ipset_strdup(arg);
|
||||
char *ptr, *tmp = saved;
|
||||
|
||||
if (strchr(tmp, '/')) {
|
||||
parse_ipandmask(tmp, &mydata->ip, &mask);
|
||||
mydata->end = mydata->ip | ~mask;
|
||||
} else {
|
||||
if ((ptr = strchr(tmp, ':')) != NULL && ++warn_once == 1)
|
||||
fprintf(stderr, "Warning: please use '-' separator token between IP range.\n"
|
||||
"Next release won't support old separator token.\n");
|
||||
ptr = strsep(&tmp, "-:");
|
||||
parse_ip(ptr, &mydata->ip);
|
||||
|
||||
if (tmp) {
|
||||
parse_ip(tmp, &mydata->end);
|
||||
} else {
|
||||
mydata->end = mydata->ip;
|
||||
}
|
||||
}
|
||||
|
||||
ipset_free(saved);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
iptreemap_initheader(struct set *set, const void *data)
|
||||
{
|
||||
const struct ip_set_req_iptreemap_create *header = data;
|
||||
struct ip_set_iptreemap *map = set->settype->header;
|
||||
|
||||
map->gc_interval = header->gc_interval;
|
||||
}
|
||||
|
||||
static void
|
||||
iptreemap_printheader(struct set *set, unsigned int options UNUSED)
|
||||
{
|
||||
struct ip_set_iptreemap *mysetdata = set->settype->header;
|
||||
|
||||
if (mysetdata->gc_interval)
|
||||
printf(" gc: %u", mysetdata->gc_interval);
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void
|
||||
iptreemap_printips_sorted(struct set *set UNUSED, void *data,
|
||||
u_int32_t len, unsigned int options, char dont_align)
|
||||
{
|
||||
struct ip_set_req_iptreemap *req;
|
||||
size_t offset = 0;
|
||||
|
||||
while (len >= offset + sizeof(struct ip_set_req_iptreemap)) {
|
||||
req = data + offset;
|
||||
|
||||
printf("%s", ip_tostring(req->ip, options));
|
||||
if (req->ip != req->end)
|
||||
printf("-%s", ip_tostring(req->end, options));
|
||||
printf("\n");
|
||||
|
||||
offset += IPSET_VALIGN(sizeof(struct ip_set_req_iptreemap), dont_align);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
iptreemap_saveheader(struct set *set, unsigned int options UNUSED)
|
||||
{
|
||||
struct ip_set_iptreemap *mysetdata = set->settype->header;
|
||||
|
||||
printf("-N %s %s", set->name, set->settype->typename);
|
||||
|
||||
if (mysetdata->gc_interval)
|
||||
printf(" --gc %u", mysetdata->gc_interval);
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void
|
||||
iptreemap_saveips(struct set *set UNUSED, void *data,
|
||||
u_int32_t len, unsigned int options, char dont_align)
|
||||
{
|
||||
struct ip_set_req_iptreemap *req;
|
||||
size_t offset = 0;
|
||||
|
||||
while (len >= offset + sizeof(struct ip_set_req_iptreemap)) {
|
||||
req = data + offset;
|
||||
|
||||
printf("-A %s %s", set->name, ip_tostring(req->ip, options));
|
||||
|
||||
if (req->ip != req->end)
|
||||
printf("-%s", ip_tostring(req->end, options));
|
||||
|
||||
printf("\n");
|
||||
|
||||
offset += IPSET_VALIGN(sizeof(struct ip_set_req_iptreemap), dont_align);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
iptreemap_usage(void)
|
||||
{
|
||||
printf(
|
||||
"-N set iptreemap --gc interval\n"
|
||||
"-A set IP\n"
|
||||
"-D set IP\n"
|
||||
"-T set IP\n"
|
||||
);
|
||||
}
|
||||
|
||||
static struct settype settype_iptreemap = {
|
||||
.typename = SETTYPE_NAME,
|
||||
.protocol_version = IP_SET_PROTOCOL_VERSION,
|
||||
|
||||
.create_size = sizeof(struct ip_set_req_iptreemap_create),
|
||||
.create_init = iptreemap_create_init,
|
||||
.create_parse = iptreemap_create_parse,
|
||||
.create_final = iptreemap_create_final,
|
||||
.create_opts = create_opts,
|
||||
|
||||
.adt_size = sizeof(struct ip_set_req_iptreemap),
|
||||
.adt_parser = iptreemap_adt_parser,
|
||||
|
||||
.header_size = sizeof(struct ip_set_iptreemap),
|
||||
.initheader = iptreemap_initheader,
|
||||
.printheader = iptreemap_printheader,
|
||||
.printips = iptreemap_printips_sorted,
|
||||
.printips_sorted = iptreemap_printips_sorted,
|
||||
.saveheader = iptreemap_saveheader,
|
||||
.saveips = iptreemap_saveips,
|
||||
|
||||
.usage = iptreemap_usage,
|
||||
};
|
||||
|
||||
CONSTRUCTOR(iptreemap)
|
||||
{
|
||||
settype_register(&settype_iptreemap);
|
||||
}
|
||||
@@ -1,382 +0,0 @@
|
||||
/* Copyright 2000, 2001, 2002 Joakim Axelsson (gozem@linux.nu)
|
||||
* Patrick Schaaf (bof@bof.de)
|
||||
* Martin Josefsson (gandalf@wlug.westbo.se)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h> /* *printf */
|
||||
#include <stdlib.h> /* mem* */
|
||||
#include <string.h> /* str* */
|
||||
#include <net/ethernet.h> /* ETH_ALEN */
|
||||
|
||||
#include "ipset.h"
|
||||
|
||||
#include "ip_set_macipmap.h"
|
||||
|
||||
#define BUFLEN 30;
|
||||
|
||||
#define OPT_CREATE_FROM 0x01U
|
||||
#define OPT_CREATE_TO 0x02U
|
||||
#define OPT_CREATE_NETWORK 0x04U
|
||||
#define OPT_CREATE_MATCHUNSET 0x08U
|
||||
|
||||
#define OPT_ADDDEL_IP 0x01U
|
||||
#define OPT_ADDDEL_MAC 0x02U
|
||||
|
||||
/* Initialize the create. */
|
||||
static void
|
||||
macipmap_create_init(void *data UNUSED)
|
||||
{
|
||||
DP("create INIT");
|
||||
/* Nothing */
|
||||
}
|
||||
|
||||
/* Function which parses command options; returns true if it ate an option */
|
||||
static int
|
||||
macipmap_create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags)
|
||||
{
|
||||
struct ip_set_req_macipmap_create *mydata = data;
|
||||
|
||||
DP("create_parse");
|
||||
|
||||
switch (c) {
|
||||
case '1':
|
||||
parse_ip(optarg, &mydata->from);
|
||||
|
||||
*flags |= OPT_CREATE_FROM;
|
||||
|
||||
DP("--from %x (%s)", mydata->from,
|
||||
ip_tostring_numeric(mydata->from));
|
||||
|
||||
break;
|
||||
|
||||
case '2':
|
||||
parse_ip(optarg, &mydata->to);
|
||||
|
||||
*flags |= OPT_CREATE_TO;
|
||||
|
||||
DP("--to %x (%s)", mydata->to,
|
||||
ip_tostring_numeric(mydata->to));
|
||||
|
||||
break;
|
||||
|
||||
case '3':
|
||||
parse_ipandmask(optarg, &mydata->from, &mydata->to);
|
||||
|
||||
/* Make to the last of from + mask */
|
||||
mydata->to = mydata->from | (~mydata->to);
|
||||
|
||||
*flags |= OPT_CREATE_NETWORK;
|
||||
|
||||
DP("--network from %x (%s)",
|
||||
mydata->from, ip_tostring_numeric(mydata->from));
|
||||
DP("--network to %x (%s)",
|
||||
mydata->to, ip_tostring_numeric(mydata->to));
|
||||
|
||||
break;
|
||||
|
||||
case '4':
|
||||
mydata->flags |= IPSET_MACIP_MATCHUNSET;
|
||||
|
||||
*flags |= OPT_CREATE_MATCHUNSET;
|
||||
|
||||
DP("--matchunset");
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
static void
|
||||
macipmap_create_final(void *data, unsigned int flags)
|
||||
{
|
||||
struct ip_set_req_macipmap_create *mydata = data;
|
||||
|
||||
if (flags == 0)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Need to specify --from and --to, or --network\n");
|
||||
|
||||
if (flags & OPT_CREATE_NETWORK) {
|
||||
/* --network */
|
||||
if ((flags & OPT_CREATE_FROM) || (flags & OPT_CREATE_TO))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Can't specify --from or --to with --network\n");
|
||||
} else {
|
||||
/* --from --to */
|
||||
if ((flags & OPT_CREATE_FROM) == 0
|
||||
|| (flags & OPT_CREATE_TO) == 0)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Need to specify both --from and --to\n");
|
||||
}
|
||||
|
||||
|
||||
DP("from : %x to: %x diff: %d match unset: %d", mydata->from,
|
||||
mydata->to, mydata->to - mydata->from,
|
||||
flags & OPT_CREATE_MATCHUNSET);
|
||||
|
||||
if (mydata->from > mydata->to)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"From can't be lower than to.\n");
|
||||
|
||||
if (mydata->to - mydata->from > MAX_RANGE)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Range too large. Max is %d IPs in range\n",
|
||||
MAX_RANGE+1);
|
||||
}
|
||||
|
||||
/* Create commandline options */
|
||||
static const struct option create_opts[] = {
|
||||
{.name = "from", .has_arg = required_argument, .val = '1'},
|
||||
{.name = "to", .has_arg = required_argument, .val = '2'},
|
||||
{.name = "network", .has_arg = required_argument, .val = '3'},
|
||||
{.name = "matchunset", .has_arg = no_argument, .val = '4'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
static void
|
||||
parse_mac(const char *mac, unsigned char *ethernet)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
|
||||
if (strlen(mac) != ETH_ALEN * 3 - 1)
|
||||
exit_error(PARAMETER_PROBLEM, "Bad mac address `%s'", mac);
|
||||
|
||||
for (i = 0; i < ETH_ALEN; i++) {
|
||||
long number;
|
||||
char *end;
|
||||
|
||||
number = strtol(mac + i * 3, &end, 16);
|
||||
|
||||
if (end == mac + i * 3 + 2 && number >= 0 && number <= 255)
|
||||
ethernet[i] = number;
|
||||
else
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Bad mac address `%s'", mac);
|
||||
}
|
||||
}
|
||||
|
||||
/* Add, del, test parser */
|
||||
static ip_set_ip_t
|
||||
macipmap_adt_parser(int cmd UNUSED, const char *arg, void *data)
|
||||
{
|
||||
struct ip_set_req_macipmap *mydata = data;
|
||||
char *saved = ipset_strdup(arg);
|
||||
char *ptr, *tmp = saved;
|
||||
|
||||
DP("macipmap: %p %p", arg, data);
|
||||
|
||||
ptr = strsep(&tmp, ",");
|
||||
if (!tmp) {
|
||||
tmp = saved;
|
||||
ptr = strsep(&tmp, ":%");
|
||||
if (tmp && ++warn_once == 1)
|
||||
fprintf(stderr, "Warning: please use ',' separator token between ip,mac.\n"
|
||||
"Next release won't support old separator tokens.\n");
|
||||
}
|
||||
parse_ip(ptr, &mydata->ip);
|
||||
|
||||
if (tmp)
|
||||
parse_mac(tmp, mydata->ethernet);
|
||||
else
|
||||
memset(mydata->ethernet, 0, ETH_ALEN);
|
||||
|
||||
free(saved);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Print and save
|
||||
*/
|
||||
|
||||
static void
|
||||
macipmap_initheader(struct set *set, const void *data)
|
||||
{
|
||||
const struct ip_set_req_macipmap_create *header = data;
|
||||
struct ip_set_macipmap *map = set->settype->header;
|
||||
|
||||
memset(map, 0, sizeof(struct ip_set_macipmap));
|
||||
map->first_ip = header->from;
|
||||
map->last_ip = header->to;
|
||||
map->flags = header->flags;
|
||||
}
|
||||
|
||||
static void
|
||||
macipmap_printheader(struct set *set, unsigned options)
|
||||
{
|
||||
struct ip_set_macipmap *mysetdata = set->settype->header;
|
||||
|
||||
printf(" from: %s", ip_tostring(mysetdata->first_ip, options));
|
||||
printf(" to: %s", ip_tostring(mysetdata->last_ip, options));
|
||||
|
||||
if (mysetdata->flags & IPSET_MACIP_MATCHUNSET)
|
||||
printf(" matchunset");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void
|
||||
print_mac(unsigned char macaddress[ETH_ALEN])
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
printf("%02X", macaddress[0]);
|
||||
for (i = 1; i < ETH_ALEN; i++)
|
||||
printf(":%02X", macaddress[i]);
|
||||
}
|
||||
|
||||
static inline void
|
||||
__macipmap_printips_sorted(struct set *set, void *data,
|
||||
u_int32_t len UNUSED, unsigned options)
|
||||
{
|
||||
struct ip_set_macipmap *mysetdata = set->settype->header;
|
||||
struct ip_set_macip *table = data;
|
||||
u_int32_t addr = mysetdata->first_ip;
|
||||
|
||||
while (addr <= mysetdata->last_ip) {
|
||||
if (table[addr - mysetdata->first_ip].match) {
|
||||
printf("%s,", ip_tostring(addr, options));
|
||||
print_mac(table[addr - mysetdata->first_ip].
|
||||
ethernet);
|
||||
printf("\n");
|
||||
}
|
||||
addr++;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
macipmap_printips_sorted(struct set *set, void *data,
|
||||
u_int32_t len, unsigned options,
|
||||
char dont_align)
|
||||
{
|
||||
struct ip_set_req_macipmap *d;
|
||||
size_t offset = 0;
|
||||
|
||||
if (dont_align)
|
||||
return __macipmap_printips_sorted(set, data, len, options);
|
||||
|
||||
while (offset < len) {
|
||||
d = data + offset;
|
||||
printf("%s,", ip_tostring(d->ip, options));
|
||||
print_mac(d->ethernet);
|
||||
printf("\n");
|
||||
offset += IPSET_ALIGN(sizeof(struct ip_set_req_macipmap));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
macipmap_saveheader(struct set *set, unsigned options)
|
||||
{
|
||||
struct ip_set_macipmap *mysetdata = set->settype->header;
|
||||
|
||||
printf("-N %s %s --from %s",
|
||||
set->name, set->settype->typename,
|
||||
ip_tostring(mysetdata->first_ip, options));
|
||||
printf(" --to %s", ip_tostring(mysetdata->last_ip, options));
|
||||
|
||||
if (mysetdata->flags & IPSET_MACIP_MATCHUNSET)
|
||||
printf(" --matchunset");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static inline void
|
||||
__macipmap_saveips(struct set *set, void *data,
|
||||
u_int32_t len UNUSED, unsigned options)
|
||||
{
|
||||
struct ip_set_macipmap *mysetdata = set->settype->header;
|
||||
struct ip_set_macip *table = data;
|
||||
u_int32_t addr = mysetdata->first_ip;
|
||||
|
||||
while (addr <= mysetdata->last_ip) {
|
||||
if (table[addr - mysetdata->first_ip].match) {
|
||||
printf("-A %s %s,",
|
||||
set->name, ip_tostring(addr, options));
|
||||
print_mac(table[addr - mysetdata->first_ip].
|
||||
ethernet);
|
||||
printf("\n");
|
||||
}
|
||||
addr++;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
macipmap_saveips(struct set *set, void *data,
|
||||
u_int32_t len, unsigned options,
|
||||
char dont_align)
|
||||
{
|
||||
struct ip_set_req_macipmap *d;
|
||||
size_t offset = 0;
|
||||
|
||||
if (dont_align)
|
||||
return __macipmap_saveips(set, data, len, options);
|
||||
|
||||
while (offset < len) {
|
||||
d = data + offset;
|
||||
printf("-A %s %s,", set->name, ip_tostring(d->ip, options));
|
||||
print_mac(d->ethernet);
|
||||
printf("\n");
|
||||
offset += IPSET_ALIGN(sizeof(struct ip_set_req_macipmap));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
macipmap_usage(void)
|
||||
{
|
||||
printf
|
||||
("-N set macipmap --from IP --to IP [--matchunset]\n"
|
||||
"-N set macipmap --network IP/mask [--matchunset]\n"
|
||||
"-A set IP[,MAC]\n"
|
||||
"-D set IP[,MAC]\n"
|
||||
"-T set IP[,MAC]\n");
|
||||
}
|
||||
|
||||
static struct settype settype_macipmap = {
|
||||
.typename = SETTYPE_NAME,
|
||||
.protocol_version = IP_SET_PROTOCOL_VERSION,
|
||||
|
||||
/* Create */
|
||||
.create_size = sizeof(struct ip_set_req_macipmap_create),
|
||||
.create_init = macipmap_create_init,
|
||||
.create_parse = macipmap_create_parse,
|
||||
.create_final = macipmap_create_final,
|
||||
.create_opts = create_opts,
|
||||
|
||||
/* Add/del/test */
|
||||
.adt_size = sizeof(struct ip_set_req_macipmap),
|
||||
.adt_parser = macipmap_adt_parser,
|
||||
|
||||
/* Printing */
|
||||
.header_size = sizeof(struct ip_set_macipmap),
|
||||
.initheader = macipmap_initheader,
|
||||
.printheader = macipmap_printheader,
|
||||
.printips = macipmap_printips_sorted,
|
||||
.printips_sorted = macipmap_printips_sorted,
|
||||
.saveheader = macipmap_saveheader,
|
||||
.saveips = macipmap_saveips,
|
||||
|
||||
.usage = macipmap_usage,
|
||||
};
|
||||
|
||||
CONSTRUCTOR(macipmap)
|
||||
{
|
||||
settype_register(&settype_macipmap);
|
||||
|
||||
}
|
||||
@@ -1,308 +0,0 @@
|
||||
/* Copyright 2004 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <limits.h> /* UINT_MAX */
|
||||
#include <stdio.h> /* *printf */
|
||||
#include <string.h> /* mem*, str* */
|
||||
|
||||
#include "ipset.h"
|
||||
|
||||
#include "ip_set_nethash.h"
|
||||
|
||||
#define BUFLEN 30;
|
||||
|
||||
#define OPT_CREATE_HASHSIZE 0x01U
|
||||
#define OPT_CREATE_PROBES 0x02U
|
||||
#define OPT_CREATE_RESIZE 0x04U
|
||||
|
||||
/* Initialize the create. */
|
||||
static void
|
||||
nethash_create_init(void *data)
|
||||
{
|
||||
struct ip_set_req_nethash_create *mydata = data;
|
||||
|
||||
DP("create INIT");
|
||||
|
||||
/* Default create parameters */
|
||||
mydata->hashsize = IP_NF_SET_HASHSIZE;
|
||||
mydata->probes = 4;
|
||||
mydata->resize = 50;
|
||||
}
|
||||
|
||||
/* Function which parses command options; returns true if it ate an option */
|
||||
static int
|
||||
nethash_create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags)
|
||||
{
|
||||
struct ip_set_req_nethash_create *mydata = data;
|
||||
ip_set_ip_t value;
|
||||
|
||||
DP("create_parse");
|
||||
|
||||
switch (c) {
|
||||
case '1':
|
||||
|
||||
if (string_to_number(optarg, 1, UINT_MAX - 1, &mydata->hashsize))
|
||||
exit_error(PARAMETER_PROBLEM, "Invalid hashsize `%s' specified", optarg);
|
||||
|
||||
*flags |= OPT_CREATE_HASHSIZE;
|
||||
|
||||
DP("--hashsize %u", mydata->hashsize);
|
||||
|
||||
break;
|
||||
|
||||
case '2':
|
||||
|
||||
if (string_to_number(optarg, 1, 65535, &value))
|
||||
exit_error(PARAMETER_PROBLEM, "Invalid probes `%s' specified", optarg);
|
||||
|
||||
mydata->probes = value;
|
||||
*flags |= OPT_CREATE_PROBES;
|
||||
|
||||
DP("--probes %u", mydata->probes);
|
||||
|
||||
break;
|
||||
|
||||
case '3':
|
||||
|
||||
if (string_to_number(optarg, 0, 65535, &value))
|
||||
exit_error(PARAMETER_PROBLEM, "Invalid resize `%s' specified", optarg);
|
||||
|
||||
mydata->resize = value;
|
||||
*flags |= OPT_CREATE_RESIZE;
|
||||
|
||||
DP("--resize %u", mydata->resize);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
static void
|
||||
nethash_create_final(void *data UNUSED, unsigned int flags UNUSED)
|
||||
{
|
||||
}
|
||||
|
||||
/* Create commandline options */
|
||||
static const struct option create_opts[] = {
|
||||
{.name = "hashsize", .has_arg = required_argument, .val = '1'},
|
||||
{.name = "probes", .has_arg = required_argument, .val = '2'},
|
||||
{.name = "resize", .has_arg = required_argument, .val = '3'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
/* Add, del, test parser */
|
||||
static ip_set_ip_t
|
||||
nethash_adt_parser(int cmd, const char *arg, void *data)
|
||||
{
|
||||
struct ip_set_req_nethash *mydata = data;
|
||||
char *saved = ipset_strdup(arg);
|
||||
char *ptr, *tmp = saved;
|
||||
ip_set_ip_t cidr;
|
||||
|
||||
ptr = strsep(&tmp, "/");
|
||||
|
||||
if (tmp == NULL) {
|
||||
if (cmd == CMD_TEST)
|
||||
cidr = 32;
|
||||
else
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Missing cidr from `%s'", arg);
|
||||
} else
|
||||
if (string_to_number(tmp, 1, 31, &cidr))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Out of range cidr `%s' specified", arg);
|
||||
|
||||
mydata->cidr = cidr;
|
||||
parse_ip(ptr, &mydata->ip);
|
||||
#if 0
|
||||
if (!mydata->ip)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Zero valued IP address `%s' specified", ptr);
|
||||
#endif
|
||||
ipset_free(saved);
|
||||
|
||||
return 1;
|
||||
};
|
||||
|
||||
/*
|
||||
* Print and save
|
||||
*/
|
||||
|
||||
static void
|
||||
nethash_initheader(struct set *set, const void *data)
|
||||
{
|
||||
const struct ip_set_req_nethash_create *header = data;
|
||||
struct ip_set_nethash *map = set->settype->header;
|
||||
|
||||
memset(map, 0, sizeof(struct ip_set_nethash));
|
||||
map->hashsize = header->hashsize;
|
||||
map->probes = header->probes;
|
||||
map->resize = header->resize;
|
||||
}
|
||||
|
||||
static void
|
||||
nethash_printheader(struct set *set, unsigned options UNUSED)
|
||||
{
|
||||
struct ip_set_nethash *mysetdata = set->settype->header;
|
||||
|
||||
printf(" hashsize: %u", mysetdata->hashsize);
|
||||
printf(" probes: %u", mysetdata->probes);
|
||||
printf(" resize: %u\n", mysetdata->resize);
|
||||
}
|
||||
|
||||
static char buf[20];
|
||||
|
||||
static char *
|
||||
unpack_ip_tostring(ip_set_ip_t ip, unsigned options UNUSED)
|
||||
{
|
||||
int i, j = 3;
|
||||
unsigned char a, b;
|
||||
|
||||
ip = htonl(ip);
|
||||
for (i = 3; i >= 0; i--)
|
||||
if (((unsigned char *)&ip)[i] != 0) {
|
||||
j = i;
|
||||
break;
|
||||
}
|
||||
|
||||
a = ((unsigned char *)&ip)[j];
|
||||
if (a <= 128) {
|
||||
a = (a - 1) * 2;
|
||||
b = 7;
|
||||
} else if (a <= 192) {
|
||||
a = (a - 129) * 4;
|
||||
b = 6;
|
||||
} else if (a <= 224) {
|
||||
a = (a - 193) * 8;
|
||||
b = 5;
|
||||
} else if (a <= 240) {
|
||||
a = (a - 225) * 16;
|
||||
b = 4;
|
||||
} else if (a <= 248) {
|
||||
a = (a - 241) * 32;
|
||||
b = 3;
|
||||
} else if (a <= 252) {
|
||||
a = (a - 249) * 64;
|
||||
b = 2;
|
||||
} else if (a <= 254) {
|
||||
a = (a - 253) * 128;
|
||||
b = 1;
|
||||
} else {
|
||||
a = b = 0;
|
||||
}
|
||||
((unsigned char *)&ip)[j] = a;
|
||||
b += j * 8;
|
||||
|
||||
sprintf(buf, "%u.%u.%u.%u/%u",
|
||||
((unsigned char *)&ip)[0],
|
||||
((unsigned char *)&ip)[1],
|
||||
((unsigned char *)&ip)[2],
|
||||
((unsigned char *)&ip)[3],
|
||||
b);
|
||||
|
||||
DP("%s %s", ip_tostring(ntohl(ip), 0), buf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void
|
||||
nethash_printips(struct set *set UNUSED, void *data, u_int32_t len,
|
||||
unsigned options, char dont_align)
|
||||
{
|
||||
size_t offset = 0;
|
||||
ip_set_ip_t *ip;
|
||||
|
||||
while (offset < len) {
|
||||
ip = data + offset;
|
||||
printf("%s\n", unpack_ip_tostring(*ip, options));
|
||||
offset += IPSET_VALIGN(sizeof(ip_set_ip_t), dont_align);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nethash_saveheader(struct set *set, unsigned options UNUSED)
|
||||
{
|
||||
struct ip_set_nethash *mysetdata = set->settype->header;
|
||||
|
||||
printf("-N %s %s --hashsize %u --probes %u --resize %u\n",
|
||||
set->name, set->settype->typename,
|
||||
mysetdata->hashsize, mysetdata->probes, mysetdata->resize);
|
||||
}
|
||||
|
||||
/* Print save for an IP */
|
||||
static void
|
||||
nethash_saveips(struct set *set UNUSED, void *data, u_int32_t len,
|
||||
unsigned options, char dont_align)
|
||||
{
|
||||
size_t offset = 0;
|
||||
ip_set_ip_t *ip;
|
||||
|
||||
while (offset < len) {
|
||||
ip = data + offset;
|
||||
printf("-A %s %s\n", set->name,
|
||||
unpack_ip_tostring(*ip, options));
|
||||
offset += IPSET_VALIGN(sizeof(ip_set_ip_t), dont_align);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nethash_usage(void)
|
||||
{
|
||||
printf
|
||||
("-N set nethash [--hashsize hashsize] [--probes probes ]\n"
|
||||
" [--resize resize]\n"
|
||||
"-A set IP/cidr\n"
|
||||
"-D set IP/cidr\n"
|
||||
"-T set IP/cidr\n");
|
||||
}
|
||||
|
||||
static struct settype settype_nethash = {
|
||||
.typename = SETTYPE_NAME,
|
||||
.protocol_version = IP_SET_PROTOCOL_VERSION,
|
||||
|
||||
/* Create */
|
||||
.create_size = sizeof(struct ip_set_req_nethash_create),
|
||||
.create_init = nethash_create_init,
|
||||
.create_parse = nethash_create_parse,
|
||||
.create_final = nethash_create_final,
|
||||
.create_opts = create_opts,
|
||||
|
||||
/* Add/del/test */
|
||||
.adt_size = sizeof(struct ip_set_req_nethash),
|
||||
.adt_parser = nethash_adt_parser,
|
||||
|
||||
/* Printing */
|
||||
.header_size = sizeof(struct ip_set_nethash),
|
||||
.initheader = nethash_initheader,
|
||||
.printheader = nethash_printheader,
|
||||
.printips = nethash_printips,
|
||||
.printips_sorted = nethash_printips,
|
||||
.saveheader = nethash_saveheader,
|
||||
.saveips = nethash_saveips,
|
||||
|
||||
.usage = nethash_usage,
|
||||
};
|
||||
|
||||
CONSTRUCTOR(nethash)
|
||||
{
|
||||
settype_register(&settype_nethash);
|
||||
|
||||
}
|
||||
@@ -1,272 +0,0 @@
|
||||
/* Copyright 2004 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h> /* *printf */
|
||||
#include <string.h> /* mem* */
|
||||
|
||||
#include "ipset.h"
|
||||
|
||||
#include "ip_set_portmap.h"
|
||||
|
||||
#define BUFLEN 30;
|
||||
|
||||
#define OPT_CREATE_FROM 0x01U
|
||||
#define OPT_CREATE_TO 0x02U
|
||||
|
||||
#define OPT_ADDDEL_PORT 0x01U
|
||||
|
||||
/* Initialize the create. */
|
||||
static void
|
||||
portmap_create_init(void *data UNUSED)
|
||||
{
|
||||
DP("create INIT");
|
||||
/* Nothing */
|
||||
}
|
||||
|
||||
/* Function which parses command options; returns true if it ate an option */
|
||||
static int
|
||||
portmap_create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags)
|
||||
{
|
||||
struct ip_set_req_portmap_create *mydata = data;
|
||||
|
||||
DP("create_parse");
|
||||
|
||||
switch (c) {
|
||||
case '1':
|
||||
parse_port(optarg, &mydata->from);
|
||||
|
||||
*flags |= OPT_CREATE_FROM;
|
||||
|
||||
DP("--from %x (%s)", mydata->from,
|
||||
port_tostring(mydata->from, 0));
|
||||
|
||||
break;
|
||||
|
||||
case '2':
|
||||
parse_port(optarg, &mydata->to);
|
||||
|
||||
*flags |= OPT_CREATE_TO;
|
||||
|
||||
DP("--to %x (%s)", mydata->to,
|
||||
port_tostring(mydata->to, 0));
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
static void
|
||||
portmap_create_final(void *data, unsigned int flags)
|
||||
{
|
||||
struct ip_set_req_portmap_create *mydata = data;
|
||||
|
||||
if (flags == 0) {
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Need to specify --from and --to\n");
|
||||
} else {
|
||||
/* --from --to */
|
||||
if ((flags & OPT_CREATE_FROM) == 0
|
||||
|| (flags & OPT_CREATE_TO) == 0)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Need to specify both --from and --to\n");
|
||||
}
|
||||
|
||||
DP("from : %x to: %x diff: %d", mydata->from, mydata->to,
|
||||
mydata->to - mydata->from);
|
||||
|
||||
if (mydata->from > mydata->to)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"From can't be lower than to.\n");
|
||||
|
||||
if (mydata->to - mydata->from > MAX_RANGE)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Range too large. Max is %d ports in range\n",
|
||||
MAX_RANGE+1);
|
||||
}
|
||||
|
||||
/* Create commandline options */
|
||||
static const struct option create_opts[] = {
|
||||
{.name = "from", .has_arg = required_argument, .val = '1'},
|
||||
{.name = "to", .has_arg = required_argument, .val = '2'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
/* Add, del, test parser */
|
||||
static ip_set_ip_t
|
||||
portmap_adt_parser(int cmd UNUSED, const char *arg, void *data)
|
||||
{
|
||||
struct ip_set_req_portmap *mydata = data;
|
||||
|
||||
parse_port(arg, &mydata->ip);
|
||||
DP("%s", port_tostring(mydata->ip, 0));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Print and save
|
||||
*/
|
||||
|
||||
static void
|
||||
portmap_initheader(struct set *set, const void *data)
|
||||
{
|
||||
const struct ip_set_req_portmap_create *header = data;
|
||||
struct ip_set_portmap *map = set->settype->header;
|
||||
|
||||
memset(map, 0, sizeof(struct ip_set_portmap));
|
||||
map->first_ip = header->from;
|
||||
map->last_ip = header->to;
|
||||
}
|
||||
|
||||
static void
|
||||
portmap_printheader(struct set *set, unsigned options)
|
||||
{
|
||||
struct ip_set_portmap *mysetdata = set->settype->header;
|
||||
|
||||
printf(" from: %s", port_tostring(mysetdata->first_ip, options));
|
||||
printf(" to: %s\n", port_tostring(mysetdata->last_ip, options));
|
||||
}
|
||||
|
||||
static inline void
|
||||
__portmap_printips_sorted(struct set *set, void *data,
|
||||
u_int32_t len UNUSED, unsigned options)
|
||||
{
|
||||
struct ip_set_portmap *mysetdata = set->settype->header;
|
||||
ip_set_ip_t addr = mysetdata->first_ip;
|
||||
|
||||
DP("%u -- %u", mysetdata->first_ip, mysetdata->last_ip);
|
||||
while (addr <= mysetdata->last_ip) {
|
||||
if (test_bit(addr - mysetdata->first_ip, data))
|
||||
printf("%s\n", port_tostring(addr, options));
|
||||
addr++;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
portmap_printips_sorted(struct set *set, void *data,
|
||||
u_int32_t len, unsigned options,
|
||||
char dont_align)
|
||||
{
|
||||
ip_set_ip_t *ip;
|
||||
size_t offset = 0;
|
||||
|
||||
if (dont_align)
|
||||
return __portmap_printips_sorted(set, data, len, options);
|
||||
|
||||
while (offset < len) {
|
||||
ip = data + offset;
|
||||
printf("%s\n", port_tostring(*ip, options));
|
||||
offset += IPSET_ALIGN(sizeof(ip_set_ip_t));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
portmap_saveheader(struct set *set, unsigned options)
|
||||
{
|
||||
struct ip_set_portmap *mysetdata = set->settype->header;
|
||||
|
||||
printf("-N %s %s --from %s",
|
||||
set->name,
|
||||
set->settype->typename,
|
||||
port_tostring(mysetdata->first_ip, options));
|
||||
printf(" --to %s\n",
|
||||
port_tostring(mysetdata->last_ip, options));
|
||||
}
|
||||
|
||||
static inline void
|
||||
__portmap_saveips(struct set *set, void *data,
|
||||
u_int32_t len UNUSED, unsigned options)
|
||||
{
|
||||
struct ip_set_portmap *mysetdata = set->settype->header;
|
||||
ip_set_ip_t addr = mysetdata->first_ip;
|
||||
|
||||
while (addr <= mysetdata->last_ip) {
|
||||
DP("addr: %lu, last_ip %lu", (long unsigned)addr, (long unsigned)mysetdata->last_ip);
|
||||
if (test_bit(addr - mysetdata->first_ip, data))
|
||||
printf("-A %s %s\n",
|
||||
set->name,
|
||||
port_tostring(addr, options));
|
||||
addr++;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
portmap_saveips(struct set *set, void *data,
|
||||
u_int32_t len, unsigned options,
|
||||
char dont_align)
|
||||
{
|
||||
ip_set_ip_t *ip;
|
||||
size_t offset = 0;
|
||||
|
||||
if (dont_align)
|
||||
return __portmap_saveips(set, data, len, options);
|
||||
|
||||
while (offset < len) {
|
||||
ip = data + offset;
|
||||
printf("-A %s %s\n", set->name, port_tostring(*ip, options));
|
||||
offset += IPSET_ALIGN(sizeof(ip_set_ip_t));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
portmap_usage(void)
|
||||
{
|
||||
printf
|
||||
("-N set portmap --from PORT --to PORT\n"
|
||||
"-A set PORT\n"
|
||||
"-D set PORT\n"
|
||||
"-T set PORT\n");
|
||||
}
|
||||
|
||||
static struct settype settype_portmap = {
|
||||
.typename = SETTYPE_NAME,
|
||||
.protocol_version = IP_SET_PROTOCOL_VERSION,
|
||||
|
||||
/* Create */
|
||||
.create_size = sizeof(struct ip_set_req_portmap_create),
|
||||
.create_init = portmap_create_init,
|
||||
.create_parse = portmap_create_parse,
|
||||
.create_final = portmap_create_final,
|
||||
.create_opts = create_opts,
|
||||
|
||||
/* Add/del/test */
|
||||
.adt_size = sizeof(struct ip_set_req_portmap),
|
||||
.adt_parser = portmap_adt_parser,
|
||||
|
||||
/* Printing */
|
||||
.header_size = sizeof(struct ip_set_portmap),
|
||||
.initheader = portmap_initheader,
|
||||
.printheader = portmap_printheader,
|
||||
.printips = portmap_printips_sorted,
|
||||
.printips_sorted = portmap_printips_sorted,
|
||||
.saveheader = portmap_saveheader,
|
||||
.saveips = portmap_saveips,
|
||||
|
||||
.usage = portmap_usage,
|
||||
};
|
||||
|
||||
CONSTRUCTOR(portmap)
|
||||
{
|
||||
settype_register(&settype_portmap);
|
||||
|
||||
}
|
||||
@@ -1,229 +0,0 @@
|
||||
/* Copyright 2008 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "ip_set_setlist.h"
|
||||
#include "ipset.h"
|
||||
|
||||
/* Initialize the create. */
|
||||
static void
|
||||
setlist_create_init(void *data)
|
||||
{
|
||||
struct ip_set_req_setlist_create *mydata = data;
|
||||
|
||||
mydata->size = 8;
|
||||
}
|
||||
|
||||
/* Function which parses command options; returns true if it ate an option */
|
||||
static int
|
||||
setlist_create_parse(int c, char *argv[] UNUSED, void *data,
|
||||
unsigned *flags UNUSED)
|
||||
{
|
||||
struct ip_set_req_setlist_create *mydata = data;
|
||||
unsigned int size;
|
||||
|
||||
switch (c) {
|
||||
case '1':
|
||||
if (string_to_number(optarg, 1, 255, &size))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Invalid size '%s specified: must be "
|
||||
"between 1-255", optarg);
|
||||
mydata->size = size;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
static void
|
||||
setlist_create_final(void *data UNUSED, unsigned int flags UNUSED)
|
||||
{
|
||||
}
|
||||
|
||||
/* Create commandline options */
|
||||
static const struct option create_opts[] = {
|
||||
{.name = "size", .has_arg = required_argument, .val = '1'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
static void
|
||||
check_setname(const char *name)
|
||||
{
|
||||
if (strlen(name) > IP_SET_MAXNAMELEN - 1)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Setname %s is longer than %d characters.",
|
||||
name, IP_SET_MAXNAMELEN - 1);
|
||||
}
|
||||
|
||||
/* Add, del, test parser */
|
||||
static ip_set_ip_t
|
||||
setlist_adt_parser(int cmd UNUSED, const char *arg, void *data)
|
||||
{
|
||||
struct ip_set_req_setlist *mydata = data;
|
||||
char *saved = ipset_strdup(arg);
|
||||
char *ptr, *tmp = saved;
|
||||
|
||||
DP("setlist: %p %p", arg, data);
|
||||
|
||||
ptr = strsep(&tmp, ",");
|
||||
check_setname(ptr);
|
||||
strcpy(mydata->name, ptr);
|
||||
|
||||
if (!tmp) {
|
||||
mydata->before = 0;
|
||||
mydata->ref[0] = '\0';
|
||||
return 1;
|
||||
}
|
||||
|
||||
ptr = strsep(&tmp, ",");
|
||||
|
||||
if (tmp == NULL || !(strcmp(ptr, "before") == 0 || strcmp(ptr, "after") == 0))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Syntax error, you must specify elements as setname,[before|after],setname");
|
||||
|
||||
check_setname(tmp);
|
||||
strcpy(mydata->ref, tmp);
|
||||
mydata->before = !strcmp(ptr, "before");
|
||||
|
||||
free(saved);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Print and save
|
||||
*/
|
||||
|
||||
static void
|
||||
setlist_initheader(struct set *set, const void *data)
|
||||
{
|
||||
const struct ip_set_req_setlist_create *header = data;
|
||||
struct ip_set_setlist *map = set->settype->header;
|
||||
|
||||
memset(map, 0, sizeof(struct ip_set_setlist));
|
||||
map->size = header->size;
|
||||
}
|
||||
|
||||
static void
|
||||
setlist_printheader(struct set *set, unsigned options UNUSED)
|
||||
{
|
||||
struct ip_set_setlist *mysetdata = set->settype->header;
|
||||
|
||||
printf(" size: %u\n", mysetdata->size);
|
||||
}
|
||||
|
||||
static void
|
||||
setlist_printips_sorted(struct set *set, void *data,
|
||||
u_int32_t len UNUSED, unsigned options UNUSED,
|
||||
char dont_align)
|
||||
{
|
||||
struct ip_set_setlist *mysetdata = set->settype->header;
|
||||
int i, asize;
|
||||
ip_set_id_t *id;
|
||||
struct set *elem;
|
||||
|
||||
asize = IPSET_VALIGN(sizeof(ip_set_id_t), dont_align);
|
||||
for (i = 0; i < mysetdata->size; i++ ) {
|
||||
DP("Try %u", i);
|
||||
id = (ip_set_id_t *)(data + i * asize);
|
||||
DP("Try %u, check", i);
|
||||
if (*id == IP_SET_INVALID_ID)
|
||||
return;
|
||||
elem = set_find_byid(*id);
|
||||
printf("%s\n", elem->name);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
setlist_saveheader(struct set *set, unsigned options UNUSED)
|
||||
{
|
||||
struct ip_set_setlist *mysetdata = set->settype->header;
|
||||
|
||||
printf("-N %s %s --size %u\n",
|
||||
set->name, set->settype->typename,
|
||||
mysetdata->size);
|
||||
}
|
||||
|
||||
static void
|
||||
setlist_saveips(struct set *set, void *data,
|
||||
u_int32_t len UNUSED, unsigned options UNUSED, char dont_align)
|
||||
{
|
||||
struct ip_set_setlist *mysetdata = set->settype->header;
|
||||
int i, asize;
|
||||
ip_set_id_t *id;
|
||||
struct set *elem;
|
||||
|
||||
asize = IPSET_VALIGN(sizeof(ip_set_id_t), dont_align);
|
||||
for (i = 0; i < mysetdata->size; i++ ) {
|
||||
id = (ip_set_id_t *)(data + i * asize);
|
||||
if (*id == IP_SET_INVALID_ID)
|
||||
return;
|
||||
elem = set_find_byid(*id);
|
||||
printf("-A %s %s\n", set->name, elem->name);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
setlist_usage(void)
|
||||
{
|
||||
printf
|
||||
("-N set setlist --size size\n"
|
||||
"-A set setname[,before|after,setname]\n"
|
||||
"-D set setname\n"
|
||||
"-T set setname\n");
|
||||
}
|
||||
|
||||
static struct settype settype_setlist = {
|
||||
.typename = SETTYPE_NAME,
|
||||
.protocol_version = IP_SET_PROTOCOL_VERSION,
|
||||
|
||||
/* Create */
|
||||
.create_size = sizeof(struct ip_set_req_setlist_create),
|
||||
.create_init = setlist_create_init,
|
||||
.create_parse = setlist_create_parse,
|
||||
.create_final = setlist_create_final,
|
||||
.create_opts = create_opts,
|
||||
|
||||
/* Add/del/test */
|
||||
.adt_size = sizeof(struct ip_set_req_setlist),
|
||||
.adt_parser = setlist_adt_parser,
|
||||
|
||||
/* Printing */
|
||||
.header_size = sizeof(struct ip_set_setlist),
|
||||
.initheader = setlist_initheader,
|
||||
.printheader = setlist_printheader,
|
||||
.printips = setlist_printips_sorted,
|
||||
.printips_sorted = setlist_printips_sorted,
|
||||
.saveheader = setlist_saveheader,
|
||||
.saveips = setlist_saveips,
|
||||
|
||||
.usage = setlist_usage,
|
||||
};
|
||||
|
||||
CONSTRUCTOR(setlist)
|
||||
{
|
||||
settype_register(&settype_setlist);
|
||||
|
||||
}
|
||||
@@ -1,138 +0,0 @@
|
||||
/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
|
||||
* Patrick Schaaf <bof@bof.de>
|
||||
* Martin Josefsson <gandalf@wlug.westbo.se>
|
||||
* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* ipt_SET.c - netfilter target to manipulate IP sets */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#include <linux/netfilter_ipv4.h>
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
#define xt_register_target ipt_register_target
|
||||
#define xt_unregister_target ipt_unregister_target
|
||||
#define xt_target ipt_target
|
||||
#define XT_CONTINUE IPT_CONTINUE
|
||||
#else
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#endif
|
||||
#include "ipt_set.h"
|
||||
#include "../compat_xtables.h"
|
||||
|
||||
static unsigned int
|
||||
target(struct sk_buff **pskb, const struct xt_action_param *par)
|
||||
{
|
||||
const struct ipt_set_info_target *info = par->targinfo;
|
||||
|
||||
if (info->add_set.index != IP_SET_INVALID_ID)
|
||||
ip_set_addip_kernel(info->add_set.index,
|
||||
*pskb,
|
||||
info->add_set.flags);
|
||||
if (info->del_set.index != IP_SET_INVALID_ID)
|
||||
ip_set_delip_kernel(info->del_set.index,
|
||||
*pskb,
|
||||
info->del_set.flags);
|
||||
|
||||
return XT_CONTINUE;
|
||||
}
|
||||
|
||||
static int
|
||||
checkentry(const struct xt_tgchk_param *par)
|
||||
{
|
||||
struct ipt_set_info_target *info = par->targinfo;
|
||||
ip_set_id_t index;
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
|
||||
if (targinfosize != IPT_ALIGN(sizeof(*info))) {
|
||||
DP("bad target info size %u", targinfosize);
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (info->add_set.index != IP_SET_INVALID_ID) {
|
||||
index = ip_set_get_byindex(info->add_set.index);
|
||||
if (index == IP_SET_INVALID_ID) {
|
||||
ip_set_printk("cannot find add_set index %u as target",
|
||||
info->add_set.index);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (info->del_set.index != IP_SET_INVALID_ID) {
|
||||
index = ip_set_get_byindex(info->del_set.index);
|
||||
if (index == IP_SET_INVALID_ID) {
|
||||
ip_set_printk("cannot find del_set index %u as target",
|
||||
info->del_set.index);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
if (info->add_set.flags[IP_SET_MAX_BINDINGS] != 0
|
||||
|| info->del_set.flags[IP_SET_MAX_BINDINGS] != 0) {
|
||||
ip_set_printk("That's nasty!");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void destroy(const struct xt_tgdtor_param *par)
|
||||
{
|
||||
struct ipt_set_info_target *info = par->targinfo;
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
|
||||
if (targetsize != IPT_ALIGN(sizeof(struct ipt_set_info_target))) {
|
||||
ip_set_printk("invalid targetsize %d", targetsize);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (info->add_set.index != IP_SET_INVALID_ID)
|
||||
ip_set_put_byindex(info->add_set.index);
|
||||
if (info->del_set.index != IP_SET_INVALID_ID)
|
||||
ip_set_put_byindex(info->del_set.index);
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
|
||||
static struct xt_target SET_target = {
|
||||
.name = "SET",
|
||||
.target = target,
|
||||
.checkentry = checkentry,
|
||||
.destroy = destroy,
|
||||
.me = THIS_MODULE
|
||||
};
|
||||
#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) */
|
||||
static struct xt_target SET_target = {
|
||||
.name = "SET",
|
||||
.family = AF_INET,
|
||||
.target = target,
|
||||
.targetsize = sizeof(struct ipt_set_info_target),
|
||||
.checkentry = checkentry,
|
||||
.destroy = destroy,
|
||||
.me = THIS_MODULE
|
||||
};
|
||||
#endif
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("iptables IP set target module");
|
||||
|
||||
static int __init ipt_SET_init(void)
|
||||
{
|
||||
return xt_register_target(&SET_target);
|
||||
}
|
||||
|
||||
static void __exit ipt_SET_fini(void)
|
||||
{
|
||||
xt_unregister_target(&SET_target);
|
||||
}
|
||||
|
||||
module_init(ipt_SET_init);
|
||||
module_exit(ipt_SET_fini);
|
||||
@@ -1,126 +0,0 @@
|
||||
/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
|
||||
* Patrick Schaaf <bof@bof.de>
|
||||
* Martin Josefsson <gandalf@wlug.westbo.se>
|
||||
* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* Kernel module to match an IP set. */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
#define xt_register_match ipt_register_match
|
||||
#define xt_unregister_match ipt_unregister_match
|
||||
#define xt_match ipt_match
|
||||
#else
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#endif
|
||||
#include "ip_set.h"
|
||||
#include "ipt_set.h"
|
||||
#include "../compat_xtables.h"
|
||||
|
||||
static inline int
|
||||
match_set(const struct ipt_set_info *info,
|
||||
const struct sk_buff *skb,
|
||||
int inv)
|
||||
{
|
||||
if (ip_set_testip_kernel(info->index, skb, info->flags))
|
||||
inv = !inv;
|
||||
return inv;
|
||||
}
|
||||
|
||||
static bool
|
||||
match(const struct sk_buff *skb, struct xt_action_param *par)
|
||||
{
|
||||
const struct ipt_set_info_match *info = par->matchinfo;
|
||||
|
||||
return match_set(&info->match_set,
|
||||
skb,
|
||||
info->match_set.flags[0] & IPSET_MATCH_INV);
|
||||
}
|
||||
|
||||
static int
|
||||
checkentry(const struct xt_mtchk_param *par)
|
||||
{
|
||||
struct ipt_set_info_match *info = par->matchinfo;
|
||||
ip_set_id_t index;
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
|
||||
if (matchsize != IPT_ALIGN(sizeof(struct ipt_set_info_match))) {
|
||||
ip_set_printk("invalid matchsize %d", matchsize);
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
index = ip_set_get_byindex(info->match_set.index);
|
||||
|
||||
if (index == IP_SET_INVALID_ID) {
|
||||
ip_set_printk("Cannot find set indentified by id %u to match",
|
||||
info->match_set.index);
|
||||
return -ENOENT;
|
||||
}
|
||||
if (info->match_set.flags[IP_SET_MAX_BINDINGS] != 0) {
|
||||
ip_set_printk("That's nasty!");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void destroy(const struct xt_mtdtor_param *par)
|
||||
{
|
||||
struct ipt_set_info_match *info = par->matchinfo;
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
|
||||
if (matchsize != IPT_ALIGN(sizeof(struct ipt_set_info_match))) {
|
||||
ip_set_printk("invalid matchsize %d", matchsize);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
ip_set_put_byindex(info->match_set.index);
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
|
||||
static struct xt_match set_match = {
|
||||
.name = "set",
|
||||
.match = &match,
|
||||
.checkentry = &checkentry,
|
||||
.destroy = &destroy,
|
||||
.me = THIS_MODULE
|
||||
};
|
||||
#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) */
|
||||
static struct xt_match set_match = {
|
||||
.name = "set",
|
||||
.family = AF_INET,
|
||||
.match = &match,
|
||||
.matchsize = sizeof(struct ipt_set_info_match),
|
||||
.checkentry = &checkentry,
|
||||
.destroy = &destroy,
|
||||
.me = THIS_MODULE
|
||||
};
|
||||
#endif
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("iptables IP set match module");
|
||||
|
||||
static int __init ipt_ipset_init(void)
|
||||
{
|
||||
return xt_register_match(&set_match);
|
||||
}
|
||||
|
||||
static void __exit ipt_ipset_fini(void)
|
||||
{
|
||||
xt_unregister_match(&set_match);
|
||||
}
|
||||
|
||||
module_init(ipt_ipset_init);
|
||||
module_exit(ipt_ipset_fini);
|
||||
@@ -1,21 +0,0 @@
|
||||
#ifndef _IPT_SET_H
|
||||
#define _IPT_SET_H
|
||||
|
||||
#include "ip_set.h"
|
||||
|
||||
struct ipt_set_info {
|
||||
ip_set_id_t index;
|
||||
u_int32_t flags[IP_SET_MAX_BINDINGS + 1];
|
||||
};
|
||||
|
||||
/* match info */
|
||||
struct ipt_set_info_match {
|
||||
struct ipt_set_info match_set;
|
||||
};
|
||||
|
||||
struct ipt_set_info_target {
|
||||
struct ipt_set_info add_set;
|
||||
struct ipt_set_info del_set;
|
||||
};
|
||||
|
||||
#endif /*_IPT_SET_H*/
|
||||
1
extensions/ipset-5/.gitignore
vendored
1
extensions/ipset-5/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
/ipset
|
||||
@@ -1,11 +0,0 @@
|
||||
# -*- Makefile -*-
|
||||
|
||||
obj-m += xt_set.o
|
||||
obj-m += ip_set.o ip_set_bitmap_ip.o ip_set_bitmap_ipmac.o
|
||||
obj-m += ip_set_bitmap_port.o ip_set_hash_ip.o ip_set_hash_ipport.o
|
||||
obj-m += ip_set_hash_ipportip.o ip_set_hash_ipportnet.o ip_set_hash_net.o
|
||||
obj-m += ip_set_hash_netport.o ip_set_list_set.o
|
||||
|
||||
ip_set-y := ip_set_core.o ip_set_getport.o pfxlen.o
|
||||
|
||||
EXTRA_CFLAGS += -DLCONFIG_IP_SET_MAX=256
|
||||
@@ -1,24 +0,0 @@
|
||||
# -*- Makefile -*-
|
||||
|
||||
AM_CPPFLAGS = -I${srcdir}/include -DNDEBUG
|
||||
AM_CFLAGS = ${regular_CFLAGS} ${libmnl_CFLAGS}
|
||||
|
||||
include ../../Makefile.extra
|
||||
|
||||
lib_LTLIBRARIES = libipset.la
|
||||
libipset_la_SOURCES = libipset/data.c libipset/icmp.c libipset/icmpv6.c \
|
||||
libipset/mnl.c libipset/parse.c libipset/print.c \
|
||||
libipset/session.c libipset/types.c
|
||||
libipset_la_LIBADD = ${libmnl_LIBS}
|
||||
libipset_la_LDFLAGS = -version-info 1:0:0
|
||||
|
||||
sbin_PROGRAMS = ipset
|
||||
ipset_SOURCES = src/ipset.c src/errcode.c src/ui.c src/ipset_bitmap_ip.c \
|
||||
src/ipset_bitmap_ipmac.c src/ipset_bitmap_port.c \
|
||||
src/ipset_hash_ip.c src/ipset_hash_ipport.c \
|
||||
src/ipset_hash_ipportip.c src/ipset_hash_ipportnet.c \
|
||||
src/ipset_hash_net.c src/ipset_hash_netport.c \
|
||||
src/ipset_list_set.c
|
||||
ipset_LDADD = libipset.la
|
||||
|
||||
man_MANS = ipset.8
|
||||
@@ -1,2 +0,0 @@
|
||||
# -*- Makefile -*-
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
5.4.1-genl
|
||||
@@ -1,133 +0,0 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_DATA_H
|
||||
#define LIBIPSET_DATA_H
|
||||
|
||||
#include <stdbool.h> /* bool */
|
||||
#include <libipset/nf_inet_addr.h> /* union nf_inet_addr */
|
||||
|
||||
/* Data options */
|
||||
enum ipset_opt {
|
||||
IPSET_OPT_NONE = 0,
|
||||
/* Common ones */
|
||||
IPSET_SETNAME,
|
||||
IPSET_OPT_TYPENAME,
|
||||
IPSET_OPT_FAMILY,
|
||||
/* CADT options */
|
||||
IPSET_OPT_IP,
|
||||
IPSET_OPT_IP_FROM = IPSET_OPT_IP,
|
||||
IPSET_OPT_IP_TO,
|
||||
IPSET_OPT_CIDR,
|
||||
IPSET_OPT_PORT,
|
||||
IPSET_OPT_PORT_FROM = IPSET_OPT_PORT,
|
||||
IPSET_OPT_PORT_TO,
|
||||
IPSET_OPT_TIMEOUT,
|
||||
/* Create-specific options */
|
||||
IPSET_OPT_GC,
|
||||
IPSET_OPT_HASHSIZE,
|
||||
IPSET_OPT_MAXELEM,
|
||||
IPSET_OPT_NETMASK,
|
||||
IPSET_OPT_PROBES,
|
||||
IPSET_OPT_RESIZE,
|
||||
IPSET_OPT_SIZE,
|
||||
/* Create-specific options, filled out by the kernel */
|
||||
IPSET_OPT_ELEMENTS,
|
||||
IPSET_OPT_REFERENCES,
|
||||
IPSET_OPT_MEMSIZE,
|
||||
/* ADT-specific options */
|
||||
IPSET_OPT_ETHER,
|
||||
IPSET_OPT_NAME,
|
||||
IPSET_OPT_NAMEREF,
|
||||
IPSET_OPT_IP2,
|
||||
IPSET_OPT_CIDR2,
|
||||
IPSET_OPT_PROTO,
|
||||
/* Swap/rename to */
|
||||
IPSET_OPT_SETNAME2,
|
||||
/* Flags */
|
||||
IPSET_OPT_EXIST,
|
||||
IPSET_OPT_BEFORE,
|
||||
/* Internal options */
|
||||
IPSET_OPT_FLAGS = 48, /* IPSET_FLAG_EXIST| */
|
||||
IPSET_OPT_CADT_FLAGS, /* IPSET_FLAG_BEFORE| */
|
||||
IPSET_OPT_ELEM,
|
||||
IPSET_OPT_TYPE,
|
||||
IPSET_OPT_LINENO,
|
||||
IPSET_OPT_REVISION,
|
||||
IPSET_OPT_REVISION_MIN,
|
||||
IPSET_OPT_MAX,
|
||||
};
|
||||
|
||||
#define IPSET_FLAG(opt) (1LL << (opt))
|
||||
#define IPSET_FLAGS_ALL (~0LL)
|
||||
|
||||
#define IPSET_CREATE_FLAGS \
|
||||
( IPSET_FLAG(IPSET_OPT_FAMILY) \
|
||||
| IPSET_FLAG(IPSET_OPT_TYPENAME)\
|
||||
| IPSET_FLAG(IPSET_OPT_TYPE) \
|
||||
| IPSET_FLAG(IPSET_OPT_IP) \
|
||||
| IPSET_FLAG(IPSET_OPT_IP_TO) \
|
||||
| IPSET_FLAG(IPSET_OPT_CIDR) \
|
||||
| IPSET_FLAG(IPSET_OPT_PORT) \
|
||||
| IPSET_FLAG(IPSET_OPT_PORT_TO) \
|
||||
| IPSET_FLAG(IPSET_OPT_TIMEOUT) \
|
||||
| IPSET_FLAG(IPSET_OPT_GC) \
|
||||
| IPSET_FLAG(IPSET_OPT_HASHSIZE)\
|
||||
| IPSET_FLAG(IPSET_OPT_MAXELEM) \
|
||||
| IPSET_FLAG(IPSET_OPT_NETMASK) \
|
||||
| IPSET_FLAG(IPSET_OPT_PROBES) \
|
||||
| IPSET_FLAG(IPSET_OPT_RESIZE) \
|
||||
| IPSET_FLAG(IPSET_OPT_SIZE))
|
||||
|
||||
#define IPSET_ADT_FLAGS \
|
||||
( IPSET_FLAG(IPSET_OPT_IP) \
|
||||
| IPSET_FLAG(IPSET_OPT_IP_TO) \
|
||||
| IPSET_FLAG(IPSET_OPT_CIDR) \
|
||||
| IPSET_FLAG(IPSET_OPT_PORT) \
|
||||
| IPSET_FLAG(IPSET_OPT_PORT_TO) \
|
||||
| IPSET_FLAG(IPSET_OPT_TIMEOUT) \
|
||||
| IPSET_FLAG(IPSET_OPT_ETHER) \
|
||||
| IPSET_FLAG(IPSET_OPT_NAME) \
|
||||
| IPSET_FLAG(IPSET_OPT_NAMEREF) \
|
||||
| IPSET_FLAG(IPSET_OPT_IP2) \
|
||||
| IPSET_FLAG(IPSET_OPT_CIDR2) \
|
||||
| IPSET_FLAG(IPSET_OPT_PROTO) \
|
||||
| IPSET_FLAG(IPSET_OPT_CADT_FLAGS)\
|
||||
| IPSET_FLAG(IPSET_OPT_BEFORE))
|
||||
|
||||
struct ipset_data;
|
||||
|
||||
extern void ipset_strlcpy(char *dst, const char *src, size_t len);
|
||||
extern bool ipset_data_flags_test(const struct ipset_data *data,
|
||||
uint64_t flags);
|
||||
extern void ipset_data_flags_set(struct ipset_data *data, uint64_t flags);
|
||||
extern void ipset_data_flags_unset(struct ipset_data *data, uint64_t flags);
|
||||
extern bool ipset_data_ignored(struct ipset_data *data, enum ipset_opt opt);
|
||||
|
||||
extern int ipset_data_set(struct ipset_data *data, enum ipset_opt opt,
|
||||
const void *value);
|
||||
extern const void * ipset_data_get(const struct ipset_data *data,
|
||||
enum ipset_opt opt);
|
||||
|
||||
static inline bool
|
||||
ipset_data_test(const struct ipset_data *data, enum ipset_opt opt)
|
||||
{
|
||||
return ipset_data_flags_test(data, IPSET_FLAG(opt));
|
||||
}
|
||||
|
||||
/* Shortcuts */
|
||||
extern const char * ipset_data_setname(const struct ipset_data *data);
|
||||
extern uint8_t ipset_data_family(const struct ipset_data *data);
|
||||
extern uint8_t ipset_data_cidr(const struct ipset_data *data);
|
||||
extern uint64_t ipset_data_flags(const struct ipset_data *data);
|
||||
|
||||
extern void ipset_data_reset(struct ipset_data *data);
|
||||
extern struct ipset_data * ipset_data_init(void);
|
||||
extern void ipset_data_fini(struct ipset_data *data);
|
||||
|
||||
extern size_t ipset_data_sizeof(enum ipset_opt opt, uint8_t family);
|
||||
|
||||
#endif /* LIBIPSET_DATA_H */
|
||||
@@ -1,33 +0,0 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_DEBUG_H
|
||||
#define LIBIPSET_DEBUG_H
|
||||
|
||||
#ifdef IPSET_DEBUG
|
||||
#include <stdio.h>
|
||||
#include <sys/socket.h>
|
||||
#include <linux/netlink.h>
|
||||
#define D(fmt, args...) \
|
||||
fprintf(stderr, "%s: %s: " fmt "\n", __FILE__, __FUNCTION__ , ## args)
|
||||
#define IF_D(test, fmt, args...) \
|
||||
if (test) \
|
||||
D(fmt , ## args)
|
||||
|
||||
static inline void
|
||||
dump_nla(struct nlattr *nla[], int maxlen)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < maxlen; i++)
|
||||
D("nla[%u] does%s exist", i, nla[i] ? "" : " NOT");
|
||||
}
|
||||
#else
|
||||
#define D(fmt, args...)
|
||||
#define IF_D(test, fmt, args...)
|
||||
#define dump_nla(nla, maxlen)
|
||||
#endif
|
||||
|
||||
#endif /* LIBIPSET_DEBUG_H */
|
||||
@@ -1,24 +0,0 @@
|
||||
/* Copyright 2007-2008 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_ERRCODE_H
|
||||
#define LIBIPSET_ERRCODE_H
|
||||
|
||||
#include <libipset/linux_ip_set.h> /* enum ipset_cmd */
|
||||
|
||||
struct ipset_session;
|
||||
|
||||
/* Kernel error code to message table */
|
||||
struct ipset_errcode_table {
|
||||
int errcode; /* error code returned by the kernel */
|
||||
enum ipset_cmd cmd; /* issued command */
|
||||
const char *message; /* error message the code translated to */
|
||||
};
|
||||
|
||||
extern int ipset_errcode(struct ipset_session *session, enum ipset_cmd cmd,
|
||||
int errcode);
|
||||
|
||||
#endif /* LIBIPSET_ERRCODE_H */
|
||||
@@ -1,16 +0,0 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_ICMP_H
|
||||
#define LIBIPSET_ICMP_H
|
||||
|
||||
#include <stdint.h> /* uintxx_t */
|
||||
|
||||
extern const char * id_to_icmp(uint8_t id);
|
||||
extern const char * icmp_to_name(uint8_t type, uint8_t code);
|
||||
extern int name_to_icmp(const char *str, uint16_t *typecode);
|
||||
|
||||
#endif /* LIBIPSET_ICMP_H */
|
||||
@@ -1,16 +0,0 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_ICMPV6_H
|
||||
#define LIBIPSET_ICMPV6_H
|
||||
|
||||
#include <stdint.h> /* uintxx_t */
|
||||
|
||||
extern const char * id_to_icmpv6(uint8_t id);
|
||||
extern const char * icmpv6_to_name(uint8_t type, uint8_t code);
|
||||
extern int name_to_icmpv6(const char *str, uint16_t *typecode);
|
||||
|
||||
#endif /* LIBIPSET_ICMPV6_H */
|
||||
@@ -1,163 +0,0 @@
|
||||
#ifndef _IP_SET_H
|
||||
#define _IP_SET_H
|
||||
|
||||
/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
|
||||
* Patrick Schaaf <bof@bof.de>
|
||||
* Martin Josefsson <gandalf@wlug.westbo.se>
|
||||
* Copyright (C) 2003-2010 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* The protocol version */
|
||||
#define IPSET_PROTOCOL 5
|
||||
|
||||
/* The max length of strings including NUL: set and type identifiers */
|
||||
#define IPSET_MAXNAMELEN 32
|
||||
|
||||
/* Message types and commands */
|
||||
enum ipset_cmd {
|
||||
IPSET_CMD_NONE,
|
||||
IPSET_CMD_PROTOCOL, /* 1: Return protocol version */
|
||||
IPSET_CMD_CREATE, /* 2: Create a new (empty) set */
|
||||
IPSET_CMD_DESTROY, /* 3: Destroy a (empty) set */
|
||||
IPSET_CMD_FLUSH, /* 4: Remove all elements from a set */
|
||||
IPSET_CMD_RENAME, /* 5: Rename a set */
|
||||
IPSET_CMD_SWAP, /* 6: Swap two sets */
|
||||
IPSET_CMD_LIST, /* 7: List sets */
|
||||
IPSET_CMD_SAVE, /* 8: Save sets */
|
||||
IPSET_CMD_ADD, /* 9: Add an element to a set */
|
||||
IPSET_CMD_DEL, /* 10: Delete an element from a set */
|
||||
IPSET_CMD_TEST, /* 11: Test an element in a set */
|
||||
IPSET_CMD_HEADER, /* 12: Get set header data only */
|
||||
IPSET_CMD_TYPE, /* 13: Get set type */
|
||||
IPSET_MSG_MAX, /* Netlink message commands */
|
||||
|
||||
/* Commands in userspace: */
|
||||
IPSET_CMD_RESTORE = IPSET_MSG_MAX, /* 14: Enter restore mode */
|
||||
IPSET_CMD_HELP, /* 15: Get help */
|
||||
IPSET_CMD_VERSION, /* 16: Get program version */
|
||||
IPSET_CMD_QUIT, /* 17: Quit from interactive mode */
|
||||
|
||||
IPSET_CMD_MAX,
|
||||
|
||||
IPSET_CMD_COMMIT = IPSET_CMD_MAX, /* 18: Commit buffered commands */
|
||||
};
|
||||
|
||||
/* Attributes at command level */
|
||||
enum {
|
||||
IPSET_ATTR_UNSPEC,
|
||||
IPSET_ATTR_PROTOCOL, /* 1: Protocol version */
|
||||
IPSET_ATTR_SETNAME, /* 2: Name of the set */
|
||||
IPSET_ATTR_TYPENAME, /* 3: Typename */
|
||||
IPSET_ATTR_SETNAME2 = IPSET_ATTR_TYPENAME, /* Setname at rename/swap */
|
||||
IPSET_ATTR_REVISION, /* 4: Settype revision */
|
||||
IPSET_ATTR_FAMILY, /* 5: Settype family */
|
||||
IPSET_ATTR_FLAGS, /* 6: Flags at command level */
|
||||
IPSET_ATTR_DATA, /* 7: Nested attributes */
|
||||
IPSET_ATTR_ADT, /* 8: Multiple data containers */
|
||||
IPSET_ATTR_LINENO, /* 9: Restore lineno */
|
||||
IPSET_ATTR_PROTOCOL_MIN, /* 10: Minimal supported version number */
|
||||
IPSET_ATTR_REVISION_MIN = IPSET_ATTR_PROTOCOL_MIN, /* type rev min */
|
||||
__IPSET_ATTR_CMD_MAX,
|
||||
};
|
||||
#define IPSET_ATTR_CMD_MAX (__IPSET_ATTR_CMD_MAX - 1)
|
||||
|
||||
/* CADT specific attributes */
|
||||
enum {
|
||||
IPSET_ATTR_IP = IPSET_ATTR_UNSPEC + 1,
|
||||
IPSET_ATTR_IP_FROM = IPSET_ATTR_IP,
|
||||
IPSET_ATTR_IP_TO, /* 2 */
|
||||
IPSET_ATTR_CIDR, /* 3 */
|
||||
IPSET_ATTR_PORT, /* 4 */
|
||||
IPSET_ATTR_PORT_FROM = IPSET_ATTR_PORT,
|
||||
IPSET_ATTR_PORT_TO, /* 5 */
|
||||
IPSET_ATTR_TIMEOUT, /* 6 */
|
||||
IPSET_ATTR_PROTO, /* 7 */
|
||||
IPSET_ATTR_CADT_FLAGS, /* 8 */
|
||||
IPSET_ATTR_CADT_LINENO = IPSET_ATTR_LINENO, /* 9 */
|
||||
/* Reserve empty slots */
|
||||
IPSET_ATTR_CADT_MAX = 16,
|
||||
/* Create-only specific attributes */
|
||||
IPSET_ATTR_GC,
|
||||
IPSET_ATTR_HASHSIZE,
|
||||
IPSET_ATTR_MAXELEM,
|
||||
IPSET_ATTR_NETMASK,
|
||||
IPSET_ATTR_PROBES,
|
||||
IPSET_ATTR_RESIZE,
|
||||
IPSET_ATTR_SIZE,
|
||||
/* Kernel-only */
|
||||
IPSET_ATTR_ELEMENTS,
|
||||
IPSET_ATTR_REFERENCES,
|
||||
IPSET_ATTR_MEMSIZE,
|
||||
|
||||
__IPSET_ATTR_CREATE_MAX,
|
||||
};
|
||||
#define IPSET_ATTR_CREATE_MAX (__IPSET_ATTR_CREATE_MAX - 1)
|
||||
|
||||
/* ADT specific attributes */
|
||||
enum {
|
||||
IPSET_ATTR_ETHER = IPSET_ATTR_CADT_MAX + 1,
|
||||
IPSET_ATTR_NAME,
|
||||
IPSET_ATTR_NAMEREF,
|
||||
IPSET_ATTR_IP2,
|
||||
IPSET_ATTR_CIDR2,
|
||||
__IPSET_ATTR_ADT_MAX,
|
||||
};
|
||||
#define IPSET_ATTR_ADT_MAX (__IPSET_ATTR_ADT_MAX - 1)
|
||||
|
||||
/* IP specific attributes */
|
||||
enum {
|
||||
IPSET_ATTR_IPADDR_IPV4 = IPSET_ATTR_UNSPEC + 1,
|
||||
IPSET_ATTR_IPADDR_IPV6,
|
||||
__IPSET_ATTR_IPADDR_MAX,
|
||||
};
|
||||
#define IPSET_ATTR_IPADDR_MAX (__IPSET_ATTR_IPADDR_MAX - 1)
|
||||
|
||||
/* Error codes */
|
||||
enum ipset_errno {
|
||||
IPSET_ERR_PRIVATE = 128,
|
||||
IPSET_ERR_PROTOCOL,
|
||||
IPSET_ERR_FIND_TYPE,
|
||||
IPSET_ERR_MAX_SETS,
|
||||
IPSET_ERR_BUSY,
|
||||
IPSET_ERR_EXIST_SETNAME2,
|
||||
IPSET_ERR_TYPE_MISMATCH,
|
||||
IPSET_ERR_EXIST,
|
||||
IPSET_ERR_INVALID_CIDR,
|
||||
IPSET_ERR_INVALID_NETMASK,
|
||||
IPSET_ERR_INVALID_FAMILY,
|
||||
IPSET_ERR_TIMEOUT,
|
||||
IPSET_ERR_REFERENCED,
|
||||
IPSET_ERR_IPADDR_IPV4,
|
||||
IPSET_ERR_IPADDR_IPV6,
|
||||
|
||||
/* Type specific error codes */
|
||||
IPSET_ERR_TYPE_SPECIFIC = 160,
|
||||
};
|
||||
|
||||
/* Flags at command level */
|
||||
enum ipset_cmd_flags {
|
||||
IPSET_FLAG_BIT_EXIST = 0,
|
||||
IPSET_FLAG_EXIST = (1 << IPSET_FLAG_BIT_EXIST),
|
||||
};
|
||||
|
||||
/* Flags at CADT attribute level */
|
||||
enum ipset_cadt_flags {
|
||||
IPSET_FLAG_BIT_BEFORE = 0,
|
||||
IPSET_FLAG_BEFORE = (1 << IPSET_FLAG_BIT_BEFORE),
|
||||
};
|
||||
|
||||
/* Commands with settype-specific attributes */
|
||||
enum ipset_adt {
|
||||
IPSET_ADD,
|
||||
IPSET_DEL,
|
||||
IPSET_TEST,
|
||||
IPSET_ADT_MAX,
|
||||
IPSET_CREATE = IPSET_ADT_MAX,
|
||||
IPSET_CADT_MAX,
|
||||
};
|
||||
|
||||
#endif /* __IP_SET_H */
|
||||
@@ -1,12 +0,0 @@
|
||||
#ifndef __IP_SET_BITMAP_H
|
||||
#define __IP_SET_BITMAP_H
|
||||
|
||||
/* Bitmap type specific error codes */
|
||||
enum {
|
||||
/* The element is out of the range of the set */
|
||||
IPSET_ERR_BITMAP_RANGE = IPSET_ERR_TYPE_SPECIFIC,
|
||||
/* The range exceeds the size limit of the set type */
|
||||
IPSET_ERR_BITMAP_RANGE_SIZE,
|
||||
};
|
||||
|
||||
#endif /* __IP_SET_BITMAP_H */
|
||||
@@ -1,16 +0,0 @@
|
||||
#ifndef __IP_SET_HASH_H
|
||||
#define __IP_SET_HASH_H
|
||||
|
||||
/* Hash type specific error codes */
|
||||
enum {
|
||||
/* Hash is full */
|
||||
IPSET_ERR_HASH_FULL = IPSET_ERR_TYPE_SPECIFIC,
|
||||
/* Null-valued element */
|
||||
IPSET_ERR_HASH_ELEM,
|
||||
/* Invalid protocol */
|
||||
IPSET_ERR_INVALID_PROTO,
|
||||
/* Protocol missing but must be specified */
|
||||
IPSET_ERR_MISSING_PROTO,
|
||||
};
|
||||
|
||||
#endif /* __IP_SET_HASH_H */
|
||||
@@ -1,20 +0,0 @@
|
||||
#ifndef __IP_SET_LIST_H
|
||||
#define __IP_SET_LIST_H
|
||||
|
||||
/* List type specific error codes */
|
||||
enum {
|
||||
/* Set name to be added/deleted/tested does not exist. */
|
||||
IPSET_ERR_NAME = IPSET_ERR_TYPE_SPECIFIC,
|
||||
/* list:set type is not permitted to add */
|
||||
IPSET_ERR_LOOP,
|
||||
/* Missing reference set */
|
||||
IPSET_ERR_BEFORE,
|
||||
/* Reference set does not exist */
|
||||
IPSET_ERR_NAMEREF,
|
||||
/* Set is full */
|
||||
IPSET_ERR_LIST_FULL,
|
||||
/* Reference set is not added to the set */
|
||||
IPSET_ERR_REF_EXIST,
|
||||
};
|
||||
|
||||
#endif /* __IP_SET_LIST_H */
|
||||
@@ -1,29 +0,0 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_MNL_H
|
||||
#define LIBIPSET_MNL_H
|
||||
|
||||
#include <stdint.h> /* uintxx_t */
|
||||
#include <libmnl/libmnl.h> /* libmnl backend */
|
||||
|
||||
#include <libipset/transport.h> /* struct ipset_transport */
|
||||
|
||||
#ifndef NFNETLINK_V0
|
||||
#define NFNETLINK_V0 0
|
||||
|
||||
struct nfgenmsg {
|
||||
uint8_t nfgen_family;
|
||||
uint8_t version;
|
||||
uint16_t res_id;
|
||||
};
|
||||
#endif
|
||||
|
||||
extern int ipset_get_nlmsg_type(const struct nlmsghdr *nlh);
|
||||
|
||||
extern const struct ipset_transport ipset_mnl_transport;
|
||||
|
||||
#endif /* LIBIPSET_MNL_H */
|
||||
@@ -1,22 +0,0 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_NF_INET_ADDR_H
|
||||
#define LIBIPSET_NF_INET_ADDR_H
|
||||
|
||||
#include <stdint.h> /* uint32_t */
|
||||
#include <netinet/in.h> /* struct in[6]_addr */
|
||||
|
||||
/* The structure to hold IP addresses, same as in linux/netfilter.h */
|
||||
union nf_inet_addr {
|
||||
uint32_t all[4];
|
||||
uint32_t ip;
|
||||
uint32_t ip6[4];
|
||||
struct in_addr in;
|
||||
struct in6_addr in6;
|
||||
};
|
||||
|
||||
#endif /* LIBIPSET_NF_INET_ADDR_H */
|
||||
@@ -1,96 +0,0 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_PARSE_H
|
||||
#define LIBIPSET_PARSE_H
|
||||
|
||||
#include <libipset/data.h> /* enum ipset_opt */
|
||||
|
||||
/* For parsing/printing data */
|
||||
#define IPSET_CIDR_SEPARATOR "/"
|
||||
#define IPSET_RANGE_SEPARATOR "-"
|
||||
#define IPSET_ELEM_SEPARATOR ","
|
||||
#define IPSET_NAME_SEPARATOR ","
|
||||
#define IPSET_PROTO_SEPARATOR ":"
|
||||
|
||||
struct ipset_session;
|
||||
|
||||
typedef int (*ipset_parsefn)(struct ipset_session *s,
|
||||
enum ipset_opt opt, const char *str);
|
||||
|
||||
extern int ipset_parse_ether(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_port(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str,
|
||||
const char *proto);
|
||||
extern int ipset_parse_tcpudp_port(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str,
|
||||
const char *proto);
|
||||
extern int ipset_parse_tcp_port(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_single_tcp_port(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_proto(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_icmp(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_icmpv6(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_proto_port(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_family(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_ip(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_single_ip(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_net(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_range(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_netrange(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_iprange(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_ipnet(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_ip4_single6(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_name(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_before(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_after(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_setname(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_uint32(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_uint8(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_netmask(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_flag(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_typename(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_output(struct ipset_session *session,
|
||||
int opt, const char *str);
|
||||
extern int ipset_parse_ignored(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_elem(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_call_parser(struct ipset_session *session,
|
||||
ipset_parsefn parse, const char *optstr,
|
||||
enum ipset_opt optional, const char *str);
|
||||
|
||||
/* Compatibility parser functions */
|
||||
extern int ipset_parse_iptimeout(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_name_compat(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
|
||||
#endif /* LIBIPSET_PARSE_H */
|
||||
@@ -1,157 +0,0 @@
|
||||
#ifndef _NET_PFXLEN_H
|
||||
#define _NET_PFXLEN_H 1
|
||||
|
||||
#include <asm/byteorder.h>
|
||||
#ifdef HAVE_PFXLEN_H
|
||||
#include <linux/netfilter/pfxlen.h>
|
||||
#else
|
||||
|
||||
#include <libipset/nf_inet_addr.h> /* union nf_inet_addr */
|
||||
|
||||
#define E(a, b, c, d) \
|
||||
{.ip6 = { \
|
||||
__constant_htonl(a), __constant_htonl(b), \
|
||||
__constant_htonl(c), __constant_htonl(d), \
|
||||
}}
|
||||
|
||||
/*
|
||||
* This table works for both IPv4 and IPv6;
|
||||
* just use prefixlen_netmask_map[prefixlength].ip.
|
||||
*/
|
||||
const union nf_inet_addr prefixlen_netmask_map[] = {
|
||||
E(0x00000000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0x80000000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xC0000000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xE0000000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xF0000000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xF8000000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFC000000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFE000000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFF000000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFF800000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFC00000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFE00000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFF00000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFF80000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFC0000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFE0000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFF0000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFF8000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFC000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFE000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFF000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFF800, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFC00, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFE00, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFF00, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFF80, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFC0, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFE0, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFF0, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFF8, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFC, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFE, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0x80000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xC0000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xE0000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xF0000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xF8000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFC000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFE000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFF000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFF800000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFC00000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFE00000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFF00000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFF80000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFC0000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFE0000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFF0000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFF8000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFC000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFE000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFF000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFF800, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFC00, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFE00, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFF00, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFF80, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFC0, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFE0, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFF0, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFF8, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFC, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFE, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0x80000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xC0000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xE0000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xF0000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xF8000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFC000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFE000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFF800000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFC00000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFE00000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFF00000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFF80000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFC0000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFE0000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF0000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF8000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFC000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF800, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFC00, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFE00, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF00, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF80, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFC0, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFE0, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF0, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF8, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFC, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x80000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xC0000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xE0000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xF0000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xF8000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFC000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFE000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF800000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFC00000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFE00000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFF00000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFF80000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFC0000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFE0000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF0000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF8000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFC000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF800),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFC00),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFE00),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF00),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF80),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFC0),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFE0),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF0),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF8),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFC),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF),
|
||||
};
|
||||
#endif /* !HAVE_PFXLEN_H */
|
||||
|
||||
#define PFXLEN(n) prefixlen_netmask_map[n].ip
|
||||
#define PFXLEN6(n) prefixlen_netmask_map[n].ip6
|
||||
|
||||
#endif
|
||||
@@ -1,65 +0,0 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_PRINT_H
|
||||
#define LIBIPSET_PRINT_H
|
||||
|
||||
#include <libipset/data.h> /* enum ipset_opt */
|
||||
|
||||
typedef int (*ipset_printfn)(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
|
||||
extern int ipset_print_ether(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_family(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_type(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_ip(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_ipaddr(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_number(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_name(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_port(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_proto(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_icmp(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_icmpv6(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_proto_port(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_flag(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_elem(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
|
||||
#define ipset_print_portnum ipset_print_number
|
||||
|
||||
extern int ipset_print_data(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
|
||||
#endif /* LIBIPSET_PRINT_H */
|
||||
@@ -1,95 +0,0 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_SESSION_H
|
||||
#define LIBIPSET_SESSION_H
|
||||
|
||||
#include <stdbool.h> /* bool */
|
||||
#include <stdint.h> /* uintxx_t */
|
||||
#include <stdio.h> /* printf */
|
||||
|
||||
#include <libipset/linux_ip_set.h> /* enum ipset_cmd */
|
||||
|
||||
/* Report and output buffer sizes */
|
||||
#define IPSET_ERRORBUFLEN 1024
|
||||
#define IPSET_OUTBUFLEN 8192
|
||||
|
||||
struct ipset_session;
|
||||
struct ipset_data;
|
||||
struct ipset_handle;
|
||||
|
||||
extern struct ipset_data * ipset_session_data(const struct ipset_session *session);
|
||||
extern struct ipset_handle * ipset_session_handle(const struct ipset_session *session);
|
||||
extern const struct ipset_type * ipset_saved_type(const struct ipset_session *session);
|
||||
extern void ipset_session_lineno(struct ipset_session *session, uint32_t lineno);
|
||||
|
||||
enum ipset_err_type {
|
||||
IPSET_ERROR,
|
||||
IPSET_WARNING,
|
||||
};
|
||||
|
||||
extern int ipset_session_report(struct ipset_session *session,
|
||||
enum ipset_err_type type,
|
||||
const char *fmt, ...);
|
||||
|
||||
#define ipset_err(session, fmt, args...) \
|
||||
ipset_session_report(session, IPSET_ERROR, fmt , ## args)
|
||||
|
||||
#define ipset_warn(session, fmt, args...) \
|
||||
ipset_session_report(session, IPSET_WARNING, fmt , ## args)
|
||||
|
||||
#define ipset_errptr(session, fmt, args...) ({ \
|
||||
ipset_session_report(session, IPSET_ERROR, fmt , ## args); \
|
||||
NULL; \
|
||||
})
|
||||
|
||||
extern void ipset_session_report_reset(struct ipset_session *session);
|
||||
extern const char * ipset_session_error(const struct ipset_session *session);
|
||||
extern const char * ipset_session_warning(const struct ipset_session *session);
|
||||
|
||||
#define ipset_session_data_set(session, opt, value) \
|
||||
ipset_data_set(ipset_session_data(session), opt, value)
|
||||
#define ipset_session_data_get(session, opt) \
|
||||
ipset_data_get(ipset_session_data(session), opt)
|
||||
|
||||
/* Environment option flags */
|
||||
enum ipset_envopt {
|
||||
IPSET_ENV_BIT_SORTED = 0,
|
||||
IPSET_ENV_SORTED = (1 << IPSET_ENV_BIT_SORTED),
|
||||
IPSET_ENV_BIT_QUIET = 1,
|
||||
IPSET_ENV_QUIET = (1 << IPSET_ENV_BIT_QUIET),
|
||||
IPSET_ENV_BIT_RESOLVE = 2,
|
||||
IPSET_ENV_RESOLVE = (1 << IPSET_ENV_BIT_RESOLVE),
|
||||
IPSET_ENV_BIT_EXIST = 3,
|
||||
IPSET_ENV_EXIST = (1 << IPSET_ENV_BIT_EXIST),
|
||||
};
|
||||
|
||||
extern int ipset_envopt_parse(struct ipset_session *session,
|
||||
int env, const char *str);
|
||||
extern bool ipset_envopt_test(struct ipset_session *session,
|
||||
enum ipset_envopt env);
|
||||
|
||||
enum ipset_output_mode {
|
||||
IPSET_LIST_NONE,
|
||||
IPSET_LIST_PLAIN,
|
||||
IPSET_LIST_SAVE,
|
||||
IPSET_LIST_XML,
|
||||
};
|
||||
|
||||
extern int ipset_session_output(struct ipset_session *session,
|
||||
enum ipset_output_mode mode);
|
||||
|
||||
extern int ipset_commit(struct ipset_session *session);
|
||||
extern int ipset_cmd(struct ipset_session *session, enum ipset_cmd cmd,
|
||||
uint32_t lineno);
|
||||
|
||||
typedef int (*ipset_outfn)(const char *fmt, ...)
|
||||
__attribute__ ((format (printf, 1, 2)));
|
||||
|
||||
extern struct ipset_session * ipset_session_init(ipset_outfn outfn);
|
||||
extern int ipset_session_fini(struct ipset_session *session);
|
||||
|
||||
#endif /* LIBIPSET_SESSION_H */
|
||||
@@ -1,27 +0,0 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_TRANSPORT_H
|
||||
#define LIBIPSET_TRANSPORT_H
|
||||
|
||||
#include <stdint.h> /* uintxx_t */
|
||||
#include <linux/netlink.h> /* struct nlmsghdr */
|
||||
|
||||
#include <libmnl/libmnl.h> /* mnl_cb_t */
|
||||
|
||||
#include <libipset/linux_ip_set.h> /* enum ipset_cmd */
|
||||
|
||||
struct ipset_handle;
|
||||
|
||||
struct ipset_transport {
|
||||
struct ipset_handle * (*init)(mnl_cb_t *cb_ctl, void *data);
|
||||
int (*fini)(struct ipset_handle *handle);
|
||||
void (*fill_hdr)(struct ipset_handle *handle, enum ipset_cmd cmd,
|
||||
void *buffer, size_t len, uint8_t envflags);
|
||||
int (*query)(struct ipset_handle *handle, void *buffer, size_t len);
|
||||
};
|
||||
|
||||
#endif /* LIBIPSET_TRANSPORT_H */
|
||||
@@ -1,110 +0,0 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_TYPES_H
|
||||
#define LIBIPSET_TYPES_H
|
||||
|
||||
#include <stddef.h> /* NULL */
|
||||
#include <stdint.h> /* uintxx_t */
|
||||
|
||||
#include <libipset/data.h> /* enum ipset_opt */
|
||||
#include <libipset/parse.h> /* ipset_parsefn */
|
||||
#include <libipset/print.h> /* ipset_printfn */
|
||||
#include <libipset/linux_ip_set.h> /* IPSET_MAXNAMELEN */
|
||||
|
||||
#define AF_INET46 255
|
||||
|
||||
/* Family rules:
|
||||
* - AF_UNSPEC: type is family-neutral
|
||||
* - AF_INET: type supports IPv4 only
|
||||
* - AF_INET6: type supports IPv6 only
|
||||
* - AF_INET46: type supports both IPv4 and IPv6
|
||||
*/
|
||||
|
||||
/* Set dimensions */
|
||||
enum {
|
||||
IPSET_DIM_ONE, /* foo */
|
||||
IPSET_DIM_TWO, /* foo,bar */
|
||||
IPSET_DIM_THREE, /* foo,bar,fie */
|
||||
IPSET_DIM_MAX,
|
||||
};
|
||||
|
||||
/* Parser options */
|
||||
enum {
|
||||
IPSET_NO_ARG = -1,
|
||||
IPSET_OPTIONAL_ARG,
|
||||
IPSET_MANDATORY_ARG,
|
||||
IPSET_MANDATORY_ARG2,
|
||||
};
|
||||
|
||||
struct ipset_session;
|
||||
|
||||
/* Parse and print type-specific arguments */
|
||||
struct ipset_arg {
|
||||
const char *name[2]; /* option names */
|
||||
int has_arg; /* mandatory/optional/no arg */
|
||||
enum ipset_opt opt; /* argumentum type */
|
||||
ipset_parsefn parse; /* parser function */
|
||||
ipset_printfn print; /* printing function */
|
||||
};
|
||||
|
||||
/* Type check against the kernel */
|
||||
enum {
|
||||
IPSET_KERNEL_MISMATCH = -1,
|
||||
IPSET_KERNEL_CHECK_NEEDED,
|
||||
IPSET_KERNEL_OK,
|
||||
};
|
||||
|
||||
/* How element parts are parsed */
|
||||
struct ipset_elem {
|
||||
ipset_parsefn parse; /* elem parser function */
|
||||
ipset_printfn print; /* elem print function */
|
||||
enum ipset_opt opt; /* elem option */
|
||||
};
|
||||
|
||||
/* The set types in userspace
|
||||
* we could collapse 'args' and 'mandatory' to two-element lists
|
||||
* but for the readability the full list is supported.
|
||||
*/
|
||||
struct ipset_type {
|
||||
char name[IPSET_MAXNAMELEN]; /* type name */
|
||||
uint8_t revision; /* revision number */
|
||||
uint8_t family; /* supported family */
|
||||
uint8_t dimension; /* elem dimension */
|
||||
int8_t kernel_check; /* kernel check */
|
||||
bool last_elem_optional; /* last element optional */
|
||||
struct ipset_elem elem[IPSET_DIM_MAX]; /* parse elem */
|
||||
ipset_parsefn compat_parse_elem; /* compatibility parser */
|
||||
const struct ipset_arg *args[IPSET_CADT_MAX]; /* create/ADT args besides elem */
|
||||
uint64_t mandatory[IPSET_CADT_MAX]; /* create/ADT mandatory flags */
|
||||
uint64_t full[IPSET_CADT_MAX]; /* full args flags */
|
||||
const char *usage; /* terse usage */
|
||||
void (*usagefn)(void); /* additional usage */
|
||||
|
||||
struct ipset_type *next;
|
||||
const char *alias[]; /* name alias(es) */
|
||||
};
|
||||
|
||||
extern int ipset_cache_add(const char *name, const struct ipset_type *type,
|
||||
uint8_t family);
|
||||
extern int ipset_cache_del(const char *name);
|
||||
extern int ipset_cache_rename(const char *from, const char *to);
|
||||
extern int ipset_cache_swap(const char *from, const char *to);
|
||||
|
||||
extern int ipset_cache_init(void);
|
||||
extern void ipset_cache_fini(void);
|
||||
|
||||
extern const struct ipset_type * ipset_type_get(struct ipset_session *session,
|
||||
enum ipset_cmd cmd);
|
||||
extern const struct ipset_type * ipset_type_check(struct ipset_session *session);
|
||||
|
||||
extern int ipset_type_add(struct ipset_type *type);
|
||||
extern const struct ipset_type * ipset_types(void);
|
||||
extern const char * ipset_typename_resolve(const char *str);
|
||||
extern bool ipset_match_typename(const char *str,
|
||||
const struct ipset_type *t);
|
||||
|
||||
#endif /* LIBIPSET_TYPES_H */
|
||||
@@ -1,44 +0,0 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_UI_H
|
||||
#define LIBIPSET_UI_H
|
||||
|
||||
#include <libipset/linux_ip_set.h> /* enum ipset_cmd */
|
||||
|
||||
/* Commands in userspace */
|
||||
struct ipset_commands {
|
||||
enum ipset_cmd cmd;
|
||||
int has_arg;
|
||||
const char *name[2];
|
||||
const char *help;
|
||||
};
|
||||
|
||||
extern const struct ipset_commands ipset_commands[];
|
||||
|
||||
struct ipset_session;
|
||||
struct ipset_data;
|
||||
|
||||
/* Environment options */
|
||||
struct ipset_envopts {
|
||||
int flag;
|
||||
int has_arg;
|
||||
const char *name[2];
|
||||
const char *help;
|
||||
int (*parse)(struct ipset_session *s, int flag, const char *str);
|
||||
int (*print)(char *buf, unsigned int len,
|
||||
const struct ipset_data *data, int flag, uint8_t env);
|
||||
};
|
||||
|
||||
extern const struct ipset_envopts ipset_envopts[];
|
||||
|
||||
extern bool ipset_match_cmd(const char *arg, const char * const name[]);
|
||||
extern bool ipset_match_option(const char *arg, const char * const name[]);
|
||||
extern bool ipset_match_envopt(const char *arg, const char * const name[]);
|
||||
extern void ipset_shift_argv(int *argc, char *argv[], int from);
|
||||
extern void ipset_port_usage(void);
|
||||
|
||||
#endif /* LIBIPSET_UI_H */
|
||||
@@ -1,50 +0,0 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_UTILS_H
|
||||
#define LIBIPSET_UTILS_H
|
||||
|
||||
#include <string.h> /* strcmp */
|
||||
#include <netinet/in.h> /* struct in[6]_addr */
|
||||
|
||||
/* String equality tests */
|
||||
#define STREQ(a,b) (strcmp(a,b) == 0)
|
||||
#define STRNEQ(a,b,n) (strncmp(a,b,n) == 0)
|
||||
#define STRCASEQ(a,b) (strcasecmp(a,b) == 0)
|
||||
#define STRNCASEQ(a,b,n) (strncasecmp(a,b,n) == 0)
|
||||
|
||||
/* Stringify tokens */
|
||||
#define _STR(c) #c
|
||||
#define STR(c) _STR(c)
|
||||
|
||||
/* Min/max */
|
||||
#define MIN(a, b) (a < b ? a : b)
|
||||
#define MAX(a, b) (a > b ? a : b)
|
||||
|
||||
#define UNUSED __attribute__ ((unused))
|
||||
#ifdef NDEBUG
|
||||
#define ASSERT_UNUSED UNUSED
|
||||
#else
|
||||
#define ASSERT_UNUSED
|
||||
#endif
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
|
||||
#endif
|
||||
|
||||
static inline void
|
||||
in4cpy(struct in_addr *dest, const struct in_addr *src)
|
||||
{
|
||||
dest->s_addr = src->s_addr;
|
||||
}
|
||||
|
||||
static inline void
|
||||
in6cpy(struct in6_addr *dest, const struct in6_addr *src)
|
||||
{
|
||||
memcpy(dest, src, sizeof(struct in6_addr));
|
||||
}
|
||||
|
||||
#endif /* LIBIPSET_UTILS_H */
|
||||
@@ -1,464 +0,0 @@
|
||||
#ifndef _IP_SET_H
|
||||
#define _IP_SET_H
|
||||
|
||||
/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
|
||||
* Patrick Schaaf <bof@bof.de>
|
||||
* Martin Josefsson <gandalf@wlug.westbo.se>
|
||||
* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/netlink.h>
|
||||
|
||||
/* The protocol version */
|
||||
#define IPSET_PROTOCOL 5
|
||||
|
||||
/* The max length of strings including NUL: set and type identifiers */
|
||||
#define IPSET_MAXNAMELEN 32
|
||||
|
||||
/* Message types and commands */
|
||||
enum ipset_cmd {
|
||||
IPSET_CMD_NONE,
|
||||
IPSET_CMD_PROTOCOL, /* 1: Return protocol version */
|
||||
IPSET_CMD_CREATE, /* 2: Create a new (empty) set */
|
||||
IPSET_CMD_DESTROY, /* 3: Destroy a (empty) set */
|
||||
IPSET_CMD_FLUSH, /* 4: Remove all elements from a set */
|
||||
IPSET_CMD_RENAME, /* 5: Rename a set */
|
||||
IPSET_CMD_SWAP, /* 6: Swap two sets */
|
||||
IPSET_CMD_LIST, /* 7: List sets */
|
||||
IPSET_CMD_SAVE, /* 8: Save sets */
|
||||
IPSET_CMD_ADD, /* 9: Add an element to a set */
|
||||
IPSET_CMD_DEL, /* 10: Delete an element from a set */
|
||||
IPSET_CMD_TEST, /* 11: Test an element in a set */
|
||||
IPSET_CMD_HEADER, /* 12: Get set header data only */
|
||||
IPSET_CMD_TYPE, /* 13: Get set type */
|
||||
IPSET_MSG_MAX, /* Netlink message commands */
|
||||
|
||||
/* Commands in userspace: */
|
||||
IPSET_CMD_RESTORE = IPSET_MSG_MAX, /* 14: Enter restore mode */
|
||||
IPSET_CMD_HELP, /* 15: Get help */
|
||||
IPSET_CMD_VERSION, /* 16: Get program version */
|
||||
IPSET_CMD_QUIT, /* 17: Quit from interactive mode */
|
||||
|
||||
IPSET_CMD_MAX,
|
||||
|
||||
IPSET_CMD_COMMIT = IPSET_CMD_MAX, /* 18: Commit buffered commands */
|
||||
};
|
||||
|
||||
/* Attributes at command level */
|
||||
enum {
|
||||
IPSET_ATTR_UNSPEC,
|
||||
IPSET_ATTR_PROTOCOL, /* 1: Protocol version */
|
||||
IPSET_ATTR_SETNAME, /* 2: Name of the set */
|
||||
IPSET_ATTR_TYPENAME, /* 3: Typename */
|
||||
IPSET_ATTR_SETNAME2 = IPSET_ATTR_TYPENAME, /* Setname at rename/swap */
|
||||
IPSET_ATTR_REVISION, /* 4: Settype revision */
|
||||
IPSET_ATTR_FAMILY, /* 5: Settype family */
|
||||
IPSET_ATTR_FLAGS, /* 6: Flags at command level */
|
||||
IPSET_ATTR_DATA, /* 7: Nested attributes */
|
||||
IPSET_ATTR_ADT, /* 8: Multiple data containers */
|
||||
IPSET_ATTR_LINENO, /* 9: Restore lineno */
|
||||
IPSET_ATTR_PROTOCOL_MIN, /* 10: Minimal supported version number */
|
||||
IPSET_ATTR_REVISION_MIN = IPSET_ATTR_PROTOCOL_MIN, /* type rev min */
|
||||
__IPSET_ATTR_CMD_MAX,
|
||||
};
|
||||
#define IPSET_ATTR_CMD_MAX (__IPSET_ATTR_CMD_MAX - 1)
|
||||
|
||||
/* CADT specific attributes */
|
||||
enum {
|
||||
IPSET_ATTR_IP = IPSET_ATTR_UNSPEC + 1,
|
||||
IPSET_ATTR_IP_FROM = IPSET_ATTR_IP,
|
||||
IPSET_ATTR_IP_TO, /* 2 */
|
||||
IPSET_ATTR_CIDR, /* 3 */
|
||||
IPSET_ATTR_PORT, /* 4 */
|
||||
IPSET_ATTR_PORT_FROM = IPSET_ATTR_PORT,
|
||||
IPSET_ATTR_PORT_TO, /* 5 */
|
||||
IPSET_ATTR_TIMEOUT, /* 6 */
|
||||
IPSET_ATTR_PROTO, /* 7 */
|
||||
IPSET_ATTR_CADT_FLAGS, /* 8 */
|
||||
IPSET_ATTR_CADT_LINENO = IPSET_ATTR_LINENO, /* 9 */
|
||||
/* Reserve empty slots */
|
||||
IPSET_ATTR_CADT_MAX = 16,
|
||||
/* Create-only specific attributes */
|
||||
IPSET_ATTR_GC,
|
||||
IPSET_ATTR_HASHSIZE,
|
||||
IPSET_ATTR_MAXELEM,
|
||||
IPSET_ATTR_NETMASK,
|
||||
IPSET_ATTR_PROBES,
|
||||
IPSET_ATTR_RESIZE,
|
||||
IPSET_ATTR_SIZE,
|
||||
/* Kernel-only */
|
||||
IPSET_ATTR_ELEMENTS,
|
||||
IPSET_ATTR_REFERENCES,
|
||||
IPSET_ATTR_MEMSIZE,
|
||||
|
||||
__IPSET_ATTR_CREATE_MAX,
|
||||
};
|
||||
#define IPSET_ATTR_CREATE_MAX (__IPSET_ATTR_CREATE_MAX - 1)
|
||||
|
||||
/* ADT specific attributes */
|
||||
enum {
|
||||
IPSET_ATTR_ETHER = IPSET_ATTR_CADT_MAX + 1,
|
||||
IPSET_ATTR_NAME,
|
||||
IPSET_ATTR_NAMEREF,
|
||||
IPSET_ATTR_IP2,
|
||||
IPSET_ATTR_CIDR2,
|
||||
__IPSET_ATTR_ADT_MAX,
|
||||
};
|
||||
#define IPSET_ATTR_ADT_MAX (__IPSET_ATTR_ADT_MAX - 1)
|
||||
|
||||
/* IP specific attributes */
|
||||
enum {
|
||||
IPSET_ATTR_IPADDR_IPV4 = IPSET_ATTR_UNSPEC + 1,
|
||||
IPSET_ATTR_IPADDR_IPV6,
|
||||
__IPSET_ATTR_IPADDR_MAX,
|
||||
};
|
||||
#define IPSET_ATTR_IPADDR_MAX (__IPSET_ATTR_IPADDR_MAX - 1)
|
||||
|
||||
/* Error codes */
|
||||
enum ipset_errno {
|
||||
IPSET_ERR_PRIVATE = 128,
|
||||
IPSET_ERR_PROTOCOL,
|
||||
IPSET_ERR_FIND_TYPE,
|
||||
IPSET_ERR_MAX_SETS,
|
||||
IPSET_ERR_BUSY,
|
||||
IPSET_ERR_EXIST_SETNAME2,
|
||||
IPSET_ERR_TYPE_MISMATCH,
|
||||
IPSET_ERR_EXIST,
|
||||
IPSET_ERR_INVALID_CIDR,
|
||||
IPSET_ERR_INVALID_NETMASK,
|
||||
IPSET_ERR_INVALID_FAMILY,
|
||||
IPSET_ERR_TIMEOUT,
|
||||
IPSET_ERR_REFERENCED,
|
||||
IPSET_ERR_IPADDR_IPV4,
|
||||
IPSET_ERR_IPADDR_IPV6,
|
||||
|
||||
/* Type specific error codes */
|
||||
IPSET_ERR_TYPE_SPECIFIC = 160,
|
||||
};
|
||||
|
||||
/* Flags at command level */
|
||||
enum ipset_cmd_flags {
|
||||
IPSET_FLAG_BIT_EXIST = 0,
|
||||
IPSET_FLAG_EXIST = (1 << IPSET_FLAG_BIT_EXIST),
|
||||
};
|
||||
|
||||
/* Flags at CADT attribute level */
|
||||
enum ipset_cadt_flags {
|
||||
IPSET_FLAG_BIT_BEFORE = 0,
|
||||
IPSET_FLAG_BEFORE = (1 << IPSET_FLAG_BIT_BEFORE),
|
||||
};
|
||||
|
||||
/* Commands with settype-specific attributes */
|
||||
enum ipset_adt {
|
||||
IPSET_ADD,
|
||||
IPSET_DEL,
|
||||
IPSET_TEST,
|
||||
IPSET_ADT_MAX,
|
||||
IPSET_CREATE = IPSET_ADT_MAX,
|
||||
IPSET_CADT_MAX,
|
||||
};
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#include <linux/ip.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <net/netlink.h>
|
||||
|
||||
/* Sets are identified by an index in kernel space. Tweak with ip_set_id_t
|
||||
* and IPSET_INVALID_ID if you want to increase the max number of sets.
|
||||
*/
|
||||
typedef u16 ip_set_id_t;
|
||||
|
||||
#define IPSET_INVALID_ID 65535
|
||||
|
||||
enum ip_set_dim {
|
||||
IPSET_DIM_ZERO = 0,
|
||||
IPSET_DIM_ONE,
|
||||
IPSET_DIM_TWO,
|
||||
IPSET_DIM_THREE,
|
||||
/* Max dimension in elements.
|
||||
* If changed, new revision of iptables match/target is required.
|
||||
*/
|
||||
IPSET_DIM_MAX = 6,
|
||||
};
|
||||
|
||||
/* Option flags for kernel operations */
|
||||
enum ip_set_kopt {
|
||||
IPSET_INV_MATCH = (1 << IPSET_DIM_ZERO),
|
||||
IPSET_DIM_ONE_SRC = (1 << IPSET_DIM_ONE),
|
||||
IPSET_DIM_TWO_SRC = (1 << IPSET_DIM_TWO),
|
||||
IPSET_DIM_THREE_SRC = (1 << IPSET_DIM_THREE),
|
||||
};
|
||||
|
||||
/* Set features */
|
||||
enum ip_set_feature {
|
||||
IPSET_TYPE_IP_FLAG = 0,
|
||||
IPSET_TYPE_IP = (1 << IPSET_TYPE_IP_FLAG),
|
||||
IPSET_TYPE_PORT_FLAG = 1,
|
||||
IPSET_TYPE_PORT = (1 << IPSET_TYPE_PORT_FLAG),
|
||||
IPSET_TYPE_MAC_FLAG = 2,
|
||||
IPSET_TYPE_MAC = (1 << IPSET_TYPE_MAC_FLAG),
|
||||
IPSET_TYPE_IP2_FLAG = 3,
|
||||
IPSET_TYPE_IP2 = (1 << IPSET_TYPE_IP2_FLAG),
|
||||
IPSET_TYPE_NAME_FLAG = 4,
|
||||
IPSET_TYPE_NAME = (1 << IPSET_TYPE_NAME_FLAG),
|
||||
/* Strictly speaking not a feature, but a flag for dumping:
|
||||
* this settype must be dumped last */
|
||||
IPSET_DUMP_LAST_FLAG = 7,
|
||||
IPSET_DUMP_LAST = (1 << IPSET_DUMP_LAST_FLAG),
|
||||
};
|
||||
|
||||
struct ip_set;
|
||||
|
||||
typedef int (*ipset_adtfn)(struct ip_set *set, void *value, u32 timeout);
|
||||
|
||||
/* Set type, variant-specific part */
|
||||
struct ip_set_type_variant {
|
||||
/* Kernelspace: test/add/del entries
|
||||
* returns negative error code,
|
||||
* zero for no match/success to add/delete
|
||||
* positive for matching element */
|
||||
int (*kadt)(struct ip_set *set, const struct sk_buff * skb,
|
||||
enum ipset_adt adt, u8 pf, u8 dim, u8 flags);
|
||||
|
||||
/* Userspace: test/add/del entries
|
||||
* returns negative error code,
|
||||
* zero for no match/success to add/delete
|
||||
* positive for matching element */
|
||||
int (*uadt)(struct ip_set *set, struct nlattr *head, int len,
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags);
|
||||
|
||||
/* Low level add/del/test functions */
|
||||
ipset_adtfn adt[IPSET_ADT_MAX];
|
||||
|
||||
/* When adding entries and set is full, try to resize the set */
|
||||
int (*resize)(struct ip_set *set, bool retried);
|
||||
/* Destroy the set */
|
||||
void (*destroy)(struct ip_set *set);
|
||||
/* Flush the elements */
|
||||
void (*flush)(struct ip_set *set);
|
||||
/* Expire entries before listing */
|
||||
void (*expire)(struct ip_set *set);
|
||||
/* List set header data */
|
||||
int (*head)(struct ip_set *set, struct sk_buff *skb);
|
||||
/* List elements */
|
||||
int (*list)(const struct ip_set *set, struct sk_buff *skb,
|
||||
struct netlink_callback *cb);
|
||||
|
||||
/* Return true if "b" set is the same as "a"
|
||||
* according to the create set parameters */
|
||||
bool (*same_set)(const struct ip_set *a, const struct ip_set *b);
|
||||
};
|
||||
|
||||
/* The core set type structure */
|
||||
struct ip_set_type {
|
||||
struct list_head list;
|
||||
|
||||
/* Typename */
|
||||
char name[IPSET_MAXNAMELEN];
|
||||
/* Protocol version */
|
||||
u8 protocol;
|
||||
/* Set features to control swapping */
|
||||
u8 features;
|
||||
/* Set type dimension */
|
||||
u8 dimension;
|
||||
/* Supported family: may be AF_UNSPEC for both AF_INET/AF_INET6 */
|
||||
u8 family;
|
||||
/* Type revision */
|
||||
u8 revision;
|
||||
|
||||
/* Create set */
|
||||
int (*create)(struct ip_set *set,
|
||||
struct nlattr *head, int len, u32 flags);
|
||||
|
||||
/* Set this to THIS_MODULE if you are a module, otherwise NULL */
|
||||
struct module *me;
|
||||
};
|
||||
|
||||
/* register and unregister set type */
|
||||
extern int ip_set_type_register(struct ip_set_type *set_type);
|
||||
extern void ip_set_type_unregister(struct ip_set_type *set_type);
|
||||
|
||||
/* A generic IP set */
|
||||
struct ip_set {
|
||||
/* The name of the set */
|
||||
char name[IPSET_MAXNAMELEN];
|
||||
/* Lock protecting the set data */
|
||||
rwlock_t lock;
|
||||
/* References to the set */
|
||||
atomic_t ref;
|
||||
/* The core set type */
|
||||
struct ip_set_type *type;
|
||||
/* The type variant doing the real job */
|
||||
const struct ip_set_type_variant *variant;
|
||||
/* The actual INET family of the set */
|
||||
u8 family;
|
||||
/* The type specific data */
|
||||
void *data;
|
||||
};
|
||||
|
||||
/* register and unregister set references */
|
||||
extern ip_set_id_t ip_set_get_byname(const char *name, struct ip_set **set);
|
||||
extern void ip_set_put_byindex(ip_set_id_t index);
|
||||
extern const char * ip_set_name_byindex(ip_set_id_t index);
|
||||
extern ip_set_id_t ip_set_nfnl_get(const char *name);
|
||||
extern ip_set_id_t ip_set_nfnl_get_byindex(ip_set_id_t index);
|
||||
extern void ip_set_nfnl_put(ip_set_id_t index);
|
||||
|
||||
/* API for iptables set match, and SET target */
|
||||
extern int ip_set_add(ip_set_id_t id, const struct sk_buff *skb,
|
||||
u8 family, u8 dim, u8 flags);
|
||||
extern int ip_set_del(ip_set_id_t id, const struct sk_buff *skb,
|
||||
u8 family, u8 dim, u8 flags);
|
||||
extern int ip_set_test(ip_set_id_t id, const struct sk_buff *skb,
|
||||
u8 family, u8 dim, u8 flags);
|
||||
|
||||
/* Utility functions */
|
||||
extern void * ip_set_alloc(size_t size, gfp_t gfp_mask);
|
||||
extern void ip_set_free(void *members);
|
||||
extern int ip_set_get_ipaddr4(struct nlattr *nla, __be32 *ipaddr);
|
||||
extern int ip_set_get_ipaddr6(struct nlattr *nla, union nf_inet_addr *ipaddr);
|
||||
|
||||
static inline int
|
||||
ip_set_get_hostipaddr4(struct nlattr *nla, u32 *ipaddr)
|
||||
{
|
||||
__be32 ip;
|
||||
int ret = ip_set_get_ipaddr4(nla, &ip);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
*ipaddr = ntohl(ip);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Ignore IPSET_ERR_EXIST errors if asked to do so? */
|
||||
static inline bool
|
||||
ip_set_eexist(int ret, u32 flags)
|
||||
{
|
||||
return ret == -IPSET_ERR_EXIST && (flags & IPSET_FLAG_EXIST);
|
||||
}
|
||||
|
||||
/* Check the NLA_F_NET_BYTEORDER flag */
|
||||
static inline bool
|
||||
ip_set_attr_netorder(struct nlattr *tb[], int type)
|
||||
{
|
||||
return tb[type] && (tb[type]->nla_type & NLA_F_NET_BYTEORDER);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
ip_set_optattr_netorder(struct nlattr *tb[], int type)
|
||||
{
|
||||
return !tb[type] || (tb[type]->nla_type & NLA_F_NET_BYTEORDER);
|
||||
}
|
||||
|
||||
/* Useful converters */
|
||||
static inline u32
|
||||
ip_set_get_h32(const struct nlattr *attr)
|
||||
{
|
||||
return ntohl(nla_get_be32(attr));
|
||||
}
|
||||
|
||||
static inline u16
|
||||
ip_set_get_h16(const struct nlattr *attr)
|
||||
{
|
||||
return ntohs(nla_get_be16(attr));
|
||||
}
|
||||
|
||||
#define ipset_nest_start(skb, attr) nla_nest_start(skb, attr | NLA_F_NESTED)
|
||||
#define ipset_nest_end(skb, start) nla_nest_end(skb, start)
|
||||
|
||||
#ifndef NLA_PUT_NET16
|
||||
#define NLA_PUT_NET16(skb, attrtype, value) \
|
||||
NLA_PUT_BE16(skb, attrtype | NLA_F_NET_BYTEORDER, value)
|
||||
#endif
|
||||
#ifndef NLA_PUT_NET32
|
||||
#define NLA_PUT_NET32(skb, attrtype, value) \
|
||||
NLA_PUT_BE32(skb, attrtype | NLA_F_NET_BYTEORDER, value)
|
||||
#endif
|
||||
#ifndef NLA_PUT_NET64
|
||||
#define NLA_PUT_NET64(skb, attrtype, value) \
|
||||
NLA_PUT_BE64(skb, attrtype | NLA_F_NET_BYTEORDER, value)
|
||||
#endif
|
||||
|
||||
#define NLA_PUT_IPADDR4(skb, type, ipaddr) \
|
||||
do { \
|
||||
struct nlattr *__nested = ipset_nest_start(skb, type); \
|
||||
\
|
||||
if (!__nested) \
|
||||
goto nla_put_failure; \
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_IPADDR_IPV4, ipaddr); \
|
||||
ipset_nest_end(skb, __nested); \
|
||||
} while (0)
|
||||
|
||||
#define NLA_PUT_IPADDR6(skb, type, ipaddrptr) \
|
||||
do { \
|
||||
struct nlattr *__nested = ipset_nest_start(skb, type); \
|
||||
\
|
||||
if (!__nested) \
|
||||
goto nla_put_failure; \
|
||||
NLA_PUT(skb, IPSET_ATTR_IPADDR_IPV6, \
|
||||
sizeof(struct in6_addr), ipaddrptr); \
|
||||
ipset_nest_end(skb, __nested); \
|
||||
} while (0)
|
||||
|
||||
/* Get address from skbuff */
|
||||
static inline __be32
|
||||
ip4addr(const struct sk_buff *skb, bool src)
|
||||
{
|
||||
return src ? ip_hdr(skb)->saddr : ip_hdr(skb)->daddr;
|
||||
}
|
||||
|
||||
static inline void
|
||||
ip4addrptr(const struct sk_buff *skb, bool src, __be32 *addr)
|
||||
{
|
||||
*addr = src ? ip_hdr(skb)->saddr : ip_hdr(skb)->daddr;
|
||||
}
|
||||
|
||||
static inline void
|
||||
ip6addrptr(const struct sk_buff *skb, bool src, struct in6_addr *addr)
|
||||
{
|
||||
memcpy(addr, src ? &ipv6_hdr(skb)->saddr : &ipv6_hdr(skb)->daddr,
|
||||
sizeof(*addr));
|
||||
}
|
||||
|
||||
/* Calculate the bytes required to store the inclusive range of a-b */
|
||||
static inline int
|
||||
bitmap_bytes(u32 a, u32 b)
|
||||
{
|
||||
return 4 * ((((b - a + 8) / 8) + 3) / 4);
|
||||
}
|
||||
|
||||
/* Interface to iptables/ip6tables */
|
||||
|
||||
#define SO_IP_SET 83
|
||||
|
||||
union ip_set_name_index {
|
||||
char name[IPSET_MAXNAMELEN];
|
||||
ip_set_id_t index;
|
||||
};
|
||||
|
||||
#define IP_SET_OP_GET_BYNAME 0x00000006 /* Get set index by name */
|
||||
struct ip_set_req_get_set {
|
||||
unsigned op;
|
||||
unsigned version;
|
||||
union ip_set_name_index set;
|
||||
};
|
||||
|
||||
#define IP_SET_OP_GET_BYINDEX 0x00000007 /* Get set name by index */
|
||||
/* Uses ip_set_req_get_set */
|
||||
|
||||
#define IP_SET_OP_VERSION 0x00000100 /* Ask kernel version */
|
||||
struct ip_set_req_version {
|
||||
unsigned op;
|
||||
unsigned version;
|
||||
};
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /*_IP_SET_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,31 +0,0 @@
|
||||
#ifndef __IP_SET_BITMAP_H
|
||||
#define __IP_SET_BITMAP_H
|
||||
|
||||
/* Bitmap type specific error codes */
|
||||
enum {
|
||||
/* The element is out of the range of the set */
|
||||
IPSET_ERR_BITMAP_RANGE = IPSET_ERR_TYPE_SPECIFIC,
|
||||
/* The range exceeds the size limit of the set type */
|
||||
IPSET_ERR_BITMAP_RANGE_SIZE,
|
||||
};
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#define IPSET_BITMAP_MAX_RANGE 0x0000FFFF
|
||||
|
||||
/* Common functions */
|
||||
|
||||
static inline u32
|
||||
range_to_mask(u32 from, u32 to, u8 *bits)
|
||||
{
|
||||
u32 mask = 0xFFFFFFFE;
|
||||
|
||||
*bits = 32;
|
||||
while (--(*bits) > 0 && mask && (to & mask) != from)
|
||||
mask <<= 1;
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* __IP_SET_BITMAP_H */
|
||||
@@ -1,732 +0,0 @@
|
||||
/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
|
||||
* Patrick Schaaf <bof@bof.de>
|
||||
* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an IP set type: the bitmap:ip type */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/timer.h>
|
||||
#include <net/netlink.h>
|
||||
#include <net/tcp.h>
|
||||
|
||||
#include "pfxlen.h"
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_bitmap.h"
|
||||
#define IP_SET_BITMAP_TIMEOUT
|
||||
#include "ip_set_timeout.h"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("bitmap:ip type of IP sets");
|
||||
MODULE_ALIAS("ip_set_bitmap:ip");
|
||||
|
||||
/* Base variant */
|
||||
|
||||
struct bitmap_ip {
|
||||
void *members; /* the set members */
|
||||
u32 first_ip; /* host byte order, included in range */
|
||||
u32 last_ip; /* host byte order, included in range */
|
||||
u32 elements; /* number of max elements in the set */
|
||||
u32 hosts; /* number of hosts in a subnet */
|
||||
size_t memsize; /* members size */
|
||||
u8 netmask; /* subnet netmask */
|
||||
};
|
||||
|
||||
static inline u32
|
||||
ip_to_id(const struct bitmap_ip *m, u32 ip)
|
||||
{
|
||||
return ((ip & ip_set_hostmask(m->netmask)) - m->first_ip)/m->hosts;
|
||||
}
|
||||
|
||||
static inline int
|
||||
bitmap_ip_test(const struct bitmap_ip *map, u32 id)
|
||||
{
|
||||
return !!test_bit(id, map->members);
|
||||
}
|
||||
|
||||
static inline int
|
||||
bitmap_ip_add(struct bitmap_ip *map, u32 id)
|
||||
{
|
||||
if (test_and_set_bit(id, map->members))
|
||||
return -IPSET_ERR_EXIST;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
bitmap_ip_del(struct bitmap_ip *map, u32 id)
|
||||
{
|
||||
if (!test_and_clear_bit(id, map->members))
|
||||
return -IPSET_ERR_EXIST;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
|
||||
{
|
||||
struct bitmap_ip *map = set->data;
|
||||
u32 ip;
|
||||
|
||||
ip = ntohl(ip4addr(skb, flags & IPSET_DIM_ONE_SRC));
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
ip = ip_to_id(map, ip);
|
||||
|
||||
switch (adt) {
|
||||
case IPSET_TEST:
|
||||
return bitmap_ip_test(map, ip);
|
||||
case IPSET_ADD:
|
||||
return bitmap_ip_add(map, ip);
|
||||
case IPSET_DEL:
|
||||
return bitmap_ip_del(map, ip);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct nla_policy bitmap_ip_adt_policy[IPSET_ATTR_ADT_MAX+1] = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_CIDR] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int
|
||||
bitmap_ip_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
struct bitmap_ip *map = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
u32 ip, ip_to, id;
|
||||
int ret = 0;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len,
|
||||
bitmap_ip_adt_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP]))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
/* Set was defined without timeout support:
|
||||
* don't ignore the attribute silently */
|
||||
if (tb[IPSET_ATTR_TIMEOUT])
|
||||
return -IPSET_ERR_TIMEOUT;
|
||||
|
||||
if (adt == IPSET_TEST)
|
||||
return bitmap_ip_test(map, ip_to_id(map, ip));
|
||||
|
||||
if (tb[IPSET_ATTR_IP_TO]) {
|
||||
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (ip > ip_to) {
|
||||
swap(ip, ip_to);
|
||||
if (ip < map->first_ip)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
}
|
||||
} else if (tb[IPSET_ATTR_CIDR]) {
|
||||
u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
|
||||
|
||||
if (cidr > 32)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
ip &= ip_set_hostmask(cidr);
|
||||
ip_to = ip | ~ip_set_hostmask(cidr);
|
||||
} else
|
||||
ip_to = ip;
|
||||
|
||||
if (ip_to > map->last_ip)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
for (; !before(ip_to, ip); ip += map->hosts) {
|
||||
id = ip_to_id(map, ip);
|
||||
ret = adt == IPSET_ADD ? bitmap_ip_add(map, id)
|
||||
: bitmap_ip_del(map, id);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
bitmap_ip_destroy(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_ip *map = set->data;
|
||||
|
||||
ip_set_free(map->members);
|
||||
kfree(map);
|
||||
|
||||
set->data = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
bitmap_ip_flush(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_ip *map = set->data;
|
||||
|
||||
memset(map->members, 0, map->memsize);
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_head(struct ip_set *set, struct sk_buff *skb)
|
||||
{
|
||||
const struct bitmap_ip *map = set->data;
|
||||
struct nlattr *nested;
|
||||
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested)
|
||||
goto nla_put_failure;
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, htonl(map->first_ip));
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip));
|
||||
if (map->netmask != 32)
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_NETMASK, map->netmask);
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES,
|
||||
htonl(atomic_read(&set->ref) - 1));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
|
||||
htonl(sizeof(*map) + map->memsize));
|
||||
ipset_nest_end(skb, nested);
|
||||
|
||||
return 0;
|
||||
nla_put_failure:
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_list(const struct ip_set *set,
|
||||
struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
const struct bitmap_ip *map = set->data;
|
||||
struct nlattr *atd, *nested;
|
||||
u32 id, first = cb->args[2];
|
||||
|
||||
atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
|
||||
if (!atd)
|
||||
return -EFAULT;
|
||||
for (; cb->args[2] < map->elements; cb->args[2]++) {
|
||||
id = cb->args[2];
|
||||
if (!bitmap_ip_test(map, id))
|
||||
continue;
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested) {
|
||||
if (id == first) {
|
||||
nla_nest_cancel(skb, atd);
|
||||
return -EFAULT;
|
||||
} else
|
||||
goto nla_put_failure;
|
||||
}
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP,
|
||||
htonl(map->first_ip + id * map->hosts));
|
||||
ipset_nest_end(skb, nested);
|
||||
}
|
||||
ipset_nest_end(skb, atd);
|
||||
/* Set listing finished */
|
||||
cb->args[2] = 0;
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
nla_nest_cancel(skb, nested);
|
||||
ipset_nest_end(skb, atd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
bitmap_ip_same_set(const struct ip_set *a, const struct ip_set *b)
|
||||
{
|
||||
const struct bitmap_ip *x = a->data;
|
||||
const struct bitmap_ip *y = b->data;
|
||||
|
||||
return x->first_ip == y->first_ip &&
|
||||
x->last_ip == y->last_ip &&
|
||||
x->netmask == y->netmask;
|
||||
}
|
||||
|
||||
static const struct ip_set_type_variant bitmap_ip = {
|
||||
.kadt = bitmap_ip_kadt,
|
||||
.uadt = bitmap_ip_uadt,
|
||||
.destroy = bitmap_ip_destroy,
|
||||
.flush = bitmap_ip_flush,
|
||||
.head = bitmap_ip_head,
|
||||
.list = bitmap_ip_list,
|
||||
.same_set = bitmap_ip_same_set,
|
||||
};
|
||||
|
||||
/* Timeout variant */
|
||||
|
||||
struct bitmap_ip_timeout {
|
||||
unsigned long *members; /* the set members */
|
||||
u32 first_ip; /* host byte order, included in range */
|
||||
u32 last_ip; /* host byte order, included in range */
|
||||
u32 elements; /* number of max elements in the set */
|
||||
u32 hosts; /* number of hosts in a subnet */
|
||||
size_t memsize; /* members size */
|
||||
u8 netmask; /* subnet netmask */
|
||||
|
||||
u32 timeout; /* timeout parameter */
|
||||
struct timer_list gc; /* garbage collection */
|
||||
};
|
||||
|
||||
static inline bool
|
||||
bitmap_ip_timeout_test(const struct bitmap_ip_timeout *map, u32 id)
|
||||
{
|
||||
return ip_set_timeout_test(map->members[id]);
|
||||
}
|
||||
|
||||
static inline int
|
||||
bitmap_ip_timeout_add(struct bitmap_ip_timeout *map,
|
||||
u32 id, u32 timeout)
|
||||
{
|
||||
if (bitmap_ip_timeout_test(map, id))
|
||||
return -IPSET_ERR_EXIST;
|
||||
|
||||
map->members[id] = ip_set_timeout_set(timeout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
bitmap_ip_timeout_del(struct bitmap_ip_timeout *map, u32 id)
|
||||
{
|
||||
int ret = -IPSET_ERR_EXIST;
|
||||
|
||||
if (bitmap_ip_timeout_test(map, id))
|
||||
ret = 0;
|
||||
|
||||
map->members[id] = IPSET_ELEM_UNSET;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_timeout_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
|
||||
{
|
||||
struct bitmap_ip_timeout *map = set->data;
|
||||
u32 ip;
|
||||
|
||||
ip = ntohl(ip4addr(skb, flags & IPSET_DIM_ONE_SRC));
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
ip = ip_to_id((const struct bitmap_ip *)map, ip);
|
||||
|
||||
switch (adt) {
|
||||
case IPSET_TEST:
|
||||
return bitmap_ip_timeout_test(map, ip);
|
||||
case IPSET_ADD:
|
||||
return bitmap_ip_timeout_add(map, ip, map->timeout);
|
||||
case IPSET_DEL:
|
||||
return bitmap_ip_timeout_del(map, ip);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_timeout_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
struct bitmap_ip_timeout *map = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
u32 ip, ip_to, id, timeout = map->timeout;
|
||||
int ret = 0;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len,
|
||||
bitmap_ip_adt_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
if (adt == IPSET_TEST)
|
||||
return bitmap_ip_timeout_test(map,
|
||||
ip_to_id((const struct bitmap_ip *)map, ip));
|
||||
|
||||
if (tb[IPSET_ATTR_IP_TO]) {
|
||||
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (ip > ip_to) {
|
||||
swap(ip, ip_to);
|
||||
if (ip < map->first_ip)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
}
|
||||
} else if (tb[IPSET_ATTR_CIDR]) {
|
||||
u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
|
||||
|
||||
if (cidr > 32)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
ip &= ip_set_hostmask(cidr);
|
||||
ip_to = ip | ~ip_set_hostmask(cidr);
|
||||
} else
|
||||
ip_to = ip;
|
||||
|
||||
if (ip_to > map->last_ip)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT])
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
|
||||
for (; !before(ip_to, ip); ip += map->hosts) {
|
||||
id = ip_to_id((const struct bitmap_ip *)map, ip);
|
||||
ret = adt == IPSET_ADD
|
||||
? bitmap_ip_timeout_add(map, id, timeout)
|
||||
: bitmap_ip_timeout_del(map, id);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
bitmap_ip_timeout_destroy(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_ip_timeout *map = set->data;
|
||||
|
||||
del_timer_sync(&map->gc);
|
||||
ip_set_free(map->members);
|
||||
kfree(map);
|
||||
|
||||
set->data = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
bitmap_ip_timeout_flush(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_ip_timeout *map = set->data;
|
||||
|
||||
memset(map->members, IPSET_ELEM_UNSET, map->memsize);
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_timeout_head(struct ip_set *set, struct sk_buff *skb)
|
||||
{
|
||||
const struct bitmap_ip_timeout *map = set->data;
|
||||
struct nlattr *nested;
|
||||
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested)
|
||||
goto nla_put_failure;
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, htonl(map->first_ip));
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip));
|
||||
if (map->netmask != 32)
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_NETMASK, map->netmask);
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES,
|
||||
htonl(atomic_read(&set->ref) - 1));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
|
||||
htonl(sizeof(*map) + map->memsize));
|
||||
ipset_nest_end(skb, nested);
|
||||
|
||||
return 0;
|
||||
nla_put_failure:
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_timeout_list(const struct ip_set *set,
|
||||
struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
const struct bitmap_ip_timeout *map = set->data;
|
||||
struct nlattr *adt, *nested;
|
||||
u32 id, first = cb->args[2];
|
||||
const unsigned long *table = map->members;
|
||||
|
||||
adt = ipset_nest_start(skb, IPSET_ATTR_ADT);
|
||||
if (!adt)
|
||||
return -EFAULT;
|
||||
for (; cb->args[2] < map->elements; cb->args[2]++) {
|
||||
id = cb->args[2];
|
||||
if (!bitmap_ip_timeout_test(map, id))
|
||||
continue;
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested) {
|
||||
if (id == first) {
|
||||
nla_nest_cancel(skb, adt);
|
||||
return -EFAULT;
|
||||
} else
|
||||
goto nla_put_failure;
|
||||
}
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP,
|
||||
htonl(map->first_ip + id * map->hosts));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
|
||||
htonl(ip_set_timeout_get(table[id])));
|
||||
ipset_nest_end(skb, nested);
|
||||
}
|
||||
ipset_nest_end(skb, adt);
|
||||
|
||||
/* Set listing finished */
|
||||
cb->args[2] = 0;
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
nla_nest_cancel(skb, nested);
|
||||
ipset_nest_end(skb, adt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
bitmap_ip_timeout_same_set(const struct ip_set *a, const struct ip_set *b)
|
||||
{
|
||||
const struct bitmap_ip_timeout *x = a->data;
|
||||
const struct bitmap_ip_timeout *y = b->data;
|
||||
|
||||
return x->first_ip == y->first_ip &&
|
||||
x->last_ip == y->last_ip &&
|
||||
x->netmask == y->netmask &&
|
||||
x->timeout == y->timeout;
|
||||
}
|
||||
|
||||
static const struct ip_set_type_variant bitmap_ip_timeout = {
|
||||
.kadt = bitmap_ip_timeout_kadt,
|
||||
.uadt = bitmap_ip_timeout_uadt,
|
||||
.destroy = bitmap_ip_timeout_destroy,
|
||||
.flush = bitmap_ip_timeout_flush,
|
||||
.head = bitmap_ip_timeout_head,
|
||||
.list = bitmap_ip_timeout_list,
|
||||
.same_set = bitmap_ip_timeout_same_set,
|
||||
};
|
||||
|
||||
static void
|
||||
bitmap_ip_gc(unsigned long ul_set)
|
||||
{
|
||||
struct ip_set *set = (struct ip_set *) ul_set;
|
||||
struct bitmap_ip_timeout *map = set->data;
|
||||
unsigned long *table = map->members;
|
||||
u32 id;
|
||||
|
||||
/* We run parallel with other readers (test element)
|
||||
* but adding/deleting new entries is locked out */
|
||||
read_lock_bh(&set->lock);
|
||||
for (id = 0; id < map->elements; id++)
|
||||
if (ip_set_timeout_expired(table[id]))
|
||||
table[id] = IPSET_ELEM_UNSET;
|
||||
read_unlock_bh(&set->lock);
|
||||
|
||||
map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
|
||||
add_timer(&map->gc);
|
||||
}
|
||||
|
||||
static void
|
||||
bitmap_ip_gc_init(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_ip_timeout *map = set->data;
|
||||
|
||||
init_timer(&map->gc);
|
||||
map->gc.data = (unsigned long) set;
|
||||
map->gc.function = bitmap_ip_gc;
|
||||
map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
|
||||
add_timer(&map->gc);
|
||||
}
|
||||
|
||||
/* Create bitmap:ip type of sets */
|
||||
|
||||
static const struct nla_policy
|
||||
bitmap_ip_create_policy[IPSET_ATTR_CREATE_MAX+1] = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_CIDR] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_NETMASK] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static bool
|
||||
init_map_ip(struct ip_set *set, struct bitmap_ip *map,
|
||||
u32 first_ip, u32 last_ip,
|
||||
u32 elements, u32 hosts, u8 netmask)
|
||||
{
|
||||
map->members = ip_set_alloc(map->memsize, GFP_KERNEL);
|
||||
if (!map->members)
|
||||
return false;
|
||||
map->first_ip = first_ip;
|
||||
map->last_ip = last_ip;
|
||||
map->elements = elements;
|
||||
map->hosts = hosts;
|
||||
map->netmask = netmask;
|
||||
|
||||
set->data = map;
|
||||
set->family = AF_INET;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_create(struct ip_set *set, struct nlattr *head, int len,
|
||||
u32 flags)
|
||||
{
|
||||
struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1];
|
||||
u32 first_ip, last_ip, hosts, elements;
|
||||
u8 netmask = 32;
|
||||
int ret;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_CREATE_MAX, head, len,
|
||||
bitmap_ip_create_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &first_ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (tb[IPSET_ATTR_IP_TO]) {
|
||||
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &last_ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (first_ip > last_ip) {
|
||||
u32 tmp = first_ip;
|
||||
|
||||
first_ip = last_ip;
|
||||
last_ip = tmp;
|
||||
}
|
||||
} else if (tb[IPSET_ATTR_CIDR]) {
|
||||
u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
|
||||
|
||||
if (cidr >= 32)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
last_ip = first_ip | ~ip_set_hostmask(cidr);
|
||||
} else
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_NETMASK]) {
|
||||
netmask = nla_get_u8(tb[IPSET_ATTR_NETMASK]);
|
||||
|
||||
if (netmask > 32)
|
||||
return -IPSET_ERR_INVALID_NETMASK;
|
||||
|
||||
first_ip &= ip_set_hostmask(netmask);
|
||||
last_ip |= ~ip_set_hostmask(netmask);
|
||||
}
|
||||
|
||||
if (netmask == 32) {
|
||||
hosts = 1;
|
||||
elements = last_ip - first_ip + 1;
|
||||
} else {
|
||||
u8 mask_bits;
|
||||
u32 mask;
|
||||
|
||||
mask = range_to_mask(first_ip, last_ip, &mask_bits);
|
||||
|
||||
if ((!mask && (first_ip || last_ip != 0xFFFFFFFF)) ||
|
||||
netmask <= mask_bits)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
pr_debug("mask_bits %u, netmask %u\n", mask_bits, netmask);
|
||||
hosts = 2 << (32 - netmask - 1);
|
||||
elements = 2 << (netmask - mask_bits - 1);
|
||||
}
|
||||
if (elements > IPSET_BITMAP_MAX_RANGE + 1)
|
||||
return -IPSET_ERR_BITMAP_RANGE_SIZE;
|
||||
|
||||
pr_debug("hosts %u, elements %u\n", hosts, elements);
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
struct bitmap_ip_timeout *map;
|
||||
|
||||
map = kzalloc(sizeof(*map), GFP_KERNEL);
|
||||
if (!map)
|
||||
return -ENOMEM;
|
||||
|
||||
map->memsize = elements * sizeof(unsigned long);
|
||||
|
||||
if (!init_map_ip(set, (struct bitmap_ip *)map,
|
||||
first_ip, last_ip,
|
||||
elements, hosts, netmask)) {
|
||||
kfree(map);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
map->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
set->variant = &bitmap_ip_timeout;
|
||||
|
||||
bitmap_ip_gc_init(set);
|
||||
} else {
|
||||
struct bitmap_ip *map;
|
||||
|
||||
map = kzalloc(sizeof(*map), GFP_KERNEL);
|
||||
if (!map)
|
||||
return -ENOMEM;
|
||||
|
||||
map->memsize = bitmap_bytes(0, elements - 1);
|
||||
|
||||
if (!init_map_ip(set, map,
|
||||
first_ip, last_ip,
|
||||
elements, hosts, netmask)) {
|
||||
kfree(map);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
set->variant = &bitmap_ip;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ip_set_type bitmap_ip_type __read_mostly = {
|
||||
.name = "bitmap:ip",
|
||||
.protocol = IPSET_PROTOCOL,
|
||||
.features = IPSET_TYPE_IP,
|
||||
.dimension = IPSET_DIM_ONE,
|
||||
.family = AF_INET,
|
||||
.revision = 0,
|
||||
.create = bitmap_ip_create,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init
|
||||
bitmap_ip_init(void)
|
||||
{
|
||||
return ip_set_type_register(&bitmap_ip_type);
|
||||
}
|
||||
|
||||
static void __exit
|
||||
bitmap_ip_fini(void)
|
||||
{
|
||||
ip_set_type_unregister(&bitmap_ip_type);
|
||||
}
|
||||
|
||||
module_init(bitmap_ip_init);
|
||||
module_exit(bitmap_ip_fini);
|
||||
@@ -1,666 +0,0 @@
|
||||
/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
|
||||
* Patrick Schaaf <bof@bof.de>
|
||||
* Martin Josefsson <gandalf@wlug.westbo.se>
|
||||
* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an IP set type: the bitmap:ip,mac type */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/timer.h>
|
||||
#include <net/netlink.h>
|
||||
|
||||
#include "pfxlen.h"
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_timeout.h"
|
||||
#include "ip_set_bitmap.h"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("bitmap:ip,mac type of IP sets");
|
||||
MODULE_ALIAS("ip_set_bitmap:ip,mac");
|
||||
|
||||
enum {
|
||||
MAC_EMPTY, /* element is not set */
|
||||
MAC_FILLED, /* element is set with MAC */
|
||||
MAC_UNSET, /* element is set, without MAC */
|
||||
};
|
||||
|
||||
/* Type structure */
|
||||
struct bitmap_ipmac {
|
||||
void *members; /* the set members */
|
||||
u32 first_ip; /* host byte order, included in range */
|
||||
u32 last_ip; /* host byte order, included in range */
|
||||
u32 timeout; /* timeout value */
|
||||
struct timer_list gc; /* garbage collector */
|
||||
size_t dsize; /* size of element */
|
||||
};
|
||||
|
||||
/* ADT structure for generic function args */
|
||||
struct ipmac {
|
||||
u32 id; /* id in array */
|
||||
unsigned char *ether; /* ethernet address */
|
||||
};
|
||||
|
||||
/* Member element without and with timeout */
|
||||
|
||||
struct ipmac_elem {
|
||||
unsigned char ether[ETH_ALEN];
|
||||
unsigned char match;
|
||||
} __attribute__ ((aligned));
|
||||
|
||||
struct ipmac_telem {
|
||||
unsigned char ether[ETH_ALEN];
|
||||
unsigned char match;
|
||||
unsigned long timeout;
|
||||
} __attribute__ ((aligned));
|
||||
|
||||
static inline void *
|
||||
bitmap_ipmac_elem(const struct bitmap_ipmac *map, u32 id)
|
||||
{
|
||||
return (void *)((char *)map->members + id * map->dsize);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
bitmap_timeout(const struct bitmap_ipmac *map, u32 id)
|
||||
{
|
||||
const struct ipmac_telem *elem = bitmap_ipmac_elem(map, id);
|
||||
|
||||
return ip_set_timeout_test(elem->timeout);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
bitmap_expired(const struct bitmap_ipmac *map, u32 id)
|
||||
{
|
||||
const struct ipmac_telem *elem = bitmap_ipmac_elem(map, id);
|
||||
|
||||
return ip_set_timeout_expired(elem->timeout);
|
||||
}
|
||||
|
||||
static inline int
|
||||
bitmap_ipmac_exist(const struct ipmac_telem *elem)
|
||||
{
|
||||
return elem->match == MAC_UNSET ||
|
||||
(elem->match == MAC_FILLED &&
|
||||
!ip_set_timeout_expired(elem->timeout));
|
||||
}
|
||||
|
||||
/* Base variant */
|
||||
|
||||
static int
|
||||
bitmap_ipmac_test(struct ip_set *set, void *value, u32 timeout)
|
||||
{
|
||||
const struct bitmap_ipmac *map = set->data;
|
||||
const struct ipmac *data = value;
|
||||
const struct ipmac_elem *elem = bitmap_ipmac_elem(map, data->id);
|
||||
|
||||
switch (elem->match) {
|
||||
case MAC_UNSET:
|
||||
/* Trigger kernel to fill out the ethernet address */
|
||||
return -EAGAIN;
|
||||
case MAC_FILLED:
|
||||
return data->ether == NULL ||
|
||||
compare_ether_addr(data->ether, elem->ether) == 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ipmac_add(struct ip_set *set, void *value, u32 timeout)
|
||||
{
|
||||
struct bitmap_ipmac *map = set->data;
|
||||
const struct ipmac *data = value;
|
||||
struct ipmac_elem *elem = bitmap_ipmac_elem(map, data->id);
|
||||
|
||||
switch (elem->match) {
|
||||
case MAC_UNSET:
|
||||
if (!data->ether)
|
||||
/* Already added without ethernet address */
|
||||
return -IPSET_ERR_EXIST;
|
||||
/* Fill the MAC address */
|
||||
memcpy(elem->ether, data->ether, ETH_ALEN);
|
||||
elem->match = MAC_FILLED;
|
||||
break;
|
||||
case MAC_FILLED:
|
||||
return -IPSET_ERR_EXIST;
|
||||
case MAC_EMPTY:
|
||||
if (data->ether) {
|
||||
memcpy(elem->ether, data->ether, ETH_ALEN);
|
||||
elem->match = MAC_FILLED;
|
||||
} else
|
||||
elem->match = MAC_UNSET;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ipmac_del(struct ip_set *set, void *value, u32 timeout)
|
||||
{
|
||||
struct bitmap_ipmac *map = set->data;
|
||||
const struct ipmac *data = value;
|
||||
struct ipmac_elem *elem = bitmap_ipmac_elem(map, data->id);
|
||||
|
||||
if (elem->match == MAC_EMPTY)
|
||||
return -IPSET_ERR_EXIST;
|
||||
|
||||
elem->match = MAC_EMPTY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ipmac_list(const struct ip_set *set,
|
||||
struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
const struct bitmap_ipmac *map = set->data;
|
||||
const struct ipmac_elem *elem;
|
||||
struct nlattr *atd, *nested;
|
||||
u32 id, first = cb->args[2];
|
||||
u32 last = map->last_ip - map->first_ip;
|
||||
|
||||
atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
|
||||
if (!atd)
|
||||
return -EFAULT;
|
||||
for (; cb->args[2] <= last; cb->args[2]++) {
|
||||
id = cb->args[2];
|
||||
elem = bitmap_ipmac_elem(map, id);
|
||||
if (elem->match == MAC_EMPTY)
|
||||
continue;
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested) {
|
||||
if (id == first) {
|
||||
nla_nest_cancel(skb, atd);
|
||||
return -EFAULT;
|
||||
} else
|
||||
goto nla_put_failure;
|
||||
}
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP,
|
||||
htonl(map->first_ip + id));
|
||||
if (elem->match == MAC_FILLED)
|
||||
NLA_PUT(skb, IPSET_ATTR_ETHER, ETH_ALEN,
|
||||
elem->ether);
|
||||
ipset_nest_end(skb, nested);
|
||||
}
|
||||
ipset_nest_end(skb, atd);
|
||||
/* Set listing finished */
|
||||
cb->args[2] = 0;
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
nla_nest_cancel(skb, nested);
|
||||
ipset_nest_end(skb, atd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Timeout variant */
|
||||
|
||||
static int
|
||||
bitmap_ipmac_ttest(struct ip_set *set, void *value, u32 timeout)
|
||||
{
|
||||
const struct bitmap_ipmac *map = set->data;
|
||||
const struct ipmac *data = value;
|
||||
const struct ipmac_elem *elem = bitmap_ipmac_elem(map, data->id);
|
||||
|
||||
switch (elem->match) {
|
||||
case MAC_UNSET:
|
||||
/* Trigger kernel to fill out the ethernet address */
|
||||
return -EAGAIN;
|
||||
case MAC_FILLED:
|
||||
return (data->ether == NULL ||
|
||||
compare_ether_addr(data->ether, elem->ether) == 0) &&
|
||||
!bitmap_expired(map, data->id);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ipmac_tadd(struct ip_set *set, void *value, u32 timeout)
|
||||
{
|
||||
struct bitmap_ipmac *map = set->data;
|
||||
const struct ipmac *data = value;
|
||||
struct ipmac_telem *elem = bitmap_ipmac_elem(map, data->id);
|
||||
|
||||
switch (elem->match) {
|
||||
case MAC_UNSET:
|
||||
if (!data->ether)
|
||||
/* Already added without ethernet address */
|
||||
return -IPSET_ERR_EXIST;
|
||||
/* Fill the MAC address and activate the timer */
|
||||
memcpy(elem->ether, data->ether, ETH_ALEN);
|
||||
elem->match = MAC_FILLED;
|
||||
if (timeout == map->timeout)
|
||||
/* Timeout was not specified, get stored one */
|
||||
timeout = elem->timeout;
|
||||
elem->timeout = ip_set_timeout_set(timeout);
|
||||
break;
|
||||
case MAC_FILLED:
|
||||
if (!bitmap_expired(map, data->id))
|
||||
return -IPSET_ERR_EXIST;
|
||||
/* Fall through */
|
||||
case MAC_EMPTY:
|
||||
if (data->ether) {
|
||||
memcpy(elem->ether, data->ether, ETH_ALEN);
|
||||
elem->match = MAC_FILLED;
|
||||
} else
|
||||
elem->match = MAC_UNSET;
|
||||
/* If MAC is unset yet, we store plain timeout value
|
||||
* because the timer is not activated yet
|
||||
* and we can reuse it later when MAC is filled out,
|
||||
* possibly by the kernel */
|
||||
elem->timeout = data->ether ? ip_set_timeout_set(timeout)
|
||||
: timeout;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ipmac_tdel(struct ip_set *set, void *value, u32 timeout)
|
||||
{
|
||||
struct bitmap_ipmac *map = set->data;
|
||||
const struct ipmac *data = value;
|
||||
struct ipmac_telem *elem = bitmap_ipmac_elem(map, data->id);
|
||||
|
||||
if (elem->match == MAC_EMPTY || bitmap_expired(map, data->id))
|
||||
return -IPSET_ERR_EXIST;
|
||||
|
||||
elem->match = MAC_EMPTY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ipmac_tlist(const struct ip_set *set,
|
||||
struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
const struct bitmap_ipmac *map = set->data;
|
||||
const struct ipmac_telem *elem;
|
||||
struct nlattr *atd, *nested;
|
||||
u32 id, first = cb->args[2];
|
||||
u32 timeout, last = map->last_ip - map->first_ip;
|
||||
|
||||
atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
|
||||
if (!atd)
|
||||
return -EFAULT;
|
||||
for (; cb->args[2] <= last; cb->args[2]++) {
|
||||
id = cb->args[2];
|
||||
elem = bitmap_ipmac_elem(map, id);
|
||||
if (!bitmap_ipmac_exist(elem))
|
||||
continue;
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested) {
|
||||
if (id == first) {
|
||||
nla_nest_cancel(skb, atd);
|
||||
return -EFAULT;
|
||||
} else
|
||||
goto nla_put_failure;
|
||||
}
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP,
|
||||
htonl(map->first_ip + id));
|
||||
if (elem->match == MAC_FILLED)
|
||||
NLA_PUT(skb, IPSET_ATTR_ETHER, ETH_ALEN,
|
||||
elem->ether);
|
||||
timeout = elem->match == MAC_UNSET ? elem->timeout
|
||||
: ip_set_timeout_get(elem->timeout);
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(timeout));
|
||||
ipset_nest_end(skb, nested);
|
||||
}
|
||||
ipset_nest_end(skb, atd);
|
||||
/* Set listing finished */
|
||||
cb->args[2] = 0;
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
nla_nest_cancel(skb, nested);
|
||||
ipset_nest_end(skb, atd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
|
||||
{
|
||||
struct bitmap_ipmac *map = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct ipmac data;
|
||||
|
||||
data.id = ntohl(ip4addr(skb, flags & IPSET_DIM_ONE_SRC));
|
||||
if (data.id < map->first_ip || data.id > map->last_ip)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
/* Backward compatibility: we don't check the second flag */
|
||||
if (skb_mac_header(skb) < skb->head ||
|
||||
(skb_mac_header(skb) + ETH_HLEN) > skb->data)
|
||||
return -EINVAL;
|
||||
|
||||
data.id -= map->first_ip;
|
||||
data.ether = eth_hdr(skb)->h_source;
|
||||
|
||||
return adtfn(set, &data, map->timeout);
|
||||
}
|
||||
|
||||
static const struct nla_policy
|
||||
bitmap_ipmac_adt_policy[IPSET_ATTR_ADT_MAX + 1] = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_ETHER] = { .type = NLA_BINARY, .len = ETH_ALEN },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int
|
||||
bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
const struct bitmap_ipmac *map = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct ipmac data;
|
||||
u32 timeout = map->timeout;
|
||||
int ret = 0;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len,
|
||||
bitmap_ipmac_adt_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &data.id);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (data.id < map->first_ip || data.id > map->last_ip)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
if (tb[IPSET_ATTR_ETHER])
|
||||
data.ether = nla_data(tb[IPSET_ATTR_ETHER]);
|
||||
else
|
||||
data.ether = NULL;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(map->timeout))
|
||||
return -IPSET_ERR_TIMEOUT;
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
data.id -= map->first_ip;
|
||||
|
||||
ret = adtfn(set, &data, timeout);
|
||||
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
static void
|
||||
bitmap_ipmac_destroy(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_ipmac *map = set->data;
|
||||
|
||||
if (with_timeout(map->timeout))
|
||||
del_timer_sync(&map->gc);
|
||||
|
||||
ip_set_free(map->members);
|
||||
kfree(map);
|
||||
|
||||
set->data = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
bitmap_ipmac_flush(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_ipmac *map = set->data;
|
||||
|
||||
memset(map->members, 0,
|
||||
(map->last_ip - map->first_ip + 1) * map->dsize);
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ipmac_head(struct ip_set *set, struct sk_buff *skb)
|
||||
{
|
||||
const struct bitmap_ipmac *map = set->data;
|
||||
struct nlattr *nested;
|
||||
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested)
|
||||
goto nla_put_failure;
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, htonl(map->first_ip));
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES,
|
||||
htonl(atomic_read(&set->ref) - 1));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
|
||||
htonl(sizeof(*map)
|
||||
+ (map->last_ip - map->first_ip + 1) * map->dsize));
|
||||
if (with_timeout(map->timeout))
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout));
|
||||
ipset_nest_end(skb, nested);
|
||||
|
||||
return 0;
|
||||
nla_put_failure:
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static bool
|
||||
bitmap_ipmac_same_set(const struct ip_set *a, const struct ip_set *b)
|
||||
{
|
||||
const struct bitmap_ipmac *x = a->data;
|
||||
const struct bitmap_ipmac *y = b->data;
|
||||
|
||||
return x->first_ip == y->first_ip &&
|
||||
x->last_ip == y->last_ip &&
|
||||
x->timeout == y->timeout;
|
||||
}
|
||||
|
||||
static const struct ip_set_type_variant bitmap_ipmac = {
|
||||
.kadt = bitmap_ipmac_kadt,
|
||||
.uadt = bitmap_ipmac_uadt,
|
||||
.adt = {
|
||||
[IPSET_ADD] = bitmap_ipmac_add,
|
||||
[IPSET_DEL] = bitmap_ipmac_del,
|
||||
[IPSET_TEST] = bitmap_ipmac_test,
|
||||
},
|
||||
.destroy = bitmap_ipmac_destroy,
|
||||
.flush = bitmap_ipmac_flush,
|
||||
.head = bitmap_ipmac_head,
|
||||
.list = bitmap_ipmac_list,
|
||||
.same_set = bitmap_ipmac_same_set,
|
||||
};
|
||||
|
||||
static const struct ip_set_type_variant bitmap_tipmac = {
|
||||
.kadt = bitmap_ipmac_kadt,
|
||||
.uadt = bitmap_ipmac_uadt,
|
||||
.adt = {
|
||||
[IPSET_ADD] = bitmap_ipmac_tadd,
|
||||
[IPSET_DEL] = bitmap_ipmac_tdel,
|
||||
[IPSET_TEST] = bitmap_ipmac_ttest,
|
||||
},
|
||||
.destroy = bitmap_ipmac_destroy,
|
||||
.flush = bitmap_ipmac_flush,
|
||||
.head = bitmap_ipmac_head,
|
||||
.list = bitmap_ipmac_tlist,
|
||||
.same_set = bitmap_ipmac_same_set,
|
||||
};
|
||||
|
||||
static void
|
||||
bitmap_ipmac_gc(unsigned long ul_set)
|
||||
{
|
||||
struct ip_set *set = (struct ip_set *) ul_set;
|
||||
struct bitmap_ipmac *map = set->data;
|
||||
struct ipmac_telem *elem;
|
||||
u32 id, last = map->last_ip - map->first_ip;
|
||||
|
||||
/* We run parallel with other readers (test element)
|
||||
* but adding/deleting new entries is locked out */
|
||||
read_lock_bh(&set->lock);
|
||||
for (id = 0; id <= last; id++) {
|
||||
elem = bitmap_ipmac_elem(map, id);
|
||||
if (elem->match == MAC_FILLED &&
|
||||
ip_set_timeout_expired(elem->timeout))
|
||||
elem->match = MAC_EMPTY;
|
||||
}
|
||||
read_unlock_bh(&set->lock);
|
||||
|
||||
map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
|
||||
add_timer(&map->gc);
|
||||
}
|
||||
|
||||
static void
|
||||
bitmap_ipmac_gc_init(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_ipmac *map = set->data;
|
||||
|
||||
init_timer(&map->gc);
|
||||
map->gc.data = (unsigned long) set;
|
||||
map->gc.function = bitmap_ipmac_gc;
|
||||
map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
|
||||
add_timer(&map->gc);
|
||||
}
|
||||
|
||||
/* Create bitmap:ip,mac type of sets */
|
||||
|
||||
static const struct nla_policy
|
||||
bitmap_ipmac_create_policy[IPSET_ATTR_CREATE_MAX+1] = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_CIDR] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static bool
|
||||
init_map_ipmac(struct ip_set *set, struct bitmap_ipmac *map,
|
||||
u32 first_ip, u32 last_ip)
|
||||
{
|
||||
map->members = ip_set_alloc((last_ip - first_ip + 1) * map->dsize,
|
||||
GFP_KERNEL);
|
||||
if (!map->members)
|
||||
return false;
|
||||
map->first_ip = first_ip;
|
||||
map->last_ip = last_ip;
|
||||
map->timeout = IPSET_NO_TIMEOUT;
|
||||
|
||||
set->data = map;
|
||||
set->family = AF_INET;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ipmac_create(struct ip_set *set, struct nlattr *head, int len,
|
||||
u32 flags)
|
||||
{
|
||||
struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1];
|
||||
u32 first_ip, last_ip, elements;
|
||||
struct bitmap_ipmac *map;
|
||||
int ret;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_CREATE_MAX, head, len,
|
||||
bitmap_ipmac_create_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &first_ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (tb[IPSET_ATTR_IP_TO]) {
|
||||
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &last_ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (first_ip > last_ip) {
|
||||
u32 tmp = first_ip;
|
||||
|
||||
first_ip = last_ip;
|
||||
last_ip = tmp;
|
||||
}
|
||||
} else if (tb[IPSET_ATTR_CIDR]) {
|
||||
u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
|
||||
|
||||
if (cidr >= 32)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
last_ip = first_ip | ~ip_set_hostmask(cidr);
|
||||
} else
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
elements = last_ip - first_ip + 1;
|
||||
|
||||
if (elements > IPSET_BITMAP_MAX_RANGE + 1)
|
||||
return -IPSET_ERR_BITMAP_RANGE_SIZE;
|
||||
|
||||
map = kzalloc(sizeof(*map), GFP_KERNEL);
|
||||
if (!map)
|
||||
return -ENOMEM;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
map->dsize = sizeof(struct ipmac_telem);
|
||||
|
||||
if (!init_map_ipmac(set, map, first_ip, last_ip)) {
|
||||
kfree(map);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
map->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
|
||||
set->variant = &bitmap_tipmac;
|
||||
|
||||
bitmap_ipmac_gc_init(set);
|
||||
} else {
|
||||
map->dsize = sizeof(struct ipmac_elem);
|
||||
|
||||
if (!init_map_ipmac(set, map, first_ip, last_ip)) {
|
||||
kfree(map);
|
||||
return -ENOMEM;
|
||||
}
|
||||
set->variant = &bitmap_ipmac;
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ip_set_type bitmap_ipmac_type = {
|
||||
.name = "bitmap:ip,mac",
|
||||
.protocol = IPSET_PROTOCOL,
|
||||
.features = IPSET_TYPE_IP | IPSET_TYPE_MAC,
|
||||
.dimension = IPSET_DIM_TWO,
|
||||
.family = AF_INET,
|
||||
.revision = 0,
|
||||
.create = bitmap_ipmac_create,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init
|
||||
bitmap_ipmac_init(void)
|
||||
{
|
||||
return ip_set_type_register(&bitmap_ipmac_type);
|
||||
}
|
||||
|
||||
static void __exit
|
||||
bitmap_ipmac_fini(void)
|
||||
{
|
||||
ip_set_type_unregister(&bitmap_ipmac_type);
|
||||
}
|
||||
|
||||
module_init(bitmap_ipmac_init);
|
||||
module_exit(bitmap_ipmac_fini);
|
||||
@@ -1,649 +0,0 @@
|
||||
/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an IP set type: the bitmap:port type */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/udp.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/timer.h>
|
||||
#include <net/netlink.h>
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_bitmap.h"
|
||||
#include "ip_set_getport.h"
|
||||
#define IP_SET_BITMAP_TIMEOUT
|
||||
#include "ip_set_timeout.h"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("bitmap:port type of IP sets");
|
||||
MODULE_ALIAS("ip_set_bitmap:port");
|
||||
|
||||
/* Base variant */
|
||||
|
||||
struct bitmap_port {
|
||||
void *members; /* the set members */
|
||||
u16 first_port; /* host byte order, included in range */
|
||||
u16 last_port; /* host byte order, included in range */
|
||||
size_t memsize; /* members size */
|
||||
};
|
||||
|
||||
static inline int
|
||||
bitmap_port_test(const struct bitmap_port *map, u16 id)
|
||||
{
|
||||
return !!test_bit(id, map->members);
|
||||
}
|
||||
|
||||
static inline int
|
||||
bitmap_port_add(struct bitmap_port *map, u16 id)
|
||||
{
|
||||
if (test_and_set_bit(id, map->members))
|
||||
return -IPSET_ERR_EXIST;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_del(struct bitmap_port *map, u16 id)
|
||||
{
|
||||
if (!test_and_clear_bit(id, map->members))
|
||||
return -IPSET_ERR_EXIST;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
|
||||
{
|
||||
struct bitmap_port *map = set->data;
|
||||
__be16 __port;
|
||||
u16 port = 0;
|
||||
|
||||
if (!ip_set_get_ip_port(skb, pf, flags & IPSET_DIM_ONE_SRC, &__port))
|
||||
return -EINVAL;
|
||||
|
||||
port = ntohs(__port);
|
||||
|
||||
if (port < map->first_port || port > map->last_port)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
port -= map->first_port;
|
||||
|
||||
switch (adt) {
|
||||
case IPSET_TEST:
|
||||
return bitmap_port_test(map, port);
|
||||
case IPSET_ADD:
|
||||
return bitmap_port_add(map, port);
|
||||
case IPSET_DEL:
|
||||
return bitmap_port_del(map, port);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct nla_policy bitmap_port_adt_policy[IPSET_ATTR_ADT_MAX+1] = {
|
||||
[IPSET_ATTR_PORT] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_PORT_TO] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int
|
||||
bitmap_port_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
struct bitmap_port *map = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
u32 port; /* wraparound */
|
||||
u16 id, port_to;
|
||||
int ret = 0;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len,
|
||||
bitmap_port_adt_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
port = ip_set_get_h16(tb[IPSET_ATTR_PORT]);
|
||||
if (port < map->first_port || port > map->last_port)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT])
|
||||
return -IPSET_ERR_TIMEOUT;
|
||||
|
||||
if (adt == IPSET_TEST)
|
||||
return bitmap_port_test(map, port - map->first_port);
|
||||
|
||||
if (tb[IPSET_ATTR_PORT_TO]) {
|
||||
port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
|
||||
if (port > port_to) {
|
||||
swap(port, port_to);
|
||||
if (port < map->first_port)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
}
|
||||
} else
|
||||
port_to = port;
|
||||
|
||||
if (port_to > map->last_port)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
for (; port <= port_to; port++) {
|
||||
id = port - map->first_port;
|
||||
ret = adt == IPSET_ADD ? bitmap_port_add(map, id)
|
||||
: bitmap_port_del(map, id);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
bitmap_port_destroy(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_port *map = set->data;
|
||||
|
||||
ip_set_free(map->members);
|
||||
kfree(map);
|
||||
|
||||
set->data = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
bitmap_port_flush(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_port *map = set->data;
|
||||
|
||||
memset(map->members, 0, map->memsize);
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_head(struct ip_set *set, struct sk_buff *skb)
|
||||
{
|
||||
const struct bitmap_port *map = set->data;
|
||||
struct nlattr *nested;
|
||||
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested)
|
||||
goto nla_put_failure;
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, htons(map->first_port));
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT_TO, htons(map->last_port));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES,
|
||||
htonl(atomic_read(&set->ref) - 1));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
|
||||
htonl(sizeof(*map) + map->memsize));
|
||||
ipset_nest_end(skb, nested);
|
||||
|
||||
return 0;
|
||||
nla_put_failure:
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_list(const struct ip_set *set,
|
||||
struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
const struct bitmap_port *map = set->data;
|
||||
struct nlattr *atd, *nested;
|
||||
u16 id, first = cb->args[2];
|
||||
u16 last = map->last_port - map->first_port;
|
||||
|
||||
atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
|
||||
if (!atd)
|
||||
return -EFAULT;
|
||||
for (; cb->args[2] <= last; cb->args[2]++) {
|
||||
id = cb->args[2];
|
||||
if (!test_bit(id, map->members))
|
||||
continue;
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested) {
|
||||
if (id == first) {
|
||||
nla_nest_cancel(skb, atd);
|
||||
return -EFAULT;
|
||||
} else
|
||||
goto nla_put_failure;
|
||||
}
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT,
|
||||
htons(map->first_port + id));
|
||||
ipset_nest_end(skb, nested);
|
||||
}
|
||||
ipset_nest_end(skb, atd);
|
||||
/* Set listing finished */
|
||||
cb->args[2] = 0;
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
nla_nest_cancel(skb, nested);
|
||||
ipset_nest_end(skb, atd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
bitmap_port_same_set(const struct ip_set *a, const struct ip_set *b)
|
||||
{
|
||||
const struct bitmap_port *x = a->data;
|
||||
const struct bitmap_port *y = b->data;
|
||||
|
||||
return x->first_port == y->first_port &&
|
||||
x->last_port == y->last_port;
|
||||
}
|
||||
|
||||
static const struct ip_set_type_variant bitmap_port = {
|
||||
.kadt = bitmap_port_kadt,
|
||||
.uadt = bitmap_port_uadt,
|
||||
.destroy = bitmap_port_destroy,
|
||||
.flush = bitmap_port_flush,
|
||||
.head = bitmap_port_head,
|
||||
.list = bitmap_port_list,
|
||||
.same_set = bitmap_port_same_set,
|
||||
};
|
||||
|
||||
/* Timeout variant */
|
||||
|
||||
struct bitmap_port_timeout {
|
||||
unsigned long *members; /* the set members */
|
||||
u16 first_port; /* host byte order, included in range */
|
||||
u16 last_port; /* host byte order, included in range */
|
||||
size_t memsize; /* members size */
|
||||
|
||||
u32 timeout; /* timeout parameter */
|
||||
struct timer_list gc; /* garbage collection */
|
||||
};
|
||||
|
||||
static inline bool
|
||||
bitmap_port_timeout_test(const struct bitmap_port_timeout *map, u16 id)
|
||||
{
|
||||
return ip_set_timeout_test(map->members[id]);
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_timeout_add(const struct bitmap_port_timeout *map,
|
||||
u16 id, u32 timeout)
|
||||
{
|
||||
if (bitmap_port_timeout_test(map, id))
|
||||
return -IPSET_ERR_EXIST;
|
||||
|
||||
map->members[id] = ip_set_timeout_set(timeout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_timeout_del(const struct bitmap_port_timeout *map,
|
||||
u16 id)
|
||||
{
|
||||
int ret = -IPSET_ERR_EXIST;
|
||||
|
||||
if (bitmap_port_timeout_test(map, id))
|
||||
ret = 0;
|
||||
|
||||
map->members[id] = IPSET_ELEM_UNSET;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_timeout_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
|
||||
{
|
||||
struct bitmap_port_timeout *map = set->data;
|
||||
__be16 __port;
|
||||
u16 port = 0;
|
||||
|
||||
if (!ip_set_get_ip_port(skb, pf, flags & IPSET_DIM_ONE_SRC, &__port))
|
||||
return -EINVAL;
|
||||
|
||||
port = ntohs(__port);
|
||||
|
||||
if (port < map->first_port || port > map->last_port)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
port -= map->first_port;
|
||||
|
||||
switch (adt) {
|
||||
case IPSET_TEST:
|
||||
return bitmap_port_timeout_test(map, port);
|
||||
case IPSET_ADD:
|
||||
return bitmap_port_timeout_add(map, port, map->timeout);
|
||||
case IPSET_DEL:
|
||||
return bitmap_port_timeout_del(map, port);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_timeout_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
const struct bitmap_port_timeout *map = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
u16 id, port_to;
|
||||
u32 port, timeout = map->timeout; /* wraparound */
|
||||
int ret = 0;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len,
|
||||
bitmap_port_adt_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
port = ip_set_get_h16(tb[IPSET_ATTR_PORT]);
|
||||
if (port < map->first_port || port > map->last_port)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
if (adt == IPSET_TEST)
|
||||
return bitmap_port_timeout_test(map, port - map->first_port);
|
||||
|
||||
if (tb[IPSET_ATTR_PORT_TO]) {
|
||||
port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
|
||||
if (port > port_to) {
|
||||
swap(port, port_to);
|
||||
if (port < map->first_port)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
}
|
||||
} else
|
||||
port_to = port;
|
||||
|
||||
if (port_to > map->last_port)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT])
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
|
||||
for (; port <= port_to; port++) {
|
||||
id = port - map->first_port;
|
||||
ret = adt == IPSET_ADD
|
||||
? bitmap_port_timeout_add(map, id, timeout)
|
||||
: bitmap_port_timeout_del(map, id);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
bitmap_port_timeout_destroy(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_port_timeout *map = set->data;
|
||||
|
||||
del_timer_sync(&map->gc);
|
||||
ip_set_free(map->members);
|
||||
kfree(map);
|
||||
|
||||
set->data = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
bitmap_port_timeout_flush(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_port_timeout *map = set->data;
|
||||
|
||||
memset(map->members, 0, map->memsize);
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_timeout_head(struct ip_set *set, struct sk_buff *skb)
|
||||
{
|
||||
const struct bitmap_port_timeout *map = set->data;
|
||||
struct nlattr *nested;
|
||||
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested)
|
||||
goto nla_put_failure;
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, htons(map->first_port));
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT_TO, htons(map->last_port));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT , htonl(map->timeout));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES,
|
||||
htonl(atomic_read(&set->ref) - 1));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
|
||||
htonl(sizeof(*map) + map->memsize));
|
||||
ipset_nest_end(skb, nested);
|
||||
|
||||
return 0;
|
||||
nla_put_failure:
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_timeout_list(const struct ip_set *set,
|
||||
struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
const struct bitmap_port_timeout *map = set->data;
|
||||
struct nlattr *adt, *nested;
|
||||
u16 id, first = cb->args[2];
|
||||
u16 last = map->last_port - map->first_port;
|
||||
const unsigned long *table = map->members;
|
||||
|
||||
adt = ipset_nest_start(skb, IPSET_ATTR_ADT);
|
||||
if (!adt)
|
||||
return -EFAULT;
|
||||
for (; cb->args[2] <= last; cb->args[2]++) {
|
||||
id = cb->args[2];
|
||||
if (!bitmap_port_timeout_test(map, id))
|
||||
continue;
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested) {
|
||||
if (id == first) {
|
||||
nla_nest_cancel(skb, adt);
|
||||
return -EFAULT;
|
||||
} else
|
||||
goto nla_put_failure;
|
||||
}
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT,
|
||||
htons(map->first_port + id));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
|
||||
htonl(ip_set_timeout_get(table[id])));
|
||||
ipset_nest_end(skb, nested);
|
||||
}
|
||||
ipset_nest_end(skb, adt);
|
||||
|
||||
/* Set listing finished */
|
||||
cb->args[2] = 0;
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
nla_nest_cancel(skb, nested);
|
||||
ipset_nest_end(skb, adt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
bitmap_port_timeout_same_set(const struct ip_set *a, const struct ip_set *b)
|
||||
{
|
||||
const struct bitmap_port_timeout *x = a->data;
|
||||
const struct bitmap_port_timeout *y = b->data;
|
||||
|
||||
return x->first_port == y->first_port &&
|
||||
x->last_port == y->last_port &&
|
||||
x->timeout == y->timeout;
|
||||
}
|
||||
|
||||
static const struct ip_set_type_variant bitmap_port_timeout = {
|
||||
.kadt = bitmap_port_timeout_kadt,
|
||||
.uadt = bitmap_port_timeout_uadt,
|
||||
.destroy = bitmap_port_timeout_destroy,
|
||||
.flush = bitmap_port_timeout_flush,
|
||||
.head = bitmap_port_timeout_head,
|
||||
.list = bitmap_port_timeout_list,
|
||||
.same_set = bitmap_port_timeout_same_set,
|
||||
};
|
||||
|
||||
static void
|
||||
bitmap_port_gc(unsigned long ul_set)
|
||||
{
|
||||
struct ip_set *set = (struct ip_set *) ul_set;
|
||||
struct bitmap_port_timeout *map = set->data;
|
||||
unsigned long *table = map->members;
|
||||
u32 id; /* wraparound */
|
||||
u16 last = map->last_port - map->first_port;
|
||||
|
||||
/* We run parallel with other readers (test element)
|
||||
* but adding/deleting new entries is locked out */
|
||||
read_lock_bh(&set->lock);
|
||||
for (id = 0; id <= last; id++)
|
||||
if (ip_set_timeout_expired(table[id]))
|
||||
table[id] = IPSET_ELEM_UNSET;
|
||||
read_unlock_bh(&set->lock);
|
||||
|
||||
map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
|
||||
add_timer(&map->gc);
|
||||
}
|
||||
|
||||
static void
|
||||
bitmap_port_gc_init(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_port_timeout *map = set->data;
|
||||
|
||||
init_timer(&map->gc);
|
||||
map->gc.data = (unsigned long) set;
|
||||
map->gc.function = bitmap_port_gc;
|
||||
map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
|
||||
add_timer(&map->gc);
|
||||
}
|
||||
|
||||
/* Create bitmap:ip type of sets */
|
||||
|
||||
static const struct nla_policy
|
||||
bitmap_port_create_policy[IPSET_ATTR_CREATE_MAX+1] = {
|
||||
[IPSET_ATTR_PORT] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_PORT_TO] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static bool
|
||||
init_map_port(struct ip_set *set, struct bitmap_port *map,
|
||||
u16 first_port, u16 last_port)
|
||||
{
|
||||
map->members = ip_set_alloc(map->memsize, GFP_KERNEL);
|
||||
if (!map->members)
|
||||
return false;
|
||||
map->first_port = first_port;
|
||||
map->last_port = last_port;
|
||||
|
||||
set->data = map;
|
||||
set->family = AF_UNSPEC;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_create(struct ip_set *set, struct nlattr *head, int len,
|
||||
u32 flags)
|
||||
{
|
||||
struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1];
|
||||
u16 first_port, last_port;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_CREATE_MAX, head, len,
|
||||
bitmap_port_create_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
|
||||
!ip_set_attr_netorder(tb, IPSET_ATTR_PORT_TO) ||
|
||||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
first_port = ip_set_get_h16(tb[IPSET_ATTR_PORT]);
|
||||
last_port = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
|
||||
if (first_port > last_port) {
|
||||
u16 tmp = first_port;
|
||||
|
||||
first_port = last_port;
|
||||
last_port = tmp;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
struct bitmap_port_timeout *map;
|
||||
|
||||
map = kzalloc(sizeof(*map), GFP_KERNEL);
|
||||
if (!map)
|
||||
return -ENOMEM;
|
||||
|
||||
map->memsize = (last_port - first_port + 1)
|
||||
* sizeof(unsigned long);
|
||||
|
||||
if (!init_map_port(set, (struct bitmap_port *) map,
|
||||
first_port, last_port)) {
|
||||
kfree(map);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
map->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
set->variant = &bitmap_port_timeout;
|
||||
|
||||
bitmap_port_gc_init(set);
|
||||
} else {
|
||||
struct bitmap_port *map;
|
||||
|
||||
map = kzalloc(sizeof(*map), GFP_KERNEL);
|
||||
if (!map)
|
||||
return -ENOMEM;
|
||||
|
||||
map->memsize = bitmap_bytes(0, last_port - first_port);
|
||||
pr_debug("memsize: %zu\n", map->memsize);
|
||||
if (!init_map_port(set, map, first_port, last_port)) {
|
||||
kfree(map);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
set->variant = &bitmap_port;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ip_set_type bitmap_port_type = {
|
||||
.name = "bitmap:port",
|
||||
.protocol = IPSET_PROTOCOL,
|
||||
.features = IPSET_TYPE_PORT,
|
||||
.dimension = IPSET_DIM_ONE,
|
||||
.family = AF_UNSPEC,
|
||||
.revision = 0,
|
||||
.create = bitmap_port_create,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init
|
||||
bitmap_port_init(void)
|
||||
{
|
||||
return ip_set_type_register(&bitmap_port_type);
|
||||
}
|
||||
|
||||
static void __exit
|
||||
bitmap_port_fini(void)
|
||||
{
|
||||
ip_set_type_unregister(&bitmap_port_type);
|
||||
}
|
||||
|
||||
module_init(bitmap_port_init);
|
||||
module_exit(bitmap_port_fini);
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user