blob: 9ed5931d3c66e2a002745183e6a6e8b23ff38f89 [file] [log] [blame]
Marc Bouchere6869a82000-03-20 06:03:29 +00001/* Shared library add-on to iptables to add multiple TCP port support. */
Jan Engelhardt32b8e612010-07-23 21:16:14 +02002#include <stdbool.h>
Marc Bouchere6869a82000-03-20 06:03:29 +00003#include <stdio.h>
4#include <netdb.h>
5#include <string.h>
6#include <stdlib.h>
7#include <getopt.h>
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +00008
9#include <xtables.h>
10#include <libiptc/libiptc.h>
Yasuyuki KOZAKAIdf2cf4f2007-07-24 06:49:15 +000011#include <libiptc/libip6tc.h>
Jan Engelhardt4e418542009-02-21 03:46:37 +010012#include <limits.h> /* INT_MAX in ip_tables.h/ip6_tables.h */
Jan Engelhardtafe6b352009-02-21 03:44:36 +010013#include <linux/netfilter_ipv4/ip_tables.h>
Jan Engelhardt2bc9d342009-02-21 03:40:27 +010014#include <linux/netfilter_ipv6/ip6_tables.h>
Jan Engelhardta2a7f2b2008-09-01 14:20:13 +020015#include <linux/netfilter/xt_multiport.h>
Marc Bouchere6869a82000-03-20 06:03:29 +000016
17/* Function which prints out usage message. */
Jan Engelhardt181dead2007-10-04 16:27:07 +000018static void multiport_help(void)
Marc Bouchere6869a82000-03-20 06:03:29 +000019{
20 printf(
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +020021"multiport match options:\n"
Marc Bouchere6869a82000-03-20 06:03:29 +000022" --source-ports port[,port,port...]\n"
23" --sports ...\n"
24" match source port(s)\n"
25" --destination-ports port[,port,port...]\n"
26" --dports ...\n"
27" match destination port(s)\n"
28" --ports port[,port,port]\n"
Pablo Neira5df95472005-01-03 09:37:07 +000029" match both source and destination port(s)\n"
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +020030" NOTE: this kernel does not support port ranges in multiport.\n");
Pablo Neira5df95472005-01-03 09:37:07 +000031}
32
Jan Engelhardt181dead2007-10-04 16:27:07 +000033static void multiport_help_v1(void)
Pablo Neira5df95472005-01-03 09:37:07 +000034{
35 printf(
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +020036"multiport match options:\n"
Jan Engelhardt96727922008-08-13 14:42:41 +020037"[!] --source-ports port[,port:port,port...]\n"
Pablo Neira5df95472005-01-03 09:37:07 +000038" --sports ...\n"
39" match source port(s)\n"
Jan Engelhardt96727922008-08-13 14:42:41 +020040"[!] --destination-ports port[,port:port,port...]\n"
Pablo Neira5df95472005-01-03 09:37:07 +000041" --dports ...\n"
42" match destination port(s)\n"
Jan Engelhardt96727922008-08-13 14:42:41 +020043"[!] --ports port[,port:port,port]\n"
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +020044" match both source and destination port(s)\n");
Marc Bouchere6869a82000-03-20 06:03:29 +000045}
46
Jan Engelhardt181dead2007-10-04 16:27:07 +000047static const struct option multiport_opts[] = {
Jan Engelhardt32b8e612010-07-23 21:16:14 +020048 {.name = "source-ports", .has_arg = true, .val = '1'},
49 {.name = "sports", .has_arg = true, .val = '1'}, /* synonym */
50 {.name = "destination-ports", .has_arg = true, .val = '2'},
51 {.name = "dports", .has_arg = true, .val = '2'}, /* synonym */
52 {.name = "ports", .has_arg = true, .val = '3'},
53 XT_GETOPT_TABLEEND,
Marc Bouchere6869a82000-03-20 06:03:29 +000054};
55
Patrick McHardyJesper Brouerc1eae412006-07-25 01:50:48 +000056static char *
Jan Engelhardt7ac40522011-01-07 12:34:04 +010057proto_to_name(uint8_t proto)
Patrick McHardyJesper Brouerc1eae412006-07-25 01:50:48 +000058{
59 switch (proto) {
60 case IPPROTO_TCP:
61 return "tcp";
62 case IPPROTO_UDP:
63 return "udp";
Patrick McHardy95616062007-01-11 09:08:22 +000064 case IPPROTO_UDPLITE:
65 return "udplite";
Patrick McHardyJesper Brouerc1eae412006-07-25 01:50:48 +000066 case IPPROTO_SCTP:
67 return "sctp";
68 case IPPROTO_DCCP:
69 return "dccp";
70 default:
71 return NULL;
72 }
73}
74
Marc Bouchere6869a82000-03-20 06:03:29 +000075static unsigned int
Jan Engelhardt7ac40522011-01-07 12:34:04 +010076parse_multi_ports(const char *portstring, uint16_t *ports, const char *proto)
Marc Bouchere6869a82000-03-20 06:03:29 +000077{
78 char *buffer, *cp, *next;
79 unsigned int i;
80
81 buffer = strdup(portstring);
Jan Engelhardt1829ed42009-02-21 03:29:44 +010082 if (!buffer) xtables_error(OTHER_PROBLEM, "strdup failed");
Marc Bouchere6869a82000-03-20 06:03:29 +000083
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +000084 for (cp=buffer, i=0; cp && i<XT_MULTI_PORTS; cp=next,i++)
Marc Bouchere6869a82000-03-20 06:03:29 +000085 {
86 next=strchr(cp, ',');
87 if (next) *next++='\0';
Jan Engelhardtaae6be92009-01-30 04:24:47 +010088 ports[i] = xtables_parse_port(cp, proto);
Marc Bouchere6869a82000-03-20 06:03:29 +000089 }
Jan Engelhardt1829ed42009-02-21 03:29:44 +010090 if (cp) xtables_error(PARAMETER_PROBLEM, "too many ports specified");
Marc Bouchere6869a82000-03-20 06:03:29 +000091 free(buffer);
92 return i;
93}
94
Pablo Neira5df95472005-01-03 09:37:07 +000095static void
96parse_multi_ports_v1(const char *portstring,
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +000097 struct xt_multiport_v1 *multiinfo,
Pablo Neira5df95472005-01-03 09:37:07 +000098 const char *proto)
99{
100 char *buffer, *cp, *next, *range;
101 unsigned int i;
Jan Engelhardt7ac40522011-01-07 12:34:04 +0100102 uint16_t m;
Pablo Neira5df95472005-01-03 09:37:07 +0000103
104 buffer = strdup(portstring);
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100105 if (!buffer) xtables_error(OTHER_PROBLEM, "strdup failed");
Pablo Neira5df95472005-01-03 09:37:07 +0000106
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000107 for (i=0; i<XT_MULTI_PORTS; i++)
Pablo Neira5df95472005-01-03 09:37:07 +0000108 multiinfo->pflags[i] = 0;
109
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000110 for (cp=buffer, i=0; cp && i<XT_MULTI_PORTS; cp=next, i++) {
Pablo Neira5df95472005-01-03 09:37:07 +0000111 next=strchr(cp, ',');
112 if (next) *next++='\0';
113 range = strchr(cp, ':');
114 if (range) {
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000115 if (i == XT_MULTI_PORTS-1)
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100116 xtables_error(PARAMETER_PROBLEM,
Pablo Neira5df95472005-01-03 09:37:07 +0000117 "too many ports specified");
118 *range++ = '\0';
119 }
Jan Engelhardtaae6be92009-01-30 04:24:47 +0100120 multiinfo->ports[i] = xtables_parse_port(cp, proto);
Pablo Neira5df95472005-01-03 09:37:07 +0000121 if (range) {
122 multiinfo->pflags[i] = 1;
Jan Engelhardtaae6be92009-01-30 04:24:47 +0100123 multiinfo->ports[++i] = xtables_parse_port(range, proto);
Pablo Neira5df95472005-01-03 09:37:07 +0000124 if (multiinfo->ports[i-1] >= multiinfo->ports[i])
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100125 xtables_error(PARAMETER_PROBLEM,
Pablo Neira5df95472005-01-03 09:37:07 +0000126 "invalid portrange specified");
127 m <<= 1;
128 }
129 }
130 multiinfo->count = i;
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100131 if (cp) xtables_error(PARAMETER_PROBLEM, "too many ports specified");
Pablo Neira5df95472005-01-03 09:37:07 +0000132 free(buffer);
133}
134
Marc Bouchere6869a82000-03-20 06:03:29 +0000135static const char *
Jan Engelhardt7ac40522011-01-07 12:34:04 +0100136check_proto(uint16_t pnum, uint8_t invflags)
Marc Bouchere6869a82000-03-20 06:03:29 +0000137{
Patrick McHardy2452baf2006-04-28 08:10:08 +0000138 char *proto;
139
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000140 if (invflags & XT_INV_PROTO)
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100141 xtables_error(PARAMETER_PROBLEM,
Patrick McHardy95616062007-01-11 09:08:22 +0000142 "multiport only works with TCP, UDP, UDPLITE, SCTP and DCCP");
Rusty Russell225f4622005-01-03 09:51:58 +0000143
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000144 if ((proto = proto_to_name(pnum)) != NULL)
Patrick McHardy2452baf2006-04-28 08:10:08 +0000145 return proto;
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000146 else if (!pnum)
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100147 xtables_error(PARAMETER_PROBLEM,
Patrick McHardy95616062007-01-11 09:08:22 +0000148 "multiport needs `-p tcp', `-p udp', `-p udplite', "
149 "`-p sctp' or `-p dccp'");
Marc Bouchere6869a82000-03-20 06:03:29 +0000150 else
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100151 xtables_error(PARAMETER_PROBLEM,
Patrick McHardy95616062007-01-11 09:08:22 +0000152 "multiport only works with TCP, UDP, UDPLITE, SCTP and DCCP");
Marc Bouchere6869a82000-03-20 06:03:29 +0000153}
154
155/* Function which parses command options; returns true if it
156 ate an option */
157static int
Jan Engelhardt181dead2007-10-04 16:27:07 +0000158__multiport_parse(int c, char **argv, int invert, unsigned int *flags,
Jan Engelhardt7ac40522011-01-07 12:34:04 +0100159 struct xt_entry_match **match, uint16_t pnum,
160 uint8_t invflags)
Marc Bouchere6869a82000-03-20 06:03:29 +0000161{
162 const char *proto;
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000163 struct xt_multiport *multiinfo
164 = (struct xt_multiport *)(*match)->data;
Marc Bouchere6869a82000-03-20 06:03:29 +0000165
166 switch (c) {
167 case '1':
Jan Engelhardtbbe83862009-10-24 00:45:33 +0200168 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000169 proto = check_proto(pnum, invflags);
Jan Engelhardtbbe83862009-10-24 00:45:33 +0200170 multiinfo->count = parse_multi_ports(optarg,
Marc Bouchere6869a82000-03-20 06:03:29 +0000171 multiinfo->ports, proto);
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000172 multiinfo->flags = XT_MULTIPORT_SOURCE;
Marc Bouchere6869a82000-03-20 06:03:29 +0000173 break;
174
175 case '2':
Jan Engelhardtbbe83862009-10-24 00:45:33 +0200176 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000177 proto = check_proto(pnum, invflags);
Jan Engelhardtbbe83862009-10-24 00:45:33 +0200178 multiinfo->count = parse_multi_ports(optarg,
Marc Bouchere6869a82000-03-20 06:03:29 +0000179 multiinfo->ports, proto);
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000180 multiinfo->flags = XT_MULTIPORT_DESTINATION;
Marc Bouchere6869a82000-03-20 06:03:29 +0000181 break;
182
183 case '3':
Jan Engelhardtbbe83862009-10-24 00:45:33 +0200184 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000185 proto = check_proto(pnum, invflags);
Jan Engelhardtbbe83862009-10-24 00:45:33 +0200186 multiinfo->count = parse_multi_ports(optarg,
Marc Bouchere6869a82000-03-20 06:03:29 +0000187 multiinfo->ports, proto);
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000188 multiinfo->flags = XT_MULTIPORT_EITHER;
Marc Bouchere6869a82000-03-20 06:03:29 +0000189 break;
190
191 default:
192 return 0;
193 }
194
Patrick McHardyd0a2e8a2004-09-18 17:43:36 +0000195 if (invert)
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100196 xtables_error(PARAMETER_PROBLEM,
Patrick McHardyd0a2e8a2004-09-18 17:43:36 +0000197 "multiport does not support invert");
198
Marc Bouchere6869a82000-03-20 06:03:29 +0000199 if (*flags)
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100200 xtables_error(PARAMETER_PROBLEM,
Marc Bouchere6869a82000-03-20 06:03:29 +0000201 "multiport can only have one option");
202 *flags = 1;
203 return 1;
204}
205
Pablo Neira5df95472005-01-03 09:37:07 +0000206static int
Jan Engelhardt181dead2007-10-04 16:27:07 +0000207multiport_parse(int c, char **argv, int invert, unsigned int *flags,
208 const void *e, struct xt_entry_match **match)
Pablo Neira5df95472005-01-03 09:37:07 +0000209{
Yasuyuki KOZAKAIac8b2712007-07-24 06:06:59 +0000210 const struct ipt_entry *entry = e;
Jan Engelhardt181dead2007-10-04 16:27:07 +0000211 return __multiport_parse(c, argv, invert, flags, match,
212 entry->ip.proto, entry->ip.invflags);
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000213}
214
215static int
Jan Engelhardt181dead2007-10-04 16:27:07 +0000216multiport_parse6(int c, char **argv, int invert, unsigned int *flags,
217 const void *e, struct xt_entry_match **match)
Yasuyuki KOZAKAIdf2cf4f2007-07-24 06:49:15 +0000218{
Jan Engelhardtecd48dd2009-06-08 15:46:52 +0200219 const struct ip6t_entry *entry = e;
Jan Engelhardt181dead2007-10-04 16:27:07 +0000220 return __multiport_parse(c, argv, invert, flags, match,
221 entry->ipv6.proto, entry->ipv6.invflags);
Yasuyuki KOZAKAIdf2cf4f2007-07-24 06:49:15 +0000222}
223
224static int
Jan Engelhardt181dead2007-10-04 16:27:07 +0000225__multiport_parse_v1(int c, char **argv, int invert, unsigned int *flags,
Jan Engelhardt7ac40522011-01-07 12:34:04 +0100226 struct xt_entry_match **match, uint16_t pnum,
227 uint8_t invflags)
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000228{
Pablo Neira5df95472005-01-03 09:37:07 +0000229 const char *proto;
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000230 struct xt_multiport_v1 *multiinfo
231 = (struct xt_multiport_v1 *)(*match)->data;
Pablo Neira5df95472005-01-03 09:37:07 +0000232
233 switch (c) {
234 case '1':
Jan Engelhardtbbe83862009-10-24 00:45:33 +0200235 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000236 proto = check_proto(pnum, invflags);
Jan Engelhardtbbe83862009-10-24 00:45:33 +0200237 parse_multi_ports_v1(optarg, multiinfo, proto);
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000238 multiinfo->flags = XT_MULTIPORT_SOURCE;
Pablo Neira5df95472005-01-03 09:37:07 +0000239 break;
240
241 case '2':
Jan Engelhardtbbe83862009-10-24 00:45:33 +0200242 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000243 proto = check_proto(pnum, invflags);
Jan Engelhardtbbe83862009-10-24 00:45:33 +0200244 parse_multi_ports_v1(optarg, multiinfo, proto);
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000245 multiinfo->flags = XT_MULTIPORT_DESTINATION;
Pablo Neira5df95472005-01-03 09:37:07 +0000246 break;
247
248 case '3':
Jan Engelhardtbbe83862009-10-24 00:45:33 +0200249 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000250 proto = check_proto(pnum, invflags);
Jan Engelhardtbbe83862009-10-24 00:45:33 +0200251 parse_multi_ports_v1(optarg, multiinfo, proto);
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000252 multiinfo->flags = XT_MULTIPORT_EITHER;
Pablo Neira5df95472005-01-03 09:37:07 +0000253 break;
254
255 default:
256 return 0;
257 }
258
259 if (invert)
Phil Oesterb2eedcd2005-02-02 19:20:15 +0000260 multiinfo->invert = 1;
Pablo Neira5df95472005-01-03 09:37:07 +0000261
262 if (*flags)
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100263 xtables_error(PARAMETER_PROBLEM,
Pablo Neira5df95472005-01-03 09:37:07 +0000264 "multiport can only have one option");
265 *flags = 1;
266 return 1;
267}
268
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000269static int
Jan Engelhardt181dead2007-10-04 16:27:07 +0000270multiport_parse_v1(int c, char **argv, int invert, unsigned int *flags,
271 const void *e, struct xt_entry_match **match)
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000272{
273 const struct ipt_entry *entry = e;
Jan Engelhardt181dead2007-10-04 16:27:07 +0000274 return __multiport_parse_v1(c, argv, invert, flags, match,
275 entry->ip.proto, entry->ip.invflags);
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000276}
277
Yasuyuki KOZAKAIdf2cf4f2007-07-24 06:49:15 +0000278static int
Jan Engelhardt181dead2007-10-04 16:27:07 +0000279multiport_parse6_v1(int c, char **argv, int invert, unsigned int *flags,
280 const void *e, struct xt_entry_match **match)
Yasuyuki KOZAKAIdf2cf4f2007-07-24 06:49:15 +0000281{
Jan Engelhardtecd48dd2009-06-08 15:46:52 +0200282 const struct ip6t_entry *entry = e;
Jan Engelhardt181dead2007-10-04 16:27:07 +0000283 return __multiport_parse_v1(c, argv, invert, flags, match,
284 entry->ipv6.proto, entry->ipv6.invflags);
Yasuyuki KOZAKAIdf2cf4f2007-07-24 06:49:15 +0000285}
286
Marc Bouchere6869a82000-03-20 06:03:29 +0000287/* Final check; must specify something. */
Jan Engelhardt181dead2007-10-04 16:27:07 +0000288static void multiport_check(unsigned int flags)
Marc Bouchere6869a82000-03-20 06:03:29 +0000289{
290 if (!flags)
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100291 xtables_error(PARAMETER_PROBLEM, "multiport expection an option");
Marc Bouchere6869a82000-03-20 06:03:29 +0000292}
293
294static char *
Jan Engelhardt7ac40522011-01-07 12:34:04 +0100295port_to_service(int port, uint8_t proto)
Marc Bouchere6869a82000-03-20 06:03:29 +0000296{
297 struct servent *service;
298
Patrick McHardyJesper Brouerc1eae412006-07-25 01:50:48 +0000299 if ((service = getservbyport(htons(port), proto_to_name(proto))))
Marc Bouchere6869a82000-03-20 06:03:29 +0000300 return service->s_name;
301
302 return NULL;
303}
304
305static void
Jan Engelhardt7ac40522011-01-07 12:34:04 +0100306print_port(uint16_t port, uint8_t protocol, int numeric)
Marc Bouchere6869a82000-03-20 06:03:29 +0000307{
308 char *service;
309
310 if (numeric || (service = port_to_service(port, protocol)) == NULL)
311 printf("%u", port);
312 else
313 printf("%s", service);
314}
315
316/* Prints out the matchinfo. */
317static void
Jan Engelhardt181dead2007-10-04 16:27:07 +0000318__multiport_print(const struct xt_entry_match *match, int numeric,
Jan Engelhardt7ac40522011-01-07 12:34:04 +0100319 uint16_t proto)
Marc Bouchere6869a82000-03-20 06:03:29 +0000320{
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000321 const struct xt_multiport *multiinfo
322 = (const struct xt_multiport *)match->data;
Marc Bouchere6869a82000-03-20 06:03:29 +0000323 unsigned int i;
324
325 printf("multiport ");
326
327 switch (multiinfo->flags) {
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000328 case XT_MULTIPORT_SOURCE:
Marc Bouchere6869a82000-03-20 06:03:29 +0000329 printf("sports ");
330 break;
331
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000332 case XT_MULTIPORT_DESTINATION:
Marc Bouchere6869a82000-03-20 06:03:29 +0000333 printf("dports ");
334 break;
335
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000336 case XT_MULTIPORT_EITHER:
Marc Bouchere6869a82000-03-20 06:03:29 +0000337 printf("ports ");
338 break;
339
340 default:
341 printf("ERROR ");
342 break;
343 }
344
345 for (i=0; i < multiinfo->count; i++) {
346 printf("%s", i ? "," : "");
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000347 print_port(multiinfo->ports[i], proto, numeric);
Marc Bouchere6869a82000-03-20 06:03:29 +0000348 }
349 printf(" ");
350}
351
Jan Engelhardt181dead2007-10-04 16:27:07 +0000352static void multiport_print(const void *ip_void,
353 const struct xt_entry_match *match, int numeric)
Pablo Neira5df95472005-01-03 09:37:07 +0000354{
Yasuyuki KOZAKAIac8b2712007-07-24 06:06:59 +0000355 const struct ipt_ip *ip = ip_void;
Jan Engelhardt181dead2007-10-04 16:27:07 +0000356 __multiport_print(match, numeric, ip->proto);
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000357}
358
Jan Engelhardt181dead2007-10-04 16:27:07 +0000359static void multiport_print6(const void *ip_void,
360 const struct xt_entry_match *match, int numeric)
Yasuyuki KOZAKAIdf2cf4f2007-07-24 06:49:15 +0000361{
Jan Engelhardtecd48dd2009-06-08 15:46:52 +0200362 const struct ip6t_ip6 *ip = ip_void;
Jan Engelhardt181dead2007-10-04 16:27:07 +0000363 __multiport_print(match, numeric, ip->proto);
Yasuyuki KOZAKAIdf2cf4f2007-07-24 06:49:15 +0000364}
365
Jan Engelhardt181dead2007-10-04 16:27:07 +0000366static void __multiport_print_v1(const struct xt_entry_match *match,
Jan Engelhardt7ac40522011-01-07 12:34:04 +0100367 int numeric, uint16_t proto)
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000368{
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000369 const struct xt_multiport_v1 *multiinfo
370 = (const struct xt_multiport_v1 *)match->data;
Pablo Neira5df95472005-01-03 09:37:07 +0000371 unsigned int i;
372
373 printf("multiport ");
374
375 switch (multiinfo->flags) {
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000376 case XT_MULTIPORT_SOURCE:
Pablo Neira5df95472005-01-03 09:37:07 +0000377 printf("sports ");
378 break;
379
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000380 case XT_MULTIPORT_DESTINATION:
Pablo Neira5df95472005-01-03 09:37:07 +0000381 printf("dports ");
382 break;
383
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000384 case XT_MULTIPORT_EITHER:
Pablo Neira5df95472005-01-03 09:37:07 +0000385 printf("ports ");
386 break;
387
388 default:
389 printf("ERROR ");
390 break;
391 }
392
Phil Oesterb2eedcd2005-02-02 19:20:15 +0000393 if (multiinfo->invert)
394 printf("! ");
395
Pablo Neira5df95472005-01-03 09:37:07 +0000396 for (i=0; i < multiinfo->count; i++) {
397 printf("%s", i ? "," : "");
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000398 print_port(multiinfo->ports[i], proto, numeric);
Pablo Neira5df95472005-01-03 09:37:07 +0000399 if (multiinfo->pflags[i]) {
400 printf(":");
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000401 print_port(multiinfo->ports[++i], proto, numeric);
Pablo Neira5df95472005-01-03 09:37:07 +0000402 }
403 }
404 printf(" ");
405}
406
Jan Engelhardt181dead2007-10-04 16:27:07 +0000407static void multiport_print_v1(const void *ip_void,
408 const struct xt_entry_match *match, int numeric)
Marc Bouchere6869a82000-03-20 06:03:29 +0000409{
Yasuyuki KOZAKAIac8b2712007-07-24 06:06:59 +0000410 const struct ipt_ip *ip = ip_void;
Jan Engelhardt181dead2007-10-04 16:27:07 +0000411 __multiport_print_v1(match, numeric, ip->proto);
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000412}
413
Jan Engelhardt181dead2007-10-04 16:27:07 +0000414static void multiport_print6_v1(const void *ip_void,
415 const struct xt_entry_match *match, int numeric)
Yasuyuki KOZAKAIdf2cf4f2007-07-24 06:49:15 +0000416{
Jan Engelhardtecd48dd2009-06-08 15:46:52 +0200417 const struct ip6t_ip6 *ip = ip_void;
Jan Engelhardt181dead2007-10-04 16:27:07 +0000418 __multiport_print_v1(match, numeric, ip->proto);
Yasuyuki KOZAKAIdf2cf4f2007-07-24 06:49:15 +0000419}
420
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000421/* Saves the union ipt_matchinfo in parsable form to stdout. */
Jan Engelhardt181dead2007-10-04 16:27:07 +0000422static void __multiport_save(const struct xt_entry_match *match,
Jan Engelhardt7ac40522011-01-07 12:34:04 +0100423 uint16_t proto)
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000424{
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000425 const struct xt_multiport *multiinfo
426 = (const struct xt_multiport *)match->data;
Marc Bouchere6869a82000-03-20 06:03:29 +0000427 unsigned int i;
428
429 switch (multiinfo->flags) {
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000430 case XT_MULTIPORT_SOURCE:
Marc Bouchere6869a82000-03-20 06:03:29 +0000431 printf("--sports ");
432 break;
433
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000434 case XT_MULTIPORT_DESTINATION:
Marc Bouchere6869a82000-03-20 06:03:29 +0000435 printf("--dports ");
436 break;
437
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000438 case XT_MULTIPORT_EITHER:
Marc Bouchere6869a82000-03-20 06:03:29 +0000439 printf("--ports ");
440 break;
441 }
442
443 for (i=0; i < multiinfo->count; i++) {
444 printf("%s", i ? "," : "");
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000445 print_port(multiinfo->ports[i], proto, 1);
Marc Bouchere6869a82000-03-20 06:03:29 +0000446 }
447 printf(" ");
448}
449
Jan Engelhardt181dead2007-10-04 16:27:07 +0000450static void multiport_save(const void *ip_void,
451 const struct xt_entry_match *match)
Pablo Neira5df95472005-01-03 09:37:07 +0000452{
Yasuyuki KOZAKAIac8b2712007-07-24 06:06:59 +0000453 const struct ipt_ip *ip = ip_void;
Jan Engelhardt181dead2007-10-04 16:27:07 +0000454 __multiport_save(match, ip->proto);
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000455}
456
Jan Engelhardt181dead2007-10-04 16:27:07 +0000457static void multiport_save6(const void *ip_void,
458 const struct xt_entry_match *match)
Yasuyuki KOZAKAIdf2cf4f2007-07-24 06:49:15 +0000459{
Jan Engelhardtecd48dd2009-06-08 15:46:52 +0200460 const struct ip6t_ip6 *ip = ip_void;
Jan Engelhardt181dead2007-10-04 16:27:07 +0000461 __multiport_save(match, ip->proto);
Yasuyuki KOZAKAIdf2cf4f2007-07-24 06:49:15 +0000462}
463
Jan Engelhardt181dead2007-10-04 16:27:07 +0000464static void __multiport_save_v1(const struct xt_entry_match *match,
Jan Engelhardt7ac40522011-01-07 12:34:04 +0100465 uint16_t proto)
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000466{
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000467 const struct xt_multiport_v1 *multiinfo
468 = (const struct xt_multiport_v1 *)match->data;
Pablo Neira5df95472005-01-03 09:37:07 +0000469 unsigned int i;
470
Jan Engelhardtcea9f712008-12-09 15:06:20 +0100471 if (multiinfo->invert)
472 printf("! ");
473
Pablo Neira5df95472005-01-03 09:37:07 +0000474 switch (multiinfo->flags) {
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000475 case XT_MULTIPORT_SOURCE:
Pablo Neira5df95472005-01-03 09:37:07 +0000476 printf("--sports ");
477 break;
478
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000479 case XT_MULTIPORT_DESTINATION:
Pablo Neira5df95472005-01-03 09:37:07 +0000480 printf("--dports ");
481 break;
482
Yasuyuki KOZAKAIeb6e65e2007-07-24 06:45:03 +0000483 case XT_MULTIPORT_EITHER:
Pablo Neira5df95472005-01-03 09:37:07 +0000484 printf("--ports ");
485 break;
486 }
487
488 for (i=0; i < multiinfo->count; i++) {
489 printf("%s", i ? "," : "");
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000490 print_port(multiinfo->ports[i], proto, 1);
Pablo Neira5df95472005-01-03 09:37:07 +0000491 if (multiinfo->pflags[i]) {
492 printf(":");
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000493 print_port(multiinfo->ports[++i], proto, 1);
Pablo Neira5df95472005-01-03 09:37:07 +0000494 }
495 }
496 printf(" ");
497}
498
Jan Engelhardt181dead2007-10-04 16:27:07 +0000499static void multiport_save_v1(const void *ip_void,
500 const struct xt_entry_match *match)
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000501{
502 const struct ipt_ip *ip = ip_void;
Jan Engelhardt181dead2007-10-04 16:27:07 +0000503 __multiport_save_v1(match, ip->proto);
Yasuyuki KOZAKAIf451b572007-07-24 06:46:08 +0000504}
505
Jan Engelhardt181dead2007-10-04 16:27:07 +0000506static void multiport_save6_v1(const void *ip_void,
507 const struct xt_entry_match *match)
Yasuyuki KOZAKAIdf2cf4f2007-07-24 06:49:15 +0000508{
Jan Engelhardtecd48dd2009-06-08 15:46:52 +0200509 const struct ip6t_ip6 *ip = ip_void;
Jan Engelhardt181dead2007-10-04 16:27:07 +0000510 __multiport_save_v1(match, ip->proto);
Yasuyuki KOZAKAIdf2cf4f2007-07-24 06:49:15 +0000511}
512
Jan Engelhardtf2a77522009-06-25 20:12:12 +0200513static struct xtables_match multiport_mt_reg[] = {
514 {
515 .family = NFPROTO_IPV4,
516 .name = "multiport",
517 .revision = 0,
518 .version = XTABLES_VERSION,
519 .size = XT_ALIGN(sizeof(struct xt_multiport)),
520 .userspacesize = XT_ALIGN(sizeof(struct xt_multiport)),
521 .help = multiport_help,
522 .parse = multiport_parse,
523 .final_check = multiport_check,
524 .print = multiport_print,
525 .save = multiport_save,
526 .extra_opts = multiport_opts,
527 },
528 {
529 .family = NFPROTO_IPV6,
530 .name = "multiport",
531 .revision = 0,
532 .version = XTABLES_VERSION,
533 .size = XT_ALIGN(sizeof(struct xt_multiport)),
534 .userspacesize = XT_ALIGN(sizeof(struct xt_multiport)),
535 .help = multiport_help,
536 .parse = multiport_parse6,
537 .final_check = multiport_check,
538 .print = multiport_print6,
539 .save = multiport_save6,
540 .extra_opts = multiport_opts,
541 },
542 {
543 .family = NFPROTO_IPV4,
544 .name = "multiport",
545 .version = XTABLES_VERSION,
546 .revision = 1,
547 .size = XT_ALIGN(sizeof(struct xt_multiport_v1)),
548 .userspacesize = XT_ALIGN(sizeof(struct xt_multiport_v1)),
549 .help = multiport_help_v1,
550 .parse = multiport_parse_v1,
551 .final_check = multiport_check,
552 .print = multiport_print_v1,
553 .save = multiport_save_v1,
554 .extra_opts = multiport_opts,
555 },
556 {
557 .family = NFPROTO_IPV6,
558 .name = "multiport",
559 .version = XTABLES_VERSION,
560 .revision = 1,
561 .size = XT_ALIGN(sizeof(struct xt_multiport_v1)),
562 .userspacesize = XT_ALIGN(sizeof(struct xt_multiport_v1)),
563 .help = multiport_help_v1,
564 .parse = multiport_parse6_v1,
565 .final_check = multiport_check,
566 .print = multiport_print6_v1,
567 .save = multiport_save6_v1,
568 .extra_opts = multiport_opts,
569 },
Yasuyuki KOZAKAIdf2cf4f2007-07-24 06:49:15 +0000570};
571
Marc Bouchere6869a82000-03-20 06:03:29 +0000572void
573_init(void)
574{
Jan Engelhardtf2a77522009-06-25 20:12:12 +0200575 xtables_register_matches(multiport_mt_reg, ARRAY_SIZE(multiport_mt_reg));
Marc Bouchere6869a82000-03-20 06:03:29 +0000576}