Compare commits

...

55 Commits
v1.32 ... v1.34

Author SHA1 Message Date
Jan Engelhardt
b60f8f1de2 Xtables-addons 1.34 2011-04-07 15:15:39 +02:00
Jan Engelhardt
509953daec build: notify of unsupported Linux kernel versions 2011-04-04 00:18:54 +02:00
Jan Engelhardt
c53a86874d build: notify of unsupported Linux kernel versions
I would like to move forward a bit, and today, two issues prompted
me to start removing old code:

* make 3.82 does not like mixing normal rules with implicit rules,
  which rejects Makefiles of Linux kernels before 2.6.34.

* xt_DNETMAP uses functionality not available before 2.6.29.
2011-04-04 00:10:23 +02:00
Jan Engelhardt
309b960012 Merge branch 'dnetmap' 2011-04-03 23:59:18 +02:00
Marek Kierdelewicz
f4882ca029 xt_DNETMAP: support for kernels below 2.6.34 2011-04-03 23:50:10 +02:00
Jan Engelhardt
8fd3eb56eb xt_DNETMAP: add missing alias 2011-04-03 23:49:53 +02:00
Jan Engelhardt
94574fb829 Merge branch 'pknock'
Kernel warnings and oopses resulting from the inversion (HEAD^2)
reported by user mancha (mancha!debian-tor@gateway/tor-sasl/mancha) on
irc.freenode.net/#netfilter.
2011-02-28 20:51:25 +01:00
Jan Engelhardt
32871bad39 xt_pknock: avoid inversion of rule lookup that led to warnings
Commit v1.18-48-g58839b9 had this screwed up.
2011-02-25 01:22:16 +01:00
Jan Engelhardt
0ba44bd461 xt_pknock: avoid crash when hash TFM could not be allocated 2011-02-25 01:22:16 +01:00
Jan Engelhardt
d4e6e3d155 xt_pknock: indent 2011-02-25 01:20:12 +01:00
Jan Engelhardt
9f59f21614 Xtables-addons 1.33 2011-02-02 05:21:56 +01:00
Jan Engelhardt
7a8bfed52c xt_geoip: keep compiling for <= 2.6.23 2011-02-02 05:21:56 +01:00
Jan Engelhardt
1edc9b943b build: do not forget including path for compat_user.h 2011-02-02 05:15:09 +01:00
Jan Engelhardt
ebfa77795a build: preliminary support for iptables 1.4.11 2011-02-02 05:09:58 +01:00
Jan Engelhardt
4a8aa505c4 build: support for Linux up to 2.6.38
No API changes that needed to be taken care of, so just bump the
version check in configure.ac.
2011-02-02 04:59:58 +01:00
Jan Engelhardt
4654ee127f xt_DNETMAP: disable by default for now
I wanted xt_DNETMAP to be included in the release already, though
because it only compiled with Linux >= 2.6.34 currently (some work
will be needed), deactive it by default.
2011-02-02 04:55:34 +01:00
Jan Engelhardt
a7a77d7146 Merge branch 'dnetmap' 2011-02-02 04:54:25 +01:00
Jan Engelhardt
2a61ca7d4b build: fix missing inclusion of dependency rules 2011-02-02 04:53:30 +01:00
Jan Engelhardt
39de351a91 libxt_geoip: update manual page with new tool syntax 2011-02-02 04:51:38 +01:00
Jan Engelhardt
07bf41a294 Merge branch 'geoip' 2011-02-02 04:48:40 +01:00
Jan Engelhardt
07cd29d9ce xt_geoip: IPv6 support 2011-02-02 04:47:28 +01:00
Jan Engelhardt
eb9634aee6 xt_geoip: v4/v6 name preparations 2011-02-02 04:43:36 +01:00
Jan Engelhardt
19f241a09c xt_geoip: cleanups, preparations for IPv6 geoip 2011-02-02 01:55:09 +01:00
Jan Engelhardt
0a29c1d32f xt_DNETMAP: style considerations
Clean up the files a bit. For one, break dangerously right-indented
function headers, and correct some spaces that should be tab.
2011-01-27 03:23:22 +01:00
Jan Engelhardt
93a17fdde0 geoipdb builder: get rid of some global variables 2011-01-27 03:05:30 +01:00
Jan Engelhardt
80444b0d31 geoipdb builder: separate into functions 2011-01-27 03:02:39 +01:00
Jan Engelhardt
f180c0e5c6 geoipdb tools: IPv6 support 2011-01-27 02:57:00 +01:00
Jan Engelhardt
ca8ebe4467 Merge remote branch 'origin/master' 2011-01-22 18:10:18 +01:00
Jan Engelhardt
e82410735a xt_DNETMAP: use compat_xtables layer to run on older kernels 2011-01-22 18:09:15 +01:00
Jan Engelhardt
89e72bb0f4 doc: Add version information to README 2011-01-22 17:34:48 +01:00
Jan Engelhardt
77b9f2024c Merge branch 'account' 2011-01-22 17:34:43 +01:00
Jan Engelhardt
0edb572f6e ACCOUNT: update to 1.16
There are no changes to integrate from ipt_ACCOUNT because xt_ACCOUT
already, by way of the compat_xtables layer, supports multiple kernel
versions.
2011-01-22 17:34:06 +01:00
Jan Engelhardt
8b1ff64b8b Merge branch 'pknock' 2011-01-22 17:33:45 +01:00
Jan Engelhardt
ebb61aa3c9 pknock: resolve warnings about unused variables 2011-01-22 17:32:38 +01:00
Jan Engelhardt
bd2e6108f3 pknock: use build flags in pknock Makefile 2011-01-22 17:31:53 +01:00
Jan Engelhardt
288492c820 xt_DNETMAP: order mconfig 2011-01-22 17:24:51 +01:00
Jan Engelhardt
e425c8f277 xt_DNETMAP: use more appropriate format specifiers
Substitute %i -> %d. Use %u for prefix length.
2011-01-22 17:23:13 +01:00
Jan Engelhardt
e3e88827fb xt_DNETMAP: use permission mnemonic constants 2011-01-22 15:59:15 +01:00
Jan Engelhardt
6c709fd682 Merge branch 'ipset-5' 2011-01-22 15:56:57 +01:00
Jan Engelhardt
1b53724a61 ipset: update to 5.4.1 2011-01-22 15:56:44 +01:00
Jan Engelhardt
983b28fe8e Merge branch 'ipset-5' 2011-01-21 23:26:11 +01:00
Jan Engelhardt
3141b2ff86 ipset: update to 5.3 2011-01-19 02:55:23 +01:00
Jan Engelhardt
980a53348f build: use AM_CPPFLAGS in ipset-5/ 2011-01-19 02:36:26 +01:00
Jan Engelhardt
8ea781e257 build: fix objdir builds for ipset-5 (xt-a specific) 2011-01-19 02:35:49 +01:00
Jan Engelhardt
7e39ee66e0 libxt_length: fix name of manpage file 2011-01-15 05:23:38 +01:00
Jan Engelhardt
65e97a66e6 build: restore functionality of configure's --without-kbuild option 2011-01-13 20:25:00 +01:00
Jan Engelhardt
d82b20ead7 xt_LOGMARK: fix detection of untracked connection for Linux >= 2.6.36 2011-01-12 01:53:38 +01:00
Marek Kierdelewicz
c5d4dd0bcf Import of xt_DNETMAP 2011-01-10 22:59:32 +01:00
Jan Engelhardt
0168f8e8a2 doc: deprecate --with-xtlibdir configure option 2011-01-04 12:47:09 +01:00
Jan Engelhardt
dc22ec7bd1 build: mark Linux 2.6.37 as supported 2011-01-04 12:44:55 +01:00
Jan Engelhardt
25bf680ead geoip: put IPv4 geoip data into its own map 2010-12-19 00:48:42 +01:00
Jan Engelhardt
4d547c2bfc geoip: remove -b option, always build both endianesses 2010-12-17 22:47:01 +01:00
Jan Engelhardt
f7c7264a65 geoip: remove %names map 2010-12-17 22:41:08 +01:00
Jan Engelhardt
0f42828fd6 geoip: add manpages to utility programs 2010-12-17 22:29:54 +01:00
Jan Engelhardt
e2da87230a geoip: prefix tools with xt_
This is preferable to have when manpages go into system locations.
2010-12-17 22:08:15 +01:00
82 changed files with 3414 additions and 1620 deletions

21
INSTALL
View File

@@ -4,7 +4,7 @@ Installation instructions for Xtables-addons
Xtables-addons uses the well-known configure(autotools) infrastructure
in combination with the kernel's Kbuild system.
$ ./configure --with-xtlibdir=SEE_BELOW
$ ./configure
$ make
# make install
@@ -14,7 +14,7 @@ Supported configurations for this release
* iptables >= 1.4.3
* kernel-source >= 2.6.17, no upper bound known
* kernel-source >= 2.6.29
with prepared build/output directory
- CONFIG_NF_CONNTRACK or CONFIG_IP_NF_CONNTRACK
- CONFIG_NF_CONNTRACK_MARK or CONFIG_IP_NF_CONNTRACK_MARK
@@ -22,12 +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
@@ -60,11 +54,12 @@ Configuring and compiling
--with-xtlibdir=
Specifies the path to where the newly built extensions should
be installed when `make install` is run. It uses the same
default as the Xtables/iptables package, ${libexecdir}/xtables,
but you may need to specify this nevertheless, as autotools
defaults to using /usr/local as prefix, and distributions put
the files in differing locations.
be installed when `make install` is run. The default is to
use the same path that Xtables/iptables modules use, as
determined by `pkg-config xtables --variable xtlibdir`.
Thus, this option normally does NOT need to be specified
anymore, even if your distribution put modules in a strange
location.
If you want to enable debugging, use

7
README
View File

@@ -16,6 +16,13 @@ sanity checks and incorrect endianess handling have been fixed,
simplified, and sped up.
Included in this package
========================
- ipset 4.5
- ipset 5.4.1
- xt_ACCOUNT 1.16, libxt_ACCOUNT 1.3
Inclusion into a kernel tree
============================

View File

@@ -1,9 +1,9 @@
AC_INIT([xtables-addons], [1.32])
AC_INIT([xtables-addons], [1.34])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])
AC_PROG_INSTALL
AM_INIT_AUTOMAKE([1.10.2 -Wall foreign subdir-objects])
AM_INIT_AUTOMAKE([1.10b -Wall foreign subdir-objects])
AC_PROG_CC
AM_PROG_CC_C_O
AC_DISABLE_STATIC
@@ -40,44 +40,41 @@ 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;
AC_MSG_CHECKING([kernel version that we will build against])
krel="$(make -sC "$kbuilddir" M=. kernelrelease)";
kmajor="${krel%%[[^0-9]]*}";
kmajor="$(($kmajor+0))";
krel="${krel:${#kmajor}}";
krel="${krel#.}";
kminor="${krel%%[[^0-9]]*}";
kminor="$(($kminor+0))";
krel="${krel:${#kminor}}";
krel="${krel#.}";
kmicro="${krel%%[[^0-9]]*}";
kmicro="$(($kmicro+0))";
krel="${krel:${#kmicro}}";
krel="${krel#.}";
kstable="${krel%%[[^0-9]]*}";
kstable="$(($kstable+0))";
if test -z "$kmajor" -o -z "$kminor" -o -z "$kmicro"; then
echo "WARNING: Version detection did not succeed. Continue at own luck.";
else
echo "$kmajor.$kminor.$kmicro.$kstable in $kbuilddir";
if test "$kmajor" -gt 2 -o "$kminor" -gt 6 -o "$kmicro" -gt 36; 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;
if test -n "$kbuilddir"; then
AC_MSG_CHECKING([kernel version that we will build against])
krel="$(make -sC "$kbuilddir" M=. kernelrelease)";
kmajor="${krel%%[[^0-9]]*}";
kmajor="$(($kmajor+0))";
krel="${krel:${#kmajor}}";
krel="${krel#.}";
kminor="${krel%%[[^0-9]]*}";
kminor="$(($kminor+0))";
krel="${krel:${#kminor}}";
krel="${krel#.}";
kmicro="${krel%%[[^0-9]]*}";
kmicro="$(($kmicro+0))";
krel="${krel:${#kmicro}}";
krel="${krel#.}";
kstable="${krel%%[[^0-9]]*}";
kstable="$(($kstable+0))";
if test -z "$kmajor" -o -z "$kminor" -o -z "$kmicro"; then
echo "WARNING: Version detection did not succeed. Continue at own luck.";
else
echo "$kmajor.$kminor.$kmicro.$kstable in $kbuilddir";
if test "$kmajor" -gt 2 -o "$kminor" -gt 6 -o "$kmicro" -gt 38; then
echo "WARNING: You are trying a newer kernel. Results may vary. :-)";
elif test "$kmajor" -eq 2 -a "$kminor" -eq 6 -a "$kmicro" -ge 29; then
:; # everything ok
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 at all. Please see INSTALL for minimum configuration.";
exit 1;
else
echo "WARNING: That kernel version has been recently deprecated for use with Xtables-addons). Compilation may fail.";
fi;
fi;
fi;

View File

@@ -3,6 +3,39 @@ HEAD
====
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.
Expect that compat code will be removed shortly.
v1.33 (2011-02-02)
==================
Fixes:
- build: restore functionality of `configure --without-kbuild`
- build: fix objdir builds for ipset-5 (xt-a specific)
- build: fix missing inclusion of dependency rules
- xt_LOGMARK: fix detection of untracked connection for Linux >= 2.6.36
Enhancements:
- IPv6 support for xt_geoip
- Update to ipset 5.3
* make IPv4 and IPv6 address handling similar
* show correct line numbers in restore output for parser errors
- Update to ipset 5.4
* fixed ICMP and ICMPv6 handling
* fixed trailing whitespaces and pr_* messages
* fixed module loading at create/header commands
- build: support for Linux up to 2.6.38
- build: preliminary support for iptables 1.4.11
v1.32 (2011-01-04)
==================
Fixes:

View File

@@ -1,5 +1,8 @@
# -*- Makefile -*-
AM_CPPFLAGS = ${regular_CPPFLAGS} -I${abs_top_srcdir}/extensions
AM_CFLAGS = ${regular_CFLAGS}
include ../../Makefile.extra
sbin_PROGRAMS = iptaccount

View File

@@ -0,0 +1 @@
1.16

View File

@@ -105,11 +105,11 @@ static void account_tg_print_it(const void *ip,
struct in_addr a;
if (!do_prefix)
printf("ACCOUNT ");
printf(" ACCOUNT ");
// Network information
if (do_prefix)
printf("--");
printf(" --");
printf("%s ", account_tg_opts[0].name);
a.s_addr = accountinfo->net_ip;
@@ -119,7 +119,7 @@ static void account_tg_print_it(const void *ip,
printf(" ");
if (do_prefix)
printf("--");
printf(" --");
printf("%s %s", account_tg_opts[1].name, accountinfo->table_name);
}

View File

@@ -3,7 +3,7 @@
* See http://www.intra2net.com/opensource/ipt_account *
* for further information *
* *
* Copyright (C) 2004-2008 by Intra2net AG *
* Copyright (C) 2004-2011 by Intra2net AG *
* opensource@intra2net.com *
* *
* This program is free software; you can redistribute it and/or modify *

View File

@@ -10,6 +10,7 @@ obj-${build_CHAOS} += xt_CHAOS.o
obj-${build_CHECKSUM} += xt_CHECKSUM.o
obj-${build_DELUDE} += xt_DELUDE.o
obj-${build_DHCPMAC} += xt_DHCPMAC.o
obj-${build_DNETMAP} += xt_DNETMAP.o
obj-${build_ECHO} += xt_ECHO.o
obj-${build_IPMARK} += xt_IPMARK.o
obj-${build_LOGMARK} += xt_LOGMARK.o

View File

@@ -5,6 +5,7 @@ obj-${build_CHAOS} += libxt_CHAOS.so
obj-${build_CHECKSUM} += libxt_CHECKSUM.so
obj-${build_DELUDE} += libxt_DELUDE.so
obj-${build_DHCPMAC} += libxt_DHCPMAC.so libxt_dhcpmac.so
obj-${build_DNETMAP} += libxt_DNETMAP.so
obj-${build_ECHO} += libxt_ECHO.so
obj-${build_IPMARK} += libxt_IPMARK.so
obj-${build_LOGMARK} += libxt_LOGMARK.so

View File

@@ -0,0 +1 @@
4.5

View File

@@ -5,3 +5,7 @@ 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

View File

@@ -1,6 +1,7 @@
# -*- Makefile -*-
AM_CFLAGS = ${regular_CFLAGS} ${libmnl_CFLAGS} -Iinclude
AM_CPPFLAGS = -I${srcdir}/include -DNDEBUG
AM_CFLAGS = ${regular_CFLAGS} ${libmnl_CFLAGS}
include ../../Makefile.extra

View File

@@ -0,0 +1 @@
5.4.1-genl

View File

@@ -24,6 +24,7 @@ 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,

View File

@@ -25,6 +25,11 @@
#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)))

View File

@@ -4,13 +4,15 @@
/* 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>
* 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
@@ -279,6 +281,7 @@ struct ip_set_type {
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);
@@ -291,7 +294,7 @@ struct ip_set {
/* References to the set */
atomic_t ref;
/* The core set type */
const struct ip_set_type *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 */
@@ -316,37 +319,22 @@ extern int ip_set_del(ip_set_id_t id, const struct sk_buff *skb,
extern int ip_set_test(ip_set_id_t id, const struct sk_buff *skb,
u8 family, u8 dim, u8 flags);
/* Allocate members */
static inline void *
ip_set_alloc(size_t size, gfp_t gfp_mask)
/* 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)
{
void *members = NULL;
if (size < KMALLOC_MAX_SIZE)
members = kzalloc(size, gfp_mask | __GFP_NOWARN);
if (members) {
pr_debug("%p: allocated with kmalloc", members);
return members;
}
members = __vmalloc(size, gfp_mask | __GFP_ZERO, PAGE_KERNEL);
if (!members)
return NULL;
pr_debug("%p: allocated with vmalloc", members);
return members;
}
static inline void
ip_set_free(void *members)
{
pr_debug("%p: free with %s", members,
is_vmalloc_addr(members) ? "vfree" : "kfree");
if (is_vmalloc_addr(members))
vfree(members);
else
kfree(members);
__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? */
@@ -356,92 +344,47 @@ 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)
{
u32 value = nla_get_u32(attr);
return attr->nla_type & NLA_F_NET_BYTEORDER ? ntohl(value) : value;
return ntohl(nla_get_be32(attr));
}
static inline u16
ip_set_get_h16(const struct nlattr *attr)
{
u16 value = nla_get_u16(attr);
return attr->nla_type & NLA_F_NET_BYTEORDER ? ntohs(value) : value;
}
static inline u32
ip_set_get_n32(const struct nlattr *attr)
{
u32 value = nla_get_u32(attr);
return attr->nla_type & NLA_F_NET_BYTEORDER ? value : htonl(value);
}
static inline u16
ip_set_get_n16(const struct nlattr *attr)
{
u16 value = nla_get_u16(attr);
return attr->nla_type & NLA_F_NET_BYTEORDER ? value : htons(value);
}
static const struct nla_policy ipaddr_policy[IPSET_ATTR_IPADDR_MAX + 1] = {
[IPSET_ATTR_IPADDR_IPV4] = { .type = NLA_U32 },
[IPSET_ATTR_IPADDR_IPV6] = { .type = NLA_BINARY,
.len = sizeof(struct in6_addr) },
};
static inline int
ip_set_get_ipaddr4(struct nlattr *attr[], int type, u32 *ipaddr)
{
struct nlattr *tb[IPSET_ATTR_IPADDR_MAX+1] = {};
if (!attr[type])
return -IPSET_ERR_PROTOCOL;
if (nla_parse(tb, IPSET_ATTR_IPADDR_MAX,
nla_data(attr[type]), nla_len(attr[type]),
ipaddr_policy))
return -IPSET_ERR_PROTOCOL;
if (!tb[IPSET_ATTR_IPADDR_IPV4])
return -IPSET_ERR_IPADDR_IPV4;
*ipaddr = ip_set_get_n32(tb[IPSET_ATTR_IPADDR_IPV4]);
return 0;
}
static inline int
ip_set_get_ipaddr6(struct nlattr *attr[], int type, union nf_inet_addr *ipaddr)
{
struct nlattr *tb[IPSET_ATTR_IPADDR_MAX+1] = {};
if (!attr[type])
return -IPSET_ERR_PROTOCOL;
if (nla_parse(tb, IPSET_ATTR_IPADDR_MAX,
nla_data(attr[type]), nla_len(attr[type]),
ipaddr_policy))
return -IPSET_ERR_PROTOCOL;
if (!tb[IPSET_ATTR_IPADDR_IPV6])
return -IPSET_ERR_IPADDR_IPV6;
memcpy(ipaddr, nla_data(tb[IPSET_ATTR_IPADDR_IPV6]),
sizeof(struct in6_addr));
return 0;
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)
#define NLA_PUT_NET32(skb, type, value) \
NLA_PUT_BE32(skb, type | NLA_F_NET_BYTEORDER, value)
#define NLA_PUT_NET16(skb, type, value) \
NLA_PUT_BE16(skb, type | NLA_F_NET_BYTEORDER, value)
#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 { \
@@ -465,14 +408,14 @@ do { \
} while (0)
/* Get address from skbuff */
static inline u32
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, u32 *addr)
ip4addrptr(const struct sk_buff *skb, bool src, __be32 *addr)
{
*addr = src ? ip_hdr(skb)->saddr : ip_hdr(skb)->daddr;
}
@@ -491,15 +434,6 @@ bitmap_bytes(u32 a, u32 b)
return 4 * ((((b - a + 8) / 8) + 3) / 4);
}
/* Prefixlen maps */
extern const union nf_inet_addr prefixlen_netmask_map[];
extern const union nf_inet_addr prefixlen_hostmask_map[];
#define NETMASK(n) prefixlen_netmask_map[n].ip
#define NETMASK6(n) prefixlen_netmask_map[n].ip6
#define HOSTMASK(n) prefixlen_hostmask_map[n].ip
#define HOSTMASK6(n) prefixlen_hostmask_map[n].ip6
/* Interface to iptables/ip6tables */
#define SO_IP_SET 83

View File

