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