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 21 static int __net_init iptable_nat_table_init(struct net *net); 22 23 static const struct xt_table nf_nat_ipv4_table = { 24 .name = "nat", 25 .valid_hooks = (1 << NF_INET_PRE_ROUTING) | 26 (1 << NF_INET_POST_ROUTING) | 27 (1 << NF_INET_LOCAL_OUT) | 28 (1 << NF_INET_LOCAL_IN), 29 .me = THIS_MODULE, 30 .af = NFPROTO_IPV4, 31 .table_init = iptable_nat_table_init, 32 }; 33 34 static unsigned int iptable_nat_do_chain(void *priv, 35 struct sk_buff *skb, 36 const struct nf_hook_state *state, 37 struct nf_conn *ct) 38 { 39 return ipt_do_table(skb, state, state->net->ipv4.nat_table); 40 } 41 42 static unsigned int iptable_nat_ipv4_fn(void *priv, 43 struct sk_buff *skb, 44 const struct nf_hook_state *state) 45 { 46 return nf_nat_ipv4_fn(priv, skb, state, iptable_nat_do_chain); 47 } 48 49 static unsigned int iptable_nat_ipv4_in(void *priv, 50 struct sk_buff *skb, 51 const struct nf_hook_state *state) 52 { 53 return nf_nat_ipv4_in(priv, skb, state, iptable_nat_do_chain); 54 } 55 56 static unsigned int iptable_nat_ipv4_out(void *priv, 57 struct sk_buff *skb, 58 const struct nf_hook_state *state) 59 { 60 return nf_nat_ipv4_out(priv, skb, state, iptable_nat_do_chain); 61 } 62 63 static unsigned int iptable_nat_ipv4_local_fn(void *priv, 64 struct sk_buff *skb, 65 const struct nf_hook_state *state) 66 { 67 return nf_nat_ipv4_local_fn(priv, skb, state, iptable_nat_do_chain); 68 } 69 70 static struct nf_hook_ops nf_nat_ipv4_ops[] __read_mostly = { 71 /* Before packet filtering, change destination */ 72 { 73 .hook = iptable_nat_ipv4_in, 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 .pf = NFPROTO_IPV4, 82 .hooknum = NF_INET_POST_ROUTING, 83 .priority = NF_IP_PRI_NAT_SRC, 84 }, 85 /* Before packet filtering, change destination */ 86 { 87 .hook = iptable_nat_ipv4_local_fn, 88 .pf = NFPROTO_IPV4, 89 .hooknum = NF_INET_LOCAL_OUT, 90 .priority = NF_IP_PRI_NAT_DST, 91 }, 92 /* After packet filtering, change source */ 93 { 94 .hook = iptable_nat_ipv4_fn, 95 .pf = NFPROTO_IPV4, 96 .hooknum = NF_INET_LOCAL_IN, 97 .priority = NF_IP_PRI_NAT_SRC, 98 }, 99 }; 100 101 static int __net_init iptable_nat_table_init(struct net *net) 102 { 103 struct ipt_replace *repl; 104 int ret; 105 106 if (net->ipv4.nat_table) 107 return 0; 108 109 repl = ipt_alloc_initial_table(&nf_nat_ipv4_table); 110 if (repl == NULL) 111 return -ENOMEM; 112 ret = ipt_register_table(net, &nf_nat_ipv4_table, repl, 113 nf_nat_ipv4_ops, &net->ipv4.nat_table); 114 kfree(repl); 115 return ret; 116 } 117 118 static void __net_exit iptable_nat_net_exit(struct net *net) 119 { 120 if (!net->ipv4.nat_table) 121 return; 122 ipt_unregister_table(net, net->ipv4.nat_table, nf_nat_ipv4_ops); 123 net->ipv4.nat_table = NULL; 124 } 125 126 static struct pernet_operations iptable_nat_net_ops = { 127 .exit = iptable_nat_net_exit, 128 }; 129 130 static int __init iptable_nat_init(void) 131 { 132 int ret = register_pernet_subsys(&iptable_nat_net_ops); 133 134 if (ret) 135 return ret; 136 137 ret = iptable_nat_table_init(&init_net); 138 if (ret) 139 unregister_pernet_subsys(&iptable_nat_net_ops); 140 return ret; 141 } 142 143 static void __exit iptable_nat_exit(void) 144 { 145 unregister_pernet_subsys(&iptable_nat_net_ops); 146 } 147 148 module_init(iptable_nat_init); 149 module_exit(iptable_nat_exit); 150 151 MODULE_LICENSE("GPL"); 152