Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /* x_tables module for setting the IPv4/IPv6 DSCP field, Version 1.8
0003  *
0004  * (C) 2002 by Harald Welte <laforge@netfilter.org>
0005  * based on ipt_FTOS.c (C) 2000 by Matthew G. Marsh <mgm@paktronix.com>
0006  *
0007  * See RFC2474 for a description of the DSCP field within the IP Header.
0008 */
0009 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0010 #include <linux/module.h>
0011 #include <linux/skbuff.h>
0012 #include <linux/ip.h>
0013 #include <linux/ipv6.h>
0014 #include <net/dsfield.h>
0015 
0016 #include <linux/netfilter/x_tables.h>
0017 #include <linux/netfilter/xt_DSCP.h>
0018 
0019 MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
0020 MODULE_DESCRIPTION("Xtables: DSCP/TOS field modification");
0021 MODULE_LICENSE("GPL");
0022 MODULE_ALIAS("ipt_DSCP");
0023 MODULE_ALIAS("ip6t_DSCP");
0024 MODULE_ALIAS("ipt_TOS");
0025 MODULE_ALIAS("ip6t_TOS");
0026 
0027 #define XT_DSCP_ECN_MASK    3u
0028 
0029 static unsigned int
0030 dscp_tg(struct sk_buff *skb, const struct xt_action_param *par)
0031 {
0032     const struct xt_DSCP_info *dinfo = par->targinfo;
0033     u_int8_t dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT;
0034 
0035     if (dscp != dinfo->dscp) {
0036         if (skb_ensure_writable(skb, sizeof(struct iphdr)))
0037             return NF_DROP;
0038 
0039         ipv4_change_dsfield(ip_hdr(skb), XT_DSCP_ECN_MASK,
0040                     dinfo->dscp << XT_DSCP_SHIFT);
0041 
0042     }
0043     return XT_CONTINUE;
0044 }
0045 
0046 static unsigned int
0047 dscp_tg6(struct sk_buff *skb, const struct xt_action_param *par)
0048 {
0049     const struct xt_DSCP_info *dinfo = par->targinfo;
0050     u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> XT_DSCP_SHIFT;
0051 
0052     if (dscp != dinfo->dscp) {
0053         if (skb_ensure_writable(skb, sizeof(struct ipv6hdr)))
0054             return NF_DROP;
0055 
0056         ipv6_change_dsfield(ipv6_hdr(skb), XT_DSCP_ECN_MASK,
0057                     dinfo->dscp << XT_DSCP_SHIFT);
0058     }
0059     return XT_CONTINUE;
0060 }
0061 
0062 static int dscp_tg_check(const struct xt_tgchk_param *par)
0063 {
0064     const struct xt_DSCP_info *info = par->targinfo;
0065 
0066     if (info->dscp > XT_DSCP_MAX)
0067         return -EDOM;
0068     return 0;
0069 }
0070 
0071 static unsigned int
0072 tos_tg(struct sk_buff *skb, const struct xt_action_param *par)
0073 {
0074     const struct xt_tos_target_info *info = par->targinfo;
0075     struct iphdr *iph = ip_hdr(skb);
0076     u_int8_t orig, nv;
0077 
0078     orig = ipv4_get_dsfield(iph);
0079     nv   = (orig & ~info->tos_mask) ^ info->tos_value;
0080 
0081     if (orig != nv) {
0082         if (skb_ensure_writable(skb, sizeof(struct iphdr)))
0083             return NF_DROP;
0084         iph = ip_hdr(skb);
0085         ipv4_change_dsfield(iph, 0, nv);
0086     }
0087 
0088     return XT_CONTINUE;
0089 }
0090 
0091 static unsigned int
0092 tos_tg6(struct sk_buff *skb, const struct xt_action_param *par)
0093 {
0094     const struct xt_tos_target_info *info = par->targinfo;
0095     struct ipv6hdr *iph = ipv6_hdr(skb);
0096     u_int8_t orig, nv;
0097 
0098     orig = ipv6_get_dsfield(iph);
0099     nv   = (orig & ~info->tos_mask) ^ info->tos_value;
0100 
0101     if (orig != nv) {
0102         if (skb_ensure_writable(skb, sizeof(struct iphdr)))
0103             return NF_DROP;
0104         iph = ipv6_hdr(skb);
0105         ipv6_change_dsfield(iph, 0, nv);
0106     }
0107 
0108     return XT_CONTINUE;
0109 }
0110 
0111 static struct xt_target dscp_tg_reg[] __read_mostly = {
0112     {
0113         .name       = "DSCP",
0114         .family     = NFPROTO_IPV4,
0115         .checkentry = dscp_tg_check,
0116         .target     = dscp_tg,
0117         .targetsize = sizeof(struct xt_DSCP_info),
0118         .table      = "mangle",
0119         .me     = THIS_MODULE,
0120     },
0121     {
0122         .name       = "DSCP",
0123         .family     = NFPROTO_IPV6,
0124         .checkentry = dscp_tg_check,
0125         .target     = dscp_tg6,
0126         .targetsize = sizeof(struct xt_DSCP_info),
0127         .table      = "mangle",
0128         .me     = THIS_MODULE,
0129     },
0130     {
0131         .name       = "TOS",
0132         .revision   = 1,
0133         .family     = NFPROTO_IPV4,
0134         .table      = "mangle",
0135         .target     = tos_tg,
0136         .targetsize = sizeof(struct xt_tos_target_info),
0137         .me     = THIS_MODULE,
0138     },
0139     {
0140         .name       = "TOS",
0141         .revision   = 1,
0142         .family     = NFPROTO_IPV6,
0143         .table      = "mangle",
0144         .target     = tos_tg6,
0145         .targetsize = sizeof(struct xt_tos_target_info),
0146         .me     = THIS_MODULE,
0147     },
0148 };
0149 
0150 static int __init dscp_tg_init(void)
0151 {
0152     return xt_register_targets(dscp_tg_reg, ARRAY_SIZE(dscp_tg_reg));
0153 }
0154 
0155 static void __exit dscp_tg_exit(void)
0156 {
0157     xt_unregister_targets(dscp_tg_reg, ARRAY_SIZE(dscp_tg_reg));
0158 }
0159 
0160 module_init(dscp_tg_init);
0161 module_exit(dscp_tg_exit);