Commit a89ecb6a2ef732d04058d87801e2b6bd7e5c7089

Authored by Yasuyuki Kozakai
Committed by David S. Miller
1 parent dc5ab2faec

[NETFILTER]: x_tables: unify IPv4/IPv6 multiport match

This unifies ipt_multiport and ip6t_multiport to xt_multiport.
As a result, this addes support for inversion and port range match
to IPv6 packets.

Signed-off-by: Yasuyuki Kozakai <yasuyuki.kozakai@toshiba.co.jp>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 12 changed files with 372 additions and 381 deletions Side-by-side Diff

include/linux/netfilter/xt_multiport.h
  1 +#ifndef _XT_MULTIPORT_H
  2 +#define _XT_MULTIPORT_H
  3 +
  4 +enum xt_multiport_flags
  5 +{
  6 + XT_MULTIPORT_SOURCE,
  7 + XT_MULTIPORT_DESTINATION,
  8 + XT_MULTIPORT_EITHER
  9 +};
  10 +
  11 +#define XT_MULTI_PORTS 15
  12 +
  13 +/* Must fit inside union xt_matchinfo: 16 bytes */
  14 +struct xt_multiport
  15 +{
  16 + u_int8_t flags; /* Type of comparison */
  17 + u_int8_t count; /* Number of ports */
  18 + u_int16_t ports[XT_MULTI_PORTS]; /* Ports */
  19 +};
  20 +
  21 +struct xt_multiport_v1
  22 +{
  23 + u_int8_t flags; /* Type of comparison */
  24 + u_int8_t count; /* Number of ports */
  25 + u_int16_t ports[XT_MULTI_PORTS]; /* Ports */
  26 + u_int8_t pflags[XT_MULTI_PORTS]; /* Port flags */
  27 + u_int8_t invert; /* Invert flag */
  28 +};
  29 +
  30 +#endif /*_XT_MULTIPORT_H*/
include/linux/netfilter_ipv4/ipt_multiport.h
1 1 #ifndef _IPT_MULTIPORT_H
2 2 #define _IPT_MULTIPORT_H
3   -#include <linux/netfilter_ipv4/ip_tables.h>
4 3  
5   -enum ipt_multiport_flags
6   -{
7   - IPT_MULTIPORT_SOURCE,
8   - IPT_MULTIPORT_DESTINATION,
9   - IPT_MULTIPORT_EITHER
10   -};
  4 +#include <linux/netfilter/xt_multiport.h>
11 5  
12   -#define IPT_MULTI_PORTS 15
  6 +#define IPT_MULTIPORT_SOURCE XT_MULTIPORT_SOURCE
  7 +#define IPT_MULTIPORT_DESTINATION XT_MULTIPORT_DESTINATION
  8 +#define IPT_MULTIPORT_EITHER XT_MULTIPORT_EITHER
13 9  
14   -/* Must fit inside union ipt_matchinfo: 16 bytes */
15   -struct ipt_multiport
16   -{
17   - u_int8_t flags; /* Type of comparison */
18   - u_int8_t count; /* Number of ports */
19   - u_int16_t ports[IPT_MULTI_PORTS]; /* Ports */
20   -};
  10 +#define IPT_MULTI_PORTS XT_MULTI_PORTS
21 11  
22   -struct ipt_multiport_v1
23   -{
24   - u_int8_t flags; /* Type of comparison */
25   - u_int8_t count; /* Number of ports */
26   - u_int16_t ports[IPT_MULTI_PORTS]; /* Ports */
27   - u_int8_t pflags[IPT_MULTI_PORTS]; /* Port flags */
28   - u_int8_t invert; /* Invert flag */
29   -};
  12 +#define ipt_multiport xt_multiport
  13 +#define ipt_multiport_v1 xt_multiport_v1
  14 +
