1/* This file contains all the functions required for the standalone 2 ip_nat module. 3 4 These are not required by the compatibility layer. 5*/ 6 7/* (c) 1999 Paul `Rusty' Russell. Licenced under the GNU General 8 * Public Licence. 9 * 10 * 23 Apr 2001: Harald Welte <laforge@gnumonks.org> 11 * - new API and handling of conntrack/nat helpers 12 * - now capable of multiple expectations for one master 13 * */ 14 15#include <linux/config.h> 16#include <linux/types.h> 17#include <linux/ip.h> 18#include <linux/netfilter.h> 19#include <linux/netfilter_ipv4.h> 20#include <linux/module.h> 21#include <linux/skbuff.h> 22#include <linux/proc_fs.h> 23#include <net/checksum.h> 24#include <linux/spinlock.h> 25#include <linux/version.h> 26#include <linux/brlock.h> 27 28#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_nat_lock) 29#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_nat_lock) 30 31#include <linux/netfilter_ipv4/ip_nat.h> 32#include <linux/netfilter_ipv4/ip_nat_rule.h> 33#include <linux/netfilter_ipv4/ip_nat_protocol.h> 34#include <linux/netfilter_ipv4/ip_nat_core.h> 35#include <linux/netfilter_ipv4/ip_nat_helper.h> 36#include <linux/netfilter_ipv4/ip_tables.h> 37#include <linux/netfilter_ipv4/ip_conntrack_core.h> 38#include <linux/netfilter_ipv4/listhelp.h> 39 40#define DEBUGP(format, args...) 41 42#define HOOKNAME(hooknum) ((hooknum) == NF_IP_POST_ROUTING ? "POST_ROUTING" \ 43 : ((hooknum) == NF_IP_PRE_ROUTING ? "PRE_ROUTING" \ 44 : ((hooknum) == NF_IP_LOCAL_OUT ? "LOCAL_OUT" \ 45 : ((hooknum) == NF_IP_LOCAL_IN ? "LOCAL_IN" \ 46 : "*ERROR*"))) 47 48static inline int call_expect(struct ip_conntrack *master, 49 struct sk_buff **pskb, 50 unsigned int hooknum, 51 struct ip_conntrack *ct, 52 struct ip_nat_info *info) 53{ 54 return master->nat.info.helper->expect(pskb, hooknum, ct, info); 55} 56 57static unsigned int 58ip_nat_fn(unsigned int hooknum, 59 struct sk_buff **pskb, 60 const struct net_device *in, 61 const struct net_device *out, 62 int (*okfn)(struct sk_buff *)) 63{ 64 struct ip_conntrack *ct; 65 enum ip_conntrack_info ctinfo; 66 struct ip_nat_info *info; 67 /* maniptype == SRC for postrouting. */ 68 enum ip_nat_manip_type maniptype = HOOK2MANIP(hooknum); 69 70 /* We never see fragments: conntrack defrags on pre-routing 71 and local-out, and ip_nat_out protects post-routing. */ 72 IP_NF_ASSERT(!((*pskb)->nh.iph->frag_off 73 & htons(IP_MF|IP_OFFSET))); 74 75 (*pskb)->nfcache |= NFC_UNKNOWN; 76 77 /* If we had a hardware checksum before, it's now invalid */ 78 if ((*pskb)->ip_summed == CHECKSUM_HW) 79 (*pskb)->ip_summed = CHECKSUM_NONE; 80 81 ct = ip_conntrack_get(*pskb, &ctinfo); 82 /* Can't track? It's not due to stress, or conntrack would 83 have dropped it. Hence it's the user's responsibilty to 84 packet filter it out, or implement conntrack/NAT for that 85 protocol. 8) --RR */ 86 if (!ct) { 87 /* Exception: ICMP redirect to new connection (not in 88 hash table yet). We must not let this through, in 89 case we're doing NAT to the same network. */ 90 struct iphdr *iph = (*pskb)->nh.iph; 91 struct icmphdr *hdr = (struct icmphdr *) 92 ((u_int32_t *)iph + iph->ihl); 93 if (iph->protocol == IPPROTO_ICMP 94 && hdr->type == ICMP_REDIRECT) 95 return NF_DROP; 96 return NF_ACCEPT; 97 } 98 99 switch (ctinfo) { 100 case IP_CT_RELATED: 101 case IP_CT_RELATED+IP_CT_IS_REPLY: 102 if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP) { 103 return icmp_reply_translation(*pskb, ct, hooknum, 104 CTINFO2DIR(ctinfo)); 105 } 106 /* Fall thru... (Only ICMPs can be IP_CT_IS_REPLY) */ 107 case IP_CT_NEW: 108#ifdef CONFIG_IP_NF_NAT_LOCAL 109 /* LOCAL_IN hook doesn't have a chain and thus doesn't care 110 * about new packets -HW */ 111 if (hooknum == NF_IP_LOCAL_IN) 112 return NF_ACCEPT; 113#endif 114 info = &ct->nat.info; 115 116 WRITE_LOCK(&ip_nat_lock); 117 /* Seen it before? This can happen for loopback, retrans, 118 or local packets.. */ 119 if (!(info->initialized & (1 << maniptype))) { 120 int in_hashes = info->initialized; 121 unsigned int ret; 122 123 if (ct->master 124 && master_ct(ct)->nat.info.helper 125 && master_ct(ct)->nat.info.helper->expect) { 126 ret = call_expect(master_ct(ct), pskb, 127 hooknum, ct, info); 128 } else { 129 ret = ip_nat_rule_find(pskb, hooknum, in, out, 130 ct, info); 131 } 132 133 if (ret != NF_ACCEPT) { 134 WRITE_UNLOCK(&ip_nat_lock); 135 return ret; 136 } 137 138 if (in_hashes) { 139 IP_NF_ASSERT(info->bysource.conntrack); 140 replace_in_hashes(ct, info); 141 } else { 142 place_in_hashes(ct, info); 143 } 144 } else 145 DEBUGP("Already setup manip %s for ct %p\n", 146 maniptype == IP_NAT_MANIP_SRC ? "SRC" : "DST", 147 ct); 148 WRITE_UNLOCK(&ip_nat_lock); 149 break; 150 151 default: 152 /* ESTABLISHED */ 153 IP_NF_ASSERT(ctinfo == IP_CT_ESTABLISHED 154 || ctinfo == (IP_CT_ESTABLISHED+IP_CT_IS_REPLY)); 155 info = &ct->nat.info; 156 } 157 158 IP_NF_ASSERT(info); 159 return do_bindings(ct, ctinfo, info, hooknum, pskb); 160} 161 162static unsigned int 163ip_nat_out(unsigned int hooknum, 164 struct sk_buff **pskb, 165 const struct net_device *in, 166 const struct net_device *out, 167 int (*okfn)(struct sk_buff *)) 168{ 169 /* root is playing with raw sockets. */ 170 if ((*pskb)->len < sizeof(struct iphdr) 171 || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) 172 return NF_ACCEPT; 173 174 /* We can hit fragment here; forwarded packets get 175 defragmented by connection tracking coming in, then 176 fragmented (grr) by the forward code. 177 178 In future: If we have nfct != NULL, AND we have NAT 179 initialized, AND there is no helper, then we can do full 180 NAPT on the head, and IP-address-only NAT on the rest. 181 182 I'm starting to have nightmares about fragments. */ 183 184 if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) { 185 *pskb = ip_ct_gather_frags(*pskb); 186 187 if (!*pskb) 188 return NF_STOLEN; 189 } 190 191 return ip_nat_fn(hooknum, pskb, in, out, okfn); 192} 193 194static unsigned int 195ip_nat_local_fn(unsigned int hooknum, 196 struct sk_buff **pskb, 197 const struct net_device *in, 198 const struct net_device *out, 199 int (*okfn)(struct sk_buff *)) 200{ 201 u_int32_t saddr, daddr; 202 unsigned int ret; 203 204 /* root is playing with raw sockets. */ 205 if ((*pskb)->len < sizeof(struct iphdr) 206 || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) 207 return NF_ACCEPT; 208 209 saddr = (*pskb)->nh.iph->saddr; 210 daddr = (*pskb)->nh.iph->daddr; 211 212 ret = ip_nat_fn(hooknum, pskb, in, out, okfn); 213 if (ret != NF_DROP && ret != NF_STOLEN 214 && ((*pskb)->nh.iph->saddr != saddr 215 || (*pskb)->nh.iph->daddr != daddr)) 216 return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP; 217 return ret; 218} 219 220/* We must be after connection tracking and before packet filtering. */ 221 222/* Before packet filtering, change destination */ 223static struct nf_hook_ops ip_nat_in_ops 224= { { NULL, NULL }, ip_nat_fn, PF_INET, NF_IP_PRE_ROUTING, NF_IP_PRI_NAT_DST }; 225/* After packet filtering, change source */ 226static struct nf_hook_ops ip_nat_out_ops 227= { { NULL, NULL }, ip_nat_out, PF_INET, NF_IP_POST_ROUTING, NF_IP_PRI_NAT_SRC}; 228/* Before packet filtering, change destination */ 229static struct nf_hook_ops ip_nat_local_out_ops 230= { { NULL, NULL }, ip_nat_local_fn, PF_INET, NF_IP_LOCAL_OUT, NF_IP_PRI_NAT_DST }; 231 232#ifdef CONFIG_IP_NF_NAT_LOCAL 233static struct nf_hook_ops ip_nat_local_in_ops 234= { { NULL, NULL }, ip_nat_fn, PF_INET, NF_IP_LOCAL_IN, NF_IP_PRI_NAT_SRC }; 235#endif 236 237/* Protocol registration. */ 238int ip_nat_protocol_register(struct ip_nat_protocol *proto) 239{ 240 int ret = 0; 241 struct list_head *i; 242 243 WRITE_LOCK(&ip_nat_lock); 244 for (i = protos.next; i != &protos; i = i->next) { 245 if (((struct ip_nat_protocol *)i)->protonum 246 == proto->protonum) { 247 ret = -EBUSY; 248 goto out; 249 } 250 } 251 252 list_prepend(&protos, proto); 253 MOD_INC_USE_COUNT; 254 255 out: 256 WRITE_UNLOCK(&ip_nat_lock); 257 return ret; 258} 259 260/* Noone stores the protocol anywhere; simply delete it. */ 261void ip_nat_protocol_unregister(struct ip_nat_protocol *proto) 262{ 263 WRITE_LOCK(&ip_nat_lock); 264 LIST_DELETE(&protos, proto); 265 WRITE_UNLOCK(&ip_nat_lock); 266 267 /* Someone could be still looking at the proto in a bh. */ 268 br_write_lock_bh(BR_NETPROTO_LOCK); 269 br_write_unlock_bh(BR_NETPROTO_LOCK); 270 271 MOD_DEC_USE_COUNT; 272} 273 274static int init_or_cleanup(int init) 275{ 276 int ret = 0; 277 278 if (!init) goto cleanup; 279 280 ret = ip_nat_rule_init(); 281 if (ret < 0) { 282 printk("ip_nat_init: can't setup rules.\n"); 283 goto cleanup_nothing; 284 } 285 ret = ip_nat_init(); 286 if (ret < 0) { 287 printk("ip_nat_init: can't setup rules.\n"); 288 goto cleanup_rule_init; 289 } 290 ret = nf_register_hook(&ip_nat_in_ops); 291 if (ret < 0) { 292 printk("ip_nat_init: can't register in hook.\n"); 293 goto cleanup_nat; 294 } 295 ret = nf_register_hook(&ip_nat_out_ops); 296 if (ret < 0) { 297 printk("ip_nat_init: can't register out hook.\n"); 298 goto cleanup_inops; 299 } 300 ret = nf_register_hook(&ip_nat_local_out_ops); 301 if (ret < 0) { 302 printk("ip_nat_init: can't register local out hook.\n"); 303 goto cleanup_outops; 304 } 305#ifdef CONFIG_IP_NF_NAT_LOCAL 306 ret = nf_register_hook(&ip_nat_local_in_ops); 307 if (ret < 0) { 308 printk("ip_nat_init: can't register local in hook.\n"); 309 goto cleanup_localoutops; 310 } 311#endif 312 if (ip_conntrack_module) 313 __MOD_INC_USE_COUNT(ip_conntrack_module); 314 return ret; 315 316 cleanup: 317 if (ip_conntrack_module) 318 __MOD_DEC_USE_COUNT(ip_conntrack_module); 319#ifdef CONFIG_IP_NF_NAT_LOCAL 320 nf_unregister_hook(&ip_nat_local_in_ops); 321 cleanup_localoutops: 322#endif 323 nf_unregister_hook(&ip_nat_local_out_ops); 324 cleanup_outops: 325 nf_unregister_hook(&ip_nat_out_ops); 326 cleanup_inops: 327 nf_unregister_hook(&ip_nat_in_ops); 328 cleanup_nat: 329 ip_nat_cleanup(); 330 cleanup_rule_init: 331 ip_nat_rule_cleanup(); 332 cleanup_nothing: 333 MUST_BE_READ_WRITE_UNLOCKED(&ip_nat_lock); 334 return ret; 335} 336 337static int __init init(void) 338{ 339 return init_or_cleanup(1); 340} 341 342static void __exit fini(void) 343{ 344 init_or_cleanup(0); 345} 346 347module_init(init); 348module_exit(fini); 349 350EXPORT_SYMBOL(ip_nat_setup_info); 351EXPORT_SYMBOL(ip_nat_protocol_register); 352EXPORT_SYMBOL(ip_nat_protocol_unregister); 353EXPORT_SYMBOL(ip_nat_helper_register); 354EXPORT_SYMBOL(ip_nat_helper_unregister); 355EXPORT_SYMBOL(ip_nat_cheat_check); 356EXPORT_SYMBOL(ip_nat_mangle_tcp_packet); 357EXPORT_SYMBOL(ip_nat_mangle_udp_packet); 358EXPORT_SYMBOL(ip_nat_used_tuple); 359MODULE_LICENSE("GPL"); 360