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: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
@@ -302,26 +302,6 @@ void _nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(_nf_unregister_hooks);
|
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,
|
/* Returns 1 if okfn() needs to be executed by the caller,
|
||||||
* -EPERM for NF_DROP, 0 otherwise. Caller must hold rcu_read_lock. */
|
* -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,
|
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;
|
unsigned int verdict;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
next_hook:
|
do {
|
||||||
verdict = nf_iterate(skb, state, &entry);
|
verdict = entry->ops.hook(entry->ops.priv, skb, state);
|
||||||
switch (verdict & NF_VERDICT_MASK) {
|
switch (verdict & NF_VERDICT_MASK) {
|
||||||
case NF_ACCEPT:
|
case NF_ACCEPT:
|
||||||
ret = 1;
|
entry = rcu_dereference(entry->next);
|
||||||
break;
|
break;
|
||||||
case NF_DROP:
|
case NF_DROP:
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
ret = NF_DROP_GETERR(verdict);
|
ret = NF_DROP_GETERR(verdict);
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
ret = -EPERM;
|
ret = -EPERM;
|
||||||
break;
|
return ret;
|
||||||
case NF_QUEUE:
|
case NF_REPEAT:
|
||||||
ret = nf_queue(skb, state, &entry, verdict);
|
continue;
|
||||||
if (ret == 1 && entry)
|
case NF_QUEUE:
|
||||||
goto next_hook;
|
ret = nf_queue(skb, state, &entry, verdict);
|
||||||
/* Fall through. */
|
if (ret == 1 && entry)
|
||||||
default:
|
continue;
|
||||||
/* Implicit handling for NF_STOLEN, as well as any other non
|
return ret;
|
||||||
* conventional verdicts.
|
default:
|
||||||
*/
|
/* Implicit handling for NF_STOLEN, as well as any other
|
||||||
ret = 0;
|
* non conventional verdicts.
|
||||||
break;
|
*/
|
||||||
}
|
return 0;
|
||||||
return ret;
|
}
|
||||||
|
} while (entry);
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(nf_hook_slow);
|
EXPORT_SYMBOL(nf_hook_slow);
|
||||||
|
|
||||||
|
|||||||
@@ -11,11 +11,6 @@
|
|||||||
#define NFDEBUG(format, args...)
|
#define NFDEBUG(format, args...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* core.c */
|
|
||||||
unsigned int nf_iterate(struct sk_buff *skb, struct nf_hook_state *state,
|
|
||||||
struct nf_hook_entry **entryp);
|
|
||||||
|
|
||||||
/* nf_queue.c */
|
/* nf_queue.c */
|
||||||
int nf_queue(struct sk_buff *skb, struct nf_hook_state *state,
|
int nf_queue(struct sk_buff *skb, struct nf_hook_state *state,
|
||||||
struct nf_hook_entry **entryp, unsigned int verdict);
|
struct nf_hook_entry **entryp, unsigned int verdict);
|
||||||
|
|||||||
@@ -177,6 +177,26 @@ int nf_queue(struct sk_buff *skb, struct nf_hook_state *state,
|
|||||||
return 0;
|
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)
|
void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
|
||||||
{
|
{
|
||||||
struct nf_hook_entry *hook_entry = entry->hook;
|
struct nf_hook_entry *hook_entry = entry->hook;
|
||||||
|
|||||||
Reference in New Issue
Block a user