30 15 #endif /*_IPT_MULTIPORT_H*/
include/linux/netfilter_ipv6/ip6t_multiport.h
1 1 #ifndef _IP6T_MULTIPORT_H
2 2 #define _IP6T_MULTIPORT_H
3   -#include <linux/netfilter_ipv6/ip6_tables.h>
4 3  
5   -enum ip6t_multiport_flags
6   -{
7   - IP6T_MULTIPORT_SOURCE,
8   - IP6T_MULTIPORT_DESTINATION,
9   - IP6T_MULTIPORT_EITHER
10   -};
  4 +#include <linux/netfilter/xt_multiport.h>
11 5  
12   -#define IP6T_MULTI_PORTS 15
  6 +#define IP6T_MULTIPORT_SOURCE XT_MULTIPORT_SOURCE
  7 +#define IP6T_MULTIPORT_DESTINATION XT_MULTIPORT_DESTINATION
  8 +#define IP6T_MULTIPORT_EITHER XT_MULTIPORT_EITHER
13 9  
14   -/* Must fit inside union ip6t_matchinfo: 16 bytes */
15   -struct ip6t_multiport
16   -{
17   - u_int8_t flags; /* Type of comparison */
18   - u_int8_t count; /* Number of ports */
19   - u_int16_t ports[IP6T_MULTI_PORTS]; /* Ports */
20   -};
21   -#endif /*_IPT_MULTIPORT_H*/
  10 +#define IP6T_MULTI_PORTS XT_MULTI_PORTS
  11 +
  12 +#define ip6t_multiport xt_multiport
  13 +
  14 +#endif /*_IP6T_MULTIPORT_H*/
