7a10a5022f260e31fbfb331ada3f4fd1054c7981
[iptables.git] / extensions / libipt_tos.c
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 unsigned 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 _init(void)
170 {
171         register_match(&tos);
172 }