blob: fb0169a8f9bbd3b03411a0287fb021042104afa9 [file] [log] [blame]
Thomas Gleixnerd2912cb2019-06-04 10:11:33 +02001// SPDX-License-Identifier: GPL-2.0-only
Yasuyuki Kozakai9ba16272006-08-22 00:29:37 -07002/* IP tables module for matching the value of the IPv4/IPv6 DSCP field
3 *
Yasuyuki Kozakai9ba16272006-08-22 00:29:37 -07004 * (C) 2002 by Harald Welte <laforge@netfilter.org>
Yasuyuki Kozakai9ba16272006-08-22 00:29:37 -07005 */
Jan Engelhardt8bee4ba2010-03-17 16:04:40 +01006#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
Yasuyuki Kozakai9ba16272006-08-22 00:29:37 -07007#include <linux/module.h>
8#include <linux/skbuff.h>
9#include <linux/ip.h>
10#include <linux/ipv6.h>
11#include <net/dsfield.h>
12
Yasuyuki Kozakai9ba16272006-08-22 00:29:37 -070013#include <linux/netfilter/x_tables.h>
Jan Engelhardtc3b33e62007-12-04 23:37:54 -080014#include <linux/netfilter/xt_dscp.h>
Yasuyuki Kozakai9ba16272006-08-22 00:29:37 -070015
16MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
Jan Engelhardt2ae15b62008-01-14 23:42:28 -080017MODULE_DESCRIPTION("Xtables: DSCP/TOS field match");
Yasuyuki Kozakai9ba16272006-08-22 00:29:37 -070018MODULE_LICENSE("GPL");
19MODULE_ALIAS("ipt_dscp");
20MODULE_ALIAS("ip6t_dscp");
Jan Engelhardtc3b33e62007-12-04 23:37:54 -080021MODULE_ALIAS("ipt_tos");
Jan Engelhardtf1095ab2007-12-04 23:38:30 -080022MODULE_ALIAS("ip6t_tos");
Yasuyuki Kozakai9ba16272006-08-22 00:29:37 -070023
Jan Engelhardtd3c5ee62007-12-04 23:24:03 -080024static bool
Jan Engelhardt62fc8052009-07-07 20:42:08 +020025dscp_mt(const struct sk_buff *skb, struct xt_action_param *par)
Yasuyuki Kozakai9ba16272006-08-22 00:29:37 -070026{
Jan Engelhardtf7108a202008-10-08 11:35:18 +020027 const struct xt_dscp_info *info = par->matchinfo;
Jan Engelhardt1d93a9c2007-07-07 22:15:35 -070028 u_int8_t dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT;
29
30 return (dscp == info->dscp) ^ !!info->invert;
31}
32
Jan Engelhardtd3c5ee62007-12-04 23:24:03 -080033static bool
Jan Engelhardt62fc8052009-07-07 20:42:08 +020034dscp_mt6(const struct sk_buff *skb, struct xt_action_param *par)
Jan Engelhardt1d93a9c2007-07-07 22:15:35 -070035{
Jan Engelhardtf7108a202008-10-08 11:35:18 +020036 const struct xt_dscp_info *info = par->matchinfo;
Arnaldo Carvalho de Melo0660e032007-04-25 17:54:47 -070037 u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> XT_DSCP_SHIFT;
Yasuyuki Kozakai9ba16272006-08-22 00:29:37 -070038
39 return (dscp == info->dscp) ^ !!info->invert;
40}
41
Jan Engelhardtb0f38452010-03-19 17:16:42 +010042static int dscp_mt_check(const struct xt_mtchk_param *par)
Yasuyuki Kozakai9ba16272006-08-22 00:29:37 -070043{
Jan Engelhardt9b4fce72008-10-08 11:35:18 +020044 const struct xt_dscp_info *info = par->matchinfo;
Yasuyuki Kozakai9ba16272006-08-22 00:29:37 -070045
Florian Westphal0cc95012018-02-09 15:51:59 +010046 if (info->dscp > XT_DSCP_MAX)
Jan Engelhardt4a5a5c72010-03-19 17:32:59 +010047 return -EDOM;
Yasuyuki Kozakai9ba16272006-08-22 00:29:37 -070048
Jan Engelhardtbd414ee2010-03-23 16:35:56 +010049 return 0;
Yasuyuki Kozakai9ba16272006-08-22 00:29:37 -070050}
51
Jan Engelhardt62fc8052009-07-07 20:42:08 +020052static bool tos_mt(const struct sk_buff *skb, struct xt_action_param *par)
Jan Engelhardtf1095ab2007-12-04 23:38:30 -080053{
Jan Engelhardtf7108a202008-10-08 11:35:18 +020054 const struct xt_tos_match_info *info = par->matchinfo;
Jan Engelhardtf1095ab2007-12-04 23:38:30 -080055
Pablo Neira Ayuso613dbd92016-11-03 10:56:21 +010056 if (xt_family(par) == NFPROTO_IPV4)
Jan Engelhardtf1095ab2007-12-04 23:38:30 -080057 return ((ip_hdr(skb)->tos & info->tos_mask) ==
58 info->tos_value) ^ !!info->invert;
59 else
60 return ((ipv6_get_dsfield(ipv6_hdr(skb)) & info->tos_mask) ==
61 info->tos_value) ^ !!info->invert;
62}
63
Jan Engelhardtd3c5ee62007-12-04 23:24:03 -080064static struct xt_match dscp_mt_reg[] __read_mostly = {
Patrick McHardy4470bbc2006-08-22 00:34:04 -070065 {
66 .name = "dscp",
Jan Engelhardtee999d82008-10-08 11:35:01 +020067 .family = NFPROTO_IPV4,
Jan Engelhardtd3c5ee62007-12-04 23:24:03 -080068 .checkentry = dscp_mt_check,
69 .match = dscp_mt,
Patrick McHardy4470bbc2006-08-22 00:34:04 -070070 .matchsize = sizeof(struct xt_dscp_info),
71 .me = THIS_MODULE,
72 },
73 {
74 .name = "dscp",
Jan Engelhardtee999d82008-10-08 11:35:01 +020075 .family = NFPROTO_IPV6,
Jan Engelhardtd3c5ee62007-12-04 23:24:03 -080076 .checkentry = dscp_mt_check,
77 .match = dscp_mt6,
Patrick McHardy4470bbc2006-08-22 00:34:04 -070078 .matchsize = sizeof(struct xt_dscp_info),
79 .me = THIS_MODULE,
80 },
Jan Engelhardtc3b33e62007-12-04 23:37:54 -080081 {
82 .name = "tos",
Jan Engelhardtf1095ab2007-12-04 23:38:30 -080083 .revision = 1,
Jan Engelhardtee999d82008-10-08 11:35:01 +020084 .family = NFPROTO_IPV4,
Jan Engelhardtf1095ab2007-12-04 23:38:30 -080085 .match = tos_mt,
86 .matchsize = sizeof(struct xt_tos_match_info),
87 .me = THIS_MODULE,
88 },
89 {
90 .name = "tos",
91 .revision = 1,
Jan Engelhardtee999d82008-10-08 11:35:01 +020092 .family = NFPROTO_IPV6,
Jan Engelhardtf1095ab2007-12-04 23:38:30 -080093 .match = tos_mt,
94 .matchsize = sizeof(struct xt_tos_match_info),
95 .me = THIS_MODULE,
96 },
Yasuyuki Kozakai9ba16272006-08-22 00:29:37 -070097};
98
Jan Engelhardtd3c5ee62007-12-04 23:24:03 -080099static int __init dscp_mt_init(void)
Yasuyuki Kozakai9ba16272006-08-22 00:29:37 -0700100{
Jan Engelhardtd3c5ee62007-12-04 23:24:03 -0800101 return xt_register_matches(dscp_mt_reg, ARRAY_SIZE(dscp_mt_reg));
Yasuyuki Kozakai9ba16272006-08-22 00:29:37 -0700102}
103
Jan Engelhardtd3c5ee62007-12-04 23:24:03 -0800104static void __exit dscp_mt_exit(void)
Yasuyuki Kozakai9ba16272006-08-22 00:29:37 -0700105{
Jan Engelhardtd3c5ee62007-12-04 23:24:03 -0800106 xt_unregister_matches(dscp_mt_reg, ARRAY_SIZE(dscp_mt_reg));
Yasuyuki Kozakai9ba16272006-08-22 00:29:37 -0700107}
108
Jan Engelhardtd3c5ee62007-12-04 23:24:03 -0800109module_init(dscp_mt_init);
110module_exit(dscp_mt_exit);