Skip to content

Commit

Permalink
Merge branch 'master' of git://1984.lsi.us.es/nf-next
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
David S. Miller committed Sep 24, 2012
2 parents 2ddc7fe + 6ee584b commit ae47351
Show file tree
Hide file tree
Showing 37 changed files with 773 additions and 670 deletions.
15 changes: 13 additions & 2 deletions include/linux/netfilter/ipset/ip_set.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -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__
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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);

Expand Down Expand Up @@ -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;
Expand Down
106 changes: 56 additions & 50 deletions include/linux/netfilter/ipset/ip_set_ahash.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

++h->nets[cidr-1].nets;

pr_debug("add_cidr added %u: %u\n", cidr, h->nets[cidr-1].nets);
int i, j;

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 (j != -1) {
for (; i > j; i--) {
h->nets[i].cidr = h->nets[i - 1].cidr;
h->nets[i].nets = h->nets[i - 1].nets;
}
}
if (i < host_mask)
h->nets[i].cidr = cidr;
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;

--h->nets[cidr-1].nets;
u8 i, j;

pr_debug("del_cidr deleted %u: %u\n", cidr, h->nets[cidr-1].nets);
for (i = 0; i < nets_length - 1 && h->nets[i].cidr != cidr; i++)
;
h->nets[i].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 */
Expand All @@ -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);

Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -690,7 +696,7 @@ type_pf_list(const struct ip_set *set,
}

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
Expand Down Expand Up @@ -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;
Expand All @@ -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 */
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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);
Expand All @@ -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:
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
6 changes: 5 additions & 1 deletion include/linux/netfilter/nf_conntrack_ftp.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions include/linux/netfilter/nfnetlink_queue.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
};
Expand Down
5 changes: 5 additions & 0 deletions include/linux/netfilter/xt_time.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,16 @@ 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,
XT_TIME_MIN_DAYTIME = 0,
XT_TIME_MAX_DAYTIME = 24 * 60 * 60 - 1,
};

#define XT_TIME_ALL_FLAGS (XT_TIME_LOCAL_TZ|XT_TIME_CONTIGUOUS)

#endif /* _XT_TIME_H */
23 changes: 10 additions & 13 deletions net/ipv4/netfilter/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Loading

0 comments on commit ae47351

Please sign in to comment.