mirror of
git://git.code.sf.net/p/xtables-addons/xtables-addons
synced 2025-09-20 19:44:56 +02:00
Compare commits
45 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
9f59f21614 | ||
![]() |
7a8bfed52c | ||
![]() |
1edc9b943b | ||
![]() |
ebfa77795a | ||
![]() |
4a8aa505c4 | ||
![]() |
4654ee127f | ||
![]() |
a7a77d7146 | ||
![]() |
2a61ca7d4b | ||
![]() |
39de351a91 | ||
![]() |
07bf41a294 | ||
![]() |
07cd29d9ce | ||
![]() |
eb9634aee6 | ||
![]() |
19f241a09c | ||
![]() |
0a29c1d32f | ||
![]() |
93a17fdde0 | ||
![]() |
80444b0d31 | ||
![]() |
f180c0e5c6 | ||
![]() |
ca8ebe4467 | ||
![]() |
e82410735a | ||
![]() |
89e72bb0f4 | ||
![]() |
77b9f2024c | ||
![]() |
0edb572f6e | ||
![]() |
8b1ff64b8b | ||
![]() |
ebb61aa3c9 | ||
![]() |
bd2e6108f3 | ||
![]() |
288492c820 | ||
![]() |
e425c8f277 | ||
![]() |
e3e88827fb | ||
![]() |
6c709fd682 | ||
![]() |
1b53724a61 | ||
![]() |
983b28fe8e | ||
![]() |
3141b2ff86 | ||
![]() |
980a53348f | ||
![]() |
8ea781e257 | ||
![]() |
7e39ee66e0 | ||
![]() |
65e97a66e6 | ||
![]() |
d82b20ead7 | ||
![]() |
c5d4dd0bcf | ||
![]() |
0168f8e8a2 | ||
![]() |
dc22ec7bd1 | ||
![]() |
25bf680ead | ||
![]() |
4d547c2bfc | ||
![]() |
f7c7264a65 | ||
![]() |
0f42828fd6 | ||
![]() |
e2da87230a |
13
INSTALL
13
INSTALL
@@ -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
|
||||
|
||||
@@ -60,11 +60,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
7
README
@@ -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
|
||||
============================
|
||||
|
||||
|
64
configure.ac
64
configure.ac
@@ -1,9 +1,9 @@
|
||||
|
||||
AC_INIT([xtables-addons], [1.32])
|
||||
AC_INIT([xtables-addons], [1.33])
|
||||
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
|
||||
@@ -49,35 +49,37 @@ if grep -q "CentOS release 5\." /etc/redhat-release 2>/dev/null ||
|
||||
# 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" -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;
|
||||
fi;
|
||||
fi;
|
||||
fi;
|
||||
|
||||
|
@@ -3,6 +3,26 @@ HEAD
|
||||
====
|
||||
|
||||
|
||||
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:
|
||||
|
@@ -1,5 +1,8 @@
|
||||
# -*- Makefile -*-
|
||||
|
||||
AM_CPPFLAGS = ${regular_CPPFLAGS} -I${abs_top_srcdir}/extensions
|
||||
AM_CFLAGS = ${regular_CFLAGS}
|
||||
|
||||
include ../../Makefile.extra
|
||||
|
||||
sbin_PROGRAMS = iptaccount
|
||||
|
1
extensions/ACCOUNT/VERSION.txt
Normal file
1
extensions/ACCOUNT/VERSION.txt
Normal file
@@ -0,0 +1 @@
|
||||
1.16
|
@@ -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);
|
||||
}
|
||||
|
@@ -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 *
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
1
extensions/ipset-4/VERSION.txt
Normal file
1
extensions/ipset-4/VERSION.txt
Normal file
@@ -0,0 +1 @@
|
||||
4.5
|
@@ -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
|
||||
|
@@ -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
|
||||
|
||||
|
1
extensions/ipset-5/VERSION.txt
Normal file
1
extensions/ipset-5/VERSION.txt
Normal file
@@ -0,0 +1 @@
|
||||
5.4.1-genl
|
@@ -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,
|
||||
|
@@ -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)))
|
||||
|
@@ -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
|
||||
|
@@ -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));
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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,
|
||||
|
@@ -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,
|
||||
|
File diff suppressed because it is too large
Load Diff
136
extensions/ipset-5/ip_set_getport.c
Normal file
136
extensions/ipset-5/ip_set_getport.c
Normal 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);
|
@@ -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*/
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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 */
|
@@ -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)
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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
291
extensions/ipset-5/pfxlen.c
Normal 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);
|
35
extensions/ipset-5/pfxlen.h
Normal file
35
extensions/ipset-5/pfxlen.h
Normal 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 */
|
@@ -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);
|
||||
}
|
||||
|
@@ -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 */
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -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 = {
|
||||
|
@@ -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
241
extensions/libxt_DNETMAP.c
Normal 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);
|
||||
}
|
91
extensions/libxt_DNETMAP.man
Normal file
91
extensions/libxt_DNETMAP.man
Normal 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.
|
||||
|
||||
.
|
@@ -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 = {
|
||||
|
@@ -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 = {
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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 = {
|
||||
|
@@ -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 = {
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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 = {
|
||||
|
@@ -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));
|
||||
}
|
||||
|
@@ -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.
|
||||
|
@@ -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 = {
|
||||
|
@@ -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");
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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)
|
||||
|
@@ -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
|
||||
|
@@ -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 = {
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
@@ -1,5 +1,8 @@
|
||||
# -*- Makefile -*-
|
||||
|
||||
AM_CPPFLAGS = ${regular_CPPFLAGS} -I${abs_top_srcdir}/extensions
|
||||
AM_CFLAGS = ${regular_CFLAGS}
|
||||
|
||||
include ../../Makefile.extra
|
||||
|
||||
noinst_PROGRAMS = pknlusr
|
||||
|
@@ -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 = {
|
||||
|
@@ -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];
|
||||
|
699
extensions/xt_DNETMAP.c
Normal file
699
extensions/xt_DNETMAP.c
Normal file
@@ -0,0 +1,699 @@
|
||||
/* 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) 2010 Marek Kierdelewicz <marek@koba.pl>
|
||||
*
|
||||
* module is dedicated to my wife Eliza and my daughters Jula and Ola :* :* :*
|
||||
*
|
||||
* 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 <net/netfilter/nf_nat_rule.h>
|
||||
#include <net/net_namespace.h>
|
||||
#include <net/netns/generic.h>
|
||||
#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");
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
static int dnetmap_net_id;
|
||||
static inline struct dnetmap_net *dnetmap_pernet(struct net *net)
|
||||
{
|
||||
return net_generic(net, dnetmap_net_id);
|
||||
}
|
||||
|
||||
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, "%pI4/%u", &mr->range[0].min_ip,
|
||||
33 - ffs(~(ip_min ^ ip_max)));
|
||||
#ifdef CONFIG_PROC_FS
|
||||
sprintf(proc_str_data, "%pI4_%u", &mr->range[0].min_ip,
|
||||
33 - ffs(~(ip_min ^ ip_max)));
|
||||
sprintf(proc_str_stat, "%pI4_%u_stat", &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 %pI4 - no free adresses in prefix %s\n",
|
||||
&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 %pI4 -> %pI4\n",
|
||||
&prenat_ip_prev, &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 %pI4 -> %pI4\n", &prenat_ip,
|
||||
&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 %pI4 -> %pI4\n",
|
||||
&e->prenat_addr,
|
||||
&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, "%pI4_%u", &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, "%pI4_%u_stat", &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, "%pI4 -> %pI4 --- ttl: %d lasthit: %lu\n",
|
||||
&e->prenat_addr, &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;
|
||||
|
||||
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);
|
||||
dnetmap_proc_net_exit(net);
|
||||
}
|
||||
|
||||
static struct pernet_operations dnetmap_net_ops = {
|
||||
.init = dnetmap_net_init,
|
||||
.exit = dnetmap_net_exit,
|
||||
.id = &dnetmap_net_id,
|
||||
.size = sizeof(struct dnetmap_net),
|
||||
};
|
||||
|
||||
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
16
extensions/xt_DNETMAP.h
Normal 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
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -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 */
|
||||
|
@@ -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
|
||||
|
@@ -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
143
geoip/xt_geoip_build
Executable 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
35
geoip/xt_geoip_build.1
Normal 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
21
geoip/xt_geoip_dl.1
Normal 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)
|
215
include/net/netfilter/nf_conntrack_tuple.h
Normal file
215
include/net/netfilter/nf_conntrack_tuple.h
Normal 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 */
|
93
include/net/netfilter/nf_nat.h
Normal file
93
include/net/netfilter/nf_nat.h
Normal 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
|
Reference in New Issue
Block a user