ipt_SAME.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. /* Same. Just like SNAT, only try to make the connections
  2. * between client A and server B always have the same source ip.
  3. *
  4. * (C) 2000 Paul `Rusty' Russell
  5. * (C) 2001 Martin Josefsson
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License version 2 as
  9. * published by the Free Software Foundation.
  10. *
  11. * 010320 Martin Josefsson <gandalf@wlug.westbo.se>
  12. * * copied ipt_BALANCE.c to ipt_SAME.c and changed a few things.
  13. * 010728 Martin Josefsson <gandalf@wlug.westbo.se>
  14. * * added --nodst to not include destination-ip in new source
  15. * calculations.
  16. * * added some more sanity-checks.
  17. * 010729 Martin Josefsson <gandalf@wlug.westbo.se>
  18. * * fixed a buggy if-statement in same_check(), should have
  19. * used ntohl() but didn't.
  20. * * added support for multiple ranges. IPT_SAME_MAX_RANGE is
  21. * defined in linux/include/linux/netfilter_ipv4/ipt_SAME.h
  22. * and is currently set to 10.
  23. * * added support for 1-address range, nice to have now that
  24. * we have multiple ranges.
  25. */
  26. #include <linux/types.h>
  27. #include <linux/ip.h>
  28. #include <linux/timer.h>
  29. #include <linux/module.h>
  30. #include <linux/netfilter.h>
  31. #include <linux/netdevice.h>
  32. #include <linux/if.h>
  33. #include <linux/inetdevice.h>
  34. #include <net/protocol.h>
  35. #include <net/checksum.h>
  36. #include <linux/netfilter_ipv4.h>
  37. #include <linux/netfilter/x_tables.h>
  38. #ifdef CONFIG_NF_NAT_NEEDED
  39. #include <net/netfilter/nf_nat_rule.h>
  40. #else
  41. #include <linux/netfilter_ipv4/ip_nat_rule.h>
  42. #endif
  43. #include <linux/netfilter_ipv4/ipt_SAME.h>
  44. MODULE_LICENSE("GPL");
  45. MODULE_AUTHOR("Martin Josefsson <gandalf@wlug.westbo.se>");
  46. MODULE_DESCRIPTION("iptables special SNAT module for consistent sourceip");
  47. #if 0
  48. #define DEBUGP printk
  49. #else
  50. #define DEBUGP(format, args...)
  51. #endif
  52. static int
  53. same_check(const char *tablename,
  54. const void *e,
  55. const struct xt_target *target,
  56. void *targinfo,
  57. unsigned int hook_mask)
  58. {
  59. unsigned int count, countess, rangeip, index = 0;
  60. struct ipt_same_info *mr = targinfo;
  61. mr->ipnum = 0;
  62. if (mr->rangesize < 1) {
  63. DEBUGP("same_check: need at least one dest range.\n");
  64. return 0;
  65. }
  66. if (mr->rangesize > IPT_SAME_MAX_RANGE) {
  67. DEBUGP("same_check: too many ranges specified, maximum "
  68. "is %u ranges\n",
  69. IPT_SAME_MAX_RANGE);
  70. return 0;
  71. }
  72. for (count = 0; count < mr->rangesize; count++) {
  73. if (ntohl(mr->range[count].min_ip) >
  74. ntohl(mr->range[count].max_ip)) {
  75. DEBUGP("same_check: min_ip is larger than max_ip in "
  76. "range `%u.%u.%u.%u-%u.%u.%u.%u'.\n",
  77. NIPQUAD(mr->range[count].min_ip),
  78. NIPQUAD(mr->range[count].max_ip));
  79. return 0;
  80. }
  81. if (!(mr->range[count].flags & IP_NAT_RANGE_MAP_IPS)) {
  82. DEBUGP("same_check: bad MAP_IPS.\n");
  83. return 0;
  84. }
  85. rangeip = (ntohl(mr->range[count].max_ip) -
  86. ntohl(mr->range[count].min_ip) + 1);
  87. mr->ipnum += rangeip;
  88. DEBUGP("same_check: range %u, ipnum = %u\n", count, rangeip);
  89. }
  90. DEBUGP("same_check: total ipaddresses = %u\n", mr->ipnum);
  91. mr->iparray = kmalloc((sizeof(u_int32_t) * mr->ipnum), GFP_KERNEL);
  92. if (!mr->iparray) {
  93. DEBUGP("same_check: Couldn't allocate %u bytes "
  94. "for %u ipaddresses!\n",
  95. (sizeof(u_int32_t) * mr->ipnum), mr->ipnum);
  96. return 0;
  97. }
  98. DEBUGP("same_check: Allocated %u bytes for %u ipaddresses.\n",
  99. (sizeof(u_int32_t) * mr->ipnum), mr->ipnum);
  100. for (count = 0; count < mr->rangesize; count++) {
  101. for (countess = ntohl(mr->range[count].min_ip);
  102. countess <= ntohl(mr->range[count].max_ip);
  103. countess++) {
  104. mr->iparray[index] = countess;
  105. DEBUGP("same_check: Added ipaddress `%u.%u.%u.%u' "
  106. "in index %u.\n",
  107. HIPQUAD(countess), index);
  108. index++;
  109. }
  110. }
  111. return 1;
  112. }
  113. static void
  114. same_destroy(const struct xt_target *target, void *targinfo)
  115. {
  116. struct ipt_same_info *mr = targinfo;
  117. kfree(mr->iparray);
  118. DEBUGP("same_destroy: Deallocated %u bytes for %u ipaddresses.\n",
  119. (sizeof(u_int32_t) * mr->ipnum), mr->ipnum);
  120. }
  121. static unsigned int
  122. same_target(struct sk_buff **pskb,
  123. const struct net_device *in,
  124. const struct net_device *out,
  125. unsigned int hooknum,
  126. const struct xt_target *target,
  127. const void *targinfo)
  128. {
  129. struct ip_conntrack *ct;
  130. enum ip_conntrack_info ctinfo;
  131. u_int32_t tmpip, aindex;
  132. __be32 new_ip;
  133. const struct ipt_same_info *same = targinfo;
  134. struct ip_nat_range newrange;
  135. const struct ip_conntrack_tuple *t;
  136. IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING ||
  137. hooknum == NF_IP_POST_ROUTING);
  138. ct = ip_conntrack_get(*pskb, &ctinfo);
  139. t = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
  140. /* Base new source on real src ip and optionally dst ip,
  141. giving some hope for consistency across reboots.
  142. Here we calculate the index in same->iparray which
  143. holds the ipaddress we should use */
  144. #ifdef CONFIG_NF_NAT_NEEDED
  145. tmpip = ntohl(t->src.u3.ip);
  146. if (!(same->info & IPT_SAME_NODST))
  147. tmpip += ntohl(t->dst.u3.ip);
  148. #else
  149. tmpip = ntohl(t->src.ip);
  150. if (!(same->info & IPT_SAME_NODST))
  151. tmpip += ntohl(t->dst.ip);
  152. #endif
  153. aindex = tmpip % same->ipnum;
  154. new_ip = htonl(same->iparray[aindex]);
  155. DEBUGP("ipt_SAME: src=%u.%u.%u.%u dst=%u.%u.%u.%u, "
  156. "new src=%u.%u.%u.%u\n",
  157. NIPQUAD(t->src.ip), NIPQUAD(t->dst.ip),
  158. NIPQUAD(new_ip));
  159. /* Transfer from original range. */
  160. newrange = ((struct ip_nat_range)
  161. { same->range[0].flags, new_ip, new_ip,
  162. /* FIXME: Use ports from correct range! */
  163. same->range[0].min, same->range[0].max });
  164. /* Hand modified range to generic setup. */
  165. return ip_nat_setup_info(ct, &newrange, hooknum);
  166. }
  167. static struct xt_target same_reg = {
  168. .name = "SAME",
  169. .family = AF_INET,
  170. .target = same_target,
  171. .targetsize = sizeof(struct ipt_same_info),
  172. .table = "nat",
  173. .hooks = (1 << NF_IP_PRE_ROUTING | 1 << NF_IP_POST_ROUTING),
  174. .checkentry = same_check,
  175. .destroy = same_destroy,
  176. .me = THIS_MODULE,
  177. };
  178. static int __init ipt_same_init(void)
  179. {
  180. return xt_register_target(&same_reg);
  181. }
  182. static void __exit ipt_same_fini(void)
  183. {
  184. xt_unregister_target(&same_reg);
  185. }
  186. module_init(ipt_same_init);
  187. module_exit(ipt_same_fini);