Commit 5fe8e519 authored by David S. Miller's avatar David S. Miller

Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next

Pablo Neira Ayuso says:

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

The following patchset contains Netfilter updates for net-next:

1) Support for SCTP chunks matching on nf_tables, from Phil Sutter.

2) Skip LDMXCSR, we don't need a valid MXCSR state. From Stefano Brivio.

3) CONFIG_RETPOLINE for nf_tables set lookups, from Florian Westphal.

4) A few Kconfig leading spaces removal, from Juerg Haefliger.

5) Remove spinlock from xt_limit, from Jason Baron.

6) Remove useless initialization in xt_CT, oneliner from Yang Li.

7) Tree-wide replacement of netlink_unicast() by nfnetlink_unicast().

8) Reduce footprint of several structures: xt_action_param,
   nft_pktinfo and nf_hook_state, from Florian.

10) Add nft_thoff() and nft_sk() helpers and use them, also from Florian.

11) Fix documentation in nf_tables pipapo avx2, from Florian Westphal.

12) Fix clang-12 fmt string warnings, also from Florian.
====================
parents 92c35cfd 8a1c08ad
...@@ -65,8 +65,8 @@ struct nf_hook_ops; ...@@ -65,8 +65,8 @@ struct nf_hook_ops;
struct sock; struct sock;
struct nf_hook_state { struct nf_hook_state {
unsigned int hook; u8 hook;
u_int8_t pf; u8 pf;
struct net_device *in; struct net_device *in;
struct net_device *out; struct net_device *out;
struct sock *sk; struct sock *sk;
......
...@@ -36,8 +36,8 @@ struct xt_action_param { ...@@ -36,8 +36,8 @@ struct xt_action_param {
const void *matchinfo, *targinfo; const void *matchinfo, *targinfo;
}; };
const struct nf_hook_state *state; const struct nf_hook_state *state;
int fragoff;
unsigned int thoff; unsigned int thoff;
u16 fragoff;
bool hotdrop; bool hotdrop;
}; };
......
...@@ -23,35 +23,46 @@ struct module; ...@@ -23,35 +23,46 @@ struct module;
struct nft_pktinfo { struct nft_pktinfo {
struct sk_buff *skb; struct sk_buff *skb;
const struct nf_hook_state *state;
bool tprot_set; bool tprot_set;
u8 tprot; u8 tprot;
/* for x_tables compatibility */ u16 fragoff;
struct xt_action_param xt; unsigned int thoff;
}; };
static inline struct sock *nft_sk(const struct nft_pktinfo *pkt)
{
return pkt->state->sk;
}
static inline unsigned int nft_thoff(const struct nft_pktinfo *pkt)
{
return pkt->thoff;
}
static inline struct net *nft_net(const struct nft_pktinfo *pkt) static inline struct net *nft_net(const struct nft_pktinfo *pkt)
{ {
return pkt->xt.state->net; return pkt->state->net;
} }
static inline unsigned int nft_hook(const struct nft_pktinfo *pkt) static inline unsigned int nft_hook(const struct nft_pktinfo *pkt)
{ {
return pkt->xt.state->hook; return pkt->state->hook;
} }
static inline u8 nft_pf(const struct nft_pktinfo *pkt) static inline u8 nft_pf(const struct nft_pktinfo *pkt)
{ {
return pkt->xt.state->pf; return pkt->state->pf;
} }
static inline const struct net_device *nft_in(const struct nft_pktinfo *pkt) static inline const struct net_device *nft_in(const struct nft_pktinfo *pkt)
{ {
return pkt->xt.state->in; return pkt->state->in;
} }
static inline const struct net_device *nft_out(const struct nft_pktinfo *pkt) static inline const struct net_device *nft_out(const struct nft_pktinfo *pkt)
{ {
return pkt->xt.state->out; return pkt->state->out;
} }
static inline void nft_set_pktinfo(struct nft_pktinfo *pkt, static inline void nft_set_pktinfo(struct nft_pktinfo *pkt,
...@@ -59,16 +70,15 @@ static inline void nft_set_pktinfo(struct nft_pktinfo *pkt, ...@@ -59,16 +70,15 @@ static inline void nft_set_pktinfo(struct nft_pktinfo *pkt,
const struct nf_hook_state *state) const struct nf_hook_state *state)
{ {
pkt->skb = skb; pkt->skb = skb;
pkt->xt.state = state; pkt->state = state;
} }
static inline void nft_set_pktinfo_unspec(struct nft_pktinfo *pkt, static inline void nft_set_pktinfo_unspec(struct nft_pktinfo *pkt)
struct sk_buff *skb)
{ {
pkt->tprot_set = false; pkt->tprot_set = false;
pkt->tprot = 0; pkt->tprot = 0;
pkt->xt.thoff = 0; pkt->thoff = 0;
pkt->xt.fragoff = 0; pkt->fragoff = 0;
} }
/** /**
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#define _NET_NF_TABLES_CORE_H #define _NET_NF_TABLES_CORE_H
#include <net/netfilter/nf_tables.h> #include <net/netfilter/nf_tables.h>
#include <linux/indirect_call_wrapper.h>
extern struct nft_expr_type nft_imm_type; extern struct nft_expr_type nft_imm_type;
extern struct nft_expr_type nft_cmp_type; extern struct nft_expr_type nft_cmp_type;
...@@ -88,6 +89,36 @@ extern const struct nft_set_type nft_set_bitmap_type; ...@@ -88,6 +89,36 @@ extern const struct nft_set_type nft_set_bitmap_type;
extern const struct nft_set_type nft_set_pipapo_type; extern const struct nft_set_type nft_set_pipapo_type;
extern const struct nft_set_type nft_set_pipapo_avx2_type; extern const struct nft_set_type nft_set_pipapo_avx2_type;
#ifdef CONFIG_RETPOLINE
bool nft_rhash_lookup(const struct net *net, const struct nft_set *set,
const u32 *key, const struct nft_set_ext **ext);
bool nft_rbtree_lookup(const struct net *net, const struct nft_set *set,
const u32 *key, const struct nft_set_ext **ext);
bool nft_bitmap_lookup(const struct net *net, const struct nft_set *set,
const u32 *key, const struct nft_set_ext **ext);
bool nft_hash_lookup_fast(const struct net *net,
const struct nft_set *set,
const u32 *key, const struct nft_set_ext **ext);
bool nft_hash_lookup(const struct net *net, const struct nft_set *set,
const u32 *key, const struct nft_set_ext **ext);
bool nft_set_do_lookup(const struct net *net, const struct nft_set *set,
const u32 *key, const struct nft_set_ext **ext);
#else
static inline bool
nft_set_do_lookup(const struct net *net, const struct nft_set *set,
const u32 *key, const struct nft_set_ext **ext)
{
return set->ops->lookup(net, set, key, ext);
}
#endif
/* called from nft_pipapo_avx2.c */
bool nft_pipapo_lookup(const struct net *net, const struct nft_set *set,
const u32 *key, const struct nft_set_ext **ext);
/* called from nft_set_pipapo.c */
bool nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set,
const u32 *key, const struct nft_set_ext **ext);
struct nft_expr; struct nft_expr;
struct nft_regs; struct nft_regs;
struct nft_pktinfo; struct nft_pktinfo;
......
...@@ -5,26 +5,24 @@ ...@@ -5,26 +5,24 @@
#include <net/netfilter/nf_tables.h> #include <net/netfilter/nf_tables.h>
#include <net/ip.h> #include <net/ip.h>
static inline void nft_set_pktinfo_ipv4(struct nft_pktinfo *pkt, static inline void nft_set_pktinfo_ipv4(struct nft_pktinfo *pkt)
struct sk_buff *skb)
{ {
struct iphdr *ip; struct iphdr *ip;
ip = ip_hdr(pkt->skb); ip = ip_hdr(pkt->skb);
pkt->tprot_set = true; pkt->tprot_set = true;
pkt->tprot = ip->protocol; pkt->tprot = ip->protocol;
pkt->xt.thoff = ip_hdrlen(pkt->skb); pkt->thoff = ip_hdrlen(pkt->skb);
pkt->xt.fragoff = ntohs(ip->frag_off) & IP_OFFSET; pkt->fragoff = ntohs(ip->frag_off) & IP_OFFSET;
} }
static inline int __nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt, static inline int __nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt)
struct sk_buff *skb)
{ {
struct iphdr *iph, _iph; struct iphdr *iph, _iph;
u32 len, thoff; u32 len, thoff;
iph = skb_header_pointer(skb, skb_network_offset(skb), sizeof(*iph), iph = skb_header_pointer(pkt->skb, skb_network_offset(pkt->skb),
&_iph); sizeof(*iph), &_iph);
if (!iph) if (!iph)
return -1; return -1;
...@@ -33,42 +31,40 @@ static inline int __nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt, ...@@ -33,42 +31,40 @@ static inline int __nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt,
len = ntohs(iph->tot_len); len = ntohs(iph->tot_len);
thoff = iph->ihl * 4; thoff = iph->ihl * 4;
if (skb->len < len) if (pkt->skb->len < len)
return -1; return -1;
else if (len < thoff) else if (len < thoff)
return -1; return -1;
pkt->tprot_set = true; pkt->tprot_set = true;
pkt->tprot = iph->protocol; pkt->tprot = iph->protocol;
pkt->xt.thoff = thoff; pkt->thoff = thoff;
pkt->xt.fragoff = ntohs(iph->frag_off) & IP_OFFSET; pkt->fragoff = ntohs(iph->frag_off) & IP_OFFSET;
return 0; return 0;
} }
static inline void nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt, static inline void nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt)
struct sk_buff *skb)
{ {
if (__nft_set_pktinfo_ipv4_validate(pkt, skb) < 0) if (__nft_set_pktinfo_ipv4_validate(pkt) < 0)
nft_set_pktinfo_unspec(pkt, skb); nft_set_pktinfo_unspec(pkt);
} }
static inline int nft_set_pktinfo_ipv4_ingress(struct nft_pktinfo *pkt, static inline int nft_set_pktinfo_ipv4_ingress(struct nft_pktinfo *pkt)
struct sk_buff *skb)
{ {
struct iphdr *iph; struct iphdr *iph;
u32 len, thoff; u32 len, thoff;
if (!pskb_may_pull(skb, sizeof(*iph))) if (!pskb_may_pull(pkt->skb, sizeof(*iph)))
return -1; return -1;
iph = ip_hdr(skb); iph = ip_hdr(pkt->skb);
if (iph->ihl < 5 || iph->version != 4) if (iph->ihl < 5 || iph->version != 4)
goto inhdr_error; goto inhdr_error;
len = ntohs(iph->tot_len); len = ntohs(iph->tot_len);
thoff = iph->ihl * 4; thoff = iph->ihl * 4;
if (skb->len < len) { if (pkt->skb->len < len) {
__IP_INC_STATS(nft_net(pkt), IPSTATS_MIB_INTRUNCATEDPKTS); __IP_INC_STATS(nft_net(pkt), IPSTATS_MIB_INTRUNCATEDPKTS);
return -1; return -1;
} else if (len < thoff) { } else if (len < thoff) {
...@@ -77,8 +73,8 @@ static inline int nft_set_pktinfo_ipv4_ingress(struct nft_pktinfo *pkt, ...@@ -77,8 +73,8 @@ static inline int nft_set_pktinfo_ipv4_ingress(struct nft_pktinfo *pkt,
pkt->tprot_set = true; pkt->tprot_set = true;
pkt->tprot = iph->protocol; pkt->tprot = iph->protocol;
pkt->xt.thoff = thoff; pkt->thoff = thoff;
pkt->xt.fragoff = ntohs(iph->frag_off) & IP_OFFSET; pkt->fragoff = ntohs(iph->frag_off) & IP_OFFSET;
return 0; return 0;
......
...@@ -6,8 +6,7 @@ ...@@ -6,8 +6,7 @@
#include <net/ipv6.h> #include <net/ipv6.h>
#include <net/netfilter/nf_tables.h> #include <net/netfilter/nf_tables.h>
static inline void nft_set_pktinfo_ipv6(struct nft_pktinfo *pkt, static inline void nft_set_pktinfo_ipv6(struct nft_pktinfo *pkt)
struct sk_buff *skb)
{ {
unsigned int flags = IP6_FH_F_AUTH; unsigned int flags = IP6_FH_F_AUTH;
int protohdr, thoff = 0; int protohdr, thoff = 0;
...@@ -15,18 +14,17 @@ static inline void nft_set_pktinfo_ipv6(struct nft_pktinfo *pkt, ...@@ -15,18 +14,17 @@ static inline void nft_set_pktinfo_ipv6(struct nft_pktinfo *pkt,
protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, &flags); protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, &flags);
if (protohdr < 0) { if (protohdr < 0) {
nft_set_pktinfo_unspec(pkt, skb); nft_set_pktinfo_unspec(pkt);
return; return;
} }
pkt->tprot_set = true; pkt->tprot_set = true;
pkt->tprot = protohdr; pkt->tprot = protohdr;
pkt->xt.thoff = thoff; pkt->thoff = thoff;
pkt->xt.fragoff = frag_off; pkt->fragoff = frag_off;
} }
static inline int __nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt, static inline int __nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt)
struct sk_buff *skb)
{ {
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
unsigned int flags = IP6_FH_F_AUTH; unsigned int flags = IP6_FH_F_AUTH;
...@@ -36,8 +34,8 @@ static inline int __nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt, ...@@ -36,8 +34,8 @@ static inline int __nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt,
int protohdr; int protohdr;
u32 pkt_len; u32 pkt_len;
ip6h = skb_header_pointer(skb, skb_network_offset(skb), sizeof(*ip6h), ip6h = skb_header_pointer(pkt->skb, skb_network_offset(pkt->skb),
&_ip6h); sizeof(*ip6h), &_ip6h);
if (!ip6h) if (!ip6h)
return -1; return -1;
...@@ -45,7 +43,7 @@ static inline int __nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt, ...@@ -45,7 +43,7 @@ static inline int __nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt,
return -1; return -1;
pkt_len = ntohs(ip6h->payload_len); pkt_len = ntohs(ip6h->payload_len);
if (pkt_len + sizeof(*ip6h) > skb->len) if (pkt_len + sizeof(*ip6h) > pkt->skb->len)
return -1; return -1;
protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, &flags); protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, &flags);
...@@ -54,8 +52,8 @@ static inline int __nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt, ...@@ -54,8 +52,8 @@ static inline int __nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt,
pkt->tprot_set = true; pkt->tprot_set = true;
pkt->tprot = protohdr; pkt->tprot = protohdr;
pkt->xt.thoff = thoff; pkt->thoff = thoff;
pkt->xt.fragoff = frag_off; pkt->fragoff = frag_off;
return 0; return 0;
#else #else
...@@ -63,15 +61,13 @@ static inline int __nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt, ...@@ -63,15 +61,13 @@ static inline int __nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt,
#endif #endif
} }
static inline void nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt, static inline void nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt)
struct sk_buff *skb)
{ {
if (__nft_set_pktinfo_ipv6_validate(pkt, skb) < 0) if (__nft_set_pktinfo_ipv6_validate(pkt) < 0)
nft_set_pktinfo_unspec(pkt, skb); nft_set_pktinfo_unspec(pkt);
} }
static inline int nft_set_pktinfo_ipv6_ingress(struct nft_pktinfo *pkt, static inline int nft_set_pktinfo_ipv6_ingress(struct nft_pktinfo *pkt)
struct sk_buff *skb)
{ {
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
unsigned int flags = IP6_FH_F_AUTH; unsigned int flags = IP6_FH_F_AUTH;
...@@ -82,15 +78,15 @@ static inline int nft_set_pktinfo_ipv6_ingress(struct nft_pktinfo *pkt, ...@@ -82,15 +78,15 @@ static inline int nft_set_pktinfo_ipv6_ingress(struct nft_pktinfo *pkt,
int protohdr; int protohdr;
u32 pkt_len; u32 pkt_len;
if (!pskb_may_pull(skb, sizeof(*ip6h))) if (!pskb_may_pull(pkt->skb, sizeof(*ip6h)))
return -1; return -1;
ip6h = ipv6_hdr(skb); ip6h = ipv6_hdr(pkt->skb);
if (ip6h->version != 6) if (ip6h->version != 6)
goto inhdr_error; goto inhdr_error;
pkt_len = ntohs(ip6h->payload_len); pkt_len = ntohs(ip6h->payload_len);
if (pkt_len + sizeof(*ip6h) > skb->len) { if (pkt_len + sizeof(*ip6h) > pkt->skb->len) {
idev = __in6_dev_get(nft_in(pkt)); idev = __in6_dev_get(nft_in(pkt));
__IP6_INC_STATS(nft_net(pkt), idev, IPSTATS_MIB_INTRUNCATEDPKTS); __IP6_INC_STATS(nft_net(pkt), idev, IPSTATS_MIB_INTRUNCATEDPKTS);
return -1; return -1;
...@@ -102,8 +98,8 @@ static inline int nft_set_pktinfo_ipv6_ingress(struct nft_pktinfo *pkt, ...@@ -102,8 +98,8 @@ static inline int nft_set_pktinfo_ipv6_ingress(struct nft_pktinfo *pkt,
pkt->tprot_set = true; pkt->tprot_set = true;
pkt->tprot = protohdr; pkt->tprot = protohdr;
pkt->xt.thoff = thoff; pkt->thoff = thoff;
pkt->xt.fragoff = frag_off; pkt->fragoff = frag_off;
return 0; return 0;
......
...@@ -813,11 +813,13 @@ enum nft_exthdr_flags { ...@@ -813,11 +813,13 @@ enum nft_exthdr_flags {
* @NFT_EXTHDR_OP_IPV6: match against ipv6 extension headers * @NFT_EXTHDR_OP_IPV6: match against ipv6 extension headers
* @NFT_EXTHDR_OP_TCP: match against tcp options * @NFT_EXTHDR_OP_TCP: match against tcp options
* @NFT_EXTHDR_OP_IPV4: match against ipv4 options * @NFT_EXTHDR_OP_IPV4: match against ipv4 options
* @NFT_EXTHDR_OP_SCTP: match against sctp chunks
*/ */
enum nft_exthdr_op { enum nft_exthdr_op {
NFT_EXTHDR_OP_IPV6, NFT_EXTHDR_OP_IPV6,
NFT_EXTHDR_OP_TCPOPT, NFT_EXTHDR_OP_TCPOPT,
NFT_EXTHDR_OP_IPV4, NFT_EXTHDR_OP_IPV4,
NFT_EXTHDR_OP_SCTP,
__NFT_EXTHDR_OP_MAX __NFT_EXTHDR_OP_MAX
}; };
#define NFT_EXTHDR_OP_MAX (__NFT_EXTHDR_OP_MAX - 1) #define NFT_EXTHDR_OP_MAX (__NFT_EXTHDR_OP_MAX - 1)
......
...@@ -27,7 +27,7 @@ static void nft_reject_ipv4_eval(const struct nft_expr *expr, ...@@ -27,7 +27,7 @@ static void nft_reject_ipv4_eval(const struct nft_expr *expr,
nf_send_unreach(pkt->skb, priv->icmp_code, nft_hook(pkt)); nf_send_unreach(pkt->skb, priv->icmp_code, nft_hook(pkt));
break; break;
case NFT_REJECT_TCP_RST: case NFT_REJECT_TCP_RST:
nf_send_reset(nft_net(pkt), pkt->xt.state->sk, pkt->skb, nf_send_reset(nft_net(pkt), nft_sk(pkt), pkt->skb,
nft_hook(pkt)); nft_hook(pkt));
break; break;
default: default:
......
...@@ -51,7 +51,7 @@ ip6_packet_match(const struct sk_buff *skb, ...@@ -51,7 +51,7 @@ ip6_packet_match(const struct sk_buff *skb,
const char *outdev, const char *outdev,
const struct ip6t_ip6 *ip6info, const struct ip6t_ip6 *ip6info,
unsigned int *protoff, unsigned int *protoff,
int *fragoff, bool *hotdrop) u16 *fragoff, bool *hotdrop)
{ {
unsigned long ret; unsigned long ret;
const struct ipv6hdr *ipv6 = ipv6_hdr(skb); const struct ipv6hdr *ipv6 = ipv6_hdr(skb);
......
...@@ -28,7 +28,7 @@ static void nft_reject_ipv6_eval(const struct nft_expr *expr, ...@@ -28,7 +28,7 @@ static void nft_reject_ipv6_eval(const struct nft_expr *expr,
nft_hook(pkt)); nft_hook(pkt));
break; break;
case NFT_REJECT_TCP_RST: case NFT_REJECT_TCP_RST:
nf_send_reset6(nft_net(pkt), pkt->xt.state->sk, pkt->skb, nf_send_reset6(nft_net(pkt), nft_sk(pkt), pkt->skb,
nft_hook(pkt)); nft_hook(pkt));
break; break;
default: default:
......
...@@ -1685,8 +1685,8 @@ static const struct nla_policy ip_set_adt_policy[IPSET_ATTR_CMD_MAX + 1] = { ...@@ -1685,8 +1685,8 @@ static const struct nla_policy ip_set_adt_policy[IPSET_ATTR_CMD_MAX + 1] = {
}; };
static int static int
call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set, call_ad(struct net *net, struct sock *ctnl, struct sk_buff *skb,
struct nlattr *tb[], enum ipset_adt adt, struct ip_set *set, struct nlattr *tb[], enum ipset_adt adt,
u32 flags, bool use_lineno) u32 flags, bool use_lineno)
{ {
int ret; int ret;
...@@ -1738,8 +1738,7 @@ call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set, ...@@ -1738,8 +1738,7 @@ call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set,
*errline = lineno; *errline = lineno;
netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid, nfnetlink_unicast(skb2, net, NETLINK_CB(skb).portid);
MSG_DONTWAIT);
/* Signal netlink not to send its ACK/errmsg. */ /* Signal netlink not to send its ACK/errmsg. */
return -EINTR; return -EINTR;
} }
...@@ -1783,7 +1782,7 @@ static int ip_set_ad(struct net *net, struct sock *ctnl, ...@@ -1783,7 +1782,7 @@ static int ip_set_ad(struct net *net, struct sock *ctnl,
attr[IPSET_ATTR_DATA], attr[IPSET_ATTR_DATA],
set->type->adt_policy, NULL)) set->type->adt_policy, NULL))
return -IPSET_ERR_PROTOCOL; return -IPSET_ERR_PROTOCOL;
ret = call_ad(ctnl, skb, set, tb, adt, flags, ret = call_ad(net, ctnl, skb, set, tb, adt, flags,
use_lineno); use_lineno);
} else { } else {
int nla_rem; int nla_rem;
...@@ -1794,7 +1793,7 @@ static int ip_set_ad(struct net *net, struct sock *ctnl, ...@@ -1794,7 +1793,7 @@ static int ip_set_ad(struct net *net, struct sock *ctnl,
nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, nla, nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, nla,
set->type->adt_policy, NULL)) set->type->adt_policy, NULL))
return -IPSET_ERR_PROTOCOL; return -IPSET_ERR_PROTOCOL;
ret = call_ad(ctnl, skb, set, tb, adt, ret = call_ad(net, ctnl, skb, set, tb, adt,
flags, use_lineno); flags, use_lineno);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -1859,7 +1858,6 @@ static int ip_set_header(struct sk_buff *skb, const struct nfnl_info *info, ...@@ -1859,7 +1858,6 @@ static int ip_set_header(struct sk_buff *skb, const struct nfnl_info *info,
const struct ip_set *set; const struct ip_set *set;
struct sk_buff *skb2; struct sk_buff *skb2;
struct nlmsghdr *nlh2; struct nlmsghdr *nlh2;
int ret = 0;
if (unlikely(protocol_min_failed(attr) || if (unlikely(protocol_min_failed(attr) ||
!attr[IPSET_ATTR_SETNAME])) !attr[IPSET_ATTR_SETNAME]))
...@@ -1885,12 +1883,7 @@ static int ip_set_header(struct sk_buff *skb, const struct nfnl_info *info, ...@@ -1885,12 +1883,7 @@ static int ip_set_header(struct sk_buff *skb, const struct nfnl_info *info,
goto nla_put_failure; goto nla_put_failure;
nlmsg_end(skb2, nlh2); nlmsg_end(skb2, nlh2);
ret = netlink_unicast(info->sk, skb2, NETLINK_CB(skb).portid, return nfnetlink_unicast(skb2, info->net, NETLINK_CB(skb).portid);
MSG_DONTWAIT);
if (ret < 0)
return ret;
return 0;
nla_put_failure: nla_put_failure:
nlmsg_cancel(skb2, nlh2); nlmsg_cancel(skb2, nlh2);
...@@ -1945,12 +1938,7 @@ static int ip_set_type(struct sk_buff *skb, const struct nfnl_info *info, ...@@ -1945,12 +1938,7 @@ static int ip_set_type(struct sk_buff *skb, const struct nfnl_info *info,
nlmsg_end(skb2, nlh2); nlmsg_end(skb2, nlh2);
pr_debug("Send TYPE, nlmsg_len: %u\n", nlh2->nlmsg_len); pr_debug("Send TYPE, nlmsg_len: %u\n", nlh2->nlmsg_len);
ret = netlink_unicast(info->sk, skb2, NETLINK_CB(skb).portid, return nfnetlink_unicast(skb2, info->net, NETLINK_CB(skb).portid);
MSG_DONTWAIT);
if (ret < 0)
return ret;
return 0;
nla_put_failure: nla_put_failure:
nlmsg_cancel(skb2, nlh2); nlmsg_cancel(skb2, nlh2);
...@@ -1971,7 +1959,6 @@ static int ip_set_protocol(struct sk_buff *skb, const struct nfnl_info *info, ...@@ -1971,7 +1959,6 @@ static int ip_set_protocol(struct sk_buff *skb, const struct nfnl_info *info,
{ {
struct sk_buff *skb2; struct sk_buff *skb2;
struct nlmsghdr *nlh2; struct nlmsghdr *nlh2;
int ret = 0;
if (unlikely(!attr[IPSET_ATTR_PROTOCOL])) if (unlikely(!attr[IPSET_ATTR_PROTOCOL]))
return -IPSET_ERR_PROTOCOL; return -IPSET_ERR_PROTOCOL;
...@@ -1990,12 +1977,7 @@ static int ip_set_protocol(struct sk_buff *skb, const struct nfnl_info *info, ...@@ -1990,12 +1977,7 @@ static int ip_set_protocol(struct sk_buff *skb, const struct nfnl_info *info,
goto nla_put_failure; goto nla_put_failure;
nlmsg_end(skb2, nlh2); nlmsg_end(skb2, nlh2);
ret = netlink_unicast(info->sk, skb2, NETLINK_CB(skb).portid, return nfnetlink_unicast(skb2, info->net, NETLINK_CB(skb).portid);
MSG_DONTWAIT);
if (ret < 0)
return ret;
return 0;
nla_put_failure: nla_put_failure:
nlmsg_cancel(skb2, nlh2); nlmsg_cancel(skb2, nlh2);
...@@ -2014,7 +1996,6 @@ static int ip_set_byname(struct sk_buff *skb, const struct nfnl_info *info, ...@@ -2014,7 +1996,6 @@ static int ip_set_byname(struct sk_buff *skb, const struct nfnl_info *info,
struct nlmsghdr *nlh2; struct nlmsghdr *nlh2;
ip_set_id_t id = IPSET_INVALID_ID; ip_set_id_t id = IPSET_INVALID_ID;
const struct ip_set *set; const struct ip_set *set;
int ret = 0;
if (unlikely(protocol_failed(attr) || if (unlikely(protocol_failed(attr) ||
!attr[IPSET_ATTR_SETNAME])) !attr[IPSET_ATTR_SETNAME]))
...@@ -2038,12 +2019,7 @@ static int ip_set_byname(struct sk_buff *skb, const struct nfnl_info *info, ...@@ -2038,12 +2019,7 @@ static int ip_set_byname(struct sk_buff *skb, const struct nfnl_info *info,
goto nla_put_failure; goto nla_put_failure;
nlmsg_end(skb2, nlh2); nlmsg_end(skb2, nlh2);
ret = netlink_unicast(info->sk, skb2, NETLINK_CB(skb).portid, return nfnetlink_unicast(skb2, info->net, NETLINK_CB(skb).portid);
MSG_DONTWAIT);
if (ret < 0)
return ret;
return 0;
nla_put_failure: nla_put_failure:
nlmsg_cancel(skb2, nlh2); nlmsg_cancel(skb2, nlh2);
...@@ -2065,7 +2041,6 @@ static int ip_set_byindex(struct sk_buff *skb, const struct nfnl_info *info, ...@@ -2065,7 +2041,6 @@ static int ip_set_byindex(struct sk_buff *skb, const struct nfnl_info *info,
struct nlmsghdr *nlh2; struct nlmsghdr *nlh2;
ip_set_id_t id = IPSET_INVALID_ID; ip_set_id_t id = IPSET_INVALID_ID;
const struct ip_set *set; const struct ip_set *set;
int ret = 0;
if (unlikely(protocol_failed(attr) || if (unlikely(protocol_failed(attr) ||
!attr[IPSET_ATTR_INDEX])) !attr[IPSET_ATTR_INDEX]))
...@@ -2091,12 +2066,7 @@ static int ip_set_byindex(struct sk_buff *skb, const struct nfnl_info *info, ...@@ -2091,12 +2066,7 @@ static int ip_set_byindex(struct sk_buff *skb, const struct nfnl_info *info,
goto nla_put_failure; goto nla_put_failure;
nlmsg_end(skb2, nlh2); nlmsg_end(skb2, nlh2);
ret = netlink_unicast(info->sk, skb2, NETLINK_CB(skb).portid, return nfnetlink_unicast(skb2, info->net, NETLINK_CB(skb).portid);
MSG_DONTWAIT);
if (ret < 0)
return ret;
return 0;
nla_put_failure: nla_put_failure:
nlmsg_cancel(skb2, nlh2); nlmsg_cancel(skb2, nlh2);
......
...@@ -194,7 +194,7 @@ static int get_tpkt_data(struct sk_buff *skb, unsigned int protoff, ...@@ -194,7 +194,7 @@ static int get_tpkt_data(struct sk_buff *skb, unsigned int protoff,
if (tcpdatalen == 4) { /* Separate TPKT header */ if (tcpdatalen == 4) { /* Separate TPKT header */
/* Netmeeting sends TPKT header and data separately */ /* Netmeeting sends TPKT header and data separately */
pr_debug("nf_ct_h323: separate TPKT header indicates " pr_debug("nf_ct_h323: separate TPKT header indicates "
"there will be TPKT data of %hu bytes\n", "there will be TPKT data of %d bytes\n",
tpktlen - 4); tpktlen - 4);
info->tpkt_len[dir] = tpktlen - 4; info->tpkt_len[dir] = tpktlen - 4;
return 0; return 0;
......
...@@ -1628,9 +1628,8 @@ static int ctnetlink_get_conntrack(struct sk_buff *skb, ...@@ -1628,9 +1628,8 @@ static int ctnetlink_get_conntrack(struct sk_buff *skb,
ct = nf_ct_tuplehash_to_ctrack(h); ct = nf_ct_tuplehash_to_ctrack(h);
err = -ENOMEM;
skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (skb2 == NULL) { if (!skb2) {
nf_ct_put(ct); nf_ct_put(ct);
return -ENOMEM; return -ENOMEM;
} }
...@@ -1640,21 +1639,12 @@ static int ctnetlink_get_conntrack(struct sk_buff *skb, ...@@ -1640,21 +1639,12 @@ static int ctnetlink_get_conntrack(struct sk_buff *skb,
NFNL_MSG_TYPE(info->nlh->nlmsg_type), ct, NFNL_MSG_TYPE(info->nlh->nlmsg_type), ct,
true, 0); true, 0);
nf_ct_put(ct); nf_ct_put(ct);
if (err <= 0) if (err <= 0) {
goto free;
err = netlink_unicast(info->sk, skb2, NETLINK_CB(skb).portid,
MSG_DONTWAIT);
if (err < 0)
goto out;
return 0;
free:
kfree_skb(skb2); kfree_skb(skb2);
out: return -ENOMEM;
/* this avoids a loop in nfnetlink. */ }
return err == -EAGAIN ? -ENOBUFS : err;
return nfnetlink_unicast(skb2, info->net, NETLINK_CB(skb).portid);
} }
static int ctnetlink_done_list(struct netlink_callback *cb) static int ctnetlink_done_list(struct netlink_callback *cb)
...@@ -2590,21 +2580,12 @@ static int ctnetlink_stat_ct(struct sk_buff *skb, const struct nfnl_info *info, ...@@ -2590,21 +2580,12 @@ static int ctnetlink_stat_ct(struct sk_buff *skb, const struct nfnl_info *info,
info->nlh->nlmsg_seq, info->nlh->nlmsg_seq,
NFNL_MSG_TYPE(info->nlh->nlmsg_type), NFNL_MSG_TYPE(info->nlh->nlmsg_type),
sock_net(skb->sk)); sock_net(skb->sk));
if (err <= 0) if (err <= 0) {
goto free;
err = netlink_unicast(info->sk, skb2, NETLINK_CB(skb).portid,
MSG_DONTWAIT);
if (err < 0)
goto out;
return 0;
free:
kfree_skb(skb2); kfree_skb(skb2);
out: return -ENOMEM;
/* this avoids a loop in nfnetlink. */ }
return err == -EAGAIN ? -ENOBUFS : err;
return nfnetlink_unicast(skb2, info->net, NETLINK_CB(skb).portid);
} }
static const struct nla_policy exp_nla_policy[CTA_EXPECT_MAX+1] = { static const struct nla_policy exp_nla_policy[CTA_EXPECT_MAX+1] = {
...@@ -3329,11 +3310,10 @@ static int ctnetlink_get_expect(struct sk_buff *skb, ...@@ -3329,11 +3310,10 @@ static int ctnetlink_get_expect(struct sk_buff *skb,
} }
} }
err = -ENOMEM;
skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (skb2 == NULL) { if (!skb2) {
nf_ct_expect_put(exp); nf_ct_expect_put(exp);
goto out; return -ENOMEM;
} }
rcu_read_lock(); rcu_read_lock();
...@@ -3342,21 +3322,12 @@ static int ctnetlink_get_expect(struct sk_buff *skb, ...@@ -3342,21 +3322,12 @@ static int ctnetlink_get_expect(struct sk_buff *skb,
exp); exp);
rcu_read_unlock(); rcu_read_unlock();
nf_ct_expect_put(exp); nf_ct_expect_put(exp);
if (err <= 0) if (err <= 0) {
goto free;
err = netlink_unicast(info->sk, skb2, NETLINK_CB(skb).portid,
MSG_DONTWAIT);
if (err < 0)
goto out;
return 0;
free:
kfree_skb(skb2); kfree_skb(skb2);
out: return -ENOMEM;
/* this avoids a loop in nfnetlink. */ }
return err == -EAGAIN ? -ENOBUFS : err;
return nfnetlink_unicast(skb2, info->net, NETLINK_CB(skb).portid);
} }
static bool expect_iter_name(struct nf_conntrack_expect *exp, void *data) static bool expect_iter_name(struct nf_conntrack_expect *exp, void *data)
......
...@@ -81,7 +81,7 @@ static bool nft_payload_fast_eval(const struct nft_expr *expr, ...@@ -81,7 +81,7 @@ static bool nft_payload_fast_eval(const struct nft_expr *expr,
else { else {
if (!pkt->tprot_set) if (!pkt->tprot_set)
return false; return false;
ptr = skb_network_header(skb) + pkt->xt.thoff; ptr = skb_network_header(skb) + nft_thoff(pkt);
} }
ptr += priv->offset; ptr += priv->offset;
......
...@@ -113,17 +113,17 @@ static int nf_trace_fill_pkt_info(struct sk_buff *nlskb, ...@@ -113,17 +113,17 @@ static int nf_trace_fill_pkt_info(struct sk_buff *nlskb,
int off = skb_network_offset(skb); int off = skb_network_offset(skb);
unsigned int len, nh_end; unsigned int len, nh_end;
nh_end = pkt->tprot_set ? pkt->xt.thoff : skb->len; nh_end = pkt->tprot_set ? nft_thoff(pkt) : skb->len;
len = min_t(unsigned int, nh_end - skb_network_offset(skb), len = min_t(unsigned int, nh_end - skb_network_offset(skb),
NFT_TRACETYPE_NETWORK_HSIZE); NFT_TRACETYPE_NETWORK_HSIZE);
if (trace_fill_header(nlskb, NFTA_TRACE_NETWORK_HEADER, skb, off, len)) if (trace_fill_header(nlskb, NFTA_TRACE_NETWORK_HEADER, skb, off, len))
return -1; return -1;
if (pkt->tprot_set) { if (pkt->tprot_set) {
len = min_t(unsigned int, skb->len - pkt->xt.thoff, len = min_t(unsigned int, skb->len - nft_thoff(pkt),
NFT_TRACETYPE_TRANSPORT_HSIZE); NFT_TRACETYPE_TRANSPORT_HSIZE);
if (trace_fill_header(nlskb, NFTA_TRACE_TRANSPORT_HEADER, skb, if (trace_fill_header(nlskb, NFTA_TRACE_TRANSPORT_HEADER, skb,
pkt->xt.thoff, len)) nft_thoff(pkt), len))
return -1; return -1;
} }
......
...@@ -314,14 +314,11 @@ static int nfnl_acct_get(struct sk_buff *skb, const struct nfnl_info *info, ...@@ -314,14 +314,11 @@ static int nfnl_acct_get(struct sk_buff *skb, const struct nfnl_info *info,
kfree_skb(skb2); kfree_skb(skb2);
break; break;
} }
ret = netlink_unicast(info->sk, skb2, NETLINK_CB(skb).portid,
MSG_DONTWAIT);
if (ret > 0)
ret = 0;
/* this avoids a loop in nfnetlink. */ ret = nfnetlink_unicast(skb2, info->net, NETLINK_CB(skb).portid);
return ret == -EAGAIN ? -ENOBUFS : ret; break;
} }
return ret; return ret;
} }
......
...@@ -663,14 +663,10 @@ static int nfnl_cthelper_get(struct sk_buff *skb, const struct nfnl_info *info, ...@@ -663,14 +663,10 @@ static int nfnl_cthelper_get(struct sk_buff *skb, const struct nfnl_info *info,
break; break;
} }
ret = netlink_unicast(info->sk, skb2, NETLINK_CB(skb).portid, ret = nfnetlink_unicast(skb2, info->net, NETLINK_CB(skb).portid);
MSG_DONTWAIT); break;
if (ret > 0)
ret = 0;
/* this avoids a loop in nfnetlink. */
return ret == -EAGAIN ? -ENOBUFS : ret;
} }
return ret; return ret;
} }
......
...@@ -287,14 +287,11 @@ static int cttimeout_get_timeout(struct sk_buff *skb, ...@@ -287,14 +287,11 @@ static int cttimeout_get_timeout(struct sk_buff *skb,
kfree_skb(skb2); kfree_skb(skb2);
break; break;
} }
ret = netlink_unicast(info->sk, skb2, NETLINK_CB(skb).portid,
MSG_DONTWAIT);
if (ret > 0)
ret = 0;
/* this avoids a loop in nfnetlink. */ ret = nfnetlink_unicast(skb2, info->net, NETLINK_CB(skb).portid);
return ret == -EAGAIN ? -ENOBUFS : ret; break;
} }
return ret; return ret;
} }
...@@ -427,9 +424,9 @@ static int cttimeout_default_get(struct sk_buff *skb, ...@@ -427,9 +424,9 @@ static int cttimeout_default_get(struct sk_buff *skb,
const struct nf_conntrack_l4proto *l4proto; const struct nf_conntrack_l4proto *l4proto;
unsigned int *timeouts = NULL; unsigned int *timeouts = NULL;
struct sk_buff *skb2; struct sk_buff *skb2;
int ret, err;
__u16 l3num; __u16 l3num;
__u8 l4num; __u8 l4num;
int ret;
if (!cda[CTA_TIMEOUT_L3PROTO] || !cda[CTA_TIMEOUT_L4PROTO]) if (!cda[CTA_TIMEOUT_L3PROTO] || !cda[CTA_TIMEOUT_L4PROTO])
return -EINVAL; return -EINVAL;
...@@ -438,9 +435,8 @@ static int cttimeout_default_get(struct sk_buff *skb, ...@@ -438,9 +435,8 @@ static int cttimeout_default_get(struct sk_buff *skb,
l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]); l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]);
l4proto = nf_ct_l4proto_find(l4num); l4proto = nf_ct_l4proto_find(l4num);
err = -EOPNOTSUPP;
if (l4proto->l4proto != l4num) if (l4proto->l4proto != l4num)
goto err; return -EOPNOTSUPP;
switch (l4proto->l4proto) { switch (l4proto->l4proto) {
case IPPROTO_ICMP: case IPPROTO_ICMP:
...@@ -480,13 +476,11 @@ static int cttimeout_default_get(struct sk_buff *skb, ...@@ -480,13 +476,11 @@ static int cttimeout_default_get(struct sk_buff *skb,
} }
if (!timeouts) if (!timeouts)
goto err; return -EOPNOTSUPP;
skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (skb2 == NULL) { if (!skb2)
err = -ENOMEM; return -ENOMEM;
goto err;
}
ret = cttimeout_default_fill_info(info->net, skb2, ret = cttimeout_default_fill_info(info->net, skb2,
NETLINK_CB(skb).portid, NETLINK_CB(skb).portid,
...@@ -496,18 +490,10 @@ static int cttimeout_default_get(struct sk_buff *skb, ...@@ -496,18 +490,10 @@ static int cttimeout_default_get(struct sk_buff *skb,
l3num, l4proto, timeouts); l3num, l4proto, timeouts);
if (ret <= 0) { if (ret <= 0) {
kfree_skb(skb2); kfree_skb(skb2);
err = -ENOMEM; return -ENOMEM;
goto err;
} }
ret = netlink_unicast(info->sk, skb2, NETLINK_CB(skb).portid,
MSG_DONTWAIT);
if (ret > 0)
ret = 0;
/* this avoids a loop in nfnetlink. */ return nfnetlink_unicast(skb2, info->net, NETLINK_CB(skb).portid);
return ret == -EAGAIN ? -ENOBUFS : ret;
err:
return err;
} }
static struct nf_ct_timeout *ctnl_timeout_find_get(struct net *net, static struct nf_ct_timeout *ctnl_timeout_find_get(struct net *net,
......
...@@ -18,7 +18,7 @@ static unsigned int nft_do_chain_ipv4(void *priv, ...@@ -18,7 +18,7 @@ static unsigned int nft_do_chain_ipv4(void *priv,
struct nft_pktinfo pkt; struct nft_pktinfo pkt;
nft_set_pktinfo(&pkt, skb, state); nft_set_pktinfo(&pkt, skb, state);
nft_set_pktinfo_ipv4(&pkt, skb); nft_set_pktinfo_ipv4(&pkt);
return nft_do_chain(&pkt, priv); return nft_do_chain(&pkt, priv);
} }
...@@ -62,7 +62,7 @@ static unsigned int nft_do_chain_arp(void *priv, struct sk_buff *skb, ...@@ -62,7 +62,7 @@ static unsigned int nft_do_chain_arp(void *priv, struct sk_buff *skb,
struct nft_pktinfo pkt; struct nft_pktinfo pkt;
nft_set_pktinfo(&pkt, skb, state); nft_set_pktinfo(&pkt, skb, state);
nft_set_pktinfo_unspec(&pkt, skb); nft_set_pktinfo_unspec(&pkt);
return nft_do_chain(&pkt, priv); return nft_do_chain(&pkt, priv);
} }
...@@ -102,7 +102,7 @@ static unsigned int nft_do_chain_ipv6(void *priv, ...@@ -102,7 +102,7 @@ static unsigned int nft_do_chain_ipv6(void *priv,
struct nft_pktinfo pkt; struct nft_pktinfo pkt;
nft_set_pktinfo(&pkt, skb, state); nft_set_pktinfo(&pkt, skb, state);
nft_set_pktinfo_ipv6(&pkt, skb); nft_set_pktinfo_ipv6(&pkt);
return nft_do_chain(&pkt, priv); return nft_do_chain(&pkt, priv);
} }
...@@ -149,10 +149,10 @@ static unsigned int nft_do_chain_inet(void *priv, struct sk_buff *skb, ...@@ -149,10 +149,10 @@ static unsigned int nft_do_chain_inet(void *priv, struct sk_buff *skb,
switch (state->pf) { switch (state->pf) {
case NFPROTO_IPV4: case NFPROTO_IPV4:
nft_set_pktinfo_ipv4(&pkt, skb); nft_set_pktinfo_ipv4(&pkt);
break; break;
case NFPROTO_IPV6: case NFPROTO_IPV6:
nft_set_pktinfo_ipv6(&pkt, skb); nft_set_pktinfo_ipv6(&pkt);
break; break;
default: default:
break; break;
...@@ -174,7 +174,7 @@ static unsigned int nft_do_chain_inet_ingress(void *priv, struct sk_buff *skb, ...@@ -174,7 +174,7 @@ static unsigned int nft_do_chain_inet_ingress(void *priv, struct sk_buff *skb,
ingress_state.hook = NF_INET_INGRESS; ingress_state.hook = NF_INET_INGRESS;
nft_set_pktinfo(&pkt, skb, &ingress_state); nft_set_pktinfo(&pkt, skb, &ingress_state);
if (nft_set_pktinfo_ipv4_ingress(&pkt, skb) < 0) if (nft_set_pktinfo_ipv4_ingress(&pkt) < 0)
return NF_DROP; return NF_DROP;
break; break;
case htons(ETH_P_IPV6): case htons(ETH_P_IPV6):
...@@ -182,7 +182,7 @@ static unsigned int nft_do_chain_inet_ingress(void *priv, struct sk_buff *skb, ...@@ -182,7 +182,7 @@ static unsigned int nft_do_chain_inet_ingress(void *priv, struct sk_buff *skb,
ingress_state.hook = NF_INET_INGRESS; ingress_state.hook = NF_INET_INGRESS;
nft_set_pktinfo(&pkt, skb, &ingress_state); nft_set_pktinfo(&pkt, skb, &ingress_state);
if (nft_set_pktinfo_ipv6_ingress(&pkt, skb) < 0) if (nft_set_pktinfo_ipv6_ingress(&pkt) < 0)
return NF_DROP; return NF_DROP;
break; break;
default: default:
...@@ -238,13 +238,13 @@ nft_do_chain_bridge(void *priv, ...@@ -238,13 +238,13 @@ nft_do_chain_bridge(void *priv,
switch (eth_hdr(skb)->h_proto) { switch (eth_hdr(skb)->h_proto) {
case htons(ETH_P_IP): case htons(ETH_P_IP):
nft_set_pktinfo_ipv4_validate(&pkt, skb); nft_set_pktinfo_ipv4_validate(&pkt);
break; break;
case htons(ETH_P_IPV6): case htons(ETH_P_IPV6):
nft_set_pktinfo_ipv6_validate(&pkt, skb); nft_set_pktinfo_ipv6_validate(&pkt);
break; break;
default: default:
nft_set_pktinfo_unspec(&pkt, skb); nft_set_pktinfo_unspec(&pkt);
break; break;
} }
...@@ -293,13 +293,13 @@ static unsigned int nft_do_chain_netdev(void *priv, struct sk_buff *skb, ...@@ -293,13 +293,13 @@ static unsigned int nft_do_chain_netdev(void *priv, struct sk_buff *skb,
switch (skb->protocol) { switch (skb->protocol) {
case htons(ETH_P_IP): case htons(ETH_P_IP):
nft_set_pktinfo_ipv4_validate(&pkt, skb); nft_set_pktinfo_ipv4_validate(&pkt);
break; break;
case htons(ETH_P_IPV6): case htons(ETH_P_IPV6):
nft_set_pktinfo_ipv6_validate(&pkt, skb); nft_set_pktinfo_ipv6_validate(&pkt);
break; break;
default: default:
nft_set_pktinfo_unspec(&pkt, skb); nft_set_pktinfo_unspec(&pkt);
break; break;
} }
......
...@@ -17,12 +17,12 @@ static unsigned int nft_nat_do_chain(void *priv, struct sk_buff *skb, ...@@ -17,12 +17,12 @@ static unsigned int nft_nat_do_chain(void *priv, struct sk_buff *skb,
switch (state->pf) { switch (state->pf) {
#ifdef CONFIG_NF_TABLES_IPV4 #ifdef CONFIG_NF_TABLES_IPV4
case NFPROTO_IPV4: case NFPROTO_IPV4:
nft_set_pktinfo_ipv4(&pkt, skb); nft_set_pktinfo_ipv4(&pkt);
break; break;
#endif #endif
#ifdef CONFIG_NF_TABLES_IPV6 #ifdef CONFIG_NF_TABLES_IPV6
case NFPROTO_IPV6: case NFPROTO_IPV6:
nft_set_pktinfo_ipv6(&pkt, skb); nft_set_pktinfo_ipv6(&pkt);
break; break;
#endif #endif
default: default:
......
...@@ -26,7 +26,7 @@ static unsigned int nf_route_table_hook4(void *priv, ...@@ -26,7 +26,7 @@ static unsigned int nf_route_table_hook4(void *priv,
u8 tos; u8 tos;
nft_set_pktinfo(&pkt, skb, state); nft_set_pktinfo(&pkt, skb, state);
nft_set_pktinfo_ipv4(&pkt, skb); nft_set_pktinfo_ipv4(&pkt);
mark = skb->mark; mark = skb->mark;
iph = ip_hdr(skb); iph = ip_hdr(skb);
...@@ -74,7 +74,7 @@ static unsigned int nf_route_table_hook6(void *priv, ...@@ -74,7 +74,7 @@ static unsigned int nf_route_table_hook6(void *priv,
int err; int err;
nft_set_pktinfo(&pkt, skb, state); nft_set_pktinfo(&pkt, skb, state);
nft_set_pktinfo_ipv6(&pkt, skb); nft_set_pktinfo_ipv6(&pkt);
/* save source/dest address, mark, hoplimit, flowlabel, priority */ /* save source/dest address, mark, hoplimit, flowlabel, priority */
memcpy(&saddr, &ipv6_hdr(skb)->saddr, sizeof(saddr)); memcpy(&saddr, &ipv6_hdr(skb)->saddr, sizeof(saddr));
......
...@@ -57,8 +57,13 @@ union nft_entry { ...@@ -57,8 +57,13 @@ union nft_entry {
}; };
static inline void static inline void
nft_compat_set_par(struct xt_action_param *par, void *xt, const void *xt_info) nft_compat_set_par(struct xt_action_param *par,
const struct nft_pktinfo *pkt,
const void *xt, const void *xt_info)
{ {
par->state = pkt->state;
par->thoff = nft_thoff(pkt);
par->fragoff = pkt->fragoff;
par->target = xt; par->target = xt;
par->targinfo = xt_info; par->targinfo = xt_info;
par->hotdrop = false; par->hotdrop = false;
...@@ -71,13 +76,14 @@ static void nft_target_eval_xt(const struct nft_expr *expr, ...@@ -71,13 +76,14 @@ static void nft_target_eval_xt(const struct nft_expr *expr,
void *info = nft_expr_priv(expr); void *info = nft_expr_priv(expr);
struct xt_target *target = expr->ops->data; struct xt_target *target = expr->ops->data;
struct sk_buff *skb = pkt->skb; struct sk_buff *skb = pkt->skb;
struct xt_action_param xt;
int ret; int ret;
nft_compat_set_par((struct xt_action_param *)&pkt->xt, target, info); nft_compat_set_par(&xt, pkt, target, info);
ret = target->target(skb, &pkt->xt); ret = target->target(skb, &xt);
if (pkt->xt.hotdrop) if (xt.hotdrop)
ret = NF_DROP; ret = NF_DROP;
switch (ret) { switch (ret) {
...@@ -97,13 +103,14 @@ static void nft_target_eval_bridge(const struct nft_expr *expr, ...@@ -97,13 +103,14 @@ static void nft_target_eval_bridge(const struct nft_expr *expr,
void *info = nft_expr_priv(expr); void *info = nft_expr_priv(expr);
struct xt_target *target = expr->ops->data; struct xt_target *target = expr->ops->data;
struct sk_buff *skb = pkt->skb; struct sk_buff *skb = pkt->skb;
struct xt_action_param xt;
int ret; int ret;
nft_compat_set_par((struct xt_action_param *)&pkt->xt, target, info); nft_compat_set_par(&xt, pkt, target, info);
ret = target->target(skb, &pkt->xt); ret = target->target(skb, &xt);
if (pkt->xt.hotdrop) if (xt.hotdrop)
ret = NF_DROP; ret = NF_DROP;
switch (ret) { switch (ret) {
...@@ -350,13 +357,14 @@ static void __nft_match_eval(const struct nft_expr *expr, ...@@ -350,13 +357,14 @@ static void __nft_match_eval(const struct nft_expr *expr,
{ {
struct xt_match *match = expr->ops->data; struct xt_match *match = expr->ops->data;
struct sk_buff *skb = pkt->skb; struct sk_buff *skb = pkt->skb;
struct xt_action_param xt;
bool ret; bool ret;
nft_compat_set_par((struct xt_action_param *)&pkt->xt, match, info); nft_compat_set_par(&xt, pkt, match, info);
ret = match->match(skb, (struct xt_action_param *)&pkt->xt); ret = match->match(skb, &xt);
if (pkt->xt.hotdrop) { if (xt.hotdrop) {
regs->verdict.code = NF_DROP; regs->verdict.code = NF_DROP;
return; return;
} }
......
...@@ -10,8 +10,10 @@ ...@@ -10,8 +10,10 @@
#include <linux/netlink.h> #include <linux/netlink.h>
#include <linux/netfilter.h> #include <linux/netfilter.h>
#include <linux/netfilter/nf_tables.h> #include <linux/netfilter/nf_tables.h>
#include <linux/sctp.h>
#include <net/netfilter/nf_tables_core.h> #include <net/netfilter/nf_tables_core.h>
#include <net/netfilter/nf_tables.h> #include <net/netfilter/nf_tables.h>
#include <net/sctp/sctp.h>
#include <net/tcp.h> #include <net/tcp.h>
struct nft_exthdr { struct nft_exthdr {
...@@ -165,7 +167,7 @@ nft_tcp_header_pointer(const struct nft_pktinfo *pkt, ...@@ -165,7 +167,7 @@ nft_tcp_header_pointer(const struct nft_pktinfo *pkt,
if (!pkt->tprot_set || pkt->tprot != IPPROTO_TCP) if (!pkt->tprot_set || pkt->tprot != IPPROTO_TCP)
return NULL; return NULL;
tcph = skb_header_pointer(pkt->skb, pkt->xt.thoff, sizeof(*tcph), buffer); tcph = skb_header_pointer(pkt->skb, nft_thoff(pkt), sizeof(*tcph), buffer);
if (!tcph) if (!tcph)
return NULL; return NULL;
...@@ -173,7 +175,7 @@ nft_tcp_header_pointer(const struct nft_pktinfo *pkt, ...@@ -173,7 +175,7 @@ nft_tcp_header_pointer(const struct nft_pktinfo *pkt,
if (*tcphdr_len < sizeof(*tcph) || *tcphdr_len > len) if (*tcphdr_len < sizeof(*tcph) || *tcphdr_len > len)
return NULL; return NULL;
return skb_header_pointer(pkt->skb, pkt->xt.thoff, *tcphdr_len, buffer); return skb_header_pointer(pkt->skb, nft_thoff(pkt), *tcphdr_len, buffer);
} }
static void nft_exthdr_tcp_eval(const struct nft_expr *expr, static void nft_exthdr_tcp_eval(const struct nft_expr *expr,
...@@ -249,7 +251,7 @@ static void nft_exthdr_tcp_set_eval(const struct nft_expr *expr, ...@@ -249,7 +251,7 @@ static void nft_exthdr_tcp_set_eval(const struct nft_expr *expr,
return; return;
if (skb_ensure_writable(pkt->skb, if (skb_ensure_writable(pkt->skb,
pkt->xt.thoff + i + priv->len)) nft_thoff(pkt) + i + priv->len))
return; return;
tcph = nft_tcp_header_pointer(pkt, sizeof(buff), buff, tcph = nft_tcp_header_pointer(pkt, sizeof(buff), buff,
...@@ -300,6 +302,43 @@ static void nft_exthdr_tcp_set_eval(const struct nft_expr *expr, ...@@ -300,6 +302,43 @@ static void nft_exthdr_tcp_set_eval(const struct nft_expr *expr,
} }
} }
static void nft_exthdr_sctp_eval(const struct nft_expr *expr,
struct nft_regs *regs,
const struct nft_pktinfo *pkt)
{
unsigned int offset = nft_thoff(pkt) + sizeof(struct sctphdr);
struct nft_exthdr *priv = nft_expr_priv(expr);
u32 *dest = &regs->data[priv->dreg];
const struct sctp_chunkhdr *sch;
struct sctp_chunkhdr _sch;
do {
sch = skb_header_pointer(pkt->skb, offset, sizeof(_sch), &_sch);
if (!sch || !sch->length)
break;
if (sch->type == priv->type) {
if (priv->flags & NFT_EXTHDR_F_PRESENT) {
nft_reg_store8(dest, true);
return;
}
if (priv->offset + priv->len > ntohs(sch->length) ||
offset + ntohs(sch->length) > pkt->skb->len)
break;
dest[priv->len / NFT_REG32_SIZE] = 0;
memcpy(dest, (char *)sch + priv->offset, priv->len);
return;
}
offset += SCTP_PAD4(ntohs(sch->length));
} while (offset < pkt->skb->len);
if (priv->flags & NFT_EXTHDR_F_PRESENT)
nft_reg_store8(dest, false);
else
regs->verdict.code = NFT_BREAK;
}
static const struct nla_policy nft_exthdr_policy[NFTA_EXTHDR_MAX + 1] = { static const struct nla_policy nft_exthdr_policy[NFTA_EXTHDR_MAX + 1] = {
[NFTA_EXTHDR_DREG] = { .type = NLA_U32 }, [NFTA_EXTHDR_DREG] = { .type = NLA_U32 },
[NFTA_EXTHDR_TYPE] = { .type = NLA_U8 }, [NFTA_EXTHDR_TYPE] = { .type = NLA_U8 },
...@@ -499,6 +538,14 @@ static const struct nft_expr_ops nft_exthdr_tcp_set_ops = { ...@@ -499,6 +538,14 @@ static const struct nft_expr_ops nft_exthdr_tcp_set_ops = {
.dump = nft_exthdr_dump_set, .dump = nft_exthdr_dump_set,
}; };
static const struct nft_expr_ops nft_exthdr_sctp_ops = {
.type = &nft_exthdr_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_exthdr)),
.eval = nft_exthdr_sctp_eval,
.init = nft_exthdr_init,
.dump = nft_exthdr_dump,
};
static const struct nft_expr_ops * static const struct nft_expr_ops *
nft_exthdr_select_ops(const struct nft_ctx *ctx, nft_exthdr_select_ops(const struct nft_ctx *ctx,
const struct nlattr * const tb[]) const struct nlattr * const tb[])
...@@ -529,6 +576,10 @@ nft_exthdr_select_ops(const struct nft_ctx *ctx, ...@@ -529,6 +576,10 @@ nft_exthdr_select_ops(const struct nft_ctx *ctx,
return &nft_exthdr_ipv4_ops; return &nft_exthdr_ipv4_ops;
} }
break; break;
case NFT_EXTHDR_OP_SCTP:
if (tb[NFTA_EXTHDR_DREG])
return &nft_exthdr_sctp_ops;
break;
} }
return ERR_PTR(-EOPNOTSUPP); return ERR_PTR(-EOPNOTSUPP);
......
...@@ -291,7 +291,7 @@ static void nft_flow_offload_eval(const struct nft_expr *expr, ...@@ -291,7 +291,7 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
switch (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum) { switch (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum) {
case IPPROTO_TCP: case IPPROTO_TCP:
tcph = skb_header_pointer(pkt->skb, pkt->xt.thoff, tcph = skb_header_pointer(pkt->skb, nft_thoff(pkt),
sizeof(_tcph), &_tcph); sizeof(_tcph), &_tcph);
if (unlikely(!tcph || tcph->fin || tcph->rst)) if (unlikely(!tcph || tcph->fin || tcph->rst))
goto out; goto out;
......
...@@ -23,6 +23,37 @@ struct nft_lookup { ...@@ -23,6 +23,37 @@ struct nft_lookup {
struct nft_set_binding binding; struct nft_set_binding binding;
}; };
#ifdef CONFIG_RETPOLINE
bool nft_set_do_lookup(const struct net *net, const struct nft_set *set,
const u32 *key, const struct nft_set_ext **ext)
{
if (set->ops == &nft_set_hash_fast_type.ops)
return nft_hash_lookup_fast(net, set, key, ext);
if (set->ops == &nft_set_hash_type.ops)
return nft_hash_lookup(net, set, key, ext);
if (set->ops == &nft_set_rhash_type.ops)
return nft_rhash_lookup(net, set, key, ext);
if (set->ops == &nft_set_bitmap_type.ops)
return nft_bitmap_lookup(net, set, key, ext);
if (set->ops == &nft_set_pipapo_type.ops)
return nft_pipapo_lookup(net, set, key, ext);
#if defined(CONFIG_X86_64) && !defined(CONFIG_UML)
if (set->ops == &nft_set_pipapo_avx2_type.ops)
return nft_pipapo_avx2_lookup(net, set, key, ext);
#endif
if (set->ops == &nft_set_rbtree_type.ops)
return nft_rbtree_lookup(net, set, key, ext);
WARN_ON_ONCE(1);
return set->ops->lookup(net, set, key, ext);
}
EXPORT_SYMBOL_GPL(nft_set_do_lookup);
#endif
void nft_lookup_eval(const struct nft_expr *expr, void nft_lookup_eval(const struct nft_expr *expr,
struct nft_regs *regs, struct nft_regs *regs,
const struct nft_pktinfo *pkt) const struct nft_pktinfo *pkt)
...@@ -33,7 +64,7 @@ void nft_lookup_eval(const struct nft_expr *expr, ...@@ -33,7 +64,7 @@ void nft_lookup_eval(const struct nft_expr *expr,
const struct net *net = nft_net(pkt); const struct net *net = nft_net(pkt);
bool found; bool found;
found = set->ops->lookup(net, set, &regs->data[priv->sreg], &ext) ^ found = nft_set_do_lookup(net, set, &regs->data[priv->sreg], &ext) ^
priv->invert; priv->invert;
if (!found) { if (!found) {
ext = nft_set_catchall_lookup(net, set); ext = nft_set_catchall_lookup(net, set);
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
#include <linux/netlink.h> #include <linux/netlink.h>
#include <linux/netfilter.h> #include <linux/netfilter.h>
#include <linux/netfilter/nf_tables.h> #include <linux/netfilter/nf_tables.h>
#include <net/netfilter/nf_tables.h> #include <net/netfilter/nf_tables_core.h>
#define nft_objref_priv(expr) *((struct nft_object **)nft_expr_priv(expr)) #define nft_objref_priv(expr) *((struct nft_object **)nft_expr_priv(expr))
...@@ -110,7 +110,7 @@ static void nft_objref_map_eval(const struct nft_expr *expr, ...@@ -110,7 +110,7 @@ static void nft_objref_map_eval(const struct nft_expr *expr,
struct nft_object *obj; struct nft_object *obj;
bool found; bool found;
found = set->ops->lookup(net, set, &regs->data[priv->sreg], &ext); found = nft_set_do_lookup(net, set, &regs->data[priv->sreg], &ext);
if (!found) { if (!found) {
ext = nft_set_catchall_lookup(net, set); ext = nft_set_catchall_lookup(net, set);
if (!ext) { if (!ext) {
......
...@@ -110,7 +110,7 @@ void nft_payload_eval(const struct nft_expr *expr, ...@@ -110,7 +110,7 @@ void nft_payload_eval(const struct nft_expr *expr,
case NFT_PAYLOAD_TRANSPORT_HEADER: case NFT_PAYLOAD_TRANSPORT_HEADER:
if (!pkt->tprot_set) if (!pkt->tprot_set)
goto err; goto err;
offset = pkt->xt.thoff; offset = nft_thoff(pkt);
break; break;
default: default:
BUG(); BUG();
...@@ -507,7 +507,7 @@ static int nft_payload_l4csum_offset(const struct nft_pktinfo *pkt, ...@@ -507,7 +507,7 @@ static int nft_payload_l4csum_offset(const struct nft_pktinfo *pkt,
*l4csum_offset = offsetof(struct tcphdr, check); *l4csum_offset = offsetof(struct tcphdr, check);
break; break;
case IPPROTO_UDP: case IPPROTO_UDP:
if (!nft_payload_udp_checksum(skb, pkt->xt.thoff)) if (!nft_payload_udp_checksum(skb, nft_thoff(pkt)))
return -1; return -1;
fallthrough; fallthrough;
case IPPROTO_UDPLITE: case IPPROTO_UDPLITE:
...@@ -520,7 +520,7 @@ static int nft_payload_l4csum_offset(const struct nft_pktinfo *pkt, ...@@ -520,7 +520,7 @@ static int nft_payload_l4csum_offset(const struct nft_pktinfo *pkt,
return -1; return -1;
} }
*l4csum_offset += pkt->xt.thoff; *l4csum_offset += nft_thoff(pkt);
return 0; return 0;
} }
...@@ -612,7 +612,7 @@ static void nft_payload_set_eval(const struct nft_expr *expr, ...@@ -612,7 +612,7 @@ static void nft_payload_set_eval(const struct nft_expr *expr,
case NFT_PAYLOAD_TRANSPORT_HEADER: case NFT_PAYLOAD_TRANSPORT_HEADER:
if (!pkt->tprot_set) if (!pkt->tprot_set)
goto err; goto err;
offset = pkt->xt.thoff; offset = nft_thoff(pkt);
break; break;
default: default:
BUG(); BUG();
...@@ -643,7 +643,7 @@ static void nft_payload_set_eval(const struct nft_expr *expr, ...@@ -643,7 +643,7 @@ static void nft_payload_set_eval(const struct nft_expr *expr,
if (priv->csum_type == NFT_PAYLOAD_CSUM_SCTP && if (priv->csum_type == NFT_PAYLOAD_CSUM_SCTP &&
pkt->tprot == IPPROTO_SCTP && pkt->tprot == IPPROTO_SCTP &&
skb->ip_summed != CHECKSUM_PARTIAL) { skb->ip_summed != CHECKSUM_PARTIAL) {
if (nft_payload_csum_sctp(skb, pkt->xt.thoff)) if (nft_payload_csum_sctp(skb, nft_thoff(pkt)))
goto err; goto err;
} }
......
...@@ -28,7 +28,7 @@ static void nft_reject_inet_eval(const struct nft_expr *expr, ...@@ -28,7 +28,7 @@ static void nft_reject_inet_eval(const struct nft_expr *expr,
nft_hook(pkt)); nft_hook(pkt));
break; break;
case NFT_REJECT_TCP_RST: case NFT_REJECT_TCP_RST:
nf_send_reset(nft_net(pkt), pkt->xt.state->sk, nf_send_reset(nft_net(pkt), nft_sk(pkt),
pkt->skb, nft_hook(pkt)); pkt->skb, nft_hook(pkt));
break; break;
case NFT_REJECT_ICMPX_UNREACH: case NFT_REJECT_ICMPX_UNREACH:
...@@ -45,7 +45,7 @@ static void nft_reject_inet_eval(const struct nft_expr *expr, ...@@ -45,7 +45,7 @@ static void nft_reject_inet_eval(const struct nft_expr *expr,
priv->icmp_code, nft_hook(pkt)); priv->icmp_code, nft_hook(pkt));
break; break;
case NFT_REJECT_TCP_RST: case NFT_REJECT_TCP_RST:
nf_send_reset6(nft_net(pkt), pkt->xt.state->sk, nf_send_reset6(nft_net(pkt), nft_sk(pkt),
pkt->skb, nft_hook(pkt)); pkt->skb, nft_hook(pkt));
break; break;
case NFT_REJECT_ICMPX_UNREACH: case NFT_REJECT_ICMPX_UNREACH:
......
...@@ -73,7 +73,8 @@ nft_bitmap_active(const u8 *bitmap, u32 idx, u32 off, u8 genmask) ...@@ -73,7 +73,8 @@ nft_bitmap_active(const u8 *bitmap, u32 idx, u32 off, u8 genmask)
return (bitmap[idx] & (0x3 << off)) & (genmask << off); return (bitmap[idx] & (0x3 << off)) & (genmask << off);
} }
static bool nft_bitmap_lookup(const struct net *net, const struct nft_set *set, INDIRECT_CALLABLE_SCOPE
bool nft_bitmap_lookup(const struct net *net, const struct nft_set *set,
const u32 *key, const struct nft_set_ext **ext) const u32 *key, const struct nft_set_ext **ext)
{ {
const struct nft_bitmap *priv = nft_set_priv(set); const struct nft_bitmap *priv = nft_set_priv(set);
......
...@@ -74,7 +74,8 @@ static const struct rhashtable_params nft_rhash_params = { ...@@ -74,7 +74,8 @@ static const struct rhashtable_params nft_rhash_params = {
.automatic_shrinking = true, .automatic_shrinking = true,
}; };
static bool nft_rhash_lookup(const struct net *net, const struct nft_set *set, INDIRECT_CALLABLE_SCOPE
bool nft_rhash_lookup(const struct net *net, const struct nft_set *set,
const u32 *key, const struct nft_set_ext **ext) const u32 *key, const struct nft_set_ext **ext)
{ {
struct nft_rhash *priv = nft_set_priv(set); struct nft_rhash *priv = nft_set_priv(set);
...@@ -446,7 +447,8 @@ struct nft_hash_elem { ...@@ -446,7 +447,8 @@ struct nft_hash_elem {
struct nft_set_ext ext; struct nft_set_ext ext;
}; };
static bool nft_hash_lookup(const struct net *net, const struct nft_set *set, INDIRECT_CALLABLE_SCOPE
bool nft_hash_lookup(const struct net *net, const struct nft_set *set,
const u32 *key, const struct nft_set_ext **ext) const u32 *key, const struct nft_set_ext **ext)
{ {
struct nft_hash *priv = nft_set_priv(set); struct nft_hash *priv = nft_set_priv(set);
...@@ -484,7 +486,8 @@ static void *nft_hash_get(const struct net *net, const struct nft_set *set, ...@@ -484,7 +486,8 @@ static void *nft_hash_get(const struct net *net, const struct nft_set *set,
return ERR_PTR(-ENOENT); return ERR_PTR(-ENOENT);
} }
static bool nft_hash_lookup_fast(const struct net *net, INDIRECT_CALLABLE_SCOPE
bool nft_hash_lookup_fast(const struct net *net,
const struct nft_set *set, const struct nft_set *set,
const u32 *key, const struct nft_set_ext **ext) const u32 *key, const struct nft_set_ext **ext)
{ {
......
...@@ -178,8 +178,6 @@ struct nft_pipapo_elem { ...@@ -178,8 +178,6 @@ struct nft_pipapo_elem {
int pipapo_refill(unsigned long *map, int len, int rules, unsigned long *dst, int pipapo_refill(unsigned long *map, int len, int rules, unsigned long *dst,
union nft_pipapo_map_bucket *mt, bool match_only); union nft_pipapo_map_bucket *mt, bool match_only);
bool nft_pipapo_lookup(const struct net *net, const struct nft_set *set,
const u32 *key, const struct nft_set_ext **ext);
/** /**
* pipapo_and_field_buckets_4bit() - Intersect 4-bit buckets * pipapo_and_field_buckets_4bit() - Intersect 4-bit buckets
......
...@@ -142,7 +142,6 @@ static void nft_pipapo_avx2_fill(unsigned long *data, int start, int len) ...@@ -142,7 +142,6 @@ static void nft_pipapo_avx2_fill(unsigned long *data, int start, int len)
* @map: Bitmap to be scanned for set bits * @map: Bitmap to be scanned for set bits
* @dst: Destination bitmap * @dst: Destination bitmap
* @mt: Mapping table containing bit set specifiers * @mt: Mapping table containing bit set specifiers
* @len: Length of bitmap in longs
* @last: Return index of first set bit, if this is the last field * @last: Return index of first set bit, if this is the last field
* *
* This is an alternative implementation of pipapo_refill() suitable for usage * This is an alternative implementation of pipapo_refill() suitable for usage
...@@ -1109,7 +1108,7 @@ bool nft_pipapo_avx2_estimate(const struct nft_set_desc *desc, u32 features, ...@@ -1109,7 +1108,7 @@ bool nft_pipapo_avx2_estimate(const struct nft_set_desc *desc, u32 features,
* nft_pipapo_avx2_lookup() - Lookup function for AVX2 implementation * nft_pipapo_avx2_lookup() - Lookup function for AVX2 implementation
* @net: Network namespace * @net: Network namespace
* @set: nftables API set representation * @set: nftables API set representation
* @elem: nftables API element representation containing key data * @key: nftables API element representation containing key data
* @ext: nftables API extension pointer, filled with matching reference * @ext: nftables API extension pointer, filled with matching reference
* *
* For more details, see DOC: Theory of Operation in nft_set_pipapo.c. * For more details, see DOC: Theory of Operation in nft_set_pipapo.c.
...@@ -1136,8 +1135,13 @@ bool nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set, ...@@ -1136,8 +1135,13 @@ bool nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set,
m = rcu_dereference(priv->match); m = rcu_dereference(priv->match);
/* This also protects access to all data related to scratch maps */ /* This also protects access to all data related to scratch maps.
kernel_fpu_begin(); *
* Note that we don't need a valid MXCSR state for any of the
* operations we use here, so pass 0 as mask and spare a LDMXCSR
* instruction.
*/
kernel_fpu_begin_mask(0);
scratch = *raw_cpu_ptr(m->scratch_aligned); scratch = *raw_cpu_ptr(m->scratch_aligned);
if (unlikely(!scratch)) { if (unlikely(!scratch)) {
......
...@@ -5,8 +5,6 @@ ...@@ -5,8 +5,6 @@
#include <asm/fpu/xstate.h> #include <asm/fpu/xstate.h>
#define NFT_PIPAPO_ALIGN (XSAVE_YMM_SIZE / BITS_PER_BYTE) #define NFT_PIPAPO_ALIGN (XSAVE_YMM_SIZE / BITS_PER_BYTE)
bool nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set,
const u32 *key, const struct nft_set_ext **ext);
bool nft_pipapo_avx2_estimate(const struct nft_set_desc *desc, u32 features, bool nft_pipapo_avx2_estimate(const struct nft_set_desc *desc, u32 features,
struct nft_set_estimate *est); struct nft_set_estimate *est);
#endif /* defined(CONFIG_X86_64) && !defined(CONFIG_UML) */ #endif /* defined(CONFIG_X86_64) && !defined(CONFIG_UML) */
......
...@@ -107,7 +107,8 @@ static bool __nft_rbtree_lookup(const struct net *net, const struct nft_set *set ...@@ -107,7 +107,8 @@ static bool __nft_rbtree_lookup(const struct net *net, const struct nft_set *set
return false; return false;
} }
static bool nft_rbtree_lookup(const struct net *net, const struct nft_set *set, INDIRECT_CALLABLE_SCOPE
bool nft_rbtree_lookup(const struct net *net, const struct nft_set *set,
const u32 *key, const struct nft_set_ext **ext) const u32 *key, const struct nft_set_ext **ext)
{ {
struct nft_rbtree *priv = nft_set_priv(set); struct nft_rbtree *priv = nft_set_priv(set);
......
...@@ -109,7 +109,7 @@ static void nft_synproxy_do_eval(const struct nft_synproxy *priv, ...@@ -109,7 +109,7 @@ static void nft_synproxy_do_eval(const struct nft_synproxy *priv,
{ {
struct synproxy_options opts = {}; struct synproxy_options opts = {};
struct sk_buff *skb = pkt->skb; struct sk_buff *skb = pkt->skb;
int thoff = pkt->xt.thoff; int thoff = nft_thoff(pkt);
const struct tcphdr *tcp; const struct tcphdr *tcp;
struct tcphdr _tcph; struct tcphdr _tcph;
...@@ -123,7 +123,7 @@ static void nft_synproxy_do_eval(const struct nft_synproxy *priv, ...@@ -123,7 +123,7 @@ static void nft_synproxy_do_eval(const struct nft_synproxy *priv,
return; return;
} }
tcp = skb_header_pointer(skb, pkt->xt.thoff, tcp = skb_header_pointer(skb, thoff,
sizeof(struct tcphdr), sizeof(struct tcphdr),
&_tcph); &_tcph);
if (!tcp) { if (!tcp) {
......
...@@ -82,9 +82,9 @@ static void nft_tproxy_eval_v6(const struct nft_expr *expr, ...@@ -82,9 +82,9 @@ static void nft_tproxy_eval_v6(const struct nft_expr *expr,
const struct nft_tproxy *priv = nft_expr_priv(expr); const struct nft_tproxy *priv = nft_expr_priv(expr);
struct sk_buff *skb = pkt->skb; struct sk_buff *skb = pkt->skb;
const struct ipv6hdr *iph = ipv6_hdr(skb); const struct ipv6hdr *iph = ipv6_hdr(skb);
struct in6_addr taddr; int thoff = nft_thoff(pkt);
int thoff = pkt->xt.thoff;
struct udphdr _hdr, *hp; struct udphdr _hdr, *hp;
struct in6_addr taddr;
__be16 tport = 0; __be16 tport = 0;
struct sock *sk; struct sock *sk;
int l4proto; int l4proto;
......
...@@ -117,7 +117,7 @@ static int audit_tg_check(const struct xt_tgchk_param *par) ...@@ -117,7 +117,7 @@ static int audit_tg_check(const struct xt_tgchk_param *par)
const struct xt_audit_info *info = par->targinfo; const struct xt_audit_info *info = par->targinfo;
if (info->type > XT_AUDIT_TYPE_MAX) { if (info->type > XT_AUDIT_TYPE_MAX) {
pr_info_ratelimited("Audit type out of range (valid range: 0..%hhu)\n", pr_info_ratelimited("Audit type out of range (valid range: 0..%u)\n",
XT_AUDIT_TYPE_MAX); XT_AUDIT_TYPE_MAX);
return -ERANGE; return -ERANGE;
} }
......
...@@ -172,7 +172,6 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par, ...@@ -172,7 +172,6 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par,
goto err2; goto err2;
} }
ret = 0;
if ((info->ct_events || info->exp_events) && if ((info->ct_events || info->exp_events) &&
!nf_ct_ecache_ext_add(ct, info->ct_events, info->exp_events, !nf_ct_ecache_ext_add(ct, info->ct_events, info->exp_events,
GFP_KERNEL)) { GFP_KERNEL)) {
......
...@@ -8,16 +8,14 @@ ...@@ -8,16 +8,14 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/netfilter/x_tables.h> #include <linux/netfilter/x_tables.h>
#include <linux/netfilter/xt_limit.h> #include <linux/netfilter/xt_limit.h>
struct xt_limit_priv { struct xt_limit_priv {
spinlock_t lock;
unsigned long prev; unsigned long prev;
uint32_t credit; u32 credit;
}; };
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -66,22 +64,31 @@ limit_mt(const struct sk_buff *skb, struct xt_action_param *par) ...@@ -66,22 +64,31 @@ limit_mt(const struct sk_buff *skb, struct xt_action_param *par)
{ {
const struct xt_rateinfo *r = par->matchinfo; const struct xt_rateinfo *r = par->matchinfo;
struct xt_limit_priv *priv = r->master; struct xt_limit_priv *priv = r->master;
unsigned long now = jiffies; unsigned long now;
u32 old_credit, new_credit, credit_increase = 0;
spin_lock_bh(&priv->lock); bool ret;
priv->credit += (now - xchg(&priv->prev, now)) * CREDITS_PER_JIFFY;
if (priv->credit > r->credit_cap)
priv->credit = r->credit_cap;
if (priv->credit >= r->cost) {
/* We're not limited. */
priv->credit -= r->cost;
spin_unlock_bh(&priv->lock);
return true;
}
spin_unlock_bh(&priv->lock); /* fastpath if there is nothing to update */
if ((READ_ONCE(priv->credit) < r->cost) && (READ_ONCE(priv->prev) == jiffies))
return false; return false;
do {
now = jiffies;
credit_increase += (now - xchg(&priv->prev, now)) * CREDITS_PER_JIFFY;
old_credit = READ_ONCE(priv->credit);
new_credit = old_credit;
new_credit += credit_increase;
if (new_credit > r->credit_cap)
new_credit = r->credit_cap;
if (new_credit >= r->cost) {
ret = true;
new_credit -= r->cost;
} else {
ret = false;
}
} while (cmpxchg(&priv->credit, old_credit, new_credit) != old_credit);
return ret;
} }
/* Precision saver. */ /* Precision saver. */
...@@ -122,7 +129,6 @@ static int limit_mt_check(const struct xt_mtchk_param *par) ...@@ -122,7 +129,6 @@ static int limit_mt_check(const struct xt_mtchk_param *par)
r->credit_cap = priv->credit; /* Credits full. */ r->credit_cap = priv->credit; /* Credits full. */
r->cost = user2credits(r->avg); r->cost = user2credits(r->avg);
} }
spin_lock_init(&priv->lock);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment