]> git.pld-linux.org Git - packages/kernel.git/blob - kernel-pom-ng-connlimit.patch
- fix netlink (inet_diag) inside vservers
[packages/kernel.git] / kernel-pom-ng-connlimit.patch
1 diff -Nru linux-2.6.22/include/linux/netfilter_ipv4/ipt_connlimit.h linux-2.6.22-pom2patch/include/linux/netfilter_ipv4/ipt_connlimit.h
2 --- linux-2.6.22/include/linux/netfilter_ipv4/ipt_connlimit.h   1970-01-01 01:00:00.000000000 +0100
3 +++ linux-2.6.22-pom2patch/include/linux/netfilter_ipv4/ipt_connlimit.h 2007-08-07 18:38:25.000000000 +0200
4 @@ -0,0 +1,12 @@
5 +#ifndef _IPT_CONNLIMIT_H
6 +#define _IPT_CONNLIMIT_H
7 +
8 +struct ipt_connlimit_data;
9 +
10 +struct ipt_connlimit_info {
11 +       int limit;
12 +       int inverse;
13 +       u_int32_t mask;
14 +       struct ipt_connlimit_data *data;
15 +};
16 +#endif /* _IPT_CONNLIMIT_H */
17 diff -Nru linux-2.6.22/net/ipv4/netfilter/ipt_connlimit.c linux-2.6.22-pom2patch/net/ipv4/netfilter/ipt_connlimit.c
18 --- linux-2.6.22/net/ipv4/netfilter/ipt_connlimit.c     1970-01-01 01:00:00.000000000 +0100
19 +++ linux-2.6.22-pom2patch/net/ipv4/netfilter/ipt_connlimit.c   2007-08-07 18:38:25.000000000 +0200
20 @@ -0,0 +1,340 @@
21 +/*
22 + * netfilter module to limit the number of parallel tcp
23 + * connections per IP address.
24 + *   (c) 2000 Gerd Knorr <kraxel@bytesex.org>
25 + *   Nov 2002: Martin Bene <martin.bene@icomedias.com>:
26 + *             only ignore TIME_WAIT or gone connections
27 + *
28 + * based on ...
29 + *
30 + * Kernel module to match connection tracking information.
31 + * GPL (C) 1999  Rusty Russell (rusty@rustcorp.com.au).
32 + */
33 +#include <linux/module.h>
34 +#include <linux/skbuff.h>
35 +#include <linux/version.h>
36 +#include <linux/list.h>
37 +
38 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
39 +#define CONFIG_NF_CONNTRACK_SUPPORT
40 +#endif
41 +
42 +#ifdef CONFIG_NF_CONNTRACK_SUPPORT
43 +#include <net/netfilter/nf_conntrack.h>
44 +#include <net/netfilter/nf_conntrack_core.h>
45 +#include <linux/netfilter/nf_conntrack_tcp.h>
46 +#else
47 +#include <linux/netfilter_ipv4/ip_conntrack.h>
48 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
49 +#include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
50 +#endif
51 +
52 +#include <linux/netfilter_ipv4/ip_tables.h>
53 +#include <linux/netfilter_ipv4/ipt_connlimit.h>
54 +
55 +#define DEBUG 0
56 +
57 +MODULE_LICENSE("GPL");
58 +
59 +/* we'll save the tuples of all connections we care about */
60 +struct ipt_connlimit_conn
61 +{
62 +        struct list_head list;
63 +#ifndef CONFIG_NF_CONNTRACK_SUPPORT
64 +       struct ip_conntrack_tuple tuple;
65 +#else
66 +       struct nf_conntrack_tuple tuple;
67 +#endif
68 +};
69 +
70 +struct ipt_connlimit_data {
71 +       spinlock_t lock;
72 +       struct list_head iphash[256];
73 +};
74 +
75 +static inline unsigned ipt_iphash(const unsigned addr)
76 +{
77 +       return ((addr ^ (addr >> 8) ^ (addr >> 16) ^ (addr >> 24)) & 0xff);
78 +}
79 +
80 +static int count_them(struct ipt_connlimit_data *data,
81 +                     u_int32_t addr, u_int32_t mask,
82 +#ifndef CONFIG_NF_CONNTRACK_SUPPORT
83 +                     struct ip_conntrack *ct)
84 +#else
85 +                     struct nf_conn *ct)
86 +#endif
87 +
88 +{
89 +#if DEBUG
90 +       const static char *tcp[] = { "none", "established", "syn_sent", "syn_recv",
91 +                                    "fin_wait", "time_wait", "close", "close_wait",
92 +                                    "last_ack", "listen" };
93 +#endif
94 +       int addit = 1, matches = 0;
95 +#ifndef CONFIG_NF_CONNTRACK_SUPPORT
96 +       struct ip_conntrack_tuple tuple;
97 +       struct ip_conntrack_tuple_hash *found;
98 +#else
99 +       struct nf_conntrack_tuple tuple;
100 +       struct nf_conntrack_tuple_hash *found;
101 +#endif
102 +       struct ipt_connlimit_conn *conn;
103 +       struct list_head *hash,*lh;
104 +
105 +       spin_lock_bh(&data->lock);
106 +       tuple = ct->tuplehash[0].tuple;
107 +       hash = &data->iphash[ipt_iphash(addr & mask)];
108 +
109 +       /* check the saved connections */
110 +       for (lh = hash->next; lh != hash; lh = lh->next) {
111 +#ifndef CONFIG_NF_CONNTRACK_SUPPORT
112 +               struct ip_conntrack *found_ct = NULL;
113 +               conn = list_entry(lh, struct ipt_connlimit_conn, list);
114 +               found = ip_conntrack_find_get(&conn->tuple, ct);
115 +#else
116 +               struct nf_conn *found_ct = NULL;
117 +               conn = list_entry(lh, struct ipt_connlimit_conn, list);
118 +               found = nf_conntrack_find_get(&conn->tuple, ct);
119 +#endif
120 +
121 +                if (found != NULL 
122 +#ifndef CONFIG_NF_CONNTRACK_SUPPORT
123 +                    && (found_ct = tuplehash_to_ctrack(found)) != NULL
124 +#else
125 +                    && (found_ct = nf_ct_tuplehash_to_ctrack(found)) != NULL
126 +#endif
127 +                    && 0 == memcmp(&conn->tuple,&tuple,sizeof(tuple)) 
128 +                    && found_ct->proto.tcp.state != TCP_CONNTRACK_TIME_WAIT) {
129 +                       /* Just to be sure we have it only once in the list.
130 +                          We should'nt see tuples twice unless someone hooks this
131 +                          into a table without "-p tcp --syn" */
132 +                       addit = 0;
133 +               }
134 +#if DEBUG
135 +               printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d %s\n",
136 +                      ipt_iphash(addr & mask),
137 +#ifndef CONFIG_NF_CONNTRACK_SUPPORT
138 +                      NIPQUAD(conn->tuple.src.ip), ntohs(conn->tuple.src.u.tcp.port),
139 +                      NIPQUAD(conn->tuple.dst.ip), ntohs(conn->tuple.dst.u.tcp.port),
140 +#else
141 +                      NIPQUAD(conn->tuple.src.u3.ip), ntohs(conn->tuple.src.u.tcp.port),
142 +                      NIPQUAD(conn->tuple.dst.u3.ip), ntohs(conn->tuple.dst.u.tcp.port),
143 +#endif
144 +                      (NULL != found) ? tcp[found_ct->proto.tcp.state] : "gone");
145 +#endif
146 +               if (NULL == found) {
147 +                       /* this one is gone */
148 +                       lh = lh->prev;
149 +                       list_del(lh->next);
150 +                       kfree(conn);
151 +                       continue;
152 +               }
153 +               if (found_ct->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT) {
154 +                       /* we don't care about connections which are
155 +                          closed already -> ditch it */
156 +                       lh = lh->prev;
157 +                       list_del(lh->next);
158 +                       kfree(conn);
159 +                       nf_conntrack_put(&found_ct->ct_general);
160 +                       continue;
161 +               }
162 +#ifndef CONFIG_NF_CONNTRACK_SUPPORT
163 +               if ((addr & mask) == (conn->tuple.src.ip & mask)) {
164 +#else
165 +               if ((addr & mask) == (conn->tuple.src.u3.ip & mask)) {
166 +#endif
167 +                       /* same source IP address -> be counted! */
168 +                       matches++;
169 +               }
170 +               nf_conntrack_put(&found_ct->ct_general);
171 +       }
172 +       if (addit) {
173 +               /* save the new connection in our list */
174 +#if DEBUG
175 +               printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d new\n",
176 +                      ipt_iphash(addr & mask),
177 +#ifndef CONFIG_NF_CONNTRACK_SUPPORT
178 +                      NIPQUAD(tuple.src.ip), ntohs(tuple.src.u.tcp.port),
179 +                      NIPQUAD(tuple.dst.ip), ntohs(tuple.dst.u.tcp.port));
180 +#else
181 +                      NIPQUAD(tuple.src.u3.ip), ntohs(tuple.src.u.tcp.port),
182 +                      NIPQUAD(tuple.dst.u3.ip), ntohs(tuple.dst.u.tcp.port));
183 +#endif
184 +
185 +#endif
186 +               conn = kmalloc(sizeof(*conn),GFP_ATOMIC);
187 +               if (NULL == conn) {
188 +                       spin_unlock_bh(&data->lock);
189 +                       return -1;
190 +               }
191 +               memset(conn,0,sizeof(*conn));
192 +               INIT_LIST_HEAD(&conn->list);
193 +               conn->tuple = tuple;
194 +               list_add(&conn->list,hash);
195 +               matches++;
196 +       }
197 +       spin_unlock_bh(&data->lock);
198 +       return matches;
199 +}
200 +
201 +static int
202 +match(const struct sk_buff *skb,
203 +      const struct net_device *in,
204 +      const struct net_device *out,
205 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
206 +      const struct xt_match *match,
207 +#endif
208 +      const void *matchinfo,
209 +      int offset,
210 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
211 +      unsigned int protoff,
212 +#endif
213 +      int *hotdrop)
214 +{
215 +       const struct ipt_connlimit_info *info = matchinfo;
216 +       int connections, rv;
217 +#ifndef CONFIG_NF_CONNTRACK_SUPPORT
218 +       struct ip_conntrack *ct;
219 +       enum ip_conntrack_info ctinfo;
220 +
221 +       ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
222 +#else
223 +       struct nf_conn *ct;
224 +       enum ip_conntrack_info ctinfo;
225 +
226 +       ct = nf_ct_get((struct sk_buff *)skb, &ctinfo);
227 +#endif
228 +       if (NULL == ct) {
229 +               printk("ipt_connlimit: Oops: invalid ct state ?\n");
230 +               *hotdrop = 1;
231 +               return 0;
232 +       }
233 +
234 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
235 +       connections = count_them(info->data, ip_hdr(skb)->saddr, info->mask, ct);
236 +#else
237 +       connections = count_them(info->data, skb->nh.iph->saddr, info->mask, ct);
238 +#endif
239 +       if (-1 == connections) {
240 +               printk("ipt_connlimit: Hmm, kmalloc failed :-(\n");
241 +               *hotdrop = 1; /* let's free some memory :-) */
242 +               return 0;
243 +       }
244 +        rv = (info->inverse) ? (connections <= info->limit) : (connections > info->limit);
245 +#if DEBUG
246 +       printk("ipt_connlimit: src=%u.%u.%u.%u mask=%u.%u.%u.%u "
247 +              "connections=%d limit=%d match=%s\n",
248 +              NIPQUAD(skb->nh.iph->saddr), NIPQUAD(info->mask),
249 +              connections, info->limit, rv?"yes":"no");
250 +#endif
251 +
252 +       return rv;
253 +}
254 +
255 +static int checkentry(const char *tablename,
256 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
257 +                const void *ip_void,
258 +#else
259 +                const struct ipt_ip *ip,
260 +#endif
261 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
262 +                const struct xt_match *match,
263 +#endif
264 +                void *matchinfo,
265 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
266 +                unsigned int matchsize,
267 +#endif
268 +                unsigned int hook_mask)
269 +{
270 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
271 +       const struct ipt_ip *ip = ip_void;
272 +#endif
273 +
274 +       struct ipt_connlimit_info *info = matchinfo;
275 +       int i;
276 +
277 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
278 +       /* verify size */
279 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_connlimit_info)))
280 +               return 0;
281 +#endif
282 +
283 +       /* refuse anything but tcp */
284 +       if (ip->proto != IPPROTO_TCP)
285 +               return 0;
286 +
287 +       /* init private data */
288 +       info->data = kmalloc(sizeof(struct ipt_connlimit_data),GFP_KERNEL);
289 +       spin_lock_init(&(info->data->lock));
290 +       for (i = 0; i < 256; i++)
291 +               INIT_LIST_HEAD(&(info->data->iphash[i]));
292 +       
293 +       return 1;
294 +}
295 +
296 +static void destroy(
297 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
298 +                   const struct xt_match *match,
299 +#endif
300 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
301 +                   void *matchinfo, unsigned int matchsize)
302 +#else
303 +                   void *matchinfo)
304 +#endif
305 +{
306 +       struct ipt_connlimit_info *info = matchinfo;
307 +       struct ipt_connlimit_conn *conn;
308 +       struct list_head *hash;
309 +       int i;
310 +
311 +       /* cleanup */
312 +       for (i = 0; i < 256; i++) {
313 +               hash = &(info->data->iphash[i]);
314 +               while (hash != hash->next) {
315 +                       conn = list_entry(hash->next,struct ipt_connlimit_conn,list);
316 +                       list_del(hash->next);
317 +                       kfree(conn);
318 +               }
319 +       }
320 +       kfree(info->data);
321 +}
322 +
323 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
324 +static struct xt_match connlimit_match = {
325 +#else
326 +static struct ipt_match connlimit_match = { 
327 +#endif
328 +       .name           = "connlimit",
329 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
330 +       .family         = AF_INET,
331 +#endif
332 +       .match          = &match,
333 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
334 +       .matchsize      = sizeof(struct ipt_connlimit_info),
335 +#endif
336 +       .checkentry     = &checkentry,
337 +       .destroy        = &destroy,
338 +       .me             = THIS_MODULE
339 +};
340 +
341 +static int __init init(void)
342 +{
343 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
344 +       return xt_register_match(&connlimit_match);
345 +#else
346 +       return ipt_register_match(&connlimit_match);
347 +#endif
348 +}
349 +
350 +static void __exit fini(void)
351 +{
352 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
353 +       xt_unregister_match(&connlimit_match);
354 +#else
355 +       ipt_unregister_match(&connlimit_match);
356 +#endif
357 +}
358 +
359 +module_init(init);
360 +module_exit(fini);
361 diff -Nru linux-2.6.22/net/ipv4/netfilter/Kconfig linux-2.6.22-pom2patch/net/ipv4/netfilter/Kconfig
362 --- linux-2.6.22/net/ipv4/netfilter/Kconfig     2007-07-09 01:32:17.000000000 +0200
363 +++ linux-2.6.22-pom2patch/net/ipv4/netfilter/Kconfig   2007-08-07 18:38:25.000000000 +0200
364 @@ -402,5 +402,15 @@
365           Allows altering the ARP packet payload: source and destination
366           hardware and network addresses.
367  
368 +config IP_NF_MATCH_CONNLIMIT
369 +       tristate  'Connections/IP limit match support'
370 +       depends on IP_NF_IPTABLES
371 +       help
372 +         This match allows you to restrict the number of parallel TCP
373 +         connections to a server per client IP address (or address block).
374 +       
375 +         If you want to compile it as a module, say M here and read
376 +         Documentation/modules.txt.  If unsure, say `N'.
377 +
378  endmenu
379  
380 diff -Nru linux-2.6.22/net/ipv4/netfilter/Makefile linux-2.6.22-pom2patch/net/ipv4/netfilter/Makefile
381 --- linux-2.6.22/net/ipv4/netfilter/Makefile    2007-07-09 01:32:17.000000000 +0200
382 +++ linux-2.6.22-pom2patch/net/ipv4/netfilter/Makefile  2007-08-07 18:38:25.000000000 +0200
383 @@ -44,6 +44,7 @@
384  obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
385  
386  obj-$(CONFIG_IP_NF_MATCH_IPV4OPTIONS) += ipt_ipv4options.o
387 +obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
388  
389  obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
390  obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
This page took 0.058332 seconds and 3 git commands to generate.