linux/net/ipv4/netfilter/iptable_nat.c
<<
>>
Prefs
   1/* (C) 1999-2001 Paul `Rusty' Russell
   2 * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
   3 * (C) 2011 Patrick McHardy <kaber@trash.net>
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License version 2 as
   7 * published by the Free Software Foundation.
   8 */
   9
  10#include <linux/module.h>
  11#include <linux/netfilter.h>
  12#include <linux/netfilter_ipv4.h>
  13#include <linux/netfilter_ipv4/ip_tables.h>
  14#include <linux/ip.h>
  15#include <net/ip.h>
  16
  17#include <net/netfilter/nf_nat.h>
  18#include <net/netfilter/nf_nat_core.h>
  19#include <net/netfilter/nf_nat_l3proto.h>
  20
  21static const struct xt_table nf_nat_ipv4_table = {
  22        .name           = "nat",
  23        .valid_hooks    = (1 << NF_INET_PRE_ROUTING) |
  24                          (1 << NF_INET_POST_ROUTING) |
  25                          (1 << NF_INET_LOCAL_OUT) |
  26                          (1 << NF_INET_LOCAL_IN),
  27        .me             = THIS_MODULE,
  28        .af             = NFPROTO_IPV4,
  29};
  30
  31static unsigned int iptable_nat_do_chain(const struct nf_hook_ops *ops,
  32                                         struct sk_buff *skb,
  33                                         const struct nf_hook_state *state,
  34                                         struct nf_conn *ct)
  35{
  36        struct net *net = nf_ct_net(ct);
  37
  38        return ipt_do_table(skb, ops->hooknum, state, net->ipv4.nat_table);
  39}
  40
  41static unsigned int iptable_nat_ipv4_fn(const struct nf_hook_ops *ops,
  42                                        struct sk_buff *skb,
  43                                        const struct nf_hook_state *state)
  44{
  45        return nf_nat_ipv4_fn(ops, skb, state, iptable_nat_do_chain);
  46}
  47
  48static unsigned int iptable_nat_ipv4_in(const struct nf_hook_ops *ops,
  49                                        struct sk_buff *skb,
  50                                        const struct nf_hook_state *state)
  51{
  52        return nf_nat_ipv4_in(ops, skb, state, iptable_nat_do_chain);
  53}
  54
  55static unsigned int iptable_nat_ipv4_out(const struct nf_hook_ops *ops,
  56                                         struct sk_buff *skb,
  57                                         const struct nf_hook_state *state)
  58{
  59        return nf_nat_ipv4_out(ops, skb, state, iptable_nat_do_chain);
  60}
  61
  62static unsigned int iptable_nat_ipv4_local_fn(const struct nf_hook_ops *ops,
  63                                              struct sk_buff *skb,
  64                                              const struct nf_hook_state *state)
  65{
  66        return nf_nat_ipv4_local_fn(ops, skb, state, iptable_nat_do_chain);
  67}
  68
  69static struct nf_hook_ops nf_nat_ipv4_ops[] __read_mostly = {
  70        /* Before packet filtering, change destination */
  71        {
  72                .hook           = iptable_nat_ipv4_in,
  73                .owner          = THIS_MODULE,
  74                .pf             = NFPROTO_IPV4,
  75                .hooknum        = NF_INET_PRE_ROUTING,
  76                .priority       = NF_IP_PRI_NAT_DST,
  77        },
  78        /* After packet filtering, change source */
  79        {
  80                .hook           = iptable_nat_ipv4_out,
  81                .owner          = THIS_MODULE,
  82                .pf             = NFPROTO_IPV4,
  83                .hooknum        = NF_INET_POST_ROUTING,
  84                .priority       = NF_IP_PRI_NAT_SRC,
  85        },
  86        /* Before packet filtering, change destination */
  87        {
  88                .hook           = iptable_nat_ipv4_local_fn,
  89                .owner          = THIS_MODULE,
  90                .pf             = NFPROTO_IPV4,
  91                .hooknum        = NF_INET_LOCAL_OUT,
  92                .priority       = NF_IP_PRI_NAT_DST,
  93        },
  94        /* After packet filtering, change source */
  95        {
  96                .hook           = iptable_nat_ipv4_fn,
  97                .owner          = THIS_MODULE,
  98                .pf             = NFPROTO_IPV4,
  99                .hooknum        = NF_INET_LOCAL_IN,
 100                .priority       = NF_IP_PRI_NAT_SRC,
 101        },
 102};
 103
 104static int __net_init iptable_nat_net_init(struct net *net)
 105{
 106        struct ipt_replace *repl;
 107
 108        repl = ipt_alloc_initial_table(&nf_nat_ipv4_table);
 109        if (repl == NULL)
 110                return -ENOMEM;
 111        net->ipv4.nat_table = ipt_register_table(net, &nf_nat_ipv4_table, repl);
 112        kfree(repl);
 113        return PTR_ERR_OR_ZERO(net->ipv4.nat_table);
 114}
 115
 116static void __net_exit iptable_nat_net_exit(struct net *net)
 117{
 118        ipt_unregister_table(net, net->ipv4.nat_table);
 119}
 120
 121static struct pernet_operations iptable_nat_net_ops = {
 122        .init   = iptable_nat_net_init,
 123        .exit   = iptable_nat_net_exit,
 124};
 125
 126static int __init iptable_nat_init(void)
 127{
 128        int err;
 129
 130        err = register_pernet_subsys(&iptable_nat_net_ops);
 131        if (err < 0)
 132                goto err1;
 133
 134        err = nf_register_hooks(nf_nat_ipv4_ops, ARRAY_SIZE(nf_nat_ipv4_ops));
 135        if (err < 0)
 136                goto err2;
 137        return 0;
 138
 139err2:
 140        unregister_pernet_subsys(&iptable_nat_net_ops);
 141err1:
 142        return err;
 143}
 144
 145static void __exit iptable_nat_exit(void)
 146{
 147        nf_unregister_hooks(nf_nat_ipv4_ops, ARRAY_SIZE(nf_nat_ipv4_ops));
 148        unregister_pernet_subsys(&iptable_nat_net_ops);
 149}
 150
 151module_init(iptable_nat_init);
 152module_exit(iptable_nat_exit);
 153
 154MODULE_LICENSE("GPL");
 155