19ba1627617d396135a4d679542a3623d5819e628Yasuyuki Kozakai/* IP tables module for matching the value of the IPv4/IPv6 DSCP field
29ba1627617d396135a4d679542a3623d5819e628Yasuyuki Kozakai *
39ba1627617d396135a4d679542a3623d5819e628Yasuyuki Kozakai * (C) 2002 by Harald Welte <laforge@netfilter.org>
49ba1627617d396135a4d679542a3623d5819e628Yasuyuki Kozakai *
59ba1627617d396135a4d679542a3623d5819e628Yasuyuki Kozakai * This program is free software; you can redistribute it and/or modify
69ba1627617d396135a4d679542a3623d5819e628Yasuyuki Kozakai * it under the terms of the GNU General Public License version 2 as
79ba1627617d396135a4d679542a3623d5819e628Yasuyuki Kozakai * published by the Free Software Foundation.
89ba1627617d396135a4d679542a3623d5819e628Yasuyuki Kozakai */
98bee4bad03c5b601bd6cea123c31025680587cccJan Engelhardt#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
109ba1627617d396135a4d679542a3623d5819e628Yasuyuki Kozakai#include <linux/module.h>
119ba1627617d396135a4d679542a3623d5819e628Yasuyuki Kozakai#include <linux/skbuff.h>
129ba1627617d396135a4d679542a3623d5819e628Yasuyuki Kozakai#include <linux/ip.h>
139ba1627617d396135a4d679542a3623d5819e628Yasuyuki Kozakai#include <linux/ipv6.h>
149ba1627617d396135a4d679542a3623d5819e628Yasuyuki Kozakai#include <net/dsfield.h>
159ba1627617d396135a4d679542a3623d5819e628Yasuyuki Kozakai
169ba1627617d396135a4d679542a3623d5819e628Yasuyuki Kozakai#include <linux/netfilter/x_tables.h>
17c3b33e6a2cdefba38d83442ebae2ee42e853ea51Jan Engelhardt#include <linux/netfilter/xt_dscp.h>
189ba1627617d396135a4d679542a3623d5819e628Yasuyuki Kozakai
199ba1627617d396135a4d679542a3623d5819e628Yasuyuki KozakaiMODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
202ae15b64e6a1608c840c60df38e8e5eef7b2b8c3Jan EngelhardtMODULE_DESCRIPTION("Xtables: DSCP/TOS field match");
219ba1627617d396135a4d679542a3623d5819e628Yasuyuki KozakaiMODULE_LICENSE("GPL");
229ba1627617d396135a4d679542a3623d5819e628Yasuyuki KozakaiMODULE_ALIAS("ipt_dscp");
239ba1627617d396135a4d679542a3623d5819e628Yasuyuki KozakaiMODULE_ALIAS("ip6t_dscp");
24c3b33e6a2cdefba38d83442ebae2ee42e853ea51Jan EngelhardtMODULE_ALIAS("ipt_tos");
25f1095ab51d4297d4a84b64a65c71054183a73486Jan EngelhardtMODULE_ALIAS("ip6t_tos");
269ba1627617d396135a4d679542a3623d5819e628Yasuyuki Kozakai
27d3c5ee6d545b5372fd525ebe16988a5b6efeceb0Jan Engelhardtstatic bool
2862fc8051083a334578c3f4b3488808f210b4565fJan Engelhardtdscp_mt(const struct sk_buff *skb, struct xt_action_param *par)
299ba1627617d396135a4d679542a3623d5819e628Yasuyuki Kozakai{
30f7108a20dee44e5bb037f9e48f6a207b42e6ae1cJan Engelhardt	const struct xt_dscp_info *info = par->matchinfo;
311d93a9cbad608f6398ba6c5b588c504ccd35a2caJan Engelhardt	u_int8_t dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT;
321d93a9cbad608f6398ba6c5b588c504ccd35a2caJan Engelhardt
331d93a9cbad608f6398ba6c5b588c504ccd35a2caJan Engelhardt	return (dscp == info->dscp) ^ !!info->invert;
341d93a9cbad608f6398ba6c5b588c504ccd35a2caJan Engelhardt}
351d93a9cbad608f6398ba6c5b588c504ccd35a2caJan Engelhardt
36d3c5ee6d545b5372fd525ebe16988a5b6efeceb0Jan Engelhardtstatic bool
3762fc8051083a334578c3f4b3488808f210b4565fJan Engelhardtdscp_mt6(const struct sk_buff *skb, struct xt_action_param *par)
381d93a9cbad608f6398ba6c5b588c504ccd35a2caJan Engelhardt{
39f7108a20dee44e5bb037f9e48f6a207b42e6ae1cJan Engelhardt	const struct xt_dscp_info *info = par->matchinfo;
400660e03f6b18f19b6bbafe7583265a51b90daf36Arnaldo Carvalho de Melo	u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> XT_DSCP_SHIFT;
419ba1627617d396135a4d679542a3623d5819e628Yasuyuki Kozakai
429ba1627617d396135a4d679542a3623d5819e628Yasuyuki Kozakai	return (dscp == info->dscp) ^ !!info->invert;
439ba1627617d396135a4d679542a3623d5819e628Yasuyuki Kozakai}
449ba1627617d396135a4d679542a3623d5819e628Yasuyuki Kozakai
45b0f38452ff73da7e9e0ddc68cd5c6b93c897ca0dJan Engelhardtstatic int dscp_mt_check(const struct xt_mtchk_param *par)
469ba1627617d396135a4d679542a3623d5819e628Yasuyuki Kozakai{
479b4fce7a3508a9776534188b6065b206a9608ccfJan Engelhardt	const struct xt_dscp_info *info = par->matchinfo;
489ba1627617d396135a4d679542a3623d5819e628Yasuyuki Kozakai
499b4fce7a3508a9776534188b6065b206a9608ccfJan Engelhardt	if (info->dscp > XT_DSCP_MAX) {
508bee4bad03c5b601bd6cea123c31025680587cccJan Engelhardt		pr_info("dscp %x out of range\n", info->dscp);
514a5a5c73b7cfee46a0b1411903cfa0dea532deecJan Engelhardt		return -EDOM;
529ba1627617d396135a4d679542a3623d5819e628Yasuyuki Kozakai	}
539ba1627617d396135a4d679542a3623d5819e628Yasuyuki Kozakai
54bd414ee605ff3ac5fcd79f57269a897879ee4cdeJan Engelhardt	return 0;
559ba1627617d396135a4d679542a3623d5819e628Yasuyuki Kozakai}
569ba1627617d396135a4d679542a3623d5819e628Yasuyuki Kozakai
5762fc8051083a334578c3f4b3488808f210b4565fJan Engelhardtstatic bool tos_mt(const struct sk_buff *skb, struct xt_action_param *par)
58f1095ab51d4297d4a84b64a65c71054183a73486Jan Engelhardt{
59f7108a20dee44e5bb037f9e48f6a207b42e6ae1cJan Engelhardt	const struct xt_tos_match_info *info = par->matchinfo;
60f1095ab51d4297d4a84b64a65c71054183a73486Jan Engelhardt
61aa5fa3185791aac71c9172d4fda3e8729164b5d1Jan Engelhardt	if (par->family == NFPROTO_IPV4)
62f1095ab51d4297d4a84b64a65c71054183a73486Jan Engelhardt		return ((ip_hdr(skb)->tos & info->tos_mask) ==
63f1095ab51d4297d4a84b64a65c71054183a73486Jan Engelhardt		       info->tos_value) ^ !!info->invert;
64f1095ab51d4297d4a84b64a65c71054183a73486Jan Engelhardt	else
65f1095ab51d4297d4a84b64a65c71054183a73486Jan Engelhardt		return ((ipv6_get_dsfield(ipv6_hdr(skb)) & info->tos_mask) ==
66f1095ab51d4297d4a84b64a65c71054183a73486Jan Engelhardt		       info->tos_value) ^ !!info->invert;
67f1095ab51d4297d4a84b64a65c71054183a73486Jan Engelhardt}
68f1095ab51d4297d4a84b64a65c71054183a73486Jan Engelhardt
69d3c5ee6d545b5372fd525ebe16988a5b6efeceb0Jan Engelhardtstatic struct xt_match dscp_mt_reg[] __read_mostly = {
704470bbc749e5551cce914529309456f631e25120Patrick McHardy	{
714470bbc749e5551cce914529309456f631e25120Patrick McHardy		.name		= "dscp",
72ee999d8b9573df1b547aacdc6d79f86eb79c25cdJan Engelhardt		.family		= NFPROTO_IPV4,
73d3c5ee6d545b5372fd525ebe16988a5b6efeceb0Jan Engelhardt		.checkentry	= dscp_mt_check,
74d3c5ee6d545b5372fd525ebe16988a5b6efeceb0Jan Engelhardt		.match		= dscp_mt,
754470bbc749e5551cce914529309456f631e25120Patrick McHardy		.matchsize	= sizeof(struct xt_dscp_info),
764470bbc749e5551cce914529309456f631e25120Patrick McHardy		.me		= THIS_MODULE,
774470bbc749e5551cce914529309456f631e25120Patrick McHardy	},
784470bbc749e5551cce914529309456f631e25120Patrick McHardy	{
794470bbc749e5551cce914529309456f631e25120Patrick McHardy		.name		= "dscp",
80ee999d8b9573df1b547aacdc6d79f86eb79c25cdJan Engelhardt		.family		= NFPROTO_IPV6,
81d3c5ee6d545b5372fd525ebe16988a5b6efeceb0Jan Engelhardt		.checkentry	= dscp_mt_check,
82d3c5ee6d545b5372fd525ebe16988a5b6efeceb0Jan Engelhardt		.match		= dscp_mt6,
834470bbc749e5551cce914529309456f631e25120Patrick McHardy		.matchsize	= sizeof(struct xt_dscp_info),
844470bbc749e5551cce914529309456f631e25120Patrick McHardy		.me		= THIS_MODULE,
854470bbc749e5551cce914529309456f631e25120Patrick McHardy	},
86c3b33e6a2cdefba38d83442ebae2ee42e853ea51Jan Engelhardt	{
87c3b33e6a2cdefba38d83442ebae2ee42e853ea51Jan Engelhardt		.name		= "tos",
88f1095ab51d4297d4a84b64a65c71054183a73486Jan Engelhardt		.revision	= 1,
89ee999d8b9573df1b547aacdc6d79f86eb79c25cdJan Engelhardt		.family		= NFPROTO_IPV4,
90f1095ab51d4297d4a84b64a65c71054183a73486Jan Engelhardt		.match		= tos_mt,
91f1095ab51d4297d4a84b64a65c71054183a73486Jan Engelhardt		.matchsize	= sizeof(struct xt_tos_match_info),
92f1095ab51d4297d4a84b64a65c71054183a73486Jan Engelhardt		.me		= THIS_MODULE,
93f1095ab51d4297d4a84b64a65c71054183a73486Jan Engelhardt	},
94f1095ab51d4297d4a84b64a65c71054183a73486Jan Engelhardt	{
95f1095ab51d4297d4a84b64a65c71054183a73486Jan Engelhardt		.name		= "tos",
96f1095ab51d4297d4a84b64a65c71054183a73486Jan Engelhardt		.revision	= 1,
97ee999d8b9573df1b547aacdc6d79f86eb79c25cdJan Engelhardt		.family		= NFPROTO_IPV6,
98f1095ab51d4297d4a84b64a65c71054183a73486Jan Engelhardt		.match		= tos_mt,
99f1095ab51d4297d4a84b64a65c71054183a73486Jan Engelhardt		.matchsize	= sizeof(struct xt_tos_match_info),
100f1095ab51d4297d4a84b64a65c71054183a73486Jan Engelhardt		.me		= THIS_MODULE,
101f1095ab51d4297d4a84b64a65c71054183a73486Jan Engelhardt	},
1029ba1627617d396135a4d679542a3623d5819e628Yasuyuki Kozakai};
1039ba1627617d396135a4d679542a3623d5819e628Yasuyuki Kozakai
104d3c5ee6d545b5372fd525ebe16988a5b6efeceb0Jan Engelhardtstatic int __init dscp_mt_init(void)
1059ba1627617d396135a4d679542a3623d5819e628Yasuyuki Kozakai{
106d3c5ee6d545b5372fd525ebe16988a5b6efeceb0Jan Engelhardt	return xt_register_matches(dscp_mt_reg, ARRAY_SIZE(dscp_mt_reg));
1079ba1627617d396135a4d679542a3623d5819e628Yasuyuki Kozakai}
1089ba1627617d396135a4d679542a3623d5819e628Yasuyuki Kozakai
109d3c5ee6d545b5372fd525ebe16988a5b6efeceb0Jan Engelhardtstatic void __exit dscp_mt_exit(void)
1109ba1627617d396135a4d679542a3623d5819e628Yasuyuki Kozakai{
111d3c5ee6d545b5372fd525ebe16988a5b6efeceb0Jan Engelhardt	xt_unregister_matches(dscp_mt_reg, ARRAY_SIZE(dscp_mt_reg));
1129ba1627617d396135a4d679542a3623d5819e628Yasuyuki Kozakai}
1139ba1627617d396135a4d679542a3623d5819e628Yasuyuki Kozakai
114d3c5ee6d545b5372fd525ebe16988a5b6efeceb0Jan Engelhardtmodule_init(dscp_mt_init);
115d3c5ee6d545b5372fd525ebe16988a5b6efeceb0Jan Engelhardtmodule_exit(dscp_mt_exit);
116