1/* This is a module which is used for setting the TOS field of a packet. */ 2#include <linux/module.h> 3#include <linux/skbuff.h> 4#include <linux/ip.h> 5#include <net/checksum.h> 6 7#include <linux/netfilter_ipv4/ip_tables.h> 8#include <linux/netfilter_ipv4/ipt_TOS.h> 9 10static unsigned int 11target(struct sk_buff **pskb, 12 unsigned int hooknum, 13 const struct net_device *in, 14 const struct net_device *out, 15 const void *targinfo, 16 void *userinfo) 17{ 18 struct iphdr *iph = (*pskb)->nh.iph; 19 const struct ipt_tos_target_info *tosinfo = targinfo; 20 21 if ((iph->tos & IPTOS_TOS_MASK) != tosinfo->tos) { 22 u_int16_t diffs[2]; 23 24 /* raw socket (tcpdump) may have clone of incoming 25 skb: don't disturb it --RR */ 26 if (skb_cloned(*pskb) && !(*pskb)->sk) { 27 struct sk_buff *nskb = skb_copy(*pskb, GFP_ATOMIC); 28 if (!nskb) 29 return NF_DROP; 30 kfree_skb(*pskb); 31 *pskb = nskb; 32 iph = (*pskb)->nh.iph; 33 } 34 35 diffs[0] = htons(iph->tos) ^ 0xFFFF; 36 iph->tos = (iph->tos & IPTOS_PREC_MASK) | tosinfo->tos; 37 diffs[1] = htons(iph->tos); 38 iph->check = csum_fold(csum_partial((char *)diffs, 39 sizeof(diffs), 40 iph->check^0xFFFF)); 41 (*pskb)->nfcache |= NFC_ALTERED; 42 } 43 return IPT_CONTINUE; 44} 45 46static int 47checkentry(const char *tablename, 48 const struct ipt_entry *e, 49 void *targinfo, 50 unsigned int targinfosize, 51 unsigned int hook_mask) 52{ 53 const u_int8_t tos = ((struct ipt_tos_target_info *)targinfo)->tos; 54 55 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_tos_target_info))) { 56 printk(KERN_WARNING "TOS: targinfosize %u != %Zu\n", 57 targinfosize, 58 IPT_ALIGN(sizeof(struct ipt_tos_target_info))); 59 return 0; 60 } 61 62 if (strcmp(tablename, "mangle") != 0) { 63 printk(KERN_WARNING "TOS: can only be called from \"mangle\" table, not \"%s\"\n", tablename); 64 return 0; 65 } 66 67 if (tos != IPTOS_LOWDELAY 68 && tos != IPTOS_THROUGHPUT 69 && tos != IPTOS_RELIABILITY 70 && tos != IPTOS_MINCOST 71 && tos != IPTOS_NORMALSVC) { 72 printk(KERN_WARNING "TOS: bad tos value %#x\n", tos); 73 return 0; 74 } 75 76 return 1; 77} 78 79static struct ipt_target ipt_tos_reg 80= { { NULL, NULL }, "TOS", target, checkentry, NULL, THIS_MODULE }; 81 82static int __init init(void) 83{ 84 if (ipt_register_target(&ipt_tos_reg)) 85 return -EINVAL; 86 87 return 0; 88} 89 90static void __exit fini(void) 91{ 92 ipt_unregister_target(&ipt_tos_reg); 93} 94 95module_init(init); 96module_exit(fini); 97MODULE_LICENSE("GPL"); 98