net/ipv4/netfilter/Kconfig
... ... @@ -221,16 +221,6 @@
221 221  
222 222 To compile it as a module, choose M here. If unsure, say N.
223 223  
224   -config IP_NF_MATCH_MULTIPORT
225   - tristate "Multiple port match support"
226   - depends on IP_NF_IPTABLES
227   - help
228   - Multiport matching allows you to match TCP or UDP packets based on
229   - a series of source or destination ports: normally a rule can only
230   - match a single range of ports.
231   -
232   - To compile it as a module, choose M here. If unsure, say N.
233   -
234 224 config IP_NF_MATCH_TOS
235 225 tristate "TOS match support"
236 226 depends on IP_NF_IPTABLES
net/ipv4/netfilter/Makefile
... ... @@ -53,7 +53,6 @@
53 53 # matches
54 54 obj-$(CONFIG_IP_NF_MATCH_HASHLIMIT) += ipt_hashlimit.o
55 55 obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
56   -obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
57 56 obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
58 57 obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
59 58 obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
net/ipv4/netfilter/ipt_multiport.c
1   -/* Kernel module to match one of a list of TCP/UDP ports: ports are in
2   - the same place so we can treat them as equal. */
3   -
4   -/* (C) 1999-2001 Paul `Rusty' Russell
5   - * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
6   - *
7   - * This program is free software; you can redistribute it and/or modify
8   - * it under the terms of the GNU General Public License version 2 as
9   - * published by the Free Software Foundation.
10   - */
11   -
12   -#include <linux/module.h>
13   -#include <linux/types.h>
14   -#include <linux/udp.h>
15   -#include <linux/skbuff.h>
16   -
17   -#include <linux/netfilter_ipv4/ipt_multiport.h>
18   -#include <linux/netfilter_ipv4/ip_tables.h>
19   -
20   -MODULE_LICENSE("GPL");
21   -MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
22   -MODULE_DESCRIPTION("iptables multiple port match module");
23   -
24   -#if 0
25   -#define duprintf(format, args...) printk(format , ## args)
26   -#else
27   -#define duprintf(format, args...)
28   -#endif
29   -
30   -/* Returns 1 if the port is matched by the test, 0 otherwise. */
31   -static inline int
32   -ports_match(const u_int16_t *portlist, enum ipt_multiport_flags flags,
33   - u_int8_t count, u_int16_t src, u_int16_t dst)
34   -{
35   - unsigned int i;
36   - for (i=0; i<count; i++) {
37   - if (flags != IPT_MULTIPORT_DESTINATION
38   - && portlist[i] == src)
39   - return 1;
40   -
41   - if (flags != IPT_MULTIPORT_SOURCE
42   - && portlist[i] == dst)
43   - return 1;
44   - }
45   -
46   - return 0;
47   -}
48   -
49   -/* Returns 1 if the port is matched by the test, 0 otherwise. */
50   -static inline int
51   -ports_match_v1(const struct ipt_multiport_v1 *minfo,
52   - u_int16_t src, u_int16_t dst)
53   -{
54   - unsigned int i;
55   - u_int16_t s, e;
56   -
57   - for (i=0; i < minfo->count; i++) {
58   - s = minfo->ports[i];
59   -
60   - if (minfo->pflags[i]) {
61   - /* range port matching */
62   - e = minfo->ports[++i];
63   - duprintf("src or dst matches with %d-%d?\n", s, e);
64   -
65   - if (minfo->flags == IPT_MULTIPORT_SOURCE
66   - && src >= s && src <= e)
67   - return 1 ^ minfo->invert;
68   - if (minfo->flags == IPT_MULTIPORT_DESTINATION
69   - && dst >= s && dst <= e)
70   - return 1 ^ minfo->invert;
71   - if (minfo->flags == IPT_MULTIPORT_EITHER
72   - && ((dst >= s && dst <= e)
73   - || (src >= s && src <= e)))
74   - return 1 ^ minfo->invert;
75   - } else {
76   - /* exact port matching */
77   - duprintf("src or dst matches with %d?\n", s);
78   -
79   - if (minfo->flags == IPT_MULTIPORT_SOURCE
80   - && src == s)
81   - return 1 ^ minfo->invert;
82   - if (minfo->flags == IPT_MULTIPORT_DESTINATION
83   - && dst == s)
84   - return 1 ^ minfo->invert;
85   - if (minfo->flags == IPT_MULTIPORT_EITHER
86   - && (src == s || dst == s))
87   - return 1 ^ minfo->invert;
88   - }
89   - }
90   -
91   - return minfo->invert;
92   -}
93   -
94   -static int
95   -match(const struct sk_buff *skb,
96   - const struct net_device *in,
97   - const struct net_device *out,
98   - const struct xt_match *match,
99   - const void *matchinfo,
100   - int offset,
101   - unsigned int protoff,
102   - int *hotdrop)
103   -{
104   - u16 _ports[2], *pptr;
105   - const struct ipt_multiport *multiinfo = matchinfo;
106   -
107   - if (offset)
108   - return 0;
109   -
110   - pptr = skb_header_pointer(skb, protoff,
111   - sizeof(_ports), _ports);
112   - if (pptr == NULL) {
113   - /* We've been asked to examine this packet, and we
114   - * can't. Hence, no choice but to drop.
115   - */
116   - duprintf("ipt_multiport:"
117   - " Dropping evil offset=0 tinygram.\n");
118   - *hotdrop = 1;
119   - return 0;
120   - }
121   -
122   - return ports_match(multiinfo->ports,
123   - multiinfo->flags, multiinfo->count,
124   - ntohs(pptr[0]), ntohs(pptr[1]));
125   -}
126   -
127   -static int
128   -match_v1(const struct sk_buff *skb,
129   - const struct net_device *in,
130   - const struct net_device *out,
131   - const struct xt_match *match,
132   - const void *matchinfo,
133   - int offset,
134   - unsigned int protoff,
135   - int *hotdrop)
136   -{
137   - u16 _ports[2], *pptr;
138   - const struct ipt_multiport_v1 *multiinfo = matchinfo;
139   -
140   - if (offset)
141   - return 0;
142   -
143   - pptr = skb_header_pointer(skb, protoff,
144   - sizeof(_ports), _ports);
145   - if (pptr == NULL) {
146   - /* We've been asked to examine this packet, and we
147   - * can't. Hence, no choice but to drop.
148   - */
149   - duprintf("ipt_multiport:"
150   - " Dropping evil offset=0 tinygram.\n");
151   - *hotdrop = 1;
152   - return 0;
153   - }
154   -
155   - return ports_match_v1(multiinfo, ntohs(pptr[0]), ntohs(pptr[1]));
156   -}
157   -
158   -static struct ipt_match multiport_match = {
159   - .name = "multiport",
160   - .revision = 0,
161   - .match = match,
162   - .matchsize = sizeof(struct ipt_multiport),
163   - .me = THIS_MODULE,
164   -};
165   -
166   -static struct ipt_match multiport_match_v1 = {
167   - .name = "multiport",
168   - .revision = 1,
169   - .match = match_v1,
170   - .matchsize = sizeof(struct ipt_multiport_v1),
171   - .me = THIS_MODULE,
172   -};
173   -
174   -static int __init ipt_multiport_init(void)
175   -{
176   - int err;
177   -
178   - err = ipt_register_match(&multiport_match);
179   - if (!err) {
180   - err = ipt_register_match(&multiport_match_v1);
181   - if (err)
182   - ipt_unregister_match(&multiport_match);
183   - }
184   -
185   - return err;
186   -}
187   -
188   -static void __exit ipt_multiport_fini(void)
189   -{
190   - ipt_unregister_match(&multiport_match);
191   - ipt_unregister_match(&multiport_match_v1);
192   -}
193   -
194   -module_init(ipt_multiport_init);
195   -module_exit(ipt_multiport_fini);
net/ipv6/netfilter/Kconfig
... ... @@ -87,16 +87,6 @@
87 87  
88 88 To compile it as a module, choose M here. If unsure, say N.
89 89  
90   -config IP6_NF_MATCH_MULTIPORT
91   - tristate "Multiple port match support"
92   - depends on IP6_NF_IPTABLES
93   - help
94   - Multiport matching allows you to match TCP or UDP packets based on
95   - a series of source or destination ports: normally a rule can only
96   - match a single range of ports.
97   -
98   - To compile it as a module, choose M here. If unsure, say N.
99   -
100 90 config IP6_NF_MATCH_OWNER
101 91 tristate "Owner match support"
102 92 depends on IP6_NF_IPTABLES
net/ipv6/netfilter/Makefile
... ... @@ -10,7 +10,6 @@
10 10 obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o
11 11 obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o
12 12 obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o
13   -obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o
14 13 obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o
15 14 obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
16 15 obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
net/ipv6/netfilter/ip6t_multiport.c
1   -/* Kernel module to match one of a list of TCP/UDP ports: ports are in
2   - the same place so we can treat them as equal. */
3   -
4   -/* (C) 1999-2001 Paul `Rusty' Russell
5   - * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
6   - *
7   - * This program is free software; you can redistribute it and/or modify
8   - * it under the terms of the GNU General Public License version 2 as
9   - * published by the Free Software Foundation.
10   - */
11   -
12   -#include <linux/module.h>
13   -#include <linux/types.h>
14   -#include <linux/udp.h>
15   -#include <linux/skbuff.h>
16   -#include <linux/in.h>
17   -
18   -#include <linux/netfilter_ipv6/ip6t_multiport.h>
19   -#include <linux/netfilter_ipv6/ip6_tables.h>
20   -
21   -MODULE_LICENSE("GPL");
22   -MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
23   -MODULE_DESCRIPTION("ip6tables match for multiple ports");
24   -
25   -#if 0
26   -#define duprintf(format, args...) printk(format , ## args)
27   -#else
28   -#define duprintf(format, args...)
29   -#endif
30   -
31   -/* Returns 1 if the port is matched by the test, 0 otherwise. */
32   -static inline int
33   -ports_match(const u_int16_t *portlist, enum ip6t_multiport_flags flags,
34   - u_int8_t count, u_int16_t src, u_int16_t dst)
35   -{
36   - unsigned int i;
37   - for (i=0; i<count; i++) {
38   - if (flags != IP6T_MULTIPORT_DESTINATION
39   - && portlist[i] == src)
40   - return 1;
41   -
42   - if (flags != IP6T_MULTIPORT_SOURCE
43   - && portlist[i] == dst)
44   - return 1;
45   - }
46   -
47   - return 0;
48   -}
49   -
50   -static int
51   -match(const struct sk_buff *skb,
52   - const struct net_device *in,
53   - const struct net_device *out,
54   - const struct xt_match *match,
55   - const void *matchinfo,
56   - int offset,
57   - unsigned int protoff,
58   - int *hotdrop)
59   -{
60   - u16 _ports[2], *pptr;
61   - const struct ip6t_multiport *multiinfo = matchinfo;
62   -
63   - /* Must not be a fragment. */
64   - if (offset)
65   - return 0;
66   -
67   - /* Must be big enough to read ports (both UDP and TCP have
68   - them at the start). */
69   - pptr = skb_header_pointer(skb, protoff, sizeof(_ports), &_ports[0]);
70   - if (pptr == NULL) {
71   - /* We've been asked to examine this packet, and we
72   - * can't. Hence, no choice but to drop.
73   - */
74   - duprintf("ip6t_multiport:"
75   - " Dropping evil offset=0 tinygram.\n");
76   - *hotdrop = 1;
77   - return 0;
78   - }
79   -
80   - return ports_match(multiinfo->ports,
81   - multiinfo->flags, multiinfo->count,
82   - ntohs(pptr[0]), ntohs(pptr[1]));
83   -}
84   -
85   -/* Called when user tries to insert an entry of this type. */
86   -static int
87   -checkentry(const char *tablename,
88   - const void *info,
89   - const struct xt_match *match,
90   - void *matchinfo,
91   - unsigned int matchsize,
92   - unsigned int hook_mask)
93   -{
94   - const struct ip6t_ip6 *ip = info;
95   - const struct ip6t_multiport *multiinfo = matchinfo;
96   -
97   - /* Must specify proto == TCP/UDP, no unknown flags or bad count */
98   - return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP)
99   - && !(ip->invflags & IP6T_INV_PROTO)
100   - && (multiinfo->flags == IP6T_MULTIPORT_SOURCE
101   - || multiinfo->flags == IP6T_MULTIPORT_DESTINATION
102   - || multiinfo->flags == IP6T_MULTIPORT_EITHER)
103   - && multiinfo->count <= IP6T_MULTI_PORTS;
104   -}
105   -
106   -static struct ip6t_match multiport_match = {
107   - .name = "multiport",
108   - .match = match,
109   - .matchsize = sizeof(struct ip6t_multiport),
110   - .checkentry = checkentry,
111   - .me = THIS_MODULE,
112   -};
113   -
114   -static int __init ip6t_multiport_init(void)
115   -{
116   - return ip6t_register_match(&multiport_match);
117   -}
118   -
119   -static void __exit ip6t_multiport_fini(void)
120   -{
121   - ip6t_unregister_match(&multiport_match);
122   -}
123   -
124   -module_init(ip6t_multiport_init);
125   -module_exit(ip6t_multiport_fini);
net/netfilter/Kconfig
... ... @@ -298,6 +298,16 @@
298 298  
299 299 To compile it as a module, choose M here. If unsure, say N.
300 300  
  301 +config NETFILTER_XT_MATCH_MULTIPORT
  302 + tristate "Multiple port match support"
  303 + depends on NETFILTER_XTABLES
  304 + help
  305 + Multiport matching allows you to match TCP or UDP packets based on
  306 + a series of source or destination ports: normally a rule can only
  307 + match a single range of ports.
  308 +
  309 + To compile it as a module, choose M here. If unsure, say N.
  310 +
