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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* iptables module for setting the IPv4 DSCP field, Version 1.8
  2.  *
  3.  * (C) 2002 by Harald Welte <laforge@gnumonks.org>
  4.  * based on ipt_FTOS.c (C) 2000 by Matthew G. Marsh <mgm@paktronix.com>
  5.  * This software is distributed under GNU GPL v2, 1991
  6.  * 
  7.  * See RFC2474 for a description of the DSCP field within the IP Header.
  8.  *
  9.  * ipt_DSCP.c,v 1.8 2002/08/06 18:41:57 laforge Exp
  10. */
  11. #include <linux/module.h>
  12. #include <linux/skbuff.h>
  13. #include <linux/ip.h>
  14. #include <net/checksum.h>
  15. #include <linux/netfilter_ipv4/ip_tables.h>
  16. #include <linux/netfilter_ipv4/ipt_DSCP.h>
  17. MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
  18. MODULE_DESCRIPTION("IP tables DSCP modification module");
  19. MODULE_LICENSE("GPL");
  20. static unsigned int
  21. target(struct sk_buff **pskb,
  22.        unsigned int hooknum,
  23.        const struct net_device *in,
  24.        const struct net_device *out,
  25.        const void *targinfo,
  26.        void *userinfo)
  27. {
  28. struct iphdr *iph = (*pskb)->nh.iph;
  29. const struct ipt_DSCP_info *dinfo = targinfo;
  30. u_int8_t sh_dscp = ((dinfo->dscp << IPT_DSCP_SHIFT) & IPT_DSCP_MASK);
  31. if ((iph->tos & IPT_DSCP_MASK) != sh_dscp) {
  32. u_int16_t diffs[2];
  33. /* raw socket (tcpdump) may have clone of incoming
  34.  * skb: don't disturb it --RR */
  35. if (skb_cloned(*pskb) && !(*pskb)->sk) {
  36. struct sk_buff *nskb = skb_copy(*pskb, GFP_ATOMIC);
  37. if (!nskb)
  38. return NF_DROP;
  39. kfree_skb(*pskb);
  40. *pskb = nskb;
  41. iph = (*pskb)->nh.iph;
  42. }
  43. diffs[0] = htons(iph->tos) ^ 0xFFFF;
  44. iph->tos = (iph->tos & ~IPT_DSCP_MASK) | sh_dscp;
  45. diffs[1] = htons(iph->tos);
  46. iph->check = csum_fold(csum_partial((char *)diffs,
  47.                                     sizeof(diffs),
  48.                                     iph->check^0xFFFF));
  49. (*pskb)->nfcache |= NFC_ALTERED;
  50. }
  51. return IPT_CONTINUE;
  52. }
  53. static int
  54. checkentry(const char *tablename,
  55.    const struct ipt_entry *e,
  56.            void *targinfo,
  57.            unsigned int targinfosize,
  58.            unsigned int hook_mask)
  59. {
  60. const u_int8_t dscp = ((struct ipt_DSCP_info *)targinfo)->dscp;
  61. if (targinfosize != IPT_ALIGN(sizeof(struct ipt_DSCP_info))) {
  62. printk(KERN_WARNING "DSCP: targinfosize %u != %Zun",
  63.        targinfosize,
  64.        IPT_ALIGN(sizeof(struct ipt_DSCP_info)));
  65. return 0;
  66. }
  67. if (strcmp(tablename, "mangle") != 0) {
  68. printk(KERN_WARNING "DSCP: can only be called from "mangle" table, not "%s"n", tablename);
  69. return 0;
  70. }
  71. if ((dscp > IPT_DSCP_MAX)) {
  72. printk(KERN_WARNING "DSCP: dscp %x out of rangen", dscp);
  73. return 0;
  74. }
  75. return 1;
  76. }
  77. static struct ipt_target ipt_dscp_reg
  78. = { { NULL, NULL }, "DSCP", target, checkentry, NULL, THIS_MODULE };
  79. static int __init init(void)
  80. {
  81. if (ipt_register_target(&ipt_dscp_reg))
  82. return -EINVAL;
  83. return 0;
  84. }
  85. static void __exit fini(void)
  86. {
  87. ipt_unregister_target(&ipt_dscp_reg);
  88. }
  89. module_init(init);
  90. module_exit(fini);