]> git.pld-linux.org Git - packages/kernel.git/blob - pom-ng-account-20060504.patch
- applies
[packages/kernel.git] / pom-ng-account-20060504.patch
1  include/linux/netfilter_ipv4/ipt_account.h |   26 
2  net/ipv4/netfilter/Kconfig                 |   46 +
3  net/ipv4/netfilter/Makefile                |    1 
4  net/ipv4/netfilter/ipt_account.c           |  937 +++++++++++++++++++++++++++++
5  4 files changed, 1010 insertions(+)
6
7 diff -Nur --exclude '*.orig' linux.org/include/linux/netfilter_ipv4/ipt_account.h linux/include/linux/netfilter_ipv4/ipt_account.h
8 --- linux.org/include/linux/netfilter_ipv4/ipt_account.h        1970-01-01 01:00:00.000000000 +0100
9 +++ linux/include/linux/netfilter_ipv4/ipt_account.h    2006-05-04 11:23:02.000000000 +0200
10 @@ -0,0 +1,26 @@
11 +/* 
12 + * accounting match (ipt_account.c)
13 + * (C) 2003,2004 by Piotr Gasidlo (quaker@barbara.eu.org)
14 + *
15 + * Version: 0.1.7
16 + *
17 + * This software is distributed under the terms of GNU GPL
18 + */
19 +
20 +#ifndef _IPT_ACCOUNT_H_
21 +#define _IPT_ACCOUNT_H_
22 +
23 +#define IPT_ACCOUNT_NAME_LEN 64
24 +
25 +#define IPT_ACCOUNT_NAME "ipt_account"
26 +#define IPT_ACCOUNT_VERSION  "0.1.7"
27 +
28 +struct t_ipt_account_info {
29 +       char name[IPT_ACCOUNT_NAME_LEN];
30 +       u_int32_t network;
31 +       u_int32_t netmask;
32 +       int shortlisting:1;
33 +};
34 +
35 +#endif
36 +
37 diff -Nur --exclude '*.orig' linux.org/net/ipv4/netfilter/Kconfig linux/net/ipv4/netfilter/Kconfig
38 --- linux.org/net/ipv4/netfilter/Kconfig        2006-05-02 23:38:44.000000000 +0200
39 +++ linux/net/ipv4/netfilter/Kconfig    2006-05-04 11:23:02.000000000 +0200
40 @@ -606,5 +606,51 @@
41           Allows altering the ARP packet payload: source and destination
42           hardware and network addresses.
43  
44 +config IP_NF_MATCH_ACCOUNT
45 +       tristate "account match support"
46 +       depends on IP_NF_IPTABLES && PROC_FS
47 +       help
48 +         This match is used for accounting traffic for all hosts in
49 +         defined network/netmask. 
50 +         
51 +         Features:
52 +         - long (one counter per protocol TCP/UDP/IMCP/Other) and short statistics
53 +         - one iptables rule for all hosts in network/netmask
54 +         - loading/saving counters (by reading/writting to procfs entries)
55 +         
56 +         Example usage:
57 +         
58 +         account traffic for/to 192.168.0.0/24 network into table mynetwork:
59 +         
60 +         # iptables -A FORWARD -m account --aname mynetwork --aaddr 192.168.0.0/24
61 +         
62 +         account traffic for/to WWW serwer for 192.168.0.0/24 network into table 
63 +         mywwwserver:
64 +         
65 +         # iptables -A INPUT -p tcp --dport 80 
66 +           -m account --aname mywwwserver --aaddr 192.168.0.0/24 --ashort
67 +         # iptables -A OUTPUT -p tcp --sport 80
68 +           -m account --aname mywwwserver --aaddr 192.168.0.0/24 --ashort    
69 +         
70 +         read counters:
71 +         
72 +         # cat /proc/net/ipt_account/mynetwork
73 +         # cat /proc/net/ipt_account/mywwwserver
74 +         
75 +         set counters:
76 +         
77 +         # echo "ip = 192.168.0.1 packets_src = 0" > /proc/net/ipt_account/mywwserver
78 +         
79 +         Webpage: 
80 +           http://www.barbara.eu.org/~quaker/ipt_account/
81 +
82 +config IP_NF_MATCH_ACCOUNT_DEBUG
83 +       bool "account debugging output"
84 +       depends on IP_NF_MATCH_ACCOUNT
85 +       help
86 +         Say Y to get lots of debugging output.
87 +         
88 +
89 +
90  endmenu
91  
92 diff -Nur --exclude '*.orig' linux.org/net/ipv4/netfilter/Makefile linux/net/ipv4/netfilter/Makefile
93 --- linux.org/net/ipv4/netfilter/Makefile       2006-05-02 23:38:44.000000000 +0200
94 +++ linux/net/ipv4/netfilter/Makefile   2006-05-04 11:23:02.000000000 +0200
95 @@ -0,0 +0,1 @@
96 +obj-$(CONFIG_IP_NF_MATCH_ACCOUNT) += ipt_account.o
97 diff -Nur --exclude '*.orig' linux.org/net/ipv4/netfilter/ipt_account.c linux/net/ipv4/netfilter/ipt_account.c
98 --- linux.org/net/ipv4/netfilter/ipt_account.c  1970-01-01 01:00:00.000000000 +0100
99 +++ linux/net/ipv4/netfilter/ipt_account.c      2006-05-04 11:23:02.000000000 +0200
100 @@ -0,0 +1,938 @@
101 +/* 
102 + * accounting match (ipt_account.c)
103 + * (C) 2003,2004 by Piotr Gasidlo (quaker@barbara.eu.org)
104 + *
105 + * Version: 0.1.7
106 + *
107 + * This software is distributed under the terms of GNU GPL
108 + */
109 +
110 +#include <linux/module.h>
111 +#include <linux/skbuff.h>
112 +#include <linux/proc_fs.h>
113 +#include <linux/spinlock.h>
114 +#include <linux/vmalloc.h>
115 +#include <linux/interrupt.h>
116 +#include <linux/ctype.h>
117 +
118 +#include <linux/seq_file.h>
119 +
120 +#include <asm/uaccess.h>
121 +
122 +#include <linux/ip.h>
123 +#include <linux/tcp.h>
124 +#include <linux/udp.h>
125 +
126 +#include <linux/netfilter_ipv4/ip_tables.h>
127 +#include <linux/netfilter_ipv4/ipt_account.h>
128 +
129 +#if defined(CONFIG_IP_NF_MATCH_ACCOUNT_DEBUG)
130 +       #define dprintk(format,args...) printk(format,##args)
131 +#else
132 +        #define dprintk(format,args...)
133 +#endif
134 +
135 +static char version[] =
136 +KERN_INFO IPT_ACCOUNT_NAME " " IPT_ACCOUNT_VERSION " : Piotr Gasid³o <quaker@barbara.eu.org>, http://www.barbara.eu.org/~quaker/ipt_account/\n";
137 +
138 +/* rights for files created in /proc/net/ipt_account/ */
139 +static int permissions = 0644;
140 +/* maximal netmask for single table */
141 +static int netmask = 16;
142 +
143 +/* module information */
144 +MODULE_AUTHOR("Piotr Gasidlo <quaker@barbara.eu.org>");
145 +MODULE_DESCRIPTION("Traffic accounting modules");
146 +MODULE_LICENSE("GPL");
147 +module_param(permissions, int, 0400);
148 +module_param(netmask, int, 0400);
149 +MODULE_PARM_DESC(permissions,"permissions on /proc/net/ipt_account/* files");
150 +MODULE_PARM_DESC(netmask, "maximum *save* size of one list (netmask)");
151 +
152 +/* structure with statistics counters */
153 +struct t_ipt_account_stat {
154 +       u_int64_t b_all, b_tcp, b_udp, b_icmp, b_other;         /* byte counters for all/tcp/udp/icmp/other traffic  */
155 +       u_int64_t p_all, p_tcp, p_udp, p_icmp, p_other;         /* packet counters for all/tcp/udp/icmp/other traffic */
156 +};
157 +
158 +/* stucture with statistics counters, used when table is created with --ashort switch */
159 +struct t_ipt_account_stat_short {
160 +       u_int64_t b_all;                                        /* byte counters for all traffic */
161 +       u_int64_t p_all;                                        /* packet counters for all traffic */
162 +};
163
164 +/* structure holding to/from statistics for single ip */
165 +struct t_ipt_account_ip_list {
166 +       struct t_ipt_account_stat src;
167 +       struct t_ipt_account_stat dest;
168 +       unsigned long time;                                     /* time when this record was last updated */    
169 +       
170 +};
171 +
172 +/* same as above, for tables with --ashort switch */
173 +struct t_ipt_account_ip_list_short {
174 +       struct t_ipt_account_stat_short src;
175 +       struct t_ipt_account_stat_short dest;
176 +       unsigned long time;
177 +};
178 +
179 +/* structure describing single table */
180 +struct t_ipt_account_table {
181 +       char name[IPT_ACCOUNT_NAME_LEN];        /* table name ( = filename in /proc/net/ipt_account/) */
182 +       union {                                 /* table with statistics for each ip in network/netmask */
183 +               struct t_ipt_account_ip_list *l;
184 +               struct t_ipt_account_ip_list_short *s;
185 +       } ip_list;
186 +       u_int32_t network;                      /* network/netmask covered by table*/
187 +       u_int32_t netmask;                                      
188 +       u_int32_t count;
189 +       int shortlisting:1;                     /* show only total columns of counters */       
190 +       int use_count;                          /* rules counter - counting number of rules using this table */
191 +       struct t_ipt_account_table *next;
192 +       spinlock_t ip_list_lock;
193 +       struct proc_dir_entry *status_file;
194 +};
195 +
196 +/* we must use spinlocks to avoid parallel modifications of table list */
197 +static spinlock_t account_lock = SPIN_LOCK_UNLOCKED;
198 +
199 +static struct proc_dir_entry *proc_net_ipt_account = NULL;
200 +
201 +/* root pointer holding list of the tables */
202 +static struct t_ipt_account_table *account_tables = NULL;
203 +
204 +/* convert ascii to ip */
205 +int atoip(char *buffer, u_int32_t *ip) {
206 +
207 +       char *bufferptr = buffer;
208 +       int part, shift;
209 +       
210 +       /* zero ip */
211 +       *ip = 0;
212 +
213 +       /* first must be a digit */
214 +       if (!isdigit(*bufferptr))
215 +               return 0;
216 +
217 +       /* parse first 3 octets (III.III.III.iii) */
218 +       for (part = 0, shift = 24; *bufferptr && shift; bufferptr++) {
219 +               if (isdigit(*bufferptr)) {
220 +                       part = part * 10 + (*bufferptr - '0');
221 +                       continue;
222 +               }
223 +               if (*bufferptr == '.') {
224 +                       if (part > 255)
225 +                               return 0;
226 +                       *ip |= part << shift;
227 +                       shift -= 8;
228 +                       part = 0;
229 +                       continue;
230 +               }
231 +               return 0;
232 +       }
233 +       
234 +       /* we expect more digts */
235 +       if (!*bufferptr)
236 +               return 0;
237 +       /* parse last octet (iii.iii.iii.III) */
238 +       for (; *bufferptr; bufferptr++) {
239 +               if (isdigit(*bufferptr)) {
240 +                       part = part * 10 + (*bufferptr - '0');                  
241 +                       continue;
242 +               } else {
243 +                       if (part > 255)
244 +                               return 0;
245 +                       *ip |= part;
246 +                       break;
247 +               }
248 +       }
249 +       return (bufferptr - buffer);
250 +}
251 +
252 +/* convert ascii to 64bit integer */
253 +int atoi64(char *buffer, u_int64_t *i) {       
254 +       char *bufferptr = buffer;
255 +
256 +       /* zero integer */
257 +       *i = 0;
258 +       
259 +       while (isdigit(*bufferptr)) {
260 +               *i = *i * 10 + (*bufferptr - '0');
261 +               bufferptr++;
262 +       }
263 +       return (bufferptr - buffer);
264 +}
265 +
266 +static void *account_seq_start(struct seq_file *s, loff_t *pos)
267 +{
268 +       struct proc_dir_entry *pde = s->private;
269 +       struct t_ipt_account_table *table = pde->data;
270 +
271 +       unsigned int *bucket;
272 +       
273 +       spin_lock_bh(&table->ip_list_lock);
274 +       if (*pos >= table->count)
275 +               return NULL;
276 +
277 +       bucket = kmalloc(sizeof(unsigned int), GFP_KERNEL);
278 +       if (!bucket)
279 +               return ERR_PTR(-ENOMEM);
280 +       *bucket = *pos;
281 +       return bucket;
282 +}
283 +
284 +static void *account_seq_next(struct seq_file *s, void *v, loff_t *pos)
285 +{
286 +       struct proc_dir_entry *pde = s->private;
287 +       struct t_ipt_account_table *table = pde->data;
288 +       
289 +       unsigned int *bucket = (unsigned int *)v;
290 +       
291 +       *pos = ++(*bucket);
292 +       if (*pos >= table->count) {
293 +               kfree(v);
294 +               return NULL;
295 +       }
296 +       return bucket;
297 +}
298 +
299 +static void account_seq_stop(struct seq_file *s, void *v)
300 +{
301 +       struct proc_dir_entry *pde = s->private;
302 +       struct t_ipt_account_table *table = pde->data;
303 +       unsigned int *bucket = (unsigned int *)v;
304 +       kfree(bucket);
305 +       spin_unlock_bh(&table->ip_list_lock);
306 +}
307 +
308 +static int account_seq_write(struct file *file, const char *ubuffer, 
309 +               size_t ulength, loff_t *pos)
310 +{
311 +       struct proc_dir_entry *pde = ((struct seq_file *)file->private_data)->private;
312 +       struct t_ipt_account_table *table = pde->data;
313 +       char buffer[1024], *bufferptr;
314 +       int length;
315 +
316 +       u_int32_t ip;
317 +       int len, i;
318 +       struct t_ipt_account_ip_list l;
319 +       struct t_ipt_account_ip_list_short s;
320 +       u_int64_t *p, dummy;
321 +       
322 +       
323 +       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() entered.\n");
324 +       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() ulength = %zi.\n", ulength);
325 +       
326 +       length = ulength;
327 +       if (ulength > 1024)
328 +               length = 1024;
329 +       if (copy_from_user(buffer, ubuffer, length))
330 +               return -EFAULT;
331 +       buffer[length - 1] = 0;
332 +       bufferptr = buffer;
333 +
334 +       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() buffer = \'%s\' length = %i.\n", buffer, length);
335 +       
336 +       /* reset table counters */
337 +       if (!memcmp(buffer, "reset", 5)) {
338 +               dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() got \"reset\".\n");
339 +               if (!table->shortlisting) {
340 +                       spin_lock_bh(&table->ip_list_lock);
341 +                       memset(table->ip_list.l, 0, sizeof(struct t_ipt_account_ip_list) * table->count);
342 +                       spin_unlock_bh(&table->ip_list_lock);
343 +               } else {
344 +                       spin_lock_bh(&table->ip_list_lock);
345 +                       memset(table->ip_list.s, 0, sizeof(struct t_ipt_account_ip_list_short) * table->count);
346 +                       spin_unlock_bh(&table->ip_list_lock);
347 +               }
348 +               return length;
349 +       }
350 +
351 +       if (!memcmp(buffer, "ip", 2)) {
352 +               dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() got \"ip\".\n");
353 +               bufferptr += 2;
354 +               if (!isspace(*bufferptr)) {
355 +                       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected space (%ti).\n", bufferptr - buffer);
356 +                       return length; /* expected space */
357 +               }
358 +               bufferptr += 1;
359 +               if (*bufferptr != '=') {
360 +                       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected equal (%ti).\n", bufferptr - buffer);
361 +                       return length; /* expected equal */
362 +               }
363 +               bufferptr += 1;
364 +               if (!isspace(*bufferptr)) {
365 +                       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected space (%ti).\n", bufferptr - buffer);
366 +                       return length; /* expected space */
367 +               }
368 +               bufferptr += 1;
369 +               if (!(len = atoip(bufferptr, &ip))) {
370 +                       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected ip (%ti).\n", bufferptr - buffer);
371 +                       return length; /* expected ip */
372 +               }
373 +               bufferptr += len;
374 +               if ((ip & table->netmask) != table->network) {
375 +                       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected ip [%u.%u.%u.%u] from table's network/netmask [%u.%u.%u.%u/%u.%u.%u.%u].\n", HIPQUAD(ip), HIPQUAD(table->network), HIPQUAD(table->netmask));
376 +                       return length; /* expected ip from table's network/netmask */
377 +               }
378 +               if (!table->shortlisting) {
379 +                       memset(&l, 0, sizeof(struct t_ipt_account_ip_list));
380 +                       while(*bufferptr) {
381 +                               if (!isspace(*bufferptr)) {
382 +                                       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected space (%ti).\n", bufferptr - buffer);
383 +                                       return length; /* expected space */
384 +                               }
385 +                               bufferptr += 1;
386 +                               if (!memcmp(bufferptr, "bytes_src", 9)) {
387 +                                       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() got bytes_src (%ti).\n", bufferptr - buffer);
388 +                                       p = &l.src.b_all;
389 +                                       bufferptr += 9;
390 +                               } else if (!memcmp(bufferptr, "bytes_dest", 10)) {                                      
391 +                                       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() got bytes_dest (%ti).\n", bufferptr - buffer);
392 +                                       p = &l.dest.b_all;
393 +                                       bufferptr += 10;
394 +                               } else if (!memcmp(bufferptr, "packets_src", 11)) {
395 +                                       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() got packets_src (%ti).\n", bufferptr - buffer);
396 +                                       p = &l.src.p_all;
397 +                                       bufferptr += 11;
398 +                               } else if (!memcmp(bufferptr, "packets_dest", 12)) {
399 +                                       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() got packets_dest (%ti).\n", bufferptr - buffer);
400 +                                       p = &l.dest.p_all;
401 +                                       bufferptr += 12;
402 +                               } else if (!memcmp(bufferptr, "time", 4)) {
403 +                                       /* time hack, ignore time tokens */
404 +                                       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() got time (%ti).\n", bufferptr - buffer);
405 +                                       bufferptr += 4;
406 +                                       if (!isspace(*bufferptr)) {
407 +                                               dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected space (%ti).\n", bufferptr - buffer);
408 +                                               return length; /* expected space */
409 +                                       }
410 +                                       bufferptr += 1;
411 +                                       if (*bufferptr != '=') {
412 +                                               dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected equal (%ti).\n", bufferptr - buffer);
413 +                                               return length; /* expected equal */
414 +                                       }
415 +                                       bufferptr += 1;
416 +                                       if (!isspace(*bufferptr)) {
417 +                                               dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected space (%ti).\n", bufferptr - buffer);
418 +                                               return length; /* expected space */
419 +                                       }
420 +                                       bufferptr += 1;
421 +                                       if (!(len = atoi64(bufferptr, &dummy))) {
422 +                                               dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected int64 (%ti).\n", bufferptr - buffer);
423 +                                               return length; /* expected int64 */
424 +                                       }
425 +                                       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() got %llu (%ti).\n", dummy, bufferptr - buffer);
426 +                                       bufferptr += len;
427 +                                       continue; /* skip time token */
428 +                               } else
429 +                                       return length;  /* expected token */
430 +                               if (!isspace(*bufferptr)) {
431 +                                       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected space (%ti).\n", bufferptr - buffer);
432 +                                       return length; /* expected space */
433 +                               }
434 +                               bufferptr += 1;
435 +                               if (*bufferptr != '=') {
436 +                                       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected equal (%ti).\n", bufferptr - buffer);
437 +                                       return length; /* expected equal */
438 +                               }
439 +                               bufferptr += 1;
440 +                               for (i = 0; i < 5; i++) {
441 +                                       if (!isspace(*bufferptr)) {
442 +                                               dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected space (%ti).\n", bufferptr - buffer);
443 +                                               return length; /* expected space */
444 +                                       }
445 +                                       bufferptr += 1;
446 +                                       if (!(len = atoi64(bufferptr, p))) {
447 +                                               dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected int64 (%ti).\n", bufferptr - buffer);
448 +                                               return length; /* expected int64 */
449 +                                       }
450 +                                       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() got %llu (%ti).\n", *p, bufferptr - buffer);
451 +                                       bufferptr += len;
452 +                                       p++;
453 +                               }
454 +                       }
455 +                       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() updating row.\n");
456 +                       spin_lock_bh(&table->ip_list_lock);
457 +                       /* update counters, do not overwrite time field */
458 +                       memcpy(&table->ip_list.l[ip - table->network], &l, sizeof(struct t_ipt_account_ip_list) - sizeof(unsigned long));
459 +                       spin_unlock_bh(&table->ip_list_lock);
460 +               } else {
461 +                       memset(&s, 0, sizeof(struct t_ipt_account_ip_list_short));
462 +                       while(*bufferptr) {
463 +                               if (!isspace(*bufferptr)) {
464 +                                       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected space (%ti).\n", bufferptr - buffer);
465 +                                       return length; /* expected space */
466 +                               }
467 +                               bufferptr += 1;
468 +                               if (!memcmp(bufferptr, "bytes_src", 9)) {
469 +                                       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() got bytes_src (%ti).\n", bufferptr - buffer);
470 +                                       p = &s.src.b_all;
471 +                                       bufferptr += 9;
472 +                               } else if (!memcmp(bufferptr, "bytes_dest", 10)) {                                      
473 +                                       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() got bytes_dest (%ti).\n", bufferptr - buffer);
474 +                                       p = &s.dest.b_all;
475 +                                       bufferptr += 10;
476 +                               } else if (!memcmp(bufferptr, "packets_src", 11)) {
477 +                                       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() got packets_src (%ti).\n", bufferptr - buffer);
478 +                                       p = &s.src.p_all;
479 +                                       bufferptr += 11;
480 +                               } else if (!memcmp(bufferptr, "packets_dest", 12)) {
481 +                                       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() got packets_dest (%ti).\n", bufferptr - buffer);
482 +                                       p = &s.dest.p_all;
483 +                                       bufferptr += 12;
484 +                               } else if (!memcmp(bufferptr, "time", 4)) {
485 +                                       /* time hack, ignore time tokens */
486 +                                       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() got time (%ti).\n", bufferptr - buffer);
487 +                                       bufferptr += 4;
488 +                                       if (!isspace(*bufferptr)) {
489 +                                               dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected space (%ti).\n", bufferptr - buffer);
490 +                                               return length; /* expected space */
491 +                                       }
492 +                                       bufferptr += 1;
493 +                                       if (*bufferptr != '=') {
494 +                                               dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected equal (%ti).\n", bufferptr - buffer);
495 +                                               return length; /* expected equal */
496 +                                       }
497 +                                       bufferptr += 1;
498 +                                       if (!isspace(*bufferptr)) {
499 +                                               dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected space (%ti).\n", bufferptr - buffer);
500 +                                               return length; /* expected space */
501 +                                       }
502 +                                       bufferptr += 1;
503 +                                       if (!(len = atoi64(bufferptr, &dummy))) {
504 +                                               dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected int64 (%ti).\n", bufferptr - buffer);
505 +                                               return length; /* expected int64 */
506 +                                       }
507 +                                       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() got %llu (%ti).\n", dummy, bufferptr - buffer);
508 +                                       bufferptr += len;
509 +                                       continue; /* skip time token */
510 +                               } else {
511 +                                       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected token (%ti).\n", bufferptr - buffer);
512 +                                       return length;  /* expected token */
513 +                               }
514 +                               if (!isspace(*bufferptr)) {
515 +                                       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected space (%ti).\n", bufferptr - buffer);
516 +                                       return length; /* expected space */
517 +                               }
518 +                               bufferptr += 1;
519 +                               if (*bufferptr != '=') {
520 +                                       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected equal (%ti).\n", bufferptr - buffer);
521 +                                       return length; /* expected equal */
522 +                               }
523 +                               bufferptr += 1;
524 +                               if (!isspace(*bufferptr)) {
525 +                                       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected space (%ti).\n", bufferptr - buffer);
526 +                                       return length; /* expected space */
527 +                               }
528 +                               bufferptr += 1;
529 +                               if (!(len = atoi64(bufferptr, p))) {
530 +                                       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected int64 (%ti).\n", bufferptr - buffer);
531 +                                       return length; /* expected int64 */
532 +                               }
533 +                               dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() got %llu (%ti).\n", *p, bufferptr - buffer);
534 +                               bufferptr += len;
535 +                       }
536 +                       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() updating row.\n");
537 +                       spin_lock_bh(&table->ip_list_lock);
538 +                       /* update counters, do not overwrite time field */
539 +                       memcpy(&table->ip_list.s[ip - table->network], &s, sizeof(struct t_ipt_account_ip_list_short) - sizeof(unsigned long));
540 +                       spin_unlock_bh(&table->ip_list_lock);
541 +               }
542 +       }
543 +       
544 +       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() left.\n");
545 +       return length;
546 +}
547 +
548 +
549 +static int account_seq_show(struct seq_file *s, void *v)
550 +{
551 +       struct proc_dir_entry *pde = s->private;
552 +       struct t_ipt_account_table *table = pde->data;
553 +       unsigned int *bucket = (unsigned int *)v;
554 +
555 +       u_int32_t address = table->network + *bucket;
556 +       struct timespec last;
557 +
558 +       if (!table->shortlisting) {
559 +               jiffies_to_timespec(jiffies - table->ip_list.l[*bucket].time, &last);
560 +               seq_printf(s,
561 +                               "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 time = %lu\n",
562 +                               HIPQUAD(address),
563 +                               table->ip_list.l[*bucket].src.b_all,
564 +                               table->ip_list.l[*bucket].src.b_tcp,
565 +                               table->ip_list.l[*bucket].src.b_udp,
566 +                               table->ip_list.l[*bucket].src.b_icmp,
567 +                               table->ip_list.l[*bucket].src.b_other,
568 +                               table->ip_list.l[*bucket].src.p_all,
569 +                               table->ip_list.l[*bucket].src.p_tcp,
570 +                               table->ip_list.l[*bucket].src.p_udp,
571 +                               table->ip_list.l[*bucket].src.p_icmp,
572 +                               table->ip_list.l[*bucket].src.p_other,
573 +                               table->ip_list.l[*bucket].dest.b_all,
574 +                               table->ip_list.l[*bucket].dest.b_tcp,
575 +                               table->ip_list.l[*bucket].dest.b_udp,
576 +                               table->ip_list.l[*bucket].dest.b_icmp,
577 +                               table->ip_list.l[*bucket].dest.b_other,                         
578 +                               table->ip_list.l[*bucket].dest.p_all,
579 +                               table->ip_list.l[*bucket].dest.p_tcp,
580 +                               table->ip_list.l[*bucket].dest.p_udp,
581 +                               table->ip_list.l[*bucket].dest.p_icmp,
582 +                               table->ip_list.l[*bucket].dest.p_other,
583 +                               last.tv_sec
584 +                       );
585 +       } else {
586 +               jiffies_to_timespec(jiffies - table->ip_list.s[*bucket].time, &last);
587 +               seq_printf(s,
588 +                               "ip = %u.%u.%u.%u bytes_src = %llu packets_src = %llu bytes_dest = %llu packets_dest = %llu time = %lu\n",
589 +                               HIPQUAD(address),
590 +                               table->ip_list.s[*bucket].src.b_all,
591 +                               table->ip_list.s[*bucket].src.p_all,
592 +                               table->ip_list.s[*bucket].dest.b_all,
593 +                               table->ip_list.s[*bucket].dest.p_all,
594 +                               last.tv_sec
595 +                         );
596 +       }
597 +       return 0;
598 +}
599 +
600 +static struct seq_operations account_seq_ops = {
601 +       .start = account_seq_start,
602 +       .next  = account_seq_next,
603 +       .stop  = account_seq_stop,
604 +       .show  = account_seq_show
605 +};
606 +
607 +static int account_seq_open(struct inode *inode, struct file *file)
608 +{
609 +       int ret = seq_open(file, &account_seq_ops);
610 +       
611 +       if (!ret) {
612 +               struct seq_file *sf = file->private_data;
613 +               sf->private = PDE(inode);
614 +       }
615 +       return ret;
616 +}
617 +
618 +static struct file_operations account_file_ops = {
619 +       .owner = THIS_MODULE,
620 +       .open = account_seq_open,
621 +       .read = seq_read,
622 +       .write = account_seq_write,
623 +       .llseek = seq_lseek,
624 +       .release = seq_release
625 +};
626 +
627 +/* do raw accounting */
628 +static inline void do_account(struct t_ipt_account_stat *stat, const struct sk_buff *skb) {
629 +       
630 +       /* update packet & bytes counters in *stat structure */
631 +       stat->b_all += skb->len;
632 +       stat->p_all++;
633 +       
634 +       switch (skb->nh.iph->protocol) {
635 +               case IPPROTO_TCP:
636 +                       stat->b_tcp += skb->len;
637 +                       stat->p_tcp++;
638 +                       break;
639 +               case IPPROTO_UDP:
640 +                       stat->b_udp += skb->len;
641 +                       stat->p_udp++;
642 +                       break;
643 +               case IPPROTO_ICMP:
644 +                       stat->b_icmp += skb->len;
645 +                       stat->p_icmp++;
646 +                       break;
647 +               default:
648 +                       stat->b_other += skb->len;
649 +                       stat->p_other++;
650 +       }
651 +}
652 +
653 +static inline void do_account_short(struct t_ipt_account_stat_short *stat, const struct sk_buff *skb) {
654 +
655 +       /* update packet & bytes counters in *stat structure */
656 +       stat->b_all += skb->len;
657 +       stat->p_all++;
658 +}
659 +
660 +static int match(const struct sk_buff *skb,
661 +         const struct net_device *in,
662 +         const struct net_device *out,
663 +         const void *matchinfo,
664 +         int offset,
665 +         unsigned int protoff,
666 +         int *hotdrop)
667 +{
668 +       
669 +       const struct t_ipt_account_info *info = (struct t_ipt_account_info*)matchinfo;
670 +       struct t_ipt_account_table *table;
671 +       int ret;
672 +       unsigned long now;
673 +
674 +       u_int32_t address;
675 +       
676 +       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": match() entered.\n");
677 +       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": match() match name = %s.\n", info->name);
678 +       
679 +       spin_lock_bh(&account_lock);
680 +       /* find the right table */
681 +       table = account_tables;
682 +       while (table && strncmp(table->name, info->name, IPT_ACCOUNT_NAME_LEN) && (table = table->next));
683 +       spin_unlock_bh(&account_lock);
684 +
685 +       if (table == NULL) {
686 +               /* ups, no table with that name */
687 +               dprintk(KERN_INFO IPT_ACCOUNT_NAME ": match() table %s not found. Leaving.\n", info->name);
688 +               return 0;
689 +       }
690 +
691 +       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": match() table found %s\n", table->name);
692 +
693 +       /*  lock table while updating statistics */
694 +       spin_lock_bh(&table->ip_list_lock);
695 +
696 +       /* default: no match */
697 +       ret = 0;
698 +
699 +       /* get current time */
700 +       now = jiffies;
701 +
702 +       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": match() got packet src = %u.%u.%u.%u, dst = %u.%u.%u.%u, proto = %u.\n", NIPQUAD(skb->nh.iph->saddr), NIPQUAD(skb->nh.iph->daddr), skb->nh.iph->protocol);
703 +                       
704 +       /* check whether traffic from source ip address ... */
705 +       address = ntohl(skb->nh.iph->saddr);
706 +       /* ... is being accounted by this table */      
707 +       if (address && ((u_int32_t)(address & table->netmask) == (u_int32_t)table->network)) {          
708 +               /* yes, account this packet */
709 +               dprintk(KERN_INFO "ipt_account: match() accounting packet src = %u.%u.%u.%u, proto = %u.\n", HIPQUAD(address), skb->nh.iph->protocol);
710 +               /* update counters this host */
711 +               if (!table->shortlisting) {
712 +                       do_account(&table->ip_list.l[address - table->network].src, skb);
713 +                       table->ip_list.l[address - table->network].time = now;
714 +                       /* update also counters for all hosts in this table (network address) */
715 +                       if (table->netmask != INADDR_BROADCAST) {
716 +                               do_account(&table->ip_list.l[0].src, skb);
717 +                               table->ip_list.l[0].time = now;
718 +                       }
719 +               } else {
720 +                       do_account_short(&table->ip_list.s[address - table->network].src, skb);
721 +                       table->ip_list.s[address - table->network].time = now;
722 +                       /* update also counters for all hosts in this table (network address) */
723 +                       if (table->netmask != INADDR_BROADCAST) {
724 +                               do_account_short(&table->ip_list.s[0].src, skb);
725 +                               table->ip_list.s[0].time = now;
726 +                       }
727 +               }
728 +               /* yes, it's a match */
729 +               ret = 1;
730 +       }
731 +
732 +       /* do the same thing with destination ip address */
733 +       address = ntohl(skb->nh.iph->daddr);
734 +       if (address && ((u_int32_t)(address & table->netmask) == (u_int32_t)table->network)) {
735 +               dprintk(KERN_INFO IPT_ACCOUNT_NAME ": match() accounting packet dst = %u.%u.%u.%u, proto = %u.\n", HIPQUAD(address), skb->nh.iph->protocol);
736 +               if (!table->shortlisting) {
737 +                       do_account(&table->ip_list.l[address - table->network].dest, skb);
738 +                       table->ip_list.l[address - table->network].time = now;
739 +                       if (table->netmask != INADDR_BROADCAST) {
740 +                               do_account(&table->ip_list.l[0].dest, skb);                             
741 +                               table->ip_list.s[0].time = now;
742 +                       }
743 +               } else {
744 +                       do_account_short(&table->ip_list.s[address - table->network].dest, skb);
745 +                       table->ip_list.s[address - table->network].time = now;
746 +                       if (table->netmask != INADDR_BROADCAST) {
747 +                               do_account_short(&table->ip_list.s[0].dest, skb);
748 +                               table->ip_list.s[0].time = now;
749 +                       }
750 +               }
751 +               ret = 1;
752 +       }
753 +       spin_unlock_bh(&table->ip_list_lock);
754 +       
755 +       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": match() left.\n");        
756 +
757 +       return ret;
758 +}
759 +
760 +static int checkentry(const char *tablename,
761 +              const struct ipt_ip *ip,
762 +              void *matchinfo,
763 +              unsigned int matchinfosize,
764 +              unsigned int hook_mask)
765 +{
766 +       const struct t_ipt_account_info *info = matchinfo;
767 +       struct t_ipt_account_table *table, *find_table, *last_table;
768 +       int ret = 0;
769 +
770 +       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() entered.\n");
771 +
772 +       if (matchinfosize != IPT_ALIGN(sizeof(struct t_ipt_account_info))) return 0;
773 +       if (!info->name || !info->name[0]) return 0;
774 +
775 +       /* find whether table with this name already exists */
776 +       spin_lock_bh(&account_lock);
777 +       find_table = account_tables;
778 +       while( (last_table = find_table) && strncmp(info->name,find_table->name,IPT_ACCOUNT_NAME_LEN) && (find_table = find_table->next) );
779 +       if (find_table != NULL) {
780 +               dprintk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() table %s found.\n", info->name);             
781 +               /* if table exists, check whether table network/netmask equals rule network/netmask */
782 +               if (find_table->network != info->network || find_table->netmask != info->netmask || find_table->shortlisting != info->shortlisting) {
783 +                       spin_unlock_bh(&account_lock);
784 +                       printk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() wrong parameters (not equals existing table parameters).\n");
785 +                       ret = 0;
786 +                       goto failure;
787 +               }
788 +               /* increment table use count */
789 +               find_table->use_count++;
790 +               spin_unlock_bh(&account_lock);
791 +               dprintk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() incrementing use count.\n");
792 +               ret = 1;
793 +               goto failure;
794 +       }
795 +       spin_unlock_bh(&account_lock);
796 +
797 +       /* check netmask first, before allocating memory */
798 +       if (info->netmask < ((1 << netmask) - 1)) {
799 +               printk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() too big netmask.\n");
800 +               ret = 0;
801 +               goto failure;
802 +       }
803 +
804 +       /* table doesn't exist - create new */
805 +       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() allocating %zu for new table %s.\n", sizeof(struct t_ipt_account_table), info->name);
806 +        table = vmalloc(sizeof(struct t_ipt_account_table));
807 +       if (table == NULL) {
808 +               printk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() failed to allocate %zu for new table %s.\n", sizeof(struct t_ipt_account_table), info->name);
809 +               ret = 0;
810 +               goto failure;
811 +       }
812 +       
813 +       /* setup table parameters */
814 +       table->ip_list_lock = SPIN_LOCK_UNLOCKED;
815 +       table->next = NULL;
816 +       table->use_count = 1;
817 +       table->network = info->network;
818 +       table->netmask = info->netmask;
819 +       table->shortlisting = info->shortlisting;
820 +       table->count = (~table->netmask) + 1;
821 +       strncpy(table->name,info->name,IPT_ACCOUNT_NAME_LEN);
822 +       table->name[IPT_ACCOUNT_NAME_LEN - 1] = '\0';
823 +       
824 +       /* allocate memory for table->ip_list */
825 +       if (!table->shortlisting) {
826 +               dprintk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() allocating %zu for ip_list.\n", sizeof(struct t_ipt_account_ip_list) * table->count);
827 +               table->ip_list.l = vmalloc(sizeof(struct t_ipt_account_ip_list) * table->count);
828 +               if (table->ip_list.l == NULL) {
829 +                       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() failed to allocate %zu for ip_list.\n", sizeof(struct t_ipt_account_ip_list) * table->count);
830 +                       ret = 0;
831 +                       goto failure_table;
832 +               }
833 +               memset(table->ip_list.l, 0, sizeof(struct t_ipt_account_ip_list) * table->count);
834 +       } else {
835 +               dprintk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() allocating %zu for ip_list.\n", sizeof(struct t_ipt_account_ip_list_short) * table->count);
836 +               table->ip_list.s = vmalloc(sizeof(struct t_ipt_account_ip_list_short) * table->count);
837 +               if (table->ip_list.s == NULL) {
838 +                       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() failed to allocate %zu for ip_list.\n", sizeof(struct t_ipt_account_ip_list_short) * table->count);
839 +                       ret = 0;
840 +                       goto failure_table;
841 +               }
842 +               memset(table->ip_list.s, 0, sizeof(struct t_ipt_account_ip_list_short) * table->count);
843 +       }
844 +       
845 +       /* put table into chain */
846 +       spin_lock_bh(&account_lock);
847 +       find_table = account_tables;
848 +       while( (last_table = find_table) && strncmp(info->name, find_table->name, IPT_ACCOUNT_NAME_LEN) && (find_table = find_table->next) );
849 +       if (find_table != NULL) {
850 +               dprintk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() table %s found.\n", info->name);
851 +               if (find_table->network != info->network || find_table->netmask != info->netmask) {
852 +                       spin_unlock_bh(&account_lock);
853 +                       printk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() wrong network/netmask.\n");
854 +                       ret = 0;
855 +                       goto failure_ip_list;
856 +               }
857 +               find_table->use_count++;
858 +               spin_unlock_bh(&account_lock);
859 +               dprintk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() incrementing use count.\n");
860 +               ret = 1;
861 +               goto failure_ip_list;
862 +       }
863 +       if (!last_table) 
864 +               account_tables = table; 
865 +       else 
866 +               last_table->next = table;
867 +       spin_unlock_bh(&account_lock);
868 +
869 +       /* create procfs status file */
870 +       table->status_file = create_proc_entry(table->name, permissions, proc_net_ipt_account);
871 +       if (table->status_file == NULL) {
872 +               ret = 0;
873 +               goto failure_unlink;
874 +       }
875 +       table->status_file->owner = THIS_MODULE;
876 +       table->status_file->data = table;       
877 +       wmb();
878 +       table->status_file->proc_fops = &account_file_ops;
879 +
880 +       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() left.\n");   
881 +       /* everything went just okey */
882 +       return 1;
883 +
884 +       /* do cleanup in case of failure */
885 +failure_unlink:
886 +       /* remove table from list */
887 +       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() removing table.\n");
888 +       spin_lock_bh(&account_lock);
889 +       last_table = NULL;
890 +       table = account_tables;
891 +       if (table == NULL) {
892 +               dprintk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() no table found. Leaving.\n");
893 +               spin_unlock_bh(&account_lock);
894 +               return 0;
895 +       }
896 +       while (strncmp(info->name, table->name, IPT_ACCOUNT_NAME_LEN) && (last_table = table) && (table = table->next));
897 +       if (table == NULL) {
898 +               dprintk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() table already destroyed. Leaving.\n");
899 +               spin_unlock_bh(&account_lock);
900 +               return 0;
901 +       }
902 +       if (last_table)
903 +               last_table->next = table->next;
904 +       else
905 +               account_tables = table->next;
906 +       spin_unlock_bh(&account_lock);
907 +failure_ip_list:
908 +       /* free memory allocated for statistics table */
909 +       if (!table->shortlisting)
910 +               vfree(table->ip_list.l);
911 +       else
912 +               vfree(table->ip_list.s);
913 +failure_table:
914 +       /* free table */
915 +       vfree(table);
916 +failure:
917 +       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() left. Table not created.\n");        
918 +       /* failure return */
919 +       return ret;
920 +}
921 +
922 +static void destroy(void *matchinfo, 
923 +            unsigned int matchinfosize)
924 +{
925 +       const struct t_ipt_account_info *info = matchinfo;
926 +       struct t_ipt_account_table *table, *last_table;
927 +
928 +       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": destory() entered.\n");
929 +       
930 +       if (matchinfosize != IPT_ALIGN(sizeof(struct t_ipt_account_info))) return;
931 +
932 +       /* search for table */
933 +       spin_lock_bh(&account_lock);
934 +       last_table = NULL;
935 +       table = account_tables;
936 +       if(table == NULL) {
937 +               dprintk(KERN_INFO IPT_ACCOUNT_NAME ": destory() no tables found. Leaving.\n");
938 +               spin_unlock_bh(&account_lock);
939 +               return;
940 +       }
941 +       while( strncmp(info->name,table->name,IPT_ACCOUNT_NAME_LEN) && (last_table = table) && (table = table->next) );
942 +       if (table == NULL) {
943 +               dprintk(KERN_INFO IPT_ACCOUNT_NAME ": destory() no table %s not found. Leaving.\n", info->name);
944 +               spin_unlock_bh(&account_lock);
945 +               return;
946 +       }
947 +
948 +       /* decrement table use-count */
949 +       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": destory() decrementing use count.\n");
950 +       table->use_count--;
951 +       if (table->use_count) {
952 +               dprintk(KERN_INFO IPT_ACCOUNT_NAME ": destory() table still in use. Leaving.\n");
953 +               spin_unlock_bh(&account_lock);
954 +               return;
955 +       }
956 +
957 +       /* remove table if use-count is zero */
958 +       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": destory() table %s not used. Removing.\n", table->name);
959 +
960 +       /* unlink table */
961 +       if(last_table) 
962 +               last_table->next = table->next; 
963 +       else 
964 +               account_tables = table->next;
965 +       spin_unlock_bh(&account_lock);
966 +
967 +       /* wait while table is still in use */
968 +       spin_lock_bh(&table->ip_list_lock);
969 +       spin_unlock_bh(&table->ip_list_lock);
970 +
971 +       /* remove proc entries */       
972 +       remove_proc_entry(table->name, proc_net_ipt_account);
973 +
974 +       /* remove table */
975 +       if (!table->shortlisting)
976 +               vfree(table->ip_list.l);
977 +       else
978 +               vfree(table->ip_list.s);
979 +       vfree(table);
980 +
981 +       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": destory() left.\n");
982 +       return;
983 +}
984 +
985 +static struct ipt_match account_match = {
986 +       .name = "account",
987 +       .match = &match,
988 +       .checkentry = &checkentry,
989 +       .destroy = &destroy,
990 +       .me = THIS_MODULE
991 +};
992 +
993 +static int __init init(void) 
994 +{
995 +       int err;
996 +       
997 +       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": __init() entered.\n");
998 +       printk(version);        
999 +       /* check params */
1000 +       if (netmask > 32 || netmask < 0) {
1001 +               printk(KERN_INFO "account: Wrong netmask given by netmask parameter (%i). Valid is 32 to 0.\n", netmask);
1002 +               err = -EINVAL;
1003 +               goto doexit;
1004 +       }
1005 +
1006 +       /* create /proc/net/ipt_account directory */
1007 +       proc_net_ipt_account = proc_mkdir("ipt_account", proc_net);
1008 +       if (!proc_net_ipt_account) {            
1009 +               printk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() failed to create procfs entry.\n");
1010 +               err = -ENOMEM;
1011 +               goto doexit;
1012 +       }
1013 +       proc_net_ipt_account->owner = THIS_MODULE;
1014 +       
1015 +       err = ipt_register_match(&account_match);
1016 +       if (err) {
1017 +               printk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() failed to register match.\n");
1018 +               remove_proc_entry("ipt_account", proc_net);
1019 +       }
1020 +doexit:        
1021 +       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": __init() left.\n");
1022 +       return err;
1023 +}
1024 +
1025 +static void __exit fini(void) 
1026 +{
1027 +       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": __exit() entered.\n");
1028 +       
1029 +       ipt_unregister_match(&account_match);
1030 +       /* remove /proc/net/ipt_account/ directory */
1031 +       remove_proc_entry("ipt_account", proc_net);
1032 +
1033 +       dprintk(KERN_INFO IPT_ACCOUNT_NAME ": __exit() left.\n");
1034 +}
1035 +
1036 +module_init(init);
1037 +module_exit(fini);
1038 +
This page took 0.102162 seconds and 3 git commands to generate.