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

Linux/Unix编程

开发平台:

Unix_Linux

  1. #include <linux/types.h>
  2. #include <linux/init.h>
  3. #include <linux/netfilter.h>
  4. #include <linux/ip.h>
  5. #include <linux/icmp.h>
  6. #include <linux/if.h>
  7. #include <linux/netfilter_ipv4/ip_nat.h>
  8. #include <linux/netfilter_ipv4/ip_nat_rule.h>
  9. #include <linux/netfilter_ipv4/ip_nat_protocol.h>
  10. static int
  11. icmp_in_range(const struct ip_conntrack_tuple *tuple,
  12.       enum ip_nat_manip_type maniptype,
  13.       const union ip_conntrack_manip_proto *min,
  14.       const union ip_conntrack_manip_proto *max)
  15. {
  16. return (tuple->src.u.icmp.id >= min->icmp.id
  17. && tuple->src.u.icmp.id <= max->icmp.id);
  18. }
  19. static int
  20. icmp_unique_tuple(struct ip_conntrack_tuple *tuple,
  21.   const struct ip_nat_range *range,
  22.   enum ip_nat_manip_type maniptype,
  23.   const struct ip_conntrack *conntrack)
  24. {
  25. static u_int16_t id = 0;
  26. unsigned int range_size
  27. = (unsigned int)range->max.icmp.id - range->min.icmp.id + 1;
  28. unsigned int i;
  29. /* If no range specified... */
  30. if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED))
  31. range_size = 0xFFFF;
  32. for (i = 0; i < range_size; i++, id++) {
  33. tuple->src.u.icmp.id = range->min.icmp.id + (id % range_size);
  34. if (!ip_nat_used_tuple(tuple, conntrack))
  35. return 1;
  36. }
  37. return 0;
  38. }
  39. static void
  40. icmp_manip_pkt(struct iphdr *iph, size_t len,
  41.        const struct ip_conntrack_manip *manip,
  42.        enum ip_nat_manip_type maniptype)
  43. {
  44. struct icmphdr *hdr = (struct icmphdr *)((u_int32_t *)iph + iph->ihl);
  45. hdr->checksum = ip_nat_cheat_check(hdr->un.echo.id ^ 0xFFFF,
  46.    manip->u.icmp.id,
  47.    hdr->checksum);
  48. hdr->un.echo.id = manip->u.icmp.id;
  49. }
  50. static unsigned int
  51. icmp_print(char *buffer,
  52.    const struct ip_conntrack_tuple *match,
  53.    const struct ip_conntrack_tuple *mask)
  54. {
  55. unsigned int len = 0;
  56. if (mask->src.u.icmp.id)
  57. len += sprintf(buffer + len, "id=%u ",
  58.        ntohs(match->src.u.icmp.id));
  59. if (mask->dst.u.icmp.type)
  60. len += sprintf(buffer + len, "type=%u ",
  61.        ntohs(match->dst.u.icmp.type));
  62. if (mask->dst.u.icmp.code)
  63. len += sprintf(buffer + len, "code=%u ",
  64.        ntohs(match->dst.u.icmp.code));
  65. return len;
  66. }
  67. static unsigned int
  68. icmp_print_range(char *buffer, const struct ip_nat_range *range)
  69. {
  70. if (range->min.icmp.id != 0 || range->max.icmp.id != 0xFFFF)
  71. return sprintf(buffer, "id %u-%u ",
  72.        ntohs(range->min.icmp.id),
  73.        ntohs(range->max.icmp.id));
  74. else return 0;
  75. }
  76. struct ip_nat_protocol ip_nat_protocol_icmp
  77. = { { NULL, NULL }, "ICMP", IPPROTO_ICMP,
  78.     icmp_manip_pkt,
  79.     icmp_in_range,
  80.     icmp_unique_tuple,
  81.     icmp_print,
  82.     icmp_print_range
  83. };