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 const struct nf_hook_ops nf_nat_ipv4_ops[] = { 71 /* Before packet filtering, change destination */ 72 { 73 .hook = iptable_nat_ipv4_in, 74 .pf = NFPROTO_IPV4, 75 .nat_hook = true, 76 .hooknum = NF_INET_PRE_ROUTING, 77 .priority = NF_IP_PRI_NAT_DST, 78 }, 79 /* After packet filtering, change source */ 80 { 81 .hook = iptable_nat_ipv4_out, 82 .pf = NFPROTO_IPV4, 83 .nat_hook = true, 84 .hooknum = NF_INET_POST_ROUTING, 85 .priority = NF_IP_PRI_NAT_SRC, 86 }, 87 /* Before packet filtering, change destination */ 88 { 89 .hook = iptable_nat_ipv4_local_fn, 90 .pf = NFPROTO_IPV4, 91 .nat_hook = true, 92 .hooknum = NF_INET_LOCAL_OUT, 93 .priority = NF_IP_PRI_NAT_DST, 94 }, 95 /* After packet filtering, change source */ 96 { 97 .hook = iptable_nat_ipv4_fn, 98 .pf = NFPROTO_IPV4, 99 .nat_hook = true, 100 .hooknum = NF_INET_LOCAL_IN, 101 .priority = NF_IP_PRI_NAT_SRC, 102 }, 103 }; 104 105 static int __net_init iptable_nat_table_init(struct net *net) 106 { 107 struct ipt_replace *repl; 108 int ret; 109 110 if (net->ipv4.nat_table) 111 return 0; 112 113 repl = ipt_alloc_initial_table(&nf_nat_ipv4_table); 114 if (repl == NULL) 115 return -ENOMEM; 116 ret = ipt_register_table(net, &nf_nat_ipv4_table, repl, 117 nf_nat_ipv4_ops, &net->ipv4.nat_table); 118 kfree(repl); 119 return ret; 120 } 121 122 static void __net_exit iptable_nat_net_exit(struct net *net) 123 { 124 if (!net->ipv4.nat_table) 125 return; 126 ipt_unregister_table(net, net->ipv4.nat_table, nf_nat_ipv4_ops); 127 net->ipv4.nat_table = NULL; 128 } 129 130 static struct pernet_operations iptable_nat_net_ops = { 131 .exit = iptable_nat_net_exit, 132 }; 133 134 static int __init iptable_nat_init(void) 135 { 136 int ret = register_pernet_subsys(&iptable_nat_net_ops); 137 138 if (ret) 139 return ret; 140 141 ret = iptable_nat_table_init(&init_net); 142 if (ret) 143 unregister_pernet_subsys(&iptable_nat_net_ops); 144 return ret; 145 } 146 147 static void __exit iptable_nat_exit(void) 148 { 149 unregister_pernet_subsys(&iptable_nat_net_ops); 150 } 151 152 module_init(iptable_nat_init); 153 module_exit(iptable_nat_exit); 154 155 MODULE_LICENSE("GPL"); 156