1 /* Shared library add-on to iptables to add CONNMARK target support.
2 *
3 * (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
4 * by Henrik Nordstrom <hno@marasystems.com>
5 *
6 * Version 1.1
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22 #include <stdbool.h>
23 #include <stdint.h>
24 #include <stdio.h>
25 #include <xtables.h>
26 #include <linux/netfilter/xt_CONNMARK.h>
27
28 struct xt_connmark_target_info {
29 unsigned long mark;
30 unsigned long mask;
31 uint8_t mode;
32 };
33
34 enum {
35 O_SET_MARK = 0,
36 O_SAVE_MARK,
37 O_RESTORE_MARK,
38 O_AND_MARK,
39 O_OR_MARK,
40 O_XOR_MARK,
41 O_SET_XMARK,
42 O_CTMASK,
43 O_NFMASK,
44 O_MASK,
45 F_SET_MARK = 1 << O_SET_MARK,
46 F_SAVE_MARK = 1 << O_SAVE_MARK,
47 F_RESTORE_MARK = 1 << O_RESTORE_MARK,
48 F_AND_MARK = 1 << O_AND_MARK,
49 F_OR_MARK = 1 << O_OR_MARK,
50 F_XOR_MARK = 1 << O_XOR_MARK,
51 F_SET_XMARK = 1 << O_SET_XMARK,
52 F_CTMASK = 1 << O_CTMASK,
53 F_NFMASK = 1 << O_NFMASK,
54 F_MASK = 1 << O_MASK,
55 F_OP_ANY = F_SET_MARK | F_SAVE_MARK | F_RESTORE_MARK |
56 F_AND_MARK | F_OR_MARK | F_XOR_MARK | F_SET_XMARK,
57 };
58
CONNMARK_help(void)59 static void CONNMARK_help(void)
60 {
61 printf(
62 "CONNMARK target options:\n"
63 " --set-mark value[/mask] Set conntrack mark value\n"
64 " --save-mark [--mask mask] Save the packet nfmark in the connection\n"
65 " --restore-mark [--mask mask] Restore saved nfmark value\n");
66 }
67
68 #define s struct xt_connmark_target_info
69 static const struct xt_option_entry CONNMARK_opts[] = {
70 {.name = "set-mark", .id = O_SET_MARK, .type = XTTYPE_MARKMASK32,
71 .excl = F_OP_ANY},
72 {.name = "save-mark", .id = O_SAVE_MARK, .type = XTTYPE_NONE,
73 .excl = F_OP_ANY},
74 {.name = "restore-mark", .id = O_RESTORE_MARK, .type = XTTYPE_NONE,
75 .excl = F_OP_ANY},
76 {.name = "mask", .id = O_MASK, .type = XTTYPE_UINT32},
77 XTOPT_TABLEEND,
78 };
79 #undef s
80
81 #define s struct xt_connmark_tginfo1
82 static const struct xt_option_entry connmark_tg_opts[] = {
83 {.name = "set-xmark", .id = O_SET_XMARK, .type = XTTYPE_MARKMASK32,
84 .excl = F_OP_ANY},
85 {.name = "set-mark", .id = O_SET_MARK, .type = XTTYPE_MARKMASK32,
86 .excl = F_OP_ANY},
87 {.name = "and-mark", .id = O_AND_MARK, .type = XTTYPE_UINT32,
88 .excl = F_OP_ANY},
89 {.name = "or-mark", .id = O_OR_MARK, .type = XTTYPE_UINT32,
90 .excl = F_OP_ANY},
91 {.name = "xor-mark", .id = O_XOR_MARK, .type = XTTYPE_UINT32,
92 .excl = F_OP_ANY},
93 {.name = "save-mark", .id = O_SAVE_MARK, .type = XTTYPE_NONE,
94 .excl = F_OP_ANY},
95 {.name = "restore-mark", .id = O_RESTORE_MARK, .type = XTTYPE_NONE,
96 .excl = F_OP_ANY},
97 {.name = "ctmask", .id = O_CTMASK, .type = XTTYPE_UINT32,
98 .excl = F_MASK, .flags = XTOPT_PUT, XTOPT_POINTER(s, ctmask)},
99 {.name = "nfmask", .id = O_NFMASK, .type = XTTYPE_UINT32,
100 .excl = F_MASK, .flags = XTOPT_PUT, XTOPT_POINTER(s, nfmask)},
101 {.name = "mask", .id = O_MASK, .type = XTTYPE_UINT32,
102 .excl = F_CTMASK | F_NFMASK},
103 XTOPT_TABLEEND,
104 };
105 #undef s
106
connmark_tg_help(void)107 static void connmark_tg_help(void)
108 {
109 printf(
110 "CONNMARK target options:\n"
111 " --set-xmark value[/ctmask] Zero mask bits and XOR ctmark with value\n"
112 " --save-mark [--ctmask mask] [--nfmask mask]\n"
113 " Copy ctmark to nfmark using masks\n"
114 " --restore-mark [--ctmask mask] [--nfmask mask]\n"
115 " Copy nfmark to ctmark using masks\n"
116 " --set-mark value[/mask] Set conntrack mark value\n"
117 " --save-mark [--mask mask] Save the packet nfmark in the connection\n"
118 " --restore-mark [--mask mask] Restore saved nfmark value\n"
119 " --and-mark value Binary AND the ctmark with bits\n"
120 " --or-mark value Binary OR the ctmark with bits\n"
121 " --xor-mark value Binary XOR the ctmark with bits\n"
122 );
123 }
124
connmark_tg_init(struct xt_entry_target * target)125 static void connmark_tg_init(struct xt_entry_target *target)
126 {
127 struct xt_connmark_tginfo1 *info = (void *)target->data;
128
129 /*
130 * Need these defaults for --save-mark/--restore-mark if no
131 * --ctmark or --nfmask is given.
132 */
133 info->ctmask = UINT32_MAX;
134 info->nfmask = UINT32_MAX;
135 }
136
CONNMARK_parse(struct xt_option_call * cb)137 static void CONNMARK_parse(struct xt_option_call *cb)
138 {
139 struct xt_connmark_target_info *markinfo = cb->data;
140
141 xtables_option_parse(cb);
142 switch (cb->entry->id) {
143 case O_SET_MARK:
144 markinfo->mode = XT_CONNMARK_SET;
145 markinfo->mark = cb->val.mark;
146 markinfo->mask = cb->val.mask;
147 break;
148 case O_SAVE_MARK:
149 markinfo->mode = XT_CONNMARK_SAVE;
150 break;
151 case O_RESTORE_MARK:
152 markinfo->mode = XT_CONNMARK_RESTORE;
153 break;
154 case O_MASK:
155 markinfo->mask = cb->val.u32;
156 break;
157 }
158 }
159
connmark_tg_parse(struct xt_option_call * cb)160 static void connmark_tg_parse(struct xt_option_call *cb)
161 {
162 struct xt_connmark_tginfo1 *info = cb->data;
163
164 xtables_option_parse(cb);
165 switch (cb->entry->id) {
166 case O_SET_XMARK:
167 info->mode = XT_CONNMARK_SET;
168 info->ctmark = cb->val.mark;
169 info->ctmask = cb->val.mask;
170 break;
171 case O_SET_MARK:
172 info->mode = XT_CONNMARK_SET;
173 info->ctmark = cb->val.mark;
174 info->ctmask = cb->val.mark | cb->val.mask;
175 break;
176 case O_AND_MARK:
177 info->mode = XT_CONNMARK_SET;
178 info->ctmark = 0;
179 info->ctmask = ~cb->val.u32;
180 break;
181 case O_OR_MARK:
182 info->mode = XT_CONNMARK_SET;
183 info->ctmark = cb->val.u32;
184 info->ctmask = cb->val.u32;
185 break;
186 case O_XOR_MARK:
187 info->mode = XT_CONNMARK_SET;
188 info->ctmark = cb->val.u32;
189 info->ctmask = 0;
190 break;
191 case O_SAVE_MARK:
192 info->mode = XT_CONNMARK_SAVE;
193 break;
194 case O_RESTORE_MARK:
195 info->mode = XT_CONNMARK_RESTORE;
196 break;
197 case O_MASK:
198 info->nfmask = info->ctmask = cb->val.u32;
199 break;
200 }
201 }
202
connmark_tg_check(struct xt_fcheck_call * cb)203 static void connmark_tg_check(struct xt_fcheck_call *cb)
204 {
205 if (!(cb->xflags & F_OP_ANY))
206 xtables_error(PARAMETER_PROBLEM,
207 "CONNMARK target: No operation specified");
208 }
209
210 static void
print_mark(unsigned long mark)211 print_mark(unsigned long mark)
212 {
213 printf("0x%lx", mark);
214 }
215
216 static void
print_mask(const char * text,unsigned long mask)217 print_mask(const char *text, unsigned long mask)
218 {
219 if (mask != 0xffffffffUL)
220 printf("%s0x%lx", text, mask);
221 }
222
CONNMARK_print(const void * ip,const struct xt_entry_target * target,int numeric)223 static void CONNMARK_print(const void *ip,
224 const struct xt_entry_target *target, int numeric)
225 {
226 const struct xt_connmark_target_info *markinfo =
227 (const struct xt_connmark_target_info *)target->data;
228 switch (markinfo->mode) {
229 case XT_CONNMARK_SET:
230 printf(" CONNMARK set ");
231 print_mark(markinfo->mark);
232 print_mask("/", markinfo->mask);
233 break;
234 case XT_CONNMARK_SAVE:
235 printf(" CONNMARK save ");
236 print_mask("mask ", markinfo->mask);
237 break;
238 case XT_CONNMARK_RESTORE:
239 printf(" CONNMARK restore ");
240 print_mask("mask ", markinfo->mask);
241 break;
242 default:
243 printf(" ERROR: UNKNOWN CONNMARK MODE");
244 break;
245 }
246 }
247
248 static void
connmark_tg_print(const void * ip,const struct xt_entry_target * target,int numeric)249 connmark_tg_print(const void *ip, const struct xt_entry_target *target,
250 int numeric)
251 {
252 const struct xt_connmark_tginfo1 *info = (const void *)target->data;
253
254 switch (info->mode) {
255 case XT_CONNMARK_SET:
256 if (info->ctmark == 0)
257 printf(" CONNMARK and 0x%x",
258 (unsigned int)(uint32_t)~info->ctmask);
259 else if (info->ctmark == info->ctmask)
260 printf(" CONNMARK or 0x%x", info->ctmark);
261 else if (info->ctmask == 0)
262 printf(" CONNMARK xor 0x%x", info->ctmark);
263 else if (info->ctmask == 0xFFFFFFFFU)
264 printf(" CONNMARK set 0x%x", info->ctmark);
265 else
266 printf(" CONNMARK xset 0x%x/0x%x",
267 info->ctmark, info->ctmask);
268 break;
269 case XT_CONNMARK_SAVE:
270 if (info->nfmask == UINT32_MAX && info->ctmask == UINT32_MAX)
271 printf(" CONNMARK save");
272 else if (info->nfmask == info->ctmask)
273 printf(" CONNMARK save mask 0x%x", info->nfmask);
274 else
275 printf(" CONNMARK save nfmask 0x%x ctmask ~0x%x",
276 info->nfmask, info->ctmask);
277 break;
278 case XT_CONNMARK_RESTORE:
279 if (info->ctmask == UINT32_MAX && info->nfmask == UINT32_MAX)
280 printf(" CONNMARK restore");
281 else if (info->ctmask == info->nfmask)
282 printf(" CONNMARK restore mask 0x%x", info->ctmask);
283 else
284 printf(" CONNMARK restore ctmask 0x%x nfmask ~0x%x",
285 info->ctmask, info->nfmask);
286 break;
287
288 default:
289 printf(" ERROR: UNKNOWN CONNMARK MODE");
290 break;
291 }
292 }
293
CONNMARK_save(const void * ip,const struct xt_entry_target * target)294 static void CONNMARK_save(const void *ip, const struct xt_entry_target *target)
295 {
296 const struct xt_connmark_target_info *markinfo =
297 (const struct xt_connmark_target_info *)target->data;
298
299 switch (markinfo->mode) {
300 case XT_CONNMARK_SET:
301 printf(" --set-mark ");
302 print_mark(markinfo->mark);
303 print_mask("/", markinfo->mask);
304 break;
305 case XT_CONNMARK_SAVE:
306 printf(" --save-mark ");
307 print_mask("--mask ", markinfo->mask);
308 break;
309 case XT_CONNMARK_RESTORE:
310 printf(" --restore-mark ");
311 print_mask("--mask ", markinfo->mask);
312 break;
313 default:
314 printf(" ERROR: UNKNOWN CONNMARK MODE");
315 break;
316 }
317 }
318
CONNMARK_init(struct xt_entry_target * t)319 static void CONNMARK_init(struct xt_entry_target *t)
320 {
321 struct xt_connmark_target_info *markinfo
322 = (struct xt_connmark_target_info *)t->data;
323
324 markinfo->mask = 0xffffffffUL;
325 }
326
327 static void
connmark_tg_save(const void * ip,const struct xt_entry_target * target)328 connmark_tg_save(const void *ip, const struct xt_entry_target *target)
329 {
330 const struct xt_connmark_tginfo1 *info = (const void *)target->data;
331
332 switch (info->mode) {
333 case XT_CONNMARK_SET:
334 printf(" --set-xmark 0x%x/0x%x", info->ctmark, info->ctmask);
335 break;
336 case XT_CONNMARK_SAVE:
337 printf(" --save-mark --nfmask 0x%x --ctmask 0x%x",
338 info->nfmask, info->ctmask);
339 break;
340 case XT_CONNMARK_RESTORE:
341 printf(" --restore-mark --nfmask 0x%x --ctmask 0x%x",
342 info->nfmask, info->ctmask);
343 break;
344 default:
345 printf(" ERROR: UNKNOWN CONNMARK MODE");
346 break;
347 }
348 }
349
350 static struct xtables_target connmark_tg_reg[] = {
351 {
352 .family = NFPROTO_UNSPEC,
353 .name = "CONNMARK",
354 .revision = 0,
355 .version = XTABLES_VERSION,
356 .size = XT_ALIGN(sizeof(struct xt_connmark_target_info)),
357 .userspacesize = XT_ALIGN(sizeof(struct xt_connmark_target_info)),
358 .help = CONNMARK_help,
359 .init = CONNMARK_init,
360 .print = CONNMARK_print,
361 .save = CONNMARK_save,
362 .x6_parse = CONNMARK_parse,
363 .x6_fcheck = connmark_tg_check,
364 .x6_options = CONNMARK_opts,
365 },
366 {
367 .version = XTABLES_VERSION,
368 .name = "CONNMARK",
369 .revision = 1,
370 .family = NFPROTO_UNSPEC,
371 .size = XT_ALIGN(sizeof(struct xt_connmark_tginfo1)),
372 .userspacesize = XT_ALIGN(sizeof(struct xt_connmark_tginfo1)),
373 .help = connmark_tg_help,
374 .init = connmark_tg_init,
375 .print = connmark_tg_print,
376 .save = connmark_tg_save,
377 .x6_parse = connmark_tg_parse,
378 .x6_fcheck = connmark_tg_check,
379 .x6_options = connmark_tg_opts,
380 },
381 };
382
_init(void)383 void _init(void)
384 {
385 xtables_register_targets(connmark_tg_reg, ARRAY_SIZE(connmark_tg_reg));
386 }
387