1 diff -uprN linux1/include/linux/netfilter_ipv4/ipt_ACCOUNT.h linux-2.6/include/linux/netfilter_ipv4/ipt_ACCOUNT.h
2 --- linux1/include/linux/netfilter_ipv4/ipt_ACCOUNT.h 1970-01-01 01:00:00.000000000 +0100
3 +++ linux-2.6/include/linux/netfilter_ipv4/ipt_ACCOUNT.h 2007-12-14 10:42:16.000000000 +0100
5 +/***************************************************************************
6 + * Copyright (C) 2004-2006 by Intra2net AG *
7 + * opensource@intra2net.com *
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; *
13 + ***************************************************************************/
15 +#ifndef _IPT_ACCOUNT_H
16 +#define _IPT_ACCOUNT_H
18 +#define ACCOUNT_MAX_TABLES 128
19 +#define ACCOUNT_TABLE_NAME_LEN 32
20 +#define ACCOUNT_MAX_HANDLES 10
22 +/* Structure for the userspace part of ipt_ACCOUNT */
23 +struct ipt_acc_info {
26 + char table_name[ACCOUNT_TABLE_NAME_LEN];
30 +/* Internal table structure, generated by check_entry() */
31 +struct ipt_acc_table {
32 + char name[ACCOUNT_TABLE_NAME_LEN]; /* name of the table */
33 + u_int32_t ip; /* base IP of network */
34 + u_int32_t netmask; /* netmask of the network */
35 + unsigned char depth; /* size of network:
36 + 0: 8 bit, 1: 16bit, 2: 24 bit */
37 + u_int32_t refcount; /* refcount of this table.
38 + if zero, destroy it */
39 + u_int32_t itemcount; /* number of IPs in this table */
40 + void *data; /* pointer to the actual data,
41 + depending on netmask */
44 +/* Internal handle structure */
45 +struct ipt_acc_handle {
46 + u_int32_t ip; /* base IP of network. Used for
47 + caculating the final IP during
49 + unsigned char depth; /* size of network. See above for
51 + u_int32_t itemcount; /* number of IPs in this table */
52 + void *data; /* pointer to the actual data,
53 + depending on size */
56 +/* Handle structure for communication with the userspace library */
57 +struct ipt_acc_handle_sockopt {
58 + u_int32_t handle_nr; /* Used for HANDLE_FREE */
59 + char name[ACCOUNT_TABLE_NAME_LEN]; /* Used for HANDLE_PREPARE_READ/
60 + HANDLE_READ_FLUSH */
61 + u_int32_t itemcount; /* Used for HANDLE_PREPARE_READ/
62 + HANDLE_READ_FLUSH */
65 +/* Used for every IP entry
66 + Size is 16 bytes so that 256 (class C network) * 16
67 + fits in one kernel (zero) page */
69 + u_int32_t src_packets;
70 + u_int32_t src_bytes;
71 + u_int32_t dst_packets;
72 + u_int32_t dst_bytes;
76 + Used for every IP when returning data
78 +struct ipt_acc_handle_ip {
80 + u_int32_t src_packets;
81 + u_int32_t src_bytes;
82 + u_int32_t dst_packets;
83 + u_int32_t dst_bytes;
87 + The IPs are organized as an array so that direct slot
88 + calculations are possible.
89 + Only 8 bit networks are preallocated, 16/24 bit networks
90 + allocate their slots when needed -> very efficent.
92 +struct ipt_acc_mask_24 {
93 + struct ipt_acc_ip ip[256];
96 +struct ipt_acc_mask_16 {
97 + struct ipt_acc_mask_24 *mask_24[256];
100 +struct ipt_acc_mask_8 {
101 + struct ipt_acc_mask_16 *mask_16[256];
104 +#endif /*_IPT_ACCOUNT_H*/
105 diff -uprN linux1/net/ipv4/netfilter/ipt_ACCOUNT.c linux-2.6/net/ipv4/netfilter/ipt_ACCOUNT.c
106 --- linux1/net/ipv4/netfilter/ipt_ACCOUNT.c 1970-01-01 01:00:00.000000000 +0100
107 +++ linux-2.6/net/ipv4/netfilter/ipt_ACCOUNT.c 2008-03-10 11:39:42.000000000 +0100
109 +/***************************************************************************
110 + * This is a module which is used for counting packets. *
111 + * See http://www.intra2net.com/opensource/ipt_account *
112 + * for further information *
114 + * Copyright (C) 2004-2007 by Intra2net AG *
115 + * opensource@intra2net.com *
117 + * This program is free software; you can redistribute it and/or modify *
118 + * it under the terms of the GNU General Public License *
119 + * version 2 as published by the Free Software Foundation; *
121 + ***************************************************************************/
123 +#include <linux/module.h>
124 +#include <linux/version.h>
125 +#include <linux/skbuff.h>
126 +#include <linux/ip.h>
127 +#include <net/icmp.h>
128 +#include <net/udp.h>
129 +#include <net/tcp.h>
130 +#include <linux/netfilter_ipv4/ip_tables.h>
131 +#include <linux/semaphore.h>
132 +#include <linux/kernel.h>
133 +#include <linux/mm.h>
134 +#include <linux/string.h>
135 +#include <linux/spinlock.h>
136 +#include <asm/uaccess.h>
138 +#include <net/route.h>
139 +#include <linux/netfilter_ipv4/ipt_ACCOUNT.h>
142 +#define DEBUGP printk
144 +#define DEBUGP(format, args...)
147 +#if (PAGE_SIZE < 4096)
148 +#error "ipt_ACCOUNT needs at least a PAGE_SIZE of 4096"
151 +static struct ipt_acc_table *ipt_acc_tables = NULL;
152 +static struct ipt_acc_handle *ipt_acc_handles = NULL;
153 +static void *ipt_acc_tmpbuf = NULL;
155 +/* Spinlock used for manipulating the current accounting tables/data */
156 +static DEFINE_SPINLOCK(ipt_acc_lock);
157 +/* Mutex (semaphore) used for manipulating userspace handles/snapshot data */
158 +static struct semaphore ipt_acc_userspace_mutex;
160 +/* Allocates a page and clears it */
161 +static void *ipt_acc_zalloc_page(void)
163 + // Don't use get_zeroed_page until it's fixed in the kernel.
164 + // get_zeroed_page(GFP_ATOMIC)
165 + void *mem = (void *)__get_free_page(GFP_ATOMIC);
167 + memset (mem, 0, PAGE_SIZE);
173 +/* Recursive free of all data structures */
174 +static void ipt_acc_data_free(void *data, unsigned char depth)
176 + /* Empty data set */
180 + /* Free for 8 bit network */
182 + free_page((unsigned long)data);
186 + /* Free for 16 bit network */
188 + struct ipt_acc_mask_16 *mask_16 = (struct ipt_acc_mask_16 *)data;
190 + for (b=0; b <= 255; b++) {
191 + if (mask_16->mask_24[b]) {
192 + free_page((unsigned long)mask_16->mask_24[b]);
195 + free_page((unsigned long)data);
199 + /* Free for 24 bit network */
202 + for (a=0; a <= 255; a++) {
203 + if (((struct ipt_acc_mask_8 *)data)->mask_16[a]) {
204 + struct ipt_acc_mask_16 *mask_16 = (struct ipt_acc_mask_16*)
205 + ((struct ipt_acc_mask_8 *)data)->mask_16[a];
207 + for (b=0; b <= 255; b++) {
208 + if (mask_16->mask_24[b]) {
209 + free_page((unsigned long)mask_16->mask_24[b]);
212 + free_page((unsigned long)mask_16);
215 + free_page((unsigned long)data);
219 + printk("ACCOUNT: ipt_acc_data_free called with unknown depth: %d\n",
224 +/* Look for existing table / insert new one.
225 + Return internal ID or -1 on error */
226 +static int ipt_acc_table_insert(char *name, u_int32_t ip, u_int32_t netmask)
230 + DEBUGP("ACCOUNT: ipt_acc_table_insert: %s, %u.%u.%u.%u/%u.%u.%u.%u\n",
231 + name, NIPQUAD(ip), NIPQUAD(netmask));
233 + /* Look for existing table */
234 + for (i = 0; i < ACCOUNT_MAX_TABLES; i++) {
235 + if (strncmp(ipt_acc_tables[i].name, name,
236 + ACCOUNT_TABLE_NAME_LEN) == 0) {
237 + DEBUGP("ACCOUNT: Found existing slot: %d - "
238 + "%u.%u.%u.%u/%u.%u.%u.%u\n", i,
239 + NIPQUAD(ipt_acc_tables[i].ip),
240 + NIPQUAD(ipt_acc_tables[i].netmask));
242 + if (ipt_acc_tables[i].ip != ip
243 + || ipt_acc_tables[i].netmask != netmask) {
244 + printk("ACCOUNT: Table %s found, but IP/netmask mismatch. "
245 + "IP/netmask found: %u.%u.%u.%u/%u.%u.%u.%u\n",
246 + name, NIPQUAD(ipt_acc_tables[i].ip),
247 + NIPQUAD(ipt_acc_tables[i].netmask));
251 + ipt_acc_tables[i].refcount++;
252 + DEBUGP("ACCOUNT: Refcount: %d\n", ipt_acc_tables[i].refcount);
257 + /* Insert new table */
258 + for (i = 0; i < ACCOUNT_MAX_TABLES; i++) {
259 + /* Found free slot */
260 + if (ipt_acc_tables[i].name[0] == 0) {
261 + unsigned int netsize=0;
262 + u_int32_t calc_mask;
263 + int j; /* needs to be signed, otherwise we risk endless loop */
265 + DEBUGP("ACCOUNT: Found free slot: %d\n", i);
266 + strncpy (ipt_acc_tables[i].name, name, ACCOUNT_TABLE_NAME_LEN-1);
268 + ipt_acc_tables[i].ip = ip;
269 + ipt_acc_tables[i].netmask = netmask;
271 + /* Calculate netsize */
272 + calc_mask = htonl(netmask);
273 + for (j = 31; j >= 0; j--) {
274 + if (calc_mask&(1<<j))
280 + /* Calculate depth from netsize */
282 + ipt_acc_tables[i].depth = 0;
283 + else if (netsize >= 16)
284 + ipt_acc_tables[i].depth = 1;
285 + else if(netsize >= 8)
286 + ipt_acc_tables[i].depth = 2;
288 + DEBUGP("ACCOUNT: calculated netsize: %u -> "
289 + "ipt_acc_table depth %u\n", netsize,
290 + ipt_acc_tables[i].depth);
292 + ipt_acc_tables[i].refcount++;
293 + if ((ipt_acc_tables[i].data
294 + = ipt_acc_zalloc_page()) == NULL) {
295 + printk("ACCOUNT: out of memory for data of table: %s\n", name);
296 + memset(&ipt_acc_tables[i], 0,
297 + sizeof(struct ipt_acc_table));
305 + /* No free slot found */
306 + printk("ACCOUNT: No free table slot found (max: %d). "
307 + "Please increase ACCOUNT_MAX_TABLES.\n", ACCOUNT_MAX_TABLES);
311 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
312 +static bool ipt_acc_checkentry(const char *tablename,
314 +static int ipt_acc_checkentry(const char *tablename,
316 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
319 + const struct ipt_entry *e,
321 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
322 + const struct xt_target *target,
325 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
326 + unsigned int targinfosize,
328 + unsigned int hook_mask)
330 + struct ipt_acc_info *info = targinfo;
333 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
334 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_acc_info))) {
335 + DEBUGP("ACCOUNT: targinfosize %u != %u\n",
336 + targinfosize, IPT_ALIGN(sizeof(struct ipt_acc_info)));
341 + spin_lock_bh(&ipt_acc_lock);
342 + table_nr = ipt_acc_table_insert(info->table_name, info->net_ip,
344 + spin_unlock_bh(&ipt_acc_lock);
346 + if (table_nr == -1) {
347 + printk("ACCOUNT: Table insert problem. Aborting\n");
348 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
354 + /* Table nr caching so we don't have to do an extra string compare
355 + for every packet */
356 + info->table_nr = table_nr;
358 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
365 +static void ipt_acc_destroy(
366 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
367 + const struct xt_target *target,
369 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
373 + unsigned int targinfosize)
377 + struct ipt_acc_info *info = targinfo;
379 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
380 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_acc_info))) {
381 + DEBUGP("ACCOUNT: targinfosize %u != %u\n",
382 + targinfosize, IPT_ALIGN(sizeof(struct ipt_acc_info)));
386 + spin_lock_bh(&ipt_acc_lock);
388 + DEBUGP("ACCOUNT: ipt_acc_deleteentry called for table: %s (#%d)\n",
389 + info->table_name, info->table_nr);
391 + info->table_nr = -1; /* Set back to original state */
393 + /* Look for table */
394 + for (i = 0; i < ACCOUNT_MAX_TABLES; i++) {
395 + if (strncmp(ipt_acc_tables[i].name, info->table_name,
396 + ACCOUNT_TABLE_NAME_LEN) == 0) {
397 + DEBUGP("ACCOUNT: Found table at slot: %d\n", i);
399 + ipt_acc_tables[i].refcount--;
400 + DEBUGP("ACCOUNT: Refcount left: %d\n",
401 + ipt_acc_tables[i].refcount);
403 + /* Table not needed anymore? */
404 + if (ipt_acc_tables[i].refcount == 0) {
405 + DEBUGP("ACCOUNT: Destroying table at slot: %d\n", i);
406 + ipt_acc_data_free(ipt_acc_tables[i].data,
407 + ipt_acc_tables[i].depth);
408 + memset(&ipt_acc_tables[i], 0,
409 + sizeof(struct ipt_acc_table));
412 + spin_unlock_bh(&ipt_acc_lock);
417 + /* Table not found */
418 + printk("ACCOUNT: Table %s not found for destroy\n", info->table_name);
419 + spin_unlock_bh(&ipt_acc_lock);
422 +static void ipt_acc_depth0_insert(struct ipt_acc_mask_24 *mask_24,
423 + u_int32_t net_ip, u_int32_t netmask,
424 + u_int32_t src_ip, u_int32_t dst_ip,
425 + u_int32_t size, u_int32_t *itemcount)
427 + unsigned char is_src = 0, is_dst = 0, src_slot, dst_slot;
428 + char is_src_new_ip = 0, is_dst_new_ip = 0; /* Check if this entry is new */
430 + DEBUGP("ACCOUNT: ipt_acc_depth0_insert: %u.%u.%u.%u/%u.%u.%u.%u "
431 + "for net %u.%u.%u.%u/%u.%u.%u.%u, size: %u\n", NIPQUAD(src_ip),
432 + NIPQUAD(dst_ip), NIPQUAD(net_ip), NIPQUAD(netmask), size);
434 + /* Check if src/dst is inside our network. */
435 + /* Special: net_ip = 0.0.0.0/0 gets stored as src in slot 0 */
438 + if ((net_ip&netmask) == (src_ip&netmask))
440 + if ((net_ip&netmask) == (dst_ip&netmask) && netmask)
443 + if (!is_src && !is_dst) {
444 + DEBUGP("ACCOUNT: Skipping packet %u.%u.%u.%u/%u.%u.%u.%u "
445 + "for net %u.%u.%u.%u/%u.%u.%u.%u\n", NIPQUAD(src_ip),
446 + NIPQUAD(dst_ip), NIPQUAD(net_ip), NIPQUAD(netmask));
450 + /* Calculate array positions */
451 + src_slot = (unsigned char)((src_ip&0xFF000000) >> 24);
452 + dst_slot = (unsigned char)((dst_ip&0xFF000000) >> 24);
454 + /* Increase size counters */
456 + /* Calculate network slot */
457 + DEBUGP("ACCOUNT: Calculated SRC 8 bit network slot: %d\n", src_slot);
458 + if (!mask_24->ip[src_slot].src_packets
459 + && !mask_24->ip[src_slot].dst_packets)
462 + mask_24->ip[src_slot].src_packets++;
463 + mask_24->ip[src_slot].src_bytes+=size;
466 + DEBUGP("ACCOUNT: Calculated DST 8 bit network slot: %d\n", dst_slot);
467 + if (!mask_24->ip[dst_slot].src_packets
468 + && !mask_24->ip[dst_slot].dst_packets)
471 + mask_24->ip[dst_slot].dst_packets++;
472 + mask_24->ip[dst_slot].dst_bytes+=size;
475 + /* Increase itemcounter */
476 + DEBUGP("ACCOUNT: Itemcounter before: %d\n", *itemcount);
477 + if (src_slot == dst_slot) {
478 + if (is_src_new_ip || is_dst_new_ip) {
479 + DEBUGP("ACCOUNT: src_slot == dst_slot: %d, %d\n",
480 + is_src_new_ip, is_dst_new_ip);
484 + if (is_src_new_ip) {
485 + DEBUGP("ACCOUNT: New src_ip: %u.%u.%u.%u\n", NIPQUAD(src_ip));
488 + if (is_dst_new_ip) {
489 + DEBUGP("ACCOUNT: New dst_ip: %u.%u.%u.%u\n", NIPQUAD(dst_ip));
493 + DEBUGP("ACCOUNT: Itemcounter after: %d\n", *itemcount);
496 +static void ipt_acc_depth1_insert(struct ipt_acc_mask_16 *mask_16,
497 + u_int32_t net_ip, u_int32_t netmask,
498 + u_int32_t src_ip, u_int32_t dst_ip,
499 + u_int32_t size, u_int32_t *itemcount)
501 + /* Do we need to process src IP? */
502 + if ((net_ip&netmask) == (src_ip&netmask)) {
503 + unsigned char slot = (unsigned char)((src_ip&0x00FF0000) >> 16);
504 + DEBUGP("ACCOUNT: Calculated SRC 16 bit network slot: %d\n", slot);
506 + /* Do we need to create a new mask_24 bucket? */
507 + if (!mask_16->mask_24[slot] && (mask_16->mask_24[slot] =
508 + ipt_acc_zalloc_page()) == NULL) {
509 + printk("ACCOUNT: Can't process packet because out of memory!\n");
513 + ipt_acc_depth0_insert((struct ipt_acc_mask_24 *)mask_16->mask_24[slot],
514 + net_ip, netmask, src_ip, 0, size, itemcount);
517 + /* Do we need to process dst IP? */
518 + if ((net_ip&netmask) == (dst_ip&netmask)) {
519 + unsigned char slot = (unsigned char)((dst_ip&0x00FF0000) >> 16);
520 + DEBUGP("ACCOUNT: Calculated DST 16 bit network slot: %d\n", slot);
522 + /* Do we need to create a new mask_24 bucket? */
523 + if (!mask_16->mask_24[slot] && (mask_16->mask_24[slot]
524 + = ipt_acc_zalloc_page()) == NULL) {
525 + printk("ACCOUT: Can't process packet because out of memory!\n");
529 + ipt_acc_depth0_insert((struct ipt_acc_mask_24 *)mask_16->mask_24[slot],
530 + net_ip, netmask, 0, dst_ip, size, itemcount);
534 +static void ipt_acc_depth2_insert(struct ipt_acc_mask_8 *mask_8,
535 + u_int32_t net_ip, u_int32_t netmask,
536 + u_int32_t src_ip, u_int32_t dst_ip,
537 + u_int32_t size, u_int32_t *itemcount)
539 + /* Do we need to process src IP? */
540 + if ((net_ip&netmask) == (src_ip&netmask)) {
541 + unsigned char slot = (unsigned char)((src_ip&0x0000FF00) >> 8);
542 + DEBUGP("ACCOUNT: Calculated SRC 24 bit network slot: %d\n", slot);
544 + /* Do we need to create a new mask_24 bucket? */
545 + if (!mask_8->mask_16[slot] && (mask_8->mask_16[slot]
546 + = ipt_acc_zalloc_page()) == NULL) {
547 + printk("ACCOUNT: Can't process packet because out of memory!\n");
551 + ipt_acc_depth1_insert((struct ipt_acc_mask_16 *)mask_8->mask_16[slot],
552 + net_ip, netmask, src_ip, 0, size, itemcount);
555 + /* Do we need to process dst IP? */
556 + if ((net_ip&netmask) == (dst_ip&netmask)) {
557 + unsigned char slot = (unsigned char)((dst_ip&0x0000FF00) >> 8);
558 + DEBUGP("ACCOUNT: Calculated DST 24 bit network slot: %d\n", slot);
560 + /* Do we need to create a new mask_24 bucket? */
561 + if (!mask_8->mask_16[slot] && (mask_8->mask_16[slot]
562 + = ipt_acc_zalloc_page()) == NULL) {
563 + printk("ACCOUNT: Can't process packet because out of memory!\n");
567 + ipt_acc_depth1_insert((struct ipt_acc_mask_16 *)mask_8->mask_16[slot],
568 + net_ip, netmask, 0, dst_ip, size, itemcount);
572 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
573 +static unsigned int ipt_acc_target(struct sk_buff *skb,
575 +static unsigned int ipt_acc_target(struct sk_buff **pskb,
577 + const struct net_device *in,
578 + const struct net_device *out,
579 + unsigned int hooknum,
580 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
581 + const struct xt_target *target,
583 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
584 + const void *targinfo)
586 + const void *targinfo,
590 + const struct ipt_acc_info *info =
591 + (const struct ipt_acc_info *)targinfo;
592 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
593 + u_int32_t src_ip = ip_hdr(skb)->saddr;
594 + u_int32_t dst_ip = ip_hdr(skb)->daddr;
595 + u_int32_t size = ntohs(ip_hdr(skb)->tot_len);
597 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
598 + u_int32_t src_ip = ip_hdr(*pskb)->saddr;
599 + u_int32_t dst_ip = ip_hdr(*pskb)->daddr;
600 + u_int32_t size = ntohs(ip_hdr(*pskb)->tot_len);
602 + u_int32_t src_ip = (*pskb)->nh.iph->saddr;
603 + u_int32_t dst_ip = (*pskb)->nh.iph->daddr;
604 + u_int32_t size = ntohs((*pskb)->nh.iph->tot_len);
608 + spin_lock_bh(&ipt_acc_lock);
610 + if (ipt_acc_tables[info->table_nr].name[0] == 0) {
611 + printk("ACCOUNT: ipt_acc_target: Invalid table id %u. "
612 + "IPs %u.%u.%u.%u/%u.%u.%u.%u\n", info->table_nr,
613 + NIPQUAD(src_ip), NIPQUAD(dst_ip));
614 + spin_unlock_bh(&ipt_acc_lock);
615 + return IPT_CONTINUE;
618 + /* 8 bit network or "any" network */
619 + if (ipt_acc_tables[info->table_nr].depth == 0) {
620 + /* Count packet and check if the IP is new */
621 + ipt_acc_depth0_insert(
622 + (struct ipt_acc_mask_24 *)ipt_acc_tables[info->table_nr].data,
623 + ipt_acc_tables[info->table_nr].ip,
624 + ipt_acc_tables[info->table_nr].netmask,
625 + src_ip, dst_ip, size, &ipt_acc_tables[info->table_nr].itemcount);
626 + spin_unlock_bh(&ipt_acc_lock);
627 + return IPT_CONTINUE;
630 + /* 16 bit network */
631 + if (ipt_acc_tables[info->table_nr].depth == 1) {
632 + ipt_acc_depth1_insert(
633 + (struct ipt_acc_mask_16 *)ipt_acc_tables[info->table_nr].data,
634 + ipt_acc_tables[info->table_nr].ip,
635 + ipt_acc_tables[info->table_nr].netmask,
636 + src_ip, dst_ip, size, &ipt_acc_tables[info->table_nr].itemcount);
637 + spin_unlock_bh(&ipt_acc_lock);
638 + return IPT_CONTINUE;
641 + /* 24 bit network */
642 + if (ipt_acc_tables[info->table_nr].depth == 2) {
643 + ipt_acc_depth2_insert(
644 + (struct ipt_acc_mask_8 *)ipt_acc_tables[info->table_nr].data,
645 + ipt_acc_tables[info->table_nr].ip,
646 + ipt_acc_tables[info->table_nr].netmask,
647 + src_ip, dst_ip, size, &ipt_acc_tables[info->table_nr].itemcount);
648 + spin_unlock_bh(&ipt_acc_lock);
649 + return IPT_CONTINUE;
652 + printk("ACCOUNT: ipt_acc_target: Unable to process packet. "
653 + "Table id %u. IPs %u.%u.%u.%u/%u.%u.%u.%u\n",
654 + info->table_nr, NIPQUAD(src_ip), NIPQUAD(dst_ip));
656 + spin_unlock_bh(&ipt_acc_lock);
657 + return IPT_CONTINUE;
661 + Functions dealing with "handles":
662 + Handles are snapshots of a accounting state.
664 + read snapshots are only for debugging the code
665 + and are very expensive concerning speed/memory
666 + compared to read_and_flush.
668 + The functions aren't protected by spinlocks themselves
669 + as this is done in the ioctl part of the code.
673 + Find a free handle slot. Normally only one should be used,
674 + but there could be two or more applications accessing the data
677 +static int ipt_acc_handle_find_slot(void)
680 + /* Insert new table */
681 + for (i = 0; i < ACCOUNT_MAX_HANDLES; i++) {
682 + /* Found free slot */
683 + if (ipt_acc_handles[i].data == NULL) {
684 + /* Don't "mark" data as used as we are protected by a spinlock
685 + by the calling function. handle_find_slot() is only a function
686 + to prevent code duplication. */
691 + /* No free slot found */
692 + printk("ACCOUNT: No free handle slot found (max: %u). "
693 + "Please increase ACCOUNT_MAX_HANDLES.\n", ACCOUNT_MAX_HANDLES);
697 +static int ipt_acc_handle_free(unsigned int handle)
699 + if (handle >= ACCOUNT_MAX_HANDLES) {
700 + printk("ACCOUNT: Invalid handle for ipt_acc_handle_free() specified:"
705 + ipt_acc_data_free(ipt_acc_handles[handle].data,
706 + ipt_acc_handles[handle].depth);
707 + memset (&ipt_acc_handles[handle], 0, sizeof (struct ipt_acc_handle));
711 +/* Prepare data for read without flush. Use only for debugging!
712 + Real applications should use read&flush as it's way more efficent */
713 +static int ipt_acc_handle_prepare_read(char *tablename,
714 + struct ipt_acc_handle *dest, u_int32_t *count)
717 + unsigned char depth;
719 + for (table_nr = 0; table_nr < ACCOUNT_MAX_TABLES; table_nr++)
720 + if (strncmp(ipt_acc_tables[table_nr].name, tablename,
721 + ACCOUNT_TABLE_NAME_LEN) == 0)
724 + if (table_nr == ACCOUNT_MAX_TABLES) {
725 + printk("ACCOUNT: ipt_acc_handle_prepare_read(): "
726 + "Table %s not found\n", tablename);
730 + /* Fill up handle structure */
731 + dest->ip = ipt_acc_tables[table_nr].ip;
732 + dest->depth = ipt_acc_tables[table_nr].depth;
733 + dest->itemcount = ipt_acc_tables[table_nr].itemcount;
735 + /* allocate "root" table */
736 + if ((dest->data = ipt_acc_zalloc_page()) == NULL) {
737 + printk("ACCOUNT: out of memory for root table "
738 + "in ipt_acc_handle_prepare_read()\n");
742 + /* Recursive copy of complete data structure */
743 + depth = dest->depth;
746 + ipt_acc_tables[table_nr].data,
747 + sizeof(struct ipt_acc_mask_24));
748 + } else if (depth == 1) {
749 + struct ipt_acc_mask_16 *src_16 =
750 + (struct ipt_acc_mask_16 *)ipt_acc_tables[table_nr].data;
751 + struct ipt_acc_mask_16 *network_16 =
752 + (struct ipt_acc_mask_16 *)dest->data;
755 + for (b = 0; b <= 255; b++) {
756 + if (src_16->mask_24[b]) {
757 + if ((network_16->mask_24[b] =
758 + ipt_acc_zalloc_page()) == NULL) {
759 + printk("ACCOUNT: out of memory during copy of 16 bit "
760 + "network in ipt_acc_handle_prepare_read()\n");
761 + ipt_acc_data_free(dest->data, depth);
765 + memcpy(network_16->mask_24[b], src_16->mask_24[b],
766 + sizeof(struct ipt_acc_mask_24));
769 + } else if(depth == 2) {
770 + struct ipt_acc_mask_8 *src_8 =
771 + (struct ipt_acc_mask_8 *)ipt_acc_tables[table_nr].data;
772 + struct ipt_acc_mask_8 *network_8 =
773 + (struct ipt_acc_mask_8 *)dest->data;
774 + struct ipt_acc_mask_16 *src_16, *network_16;
777 + for (a = 0; a <= 255; a++) {
778 + if (src_8->mask_16[a]) {
779 + if ((network_8->mask_16[a] =
780 + ipt_acc_zalloc_page()) == NULL) {
781 + printk("ACCOUNT: out of memory during copy of 24 bit network"
782 + " in ipt_acc_handle_prepare_read()\n");
783 + ipt_acc_data_free(dest->data, depth);
787 + memcpy(network_8->mask_16[a], src_8->mask_16[a],
788 + sizeof(struct ipt_acc_mask_16));
790 + src_16 = src_8->mask_16[a];
791 + network_16 = network_8->mask_16[a];
793 + for (b = 0; b <= 255; b++) {
794 + if (src_16->mask_24[b]) {
795 + if ((network_16->mask_24[b] =
796 + ipt_acc_zalloc_page()) == NULL) {
797 + printk("ACCOUNT: out of memory during copy of 16 bit"
798 + " network in ipt_acc_handle_prepare_read()\n");
799 + ipt_acc_data_free(dest->data, depth);
803 + memcpy(network_16->mask_24[b], src_16->mask_24[b],
804 + sizeof(struct ipt_acc_mask_24));
811 + *count = ipt_acc_tables[table_nr].itemcount;
816 +/* Prepare data for read and flush it */
817 +static int ipt_acc_handle_prepare_read_flush(char *tablename,
818 + struct ipt_acc_handle *dest, u_int32_t *count)
821 + void *new_data_page;
823 + for (table_nr = 0; table_nr < ACCOUNT_MAX_TABLES; table_nr++)
824 + if (strncmp(ipt_acc_tables[table_nr].name, tablename,
825 + ACCOUNT_TABLE_NAME_LEN) == 0)
828 + if (table_nr == ACCOUNT_MAX_TABLES) {
829 + printk("ACCOUNT: ipt_acc_handle_prepare_read_flush(): "
830 + "Table %s not found\n", tablename);
834 + /* Try to allocate memory */
835 + if (!(new_data_page = ipt_acc_zalloc_page())) {
836 + printk("ACCOUNT: ipt_acc_handle_prepare_read_flush(): "
837 + "Out of memory!\n");
841 + /* Fill up handle structure */
842 + dest->ip = ipt_acc_tables[table_nr].ip;
843 + dest->depth = ipt_acc_tables[table_nr].depth;
844 + dest->itemcount = ipt_acc_tables[table_nr].itemcount;
845 + dest->data = ipt_acc_tables[table_nr].data;
846 + *count = ipt_acc_tables[table_nr].itemcount;
848 + /* "Flush" table data */
849 + ipt_acc_tables[table_nr].data = new_data_page;
850 + ipt_acc_tables[table_nr].itemcount = 0;
855 +/* Copy 8 bit network data into a prepared buffer.
856 + We only copy entries != 0 to increase performance.
858 +static int ipt_acc_handle_copy_data(void *to_user, unsigned long *to_user_pos,
859 + unsigned long *tmpbuf_pos,
860 + struct ipt_acc_mask_24 *data,
861 + u_int32_t net_ip, u_int32_t net_OR_mask)
863 + struct ipt_acc_handle_ip handle_ip;
864 + size_t handle_ip_size = sizeof (struct ipt_acc_handle_ip);
867 + for (i = 0; i <= 255; i++) {
868 + if (data->ip[i].src_packets || data->ip[i].dst_packets) {
869 + handle_ip.ip = net_ip | net_OR_mask | (i<<24);
871 + handle_ip.src_packets = data->ip[i].src_packets;
872 + handle_ip.src_bytes = data->ip[i].src_bytes;
873 + handle_ip.dst_packets = data->ip[i].dst_packets;
874 + handle_ip.dst_bytes = data->ip[i].dst_bytes;
876 + /* Temporary buffer full? Flush to userspace */
877 + if (*tmpbuf_pos+handle_ip_size >= PAGE_SIZE) {
878 + if (copy_to_user(to_user + *to_user_pos, ipt_acc_tmpbuf,
881 + *to_user_pos = *to_user_pos + *tmpbuf_pos;
884 + memcpy(ipt_acc_tmpbuf+*tmpbuf_pos, &handle_ip, handle_ip_size);
885 + *tmpbuf_pos += handle_ip_size;
892 +/* Copy the data from our internal structure
893 + We only copy entries != 0 to increase performance.
894 + Overwrites ipt_acc_tmpbuf.
896 +static int ipt_acc_handle_get_data(u_int32_t handle, void *to_user)
898 + unsigned long to_user_pos=0, tmpbuf_pos=0;
900 + unsigned char depth;
902 + if (handle >= ACCOUNT_MAX_HANDLES) {
903 + printk("ACCOUNT: invalid handle for ipt_acc_handle_get_data() "
904 + "specified: %u\n", handle);
908 + if (ipt_acc_handles[handle].data == NULL) {
909 + printk("ACCOUNT: handle %u is BROKEN: Contains no data\n", handle);
913 + net_ip = ipt_acc_handles[handle].ip;
914 + depth = ipt_acc_handles[handle].depth;
916 + /* 8 bit network */
918 + struct ipt_acc_mask_24 *network =
919 + (struct ipt_acc_mask_24*)ipt_acc_handles[handle].data;
920 + if (ipt_acc_handle_copy_data(to_user, &to_user_pos, &tmpbuf_pos,
921 + network, net_ip, 0))
924 + /* Flush remaining data to userspace */
926 + if (copy_to_user(to_user+to_user_pos, ipt_acc_tmpbuf, tmpbuf_pos))
932 + /* 16 bit network */
934 + struct ipt_acc_mask_16 *network_16 =
935 + (struct ipt_acc_mask_16*)ipt_acc_handles[handle].data;
937 + for (b = 0; b <= 255; b++) {
938 + if (network_16->mask_24[b]) {
939 + struct ipt_acc_mask_24 *network =
940 + (struct ipt_acc_mask_24*)network_16->mask_24[b];
941 + if (ipt_acc_handle_copy_data(to_user, &to_user_pos,
942 + &tmpbuf_pos, network, net_ip, (b << 16)))
947 + /* Flush remaining data to userspace */
949 + if (copy_to_user(to_user+to_user_pos, ipt_acc_tmpbuf, tmpbuf_pos))
955 + /* 24 bit network */
957 + struct ipt_acc_mask_8 *network_8 =
958 + (struct ipt_acc_mask_8*)ipt_acc_handles[handle].data;
960 + for (a = 0; a <= 255; a++) {
961 + if (network_8->mask_16[a]) {
962 + struct ipt_acc_mask_16 *network_16 =
963 + (struct ipt_acc_mask_16*)network_8->mask_16[a];
964 + for (b = 0; b <= 255; b++) {
965 + if (network_16->mask_24[b]) {
966 + struct ipt_acc_mask_24 *network =
967 + (struct ipt_acc_mask_24*)network_16->mask_24[b];
968 + if (ipt_acc_handle_copy_data(to_user,
969 + &to_user_pos, &tmpbuf_pos,
970 + network, net_ip, (a << 8) | (b << 16)))
977 + /* Flush remaining data to userspace */
979 + if (copy_to_user(to_user+to_user_pos, ipt_acc_tmpbuf, tmpbuf_pos))
988 +static int ipt_acc_set_ctl(struct sock *sk, int cmd,
989 + void *user, unsigned int len)
991 + struct ipt_acc_handle_sockopt handle;
994 + if (!capable(CAP_NET_ADMIN))
998 + case IPT_SO_SET_ACCOUNT_HANDLE_FREE:
999 + if (len != sizeof(struct ipt_acc_handle_sockopt)) {
1000 + printk("ACCOUNT: ipt_acc_set_ctl: wrong data size (%u != %zu) "
1001 + "for IPT_SO_SET_HANDLE_FREE\n",
1002 + len, sizeof(struct ipt_acc_handle_sockopt));
1006 + if (copy_from_user (&handle, user, len)) {
1007 + printk("ACCOUNT: ipt_acc_set_ctl: copy_from_user failed for "
1008 + "IPT_SO_SET_HANDLE_FREE\n");
1012 + down(&ipt_acc_userspace_mutex);
1013 + ret = ipt_acc_handle_free(handle.handle_nr);
1014 + up(&ipt_acc_userspace_mutex);
1016 + case IPT_SO_SET_ACCOUNT_HANDLE_FREE_ALL: {
1018 + down(&ipt_acc_userspace_mutex);
1019 + for (i = 0; i < ACCOUNT_MAX_HANDLES; i++)
1020 + ipt_acc_handle_free(i);
1021 + up(&ipt_acc_userspace_mutex);
1026 + printk("ACCOUNT: ipt_acc_set_ctl: unknown request %i\n", cmd);
1032 +static int ipt_acc_get_ctl(struct sock *sk, int cmd, void *user, int *len)
1034 + struct ipt_acc_handle_sockopt handle;
1035 + int ret = -EINVAL;
1037 + if (!capable(CAP_NET_ADMIN))
1041 + case IPT_SO_GET_ACCOUNT_PREPARE_READ_FLUSH:
1042 + case IPT_SO_GET_ACCOUNT_PREPARE_READ: {
1043 + struct ipt_acc_handle dest;
1045 + if (*len < sizeof(struct ipt_acc_handle_sockopt)) {
1046 + printk("ACCOUNT: ipt_acc_get_ctl: wrong data size (%u != %zu) "
1047 + "for IPT_SO_GET_ACCOUNT_PREPARE_READ/READ_FLUSH\n",
1048 + *len, sizeof(struct ipt_acc_handle_sockopt));
1052 + if (copy_from_user (&handle, user,
1053 + sizeof(struct ipt_acc_handle_sockopt))) {
1058 + spin_lock_bh(&ipt_acc_lock);
1059 + if (cmd == IPT_SO_GET_ACCOUNT_PREPARE_READ_FLUSH)
1060 + ret = ipt_acc_handle_prepare_read_flush(
1061 + handle.name, &dest, &handle.itemcount);
1063 + ret = ipt_acc_handle_prepare_read(
1064 + handle.name, &dest, &handle.itemcount);
1065 + spin_unlock_bh(&ipt_acc_lock);
1066 + // Error occured during prepare_read?
1070 + /* Allocate a userspace handle */
1071 + down(&ipt_acc_userspace_mutex);
1072 + if ((handle.handle_nr = ipt_acc_handle_find_slot()) == -1) {
1073 + ipt_acc_data_free(dest.data, dest.depth);
1074 + up(&ipt_acc_userspace_mutex);
1077 + memcpy(&ipt_acc_handles[handle.handle_nr], &dest,
1078 + sizeof(struct ipt_acc_handle));
1079 + up(&ipt_acc_userspace_mutex);
1081 + if (copy_to_user(user, &handle,
1082 + sizeof(struct ipt_acc_handle_sockopt))) {
1089 + case IPT_SO_GET_ACCOUNT_GET_DATA:
1090 + if (*len < sizeof(struct ipt_acc_handle_sockopt)) {
1091 + printk("ACCOUNT: ipt_acc_get_ctl: wrong data size (%u != %zu)"
1092 + " for IPT_SO_GET_ACCOUNT_PREPARE_READ/READ_FLUSH\n",
1093 + *len, sizeof(struct ipt_acc_handle_sockopt));
1097 + if (copy_from_user (&handle, user,
1098 + sizeof(struct ipt_acc_handle_sockopt))) {
1103 + if (handle.handle_nr >= ACCOUNT_MAX_HANDLES) {
1108 + if (*len < ipt_acc_handles[handle.handle_nr].itemcount
1109 + * sizeof(struct ipt_acc_handle_ip)) {
1110 + printk("ACCOUNT: ipt_acc_get_ctl: not enough space (%u < %zu)"
1111 + " to store data from IPT_SO_GET_ACCOUNT_GET_DATA\n",
1112 + *len, ipt_acc_handles[handle.handle_nr].itemcount
1113 + * sizeof(struct ipt_acc_handle_ip));
1118 + down(&ipt_acc_userspace_mutex);
1119 + ret = ipt_acc_handle_get_data(handle.handle_nr, user);
1120 + up(&ipt_acc_userspace_mutex);
1122 + printk("ACCOUNT: ipt_acc_get_ctl: ipt_acc_handle_get_data"
1123 + " failed for handle %u\n", handle.handle_nr);
1129 + case IPT_SO_GET_ACCOUNT_GET_HANDLE_USAGE: {
1131 + if (*len < sizeof(struct ipt_acc_handle_sockopt)) {
1132 + printk("ACCOUNT: ipt_acc_get_ctl: wrong data size (%u != %zu)"
1133 + " for IPT_SO_GET_ACCOUNT_GET_HANDLE_USAGE\n",
1134 + *len, sizeof(struct ipt_acc_handle_sockopt));
1138 + /* Find out how many handles are in use */
1139 + handle.itemcount = 0;
1140 + down(&ipt_acc_userspace_mutex);
1141 + for (i = 0; i < ACCOUNT_MAX_HANDLES; i++)
1142 + if (ipt_acc_handles[i].data)
1143 + handle.itemcount++;
1144 + up(&ipt_acc_userspace_mutex);
1146 + if (copy_to_user(user, &handle,
1147 + sizeof(struct ipt_acc_handle_sockopt))) {
1154 + case IPT_SO_GET_ACCOUNT_GET_TABLE_NAMES: {
1155 + u_int32_t size = 0, i, name_len;
1158 + spin_lock_bh(&ipt_acc_lock);
1160 + /* Determine size of table names */
1161 + for (i = 0; i < ACCOUNT_MAX_TABLES; i++) {
1162 + if (ipt_acc_tables[i].name[0] != 0)
1163 + size += strlen (ipt_acc_tables[i].name) + 1;
1165 + size += 1; /* Terminating NULL character */
1167 + if (*len < size || size > PAGE_SIZE) {
1168 + spin_unlock_bh(&ipt_acc_lock);
1169 + printk("ACCOUNT: ipt_acc_get_ctl: not enough space (%u < %u < %lu)"
1170 + " to store table names\n", *len, size, PAGE_SIZE);
1174 + /* Copy table names to userspace */
1175 + tnames = ipt_acc_tmpbuf;
1176 + for (i = 0; i < ACCOUNT_MAX_TABLES; i++) {
1177 + if (ipt_acc_tables[i].name[0] != 0) {
1178 + name_len = strlen (ipt_acc_tables[i].name) + 1;
1179 + memcpy(tnames, ipt_acc_tables[i].name, name_len);
1180 + tnames += name_len;
1183 + spin_unlock_bh(&ipt_acc_lock);
1185 + /* Terminating NULL character */
1188 + /* Transfer to userspace */
1189 + if (copy_to_user(user, ipt_acc_tmpbuf, size))
1196 + printk("ACCOUNT: ipt_acc_get_ctl: unknown request %i\n", cmd);
1202 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
1203 +static struct xt_target xt_acc_reg = {
1205 +static struct ipt_target ipt_acc_reg = {
1207 + .name = "ACCOUNT",
1208 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
1209 + .family = AF_INET,
1211 + .target = ipt_acc_target,
1212 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
1213 + .targetsize = sizeof(struct ipt_acc_info),
1215 + .checkentry = ipt_acc_checkentry,
1216 + .destroy = ipt_acc_destroy,
1220 +static struct nf_sockopt_ops ipt_acc_sockopts = {
1222 + .set_optmin = IPT_SO_SET_ACCOUNT_HANDLE_FREE,
1223 + .set_optmax = IPT_SO_SET_ACCOUNT_MAX+1,
1224 + .set = ipt_acc_set_ctl,
1225 + .get_optmin = IPT_SO_GET_ACCOUNT_PREPARE_READ,
1226 + .get_optmax = IPT_SO_GET_ACCOUNT_MAX+1,
1227 + .get = ipt_acc_get_ctl
1230 +static int __init init(void)
1232 + init_MUTEX(&ipt_acc_userspace_mutex);
1234 + if ((ipt_acc_tables =
1235 + kmalloc(ACCOUNT_MAX_TABLES *
1236 + sizeof(struct ipt_acc_table), GFP_KERNEL)) == NULL) {
1237 + printk("ACCOUNT: Out of memory allocating account_tables structure");
1238 + goto error_cleanup;
1240 + memset(ipt_acc_tables, 0,
1241 + ACCOUNT_MAX_TABLES * sizeof(struct ipt_acc_table));
1243 + if ((ipt_acc_handles =
1244 + kmalloc(ACCOUNT_MAX_HANDLES *
1245 + sizeof(struct ipt_acc_handle), GFP_KERNEL)) == NULL) {
1246 + printk("ACCOUNT: Out of memory allocating account_handles structure");
1247 + goto error_cleanup;
1249 + memset(ipt_acc_handles, 0,
1250 + ACCOUNT_MAX_HANDLES * sizeof(struct ipt_acc_handle));
1252 + /* Allocate one page as temporary storage */
1253 + if ((ipt_acc_tmpbuf = (void*)__get_free_page(GFP_KERNEL)) == NULL) {
1254 + printk("ACCOUNT: Out of memory for temporary buffer page\n");
1255 + goto error_cleanup;
1258 + /* Register setsockopt */
1259 + if (nf_register_sockopt(&ipt_acc_sockopts) < 0) {
1260 + printk("ACCOUNT: Can't register sockopts. Aborting\n");
1261 + goto error_cleanup;
1264 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
1265 + if (xt_register_target(&xt_acc_reg))
1267 + if (ipt_register_target(&ipt_acc_reg))
1269 + goto error_cleanup;
1274 + if(ipt_acc_tables)
1275 + kfree(ipt_acc_tables);
1276 + if(ipt_acc_handles)
1277 + kfree(ipt_acc_handles);
1278 + if (ipt_acc_tmpbuf)
1279 + free_page((unsigned long)ipt_acc_tmpbuf);
1284 +static void __exit fini(void)
1286 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
1287 + xt_unregister_target(&xt_acc_reg);
1289 + ipt_unregister_target(&ipt_acc_reg);
1292 + nf_unregister_sockopt(&ipt_acc_sockopts);
1294 + kfree(ipt_acc_tables);
1295 + kfree(ipt_acc_handles);
1296 + free_page((unsigned long)ipt_acc_tmpbuf);
1301 +MODULE_LICENSE("GPL");
1302 diff -uprN linux1/net/ipv4/netfilter/Kconfig.ladd linux-2.6/net/ipv4/netfilter/Kconfig.ladd
1303 --- linux1/net/ipv4/netfilter/Kconfig 1970-01-01 01:00:00.000000000 +0100
1304 +++ linux-2.6/net/ipv4/netfilter/Kconfig 2007-12-14 10:42:16.000000000 +0100
1305 @@ -647,5 +647,26 @@
1306 If you want to compile it as a module, say M here and read
1307 <file:Documentation/modules.txt>. If unsure, say `N'.
1309 +config IP_NF_TARGET_ACCOUNT
1310 + tristate "ACCOUNT target support"
1311 + depends on IP_NF_IPTABLES
1313 + The ACCOUNT target is a high performance accounting system for local networks.
1314 + It takes two parameters: --addr network/netmask and --tname NAME.
1316 + --addr is the subnet which is accounted for
1317 + --tname is the table name where the information is stored
1319 + The data can be queried later using the libipt_ACCOUNT userspace library
1320 + or by the "iptaccount" tool which is part of the libipt_ACCOUNT package.
1322 + A special subnet is "0.0.0.0/0": All data is stored in the src_bytes
1323 + and src_packets structure of slot "0". This is useful if you want
1324 + to account the overall traffic to/from your internet provider.
1326 + For more information go to:
1327 + http://www.intra2net.com/de/produkte/opensource/ipt_account/
1329 + To compile it as a module, choose M here. If unsure, say N.
1332 diff -uprN linux1/net/ipv4/netfilter/Makefile.ladd linux-2.6/net/ipv4/netfilter/Makefile.ladd
1333 --- linux1/net/ipv4/netfilter/Makefile 1971-01-01 01:00:00.000000000 +0100
1334 +++ linux-2.6/net/ipv4/netfilter/Makefile 2007-12-14 10:42:16.000000000 +0100
1336 +obj-$(CONFIG_IP_NF_TARGET_ACCOUNT) += ipt_ACCOUNT.o
1337 diff -ur linux-2.6.19.1/include/linux/netfilter_ipv4/ip_tables.h linux-2.6.19.1.ipt_ACCOUNT/include/linux/netfilter_ipv4/ip_tables.h
1338 --- linux-2.6.19.1/include/linux/netfilter_ipv4/ip_tables.h Mon Dec 11 20:32:53 2006
1339 +++ linux-2.6.19.1.ipt_ACCOUNT/include/linux/netfilter_ipv4/ip_tables.h Wed Dec 20 15:56:35 2006
1340 @@ -111,11 +111,22 @@
1341 #define IPT_SO_SET_ADD_COUNTERS (IPT_BASE_CTL + 1)
1342 #define IPT_SO_SET_MAX IPT_SO_SET_ADD_COUNTERS
1344 +#define IPT_SO_SET_ACCOUNT_HANDLE_FREE (IPT_BASE_CTL + 2)
1345 +#define IPT_SO_SET_ACCOUNT_HANDLE_FREE_ALL (IPT_BASE_CTL + 3)
1346 +#define IPT_SO_SET_ACCOUNT_MAX IPT_SO_SET_ACCOUNT_HANDLE_FREE_ALL
1348 #define IPT_SO_GET_INFO (IPT_BASE_CTL)
1349 #define IPT_SO_GET_ENTRIES (IPT_BASE_CTL + 1)
1350 #define IPT_SO_GET_REVISION_MATCH (IPT_BASE_CTL + 2)
1351 #define IPT_SO_GET_REVISION_TARGET (IPT_BASE_CTL + 3)
1352 #define IPT_SO_GET_MAX IPT_SO_GET_REVISION_TARGET
1354 +#define IPT_SO_GET_ACCOUNT_PREPARE_READ (IPT_BASE_CTL + 4)
1355 +#define IPT_SO_GET_ACCOUNT_PREPARE_READ_FLUSH (IPT_BASE_CTL + 5)
1356 +#define IPT_SO_GET_ACCOUNT_GET_DATA (IPT_BASE_CTL + 6)
1357 +#define IPT_SO_GET_ACCOUNT_GET_HANDLE_USAGE (IPT_BASE_CTL + 7)
1358 +#define IPT_SO_GET_ACCOUNT_GET_TABLE_NAMES (IPT_BASE_CTL + 8)
1359 +#define IPT_SO_GET_ACCOUNT_MAX IPT_SO_GET_ACCOUNT_GET_TABLE_NAMES
1361 #define IPT_CONTINUE XT_CONTINUE
1362 #define IPT_RETURN XT_RETURN