57c6d55e33d3a04568e564c796c5b70a25e12766
[linux-2.6.git] / net / netfilter / xt_MARK.c
1 /* This is a module which is used for setting the NFMARK field of an skb. */
2
3 /* (C) 1999-2001 Marc Boucher <marc@mbsi.ca>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  */
9
10 #include <linux/module.h>
11 #include <linux/skbuff.h>
12 #include <linux/ip.h>
13 #include <net/checksum.h>
14
15 #include <linux/netfilter/x_tables.h>
16 #include <linux/netfilter/xt_MARK.h>
17
18 MODULE_LICENSE("GPL");
19 MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
20 MODULE_DESCRIPTION("ip[6]tables MARK modification module");
21 MODULE_ALIAS("ipt_MARK");
22 MODULE_ALIAS("ip6t_MARK");
23
24 static unsigned int
25 mark_tg_v0(struct sk_buff *skb, const struct net_device *in,
26            const struct net_device *out, unsigned int hooknum,
27            const struct xt_target *target, const void *targinfo)
28 {
29         const struct xt_mark_target_info *markinfo = targinfo;
30
31         skb->mark = markinfo->mark;
32         return XT_CONTINUE;
33 }
34
35 static unsigned int
36 mark_tg(struct sk_buff *skb, const struct net_device *in,
37         const struct net_device *out, unsigned int hooknum,
38         const struct xt_target *target, const void *targinfo)
39 {
40         const struct xt_mark_target_info_v1 *markinfo = targinfo;
41         int mark = 0;
42
43         switch (markinfo->mode) {
44         case XT_MARK_SET:
45                 mark = markinfo->mark;
46                 break;
47
48         case XT_MARK_AND:
49                 mark = skb->mark & markinfo->mark;
50                 break;
51
52         case XT_MARK_OR:
53                 mark = skb->mark | markinfo->mark;
54                 break;
55         }
56
57         skb->mark = mark;
58         return XT_CONTINUE;
59 }
60
61 static bool
62 mark_tg_check_v0(const char *tablename, const void *entry,
63                  const struct xt_target *target, void *targinfo,
64                  unsigned int hook_mask)
65 {
66         const struct xt_mark_target_info *markinfo = targinfo;
67
68         if (markinfo->mark > 0xffffffff) {
69                 printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n");
70                 return false;
71         }
72         return true;
73 }
74
75 static bool
76 mark_tg_check(const char *tablename, const void *entry,
77               const struct xt_target *target, void *targinfo,
78               unsigned int hook_mask)
79 {
80         const struct xt_mark_target_info_v1 *markinfo = targinfo;
81
82         if (markinfo->mode != XT_MARK_SET
83             && markinfo->mode != XT_MARK_AND
84             && markinfo->mode != XT_MARK_OR) {
85                 printk(KERN_WARNING "MARK: unknown mode %u\n",
86                        markinfo->mode);
87                 return false;
88         }
89         if (markinfo->mark > 0xffffffff) {
90                 printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n");
91                 return false;
92         }
93         return true;
94 }
95
96 #ifdef CONFIG_COMPAT
97 struct compat_xt_mark_target_info {
98         compat_ulong_t  mark;
99 };
100
101 static void mark_tg_compat_from_user(void *dst, void *src)
102 {
103         const struct compat_xt_mark_target_info *cm = src;
104         struct xt_mark_target_info m = {
105                 .mark   = cm->mark,
106         };
107         memcpy(dst, &m, sizeof(m));
108 }
109
110 static int mark_tg_compat_to_user(void __user *dst, void *src)
111 {
112         const struct xt_mark_target_info *m = src;
113         struct compat_xt_mark_target_info cm = {
114                 .mark   = m->mark,
115         };
116         return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0;
117 }
118
119 struct compat_xt_mark_target_info_v1 {
120         compat_ulong_t  mark;
121         u_int8_t        mode;
122         u_int8_t        __pad1;
123         u_int16_t       __pad2;
124 };
125
126 static void mark_tg_compat_from_user_v1(void *dst, void *src)
127 {
128         const struct compat_xt_mark_target_info_v1 *cm = src;
129         struct xt_mark_target_info_v1 m = {
130                 .mark   = cm->mark,
131                 .mode   = cm->mode,
132         };
133         memcpy(dst, &m, sizeof(m));
134 }
135
136 static int mark_tg_compat_to_user_v1(void __user *dst, void *src)
137 {
138         const struct xt_mark_target_info_v1 *m = src;
139         struct compat_xt_mark_target_info_v1 cm = {
140                 .mark   = m->mark,
141                 .mode   = m->mode,
142         };
143         return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0;
144 }
145 #endif /* CONFIG_COMPAT */
146
147 static struct xt_target mark_tg_reg[] __read_mostly = {
148         {
149                 .name           = "MARK",
150                 .family         = AF_INET,
151                 .revision       = 0,
152                 .checkentry     = mark_tg_check_v0,
153                 .target         = mark_tg_v0,
154                 .targetsize     = sizeof(struct xt_mark_target_info),
155 #ifdef CONFIG_COMPAT
156                 .compatsize     = sizeof(struct compat_xt_mark_target_info),
157                 .compat_from_user = mark_tg_compat_from_user,
158                 .compat_to_user = mark_tg_compat_to_user,
159 #endif
160                 .table          = "mangle",
161                 .me             = THIS_MODULE,
162         },
163         {
164                 .name           = "MARK",
165                 .family         = AF_INET,
166                 .revision       = 1,
167                 .checkentry     = mark_tg_check,
168                 .target         = mark_tg,
169                 .targetsize     = sizeof(struct xt_mark_target_info_v1),
170 #ifdef CONFIG_COMPAT
171                 .compatsize     = sizeof(struct compat_xt_mark_target_info_v1),
172                 .compat_from_user = mark_tg_compat_from_user_v1,
173                 .compat_to_user = mark_tg_compat_to_user_v1,
174 #endif
175                 .table          = "mangle",
176                 .me             = THIS_MODULE,
177         },
178         {
179                 .name           = "MARK",
180                 .family         = AF_INET6,
181                 .revision       = 0,
182                 .checkentry     = mark_tg_check_v0,
183                 .target         = mark_tg_v0,
184                 .targetsize     = sizeof(struct xt_mark_target_info),
185 #ifdef CONFIG_COMPAT
186                 .compatsize     = sizeof(struct compat_xt_mark_target_info),
187                 .compat_from_user = mark_tg_compat_from_user,
188                 .compat_to_user = mark_tg_compat_to_user,
189 #endif
190                 .table          = "mangle",
191                 .me             = THIS_MODULE,
192         },
193         {
194                 .name           = "MARK",
195                 .family         = AF_INET6,
196                 .revision       = 1,
197                 .checkentry     = mark_tg_check,
198                 .target         = mark_tg,
199                 .targetsize     = sizeof(struct xt_mark_target_info_v1),
200 #ifdef CONFIG_COMPAT
201                 .compatsize     = sizeof(struct compat_xt_mark_target_info_v1),
202                 .compat_from_user = mark_tg_compat_from_user_v1,
203                 .compat_to_user = mark_tg_compat_to_user_v1,
204 #endif
205                 .table          = "mangle",
206                 .me             = THIS_MODULE,
207         },
208 };
209
210 static int __init mark_tg_init(void)
211 {
212         return xt_register_targets(mark_tg_reg, ARRAY_SIZE(mark_tg_reg));
213 }
214
215 static void __exit mark_tg_exit(void)
216 {
217         xt_unregister_targets(mark_tg_reg, ARRAY_SIZE(mark_tg_reg));
218 }
219
220 module_init(mark_tg_init);
221 module_exit(mark_tg_exit);