xt_nat.c 6.6 KB

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