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. */ 12 static 13 struct 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. */ 26 static void 27 help(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", 35 IPTABLES_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 45 static struct option opts[] = { 46 { "tos", 1, 0, '1' }, 47 {0} 48 }; 49 50 static void 51 parse_tos(const char *s, struct ipt_tos_info *info) 52 { 53 unsigned int i; 54 unsigned int tos; 55 56 if (string_to_number(s, 0, 255, &tos) != -1) { 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 exit_error(PARAMETER_PROBLEM, "Bad TOS value `%s'", s); 73 } 74 75 /* Function which parses command options; returns true if it 76 ate an option */ 77 static int 78 parse(int c, char **argv, int invert, unsigned int *flags, 79 const struct ipt_entry *entry, 80 unsigned int *nfcache, 81 struct ipt_entry_match **match) 82 { 83 struct ipt_tos_info *tosinfo = (struct ipt_tos_info *)(*match)->data; 84 85 switch (c) { 86 case '1': 87 /* Ensure that `--tos' haven't been used yet. */ 88 if (*flags == 1) 89 exit_error(PARAMETER_PROBLEM, 90 "tos match: only use --tos once!"); 91 92 check_inverse(optarg, &invert, &optind, 0); 93 parse_tos(argv[optind-1], tosinfo); 94 if (invert) 95 tosinfo->invert = 1; 96 *flags = 1; 97 break; 98 99 default: 100 return 0; 101 } 102 return 1; 103 } 104 105 static void 106 print_tos(u_int8_t tos, int numeric) 107 { 108 unsigned int i; 109 110 if (!numeric) { 111 for (i = 0; i<sizeof(TOS_values)/sizeof(struct TOS_value); i++) 112 if (TOS_values[i].TOS == tos) { 113 printf("%s ", TOS_values[i].name); 114 return; 115 } 116 } 117 printf("0x%02x ", tos); 118 } 119 120 /* Final check; must have specified --tos. */ 121 static void 122 final_check(unsigned int flags) 123 { 124 if (!flags) 125 exit_error(PARAMETER_PROBLEM, 126 "TOS match: You must specify `--tos'"); 127 } 128 129 /* Prints out the matchinfo. */ 130 static void 131 print(const struct ipt_ip *ip, 132 const struct ipt_entry_match *match, 133 int numeric) 134 { 135 const struct ipt_tos_info *info = (const struct ipt_tos_info *)match->data; 136 137 printf("TOS match "); 138 if (info->invert) 139 printf("!"); 140 print_tos(info->tos, numeric); 141 } 142 143 /* Saves the union ipt_matchinfo in parsable form to stdout. */ 144 static void 145 save(const struct ipt_ip *ip, const struct ipt_entry_match *match) 146 { 147 const struct ipt_tos_info *info = (const struct ipt_tos_info *)match->data; 148 149 if (info->invert) 150 printf("! "); 151 printf("--tos "); 152 print_tos(info->tos, 0); 153 } 154 155 static struct iptables_match tos = { 156 .next = NULL, 157 .name = "tos", 158 .version = IPTABLES_VERSION, 159 .size = IPT_ALIGN(sizeof(struct ipt_tos_info)), 160 .userspacesize = IPT_ALIGN(sizeof(struct ipt_tos_info)), 161 .help = &help, 162 .parse = &parse, 163 .final_check = &final_check, 164 .print = &print, 165 .save = &save, 166 .extra_opts = opts 167 }; 168 169 void ipt_2tos_init(void) 170 { 171 register_match(&tos); 172 } 173