Commit 3abbd7ed authored by Florian Westphal's avatar Florian Westphal Committed by David S. Miller
Browse files

act_ct: prepare for stolen verdict coming from conntrack and nat engine



At this time, conntrack either returns NF_ACCEPT or NF_DROP.
To improve debuging it would be nice to be able to replace NF_DROP verdict
with NF_DROP_REASON() helper,

This helper releases the skb instantly (so drop_monitor can pinpoint
exact location) and returns NF_STOLEN.

Prepare call sites to deal with this before introducing such changes
in conntrack and nat core.

Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
Reviewed-by: default avatarSimon Horman <horms@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 2f5e6395
Loading
Loading
Loading
Loading
+25 −6
Original line number Diff line number Diff line
@@ -944,6 +944,8 @@ static int tcf_ct_act_nat(struct sk_buff *skb,
		action |= BIT(NF_NAT_MANIP_DST);

	err = nf_ct_nat(skb, ct, ctinfo, &action, range, commit);
	if (err != NF_ACCEPT)
		return err & NF_VERDICT_MASK;

	if (action & BIT(NF_NAT_MANIP_SRC))
		tc_skb_cb(skb)->post_ct_snat = 1;
@@ -1035,7 +1037,7 @@ TC_INDIRECT_SCOPE int tcf_ct_act(struct sk_buff *skb, const struct tc_action *a,
		state.pf = family;
		err = nf_conntrack_in(skb, &state);
		if (err != NF_ACCEPT)
			goto out_push;
			goto nf_error;
	}

do_nat:
@@ -1047,7 +1049,7 @@ TC_INDIRECT_SCOPE int tcf_ct_act(struct sk_buff *skb, const struct tc_action *a,

	err = tcf_ct_act_nat(skb, ct, ctinfo, p->ct_action, &p->range, commit);
	if (err != NF_ACCEPT)
		goto drop;
		goto nf_error;

	if (!nf_ct_is_confirmed(ct) && commit && p->helper && !nfct_help(ct)) {
		err = __nf_ct_try_assign_helper(ct, p->tmpl, GFP_ATOMIC);
@@ -1061,8 +1063,9 @@ TC_INDIRECT_SCOPE int tcf_ct_act(struct sk_buff *skb, const struct tc_action *a,
	}

	if (nf_ct_is_confirmed(ct) ? ((!cached && !skip_add) || add_helper) : commit) {
		if (nf_ct_helper(skb, ct, ctinfo, family) != NF_ACCEPT)
			goto drop;
		err = nf_ct_helper(skb, ct, ctinfo, family);
		if (err != NF_ACCEPT)
			goto nf_error;
	}

	if (commit) {
@@ -1075,8 +1078,9 @@ TC_INDIRECT_SCOPE int tcf_ct_act(struct sk_buff *skb, const struct tc_action *a,
		/* This will take care of sending queued events
		 * even if the connection is already confirmed.
		 */
		if (nf_conntrack_confirm(skb) != NF_ACCEPT)
			goto drop;
		err = nf_conntrack_confirm(skb);
		if (err != NF_ACCEPT)
			goto nf_error;
	}

	if (!skip_add)
@@ -1100,6 +1104,21 @@ TC_INDIRECT_SCOPE int tcf_ct_act(struct sk_buff *skb, const struct tc_action *a,
drop:
	tcf_action_inc_drop_qstats(&c->common);
	return TC_ACT_SHOT;

nf_error:
	/* some verdicts store extra data in upper bits, such
	 * as errno or queue number.
	 */
	switch (err & NF_VERDICT_MASK) {
	case NF_DROP:
		goto drop;
	case NF_STOLEN:
		tcf_action_inc_drop_qstats(&c->common);
		return TC_ACT_CONSUMED;
	default:
		DEBUG_NET_WARN_ON_ONCE(1);
		goto drop;
	}
}

static const struct nla_policy ct_policy[TCA_CT_MAX + 1] = {