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