]> git.pld-linux.org Git - packages/kernel.git/blob - pom-ng-connlimit-20060504.patch
- added LED devices support
[packages/kernel.git] / pom-ng-connlimit-20060504.patch
1  include/linux/netfilter_ipv4/ipt_connlimit.h |   12 +
2  net/ipv4/netfilter/Kconfig                   |   10 +
3  net/ipv4/netfilter/Makefile                  |    1 
4  net/ipv4/netfilter/ipt_connlimit.c           |  228 +++++++++++++++++++++++++++
5  4 files changed, 251 insertions(+)
6
7 diff -Nur --exclude '*.orig' linux.org/include/linux/netfilter_ipv4/ipt_connlimit.h linux/include/linux/netfilter_ipv4/ipt_connlimit.h
8 --- linux.org/include/linux/netfilter_ipv4/ipt_connlimit.h      1970-01-01 01:00:00.000000000 +0100
9 +++ linux/include/linux/netfilter_ipv4/ipt_connlimit.h  2006-05-04 10:02:23.000000000 +0200
10 @@ -0,0 +1,12 @@
11 +#ifndef _IPT_CONNLIMIT_H
12 +#define _IPT_CONNLIMIT_H
13 +
14 +struct ipt_connlimit_data;
15 +
16 +struct ipt_connlimit_info {
17 +       int limit;
18 +       int inverse;
19 +       u_int32_t mask;
20 +       struct ipt_connlimit_data *data;
21 +};
22 +#endif /* _IPT_CONNLIMIT_H */
23 diff -Nur --exclude '*.orig' linux.org/net/ipv4/netfilter/Kconfig linux/net/ipv4/netfilter/Kconfig
24 --- linux.org/net/ipv4/netfilter/Kconfig        2006-05-02 23:38:44.000000000 +0200
25 +++ linux/net/ipv4/netfilter/Kconfig    2006-05-04 10:02:23.000000000 +0200
26 @@ -606,5 +606,15 @@
27           Allows altering the ARP packet payload: source and destination
28           hardware and network addresses.
29  
30 +config IP_NF_MATCH_CONNLIMIT
31 +       tristate  'Connections/IP limit match support'
32 +       depends on IP_NF_IPTABLES
33 +       help
34 +         This match allows you to restrict the number of parallel TCP
35 +         connections to a server per client IP address (or address block).
36 +       
37 +         If you want to compile it as a module, say M here and read
38 +         Documentation/modules.txt.  If unsure, say `N'.
39 +
40  endmenu
41  
42 diff -Nur --exclude '*.orig' linux.org/net/ipv4/netfilter/Makefile linux/net/ipv4/netfilter/Makefile
43 --- linux.org/net/ipv4/netfilter/Makefile       2006-05-02 23:38:44.000000000 +0200
44 +++ linux/net/ipv4/netfilter/Makefile   2006-05-04 10:02:23.000000000 +0200
45 @@ -0,0 +0,1 @@
46 +obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
47 diff -Nur --exclude '*.orig' linux.org/net/ipv4/netfilter/ipt_connlimit.c linux/net/ipv4/netfilter/ipt_connlimit.c
48 --- linux.org/net/ipv4/netfilter/ipt_connlimit.c        1970-01-01 01:00:00.000000000 +0100
49 +++ linux/net/ipv4/netfilter/ipt_connlimit.c    2006-05-04 10:02:23.000000000 +0200
50 @@ -0,0 +1,229 @@
51 +/*
52 + * netfilter module to limit the number of parallel tcp
53 + * connections per IP address.
54 + *   (c) 2000 Gerd Knorr <kraxel@bytesex.org>
55 + *   Nov 2002: Martin Bene <martin.bene@icomedias.com>:
56 + *             only ignore TIME_WAIT or gone connections
57 + *
58 + * based on ...
59 + *
60 + * Kernel module to match connection tracking information.
61 + * GPL (C) 1999  Rusty Russell (rusty@rustcorp.com.au).
62 + */
63 +#include <linux/module.h>
64 +#include <linux/skbuff.h>
65 +#include <linux/list.h>
66 +#include <linux/netfilter_ipv4/ip_conntrack.h>
67 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
68 +#include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
69 +#include <linux/netfilter_ipv4/ip_tables.h>
70 +#include <linux/netfilter_ipv4/ipt_connlimit.h>
71 +
72 +#define DEBUG 0
73 +
74 +MODULE_LICENSE("GPL");
75 +
76 +/* we'll save the tuples of all connections we care about */
77 +struct ipt_connlimit_conn
78 +{
79 +        struct list_head list;
80 +       struct ip_conntrack_tuple tuple;
81 +};
82 +
83 +struct ipt_connlimit_data {
84 +       spinlock_t lock;
85 +       struct list_head iphash[256];
86 +};
87 +
88 +static inline unsigned ipt_iphash(const unsigned addr)
89 +{
90 +       return ((addr ^ (addr >> 8) ^ (addr >> 16) ^ (addr >> 24)) & 0xff);
91 +}
92 +
93 +static int count_them(struct ipt_connlimit_data *data,
94 +                     u_int32_t addr, u_int32_t mask,
95 +                     struct ip_conntrack *ct)
96 +{
97 +#if DEBUG
98 +       const static char *tcp[] = { "none", "established", "syn_sent", "syn_recv",
99 +                                    "fin_wait", "time_wait", "close", "close_wait",
100 +                                    "last_ack", "listen" };
101 +#endif
102 +       int addit = 1, matches = 0;
103 +       struct ip_conntrack_tuple tuple;
104 +       struct ip_conntrack_tuple_hash *found;
105 +       struct ipt_connlimit_conn *conn;
106 +       struct list_head *hash,*lh;
107 +
108 +       spin_lock_bh(&data->lock);
109 +       tuple = ct->tuplehash[0].tuple;
110 +       hash = &data->iphash[ipt_iphash(addr & mask)];
111 +
112 +       /* check the saved connections */
113 +       for (lh = hash->next; lh != hash; lh = lh->next) {
114 +               struct ip_conntrack *found_ct = NULL;
115 +               conn = list_entry(lh,struct ipt_connlimit_conn,list);
116 +               found = ip_conntrack_find_get(&conn->tuple,ct);
117 +                if (found != NULL 
118 +                    && (found_ct = tuplehash_to_ctrack(found)) != NULL
119 +                    && 0 == memcmp(&conn->tuple,&tuple,sizeof(tuple)) 
120 +                    && found_ct->proto.tcp.state != TCP_CONNTRACK_TIME_WAIT) {
121 +                       /* Just to be sure we have it only once in the list.
122 +                          We should'nt see tuples twice unless someone hooks this
123 +                          into a table without "-p tcp --syn" */
124 +                       addit = 0;
125 +               }
126 +#if DEBUG
127 +               printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d %s\n",
128 +                      ipt_iphash(addr & mask),
129 +                      NIPQUAD(conn->tuple.src.ip), ntohs(conn->tuple.src.u.tcp.port),
130 +                      NIPQUAD(conn->tuple.dst.ip), ntohs(conn->tuple.dst.u.tcp.port),
131 +                      (NULL != found) ? tcp[found_ct->proto.tcp.state] : "gone");
132 +#endif
133 +               if (NULL == found) {
134 +                       /* this one is gone */
135 +                       lh = lh->prev;
136 +                       list_del(lh->next);
137 +                       kfree(conn);
138 +                       continue;
139 +               }
140 +               if (found_ct->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT) {
141 +                       /* we don't care about connections which are
142 +                          closed already -> ditch it */
143 +                       lh = lh->prev;
144 +                       list_del(lh->next);
145 +                       kfree(conn);
146 +                       nf_conntrack_put(&found_ct->ct_general);
147 +                       continue;
148 +               }
149 +               if ((addr & mask) == (conn->tuple.src.ip & mask)) {
150 +                       /* same source IP address -> be counted! */
151 +                       matches++;
152 +               }
153 +               nf_conntrack_put(&found_ct->ct_general);
154 +       }
155 +       if (addit) {
156 +               /* save the new connection in our list */
157 +#if DEBUG
158 +               printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d new\n",
159 +                      ipt_iphash(addr & mask),
160 +                      NIPQUAD(tuple.src.ip), ntohs(tuple.src.u.tcp.port),
161 +                      NIPQUAD(tuple.dst.ip), ntohs(tuple.dst.u.tcp.port));
162 +#endif
163 +               conn = kmalloc(sizeof(*conn),GFP_ATOMIC);
164 +               if (NULL == conn) {
165 +                       spin_unlock_bh(&data->lock);
166 +                       return -1;
167 +               }
168 +               memset(conn,0,sizeof(*conn));
169 +               INIT_LIST_HEAD(&conn->list);
170 +               conn->tuple = tuple;
171 +               list_add(&conn->list,hash);
172 +               matches++;
173 +       }
174 +       spin_unlock_bh(&data->lock);
175 +       return matches;
176 +}
177 +
178 +static int
179 +match(const struct sk_buff *skb,
180 +      const struct net_device *in,
181 +      const struct net_device *out,
182 +      const void *matchinfo,
183 +      int offset,
184 +      unsigned int protoff,
185 +      int *hotdrop)
186 +{
187 +       const struct ipt_connlimit_info *info = matchinfo;
188 +       int connections, match;
189 +       struct ip_conntrack *ct;
190 +       enum ip_conntrack_info ctinfo;
191 +
192 +       ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
193 +       if (NULL == ct) {
194 +               printk("ipt_connlimit: Oops: invalid ct state ?\n");
195 +               *hotdrop = 1;
196 +               return 0;
197 +       }
198 +       connections = count_them(info->data,skb->nh.iph->saddr,info->mask,ct);
199 +       if (-1 == connections) {
200 +               printk("ipt_connlimit: Hmm, kmalloc failed :-(\n");
201 +               *hotdrop = 1; /* let's free some memory :-) */
202 +               return 0;
203 +       }
204 +        match = (info->inverse) ? (connections <= info->limit) : (connections > info->limit);
205 +#if DEBUG
206 +       printk("ipt_connlimit: src=%u.%u.%u.%u mask=%u.%u.%u.%u "
207 +              "connections=%d limit=%d match=%s\n",
208 +              NIPQUAD(skb->nh.iph->saddr), NIPQUAD(info->mask),
209 +              connections, info->limit, match ? "yes" : "no");
210 +#endif
211 +
212 +       return match;
213 +}
214 +
215 +static int check(const char *tablename,
216 +                const struct ipt_ip *ip,
217 +                void *matchinfo,
218 +                unsigned int matchsize,
219 +                unsigned int hook_mask)
220 +{
221 +       struct ipt_connlimit_info *info = matchinfo;
222 +       int i;
223 +
224 +       /* verify size */
225 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_connlimit_info)))
226 +               return 0;
227 +
228 +       /* refuse anything but tcp */
229 +       if (ip->proto != IPPROTO_TCP)
230 +               return 0;
231 +
232 +       /* init private data */
233 +       info->data = kmalloc(sizeof(struct ipt_connlimit_data),GFP_KERNEL);
234 +       spin_lock_init(&(info->data->lock));
235 +       for (i = 0; i < 256; i++)
236 +               INIT_LIST_HEAD(&(info->data->iphash[i]));
237 +       
238 +       return 1;
239 +}
240 +
241 +static void destroy(void *matchinfo, unsigned int matchinfosize)
242 +{
243 +       struct ipt_connlimit_info *info = matchinfo;
244 +       struct ipt_connlimit_conn *conn;
245 +       struct list_head *hash;
246 +       int i;
247 +
248 +       /* cleanup */
249 +       for (i = 0; i < 256; i++) {
250 +               hash = &(info->data->iphash[i]);
251 +               while (hash != hash->next) {
252 +                       conn = list_entry(hash->next,struct ipt_connlimit_conn,list);
253 +                       list_del(hash->next);
254 +                       kfree(conn);
255 +               }
256 +       }
257 +       kfree(info->data);
258 +}
259 +
260 +static struct ipt_match connlimit_match = { 
261 +       .name = "connlimit",
262 +       .match = &match,
263 +       .checkentry = &check,
264 +       .destroy = &destroy,
265 +       .me = THIS_MODULE
266 +};
267 +
268 +static int __init init(void)
269 +{
270 +       return ipt_register_match(&connlimit_match);
271 +}
272 +
273 +static void __exit fini(void)
274 +{
275 +       ipt_unregister_match(&connlimit_match);
276 +}
277 +
278 +module_init(init);
279 +module_exit(fini);
This page took 0.165419 seconds and 3 git commands to generate.