Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d639feaa authored by David S. Miller's avatar David S. Miller
Browse files


Pablo Neira Ayuso says:

====================
The following patchset contains Netfilter updates for your net-next tree,
mostly ipset improvements and enhancements features, they are:

* Don't call ip_nest_end needlessly in the error path from me, suggested
  by Pablo Neira Ayuso, from Jozsef Kadlecsik.

* Fixed sparse warnings about shadowed variable and missing rcu annotation
  and fix of "may be used uninitialized" warnings, also from Jozsef.

* Renamed simple macro names to avoid namespace issues, reported by David
  Laight, again from Jozsef.

* Use fix sized type for timeout in the extension part, and cosmetic
  ordering of matches and targets separatedly in xt_set.c, from Jozsef.

* Support package fragments for IPv4 protos without ports from Anders K.
  Pedersen. For example this allows a hash:ip,port ipset containing the
  entry 192.168.0.1,gre:0 to match all package fragments for PPTP VPN
  tunnels to/from the host. Without this patch only the first package
  fragment (with fragment offset 0) was matched.

* Introduced a new operation to get both setname and family, from Jozsef.
  ip[6]tables set match and SET target need to know the family of the set
  in order to reject adding rules which refer to a set with a non-mathcing
  family. Currently such rules are silently accepted and then ignored
  instead of generating an error message to the user.

* Reworked extensions support in ipset types from Jozsef. The approach of
  defining structures with all variations is not manageable as the
  number of extensions grows. Therefore a blob for the extensions is
  introduced, somewhat similar to conntrack. The support of extensions
  which need a per data destroy function is added as well.

* When an element timed out in a list:set type of set, the garbage
  collector skipped the checking of the next element. So the purging
  was delayed to the next run of the gc, fixed by Jozsef.

* A small Kconfig fix: NETFILTER_NETLINK cannot be selected and
  ipset requires it.

* hash:net,net type from Oliver Smith. The type provides the ability to
  store pairs of subnets in a set.

* Comment for ipset entries from Oliver Smith. This makes possible to
  annotate entries in a set with comments, for example:

  ipset n foo hash:net,net comment
  ipset a foo 10.0.0.0/21,192.168.1.0/24 comment "office nets A and B"

* Fix of hash types resizing with comment extension from Jozsef.

* Fix of new extensions for list:set type when an element is added
  into a slot from where another element was pushed away from Jozsef.

* Introduction of a common function for the listing of the element
  extensions from Jozsef.

* Net namespace support for ipset from Vitaly Lavrov.

* hash:net,port,net type from Oliver Smith, which makes possible
  to store the triples of two subnets and a protocol, port pair in
  a set.

* Get xt_TCPMSS working with net namespace, by Gao feng.

* Use the proper net netnamespace to allocate skbs, also by Gao feng.

* A couple of cleanups for the conntrack SIP helper, by Holger
  Eitzenberger.

* Extend cttimeout to allow setting default conntrack timeouts via
  nfnetlink, so we can get rid of all our sysctl/proc interfaces in
  the future for timeout tuning, from me.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 96f817fe 91cb498e
