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