@@ -25,7 +25,10 @@ static inline int NF_DROP_GETERR(int verdict)
static __always_inline int
NF_DROP_REASON(struct sk_buff *skb, enum skb_drop_reason reason, u32 err)
{
- BUILD_BUG_ON(err > 0xffff);
+ if (__builtin_constant_p(err))
+ BUILD_BUG_ON(err > 0xffff);
+ else if (WARN_ON_ONCE(err > 0xffff))
+ err = 0;
kfree_skb_reason(skb, reason);
@@ -166,7 +166,7 @@ static void nft_reject_bridge_eval(const struct nft_expr *expr,
break;
}
out:
- regs->verdict.code = NF_DROP;
+ regs->verdict.code = NF_DROP_REASON(pkt->skb, SKB_DROP_REASON_NETFILTER_DROP, EPERM);
}
static int nft_reject_bridge_validate(const struct nft_ctx *ctx,
@@ -34,7 +34,7 @@ static void nft_reject_ipv4_eval(const struct nft_expr *expr,
break;
}
- regs->verdict.code = NF_DROP;
+ regs->verdict.code = NF_DROP_REASON(pkt->skb, SKB_DROP_REASON_NETFILTER_DROP, EPERM);
}
static struct nft_expr_type nft_reject_ipv4_type;
@@ -70,7 +70,10 @@ static unsigned int ipv6_defrag(void *priv,
if (err == -EINPROGRESS)
return NF_STOLEN;
- return err == 0 ? NF_ACCEPT : NF_DROP;
+ if (err == 0)
+ return NF_ACCEPT;
+
+ return NF_DROP_REASON(skb, SKB_DROP_REASON_NETFILTER_DROP, -err);
}
static const struct nf_hook_ops ipv6_defrag_ops[] = {
@@ -439,7 +439,7 @@ unsigned int nf_nat_manip_pkt(struct sk_buff *skb, struct nf_conn *ct,
break;
}
- return NF_DROP;
+ return NF_DROP_REASON(skb, SKB_DROP_REASON_NETFILTER_DROP, EPERM);
}
static void nf_nat_ipv4_csum_update(struct sk_buff *skb,
@@ -636,7 +636,7 @@ nf_nat_ipv4_fn(void *priv, struct sk_buff *skb,
if (ip_hdr(skb)->protocol == IPPROTO_ICMP) {
if (!nf_nat_icmp_reply_translation(skb, ct, ctinfo,
state->hook))
- return NF_DROP;
+ return NF_DROP_REASON(skb, SKB_DROP_REASON_NETFILTER_DROP, EPERM);
else
return NF_ACCEPT;
}
@@ -781,7 +781,7 @@ nf_nat_ipv4_out(void *priv, struct sk_buff *skb,
ct->tuplehash[!dir].tuple.dst.u.all)) {
err = nf_xfrm_me_harder(state->net, skb, AF_INET);
if (err < 0)
- ret = NF_DROP_ERR(err);
+ ret = NF_DROP_REASON(skb, SKB_DROP_REASON_NETFILTER_DROP, -err);
}
}
#endif
@@ -809,7 +809,7 @@ nf_nat_ipv4_local_fn(void *priv, struct sk_buff *skb,
ct->tuplehash[!dir].tuple.src.u3.ip) {
err = ip_route_me_harder(state->net, state->sk, skb, RTN_UNSPEC);
if (err < 0)
- ret = NF_DROP_ERR(err);
+ ret = NF_DROP_REASON(skb, SKB_DROP_REASON_NETFILTER_DROP, -err);
}
#ifdef CONFIG_XFRM
else if (!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) &&
@@ -818,7 +818,7 @@ nf_nat_ipv4_local_fn(void *priv, struct sk_buff *skb,
ct->tuplehash[!dir].tuple.src.u.all) {
err = nf_xfrm_me_harder(state->net, skb, AF_INET);
if (err < 0)
- ret = NF_DROP_ERR(err);
+ ret = NF_DROP_REASON(skb, SKB_DROP_REASON_NETFILTER_DROP, -err);
}
#endif
}
@@ -965,7 +965,7 @@ nf_nat_ipv6_fn(void *priv, struct sk_buff *skb,
if (!nf_nat_icmpv6_reply_translation(skb, ct, ctinfo,
state->hook,
hdrlen))
- return NF_DROP;
+ return NF_DROP_REASON(skb, SKB_DROP_REASON_NETFILTER_DROP, EPERM);
else
return NF_ACCEPT;
}
@@ -1040,7 +1040,7 @@ nf_nat_ipv6_out(void *priv, struct sk_buff *skb,
ct->tuplehash[!dir].tuple.dst.u.all)) {
err = nf_xfrm_me_harder(state->net, skb, AF_INET6);
if (err < 0)
- ret = NF_DROP_ERR(err);
+ ret = NF_DROP_REASON(skb, SKB_DROP_REASON_NETFILTER_DROP, -err);
}
}
#endif
@@ -1069,7 +1069,7 @@ nf_nat_ipv6_local_fn(void *priv, struct sk_buff *skb,
&ct->tuplehash[!dir].tuple.src.u3)) {
err = nf_ip6_route_me_harder(state->net, state->sk, skb);
if (err < 0)
- ret = NF_DROP_ERR(err);
+ ret = NF_DROP_REASON(skb, SKB_DROP_REASON_NETFILTER_DROP, -err);
}
#ifdef CONFIG_XFRM
else if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) &&
@@ -1078,7 +1078,7 @@ nf_nat_ipv6_local_fn(void *priv, struct sk_buff *skb,
ct->tuplehash[!dir].tuple.src.u.all) {
err = nf_xfrm_me_harder(state->net, skb, AF_INET6);
if (err < 0)
- ret = NF_DROP_ERR(err);
+ ret = NF_DROP_REASON(skb, SKB_DROP_REASON_NETFILTER_DROP, -err);
}
#endif
}
@@ -71,7 +71,7 @@ nf_nat_redirect_ipv4(struct sk_buff *skb, const struct nf_nat_range2 *range,
}
if (!newdst.ip)
- return NF_DROP;
+ return NF_DROP_REASON(skb, SKB_DROP_REASON_NETFILTER_DROP, EPERM);
}
return nf_nat_redirect(skb, range, &newdst);
@@ -130,7 +130,7 @@ nf_nat_redirect_ipv6(struct sk_buff *skb, const struct nf_nat_range2 *range,
}
if (!addr)
- return NF_DROP;
+ return NF_DROP_REASON(skb, SKB_DROP_REASON_NETFILTER_DROP, EPERM);
}
return nf_nat_redirect(skb, range, &newdst);
@@ -664,7 +664,7 @@ ipv4_synproxy_hook(void *priv, struct sk_buff *skb,
thoff = ip_hdrlen(skb);
th = skb_header_pointer(skb, thoff, sizeof(_th), &_th);
if (!th)
- return NF_DROP;
+ return NF_DROP_REASON(skb, SKB_DROP_REASON_NETFILTER_DROP, EPERM);
state = &ct->proto.tcp;
switch (state->state) {
@@ -689,7 +689,7 @@ ipv4_synproxy_hook(void *priv, struct sk_buff *skb,
fallthrough;
case TCP_CONNTRACK_SYN_SENT:
if (!synproxy_parse_options(skb, thoff, th, &opts))
- return NF_DROP;
+ return NF_DROP_REASON(skb, SKB_DROP_REASON_NETFILTER_DROP, EPERM);
if (!th->syn && th->ack &&
CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) {
@@ -703,7 +703,7 @@ ipv4_synproxy_hook(void *priv, struct sk_buff *skb,
consume_skb(skb);
return NF_STOLEN;
} else {
- return NF_DROP;
+ return NF_DROP_REASON(skb, SKB_DROP_REASON_NETFILTER_DROP, EPERM);
}
}
@@ -718,7 +718,7 @@ ipv4_synproxy_hook(void *priv, struct sk_buff *skb,
break;
if (!synproxy_parse_options(skb, thoff, th, &opts))
- return NF_DROP;
+ return NF_DROP_REASON(skb, SKB_DROP_REASON_NETFILTER_DROP, EPERM);
if (opts.options & NF_SYNPROXY_OPT_TIMESTAMP) {
synproxy->tsoff = opts.tsval - synproxy->its;
@@ -1087,7 +1087,7 @@ ipv6_synproxy_hook(void *priv, struct sk_buff *skb,
th = skb_header_pointer(skb, thoff, sizeof(_th), &_th);
if (!th)
- return NF_DROP;
+ return NF_DROP_REASON(skb, SKB_DROP_REASON_NETFILTER_DROP, EPERM);
state = &ct->proto.tcp;
switch (state->state) {
@@ -1112,7 +1112,7 @@ ipv6_synproxy_hook(void *priv, struct sk_buff *skb,
fallthrough;
case TCP_CONNTRACK_SYN_SENT:
if (!synproxy_parse_options(skb, thoff, th, &opts))
- return NF_DROP;
+ return NF_DROP_REASON(skb, SKB_DROP_REASON_NETFILTER_DROP, EPERM);
if (!th->syn && th->ack &&
CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) {
@@ -1126,7 +1126,7 @@ ipv6_synproxy_hook(void *priv, struct sk_buff *skb,
consume_skb(skb);
return NF_STOLEN;
} else {
- return NF_DROP;
+ return NF_DROP_REASON(skb, SKB_DROP_REASON_NETFILTER_DROP, EPERM);
}
}
@@ -1141,7 +1141,7 @@ ipv6_synproxy_hook(void *priv, struct sk_buff *skb,
break;
if (!synproxy_parse_options(skb, thoff, th, &opts))
- return NF_DROP;
+ return NF_DROP_REASON(skb, SKB_DROP_REASON_NETFILTER_DROP, EPERM);
if (opts.options & NF_SYNPROXY_OPT_TIMESTAMP) {
synproxy->tsoff = opts.tsval - synproxy->its;
@@ -175,7 +175,7 @@ static unsigned int nft_do_chain_inet_ingress(void *priv, struct sk_buff *skb,
nft_set_pktinfo(&pkt, skb, &ingress_state);
if (nft_set_pktinfo_ipv4_ingress(&pkt) < 0)
- return NF_DROP;
+ return NF_DROP_REASON(skb, SKB_DROP_REASON_NETFILTER_DROP, EPERM);
break;
case htons(ETH_P_IPV6):
ingress_state.pf = NFPROTO_IPV6;
@@ -183,7 +183,7 @@ static unsigned int nft_do_chain_inet_ingress(void *priv, struct sk_buff *skb,
nft_set_pktinfo(&pkt, skb, &ingress_state);
if (nft_set_pktinfo_ipv6_ingress(&pkt) < 0)
- return NF_DROP;
+ return NF_DROP_REASON(skb, SKB_DROP_REASON_NETFILTER_DROP, EPERM);
break;
default:
return NF_ACCEPT;
@@ -85,7 +85,7 @@ static void nft_target_eval_xt(const struct nft_expr *expr,
ret = target->target(skb, &xt);
if (xt.hotdrop)
- ret = NF_DROP;
+ ret = NF_DROP_REASON(skb, SKB_DROP_REASON_NETFILTER_DROP, EPERM);
switch (ret) {
case XT_CONTINUE:
@@ -112,14 +112,14 @@ static void nft_target_eval_bridge(const struct nft_expr *expr,
ret = target->target(skb, &xt);
if (xt.hotdrop)
- ret = NF_DROP;
+ ret = NF_DROP_REASON(skb, SKB_DROP_REASON_NETFILTER_DROP, EPERM);
switch (ret) {
case EBT_ACCEPT:
regs->verdict.code = NF_ACCEPT;
break;
case EBT_DROP:
- regs->verdict.code = NF_DROP;
+ regs->verdict.code = NF_DROP_REASON(skb, SKB_DROP_REASON_NETFILTER_DROP, EPERM);
break;
case EBT_CONTINUE:
regs->verdict.code = NFT_CONTINUE;
@@ -403,7 +403,7 @@ static void __nft_match_eval(const struct nft_expr *expr,
ret = match->match(skb, &xt);
if (xt.hotdrop) {
- regs->verdict.code = NF_DROP;
+ regs->verdict.code = NF_DROP_REASON(skb, SKB_DROP_REASON_NETFILTER_DROP, EPERM);
return;
}
@@ -39,12 +39,12 @@ static inline void nft_connlimit_do_eval(struct nft_connlimit *priv,
zone = nf_ct_zone(ct);
} else if (!nf_ct_get_tuplepr(pkt->skb, skb_network_offset(pkt->skb),
nft_pf(pkt), nft_net(pkt), &tuple)) {
- regs->verdict.code = NF_DROP;
+ regs->verdict.code = NF_DROP_REASON(pkt->skb, SKB_DROP_REASON_NETFILTER_DROP, EPERM);
return;
}
if (nf_conncount_add(nft_net(pkt), priv->list, tuple_ptr, zone)) {
- regs->verdict.code = NF_DROP;
+ regs->verdict.code = NF_DROP_REASON(pkt->skb, SKB_DROP_REASON_NETFILTER_DROP, EPERM);
return;
}
@@ -259,7 +259,7 @@ static void nft_ct_set_zone_eval(const struct nft_expr *expr,
*/
ct = nf_ct_tmpl_alloc(nft_net(pkt), &zone, GFP_ATOMIC);
if (!ct) {
- regs->verdict.code = NF_DROP;
+ regs->verdict.code = NF_DROP_REASON(skb, SKB_DROP_REASON_NOMEM, ENOMEM);
return;
}
__set_bit(IPS_CONFIRMED_BIT, &ct->status);
@@ -917,7 +917,7 @@ static void nft_ct_timeout_obj_eval(struct nft_object *obj,
if (!timeout) {
timeout = nf_ct_timeout_ext_add(ct, priv->timeout, GFP_ATOMIC);
if (!timeout) {
- regs->verdict.code = NF_DROP;
+ regs->verdict.code = NF_DROP_REASON(pkt->skb, SKB_DROP_REASON_NOMEM, ENOMEM);
return;
}
}
@@ -1316,6 +1316,7 @@ static void nft_ct_expect_obj_eval(struct nft_object *obj,
enum ip_conntrack_dir dir;
u16 l3num = priv->l3num;
struct nf_conn *ct;
+ int err;
ct = nf_ct_get(pkt->skb, &ctinfo);
if (!ct || nf_ct_is_confirmed(ct) || nf_ct_is_template(ct)) {
@@ -1328,7 +1329,7 @@ static void nft_ct_expect_obj_eval(struct nft_object *obj,
if (!help)
help = nf_ct_helper_ext_add(ct, GFP_ATOMIC);
if (!help) {
- regs->verdict.code = NF_DROP;
+ regs->verdict.code = NF_DROP_REASON(pkt->skb, SKB_DROP_REASON_NOMEM, ENOMEM);
return;
}
@@ -1341,7 +1342,7 @@ static void nft_ct_expect_obj_eval(struct nft_object *obj,
exp = nf_ct_expect_alloc(ct);
if (exp == NULL) {
- regs->verdict.code = NF_DROP;
+ regs->verdict.code = NF_DROP_REASON(pkt->skb, SKB_DROP_REASON_NOMEM, ENOMEM);
return;
}
nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, l3num,
@@ -1350,8 +1351,9 @@ static void nft_ct_expect_obj_eval(struct nft_object *obj,
priv->l4proto, NULL, &priv->dport);
exp->timeout.expires = jiffies + priv->timeout * HZ;
- if (nf_ct_expect_related(exp, 0) != 0)
- regs->verdict.code = NF_DROP;
+ err = nf_ct_expect_related(exp, 0);
+ if (err != 0)
+ regs->verdict.code = NF_DROP_REASON(pkt->skb, SKB_DROP_REASON_NETFILTER_DROP, -err);
}
static const struct nla_policy nft_ct_expect_policy[NFTA_CT_EXPECT_MAX + 1] = {
@@ -365,7 +365,7 @@ static void nft_exthdr_tcp_strip_eval(const struct nft_expr *expr,
return;
drop:
/* can't remove, no choice but to drop */
- regs->verdict.code = NF_DROP;
+ regs->verdict.code = NF_DROP_REASON(pkt->skb, SKB_DROP_REASON_NETFILTER_DROP, EPERM);
}
static void nft_exthdr_sctp_eval(const struct nft_expr *expr,
@@ -38,7 +38,7 @@ static void nft_fib_inet_eval(const struct nft_expr *expr,
break;
}
- regs->verdict.code = NF_DROP;
+ regs->verdict.code = NF_DROP_REASON(pkt->skb, SKB_DROP_REASON_NETFILTER_DROP, EPERM);
}
static struct nft_expr_type nft_fib_inet_type;
@@ -112,7 +112,7 @@ static void nft_fwd_neigh_eval(const struct nft_expr *expr,
goto out;
}
if (skb_try_make_writable(skb, sizeof(*iph))) {
- verdict = NF_DROP;
+ verdict = NF_DROP_REASON(skb, SKB_DROP_REASON_NETFILTER_DROP, EPERM);
goto out;
}
iph = ip_hdr(skb);
@@ -128,7 +128,7 @@ static void nft_fwd_neigh_eval(const struct nft_expr *expr,
goto out;
}
if (skb_try_make_writable(skb, sizeof(*ip6h))) {
- verdict = NF_DROP;
+ verdict = NF_DROP_REASON(skb, SKB_DROP_REASON_NETFILTER_DROP, EPERM);
goto out;
}
ip6h = ipv6_hdr(skb);
@@ -57,7 +57,7 @@ static void nft_reject_inet_eval(const struct nft_expr *expr,
break;
}
- regs->verdict.code = NF_DROP;
+ regs->verdict.code = NF_DROP_REASON(pkt->skb, SKB_DROP_REASON_NETFILTER_DROP, EPERM);
}
static int nft_reject_inet_validate(const struct nft_ctx *ctx,
@@ -141,7 +141,7 @@ static void nft_reject_netdev_eval(const struct nft_expr *expr,
break;
}
out:
- regs->verdict.code = NF_DROP;
+ regs->verdict.code = NF_DROP_REASON(pkt->skb, SKB_DROP_REASON_NETFILTER_DROP, EPERM);
}
static int nft_reject_netdev_validate(const struct nft_ctx *ctx,
@@ -66,7 +66,7 @@ static void nft_synproxy_eval_v4(const struct nft_synproxy *priv,
consume_skb(skb);
regs->verdict.code = NF_STOLEN;
} else {
- regs->verdict.code = NF_DROP;
+ regs->verdict.code = NF_DROP_REASON(skb, SKB_DROP_REASON_NETFILTER_DROP, EPERM);
}
}
}
@@ -97,7 +97,7 @@ static void nft_synproxy_eval_v6(const struct nft_synproxy *priv,
consume_skb(skb);
regs->verdict.code = NF_STOLEN;
} else {
- regs->verdict.code = NF_DROP;
+ regs->verdict.code = NF_DROP_REASON(skb, SKB_DROP_REASON_NETFILTER_DROP, EPERM);
}
}
}
@@ -119,7 +119,7 @@ static void nft_synproxy_do_eval(const struct nft_synproxy *priv,
}
if (nf_ip_checksum(skb, nft_hook(pkt), thoff, IPPROTO_TCP)) {
- regs->verdict.code = NF_DROP;
+ regs->verdict.code = NF_DROP_REASON(skb, SKB_DROP_REASON_NETFILTER_DROP, EPERM);
return;
}
@@ -127,12 +127,12 @@ static void nft_synproxy_do_eval(const struct nft_synproxy *priv,
sizeof(struct tcphdr),
&_tcph);
if (!tcp) {
- regs->verdict.code = NF_DROP;
+ regs->verdict.code = NF_DROP_REASON(skb, SKB_DROP_REASON_NETFILTER_DROP, EPERM);
return;
}
if (!synproxy_parse_options(skb, thoff, tcp, &opts)) {
- regs->verdict.code = NF_DROP;
+ regs->verdict.code = NF_DROP_REASON(skb, SKB_DROP_REASON_NETFILTER_DROP, EPERM);
return;
}
same as previous patch: extend nftables nat and masquerade functions to indicate more precise drop locations. Signed-off-by: Florian Westphal <fw@strlen.de> --- include/linux/netfilter.h | 5 ++++- net/bridge/netfilter/nft_reject_bridge.c | 2 +- net/ipv4/netfilter/nft_reject_ipv4.c | 2 +- net/ipv6/netfilter/nf_defrag_ipv6_hooks.c | 5 ++++- net/netfilter/nf_nat_proto.c | 18 +++++++++--------- net/netfilter/nf_nat_redirect.c | 4 ++-- net/netfilter/nf_synproxy_core.c | 16 ++++++++-------- net/netfilter/nft_chain_filter.c | 4 ++-- net/netfilter/nft_compat.c | 8 ++++---- net/netfilter/nft_connlimit.c | 4 ++-- net/netfilter/nft_ct.c | 14 ++++++++------ net/netfilter/nft_exthdr.c | 2 +- net/netfilter/nft_fib_inet.c | 2 +- net/netfilter/nft_fwd_netdev.c | 4 ++-- net/netfilter/nft_reject_inet.c | 2 +- net/netfilter/nft_reject_netdev.c | 2 +- net/netfilter/nft_synproxy.c | 10 +++++----- 17 files changed, 56 insertions(+), 48 deletions(-)