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