@@ -63,7 +63,7 @@ struct ip_set_hash {
};
/* Compute htable_bits from the user input parameter hashsize */
static inline u8
static u8
htable_bits(u32 hashsize)
{
/* Assume that hashsize == 2^htable_bits */
@@ -81,14 +81,14 @@ htable_bits(u32 hashsize)
/* Network cidr size book keeping when the hash stores different
* sized networks */
static inline void
static void
add_cidr(struct ip_set_hash *h, u8 cidr, u8 host_mask)
{
u8 i;
++h->nets[cidr-1].nets;
pr_debug("add_cidr added %u: %u", cidr, h->nets[cidr-1].nets);
pr_debug("add_cidr added %u: %u\n", cidr, h->nets[cidr-1].nets);
if (h->nets[cidr-1].nets > 1)
return;
@@ -103,14 +103,14 @@ add_cidr(struct ip_set_hash *h, u8 cidr, u8 host_mask)
h->nets[i].cidr = cidr;
}
static inline void
static void
del_cidr(struct ip_set_hash *h, u8 cidr, u8 host_mask)
{
u8 i;
--h->nets[cidr-1].nets;
pr_debug("del_cidr deleted %u: %u", cidr, h->nets[cidr-1].nets);
pr_debug("del_cidr deleted %u: %u\n", cidr, h->nets[cidr-1].nets);
if (h->nets[cidr-1].nets != 0)
return;
@@ -142,7 +142,7 @@ ahash_destroy(struct htable *t)
}
/* Calculate the actual memory size of the set data */
static inline size_t
static size_t
ahash_memsize(const struct ip_set_hash *h, size_t dsize, u8 host_mask)
{
u32 i;
@@ -340,7 +340,7 @@ retry:
/* Give time to other readers of the set */
synchronize_rcu_bh();
pr_debug("set %s resized from %u (%p) to %u (%p)", set->name,
pr_debug("set %s resized from %u (%p) to %u (%p)\n", set->name,
orig->htable_bits, orig, t->htable_bits, t);
ahash_destroy(orig);
@@ -436,7 +436,7 @@ type_pf_del(struct ip_set *set, void *value, u32 timeout)
/* Special test function which takes into account the different network
* sizes added to the set */
static inline int
static int
type_pf_test_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout)
{
struct ip_set_hash *h = set->data;
@@ -447,7 +447,7 @@ type_pf_test_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout)
u32 key;
u8 host_mask = SET_HOST_MASK(set->family);
pr_debug("test by nets");
pr_debug("test by nets\n");
for (; j < host_mask && h->nets[j].cidr; j++) {
type_pf_data_netmask(d, h->nets[j].cidr);
key = HKEY(d, h->initval, t->htable_bits);
@@ -546,14 +546,14 @@ type_pf_list(const struct ip_set *set,
atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
if (!atd)
return -EFAULT;
pr_debug("list hash set %s", set->name);
pr_debug("list hash set %s\n", set->name);
for (; cb->args[2] < jhash_size(t->htable_bits); cb->args[2]++) {
incomplete = skb_tail_pointer(skb);
n = hbucket(t, cb->args[2]);
pr_debug("cb->args[2]: %lu, t %p n %p", cb->args[2], t, n);
pr_debug("cb->args[2]: %lu, t %p n %p\n", cb->args[2], t, n);
for (i = 0; i < n->pos; i++) {
data = ahash_data(n, i);
pr_debug("list hash %lu hbucket %p i %u, data %p",
pr_debug("list hash %lu hbucket %p i %u, data %p\n",
cb->args[2], n, i, data);
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
if (!nested) {
@@ -686,7 +686,7 @@ type_pf_expire(struct ip_set_hash *h)
for (j = 0; j < n->pos; j++) {
data = ahash_tdata(n, j);
if (type_pf_data_expired(data)) {
pr_debug("expired %u/%u", i, j);
pr_debug("expired %u/%u\n", i, j);
#ifdef IP_SET_HASH_WITH_NETS
del_cidr(h, data->cidr, HOST_MASK);
#endif
@@ -701,7 +701,7 @@ type_pf_expire(struct ip_set_hash *h)
if (n->pos + AHASH_INIT_SIZE < n->size) {
void *tmp = kzalloc((n->size - AHASH_INIT_SIZE)
* sizeof(struct type_pf_telem),
GFP_KERNEL);
GFP_ATOMIC);
if (!tmp)
/* Still try to delete expired elements */
continue;
@@ -807,8 +807,8 @@ type_pf_tadd(struct ip_set *set, void *value, u32 timeout)
ret = -IPSET_ERR_EXIST;
goto out;
}
} else if (j == AHASH_MAX_SIZE + 1
&& type_pf_data_expired(data))
} else if (j == AHASH_MAX_SIZE + 1 &&
type_pf_data_expired(data))
j = i;
}
if (j != AHASH_MAX_SIZE + 1) {
@@ -881,7 +881,7 @@ type_pf_tdel(struct ip_set *set, void *value, u32 timeout)
}
#ifdef IP_SET_HASH_WITH_NETS
static inline int
static int
type_pf_ttest_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout)
{
struct ip_set_hash *h = set->data;
@@ -952,10 +952,10 @@ type_pf_tlist(const struct ip_set *set,
n = hbucket(t, cb->args[2]);
for (i = 0; i < n->pos; i++) {
data = ahash_tdata(n, i);
pr_debug("list %p %u", n, i);
pr_debug("list %p %u\n", n, i);
if (type_pf_data_expired(data))
continue;
pr_debug("do list %p %u", n, i);
pr_debug("do list %p %u\n", n, i);
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
if (!nested) {
if (cb->args[2] == first) {
@@ -1008,7 +1008,7 @@ type_pf_gc(unsigned long ul_set)
struct ip_set *set = (struct ip_set *) ul_set;
struct ip_set_hash *h = set->data;
pr_debug("called");
pr_debug("called\n");
write_lock_bh(&set->lock);
type_pf_expire(h);
write_unlock_bh(&set->lock);
@@ -1017,7 +1017,7 @@ type_pf_gc(unsigned long ul_set)
add_timer(&h->gc);
}
static inline void
static void
type_pf_gc_init(struct ip_set *set)
{
struct ip_set_hash *h = set->data;
@@ -1027,7 +1027,7 @@ type_pf_gc_init(struct ip_set *set)
h->gc.function = type_pf_gc;
h->gc.expires = jiffies + IPSET_GC_PERIOD(h->timeout) * HZ;
add_timer(&h->gc);
pr_debug("gc initialized, run in every %u",
pr_debug("gc initialized, run in every %u\n",
IPSET_GC_PERIOD(h->timeout));
}

View File

@@ -1,6 +1,6 @@
/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
* Patrick Schaaf <bof@bof.de>
* Copyright (C) 2003-2010 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
* 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
@@ -9,7 +9,6 @@
/* Kernel module implementing an IP set type: the bitmap:ip type */
#include "ip_set_kernel.h"
#include <linux/module.h>
#include <linux/ip.h>
#include <linux/skbuff.h>
@@ -23,6 +22,7 @@
#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
@@ -46,9 +46,9 @@ struct bitmap_ip {
};
static inline u32
ip_to_id(const struct bitmap_ip *map, u32 ip)
ip_to_id(const struct bitmap_ip *m, u32 ip)
{
return ((ip & HOSTMASK(map->netmask)) - map->first_ip)/map->hosts;
return ((ip & ip_set_hostmask(m->netmask)) - m->first_ip)/m->hosts;
}
static inline int
@@ -121,13 +121,15 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *head, int 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_ipaddr4(tb, IPSET_ATTR_IP, &ip);
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
if (ret)
return ret;
ip = ntohl(ip);
if (ip < map->first_ip || ip > map->last_ip)
return -IPSET_ERR_BITMAP_RANGE;
@@ -141,10 +143,9 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *head, int len,
return bitmap_ip_test(map, ip_to_id(map, ip));
if (tb[IPSET_ATTR_IP_TO]) {
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP_TO, &ip_to);
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
if (ret)
return ret;
ip_to = ntohl(ip_to);
if (ip > ip_to) {
swap(ip, ip_to);
if (ip < map->first_ip)
@@ -155,8 +156,8 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *head, int len,
if (cidr > 32)
return -IPSET_ERR_INVALID_CIDR;
ip &= HOSTMASK(cidr);
ip_to = ip | ~HOSTMASK(cidr);
ip &= ip_set_hostmask(cidr);
ip_to = ip | ~ip_set_hostmask(cidr);
} else
ip_to = ip;
@@ -263,9 +264,9 @@ 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;
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 = {
@@ -361,13 +362,16 @@ bitmap_ip_timeout_uadt(struct ip_set *set, struct nlattr *head, int 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_ipaddr4(tb, IPSET_ATTR_IP, &ip);
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
if (ret)
return ret;
ip = ntohl(ip);
if (ip < map->first_ip || ip > map->last_ip)
return -IPSET_ERR_BITMAP_RANGE;
@@ -377,10 +381,9 @@ bitmap_ip_timeout_uadt(struct ip_set *set, struct nlattr *head, int len,
ip_to_id((const struct bitmap_ip *)map, ip));
if (tb[IPSET_ATTR_IP_TO]) {
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP_TO, &ip_to);
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
if (ret)
return ret;
ip_to = ntohl(ip_to);
if (ip > ip_to) {
swap(ip, ip_to);
if (ip < map->first_ip)
@@ -391,8 +394,8 @@ bitmap_ip_timeout_uadt(struct ip_set *set, struct nlattr *head, int len,
if (cidr > 32)
return -IPSET_ERR_INVALID_CIDR;
ip &= HOSTMASK(cidr);
ip_to = ip | ~HOSTMASK(cidr);
ip &= ip_set_hostmask(cidr);
ip_to = ip | ~ip_set_hostmask(cidr);
} else
ip_to = ip;
@@ -510,10 +513,10 @@ 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;
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 = {
@@ -546,7 +549,7 @@ bitmap_ip_gc(unsigned long ul_set)
add_timer(&map->gc);
}
static inline void
static void
bitmap_ip_gc_init(struct ip_set *set)
{
struct bitmap_ip_timeout *map = set->data;
@@ -602,16 +605,18 @@ bitmap_ip_create(struct ip_set *set, struct nlattr *head, int len,
bitmap_ip_create_policy))
return -IPSET_ERR_PROTOCOL;
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &first_ip);
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;
first_ip = ntohl(first_ip);
if (tb[IPSET_ATTR_IP_TO]) {
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP_TO, &last_ip);
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &last_ip);
if (ret)
return ret;
last_ip = htonl(last_ip);
if (first_ip > last_ip) {
u32 tmp = first_ip;
@@ -623,7 +628,7 @@ bitmap_ip_create(struct ip_set *set, struct nlattr *head, int len,
if (cidr >= 32)
return -IPSET_ERR_INVALID_CIDR;
last_ip = first_ip | ~HOSTMASK(cidr);
last_ip = first_ip | ~ip_set_hostmask(cidr);
} else
return -IPSET_ERR_PROTOCOL;
@@ -633,8 +638,8 @@ bitmap_ip_create(struct ip_set *set, struct nlattr *head, int len,
if (netmask > 32)
return -IPSET_ERR_INVALID_NETMASK;
first_ip &= HOSTMASK(netmask);
last_ip |= ~HOSTMASK(netmask);
first_ip &= ip_set_hostmask(netmask);
last_ip |= ~ip_set_hostmask(netmask);
}
if (netmask == 32) {
@@ -646,18 +651,18 @@ bitmap_ip_create(struct ip_set *set, struct nlattr *head, int len,
mask = range_to_mask(first_ip, last_ip, &mask_bits);
if ((!mask && (first_ip || last_ip != 0xFFFFFFFF))
|| netmask <= mask_bits)
if ((!mask && (first_ip || last_ip != 0xFFFFFFFF)) ||
netmask <= mask_bits)
return -IPSET_ERR_BITMAP_RANGE;
pr_debug("mask_bits %u, netmask %u", mask_bits, netmask);
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", hosts, elements);
pr_debug("hosts %u, elements %u\n", hosts, elements);
if (tb[IPSET_ATTR_TIMEOUT]) {
struct bitmap_ip_timeout *map;

View File

@@ -1,7 +1,7 @@
/* 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>
* 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
@@ -10,7 +10,6 @@
/* Kernel module implementing an IP set type: the bitmap:ip,mac type */
#include "ip_set_kernel.h"
#include <linux/module.h>
#include <linux/ip.h>
#include <linux/etherdevice.h>
@@ -25,6 +24,7 @@
#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"
@@ -94,9 +94,9 @@ bitmap_expired(const struct bitmap_ipmac *map, u32 id)
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));
return elem->match == MAC_UNSET ||
(elem->match == MAC_FILLED &&
!ip_set_timeout_expired(elem->timeout));
}
/* Base variant */
@@ -113,8 +113,8 @@ bitmap_ipmac_test(struct ip_set *set, void *value, u32 timeout)
/* 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 data->ether == NULL ||
compare_ether_addr(data->ether, elem->ether) == 0;
}
return 0;
}
@@ -222,9 +222,9 @@ bitmap_ipmac_ttest(struct ip_set *set, void *value, u32 timeout)
/* 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 (data->ether == NULL ||
compare_ether_addr(data->ether, elem->ether) == 0) &&
!bitmap_expired(map, data->id);
}
return 0;
}
@@ -347,8 +347,8 @@ bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
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)
if (skb_mac_header(skb) < skb->head ||
(skb_mac_header(skb) + ETH_HLEN) > skb->data)
return -EINVAL;
data.id -= map->first_ip;
@@ -380,13 +380,16 @@ bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *head, int 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_ipaddr4(tb, IPSET_ATTR_IP, &data.id);
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &data.id);
if (ret)
return ret;
data.id = ntohl(data.id);
if (data.id < map->first_ip || data.id > map->last_ip)
return -IPSET_ERR_BITMAP_RANGE;
@@ -463,12 +466,12 @@ 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;
return x->first_ip == y->first_ip &&
x->last_ip == y->last_ip &&
x->timeout == y->timeout;
}
const struct ip_set_type_variant bitmap_ipmac = {
static const struct ip_set_type_variant bitmap_ipmac = {
.kadt = bitmap_ipmac_kadt,
.uadt = bitmap_ipmac_uadt,
.adt = {
@@ -483,7 +486,7 @@ const struct ip_set_type_variant bitmap_ipmac = {
.same_set = bitmap_ipmac_same_set,
};
const struct ip_set_type_variant bitmap_tipmac = {
static const struct ip_set_type_variant bitmap_tipmac = {
.kadt = bitmap_ipmac_kadt,
.uadt = bitmap_ipmac_uadt,
.adt = {
@@ -511,8 +514,8 @@ bitmap_ipmac_gc(unsigned long ul_set)
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))
if (elem->match == MAC_FILLED &&
ip_set_timeout_expired(elem->timeout))
elem->match = MAC_EMPTY;
}
read_unlock_bh(&set->lock);
@@ -521,7 +524,7 @@ bitmap_ipmac_gc(unsigned long ul_set)
add_timer(&map->gc);
}
static inline void
static void
bitmap_ipmac_gc_init(struct ip_set *set)
{
struct bitmap_ipmac *map = set->data;
@@ -539,6 +542,7 @@ 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 },
};
@@ -573,16 +577,18 @@ bitmap_ipmac_create(struct ip_set *set, struct nlattr *head, int len,
bitmap_ipmac_create_policy))
return -IPSET_ERR_PROTOCOL;
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &first_ip);
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;
first_ip = ntohl(first_ip);
if (tb[IPSET_ATTR_IP_TO]) {
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP_TO, &last_ip);
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &last_ip);
if (ret)
return ret;
last_ip = ntohl(last_ip);
if (first_ip > last_ip) {
u32 tmp = first_ip;
@@ -594,7 +600,7 @@ bitmap_ipmac_create(struct ip_set *set, struct nlattr *head, int len,
if (cidr >= 32)
return -IPSET_ERR_INVALID_CIDR;
last_ip = first_ip | ~HOSTMASK(cidr);
last_ip = first_ip | ~ip_set_hostmask(cidr);
} else
return -IPSET_ERR_PROTOCOL;
@@ -633,7 +639,7 @@ bitmap_ipmac_create(struct ip_set *set, struct nlattr *head, int len,
return 0;
}
struct ip_set_type bitmap_ipmac_type = {
static struct ip_set_type bitmap_ipmac_type = {
.name = "bitmap:ip,mac",
.protocol = IPSET_PROTOCOL,
.features = IPSET_TYPE_IP | IPSET_TYPE_MAC,

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2003-2010 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
/* 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
@@ -7,7 +7,6 @@
/* Kernel module implementing an IP set type: the bitmap:port type */
#include "ip_set_kernel.h"
#include <linux/module.h>
#include <linux/ip.h>
#include <linux/tcp.h>
@@ -71,12 +70,13 @@ 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 (!get_ip_port(skb, pf, flags & IPSET_DIM_ONE_SRC, &port))
if (!ip_set_get_ip_port(skb, pf, flags & IPSET_DIM_ONE_SRC, &__port))
return -EINVAL;
port = ntohs(port);
port = ntohs(__port);
if (port < map->first_port || port > map->last_port)
return -IPSET_ERR_BITMAP_RANGE;
@@ -116,14 +116,14 @@ bitmap_port_uadt(struct ip_set *set, struct nlattr *head, int 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]);
if (tb[IPSET_ATTR_PORT])
port = ip_set_get_h16(tb[IPSET_ATTR_PORT]);
else
return -IPSET_ERR_PROTOCOL;
port = ip_set_get_h16(tb[IPSET_ATTR_PORT]);
if (port < map->first_port || port > map->last_port)
return -IPSET_ERR_BITMAP_RANGE;
@@ -246,11 +246,11 @@ 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;
return x->first_port == y->first_port &&
x->last_port == y->last_port;
}
const struct ip_set_type_variant bitmap_port = {
static const struct ip_set_type_variant bitmap_port = {
.kadt = bitmap_port_kadt,
.uadt = bitmap_port_uadt,
.destroy = bitmap_port_destroy,
@@ -308,12 +308,13 @@ 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 (!get_ip_port(skb, pf, flags & IPSET_DIM_ONE_SRC, &port))
if (!ip_set_get_ip_port(skb, pf, flags & IPSET_DIM_ONE_SRC, &__port))
return -EINVAL;
port = ntohs(port);
port = ntohs(__port);
if (port < map->first_port || port > map->last_port)
return -IPSET_ERR_BITMAP_RANGE;
@@ -346,14 +347,15 @@ bitmap_port_timeout_uadt(struct ip_set *set, struct nlattr *head, int 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]);
if (tb[IPSET_ATTR_PORT])
port = ip_set_get_h16(tb[IPSET_ATTR_PORT]);
else
return -IPSET_ERR_PROTOCOL;
port = ip_set_get_h16(tb[IPSET_ATTR_PORT]);
if (port < map->first_port || port > map->last_port)
return -IPSET_ERR_BITMAP_RANGE;
@@ -483,12 +485,12 @@ 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;
return x->first_port == y->first_port &&
x->last_port == y->last_port &&
x->timeout == y->timeout;
}
const struct ip_set_type_variant bitmap_port_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,
@@ -519,7 +521,7 @@ bitmap_port_gc(unsigned long ul_set)
add_timer(&map->gc);
}
static inline void
static void
bitmap_port_gc_init(struct ip_set *set)
{
struct bitmap_port_timeout *map = set->data;
@@ -567,21 +569,19 @@ bitmap_port_create(struct ip_set *set, struct nlattr *head, int len,
bitmap_port_create_policy))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_PORT])
first_port = ip_set_get_h16(tb[IPSET_ATTR_PORT]);
else
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;
if (tb[IPSET_ATTR_PORT_TO]) {
last_port = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
if (first_port > last_port) {
u16 tmp = first_port;
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;
}
} else
return -IPSET_ERR_PROTOCOL;
first_port = last_port;
last_port = tmp;
}
if (tb[IPSET_ATTR_TIMEOUT]) {
struct bitmap_port_timeout *map;
@@ -611,7 +611,7 @@ bitmap_port_create(struct ip_set *set, struct nlattr *head, int len,
return -ENOMEM;
map->memsize = bitmap_bytes(0, last_port - first_port);
pr_debug("memsize: %zu", map->memsize);
pr_debug("memsize: %zu\n", map->memsize);
if (!init_map_port(set, map, first_port, last_port)) {
kfree(map);
return -ENOMEM;
@@ -622,7 +622,7 @@ bitmap_port_create(struct ip_set *set, struct nlattr *head, int len,
return 0;
}
struct ip_set_type bitmap_port_type = {
static struct ip_set_type bitmap_port_type = {
.name = "bitmap:port",
.protocol = IPSET_PROTOCOL,
.features = IPSET_TYPE_PORT,

View File

@@ -0,0 +1,136 @@
/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/* Get Layer-4 data from the packets */
#include <linux/ip.h>
#include <linux/skbuff.h>
#include <linux/icmp.h>
#include <linux/icmpv6.h>
#include <linux/netfilter_ipv6/ip6_tables.h>
#include <net/ip.h>
#include "ip_set_getport.h"
/* We must handle non-linear skbs */
static bool
get_port(const struct sk_buff *skb, int protocol, unsigned int protooff,
bool src, __be16 *port, u8 *proto)
{
switch (protocol) {
case IPPROTO_TCP: {
struct tcphdr _tcph;
const struct tcphdr *th;
th = skb_header_pointer(skb, protooff, sizeof(_tcph), &_tcph);
if (th == NULL)
/* No choice either */
return false;
*port = src ? th->source : th->dest;
break;
}
case IPPROTO_UDP: {
struct udphdr _udph;
const struct udphdr *uh;
uh = skb_header_pointer(skb, protooff, sizeof(_udph), &_udph);
if (uh == NULL)
/* No choice either */
return false;
*port = src ? uh->source : uh->dest;
break;
}
case IPPROTO_ICMP: {
struct icmphdr _ich;
const struct icmphdr *ic;
ic = skb_header_pointer(skb, protooff, sizeof(_ich), &_ich);
if (ic == NULL)
return false;
*port = (__force __be16)htons((ic->type << 8) | ic->code);
break;
}
case IPPROTO_ICMPV6: {
struct icmp6hdr _ich;
const struct icmp6hdr *ic;
ic = skb_header_pointer(skb, protooff, sizeof(_ich), &_ich);
if (ic == NULL)
return false;
*port = (__force __be16)
htons((ic->icmp6_type << 8) | ic->icmp6_code);
break;
}
default:
break;
}
*proto = protocol;
return true;
}
bool
ip_set_get_ip4_port(const struct sk_buff *skb, bool src,
__be16 *port, u8 *proto)
{
const struct iphdr *iph = ip_hdr(skb);
unsigned int protooff = ip_hdrlen(skb);
int protocol = iph->protocol;
/* See comments at tcp_match in ip_tables.c */
if (protocol <= 0 || (ntohs(iph->frag_off) & IP_OFFSET))
return false;
return get_port(skb, protocol, protooff, src, port, proto);
}
EXPORT_SYMBOL_GPL(ip_set_get_ip4_port);
bool
ip_set_get_ip6_port(const struct sk_buff *skb, bool src,
__be16 *port, u8 *proto)
{
unsigned int protooff = 0;
int protocol;
unsigned short fragoff;
protocol = ipv6_find_hdr(skb, &protooff, -1, &fragoff);
if (protocol <= 0 || fragoff)
return false;
return get_port(skb, protocol, protooff, src, port, proto);
}
EXPORT_SYMBOL_GPL(ip_set_get_ip6_port);
bool
ip_set_get_ip_port(const struct sk_buff *skb, u8 pf, bool src, __be16 *port)
{
bool ret;
u8 proto;
switch (pf) {
case AF_INET:
ret = ip_set_get_ip4_port(skb, src, port, &proto);
case AF_INET6:
ret = ip_set_get_ip6_port(skb, src, port, &proto);
default:
return false;
}
if (!ret)
return ret;
switch (proto) {
case IPPROTO_TCP:
case IPPROTO_UDP:
return true;
default:
return false;
}
}
EXPORT_SYMBOL_GPL(ip_set_get_ip_port);

View File

@@ -1,126 +1,11 @@
#ifndef _IP_SET_GETPORT_H
#define _IP_SET_GETPORT_H
#ifdef __KERNEL__
#include <linux/icmp.h>
#include <linux/icmpv6.h>
#include <linux/netfilter_ipv6/ip6_tables.h>
#include <net/ip.h>
#define IPSET_INVALID_PORT 65536
/* We must handle non-linear skbs */
static inline bool
get_port(const struct sk_buff *skb, int protocol, unsigned int protooff,
bool src, u16 *port, u8 *proto)
{
switch (protocol) {
case IPPROTO_TCP: {
struct tcphdr _tcph;
const struct tcphdr *th;
th = skb_header_pointer(skb, protooff, sizeof(_tcph), &_tcph);
if (th == NULL)
/* No choice either */
return false;
*port = src ? th->source : th->dest;
break;
}
case IPPROTO_UDP: {
struct udphdr _udph;
const struct udphdr *uh;
uh = skb_header_pointer(skb, protooff, sizeof(_udph), &_udph);
if (uh == NULL)
/* No choice either */
return false;
*port = src ? uh->source : uh->dest;
break;
}
case IPPROTO_ICMP: {
struct icmphdr _icmph;
const struct icmphdr *ic;
ic = skb_header_pointer(skb, protooff, sizeof(_icmph), &_icmph);
if (ic == NULL)
return false;
*port = (ic->type << 8) & ic->code;
break;
}
case IPPROTO_ICMPV6: {
struct icmp6hdr _icmph;
const struct icmp6hdr *ic;
ic = skb_header_pointer(skb, protooff, sizeof(_icmph), &_icmph);
if (ic == NULL)
return false;
*port = (ic->icmp6_type << 8) & ic->icmp6_code;
break;
}
default:
break;
}
*proto = protocol;
return true;
}
static inline bool
get_ip4_port(const struct sk_buff *skb, bool src, u16 *port, u8 *proto)
{
const struct iphdr *iph = ip_hdr(skb);
unsigned int protooff = ip_hdrlen(skb);
int protocol = iph->protocol;
/* See comments at tcp_match in ip_tables.c */
if (protocol <= 0 || (ntohs(iph->frag_off) & IP_OFFSET))
return false;
return get_port(skb, protocol, protooff, src, port, proto);
}
static inline bool
get_ip6_port(const struct sk_buff *skb, bool src, u16 *port, u8 *proto)
{
unsigned int protooff = 0;
int protocol;
unsigned short fragoff;
protocol = ipv6_find_hdr(skb, &protooff, -1, &fragoff);
if (protocol <= 0 || fragoff)
return false;
return get_port(skb, protocol, protooff, src, port, proto);
}
static inline bool
get_ip_port(const struct sk_buff *skb, u8 pf, bool src, u16 *port)
{
bool ret;
u8 proto;
switch (pf) {
case AF_INET:
ret = get_ip4_port(skb, src, port, &proto);
case AF_INET6:
ret = get_ip6_port(skb, src, port, &proto);
default:
return false;
}
if (!ret)
return ret;
switch (proto) {
case IPPROTO_TCP:
case IPPROTO_UDP:
return true;
default:
return false;
}
}
#endif /* __KERNEL__ */
extern bool ip_set_get_ip4_port(const struct sk_buff *skb, bool src,
__be16 *port, u8 *proto);
extern bool ip_set_get_ip6_port(const struct sk_buff *skb, bool src,
__be16 *port, u8 *proto);
extern bool ip_set_get_ip_port(const struct sk_buff *skb, u8 pf, bool src,
__be16 *port);
#endif /*_IP_SET_GETPORT_H*/

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2003-2010 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
/* 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
@@ -7,7 +7,6 @@
/* Kernel module implementing an IP set type: the hash:ip type */
#include "ip_set_kernel.h"
#include "jhash.h"
#include <linux/module.h>
#include <linux/ip.h>
@@ -23,6 +22,7 @@
#include <net/tcp.h>
#include <linux/netfilter.h>
#include "pfxlen.h"
#include "ip_set.h"
#include "ip_set_timeout.h"
#include "ip_set_hash.h"
@@ -45,12 +45,12 @@ hash_ip_same_set(const struct ip_set *a, const struct ip_set *b);
/* Member elements without timeout */
struct hash_ip4_elem {
u32 ip;
__be32 ip;
};
/* Member elements with timeout support */
struct hash_ip4_telem {
u32 ip;
__be32 ip;
unsigned long timeout;
};
@@ -73,12 +73,6 @@ hash_ip4_data_copy(struct hash_ip4_elem *dst, const struct hash_ip4_elem *src)
dst->ip = src->ip;
}
static inline void
hash_ip4_data_swap(struct hash_ip4_elem *dst, struct hash_ip4_elem *src)
{
swap(dst->ip, src->ip);
}
/* Zero valued IP addresses cannot be stored */
static inline void
hash_ip4_data_zero_out(struct hash_ip4_elem *elem)
@@ -96,7 +90,7 @@ nla_put_failure:
return 1;
}
static inline bool
static bool
hash_ip4_data_tlist(struct sk_buff *skb, const struct hash_ip4_elem *data)
{
const struct hash_ip4_telem *tdata =
@@ -123,10 +117,10 @@ hash_ip4_kadt(struct ip_set *set, const struct sk_buff *skb,
{
const struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
u32 ip;
__be32 ip;
ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &ip);
ip &= NETMASK(h->netmask);
ip &= ip_set_netmask(h->netmask);
if (ip == 0)
return -EINVAL;
@@ -148,23 +142,26 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *head, int len,
const struct ip_set_hash *h = set->data;
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
ipset_adtfn adtfn = set->variant->adt[adt];
u32 ip, nip, ip_to, hosts, timeout = h->timeout;
u32 ip, ip_to, hosts, timeout = h->timeout;
__be32 nip;
int ret = 0;
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len,
hash_ip4_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_ipaddr4(tb, IPSET_ATTR_IP, &ip);
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
if (ret)
return ret;
ip &= NETMASK(h->netmask);
if (ip == 0)
return -IPSET_ERR_HASH_ELEM;
ip &= ip_set_hostmask(h->netmask);
if (tb[IPSET_ATTR_TIMEOUT]) {
if (!with_timeout(h->timeout))
@@ -172,15 +169,17 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *head, int len,
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
}
if (adt == IPSET_TEST)
return adtfn(set, &ip, timeout);
if (adt == IPSET_TEST) {
nip = htonl(ip);
if (nip == 0)
return -IPSET_ERR_HASH_ELEM;
return adtfn(set, &nip, timeout);
}
ip = ntohl(ip);
if (tb[IPSET_ATTR_IP_TO]) {
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP_TO, &ip_to);
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
if (ret)
return ret;
ip_to = ntohl(ip_to);
if (ip > ip_to)
swap(ip, ip_to);
} else if (tb[IPSET_ATTR_CIDR]) {
@@ -188,8 +187,8 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *head, int len,
if (cidr > 32)
return -IPSET_ERR_INVALID_CIDR;
ip &= HOSTMASK(cidr);
ip_to = ip | ~HOSTMASK(cidr);
ip &= ip_set_hostmask(cidr);
ip_to = ip | ~ip_set_hostmask(cidr);
} else
ip_to = ip;
@@ -197,6 +196,8 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *head, int len,
for (; !before(ip_to, ip); ip += hosts) {
nip = htonl(ip);
if (nip == 0)
return -IPSET_ERR_HASH_ELEM;
ret = adtfn(set, &nip, timeout);
if (ret && !ip_set_eexist(ret, flags))
@@ -214,9 +215,9 @@ hash_ip_same_set(const struct ip_set *a, const struct ip_set *b)
const struct ip_set_hash *y = b->data;
/* Resizing changes htable_bits, so we ignore it */
return x->maxelem == y->maxelem
&& x->timeout == y->timeout
&& x->netmask == y->netmask;
return x->maxelem == y->maxelem &&
x->timeout == y->timeout &&
x->netmask == y->netmask;
}
/* The type variant functions: IPv6 */
@@ -249,16 +250,6 @@ hash_ip6_data_copy(struct hash_ip6_elem *dst, const struct hash_ip6_elem *src)
ipv6_addr_copy(&dst->ip.in6, &src->ip.in6);
}
static inline void
hash_ip6_data_swap(struct hash_ip6_elem *dst, struct hash_ip6_elem *src)
{
struct in6_addr tmp;
ipv6_addr_copy(&tmp, &dst->ip.in6);
ipv6_addr_copy(&dst->ip.in6, &src->ip.in6);
ipv6_addr_copy(&src->ip.in6, &tmp);
}
static inline void
hash_ip6_data_zero_out(struct hash_ip6_elem *elem)
{
@@ -268,13 +259,13 @@ hash_ip6_data_zero_out(struct hash_ip6_elem *elem)
static inline void
ip6_netmask(union nf_inet_addr *ip, u8 prefix)
{
ip->ip6[0] &= NETMASK6(prefix)[0];
ip->ip6[1] &= NETMASK6(prefix)[1];
ip->ip6[2] &= NETMASK6(prefix)[2];
ip->ip6[3] &= NETMASK6(prefix)[3];
ip->ip6[0] &= ip_set_netmask6(prefix)[0];
ip->ip6[1] &= ip_set_netmask6(prefix)[1];
ip->ip6[2] &= ip_set_netmask6(prefix)[2];
ip->ip6[3] &= ip_set_netmask6(prefix)[3];
}
static inline bool
static bool
hash_ip6_data_list(struct sk_buff *skb, const struct hash_ip6_elem *data)
{
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
@@ -284,7 +275,7 @@ nla_put_failure:
return 1;
}
static inline bool
static bool
hash_ip6_data_tlist(struct sk_buff *skb, const struct hash_ip6_elem *data)
{
const struct hash_ip6_telem *e =
@@ -343,10 +334,14 @@ hash_ip6_uadt(struct ip_set *set, struct nlattr *head, int len,
hash_ip6_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_ipaddr6(tb, IPSET_ATTR_IP, &ip);
ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &ip);
if (ret)
return ret;
@@ -388,13 +383,18 @@ hash_ip_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
if (!(set->family == AF_INET || set->family == AF_INET6))
return -IPSET_ERR_INVALID_FAMILY;
netmask = set->family == AF_INET ? 32 : 128;
pr_debug("Create set %s with family %s",
pr_debug("Create set %s with family %s\n",
set->name, set->family == AF_INET ? "inet" : "inet6");
if (nla_parse(tb, IPSET_ATTR_CREATE_MAX, head, len,
hash_ip_create_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_HASHSIZE]) {
hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
if (hashsize < IPSET_MIMINAL_HASHSIZE)
@@ -407,9 +407,9 @@ hash_ip_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
if (tb[IPSET_ATTR_NETMASK]) {
netmask = nla_get_u8(tb[IPSET_ATTR_NETMASK]);
if ((set->family == AF_INET && netmask > 32)
|| (set->family == AF_INET6 && netmask > 128)
|| netmask == 0)
if ((set->family == AF_INET && netmask > 32) ||
(set->family == AF_INET6 && netmask > 128) ||
netmask == 0)
return -IPSET_ERR_INVALID_NETMASK;
}
@@ -450,7 +450,7 @@ hash_ip_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
? &hash_ip4_variant : &hash_ip6_variant;
}
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)",
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
set->name, jhash_size(h->table->htable_bits),
h->table->htable_bits, h->maxelem, set->data, h->table);

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2003-2010 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
/* 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
@@ -7,7 +7,6 @@
/* Kernel module implementing an IP set type: the hash:ip,port type */
#include "ip_set_kernel.h"
#include "jhash.h"
#include <linux/module.h>
#include <linux/ip.h>
@@ -23,6 +22,7 @@
#include <net/tcp.h>
#include <linux/netfilter.h>
#include "pfxlen.h"
#include "ip_set.h"
#include "ip_set_timeout.h"
#include "ip_set_getport.h"
@@ -46,16 +46,16 @@ hash_ipport_same_set(const struct ip_set *a, const struct ip_set *b);
/* Member elements without timeout */
struct hash_ipport4_elem {
u32 ip;
u16 port;
__be32 ip;
__be16 port;
u8 proto;
u8 padding;
};
/* Member elements with timeout support */
struct hash_ipport4_telem {
u32 ip;
u16 port;
__be32 ip;
__be16 port;
u8 proto;
u8 padding;
unsigned long timeout;
@@ -65,9 +65,9 @@ static inline bool
hash_ipport4_data_equal(const struct hash_ipport4_elem *ip1,
const struct hash_ipport4_elem *ip2)
{
return ip1->ip == ip2->ip
&& ip1->port == ip2->port
&& ip1->proto == ip2->proto;
return ip1->ip == ip2->ip &&
ip1->port == ip2->port &&
ip1->proto == ip2->proto;
}
static inline bool
@@ -85,22 +85,13 @@ hash_ipport4_data_copy(struct hash_ipport4_elem *dst,
dst->proto = src->proto;
}
static inline void
hash_ipport4_data_swap(struct hash_ipport4_elem *dst,
struct hash_ipport4_elem *src)
{
swap(dst->ip, src->ip);
swap(dst->port, src->port);
swap(dst->proto, src->proto);
}
static inline void
hash_ipport4_data_zero_out(struct hash_ipport4_elem *elem)
{
elem->proto = 0;
}
static inline bool
static bool
hash_ipport4_data_list(struct sk_buff *skb,
const struct hash_ipport4_elem *data)
{
@@ -113,7 +104,7 @@ nla_put_failure:
return 1;
}
static inline bool
static bool
hash_ipport4_data_tlist(struct sk_buff *skb,
const struct hash_ipport4_elem *data)
{
@@ -144,8 +135,8 @@ hash_ipport4_kadt(struct ip_set *set, const struct sk_buff *skb,
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipport4_elem data = { };
if (!get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
if (!ip_set_get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
return -EINVAL;
ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
@@ -181,15 +172,21 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *head, int len,
hash_ipport_adt_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!tb[IPSET_ATTR_IP] ||
!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &data.ip);
ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip);
if (ret)
return ret;
if (tb[IPSET_ATTR_PORT])
data.port = ip_set_get_n16(tb[IPSET_ATTR_PORT]);
data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
else
return -IPSET_ERR_PROTOCOL;
@@ -217,20 +214,19 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *head, int len,
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
}
if (adt == IPSET_TEST
|| !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP)
|| !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR]
|| tb[IPSET_ATTR_PORT_TO])) {
if (adt == IPSET_TEST ||
!(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
!(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
tb[IPSET_ATTR_PORT_TO])) {
ret = adtfn(set, &data, timeout);
return ip_set_eexist(ret, flags) ? 0 : ret;
}
ip = ntohl(data.ip);
if (tb[IPSET_ATTR_IP_TO]) {
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP_TO, &ip_to);
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
if (ret)
return ret;
ip_to = ntohl(ip_to);
if (ip > ip_to)
swap(ip, ip_to);
} else if (tb[IPSET_ATTR_CIDR]) {
@@ -238,8 +234,8 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *head, int len,
if (cidr > 32)
return -IPSET_ERR_INVALID_CIDR;
ip &= HOSTMASK(cidr);
ip_to = ip | ~HOSTMASK(cidr);
ip &= ip_set_hostmask(cidr);
ip_to = ip | ~ip_set_hostmask(cidr);
} else
ip_to = ip;
@@ -272,22 +268,22 @@ hash_ipport_same_set(const struct ip_set *a, const struct ip_set *b)
const struct ip_set_hash *y = b->data;
/* Resizing changes htable_bits, so we ignore it */
return x->maxelem == y->maxelem
&& x->timeout == y->timeout;
return x->maxelem == y->maxelem &&
x->timeout == y->timeout;
}
/* The type variant functions: IPv6 */
struct hash_ipport6_elem {
union nf_inet_addr ip;
u16 port;
__be16 port;
u8 proto;
u8 padding;
};
struct hash_ipport6_telem {
union nf_inet_addr ip;
u16 port;
__be16 port;
u8 proto;
u8 padding;
unsigned long timeout;
@@ -297,9 +293,9 @@ static inline bool
hash_ipport6_data_equal(const struct hash_ipport6_elem *ip1,
const struct hash_ipport6_elem *ip2)
{
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0
&& ip1->port == ip2->port
&& ip1->proto == ip2->proto;
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
ip1->port == ip2->port &&
ip1->proto == ip2->proto;
}
static inline bool
@@ -315,24 +311,13 @@ hash_ipport6_data_copy(struct hash_ipport6_elem *dst,
memcpy(dst, src, sizeof(*dst));
}
static inline void
hash_ipport6_data_swap(struct hash_ipport6_elem *dst,
struct hash_ipport6_elem *src)
{
struct hash_ipport6_elem tmp;
memcpy(&tmp, dst, sizeof(tmp));
memcpy(dst, src, sizeof(tmp));
memcpy(src, &tmp, sizeof(tmp));
}
static inline void
hash_ipport6_data_zero_out(struct hash_ipport6_elem *elem)
{
elem->proto = 0;
}
static inline bool
static bool
hash_ipport6_data_list(struct sk_buff *skb,
const struct hash_ipport6_elem *data)
{
@@ -345,7 +330,7 @@ nla_put_failure:
return 1;
}
static inline bool
static bool
hash_ipport6_data_tlist(struct sk_buff *skb,
const struct hash_ipport6_elem *data)
{
@@ -378,8 +363,8 @@ hash_ipport6_kadt(struct ip_set *set, const struct sk_buff *skb,
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipport6_elem data = { };
if (!get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
if (!ip_set_get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
return -EINVAL;
ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
@@ -403,15 +388,21 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *head, int len,
hash_ipport_adt_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!tb[IPSET_ATTR_IP] ||
!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP, &data.ip);
ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
if (ret)
return ret;
if (tb[IPSET_ATTR_PORT])
data.port = ip_set_get_n16(tb[IPSET_ATTR_PORT]);
data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
else
return -IPSET_ERR_PROTOCOL;
@@ -439,9 +430,9 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *head, int len,
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
}
if (adt == IPSET_TEST
|| !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP)
|| !tb[IPSET_ATTR_PORT_TO]) {
if (adt == IPSET_TEST ||
!(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
!tb[IPSET_ATTR_PORT_TO]) {
ret = adtfn(set, &data, timeout);
return ip_set_eexist(ret, flags) ? 0 : ret;
}
@@ -490,6 +481,11 @@ hash_ipport_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
hash_ipport_create_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_HASHSIZE]) {
hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
if (hashsize < IPSET_MIMINAL_HASHSIZE)
@@ -535,7 +531,7 @@ hash_ipport_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
? &hash_ipport4_variant : &hash_ipport6_variant;
}
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)",
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
set->name, jhash_size(h->table->htable_bits),
h->table->htable_bits, h->maxelem, set->data, h->table);

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2003-2010 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
/* 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
@@ -7,7 +7,6 @@
/* Kernel module implementing an IP set type: the hash:ip,port,ip type */
#include "ip_set_kernel.h"
#include "jhash.h"
#include <linux/module.h>
#include <linux/ip.h>
@@ -23,6 +22,7 @@
#include <net/tcp.h>
#include <linux/netfilter.h>
#include "pfxlen.h"
#include "ip_set.h"
#include "ip_set_timeout.h"
#include "ip_set_getport.h"
@@ -46,18 +46,18 @@ hash_ipportip_same_set(const struct ip_set *a, const struct ip_set *b);
/* Member elements without timeout */
struct hash_ipportip4_elem {
u32 ip;
u32 ip2;
u16 port;
__be32 ip;
__be32 ip2;
__be16 port;
u8 proto;
u8 padding;
};
/* Member elements with timeout support */
struct hash_ipportip4_telem {
u32 ip;
u32 ip2;
u16 port;
__be32 ip;
__be32 ip2;
__be16 port;
u8 proto;
u8 padding;
unsigned long timeout;
@@ -67,10 +67,10 @@ static inline bool
hash_ipportip4_data_equal(const struct hash_ipportip4_elem *ip1,
const struct hash_ipportip4_elem *ip2)
{
return ip1->ip == ip2->ip
&& ip1->ip2 == ip2->ip2
&& ip1->port == ip2->port
&& ip1->proto == ip2->proto;
return ip1->ip == ip2->ip &&
ip1->ip2 == ip2->ip2 &&
ip1->port == ip2->port &&
ip1->proto == ip2->proto;
}
static inline bool
@@ -86,24 +86,13 @@ hash_ipportip4_data_copy(struct hash_ipportip4_elem *dst,
memcpy(dst, src, sizeof(*dst));
}
static inline void
hash_ipportip4_data_swap(struct hash_ipportip4_elem *dst,
struct hash_ipportip4_elem *src)
{
struct hash_ipportip4_elem tmp;
memcpy(&tmp, dst, sizeof(tmp));
memcpy(dst, src, sizeof(tmp));
memcpy(src, &tmp, sizeof(tmp));
}
static inline void
hash_ipportip4_data_zero_out(struct hash_ipportip4_elem *elem)
{
elem->proto = 0;
}
static inline bool
static bool
hash_ipportip4_data_list(struct sk_buff *skb,
const struct hash_ipportip4_elem *data)
{
@@ -117,7 +106,7 @@ nla_put_failure:
return 1;
}
static inline bool
static bool
hash_ipportip4_data_tlist(struct sk_buff *skb,
const struct hash_ipportip4_elem *data)
{
@@ -149,8 +138,8 @@ hash_ipportip4_kadt(struct ip_set *set, const struct sk_buff *skb,
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipportip4_elem data = { };
if (!get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
if (!ip_set_get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
return -EINVAL;
ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
@@ -188,19 +177,25 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *head, int len,
hash_ipportip_adt_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &data.ip);
ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip);
if (ret)
return ret;
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP2, &data.ip2);
ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP2], &data.ip2);
if (ret)
return ret;
if (tb[IPSET_ATTR_PORT])
data.port = ip_set_get_n16(tb[IPSET_ATTR_PORT]);
data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
else
return -IPSET_ERR_PROTOCOL;
@@ -228,20 +223,19 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *head, int len,
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
}
if (adt == IPSET_TEST
|| !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP)
|| !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR]
|| tb[IPSET_ATTR_PORT_TO])) {
if (adt == IPSET_TEST ||
!(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
!(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
tb[IPSET_ATTR_PORT_TO])) {
ret = adtfn(set, &data, timeout);
return ip_set_eexist(ret, flags) ? 0 : ret;
}
ip = ntohl(data.ip);
if (tb[IPSET_ATTR_IP_TO]) {
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP_TO, &ip_to);
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
if (ret)
return ret;
ip_to = ntohl(ip_to);
if (ip > ip_to)
swap(ip, ip_to);
} else if (tb[IPSET_ATTR_CIDR]) {
@@ -249,8 +243,8 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *head, int len,
if (cidr > 32)
return -IPSET_ERR_INVALID_CIDR;
ip &= HOSTMASK(cidr);
ip_to = ip | ~HOSTMASK(cidr);
ip &= ip_set_hostmask(cidr);
ip_to = ip | ~ip_set_hostmask(cidr);
} else
ip_to = ip;
@@ -283,8 +277,8 @@ hash_ipportip_same_set(const struct ip_set *a, const struct ip_set *b)
const struct ip_set_hash *y = b->data;
/* Resizing changes htable_bits, so we ignore it */
return x->maxelem == y->maxelem
&& x->timeout == y->timeout;
return x->maxelem == y->maxelem &&
x->timeout == y->timeout;
}
/* The type variant functions: IPv6 */
@@ -292,7 +286,7 @@ hash_ipportip_same_set(const struct ip_set *a, const struct ip_set *b)
struct hash_ipportip6_elem {
union nf_inet_addr ip;
union nf_inet_addr ip2;
u16 port;
__be16 port;
u8 proto;
u8 padding;
};
@@ -300,7 +294,7 @@ struct hash_ipportip6_elem {
struct hash_ipportip6_telem {
union nf_inet_addr ip;
union nf_inet_addr ip2;
u16 port;
__be16 port;
u8 proto;
u8 padding;
unsigned long timeout;
@@ -310,10 +304,10 @@ static inline bool
hash_ipportip6_data_equal(const struct hash_ipportip6_elem *ip1,
const struct hash_ipportip6_elem *ip2)
{
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0
&& ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0
&& ip1->port == ip2->port
&& ip1->proto == ip2->proto;
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 &&
ip1->port == ip2->port &&
ip1->proto == ip2->proto;
}
static inline bool
@@ -329,24 +323,13 @@ hash_ipportip6_data_copy(struct hash_ipportip6_elem *dst,
memcpy(dst, src, sizeof(*dst));
}
static inline void
hash_ipportip6_data_swap(struct hash_ipportip6_elem *dst,
struct hash_ipportip6_elem *src)
{
struct hash_ipportip6_elem tmp;
memcpy(&tmp, dst, sizeof(tmp));
memcpy(dst, src, sizeof(tmp));
memcpy(src, &tmp, sizeof(tmp));
}
static inline void
hash_ipportip6_data_zero_out(struct hash_ipportip6_elem *elem)
{
elem->proto = 0;
}
static inline bool
static bool
hash_ipportip6_data_list(struct sk_buff *skb,
const struct hash_ipportip6_elem *data)
{
@@ -360,7 +343,7 @@ nla_put_failure:
return 1;
}
static inline bool
static bool
hash_ipportip6_data_tlist(struct sk_buff *skb,
const struct hash_ipportip6_elem *data)
{
@@ -394,8 +377,8 @@ hash_ipportip6_kadt(struct ip_set *set, const struct sk_buff *skb,
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipportip6_elem data = { };
if (!get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
if (!ip_set_get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
return -EINVAL;
ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
@@ -420,19 +403,25 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *head, int len,
hash_ipportip_adt_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP, &data.ip);
ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
if (ret)
return ret;
ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP2, &data.ip2);
ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP2], &data.ip2);
if (ret)
return ret;
if (tb[IPSET_ATTR_PORT])
data.port = ip_set_get_n16(tb[IPSET_ATTR_PORT]);
data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
else
return -IPSET_ERR_PROTOCOL;
@@ -460,9 +449,9 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *head, int len,
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
}
if (adt == IPSET_TEST
|| !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP)
|| !tb[IPSET_ATTR_PORT_TO]) {
if (adt == IPSET_TEST ||
!(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
!tb[IPSET_ATTR_PORT_TO]) {
ret = adtfn(set, &data, timeout);
return ip_set_eexist(ret, flags) ? 0 : ret;
}
@@ -511,6 +500,11 @@ hash_ipportip_create(struct ip_set *set, struct nlattr *head,
hash_ipportip_create_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_HASHSIZE]) {
hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
if (hashsize < IPSET_MIMINAL_HASHSIZE)
@@ -556,7 +550,7 @@ hash_ipportip_create(struct ip_set *set, struct nlattr *head,
? &hash_ipportip4_variant : &hash_ipportip6_variant;
}
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)",
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
set->name, jhash_size(h->table->htable_bits),
h->table->htable_bits, h->maxelem, set->data, h->table);

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2003-2010 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
/* 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
@@ -7,7 +7,6 @@
/* Kernel module implementing an IP set type: the hash:ip,port,net type */
#include "ip_set_kernel.h"
#include "jhash.h"
#include <linux/module.h>
#include <linux/ip.h>
@@ -23,6 +22,7 @@
#include <net/tcp.h>
#include <linux/netfilter.h>
#include "pfxlen.h"
#include "ip_set.h"
#include "ip_set_timeout.h"
#include "ip_set_getport.h"
@@ -46,18 +46,18 @@ hash_ipportnet_same_set(const struct ip_set *a, const struct ip_set *b);
/* Member elements without timeout */
struct hash_ipportnet4_elem {
u32 ip;
u32 ip2;
u16 port;
__be32 ip;
__be32 ip2;
__be16 port;
u8 cidr;
u8 proto;
};
/* Member elements with timeout support */
struct hash_ipportnet4_telem {
u32 ip;
u32 ip2;
u16 port;
__be32 ip;
__be32 ip2;
__be16 port;
u8 cidr;
u8 proto;
unsigned long timeout;
@@ -67,11 +67,11 @@ static inline bool
hash_ipportnet4_data_equal(const struct hash_ipportnet4_elem *ip1,
const struct hash_ipportnet4_elem *ip2)
{
return ip1->ip == ip2->ip
&& ip1->ip2 == ip2->ip2
&& ip1->cidr == ip2->cidr
&& ip1->port == ip2->port
&& ip1->proto == ip2->proto;
return ip1->ip == ip2->ip &&
ip1->ip2 == ip2->ip2 &&
ip1->cidr == ip2->cidr &&
ip1->port == ip2->port &&
ip1->proto == ip2->proto;
}
static inline bool
@@ -87,21 +87,10 @@ hash_ipportnet4_data_copy(struct hash_ipportnet4_elem *dst,
memcpy(dst, src, sizeof(*dst));
}
static inline void
hash_ipportnet4_data_swap(struct hash_ipportnet4_elem *dst,
struct hash_ipportnet4_elem *src)
{
struct hash_ipportnet4_elem tmp;
memcpy(&tmp, dst, sizeof(tmp));
memcpy(dst, src, sizeof(tmp));
memcpy(src, &tmp, sizeof(tmp));
}
static inline void
hash_ipportnet4_data_netmask(struct hash_ipportnet4_elem *elem, u8 cidr)
{
elem->ip2 &= NETMASK(cidr);
elem->ip2 &= ip_set_netmask(cidr);
elem->cidr = cidr;
}
@@ -111,7 +100,7 @@ hash_ipportnet4_data_zero_out(struct hash_ipportnet4_elem *elem)
elem->proto = 0;
}
static inline bool
static bool
hash_ipportnet4_data_list(struct sk_buff *skb,
const struct hash_ipportnet4_elem *data)
{
@@ -126,7 +115,7 @@ nla_put_failure:
return 1;
}
static inline bool
static bool
hash_ipportnet4_data_tlist(struct sk_buff *skb,
const struct hash_ipportnet4_elem *data)
{
@@ -168,13 +157,13 @@ hash_ipportnet4_kadt(struct ip_set *set, const struct sk_buff *skb,
if (adt == IPSET_TEST)
data.cidr = HOST_MASK;
if (!get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
if (!ip_set_get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
return -EINVAL;
ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
ip4addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2);
data.ip2 &= NETMASK(data.cidr);
data.ip2 &= ip_set_netmask(data.cidr);
return adtfn(set, &data, h->timeout);
}
@@ -209,14 +198,20 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *head, int len,
hash_ipportnet_adt_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &data.ip);
ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip);
if (ret)
return ret;
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP2, &data.ip2);
ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP2], &data.ip2);
if (ret)
return ret;
@@ -226,16 +221,16 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *head, int len,
if (!data.cidr)
return -IPSET_ERR_INVALID_CIDR;
data.ip2 &= NETMASK(data.cidr);
data.ip2 &= ip_set_netmask(data.cidr);
if (tb[IPSET_ATTR_PORT])
data.port = ip_set_get_n16(tb[IPSET_ATTR_PORT]);
data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
else
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_PROTO]) {
data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
if (data.proto == 0)
return -IPSET_ERR_INVALID_PROTO;
} else
@@ -257,20 +252,19 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *head, int len,
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
}
if (adt == IPSET_TEST
|| !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP)
|| !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR]
|| tb[IPSET_ATTR_PORT_TO])) {
if (adt == IPSET_TEST ||
!(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
!(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
tb[IPSET_ATTR_PORT_TO])) {
ret = adtfn(set, &data, timeout);
return ip_set_eexist(ret, flags) ? 0 : ret;
}
ip = ntohl(data.ip);
if (tb[IPSET_ATTR_IP_TO]) {
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP_TO, &ip_to);
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
if (ret)
return ret;
ip_to = ntohl(ip_to);
if (ip > ip_to)
swap(ip, ip_to);
} else if (tb[IPSET_ATTR_CIDR]) {
@@ -278,8 +272,8 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *head, int len,
if (cidr > 32)
return -IPSET_ERR_INVALID_CIDR;
ip &= HOSTMASK(cidr);
ip_to = ip | ~HOSTMASK(cidr);
ip &= ip_set_hostmask(cidr);
ip_to = ip | ~ip_set_hostmask(cidr);
} else
ip_to = ip;
@@ -310,10 +304,10 @@ hash_ipportnet_same_set(const struct ip_set *a, const struct ip_set *b)
{
const struct ip_set_hash *x = a->data;
const struct ip_set_hash *y = b->data;
/* Resizing changes htable_bits, so we ignore it */
return x->maxelem == y->maxelem
&& x->timeout == y->timeout;
return x->maxelem == y->maxelem &&
x->timeout == y->timeout;
}
/* The type variant functions: IPv6 */
@@ -321,7 +315,7 @@ hash_ipportnet_same_set(const struct ip_set *a, const struct ip_set *b)
struct hash_ipportnet6_elem {
union nf_inet_addr ip;
union nf_inet_addr ip2;
u16 port;
__be16 port;
u8 cidr;
u8 proto;
};
@@ -329,7 +323,7 @@ struct hash_ipportnet6_elem {
struct hash_ipportnet6_telem {
union nf_inet_addr ip;
union nf_inet_addr ip2;
u16 port;
__be16 port;
u8 cidr;
u8 proto;
unsigned long timeout;
@@ -339,11 +333,11 @@ static inline bool
hash_ipportnet6_data_equal(const struct hash_ipportnet6_elem *ip1,
const struct hash_ipportnet6_elem *ip2)
{
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0
&& ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0
&& ip1->cidr == ip2->cidr
&& ip1->port == ip2->port
&& ip1->proto == ip2->proto;
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 &&
ip1->cidr == ip2->cidr &&
ip1->port == ip2->port &&
ip1->proto == ip2->proto;
}
static inline bool
@@ -359,17 +353,6 @@ hash_ipportnet6_data_copy(struct hash_ipportnet6_elem *dst,
memcpy(dst, src, sizeof(*dst));
}
static inline void
hash_ipportnet6_data_swap(struct hash_ipportnet6_elem *dst,
struct hash_ipportnet6_elem *src)
{
struct hash_ipportnet6_elem tmp;
memcpy(&tmp, dst, sizeof(tmp));
memcpy(dst, src, sizeof(tmp));
memcpy(src, &tmp, sizeof(tmp));
}
static inline void
hash_ipportnet6_data_zero_out(struct hash_ipportnet6_elem *elem)
{
@@ -379,10 +362,10 @@ hash_ipportnet6_data_zero_out(struct hash_ipportnet6_elem *elem)
static inline void
ip6_netmask(union nf_inet_addr *ip, u8 prefix)
{
ip->ip6[0] &= NETMASK6(prefix)[0];
ip->ip6[1] &= NETMASK6(prefix)[1];
ip->ip6[2] &= NETMASK6(prefix)[2];
ip->ip6[3] &= NETMASK6(prefix)[3];
ip->ip6[0] &= ip_set_netmask6(prefix)[0];
ip->ip6[1] &= ip_set_netmask6(prefix)[1];
ip->ip6[2] &= ip_set_netmask6(prefix)[2];
ip->ip6[3] &= ip_set_netmask6(prefix)[3];
}
static inline void
@@ -392,7 +375,7 @@ hash_ipportnet6_data_netmask(struct hash_ipportnet6_elem *elem, u8 cidr)
elem->cidr = cidr;
}
static inline bool
static bool
hash_ipportnet6_data_list(struct sk_buff *skb,
const struct hash_ipportnet6_elem *data)
{
@@ -407,13 +390,13 @@ nla_put_failure:
return 1;
}
static inline bool
static bool
hash_ipportnet6_data_tlist(struct sk_buff *skb,
const struct hash_ipportnet6_elem *data)
{
const struct hash_ipportnet6_telem *e =
const struct hash_ipportnet6_telem *e =
(const struct hash_ipportnet6_telem *)data;
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2);
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
@@ -448,8 +431,8 @@ hash_ipportnet6_kadt(struct ip_set *set, const struct sk_buff *skb,
if (adt == IPSET_TEST)
data.cidr = HOST_MASK;
if (!get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
if (!ip_set_get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
return -EINVAL;
ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
@@ -475,14 +458,20 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *head, int len,
hash_ipportnet_adt_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP, &data.ip);
ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
if (ret)
return ret;
ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP2, &data.ip2);
ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP2], &data.ip2);
if (ret)
return ret;
@@ -495,7 +484,7 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *head, int len,
ip6_netmask(&data.ip2, data.cidr);
if (tb[IPSET_ATTR_PORT])
data.port = ip_set_get_n16(tb[IPSET_ATTR_PORT]);
data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
else
return -IPSET_ERR_PROTOCOL;
@@ -523,9 +512,9 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *head, int len,
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
}
if (adt == IPSET_TEST
|| !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP)
|| !tb[IPSET_ATTR_PORT_TO]) {
if (adt == IPSET_TEST ||
!(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
!tb[IPSET_ATTR_PORT_TO]) {
ret = adtfn(set, &data, timeout);
return ip_set_eexist(ret, flags) ? 0 : ret;
}
@@ -574,6 +563,11 @@ hash_ipportnet_create(struct ip_set *set, struct nlattr *head,
hash_ipportnet_create_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_HASHSIZE]) {
hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
if (hashsize < IPSET_MIMINAL_HASHSIZE)
@@ -608,7 +602,7 @@ hash_ipportnet_create(struct ip_set *set, struct nlattr *head,
if (tb[IPSET_ATTR_TIMEOUT]) {
h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
set->variant = set->family == AF_INET
? &hash_ipportnet4_tvariant
: &hash_ipportnet6_tvariant;
@@ -621,11 +615,11 @@ hash_ipportnet_create(struct ip_set *set, struct nlattr *head,
set->variant = set->family == AF_INET
? &hash_ipportnet4_variant : &hash_ipportnet6_variant;
}
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)",
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
set->name, jhash_size(h->table->htable_bits),
h->table->htable_bits, h->maxelem, set->data, h->table);
return 0;
}

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2003-2010 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
/* 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
@@ -7,7 +7,6 @@
/* Kernel module implementing an IP set type: the hash:net type */
#include "ip_set_kernel.h"
#include "jhash.h"
#include <linux/module.h>
#include <linux/ip.h>
@@ -22,6 +21,7 @@
#include <net/netlink.h>
#include <linux/netfilter.h>
#include "pfxlen.h"
#include "ip_set.h"
#include "ip_set_timeout.h"
#include "ip_set_hash.h"
@@ -44,7 +44,7 @@ hash_net_same_set(const struct ip_set *a, const struct ip_set *b);
/* Member elements without timeout */
struct hash_net4_elem {
u32 ip;
__be32 ip;
u16 padding0;
u8 padding1;
u8 cidr;
@@ -52,7 +52,7 @@ struct hash_net4_elem {
/* Member elements with timeout support */
struct hash_net4_telem {
u32 ip;
__be32 ip;
u16 padding0;
u8 padding1;
u8 cidr;
@@ -80,18 +80,10 @@ hash_net4_data_copy(struct hash_net4_elem *dst,
dst->cidr = src->cidr;
}
static inline void
hash_net4_data_swap(struct hash_net4_elem *dst,
struct hash_net4_elem *src)
{
swap(dst->ip, src->ip);
swap(dst->cidr, src->cidr);
}
static inline void
hash_net4_data_netmask(struct hash_net4_elem *elem, u8 cidr)
{
elem->ip &= NETMASK(cidr);
elem->ip &= ip_set_netmask(cidr);
elem->cidr = cidr;
}
@@ -102,7 +94,7 @@ hash_net4_data_zero_out(struct hash_net4_elem *elem)
elem->cidr = 0;
}
static inline bool
static bool
hash_net4_data_list(struct sk_buff *skb, const struct hash_net4_elem *data)
{
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
@@ -113,7 +105,7 @@ nla_put_failure:
return 1;
}
static inline bool
static bool
hash_net4_data_tlist(struct sk_buff *skb, const struct hash_net4_elem *data)
{
const struct hash_net4_telem *tdata =
@@ -150,7 +142,7 @@ hash_net4_kadt(struct ip_set *set, const struct sk_buff *skb,
data.cidr = HOST_MASK;
ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
data.ip &= NETMASK(data.cidr);
data.ip &= ip_set_netmask(data.cidr);
return adtfn(set, &data, h->timeout);
}
@@ -176,10 +168,14 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *head, int len,
hash_net_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_ipaddr4(tb, IPSET_ATTR_IP, &data.ip);
ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip);
if (ret)
return ret;
@@ -189,7 +185,7 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *head, int len,
if (!data.cidr)
return -IPSET_ERR_INVALID_CIDR;
data.ip &= NETMASK(data.cidr);
data.ip &= ip_set_netmask(data.cidr);
if (tb[IPSET_ATTR_TIMEOUT]) {
if (!with_timeout(h->timeout))
@@ -209,8 +205,8 @@ hash_net_same_set(const struct ip_set *a, const struct ip_set *b)
const struct ip_set_hash *y = b->data;
/* Resizing changes htable_bits, so we ignore it */
return x->maxelem == y->maxelem
&& x->timeout == y->timeout;
return x->maxelem == y->maxelem &&
x->timeout == y->timeout;
}
/* The type variant functions: IPv6 */
@@ -234,8 +230,8 @@ static inline bool
hash_net6_data_equal(const struct hash_net6_elem *ip1,
const struct hash_net6_elem *ip2)
{
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0
&& ip1->cidr == ip2->cidr;
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
ip1->cidr == ip2->cidr;
}
static inline bool
@@ -252,16 +248,6 @@ hash_net6_data_copy(struct hash_net6_elem *dst,
dst->cidr = src->cidr;
}
static inline void
hash_net6_data_swap(struct hash_net6_elem *dst, struct hash_net6_elem *src)
{
struct hash_net6_elem tmp;
memcpy(&tmp, dst, sizeof(tmp));
memcpy(dst, src, sizeof(tmp));
memcpy(src, &tmp, sizeof(tmp));
}
static inline void
hash_net6_data_zero_out(struct hash_net6_elem *elem)
{
@@ -271,10 +257,10 @@ hash_net6_data_zero_out(struct hash_net6_elem *elem)
static inline void
ip6_netmask(union nf_inet_addr *ip, u8 prefix)
{
ip->ip6[0] &= NETMASK6(prefix)[0];
ip->ip6[1] &= NETMASK6(prefix)[1];
ip->ip6[2] &= NETMASK6(prefix)[2];
ip->ip6[3] &= NETMASK6(prefix)[3];
ip->ip6[0] &= ip_set_netmask6(prefix)[0];
ip->ip6[1] &= ip_set_netmask6(prefix)[1];
ip->ip6[2] &= ip_set_netmask6(prefix)[2];
ip->ip6[3] &= ip_set_netmask6(prefix)[3];
}
static inline void
@@ -284,7 +270,7 @@ hash_net6_data_netmask(struct hash_net6_elem *elem, u8 cidr)
elem->cidr = cidr;
}
static inline bool
static bool
hash_net6_data_list(struct sk_buff *skb, const struct hash_net6_elem *data)
{
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
@@ -295,7 +281,7 @@ nla_put_failure:
return 1;
}
static inline bool
static bool
hash_net6_data_tlist(struct sk_buff *skb, const struct hash_net6_elem *data)
{
const struct hash_net6_telem *e =
@@ -352,10 +338,14 @@ hash_net6_uadt(struct ip_set *set, struct nlattr *head, int len,
hash_net_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_ipaddr6(tb, IPSET_ATTR_IP, &data.ip);
ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
if (ret)
return ret;
@@ -404,6 +394,11 @@ hash_net_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
hash_net_create_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_HASHSIZE]) {
hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
if (hashsize < IPSET_MIMINAL_HASHSIZE)
@@ -451,7 +446,7 @@ hash_net_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
? &hash_net4_variant : &hash_net6_variant;
}
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)",
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
set->name, jhash_size(h->table->htable_bits),
h->table->htable_bits, h->maxelem, set->data, h->table);

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2003-2010 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
/* 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
@@ -7,7 +7,6 @@
/* Kernel module implementing an IP set type: the hash:net,port type */
#include "ip_set_kernel.h"
#include "jhash.h"
#include <linux/module.h>
#include <linux/ip.h>
@@ -22,6 +21,7 @@
#include <net/netlink.h>
#include <linux/netfilter.h>
#include "pfxlen.h"
#include "ip_set.h"
#include "ip_set_timeout.h"
#include "ip_set_getport.h"
@@ -45,16 +45,16 @@ hash_netport_same_set(const struct ip_set *a, const struct ip_set *b);
/* Member elements without timeout */
struct hash_netport4_elem {
u32 ip;
u16 port;
__be32 ip;
__be16 port;
u8 proto;
u8 cidr;
};
/* Member elements with timeout support */
struct hash_netport4_telem {
u32 ip;
u16 port;
__be32 ip;
__be16 port;
u8 proto;
u8 cidr;
unsigned long timeout;
@@ -64,10 +64,10 @@ static inline bool
hash_netport4_data_equal(const struct hash_netport4_elem *ip1,
const struct hash_netport4_elem *ip2)
{
return ip1->ip == ip2->ip
&& ip1->port == ip2->port
&& ip1->proto == ip2->proto
&& ip1->cidr == ip2->cidr;
return ip1->ip == ip2->ip &&
ip1->port == ip2->port &&
ip1->proto == ip2->proto &&
ip1->cidr == ip2->cidr;
}
static inline bool
@@ -86,20 +86,10 @@ hash_netport4_data_copy(struct hash_netport4_elem *dst,
dst->cidr = src->cidr;
}
static inline void
hash_netport4_data_swap(struct hash_netport4_elem *dst,
struct hash_netport4_elem *src)
{
swap(dst->ip, src->ip);
swap(dst->port, src->port);
swap(dst->proto, src->proto);
swap(dst->cidr, src->cidr);
}
static inline void
hash_netport4_data_netmask(struct hash_netport4_elem *elem, u8 cidr)
{
elem->ip &= NETMASK(cidr);
elem->ip &= ip_set_netmask(cidr);
elem->cidr = cidr;
}
@@ -109,7 +99,7 @@ hash_netport4_data_zero_out(struct hash_netport4_elem *elem)
elem->proto = 0;
}
static inline bool
static bool
hash_netport4_data_list(struct sk_buff *skb,
const struct hash_netport4_elem *data)
{
@@ -123,7 +113,7 @@ nla_put_failure:
return 1;
}
static inline bool
static bool
hash_netport4_data_tlist(struct sk_buff *skb,
const struct hash_netport4_elem *data)
{
@@ -164,12 +154,12 @@ hash_netport4_kadt(struct ip_set *set, const struct sk_buff *skb,
if (adt == IPSET_TEST)
data.cidr = HOST_MASK;
if (!get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
if (!ip_set_get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
return -EINVAL;
ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
data.ip &= NETMASK(data.cidr);
data.ip &= ip_set_netmask(data.cidr);
return adtfn(set, &data, h->timeout);
}
@@ -201,10 +191,16 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *head, int len,
hash_netport_adt_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!tb[IPSET_ATTR_IP] ||
!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &data.ip);
ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip);
if (ret)
return ret;
@@ -212,10 +208,10 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *head, int len,
data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
if (!data.cidr)
return -IPSET_ERR_INVALID_CIDR;
data.ip &= NETMASK(data.cidr);
data.ip &= ip_set_netmask(data.cidr);
if (tb[IPSET_ATTR_PORT])
data.port = ip_set_get_n16(tb[IPSET_ATTR_PORT]);
data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
else
return -IPSET_ERR_PROTOCOL;
@@ -243,9 +239,9 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *head, int len,
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
}
if (adt == IPSET_TEST
|| !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP)
|| !tb[IPSET_ATTR_PORT_TO]) {
if (adt == IPSET_TEST ||
!(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
!tb[IPSET_ATTR_PORT_TO]) {
ret = adtfn(set, &data, timeout);
return ip_set_eexist(ret, flags) ? 0 : ret;
}
@@ -274,22 +270,22 @@ hash_netport_same_set(const struct ip_set *a, const struct ip_set *b)
const struct ip_set_hash *y = b->data;
/* Resizing changes htable_bits, so we ignore it */
return x->maxelem == y->maxelem
&& x->timeout == y->timeout;
return x->maxelem == y->maxelem &&
x->timeout == y->timeout;
}
/* The type variant functions: IPv6 */
struct hash_netport6_elem {
union nf_inet_addr ip;
u16 port;
__be16 port;
u8 proto;
u8 cidr;
};
struct hash_netport6_telem {
union nf_inet_addr ip;
u16 port;
__be16 port;
u8 proto;
u8 cidr;
unsigned long timeout;
@@ -299,10 +295,10 @@ static inline bool
hash_netport6_data_equal(const struct hash_netport6_elem *ip1,
const struct hash_netport6_elem *ip2)
{
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0
&& ip1->port == ip2->port
&& ip1->proto == ip2->proto
&& ip1->cidr == ip2->cidr;
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
ip1->port == ip2->port &&
ip1->proto == ip2->proto &&
ip1->cidr == ip2->cidr;
}
static inline bool
@@ -318,17 +314,6 @@ hash_netport6_data_copy(struct hash_netport6_elem *dst,
memcpy(dst, src, sizeof(*dst));
}
static inline void
hash_netport6_data_swap(struct hash_netport6_elem *dst,
struct hash_netport6_elem *src)
{
struct hash_netport6_elem tmp;
memcpy(&tmp, dst, sizeof(tmp));
memcpy(dst, src, sizeof(tmp));
memcpy(src, &tmp, sizeof(tmp));
}
static inline void
hash_netport6_data_zero_out(struct hash_netport6_elem *elem)
{
@@ -338,10 +323,10 @@ hash_netport6_data_zero_out(struct hash_netport6_elem *elem)
static inline void
ip6_netmask(union nf_inet_addr *ip, u8 prefix)
{
ip->ip6[0] &= NETMASK6(prefix)[0];
ip->ip6[1] &= NETMASK6(prefix)[1];
ip->ip6[2] &= NETMASK6(prefix)[2];
ip->ip6[3] &= NETMASK6(prefix)[3];
ip->ip6[0] &= ip_set_netmask6(prefix)[0];
ip->ip6[1] &= ip_set_netmask6(prefix)[1];
ip->ip6[2] &= ip_set_netmask6(prefix)[2];
ip->ip6[3] &= ip_set_netmask6(prefix)[3];
}
static inline void
@@ -351,7 +336,7 @@ hash_netport6_data_netmask(struct hash_netport6_elem *elem, u8 cidr)
elem->cidr = cidr;
}
static inline bool
static bool
hash_netport6_data_list(struct sk_buff *skb,
const struct hash_netport6_elem *data)
{
@@ -365,7 +350,7 @@ nla_put_failure:
return 1;
}
static inline bool
static bool
hash_netport6_data_tlist(struct sk_buff *skb,
const struct hash_netport6_elem *data)
{
@@ -405,8 +390,8 @@ hash_netport6_kadt(struct ip_set *set, const struct sk_buff *skb,
if (adt == IPSET_TEST)
data.cidr = HOST_MASK;
if (!get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
if (!ip_set_get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
&data.port, &data.proto))
return -EINVAL;
ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
@@ -431,10 +416,16 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *head, int len,
hash_netport_adt_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!tb[IPSET_ATTR_IP] ||
!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP, &data.ip);
ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
if (ret)
return ret;
@@ -445,7 +436,7 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *head, int len,
ip6_netmask(&data.ip, data.cidr);
if (tb[IPSET_ATTR_PORT])
data.port = ip_set_get_n16(tb[IPSET_ATTR_PORT]);
data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
else
return -IPSET_ERR_PROTOCOL;
@@ -473,9 +464,9 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *head, int len,
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
}
if (adt == IPSET_TEST
|| !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP)
|| !tb[IPSET_ATTR_PORT_TO]) {
if (adt == IPSET_TEST ||
!(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
!tb[IPSET_ATTR_PORT_TO]) {
ret = adtfn(set, &data, timeout);
return ip_set_eexist(ret, flags) ? 0 : ret;
}
@@ -524,6 +515,11 @@ hash_netport_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
hash_netport_create_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_HASHSIZE]) {
hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
if (hashsize < IPSET_MIMINAL_HASHSIZE)
@@ -571,7 +567,7 @@ hash_netport_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
? &hash_netport4_variant : &hash_netport6_variant;
}
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)",
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
set->name, jhash_size(h->table->htable_bits),
h->table->htable_bits, h->maxelem, set->data, h->table);

