]> git.pld-linux.org Git - packages/kernel.git/blob - 2.6.6-ipt_account.patch
- obsolete
[packages/kernel.git] / 2.6.6-ipt_account.patch
1 diff -uNr linux-2.6.6/include.orig/linux/netfilter_ipv4/ipt_account.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_account.h
2 --- linux-2.6.6/include.orig/linux/netfilter_ipv4/ipt_account.h 1970-01-01 01:00:00.000000000 +0100
3 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_account.h      2004-05-22 15:29:38.813343664 +0200
4 @@ -0,0 +1,21 @@
5 +/* 
6 + * accounting match (ipt_account.c)
7 + * (C) 2003,2004 by Piotr Gasid³o (quaker@barbara.eu.org)
8 + *
9 + * Version: 0.1.5
10 + *
11 + * This software is distributed under the terms of GNU GPL
12 + */
13 +
14 +#ifndef _IPT_ACCOUNT_H_
15 +#define _IPT_ACCOUNT_H_
16 +
17 +#define IPT_ACCOUNT_NAME_LEN 64
18 +
19 +struct t_ipt_account_info {
20 +       char name[IPT_ACCOUNT_NAME_LEN];
21 +       u_int32_t network;
22 +       u_int32_t netmask;
23 +};
24 +
25 +#endif
26 diff -uNr linux-2.6.6/net/ipv4/netfilter.orig/ipt_account.c linux-2.6.6/net/ipv4/netfilter/ipt_account.c
27 --- linux-2.6.6/net/ipv4/netfilter.orig/ipt_account.c   1970-01-01 01:00:00.000000000 +0100
28 +++ linux-2.6.6/net/ipv4/netfilter/ipt_account.c        2004-05-22 15:29:38.819342752 +0200
29 @@ -0,0 +1,617 @@
30 +/* 
31 + * accounting match (ipt_account.c)
32 + * (C) 2003,2004 by Piotr Gasid³o (quaker@barbara.eu.org)
33 + *
34 + * Version: 0.1.5
35 + *
36 + * This software is distributed under the terms of GNU GPL
37 + */
38 +
39 +#include <linux/module.h>
40 +#include <linux/skbuff.h>
41 +#include <linux/proc_fs.h>
42 +#include <linux/spinlock.h>
43 +#include <linux/vmalloc.h>
44 +#include <linux/interrupt.h>
45 +
46 +#include <asm/uaccess.h>
47 +
48 +#include <linux/ip.h>
49 +#include <linux/tcp.h>
50 +#include <linux/udp.h>
51 +
52 +#include <linux/netfilter_ipv4/ip_tables.h>
53 +#include <linux/netfilter_ipv4/ipt_account.h>
54 +
55 +static char version[] =
56 +KERN_INFO "ipt_account 0.1.5 : Piotr Gasid³o <quaker@barbara.eu.org>, http://www.barbara.eu.org/~quaker/ipt_account/\n";
57 +
58 +/* default rights for files created in /proc/net/ipt_account/ */
59 +static int ip_list_perms = 0644;
60 +
61 +/* 
62 + * safe netmask, if you want account traffic for networks 
63 + * bigger that /17 you must specify ip_list_max_hosts parameter 
64 + * during load 
65 + */
66 +static int ip_list_max_mask = 17;
67 +static int ip_list_max_hosts_count;
68 +static int debug = 0;
69 +
70 +/* module information */
71 +MODULE_AUTHOR("Piotr Gasid³o <quaker@barbara.eu.org>");
72 +MODULE_DESCRIPTION("Traffic accounting modules");
73 +MODULE_LICENSE("GPL");
74 +MODULE_PARM(ip_list_perms,"i");
75 +MODULE_PARM_DESC(ip_list_perms,"permissions on /proc/net/ipt_account/* files");
76 +MODULE_PARM(ip_list_max_mask, "i");
77 +MODULE_PARM_DESC(ip_list_max_mask, "maximum *save* size of one list (netmask)");
78 +#ifdef DEBUG
79 +MODULE_PARM(debug,"i");
80 +MODULE_PARM_DESC(debug,"debugging level, defaults to 0");
81 +#endif
82 +
83 +/* structure with statistics counters */
84 +struct t_ipt_account_stat {
85 +       u_int64_t b_all, b_tcp, b_udp, b_icmp, b_other;         /* byte counters for all/tcp/udp/icmp/other traffic  */
86 +       u_int64_t p_all, p_tcp, p_udp, p_icmp, p_other;         /* packet counters for all/tcp/udp/icmp/other traffic */
87 +};
88
89 +/* structure holding to/from statistics for single ip */
90 +struct t_ipt_account_ip_list {
91 +       struct t_ipt_account_stat src;
92 +       struct t_ipt_account_stat dest;
93 +};
94 +
95 +/* structure describing single table */
96 +struct t_ipt_account_table {
97 +       char name[IPT_ACCOUNT_NAME_LEN];        /* table name ( = filename in /proc/net/ipt_account/) */
98 +       struct t_ipt_account_ip_list *ip_list;  /* table with statistics for each ip in network/netmask */
99 +       struct t_ipt_account_table *next;
100 +       u_int32_t network;                      /* network/netmask covered by table*/
101 +       u_int32_t netmask;                                      
102 +       int use_count;                          /* rules counter - counting number of rules using this table */
103 +       spinlock_t ip_list_lock;
104 +       struct proc_dir_entry *status_proc_64, *status_proc_32;
105 +};
106 +
107 +/* we must use spinlocks to avoid parallel modifications of table list */
108 +static spinlock_t ipt_account_tables_lock = SPIN_LOCK_UNLOCKED;
109 +
110 +static struct proc_dir_entry *proc_net_ipt_account = NULL;
111 +
112 +/* root pointer holding list of the tables */
113 +static struct t_ipt_account_table *ipt_account_tables = NULL;
114 +
115 +static int ip_list_read_proc_64(char *buffer, char **start, off_t offset,
116 +               int length, int *eof, void *data) {
117 +       
118 +       int len = 0, last_len = 0;
119 +       off_t pos = 0, begin = 0;
120 +
121 +       u_int32_t address, index;       
122 +
123 +       struct t_ipt_account_table *table = (struct t_ipt_account_table*)data;
124 +
125 +       spin_lock(&table->ip_list_lock);
126 +       for (address = table->network; (u_int32_t)(address & table->netmask) == (u_int32_t)(table->network); address++) {
127 +               last_len = len;         
128 +               index = address - table->network;
129 +                       len += sprintf(buffer + len,
130 +                               "ip = %u.%u.%u.%u bytes_src = %llu %llu %llu %llu %llu packets_src = %llu %llu %llu %llu %llu bytes_dest = %llu %llu %llu %llu %llu packets_dest = %llu %llu %llu %llu %llu\n",
131 +                               HIPQUAD(address),
132 +                               table->ip_list[index].src.b_all,
133 +                               table->ip_list[index].src.b_tcp,
134 +                               table->ip_list[index].src.b_udp,
135 +                               table->ip_list[index].src.b_icmp,
136 +                               table->ip_list[index].src.b_other,
137 +                               
138 +                               table->ip_list[index].src.p_all,
139 +                               table->ip_list[index].src.p_tcp,
140 +                               table->ip_list[index].src.p_udp,
141 +                               table->ip_list[index].src.p_icmp,
142 +                               table->ip_list[index].src.p_other,
143 +                               
144 +                               table->ip_list[index].dest.b_all,
145 +                               table->ip_list[index].dest.b_tcp,
146 +                               table->ip_list[index].dest.b_udp,
147 +                               table->ip_list[index].dest.b_icmp,
148 +                               table->ip_list[index].dest.b_other,                             
149 +                               
150 +                               table->ip_list[index].dest.p_all,
151 +                               table->ip_list[index].dest.p_tcp,
152 +                               table->ip_list[index].dest.p_udp,
153 +                               table->ip_list[index].dest.p_icmp,
154 +                               table->ip_list[index].dest.p_other
155 +                               );
156 +               pos = begin + len;
157 +               if (pos < offset) {
158 +                       len = 0;
159 +                       begin = pos;
160 +               }
161 +               if (pos > offset + length) {
162 +                       len = last_len;
163 +                       break;
164 +               }
165 +       }
166 +       spin_unlock(&table->ip_list_lock);
167 +       *start = buffer + (offset - begin);
168 +       len -= (offset - begin);
169 +       if (len > length)
170 +               len = length;
171 +       return len;
172 +}
173 +
174 +static int ip_list_read_proc_32(char *buffer, char **start, off_t offset,
175 +               int length, int *eof, void *data) {
176 +       
177 +       int len = 0, last_len = 0;
178 +       off_t pos = 0, begin = 0;
179 +
180 +       u_int32_t address, index;
181 +
182 +       struct t_ipt_account_table *table = (struct t_ipt_account_table*)data;
183 +       
184 +       spin_lock(&table->ip_list_lock);
185 +       for (address = table->network; (u_int32_t)(address & table->netmask) == (u_int32_t)(table->network); address++) {
186 +               last_len = len; 
187 +               index = address - table->network;
188 +               len += sprintf(buffer + len,
189 +                               "ip = %u.%u.%u.%u bytes_src = %u %u %u %u %u packets_src = %u %u %u %u %u bytes_dest = %u %u %u %u %u packets_dest = %u %u %u %u %u\n",
190 +                               HIPQUAD(address),
191 +                               (u_int32_t)table->ip_list[index].src.b_all,
192 +                               (u_int32_t)table->ip_list[index].src.b_tcp,
193 +                               (u_int32_t)table->ip_list[index].src.b_udp,
194 +                               (u_int32_t)table->ip_list[index].src.b_icmp,
195 +                               (u_int32_t)table->ip_list[index].src.b_other,
196 +                               
197 +                               (u_int32_t)table->ip_list[index].src.p_all,
198 +                               (u_int32_t)table->ip_list[index].src.p_tcp,
199 +                               (u_int32_t)table->ip_list[index].src.p_udp,
200 +                               (u_int32_t)table->ip_list[index].src.p_icmp,
201 +                               (u_int32_t)table->ip_list[index].src.p_other,
202 +                               
203 +                               (u_int32_t)table->ip_list[index].dest.b_all,
204 +                               (u_int32_t)table->ip_list[index].dest.b_tcp,
205 +                               (u_int32_t)table->ip_list[index].dest.b_udp,
206 +                               (u_int32_t)table->ip_list[index].dest.b_icmp,
207 +                               (u_int32_t)table->ip_list[index].dest.b_other,
208 +                               
209 +                               (u_int32_t)table->ip_list[index].dest.p_all,
210 +                               (u_int32_t)table->ip_list[index].dest.p_tcp,
211 +                               (u_int32_t)table->ip_list[index].dest.p_udp,
212 +                               (u_int32_t)table->ip_list[index].dest.p_icmp,
213 +                               (u_int32_t)table->ip_list[index].dest.p_other
214 +               
215 +                       );
216 +               pos = begin + len;
217 +               if (pos < offset) {
218 +                       len = 0;
219 +                       begin = pos;
220 +               }
221 +               if (pos > offset + length) {
222 +                       len = last_len;
223 +                       break;
224 +               }               
225 +       }
226 +       spin_unlock(&table->ip_list_lock);                              
227 +       *start = buffer + (offset - begin);
228 +       len -= (offset - begin);
229 +       if (len > length)
230 +               len = length;
231 +       return len;
232 +}
233 +
234 +static int ip_list_write_proc(struct file *file, const char *buffer, 
235 +               unsigned long length, void *data) {
236 +
237 +       int len = (length > 1024) ? length : 1024;
238 +       struct t_ipt_account_table *table = (struct t_ipt_account_table*)data;
239 +       char kernel_buffer[1024];
240 +       u_int32_t hosts_count = INADDR_BROADCAST - table->netmask + 1;
241 +       
242 +       copy_from_user(kernel_buffer, buffer, len);
243 +       kernel_buffer[len - 1] = 0;
244 +       
245 +       /* echo "reset" > /proc/net/ipt_recent/table clears the table */
246 +       if (!strncmp(kernel_buffer, "reset", len)) {
247 +               spin_lock(&table->ip_list_lock);
248 +               memset(table->ip_list, 0, sizeof(struct t_ipt_account_ip_list) * hosts_count);
249 +               spin_unlock(&table->ip_list_lock);
250 +       }
251 +       
252 +       return len;
253 +}
254 +
255 +/* do raw accounting */
256 +static void do_account(struct t_ipt_account_stat *stat, u_int8_t proto, u_int16_t pktlen) {
257 +       
258 +       /* update packet & bytes counters in *stat structure */
259 +       stat->b_all += pktlen;
260 +       stat->p_all++;
261 +       
262 +       switch (proto) {
263 +               case IPPROTO_TCP:
264 +                       stat->b_tcp += pktlen;
265 +                       stat->p_tcp++;
266 +                       break;
267 +               case IPPROTO_UDP:
268 +                       stat->b_udp += pktlen;
269 +                       stat->p_udp++;
270 +                       break;
271 +               case IPPROTO_ICMP:
272 +                       stat->b_icmp += pktlen;
273 +                       stat->p_icmp++;
274 +                       break;
275 +               default:
276 +                       stat->b_other += pktlen;
277 +                       stat->p_other++;
278 +       }
279 +}
280 +
281 +static int match(const struct sk_buff *skb,
282 +         const struct net_device *in,
283 +         const struct net_device *out,
284 +         const void *matchinfo,
285 +         int offset,
286 +         const void *hdr,
287 +         u_int16_t datalen,
288 +         int *hotdrop)
289 +{
290 +       
291 +       const struct t_ipt_account_info *info = (struct t_ipt_account_info*)matchinfo;
292 +       struct t_ipt_account_table *table;
293 +       int ret;
294 +
295 +       u_int32_t address;
296 +       u_int16_t pktlen;
297 +       u_int8_t proto;
298 +       
299 +       if (debug) {
300 +               printk(KERN_INFO "ipt_account: match() entering.\n");
301 +               printk(KERN_INFO "ipt_account: match() match name = %s.\n", info->name);
302 +       }
303 +       
304 +       spin_lock(&ipt_account_tables_lock);
305 +       /* find the right table */
306 +       table = ipt_account_tables;
307 +       while (table && strncmp(table->name, info->name, IPT_ACCOUNT_NAME_LEN) && (table = table->next));
308 +       spin_unlock(&ipt_account_tables_lock);
309 +
310 +       if (table == NULL) {
311 +               /* ups, no table with that name */
312 +               if (debug)
313 +                       printk(KERN_INFO "ipt_account: match() table %s not found. Leaving.\n", info->name);
314 +               return 0;
315 +       }
316 +
317 +       if (debug)
318 +               printk(KERN_INFO "ipt_account: match() table found %s\n", table->name);
319 +
320 +       /* default: no match */
321 +       ret = 0;
322 +
323 +       /* get packet protocol/length */
324 +       pktlen = skb->len;
325 +       proto = skb->nh.iph->protocol;
326 +
327 +       if (debug)
328 +               printk(KERN_INFO "ipt_account: match() got packet src = %u.%u.%u.%u, dst = %u.%u.%u.%u, proto = %u.\n",
329 +                                NIPQUAD(skb->nh.iph->saddr),
330 +                                NIPQUAD(skb->nh.iph->daddr),
331 +                                proto
332 +                                );
333 +
334 +       /* check whether traffic from source ip address ... */
335 +       address = ntohl(skb->nh.iph->saddr);
336 +       
337 +       /* ... is being accounted by this table */      
338 +       if (address && ((u_int32_t)(address & table->netmask) == (u_int32_t)table->network)) {          
339 +               if (debug)
340 +                       printk(KERN_INFO "ipt_account: match() accounting packet src = %u.%u.%u.%u, proto = %u.\n",
341 +                                        HIPQUAD(address),
342 +                                        proto
343 +                                        );
344 +               /* yes, account this packet */
345 +               spin_lock(&table->ip_list_lock);
346 +               /* update counters this host */
347 +               do_account(&table->ip_list[(u_int32_t)(address - table->network)].src, proto, pktlen);
348 +               /* update counters for all hosts in this table (network address) */
349 +               if (table->netmask != INADDR_BROADCAST)
350 +                       do_account(&table->ip_list[0].src, proto, pktlen);
351 +               spin_unlock(&table->ip_list_lock);
352 +               /* yes, it's a match */
353 +               ret = 1;
354 +       }
355 +
356 +       /* do the same thing with destination ip address */
357 +       address = ntohl(skb->nh.iph->daddr);
358 +    if (address && ((u_int32_t)(address & table->netmask) == (u_int32_t)table->network)) {
359 +               if (debug)
360 +                       printk(KERN_INFO "ipt_account: match() accounting packet dst = %u.%u.%u.%u, proto = %u.\n",
361 +                                       HIPQUAD(address),
362 +                                       proto
363 +                                       );
364 +               spin_lock(&table->ip_list_lock);
365 +               do_account(&table->ip_list[(u_int32_t)(address - table->network)].dest, proto, pktlen);
366 +               if (table->netmask != INADDR_BROADCAST)
367 +                       do_account(&table->ip_list[0].dest, proto, pktlen);
368 +               spin_unlock(&table->ip_list_lock);
369 +               ret = 1;
370 +       
371 +       }
372 +
373 +       if (debug)
374 +               printk(KERN_INFO "ipt_account: match() leaving.\n");    
375 +       
376 +       return ret;
377 +       
378 +}
379 +
380 +static int checkentry(const char *tablename,
381 +              const struct ipt_ip *ip,
382 +              void *matchinfo,
383 +              unsigned int matchinfosize,
384 +              unsigned int hook_mask)
385 +{
386 +       const struct t_ipt_account_info *info = matchinfo;
387 +       struct t_ipt_account_table *table;
388 +
389 +       char proc_entry_name[IPT_ACCOUNT_NAME_LEN + 3];
390 +
391 +       u_int32_t hosts_count;
392 +
393 +       if (debug)
394 +               printk(KERN_INFO "ipt_account: checkentry() entering.\n");
395 +
396 +       if (matchinfosize != IPT_ALIGN(sizeof(struct t_ipt_account_info)))
397 +               return 0;
398 +       
399 +       if (!info->name || !info->name[0])
400 +               return 0;
401 +
402 +       /* find whether table with this name already exists */
403 +       spin_lock(&ipt_account_tables_lock);
404 +       table = ipt_account_tables;
405 +       while (table && strncmp(info->name, table->name, IPT_ACCOUNT_NAME_LEN) && (table = table->next));
406 +       
407 +       if (table) {
408 +               /* yes, table exists */
409 +               if (info->network != table->network || info->netmask != table->netmask) {
410 +                       /* 
411 +                        * tried to do accounting in existing table, but network/netmask in iptable rule
412 +                        * doesn't match network/netmask in table structure - deny adding the rule 
413 +                        */
414 +                       printk(KERN_ERR "ipt_account: checkentry() table %s found. But table netmask/network %u.%u.%u.%u/%u.%u.%u.%u differs from rule netmask/network %u.%u.%u.%u/%u.%u.%u.%u. Leaving without creating entry.\n", 
415 +                                       table->name,
416 +                                       HIPQUAD(table->network),
417 +                                       HIPQUAD(table->netmask),
418 +                                       HIPQUAD(info->network),
419 +                                       HIPQUAD(info->netmask)
420 +                                       );
421 +                       spin_unlock(&ipt_account_tables_lock);
422 +                       return 0;
423 +               }                       
424 +               if (debug)
425 +                       printk(KERN_INFO "ipt_account: checkentry() table %s found. Incrementing use count (use_count = %i). Leaving.\n", table->name, table->use_count);
426 +               /* increase table use count */          
427 +               table->use_count++;
428 +               spin_unlock(&ipt_account_tables_lock);
429 +               /* everything went okey */
430 +               return 1;
431 +       };
432 +       
433 +       if (debug)
434 +               printk(KERN_INFO "ipt_account: checkentry() table %s not found. Creating.\n", info->name);
435 +       
436 +       /* table doesn't exist - create one */
437 +       table = vmalloc(sizeof(struct t_ipt_account_table));
438 +       if (table == NULL) {
439 +           if (debug)
440 +                   printk(KERN_INFO "ipt_account: checkentry() unable to allocate memory (t_account_table) for table %s. Leaving.\n", info->name);
441 +           spin_unlock(&ipt_account_tables_lock);
442 +           return -ENOMEM;
443 +       }
444 +       
445 +       /* set table parameters */
446 +       strncpy(table->name, info->name, IPT_ACCOUNT_NAME_LEN);
447 +       table->use_count = 1;   
448 +       table->network = info->network;
449 +       table->netmask = info->netmask;
450 +       table->ip_list_lock = SPIN_LOCK_UNLOCKED;
451 +       
452 +       hosts_count = INADDR_BROADCAST - table->netmask + 1;
453 +       
454 +       if (debug)
455 +               printk(KERN_INFO "ipt_account: checkentry() allocating memory for %u hosts (%u netmask).\n", hosts_count, info->netmask);
456 +
457 +       /* check whether table is not too big */
458 +       if (hosts_count > ip_list_max_hosts_count) {
459 +               printk(KERN_ERR "ipt_account: checkentry() unable allocate memory for %u hosts (%u netmask). Increase value of ip_list_max_mask parameter.\n", hosts_count, info->netmask);
460 +               vfree(table);
461 +               spin_unlock(&ipt_account_tables_lock);
462 +               return -ENOMEM;
463 +       }
464 +
465 +       table->ip_list = vmalloc(sizeof(struct t_ipt_account_ip_list) * hosts_count);
466 +       if (table->ip_list == NULL) {
467 +           if (debug)
468 +                   printk(KERN_INFO "ipt_account: checkentry() unable to allocate memory (t_account_ip_list) for table %s. Leaving.\n", table->name);
469 +           vfree(table);
470 +           spin_unlock(&ipt_account_tables_lock);
471 +           return -ENOMEM;
472 +       }
473 +
474 +       memset(table->ip_list, 0, sizeof(struct t_ipt_account_ip_list) * hosts_count);
475 +
476 +       /* 
477 +        * create entries in /proc/net/ipt_account: one with full 64-bit counters and
478 +        * second with 32-bit ones. The second can be used in programs supporting only 32-bit numbers
479 +        * (mrtg, rrdtool).
480 +        */
481 +       
482 +       strncpy(proc_entry_name, table->name, IPT_ACCOUNT_NAME_LEN);
483 +       strncat(proc_entry_name, "_64", 4);
484 +       
485 +       table->status_proc_64 = create_proc_entry(proc_entry_name, ip_list_perms, proc_net_ipt_account);
486 +       if (table->status_proc_64 == NULL) {        
487 +           if (debug)
488 +                   printk(KERN_INFO "ipt_account: checkentry() unable to allocate memory (status_proc_64) for table %s. Leaving.\n", table->name);
489 +           vfree(table->ip_list);
490 +           vfree(table);
491 +           spin_unlock(&ipt_account_tables_lock);
492 +           return -ENOMEM;
493 +       }
494 +
495 +       table->status_proc_64->owner = THIS_MODULE;
496 +       table->status_proc_64->read_proc = ip_list_read_proc_64;
497 +       table->status_proc_64->write_proc = ip_list_write_proc;
498 +       table->status_proc_64->data = table;    
499 +
500 +       strncpy(proc_entry_name, table->name, IPT_ACCOUNT_NAME_LEN);
501 +       strncat(proc_entry_name, "_32", 4);
502 +       
503 +       table->status_proc_32 = create_proc_entry(proc_entry_name, ip_list_perms, proc_net_ipt_account);
504 +       if (table->status_proc_32 == NULL) {        
505 +           if (debug)
506 +                   printk(KERN_INFO "ipt_account: checkentry() unable to allocate memory (status_proc_32) for table %s. Leaving.\n", table->name);
507 +           vfree(table->ip_list);
508 +           vfree(table);
509 +           spin_unlock(&ipt_account_tables_lock);
510 +           return -ENOMEM;
511 +       }
512 +
513 +       table->status_proc_32->owner = THIS_MODULE;
514 +       table->status_proc_32->read_proc = ip_list_read_proc_32;
515 +       table->status_proc_32->write_proc = ip_list_write_proc;
516 +       table->status_proc_32->data = table;
517 +       
518 +       /* finaly, insert table into list */
519 +       table->next = ipt_account_tables;
520 +       ipt_account_tables = table;
521 +
522 +       if (debug)
523 +               printk(KERN_INFO "ipt_account: checkentry() successfully created table %s (use_count = %i).\n", table->name, table->use_count);
524 +
525 +       spin_unlock(&ipt_account_tables_lock);
526 +       
527 +       if (debug)
528 +               printk(KERN_INFO "ipt_account: checkentry() leaving.\n");
529 +       return 1;
530 +}
531 +
532 +static void destroy(void *matchinfo, 
533 +            unsigned int matchinfosize)
534 +{
535 +       const struct t_ipt_account_info *info = matchinfo;
536 +       struct t_ipt_account_table *table, *last_table;
537 +       char proc_entry_name[IPT_ACCOUNT_NAME_LEN + 3];
538 +       
539 +       if (debug)
540 +               printk(KERN_INFO "ipt_account: destroy() entered.\n");
541 +       
542 +       if (matchinfosize != IPT_ALIGN(sizeof(struct t_ipt_account_info)))
543 +               return;
544 +
545 +       spin_lock(&ipt_account_tables_lock);
546 +       table = ipt_account_tables;
547 +
548 +       if (table == NULL) {
549 +               /* list is empty, sometheing is realy wrong! */
550 +               if (debug)
551 +                       printk(KERN_INFO "ipt_account: destroy() unable to found any tables (asked for %s). Leaving.\n", info->name);
552 +               spin_unlock(&ipt_account_tables_lock);
553 +               return;
554 +       }
555 +       
556 +       /* find table combined with this rule - this code is taken for ipt_recent ;) */
557 +       last_table = NULL;
558 +       while (strncmp(table->name, info->name, IPT_ACCOUNT_NAME_LEN) && (last_table = table) && (table = table->next));
559 +
560 +       if (table == NULL) {
561 +               printk(KERN_ERR "ipt_account: destroy() unable to found table %s. Leaving.\n", info->name);
562 +               spin_unlock(&ipt_account_tables_lock);
563 +               return;
564 +       }
565 +
566 +       /* decrease table use counter */
567 +       table->use_count--;
568 +       if (table->use_count != 0) {
569 +               /* table is used by other rule, can't remove it */
570 +               if (debug)
571 +                       printk(KERN_INFO "ipt_account: destroy() table %s is still used (use_count = %i). Leaving.\n", table->name, table->use_count);
572 +               spin_unlock(&ipt_account_tables_lock);
573 +               return;
574 +       }
575 +
576 +       /* table is not used by any other tule - remove it */
577 +       if (debug)
578 +               printk(KERN_INFO "ipt_account: destroy() removing table %s (use_count = %i).\n", table->name, table->use_count);
579 +       
580 +       if (last_table)
581 +               last_table->next = table->next;
582 +       else
583 +               ipt_account_tables = table->next;
584 +       
585 +       spin_lock(&table->ip_list_lock);
586 +       spin_unlock(&table->ip_list_lock);
587 +       
588 +       /* remove procfs entries */
589 +       strncpy(proc_entry_name, table->name, IPT_ACCOUNT_NAME_LEN);
590 +       strncat(proc_entry_name, "_64", 4);
591 +       remove_proc_entry(proc_entry_name, proc_net_ipt_account);
592 +       strncpy(proc_entry_name, table->name, IPT_ACCOUNT_NAME_LEN);
593 +       strncat(proc_entry_name, "_32", 4);
594 +       remove_proc_entry(proc_entry_name, proc_net_ipt_account);
595 +       vfree(table->ip_list);
596 +       vfree(table);
597 +
598 +       spin_unlock(&ipt_account_tables_lock);
599 +       
600 +       if (debug)
601 +               printk(KERN_INFO "account: destroy() leaving.\n");
602 +
603 +       return;
604 +}
605 +
606 +static struct ipt_match account_match = {
607 +       { NULL, NULL },
608 +       "account",
609 +       &match,
610 +       &checkentry,
611 +       &destroy,
612 +       THIS_MODULE
613 +};
614 +
615 +static int __init init(void) 
616 +{
617 +       printk(version);        
618 +       if (debug)
619 +               printk(KERN_INFO "account: __init(): ip_list_perms = %i, ip_list_max_mask = %i\n", ip_list_perms, ip_list_max_mask);                            
620 +       /* check params */
621 +       if (ip_list_max_mask > 32 || ip_list_max_mask < 0) {
622 +               printk(KERN_ERR "account: Wrong netmask given by ip_list_max_mask parameter (%u). Valid is 32 to 0.\n", ip_list_max_mask);
623 +               return 0;
624 +       }
625 +
626 +       ip_list_max_hosts_count = (1 << (32 - ip_list_max_mask)) + 1;
627 +       
628 +       /* create /proc/net/ipt_account directory */
629 +       proc_net_ipt_account = proc_mkdir("ipt_account", proc_net);
630 +       if (!proc_net_ipt_account)
631 +               return -ENOMEM;
632 +
633 +       return ipt_register_match(&account_match);
634 +}
635 +
636 +/* procedura usuwaj±ca modu³ */
637 +static void __exit fini(void) 
638 +{
639 +       ipt_unregister_match(&account_match);
640 +       /* remove /proc/net/ipt_account/ directory */
641 +       remove_proc_entry("ipt_account", proc_net);
642 +}
643 +
644 +module_init(init);
645 +module_exit(fini);
646 +
647 diff -uNr linux-2.6.6/net/ipv4/netfilter.orig/Kconfig linux-2.6.6/net/ipv4/netfilter/Kconfig
648 --- linux-2.6.6/net/ipv4/netfilter.orig/Kconfig 2004-05-22 15:21:26.033257624 +0200
649 +++ linux-2.6.6/net/ipv4/netfilter/Kconfig      2004-05-22 15:29:38.823342144 +0200
650 @@ -168,6 +168,17 @@
651  
652           To compile it as a module, choose M here.  If unsure, say N.
653  
654 +config IP_NF_MATCH_ACCOUNT
655 +       tristate "account match support"
656 +       depends on IP_NF_IPTABLES
657 +       help
658 +         This match is used for accounting traffic.
659 +
660 +         Short options are available by using 'iptables -m account -h'
661 +         Official Website: <http://www.barbara.eu.org/~quaker/ipt_account/>
662 +
663 +         To compile it as a module, choose M here.  If unsure, say N.
664 +
665  config IP_NF_MATCH_ECN
666         tristate "ECN match support"
667         depends on IP_NF_IPTABLES
668 diff -uNr linux-2.6.6/net/ipv4/netfilter.orig/Makefile linux-2.6.6/net/ipv4/netfilter/Makefile
669 --- linux-2.6.6/net/ipv4/netfilter.orig/Makefile        2004-05-22 15:21:26.034257472 +0200
670 +++ linux-2.6.6/net/ipv4/netfilter/Makefile     2004-05-22 15:30:30.150539224 +0200
671 @@ -118,6 +118,7 @@
672  obj-$(CONFIG_IP_NF_MATCH_FUZZY) += ipt_fuzzy.o
673  
674  obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
675 +obj-$(CONFIG_IP_NF_MATCH_ACCOUNT) += ipt_account.o
676  
677  obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
678  obj-$(CONFIG_IP_NF_MATCH_DSCP) += ipt_dscp.o
This page took 0.074156 seconds and 3 git commands to generate.