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