fix for f12, gcc4.4
[iptables.git] / extensions / libipt_ipv4options.c
1 /* Shared library add-on to iptables to add ipv4 options 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_ipv4options.h>
10
11 /* Function which prints out usage message. */
12 static void
13 help(void)
14 {
15         printf(
16 "ipv4options v%s options:\n"
17 "      --ssrr    (match strict source routing flag)\n"
18 "      --lsrr    (match loose  source routing flag)\n"
19 "      --no-srr  (match packets with no source routing)\n\n"
20 "  [!] --rr      (match record route flag)\n\n"
21 "  [!] --ts      (match timestamp flag)\n\n"
22 "  [!] --ra      (match router-alert option)\n\n"
23 "  [!] --any-opt (match any option or no option at all if used with '!')\n",
24 IPTABLES_VERSION);
25 }
26
27 static struct option opts[] = {
28         { "ssrr", 0, 0, '1' },
29         { "lsrr", 0, 0, '2' },
30         { "no-srr", 0, 0, '3'},
31         { "rr", 0, 0, '4'},
32         { "ts", 0, 0, '5'},
33         { "ra", 0, 0, '6'},
34         { "any-opt", 0, 0, '7'},
35         {0}
36 };
37
38 /* Function which parses command options; returns true if it
39    ate an option */
40 static int
41 parse(int c, char **argv, int invert, unsigned int *flags,
42       const struct ipt_entry *entry,
43       struct ipt_entry_match **match)
44 {
45         struct ipt_ipv4options_info *info = (struct ipt_ipv4options_info *)(*match)->data;
46
47         switch (c)
48         {
49                 /* strict-source-routing */
50         case '1':
51                 if (invert) 
52                         exit_error(PARAMETER_PROBLEM,
53                                    "ipv4options: unexpected `!' with --ssrr");
54                 if (*flags & IPT_IPV4OPTION_MATCH_SSRR)
55                         exit_error(PARAMETER_PROBLEM,
56                                    "Can't specify --ssrr twice");
57                 if (*flags & IPT_IPV4OPTION_MATCH_LSRR)
58                         exit_error(PARAMETER_PROBLEM,
59                                    "Can't specify --ssrr with --lsrr");
60                 if (*flags & IPT_IPV4OPTION_DONT_MATCH_SRR)
61                         exit_error(PARAMETER_PROBLEM,
62                                    "Can't specify --ssrr with --no-srr");
63
64                 info->options |= IPT_IPV4OPTION_MATCH_SSRR;
65                 *flags |= IPT_IPV4OPTION_MATCH_SSRR;
66                 break;
67
68                 /* loose-source-routing */
69         case '2':
70                 if (invert) 
71                         exit_error(PARAMETER_PROBLEM,
72                                    "ipv4options: unexpected `!' with --lsrr");
73                 if (*flags & IPT_IPV4OPTION_MATCH_SSRR)
74                         exit_error(PARAMETER_PROBLEM,
75                                    "Can't specify --lsrr twice");
76                 if (*flags & IPT_IPV4OPTION_MATCH_LSRR)
77                         exit_error(PARAMETER_PROBLEM,
78                                    "Can't specify --lsrr with --ssrr");
79                 if (*flags & IPT_IPV4OPTION_DONT_MATCH_SRR)
80                         exit_error(PARAMETER_PROBLEM,
81                                    "Can't specify --lsrr with --no-srr");
82                 info->options |= IPT_IPV4OPTION_MATCH_LSRR;
83                 *flags |= IPT_IPV4OPTION_MATCH_LSRR;
84                 break;
85
86                 /* no-source-routing */
87         case '3':
88                 if (invert) 
89                         exit_error(PARAMETER_PROBLEM,
90                                            "ipv4options: unexpected `!' with --no-srr");
91                 if (*flags & IPT_IPV4OPTION_DONT_MATCH_SRR)
92                         exit_error(PARAMETER_PROBLEM,
93                                    "Can't specify --no-srr twice");
94                 if (*flags & IPT_IPV4OPTION_MATCH_SSRR)
95                         exit_error(PARAMETER_PROBLEM,
96                                    "Can't specify --no-srr with --ssrr");
97                 if (*flags & IPT_IPV4OPTION_MATCH_LSRR)
98                         exit_error(PARAMETER_PROBLEM,
99                                    "Can't specify --no-srr with --lsrr");
100                 info->options |= IPT_IPV4OPTION_DONT_MATCH_SRR;
101                 *flags |= IPT_IPV4OPTION_DONT_MATCH_SRR;
102                 break;
103
104                 /* record-route */
105         case '4':
106                 if ((!invert) && (*flags & IPT_IPV4OPTION_MATCH_RR))
107                         exit_error(PARAMETER_PROBLEM,
108                                    "Can't specify --rr twice"); 
109                 if (invert && (*flags & IPT_IPV4OPTION_DONT_MATCH_RR))
110                         exit_error(PARAMETER_PROBLEM,
111                                    "Can't specify ! --rr twice");
112                 if ((!invert) && (*flags & IPT_IPV4OPTION_DONT_MATCH_RR))
113                         exit_error(PARAMETER_PROBLEM,
114                                    "Can't specify --rr with ! --rr");
115                 if (invert && (*flags & IPT_IPV4OPTION_MATCH_RR))
116                         exit_error(PARAMETER_PROBLEM,
117                                    "Can't specify ! --rr with --rr");
118                 if (invert) {
119                         info->options |= IPT_IPV4OPTION_DONT_MATCH_RR;
120                         *flags |= IPT_IPV4OPTION_DONT_MATCH_RR;
121                 }
122                 else {
123                         info->options |= IPT_IPV4OPTION_MATCH_RR;
124                         *flags |= IPT_IPV4OPTION_MATCH_RR;
125                 }
126                 break;
127
128                 /* timestamp */
129         case '5':
130                 if ((!invert) && (*flags & IPT_IPV4OPTION_MATCH_TIMESTAMP))
131                         exit_error(PARAMETER_PROBLEM,
132                                    "Can't specify --ts twice"); 
133                 if (invert && (*flags & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP))
134                         exit_error(PARAMETER_PROBLEM,
135                                    "Can't specify ! --ts twice");
136                 if ((!invert) && (*flags & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP))
137                         exit_error(PARAMETER_PROBLEM,
138                                    "Can't specify --ts with ! --ts");
139                 if (invert && (*flags & IPT_IPV4OPTION_MATCH_TIMESTAMP))
140                         exit_error(PARAMETER_PROBLEM,
141                                    "Can't specify ! --ts with --ts");
142                 if (invert) {
143                         info->options |= IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP;
144                         *flags |= IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP;
145                 }
146                 else {
147                         info->options |= IPT_IPV4OPTION_MATCH_TIMESTAMP;
148                         *flags |= IPT_IPV4OPTION_MATCH_TIMESTAMP;
149                 }
150                 break;
151
152                 /* router-alert  */
153         case '6':
154                 if ((!invert) && (*flags & IPT_IPV4OPTION_MATCH_ROUTER_ALERT))
155                         exit_error(PARAMETER_PROBLEM,
156                                    "Can't specify --ra twice"); 
157                 if (invert && (*flags & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT))
158                         exit_error(PARAMETER_PROBLEM,
159                                    "Can't specify ! --rr twice");
160                 if ((!invert) && (*flags & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT))
161                         exit_error(PARAMETER_PROBLEM,
162                                    "Can't specify --ra with ! --ra");
163                 if (invert && (*flags & IPT_IPV4OPTION_MATCH_ROUTER_ALERT))
164                         exit_error(PARAMETER_PROBLEM,
165                                    "Can't specify ! --ra with --ra");
166                 if (invert) {
167                         info->options |= IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT;
168                         *flags |= IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT;
169                 }
170                 else {
171                         info->options |= IPT_IPV4OPTION_MATCH_ROUTER_ALERT;
172                         *flags |= IPT_IPV4OPTION_MATCH_ROUTER_ALERT;
173                 }
174                 break;
175
176                 /* any option */
177         case '7' :
178                 if ((!invert) && (*flags & IPT_IPV4OPTION_MATCH_ANY_OPT))
179                         exit_error(PARAMETER_PROBLEM,
180                                    "Can't specify --any-opt twice");
181                 if (invert && (*flags & IPT_IPV4OPTION_MATCH_ANY_OPT))
182                         exit_error(PARAMETER_PROBLEM,
183                                    "Can't specify ! --any-opt with --any-opt");
184                 if (invert && (*flags & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT))
185                         exit_error(PARAMETER_PROBLEM,
186                                    "Can't specify ! --any-opt twice");
187                 if ((!invert) &&
188                     ((*flags & IPT_IPV4OPTION_DONT_MATCH_SRR)       ||
189                      (*flags & IPT_IPV4OPTION_DONT_MATCH_RR)        ||
190                      (*flags & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) ||
191                      (*flags & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT)))
192                         exit_error(PARAMETER_PROBLEM,
193                                    "Can't specify --any-opt with any other negative ipv4options match");
194                 if (invert &&
195                     ((*flags & IPT_IPV4OPTION_MATCH_LSRR)      ||
196                      (*flags & IPT_IPV4OPTION_MATCH_SSRR)      ||
197                      (*flags & IPT_IPV4OPTION_MATCH_RR)        ||
198                      (*flags & IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
199                      (*flags & IPT_IPV4OPTION_MATCH_ROUTER_ALERT)))
200                         exit_error(PARAMETER_PROBLEM,
201                                    "Can't specify ! --any-opt with any other positive ipv4options match");
202                 if (invert) {
203                         info->options |= IPT_IPV4OPTION_DONT_MATCH_ANY_OPT;
204                         *flags |= IPT_IPV4OPTION_DONT_MATCH_ANY_OPT;    
205                 }
206                 else {
207                         info->options |= IPT_IPV4OPTION_MATCH_ANY_OPT;
208                         *flags |= IPT_IPV4OPTION_MATCH_ANY_OPT;
209                 }
210                 break;
211
212         default:
213                 return 0;
214         }
215         return 1;
216 }
217
218 static void
219 final_check(unsigned int flags)
220 {
221         if (flags == 0)
222                 exit_error(PARAMETER_PROBLEM,
223                            "ipv4options match: you must specify some parameters. See iptables -m ipv4options --help for help.'");
224 }
225
226 /* Prints out the matchinfo. */
227 static void
228 print(const struct ipt_ip *ip,
229       const struct ipt_entry_match *match,
230       int numeric)
231 {
232         struct ipt_ipv4options_info *info = ((struct ipt_ipv4options_info *)match->data);
233
234         printf(" IPV4OPTS");
235         if (info->options & IPT_IPV4OPTION_MATCH_SSRR)
236                 printf(" SSRR");
237         else if (info->options & IPT_IPV4OPTION_MATCH_LSRR)
238                 printf(" LSRR");
239         else if (info->options & IPT_IPV4OPTION_DONT_MATCH_SRR)
240                 printf(" !SRR");
241         if (info->options & IPT_IPV4OPTION_MATCH_RR)
242                 printf(" RR");
243         else if (info->options & IPT_IPV4OPTION_DONT_MATCH_RR)
244                 printf(" !RR");
245         if (info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP)
246                 printf(" TS");
247         else if (info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP)
248                 printf(" !TS");
249         if (info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT)
250                 printf(" RA");
251         else if (info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT)
252                 printf(" !RA");
253         if (info->options & IPT_IPV4OPTION_MATCH_ANY_OPT)
254                 printf(" ANYOPT ");
255         else if (info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)
256                 printf(" NOOPT");
257
258         printf(" ");
259 }
260
261 /* Saves the data in parsable form to stdout. */
262 static void
263 save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
264 {
265         struct ipt_ipv4options_info *info = ((struct ipt_ipv4options_info *)match->data);
266
267         if (info->options & IPT_IPV4OPTION_MATCH_SSRR)
268                 printf(" --ssrr");
269         else if (info->options & IPT_IPV4OPTION_MATCH_LSRR)
270                 printf(" --lsrr");
271         else if (info->options & IPT_IPV4OPTION_DONT_MATCH_SRR)
272                 printf(" --no-srr");
273         if (info->options & IPT_IPV4OPTION_MATCH_RR)
274                 printf(" --rr");
275         else if (info->options & IPT_IPV4OPTION_DONT_MATCH_RR)
276                 printf(" ! --rr");
277         if (info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP)
278                 printf(" --ts");
279         else if (info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP)
280                 printf(" ! --ts");
281         if (info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT)
282                 printf(" --ra");
283         else if (info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT)
284                 printf(" ! --ra");
285         if (info->options & IPT_IPV4OPTION_MATCH_ANY_OPT)
286                 printf(" --any-opt");
287         if (info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)
288                 printf(" ! --any-opt");
289
290         printf(" ");
291 }
292
293 static struct iptables_match ipv4options_struct = { 
294         .next           = NULL,
295         .name           = "ipv4options",
296         .version        = IPTABLES_VERSION,
297         .size           = IPT_ALIGN(sizeof(struct ipt_ipv4options_info)),
298         .userspacesize  = IPT_ALIGN(sizeof(struct ipt_ipv4options_info)),
299         .help           = &help,
300         .parse          = &parse,
301         .final_check    = &final_check,
302         .print          = &print,
303         .save           = &save,
304         .extra_opts     = opts
305 };
306
307 void _init(void)
308 {
309         register_match(&ipv4options_struct);
310 }