ipt_MIRROR.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:4k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.   This is a module which is used for resending packets with inverted src and dst.
  3.   Based on code from: ip_nat_dumb.c,v 1.9 1999/08/20
  4.   and various sources.
  5.   Copyright (C) 2000 Emmanuel Roger <winfield@freegates.be>
  6.   Changes:
  7. 25 Aug 2001 Harald Welte <laforge@gnumonks.org>
  8. - decrement and check TTL if not called from FORWARD hook
  9.   This program is free software; you can redistribute it and/or modify it
  10.   under the terms of the GNU General Public License as published by the
  11.   Free Software Foundation; either version 2 of the License, or (at your
  12.   option) any later version.
  13.   This program is distributed in the hope that it will be useful, but
  14.   WITHOUT ANY WARRANTY; without even the implied warranty of
  15.   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.   General Public License for more details.
  17.   You should have received a copy of the GNU General Public License
  18.   along with this program; if not, write to the Free Software Foundation,
  19.   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  20.  */
  21. #include <linux/module.h>
  22. #include <linux/skbuff.h>
  23. #include <linux/ip.h>
  24. #include <net/ip.h>
  25. #include <net/icmp.h>
  26. #include <linux/netfilter_ipv4/ip_tables.h>
  27. #include <linux/netdevice.h>
  28. #include <linux/route.h>
  29. struct in_device;
  30. #include <net/route.h>
  31. #if 0
  32. #define DEBUGP printk
  33. #else
  34. #define DEBUGP(format, args...)
  35. #endif
  36. static int route_mirror(struct sk_buff *skb)
  37. {
  38.         struct iphdr *iph = skb->nh.iph;
  39. struct rtable *rt;
  40. /* Backwards */
  41. if (ip_route_output(&rt, iph->saddr, iph->daddr,
  42.     RT_TOS(iph->tos) | RTO_CONN,
  43.     0)) {
  44. return 0;
  45. }
  46. /* check if the interface we are leaving by is the same as the
  47.            one we arrived on */
  48. if (skb->dev == rt->u.dst.dev) {
  49. /* Drop old route. */
  50. dst_release(skb->dst);
  51. skb->dst = &rt->u.dst;
  52. return 1;
  53. }
  54. return 0;
  55. }
  56. static void
  57. ip_rewrite(struct sk_buff *skb)
  58. {
  59. struct iphdr *iph = skb->nh.iph;
  60. u32 odaddr = iph->saddr;
  61. u32 osaddr = iph->daddr;
  62. skb->nfcache |= NFC_ALTERED;
  63. /* Rewrite IP header */
  64. iph->daddr = odaddr;
  65. iph->saddr = osaddr;
  66. }
  67. /* Stolen from ip_finish_output2 */
  68. static void ip_direct_send(struct sk_buff *skb)
  69. {
  70. struct dst_entry *dst = skb->dst;
  71. struct hh_cache *hh = dst->hh;
  72. if (hh) {
  73. read_lock_bh(&hh->hh_lock);
  74.    memcpy(skb->data - 16, hh->hh_data, 16);
  75. read_unlock_bh(&hh->hh_lock);
  76.         skb_push(skb, hh->hh_len);
  77. hh->hh_output(skb);
  78. } else if (dst->neighbour)
  79. dst->neighbour->output(skb);
  80. else {
  81. printk(KERN_DEBUG "khm in MIRRORn");
  82. kfree_skb(skb);
  83. }
  84. }
  85. static unsigned int ipt_mirror_target(struct sk_buff **pskb,
  86.       unsigned int hooknum,
  87.       const struct net_device *in,
  88.       const struct net_device *out,
  89.       const void *targinfo,
  90.       void *userinfo)
  91. {
  92. if (((*pskb)->dst != NULL) &&
  93.     route_mirror(*pskb)) {
  94. ip_rewrite(*pskb);
  95. /* If we are not at FORWARD hook (INPUT/PREROUTING),
  96.  * the TTL isn't decreased by the IP stack */
  97. if (hooknum != NF_IP_FORWARD) {
  98. struct iphdr *iph = (*pskb)->nh.iph;
  99. if (iph->ttl <= 1) {
  100. /* this will traverse normal stack, and 
  101.  * thus call conntrack on the icmp packet */
  102. icmp_send(*pskb, ICMP_TIME_EXCEEDED, 
  103.   ICMP_EXC_TTL, 0);
  104. return NF_DROP;
  105. }
  106. ip_decrease_ttl(iph);
  107. }
  108. /* Don't let conntrack code see this packet:
  109.                    it will think we are starting a new
  110.                    connection! --RR */
  111. ip_direct_send(*pskb);
  112. return NF_STOLEN;
  113. }
  114. return NF_DROP;
  115. }
  116. static int ipt_mirror_checkentry(const char *tablename,
  117.  const struct ipt_entry *e,
  118.  void *targinfo,
  119.  unsigned int targinfosize,
  120.  unsigned int hook_mask)
  121. {
  122. /* Only on INPUT, FORWARD or PRE_ROUTING, otherwise loop danger. */
  123. if (hook_mask & ~((1 << NF_IP_PRE_ROUTING)
  124.   | (1 << NF_IP_FORWARD)
  125.   | (1 << NF_IP_LOCAL_IN))) {
  126. DEBUGP("MIRROR: bad hookn");
  127. return 0;
  128. }
  129. if (targinfosize != IPT_ALIGN(0)) {
  130. DEBUGP("MIRROR: targinfosize %u != 0n", targinfosize);
  131. return 0;
  132. }
  133. return 1;
  134. }
  135. static struct ipt_target ipt_mirror_reg
  136. = { { NULL, NULL }, "MIRROR", ipt_mirror_target, ipt_mirror_checkentry, NULL,
  137.     THIS_MODULE };
  138. static int __init init(void)
  139. {
  140. return ipt_register_target(&ipt_mirror_reg);
  141. }
  142. static void __exit fini(void)
  143. {
  144. ipt_unregister_target(&ipt_mirror_reg);
  145. }
  146. module_init(init);
  147. module_exit(fini);
  148. MODULE_LICENSE("GPL");