mirror of
git://git.code.sf.net/p/xtables-addons/xtables-addons
synced 2025-09-08 05:34:58 +02:00
Merge branch 'ACCOUNT'
This commit is contained in:
@@ -21,6 +21,7 @@
|
|||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
#include <libxt_ACCOUNT_cl.h>
|
#include <libxt_ACCOUNT_cl.h>
|
||||||
|
|
||||||
bool exit_now;
|
bool exit_now;
|
||||||
@@ -33,15 +34,14 @@ static void sig_term(int signr)
|
|||||||
exit_now = true;
|
exit_now = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *addr_to_dotted(unsigned int);
|
static char *addr_to_dotted(unsigned int addr)
|
||||||
char *addr_to_dotted(unsigned int addr)
|
|
||||||
{
|
{
|
||||||
static char buf[17];
|
static char buf[16];
|
||||||
const unsigned char *bytep;
|
const unsigned char *bytep;
|
||||||
|
|
||||||
|
addr = ntohl(addr);
|
||||||
bytep = (const unsigned char *)&addr;
|
bytep = (const unsigned char *)&addr;
|
||||||
snprintf(buf, 16, "%u.%u.%u.%u", bytep[0], bytep[1], bytep[2], bytep[3]);
|
snprintf(buf, sizeof(buf), "%u.%u.%u.%u", bytep[3], bytep[2], bytep[1], bytep[0]);
|
||||||
buf[16] = 0;
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,7 +188,7 @@ int main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
printf("Read failed: %s\n", ctx.error_str);
|
printf("Read failed: %s\n", ctx.error_str);
|
||||||
ipt_ACCOUNT_deinit(&ctx);
|
ipt_ACCOUNT_deinit(&ctx);
|
||||||
exit(-1);
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!doCSV)
|
if (!doCSV)
|
||||||
@@ -219,5 +219,5 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
printf("Finished.\n");
|
printf("Finished.\n");
|
||||||
ipt_ACCOUNT_deinit(&ctx);
|
ipt_ACCOUNT_deinit(&ctx);
|
||||||
exit(0);
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
Author: Intra2net AG <opensource@intra2net.com>
|
Author: Intra2net AG <opensource@intra2net.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -13,9 +14,9 @@
|
|||||||
#include "xt_ACCOUNT.h"
|
#include "xt_ACCOUNT.h"
|
||||||
|
|
||||||
static struct option account_tg_opts[] = {
|
static struct option account_tg_opts[] = {
|
||||||
{ .name = "addr", .has_arg = 1, .flag = 0, .val = 'a' },
|
{.name = "addr", .has_arg = true, .val = 'a'},
|
||||||
{ .name = "tname", .has_arg = 1, .flag = 0, .val = 't' },
|
{.name = "tname", .has_arg = true, .val = 't'},
|
||||||
{ .name = 0 }
|
{NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Function which prints out usage message. */
|
/* Function which prints out usage message. */
|
||||||
@@ -105,7 +106,7 @@ static void account_tg_check(unsigned int flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void account_tg_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 xt_entry_target *target, bool do_prefix)
|
||||||
{
|
{
|
||||||
const struct ipt_acc_info *accountinfo
|
const struct ipt_acc_info *accountinfo
|
||||||
= (const struct ipt_acc_info *)target->data;
|
= (const struct ipt_acc_info *)target->data;
|
||||||
@@ -137,18 +138,19 @@ account_tg_print(const void *ip,
|
|||||||
const struct xt_entry_target *target,
|
const struct xt_entry_target *target,
|
||||||
int numeric)
|
int numeric)
|
||||||
{
|
{
|
||||||
account_tg_print_it(ip, target, 0);
|
account_tg_print_it(ip, target, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Saves the union ipt_targinfo in parsable form to stdout. */
|
/* Saves the union ipt_targinfo in parsable form to stdout. */
|
||||||
static void
|
static void
|
||||||
account_tg_save(const void *ip, const struct xt_entry_target *target)
|
account_tg_save(const void *ip, const struct xt_entry_target *target)
|
||||||
{
|
{
|
||||||
account_tg_print_it(ip, target, 1);
|
account_tg_print_it(ip, target, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct xtables_target account_tg_reg = {
|
static struct xtables_target account_tg_reg = {
|
||||||
.name = "ACCOUNT",
|
.name = "ACCOUNT",
|
||||||
|
.revision = 1,
|
||||||
.family = AF_INET,
|
.family = AF_INET,
|
||||||
.version = XTABLES_VERSION,
|
.version = XTABLES_VERSION,
|
||||||
.size = XT_ALIGN(sizeof(struct ipt_acc_info)),
|
.size = XT_ALIGN(sizeof(struct ipt_acc_info)),
|
||||||
|
@@ -42,6 +42,68 @@
|
|||||||
#error "ipt_ACCOUNT needs at least a PAGE_SIZE of 4096"
|
#error "ipt_ACCOUNT needs at least a PAGE_SIZE of 4096"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal table structure, generated by check_entry()
|
||||||
|
* @name: name of the table
|
||||||
|
* @ip: base IP address of the network
|
||||||
|
* @mask: netmask of the network
|
||||||
|
* @depth: size of network (0: 8-bit, 1: 16-bit, 2: 24-bit)
|
||||||
|
* @refcount: refcount of the table; if zero, destroy it
|
||||||
|
* @itemcount: number of IP addresses in this table
|
||||||
|
* @data; pointer to the actual data, depending on netmask
|
||||||
|
*/
|
||||||
|
struct ipt_acc_table {
|
||||||
|
char name[ACCOUNT_TABLE_NAME_LEN];
|
||||||
|
__be32 ip;
|
||||||
|
__be32 netmask;
|
||||||
|
uint8_t depth;
|
||||||
|
uint32_t refcount;
|
||||||
|
uint32_t itemcount;
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal handle structure
|
||||||
|
* @ip: base IP address of the network. Used for caculating the final
|
||||||
|
* address during get_data().
|
||||||
|
* @depth: size of the network; see above
|
||||||
|
* @itemcount: number of addresses in this table
|
||||||
|
*/
|
||||||
|
struct ipt_acc_handle {
|
||||||
|
uint32_t ip;
|
||||||
|
uint8_t depth;
|
||||||
|
uint32_t itemcount;
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The IP addresses 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];
|
||||||
|
};
|
||||||
|
|
||||||
static struct ipt_acc_table *ipt_acc_tables;
|
static struct ipt_acc_table *ipt_acc_tables;
|
||||||
static struct ipt_acc_handle *ipt_acc_handles;
|
static struct ipt_acc_handle *ipt_acc_handles;
|
||||||
static void *ipt_acc_tmpbuf;
|
static void *ipt_acc_tmpbuf;
|
||||||
@@ -65,7 +127,7 @@ static void *ipt_acc_zalloc_page(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Recursive free of all data structures */
|
/* Recursive free of all data structures */
|
||||||
static void ipt_acc_data_free(void *data, unsigned char depth)
|
static void ipt_acc_data_free(void *data, uint8_t depth)
|
||||||
{
|
{
|
||||||
/* Empty data set */
|
/* Empty data set */
|
||||||
if (!data)
|
if (!data)
|
||||||
@@ -117,7 +179,7 @@ static void ipt_acc_data_free(void *data, unsigned char depth)
|
|||||||
|
|
||||||
/* Look for existing table / insert new one.
|
/* Look for existing table / insert new one.
|
||||||
Return internal ID or -1 on error */
|
Return internal ID or -1 on error */
|
||||||
static int ipt_acc_table_insert(char *name, uint32_t ip, uint32_t netmask)
|
static int ipt_acc_table_insert(const char *name, __be32 ip, __be32 netmask)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
@@ -265,12 +327,14 @@ static void ipt_acc_destroy(const struct xt_tgdtor_param *par)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void ipt_acc_depth0_insert(struct ipt_acc_mask_24 *mask_24,
|
static void ipt_acc_depth0_insert(struct ipt_acc_mask_24 *mask_24,
|
||||||
uint32_t net_ip, uint32_t netmask,
|
__be32 net_ip, __be32 netmask,
|
||||||
uint32_t src_ip, uint32_t dst_ip,
|
__be32 src_ip, __be32 dst_ip,
|
||||||
uint32_t size, uint32_t *itemcount)
|
uint32_t size, uint32_t *itemcount)
|
||||||
{
|
{
|
||||||
unsigned char is_src = 0, is_dst = 0, src_slot, dst_slot;
|
uint8_t src_slot, dst_slot;
|
||||||
char is_src_new_ip = 0, is_dst_new_ip = 0; /* Check if this entry is new */
|
bool is_src = false, is_dst = false;
|
||||||
|
/* Check if this entry is new */
|
||||||
|
bool is_src_new_ip = false, is_dst_new_ip = false;
|
||||||
|
|
||||||
pr_debug("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),
|
"for net %u.%u.%u.%u/%u.%u.%u.%u, size: %u\n", NIPQUAD(src_ip),
|
||||||
@@ -278,12 +342,12 @@ static void ipt_acc_depth0_insert(struct ipt_acc_mask_24 *mask_24,
|
|||||||
|
|
||||||
/* Check if src/dst is inside our network. */
|
/* Check if src/dst is inside our network. */
|
||||||
/* Special: net_ip = 0.0.0.0/0 gets stored as src in slot 0 */
|
/* Special: net_ip = 0.0.0.0/0 gets stored as src in slot 0 */
|
||||||
if (!netmask)
|
if (netmask == 0)
|
||||||
src_ip = 0;
|
src_ip = 0;
|
||||||
if ((net_ip & netmask) == (src_ip & netmask))
|
if ((net_ip & netmask) == (src_ip & netmask))
|
||||||
is_src = 1;
|
is_src = true;
|
||||||
if ((net_ip & netmask) == (dst_ip & netmask) && netmask)
|
if ((net_ip & netmask) == (dst_ip & netmask) && netmask != 0)
|
||||||
is_dst = 1;
|
is_dst = true;
|
||||||
|
|
||||||
if (!is_src && !is_dst) {
|
if (!is_src && !is_dst) {
|
||||||
pr_debug("ACCOUNT: Skipping packet %u.%u.%u.%u/%u.%u.%u.%u "
|
pr_debug("ACCOUNT: Skipping packet %u.%u.%u.%u/%u.%u.%u.%u "
|
||||||
@@ -293,8 +357,8 @@ static void ipt_acc_depth0_insert(struct ipt_acc_mask_24 *mask_24,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate array positions */
|
/* Calculate array positions */
|
||||||
src_slot = (src_ip & 0xFF000000) >> 24;
|
src_slot = ntohl(src_ip) & 0xFF;
|
||||||
dst_slot = (dst_ip & 0xFF000000) >> 24;
|
dst_slot = ntohl(dst_ip) & 0xFF;
|
||||||
|
|
||||||
/* Increase size counters */
|
/* Increase size counters */
|
||||||
if (is_src) {
|
if (is_src) {
|
||||||
@@ -302,7 +366,7 @@ static void ipt_acc_depth0_insert(struct ipt_acc_mask_24 *mask_24,
|
|||||||
pr_debug("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
|
if (!mask_24->ip[src_slot].src_packets
|
||||||
&& !mask_24->ip[src_slot].dst_packets)
|
&& !mask_24->ip[src_slot].dst_packets)
|
||||||
is_src_new_ip = 1;
|
is_src_new_ip = true;
|
||||||
|
|
||||||
mask_24->ip[src_slot].src_packets++;
|
mask_24->ip[src_slot].src_packets++;
|
||||||
mask_24->ip[src_slot].src_bytes += size;
|
mask_24->ip[src_slot].src_bytes += size;
|
||||||
@@ -311,7 +375,7 @@ static void ipt_acc_depth0_insert(struct ipt_acc_mask_24 *mask_24,
|
|||||||
pr_debug("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
|
if (!mask_24->ip[dst_slot].src_packets
|
||||||
&& !mask_24->ip[dst_slot].dst_packets)
|
&& !mask_24->ip[dst_slot].dst_packets)
|
||||||
is_dst_new_ip = 1;
|
is_dst_new_ip = true;
|
||||||
|
|
||||||
mask_24->ip[dst_slot].dst_packets++;
|
mask_24->ip[dst_slot].dst_packets++;
|
||||||
mask_24->ip[dst_slot].dst_bytes += size;
|
mask_24->ip[dst_slot].dst_bytes += size;
|
||||||
@@ -323,29 +387,29 @@ static void ipt_acc_depth0_insert(struct ipt_acc_mask_24 *mask_24,
|
|||||||
if (is_src_new_ip || is_dst_new_ip) {
|
if (is_src_new_ip || is_dst_new_ip) {
|
||||||
pr_debug("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);
|
is_src_new_ip, is_dst_new_ip);
|
||||||
(*itemcount)++;
|
++*itemcount;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (is_src_new_ip) {
|
if (is_src_new_ip) {
|
||||||
pr_debug("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)++;
|
++*itemcount;
|
||||||
}
|
}
|
||||||
if (is_dst_new_ip) {
|
if (is_dst_new_ip) {
|
||||||
pr_debug("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)++;
|
++*itemcount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pr_debug("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,
|
static void ipt_acc_depth1_insert(struct ipt_acc_mask_16 *mask_16,
|
||||||
uint32_t net_ip, uint32_t netmask,
|
__be32 net_ip, __be32 netmask,
|
||||||
uint32_t src_ip, uint32_t dst_ip,
|
__be32 src_ip, __be32 dst_ip,
|
||||||
uint32_t size, uint32_t *itemcount)
|
uint32_t size, uint32_t *itemcount)
|
||||||
{
|
{
|
||||||
/* Do we need to process src IP? */
|
/* Do we need to process src IP? */
|
||||||
if ((net_ip & netmask) == (src_ip & netmask)) {
|
if ((net_ip & netmask) == (src_ip & netmask)) {
|
||||||
unsigned char slot = (src_ip & 0x00FF0000) >> 16;
|
uint8_t slot = (ntohl(src_ip) & 0xFF00) >> 8;
|
||||||
pr_debug("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? */
|
/* Do we need to create a new mask_24 bucket? */
|
||||||
@@ -361,7 +425,7 @@ static void ipt_acc_depth1_insert(struct ipt_acc_mask_16 *mask_16,
|
|||||||
|
|
||||||
/* Do we need to process dst IP? */
|
/* Do we need to process dst IP? */
|
||||||
if ((net_ip & netmask) == (dst_ip & netmask)) {
|
if ((net_ip & netmask) == (dst_ip & netmask)) {
|
||||||
unsigned char slot = (dst_ip & 0x00FF0000) >> 16;
|
uint8_t slot = (ntohl(dst_ip) & 0xFF00) >> 8;
|
||||||
pr_debug("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? */
|
/* Do we need to create a new mask_24 bucket? */
|
||||||
@@ -377,13 +441,13 @@ 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,
|
__be32 net_ip, __be32 netmask,
|
||||||
uint32_t src_ip, uint32_t dst_ip,
|
__be32 src_ip, __be32 dst_ip,
|
||||||
uint32_t size, uint32_t *itemcount)
|
uint32_t size, uint32_t *itemcount)
|
||||||
{
|
{
|
||||||
/* Do we need to process src IP? */
|
/* Do we need to process src IP? */
|
||||||
if ((net_ip & netmask) == (src_ip & netmask)) {
|
if ((net_ip & netmask) == (src_ip & netmask)) {
|
||||||
unsigned char slot = (src_ip & 0x0000FF00) >> 8;
|
uint8_t slot = (ntohl(src_ip) & 0xFF0000) >> 16;
|
||||||
pr_debug("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? */
|
/* Do we need to create a new mask_24 bucket? */
|
||||||
@@ -399,7 +463,7 @@ static void ipt_acc_depth2_insert(struct ipt_acc_mask_8 *mask_8,
|
|||||||
|
|
||||||
/* Do we need to process dst IP? */
|
/* Do we need to process dst IP? */
|
||||||
if ((net_ip & netmask) == (dst_ip & netmask)) {
|
if ((net_ip & netmask) == (dst_ip & netmask)) {
|
||||||
unsigned char slot = (dst_ip & 0x0000FF00) >> 8;
|
uint8_t slot = (ntohl(dst_ip) & 0xFF0000) >> 16;
|
||||||
pr_debug("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? */
|
/* Do we need to create a new mask_24 bucket? */
|
||||||
@@ -419,8 +483,8 @@ static unsigned int ipt_acc_target(struct sk_buff **pskb, const struct xt_target
|
|||||||
const struct ipt_acc_info *info =
|
const struct ipt_acc_info *info =
|
||||||
par->targinfo;
|
par->targinfo;
|
||||||
|
|
||||||
uint32_t src_ip = ip_hdr(*pskb)->saddr;
|
__be32 src_ip = ip_hdr(*pskb)->saddr;
|
||||||
uint32_t dst_ip = ip_hdr(*pskb)->daddr;
|
__be32 dst_ip = ip_hdr(*pskb)->daddr;
|
||||||
uint32_t size = ntohs(ip_hdr(*pskb)->tot_len);
|
uint32_t size = ntohs(ip_hdr(*pskb)->tot_len);
|
||||||
|
|
||||||
spin_lock_bh(&ipt_acc_lock);
|
spin_lock_bh(&ipt_acc_lock);
|
||||||
@@ -532,7 +596,7 @@ 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;
|
int table_nr = -1;
|
||||||
unsigned char depth;
|
uint8_t depth;
|
||||||
|
|
||||||
for (table_nr = 0; table_nr < ACCOUNT_MAX_TABLES; table_nr++)
|
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,
|
||||||
@@ -682,7 +746,7 @@ static int ipt_acc_handle_copy_data(void *to_user, unsigned long *to_user_pos,
|
|||||||
|
|
||||||
for (i = 0; i <= 255; i++) {
|
for (i = 0; i <= 255; i++) {
|
||||||
if (data->ip[i].src_packets || data->ip[i].dst_packets) {
|
if (data->ip[i].src_packets || data->ip[i].dst_packets) {
|
||||||
handle_ip.ip = net_ip | net_OR_mask | (i << 24);
|
handle_ip.ip = htonl(net_ip | net_OR_mask | i);
|
||||||
|
|
||||||
handle_ip.src_packets = data->ip[i].src_packets;
|
handle_ip.src_packets = data->ip[i].src_packets;
|
||||||
handle_ip.src_bytes = data->ip[i].src_bytes;
|
handle_ip.src_bytes = data->ip[i].src_bytes;
|
||||||
@@ -713,7 +777,7 @@ static int ipt_acc_handle_get_data(uint32_t handle, void *to_user)
|
|||||||
{
|
{
|
||||||
unsigned long to_user_pos = 0, tmpbuf_pos = 0;
|
unsigned long to_user_pos = 0, tmpbuf_pos = 0;
|
||||||
uint32_t net_ip;
|
uint32_t net_ip;
|
||||||
unsigned char depth;
|
uint8_t depth;
|
||||||
|
|
||||||
if (handle >= ACCOUNT_MAX_HANDLES) {
|
if (handle >= ACCOUNT_MAX_HANDLES) {
|
||||||
printk("ACCOUNT: invalid handle for ipt_acc_handle_get_data() "
|
printk("ACCOUNT: invalid handle for ipt_acc_handle_get_data() "
|
||||||
@@ -726,7 +790,7 @@ static int ipt_acc_handle_get_data(uint32_t handle, void *to_user)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
net_ip = ipt_acc_handles[handle].ip;
|
net_ip = ntohl(ipt_acc_handles[handle].ip);
|
||||||
depth = ipt_acc_handles[handle].depth;
|
depth = ipt_acc_handles[handle].depth;
|
||||||
|
|
||||||
/* 8 bit network */
|
/* 8 bit network */
|
||||||
@@ -755,7 +819,7 @@ static int ipt_acc_handle_get_data(uint32_t handle, void *to_user)
|
|||||||
struct ipt_acc_mask_24 *network =
|
struct ipt_acc_mask_24 *network =
|
||||||
network_16->mask_24[b];
|
network_16->mask_24[b];
|
||||||
if (ipt_acc_handle_copy_data(to_user, &to_user_pos,
|
if (ipt_acc_handle_copy_data(to_user, &to_user_pos,
|
||||||
&tmpbuf_pos, network, net_ip, (b << 16)))
|
&tmpbuf_pos, network, net_ip, (b << 8)))
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -783,7 +847,7 @@ static int ipt_acc_handle_get_data(uint32_t handle, void *to_user)
|
|||||||
network_16->mask_24[b];
|
network_16->mask_24[b];
|
||||||
if (ipt_acc_handle_copy_data(to_user,
|
if (ipt_acc_handle_copy_data(to_user,
|
||||||
&to_user_pos, &tmpbuf_pos,
|
&to_user_pos, &tmpbuf_pos,
|
||||||
network, net_ip, (a << 8) | (b << 16)))
|
network, net_ip, (a << 16) | (b << 8)))
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1017,6 +1081,7 @@ static int ipt_acc_get_ctl(struct sock *sk, int cmd, void *user, int *len)
|
|||||||
|
|
||||||
static struct xt_target xt_acc_reg __read_mostly = {
|
static struct xt_target xt_acc_reg __read_mostly = {
|
||||||
.name = "ACCOUNT",
|
.name = "ACCOUNT",
|
||||||
|
.revision = 1,
|
||||||
.family = AF_INET,
|
.family = AF_INET,
|
||||||
.target = ipt_acc_target,
|
.target = ipt_acc_target,
|
||||||
.targetsize = sizeof(struct ipt_acc_info),
|
.targetsize = sizeof(struct ipt_acc_info),
|
||||||
|
@@ -35,38 +35,12 @@
|
|||||||
|
|
||||||
/* Structure for the userspace part of ipt_ACCOUNT */
|
/* Structure for the userspace part of ipt_ACCOUNT */
|
||||||
struct ipt_acc_info {
|
struct ipt_acc_info {
|
||||||
uint32_t net_ip;
|
__be32 net_ip;
|
||||||
uint32_t net_mask;
|
__be32 net_mask;
|
||||||
char table_name[ACCOUNT_TABLE_NAME_LEN];
|
char table_name[ACCOUNT_TABLE_NAME_LEN];
|
||||||
int32_t table_nr;
|
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 */
|
/* Handle structure for communication with the userspace library */
|
||||||
struct ipt_acc_handle_sockopt {
|
struct ipt_acc_handle_sockopt {
|
||||||
uint32_t handle_nr; /* Used for HANDLE_FREE */
|
uint32_t handle_nr; /* Used for HANDLE_FREE */
|
||||||
@@ -76,43 +50,15 @@ struct ipt_acc_handle_sockopt {
|
|||||||
HANDLE_READ_FLUSH */
|
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
|
Used for every IP when returning data
|
||||||
*/
|
*/
|
||||||
struct ipt_acc_handle_ip {
|
struct ipt_acc_handle_ip {
|
||||||
uint32_t ip;
|
__be32 ip;
|
||||||
uint32_t src_packets;
|
uint32_t src_packets;
|
||||||
uint32_t src_bytes;
|
uint32_t src_bytes;
|
||||||
uint32_t dst_packets;
|
uint32_t dst_packets;
|
||||||
uint32_t dst_bytes;
|
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 */
|
#endif /* _IPT_ACCOUNT_H */
|
||||||
|
Reference in New Issue
Block a user