1 /* Shared library add-on to iptables to add multiple TCP port support. */
8 #include <linux/netfilter_ipv6/ip6t_multiport.h>
10 /* Function which prints out usage message. */
15 "multiport v%s options:\n"
16 " --source-ports port[,port,port...]\n"
18 " match source port(s)\n"
19 " --destination-ports port[,port,port...]\n"
21 " match destination port(s)\n"
22 " --ports port[,port,port]\n"
23 " match both source and destination port(s)\n",
27 static struct option opts[] = {
28 { "source-ports", 1, 0, '1' },
29 { "sports", 1, 0, '1' }, /* synonym */
30 { "destination-ports", 1, 0, '2' },
31 { "dports", 1, 0, '2' }, /* synonym */
32 { "ports", 1, 0, '3' },
37 service_to_port(const char *name, const char *proto)
39 struct servent *service;
41 if ((service = getservbyname(name, proto)) != NULL)
42 return ntohs((unsigned short) service->s_port);
48 parse_port(const char *port, const char *proto)
52 if ((string_to_number(port, 0, 65535, &portnum)) != -1 ||
53 (portnum = service_to_port(port, proto)) != -1)
54 return (u_int16_t)portnum;
56 exit_error(PARAMETER_PROBLEM,
57 "invalid port/service `%s' specified", port);
61 parse_multi_ports(const char *portstring, u_int16_t *ports, const char *proto)
63 char *buffer, *cp, *next;
66 buffer = strdup(portstring);
67 if (!buffer) exit_error(OTHER_PROBLEM, "strdup failed");
69 for (cp=buffer, i=0; cp && i<IP6T_MULTI_PORTS; cp=next,i++)
72 if (next) *next++='\0';
73 ports[i] = parse_port(cp, proto);
75 if (cp) exit_error(PARAMETER_PROBLEM, "too many ports specified");
80 /* Initialize the match. */
82 init(struct ip6t_entry_match *m, unsigned int *nfcache)
87 check_proto(const struct ip6t_entry *entry)
89 if (entry->ipv6.proto == IPPROTO_TCP)
91 else if (entry->ipv6.proto == IPPROTO_UDP)
93 else if (!entry->ipv6.proto)
94 exit_error(PARAMETER_PROBLEM,
95 "multiport needs `-p tcp' or `-p udp'");
97 exit_error(PARAMETER_PROBLEM,
98 "multiport only works with TCP or UDP");
101 /* Function which parses command options; returns true if it
104 parse(int c, char **argv, int invert, unsigned int *flags,
105 const struct ip6t_entry *entry,
106 unsigned int *nfcache,
107 struct ip6t_entry_match **match)
110 struct ip6t_multiport *multiinfo
111 = (struct ip6t_multiport *)(*match)->data;
115 check_inverse(argv[optind-1], &invert, &optind, 0);
116 proto = check_proto(entry);
117 multiinfo->count = parse_multi_ports(argv[optind-1],
118 multiinfo->ports, proto);
119 multiinfo->flags = IP6T_MULTIPORT_SOURCE;
123 check_inverse(argv[optind-1], &invert, &optind, 0);
124 proto = check_proto(entry);
125 multiinfo->count = parse_multi_ports(argv[optind-1],
126 multiinfo->ports, proto);
127 multiinfo->flags = IP6T_MULTIPORT_DESTINATION;
131 check_inverse(argv[optind-1], &invert, &optind, 0);
132 proto = check_proto(entry);
133 multiinfo->count = parse_multi_ports(argv[optind-1],
134 multiinfo->ports, proto);
135 multiinfo->flags = IP6T_MULTIPORT_EITHER;
143 exit_error(PARAMETER_PROBLEM,
144 "multiport does not support invert");
147 exit_error(PARAMETER_PROBLEM,
148 "multiport can only have one option");
153 /* Final check; must specify something. */
155 final_check(unsigned int flags)
158 exit_error(PARAMETER_PROBLEM, "multiport expection an option");
162 port_to_service(int port, u_int8_t proto)
164 struct servent *service;
166 if ((service = getservbyport(htons(port),
167 proto == IPPROTO_TCP ? "tcp" : "udp")))
168 return service->s_name;
174 print_port(u_int16_t port, u_int8_t protocol, int numeric)
178 if (numeric || (service = port_to_service(port, protocol)) == NULL)
181 printf("%s", service);
184 /* Prints out the matchinfo. */
186 print(const struct ip6t_ip6 *ip,
187 const struct ip6t_entry_match *match,
190 const struct ip6t_multiport *multiinfo
191 = (const struct ip6t_multiport *)match->data;
194 printf("multiport ");
196 switch (multiinfo->flags) {
197 case IP6T_MULTIPORT_SOURCE:
201 case IP6T_MULTIPORT_DESTINATION:
205 case IP6T_MULTIPORT_EITHER:
214 for (i=0; i < multiinfo->count; i++) {
215 printf("%s", i ? "," : "");
216 print_port(multiinfo->ports[i], ip->proto, numeric);
221 /* Saves the union ip6t_matchinfo in parsable form to stdout. */
222 static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
224 const struct ip6t_multiport *multiinfo
225 = (const struct ip6t_multiport *)match->data;
228 switch (multiinfo->flags) {
229 case IP6T_MULTIPORT_SOURCE:
233 case IP6T_MULTIPORT_DESTINATION:
237 case IP6T_MULTIPORT_EITHER:
242 for (i=0; i < multiinfo->count; i++) {
243 printf("%s", i ? "," : "");
244 print_port(multiinfo->ports[i], ip->proto, 1);
249 static struct ip6tables_match multiport = {
251 .version = IPTABLES_VERSION,
252 .size = IP6T_ALIGN(sizeof(struct ip6t_multiport)),
253 .userspacesize = IP6T_ALIGN(sizeof(struct ip6t_multiport)),
257 .final_check = &final_check,
266 register_match6(&multiport);