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 (at) medozas.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 18 struct ipt_tos_target_info { 19 uint8_t tos; 20 }; 21 22 enum { 23 O_SET_TOS = 0, 24 O_AND_TOS, 25 O_OR_TOS, 26 O_XOR_TOS, 27 F_SET_TOS = 1 << O_SET_TOS, 28 F_AND_TOS = 1 << O_AND_TOS, 29 F_OR_TOS = 1 << O_OR_TOS, 30 F_XOR_TOS = 1 << O_XOR_TOS, 31 F_ANY = F_SET_TOS | F_AND_TOS | F_OR_TOS | F_XOR_TOS, 32 }; 33 34 static const struct xt_option_entry tos_tg_opts_v0[] = { 35 {.name = "set-tos", .id = O_SET_TOS, .type = XTTYPE_TOSMASK, 36 .excl = F_ANY, .max = 0xFF}, 37 XTOPT_TABLEEND, 38 }; 39 40 static const struct xt_option_entry tos_tg_opts[] = { 41 {.name = "set-tos", .id = O_SET_TOS, .type = XTTYPE_TOSMASK, 42 .excl = F_ANY, .max = 0x3F}, 43 {.name = "and-tos", .id = O_AND_TOS, .type = XTTYPE_UINT8, 44 .excl = F_ANY}, 45 {.name = "or-tos", .id = O_OR_TOS, .type = XTTYPE_UINT8, 46 .excl = F_ANY}, 47 {.name = "xor-tos", .id = O_XOR_TOS, .type = XTTYPE_UINT8, 48 .excl = F_ANY}, 49 XTOPT_TABLEEND, 50 }; 51 52 static void tos_tg_help_v0(void) 53 { 54 const struct tos_symbol_info *symbol; 55 56 printf( 57 "TOS target options:\n" 58 " --set-tos value Set Type of Service/Priority field to value\n" 59 " --set-tos symbol Set TOS field (IPv4 only) by symbol\n" 60 " Accepted symbolic names for value are:\n"); 61 62 for (symbol = tos_symbol_names; symbol->name != NULL; ++symbol) 63 printf(" (0x%02x) %2u %s\n", 64 symbol->value, symbol->value, symbol->name); 65 66 printf("\n"); 67 } 68 69 static void tos_tg_help(void) 70 { 71 const struct tos_symbol_info *symbol; 72 73 printf( 74 "TOS target v%s options:\n" 75 " --set-tos value[/mask] Set Type of Service/Priority field to value\n" 76 " (Zero out bits in mask and XOR value into TOS)\n" 77 " --set-tos symbol Set TOS field (IPv4 only) by symbol\n" 78 " (this zeroes the 4-bit Precedence part!)\n" 79 " Accepted symbolic names for value are:\n", 80 XTABLES_VERSION); 81 82 for (symbol = tos_symbol_names; symbol->name != NULL; ++symbol) 83 printf(" (0x%02x) %2u %s\n", 84 symbol->value, symbol->value, symbol->name); 85 86 printf( 87 "\n" 88 " --and-tos bits Binary AND the TOS value with bits\n" 89 " --or-tos bits Binary OR the TOS value with bits\n" 90 " --xor-tos bits Binary XOR the TOS value with bits\n" 91 ); 92 } 93 94 static void tos_tg_parse_v0(struct xt_option_call *cb) 95 { 96 struct ipt_tos_target_info *info = cb->data; 97 98 xtables_option_parse(cb); 99 if (cb->val.tos_mask != 0xFF) 100 xtables_error(PARAMETER_PROBLEM, "tos match: Your kernel " 101 "is too old to support anything besides " 102 "/0xFF as a mask."); 103 info->tos = cb->val.tos_value; 104 } 105 106 static void tos_tg_parse(struct xt_option_call *cb) 107 { 108 struct xt_tos_target_info *info = cb->data; 109 110 xtables_option_parse(cb); 111 switch (cb->entry->id) { 112 case O_SET_TOS: 113 info->tos_value = cb->val.tos_value; 114 info->tos_mask = cb->val.tos_mask; 115 break; 116 case O_AND_TOS: 117 info->tos_value = 0; 118 info->tos_mask = ~cb->val.u8; 119 break; 120 case O_OR_TOS: 121 info->tos_value = cb->val.u8; 122 info->tos_mask = cb->val.u8; 123 break; 124 case O_XOR_TOS: 125 info->tos_value = cb->val.u8; 126 info->tos_mask = 0; 127 break; 128 } 129 } 130 131 static void tos_tg_check(struct xt_fcheck_call *cb) 132 { 133 if (!(cb->xflags & F_ANY)) 134 xtables_error(PARAMETER_PROBLEM, 135 "TOS: An action is required"); 136 } 137 138 static void tos_tg_print_v0(const void *ip, 139 const struct xt_entry_target *target, int numeric) 140 { 141 const struct ipt_tos_target_info *info = (const void *)target->data; 142 143 printf(" TOS set "); 144 if (numeric || !tos_try_print_symbolic("", info->tos, 0xFF)) 145 printf("0x%02x", info->tos); 146 } 147 148 static void tos_tg_print(const void *ip, const struct xt_entry_target *target, 149 int numeric) 150 { 151 const struct xt_tos_target_info *info = (const void *)target->data; 152 153 if (numeric) 154 printf(" TOS set 0x%02x/0x%02x", 155 info->tos_value, info->tos_mask); 156 else if (tos_try_print_symbolic(" TOS set", 157 info->tos_value, info->tos_mask)) 158 /* already printed by call */ 159 return; 160 else if (info->tos_value == 0) 161 printf(" TOS and 0x%02x", 162 (unsigned int)(uint8_t)~info->tos_mask); 163 else if (info->tos_value == info->tos_mask) 164 printf(" TOS or 0x%02x", info->tos_value); 165 else if (info->tos_mask == 0) 166 printf(" TOS xor 0x%02x", info->tos_value); 167 else 168 printf(" TOS set 0x%02x/0x%02x", 169 info->tos_value, info->tos_mask); 170 } 171 172 static void tos_tg_save_v0(const void *ip, const struct xt_entry_target *target) 173 { 174 const struct ipt_tos_target_info *info = (const void *)target->data; 175 176 printf(" --set-tos 0x%02x", info->tos); 177 } 178 179 static void tos_tg_save(const void *ip, const struct xt_entry_target *target) 180 { 181 const struct xt_tos_target_info *info = (const void *)target->data; 182 183 printf(" --set-tos 0x%02x/0x%02x", info->tos_value, info->tos_mask); 184 } 185 186 static struct xtables_target tos_tg_reg[] = { 187 { 188 .version = XTABLES_VERSION, 189 .name = "TOS", 190 .revision = 0, 191 .family = NFPROTO_IPV4, 192 .size = XT_ALIGN(sizeof(struct xt_tos_target_info)), 193 .userspacesize = XT_ALIGN(sizeof(struct xt_tos_target_info)), 194 .help = tos_tg_help_v0, 195 .print = tos_tg_print_v0, 196 .save = tos_tg_save_v0, 197 .x6_parse = tos_tg_parse_v0, 198 .x6_fcheck = tos_tg_check, 199 .x6_options = tos_tg_opts_v0, 200 }, 201 { 202 .version = XTABLES_VERSION, 203 .name = "TOS", 204 .revision = 1, 205 .family = NFPROTO_UNSPEC, 206 .size = XT_ALIGN(sizeof(struct xt_tos_target_info)), 207 .userspacesize = XT_ALIGN(sizeof(struct xt_tos_target_info)), 208 .help = tos_tg_help, 209 .print = tos_tg_print, 210 .save = tos_tg_save, 211 .x6_parse = tos_tg_parse, 212 .x6_fcheck = tos_tg_check, 213 .x6_options = tos_tg_opts, 214 }, 215 }; 216 217 void _init(void) 218 { 219 xtables_register_targets(tos_tg_reg, ARRAY_SIZE(tos_tg_reg)); 220 } 221