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 proto = check_proto(entry);
116 multiinfo->count = parse_multi_ports(argv[optind-1],
117 multiinfo->ports, proto);
118 multiinfo->flags = IP6T_MULTIPORT_SOURCE;
119 *nfcache |= NFC_IP6_SRC_PT;
123 proto = check_proto(entry);
124 multiinfo->count = parse_multi_ports(argv[optind-1],
125 multiinfo->ports, proto);
126 multiinfo->flags = IP6T_MULTIPORT_DESTINATION;
127 *nfcache |= NFC_IP6_DST_PT;
131 proto = check_proto(entry);
132 multiinfo->count = parse_multi_ports(argv[optind-1],
133 multiinfo->ports, proto);
134 multiinfo->flags = IP6T_MULTIPORT_EITHER;
135 *nfcache |= NFC_IP6_SRC_PT | NFC_IP6_DST_PT;
143 exit_error(PARAMETER_PROBLEM,
144 "multiport can only have one option");
149 /* Final check; must specify something. */
151 final_check(unsigned int flags)
154 exit_error(PARAMETER_PROBLEM, "multiport expection an option");
158 port_to_service(int port, u_int8_t proto)
160 struct servent *service;
162 if ((service = getservbyport(htons(port),
163 proto == IPPROTO_TCP ? "tcp" : "udp")))
164 return service->s_name;
170 print_port(u_int16_t port, u_int8_t protocol, int numeric)
174 if (numeric || (service = port_to_service(port, protocol)) == NULL)
177 printf("%s", service);
180 /* Prints out the matchinfo. */
182 print(const struct ip6t_ip6 *ip,
183 const struct ip6t_entry_match *match,
186 const struct ip6t_multiport *multiinfo
187 = (const struct ip6t_multiport *)match->data;
190 printf("multiport ");
192 switch (multiinfo->flags) {
193 case IP6T_MULTIPORT_SOURCE:
197 case IP6T_MULTIPORT_DESTINATION:
201 case IP6T_MULTIPORT_EITHER:
210 for (i=0; i < multiinfo->count; i++) {
211 printf("%s", i ? "," : "");
212 print_port(multiinfo->ports[i], ip->proto, numeric);
217 /* Saves the union ip6t_matchinfo in parsable form to stdout. */
218 static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
220 const struct ip6t_multiport *multiinfo
221 = (const struct ip6t_multiport *)match->data;
224 switch (multiinfo->flags) {
225 case IP6T_MULTIPORT_SOURCE:
229 case IP6T_MULTIPORT_DESTINATION:
233 case IP6T_MULTIPORT_EITHER:
238 for (i=0; i < multiinfo->count; i++) {
239 printf("%s", i ? "," : "");
240 print_port(multiinfo->ports[i], ip->proto, 1);
246 struct ip6tables_match multiport
250 IP6T_ALIGN(sizeof(struct ip6t_multiport)),
251 IP6T_ALIGN(sizeof(struct ip6t_multiport)),
264 register_match6(&multiport);