]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - include/linux/netfilter.h
mm/memory_hotplug: export generic_online_page()
[linux.git] / include / linux / netfilter.h
index 77ebb61faf48634f63e0756787c435a6abcbcfcd..eb312e7ca36ee5dcdd1691b4b6dcb2fb5f7c4349 100644 (file)
@@ -199,6 +199,8 @@ extern struct static_key nf_hooks_needed[NFPROTO_NUMPROTO][NF_MAX_HOOKS];
 int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state,
                 const struct nf_hook_entries *e, unsigned int i);
 
+void nf_hook_slow_list(struct list_head *head, struct nf_hook_state *state,
+                      const struct nf_hook_entries *e);
 /**
  *     nf_hook - call a netfilter hook
  *
@@ -311,17 +313,36 @@ NF_HOOK_LIST(uint8_t pf, unsigned int hook, struct net *net, struct sock *sk,
             struct list_head *head, struct net_device *in, struct net_device *out,
             int (*okfn)(struct net *, struct sock *, struct sk_buff *))
 {
-       struct sk_buff *skb, *next;
-       struct list_head sublist;
-
-       INIT_LIST_HEAD(&sublist);
-       list_for_each_entry_safe(skb, next, head, list) {
-               list_del(&skb->list);
-               if (nf_hook(pf, hook, net, sk, skb, in, out, okfn) == 1)
-                       list_add_tail(&skb->list, &sublist);
+       struct nf_hook_entries *hook_head = NULL;
+
+#ifdef CONFIG_JUMP_LABEL
+       if (__builtin_constant_p(pf) &&
+           __builtin_constant_p(hook) &&
+           !static_key_false(&nf_hooks_needed[pf][hook]))
+               return;
+#endif
+
+       rcu_read_lock();
+       switch (pf) {
+       case NFPROTO_IPV4:
+               hook_head = rcu_dereference(net->nf.hooks_ipv4[hook]);
+               break;
+       case NFPROTO_IPV6:
+               hook_head = rcu_dereference(net->nf.hooks_ipv6[hook]);
+               break;
+       default:
+               WARN_ON_ONCE(1);
+               break;
        }
-       /* Put passed packets back on main list */
-       list_splice(&sublist, head);
+
+       if (hook_head) {
+               struct nf_hook_state state;
+
+               nf_hook_state_init(&state, hook, pf, in, out, sk, net, okfn);
+
+               nf_hook_slow_list(head, &state, hook_head);
+       }
+       rcu_read_unlock();
 }
 
 /* Call setsockopt() */