xt_NETMAP.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * (C) 2000-2001 Svenning Soerensen <svenning@post5.tele.dk>
  4. * Copyright (c) 2011 Patrick McHardy <kaber@trash.net>
  5. */
  6. #include <linux/ip.h>
  7. #include <linux/kernel.h>
  8. #include <linux/module.h>
  9. #include <linux/netdevice.h>
  10. #include <linux/ipv6.h>
  11. #include <linux/netfilter.h>
  12. #include <linux/netfilter_ipv4.h>
  13. #include <linux/netfilter_ipv6.h>
  14. #include <linux/netfilter/x_tables.h>
  15. #include <net/netfilter/nf_nat.h>
  16. static unsigned int
  17. netmap_tg6(struct sk_buff *skb, const struct xt_action_param *par)
  18. {
  19. const struct nf_nat_range2 *range = par->targinfo;
  20. struct nf_nat_range2 newrange;
  21. struct nf_conn *ct;
  22. enum ip_conntrack_info ctinfo;
  23. union nf_inet_addr new_addr, netmask;
  24. unsigned int i;
  25. ct = nf_ct_get(skb, &ctinfo);
  26. for (i = 0; i < ARRAY_SIZE(range->min_addr.ip6); i++)
  27. netmask.ip6[i] = ~(range->min_addr.ip6[i] ^
  28. range->max_addr.ip6[i]);
  29. if (xt_hooknum(par) == NF_INET_PRE_ROUTING ||
  30. xt_hooknum(par) == NF_INET_LOCAL_OUT)
  31. new_addr.in6 = ipv6_hdr(skb)->daddr;
  32. else
  33. new_addr.in6 = ipv6_hdr(skb)->saddr;
  34. for (i = 0; i < ARRAY_SIZE(new_addr.ip6); i++) {
  35. new_addr.ip6[i] &= ~netmask.ip6[i];
  36. new_addr.ip6[i] |= range->min_addr.ip6[i] &
  37. netmask.ip6[i];
  38. }
  39. newrange.flags = range->flags | NF_NAT_RANGE_MAP_IPS;
  40. newrange.min_addr = new_addr;
  41. newrange.max_addr = new_addr;
  42. newrange.min_proto = range->min_proto;
  43. newrange.max_proto = range->max_proto;
  44. return nf_nat_setup_info(ct, &newrange, HOOK2MANIP(xt_hooknum(par)));
  45. }
  46. static int netmap_tg6_checkentry(const struct xt_tgchk_param *par)
  47. {
  48. const struct nf_nat_range2 *range = par->targinfo;
  49. if (!(range->flags & NF_NAT_RANGE_MAP_IPS))
  50. return -EINVAL;
  51. return nf_ct_netns_get(par->net, par->family);
  52. }
  53. static void netmap_tg_destroy(const struct xt_tgdtor_param *par)
  54. {
  55. nf_ct_netns_put(par->net, par->family);
  56. }
  57. static unsigned int
  58. netmap_tg4(struct sk_buff *skb, const struct xt_action_param *par)
  59. {
  60. struct nf_conn *ct;
  61. enum ip_conntrack_info ctinfo;
  62. __be32 new_ip, netmask;
  63. const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
  64. struct nf_nat_range2 newrange;
  65. WARN_ON(xt_hooknum(par) != NF_INET_PRE_ROUTING &&
  66. xt_hooknum(par) != NF_INET_POST_ROUTING &&
  67. xt_hooknum(par) != NF_INET_LOCAL_OUT &&
  68. xt_hooknum(par) != NF_INET_LOCAL_IN);
  69. ct = nf_ct_get(skb, &ctinfo);
  70. netmask = ~(mr->range[0].min_ip ^ mr->range[0].max_ip);
  71. if (xt_hooknum(par) == NF_INET_PRE_ROUTING ||
  72. xt_hooknum(par) == NF_INET_LOCAL_OUT)
  73. new_ip = ip_hdr(skb)->daddr & ~netmask;
  74. else
  75. new_ip = ip_hdr(skb)->saddr & ~netmask;
  76. new_ip |= mr->range[0].min_ip & netmask;
  77. memset(&newrange.min_addr, 0, sizeof(newrange.min_addr));
  78. memset(&newrange.max_addr, 0, sizeof(newrange.max_addr));
  79. newrange.flags = mr->range[0].flags | NF_NAT_RANGE_MAP_IPS;
  80. newrange.min_addr.ip = new_ip;
  81. newrange.max_addr.ip = new_ip;
  82. newrange.min_proto = mr->range[0].min;
  83. newrange.max_proto = mr->range[0].max;
  84. /* Hand modified range to generic setup. */
  85. return nf_nat_setup_info(ct, &newrange, HOOK2MANIP(xt_hooknum(par)));
  86. }
  87. static int netmap_tg4_check(const struct xt_tgchk_param *par)
  88. {
  89. const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
  90. if (!(mr->range[0].flags & NF_NAT_RANGE_MAP_IPS)) {
  91. pr_debug("bad MAP_IPS.\n");
  92. return -EINVAL;
  93. }
  94. if (mr->rangesize != 1) {
  95. pr_debug("bad rangesize %u.\n", mr->rangesize);
  96. return -EINVAL;
  97. }
  98. return nf_ct_netns_get(par->net, par->family);
  99. }
  100. static struct xt_target netmap_tg_reg[] __read_mostly = {
  101. {
  102. .name = "NETMAP",
  103. .family = NFPROTO_IPV6,
  104. .revision = 0,
  105. .target = netmap_tg6,
  106. .targetsize = sizeof(struct nf_nat_range),
  107. .table = "nat",
  108. .hooks = (1 << NF_INET_PRE_ROUTING) |
  109. (1 << NF_INET_POST_ROUTING) |
  110. (1 << NF_INET_LOCAL_OUT) |
  111. (1 << NF_INET_LOCAL_IN),
  112. .checkentry = netmap_tg6_checkentry,
  113. .destroy = netmap_tg_destroy,
  114. .me = THIS_MODULE,
  115. },
  116. {
  117. .name = "NETMAP",
  118. .family = NFPROTO_IPV4,
  119. .revision = 0,
  120. .target = netmap_tg4,
  121. .targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat),
  122. .table = "nat",
  123. .hooks = (1 << NF_INET_PRE_ROUTING) |
  124. (1 << NF_INET_POST_ROUTING) |
  125. (1 << NF_INET_LOCAL_OUT) |
  126. (1 << NF_INET_LOCAL_IN),
  127. .checkentry = netmap_tg4_check,
  128. .destroy = netmap_tg_destroy,
  129. .me = THIS_MODULE,
  130. },
  131. };
  132. static int __init netmap_tg_init(void)
  133. {
  134. return xt_register_targets(netmap_tg_reg, ARRAY_SIZE(netmap_tg_reg));
  135. }
  136. static void netmap_tg_exit(void)
  137. {
  138. xt_unregister_targets(netmap_tg_reg, ARRAY_SIZE(netmap_tg_reg));
  139. }
  140. module_init(netmap_tg_init);
  141. module_exit(netmap_tg_exit);
  142. MODULE_LICENSE("GPL");
  143. MODULE_DESCRIPTION("Xtables: 1:1 NAT mapping of subnets");
  144. MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
  145. MODULE_ALIAS("ip6t_NETMAP");
  146. MODULE_ALIAS("ipt_NETMAP");