View File

@@ -1,15 +0,0 @@
#ifndef _IP_SET_KERNEL_H
#define _IP_SET_KERNEL_H
#ifdef __KERNEL__
#ifdef CONFIG_DEBUG_KERNEL
/* Complete debug messages */
#define pr_fmt(fmt) "%s %s[%i]: " fmt "\n", __FILE__, __func__, __LINE__
#endif
#include <linux/kernel.h>
#endif /* __KERNEL__ */
#endif /*_IP_SET_H */

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2008-2010 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
/* Copyright (C) 2008-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -7,7 +7,6 @@
/* Kernel module implementing an IP set type: the list:set type */
#include "ip_set_kernel.h"
#include <linux/module.h>
#include <linux/ip.h>
#include <linux/skbuff.h>
@@ -68,8 +67,8 @@ list_set_expired(const struct list_set *map, u32 id)
static inline int
list_set_exist(const struct set_telem *elem)
{
return elem->id != IPSET_INVALID_ID
&& !ip_set_timeout_expired(elem->timeout);
return elem->id != IPSET_INVALID_ID &&
!ip_set_timeout_expired(elem->timeout);
}
/* Set list without and with timeout */
@@ -122,22 +121,22 @@ static const struct nla_policy list_set_adt_policy[IPSET_ATTR_ADT_MAX+1] = {
[IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
};
static inline bool
static bool
next_id_eq(const struct list_set *map, u32 i, ip_set_id_t id)
{
const struct set_elem *elem;
if (i + 1 < map->size) {
elem = list_set_elem(map, i + 1);
return !!(elem->id == id
&& !(with_timeout(map->timeout)
&& list_set_expired(map, i + 1)));
return !!(elem->id == id &&
!(with_timeout(map->timeout) &&
list_set_expired(map, i + 1)));
}
return 0;
}
static inline void
static void
list_elem_add(struct list_set *map, u32 i, ip_set_id_t id)
{
struct set_elem *e;
@@ -150,7 +149,7 @@ list_elem_add(struct list_set *map, u32 i, ip_set_id_t id)
}
}
static inline void
static void
list_elem_tadd(struct list_set *map, u32 i, ip_set_id_t id,
unsigned long timeout)
{
@@ -223,20 +222,22 @@ list_set_uadt(struct ip_set *set, struct nlattr *head, int len,
list_set_adt_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!tb[IPSET_ATTR_NAME] ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
if (tb[IPSET_ATTR_NAME]) {
id = ip_set_get_byname(nla_data(tb[IPSET_ATTR_NAME]), &s);
if (id == IPSET_INVALID_ID)
return -IPSET_ERR_NAME;
/* "Loop detection" */
if (s->type->features & IPSET_TYPE_NAME) {
ret = -IPSET_ERR_LOOP;
goto finish;
}
} else
return -IPSET_ERR_PROTOCOL;
id = ip_set_get_byname(nla_data(tb[IPSET_ATTR_NAME]), &s);
if (id == IPSET_INVALID_ID)
return -IPSET_ERR_NAME;
/* "Loop detection" */
if (s->type->features & IPSET_TYPE_NAME) {
ret = -IPSET_ERR_LOOP;
goto finish;
}
if (tb[IPSET_ATTR_CADT_FLAGS]) {
u32 f = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
@@ -270,8 +271,8 @@ list_set_uadt(struct ip_set *set, struct nlattr *head, int len,
case IPSET_TEST:
for (i = 0; i < map->size && !ret; i++) {
elem = list_set_elem(map, i);
if (elem->id == IPSET_INVALID_ID
|| (before != 0 && i + 1 >= map->size))
if (elem->id == IPSET_INVALID_ID ||
(before != 0 && i + 1 >= map->size))
break;
else if (with_timeout && list_set_expired(map, i))
continue;
@@ -286,8 +287,8 @@ list_set_uadt(struct ip_set *set, struct nlattr *head, int len,
case IPSET_ADD:
for (i = 0; i < map->size && !ret; i++) {
elem = list_set_elem(map, i);
if (elem->id == id
&& !(with_timeout && list_set_expired(map, i)))
if (elem->id == id &&
!(with_timeout && list_set_expired(map, i)))
ret = -IPSET_ERR_EXIST;
}
if (ret == -IPSET_ERR_EXIST)
@@ -318,14 +319,14 @@ list_set_uadt(struct ip_set *set, struct nlattr *head, int len,
break;
} else if (with_timeout && list_set_expired(map, i))
continue;
else if (elem->id == id
&& (before == 0
|| (before > 0
&& next_id_eq(map, i, refid))))
else if (elem->id == id &&
(before == 0 ||
(before > 0 &&
next_id_eq(map, i, refid))))
ret = list_set_del(map, id, i);
else if (before < 0
&& elem->id == refid
&& next_id_eq(map, i, id))
else if (before < 0 &&
elem->id == refid &&
next_id_eq(map, i, id))
ret = list_set_del(map, id, i + 1);
}
break;
@@ -449,8 +450,8 @@ list_set_same_set(const struct ip_set *a, const struct ip_set *b)
const struct list_set *x = a->data;
const struct list_set *y = b->data;
return x->size == y->size
&& x->timeout == y->timeout;
return x->size == y->size &&
x->timeout == y->timeout;
}
static const struct ip_set_type_variant list_set = {
@@ -476,8 +477,8 @@ list_set_gc(unsigned long ul_set)
read_lock_bh(&set->lock);
for (i = map->size - 1; i >= 0; i--) {
e = (struct set_telem *) list_set_elem(map, i);
if (e->id != IPSET_INVALID_ID
&& list_set_expired(map, i))
if (e->id != IPSET_INVALID_ID &&
list_set_expired(map, i))
list_set_del(map, e->id, i);
}
read_unlock_bh(&set->lock);
@@ -486,7 +487,7 @@ list_set_gc(unsigned long ul_set)
add_timer(&map->gc);
}
static inline void
static void
list_set_gc_init(struct ip_set *set)
{
struct list_set *map = set->data;
@@ -506,7 +507,7 @@ list_set_create_policy[IPSET_ATTR_CREATE_MAX+1] = {
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
};
static inline bool
static bool
init_list_set(struct ip_set *set, u32 size, size_t dsize,
unsigned long timeout)
{
@@ -542,6 +543,10 @@ list_set_create(struct ip_set *set, struct nlattr *head, int len,
list_set_create_policy))
return -IPSET_ERR_PROTOCOL;
if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_SIZE) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_SIZE])
size = ip_set_get_h32(tb[IPSET_ATTR_SIZE]);
if (size < IP_SET_LIST_MIN_SIZE)

View File

@@ -1,7 +1,7 @@
#ifndef _IP_SET_TIMEOUT_H
#define _IP_SET_TIMEOUT_H
/* Copyright (C) 2003-2010 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
/* 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
@@ -43,17 +43,17 @@ ip_set_timeout_uget(struct nlattr *tb)
static inline bool
ip_set_timeout_test(unsigned long timeout)
{
return timeout != IPSET_ELEM_UNSET
&& (timeout == IPSET_ELEM_PERMANENT
|| time_after(timeout, jiffies));
return timeout != IPSET_ELEM_UNSET &&
(timeout == IPSET_ELEM_PERMANENT ||
time_after(timeout, jiffies));
}
static inline bool
ip_set_timeout_expired(unsigned long timeout)
{
return timeout != IPSET_ELEM_UNSET
&& timeout != IPSET_ELEM_PERMANENT
&& time_before(timeout, jiffies);
return timeout != IPSET_ELEM_UNSET &&
timeout != IPSET_ELEM_PERMANENT &&
time_before(timeout, jiffies);
}
static inline unsigned long
@@ -88,15 +88,15 @@ ip_set_timeout_get(unsigned long timeout)
static inline bool
ip_set_timeout_test(unsigned long timeout)
{
return timeout == IPSET_ELEM_PERMANENT
|| time_after(timeout, jiffies);
return timeout == IPSET_ELEM_PERMANENT ||
time_after(timeout, jiffies);
}
static inline bool
ip_set_timeout_expired(unsigned long timeout)
{
return timeout != IPSET_ELEM_PERMANENT
&& time_before(timeout, jiffies);
return timeout != IPSET_ELEM_PERMANENT &&
time_before(timeout, jiffies);
}
static inline unsigned long

View File

@@ -711,6 +711,14 @@ enum ipaddr_type {
IPADDR_RANGE,
};
static inline bool
cidr_hostaddr(const char *str, uint8_t family)
{
char *a = cidr_separator(str);
return family == AF_INET ? STREQ(a, "/32") : STREQ(a, "/128");
}
static int
parse_ip(struct ipset_session *session,
enum ipset_opt opt, const char *str, enum ipaddr_type addrtype)
@@ -725,7 +733,8 @@ parse_ip(struct ipset_session *session,
switch (addrtype) {
case IPADDR_PLAIN:
if (range_separator(str) || cidr_separator(str))
if (range_separator(str)
|| (cidr_separator(str) && !cidr_hostaddr(str, family)))
return syntax_err("plain IP address must be supplied: %s",
str);
break;
@@ -836,7 +845,7 @@ ipset_parse_net(struct ipset_session *session,
*/
int
ipset_parse_range(struct ipset_session *session,
enum ipset_opt opt, const char *str)
enum ipset_opt opt ASSERT_UNUSED, const char *str)
{
assert(session);
assert(opt == IPSET_OPT_IP || opt == IPSET_OPT_IP2);
@@ -1313,7 +1322,7 @@ ipset_parse_flag(struct ipset_session *session,
*/
int
ipset_parse_typename(struct ipset_session *session,
enum ipset_opt opt, const char *str)
enum ipset_opt opt ASSERT_UNUSED, const char *str)
{
const struct ipset_type *type;
const char *typename;

View File

@@ -89,7 +89,8 @@ ipset_print_ether(char *buf, unsigned int len,
*/
int
ipset_print_family(char *buf, unsigned int len,
const struct ipset_data *data, enum ipset_opt opt,
const struct ipset_data *data,
enum ipset_opt opt ASSERT_UNUSED,
uint8_t env UNUSED)
{
uint8_t family;
@@ -410,7 +411,8 @@ ipset_print_name(char *buf, unsigned int len,
*/
int
ipset_print_port(char *buf, unsigned int len,
const struct ipset_data *data, enum ipset_opt opt,
const struct ipset_data *data,
enum ipset_opt opt ASSERT_UNUSED,
uint8_t env UNUSED)
{
const uint16_t *port;
@@ -454,7 +456,8 @@ ipset_print_port(char *buf, unsigned int len,
*/
int
ipset_print_proto(char *buf, unsigned int len,
const struct ipset_data *data, enum ipset_opt opt,
const struct ipset_data *data,
enum ipset_opt opt ASSERT_UNUSED,
uint8_t env UNUSED)
{
const struct protoent *protoent;
@@ -490,7 +493,8 @@ ipset_print_proto(char *buf, unsigned int len,
*/
int
ipset_print_icmp(char *buf, unsigned int len,
const struct ipset_data *data, enum ipset_opt opt,
const struct ipset_data *data,
enum ipset_opt opt ASSERT_UNUSED,
uint8_t env UNUSED)
{
const char *name;
@@ -523,7 +527,8 @@ ipset_print_icmp(char *buf, unsigned int len,
*/
int
ipset_print_icmpv6(char *buf, unsigned int len,
const struct ipset_data *data, enum ipset_opt opt,
const struct ipset_data *data,
enum ipset_opt opt ASSERT_UNUSED,
uint8_t env UNUSED)
{
const char *name;
@@ -556,7 +561,8 @@ ipset_print_icmpv6(char *buf, unsigned int len,
*/
int
ipset_print_proto_port(char *buf, unsigned int len,
const struct ipset_data *data, enum ipset_opt opt,
const struct ipset_data *data,
enum ipset_opt opt ASSERT_UNUSED,
uint8_t env UNUSED)
{
int size, offset = 0;

View File

@@ -100,6 +100,19 @@ ipset_saved_type(const struct ipset_session *session)
return session->saved_type;
}
/**
* ipset_session_lineno - set session lineno
* @session: session structure
*
* Set session lineno to report parser errors correctly.
*/
void
ipset_session_lineno(struct ipset_session *session, uint32_t lineno)
{
assert(session);
session->lineno = lineno;
}
/*
* Environment options
*/

291
extensions/ipset-5/pfxlen.c Normal file
View File

@@ -0,0 +1,291 @@
#include "pfxlen.h"
/*
* Prefixlen maps for fast conversions, by Jan Engelhardt.
*/
#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 ip_set_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),
};
EXPORT_SYMBOL_GPL(ip_set_netmask_map);
#undef E
#define E(a, b, c, d) \
{.ip6 = { (__force __be32) a, (__force __be32) b, \
(__force __be32) c, (__force __be32) d, \
} }
/*
* This table works for both IPv4 and IPv6;
* just use prefixlen_hostmask_map[prefixlength].ip.
*/
const union nf_inet_addr ip_set_hostmask_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),
};
EXPORT_SYMBOL_GPL(ip_set_hostmask_map);

View File

@@ -0,0 +1,35 @@
#ifndef _PFXLEN_H
#define _PFXLEN_H
#include <asm/byteorder.h>
#include <linux/netfilter.h>
/* Prefixlen maps, by Jan Engelhardt */
extern const union nf_inet_addr ip_set_netmask_map[];
extern const union nf_inet_addr ip_set_hostmask_map[];
static inline __be32
ip_set_netmask(u8 pfxlen)
{
return ip_set_netmask_map[pfxlen].ip;
}
static inline const __be32 *
ip_set_netmask6(u8 pfxlen)
{
return &ip_set_netmask_map[pfxlen].ip6[0];
}
static inline u32
ip_set_hostmask(u8 pfxlen)
{
return (__force u32) ip_set_hostmask_map[pfxlen].ip;
}
static inline const __be32 *
ip_set_hostmask6(u8 pfxlen)
{
return &ip_set_hostmask_map[pfxlen].ip6[0];
}
#endif /*_PFXLEN_H */

View File

@@ -431,13 +431,8 @@ parse_commandline(int argc, char *argv[])
const struct ipset_commands *command;
const struct ipset_type *type;
/* Initialize session */
if (session == NULL) {
session = ipset_session_init(printf);
if (session == NULL)
return exit_error(OTHER_PROBLEM,
"Cannot initialize ipset session, aborting.");
}
/* Set session lineno to report parser errors correctly */
ipset_session_lineno(session, restore_line);
/* Commandline parsing, somewhat similar to that of 'ip' */
@@ -743,5 +738,11 @@ main(int argc, char *argv[])
ipset_type_add(&ipset_hash_ipportnet0);
ipset_type_add(&ipset_list_set0);
/* Initialize session */
session = ipset_session_init(printf);
if (session == NULL)
return exit_error(OTHER_PROBLEM,
"Cannot initialize ipset session, aborting.");
return parse_commandline(argc, argv);
}

View File

@@ -1,7 +1,7 @@
/* 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>
* 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
@@ -108,12 +108,12 @@ set_match_v0_checkentry(const struct xt_mtchk_param *par)
index = ip_set_nfnl_get_byindex(info->match_set.index);
if (index == IPSET_INVALID_ID) {
pr_warning("Cannot find set indentified by id %u to match",
pr_warning("Cannot find set indentified by id %u to match\n",
info->match_set.index);
return CHECK_FAIL; /* error */
}
if (info->match_set.u.flags[IPSET_DIM_MAX-1] != 0) {
pr_warning("That's nasty!");
pr_warning("That's nasty!\n");
return CHECK_FAIL; /* error */
}
@@ -167,7 +167,7 @@ set_target_v0_checkentry(const struct xt_tgchk_param *par)
if (info->add_set.index != IPSET_INVALID_ID) {
index = ip_set_nfnl_get_byindex(info->add_set.index);
if (index == IPSET_INVALID_ID) {
pr_warning("cannot find add_set index %u as target",
pr_warning("cannot find add_set index %u as target\n",
info->add_set.index);
return CHECK_FAIL; /* error */
}
@@ -176,14 +176,14 @@ set_target_v0_checkentry(const struct xt_tgchk_param *par)
if (info->del_set.index != IPSET_INVALID_ID) {
index = ip_set_nfnl_get_byindex(info->del_set.index);
if (index == IPSET_INVALID_ID) {
pr_warning("cannot find del_set index %u as target",
pr_warning("cannot find del_set index %u as target\n",
info->del_set.index);
return CHECK_FAIL; /* error */
}
}
if (info->add_set.u.flags[IPSET_DIM_MAX-1] != 0
|| info->del_set.u.flags[IPSET_DIM_MAX-1] != 0) {
pr_warning("That's nasty!");
if (info->add_set.u.flags[IPSET_DIM_MAX-1] != 0 ||
info->del_set.u.flags[IPSET_DIM_MAX-1] != 0) {
pr_warning("That's nasty!\n");
return CHECK_FAIL; /* error */
}
@@ -237,12 +237,12 @@ set_match_checkentry(const struct xt_mtchk_param *par)
index = ip_set_nfnl_get_byindex(info->match_set.index);
if (index == IPSET_INVALID_ID) {
pr_warning("Cannot find set indentified by id %u to match",
pr_warning("Cannot find set indentified by id %u to match\n",
info->match_set.index);
return CHECK_FAIL; /* error */
}
if (info->match_set.dim > IPSET_DIM_MAX) {
pr_warning("That's nasty!");
pr_warning("That's nasty!\n");
return CHECK_FAIL; /* error */
}
@@ -295,7 +295,7 @@ set_target_checkentry(const struct xt_tgchk_param *par)
if (info->add_set.index != IPSET_INVALID_ID) {
index = ip_set_nfnl_get_byindex(info->add_set.index);
if (index == IPSET_INVALID_ID) {
pr_warning("cannot find add_set index %u as target",
pr_warning("cannot find add_set index %u as target\n",
info->add_set.index);
return CHECK_FAIL; /* error */
}
@@ -304,14 +304,14 @@ set_target_checkentry(const struct xt_tgchk_param *par)
if (info->del_set.index != IPSET_INVALID_ID) {
index = ip_set_nfnl_get_byindex(info->del_set.index);
if (index == IPSET_INVALID_ID) {
pr_warning("cannot find del_set index %u as target",
pr_warning("cannot find del_set index %u as target\n",
info->del_set.index);
return CHECK_FAIL; /* error */
}
}
if (info->add_set.dim > IPSET_DIM_MAX
|| info->del_set.flags > IPSET_DIM_MAX) {
pr_warning("That's nasty!");
if (info->add_set.dim > IPSET_DIM_MAX ||
info->del_set.flags > IPSET_DIM_MAX) {
pr_warning("That's nasty!\n");
return CHECK_FAIL; /* error */
}

View File

@@ -71,10 +71,10 @@ static void chaos_tg_print(const void *ip,
switch (info->variant) {
case XTCHAOS_DELUDE:
printf("DELUDE ");
printf(" DELUDE ");
break;
case XTCHAOS_TARPIT:
printf("TARPIT ");
printf(" TARPIT ");
break;
}
}
@@ -85,10 +85,10 @@ static void chaos_tg_save(const void *ip, const struct xt_entry_target *target)
switch (info->variant) {
case XTCHAOS_DELUDE:
printf("--delude ");
printf(" --delude ");
break;
case XTCHAOS_TARPIT:
printf("--tarpit ");
printf(" --tarpit ");
break;
}
}

View File

@@ -62,7 +62,7 @@ static void CHECKSUM_print(const void *ip, const struct xt_entry_target *target,
printf("CHECKSUM ");
if (einfo->operation & XT_CHECKSUM_OP_FILL)
printf("fill ");
printf(" fill ");
}
static void CHECKSUM_save(const void *ip, const struct xt_entry_target *target)
@@ -71,7 +71,7 @@ static void CHECKSUM_save(const void *ip, const struct xt_entry_target *target)
(const struct xt_CHECKSUM_info *)target->data;
if (einfo->operation & XT_CHECKSUM_OP_FILL)
printf("--checksum-fill ");
printf(" --checksum-fill ");
}
static struct xtables_target checksum_tg_reg = {

View File

@@ -66,7 +66,7 @@ static void dhcpmac_tg_print(const void *ip,
{
const struct dhcpmac_info *info = (void *)target->data;
printf("DHCPMAC %s" DH_MAC_FMT "/%u ",
printf(" DHCPMAC %s" DH_MAC_FMT "/%u ",
info->invert ? "!" : "", DH_MAC_HEX(info->addr), info->mask);
}
@@ -76,8 +76,8 @@ static void dhcpmac_tg_save(const void *ip,
const struct dhcpmac_info *info = (const void *)target->data;
if (info->invert)
printf("! ");
printf("--set-mac " DH_MAC_FMT "/%u ",
printf(" !");
printf(" --set-mac " DH_MAC_FMT "/%u ",
DH_MAC_HEX(info->addr), info->mask);
}

241
extensions/libxt_DNETMAP.c Normal file
View File

@@ -0,0 +1,241 @@
/* Shared library add-on to iptables to add DNETMAP support.
* (C) 2010 Marek Kierdelewicz <marek@koba.pl>
*
* uses some code from libipt_NETMAP by:
* Svenning Soerensen <svenning@post5.tele.dk>
*/
#include <stdio.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
#include <xtables.h>
#include <net/netfilter/nf_nat.h>
#include "xt_DNETMAP.h"
#define MODULENAME "DNETMAP"
static const struct option DNETMAP_opts[] = {
{"prefix", 1, NULL, 'p'},
{"reuse", 0, NULL, 'r'},
{"ttl", 1, NULL, 't'},
{.name = NULL}
};
static void DNETMAP_help(void)
{
printf(MODULENAME " target options:\n"
" --%s address[/mask]\n"
" Network subnet to map to. If not specified, all existing prefixes are used.\n"
" --%s\n"
" Reuse entry for given prenat-ip from any prefix despite bindings ttl < 0.\n"
" --%s seconds\n"
" Regenerate bindings ttl value to seconds. If negative value is specified,\n"
" bindings ttl is kept unchanged. If not specified then default ttl value (600s)\n"
" is used.\n\n",
DNETMAP_opts[0].name, DNETMAP_opts[1].name,
DNETMAP_opts[2].name);
}
static u_int32_t bits2netmask(int bits)
{
u_int32_t netmask, bm;
if (bits >= 32 || bits < 0)
return ~0;
for (netmask = 0, bm = 0x80000000; bits; bits--, bm >>= 1)
netmask |= bm;
return htonl(netmask);
}
static int netmask2bits(u_int32_t netmask)
{
u_int32_t bm;
int bits;
netmask = ntohl(netmask);
for (bits = 0, bm = 0x80000000; netmask & bm; netmask <<= 1)
bits++;
if (netmask)
return -1; /* holes in netmask */
return bits;
}
static void DNETMAP_init(struct xt_entry_target *t)
{
struct xt_DNETMAP_tginfo *tginfo = (void *)&t->data;
struct nf_nat_multi_range *mr = &tginfo->prefix;
/* Actually, it's 0, but it's ignored at the moment. */
mr->rangesize = 1;
tginfo->ttl = 0;
tginfo->flags = 0;
}
/* Parses network address */
static void parse_prefix(char *arg, struct nf_nat_range *range)
{
char *slash;
const struct in_addr *ip;
u_int32_t netmask;
unsigned int bits;
range->flags |= IP_NAT_RANGE_MAP_IPS;
slash = strchr(arg, '/');
if (slash)
*slash = '\0';
ip = xtables_numeric_to_ipaddr(arg);
if (ip == NULL)
xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
arg);
range->min_ip = ip->s_addr;
if (slash) {
if (strchr(slash + 1, '.')) {
ip = xtables_numeric_to_ipmask(slash + 1);
if (ip == NULL)
xtables_error(PARAMETER_PROBLEM,
"Bad netmask \"%s\"\n",
slash + 1);
netmask = ip->s_addr;
} else {
if (!xtables_strtoui(slash + 1, NULL, &bits, 0, 32))
xtables_error(PARAMETER_PROBLEM,
"Bad netmask \"%s\"\n",
slash + 1);
netmask = bits2netmask(bits);
}
/* Don't allow /0 (/1 is probably insane, too) */
if (netmask == 0)
xtables_error(PARAMETER_PROBLEM, "Netmask needed\n");
/* Mask should be <= then /16 */
if (bits < 16)
xtables_error(PARAMETER_PROBLEM,
"Max netmask size is /16\n");
} else
netmask = ~0;
if (range->min_ip & ~netmask) {
if (slash)
*slash = '/';
xtables_error(PARAMETER_PROBLEM, "Bad network address \"%s\"\n",
arg);
}
range->max_ip = range->min_ip | ~netmask;
}
static int DNETMAP_parse(int c, char **argv, int invert, unsigned int *flags,
const void *entry, struct xt_entry_target **target)
{
struct xt_DNETMAP_tginfo *tginfo = (void *)(*target)->data;
struct nf_nat_multi_range *mr = &tginfo->prefix;
char *end;
switch (c) {
case 'p':
xtables_param_act(XTF_ONLY_ONCE, MODULENAME, "--prefix",
*flags & XT_DNETMAP_PREFIX);
xtables_param_act(XTF_NO_INVERT, MODULENAME, "--prefix",
invert);
/* TO-DO use xtables_ipparse_any instead? */
parse_prefix(optarg, &mr->range[0]);
*flags |= XT_DNETMAP_PREFIX;
tginfo->flags |= XT_DNETMAP_PREFIX;
return 1;
case 'r':
xtables_param_act(XTF_ONLY_ONCE, MODULENAME, "--reuse",
*flags & XT_DNETMAP_REUSE);
xtables_param_act(XTF_NO_INVERT, MODULENAME, "--reuse", invert);
*flags |= XT_DNETMAP_REUSE;
tginfo->flags |= XT_DNETMAP_REUSE;
return 1;
case 't':
xtables_param_act(XTF_ONLY_ONCE, MODULENAME, "--ttl",
*flags & XT_DNETMAP_TTL);
xtables_param_act(XTF_NO_INVERT, MODULENAME, "--ttl", invert);
*flags |= XT_DNETMAP_TTL;
tginfo->flags |= XT_DNETMAP_TTL;
tginfo->ttl = strtol(optarg, &end, 10);
if (*end != '\0')
return 0;
return 1;
default:
return 0;
}
}
static void DNETMAP_print_addr(const void *ip,
const struct xt_entry_target *target,
int numeric)
{
struct xt_DNETMAP_tginfo *tginfo = (void *)&target->data;
const struct nf_nat_multi_range *mr = &tginfo->prefix;
const struct nf_nat_range *r = &mr->range[0];
struct in_addr a;
int bits;
a.s_addr = r->min_ip;
printf("%s", xtables_ipaddr_to_numeric(&a));
a.s_addr = ~(r->min_ip ^ r->max_ip);
bits = netmask2bits(a.s_addr);
if (bits < 0)
printf("/%s", xtables_ipaddr_to_numeric(&a));
else
printf("/%d", bits);
}
static void DNETMAP_print(const void *ip, const struct xt_entry_target *target,
int numeric)
{
struct xt_DNETMAP_tginfo *tginfo = (void *)&target->data;
const __u8 *flags = &tginfo->flags;
printf(" prefix ");
if (*flags & XT_DNETMAP_PREFIX)
DNETMAP_print_addr(ip, target, numeric);
else
printf("any");
printf(" reuse %i", (*flags & XT_DNETMAP_REUSE) > 0);
if (*flags & XT_DNETMAP_TTL)
printf(" ttl %i", tginfo->ttl);
else
printf(" ttl default");
}
static void DNETMAP_save(const void *ip, const struct xt_entry_target *target)
{
struct xt_DNETMAP_tginfo *tginfo = (void *)&target->data;
const __u8 *flags = &tginfo->flags;
if (*flags & XT_DNETMAP_PREFIX) {
printf(" --%s ", DNETMAP_opts[0].name);
DNETMAP_print_addr(ip, target, 0);
}
printf(" --reuse %i ", *flags & XT_DNETMAP_REUSE);
/* ommited because default value can change as kernel mod param */
if (*flags & XT_DNETMAP_TTL)
printf(" --ttl %i ", tginfo->ttl);
}
static struct xtables_target dnetmap_tg_reg = {
.name = MODULENAME,
.version = XTABLES_VERSION,
.family = NFPROTO_IPV4,
.size = XT_ALIGN(sizeof(struct xt_DNETMAP_tginfo)),
.userspacesize = XT_ALIGN(sizeof(struct xt_DNETMAP_tginfo)),
.help = DNETMAP_help,
.init = DNETMAP_init,
.parse = DNETMAP_parse,
.print = DNETMAP_print,
.save = DNETMAP_save,
.extra_opts = DNETMAP_opts,
};
static void _init(void)
{
xtables_register_target(&dnetmap_tg_reg);
}

View File

@@ -0,0 +1,91 @@
The \fBDNETMAP\fR target allows dynamic two-way 1:1 mapping of IPv4 subnets.
Single rule can map private subnet to shorter public subnet creating and
maintaining unambigeous private-public ip bindings. Second rule can be used to
map new flows to private subnet according to maintained bindings. Target allows
efficient public IPv4 space usage and unambigeous NAT at the same time.
Target can be used only in \fBnat\fR table in \fBPOSTROUTING\fR or \fBOUTPUT\fR
chains for SNAT and in \fBPREROUTING\fR for DNAT. Only flows directed to bound
IPs will be DNATed. Packet continues chain traversal if there is no free
postnat-ip to be assigned to prenat-ip. Default binding \fBttl\fR is \fI10
minutes\fR and can be changed using \fBdefault_ttl\fR module option. Default ip
hash size is 256 and can be changed using \fBhash_size\fR module option.
.TP
\fB\-\-prefix\fR \fIaddr\fR\fB/\fR\fImask\fR
Network subnet to map to. If not specified, all existing prefixes are used.
.TP
\fB\-\-reuse\fR
Reuse entry for given prenat-ip from any prefix despite bindings ttl < 0.
.TP
\fB\-\-ttl\fR \fIseconds\fR
Regenerate bindings ttl value to \fIseconds\fR. If negative value is specified,
bindings ttl is kept unchanged. If not specified then default ttl value (600s)
is used.
.PP
\fB* /proc interface\fR
Module creates following entries for each new specified subnet:
.TP
\fB/proc/net/xt_DNETMAP/\fR\fIsubnet\fR\fB_\fR\fImask\fR
Contains binding table for subnet/mask. Each line contains \fBprenat-ip\fR,
\fBpostnat-ip\fR,\fBttl\fR (seconds till entry times out), \fBlasthit\fR (last
entry hit in seconds relative to system boot time).
.TP
\fB/proc/net/xt_DNETMAP/\fR\fIsubnet\fR\fB_\fR\fImask\fR\fB_stat\fR
Contains statistics for given subnet/mask. Line contains contains three
numerical values separated by spaces. First one is number of currently used
addresses (bindings with negative ttl excluded), second one is number of all
usable addresses in subnet and third one is mean \fBttl\fR value for all active
entries.
.PP
Entries are removed if the last iptables rule for a specific subnet is deleted.
\fB* Logging\fR
Module logs binding add/timeout events to klog. This behaviour can be disabled
using \fBdisable_log\fR module parameter.
\fB* Examples\fR
\fB1.\fR Map subnet 192.168.0.0/24 to subnets 20.0.0.0/26. SNAT only:
iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -j DNETMAP --prefix 20.0.0.0/26
Active hosts from 192.168.0.0/24 subnet are mapped to 20.0.0.0/26. If packet
from not yet bound prenat-ip hits the rule and there are no free or timed-out
(ttl<0) entries in prefix 20.0.0.0/28, then notice is logged to klog and chain
traversal continues. If packet from already bound prenat-ip hits the rule,
bindings ttl value is regenerated to default_ttl and SNAT is performed.
\fB2.\fR Use of \fB\-\-reuse\fR and \fB\-\-ttl\fR switches, multiple rule
interaction:
iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -j DNETMAP --prefix
20.0.0.0/26 --reuse --ttl 200
iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -j DNETMAP --prefix 30.0.0.0/26
Active hosts from 192.168.0.0/24 subnet are mapped to 20.0.0.0/26 with ttl =
200 seconds. If there are no free addresses in first prefix the next one
(30.0.0.0/26) is used with default ttl. It's important to note that the first
rule SNATs all flows whose source IP is already actively (ttl>0) bound to ANY
prefix. Parameter \fB\-\-reuse\fR makes this functionality work even for
inactive (ttl<0) entries.
If both subnets are exhaused, then chain traversal continues.
\fB3.\fR Map 192.168.0.0/24 to subnets 20.0.0.0/26 bidirectional way:
iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -j DNETMAP --prefix 20.0.0.0/26
iptables -t nat -A PREROUTING -j DNETMAP
If host 192.168.0.10 generates some traffic, it gets bound to first free IP in
subnet - 20.0.0.0. Now any traffic directed to 20.0.0.0 gets DNATed to
192.168.0.10 as long as there's an active (ttl>0) binding. There's no need to
specify \fB\-\-prefix\fR parameter in PREROUTING rule, because this way it DNATs
traffic to all active prefixes. You could specify prefix it you'd like to make
DNAT work for specific prefix only.
.

View File

@@ -119,16 +119,16 @@ ipmark_tg_print(const void *entry, const struct xt_entry_target *target,
const struct xt_ipmark_tginfo *info = (const void *)target->data;
if (info->selector == XT_IPMARK_SRC)
printf("IPMARK src ip ");
printf(" IPMARK src ip ");
else
printf("IPMARK dst ip ");
printf(" IPMARK dst ip ");
if (info->shift != 0)
printf("shift %u ", (unsigned int)info->shift);
printf(" shift %u ", (unsigned int)info->shift);
if (info->andmask != ~0U)
printf("and 0x%x ", (unsigned int)info->andmask);
printf(" and 0x%x ", (unsigned int)info->andmask);
if (info->ormask != 0)
printf("or 0x%x ", (unsigned int)info->ormask);
printf(" or 0x%x ", (unsigned int)info->ormask);
}
static void
@@ -137,16 +137,16 @@ ipmark_tg_save(const void *entry, const struct xt_entry_target *target)
const struct xt_ipmark_tginfo *info = (const void *)target->data;
if (info->selector == XT_IPMARK_SRC)
printf("--addr src ");
printf(" --addr src ");
else
printf("--addr dst ");
printf(" --addr dst ");
if (info->shift != 0)
printf("--shift %u ", (unsigned int)info->shift);
printf(" --shift %u ", (unsigned int)info->shift);
if (info->andmask != ~0U)
printf("--and-mask 0x%x ", (unsigned int)info->andmask);
printf(" --and-mask 0x%x ", (unsigned int)info->andmask);
if (info->ormask != 0)
printf("--or-mask 0x%x ", (unsigned int)info->ormask);
printf(" --or-mask 0x%x ", (unsigned int)info->ormask);
}
static struct xtables_target ipmark_tg_reg = {

View File

@@ -83,7 +83,7 @@ logmark_tg_print(const void *ip, const struct xt_entry_target *target,
{
const struct xt_logmark_tginfo *info = (void *)target->data;
printf("LOGMARK level %u prefix \"%s\" ", info->level, info->prefix);
printf(" LOGMARK level %u prefix \"%s\" ", info->level, info->prefix);
}
static void
@@ -92,9 +92,9 @@ logmark_tg_save(const void *ip, const struct xt_entry_target *target)
const struct xt_logmark_tginfo *info = (void *)target->data;
if (info->level != 4)
printf("--log-level %u ", info->level);
printf(" --log-level %u ", info->level);
if (*info->prefix != '\0')
printf("--log-prefix \"%s\" ", info->prefix);
printf(" --log-prefix \"%s\" ", info->prefix);
}
static struct xtables_target logmark_tg_reg = {

View File

@@ -110,10 +110,10 @@ rawdnat_tg4_print(const void *entry, const struct xt_entry_target *target,
const struct xt_rawnat_tginfo *info = (const void *)target->data;
if (!numeric && info->mask == 32)
printf("to-destination %s ",
printf(" to-destination %s ",
xtables_ipaddr_to_anyname(&info->addr.in));
else
printf("to-destination %s/%u ",
printf(" to-destination %s/%u ",
xtables_ipaddr_to_numeric(&info->addr.in), info->mask);
}
@@ -124,10 +124,10 @@ rawdnat_tg6_print(const void *entry, const struct xt_entry_target *target,
const struct xt_rawnat_tginfo *info = (const void *)target->data;
if (!numeric && info->mask == 128)
printf("to-destination %s ",
printf(" to-destination %s ",
xtables_ip6addr_to_anyname(&info->addr.in6));
else
printf("to-destination %s/%u ",
printf(" to-destination %s/%u ",
xtables_ip6addr_to_numeric(&info->addr.in6), info->mask);
}
@@ -136,7 +136,7 @@ rawdnat_tg4_save(const void *entry, const struct xt_entry_target *target)
{
const struct xt_rawnat_tginfo *info = (const void *)target->data;
printf("--to-destination %s/%u ",
printf(" --to-destination %s/%u ",
xtables_ipaddr_to_numeric(&info->addr.in),
info->mask);
}
@@ -146,7 +146,7 @@ rawdnat_tg6_save(const void *entry, const struct xt_entry_target *target)
{
const struct xt_rawnat_tginfo *info = (const void *)target->data;
printf("--to-destination %s/%u ",
printf(" --to-destination %s/%u ",
xtables_ip6addr_to_numeric(&info->addr.in6),
info->mask);
}

View File

@@ -110,10 +110,10 @@ rawsnat_tg4_print(const void *entry, const struct xt_entry_target *target,
const struct xt_rawnat_tginfo *info = (const void *)target->data;
if (!numeric && info->mask == 32)
printf("to-source %s ",
printf(" to-source %s ",
xtables_ipaddr_to_anyname(&info->addr.in));
else
printf("to-source %s/%u ",
printf(" to-source %s/%u ",
xtables_ipaddr_to_numeric(&info->addr.in), info->mask);
}
@@ -124,10 +124,10 @@ rawsnat_tg6_print(const void *entry, const struct xt_entry_target *target,
const struct xt_rawnat_tginfo *info = (const void *)target->data;
if (!numeric && info->mask == 128)
printf("to-source %s ",
printf(" to-source %s ",
xtables_ip6addr_to_anyname(&info->addr.in6));
else
printf("to-source %s/%u ",
printf(" to-source %s/%u ",
xtables_ip6addr_to_numeric(&info->addr.in6), info->mask);
}
@@ -136,7 +136,7 @@ rawsnat_tg4_save(const void *entry, const struct xt_entry_target *target)
{
const struct xt_rawnat_tginfo *info = (const void *)target->data;
printf("--to-source %s/%u ",
printf(" --to-source %s/%u ",
xtables_ipaddr_to_numeric(&info->addr.in),
info->mask);
}
@@ -146,7 +146,7 @@ rawsnat_tg6_save(const void *entry, const struct xt_entry_target *target)
{
const struct xt_rawnat_tginfo *info = (const void *)target->data;
printf("--to-source %s/%u ",
printf(" --to-source %s/%u ",
xtables_ip6addr_to_numeric(&info->addr.in6),
info->mask);
}

View File

@@ -105,9 +105,9 @@ static void tee_tg_print(const void *ip, const struct xt_entry_target *target,
const struct xt_tee_tginfo *info = (const void *)target->data;
if (numeric)
printf("TEE gw:%s ", xtables_ipaddr_to_numeric(&info->gw.in));
printf(" TEE gw:%s ", xtables_ipaddr_to_numeric(&info->gw.in));
else
printf("TEE gw:%s ", xtables_ipaddr_to_anyname(&info->gw.in));
printf(" TEE gw:%s ", xtables_ipaddr_to_anyname(&info->gw.in));
}
static void tee_tg6_print(const void *ip, const struct xt_entry_target *target,
@@ -116,23 +116,23 @@ static void tee_tg6_print(const void *ip, const struct xt_entry_target *target,
const struct xt_tee_tginfo *info = (const void *)target->data;
if (numeric)
printf("TEE gw:%s ", xtables_ip6addr_to_numeric(&info->gw.in6));
printf(" TEE gw:%s ", xtables_ip6addr_to_numeric(&info->gw.in6));
else
printf("TEE gw:%s ", xtables_ip6addr_to_anyname(&info->gw.in6));
printf(" TEE gw:%s ", xtables_ip6addr_to_anyname(&info->gw.in6));
}
static void tee_tg_save(const void *ip, const struct xt_entry_target *target)
{
const struct xt_tee_tginfo *info = (const void *)target->data;
printf("--gateway %s ", xtables_ipaddr_to_numeric(&info->gw.in));
printf(" --gateway %s ", xtables_ipaddr_to_numeric(&info->gw.in));
}
static void tee_tg6_save(const void *ip, const struct xt_entry_target *target)
{
const struct xt_tee_tginfo *info = (const void *)target->data;
printf("--gateway %s ", xtables_ip6addr_to_numeric(&info->gw.in6));
printf(" --gateway %s ", xtables_ip6addr_to_numeric(&info->gw.in6));
}
static struct xtables_target tee_tg_reg = {

View File

@@ -67,7 +67,7 @@ static void condition_print(const void *ip, const struct xt_entry_match *match,
{
const struct xt_condition_mtinfo *info = (const void *)match->data;
printf("condition %s%s ", (info->invert) ? "!" : "", info->name);
printf(" condition %s%s ", (info->invert) ? "!" : "", info->name);
}
@@ -75,7 +75,7 @@ static void condition_save(const void *ip, const struct xt_entry_match *match)
{
const struct xt_condition_mtinfo *info = (const void *)match->data;
printf("%s--condition \"%s\" ", info->invert ? "! " : "", info->name);
printf("%s --condition \"%s\" ", info->invert ? " !" : "", info->name);
}
static struct xtables_match condition_mt_reg = {

View File

@@ -67,7 +67,7 @@ static void dhcpmac_mt_print(const void *ip,
{
const struct dhcpmac_info *info = (void *)match->data;
printf("dhcpmac %s" DH_MAC_FMT "/%u ",
printf(" dhcpmac %s" DH_MAC_FMT "/%u ",
info->invert ? "!" : "", DH_MAC_HEX(info->addr), info->mask);
}
@@ -77,8 +77,8 @@ static void dhcpmac_mt_save(const void *ip,
const struct dhcpmac_info *info = (void *)match->data;
if (info->invert)
printf("! ");
printf("--mac " DH_MAC_FMT "/%u ",
printf(" !");
printf(" --mac " DH_MAC_FMT "/%u ",
DH_MAC_HEX(info->addr), info->mask);
}

View File

@@ -88,7 +88,7 @@ static void fuzzy_mt_print(const void *ip, const struct xt_entry_match *match,
{
const struct xt_fuzzy_mtinfo *info = (const void *)match->data;
printf("fuzzy: lower limit = %u pps - upper limit = %u pps ",
printf(" fuzzy: lower limit = %u pps - upper limit = %u pps ",
info->minimum_rate, info->maximum_rate);
}
@@ -96,8 +96,8 @@ static void fuzzy_mt_save(const void *ip, const struct xt_entry_match *match)
{
const struct xt_fuzzy_mtinfo *info = (const void *)match->data;
printf("--lower-limit %u ", info->minimum_rate);
printf("--upper-limit %u ", info->maximum_rate);
printf(" --lower-limit %u ", info->minimum_rate);
printf(" --upper-limit %u ", info->maximum_rate);
}
static struct xtables_match fuzzy_mt_reg = {

View File

@@ -2,7 +2,7 @@
* "geoip" match extension for iptables
* Copyright © Samuel Jean <peejix [at] people netfilter org>, 2004 - 2008
* Copyright © Nicolas Bouliane <acidfu [at] people netfilter org>, 2004 - 2008
* Jan Engelhardt <jengelh [at] medozas de>, 2008
* Jan Engelhardt <jengelh [at] medozas de>, 2008-2011
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License; either
@@ -49,19 +49,28 @@ static struct option geoip_opts[] = {
{NULL},
};
static struct geoip_subnet *geoip_get_subnets(const char *code, uint32_t *count)
static void *
geoip_get_subnets(const char *code, uint32_t *count, uint8_t nfproto)
{
struct geoip_subnet *subnets;
void *subnets;
struct stat sb;
char buf[256];
int fd;
/* Use simple integer vector files */
if (nfproto == NFPROTO_IPV6) {
#if __BYTE_ORDER == _BIG_ENDIAN
snprintf(buf, sizeof(buf), GEOIP_DB_DIR "/BE/%s.iv0", code);
snprintf(buf, sizeof(buf), GEOIP_DB_DIR "/BE/%s.iv6", code);
#else
snprintf(buf, sizeof(buf), GEOIP_DB_DIR "/LE/%s.iv0", code);
snprintf(buf, sizeof(buf), GEOIP_DB_DIR "/LE/%s.iv6", code);
#endif
} else {
#if __BYTE_ORDER == _BIG_ENDIAN
snprintf(buf, sizeof(buf), GEOIP_DB_DIR "/BE/%s.iv4", code);
#else
snprintf(buf, sizeof(buf), GEOIP_DB_DIR "/LE/%s.iv4", code);
#endif
}
if ((fd = open(buf, O_RDONLY)) < 0) {
fprintf(stderr, "Could not open %s: %s\n", buf, strerror(errno));
@@ -69,20 +78,31 @@ static struct geoip_subnet *geoip_get_subnets(const char *code, uint32_t *count)
}
fstat(fd, &sb);
if (sb.st_size % sizeof(struct geoip_subnet) != 0)
xtables_error(OTHER_PROBLEM, "Database file %s seems to be "
"corrupted", buf);
*count = sb.st_size;
switch (nfproto) {
case NFPROTO_IPV6:
if (sb.st_size % sizeof(struct geoip_subnet6) != 0)
xtables_error(OTHER_PROBLEM,
"Database file %s seems to be corrupted", buf);
*count /= sizeof(struct geoip_subnet6);
break;
case NFPROTO_IPV4:
if (sb.st_size % sizeof(struct geoip_subnet4) != 0)
xtables_error(OTHER_PROBLEM,
"Database file %s seems to be corrupted", buf);
*count /= sizeof(struct geoip_subnet4);
break;
}
subnets = malloc(sb.st_size);
if (subnets == NULL)
xtables_error(OTHER_PROBLEM, "geoip: insufficient memory");
read(fd, subnets, sb.st_size);
close(fd);
*count = sb.st_size / sizeof(struct geoip_subnet);
return subnets;
}
static struct geoip_country_user *geoip_load_cc(const char *code,
unsigned short cc)
unsigned short cc, uint8_t nfproto)
{
struct geoip_country_user *ginfo;
ginfo = malloc(sizeof(struct geoip_country_user));
@@ -90,7 +110,8 @@ static struct geoip_country_user *geoip_load_cc(const char *code,
if (!ginfo)
return NULL;
ginfo->subnets = (unsigned long)geoip_get_subnets(code, &ginfo->count);
ginfo->subnets = (unsigned long)geoip_get_subnets(code,
&ginfo->count, nfproto);
ginfo->cc = cc;
return ginfo;
@@ -133,7 +154,7 @@ check_geoip_cc(char *cc, u_int16_t cc_used[], u_int8_t count)
}
static unsigned int parse_geoip_cc(const char *ccstr, uint16_t *cc,
union geoip_country_group *mem)
union geoip_country_group *mem, uint8_t nfproto)
{
char *buffer, *cp, *next;
u_int8_t i, count = 0;
@@ -150,7 +171,8 @@ static unsigned int parse_geoip_cc(const char *ccstr, uint16_t *cc,
if (next) *next++ = '\0';
if ((cctmp = check_geoip_cc(cp, cc, count)) != 0) {
if ((mem[count++].user = (unsigned long)geoip_load_cc(cp, cctmp)) == 0)
if ((mem[count++].user =
(unsigned long)geoip_load_cc(cp, cctmp, nfproto)) == 0)
xtables_error(OTHER_PROBLEM,
"geoip: insufficient memory available");
cc[count-1] = cctmp;
@@ -169,11 +191,9 @@ static unsigned int parse_geoip_cc(const char *ccstr, uint16_t *cc,
return count;
}
static int geoip_parse(int c, char **argv, int invert, unsigned int *flags,
const void *entry, struct xt_entry_match **match)
static int geoip_parse(int c, bool invert, unsigned int *flags,
const char *arg, struct xt_geoip_match_info *info, uint8_t nfproto)
{
struct xt_geoip_match_info *info = (void *)(*match)->data;
switch (c) {
case '1':
if (*flags & (XT_GEOIP_SRC | XT_GEOIP_DST))
@@ -185,7 +205,8 @@ static int geoip_parse(int c, char **argv, int invert, unsigned int *flags,
if (invert)
*flags |= XT_GEOIP_INV;
info->count = parse_geoip_cc(argv[optind-1], info->cc, info->mem);
info->count = parse_geoip_cc(arg, info->cc, info->mem,
nfproto);
info->flags = *flags;
return true;
@@ -199,7 +220,8 @@ static int geoip_parse(int c, char **argv, int invert, unsigned int *flags,
if (invert)
*flags |= XT_GEOIP_INV;
info->count = parse_geoip_cc(argv[optind-1], info->cc, info->mem);
info->count = parse_geoip_cc(arg, info->cc, info->mem,
nfproto);
info->flags = *flags;
return true;
}
@@ -207,6 +229,20 @@ static int geoip_parse(int c, char **argv, int invert, unsigned int *flags,
return false;
}
static int geoip_parse6(int c, char **argv, int invert, unsigned int *flags,
const void *entry, struct xt_entry_match **match)
{
return geoip_parse(c, invert, flags, optarg,
(void *)(*match)->data, NFPROTO_IPV6);
}
static int geoip_parse4(int c, char **argv, int invert, unsigned int *flags,
const void *entry, struct xt_entry_match **match)
{
return geoip_parse(c, invert, flags, optarg,
(void *)(*match)->data, NFPROTO_IPV4);
}
static void
geoip_final_check(unsigned int flags)
{
@@ -223,9 +259,9 @@ geoip_print(const void *ip, const struct xt_entry_match *match, int numeric)
u_int8_t i;
if (info->flags & XT_GEOIP_SRC)
printf("Source ");
printf(" Source ");
else
printf("Destination ");
printf(" Destination ");
if (info->count > 1)
printf("countries: ");
@@ -247,34 +283,51 @@ geoip_save(const void *ip, const struct xt_entry_match *match)
u_int8_t i;
if (info->flags & XT_GEOIP_INV)
printf("! ");
printf(" !");
if (info->flags & XT_GEOIP_SRC)
printf("--source-country ");
printf(" --source-country ");
else
printf("--destination-country ");
printf(" --destination-country ");
for (i = 0; i < info->count; i++)
printf("%s%c%c", i ? "," : "", COUNTRY(info->cc[i]));
printf(" ");
}
static struct xtables_match geoip_match = {
.family = NFPROTO_IPV4,
.name = "geoip",
.revision = 1,
.version = XTABLES_VERSION,
.size = XT_ALIGN(sizeof(struct xt_geoip_match_info)),
.userspacesize = offsetof(struct xt_geoip_match_info, mem),
.help = geoip_help,
.parse = geoip_parse,
.final_check = geoip_final_check,
.print = geoip_print,
.save = geoip_save,
.extra_opts = geoip_opts,
static struct xtables_match geoip_match[] = {
{
.family = NFPROTO_IPV6,
.name = "geoip",
.revision = 1,
.version = XTABLES_VERSION,
.size = XT_ALIGN(sizeof(struct xt_geoip_match_info)),
.userspacesize = offsetof(struct xt_geoip_match_info, mem),
.help = geoip_help,
.parse = geoip_parse6,
.final_check = geoip_final_check,
.print = geoip_print,
.save = geoip_save,
.extra_opts = geoip_opts,
},
{
.family = NFPROTO_IPV4,
.name = "geoip",
.revision = 1,
.version = XTABLES_VERSION,
.size = XT_ALIGN(sizeof(struct xt_geoip_match_info)),
.userspacesize = offsetof(struct xt_geoip_match_info, mem),
.help = geoip_help,
.parse = geoip_parse4,
.final_check = geoip_final_check,
.print = geoip_print,
.save = geoip_save,
.extra_opts = geoip_opts,
},
};
static __attribute__((constructor)) void geoip_mt_ldr(void)
{
xtables_register_match(&geoip_match);
xtables_register_matches(geoip_match,
sizeof(geoip_match) / sizeof(*geoip_match));
}

View File

@@ -15,9 +15,8 @@ with the source package, and which should be available in compiled packages in
/usr/lib(exec)/xtables-addons/. The first command retrieves CSV files from
MaxMind, while the other two build packed bisectable range files:
.PP
cd /tmp; $path/to/geoip_download.sh;
mkdir -p /usr/share/xt_geoip; cd /tmp; $path/to/xt_geoip_dl;
.PP
$path/to/geoip_build_db.pl -D /usr/share/xt_geoip/LE
$path/to/geoip_build_db.pl -D /usr/share/xt_geoip/BE -b
$path/to/xt_geoip_build -D /usr/share/xt_geoip GeoIP*.csv;
.PP
The shared library is hardcoded to look in these paths, so use them.

View File

@@ -73,9 +73,9 @@ static void gradm_mt_save(const void *ip, const struct xt_entry_match *match)
const struct xt_gradm_mtinfo *info = (const void *)match->data;
if (info->invflags)
printf("--disabled ");
printf(" --disabled ");
else
printf("--enabled ");
printf(" --enabled ");
}
static struct xtables_match gradm_mt_reg = {

View File

@@ -180,7 +180,7 @@ static void iface_mt_print(const void *ip, const struct xt_entry_match *match,
{
const struct xt_iface_mtinfo *info = (const void *)match->data;
printf("iface: ");
printf(" iface: ");
if (info->flags & XT_IFACE_DEV_IN)
printf("(in)");
else if (info->flags & XT_IFACE_DEV_OUT)
@@ -207,11 +207,11 @@ static void iface_mt_save(const void *ip, const struct xt_entry_match *match)
const struct xt_iface_mtinfo *info = (const void *)match->data;
if (info->flags & XT_IFACE_DEV_IN)
printf("--dev-in");
printf(" --dev-in");
else if (info->flags & XT_IFACE_DEV_OUT)
printf("--dev-out");
printf(" --dev-out");
else
printf("--iface %s", info->ifname);
printf(" --iface %s", info->ifname);
iface_print_opt(info, XT_IFACE_UP, "--up");
iface_print_opt(info, XT_IFACE_BROADCAST, "--broadcast");
iface_print_opt(info, XT_IFACE_LOOPBACK, "--loopback");

View File

@@ -208,16 +208,16 @@ ipp2p_mt_print1(const void *entry, const struct xt_entry_match *match,
for (i = IPP2N_EDK; i <= IPP2N_XDCC; ++i)
if (info->cmd & (1 << i))
printf("%s ", ipp2p_cmds[i]);
printf(" %s ", ipp2p_cmds[i]);
if (info->debug != 0)
printf("--debug ");
printf(" --debug ");
}
static void ipp2p_mt_print(const void *entry,
const struct xt_entry_match *match, int numeric)
{
printf("ipp2p ");
printf(" ipp2p ");
ipp2p_mt_print1(entry, match, true);
}

View File

@@ -1,6 +1,6 @@
/*
* "ipv4options" match extension for iptables
* Coprygith © Jan Engelhardt, 2009
* Copyright © Jan Engelhardt, 2009
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License; either
@@ -138,7 +138,7 @@ static void ipv4options_mt_print(const void *ip,
{
const struct xt_ipv4options_mtinfo1 *info = (void *)match->data;
printf("ipv4options %s ",
printf(" ipv4options %s ",
(info->flags & XT_V4OPTS_ANY) ? "any-of" : "all-of");
ipv4options_print_flags(info, numeric);
printf(" ");
@@ -150,7 +150,7 @@ static void ipv4options_mt_save(const void *ip,
const struct xt_ipv4options_mtinfo1 *info = (void *)match->data;
if (info->map != 0) {
printf("--flags ");
printf(" --flags ");
ipv4options_print_flags(info, true);
}
if (info->flags & XT_V4OPTS_ANY)

View File

@@ -113,14 +113,14 @@ static void length_mt_print(const void *ip, const struct xt_entry_match *match,
const struct xt_length_mtinfo2 *info = (const void *)match->data;
if (info->flags & XT_LENGTH_LAYER3)
printf("layer3 ");
printf(" layer3 ");
else if (info->flags & XT_LENGTH_LAYER4)
printf("layer4 ");
printf(" layer4 ");
else if (info->flags & XT_LENGTH_LAYER5)
printf("layer5 ");
printf(" layer5 ");
else if (info->flags & XT_LENGTH_LAYER7)
printf("layer7 ");
printf("length ");
printf(" layer7 ");
printf(" length ");
if (info->flags & XT_LENGTH_INVERT)
printf("! ");
if (info->min == info->max)
@@ -135,16 +135,16 @@ static void length_mt_save(const void *ip, const struct xt_entry_match *match)
const struct xt_length_mtinfo2 *info = (const void *)match->data;
if (info->flags & XT_LENGTH_LAYER3)
printf("--layer3 ");
printf(" --layer3 ");
else if (info->flags & XT_LENGTH_LAYER4)
printf("--layer4 ");
printf(" --layer4 ");
else if (info->flags & XT_LENGTH_LAYER5)
printf("--layer5 ");
printf(" --layer5 ");
else if (info->flags & XT_LENGTH_LAYER7)
printf("--layer7 ");
printf(" --layer7 ");
if (info->flags & XT_LENGTH_INVERT)
printf("! ");
printf("--length ");
printf(" !");
printf(" --length ");
if (info->min == info->max)
printf("%u ", (unsigned int)info->min);
else

View File

@@ -70,7 +70,7 @@ static void lscan_mt_print(const void *ip,
const struct xt_lscan_mtinfo *info = (const void *)(match->data);
const char *s = "";
printf("lscan ");
printf(" lscan ");
if (info->match_stealth) {
printf("STEALTH");
s = ",";
@@ -93,13 +93,13 @@ static void lscan_mt_save(const void *ip, const struct xt_entry_match *match)
const struct xt_lscan_mtinfo *info = (const void *)(match->data);
if (info->match_stealth)
printf("--stealth ");
printf(" --stealth ");
if (info->match_syn)
printf("--synscan ");
printf(" --synscan ");
if (info->match_cn)
printf("--cnscan ");
printf(" --cnscan ");
if (info->match_gr)
printf("--grscan ");
printf(" --grscan ");
}
static struct xtables_match lscan_mt_reg = {

View File

@@ -119,7 +119,7 @@ static void psd_mt_final_check(unsigned int flags) {}
static void psd_mt_print(const void *ip, const struct xt_entry_match *match, int numeric)
{
const struct xt_psd_info *psdinfo = (const struct xt_psd_info *)match->data;
printf("psd ");
printf(" psd ");
printf("weight-threshold: %u ", psdinfo->weight_threshold);
printf("delay-threshold: %u ", psdinfo->delay_threshold);
printf("lo-ports-weight: %u ", psdinfo->lo_ports_weight);
@@ -130,7 +130,7 @@ static void psd_mt_print(const void *ip, const struct xt_entry_match *match, int
static void psd_mt_save(const void *ip, const struct xt_entry_match *match)
{
const struct xt_psd_info *psdinfo = (const struct xt_psd_info *)match->data;
printf("--psd-weight-threshold %u ", psdinfo->weight_threshold);
printf(" --psd-weight-threshold %u ", psdinfo->weight_threshold);
printf("--psd-delay-threshold %u ", psdinfo->delay_threshold);
printf("--psd-lo-ports-weight %u ", psdinfo->lo_ports_weight);
printf("--psd-hi-ports-weight %u ", psdinfo->hi_ports_weight);

View File

@@ -99,16 +99,16 @@ quota_mt2_save(const void *ip, const struct xt_entry_match *match)
const struct xt_quota_mtinfo2 *q = (void *)match->data;
if (q->flags & XT_QUOTA_INVERT)
printf("! ");
printf(" !");
if (q->flags & XT_QUOTA_GROW)
printf("--grow ");
printf(" --grow ");
if (q->flags & XT_QUOTA_NO_CHANGE)
printf("--no-change ");
printf(" --no-change ");
if (q->flags & XT_QUOTA_PACKET)
printf("--packets ");
printf(" --packets ");
if (*q->name != '\0')
printf("--name %s ", q->name);
printf("--quota %llu ", (unsigned long long)q->quota);
printf(" --name %s ", q->name);
printf(" --quota %llu ", (unsigned long long)q->quota);
}
static void quota_mt2_print(const void *ip, const struct xt_entry_match *match,
@@ -117,11 +117,11 @@ static void quota_mt2_print(const void *ip, const struct xt_entry_match *match,
const struct xt_quota_mtinfo2 *q = (const void *)match->data;
if (q->flags & XT_QUOTA_INVERT)
printf("! ");
printf(" !");
if (q->flags & XT_QUOTA_GROW)
printf("counter");
printf(" counter");
else
printf("quota");
printf(" quota");
if (*q->name != '\0')
printf(" %s:", q->name);
printf(" %llu ", (unsigned long long)q->quota);

View File

@@ -1,5 +1,8 @@
# -*- Makefile -*-
AM_CPPFLAGS = ${regular_CPPFLAGS} -I${abs_top_srcdir}/extensions
AM_CFLAGS = ${regular_CFLAGS}
include ../../Makefile.extra
noinst_PROGRAMS = pknlusr

View File

@@ -272,7 +272,7 @@ static void pknock_mt_print(const void *ip,
const struct xt_pknock_mtinfo *info = (void *)match->data;
int i;
printf("pknock ");
printf(" pknock ");
if (info->option & XT_PKNOCK_KNOCKPORT) {
printf("knockports ");
for (i = 0; i < info->ports_count; ++i)
@@ -301,26 +301,26 @@ static void pknock_mt_save(const void *ip, const struct xt_entry_match *match)
const struct xt_pknock_mtinfo *info = (void *)match->data;
if (info->option & XT_PKNOCK_KNOCKPORT) {
printf("--knockports ");
printf(" --knockports ");
for (i = 0; i < info->ports_count; ++i)
printf("%s%d", i ? "," : "", info->port[i]);
printf(" ");
}
if (info->option & XT_PKNOCK_TIME)
printf("--time %ld ", (long)info->max_time);
printf(" --time %ld ", (long)info->max_time);
if (info->option & XT_PKNOCK_AUTOCLOSE)
printf("--autoclose %lu ",
printf(" --autoclose %lu ",
(unsigned long)info->autoclose_time);
if (info->option & XT_PKNOCK_NAME)
printf("--name %s ", info->rule_name);
printf(" --name %s ", info->rule_name);
if (info->option & XT_PKNOCK_OPENSECRET)
printf("--opensecret ");
printf(" --opensecret ");
if (info->option & XT_PKNOCK_CLOSESECRET)
printf("--closesecret ");
printf(" --closesecret ");
if (info->option & XT_PKNOCK_STRICT)
printf("--strict ");
printf(" --strict ");
if (info->option & XT_PKNOCK_CHECKIP)
printf("--checkip ");
printf(" --checkip ");
}
static struct xtables_match pknock_mt_reg = {

View File

@@ -13,7 +13,6 @@
#define GROUP 1
static struct sockaddr_nl src_addr, dest_addr;
static struct msghdr msg;
static int sock_fd;
static unsigned char *buf;
@@ -25,9 +24,8 @@ int main(void)
socklen_t addrlen;
int status;
int group = GROUP;
struct cn_msg *cnmsg;
int i, buf_size;
int buf_size;
const char *ip;
char ipbuf[48];

View File

@@ -398,19 +398,15 @@ peer_gc(unsigned long r)
/**
* Compares length and name equality for the rules.
*
* @info
* @rule
* @return: 0 equals, 1 otherwise
*/
static inline bool
rulecmp(const struct xt_pknock_mtinfo *info, const struct xt_pknock_rule *rule)
{
if (info->rule_name_len != rule->rule_name_len)
return true;
return false;
if (strncmp(info->rule_name, rule->rule_name, info->rule_name_len) != 0)
return true;
return false;
return false;
return true;
}
/**
@@ -427,9 +423,9 @@ static struct xt_pknock_rule *search_rule(const struct xt_pknock_mtinfo *info)
ipt_pknock_hash_rnd, rule_hashsize);
list_for_each_safe(pos, n, &rule_hashtable[hash]) {
rule = list_entry(pos, struct xt_pknock_rule, head);
if (rulecmp(info, rule))
return rule;
rule = list_entry(pos, struct xt_pknock_rule, head);
if (rulecmp(info, rule))
return rule;
}
return NULL;
}
@@ -451,23 +447,20 @@ add_rule(struct xt_pknock_mtinfo *info)
list_for_each_safe(pos, n, &rule_hashtable[hash]) {
rule = list_entry(pos, struct xt_pknock_rule, head);
if (rulecmp(info, rule)) {
++rule->ref_count;
if (!rulecmp(info, rule))
continue;
++rule->ref_count;
if (info->option & XT_PKNOCK_OPENSECRET) {
rule->max_time = info->max_time;
rule->autoclose_time = info->autoclose_time;
}
if (info->option & XT_PKNOCK_CHECKIP) {
pr_debug("add_rule() (AC)"
" rule found: %s - "
"ref_count: %d\n",
rule->rule_name,
rule->ref_count);
}
return true;
if (info->option & XT_PKNOCK_OPENSECRET) {
rule->max_time = info->max_time;
rule->autoclose_time = info->autoclose_time;
}
if (info->option & XT_PKNOCK_CHECKIP)
pr_debug("add_rule() (AC) rule found: %s - "
"ref_count: %d\n",
rule->rule_name, rule->ref_count);
return true;
}
rule = kmalloc(sizeof(*rule), GFP_KERNEL);
@@ -523,7 +516,8 @@ remove_rule(struct xt_pknock_mtinfo *info)
unsigned int hash = pknock_hash(info->rule_name, info->rule_name_len,
ipt_pknock_hash_rnd, rule_hashsize);
if (list_empty(&rule_hashtable[hash])) return;
if (list_empty(&rule_hashtable[hash]))
return;
list_for_each_safe(pos, n, &rule_hashtable[hash]) {
rule = list_entry(pos, struct xt_pknock_rule, head);
@@ -576,7 +570,8 @@ static struct peer *get_peer(struct xt_pknock_rule *rule, __be32 ip)
list_for_each_safe(pos, n, &rule->peer_head[hash]) {
peer = list_entry(pos, struct peer, head);
if (peer->ip == ip) return peer;
if (peer->ip == ip)
return peer;
}
return NULL;
}
@@ -1043,7 +1038,8 @@ static bool pknock_mt(const struct sk_buff *skb,
add_peer(peer, rule);
}
if (peer == NULL) goto out;
if (peer == NULL)
goto out;
update_peer(peer, info, rule, &hdr);
}
@@ -1087,15 +1083,15 @@ static int pknock_mt_check(const struct xt_mtchk_param *par)
RETURN_ERR("No crypto support available; "
"cannot use opensecret/closescret\n");
#endif
if ((info->option & XT_PKNOCK_OPENSECRET) && (info->ports_count != 1))
if (info->option & XT_PKNOCK_OPENSECRET && info->ports_count != 1)
RETURN_ERR("--opensecret must have just one knock port\n");
if (info->option & XT_PKNOCK_KNOCKPORT) {
if (info->option & XT_PKNOCK_CHECKIP)
RETURN_ERR("Can't specify --knockports with --checkip.\n");
if ((info->option & XT_PKNOCK_OPENSECRET) &&
if (info->option & XT_PKNOCK_OPENSECRET &&
!(info->option & XT_PKNOCK_CLOSESECRET))
RETURN_ERR("--opensecret must go with --closesecret.\n");
if ((info->option & XT_PKNOCK_CLOSESECRET) &&
if (info->option & XT_PKNOCK_CLOSESECRET &&
!(info->option & XT_PKNOCK_OPENSECRET))
RETURN_ERR("--closesecret must go with --opensecret.\n");
}
@@ -1115,13 +1111,11 @@ static int pknock_mt_check(const struct xt_mtchk_param *par)
RETURN_ERR("you must specify --time.\n");
}
if (info->option & XT_PKNOCK_OPENSECRET) {
if (info->open_secret_len == info->close_secret_len) {
if (memcmp(info->open_secret, info->close_secret,
info->open_secret_len) == 0)
RETURN_ERR("opensecret & closesecret cannot be equal.\n");
}
}
if (info->option & XT_PKNOCK_OPENSECRET &&
info->open_secret_len == info->close_secret_len &&
memcmp(info->open_secret, info->close_secret,
info->open_secret_len) == 0)
RETURN_ERR("opensecret & closesecret cannot be equal.\n");
if (!add_rule(info))
/* should ENOMEM here */
@@ -1166,11 +1160,10 @@ static int __init xt_pknock_mt_init(void)
}
crypto.tfm = crypto_alloc_hash(crypto.algo, 0, CRYPTO_ALG_ASYNC);
if (crypto.tfm == NULL) {
if (IS_ERR(crypto.tfm)) {
printk(KERN_ERR PKNOCK "failed to load transform for %s\n",
crypto.algo);
return -ENXIO;
return PTR_ERR(crypto.tfm);
}
crypto.size = crypto_hash_digestsize(crypto.tfm);
@@ -1195,7 +1188,8 @@ static void __exit xt_pknock_mt_exit(void)
kfree(rule_hashtable);
#ifdef PK_CRYPTO
if (crypto.tfm != NULL) crypto_free_hash(crypto.tfm);
if (crypto.tfm != NULL)
crypto_free_hash(crypto.tfm);
#endif
}

722
extensions/xt_DNETMAP.c Normal file
View File

@@ -0,0 +1,722 @@
/* DNETMAP - dynamic two-way 1:1 NAT mapping of IPv4 network addresses.
* The mapping can be applied to source (POSTROUTING|OUTPUT)
* or destination (PREROUTING),
*/
/* (C) 2011 Marek Kierdelewicz <marek@koba.pl>
*
* module is dedicated to my wife Eliza and my daughters Jula and Ola :* :* :*
*
* module audited and cleaned-up by Jan Engelhardt
*
* module uses some code and ideas from following modules:
* - "NETMAP" module by Svenning Soerensen <svenning@post5.tele.dk>
* - "recent" module by Stephen Frost <sfrost@snowman.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.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/ip.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter/x_tables.h>
#include <linux/version.h>
#include <net/netfilter/nf_nat_rule.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)
#include <net/net_namespace.h>
#include <net/netns/generic.h>
#endif
#include "xt_DNETMAP.h"
#include "compat_xtables.h"
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Marek Kierdelewicz <marek@koba.pl>");
MODULE_DESCRIPTION(
"Xtables: dynamic two-way 1:1 NAT mapping of IPv4 addresses");
MODULE_ALIAS("ipt_DNETMAP");
static unsigned int default_ttl = 600;
static unsigned int proc_perms = S_IRUGO | S_IWUSR;
static unsigned int proc_uid;
static unsigned int proc_gid;
static unsigned int default_hash_size = 256;
static unsigned int hash_size = 256;
static unsigned int disable_log;
static unsigned int whole_prefix = 1;
module_param(default_ttl, uint, S_IRUSR);
MODULE_PARM_DESC(default_ttl,
" default ttl value to be used if rule doesn't specify any (default: 600)");
module_param(hash_size, uint, S_IRUSR);
MODULE_PARM_DESC(hash_size,
" hash size for ip lists, needs to be power of 2 (default: 256)");
module_param(disable_log, uint, S_IRUSR);
MODULE_PARM_DESC(disable_log,
" disables logging of bind/timeout events (default: 0)");
module_param(whole_prefix, uint, S_IRUSR);
MODULE_PARM_DESC(whole_prefix,
" use network and broadcast addresses of specified prefix for bindings (default: 1)");
static unsigned int jtimeout;
struct dnetmap_entry {
struct list_head list;
/* priv2entry */
struct list_head glist;
/* pub2entry */
struct list_head grlist;
struct list_head lru_list;
__be32 prenat_addr;
__be32 postnat_addr;
unsigned long stamp;
struct dnetmap_prefix *prefix;
};
struct dnetmap_prefix {
struct nf_nat_multi_range_compat prefix;
char prefix_str[16];
struct list_head list;
unsigned int refcnt;
/* lru entry list */
struct list_head lru_list;
/* hash based on prenat-ips */
struct list_head iphash[0];
};
struct dnetmap_net {
struct list_head prefixes;
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *xt_dnetmap;
#endif
/* global hash */
struct list_head *dnetmap_iphash;
};
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)
static int dnetmap_net_id;
static inline struct dnetmap_net *dnetmap_pernet(struct net *net)
{
return net_generic(net, dnetmap_net_id);
}
#else
struct dnetmap_net *dnetmap;
#define dnetmap_pernet(x) dnetmap
#endif
static DEFINE_SPINLOCK(dnetmap_lock);
static DEFINE_MUTEX(dnetmap_mutex);
#ifdef CONFIG_PROC_FS
static const struct file_operations dnetmap_tg_fops;
#endif
static int dnetmap_stat_proc_read(char __user *buffer, char **start,
off_t offset, int length, int *eof,
void *data);
static inline unsigned int dnetmap_entry_hash(const __be32 addr)
{
return ntohl(addr) & (hash_size - 1);
}
static struct dnetmap_entry *
dnetmap_entry_lookup(struct dnetmap_net *dnetmap_net, const __be32 addr)
{
struct dnetmap_entry *e;
unsigned int h;
h = dnetmap_entry_hash(addr);
list_for_each_entry(e, &dnetmap_net->dnetmap_iphash[h], glist)
if (memcmp(&e->prenat_addr, &addr, sizeof(addr)) == 0)
return e;
return NULL;
}
static struct dnetmap_entry *
dnetmap_entry_rlookup(struct dnetmap_net *dnetmap_net, const __be32 addr)
{
struct dnetmap_entry *e;
unsigned int h;
h = dnetmap_entry_hash(addr);
list_for_each_entry(e, &dnetmap_net->dnetmap_iphash[hash_size + h],
grlist)
if (memcmp(&e->postnat_addr, &addr, sizeof(addr)) == 0)
return e;
return NULL;
}
static struct dnetmap_prefix *
dnetmap_prefix_lookup(struct dnetmap_net *dnetmap_net,
const struct nf_nat_multi_range_compat *mr)
{
struct dnetmap_prefix *p;
list_for_each_entry(p, &dnetmap_net->prefixes, list)
if (memcmp(&p->prefix, mr, sizeof(*mr)) == 0)
return p;
return NULL;
}
static void dnetmap_prefix_flush(struct dnetmap_net *dnetmap_net,
struct dnetmap_prefix *p)
{
struct dnetmap_entry *e, *next;
unsigned int i;
for (i = 0; i < hash_size; i++) {
list_for_each_entry_safe(e, next,
&dnetmap_net->dnetmap_iphash[i], glist)
if (e->prefix == p)
list_del(&e->glist);
list_for_each_entry_safe(e, next,
&dnetmap_net->
dnetmap_iphash[hash_size + i], grlist)
if (e->prefix == p)
list_del(&e->grlist);
list_for_each_entry_safe(e, next, &p->iphash[i], list) {
list_del(&e->list);
list_del(&e->lru_list);
kfree(e);
}
}
}
static int dnetmap_tg_check(const struct xt_tgchk_param *par)
{
struct dnetmap_net *dnetmap_net = dnetmap_pernet(par->net);
const struct xt_DNETMAP_tginfo *tginfo = par->targinfo;
const struct nf_nat_multi_range_compat *mr = &tginfo->prefix;
struct dnetmap_prefix *p;
struct dnetmap_entry *e;
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *pde_data, *pde_stat;
char proc_str_data[20];
char proc_str_stat[25];
#endif
int ret = -EINVAL;
int i;
__be32 a;
__u32 ip_min, ip_max, ip;
/* prefix not specified - no need to do anything */
if (!(tginfo->flags & XT_DNETMAP_PREFIX)) {
ret = 0;
return ret;
}
if (!(mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)) {
pr_debug("DNETMAP:check: bad MAP_IPS.\n");
return -EINVAL;
}
if (mr->rangesize != 1) {
pr_debug("DNETMAP:check: bad rangesize %u.\n", mr->rangesize);
return -EINVAL;
}
mutex_lock(&dnetmap_mutex);
p = dnetmap_prefix_lookup(dnetmap_net, mr);
if (p != NULL) {
p->refcnt++;
ret = 0;
goto out;
}
p = kzalloc(sizeof(*p) + sizeof(struct list_head) * hash_size * 2,
GFP_KERNEL);
if (p == NULL) {
ret = -ENOMEM;
goto out;
}
p->refcnt = 1;
memcpy(&p->prefix, mr, sizeof(*mr));
INIT_LIST_HEAD(&p->lru_list);
for (i = 0; i < hash_size * 2; i++)
INIT_LIST_HEAD(&p->iphash[i]);
ip_min = ntohl(mr->range[0].min_ip) + (whole_prefix == 0);
ip_max = ntohl(mr->range[0].max_ip) - (whole_prefix == 0);
sprintf(p->prefix_str, NIPQUAD_FMT "/%u", NIPQUAD(mr->range[0].min_ip),
33 - ffs(~(ip_min ^ ip_max)));
#ifdef CONFIG_PROC_FS
sprintf(proc_str_data, NIPQUAD_FMT "_%u", NIPQUAD(mr->range[0].min_ip),
33 - ffs(~(ip_min ^ ip_max)));
sprintf(proc_str_stat, NIPQUAD_FMT "_%u_stat", NIPQUAD(mr->range[0].min_ip),
33 - ffs(~(ip_min ^ ip_max)));
#endif
printk(KERN_INFO KBUILD_MODNAME ": new prefix %s\n", p->prefix_str);
for (ip = ip_min; ip <= ip_max; ip++) {
a = htonl(ip);
e = kmalloc(sizeof(*e), GFP_ATOMIC);
if (e == NULL)
return 0;
e->postnat_addr = a;
e->prenat_addr = 0;
e->stamp = jiffies;
e->prefix = p;
list_add_tail(&e->lru_list, &p->lru_list);
}
#ifdef CONFIG_PROC_FS
/* data */
pde_data = proc_create_data(proc_str_data, proc_perms,
dnetmap_net->xt_dnetmap,
&dnetmap_tg_fops, p);
if (pde_data == NULL) {
kfree(p);
ret = -ENOMEM;
goto out;
}
pde_data->uid = proc_uid;
pde_data->gid = proc_gid;
/* statistics */
pde_stat = create_proc_entry(proc_str_stat, proc_perms,
dnetmap_net->xt_dnetmap);
if (pde_stat == NULL) {
kfree(p);
ret = -ENOMEM;
goto out;
}
pde_stat->data = p;
pde_stat->read_proc = dnetmap_stat_proc_read;
pde_stat->uid = proc_uid;
pde_stat->gid = proc_gid;
#endif
spin_lock_bh(&dnetmap_lock);
list_add_tail(&p->list, &dnetmap_net->prefixes);
spin_unlock_bh(&dnetmap_lock);
ret = 0;
out:
mutex_unlock(&dnetmap_mutex);
return ret;
}
static unsigned int
dnetmap_tg(struct sk_buff **pskb, const struct xt_action_param *par)
{
struct sk_buff *skb = *pskb;
struct net *net = dev_net(par->in ? par->in : par->out);
struct dnetmap_net *dnetmap_net = dnetmap_pernet(net);
struct nf_conn *ct;
enum ip_conntrack_info ctinfo;
__be32 prenat_ip, postnat_ip, prenat_ip_prev;
const struct xt_DNETMAP_tginfo *tginfo = par->targinfo;
const struct nf_nat_multi_range_compat *mr = &tginfo->prefix;
struct nf_nat_range newrange;
struct dnetmap_entry *e;
struct dnetmap_prefix *p;
__s32 jttl;
NF_CT_ASSERT(par->hooknum == NF_INET_POST_ROUTING ||
par->hooknum == NF_INET_LOCAL_OUT ||
par->hooknum == NF_INET_PRE_ROUTING);
ct = nf_ct_get(skb, &ctinfo);
jttl = tginfo->flags & XT_DNETMAP_TTL ? tginfo->ttl * HZ : jtimeout;
/* in prerouting we try to map postnat-ip to prenat-ip */
if (par->hooknum == NF_INET_PRE_ROUTING) {
postnat_ip = ip_hdr(skb)->daddr;
spin_lock_bh(&dnetmap_lock);
e = dnetmap_entry_rlookup(dnetmap_net, postnat_ip);
if (e == NULL)
goto no_rev_map; /* no binding found */
/* if prefix is specified, we check if
it matches lookedup entry */
if (tginfo->flags & XT_DNETMAP_PREFIX)
if (memcmp(mr, &e->prefix, sizeof(*mr)))
goto no_rev_map;
/* don't reset ttl if flag is set */
if (jttl >= 0) {
p = e->prefix;
e->stamp = jiffies + jttl;
list_move_tail(&e->lru_list, &p->lru_list);
}
spin_unlock_bh(&dnetmap_lock);
newrange = ((struct nf_nat_range) {
mr->range[0].flags | IP_NAT_RANGE_MAP_IPS,
e->prenat_addr, e->prenat_addr,
mr->range[0].min, mr->range[0].max});
/* Hand modified range to generic setup. */
return nf_nat_setup_info(ct, &newrange,
HOOK2MANIP(par->hooknum));
}
prenat_ip = ip_hdr(skb)->saddr;
spin_lock_bh(&dnetmap_lock);
p = dnetmap_prefix_lookup(dnetmap_net, mr);
e = dnetmap_entry_lookup(dnetmap_net, prenat_ip);
if (e == NULL) { /* need for new binding */
bind_new_prefix:
e = list_entry(p->lru_list.next, struct dnetmap_entry,
lru_list);
if (e->prenat_addr != 0 && time_before(jiffies, e->stamp)) {
if (!disable_log)
printk(KERN_INFO KBUILD_MODNAME
": ip " NIPQUAD_FMT " - no free adresses in prefix %s\n",
NIPQUAD(prenat_ip), p->prefix_str);
goto no_free_ip;
}
postnat_ip = e->postnat_addr;
if (e->prenat_addr != 0) {
prenat_ip_prev = e->prenat_addr;
if (!disable_log)
printk(KERN_INFO KBUILD_MODNAME
": timeout binding " NIPQUAD_FMT " -> " NIPQUAD_FMT "\n",
NIPQUAD(prenat_ip_prev), NIPQUAD(postnat_ip) );
list_del(&e->list);
list_del(&e->glist);
list_del(&e->grlist);
}
e->prenat_addr = prenat_ip;
e->stamp = jiffies + jttl;
list_move_tail(&e->lru_list, &p->lru_list);
list_add_tail(&e->list,
&p->iphash[dnetmap_entry_hash(prenat_ip)]);
list_add_tail(&e->glist,
&dnetmap_net->
dnetmap_iphash[dnetmap_entry_hash(prenat_ip)]);
list_add_tail(&e->grlist,
&dnetmap_net->dnetmap_iphash[hash_size +
dnetmap_entry_hash
(postnat_ip)]);
if (!disable_log)
printk(KERN_INFO KBUILD_MODNAME
": add binding " NIPQUAD_FMT " -> " NIPQUAD_FMT "\n",
NIPQUAD(prenat_ip),NIPQUAD(postnat_ip));
} else {
if (!(tginfo->flags & XT_DNETMAP_REUSE))
if (time_before(e->stamp, jiffies) && p != e->prefix) {
if (!disable_log)
printk(KERN_INFO KBUILD_MODNAME
": timeout binding " NIPQUAD_FMT " -> " NIPQUAD_FMT "\n",
NIPQUAD(e->prenat_addr),
NIPQUAD(e->postnat_addr));
list_del(&e->list);
list_del(&e->glist);
list_del(&e->grlist);
e->prenat_addr = 0;
goto bind_new_prefix;
}
/* don't reset ttl if flag is set */
if (jttl >= 0) {
e->stamp = jiffies + jttl;
p = e->prefix;
list_move_tail(&e->lru_list, &p->lru_list);
}
postnat_ip = e->postnat_addr;
}
spin_unlock_bh(&dnetmap_lock);
newrange = ((struct nf_nat_range) {
mr->range[0].flags | IP_NAT_RANGE_MAP_IPS,
postnat_ip, postnat_ip,
mr->range[0].min, mr->range[0].max});
/* Hand modified range to generic setup. */
return nf_nat_setup_info(ct, &newrange, HOOK2MANIP(par->hooknum));
no_rev_map:
no_free_ip:
spin_unlock_bh(&dnetmap_lock);
return XT_CONTINUE;
}
static void dnetmap_tg_destroy(const struct xt_tgdtor_param *par)
{
struct dnetmap_net *dnetmap_net = dnetmap_pernet(par->net);
const struct xt_DNETMAP_tginfo *tginfo = par->targinfo;
const struct nf_nat_multi_range_compat *mr = &tginfo->prefix;
struct dnetmap_prefix *p;
#ifdef CONFIG_PROC_FS
char str[25];
#endif
if (!(tginfo->flags & XT_DNETMAP_PREFIX))
return;
mutex_lock(&dnetmap_mutex);
p = dnetmap_prefix_lookup(dnetmap_net, mr);
if (--p->refcnt == 0) {
spin_lock_bh(&dnetmap_lock);
list_del(&p->list);
spin_unlock_bh(&dnetmap_lock);
#ifdef CONFIG_PROC_FS
sprintf(str, NIPQUAD_FMT "_%u", NIPQUAD(mr->range[0].min_ip),
33 - ffs(~(ntohl(mr->range[0].min_ip ^
mr->range[0].max_ip))));
remove_proc_entry(str, dnetmap_net->xt_dnetmap);
sprintf(str, NIPQUAD_FMT "_%u_stat", NIPQUAD(mr->range[0].min_ip),
33 - ffs(~(ntohl(mr->range[0].min_ip ^
mr->range[0].max_ip))));
remove_proc_entry(str, dnetmap_net->xt_dnetmap);
#endif
dnetmap_prefix_flush(dnetmap_net, p);
kfree(p);
}
mutex_unlock(&dnetmap_mutex);
}
#ifdef CONFIG_PROC_FS
struct dnetmap_iter_state {
const struct dnetmap_prefix *p;
unsigned int bucket;
};
static void *dnetmap_seq_start(struct seq_file *seq, loff_t * pos)
__acquires(dnetmap_lock)
{
struct dnetmap_iter_state *st = seq->private;
const struct dnetmap_prefix *prefix = st->p;
struct dnetmap_entry *e;
loff_t p = *pos;
spin_lock_bh(&dnetmap_lock);
list_for_each_entry(e, &prefix->lru_list, lru_list)
if (p-- == 0)
return e;
return NULL;
}
static void *dnetmap_seq_next(struct seq_file *seq, void *v, loff_t * pos)
{
struct dnetmap_iter_state *st = seq->private;
const struct dnetmap_prefix *prefix = st->p;
const struct dnetmap_entry *e = v;
const struct list_head *head = e->lru_list.next;
if (head == &prefix->lru_list)
return NULL;
++*pos;
return list_entry(head, struct dnetmap_entry, lru_list);
}
static void dnetmap_seq_stop(struct seq_file *s, void *v)
__releases(dnetmap_lock)
{
spin_unlock_bh(&dnetmap_lock);
}
static int dnetmap_seq_show(struct seq_file *seq, void *v)
{
const struct dnetmap_entry *e = v;
seq_printf(seq, NIPQUAD_FMT " -> " NIPQUAD_FMT " --- ttl: %d lasthit: %lu\n",
NIPQUAD(e->prenat_addr), NIPQUAD(e->postnat_addr),
(int)(e->stamp - jiffies) / HZ, (e->stamp - jtimeout) / HZ);
return 0;
}
static const struct seq_operations dnetmap_seq_ops = {
.start = dnetmap_seq_start,
.next = dnetmap_seq_next,
.stop = dnetmap_seq_stop,
.show = dnetmap_seq_show,
};
static int dnetmap_seq_open(struct inode *inode, struct file *file)
{
struct proc_dir_entry *pde = PDE(inode);
struct dnetmap_iter_state *st;
st = __seq_open_private(file, &dnetmap_seq_ops, sizeof(*st));
if (st == NULL)
return -ENOMEM;
st->p = pde->data;
return 0;
}
static const struct file_operations dnetmap_tg_fops = {
.open = dnetmap_seq_open,
.read = seq_read,
.release = seq_release_private,
.owner = THIS_MODULE,
};
/* for statistics */
static int dnetmap_stat_proc_read(char __user *buffer, char **start,
off_t offset, int length, int *eof,
void *data)
{
const struct dnetmap_prefix *p = data;
struct dnetmap_entry *e;
unsigned int used, all;
long int ttl, sum_ttl;
used = 0;
all = 0;
sum_ttl = 0;
spin_lock_bh(&dnetmap_lock);
list_for_each_entry(e, &p->lru_list, lru_list) {
ttl = e->stamp - jiffies;
if (e->prenat_addr != 0 && ttl >= 0) {
used++;
sum_ttl += ttl;
}
all++;
}
sum_ttl = used > 0 ? sum_ttl / (used * HZ) : 0;
sprintf(buffer, "%u %u %ld\n", used, all, sum_ttl);
if (length >= strlen(buffer))
*eof = true;
spin_unlock_bh(&dnetmap_lock);
return strlen(buffer);
}
static int __net_init dnetmap_proc_net_init(struct net *net)
{
struct dnetmap_net *dnetmap_net = dnetmap_pernet(net);
dnetmap_net->xt_dnetmap = proc_mkdir("xt_DNETMAP", net->proc_net);
if (dnetmap_net->xt_dnetmap == NULL)
return -ENOMEM;
return 0;
}
static void __net_exit dnetmap_proc_net_exit(struct net *net)
{
proc_net_remove(net, "xt_DNETMAP");
}
#else
static inline int dnetmap_proc_net_init(struct net *net)
{
return 0;
}
static inline void dnetmap_proc_net_exit(struct net *net)
{
}
#endif /* CONFIG_PROC_FS */
static int __net_init dnetmap_net_init(struct net *net)
{
struct dnetmap_net *dnetmap_net = dnetmap_pernet(net);
int i;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34)
dnetmap = kmalloc(sizeof(struct dnetmap_net),GFP_ATOMIC);
if (dnetmap == NULL)
return -ENOMEM;
dnetmap_net = dnetmap;
#endif
dnetmap_net->dnetmap_iphash = kmalloc(sizeof(struct list_head) *
hash_size * 2, GFP_ATOMIC);
if (dnetmap_net->dnetmap_iphash == NULL)
return -ENOMEM;
INIT_LIST_HEAD(&dnetmap_net->prefixes);
for (i = 0; i < hash_size * 2; i++)
INIT_LIST_HEAD(&dnetmap_net->dnetmap_iphash[i]);
return dnetmap_proc_net_init(net);
}
static void __net_exit dnetmap_net_exit(struct net *net)
{
struct dnetmap_net *dnetmap_net = dnetmap_pernet(net);
BUG_ON(!list_empty(&dnetmap_net->prefixes));
kfree(dnetmap_net->dnetmap_iphash);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34)
kfree(dnetmap_net);
#endif
dnetmap_proc_net_exit(net);
}
static struct pernet_operations dnetmap_net_ops = {
.init = dnetmap_net_init,
.exit = dnetmap_net_exit,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)
.id = &dnetmap_net_id,
.size = sizeof(struct dnetmap_net),
#endif
};
static struct xt_target dnetmap_tg_reg __read_mostly = {
.name = "DNETMAP",
.family = NFPROTO_IPV4,
.target = dnetmap_tg,
.targetsize = sizeof(struct xt_DNETMAP_tginfo),
.table = "nat",
.hooks = (1 << NF_INET_POST_ROUTING) | (1 << NF_INET_LOCAL_OUT) |
(1 << NF_INET_PRE_ROUTING),
.checkentry = dnetmap_tg_check,
.destroy = dnetmap_tg_destroy,
.me = THIS_MODULE
};
static int __init dnetmap_tg_init(void)
{
int err;
/* verify parameters */
if (ffs(hash_size) != fls(hash_size) || hash_size <= 0) {
pr_info("bad hash_size parameter value - using defaults");
hash_size = default_hash_size;
}
jtimeout = default_ttl * HZ;
err = register_pernet_subsys(&dnetmap_net_ops);
if (err)
return err;
err = xt_register_target(&dnetmap_tg_reg);
if (err)
unregister_pernet_subsys(&dnetmap_net_ops);
return err;
}
static void __exit dnetmap_tg_exit(void)
{
xt_unregister_target(&dnetmap_tg_reg);
unregister_pernet_subsys(&dnetmap_net_ops);
}
module_init(dnetmap_tg_init);
module_exit(dnetmap_tg_exit);

16
extensions/xt_DNETMAP.h Normal file
View File

@@ -0,0 +1,16 @@
#ifndef _LINUX_NETFILTER_XT_DNETMAP_H
#define _LINUX_NETFILTER_XT_DNETMAP_H 1
enum {
XT_DNETMAP_TTL = 1 << 0,
XT_DNETMAP_REUSE = 1 << 1,
XT_DNETMAP_PREFIX = 1 << 2,
};
struct xt_DNETMAP_tginfo {
struct nf_nat_multi_range_compat prefix;
__u8 flags;
__s16 ttl;
};
#endif

View File

@@ -48,8 +48,13 @@ logmark_tg(struct sk_buff **pskb, const struct xt_action_param *par)
printk(" ctdir=%s", dir_names[ctinfo >= IP_CT_IS_REPLY]);
if (ct == NULL) {
printk(" ct=NULL ctmark=NULL ctstate=INVALID ctstatus=NONE");
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
} else if (nf_ct_is_untracked(ct)) {
printk(" ct=UNTRACKED ctmark=NULL ctstate=UNTRACKED ctstatus=NONE");
#else
} else if (ct == &nf_conntrack_untracked) {
printk(" ct=UNTRACKED ctmark=NULL ctstate=UNTRACKED ctstatus=NONE");
#endif
} else {
printk(" ct=0x%p ctmark=0x%x ctstate=", ct, ct->mark);
ctinfo %= IP_CT_IS_REPLY;

View File

@@ -9,6 +9,7 @@
* Samuel Jean & Nicolas Bouliane
*/
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/module.h>
@@ -27,25 +28,49 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Nicolas Bouliane");
MODULE_AUTHOR("Samuel Jean");
MODULE_DESCRIPTION("xtables module for geoip match");
MODULE_ALIAS("ip6t_geoip");
MODULE_ALIAS("ipt_geoip");
enum geoip_proto {
GEOIPROTO_IPV6,
GEOIPROTO_IPV4,
__GEOIPROTO_MAX,
};
/**
* @list: anchor point for geoip_head
* @subnets: packed ordered list of ranges (either v6 or v4)
* @count: number of ranges
* @cc: country code
*/
struct geoip_country_kernel {
struct list_head list;
struct geoip_subnet *subnets;
void *subnets;
atomic_t ref;
unsigned int count;
unsigned short cc;
};
static LIST_HEAD(geoip_head);
static struct list_head geoip_head[__GEOIPROTO_MAX];
static DEFINE_SPINLOCK(geoip_lock);
static const enum geoip_proto nfp2geo[] = {
[NFPROTO_IPV6] = GEOIPROTO_IPV6,
[NFPROTO_IPV4] = GEOIPROTO_IPV4,
};
static const size_t geoproto_size[] = {
[GEOIPROTO_IPV6] = sizeof(struct geoip_subnet6),
[GEOIPROTO_IPV4] = sizeof(struct geoip_subnet4),
};
static struct geoip_country_kernel *
geoip_add_node(const struct geoip_country_user __user *umem_ptr)
geoip_add_node(const struct geoip_country_user __user *umem_ptr,
enum geoip_proto proto)
{
struct geoip_country_user umem;
struct geoip_country_kernel *p;
struct geoip_subnet *s;
size_t size;
void *subnet;
int ret;
if (copy_from_user(&umem, umem_ptr, sizeof(umem)) != 0)
@@ -57,30 +82,30 @@ geoip_add_node(const struct geoip_country_user __user *umem_ptr)
p->count = umem.count;
p->cc = umem.cc;
s = vmalloc(p->count * sizeof(struct geoip_subnet));
if (s == NULL) {
size = p->count * geoproto_size[proto];
subnet = vmalloc(size);
if (subnet == NULL) {
ret = -ENOMEM;
goto free_p;
}
if (copy_from_user(s, (const void __user *)(unsigned long)umem.subnets,
p->count * sizeof(struct geoip_subnet)) != 0) {
if (copy_from_user(subnet,
(const void __user *)(unsigned long)umem.subnets, size) != 0) {
ret = -EFAULT;
goto free_s;
}
p->subnets = s;
p->subnets = subnet;
atomic_set(&p->ref, 1);
INIT_LIST_HEAD(&p->list);
spin_lock(&geoip_lock);
list_add_tail_rcu(&p->list, &geoip_head);
list_add_tail_rcu(&p->list, &geoip_head[proto]);
spin_unlock(&geoip_lock);
return p;
free_s:
vfree(s);
vfree(subnet);
free_p:
kfree(p);
return ERR_PTR(ret);
@@ -105,12 +130,13 @@ static void geoip_try_remove_node(struct geoip_country_kernel *p)
kfree(p);
}
static struct geoip_country_kernel *find_node(unsigned short cc)
static struct geoip_country_kernel *find_node(unsigned short cc,
enum geoip_proto proto)
{
struct geoip_country_kernel *p;
spin_lock(&geoip_lock);
list_for_each_entry_rcu(p, &geoip_head, list)
list_for_each_entry_rcu(p, &geoip_head[proto], list)
if (p->cc == cc) {
atomic_inc(&p->ref);
spin_unlock(&geoip_lock);
@@ -121,7 +147,73 @@ static struct geoip_country_kernel *find_node(unsigned short cc)
return NULL;
}
static bool geoip_bsearch(const struct geoip_subnet *range,
static inline int
ipv6_cmp(const struct in6_addr *p, const struct in6_addr *q)
{
unsigned int i;
for (i = 0; i < 4; ++i) {
if (p->s6_addr32[i] < q->s6_addr32[i])
return -1;
else if (p->s6_addr32[i] > q->s6_addr32[i])
return 1;
}
return 0;
}
static bool geoip_bsearch6(const struct geoip_subnet6 *range,
const struct in6_addr *addr, int lo, int hi)
{
int mid;
if (hi <= lo)
return false;
mid = (lo + hi) / 2;
if (ipv6_cmp(&range[mid].begin, addr) <= 0 &&
ipv6_cmp(addr, &range[mid].end) <= 0)
return true;
if (ipv6_cmp(&range[mid].begin, addr) > 0)
return geoip_bsearch6(range, addr, lo, mid);
else if (ipv6_cmp(&range[mid].end, addr) < 0)
return geoip_bsearch6(range, addr, mid + 1, hi);
WARN_ON(true);
return false;
}
static bool
xt_geoip_mt6(const struct sk_buff *skb, struct xt_action_param *par)
{
const struct xt_geoip_match_info *info = par->matchinfo;
const struct geoip_country_kernel *node;
const struct ipv6hdr *iph = ipv6_hdr(skb);
unsigned int i;
struct in6_addr ip;
memcpy(&ip, (info->flags & XT_GEOIP_SRC) ? &iph->saddr : &iph->daddr,
sizeof(ip));
for (i = 0; i < 4; ++i)
ip.s6_addr32[i] = ntohl(ip.s6_addr32[i]);
rcu_read_lock();
for (i = 0; i < info->count; i++) {
if ((node = info->mem[i].kernel) == NULL) {
printk(KERN_ERR "xt_geoip: what the hell ?? '%c%c' isn't loaded into memory... skip it!\n",
COUNTRY(info->cc[i]));
continue;
}
if (geoip_bsearch6(node->subnets, &ip, 0, node->count)) {
rcu_read_unlock();
return !(info->flags & XT_GEOIP_INV);
}
}
rcu_read_unlock();
return info->flags & XT_GEOIP_INV;
}
static bool geoip_bsearch4(const struct geoip_subnet4 *range,
uint32_t addr, int lo, int hi)
{
int mid;
@@ -132,16 +224,16 @@ static bool geoip_bsearch(const struct geoip_subnet *range,
if (range[mid].begin <= addr && addr <= range[mid].end)
return true;
if (range[mid].begin > addr)
return geoip_bsearch(range, addr, lo, mid);
return geoip_bsearch4(range, addr, lo, mid);
else if (range[mid].end < addr)
return geoip_bsearch(range, addr, mid + 1, hi);
return geoip_bsearch4(range, addr, mid + 1, hi);
WARN_ON(true);
return false;
}
static bool
xt_geoip_mt(const struct sk_buff *skb, struct xt_action_param *par)
xt_geoip_mt4(const struct sk_buff *skb, struct xt_action_param *par)
{
const struct xt_geoip_match_info *info = par->matchinfo;
const struct geoip_country_kernel *node;
@@ -149,21 +241,15 @@ xt_geoip_mt(const struct sk_buff *skb, struct xt_action_param *par)
unsigned int i;
uint32_t ip;
if (info->flags & XT_GEOIP_SRC)
ip = ntohl(iph->saddr);
else
ip = ntohl(iph->daddr);
ip = ntohl((info->flags & XT_GEOIP_SRC) ? iph->saddr : iph->daddr);
rcu_read_lock();
for (i = 0; i < info->count; i++) {
if ((node = info->mem[i].kernel) == NULL) {
printk(KERN_ERR "xt_geoip: what the hell ?? '%c%c' isn't loaded into memory... skip it!\n",
COUNTRY(info->cc[i]));
continue;
}
if (geoip_bsearch(node->subnets, ip, 0, node->count)) {
if (geoip_bsearch4(node->subnets, ip, 0, node->count)) {
rcu_read_unlock();
return !(info->flags & XT_GEOIP_INV);
}
@@ -180,9 +266,10 @@ static int xt_geoip_mt_checkentry(const struct xt_mtchk_param *par)
unsigned int i;
for (i = 0; i < info->count; i++) {
node = find_node(info->cc[i]);
node = find_node(info->cc[i], nfp2geo[par->family]);
if (node == NULL) {
node = geoip_add_node((const void __user *)(unsigned long)info->mem[i].user);
node = geoip_add_node((const void __user *)(unsigned long)info->mem[i].user,
nfp2geo[par->family]);
if (IS_ERR(node)) {
printk(KERN_ERR
"xt_geoip: unable to load '%c%c' into memory: %ld\n",
@@ -227,25 +314,41 @@ static void xt_geoip_mt_destroy(const struct xt_mtdtor_param *par)
"xt_geoip: please report this bug to the maintainers\n");
}
static struct xt_match xt_geoip_match __read_mostly = {
.name = "geoip",
.revision = 1,
.family = NFPROTO_IPV4,
.match = xt_geoip_mt,
.checkentry = xt_geoip_mt_checkentry,
.destroy = xt_geoip_mt_destroy,
.matchsize = sizeof(struct xt_geoip_match_info),
.me = THIS_MODULE,
static struct xt_match xt_geoip_match[] __read_mostly = {
{
.name = "geoip",
.revision = 1,
.family = NFPROTO_IPV6,
.match = xt_geoip_mt6,
.checkentry = xt_geoip_mt_checkentry,
.destroy = xt_geoip_mt_destroy,
.matchsize = sizeof(struct xt_geoip_match_info),
.me = THIS_MODULE,
},
{
.name = "geoip",
.revision = 1,
.family = NFPROTO_IPV4,
.match = xt_geoip_mt4,
.checkentry = xt_geoip_mt_checkentry,
.destroy = xt_geoip_mt_destroy,
.matchsize = sizeof(struct xt_geoip_match_info),
.me = THIS_MODULE,
},
};
static int __init xt_geoip_mt_init(void)
{
return xt_register_match(&xt_geoip_match);
unsigned int i;
for (i = 0; i < ARRAY_SIZE(geoip_head); ++i)
INIT_LIST_HEAD(&geoip_head[i]);
return xt_register_matches(xt_geoip_match, ARRAY_SIZE(xt_geoip_match));
}
static void __exit xt_geoip_mt_fini(void)
{
xt_unregister_match(&xt_geoip_match);
xt_unregister_matches(xt_geoip_match, ARRAY_SIZE(xt_geoip_match));
}
module_init(xt_geoip_mt_init);

View File

@@ -22,11 +22,15 @@ enum {
};
/* Yup, an address range will be passed in with host-order */
struct geoip_subnet {
struct geoip_subnet4 {
__u32 begin;
__u32 end;
};
struct geoip_subnet6 {
struct in6_addr begin, end;
};
struct geoip_country_user {
aligned_u64 subnets;
__u32 count;
@@ -36,7 +40,7 @@ struct geoip_country_user {
struct geoip_country_kernel;
union geoip_country_group {
aligned_u64 user;
aligned_u64 user; /* struct geoip_country_user * */
struct geoip_country_kernel *kernel;
};
@@ -49,6 +53,6 @@ struct xt_geoip_match_info {
union geoip_country_group mem[XT_GEOIP_MAX];
};
#define COUNTRY(cc) (cc >> 8), (cc & 0x00FF)
#define COUNTRY(cc) ((cc) >> 8), ((cc) & 0x00FF)
#endif /* _LINUX_NETFILTER_XT_GEOIP_H */

View File

@@ -1,3 +1,5 @@
# -*- Makefile -*-
pkglibexec_SCRIPTS = geoip_build_db.pl geoip_download.sh
pkglibexec_SCRIPTS = xt_geoip_build xt_geoip_dl
man1_MANS = xt_geoip_build.1 xt_geoip_dl.1

View File

@@ -1,54 +0,0 @@
#!/usr/bin/perl
#
# Converter for MaxMind CSV database to binary, for xt_geoip
# Copyright © Jan Engelhardt <jengelh@medozas.de>, 2008
#
# Use -b argument to create big-endian tables.
#
use Getopt::Long;
use IO::Handle;
use Text::CSV_XS; # or trade for Text::CSV
use strict;
my %country;
my %names;
my $csv = Text::CSV_XS->new({binary => 0, eol => $/}); # or Text::CSV
my $mode = "VV";
my $target_dir = ".";
&Getopt::Long::Configure(qw(bundling));
&GetOptions(
"D=s" => \$target_dir,
"b" => sub { $mode = "NN"; },
);
if (!-d $target_dir) {
print STDERR "Target directory $target_dir does not exist.\n";
exit 1;
}
while (my $row = $csv->getline(*ARGV)) {
if (!defined($country{$row->[4]})) {
$country{$row->[4]} = [];
$names{$row->[4]} = $row->[5];
}
my $c = $country{$row->[4]};
push(@$c, [$row->[2], $row->[3]]);
if ($. % 4096 == 0) {
print STDERR "\r\e[2K$. entries";
}
}
print STDERR "\r\e[2K$. entries total\n";
foreach my $iso_code (sort keys %country) {
printf "%5u ranges for %s %s\n",
scalar(@{$country{$iso_code}}),
$iso_code, $names{$iso_code};
open(my $fh, "> $target_dir/".uc($iso_code).".iv0");
foreach my $range (@{$country{$iso_code}}) {
print $fh pack($mode, $range->[0], $range->[1]);
}
close $fh;
}

143
geoip/xt_geoip_build Executable file
View File

@@ -0,0 +1,143 @@
#!/usr/bin/perl
#
# Converter for MaxMind CSV database to binary, for xt_geoip
# Copyright © Jan Engelhardt <jengelh@medozas.de>, 2008-2011
#
# Use -b argument to create big-endian tables.
#
use Getopt::Long;
use IO::Handle;
use Text::CSV_XS; # or trade for Text::CSV
use strict;
my $csv = Text::CSV_XS->new({
allow_whitespace => 1,
binary => 1,
eol => $/,
}); # or Text::CSV
my $target_dir = ".";
&Getopt::Long::Configure(qw(bundling));
&GetOptions(
"D=s" => \$target_dir,
);
if (!-d $target_dir) {
print STDERR "Target directory $target_dir does not exist.\n";
exit 1;
}
foreach (qw(LE BE)) {
my $dir = "$target_dir/$_";
if (!-e $dir && !mkdir($dir)) {
print STDERR "Could not mkdir $dir: $!\n";
exit 1;
}
}
&dump(&collect());
sub collect
{
my %country;
while (my $row = $csv->getline(*ARGV)) {
if (!defined($country{$row->[4]})) {
$country{$row->[4]} = {
name => $row->[5],
pool_v4 => [],
pool_v6 => [],
};
}
my $c = $country{$row->[4]};
if ($row->[0] =~ /:/) {
push(@{$c->{pool_v6}},
[&ip6_pack($row->[0]), &ip6_pack($row->[1])]);
} else {
push(@{$c->{pool_v4}}, [$row->[2], $row->[3]]);
}
if ($. % 4096 == 0) {
print STDERR "\r\e[2K$. entries";
}
}
print STDERR "\r\e[2K$. entries total\n";
return \%country;
}
sub dump
{
my $country = shift @_;
foreach my $iso_code (sort keys %$country) {
&dump_one($iso_code, $country->{$iso_code});
}
}
sub dump_one
{
my($iso_code, $country) = @_;
my($file, $fh_le, $fh_be);
printf "%5u IPv6 ranges for %s %s\n",
scalar(@{$country->{pool_v6}}),
$iso_code, $country->{name};
$file = "$target_dir/LE/".uc($iso_code).".iv6";
if (!open($fh_le, "> $file")) {
print STDERR "Error opening $file: $!\n";
exit 1;
}
$file = "$target_dir/BE/".uc($iso_code).".iv6";
if (!open($fh_be, "> $file")) {
print STDERR "Error opening $file: $!\n";
exit 1;
}
foreach my $range (@{$country->{pool_v6}}) {
print $fh_be $range->[0], $range->[1];
print $fh_le &ip6_swap($range->[0]), &ip6_swap($range->[1]);
}
close $fh_le;
close $fh_be;
printf "%5u IPv4 ranges for %s %s\n",
scalar(@{$country->{pool_v4}}),
$iso_code, $country->{name};
$file = "$target_dir/LE/".uc($iso_code).".iv4";
if (!open($fh_le, "> $file")) {
print STDERR "Error opening $file: $!\n";
exit 1;
}
$file = "$target_dir/BE/".uc($iso_code).".iv4";
if (!open($fh_be, "> $file")) {
print STDERR "Error opening $file: $!\n";
exit 1;
}
foreach my $range (@{$country->{pool_v4}}) {
print $fh_le pack("VV", $range->[0], $range->[1]);
print $fh_be pack("NN", $range->[0], $range->[1]);
}
close $fh_le;
close $fh_be;
}
sub ip6_pack
{
my $addr = shift @_;
$addr =~ s{::}{:!:};
my @addr = split(/:/, $addr);
my @e = (0) x 8;
foreach (@addr) {
if ($_ eq "!") {
$_ = join(':', @e[0..(8-scalar(@addr))]);
}
}
@addr = split(/:/, join(':', @addr));
$_ = hex($_) foreach @addr;
return pack("n*", @addr);
}
sub ip6_swap
{
return pack("V*", unpack("N*", shift @_));
}

35
geoip/xt_geoip_build.1 Normal file
View File

@@ -0,0 +1,35 @@
.TH xt_geoip_build 1 "2010-12-17" "xtables-addons" "xtables-addons"
.SH Name
.PP
xt_geoip_build \(em convert GeoIP.csv to packed format for xt_geoip
.SH Syntax
.PP
\fI/usr/libexec/xt_geoip/\fP\fBxt_geoip_build\fP [\fB\-D\fP
\fItarget_dir\fP] [\fIfile\fP...]
.SH Description
.PP
xt_geoip_build is used to build packed raw representations of the range
database that the xt_geoip module relies on. Since kernel memory is precious,
much of the preprocessing is done in userspace by this very building tool. One
file is produced for each country, so that no more addresses than needed are
required to be loaded into memory. The ranges in the packed database files are
also ordered, as xt_geoip relies on this property for its bisection approach to
work.
.PP
Input is processed from the listed files, or if none is given, from stdin.
.PP
Since the script is usually installed to the libexec directory of the
xtables-addons package and this is outside $PATH (on purpose), invoking the
script requires it to be called with a path.
.PP Options
.TP
\fB\-D\fP \fItarget_dir\fP
Specify a target directory into which the files are to be put.
.SH Application
.PP
Shell commands to build the databases and put them to where they are expected:
.PP
xt_geoip_build -D /usr/share/xt_geoip
.SH See also
.PP
xt_geoip_dl(1)

21
geoip/xt_geoip_dl.1 Normal file
View File

@@ -0,0 +1,21 @@
.TH xt_geoip_dl 1 "2010-12-17" "xtables-addons" "xtables-addons"
.SH Name
.PP
xt_geoip_dl \(em download GeoIP database files
.SH Syntax
.PP
\fI/usr/libexec/xt_geoip/\fP\fBxt_geoip_dl\fP
.SH Description
.PP
Downloads and unpacks the MaxMind GeoIP Country Lite databases for IPv4 and
IPv6 and unpacks them to the current directory.
.PP
Since the script is usually installed to the libexec directory of the
xtables-addons package and this is outside $PATH (on purpose), invoking the
script requires it to be called with a path.
.SH Options
.PP
None.
.SH See also
.PP
xt_geoip_build(1)

View File

@@ -0,0 +1,215 @@
/*
* Definitions and Declarations for tuple.
*
* 16 Dec 2003: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
* - generalize L3 protocol dependent part.
*
* Derived from include/linux/netfiter_ipv4/ip_conntrack_tuple.h
*/
#ifndef _NF_CONNTRACK_TUPLE_H
#define _NF_CONNTRACK_TUPLE_H
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter/nf_conntrack_tuple_common.h>
/*#include <linux/list_nulls.h>*/
/* A `tuple' is a structure containing the information to uniquely
identify a connection. ie. if two packets have the same tuple, they
are in the same connection; if not, they are not.
We divide the structure along "manipulatable" and
"non-manipulatable" lines, for the benefit of the NAT code.
*/
#define NF_CT_TUPLE_L3SIZE ARRAY_SIZE(((union nf_inet_addr *)NULL)->all)
/* The protocol-specific manipulable parts of the tuple: always in
network order! */
union nf_conntrack_man_proto {
/* Add other protocols here. */
__be16 all;
struct {
__be16 port;
} tcp;
struct {
__be16 port;
} udp;
struct {
__be16 id;
} icmp;
struct {
__be16 port;
} dccp;
struct {
__be16 port;
} sctp;
struct {
__be16 key; /* GRE key is 32bit, PPtP only uses 16bit */
} gre;
};
/* The manipulable part of the tuple. */
struct nf_conntrack_man {
union nf_inet_addr u3;
union nf_conntrack_man_proto u;
/* Layer 3 protocol */
u_int16_t l3num;
};
/* This contains the information to distinguish a connection. */
struct nf_conntrack_tuple {
struct nf_conntrack_man src;
/* These are the parts of the tuple which are fixed. */
struct {
union nf_inet_addr u3;
union {
/* Add other protocols here. */
__be16 all;
struct {
__be16 port;
} tcp;
struct {
__be16 port;
} udp;
struct {
u_int8_t type, code;
} icmp;
struct {
__be16 port;
} dccp;
struct {
__be16 port;
} sctp;
struct {
__be16 key;
} gre;
} u;
/* The protocol. */
u_int8_t protonum;
/* The direction (for tuplehash) */
u_int8_t dir;
} dst;
};
struct nf_conntrack_tuple_mask {
struct {
union nf_inet_addr u3;
union nf_conntrack_man_proto u;
} src;
};
#ifdef __KERNEL__
static inline void nf_ct_dump_tuple_ip(const struct nf_conntrack_tuple *t)
{
#ifdef DEBUG
printk("tuple %p: %u %pI4:%hu -> %pI4:%hu\n",
t, t->dst.protonum,
&t->src.u3.ip, ntohs(t->src.u.all),
&t->dst.u3.ip, ntohs(t->dst.u.all));
#endif
}
static inline void nf_ct_dump_tuple_ipv6(const struct nf_conntrack_tuple *t)
{
#ifdef DEBUG
printk("tuple %p: %u %pI6 %hu -> %pI6 %hu\n",
t, t->dst.protonum,
t->src.u3.all, ntohs(t->src.u.all),
t->dst.u3.all, ntohs(t->dst.u.all));
#endif
}
static inline void nf_ct_dump_tuple(const struct nf_conntrack_tuple *t)
{
switch (t->src.l3num) {
case AF_INET:
nf_ct_dump_tuple_ip(t);
break;
case AF_INET6:
nf_ct_dump_tuple_ipv6(t);
break;
}
}
/* If we're the first tuple, it's the original dir. */
#define NF_CT_DIRECTION(h) \
((enum ip_conntrack_dir)(h)->tuple.dst.dir)
/* Connections have two entries in the hash table: one for each way */
struct nf_conntrack_tuple_hash {
struct hlist_nulls_node hnnode;
struct nf_conntrack_tuple tuple;
};
static inline bool __nf_ct_tuple_src_equal(const struct nf_conntrack_tuple *t1,
const struct nf_conntrack_tuple *t2)
{
return (nf_inet_addr_cmp(&t1->src.u3, &t2->src.u3) &&
t1->src.u.all == t2->src.u.all &&
t1->src.l3num == t2->src.l3num);
}
static inline bool __nf_ct_tuple_dst_equal(const struct nf_conntrack_tuple *t1,
const struct nf_conntrack_tuple *t2)
{
return (nf_inet_addr_cmp(&t1->dst.u3, &t2->dst.u3) &&
t1->dst.u.all == t2->dst.u.all &&
t1->dst.protonum == t2->dst.protonum);
}
static inline bool nf_ct_tuple_equal(const struct nf_conntrack_tuple *t1,
const struct nf_conntrack_tuple *t2)
{
return __nf_ct_tuple_src_equal(t1, t2) &&
__nf_ct_tuple_dst_equal(t1, t2);
}
static inline bool
nf_ct_tuple_mask_equal(const struct nf_conntrack_tuple_mask *m1,
const struct nf_conntrack_tuple_mask *m2)
{
return (nf_inet_addr_cmp(&m1->src.u3, &m2->src.u3) &&
m1->src.u.all == m2->src.u.all);
}
static inline bool
nf_ct_tuple_src_mask_cmp(const struct nf_conntrack_tuple *t1,
const struct nf_conntrack_tuple *t2,
const struct nf_conntrack_tuple_mask *mask)
{
int count;
for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++) {
if ((t1->src.u3.all[count] ^ t2->src.u3.all[count]) &
mask->src.u3.all[count])
return false;
}
if ((t1->src.u.all ^ t2->src.u.all) & mask->src.u.all)
return false;
if (t1->src.l3num != t2->src.l3num ||
t1->dst.protonum != t2->dst.protonum)
return false;
return true;
}
static inline bool
nf_ct_tuple_mask_cmp(const struct nf_conntrack_tuple *t,
const struct nf_conntrack_tuple *tuple,
const struct nf_conntrack_tuple_mask *mask)
{
return nf_ct_tuple_src_mask_cmp(t, tuple, mask) &&
__nf_ct_tuple_dst_equal(t, tuple);
}
#endif /* __KERNEL__ */
#endif /* _NF_CONNTRACK_TUPLE_H */

View File

@@ -0,0 +1,93 @@
#ifndef _NF_NAT_H
#define _NF_NAT_H
#include <linux/netfilter_ipv4.h>
#include <net/netfilter/nf_conntrack_tuple.h>
#define NF_NAT_MAPPING_TYPE_MAX_NAMELEN 16
enum nf_nat_manip_type {
IP_NAT_MANIP_SRC,
IP_NAT_MANIP_DST
};
/* SRC manip occurs POST_ROUTING or LOCAL_IN */
#define HOOK2MANIP(hooknum) ((hooknum) != NF_INET_POST_ROUTING && \
(hooknum) != NF_INET_LOCAL_IN)
#define IP_NAT_RANGE_MAP_IPS 1
#define IP_NAT_RANGE_PROTO_SPECIFIED 2
#define IP_NAT_RANGE_PROTO_RANDOM 4
#define IP_NAT_RANGE_PERSISTENT 8
/* NAT sequence number modifications */
struct nf_nat_seq {
/* position of the last TCP sequence number modification (if any) */
u_int32_t correction_pos;
/* sequence number offset before and after last modification */
int16_t offset_before, offset_after;
};
/* Single range specification. */
struct nf_nat_range {
/* Set to OR of flags above. */
unsigned int flags;
/* Inclusive: network order. */
__be32 min_ip, max_ip;
/* Inclusive: network order */
union nf_conntrack_man_proto min, max;
};
/* For backwards compat: don't use in modern code. */
struct nf_nat_multi_range_compat {
unsigned int rangesize; /* Must be 1. */
/* hangs off end. */
struct nf_nat_range range[1];
};
#ifdef __KERNEL__
#include <linux/list.h>
#include <linux/netfilter/nf_conntrack_pptp.h>
#include <net/netfilter/nf_conntrack_extend.h>
/* per conntrack: nat application helper private data */
union nf_conntrack_nat_help {
/* insert nat helper private data here */
struct nf_nat_pptp nat_pptp_info;
};
struct nf_conn;
/* The structure embedded in the conntrack structure. */
struct nf_conn_nat {
struct hlist_node bysource;
struct nf_nat_seq seq[IP_CT_DIR_MAX];
struct nf_conn *ct;
union nf_conntrack_nat_help help;
#if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \
defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE)
int masq_index;
#endif
};
/* Set up the info structure to map into this range. */
extern unsigned int nf_nat_setup_info(struct nf_conn *ct,
const struct nf_nat_range *range,
enum nf_nat_manip_type maniptype);
/* Is this tuple already taken? (not by us)*/
extern int nf_nat_used_tuple(const struct nf_conntrack_tuple *tuple,
const struct nf_conn *ignored_conntrack);
static inline struct nf_conn_nat *nfct_nat(const struct nf_conn *ct)
{
return nf_ct_ext_find(ct, NF_CT_EXT_NAT);
}
#else /* !__KERNEL__: iptables wants this to compile. */
#define nf_nat_multi_range nf_nat_multi_range_compat
#endif /*__KERNEL__*/
#endif

View File

@@ -5,6 +5,7 @@ build_CHAOS=m
build_CHECKSUM=
build_DELUDE=m
build_DHCPMAC=m
build_DNETMAP=m
build_ECHO=
build_IPMARK=m
build_LOGMARK=m