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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* Kernel module to match TCP MSS values. */
  2. #include <linux/module.h>
  3. #include <linux/skbuff.h>
  4. #include <net/tcp.h>
  5. #include <linux/netfilter_ipv4/ipt_tcpmss.h>
  6. #include <linux/netfilter_ipv4/ip_tables.h>
  7. #define TH_SYN 0x02
  8. /* Returns 1 if the mss option is set and matched by the range, 0 otherwise */
  9. static inline int
  10. mssoption_match(u_int16_t min, u_int16_t max,
  11. const struct tcphdr *tcp,
  12. u_int16_t datalen,
  13. int invert,
  14. int *hotdrop)
  15. {
  16. unsigned int i;
  17. const u_int8_t *opt = (u_int8_t *)tcp;
  18. /* If we don't have the whole header, drop packet. */
  19. if (tcp->doff * 4 > datalen) {
  20. *hotdrop = 1;
  21. return 0;
  22. }
  23. for (i = sizeof(struct tcphdr); i < tcp->doff * 4; ) {
  24. if ((opt[i] == TCPOPT_MSS)
  25.     && ((tcp->doff * 4 - i) >= TCPOLEN_MSS)
  26.     && (opt[i+1] == TCPOLEN_MSS)) {
  27. u_int16_t mssval;
  28. mssval = (opt[i+2] << 8) | opt[i+3];
  29. return (mssval >= min && mssval <= max) ^ invert;
  30. }
  31. if (opt[i] < 2) i++;
  32. else i += opt[i+1]?:1;
  33. }
  34. return invert;
  35. }
  36. static int
  37. match(const struct sk_buff *skb,
  38.       const struct net_device *in,
  39.       const struct net_device *out,
  40.       const void *matchinfo,
  41.       int offset,
  42.       const void *hdr,
  43.       u_int16_t datalen,
  44.       int *hotdrop)
  45. {
  46. const struct ipt_tcpmss_match_info *info = matchinfo;
  47. const struct tcphdr *tcph = (void *)skb->nh.iph + skb->nh.iph->ihl*4;
  48. return mssoption_match(info->mss_min, info->mss_max, tcph,
  49.        skb->len - skb->nh.iph->ihl*4,
  50.        info->invert, hotdrop);
  51. }
  52. static inline int find_syn_match(const struct ipt_entry_match *m)
  53. {
  54. const struct ipt_tcp *tcpinfo = (const struct ipt_tcp *)m->data;
  55. if (strcmp(m->u.kernel.match->name, "tcp") == 0
  56.     && (tcpinfo->flg_cmp & TH_SYN)
  57.     && !(tcpinfo->invflags & IPT_TCP_INV_FLAGS))
  58. return 1;
  59. return 0;
  60. }
  61. static int
  62. checkentry(const char *tablename,
  63.            const struct ipt_ip *ip,
  64.            void *matchinfo,
  65.            unsigned int matchsize,
  66.            unsigned int hook_mask)
  67. {
  68. if (matchsize != IPT_ALIGN(sizeof(struct ipt_tcpmss_match_info)))
  69. return 0;
  70. /* Must specify -p tcp */
  71. if (ip->proto != IPPROTO_TCP || (ip->invflags & IPT_INV_PROTO)) {
  72. printk("tcpmss: Only works on TCP packetsn");
  73. return 0;
  74. }
  75. return 1;
  76. }
  77. static struct ipt_match tcpmss_match
  78. = { { NULL, NULL }, "tcpmss", &match, &checkentry, NULL, THIS_MODULE };
  79. static int __init init(void)
  80. {
  81. return ipt_register_match(&tcpmss_match);
  82. }
  83. static void __exit fini(void)
  84. {
  85. ipt_unregister_match(&tcpmss_match);
  86. }
  87. module_init(init);
  88. module_exit(fini);
  89. MODULE_LICENSE("GPL");