Root/target/linux/generic-2.4/patches/618-netfilter_multiport_backport.patch

1--- a/include/linux/netfilter_ipv4/ipt_multiport.h
2+++ b/include/linux/netfilter_ipv4/ipt_multiport.h
3@@ -11,11 +11,12 @@ enum ipt_multiport_flags
4 
5 #define IPT_MULTI_PORTS 15
6 
7-/* Must fit inside union ipt_matchinfo: 16 bytes */
8-struct ipt_multiport
9+struct ipt_multiport_v1
10 {
11     u_int8_t flags; /* Type of comparison */
12     u_int8_t count; /* Number of ports */
13     u_int16_t ports[IPT_MULTI_PORTS]; /* Ports */
14+ u_int8_t pflags[IPT_MULTI_PORTS]; /* Port flags */
15+ u_int8_t invert; /* Invert flag */
16 };
17 #endif /*_IPT_MULTIPORT_H*/
18--- a/net/ipv4/netfilter/ipt_multiport.c
19+++ b/net/ipv4/netfilter/ipt_multiport.c
20@@ -1,5 +1,14 @@
21 /* Kernel module to match one of a list of TCP/UDP ports: ports are in
22    the same place so we can treat them as equal. */
23+
24+/* (C) 1999-2001 Paul `Rusty' Russell
25+ * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
26+ *
27+ * This program is free software; you can redistribute it and/or modify
28+ * it under the terms of the GNU General Public License version 2 as
29+ * published by the Free Software Foundation.
30+ */
31+
32 #include <linux/module.h>
33 #include <linux/types.h>
34 #include <linux/udp.h>
35@@ -8,97 +17,136 @@
36 #include <linux/netfilter_ipv4/ipt_multiport.h>
37 #include <linux/netfilter_ipv4/ip_tables.h>
38 
39+MODULE_LICENSE("GPL");
40+MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
41+MODULE_DESCRIPTION("iptables multiple port match module");
42+
43 #if 0
44 #define duprintf(format, args...) printk(format , ## args)
45 #else
46 #define duprintf(format, args...)
47 #endif
48 
49+/* from linux 2.6 skbuff.h */
50+static inline void *skb_header_pointer(const struct sk_buff *skb, int offset,
51+ int len, void *buffer)
52+{
53+ int hlen = skb_headlen(skb);
54+
55+ if (hlen - offset >= len)
56+ return skb->data + offset;
57+
58+ if (skb_copy_bits(skb, offset, buffer, len) < 0)
59+ return NULL;
60+
61+ return buffer;
62+}
63+
64+
65 /* Returns 1 if the port is matched by the test, 0 otherwise. */
66 static inline int
67-ports_match(const u_int16_t *portlist, enum ipt_multiport_flags flags,
68- u_int8_t count, u_int16_t src, u_int16_t dst)
69+ports_match_v1(const struct ipt_multiport_v1 *minfo,
70+ u_int16_t src, u_int16_t dst)
71 {
72     unsigned int i;
73- for (i=0; i<count; i++) {
74- if (flags != IPT_MULTIPORT_DESTINATION
75- && portlist[i] == src)
76- return 1;
77-
78- if (flags != IPT_MULTIPORT_SOURCE
79- && portlist[i] == dst)
80- return 1;
81- }
82+ u_int16_t s, e;
83 
84- return 0;
85+ for (i=0; i < minfo->count; i++) {
86+ s = minfo->ports[i];
87+
88+ if (minfo->pflags[i]) {
89+ /* range port matching */
90+ e = minfo->ports[++i];
91+ duprintf("src or dst matches with %d-%d?\n", s, e);
92+
93+ if (minfo->flags == IPT_MULTIPORT_SOURCE
94+ && src >= s && src <= e)
95+ return 1 ^ minfo->invert;
96+ if (minfo->flags == IPT_MULTIPORT_DESTINATION
97+ && dst >= s && dst <= e)
98+ return 1 ^ minfo->invert;
99+ if (minfo->flags == IPT_MULTIPORT_EITHER
100+ && ((dst >= s && dst <= e)
101+ || (src >= s && src <= e)))
102+ return 1 ^ minfo->invert;
103+ } else {
104+ /* exact port matching */
105+ duprintf("src or dst matches with %d?\n", s);
106+
107+ if (minfo->flags == IPT_MULTIPORT_SOURCE
108+ && src == s)
109+ return 1 ^ minfo->invert;
110+ if (minfo->flags == IPT_MULTIPORT_DESTINATION
111+ && dst == s)
112+ return 1 ^ minfo->invert;
113+ if (minfo->flags == IPT_MULTIPORT_EITHER
114+ && (src == s || dst == s))
115+ return 1 ^ minfo->invert;
116+ }
117+ }
118+
119+ return minfo->invert;
120 }
121 
122 static int
123-match(const struct sk_buff *skb,
124- const struct net_device *in,
125- const struct net_device *out,
126- const void *matchinfo,
127- int offset,
128- const void *hdr,
129- u_int16_t datalen,
130- int *hotdrop)
131+match_v1(const struct sk_buff *skb,
132+ const struct net_device *in,
133+ const struct net_device *out,
134+ const void *matchinfo,
135+ int offset,
136+ int *hotdrop)
137 {
138- const struct udphdr *udp = hdr;
139- const struct ipt_multiport *multiinfo = matchinfo;
140+ u16 _ports[2], *pptr;
141+ const struct ipt_multiport_v1 *multiinfo = matchinfo;
142+
143+ if (offset)
144+ return 0;
145 
146- /* Must be big enough to read ports. */
147- if (offset == 0 && datalen < sizeof(struct udphdr)) {
148+ pptr = skb_header_pointer(skb, skb->nh.iph->ihl * 4,
149+ sizeof(_ports), _ports);
150+ if (pptr == NULL) {
151         /* We've been asked to examine this packet, and we
152- can't. Hence, no choice but to drop. */
153- duprintf("ipt_multiport:"
154- " Dropping evil offset=0 tinygram.\n");
155- *hotdrop = 1;
156- return 0;
157+ * can't. Hence, no choice but to drop.
158+ */
159+ duprintf("ipt_multiport:"
160+ " Dropping evil offset=0 tinygram.\n");
161+ *hotdrop = 1;
162+ return 0;
163     }
164 
165- /* Must not be a fragment. */
166- return !offset
167- && ports_match(multiinfo->ports,
168- multiinfo->flags, multiinfo->count,
169- ntohs(udp->source), ntohs(udp->dest));
170+ return ports_match_v1(multiinfo, ntohs(pptr[0]), ntohs(pptr[1]));
171 }
172 
173-/* Called when user tries to insert an entry of this type. */
174 static int
175-checkentry(const char *tablename,
176- const struct ipt_ip *ip,
177- void *matchinfo,
178- unsigned int matchsize,
179- unsigned int hook_mask)
180+checkentry_v1(const char *tablename,
181+ const struct ipt_ip *ip,
182+ void *matchinfo,
183+ unsigned int matchsize,
184+ unsigned int hook_mask)
185 {
186- const struct ipt_multiport *multiinfo = matchinfo;
187-
188- if (matchsize != IPT_ALIGN(sizeof(struct ipt_multiport)))
189- return 0;
190-
191- /* Must specify proto == TCP/UDP, no unknown flags or bad count */
192- return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP)
193- && !(ip->invflags & IPT_INV_PROTO)
194- && matchsize == IPT_ALIGN(sizeof(struct ipt_multiport))
195- && (multiinfo->flags == IPT_MULTIPORT_SOURCE
196- || multiinfo->flags == IPT_MULTIPORT_DESTINATION
197- || multiinfo->flags == IPT_MULTIPORT_EITHER)
198- && multiinfo->count <= IPT_MULTI_PORTS;
199+ return (matchsize == IPT_ALIGN(sizeof(struct ipt_multiport_v1)));
200 }
201 
202-static struct ipt_match multiport_match
203-= { { NULL, NULL }, "multiport", &match, &checkentry, NULL, THIS_MODULE };
204+static struct ipt_match multiport_match_v1 = {
205+ .name = "multiport",
206+ .match = &match_v1,
207+ .checkentry = &checkentry_v1,
208+ .me = THIS_MODULE,
209+};
210 
211 static int __init init(void)
212 {
213- return ipt_register_match(&multiport_match);
214+ int err;
215+
216+ err = ipt_register_match(&multiport_match_v1);
217+
218+ return err;
219 }
220 
221 static void __exit fini(void)
222 {
223- ipt_unregister_match(&multiport_match);
224+ ipt_unregister_match(&multiport_match_v1);
225 }
226 
227 module_init(init);
228 module_exit(fini);
229-MODULE_LICENSE("GPL");
230

Archive Download this file



interactive