1/* 2 * (C) 1999-2001 Paul `Rusty' Russell 3 * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org> 4 * (C) 2011 Patrick McHardy <kaber@trash.net> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 */ 10 11#include <linux/module.h> 12#include <linux/skbuff.h> 13#include <linux/netfilter.h> 14#include <linux/netfilter/x_tables.h> 15#include <net/netfilter/nf_nat_core.h> 16 17static int xt_nat_checkentry_v0(const struct xt_tgchk_param *par) 18{ 19 const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; 20 21 if (mr->rangesize != 1) { 22 pr_info("%s: multiple ranges no longer supported\n", 23 par->target->name); 24 return -EINVAL; 25 } 26 return 0; 27} 28 29static void xt_nat_convert_range(struct nf_nat_range *dst, 30 const struct nf_nat_ipv4_range *src) 31{ 32 memset(&dst->min_addr, 0, sizeof(dst->min_addr)); 33 memset(&dst->max_addr, 0, sizeof(dst->max_addr)); 34 35 dst->flags = src->flags; 36 dst->min_addr.ip = src->min_ip; 37 dst->max_addr.ip = src->max_ip; 38 dst->min_proto = src->min; 39 dst->max_proto = src->max; 40} 41 42static unsigned int 43xt_snat_target_v0(struct sk_buff *skb, const struct xt_action_param *par) 44{ 45 const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; 46 struct nf_nat_range range; 47 enum ip_conntrack_info ctinfo; 48 struct nf_conn *ct; 49 50 ct = nf_ct_get(skb, &ctinfo); 51 NF_CT_ASSERT(ct != NULL && 52 (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED || 53 ctinfo == IP_CT_RELATED_REPLY)); 54 55 xt_nat_convert_range(&range, &mr->range[0]); 56 return nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC); 57} 58 59static unsigned int 60xt_dnat_target_v0(struct sk_buff *skb, const struct xt_action_param *par) 61{ 62 const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; 63 struct nf_nat_range range; 64 enum ip_conntrack_info ctinfo; 65 struct nf_conn *ct; 66 67 ct = nf_ct_get(skb, &ctinfo); 68 NF_CT_ASSERT(ct != NULL && 69 (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)); 70 71 xt_nat_convert_range(&range, &mr->range[0]); 72 return nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST); 73} 74 75static unsigned int 76xt_snat_target_v1(struct sk_buff *skb, const struct xt_action_param *par) 77{ 78 const struct nf_nat_range *range = par->targinfo; 79 enum ip_conntrack_info ctinfo; 80 struct nf_conn *ct; 81 82 ct = nf_ct_get(skb, &ctinfo); 83 NF_CT_ASSERT(ct != NULL && 84 (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED || 85 ctinfo == IP_CT_RELATED_REPLY)); 86 87 return nf_nat_setup_info(ct, range, NF_NAT_MANIP_SRC); 88} 89 90static unsigned int 91xt_dnat_target_v1(struct sk_buff *skb, const struct xt_action_param *par) 92{ 93 const struct nf_nat_range *range = par->targinfo; 94 enum ip_conntrack_info ctinfo; 95 struct nf_conn *ct; 96 97 ct = nf_ct_get(skb, &ctinfo); 98 NF_CT_ASSERT(ct != NULL && 99 (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)); 100 101 return nf_nat_setup_info(ct, range, NF_NAT_MANIP_DST); 102} 103 104static struct xt_target xt_nat_target_reg[] __read_mostly = { 105 { 106 .name = "SNAT", 107 .revision = 0, 108 .checkentry = xt_nat_checkentry_v0, 109 .target = xt_snat_target_v0, 110 .targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat), 111 .family = NFPROTO_IPV4, 112 .table = "nat", 113 .hooks = (1 << NF_INET_POST_ROUTING) | 114 (1 << NF_INET_LOCAL_IN), 115 .me = THIS_MODULE, 116 }, 117 { 118 .name = "DNAT", 119 .revision = 0, 120 .checkentry = xt_nat_checkentry_v0, 121 .target = xt_dnat_target_v0, 122 .targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat), 123 .family = NFPROTO_IPV4, 124 .table = "nat", 125 .hooks = (1 << NF_INET_PRE_ROUTING) | 126 (1 << NF_INET_LOCAL_OUT), 127 .me = THIS_MODULE, 128 }, 129 { 130 .name = "SNAT", 131 .revision = 1, 132 .target = xt_snat_target_v1, 133 .targetsize = sizeof(struct nf_nat_range), 134 .table = "nat", 135 .hooks = (1 << NF_INET_POST_ROUTING) | 136 (1 << NF_INET_LOCAL_IN), 137 .me = THIS_MODULE, 138 }, 139 { 140 .name = "DNAT", 141 .revision = 1, 142 .target = xt_dnat_target_v1, 143 .targetsize = sizeof(struct nf_nat_range), 144 .table = "nat", 145 .hooks = (1 << NF_INET_PRE_ROUTING) | 146 (1 << NF_INET_LOCAL_OUT), 147 .me = THIS_MODULE, 148 }, 149}; 150 151static int __init xt_nat_init(void) 152{ 153 return xt_register_targets(xt_nat_target_reg, 154 ARRAY_SIZE(xt_nat_target_reg)); 155} 156 157static void __exit xt_nat_exit(void) 158{ 159 xt_unregister_targets(xt_nat_target_reg, ARRAY_SIZE(xt_nat_target_reg)); 160} 161 162module_init(xt_nat_init); 163module_exit(xt_nat_exit); 164 165MODULE_LICENSE("GPL"); 166MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); 167MODULE_ALIAS("ipt_SNAT"); 168MODULE_ALIAS("ipt_DNAT"); 169MODULE_ALIAS("ip6t_SNAT"); 170MODULE_ALIAS("ip6t_DNAT"); 171