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