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 (at) 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 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 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 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 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 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 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 211 print_mark(unsigned long mark) 212 { 213 printf("0x%lx", mark); 214 } 215 216 static void 217 print_mask(const char *text, unsigned long mask) 218 { 219 if (mask != 0xffffffffUL) 220 printf("%s0x%lx", text, mask); 221 } 222 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 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 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 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 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 383 void _init(void) 384 { 385 xtables_register_targets(connmark_tg_reg, ARRAY_SIZE(connmark_tg_reg)); 386 } 387