1 /* Shared library add-on to iptables to add multiple TCP port support. */
8 /* To ensure that iptables compiles with an old kernel */
9 #include "../include/linux/netfilter_ipv6/ip6t_multiport.h"
11 /* Function which prints out usage message. */
17 "multiport v%s options:\n"
18 " --source-ports port[,port,port...]\n"
20 " match source port(s)\n"
21 " --destination-ports port[,port,port...]\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",
35 "multiport v%s options:\n"
36 " --source-ports [!] port[,port:port,port...]\n"
38 " match source port(s)\n"
39 " --destination-ports [!] port[,port:port,port...]\n"
41 " match destination port(s)\n"
42 " --ports [!] port[,port:port,port]\n"
43 " match both source and destination port(s)\n",
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' },
57 proto_to_name(u_int8_t proto
)
75 parse_multi_ports(const char *portstring
, u_int16_t
*ports
, const char *proto
)
77 char *buffer
, *cp
, *next
;
80 buffer
= strdup(portstring
);
81 if (!buffer
) exit_error(OTHER_PROBLEM
, "strdup failed");
83 for (cp
=buffer
, i
=0; cp
&& i
<IP6T_MULTI_PORTS
; cp
=next
,i
++)
86 if (next
) *next
++='\0';
87 ports
[i
] = parse_port(cp
, proto
);
89 if (cp
) exit_error(PARAMETER_PROBLEM
, "too many ports specified");
96 parse_multi_ports_v1(const char *portstring
,
97 struct ip6t_multiport_v1
*multiinfo
,
100 char *buffer
, *cp
, *next
, *range
;
104 buffer
= strdup(portstring
);
105 if (!buffer
) exit_error(OTHER_PROBLEM
, "strdup failed");
107 for (i
=0; i
<IP6T_MULTI_PORTS
; i
++)
108 multiinfo
->pflags
[i
] = 0;
110 for (cp
=buffer
, i
=0; cp
&& i
<IP6T_MULTI_PORTS
; cp
=next
, i
++) {
111 next
=strchr(cp
, ',');
112 if (next
) *next
++='\0';
113 range
= strchr(cp
, ':');
115 if (i
== IP6T_MULTI_PORTS
-1)
116 exit_error(PARAMETER_PROBLEM
,
117 "too many ports specified");
120 multiinfo
->ports
[i
] = parse_port(cp
, proto
);
122 multiinfo
->pflags
[i
] = 1;
123 multiinfo
->ports
[++i
] = parse_port(range
, proto
);
124 if (multiinfo
->ports
[i
-1] >= multiinfo
->ports
[i
])
125 exit_error(PARAMETER_PROBLEM
,
126 "invalid portrange specified");
130 multiinfo
->count
= i
;
131 if (cp
) exit_error(PARAMETER_PROBLEM
, "too many ports specified");
135 /* Initialize the match. */
137 init(struct ip6t_entry_match
*m
, unsigned int *nfcache
)
142 check_proto(const struct ip6t_entry
*entry
)
146 if ((proto
= proto_to_name(entry
->ipv6
.proto
)) != NULL
)
148 else if (!entry
->ipv6
.proto
)
149 exit_error(PARAMETER_PROBLEM
,
150 "multiport needs `-p tcp', `-p udp', `-p sctp' or `-p dccp'");
152 exit_error(PARAMETER_PROBLEM
,
153 "multiport only works with TCP, UDP, SCTP and DCCP");
156 /* Function which parses command options; returns true if it
160 parse(int c
, char **argv
, int invert
, unsigned int *flags
,
161 const struct ip6t_entry
*entry
,
162 unsigned int *nfcache
,
163 struct ip6t_entry_match
**match
)
166 struct ip6t_multiport
*multiinfo
167 = (struct ip6t_multiport
*)(*match
)->data
;
171 check_inverse(argv
[optind
-1], &invert
, &optind
, 0);
172 proto
= check_proto(entry
);
173 multiinfo
->count
= parse_multi_ports(argv
[optind
-1],
174 multiinfo
->ports
, proto
);
175 multiinfo
->flags
= IP6T_MULTIPORT_SOURCE
;
179 check_inverse(argv
[optind
-1], &invert
, &optind
, 0);
180 proto
= check_proto(entry
);
181 multiinfo
->count
= parse_multi_ports(argv
[optind
-1],
182 multiinfo
->ports
, proto
);
183 multiinfo
->flags
= IP6T_MULTIPORT_DESTINATION
;
187 check_inverse(argv
[optind
-1], &invert
, &optind
, 0);
188 proto
= check_proto(entry
);
189 multiinfo
->count
= parse_multi_ports(argv
[optind
-1],
190 multiinfo
->ports
, proto
);
191 multiinfo
->flags
= IP6T_MULTIPORT_EITHER
;
199 exit_error(PARAMETER_PROBLEM
,
200 "multiport does not support invert");
203 exit_error(PARAMETER_PROBLEM
,
204 "multiport can only have one option");
211 parse_v1(int c
, char **argv
, int invert
, unsigned int *flags
,
212 const struct ip6t_entry
*entry
,
213 unsigned int *nfcache
,
214 struct ip6t_entry_match
**match
)
217 struct ip6t_multiport_v1
*multiinfo
218 = (struct ip6t_multiport_v1
*)(*match
)->data
;
222 check_inverse(argv
[optind
-1], &invert
, &optind
, 0);
223 proto
= check_proto(entry
);
224 parse_multi_ports_v1(argv
[optind
-1], multiinfo
, proto
);
225 multiinfo
->flags
= IP6T_MULTIPORT_SOURCE
;
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
= IP6T_MULTIPORT_DESTINATION
;
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
= IP6T_MULTIPORT_EITHER
;
247 multiinfo
->invert
= 1;
250 exit_error(PARAMETER_PROBLEM
,
251 "multiport can only have one option");
256 /* Final check; must specify something. */
258 final_check(unsigned int flags
)
261 exit_error(PARAMETER_PROBLEM
, "multiport expection an option");
265 port_to_service(int port
, u_int8_t proto
)
267 struct servent
*service
;
269 if ((service
= getservbyport(htons(port
), proto_to_name(proto
))))
270 return service
->s_name
;
276 print_port(u_int16_t port
, u_int8_t protocol
, int numeric
)
280 if (numeric
|| (service
= port_to_service(port
, protocol
)) == NULL
)
283 printf("%s", service
);
286 /* Prints out the matchinfo. */
289 print(const struct ip6t_ip6
*ip
,
290 const struct ip6t_entry_match
*match
,
293 const struct ip6t_multiport
*multiinfo
294 = (const struct ip6t_multiport
*)match
->data
;
297 printf("multiport ");
299 switch (multiinfo
->flags
) {
300 case IP6T_MULTIPORT_SOURCE
:
304 case IP6T_MULTIPORT_DESTINATION
:
308 case IP6T_MULTIPORT_EITHER
:
317 for (i
=0; i
< multiinfo
->count
; i
++) {
318 printf("%s", i
? "," : "");
319 print_port(multiinfo
->ports
[i
], ip
->proto
, numeric
);
326 print_v1(const struct ip6t_ip6
*ip
,
327 const struct ip6t_entry_match
*match
,
330 const struct ip6t_multiport_v1
*multiinfo
331 = (const struct ip6t_multiport_v1
*)match
->data
;
334 printf("multiport ");
336 switch (multiinfo
->flags
) {
337 case IP6T_MULTIPORT_SOURCE
:
341 case IP6T_MULTIPORT_DESTINATION
:
345 case IP6T_MULTIPORT_EITHER
:
354 if (multiinfo
->invert
)
357 for (i
=0; i
< multiinfo
->count
; i
++) {
358 printf("%s", i
? "," : "");
359 print_port(multiinfo
->ports
[i
], ip
->proto
, numeric
);
360 if (multiinfo
->pflags
[i
]) {
362 print_port(multiinfo
->ports
[++i
], ip
->proto
, numeric
);
368 /* Saves the union ip6t_matchinfo in parsable form to stdout. */
370 static void save(const struct ip6t_ip6
*ip
, const struct ip6t_entry_match
*match
)
372 const struct ip6t_multiport
*multiinfo
373 = (const struct ip6t_multiport
*)match
->data
;
376 switch (multiinfo
->flags
) {
377 case IP6T_MULTIPORT_SOURCE
:
381 case IP6T_MULTIPORT_DESTINATION
:
385 case IP6T_MULTIPORT_EITHER
:
390 for (i
=0; i
< multiinfo
->count
; i
++) {
391 printf("%s", i
? "," : "");
392 print_port(multiinfo
->ports
[i
], ip
->proto
, 1);
398 static void save_v1(const struct ip6t_ip6
*ip
,
399 const struct ip6t_entry_match
*match
)
401 const struct ip6t_multiport_v1
*multiinfo
402 = (const struct ip6t_multiport_v1
*)match
->data
;
405 switch (multiinfo
->flags
) {
406 case IP6T_MULTIPORT_SOURCE
:
410 case IP6T_MULTIPORT_DESTINATION
:
414 case IP6T_MULTIPORT_EITHER
:
419 if (multiinfo
->invert
)
422 for (i
=0; i
< multiinfo
->count
; i
++) {
423 printf("%s", i
? "," : "");
424 print_port(multiinfo
->ports
[i
], ip
->proto
, 1);
425 if (multiinfo
->pflags
[i
]) {
427 print_port(multiinfo
->ports
[++i
], ip
->proto
, 1);
434 static struct ip6tables_match multiport
= {
436 .version
= IPTABLES_VERSION
,
437 .size
= IP6T_ALIGN(sizeof(struct ip6t_multiport
)),
438 .userspacesize
= IP6T_ALIGN(sizeof(struct ip6t_multiport
)),
442 .final_check
= &final_check
,
449 static struct ip6tables_match multiport_v1
= {
453 .version
= IPTABLES_VERSION
,
454 .size
= IP6T_ALIGN(sizeof(struct ip6t_multiport_v1
)),
455 .userspacesize
= IP6T_ALIGN(sizeof(struct ip6t_multiport_v1
)),
459 .final_check
= &final_check
,
469 register_match6(&multiport
);
471 register_match6(&multiport_v1
);