Merge branch 'master' of git://1984.lsi.us.es/nf-next
Pablo Neira Ayuso says: ==================== This patchset contains updates for your net-next tree, they are: * Mostly fixes for the recently pushed IPv6 NAT support: - Fix crash while removing nf_nat modules from Patrick McHardy. - Fix unbalanced rcu_read_unlock from Ulrich Weber. - Merge NETMAP and REDIRECT into one single xt_target module, from Jan Engelhardt. - Fix Kconfig for IPv6 NAT, which allows inconsistent configurations, from myself. * Updates for ipset, all of the from Jozsef Kadlecsik: - Add the new "nomatch" option to obtain reverse set matching. - Support for /0 CIDR in hash:net,iface set type. - One non-critical fix for a rare crash due to pass really wrong configuration parameters. - Coding style cleanups. - Sparse fixes. - Add set revision supported via modinfo.i * One extension for the xt_time match, to support matching during the transition between two days with one single rule, from Florian Westphal. * Fix maximum packet length supported by nfnetlink_queue and add NFQA_CAP_LEN attribute, from myself. You can notice that this batch contains a couple of fixes that may go to 3.6-rc but I don't consider them critical to push them: * The ipset fix for the /0 cidr case, which is triggered with one inconsistent command line invocation of ipset. * The nfnetlink_queue maximum packet length supported since it requires the new NFQA_CAP_LEN attribute to provide a full workaround for the described problem. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
ae4735166e
@ -190,6 +190,7 @@ enum ip_set_dim {
|
||||
* If changed, new revision of iptables match/target is required.
|
||||
*/
|
||||
IPSET_DIM_MAX = 6,
|
||||
IPSET_BIT_RETURN_NOMATCH = 7,
|
||||
};
|
||||
|
||||
/* Option flags for kernel operations */
|
||||
@ -198,6 +199,7 @@ enum ip_set_kopt {
|
||||
IPSET_DIM_ONE_SRC = (1 << IPSET_DIM_ONE),
|
||||
IPSET_DIM_TWO_SRC = (1 << IPSET_DIM_TWO),
|
||||
IPSET_DIM_THREE_SRC = (1 << IPSET_DIM_THREE),
|
||||
IPSET_RETURN_NOMATCH = (1 << IPSET_BIT_RETURN_NOMATCH),
|
||||
};
|
||||
|
||||
#ifdef __KERNEL__
|
||||
@ -206,9 +208,15 @@ enum ip_set_kopt {
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#include <linux/stringify.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <net/netlink.h>
|
||||
|
||||
#define _IP_SET_MODULE_DESC(a, b, c) \
|
||||
MODULE_DESCRIPTION(a " type of IP sets, revisions " b "-" c)
|
||||
#define IP_SET_MODULE_DESC(a, b, c) \
|
||||
_IP_SET_MODULE_DESC(a, __stringify(b), __stringify(c))
|
||||
|
||||
/* Set features */
|
||||
enum ip_set_feature {
|
||||
IPSET_TYPE_IP_FLAG = 0,
|
||||
@ -223,6 +231,8 @@ enum ip_set_feature {
|
||||
IPSET_TYPE_NAME = (1 << IPSET_TYPE_NAME_FLAG),
|
||||
IPSET_TYPE_IFACE_FLAG = 5,
|
||||
IPSET_TYPE_IFACE = (1 << IPSET_TYPE_IFACE_FLAG),
|
||||
IPSET_TYPE_NOMATCH_FLAG = 6,
|
||||
IPSET_TYPE_NOMATCH = (1 << IPSET_TYPE_NOMATCH_FLAG),
|
||||
/* Strictly speaking not a feature, but a flag for dumping:
|
||||
* this settype must be dumped last */
|
||||
IPSET_DUMP_LAST_FLAG = 7,
|
||||
@ -249,7 +259,7 @@ struct ip_set_type_variant {
|
||||
* returns negative error code,
|
||||
* zero for no match/success to add/delete
|
||||
* positive for matching element */
|
||||
int (*kadt)(struct ip_set *set, const struct sk_buff * skb,
|
||||
int (*kadt)(struct ip_set *set, const struct sk_buff *skb,
|
||||
const struct xt_action_param *par,
|
||||
enum ipset_adt adt, const struct ip_set_adt_opt *opt);
|
||||
|
||||
@ -424,7 +434,8 @@ static inline int nla_put_ipaddr4(struct sk_buff *skb, int type, __be32 ipaddr)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int nla_put_ipaddr6(struct sk_buff *skb, int type, const struct in6_addr *ipaddrptr)
|
||||
static inline int nla_put_ipaddr6(struct sk_buff *skb, int type,
|
||||
const struct in6_addr *ipaddrptr)
|
||||
{
|
||||
struct nlattr *__nested = ipset_nest_start(skb, type);
|
||||
int ret;
|
||||
|
@ -137,50 +137,59 @@ htable_bits(u32 hashsize)
|
||||
#endif
|
||||
|
||||
#define SET_HOST_MASK(family) (family == AF_INET ? 32 : 128)
|
||||
#ifdef IP_SET_HASH_WITH_MULTI
|
||||
#define NETS_LENGTH(family) (SET_HOST_MASK(family) + 1)
|
||||
#else
|
||||
#define NETS_LENGTH(family) SET_HOST_MASK(family)
|
||||
#endif
|
||||
|
||||
/* Network cidr size book keeping when the hash stores different
|
||||
* sized networks */
|
||||
static void
|
||||
add_cidr(struct ip_set_hash *h, u8 cidr, u8 host_mask)
|
||||
add_cidr(struct ip_set_hash *h, u8 cidr, u8 nets_length)
|
||||
{
|
||||
u8 i;
|
||||
int i, j;
|
||||
|
||||
++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;
|
||||
|
||||
/* New cidr size */
|
||||
for (i = 0; i < host_mask && h->nets[i].cidr; i++) {
|
||||
/* Add in increasing prefix order, so larger cidr first */
|
||||
if (h->nets[i].cidr < cidr)
|
||||
swap(h->nets[i].cidr, cidr);
|
||||
/* Add in increasing prefix order, so larger cidr first */
|
||||
for (i = 0, j = -1; i < nets_length && h->nets[i].nets; i++) {
|
||||
if (j != -1)
|
||||
continue;
|
||||
else if (h->nets[i].cidr < cidr)
|
||||
j = i;
|
||||
else if (h->nets[i].cidr == cidr) {
|
||||
h->nets[i].nets++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (i < host_mask)
|
||||
h->nets[i].cidr = cidr;
|
||||
if (j != -1) {
|
||||
for (; i > j; i--) {
|
||||
h->nets[i].cidr = h->nets[i - 1].cidr;
|
||||
h->nets[i].nets = h->nets[i - 1].nets;
|
||||
}
|
||||
}
|
||||
h->nets[i].cidr = cidr;
|
||||
h->nets[i].nets = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
del_cidr(struct ip_set_hash *h, u8 cidr, u8 host_mask)
|
||||
del_cidr(struct ip_set_hash *h, u8 cidr, u8 nets_length)
|
||||
{
|
||||
u8 i;
|
||||
u8 i, j;
|
||||
|
||||
--h->nets[cidr-1].nets;
|
||||
for (i = 0; i < nets_length - 1 && h->nets[i].cidr != cidr; i++)
|
||||
;
|
||||
h->nets[i].nets--;
|
||||
|
||||
pr_debug("del_cidr deleted %u: %u\n", cidr, h->nets[cidr-1].nets);
|
||||
|
||||
if (h->nets[cidr-1].nets != 0)
|
||||
if (h->nets[i].nets != 0)
|
||||
return;
|
||||
|
||||
/* All entries with this cidr size deleted, so cleanup h->cidr[] */
|
||||
for (i = 0; i < host_mask - 1 && h->nets[i].cidr; i++) {
|
||||
if (h->nets[i].cidr == cidr)
|
||||
h->nets[i].cidr = cidr = h->nets[i+1].cidr;
|
||||
for (j = i; j < nets_length - 1 && h->nets[j].nets; j++) {
|
||||
h->nets[j].cidr = h->nets[j + 1].cidr;
|
||||
h->nets[j].nets = h->nets[j + 1].nets;
|
||||
}
|
||||
h->nets[i - 1].cidr = 0;
|
||||
}
|
||||
#else
|
||||
#define NETS_LENGTH(family) 0
|
||||
#endif
|
||||
|
||||
/* Destroy the hashtable part of the set */
|
||||
@ -202,14 +211,14 @@ ahash_destroy(struct htable *t)
|
||||
|
||||
/* Calculate the actual memory size of the set data */
|
||||
static size_t
|
||||
ahash_memsize(const struct ip_set_hash *h, size_t dsize, u8 host_mask)
|
||||
ahash_memsize(const struct ip_set_hash *h, size_t dsize, u8 nets_length)
|
||||
{
|
||||
u32 i;
|
||||
struct htable *t = h->table;
|
||||
size_t memsize = sizeof(*h)
|
||||
+ sizeof(*t)
|
||||
#ifdef IP_SET_HASH_WITH_NETS
|
||||
+ sizeof(struct ip_set_hash_nets) * host_mask
|
||||
+ sizeof(struct ip_set_hash_nets) * nets_length
|
||||
#endif
|
||||
+ jhash_size(t->htable_bits) * sizeof(struct hbucket);
|
||||
|
||||
@ -238,7 +247,7 @@ ip_set_hash_flush(struct ip_set *set)
|
||||
}
|
||||
#ifdef IP_SET_HASH_WITH_NETS
|
||||
memset(h->nets, 0, sizeof(struct ip_set_hash_nets)
|
||||
* SET_HOST_MASK(set->family));
|
||||
* NETS_LENGTH(set->family));
|
||||
#endif
|
||||
h->elements = 0;
|
||||
}
|
||||
@ -271,9 +280,6 @@ ip_set_hash_destroy(struct ip_set *set)
|
||||
(jhash2((u32 *)(data), HKEY_DATALEN/sizeof(u32), initval) \
|
||||
& jhash_mask(htable_bits))
|
||||
|
||||
#define CONCAT(a, b, c) a##b##c
|
||||
#define TOKEN(a, b, c) CONCAT(a, b, c)
|
||||
|
||||
/* Type/family dependent function prototypes */
|
||||
|
||||
#define type_pf_data_equal TOKEN(TYPE, PF, _data_equal)
|
||||
@ -478,7 +484,7 @@ type_pf_add(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
}
|
||||
|
||||
#ifdef IP_SET_HASH_WITH_NETS
|
||||
add_cidr(h, CIDR(d->cidr), HOST_MASK);
|
||||
add_cidr(h, CIDR(d->cidr), NETS_LENGTH(set->family));
|
||||
#endif
|
||||
h->elements++;
|
||||
out:
|
||||
@ -513,7 +519,7 @@ type_pf_del(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
n->pos--;
|
||||
h->elements--;
|
||||
#ifdef IP_SET_HASH_WITH_NETS
|
||||
del_cidr(h, CIDR(d->cidr), HOST_MASK);
|
||||
del_cidr(h, CIDR(d->cidr), NETS_LENGTH(set->family));
|
||||
#endif
|
||||
if (n->pos + AHASH_INIT_SIZE < n->size) {
|
||||
void *tmp = kzalloc((n->size - AHASH_INIT_SIZE)
|
||||
@ -546,10 +552,10 @@ type_pf_test_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout)
|
||||
const struct type_pf_elem *data;
|
||||
int i, j = 0;
|
||||
u32 key, multi = 0;
|
||||
u8 host_mask = SET_HOST_MASK(set->family);
|
||||
u8 nets_length = NETS_LENGTH(set->family);
|
||||
|
||||
pr_debug("test by nets\n");
|
||||
for (; j < host_mask && h->nets[j].cidr && !multi; j++) {
|
||||
for (; j < nets_length && h->nets[j].nets && !multi; j++) {
|
||||
type_pf_data_netmask(d, h->nets[j].cidr);
|
||||
key = HKEY(d, h->initval, t->htable_bits);
|
||||
n = hbucket(t, key);
|
||||
@ -604,7 +610,7 @@ type_pf_head(struct ip_set *set, struct sk_buff *skb)
|
||||
memsize = ahash_memsize(h, with_timeout(h->timeout)
|
||||
? sizeof(struct type_pf_telem)
|
||||
: sizeof(struct type_pf_elem),
|
||||
set->family == AF_INET ? 32 : 128);
|
||||
NETS_LENGTH(set->family));
|
||||
read_unlock_bh(&set->lock);
|
||||
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
@ -690,7 +696,7 @@ nla_put_failure:
|
||||
}
|
||||
|
||||
static int
|
||||
type_pf_kadt(struct ip_set *set, const struct sk_buff * skb,
|
||||
type_pf_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
const struct xt_action_param *par,
|
||||
enum ipset_adt adt, const struct ip_set_adt_opt *opt);
|
||||
static int
|
||||
@ -783,7 +789,7 @@ type_pf_elem_tadd(struct hbucket *n, const struct type_pf_elem *value,
|
||||
|
||||
/* Delete expired elements from the hashtable */
|
||||
static void
|
||||
type_pf_expire(struct ip_set_hash *h)
|
||||
type_pf_expire(struct ip_set_hash *h, u8 nets_length)
|
||||
{
|
||||
struct htable *t = h->table;
|
||||
struct hbucket *n;
|
||||
@ -798,7 +804,7 @@ type_pf_expire(struct ip_set_hash *h)
|
||||
if (type_pf_data_expired(data)) {
|
||||
pr_debug("expired %u/%u\n", i, j);
|
||||
#ifdef IP_SET_HASH_WITH_NETS
|
||||
del_cidr(h, CIDR(data->cidr), HOST_MASK);
|
||||
del_cidr(h, CIDR(data->cidr), nets_length);
|
||||
#endif
|
||||
if (j != n->pos - 1)
|
||||
/* Not last one */
|
||||
@ -839,7 +845,7 @@ type_pf_tresize(struct ip_set *set, bool retried)
|
||||
if (!retried) {
|
||||
i = h->elements;
|
||||
write_lock_bh(&set->lock);
|
||||
type_pf_expire(set->data);
|
||||
type_pf_expire(set->data, NETS_LENGTH(set->family));
|
||||
write_unlock_bh(&set->lock);
|
||||
if (h->elements < i)
|
||||
return 0;
|
||||
@ -904,7 +910,7 @@ type_pf_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
|
||||
if (h->elements >= h->maxelem)
|
||||
/* FIXME: when set is full, we slow down here */
|
||||
type_pf_expire(h);
|
||||
type_pf_expire(h, NETS_LENGTH(set->family));
|
||||
if (h->elements >= h->maxelem) {
|
||||
if (net_ratelimit())
|
||||
pr_warning("Set %s is full, maxelem %u reached\n",
|
||||
@ -933,8 +939,8 @@ type_pf_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
if (j != AHASH_MAX(h) + 1) {
|
||||
data = ahash_tdata(n, j);
|
||||
#ifdef IP_SET_HASH_WITH_NETS
|
||||
del_cidr(h, CIDR(data->cidr), HOST_MASK);
|
||||
add_cidr(h, CIDR(d->cidr), HOST_MASK);
|
||||
del_cidr(h, CIDR(data->cidr), NETS_LENGTH(set->family));
|
||||
add_cidr(h, CIDR(d->cidr), NETS_LENGTH(set->family));
|
||||
#endif
|
||||
type_pf_data_copy(data, d);
|
||||
type_pf_data_timeout_set(data, timeout);
|
||||
@ -952,7 +958,7 @@ type_pf_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
}
|
||||
|
||||
#ifdef IP_SET_HASH_WITH_NETS
|
||||
add_cidr(h, CIDR(d->cidr), HOST_MASK);
|
||||
add_cidr(h, CIDR(d->cidr), NETS_LENGTH(set->family));
|
||||
#endif
|
||||
h->elements++;
|
||||
out:
|
||||
@ -986,7 +992,7 @@ type_pf_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
n->pos--;
|
||||
h->elements--;
|
||||
#ifdef IP_SET_HASH_WITH_NETS
|
||||
del_cidr(h, CIDR(d->cidr), HOST_MASK);
|
||||
del_cidr(h, CIDR(d->cidr), NETS_LENGTH(set->family));
|
||||
#endif
|
||||
if (n->pos + AHASH_INIT_SIZE < n->size) {
|
||||
void *tmp = kzalloc((n->size - AHASH_INIT_SIZE)
|
||||
@ -1016,9 +1022,9 @@ type_pf_ttest_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout)
|
||||
struct hbucket *n;
|
||||
int i, j = 0;
|
||||
u32 key, multi = 0;
|
||||
u8 host_mask = SET_HOST_MASK(set->family);
|
||||
u8 nets_length = NETS_LENGTH(set->family);
|
||||
|
||||
for (; j < host_mask && h->nets[j].cidr && !multi; j++) {
|
||||
for (; j < nets_length && h->nets[j].nets && !multi; j++) {
|
||||
type_pf_data_netmask(d, h->nets[j].cidr);
|
||||
key = HKEY(d, h->initval, t->htable_bits);
|
||||
n = hbucket(t, key);
|
||||
@ -1147,7 +1153,7 @@ type_pf_gc(unsigned long ul_set)
|
||||
|
||||
pr_debug("called\n");
|
||||
write_lock_bh(&set->lock);
|
||||
type_pf_expire(h);
|
||||
type_pf_expire(h, NETS_LENGTH(set->family));
|
||||
write_unlock_bh(&set->lock);
|
||||
|
||||
h->gc.expires = jiffies + IPSET_GC_PERIOD(h->timeout) * HZ;
|
||||
|
@ -18,13 +18,17 @@ enum nf_ct_ftp_type {
|
||||
|
||||
#define FTP_PORT 21
|
||||
|
||||
#define NF_CT_FTP_SEQ_PICKUP (1 << 0)
|
||||
|
||||
#define NUM_SEQ_TO_REMEMBER 2
|
||||
/* This structure exists only once per master */
|
||||
struct nf_ct_ftp_master {
|
||||
/* Valid seq positions for cmd matching after newline */
|
||||
u_int32_t seq_aft_nl[IP_CT_DIR_MAX][NUM_SEQ_TO_REMEMBER];
|
||||
/* 0 means seq_match_aft_nl not set */
|
||||
int seq_aft_nl_num[IP_CT_DIR_MAX];
|
||||
u_int16_t seq_aft_nl_num[IP_CT_DIR_MAX];
|
||||
/* pickup sequence tracking, useful for conntrackd */
|
||||
u_int16_t flags[IP_CT_DIR_MAX];
|
||||
};
|
||||
|
||||
struct nf_conntrack_expect;
|
||||
|
@ -44,6 +44,7 @@ enum nfqnl_attr_type {
|
||||
NFQA_PAYLOAD, /* opaque data payload */
|
||||
NFQA_CT, /* nf_conntrack_netlink.h */
|
||||
NFQA_CT_INFO, /* enum ip_conntrack_info */
|
||||
NFQA_CAP_LEN, /* __u32 length of captured packet */
|
||||
|
||||
__NFQA_MAX
|
||||
};
|
||||
|
@ -17,6 +17,9 @@ enum {
|
||||
/* Match against local time (instead of UTC) */
|
||||
XT_TIME_LOCAL_TZ = 1 << 0,
|
||||
|
||||
/* treat timestart > timestop (e.g. 23:00-01:00) as single period */
|
||||
XT_TIME_CONTIGUOUS = 1 << 1,
|
||||
|
||||
/* Shortcuts */
|
||||
XT_TIME_ALL_MONTHDAYS = 0xFFFFFFFE,
|
||||
XT_TIME_ALL_WEEKDAYS = 0xFE,
|
||||
@ -24,4 +27,6 @@ enum {
|
||||
XT_TIME_MAX_DAYTIME = 24 * 60 * 60 - 1,
|
||||
};
|
||||
|
||||
#define XT_TIME_ALL_FLAGS (XT_TIME_LOCAL_TZ|XT_TIME_CONTIGUOUS)
|
||||
|
||||
#endif /* _XT_TIME_H */
|
||||
|
@ -172,23 +172,20 @@ config IP_NF_TARGET_MASQUERADE
|
||||
config IP_NF_TARGET_NETMAP
|
||||
tristate "NETMAP target support"
|
||||
depends on NETFILTER_ADVANCED
|
||||
help
|
||||
NETMAP is an implementation of static 1:1 NAT mapping of network
|
||||
addresses. It maps the network address part, while keeping the host
|
||||
address part intact.
|
||||
|
||||
To compile it as a module, choose M here. If unsure, say N.
|
||||
select NETFILTER_XT_TARGET_NETMAP
|
||||
---help---
|
||||
This is a backwards-compat option for the user's convenience
|
||||
(e.g. when running oldconfig). It selects
|
||||
CONFIG_NETFILTER_XT_TARGET_NETMAP.
|
||||
|
||||
config IP_NF_TARGET_REDIRECT
|
||||
tristate "REDIRECT target support"
|
||||
depends on NETFILTER_ADVANCED
|
||||
help
|
||||
REDIRECT is a special case of NAT: all incoming connections are
|
||||
mapped onto the incoming interface's address, causing the packets to
|
||||
come to the local machine instead of passing through. This is
|
||||
useful for transparent proxies.
|
||||
|
||||
To compile it as a module, choose M here. If unsure, say N.
|
||||
select NETFILTER_XT_TARGET_REDIRECT
|
||||
---help---
|
||||
This is a backwards-compat option for the user's convenience
|
||||
(e.g. when running oldconfig). It selects
|
||||
CONFIG_NETFILTER_XT_TARGET_REDIRECT.
|
||||
|
||||
endif
|
||||
|
||||
|
@ -45,8 +45,6 @@ obj-$(CONFIG_IP_NF_MATCH_RPFILTER) += ipt_rpfilter.o
|
||||
obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o
|
||||
obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
|
||||
obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
|
||||
obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
|
||||
obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
|
||||
obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
|
||||
obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
|
||||
|
||||
|
@ -1,101 +0,0 @@
|
||||
/* NETMAP - static NAT mapping of IP network addresses (1:1).
|
||||
* The mapping can be applied to source (POSTROUTING),
|
||||
* destination (PREROUTING), or both (with separate rules).
|
||||
*/
|
||||
|
||||
/* (C) 2000-2001 Svenning Soerensen <svenning@post5.tele.dk>
|
||||
*
|
||||
* 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.h>
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Svenning Soerensen <svenning@post5.tele.dk>");
|
||||
MODULE_DESCRIPTION("Xtables: 1:1 NAT mapping of IPv4 subnets");
|
||||
|
||||
static int netmap_tg_check(const struct xt_tgchk_param *par)
|
||||
{
|
||||
const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
|
||||
|
||||
if (!(mr->range[0].flags & NF_NAT_RANGE_MAP_IPS)) {
|
||||
pr_debug("bad MAP_IPS.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (mr->rangesize != 1) {
|
||||
pr_debug("bad rangesize %u.\n", mr->rangesize);
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
netmap_tg(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
{
|
||||
struct nf_conn *ct;
|
||||
enum ip_conntrack_info ctinfo;
|
||||
__be32 new_ip, netmask;
|
||||
const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
|
||||
struct nf_nat_range newrange;
|
||||
|
||||
NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING ||
|
||||
par->hooknum == NF_INET_POST_ROUTING ||
|
||||
par->hooknum == NF_INET_LOCAL_OUT ||
|
||||
par->hooknum == NF_INET_LOCAL_IN);
|
||||
ct = nf_ct_get(skb, &ctinfo);
|
||||
|
||||
netmask = ~(mr->range[0].min_ip ^ mr->range[0].max_ip);
|
||||
|
||||
if (par->hooknum == NF_INET_PRE_ROUTING ||
|
||||
par->hooknum == NF_INET_LOCAL_OUT)
|
||||
new_ip = ip_hdr(skb)->daddr & ~netmask;
|
||||
else
|
||||
new_ip = ip_hdr(skb)->saddr & ~netmask;
|
||||
new_ip |= mr->range[0].min_ip & netmask;
|
||||
|
||||
memset(&newrange.min_addr, 0, sizeof(newrange.min_addr));
|
||||
memset(&newrange.max_addr, 0, sizeof(newrange.max_addr));
|
||||
newrange.flags = mr->range[0].flags | NF_NAT_RANGE_MAP_IPS;
|
||||
newrange.min_addr.ip = new_ip;
|
||||
newrange.max_addr.ip = new_ip;
|
||||
newrange.min_proto = mr->range[0].min;
|
||||
newrange.max_proto = mr->range[0].max;
|
||||
|
||||
/* Hand modified range to generic setup. */
|
||||
return nf_nat_setup_info(ct, &newrange, HOOK2MANIP(par->hooknum));
|
||||
}
|
||||
|
||||
static struct xt_target netmap_tg_reg __read_mostly = {
|
||||
.name = "NETMAP",
|
||||
.family = NFPROTO_IPV4,
|
||||
.target = netmap_tg,
|
||||
.targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat),
|
||||
.table = "nat",
|
||||
.hooks = (1 << NF_INET_PRE_ROUTING) |
|
||||
(1 << NF_INET_POST_ROUTING) |
|
||||
(1 << NF_INET_LOCAL_OUT) |
|
||||
(1 << NF_INET_LOCAL_IN),
|
||||
.checkentry = netmap_tg_check,
|
||||
.me = THIS_MODULE
|
||||
};
|
||||
|
||||
static int __init netmap_tg_init(void)
|
||||
{
|
||||
return xt_register_target(&netmap_tg_reg);
|
||||
}
|
||||
|
||||
static void __exit netmap_tg_exit(void)
|
||||
{
|
||||
xt_unregister_target(&netmap_tg_reg);
|
||||
}
|
||||
|
||||
module_init(netmap_tg_init);
|
||||
module_exit(netmap_tg_exit);
|
@ -1,113 +0,0 @@
|
||||
/* Redirect. Simple mapping which alters dst to a local IP address. */
|
||||
/* (C) 1999-2001 Paul `Rusty' Russell
|
||||
* (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
|
||||
*
|
||||
* 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/types.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/inetdevice.h>
|
||||
#include <net/protocol.h>
|
||||
#include <net/checksum.h>
|
||||
#include <linux/netfilter_ipv4.h>
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#include <net/netfilter/nf_nat.h>
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
|
||||
MODULE_DESCRIPTION("Xtables: Connection redirection to localhost");
|
||||
|
||||
/* FIXME: Take multiple ranges --RR */
|
||||
static int redirect_tg_check(const struct xt_tgchk_param *par)
|
||||
{
|
||||
const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
|
||||
|
||||
if (mr->range[0].flags & NF_NAT_RANGE_MAP_IPS) {
|
||||
pr_debug("bad MAP_IPS.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (mr->rangesize != 1) {
|
||||
pr_debug("bad rangesize %u.\n", mr->rangesize);
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
redirect_tg(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
{
|
||||
struct nf_conn *ct;
|
||||
enum ip_conntrack_info ctinfo;
|
||||
__be32 newdst;
|
||||
const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
|
||||
struct nf_nat_range newrange;
|
||||
|
||||
NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING ||
|
||||
par->hooknum == NF_INET_LOCAL_OUT);
|
||||
|
||||
ct = nf_ct_get(skb, &ctinfo);
|
||||
NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED));
|
||||
|
||||
/* Local packets: make them go to loopback */
|
||||
if (par->hooknum == NF_INET_LOCAL_OUT)
|
||||
newdst = htonl(0x7F000001);
|
||||
else {
|
||||
struct in_device *indev;
|
||||
struct in_ifaddr *ifa;
|
||||
|
||||
newdst = 0;
|
||||
|
||||
rcu_read_lock();
|
||||
indev = __in_dev_get_rcu(skb->dev);
|
||||
if (indev && (ifa = indev->ifa_list))
|
||||
newdst = ifa->ifa_local;
|
||||
rcu_read_unlock();
|
||||
|
||||
if (!newdst)
|
||||
return NF_DROP;
|
||||
}
|
||||
|
||||
/* Transfer from original range. */
|
||||
memset(&newrange.min_addr, 0, sizeof(newrange.min_addr));
|
||||
memset(&newrange.max_addr, 0, sizeof(newrange.max_addr));
|
||||
newrange.flags = mr->range[0].flags | NF_NAT_RANGE_MAP_IPS;
|
||||
newrange.min_addr.ip = newdst;
|
||||
newrange.max_addr.ip = newdst;
|
||||
newrange.min_proto = mr->range[0].min;
|
||||
newrange.max_proto = mr->range[0].max;
|
||||
|
||||
/* Hand modified range to generic setup. */
|
||||
return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST);
|
||||
}
|
||||
|
||||
static struct xt_target redirect_tg_reg __read_mostly = {
|
||||
.name = "REDIRECT",
|
||||
.family = NFPROTO_IPV4,
|
||||
.target = redirect_tg,
|
||||
.targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat),
|
||||
.table = "nat",
|
||||
.hooks = (1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT),
|
||||
.checkentry = redirect_tg_check,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init redirect_tg_init(void)
|
||||
{
|
||||
return xt_register_target(&redirect_tg_reg);
|
||||
}
|
||||
|
||||
static void __exit redirect_tg_exit(void)
|
||||
{
|
||||
xt_unregister_target(&redirect_tg_reg);
|
||||
}
|
||||
|
||||
module_init(redirect_tg_init);
|
||||
module_exit(redirect_tg_exit);
|
@ -25,18 +25,6 @@ config NF_CONNTRACK_IPV6
|
||||
|
||||
To compile it as a module, choose M here. If unsure, say N.
|
||||
|
||||
config NF_NAT_IPV6
|
||||
tristate "IPv6 NAT"
|
||||
depends on NF_CONNTRACK_IPV6
|
||||
depends on NETFILTER_ADVANCED
|
||||
select NF_NAT
|
||||
help
|
||||
The IPv6 NAT option allows masquerading, port forwarding and other
|
||||
forms of full Network Address Port Translation. It is controlled by
|
||||
the `nat' table in ip6tables, see the man page for ip6tables(8).
|
||||
|
||||
To compile it as a module, choose M here. If unsure, say N.
|
||||
|
||||
config IP6_NF_IPTABLES
|
||||
tristate "IP6 tables support (required for filtering)"
|
||||
depends on INET && IPV6
|
||||
@ -144,48 +132,6 @@ config IP6_NF_TARGET_HL
|
||||
(e.g. when running oldconfig). It selects
|
||||
CONFIG_NETFILTER_XT_TARGET_HL.
|
||||
|
||||
config IP6_NF_TARGET_MASQUERADE
|
||||
tristate "MASQUERADE target support"
|
||||
depends on NF_NAT_IPV6
|
||||
help
|
||||
Masquerading is a special case of NAT: all outgoing connections are
|
||||
changed to seem to come from a particular interface's address, and
|
||||
if the interface goes down, those connections are lost. This is
|
||||
only useful for dialup accounts with dynamic IP address (ie. your IP
|
||||
address will be different on next dialup).
|
||||
|
||||
To compile it as a module, choose M here. If unsure, say N.
|
||||
|
||||
config IP6_NF_TARGET_NETMAP
|
||||
tristate "NETMAP target support"
|
||||
depends on NF_NAT_IPV6
|
||||
help
|
||||
NETMAP is an implementation of static 1:1 NAT mapping of network
|
||||
addresses. It maps the network address part, while keeping the host
|
||||
address part intact.
|
||||
|
||||
To compile it as a module, choose M here. If unsure, say N.
|
||||
|
||||
config IP6_NF_TARGET_REDIRECT
|
||||
tristate "REDIRECT target support"
|
||||
depends on NF_NAT_IPV6
|
||||
help
|
||||
REDIRECT is a special case of NAT: all incoming connections are
|
||||
mapped onto the incoming interface's address, causing the packets to
|
||||
come to the local machine instead of passing through. This is
|
||||
useful for transparent proxies.
|
||||
|
||||
To compile it as a module, choose M here. If unsure, say N.
|
||||
|
||||
config IP6_NF_TARGET_NPT
|
||||
tristate "NPT (Network Prefix translation) target support"
|
||||
depends on NETFILTER_ADVANCED
|
||||
help
|
||||
This option adds the `SNPT' and `DNPT' target, which perform
|
||||
stateless IPv6-to-IPv6 Network Prefix Translation per RFC 6296.
|
||||
|
||||
To compile it as a module, choose M here. If unsure, say N.
|
||||
|
||||
config IP6_NF_FILTER
|
||||
tristate "Packet filtering"
|
||||
default m if NETFILTER_ADVANCED=n
|
||||
@ -235,9 +181,44 @@ config IP6_NF_SECURITY
|
||||
help
|
||||
This option adds a `security' table to iptables, for use
|
||||
with Mandatory Access Control (MAC) policy.
|
||||
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config NF_NAT_IPV6
|
||||
tristate "IPv6 NAT"
|
||||
depends on NF_CONNTRACK_IPV6
|
||||
depends on NETFILTER_ADVANCED
|
||||
select NF_NAT
|
||||
help
|
||||
The IPv6 NAT option allows masquerading, port forwarding and other
|
||||
forms of full Network Address Port Translation. It is controlled by
|
||||
the `nat' table in ip6tables, see the man page for ip6tables(8).
|
||||
|
||||
To compile it as a module, choose M here. If unsure, say N.
|
||||
|
||||
if NF_NAT_IPV6
|
||||
|
||||
config IP6_NF_TARGET_MASQUERADE
|
||||
tristate "MASQUERADE target support"
|
||||
help
|
||||
Masquerading is a special case of NAT: all outgoing connections are
|
||||
changed to seem to come from a particular interface's address, and
|
||||
if the interface goes down, those connections are lost. This is
|
||||
only useful for dialup accounts with dynamic IP address (ie. your IP
|
||||
address will be different on next dialup).
|
||||
|
||||
To compile it as a module, choose M here. If unsure, say N.
|
||||
|
||||
config IP6_NF_TARGET_NPT
|
||||
tristate "NPT (Network Prefix translation) target support"
|
||||
help
|
||||
This option adds the `SNPT' and `DNPT' target, which perform
|
||||
stateless IPv6-to-IPv6 Network Prefix Translation per RFC 6296.
|
||||
|
||||
To compile it as a module, choose M here. If unsure, say N.
|
||||
|
||||
endif # NF_NAT_IPV6
|
||||
|
||||
endif # IP6_NF_IPTABLES
|
||||
|
||||
endmenu
|
||||
|
@ -35,7 +35,5 @@ obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
|
||||
|
||||
# targets
|
||||
obj-$(CONFIG_IP6_NF_TARGET_MASQUERADE) += ip6t_MASQUERADE.o
|
||||
obj-$(CONFIG_IP6_NF_TARGET_NETMAP) += ip6t_NETMAP.o
|
||||
obj-$(CONFIG_IP6_NF_TARGET_NPT) += ip6t_NPT.o
|
||||
obj-$(CONFIG_IP6_NF_TARGET_REDIRECT) += ip6t_REDIRECT.o
|
||||
obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
|
||||
|
@ -1,94 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Patrick McHardy <kaber@trash.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.
|
||||
*
|
||||
* Based on Svenning Soerensen's IPv4 NETMAP target. Development of IPv6
|
||||
* NAT funded by Astaro.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netfilter_ipv6.h>
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#include <net/netfilter/nf_nat.h>
|
||||
|
||||
static unsigned int
|
||||
netmap_tg6(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
{
|
||||
const struct nf_nat_range *range = par->targinfo;
|
||||
struct nf_nat_range newrange;
|
||||
struct nf_conn *ct;
|
||||
enum ip_conntrack_info ctinfo;
|
||||
union nf_inet_addr new_addr, netmask;
|
||||
unsigned int i;
|
||||
|
||||
ct = nf_ct_get(skb, &ctinfo);
|
||||
for (i = 0; i < ARRAY_SIZE(range->min_addr.ip6); i++)
|
||||
netmask.ip6[i] = ~(range->min_addr.ip6[i] ^
|
||||
range->max_addr.ip6[i]);
|
||||
|
||||
if (par->hooknum == NF_INET_PRE_ROUTING ||
|
||||
par->hooknum == NF_INET_LOCAL_OUT)
|
||||
new_addr.in6 = ipv6_hdr(skb)->daddr;
|
||||
else
|
||||
new_addr.in6 = ipv6_hdr(skb)->saddr;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(new_addr.ip6); i++) {
|
||||
new_addr.ip6[i] &= ~netmask.ip6[i];
|
||||
new_addr.ip6[i] |= range->min_addr.ip6[i] &
|
||||
netmask.ip6[i];
|
||||
}
|
||||
|
||||
newrange.flags = range->flags | NF_NAT_RANGE_MAP_IPS;
|
||||
newrange.min_addr = new_addr;
|
||||
newrange.max_addr = new_addr;
|
||||
newrange.min_proto = range->min_proto;
|
||||
newrange.max_proto = range->max_proto;
|
||||
|
||||
return nf_nat_setup_info(ct, &newrange, HOOK2MANIP(par->hooknum));
|
||||
}
|
||||
|
||||
static int netmap_tg6_checkentry(const struct xt_tgchk_param *par)
|
||||
{
|
||||
const struct nf_nat_range *range = par->targinfo;
|
||||
|
||||
if (!(range->flags & NF_NAT_RANGE_MAP_IPS))
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct xt_target netmap_tg6_reg __read_mostly = {
|
||||
.name = "NETMAP",
|
||||
.family = NFPROTO_IPV6,
|
||||
.target = netmap_tg6,
|
||||
.targetsize = sizeof(struct nf_nat_range),
|
||||
.table = "nat",
|
||||
.hooks = (1 << NF_INET_PRE_ROUTING) |
|
||||
(1 << NF_INET_POST_ROUTING) |
|
||||
(1 << NF_INET_LOCAL_OUT) |
|
||||
(1 << NF_INET_LOCAL_IN),
|
||||
.checkentry = netmap_tg6_checkentry,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init netmap_tg6_init(void)
|
||||
{
|
||||
return xt_register_target(&netmap_tg6_reg);
|
||||
}
|
||||
|
||||
static void netmap_tg6_exit(void)
|
||||
{
|
||||
xt_unregister_target(&netmap_tg6_reg);
|
||||
}
|
||||
|
||||
module_init(netmap_tg6_init);
|
||||
module_exit(netmap_tg6_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Xtables: 1:1 NAT mapping of IPv6 subnets");
|
||||
MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
|
@ -1,98 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Patrick McHardy <kaber@trash.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.
|
||||
*
|
||||
* Based on Rusty Russell's IPv4 REDIRECT target. Development of IPv6
|
||||
* NAT funded by Astaro.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netfilter_ipv6.h>
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#include <net/addrconf.h>
|
||||
#include <net/netfilter/nf_nat.h>
|
||||
|
||||
static const struct in6_addr loopback_addr = IN6ADDR_LOOPBACK_INIT;
|
||||
|
||||
static unsigned int
|
||||
redirect_tg6(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
{
|
||||
const struct nf_nat_range *range = par->targinfo;
|
||||
struct nf_nat_range newrange;
|
||||
struct in6_addr newdst;
|
||||
enum ip_conntrack_info ctinfo;
|
||||
struct nf_conn *ct;
|
||||
|
||||
ct = nf_ct_get(skb, &ctinfo);
|
||||
if (par->hooknum == NF_INET_LOCAL_OUT)
|
||||
newdst = loopback_addr;
|
||||
else {
|
||||
struct inet6_dev *idev;
|
||||
struct inet6_ifaddr *ifa;
|
||||
bool addr = false;
|
||||
|
||||
rcu_read_lock();
|
||||
idev = __in6_dev_get(skb->dev);
|
||||
if (idev != NULL) {
|
||||
list_for_each_entry(ifa, &idev->addr_list, if_list) {
|
||||
newdst = ifa->addr;
|
||||
addr = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
if (!addr)
|
||||
return NF_DROP;
|
||||
}
|
||||
|
||||
newrange.flags = range->flags | NF_NAT_RANGE_MAP_IPS;
|
||||
newrange.min_addr.in6 = newdst;
|
||||
newrange.max_addr.in6 = newdst;
|
||||
newrange.min_proto = range->min_proto;
|
||||
newrange.max_proto = range->max_proto;
|
||||
|
||||
return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST);
|
||||
}
|
||||
|
||||
static int redirect_tg6_checkentry(const struct xt_tgchk_param *par)
|
||||
{
|
||||
const struct nf_nat_range *range = par->targinfo;
|
||||
|
||||
if (range->flags & NF_NAT_RANGE_MAP_IPS)
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct xt_target redirect_tg6_reg __read_mostly = {
|
||||
.name = "REDIRECT",
|
||||
.family = NFPROTO_IPV6,
|
||||
.checkentry = redirect_tg6_checkentry,
|
||||
.target = redirect_tg6,
|
||||
.targetsize = sizeof(struct nf_nat_range),
|
||||
.table = "nat",
|
||||
.hooks = (1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT),
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init redirect_tg6_init(void)
|
||||
{
|
||||
return xt_register_target(&redirect_tg6_reg);
|
||||
}
|
||||
|
||||
static void __exit redirect_tg6_exit(void)
|
||||
{
|
||||
xt_unregister_target(&redirect_tg6_reg);
|
||||
}
|
||||
|
||||
module_init(redirect_tg6_init);
|
||||
module_exit(redirect_tg6_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
|
||||
MODULE_DESCRIPTION("Xtables: Connection redirection to localhost");
|
@ -648,6 +648,16 @@ config NETFILTER_XT_TARGET_MARK
|
||||
(e.g. when running oldconfig). It selects
|
||||
CONFIG_NETFILTER_XT_MARK (combined mark/MARK module).
|
||||
|
||||
config NETFILTER_XT_TARGET_NETMAP
|
||||
tristate '"NETMAP" target support'
|
||||
depends on NF_NAT
|
||||
---help---
|
||||
NETMAP is an implementation of static 1:1 NAT mapping of network
|
||||
addresses. It maps the network address part, while keeping the host
|
||||
address part intact.
|
||||
|
||||
To compile it as a module, choose M here. If unsure, say N.
|
||||
|
||||
config NETFILTER_XT_TARGET_NFLOG
|
||||
tristate '"NFLOG" target support'
|
||||
default m if NETFILTER_ADVANCED=n
|
||||
@ -680,6 +690,17 @@ config NETFILTER_XT_TARGET_RATEEST
|
||||
|
||||
To compile it as a module, choose M here. If unsure, say N.
|
||||
|
||||
config NETFILTER_XT_TARGET_REDIRECT
|
||||
tristate "REDIRECT target support"
|
||||
depends on NF_NAT
|
||||
---help---
|
||||
REDIRECT is a special case of NAT: all incoming connections are
|
||||
mapped onto the incoming interface's address, causing the packets to
|
||||
come to the local machine instead of passing through. This is
|
||||
useful for transparent proxies.
|
||||
|
||||
To compile it as a module, choose M here. If unsure, say N.
|
||||
|
||||
config NETFILTER_XT_TARGET_TEE
|
||||
tristate '"TEE" - packet cloning to alternate destination'
|
||||
depends on NETFILTER_ADVANCED
|
||||
|
@ -83,9 +83,11 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o
|
||||
obj-$(CONFIG_NETFILTER_XT_TARGET_HMARK) += xt_HMARK.o
|
||||
obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o
|
||||
obj-$(CONFIG_NETFILTER_XT_TARGET_LOG) += xt_LOG.o
|
||||
obj-$(CONFIG_NETFILTER_XT_TARGET_NETMAP) += xt_NETMAP.o
|
||||
obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o
|
||||
obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
|
||||
obj-$(CONFIG_NETFILTER_XT_TARGET_RATEEST) += xt_RATEEST.o
|
||||
obj-$(CONFIG_NETFILTER_XT_TARGET_REDIRECT) += xt_REDIRECT.o
|
||||
obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o
|
||||
obj-$(CONFIG_NETFILTER_XT_TARGET_TPROXY) += xt_TPROXY.o
|
||||
obj-$(CONFIG_NETFILTER_XT_TARGET_TCPMSS) += xt_TCPMSS.o
|
||||
|
@ -27,9 +27,12 @@
|
||||
#define IP_SET_BITMAP_TIMEOUT
|
||||
#include <linux/netfilter/ipset/ip_set_timeout.h>
|
||||
|
||||
#define REVISION_MIN 0
|
||||
#define REVISION_MAX 0
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("bitmap:ip type of IP sets");
|
||||
IP_SET_MODULE_DESC("bitmap:ip", REVISION_MIN, REVISION_MAX);
|
||||
MODULE_ALIAS("ip_set_bitmap:ip");
|
||||
|
||||
/* Type structure */
|
||||
@ -284,7 +287,7 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
} else if (tb[IPSET_ATTR_CIDR]) {
|
||||
u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
|
||||
|
||||
if (cidr > 32)
|
||||
if (!cidr || cidr > 32)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
ip_set_mask_from_to(ip, ip_to, cidr);
|
||||
} else
|
||||
@ -454,7 +457,8 @@ static int
|
||||
bitmap_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
|
||||
{
|
||||
struct bitmap_ip *map;
|
||||
u32 first_ip, last_ip, hosts, elements;
|
||||
u32 first_ip, last_ip, hosts;
|
||||
u64 elements;
|
||||
u8 netmask = 32;
|
||||
int ret;
|
||||
|
||||
@ -497,7 +501,7 @@ bitmap_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
|
||||
|
||||
if (netmask == 32) {
|
||||
hosts = 1;
|
||||
elements = last_ip - first_ip + 1;
|
||||
elements = (u64)last_ip - first_ip + 1;
|
||||
} else {
|
||||
u8 mask_bits;
|
||||
u32 mask;
|
||||
@ -515,7 +519,8 @@ bitmap_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
|
||||
if (elements > IPSET_BITMAP_MAX_RANGE + 1)
|
||||
return -IPSET_ERR_BITMAP_RANGE_SIZE;
|
||||
|
||||
pr_debug("hosts %u, elements %u\n", hosts, elements);
|
||||
pr_debug("hosts %u, elements %llu\n",
|
||||
hosts, (unsigned long long)elements);
|
||||
|
||||
map = kzalloc(sizeof(*map), GFP_KERNEL);
|
||||
if (!map)
|
||||
@ -554,8 +559,8 @@ static struct ip_set_type bitmap_ip_type __read_mostly = {
|
||||
.features = IPSET_TYPE_IP,
|
||||
.dimension = IPSET_DIM_ONE,
|
||||
.family = NFPROTO_IPV4,
|
||||
.revision_min = 0,
|
||||
.revision_max = 0,
|
||||
.revision_min = REVISION_MIN,
|
||||
.revision_max = REVISION_MAX,
|
||||
.create = bitmap_ip_create,
|
||||
.create_policy = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
|
@ -26,9 +26,12 @@
|
||||
#include <linux/netfilter/ipset/ip_set_timeout.h>
|
||||
#include <linux/netfilter/ipset/ip_set_bitmap.h>
|
||||
|
||||
#define REVISION_MIN 0
|
||||
#define REVISION_MAX 0
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("bitmap:ip,mac type of IP sets");
|
||||
IP_SET_MODULE_DESC("bitmap:ip,mac", REVISION_MIN, REVISION_MAX);
|
||||
MODULE_ALIAS("ip_set_bitmap:ip,mac");
|
||||
|
||||
enum {
|
||||
@ -320,11 +323,11 @@ bitmap_ipmac_tlist(const struct ip_set *set,
|
||||
(elem->match == MAC_FILLED &&
|
||||
nla_put(skb, IPSET_ATTR_ETHER, ETH_ALEN,
|
||||
elem->ether)))
|
||||
goto nla_put_failure;
|
||||
goto nla_put_failure;
|
||||
timeout = elem->match == MAC_UNSET ? elem->timeout
|
||||
: ip_set_timeout_get(elem->timeout);
|
||||
if (nla_put_net32(skb, IPSET_ATTR_TIMEOUT, htonl(timeout)))
|
||||
goto nla_put_failure;
|
||||
goto nla_put_failure;
|
||||
ipset_nest_end(skb, nested);
|
||||
}
|
||||
ipset_nest_end(skb, atd);
|
||||
@ -557,7 +560,8 @@ static int
|
||||
bitmap_ipmac_create(struct ip_set *set, struct nlattr *tb[],
|
||||
u32 flags)
|
||||
{
|
||||
u32 first_ip, last_ip, elements;
|
||||
u32 first_ip, last_ip;
|
||||
u64 elements;
|
||||
struct bitmap_ipmac *map;
|
||||
int ret;
|
||||
|
||||
@ -588,7 +592,7 @@ bitmap_ipmac_create(struct ip_set *set, struct nlattr *tb[],
|
||||
} else
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
elements = last_ip - first_ip + 1;
|
||||
elements = (u64)last_ip - first_ip + 1;
|
||||
|
||||
if (elements > IPSET_BITMAP_MAX_RANGE + 1)
|
||||
return -IPSET_ERR_BITMAP_RANGE_SIZE;
|
||||
@ -629,8 +633,8 @@ static struct ip_set_type bitmap_ipmac_type = {
|
||||
.features = IPSET_TYPE_IP | IPSET_TYPE_MAC,
|
||||
.dimension = IPSET_DIM_TWO,
|
||||
.family = NFPROTO_IPV4,
|
||||
.revision_min = 0,
|
||||
.revision_max = 0,
|
||||
.revision_min = REVISION_MIN,
|
||||
.revision_max = REVISION_MAX,
|
||||
.create = bitmap_ipmac_create,
|
||||
.create_policy = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
|
@ -22,9 +22,12 @@
|
||||
#define IP_SET_BITMAP_TIMEOUT
|
||||
#include <linux/netfilter/ipset/ip_set_timeout.h>
|
||||
|
||||
#define REVISION_MIN 0
|
||||
#define REVISION_MAX 0
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("bitmap:port type of IP sets");
|
||||
IP_SET_MODULE_DESC("bitmap:port", REVISION_MIN, REVISION_MAX);
|
||||
MODULE_ALIAS("ip_set_bitmap:port");
|
||||
|
||||
/* Type structure */
|
||||
@ -487,8 +490,8 @@ static struct ip_set_type bitmap_port_type = {
|
||||
.features = IPSET_TYPE_PORT,
|
||||
.dimension = IPSET_DIM_ONE,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.revision_min = 0,
|
||||
.revision_max = 0,
|
||||
.revision_min = REVISION_MIN,
|
||||
.revision_max = REVISION_MAX,
|
||||
.create = bitmap_port_create,
|
||||
.create_policy = {
|
||||
[IPSET_ATTR_PORT] = { .type = NLA_U16 },
|
||||
|
@ -69,7 +69,8 @@ find_set_type(const char *name, u8 family, u8 revision)
|
||||
|
||||
list_for_each_entry_rcu(type, &ip_set_type_list, list)
|
||||
if (STREQ(type->name, name) &&
|
||||
(type->family == family || type->family == NFPROTO_UNSPEC) &&
|
||||
(type->family == family ||
|
||||
type->family == NFPROTO_UNSPEC) &&
|
||||
revision >= type->revision_min &&
|
||||
revision <= type->revision_max)
|
||||
return type;
|
||||
@ -149,7 +150,8 @@ __find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max,
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(type, &ip_set_type_list, list)
|
||||
if (STREQ(type->name, name) &&
|
||||
(type->family == family || type->family == NFPROTO_UNSPEC)) {
|
||||
(type->family == family ||
|
||||
type->family == NFPROTO_UNSPEC)) {
|
||||
found = true;
|
||||
if (type->revision_min < *min)
|
||||
*min = type->revision_min;
|
||||
@ -368,6 +370,12 @@ ip_set_test(ip_set_id_t index, const struct sk_buff *skb,
|
||||
set->variant->kadt(set, skb, par, IPSET_ADD, opt);
|
||||
write_unlock_bh(&set->lock);
|
||||
ret = 1;
|
||||
} else {
|
||||
/* --return-nomatch: invert matched element */
|
||||
if ((opt->flags & IPSET_RETURN_NOMATCH) &&
|
||||
(set->type->features & IPSET_TYPE_NOMATCH) &&
|
||||
(ret > 0 || ret == -ENOTEMPTY))
|
||||
ret = -ret;
|
||||
}
|
||||
|
||||
/* Convert error codes to nomatch */
|
||||
@ -721,7 +729,8 @@ ip_set_create(struct sock *ctnl, struct sk_buff *skb,
|
||||
* by the nfnl mutex. Find the first free index in ip_set_list
|
||||
* and check clashing.
|
||||
*/
|
||||
if ((ret = find_free_id(set->name, &index, &clash)) != 0) {
|
||||
ret = find_free_id(set->name, &index, &clash);
|
||||
if (ret != 0) {
|
||||
/* If this is the same set and requested, ignore error */
|
||||
if (ret == -EEXIST &&
|
||||
(flags & IPSET_FLAG_EXIST) &&
|
||||
|
@ -24,9 +24,12 @@
|
||||
#include <linux/netfilter/ipset/ip_set_timeout.h>
|
||||
#include <linux/netfilter/ipset/ip_set_hash.h>
|
||||
|
||||
#define REVISION_MIN 0
|
||||
#define REVISION_MAX 0
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("hash:ip type of IP sets");
|
||||
IP_SET_MODULE_DESC("hash:ip", REVISION_MIN, REVISION_MAX);
|
||||
MODULE_ALIAS("ip_set_hash:ip");
|
||||
|
||||
/* Type specific function prefix */
|
||||
@ -114,7 +117,7 @@ nla_put_failure:
|
||||
static inline void
|
||||
hash_ip4_data_next(struct ip_set_hash *h, const struct hash_ip4_elem *d)
|
||||
{
|
||||
h->next.ip = ntohl(d->ip);
|
||||
h->next.ip = d->ip;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -179,7 +182,7 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
} else if (tb[IPSET_ATTR_CIDR]) {
|
||||
u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
|
||||
|
||||
if (cidr > 32)
|
||||
if (!cidr || cidr > 32)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
ip_set_mask_from_to(ip, ip_to, cidr);
|
||||
} else
|
||||
@ -188,7 +191,7 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1);
|
||||
|
||||
if (retried)
|
||||
ip = h->next.ip;
|
||||
ip = ntohl(h->next.ip);
|
||||
for (; !before(ip_to, ip); ip += hosts) {
|
||||
nip = htonl(ip);
|
||||
if (nip == 0)
|
||||
@ -452,8 +455,8 @@ static struct ip_set_type hash_ip_type __read_mostly = {
|
||||
.features = IPSET_TYPE_IP,
|
||||
.dimension = IPSET_DIM_ONE,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.revision_min = 0,
|
||||
.revision_max = 0,
|
||||
.revision_min = REVISION_MIN,
|
||||
.revision_max = REVISION_MAX,
|
||||
.create = hash_ip_create,
|
||||
.create_policy = {
|
||||
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
|
||||
|
@ -25,9 +25,12 @@
|
||||
#include <linux/netfilter/ipset/ip_set_getport.h>
|
||||
#include <linux/netfilter/ipset/ip_set_hash.h>
|
||||
|
||||
#define REVISION_MIN 0
|
||||
#define REVISION_MAX 1 /* SCTP and UDPLITE support added */
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("hash:ip,port type of IP sets");
|
||||
IP_SET_MODULE_DESC("hash:ip,port", REVISION_MIN, REVISION_MAX);
|
||||
MODULE_ALIAS("ip_set_hash:ip,port");
|
||||
|
||||
/* Type specific function prefix */
|
||||
@ -130,8 +133,8 @@ static inline void
|
||||
hash_ipport4_data_next(struct ip_set_hash *h,
|
||||
const struct hash_ipport4_elem *d)
|
||||
{
|
||||
h->next.ip = ntohl(d->ip);
|
||||
h->next.port = ntohs(d->port);
|
||||
h->next.ip = d->ip;
|
||||
h->next.port = d->port;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -217,7 +220,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
} else if (tb[IPSET_ATTR_CIDR]) {
|
||||
u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
|
||||
|
||||
if (cidr > 32)
|
||||
if (!cidr || cidr > 32)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
ip_set_mask_from_to(ip, ip_to, cidr);
|
||||
} else
|
||||
@ -231,9 +234,10 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
}
|
||||
|
||||
if (retried)
|
||||
ip = h->next.ip;
|
||||
ip = ntohl(h->next.ip);
|
||||
for (; !before(ip_to, ip); ip++) {
|
||||
p = retried && ip == h->next.ip ? h->next.port : port;
|
||||
p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port)
|
||||
: port;
|
||||
for (; p <= port_to; p++) {
|
||||
data.ip = htonl(ip);
|
||||
data.port = htons(p);
|
||||
@ -349,7 +353,7 @@ static inline void
|
||||
hash_ipport6_data_next(struct ip_set_hash *h,
|
||||
const struct hash_ipport6_elem *d)
|
||||
{
|
||||
h->next.port = ntohs(d->port);
|
||||
h->next.port = d->port;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -431,7 +435,7 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
swap(port, port_to);
|
||||
|
||||
if (retried)
|
||||
port = h->next.port;
|
||||
port = ntohs(h->next.port);
|
||||
for (; port <= port_to; port++) {
|
||||
data.port = htons(port);
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
@ -522,8 +526,8 @@ static struct ip_set_type hash_ipport_type __read_mostly = {
|
||||
.features = IPSET_TYPE_IP | IPSET_TYPE_PORT,
|
||||
.dimension = IPSET_DIM_TWO,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.revision_min = 0,
|
||||
.revision_max = 1, /* SCTP and UDPLITE support added */
|
||||
.revision_min = REVISION_MIN,
|
||||
.revision_max = REVISION_MAX,
|
||||
.create = hash_ipport_create,
|
||||
.create_policy = {
|
||||
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
|
||||
|
@ -25,9 +25,12 @@
|
||||
#include <linux/netfilter/ipset/ip_set_getport.h>
|
||||
#include <linux/netfilter/ipset/ip_set_hash.h>
|
||||
|
||||
#define REVISION_MIN 0
|
||||
#define REVISION_MAX 1 /* SCTP and UDPLITE support added */
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("hash:ip,port,ip type of IP sets");
|
||||
IP_SET_MODULE_DESC("hash:ip,port,ip", REVISION_MIN, REVISION_MAX);
|
||||
MODULE_ALIAS("ip_set_hash:ip,port,ip");
|
||||
|
||||
/* Type specific function prefix */
|
||||
@ -133,8 +136,8 @@ static inline void
|
||||
hash_ipportip4_data_next(struct ip_set_hash *h,
|
||||
const struct hash_ipportip4_elem *d)
|
||||
{
|
||||
h->next.ip = ntohl(d->ip);
|
||||
h->next.port = ntohs(d->port);
|
||||
h->next.ip = d->ip;
|
||||
h->next.port = d->port;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -225,7 +228,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
} else if (tb[IPSET_ATTR_CIDR]) {
|
||||
u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
|
||||
|
||||
if (cidr > 32)
|
||||
if (!cidr || cidr > 32)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
ip_set_mask_from_to(ip, ip_to, cidr);
|
||||
} else
|
||||
@ -239,9 +242,10 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
}
|
||||
|
||||
if (retried)
|
||||
ip = h->next.ip;
|
||||
ip = ntohl(h->next.ip);
|
||||
for (; !before(ip_to, ip); ip++) {
|
||||
p = retried && ip == h->next.ip ? h->next.port : port;
|
||||
p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port)
|
||||
: port;
|
||||
for (; p <= port_to; p++) {
|
||||
data.ip = htonl(ip);
|
||||
data.port = htons(p);
|
||||
@ -362,7 +366,7 @@ static inline void
|
||||
hash_ipportip6_data_next(struct ip_set_hash *h,
|
||||
const struct hash_ipportip6_elem *d)
|
||||
{
|
||||
h->next.port = ntohs(d->port);
|
||||
h->next.port = d->port;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -449,7 +453,7 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
swap(port, port_to);
|
||||
|
||||
if (retried)
|
||||
port = h->next.port;
|
||||
port = ntohs(h->next.port);
|
||||
for (; port <= port_to; port++) {
|
||||
data.port = htons(port);
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
@ -540,8 +544,8 @@ static struct ip_set_type hash_ipportip_type __read_mostly = {
|
||||
.features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2,
|
||||
.dimension = IPSET_DIM_THREE,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.revision_min = 0,
|
||||
.revision_max = 1, /* SCTP and UDPLITE support added */
|
||||
.revision_min = REVISION_MIN,
|
||||
.revision_max = REVISION_MAX,
|
||||
.create = hash_ipportip_create,
|
||||
.create_policy = {
|
||||
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
|
||||
|
@ -25,9 +25,14 @@
|
||||
#include <linux/netfilter/ipset/ip_set_getport.h>
|
||||
#include <linux/netfilter/ipset/ip_set_hash.h>
|
||||
|
||||
#define REVISION_MIN 0
|
||||
/* 1 SCTP and UDPLITE support added */
|
||||
/* 2 Range as input support for IPv4 added */
|
||||
#define REVISION_MAX 3 /* nomatch flag support added */
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("hash:ip,port,net type of IP sets");
|
||||
IP_SET_MODULE_DESC("hash:ip,port,net", REVISION_MIN, REVISION_MAX);
|
||||
MODULE_ALIAS("ip_set_hash:ip,port,net");
|
||||
|
||||
/* Type specific function prefix */
|
||||
@ -99,10 +104,10 @@ hash_ipportnet4_data_flags(struct hash_ipportnet4_elem *dst, u32 flags)
|
||||
dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
static inline int
|
||||
hash_ipportnet4_data_match(const struct hash_ipportnet4_elem *elem)
|
||||
{
|
||||
return !elem->nomatch;
|
||||
return elem->nomatch ? -ENOTEMPTY : 1;
|
||||
}
|
||||
|
||||
static inline void
|
||||
@ -173,9 +178,9 @@ static inline void
|
||||
hash_ipportnet4_data_next(struct ip_set_hash *h,
|
||||
const struct hash_ipportnet4_elem *d)
|
||||
{
|
||||
h->next.ip = ntohl(d->ip);
|
||||
h->next.port = ntohs(d->port);
|
||||
h->next.ip2 = ntohl(d->ip2);
|
||||
h->next.ip = d->ip;
|
||||
h->next.port = d->port;
|
||||
h->next.ip2 = d->ip2;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -290,7 +295,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
} else if (tb[IPSET_ATTR_CIDR]) {
|
||||
u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
|
||||
|
||||
if (cidr > 32)
|
||||
if (!cidr || cidr > 32)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
ip_set_mask_from_to(ip, ip_to, cidr);
|
||||
}
|
||||
@ -314,14 +319,17 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
}
|
||||
|
||||
if (retried)
|
||||
ip = h->next.ip;
|
||||
ip = ntohl(h->next.ip);
|
||||
for (; !before(ip_to, ip); ip++) {
|
||||
data.ip = htonl(ip);
|
||||
p = retried && ip == h->next.ip ? h->next.port : port;
|
||||
p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port)
|
||||
: port;
|
||||
for (; p <= port_to; p++) {
|
||||
data.port = htons(p);
|
||||
ip2 = retried && ip == h->next.ip && p == h->next.port
|
||||
? h->next.ip2 : ip2_from;
|
||||
ip2 = retried
|
||||
&& ip == ntohl(h->next.ip)
|
||||
&& p == ntohs(h->next.port)
|
||||
? ntohl(h->next.ip2) : ip2_from;
|
||||
while (!after(ip2, ip2_to)) {
|
||||
data.ip2 = htonl(ip2);
|
||||
ip2_last = ip_set_range_to_cidr(ip2, ip2_to,
|
||||
@ -403,10 +411,10 @@ hash_ipportnet6_data_flags(struct hash_ipportnet6_elem *dst, u32 flags)
|
||||
dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
static inline int
|
||||
hash_ipportnet6_data_match(const struct hash_ipportnet6_elem *elem)
|
||||
{
|
||||
return !elem->nomatch;
|
||||
return elem->nomatch ? -ENOTEMPTY : 1;
|
||||
}
|
||||
|
||||
static inline void
|
||||
@ -486,7 +494,7 @@ static inline void
|
||||
hash_ipportnet6_data_next(struct ip_set_hash *h,
|
||||
const struct hash_ipportnet6_elem *d)
|
||||
{
|
||||
h->next.port = ntohs(d->port);
|
||||
h->next.port = d->port;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -598,7 +606,7 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
swap(port, port_to);
|
||||
|
||||
if (retried)
|
||||
port = h->next.port;
|
||||
port = ntohs(h->next.port);
|
||||
for (; port <= port_to; port++) {
|
||||
data.port = htons(port);
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
@ -689,13 +697,12 @@ hash_ipportnet_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
|
||||
static struct ip_set_type hash_ipportnet_type __read_mostly = {
|
||||
.name = "hash:ip,port,net",
|
||||
.protocol = IPSET_PROTOCOL,
|
||||
.features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2,
|
||||
.features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2 |
|
||||
IPSET_TYPE_NOMATCH,
|
||||
.dimension = IPSET_DIM_THREE,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.revision_min = 0,
|
||||
/* 1 SCTP and UDPLITE support added */
|
||||
/* 2 Range as input support for IPv4 added */
|
||||
.revision_max = 3, /* nomatch flag support added */
|
||||
.revision_min = REVISION_MIN,
|
||||
.revision_max = REVISION_MAX,
|
||||
.create = hash_ipportnet_create,
|
||||
.create_policy = {
|
||||
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
|
||||
|
@ -23,9 +23,13 @@
|
||||
#include <linux/netfilter/ipset/ip_set_timeout.h>
|
||||
#include <linux/netfilter/ipset/ip_set_hash.h>
|
||||
|
||||
#define REVISION_MIN 0
|
||||
/* 1 Range as input support for IPv4 added */
|
||||
#define REVISION_MAX 2 /* nomatch flag support added */
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("hash:net type of IP sets");
|
||||
IP_SET_MODULE_DESC("hash:net", REVISION_MIN, REVISION_MAX);
|
||||
MODULE_ALIAS("ip_set_hash:net");
|
||||
|
||||
/* Type specific function prefix */
|
||||
@ -86,10 +90,10 @@ hash_net4_data_flags(struct hash_net4_elem *dst, u32 flags)
|
||||
dst->nomatch = flags & IPSET_FLAG_NOMATCH;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
static inline int
|
||||
hash_net4_data_match(const struct hash_net4_elem *elem)
|
||||
{
|
||||
return !elem->nomatch;
|
||||
return elem->nomatch ? -ENOTEMPTY : 1;
|
||||
}
|
||||
|
||||
static inline void
|
||||
@ -152,7 +156,7 @@ static inline void
|
||||
hash_net4_data_next(struct ip_set_hash *h,
|
||||
const struct hash_net4_elem *d)
|
||||
{
|
||||
h->next.ip = ntohl(d->ip);
|
||||
h->next.ip = d->ip;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -235,7 +239,7 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
return -IPSET_ERR_HASH_RANGE;
|
||||
}
|
||||
if (retried)
|
||||
ip = h->next.ip;
|
||||
ip = ntohl(h->next.ip);
|
||||
while (!after(ip, ip_to)) {
|
||||
data.ip = htonl(ip);
|
||||
last = ip_set_range_to_cidr(ip, ip_to, &data.cidr);
|
||||
@ -307,10 +311,10 @@ hash_net6_data_flags(struct hash_net6_elem *dst, u32 flags)
|
||||
dst->nomatch = flags & IPSET_FLAG_NOMATCH;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
static inline int
|
||||
hash_net6_data_match(const struct hash_net6_elem *elem)
|
||||
{
|
||||
return !elem->nomatch;
|
||||
return elem->nomatch ? -ENOTEMPTY : 1;
|
||||
}
|
||||
|
||||
static inline void
|
||||
@ -532,12 +536,11 @@ hash_net_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
|
||||
static struct ip_set_type hash_net_type __read_mostly = {
|
||||
.name = "hash:net",
|
||||
.protocol = IPSET_PROTOCOL,
|
||||
.features = IPSET_TYPE_IP,
|
||||
.features = IPSET_TYPE_IP | IPSET_TYPE_NOMATCH,
|
||||
.dimension = IPSET_DIM_ONE,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.revision_min = 0,
|
||||
/* = 1 Range as input support for IPv4 added */
|
||||
.revision_max = 2, /* nomatch flag support added */
|
||||
.revision_min = REVISION_MIN,
|
||||
.revision_max = REVISION_MAX,
|
||||
.create = hash_net_create,
|
||||
.create_policy = {
|
||||
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
|
||||
|
@ -24,9 +24,13 @@
|
||||
#include <linux/netfilter/ipset/ip_set_timeout.h>
|
||||
#include <linux/netfilter/ipset/ip_set_hash.h>
|
||||
|
||||
#define REVISION_MIN 0
|
||||
/* 1 nomatch flag support added */
|
||||
#define REVISION_MAX 2 /* /0 support added */
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("hash:net,iface type of IP sets");
|
||||
IP_SET_MODULE_DESC("hash:net,iface", REVISION_MIN, REVISION_MAX);
|
||||
MODULE_ALIAS("ip_set_hash:net,iface");
|
||||
|
||||
/* Interface name rbtree */
|
||||
@ -140,7 +144,7 @@ struct hash_netiface4_elem_hashed {
|
||||
u8 physdev;
|
||||
u8 cidr;
|
||||
u8 nomatch;
|
||||
u8 padding;
|
||||
u8 elem;
|
||||
};
|
||||
|
||||
#define HKEY_DATALEN sizeof(struct hash_netiface4_elem_hashed)
|
||||
@ -151,7 +155,7 @@ struct hash_netiface4_elem {
|
||||
u8 physdev;
|
||||
u8 cidr;
|
||||
u8 nomatch;
|
||||
u8 padding;
|
||||
u8 elem;
|
||||
const char *iface;
|
||||
};
|
||||
|
||||
@ -161,7 +165,7 @@ struct hash_netiface4_telem {
|
||||
u8 physdev;
|
||||
u8 cidr;
|
||||
u8 nomatch;
|
||||
u8 padding;
|
||||
u8 elem;
|
||||
const char *iface;
|
||||
unsigned long timeout;
|
||||
};
|
||||
@ -181,18 +185,14 @@ hash_netiface4_data_equal(const struct hash_netiface4_elem *ip1,
|
||||
static inline bool
|
||||
hash_netiface4_data_isnull(const struct hash_netiface4_elem *elem)
|
||||
{
|
||||
return elem->cidr == 0;
|
||||
return elem->elem == 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_netiface4_data_copy(struct hash_netiface4_elem *dst,
|
||||
const struct hash_netiface4_elem *src)
|
||||
{
|
||||
dst->ip = src->ip;
|
||||
dst->cidr = src->cidr;
|
||||
dst->physdev = src->physdev;
|
||||
dst->iface = src->iface;
|
||||
dst->nomatch = src->nomatch;
|
||||
memcpy(dst, src, sizeof(*dst));
|
||||
}
|
||||
|
||||
static inline void
|
||||
@ -201,10 +201,10 @@ hash_netiface4_data_flags(struct hash_netiface4_elem *dst, u32 flags)
|
||||
dst->nomatch = flags & IPSET_FLAG_NOMATCH;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
static inline int
|
||||
hash_netiface4_data_match(const struct hash_netiface4_elem *elem)
|
||||
{
|
||||
return !elem->nomatch;
|
||||
return elem->nomatch ? -ENOTEMPTY : 1;
|
||||
}
|
||||
|
||||
static inline void
|
||||
@ -217,7 +217,7 @@ hash_netiface4_data_netmask(struct hash_netiface4_elem *elem, u8 cidr)
|
||||
static inline void
|
||||
hash_netiface4_data_zero_out(struct hash_netiface4_elem *elem)
|
||||
{
|
||||
elem->cidr = 0;
|
||||
elem->elem = 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
@ -277,7 +277,7 @@ static inline void
|
||||
hash_netiface4_data_next(struct ip_set_hash *h,
|
||||
const struct hash_netiface4_elem *d)
|
||||
{
|
||||
h->next.ip = ntohl(d->ip);
|
||||
h->next.ip = d->ip;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -288,7 +288,8 @@ hash_netiface4_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_netiface4_elem data = {
|
||||
.cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK
|
||||
.cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK,
|
||||
.elem = 1,
|
||||
};
|
||||
int ret;
|
||||
|
||||
@ -339,7 +340,7 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
{
|
||||
struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_netiface4_elem data = { .cidr = HOST_MASK };
|
||||
struct hash_netiface4_elem data = { .cidr = HOST_MASK, .elem = 1 };
|
||||
u32 ip = 0, ip_to, last;
|
||||
u32 timeout = h->timeout;
|
||||
char iface[IFNAMSIZ];
|
||||
@ -360,7 +361,7 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
|
||||
if (tb[IPSET_ATTR_CIDR]) {
|
||||
data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
|
||||
if (!data.cidr || data.cidr > HOST_MASK)
|
||||
if (data.cidr > HOST_MASK)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
}
|
||||
|
||||
@ -389,7 +390,6 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
if (adt == IPSET_ADD && (cadt_flags & IPSET_FLAG_NOMATCH))
|
||||
flags |= (cadt_flags << 16);
|
||||
}
|
||||
|
||||
if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) {
|
||||
data.ip = htonl(ip & ip_set_hostmask(data.cidr));
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
@ -409,7 +409,7 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
}
|
||||
|
||||
if (retried)
|
||||
ip = h->next.ip;
|
||||
ip = ntohl(h->next.ip);
|
||||
while (!after(ip, ip_to)) {
|
||||
data.ip = htonl(ip);
|
||||
last = ip_set_range_to_cidr(ip, ip_to, &data.cidr);
|
||||
@ -442,7 +442,7 @@ struct hash_netiface6_elem_hashed {
|
||||
u8 physdev;
|
||||
u8 cidr;
|
||||
u8 nomatch;
|
||||
u8 padding;
|
||||
u8 elem;
|
||||
};
|
||||
|
||||
#define HKEY_DATALEN sizeof(struct hash_netiface6_elem_hashed)
|
||||
@ -452,7 +452,7 @@ struct hash_netiface6_elem {
|
||||
u8 physdev;
|
||||
u8 cidr;
|
||||
u8 nomatch;
|
||||
u8 padding;
|
||||
u8 elem;
|
||||
const char *iface;
|
||||
};
|
||||
|
||||
@ -461,7 +461,7 @@ struct hash_netiface6_telem {
|
||||
u8 physdev;
|
||||
u8 cidr;
|
||||
u8 nomatch;
|
||||
u8 padding;
|
||||
u8 elem;
|
||||
const char *iface;
|
||||
unsigned long timeout;
|
||||
};
|
||||
@ -481,7 +481,7 @@ hash_netiface6_data_equal(const struct hash_netiface6_elem *ip1,
|
||||
static inline bool
|
||||
hash_netiface6_data_isnull(const struct hash_netiface6_elem *elem)
|
||||
{
|
||||
return elem->cidr == 0;
|
||||
return elem->elem == 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
@ -497,16 +497,16 @@ hash_netiface6_data_flags(struct hash_netiface6_elem *dst, u32 flags)
|
||||
dst->nomatch = flags & IPSET_FLAG_NOMATCH;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
static inline int
|
||||
hash_netiface6_data_match(const struct hash_netiface6_elem *elem)
|
||||
{
|
||||
return !elem->nomatch;
|
||||
return elem->nomatch ? -ENOTEMPTY : 1;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_netiface6_data_zero_out(struct hash_netiface6_elem *elem)
|
||||
{
|
||||
elem->cidr = 0;
|
||||
elem->elem = 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
@ -590,7 +590,8 @@ hash_netiface6_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_netiface6_elem data = {
|
||||
.cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK
|
||||
.cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK,
|
||||
.elem = 1,
|
||||
};
|
||||
int ret;
|
||||
|
||||
@ -637,7 +638,7 @@ hash_netiface6_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
{
|
||||
struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_netiface6_elem data = { .cidr = HOST_MASK };
|
||||
struct hash_netiface6_elem data = { .cidr = HOST_MASK, .elem = 1 };
|
||||
u32 timeout = h->timeout;
|
||||
char iface[IFNAMSIZ];
|
||||
int ret;
|
||||
@ -659,7 +660,7 @@ hash_netiface6_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
|
||||
if (tb[IPSET_ATTR_CIDR])
|
||||
data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
|
||||
if (!data.cidr || data.cidr > HOST_MASK)
|
||||
if (data.cidr > HOST_MASK)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
ip6_netmask(&data.ip, data.cidr);
|
||||
|
||||
@ -773,11 +774,12 @@ hash_netiface_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
|
||||
static struct ip_set_type hash_netiface_type __read_mostly = {
|
||||
.name = "hash:net,iface",
|
||||
.protocol = IPSET_PROTOCOL,
|
||||
.features = IPSET_TYPE_IP | IPSET_TYPE_IFACE,
|
||||
.features = IPSET_TYPE_IP | IPSET_TYPE_IFACE |
|
||||
IPSET_TYPE_NOMATCH,
|
||||
.dimension = IPSET_DIM_TWO,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.revision_min = 0,
|
||||
.revision_max = 1, /* nomatch flag support added */
|
||||
.revision_min = REVISION_MIN,
|
||||
.revision_max = REVISION_MAX,
|
||||
.create = hash_netiface_create,
|
||||
.create_policy = {
|
||||
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
|
||||
|
@ -24,9 +24,14 @@
|
||||
#include <linux/netfilter/ipset/ip_set_getport.h>
|
||||
#include <linux/netfilter/ipset/ip_set_hash.h>
|
||||
|
||||
#define REVISION_MIN 0
|
||||
/* 1 SCTP and UDPLITE support added */
|
||||
/* 2 Range as input support for IPv4 added */
|
||||
#define REVISION_MAX 3 /* nomatch flag support added */
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("hash:net,port type of IP sets");
|
||||
IP_SET_MODULE_DESC("hash:net,port", REVISION_MIN, REVISION_MAX);
|
||||
MODULE_ALIAS("ip_set_hash:net,port");
|
||||
|
||||
/* Type specific function prefix */
|
||||
@ -99,10 +104,10 @@ hash_netport4_data_flags(struct hash_netport4_elem *dst, u32 flags)
|
||||
dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
static inline int
|
||||
hash_netport4_data_match(const struct hash_netport4_elem *elem)
|
||||
{
|
||||
return !elem->nomatch;
|
||||
return elem->nomatch ? -ENOTEMPTY : 1;
|
||||
}
|
||||
|
||||
static inline void
|
||||
@ -171,8 +176,8 @@ static inline void
|
||||
hash_netport4_data_next(struct ip_set_hash *h,
|
||||
const struct hash_netport4_elem *d)
|
||||
{
|
||||
h->next.ip = ntohl(d->ip);
|
||||
h->next.port = ntohs(d->port);
|
||||
h->next.ip = d->ip;
|
||||
h->next.port = d->port;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -289,12 +294,13 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
}
|
||||
|
||||
if (retried)
|
||||
ip = h->next.ip;
|
||||
ip = ntohl(h->next.ip);
|
||||
while (!after(ip, ip_to)) {
|
||||
data.ip = htonl(ip);
|
||||
last = ip_set_range_to_cidr(ip, ip_to, &cidr);
|
||||
data.cidr = cidr - 1;
|
||||
p = retried && ip == h->next.ip ? h->next.port : port;
|
||||
p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port)
|
||||
: port;
|
||||
for (; p <= port_to; p++) {
|
||||
data.port = htons(p);
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
@ -369,10 +375,10 @@ hash_netport6_data_flags(struct hash_netport6_elem *dst, u32 flags)
|
||||
dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
static inline int
|
||||
hash_netport6_data_match(const struct hash_netport6_elem *elem)
|
||||
{
|
||||
return !elem->nomatch;
|
||||
return elem->nomatch ? -ENOTEMPTY : 1;
|
||||
}
|
||||
|
||||
static inline void
|
||||
@ -450,7 +456,7 @@ static inline void
|
||||
hash_netport6_data_next(struct ip_set_hash *h,
|
||||
const struct hash_netport6_elem *d)
|
||||
{
|
||||
h->next.port = ntohs(d->port);
|
||||
h->next.port = d->port;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -554,7 +560,7 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
swap(port, port_to);
|
||||
|
||||
if (retried)
|
||||
port = h->next.port;
|
||||
port = ntohs(h->next.port);
|
||||
for (; port <= port_to; port++) {
|
||||
data.port = htons(port);
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
@ -644,13 +650,11 @@ hash_netport_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
|
||||
static struct ip_set_type hash_netport_type __read_mostly = {
|
||||
.name = "hash:net,port",
|
||||
.protocol = IPSET_PROTOCOL,
|
||||
.features = IPSET_TYPE_IP | IPSET_TYPE_PORT,
|
||||
.features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_NOMATCH,
|
||||
.dimension = IPSET_DIM_TWO,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.revision_min = 0,
|
||||
/* 1 SCTP and UDPLITE support added */
|
||||
/* 2, Range as input support for IPv4 added */
|
||||
.revision_max = 3, /* nomatch flag support added */
|
||||
.revision_min = REVISION_MIN,
|
||||
.revision_max = REVISION_MAX,
|
||||
.create = hash_netport_create,
|
||||
.create_policy = {
|
||||
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
|
||||
|
@ -16,9 +16,12 @@
|
||||
#include <linux/netfilter/ipset/ip_set_timeout.h>
|
||||
#include <linux/netfilter/ipset/ip_set_list.h>
|
||||
|
||||
#define REVISION_MIN 0
|
||||
#define REVISION_MAX 0
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("list:set type of IP sets");
|
||||
IP_SET_MODULE_DESC("list:set", REVISION_MIN, REVISION_MAX);
|
||||
MODULE_ALIAS("ip_set_list:set");
|
||||
|
||||
/* Member elements without and with timeout */
|
||||
@ -579,8 +582,8 @@ static struct ip_set_type list_set_type __read_mostly = {
|
||||
.features = IPSET_TYPE_NAME | IPSET_DUMP_LAST,
|
||||
.dimension = IPSET_DIM_ONE,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.revision_min = 0,
|
||||
.revision_max = 0,
|
||||
.revision_min = REVISION_MIN,
|
||||
.revision_max = REVISION_MAX,
|
||||
.create = list_set_create,
|
||||
.create_policy = {
|
||||
[IPSET_ATTR_SIZE] = { .type = NLA_U32 },
|
||||
|
@ -1224,6 +1224,8 @@ get_next_corpse(struct net *net, int (*iter)(struct nf_conn *i, void *data),
|
||||
spin_lock_bh(&nf_conntrack_lock);
|
||||
for (; *bucket < net->ct.htable_size; (*bucket)++) {
|
||||
hlist_nulls_for_each_entry(h, n, &net->ct.hash[*bucket], hnnode) {
|
||||
if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL)
|
||||
continue;
|
||||
ct = nf_ct_tuplehash_to_ctrack(h);
|
||||
if (iter(ct, data))
|
||||
goto found;
|
||||
|
@ -396,6 +396,12 @@ static int help(struct sk_buff *skb,
|
||||
|
||||
/* Look up to see if we're just after a \n. */
|
||||
if (!find_nl_seq(ntohl(th->seq), ct_ftp_info, dir)) {
|
||||
/* We're picking up this, clear flags and let it continue */
|
||||
if (unlikely(ct_ftp_info->flags[dir] & NF_CT_FTP_SEQ_PICKUP)) {
|
||||
ct_ftp_info->flags[dir] ^= NF_CT_FTP_SEQ_PICKUP;
|
||||
goto skip_nl_seq;
|
||||
}
|
||||
|
||||
/* Now if this ends in \n, update ftp info. */
|
||||
pr_debug("nf_conntrack_ftp: wrong seq pos %s(%u) or %s(%u)\n",
|
||||
ct_ftp_info->seq_aft_nl_num[dir] > 0 ? "" : "(UNSET)",
|
||||
@ -406,6 +412,7 @@ static int help(struct sk_buff *skb,
|
||||
goto out_update_nl;
|
||||
}
|
||||
|
||||
skip_nl_seq:
|
||||
/* Initialize IP/IPv6 addr to expected address (it's not mentioned
|
||||
in EPSV responses) */
|
||||
cmd.l3num = nf_ct_l3num(ct);
|
||||
@ -512,6 +519,19 @@ out_update_nl:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int nf_ct_ftp_from_nlattr(struct nlattr *attr, struct nf_conn *ct)
|
||||
{
|
||||
struct nf_ct_ftp_master *ftp = nfct_help_data(ct);
|
||||
|
||||
/* This conntrack has been injected from user-space, always pick up
|
||||
* sequence tracking. Otherwise, the first FTP command after the
|
||||
* failover breaks.
|
||||
*/
|
||||
ftp->flags[IP_CT_DIR_ORIGINAL] |= NF_CT_FTP_SEQ_PICKUP;
|
||||
ftp->flags[IP_CT_DIR_REPLY] |= NF_CT_FTP_SEQ_PICKUP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct nf_conntrack_helper ftp[MAX_PORTS][2] __read_mostly;
|
||||
|
||||
static const struct nf_conntrack_expect_policy ftp_exp_policy = {
|
||||
@ -561,6 +581,7 @@ static int __init nf_conntrack_ftp_init(void)
|
||||
ftp[i][j].expect_policy = &ftp_exp_policy;
|
||||
ftp[i][j].me = THIS_MODULE;
|
||||
ftp[i][j].help = help;
|
||||
ftp[i][j].from_nlattr = nf_ct_ftp_from_nlattr;
|
||||
if (ports[i] == FTP_PORT)
|
||||
sprintf(ftp[i][j].name, "ftp");
|
||||
else
|
||||
|
@ -1238,7 +1238,7 @@ ctnetlink_change_helper(struct nf_conn *ct, const struct nlattr * const cda[])
|
||||
if (help) {
|
||||
if (help->helper == helper) {
|
||||
/* update private helper data if allowed. */
|
||||
if (helper->from_nlattr && helpinfo)
|
||||
if (helper->from_nlattr)
|
||||
helper->from_nlattr(helpinfo, ct);
|
||||
return 0;
|
||||
} else
|
||||
@ -1467,7 +1467,7 @@ ctnetlink_create_conntrack(struct net *net, u16 zone,
|
||||
goto err2;
|
||||
}
|
||||
/* set private helper data if allowed. */
|
||||
if (helper->from_nlattr && helpinfo)
|
||||
if (helper->from_nlattr)
|
||||
helper->from_nlattr(helpinfo, ct);
|
||||
|
||||
/* not in hash table yet so not strictly necessary */
|
||||
|
@ -201,10 +201,8 @@ find_appropriate_src(struct net *net, u16 zone,
|
||||
&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
|
||||
result->dst = tuple->dst;
|
||||
|
||||
if (in_range(l3proto, l4proto, result, range)) {
|
||||
rcu_read_unlock();
|
||||
if (in_range(l3proto, l4proto, result, range))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@ -481,6 +479,8 @@ static int nf_nat_proto_clean(struct nf_conn *i, void *data)
|
||||
|
||||
if (!nat)
|
||||
return 0;
|
||||
if (!(i->status & IPS_SRC_NAT_DONE))
|
||||
return 0;
|
||||
if ((clean->l3proto && nf_ct_l3num(i) != clean->l3proto) ||
|
||||
(clean->l4proto && nf_ct_protonum(i) != clean->l4proto))
|
||||
return 0;
|
||||
|
@ -85,6 +85,9 @@ nfnl_cthelper_from_nlattr(struct nlattr *attr, struct nf_conn *ct)
|
||||
{
|
||||
const struct nf_conn_help *help = nfct_help(ct);
|
||||
|
||||
if (attr == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (help->helper->data_len == 0)
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -225,7 +225,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
|
||||
{
|
||||
sk_buff_data_t old_tail;
|
||||
size_t size;
|
||||
size_t data_len = 0;
|
||||
size_t data_len = 0, cap_len = 0;
|
||||
struct sk_buff *skb;
|
||||
struct nlattr *nla;
|
||||
struct nfqnl_msg_packet_hdr *pmsg;
|
||||
@ -247,7 +247,8 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
|
||||
#endif
|
||||
+ nla_total_size(sizeof(u_int32_t)) /* mark */
|
||||
+ nla_total_size(sizeof(struct nfqnl_msg_packet_hw))
|
||||
+ nla_total_size(sizeof(struct nfqnl_msg_packet_timestamp));
|
||||
+ nla_total_size(sizeof(struct nfqnl_msg_packet_timestamp)
|
||||
+ nla_total_size(sizeof(u_int32_t))); /* cap_len */
|
||||
|
||||
outdev = entry->outdev;
|
||||
|
||||
@ -266,6 +267,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
|
||||
data_len = entskb->len;
|
||||
|
||||
size += nla_total_size(data_len);
|
||||
cap_len = entskb->len;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -402,6 +404,9 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
|
||||
if (ct && nfqnl_ct_put(skb, ct, ctinfo) < 0)
|
||||
goto nla_put_failure;
|
||||
|
||||
if (cap_len > 0 && nla_put_be32(skb, NFQA_CAP_LEN, htonl(cap_len)))
|
||||
goto nla_put_failure;
|
||||
|
||||
nlh->nlmsg_len = skb->tail - old_tail;
|
||||
return skb;
|
||||
|
||||
@ -526,9 +531,13 @@ nfqnl_set_mode(struct nfqnl_instance *queue,
|
||||
|
||||
case NFQNL_COPY_PACKET:
|
||||
queue->copy_mode = mode;
|
||||
/* we're using struct nlattr which has 16bit nla_len */
|
||||
if (range > 0xffff)
|
||||
queue->copy_range = 0xffff;
|
||||
/* We're using struct nlattr which has 16bit nla_len. Note that
|
||||
* nla_len includes the header length. Thus, the maximum packet
|
||||
* length that we support is 65531 bytes. We send truncated
|
||||
* packets if the specified length is larger than that.
|
||||
*/
|
||||
if (range > 0xffff - NLA_HDRLEN)
|
||||
queue->copy_range = 0xffff - NLA_HDRLEN;
|
||||
else
|
||||
queue->copy_range = range;
|
||||
break;
|
||||
|
165
net/netfilter/xt_NETMAP.c
Normal file
165
net/netfilter/xt_NETMAP.c
Normal file
@ -0,0 +1,165 @@
|
||||
/*
|
||||
* (C) 2000-2001 Svenning Soerensen <svenning@post5.tele.dk>
|
||||
* Copyright (c) 2011 Patrick McHardy <kaber@trash.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.
|
||||
*/
|
||||
|
||||
#include <linux/ip.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netfilter_ipv4.h>
|
||||
#include <linux/netfilter_ipv6.h>
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#include <net/netfilter/nf_nat.h>
|
||||
|
||||
static unsigned int
|
||||
netmap_tg6(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
{
|
||||
const struct nf_nat_range *range = par->targinfo;
|
||||
struct nf_nat_range newrange;
|
||||
struct nf_conn *ct;
|
||||
enum ip_conntrack_info ctinfo;
|
||||
union nf_inet_addr new_addr, netmask;
|
||||
unsigned int i;
|
||||
|
||||
ct = nf_ct_get(skb, &ctinfo);
|
||||
for (i = 0; i < ARRAY_SIZE(range->min_addr.ip6); i++)
|
||||
netmask.ip6[i] = ~(range->min_addr.ip6[i] ^
|
||||
range->max_addr.ip6[i]);
|
||||
|
||||
if (par->hooknum == NF_INET_PRE_ROUTING ||
|
||||
par->hooknum == NF_INET_LOCAL_OUT)
|
||||
new_addr.in6 = ipv6_hdr(skb)->daddr;
|
||||
else
|
||||
new_addr.in6 = ipv6_hdr(skb)->saddr;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(new_addr.ip6); i++) {
|
||||
new_addr.ip6[i] &= ~netmask.ip6[i];
|
||||
new_addr.ip6[i] |= range->min_addr.ip6[i] &
|
||||
netmask.ip6[i];
|
||||
}
|
||||
|
||||
newrange.flags = range->flags | NF_NAT_RANGE_MAP_IPS;
|
||||
newrange.min_addr = new_addr;
|
||||
newrange.max_addr = new_addr;
|
||||
newrange.min_proto = range->min_proto;
|
||||
newrange.max_proto = range->max_proto;
|
||||
|
||||
return nf_nat_setup_info(ct, &newrange, HOOK2MANIP(par->hooknum));
|
||||
}
|
||||
|
||||
static int netmap_tg6_checkentry(const struct xt_tgchk_param *par)
|
||||
{
|
||||
const struct nf_nat_range *range = par->targinfo;
|
||||
|
||||
if (!(range->flags & NF_NAT_RANGE_MAP_IPS))
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
netmap_tg4(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
{
|
||||
struct nf_conn *ct;
|
||||
enum ip_conntrack_info ctinfo;
|
||||
__be32 new_ip, netmask;
|
||||
const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
|
||||
struct nf_nat_range newrange;
|
||||
|
||||
NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING ||
|
||||
par->hooknum == NF_INET_POST_ROUTING ||
|
||||
par->hooknum == NF_INET_LOCAL_OUT ||
|
||||
par->hooknum == NF_INET_LOCAL_IN);
|
||||
ct = nf_ct_get(skb, &ctinfo);
|
||||
|
||||
netmask = ~(mr->range[0].min_ip ^ mr->range[0].max_ip);
|
||||
|
||||
if (par->hooknum == NF_INET_PRE_ROUTING ||
|
||||
par->hooknum == NF_INET_LOCAL_OUT)
|
||||
new_ip = ip_hdr(skb)->daddr & ~netmask;
|
||||
else
|
||||
new_ip = ip_hdr(skb)->saddr & ~netmask;
|
||||
new_ip |= mr->range[0].min_ip & netmask;
|
||||
|
||||
memset(&newrange.min_addr, 0, sizeof(newrange.min_addr));
|
||||
memset(&newrange.max_addr, 0, sizeof(newrange.max_addr));
|
||||
newrange.flags = mr->range[0].flags | NF_NAT_RANGE_MAP_IPS;
|
||||
newrange.min_addr.ip = new_ip;
|
||||
newrange.max_addr.ip = new_ip;
|
||||
newrange.min_proto = mr->range[0].min;
|
||||
newrange.max_proto = mr->range[0].max;
|
||||
|
||||
/* Hand modified range to generic setup. */
|
||||
return nf_nat_setup_info(ct, &newrange, HOOK2MANIP(par->hooknum));
|
||||
}
|
||||
|
||||
static int netmap_tg4_check(const struct xt_tgchk_param *par)
|
||||
{
|
||||
const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
|
||||
|
||||
if (!(mr->range[0].flags & NF_NAT_RANGE_MAP_IPS)) {
|
||||
pr_debug("bad MAP_IPS.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (mr->rangesize != 1) {
|
||||
pr_debug("bad rangesize %u.\n", mr->rangesize);
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct xt_target netmap_tg_reg[] __read_mostly = {
|
||||
{
|
||||
.name = "NETMAP",
|
||||
.family = NFPROTO_IPV6,
|
||||
.revision = 0,
|
||||
.target = netmap_tg6,
|
||||
.targetsize = sizeof(struct nf_nat_range),
|
||||
.table = "nat",
|
||||
.hooks = (1 << NF_INET_PRE_ROUTING) |
|
||||
(1 << NF_INET_POST_ROUTING) |
|
||||
(1 << NF_INET_LOCAL_OUT) |
|
||||
(1 << NF_INET_LOCAL_IN),
|
||||
.checkentry = netmap_tg6_checkentry,
|
||||
.me = THIS_MODULE,
|
||||
},
|
||||
{
|
||||
.name = "NETMAP",
|
||||
.family = NFPROTO_IPV4,
|
||||
.revision = 0,
|
||||
.target = netmap_tg4,
|
||||
.targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat),
|
||||
.table = "nat",
|
||||
.hooks = (1 << NF_INET_PRE_ROUTING) |
|
||||
(1 << NF_INET_POST_ROUTING) |
|
||||
(1 << NF_INET_LOCAL_OUT) |
|
||||
(1 << NF_INET_LOCAL_IN),
|
||||
.checkentry = netmap_tg4_check,
|
||||
.me = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init netmap_tg_init(void)
|
||||
{
|
||||
return xt_register_targets(netmap_tg_reg, ARRAY_SIZE(netmap_tg_reg));
|
||||
}
|
||||
|
||||
static void netmap_tg_exit(void)
|
||||
{
|
||||
xt_unregister_targets(netmap_tg_reg, ARRAY_SIZE(netmap_tg_reg));
|
||||
}
|
||||
|
||||
module_init(netmap_tg_init);
|
||||
module_exit(netmap_tg_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Xtables: 1:1 NAT mapping of subnets");
|
||||
MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
|
||||
MODULE_ALIAS("ip6t_NETMAP");
|
||||
MODULE_ALIAS("ipt_NETMAP");
|
190
net/netfilter/xt_REDIRECT.c
Normal file
190
net/netfilter/xt_REDIRECT.c
Normal file
@ -0,0 +1,190 @@
|
||||
/*
|
||||
* (C) 1999-2001 Paul `Rusty' Russell
|
||||
* (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
|
||||
* Copyright (c) 2011 Patrick McHardy <kaber@trash.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.
|
||||
*
|
||||
* Based on Rusty Russell's IPv4 REDIRECT target. Development of IPv6
|
||||
* NAT funded by Astaro.
|
||||
*/
|
||||
|
||||
#include <linux/if.h>
|
||||
#include <linux/inetdevice.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/netfilter_ipv4.h>
|
||||
#include <linux/netfilter_ipv6.h>
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#include <net/addrconf.h>
|
||||
#include <net/checksum.h>
|
||||
#include <net/protocol.h>
|
||||
#include <net/netfilter/nf_nat.h>
|
||||
|
||||
static const struct in6_addr loopback_addr = IN6ADDR_LOOPBACK_INIT;
|
||||
|
||||
static unsigned int
|
||||
redirect_tg6(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
{
|
||||
const struct nf_nat_range *range = par->targinfo;
|
||||
struct nf_nat_range newrange;
|
||||
struct in6_addr newdst;
|
||||
enum ip_conntrack_info ctinfo;
|
||||
struct nf_conn *ct;
|
||||
|
||||
ct = nf_ct_get(skb, &ctinfo);
|
||||
if (par->hooknum == NF_INET_LOCAL_OUT)
|
||||
newdst = loopback_addr;
|
||||
else {
|
||||
struct inet6_dev *idev;
|
||||
struct inet6_ifaddr *ifa;
|
||||
bool addr = false;
|
||||
|
||||
rcu_read_lock();
|
||||
idev = __in6_dev_get(skb->dev);
|
||||
if (idev != NULL) {
|
||||
list_for_each_entry(ifa, &idev->addr_list, if_list) {
|
||||
newdst = ifa->addr;
|
||||
addr = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
if (!addr)
|
||||
return NF_DROP;
|
||||
}
|
||||
|
||||
newrange.flags = range->flags | NF_NAT_RANGE_MAP_IPS;
|
||||
newrange.min_addr.in6 = newdst;
|
||||
newrange.max_addr.in6 = newdst;
|
||||
newrange.min_proto = range->min_proto;
|
||||
newrange.max_proto = range->max_proto;
|
||||
|
||||
return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST);
|
||||
}
|
||||
|
||||
static int redirect_tg6_checkentry(const struct xt_tgchk_param *par)
|
||||
{
|
||||
const struct nf_nat_range *range = par->targinfo;
|
||||
|
||||
if (range->flags & NF_NAT_RANGE_MAP_IPS)
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* FIXME: Take multiple ranges --RR */
|
||||
static int redirect_tg4_check(const struct xt_tgchk_param *par)
|
||||
{
|
||||
const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
|
||||
|
||||
if (mr->range[0].flags & NF_NAT_RANGE_MAP_IPS) {
|
||||
pr_debug("bad MAP_IPS.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (mr->rangesize != 1) {
|
||||
pr_debug("bad rangesize %u.\n", mr->rangesize);
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
redirect_tg4(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
{
|
||||
struct nf_conn *ct;
|
||||
enum ip_conntrack_info ctinfo;
|
||||
__be32 newdst;
|
||||
const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
|
||||
struct nf_nat_range newrange;
|
||||
|
||||
NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING ||
|
||||
par->hooknum == NF_INET_LOCAL_OUT);
|
||||
|
||||
ct = nf_ct_get(skb, &ctinfo);
|
||||
NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED));
|
||||
|
||||
/* Local packets: make them go to loopback */
|
||||
if (par->hooknum == NF_INET_LOCAL_OUT)
|
||||
newdst = htonl(0x7F000001);
|
||||
else {
|
||||
struct in_device *indev;
|
||||
struct in_ifaddr *ifa;
|
||||
|
||||
newdst = 0;
|
||||
|
||||
rcu_read_lock();
|
||||
indev = __in_dev_get_rcu(skb->dev);
|
||||
if (indev && (ifa = indev->ifa_list))
|
||||
newdst = ifa->ifa_local;
|
||||
rcu_read_unlock();
|
||||
|
||||
if (!newdst)
|
||||
return NF_DROP;
|
||||
}
|
||||
|
||||
/* Transfer from original range. */
|
||||
memset(&newrange.min_addr, 0, sizeof(newrange.min_addr));
|
||||
memset(&newrange.max_addr, 0, sizeof(newrange.max_addr));
|
||||
newrange.flags = mr->range[0].flags | NF_NAT_RANGE_MAP_IPS;
|
||||
newrange.min_addr.ip = newdst;
|
||||
newrange.max_addr.ip = newdst;
|
||||
newrange.min_proto = mr->range[0].min;
|
||||
newrange.max_proto = mr->range[0].max;
|
||||
|
||||
/* Hand modified range to generic setup. */
|
||||
return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST);
|
||||
}
|
||||
|
||||
static struct xt_target redirect_tg_reg[] __read_mostly = {
|
||||
{
|
||||
.name = "REDIRECT",
|
||||
.family = NFPROTO_IPV6,
|
||||
.revision = 0,
|
||||
.table = "nat",
|
||||
.checkentry = redirect_tg6_checkentry,
|
||||
.target = redirect_tg6,
|
||||
.targetsize = sizeof(struct nf_nat_range),
|
||||
.hooks = (1 << NF_INET_PRE_ROUTING) |
|
||||
(1 << NF_INET_LOCAL_OUT),
|
||||
.me = THIS_MODULE,
|
||||
},
|
||||
{
|
||||
.name = "REDIRECT",
|
||||
.family = NFPROTO_IPV4,
|
||||
.revision = 0,
|
||||
.table = "nat",
|
||||
.target = redirect_tg4,
|
||||
.checkentry = redirect_tg4_check,
|
||||
.targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat),
|
||||
.hooks = (1 << NF_INET_PRE_ROUTING) |
|
||||
(1 << NF_INET_LOCAL_OUT),
|
||||
.me = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init redirect_tg_init(void)
|
||||
{
|
||||
return xt_register_targets(redirect_tg_reg,
|
||||
ARRAY_SIZE(redirect_tg_reg));
|
||||
}
|
||||
|
||||
static void __exit redirect_tg_exit(void)
|
||||
{
|
||||
xt_unregister_targets(redirect_tg_reg, ARRAY_SIZE(redirect_tg_reg));
|
||||
}
|
||||
|
||||
module_init(redirect_tg_init);
|
||||
module_exit(redirect_tg_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
|
||||
MODULE_DESCRIPTION("Xtables: Connection redirection to localhost");
|
||||
MODULE_ALIAS("ip6t_REDIRECT");
|
||||
MODULE_ALIAS("ipt_REDIRECT");
|
@ -356,6 +356,27 @@ static struct xt_match set_matches[] __read_mostly = {
|
||||
.destroy = set_match_v1_destroy,
|
||||
.me = THIS_MODULE
|
||||
},
|
||||
/* --return-nomatch flag support */
|
||||
{
|
||||
.name = "set",
|
||||
.family = NFPROTO_IPV4,
|
||||
.revision = 2,
|
||||
.match = set_match_v1,
|
||||
.matchsize = sizeof(struct xt_set_info_match_v1),
|
||||
.checkentry = set_match_v1_checkentry,
|
||||
.destroy = set_match_v1_destroy,
|
||||
.me = THIS_MODULE
|
||||
},
|
||||
{
|
||||
.name = "set",
|
||||
.family = NFPROTO_IPV6,
|
||||
.revision = 2,
|
||||
.match = set_match_v1,
|
||||
.matchsize = sizeof(struct xt_set_info_match_v1),
|
||||
.checkentry = set_match_v1_checkentry,
|
||||
.destroy = set_match_v1_destroy,
|
||||
.me = THIS_MODULE
|
||||
},
|
||||
};
|
||||
|
||||
static struct xt_target set_targets[] __read_mostly = {
|
||||
@ -389,6 +410,7 @@ static struct xt_target set_targets[] __read_mostly = {
|
||||
.destroy = set_target_v1_destroy,
|
||||
.me = THIS_MODULE
|
||||
},
|
||||
/* --timeout and --exist flags support */
|
||||
{
|
||||
.name = "SET",
|
||||
.revision = 2,
|
||||
|
@ -42,6 +42,7 @@ static const u_int16_t days_since_leapyear[] = {
|
||||
*/
|
||||
enum {
|
||||
DSE_FIRST = 2039,
|
||||
SECONDS_PER_DAY = 86400,
|
||||
};
|
||||
static const u_int16_t days_since_epoch[] = {
|
||||
/* 2039 - 2030 */
|
||||
@ -78,7 +79,7 @@ static inline unsigned int localtime_1(struct xtm *r, time_t time)
|
||||
unsigned int v, w;
|
||||
|
||||
/* Each day has 86400s, so finding the hour/minute is actually easy. */
|
||||
v = time % 86400;
|
||||
v = time % SECONDS_PER_DAY;
|
||||
r->second = v % 60;
|
||||
w = v / 60;
|
||||
r->minute = w % 60;
|
||||
@ -199,6 +200,18 @@ time_mt(const struct sk_buff *skb, struct xt_action_param *par)
|
||||
if (packet_time < info->daytime_start &&
|
||||
packet_time > info->daytime_stop)
|
||||
return false;
|
||||
|
||||
/** if user asked to ignore 'next day', then e.g.
|
||||
* '1 PM Wed, August 1st' should be treated
|
||||
* like 'Tue 1 PM July 31st'.
|
||||
*
|
||||
* This also causes
|
||||
* 'Monday, "23:00 to 01:00", to match for 2 hours, starting
|
||||
* Monday 23:00 to Tuesday 01:00.
|
||||
*/
|
||||
if ((info->flags & XT_TIME_CONTIGUOUS) &&
|
||||
packet_time <= info->daytime_stop)
|
||||
stamp -= SECONDS_PER_DAY;
|
||||
}
|
||||
|
||||
localtime_2(¤t_time, stamp);
|
||||
@ -227,6 +240,15 @@ static int time_mt_check(const struct xt_mtchk_param *par)
|
||||
return -EDOM;
|
||||
}
|
||||
|
||||
if (info->flags & ~XT_TIME_ALL_FLAGS) {
|
||||
pr_info("unknown flags 0x%x\n", info->flags & ~XT_TIME_ALL_FLAGS);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((info->flags & XT_TIME_CONTIGUOUS) &&
|
||||
info->daytime_start < info->daytime_stop)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user