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.30-rc4 210 lines 5.2 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 xt_target_param *par) 33{ 34 const struct xt_DSCP_info *dinfo = par->targinfo; 35 u_int8_t dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT; 36 37 if (dscp != dinfo->dscp) { 38 if (!skb_make_writable(skb, sizeof(struct iphdr))) 39 return NF_DROP; 40 41 ipv4_change_dsfield(ip_hdr(skb), (__u8)(~XT_DSCP_MASK), 42 dinfo->dscp << XT_DSCP_SHIFT); 43 44 } 45 return XT_CONTINUE; 46} 47 48static unsigned int 49dscp_tg6(struct sk_buff *skb, const struct xt_target_param *par) 50{ 51 const struct xt_DSCP_info *dinfo = par->targinfo; 52 u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> XT_DSCP_SHIFT; 53 54 if (dscp != dinfo->dscp) { 55 if (!skb_make_writable(skb, sizeof(struct ipv6hdr))) 56 return NF_DROP; 57 58 ipv6_change_dsfield(ipv6_hdr(skb), (__u8)(~XT_DSCP_MASK), 59 dinfo->dscp << XT_DSCP_SHIFT); 60 } 61 return XT_CONTINUE; 62} 63 64static bool dscp_tg_check(const struct xt_tgchk_param *par) 65{ 66 const struct xt_DSCP_info *info = par->targinfo; 67 68 if (info->dscp > XT_DSCP_MAX) { 69 printk(KERN_WARNING "DSCP: dscp %x out of range\n", info->dscp); 70 return false; 71 } 72 return true; 73} 74 75static unsigned int 76tos_tg_v0(struct sk_buff *skb, const struct xt_target_param *par) 77{ 78 const struct ipt_tos_target_info *info = par->targinfo; 79 struct iphdr *iph = ip_hdr(skb); 80 u_int8_t oldtos; 81 82 if ((iph->tos & IPTOS_TOS_MASK) != info->tos) { 83 if (!skb_make_writable(skb, sizeof(struct iphdr))) 84 return NF_DROP; 85 86 iph = ip_hdr(skb); 87 oldtos = iph->tos; 88 iph->tos = (iph->tos & IPTOS_PREC_MASK) | info->tos; 89 csum_replace2(&iph->check, htons(oldtos), htons(iph->tos)); 90 } 91 92 return XT_CONTINUE; 93} 94 95static bool tos_tg_check_v0(const struct xt_tgchk_param *par) 96{ 97 const struct ipt_tos_target_info *info = par->targinfo; 98 const uint8_t tos = info->tos; 99 100 if (tos != IPTOS_LOWDELAY && tos != IPTOS_THROUGHPUT && 101 tos != IPTOS_RELIABILITY && tos != IPTOS_MINCOST && 102 tos != IPTOS_NORMALSVC) { 103 printk(KERN_WARNING "TOS: bad tos value %#x\n", tos); 104 return false; 105 } 106 107 return true; 108} 109 110static unsigned int 111tos_tg(struct sk_buff *skb, const struct xt_target_param *par) 112{ 113 const struct xt_tos_target_info *info = par->targinfo; 114 struct iphdr *iph = ip_hdr(skb); 115 u_int8_t orig, nv; 116 117 orig = ipv4_get_dsfield(iph); 118 nv = (orig & ~info->tos_mask) ^ info->tos_value; 119 120 if (orig != nv) { 121 if (!skb_make_writable(skb, sizeof(struct iphdr))) 122 return NF_DROP; 123 iph = ip_hdr(skb); 124 ipv4_change_dsfield(iph, 0, nv); 125 } 126 127 return XT_CONTINUE; 128} 129 130static unsigned int 131tos_tg6(struct sk_buff *skb, const struct xt_target_param *par) 132{ 133 const struct xt_tos_target_info *info = par->targinfo; 134 struct ipv6hdr *iph = ipv6_hdr(skb); 135 u_int8_t orig, nv; 136 137 orig = ipv6_get_dsfield(iph); 138 nv = (orig & info->tos_mask) ^ info->tos_value; 139 140 if (orig != nv) { 141 if (!skb_make_writable(skb, sizeof(struct iphdr))) 142 return NF_DROP; 143 iph = ipv6_hdr(skb); 144 ipv6_change_dsfield(iph, 0, nv); 145 } 146 147 return XT_CONTINUE; 148} 149 150static struct xt_target dscp_tg_reg[] __read_mostly = { 151 { 152 .name = "DSCP", 153 .family = NFPROTO_IPV4, 154 .checkentry = dscp_tg_check, 155 .target = dscp_tg, 156 .targetsize = sizeof(struct xt_DSCP_info), 157 .table = "mangle", 158 .me = THIS_MODULE, 159 }, 160 { 161 .name = "DSCP", 162 .family = NFPROTO_IPV6, 163 .checkentry = dscp_tg_check, 164 .target = dscp_tg6, 165 .targetsize = sizeof(struct xt_DSCP_info), 166 .table = "mangle", 167 .me = THIS_MODULE, 168 }, 169 { 170 .name = "TOS", 171 .revision = 0, 172 .family = NFPROTO_IPV4, 173 .table = "mangle", 174 .target = tos_tg_v0, 175 .targetsize = sizeof(struct ipt_tos_target_info), 176 .checkentry = tos_tg_check_v0, 177 .me = THIS_MODULE, 178 }, 179 { 180 .name = "TOS", 181 .revision = 1, 182 .family = NFPROTO_IPV4, 183 .table = "mangle", 184 .target = tos_tg, 185 .targetsize = sizeof(struct xt_tos_target_info), 186 .me = THIS_MODULE, 187 }, 188 { 189 .name = "TOS", 190 .revision = 1, 191 .family = NFPROTO_IPV6, 192 .table = "mangle", 193 .target = tos_tg6, 194 .targetsize = sizeof(struct xt_tos_target_info), 195 .me = THIS_MODULE, 196 }, 197}; 198 199static int __init dscp_tg_init(void) 200{ 201 return xt_register_targets(dscp_tg_reg, ARRAY_SIZE(dscp_tg_reg)); 202} 203 204static void __exit dscp_tg_exit(void) 205{ 206 xt_unregister_targets(dscp_tg_reg, ARRAY_SIZE(dscp_tg_reg)); 207} 208 209module_init(dscp_tg_init); 210module_exit(dscp_tg_exit);