Loading
Loading
Loading
Loading
+125 −26
Original line number Diff line number Diff line
@@ -49,31 +49,68 @@ enum ip_set_feature {

/* Set extensions */
enum ip_set_extension {
	IPSET_EXT_NONE = 0,
	IPSET_EXT_BIT_TIMEOUT = 1,
	IPSET_EXT_BIT_TIMEOUT = 0,
	IPSET_EXT_TIMEOUT = (1 << IPSET_EXT_BIT_TIMEOUT),
	IPSET_EXT_BIT_COUNTER = 2,
	IPSET_EXT_BIT_COUNTER = 1,
	IPSET_EXT_COUNTER = (1 << IPSET_EXT_BIT_COUNTER),
};

/* Extension offsets */
enum ip_set_offset {
	IPSET_OFFSET_TIMEOUT = 0,
	IPSET_OFFSET_COUNTER,
	IPSET_OFFSET_MAX,
	IPSET_EXT_BIT_COMMENT = 2,
	IPSET_EXT_COMMENT = (1 << IPSET_EXT_BIT_COMMENT),
	/* Mark set with an extension which needs to call destroy */
	IPSET_EXT_BIT_DESTROY = 7,
	IPSET_EXT_DESTROY = (1 << IPSET_EXT_BIT_DESTROY),
};

#define SET_WITH_TIMEOUT(s)	((s)->extensions & IPSET_EXT_TIMEOUT)
#define SET_WITH_COUNTER(s)	((s)->extensions & IPSET_EXT_COUNTER)
#define SET_WITH_COMMENT(s)	((s)->extensions & IPSET_EXT_COMMENT)

/* Extension id, in size order */
enum ip_set_ext_id {
	IPSET_EXT_ID_COUNTER = 0,
	IPSET_EXT_ID_TIMEOUT,
	IPSET_EXT_ID_COMMENT,
	IPSET_EXT_ID_MAX,
};

/* Extension type */
struct ip_set_ext_type {
	/* Destroy extension private data (can be NULL) */
	void (*destroy)(void *ext);
	enum ip_set_extension type;
	enum ipset_cadt_flags flag;
	/* Size and minimal alignment */
	u8 len;
	u8 align;
};

extern const struct ip_set_ext_type ip_set_extensions[];

struct ip_set_ext {
	unsigned long timeout;
	u64 packets;
	u64 bytes;
	u32 timeout;
	char *comment;
};

struct ip_set_counter {
	atomic64_t bytes;
	atomic64_t packets;
};

struct ip_set_comment {
	char *str;
};

struct ip_set;

#define ext_timeout(e, s)	\
(unsigned long *)(((void *)(e)) + (s)->offset[IPSET_EXT_ID_TIMEOUT])
#define ext_counter(e, s)	\
(struct ip_set_counter *)(((void *)(e)) + (s)->offset[IPSET_EXT_ID_COUNTER])
#define ext_comment(e, s)	\
(struct ip_set_comment *)(((void *)(e)) + (s)->offset[IPSET_EXT_ID_COMMENT])


typedef int (*ipset_adtfn)(struct ip_set *set, void *value,
			   const struct ip_set_ext *ext,
			   struct ip_set_ext *mext, u32 cmdflags);
@@ -147,7 +184,8 @@ struct ip_set_type {
	u8 revision_min, revision_max;

	/* Create set */
	int (*create)(struct ip_set *set, struct nlattr *tb[], u32 flags);
	int (*create)(struct net *net, struct ip_set *set,
		      struct nlattr *tb[], u32 flags);

	/* Attribute policies */
	const struct nla_policy create_policy[IPSET_ATTR_CREATE_MAX + 1];
@@ -179,14 +217,45 @@ struct ip_set {
	u8 revision;
	/* Extensions */
	u8 extensions;
	/* Default timeout value, if enabled */
	u32 timeout;
	/* Element data size */
	size_t dsize;
	/* Offsets to extensions in elements */
	size_t offset[IPSET_EXT_ID_MAX];
	/* The type specific data */
	void *data;
};

struct ip_set_counter {
	atomic64_t bytes;
	atomic64_t packets;
};
static inline void
ip_set_ext_destroy(struct ip_set *set, void *data)
{
	/* Check that the extension is enabled for the set and
	 * call it's destroy function for its extension part in data.
	 */
	if (SET_WITH_COMMENT(set))
		ip_set_extensions[IPSET_EXT_ID_COMMENT].destroy(
			ext_comment(data, set));
}

static inline int
ip_set_put_flags(struct sk_buff *skb, struct ip_set *set)
{
	u32 cadt_flags = 0;

	if (SET_WITH_TIMEOUT(set))
		if (unlikely(nla_put_net32(skb, IPSET_ATTR_TIMEOUT,
					   htonl(set->timeout))))
			return -EMSGSIZE;
	if (SET_WITH_COUNTER(set))
		cadt_flags |= IPSET_FLAG_WITH_COUNTERS;
	if (SET_WITH_COMMENT(set))
		cadt_flags |= IPSET_FLAG_WITH_COMMENT;

	if (!cadt_flags)
		return 0;
	return nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(cadt_flags));
}

static inline void
ip_set_add_bytes(u64 bytes, struct ip_set_counter *counter)
@@ -248,12 +317,13 @@ ip_set_init_counter(struct ip_set_counter *counter,
}

/* register and unregister set references */
extern ip_set_id_t ip_set_get_byname(const char *name, struct ip_set **set);
extern void ip_set_put_byindex(ip_set_id_t index);
extern const char *ip_set_name_byindex(ip_set_id_t index);
extern ip_set_id_t ip_set_nfnl_get(const char *name);
extern ip_set_id_t ip_set_nfnl_get_byindex(ip_set_id_t index);
extern void ip_set_nfnl_put(ip_set_id_t index);
extern ip_set_id_t ip_set_get_byname(struct net *net,
				     const char *name, struct ip_set **set);
extern void ip_set_put_byindex(struct net *net, ip_set_id_t index);
extern const char *ip_set_name_byindex(struct net *net, ip_set_id_t index);
extern ip_set_id_t ip_set_nfnl_get(struct net *net, const char *name);
extern ip_set_id_t ip_set_nfnl_get_byindex(struct net *net, ip_set_id_t index);
extern void ip_set_nfnl_put(struct net *net, ip_set_id_t index);

/* API for iptables set match, and SET target */

@@ -272,6 +342,8 @@ extern void *ip_set_alloc(size_t size);
extern void ip_set_free(void *members);
extern int ip_set_get_ipaddr4(struct nlattr *nla,  __be32 *ipaddr);
extern int ip_set_get_ipaddr6(struct nlattr *nla, union nf_inet_addr *ipaddr);
extern size_t ip_set_elem_len(struct ip_set *set, struct nlattr *tb[],
			      size_t len);
extern int ip_set_get_extensions(struct ip_set *set, struct nlattr *tb[],
				 struct ip_set_ext *ext);

@@ -389,13 +461,40 @@ bitmap_bytes(u32 a, u32 b)
}

