libxt_CONNMARK.c revision f2a77520693f0a6dd1df1f87be4b81913961c1f5
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 <stdio.h> 23#include <string.h> 24#include <stdlib.h> 25#include <getopt.h> 26 27#include <xtables.h> 28#include <linux/netfilter/x_tables.h> 29#include <linux/netfilter/xt_CONNMARK.h> 30 31enum { 32 F_MARK = 1 << 0, 33 F_SR_MARK = 1 << 1, 34}; 35 36static void CONNMARK_help(void) 37{ 38 printf( 39"CONNMARK target options:\n" 40" --set-mark value[/mask] Set conntrack mark value\n" 41" --save-mark [--mask mask] Save the packet nfmark in the connection\n" 42" --restore-mark [--mask mask] Restore saved nfmark value\n"); 43} 44 45static const struct option CONNMARK_opts[] = { 46 { "set-mark", 1, NULL, '1' }, 47 { "save-mark", 0, NULL, '2' }, 48 { "restore-mark", 0, NULL, '3' }, 49 { "mask", 1, NULL, '4' }, 50 { .name = NULL } 51}; 52 53static const struct option connmark_tg_opts[] = { 54 {.name = "set-xmark", .has_arg = true, .val = '='}, 55 {.name = "set-mark", .has_arg = true, .val = '-'}, 56 {.name = "and-mark", .has_arg = true, .val = '&'}, 57 {.name = "or-mark", .has_arg = true, .val = '|'}, 58 {.name = "xor-mark", .has_arg = true, .val = '^'}, 59 {.name = "save-mark", .has_arg = false, .val = 'S'}, 60 {.name = "restore-mark", .has_arg = false, .val = 'R'}, 61 {.name = "ctmask", .has_arg = true, .val = 'c'}, 62 {.name = "nfmask", .has_arg = true, .val = 'n'}, 63 {.name = "mask", .has_arg = true, .val = 'm'}, 64 {.name = NULL}, 65}; 66 67static void connmark_tg_help(void) 68{ 69 printf( 70"CONNMARK target options:\n" 71" --set-xmark value[/ctmask] Zero mask bits and XOR ctmark with value\n" 72" --save-mark [--ctmask mask] [--nfmask mask]\n" 73" Copy ctmark to nfmark using masks\n" 74" --restore-mark [--ctmask mask] [--nfmask mask]\n" 75" Copy nfmark to ctmark using masks\n" 76" --set-mark value[/mask] Set conntrack mark value\n" 77" --save-mark [--mask mask] Save the packet nfmark in the connection\n" 78" --restore-mark [--mask mask] Restore saved nfmark value\n" 79" --and-mark value Binary AND the ctmark with bits\n" 80" --or-mark value Binary OR the ctmark with bits\n" 81" --xor-mark value Binary XOR the ctmark with bits\n" 82); 83} 84 85static void connmark_tg_init(struct xt_entry_target *target) 86{ 87 struct xt_connmark_tginfo1 *info = (void *)target->data; 88 89 /* 90 * Need these defaults for --save-mark/--restore-mark if no 91 * --ctmark or --nfmask is given. 92 */ 93 info->ctmask = UINT32_MAX; 94 info->nfmask = UINT32_MAX; 95} 96 97static int 98CONNMARK_parse(int c, char **argv, int invert, unsigned int *flags, 99 const void *entry, struct xt_entry_target **target) 100{ 101 struct xt_connmark_target_info *markinfo 102 = (struct xt_connmark_target_info *)(*target)->data; 103 104 switch (c) { 105 char *end; 106 case '1': 107 markinfo->mode = XT_CONNMARK_SET; 108 109 markinfo->mark = strtoul(optarg, &end, 0); 110 if (*end == '/' && end[1] != '\0') 111 markinfo->mask = strtoul(end+1, &end, 0); 112 113 if (*end != '\0' || end == optarg) 114 xtables_error(PARAMETER_PROBLEM, "Bad MARK value \"%s\"", optarg); 115 if (*flags) 116 xtables_error(PARAMETER_PROBLEM, 117 "CONNMARK target: Can't specify --set-mark twice"); 118 *flags = 1; 119 break; 120 case '2': 121 markinfo->mode = XT_CONNMARK_SAVE; 122 if (*flags) 123 xtables_error(PARAMETER_PROBLEM, 124 "CONNMARK target: Can't specify --save-mark twice"); 125 *flags = 1; 126 break; 127 case '3': 128 markinfo->mode = XT_CONNMARK_RESTORE; 129 if (*flags) 130 xtables_error(PARAMETER_PROBLEM, 131 "CONNMARK target: Can't specify --restore-mark twice"); 132 *flags = 1; 133 break; 134 case '4': 135 if (!*flags) 136 xtables_error(PARAMETER_PROBLEM, 137 "CONNMARK target: Can't specify --mask without a operation"); 138 markinfo->mask = strtoul(optarg, &end, 0); 139 140 if (*end != '\0' || end == optarg) 141 xtables_error(PARAMETER_PROBLEM, "Bad MASK value \"%s\"", optarg); 142 break; 143 default: 144 return 0; 145 } 146 147 return 1; 148} 149 150static int connmark_tg_parse(int c, char **argv, int invert, 151 unsigned int *flags, const void *entry, 152 struct xt_entry_target **target) 153{ 154 struct xt_connmark_tginfo1 *info = (void *)(*target)->data; 155 unsigned int value, mask = UINT32_MAX; 156 char *end; 157 158 switch (c) { 159 case '=': /* --set-xmark */ 160 case '-': /* --set-mark */ 161 xtables_param_act(XTF_ONE_ACTION, "CONNMARK", *flags & F_MARK); 162 if (!xtables_strtoui(optarg, &end, &value, 0, UINT32_MAX)) 163 xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--set-xmark/--set-mark", optarg); 164 if (*end == '/') 165 if (!xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX)) 166 xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--set-xmark/--set-mark", optarg); 167 if (*end != '\0') 168 xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--set-xmark/--set-mark", optarg); 169 info->mode = XT_CONNMARK_SET; 170 info->ctmark = value; 171 info->ctmask = mask; 172 if (c == '-') 173 info->ctmask |= value; 174 *flags |= F_MARK; 175 return true; 176 177 case '&': /* --and-mark */ 178 xtables_param_act(XTF_ONE_ACTION, "CONNMARK", *flags & F_MARK); 179 if (!xtables_strtoui(optarg, NULL, &mask, 0, UINT32_MAX)) 180 xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--and-mark", optarg); 181 info->mode = XT_CONNMARK_SET; 182 info->ctmark = 0; 183 info->ctmask = ~mask; 184 *flags |= F_MARK; 185 return true; 186 187 case '|': /* --or-mark */ 188 xtables_param_act(XTF_ONE_ACTION, "CONNMARK", *flags & F_MARK); 189 if (!xtables_strtoui(optarg, NULL, &value, 0, UINT32_MAX)) 190 xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--or-mark", optarg); 191 info->mode = XT_CONNMARK_SET; 192 info->ctmark = value; 193 info->ctmask = value; 194 *flags |= F_MARK; 195 return true; 196 197 case '^': /* --xor-mark */ 198 xtables_param_act(XTF_ONE_ACTION, "CONNMARK", *flags & F_MARK); 199 if (!xtables_strtoui(optarg, NULL, &value, 0, UINT32_MAX)) 200 xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--xor-mark", optarg); 201 info->mode = XT_CONNMARK_SET; 202 info->ctmark = value; 203 info->ctmask = 0; 204 *flags |= F_MARK; 205 return true; 206 207 case 'S': /* --save-mark */ 208 xtables_param_act(XTF_ONE_ACTION, "CONNMARK", *flags & F_MARK); 209 info->mode = XT_CONNMARK_SAVE; 210 *flags |= F_MARK | F_SR_MARK; 211 return true; 212 213 case 'R': /* --restore-mark */ 214 xtables_param_act(XTF_ONE_ACTION, "CONNMARK", *flags & F_MARK); 215 info->mode = XT_CONNMARK_RESTORE; 216 *flags |= F_MARK | F_SR_MARK; 217 return true; 218 219 case 'n': /* --nfmask */ 220 if (!(*flags & F_SR_MARK)) 221 xtables_error(PARAMETER_PROBLEM, "CONNMARK: --save-mark " 222 "or --restore-mark is required for " 223 "--nfmask"); 224 if (!xtables_strtoui(optarg, NULL, &value, 0, UINT32_MAX)) 225 xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--nfmask", optarg); 226 info->nfmask = value; 227 return true; 228 229 case 'c': /* --ctmask */ 230 if (!(*flags & F_SR_MARK)) 231 xtables_error(PARAMETER_PROBLEM, "CONNMARK: --save-mark " 232 "or --restore-mark is required for " 233 "--ctmask"); 234 if (!xtables_strtoui(optarg, NULL, &value, 0, UINT32_MAX)) 235 xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--ctmask", optarg); 236 info->ctmask = value; 237 return true; 238 239 case 'm': /* --mask */ 240 if (!(*flags & F_SR_MARK)) 241 xtables_error(PARAMETER_PROBLEM, "CONNMARK: --save-mark " 242 "or --restore-mark is required for " 243 "--mask"); 244 if (!xtables_strtoui(optarg, NULL, &value, 0, UINT32_MAX)) 245 xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--mask", optarg); 246 info->nfmask = info->ctmask = value; 247 return true; 248 } 249 250 return false; 251} 252 253static void connmark_tg_check(unsigned int flags) 254{ 255 if (!flags) 256 xtables_error(PARAMETER_PROBLEM, 257 "CONNMARK target: No operation specified"); 258} 259 260static void 261print_mark(unsigned long mark) 262{ 263 printf("0x%lx", mark); 264} 265 266static void 267print_mask(const char *text, unsigned long mask) 268{ 269 if (mask != 0xffffffffUL) 270 printf("%s0x%lx", text, mask); 271} 272 273static void CONNMARK_print(const void *ip, 274 const struct xt_entry_target *target, int numeric) 275{ 276 const struct xt_connmark_target_info *markinfo = 277 (const struct xt_connmark_target_info *)target->data; 278 switch (markinfo->mode) { 279 case XT_CONNMARK_SET: 280 printf("CONNMARK set "); 281 print_mark(markinfo->mark); 282 print_mask("/", markinfo->mask); 283 printf(" "); 284 break; 285 case XT_CONNMARK_SAVE: 286 printf("CONNMARK save "); 287 print_mask("mask ", markinfo->mask); 288 printf(" "); 289 break; 290 case XT_CONNMARK_RESTORE: 291 printf("CONNMARK restore "); 292 print_mask("mask ", markinfo->mask); 293 break; 294 default: 295 printf("ERROR: UNKNOWN CONNMARK MODE "); 296 break; 297 } 298} 299 300static void 301connmark_tg_print(const void *ip, const struct xt_entry_target *target, 302 int numeric) 303{ 304 const struct xt_connmark_tginfo1 *info = (const void *)target->data; 305 306 switch (info->mode) { 307 case XT_CONNMARK_SET: 308 if (info->ctmark == 0) 309 printf("CONNMARK and 0x%x ", 310 (unsigned int)(u_int32_t)~info->ctmask); 311 else if (info->ctmark == info->ctmask) 312 printf("CONNMARK or 0x%x ", info->ctmark); 313 else if (info->ctmask == 0) 314 printf("CONNMARK xor 0x%x ", info->ctmark); 315 else 316 printf("CONNMARK xset 0x%x/0x%x ", 317 info->ctmark, info->ctmask); 318 break; 319 case XT_CONNMARK_SAVE: 320 if (info->nfmask == UINT32_MAX && info->ctmask == UINT32_MAX) 321 printf("CONNMARK save "); 322 else if (info->nfmask == info->ctmask) 323 printf("CONNMARK save mask 0x%x ", info->nfmask); 324 else 325 printf("CONNMARK save nfmask 0x%x ctmask ~0x%x ", 326 info->nfmask, info->ctmask); 327 break; 328 case XT_CONNMARK_RESTORE: 329 if (info->ctmask == UINT32_MAX && info->nfmask == UINT32_MAX) 330 printf("CONNMARK restore "); 331 else if (info->ctmask == info->nfmask) 332 printf("CONNMARK restore mask 0x%x ", info->ctmask); 333 else 334 printf("CONNMARK restore ctmask 0x%x nfmask ~0x%x ", 335 info->ctmask, info->nfmask); 336 break; 337 338 default: 339 printf("ERROR: UNKNOWN CONNMARK MODE"); 340 break; 341 } 342} 343 344static void CONNMARK_save(const void *ip, const struct xt_entry_target *target) 345{ 346 const struct xt_connmark_target_info *markinfo = 347 (const struct xt_connmark_target_info *)target->data; 348 349 switch (markinfo->mode) { 350 case XT_CONNMARK_SET: 351 printf("--set-mark "); 352 print_mark(markinfo->mark); 353 print_mask("/", markinfo->mask); 354 printf(" "); 355 break; 356 case XT_CONNMARK_SAVE: 357 printf("--save-mark "); 358 print_mask("--mask ", markinfo->mask); 359 break; 360 case XT_CONNMARK_RESTORE: 361 printf("--restore-mark "); 362 print_mask("--mask ", markinfo->mask); 363 break; 364 default: 365 printf("ERROR: UNKNOWN CONNMARK MODE "); 366 break; 367 } 368} 369 370static void CONNMARK_init(struct xt_entry_target *t) 371{ 372 struct xt_connmark_target_info *markinfo 373 = (struct xt_connmark_target_info *)t->data; 374 375 markinfo->mask = 0xffffffffUL; 376} 377 378static void 379connmark_tg_save(const void *ip, const struct xt_entry_target *target) 380{ 381 const struct xt_connmark_tginfo1 *info = (const void *)target->data; 382 383 switch (info->mode) { 384 case XT_CONNMARK_SET: 385 printf("--set-xmark 0x%x/0x%x ", info->ctmark, info->ctmask); 386 break; 387 case XT_CONNMARK_SAVE: 388 printf("--save-mark --nfmask 0x%x --ctmask 0x%x ", 389 info->nfmask, info->ctmask); 390 break; 391 case XT_CONNMARK_RESTORE: 392 printf("--restore-mark --nfmask 0x%x --ctmask 0x%x ", 393 info->nfmask, info->ctmask); 394 break; 395 default: 396 printf("ERROR: UNKNOWN CONNMARK MODE"); 397 break; 398 } 399} 400 401static struct xtables_target connmark_tg_reg[] = { 402 { 403 .family = NFPROTO_UNSPEC, 404 .name = "CONNMARK", 405 .revision = 0, 406 .version = XTABLES_VERSION, 407 .size = XT_ALIGN(sizeof(struct xt_connmark_target_info)), 408 .userspacesize = XT_ALIGN(sizeof(struct xt_connmark_target_info)), 409 .help = CONNMARK_help, 410 .init = CONNMARK_init, 411 .parse = CONNMARK_parse, 412 .final_check = connmark_tg_check, 413 .print = CONNMARK_print, 414 .save = CONNMARK_save, 415 .extra_opts = CONNMARK_opts, 416 }, 417 { 418 .version = XTABLES_VERSION, 419 .name = "CONNMARK", 420 .revision = 1, 421 .family = NFPROTO_UNSPEC, 422 .size = XT_ALIGN(sizeof(struct xt_connmark_tginfo1)), 423 .userspacesize = XT_ALIGN(sizeof(struct xt_connmark_tginfo1)), 424 .help = connmark_tg_help, 425 .init = connmark_tg_init, 426 .parse = connmark_tg_parse, 427 .final_check = connmark_tg_check, 428 .print = connmark_tg_print, 429 .save = connmark_tg_save, 430 .extra_opts = connmark_tg_opts, 431 }, 432}; 433 434void _init(void) 435{ 436 xtables_register_targets(connmark_tg_reg, ARRAY_SIZE(connmark_tg_reg)); 437} 438