blob: dae6e3350a1d19a16df6739d875970b7a9b054d0 [file] [log] [blame]
Marc Bouchere6869a82000-03-20 06:03:29 +00001/* 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>
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +00007
8#include <xtables.h>
9#include <libiptc/libiptc.h>
Yasuyuki KOZAKAIdf2cf4f2007-07-24 06:49:15 +000010#include <libiptc/libip6tc.h>
Jan Engelhardta2a7f2b2008-09-01 14:20:13 +020011#include <linux/netfilter/xt_multiport.h>
Marc Bouchere6869a82000-03-20 06:03:29 +000012
13/* Function which prints out usage message. */
Jan Engelhardt181dead2007-10-04 16:27:07 +000014static void multiport_help(void)
Marc Bouchere6869a82000-03-20 06:03:29 +000015{
16 printf(
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +020017"multiport match options:\n"
Marc Bouchere6869a82000-03-20 06:03:29 +000018" --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"
Pablo Neira5df95472005-01-03 09:37:07 +000025" match both source and destination port(s)\n"
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +020026" NOTE: this kernel does not support port ranges in multiport.\n");
Pablo Neira5df95472005-01-03 09:37:07 +000027}
28
Jan Engelhardt181dead2007-10-04 16:27:07 +000029static void multiport_help_v1(void)
Pablo Neira5df95472005-01-03 09:37:07 +000030{
31 printf(
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +020032"multiport match options:\n"
Jan Engelhardt96727922008-08-13 14:42:41 +020033"[!] --source-ports port[,port:port,port...]\n"
Pablo Neira5df95472005-01-03 09:37:07 +000034" --sports ...\n"
35" match source port(s)\n"
Jan Engelhardt96727922008-08-13 14:42:41 +020036"[!] --destination-ports port[,port:port,port...]\n"
Pablo Neira5df95472005-01-03 09:37:07 +000037" --dports ...\n"
38" match destination port(s)\n"
Jan Engelhardt96727922008-08-13 14:42:41 +020039"[!] --ports port[,port:port,port]\n"
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +020040" match both source and destination port(s)\n");
Marc Bouchere6869a82000-03-20 06:03:29 +000041}
42
Jan Engelhardt181dead2007-10-04 16:27:07 +000043static const struct option multiport_opts[] = {
Patrick McHardy500f4832007-09-08 15:59:04 +000044 { "source-ports", 1, NULL, '1' },
45 { "sports", 1, NULL, '1' }, /* synonym */
46 { "destination-ports", 1, NULL, '2' },
47 { "dports", 1, NULL, '2' }, /* synonym */
48 { "ports", 1, NULL, '3' },
Max Kellermann9ee386a2008-01-29 13:48:05 +000049 { .name = NULL }
Marc Bouchere6869a82000-03-20 06:03:29 +000050};
51
Patrick McHardyJesper Brouerc1eae412006-07-25 01:50:48 +000052static char *
53proto_to_name(u_int8_t proto)
54{
55 switch (proto) {
56 case IPPROTO_TCP:
57 return "tcp";
58 case IPPROTO_UDP:
59 return "udp";
Patrick McHardy95616062007-01-11 09:08:22 +000060 case IPPROTO_UDPLITE:
61 return "udplite";
Patrick McHardyJesper Brouerc1eae412006-07-25 01:50:48 +000062 case IPPROTO_SCTP:
63 return "sctp";
64 case IPPROTO_DCCP:
65 return "dccp";
66 default:
67 return NULL;
68 }
69}
70
Marc Bouchere6869a82000-03-20 06:03:29 +000071static unsigned int
72parse_multi_ports(const char *portstring, u_int16_t *ports, const char *proto)
73{
74 char *buffer, *cp, *next;
75 unsigned int i;
76
77 buffer = strdup(portstring);
78 if (!buffer) exit_error(OTHER_PROBLEM, "strdup failed");
79
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +000080 for (cp=buffer, i=0; cp && i<XT_MULTI_PORTS; cp=next,i++)
Marc Bouchere6869a82000-03-20 06:03:29 +000081 {
82 next=strchr(cp, ',');
83 if (next) *next++='\0';
84 ports[i] = parse_port(cp, proto);
85 }
86 if (cp) exit_error(PARAMETER_PROBLEM, "too many ports specified");
87 free(buffer);
88 return i;
89}
90
Pablo Neira5df95472005-01-03 09:37:07 +000091static void
92parse_multi_ports_v1(const char *portstring,
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +000093 struct xt_multiport_v1 *multiinfo,
Pablo Neira5df95472005-01-03 09:37:07 +000094 const char *proto)
95{
96 char *buffer, *cp, *next, *range;
97 unsigned int i;
98 u_int16_t m;
99
100 buffer = strdup(portstring);
101 if (!buffer) exit_error(OTHER_PROBLEM, "strdup failed");
102
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000103 for (i=0; i<XT_MULTI_PORTS; i++)
Pablo Neira5df95472005-01-03 09:37:07 +0000104 multiinfo->pflags[i] = 0;
105
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000106 for (cp=buffer, i=0; cp && i<XT_MULTI_PORTS; cp=next, i++) {
Pablo Neira5df95472005-01-03 09:37:07 +0000107 next=strchr(cp, ',');
108 if (next) *next++='\0';
109 range = strchr(cp, ':');
110 if (range) {
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000111 if (i == XT_MULTI_PORTS-1)
Pablo Neira5df95472005-01-03 09:37:07 +0000112 exit_error(PARAMETER_PROBLEM,
113 "too many ports specified");
114 *range++ = '\0';
115 }
116 multiinfo->ports[i] = parse_port(cp, proto);
117 if (range) {
118 multiinfo->pflags[i] = 1;
119 multiinfo->ports[++i] = parse_port(range, proto);
120 if (multiinfo->ports[i-1] >= multiinfo->ports[i])
121 exit_error(PARAMETER_PROBLEM,
122 "invalid portrange specified");
123 m <<= 1;
124 }
125 }
126 multiinfo->count = i;
127 if (cp) exit_error(PARAMETER_PROBLEM, "too many ports specified");
128 free(buffer);
129}
130
Marc Bouchere6869a82000-03-20 06:03:29 +0000131static const char *
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000132check_proto(u_int16_t pnum, u_int8_t invflags)
Marc Bouchere6869a82000-03-20 06:03:29 +0000133{
Patrick McHardy2452baf2006-04-28 08:10:08 +0000134 char *proto;
135
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000136 if (invflags & XT_INV_PROTO)
Rusty Russell225f4622005-01-03 09:51:58 +0000137 exit_error(PARAMETER_PROBLEM,
Patrick McHardy95616062007-01-11 09:08:22 +0000138 "multiport only works with TCP, UDP, UDPLITE, SCTP and DCCP");
Rusty Russell225f4622005-01-03 09:51:58 +0000139
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000140 if ((proto = proto_to_name(pnum)) != NULL)
Patrick McHardy2452baf2006-04-28 08:10:08 +0000141 return proto;
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000142 else if (!pnum)
Marc Bouchere6869a82000-03-20 06:03:29 +0000143 exit_error(PARAMETER_PROBLEM,
Patrick McHardy95616062007-01-11 09:08:22 +0000144 "multiport needs `-p tcp', `-p udp', `-p udplite', "
145 "`-p sctp' or `-p dccp'");
Marc Bouchere6869a82000-03-20 06:03:29 +0000146 else
147 exit_error(PARAMETER_PROBLEM,
Patrick McHardy95616062007-01-11 09:08:22 +0000148 "multiport only works with TCP, UDP, UDPLITE, SCTP and DCCP");
Marc Bouchere6869a82000-03-20 06:03:29 +0000149}
150
151/* Function which parses command options; returns true if it
152 ate an option */
153static int
Jan Engelhardt181dead2007-10-04 16:27:07 +0000154__multiport_parse(int c, char **argv, int invert, unsigned int *flags,
155 struct xt_entry_match **match, u_int16_t pnum,
156 u_int8_t invflags)
Marc Bouchere6869a82000-03-20 06:03:29 +0000157{
158 const char *proto;
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000159 struct xt_multiport *multiinfo
160 = (struct xt_multiport *)(*match)->data;
Marc Bouchere6869a82000-03-20 06:03:29 +0000161
162 switch (c) {
163 case '1':
Patrick McHardyd0a2e8a2004-09-18 17:43:36 +0000164 check_inverse(argv[optind-1], &invert, &optind, 0);
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000165 proto = check_proto(pnum, invflags);
Marc Bouchere6869a82000-03-20 06:03:29 +0000166 multiinfo->count = parse_multi_ports(argv[optind-1],
167 multiinfo->ports, proto);
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000168 multiinfo->flags = XT_MULTIPORT_SOURCE;
Marc Bouchere6869a82000-03-20 06:03:29 +0000169 break;
170
171 case '2':
Patrick McHardyd0a2e8a2004-09-18 17:43:36 +0000172 check_inverse(argv[optind-1], &invert, &optind, 0);
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000173 proto = check_proto(pnum, invflags);
Marc Bouchere6869a82000-03-20 06:03:29 +0000174 multiinfo->count = parse_multi_ports(argv[optind-1],
175 multiinfo->ports, proto);
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000176 multiinfo->flags = XT_MULTIPORT_DESTINATION;
Marc Bouchere6869a82000-03-20 06:03:29 +0000177 break;
178
179 case '3':
Patrick McHardyd0a2e8a2004-09-18 17:43:36 +0000180 check_inverse(argv[optind-1], &invert, &optind, 0);
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000181 proto = check_proto(pnum, invflags);
Marc Bouchere6869a82000-03-20 06:03:29 +0000182 multiinfo->count = parse_multi_ports(argv[optind-1],
183 multiinfo->ports, proto);
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000184 multiinfo->flags = XT_MULTIPORT_EITHER;
Marc Bouchere6869a82000-03-20 06:03:29 +0000185 break;
186
187 default:
188 return 0;
189 }
190
Patrick McHardyd0a2e8a2004-09-18 17:43:36 +0000191 if (invert)
192 exit_error(PARAMETER_PROBLEM,
193 "multiport does not support invert");
194
Marc Bouchere6869a82000-03-20 06:03:29 +0000195 if (*flags)
196 exit_error(PARAMETER_PROBLEM,
197 "multiport can only have one option");
198 *flags = 1;
199 return 1;
200}
201
Pablo Neira5df95472005-01-03 09:37:07 +0000202static int
Jan Engelhardt181dead2007-10-04 16:27:07 +0000203multiport_parse(int c, char **argv, int invert, unsigned int *flags,
204 const void *e, struct xt_entry_match **match)
Pablo Neira5df95472005-01-03 09:37:07 +0000205{
Yasuyuki KOZAKAIac8b2712007-07-24 06:06:59 +0000206 const struct ipt_entry *entry = e;
Jan Engelhardt181dead2007-10-04 16:27:07 +0000207 return __multiport_parse(c, argv, invert, flags, match,
208 entry->ip.proto, entry->ip.invflags);
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000209}
210
211static int
Jan Engelhardt181dead2007-10-04 16:27:07 +0000212multiport_parse6(int c, char **argv, int invert, unsigned int *flags,
213 const void *e, struct xt_entry_match **match)
Yasuyuki KOZAKAIdf2cf4f2007-07-24 06:49:15 +0000214{
215 const struct ip6t_entry *entry = (const struct ip6t_entry *)e;
Jan Engelhardt181dead2007-10-04 16:27:07 +0000216 return __multiport_parse(c, argv, invert, flags, match,
217 entry->ipv6.proto, entry->ipv6.invflags);
Yasuyuki KOZAKAIdf2cf4f2007-07-24 06:49:15 +0000218}
219
220static int
Jan Engelhardt181dead2007-10-04 16:27:07 +0000221__multiport_parse_v1(int c, char **argv, int invert, unsigned int *flags,
222 struct xt_entry_match **match, u_int16_t pnum,
223 u_int8_t invflags)
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000224{
Pablo Neira5df95472005-01-03 09:37:07 +0000225 const char *proto;
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000226 struct xt_multiport_v1 *multiinfo
227 = (struct xt_multiport_v1 *)(*match)->data;
Pablo Neira5df95472005-01-03 09:37:07 +0000228
229 switch (c) {
230 case '1':
231 check_inverse(argv[optind-1], &invert, &optind, 0);
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000232 proto = check_proto(pnum, invflags);
Pablo Neira5df95472005-01-03 09:37:07 +0000233 parse_multi_ports_v1(argv[optind-1], multiinfo, proto);
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000234 multiinfo->flags = XT_MULTIPORT_SOURCE;
Pablo Neira5df95472005-01-03 09:37:07 +0000235 break;
236
237 case '2':
238 check_inverse(argv[optind-1], &invert, &optind, 0);
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000239 proto = check_proto(pnum, invflags);
Pablo Neira5df95472005-01-03 09:37:07 +0000240 parse_multi_ports_v1(argv[optind-1], multiinfo, proto);
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000241 multiinfo->flags = XT_MULTIPORT_DESTINATION;
Pablo Neira5df95472005-01-03 09:37:07 +0000242 break;
243
244 case '3':
245 check_inverse(argv[optind-1], &invert, &optind, 0);
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000246 proto = check_proto(pnum, invflags);
Pablo Neira5df95472005-01-03 09:37:07 +0000247 parse_multi_ports_v1(argv[optind-1], multiinfo, proto);
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000248 multiinfo->flags = XT_MULTIPORT_EITHER;
Pablo Neira5df95472005-01-03 09:37:07 +0000249 break;
250
251 default:
252 return 0;
253 }
254
255 if (invert)
Phil Oesterb2eedcd2005-02-02 19:20:15 +0000256 multiinfo->invert = 1;
Pablo Neira5df95472005-01-03 09:37:07 +0000257
258 if (*flags)
259 exit_error(PARAMETER_PROBLEM,
260 "multiport can only have one option");
261 *flags = 1;
262 return 1;
263}
264
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000265static int
Jan Engelhardt181dead2007-10-04 16:27:07 +0000266multiport_parse_v1(int c, char **argv, int invert, unsigned int *flags,
267 const void *e, struct xt_entry_match **match)
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000268{
269 const struct ipt_entry *entry = e;
Jan Engelhardt181dead2007-10-04 16:27:07 +0000270 return __multiport_parse_v1(c, argv, invert, flags, match,
271 entry->ip.proto, entry->ip.invflags);
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000272}
273
Yasuyuki KOZAKAIdf2cf4f2007-07-24 06:49:15 +0000274static int
Jan Engelhardt181dead2007-10-04 16:27:07 +0000275multiport_parse6_v1(int c, char **argv, int invert, unsigned int *flags,
276 const void *e, struct xt_entry_match **match)
Yasuyuki KOZAKAIdf2cf4f2007-07-24 06:49:15 +0000277{
278 const struct ip6t_entry *entry = (const struct ip6t_entry *)e;
Jan Engelhardt181dead2007-10-04 16:27:07 +0000279 return __multiport_parse_v1(c, argv, invert, flags, match,
280 entry->ipv6.proto, entry->ipv6.invflags);
Yasuyuki KOZAKAIdf2cf4f2007-07-24 06:49:15 +0000281}
282
Marc Bouchere6869a82000-03-20 06:03:29 +0000283/* Final check; must specify something. */
Jan Engelhardt181dead2007-10-04 16:27:07 +0000284static void multiport_check(unsigned int flags)
Marc Bouchere6869a82000-03-20 06:03:29 +0000285{
286 if (!flags)
287 exit_error(PARAMETER_PROBLEM, "multiport expection an option");
288}
289
290static char *
291port_to_service(int port, u_int8_t proto)
292{
293 struct servent *service;
294
Patrick McHardyJesper Brouerc1eae412006-07-25 01:50:48 +0000295 if ((service = getservbyport(htons(port), proto_to_name(proto))))
Marc Bouchere6869a82000-03-20 06:03:29 +0000296 return service->s_name;
297
298 return NULL;
299}
300
301static void
302print_port(u_int16_t port, u_int8_t protocol, int numeric)
303{
304 char *service;
305
306 if (numeric || (service = port_to_service(port, protocol)) == NULL)
307 printf("%u", port);
308 else
309 printf("%s", service);
310}
311
312/* Prints out the matchinfo. */
313static void
Jan Engelhardt181dead2007-10-04 16:27:07 +0000314__multiport_print(const struct xt_entry_match *match, int numeric,
315 u_int16_t proto)
Marc Bouchere6869a82000-03-20 06:03:29 +0000316{
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000317 const struct xt_multiport *multiinfo
318 = (const struct xt_multiport *)match->data;
Marc Bouchere6869a82000-03-20 06:03:29 +0000319 unsigned int i;
320
321 printf("multiport ");
322
323 switch (multiinfo->flags) {
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000324 case XT_MULTIPORT_SOURCE:
Marc Bouchere6869a82000-03-20 06:03:29 +0000325 printf("sports ");
326 break;
327
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000328 case XT_MULTIPORT_DESTINATION:
Marc Bouchere6869a82000-03-20 06:03:29 +0000329 printf("dports ");
330 break;
331
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000332 case XT_MULTIPORT_EITHER:
Marc Bouchere6869a82000-03-20 06:03:29 +0000333 printf("ports ");
334 break;
335
336 default:
337 printf("ERROR ");
338 break;
339 }
340
341 for (i=0; i < multiinfo->count; i++) {
342 printf("%s", i ? "," : "");
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000343 print_port(multiinfo->ports[i], proto, numeric);
Marc Bouchere6869a82000-03-20 06:03:29 +0000344 }
345 printf(" ");
346}
347
Jan Engelhardt181dead2007-10-04 16:27:07 +0000348static void multiport_print(const void *ip_void,
349 const struct xt_entry_match *match, int numeric)
Pablo Neira5df95472005-01-03 09:37:07 +0000350{
Yasuyuki KOZAKAIac8b2712007-07-24 06:06:59 +0000351 const struct ipt_ip *ip = ip_void;
Jan Engelhardt181dead2007-10-04 16:27:07 +0000352 __multiport_print(match, numeric, ip->proto);
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000353}
354
Jan Engelhardt181dead2007-10-04 16:27:07 +0000355static void multiport_print6(const void *ip_void,
356 const struct xt_entry_match *match, int numeric)
Yasuyuki KOZAKAIdf2cf4f2007-07-24 06:49:15 +0000357{
358 const struct ip6t_ip6 *ip = (const struct ip6t_ip6 *)ip_void;
Jan Engelhardt181dead2007-10-04 16:27:07 +0000359 __multiport_print(match, numeric, ip->proto);
Yasuyuki KOZAKAIdf2cf4f2007-07-24 06:49:15 +0000360}
361
Jan Engelhardt181dead2007-10-04 16:27:07 +0000362static void __multiport_print_v1(const struct xt_entry_match *match,
363 int numeric, u_int16_t proto)
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000364{
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000365 const struct xt_multiport_v1 *multiinfo
366 = (const struct xt_multiport_v1 *)match->data;
Pablo Neira5df95472005-01-03 09:37:07 +0000367 unsigned int i;
368
369 printf("multiport ");
370
371 switch (multiinfo->flags) {
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000372 case XT_MULTIPORT_SOURCE:
Pablo Neira5df95472005-01-03 09:37:07 +0000373 printf("sports ");
374 break;
375
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000376 case XT_MULTIPORT_DESTINATION:
Pablo Neira5df95472005-01-03 09:37:07 +0000377 printf("dports ");
378 break;
379
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000380 case XT_MULTIPORT_EITHER:
Pablo Neira5df95472005-01-03 09:37:07 +0000381 printf("ports ");
382 break;
383
384 default:
385 printf("ERROR ");
386 break;
387 }
388
Phil Oesterb2eedcd2005-02-02 19:20:15 +0000389 if (multiinfo->invert)
390 printf("! ");
391
Pablo Neira5df95472005-01-03 09:37:07 +0000392 for (i=0; i < multiinfo->count; i++) {
393 printf("%s", i ? "," : "");
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000394 print_port(multiinfo->ports[i], proto, numeric);
Pablo Neira5df95472005-01-03 09:37:07 +0000395 if (multiinfo->pflags[i]) {
396 printf(":");
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000397 print_port(multiinfo->ports[++i], proto, numeric);
Pablo Neira5df95472005-01-03 09:37:07 +0000398 }
399 }
400 printf(" ");
401}
402
Jan Engelhardt181dead2007-10-04 16:27:07 +0000403static void multiport_print_v1(const void *ip_void,
404 const struct xt_entry_match *match, int numeric)
Marc Bouchere6869a82000-03-20 06:03:29 +0000405{
Yasuyuki KOZAKAIac8b2712007-07-24 06:06:59 +0000406 const struct ipt_ip *ip = ip_void;
Jan Engelhardt181dead2007-10-04 16:27:07 +0000407 __multiport_print_v1(match, numeric, ip->proto);
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000408}
409
Jan Engelhardt181dead2007-10-04 16:27:07 +0000410static void multiport_print6_v1(const void *ip_void,
411 const struct xt_entry_match *match, int numeric)
Yasuyuki KOZAKAIdf2cf4f2007-07-24 06:49:15 +0000412{
413 const struct ip6t_ip6 *ip = (const struct ip6t_ip6 *)ip_void;
Jan Engelhardt181dead2007-10-04 16:27:07 +0000414 __multiport_print_v1(match, numeric, ip->proto);
Yasuyuki KOZAKAIdf2cf4f2007-07-24 06:49:15 +0000415}
416
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000417/* Saves the union ipt_matchinfo in parsable form to stdout. */
Jan Engelhardt181dead2007-10-04 16:27:07 +0000418static void __multiport_save(const struct xt_entry_match *match,
419 u_int16_t proto)
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000420{
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000421 const struct xt_multiport *multiinfo
422 = (const struct xt_multiport *)match->data;
Marc Bouchere6869a82000-03-20 06:03:29 +0000423 unsigned int i;
424
425 switch (multiinfo->flags) {
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000426 case XT_MULTIPORT_SOURCE:
Marc Bouchere6869a82000-03-20 06:03:29 +0000427 printf("--sports ");
428 break;
429
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000430 case XT_MULTIPORT_DESTINATION:
Marc Bouchere6869a82000-03-20 06:03:29 +0000431 printf("--dports ");
432 break;
433
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000434 case XT_MULTIPORT_EITHER:
Marc Bouchere6869a82000-03-20 06:03:29 +0000435 printf("--ports ");
436 break;
437 }
438
439 for (i=0; i < multiinfo->count; i++) {
440 printf("%s", i ? "," : "");
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000441 print_port(multiinfo->ports[i], proto, 1);
Marc Bouchere6869a82000-03-20 06:03:29 +0000442 }
443 printf(" ");
444}
445
Jan Engelhardt181dead2007-10-04 16:27:07 +0000446static void multiport_save(const void *ip_void,
447 const struct xt_entry_match *match)
Pablo Neira5df95472005-01-03 09:37:07 +0000448{
Yasuyuki KOZAKAIac8b2712007-07-24 06:06:59 +0000449 const struct ipt_ip *ip = ip_void;
Jan Engelhardt181dead2007-10-04 16:27:07 +0000450 __multiport_save(match, ip->proto);
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000451}
452
Jan Engelhardt181dead2007-10-04 16:27:07 +0000453static void multiport_save6(const void *ip_void,
454 const struct xt_entry_match *match)
Yasuyuki KOZAKAIdf2cf4f2007-07-24 06:49:15 +0000455{
456 const struct ip6t_ip6 *ip = (const struct ip6t_ip6 *)ip_void;
Jan Engelhardt181dead2007-10-04 16:27:07 +0000457 __multiport_save(match, ip->proto);
Yasuyuki KOZAKAIdf2cf4f2007-07-24 06:49:15 +0000458}
459
Jan Engelhardt181dead2007-10-04 16:27:07 +0000460static void __multiport_save_v1(const struct xt_entry_match *match,
461 u_int16_t proto)
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000462{
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000463 const struct xt_multiport_v1 *multiinfo
464 = (const struct xt_multiport_v1 *)match->data;
Pablo Neira5df95472005-01-03 09:37:07 +0000465 unsigned int i;
466
Jan Engelhardtcea9f712008-12-09 15:06:20 +0100467 if (multiinfo->invert)
468 printf("! ");
469
Pablo Neira5df95472005-01-03 09:37:07 +0000470 switch (multiinfo->flags) {
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000471 case XT_MULTIPORT_SOURCE:
Pablo Neira5df95472005-01-03 09:37:07 +0000472 printf("--sports ");
473 break;
474
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000475 case XT_MULTIPORT_DESTINATION:
Pablo Neira5df95472005-01-03 09:37:07 +0000476 printf("--dports ");
477 break;
478
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000479 case XT_MULTIPORT_EITHER:
Pablo Neira5df95472005-01-03 09:37:07 +0000480 printf("--ports ");
481 break;
482 }
483
484 for (i=0; i < multiinfo->count; i++) {
485 printf("%s", i ? "," : "");
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000486 print_port(multiinfo->ports[i], proto, 1);
Pablo Neira5df95472005-01-03 09:37:07 +0000487 if (multiinfo->pflags[i]) {
488 printf(":");
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000489 print_port(multiinfo->ports[++i], proto, 1);
Pablo Neira5df95472005-01-03 09:37:07 +0000490 }
491 }
492 printf(" ");
493}
494
Jan Engelhardt181dead2007-10-04 16:27:07 +0000495static void multiport_save_v1(const void *ip_void,
496 const struct xt_entry_match *match)
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000497{
498 const struct ipt_ip *ip = ip_void;
Jan Engelhardt181dead2007-10-04 16:27:07 +0000499 __multiport_save_v1(match, ip->proto);
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000500}
501
Jan Engelhardt181dead2007-10-04 16:27:07 +0000502static void multiport_save6_v1(const void *ip_void,
503 const struct xt_entry_match *match)
Yasuyuki KOZAKAIdf2cf4f2007-07-24 06:49:15 +0000504{
505 const struct ip6t_ip6 *ip = (const struct ip6t_ip6 *)ip_void;
Jan Engelhardt181dead2007-10-04 16:27:07 +0000506 __multiport_save_v1(match, ip->proto);
Yasuyuki KOZAKAIdf2cf4f2007-07-24 06:49:15 +0000507}
508
Jan Engelhardt181dead2007-10-04 16:27:07 +0000509static struct xtables_match multiport_match = {
Jan Engelhardt03d99482008-11-18 12:27:54 +0100510 .family = NFPROTO_IPV4,
Pablo Neira8caee8b2004-12-28 13:11:59 +0000511 .name = "multiport",
Pablo Neira5df95472005-01-03 09:37:07 +0000512 .revision = 0,
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200513 .version = XTABLES_VERSION,
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000514 .size = XT_ALIGN(sizeof(struct xt_multiport)),
515 .userspacesize = XT_ALIGN(sizeof(struct xt_multiport)),
Jan Engelhardt181dead2007-10-04 16:27:07 +0000516 .help = multiport_help,
517 .parse = multiport_parse,
518 .final_check = multiport_check,
519 .print = multiport_print,
520 .save = multiport_save,
521 .extra_opts = multiport_opts,
Marc Bouchere6869a82000-03-20 06:03:29 +0000522};
523
Jan Engelhardt181dead2007-10-04 16:27:07 +0000524static struct xtables_match multiport_match6 = {
Jan Engelhardt03d99482008-11-18 12:27:54 +0100525 .family = NFPROTO_IPV6,
Yasuyuki KOZAKAIdf2cf4f2007-07-24 06:49:15 +0000526 .name = "multiport",
527 .revision = 0,
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200528 .version = XTABLES_VERSION,
Yasuyuki KOZAKAIdf2cf4f2007-07-24 06:49:15 +0000529 .size = XT_ALIGN(sizeof(struct xt_multiport)),
530 .userspacesize = XT_ALIGN(sizeof(struct xt_multiport)),
Jan Engelhardt181dead2007-10-04 16:27:07 +0000531 .help = multiport_help,
532 .parse = multiport_parse6,
533 .final_check = multiport_check,
534 .print = multiport_print6,
535 .save = multiport_save6,
536 .extra_opts = multiport_opts,
Yasuyuki KOZAKAIdf2cf4f2007-07-24 06:49:15 +0000537};
538
Jan Engelhardt181dead2007-10-04 16:27:07 +0000539static struct xtables_match multiport_match_v1 = {
Jan Engelhardt03d99482008-11-18 12:27:54 +0100540 .family = NFPROTO_IPV4,
Pablo Neira5df95472005-01-03 09:37:07 +0000541 .name = "multiport",
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200542 .version = XTABLES_VERSION,
Pablo Neira5df95472005-01-03 09:37:07 +0000543 .revision = 1,
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000544 .size = XT_ALIGN(sizeof(struct xt_multiport_v1)),
545 .userspacesize = XT_ALIGN(sizeof(struct xt_multiport_v1)),
Jan Engelhardt181dead2007-10-04 16:27:07 +0000546 .help = multiport_help_v1,
547 .parse = multiport_parse_v1,
548 .final_check = multiport_check,
549 .print = multiport_print_v1,
550 .save = multiport_save_v1,
551 .extra_opts = multiport_opts,
Pablo Neira5df95472005-01-03 09:37:07 +0000552};
553
Jan Engelhardt181dead2007-10-04 16:27:07 +0000554static struct xtables_match multiport_match6_v1 = {
Jan Engelhardt03d99482008-11-18 12:27:54 +0100555 .family = NFPROTO_IPV6,
Yasuyuki KOZAKAIdf2cf4f2007-07-24 06:49:15 +0000556 .name = "multiport",
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200557 .version = XTABLES_VERSION,
Yasuyuki KOZAKAIdf2cf4f2007-07-24 06:49:15 +0000558 .revision = 1,
559 .size = XT_ALIGN(sizeof(struct xt_multiport_v1)),
560 .userspacesize = XT_ALIGN(sizeof(struct xt_multiport_v1)),
Jan Engelhardt181dead2007-10-04 16:27:07 +0000561 .help = multiport_help_v1,
562 .parse = multiport_parse6_v1,
563 .final_check = multiport_check,
564 .print = multiport_print6_v1,
565 .save = multiport_save6_v1,
566 .extra_opts = multiport_opts,
Yasuyuki KOZAKAIdf2cf4f2007-07-24 06:49:15 +0000567};
568
Marc Bouchere6869a82000-03-20 06:03:29 +0000569void
570_init(void)
571{
Jan Engelhardt181dead2007-10-04 16:27:07 +0000572 xtables_register_match(&multiport_match);
573 xtables_register_match(&multiport_match6);
574 xtables_register_match(&multiport_match_v1);
575 xtables_register_match(&multiport_match6_v1);
Marc Bouchere6869a82000-03-20 06:03:29 +0000576}