1*a71a9546SAutomerger Merge Worker /* 2*a71a9546SAutomerger Merge Worker * Shared library add-on to iptables to add TOS target support 3*a71a9546SAutomerger Merge Worker * 4*a71a9546SAutomerger Merge Worker * Copyright © CC Computer Consultants GmbH, 2007 5*a71a9546SAutomerger Merge Worker * Contact: Jan Engelhardt <[email protected]> 6*a71a9546SAutomerger Merge Worker */ 7*a71a9546SAutomerger Merge Worker #include <getopt.h> 8*a71a9546SAutomerger Merge Worker #include <stdbool.h> 9*a71a9546SAutomerger Merge Worker #include <stdio.h> 10*a71a9546SAutomerger Merge Worker #include <stdlib.h> 11*a71a9546SAutomerger Merge Worker #include <string.h> 12*a71a9546SAutomerger Merge Worker #include <netinet/in.h> 13*a71a9546SAutomerger Merge Worker 14*a71a9546SAutomerger Merge Worker #include <xtables.h> 15*a71a9546SAutomerger Merge Worker #include <linux/netfilter/xt_DSCP.h> 16*a71a9546SAutomerger Merge Worker #include "tos_values.c" 17*a71a9546SAutomerger Merge Worker 18*a71a9546SAutomerger Merge Worker struct ipt_tos_target_info { 19*a71a9546SAutomerger Merge Worker uint8_t tos; 20*a71a9546SAutomerger Merge Worker }; 21*a71a9546SAutomerger Merge Worker 22*a71a9546SAutomerger Merge Worker enum { 23*a71a9546SAutomerger Merge Worker O_SET_TOS = 0, 24*a71a9546SAutomerger Merge Worker O_AND_TOS, 25*a71a9546SAutomerger Merge Worker O_OR_TOS, 26*a71a9546SAutomerger Merge Worker O_XOR_TOS, 27*a71a9546SAutomerger Merge Worker F_SET_TOS = 1 << O_SET_TOS, 28*a71a9546SAutomerger Merge Worker F_AND_TOS = 1 << O_AND_TOS, 29*a71a9546SAutomerger Merge Worker F_OR_TOS = 1 << O_OR_TOS, 30*a71a9546SAutomerger Merge Worker F_XOR_TOS = 1 << O_XOR_TOS, 31*a71a9546SAutomerger Merge Worker F_ANY = F_SET_TOS | F_AND_TOS | F_OR_TOS | F_XOR_TOS, 32*a71a9546SAutomerger Merge Worker }; 33*a71a9546SAutomerger Merge Worker 34*a71a9546SAutomerger Merge Worker static const struct xt_option_entry tos_tg_opts_v0[] = { 35*a71a9546SAutomerger Merge Worker {.name = "set-tos", .id = O_SET_TOS, .type = XTTYPE_TOSMASK, 36*a71a9546SAutomerger Merge Worker .excl = F_ANY, .max = 0xFF}, 37*a71a9546SAutomerger Merge Worker XTOPT_TABLEEND, 38*a71a9546SAutomerger Merge Worker }; 39*a71a9546SAutomerger Merge Worker 40*a71a9546SAutomerger Merge Worker static const struct xt_option_entry tos_tg_opts[] = { 41*a71a9546SAutomerger Merge Worker {.name = "set-tos", .id = O_SET_TOS, .type = XTTYPE_TOSMASK, 42*a71a9546SAutomerger Merge Worker .excl = F_ANY, .max = 0x3F}, 43*a71a9546SAutomerger Merge Worker {.name = "and-tos", .id = O_AND_TOS, .type = XTTYPE_UINT8, 44*a71a9546SAutomerger Merge Worker .excl = F_ANY}, 45*a71a9546SAutomerger Merge Worker {.name = "or-tos", .id = O_OR_TOS, .type = XTTYPE_UINT8, 46*a71a9546SAutomerger Merge Worker .excl = F_ANY}, 47*a71a9546SAutomerger Merge Worker {.name = "xor-tos", .id = O_XOR_TOS, .type = XTTYPE_UINT8, 48*a71a9546SAutomerger Merge Worker .excl = F_ANY}, 49*a71a9546SAutomerger Merge Worker XTOPT_TABLEEND, 50*a71a9546SAutomerger Merge Worker }; 51*a71a9546SAutomerger Merge Worker 52*a71a9546SAutomerger Merge Worker static void tos_tg_help_v0(void) 53*a71a9546SAutomerger Merge Worker { 54*a71a9546SAutomerger Merge Worker const struct tos_symbol_info *symbol; 55*a71a9546SAutomerger Merge Worker 56*a71a9546SAutomerger Merge Worker printf( 57*a71a9546SAutomerger Merge Worker "TOS target options:\n" 58*a71a9546SAutomerger Merge Worker " --set-tos value Set Type of Service/Priority field to value\n" 59*a71a9546SAutomerger Merge Worker " --set-tos symbol Set TOS field (IPv4 only) by symbol\n" 60*a71a9546SAutomerger Merge Worker " Accepted symbolic names for value are:\n"); 61*a71a9546SAutomerger Merge Worker 62*a71a9546SAutomerger Merge Worker for (symbol = tos_symbol_names; symbol->name != NULL; ++symbol) 63*a71a9546SAutomerger Merge Worker printf(" (0x%02x) %2u %s\n", 64*a71a9546SAutomerger Merge Worker symbol->value, symbol->value, symbol->name); 65*a71a9546SAutomerger Merge Worker 66*a71a9546SAutomerger Merge Worker printf("\n"); 67*a71a9546SAutomerger Merge Worker } 68*a71a9546SAutomerger Merge Worker 69*a71a9546SAutomerger Merge Worker static void tos_tg_help(void) 70*a71a9546SAutomerger Merge Worker { 71*a71a9546SAutomerger Merge Worker const struct tos_symbol_info *symbol; 72*a71a9546SAutomerger Merge Worker 73*a71a9546SAutomerger Merge Worker printf( 74*a71a9546SAutomerger Merge Worker "TOS target v%s options:\n" 75*a71a9546SAutomerger Merge Worker " --set-tos value[/mask] Set Type of Service/Priority field to value\n" 76*a71a9546SAutomerger Merge Worker " (Zero out bits in mask and XOR value into TOS)\n" 77*a71a9546SAutomerger Merge Worker " --set-tos symbol Set TOS field (IPv4 only) by symbol\n" 78*a71a9546SAutomerger Merge Worker " (this zeroes the 4-bit Precedence part!)\n" 79*a71a9546SAutomerger Merge Worker " Accepted symbolic names for value are:\n", 80*a71a9546SAutomerger Merge Worker XTABLES_VERSION); 81*a71a9546SAutomerger Merge Worker 82*a71a9546SAutomerger Merge Worker for (symbol = tos_symbol_names; symbol->name != NULL; ++symbol) 83*a71a9546SAutomerger Merge Worker printf(" (0x%02x) %2u %s\n", 84*a71a9546SAutomerger Merge Worker symbol->value, symbol->value, symbol->name); 85*a71a9546SAutomerger Merge Worker 86*a71a9546SAutomerger Merge Worker printf( 87*a71a9546SAutomerger Merge Worker "\n" 88*a71a9546SAutomerger Merge Worker " --and-tos bits Binary AND the TOS value with bits\n" 89*a71a9546SAutomerger Merge Worker " --or-tos bits Binary OR the TOS value with bits\n" 90*a71a9546SAutomerger Merge Worker " --xor-tos bits Binary XOR the TOS value with bits\n" 91*a71a9546SAutomerger Merge Worker ); 92*a71a9546SAutomerger Merge Worker } 93*a71a9546SAutomerger Merge Worker 94*a71a9546SAutomerger Merge Worker static void tos_tg_parse_v0(struct xt_option_call *cb) 95*a71a9546SAutomerger Merge Worker { 96*a71a9546SAutomerger Merge Worker struct ipt_tos_target_info *info = cb->data; 97*a71a9546SAutomerger Merge Worker 98*a71a9546SAutomerger Merge Worker xtables_option_parse(cb); 99*a71a9546SAutomerger Merge Worker if (cb->val.tos_mask != 0xFF) 100*a71a9546SAutomerger Merge Worker xtables_error(PARAMETER_PROBLEM, "tos match: Your kernel " 101*a71a9546SAutomerger Merge Worker "is too old to support anything besides " 102*a71a9546SAutomerger Merge Worker "/0xFF as a mask."); 103*a71a9546SAutomerger Merge Worker info->tos = cb->val.tos_value; 104*a71a9546SAutomerger Merge Worker } 105*a71a9546SAutomerger Merge Worker 106*a71a9546SAutomerger Merge Worker static void tos_tg_parse(struct xt_option_call *cb) 107*a71a9546SAutomerger Merge Worker { 108*a71a9546SAutomerger Merge Worker struct xt_tos_target_info *info = cb->data; 109*a71a9546SAutomerger Merge Worker 110*a71a9546SAutomerger Merge Worker xtables_option_parse(cb); 111*a71a9546SAutomerger Merge Worker switch (cb->entry->id) { 112*a71a9546SAutomerger Merge Worker case O_SET_TOS: 113*a71a9546SAutomerger Merge Worker info->tos_value = cb->val.tos_value; 114*a71a9546SAutomerger Merge Worker info->tos_mask = cb->val.tos_mask; 115*a71a9546SAutomerger Merge Worker break; 116*a71a9546SAutomerger Merge Worker case O_AND_TOS: 117*a71a9546SAutomerger Merge Worker info->tos_value = 0; 118*a71a9546SAutomerger Merge Worker info->tos_mask = ~cb->val.u8; 119*a71a9546SAutomerger Merge Worker break; 120*a71a9546SAutomerger Merge Worker case O_OR_TOS: 121*a71a9546SAutomerger Merge Worker info->tos_value = cb->val.u8; 122*a71a9546SAutomerger Merge Worker info->tos_mask = cb->val.u8; 123*a71a9546SAutomerger Merge Worker break; 124*a71a9546SAutomerger Merge Worker case O_XOR_TOS: 125*a71a9546SAutomerger Merge Worker info->tos_value = cb->val.u8; 126*a71a9546SAutomerger Merge Worker info->tos_mask = 0; 127*a71a9546SAutomerger Merge Worker break; 128*a71a9546SAutomerger Merge Worker } 129*a71a9546SAutomerger Merge Worker } 130*a71a9546SAutomerger Merge Worker 131*a71a9546SAutomerger Merge Worker static void tos_tg_check(struct xt_fcheck_call *cb) 132*a71a9546SAutomerger Merge Worker { 133*a71a9546SAutomerger Merge Worker if (!(cb->xflags & F_ANY)) 134*a71a9546SAutomerger Merge Worker xtables_error(PARAMETER_PROBLEM, 135*a71a9546SAutomerger Merge Worker "TOS: An action is required"); 136*a71a9546SAutomerger Merge Worker } 137*a71a9546SAutomerger Merge Worker 138*a71a9546SAutomerger Merge Worker static void tos_tg_print_v0(const void *ip, 139*a71a9546SAutomerger Merge Worker const struct xt_entry_target *target, int numeric) 140*a71a9546SAutomerger Merge Worker { 141*a71a9546SAutomerger Merge Worker const struct ipt_tos_target_info *info = (const void *)target->data; 142*a71a9546SAutomerger Merge Worker 143*a71a9546SAutomerger Merge Worker printf(" TOS set "); 144*a71a9546SAutomerger Merge Worker if (numeric || !tos_try_print_symbolic("", info->tos, 0xFF)) 145*a71a9546SAutomerger Merge Worker printf("0x%02x", info->tos); 146*a71a9546SAutomerger Merge Worker } 147*a71a9546SAutomerger Merge Worker 148*a71a9546SAutomerger Merge Worker static void tos_tg_print(const void *ip, const struct xt_entry_target *target, 149*a71a9546SAutomerger Merge Worker int numeric) 150*a71a9546SAutomerger Merge Worker { 151*a71a9546SAutomerger Merge Worker const struct xt_tos_target_info *info = (const void *)target->data; 152*a71a9546SAutomerger Merge Worker 153*a71a9546SAutomerger Merge Worker if (numeric) 154*a71a9546SAutomerger Merge Worker printf(" TOS set 0x%02x/0x%02x", 155*a71a9546SAutomerger Merge Worker info->tos_value, info->tos_mask); 156*a71a9546SAutomerger Merge Worker else if (tos_try_print_symbolic(" TOS set", 157*a71a9546SAutomerger Merge Worker info->tos_value, info->tos_mask)) 158*a71a9546SAutomerger Merge Worker /* already printed by call */ 159*a71a9546SAutomerger Merge Worker return; 160*a71a9546SAutomerger Merge Worker else if (info->tos_value == 0) 161*a71a9546SAutomerger Merge Worker printf(" TOS and 0x%02x", 162*a71a9546SAutomerger Merge Worker (unsigned int)(uint8_t)~info->tos_mask); 163*a71a9546SAutomerger Merge Worker else if (info->tos_value == info->tos_mask) 164*a71a9546SAutomerger Merge Worker printf(" TOS or 0x%02x", info->tos_value); 165*a71a9546SAutomerger Merge Worker else if (info->tos_mask == 0) 166*a71a9546SAutomerger Merge Worker printf(" TOS xor 0x%02x", info->tos_value); 167*a71a9546SAutomerger Merge Worker else 168*a71a9546SAutomerger Merge Worker printf(" TOS set 0x%02x/0x%02x", 169*a71a9546SAutomerger Merge Worker info->tos_value, info->tos_mask); 170*a71a9546SAutomerger Merge Worker } 171*a71a9546SAutomerger Merge Worker 172*a71a9546SAutomerger Merge Worker static void tos_tg_save_v0(const void *ip, const struct xt_entry_target *target) 173*a71a9546SAutomerger Merge Worker { 174*a71a9546SAutomerger Merge Worker const struct ipt_tos_target_info *info = (const void *)target->data; 175*a71a9546SAutomerger Merge Worker 176*a71a9546SAutomerger Merge Worker printf(" --set-tos 0x%02x", info->tos); 177*a71a9546SAutomerger Merge Worker } 178*a71a9546SAutomerger Merge Worker 179*a71a9546SAutomerger Merge Worker static void tos_tg_save(const void *ip, const struct xt_entry_target *target) 180*a71a9546SAutomerger Merge Worker { 181*a71a9546SAutomerger Merge Worker const struct xt_tos_target_info *info = (const void *)target->data; 182*a71a9546SAutomerger Merge Worker 183*a71a9546SAutomerger Merge Worker printf(" --set-tos 0x%02x/0x%02x", info->tos_value, info->tos_mask); 184*a71a9546SAutomerger Merge Worker } 185*a71a9546SAutomerger Merge Worker 186*a71a9546SAutomerger Merge Worker static int __tos_xlate(struct xt_xlate *xl, const char *ip, 187*a71a9546SAutomerger Merge Worker uint8_t tos, uint8_t tosmask) 188*a71a9546SAutomerger Merge Worker { 189*a71a9546SAutomerger Merge Worker xt_xlate_add(xl, "%s dscp set ", ip); 190*a71a9546SAutomerger Merge Worker if ((tosmask & 0x3f) == 0x3f) 191*a71a9546SAutomerger Merge Worker xt_xlate_add(xl, "0x%02x", tos >> 2); 192*a71a9546SAutomerger Merge Worker else if (!tos) 193*a71a9546SAutomerger Merge Worker xt_xlate_add(xl, "%s dscp and 0x%02x", 194*a71a9546SAutomerger Merge Worker ip, (uint8_t)~tosmask >> 2); 195*a71a9546SAutomerger Merge Worker else if (tos == tosmask) 196*a71a9546SAutomerger Merge Worker xt_xlate_add(xl, "%s dscp or 0x%02x", ip, tos >> 2); 197*a71a9546SAutomerger Merge Worker else if (!tosmask) 198*a71a9546SAutomerger Merge Worker xt_xlate_add(xl, "%s dscp xor 0x%02x", ip, tos >> 2); 199*a71a9546SAutomerger Merge Worker else 200*a71a9546SAutomerger Merge Worker xt_xlate_add(xl, "%s dscp and 0x%02x xor 0x%02x", 201*a71a9546SAutomerger Merge Worker ip, (uint8_t)~tosmask >> 2, tos >> 2); 202*a71a9546SAutomerger Merge Worker return 1; 203*a71a9546SAutomerger Merge Worker } 204*a71a9546SAutomerger Merge Worker 205*a71a9546SAutomerger Merge Worker static int tos_xlate(struct xt_xlate *xl, 206*a71a9546SAutomerger Merge Worker const struct xt_xlate_tg_params *params) 207*a71a9546SAutomerger Merge Worker { 208*a71a9546SAutomerger Merge Worker const struct ipt_tos_target_info *info = 209*a71a9546SAutomerger Merge Worker (struct ipt_tos_target_info *) params->target->data; 210*a71a9546SAutomerger Merge Worker 211*a71a9546SAutomerger Merge Worker return __tos_xlate(xl, "ip", info->tos, UINT8_MAX); 212*a71a9546SAutomerger Merge Worker } 213*a71a9546SAutomerger Merge Worker 214*a71a9546SAutomerger Merge Worker static int tos_xlate6(struct xt_xlate *xl, 215*a71a9546SAutomerger Merge Worker const struct xt_xlate_tg_params *params) 216*a71a9546SAutomerger Merge Worker { 217*a71a9546SAutomerger Merge Worker const struct xt_tos_target_info *info = 218*a71a9546SAutomerger Merge Worker (struct xt_tos_target_info *)params->target->data; 219*a71a9546SAutomerger Merge Worker 220*a71a9546SAutomerger Merge Worker return __tos_xlate(xl, "ip6", info->tos_value, info->tos_mask); 221*a71a9546SAutomerger Merge Worker } 222*a71a9546SAutomerger Merge Worker 223*a71a9546SAutomerger Merge Worker static struct xtables_target tos_tg_reg[] = { 224*a71a9546SAutomerger Merge Worker { 225*a71a9546SAutomerger Merge Worker .version = XTABLES_VERSION, 226*a71a9546SAutomerger Merge Worker .name = "TOS", 227*a71a9546SAutomerger Merge Worker .revision = 0, 228*a71a9546SAutomerger Merge Worker .family = NFPROTO_IPV4, 229*a71a9546SAutomerger Merge Worker .size = XT_ALIGN(sizeof(struct xt_tos_target_info)), 230*a71a9546SAutomerger Merge Worker .userspacesize = XT_ALIGN(sizeof(struct xt_tos_target_info)), 231*a71a9546SAutomerger Merge Worker .help = tos_tg_help_v0, 232*a71a9546SAutomerger Merge Worker .print = tos_tg_print_v0, 233*a71a9546SAutomerger Merge Worker .save = tos_tg_save_v0, 234*a71a9546SAutomerger Merge Worker .x6_parse = tos_tg_parse_v0, 235*a71a9546SAutomerger Merge Worker .x6_fcheck = tos_tg_check, 236*a71a9546SAutomerger Merge Worker .x6_options = tos_tg_opts_v0, 237*a71a9546SAutomerger Merge Worker .xlate = tos_xlate, 238*a71a9546SAutomerger Merge Worker }, 239*a71a9546SAutomerger Merge Worker { 240*a71a9546SAutomerger Merge Worker .version = XTABLES_VERSION, 241*a71a9546SAutomerger Merge Worker .name = "TOS", 242*a71a9546SAutomerger Merge Worker .revision = 1, 243*a71a9546SAutomerger Merge Worker .family = NFPROTO_UNSPEC, 244*a71a9546SAutomerger Merge Worker .size = XT_ALIGN(sizeof(struct xt_tos_target_info)), 245*a71a9546SAutomerger Merge Worker .userspacesize = XT_ALIGN(sizeof(struct xt_tos_target_info)), 246*a71a9546SAutomerger Merge Worker .help = tos_tg_help, 247*a71a9546SAutomerger Merge Worker .print = tos_tg_print, 248*a71a9546SAutomerger Merge Worker .save = tos_tg_save, 249*a71a9546SAutomerger Merge Worker .x6_parse = tos_tg_parse, 250*a71a9546SAutomerger Merge Worker .x6_fcheck = tos_tg_check, 251*a71a9546SAutomerger Merge Worker .x6_options = tos_tg_opts, 252*a71a9546SAutomerger Merge Worker .xlate = tos_xlate6, 253*a71a9546SAutomerger Merge Worker }, 254*a71a9546SAutomerger Merge Worker }; 255*a71a9546SAutomerger Merge Worker 256*a71a9546SAutomerger Merge Worker void _init(void) 257*a71a9546SAutomerger Merge Worker { 258*a71a9546SAutomerger Merge Worker xtables_register_targets(tos_tg_reg, ARRAY_SIZE(tos_tg_reg)); 259*a71a9546SAutomerger Merge Worker } 260