301 311 config NETFILTER_XT_MATCH_PHYSDEV
302 312 tristate '"physdev" match support'
303 313 depends on NETFILTER_XTABLES && BRIDGE_NETFILTER
net/netfilter/Makefile
... ... @@ -41,6 +41,7 @@
41 41 obj-$(CONFIG_NETFILTER_XT_MATCH_LIMIT) += xt_limit.o
42 42 obj-$(CONFIG_NETFILTER_XT_MATCH_MAC) += xt_mac.o
43 43 obj-$(CONFIG_NETFILTER_XT_MATCH_MARK) += xt_mark.o
  44 +obj-$(CONFIG_NETFILTER_XT_MATCH_MULTIPORT) += xt_multiport.o
44 45 obj-$(CONFIG_NETFILTER_XT_MATCH_POLICY) += xt_policy.o
45 46 obj-$(CONFIG_NETFILTER_XT_MATCH_PKTTYPE) += xt_pkttype.o
46 47 obj-$(CONFIG_NETFILTER_XT_MATCH_REALM) += xt_realm.o
net/netfilter/xt_multiport.c
  1 +/* Kernel module to match one of a list of TCP/UDP ports: ports are in
  2 + the same place so we can treat them as equal. */
  3 +
  4 +/* (C) 1999-2001 Paul `Rusty' Russell
  5 + * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
  6 + *
  7 + * This program is free software; you can redistribute it and/or modify
  8 + * it under the terms of the GNU General Public License version 2 as
  9 + * published by the Free Software Foundation.
  10 + */
  11 +
  12 +#include <linux/module.h>
  13 +#include <linux/types.h>
  14 +#include <linux/udp.h>
  15 +#include <linux/skbuff.h>
  16 +#include <linux/in.h>
  17 +
  18 +#include <linux/netfilter/xt_multiport.h>
  19 +#include <linux/netfilter/x_tables.h>
  20 +#include <linux/netfilter_ipv4/ip_tables.h>
  21 +#include <linux/netfilter_ipv6/ip6_tables.h>
  22 +
  23 +MODULE_LICENSE("GPL");
  24 +MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
  25 +MODULE_DESCRIPTION("x_tables multiple port match module");
  26 +MODULE_ALIAS("ipt_multiport");
  27 +MODULE_ALIAS("ip6t_multiport");
  28 +
  29 +#if 0
  30 +#define duprintf(format, args...) printk(format , ## args)
  31 +#else
  32 +#define duprintf(format, args...)
  33 +#endif
  34 +
  35 +/* Returns 1 if the port is matched by the test, 0 otherwise. */
  36 +static inline int
  37 +ports_match(const u_int16_t *portlist, enum xt_multiport_flags flags,
  38 + u_int8_t count, u_int16_t src, u_int16_t dst)
  39 +{
  40 + unsigned int i;
  41 + for (i = 0; i < count; i++) {
  42 + if (flags != XT_MULTIPORT_DESTINATION && portlist[i] == src)
  43 + return 1;
  44 +
  45 + if (flags != XT_MULTIPORT_SOURCE && portlist[i] == dst)
  46 + return 1;
  47 + }
  48 +
  49 + return 0;
  50 +}
  51 +
  52 +/* Returns 1 if the port is matched by the test, 0 otherwise. */
  53 +static inline int
  54 +ports_match_v1(const struct xt_multiport_v1 *minfo,
  55 + u_int16_t src, u_int16_t dst)
  56 +{
  57 + unsigned int i;
  58 + u_int16_t s, e;
  59 +
  60 + for (i = 0; i < minfo->count; i++) {
  61 + s = minfo->ports[i];
  62 +
  63 + if (minfo->pflags[i]) {
  64 + /* range port matching */
  65 + e = minfo->ports[++i];
  66 + duprintf("src or dst matches with %d-%d?\n", s, e);
  67 +
  68 + if (minfo->flags == XT_MULTIPORT_SOURCE
  69 + && src >= s && src <= e)
  70 + return 1 ^ minfo->invert;
  71 + if (minfo->flags == XT_MULTIPORT_DESTINATION
  72 + && dst >= s && dst <= e)
  73 + return 1 ^ minfo->invert;
  74 + if (minfo->flags == XT_MULTIPORT_EITHER
  75 + && ((dst >= s && dst <= e)
  76 + || (src >= s && src <= e)))
  77 + return 1 ^ minfo->invert;
  78 + } else {
  79 + /* exact port matching */
  80 + duprintf("src or dst matches with %d?\n", s);
  81 +
  82 + if (minfo->flags == XT_MULTIPORT_SOURCE
  83 + && src == s)
  84 + return 1 ^ minfo->invert;
  85 + if (minfo->flags == XT_MULTIPORT_DESTINATION
  86 + && dst == s)
  87 + return 1 ^ minfo->invert;
  88 + if (minfo->flags == XT_MULTIPORT_EITHER
  89 + && (src == s || dst == s))
  90 + return 1 ^ minfo->invert;
  91 + }
  92 + }
  93 +
  94 + return minfo->invert;
  95 +}
  96 +
  97 +static int
  98 +match(const struct sk_buff *skb,
  99 + const struct net_device *in,
  100 + const struct net_device *out,
  101 + const struct xt_match *match,
  102 + const void *matchinfo,
  103 + int offset,
  104 + unsigned int protoff,
  105 + int *hotdrop)
  106 +{
  107 + u16 _ports[2], *pptr;
  108 + const struct xt_multiport *multiinfo = matchinfo;
  109 +
  110 + if (offset)
  111 + return 0;
  112 +
  113 + pptr = skb_header_pointer(skb, protoff, sizeof(_ports), _ports);
  114 + if (pptr == NULL) {
  115 + /* We've been asked to examine this packet, and we
  116 + * can't. Hence, no choice but to drop.
  117 + */
  118 + duprintf("xt_multiport: Dropping evil offset=0 tinygram.\n");
  119 + *hotdrop = 1;
  120 + return 0;
  121 + }
  122 +
  123 + return ports_match(multiinfo->ports,
  124 + multiinfo->flags, multiinfo->count,
  125 + ntohs(pptr[0]), ntohs(pptr[1]));
  126 +}
  127 +
  128 +static int
  129 +match_v1(const struct sk_buff *skb,
  130 + const struct net_device *in,
  131 + const struct net_device *out,
  132 + const struct xt_match *match,
  133 + const void *matchinfo,
  134 + int offset,
  135 + unsigned int protoff,
  136 + int *hotdrop)
  137 +{
  138 + u16 _ports[2], *pptr;
  139 + const struct xt_multiport_v1 *multiinfo = matchinfo;
  140 +
  141 + if (offset)
  142 + return 0;
  143 +
  144 + pptr = skb_header_pointer(skb, protoff, sizeof(_ports), _ports);
  145 + if (pptr == NULL) {
  146 + /* We've been asked to examine this packet, and we
  147 + * can't. Hence, no choice but to drop.
  148 + */
  149 + duprintf("xt_multiport: Dropping evil offset=0 tinygram.\n");
  150 + *hotdrop = 1;
  151 + return 0;
  152 + }
  153 +
  154 + return ports_match_v1(multiinfo, ntohs(pptr[0]), ntohs(pptr[1]));
  155 +}
  156 +
  157 +static inline int
  158 +check(u_int16_t proto,
  159 + u_int8_t ip_invflags,
  160 + u_int8_t match_flags,
  161 + u_int8_t count)
  162 +{
  163 + /* Must specify proto == TCP/UDP, no unknown flags or bad count */
  164 + return (proto == IPPROTO_TCP || proto == IPPROTO_UDP)
  165 + && !(ip_invflags & XT_INV_PROTO)
  166 + && (match_flags == XT_MULTIPORT_SOURCE
  167 + || match_flags == XT_MULTIPORT_DESTINATION
  168 + || match_flags == XT_MULTIPORT_EITHER)
  169 + && count <= XT_MULTI_PORTS;
  170 +}
  171 +
  172 +/* Called when user tries to insert an entry of this type. */
  173 +static int
  174 +checkentry(const char *tablename,
  175 + const void *info,
  176 + const struct xt_match *match,
  177 + void *matchinfo,
  178 + unsigned int matchsize,
  179 + unsigned int hook_mask)
  180 +{
  181 + const struct ipt_ip *ip = info;
  182 + const struct xt_multiport *multiinfo = matchinfo;
  183 +
  184 + return check(ip->proto, ip->invflags, multiinfo->flags,
  185 + multiinfo->count);
  186 +}
  187 +
  188 +static int
  189 +checkentry_v1(const char *tablename,
  190 + const void *info,
  191 + const struct xt_match *match,
  192 + void *matchinfo,
  193 + unsigned int matchsize,
  194 + unsigned int hook_mask)
  195 +{
  196 + const struct ipt_ip *ip = info;
  197 + const struct xt_multiport_v1 *multiinfo = matchinfo;
  198 +
  199 + return check(ip->proto, ip->invflags, multiinfo->flags,
  200 + multiinfo->count);
  201 +}
  202 +
  203 +static int
  204 +checkentry6(const char *tablename,
  205 + const void *info,
  206 + const struct xt_match *match,
  207 + void *matchinfo,
  208 + unsigned int matchsize,
  209 + unsigned int hook_mask)
  210 +{
  211 + const struct ip6t_ip6 *ip = info;
  212 + const struct xt_multiport *multiinfo = matchinfo;
  213 +
  214 + return check(ip->proto, ip->invflags, multiinfo->flags,
  215 + multiinfo->count);
  216 +}
  217 +
  218 +static int
  219 +checkentry6_v1(const char *tablename,
  220 + const void *info,
  221 + const struct xt_match *match,
  222 + void *matchinfo,
  223 + unsigned int matchsize,
  224 + unsigned int hook_mask)
  225 +{
  226 + const struct ip6t_ip6 *ip = info;
  227 + const struct xt_multiport_v1 *multiinfo = matchinfo;
  228 +
  229 + return check(ip->proto, ip->invflags, multiinfo->flags,
  230 + multiinfo->count);
  231 +}
  232 +
  233 +static struct xt_match multiport_match = {
  234 + .name = "multiport",
  235 + .revision = 0,
  236 + .matchsize = sizeof(struct xt_multiport),
  237 + .match = &match,
  238 + .checkentry = &checkentry,
  239 + .family = AF_INET,
  240 + .me = THIS_MODULE,
  241 +};
  242 +
  243 +static struct xt_match multiport_match_v1 = {
  244 + .name = "multiport",
  245 + .revision = 1,
  246 + .matchsize = sizeof(struct xt_multiport_v1),
  247 + .match = &match_v1,
  248 + .checkentry = &checkentry_v1,
  249 + .family = AF_INET,
  250 + .me = THIS_MODULE,
  251 +};
  252 +
  253 +static struct xt_match multiport6_match = {
  254 + .name = "multiport",
  255 + .revision = 0,
  256 + .matchsize = sizeof(struct xt_multiport),
  257 + .match = &match,
  258 + .checkentry = &checkentry6,
  259 + .family = AF_INET6,
  260 + .me = THIS_MODULE,
  261 +};
  262 +
  263 +static struct xt_match multiport6_match_v1 = {
  264 + .name = "multiport",
  265 + .revision = 1,
  266 + .matchsize = sizeof(struct xt_multiport_v1),
  267 + .match = &match_v1,
  268 + .checkentry = &checkentry6_v1,
  269 + .family = AF_INET6,
  270 + .me = THIS_MODULE,
  271 +};
  272 +
  273 +static int __init xt_multiport_init(void)
  274 +{
  275 + int ret;
  276 +
  277 + ret = xt_register_match(&multiport_match);
  278 + if (ret)
  279 + goto out;
  280 +
  281 + ret = xt_register_match(&multiport_match_v1);
  282 + if (ret)
  283 + goto out_unreg_multi_v0;
  284 +
  285 + ret = xt_register_match(&multiport6_match);
  286 + if (ret)
  287 + goto out_unreg_multi_v1;
  288 +
  289 + ret = xt_register_match(&multiport6_match_v1);
  290 + if (ret)
  291 + goto out_unreg_multi6_v0;
  292 +
  293 + return ret;
  294 +
  295 +out_unreg_multi6_v0:
  296 + xt_unregister_match(&multiport6_match);
  297 +out_unreg_multi_v1:
  298 + xt_unregister_match(&multiport_match_v1);
  299 +out_unreg_multi_v0:
  300 + xt_unregister_match(&multiport_match);
  301 +out:
  302 + return ret;
  303 +}
  304 +
  305 +static void __exit xt_multiport_fini(void)
  306 +{
  307 + xt_unregister_match(&multiport_match);
  308 + xt_unregister_match(&multiport_match_v1);
  309 + xt_unregister_match(&multiport6_match);
  310 + xt_unregister_match(&multiport6_match_v1);
  311 +}
  312 +
  313 +module_init(xt_multiport_init);
  314 +module_exit(xt_multiport_fini);