mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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: Florian Westphal <fw@strlen.de> Reviewed-by: Simon Horman <horms@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									2f5e639571
								
							
						
					
					
						commit
						3abbd7ed8b
					
				
					 1 changed files with 25 additions and 6 deletions
				
			
		| 
						 | 
					@ -944,6 +944,8 @@ static int tcf_ct_act_nat(struct sk_buff *skb,
 | 
				
			||||||
		action |= BIT(NF_NAT_MANIP_DST);
 | 
							action |= BIT(NF_NAT_MANIP_DST);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = nf_ct_nat(skb, ct, ctinfo, &action, range, commit);
 | 
						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))
 | 
						if (action & BIT(NF_NAT_MANIP_SRC))
 | 
				
			||||||
		tc_skb_cb(skb)->post_ct_snat = 1;
 | 
							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;
 | 
							state.pf = family;
 | 
				
			||||||
		err = nf_conntrack_in(skb, &state);
 | 
							err = nf_conntrack_in(skb, &state);
 | 
				
			||||||
		if (err != NF_ACCEPT)
 | 
							if (err != NF_ACCEPT)
 | 
				
			||||||
			goto out_push;
 | 
								goto nf_error;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
do_nat:
 | 
					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);
 | 
						err = tcf_ct_act_nat(skb, ct, ctinfo, p->ct_action, &p->range, commit);
 | 
				
			||||||
	if (err != NF_ACCEPT)
 | 
						if (err != NF_ACCEPT)
 | 
				
			||||||
		goto drop;
 | 
							goto nf_error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!nf_ct_is_confirmed(ct) && commit && p->helper && !nfct_help(ct)) {
 | 
						if (!nf_ct_is_confirmed(ct) && commit && p->helper && !nfct_help(ct)) {
 | 
				
			||||||
		err = __nf_ct_try_assign_helper(ct, p->tmpl, GFP_ATOMIC);
 | 
							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_is_confirmed(ct) ? ((!cached && !skip_add) || add_helper) : commit) {
 | 
				
			||||||
		if (nf_ct_helper(skb, ct, ctinfo, family) != NF_ACCEPT)
 | 
							err = nf_ct_helper(skb, ct, ctinfo, family);
 | 
				
			||||||
			goto drop;
 | 
							if (err != NF_ACCEPT)
 | 
				
			||||||
 | 
								goto nf_error;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (commit) {
 | 
						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
 | 
							/* This will take care of sending queued events
 | 
				
			||||||
		 * even if the connection is already confirmed.
 | 
							 * even if the connection is already confirmed.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		if (nf_conntrack_confirm(skb) != NF_ACCEPT)
 | 
							err = nf_conntrack_confirm(skb);
 | 
				
			||||||
			goto drop;
 | 
							if (err != NF_ACCEPT)
 | 
				
			||||||
 | 
								goto nf_error;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!skip_add)
 | 
						if (!skip_add)
 | 
				
			||||||
| 
						 | 
					@ -1100,6 +1104,21 @@ TC_INDIRECT_SCOPE int tcf_ct_act(struct sk_buff *skb, const struct tc_action *a,
 | 
				
			||||||
drop:
 | 
					drop:
 | 
				
			||||||
	tcf_action_inc_drop_qstats(&c->common);
 | 
						tcf_action_inc_drop_qstats(&c->common);
 | 
				
			||||||
	return TC_ACT_SHOT;
 | 
						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] = {
 | 
					static const struct nla_policy ct_policy[TCA_CT_MAX + 1] = {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue