linux/net/netfilter/xt_DSCP.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/* x_tables module for setting the IPv4/IPv6 DSCP field, Version 1.8
   3 *
   4 * (C) 2002 by Harald Welte <laforge@netfilter.org>
   5 * based on ipt_FTOS.c (C) 2000 by Matthew G. Marsh <mgm@paktronix.com>
   6 *
   7 * See RFC2474 for a description of the DSCP field within the IP Header.
   8*/
   9#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  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/x_tables.h>
  17#include <linux/netfilter/xt_DSCP.h>
  18
  19MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
  20MODULE_DESCRIPTION("Xtables: DSCP/TOS field modification");
  21MODULE_LICENSE("GPL");
  22MODULE_ALIAS("ipt_DSCP");
  23MODULE_ALIAS("ip6t_DSCP");
  24MODULE_ALIAS("ipt_TOS");
  25MODULE_ALIAS("ip6t_TOS");
  26
  27static unsigned int
  28dscp_tg(struct sk_buff *skb, const struct xt_action_param *par)
  29{
  30        const struct xt_DSCP_info *dinfo = par->targinfo;
  31        u_int8_t dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT;
  32
  33        if (dscp != dinfo->dscp) {
  34                if (skb_ensure_writable(skb, sizeof(struct iphdr)))
  35                        return NF_DROP;
  36
  37                ipv4_change_dsfield(ip_hdr(skb),
  38                                    (__force __u8)(~XT_DSCP_MASK),
  39                                    dinfo->dscp << XT_DSCP_SHIFT);
  40
  41        }
  42        return XT_CONTINUE;
  43}
  44
  45static unsigned int
  46dscp_tg6(struct sk_buff *skb, const struct xt_action_param *par)
  47{
  48        const struct xt_DSCP_info *dinfo = par->targinfo;
  49        u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> XT_DSCP_SHIFT;
  50
  51        if (dscp != dinfo->dscp) {
  52                if (skb_ensure_writable(skb, sizeof(struct ipv6hdr)))
  53                        return NF_DROP;
  54
  55                ipv6_change_dsfield(ipv6_hdr(skb),
  56                                    (__force __u8)(~XT_DSCP_MASK),
  57                                    dinfo->dscp << XT_DSCP_SHIFT);
  58        }
  59        return XT_CONTINUE;
  60}
  61
  62static int dscp_tg_check(const struct xt_tgchk_param *par)
  63{
  64        const struct xt_DSCP_info *info = par->targinfo;
  65
  66        if (info->dscp > XT_DSCP_MAX)
  67                return -EDOM;
  68        return 0;
  69}
  70
  71static unsigned int
  72tos_tg(struct sk_buff *skb, const struct xt_action_param *par)
  73{
  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
  91static unsigned int
  92tos_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;
 109}
 110
 111static struct xt_target dscp_tg_reg[] __read_mostly = {
 112        {
 113                .name           = "DSCP",
 114                .family         = NFPROTO_IPV4,
 115                .checkentry     = dscp_tg_check,
 116                .target         = dscp_tg,
 117                .targetsize     = sizeof(struct xt_DSCP_info),
 118                .table          = "mangle",
 119                .me             = THIS_MODULE,
 120        },
 121        {
 122                .name           = "DSCP",
 123                .family         = NFPROTO_IPV6,
 124                .checkentry     = dscp_tg_check,
 125                .target         = dscp_tg6,
 126                .targetsize     = sizeof(struct xt_DSCP_info),
 127                .table          = "mangle",
 128                .me             = THIS_MODULE,
 129        },
 130        {
 131                .name           = "TOS",
 132                .revision       = 1,
 133                .family         = NFPROTO_IPV4,
 134                .table          = "mangle",
 135                .target         = tos_tg,
 136                .targetsize     = sizeof(struct xt_tos_target_info),
 137                .me             = THIS_MODULE,
 138        },
 139        {
 140                .name           = "TOS",
 141                .revision       = 1,
 142                .family         = NFPROTO_IPV6,
 143                .table          = "mangle",
 144                .target         = tos_tg6,
 145                .targetsize     = sizeof(struct xt_tos_target_info),
 146                .me             = THIS_MODULE,
 147        },
 148};
 149
 150static int __init dscp_tg_init(void)
 151{
 152        return xt_register_targets(dscp_tg_reg, ARRAY_SIZE(dscp_tg_reg));
 153}
 154
 155static void __exit dscp_tg_exit(void)
 156{
 157        xt_unregister_targets(dscp_tg_reg, ARRAY_SIZE(dscp_tg_reg));
 158}
 159
 160module_init(dscp_tg_init);
 161module_exit(dscp_tg_exit);
 162