linux/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
<<
>>
Prefs
   1/* (C) 1999-2001 Paul `Rusty' Russell
   2 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License version 2 as
   6 * published by the Free Software Foundation.
   7 */
   8
   9#include <linux/types.h>
  10#include <linux/ipv6.h>
  11#include <linux/in6.h>
  12#include <linux/netfilter.h>
  13#include <linux/module.h>
  14#include <linux/skbuff.h>
  15#include <linux/icmp.h>
  16#include <linux/sysctl.h>
  17#include <net/ipv6.h>
  18#include <net/inet_frag.h>
  19
  20#include <linux/netfilter_ipv6.h>
  21#include <linux/netfilter_bridge.h>
  22#if IS_ENABLED(CONFIG_NF_CONNTRACK)
  23#include <net/netfilter/nf_conntrack.h>
  24#include <net/netfilter/nf_conntrack_helper.h>
  25#include <net/netfilter/nf_conntrack_l4proto.h>
  26#include <net/netfilter/nf_conntrack_l3proto.h>
  27#include <net/netfilter/nf_conntrack_core.h>
  28#include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
  29#endif
  30#include <net/netfilter/nf_conntrack_zones.h>
  31#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
  32
  33static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum,
  34                                                struct sk_buff *skb)
  35{
  36        u16 zone = NF_CT_DEFAULT_ZONE;
  37
  38#if IS_ENABLED(CONFIG_NF_CONNTRACK)
  39        if (skb->nfct)
  40                zone = nf_ct_zone((struct nf_conn *)skb->nfct);
  41#endif
  42
  43#ifdef CONFIG_BRIDGE_NETFILTER
  44        if (skb->nf_bridge &&
  45            skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)
  46                return IP6_DEFRAG_CONNTRACK_BRIDGE_IN + zone;
  47#endif
  48        if (hooknum == NF_INET_PRE_ROUTING)
  49                return IP6_DEFRAG_CONNTRACK_IN + zone;
  50        else
  51                return IP6_DEFRAG_CONNTRACK_OUT + zone;
  52
  53}
  54
  55static unsigned int ipv6_defrag(unsigned int hooknum,
  56                                struct sk_buff *skb,
  57                                const struct net_device *in,
  58                                const struct net_device *out,
  59                                int (*okfn)(struct sk_buff *))
  60{
  61        struct sk_buff *reasm;
  62
  63#if IS_ENABLED(CONFIG_NF_CONNTRACK)
  64        /* Previously seen (loopback)?  */
  65        if (skb->nfct && !nf_ct_is_template((struct nf_conn *)skb->nfct))
  66                return NF_ACCEPT;
  67#endif
  68
  69        reasm = nf_ct_frag6_gather(skb, nf_ct6_defrag_user(hooknum, skb));
  70        /* queued */
  71        if (reasm == NULL)
  72                return NF_STOLEN;
  73
  74        /* error occurred or not fragmented */
  75        if (reasm == skb)
  76                return NF_ACCEPT;
  77
  78        nf_ct_frag6_output(hooknum, reasm, (struct net_device *)in,
  79                           (struct net_device *)out, okfn);
  80
  81        return NF_STOLEN;
  82}
  83
  84static struct nf_hook_ops ipv6_defrag_ops[] = {
  85        {
  86                .hook           = ipv6_defrag,
  87                .owner          = THIS_MODULE,
  88                .pf             = NFPROTO_IPV6,
  89                .hooknum        = NF_INET_PRE_ROUTING,
  90                .priority       = NF_IP6_PRI_CONNTRACK_DEFRAG,
  91        },
  92        {
  93                .hook           = ipv6_defrag,
  94                .owner          = THIS_MODULE,
  95                .pf             = NFPROTO_IPV6,
  96                .hooknum        = NF_INET_LOCAL_OUT,
  97                .priority       = NF_IP6_PRI_CONNTRACK_DEFRAG,
  98        },
  99};
 100
 101static int __init nf_defrag_init(void)
 102{
 103        int ret = 0;
 104
 105        ret = nf_ct_frag6_init();
 106        if (ret < 0) {
 107                pr_err("nf_defrag_ipv6: can't initialize frag6.\n");
 108                return ret;
 109        }
 110        ret = nf_register_hooks(ipv6_defrag_ops, ARRAY_SIZE(ipv6_defrag_ops));
 111        if (ret < 0) {
 112                pr_err("nf_defrag_ipv6: can't register hooks\n");
 113                goto cleanup_frag6;
 114        }
 115        return ret;
 116
 117cleanup_frag6:
 118        nf_ct_frag6_cleanup();
 119        return ret;
 120
 121}
 122
 123static void __exit nf_defrag_fini(void)
 124{
 125        nf_unregister_hooks(ipv6_defrag_ops, ARRAY_SIZE(ipv6_defrag_ops));
 126        nf_ct_frag6_cleanup();
 127}
 128
 129void nf_defrag_ipv6_enable(void)
 130{
 131}
 132EXPORT_SYMBOL_GPL(nf_defrag_ipv6_enable);
 133
 134module_init(nf_defrag_init);
 135module_exit(nf_defrag_fini);
 136
 137MODULE_LICENSE("GPL");
 138