root/net/ipv6/netfilter/ip6table_mangle.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ip6t_mangle_out
  2. ip6table_mangle_hook
  3. ip6table_mangle_table_init
  4. ip6table_mangle_net_exit
  5. ip6table_mangle_init
  6. ip6table_mangle_fini

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * IPv6 packet mangling table, a port of the IPv4 mangle table to IPv6
   4  *
   5  * Copyright (C) 2000-2001 by Harald Welte <laforge@gnumonks.org>
   6  * Copyright (C) 2000-2004 Netfilter Core Team <coreteam@netfilter.org>
   7  */
   8 #include <linux/module.h>
   9 #include <linux/netfilter_ipv6/ip6_tables.h>
  10 #include <linux/slab.h>
  11 #include <net/ipv6.h>
  12 
  13 MODULE_LICENSE("GPL");
  14 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
  15 MODULE_DESCRIPTION("ip6tables mangle table");
  16 
  17 #define MANGLE_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | \
  18                             (1 << NF_INET_LOCAL_IN) | \
  19                             (1 << NF_INET_FORWARD) | \
  20                             (1 << NF_INET_LOCAL_OUT) | \
  21                             (1 << NF_INET_POST_ROUTING))
  22 
  23 static int __net_init ip6table_mangle_table_init(struct net *net);
  24 
  25 static const struct xt_table packet_mangler = {
  26         .name           = "mangle",
  27         .valid_hooks    = MANGLE_VALID_HOOKS,
  28         .me             = THIS_MODULE,
  29         .af             = NFPROTO_IPV6,
  30         .priority       = NF_IP6_PRI_MANGLE,
  31         .table_init     = ip6table_mangle_table_init,
  32 };
  33 
  34 static unsigned int
  35 ip6t_mangle_out(struct sk_buff *skb, const struct nf_hook_state *state)
  36 {
  37         unsigned int ret;
  38         struct in6_addr saddr, daddr;
  39         u_int8_t hop_limit;
  40         u_int32_t flowlabel, mark;
  41         int err;
  42 
  43         /* save source/dest address, mark, hoplimit, flowlabel, priority,  */
  44         memcpy(&saddr, &ipv6_hdr(skb)->saddr, sizeof(saddr));
  45         memcpy(&daddr, &ipv6_hdr(skb)->daddr, sizeof(daddr));
  46         mark = skb->mark;
  47         hop_limit = ipv6_hdr(skb)->hop_limit;
  48 
  49         /* flowlabel and prio (includes version, which shouldn't change either */
  50         flowlabel = *((u_int32_t *)ipv6_hdr(skb));
  51 
  52         ret = ip6t_do_table(skb, state, state->net->ipv6.ip6table_mangle);
  53 
  54         if (ret != NF_DROP && ret != NF_STOLEN &&
  55             (!ipv6_addr_equal(&ipv6_hdr(skb)->saddr, &saddr) ||
  56              !ipv6_addr_equal(&ipv6_hdr(skb)->daddr, &daddr) ||
  57              skb->mark != mark ||
  58              ipv6_hdr(skb)->hop_limit != hop_limit ||
  59              flowlabel != *((u_int32_t *)ipv6_hdr(skb)))) {
  60                 err = ip6_route_me_harder(state->net, skb);
  61                 if (err < 0)
  62                         ret = NF_DROP_ERR(err);
  63         }
  64 
  65         return ret;
  66 }
  67 
  68 /* The work comes in here from netfilter.c. */
  69 static unsigned int
  70 ip6table_mangle_hook(void *priv, struct sk_buff *skb,
  71                      const struct nf_hook_state *state)
  72 {
  73         if (state->hook == NF_INET_LOCAL_OUT)
  74                 return ip6t_mangle_out(skb, state);
  75         return ip6t_do_table(skb, state, state->net->ipv6.ip6table_mangle);
  76 }
  77 
  78 static struct nf_hook_ops *mangle_ops __read_mostly;
  79 static int __net_init ip6table_mangle_table_init(struct net *net)
  80 {
  81         struct ip6t_replace *repl;
  82         int ret;
  83 
  84         if (net->ipv6.ip6table_mangle)
  85                 return 0;
  86 
  87         repl = ip6t_alloc_initial_table(&packet_mangler);
  88         if (repl == NULL)
  89                 return -ENOMEM;
  90         ret = ip6t_register_table(net, &packet_mangler, repl, mangle_ops,
  91                                   &net->ipv6.ip6table_mangle);
  92         kfree(repl);
  93         return ret;
  94 }
  95 
  96 static void __net_exit ip6table_mangle_net_exit(struct net *net)
  97 {
  98         if (!net->ipv6.ip6table_mangle)
  99                 return;
 100 
 101         ip6t_unregister_table(net, net->ipv6.ip6table_mangle, mangle_ops);
 102         net->ipv6.ip6table_mangle = NULL;
 103 }
 104 
 105 static struct pernet_operations ip6table_mangle_net_ops = {
 106         .exit = ip6table_mangle_net_exit,
 107 };
 108 
 109 static int __init ip6table_mangle_init(void)
 110 {
 111         int ret;
 112 
 113         mangle_ops = xt_hook_ops_alloc(&packet_mangler, ip6table_mangle_hook);
 114         if (IS_ERR(mangle_ops))
 115                 return PTR_ERR(mangle_ops);
 116 
 117         ret = register_pernet_subsys(&ip6table_mangle_net_ops);
 118         if (ret < 0) {
 119                 kfree(mangle_ops);
 120                 return ret;
 121         }
 122 
 123         ret = ip6table_mangle_table_init(&init_net);
 124         if (ret) {
 125                 unregister_pernet_subsys(&ip6table_mangle_net_ops);
 126                 kfree(mangle_ops);
 127         }
 128         return ret;
 129 }
 130 
 131 static void __exit ip6table_mangle_fini(void)
 132 {
 133         unregister_pernet_subsys(&ip6table_mangle_net_ops);
 134         kfree(mangle_ops);
 135 }
 136 
 137 module_init(ip6table_mangle_init);
 138 module_exit(ip6table_mangle_fini);

/* [<][>][^][v][top][bottom][index][help] */