linux/net/netfilter/core.c
<<
>>
Prefs
   1/* netfilter.c: look after the filters for various protocols.
   2 * Heavily influenced by the old firewall.c by David Bonn and Alan Cox.
   3 *
   4 * Thanks to Rob `CmdrTaco' Malda for not influencing this code in any
   5 * way.
   6 *
   7 * Rusty Russell (C)2000 -- This code is GPL.
   8 * Patrick McHardy (c) 2006-2012
   9 */
  10#include <linux/kernel.h>
  11#include <linux/netfilter.h>
  12#include <net/protocol.h>
  13#include <linux/init.h>
  14#include <linux/skbuff.h>
  15#include <linux/wait.h>
  16#include <linux/module.h>
  17#include <linux/interrupt.h>
  18#include <linux/if.h>
  19#include <linux/netdevice.h>
  20#include <linux/inetdevice.h>
  21#include <linux/proc_fs.h>
  22#include <linux/mutex.h>
  23#include <linux/slab.h>
  24#include <net/net_namespace.h>
  25#include <net/sock.h>
  26
  27#include "nf_internals.h"
  28
  29static DEFINE_MUTEX(afinfo_mutex);
  30
  31const struct nf_afinfo __rcu *nf_afinfo[NFPROTO_NUMPROTO] __read_mostly;
  32EXPORT_SYMBOL(nf_afinfo);
  33const struct nf_ipv6_ops __rcu *nf_ipv6_ops __read_mostly;
  34EXPORT_SYMBOL_GPL(nf_ipv6_ops);
  35
  36int nf_register_afinfo(const struct nf_afinfo *afinfo)
  37{
  38        int err;
  39
  40        err = mutex_lock_interruptible(&afinfo_mutex);
  41        if (err < 0)
  42                return err;
  43        RCU_INIT_POINTER(nf_afinfo[afinfo->family], afinfo);
  44        mutex_unlock(&afinfo_mutex);
  45        return 0;
  46}
  47EXPORT_SYMBOL_GPL(nf_register_afinfo);
  48
  49void nf_unregister_afinfo(const struct nf_afinfo *afinfo)
  50{
  51        mutex_lock(&afinfo_mutex);
  52        RCU_INIT_POINTER(nf_afinfo[afinfo->family], NULL);
  53        mutex_unlock(&afinfo_mutex);
  54        synchronize_rcu();
  55}
  56EXPORT_SYMBOL_GPL(nf_unregister_afinfo);
  57
  58struct list_head nf_hooks[NFPROTO_NUMPROTO][NF_MAX_HOOKS] __read_mostly;
  59EXPORT_SYMBOL(nf_hooks);
  60
  61#if defined(CONFIG_JUMP_LABEL)
  62struct static_key nf_hooks_needed[NFPROTO_NUMPROTO][NF_MAX_HOOKS];
  63EXPORT_SYMBOL(nf_hooks_needed);
  64#endif
  65
  66static DEFINE_MUTEX(nf_hook_mutex);
  67
  68int nf_register_hook(struct nf_hook_ops *reg)
  69{
  70        struct nf_hook_ops *elem;
  71        int err;
  72
  73        err = mutex_lock_interruptible(&nf_hook_mutex);
  74        if (err < 0)
  75                return err;
  76        list_for_each_entry(elem, &nf_hooks[reg->pf][reg->hooknum], list) {
  77                if (reg->priority < elem->priority)
  78                        break;
  79        }
  80        list_add_rcu(&reg->list, elem->list.prev);
  81        mutex_unlock(&nf_hook_mutex);
  82#if defined(CONFIG_JUMP_LABEL)
  83        static_key_slow_inc(&nf_hooks_needed[reg->pf][reg->hooknum]);
  84#endif
  85        return 0;
  86}
  87EXPORT_SYMBOL(nf_register_hook);
  88
  89void nf_unregister_hook(struct nf_hook_ops *reg)
  90{
  91        mutex_lock(&nf_hook_mutex);
  92        list_del_rcu(&reg->list);
  93        mutex_unlock(&nf_hook_mutex);
  94#if defined(CONFIG_JUMP_LABEL)
  95        static_key_slow_dec(&nf_hooks_needed[reg->pf][reg->hooknum]);
  96#endif
  97        synchronize_net();
  98}
  99EXPORT_SYMBOL(nf_unregister_hook);
 100
 101int nf_register_hooks(struct nf_hook_ops *reg, unsigned int n)
 102{
 103        unsigned int i;
 104        int err = 0;
 105
 106        for (i = 0; i < n; i++) {
 107                err = nf_register_hook(&reg[i]);
 108                if (err)
 109                        goto err;
 110        }
 111        return err;
 112
 113err:
 114        if (i > 0)
 115                nf_unregister_hooks(reg, i);
 116        return err;
 117}
 118EXPORT_SYMBOL(nf_register_hooks);
 119
 120void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n)
 121{
 122        while (n-- > 0)
 123                nf_unregister_hook(&reg[n]);
 124}
 125EXPORT_SYMBOL(nf_unregister_hooks);
 126
 127unsigned int nf_iterate(struct list_head *head,
 128                        struct sk_buff *skb,
 129                        unsigned int hook,
 130                        const struct net_device *indev,
 131                        const struct net_device *outdev,
 132                        struct nf_hook_ops **elemp,
 133                        int (*okfn)(struct sk_buff *),
 134                        int hook_thresh)
 135{
 136        unsigned int verdict;
 137
 138        /*
 139         * The caller must not block between calls to this
 140         * function because of risk of continuing from deleted element.
 141         */
 142        list_for_each_entry_continue_rcu((*elemp), head, list) {
 143                if (hook_thresh > (*elemp)->priority)
 144                        continue;
 145
 146                /* Optimization: we don't need to hold module
 147                   reference here, since function can't sleep. --RR */
 148repeat:
 149                verdict = (*elemp)->hook(hook, skb, indev, outdev, okfn);
 150                if (verdict != NF_ACCEPT) {
 151#ifdef CONFIG_NETFILTER_DEBUG
 152                        if (unlikely((verdict & NF_VERDICT_MASK)
 153                                                        > NF_MAX_VERDICT)) {
 154                                NFDEBUG("Evil return from %p(%u).\n",
 155                                        (*elemp)->hook, hook);
 156                                continue;
 157                        }
 158#endif
 159                        if (verdict != NF_REPEAT)
 160                                return verdict;
 161                        goto repeat;
 162                }
 163        }
 164        return NF_ACCEPT;
 165}
 166
 167
 168/* Returns 1 if okfn() needs to be executed by the caller,
 169 * -EPERM for NF_DROP, 0 otherwise. */
 170int nf_hook_slow(u_int8_t pf, unsigned int hook, struct sk_buff *skb,
 171                 struct net_device *indev,
 172                 struct net_device *outdev,
 173                 int (*okfn)(struct sk_buff *),
 174                 int hook_thresh)
 175{
 176        struct nf_hook_ops *elem;
 177        unsigned int verdict;
 178        int ret = 0;
 179
 180        /* We may already have this, but read-locks nest anyway */
 181        rcu_read_lock();
 182
 183        elem = list_entry_rcu(&nf_hooks[pf][hook], struct nf_hook_ops, list);
 184next_hook:
 185        verdict = nf_iterate(&nf_hooks[pf][hook], skb, hook, indev,
 186                             outdev, &elem, okfn, hook_thresh);
 187        if (verdict == NF_ACCEPT || verdict == NF_STOP) {
 188                ret = 1;
 189        } else if ((verdict & NF_VERDICT_MASK) == NF_DROP) {
 190                kfree_skb(skb);
 191                ret = NF_DROP_GETERR(verdict);
 192                if (ret == 0)
 193                        ret = -EPERM;
 194        } else if ((verdict & NF_VERDICT_MASK) == NF_QUEUE) {
 195                int err = nf_queue(skb, elem, pf, hook, indev, outdev, okfn,
 196                                                verdict >> NF_VERDICT_QBITS);
 197                if (err < 0) {
 198                        if (err == -ECANCELED)
 199                                goto next_hook;
 200                        if (err == -ESRCH &&
 201                           (verdict & NF_VERDICT_FLAG_QUEUE_BYPASS))
 202                                goto next_hook;
 203                        kfree_skb(skb);
 204                }
 205        }
 206        rcu_read_unlock();
 207        return ret;
 208}
 209EXPORT_SYMBOL(nf_hook_slow);
 210
 211
 212int skb_make_writable(struct sk_buff *skb, unsigned int writable_len)
 213{
 214        if (writable_len > skb->len)
 215                return 0;
 216
 217        /* Not exclusive use of packet?  Must copy. */
 218        if (!skb_cloned(skb)) {
 219                if (writable_len <= skb_headlen(skb))
 220                        return 1;
 221        } else if (skb_clone_writable(skb, writable_len))
 222                return 1;
 223
 224        if (writable_len <= skb_headlen(skb))
 225                writable_len = 0;
 226        else
 227                writable_len -= skb_headlen(skb);
 228
 229        return !!__pskb_pull_tail(skb, writable_len);
 230}
 231EXPORT_SYMBOL(skb_make_writable);
 232
 233#if IS_ENABLED(CONFIG_NF_CONNTRACK)
 234/* This does not belong here, but locally generated errors need it if connection
 235   tracking in use: without this, connection may not be in hash table, and hence
 236   manufactured ICMP or RST packets will not be associated with it. */
 237void (*ip_ct_attach)(struct sk_buff *, struct sk_buff *) __rcu __read_mostly;
 238EXPORT_SYMBOL(ip_ct_attach);
 239
 240void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb)
 241{
 242        void (*attach)(struct sk_buff *, struct sk_buff *);
 243
 244        if (skb->nfct) {
 245                rcu_read_lock();
 246                attach = rcu_dereference(ip_ct_attach);
 247                if (attach)
 248                        attach(new, skb);
 249                rcu_read_unlock();
 250        }
 251}
 252EXPORT_SYMBOL(nf_ct_attach);
 253
 254void (*nf_ct_destroy)(struct nf_conntrack *) __rcu __read_mostly;
 255EXPORT_SYMBOL(nf_ct_destroy);
 256
 257void nf_conntrack_destroy(struct nf_conntrack *nfct)
 258{
 259        void (*destroy)(struct nf_conntrack *);
 260
 261        rcu_read_lock();
 262        destroy = rcu_dereference(nf_ct_destroy);
 263        BUG_ON(destroy == NULL);
 264        destroy(nfct);
 265        rcu_read_unlock();
 266}
 267EXPORT_SYMBOL(nf_conntrack_destroy);
 268
 269struct nfq_ct_hook __rcu *nfq_ct_hook __read_mostly;
 270EXPORT_SYMBOL_GPL(nfq_ct_hook);
 271
 272struct nfq_ct_nat_hook __rcu *nfq_ct_nat_hook __read_mostly;
 273EXPORT_SYMBOL_GPL(nfq_ct_nat_hook);
 274
 275#endif /* CONFIG_NF_CONNTRACK */
 276
 277#ifdef CONFIG_NF_NAT_NEEDED
 278void (*nf_nat_decode_session_hook)(struct sk_buff *, struct flowi *);
 279EXPORT_SYMBOL(nf_nat_decode_session_hook);
 280#endif
 281
 282static int __net_init netfilter_net_init(struct net *net)
 283{
 284#ifdef CONFIG_PROC_FS
 285        net->nf.proc_netfilter = proc_net_mkdir(net, "netfilter",
 286                                                net->proc_net);
 287        if (!net->nf.proc_netfilter) {
 288                if (!net_eq(net, &init_net))
 289                        pr_err("cannot create netfilter proc entry");
 290
 291                return -ENOMEM;
 292        }
 293#endif
 294        return 0;
 295}
 296
 297static void __net_exit netfilter_net_exit(struct net *net)
 298{
 299        remove_proc_entry("netfilter", net->proc_net);
 300}
 301
 302static struct pernet_operations netfilter_net_ops = {
 303        .init = netfilter_net_init,
 304        .exit = netfilter_net_exit,
 305};
 306
 307int __init netfilter_init(void)
 308{
 309        int i, h, ret;
 310
 311        for (i = 0; i < ARRAY_SIZE(nf_hooks); i++) {
 312                for (h = 0; h < NF_MAX_HOOKS; h++)
 313                        INIT_LIST_HEAD(&nf_hooks[i][h]);
 314        }
 315
 316        ret = register_pernet_subsys(&netfilter_net_ops);
 317        if (ret < 0)
 318                goto err;
 319
 320        ret = netfilter_log_init();
 321        if (ret < 0)
 322                goto err_pernet;
 323
 324        return 0;
 325err_pernet:
 326        unregister_pernet_subsys(&netfilter_net_ops);
 327err:
 328        return ret;
 329}
 330
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.