Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 26dfab72 authored by Pablo Neira Ayuso's avatar Pablo Neira Ayuso
Browse files

netfilter: merge nf_iterate() into nf_hook_slow()



nf_iterate() has become rather simple, we can integrate this code into
nf_hook_slow() to reduce the amount of LOC in the core path.

However, we still need nf_iterate() around for nf_queue packet handling,
so move this function there where we only need it. I think it should be
possible to refactor nf_queue code to get rid of it definitely, but
given this is slow path anyway, let's have a look this later.

Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 01886bd9
Loading
Loading
Loading
Loading
+28 −45
Original line number Diff line number Diff line
@@ -302,26 +302,6 @@ void _nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n)
}
EXPORT_SYMBOL(_nf_unregister_hooks);

unsigned int nf_iterate(struct sk_buff *skb,
			struct nf_hook_state *state,
			struct nf_hook_entry **entryp)
{
	unsigned int verdict;

	do {
repeat:
		verdict = (*entryp)->ops.hook((*entryp)->ops.priv, skb, state);
		if (verdict != NF_ACCEPT) {
			if (verdict != NF_REPEAT)
				return verdict;
			goto repeat;
		}
		*entryp = rcu_dereference((*entryp)->next);
	} while (*entryp);
	return NF_ACCEPT;
}


/* Returns 1 if okfn() needs to be executed by the caller,
 * -EPERM for NF_DROP, 0 otherwise.  Caller must hold rcu_read_lock. */
int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state,
@@ -330,31 +310,34 @@ int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state,
	unsigned int verdict;
	int ret;

next_hook:
	verdict = nf_iterate(skb, state, &entry);
	do {
		verdict = entry->ops.hook(entry->ops.priv, skb, state);
		switch (verdict & NF_VERDICT_MASK) {
		case NF_ACCEPT:
		ret = 1;
			entry = rcu_dereference(entry->next);
			break;
		case NF_DROP:
			kfree_skb(skb);
			ret = NF_DROP_GETERR(verdict);
			if (ret == 0)
				ret = -EPERM;
		break;
			return ret;
		case NF_REPEAT:
			continue;
		case NF_QUEUE:
			ret = nf_queue(skb, state, &entry, verdict);
			if (ret == 1 && entry)
			goto next_hook;
		/* Fall through. */
				continue;
			return ret;
		default:
		/* Implicit handling for NF_STOLEN, as well as any other non
		 * conventional verdicts.
			/* Implicit handling for NF_STOLEN, as well as any other
			 * non conventional verdicts.
			 */
		ret = 0;
		break;
			return 0;
		}
	return ret;
	} while (entry);

	return 1;
}
EXPORT_SYMBOL(nf_hook_slow);

+0 −5
Original line number Diff line number Diff line
@@ -11,11 +11,6 @@
#define NFDEBUG(format, args...)
#endif


/* core.c */
unsigned int nf_iterate(struct sk_buff *skb, struct nf_hook_state *state,
			struct nf_hook_entry **entryp);

/* nf_queue.c */
int nf_queue(struct sk_buff *skb, struct nf_hook_state *state,
	     struct nf_hook_entry **entryp, unsigned int verdict);
+20 −0
Original line number Diff line number Diff line
@@ -177,6 +177,26 @@ int nf_queue(struct sk_buff *skb, struct nf_hook_state *state,
	return 0;
}

static unsigned int nf_iterate(struct sk_buff *skb,
			       struct nf_hook_state *state,
			       struct nf_hook_entry **entryp)
{
	unsigned int verdict;

	do {
repeat:
		verdict = (*entryp)->ops.hook((*entryp)->ops.priv, skb, state);
		if (verdict != NF_ACCEPT) {
			if (verdict != NF_REPEAT)
				return verdict;
			goto repeat;
		}
		*entryp = rcu_dereference((*entryp)->next);
	} while (*entryp);

	return NF_ACCEPT;
}

void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
{
	struct nf_hook_entry *hook_entry = entry->hook;