xref: /openbmc/linux/net/netfilter/xt_multiport.c (revision a89ecb6a)
1a89ecb6aSYasuyuki Kozakai /* Kernel module to match one of a list of TCP/UDP ports: ports are in
2a89ecb6aSYasuyuki Kozakai    the same place so we can treat them as equal. */
3a89ecb6aSYasuyuki Kozakai 
4a89ecb6aSYasuyuki Kozakai /* (C) 1999-2001 Paul `Rusty' Russell
5a89ecb6aSYasuyuki Kozakai  * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
6a89ecb6aSYasuyuki Kozakai  *
7a89ecb6aSYasuyuki Kozakai  * This program is free software; you can redistribute it and/or modify
8a89ecb6aSYasuyuki Kozakai  * it under the terms of the GNU General Public License version 2 as
9a89ecb6aSYasuyuki Kozakai  * published by the Free Software Foundation.
10a89ecb6aSYasuyuki Kozakai  */
11a89ecb6aSYasuyuki Kozakai 
12a89ecb6aSYasuyuki Kozakai #include <linux/module.h>
13a89ecb6aSYasuyuki Kozakai #include <linux/types.h>
14a89ecb6aSYasuyuki Kozakai #include <linux/udp.h>
15a89ecb6aSYasuyuki Kozakai #include <linux/skbuff.h>
16a89ecb6aSYasuyuki Kozakai #include <linux/in.h>
17a89ecb6aSYasuyuki Kozakai 
18a89ecb6aSYasuyuki Kozakai #include <linux/netfilter/xt_multiport.h>
19a89ecb6aSYasuyuki Kozakai #include <linux/netfilter/x_tables.h>
20a89ecb6aSYasuyuki Kozakai #include <linux/netfilter_ipv4/ip_tables.h>
21a89ecb6aSYasuyuki Kozakai #include <linux/netfilter_ipv6/ip6_tables.h>
22a89ecb6aSYasuyuki Kozakai 
23a89ecb6aSYasuyuki Kozakai MODULE_LICENSE("GPL");
24a89ecb6aSYasuyuki Kozakai MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
25a89ecb6aSYasuyuki Kozakai MODULE_DESCRIPTION("x_tables multiple port match module");
26a89ecb6aSYasuyuki Kozakai MODULE_ALIAS("ipt_multiport");
27a89ecb6aSYasuyuki Kozakai MODULE_ALIAS("ip6t_multiport");
28a89ecb6aSYasuyuki Kozakai 
29a89ecb6aSYasuyuki Kozakai #if 0
30a89ecb6aSYasuyuki Kozakai #define duprintf(format, args...) printk(format , ## args)
31a89ecb6aSYasuyuki Kozakai #else
32a89ecb6aSYasuyuki Kozakai #define duprintf(format, args...)
33a89ecb6aSYasuyuki Kozakai #endif
34a89ecb6aSYasuyuki Kozakai 
35a89ecb6aSYasuyuki Kozakai /* Returns 1 if the port is matched by the test, 0 otherwise. */
36a89ecb6aSYasuyuki Kozakai static inline int
37a89ecb6aSYasuyuki Kozakai ports_match(const u_int16_t *portlist, enum xt_multiport_flags flags,
38a89ecb6aSYasuyuki Kozakai 	    u_int8_t count, u_int16_t src, u_int16_t dst)
39a89ecb6aSYasuyuki Kozakai {
40a89ecb6aSYasuyuki Kozakai 	unsigned int i;
41a89ecb6aSYasuyuki Kozakai 	for (i = 0; i < count; i++) {
42a89ecb6aSYasuyuki Kozakai 		if (flags != XT_MULTIPORT_DESTINATION && portlist[i] == src)
43a89ecb6aSYasuyuki Kozakai 			return 1;
44a89ecb6aSYasuyuki Kozakai 
45a89ecb6aSYasuyuki Kozakai 		if (flags != XT_MULTIPORT_SOURCE && portlist[i] == dst)
46a89ecb6aSYasuyuki Kozakai 			return 1;
47a89ecb6aSYasuyuki Kozakai 	}
48a89ecb6aSYasuyuki Kozakai 
49a89ecb6aSYasuyuki Kozakai 	return 0;
50a89ecb6aSYasuyuki Kozakai }
51a89ecb6aSYasuyuki Kozakai 
52a89ecb6aSYasuyuki Kozakai /* Returns 1 if the port is matched by the test, 0 otherwise. */
53a89ecb6aSYasuyuki Kozakai static inline int
54a89ecb6aSYasuyuki Kozakai ports_match_v1(const struct xt_multiport_v1 *minfo,
55a89ecb6aSYasuyuki Kozakai 	       u_int16_t src, u_int16_t dst)
56a89ecb6aSYasuyuki Kozakai {
57a89ecb6aSYasuyuki Kozakai 	unsigned int i;
58a89ecb6aSYasuyuki Kozakai 	u_int16_t s, e;
59a89ecb6aSYasuyuki Kozakai 
60a89ecb6aSYasuyuki Kozakai 	for (i = 0; i < minfo->count; i++) {
61a89ecb6aSYasuyuki Kozakai 		s = minfo->ports[i];
62a89ecb6aSYasuyuki Kozakai 
63a89ecb6aSYasuyuki Kozakai 		if (minfo->pflags[i]) {
64a89ecb6aSYasuyuki Kozakai 			/* range port matching */
65a89ecb6aSYasuyuki Kozakai 			e = minfo->ports[++i];
66a89ecb6aSYasuyuki Kozakai 			duprintf("src or dst matches with %d-%d?\n", s, e);
67a89ecb6aSYasuyuki Kozakai 
68a89ecb6aSYasuyuki Kozakai 			if (minfo->flags == XT_MULTIPORT_SOURCE
69a89ecb6aSYasuyuki Kozakai 			    && src >= s && src <= e)
70a89ecb6aSYasuyuki Kozakai 				return 1 ^ minfo->invert;
71a89ecb6aSYasuyuki Kozakai 			if (minfo->flags == XT_MULTIPORT_DESTINATION
72a89ecb6aSYasuyuki Kozakai 			    && dst >= s && dst <= e)
73a89ecb6aSYasuyuki Kozakai 				return 1 ^ minfo->invert;
74a89ecb6aSYasuyuki Kozakai 			if (minfo->flags == XT_MULTIPORT_EITHER
75a89ecb6aSYasuyuki Kozakai 			    && ((dst >= s && dst <= e)
76a89ecb6aSYasuyuki Kozakai 				|| (src >= s && src <= e)))
77a89ecb6aSYasuyuki Kozakai 				return 1 ^ minfo->invert;
78a89ecb6aSYasuyuki Kozakai 		} else {
79a89ecb6aSYasuyuki Kozakai 			/* exact port matching */
80a89ecb6aSYasuyuki Kozakai 			duprintf("src or dst matches with %d?\n", s);
81a89ecb6aSYasuyuki Kozakai 
82a89ecb6aSYasuyuki Kozakai 			if (minfo->flags == XT_MULTIPORT_SOURCE
83a89ecb6aSYasuyuki Kozakai 			    && src == s)
84a89ecb6aSYasuyuki Kozakai 				return 1 ^ minfo->invert;
85a89ecb6aSYasuyuki Kozakai 			if (minfo->flags == XT_MULTIPORT_DESTINATION
86a89ecb6aSYasuyuki Kozakai 			    && dst == s)
87a89ecb6aSYasuyuki Kozakai 				return 1 ^ minfo->invert;
88a89ecb6aSYasuyuki Kozakai 			if (minfo->flags == XT_MULTIPORT_EITHER
89a89ecb6aSYasuyuki Kozakai 			    && (src == s || dst == s))
90a89ecb6aSYasuyuki Kozakai 				return 1 ^ minfo->invert;
91a89ecb6aSYasuyuki Kozakai 		}
92a89ecb6aSYasuyuki Kozakai 	}
93a89ecb6aSYasuyuki Kozakai 
94a89ecb6aSYasuyuki Kozakai  	return minfo->invert;
95a89ecb6aSYasuyuki Kozakai }
96a89ecb6aSYasuyuki Kozakai 
97a89ecb6aSYasuyuki Kozakai static int
98a89ecb6aSYasuyuki Kozakai match(const struct sk_buff *skb,
99a89ecb6aSYasuyuki Kozakai       const struct net_device *in,
100a89ecb6aSYasuyuki Kozakai       const struct net_device *out,
101a89ecb6aSYasuyuki Kozakai       const struct xt_match *match,
102a89ecb6aSYasuyuki Kozakai       const void *matchinfo,
103a89ecb6aSYasuyuki Kozakai       int offset,
104a89ecb6aSYasuyuki Kozakai       unsigned int protoff,
105a89ecb6aSYasuyuki Kozakai       int *hotdrop)
106a89ecb6aSYasuyuki Kozakai {
107a89ecb6aSYasuyuki Kozakai 	u16 _ports[2], *pptr;
108a89ecb6aSYasuyuki Kozakai 	const struct xt_multiport *multiinfo = matchinfo;
109a89ecb6aSYasuyuki Kozakai 
110a89ecb6aSYasuyuki Kozakai 	if (offset)
111a89ecb6aSYasuyuki Kozakai 		return 0;
112a89ecb6aSYasuyuki Kozakai 
113a89ecb6aSYasuyuki Kozakai 	pptr = skb_header_pointer(skb, protoff, sizeof(_ports), _ports);
114a89ecb6aSYasuyuki Kozakai 	if (pptr == NULL) {
115a89ecb6aSYasuyuki Kozakai 		/* We've been asked to examine this packet, and we
116a89ecb6aSYasuyuki Kozakai 		 * can't.  Hence, no choice but to drop.
117a89ecb6aSYasuyuki Kozakai 		 */
118a89ecb6aSYasuyuki Kozakai 		duprintf("xt_multiport: Dropping evil offset=0 tinygram.\n");
119a89ecb6aSYasuyuki Kozakai 		*hotdrop = 1;
120a89ecb6aSYasuyuki Kozakai 		return 0;
121a89ecb6aSYasuyuki Kozakai 	}
122a89ecb6aSYasuyuki Kozakai 
123a89ecb6aSYasuyuki Kozakai 	return ports_match(multiinfo->ports,
124a89ecb6aSYasuyuki Kozakai 			   multiinfo->flags, multiinfo->count,
125a89ecb6aSYasuyuki Kozakai 			   ntohs(pptr[0]), ntohs(pptr[1]));
126a89ecb6aSYasuyuki Kozakai }
127a89ecb6aSYasuyuki Kozakai 
128a89ecb6aSYasuyuki Kozakai static int
129a89ecb6aSYasuyuki Kozakai match_v1(const struct sk_buff *skb,
130a89ecb6aSYasuyuki Kozakai 	 const struct net_device *in,
131a89ecb6aSYasuyuki Kozakai 	 const struct net_device *out,
132a89ecb6aSYasuyuki Kozakai 	 const struct xt_match *match,
133a89ecb6aSYasuyuki Kozakai 	 const void *matchinfo,
134a89ecb6aSYasuyuki Kozakai 	 int offset,
135a89ecb6aSYasuyuki Kozakai 	 unsigned int protoff,
136a89ecb6aSYasuyuki Kozakai 	 int *hotdrop)
137a89ecb6aSYasuyuki Kozakai {
138a89ecb6aSYasuyuki Kozakai 	u16 _ports[2], *pptr;
139a89ecb6aSYasuyuki Kozakai 	const struct xt_multiport_v1 *multiinfo = matchinfo;
140a89ecb6aSYasuyuki Kozakai 
141a89ecb6aSYasuyuki Kozakai 	if (offset)
142a89ecb6aSYasuyuki Kozakai 		return 0;
143a89ecb6aSYasuyuki Kozakai 
144a89ecb6aSYasuyuki Kozakai 	pptr = skb_header_pointer(skb, protoff, sizeof(_ports), _ports);
145a89ecb6aSYasuyuki Kozakai 	if (pptr == NULL) {
146a89ecb6aSYasuyuki Kozakai 		/* We've been asked to examine this packet, and we
147a89ecb6aSYasuyuki Kozakai 		 * can't.  Hence, no choice but to drop.
148a89ecb6aSYasuyuki Kozakai 		 */
149a89ecb6aSYasuyuki Kozakai 		duprintf("xt_multiport: Dropping evil offset=0 tinygram.\n");
150a89ecb6aSYasuyuki Kozakai 		*hotdrop = 1;
151a89ecb6aSYasuyuki Kozakai 		return 0;
152a89ecb6aSYasuyuki Kozakai 	}
153a89ecb6aSYasuyuki Kozakai 
154a89ecb6aSYasuyuki Kozakai 	return ports_match_v1(multiinfo, ntohs(pptr[0]), ntohs(pptr[1]));
155a89ecb6aSYasuyuki Kozakai }
156a89ecb6aSYasuyuki Kozakai 
157a89ecb6aSYasuyuki Kozakai static inline int
158a89ecb6aSYasuyuki Kozakai check(u_int16_t proto,
159a89ecb6aSYasuyuki Kozakai       u_int8_t ip_invflags,
160a89ecb6aSYasuyuki Kozakai       u_int8_t match_flags,
161a89ecb6aSYasuyuki Kozakai       u_int8_t count)
162a89ecb6aSYasuyuki Kozakai {
163a89ecb6aSYasuyuki Kozakai 	/* Must specify proto == TCP/UDP, no unknown flags or bad count */
164a89ecb6aSYasuyuki Kozakai 	return (proto == IPPROTO_TCP || proto == IPPROTO_UDP)
165a89ecb6aSYasuyuki Kozakai 		&& !(ip_invflags & XT_INV_PROTO)
166a89ecb6aSYasuyuki Kozakai 		&& (match_flags == XT_MULTIPORT_SOURCE
167a89ecb6aSYasuyuki Kozakai 		    || match_flags == XT_MULTIPORT_DESTINATION
168a89ecb6aSYasuyuki Kozakai 		    || match_flags == XT_MULTIPORT_EITHER)
169a89ecb6aSYasuyuki Kozakai 		&& count <= XT_MULTI_PORTS;
170a89ecb6aSYasuyuki Kozakai }
171a89ecb6aSYasuyuki Kozakai 
172a89ecb6aSYasuyuki Kozakai /* Called when user tries to insert an entry of this type. */
173a89ecb6aSYasuyuki Kozakai static int
174a89ecb6aSYasuyuki Kozakai checkentry(const char *tablename,
175a89ecb6aSYasuyuki Kozakai 	   const void *info,
176a89ecb6aSYasuyuki Kozakai 	   const struct xt_match *match,
177a89ecb6aSYasuyuki Kozakai 	   void *matchinfo,
178a89ecb6aSYasuyuki Kozakai 	   unsigned int matchsize,
179a89ecb6aSYasuyuki Kozakai 	   unsigned int hook_mask)
180a89ecb6aSYasuyuki Kozakai {
181a89ecb6aSYasuyuki Kozakai 	const struct ipt_ip *ip = info;
182a89ecb6aSYasuyuki Kozakai 	const struct xt_multiport *multiinfo = matchinfo;
183a89ecb6aSYasuyuki Kozakai 
184a89ecb6aSYasuyuki Kozakai 	return check(ip->proto, ip->invflags, multiinfo->flags,
185a89ecb6aSYasuyuki Kozakai 		     multiinfo->count);
186a89ecb6aSYasuyuki Kozakai }
187a89ecb6aSYasuyuki Kozakai 
188a89ecb6aSYasuyuki Kozakai static int
189a89ecb6aSYasuyuki Kozakai checkentry_v1(const char *tablename,
190a89ecb6aSYasuyuki Kozakai 	      const void *info,
191a89ecb6aSYasuyuki Kozakai 	      const struct xt_match *match,
192a89ecb6aSYasuyuki Kozakai 	      void *matchinfo,
193a89ecb6aSYasuyuki Kozakai 	      unsigned int matchsize,
194a89ecb6aSYasuyuki Kozakai 	      unsigned int hook_mask)
195a89ecb6aSYasuyuki Kozakai {
196a89ecb6aSYasuyuki Kozakai 	const struct ipt_ip *ip = info;
197a89ecb6aSYasuyuki Kozakai 	const struct xt_multiport_v1 *multiinfo = matchinfo;
198a89ecb6aSYasuyuki Kozakai 
199a89ecb6aSYasuyuki Kozakai 	return check(ip->proto, ip->invflags, multiinfo->flags,
200a89ecb6aSYasuyuki Kozakai 		     multiinfo->count);
201a89ecb6aSYasuyuki Kozakai }
202a89ecb6aSYasuyuki Kozakai 
203a89ecb6aSYasuyuki Kozakai static int
204a89ecb6aSYasuyuki Kozakai checkentry6(const char *tablename,
205a89ecb6aSYasuyuki Kozakai 	    const void *info,
206a89ecb6aSYasuyuki Kozakai 	    const struct xt_match *match,
207a89ecb6aSYasuyuki Kozakai 	    void *matchinfo,
208a89ecb6aSYasuyuki Kozakai 	    unsigned int matchsize,
209a89ecb6aSYasuyuki Kozakai 	    unsigned int hook_mask)
210a89ecb6aSYasuyuki Kozakai {
211a89ecb6aSYasuyuki Kozakai 	const struct ip6t_ip6 *ip = info;
212a89ecb6aSYasuyuki Kozakai 	const struct xt_multiport *multiinfo = matchinfo;
213a89ecb6aSYasuyuki Kozakai 
214a89ecb6aSYasuyuki Kozakai 	return check(ip->proto, ip->invflags, multiinfo->flags,
215a89ecb6aSYasuyuki Kozakai 		     multiinfo->count);
216a89ecb6aSYasuyuki Kozakai }
217a89ecb6aSYasuyuki Kozakai 
218a89ecb6aSYasuyuki Kozakai static int
219a89ecb6aSYasuyuki Kozakai checkentry6_v1(const char *tablename,
220a89ecb6aSYasuyuki Kozakai 	       const void *info,
221a89ecb6aSYasuyuki Kozakai 	       const struct xt_match *match,
222a89ecb6aSYasuyuki Kozakai 	       void *matchinfo,
223a89ecb6aSYasuyuki Kozakai 	       unsigned int matchsize,
224a89ecb6aSYasuyuki Kozakai 	       unsigned int hook_mask)
225a89ecb6aSYasuyuki Kozakai {
226a89ecb6aSYasuyuki Kozakai 	const struct ip6t_ip6 *ip = info;
227a89ecb6aSYasuyuki Kozakai 	const struct xt_multiport_v1 *multiinfo = matchinfo;
228a89ecb6aSYasuyuki Kozakai 
229a89ecb6aSYasuyuki Kozakai 	return check(ip->proto, ip->invflags, multiinfo->flags,
230a89ecb6aSYasuyuki Kozakai 		     multiinfo->count);
231a89ecb6aSYasuyuki Kozakai }
232a89ecb6aSYasuyuki Kozakai 
233a89ecb6aSYasuyuki Kozakai static struct xt_match multiport_match = {
234a89ecb6aSYasuyuki Kozakai 	.name		= "multiport",
235a89ecb6aSYasuyuki Kozakai 	.revision	= 0,
236a89ecb6aSYasuyuki Kozakai 	.matchsize	= sizeof(struct xt_multiport),
237a89ecb6aSYasuyuki Kozakai 	.match		= &match,
238a89ecb6aSYasuyuki Kozakai 	.checkentry	= &checkentry,
239a89ecb6aSYasuyuki Kozakai 	.family		= AF_INET,
240a89ecb6aSYasuyuki Kozakai 	.me		= THIS_MODULE,
241a89ecb6aSYasuyuki Kozakai };
242a89ecb6aSYasuyuki Kozakai 
243a89ecb6aSYasuyuki Kozakai static struct xt_match multiport_match_v1 = {
244a89ecb6aSYasuyuki Kozakai 	.name		= "multiport",
245a89ecb6aSYasuyuki Kozakai 	.revision	= 1,
246a89ecb6aSYasuyuki Kozakai 	.matchsize	= sizeof(struct xt_multiport_v1),
247a89ecb6aSYasuyuki Kozakai 	.match		= &match_v1,
248a89ecb6aSYasuyuki Kozakai 	.checkentry	= &checkentry_v1,
249a89ecb6aSYasuyuki Kozakai 	.family		= AF_INET,
250a89ecb6aSYasuyuki Kozakai 	.me		= THIS_MODULE,
251a89ecb6aSYasuyuki Kozakai };
252a89ecb6aSYasuyuki Kozakai 
253a89ecb6aSYasuyuki Kozakai static struct xt_match multiport6_match = {
254a89ecb6aSYasuyuki Kozakai 	.name		= "multiport",
255a89ecb6aSYasuyuki Kozakai 	.revision	= 0,
256a89ecb6aSYasuyuki Kozakai 	.matchsize	= sizeof(struct xt_multiport),
257a89ecb6aSYasuyuki Kozakai 	.match		= &match,
258a89ecb6aSYasuyuki Kozakai 	.checkentry	= &checkentry6,
259a89ecb6aSYasuyuki Kozakai 	.family		= AF_INET6,
260a89ecb6aSYasuyuki Kozakai 	.me		= THIS_MODULE,
261a89ecb6aSYasuyuki Kozakai };
262a89ecb6aSYasuyuki Kozakai 
263a89ecb6aSYasuyuki Kozakai static struct xt_match multiport6_match_v1 = {
264a89ecb6aSYasuyuki Kozakai 	.name		= "multiport",
265a89ecb6aSYasuyuki Kozakai 	.revision	= 1,
266a89ecb6aSYasuyuki Kozakai 	.matchsize	= sizeof(struct xt_multiport_v1),
267a89ecb6aSYasuyuki Kozakai 	.match		= &match_v1,
268a89ecb6aSYasuyuki Kozakai 	.checkentry	= &checkentry6_v1,
269a89ecb6aSYasuyuki Kozakai 	.family		= AF_INET6,
270a89ecb6aSYasuyuki Kozakai 	.me		= THIS_MODULE,
271a89ecb6aSYasuyuki Kozakai };
272a89ecb6aSYasuyuki Kozakai 
273a89ecb6aSYasuyuki Kozakai static int __init xt_multiport_init(void)
274a89ecb6aSYasuyuki Kozakai {
275a89ecb6aSYasuyuki Kozakai 	int ret;
276a89ecb6aSYasuyuki Kozakai 
277a89ecb6aSYasuyuki Kozakai 	ret = xt_register_match(&multiport_match);
278a89ecb6aSYasuyuki Kozakai 	if (ret)
279a89ecb6aSYasuyuki Kozakai 		goto out;
280a89ecb6aSYasuyuki Kozakai 
281a89ecb6aSYasuyuki Kozakai 	ret = xt_register_match(&multiport_match_v1);
282a89ecb6aSYasuyuki Kozakai 	if (ret)
283a89ecb6aSYasuyuki Kozakai 		goto out_unreg_multi_v0;
284a89ecb6aSYasuyuki Kozakai 
285a89ecb6aSYasuyuki Kozakai 	ret = xt_register_match(&multiport6_match);
286a89ecb6aSYasuyuki Kozakai 	if (ret)
287a89ecb6aSYasuyuki Kozakai 		goto out_unreg_multi_v1;
288a89ecb6aSYasuyuki Kozakai 
289a89ecb6aSYasuyuki Kozakai 	ret = xt_register_match(&multiport6_match_v1);
290a89ecb6aSYasuyuki Kozakai 	if (ret)
291a89ecb6aSYasuyuki Kozakai 		goto out_unreg_multi6_v0;
292a89ecb6aSYasuyuki Kozakai 
293a89ecb6aSYasuyuki Kozakai 	return ret;
294a89ecb6aSYasuyuki Kozakai 
295a89ecb6aSYasuyuki Kozakai out_unreg_multi6_v0:
296a89ecb6aSYasuyuki Kozakai 	xt_unregister_match(&multiport6_match);
297a89ecb6aSYasuyuki Kozakai out_unreg_multi_v1:
298a89ecb6aSYasuyuki Kozakai 	xt_unregister_match(&multiport_match_v1);
299a89ecb6aSYasuyuki Kozakai out_unreg_multi_v0:
300a89ecb6aSYasuyuki Kozakai 	xt_unregister_match(&multiport_match);
301a89ecb6aSYasuyuki Kozakai out:
302a89ecb6aSYasuyuki Kozakai 	return ret;
303a89ecb6aSYasuyuki Kozakai }
304a89ecb6aSYasuyuki Kozakai 
305a89ecb6aSYasuyuki Kozakai static void __exit xt_multiport_fini(void)
306a89ecb6aSYasuyuki Kozakai {
307a89ecb6aSYasuyuki Kozakai 	xt_unregister_match(&multiport_match);
308a89ecb6aSYasuyuki Kozakai 	xt_unregister_match(&multiport_match_v1);
309a89ecb6aSYasuyuki Kozakai 	xt_unregister_match(&multiport6_match);
310a89ecb6aSYasuyuki Kozakai 	xt_unregister_match(&multiport6_match_v1);
311a89ecb6aSYasuyuki Kozakai }
312a89ecb6aSYasuyuki Kozakai 
313a89ecb6aSYasuyuki Kozakai module_init(xt_multiport_init);
314a89ecb6aSYasuyuki Kozakai module_exit(xt_multiport_fini);
315