From a44c4e4b1d0722b775e4dd28562b2438c0e3f18f Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Thu, 3 Sep 2009 13:20:43 +0200 Subject: [PATCH 01/15] Import ACCOUNT kernel and iptables modules Reference: git://developer.intra2net.com/ipt_ACCOUNT # v1.15-1-gfb4dd1a --- extensions/Kbuild | 1 + extensions/Mbuild | 1 + extensions/libxt_ACCOUNT.c | 198 ++++++ extensions/xt_ACCOUNT.c | 1224 ++++++++++++++++++++++++++++++++++++ extensions/xt_ACCOUNT.h | 111 ++++ mconfig | 1 + 6 files changed, 1536 insertions(+) create mode 100644 extensions/libxt_ACCOUNT.c create mode 100644 extensions/xt_ACCOUNT.c create mode 100644 extensions/xt_ACCOUNT.h diff --git a/extensions/Kbuild b/extensions/Kbuild index 64c7d35..20d43a8 100644 --- a/extensions/Kbuild +++ b/extensions/Kbuild @@ -5,6 +5,7 @@ include ${XA_TOPSRCDIR}/mconfig obj-m += compat_xtables.o +obj-${build_ACCOUNT} += xt_ACCOUNT.o obj-${build_CHAOS} += xt_CHAOS.o obj-${build_DELUDE} += xt_DELUDE.o obj-${build_DHCPMAC} += xt_DHCPMAC.o diff --git a/extensions/Mbuild b/extensions/Mbuild index 0a24854..ace420b 100644 --- a/extensions/Mbuild +++ b/extensions/Mbuild @@ -1,3 +1,4 @@ +obj-${build_ACCOUNT} += libxt_ACCOUNT.so obj-${build_CHAOS} += libxt_CHAOS.so obj-${build_DELUDE} += libxt_DELUDE.so obj-${build_DHCPMAC} += libxt_DHCPMAC.so libxt_dhcpmac.so diff --git a/extensions/libxt_ACCOUNT.c b/extensions/libxt_ACCOUNT.c new file mode 100644 index 0000000..55a6362 --- /dev/null +++ b/extensions/libxt_ACCOUNT.c @@ -0,0 +1,198 @@ +/* Shared library add-on to iptables to add ACCOUNT(ing) support. + Author: Intra2net AG +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "xt_ACCOUNT.h" + +static struct option opts[] = { + { .name = "addr", .has_arg = 1, .flag = 0, .val = 'a' }, + { .name = "tname", .has_arg = 1, .flag = 0, .val = 't' }, + { .name = 0 } +}; + +/* Compat glue for iptables 1.4.0 */ +#ifndef XTABLES_VERSION +#define XTABLES_VERSION IPTABLES_VERSION +#endif + +/* Function which prints out usage message. */ +static void help(void) +{ + printf( +"ACCOUNT v%s options:\n" +" --%s ip/netmask\t\tBase network IP and netmask used for this table\n" +" --%s name\t\t\tTable name for the userspace library\n", +XTABLES_VERSION, opts[0].name, opts[1].name); +} + +/* Initialize the target. */ +static void +init(struct xt_entry_target *t) +{ + struct ipt_acc_info *accountinfo = (struct ipt_acc_info *)t->data; + + accountinfo->table_nr = -1; +} + +#define IPT_ACCOUNT_OPT_ADDR 0x01 +#define IPT_ACCOUNT_OPT_TABLE 0x02 + +/* Function which parses command options; returns true if it + ate an option */ + +static int parse(int c, char **argv, int invert, unsigned int *flags, + const void *entry, struct xt_entry_target **target) +{ + struct ipt_acc_info *accountinfo = (struct ipt_acc_info *)(*target)->data; + struct in_addr *addrs = NULL, mask; + unsigned int naddrs = 0; + + switch (c) { + case 'a': + if (*flags & IPT_ACCOUNT_OPT_ADDR) + xtables_error(PARAMETER_PROBLEM, "Can't specify --%s twice", + opts[0].name); + + if (xtables_check_inverse(optarg, &invert, NULL, 0)) + xtables_error(PARAMETER_PROBLEM, "Unexpected `!' after --%s", + opts[0].name); + +#ifdef XTABLES_VERSION_CODE + xtables_ipparse_any(optarg, &addrs, &mask, &naddrs); +#else + parse_hostnetworkmask(optarg, &addrs, &mask, &naddrs); +#endif + + if (naddrs > 1) + xtables_error(PARAMETER_PROBLEM, "multiple IP addresses not allowed"); + + accountinfo->net_ip = addrs[0].s_addr; + accountinfo->net_mask = mask.s_addr; + + *flags |= IPT_ACCOUNT_OPT_ADDR; + break; + + case 't': + if (*flags & IPT_ACCOUNT_OPT_TABLE) + xtables_error(PARAMETER_PROBLEM, + "Can't specify --%s twice", opts[1].name); + + if (xtables_check_inverse(optarg, &invert, NULL, 0)) + xtables_error(PARAMETER_PROBLEM, + "Unexpected `!' after --%s", opts[1].name); + + if (strlen(optarg) > ACCOUNT_TABLE_NAME_LEN - 1) + xtables_error(PARAMETER_PROBLEM, + "Maximum table name length %u for --%s", + ACCOUNT_TABLE_NAME_LEN - 1, opts[1].name); + + strcpy(accountinfo->table_name, optarg); + *flags |= IPT_ACCOUNT_OPT_TABLE; + break; + + default: + return 0; + } + return 1; +} + +/* Final check; nothing. */ +static void final_check(unsigned int flags) +{ + if (!(flags&IPT_ACCOUNT_OPT_ADDR) || !(flags&IPT_ACCOUNT_OPT_TABLE)) + xtables_error(PARAMETER_PROBLEM, "ACCOUNT: needs --%s and --%s", + opts[0].name, opts[1].name); +} + +static const char *print_helper_ip(struct in_addr a) +{ +#ifdef XTABLES_VERSION_CODE + return xtables_ipaddr_to_numeric(&a); +#else + return addr_to_dotted(&a); +#endif +} + +static const char *print_helper_mask(struct in_addr a) +{ +#ifdef XTABLES_VERSION_CODE + return xtables_ipmask_to_numeric(&a); +#else + return mask_to_dotted(&a); +#endif +} + +static void print_it(const void *ip, + const struct xt_entry_target *target, char do_prefix) +{ + const struct ipt_acc_info *accountinfo + = (const struct ipt_acc_info *)target->data; + struct in_addr a; + + if (!do_prefix) + printf("ACCOUNT "); + + // Network information + if (do_prefix) + printf("--"); + printf("%s ", opts[0].name); + + a.s_addr = accountinfo->net_ip; + printf("%s", print_helper_ip(a)); + a.s_addr = accountinfo->net_mask; + printf("%s", print_helper_mask(a)); + + printf(" "); + if (do_prefix) + printf("--"); + + printf("%s %s", opts[1].name, accountinfo->table_name); +} + + +static void +print(const void *ip, + const struct xt_entry_target *target, + int numeric) +{ + print_it (ip, target, 0); +} + +/* Saves the union ipt_targinfo in parsable form to stdout. */ +static void +save(const void *ip, const struct xt_entry_target *target) +{ + print_it(ip, target, 1); +} + +static +struct xtables_target account += { + .next = NULL, + .name = "ACCOUNT", + .family = AF_INET, + .version = XTABLES_VERSION, + .size = XT_ALIGN(sizeof(struct ipt_acc_info)), + .userspacesize = offsetof(struct ipt_acc_info, table_nr), + .help = &help, + .init = &init, + .parse = &parse, + .final_check = &final_check, + .print = &print, + .save = &save, + .extra_opts = opts +}; + +void _init(void) +{ + xtables_register_target(&account); +} diff --git a/extensions/xt_ACCOUNT.c b/extensions/xt_ACCOUNT.c new file mode 100644 index 0000000..edac229 --- /dev/null +++ b/extensions/xt_ACCOUNT.c @@ -0,0 +1,1224 @@ +/*************************************************************************** + * This is a module which is used for counting packets. * + * See http://www.intra2net.com/opensource/ipt_account * + * for further information * + * * + * Copyright (C) 2004-2008 by Intra2net AG * + * opensource@intra2net.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License * + * version 2 as published by the Free Software Foundation; * + * * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) + #include +#else + #include +#endif + +#include +#include +#include +#include +#include + +#include +#include "xt_ACCOUNT.h" + +#if 0 +#define DEBUGP printk +#else +#define DEBUGP(format, args...) +#endif + +#if (PAGE_SIZE < 4096) +#error "ipt_ACCOUNT needs at least a PAGE_SIZE of 4096" +#endif + +static struct ipt_acc_table *ipt_acc_tables = NULL; +static struct ipt_acc_handle *ipt_acc_handles = NULL; +static void *ipt_acc_tmpbuf = NULL; + +/* Spinlock used for manipulating the current accounting tables/data */ +static DEFINE_SPINLOCK(ipt_acc_lock); +/* Mutex (semaphore) used for manipulating userspace handles/snapshot data */ +static struct semaphore ipt_acc_userspace_mutex; + +/* Allocates a page and clears it */ +static void *ipt_acc_zalloc_page(void) +{ + // Don't use get_zeroed_page until it's fixed in the kernel. + // get_zeroed_page(GFP_ATOMIC) + void *mem = (void *)__get_free_page(GFP_ATOMIC); + if (mem) { + memset (mem, 0, PAGE_SIZE); + } + + return mem; +} + +/* Recursive free of all data structures */ +static void ipt_acc_data_free(void *data, unsigned char depth) +{ + /* Empty data set */ + if (!data) + return; + + /* Free for 8 bit network */ + if (depth == 0) { + free_page((unsigned long)data); + return; + } + + /* Free for 16 bit network */ + if (depth == 1) { + struct ipt_acc_mask_16 *mask_16 = (struct ipt_acc_mask_16 *)data; + unsigned int b; + for (b=0; b <= 255; b++) { + if (mask_16->mask_24[b]) { + free_page((unsigned long)mask_16->mask_24[b]); + } + } + free_page((unsigned long)data); + return; + } + + /* Free for 24 bit network */ + if (depth == 2) { + unsigned int a, b; + for (a=0; a <= 255; a++) { + if (((struct ipt_acc_mask_8 *)data)->mask_16[a]) { + struct ipt_acc_mask_16 *mask_16 = (struct ipt_acc_mask_16*) + ((struct ipt_acc_mask_8 *)data)->mask_16[a]; + + for (b=0; b <= 255; b++) { + if (mask_16->mask_24[b]) { + free_page((unsigned long)mask_16->mask_24[b]); + } + } + free_page((unsigned long)mask_16); + } + } + free_page((unsigned long)data); + return; + } + + printk("ACCOUNT: ipt_acc_data_free called with unknown depth: %d\n", + depth); + return; +} + +/* Look for existing table / insert new one. + Return internal ID or -1 on error */ +static int ipt_acc_table_insert(char *name, uint32_t ip, uint32_t netmask) +{ + unsigned int i; + + DEBUGP("ACCOUNT: ipt_acc_table_insert: %s, %u.%u.%u.%u/%u.%u.%u.%u\n", + name, NIPQUAD(ip), NIPQUAD(netmask)); + + /* Look for existing table */ + for (i = 0; i < ACCOUNT_MAX_TABLES; i++) { + if (strncmp(ipt_acc_tables[i].name, name, + ACCOUNT_TABLE_NAME_LEN) == 0) { + DEBUGP("ACCOUNT: Found existing slot: %d - " + "%u.%u.%u.%u/%u.%u.%u.%u\n", i, + NIPQUAD(ipt_acc_tables[i].ip), + NIPQUAD(ipt_acc_tables[i].netmask)); + + if (ipt_acc_tables[i].ip != ip + || ipt_acc_tables[i].netmask != netmask) { + printk("ACCOUNT: Table %s found, but IP/netmask mismatch. " + "IP/netmask found: %u.%u.%u.%u/%u.%u.%u.%u\n", + name, NIPQUAD(ipt_acc_tables[i].ip), + NIPQUAD(ipt_acc_tables[i].netmask)); + return -1; + } + + ipt_acc_tables[i].refcount++; + DEBUGP("ACCOUNT: Refcount: %d\n", ipt_acc_tables[i].refcount); + return i; + } + } + + /* Insert new table */ + for (i = 0; i < ACCOUNT_MAX_TABLES; i++) { + /* Found free slot */ + if (ipt_acc_tables[i].name[0] == 0) { + unsigned int netsize=0; + uint32_t calc_mask; + int j; /* needs to be signed, otherwise we risk endless loop */ + + DEBUGP("ACCOUNT: Found free slot: %d\n", i); + strncpy (ipt_acc_tables[i].name, name, ACCOUNT_TABLE_NAME_LEN-1); + + ipt_acc_tables[i].ip = ip; + ipt_acc_tables[i].netmask = netmask; + + /* Calculate netsize */ + calc_mask = htonl(netmask); + for (j = 31; j >= 0; j--) { + if (calc_mask&(1<= 24) + ipt_acc_tables[i].depth = 0; + else if (netsize >= 16) + ipt_acc_tables[i].depth = 1; + else if(netsize >= 8) + ipt_acc_tables[i].depth = 2; + + DEBUGP("ACCOUNT: calculated netsize: %u -> " + "ipt_acc_table depth %u\n", netsize, + ipt_acc_tables[i].depth); + + ipt_acc_tables[i].refcount++; + if ((ipt_acc_tables[i].data + = ipt_acc_zalloc_page()) == NULL) { + printk("ACCOUNT: out of memory for data of table: %s\n", name); + memset(&ipt_acc_tables[i], 0, + sizeof(struct ipt_acc_table)); + return -1; + } + + return i; + } + } + + /* No free slot found */ + printk("ACCOUNT: No free table slot found (max: %d). " + "Please increase ACCOUNT_MAX_TABLES.\n", ACCOUNT_MAX_TABLES); + return -1; +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) +static bool ipt_acc_checkentry(const struct xt_tgchk_param *par) +#else +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) +static bool ipt_acc_checkentry(const char *tablename, +#else +static int ipt_acc_checkentry(const char *tablename, +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) + const void *e, +#else + const struct ipt_entry *e, +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) + const struct xt_target *target, +#endif + void *targinfo, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) + unsigned int targinfosize, +#endif + unsigned int hook_mask) +#endif /* >= 2.6.28 */ +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) + struct ipt_acc_info *info = par->targinfo; +#else + struct ipt_acc_info *info = targinfo; +#endif + int table_nr; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_acc_info))) { + DEBUGP("ACCOUNT: targinfosize %u != %u\n", + targinfosize, IPT_ALIGN(sizeof(struct ipt_acc_info))); + return 0; + } +#endif + + spin_lock_bh(&ipt_acc_lock); + table_nr = ipt_acc_table_insert(info->table_name, info->net_ip, + info->net_mask); + spin_unlock_bh(&ipt_acc_lock); + + if (table_nr == -1) { + printk("ACCOUNT: Table insert problem. Aborting\n"); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) + return false; +#else + return 0; +#endif + } + /* Table nr caching so we don't have to do an extra string compare + for every packet */ + info->table_nr = table_nr; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) + return true; +#else + return 1; +#endif +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) +static void ipt_acc_destroy(const struct xt_tgdtor_param *par) +#else +static void ipt_acc_destroy( +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) + const struct xt_target *target, +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19) + void *targinfo) +#else + void *targinfo, + unsigned int targinfosize) +#endif +#endif /* >= 2.6.28 */ +{ + unsigned int i; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) + struct ipt_acc_info *info = par->targinfo; +#else + struct ipt_acc_info *info = targinfo; +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_acc_info))) { + DEBUGP("ACCOUNT: targinfosize %u != %u\n", + targinfosize, IPT_ALIGN(sizeof(struct ipt_acc_info))); + } +#endif + + spin_lock_bh(&ipt_acc_lock); + + DEBUGP("ACCOUNT: ipt_acc_deleteentry called for table: %s (#%d)\n", + info->table_name, info->table_nr); + + info->table_nr = -1; /* Set back to original state */ + + /* Look for table */ + for (i = 0; i < ACCOUNT_MAX_TABLES; i++) { + if (strncmp(ipt_acc_tables[i].name, info->table_name, + ACCOUNT_TABLE_NAME_LEN) == 0) { + DEBUGP("ACCOUNT: Found table at slot: %d\n", i); + + ipt_acc_tables[i].refcount--; + DEBUGP("ACCOUNT: Refcount left: %d\n", + ipt_acc_tables[i].refcount); + + /* Table not needed anymore? */ + if (ipt_acc_tables[i].refcount == 0) { + DEBUGP("ACCOUNT: Destroying table at slot: %d\n", i); + ipt_acc_data_free(ipt_acc_tables[i].data, + ipt_acc_tables[i].depth); + memset(&ipt_acc_tables[i], 0, + sizeof(struct ipt_acc_table)); + } + + spin_unlock_bh(&ipt_acc_lock); + return; + } + } + + /* Table not found */ + printk("ACCOUNT: Table %s not found for destroy\n", info->table_name); + spin_unlock_bh(&ipt_acc_lock); +} + +static void ipt_acc_depth0_insert(struct ipt_acc_mask_24 *mask_24, + uint32_t net_ip, uint32_t netmask, + uint32_t src_ip, uint32_t dst_ip, + uint32_t size, uint32_t *itemcount) +{ + unsigned char is_src = 0, is_dst = 0, src_slot, dst_slot; + char is_src_new_ip = 0, is_dst_new_ip = 0; /* Check if this entry is new */ + + DEBUGP("ACCOUNT: ipt_acc_depth0_insert: %u.%u.%u.%u/%u.%u.%u.%u " + "for net %u.%u.%u.%u/%u.%u.%u.%u, size: %u\n", NIPQUAD(src_ip), + NIPQUAD(dst_ip), NIPQUAD(net_ip), NIPQUAD(netmask), size); + + /* Check if src/dst is inside our network. */ + /* Special: net_ip = 0.0.0.0/0 gets stored as src in slot 0 */ + if (!netmask) + src_ip = 0; + if ((net_ip&netmask) == (src_ip&netmask)) + is_src = 1; + if ((net_ip&netmask) == (dst_ip&netmask) && netmask) + is_dst = 1; + + if (!is_src && !is_dst) { + DEBUGP("ACCOUNT: Skipping packet %u.%u.%u.%u/%u.%u.%u.%u " + "for net %u.%u.%u.%u/%u.%u.%u.%u\n", NIPQUAD(src_ip), + NIPQUAD(dst_ip), NIPQUAD(net_ip), NIPQUAD(netmask)); + return; + } + + /* Calculate array positions */ + src_slot = (unsigned char)((src_ip&0xFF000000) >> 24); + dst_slot = (unsigned char)((dst_ip&0xFF000000) >> 24); + + /* Increase size counters */ + if (is_src) { + /* Calculate network slot */ + DEBUGP("ACCOUNT: Calculated SRC 8 bit network slot: %d\n", src_slot); + if (!mask_24->ip[src_slot].src_packets + && !mask_24->ip[src_slot].dst_packets) + is_src_new_ip = 1; + + mask_24->ip[src_slot].src_packets++; + mask_24->ip[src_slot].src_bytes+=size; + } + if (is_dst) { + DEBUGP("ACCOUNT: Calculated DST 8 bit network slot: %d\n", dst_slot); + if (!mask_24->ip[dst_slot].src_packets + && !mask_24->ip[dst_slot].dst_packets) + is_dst_new_ip = 1; + + mask_24->ip[dst_slot].dst_packets++; + mask_24->ip[dst_slot].dst_bytes+=size; + } + + /* Increase itemcounter */ + DEBUGP("ACCOUNT: Itemcounter before: %d\n", *itemcount); + if (src_slot == dst_slot) { + if (is_src_new_ip || is_dst_new_ip) { + DEBUGP("ACCOUNT: src_slot == dst_slot: %d, %d\n", + is_src_new_ip, is_dst_new_ip); + (*itemcount)++; + } + } else { + if (is_src_new_ip) { + DEBUGP("ACCOUNT: New src_ip: %u.%u.%u.%u\n", NIPQUAD(src_ip)); + (*itemcount)++; + } + if (is_dst_new_ip) { + DEBUGP("ACCOUNT: New dst_ip: %u.%u.%u.%u\n", NIPQUAD(dst_ip)); + (*itemcount)++; + } + } + DEBUGP("ACCOUNT: Itemcounter after: %d\n", *itemcount); +} + +static void ipt_acc_depth1_insert(struct ipt_acc_mask_16 *mask_16, + uint32_t net_ip, uint32_t netmask, + uint32_t src_ip, uint32_t dst_ip, + uint32_t size, uint32_t *itemcount) +{ + /* Do we need to process src IP? */ + if ((net_ip&netmask) == (src_ip&netmask)) { + unsigned char slot = (unsigned char)((src_ip&0x00FF0000) >> 16); + DEBUGP("ACCOUNT: Calculated SRC 16 bit network slot: %d\n", slot); + + /* Do we need to create a new mask_24 bucket? */ + if (!mask_16->mask_24[slot] && (mask_16->mask_24[slot] = + ipt_acc_zalloc_page()) == NULL) { + printk("ACCOUNT: Can't process packet because out of memory!\n"); + return; + } + + ipt_acc_depth0_insert((struct ipt_acc_mask_24 *)mask_16->mask_24[slot], + net_ip, netmask, src_ip, 0, size, itemcount); + } + + /* Do we need to process dst IP? */ + if ((net_ip&netmask) == (dst_ip&netmask)) { + unsigned char slot = (unsigned char)((dst_ip&0x00FF0000) >> 16); + DEBUGP("ACCOUNT: Calculated DST 16 bit network slot: %d\n", slot); + + /* Do we need to create a new mask_24 bucket? */ + if (!mask_16->mask_24[slot] && (mask_16->mask_24[slot] + = ipt_acc_zalloc_page()) == NULL) { + printk("ACCOUT: Can't process packet because out of memory!\n"); + return; + } + + ipt_acc_depth0_insert((struct ipt_acc_mask_24 *)mask_16->mask_24[slot], + net_ip, netmask, 0, dst_ip, size, itemcount); + } +} + +static void ipt_acc_depth2_insert(struct ipt_acc_mask_8 *mask_8, + uint32_t net_ip, uint32_t netmask, + uint32_t src_ip, uint32_t dst_ip, + uint32_t size, uint32_t *itemcount) +{ + /* Do we need to process src IP? */ + if ((net_ip&netmask) == (src_ip&netmask)) { + unsigned char slot = (unsigned char)((src_ip&0x0000FF00) >> 8); + DEBUGP("ACCOUNT: Calculated SRC 24 bit network slot: %d\n", slot); + + /* Do we need to create a new mask_24 bucket? */ + if (!mask_8->mask_16[slot] && (mask_8->mask_16[slot] + = ipt_acc_zalloc_page()) == NULL) { + printk("ACCOUNT: Can't process packet because out of memory!\n"); + return; + } + + ipt_acc_depth1_insert((struct ipt_acc_mask_16 *)mask_8->mask_16[slot], + net_ip, netmask, src_ip, 0, size, itemcount); + } + + /* Do we need to process dst IP? */ + if ((net_ip&netmask) == (dst_ip&netmask)) { + unsigned char slot = (unsigned char)((dst_ip&0x0000FF00) >> 8); + DEBUGP("ACCOUNT: Calculated DST 24 bit network slot: %d\n", slot); + + /* Do we need to create a new mask_24 bucket? */ + if (!mask_8->mask_16[slot] && (mask_8->mask_16[slot] + = ipt_acc_zalloc_page()) == NULL) { + printk("ACCOUNT: Can't process packet because out of memory!\n"); + return; + } + + ipt_acc_depth1_insert((struct ipt_acc_mask_16 *)mask_8->mask_16[slot], + net_ip, netmask, 0, dst_ip, size, itemcount); + } +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) +static unsigned int ipt_acc_target(struct sk_buff *skb, const struct xt_target_param *par) +#else +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) +static unsigned int ipt_acc_target(struct sk_buff *skb, +#else +static unsigned int ipt_acc_target(struct sk_buff **pskb, +#endif + const struct net_device *in, + const struct net_device *out, + unsigned int hooknum, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) + const struct xt_target *target, +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19) + const void *targinfo) +#else + const void *targinfo, + void *userinfo) +#endif +#endif /* 2.6.28 */ +{ + const struct ipt_acc_info *info = +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) + par->targinfo; +#else + (const struct ipt_acc_info *)targinfo; +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) + uint32_t src_ip = ip_hdr(skb)->saddr; + uint32_t dst_ip = ip_hdr(skb)->daddr; + uint32_t size = ntohs(ip_hdr(skb)->tot_len); +#else +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) + uint32_t src_ip = ip_hdr(*pskb)->saddr; + uint32_t dst_ip = ip_hdr(*pskb)->daddr; + uint32_t size = ntohs(ip_hdr(*pskb)->tot_len); +#else + uint32_t src_ip = (*pskb)->nh.iph->saddr; + uint32_t dst_ip = (*pskb)->nh.iph->daddr; + uint32_t size = ntohs((*pskb)->nh.iph->tot_len); +#endif +#endif + + spin_lock_bh(&ipt_acc_lock); + + if (ipt_acc_tables[info->table_nr].name[0] == 0) { + printk("ACCOUNT: ipt_acc_target: Invalid table id %u. " + "IPs %u.%u.%u.%u/%u.%u.%u.%u\n", info->table_nr, + NIPQUAD(src_ip), NIPQUAD(dst_ip)); + spin_unlock_bh(&ipt_acc_lock); + return IPT_CONTINUE; + } + + /* 8 bit network or "any" network */ + if (ipt_acc_tables[info->table_nr].depth == 0) { + /* Count packet and check if the IP is new */ + ipt_acc_depth0_insert( + (struct ipt_acc_mask_24 *)ipt_acc_tables[info->table_nr].data, + ipt_acc_tables[info->table_nr].ip, + ipt_acc_tables[info->table_nr].netmask, + src_ip, dst_ip, size, &ipt_acc_tables[info->table_nr].itemcount); + spin_unlock_bh(&ipt_acc_lock); + return IPT_CONTINUE; + } + + /* 16 bit network */ + if (ipt_acc_tables[info->table_nr].depth == 1) { + ipt_acc_depth1_insert( + (struct ipt_acc_mask_16 *)ipt_acc_tables[info->table_nr].data, + ipt_acc_tables[info->table_nr].ip, + ipt_acc_tables[info->table_nr].netmask, + src_ip, dst_ip, size, &ipt_acc_tables[info->table_nr].itemcount); + spin_unlock_bh(&ipt_acc_lock); + return IPT_CONTINUE; + } + + /* 24 bit network */ + if (ipt_acc_tables[info->table_nr].depth == 2) { + ipt_acc_depth2_insert( + (struct ipt_acc_mask_8 *)ipt_acc_tables[info->table_nr].data, + ipt_acc_tables[info->table_nr].ip, + ipt_acc_tables[info->table_nr].netmask, + src_ip, dst_ip, size, &ipt_acc_tables[info->table_nr].itemcount); + spin_unlock_bh(&ipt_acc_lock); + return IPT_CONTINUE; + } + + printk("ACCOUNT: ipt_acc_target: Unable to process packet. " + "Table id %u. IPs %u.%u.%u.%u/%u.%u.%u.%u\n", + info->table_nr, NIPQUAD(src_ip), NIPQUAD(dst_ip)); + + spin_unlock_bh(&ipt_acc_lock); + return IPT_CONTINUE; +} + +/* + Functions dealing with "handles": + Handles are snapshots of a accounting state. + + read snapshots are only for debugging the code + and are very expensive concerning speed/memory + compared to read_and_flush. + + The functions aren't protected by spinlocks themselves + as this is done in the ioctl part of the code. +*/ + +/* + Find a free handle slot. Normally only one should be used, + but there could be two or more applications accessing the data + at the same time. +*/ +static int ipt_acc_handle_find_slot(void) +{ + unsigned int i; + /* Insert new table */ + for (i = 0; i < ACCOUNT_MAX_HANDLES; i++) { + /* Found free slot */ + if (ipt_acc_handles[i].data == NULL) { + /* Don't "mark" data as used as we are protected by a spinlock + by the calling function. handle_find_slot() is only a function + to prevent code duplication. */ + return i; + } + } + + /* No free slot found */ + printk("ACCOUNT: No free handle slot found (max: %u). " + "Please increase ACCOUNT_MAX_HANDLES.\n", ACCOUNT_MAX_HANDLES); + return -1; +} + +static int ipt_acc_handle_free(unsigned int handle) +{ + if (handle >= ACCOUNT_MAX_HANDLES) { + printk("ACCOUNT: Invalid handle for ipt_acc_handle_free() specified:" + " %u\n", handle); + return -EINVAL; + } + + ipt_acc_data_free(ipt_acc_handles[handle].data, + ipt_acc_handles[handle].depth); + memset (&ipt_acc_handles[handle], 0, sizeof (struct ipt_acc_handle)); + return 0; +} + +/* Prepare data for read without flush. Use only for debugging! + Real applications should use read&flush as it's way more efficent */ +static int ipt_acc_handle_prepare_read(char *tablename, + struct ipt_acc_handle *dest, uint32_t *count) +{ + int table_nr=-1; + unsigned char depth; + + for (table_nr = 0; table_nr < ACCOUNT_MAX_TABLES; table_nr++) + if (strncmp(ipt_acc_tables[table_nr].name, tablename, + ACCOUNT_TABLE_NAME_LEN) == 0) + break; + + if (table_nr == ACCOUNT_MAX_TABLES) { + printk("ACCOUNT: ipt_acc_handle_prepare_read(): " + "Table %s not found\n", tablename); + return -1; + } + + /* Fill up handle structure */ + dest->ip = ipt_acc_tables[table_nr].ip; + dest->depth = ipt_acc_tables[table_nr].depth; + dest->itemcount = ipt_acc_tables[table_nr].itemcount; + + /* allocate "root" table */ + if ((dest->data = ipt_acc_zalloc_page()) == NULL) { + printk("ACCOUNT: out of memory for root table " + "in ipt_acc_handle_prepare_read()\n"); + return -1; + } + + /* Recursive copy of complete data structure */ + depth = dest->depth; + if (depth == 0) { + memcpy(dest->data, + ipt_acc_tables[table_nr].data, + sizeof(struct ipt_acc_mask_24)); + } else if (depth == 1) { + struct ipt_acc_mask_16 *src_16 = + (struct ipt_acc_mask_16 *)ipt_acc_tables[table_nr].data; + struct ipt_acc_mask_16 *network_16 = + (struct ipt_acc_mask_16 *)dest->data; + unsigned int b; + + for (b = 0; b <= 255; b++) { + if (src_16->mask_24[b]) { + if ((network_16->mask_24[b] = + ipt_acc_zalloc_page()) == NULL) { + printk("ACCOUNT: out of memory during copy of 16 bit " + "network in ipt_acc_handle_prepare_read()\n"); + ipt_acc_data_free(dest->data, depth); + return -1; + } + + memcpy(network_16->mask_24[b], src_16->mask_24[b], + sizeof(struct ipt_acc_mask_24)); + } + } + } else if(depth == 2) { + struct ipt_acc_mask_8 *src_8 = + (struct ipt_acc_mask_8 *)ipt_acc_tables[table_nr].data; + struct ipt_acc_mask_8 *network_8 = + (struct ipt_acc_mask_8 *)dest->data; + struct ipt_acc_mask_16 *src_16, *network_16; + unsigned int a, b; + + for (a = 0; a <= 255; a++) { + if (src_8->mask_16[a]) { + if ((network_8->mask_16[a] = + ipt_acc_zalloc_page()) == NULL) { + printk("ACCOUNT: out of memory during copy of 24 bit network" + " in ipt_acc_handle_prepare_read()\n"); + ipt_acc_data_free(dest->data, depth); + return -1; + } + + memcpy(network_8->mask_16[a], src_8->mask_16[a], + sizeof(struct ipt_acc_mask_16)); + + src_16 = src_8->mask_16[a]; + network_16 = network_8->mask_16[a]; + + for (b = 0; b <= 255; b++) { + if (src_16->mask_24[b]) { + if ((network_16->mask_24[b] = + ipt_acc_zalloc_page()) == NULL) { + printk("ACCOUNT: out of memory during copy of 16 bit" + " network in ipt_acc_handle_prepare_read()\n"); + ipt_acc_data_free(dest->data, depth); + return -1; + } + + memcpy(network_16->mask_24[b], src_16->mask_24[b], + sizeof(struct ipt_acc_mask_24)); + } + } + } + } + } + + *count = ipt_acc_tables[table_nr].itemcount; + + return 0; +} + +/* Prepare data for read and flush it */ +static int ipt_acc_handle_prepare_read_flush(char *tablename, + struct ipt_acc_handle *dest, uint32_t *count) +{ + int table_nr; + void *new_data_page; + + for (table_nr = 0; table_nr < ACCOUNT_MAX_TABLES; table_nr++) + if (strncmp(ipt_acc_tables[table_nr].name, tablename, + ACCOUNT_TABLE_NAME_LEN) == 0) + break; + + if (table_nr == ACCOUNT_MAX_TABLES) { + printk("ACCOUNT: ipt_acc_handle_prepare_read_flush(): " + "Table %s not found\n", tablename); + return -1; + } + + /* Try to allocate memory */ + if (!(new_data_page = ipt_acc_zalloc_page())) { + printk("ACCOUNT: ipt_acc_handle_prepare_read_flush(): " + "Out of memory!\n"); + return -1; + } + + /* Fill up handle structure */ + dest->ip = ipt_acc_tables[table_nr].ip; + dest->depth = ipt_acc_tables[table_nr].depth; + dest->itemcount = ipt_acc_tables[table_nr].itemcount; + dest->data = ipt_acc_tables[table_nr].data; + *count = ipt_acc_tables[table_nr].itemcount; + + /* "Flush" table data */ + ipt_acc_tables[table_nr].data = new_data_page; + ipt_acc_tables[table_nr].itemcount = 0; + + return 0; +} + +/* Copy 8 bit network data into a prepared buffer. + We only copy entries != 0 to increase performance. +*/ +static int ipt_acc_handle_copy_data(void *to_user, unsigned long *to_user_pos, + unsigned long *tmpbuf_pos, + struct ipt_acc_mask_24 *data, + uint32_t net_ip, uint32_t net_OR_mask) +{ + struct ipt_acc_handle_ip handle_ip; + size_t handle_ip_size = sizeof (struct ipt_acc_handle_ip); + unsigned int i; + + for (i = 0; i <= 255; i++) { + if (data->ip[i].src_packets || data->ip[i].dst_packets) { + handle_ip.ip = net_ip | net_OR_mask | (i<<24); + + handle_ip.src_packets = data->ip[i].src_packets; + handle_ip.src_bytes = data->ip[i].src_bytes; + handle_ip.dst_packets = data->ip[i].dst_packets; + handle_ip.dst_bytes = data->ip[i].dst_bytes; + + /* Temporary buffer full? Flush to userspace */ + if (*tmpbuf_pos+handle_ip_size >= PAGE_SIZE) { + if (copy_to_user(to_user + *to_user_pos, ipt_acc_tmpbuf, + *tmpbuf_pos)) + return -EFAULT; + *to_user_pos = *to_user_pos + *tmpbuf_pos; + *tmpbuf_pos = 0; + } + memcpy(ipt_acc_tmpbuf+*tmpbuf_pos, &handle_ip, handle_ip_size); + *tmpbuf_pos += handle_ip_size; + } + } + + return 0; +} + +/* Copy the data from our internal structure + We only copy entries != 0 to increase performance. + Overwrites ipt_acc_tmpbuf. +*/ +static int ipt_acc_handle_get_data(uint32_t handle, void *to_user) +{ + unsigned long to_user_pos=0, tmpbuf_pos=0; + uint32_t net_ip; + unsigned char depth; + + if (handle >= ACCOUNT_MAX_HANDLES) { + printk("ACCOUNT: invalid handle for ipt_acc_handle_get_data() " + "specified: %u\n", handle); + return -1; + } + + if (ipt_acc_handles[handle].data == NULL) { + printk("ACCOUNT: handle %u is BROKEN: Contains no data\n", handle); + return -1; + } + + net_ip = ipt_acc_handles[handle].ip; + depth = ipt_acc_handles[handle].depth; + + /* 8 bit network */ + if (depth == 0) { + struct ipt_acc_mask_24 *network = + (struct ipt_acc_mask_24*)ipt_acc_handles[handle].data; + if (ipt_acc_handle_copy_data(to_user, &to_user_pos, &tmpbuf_pos, + network, net_ip, 0)) + return -1; + + /* Flush remaining data to userspace */ + if (tmpbuf_pos) + if (copy_to_user(to_user+to_user_pos, ipt_acc_tmpbuf, tmpbuf_pos)) + return -1; + + return 0; + } + + /* 16 bit network */ + if (depth == 1) { + struct ipt_acc_mask_16 *network_16 = + (struct ipt_acc_mask_16*)ipt_acc_handles[handle].data; + unsigned int b; + for (b = 0; b <= 255; b++) { + if (network_16->mask_24[b]) { + struct ipt_acc_mask_24 *network = + (struct ipt_acc_mask_24*)network_16->mask_24[b]; + if (ipt_acc_handle_copy_data(to_user, &to_user_pos, + &tmpbuf_pos, network, net_ip, (b << 16))) + return -1; + } + } + + /* Flush remaining data to userspace */ + if (tmpbuf_pos) + if (copy_to_user(to_user+to_user_pos, ipt_acc_tmpbuf, tmpbuf_pos)) + return -1; + + return 0; + } + + /* 24 bit network */ + if (depth == 2) { + struct ipt_acc_mask_8 *network_8 = + (struct ipt_acc_mask_8*)ipt_acc_handles[handle].data; + unsigned int a, b; + for (a = 0; a <= 255; a++) { + if (network_8->mask_16[a]) { + struct ipt_acc_mask_16 *network_16 = + (struct ipt_acc_mask_16*)network_8->mask_16[a]; + for (b = 0; b <= 255; b++) { + if (network_16->mask_24[b]) { + struct ipt_acc_mask_24 *network = + (struct ipt_acc_mask_24*)network_16->mask_24[b]; + if (ipt_acc_handle_copy_data(to_user, + &to_user_pos, &tmpbuf_pos, + network, net_ip, (a << 8) | (b << 16))) + return -1; + } + } + } + } + + /* Flush remaining data to userspace */ + if (tmpbuf_pos) + if (copy_to_user(to_user+to_user_pos, ipt_acc_tmpbuf, tmpbuf_pos)) + return -1; + + return 0; + } + + return -1; +} + +static int ipt_acc_set_ctl(struct sock *sk, int cmd, + void *user, unsigned int len) +{ + struct ipt_acc_handle_sockopt handle; + int ret = -EINVAL; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + switch (cmd) { + case IPT_SO_SET_ACCOUNT_HANDLE_FREE: + if (len != sizeof(struct ipt_acc_handle_sockopt)) { + printk("ACCOUNT: ipt_acc_set_ctl: wrong data size (%u != %zu) " + "for IPT_SO_SET_HANDLE_FREE\n", + len, sizeof(struct ipt_acc_handle_sockopt)); + break; + } + + if (copy_from_user (&handle, user, len)) { + printk("ACCOUNT: ipt_acc_set_ctl: copy_from_user failed for " + "IPT_SO_SET_HANDLE_FREE\n"); + break; + } + + down(&ipt_acc_userspace_mutex); + ret = ipt_acc_handle_free(handle.handle_nr); + up(&ipt_acc_userspace_mutex); + break; + case IPT_SO_SET_ACCOUNT_HANDLE_FREE_ALL: { + unsigned int i; + down(&ipt_acc_userspace_mutex); + for (i = 0; i < ACCOUNT_MAX_HANDLES; i++) + ipt_acc_handle_free(i); + up(&ipt_acc_userspace_mutex); + ret = 0; + break; + } + default: + printk("ACCOUNT: ipt_acc_set_ctl: unknown request %i\n", cmd); + } + + return ret; +} + +static int ipt_acc_get_ctl(struct sock *sk, int cmd, void *user, int *len) +{ + struct ipt_acc_handle_sockopt handle; + int ret = -EINVAL; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + switch (cmd) { + case IPT_SO_GET_ACCOUNT_PREPARE_READ_FLUSH: + case IPT_SO_GET_ACCOUNT_PREPARE_READ: { + struct ipt_acc_handle dest; + + if (*len < sizeof(struct ipt_acc_handle_sockopt)) { + printk("ACCOUNT: ipt_acc_get_ctl: wrong data size (%u != %zu) " + "for IPT_SO_GET_ACCOUNT_PREPARE_READ/READ_FLUSH\n", + *len, sizeof(struct ipt_acc_handle_sockopt)); + break; + } + + if (copy_from_user (&handle, user, + sizeof(struct ipt_acc_handle_sockopt))) { + return -EFAULT; + break; + } + + spin_lock_bh(&ipt_acc_lock); + if (cmd == IPT_SO_GET_ACCOUNT_PREPARE_READ_FLUSH) + ret = ipt_acc_handle_prepare_read_flush( + handle.name, &dest, &handle.itemcount); + else + ret = ipt_acc_handle_prepare_read( + handle.name, &dest, &handle.itemcount); + spin_unlock_bh(&ipt_acc_lock); + // Error occured during prepare_read? + if (ret == -1) + return -EINVAL; + + /* Allocate a userspace handle */ + down(&ipt_acc_userspace_mutex); + if ((handle.handle_nr = ipt_acc_handle_find_slot()) == -1) { + ipt_acc_data_free(dest.data, dest.depth); + up(&ipt_acc_userspace_mutex); + return -EINVAL; + } + memcpy(&ipt_acc_handles[handle.handle_nr], &dest, + sizeof(struct ipt_acc_handle)); + up(&ipt_acc_userspace_mutex); + + if (copy_to_user(user, &handle, + sizeof(struct ipt_acc_handle_sockopt))) { + return -EFAULT; + break; + } + ret = 0; + break; + } + case IPT_SO_GET_ACCOUNT_GET_DATA: + if (*len < sizeof(struct ipt_acc_handle_sockopt)) { + printk("ACCOUNT: ipt_acc_get_ctl: wrong data size (%u != %zu)" + " for IPT_SO_GET_ACCOUNT_PREPARE_READ/READ_FLUSH\n", + *len, sizeof(struct ipt_acc_handle_sockopt)); + break; + } + + if (copy_from_user (&handle, user, + sizeof(struct ipt_acc_handle_sockopt))) { + return -EFAULT; + break; + } + + if (handle.handle_nr >= ACCOUNT_MAX_HANDLES) { + return -EINVAL; + break; + } + + if (*len < ipt_acc_handles[handle.handle_nr].itemcount + * sizeof(struct ipt_acc_handle_ip)) { + printk("ACCOUNT: ipt_acc_get_ctl: not enough space (%u < %zu)" + " to store data from IPT_SO_GET_ACCOUNT_GET_DATA\n", + *len, ipt_acc_handles[handle.handle_nr].itemcount + * sizeof(struct ipt_acc_handle_ip)); + ret = -ENOMEM; + break; + } + + down(&ipt_acc_userspace_mutex); + ret = ipt_acc_handle_get_data(handle.handle_nr, user); + up(&ipt_acc_userspace_mutex); + if (ret) { + printk("ACCOUNT: ipt_acc_get_ctl: ipt_acc_handle_get_data" + " failed for handle %u\n", handle.handle_nr); + break; + } + + ret = 0; + break; + case IPT_SO_GET_ACCOUNT_GET_HANDLE_USAGE: { + unsigned int i; + if (*len < sizeof(struct ipt_acc_handle_sockopt)) { + printk("ACCOUNT: ipt_acc_get_ctl: wrong data size (%u != %zu)" + " for IPT_SO_GET_ACCOUNT_GET_HANDLE_USAGE\n", + *len, sizeof(struct ipt_acc_handle_sockopt)); + break; + } + + /* Find out how many handles are in use */ + handle.itemcount = 0; + down(&ipt_acc_userspace_mutex); + for (i = 0; i < ACCOUNT_MAX_HANDLES; i++) + if (ipt_acc_handles[i].data) + handle.itemcount++; + up(&ipt_acc_userspace_mutex); + + if (copy_to_user(user, &handle, + sizeof(struct ipt_acc_handle_sockopt))) { + return -EFAULT; + break; + } + ret = 0; + break; + } + case IPT_SO_GET_ACCOUNT_GET_TABLE_NAMES: { + uint32_t size = 0, i, name_len; + char *tnames; + + spin_lock_bh(&ipt_acc_lock); + + /* Determine size of table names */ + for (i = 0; i < ACCOUNT_MAX_TABLES; i++) { + if (ipt_acc_tables[i].name[0] != 0) + size += strlen (ipt_acc_tables[i].name) + 1; + } + size += 1; /* Terminating NULL character */ + + if (*len < size || size > PAGE_SIZE) { + spin_unlock_bh(&ipt_acc_lock); + printk("ACCOUNT: ipt_acc_get_ctl: not enough space (%u < %u < %lu)" + " to store table names\n", *len, size, PAGE_SIZE); + ret = -ENOMEM; + break; + } + /* Copy table names to userspace */ + tnames = ipt_acc_tmpbuf; + for (i = 0; i < ACCOUNT_MAX_TABLES; i++) { + if (ipt_acc_tables[i].name[0] != 0) { + name_len = strlen (ipt_acc_tables[i].name) + 1; + memcpy(tnames, ipt_acc_tables[i].name, name_len); + tnames += name_len; + } + } + spin_unlock_bh(&ipt_acc_lock); + + /* Terminating NULL character */ + *tnames = 0; + + /* Transfer to userspace */ + if (copy_to_user(user, ipt_acc_tmpbuf, size)) + return -EFAULT; + + ret = 0; + break; + } + default: + printk("ACCOUNT: ipt_acc_get_ctl: unknown request %i\n", cmd); + } + + return ret; +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) +static struct xt_target xt_acc_reg = { +#else +static struct ipt_target ipt_acc_reg = { +#endif + .name = "ACCOUNT", +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) + .family = AF_INET, +#endif + .target = ipt_acc_target, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) + .targetsize = sizeof(struct ipt_acc_info), +#endif + .checkentry = ipt_acc_checkentry, + .destroy = ipt_acc_destroy, + .me = THIS_MODULE +}; + +static struct nf_sockopt_ops ipt_acc_sockopts = { + .pf = PF_INET, + .set_optmin = IPT_SO_SET_ACCOUNT_HANDLE_FREE, + .set_optmax = IPT_SO_SET_ACCOUNT_MAX+1, + .set = ipt_acc_set_ctl, + .get_optmin = IPT_SO_GET_ACCOUNT_PREPARE_READ, + .get_optmax = IPT_SO_GET_ACCOUNT_MAX+1, + .get = ipt_acc_get_ctl +}; + +static int __init init(void) +{ + init_MUTEX(&ipt_acc_userspace_mutex); + + if ((ipt_acc_tables = + kmalloc(ACCOUNT_MAX_TABLES * + sizeof(struct ipt_acc_table), GFP_KERNEL)) == NULL) { + printk("ACCOUNT: Out of memory allocating account_tables structure"); + goto error_cleanup; + } + memset(ipt_acc_tables, 0, + ACCOUNT_MAX_TABLES * sizeof(struct ipt_acc_table)); + + if ((ipt_acc_handles = + kmalloc(ACCOUNT_MAX_HANDLES * + sizeof(struct ipt_acc_handle), GFP_KERNEL)) == NULL) { + printk("ACCOUNT: Out of memory allocating account_handles structure"); + goto error_cleanup; + } + memset(ipt_acc_handles, 0, + ACCOUNT_MAX_HANDLES * sizeof(struct ipt_acc_handle)); + + /* Allocate one page as temporary storage */ + if ((ipt_acc_tmpbuf = (void*)__get_free_page(GFP_KERNEL)) == NULL) { + printk("ACCOUNT: Out of memory for temporary buffer page\n"); + goto error_cleanup; + } + + /* Register setsockopt */ + if (nf_register_sockopt(&ipt_acc_sockopts) < 0) { + printk("ACCOUNT: Can't register sockopts. Aborting\n"); + goto error_cleanup; + } + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) + if (xt_register_target(&xt_acc_reg)) +#else + if (ipt_register_target(&ipt_acc_reg)) +#endif + goto error_cleanup; + + return 0; + +error_cleanup: + if(ipt_acc_tables) + kfree(ipt_acc_tables); + if(ipt_acc_handles) + kfree(ipt_acc_handles); + if (ipt_acc_tmpbuf) + free_page((unsigned long)ipt_acc_tmpbuf); + + return -EINVAL; +} + +static void __exit fini(void) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) + xt_unregister_target(&xt_acc_reg); +#else + ipt_unregister_target(&ipt_acc_reg); +#endif + + nf_unregister_sockopt(&ipt_acc_sockopts); + + kfree(ipt_acc_tables); + kfree(ipt_acc_handles); + free_page((unsigned long)ipt_acc_tmpbuf); +} + +module_init(init); +module_exit(fini); +MODULE_LICENSE("GPL"); diff --git a/extensions/xt_ACCOUNT.h b/extensions/xt_ACCOUNT.h new file mode 100644 index 0000000..5fb119a --- /dev/null +++ b/extensions/xt_ACCOUNT.h @@ -0,0 +1,111 @@ +/*************************************************************************** + * Copyright (C) 2004-2006 by Intra2net AG * + * opensource@intra2net.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License * + * version 2 as published by the Free Software Foundation; * + * * + ***************************************************************************/ + +#ifndef _IPT_ACCOUNT_H +#define _IPT_ACCOUNT_H + +#define IPT_SO_SET_ACCOUNT_HANDLE_FREE (IPT_BASE_CTL + 3) +#define IPT_SO_SET_ACCOUNT_HANDLE_FREE_ALL (IPT_BASE_CTL + 4) +#define IPT_SO_SET_ACCOUNT_MAX IPT_SO_SET_ACCOUNT_HANDLE_FREE_ALL + +#define IPT_SO_GET_ACCOUNT_PREPARE_READ (IPT_BASE_CTL + 4) +#define IPT_SO_GET_ACCOUNT_PREPARE_READ_FLUSH (IPT_BASE_CTL + 5) +#define IPT_SO_GET_ACCOUNT_GET_DATA (IPT_BASE_CTL + 6) +#define IPT_SO_GET_ACCOUNT_GET_HANDLE_USAGE (IPT_BASE_CTL + 7) +#define IPT_SO_GET_ACCOUNT_GET_TABLE_NAMES (IPT_BASE_CTL + 8) +#define IPT_SO_GET_ACCOUNT_MAX IPT_SO_GET_ACCOUNT_GET_TABLE_NAMES + +#define ACCOUNT_MAX_TABLES 128 +#define ACCOUNT_TABLE_NAME_LEN 32 +#define ACCOUNT_MAX_HANDLES 10 + +/* Structure for the userspace part of ipt_ACCOUNT */ +struct ipt_acc_info { + uint32_t net_ip; + uint32_t net_mask; + char table_name[ACCOUNT_TABLE_NAME_LEN]; + int32_t table_nr; +}; + +/* Internal table structure, generated by check_entry() */ +struct ipt_acc_table { + char name[ACCOUNT_TABLE_NAME_LEN]; /* name of the table */ + uint32_t ip; /* base IP of network */ + uint32_t netmask; /* netmask of the network */ + unsigned char depth; /* size of network: + 0: 8 bit, 1: 16bit, 2: 24 bit */ + uint32_t refcount; /* refcount of this table. + if zero, destroy it */ + uint32_t itemcount; /* number of IPs in this table */ + void *data; /* pointer to the actual data, + depending on netmask */ +}; + +/* Internal handle structure */ +struct ipt_acc_handle { + uint32_t ip; /* base IP of network. Used for + caculating the final IP during + get_data() */ + unsigned char depth; /* size of network. See above for + details */ + uint32_t itemcount; /* number of IPs in this table */ + void *data; /* pointer to the actual data, + depending on size */ +}; + +/* Handle structure for communication with the userspace library */ +struct ipt_acc_handle_sockopt { + uint32_t handle_nr; /* Used for HANDLE_FREE */ + char name[ACCOUNT_TABLE_NAME_LEN]; /* Used for HANDLE_PREPARE_READ/ + HANDLE_READ_FLUSH */ + uint32_t itemcount; /* Used for HANDLE_PREPARE_READ/ + HANDLE_READ_FLUSH */ +}; + +/* Used for every IP entry + Size is 16 bytes so that 256 (class C network) * 16 + fits in one kernel (zero) page */ +struct ipt_acc_ip { + uint32_t src_packets; + uint32_t src_bytes; + uint32_t dst_packets; + uint32_t dst_bytes; +}; + +/* + Used for every IP when returning data +*/ +struct ipt_acc_handle_ip { + uint32_t ip; + uint32_t src_packets; + uint32_t src_bytes; + uint32_t dst_packets; + uint32_t dst_bytes; +}; + +/* + The IPs are organized as an array so that direct slot + calculations are possible. + Only 8 bit networks are preallocated, 16/24 bit networks + allocate their slots when needed -> very efficent. +*/ +struct ipt_acc_mask_24 { + struct ipt_acc_ip ip[256]; +}; + +struct ipt_acc_mask_16 { + struct ipt_acc_mask_24 *mask_24[256]; +}; + +struct ipt_acc_mask_8 { + struct ipt_acc_mask_16 *mask_16[256]; +}; + +#endif /*_IPT_ACCOUNT_H*/ diff --git a/mconfig b/mconfig index 47761a8..b295e8c 100644 --- a/mconfig +++ b/mconfig @@ -1,5 +1,6 @@ # -*- Makefile -*- # +build_ACCOUNT=m build_CHAOS=m build_DELUDE=m build_DHCPMAC=m From 06c01131e8713255ca1aac5810f29faccd1aef6b Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 5 Sep 2009 02:40:18 +0200 Subject: [PATCH 02/15] ACCOUNT: remove trailing whitespace --- extensions/libxt_ACCOUNT.c | 2 +- extensions/xt_ACCOUNT.c | 148 ++++++++++++++++++------------------- extensions/xt_ACCOUNT.h | 16 ++-- 3 files changed, 83 insertions(+), 83 deletions(-) diff --git a/extensions/libxt_ACCOUNT.c b/extensions/libxt_ACCOUNT.c index 55a6362..a6049b4 100644 --- a/extensions/libxt_ACCOUNT.c +++ b/extensions/libxt_ACCOUNT.c @@ -146,7 +146,7 @@ static void print_it(const void *ip, printf("--"); printf("%s ", opts[0].name); - a.s_addr = accountinfo->net_ip; + a.s_addr = accountinfo->net_ip; printf("%s", print_helper_ip(a)); a.s_addr = accountinfo->net_mask; printf("%s", print_helper_mask(a)); diff --git a/extensions/xt_ACCOUNT.c b/extensions/xt_ACCOUNT.c index edac229..b5b74de 100644 --- a/extensions/xt_ACCOUNT.c +++ b/extensions/xt_ACCOUNT.c @@ -114,12 +114,12 @@ static void ipt_acc_data_free(void *data, unsigned char depth) return; } - printk("ACCOUNT: ipt_acc_data_free called with unknown depth: %d\n", + printk("ACCOUNT: ipt_acc_data_free called with unknown depth: %d\n", depth); return; } -/* Look for existing table / insert new one. +/* Look for existing table / insert new one. Return internal ID or -1 on error */ static int ipt_acc_table_insert(char *name, uint32_t ip, uint32_t netmask) { @@ -130,18 +130,18 @@ static int ipt_acc_table_insert(char *name, uint32_t ip, uint32_t netmask) /* Look for existing table */ for (i = 0; i < ACCOUNT_MAX_TABLES; i++) { - if (strncmp(ipt_acc_tables[i].name, name, + if (strncmp(ipt_acc_tables[i].name, name, ACCOUNT_TABLE_NAME_LEN) == 0) { DEBUGP("ACCOUNT: Found existing slot: %d - " - "%u.%u.%u.%u/%u.%u.%u.%u\n", i, - NIPQUAD(ipt_acc_tables[i].ip), + "%u.%u.%u.%u/%u.%u.%u.%u\n", i, + NIPQUAD(ipt_acc_tables[i].ip), NIPQUAD(ipt_acc_tables[i].netmask)); - if (ipt_acc_tables[i].ip != ip + if (ipt_acc_tables[i].ip != ip || ipt_acc_tables[i].netmask != netmask) { printk("ACCOUNT: Table %s found, but IP/netmask mismatch. " "IP/netmask found: %u.%u.%u.%u/%u.%u.%u.%u\n", - name, NIPQUAD(ipt_acc_tables[i].ip), + name, NIPQUAD(ipt_acc_tables[i].ip), NIPQUAD(ipt_acc_tables[i].netmask)); return -1; } @@ -184,14 +184,14 @@ static int ipt_acc_table_insert(char *name, uint32_t ip, uint32_t netmask) ipt_acc_tables[i].depth = 2; DEBUGP("ACCOUNT: calculated netsize: %u -> " - "ipt_acc_table depth %u\n", netsize, + "ipt_acc_table depth %u\n", netsize, ipt_acc_tables[i].depth); ipt_acc_tables[i].refcount++; if ((ipt_acc_tables[i].data = ipt_acc_zalloc_page()) == NULL) { printk("ACCOUNT: out of memory for data of table: %s\n", name); - memset(&ipt_acc_tables[i], 0, + memset(&ipt_acc_tables[i], 0, sizeof(struct ipt_acc_table)); return -1; } @@ -257,7 +257,7 @@ static int ipt_acc_checkentry(const char *tablename, return 0; #endif } - /* Table nr caching so we don't have to do an extra string compare + /* Table nr caching so we don't have to do an extra string compare for every packet */ info->table_nr = table_nr; @@ -299,27 +299,27 @@ static void ipt_acc_destroy( spin_lock_bh(&ipt_acc_lock); - DEBUGP("ACCOUNT: ipt_acc_deleteentry called for table: %s (#%d)\n", + DEBUGP("ACCOUNT: ipt_acc_deleteentry called for table: %s (#%d)\n", info->table_name, info->table_nr); info->table_nr = -1; /* Set back to original state */ /* Look for table */ for (i = 0; i < ACCOUNT_MAX_TABLES; i++) { - if (strncmp(ipt_acc_tables[i].name, info->table_name, + if (strncmp(ipt_acc_tables[i].name, info->table_name, ACCOUNT_TABLE_NAME_LEN) == 0) { DEBUGP("ACCOUNT: Found table at slot: %d\n", i); ipt_acc_tables[i].refcount--; - DEBUGP("ACCOUNT: Refcount left: %d\n", + DEBUGP("ACCOUNT: Refcount left: %d\n", ipt_acc_tables[i].refcount); /* Table not needed anymore? */ if (ipt_acc_tables[i].refcount == 0) { DEBUGP("ACCOUNT: Destroying table at slot: %d\n", i); - ipt_acc_data_free(ipt_acc_tables[i].data, + ipt_acc_data_free(ipt_acc_tables[i].data, ipt_acc_tables[i].depth); - memset(&ipt_acc_tables[i], 0, + memset(&ipt_acc_tables[i], 0, sizeof(struct ipt_acc_table)); } @@ -342,7 +342,7 @@ static void ipt_acc_depth0_insert(struct ipt_acc_mask_24 *mask_24, char is_src_new_ip = 0, is_dst_new_ip = 0; /* Check if this entry is new */ DEBUGP("ACCOUNT: ipt_acc_depth0_insert: %u.%u.%u.%u/%u.%u.%u.%u " - "for net %u.%u.%u.%u/%u.%u.%u.%u, size: %u\n", NIPQUAD(src_ip), + "for net %u.%u.%u.%u/%u.%u.%u.%u, size: %u\n", NIPQUAD(src_ip), NIPQUAD(dst_ip), NIPQUAD(net_ip), NIPQUAD(netmask), size); /* Check if src/dst is inside our network. */ @@ -356,7 +356,7 @@ static void ipt_acc_depth0_insert(struct ipt_acc_mask_24 *mask_24, if (!is_src && !is_dst) { DEBUGP("ACCOUNT: Skipping packet %u.%u.%u.%u/%u.%u.%u.%u " - "for net %u.%u.%u.%u/%u.%u.%u.%u\n", NIPQUAD(src_ip), + "for net %u.%u.%u.%u/%u.%u.%u.%u\n", NIPQUAD(src_ip), NIPQUAD(dst_ip), NIPQUAD(net_ip), NIPQUAD(netmask)); return; } @@ -369,7 +369,7 @@ static void ipt_acc_depth0_insert(struct ipt_acc_mask_24 *mask_24, if (is_src) { /* Calculate network slot */ DEBUGP("ACCOUNT: Calculated SRC 8 bit network slot: %d\n", src_slot); - if (!mask_24->ip[src_slot].src_packets + if (!mask_24->ip[src_slot].src_packets && !mask_24->ip[src_slot].dst_packets) is_src_new_ip = 1; @@ -378,7 +378,7 @@ static void ipt_acc_depth0_insert(struct ipt_acc_mask_24 *mask_24, } if (is_dst) { DEBUGP("ACCOUNT: Calculated DST 8 bit network slot: %d\n", dst_slot); - if (!mask_24->ip[dst_slot].src_packets + if (!mask_24->ip[dst_slot].src_packets && !mask_24->ip[dst_slot].dst_packets) is_dst_new_ip = 1; @@ -390,7 +390,7 @@ static void ipt_acc_depth0_insert(struct ipt_acc_mask_24 *mask_24, DEBUGP("ACCOUNT: Itemcounter before: %d\n", *itemcount); if (src_slot == dst_slot) { if (is_src_new_ip || is_dst_new_ip) { - DEBUGP("ACCOUNT: src_slot == dst_slot: %d, %d\n", + DEBUGP("ACCOUNT: src_slot == dst_slot: %d, %d\n", is_src_new_ip, is_dst_new_ip); (*itemcount)++; } @@ -407,8 +407,8 @@ static void ipt_acc_depth0_insert(struct ipt_acc_mask_24 *mask_24, DEBUGP("ACCOUNT: Itemcounter after: %d\n", *itemcount); } -static void ipt_acc_depth1_insert(struct ipt_acc_mask_16 *mask_16, - uint32_t net_ip, uint32_t netmask, +static void ipt_acc_depth1_insert(struct ipt_acc_mask_16 *mask_16, + uint32_t net_ip, uint32_t netmask, uint32_t src_ip, uint32_t dst_ip, uint32_t size, uint32_t *itemcount) { @@ -418,7 +418,7 @@ static void ipt_acc_depth1_insert(struct ipt_acc_mask_16 *mask_16, DEBUGP("ACCOUNT: Calculated SRC 16 bit network slot: %d\n", slot); /* Do we need to create a new mask_24 bucket? */ - if (!mask_16->mask_24[slot] && (mask_16->mask_24[slot] = + if (!mask_16->mask_24[slot] && (mask_16->mask_24[slot] = ipt_acc_zalloc_page()) == NULL) { printk("ACCOUNT: Can't process packet because out of memory!\n"); return; @@ -434,7 +434,7 @@ static void ipt_acc_depth1_insert(struct ipt_acc_mask_16 *mask_16, DEBUGP("ACCOUNT: Calculated DST 16 bit network slot: %d\n", slot); /* Do we need to create a new mask_24 bucket? */ - if (!mask_16->mask_24[slot] && (mask_16->mask_24[slot] + if (!mask_16->mask_24[slot] && (mask_16->mask_24[slot] = ipt_acc_zalloc_page()) == NULL) { printk("ACCOUT: Can't process packet because out of memory!\n"); return; @@ -445,7 +445,7 @@ static void ipt_acc_depth1_insert(struct ipt_acc_mask_16 *mask_16, } } -static void ipt_acc_depth2_insert(struct ipt_acc_mask_8 *mask_8, +static void ipt_acc_depth2_insert(struct ipt_acc_mask_8 *mask_8, uint32_t net_ip, uint32_t netmask, uint32_t src_ip, uint32_t dst_ip, uint32_t size, uint32_t *itemcount) @@ -456,7 +456,7 @@ static void ipt_acc_depth2_insert(struct ipt_acc_mask_8 *mask_8, DEBUGP("ACCOUNT: Calculated SRC 24 bit network slot: %d\n", slot); /* Do we need to create a new mask_24 bucket? */ - if (!mask_8->mask_16[slot] && (mask_8->mask_16[slot] + if (!mask_8->mask_16[slot] && (mask_8->mask_16[slot] = ipt_acc_zalloc_page()) == NULL) { printk("ACCOUNT: Can't process packet because out of memory!\n"); return; @@ -472,7 +472,7 @@ static void ipt_acc_depth2_insert(struct ipt_acc_mask_8 *mask_8, DEBUGP("ACCOUNT: Calculated DST 24 bit network slot: %d\n", slot); /* Do we need to create a new mask_24 bucket? */ - if (!mask_8->mask_16[slot] && (mask_8->mask_16[slot] + if (!mask_8->mask_16[slot] && (mask_8->mask_16[slot] = ipt_acc_zalloc_page()) == NULL) { printk("ACCOUNT: Can't process packet because out of memory!\n"); return; @@ -532,7 +532,7 @@ static unsigned int ipt_acc_target(struct sk_buff **pskb, if (ipt_acc_tables[info->table_nr].name[0] == 0) { printk("ACCOUNT: ipt_acc_target: Invalid table id %u. " - "IPs %u.%u.%u.%u/%u.%u.%u.%u\n", info->table_nr, + "IPs %u.%u.%u.%u/%u.%u.%u.%u\n", info->table_nr, NIPQUAD(src_ip), NIPQUAD(dst_ip)); spin_unlock_bh(&ipt_acc_lock); return IPT_CONTINUE; @@ -543,7 +543,7 @@ static unsigned int ipt_acc_target(struct sk_buff **pskb, /* Count packet and check if the IP is new */ ipt_acc_depth0_insert( (struct ipt_acc_mask_24 *)ipt_acc_tables[info->table_nr].data, - ipt_acc_tables[info->table_nr].ip, + ipt_acc_tables[info->table_nr].ip, ipt_acc_tables[info->table_nr].netmask, src_ip, dst_ip, size, &ipt_acc_tables[info->table_nr].itemcount); spin_unlock_bh(&ipt_acc_lock); @@ -554,7 +554,7 @@ static unsigned int ipt_acc_target(struct sk_buff **pskb, if (ipt_acc_tables[info->table_nr].depth == 1) { ipt_acc_depth1_insert( (struct ipt_acc_mask_16 *)ipt_acc_tables[info->table_nr].data, - ipt_acc_tables[info->table_nr].ip, + ipt_acc_tables[info->table_nr].ip, ipt_acc_tables[info->table_nr].netmask, src_ip, dst_ip, size, &ipt_acc_tables[info->table_nr].itemcount); spin_unlock_bh(&ipt_acc_lock); @@ -565,7 +565,7 @@ static unsigned int ipt_acc_target(struct sk_buff **pskb, if (ipt_acc_tables[info->table_nr].depth == 2) { ipt_acc_depth2_insert( (struct ipt_acc_mask_8 *)ipt_acc_tables[info->table_nr].data, - ipt_acc_tables[info->table_nr].ip, + ipt_acc_tables[info->table_nr].ip, ipt_acc_tables[info->table_nr].netmask, src_ip, dst_ip, size, &ipt_acc_tables[info->table_nr].itemcount); spin_unlock_bh(&ipt_acc_lock); @@ -573,7 +573,7 @@ static unsigned int ipt_acc_target(struct sk_buff **pskb, } printk("ACCOUNT: ipt_acc_target: Unable to process packet. " - "Table id %u. IPs %u.%u.%u.%u/%u.%u.%u.%u\n", + "Table id %u. IPs %u.%u.%u.%u/%u.%u.%u.%u\n", info->table_nr, NIPQUAD(src_ip), NIPQUAD(dst_ip)); spin_unlock_bh(&ipt_acc_lock); @@ -583,11 +583,11 @@ static unsigned int ipt_acc_target(struct sk_buff **pskb, /* Functions dealing with "handles": Handles are snapshots of a accounting state. - + read snapshots are only for debugging the code and are very expensive concerning speed/memory compared to read_and_flush. - + The functions aren't protected by spinlocks themselves as this is done in the ioctl part of the code. */ @@ -604,7 +604,7 @@ static int ipt_acc_handle_find_slot(void) for (i = 0; i < ACCOUNT_MAX_HANDLES; i++) { /* Found free slot */ if (ipt_acc_handles[i].data == NULL) { - /* Don't "mark" data as used as we are protected by a spinlock + /* Don't "mark" data as used as we are protected by a spinlock by the calling function. handle_find_slot() is only a function to prevent code duplication. */ return i; @@ -625,7 +625,7 @@ static int ipt_acc_handle_free(unsigned int handle) return -EINVAL; } - ipt_acc_data_free(ipt_acc_handles[handle].data, + ipt_acc_data_free(ipt_acc_handles[handle].data, ipt_acc_handles[handle].depth); memset (&ipt_acc_handles[handle], 0, sizeof (struct ipt_acc_handle)); return 0; @@ -640,7 +640,7 @@ static int ipt_acc_handle_prepare_read(char *tablename, unsigned char depth; for (table_nr = 0; table_nr < ACCOUNT_MAX_TABLES; table_nr++) - if (strncmp(ipt_acc_tables[table_nr].name, tablename, + if (strncmp(ipt_acc_tables[table_nr].name, tablename, ACCOUNT_TABLE_NAME_LEN) == 0) break; @@ -665,11 +665,11 @@ static int ipt_acc_handle_prepare_read(char *tablename, /* Recursive copy of complete data structure */ depth = dest->depth; if (depth == 0) { - memcpy(dest->data, - ipt_acc_tables[table_nr].data, + memcpy(dest->data, + ipt_acc_tables[table_nr].data, sizeof(struct ipt_acc_mask_24)); } else if (depth == 1) { - struct ipt_acc_mask_16 *src_16 = + struct ipt_acc_mask_16 *src_16 = (struct ipt_acc_mask_16 *)ipt_acc_tables[table_nr].data; struct ipt_acc_mask_16 *network_16 = (struct ipt_acc_mask_16 *)dest->data; @@ -677,7 +677,7 @@ static int ipt_acc_handle_prepare_read(char *tablename, for (b = 0; b <= 255; b++) { if (src_16->mask_24[b]) { - if ((network_16->mask_24[b] = + if ((network_16->mask_24[b] = ipt_acc_zalloc_page()) == NULL) { printk("ACCOUNT: out of memory during copy of 16 bit " "network in ipt_acc_handle_prepare_read()\n"); @@ -685,21 +685,21 @@ static int ipt_acc_handle_prepare_read(char *tablename, return -1; } - memcpy(network_16->mask_24[b], src_16->mask_24[b], + memcpy(network_16->mask_24[b], src_16->mask_24[b], sizeof(struct ipt_acc_mask_24)); } } } else if(depth == 2) { - struct ipt_acc_mask_8 *src_8 = + struct ipt_acc_mask_8 *src_8 = (struct ipt_acc_mask_8 *)ipt_acc_tables[table_nr].data; - struct ipt_acc_mask_8 *network_8 = + struct ipt_acc_mask_8 *network_8 = (struct ipt_acc_mask_8 *)dest->data; struct ipt_acc_mask_16 *src_16, *network_16; unsigned int a, b; for (a = 0; a <= 255; a++) { if (src_8->mask_16[a]) { - if ((network_8->mask_16[a] = + if ((network_8->mask_16[a] = ipt_acc_zalloc_page()) == NULL) { printk("ACCOUNT: out of memory during copy of 24 bit network" " in ipt_acc_handle_prepare_read()\n"); @@ -707,7 +707,7 @@ static int ipt_acc_handle_prepare_read(char *tablename, return -1; } - memcpy(network_8->mask_16[a], src_8->mask_16[a], + memcpy(network_8->mask_16[a], src_8->mask_16[a], sizeof(struct ipt_acc_mask_16)); src_16 = src_8->mask_16[a]; @@ -715,7 +715,7 @@ static int ipt_acc_handle_prepare_read(char *tablename, for (b = 0; b <= 255; b++) { if (src_16->mask_24[b]) { - if ((network_16->mask_24[b] = + if ((network_16->mask_24[b] = ipt_acc_zalloc_page()) == NULL) { printk("ACCOUNT: out of memory during copy of 16 bit" " network in ipt_acc_handle_prepare_read()\n"); @@ -723,7 +723,7 @@ static int ipt_acc_handle_prepare_read(char *tablename, return -1; } - memcpy(network_16->mask_24[b], src_16->mask_24[b], + memcpy(network_16->mask_24[b], src_16->mask_24[b], sizeof(struct ipt_acc_mask_24)); } } @@ -732,7 +732,7 @@ static int ipt_acc_handle_prepare_read(char *tablename, } *count = ipt_acc_tables[table_nr].itemcount; - + return 0; } @@ -744,7 +744,7 @@ static int ipt_acc_handle_prepare_read_flush(char *tablename, void *new_data_page; for (table_nr = 0; table_nr < ACCOUNT_MAX_TABLES; table_nr++) - if (strncmp(ipt_acc_tables[table_nr].name, tablename, + if (strncmp(ipt_acc_tables[table_nr].name, tablename, ACCOUNT_TABLE_NAME_LEN) == 0) break; @@ -779,18 +779,18 @@ static int ipt_acc_handle_prepare_read_flush(char *tablename, We only copy entries != 0 to increase performance. */ static int ipt_acc_handle_copy_data(void *to_user, unsigned long *to_user_pos, - unsigned long *tmpbuf_pos, + unsigned long *tmpbuf_pos, struct ipt_acc_mask_24 *data, uint32_t net_ip, uint32_t net_OR_mask) { struct ipt_acc_handle_ip handle_ip; size_t handle_ip_size = sizeof (struct ipt_acc_handle_ip); unsigned int i; - + for (i = 0; i <= 255; i++) { if (data->ip[i].src_packets || data->ip[i].dst_packets) { handle_ip.ip = net_ip | net_OR_mask | (i<<24); - + handle_ip.src_packets = data->ip[i].src_packets; handle_ip.src_bytes = data->ip[i].src_bytes; handle_ip.dst_packets = data->ip[i].dst_packets; @@ -808,11 +808,11 @@ static int ipt_acc_handle_copy_data(void *to_user, unsigned long *to_user_pos, *tmpbuf_pos += handle_ip_size; } } - + return 0; } - -/* Copy the data from our internal structure + +/* Copy the data from our internal structure We only copy entries != 0 to increase performance. Overwrites ipt_acc_tmpbuf. */ @@ -838,12 +838,12 @@ static int ipt_acc_handle_get_data(uint32_t handle, void *to_user) /* 8 bit network */ if (depth == 0) { - struct ipt_acc_mask_24 *network = + struct ipt_acc_mask_24 *network = (struct ipt_acc_mask_24*)ipt_acc_handles[handle].data; if (ipt_acc_handle_copy_data(to_user, &to_user_pos, &tmpbuf_pos, network, net_ip, 0)) return -1; - + /* Flush remaining data to userspace */ if (tmpbuf_pos) if (copy_to_user(to_user+to_user_pos, ipt_acc_tmpbuf, tmpbuf_pos)) @@ -854,12 +854,12 @@ static int ipt_acc_handle_get_data(uint32_t handle, void *to_user) /* 16 bit network */ if (depth == 1) { - struct ipt_acc_mask_16 *network_16 = + struct ipt_acc_mask_16 *network_16 = (struct ipt_acc_mask_16*)ipt_acc_handles[handle].data; unsigned int b; for (b = 0; b <= 255; b++) { if (network_16->mask_24[b]) { - struct ipt_acc_mask_24 *network = + struct ipt_acc_mask_24 *network = (struct ipt_acc_mask_24*)network_16->mask_24[b]; if (ipt_acc_handle_copy_data(to_user, &to_user_pos, &tmpbuf_pos, network, net_ip, (b << 16))) @@ -877,16 +877,16 @@ static int ipt_acc_handle_get_data(uint32_t handle, void *to_user) /* 24 bit network */ if (depth == 2) { - struct ipt_acc_mask_8 *network_8 = + struct ipt_acc_mask_8 *network_8 = (struct ipt_acc_mask_8*)ipt_acc_handles[handle].data; unsigned int a, b; for (a = 0; a <= 255; a++) { if (network_8->mask_16[a]) { - struct ipt_acc_mask_16 *network_16 = + struct ipt_acc_mask_16 *network_16 = (struct ipt_acc_mask_16*)network_8->mask_16[a]; for (b = 0; b <= 255; b++) { if (network_16->mask_24[b]) { - struct ipt_acc_mask_24 *network = + struct ipt_acc_mask_24 *network = (struct ipt_acc_mask_24*)network_16->mask_24[b]; if (ipt_acc_handle_copy_data(to_user, &to_user_pos, &tmpbuf_pos, @@ -904,11 +904,11 @@ static int ipt_acc_handle_get_data(uint32_t handle, void *to_user) return 0; } - + return -1; } -static int ipt_acc_set_ctl(struct sock *sk, int cmd, +static int ipt_acc_set_ctl(struct sock *sk, int cmd, void *user, unsigned int len) { struct ipt_acc_handle_sockopt handle; @@ -921,7 +921,7 @@ static int ipt_acc_set_ctl(struct sock *sk, int cmd, case IPT_SO_SET_ACCOUNT_HANDLE_FREE: if (len != sizeof(struct ipt_acc_handle_sockopt)) { printk("ACCOUNT: ipt_acc_set_ctl: wrong data size (%u != %zu) " - "for IPT_SO_SET_HANDLE_FREE\n", + "for IPT_SO_SET_HANDLE_FREE\n", len, sizeof(struct ipt_acc_handle_sockopt)); break; } @@ -972,7 +972,7 @@ static int ipt_acc_get_ctl(struct sock *sk, int cmd, void *user, int *len) break; } - if (copy_from_user (&handle, user, + if (copy_from_user (&handle, user, sizeof(struct ipt_acc_handle_sockopt))) { return -EFAULT; break; @@ -1001,7 +1001,7 @@ static int ipt_acc_get_ctl(struct sock *sk, int cmd, void *user, int *len) sizeof(struct ipt_acc_handle)); up(&ipt_acc_userspace_mutex); - if (copy_to_user(user, &handle, + if (copy_to_user(user, &handle, sizeof(struct ipt_acc_handle_sockopt))) { return -EFAULT; break; @@ -1017,7 +1017,7 @@ static int ipt_acc_get_ctl(struct sock *sk, int cmd, void *user, int *len) break; } - if (copy_from_user (&handle, user, + if (copy_from_user (&handle, user, sizeof(struct ipt_acc_handle_sockopt))) { return -EFAULT; break; @@ -1066,7 +1066,7 @@ static int ipt_acc_get_ctl(struct sock *sk, int cmd, void *user, int *len) handle.itemcount++; up(&ipt_acc_userspace_mutex); - if (copy_to_user(user, &handle, + if (copy_to_user(user, &handle, sizeof(struct ipt_acc_handle_sockopt))) { return -EFAULT; break; @@ -1154,8 +1154,8 @@ static int __init init(void) { init_MUTEX(&ipt_acc_userspace_mutex); - if ((ipt_acc_tables = - kmalloc(ACCOUNT_MAX_TABLES * + if ((ipt_acc_tables = + kmalloc(ACCOUNT_MAX_TABLES * sizeof(struct ipt_acc_table), GFP_KERNEL)) == NULL) { printk("ACCOUNT: Out of memory allocating account_tables structure"); goto error_cleanup; @@ -1163,8 +1163,8 @@ static int __init init(void) memset(ipt_acc_tables, 0, ACCOUNT_MAX_TABLES * sizeof(struct ipt_acc_table)); - if ((ipt_acc_handles = - kmalloc(ACCOUNT_MAX_HANDLES * + if ((ipt_acc_handles = + kmalloc(ACCOUNT_MAX_HANDLES * sizeof(struct ipt_acc_handle), GFP_KERNEL)) == NULL) { printk("ACCOUNT: Out of memory allocating account_handles structure"); goto error_cleanup; diff --git a/extensions/xt_ACCOUNT.h b/extensions/xt_ACCOUNT.h index 5fb119a..0051c56 100644 --- a/extensions/xt_ACCOUNT.h +++ b/extensions/xt_ACCOUNT.h @@ -39,24 +39,24 @@ struct ipt_acc_table { char name[ACCOUNT_TABLE_NAME_LEN]; /* name of the table */ uint32_t ip; /* base IP of network */ uint32_t netmask; /* netmask of the network */ - unsigned char depth; /* size of network: + unsigned char depth; /* size of network: 0: 8 bit, 1: 16bit, 2: 24 bit */ - uint32_t refcount; /* refcount of this table. + uint32_t refcount; /* refcount of this table. if zero, destroy it */ uint32_t itemcount; /* number of IPs in this table */ - void *data; /* pointer to the actual data, + void *data; /* pointer to the actual data, depending on netmask */ }; /* Internal handle structure */ struct ipt_acc_handle { - uint32_t ip; /* base IP of network. Used for + uint32_t ip; /* base IP of network. Used for caculating the final IP during get_data() */ - unsigned char depth; /* size of network. See above for + unsigned char depth; /* size of network. See above for details */ uint32_t itemcount; /* number of IPs in this table */ - void *data; /* pointer to the actual data, + void *data; /* pointer to the actual data, depending on size */ }; @@ -69,8 +69,8 @@ struct ipt_acc_handle_sockopt { HANDLE_READ_FLUSH */ }; -/* Used for every IP entry - Size is 16 bytes so that 256 (class C network) * 16 +/* Used for every IP entry + Size is 16 bytes so that 256 (class C network) * 16 fits in one kernel (zero) page */ struct ipt_acc_ip { uint32_t src_packets; From dd6cb27da4cd91320595602b70b7eb689083806c Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 5 Sep 2009 03:01:37 +0200 Subject: [PATCH 03/15] ACCOUNT: simple reformat, use tabs instead of spaces The result is not perfect, but at more manageable. --- extensions/libxt_ACCOUNT.c | 174 ++-- extensions/xt_ACCOUNT.c | 1702 ++++++++++++++++++------------------ extensions/xt_ACCOUNT.h | 94 +- 3 files changed, 985 insertions(+), 985 deletions(-) diff --git a/extensions/libxt_ACCOUNT.c b/extensions/libxt_ACCOUNT.c index a6049b4..c87a2ff 100644 --- a/extensions/libxt_ACCOUNT.c +++ b/extensions/libxt_ACCOUNT.c @@ -14,9 +14,9 @@ #include "xt_ACCOUNT.h" static struct option opts[] = { - { .name = "addr", .has_arg = 1, .flag = 0, .val = 'a' }, - { .name = "tname", .has_arg = 1, .flag = 0, .val = 't' }, - { .name = 0 } + { .name = "addr", .has_arg = 1, .flag = 0, .val = 'a' }, + { .name = "tname", .has_arg = 1, .flag = 0, .val = 't' }, + { .name = 0 } }; /* Compat glue for iptables 1.4.0 */ @@ -27,7 +27,7 @@ static struct option opts[] = { /* Function which prints out usage message. */ static void help(void) { - printf( + printf( "ACCOUNT v%s options:\n" " --%s ip/netmask\t\tBase network IP and netmask used for this table\n" " --%s name\t\t\tTable name for the userspace library\n", @@ -38,9 +38,9 @@ XTABLES_VERSION, opts[0].name, opts[1].name); static void init(struct xt_entry_target *t) { - struct ipt_acc_info *accountinfo = (struct ipt_acc_info *)t->data; + struct ipt_acc_info *accountinfo = (struct ipt_acc_info *)t->data; - accountinfo->table_nr = -1; + accountinfo->table_nr = -1; } #define IPT_ACCOUNT_OPT_ADDR 0x01 @@ -50,149 +50,149 @@ init(struct xt_entry_target *t) ate an option */ static int parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_target **target) + const void *entry, struct xt_entry_target **target) { - struct ipt_acc_info *accountinfo = (struct ipt_acc_info *)(*target)->data; - struct in_addr *addrs = NULL, mask; - unsigned int naddrs = 0; + struct ipt_acc_info *accountinfo = (struct ipt_acc_info *)(*target)->data; + struct in_addr *addrs = NULL, mask; + unsigned int naddrs = 0; - switch (c) { - case 'a': - if (*flags & IPT_ACCOUNT_OPT_ADDR) - xtables_error(PARAMETER_PROBLEM, "Can't specify --%s twice", - opts[0].name); + switch (c) { + case 'a': + if (*flags & IPT_ACCOUNT_OPT_ADDR) + xtables_error(PARAMETER_PROBLEM, "Can't specify --%s twice", + opts[0].name); - if (xtables_check_inverse(optarg, &invert, NULL, 0)) - xtables_error(PARAMETER_PROBLEM, "Unexpected `!' after --%s", - opts[0].name); + if (xtables_check_inverse(optarg, &invert, NULL, 0)) + xtables_error(PARAMETER_PROBLEM, "Unexpected `!' after --%s", + opts[0].name); #ifdef XTABLES_VERSION_CODE - xtables_ipparse_any(optarg, &addrs, &mask, &naddrs); + xtables_ipparse_any(optarg, &addrs, &mask, &naddrs); #else - parse_hostnetworkmask(optarg, &addrs, &mask, &naddrs); + parse_hostnetworkmask(optarg, &addrs, &mask, &naddrs); #endif - if (naddrs > 1) - xtables_error(PARAMETER_PROBLEM, "multiple IP addresses not allowed"); + if (naddrs > 1) + xtables_error(PARAMETER_PROBLEM, "multiple IP addresses not allowed"); - accountinfo->net_ip = addrs[0].s_addr; - accountinfo->net_mask = mask.s_addr; + accountinfo->net_ip = addrs[0].s_addr; + accountinfo->net_mask = mask.s_addr; - *flags |= IPT_ACCOUNT_OPT_ADDR; - break; + *flags |= IPT_ACCOUNT_OPT_ADDR; + break; - case 't': - if (*flags & IPT_ACCOUNT_OPT_TABLE) - xtables_error(PARAMETER_PROBLEM, - "Can't specify --%s twice", opts[1].name); + case 't': + if (*flags & IPT_ACCOUNT_OPT_TABLE) + xtables_error(PARAMETER_PROBLEM, + "Can't specify --%s twice", opts[1].name); - if (xtables_check_inverse(optarg, &invert, NULL, 0)) - xtables_error(PARAMETER_PROBLEM, - "Unexpected `!' after --%s", opts[1].name); + if (xtables_check_inverse(optarg, &invert, NULL, 0)) + xtables_error(PARAMETER_PROBLEM, + "Unexpected `!' after --%s", opts[1].name); - if (strlen(optarg) > ACCOUNT_TABLE_NAME_LEN - 1) - xtables_error(PARAMETER_PROBLEM, - "Maximum table name length %u for --%s", - ACCOUNT_TABLE_NAME_LEN - 1, opts[1].name); + if (strlen(optarg) > ACCOUNT_TABLE_NAME_LEN - 1) + xtables_error(PARAMETER_PROBLEM, + "Maximum table name length %u for --%s", + ACCOUNT_TABLE_NAME_LEN - 1, opts[1].name); - strcpy(accountinfo->table_name, optarg); - *flags |= IPT_ACCOUNT_OPT_TABLE; - break; + strcpy(accountinfo->table_name, optarg); + *flags |= IPT_ACCOUNT_OPT_TABLE; + break; - default: - return 0; - } - return 1; + default: + return 0; + } + return 1; } /* Final check; nothing. */ static void final_check(unsigned int flags) { - if (!(flags&IPT_ACCOUNT_OPT_ADDR) || !(flags&IPT_ACCOUNT_OPT_TABLE)) - xtables_error(PARAMETER_PROBLEM, "ACCOUNT: needs --%s and --%s", - opts[0].name, opts[1].name); + if (!(flags & IPT_ACCOUNT_OPT_ADDR) || !(flags & IPT_ACCOUNT_OPT_TABLE)) + xtables_error(PARAMETER_PROBLEM, "ACCOUNT: needs --%s and --%s", + opts[0].name, opts[1].name); } static const char *print_helper_ip(struct in_addr a) { #ifdef XTABLES_VERSION_CODE - return xtables_ipaddr_to_numeric(&a); + return xtables_ipaddr_to_numeric(&a); #else - return addr_to_dotted(&a); + return addr_to_dotted(&a); #endif } static const char *print_helper_mask(struct in_addr a) { #ifdef XTABLES_VERSION_CODE - return xtables_ipmask_to_numeric(&a); + return xtables_ipmask_to_numeric(&a); #else - return mask_to_dotted(&a); + return mask_to_dotted(&a); #endif } static void print_it(const void *ip, - const struct xt_entry_target *target, char do_prefix) + const struct xt_entry_target *target, char do_prefix) { - const struct ipt_acc_info *accountinfo - = (const struct ipt_acc_info *)target->data; - struct in_addr a; + const struct ipt_acc_info *accountinfo + = (const struct ipt_acc_info *)target->data; + struct in_addr a; - if (!do_prefix) - printf("ACCOUNT "); + if (!do_prefix) + printf("ACCOUNT "); - // Network information - if (do_prefix) - printf("--"); - printf("%s ", opts[0].name); + // Network information + if (do_prefix) + printf("--"); + printf("%s ", opts[0].name); - a.s_addr = accountinfo->net_ip; - printf("%s", print_helper_ip(a)); - a.s_addr = accountinfo->net_mask; - printf("%s", print_helper_mask(a)); + a.s_addr = accountinfo->net_ip; + printf("%s", print_helper_ip(a)); + a.s_addr = accountinfo->net_mask; + printf("%s", print_helper_mask(a)); - printf(" "); - if (do_prefix) - printf("--"); + printf(" "); + if (do_prefix) + printf("--"); - printf("%s %s", opts[1].name, accountinfo->table_name); + printf("%s %s", opts[1].name, accountinfo->table_name); } static void print(const void *ip, - const struct xt_entry_target *target, - int numeric) + const struct xt_entry_target *target, + int numeric) { - print_it (ip, target, 0); + print_it(ip, target, 0); } /* Saves the union ipt_targinfo in parsable form to stdout. */ static void save(const void *ip, const struct xt_entry_target *target) { - print_it(ip, target, 1); + print_it(ip, target, 1); } static struct xtables_target account = { - .next = NULL, - .name = "ACCOUNT", - .family = AF_INET, - .version = XTABLES_VERSION, - .size = XT_ALIGN(sizeof(struct ipt_acc_info)), - .userspacesize = offsetof(struct ipt_acc_info, table_nr), - .help = &help, - .init = &init, - .parse = &parse, - .final_check = &final_check, - .print = &print, - .save = &save, - .extra_opts = opts + .next = NULL, + .name = "ACCOUNT", + .family = AF_INET, + .version = XTABLES_VERSION, + .size = XT_ALIGN(sizeof(struct ipt_acc_info)), + .userspacesize = offsetof(struct ipt_acc_info, table_nr), + .help = &help, + .init = &init, + .parse = &parse, + .final_check = &final_check, + .print = &print, + .save = &save, + .extra_opts = opts }; void _init(void) { - xtables_register_target(&account); + xtables_register_target(&account); } diff --git a/extensions/xt_ACCOUNT.c b/extensions/xt_ACCOUNT.c index b5b74de..e034681 100644 --- a/extensions/xt_ACCOUNT.c +++ b/extensions/xt_ACCOUNT.c @@ -58,152 +58,152 @@ static struct semaphore ipt_acc_userspace_mutex; /* Allocates a page and clears it */ static void *ipt_acc_zalloc_page(void) { - // Don't use get_zeroed_page until it's fixed in the kernel. - // get_zeroed_page(GFP_ATOMIC) - void *mem = (void *)__get_free_page(GFP_ATOMIC); - if (mem) { - memset (mem, 0, PAGE_SIZE); - } + // Don't use get_zeroed_page until it's fixed in the kernel. + // get_zeroed_page(GFP_ATOMIC) + void *mem = (void *)__get_free_page(GFP_ATOMIC); + if (mem) { + memset (mem, 0, PAGE_SIZE); + } - return mem; + return mem; } /* Recursive free of all data structures */ static void ipt_acc_data_free(void *data, unsigned char depth) { - /* Empty data set */ - if (!data) - return; + /* Empty data set */ + if (!data) + return; - /* Free for 8 bit network */ - if (depth == 0) { - free_page((unsigned long)data); - return; - } + /* Free for 8 bit network */ + if (depth == 0) { + free_page((unsigned long)data); + return; + } - /* Free for 16 bit network */ - if (depth == 1) { - struct ipt_acc_mask_16 *mask_16 = (struct ipt_acc_mask_16 *)data; - unsigned int b; - for (b=0; b <= 255; b++) { - if (mask_16->mask_24[b]) { - free_page((unsigned long)mask_16->mask_24[b]); - } - } - free_page((unsigned long)data); - return; - } + /* Free for 16 bit network */ + if (depth == 1) { + struct ipt_acc_mask_16 *mask_16 = (struct ipt_acc_mask_16 *)data; + unsigned int b; + for (b = 0; b <= 255; b++) { + if (mask_16->mask_24[b]) { + free_page((unsigned long)mask_16->mask_24[b]); + } + } + free_page((unsigned long)data); + return; + } - /* Free for 24 bit network */ - if (depth == 2) { - unsigned int a, b; - for (a=0; a <= 255; a++) { - if (((struct ipt_acc_mask_8 *)data)->mask_16[a]) { - struct ipt_acc_mask_16 *mask_16 = (struct ipt_acc_mask_16*) - ((struct ipt_acc_mask_8 *)data)->mask_16[a]; + /* Free for 24 bit network */ + if (depth == 2) { + unsigned int a, b; + for (a = 0; a <= 255; a++) { + if (((struct ipt_acc_mask_8 *)data)->mask_16[a]) { + struct ipt_acc_mask_16 *mask_16 = (struct ipt_acc_mask_16*) + ((struct ipt_acc_mask_8 *)data)->mask_16[a]; - for (b=0; b <= 255; b++) { - if (mask_16->mask_24[b]) { - free_page((unsigned long)mask_16->mask_24[b]); - } - } - free_page((unsigned long)mask_16); - } - } - free_page((unsigned long)data); - return; - } + for (b = 0; b <= 255; b++) { + if (mask_16->mask_24[b]) { + free_page((unsigned long)mask_16->mask_24[b]); + } + } + free_page((unsigned long)mask_16); + } + } + free_page((unsigned long)data); + return; + } - printk("ACCOUNT: ipt_acc_data_free called with unknown depth: %d\n", - depth); - return; + printk("ACCOUNT: ipt_acc_data_free called with unknown depth: %d\n", + depth); + return; } /* Look for existing table / insert new one. Return internal ID or -1 on error */ static int ipt_acc_table_insert(char *name, uint32_t ip, uint32_t netmask) { - unsigned int i; + unsigned int i; - DEBUGP("ACCOUNT: ipt_acc_table_insert: %s, %u.%u.%u.%u/%u.%u.%u.%u\n", - name, NIPQUAD(ip), NIPQUAD(netmask)); + DEBUGP("ACCOUNT: ipt_acc_table_insert: %s, %u.%u.%u.%u/%u.%u.%u.%u\n", + name, NIPQUAD(ip), NIPQUAD(netmask)); - /* Look for existing table */ - for (i = 0; i < ACCOUNT_MAX_TABLES; i++) { - if (strncmp(ipt_acc_tables[i].name, name, - ACCOUNT_TABLE_NAME_LEN) == 0) { - DEBUGP("ACCOUNT: Found existing slot: %d - " - "%u.%u.%u.%u/%u.%u.%u.%u\n", i, - NIPQUAD(ipt_acc_tables[i].ip), - NIPQUAD(ipt_acc_tables[i].netmask)); + /* Look for existing table */ + for (i = 0; i < ACCOUNT_MAX_TABLES; i++) { + if (strncmp(ipt_acc_tables[i].name, name, + ACCOUNT_TABLE_NAME_LEN) == 0) { + DEBUGP("ACCOUNT: Found existing slot: %d - " + "%u.%u.%u.%u/%u.%u.%u.%u\n", i, + NIPQUAD(ipt_acc_tables[i].ip), + NIPQUAD(ipt_acc_tables[i].netmask)); - if (ipt_acc_tables[i].ip != ip - || ipt_acc_tables[i].netmask != netmask) { - printk("ACCOUNT: Table %s found, but IP/netmask mismatch. " - "IP/netmask found: %u.%u.%u.%u/%u.%u.%u.%u\n", - name, NIPQUAD(ipt_acc_tables[i].ip), - NIPQUAD(ipt_acc_tables[i].netmask)); - return -1; - } + if (ipt_acc_tables[i].ip != ip + || ipt_acc_tables[i].netmask != netmask) { + printk("ACCOUNT: Table %s found, but IP/netmask mismatch. " + "IP/netmask found: %u.%u.%u.%u/%u.%u.%u.%u\n", + name, NIPQUAD(ipt_acc_tables[i].ip), + NIPQUAD(ipt_acc_tables[i].netmask)); + return -1; + } - ipt_acc_tables[i].refcount++; - DEBUGP("ACCOUNT: Refcount: %d\n", ipt_acc_tables[i].refcount); - return i; - } - } + ipt_acc_tables[i].refcount++; + DEBUGP("ACCOUNT: Refcount: %d\n", ipt_acc_tables[i].refcount); + return i; + } + } - /* Insert new table */ - for (i = 0; i < ACCOUNT_MAX_TABLES; i++) { - /* Found free slot */ - if (ipt_acc_tables[i].name[0] == 0) { - unsigned int netsize=0; - uint32_t calc_mask; - int j; /* needs to be signed, otherwise we risk endless loop */ + /* Insert new table */ + for (i = 0; i < ACCOUNT_MAX_TABLES; i++) { + /* Found free slot */ + if (ipt_acc_tables[i].name[0] == 0) { + unsigned int netsize = 0; + uint32_t calc_mask; + int j; /* needs to be signed, otherwise we risk endless loop */ - DEBUGP("ACCOUNT: Found free slot: %d\n", i); - strncpy (ipt_acc_tables[i].name, name, ACCOUNT_TABLE_NAME_LEN-1); + DEBUGP("ACCOUNT: Found free slot: %d\n", i); + strncpy(ipt_acc_tables[i].name, name, ACCOUNT_TABLE_NAME_LEN-1); - ipt_acc_tables[i].ip = ip; - ipt_acc_tables[i].netmask = netmask; + ipt_acc_tables[i].ip = ip; + ipt_acc_tables[i].netmask = netmask; - /* Calculate netsize */ - calc_mask = htonl(netmask); - for (j = 31; j >= 0; j--) { - if (calc_mask&(1<= 0; j--) { + if (calc_mask & (1 << j)) + netsize++; + else + break; + } - /* Calculate depth from netsize */ - if (netsize >= 24) - ipt_acc_tables[i].depth = 0; - else if (netsize >= 16) - ipt_acc_tables[i].depth = 1; - else if(netsize >= 8) - ipt_acc_tables[i].depth = 2; + /* Calculate depth from netsize */ + if (netsize >= 24) + ipt_acc_tables[i].depth = 0; + else if (netsize >= 16) + ipt_acc_tables[i].depth = 1; + else if (netsize >= 8) + ipt_acc_tables[i].depth = 2; - DEBUGP("ACCOUNT: calculated netsize: %u -> " - "ipt_acc_table depth %u\n", netsize, - ipt_acc_tables[i].depth); + DEBUGP("ACCOUNT: calculated netsize: %u -> " + "ipt_acc_table depth %u\n", netsize, + ipt_acc_tables[i].depth); - ipt_acc_tables[i].refcount++; - if ((ipt_acc_tables[i].data - = ipt_acc_zalloc_page()) == NULL) { - printk("ACCOUNT: out of memory for data of table: %s\n", name); - memset(&ipt_acc_tables[i], 0, - sizeof(struct ipt_acc_table)); - return -1; - } + ipt_acc_tables[i].refcount++; + if ((ipt_acc_tables[i].data + = ipt_acc_zalloc_page()) == NULL) { + printk("ACCOUNT: out of memory for data of table: %s\n", name); + memset(&ipt_acc_tables[i], 0, + sizeof(struct ipt_acc_table)); + return -1; + } - return i; - } - } + return i; + } + } - /* No free slot found */ - printk("ACCOUNT: No free table slot found (max: %d). " - "Please increase ACCOUNT_MAX_TABLES.\n", ACCOUNT_MAX_TABLES); - return -1; + /* No free slot found */ + printk("ACCOUNT: No free table slot found (max: %d). " + "Please increase ACCOUNT_MAX_TABLES.\n", ACCOUNT_MAX_TABLES); + return -1; } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) @@ -215,56 +215,56 @@ static bool ipt_acc_checkentry(const char *tablename, static int ipt_acc_checkentry(const char *tablename, #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) - const void *e, + const void *e, #else - const struct ipt_entry *e, + const struct ipt_entry *e, #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) - const struct xt_target *target, + const struct xt_target *target, #endif - void *targinfo, + void *targinfo, #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) - unsigned int targinfosize, + unsigned int targinfosize, #endif - unsigned int hook_mask) + unsigned int hook_mask) #endif /* >= 2.6.28 */ { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) - struct ipt_acc_info *info = par->targinfo; + struct ipt_acc_info *info = par->targinfo; #else - struct ipt_acc_info *info = targinfo; + struct ipt_acc_info *info = targinfo; #endif - int table_nr; + int table_nr; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) - if (targinfosize != IPT_ALIGN(sizeof(struct ipt_acc_info))) { - DEBUGP("ACCOUNT: targinfosize %u != %u\n", - targinfosize, IPT_ALIGN(sizeof(struct ipt_acc_info))); - return 0; - } + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_acc_info))) { + DEBUGP("ACCOUNT: targinfosize %u != %u\n", + targinfosize, IPT_ALIGN(sizeof(struct ipt_acc_info))); + return 0; + } #endif - spin_lock_bh(&ipt_acc_lock); - table_nr = ipt_acc_table_insert(info->table_name, info->net_ip, - info->net_mask); - spin_unlock_bh(&ipt_acc_lock); + spin_lock_bh(&ipt_acc_lock); + table_nr = ipt_acc_table_insert(info->table_name, info->net_ip, + info->net_mask); + spin_unlock_bh(&ipt_acc_lock); - if (table_nr == -1) { - printk("ACCOUNT: Table insert problem. Aborting\n"); + if (table_nr == -1) { + printk("ACCOUNT: Table insert problem. Aborting\n"); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) - return false; + return false; #else - return 0; + return 0; #endif - } - /* Table nr caching so we don't have to do an extra string compare - for every packet */ - info->table_nr = table_nr; + } + /* Table nr caching so we don't have to do an extra string compare + for every packet */ + info->table_nr = table_nr; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) - return true; + return true; #else - return 1; + return 1; #endif } @@ -273,214 +273,214 @@ static void ipt_acc_destroy(const struct xt_tgdtor_param *par) #else static void ipt_acc_destroy( #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) - const struct xt_target *target, + const struct xt_target *target, #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19) - void *targinfo) + void *targinfo) #else - void *targinfo, - unsigned int targinfosize) + void *targinfo, + unsigned int targinfosize) #endif #endif /* >= 2.6.28 */ { - unsigned int i; + unsigned int i; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) - struct ipt_acc_info *info = par->targinfo; + struct ipt_acc_info *info = par->targinfo; #else - struct ipt_acc_info *info = targinfo; + struct ipt_acc_info *info = targinfo; #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) - if (targinfosize != IPT_ALIGN(sizeof(struct ipt_acc_info))) { - DEBUGP("ACCOUNT: targinfosize %u != %u\n", - targinfosize, IPT_ALIGN(sizeof(struct ipt_acc_info))); - } + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_acc_info))) { + DEBUGP("ACCOUNT: targinfosize %u != %u\n", + targinfosize, IPT_ALIGN(sizeof(struct ipt_acc_info))); + } #endif - spin_lock_bh(&ipt_acc_lock); + spin_lock_bh(&ipt_acc_lock); - DEBUGP("ACCOUNT: ipt_acc_deleteentry called for table: %s (#%d)\n", - info->table_name, info->table_nr); + DEBUGP("ACCOUNT: ipt_acc_deleteentry called for table: %s (#%d)\n", + info->table_name, info->table_nr); - info->table_nr = -1; /* Set back to original state */ + info->table_nr = -1; /* Set back to original state */ - /* Look for table */ - for (i = 0; i < ACCOUNT_MAX_TABLES; i++) { - if (strncmp(ipt_acc_tables[i].name, info->table_name, - ACCOUNT_TABLE_NAME_LEN) == 0) { - DEBUGP("ACCOUNT: Found table at slot: %d\n", i); + /* Look for table */ + for (i = 0; i < ACCOUNT_MAX_TABLES; i++) { + if (strncmp(ipt_acc_tables[i].name, info->table_name, + ACCOUNT_TABLE_NAME_LEN) == 0) { + DEBUGP("ACCOUNT: Found table at slot: %d\n", i); - ipt_acc_tables[i].refcount--; - DEBUGP("ACCOUNT: Refcount left: %d\n", - ipt_acc_tables[i].refcount); + ipt_acc_tables[i].refcount--; + DEBUGP("ACCOUNT: Refcount left: %d\n", + ipt_acc_tables[i].refcount); - /* Table not needed anymore? */ - if (ipt_acc_tables[i].refcount == 0) { - DEBUGP("ACCOUNT: Destroying table at slot: %d\n", i); - ipt_acc_data_free(ipt_acc_tables[i].data, - ipt_acc_tables[i].depth); - memset(&ipt_acc_tables[i], 0, - sizeof(struct ipt_acc_table)); - } + /* Table not needed anymore? */ + if (ipt_acc_tables[i].refcount == 0) { + DEBUGP("ACCOUNT: Destroying table at slot: %d\n", i); + ipt_acc_data_free(ipt_acc_tables[i].data, + ipt_acc_tables[i].depth); + memset(&ipt_acc_tables[i], 0, + sizeof(struct ipt_acc_table)); + } - spin_unlock_bh(&ipt_acc_lock); - return; - } - } + spin_unlock_bh(&ipt_acc_lock); + return; + } + } - /* Table not found */ - printk("ACCOUNT: Table %s not found for destroy\n", info->table_name); - spin_unlock_bh(&ipt_acc_lock); + /* Table not found */ + printk("ACCOUNT: Table %s not found for destroy\n", info->table_name); + spin_unlock_bh(&ipt_acc_lock); } static void ipt_acc_depth0_insert(struct ipt_acc_mask_24 *mask_24, - uint32_t net_ip, uint32_t netmask, - uint32_t src_ip, uint32_t dst_ip, - uint32_t size, uint32_t *itemcount) + uint32_t net_ip, uint32_t netmask, + uint32_t src_ip, uint32_t dst_ip, + uint32_t size, uint32_t *itemcount) { - unsigned char is_src = 0, is_dst = 0, src_slot, dst_slot; - char is_src_new_ip = 0, is_dst_new_ip = 0; /* Check if this entry is new */ + unsigned char is_src = 0, is_dst = 0, src_slot, dst_slot; + char is_src_new_ip = 0, is_dst_new_ip = 0; /* Check if this entry is new */ - DEBUGP("ACCOUNT: ipt_acc_depth0_insert: %u.%u.%u.%u/%u.%u.%u.%u " - "for net %u.%u.%u.%u/%u.%u.%u.%u, size: %u\n", NIPQUAD(src_ip), - NIPQUAD(dst_ip), NIPQUAD(net_ip), NIPQUAD(netmask), size); + DEBUGP("ACCOUNT: ipt_acc_depth0_insert: %u.%u.%u.%u/%u.%u.%u.%u " + "for net %u.%u.%u.%u/%u.%u.%u.%u, size: %u\n", NIPQUAD(src_ip), + NIPQUAD(dst_ip), NIPQUAD(net_ip), NIPQUAD(netmask), size); - /* Check if src/dst is inside our network. */ - /* Special: net_ip = 0.0.0.0/0 gets stored as src in slot 0 */ - if (!netmask) - src_ip = 0; - if ((net_ip&netmask) == (src_ip&netmask)) - is_src = 1; - if ((net_ip&netmask) == (dst_ip&netmask) && netmask) - is_dst = 1; + /* Check if src/dst is inside our network. */ + /* Special: net_ip = 0.0.0.0/0 gets stored as src in slot 0 */ + if (!netmask) + src_ip = 0; + if ((net_ip & netmask) == (src_ip & netmask)) + is_src = 1; + if ((net_ip & netmask) == (dst_ip & netmask) && netmask) + is_dst = 1; - if (!is_src && !is_dst) { - DEBUGP("ACCOUNT: Skipping packet %u.%u.%u.%u/%u.%u.%u.%u " - "for net %u.%u.%u.%u/%u.%u.%u.%u\n", NIPQUAD(src_ip), - NIPQUAD(dst_ip), NIPQUAD(net_ip), NIPQUAD(netmask)); - return; - } + if (!is_src && !is_dst) { + DEBUGP("ACCOUNT: Skipping packet %u.%u.%u.%u/%u.%u.%u.%u " + "for net %u.%u.%u.%u/%u.%u.%u.%u\n", NIPQUAD(src_ip), + NIPQUAD(dst_ip), NIPQUAD(net_ip), NIPQUAD(netmask)); + return; + } - /* Calculate array positions */ - src_slot = (unsigned char)((src_ip&0xFF000000) >> 24); - dst_slot = (unsigned char)((dst_ip&0xFF000000) >> 24); + /* Calculate array positions */ + src_slot = (unsigned char)((src_ip & 0xFF000000) >> 24); + dst_slot = (unsigned char)((dst_ip & 0xFF000000) >> 24); - /* Increase size counters */ - if (is_src) { - /* Calculate network slot */ - DEBUGP("ACCOUNT: Calculated SRC 8 bit network slot: %d\n", src_slot); - if (!mask_24->ip[src_slot].src_packets - && !mask_24->ip[src_slot].dst_packets) - is_src_new_ip = 1; + /* Increase size counters */ + if (is_src) { + /* Calculate network slot */ + DEBUGP("ACCOUNT: Calculated SRC 8 bit network slot: %d\n", src_slot); + if (!mask_24->ip[src_slot].src_packets + && !mask_24->ip[src_slot].dst_packets) + is_src_new_ip = 1; - mask_24->ip[src_slot].src_packets++; - mask_24->ip[src_slot].src_bytes+=size; - } - if (is_dst) { - DEBUGP("ACCOUNT: Calculated DST 8 bit network slot: %d\n", dst_slot); - if (!mask_24->ip[dst_slot].src_packets - && !mask_24->ip[dst_slot].dst_packets) - is_dst_new_ip = 1; + mask_24->ip[src_slot].src_packets++; + mask_24->ip[src_slot].src_bytes += size; + } + if (is_dst) { + DEBUGP("ACCOUNT: Calculated DST 8 bit network slot: %d\n", dst_slot); + if (!mask_24->ip[dst_slot].src_packets + && !mask_24->ip[dst_slot].dst_packets) + is_dst_new_ip = 1; - mask_24->ip[dst_slot].dst_packets++; - mask_24->ip[dst_slot].dst_bytes+=size; - } + mask_24->ip[dst_slot].dst_packets++; + mask_24->ip[dst_slot].dst_bytes += size; + } - /* Increase itemcounter */ - DEBUGP("ACCOUNT: Itemcounter before: %d\n", *itemcount); - if (src_slot == dst_slot) { - if (is_src_new_ip || is_dst_new_ip) { - DEBUGP("ACCOUNT: src_slot == dst_slot: %d, %d\n", - is_src_new_ip, is_dst_new_ip); - (*itemcount)++; - } - } else { - if (is_src_new_ip) { - DEBUGP("ACCOUNT: New src_ip: %u.%u.%u.%u\n", NIPQUAD(src_ip)); - (*itemcount)++; - } - if (is_dst_new_ip) { - DEBUGP("ACCOUNT: New dst_ip: %u.%u.%u.%u\n", NIPQUAD(dst_ip)); - (*itemcount)++; - } - } - DEBUGP("ACCOUNT: Itemcounter after: %d\n", *itemcount); + /* Increase itemcounter */ + DEBUGP("ACCOUNT: Itemcounter before: %d\n", *itemcount); + if (src_slot == dst_slot) { + if (is_src_new_ip || is_dst_new_ip) { + DEBUGP("ACCOUNT: src_slot == dst_slot: %d, %d\n", + is_src_new_ip, is_dst_new_ip); + (*itemcount)++; + } + } else { + if (is_src_new_ip) { + DEBUGP("ACCOUNT: New src_ip: %u.%u.%u.%u\n", NIPQUAD(src_ip)); + (*itemcount)++; + } + if (is_dst_new_ip) { + DEBUGP("ACCOUNT: New dst_ip: %u.%u.%u.%u\n", NIPQUAD(dst_ip)); + (*itemcount)++; + } + } + DEBUGP("ACCOUNT: Itemcounter after: %d\n", *itemcount); } static void ipt_acc_depth1_insert(struct ipt_acc_mask_16 *mask_16, - uint32_t net_ip, uint32_t netmask, - uint32_t src_ip, uint32_t dst_ip, - uint32_t size, uint32_t *itemcount) + uint32_t net_ip, uint32_t netmask, + uint32_t src_ip, uint32_t dst_ip, + uint32_t size, uint32_t *itemcount) { - /* Do we need to process src IP? */ - if ((net_ip&netmask) == (src_ip&netmask)) { - unsigned char slot = (unsigned char)((src_ip&0x00FF0000) >> 16); - DEBUGP("ACCOUNT: Calculated SRC 16 bit network slot: %d\n", slot); + /* Do we need to process src IP? */ + if ((net_ip & netmask) == (src_ip & netmask)) { + unsigned char slot = (unsigned char)((src_ip & 0x00FF0000) >> 16); + DEBUGP("ACCOUNT: Calculated SRC 16 bit network slot: %d\n", slot); - /* Do we need to create a new mask_24 bucket? */ - if (!mask_16->mask_24[slot] && (mask_16->mask_24[slot] = - ipt_acc_zalloc_page()) == NULL) { - printk("ACCOUNT: Can't process packet because out of memory!\n"); - return; - } + /* Do we need to create a new mask_24 bucket? */ + if (!mask_16->mask_24[slot] && (mask_16->mask_24[slot] = + ipt_acc_zalloc_page()) == NULL) { + printk("ACCOUNT: Can't process packet because out of memory!\n"); + return; + } - ipt_acc_depth0_insert((struct ipt_acc_mask_24 *)mask_16->mask_24[slot], - net_ip, netmask, src_ip, 0, size, itemcount); - } + ipt_acc_depth0_insert((struct ipt_acc_mask_24 *)mask_16->mask_24[slot], + net_ip, netmask, src_ip, 0, size, itemcount); + } - /* Do we need to process dst IP? */ - if ((net_ip&netmask) == (dst_ip&netmask)) { - unsigned char slot = (unsigned char)((dst_ip&0x00FF0000) >> 16); - DEBUGP("ACCOUNT: Calculated DST 16 bit network slot: %d\n", slot); + /* Do we need to process dst IP? */ + if ((net_ip & netmask) == (dst_ip & netmask)) { + unsigned char slot = (unsigned char)((dst_ip & 0x00FF0000) >> 16); + DEBUGP("ACCOUNT: Calculated DST 16 bit network slot: %d\n", slot); - /* Do we need to create a new mask_24 bucket? */ - if (!mask_16->mask_24[slot] && (mask_16->mask_24[slot] - = ipt_acc_zalloc_page()) == NULL) { - printk("ACCOUT: Can't process packet because out of memory!\n"); - return; - } + /* Do we need to create a new mask_24 bucket? */ + if (!mask_16->mask_24[slot] && (mask_16->mask_24[slot] + = ipt_acc_zalloc_page()) == NULL) { + printk("ACCOUT: Can't process packet because out of memory!\n"); + return; + } - ipt_acc_depth0_insert((struct ipt_acc_mask_24 *)mask_16->mask_24[slot], - net_ip, netmask, 0, dst_ip, size, itemcount); - } + ipt_acc_depth0_insert((struct ipt_acc_mask_24 *)mask_16->mask_24[slot], + net_ip, netmask, 0, dst_ip, size, itemcount); + } } static void ipt_acc_depth2_insert(struct ipt_acc_mask_8 *mask_8, - uint32_t net_ip, uint32_t netmask, - uint32_t src_ip, uint32_t dst_ip, - uint32_t size, uint32_t *itemcount) + uint32_t net_ip, uint32_t netmask, + uint32_t src_ip, uint32_t dst_ip, + uint32_t size, uint32_t *itemcount) { - /* Do we need to process src IP? */ - if ((net_ip&netmask) == (src_ip&netmask)) { - unsigned char slot = (unsigned char)((src_ip&0x0000FF00) >> 8); - DEBUGP("ACCOUNT: Calculated SRC 24 bit network slot: %d\n", slot); + /* Do we need to process src IP? */ + if ((net_ip & netmask) == (src_ip & netmask)) { + unsigned char slot = (unsigned char)((src_ip & 0x0000FF00) >> 8); + DEBUGP("ACCOUNT: Calculated SRC 24 bit network slot: %d\n", slot); - /* Do we need to create a new mask_24 bucket? */ - if (!mask_8->mask_16[slot] && (mask_8->mask_16[slot] - = ipt_acc_zalloc_page()) == NULL) { - printk("ACCOUNT: Can't process packet because out of memory!\n"); - return; - } + /* Do we need to create a new mask_24 bucket? */ + if (!mask_8->mask_16[slot] && (mask_8->mask_16[slot] + = ipt_acc_zalloc_page()) == NULL) { + printk("ACCOUNT: Can't process packet because out of memory!\n"); + return; + } - ipt_acc_depth1_insert((struct ipt_acc_mask_16 *)mask_8->mask_16[slot], - net_ip, netmask, src_ip, 0, size, itemcount); - } + ipt_acc_depth1_insert((struct ipt_acc_mask_16 *)mask_8->mask_16[slot], + net_ip, netmask, src_ip, 0, size, itemcount); + } - /* Do we need to process dst IP? */ - if ((net_ip&netmask) == (dst_ip&netmask)) { - unsigned char slot = (unsigned char)((dst_ip&0x0000FF00) >> 8); - DEBUGP("ACCOUNT: Calculated DST 24 bit network slot: %d\n", slot); + /* Do we need to process dst IP? */ + if ((net_ip & netmask) == (dst_ip & netmask)) { + unsigned char slot = (unsigned char)((dst_ip & 0x0000FF00) >> 8); + DEBUGP("ACCOUNT: Calculated DST 24 bit network slot: %d\n", slot); - /* Do we need to create a new mask_24 bucket? */ - if (!mask_8->mask_16[slot] && (mask_8->mask_16[slot] - = ipt_acc_zalloc_page()) == NULL) { - printk("ACCOUNT: Can't process packet because out of memory!\n"); - return; - } + /* Do we need to create a new mask_24 bucket? */ + if (!mask_8->mask_16[slot] && (mask_8->mask_16[slot] + = ipt_acc_zalloc_page()) == NULL) { + printk("ACCOUNT: Can't process packet because out of memory!\n"); + return; + } - ipt_acc_depth1_insert((struct ipt_acc_mask_16 *)mask_8->mask_16[slot], - net_ip, netmask, 0, dst_ip, size, itemcount); - } + ipt_acc_depth1_insert((struct ipt_acc_mask_16 *)mask_8->mask_16[slot], + net_ip, netmask, 0, dst_ip, size, itemcount); + } } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) @@ -491,325 +491,325 @@ static unsigned int ipt_acc_target(struct sk_buff *skb, #else static unsigned int ipt_acc_target(struct sk_buff **pskb, #endif - const struct net_device *in, - const struct net_device *out, - unsigned int hooknum, + const struct net_device *in, + const struct net_device *out, + unsigned int hooknum, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) - const struct xt_target *target, + const struct xt_target *target, #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19) - const void *targinfo) + const void *targinfo) #else - const void *targinfo, - void *userinfo) + const void *targinfo, + void *userinfo) #endif #endif /* 2.6.28 */ { - const struct ipt_acc_info *info = + const struct ipt_acc_info *info = #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) - par->targinfo; + par->targinfo; #else - (const struct ipt_acc_info *)targinfo; + (const struct ipt_acc_info *)targinfo; #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) - uint32_t src_ip = ip_hdr(skb)->saddr; - uint32_t dst_ip = ip_hdr(skb)->daddr; - uint32_t size = ntohs(ip_hdr(skb)->tot_len); + uint32_t src_ip = ip_hdr(skb)->saddr; + uint32_t dst_ip = ip_hdr(skb)->daddr; + uint32_t size = ntohs(ip_hdr(skb)->tot_len); #else #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) - uint32_t src_ip = ip_hdr(*pskb)->saddr; - uint32_t dst_ip = ip_hdr(*pskb)->daddr; - uint32_t size = ntohs(ip_hdr(*pskb)->tot_len); + uint32_t src_ip = ip_hdr(*pskb)->saddr; + uint32_t dst_ip = ip_hdr(*pskb)->daddr; + uint32_t size = ntohs(ip_hdr(*pskb)->tot_len); #else - uint32_t src_ip = (*pskb)->nh.iph->saddr; - uint32_t dst_ip = (*pskb)->nh.iph->daddr; - uint32_t size = ntohs((*pskb)->nh.iph->tot_len); + uint32_t src_ip = (*pskb)->nh.iph->saddr; + uint32_t dst_ip = (*pskb)->nh.iph->daddr; + uint32_t size = ntohs((*pskb)->nh.iph->tot_len); #endif #endif - spin_lock_bh(&ipt_acc_lock); + spin_lock_bh(&ipt_acc_lock); - if (ipt_acc_tables[info->table_nr].name[0] == 0) { - printk("ACCOUNT: ipt_acc_target: Invalid table id %u. " - "IPs %u.%u.%u.%u/%u.%u.%u.%u\n", info->table_nr, - NIPQUAD(src_ip), NIPQUAD(dst_ip)); - spin_unlock_bh(&ipt_acc_lock); - return IPT_CONTINUE; - } + if (ipt_acc_tables[info->table_nr].name[0] == 0) { + printk("ACCOUNT: ipt_acc_target: Invalid table id %u. " + "IPs %u.%u.%u.%u/%u.%u.%u.%u\n", info->table_nr, + NIPQUAD(src_ip), NIPQUAD(dst_ip)); + spin_unlock_bh(&ipt_acc_lock); + return IPT_CONTINUE; + } - /* 8 bit network or "any" network */ - if (ipt_acc_tables[info->table_nr].depth == 0) { - /* Count packet and check if the IP is new */ - ipt_acc_depth0_insert( - (struct ipt_acc_mask_24 *)ipt_acc_tables[info->table_nr].data, - ipt_acc_tables[info->table_nr].ip, - ipt_acc_tables[info->table_nr].netmask, - src_ip, dst_ip, size, &ipt_acc_tables[info->table_nr].itemcount); - spin_unlock_bh(&ipt_acc_lock); - return IPT_CONTINUE; - } + /* 8 bit network or "any" network */ + if (ipt_acc_tables[info->table_nr].depth == 0) { + /* Count packet and check if the IP is new */ + ipt_acc_depth0_insert( + (struct ipt_acc_mask_24 *)ipt_acc_tables[info->table_nr].data, + ipt_acc_tables[info->table_nr].ip, + ipt_acc_tables[info->table_nr].netmask, + src_ip, dst_ip, size, &ipt_acc_tables[info->table_nr].itemcount); + spin_unlock_bh(&ipt_acc_lock); + return IPT_CONTINUE; + } - /* 16 bit network */ - if (ipt_acc_tables[info->table_nr].depth == 1) { - ipt_acc_depth1_insert( - (struct ipt_acc_mask_16 *)ipt_acc_tables[info->table_nr].data, - ipt_acc_tables[info->table_nr].ip, - ipt_acc_tables[info->table_nr].netmask, - src_ip, dst_ip, size, &ipt_acc_tables[info->table_nr].itemcount); - spin_unlock_bh(&ipt_acc_lock); - return IPT_CONTINUE; - } + /* 16 bit network */ + if (ipt_acc_tables[info->table_nr].depth == 1) { + ipt_acc_depth1_insert( + (struct ipt_acc_mask_16 *)ipt_acc_tables[info->table_nr].data, + ipt_acc_tables[info->table_nr].ip, + ipt_acc_tables[info->table_nr].netmask, + src_ip, dst_ip, size, &ipt_acc_tables[info->table_nr].itemcount); + spin_unlock_bh(&ipt_acc_lock); + return IPT_CONTINUE; + } - /* 24 bit network */ - if (ipt_acc_tables[info->table_nr].depth == 2) { - ipt_acc_depth2_insert( - (struct ipt_acc_mask_8 *)ipt_acc_tables[info->table_nr].data, - ipt_acc_tables[info->table_nr].ip, - ipt_acc_tables[info->table_nr].netmask, - src_ip, dst_ip, size, &ipt_acc_tables[info->table_nr].itemcount); - spin_unlock_bh(&ipt_acc_lock); - return IPT_CONTINUE; - } + /* 24 bit network */ + if (ipt_acc_tables[info->table_nr].depth == 2) { + ipt_acc_depth2_insert( + (struct ipt_acc_mask_8 *)ipt_acc_tables[info->table_nr].data, + ipt_acc_tables[info->table_nr].ip, + ipt_acc_tables[info->table_nr].netmask, + src_ip, dst_ip, size, &ipt_acc_tables[info->table_nr].itemcount); + spin_unlock_bh(&ipt_acc_lock); + return IPT_CONTINUE; + } - printk("ACCOUNT: ipt_acc_target: Unable to process packet. " - "Table id %u. IPs %u.%u.%u.%u/%u.%u.%u.%u\n", - info->table_nr, NIPQUAD(src_ip), NIPQUAD(dst_ip)); + printk("ACCOUNT: ipt_acc_target: Unable to process packet. " + "Table id %u. IPs %u.%u.%u.%u/%u.%u.%u.%u\n", + info->table_nr, NIPQUAD(src_ip), NIPQUAD(dst_ip)); - spin_unlock_bh(&ipt_acc_lock); - return IPT_CONTINUE; + spin_unlock_bh(&ipt_acc_lock); + return IPT_CONTINUE; } /* - Functions dealing with "handles": - Handles are snapshots of a accounting state. + Functions dealing with "handles": + Handles are snapshots of a accounting state. - read snapshots are only for debugging the code - and are very expensive concerning speed/memory - compared to read_and_flush. + read snapshots are only for debugging the code + and are very expensive concerning speed/memory + compared to read_and_flush. - The functions aren't protected by spinlocks themselves - as this is done in the ioctl part of the code. + The functions aren't protected by spinlocks themselves + as this is done in the ioctl part of the code. */ /* - Find a free handle slot. Normally only one should be used, - but there could be two or more applications accessing the data - at the same time. + Find a free handle slot. Normally only one should be used, + but there could be two or more applications accessing the data + at the same time. */ static int ipt_acc_handle_find_slot(void) { - unsigned int i; - /* Insert new table */ - for (i = 0; i < ACCOUNT_MAX_HANDLES; i++) { - /* Found free slot */ - if (ipt_acc_handles[i].data == NULL) { - /* Don't "mark" data as used as we are protected by a spinlock - by the calling function. handle_find_slot() is only a function - to prevent code duplication. */ - return i; - } - } + unsigned int i; + /* Insert new table */ + for (i = 0; i < ACCOUNT_MAX_HANDLES; i++) { + /* Found free slot */ + if (ipt_acc_handles[i].data == NULL) { + /* Don't "mark" data as used as we are protected by a spinlock + by the calling function. handle_find_slot() is only a function + to prevent code duplication. */ + return i; + } + } - /* No free slot found */ - printk("ACCOUNT: No free handle slot found (max: %u). " - "Please increase ACCOUNT_MAX_HANDLES.\n", ACCOUNT_MAX_HANDLES); - return -1; + /* No free slot found */ + printk("ACCOUNT: No free handle slot found (max: %u). " + "Please increase ACCOUNT_MAX_HANDLES.\n", ACCOUNT_MAX_HANDLES); + return -1; } static int ipt_acc_handle_free(unsigned int handle) { - if (handle >= ACCOUNT_MAX_HANDLES) { - printk("ACCOUNT: Invalid handle for ipt_acc_handle_free() specified:" - " %u\n", handle); - return -EINVAL; - } + if (handle >= ACCOUNT_MAX_HANDLES) { + printk("ACCOUNT: Invalid handle for ipt_acc_handle_free() specified:" + " %u\n", handle); + return -EINVAL; + } - ipt_acc_data_free(ipt_acc_handles[handle].data, - ipt_acc_handles[handle].depth); - memset (&ipt_acc_handles[handle], 0, sizeof (struct ipt_acc_handle)); - return 0; + ipt_acc_data_free(ipt_acc_handles[handle].data, + ipt_acc_handles[handle].depth); + memset(&ipt_acc_handles[handle], 0, sizeof(struct ipt_acc_handle)); + return 0; } /* Prepare data for read without flush. Use only for debugging! Real applications should use read&flush as it's way more efficent */ static int ipt_acc_handle_prepare_read(char *tablename, - struct ipt_acc_handle *dest, uint32_t *count) + struct ipt_acc_handle *dest, uint32_t *count) { - int table_nr=-1; - unsigned char depth; + int table_nr = -1; + unsigned char depth; - for (table_nr = 0; table_nr < ACCOUNT_MAX_TABLES; table_nr++) - if (strncmp(ipt_acc_tables[table_nr].name, tablename, - ACCOUNT_TABLE_NAME_LEN) == 0) - break; + for (table_nr = 0; table_nr < ACCOUNT_MAX_TABLES; table_nr++) + if (strncmp(ipt_acc_tables[table_nr].name, tablename, + ACCOUNT_TABLE_NAME_LEN) == 0) + break; - if (table_nr == ACCOUNT_MAX_TABLES) { - printk("ACCOUNT: ipt_acc_handle_prepare_read(): " - "Table %s not found\n", tablename); - return -1; - } + if (table_nr == ACCOUNT_MAX_TABLES) { + printk("ACCOUNT: ipt_acc_handle_prepare_read(): " + "Table %s not found\n", tablename); + return -1; + } - /* Fill up handle structure */ - dest->ip = ipt_acc_tables[table_nr].ip; - dest->depth = ipt_acc_tables[table_nr].depth; - dest->itemcount = ipt_acc_tables[table_nr].itemcount; + /* Fill up handle structure */ + dest->ip = ipt_acc_tables[table_nr].ip; + dest->depth = ipt_acc_tables[table_nr].depth; + dest->itemcount = ipt_acc_tables[table_nr].itemcount; - /* allocate "root" table */ - if ((dest->data = ipt_acc_zalloc_page()) == NULL) { - printk("ACCOUNT: out of memory for root table " - "in ipt_acc_handle_prepare_read()\n"); - return -1; - } + /* allocate "root" table */ + if ((dest->data = ipt_acc_zalloc_page()) == NULL) { + printk("ACCOUNT: out of memory for root table " + "in ipt_acc_handle_prepare_read()\n"); + return -1; + } - /* Recursive copy of complete data structure */ - depth = dest->depth; - if (depth == 0) { - memcpy(dest->data, - ipt_acc_tables[table_nr].data, - sizeof(struct ipt_acc_mask_24)); - } else if (depth == 1) { - struct ipt_acc_mask_16 *src_16 = - (struct ipt_acc_mask_16 *)ipt_acc_tables[table_nr].data; - struct ipt_acc_mask_16 *network_16 = - (struct ipt_acc_mask_16 *)dest->data; - unsigned int b; + /* Recursive copy of complete data structure */ + depth = dest->depth; + if (depth == 0) { + memcpy(dest->data, + ipt_acc_tables[table_nr].data, + sizeof(struct ipt_acc_mask_24)); + } else if (depth == 1) { + struct ipt_acc_mask_16 *src_16 = + (struct ipt_acc_mask_16 *)ipt_acc_tables[table_nr].data; + struct ipt_acc_mask_16 *network_16 = + (struct ipt_acc_mask_16 *)dest->data; + unsigned int b; - for (b = 0; b <= 255; b++) { - if (src_16->mask_24[b]) { - if ((network_16->mask_24[b] = - ipt_acc_zalloc_page()) == NULL) { - printk("ACCOUNT: out of memory during copy of 16 bit " - "network in ipt_acc_handle_prepare_read()\n"); - ipt_acc_data_free(dest->data, depth); - return -1; - } + for (b = 0; b <= 255; b++) { + if (src_16->mask_24[b]) { + if ((network_16->mask_24[b] = + ipt_acc_zalloc_page()) == NULL) { + printk("ACCOUNT: out of memory during copy of 16 bit " + "network in ipt_acc_handle_prepare_read()\n"); + ipt_acc_data_free(dest->data, depth); + return -1; + } - memcpy(network_16->mask_24[b], src_16->mask_24[b], - sizeof(struct ipt_acc_mask_24)); - } - } - } else if(depth == 2) { - struct ipt_acc_mask_8 *src_8 = - (struct ipt_acc_mask_8 *)ipt_acc_tables[table_nr].data; - struct ipt_acc_mask_8 *network_8 = - (struct ipt_acc_mask_8 *)dest->data; - struct ipt_acc_mask_16 *src_16, *network_16; - unsigned int a, b; + memcpy(network_16->mask_24[b], src_16->mask_24[b], + sizeof(struct ipt_acc_mask_24)); + } + } + } else if (depth == 2) { + struct ipt_acc_mask_8 *src_8 = + (struct ipt_acc_mask_8 *)ipt_acc_tables[table_nr].data; + struct ipt_acc_mask_8 *network_8 = + (struct ipt_acc_mask_8 *)dest->data; + struct ipt_acc_mask_16 *src_16, *network_16; + unsigned int a, b; - for (a = 0; a <= 255; a++) { - if (src_8->mask_16[a]) { - if ((network_8->mask_16[a] = - ipt_acc_zalloc_page()) == NULL) { - printk("ACCOUNT: out of memory during copy of 24 bit network" - " in ipt_acc_handle_prepare_read()\n"); - ipt_acc_data_free(dest->data, depth); - return -1; - } + for (a = 0; a <= 255; a++) { + if (src_8->mask_16[a]) { + if ((network_8->mask_16[a] = + ipt_acc_zalloc_page()) == NULL) { + printk("ACCOUNT: out of memory during copy of 24 bit network" + " in ipt_acc_handle_prepare_read()\n"); + ipt_acc_data_free(dest->data, depth); + return -1; + } - memcpy(network_8->mask_16[a], src_8->mask_16[a], - sizeof(struct ipt_acc_mask_16)); + memcpy(network_8->mask_16[a], src_8->mask_16[a], + sizeof(struct ipt_acc_mask_16)); - src_16 = src_8->mask_16[a]; - network_16 = network_8->mask_16[a]; + src_16 = src_8->mask_16[a]; + network_16 = network_8->mask_16[a]; - for (b = 0; b <= 255; b++) { - if (src_16->mask_24[b]) { - if ((network_16->mask_24[b] = - ipt_acc_zalloc_page()) == NULL) { - printk("ACCOUNT: out of memory during copy of 16 bit" - " network in ipt_acc_handle_prepare_read()\n"); - ipt_acc_data_free(dest->data, depth); - return -1; - } + for (b = 0; b <= 255; b++) { + if (src_16->mask_24[b]) { + if ((network_16->mask_24[b] = + ipt_acc_zalloc_page()) == NULL) { + printk("ACCOUNT: out of memory during copy of 16 bit" + " network in ipt_acc_handle_prepare_read()\n"); + ipt_acc_data_free(dest->data, depth); + return -1; + } - memcpy(network_16->mask_24[b], src_16->mask_24[b], - sizeof(struct ipt_acc_mask_24)); - } - } - } - } - } + memcpy(network_16->mask_24[b], src_16->mask_24[b], + sizeof(struct ipt_acc_mask_24)); + } + } + } + } + } - *count = ipt_acc_tables[table_nr].itemcount; + *count = ipt_acc_tables[table_nr].itemcount; - return 0; + return 0; } /* Prepare data for read and flush it */ static int ipt_acc_handle_prepare_read_flush(char *tablename, - struct ipt_acc_handle *dest, uint32_t *count) + struct ipt_acc_handle *dest, uint32_t *count) { - int table_nr; - void *new_data_page; + int table_nr; + void *new_data_page; - for (table_nr = 0; table_nr < ACCOUNT_MAX_TABLES; table_nr++) - if (strncmp(ipt_acc_tables[table_nr].name, tablename, - ACCOUNT_TABLE_NAME_LEN) == 0) - break; + for (table_nr = 0; table_nr < ACCOUNT_MAX_TABLES; table_nr++) + if (strncmp(ipt_acc_tables[table_nr].name, tablename, + ACCOUNT_TABLE_NAME_LEN) == 0) + break; - if (table_nr == ACCOUNT_MAX_TABLES) { - printk("ACCOUNT: ipt_acc_handle_prepare_read_flush(): " - "Table %s not found\n", tablename); - return -1; - } + if (table_nr == ACCOUNT_MAX_TABLES) { + printk("ACCOUNT: ipt_acc_handle_prepare_read_flush(): " + "Table %s not found\n", tablename); + return -1; + } - /* Try to allocate memory */ - if (!(new_data_page = ipt_acc_zalloc_page())) { - printk("ACCOUNT: ipt_acc_handle_prepare_read_flush(): " - "Out of memory!\n"); - return -1; - } + /* Try to allocate memory */ + if (!(new_data_page = ipt_acc_zalloc_page())) { + printk("ACCOUNT: ipt_acc_handle_prepare_read_flush(): " + "Out of memory!\n"); + return -1; + } - /* Fill up handle structure */ - dest->ip = ipt_acc_tables[table_nr].ip; - dest->depth = ipt_acc_tables[table_nr].depth; - dest->itemcount = ipt_acc_tables[table_nr].itemcount; - dest->data = ipt_acc_tables[table_nr].data; - *count = ipt_acc_tables[table_nr].itemcount; + /* Fill up handle structure */ + dest->ip = ipt_acc_tables[table_nr].ip; + dest->depth = ipt_acc_tables[table_nr].depth; + dest->itemcount = ipt_acc_tables[table_nr].itemcount; + dest->data = ipt_acc_tables[table_nr].data; + *count = ipt_acc_tables[table_nr].itemcount; - /* "Flush" table data */ - ipt_acc_tables[table_nr].data = new_data_page; - ipt_acc_tables[table_nr].itemcount = 0; + /* "Flush" table data */ + ipt_acc_tables[table_nr].data = new_data_page; + ipt_acc_tables[table_nr].itemcount = 0; - return 0; + return 0; } /* Copy 8 bit network data into a prepared buffer. We only copy entries != 0 to increase performance. */ static int ipt_acc_handle_copy_data(void *to_user, unsigned long *to_user_pos, - unsigned long *tmpbuf_pos, - struct ipt_acc_mask_24 *data, - uint32_t net_ip, uint32_t net_OR_mask) + unsigned long *tmpbuf_pos, + struct ipt_acc_mask_24 *data, + uint32_t net_ip, uint32_t net_OR_mask) { - struct ipt_acc_handle_ip handle_ip; - size_t handle_ip_size = sizeof (struct ipt_acc_handle_ip); - unsigned int i; + struct ipt_acc_handle_ip handle_ip; + size_t handle_ip_size = sizeof(struct ipt_acc_handle_ip); + unsigned int i; - for (i = 0; i <= 255; i++) { - if (data->ip[i].src_packets || data->ip[i].dst_packets) { - handle_ip.ip = net_ip | net_OR_mask | (i<<24); + for (i = 0; i <= 255; i++) { + if (data->ip[i].src_packets || data->ip[i].dst_packets) { + handle_ip.ip = net_ip | net_OR_mask | (i << 24); - handle_ip.src_packets = data->ip[i].src_packets; - handle_ip.src_bytes = data->ip[i].src_bytes; - handle_ip.dst_packets = data->ip[i].dst_packets; - handle_ip.dst_bytes = data->ip[i].dst_bytes; + handle_ip.src_packets = data->ip[i].src_packets; + handle_ip.src_bytes = data->ip[i].src_bytes; + handle_ip.dst_packets = data->ip[i].dst_packets; + handle_ip.dst_bytes = data->ip[i].dst_bytes; - /* Temporary buffer full? Flush to userspace */ - if (*tmpbuf_pos+handle_ip_size >= PAGE_SIZE) { - if (copy_to_user(to_user + *to_user_pos, ipt_acc_tmpbuf, - *tmpbuf_pos)) - return -EFAULT; - *to_user_pos = *to_user_pos + *tmpbuf_pos; - *tmpbuf_pos = 0; - } - memcpy(ipt_acc_tmpbuf+*tmpbuf_pos, &handle_ip, handle_ip_size); - *tmpbuf_pos += handle_ip_size; - } - } + /* Temporary buffer full? Flush to userspace */ + if (*tmpbuf_pos + handle_ip_size >= PAGE_SIZE) { + if (copy_to_user(to_user + *to_user_pos, ipt_acc_tmpbuf, + *tmpbuf_pos)) + return -EFAULT; + *to_user_pos = *to_user_pos + *tmpbuf_pos; + *tmpbuf_pos = 0; + } + memcpy(ipt_acc_tmpbuf + *tmpbuf_pos, &handle_ip, handle_ip_size); + *tmpbuf_pos += handle_ip_size; + } + } - return 0; + return 0; } /* Copy the data from our internal structure @@ -818,308 +818,308 @@ static int ipt_acc_handle_copy_data(void *to_user, unsigned long *to_user_pos, */ static int ipt_acc_handle_get_data(uint32_t handle, void *to_user) { - unsigned long to_user_pos=0, tmpbuf_pos=0; - uint32_t net_ip; - unsigned char depth; + unsigned long to_user_pos = 0, tmpbuf_pos = 0; + uint32_t net_ip; + unsigned char depth; - if (handle >= ACCOUNT_MAX_HANDLES) { - printk("ACCOUNT: invalid handle for ipt_acc_handle_get_data() " - "specified: %u\n", handle); - return -1; - } + if (handle >= ACCOUNT_MAX_HANDLES) { + printk("ACCOUNT: invalid handle for ipt_acc_handle_get_data() " + "specified: %u\n", handle); + return -1; + } - if (ipt_acc_handles[handle].data == NULL) { - printk("ACCOUNT: handle %u is BROKEN: Contains no data\n", handle); - return -1; - } + if (ipt_acc_handles[handle].data == NULL) { + printk("ACCOUNT: handle %u is BROKEN: Contains no data\n", handle); + return -1; + } - net_ip = ipt_acc_handles[handle].ip; - depth = ipt_acc_handles[handle].depth; + net_ip = ipt_acc_handles[handle].ip; + depth = ipt_acc_handles[handle].depth; - /* 8 bit network */ - if (depth == 0) { - struct ipt_acc_mask_24 *network = - (struct ipt_acc_mask_24*)ipt_acc_handles[handle].data; - if (ipt_acc_handle_copy_data(to_user, &to_user_pos, &tmpbuf_pos, - network, net_ip, 0)) - return -1; + /* 8 bit network */ + if (depth == 0) { + struct ipt_acc_mask_24 *network = + (struct ipt_acc_mask_24*)ipt_acc_handles[handle].data; + if (ipt_acc_handle_copy_data(to_user, &to_user_pos, &tmpbuf_pos, + network, net_ip, 0)) + return -1; - /* Flush remaining data to userspace */ - if (tmpbuf_pos) - if (copy_to_user(to_user+to_user_pos, ipt_acc_tmpbuf, tmpbuf_pos)) - return -1; + /* Flush remaining data to userspace */ + if (tmpbuf_pos) + if (copy_to_user(to_user + to_user_pos, ipt_acc_tmpbuf, tmpbuf_pos)) + return -1; - return 0; - } + return 0; + } - /* 16 bit network */ - if (depth == 1) { - struct ipt_acc_mask_16 *network_16 = - (struct ipt_acc_mask_16*)ipt_acc_handles[handle].data; - unsigned int b; - for (b = 0; b <= 255; b++) { - if (network_16->mask_24[b]) { - struct ipt_acc_mask_24 *network = - (struct ipt_acc_mask_24*)network_16->mask_24[b]; - if (ipt_acc_handle_copy_data(to_user, &to_user_pos, - &tmpbuf_pos, network, net_ip, (b << 16))) - return -1; - } - } + /* 16 bit network */ + if (depth == 1) { + struct ipt_acc_mask_16 *network_16 = + (struct ipt_acc_mask_16*)ipt_acc_handles[handle].data; + unsigned int b; + for (b = 0; b <= 255; b++) { + if (network_16->mask_24[b]) { + struct ipt_acc_mask_24 *network = + (struct ipt_acc_mask_24*)network_16->mask_24[b]; + if (ipt_acc_handle_copy_data(to_user, &to_user_pos, + &tmpbuf_pos, network, net_ip, (b << 16))) + return -1; + } + } - /* Flush remaining data to userspace */ - if (tmpbuf_pos) - if (copy_to_user(to_user+to_user_pos, ipt_acc_tmpbuf, tmpbuf_pos)) - return -1; + /* Flush remaining data to userspace */ + if (tmpbuf_pos) + if (copy_to_user(to_user + to_user_pos, ipt_acc_tmpbuf, tmpbuf_pos)) + return -1; - return 0; - } + return 0; + } - /* 24 bit network */ - if (depth == 2) { - struct ipt_acc_mask_8 *network_8 = - (struct ipt_acc_mask_8*)ipt_acc_handles[handle].data; - unsigned int a, b; - for (a = 0; a <= 255; a++) { - if (network_8->mask_16[a]) { - struct ipt_acc_mask_16 *network_16 = - (struct ipt_acc_mask_16*)network_8->mask_16[a]; - for (b = 0; b <= 255; b++) { - if (network_16->mask_24[b]) { - struct ipt_acc_mask_24 *network = - (struct ipt_acc_mask_24*)network_16->mask_24[b]; - if (ipt_acc_handle_copy_data(to_user, - &to_user_pos, &tmpbuf_pos, - network, net_ip, (a << 8) | (b << 16))) - return -1; - } - } - } - } + /* 24 bit network */ + if (depth == 2) { + struct ipt_acc_mask_8 *network_8 = + (struct ipt_acc_mask_8*)ipt_acc_handles[handle].data; + unsigned int a, b; + for (a = 0; a <= 255; a++) { + if (network_8->mask_16[a]) { + struct ipt_acc_mask_16 *network_16 = + (struct ipt_acc_mask_16*)network_8->mask_16[a]; + for (b = 0; b <= 255; b++) { + if (network_16->mask_24[b]) { + struct ipt_acc_mask_24 *network = + (struct ipt_acc_mask_24*)network_16->mask_24[b]; + if (ipt_acc_handle_copy_data(to_user, + &to_user_pos, &tmpbuf_pos, + network, net_ip, (a << 8) | (b << 16))) + return -1; + } + } + } + } - /* Flush remaining data to userspace */ - if (tmpbuf_pos) - if (copy_to_user(to_user+to_user_pos, ipt_acc_tmpbuf, tmpbuf_pos)) - return -1; + /* Flush remaining data to userspace */ + if (tmpbuf_pos) + if (copy_to_user(to_user + to_user_pos, ipt_acc_tmpbuf, tmpbuf_pos)) + return -1; - return 0; - } + return 0; + } - return -1; + return -1; } static int ipt_acc_set_ctl(struct sock *sk, int cmd, - void *user, unsigned int len) + void *user, unsigned int len) { - struct ipt_acc_handle_sockopt handle; - int ret = -EINVAL; + struct ipt_acc_handle_sockopt handle; + int ret = -EINVAL; - if (!capable(CAP_NET_ADMIN)) - return -EPERM; + if (!capable(CAP_NET_ADMIN)) + return -EPERM; - switch (cmd) { - case IPT_SO_SET_ACCOUNT_HANDLE_FREE: - if (len != sizeof(struct ipt_acc_handle_sockopt)) { - printk("ACCOUNT: ipt_acc_set_ctl: wrong data size (%u != %zu) " - "for IPT_SO_SET_HANDLE_FREE\n", - len, sizeof(struct ipt_acc_handle_sockopt)); - break; - } + switch (cmd) { + case IPT_SO_SET_ACCOUNT_HANDLE_FREE: + if (len != sizeof(struct ipt_acc_handle_sockopt)) { + printk("ACCOUNT: ipt_acc_set_ctl: wrong data size (%u != %zu) " + "for IPT_SO_SET_HANDLE_FREE\n", + len, sizeof(struct ipt_acc_handle_sockopt)); + break; + } - if (copy_from_user (&handle, user, len)) { - printk("ACCOUNT: ipt_acc_set_ctl: copy_from_user failed for " - "IPT_SO_SET_HANDLE_FREE\n"); - break; - } + if (copy_from_user(&handle, user, len)) { + printk("ACCOUNT: ipt_acc_set_ctl: copy_from_user failed for " + "IPT_SO_SET_HANDLE_FREE\n"); + break; + } - down(&ipt_acc_userspace_mutex); - ret = ipt_acc_handle_free(handle.handle_nr); - up(&ipt_acc_userspace_mutex); - break; - case IPT_SO_SET_ACCOUNT_HANDLE_FREE_ALL: { - unsigned int i; - down(&ipt_acc_userspace_mutex); - for (i = 0; i < ACCOUNT_MAX_HANDLES; i++) - ipt_acc_handle_free(i); - up(&ipt_acc_userspace_mutex); - ret = 0; - break; - } - default: - printk("ACCOUNT: ipt_acc_set_ctl: unknown request %i\n", cmd); - } + down(&ipt_acc_userspace_mutex); + ret = ipt_acc_handle_free(handle.handle_nr); + up(&ipt_acc_userspace_mutex); + break; + case IPT_SO_SET_ACCOUNT_HANDLE_FREE_ALL: { + unsigned int i; + down(&ipt_acc_userspace_mutex); + for (i = 0; i < ACCOUNT_MAX_HANDLES; i++) + ipt_acc_handle_free(i); + up(&ipt_acc_userspace_mutex); + ret = 0; + break; + } + default: + printk("ACCOUNT: ipt_acc_set_ctl: unknown request %i\n", cmd); + } - return ret; + return ret; } static int ipt_acc_get_ctl(struct sock *sk, int cmd, void *user, int *len) { - struct ipt_acc_handle_sockopt handle; - int ret = -EINVAL; + struct ipt_acc_handle_sockopt handle; + int ret = -EINVAL; - if (!capable(CAP_NET_ADMIN)) - return -EPERM; + if (!capable(CAP_NET_ADMIN)) + return -EPERM; - switch (cmd) { - case IPT_SO_GET_ACCOUNT_PREPARE_READ_FLUSH: - case IPT_SO_GET_ACCOUNT_PREPARE_READ: { - struct ipt_acc_handle dest; + switch (cmd) { + case IPT_SO_GET_ACCOUNT_PREPARE_READ_FLUSH: + case IPT_SO_GET_ACCOUNT_PREPARE_READ: { + struct ipt_acc_handle dest; - if (*len < sizeof(struct ipt_acc_handle_sockopt)) { - printk("ACCOUNT: ipt_acc_get_ctl: wrong data size (%u != %zu) " - "for IPT_SO_GET_ACCOUNT_PREPARE_READ/READ_FLUSH\n", - *len, sizeof(struct ipt_acc_handle_sockopt)); - break; - } + if (*len < sizeof(struct ipt_acc_handle_sockopt)) { + printk("ACCOUNT: ipt_acc_get_ctl: wrong data size (%u != %zu) " + "for IPT_SO_GET_ACCOUNT_PREPARE_READ/READ_FLUSH\n", + *len, sizeof(struct ipt_acc_handle_sockopt)); + break; + } - if (copy_from_user (&handle, user, - sizeof(struct ipt_acc_handle_sockopt))) { - return -EFAULT; - break; - } + if (copy_from_user (&handle, user, + sizeof(struct ipt_acc_handle_sockopt))) { + return -EFAULT; + break; + } - spin_lock_bh(&ipt_acc_lock); - if (cmd == IPT_SO_GET_ACCOUNT_PREPARE_READ_FLUSH) - ret = ipt_acc_handle_prepare_read_flush( - handle.name, &dest, &handle.itemcount); - else - ret = ipt_acc_handle_prepare_read( - handle.name, &dest, &handle.itemcount); - spin_unlock_bh(&ipt_acc_lock); - // Error occured during prepare_read? - if (ret == -1) - return -EINVAL; + spin_lock_bh(&ipt_acc_lock); + if (cmd == IPT_SO_GET_ACCOUNT_PREPARE_READ_FLUSH) + ret = ipt_acc_handle_prepare_read_flush( + handle.name, &dest, &handle.itemcount); + else + ret = ipt_acc_handle_prepare_read( + handle.name, &dest, &handle.itemcount); + spin_unlock_bh(&ipt_acc_lock); + // Error occured during prepare_read? + if (ret == -1) + return -EINVAL; - /* Allocate a userspace handle */ - down(&ipt_acc_userspace_mutex); - if ((handle.handle_nr = ipt_acc_handle_find_slot()) == -1) { - ipt_acc_data_free(dest.data, dest.depth); - up(&ipt_acc_userspace_mutex); - return -EINVAL; - } - memcpy(&ipt_acc_handles[handle.handle_nr], &dest, - sizeof(struct ipt_acc_handle)); - up(&ipt_acc_userspace_mutex); + /* Allocate a userspace handle */ + down(&ipt_acc_userspace_mutex); + if ((handle.handle_nr = ipt_acc_handle_find_slot()) == -1) { + ipt_acc_data_free(dest.data, dest.depth); + up(&ipt_acc_userspace_mutex); + return -EINVAL; + } + memcpy(&ipt_acc_handles[handle.handle_nr], &dest, + sizeof(struct ipt_acc_handle)); + up(&ipt_acc_userspace_mutex); - if (copy_to_user(user, &handle, - sizeof(struct ipt_acc_handle_sockopt))) { - return -EFAULT; - break; - } - ret = 0; - break; - } - case IPT_SO_GET_ACCOUNT_GET_DATA: - if (*len < sizeof(struct ipt_acc_handle_sockopt)) { - printk("ACCOUNT: ipt_acc_get_ctl: wrong data size (%u != %zu)" - " for IPT_SO_GET_ACCOUNT_PREPARE_READ/READ_FLUSH\n", - *len, sizeof(struct ipt_acc_handle_sockopt)); - break; - } + if (copy_to_user(user, &handle, + sizeof(struct ipt_acc_handle_sockopt))) { + return -EFAULT; + break; + } + ret = 0; + break; + } + case IPT_SO_GET_ACCOUNT_GET_DATA: + if (*len < sizeof(struct ipt_acc_handle_sockopt)) { + printk("ACCOUNT: ipt_acc_get_ctl: wrong data size (%u != %zu)" + " for IPT_SO_GET_ACCOUNT_PREPARE_READ/READ_FLUSH\n", + *len, sizeof(struct ipt_acc_handle_sockopt)); + break; + } - if (copy_from_user (&handle, user, - sizeof(struct ipt_acc_handle_sockopt))) { - return -EFAULT; - break; - } + if (copy_from_user(&handle, user, + sizeof(struct ipt_acc_handle_sockopt))) { + return -EFAULT; + break; + } - if (handle.handle_nr >= ACCOUNT_MAX_HANDLES) { - return -EINVAL; - break; - } + if (handle.handle_nr >= ACCOUNT_MAX_HANDLES) { + return -EINVAL; + break; + } - if (*len < ipt_acc_handles[handle.handle_nr].itemcount - * sizeof(struct ipt_acc_handle_ip)) { - printk("ACCOUNT: ipt_acc_get_ctl: not enough space (%u < %zu)" - " to store data from IPT_SO_GET_ACCOUNT_GET_DATA\n", - *len, ipt_acc_handles[handle.handle_nr].itemcount - * sizeof(struct ipt_acc_handle_ip)); - ret = -ENOMEM; - break; - } + if (*len < ipt_acc_handles[handle.handle_nr].itemcount + * sizeof(struct ipt_acc_handle_ip)) { + printk("ACCOUNT: ipt_acc_get_ctl: not enough space (%u < %zu)" + " to store data from IPT_SO_GET_ACCOUNT_GET_DATA\n", + *len, ipt_acc_handles[handle.handle_nr].itemcount + * sizeof(struct ipt_acc_handle_ip)); + ret = -ENOMEM; + break; + } - down(&ipt_acc_userspace_mutex); - ret = ipt_acc_handle_get_data(handle.handle_nr, user); - up(&ipt_acc_userspace_mutex); - if (ret) { - printk("ACCOUNT: ipt_acc_get_ctl: ipt_acc_handle_get_data" - " failed for handle %u\n", handle.handle_nr); - break; - } + down(&ipt_acc_userspace_mutex); + ret = ipt_acc_handle_get_data(handle.handle_nr, user); + up(&ipt_acc_userspace_mutex); + if (ret) { + printk("ACCOUNT: ipt_acc_get_ctl: ipt_acc_handle_get_data" + " failed for handle %u\n", handle.handle_nr); + break; + } - ret = 0; - break; - case IPT_SO_GET_ACCOUNT_GET_HANDLE_USAGE: { - unsigned int i; - if (*len < sizeof(struct ipt_acc_handle_sockopt)) { - printk("ACCOUNT: ipt_acc_get_ctl: wrong data size (%u != %zu)" - " for IPT_SO_GET_ACCOUNT_GET_HANDLE_USAGE\n", - *len, sizeof(struct ipt_acc_handle_sockopt)); - break; - } + ret = 0; + break; + case IPT_SO_GET_ACCOUNT_GET_HANDLE_USAGE: { + unsigned int i; + if (*len < sizeof(struct ipt_acc_handle_sockopt)) { + printk("ACCOUNT: ipt_acc_get_ctl: wrong data size (%u != %zu)" + " for IPT_SO_GET_ACCOUNT_GET_HANDLE_USAGE\n", + *len, sizeof(struct ipt_acc_handle_sockopt)); + break; + } - /* Find out how many handles are in use */ - handle.itemcount = 0; - down(&ipt_acc_userspace_mutex); - for (i = 0; i < ACCOUNT_MAX_HANDLES; i++) - if (ipt_acc_handles[i].data) - handle.itemcount++; - up(&ipt_acc_userspace_mutex); + /* Find out how many handles are in use */ + handle.itemcount = 0; + down(&ipt_acc_userspace_mutex); + for (i = 0; i < ACCOUNT_MAX_HANDLES; i++) + if (ipt_acc_handles[i].data) + handle.itemcount++; + up(&ipt_acc_userspace_mutex); - if (copy_to_user(user, &handle, - sizeof(struct ipt_acc_handle_sockopt))) { - return -EFAULT; - break; - } - ret = 0; - break; - } - case IPT_SO_GET_ACCOUNT_GET_TABLE_NAMES: { - uint32_t size = 0, i, name_len; - char *tnames; + if (copy_to_user(user, &handle, + sizeof(struct ipt_acc_handle_sockopt))) { + return -EFAULT; + break; + } + ret = 0; + break; + } + case IPT_SO_GET_ACCOUNT_GET_TABLE_NAMES: { + uint32_t size = 0, i, name_len; + char *tnames; - spin_lock_bh(&ipt_acc_lock); + spin_lock_bh(&ipt_acc_lock); - /* Determine size of table names */ - for (i = 0; i < ACCOUNT_MAX_TABLES; i++) { - if (ipt_acc_tables[i].name[0] != 0) - size += strlen (ipt_acc_tables[i].name) + 1; - } - size += 1; /* Terminating NULL character */ + /* Determine size of table names */ + for (i = 0; i < ACCOUNT_MAX_TABLES; i++) { + if (ipt_acc_tables[i].name[0] != 0) + size += strlen(ipt_acc_tables[i].name) + 1; + } + size += 1; /* Terminating NULL character */ - if (*len < size || size > PAGE_SIZE) { - spin_unlock_bh(&ipt_acc_lock); - printk("ACCOUNT: ipt_acc_get_ctl: not enough space (%u < %u < %lu)" - " to store table names\n", *len, size, PAGE_SIZE); - ret = -ENOMEM; - break; - } - /* Copy table names to userspace */ - tnames = ipt_acc_tmpbuf; - for (i = 0; i < ACCOUNT_MAX_TABLES; i++) { - if (ipt_acc_tables[i].name[0] != 0) { - name_len = strlen (ipt_acc_tables[i].name) + 1; - memcpy(tnames, ipt_acc_tables[i].name, name_len); - tnames += name_len; - } - } - spin_unlock_bh(&ipt_acc_lock); + if (*len < size || size > PAGE_SIZE) { + spin_unlock_bh(&ipt_acc_lock); + printk("ACCOUNT: ipt_acc_get_ctl: not enough space (%u < %u < %lu)" + " to store table names\n", *len, size, PAGE_SIZE); + ret = -ENOMEM; + break; + } + /* Copy table names to userspace */ + tnames = ipt_acc_tmpbuf; + for (i = 0; i < ACCOUNT_MAX_TABLES; i++) { + if (ipt_acc_tables[i].name[0] != 0) { + name_len = strlen(ipt_acc_tables[i].name) + 1; + memcpy(tnames, ipt_acc_tables[i].name, name_len); + tnames += name_len; + } + } + spin_unlock_bh(&ipt_acc_lock); - /* Terminating NULL character */ - *tnames = 0; + /* Terminating NULL character */ + *tnames = 0; - /* Transfer to userspace */ - if (copy_to_user(user, ipt_acc_tmpbuf, size)) - return -EFAULT; + /* Transfer to userspace */ + if (copy_to_user(user, ipt_acc_tmpbuf, size)) + return -EFAULT; - ret = 0; - break; - } - default: - printk("ACCOUNT: ipt_acc_get_ctl: unknown request %i\n", cmd); - } + ret = 0; + break; + } + default: + printk("ACCOUNT: ipt_acc_get_ctl: unknown request %i\n", cmd); + } - return ret; + return ret; } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) @@ -1127,96 +1127,96 @@ static struct xt_target xt_acc_reg = { #else static struct ipt_target ipt_acc_reg = { #endif - .name = "ACCOUNT", + .name = "ACCOUNT", #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) - .family = AF_INET, + .family = AF_INET, #endif - .target = ipt_acc_target, + .target = ipt_acc_target, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) - .targetsize = sizeof(struct ipt_acc_info), + .targetsize = sizeof(struct ipt_acc_info), #endif - .checkentry = ipt_acc_checkentry, - .destroy = ipt_acc_destroy, - .me = THIS_MODULE + .checkentry = ipt_acc_checkentry, + .destroy = ipt_acc_destroy, + .me = THIS_MODULE }; static struct nf_sockopt_ops ipt_acc_sockopts = { - .pf = PF_INET, - .set_optmin = IPT_SO_SET_ACCOUNT_HANDLE_FREE, - .set_optmax = IPT_SO_SET_ACCOUNT_MAX+1, - .set = ipt_acc_set_ctl, - .get_optmin = IPT_SO_GET_ACCOUNT_PREPARE_READ, - .get_optmax = IPT_SO_GET_ACCOUNT_MAX+1, - .get = ipt_acc_get_ctl + .pf = PF_INET, + .set_optmin = IPT_SO_SET_ACCOUNT_HANDLE_FREE, + .set_optmax = IPT_SO_SET_ACCOUNT_MAX+1, + .set = ipt_acc_set_ctl, + .get_optmin = IPT_SO_GET_ACCOUNT_PREPARE_READ, + .get_optmax = IPT_SO_GET_ACCOUNT_MAX+1, + .get = ipt_acc_get_ctl }; static int __init init(void) { - init_MUTEX(&ipt_acc_userspace_mutex); + init_MUTEX(&ipt_acc_userspace_mutex); - if ((ipt_acc_tables = - kmalloc(ACCOUNT_MAX_TABLES * - sizeof(struct ipt_acc_table), GFP_KERNEL)) == NULL) { - printk("ACCOUNT: Out of memory allocating account_tables structure"); - goto error_cleanup; - } - memset(ipt_acc_tables, 0, - ACCOUNT_MAX_TABLES * sizeof(struct ipt_acc_table)); + if ((ipt_acc_tables = + kmalloc(ACCOUNT_MAX_TABLES * + sizeof(struct ipt_acc_table), GFP_KERNEL)) == NULL) { + printk("ACCOUNT: Out of memory allocating account_tables structure"); + goto error_cleanup; + } + memset(ipt_acc_tables, 0, + ACCOUNT_MAX_TABLES * sizeof(struct ipt_acc_table)); - if ((ipt_acc_handles = - kmalloc(ACCOUNT_MAX_HANDLES * - sizeof(struct ipt_acc_handle), GFP_KERNEL)) == NULL) { - printk("ACCOUNT: Out of memory allocating account_handles structure"); - goto error_cleanup; - } - memset(ipt_acc_handles, 0, - ACCOUNT_MAX_HANDLES * sizeof(struct ipt_acc_handle)); + if ((ipt_acc_handles = + kmalloc(ACCOUNT_MAX_HANDLES * + sizeof(struct ipt_acc_handle), GFP_KERNEL)) == NULL) { + printk("ACCOUNT: Out of memory allocating account_handles structure"); + goto error_cleanup; + } + memset(ipt_acc_handles, 0, + ACCOUNT_MAX_HANDLES * sizeof(struct ipt_acc_handle)); - /* Allocate one page as temporary storage */ - if ((ipt_acc_tmpbuf = (void*)__get_free_page(GFP_KERNEL)) == NULL) { - printk("ACCOUNT: Out of memory for temporary buffer page\n"); - goto error_cleanup; - } + /* Allocate one page as temporary storage */ + if ((ipt_acc_tmpbuf = (void*)__get_free_page(GFP_KERNEL)) == NULL) { + printk("ACCOUNT: Out of memory for temporary buffer page\n"); + goto error_cleanup; + } - /* Register setsockopt */ - if (nf_register_sockopt(&ipt_acc_sockopts) < 0) { - printk("ACCOUNT: Can't register sockopts. Aborting\n"); - goto error_cleanup; - } + /* Register setsockopt */ + if (nf_register_sockopt(&ipt_acc_sockopts) < 0) { + printk("ACCOUNT: Can't register sockopts. Aborting\n"); + goto error_cleanup; + } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) - if (xt_register_target(&xt_acc_reg)) + if (xt_register_target(&xt_acc_reg)) #else - if (ipt_register_target(&ipt_acc_reg)) + if (ipt_register_target(&ipt_acc_reg)) #endif - goto error_cleanup; + goto error_cleanup; - return 0; + return 0; error_cleanup: - if(ipt_acc_tables) - kfree(ipt_acc_tables); - if(ipt_acc_handles) - kfree(ipt_acc_handles); - if (ipt_acc_tmpbuf) - free_page((unsigned long)ipt_acc_tmpbuf); + if (ipt_acc_tables) + kfree(ipt_acc_tables); + if (ipt_acc_handles) + kfree(ipt_acc_handles); + if (ipt_acc_tmpbuf) + free_page((unsigned long)ipt_acc_tmpbuf); - return -EINVAL; + return -EINVAL; } static void __exit fini(void) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) - xt_unregister_target(&xt_acc_reg); + xt_unregister_target(&xt_acc_reg); #else - ipt_unregister_target(&ipt_acc_reg); + ipt_unregister_target(&ipt_acc_reg); #endif - nf_unregister_sockopt(&ipt_acc_sockopts); + nf_unregister_sockopt(&ipt_acc_sockopts); - kfree(ipt_acc_tables); - kfree(ipt_acc_handles); - free_page((unsigned long)ipt_acc_tmpbuf); + kfree(ipt_acc_tables); + kfree(ipt_acc_handles); + free_page((unsigned long)ipt_acc_tmpbuf); } module_init(init); diff --git a/extensions/xt_ACCOUNT.h b/extensions/xt_ACCOUNT.h index 0051c56..07bdcdf 100644 --- a/extensions/xt_ACCOUNT.h +++ b/extensions/xt_ACCOUNT.h @@ -13,14 +13,14 @@ #define IPT_SO_SET_ACCOUNT_HANDLE_FREE (IPT_BASE_CTL + 3) #define IPT_SO_SET_ACCOUNT_HANDLE_FREE_ALL (IPT_BASE_CTL + 4) -#define IPT_SO_SET_ACCOUNT_MAX IPT_SO_SET_ACCOUNT_HANDLE_FREE_ALL +#define IPT_SO_SET_ACCOUNT_MAX IPT_SO_SET_ACCOUNT_HANDLE_FREE_ALL #define IPT_SO_GET_ACCOUNT_PREPARE_READ (IPT_BASE_CTL + 4) #define IPT_SO_GET_ACCOUNT_PREPARE_READ_FLUSH (IPT_BASE_CTL + 5) #define IPT_SO_GET_ACCOUNT_GET_DATA (IPT_BASE_CTL + 6) #define IPT_SO_GET_ACCOUNT_GET_HANDLE_USAGE (IPT_BASE_CTL + 7) #define IPT_SO_GET_ACCOUNT_GET_TABLE_NAMES (IPT_BASE_CTL + 8) -#define IPT_SO_GET_ACCOUNT_MAX IPT_SO_GET_ACCOUNT_GET_TABLE_NAMES +#define IPT_SO_GET_ACCOUNT_MAX IPT_SO_GET_ACCOUNT_GET_TABLE_NAMES #define ACCOUNT_MAX_TABLES 128 #define ACCOUNT_TABLE_NAME_LEN 32 @@ -28,84 +28,84 @@ /* Structure for the userspace part of ipt_ACCOUNT */ struct ipt_acc_info { - uint32_t net_ip; - uint32_t net_mask; - char table_name[ACCOUNT_TABLE_NAME_LEN]; - int32_t table_nr; + uint32_t net_ip; + uint32_t net_mask; + char table_name[ACCOUNT_TABLE_NAME_LEN]; + int32_t table_nr; }; /* Internal table structure, generated by check_entry() */ struct ipt_acc_table { - char name[ACCOUNT_TABLE_NAME_LEN]; /* name of the table */ - uint32_t ip; /* base IP of network */ - uint32_t netmask; /* netmask of the network */ - unsigned char depth; /* size of network: - 0: 8 bit, 1: 16bit, 2: 24 bit */ - uint32_t refcount; /* refcount of this table. - if zero, destroy it */ - uint32_t itemcount; /* number of IPs in this table */ - void *data; /* pointer to the actual data, - depending on netmask */ + char name[ACCOUNT_TABLE_NAME_LEN]; /* name of the table */ + uint32_t ip; /* base IP of network */ + uint32_t netmask; /* netmask of the network */ + unsigned char depth; /* size of network: + 0: 8 bit, 1: 16bit, 2: 24 bit */ + uint32_t refcount; /* refcount of this table. + if zero, destroy it */ + uint32_t itemcount; /* number of IPs in this table */ + void *data; /* pointer to the actual data, + depending on netmask */ }; /* Internal handle structure */ struct ipt_acc_handle { - uint32_t ip; /* base IP of network. Used for - caculating the final IP during - get_data() */ - unsigned char depth; /* size of network. See above for - details */ - uint32_t itemcount; /* number of IPs in this table */ - void *data; /* pointer to the actual data, - depending on size */ + uint32_t ip; /* base IP of network. Used for + caculating the final IP during + get_data() */ + unsigned char depth; /* size of network. See above for + details */ + uint32_t itemcount; /* number of IPs in this table */ + void *data; /* pointer to the actual data, + depending on size */ }; /* Handle structure for communication with the userspace library */ struct ipt_acc_handle_sockopt { - uint32_t handle_nr; /* Used for HANDLE_FREE */ - char name[ACCOUNT_TABLE_NAME_LEN]; /* Used for HANDLE_PREPARE_READ/ - HANDLE_READ_FLUSH */ - uint32_t itemcount; /* Used for HANDLE_PREPARE_READ/ - HANDLE_READ_FLUSH */ + uint32_t handle_nr; /* Used for HANDLE_FREE */ + char name[ACCOUNT_TABLE_NAME_LEN]; /* Used for HANDLE_PREPARE_READ/ + HANDLE_READ_FLUSH */ + uint32_t itemcount; /* Used for HANDLE_PREPARE_READ/ + HANDLE_READ_FLUSH */ }; /* Used for every IP entry Size is 16 bytes so that 256 (class C network) * 16 fits in one kernel (zero) page */ struct ipt_acc_ip { - uint32_t src_packets; - uint32_t src_bytes; - uint32_t dst_packets; - uint32_t dst_bytes; + uint32_t src_packets; + uint32_t src_bytes; + uint32_t dst_packets; + uint32_t dst_bytes; }; /* - Used for every IP when returning data + Used for every IP when returning data */ struct ipt_acc_handle_ip { - uint32_t ip; - uint32_t src_packets; - uint32_t src_bytes; - uint32_t dst_packets; - uint32_t dst_bytes; + uint32_t ip; + uint32_t src_packets; + uint32_t src_bytes; + uint32_t dst_packets; + uint32_t dst_bytes; }; /* - The IPs are organized as an array so that direct slot - calculations are possible. - Only 8 bit networks are preallocated, 16/24 bit networks - allocate their slots when needed -> very efficent. + The IPs are organized as an array so that direct slot + calculations are possible. + Only 8 bit networks are preallocated, 16/24 bit networks + allocate their slots when needed -> very efficent. */ struct ipt_acc_mask_24 { - struct ipt_acc_ip ip[256]; + struct ipt_acc_ip ip[256]; }; struct ipt_acc_mask_16 { - struct ipt_acc_mask_24 *mask_24[256]; + struct ipt_acc_mask_24 *mask_24[256]; }; struct ipt_acc_mask_8 { - struct ipt_acc_mask_16 *mask_16[256]; + struct ipt_acc_mask_16 *mask_16[256]; }; -#endif /*_IPT_ACCOUNT_H*/ +#endif /* _IPT_ACCOUNT_H */ From 8d64e7bd50d4a6ca521dca61d6e6386d5983eb63 Mon Sep 17 00:00:00 2001 From: Jan Rafaj Date: Tue, 1 Sep 2009 19:52:48 +0200 Subject: [PATCH 04/15] ACCOUNT: remove manual compat support --- extensions/xt_ACCOUNT.c | 117 ---------------------------------------- 1 file changed, 117 deletions(-) diff --git a/extensions/xt_ACCOUNT.c b/extensions/xt_ACCOUNT.c index e034681..279c41f 100644 --- a/extensions/xt_ACCOUNT.c +++ b/extensions/xt_ACCOUNT.c @@ -206,44 +206,11 @@ static int ipt_acc_table_insert(char *name, uint32_t ip, uint32_t netmask) return -1; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) static bool ipt_acc_checkentry(const struct xt_tgchk_param *par) -#else -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) -static bool ipt_acc_checkentry(const char *tablename, -#else -static int ipt_acc_checkentry(const char *tablename, -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) - const void *e, -#else - const struct ipt_entry *e, -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) - const struct xt_target *target, -#endif - void *targinfo, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) - unsigned int targinfosize, -#endif - unsigned int hook_mask) -#endif /* >= 2.6.28 */ { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) struct ipt_acc_info *info = par->targinfo; -#else - struct ipt_acc_info *info = targinfo; -#endif int table_nr; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) - if (targinfosize != IPT_ALIGN(sizeof(struct ipt_acc_info))) { - DEBUGP("ACCOUNT: targinfosize %u != %u\n", - targinfosize, IPT_ALIGN(sizeof(struct ipt_acc_info))); - return 0; - } -#endif - spin_lock_bh(&ipt_acc_lock); table_nr = ipt_acc_table_insert(info->table_name, info->net_ip, info->net_mask); @@ -251,51 +218,19 @@ static int ipt_acc_checkentry(const char *tablename, if (table_nr == -1) { printk("ACCOUNT: Table insert problem. Aborting\n"); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) return false; -#else - return 0; -#endif } /* Table nr caching so we don't have to do an extra string compare for every packet */ info->table_nr = table_nr; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) return true; -#else - return 1; -#endif } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) static void ipt_acc_destroy(const struct xt_tgdtor_param *par) -#else -static void ipt_acc_destroy( -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) - const struct xt_target *target, -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19) - void *targinfo) -#else - void *targinfo, - unsigned int targinfosize) -#endif -#endif /* >= 2.6.28 */ { unsigned int i; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) struct ipt_acc_info *info = par->targinfo; -#else - struct ipt_acc_info *info = targinfo; -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) - if (targinfosize != IPT_ALIGN(sizeof(struct ipt_acc_info))) { - DEBUGP("ACCOUNT: targinfosize %u != %u\n", - targinfosize, IPT_ALIGN(sizeof(struct ipt_acc_info))); - } -#endif spin_lock_bh(&ipt_acc_lock); @@ -483,50 +418,14 @@ static void ipt_acc_depth2_insert(struct ipt_acc_mask_8 *mask_8, } } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) static unsigned int ipt_acc_target(struct sk_buff *skb, const struct xt_target_param *par) -#else -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) -static unsigned int ipt_acc_target(struct sk_buff *skb, -#else -static unsigned int ipt_acc_target(struct sk_buff **pskb, -#endif - const struct net_device *in, - const struct net_device *out, - unsigned int hooknum, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) - const struct xt_target *target, -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19) - const void *targinfo) -#else - const void *targinfo, - void *userinfo) -#endif -#endif /* 2.6.28 */ { const struct ipt_acc_info *info = -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) par->targinfo; -#else - (const struct ipt_acc_info *)targinfo; -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) uint32_t src_ip = ip_hdr(skb)->saddr; uint32_t dst_ip = ip_hdr(skb)->daddr; uint32_t size = ntohs(ip_hdr(skb)->tot_len); -#else -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) - uint32_t src_ip = ip_hdr(*pskb)->saddr; - uint32_t dst_ip = ip_hdr(*pskb)->daddr; - uint32_t size = ntohs(ip_hdr(*pskb)->tot_len); -#else - uint32_t src_ip = (*pskb)->nh.iph->saddr; - uint32_t dst_ip = (*pskb)->nh.iph->daddr; - uint32_t size = ntohs((*pskb)->nh.iph->tot_len); -#endif -#endif spin_lock_bh(&ipt_acc_lock); @@ -1122,19 +1021,11 @@ static int ipt_acc_get_ctl(struct sock *sk, int cmd, void *user, int *len) return ret; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) static struct xt_target xt_acc_reg = { -#else -static struct ipt_target ipt_acc_reg = { -#endif .name = "ACCOUNT", -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) .family = AF_INET, -#endif .target = ipt_acc_target, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) .targetsize = sizeof(struct ipt_acc_info), -#endif .checkentry = ipt_acc_checkentry, .destroy = ipt_acc_destroy, .me = THIS_MODULE @@ -1184,11 +1075,7 @@ static int __init init(void) goto error_cleanup; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) if (xt_register_target(&xt_acc_reg)) -#else - if (ipt_register_target(&ipt_acc_reg)) -#endif goto error_cleanup; return 0; @@ -1206,11 +1093,7 @@ error_cleanup: static void __exit fini(void) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) xt_unregister_target(&xt_acc_reg); -#else - ipt_unregister_target(&ipt_acc_reg); -#endif nf_unregister_sockopt(&ipt_acc_sockopts); From 58b016f0af5be9e3cfd38a93e78daf3960fe314b Mon Sep 17 00:00:00 2001 From: Jan Rafaj Date: Tue, 1 Sep 2009 19:52:48 +0200 Subject: [PATCH 05/15] ACCOUNT: replace own DEBUGP by kernel's pr_debug --- extensions/xt_ACCOUNT.c | 51 +++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/extensions/xt_ACCOUNT.c b/extensions/xt_ACCOUNT.c index 279c41f..301c4b4 100644 --- a/extensions/xt_ACCOUNT.c +++ b/extensions/xt_ACCOUNT.c @@ -12,6 +12,7 @@ * * ***************************************************************************/ +//#define DEBUG 1 #include #include #include @@ -36,12 +37,6 @@ #include #include "xt_ACCOUNT.h" -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - #if (PAGE_SIZE < 4096) #error "ipt_ACCOUNT needs at least a PAGE_SIZE of 4096" #endif @@ -125,14 +120,14 @@ static int ipt_acc_table_insert(char *name, uint32_t ip, uint32_t netmask) { unsigned int i; - DEBUGP("ACCOUNT: ipt_acc_table_insert: %s, %u.%u.%u.%u/%u.%u.%u.%u\n", + pr_debug("ACCOUNT: ipt_acc_table_insert: %s, %u.%u.%u.%u/%u.%u.%u.%u\n", name, NIPQUAD(ip), NIPQUAD(netmask)); /* Look for existing table */ for (i = 0; i < ACCOUNT_MAX_TABLES; i++) { if (strncmp(ipt_acc_tables[i].name, name, ACCOUNT_TABLE_NAME_LEN) == 0) { - DEBUGP("ACCOUNT: Found existing slot: %d - " + pr_debug("ACCOUNT: Found existing slot: %d - " "%u.%u.%u.%u/%u.%u.%u.%u\n", i, NIPQUAD(ipt_acc_tables[i].ip), NIPQUAD(ipt_acc_tables[i].netmask)); @@ -147,7 +142,7 @@ static int ipt_acc_table_insert(char *name, uint32_t ip, uint32_t netmask) } ipt_acc_tables[i].refcount++; - DEBUGP("ACCOUNT: Refcount: %d\n", ipt_acc_tables[i].refcount); + pr_debug("ACCOUNT: Refcount: %d\n", ipt_acc_tables[i].refcount); return i; } } @@ -160,7 +155,7 @@ static int ipt_acc_table_insert(char *name, uint32_t ip, uint32_t netmask) uint32_t calc_mask; int j; /* needs to be signed, otherwise we risk endless loop */ - DEBUGP("ACCOUNT: Found free slot: %d\n", i); + pr_debug("ACCOUNT: Found free slot: %d\n", i); strncpy(ipt_acc_tables[i].name, name, ACCOUNT_TABLE_NAME_LEN-1); ipt_acc_tables[i].ip = ip; @@ -183,7 +178,7 @@ static int ipt_acc_table_insert(char *name, uint32_t ip, uint32_t netmask) else if (netsize >= 8) ipt_acc_tables[i].depth = 2; - DEBUGP("ACCOUNT: calculated netsize: %u -> " + pr_debug("ACCOUNT: calculated netsize: %u -> " "ipt_acc_table depth %u\n", netsize, ipt_acc_tables[i].depth); @@ -234,7 +229,7 @@ static void ipt_acc_destroy(const struct xt_tgdtor_param *par) spin_lock_bh(&ipt_acc_lock); - DEBUGP("ACCOUNT: ipt_acc_deleteentry called for table: %s (#%d)\n", + pr_debug("ACCOUNT: ipt_acc_deleteentry called for table: %s (#%d)\n", info->table_name, info->table_nr); info->table_nr = -1; /* Set back to original state */ @@ -243,15 +238,15 @@ static void ipt_acc_destroy(const struct xt_tgdtor_param *par) for (i = 0; i < ACCOUNT_MAX_TABLES; i++) { if (strncmp(ipt_acc_tables[i].name, info->table_name, ACCOUNT_TABLE_NAME_LEN) == 0) { - DEBUGP("ACCOUNT: Found table at slot: %d\n", i); + pr_debug("ACCOUNT: Found table at slot: %d\n", i); ipt_acc_tables[i].refcount--; - DEBUGP("ACCOUNT: Refcount left: %d\n", + pr_debug("ACCOUNT: Refcount left: %d\n", ipt_acc_tables[i].refcount); /* Table not needed anymore? */ if (ipt_acc_tables[i].refcount == 0) { - DEBUGP("ACCOUNT: Destroying table at slot: %d\n", i); + pr_debug("ACCOUNT: Destroying table at slot: %d\n", i); ipt_acc_data_free(ipt_acc_tables[i].data, ipt_acc_tables[i].depth); memset(&ipt_acc_tables[i], 0, @@ -276,7 +271,7 @@ static void ipt_acc_depth0_insert(struct ipt_acc_mask_24 *mask_24, unsigned char is_src = 0, is_dst = 0, src_slot, dst_slot; char is_src_new_ip = 0, is_dst_new_ip = 0; /* Check if this entry is new */ - DEBUGP("ACCOUNT: ipt_acc_depth0_insert: %u.%u.%u.%u/%u.%u.%u.%u " + pr_debug("ACCOUNT: ipt_acc_depth0_insert: %u.%u.%u.%u/%u.%u.%u.%u " "for net %u.%u.%u.%u/%u.%u.%u.%u, size: %u\n", NIPQUAD(src_ip), NIPQUAD(dst_ip), NIPQUAD(net_ip), NIPQUAD(netmask), size); @@ -290,7 +285,7 @@ static void ipt_acc_depth0_insert(struct ipt_acc_mask_24 *mask_24, is_dst = 1; if (!is_src && !is_dst) { - DEBUGP("ACCOUNT: Skipping packet %u.%u.%u.%u/%u.%u.%u.%u " + pr_debug("ACCOUNT: Skipping packet %u.%u.%u.%u/%u.%u.%u.%u " "for net %u.%u.%u.%u/%u.%u.%u.%u\n", NIPQUAD(src_ip), NIPQUAD(dst_ip), NIPQUAD(net_ip), NIPQUAD(netmask)); return; @@ -303,7 +298,7 @@ static void ipt_acc_depth0_insert(struct ipt_acc_mask_24 *mask_24, /* Increase size counters */ if (is_src) { /* Calculate network slot */ - DEBUGP("ACCOUNT: Calculated SRC 8 bit network slot: %d\n", src_slot); + pr_debug("ACCOUNT: Calculated SRC 8 bit network slot: %d\n", src_slot); if (!mask_24->ip[src_slot].src_packets && !mask_24->ip[src_slot].dst_packets) is_src_new_ip = 1; @@ -312,7 +307,7 @@ static void ipt_acc_depth0_insert(struct ipt_acc_mask_24 *mask_24, mask_24->ip[src_slot].src_bytes += size; } if (is_dst) { - DEBUGP("ACCOUNT: Calculated DST 8 bit network slot: %d\n", dst_slot); + pr_debug("ACCOUNT: Calculated DST 8 bit network slot: %d\n", dst_slot); if (!mask_24->ip[dst_slot].src_packets && !mask_24->ip[dst_slot].dst_packets) is_dst_new_ip = 1; @@ -322,24 +317,24 @@ static void ipt_acc_depth0_insert(struct ipt_acc_mask_24 *mask_24, } /* Increase itemcounter */ - DEBUGP("ACCOUNT: Itemcounter before: %d\n", *itemcount); + pr_debug("ACCOUNT: Itemcounter before: %d\n", *itemcount); if (src_slot == dst_slot) { if (is_src_new_ip || is_dst_new_ip) { - DEBUGP("ACCOUNT: src_slot == dst_slot: %d, %d\n", + pr_debug("ACCOUNT: src_slot == dst_slot: %d, %d\n", is_src_new_ip, is_dst_new_ip); (*itemcount)++; } } else { if (is_src_new_ip) { - DEBUGP("ACCOUNT: New src_ip: %u.%u.%u.%u\n", NIPQUAD(src_ip)); + pr_debug("ACCOUNT: New src_ip: %u.%u.%u.%u\n", NIPQUAD(src_ip)); (*itemcount)++; } if (is_dst_new_ip) { - DEBUGP("ACCOUNT: New dst_ip: %u.%u.%u.%u\n", NIPQUAD(dst_ip)); + pr_debug("ACCOUNT: New dst_ip: %u.%u.%u.%u\n", NIPQUAD(dst_ip)); (*itemcount)++; } } - DEBUGP("ACCOUNT: Itemcounter after: %d\n", *itemcount); + pr_debug("ACCOUNT: Itemcounter after: %d\n", *itemcount); } static void ipt_acc_depth1_insert(struct ipt_acc_mask_16 *mask_16, @@ -350,7 +345,7 @@ static void ipt_acc_depth1_insert(struct ipt_acc_mask_16 *mask_16, /* Do we need to process src IP? */ if ((net_ip & netmask) == (src_ip & netmask)) { unsigned char slot = (unsigned char)((src_ip & 0x00FF0000) >> 16); - DEBUGP("ACCOUNT: Calculated SRC 16 bit network slot: %d\n", slot); + pr_debug("ACCOUNT: Calculated SRC 16 bit network slot: %d\n", slot); /* Do we need to create a new mask_24 bucket? */ if (!mask_16->mask_24[slot] && (mask_16->mask_24[slot] = @@ -366,7 +361,7 @@ static void ipt_acc_depth1_insert(struct ipt_acc_mask_16 *mask_16, /* Do we need to process dst IP? */ if ((net_ip & netmask) == (dst_ip & netmask)) { unsigned char slot = (unsigned char)((dst_ip & 0x00FF0000) >> 16); - DEBUGP("ACCOUNT: Calculated DST 16 bit network slot: %d\n", slot); + pr_debug("ACCOUNT: Calculated DST 16 bit network slot: %d\n", slot); /* Do we need to create a new mask_24 bucket? */ if (!mask_16->mask_24[slot] && (mask_16->mask_24[slot] @@ -388,7 +383,7 @@ static void ipt_acc_depth2_insert(struct ipt_acc_mask_8 *mask_8, /* Do we need to process src IP? */ if ((net_ip & netmask) == (src_ip & netmask)) { unsigned char slot = (unsigned char)((src_ip & 0x0000FF00) >> 8); - DEBUGP("ACCOUNT: Calculated SRC 24 bit network slot: %d\n", slot); + pr_debug("ACCOUNT: Calculated SRC 24 bit network slot: %d\n", slot); /* Do we need to create a new mask_24 bucket? */ if (!mask_8->mask_16[slot] && (mask_8->mask_16[slot] @@ -404,7 +399,7 @@ static void ipt_acc_depth2_insert(struct ipt_acc_mask_8 *mask_8, /* Do we need to process dst IP? */ if ((net_ip & netmask) == (dst_ip & netmask)) { unsigned char slot = (unsigned char)((dst_ip & 0x0000FF00) >> 8); - DEBUGP("ACCOUNT: Calculated DST 24 bit network slot: %d\n", slot); + pr_debug("ACCOUNT: Calculated DST 24 bit network slot: %d\n", slot); /* Do we need to create a new mask_24 bucket? */ if (!mask_8->mask_16[slot] && (mask_8->mask_16[slot] From 03363a528aa54df2a7535bdc8c82e5a741e3732d Mon Sep 17 00:00:00 2001 From: Jan Rafaj Date: Tue, 1 Sep 2009 19:52:48 +0200 Subject: [PATCH 06/15] ACCOUNT: utilize compat_xtables.h for backwards compatibility --- extensions/xt_ACCOUNT.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/extensions/xt_ACCOUNT.c b/extensions/xt_ACCOUNT.c index 301c4b4..47d26fd 100644 --- a/extensions/xt_ACCOUNT.c +++ b/extensions/xt_ACCOUNT.c @@ -36,6 +36,7 @@ #include #include "xt_ACCOUNT.h" +#include "compat_xtables.h" #if (PAGE_SIZE < 4096) #error "ipt_ACCOUNT needs at least a PAGE_SIZE of 4096" @@ -413,14 +414,14 @@ static void ipt_acc_depth2_insert(struct ipt_acc_mask_8 *mask_8, } } -static unsigned int ipt_acc_target(struct sk_buff *skb, const struct xt_target_param *par) +static unsigned int ipt_acc_target(struct sk_buff **pskb, const struct xt_target_param *par) { const struct ipt_acc_info *info = par->targinfo; - uint32_t src_ip = ip_hdr(skb)->saddr; - uint32_t dst_ip = ip_hdr(skb)->daddr; - uint32_t size = ntohs(ip_hdr(skb)->tot_len); + uint32_t src_ip = ip_hdr(*pskb)->saddr; + uint32_t dst_ip = ip_hdr(*pskb)->daddr; + uint32_t size = ntohs(ip_hdr(*pskb)->tot_len); spin_lock_bh(&ipt_acc_lock); From 47e002127cf3705d03c7a977e835217daf4676c7 Mon Sep 17 00:00:00 2001 From: Jan Rafaj Date: Tue, 1 Sep 2009 19:52:48 +0200 Subject: [PATCH 07/15] ACCOUNT: use non-clashing function names [jengelh: It is just impossible to set a breakpoint right on functions if all modules call or/use the same symbol name.] --- extensions/libxt_ACCOUNT.c | 64 +++++++++++++++++++------------------- extensions/xt_ACCOUNT.c | 8 ++--- 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/extensions/libxt_ACCOUNT.c b/extensions/libxt_ACCOUNT.c index c87a2ff..90a1028 100644 --- a/extensions/libxt_ACCOUNT.c +++ b/extensions/libxt_ACCOUNT.c @@ -13,7 +13,7 @@ #include #include "xt_ACCOUNT.h" -static struct option opts[] = { +static struct option account_tg_opts[] = { { .name = "addr", .has_arg = 1, .flag = 0, .val = 'a' }, { .name = "tname", .has_arg = 1, .flag = 0, .val = 't' }, { .name = 0 } @@ -25,18 +25,18 @@ static struct option opts[] = { #endif /* Function which prints out usage message. */ -static void help(void) +static void account_tg_help(void) { printf( "ACCOUNT v%s options:\n" " --%s ip/netmask\t\tBase network IP and netmask used for this table\n" " --%s name\t\t\tTable name for the userspace library\n", -XTABLES_VERSION, opts[0].name, opts[1].name); +XTABLES_VERSION, account_tg_opts[0].name, account_tg_opts[1].name); } /* Initialize the target. */ static void -init(struct xt_entry_target *t) +account_tg_init(struct xt_entry_target *t) { struct ipt_acc_info *accountinfo = (struct ipt_acc_info *)t->data; @@ -49,7 +49,7 @@ init(struct xt_entry_target *t) /* Function which parses command options; returns true if it ate an option */ -static int parse(int c, char **argv, int invert, unsigned int *flags, +static int account_tg_parse(int c, char **argv, int invert, unsigned int *flags, const void *entry, struct xt_entry_target **target) { struct ipt_acc_info *accountinfo = (struct ipt_acc_info *)(*target)->data; @@ -60,11 +60,11 @@ static int parse(int c, char **argv, int invert, unsigned int *flags, case 'a': if (*flags & IPT_ACCOUNT_OPT_ADDR) xtables_error(PARAMETER_PROBLEM, "Can't specify --%s twice", - opts[0].name); + account_tg_opts[0].name); if (xtables_check_inverse(optarg, &invert, NULL, 0)) xtables_error(PARAMETER_PROBLEM, "Unexpected `!' after --%s", - opts[0].name); + account_tg_opts[0].name); #ifdef XTABLES_VERSION_CODE xtables_ipparse_any(optarg, &addrs, &mask, &naddrs); @@ -84,16 +84,19 @@ static int parse(int c, char **argv, int invert, unsigned int *flags, case 't': if (*flags & IPT_ACCOUNT_OPT_TABLE) xtables_error(PARAMETER_PROBLEM, - "Can't specify --%s twice", opts[1].name); + "Can't specify --%s twice", + account_tg_opts[1].name); if (xtables_check_inverse(optarg, &invert, NULL, 0)) xtables_error(PARAMETER_PROBLEM, - "Unexpected `!' after --%s", opts[1].name); + "Unexpected `!' after --%s", + account_tg_opts[1].name); if (strlen(optarg) > ACCOUNT_TABLE_NAME_LEN - 1) xtables_error(PARAMETER_PROBLEM, "Maximum table name length %u for --%s", - ACCOUNT_TABLE_NAME_LEN - 1, opts[1].name); + ACCOUNT_TABLE_NAME_LEN - 1, + account_tg_opts[1].name); strcpy(accountinfo->table_name, optarg); *flags |= IPT_ACCOUNT_OPT_TABLE; @@ -105,12 +108,11 @@ static int parse(int c, char **argv, int invert, unsigned int *flags, return 1; } -/* Final check; nothing. */ -static void final_check(unsigned int flags) +static void account_tg_check(unsigned int flags) { if (!(flags & IPT_ACCOUNT_OPT_ADDR) || !(flags & IPT_ACCOUNT_OPT_TABLE)) xtables_error(PARAMETER_PROBLEM, "ACCOUNT: needs --%s and --%s", - opts[0].name, opts[1].name); + account_tg_opts[0].name, account_tg_opts[1].name); } static const char *print_helper_ip(struct in_addr a) @@ -131,7 +133,7 @@ static const char *print_helper_mask(struct in_addr a) #endif } -static void print_it(const void *ip, +static void account_tg_print_it(const void *ip, const struct xt_entry_target *target, char do_prefix) { const struct ipt_acc_info *accountinfo @@ -144,7 +146,7 @@ static void print_it(const void *ip, // Network information if (do_prefix) printf("--"); - printf("%s ", opts[0].name); + printf("%s ", account_tg_opts[0].name); a.s_addr = accountinfo->net_ip; printf("%s", print_helper_ip(a)); @@ -155,44 +157,42 @@ static void print_it(const void *ip, if (do_prefix) printf("--"); - printf("%s %s", opts[1].name, accountinfo->table_name); + printf("%s %s", account_tg_opts[1].name, accountinfo->table_name); } static void -print(const void *ip, +account_tg_print(const void *ip, const struct xt_entry_target *target, int numeric) { - print_it(ip, target, 0); + account_tg_print_it(ip, target, 0); } /* Saves the union ipt_targinfo in parsable form to stdout. */ static void -save(const void *ip, const struct xt_entry_target *target) +account_tg_save(const void *ip, const struct xt_entry_target *target) { - print_it(ip, target, 1); + account_tg_print_it(ip, target, 1); } -static -struct xtables_target account -= { +static struct xtables_target account_tg_reg = { .next = NULL, .name = "ACCOUNT", .family = AF_INET, .version = XTABLES_VERSION, .size = XT_ALIGN(sizeof(struct ipt_acc_info)), .userspacesize = offsetof(struct ipt_acc_info, table_nr), - .help = &help, - .init = &init, - .parse = &parse, - .final_check = &final_check, - .print = &print, - .save = &save, - .extra_opts = opts + .help = account_tg_help, + .init = account_tg_init, + .parse = account_tg_parse, + .final_check = account_tg_check, + .print = account_tg_print, + .save = account_tg_save, + .extra_opts = account_tg_opts, }; -void _init(void) +static __attribute__((constructor)) void account_tg_ldr(void) { - xtables_register_target(&account); + xtables_register_target(&account_tg_reg); } diff --git a/extensions/xt_ACCOUNT.c b/extensions/xt_ACCOUNT.c index 47d26fd..1808013 100644 --- a/extensions/xt_ACCOUNT.c +++ b/extensions/xt_ACCOUNT.c @@ -1037,7 +1037,7 @@ static struct nf_sockopt_ops ipt_acc_sockopts = { .get = ipt_acc_get_ctl }; -static int __init init(void) +static int __init account_tg_init(void) { init_MUTEX(&ipt_acc_userspace_mutex); @@ -1087,7 +1087,7 @@ error_cleanup: return -EINVAL; } -static void __exit fini(void) +static void __exit account_tg_exit(void) { xt_unregister_target(&xt_acc_reg); @@ -1098,6 +1098,6 @@ static void __exit fini(void) free_page((unsigned long)ipt_acc_tmpbuf); } -module_init(init); -module_exit(fini); +module_init(account_tg_init); +module_exit(account_tg_exit); MODULE_LICENSE("GPL"); From a3baa78ae219bc9f78b62cbd419f967399e55bbd Mon Sep 17 00:00:00 2001 From: Jan Rafaj Date: Tue, 1 Sep 2009 19:52:48 +0200 Subject: [PATCH 08/15] ACCOUNT: remove compat glue from libxt_ACCOUNT --- extensions/libxt_ACCOUNT.c | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/extensions/libxt_ACCOUNT.c b/extensions/libxt_ACCOUNT.c index 90a1028..019a92d 100644 --- a/extensions/libxt_ACCOUNT.c +++ b/extensions/libxt_ACCOUNT.c @@ -10,7 +10,6 @@ #include #include #include -#include #include "xt_ACCOUNT.h" static struct option account_tg_opts[] = { @@ -19,19 +18,14 @@ static struct option account_tg_opts[] = { { .name = 0 } }; -/* Compat glue for iptables 1.4.0 */ -#ifndef XTABLES_VERSION -#define XTABLES_VERSION IPTABLES_VERSION -#endif - /* Function which prints out usage message. */ static void account_tg_help(void) { printf( -"ACCOUNT v%s options:\n" +"ACCOUNT target options:\n" " --%s ip/netmask\t\tBase network IP and netmask used for this table\n" " --%s name\t\t\tTable name for the userspace library\n", -XTABLES_VERSION, account_tg_opts[0].name, account_tg_opts[1].name); +account_tg_opts[0].name, account_tg_opts[1].name); } /* Initialize the target. */ @@ -66,12 +60,7 @@ static int account_tg_parse(int c, char **argv, int invert, unsigned int *flags, xtables_error(PARAMETER_PROBLEM, "Unexpected `!' after --%s", account_tg_opts[0].name); -#ifdef XTABLES_VERSION_CODE xtables_ipparse_any(optarg, &addrs, &mask, &naddrs); -#else - parse_hostnetworkmask(optarg, &addrs, &mask, &naddrs); -#endif - if (naddrs > 1) xtables_error(PARAMETER_PROBLEM, "multiple IP addresses not allowed"); @@ -117,20 +106,12 @@ static void account_tg_check(unsigned int flags) static const char *print_helper_ip(struct in_addr a) { -#ifdef XTABLES_VERSION_CODE return xtables_ipaddr_to_numeric(&a); -#else - return addr_to_dotted(&a); -#endif } static const char *print_helper_mask(struct in_addr a) { -#ifdef XTABLES_VERSION_CODE return xtables_ipmask_to_numeric(&a); -#else - return mask_to_dotted(&a); -#endif } static void account_tg_print_it(const void *ip, @@ -177,7 +158,6 @@ account_tg_save(const void *ip, const struct xt_entry_target *target) } static struct xtables_target account_tg_reg = { - .next = NULL, .name = "ACCOUNT", .family = AF_INET, .version = XTABLES_VERSION, From ac44a5a1fe68182c2bf199240309d7c5a5441af5 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 5 Sep 2009 03:22:23 +0200 Subject: [PATCH 09/15] ACCOUNT: direct-inline two short functions --- extensions/libxt_ACCOUNT.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/extensions/libxt_ACCOUNT.c b/extensions/libxt_ACCOUNT.c index 019a92d..00b2fb6 100644 --- a/extensions/libxt_ACCOUNT.c +++ b/extensions/libxt_ACCOUNT.c @@ -104,16 +104,6 @@ static void account_tg_check(unsigned int flags) account_tg_opts[0].name, account_tg_opts[1].name); } -static const char *print_helper_ip(struct in_addr a) -{ - return xtables_ipaddr_to_numeric(&a); -} - -static const char *print_helper_mask(struct in_addr a) -{ - return xtables_ipmask_to_numeric(&a); -} - static void account_tg_print_it(const void *ip, const struct xt_entry_target *target, char do_prefix) { @@ -130,9 +120,9 @@ static void account_tg_print_it(const void *ip, printf("%s ", account_tg_opts[0].name); a.s_addr = accountinfo->net_ip; - printf("%s", print_helper_ip(a)); + printf("%s", xtables_ipaddr_to_numeric(&a)); a.s_addr = accountinfo->net_mask; - printf("%s", print_helper_mask(a)); + printf("%s", xtables_ipmask_to_numeric(&a)); printf(" "); if (do_prefix) From cb268031b7b4b1a0adecdbcf408950addf73133b Mon Sep 17 00:00:00 2001 From: Jan Rafaj Date: Tue, 1 Sep 2009 19:52:48 +0200 Subject: [PATCH 10/15] ACCOUNT: supply manpage --- extensions/libxt_ACCOUNT.man | 72 ++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 extensions/libxt_ACCOUNT.man diff --git a/extensions/libxt_ACCOUNT.man b/extensions/libxt_ACCOUNT.man new file mode 100644 index 0000000..e80f5eb --- /dev/null +++ b/extensions/libxt_ACCOUNT.man @@ -0,0 +1,72 @@ +The ACCOUNT target is a high performance accounting system for large +local networks. It allows per-IP accounting in whole prefixes of IPv4 +addresses with size of up to /8 without the need to add individual +accouting rule for each IP address. +.PP +The ACCOUNT is designed to be queried for data every second or at +least every ten seconds. It is written as kernel module to handle high +bandwidths without packet loss. +.PP +The largest possible subnet size is 24 bit, meaning f.e. 10.0.0.0/8 +network. ACCOUNT uses fixed internal data structures +which speeds up the processing of each packet. Furthermore, +accounting data for one complete 192.168.1.X/24 network takes 4kb of +memory. Memory for 16 or 24 bit networks is only allocated when +needed. +.PP +To optimize the kernel<->userspace data transfer a bit more, the +kernel module only transfers information about IPs, where the src/dst +packet counter is not 0. This saves precious kernel time. +.PP +There is no /proc interface as it would be too slow for continuous access. +The read&flush query operation is the fastest, as no internal data +snapshot needs to be created&copied for all data. Use the "read" +operation without flush only for debugging purposes! +.PP +Usage: +.PP +ACCOUNT takes two mandatory parameters: +.TP +\fB--addr\fR \fInetwork/netmask\fR +where "network/netmask" is the subnet to account for, in CIDR syntax +.TP +\fB--tname\fP \fINAME\fP +where "NAME" is the name of the table where the accounting information +should be stored +.PP +Special case is subnet "0.0.0.0/0": all data are then stored in the src_bytes +and src_packets structure of slot "0". This is useful if you want +to account the overall traffic to/from your internet provider. +.PP +The data can be queried using the userspace libxt_ACCOUNT_cl library, +and by the reference implementation to show usage of this library, +the "iptaccount" tool, which features following options: +.PP +[\fB-u\fP] show kernel handle usage +.PP +[\fB-h\fP] free all kernel handles (experts only!) +.PP +[\fB-a\fP] list all table names +.PP +[\fB-l name\fP] show data in table \fBname\fP +.PP +[\fB-f\fP] flush data after showing +.PP +[\fB-c\fP] loop every second (abort with CTRL+C) +.PP +Here's an example of use: +.PP +iptables -A FORWARD -j ACCOUNT --addr 0.0.0.0/0 --tname all_outgoing +iptables -A FORWARD -j ACCOUNT --addr 192.168.1.0/24 --tname sales +.PP +This creates two tables called "all_outgoing" and "sales" which can be +queried using the userspace library/iptaccount tool. +.PP +Note that this target is non-terminating - the packet destined to it +will continue traversing the chain in which it has been used. +.PP +Also note that once a table has been defined for specific CIDR address/netmask +block, it can be referenced multiple times using -j ACCOUNT, provided +that both the original table name and address/netmask block are specified. +.PP +For more information go to http://www.intra2net.com/en/developer/ipt_ACCOUNT/ From c3d080f21a76fa4c8746469c538322aba619cac0 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 5 Sep 2009 03:26:26 +0200 Subject: [PATCH 11/15] ACCOUNT: manpage updates - expand "f.e." - escape dashes where appropriate - fB/fI formatting --- extensions/libxt_ACCOUNT.man | 40 ++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/extensions/libxt_ACCOUNT.man b/extensions/libxt_ACCOUNT.man index e80f5eb..14b9fee 100644 --- a/extensions/libxt_ACCOUNT.man +++ b/extensions/libxt_ACCOUNT.man @@ -7,10 +7,10 @@ The ACCOUNT is designed to be queried for data every second or at least every ten seconds. It is written as kernel module to handle high bandwidths without packet loss. .PP -The largest possible subnet size is 24 bit, meaning f.e. 10.0.0.0/8 +The largest possible subnet size is 24 bit, meaning for example 10.0.0.0/8 network. ACCOUNT uses fixed internal data structures which speeds up the processing of each packet. Furthermore, -accounting data for one complete 192.168.1.X/24 network takes 4kb of +accounting data for one complete 192.168.1.X/24 network takes 4 KB of memory. Memory for 16 or 24 bit networks is only allocated when needed. .PP @@ -19,7 +19,7 @@ kernel module only transfers information about IPs, where the src/dst packet counter is not 0. This saves precious kernel time. .PP There is no /proc interface as it would be too slow for continuous access. -The read&flush query operation is the fastest, as no internal data +The read-and-flush query operation is the fastest, as no internal data snapshot needs to be created&copied for all data. Use the "read" operation without flush only for debugging purposes! .PP @@ -27,46 +27,46 @@ Usage: .PP ACCOUNT takes two mandatory parameters: .TP -\fB--addr\fR \fInetwork/netmask\fR -where "network/netmask" is the subnet to account for, in CIDR syntax +\fB\-\-addr\fR \fInetwork\fP\fB/\fP\fInetmask\fR +where \fInetwork\fP\fB/\fP\fInetmask\fP is the subnet to account for, in CIDR syntax .TP -\fB--tname\fP \fINAME\fP -where "NAME" is the name of the table where the accounting information +\fB\-\-tname\fP \fINAME\fP +where \fINAME\fP is the name of the table where the accounting information should be stored .PP -Special case is subnet "0.0.0.0/0": all data are then stored in the src_bytes +The subnet 0.0.0.0/0 is a special case: all data are then stored in the src_bytes and src_packets structure of slot "0". This is useful if you want to account the overall traffic to/from your internet provider. .PP The data can be queried using the userspace libxt_ACCOUNT_cl library, and by the reference implementation to show usage of this library, -the "iptaccount" tool, which features following options: +the \fBiptaccount\fP(8) tool, which features following options: .PP -[\fB-u\fP] show kernel handle usage +[\fB\-u\fP] show kernel handle usage .PP -[\fB-h\fP] free all kernel handles (experts only!) +[\fB\-h\fP] free all kernel handles (experts only!) .PP -[\fB-a\fP] list all table names +[\fB\-a\fP] list all table names .PP -[\fB-l name\fP] show data in table \fBname\fP +[\fB\-l\fP \fIname\fP] show data in table \fIname\fP .PP -[\fB-f\fP] flush data after showing +[\fB\-f\fP] flush data after showing .PP -[\fB-c\fP] loop every second (abort with CTRL+C) +[\fB\-c\fP] loop every second (abort with CTRL+C) .PP -Here's an example of use: +Here is an example of use: .PP -iptables -A FORWARD -j ACCOUNT --addr 0.0.0.0/0 --tname all_outgoing -iptables -A FORWARD -j ACCOUNT --addr 192.168.1.0/24 --tname sales +iptables \-A FORWARD \-j ACCOUNT \-\-addr 0.0.0.0/0 \-\-tname all_outgoing +iptables \-A FORWARD \-j ACCOUNT \-\-addr 192.168.1.0/24 \-\-tname sales .PP This creates two tables called "all_outgoing" and "sales" which can be queried using the userspace library/iptaccount tool. .PP -Note that this target is non-terminating - the packet destined to it +Note that this target is non-terminating \(em the packet destined to it will continue traversing the chain in which it has been used. .PP Also note that once a table has been defined for specific CIDR address/netmask -block, it can be referenced multiple times using -j ACCOUNT, provided +block, it can be referenced multiple times using \-j ACCOUNT, provided that both the original table name and address/netmask block are specified. .PP For more information go to http://www.intra2net.com/en/developer/ipt_ACCOUNT/ From f4b96672ef084d854bb315ae34565cf8c323fba8 Mon Sep 17 00:00:00 2001 From: Jan Rafaj Date: Tue, 1 Sep 2009 19:52:48 +0200 Subject: [PATCH 12/15] ACCOUNT: add kernel module metadata and alias --- extensions/xt_ACCOUNT.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/extensions/xt_ACCOUNT.c b/extensions/xt_ACCOUNT.c index 1808013..bd2f1d5 100644 --- a/extensions/xt_ACCOUNT.c +++ b/extensions/xt_ACCOUNT.c @@ -1100,4 +1100,7 @@ static void __exit account_tg_exit(void) module_init(account_tg_init); module_exit(account_tg_exit); +MODULE_DESCRIPTION("Xtables: per-IP accounting for large prefixes"); +MODULE_AUTHOR("Intra2net AG "); +MODULE_ALIAS("ipt_ACCOUNT"); MODULE_LICENSE("GPL"); From 90fa3ab9e2b9b7a84b825ae3dfe6f84ec3876216 Mon Sep 17 00:00:00 2001 From: Jan Rafaj Date: Tue, 1 Sep 2009 19:52:48 +0200 Subject: [PATCH 13/15] ACCOUNT: tweak base ctl number for setsockopts IPT_BASE_CTL+3 is already used IPT_SO_GET_REVISION_TARGET and therefore must not be used by extensions. --- extensions/xt_ACCOUNT.h | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/extensions/xt_ACCOUNT.h b/extensions/xt_ACCOUNT.h index 07bdcdf..65ff4ab 100644 --- a/extensions/xt_ACCOUNT.h +++ b/extensions/xt_ACCOUNT.h @@ -11,15 +11,22 @@ #ifndef _IPT_ACCOUNT_H #define _IPT_ACCOUNT_H -#define IPT_SO_SET_ACCOUNT_HANDLE_FREE (IPT_BASE_CTL + 3) -#define IPT_SO_SET_ACCOUNT_HANDLE_FREE_ALL (IPT_BASE_CTL + 4) +/* + * Socket option interface shared between kernel (xt_ACCOUNT) and userspace + * library (libxt_ACCOUNT_cl). Hopefully we are unique at least within our + * kernel & xtables-addons space. + */ +#define SO_ACCOUNT_BASE_CTL 90 + +#define IPT_SO_SET_ACCOUNT_HANDLE_FREE (SO_ACCOUNT_BASE_CTL + 1) +#define IPT_SO_SET_ACCOUNT_HANDLE_FREE_ALL (SO_ACCOUNT_BASE_CTL + 2) #define IPT_SO_SET_ACCOUNT_MAX IPT_SO_SET_ACCOUNT_HANDLE_FREE_ALL -#define IPT_SO_GET_ACCOUNT_PREPARE_READ (IPT_BASE_CTL + 4) -#define IPT_SO_GET_ACCOUNT_PREPARE_READ_FLUSH (IPT_BASE_CTL + 5) -#define IPT_SO_GET_ACCOUNT_GET_DATA (IPT_BASE_CTL + 6) -#define IPT_SO_GET_ACCOUNT_GET_HANDLE_USAGE (IPT_BASE_CTL + 7) -#define IPT_SO_GET_ACCOUNT_GET_TABLE_NAMES (IPT_BASE_CTL + 8) +#define IPT_SO_GET_ACCOUNT_PREPARE_READ (SO_ACCOUNT_BASE_CTL + 4) +#define IPT_SO_GET_ACCOUNT_PREPARE_READ_FLUSH (SO_ACCOUNT_BASE_CTL + 5) +#define IPT_SO_GET_ACCOUNT_GET_DATA (SO_ACCOUNT_BASE_CTL + 6) +#define IPT_SO_GET_ACCOUNT_GET_HANDLE_USAGE (SO_ACCOUNT_BASE_CTL + 7) +#define IPT_SO_GET_ACCOUNT_GET_TABLE_NAMES (SO_ACCOUNT_BASE_CTL + 8) #define IPT_SO_GET_ACCOUNT_MAX IPT_SO_GET_ACCOUNT_GET_TABLE_NAMES #define ACCOUNT_MAX_TABLES 128 From 1f736c82034e5fe6ed0b0abc3aa973739229ae9d Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Thu, 3 Sep 2009 13:45:13 +0200 Subject: [PATCH 14/15] ACCOUNT: remove static initializers to zero These are not needed, .bss is zeroed. --- extensions/xt_ACCOUNT.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extensions/xt_ACCOUNT.c b/extensions/xt_ACCOUNT.c index bd2f1d5..e619672 100644 --- a/extensions/xt_ACCOUNT.c +++ b/extensions/xt_ACCOUNT.c @@ -42,9 +42,9 @@ #error "ipt_ACCOUNT needs at least a PAGE_SIZE of 4096" #endif -static struct ipt_acc_table *ipt_acc_tables = NULL; -static struct ipt_acc_handle *ipt_acc_handles = NULL; -static void *ipt_acc_tmpbuf = NULL; +static struct ipt_acc_table *ipt_acc_tables; +static struct ipt_acc_handle *ipt_acc_handles; +static void *ipt_acc_tmpbuf; /* Spinlock used for manipulating the current accounting tables/data */ static DEFINE_SPINLOCK(ipt_acc_lock); From bd4be0d9911979e7129d486ea3d7e1422f83003f Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 5 Sep 2009 04:34:10 +0200 Subject: [PATCH 15/15] ACCOUNT: remove pointless casts --- extensions/xt_ACCOUNT.c | 52 ++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/extensions/xt_ACCOUNT.c b/extensions/xt_ACCOUNT.c index e619672..0455d1a 100644 --- a/extensions/xt_ACCOUNT.c +++ b/extensions/xt_ACCOUNT.c @@ -79,7 +79,7 @@ static void ipt_acc_data_free(void *data, unsigned char depth) /* Free for 16 bit network */ if (depth == 1) { - struct ipt_acc_mask_16 *mask_16 = (struct ipt_acc_mask_16 *)data; + struct ipt_acc_mask_16 *mask_16 = data; unsigned int b; for (b = 0; b <= 255; b++) { if (mask_16->mask_24[b]) { @@ -95,7 +95,7 @@ static void ipt_acc_data_free(void *data, unsigned char depth) unsigned int a, b; for (a = 0; a <= 255; a++) { if (((struct ipt_acc_mask_8 *)data)->mask_16[a]) { - struct ipt_acc_mask_16 *mask_16 = (struct ipt_acc_mask_16*) + struct ipt_acc_mask_16 *mask_16 = ((struct ipt_acc_mask_8 *)data)->mask_16[a]; for (b = 0; b <= 255; b++) { @@ -293,8 +293,8 @@ static void ipt_acc_depth0_insert(struct ipt_acc_mask_24 *mask_24, } /* Calculate array positions */ - src_slot = (unsigned char)((src_ip & 0xFF000000) >> 24); - dst_slot = (unsigned char)((dst_ip & 0xFF000000) >> 24); + src_slot = (src_ip & 0xFF000000) >> 24; + dst_slot = (dst_ip & 0xFF000000) >> 24; /* Increase size counters */ if (is_src) { @@ -345,7 +345,7 @@ static void ipt_acc_depth1_insert(struct ipt_acc_mask_16 *mask_16, { /* Do we need to process src IP? */ if ((net_ip & netmask) == (src_ip & netmask)) { - unsigned char slot = (unsigned char)((src_ip & 0x00FF0000) >> 16); + unsigned char slot = (src_ip & 0x00FF0000) >> 16; pr_debug("ACCOUNT: Calculated SRC 16 bit network slot: %d\n", slot); /* Do we need to create a new mask_24 bucket? */ @@ -355,13 +355,13 @@ static void ipt_acc_depth1_insert(struct ipt_acc_mask_16 *mask_16, return; } - ipt_acc_depth0_insert((struct ipt_acc_mask_24 *)mask_16->mask_24[slot], + ipt_acc_depth0_insert(mask_16->mask_24[slot], net_ip, netmask, src_ip, 0, size, itemcount); } /* Do we need to process dst IP? */ if ((net_ip & netmask) == (dst_ip & netmask)) { - unsigned char slot = (unsigned char)((dst_ip & 0x00FF0000) >> 16); + unsigned char slot = (dst_ip & 0x00FF0000) >> 16; pr_debug("ACCOUNT: Calculated DST 16 bit network slot: %d\n", slot); /* Do we need to create a new mask_24 bucket? */ @@ -371,7 +371,7 @@ static void ipt_acc_depth1_insert(struct ipt_acc_mask_16 *mask_16, return; } - ipt_acc_depth0_insert((struct ipt_acc_mask_24 *)mask_16->mask_24[slot], + ipt_acc_depth0_insert(mask_16->mask_24[slot], net_ip, netmask, 0, dst_ip, size, itemcount); } } @@ -383,7 +383,7 @@ static void ipt_acc_depth2_insert(struct ipt_acc_mask_8 *mask_8, { /* Do we need to process src IP? */ if ((net_ip & netmask) == (src_ip & netmask)) { - unsigned char slot = (unsigned char)((src_ip & 0x0000FF00) >> 8); + unsigned char slot = (src_ip & 0x0000FF00) >> 8; pr_debug("ACCOUNT: Calculated SRC 24 bit network slot: %d\n", slot); /* Do we need to create a new mask_24 bucket? */ @@ -393,13 +393,13 @@ static void ipt_acc_depth2_insert(struct ipt_acc_mask_8 *mask_8, return; } - ipt_acc_depth1_insert((struct ipt_acc_mask_16 *)mask_8->mask_16[slot], + ipt_acc_depth1_insert(mask_8->mask_16[slot], net_ip, netmask, src_ip, 0, size, itemcount); } /* Do we need to process dst IP? */ if ((net_ip & netmask) == (dst_ip & netmask)) { - unsigned char slot = (unsigned char)((dst_ip & 0x0000FF00) >> 8); + unsigned char slot = (dst_ip & 0x0000FF00) >> 8; pr_debug("ACCOUNT: Calculated DST 24 bit network slot: %d\n", slot); /* Do we need to create a new mask_24 bucket? */ @@ -409,7 +409,7 @@ static void ipt_acc_depth2_insert(struct ipt_acc_mask_8 *mask_8, return; } - ipt_acc_depth1_insert((struct ipt_acc_mask_16 *)mask_8->mask_16[slot], + ipt_acc_depth1_insert(mask_8->mask_16[slot], net_ip, netmask, 0, dst_ip, size, itemcount); } } @@ -437,7 +437,7 @@ static unsigned int ipt_acc_target(struct sk_buff **pskb, const struct xt_target if (ipt_acc_tables[info->table_nr].depth == 0) { /* Count packet and check if the IP is new */ ipt_acc_depth0_insert( - (struct ipt_acc_mask_24 *)ipt_acc_tables[info->table_nr].data, + ipt_acc_tables[info->table_nr].data, ipt_acc_tables[info->table_nr].ip, ipt_acc_tables[info->table_nr].netmask, src_ip, dst_ip, size, &ipt_acc_tables[info->table_nr].itemcount); @@ -448,7 +448,7 @@ static unsigned int ipt_acc_target(struct sk_buff **pskb, const struct xt_target /* 16 bit network */ if (ipt_acc_tables[info->table_nr].depth == 1) { ipt_acc_depth1_insert( - (struct ipt_acc_mask_16 *)ipt_acc_tables[info->table_nr].data, + ipt_acc_tables[info->table_nr].data, ipt_acc_tables[info->table_nr].ip, ipt_acc_tables[info->table_nr].netmask, src_ip, dst_ip, size, &ipt_acc_tables[info->table_nr].itemcount); @@ -459,7 +459,7 @@ static unsigned int ipt_acc_target(struct sk_buff **pskb, const struct xt_target /* 24 bit network */ if (ipt_acc_tables[info->table_nr].depth == 2) { ipt_acc_depth2_insert( - (struct ipt_acc_mask_8 *)ipt_acc_tables[info->table_nr].data, + ipt_acc_tables[info->table_nr].data, ipt_acc_tables[info->table_nr].ip, ipt_acc_tables[info->table_nr].netmask, src_ip, dst_ip, size, &ipt_acc_tables[info->table_nr].itemcount); @@ -565,9 +565,8 @@ static int ipt_acc_handle_prepare_read(char *tablename, sizeof(struct ipt_acc_mask_24)); } else if (depth == 1) { struct ipt_acc_mask_16 *src_16 = - (struct ipt_acc_mask_16 *)ipt_acc_tables[table_nr].data; - struct ipt_acc_mask_16 *network_16 = - (struct ipt_acc_mask_16 *)dest->data; + ipt_acc_tables[table_nr].data; + struct ipt_acc_mask_16 *network_16 = dest->data; unsigned int b; for (b = 0; b <= 255; b++) { @@ -586,9 +585,8 @@ static int ipt_acc_handle_prepare_read(char *tablename, } } else if (depth == 2) { struct ipt_acc_mask_8 *src_8 = - (struct ipt_acc_mask_8 *)ipt_acc_tables[table_nr].data; - struct ipt_acc_mask_8 *network_8 = - (struct ipt_acc_mask_8 *)dest->data; + ipt_acc_tables[table_nr].data; + struct ipt_acc_mask_8 *network_8 = dest->data; struct ipt_acc_mask_16 *src_16, *network_16; unsigned int a, b; @@ -734,7 +732,7 @@ static int ipt_acc_handle_get_data(uint32_t handle, void *to_user) /* 8 bit network */ if (depth == 0) { struct ipt_acc_mask_24 *network = - (struct ipt_acc_mask_24*)ipt_acc_handles[handle].data; + ipt_acc_handles[handle].data; if (ipt_acc_handle_copy_data(to_user, &to_user_pos, &tmpbuf_pos, network, net_ip, 0)) return -1; @@ -750,12 +748,12 @@ static int ipt_acc_handle_get_data(uint32_t handle, void *to_user) /* 16 bit network */ if (depth == 1) { struct ipt_acc_mask_16 *network_16 = - (struct ipt_acc_mask_16*)ipt_acc_handles[handle].data; + ipt_acc_handles[handle].data; unsigned int b; for (b = 0; b <= 255; b++) { if (network_16->mask_24[b]) { struct ipt_acc_mask_24 *network = - (struct ipt_acc_mask_24*)network_16->mask_24[b]; + network_16->mask_24[b]; if (ipt_acc_handle_copy_data(to_user, &to_user_pos, &tmpbuf_pos, network, net_ip, (b << 16))) return -1; @@ -773,16 +771,16 @@ static int ipt_acc_handle_get_data(uint32_t handle, void *to_user) /* 24 bit network */ if (depth == 2) { struct ipt_acc_mask_8 *network_8 = - (struct ipt_acc_mask_8*)ipt_acc_handles[handle].data; + ipt_acc_handles[handle].data; unsigned int a, b; for (a = 0; a <= 255; a++) { if (network_8->mask_16[a]) { struct ipt_acc_mask_16 *network_16 = - (struct ipt_acc_mask_16*)network_8->mask_16[a]; + network_8->mask_16[a]; for (b = 0; b <= 255; b++) { if (network_16->mask_24[b]) { struct ipt_acc_mask_24 *network = - (struct ipt_acc_mask_24*)network_16->mask_24[b]; + network_16->mask_24[b]; if (ipt_acc_handle_copy_data(to_user, &to_user_pos, &tmpbuf_pos, network, net_ip, (a << 8) | (b << 16)))