~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/netfilter/xt_ecn.c

Version: ~ [ linux-5.18 ] ~ [ linux-5.17.9 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.41 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.117 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.195 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.244 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.280 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.315 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.302 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 /*
  3  * Xtables module for matching the value of the IPv4/IPv6 and TCP ECN bits
  4  *
  5  * (C) 2002 by Harald Welte <laforge@gnumonks.org>
  6  * (C) 2011 Patrick McHardy <kaber@trash.net>
  7  */
  8 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  9 #include <linux/in.h>
 10 #include <linux/ip.h>
 11 #include <net/ip.h>
 12 #include <linux/module.h>
 13 #include <linux/skbuff.h>
 14 #include <linux/tcp.h>
 15 
 16 #include <linux/netfilter/x_tables.h>
 17 #include <linux/netfilter/xt_ecn.h>
 18 #include <linux/netfilter_ipv4/ip_tables.h>
 19 #include <linux/netfilter_ipv6/ip6_tables.h>
 20 
 21 MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
 22 MODULE_DESCRIPTION("Xtables: Explicit Congestion Notification (ECN) flag match");
 23 MODULE_LICENSE("GPL");
 24 MODULE_ALIAS("ipt_ecn");
 25 MODULE_ALIAS("ip6t_ecn");
 26 
 27 static bool match_tcp(const struct sk_buff *skb, struct xt_action_param *par)
 28 {
 29         const struct xt_ecn_info *einfo = par->matchinfo;
 30         struct tcphdr _tcph;
 31         const struct tcphdr *th;
 32 
 33         /* In practice, TCP match does this, so can't fail.  But let's
 34          * be good citizens.
 35          */
 36         th = skb_header_pointer(skb, par->thoff, sizeof(_tcph), &_tcph);
 37         if (th == NULL)
 38                 return false;
 39 
 40         if (einfo->operation & XT_ECN_OP_MATCH_ECE) {
 41                 if (einfo->invert & XT_ECN_OP_MATCH_ECE) {
 42                         if (th->ece == 1)
 43                                 return false;
 44                 } else {
 45                         if (th->ece == 0)
 46                                 return false;
 47                 }
 48         }
 49 
 50         if (einfo->operation & XT_ECN_OP_MATCH_CWR) {
 51                 if (einfo->invert & XT_ECN_OP_MATCH_CWR) {
 52                         if (th->cwr == 1)
 53                                 return false;
 54                 } else {
 55                         if (th->cwr == 0)
 56                                 return false;
 57                 }
 58         }
 59 
 60         return true;
 61 }
 62 
 63 static inline bool match_ip(const struct sk_buff *skb,
 64                             const struct xt_ecn_info *einfo)
 65 {
 66         return ((ip_hdr(skb)->tos & XT_ECN_IP_MASK) == einfo->ip_ect) ^
 67                !!(einfo->invert & XT_ECN_OP_MATCH_IP);
 68 }
 69 
 70 static bool ecn_mt4(const struct sk_buff *skb, struct xt_action_param *par)
 71 {
 72         const struct xt_ecn_info *info = par->matchinfo;
 73 
 74         if (info->operation & XT_ECN_OP_MATCH_IP && !match_ip(skb, info))
 75                 return false;
 76 
 77         if (info->operation & (XT_ECN_OP_MATCH_ECE | XT_ECN_OP_MATCH_CWR) &&
 78             !match_tcp(skb, par))
 79                 return false;
 80 
 81         return true;
 82 }
 83 
 84 static int ecn_mt_check4(const struct xt_mtchk_param *par)
 85 {
 86         const struct xt_ecn_info *info = par->matchinfo;
 87         const struct ipt_ip *ip = par->entryinfo;
 88 
 89         if (info->operation & XT_ECN_OP_MATCH_MASK)
 90                 return -EINVAL;
 91 
 92         if (info->invert & XT_ECN_OP_MATCH_MASK)
 93                 return -EINVAL;
 94 
 95         if (info->operation & (XT_ECN_OP_MATCH_ECE | XT_ECN_OP_MATCH_CWR) &&
 96             (ip->proto != IPPROTO_TCP || ip->invflags & IPT_INV_PROTO)) {
 97                 pr_info_ratelimited("cannot match TCP bits for non-tcp packets\n");
 98                 return -EINVAL;
 99         }
100 
101         return 0;
102 }
103 
104 static inline bool match_ipv6(const struct sk_buff *skb,
105                               const struct xt_ecn_info *einfo)
106 {
107         return (((ipv6_hdr(skb)->flow_lbl[0] >> 4) & XT_ECN_IP_MASK) ==
108                 einfo->ip_ect) ^
109                !!(einfo->invert & XT_ECN_OP_MATCH_IP);
110 }
111 
112 static bool ecn_mt6(const struct sk_buff *skb, struct xt_action_param *par)
113 {
114         const struct xt_ecn_info *info = par->matchinfo;
115 
116         if (info->operation & XT_ECN_OP_MATCH_IP && !match_ipv6(skb, info))
117                 return false;
118 
119         if (info->operation & (XT_ECN_OP_MATCH_ECE | XT_ECN_OP_MATCH_CWR) &&
120             !match_tcp(skb, par))
121                 return false;
122 
123         return true;
124 }
125 
126 static int ecn_mt_check6(const struct xt_mtchk_param *par)
127 {
128         const struct xt_ecn_info *info = par->matchinfo;
129         const struct ip6t_ip6 *ip = par->entryinfo;
130 
131         if (info->operation & XT_ECN_OP_MATCH_MASK)
132                 return -EINVAL;
133 
134         if (info->invert & XT_ECN_OP_MATCH_MASK)
135                 return -EINVAL;
136 
137         if (info->operation & (XT_ECN_OP_MATCH_ECE | XT_ECN_OP_MATCH_CWR) &&
138             (ip->proto != IPPROTO_TCP || ip->invflags & IP6T_INV_PROTO)) {
139                 pr_info_ratelimited("cannot match TCP bits for non-tcp packets\n");
140                 return -EINVAL;
141         }
142 
143         return 0;
144 }
145 
146 static struct xt_match ecn_mt_reg[] __read_mostly = {
147         {
148                 .name           = "ecn",
149                 .family         = NFPROTO_IPV4,
150                 .match          = ecn_mt4,
151                 .matchsize      = sizeof(struct xt_ecn_info),
152                 .checkentry     = ecn_mt_check4,
153                 .me             = THIS_MODULE,
154         },
155         {
156                 .name           = "ecn",
157                 .family         = NFPROTO_IPV6,
158                 .match          = ecn_mt6,
159                 .matchsize      = sizeof(struct xt_ecn_info),
160                 .checkentry     = ecn_mt_check6,
161                 .me             = THIS_MODULE,
162         },
163 };
164 
165 static int __init ecn_mt_init(void)
166 {
167         return xt_register_matches(ecn_mt_reg, ARRAY_SIZE(ecn_mt_reg));
168 }
169 
170 static void __exit ecn_mt_exit(void)
171 {
172         xt_unregister_matches(ecn_mt_reg, ARRAY_SIZE(ecn_mt_reg));
173 }
174 
175 module_init(ecn_mt_init);
176 module_exit(ecn_mt_exit);
177 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp