1/* 2 * Shared library add-on to iptables to add tos match support 3 * 4 * Copyright © CC Computer Consultants GmbH, 2007 5 * Contact: Jan Engelhardt <jengelh@computergmbh.de> 6 */ 7#include <getopt.h> 8#include <netdb.h> 9#include <stdbool.h> 10#include <stdio.h> 11#include <stdlib.h> 12#include <string.h> 13 14#include <xtables.h> 15#include <linux/netfilter/xt_dscp.h> 16#include "tos_values.c" 17 18struct ipt_tos_info { 19 uint8_t tos; 20 uint8_t invert; 21}; 22 23enum { 24 O_TOS = 1 << 0, 25}; 26 27static const struct xt_option_entry tos_mt_opts_v0[] = { 28 {.name = "tos", .id = O_TOS, .type = XTTYPE_TOSMASK, 29 .flags = XTOPT_INVERT | XTOPT_MAND, .max = 0xFF}, 30 XTOPT_TABLEEND, 31}; 32 33static const struct xt_option_entry tos_mt_opts[] = { 34 {.name = "tos", .id = O_TOS, .type = XTTYPE_TOSMASK, 35 .flags = XTOPT_INVERT | XTOPT_MAND, .max = 0x3F}, 36 XTOPT_TABLEEND, 37}; 38 39static void tos_mt_help(void) 40{ 41 const struct tos_symbol_info *symbol; 42 43 printf( 44"tos match options:\n" 45"[!] --tos value[/mask] Match Type of Service/Priority field value\n" 46"[!] --tos symbol Match 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_mt_parse_v0(struct xt_option_call *cb) 57{ 58 struct ipt_tos_info *info = cb->data; 59 60 xtables_option_parse(cb); 61 if (cb->val.tos_mask != 0xFF) 62 xtables_error(PARAMETER_PROBLEM, "tos: Your kernel is " 63 "too old to support anything besides /0xFF " 64 "as a mask."); 65 info->tos = cb->val.tos_value; 66 if (cb->invert) 67 info->invert = true; 68} 69 70static void tos_mt_parse(struct xt_option_call *cb) 71{ 72 struct xt_tos_match_info *info = cb->data; 73 74 xtables_option_parse(cb); 75 info->tos_value = cb->val.tos_value; 76 info->tos_mask = cb->val.tos_mask; 77 if (cb->invert) 78 info->invert = true; 79} 80 81static void tos_mt_print_v0(const void *ip, const struct xt_entry_match *match, 82 int numeric) 83{ 84 const struct ipt_tos_info *info = (const void *)match->data; 85 86 printf(" tos match "); 87 if (info->invert) 88 printf("!"); 89 if (numeric || !tos_try_print_symbolic("", info->tos, 0x3F)) 90 printf("0x%02x", info->tos); 91} 92 93static void tos_mt_print(const void *ip, const struct xt_entry_match *match, 94 int numeric) 95{ 96 const struct xt_tos_match_info *info = (const void *)match->data; 97 98 printf(" tos match"); 99 if (info->invert) 100 printf("!"); 101 if (numeric || 102 !tos_try_print_symbolic("", info->tos_value, info->tos_mask)) 103 printf("0x%02x/0x%02x", info->tos_value, info->tos_mask); 104} 105 106static void tos_mt_save_v0(const void *ip, const struct xt_entry_match *match) 107{ 108 const struct ipt_tos_info *info = (const void *)match->data; 109 110 if (info->invert) 111 printf(" !"); 112 printf(" --tos 0x%02x", info->tos); 113} 114 115static void tos_mt_save(const void *ip, const struct xt_entry_match *match) 116{ 117 const struct xt_tos_match_info *info = (const void *)match->data; 118 119 if (info->invert) 120 printf(" !"); 121 printf(" --tos 0x%02x/0x%02x", info->tos_value, info->tos_mask); 122} 123 124static struct xtables_match tos_mt_reg[] = { 125 { 126 .version = XTABLES_VERSION, 127 .name = "tos", 128 .family = NFPROTO_IPV4, 129 .revision = 0, 130 .size = XT_ALIGN(sizeof(struct ipt_tos_info)), 131 .userspacesize = XT_ALIGN(sizeof(struct ipt_tos_info)), 132 .help = tos_mt_help, 133 .print = tos_mt_print_v0, 134 .save = tos_mt_save_v0, 135 .x6_parse = tos_mt_parse_v0, 136 .x6_options = tos_mt_opts_v0, 137 }, 138 { 139 .version = XTABLES_VERSION, 140 .name = "tos", 141 .family = NFPROTO_UNSPEC, 142 .revision = 1, 143 .size = XT_ALIGN(sizeof(struct xt_tos_match_info)), 144 .userspacesize = XT_ALIGN(sizeof(struct xt_tos_match_info)), 145 .help = tos_mt_help, 146 .print = tos_mt_print, 147 .save = tos_mt_save, 148 .x6_parse = tos_mt_parse, 149 .x6_options = tos_mt_opts, 150 }, 151}; 152 153void _init(void) 154{ 155 xtables_register_matches(tos_mt_reg, ARRAY_SIZE(tos_mt_reg)); 156} 157