Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next
Browse files Browse the repository at this point in the history
Pablo Neira Ayuso says:

====================
Netfilter updates for net-next

The following patchset contains Netfilter updates for your net-next
tree, they are:

1) Consolidate GRE protocol tracker using new GRE protocol definitions,
   patches from Gao Feng.

2) Properly parse continuation lines in SIP helper, update allowed
   characters in Call-ID header and allow tabs in SIP headers as
   specified by RFC3261, from Marco Angaroni.

3) Remove useless code in FTP conntrack helper, also from Gao Feng.

4) Add number generation expression for nf_tables, with random and
   incremental generators. This also includes specific offset to add
   to the result, patches from Laura Garcia Liebana. Liping Zhang
   follows with a fix to avoid a race in this new expression.

5) Fix new quota expression inversion logic, added in the previous
   pull request.

6) Missing validation of queue configuration in nft_queue, patch
   from Liping Zhang.

7) Remove unused ctl_table_path, as part of the deprecation of the
   ip_conntrack sysctl interface coming in the previous batch.
   Again from Liping Zhang.

8) Add offset attribute to nft_hash expression, so we can generate
   any output from a specific base offset. Moreover, check for
   possible overflow, patches from Laura Garcia.

9) Allow to invert dynamic set insertion from packet path, to check
   for overflows in case the set is full.

10) Revisit nft_set_pktinfo*() logic from nf_tables to ensure
    proper initialization of layer 4 protocol. Consolidate pktinfo
    structure initialization for bridge and netdev families.

11) Do not inconditionally drop IPv6 packets that we cannot parse
    transport protocol for ip6 and inet families, let the user decide
    on this via ruleset policy.

12) Get rid of gotos in __nf_ct_try_assign_helper().

13) Check for return value in register_netdevice_notifier() and
    nft_register_chain_type(), patches from Gao Feng.

14) Get rid of CONFIG_IP6_NF_IPTABLES dependency in nf_queue
    infrastructure that is common to nf_tables, from Liping Zhang.

15) Disable 'found' and 'searched' stats that are updates from the
    packet hotpath, not very useful these days.

16) Validate maximum value of u32 netlink attributes in nf_tables,
    this introduces nft_parse_u32_check(). From Laura Garcia.

17) Add missing code to integrate nft_queue with maps, patch from
    Liping Zhang. This also includes missing support ranges in
    nft_queue bridge family.

18) Fix check in nft_payload_fast_eval() that ensure that we don't
    go over the skbuff data boundary, from Liping Zhang.

19) Check if transport protocol is set from nf_tables tracing and
    payload expression. Again from Liping Zhang.

20) Use net_get_random_once() whenever possible, from Gao Feng.

21) Replace hardcoded value by sizeof() in xt_helper, from Gao Feng.

22) Remove superfluous check for found element in nft_lookup.

23) Simplify TCPMSS logic to check for minimum MTU, from Gao Feng.

24) Replace double linked list by single linked list in Netfilter
    core hook infrastructure, patchset from Aaron Conole. This
    includes several patches to prepare this update.

25) Fix wrong sequence adjustment of TCP RST with no ACK, from
    Gao Feng.

26) Relax check for direction attribute in nft_ct for layer 3 and 4
    protocol fields, from Liping Zhang.

27) Add new revision for hashlimit to support higher pps of upto 1
    million, from Vishwanath Pai.

28) Evict stale entries in nf_conntrack when reading entries from
    /proc/net/nf_conntrack, from Florian Westphal.

29) Fix transparent match for IPv6 request sockets, from Krisztian
    Kovacs.

30) Add new range expression for nf_tables.

31) Add missing code to support for flags in nft_log. Expose NF_LOG_*
    flags via uapi and use it from the generic logging infrastructure,
    instead of using xt specific definitions, from Liping Zhang.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Sep 26, 2016
