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