#include <linux/netfilter/ipset/ip_set_timeout.h>
#include <linux/netfilter/ipset/ip_set_comment.h>

#define IP_SET_INIT_KEXT(skb, opt, map)			\
static inline int
ip_set_put_extensions(struct sk_buff *skb, const struct ip_set *set,
		      const void *e, bool active)
{
	if (SET_WITH_TIMEOUT(set)) {
		unsigned long *timeout = ext_timeout(e, set);

		if (nla_put_net32(skb, IPSET_ATTR_TIMEOUT,
			htonl(active ? ip_set_timeout_get(timeout)
				: *timeout)))
			return -EMSGSIZE;
	}
	if (SET_WITH_COUNTER(set) &&
	    ip_set_put_counter(skb, ext_counter(e, set)))
		return -EMSGSIZE;
	if (SET_WITH_COMMENT(set) &&
	    ip_set_put_comment(skb, ext_comment(e, set)))
		return -EMSGSIZE;
	return 0;
}

#define IP_SET_INIT_KEXT(skb, opt, set)			\
	{ .bytes = (skb)->len, .packets = 1,		\
	  .timeout = ip_set_adt_opt_timeout(opt, map) }
	  .timeout = ip_set_adt_opt_timeout(opt, set) }

#define IP_SET_INIT_UEXT(map)				\
#define IP_SET_INIT_UEXT(set)				\
	{ .bytes = ULLONG_MAX, .packets = ULLONG_MAX,	\
	  .timeout = (map)->timeout }
	  .timeout = (set)->timeout }

#define IP_SET_INIT_CIDR(a, b) ((a) ? (a) : (b))

#define IPSET_CONCAT(a, b)		a##b
#define IPSET_TOKEN(a, b)		IPSET_CONCAT(a, b)

