|
1 | 1 | // SPDX-License-Identifier: GPL-2.0-only
|
2 |
| -/* IP tables module for matching the value of the IPv4/IPv6 DSCP field |
| 2 | +/* x_tables module for setting the IPv4/IPv6 DSCP field, Version 1.8 |
3 | 3 | *
|
4 | 4 | * (C) 2002 by Harald Welte <[email protected]>
|
5 |
| - */ |
| 5 | + * based on ipt_FTOS.c (C) 2000 by Matthew G. Marsh <[email protected]> |
| 6 | + * |
| 7 | + * See RFC2474 for a description of the DSCP field within the IP Header. |
| 8 | +*/ |
6 | 9 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
7 | 10 | #include <linux/module.h>
|
8 | 11 | #include <linux/skbuff.h>
|
|
11 | 14 | #include <net/dsfield.h>
|
12 | 15 |
|
13 | 16 | #include <linux/netfilter/x_tables.h>
|
14 |
| -#include <linux/netfilter/xt_dscp.h> |
| 17 | +#include <linux/netfilter/xt_DSCP.h> |
15 | 18 |
|
16 | 19 | MODULE_AUTHOR( "Harald Welte <[email protected]>");
|
17 |
| -MODULE_DESCRIPTION("Xtables: DSCP/TOS field match"); |
| 20 | +MODULE_DESCRIPTION("Xtables: DSCP/TOS field modification"); |
18 | 21 | MODULE_LICENSE("GPL");
|
19 |
| -MODULE_ALIAS("ipt_dscp"); |
20 |
| -MODULE_ALIAS("ip6t_dscp"); |
21 |
| -MODULE_ALIAS("ipt_tos"); |
22 |
| -MODULE_ALIAS("ip6t_tos"); |
| 22 | +MODULE_ALIAS("ipt_DSCP"); |
| 23 | +MODULE_ALIAS("ip6t_DSCP"); |
| 24 | +MODULE_ALIAS("ipt_TOS"); |
| 25 | +MODULE_ALIAS("ip6t_TOS"); |
| 26 | + |
| 27 | +#define XT_DSCP_ECN_MASK 3u |
23 | 28 |
|
24 |
| -static bool |
25 |
| -dscp_mt(const struct sk_buff *skb, struct xt_action_param *par) |
| 29 | +static unsigned int |
| 30 | +dscp_tg(struct sk_buff *skb, const struct xt_action_param *par) |
26 | 31 | {
|
27 |
| - const struct xt_dscp_info *info = par->matchinfo; |
| 32 | + const struct xt_DSCP_info *dinfo = par->targinfo; |
28 | 33 | u_int8_t dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT;
|
29 | 34 |
|
30 |
| - return (dscp == info->dscp) ^ !!info->invert; |
| 35 | + if (dscp != dinfo->dscp) { |
| 36 | + if (skb_ensure_writable(skb, sizeof(struct iphdr))) |
| 37 | + return NF_DROP; |
| 38 | + |
| 39 | + ipv4_change_dsfield(ip_hdr(skb), XT_DSCP_ECN_MASK, |
| 40 | + dinfo->dscp << XT_DSCP_SHIFT); |
| 41 | + |
| 42 | + } |
| 43 | + return XT_CONTINUE; |
31 | 44 | }
|
32 | 45 |
|
33 |
| -static bool |
34 |
| -dscp_mt6(const struct sk_buff *skb, struct xt_action_param *par) |
| 46 | +static unsigned int |
| 47 | +dscp_tg6(struct sk_buff *skb, const struct xt_action_param *par) |
35 | 48 | {
|
36 |
| - const struct xt_dscp_info *info = par->matchinfo; |
| 49 | + const struct xt_DSCP_info *dinfo = par->targinfo; |
37 | 50 | u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> XT_DSCP_SHIFT;
|
38 | 51 |
|
39 |
| - return (dscp == info->dscp) ^ !!info->invert; |
| 52 | + if (dscp != dinfo->dscp) { |
| 53 | + if (skb_ensure_writable(skb, sizeof(struct ipv6hdr))) |
| 54 | + return NF_DROP; |
| 55 | + |
| 56 | + ipv6_change_dsfield(ipv6_hdr(skb), XT_DSCP_ECN_MASK, |
| 57 | + dinfo->dscp << XT_DSCP_SHIFT); |
| 58 | + } |
| 59 | + return XT_CONTINUE; |
40 | 60 | }
|
41 | 61 |
|
42 |
| -static int dscp_mt_check(const struct xt_mtchk_param *par) |
| 62 | +static int dscp_tg_check(const struct xt_tgchk_param *par) |
43 | 63 | {
|
44 |
| - const struct xt_dscp_info *info = par->matchinfo; |
| 64 | + const struct xt_DSCP_info *info = par->targinfo; |
45 | 65 |
|
46 | 66 | if (info->dscp > XT_DSCP_MAX)
|
47 | 67 | return -EDOM;
|
48 |
| - |
49 | 68 | return 0;
|
50 | 69 | }
|
51 | 70 |
|
52 |
| -static bool tos_mt(const struct sk_buff *skb, struct xt_action_param *par) |
| 71 | +static unsigned int |
| 72 | +tos_tg(struct sk_buff *skb, const struct xt_action_param *par) |
53 | 73 | {
|
54 |
| - const struct xt_tos_match_info *info = par->matchinfo; |
55 |
| - |
56 |
| - if (xt_family(par) == NFPROTO_IPV4) |
57 |
| - 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; |
| 74 | + const struct xt_tos_target_info *info = par->targinfo; |
| 75 | + struct iphdr *iph = ip_hdr(skb); |
| 76 | + u_int8_t orig, nv; |
| 77 | + |
| 78 | + orig = ipv4_get_dsfield(iph); |
| 79 | + nv = (orig & ~info->tos_mask) ^ info->tos_value; |
| 80 | + |
| 81 | + if (orig != nv) { |
| 82 | + if (skb_ensure_writable(skb, sizeof(struct iphdr))) |
| 83 | + return NF_DROP; |
| 84 | + iph = ip_hdr(skb); |
| 85 | + ipv4_change_dsfield(iph, 0, nv); |
| 86 | + } |
| 87 | + |
| 88 | + return XT_CONTINUE; |
| 89 | +} |
| 90 | + |
| 91 | +static unsigned int |
| 92 | +tos_tg6(struct sk_buff *skb, const struct xt_action_param *par) |
| 93 | +{ |
| 94 | + const struct xt_tos_target_info *info = par->targinfo; |
| 95 | + struct ipv6hdr *iph = ipv6_hdr(skb); |
| 96 | + u_int8_t orig, nv; |
| 97 | + |
| 98 | + orig = ipv6_get_dsfield(iph); |
| 99 | + nv = (orig & ~info->tos_mask) ^ info->tos_value; |
| 100 | + |
| 101 | + if (orig != nv) { |
| 102 | + if (skb_ensure_writable(skb, sizeof(struct iphdr))) |
| 103 | + return NF_DROP; |
| 104 | + iph = ipv6_hdr(skb); |
| 105 | + ipv6_change_dsfield(iph, 0, nv); |
| 106 | + } |
| 107 | + |
| 108 | + return XT_CONTINUE; |
62 | 109 | }
|
63 | 110 |
|
64 |
| -static struct xt_match dscp_mt_reg[] __read_mostly = { |
| 111 | +static struct xt_target dscp_tg_reg[] __read_mostly = { |
65 | 112 | {
|
66 |
| - .name = "dscp", |
| 113 | + .name = "DSCP", |
67 | 114 | .family = NFPROTO_IPV4,
|
68 |
| - .checkentry = dscp_mt_check, |
69 |
| - .match = dscp_mt, |
70 |
| - .matchsize = sizeof(struct xt_dscp_info), |
| 115 | + .checkentry = dscp_tg_check, |
| 116 | + .target = dscp_tg, |
| 117 | + .targetsize = sizeof(struct xt_DSCP_info), |
| 118 | + .table = "mangle", |
71 | 119 | .me = THIS_MODULE,
|
72 | 120 | },
|
73 | 121 | {
|
74 |
| - .name = "dscp", |
| 122 | + .name = "DSCP", |
75 | 123 | .family = NFPROTO_IPV6,
|
76 |
| - .checkentry = dscp_mt_check, |
77 |
| - .match = dscp_mt6, |
78 |
| - .matchsize = sizeof(struct xt_dscp_info), |
| 124 | + .checkentry = dscp_tg_check, |
| 125 | + .target = dscp_tg6, |
| 126 | + .targetsize = sizeof(struct xt_DSCP_info), |
| 127 | + .table = "mangle", |
79 | 128 | .me = THIS_MODULE,
|
80 | 129 | },
|
81 | 130 | {
|
82 |
| - .name = "tos", |
| 131 | + .name = "TOS", |
83 | 132 | .revision = 1,
|
84 | 133 | .family = NFPROTO_IPV4,
|
85 |
| - .match = tos_mt, |
86 |
| - .matchsize = sizeof(struct xt_tos_match_info), |
| 134 | + .table = "mangle", |
| 135 | + .target = tos_tg, |
| 136 | + .targetsize = sizeof(struct xt_tos_target_info), |
87 | 137 | .me = THIS_MODULE,
|
88 | 138 | },
|
89 | 139 | {
|
90 |
| - .name = "tos", |
| 140 | + .name = "TOS", |
91 | 141 | .revision = 1,
|
92 | 142 | .family = NFPROTO_IPV6,
|
93 |
| - .match = tos_mt, |
94 |
| - .matchsize = sizeof(struct xt_tos_match_info), |
| 143 | + .table = "mangle", |
| 144 | + .target = tos_tg6, |
| 145 | + .targetsize = sizeof(struct xt_tos_target_info), |
95 | 146 | .me = THIS_MODULE,
|
96 | 147 | },
|
97 | 148 | };
|
98 | 149 |
|
99 |
| -static int __init dscp_mt_init(void) |
| 150 | +static int __init dscp_tg_init(void) |
100 | 151 | {
|
101 |
| - return xt_register_matches(dscp_mt_reg, ARRAY_SIZE(dscp_mt_reg)); |
| 152 | + return xt_register_targets(dscp_tg_reg, ARRAY_SIZE(dscp_tg_reg)); |
102 | 153 | }
|
103 | 154 |
|
104 |
| -static void __exit dscp_mt_exit(void) |
| 155 | +static void __exit dscp_tg_exit(void) |
105 | 156 | {
|
106 |
| - xt_unregister_matches(dscp_mt_reg, ARRAY_SIZE(dscp_mt_reg)); |
| 157 | + xt_unregister_targets(dscp_tg_reg, ARRAY_SIZE(dscp_tg_reg)); |
107 | 158 | }
|
108 | 159 |
|
109 |
| -module_init(dscp_mt_init); |
110 |
| -module_exit(dscp_mt_exit); |
| 160 | +module_init(dscp_tg_init); |
| 161 | +module_exit(dscp_tg_exit); |
0 commit comments