Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next
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: David S. Miller <davem@davemloft.net>
This commit is contained in:
@@ -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
include/linux/netfilter/ipset/ip_set_comment.h
Normal file
57
include/linux/netfilter/ipset/ip_set_comment.h
Normal file
@@ -0,0 +1,57 @@
|
||||
#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
|
||||
@@ -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)
|
||||
|
||||
@@ -107,55 +107,64 @@ enum sdp_header_types {
|
||||
SDP_HDR_MEDIA,
|
||||
};
|
||||
|
||||
extern unsigned int (*nf_nat_sip_hook)(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,
|
||||
unsigned int protoff, s16 off);
|
||||
extern unsigned int (*nf_nat_sip_expect_hook)(struct sk_buff *skb,
|
||||
unsigned int protoff,
|
||||
unsigned int dataoff,
|
||||
const char **dptr,
|
||||
unsigned int *datalen,
|
||||
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 protoff,
|
||||
unsigned int dataoff,
|
||||
const char **dptr,
|
||||
unsigned int *datalen,
|
||||
unsigned int sdpoff,
|
||||
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 protoff,
|
||||
unsigned int dataoff,
|
||||
const char **dptr,
|
||||
unsigned int *datalen,
|
||||
unsigned int matchoff,
|
||||
unsigned int matchlen,
|
||||
u_int16_t port);
|
||||
extern unsigned int (*nf_nat_sdp_session_hook)(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 protoff,
|
||||
unsigned int dataoff,
|
||||
const char **dptr,
|
||||
unsigned int *datalen,
|
||||
struct nf_conntrack_expect *rtp_exp,
|
||||
struct nf_conntrack_expect *rtcp_exp,
|
||||
unsigned int mediaoff,
|
||||
unsigned int medialen,
|
||||
union nf_inet_addr *rtp_addr);
|
||||
struct nf_nat_sip_hooks {
|
||||
unsigned int (*msg)(struct sk_buff *skb,
|
||||
unsigned int protoff,
|
||||
unsigned int dataoff,
|
||||
const char **dptr,
|
||||
unsigned int *datalen);
|
||||
|
||||
void (*seq_adjust)(struct sk_buff *skb,
|
||||
unsigned int protoff, s16 off);
|
||||
|
||||
unsigned int (*expect)(struct sk_buff *skb,
|
||||
unsigned int protoff,
|
||||
unsigned int dataoff,
|
||||
const char **dptr,
|
||||
unsigned int *datalen,
|
||||
struct nf_conntrack_expect *exp,
|
||||
unsigned int matchoff,
|
||||
unsigned int matchlen);
|
||||
|
||||
unsigned int (*sdp_addr)(struct sk_buff *skb,
|
||||
unsigned int protoff,
|
||||
unsigned int dataoff,
|
||||
const char **dptr,
|
||||
unsigned int *datalen,
|
||||
unsigned int sdpoff,
|
||||
enum sdp_header_types type,
|
||||
enum sdp_header_types term,
|
||||
const union nf_inet_addr *addr);
|
||||
|
||||
unsigned int (*sdp_port)(struct sk_buff *skb,
|
||||
unsigned int protoff,
|
||||
unsigned int dataoff,
|
||||
const char **dptr,
|
||||
unsigned int *datalen,
|
||||
unsigned int matchoff,
|
||||
unsigned int matchlen,
|
||||
u_int16_t port);
|
||||
|
||||
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);
|
||||
|
||||
unsigned int (*sdp_media)(struct sk_buff *skb,
|
||||
unsigned int protoff,
|
||||
unsigned int dataoff,
|
||||
const char **dptr,
|
||||
unsigned int *datalen,
|
||||
struct nf_conntrack_expect *rtp_exp,
|
||||
struct nf_conntrack_expect *rtcp_exp,
|
||||
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,
|
||||
|
||||
Reference in New Issue
Block a user