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