Commit | Line | Data |
---|---|---|
9ba16276 | 1 | /* IP tables module for matching the value of the IPv4/IPv6 DSCP field |
9ba16276 YK |
2 | * |
3 | * (C) 2002 by Harald Welte <laforge@netfilter.org> | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of the GNU General Public License version 2 as | |
7 | * published by the Free Software Foundation. | |
8 | */ | |
9 | ||
10 | #include <linux/module.h> | |
11 | #include <linux/skbuff.h> | |
12 | #include <linux/ip.h> | |
13 | #include <linux/ipv6.h> | |
14 | #include <net/dsfield.h> | |
15 | ||
16 | #include <linux/netfilter/xt_dscp.h> | |
17 | #include <linux/netfilter/x_tables.h> | |
18 | ||
19 | MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); | |
20 | MODULE_DESCRIPTION("x_tables DSCP matching module"); | |
21 | MODULE_LICENSE("GPL"); | |
22 | MODULE_ALIAS("ipt_dscp"); | |
23 | MODULE_ALIAS("ip6t_dscp"); | |
24 | ||
d3c5ee6d JE |
25 | static bool |
26 | dscp_mt(const struct sk_buff *skb, const struct net_device *in, | |
27 | const struct net_device *out, const struct xt_match *match, | |
28 | const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop) | |
1d93a9cb JE |
29 | { |
30 | const struct xt_dscp_info *info = matchinfo; | |
31 | u_int8_t dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT; | |
32 | ||
33 | return (dscp == info->dscp) ^ !!info->invert; | |
34 | } | |
35 | ||
d3c5ee6d JE |
36 | static bool |
37 | dscp_mt6(const struct sk_buff *skb, const struct net_device *in, | |
38 | const struct net_device *out, const struct xt_match *match, | |
39 | const void *matchinfo, int offset, unsigned int protoff, | |
40 | bool *hotdrop) | |
9ba16276 YK |
41 | { |
42 | const struct xt_dscp_info *info = matchinfo; | |
0660e03f | 43 | u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> XT_DSCP_SHIFT; |
9ba16276 YK |
44 | |
45 | return (dscp == info->dscp) ^ !!info->invert; | |
46 | } | |
47 | ||
d3c5ee6d JE |
48 | static bool |
49 | dscp_mt_check(const char *tablename, const void *info, | |
50 | const struct xt_match *match, void *matchinfo, | |
51 | unsigned int hook_mask) | |
9ba16276 YK |
52 | { |
53 | const u_int8_t dscp = ((struct xt_dscp_info *)matchinfo)->dscp; | |
54 | ||
55 | if (dscp > XT_DSCP_MAX) { | |
56 | printk(KERN_ERR "xt_dscp: dscp %x out of range\n", dscp); | |
ccb79bdc | 57 | return false; |
9ba16276 YK |
58 | } |
59 | ||
ccb79bdc | 60 | return true; |
9ba16276 YK |
61 | } |
62 | ||
d3c5ee6d | 63 | static struct xt_match dscp_mt_reg[] __read_mostly = { |
4470bbc7 PM |
64 | { |
65 | .name = "dscp", | |
66 | .family = AF_INET, | |
d3c5ee6d JE |
67 | .checkentry = dscp_mt_check, |
68 | .match = dscp_mt, | |
4470bbc7 PM |
69 | .matchsize = sizeof(struct xt_dscp_info), |
70 | .me = THIS_MODULE, | |
71 | }, | |
72 | { | |
73 | .name = "dscp", | |
74 | .family = AF_INET6, | |
d3c5ee6d JE |
75 | .checkentry = dscp_mt_check, |
76 | .match = dscp_mt6, | |
4470bbc7 PM |
77 | .matchsize = sizeof(struct xt_dscp_info), |
78 | .me = THIS_MODULE, | |
79 | }, | |
9ba16276 YK |
80 | }; |
81 | ||
d3c5ee6d | 82 | static int __init dscp_mt_init(void) |
9ba16276 | 83 | { |
d3c5ee6d | 84 | return xt_register_matches(dscp_mt_reg, ARRAY_SIZE(dscp_mt_reg)); |
9ba16276 YK |
85 | } |
86 | ||
d3c5ee6d | 87 | static void __exit dscp_mt_exit(void) |
9ba16276 | 88 | { |
d3c5ee6d | 89 | xt_unregister_matches(dscp_mt_reg, ARRAY_SIZE(dscp_mt_reg)); |
9ba16276 YK |
90 | } |
91 | ||
d3c5ee6d JE |
92 | module_init(dscp_mt_init); |
93 | module_exit(dscp_mt_exit); |