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 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 12 13 #include <linux/module.h> 14 #include <linux/skbuff.h> 15 #include <linux/netfilter.h> 16 #include <linux/netfilter/x_tables.h> 17 #include <net/netfilter/nf_nat.h> 18 19 static int xt_nat_checkentry_v0(const struct xt_tgchk_param *par) 20 { 21 const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; 22 23 if (mr->rangesize != 1) { 24 pr_info_ratelimited("multiple ranges no longer supported\n"); 25 return -EINVAL; 26 } 27 return nf_ct_netns_get(par->net, par->family); 28 } 29 30 static int xt_nat_checkentry(const struct xt_tgchk_param *par) 31 { 32 return nf_ct_netns_get(par->net, par->family); 33 } 34 35 static void xt_nat_destroy(const struct xt_tgdtor_param *par) 36 { 37 nf_ct_netns_put(par->net, par->family); 38 } 39 40 static void xt_nat_convert_range(struct nf_nat_range2 *dst, 41 const struct nf_nat_ipv4_range *src) 42 { 43 memset(&dst->min_addr, 0, sizeof(dst->min_addr)); 44 memset(&dst->max_addr, 0, sizeof(dst->max_addr)); 45 memset(&dst->base_proto, 0, sizeof(dst->base_proto)); 46 47 dst->flags = src->flags; 48 dst->min_addr.ip = src->min_ip; 49 dst->max_addr.ip = src->max_ip; 50 dst->min_proto = src->min; 51 dst->max_proto = src->max; 52 } 53 54 static unsigned int 55 xt_snat_target_v0(struct sk_buff *skb, const struct xt_action_param *par) 56 { 57 const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; 58 struct nf_nat_range2 range; 59 enum ip_conntrack_info ctinfo; 60 struct nf_conn *ct; 61 62 ct = nf_ct_get(skb, &ctinfo); 63 WARN_ON(!(ct != NULL && 64 (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED || 65 ctinfo == IP_CT_RELATED_REPLY))); 66 67 xt_nat_convert_range(&range, &mr->range[0]); 68 return nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC); 69 } 70 71 static unsigned int 72 xt_dnat_target_v0(struct sk_buff *skb, const struct xt_action_param *par) 73 { 74 const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; 75 struct nf_nat_range2 range; 76 enum ip_conntrack_info ctinfo; 77 struct nf_conn *ct; 78 79 ct = nf_ct_get(skb, &ctinfo); 80 WARN_ON(!(ct != NULL && 81 (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED))); 82 83 xt_nat_convert_range(&range, &mr->range[0]); 84 return nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST); 85 } 86 87 static unsigned int 88 xt_snat_target_v1(struct sk_buff *skb, const struct xt_action_param *par) 89 { 90 const struct nf_nat_range *range_v1 = par->targinfo; 91 struct nf_nat_range2 range; 92 enum ip_conntrack_info ctinfo; 93 struct nf_conn *ct; 94 95 ct = nf_ct_get(skb, &ctinfo); 96 WARN_ON(!(ct != NULL && 97 (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED || 98 ctinfo == IP_CT_RELATED_REPLY))); 99 100 memcpy(&range, range_v1, sizeof(*range_v1)); 101 memset(&range.base_proto, 0, sizeof(range.base_proto)); 102 103 return nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC); 104 } 105 106 static unsigned int 107 xt_dnat_target_v1(struct sk_buff *skb, const struct xt_action_param *par) 108 { 109 const struct nf_nat_range *range_v1 = par->targinfo; 110 struct nf_nat_range2 range; 111 enum ip_conntrack_info ctinfo; 112 struct nf_conn *ct; 113 114 ct = nf_ct_get(skb, &ctinfo); 115 WARN_ON(!(ct != NULL && 116 (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED))); 117 118 memcpy(&range, range_v1, sizeof(*range_v1)); 119 memset(&range.base_proto, 0, sizeof(range.base_proto)); 120 121 return nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST); 122 } 123 124 static unsigned int 125 xt_snat_target_v2(struct sk_buff *skb, const struct xt_action_param *par) 126 { 127 const struct nf_nat_range2 *range = par->targinfo; 128 enum ip_conntrack_info ctinfo; 129 struct nf_conn *ct; 130 131 ct = nf_ct_get(skb, &ctinfo); 132 WARN_ON(!(ct != NULL && 133 (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED || 134 ctinfo == IP_CT_RELATED_REPLY))); 135 136 return nf_nat_setup_info(ct, range, NF_NAT_MANIP_SRC); 137 } 138 139 static unsigned int 140 xt_dnat_target_v2(struct sk_buff *skb, const struct xt_action_param *par) 141 { 142 const struct nf_nat_range2 *range = par->targinfo; 143 enum ip_conntrack_info ctinfo; 144 struct nf_conn *ct; 145 146 ct = nf_ct_get(skb, &ctinfo); 147 WARN_ON(!(ct != NULL && 148 (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED))); 149 150 return nf_nat_setup_info(ct, range, NF_NAT_MANIP_DST); 151 } 152 153 static struct xt_target xt_nat_target_reg[] __read_mostly = { 154 { 155 .name = "SNAT", 156 .revision = 0, 157 .checkentry = xt_nat_checkentry_v0, 158 .destroy = xt_nat_destroy, 159 .target = xt_snat_target_v0, 160 .targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat), 161 .family = NFPROTO_IPV4, 162 .table = "nat", 163 .hooks = (1 << NF_INET_POST_ROUTING) | 164 (1 << NF_INET_LOCAL_IN), 165 .me = THIS_MODULE, 166 }, 167 { 168 .name = "DNAT", 169 .revision = 0, 170 .checkentry = xt_nat_checkentry_v0, 171 .destroy = xt_nat_destroy, 172 .target = xt_dnat_target_v0, 173 .targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat), 174 .family = NFPROTO_IPV4, 175 .table = "nat", 176 .hooks = (1 << NF_INET_PRE_ROUTING) | 177 (1 << NF_INET_LOCAL_OUT), 178 .me = THIS_MODULE, 179 }, 180 { 181 .name = "SNAT", 182 .revision = 1, 183 .checkentry = xt_nat_checkentry, 184 .destroy = xt_nat_destroy, 185 .target = xt_snat_target_v1, 186 .targetsize = sizeof(struct nf_nat_range), 187 .table = "nat", 188 .hooks = (1 << NF_INET_POST_ROUTING) | 189 (1 << NF_INET_LOCAL_IN), 190 .me = THIS_MODULE, 191 }, 192 { 193 .name = "DNAT", 194 .revision = 1, 195 .checkentry = xt_nat_checkentry, 196 .destroy = xt_nat_destroy, 197 .target = xt_dnat_target_v1, 198 .targetsize = sizeof(struct nf_nat_range), 199 .table = "nat", 200 .hooks = (1 << NF_INET_PRE_ROUTING) | 201 (1 << NF_INET_LOCAL_OUT), 202 .me = THIS_MODULE, 203 }, 204 { 205 .name = "SNAT", 206 .revision = 2, 207 .checkentry = xt_nat_checkentry, 208 .destroy = xt_nat_destroy, 209 .target = xt_snat_target_v2, 210 .targetsize = sizeof(struct nf_nat_range2), 211 .table = "nat", 212 .hooks = (1 << NF_INET_POST_ROUTING) | 213 (1 << NF_INET_LOCAL_IN), 214 .me = THIS_MODULE, 215 }, 216 { 217 .name = "DNAT", 218 .revision = 2, 219 .checkentry = xt_nat_checkentry, 220 .destroy = xt_nat_destroy, 221 .target = xt_dnat_target_v2, 222 .targetsize = sizeof(struct nf_nat_range2), 223 .table = "nat", 224 .hooks = (1 << NF_INET_PRE_ROUTING) | 225 (1 << NF_INET_LOCAL_OUT), 226 .me = THIS_MODULE, 227 }, 228 }; 229 230 static int __init xt_nat_init(void) 231 { 232 return xt_register_targets(xt_nat_target_reg, 233 ARRAY_SIZE(xt_nat_target_reg)); 234 } 235 236 static void __exit xt_nat_exit(void) 237 { 238 xt_unregister_targets(xt_nat_target_reg, ARRAY_SIZE(xt_nat_target_reg)); 239 } 240 241 module_init(xt_nat_init); 242 module_exit(xt_nat_exit); 243 244 MODULE_LICENSE("GPL"); 245 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); 246 MODULE_ALIAS("ipt_SNAT"); 247 MODULE_ALIAS("ipt_DNAT"); 248 MODULE_ALIAS("ip6t_SNAT"); 249 MODULE_ALIAS("ip6t_DNAT"); 250