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

[NETFILTER]: IPv6 capable xt_TOS v1 target

Extends the xt_DSCP target by xt_TOS v1 to add support for selectively
setting and flipping any bit in the IPv4 TOS and IPv6 Priority fields.
(ipt_TOS and xt_DSCP only accepted a limited range of possible
values.)

Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Jan Engelhardt and committed by
David S. Miller
5c350e5a f1095ab5

+69 -1
+5
include/linux/netfilter/xt_DSCP.h
··· 17 17 u_int8_t dscp; 18 18 }; 19 19 20 + struct xt_tos_target_info { 21 + u_int8_t tos_value; 22 + u_int8_t tos_mask; 23 + }; 24 + 20 25 #endif /* _XT_DSCP_TARGET_H */
+1 -1
net/netfilter/Kconfig
··· 304 304 305 305 It also adds the "TOS" target, which allows you to create rules in 306 306 the "mangle" table which alter the Type Of Service field of an IPv4 307 - packet prior to routing. 307 + or the Priority field of an IPv6 packet, prior to routing. 308 308 309 309 To compile it as a module, choose M here. If unsure, say N. 310 310
+63
net/netfilter/xt_DSCP.c
··· 26 26 MODULE_ALIAS("ipt_DSCP"); 27 27 MODULE_ALIAS("ip6t_DSCP"); 28 28 MODULE_ALIAS("ipt_TOS"); 29 + MODULE_ALIAS("ip6t_TOS"); 29 30 30 31 static unsigned int 31 32 dscp_tg(struct sk_buff *skb, const struct net_device *in, ··· 118 117 return true; 119 118 } 120 119 120 + static unsigned int 121 + tos_tg(struct sk_buff *skb, const struct net_device *in, 122 + const struct net_device *out, unsigned int hooknum, 123 + const struct xt_target *target, const void *targinfo) 124 + { 125 + const struct xt_tos_target_info *info = targinfo; 126 + struct iphdr *iph = ip_hdr(skb); 127 + u_int8_t orig, nv; 128 + 129 + orig = ipv4_get_dsfield(iph); 130 + nv = (orig & info->tos_mask) ^ info->tos_value; 131 + 132 + if (orig != nv) { 133 + if (!skb_make_writable(skb, sizeof(struct iphdr))) 134 + return NF_DROP; 135 + iph = ip_hdr(skb); 136 + ipv4_change_dsfield(iph, ~0, nv); 137 + } 138 + 139 + return XT_CONTINUE; 140 + } 141 + 142 + static unsigned int 143 + tos_tg6(struct sk_buff *skb, const struct net_device *in, 144 + const struct net_device *out, unsigned int hooknum, 145 + const struct xt_target *target, const void *targinfo) 146 + { 147 + const struct xt_tos_target_info *info = targinfo; 148 + struct ipv6hdr *iph = ipv6_hdr(skb); 149 + u_int8_t orig, nv; 150 + 151 + orig = ipv6_get_dsfield(iph); 152 + nv = (orig & info->tos_mask) ^ info->tos_value; 153 + 154 + if (orig != nv) { 155 + if (!skb_make_writable(skb, sizeof(struct iphdr))) 156 + return NF_DROP; 157 + iph = ipv6_hdr(skb); 158 + ipv6_change_dsfield(iph, ~0, nv); 159 + } 160 + 161 + return XT_CONTINUE; 162 + } 163 + 121 164 static struct xt_target dscp_tg_reg[] __read_mostly = { 122 165 { 123 166 .name = "DSCP", ··· 189 144 .target = tos_tg_v0, 190 145 .targetsize = sizeof(struct ipt_tos_target_info), 191 146 .checkentry = tos_tg_check_v0, 147 + .me = THIS_MODULE, 148 + }, 149 + { 150 + .name = "TOS", 151 + .revision = 1, 152 + .family = AF_INET, 153 + .table = "mangle", 154 + .target = tos_tg, 155 + .targetsize = sizeof(struct xt_tos_target_info), 156 + .me = THIS_MODULE, 157 + }, 158 + { 159 + .name = "TOS", 160 + .revision = 1, 161 + .family = AF_INET6, 162 + .table = "mangle", 163 + .target = tos_tg6, 164 + .targetsize = sizeof(struct xt_tos_target_info), 192 165 .me = THIS_MODULE, 193 166 }, 194 167 };