Merge master.kernel.org:/pub/scm/linux/kernel/git/tmlind/linux-omap-upstream into...
[linux-2.6] / net / netfilter / xt_dscp.c
1 /* IP tables module for matching the value of the IPv4/IPv6 DSCP field
2  *
3  * xt_dscp.c,v 1.3 2002/08/05 19:00:21 laforge Exp
4  *
5  * (C) 2002 by Harald Welte <laforge@netfilter.org>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  */
11
12 #include <linux/module.h>
13 #include <linux/skbuff.h>
14 #include <linux/ip.h>
15 #include <linux/ipv6.h>
16 #include <net/dsfield.h>
17
18 #include <linux/netfilter/xt_dscp.h>
19 #include <linux/netfilter/x_tables.h>
20
21 MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
22 MODULE_DESCRIPTION("x_tables DSCP matching module");
23 MODULE_LICENSE("GPL");
24 MODULE_ALIAS("ipt_dscp");
25 MODULE_ALIAS("ip6t_dscp");
26
27 static int match(const struct sk_buff *skb,
28                  const struct net_device *in,
29                  const struct net_device *out,
30                  const struct xt_match *match,
31                  const void *matchinfo,
32                  int offset,
33                  unsigned int protoff,
34                  int *hotdrop)
35 {
36         const struct xt_dscp_info *info = matchinfo;
37         u_int8_t dscp = ipv4_get_dsfield(skb->nh.iph) >> XT_DSCP_SHIFT;
38
39         return (dscp == info->dscp) ^ !!info->invert;
40 }
41
42 static int match6(const struct sk_buff *skb,
43                   const struct net_device *in,
44                   const struct net_device *out,
45                   const struct xt_match *match,
46                   const void *matchinfo,
47                   int offset,
48                   unsigned int protoff,
49                   int *hotdrop)
50 {
51         const struct xt_dscp_info *info = matchinfo;
52         u_int8_t dscp = ipv6_get_dsfield(skb->nh.ipv6h) >> XT_DSCP_SHIFT;
53
54         return (dscp == info->dscp) ^ !!info->invert;
55 }
56
57 static int checkentry(const char *tablename,
58                       const void *info,
59                       const struct xt_match *match,
60                       void *matchinfo,
61                       unsigned int hook_mask)
62 {
63         const u_int8_t dscp = ((struct xt_dscp_info *)matchinfo)->dscp;
64
65         if (dscp > XT_DSCP_MAX) {
66                 printk(KERN_ERR "xt_dscp: dscp %x out of range\n", dscp);
67                 return 0;
68         }
69
70         return 1;
71 }
72
73 static struct xt_match xt_dscp_match[] = {
74         {
75                 .name           = "dscp",
76                 .family         = AF_INET,
77                 .checkentry     = checkentry,
78                 .match          = match,
79                 .matchsize      = sizeof(struct xt_dscp_info),
80                 .me             = THIS_MODULE,
81         },
82         {
83                 .name           = "dscp",
84                 .family         = AF_INET6,
85                 .checkentry     = checkentry,
86                 .match          = match6,
87                 .matchsize      = sizeof(struct xt_dscp_info),
88                 .me             = THIS_MODULE,
89         },
90 };
91
92 static int __init xt_dscp_match_init(void)
93 {
94         return xt_register_matches(xt_dscp_match, ARRAY_SIZE(xt_dscp_match));
95 }
96
97 static void __exit xt_dscp_match_fini(void)
98 {
99         xt_unregister_matches(xt_dscp_match, ARRAY_SIZE(xt_dscp_match));
100 }
101
102 module_init(xt_dscp_match_init);
103 module_exit(xt_dscp_match_fini);