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