Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.26-rc8 225 lines 5.9 kB view raw
1/* x_tables module for setting the IPv4/IPv6 DSCP field, Version 1.8 2 * 3 * (C) 2002 by Harald Welte <laforge@netfilter.org> 4 * based on ipt_FTOS.c (C) 2000 by Matthew G. Marsh <mgm@paktronix.com> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 * 10 * See RFC2474 for a description of the DSCP field within the IP Header. 11*/ 12 13#include <linux/module.h> 14#include <linux/skbuff.h> 15#include <linux/ip.h> 16#include <linux/ipv6.h> 17#include <net/dsfield.h> 18 19#include <linux/netfilter/x_tables.h> 20#include <linux/netfilter/xt_DSCP.h> 21#include <linux/netfilter_ipv4/ipt_TOS.h> 22 23MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); 24MODULE_DESCRIPTION("Xtables: DSCP/TOS field modification"); 25MODULE_LICENSE("GPL"); 26MODULE_ALIAS("ipt_DSCP"); 27MODULE_ALIAS("ip6t_DSCP"); 28MODULE_ALIAS("ipt_TOS"); 29MODULE_ALIAS("ip6t_TOS"); 30 31static unsigned int 32dscp_tg(struct sk_buff *skb, const struct net_device *in, 33 const struct net_device *out, unsigned int hooknum, 34 const struct xt_target *target, const void *targinfo) 35{ 36 const struct xt_DSCP_info *dinfo = targinfo; 37 u_int8_t dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT; 38 39 if (dscp != dinfo->dscp) { 40 if (!skb_make_writable(skb, sizeof(struct iphdr))) 41 return NF_DROP; 42 43 ipv4_change_dsfield(ip_hdr(skb), (__u8)(~XT_DSCP_MASK), 44 dinfo->dscp << XT_DSCP_SHIFT); 45 46 } 47 return XT_CONTINUE; 48} 49 50static unsigned int 51dscp_tg6(struct sk_buff *skb, const struct net_device *in, 52 const struct net_device *out, unsigned int hooknum, 53 const struct xt_target *target, const void *targinfo) 54{ 55 const struct xt_DSCP_info *dinfo = targinfo; 56 u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> XT_DSCP_SHIFT; 57 58 if (dscp != dinfo->dscp) { 59 if (!skb_make_writable(skb, sizeof(struct ipv6hdr))) 60 return NF_DROP; 61 62 ipv6_change_dsfield(ipv6_hdr(skb), (__u8)(~XT_DSCP_MASK), 63 dinfo->dscp << XT_DSCP_SHIFT); 64 } 65 return XT_CONTINUE; 66} 67 68static bool 69dscp_tg_check(const char *tablename, const void *e_void, 70 const struct xt_target *target, void *targinfo, 71 unsigned int hook_mask) 72{ 73 const u_int8_t dscp = ((struct xt_DSCP_info *)targinfo)->dscp; 74 75 if (dscp > XT_DSCP_MAX) { 76 printk(KERN_WARNING "DSCP: dscp %x out of range\n", dscp); 77 return false; 78 } 79 return true; 80} 81 82static unsigned int 83tos_tg_v0(struct sk_buff *skb, const struct net_device *in, 84 const struct net_device *out, unsigned int hooknum, 85 const struct xt_target *target, const void *targinfo) 86{ 87 const struct ipt_tos_target_info *info = targinfo; 88 struct iphdr *iph = ip_hdr(skb); 89 u_int8_t oldtos; 90 91 if ((iph->tos & IPTOS_TOS_MASK) != info->tos) { 92 if (!skb_make_writable(skb, sizeof(struct iphdr))) 93 return NF_DROP; 94 95 iph = ip_hdr(skb); 96 oldtos = iph->tos; 97 iph->tos = (iph->tos & IPTOS_PREC_MASK) | info->tos; 98 csum_replace2(&iph->check, htons(oldtos), htons(iph->tos)); 99 } 100 101 return XT_CONTINUE; 102} 103 104static bool 105tos_tg_check_v0(const char *tablename, const void *e_void, 106 const struct xt_target *target, void *targinfo, 107 unsigned int hook_mask) 108{ 109 const u_int8_t tos = ((struct ipt_tos_target_info *)targinfo)->tos; 110 111 if (tos != IPTOS_LOWDELAY && tos != IPTOS_THROUGHPUT && 112 tos != IPTOS_RELIABILITY && tos != IPTOS_MINCOST && 113 tos != IPTOS_NORMALSVC) { 114 printk(KERN_WARNING "TOS: bad tos value %#x\n", tos); 115 return false; 116 } 117 118 return true; 119} 120 121static unsigned int 122tos_tg(struct sk_buff *skb, const struct net_device *in, 123 const struct net_device *out, unsigned int hooknum, 124 const struct xt_target *target, const void *targinfo) 125{ 126 const struct xt_tos_target_info *info = targinfo; 127 struct iphdr *iph = ip_hdr(skb); 128 u_int8_t orig, nv; 129 130 orig = ipv4_get_dsfield(iph); 131 nv = (orig & ~info->tos_mask) ^ info->tos_value; 132 133 if (orig != nv) { 134 if (!skb_make_writable(skb, sizeof(struct iphdr))) 135 return NF_DROP; 136 iph = ip_hdr(skb); 137 ipv4_change_dsfield(iph, 0, nv); 138 } 139 140 return XT_CONTINUE; 141} 142 143static unsigned int 144tos_tg6(struct sk_buff *skb, const struct net_device *in, 145 const struct net_device *out, unsigned int hooknum, 146 const struct xt_target *target, const void *targinfo) 147{ 148 const struct xt_tos_target_info *info = targinfo; 149 struct ipv6hdr *iph = ipv6_hdr(skb); 150 u_int8_t orig, nv; 151 152 orig = ipv6_get_dsfield(iph); 153 nv = (orig & info->tos_mask) ^ info->tos_value; 154 155 if (orig != nv) { 156 if (!skb_make_writable(skb, sizeof(struct iphdr))) 157 return NF_DROP; 158 iph = ipv6_hdr(skb); 159 ipv6_change_dsfield(iph, 0, nv); 160 } 161 162 return XT_CONTINUE; 163} 164 165static struct xt_target dscp_tg_reg[] __read_mostly = { 166 { 167 .name = "DSCP", 168 .family = AF_INET, 169 .checkentry = dscp_tg_check, 170 .target = dscp_tg, 171 .targetsize = sizeof(struct xt_DSCP_info), 172 .table = "mangle", 173 .me = THIS_MODULE, 174 }, 175 { 176 .name = "DSCP", 177 .family = AF_INET6, 178 .checkentry = dscp_tg_check, 179 .target = dscp_tg6, 180 .targetsize = sizeof(struct xt_DSCP_info), 181 .table = "mangle", 182 .me = THIS_MODULE, 183 }, 184 { 185 .name = "TOS", 186 .revision = 0, 187 .family = AF_INET, 188 .table = "mangle", 189 .target = tos_tg_v0, 190 .targetsize = sizeof(struct ipt_tos_target_info), 191 .checkentry = tos_tg_check_v0, 192 .me = THIS_MODULE, 193 }, 194 { 195 .name = "TOS", 196 .revision = 1, 197 .family = AF_INET, 198 .table = "mangle", 199 .target = tos_tg, 200 .targetsize = sizeof(struct xt_tos_target_info), 201 .me = THIS_MODULE, 202 }, 203 { 204 .name = "TOS", 205 .revision = 1, 206 .family = AF_INET6, 207 .table = "mangle", 208 .target = tos_tg6, 209 .targetsize = sizeof(struct xt_tos_target_info), 210 .me = THIS_MODULE, 211 }, 212}; 213 214static int __init dscp_tg_init(void) 215{ 216 return xt_register_targets(dscp_tg_reg, ARRAY_SIZE(dscp_tg_reg)); 217} 218 219static void __exit dscp_tg_exit(void) 220{ 221 xt_unregister_targets(dscp_tg_reg, ARRAY_SIZE(dscp_tg_reg)); 222} 223 224module_init(dscp_tg_init); 225module_exit(dscp_tg_exit);