diff --git a/extensions/ACCOUNT/iptaccount.c b/extensions/ACCOUNT/iptaccount.c index 2d4556f..43045f3 100644 --- a/extensions/ACCOUNT/iptaccount.c +++ b/extensions/ACCOUNT/iptaccount.c @@ -21,6 +21,7 @@ #include #include +#include #include bool exit_now; @@ -33,15 +34,14 @@ static void sig_term(int signr) exit_now = true; } -char *addr_to_dotted(unsigned int); -char *addr_to_dotted(unsigned int addr) +static char *addr_to_dotted(unsigned int addr) { - static char buf[17]; + static char buf[16]; const unsigned char *bytep; + addr = ntohl(addr); bytep = (const unsigned char *)&addr; - snprintf(buf, 16, "%u.%u.%u.%u", bytep[0], bytep[1], bytep[2], bytep[3]); - buf[16] = 0; + snprintf(buf, sizeof(buf), "%u.%u.%u.%u", bytep[3], bytep[2], bytep[1], bytep[0]); return buf; } @@ -188,7 +188,7 @@ int main(int argc, char *argv[]) { printf("Read failed: %s\n", ctx.error_str); ipt_ACCOUNT_deinit(&ctx); - exit(-1); + return EXIT_FAILURE; } if (!doCSV) @@ -219,5 +219,5 @@ int main(int argc, char *argv[]) printf("Finished.\n"); ipt_ACCOUNT_deinit(&ctx); - exit(0); + return EXIT_SUCCESS; } diff --git a/extensions/ACCOUNT/libxt_ACCOUNT.c b/extensions/ACCOUNT/libxt_ACCOUNT.c index 00b2fb6..2f15103 100644 --- a/extensions/ACCOUNT/libxt_ACCOUNT.c +++ b/extensions/ACCOUNT/libxt_ACCOUNT.c @@ -2,6 +2,7 @@ Author: Intra2net AG */ +#include #include #include #include @@ -13,9 +14,9 @@ #include "xt_ACCOUNT.h" 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 } + {.name = "addr", .has_arg = true, .val = 'a'}, + {.name = "tname", .has_arg = true, .val = 't'}, + {NULL}, }; /* 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, - 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 *)target->data; @@ -137,18 +138,19 @@ account_tg_print(const void *ip, const struct xt_entry_target *target, 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. */ static void 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 = { .name = "ACCOUNT", + .revision = 1, .family = AF_INET, .version = XTABLES_VERSION, .size = XT_ALIGN(sizeof(struct ipt_acc_info)), diff --git a/extensions/ACCOUNT/xt_ACCOUNT.c b/extensions/ACCOUNT/xt_ACCOUNT.c index 34e16b1..4616573 100644 --- a/extensions/ACCOUNT/xt_ACCOUNT.c +++ b/extensions/ACCOUNT/xt_ACCOUNT.c @@ -42,6 +42,68 @@ #error "ipt_ACCOUNT needs at least a PAGE_SIZE of 4096" #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_handle *ipt_acc_handles; static void *ipt_acc_tmpbuf; @@ -65,7 +127,7 @@ static void *ipt_acc_zalloc_page(void) } /* 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 */ if (!data) @@ -117,7 +179,7 @@ static void ipt_acc_data_free(void *data, unsigned char depth) /* 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) +static int ipt_acc_table_insert(const char *name, __be32 ip, __be32 netmask) { 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, - uint32_t net_ip, uint32_t netmask, - uint32_t src_ip, uint32_t dst_ip, + __be32 net_ip, __be32 netmask, + __be32 src_ip, __be32 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 */ + uint8_t src_slot, dst_slot; + 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 " "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. */ /* Special: net_ip = 0.0.0.0/0 gets stored as src in slot 0 */ - if (!netmask) + if (netmask == 0) src_ip = 0; if ((net_ip & netmask) == (src_ip & netmask)) - is_src = 1; - if ((net_ip & netmask) == (dst_ip & netmask) && netmask) - is_dst = 1; + is_src = true; + if ((net_ip & netmask) == (dst_ip & netmask) && netmask != 0) + is_dst = true; if (!is_src && !is_dst) { 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 */ - src_slot = (src_ip & 0xFF000000) >> 24; - dst_slot = (dst_ip & 0xFF000000) >> 24; + src_slot = ntohl(src_ip) & 0xFF; + dst_slot = ntohl(dst_ip) & 0xFF; /* Increase size counters */ 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); if (!mask_24->ip[src_slot].src_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_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); if (!mask_24->ip[dst_slot].src_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_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) { pr_debug("ACCOUNT: src_slot == dst_slot: %d, %d\n", is_src_new_ip, is_dst_new_ip); - (*itemcount)++; + ++*itemcount; } } else { if (is_src_new_ip) { pr_debug("ACCOUNT: New src_ip: %u.%u.%u.%u\n", NIPQUAD(src_ip)); - (*itemcount)++; + ++*itemcount; } if (is_dst_new_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); } 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, + __be32 net_ip, __be32 netmask, + __be32 src_ip, __be32 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 = (src_ip & 0x00FF0000) >> 16; + uint8_t slot = (ntohl(src_ip) & 0xFF00) >> 8; pr_debug("ACCOUNT: Calculated SRC 16 bit network slot: %d\n", slot); /* 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? */ 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); /* 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, - uint32_t net_ip, uint32_t netmask, - uint32_t src_ip, uint32_t dst_ip, + __be32 net_ip, __be32 netmask, + __be32 src_ip, __be32 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 = (src_ip & 0x0000FF00) >> 8; + uint8_t slot = (ntohl(src_ip) & 0xFF0000) >> 16; pr_debug("ACCOUNT: Calculated SRC 24 bit network slot: %d\n", slot); /* 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? */ 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); /* 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 = par->targinfo; - uint32_t src_ip = ip_hdr(*pskb)->saddr; - uint32_t dst_ip = ip_hdr(*pskb)->daddr; + __be32 src_ip = ip_hdr(*pskb)->saddr; + __be32 dst_ip = ip_hdr(*pskb)->daddr; uint32_t size = ntohs(ip_hdr(*pskb)->tot_len); 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) { int table_nr = -1; - unsigned char depth; + uint8_t depth; for (table_nr = 0; table_nr < ACCOUNT_MAX_TABLES; table_nr++) 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++) { 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_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; uint32_t net_ip; - unsigned char depth; + uint8_t depth; if (handle >= ACCOUNT_MAX_HANDLES) { 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; } - net_ip = ipt_acc_handles[handle].ip; + net_ip = ntohl(ipt_acc_handles[handle].ip); depth = ipt_acc_handles[handle].depth; /* 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 = network_16->mask_24[b]; 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; } } @@ -783,7 +847,7 @@ static int ipt_acc_handle_get_data(uint32_t handle, void *to_user) 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))) + network, net_ip, (a << 16) | (b << 8))) 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 = { .name = "ACCOUNT", + .revision = 1, .family = AF_INET, .target = ipt_acc_target, .targetsize = sizeof(struct ipt_acc_info), diff --git a/extensions/ACCOUNT/xt_ACCOUNT.h b/extensions/ACCOUNT/xt_ACCOUNT.h index 65ff4ab..1c7e96c 100644 --- a/extensions/ACCOUNT/xt_ACCOUNT.h +++ b/extensions/ACCOUNT/xt_ACCOUNT.h @@ -35,38 +35,12 @@ /* Structure for the userspace part of ipt_ACCOUNT */ struct ipt_acc_info { - uint32_t net_ip; - uint32_t net_mask; + __be32 net_ip; + __be32 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 */ @@ -76,43 +50,15 @@ struct ipt_acc_handle_sockopt { 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; + __be32 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 */