linux/net/netfilter/xt_dscp.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/* IP tables module for matching the value of the IPv4/IPv6 DSCP field
   3 *
   4 * (C) 2002 by Harald Welte <laforge@netfilter.org>
   5 */
   6#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
   7#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
  13#include <linux/netfilter/x_tables.h>
  14#include <linux/netfilter/xt_dscp.h>
  15
  16MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
  17MODULE_DESCRIPTION("Xtables: DSCP/TOS field match");
  18MODULE_LICENSE("GPL");
  19MODULE_ALIAS("ipt_dscp");
  20MODULE_ALIAS("ip6t_dscp");
  21MODULE_ALIAS("ipt_tos");
  22MODULE_ALIAS("ip6t_tos");
  23
  24static bool
  25dscp_mt(const struct sk_buff *skb, struct xt_action_param *par)
  26{
  27        const struct xt_dscp_info *info = par->matchinfo;
  28        u_int8_t dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT;
  29
  30        return (dscp == info->dscp) ^ !!info->invert;
  31}
  32
  33static bool
  34dscp_mt6(const struct sk_buff *skb, struct xt_action_param *par)
  35{
  36        const struct xt_dscp_info *info = par->matchinfo;
  37        u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> XT_DSCP_SHIFT;
  38
  39        return (dscp == info->dscp) ^ !!info->invert;
  40}
  41
  42static int dscp_mt_check(const struct xt_mtchk_param *par)
  43{
  44        const struct xt_dscp_info *info = par->matchinfo;
  45
  46        if (info->dscp > XT_DSCP_MAX)
  47                return -EDOM;
  48
  49        return 0;
  50}
  51
  52static bool tos_mt(const struct sk_buff *skb, struct xt_action_param *par)
  53{
  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;
  62}
  63
  64static struct xt_match dscp_mt_reg[] __read_mostly = {
  65        {
  66                .name           = "dscp",
  67                .family         = NFPROTO_IPV4,
  68                .checkentry     = dscp_mt_check,
  69                .match          = dscp_mt,
  70                .matchsize      = sizeof(struct xt_dscp_info),
  71                .me             = THIS_MODULE,
  72        },
  73        {
  74                .name           = "dscp",
  75                .family         = NFPROTO_IPV6,
  76                .checkentry     = dscp_mt_check,
  77                .match          = dscp_mt6,
  78                .matchsize      = sizeof(struct xt_dscp_info),
  79                .me             = THIS_MODULE,
  80        },
  81        {
  82                .name           = "tos",
  83                .revision       = 1,
  84                .family         = NFPROTO_IPV4,
  85                .match          = tos_mt,
  86                .matchsize      = sizeof(struct xt_tos_match_info),
  87                .me             = THIS_MODULE,
  88        },
  89        {
  90                .name           = "tos",
  91                .revision       = 1,
  92                .family         = NFPROTO_IPV6,
  93                .match          = tos_mt,
  94                .matchsize      = sizeof(struct xt_tos_match_info),
  95                .me             = THIS_MODULE,
  96        },
  97};
  98
  99static int __init dscp_mt_init(void)
 100{
 101        return xt_register_matches(dscp_mt_reg, ARRAY_SIZE(dscp_mt_reg));
 102}
 103
 104static void __exit dscp_mt_exit(void)
 105{
 106        xt_unregister_matches(dscp_mt_reg, ARRAY_SIZE(dscp_mt_reg));
 107}
 108
 109module_init(dscp_mt_init);
 110module_exit(dscp_mt_exit);
 111