linux/net/ipv6/netfilter/ip6table_mangle.c
<<
>>
Prefs
   1/*
   2 * IPv6 packet mangling table, a port of the IPv4 mangle table to IPv6
   3 *
   4 * Copyright (C) 2000-2001 by Harald Welte <laforge@gnumonks.org>
   5 * Copyright (C) 2000-2004 Netfilter Core Team <coreteam@netfilter.org>
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License version 2 as
   9 * published by the Free Software Foundation.
  10 */
  11#include <linux/module.h>
  12#include <linux/netfilter_ipv6/ip6_tables.h>
  13
  14MODULE_LICENSE("GPL");
  15MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
  16MODULE_DESCRIPTION("ip6tables mangle table");
  17
  18#define MANGLE_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | \
  19                            (1 << NF_INET_LOCAL_IN) | \
  20                            (1 << NF_INET_FORWARD) | \
  21                            (1 << NF_INET_LOCAL_OUT) | \
  22                            (1 << NF_INET_POST_ROUTING))
  23
  24static const struct
  25{
  26        struct ip6t_replace repl;
  27        struct ip6t_standard entries[5];
  28        struct ip6t_error term;
  29} initial_table __net_initdata = {
  30        .repl = {
  31                .name = "mangle",
  32                .valid_hooks = MANGLE_VALID_HOOKS,
  33                .num_entries = 6,
  34                .size = sizeof(struct ip6t_standard) * 5 + sizeof(struct ip6t_error),
  35                .hook_entry = {
  36                        [NF_INET_PRE_ROUTING]   = 0,
  37                        [NF_INET_LOCAL_IN]      = sizeof(struct ip6t_standard),
  38                        [NF_INET_FORWARD]       = sizeof(struct ip6t_standard) * 2,
  39                        [NF_INET_LOCAL_OUT]     = sizeof(struct ip6t_standard) * 3,
  40                        [NF_INET_POST_ROUTING]  = sizeof(struct ip6t_standard) * 4,
  41                },
  42                .underflow = {
  43                        [NF_INET_PRE_ROUTING]   = 0,
  44                        [NF_INET_LOCAL_IN]      = sizeof(struct ip6t_standard),
  45                        [NF_INET_FORWARD]       = sizeof(struct ip6t_standard) * 2,
  46                        [NF_INET_LOCAL_OUT]     = sizeof(struct ip6t_standard) * 3,
  47                        [NF_INET_POST_ROUTING]  = sizeof(struct ip6t_standard) * 4,
  48                },
  49        },
  50        .entries = {
  51                IP6T_STANDARD_INIT(NF_ACCEPT),  /* PRE_ROUTING */
  52                IP6T_STANDARD_INIT(NF_ACCEPT),  /* LOCAL_IN */
  53                IP6T_STANDARD_INIT(NF_ACCEPT),  /* FORWARD */
  54                IP6T_STANDARD_INIT(NF_ACCEPT),  /* LOCAL_OUT */
  55                IP6T_STANDARD_INIT(NF_ACCEPT),  /* POST_ROUTING */
  56        },
  57        .term = IP6T_ERROR_INIT,                /* ERROR */
  58};
  59
  60static const struct xt_table packet_mangler = {
  61        .name           = "mangle",
  62        .valid_hooks    = MANGLE_VALID_HOOKS,
  63        .me             = THIS_MODULE,
  64        .af             = NFPROTO_IPV6,
  65};
  66
  67/* The work comes in here from netfilter.c. */
  68static unsigned int
  69ip6t_in_hook(unsigned int hook,
  70         struct sk_buff *skb,
  71         const struct net_device *in,
  72         const struct net_device *out,
  73         int (*okfn)(struct sk_buff *))
  74{
  75        return ip6t_do_table(skb, hook, in, out,
  76                             dev_net(in)->ipv6.ip6table_mangle);
  77}
  78
  79static unsigned int
  80ip6t_post_routing_hook(unsigned int hook,
  81                struct sk_buff *skb,
  82                const struct net_device *in,
  83                const struct net_device *out,
  84                int (*okfn)(struct sk_buff *))
  85{
  86        return ip6t_do_table(skb, hook, in, out,
  87                             dev_net(out)->ipv6.ip6table_mangle);
  88}
  89
  90static unsigned int
  91ip6t_local_out_hook(unsigned int hook,
  92                   struct sk_buff *skb,
  93                   const struct net_device *in,
  94                   const struct net_device *out,
  95                   int (*okfn)(struct sk_buff *))
  96{
  97
  98        unsigned int ret;
  99        struct in6_addr saddr, daddr;
 100        u_int8_t hop_limit;
 101        u_int32_t flowlabel, mark;
 102
 103#if 0
 104        /* root is playing with raw sockets. */
 105        if (skb->len < sizeof(struct iphdr)
 106            || ip_hdrlen(skb) < sizeof(struct iphdr)) {
 107                if (net_ratelimit())
 108                        printk("ip6t_hook: happy cracking.\n");
 109                return NF_ACCEPT;
 110        }
 111#endif
 112
 113        /* save source/dest address, mark, hoplimit, flowlabel, priority,  */
 114        memcpy(&saddr, &ipv6_hdr(skb)->saddr, sizeof(saddr));
 115        memcpy(&daddr, &ipv6_hdr(skb)->daddr, sizeof(daddr));
 116        mark = skb->mark;
 117        hop_limit = ipv6_hdr(skb)->hop_limit;
 118
 119        /* flowlabel and prio (includes version, which shouldn't change either */
 120        flowlabel = *((u_int32_t *)ipv6_hdr(skb));
 121
 122        ret = ip6t_do_table(skb, hook, in, out,
 123                            dev_net(out)->ipv6.ip6table_mangle);
 124
 125        if (ret != NF_DROP && ret != NF_STOLEN
 126                && (memcmp(&ipv6_hdr(skb)->saddr, &saddr, sizeof(saddr))
 127                    || memcmp(&ipv6_hdr(skb)->daddr, &daddr, sizeof(daddr))
 128                    || skb->mark != mark
 129                    || ipv6_hdr(skb)->hop_limit != hop_limit))
 130                return ip6_route_me_harder(skb) == 0 ? ret : NF_DROP;
 131
 132        return ret;
 133}
 134
 135static struct nf_hook_ops ip6t_ops[] __read_mostly = {
 136        {
 137                .hook           = ip6t_in_hook,
 138                .owner          = THIS_MODULE,
 139                .pf             = NFPROTO_IPV6,
 140                .hooknum        = NF_INET_PRE_ROUTING,
 141                .priority       = NF_IP6_PRI_MANGLE,
 142        },
 143        {
 144                .hook           = ip6t_in_hook,
 145                .owner          = THIS_MODULE,
 146                .pf             = NFPROTO_IPV6,
 147                .hooknum        = NF_INET_LOCAL_IN,
 148                .priority       = NF_IP6_PRI_MANGLE,
 149        },
 150        {
 151                .hook           = ip6t_in_hook,
 152                .owner          = THIS_MODULE,
 153                .pf             = NFPROTO_IPV6,
 154                .hooknum        = NF_INET_FORWARD,
 155                .priority       = NF_IP6_PRI_MANGLE,
 156        },
 157        {
 158                .hook           = ip6t_local_out_hook,
 159                .owner          = THIS_MODULE,
 160                .pf             = NFPROTO_IPV6,
 161                .hooknum        = NF_INET_LOCAL_OUT,
 162                .priority       = NF_IP6_PRI_MANGLE,
 163        },
 164        {
 165                .hook           = ip6t_post_routing_hook,
 166                .owner          = THIS_MODULE,
 167                .pf             = NFPROTO_IPV6,
 168                .hooknum        = NF_INET_POST_ROUTING,
 169                .priority       = NF_IP6_PRI_MANGLE,
 170        },
 171};
 172
 173static int __net_init ip6table_mangle_net_init(struct net *net)
 174{
 175        /* Register table */
 176        net->ipv6.ip6table_mangle =
 177                ip6t_register_table(net, &packet_mangler, &initial_table.repl);
 178        if (IS_ERR(net->ipv6.ip6table_mangle))
 179                return PTR_ERR(net->ipv6.ip6table_mangle);
 180        return 0;
 181}
 182
 183static void __net_exit ip6table_mangle_net_exit(struct net *net)
 184{
 185        ip6t_unregister_table(net->ipv6.ip6table_mangle);
 186}
 187
 188static struct pernet_operations ip6table_mangle_net_ops = {
 189        .init = ip6table_mangle_net_init,
 190        .exit = ip6table_mangle_net_exit,
 191};
 192
 193static int __init ip6table_mangle_init(void)
 194{
 195        int ret;
 196
 197        ret = register_pernet_subsys(&ip6table_mangle_net_ops);
 198        if (ret < 0)
 199                return ret;
 200
 201        /* Register hooks */
 202        ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
 203        if (ret < 0)
 204                goto cleanup_table;
 205
 206        return ret;
 207
 208 cleanup_table:
 209        unregister_pernet_subsys(&ip6table_mangle_net_ops);
 210        return ret;
 211}
 212
 213static void __exit ip6table_mangle_fini(void)
 214{
 215        nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
 216        unregister_pernet_subsys(&ip6table_mangle_net_ops);
 217}
 218
 219module_init(ip6table_mangle_init);
 220module_exit(ip6table_mangle_fini);
 221