/* Recursive free of all data structures */
-void ipt_account_data_free(void *data, unsigned char depth) {
+void ipt_account_data_free(void *data, unsigned char depth)
+{
/* Empty data set */
if (!data)
return;
}
/* Free for 24 bit network */
- if (depth == 3) {
+ if (depth == 2) {
unsigned int a, b;
for (a=0; a <= 255; a++) {
if (((struct ipt_account_mask_8 *)data)->mask_16[a]) {
- struct ipt_account_mask_16 *mask_16 = (struct ipt_account_mask_16*)((struct ipt_account_mask_8 *)data)->mask_16[a];
+ struct ipt_account_mask_16 *mask_16 = (struct ipt_account_mask_16*)
+ ((struct ipt_account_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]);
}
/* Look for existing table / insert new one. Return internal ID or -1 on error */
-int ipt_account_table_insert(char *name, unsigned int ip, unsigned int netmask) {
+int ipt_account_table_insert(char *name, unsigned int ip, unsigned int netmask)
+{
unsigned int i;
- DEBUGP("ACCOUNT: ipt_account_table_insert: %s, %u.%u.%u.%u/%u.%u.%u.%u\n", name, NIPQUAD(ip), NIPQUAD(netmask));
+ DEBUGP("ACCOUNT: ipt_account_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++) {
NIPQUAD(ipt_account_tables[i].ip), NIPQUAD(ipt_account_tables[i].netmask));
if (ipt_account_tables[i].ip != ip || ipt_account_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",
+ printk("ACCOUNT: Table %s found, but IP/netmask mismatch. IP/netmask found: %u.%u.%u.%u/%u.%u.%u.%u\n",
name, NIPQUAD(ipt_account_tables[i].ip), NIPQUAD(ipt_account_tables[i].netmask));
return -1;
}
else if(netsize >= 8)
ipt_account_tables[i].depth = 2;
- printk("ACCOUNT: calculated netsize: %u -> ipt_account_table depth %u\n", netsize, ipt_account_tables[i].depth);
+ DEBUGP("ACCOUNT: calculated netsize: %u -> ipt_account_table depth %u\n",
+ netsize, ipt_account_tables[i].depth);
ipt_account_tables[i].refcount++;
if ((ipt_account_tables[i].data = (void *)get_zeroed_page(GFP_ATOMIC)) == NULL) {
const struct ipt_entry *e,
void *targinfo,
unsigned int targinfosize,
- unsigned int hook_mask) {
+ unsigned int hook_mask)
+{
struct ipt_account_info *info = targinfo;
if (targinfosize != IPT_ALIGN(sizeof(struct ipt_account_info))) {
return 1;
}
-void ipt_account_deleteentry(void *targinfo, unsigned int targinfosize) {
+void ipt_account_deleteentry(void *targinfo, unsigned int targinfosize)
+{
unsigned int i;
struct ipt_account_info *info = targinfo;
spin_unlock_bh(&ipt_account_lock);
}
-void ipt_account_depth0_insert(struct ipt_account_mask_24 *mask_24, unsigned int net_ip, unsigned int netmask,
- unsigned int src_ip, unsigned int dst_ip, unsigned int size, unsigned int *itemcount) {
+void ipt_account_depth0_insert(struct ipt_account_mask_24 *mask_24,
+ unsigned int net_ip, unsigned int netmask,
+ unsigned int src_ip, unsigned int dst_ip,
+ unsigned int size, unsigned int *itemcount)
+{
unsigned char is_src = 0, is_dst = 0;
DEBUGP("ACCOUNT: ipt_account_depth0_insert: %u.%u.%u.%u/%u.%u.%u.%u for net %u.%u.%u.%u/%u.%u.%u.%u, size: %u\n",
DEBUGP("ACCOUNT: Itemcounter after: %d\n", *itemcount);
}
-void ipt_account_depth1_insert(struct ipt_account_mask_16 *mask_16, unsigned int net_ip, unsigned int netmask,
- unsigned int src_ip, unsigned int dst_ip, unsigned int size, unsigned int *itemcount) {
+void ipt_account_depth1_insert(struct ipt_account_mask_16 *mask_16, unsigned int net_ip,
+ unsigned int netmask, unsigned int src_ip, unsigned int dst_ip,
+ unsigned int size, unsigned int *itemcount)
+{
/* Do we need to process src IP? */
if ((net_ip&netmask) == (src_ip&netmask)) {
unsigned char slot = (unsigned char)((src_ip&0x00FF0000) >> 16);
}
}
-void ipt_account_depth2_insert(struct ipt_account_mask_8 *mask_8, unsigned int net_ip, unsigned int netmask,
- unsigned int src_ip, unsigned int dst_ip, unsigned int size, unsigned int *itemcount) {
+void ipt_account_depth2_insert(struct ipt_account_mask_8 *mask_8, unsigned int net_ip,
+ unsigned int netmask, unsigned int src_ip, unsigned int dst_ip,
+ unsigned int size, unsigned int *itemcount)
+{
/* Do we need to process src IP? */
if ((net_ip&netmask) == (src_ip&netmask)) {
unsigned char slot = (unsigned char)((src_ip&0x0000FF00) >> 8);
const struct net_device *in,
const struct net_device *out,
const void *targinfo,
- void *userinfo) {
+ void *userinfo)
+{
const struct ipt_account_info *info = (const struct ipt_account_info *)targinfo;
unsigned int src_ip = (*pskb)->nh.iph->saddr;
unsigned int dst_ip = (*pskb)->nh.iph->daddr;
but there could be two or more applications accessing the data
at the same time.
*/
-int ipt_account_handle_find_slot(void) {
+int ipt_account_handle_find_slot(void)
+{
unsigned int i;
/* Insert new table */
for (i = 0; i < ACCOUNT_MAX_HANDLES; i++) {
return -1;
}
-int ipt_account_handle_free(unsigned int handle) {
+int ipt_account_handle_free(unsigned int handle)
+{
if (handle >= ACCOUNT_MAX_HANDLES) {
printk("ACCOUNT: Invalid handle for ipt_account_handle_free() specified: %u\n", handle);
return -EINVAL;
/* Prepare data for read without flush. Use only for debugging!
Real applications should use read&flush as it's way more efficent */
-int ipt_account_handle_prepare_read(char *tablename, unsigned int *count) {
+int ipt_account_handle_prepare_read(char *tablename, unsigned int *count)
+{
int handle, i, table_nr=-1;
for (i = 0; i < ACCOUNT_MAX_TABLES; i++)
}
/* Prepare data for read and flush it */
-int ipt_account_handle_prepare_read_flush(char *tablename, unsigned int *count) {
+int ipt_account_handle_prepare_read_flush(char *tablename, unsigned int *count)
+{
int handle, i, table_nr=-1;
for (i = 0; i < ACCOUNT_MAX_TABLES; i++)
return handle;
}
-/* Copy the actual that into a prepared buffer.
+/* Copy 8 bit network data into a prepared buffer.
We only copy entries != 0 to increase performance.
- The memory gets freed again in ipt_account_handle_free().
*/
-int ipt_account_handle_get_data(unsigned int handle, void *buffer) {
+void ipt_account_handle_copy_data(void *to_user, int *pos, struct ipt_account_mask_24 *data,
+ unsigned int net_ip, unsigned int net_OR_mask)
+{
struct ipt_account_handle_ip handle_ip;
unsigned int handle_ip_size = sizeof (struct ipt_account_handle_ip);
- unsigned int i, tmpbuf_pos=0;
+
+ 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 (*pos+handle_ip_size >= PAGE_SIZE) {
+ copy_to_user(to_user, ipt_account_tmpbuf, *pos);
+ *pos = 0;
+ }
+ memcpy(ipt_account_tmpbuf+*pos, &handle_ip, handle_ip_size);
+ *pos += handle_ip_size;
+ }
+ }
+}
+
+/* Copy the data from our internal structure
+ We only copy entries != 0 to increase performance.
+ Overwrites ipt_account_tmpbuf.
+*/
+int ipt_account_handle_get_data(unsigned int handle, void *to_user)
+{
+ unsigned int tmpbuf_pos=0;
if (handle >= ACCOUNT_MAX_HANDLES) {
printk("ACCOUNT: invalid handle for ipt_account_handle_get_data() specified: %u\n", handle);
/* 8 bit network */
if (depth == 0) {
struct ipt_account_mask_24 *network = (struct ipt_account_mask_24*)ipt_account_handles[handle].data;
- for (i = 0; i <= 255; i++) {
- if (network->ip[i].src_packets || network->ip[i].dst_packets) {
- handle_ip.ip = net_ip | (i<<24);
- handle_ip.src_packets = network->ip[i].src_packets;
- handle_ip.src_bytes = network->ip[i].src_bytes;
- handle_ip.dst_packets = network->ip[i].dst_packets;
- handle_ip.dst_bytes = network->ip[i].dst_bytes;
-
- /* Temporary buffer full? Flush to userspace */
- if (tmpbuf_pos+handle_ip_size >= PAGE_SIZE) {
- copy_to_user(buffer, ipt_account_tmpbuf, tmpbuf_pos);
- tmpbuf_pos = 0;
- }
- memcpy(ipt_account_tmpbuf+tmpbuf_pos, &handle_ip, handle_ip_size);
- tmpbuf_pos += handle_ip_size;
- }
- }
-
+ ipt_account_handle_copy_data(to_user, &tmpbuf_pos, network, net_ip, 0);
+
/* Flush remaining data to userspace */
if (tmpbuf_pos)
- copy_to_user(buffer, ipt_account_tmpbuf, tmpbuf_pos);
+ copy_to_user(to_user, ipt_account_tmpbuf, tmpbuf_pos);
return 0;
}
for (b = 0; b <= 255; b++) {
if (network_16->mask_24[b]) {
struct ipt_account_mask_24 *network = (struct ipt_account_mask_24*)network_16->mask_24[b];
- for (i = 0; i <= 255; i++) {
- if (network->ip[i].src_packets || network->ip[i].dst_packets) {
- handle_ip.ip = net_ip | (b << 16) | (i<<24);
- handle_ip.src_packets = network->ip[i].src_packets;
- handle_ip.src_bytes = network->ip[i].src_bytes;
- handle_ip.dst_packets = network->ip[i].dst_packets;
- handle_ip.dst_bytes = network->ip[i].dst_bytes;
-
- /* Temporary buffer full? Flush to userspace */
- if (tmpbuf_pos+handle_ip_size >= PAGE_SIZE) {
- copy_to_user(buffer, ipt_account_tmpbuf, tmpbuf_pos);
- tmpbuf_pos = 0;
- }
- memcpy(ipt_account_tmpbuf+tmpbuf_pos, &handle_ip, handle_ip_size);
- tmpbuf_pos += handle_ip_size;
- }
- }
+ ipt_account_handle_copy_data(to_user, &tmpbuf_pos, network, net_ip, (b << 16));
}
}
/* Flush remaining data to userspace */
if (tmpbuf_pos)
- copy_to_user(buffer, ipt_account_tmpbuf, tmpbuf_pos);
+ copy_to_user(to_user, ipt_account_tmpbuf, tmpbuf_pos);
return 0;
}
for (b = 0; b <= 255; b++) {
if (network_16->mask_24[b]) {
struct ipt_account_mask_24 *network = (struct ipt_account_mask_24*)network_16->mask_24[b];
- for (i = 0; i <= 255; i++) {
- if (network->ip[i].src_packets || network->ip[i].dst_packets) {
- handle_ip.ip = net_ip | (a << 8) | (b << 16) | (i<<24);
- handle_ip.src_packets = network->ip[i].src_packets;
- handle_ip.src_bytes = network->ip[i].src_bytes;
- handle_ip.dst_packets = network->ip[i].dst_packets;
- handle_ip.dst_bytes = network->ip[i].dst_bytes;
-
- /* Temporary buffer full? Flush to userspace */
- if (tmpbuf_pos+handle_ip_size >= PAGE_SIZE) {
- copy_to_user(buffer, ipt_account_tmpbuf, tmpbuf_pos);
- tmpbuf_pos = 0;
- }
- memcpy(ipt_account_tmpbuf+tmpbuf_pos, &handle_ip, handle_ip_size);
- tmpbuf_pos += handle_ip_size;
- }
- }
+ ipt_account_handle_copy_data(to_user, &tmpbuf_pos, network, net_ip, (a << 8) | (b << 16));
}
}
}
/* Flush remaining data to userspace */
if (tmpbuf_pos)
- copy_to_user(buffer, ipt_account_tmpbuf, tmpbuf_pos);
+ copy_to_user(to_user, ipt_account_tmpbuf, tmpbuf_pos);
return 0;
}
-
+
return -1;
}
-static int ipt_account_set_ctl(struct sock *sk, int cmd, void *user, unsigned int len) {
+static int ipt_account_set_ctl(struct sock *sk, int cmd, void *user, unsigned int len)
+{
struct ipt_account_handle_sockopt handle;
int ret = -EINVAL;
return ret;
}
-static int ipt_account_get_ctl(struct sock *sk, int cmd, void *user, int *len) {
+static int ipt_account_get_ctl(struct sock *sk, int cmd, void *user, int *len)
+{
struct ipt_account_handle_sockopt handle;
int ret = -EINVAL;
}
if (copy_from_user (&handle, user, sizeof(struct ipt_account_handle_sockopt))) {
- printk("ACCOUNT: ipt_account_get_ctl: copy_from_user failed for IPT_SO_GET_ACCOUNT_PREPARE_READ/READ_FLUSH\n");
+ return -EFAULT;
break;
}
spin_unlock_bh(&ipt_account_lock);
if (handle.handle_nr == -1) {
- printk("ACCOUNT: ipt_account_get_ctl: ipt_account_handle_prepare_read failed\n");
+ return -EINVAL;
break;
}
if (copy_to_user(user, &handle, sizeof(struct ipt_account_handle_sockopt))) {
- printk("ACCOUNT: ipt_account_set_ctl: copy_to_user failed for IPT_SO_GET_ACCOUNT_PREPARE_READ/READ_FLUSH\n");
+ return -EFAULT;
break;
}
ret = 0;
}
if (copy_from_user (&handle, user, sizeof(struct ipt_account_handle_sockopt))) {
- printk("ACCOUNT: ipt_account_get_ctl: copy_from_user failed for IPT_SO_GET_ACCOUNT_PREPARE_READ/READ_FLUSH\n");
+ return -EFAULT;
break;
}
if (handle.handle_nr >= ACCOUNT_MAX_HANDLES) {
- printk("ACCOUNT: Invalid handle for IPT_SO_GET_ACCOUNT_GET_DATA: %u\n", handle.handle_nr);
+ return -EINVAL;
break;
}
spin_unlock_bh(&ipt_account_userspace_lock);
if (copy_to_user(user, &handle, sizeof(struct ipt_account_handle_sockopt))) {
- printk("ACCOUNT: ipt_account_set_ctl: copy_to_user failed for IPT_SO_GET_ACCOUNT_GET_HANDLE_USAGE\n");
+ return -EFAULT;
break;
}
ret = 0;
IPT_SO_GET_ACCOUNT_PREPARE_READ, IPT_SO_GET_ACCOUNT_MAX+1, ipt_account_get_ctl, 0, NULL
};
-static int __init init(void) {
+static int __init init(void)
+{
if ((ipt_account_tables = kmalloc(ACCOUNT_MAX_TABLES*sizeof(struct ipt_account_table), GFP_KERNEL)) == NULL) {
printk("ACCOUNT: Out of memory allocating account_tables structure");
return -EINVAL;
return 0;
}
-static void __exit fini(void) {
+static void __exit fini(void)
+{
ipt_unregister_target(&ipt_account_reg);
nf_unregister_sockopt(&ipt_account_sockopts);