#endif /*_IP_SET_H */
+57 −0
Original line number Diff line number Diff line
#ifndef _IP_SET_COMMENT_H
#define _IP_SET_COMMENT_H

/* Copyright (C) 2013 Oliver Smith <oliver@8.c.9.b.0.7.4.0.1.0.0.2.ip6.arpa>
 *
 * 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.
 */

#ifdef __KERNEL__

static inline char*
ip_set_comment_uget(struct nlattr *tb)
{
	return nla_data(tb);
}

static inline void
ip_set_init_comment(struct ip_set_comment *comment,
		    const struct ip_set_ext *ext)
{
	size_t len = ext->comment ? strlen(ext->comment) : 0;

	if (unlikely(comment->str)) {
		kfree(comment->str);
		comment->str = NULL;
	}
	if (!len)
		return;
	if (unlikely(len > IPSET_MAX_COMMENT_SIZE))
		len = IPSET_MAX_COMMENT_SIZE;
	comment->str = kzalloc(len + 1, GFP_ATOMIC);
	if (unlikely(!comment->str))
		return;
	strlcpy(comment->str, ext->comment, len + 1);
}

static inline int
ip_set_put_comment(struct sk_buff *skb, struct ip_set_comment *comment)
{
	if (!comment->str)
		return 0;
	return nla_put_string(skb, IPSET_ATTR_COMMENT, comment->str);
}

static inline void
ip_set_comment_free(struct ip_set_comment *comment)
{
	if (unlikely(!comment->str))
		return;
	kfree(comment->str);
	comment->str = NULL;
}

#endif
#endif
+2 −2
Original line number Diff line number Diff line
@@ -23,8 +23,8 @@
/* Set is defined with timeout support: timeout value may be 0 */
#define IPSET_NO_TIMEOUT	UINT_MAX

#define ip_set_adt_opt_timeout(opt, map)	\
((opt)->ext.timeout != IPSET_NO_TIMEOUT ? (opt)->ext.timeout : (map)->timeout)
#define ip_set_adt_opt_timeout(opt, set)	\
((opt)->ext.timeout != IPSET_NO_TIMEOUT ? (opt)->ext.timeout : (set)->timeout)

static inline unsigned int
ip_set_timeout_uget(struct nlattr *tb)
+58 −49
Original line number Diff line number Diff line
@@ -107,14 +107,17 @@ enum sdp_header_types {
	SDP_HDR_MEDIA,
};

