1 #include <stdbool.h> 2 #include <stdio.h> 3 #include <xtables.h> 4 #include <linux/netfilter/xt_MARK.h> 5 6 /* Version 0 */ 7 struct xt_mark_target_info { 8 unsigned long mark; 9 }; 10 11 /* Version 1 */ 12 enum { 13 XT_MARK_SET=0, 14 XT_MARK_AND, 15 XT_MARK_OR, 16 }; 17 18 struct xt_mark_target_info_v1 { 19 unsigned long mark; 20 uint8_t mode; 21 }; 22 23 enum { 24 O_SET_MARK = 0, 25 O_AND_MARK, 26 O_OR_MARK, 27 O_XOR_MARK, 28 O_SET_XMARK, 29 F_SET_MARK = 1 << O_SET_MARK, 30 F_AND_MARK = 1 << O_AND_MARK, 31 F_OR_MARK = 1 << O_OR_MARK, 32 F_XOR_MARK = 1 << O_XOR_MARK, 33 F_SET_XMARK = 1 << O_SET_XMARK, 34 F_ANY = F_SET_MARK | F_AND_MARK | F_OR_MARK | 35 F_XOR_MARK | F_SET_XMARK, 36 }; 37 38 static void MARK_help(void) 39 { 40 printf( 41 "MARK target options:\n" 42 " --set-mark value Set nfmark value\n" 43 " --and-mark value Binary AND the nfmark with value\n" 44 " --or-mark value Binary OR the nfmark with value\n"); 45 } 46 47 static const struct xt_option_entry MARK_opts[] = { 48 {.name = "set-mark", .id = O_SET_MARK, .type = XTTYPE_UINT32, 49 .excl = F_ANY}, 50 {.name = "and-mark", .id = O_AND_MARK, .type = XTTYPE_UINT32, 51 .excl = F_ANY}, 52 {.name = "or-mark", .id = O_OR_MARK, .type = XTTYPE_UINT32, 53 .excl = F_ANY}, 54 XTOPT_TABLEEND, 55 }; 56 57 static const struct xt_option_entry mark_tg_opts[] = { 58 {.name = "set-xmark", .id = O_SET_XMARK, .type = XTTYPE_MARKMASK32, 59 .excl = F_ANY}, 60 {.name = "set-mark", .id = O_SET_MARK, .type = XTTYPE_MARKMASK32, 61 .excl = F_ANY}, 62 {.name = "and-mark", .id = O_AND_MARK, .type = XTTYPE_UINT32, 63 .excl = F_ANY}, 64 {.name = "or-mark", .id = O_OR_MARK, .type = XTTYPE_UINT32, 65 .excl = F_ANY}, 66 {.name = "xor-mark", .id = O_XOR_MARK, .type = XTTYPE_UINT32, 67 .excl = F_ANY}, 68 XTOPT_TABLEEND, 69 }; 70 71 static void mark_tg_help(void) 72 { 73 printf( 74 "MARK target options:\n" 75 " --set-xmark value[/mask] Clear bits in mask and XOR value into nfmark\n" 76 " --set-mark value[/mask] Clear bits in mask and OR value into nfmark\n" 77 " --and-mark bits Binary AND the nfmark with bits\n" 78 " --or-mark bits Binary OR the nfmark with bits\n" 79 " --xor-mask bits Binary XOR the nfmark with bits\n" 80 "\n"); 81 } 82 83 static void MARK_parse_v0(struct xt_option_call *cb) 84 { 85 struct xt_mark_target_info *markinfo = cb->data; 86 87 xtables_option_parse(cb); 88 switch (cb->entry->id) { 89 case O_SET_MARK: 90 markinfo->mark = cb->val.mark; 91 break; 92 default: 93 xtables_error(PARAMETER_PROBLEM, 94 "MARK target: kernel too old for --%s", 95 cb->entry->name); 96 } 97 } 98 99 static void MARK_check(struct xt_fcheck_call *cb) 100 { 101 if (cb->xflags == 0) 102 xtables_error(PARAMETER_PROBLEM, 103 "MARK target: Parameter --set/and/or-mark" 104 " is required"); 105 } 106 107 static void MARK_parse_v1(struct xt_option_call *cb) 108 { 109 struct xt_mark_target_info_v1 *markinfo = cb->data; 110 111 xtables_option_parse(cb); 112 switch (cb->entry->id) { 113 case O_SET_MARK: 114 markinfo->mode = XT_MARK_SET; 115 break; 116 case O_AND_MARK: 117 markinfo->mode = XT_MARK_AND; 118 break; 119 case O_OR_MARK: 120 markinfo->mode = XT_MARK_OR; 121 break; 122 } 123 markinfo->mark = cb->val.u32; 124 } 125 126 static void mark_tg_parse(struct xt_option_call *cb) 127 { 128 struct xt_mark_tginfo2 *info = cb->data; 129 130 xtables_option_parse(cb); 131 switch (cb->entry->id) { 132 case O_SET_XMARK: 133 info->mark = cb->val.mark; 134 info->mask = cb->val.mask; 135 break; 136 case O_SET_MARK: 137 info->mark = cb->val.mark; 138 info->mask = cb->val.mark | cb->val.mask; 139 break; 140 case O_AND_MARK: 141 info->mark = 0; 142 info->mask = ~cb->val.u32; 143 break; 144 case O_OR_MARK: 145 info->mark = info->mask = cb->val.u32; 146 break; 147 case O_XOR_MARK: 148 info->mark = cb->val.u32; 149 info->mask = 0; 150 break; 151 } 152 } 153 154 static void mark_tg_check(struct xt_fcheck_call *cb) 155 { 156 if (cb->xflags == 0) 157 xtables_error(PARAMETER_PROBLEM, "MARK: One of the --set-xmark, " 158 "--{and,or,xor,set}-mark options is required"); 159 } 160 161 static void 162 print_mark(unsigned long mark) 163 { 164 printf(" 0x%lx", mark); 165 } 166 167 static void MARK_print_v0(const void *ip, 168 const struct xt_entry_target *target, int numeric) 169 { 170 const struct xt_mark_target_info *markinfo = 171 (const struct xt_mark_target_info *)target->data; 172 printf(" MARK set"); 173 print_mark(markinfo->mark); 174 } 175 176 static void MARK_save_v0(const void *ip, const struct xt_entry_target *target) 177 { 178 const struct xt_mark_target_info *markinfo = 179 (const struct xt_mark_target_info *)target->data; 180 181 printf(" --set-mark"); 182 print_mark(markinfo->mark); 183 } 184 185 static void MARK_print_v1(const void *ip, const struct xt_entry_target *target, 186 int numeric) 187 { 188 const struct xt_mark_target_info_v1 *markinfo = 189 (const struct xt_mark_target_info_v1 *)target->data; 190 191 switch (markinfo->mode) { 192 case XT_MARK_SET: 193 printf(" MARK set"); 194 break; 195 case XT_MARK_AND: 196 printf(" MARK and"); 197 break; 198 case XT_MARK_OR: 199 printf(" MARK or"); 200 break; 201 } 202 print_mark(markinfo->mark); 203 } 204 205 static void mark_tg_print(const void *ip, const struct xt_entry_target *target, 206 int numeric) 207 { 208 const struct xt_mark_tginfo2 *info = (const void *)target->data; 209 210 if (info->mark == 0) 211 printf(" MARK and 0x%x", (unsigned int)(uint32_t)~info->mask); 212 else if (info->mark == info->mask) 213 printf(" MARK or 0x%x", info->mark); 214 else if (info->mask == 0) 215 printf(" MARK xor 0x%x", info->mark); 216 else if (info->mask == 0xffffffffU) 217 printf(" MARK set 0x%x", info->mark); 218 else 219 printf(" MARK xset 0x%x/0x%x", info->mark, info->mask); 220 } 221 222 static void MARK_save_v1(const void *ip, const struct xt_entry_target *target) 223 { 224 const struct xt_mark_target_info_v1 *markinfo = 225 (const struct xt_mark_target_info_v1 *)target->data; 226 227 switch (markinfo->mode) { 228 case XT_MARK_SET: 229 printf(" --set-mark"); 230 break; 231 case XT_MARK_AND: 232 printf(" --and-mark"); 233 break; 234 case XT_MARK_OR: 235 printf(" --or-mark"); 236 break; 237 } 238 print_mark(markinfo->mark); 239 } 240 241 static void mark_tg_save(const void *ip, const struct xt_entry_target *target) 242 { 243 const struct xt_mark_tginfo2 *info = (const void *)target->data; 244 245 printf(" --set-xmark 0x%x/0x%x", info->mark, info->mask); 246 } 247 248 static int mark_tg_xlate(struct xt_xlate *xl, 249 const struct xt_xlate_tg_params *params) 250 { 251 const struct xt_mark_tginfo2 *info = (const void *)params->target->data; 252 253 xt_xlate_add(xl, "meta mark set "); 254 255 if (info->mark == 0) 256 xt_xlate_add(xl, "mark and 0x%x ", ~info->mask); 257 else if (info->mark == info->mask) 258 xt_xlate_add(xl, "mark or 0x%x ", info->mark); 259 else if (info->mask == 0) 260 xt_xlate_add(xl, "mark xor 0x%x ", info->mark); 261 else if (info->mask == 0xffffffffU) 262 xt_xlate_add(xl, "0x%x ", info->mark); 263 else 264 xt_xlate_add(xl, "mark and 0x%x xor 0x%x ", ~info->mask, 265 info->mark); 266 267 return 1; 268 } 269 270 static int MARK_xlate(struct xt_xlate *xl, 271 const struct xt_xlate_tg_params *params) 272 { 273 const struct xt_mark_target_info_v1 *markinfo = 274 (const struct xt_mark_target_info_v1 *)params->target->data; 275 276 xt_xlate_add(xl, "meta mark set "); 277 278 switch(markinfo->mode) { 279 case XT_MARK_SET: 280 xt_xlate_add(xl, "0x%x ", markinfo->mark); 281 break; 282 case XT_MARK_AND: 283 xt_xlate_add(xl, "mark and 0x%x ", markinfo->mark); 284 break; 285 case XT_MARK_OR: 286 xt_xlate_add(xl, "mark or 0x%x ", markinfo->mark); 287 break; 288 } 289 290 return 1; 291 } 292 293 static struct xtables_target mark_tg_reg[] = { 294 { 295 .family = NFPROTO_UNSPEC, 296 .name = "MARK", 297 .version = XTABLES_VERSION, 298 .revision = 0, 299 .size = XT_ALIGN(sizeof(struct xt_mark_target_info)), 300 .userspacesize = XT_ALIGN(sizeof(struct xt_mark_target_info)), 301 .help = MARK_help, 302 .print = MARK_print_v0, 303 .save = MARK_save_v0, 304 .x6_parse = MARK_parse_v0, 305 .x6_fcheck = MARK_check, 306 .x6_options = MARK_opts, 307 }, 308 { 309 .family = NFPROTO_IPV4, 310 .name = "MARK", 311 .version = XTABLES_VERSION, 312 .revision = 1, 313 .size = XT_ALIGN(sizeof(struct xt_mark_target_info_v1)), 314 .userspacesize = XT_ALIGN(sizeof(struct xt_mark_target_info_v1)), 315 .help = MARK_help, 316 .print = MARK_print_v1, 317 .save = MARK_save_v1, 318 .x6_parse = MARK_parse_v1, 319 .x6_fcheck = MARK_check, 320 .x6_options = MARK_opts, 321 .xlate = MARK_xlate, 322 }, 323 { 324 .version = XTABLES_VERSION, 325 .name = "MARK", 326 .revision = 2, 327 .family = NFPROTO_UNSPEC, 328 .size = XT_ALIGN(sizeof(struct xt_mark_tginfo2)), 329 .userspacesize = XT_ALIGN(sizeof(struct xt_mark_tginfo2)), 330 .help = mark_tg_help, 331 .print = mark_tg_print, 332 .save = mark_tg_save, 333 .x6_parse = mark_tg_parse, 334 .x6_fcheck = mark_tg_check, 335 .x6_options = mark_tg_opts, 336 .xlate = mark_tg_xlate, 337 }, 338 }; 339 340 void _init(void) 341 { 342 xtables_register_targets(mark_tg_reg, ARRAY_SIZE(mark_tg_reg)); 343 } 344