/* * Shared library add-on to iptables to add TOS target support * * Copyright © CC Computer Consultants GmbH, 2007 * Contact: Jan Engelhardt */ #include #include #include #include #include #include #include #include #include "tos_values.c" enum { FLAG_TOS = 1 << 0, }; static const struct option tos_tg_opts_v0[] = { {.name = "set-tos", .has_arg = true, .val = '='}, { .name = NULL } }; static const struct option tos_tg_opts[] = { {.name = "set-tos", .has_arg = true, .val = '='}, {.name = "and-tos", .has_arg = true, .val = '&'}, {.name = "or-tos", .has_arg = true, .val = '|'}, {.name = "xor-tos", .has_arg = true, .val = '^'}, { .name = NULL } }; static void tos_tg_help_v0(void) { const struct tos_symbol_info *symbol; printf( "TOS target options:\n" " --set-tos value Set Type of Service/Priority field to value\n" " --set-tos symbol Set TOS field (IPv4 only) by symbol\n" " Accepted symbolic names for value are:\n"); for (symbol = tos_symbol_names; symbol->name != NULL; ++symbol) printf(" (0x%02x) %2u %s\n", symbol->value, symbol->value, symbol->name); printf("\n"); } static void tos_tg_help(void) { const struct tos_symbol_info *symbol; printf( "TOS target v%s options:\n" " --set-tos value[/mask] Set Type of Service/Priority field to value\n" " (Zero out bits in mask and XOR value into TOS)\n" " --set-tos symbol Set TOS field (IPv4 only) by symbol\n" " (this zeroes the 4-bit Precedence part!)\n" " Accepted symbolic names for value are:\n", XTABLES_VERSION); for (symbol = tos_symbol_names; symbol->name != NULL; ++symbol) printf(" (0x%02x) %2u %s\n", symbol->value, symbol->value, symbol->name); printf( "\n" " --and-tos bits Binary AND the TOS value with bits\n" " --or-tos bits Binary OR the TOS value with bits\n" " --xor-tos bits Binary XOR the TOS value with bits\n" ); } static int tos_tg_parse_v0(int c, char **argv, int invert, unsigned int *flags, const void *entry, struct xt_entry_target **target) { struct ipt_tos_target_info *info = (void *)(*target)->data; struct tos_value_mask tvm; switch (c) { case '=': param_act(P_ONLY_ONCE, "TOS", "--set-tos", *flags & FLAG_TOS); param_act(P_NO_INVERT, "TOS", "--set-tos", invert); if (!tos_parse_symbolic(optarg, &tvm, 0xFF)) param_act(P_BAD_VALUE, "TOS", "--set-tos", optarg); if (tvm.mask != 0xFF) exit_error(PARAMETER_PROBLEM, "tos match: Your kernel " "is too old to support anything besides " "/0xFF as a mask."); info->tos = tvm.value; *flags |= FLAG_TOS; return true; } return false; } static int tos_tg_parse(int c, char **argv, int invert, unsigned int *flags, const void *entry, struct xt_entry_target **target) { struct xt_tos_target_info *info = (void *)(*target)->data; struct tos_value_mask tvm; unsigned int bits; switch (c) { case '=': /* --set-tos */ param_act(P_ONLY_ONCE, "TOS", "--set-tos", *flags & FLAG_TOS); param_act(P_NO_INVERT, "TOS", "--set-tos", invert); if (!tos_parse_symbolic(optarg, &tvm, 0x3F)) param_act(P_BAD_VALUE, "TOS", "--set-tos", optarg); info->tos_value = tvm.value; info->tos_mask = tvm.mask; break; case '&': /* --and-tos */ param_act(P_ONLY_ONCE, "TOS", "--and-tos", *flags & FLAG_TOS); param_act(P_NO_INVERT, "TOS", "--and-tos", invert); if (!strtonum(optarg, NULL, &bits, 0, 0xFF)) param_act(P_BAD_VALUE, "TOS", "--and-tos", optarg); info->tos_value = 0; info->tos_mask = ~bits; break; case '|': /* --or-tos */ param_act(P_ONLY_ONCE, "TOS", "--or-tos", *flags & FLAG_TOS); param_act(P_NO_INVERT, "TOS", "--or-tos", invert); if (!strtonum(optarg, NULL, &bits, 0, 0xFF)) param_act(P_BAD_VALUE, "TOS", "--or-tos", optarg); info->tos_value = bits; info->tos_mask = bits; break; case '^': /* --xor-tos */ param_act(P_ONLY_ONCE, "TOS", "--xor-tos", *flags & FLAG_TOS); param_act(P_NO_INVERT, "TOS", "--xor-tos", invert); if (!strtonum(optarg, NULL, &bits, 0, 0xFF)) param_act(P_BAD_VALUE, "TOS", "--xor-tos", optarg); info->tos_value = bits; info->tos_mask = 0; break; default: return false; } *flags |= FLAG_TOS; return true; } static void tos_tg_check(unsigned int flags) { if (flags == 0) exit_error(PARAMETER_PROBLEM, "TOS: The --set-tos parameter is required"); } static void tos_tg_print_v0(const void *ip, const struct xt_entry_target *target, int numeric) { const struct ipt_tos_target_info *info = (const void *)target->data; printf("TOS set "); if (numeric || !tos_try_print_symbolic("", info->tos, 0xFF)) printf("0x%02x ", info->tos); } static void tos_tg_print(const void *ip, const struct xt_entry_target *target, int numeric) { const struct xt_tos_target_info *info = (const void *)target->data; if (numeric) printf("TOS set 0x%02x/0x%02x ", info->tos_value, info->tos_mask); else if (tos_try_print_symbolic("TOS set ", info->tos_value, info->tos_mask)) /* already printed by call */ return; else if (info->tos_value == 0) printf("TOS and 0x%02x ", (unsigned int)(u_int8_t)~info->tos_mask); else if (info->tos_value == info->tos_mask) printf("TOS or 0x%02x ", info->tos_value); else if (info->tos_mask == 0) printf("TOS xor 0x%02x ", info->tos_value); else printf("TOS set 0x%02x/0x%02x ", info->tos_value, info->tos_mask); } static void tos_tg_save_v0(const void *ip, const struct xt_entry_target *target) { const struct ipt_tos_target_info *info = (const void *)target->data; printf("--set-tos 0x%02x ", info->tos); } static void tos_tg_save(const void *ip, const struct xt_entry_target *target) { const struct xt_tos_target_info *info = (const void *)target->data; printf("--set-tos 0x%02x/0x%02x ", info->tos_value, info->tos_mask); } static struct xtables_target tos_tg_reg_v0 = { .version = XTABLES_VERSION, .name = "TOS", .revision = 0, .family = AF_INET, .size = XT_ALIGN(sizeof(struct xt_tos_target_info)), .userspacesize = XT_ALIGN(sizeof(struct xt_tos_target_info)), .help = tos_tg_help_v0, .parse = tos_tg_parse_v0, .final_check = tos_tg_check, .print = tos_tg_print_v0, .save = tos_tg_save_v0, .extra_opts = tos_tg_opts_v0, }; static struct xtables_target tos_tg_reg = { .version = XTABLES_VERSION, .name = "TOS", .revision = 1, .family = AF_INET, .size = XT_ALIGN(sizeof(struct xt_tos_target_info)), .userspacesize = XT_ALIGN(sizeof(struct xt_tos_target_info)), .help = tos_tg_help, .parse = tos_tg_parse, .final_check = tos_tg_check, .print = tos_tg_print, .save = tos_tg_save, .extra_opts = tos_tg_opts, }; static struct xtables_target tos_tg6_reg = { .version = XTABLES_VERSION, .name = "TOS", .family = AF_INET6, .revision = 1, .size = XT_ALIGN(sizeof(struct xt_tos_target_info)), .userspacesize = XT_ALIGN(sizeof(struct xt_tos_target_info)), .help = tos_tg_help, .parse = tos_tg_parse, .final_check = tos_tg_check, .print = tos_tg_print, .save = tos_tg_save, .extra_opts = tos_tg_opts, }; void _init(void) { xtables_register_target(&tos_tg_reg_v0); xtables_register_target(&tos_tg_reg); xtables_register_target(&tos_tg6_reg); }