2 parents fe0acb5 + f20fbc0 commit bce3414
Show file tree
Hide file tree
Showing 89 changed files with 1,381 additions and 680 deletions.
2 changes: 1 addition & 1 deletion include/linux/netdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -1799,7 +1799,7 @@ struct net_device {
#endif
struct netdev_queue __rcu *ingress_queue;
#ifdef CONFIG_NETFILTER_INGRESS
struct list_head nf_hooks_ingress;
struct nf_hook_entry __rcu *nf_hooks_ingress;
#endif

unsigned char broadcast[MAX_ADDR_LEN];
Expand Down
61 changes: 36 additions & 25 deletions include/linux/netfilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,34 @@ struct nf_hook_state {
struct net_device *out;
struct sock *sk;
struct net *net;
struct list_head *hook_list;
struct nf_hook_entry __rcu *hook_entries;
int (*okfn)(struct net *, struct sock *, struct sk_buff *);
};

typedef unsigned int nf_hookfn(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state);
struct nf_hook_ops {
struct list_head list;

/* User fills in from here down. */
nf_hookfn *hook;
struct net_device *dev;
void *priv;
u_int8_t pf;
unsigned int hooknum;
/* Hooks are ordered in ascending priority. */
int priority;
};

struct nf_hook_entry {
struct nf_hook_entry __rcu *next;
struct nf_hook_ops ops;
const struct nf_hook_ops *orig_ops;
};

static inline void nf_hook_state_init(struct nf_hook_state *p,
struct list_head *hook_list,
struct nf_hook_entry *hook_entry,
unsigned int hook,
int thresh, u_int8_t pf,
struct net_device *indev,
Expand All @@ -76,26 +98,11 @@ static inline void nf_hook_state_init(struct nf_hook_state *p,
p->out = outdev;
p->sk = sk;
p->net = net;
p->hook_list = hook_list;
RCU_INIT_POINTER(p->hook_entries, hook_entry);
p->okfn = okfn;
}

typedef unsigned int nf_hookfn(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state);

struct nf_hook_ops {
struct list_head list;

/* User fills in from here down. */
nf_hookfn *hook;
struct net_device *dev;
void *priv;
u_int8_t pf;
unsigned int hooknum;
/* Hooks are ordered in ascending priority. */
int priority;
};

struct nf_sockopt_ops {
struct list_head list;
Expand Down Expand Up @@ -163,7 +170,8 @@ static inline int nf_hook_thresh(u_int8_t pf, unsigned int hook,
int (*okfn)(struct net *, struct sock *, struct sk_buff *),
int thresh)
{
struct list_head *hook_list;
struct nf_hook_entry *hook_head;
int ret = 1;

#ifdef HAVE_JUMP_LABEL
if (__builtin_constant_p(pf) &&
Expand All @@ -172,16 +180,19 @@ static inline int nf_hook_thresh(u_int8_t pf, unsigned int hook,
return 1;
#endif

hook_list = &net->nf.hooks[pf][hook];

if (!list_empty(hook_list)) {
rcu_read_lock();
hook_head = rcu_dereference(net->nf.hooks[pf][hook]);
if (hook_head) {
struct nf_hook_state state;

nf_hook_state_init(&state, hook_list, hook, thresh,
nf_hook_state_init(&state, hook_head, hook, thresh,
pf, indev, outdev, sk, net, okfn);
return nf_hook_slow(skb, &state);

ret = nf_hook_slow(skb, &state);
}
return 1;
rcu_read_unlock();

return ret;
}

static inline int nf_hook(u_int8_t pf, unsigned int hook, struct net *net,
Expand Down
4 changes: 0 additions & 4 deletions include/linux/netfilter/nf_conntrack_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,9 @@
#include <uapi/linux/netfilter/nf_conntrack_common.h>

struct ip_conntrack_stat {
unsigned int searched;
unsigned int found;
unsigned int new;
unsigned int invalid;
unsigned int ignore;
unsigned int delete;
unsigned int delete_list;
unsigned int insert;
unsigned int insert_failed;
unsigned int drop;
Expand Down
64 changes: 2 additions & 62 deletions include/linux/netfilter/nf_conntrack_proto_gre.h
Original file line number Diff line number Diff line change
@@ -1,68 +1,8 @@
#ifndef _CONNTRACK_PROTO_GRE_H
#define _CONNTRACK_PROTO_GRE_H
#include <asm/byteorder.h>

/* GRE PROTOCOL HEADER */

/* GRE Version field */
#define GRE_VERSION_1701 0x0
#define GRE_VERSION_PPTP 0x1

/* GRE Protocol field */
#define GRE_PROTOCOL_PPTP 0x880B

/* GRE Flags */
#define GRE_FLAG_C 0x80
#define GRE_FLAG_R 0x40
#define GRE_FLAG_K 0x20
#define GRE_FLAG_S 0x10
#define GRE_FLAG_A 0x80

#define GRE_IS_C(f) ((f)&GRE_FLAG_C)
#define GRE_IS_R(f) ((f)&GRE_FLAG_R)
#define GRE_IS_K(f) ((f)&GRE_FLAG_K)
#define GRE_IS_S(f) ((f)&GRE_FLAG_S)
#define GRE_IS_A(f) ((f)&GRE_FLAG_A)

/* GRE is a mess: Four different standards */
struct gre_hdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u16 rec:3,
srr:1,
seq:1,
key:1,
routing:1,
csum:1,
version:3,
reserved:4,
ack:1;
#elif defined(__BIG_ENDIAN_BITFIELD)
__u16 csum:1,
routing:1,
key:1,
seq:1,
srr:1,
rec:3,
ack:1,
reserved:4,
version:3;
#else
#error "Adjust your <asm/byteorder.h> defines"
#endif
__be16 protocol;
};

/* modified GRE header for PPTP */
struct gre_hdr_pptp {
__u8 flags; /* bitfield */
__u8 version; /* should be GRE_VERSION_PPTP */
__be16 protocol; /* should be GRE_PROTOCOL_PPTP */
__be16 payload_len; /* size of ppp payload, not inc. gre header */
__be16 call_id; /* peer's call_id for this session */
__be32 seq; /* sequence number. Present if S==1 */
__be32 ack; /* seq number of highest packet received by */
/* sender in this session */
};
#include <net/gre.h>
#include <net/pptp.h>

struct nf_ct_gre {
unsigned int stream_timeout;
Expand Down
18 changes: 13 additions & 5 deletions include/linux/netfilter_ingress.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,30 @@ static inline bool nf_hook_ingress_active(const struct sk_buff *skb)
if (!static_key_false(&nf_hooks_needed[NFPROTO_NETDEV][NF_NETDEV_INGRESS]))
return false;
#endif
return !list_empty(&skb->dev->nf_hooks_ingress);
return rcu_access_pointer(skb->dev->nf_hooks_ingress);
}

/* caller must hold rcu_read_lock */
static inline int nf_hook_ingress(struct sk_buff *skb)
{
struct nf_hook_entry *e = rcu_dereference(skb->dev->nf_hooks_ingress);
struct nf_hook_state state;

nf_hook_state_init(&state, &skb->dev->nf_hooks_ingress,
NF_NETDEV_INGRESS, INT_MIN, NFPROTO_NETDEV,
skb->dev, NULL, NULL, dev_net(skb->dev), NULL);
/* Must recheck the ingress hook head, in the event it became NULL
* after the check in nf_hook_ingress_active evaluated to true.
*/
if (unlikely(!e))
return 0;

nf_hook_state_init(&state, e, NF_NETDEV_INGRESS, INT_MIN,
NFPROTO_NETDEV, skb->dev, NULL, NULL,
dev_net(skb->dev), NULL);
return nf_hook_slow(skb, &state);
}

static inline void nf_hook_ingress_init(struct net_device *dev)
{
INIT_LIST_HEAD(&dev->nf_hooks_ingress);
RCU_INIT_POINTER(dev->nf_hooks_ingress, NULL);
}
#else /* CONFIG_NETFILTER_INGRESS */
static inline int nf_hook_ingress_active(struct sk_buff *skb)
Expand Down
6 changes: 6 additions & 0 deletions include/net/netfilter/br_netfilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ static inline struct nf_bridge_info *nf_bridge_alloc(struct sk_buff *skb)

void nf_bridge_update_protocol(struct sk_buff *skb);

int br_nf_hook_thresh(unsigned int hook, struct net *net, struct sock *sk,
struct sk_buff *skb, struct net_device *indev,
struct net_device *outdev,
int (*okfn)(struct net *, struct sock *,
struct sk_buff *));

static inline struct nf_bridge_info *
nf_bridge_info_get(const struct sk_buff *skb)
{
Expand Down
4 changes: 0 additions & 4 deletions include/net/netfilter/nf_conntrack_l3proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,6 @@ struct nf_conntrack_l3proto {

size_t nla_size;

#ifdef CONFIG_SYSCTL
const char *ctl_table_path;
#endif /* CONFIG_SYSCTL */

/* Init l3proto pernet data */
int (*init_net)(struct net *net);

Expand Down
11 changes: 3 additions & 8 deletions include/net/netfilter/nf_log.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,10 @@
#define _NF_LOG_H

#include <linux/netfilter.h>
#include <linux/netfilter/nf_log.h>

/* those NF_LOG_* defines and struct nf_loginfo are legacy definitios that will
* disappear once iptables is replaced with pkttables. Please DO NOT use them
* for any new code! */
#define NF_LOG_TCPSEQ 0x01 /* Log TCP sequence numbers */
#define NF_LOG_TCPOPT 0x02 /* Log TCP options */
#define NF_LOG_IPOPT 0x04 /* Log IP options */
#define NF_LOG_UID 0x08 /* Log UID owning local socket */
#define NF_LOG_MASK 0x0f
/* Log tcp sequence, tcp options, ip options and uid owning local socket */
#define NF_LOG_DEFAULT_MASK 0x0f

/* This flag indicates that copy_len field in nf_loginfo is set */
#define NF_LOG_F_COPY_LEN 0x1
Expand Down
69 changes: 47 additions & 22 deletions include/net/netfilter/nf_queue.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ struct nf_queue_entry {
struct sk_buff *skb;
unsigned int id;

struct nf_hook_ops *elem;
struct nf_hook_state state;
u16 size; /* sizeof(entry) + saved route keys */

Expand All @@ -22,10 +21,10 @@ struct nf_queue_entry {

/* Packet queuing */
struct nf_queue_handler {
int (*outfn)(struct nf_queue_entry *entry,
unsigned int queuenum);
void (*nf_hook_drop)(struct net *net,
struct nf_hook_ops *ops);
int (*outfn)(struct nf_queue_entry *entry,
unsigned int queuenum);
void (*nf_hook_drop)(struct net *net,
const struct nf_hook_entry *hooks);
};

void nf_register_queue_handler(struct net *net, const struct nf_queue_handler *qh);
Expand All @@ -41,23 +40,19 @@ static inline void init_hashrandom(u32 *jhash_initval)
*jhash_initval = prandom_u32();
}

static inline u32 hash_v4(const struct sk_buff *skb, u32 jhash_initval)
static inline u32 hash_v4(const struct iphdr *iph, u32 initval)
{
const struct iphdr *iph = ip_hdr(skb);

/* packets in either direction go into same queue */
if ((__force u32)iph->saddr < (__force u32)iph->daddr)
return jhash_3words((__force u32)iph->saddr,
(__force u32)iph->daddr, iph->protocol, jhash_initval);
(__force u32)iph->daddr, iph->protocol, initval);

return jhash_3words((__force u32)iph->daddr,
(__force u32)iph->saddr, iph->protocol, jhash_initval);
(__force u32)iph->saddr, iph->protocol, initval);
}

#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
static inline u32 hash_v6(const struct sk_buff *skb, u32 jhash_initval)
static inline u32 hash_v6(const struct ipv6hdr *ip6h, u32 initval)
{
const struct ipv6hdr *ip6h = ipv6_hdr(skb);
u32 a, b, c;

if ((__force u32)ip6h->saddr.s6_addr32[3] <
Expand All @@ -75,20 +70,50 @@ static inline u32 hash_v6(const struct sk_buff *skb, u32 jhash_initval)
else
c = (__force u32) ip6h->daddr.s6_addr32[1];

return jhash_3words(a, b, c, jhash_initval);
return jhash_3words(a, b, c, initval);
}

static inline u32 hash_bridge(const struct sk_buff *skb, u32 initval)
{
struct ipv6hdr *ip6h, _ip6h;
struct iphdr *iph, _iph;

switch (eth_hdr(skb)->h_proto) {
case htons(ETH_P_IP):
iph = skb_header_pointer(skb, skb_network_offset(skb),
sizeof(*iph), &_iph);
if (iph)
return hash_v4(iph, initval);
break;
case htons(ETH_P_IPV6):
ip6h = skb_header_pointer(skb, skb_network_offset(skb),
sizeof(*ip6h), &_ip6h);
if (ip6h)
return hash_v6(ip6h, initval);
break;
}

return 0;
}
#endif

static inline u32
nfqueue_hash(const struct sk_buff *skb, u16 queue, u16 queues_total, u8 family,
u32 jhash_initval)
u32 initval)
{
if (family == NFPROTO_IPV4)
queue += ((u64) hash_v4(skb, jhash_initval) * queues_total) >> 32;
#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
else if (family == NFPROTO_IPV6)
queue += ((u64) hash_v6(skb, jhash_initval) * queues_total) >> 32;
#endif
switch (family) {
case NFPROTO_IPV4:
queue += reciprocal_scale(hash_v4(ip_hdr(skb), initval),
queues_total);
break;
case NFPROTO_IPV6:
queue += reciprocal_scale(hash_v6(ipv6_hdr(skb), initval),
queues_total);
break;
case NFPROTO_BRIDGE:
queue += reciprocal_scale(hash_bridge(skb, initval),
queues_total);
break;
}

return queue;
}
Expand Down
Loading

0 comments on commit bce3414

Please sign in to comment.