ipt_ACCOUNT: (gerd) linebreaks at width 80 (sometimes 84)
[ipt_ACCOUNT] / linux / net / ipv4 / netfilter / ipt_ACCOUNT.c
1 /***************************************************************************
2  *   This is a module which is used for counting packets.                  *
3  *   See http://www.intra2net.com/opensource/ipt_account                   *
4  *   for further information                                               *
5  *                                                                         * 
6  *   Copyright (C) 2004 by Intra2net AG                                    *
7  *   opensource@intra2net.com                                              *
8  *                                                                         *
9  *   This program is free software; you can redistribute it and/or modify  *
10  *   it under the terms of the GNU General Public License                  *
11  *   version 2 as published by the Free Software Foundation;               *
12  *                                                                         *
13  ***************************************************************************/
14
15 #include <linux/module.h>
16 #include <linux/skbuff.h>
17 #include <linux/ip.h>
18 #include <linux/spinlock.h>
19 #include <net/icmp.h>
20 #include <net/udp.h>
21 #include <net/tcp.h>
22 #include <linux/netfilter_ipv4/ip_tables.h>
23
24 struct in_device;
25 #include <net/route.h>
26 #include <linux/netfilter_ipv4/ipt_ACCOUNT.h>
27
28 #if 0
29 #define DEBUGP printk
30 #else
31 #define DEBUGP(format, args...)
32 #endif
33
34 #if (PAGE_SIZE < 4096)
35 #error "ipt_ACCOUNT needs at least a PAGE_SIZE of 4096"
36 #endif
37
38 struct ipt_account_table *ipt_account_tables = NULL;
39 struct ipt_account_handle *ipt_account_handles = NULL;
40 void *ipt_account_tmpbuf = NULL;
41
42 /* Spinlock used for manipulating the current accounting tables/data */
43 static spinlock_t ipt_account_lock = SPIN_LOCK_UNLOCKED;
44 /* Spinlock used for manipulating userspace handles/snapshot data */
45 static spinlock_t ipt_account_userspace_lock = SPIN_LOCK_UNLOCKED;
46
47
48 /* Recursive free of all data structures */
49 void ipt_account_data_free(void *data, unsigned char depth)
50 {
51     /* Empty data set */
52     if (!data)
53         return;
54
55     /* Free for 8 bit network */
56     if (depth == 0) {
57         free_page((unsigned long)data);
58         data = NULL;
59         return;
60     }
61
62     /* Free for 16 bit network */
63     if (depth == 1) {
64         struct ipt_account_mask_16 *mask_16 = (struct ipt_account_mask_16 *)data;
65         unsigned int b;
66         for (b=0; b <= 255; b++) {
67             if (mask_16->mask_24[b] != 0) {
68                 free_page((unsigned long)mask_16->mask_24[b]);
69                 mask_16->mask_24[b] = NULL;
70             }
71         }
72         free_page((unsigned long)data);
73         data = NULL;
74         return;
75     }
76
77     /* Free for 24 bit network */
78     if (depth == 2) {
79         unsigned int a, b;
80         for (a=0; a <= 255; a++) {
81             if (((struct ipt_account_mask_8 *)data)->mask_16[a]) {
82                 struct ipt_account_mask_16 *mask_16 = (struct ipt_account_mask_16*)
83                                    ((struct ipt_account_mask_8 *)data)->mask_16[a];
84                 
85                 for (b=0; b <= 255; b++) {
86                     if (mask_16->mask_24[b]) {
87                         free_page((unsigned long)mask_16->mask_24[b]);
88                         mask_16->mask_24[b] = NULL;
89                     }
90                 }
91                 free_page((unsigned long)mask_16);
92                 mask_16 = NULL;
93             }
94         }
95         free_page((unsigned long)data);
96         data = NULL;
97         return;
98     }
99
100     printk("ACCOUNT: ipt_account_data_free called with unknown depth: %d\n", 
101            depth);
102     return;
103 }
104
105 /* Look for existing table / insert new one. 
106    Return internal ID or -1 on error */
107 int ipt_account_table_insert(char *name, unsigned int ip, unsigned int netmask)
108 {
109     unsigned int i;
110
111     DEBUGP("ACCOUNT: ipt_account_table_insert: %s, %u.%u.%u.%u/%u.%u.%u.%u\n",
112                                          name, NIPQUAD(ip), NIPQUAD(netmask));
113
114     /* Look for existing table */
115     for (i = 0; i < ACCOUNT_MAX_TABLES; i++) {
116         if (strncmp(ipt_account_tables[i].name, name, 
117                     ACCOUNT_TABLE_NAME_LEN) == 0) {
118             DEBUGP("ACCOUNT: Found existing slot: %d - "
119                    "%u.%u.%u.%u/%u.%u.%u.%u\n", i, 
120                    NIPQUAD(ipt_account_tables[i].ip), 
121                    NIPQUAD(ipt_account_tables[i].netmask));
122
123             if (ipt_account_tables[i].ip != ip 
124                 || ipt_account_tables[i].netmask != netmask) {
125                 printk("ACCOUNT: Table %s found, but IP/netmask mismatch. "
126                        "IP/netmask found: %u.%u.%u.%u/%u.%u.%u.%u\n",
127                        name, NIPQUAD(ipt_account_tables[i].ip), 
128                        NIPQUAD(ipt_account_tables[i].netmask));
129                 return -1;
130             }
131
132             ipt_account_tables[i].refcount++;
133             DEBUGP("ACCOUNT: Refcount: %d\n", ipt_account_tables[i].refcount);
134             return i;
135         }
136     }
137
138     /* Insert new table */
139     for (i = 0; i < ACCOUNT_MAX_TABLES; i++) {
140         /* Found free slot */
141         if (ipt_account_tables[i].name[0] == 0) {
142             DEBUGP("ACCOUNT: Found free slot: %d\n", i);
143
144             strncpy (ipt_account_tables[i].name, name, ACCOUNT_TABLE_NAME_LEN-1);
145
146             ipt_account_tables[i].ip = ip;
147             ipt_account_tables[i].netmask = netmask;
148
149             /* Calculate netsize */
150             unsigned int j, calc_mask, netsize=0;
151             calc_mask = htonl(netmask);
152             for (j = 31; j > 0; j--) {
153                 if (calc_mask&(1<<j))
154                     netsize++;
155                 else
156                     break;
157             }
158
159             /* Calculate depth from netsize */
160             if (netsize >= 24)
161                 ipt_account_tables[i].depth = 0;
162             else if (netsize >= 16)
163                 ipt_account_tables[i].depth = 1;
164             else if(netsize >= 8)
165                 ipt_account_tables[i].depth = 2;
166
167             DEBUGP("ACCOUNT: calculated netsize: %u -> "
168                    "ipt_account_table depth %u\n", netsize, 
169                    ipt_account_tables[i].depth);
170
171             ipt_account_tables[i].refcount++;
172             if ((ipt_account_tables[i].data
173                 = (void *)get_zeroed_page(GFP_ATOMIC)) == NULL) {
174                 printk("ACCOUNT: out of memory for data of table: %s\n", name);
175                 memset(&ipt_account_tables[i], 0, 
176                        sizeof(struct ipt_account_table));
177                 return -1;
178             }
179
180             return i;
181         }
182     }
183
184     /* No free slot found */
185     printk("ACCOUNT: No free table slot found (max: %d). "
186            "Please increase ACCOUNT_MAX_TABLES.\n", ACCOUNT_MAX_TABLES);
187     return -1;
188 }
189
190 static int ipt_account_checkentry(const char *tablename,
191                                   const struct ipt_entry *e,
192                                   void *targinfo,
193                                   unsigned int targinfosize,
194                                   unsigned int hook_mask)
195 {
196     struct ipt_account_info *info = targinfo;
197
198     if (targinfosize != IPT_ALIGN(sizeof(struct ipt_account_info))) {
199         DEBUGP("ACCOUNT: targinfosize %u != %u\n",
200                targinfosize, IPT_ALIGN(sizeof(struct ipt_account_info)));
201         return 0;
202     }
203
204     spin_lock_bh(&ipt_account_lock);
205     int table_nr = ipt_account_table_insert(info->table_name, info->net_ip,
206                                             info->net_mask);
207     if (table_nr == -1) {
208         printk("ACCOUNT: Table insert problem. Aborting\n");
209         spin_unlock_bh(&ipt_account_lock);
210         return 0;
211     }
212     /* Table nr caching so we don't have to do an extra string compare 
213        for every packet */
214     info->table_nr = table_nr;
215
216     spin_unlock_bh(&ipt_account_lock);
217
218     return 1;
219 }
220
221 void ipt_account_deleteentry(void *targinfo, unsigned int targinfosize)
222 {
223     unsigned int i;
224     struct ipt_account_info *info = targinfo;
225
226     if (targinfosize != IPT_ALIGN(sizeof(struct ipt_account_info))) {
227         DEBUGP("ACCOUNT: targinfosize %u != %u\n",
228                targinfosize, IPT_ALIGN(sizeof(struct ipt_account_info)));
229     }
230
231     spin_lock_bh(&ipt_account_lock);
232
233     DEBUGP("ACCOUNT: ipt_account_deleteentry called for table: %s (#%d)\n", 
234            info->table_name, info->table_nr);
235
236     info->table_nr = -1;    /* Set back to original state */
237
238     /* Look for table */
239     for (i = 0; i < ACCOUNT_MAX_TABLES; i++) {
240         if (strncmp(ipt_account_tables[i].name, info->table_name, 
241                     ACCOUNT_TABLE_NAME_LEN) == 0) {
242             DEBUGP("ACCOUNT: Found table at slot: %d\n", i);
243
244             ipt_account_tables[i].refcount--;
245             DEBUGP("ACCOUNT: Refcount left: %d\n", 
246                    ipt_account_tables[i].refcount);
247
248             /* Table not needed anymore? */
249             if (ipt_account_tables[i].refcount == 0) {
250                 DEBUGP("ACCOUNT: Destroying table at slot: %d\n", i);
251                 ipt_account_data_free(ipt_account_tables[i].data, 
252                                       ipt_account_tables[i].depth);
253                 memset(&ipt_account_tables[i], 0, 
254                        sizeof(struct ipt_account_table));
255             }
256
257             spin_unlock_bh(&ipt_account_lock);
258             return;
259         }
260     }
261
262     /* Table not found */
263     printk("ACCOUNT: Table %s not found for destroy\n", info->table_name);
264     spin_unlock_bh(&ipt_account_lock);
265 }
266
267 void ipt_account_depth0_insert(struct ipt_account_mask_24 *mask_24,
268                                unsigned int net_ip, unsigned int netmask,
269                                unsigned int src_ip, unsigned int dst_ip,
270                                unsigned int size, unsigned int *itemcount)
271 {
272     unsigned char is_src = 0, is_dst = 0;
273
274     DEBUGP("ACCOUNT: ipt_account_depth0_insert: %u.%u.%u.%u/%u.%u.%u.%u "
275            "for net %u.%u.%u.%u/%u.%u.%u.%u, size: %u\n", NIPQUAD(src_ip), 
276            NIPQUAD(dst_ip), NIPQUAD(net_ip), NIPQUAD(netmask), size);
277
278     /* Check if src/dst is inside our network. */
279     /* Special: net_ip = 0.0.0.0/0 gets stored as src in slot 0 */
280     if (!netmask)
281         src_ip = 0;
282     if ((net_ip&netmask) == (src_ip&netmask))
283         is_src = 1;
284     if ((net_ip&netmask) == (dst_ip&netmask) && netmask)
285         is_dst = 1;
286
287     if (!is_src && !is_dst) {
288         DEBUGP("ACCOUNT: Skipping packet %u.%u.%u.%u/%u.%u.%u.%u "
289                "for net %u.%u.%u.%u/%u.%u.%u.%u\n", NIPQUAD(src_ip), 
290                NIPQUAD(dst_ip), NIPQUAD(net_ip), NIPQUAD(netmask));
291         return;
292     }
293
294     /* Check if this entry is new */
295     char is_src_new_ip = 0, is_dst_new_ip = 0;
296
297     /* Calculate array positions */
298     unsigned char src_slot = (unsigned char)((src_ip&0xFF000000) >> 24);
299     unsigned char dst_slot = (unsigned char)((dst_ip&0xFF000000) >> 24);
300
301     /* Increase size counters */
302     if (is_src) {
303         /* Calculate network slot */
304         DEBUGP("ACCOUNT: Calculated SRC 8 bit network slot: %d\n", src_slot);
305         if (!mask_24->ip[src_slot].src_packets 
306             && !mask_24->ip[src_slot].dst_packets)
307             is_src_new_ip = 1;
308
309         mask_24->ip[src_slot].src_packets++;
310         mask_24->ip[src_slot].src_bytes+=size;
311     }
312     if (is_dst) {
313         DEBUGP("ACCOUNT: Calculated DST 8 bit network slot: %d\n", dst_slot);
314         if (!mask_24->ip[dst_slot].src_packets 
315             && !mask_24->ip[dst_slot].dst_packets)
316             is_dst_new_ip = 1;
317
318         mask_24->ip[dst_slot].dst_packets++;
319         mask_24->ip[dst_slot].dst_bytes+=size;
320     }
321
322     /* Increase itemcounter */
323     DEBUGP("ACCOUNT: Itemcounter before: %d\n", *itemcount);
324     if (src_slot == dst_slot) {
325         if (is_src_new_ip || is_dst_new_ip) {
326             DEBUGP("ACCOUNT: src_slot == dst_slot: %d, %d\n", 
327                    is_src_new_ip, is_dst_new_ip);
328             (*itemcount)++;
329         }
330     } else {
331         if (is_src_new_ip) {
332             DEBUGP("ACCOUNT: New src_ip: %u.%u.%u.%u\n", NIPQUAD(src_ip));
333             (*itemcount)++;
334         }
335         if (is_dst_new_ip) {
336             DEBUGP("ACCOUNT: New dst_ip: %u.%u.%u.%u\n", NIPQUAD(dst_ip));
337             (*itemcount)++;
338         }
339     }
340     DEBUGP("ACCOUNT: Itemcounter after: %d\n", *itemcount);
341 }
342
343 void ipt_account_depth1_insert(struct ipt_account_mask_16 *mask_16, 
344                                unsigned int net_ip, unsigned int netmask, 
345                                unsigned int src_ip, unsigned int dst_ip,
346                                unsigned int size, unsigned int *itemcount)
347 {
348     /* Do we need to process src IP? */
349     if ((net_ip&netmask) == (src_ip&netmask)) {
350         unsigned char slot = (unsigned char)((src_ip&0x00FF0000) >> 16);
351         DEBUGP("ACCOUNT: Calculated SRC 16 bit network slot: %d\n", slot);
352
353         /* Do we need to create a new mask_24 bucket? */
354         if (!mask_16->mask_24[slot] && (mask_16->mask_24[slot] = 
355              (void *)get_zeroed_page(GFP_ATOMIC)) == NULL) {
356             printk("ACCOUNT: Can't process packet because out of memory!\n");
357             return;
358         }
359
360         ipt_account_depth0_insert((struct ipt_account_mask_24 *)mask_16->mask_24[slot],
361                                   net_ip, netmask, src_ip, 0, size, itemcount);
362     }
363
364     /* Do we need to process dst IP? */
365     if ((net_ip&netmask) == (dst_ip&netmask)) {
366         unsigned char slot = (unsigned char)((dst_ip&0x00FF0000) >> 16);
367         DEBUGP("ACCOUNT: Calculated DST 16 bit network slot: %d\n", slot);
368
369         /* Do we need to create a new mask_24 bucket? */
370         if (!mask_16->mask_24[slot] && (mask_16->mask_24[slot] 
371             = (void *)get_zeroed_page(GFP_ATOMIC)) == NULL) {
372             printk("ACCOUT: Can't process packet because out of memory!\n");
373             return;
374         }
375
376         ipt_account_depth0_insert((struct ipt_account_mask_24 *)mask_16->mask_24[slot],
377                                   net_ip, netmask, 0, dst_ip, size, itemcount);
378     }
379 }
380
381 void ipt_account_depth2_insert(struct ipt_account_mask_8 *mask_8, 
382                                unsigned int net_ip, unsigned int netmask,
383                                unsigned int src_ip, unsigned int dst_ip,
384                                unsigned int size, unsigned int *itemcount)
385 {
386     /* Do we need to process src IP? */
387     if ((net_ip&netmask) == (src_ip&netmask)) {
388         unsigned char slot = (unsigned char)((src_ip&0x0000FF00) >> 8);
389         DEBUGP("ACCOUNT: Calculated SRC 24 bit network slot: %d\n", slot);
390
391         /* Do we need to create a new mask_24 bucket? */
392         if (!mask_8->mask_16[slot] && (mask_8->mask_16[slot] 
393             = (void *)get_zeroed_page(GFP_ATOMIC)) == NULL) {
394             printk("ACCOUNT: Can't process packet because out of memory!\n");
395             return;
396         }
397
398         ipt_account_depth1_insert((struct ipt_account_mask_16 *)mask_8->mask_16[slot],
399                                   net_ip, netmask, src_ip, 0, size, itemcount);
400     }
401
402     /* Do we need to process dst IP? */
403     if ((net_ip&netmask) == (dst_ip&netmask)) {
404         unsigned char slot = (unsigned char)((dst_ip&0x0000FF00) >> 8);
405         DEBUGP("ACCOUNT: Calculated DST 24 bit network slot: %d\n", slot);
406
407         /* Do we need to create a new mask_24 bucket? */
408         if (!mask_8->mask_16[slot] && (mask_8->mask_16[slot] 
409             = (void *)get_zeroed_page(GFP_ATOMIC)) == NULL) {
410             printk("ACCOUNT: Can't process packet because out of memory!\n");
411             return;
412         }
413
414         ipt_account_depth1_insert((struct ipt_account_mask_16 *)mask_8->mask_16[slot],
415                                   net_ip, netmask, 0, dst_ip, size, itemcount);
416     }
417 }
418
419 static unsigned int ipt_account_target(struct sk_buff **pskb,
420                                        unsigned int hooknum,
421                                        const struct net_device *in,
422                                        const struct net_device *out,
423                                        const void *targinfo,
424                                        void *userinfo)
425 {
426     const struct ipt_account_info *info = 
427         (const struct ipt_account_info *)targinfo;
428     unsigned int src_ip = (*pskb)->nh.iph->saddr;
429     unsigned int dst_ip = (*pskb)->nh.iph->daddr;
430     unsigned int size = ntohs((*pskb)->nh.iph->tot_len);
431
432     spin_lock_bh(&ipt_account_lock);
433
434     if (ipt_account_tables[info->table_nr].name[0] == 0) {
435         printk("ACCOUNT: ipt_account_target: Invalid table id %u. "
436                "IPs %u.%u.%u.%u/%u.%u.%u.%u\n", info->table_nr, 
437                NIPQUAD(src_ip), NIPQUAD(dst_ip));
438         spin_unlock_bh(&ipt_account_lock);
439         return IPT_CONTINUE;
440     }
441
442     /* 8 bit network or "any" network */
443     if (ipt_account_tables[info->table_nr].depth == 0) {
444         /* Count packet and check if the IP is new */
445         ipt_account_depth0_insert(
446             (struct ipt_account_mask_24 *)ipt_account_tables[info->table_nr].data,
447             ipt_account_tables[info->table_nr].ip, 
448             ipt_account_tables[info->table_nr].netmask,
449             src_ip, dst_ip, size, &ipt_account_tables[info->table_nr].itemcount);
450         spin_unlock_bh(&ipt_account_lock);
451         return IPT_CONTINUE;
452     }
453
454     /* 16 bit network */
455     if (ipt_account_tables[info->table_nr].depth == 1) {
456         ipt_account_depth1_insert(
457             (struct ipt_account_mask_16 *)ipt_account_tables[info->table_nr].data,
458             ipt_account_tables[info->table_nr].ip, 
459             ipt_account_tables[info->table_nr].netmask,
460             src_ip, dst_ip, size, &ipt_account_tables[info->table_nr].itemcount);
461         spin_unlock_bh(&ipt_account_lock);
462         return IPT_CONTINUE;
463     }
464
465     /* 24 bit network */
466     if (ipt_account_tables[info->table_nr].depth == 2) {
467         ipt_account_depth2_insert(
468             (struct ipt_account_mask_8 *)ipt_account_tables[info->table_nr].data,
469             ipt_account_tables[info->table_nr].ip, 
470             ipt_account_tables[info->table_nr].netmask,
471             src_ip, dst_ip, size, &ipt_account_tables[info->table_nr].itemcount);
472         spin_unlock_bh(&ipt_account_lock);
473         return IPT_CONTINUE;
474     }
475
476     printk("ACCOUNT: ipt_account_target: Unable to process packet. "
477            "Table id %u. IPs %u.%u.%u.%u/%u.%u.%u.%u\n", 
478            info->table_nr, NIPQUAD(src_ip), NIPQUAD(dst_ip));
479
480     spin_unlock_bh(&ipt_account_lock);
481     return IPT_CONTINUE;
482 }
483
484 /*
485     Functions dealing with "handles":
486     Handles are snapshots of a accounting state.
487     
488     read snapshots are only for debugging the code
489     and are very expensive concerning speed/memory
490     compared to read_and_flush.
491     
492     The functions aren't protected by spinlocks themselves
493     as this is done in the ioctl part of the code.
494 */
495
496 /*
497     Find a free handle slot. Normally only one should be used,
498     but there could be two or more applications accessing the data
499     at the same time.
500 */
501 int ipt_account_handle_find_slot(void)
502 {
503     unsigned int i;
504     /* Insert new table */
505     for (i = 0; i < ACCOUNT_MAX_HANDLES; i++) {
506         /* Found free slot */
507         if (ipt_account_handles[i].data == NULL) {
508             /* Don't "mark" data as used as we are protected by a spinlock 
509                by the calling function. handle_find_slot() is only a function
510                to prevent code duplication. */
511             return i;
512         }
513     }
514
515     /* No free slot found */
516     printk("ACCOUNT: No free handle slot found (max: %u). "
517            "Please increase ACCOUNT_MAX_HANDLES.\n", ACCOUNT_MAX_HANDLES);
518     return -1;
519 }
520
521 int ipt_account_handle_free(unsigned int handle)
522 {
523     if (handle >= ACCOUNT_MAX_HANDLES) {
524         printk("ACCOUNT: Invalid handle for ipt_account_handle_free() specified:"
525                " %u\n", handle);
526         return -EINVAL;
527     }
528
529     ipt_account_data_free(ipt_account_handles[handle].data, 
530                           ipt_account_handles[handle].depth);
531     memset (&ipt_account_handles[handle], 0, sizeof (struct ipt_account_handle));
532     return 0;
533 }
534
535 /* Prepare data for read without flush. Use only for debugging!
536    Real applications should use read&flush as it's way more efficent */
537 int ipt_account_handle_prepare_read(char *tablename, unsigned int *count)
538 {
539     int handle, i, table_nr=-1;
540
541     for (i = 0; i < ACCOUNT_MAX_TABLES; i++)
542         if (strncmp(ipt_account_tables[i].name, tablename, 
543             ACCOUNT_TABLE_NAME_LEN) == 0) {
544             table_nr = i;
545             break;
546         }
547
548     if (table_nr == -1) {
549         printk("ACCOUNT: ipt_account_handle_prepare_read(): "
550                "Table %s not found\n", tablename);
551         return -1;
552     }
553
554     /* Can't find a free handle slot? */
555     if ((handle = ipt_account_handle_find_slot()) == -1)
556         return -1;
557
558     /* Fill up handle structure */
559     ipt_account_handles[handle].ip = ipt_account_tables[table_nr].ip;
560     ipt_account_handles[handle].depth = ipt_account_tables[table_nr].depth;
561     ipt_account_handles[handle].itemcount = ipt_account_tables[table_nr].itemcount;
562
563     /* allocate "root" table */
564     if ((ipt_account_handles[handle].data = 
565          (void*)get_zeroed_page(GFP_ATOMIC)) == NULL) {
566         printk("ACCOUNT: out of memory for root table "
567                "in ipt_account_handle_prepare_read()\n");
568         memset (&ipt_account_handles[handle], 0, 
569                 sizeof(struct ipt_account_handle));
570         return -1;
571     }
572
573     /* Recursive copy of complete data structure */
574     unsigned int depth = ipt_account_handles[handle].depth;
575     if (depth == 0) {
576         memcpy(ipt_account_handles[handle].data, 
577                ipt_account_tables[table_nr].data, 
578                sizeof(struct ipt_account_mask_24));
579     } else if (depth == 1) {
580         struct ipt_account_mask_16 *src_16 = 
581             (struct ipt_account_mask_16 *)ipt_account_tables[table_nr].data;
582         struct ipt_account_mask_16 *network_16 =
583             (struct ipt_account_mask_16 *)ipt_account_handles[handle].data;
584         unsigned int b;
585
586         for (b = 0; b <= 255; b++) {
587             if (src_16->mask_24[b]) {
588                 if ((network_16->mask_24[b] = 
589                      (void*)get_zeroed_page(GFP_ATOMIC)) == NULL) {
590                     printk("ACCOUNT: out of memory during copy of 16 bit "
591                            "network in ipt_account_handle_prepare_read()\n");
592                     ipt_account_data_free(ipt_account_handles[handle].data, depth);
593                     memset (&ipt_account_handles[handle], 0, 
594                             sizeof(struct ipt_account_handle));
595                     return -1;
596                 }
597
598                 memcpy(network_16->mask_24[b], src_16->mask_24[b], 
599                        sizeof(struct ipt_account_mask_24));
600             }
601         }
602     } else if(depth == 2) {
603         struct ipt_account_mask_8 *src_8 = 
604             (struct ipt_account_mask_8 *)ipt_account_tables[table_nr].data;
605         struct ipt_account_mask_8 *network_8 = 
606             (struct ipt_account_mask_8 *)ipt_account_handles[handle].data;
607         unsigned int a;
608
609         for (a = 0; a <= 255; a++) {
610             if (src_8->mask_16[a]) {
611                 if ((network_8->mask_16[a] = 
612                      (void*)get_zeroed_page(GFP_ATOMIC)) == NULL) {
613                     printk("ACCOUNT: out of memory during copy of 24 bit network"
614                            " in ipt_account_handle_prepare_read()\n");
615                     ipt_account_data_free(ipt_account_handles[handle].data, depth);
616                     memset (&ipt_account_handles[handle], 0, 
617                             sizeof(struct ipt_account_handle));
618                     return -1;
619                 }
620
621                 memcpy(network_8->mask_16[a], src_8->mask_16[a], 
622                        sizeof(struct ipt_account_mask_16));
623
624                 struct ipt_account_mask_16 *src_16 = src_8->mask_16[a];
625                 struct ipt_account_mask_16 *network_16 = network_8->mask_16[a];
626                 unsigned int b;
627
628                 for (b = 0; b <= 255; b++) {
629                     if (src_16->mask_24[b]) {
630                         if ((network_16->mask_24[b] = 
631                              (void*)get_zeroed_page(GFP_ATOMIC)) == NULL) {
632                             printk("ACCOUNT: out of memory during copy of 16 bit"
633                                    " network in ipt_account_handle_prepare_read()\n");
634                             ipt_account_data_free(ipt_account_handles[handle].data,
635                                                   depth);
636                             memset (&ipt_account_handles[handle], 0, 
637                                     sizeof(struct ipt_account_handle));
638                             return -1;
639                         }
640
641                         memcpy(network_16->mask_24[b], src_16->mask_24[b], 
642                                sizeof(struct ipt_account_mask_24));
643                     }
644                 }
645             }
646         }
647     }
648
649     *count = ipt_account_tables[table_nr].itemcount;
650     return handle;
651 }
652
653 /* Prepare data for read and flush it */
654 int ipt_account_handle_prepare_read_flush(char *tablename, unsigned int *count)
655 {
656     int handle, i, table_nr=-1;
657
658     for (i = 0; i < ACCOUNT_MAX_TABLES; i++)
659         if (strncmp(ipt_account_tables[i].name, tablename, 
660                     ACCOUNT_TABLE_NAME_LEN) == 0) {
661             table_nr = i;
662             break;
663         }
664
665     if (table_nr == -1) {
666         printk("ACCOUNT: ipt_account_handle_prepare_read_flush(): "
667                "Table %s not found\n", tablename);
668         return -1;
669     }
670
671     /* Can't find a free handle slot? */
672     if ((handle = ipt_account_handle_find_slot()) == -1)
673         return -1;
674
675     /* Try to allocate memory */
676     void *new_data_page = (void*)get_zeroed_page(GFP_ATOMIC);
677     if (!new_data_page)
678     {
679         printk("ACCOUNT: ipt_account_handle_prepare_read_flush(): "
680                "Out of memory!\n");
681         return -1;
682     }
683
684     /* Fill up handle structure */
685     ipt_account_handles[handle].ip = ipt_account_tables[table_nr].ip;
686     ipt_account_handles[handle].depth = ipt_account_tables[table_nr].depth;
687     ipt_account_handles[handle].itemcount = ipt_account_tables[table_nr].itemcount;
688     ipt_account_handles[handle].data = ipt_account_tables[table_nr].data;
689     *count = ipt_account_tables[table_nr].itemcount;
690
691     /* "Flush" table data */
692     ipt_account_tables[table_nr].data = new_data_page;
693     ipt_account_tables[table_nr].itemcount = 0;
694
695     return handle;
696 }
697
698 /* Copy 8 bit network data into a prepared buffer.
699    We only copy entries != 0 to increase performance.
700 */
701 void ipt_account_handle_copy_data(void *to_user, int *pos, 
702                                   struct ipt_account_mask_24 *data,
703                                   unsigned int net_ip, unsigned int net_OR_mask)
704 {
705     struct ipt_account_handle_ip handle_ip;
706     unsigned int handle_ip_size = sizeof (struct ipt_account_handle_ip);
707     
708     unsigned int i;
709     
710     for (i = 0; i <= 255; i++) {
711         if (data->ip[i].src_packets || data->ip[i].dst_packets) {
712             handle_ip.ip = net_ip | net_OR_mask | (i<<24);
713             
714             handle_ip.src_packets = data->ip[i].src_packets;
715             handle_ip.src_bytes = data->ip[i].src_bytes;
716             handle_ip.dst_packets = data->ip[i].dst_packets;
717             handle_ip.dst_bytes = data->ip[i].dst_bytes;
718
719             /* Temporary buffer full? Flush to userspace */
720             if (*pos+handle_ip_size >= PAGE_SIZE) {
721                 copy_to_user(to_user, ipt_account_tmpbuf, *pos);
722                 *pos = 0;
723             }
724             memcpy(ipt_account_tmpbuf+*pos, &handle_ip, handle_ip_size);
725             *pos += handle_ip_size;
726         }
727     }
728 }
729    
730 /* Copy the data from our internal structure 
731    We only copy entries != 0 to increase performance.
732    Overwrites ipt_account_tmpbuf.
733 */
734 int ipt_account_handle_get_data(unsigned int handle, void *to_user)
735 {
736     unsigned int tmpbuf_pos=0;
737
738     if (handle >= ACCOUNT_MAX_HANDLES) {
739         printk("ACCOUNT: invalid handle for ipt_account_handle_get_data() "
740                "specified: %u\n", handle);
741         return -1;
742     }
743
744     if (ipt_account_handles[handle].data == NULL) {
745         printk("ACCOUNT: handle %u is BROKEN: Contains no data\n", handle);
746         return -1;
747     }
748
749     unsigned int net_ip = ipt_account_handles[handle].ip;
750     unsigned int depth = ipt_account_handles[handle].depth;
751
752     /* 8 bit network */
753     if (depth == 0) {
754         struct ipt_account_mask_24 *network = 
755             (struct ipt_account_mask_24*)ipt_account_handles[handle].data;
756         ipt_account_handle_copy_data(to_user, &tmpbuf_pos, network, net_ip, 0);
757         
758         /* Flush remaining data to userspace */
759         if (tmpbuf_pos)
760             copy_to_user(to_user, ipt_account_tmpbuf, tmpbuf_pos);
761
762         return 0;
763     }
764
765     /* 16 bit network */
766     if (depth == 1) {
767         struct ipt_account_mask_16 *network_16 = 
768             (struct ipt_account_mask_16*)ipt_account_handles[handle].data;
769         unsigned int b;
770         for (b = 0; b <= 255; b++) {
771             if (network_16->mask_24[b]) {
772                 struct ipt_account_mask_24 *network = 
773                     (struct ipt_account_mask_24*)network_16->mask_24[b];
774                 ipt_account_handle_copy_data(to_user, &tmpbuf_pos, network, 
775                                              net_ip, (b << 16));
776             }
777         }
778
779         /* Flush remaining data to userspace */
780         if (tmpbuf_pos)
781             copy_to_user(to_user, ipt_account_tmpbuf, tmpbuf_pos);
782
783         return 0;
784     }
785
786     /* 24 bit network */
787     if (depth == 2) {
788         struct ipt_account_mask_8 *network_8 = 
789             (struct ipt_account_mask_8*)ipt_account_handles[handle].data;
790         unsigned int a, b;
791         for (a = 0; a <= 255; a++) {
792             if (network_8->mask_16[a]) {
793                 struct ipt_account_mask_16 *network_16 = 
794                     (struct ipt_account_mask_16*)network_8->mask_16[a];
795                 for (b = 0; b <= 255; b++) {
796                     if (network_16->mask_24[b]) {
797                         struct ipt_account_mask_24 *network = 
798                             (struct ipt_account_mask_24*)network_16->mask_24[b];
799                         ipt_account_handle_copy_data(to_user, &tmpbuf_pos, network,
800                                                      net_ip, (a << 8) | (b << 16));
801                     }
802                 }
803             }
804         }
805
806         /* Flush remaining data to userspace */
807         if (tmpbuf_pos)
808             copy_to_user(to_user, ipt_account_tmpbuf, tmpbuf_pos);
809
810         return 0;
811     }
812     
813     return -1;
814 }
815
816 static int ipt_account_set_ctl(struct sock *sk, int cmd, 
817                                void *user, unsigned int len)
818 {
819     struct ipt_account_handle_sockopt handle;
820     int ret = -EINVAL;
821
822     if (!capable(CAP_NET_ADMIN))
823         return -EPERM;
824
825     switch (cmd) {
826     case IPT_SO_SET_ACCOUNT_HANDLE_FREE:
827         if (len != sizeof(struct ipt_account_handle_sockopt)) {
828             printk("ACCOUNT: ipt_account_set_ctl: wrong data size (%u != %u) "
829                    "for IPT_SO_SET_HANDLE_FREE\n", 
830                    len, sizeof(struct ipt_account_handle_sockopt));
831             break;
832         }
833
834         if (copy_from_user (&handle, user, len)) {
835             printk("ACCOUNT: ipt_account_set_ctl: copy_from_user failed for "
836                    "IPT_SO_SET_HANDLE_FREE\n");
837             break;
838         }
839
840         spin_lock_bh(&ipt_account_userspace_lock);
841         ret = ipt_account_handle_free(handle.handle_nr);
842         spin_unlock_bh(&ipt_account_userspace_lock);
843         break;
844     case IPT_SO_SET_ACCOUNT_HANDLE_FREE_ALL: {
845             unsigned int i;
846             spin_lock_bh(&ipt_account_userspace_lock);
847             for (i = 0; i < ACCOUNT_MAX_HANDLES; i++)
848                 ipt_account_handle_free(i);
849             spin_unlock_bh(&ipt_account_userspace_lock);
850             ret = 0;
851             break;
852         }
853     default:
854         printk("ACCOUNT: ipt_account_set_ctl: unknown request %i\n", cmd);
855     }
856
857     return ret;
858 }
859
860 static int ipt_account_get_ctl(struct sock *sk, int cmd, void *user, int *len)
861 {
862     struct ipt_account_handle_sockopt handle;
863     int ret = -EINVAL;
864
865     if (!capable(CAP_NET_ADMIN))
866         return -EPERM;
867
868     switch (cmd) {
869     case IPT_SO_GET_ACCOUNT_PREPARE_READ_FLUSH:
870     case IPT_SO_GET_ACCOUNT_PREPARE_READ:
871         if (*len < sizeof(struct ipt_account_handle_sockopt)) {
872             printk("ACCOUNT: ipt_account_get_ctl: wrong data size (%u != %u) "
873                    "for IPT_SO_GET_ACCOUNT_PREPARE_READ/READ_FLUSH\n",
874                    *len, sizeof(struct ipt_account_handle_sockopt));
875             break;
876         }
877
878         if (copy_from_user (&handle, user, 
879                             sizeof(struct ipt_account_handle_sockopt))) {
880             return -EFAULT;
881             break;
882         }
883
884         spin_lock_bh(&ipt_account_lock);
885         spin_lock_bh(&ipt_account_userspace_lock);
886         if (cmd == IPT_SO_GET_ACCOUNT_PREPARE_READ_FLUSH)
887             handle.handle_nr = ipt_account_handle_prepare_read_flush(
888                                    handle.name, &handle.itemcount);
889         else
890             handle.handle_nr = ipt_account_handle_prepare_read(
891                                    handle.name, &handle.itemcount);
892         spin_unlock_bh(&ipt_account_userspace_lock);
893         spin_unlock_bh(&ipt_account_lock);
894
895         if (handle.handle_nr == -1) {
896             return -EINVAL;
897             break;
898         }
899
900         if (copy_to_user(user, &handle, 
901                          sizeof(struct ipt_account_handle_sockopt))) {
902             return -EFAULT;
903             break;
904         }
905         ret = 0;
906         break;
907     case IPT_SO_GET_ACCOUNT_GET_DATA:
908         if (*len < sizeof(struct ipt_account_handle_sockopt)) {
909             printk("ACCOUNT: ipt_account_get_ctl: wrong data size (%u != %u)"
910                    " for IPT_SO_GET_ACCOUNT_PREPARE_READ/READ_FLUSH\n",
911                    *len, sizeof(struct ipt_account_handle_sockopt));
912             break;
913         }
914
915         if (copy_from_user (&handle, user, 
916                             sizeof(struct ipt_account_handle_sockopt))) {
917             return -EFAULT;
918             break;
919         }
920
921         if (handle.handle_nr >= ACCOUNT_MAX_HANDLES) {
922             return -EINVAL;
923             break;
924         }
925
926         if (*len < ipt_account_handles[handle.handle_nr].itemcount
927                    * sizeof(struct ipt_account_handle_ip)) {
928             printk("ACCOUNT: ipt_account_get_ctl: not enough space (%u < %u)"
929                    " to store data from IPT_SO_GET_ACCOUNT_GET_DATA\n",
930                    *len, ipt_account_handles[handle.handle_nr].itemcount
931                    * sizeof(struct ipt_account_handle_ip));
932             ret = -ENOMEM;
933             break;
934         }
935
936         spin_lock_bh(&ipt_account_userspace_lock);
937         ret = ipt_account_handle_get_data(handle.handle_nr, user);
938         spin_unlock_bh(&ipt_account_userspace_lock);
939         if (ret) {
940             printk("ACCOUNT: ipt_account_get_ctl: ipt_account_handle_get_data"
941                    " failed for handle %u\n", handle.handle_nr);
942             break;
943         }
944
945         ret = 0;
946         break;
947     case IPT_SO_GET_ACCOUNT_GET_HANDLE_USAGE: {
948             if (*len < sizeof(struct ipt_account_handle_sockopt)) {
949                 printk("ACCOUNT: ipt_account_get_ctl: wrong data size (%u != %u)"
950                        " for IPT_SO_GET_ACCOUNT_GET_HANDLE_USAGE\n",
951                        *len, sizeof(struct ipt_account_handle_sockopt));
952                 break;
953             }
954
955             /* Find out how many handles are in use */
956             unsigned int i;
957             handle.itemcount = 0;
958             spin_lock_bh(&ipt_account_userspace_lock);
959             for (i = 0; i < ACCOUNT_MAX_HANDLES; i++)
960                 if (ipt_account_handles[i].data)
961                     handle.itemcount++;
962             spin_unlock_bh(&ipt_account_userspace_lock);
963
964             if (copy_to_user(user, &handle, 
965                              sizeof(struct ipt_account_handle_sockopt))) {
966                 return -EFAULT;
967                 break;
968             }
969             ret = 0;
970             break;
971         }
972     case IPT_SO_GET_ACCOUNT_GET_TABLE_NAMES: {
973             spin_lock_bh(&ipt_account_lock);
974
975             /* Determine size of table names */
976             unsigned int size = 0, i;
977             for (i = 0; i < ACCOUNT_MAX_TABLES; i++) {
978                 if (ipt_account_tables[i].name[0] != 0)
979                     size += strlen (ipt_account_tables[i].name) + 1;
980             }
981             size += 1;    /* Terminating NULL character */
982
983             if (*len < size) {
984                 spin_unlock_bh(&ipt_account_lock);
985                 printk("ACCOUNT: ipt_account_get_ctl: not enough space (%u < %u)"
986                        " to store table names\n", *len, size);
987                 ret = -ENOMEM;
988                 break;
989             }
990             /* Copy table names to userspace */
991             char *tnames = user;
992             for (i = 0; i < ACCOUNT_MAX_TABLES; i++) {
993                 if (ipt_account_tables[i].name[0] != 0) {
994                     int len = strlen (ipt_account_tables[i].name) + 1;
995                     /* copy string + terminating zero */
996                     copy_to_user(tnames, ipt_account_tables[i].name, len);
997                     tnames += len;
998                 }
999             }
1000             /* Append terminating zero */
1001             i = 0;
1002             copy_to_user(tnames, &i, 1);
1003             spin_unlock_bh(&ipt_account_lock);
1004             ret = 0;
1005             break;
1006         }
1007     default:
1008         printk("ACCOUNT: ipt_account_get_ctl: unknown request %i\n", cmd);
1009     }
1010
1011     return ret;
1012 }
1013
1014 static struct ipt_target ipt_account_reg = {
1015     {
1016         NULL, NULL
1017     },
1018     "ACCOUNT",
1019     ipt_account_target,
1020     ipt_account_checkentry,
1021     ipt_account_deleteentry,
1022     THIS_MODULE
1023 };
1024
1025 static struct nf_sockopt_ops ipt_account_sockopts = {
1026     {
1027         NULL, NULL
1028     },
1029     PF_INET,
1030     IPT_SO_SET_ACCOUNT_HANDLE_FREE,
1031     IPT_SO_SET_ACCOUNT_MAX+1,
1032     ipt_account_set_ctl,
1033     IPT_SO_GET_ACCOUNT_PREPARE_READ,
1034     IPT_SO_GET_ACCOUNT_MAX+1,
1035     ipt_account_get_ctl,
1036     0,
1037     NULL
1038 };
1039
1040 static int __init init(void)
1041 {
1042     if ((ipt_account_tables = 
1043          kmalloc(ACCOUNT_MAX_TABLES * 
1044                  sizeof(struct ipt_account_table), GFP_KERNEL)) == NULL) {
1045         printk("ACCOUNT: Out of memory allocating account_tables structure");
1046         return -EINVAL;
1047     }
1048     memset(ipt_account_tables, 0, 
1049            ACCOUNT_MAX_TABLES * sizeof(struct ipt_account_table));
1050
1051     if ((ipt_account_handles = 
1052          kmalloc(ACCOUNT_MAX_HANDLES * 
1053                  sizeof(struct ipt_account_handle), GFP_KERNEL)) == NULL) {
1054         printk("ACCOUNT: Out of memory allocating account_handles structure");
1055         kfree (ipt_account_tables);
1056         ipt_account_tables = NULL;
1057         return -EINVAL;
1058     }
1059     memset(ipt_account_handles, 0, 
1060            ACCOUNT_MAX_HANDLES * sizeof(struct ipt_account_handle));
1061
1062     /* Allocate one page as temporary storage */
1063     if ((ipt_account_tmpbuf = (void*)__get_free_page(GFP_KERNEL)) == NULL) {
1064         printk("ACCOUNT: Out of memory for temporary buffer page\n");
1065         kfree(ipt_account_tables);
1066         kfree(ipt_account_handles);
1067         ipt_account_tables = NULL;
1068         ipt_account_handles = NULL;
1069         return -EINVAL;
1070     }
1071
1072     /* Register setsockopt */
1073     if (nf_register_sockopt(&ipt_account_sockopts) < 0) {
1074         printk("ACCOUNT: Can't register sockopts. Aborting\n");
1075
1076         kfree(ipt_account_tables);
1077         kfree(ipt_account_handles);
1078         free_page((unsigned long)ipt_account_tmpbuf);
1079         ipt_account_tables = NULL;
1080         ipt_account_handles = NULL;
1081         ipt_account_tmpbuf = NULL;
1082
1083         return -EINVAL;
1084     }
1085
1086     if (ipt_register_target(&ipt_account_reg))
1087         return -EINVAL;
1088
1089     return 0;
1090 }
1091
1092 static void __exit fini(void)
1093 {
1094     ipt_unregister_target(&ipt_account_reg);
1095
1096     nf_unregister_sockopt(&ipt_account_sockopts);
1097
1098     kfree(ipt_account_tables);
1099     kfree(ipt_account_handles);
1100     free_page((unsigned long)ipt_account_tmpbuf);
1101
1102     ipt_account_tables = NULL;
1103     ipt_account_handles = NULL;
1104     ipt_account_tmpbuf = NULL;
1105 }
1106
1107 module_init(init);
1108 module_exit(fini);
1109 MODULE_LICENSE("GPL");