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