Home | History | Annotate | Download | only in extensions
      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