Root/target/linux/generic-2.4/patches/610-netfilter_connbytes.patch

1--- a/net/ipv4/netfilter/Config.in
2+++ b/net/ipv4/netfilter/Config.in
3@@ -11,6 +11,8 @@ if [ "$CONFIG_IP_NF_CONNTRACK" != "n" ];
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 fi
10 
11 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
12--- a/net/ipv4/netfilter/Makefile
13+++ b/net/ipv4/netfilter/Makefile
14@@ -85,6 +85,7 @@ obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_
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_STRING) += ipt_string.o
22--- a/net/ipv4/netfilter/ip_conntrack_amanda.c
23+++ b/net/ipv4/netfilter/ip_conntrack_amanda.c
24@@ -75,7 +75,7 @@ static int help(const struct iphdr *iph,
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--- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
34+++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
35@@ -211,7 +211,7 @@ static int tcp_packet(struct ip_conntrac
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--- a/net/ipv4/netfilter/ip_conntrack_proto_udp.c
45+++ b/net/ipv4/netfilter/ip_conntrack_proto_udp.c
46@@ -47,16 +47,16 @@ static unsigned int udp_print_conntrack(
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--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
67+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
68@@ -79,6 +79,18 @@ print_expect(char *buffer, const struct
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 @@ print_conntrack(char *buffer, struct ip_
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@@ -481,7 +497,7 @@ EXPORT_SYMBOL(ip_conntrack_get);
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--- a/net/ipv4/netfilter/ip_conntrack_proto_generic.c
113+++ b/net/ipv4/netfilter/ip_conntrack_proto_generic.c
114@@ -41,9 +41,9 @@ static unsigned int generic_print_conntr
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--- a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
127+++ b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
128@@ -82,7 +82,7 @@ static int icmp_packet(struct ip_conntra
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--- a/net/ipv4/netfilter/ip_conntrack_core.c
138+++ b/net/ipv4/netfilter/ip_conntrack_core.c
139@@ -1193,22 +1193,40 @@ void ip_conntrack_helper_unregister(stru
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--- a/include/linux/netfilter_ipv4/ip_conntrack.h
184+++ b/include/linux/netfilter_ipv4/ip_conntrack.h
185@@ -156,6 +156,12 @@ struct ip_conntrack_expect
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@@ -173,6 +179,12 @@ struct ip_conntrack
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@@ -256,8 +268,10 @@ extern int invert_tuplepr(struct ip_conn
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--- /dev/null
225+++ b/net/ipv4/netfilter/ipt_connbytes.c
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--- /dev/null
391+++ b/include/linux/netfilter_ipv4/ipt_connbytes.h
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

Archive Download this file



interactive