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 *
6 * Copyright (C) 2004-2011 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 #include <linux/module.h>
16 #include <linux/version.h>
17 #include <linux/skbuff.h>
22 #include <linux/netfilter_ipv4/ip_tables.h>
24 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
25 #include <linux/semaphore.h>
27 #include <asm/semaphore.h>
30 #include <linux/kernel.h>
32 #include <linux/string.h>
33 #include <linux/spinlock.h>
34 #include <asm/uaccess.h>
36 #include <net/route.h>
37 #include <linux/netfilter_ipv4/ipt_ACCOUNT.h>
42 #define DEBUGP(format, args...)
45 #if (PAGE_SIZE < 4096)
46 #error "ipt_ACCOUNT needs at least a PAGE_SIZE of 4096"
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;
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;
58 /* Allocates a page and clears it */
59 static void *ipt_acc_zalloc_page(void)
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);
65 memset (mem, 0, PAGE_SIZE);
71 /* Recursive free of all data structures */
72 static void ipt_acc_data_free(void *data, unsigned char depth)
78 /* Free for 8 bit network */
80 free_page((unsigned long)data);
84 /* Free for 16 bit network */
86 struct ipt_acc_mask_16 *mask_16 = (struct ipt_acc_mask_16 *)data;
88 for (b=0; b <= 255; b++) {
89 if (mask_16->mask_24[b]) {
90 free_page((unsigned long)mask_16->mask_24[b]);
93 free_page((unsigned long)data);
97 /* Free for 24 bit network */
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];
105 for (b=0; b <= 255; b++) {
106 if (mask_16->mask_24[b]) {
107 free_page((unsigned long)mask_16->mask_24[b]);
110 free_page((unsigned long)mask_16);
113 free_page((unsigned long)data);
117 printk("ACCOUNT: ipt_acc_data_free called with unknown depth: %d\n",
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)
128 DEBUGP("ACCOUNT: ipt_acc_table_insert: %s, %pI4/%pI4\n",
129 name, &ip, &netmask);
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 - "
137 &ipt_acc_tables[i].ip,
138 &ipt_acc_tables[i].netmask);
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: %pI4/%pI4\n",
144 name, &ipt_acc_tables[i].ip,
145 &ipt_acc_tables[i].netmask);
149 ipt_acc_tables[i].refcount++;
150 DEBUGP("ACCOUNT: Refcount: %d\n", ipt_acc_tables[i].refcount);
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;
161 int j; /* needs to be signed, otherwise we risk endless loop */
163 DEBUGP("ACCOUNT: Found free slot: %d\n", i);
164 strncpy (ipt_acc_tables[i].name, name, ACCOUNT_TABLE_NAME_LEN-1);
166 ipt_acc_tables[i].ip = ip;
167 ipt_acc_tables[i].netmask = netmask;
169 /* Calculate netsize */
170 calc_mask = htonl(netmask);
171 for (j = 31; j >= 0; j--) {
172 if (calc_mask&(1<<j))
178 /* Calculate depth from netsize */
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;
186 DEBUGP("ACCOUNT: calculated netsize: %u -> "
187 "ipt_acc_table depth %u\n", netsize,
188 ipt_acc_tables[i].depth);
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));
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);
209 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
210 static int ipt_acc_checkentry(const struct xt_tgchk_param *par)
211 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
212 static bool ipt_acc_checkentry(const struct xt_tgchk_param *par)
214 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
215 static bool ipt_acc_checkentry(const char *tablename,
217 static int ipt_acc_checkentry(const char *tablename,
219 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
222 const struct ipt_entry *e,
224 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
225 const struct xt_target *target,
228 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
229 unsigned int targinfosize,
231 unsigned int hook_mask)
232 #endif /* >= 2.6.28 */
234 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
235 struct ipt_acc_info *info = par->targinfo;
237 struct ipt_acc_info *info = targinfo;
241 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
242 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_acc_info))) {
243 DEBUGP("ACCOUNT: targinfosize %u != %u\n",
244 targinfosize, IPT_ALIGN(sizeof(struct ipt_acc_info)));
249 spin_lock_bh(&ipt_acc_lock);
250 table_nr = ipt_acc_table_insert(info->table_name, info->net_ip,
252 spin_unlock_bh(&ipt_acc_lock);
254 if (table_nr == -1) {
255 printk("ACCOUNT: Table insert problem. Aborting\n");
256 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
258 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
264 /* Table nr caching so we don't have to do an extra string compare
266 info->table_nr = table_nr;
269 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
271 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
278 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
279 static void ipt_acc_destroy(const struct xt_tgdtor_param *par)
281 static void ipt_acc_destroy(
282 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
283 const struct xt_target *target,
285 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
289 unsigned int targinfosize)
291 #endif /* >= 2.6.28 */
294 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
295 struct ipt_acc_info *info = par->targinfo;
297 struct ipt_acc_info *info = targinfo;
300 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
301 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_acc_info))) {
302 DEBUGP("ACCOUNT: targinfosize %u != %u\n",
303 targinfosize, IPT_ALIGN(sizeof(struct ipt_acc_info)));
307 spin_lock_bh(&ipt_acc_lock);
309 DEBUGP("ACCOUNT: ipt_acc_deleteentry called for table: %s (#%d)\n",
310 info->table_name, info->table_nr);
312 info->table_nr = -1; /* Set back to original state */
315 for (i = 0; i < ACCOUNT_MAX_TABLES; i++) {
316 if (strncmp(ipt_acc_tables[i].name, info->table_name,
317 ACCOUNT_TABLE_NAME_LEN) == 0) {
318 DEBUGP("ACCOUNT: Found table at slot: %d\n", i);
320 ipt_acc_tables[i].refcount--;
321 DEBUGP("ACCOUNT: Refcount left: %d\n",
322 ipt_acc_tables[i].refcount);
324 /* Table not needed anymore? */
325 if (ipt_acc_tables[i].refcount == 0) {
326 DEBUGP("ACCOUNT: Destroying table at slot: %d\n", i);
327 ipt_acc_data_free(ipt_acc_tables[i].data,
328 ipt_acc_tables[i].depth);
329 memset(&ipt_acc_tables[i], 0,
330 sizeof(struct ipt_acc_table));
333 spin_unlock_bh(&ipt_acc_lock);
338 /* Table not found */
339 printk("ACCOUNT: Table %s not found for destroy\n", info->table_name);
340 spin_unlock_bh(&ipt_acc_lock);
343 static void ipt_acc_depth0_insert(struct ipt_acc_mask_24 *mask_24,
344 u_int32_t net_ip, u_int32_t netmask,
345 u_int32_t src_ip, u_int32_t dst_ip,
346 u_int32_t size, u_int32_t *itemcount)
348 unsigned char is_src = 0, is_dst = 0, src_slot, dst_slot;
349 char is_src_new_ip = 0, is_dst_new_ip = 0; /* Check if this entry is new */
351 DEBUGP("ACCOUNT: ipt_acc_depth0_insert: %pI4/%pI4 "
352 "for net %pI4/%pI4, size: %u\n", &src_ip,
353 &dst_ip, &net_ip, &netmask, size);
355 /* Check if src/dst is inside our network. */
356 /* Special: net_ip = 0.0.0.0/0 gets stored as src in slot 0 */
359 if ((net_ip&netmask) == (src_ip&netmask))
361 if ((net_ip&netmask) == (dst_ip&netmask) && netmask)
364 if (!is_src && !is_dst) {
365 DEBUGP("ACCOUNT: Skipping packet %pI4/%pI4 "
366 "for net %pI4/%pI4\n", &src_ip,
367 &dst_ip, &net_ip, &netmask);
371 /* Calculate array positions */
372 src_slot = (unsigned char)((src_ip&0xFF000000) >> 24);
373 dst_slot = (unsigned char)((dst_ip&0xFF000000) >> 24);
375 /* Increase size counters */
377 /* Calculate network slot */
378 DEBUGP("ACCOUNT: Calculated SRC 8 bit network slot: %d\n", src_slot);
379 if (!mask_24->ip[src_slot].src_packets
380 && !mask_24->ip[src_slot].dst_packets)
383 mask_24->ip[src_slot].src_packets++;
384 mask_24->ip[src_slot].src_bytes+=size;
387 DEBUGP("ACCOUNT: Calculated DST 8 bit network slot: %d\n", dst_slot);
388 if (!mask_24->ip[dst_slot].src_packets
389 && !mask_24->ip[dst_slot].dst_packets)
392 mask_24->ip[dst_slot].dst_packets++;
393 mask_24->ip[dst_slot].dst_bytes+=size;
396 /* Increase itemcounter */
397 DEBUGP("ACCOUNT: Itemcounter before: %d\n", *itemcount);
398 if (src_slot == dst_slot) {
399 if (is_src_new_ip || is_dst_new_ip) {
400 DEBUGP("ACCOUNT: src_slot == dst_slot: %d, %d\n",
401 is_src_new_ip, is_dst_new_ip);
406 DEBUGP("ACCOUNT: New src_ip: %pI4\n", &src_ip);
410 DEBUGP("ACCOUNT: New dst_ip: %pI4\n", &dst_ip);
414 DEBUGP("ACCOUNT: Itemcounter after: %d\n", *itemcount);
417 static void ipt_acc_depth1_insert(struct ipt_acc_mask_16 *mask_16,
418 u_int32_t net_ip, u_int32_t netmask,
419 u_int32_t src_ip, u_int32_t dst_ip,
420 u_int32_t size, u_int32_t *itemcount)
422 /* Do we need to process src IP? */
423 if ((net_ip&netmask) == (src_ip&netmask)) {
424 unsigned char slot = (unsigned char)((src_ip&0x00FF0000) >> 16);
425 DEBUGP("ACCOUNT: Calculated SRC 16 bit network slot: %d\n", slot);
427 /* Do we need to create a new mask_24 bucket? */
428 if (!mask_16->mask_24[slot] && (mask_16->mask_24[slot] =
429 ipt_acc_zalloc_page()) == NULL) {
430 printk("ACCOUNT: Can't process packet because out of memory!\n");
434 ipt_acc_depth0_insert((struct ipt_acc_mask_24 *)mask_16->mask_24[slot],
435 net_ip, netmask, src_ip, 0, size, itemcount);
438 /* Do we need to process dst IP? */
439 if ((net_ip&netmask) == (dst_ip&netmask)) {
440 unsigned char slot = (unsigned char)((dst_ip&0x00FF0000) >> 16);
441 DEBUGP("ACCOUNT: Calculated DST 16 bit network slot: %d\n", slot);
443 /* Do we need to create a new mask_24 bucket? */
444 if (!mask_16->mask_24[slot] && (mask_16->mask_24[slot]
445 = ipt_acc_zalloc_page()) == NULL) {
446 printk("ACCOUT: Can't process packet because out of memory!\n");
450 ipt_acc_depth0_insert((struct ipt_acc_mask_24 *)mask_16->mask_24[slot],
451 net_ip, netmask, 0, dst_ip, size, itemcount);
455 static void ipt_acc_depth2_insert(struct ipt_acc_mask_8 *mask_8,
456 u_int32_t net_ip, u_int32_t netmask,
457 u_int32_t src_ip, u_int32_t dst_ip,
458 u_int32_t size, u_int32_t *itemcount)
460 /* Do we need to process src IP? */
461 if ((net_ip&netmask) == (src_ip&netmask)) {
462 unsigned char slot = (unsigned char)((src_ip&0x0000FF00) >> 8);
463 DEBUGP("ACCOUNT: Calculated SRC 24 bit network slot: %d\n", slot);
465 /* Do we need to create a new mask_24 bucket? */
466 if (!mask_8->mask_16[slot] && (mask_8->mask_16[slot]
467 = ipt_acc_zalloc_page()) == NULL) {
468 printk("ACCOUNT: Can't process packet because out of memory!\n");
472 ipt_acc_depth1_insert((struct ipt_acc_mask_16 *)mask_8->mask_16[slot],
473 net_ip, netmask, src_ip, 0, size, itemcount);
476 /* Do we need to process dst IP? */
477 if ((net_ip&netmask) == (dst_ip&netmask)) {
478 unsigned char slot = (unsigned char)((dst_ip&0x0000FF00) >> 8);
479 DEBUGP("ACCOUNT: Calculated DST 24 bit network slot: %d\n", slot);
481 /* Do we need to create a new mask_24 bucket? */
482 if (!mask_8->mask_16[slot] && (mask_8->mask_16[slot]
483 = ipt_acc_zalloc_page()) == NULL) {
484 printk("ACCOUNT: Can't process packet because out of memory!\n");
488 ipt_acc_depth1_insert((struct ipt_acc_mask_16 *)mask_8->mask_16[slot],
489 net_ip, netmask, 0, dst_ip, size, itemcount);
493 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
494 static unsigned int ipt_acc_target(struct sk_buff *skb, const struct xt_action_param *par)
495 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
496 static unsigned int ipt_acc_target(struct sk_buff *skb, const struct xt_target_param *par)
498 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
499 static unsigned int ipt_acc_target(struct sk_buff *skb,
501 static unsigned int ipt_acc_target(struct sk_buff **pskb,
503 const struct net_device *in,
504 const struct net_device *out,
505 unsigned int hooknum,
506 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
507 const struct xt_target *target,
509 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
510 const void *targinfo)
512 const void *targinfo,
517 const struct ipt_acc_info *info =
518 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
521 (const struct ipt_acc_info *)targinfo;
524 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
525 u_int32_t src_ip = ip_hdr(skb)->saddr;
526 u_int32_t dst_ip = ip_hdr(skb)->daddr;
527 u_int32_t size = ntohs(ip_hdr(skb)->tot_len);
529 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
530 u_int32_t src_ip = ip_hdr(*pskb)->saddr;
531 u_int32_t dst_ip = ip_hdr(*pskb)->daddr;
532 u_int32_t size = ntohs(ip_hdr(*pskb)->tot_len);
534 u_int32_t src_ip = (*pskb)->nh.iph->saddr;
535 u_int32_t dst_ip = (*pskb)->nh.iph->daddr;
536 u_int32_t size = ntohs((*pskb)->nh.iph->tot_len);
540 spin_lock_bh(&ipt_acc_lock);
542 if (ipt_acc_tables[info->table_nr].name[0] == 0) {
543 printk("ACCOUNT: ipt_acc_target: Invalid table id %u. "
544 "IPs %pI4/%pI4\n", info->table_nr,
546 spin_unlock_bh(&ipt_acc_lock);
550 /* 8 bit network or "any" network */
551 if (ipt_acc_tables[info->table_nr].depth == 0) {
552 /* Count packet and check if the IP is new */
553 ipt_acc_depth0_insert(
554 (struct ipt_acc_mask_24 *)ipt_acc_tables[info->table_nr].data,
555 ipt_acc_tables[info->table_nr].ip,
556 ipt_acc_tables[info->table_nr].netmask,
557 src_ip, dst_ip, size, &ipt_acc_tables[info->table_nr].itemcount);
558 spin_unlock_bh(&ipt_acc_lock);
563 if (ipt_acc_tables[info->table_nr].depth == 1) {
564 ipt_acc_depth1_insert(
565 (struct ipt_acc_mask_16 *)ipt_acc_tables[info->table_nr].data,
566 ipt_acc_tables[info->table_nr].ip,
567 ipt_acc_tables[info->table_nr].netmask,
568 src_ip, dst_ip, size, &ipt_acc_tables[info->table_nr].itemcount);
569 spin_unlock_bh(&ipt_acc_lock);
574 if (ipt_acc_tables[info->table_nr].depth == 2) {
575 ipt_acc_depth2_insert(
576 (struct ipt_acc_mask_8 *)ipt_acc_tables[info->table_nr].data,
577 ipt_acc_tables[info->table_nr].ip,
578 ipt_acc_tables[info->table_nr].netmask,
579 src_ip, dst_ip, size, &ipt_acc_tables[info->table_nr].itemcount);
580 spin_unlock_bh(&ipt_acc_lock);
584 printk("ACCOUNT: ipt_acc_target: Unable to process packet. "
585 "Table id %u. IPs %pI4/%pI4\n",
586 info->table_nr, &src_ip, &dst_ip);
588 spin_unlock_bh(&ipt_acc_lock);
593 Functions dealing with "handles":
594 Handles are snapshots of a accounting state.
596 read snapshots are only for debugging the code
597 and are very expensive concerning speed/memory
598 compared to read_and_flush.
600 The functions aren't protected by spinlocks themselves
601 as this is done in the ioctl part of the code.
605 Find a free handle slot. Normally only one should be used,
606 but there could be two or more applications accessing the data
609 static int ipt_acc_handle_find_slot(void)
612 /* Insert new table */
613 for (i = 0; i < ACCOUNT_MAX_HANDLES; i++) {
614 /* Found free slot */
615 if (ipt_acc_handles[i].data == NULL) {
616 /* Don't "mark" data as used as we are protected by a spinlock
617 by the calling function. handle_find_slot() is only a function
618 to prevent code duplication. */
623 /* No free slot found */
624 printk("ACCOUNT: No free handle slot found (max: %u). "
625 "Please increase ACCOUNT_MAX_HANDLES.\n", ACCOUNT_MAX_HANDLES);
629 static int ipt_acc_handle_free(unsigned int handle)
631 if (handle >= ACCOUNT_MAX_HANDLES) {
632 printk("ACCOUNT: Invalid handle for ipt_acc_handle_free() specified:"
637 ipt_acc_data_free(ipt_acc_handles[handle].data,
638 ipt_acc_handles[handle].depth);
639 memset (&ipt_acc_handles[handle], 0, sizeof (struct ipt_acc_handle));
643 /* Prepare data for read without flush. Use only for debugging!
644 Real applications should use read&flush as it's way more efficent */
645 static int ipt_acc_handle_prepare_read(char *tablename,
646 struct ipt_acc_handle *dest, u_int32_t *count)
651 for (table_nr = 0; table_nr < ACCOUNT_MAX_TABLES; table_nr++)
652 if (strncmp(ipt_acc_tables[table_nr].name, tablename,
653 ACCOUNT_TABLE_NAME_LEN) == 0)
656 if (table_nr == ACCOUNT_MAX_TABLES) {
657 printk("ACCOUNT: ipt_acc_handle_prepare_read(): "
658 "Table %s not found\n", tablename);
662 /* Fill up handle structure */
663 dest->ip = ipt_acc_tables[table_nr].ip;
664 dest->depth = ipt_acc_tables[table_nr].depth;
665 dest->itemcount = ipt_acc_tables[table_nr].itemcount;
667 /* allocate "root" table */
668 if ((dest->data = ipt_acc_zalloc_page()) == NULL) {
669 printk("ACCOUNT: out of memory for root table "
670 "in ipt_acc_handle_prepare_read()\n");
674 /* Recursive copy of complete data structure */
678 ipt_acc_tables[table_nr].data,
679 sizeof(struct ipt_acc_mask_24));
680 } else if (depth == 1) {
681 struct ipt_acc_mask_16 *src_16 =
682 (struct ipt_acc_mask_16 *)ipt_acc_tables[table_nr].data;
683 struct ipt_acc_mask_16 *network_16 =
684 (struct ipt_acc_mask_16 *)dest->data;
687 for (b = 0; b <= 255; b++) {
688 if (src_16->mask_24[b]) {
689 if ((network_16->mask_24[b] =
690 ipt_acc_zalloc_page()) == NULL) {
691 printk("ACCOUNT: out of memory during copy of 16 bit "
692 "network in ipt_acc_handle_prepare_read()\n");
693 ipt_acc_data_free(dest->data, depth);
697 memcpy(network_16->mask_24[b], src_16->mask_24[b],
698 sizeof(struct ipt_acc_mask_24));
701 } else if(depth == 2) {
702 struct ipt_acc_mask_8 *src_8 =
703 (struct ipt_acc_mask_8 *)ipt_acc_tables[table_nr].data;
704 struct ipt_acc_mask_8 *network_8 =
705 (struct ipt_acc_mask_8 *)dest->data;
706 struct ipt_acc_mask_16 *src_16, *network_16;
709 for (a = 0; a <= 255; a++) {
710 if (src_8->mask_16[a]) {
711 if ((network_8->mask_16[a] =
712 ipt_acc_zalloc_page()) == NULL) {
713 printk("ACCOUNT: out of memory during copy of 24 bit network"
714 " in ipt_acc_handle_prepare_read()\n");
715 ipt_acc_data_free(dest->data, depth);
719 memcpy(network_8->mask_16[a], src_8->mask_16[a],
720 sizeof(struct ipt_acc_mask_16));
722 src_16 = src_8->mask_16[a];
723 network_16 = network_8->mask_16[a];
725 for (b = 0; b <= 255; b++) {
726 if (src_16->mask_24[b]) {
727 if ((network_16->mask_24[b] =
728 ipt_acc_zalloc_page()) == NULL) {
729 printk("ACCOUNT: out of memory during copy of 16 bit"
730 " network in ipt_acc_handle_prepare_read()\n");
731 ipt_acc_data_free(dest->data, depth);
735 memcpy(network_16->mask_24[b], src_16->mask_24[b],
736 sizeof(struct ipt_acc_mask_24));
743 *count = ipt_acc_tables[table_nr].itemcount;
748 /* Prepare data for read and flush it */
749 static int ipt_acc_handle_prepare_read_flush(char *tablename,
750 struct ipt_acc_handle *dest, u_int32_t *count)
755 for (table_nr = 0; table_nr < ACCOUNT_MAX_TABLES; table_nr++)
756 if (strncmp(ipt_acc_tables[table_nr].name, tablename,
757 ACCOUNT_TABLE_NAME_LEN) == 0)
760 if (table_nr == ACCOUNT_MAX_TABLES) {
761 printk("ACCOUNT: ipt_acc_handle_prepare_read_flush(): "
762 "Table %s not found\n", tablename);
766 /* Try to allocate memory */
767 if (!(new_data_page = ipt_acc_zalloc_page())) {
768 printk("ACCOUNT: ipt_acc_handle_prepare_read_flush(): "
773 /* Fill up handle structure */
774 dest->ip = ipt_acc_tables[table_nr].ip;
775 dest->depth = ipt_acc_tables[table_nr].depth;
776 dest->itemcount = ipt_acc_tables[table_nr].itemcount;
777 dest->data = ipt_acc_tables[table_nr].data;
778 *count = ipt_acc_tables[table_nr].itemcount;
780 /* "Flush" table data */
781 ipt_acc_tables[table_nr].data = new_data_page;
782 ipt_acc_tables[table_nr].itemcount = 0;
787 /* Copy 8 bit network data into a prepared buffer.
788 We only copy entries != 0 to increase performance.
790 static int ipt_acc_handle_copy_data(void *to_user, unsigned long *to_user_pos,
791 unsigned long *tmpbuf_pos,
792 struct ipt_acc_mask_24 *data,
793 u_int32_t net_ip, u_int32_t net_OR_mask)
795 struct ipt_acc_handle_ip handle_ip;
796 size_t handle_ip_size = sizeof (struct ipt_acc_handle_ip);
799 for (i = 0; i <= 255; i++) {
800 if (data->ip[i].src_packets || data->ip[i].dst_packets) {
801 handle_ip.ip = net_ip | net_OR_mask | (i<<24);
803 handle_ip.src_packets = data->ip[i].src_packets;
804 handle_ip.src_bytes = data->ip[i].src_bytes;
805 handle_ip.dst_packets = data->ip[i].dst_packets;
806 handle_ip.dst_bytes = data->ip[i].dst_bytes;
808 /* Temporary buffer full? Flush to userspace */
809 if (*tmpbuf_pos+handle_ip_size >= PAGE_SIZE) {
810 if (copy_to_user(to_user + *to_user_pos, ipt_acc_tmpbuf,
813 *to_user_pos = *to_user_pos + *tmpbuf_pos;
816 memcpy(ipt_acc_tmpbuf+*tmpbuf_pos, &handle_ip, handle_ip_size);
817 *tmpbuf_pos += handle_ip_size;
824 /* Copy the data from our internal structure
825 We only copy entries != 0 to increase performance.
826 Overwrites ipt_acc_tmpbuf.
828 static int ipt_acc_handle_get_data(u_int32_t handle, void *to_user)
830 unsigned long to_user_pos=0, tmpbuf_pos=0;
834 if (handle >= ACCOUNT_MAX_HANDLES) {
835 printk("ACCOUNT: invalid handle for ipt_acc_handle_get_data() "
836 "specified: %u\n", handle);
840 if (ipt_acc_handles[handle].data == NULL) {
841 printk("ACCOUNT: handle %u is BROKEN: Contains no data\n", handle);
845 net_ip = ipt_acc_handles[handle].ip;
846 depth = ipt_acc_handles[handle].depth;
850 struct ipt_acc_mask_24 *network =
851 (struct ipt_acc_mask_24*)ipt_acc_handles[handle].data;
852 if (ipt_acc_handle_copy_data(to_user, &to_user_pos, &tmpbuf_pos,
856 /* Flush remaining data to userspace */
858 if (copy_to_user(to_user+to_user_pos, ipt_acc_tmpbuf, tmpbuf_pos))
866 struct ipt_acc_mask_16 *network_16 =
867 (struct ipt_acc_mask_16*)ipt_acc_handles[handle].data;
869 for (b = 0; b <= 255; b++) {
870 if (network_16->mask_24[b]) {
871 struct ipt_acc_mask_24 *network =
872 (struct ipt_acc_mask_24*)network_16->mask_24[b];
873 if (ipt_acc_handle_copy_data(to_user, &to_user_pos,
874 &tmpbuf_pos, network, net_ip, (b << 16)))
879 /* Flush remaining data to userspace */
881 if (copy_to_user(to_user+to_user_pos, ipt_acc_tmpbuf, tmpbuf_pos))
889 struct ipt_acc_mask_8 *network_8 =
890 (struct ipt_acc_mask_8*)ipt_acc_handles[handle].data;
892 for (a = 0; a <= 255; a++) {
893 if (network_8->mask_16[a]) {
894 struct ipt_acc_mask_16 *network_16 =
895 (struct ipt_acc_mask_16*)network_8->mask_16[a];
896 for (b = 0; b <= 255; b++) {
897 if (network_16->mask_24[b]) {
898 struct ipt_acc_mask_24 *network =
899 (struct ipt_acc_mask_24*)network_16->mask_24[b];
900 if (ipt_acc_handle_copy_data(to_user,
901 &to_user_pos, &tmpbuf_pos,
902 network, net_ip, (a << 8) | (b << 16)))
909 /* Flush remaining data to userspace */
911 if (copy_to_user(to_user+to_user_pos, ipt_acc_tmpbuf, tmpbuf_pos))
920 static int ipt_acc_set_ctl(struct sock *sk, int cmd,
921 void *user, unsigned int len)
923 struct ipt_acc_handle_sockopt handle;
926 if (!capable(CAP_NET_ADMIN))
930 case IPT_SO_SET_ACCOUNT_HANDLE_FREE:
931 if (len != sizeof(struct ipt_acc_handle_sockopt)) {
932 printk("ACCOUNT: ipt_acc_set_ctl: wrong data size (%u != %zu) "
933 "for IPT_SO_SET_HANDLE_FREE\n",
934 len, sizeof(struct ipt_acc_handle_sockopt));
938 if (copy_from_user (&handle, user, len)) {
939 printk("ACCOUNT: ipt_acc_set_ctl: copy_from_user failed for "
940 "IPT_SO_SET_HANDLE_FREE\n");
944 down(&ipt_acc_userspace_mutex);
945 ret = ipt_acc_handle_free(handle.handle_nr);
946 up(&ipt_acc_userspace_mutex);
948 case IPT_SO_SET_ACCOUNT_HANDLE_FREE_ALL: {
950 down(&ipt_acc_userspace_mutex);
951 for (i = 0; i < ACCOUNT_MAX_HANDLES; i++)
952 ipt_acc_handle_free(i);
953 up(&ipt_acc_userspace_mutex);
958 printk("ACCOUNT: ipt_acc_set_ctl: unknown request %i\n", cmd);
964 static int ipt_acc_get_ctl(struct sock *sk, int cmd, void *user, int *len)
966 struct ipt_acc_handle_sockopt handle;
969 if (!capable(CAP_NET_ADMIN))
973 case IPT_SO_GET_ACCOUNT_PREPARE_READ_FLUSH:
974 case IPT_SO_GET_ACCOUNT_PREPARE_READ: {
975 struct ipt_acc_handle dest;
977 if (*len < sizeof(struct ipt_acc_handle_sockopt)) {
978 printk("ACCOUNT: ipt_acc_get_ctl: wrong data size (%u != %zu) "
979 "for IPT_SO_GET_ACCOUNT_PREPARE_READ/READ_FLUSH\n",
980 *len, sizeof(struct ipt_acc_handle_sockopt));
984 if (copy_from_user (&handle, user,
985 sizeof(struct ipt_acc_handle_sockopt))) {
990 spin_lock_bh(&ipt_acc_lock);
991 if (cmd == IPT_SO_GET_ACCOUNT_PREPARE_READ_FLUSH)
992 ret = ipt_acc_handle_prepare_read_flush(
993 handle.name, &dest, &handle.itemcount);
995 ret = ipt_acc_handle_prepare_read(
996 handle.name, &dest, &handle.itemcount);
997 spin_unlock_bh(&ipt_acc_lock);
998 // Error occured during prepare_read?
1002 /* Allocate a userspace handle */
1003 down(&ipt_acc_userspace_mutex);
1004 if ((handle.handle_nr = ipt_acc_handle_find_slot()) == -1) {
1005 ipt_acc_data_free(dest.data, dest.depth);
1006 up(&ipt_acc_userspace_mutex);
1009 memcpy(&ipt_acc_handles[handle.handle_nr], &dest,
1010 sizeof(struct ipt_acc_handle));
1011 up(&ipt_acc_userspace_mutex);
1013 if (copy_to_user(user, &handle,
1014 sizeof(struct ipt_acc_handle_sockopt))) {
1021 case IPT_SO_GET_ACCOUNT_GET_DATA:
1022 if (*len < sizeof(struct ipt_acc_handle_sockopt)) {
1023 printk("ACCOUNT: ipt_acc_get_ctl: wrong data size (%u != %zu)"
1024 " for IPT_SO_GET_ACCOUNT_PREPARE_READ/READ_FLUSH\n",
1025 *len, sizeof(struct ipt_acc_handle_sockopt));
1029 if (copy_from_user (&handle, user,
1030 sizeof(struct ipt_acc_handle_sockopt))) {
1035 if (handle.handle_nr >= ACCOUNT_MAX_HANDLES) {
1040 if (*len < ipt_acc_handles[handle.handle_nr].itemcount
1041 * sizeof(struct ipt_acc_handle_ip)) {
1042 printk("ACCOUNT: ipt_acc_get_ctl: not enough space (%u < %zu)"
1043 " to store data from IPT_SO_GET_ACCOUNT_GET_DATA\n",
1044 *len, ipt_acc_handles[handle.handle_nr].itemcount
1045 * sizeof(struct ipt_acc_handle_ip));
1050 down(&ipt_acc_userspace_mutex);
1051 ret = ipt_acc_handle_get_data(handle.handle_nr, user);
1052 up(&ipt_acc_userspace_mutex);
1054 printk("ACCOUNT: ipt_acc_get_ctl: ipt_acc_handle_get_data"
1055 " failed for handle %u\n", handle.handle_nr);
1061 case IPT_SO_GET_ACCOUNT_GET_HANDLE_USAGE: {
1063 if (*len < sizeof(struct ipt_acc_handle_sockopt)) {
1064 printk("ACCOUNT: ipt_acc_get_ctl: wrong data size (%u != %zu)"
1065 " for IPT_SO_GET_ACCOUNT_GET_HANDLE_USAGE\n",
1066 *len, sizeof(struct ipt_acc_handle_sockopt));
1070 /* Find out how many handles are in use */
1071 handle.itemcount = 0;
1072 down(&ipt_acc_userspace_mutex);
1073 for (i = 0; i < ACCOUNT_MAX_HANDLES; i++)
1074 if (ipt_acc_handles[i].data)
1076 up(&ipt_acc_userspace_mutex);
1078 if (copy_to_user(user, &handle,
1079 sizeof(struct ipt_acc_handle_sockopt))) {
1086 case IPT_SO_GET_ACCOUNT_GET_TABLE_NAMES: {
1087 u_int32_t size = 0, i, name_len;
1090 spin_lock_bh(&ipt_acc_lock);
1092 /* Determine size of table names */
1093 for (i = 0; i < ACCOUNT_MAX_TABLES; i++) {
1094 if (ipt_acc_tables[i].name[0] != 0)
1095 size += strlen (ipt_acc_tables[i].name) + 1;
1097 size += 1; /* Terminating NULL character */
1099 if (*len < size || size > PAGE_SIZE) {
1100 spin_unlock_bh(&ipt_acc_lock);
1101 printk("ACCOUNT: ipt_acc_get_ctl: not enough space (%u < %u < %lu)"
1102 " to store table names\n", *len, size, PAGE_SIZE);
1106 /* Copy table names to userspace */
1107 tnames = ipt_acc_tmpbuf;
1108 for (i = 0; i < ACCOUNT_MAX_TABLES; i++) {
1109 if (ipt_acc_tables[i].name[0] != 0) {
1110 name_len = strlen (ipt_acc_tables[i].name) + 1;
1111 memcpy(tnames, ipt_acc_tables[i].name, name_len);
1115 spin_unlock_bh(&ipt_acc_lock);
1117 /* Terminating NULL character */
1120 /* Transfer to userspace */
1121 if (copy_to_user(user, ipt_acc_tmpbuf, size))
1128 printk("ACCOUNT: ipt_acc_get_ctl: unknown request %i\n", cmd);
1134 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
1135 static struct xt_target xt_acc_reg = {
1137 static struct ipt_target ipt_acc_reg = {
1140 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
1143 .target = ipt_acc_target,
1144 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
1145 .targetsize = sizeof(struct ipt_acc_info),
1147 .checkentry = ipt_acc_checkentry,
1148 .destroy = ipt_acc_destroy,
1152 static struct nf_sockopt_ops ipt_acc_sockopts = {
1154 .set_optmin = IPT_SO_SET_ACCOUNT_HANDLE_FREE,
1155 .set_optmax = IPT_SO_SET_ACCOUNT_MAX+1,
1156 .set = ipt_acc_set_ctl,
1157 .get_optmin = IPT_SO_GET_ACCOUNT_PREPARE_READ,
1158 .get_optmax = IPT_SO_GET_ACCOUNT_MAX+1,
1159 .get = ipt_acc_get_ctl
1162 static int __init init(void)
1164 sema_init(&ipt_acc_userspace_mutex, 1);
1166 if ((ipt_acc_tables =
1167 kmalloc(ACCOUNT_MAX_TABLES *
1168 sizeof(struct ipt_acc_table), GFP_KERNEL)) == NULL) {
1169 printk("ACCOUNT: Out of memory allocating account_tables structure");
1172 memset(ipt_acc_tables, 0,
1173 ACCOUNT_MAX_TABLES * sizeof(struct ipt_acc_table));
1175 if ((ipt_acc_handles =
1176 kmalloc(ACCOUNT_MAX_HANDLES *
1177 sizeof(struct ipt_acc_handle), GFP_KERNEL)) == NULL) {
1178 printk("ACCOUNT: Out of memory allocating account_handles structure");
1181 memset(ipt_acc_handles, 0,
1182 ACCOUNT_MAX_HANDLES * sizeof(struct ipt_acc_handle));
1184 /* Allocate one page as temporary storage */
1185 if ((ipt_acc_tmpbuf = (void*)__get_free_page(GFP_KERNEL)) == NULL) {
1186 printk("ACCOUNT: Out of memory for temporary buffer page\n");
1190 /* Register setsockopt */
1191 if (nf_register_sockopt(&ipt_acc_sockopts) < 0) {
1192 printk("ACCOUNT: Can't register sockopts. Aborting\n");
1196 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
1197 if (xt_register_target(&xt_acc_reg))
1199 if (ipt_register_target(&ipt_acc_reg))
1207 kfree(ipt_acc_tables);
1209 kfree(ipt_acc_handles);
1211 free_page((unsigned long)ipt_acc_tmpbuf);
1216 static void __exit fini(void)
1218 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
1219 xt_unregister_target(&xt_acc_reg);
1221 ipt_unregister_target(&ipt_acc_reg);
1224 nf_unregister_sockopt(&ipt_acc_sockopts);
1226 kfree(ipt_acc_tables);
1227 kfree(ipt_acc_handles);
1228 free_page((unsigned long)ipt_acc_tmpbuf);
1233 MODULE_LICENSE("GPL");