linux/net/netfilter/nf_queue.c
<<
>>
Prefs
   1/*
   2 * Rusty Russell (C)2000 -- This code is GPL.
   3 * Patrick McHardy (c) 2006-2012
   4 */
   5
   6#include <linux/kernel.h>
   7#include <linux/slab.h>
   8#include <linux/init.h>
   9#include <linux/module.h>
  10#include <linux/proc_fs.h>
  11#include <linux/skbuff.h>
  12#include <linux/netfilter.h>
  13#include <linux/netfilter_bridge.h>
  14#include <linux/seq_file.h>
  15#include <linux/rcupdate.h>
  16#include <net/protocol.h>
  17#include <net/netfilter/nf_queue.h>
  18#include <net/dst.h>
  19
  20#include "nf_internals.h"
  21
  22/*
  23 * Hook for nfnetlink_queue to register its queue handler.
  24 * We do this so that most of the NFQUEUE code can be modular.
  25 *
  26 * Once the queue is registered it must reinject all packets it
  27 * receives, no matter what.
  28 */
  29
  30/* return EBUSY when somebody else is registered, return EEXIST if the
  31 * same handler is registered, return 0 in case of success. */
  32void nf_register_queue_handler(struct net *net, const struct nf_queue_handler *qh)
  33{
  34        /* should never happen, we only have one queueing backend in kernel */
  35        WARN_ON(rcu_access_pointer(net->nf.queue_handler));
  36        rcu_assign_pointer(net->nf.queue_handler, qh);
  37}
  38EXPORT_SYMBOL(nf_register_queue_handler);
  39
  40/* The caller must flush their queue before this */
  41void nf_unregister_queue_handler(struct net *net)
  42{
  43        RCU_INIT_POINTER(net->nf.queue_handler, NULL);
  44}
  45EXPORT_SYMBOL(nf_unregister_queue_handler);
  46
  47void nf_queue_entry_release_refs(struct nf_queue_entry *entry)
  48{
  49        struct nf_hook_state *state = &entry->state;
  50
  51        /* Release those devices we held, or Alexey will kill me. */
  52        if (state->in)
  53                dev_put(state->in);
  54        if (state->out)
  55                dev_put(state->out);
  56        if (state->sk)
  57                sock_put(state->sk);
  58#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
  59        if (entry->skb->nf_bridge) {
  60                struct net_device *physdev;
  61
  62                physdev = nf_bridge_get_physindev(entry->skb);
  63                if (physdev)
  64                        dev_put(physdev);
  65                physdev = nf_bridge_get_physoutdev(entry->skb);
  66                if (physdev)
  67                        dev_put(physdev);
  68        }
  69#endif
  70}
  71EXPORT_SYMBOL_GPL(nf_queue_entry_release_refs);
  72
  73/* Bump dev refs so they don't vanish while packet is out */
  74void nf_queue_entry_get_refs(struct nf_queue_entry *entry)
  75{
  76        struct nf_hook_state *state = &entry->state;
  77
  78        if (state->in)
  79                dev_hold(state->in);
  80        if (state->out)
  81                dev_hold(state->out);
  82        if (state->sk)
  83                sock_hold(state->sk);
  84#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
  85        if (entry->skb->nf_bridge) {
  86                struct net_device *physdev;
  87
  88                physdev = nf_bridge_get_physindev(entry->skb);
  89                if (physdev)
  90                        dev_hold(physdev);
  91                physdev = nf_bridge_get_physoutdev(entry->skb);
  92                if (physdev)
  93                        dev_hold(physdev);
  94        }
  95#endif
  96}
  97EXPORT_SYMBOL_GPL(nf_queue_entry_get_refs);
  98
  99unsigned int nf_queue_nf_hook_drop(struct net *net)
 100{
 101        const struct nf_queue_handler *qh;
 102        unsigned int count = 0;
 103
 104        rcu_read_lock();
 105        qh = rcu_dereference(net->nf.queue_handler);
 106        if (qh)
 107                count = qh->nf_hook_drop(net);
 108        rcu_read_unlock();
 109
 110        return count;
 111}
 112
 113static int __nf_queue(struct sk_buff *skb, const struct nf_hook_state *state,
 114                      struct nf_hook_entry *hook_entry, unsigned int queuenum)
 115{
 116        int status = -ENOENT;
 117        struct nf_queue_entry *entry = NULL;
 118        const struct nf_afinfo *afinfo;
 119        const struct nf_queue_handler *qh;
 120        struct net *net = state->net;
 121
 122        /* QUEUE == DROP if no one is waiting, to be safe. */
 123        qh = rcu_dereference(net->nf.queue_handler);
 124        if (!qh) {
 125                status = -ESRCH;
 126                goto err;
 127        }
 128
 129        afinfo = nf_get_afinfo(state->pf);
 130        if (!afinfo)
 131                goto err;
 132
 133        entry = kmalloc(sizeof(*entry) + afinfo->route_key_size, GFP_ATOMIC);
 134        if (!entry) {
 135                status = -ENOMEM;
 136                goto err;
 137        }
 138
 139        *entry = (struct nf_queue_entry) {
 140                .skb    = skb,
 141                .state  = *state,
 142                .hook   = hook_entry,
 143                .size   = sizeof(*entry) + afinfo->route_key_size,
 144        };
 145
 146        nf_queue_entry_get_refs(entry);
 147        skb_dst_force(skb);
 148        afinfo->saveroute(skb, entry);
 149        status = qh->outfn(entry, queuenum);
 150
 151        if (status < 0) {
 152                nf_queue_entry_release_refs(entry);
 153                goto err;
 154        }
 155
 156        return 0;
 157
 158err:
 159        kfree(entry);
 160        return status;
 161}
 162
 163/* Packets leaving via this function must come back through nf_reinject(). */
 164int nf_queue(struct sk_buff *skb, struct nf_hook_state *state,
 165             struct nf_hook_entry **entryp, unsigned int verdict)
 166{
 167        struct nf_hook_entry *entry = *entryp;
 168        int ret;
 169
 170        ret = __nf_queue(skb, state, entry, verdict >> NF_VERDICT_QBITS);
 171        if (ret < 0) {
 172                if (ret == -ESRCH &&
 173                    (verdict & NF_VERDICT_FLAG_QUEUE_BYPASS)) {
 174                        *entryp = rcu_dereference(entry->next);
 175                        return 1;
 176                }
 177                kfree_skb(skb);
 178        }
 179
 180        return 0;
 181}
 182
 183static unsigned int nf_iterate(struct sk_buff *skb,
 184                               struct nf_hook_state *state,
 185                               struct nf_hook_entry **entryp)
 186{
 187        unsigned int verdict;
 188
 189        do {
 190repeat:
 191                verdict = nf_hook_entry_hookfn((*entryp), skb, state);
 192                if (verdict != NF_ACCEPT) {
 193                        if (verdict != NF_REPEAT)
 194                                return verdict;
 195                        goto repeat;
 196                }
 197                *entryp = rcu_dereference((*entryp)->next);
 198        } while (*entryp);
 199
 200        return NF_ACCEPT;
 201}
 202
 203void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
 204{
 205        struct nf_hook_entry *hook_entry = entry->hook;
 206        struct sk_buff *skb = entry->skb;
 207        const struct nf_afinfo *afinfo;
 208        int err;
 209
 210        nf_queue_entry_release_refs(entry);
 211
 212        /* Continue traversal iff userspace said ok... */
 213        if (verdict == NF_REPEAT)
 214                verdict = nf_hook_entry_hookfn(hook_entry, skb, &entry->state);
 215
 216        if (verdict == NF_ACCEPT) {
 217                afinfo = nf_get_afinfo(entry->state.pf);
 218                if (!afinfo || afinfo->reroute(entry->state.net, skb, entry) < 0)
 219                        verdict = NF_DROP;
 220        }
 221
 222        if (verdict == NF_ACCEPT) {
 223                hook_entry = rcu_dereference(hook_entry->next);
 224                if (hook_entry)
 225next_hook:
 226                        verdict = nf_iterate(skb, &entry->state, &hook_entry);
 227        }
 228
 229        switch (verdict & NF_VERDICT_MASK) {
 230        case NF_ACCEPT:
 231        case NF_STOP:
 232okfn:
 233                local_bh_disable();
 234                entry->state.okfn(entry->state.net, entry->state.sk, skb);
 235                local_bh_enable();
 236                break;
 237        case NF_QUEUE:
 238                err = nf_queue(skb, &entry->state, &hook_entry, verdict);
 239                if (err == 1) {
 240                        if (hook_entry)
 241                                goto next_hook;
 242                        goto okfn;
 243                }
 244                break;
 245        case NF_STOLEN:
 246                break;
 247        default:
 248                kfree_skb(skb);
 249        }
 250
 251        kfree(entry);
 252}
 253EXPORT_SYMBOL(nf_reinject);
 254