extern unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb,
struct nf_nat_sip_hooks {
	unsigned int (*msg)(struct sk_buff *skb,
			    unsigned int protoff,
			    unsigned int dataoff,
			    const char **dptr,
			    unsigned int *datalen);
extern void (*nf_nat_sip_seq_adjust_hook)(struct sk_buff *skb,

	void (*seq_adjust)(struct sk_buff *skb,
			   unsigned int protoff, s16 off);
extern unsigned int (*nf_nat_sip_expect_hook)(struct sk_buff *skb,

	unsigned int (*expect)(struct sk_buff *skb,
			       unsigned int protoff,
			       unsigned int dataoff,
			       const char **dptr,
@@ -122,7 +125,8 @@ extern unsigned int (*nf_nat_sip_expect_hook)(struct sk_buff *skb,
			       struct nf_conntrack_expect *exp,
			       unsigned int matchoff,
			       unsigned int matchlen);
extern unsigned int (*nf_nat_sdp_addr_hook)(struct sk_buff *skb,

	unsigned int (*sdp_addr)(struct sk_buff *skb,
				 unsigned int protoff,
				 unsigned int dataoff,
				 const char **dptr,
@@ -131,7 +135,8 @@ extern unsigned int (*nf_nat_sdp_addr_hook)(struct sk_buff *skb,
				 enum sdp_header_types type,
				 enum sdp_header_types term,
				 const union nf_inet_addr *addr);
extern unsigned int (*nf_nat_sdp_port_hook)(struct sk_buff *skb,

	unsigned int (*sdp_port)(struct sk_buff *skb,
				 unsigned int protoff,
				 unsigned int dataoff,
				 const char **dptr,
@@ -139,14 +144,16 @@ extern unsigned int (*nf_nat_sdp_port_hook)(struct sk_buff *skb,
				 unsigned int matchoff,
				 unsigned int matchlen,
				 u_int16_t port);
extern unsigned int (*nf_nat_sdp_session_hook)(struct sk_buff *skb,

	unsigned int (*sdp_session)(struct sk_buff *skb,
				    unsigned int protoff,
				    unsigned int dataoff,
				    const char **dptr,
				    unsigned int *datalen,
				    unsigned int sdpoff,
				    const union nf_inet_addr *addr);
extern unsigned int (*nf_nat_sdp_media_hook)(struct sk_buff *skb,

	unsigned int (*sdp_media)(struct sk_buff *skb,
				  unsigned int protoff,
				  unsigned int dataoff,
				  const char **dptr,
@@ -156,6 +163,8 @@ extern unsigned int (*nf_nat_sdp_media_hook)(struct sk_buff *skb,
				  unsigned int mediaoff,
				  unsigned int medialen,
				  union nf_inet_addr *rtp_addr);
};
extern const struct nf_nat_sip_hooks *nf_nat_sip_hooks;

int ct_sip_parse_request(const struct nf_conn *ct, const char *dptr,
			 unsigned int datalen, unsigned int *matchoff,
+15 −1
Original line number Diff line number Diff line
@@ -10,12 +10,14 @@
#ifndef _UAPI_IP_SET_H
#define _UAPI_IP_SET_H


#include <linux/types.h>

/* The protocol version */
#define IPSET_PROTOCOL		6

/* The maximum permissible comment length we will accept over netlink */
#define IPSET_MAX_COMMENT_SIZE	255

/* The max length of strings including NUL: set and type identifiers */
#define IPSET_MAXNAMELEN	32

@@ -110,6 +112,7 @@ enum {
	IPSET_ATTR_IFACE,
	IPSET_ATTR_BYTES,
	IPSET_ATTR_PACKETS,
	IPSET_ATTR_COMMENT,
	__IPSET_ATTR_ADT_MAX,
};
#define IPSET_ATTR_ADT_MAX	(__IPSET_ATTR_ADT_MAX - 1)
@@ -140,6 +143,7 @@ enum ipset_errno {
	IPSET_ERR_IPADDR_IPV4,
	IPSET_ERR_IPADDR_IPV6,
	IPSET_ERR_COUNTER,
	IPSET_ERR_COMMENT,

	/* Type specific error codes */
	IPSET_ERR_TYPE_SPECIFIC = 4352,
@@ -176,6 +180,8 @@ enum ipset_cadt_flags {
	IPSET_FLAG_NOMATCH	= (1 << IPSET_FLAG_BIT_NOMATCH),
	IPSET_FLAG_BIT_WITH_COUNTERS = 3,
	IPSET_FLAG_WITH_COUNTERS = (1 << IPSET_FLAG_BIT_WITH_COUNTERS),
	IPSET_FLAG_BIT_WITH_COMMENT = 4,
	IPSET_FLAG_WITH_COMMENT = (1 << IPSET_FLAG_BIT_WITH_COMMENT),
	IPSET_FLAG_CADT_MAX	= 15,
};

@@ -250,6 +256,14 @@ struct ip_set_req_get_set {
#define IP_SET_OP_GET_BYINDEX	0x00000007	/* Get set name by index */
/* Uses ip_set_req_get_set */

#define IP_SET_OP_GET_FNAME	0x00000008	/* Get set index and family */
struct ip_set_req_get_set_family {
	unsigned int op;
	unsigned int version;
	unsigned int family;
	union ip_set_name_index set;
};

#define IP_SET_OP_VERSION	0x00000100	/* Ask kernel version */
struct ip_set_req_version {
	unsigned int op;
Loading