Busybox: Upgrade to 1.21.1 (stable). lsof active.
[tomato.git] / release / src / router / iptables / extensions / libipt_multiport.c
blob18214d90f8457341306e5281a1950a1251ab42d2
1 /* Shared library add-on to iptables to add multiple TCP port support. */
2 #include <stdio.h>
3 #include <netdb.h>
4 #include <string.h>
5 #include <stdlib.h>
6 #include <getopt.h>
7 #include <iptables.h>
8 /* To ensure that iptables compiles with an old kernel */
9 #include "../include/linux/netfilter_ipv4/ipt_multiport.h"
11 /* Function which prints out usage message. */
12 #if 0
13 static void
14 help(void)
16 printf(
17 "multiport v%s options:\n"
18 " --source-ports port[,port,port...]\n"
19 " --sports ...\n"
20 " match source port(s)\n"
21 " --destination-ports port[,port,port...]\n"
22 " --dports ...\n"
23 " match destination port(s)\n"
24 " --ports port[,port,port]\n"
25 " match both source and destination port(s)\n"
26 " NOTE: this kernel does not support port ranges in multiport.\n",
27 IPTABLES_VERSION);
29 #endif
31 static void
32 help_v1(void)
34 printf(
35 "multiport v%s options:\n"
36 " --source-ports [!] port[,port:port,port...]\n"
37 " --sports ...\n"
38 " match source port(s)\n"
39 " --destination-ports [!] port[,port:port,port...]\n"
40 " --dports ...\n"
41 " match destination port(s)\n"
42 " --ports [!] port[,port:port,port]\n"
43 " match both source and destination port(s)\n",
44 IPTABLES_VERSION);
47 static struct option opts[] = {
48 { "source-ports", 1, 0, '1' },
49 { "sports", 1, 0, '1' }, /* synonym */
50 { "destination-ports", 1, 0, '2' },
51 { "dports", 1, 0, '2' }, /* synonym */
52 { "ports", 1, 0, '3' },
53 {0}
56 static char *
57 proto_to_name(u_int8_t proto)
59 switch (proto) {
60 case IPPROTO_TCP:
61 return "tcp";
62 case IPPROTO_UDP:
63 return "udp";
64 case IPPROTO_UDPLITE:
65 return "udplite";
66 case IPPROTO_SCTP:
67 return "sctp";
68 case IPPROTO_DCCP:
69 return "dccp";
70 default:
71 return NULL;
75 #if 0
76 static unsigned int
77 parse_multi_ports(const char *portstring, u_int16_t *ports, const char *proto)
79 char *buffer, *cp, *next;
80 unsigned int i;
82 buffer = strdup(portstring);
83 if (!buffer) exit_error(OTHER_PROBLEM, "strdup failed");
85 for (cp=buffer, i=0; cp && i<IPT_MULTI_PORTS; cp=next,i++)
87 next=strchr(cp, ',');
88 if (next) *next++='\0';
89 ports[i] = parse_port(cp, proto);
91 if (cp) exit_error(PARAMETER_PROBLEM, "too many ports specified");
92 free(buffer);
93 return i;
95 #endif
97 static void
98 parse_multi_ports_v1(const char *portstring,
99 struct ipt_multiport_v1 *multiinfo,
100 const char *proto)
102 char *buffer, *cp, *next, *range;
103 unsigned int i;
104 u_int16_t m;
106 buffer = strdup(portstring);
107 if (!buffer) exit_error(OTHER_PROBLEM, "strdup failed");
109 for (i=0; i<IPT_MULTI_PORTS; i++)
110 multiinfo->pflags[i] = 0;
112 for (cp=buffer, i=0; cp && i<IPT_MULTI_PORTS; cp=next, i++) {
113 next=strchr(cp, ',');
114 if (next) *next++='\0';
115 range = strchr(cp, ':');
116 if (range) {
117 if (i == IPT_MULTI_PORTS-1)
118 exit_error(PARAMETER_PROBLEM,
119 "too many ports specified");
120 *range++ = '\0';
122 multiinfo->ports[i] = parse_port(cp, proto);
123 if (range) {
124 multiinfo->pflags[i] = 1;
125 multiinfo->ports[++i] = parse_port(range, proto);
126 if (multiinfo->ports[i-1] >= multiinfo->ports[i])
127 exit_error(PARAMETER_PROBLEM,
128 "invalid portrange specified");
129 m <<= 1;
132 multiinfo->count = i;
133 if (cp) exit_error(PARAMETER_PROBLEM, "too many ports specified");
134 free(buffer);
137 /* Initialize the match. */
138 static void
139 init(struct ipt_entry_match *m, unsigned int *nfcache)
143 static const char *
144 check_proto(const struct ipt_entry *entry)
146 char *proto;
148 if (entry->ip.invflags & IPT_INV_PROTO)
149 exit_error(PARAMETER_PROBLEM,
150 "multiport only works with TCP, UDP, UDPLITE, SCTP and DCCP");
152 if ((proto = proto_to_name(entry->ip.proto)) != NULL)
153 return proto;
154 else if (!entry->ip.proto)
155 exit_error(PARAMETER_PROBLEM,
156 "multiport needs `-p tcp', `-p udp', `-p udplite', "
157 "`-p sctp' or `-p dccp'");
158 else
159 exit_error(PARAMETER_PROBLEM,
160 "multiport only works with TCP, UDP, UDPLITE, SCTP and DCCP");
163 /* Function which parses command options; returns true if it
164 ate an option */
165 #if 0
166 static int
167 parse(int c, char **argv, int invert, unsigned int *flags,
168 const struct ipt_entry *entry,
169 unsigned int *nfcache,
170 struct ipt_entry_match **match)
172 const char *proto;
173 struct ipt_multiport *multiinfo
174 = (struct ipt_multiport *)(*match)->data;
176 switch (c) {
177 case '1':
178 check_inverse(argv[optind-1], &invert, &optind, 0);
179 proto = check_proto(entry);
180 multiinfo->count = parse_multi_ports(argv[optind-1],
181 multiinfo->ports, proto);
182 multiinfo->flags = IPT_MULTIPORT_SOURCE;
183 break;
185 case '2':
186 check_inverse(argv[optind-1], &invert, &optind, 0);
187 proto = check_proto(entry);
188 multiinfo->count = parse_multi_ports(argv[optind-1],
189 multiinfo->ports, proto);
190 multiinfo->flags = IPT_MULTIPORT_DESTINATION;
191 break;
193 case '3':
194 check_inverse(argv[optind-1], &invert, &optind, 0);
195 proto = check_proto(entry);
196 multiinfo->count = parse_multi_ports(argv[optind-1],
197 multiinfo->ports, proto);
198 multiinfo->flags = IPT_MULTIPORT_EITHER;
199 break;
201 default:
202 return 0;
205 if (invert)
206 exit_error(PARAMETER_PROBLEM,
207 "multiport does not support invert");
209 if (*flags)
210 exit_error(PARAMETER_PROBLEM,
211 "multiport can only have one option");
212 *flags = 1;
213 return 1;
215 #endif
217 static int
218 parse_v1(int c, char **argv, int invert, unsigned int *flags,
219 const struct ipt_entry *entry,
220 unsigned int *nfcache,
221 struct ipt_entry_match **match)
223 const char *proto;
224 struct ipt_multiport_v1 *multiinfo
225 = (struct ipt_multiport_v1 *)(*match)->data;
227 switch (c) {
228 case '1':
229 check_inverse(argv[optind-1], &invert, &optind, 0);
230 proto = check_proto(entry);
231 parse_multi_ports_v1(argv[optind-1], multiinfo, proto);
232 multiinfo->flags = IPT_MULTIPORT_SOURCE;
233 break;
235 case '2':
236 check_inverse(argv[optind-1], &invert, &optind, 0);
237 proto = check_proto(entry);
238 parse_multi_ports_v1(argv[optind-1], multiinfo, proto);
239 multiinfo->flags = IPT_MULTIPORT_DESTINATION;
240 break;
242 case '3':
243 check_inverse(argv[optind-1], &invert, &optind, 0);
244 proto = check_proto(entry);
245 parse_multi_ports_v1(argv[optind-1], multiinfo, proto);
246 multiinfo->flags = IPT_MULTIPORT_EITHER;
247 break;
249 default:
250 return 0;
253 if (invert)
254 multiinfo->invert = 1;
256 if (*flags)
257 exit_error(PARAMETER_PROBLEM,
258 "multiport can only have one option");
259 *flags = 1;
260 return 1;
263 /* Final check; must specify something. */
264 static void
265 final_check(unsigned int flags)
267 if (!flags)
268 exit_error(PARAMETER_PROBLEM, "multiport expection an option");
271 static char *
272 port_to_service(int port, u_int8_t proto)
274 struct servent *service;
276 if ((service = getservbyport(htons(port), proto_to_name(proto))))
277 return service->s_name;
279 return NULL;
282 static void
283 print_port(u_int16_t port, u_int8_t protocol, int numeric)
285 char *service;
287 if (numeric || (service = port_to_service(port, protocol)) == NULL)
288 printf("%u", port);
289 else
290 printf("%s", service);
293 /* Prints out the matchinfo. */
294 #if 0
295 static void
296 print(const struct ipt_ip *ip,
297 const struct ipt_entry_match *match,
298 int numeric)
300 const struct ipt_multiport *multiinfo
301 = (const struct ipt_multiport *)match->data;
302 unsigned int i;
304 printf("multiport ");
306 switch (multiinfo->flags) {
307 case IPT_MULTIPORT_SOURCE:
308 printf("sports ");
309 break;
311 case IPT_MULTIPORT_DESTINATION:
312 printf("dports ");
313 break;
315 case IPT_MULTIPORT_EITHER:
316 printf("ports ");
317 break;
319 default:
320 printf("ERROR ");
321 break;
324 for (i=0; i < multiinfo->count; i++) {
325 printf("%s", i ? "," : "");
326 print_port(multiinfo->ports[i], ip->proto, numeric);
328 printf(" ");
330 #endif
332 static void
333 print_v1(const struct ipt_ip *ip,
334 const struct ipt_entry_match *match,
335 int numeric)
337 const struct ipt_multiport_v1 *multiinfo
338 = (const struct ipt_multiport_v1 *)match->data;
339 unsigned int i;
341 printf("multiport ");
343 switch (multiinfo->flags) {
344 case IPT_MULTIPORT_SOURCE:
345 printf("sports ");
346 break;
348 case IPT_MULTIPORT_DESTINATION:
349 printf("dports ");
350 break;
352 case IPT_MULTIPORT_EITHER:
353 printf("ports ");
354 break;
356 default:
357 printf("ERROR ");
358 break;
361 if (multiinfo->invert)
362 printf("! ");
364 for (i=0; i < multiinfo->count; i++) {
365 printf("%s", i ? "," : "");
366 print_port(multiinfo->ports[i], ip->proto, numeric);
367 if (multiinfo->pflags[i]) {
368 printf(":");
369 print_port(multiinfo->ports[++i], ip->proto, numeric);
372 printf(" ");
375 /* Saves the union ipt_matchinfo in parsable form to stdout. */
376 #if 0
377 static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
379 const struct ipt_multiport *multiinfo
380 = (const struct ipt_multiport *)match->data;
381 unsigned int i;
383 switch (multiinfo->flags) {
384 case IPT_MULTIPORT_SOURCE:
385 printf("--sports ");
386 break;
388 case IPT_MULTIPORT_DESTINATION:
389 printf("--dports ");
390 break;
392 case IPT_MULTIPORT_EITHER:
393 printf("--ports ");
394 break;
397 for (i=0; i < multiinfo->count; i++) {
398 printf("%s", i ? "," : "");
399 print_port(multiinfo->ports[i], ip->proto, 1);
401 printf(" ");
403 #endif
405 static void save_v1(const struct ipt_ip *ip,
406 const struct ipt_entry_match *match)
408 const struct ipt_multiport_v1 *multiinfo
409 = (const struct ipt_multiport_v1 *)match->data;
410 unsigned int i;
412 switch (multiinfo->flags) {
413 case IPT_MULTIPORT_SOURCE:
414 printf("--sports ");
415 break;
417 case IPT_MULTIPORT_DESTINATION:
418 printf("--dports ");
419 break;
421 case IPT_MULTIPORT_EITHER:
422 printf("--ports ");
423 break;
426 if (multiinfo->invert)
427 printf("! ");
429 for (i=0; i < multiinfo->count; i++) {
430 printf("%s", i ? "," : "");
431 print_port(multiinfo->ports[i], ip->proto, 1);
432 if (multiinfo->pflags[i]) {
433 printf(":");
434 print_port(multiinfo->ports[++i], ip->proto, 1);
437 printf(" ");
440 #if 0
441 static struct iptables_match multiport = {
442 .next = NULL,
443 .name = "multiport",
444 .revision = 0,
445 .version = IPTABLES_VERSION,
446 .size = IPT_ALIGN(sizeof(struct ipt_multiport)),
447 .userspacesize = IPT_ALIGN(sizeof(struct ipt_multiport)),
448 .help = &help,
449 .init = &init,
450 .parse = &parse,
451 .final_check = &final_check,
452 .print = &print,
453 .save = &save,
454 .extra_opts = opts
456 #endif
458 static struct iptables_match multiport_v1 = {
459 .next = NULL,
460 .name = "multiport",
461 .version = IPTABLES_VERSION,
462 .revision = 1,
463 .size = IPT_ALIGN(sizeof(struct ipt_multiport_v1)),
464 .userspacesize = IPT_ALIGN(sizeof(struct ipt_multiport_v1)),
465 .help = &help_v1,
466 .init = &init,
467 .parse = &parse_v1,
468 .final_check = &final_check,
469 .print = &print_v1,
470 .save = &save_v1,
471 .extra_opts = opts
474 void
475 _init(void)
477 #if 0
478 register_match(&multiport);
479 #endif
480 register_match(&multiport_v1);