finally move buildroot-ng to trunk
[openwrt.git] / target / linux / generic-2.4 / patches / 610-netfilter_connbytes.patch
1 --- linux/net/ipv4/netfilter/Config.in.org      2005-11-13 15:53:59.457222512 +0100
2 +++ linux/net/ipv4/netfilter/Config.in  2005-11-13 15:56:25.241060000 +0100
3 @@ -11,6 +11,8 @@
4    dep_tristate '  Amanda protocol support' CONFIG_IP_NF_AMANDA $CONFIG_IP_NF_CONNTRACK
5    dep_tristate '  TFTP protocol support' CONFIG_IP_NF_TFTP $CONFIG_IP_NF_CONNTRACK
6    dep_tristate '  IRC protocol support' CONFIG_IP_NF_IRC $CONFIG_IP_NF_CONNTRACK
7 +  dep_tristate '  Connection tracking flow accounting' CONFIG_IP_NF_CT_ACCT $CONFIG_IP_NF_CONNTRACK
8 +  dep_tristate '  Connection byte counter support' CONFIG_IP_NF_MATCH_CONNBYTES $CONFIG_IP_NF_CT_ACCT $CONFIG_IP_NF_CONNTRACK $CONFIG_IP_NF_IPTABLES
9    dep_tristate '  GRE protocol support' CONFIG_IP_NF_CT_PROTO_GRE $CONFIG_IP_NF_CONNTRACK
10    dep_tristate '   PPTP protocol support' CONFIG_IP_NF_PPTP $CONFIG_IP_NF_CT_PROTO_GRE
11  fi
12 --- linux/net/ipv4/netfilter/Makefile.org       2005-11-12 16:48:38.000000000 +0100
13 +++ linux/net/ipv4/netfilter/Makefile   2005-11-13 15:56:38.663019552 +0100
14 @@ -94,6 +94,7 @@
15  obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
16  obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
17  obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
18 +obj-$(CONFIG_IP_NF_MATCH_CONNBYTES) += ipt_connbytes.o
19  obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
20  obj-$(CONFIG_IP_NF_MATCH_UNCLEAN) += ipt_unclean.o
21  obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
22 --- linux/net/ipv4/netfilter/ip_conntrack_amanda.c.org  2004-02-18 14:36:32.000000000 +0100
23 +++ linux/net/ipv4/netfilter/ip_conntrack_amanda.c      2005-11-13 15:40:00.000000000 +0100
24 @@ -75,7 +75,7 @@
25  
26         /* increase the UDP timeout of the master connection as replies from
27          * Amanda clients to the server can be quite delayed */
28 -       ip_ct_refresh(ct, master_timeout * HZ);
29 +       ip_ct_refresh_acct(ct,ctinfo,NULL, master_timeout * HZ);
30         
31         /* Search for "CONNECT " string */
32         do {
33 --- linux/net/ipv4/netfilter/ip_conntrack_proto_tcp.c.org       2003-11-28 19:26:21.000000000 +0100
34 +++ linux/net/ipv4/netfilter/ip_conntrack_proto_tcp.c   2005-11-13 15:45:41.045992536 +0100
35 @@ -211,7 +211,7 @@
36                         set_bit(IPS_ASSURED_BIT, &conntrack->status);
37  
38                 WRITE_UNLOCK(&tcp_lock);
39 -               ip_ct_refresh(conntrack, *tcp_timeouts[newconntrack]);
40 +               ip_ct_refresh_acct(conntrack,ctinfo,iph, *tcp_timeouts[newconntrack]);
41         }
42  
43         return NF_ACCEPT;
44 --- linux/net/ipv4/netfilter/ip_conntrack_proto_udp.c.org       2003-11-28 19:26:21.000000000 +0100
45 +++ linux/net/ipv4/netfilter/ip_conntrack_proto_udp.c   2005-11-13 15:47:38.348159896 +0100
46 @@ -47,16 +47,16 @@
47  /* Returns verdict for packet, and may modify conntracktype */
48  static int udp_packet(struct ip_conntrack *conntrack,
49                       struct iphdr *iph, size_t len,
50 -                     enum ip_conntrack_info conntrackinfo)
51 +                     enum ip_conntrack_info ctinfo)
52  {
53         /* If we've seen traffic both ways, this is some kind of UDP
54            stream.  Extend timeout. */
55         if (test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)) {
56 -               ip_ct_refresh(conntrack, ip_ct_udp_timeout_stream);
57 +               ip_ct_refresh_acct(conntrack,ctinfo,iph,ip_ct_udp_timeout_stream);
58                 /* Also, more likely to be important, and not a probe */
59                 set_bit(IPS_ASSURED_BIT, &conntrack->status);
60         } else
61 -               ip_ct_refresh(conntrack, ip_ct_udp_timeout);
62 +               ip_ct_refresh_acct(conntrack,ctinfo,iph, ip_ct_udp_timeout);
63  
64         return NF_ACCEPT;
65  }
66 --- linux/net/ipv4/netfilter/ip_conntrack_standalone.c.org      2005-11-12 16:48:38.000000000 +0100
67 +++ linux/net/ipv4/netfilter/ip_conntrack_standalone.c  2005-11-13 15:51:07.608347512 +0100
68 @@ -79,6 +79,18 @@
69         return len;
70  }
71  
72 +#if defined(CONFIG_IP_NF_CT_ACCT) || \
73 +       defined(CONFIG_IP_NF_CT_ACCT_MODULE)
74 +static unsigned int
75 +print_counters(char *buffer, struct ip_conntrack_counter *counter)
76 +{
77 +       return sprintf(buffer, "packets=%llu bytes=%llu ", 
78 +                       counter->packets, counter->bytes);
79 +}
80 +#else
81 +#define print_counters(x, y)   0
82 +#endif
83 +
84  static unsigned int
85  print_conntrack(char *buffer, struct ip_conntrack *conntrack)
86  {
87 @@ -98,11 +110,15 @@
88         len += print_tuple(buffer + len,
89                            &conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
90                            proto);
91 +        len += print_counters(buffer + len, 
92 +                           &conntrack->counters[IP_CT_DIR_ORIGINAL]);
93         if (!(test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)))
94                 len += sprintf(buffer + len, "[UNREPLIED] ");
95         len += print_tuple(buffer + len,
96                            &conntrack->tuplehash[IP_CT_DIR_REPLY].tuple,
97                            proto);
98 +        len += print_counters(buffer + len, 
99 +                           &conntrack->counters[IP_CT_DIR_REPLY]);
100         if (test_bit(IPS_ASSURED_BIT, &conntrack->status))
101                 len += sprintf(buffer + len, "[ASSURED] ");
102         len += sprintf(buffer + len, "use=%u ",
103 @@ -478,7 +494,7 @@
104  EXPORT_SYMBOL(ip_conntrack_helper_register);
105  EXPORT_SYMBOL(ip_conntrack_helper_unregister);
106  EXPORT_SYMBOL(ip_ct_iterate_cleanup);
107 -EXPORT_SYMBOL(ip_ct_refresh);
108 +EXPORT_SYMBOL(ip_ct_refresh_acct);
109  EXPORT_SYMBOL(ip_ct_find_proto);
110  EXPORT_SYMBOL(__ip_ct_find_proto);
111  EXPORT_SYMBOL(ip_ct_find_helper);
112 --- linux/net/ipv4/netfilter/ip_conntrack_proto_generic.c.org   2003-11-28 19:26:21.000000000 +0100
113 +++ linux/net/ipv4/netfilter/ip_conntrack_proto_generic.c       2005-11-13 15:44:20.734201784 +0100
114 @@ -41,9 +41,9 @@
115  /* Returns verdict for packet, or -1 for invalid. */
116  static int established(struct ip_conntrack *conntrack,
117                        struct iphdr *iph, size_t len,
118 -                      enum ip_conntrack_info conntrackinfo)
119 +                      enum ip_conntrack_info ctinfo)
120  {
121 -       ip_ct_refresh(conntrack, ip_ct_generic_timeout);
122 +       ip_ct_refresh_acct(conntrack, ctinfo,iph,ip_ct_generic_timeout);
123         return NF_ACCEPT;
124  }
125  
126 --- linux/net/ipv4/netfilter/ip_conntrack_proto_icmp.c.org      2003-11-28 19:26:21.000000000 +0100
127 +++ linux/net/ipv4/netfilter/ip_conntrack_proto_icmp.c  2005-11-13 15:44:50.733641176 +0100
128 @@ -82,7 +82,7 @@
129                         ct->timeout.function((unsigned long)ct);
130         } else {
131                 atomic_inc(&ct->proto.icmp.count);
132 -               ip_ct_refresh(ct, ip_ct_icmp_timeout);
133 +               ip_ct_refresh_acct(ct,ctinfo,iph, ip_ct_icmp_timeout);
134         }
135  
136         return NF_ACCEPT;
137 --- linux/net/ipv4/netfilter/ip_conntrack_core.c.org    2005-11-12 16:48:38.000000000 +0100
138 +++ linux/net/ipv4/netfilter/ip_conntrack_core.c        2005-11-13 15:43:23.882844504 +0100
139 @@ -1196,22 +1196,40 @@
140  
141         MOD_DEC_USE_COUNT;
142  }
143 +static inline void ct_add_counters(struct ip_conntrack *ct,
144 +                                enum ip_conntrack_info ctinfo,
145 +                                 const struct iphdr *iph)
146 +{
147 +#if defined(CONFIG_IP_NF_CT_ACCT) || \
148 +       defined(CONFIG_IP_NF_CT_ACCT_MODULE)
149 +     if (iph) {
150 +            ct->counters[CTINFO2DIR(ctinfo)].packets++;
151 +            ct->counters[CTINFO2DIR(ctinfo)].bytes += 
152 +                                ntohs(iph->tot_len);
153 +   }
154 +#endif
155 +}
156  
157  /* Refresh conntrack for this many jiffies. */
158 -void ip_ct_refresh(struct ip_conntrack *ct, unsigned long extra_jiffies)
159 +void ip_ct_refresh_acct(struct ip_conntrack *ct, 
160 +                       enum ip_conntrack_info ctinfo,
161 +                       const struct iphdr *iph,
162 +                       unsigned long extra_jiffies)
163  {
164         IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct);
165  
166         WRITE_LOCK(&ip_conntrack_lock);
167         /* If not in hash table, timer will not be active yet */
168 -       if (!is_confirmed(ct))
169 +       if (!is_confirmed(ct)) {
170                 ct->timeout.expires = extra_jiffies;
171 -       else {
172 +               ct_add_counters(ct, ctinfo,iph);
173 +       } else {
174                 /* Need del_timer for race avoidance (may already be dying). */
175                 if (del_timer(&ct->timeout)) {
176                         ct->timeout.expires = jiffies + extra_jiffies;
177                         add_timer(&ct->timeout);
178                 }
179 +               ct_add_counters(ct, ctinfo, iph);
180         }
181         WRITE_UNLOCK(&ip_conntrack_lock);
182  }
183 --- linux/include/linux/netfilter_ipv4/ip_conntrack.h.org       2005-11-12 16:48:38.000000000 +0100
184 +++ linux/include/linux/netfilter_ipv4/ip_conntrack.h   2005-11-13 15:39:04.000000000 +0100
185 @@ -164,6 +164,12 @@
186         union ip_conntrack_expect_help help;
187  };
188  
189 +struct ip_conntrack_counter
190 +{
191 +       u_int64_t packets;
192 +       u_int64_t bytes;
193 +};
194 +
195  struct ip_conntrack_helper;
196  
197  struct ip_conntrack
198 @@ -181,6 +187,12 @@
199         /* Timer function; drops refcnt when it goes off. */
200         struct timer_list timeout;
201  
202 +#if defined(CONFIG_IP_NF_CT_ACCT) || \
203 +       defined(CONFIG_IP_NF_CT_ACCT_MODULE)
204 +       /* Accounting Information (same cache line as other written members) */
205 +       struct ip_conntrack_counter counters[IP_CT_DIR_MAX];
206 +#endif
207 +
208         /* If we're expecting another related connection, this will be
209             in expected linked list */
210         struct list_head sibling_list;
211 @@ -264,8 +276,10 @@
212                           const struct ip_conntrack_tuple *orig);
213  
214  /* Refresh conntrack for this many jiffies */
215 -extern void ip_ct_refresh(struct ip_conntrack *ct,
216 -                         unsigned long extra_jiffies);
217 +extern void ip_ct_refresh_acct(struct ip_conntrack *ct,
218 +                              enum ip_conntrack_info ctinfo,
219 +                              const struct iphdr *iph,
220 +                              unsigned long extra_jiffies);
221  
222  /* These are for NAT.  Icky. */
223  /* Call me when a conntrack is destroyed. */
224 --- linux/net/ipv4/netfilter/ipt_connbytes.c.org        1970-01-01 01:00:00.000000000 +0100
225 +++ linux/net/ipv4/netfilter/ipt_connbytes.c    2005-11-13 16:22:02.021433872 +0100
226 @@ -0,0 +1,163 @@
227 +/* Kernel module to match connection tracking byte counter.
228 + * GPL (C) 2002 Martin Devera (devik@cdi.cz).
229 + *
230 + * 2004-07-20 Harald Welte <laforge at netfilter.org>
231 + *      - reimplemented to use per-connection accounting counters
232 + *      - add functionality to match number of packets
233 + *      - add functionality to match average packet size
234 + *      - add support to match directions seperately
235 + *
236 + * 2004-10-24 Piotr Chytla <pch at fouk.org>
237 + *     - Connbytes with per-connection accouting backported to 2.4
238 + *     
239 + */
240 +
241 +#include <linux/module.h>
242 +#include <linux/skbuff.h>
243 +#include <linux/types.h>
244 +#include <linux/netfilter_ipv4/ip_conntrack.h>
245 +#include <linux/netfilter_ipv4/ip_tables.h>
246 +#include <linux/netfilter_ipv4/ipt_connbytes.h>
247 +
248 +#include <asm/div64.h>
249 +
250 +static u_int64_t mydiv(u_int64_t arg1,u_int32_t arg2)
251 +{
252 +       do_div(arg1,arg2);
253 +       return arg1;
254 +}
255 +
256 +static int
257 +match(const struct sk_buff *skb,
258 +      const struct net_device *in,
259 +      const struct net_device *out,
260 +      const void *matchinfo,
261 +      int offset,
262 +      const void *hdr,
263 +      u_int16_t datalen,
264 +      int *hotdrop)
265 +{
266 +       static u_int64_t what;
267 +       const struct ipt_connbytes_info *sinfo = matchinfo;
268 +       enum ip_conntrack_info ctinfo;
269 +       struct ip_conntrack *ct;
270 +
271 +       if (!(ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo)))
272 +               return 0; /* no match */
273 +        switch (sinfo->what) {
274 +        case IPT_CONNBYTES_PKTS:
275 +                switch (sinfo->direction) {
276 +                case IPT_CONNBYTES_DIR_ORIGINAL:
277 +                        what = ct->counters[IP_CT_DIR_ORIGINAL].packets;
278 +                        break;
279 +                case IPT_CONNBYTES_DIR_REPLY:
280 +                        what = ct->counters[IP_CT_DIR_REPLY].packets;
281 +                       break;
282 +                case IPT_CONNBYTES_DIR_BOTH:
283 +                        what = ct->counters[IP_CT_DIR_ORIGINAL].packets;
284 +                        what += ct->counters[IP_CT_DIR_REPLY].packets;
285 +                        break;
286 +                }
287 +               break;
288 +        case IPT_CONNBYTES_BYTES:
289 +                switch (sinfo->direction) {
290 +                case IPT_CONNBYTES_DIR_ORIGINAL:
291 +                        what = ct->counters[IP_CT_DIR_ORIGINAL].bytes;
292 +                        break;
293 +                case IPT_CONNBYTES_DIR_REPLY:
294 +                        what = ct->counters[IP_CT_DIR_REPLY].bytes;
295 +                        break;
296 +                case IPT_CONNBYTES_DIR_BOTH:
297 +                        what = ct->counters[IP_CT_DIR_ORIGINAL].bytes;
298 +                        what += ct->counters[IP_CT_DIR_REPLY].bytes;
299 +                        break;
300 +                }
301 +                break;
302 +        case IPT_CONNBYTES_AVGPKT:
303 +                switch (sinfo->direction) {
304 +                case IPT_CONNBYTES_DIR_ORIGINAL:
305 +                        {
306 +                                u_int32_t pkts32;
307 +
308 +                                if (ct->counters[IP_CT_DIR_ORIGINAL].packets > 0xfffffffff)
309 +                                        pkts32 = 0xffffffff;
310 +                                else
311 +                                        pkts32 = ct->counters[IP_CT_DIR_ORIGINAL].packets;
312 +                               what = mydiv(ct->counters[IP_CT_DIR_ORIGINAL].bytes,pkts32);
313 +                        }
314 +                        break;
315 +                case IPT_CONNBYTES_DIR_REPLY:
316 +                        {
317 +                                u_int32_t pkts32;
318 +
319 +                                if (ct->counters[IP_CT_DIR_REPLY].packets > 0xffffffff)
320 +                                        pkts32 = 0xffffffff;
321 +                                else
322 +                                        pkts32 = ct->counters[IP_CT_DIR_REPLY].packets;
323 +                               what = mydiv(ct->counters[IP_CT_DIR_REPLY].bytes,pkts32);
324 +                        }
325 +                        break;
326 +                case IPT_CONNBYTES_DIR_BOTH:
327 +                        {
328 +                                u_int64_t bytes;
329 +                                u_int64_t pkts;
330 +                                u_int32_t pkts32;
331 +                                bytes = ct->counters[IP_CT_DIR_ORIGINAL].bytes +
332 +                                        ct->counters[IP_CT_DIR_REPLY].bytes;
333 +                                pkts = ct->counters[IP_CT_DIR_ORIGINAL].packets +
334 +                                        ct->counters[IP_CT_DIR_REPLY].packets;
335 +                                if (pkts > 0xffffffff)
336 +                                        pkts32 =  0xffffffff;
337 +                                else
338 +                                        pkts32 = pkts;
339 +                               what = mydiv(bytes,pkts);
340 +                        }
341 +                        break;
342 +                }
343 +                break;
344 +        }
345 +        if (sinfo->count.to)
346 +                return (what <= sinfo->count.to && what >= sinfo->count.from);
347 +        else
348 +                return (what >= sinfo->count.from);
349 +}
350 +
351 +static int check(const char *tablename,
352 +                const struct ipt_ip *ip,
353 +                void *matchinfo,
354 +                unsigned int matchsize,
355 +                unsigned int hook_mask)
356 +{
357 +       const struct ipt_connbytes_info *sinfo = matchinfo;
358 +
359 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_connbytes_info)))
360 +               return 0;
361 +        if (sinfo->what != IPT_CONNBYTES_PKTS &&
362 +                       sinfo->what != IPT_CONNBYTES_BYTES &&
363 +                       sinfo->what != IPT_CONNBYTES_AVGPKT)
364 +                       return 0;
365 +
366 +       if (sinfo->direction != IPT_CONNBYTES_DIR_ORIGINAL &&
367 +                       sinfo->direction != IPT_CONNBYTES_DIR_REPLY &&
368 +                       sinfo->direction != IPT_CONNBYTES_DIR_BOTH)
369 +                       return 0;
370 +
371 +       return 1;
372 +}
373 +
374 +static struct ipt_match state_match
375 += { { NULL, NULL }, "connbytes", &match, &check, NULL, THIS_MODULE };
376 +
377 +static int __init init(void)
378 +{
379 +       return ipt_register_match(&state_match);
380 +}
381 +
382 +static void __exit fini(void)
383 +{
384 +       ipt_unregister_match(&state_match);
385 +}
386 +
387 +module_init(init);
388 +module_exit(fini);
389 +MODULE_LICENSE("GPL");
390 --- linux/include/linux/netfilter_ipv4/ipt_connbytes.h.org      1970-01-01 01:00:00.000000000 +0100
391 +++ linux/include/linux/netfilter_ipv4/ipt_connbytes.h  2005-11-13 16:11:24.567341624 +0100
392 @@ -0,0 +1,25 @@
393 +#ifndef _IPT_CONNBYTES_H
394 +#define _IPT_CONNBYTES_H
395 +enum ipt_connbytes_what {
396 +               IPT_CONNBYTES_PKTS,
397 +               IPT_CONNBYTES_BYTES,
398 +               IPT_CONNBYTES_AVGPKT,
399 +};
400 +
401 +enum ipt_connbytes_direction {
402 +               IPT_CONNBYTES_DIR_ORIGINAL,
403 +               IPT_CONNBYTES_DIR_REPLY,
404 +               IPT_CONNBYTES_DIR_BOTH,
405 +};
406 +
407 +struct ipt_connbytes_info
408 +{
409 +        struct {
410 +                u_int64_t from; /* count to be matched */
411 +                u_int64_t to;   /* count to be matched */
412 +        } count;
413 +        u_int8_t what;          /* ipt_connbytes_what */
414 +        u_int8_t direction;     /* ipt_connbytes_direction */
415 +};
416 +
417 +#endif
418 --- linux-2.4.32/net/ipv4/netfilter/ip_conntrack_proto_gre.c    2006-02-04 19:16:25.000000000 +0100
419 +++ /home/florian//openwrt/trunk/openwrt/build_mipsel/linux/net/ipv4/netfilter/ip_conntrack_proto_gre.c 2006-02-04 18:19:08.000000000 +0100
420 @@ -237,16 +237,16 @@
421  /* Returns verdict for packet, and may modify conntrack */
422  static int gre_packet(struct ip_conntrack *ct,
423                       struct iphdr *iph, size_t len,
424 -                     enum ip_conntrack_info conntrackinfo)
425 +                     enum ip_conntrack_info ctinfo)
426  {
427         /* If we've seen traffic both ways, this is a GRE connection.
428          * Extend timeout. */
429         if (ct->status & IPS_SEEN_REPLY) {
430 -               ip_ct_refresh_acct(ct, ct->proto.gre.stream_timeout);
431 +               ip_ct_refresh_acct(ct, ctinfo, iph, ct->proto.gre.stream_timeout);
432                 /* Also, more likely to be important, and not a probe. */
433                 set_bit(IPS_ASSURED_BIT, &ct->status);
434         } else
435 -               ip_ct_refresh_acct(ct, ct->proto.gre.timeout);
436 +               ip_ct_refresh_acct(ct, ctinfo, iph, ct->proto.gre.timeout);
437         
438         return NF_ACCEPT;
439  }