1/* Shared library add-on to iptables to add TOS matching support. */ 2#include <stdio.h> 3#include <netdb.h> 4#include <string.h> 5#include <stdlib.h> 6#include <getopt.h> 7 8#include <iptables.h> 9#include <linux/netfilter_ipv4/ipt_tos.h> 10 11/* TOS names and values. */ 12static 13struct TOS_value 14{ 15 unsigned char TOS; 16 const char *name; 17} TOS_values[] = { 18 { IPTOS_LOWDELAY, "Minimize-Delay" }, 19 { IPTOS_THROUGHPUT, "Maximize-Throughput" }, 20 { IPTOS_RELIABILITY, "Maximize-Reliability" }, 21 { IPTOS_MINCOST, "Minimize-Cost" }, 22 { IPTOS_NORMALSVC, "Normal-Service" }, 23}; 24 25/* Function which prints out usage message. */ 26static void 27help(void) 28{ 29 unsigned int i; 30 31 printf( 32"TOS match v%s options:\n" 33"[!] --tos value Match Type of Service field from one of the\n" 34" following numeric or descriptive values:\n", 35XTABLES_VERSION); 36 37 for (i = 0; i < sizeof(TOS_values)/sizeof(struct TOS_value);i++) 38 printf(" %s %u (0x%02x)\n", 39 TOS_values[i].name, 40 TOS_values[i].TOS, 41 TOS_values[i].TOS); 42 fputc('\n', stdout); 43} 44 45static struct option opts[] = { 46 { .name = "tos", .has_arg = true, .val = '1' }, 47 XT_GETOPT_TABLEEND 48}; 49 50static void 51parse_tos(const char *s, struct ipt_tos_info *info) 52{ 53 unsigned int i; 54 unsigned int tos; 55 56 if (xtables_strtoui(s, NULL, &tos, 0, UINT8_MAX)) { 57 if (tos == IPTOS_LOWDELAY 58 || tos == IPTOS_THROUGHPUT 59 || tos == IPTOS_RELIABILITY 60 || tos == IPTOS_MINCOST 61 || tos == IPTOS_NORMALSVC) { 62 info->tos = (u_int8_t )tos; 63 return; 64 } 65 } else { 66 for (i = 0; i<sizeof(TOS_values)/sizeof(struct TOS_value); i++) 67 if (strcasecmp(s,TOS_values[i].name) == 0) { 68 info->tos = TOS_values[i].TOS; 69 return; 70 } 71 } 72 xtables_error(PARAMETER_PROBLEM, "Bad TOS value `%s'", s); 73} 74 75/* Function which parses command options; returns true if it 76 ate an option */ 77static int 78parse(int c, char **argv, int invert, unsigned int *flags, 79 const void *entry, 80 struct xt_entry_match **match) 81{ 82 struct ipt_tos_info *tosinfo = (struct ipt_tos_info *)(*match)->data; 83 84 switch (c) { 85 case '1': 86 /* Ensure that `--tos' haven't been used yet. */ 87 if (*flags == 1) 88 xtables_error(PARAMETER_PROBLEM, 89 "tos match: only use --tos once!"); 90 91 parse_tos(argv[optind-1], tosinfo); 92 if (invert) 93 tosinfo->invert = 1; 94 *flags = 1; 95 break; 96 97 default: 98 return 0; 99 } 100 return 1; 101} 102 103static void 104print_tos(u_int8_t tos, int numeric) 105{ 106 unsigned int i; 107 108 if (!numeric) { 109 for (i = 0; i<sizeof(TOS_values)/sizeof(struct TOS_value); i++) 110 if (TOS_values[i].TOS == tos) { 111 printf("%s ", TOS_values[i].name); 112 return; 113 } 114 } 115 printf("0x%02x ", tos); 116} 117 118/* Final check; must have specified --tos. */ 119static void 120final_check(unsigned int flags) 121{ 122 if (!flags) 123 xtables_error(PARAMETER_PROBLEM, 124 "TOS match: You must specify `--tos'"); 125} 126 127/* Prints out the matchinfo. */ 128static void 129print(const void *ip, 130 const struct xt_entry_match *match, 131 int numeric) 132{ 133 const struct ipt_tos_info *info = (const struct ipt_tos_info *)match->data; 134 135 printf("TOS match "); 136 if (info->invert) 137 printf("!"); 138 print_tos(info->tos, numeric); 139} 140 141/* Saves the union ipt_matchinfo in parsable form to stdout. */ 142static void 143save(const void *ip, const struct xt_entry_match *match) 144{ 145 const struct ipt_tos_info *info = (const struct ipt_tos_info *)match->data; 146 147 if (info->invert) 148 printf("! "); 149 printf("--tos "); 150 print_tos(info->tos, 0); 151} 152 153static struct xtables_match tos = { 154 .name = "tos", 155 .version = XTABLES_VERSION, 156 .size = XT_ALIGN(sizeof(struct ipt_tos_info)), 157 .userspacesize = XT_ALIGN(sizeof(struct ipt_tos_info)), 158 .help = &help, 159 .parse = &parse, 160 .final_check = &final_check, 161 .print = &print, 162 .save = &save, 163 .extra_opts = opts 164}; 165 166void _init(void) 167{ 168 xtables_register_match(&tos); 169} 170