nf_nat_standalone.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. /* (C) 1999-2001 Paul `Rusty' Russell
  2. * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 2 as
  6. * published by the Free Software Foundation.
  7. */
  8. #include <linux/types.h>
  9. #include <linux/icmp.h>
  10. #include <linux/ip.h>
  11. #include <linux/netfilter.h>
  12. #include <linux/netfilter_ipv4.h>
  13. #include <linux/module.h>
  14. #include <linux/skbuff.h>
  15. #include <linux/proc_fs.h>
  16. #include <net/ip.h>
  17. #include <net/checksum.h>
  18. #include <linux/spinlock.h>
  19. #include <net/netfilter/nf_conntrack.h>
  20. #include <net/netfilter/nf_conntrack_core.h>
  21. #include <net/netfilter/nf_nat.h>
  22. #include <net/netfilter/nf_nat_rule.h>
  23. #include <net/netfilter/nf_nat_protocol.h>
  24. #include <net/netfilter/nf_nat_core.h>
  25. #include <net/netfilter/nf_nat_helper.h>
  26. #include <linux/netfilter_ipv4/ip_tables.h>
  27. #if 0
  28. #define DEBUGP printk
  29. #else
  30. #define DEBUGP(format, args...)
  31. #endif
  32. #ifdef CONFIG_XFRM
  33. static void nat_decode_session(struct sk_buff *skb, struct flowi *fl)
  34. {
  35. struct nf_conn *ct;
  36. struct nf_conntrack_tuple *t;
  37. enum ip_conntrack_info ctinfo;
  38. enum ip_conntrack_dir dir;
  39. unsigned long statusbit;
  40. ct = nf_ct_get(skb, &ctinfo);
  41. if (ct == NULL)
  42. return;
  43. dir = CTINFO2DIR(ctinfo);
  44. t = &ct->tuplehash[dir].tuple;
  45. if (dir == IP_CT_DIR_ORIGINAL)
  46. statusbit = IPS_DST_NAT;
  47. else
  48. statusbit = IPS_SRC_NAT;
  49. if (ct->status & statusbit) {
  50. fl->fl4_dst = t->dst.u3.ip;
  51. if (t->dst.protonum == IPPROTO_TCP ||
  52. t->dst.protonum == IPPROTO_UDP)
  53. fl->fl_ip_dport = t->dst.u.tcp.port;
  54. }
  55. statusbit ^= IPS_NAT_MASK;
  56. if (ct->status & statusbit) {
  57. fl->fl4_src = t->src.u3.ip;
  58. if (t->dst.protonum == IPPROTO_TCP ||
  59. t->dst.protonum == IPPROTO_UDP)
  60. fl->fl_ip_sport = t->src.u.tcp.port;
  61. }
  62. }
  63. #endif
  64. static unsigned int
  65. nf_nat_fn(unsigned int hooknum,
  66. struct sk_buff **pskb,
  67. const struct net_device *in,
  68. const struct net_device *out,
  69. int (*okfn)(struct sk_buff *))
  70. {
  71. struct nf_conn *ct;
  72. enum ip_conntrack_info ctinfo;
  73. struct nf_conn_nat *nat;
  74. struct nf_nat_info *info;
  75. /* maniptype == SRC for postrouting. */
  76. enum nf_nat_manip_type maniptype = HOOK2MANIP(hooknum);
  77. /* We never see fragments: conntrack defrags on pre-routing
  78. and local-out, and nf_nat_out protects post-routing. */
  79. NF_CT_ASSERT(!((*pskb)->nh.iph->frag_off
  80. & htons(IP_MF|IP_OFFSET)));
  81. ct = nf_ct_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. if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP) {
  91. struct icmphdr _hdr, *hp;
  92. hp = skb_header_pointer(*pskb,
  93. (*pskb)->nh.iph->ihl*4,
  94. sizeof(_hdr), &_hdr);
  95. if (hp != NULL &&
  96. hp->type == ICMP_REDIRECT)
  97. return NF_DROP;
  98. }
  99. return NF_ACCEPT;
  100. }
  101. /* Don't try to NAT if this packet is not conntracked */
  102. if (ct == &nf_conntrack_untracked)
  103. return NF_ACCEPT;
  104. nat = nfct_nat(ct);
  105. if (!nat)
  106. return NF_ACCEPT;
  107. switch (ctinfo) {
  108. case IP_CT_RELATED:
  109. case IP_CT_RELATED+IP_CT_IS_REPLY:
  110. if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP) {
  111. if (!nf_nat_icmp_reply_translation(ct, ctinfo,
  112. hooknum, pskb))
  113. return NF_DROP;
  114. else
  115. return NF_ACCEPT;
  116. }
  117. /* Fall thru... (Only ICMPs can be IP_CT_IS_REPLY) */
  118. case IP_CT_NEW:
  119. info = &nat->info;
  120. /* Seen it before? This can happen for loopback, retrans,
  121. or local packets.. */
  122. if (!nf_nat_initialized(ct, maniptype)) {
  123. unsigned int ret;
  124. if (unlikely(nf_ct_is_confirmed(ct)))
  125. /* NAT module was loaded late */
  126. ret = alloc_null_binding_confirmed(ct, info,
  127. hooknum);
  128. else if (hooknum == NF_IP_LOCAL_IN)
  129. /* LOCAL_IN hook doesn't have a chain! */
  130. ret = alloc_null_binding(ct, info, hooknum);
  131. else
  132. ret = nf_nat_rule_find(pskb, hooknum, in, out,
  133. ct, info);
  134. if (ret != NF_ACCEPT) {
  135. return ret;
  136. }
  137. } else
  138. DEBUGP("Already setup manip %s for ct %p\n",
  139. maniptype == IP_NAT_MANIP_SRC ? "SRC" : "DST",
  140. ct);
  141. break;
  142. default:
  143. /* ESTABLISHED */
  144. NF_CT_ASSERT(ctinfo == IP_CT_ESTABLISHED ||
  145. ctinfo == (IP_CT_ESTABLISHED+IP_CT_IS_REPLY));
  146. info = &nat->info;
  147. }
  148. NF_CT_ASSERT(info);
  149. return nf_nat_packet(ct, ctinfo, hooknum, pskb);
  150. }
  151. static unsigned int
  152. nf_nat_in(unsigned int hooknum,
  153. struct sk_buff **pskb,
  154. const struct net_device *in,
  155. const struct net_device *out,
  156. int (*okfn)(struct sk_buff *))
  157. {
  158. unsigned int ret;
  159. __be32 daddr = (*pskb)->nh.iph->daddr;
  160. ret = nf_nat_fn(hooknum, pskb, in, out, okfn);
  161. if (ret != NF_DROP && ret != NF_STOLEN &&
  162. daddr != (*pskb)->nh.iph->daddr) {
  163. dst_release((*pskb)->dst);
  164. (*pskb)->dst = NULL;
  165. }
  166. return ret;
  167. }
  168. static unsigned int
  169. nf_nat_out(unsigned int hooknum,
  170. struct sk_buff **pskb,
  171. const struct net_device *in,
  172. const struct net_device *out,
  173. int (*okfn)(struct sk_buff *))
  174. {
  175. #ifdef CONFIG_XFRM
  176. struct nf_conn *ct;
  177. enum ip_conntrack_info ctinfo;
  178. #endif
  179. unsigned int ret;
  180. /* root is playing with raw sockets. */
  181. if ((*pskb)->len < sizeof(struct iphdr) ||
  182. (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
  183. return NF_ACCEPT;
  184. ret = nf_nat_fn(hooknum, pskb, in, out, okfn);
  185. #ifdef CONFIG_XFRM
  186. if (ret != NF_DROP && ret != NF_STOLEN &&
  187. (ct = nf_ct_get(*pskb, &ctinfo)) != NULL) {
  188. enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
  189. if (ct->tuplehash[dir].tuple.src.u3.ip !=
  190. ct->tuplehash[!dir].tuple.dst.u3.ip
  191. || ct->tuplehash[dir].tuple.src.u.all !=
  192. ct->tuplehash[!dir].tuple.dst.u.all
  193. )
  194. return ip_xfrm_me_harder(pskb) == 0 ? ret : NF_DROP;
  195. }
  196. #endif
  197. return ret;
  198. }
  199. static unsigned int
  200. nf_nat_local_fn(unsigned int hooknum,
  201. struct sk_buff **pskb,
  202. const struct net_device *in,
  203. const struct net_device *out,
  204. int (*okfn)(struct sk_buff *))
  205. {
  206. struct nf_conn *ct;
  207. enum ip_conntrack_info ctinfo;
  208. unsigned int ret;
  209. /* root is playing with raw sockets. */
  210. if ((*pskb)->len < sizeof(struct iphdr) ||
  211. (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
  212. return NF_ACCEPT;
  213. ret = nf_nat_fn(hooknum, pskb, in, out, okfn);
  214. if (ret != NF_DROP && ret != NF_STOLEN &&
  215. (ct = nf_ct_get(*pskb, &ctinfo)) != NULL) {
  216. enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
  217. if (ct->tuplehash[dir].tuple.dst.u3.ip !=
  218. ct->tuplehash[!dir].tuple.src.u3.ip) {
  219. if (ip_route_me_harder(pskb, RTN_UNSPEC))
  220. ret = NF_DROP;
  221. }
  222. #ifdef CONFIG_XFRM
  223. else if (ct->tuplehash[dir].tuple.dst.u.all !=
  224. ct->tuplehash[!dir].tuple.src.u.all)
  225. if (ip_xfrm_me_harder(pskb))
  226. ret = NF_DROP;
  227. #endif
  228. }
  229. return ret;
  230. }
  231. static unsigned int
  232. nf_nat_adjust(unsigned int hooknum,
  233. struct sk_buff **pskb,
  234. const struct net_device *in,
  235. const struct net_device *out,
  236. int (*okfn)(struct sk_buff *))
  237. {
  238. struct nf_conn *ct;
  239. enum ip_conntrack_info ctinfo;
  240. ct = nf_ct_get(*pskb, &ctinfo);
  241. if (ct && test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) {
  242. DEBUGP("nf_nat_standalone: adjusting sequence number\n");
  243. if (!nf_nat_seq_adjust(pskb, ct, ctinfo))
  244. return NF_DROP;
  245. }
  246. return NF_ACCEPT;
  247. }
  248. /* We must be after connection tracking and before packet filtering. */
  249. static struct nf_hook_ops nf_nat_ops[] = {
  250. /* Before packet filtering, change destination */
  251. {
  252. .hook = nf_nat_in,
  253. .owner = THIS_MODULE,
  254. .pf = PF_INET,
  255. .hooknum = NF_IP_PRE_ROUTING,
  256. .priority = NF_IP_PRI_NAT_DST,
  257. },
  258. /* After packet filtering, change source */
  259. {
  260. .hook = nf_nat_out,
  261. .owner = THIS_MODULE,
  262. .pf = PF_INET,
  263. .hooknum = NF_IP_POST_ROUTING,
  264. .priority = NF_IP_PRI_NAT_SRC,
  265. },
  266. /* After conntrack, adjust sequence number */
  267. {
  268. .hook = nf_nat_adjust,
  269. .owner = THIS_MODULE,
  270. .pf = PF_INET,
  271. .hooknum = NF_IP_POST_ROUTING,
  272. .priority = NF_IP_PRI_NAT_SEQ_ADJUST,
  273. },
  274. /* Before packet filtering, change destination */
  275. {
  276. .hook = nf_nat_local_fn,
  277. .owner = THIS_MODULE,
  278. .pf = PF_INET,
  279. .hooknum = NF_IP_LOCAL_OUT,
  280. .priority = NF_IP_PRI_NAT_DST,
  281. },
  282. /* After packet filtering, change source */
  283. {
  284. .hook = nf_nat_fn,
  285. .owner = THIS_MODULE,
  286. .pf = PF_INET,
  287. .hooknum = NF_IP_LOCAL_IN,
  288. .priority = NF_IP_PRI_NAT_SRC,
  289. },
  290. /* After conntrack, adjust sequence number */
  291. {
  292. .hook = nf_nat_adjust,
  293. .owner = THIS_MODULE,
  294. .pf = PF_INET,
  295. .hooknum = NF_IP_LOCAL_IN,
  296. .priority = NF_IP_PRI_NAT_SEQ_ADJUST,
  297. },
  298. };
  299. static int __init nf_nat_standalone_init(void)
  300. {
  301. int size, ret = 0;
  302. need_conntrack();
  303. size = ALIGN(sizeof(struct nf_conn), __alignof__(struct nf_conn_nat)) +
  304. sizeof(struct nf_conn_nat);
  305. ret = nf_conntrack_register_cache(NF_CT_F_NAT, "nf_nat:base", size);
  306. if (ret < 0) {
  307. printk(KERN_ERR "nf_nat_init: Unable to create slab cache\n");
  308. return ret;
  309. }
  310. size = ALIGN(size, __alignof__(struct nf_conn_help)) +
  311. sizeof(struct nf_conn_help);
  312. ret = nf_conntrack_register_cache(NF_CT_F_NAT|NF_CT_F_HELP,
  313. "nf_nat:help", size);
  314. if (ret < 0) {
  315. printk(KERN_ERR "nf_nat_init: Unable to create slab cache\n");
  316. goto cleanup_register_cache;
  317. }
  318. #ifdef CONFIG_XFRM
  319. BUG_ON(ip_nat_decode_session != NULL);
  320. ip_nat_decode_session = nat_decode_session;
  321. #endif
  322. ret = nf_nat_rule_init();
  323. if (ret < 0) {
  324. printk("nf_nat_init: can't setup rules.\n");
  325. goto cleanup_decode_session;
  326. }
  327. ret = nf_register_hooks(nf_nat_ops, ARRAY_SIZE(nf_nat_ops));
  328. if (ret < 0) {
  329. printk("nf_nat_init: can't register hooks.\n");
  330. goto cleanup_rule_init;
  331. }
  332. nf_nat_module_is_loaded = 1;
  333. return ret;
  334. cleanup_rule_init:
  335. nf_nat_rule_cleanup();
  336. cleanup_decode_session:
  337. #ifdef CONFIG_XFRM
  338. ip_nat_decode_session = NULL;
  339. synchronize_net();
  340. #endif
  341. nf_conntrack_unregister_cache(NF_CT_F_NAT|NF_CT_F_HELP);
  342. cleanup_register_cache:
  343. nf_conntrack_unregister_cache(NF_CT_F_NAT);
  344. return ret;
  345. }
  346. static void __exit nf_nat_standalone_fini(void)
  347. {
  348. nf_unregister_hooks(nf_nat_ops, ARRAY_SIZE(nf_nat_ops));
  349. nf_nat_rule_cleanup();
  350. nf_nat_module_is_loaded = 0;
  351. #ifdef CONFIG_XFRM
  352. ip_nat_decode_session = NULL;
  353. synchronize_net();
  354. #endif
  355. /* Conntrack caches are unregistered in nf_conntrack_cleanup */
  356. }
  357. module_init(nf_nat_standalone_init);
  358. module_exit(nf_nat_standalone_fini);
  359. MODULE_LICENSE("GPL");
  360. MODULE_ALIAS("ip_nat");