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

Linux/Unix编程

开发平台:

Unix_Linux

  1. #include <linux/types.h>
  2. #include <linux/sched.h>
  3. #include <linux/timer.h>
  4. #include <linux/netfilter.h>
  5. #include <linux/in.h>
  6. #include <linux/icmp.h>
  7. #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
  8. #define ICMP_TIMEOUT (30*HZ)
  9. #if 0
  10. #define DEBUGP printk
  11. #else
  12. #define DEBUGP(format, args...)
  13. #endif
  14. static int icmp_pkt_to_tuple(const void *datah, size_t datalen,
  15.      struct ip_conntrack_tuple *tuple)
  16. {
  17. const struct icmphdr *hdr = datah;
  18. tuple->dst.u.icmp.type = hdr->type;
  19. tuple->src.u.icmp.id = hdr->un.echo.id;
  20. tuple->dst.u.icmp.code = hdr->code;
  21. return 1;
  22. }
  23. static int icmp_invert_tuple(struct ip_conntrack_tuple *tuple,
  24.      const struct ip_conntrack_tuple *orig)
  25. {
  26. /* Add 1; spaces filled with 0. */
  27. static u_int8_t invmap[]
  28. = { [ICMP_ECHO] = ICMP_ECHOREPLY + 1,
  29.     [ICMP_ECHOREPLY] = ICMP_ECHO + 1,
  30.     [ICMP_TIMESTAMP] = ICMP_TIMESTAMPREPLY + 1,
  31.     [ICMP_TIMESTAMPREPLY] = ICMP_TIMESTAMP + 1,
  32.     [ICMP_INFO_REQUEST] = ICMP_INFO_REPLY + 1,
  33.     [ICMP_INFO_REPLY] = ICMP_INFO_REQUEST + 1,
  34.     [ICMP_ADDRESS] = ICMP_ADDRESSREPLY + 1,
  35.     [ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1};
  36. if (orig->dst.u.icmp.type >= sizeof(invmap)
  37.     || !invmap[orig->dst.u.icmp.type])
  38. return 0;
  39. tuple->src.u.icmp.id = orig->src.u.icmp.id;
  40. tuple->dst.u.icmp.type = invmap[orig->dst.u.icmp.type] - 1;
  41. tuple->dst.u.icmp.code = orig->dst.u.icmp.code;
  42. return 1;
  43. }
  44. /* Print out the per-protocol part of the tuple. */
  45. static unsigned int icmp_print_tuple(char *buffer,
  46.      const struct ip_conntrack_tuple *tuple)
  47. {
  48. return sprintf(buffer, "type=%u code=%u id=%u ",
  49.        tuple->dst.u.icmp.type,
  50.        tuple->dst.u.icmp.code,
  51.        ntohs(tuple->src.u.icmp.id));
  52. }
  53. /* Print out the private part of the conntrack. */
  54. static unsigned int icmp_print_conntrack(char *buffer,
  55.      const struct ip_conntrack *conntrack)
  56. {
  57. return 0;
  58. }
  59. /* Returns verdict for packet, or -1 for invalid. */
  60. static int icmp_packet(struct ip_conntrack *ct,
  61.        struct iphdr *iph, size_t len,
  62.        enum ip_conntrack_info ctinfo)
  63. {
  64. /* Try to delete connection immediately after all replies:
  65.            won't actually vanish as we still have skb, and del_timer
  66.            means this will only run once even if count hits zero twice
  67.            (theoretically possible with SMP) */
  68. if (CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY) {
  69. if (atomic_dec_and_test(&ct->proto.icmp.count)
  70.     && del_timer(&ct->timeout))
  71. ct->timeout.function((unsigned long)ct);
  72. } else {
  73. atomic_inc(&ct->proto.icmp.count);
  74. ip_ct_refresh(ct, ICMP_TIMEOUT);
  75. }
  76. return NF_ACCEPT;
  77. }
  78. /* Called when a new connection for this protocol found. */
  79. static int icmp_new(struct ip_conntrack *conntrack,
  80.     struct iphdr *iph, size_t len)
  81. {
  82. static u_int8_t valid_new[]
  83. = { [ICMP_ECHO] = 1,
  84.     [ICMP_TIMESTAMP] = 1,
  85.     [ICMP_INFO_REQUEST] = 1,
  86.     [ICMP_ADDRESS] = 1 };
  87. if (conntrack->tuplehash[0].tuple.dst.u.icmp.type >= sizeof(valid_new)
  88.     || !valid_new[conntrack->tuplehash[0].tuple.dst.u.icmp.type]) {
  89. /* Can't create a new ICMP `conn' with this. */
  90. DEBUGP("icmp: can't create new conn with type %un",
  91.        conntrack->tuplehash[0].tuple.dst.u.icmp.type);
  92. DUMP_TUPLE(&conntrack->tuplehash[0].tuple);
  93. return 0;
  94. }
  95. atomic_set(&conntrack->proto.icmp.count, 0);
  96. return 1;
  97. }
  98. struct ip_conntrack_protocol ip_conntrack_protocol_icmp
  99. = { { NULL, NULL }, IPPROTO_ICMP, "icmp",
  100.     icmp_pkt_to_tuple, icmp_invert_tuple, icmp_print_tuple,
  101.     icmp_print_conntrack, icmp_packet, icmp_new, NULL, NULL, NULL };