[x86] the olpc config that was merged from the olpc port is a 2.6.30 config
[openwrt.git] / 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");