ipt_MASQUERADE.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:5k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* Masquerade.  Simple mapping which alters range to a local IP address
  2.    (depending on route). */
  3. #include <linux/config.h>
  4. #include <linux/types.h>
  5. #include <linux/ip.h>
  6. #include <linux/timer.h>
  7. #include <linux/module.h>
  8. #include <linux/netfilter.h>
  9. #include <net/protocol.h>
  10. #include <net/checksum.h>
  11. #include <linux/netfilter_ipv4.h>
  12. #include <linux/netfilter_ipv4/ip_nat_rule.h>
  13. #include <linux/netfilter_ipv4/ip_tables.h>
  14. #if 0
  15. #define DEBUGP printk
  16. #else
  17. #define DEBUGP(format, args...)
  18. #endif
  19. /* Lock protects masq region inside conntrack */
  20. static DECLARE_RWLOCK(masq_lock);
  21. /* FIXME: Multiple targets. --RR */
  22. static int
  23. masquerade_check(const char *tablename,
  24.  const struct ipt_entry *e,
  25.  void *targinfo,
  26.  unsigned int targinfosize,
  27.  unsigned int hook_mask)
  28. {
  29. const struct ip_nat_multi_range *mr = targinfo;
  30. if (strcmp(tablename, "nat") != 0) {
  31. DEBUGP("masquerade_check: bad table `%s'.n", table);
  32. return 0;
  33. }
  34. if (targinfosize != IPT_ALIGN(sizeof(*mr))) {
  35. DEBUGP("masquerade_check: size %u != %u.n",
  36.        targinfosize, sizeof(*mr));
  37. return 0;
  38. }
  39. if (hook_mask & ~(1 << NF_IP_POST_ROUTING)) {
  40. DEBUGP("masquerade_check: bad hooks %x.n", hook_mask);
  41. return 0;
  42. }
  43. if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) {
  44. DEBUGP("masquerade_check: bad MAP_IPS.n");
  45. return 0;
  46. }
  47. if (mr->rangesize != 1) {
  48. DEBUGP("masquerade_check: bad rangesize %u.n", mr->rangesize);
  49. return 0;
  50. }
  51. return 1;
  52. }
  53. static unsigned int
  54. masquerade_target(struct sk_buff **pskb,
  55.   unsigned int hooknum,
  56.   const struct net_device *in,
  57.   const struct net_device *out,
  58.   const void *targinfo,
  59.   void *userinfo)
  60. {
  61. struct ip_conntrack *ct;
  62. enum ip_conntrack_info ctinfo;
  63. const struct ip_nat_multi_range *mr;
  64. struct ip_nat_multi_range newrange;
  65. u_int32_t newsrc;
  66. struct rtable *rt;
  67. struct rt_key key;
  68. IP_NF_ASSERT(hooknum == NF_IP_POST_ROUTING);
  69. /* FIXME: For the moment, don't do local packets, breaks
  70.    testsuite for 2.3.49 --RR */
  71. if ((*pskb)->sk)
  72. return NF_ACCEPT;
  73. ct = ip_conntrack_get(*pskb, &ctinfo);
  74. IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW
  75.   || ctinfo == IP_CT_RELATED));
  76. mr = targinfo;
  77. key.dst = (*pskb)->nh.iph->daddr;
  78. key.src = 0; /* Unknown: that's what we're trying to establish */
  79. key.tos = RT_TOS((*pskb)->nh.iph->tos)|RTO_CONN;
  80. key.oif = out->ifindex;
  81. #ifdef CONFIG_IP_ROUTE_FWMARK
  82. key.fwmark = (*pskb)->nfmark;
  83. #endif
  84. if (ip_route_output_key(&rt, &key) != 0) {
  85. /* Shouldn't happen */
  86. printk("MASQUERADE: No route: Rusty's brain broke!n");
  87. return NF_DROP;
  88. }
  89. newsrc = rt->rt_src;
  90. DEBUGP("newsrc = %u.%u.%u.%un", NIPQUAD(newsrc));
  91. ip_rt_put(rt);
  92. WRITE_LOCK(&masq_lock);
  93. ct->nat.masq_index = out->ifindex;
  94. WRITE_UNLOCK(&masq_lock);
  95. /* Transfer from original range. */
  96. newrange = ((struct ip_nat_multi_range)
  97. { 1, { { mr->range[0].flags | IP_NAT_RANGE_MAP_IPS,
  98.  newsrc, newsrc,
  99.  mr->range[0].min, mr->range[0].max } } });
  100. /* Hand modified range to generic setup. */
  101. return ip_nat_setup_info(ct, &newrange, hooknum);
  102. }
  103. static inline int
  104. device_cmp(const struct ip_conntrack *i, void *ifindex)
  105. {
  106. int ret;
  107. READ_LOCK(&masq_lock);
  108. ret = (i->nat.masq_index == (int)(long)ifindex);
  109. READ_UNLOCK(&masq_lock);
  110. return ret;
  111. }
  112. static int masq_device_event(struct notifier_block *this,
  113.      unsigned long event,
  114.      void *ptr)
  115. {
  116. struct net_device *dev = ptr;
  117. if (event == NETDEV_DOWN) {
  118. /* Device was downed.  Search entire table for
  119.    conntracks which were associated with that device,
  120.    and forget them. */
  121. IP_NF_ASSERT(dev->ifindex != 0);
  122. ip_ct_selective_cleanup(device_cmp, (void *)(long)dev->ifindex);
  123. }
  124. return NOTIFY_DONE;
  125. }
  126. static int masq_inet_event(struct notifier_block *this,
  127.    unsigned long event,
  128.    void *ptr)
  129. {
  130. struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev;
  131. if (event == NETDEV_DOWN) {
  132. /* IP address was deleted.  Search entire table for
  133.    conntracks which were associated with that device,
  134.    and forget them. */
  135. IP_NF_ASSERT(dev->ifindex != 0);
  136. ip_ct_selective_cleanup(device_cmp, (void *)(long)dev->ifindex);
  137. }
  138. return NOTIFY_DONE;
  139. }
  140. static struct notifier_block masq_dev_notifier = {
  141. masq_device_event,
  142. NULL,
  143. 0
  144. };
  145. static struct notifier_block masq_inet_notifier = {
  146. masq_inet_event,
  147. NULL,
  148. 0
  149. };
  150. static struct ipt_target masquerade
  151. = { { NULL, NULL }, "MASQUERADE", masquerade_target, masquerade_check, NULL,
  152.     THIS_MODULE };
  153. static int __init init(void)
  154. {
  155. int ret;
  156. ret = ipt_register_target(&masquerade);
  157. if (ret == 0) {
  158. /* Register for device down reports */
  159. register_netdevice_notifier(&masq_dev_notifier);
  160. /* Register IP address change reports */
  161. register_inetaddr_notifier(&masq_inet_notifier);
  162. }
  163. return ret;
  164. }
  165. static void __exit fini(void)
  166. {
  167. ipt_unregister_target(&masquerade);
  168. unregister_netdevice_notifier(&masq_dev_notifier);
  169. unregister_inetaddr_notifier(&masq_inet_notifier);
  170. }
  171. module_init(init);
  172. module_exit(fini);
  173. MODULE_LICENSE("GPL");