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