mirror of
git://git.code.sf.net/p/dhcpd-pools/code
synced 2025-12-16 07:47:00 +00:00
IPv6: add DHCPv6 support
The DHCP version is determined according to the first IP address that appears in the configuration file. Caveat; counters are of native long type. Since IPv6 address space has 2^128 addresses, they are subject to overflow. [Sami Kerola: This commit also fixed a percent sorting bug, which has been broken always. See changes ret_percent() for the fix.] CC: LI Zimu <lzm@cernet.edu.cn> CC: Xing Li <xing@cernet.edu.cn> Reviewed-by: Sami Kerola <kerolasa@iki.fi> Signed-off-by: Cheer Xiao <xiaqqaix@gmail.com>
This commit is contained in:
parent
71bcee14e9
commit
a57d399643
8 changed files with 267 additions and 119 deletions
|
|
@ -42,20 +42,10 @@
|
|||
#include "dhcpd-pools.h"
|
||||
|
||||
/* Clean up data */
|
||||
static int ip_sort(const struct leases_t *restrict a,
|
||||
const struct leases_t *restrict b)
|
||||
{
|
||||
if (a->ip < b->ip)
|
||||
return -1;
|
||||
if (a->ip > b->ip)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int prepare_data(void)
|
||||
{
|
||||
/* Sort leases */
|
||||
HASH_SORT(leases, ip_sort);
|
||||
HASH_SORT(leases, leasecomp);
|
||||
/* Sort ranges */
|
||||
qsort(ranges, (size_t)num_ranges, sizeof(struct range_t), &rangecomp);
|
||||
return 0;
|
||||
|
|
@ -68,20 +58,18 @@ int do_counting(void)
|
|||
const struct leases_t *restrict l = leases;
|
||||
unsigned long i, k, block_size;
|
||||
|
||||
unsigned long r_end;
|
||||
range_p = ranges;
|
||||
|
||||
/* Walk through ranges */
|
||||
for (i = 0; i < num_ranges; i++) {
|
||||
for (; l != NULL && range_p->first_ip < l->ip; l = l->hh.prev)
|
||||
for (; l != NULL && ipcomp(&range_p->first_ip, &l->ip) < 0;
|
||||
l = l->hh.prev)
|
||||
/* rewind */ ;
|
||||
if (l == NULL)
|
||||
l = leases;
|
||||
/* last_ip + 1 make comparison to small bit quicker as it results to
|
||||
* be 'smaller than' not 'smaller or equal to' */
|
||||
r_end = range_p->last_ip + 1;
|
||||
for (; l != NULL && l->ip < r_end; l = l->hh.next) {
|
||||
if (l->ip < range_p->first_ip) {
|
||||
for (; l != NULL && ipcomp(&l->ip, &range_p->last_ip) <= 0;
|
||||
l = l->hh.next) {
|
||||
if (ipcomp(&l->ip, &range_p->first_ip) < 0) {
|
||||
/* should not be necessary */
|
||||
continue;
|
||||
}
|
||||
|
|
@ -114,8 +102,7 @@ int do_counting(void)
|
|||
}
|
||||
|
||||
/* Size of range, shared net & all networks */
|
||||
block_size =
|
||||
(unsigned int)(range_p->last_ip - range_p->first_ip + 1);
|
||||
block_size = get_range_size(range_p);
|
||||
if (range_p->shared_net) {
|
||||
range_p->shared_net->available += block_size;
|
||||
}
|
||||
|
|
@ -131,8 +118,7 @@ int do_counting(void)
|
|||
shared_networks->touched = 0;
|
||||
range_p = ranges;
|
||||
for (k = 0; k < num_ranges; k++) {
|
||||
shared_networks->available +=
|
||||
range_p->last_ip - range_p->first_ip + 1;
|
||||
shared_networks->available += get_range_size(range_p);
|
||||
shared_networks->used += range_p->count;
|
||||
shared_networks->touched += range_p->touched;
|
||||
shared_networks->backups += range_p->backups;
|
||||
|
|
|
|||
|
|
@ -239,6 +239,14 @@ int main(int argc, char **argv)
|
|||
/* Global allocations, counter resets etc */
|
||||
int prepare_memory(void)
|
||||
{
|
||||
/* Fill in prefix length cache */
|
||||
int i, j;
|
||||
for (i = 0; i < 2; i++) {
|
||||
for (j = 0; j < NUM_OF_PREFIX; j++) {
|
||||
prefix_length[i][j] = strlen(prefixes[i][j]);
|
||||
}
|
||||
}
|
||||
dhcp_version = VERSION_UNKNOWN;
|
||||
RANGES = 64;
|
||||
num_ranges = num_shared_networks = 0;
|
||||
shared_networks =
|
||||
|
|
|
|||
|
|
@ -52,7 +52,26 @@
|
|||
# endif
|
||||
|
||||
/* Structures and unions */
|
||||
union ipaddr_t {
|
||||
uint32_t v4;
|
||||
unsigned char v6[16];
|
||||
};
|
||||
enum dhcp_version {
|
||||
VERSION_4,
|
||||
VERSION_6,
|
||||
VERSION_UNKNOWN,
|
||||
};
|
||||
enum prefix_t {
|
||||
PREFIX_LEASE,
|
||||
PREFIX_BINDING_STATE_FREE,
|
||||
PREFIX_BINDING_STATE_ACTIVE,
|
||||
PREFIX_BINDING_STATE_BACKUP,
|
||||
PREFIX_HARDWARE_ETHERNET,
|
||||
NUM_OF_PREFIX
|
||||
};
|
||||
|
||||
struct configuration_t {
|
||||
char dhcpv6;
|
||||
char *dhcpdconf_file;
|
||||
char *dhcpdlease_file;
|
||||
char output_format[2];
|
||||
|
|
@ -72,8 +91,8 @@ struct shared_network_t {
|
|||
};
|
||||
struct range_t {
|
||||
struct shared_network_t *shared_net;
|
||||
uint32_t first_ip;
|
||||
uint32_t last_ip;
|
||||
union ipaddr_t first_ip;
|
||||
union ipaddr_t last_ip;
|
||||
unsigned long int count;
|
||||
unsigned long int touched;
|
||||
unsigned long int backups;
|
||||
|
|
@ -89,13 +108,16 @@ enum ltype {
|
|||
BACKUP
|
||||
};
|
||||
struct leases_t {
|
||||
uint32_t ip; /* ip as key */
|
||||
union ipaddr_t ip; /* ip as key */
|
||||
enum ltype type;
|
||||
UT_hash_handle hh;
|
||||
};
|
||||
|
||||
/* Global variables */
|
||||
const char *prefixes[2][NUM_OF_PREFIX];
|
||||
int prefix_length[2][NUM_OF_PREFIX];
|
||||
struct configuration_t config;
|
||||
enum dhcp_version dhcp_version;
|
||||
static int const output_limit_bit_1 = 1;
|
||||
static int const output_limit_bit_2 = 2;
|
||||
static int const output_limit_bit_3 = 4;
|
||||
|
|
@ -128,6 +150,11 @@ void flip_ranges(struct range_t *__restrict ranges,
|
|||
struct range_t *__restrict tmp_ranges)
|
||||
__attribute__ ((nonnull(1, 2)));
|
||||
/* support functions */
|
||||
int parse_ipaddr(const char *restrict src, union ipaddr_t *restrict dst);
|
||||
void copy_ipaddr(union ipaddr_t *restrict dst,
|
||||
const union ipaddr_t *restrict src);
|
||||
const char *ntop_ipaddr(const union ipaddr_t *ip);
|
||||
unsigned long get_range_size(const struct range_t *r);
|
||||
int xstrstr(const char *__restrict a, const char *__restrict b, int len)
|
||||
__attribute__ ((nonnull(1, 2)))
|
||||
# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
|
||||
|
|
@ -142,6 +169,8 @@ void usage(int status) __attribute__ ((noreturn));
|
|||
/* ...for ranges and... */
|
||||
int intcomp(const void *__restrict x, const void *__restrict y)
|
||||
__attribute__ ((nonnull(1, 2)));
|
||||
int ipcomp(const union ipaddr_t *restrict a, const union ipaddr_t *restrict b);
|
||||
int leasecomp(const void *restrict a, const void *restrict b);
|
||||
int rangecomp(const void *__restrict r1, const void *__restrict r2)
|
||||
__attribute__ ((nonnull(1, 2)));
|
||||
/* sort function pointer and functions */
|
||||
|
|
@ -170,8 +199,8 @@ int output_alarming(void);
|
|||
/* Memory release, file closing etc */
|
||||
void clean_up(void);
|
||||
/* Hash functions */
|
||||
void add_lease(int ip, enum ltype type);
|
||||
struct leases_t *find_lease(int ip);
|
||||
void add_lease(union ipaddr_t *ip, enum ltype type);
|
||||
struct leases_t *find_lease(union ipaddr_t *ip);
|
||||
void delete_lease(struct leases_t *lease);
|
||||
void delete_all_leases();
|
||||
|
||||
|
|
|
|||
|
|
@ -53,13 +53,34 @@
|
|||
#include "dhcpd-pools.h"
|
||||
#include "xalloc.h"
|
||||
|
||||
/* The .indent.pro in use will mess formatting of array below. Please do
|
||||
* not commit less readable indentation. */
|
||||
const char *prefixes[2][NUM_OF_PREFIX] = {
|
||||
[VERSION_4] = {
|
||||
[PREFIX_LEASE] = "lease ",
|
||||
[PREFIX_BINDING_STATE_FREE] = " binding state free",
|
||||
[PREFIX_BINDING_STATE_ACTIVE] = " binding state active",
|
||||
[PREFIX_BINDING_STATE_BACKUP] = " binding state backup",
|
||||
[PREFIX_HARDWARE_ETHERNET] = " hardware ethernet"
|
||||
},
|
||||
[VERSION_6] = {
|
||||
[PREFIX_LEASE] = " iaaddr ",
|
||||
[PREFIX_BINDING_STATE_FREE] = " binding state free",
|
||||
[PREFIX_BINDING_STATE_ACTIVE] = " binding state active",
|
||||
[PREFIX_BINDING_STATE_BACKUP] = " binding state backup",
|
||||
[PREFIX_HARDWARE_ETHERNET] = " hardware ethernet"
|
||||
}
|
||||
};
|
||||
|
||||
int prefix_length[2][NUM_OF_PREFIX] = { };
|
||||
|
||||
/* Parse dhcpd.leases file. All performance boosts for this function are
|
||||
* welcome */
|
||||
int parse_leases(void)
|
||||
{
|
||||
FILE *dhcpd_leases;
|
||||
char *line, *ipstring, *macstring = NULL;
|
||||
struct in_addr inp;
|
||||
union ipaddr_t addr;
|
||||
struct stat lease_file_stats;
|
||||
struct macaddr_t *macaddr_p = NULL;
|
||||
int sw_active_lease = 0;
|
||||
|
|
@ -105,43 +126,46 @@ int parse_leases(void)
|
|||
macaddr_p->next = NULL;
|
||||
}
|
||||
|
||||
const char **p = prefixes[dhcp_version];
|
||||
int *l = prefix_length[dhcp_version];
|
||||
#define HAS_PREFIX(line, type) xstrstr((line), p[type], l[type])
|
||||
|
||||
while (!feof(dhcpd_leases)) {
|
||||
if (!fgets(line, MAXLEN, dhcpd_leases) && ferror(dhcpd_leases)) {
|
||||
err(EXIT_FAILURE, "parse_leases: %s",
|
||||
config.dhcpdlease_file);
|
||||
}
|
||||
/* It's a lease, save IP */
|
||||
if (xstrstr(line, "lease", 5)) {
|
||||
memcpy(ipstring, line + 6, 16);
|
||||
nth_field(ipstring, ipstring);
|
||||
inet_aton(ipstring, &inp);
|
||||
if (HAS_PREFIX(line, PREFIX_LEASE)) {
|
||||
nth_field(ipstring, line + l[PREFIX_LEASE]);
|
||||
parse_ipaddr(ipstring, &addr);
|
||||
sw_active_lease = 0;
|
||||
continue;
|
||||
}
|
||||
if (xstrstr(line, " binding state free", 20)) {
|
||||
if (HAS_PREFIX(line, PREFIX_BINDING_STATE_FREE)) {
|
||||
/* remove old entry, if exists */
|
||||
if ((lease = find_lease(ntohl(inp.s_addr))) != NULL) {
|
||||
if ((lease = find_lease(&addr)) != NULL) {
|
||||
delete_lease(lease);
|
||||
}
|
||||
add_lease(ntohl(inp.s_addr), FREE);
|
||||
add_lease(&addr, FREE);
|
||||
continue;
|
||||
}
|
||||
/* Copy IP to correct array */
|
||||
if (xstrstr(line, " binding state active", 22)) {
|
||||
if (HAS_PREFIX(line, PREFIX_BINDING_STATE_ACTIVE)) {
|
||||
/* remove old entry, if exists */
|
||||
if ((lease = find_lease(ntohl(inp.s_addr))) != NULL) {
|
||||
if ((lease = find_lease(&addr)) != NULL) {
|
||||
delete_lease(lease);
|
||||
}
|
||||
add_lease(ntohl(inp.s_addr), ACTIVE);
|
||||
add_lease(&addr, ACTIVE);
|
||||
sw_active_lease = 1;
|
||||
continue;
|
||||
}
|
||||
if (xstrstr(line, " binding state backup", 22)) {
|
||||
if (HAS_PREFIX(line, PREFIX_BINDING_STATE_BACKUP)) {
|
||||
/* remove old entry, if exists */
|
||||
if ((lease = find_lease(ntohl(inp.s_addr))) != NULL) {
|
||||
if ((lease = find_lease(&addr)) != NULL) {
|
||||
delete_lease(lease);
|
||||
}
|
||||
add_lease(ntohl(inp.s_addr), BACKUP);
|
||||
add_lease(&addr, BACKUP);
|
||||
continue;
|
||||
}
|
||||
if ((macaddr != NULL)
|
||||
|
|
@ -159,6 +183,7 @@ int parse_leases(void)
|
|||
}
|
||||
}
|
||||
}
|
||||
#undef HAS_PREFIX
|
||||
free(line);
|
||||
free(ipstring);
|
||||
if (macaddr != NULL) {
|
||||
|
|
@ -204,7 +229,7 @@ void parse_config(int is_include, const char *restrict config_file,
|
|||
size_t i = 0;
|
||||
char *word, c;
|
||||
int braces_shared = 1000;
|
||||
struct in_addr inp;
|
||||
union ipaddr_t addr;
|
||||
struct range_t *range_p;
|
||||
|
||||
word = xmalloc(sizeof(char) * MAXLEN);
|
||||
|
|
@ -356,9 +381,9 @@ void parse_config(int is_include, const char *restrict config_file,
|
|||
case 2:
|
||||
/* printf ("range 2nd ip: %s\n", word); */
|
||||
range_p = ranges + num_ranges;
|
||||
inet_aton(word, &inp);
|
||||
parse_ipaddr(word, &addr);
|
||||
argument = 0;
|
||||
range_p->last_ip = ntohl(inp.s_addr);
|
||||
copy_ipaddr(&range_p->last_ip, &addr);
|
||||
range_p->count = 0;
|
||||
range_p->touched = 0;
|
||||
range_p->backups = 0;
|
||||
|
|
@ -377,12 +402,12 @@ void parse_config(int is_include, const char *restrict config_file,
|
|||
case 3:
|
||||
/* printf ("range 1nd ip: %s\n", word); */
|
||||
range_p = ranges + num_ranges;
|
||||
if (!(inet_aton(word, &inp))) {
|
||||
if (!(parse_ipaddr(word, &addr))) {
|
||||
/* word was not ip, try
|
||||
* again */
|
||||
break;
|
||||
}
|
||||
range_p->first_ip = ntohl(inp.s_addr);
|
||||
copy_ipaddr(&range_p->first_ip, &addr);
|
||||
argument = 2;
|
||||
break;
|
||||
case 1:
|
||||
|
|
|
|||
21
src/hash.c
21
src/hash.c
|
|
@ -36,20 +36,31 @@
|
|||
#include "dhcpd-pools.h"
|
||||
#include "xalloc.h"
|
||||
|
||||
void add_lease(int ip, enum ltype type)
|
||||
#define HASH_FIND_V6(head, findv6, out) HASH_FIND(hh, head, findv6, 16, out)
|
||||
#define HASH_ADD_V6(head, v6field, add) HASH_ADD(hh, head, v6field, 16, add)
|
||||
|
||||
void add_lease(union ipaddr_t *addr, enum ltype type)
|
||||
{
|
||||
struct leases_t *l;
|
||||
l = xmalloc(sizeof(struct leases_t));
|
||||
l->ip = ip;
|
||||
copy_ipaddr(&l->ip, addr);
|
||||
l->type = type;
|
||||
HASH_ADD_INT(leases, ip, l);
|
||||
if (dhcp_version == VERSION_6) {
|
||||
HASH_ADD_V6(leases, ip.v6, l);
|
||||
} else {
|
||||
HASH_ADD_INT(leases, ip.v4, l);
|
||||
}
|
||||
}
|
||||
|
||||
struct leases_t *find_lease(int ip)
|
||||
struct leases_t *find_lease(union ipaddr_t *addr)
|
||||
{
|
||||
struct leases_t *l;
|
||||
|
||||
HASH_FIND_INT(leases, &ip, l);
|
||||
if (dhcp_version == VERSION_6) {
|
||||
HASH_FIND_V6(leases, &addr->v6, l);
|
||||
} else {
|
||||
HASH_FIND_INT(leases, &addr->v4, l);
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
|
|
|
|||
72
src/other.c
72
src/other.c
|
|
@ -45,6 +45,78 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
|
||||
int parse_ipaddr(const char *restrict src, union ipaddr_t *restrict dst)
|
||||
{
|
||||
int rv;
|
||||
if (dhcp_version == VERSION_UNKNOWN) {
|
||||
struct in_addr addr;
|
||||
struct in6_addr addr6;
|
||||
if (inet_aton(src, &addr) == 1) {
|
||||
dhcp_version = VERSION_4;
|
||||
} else if (inet_pton(AF_INET6, src, &addr6) == 1) {
|
||||
dhcp_version = VERSION_6;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (dhcp_version == VERSION_6) {
|
||||
struct in6_addr addr;
|
||||
rv = inet_pton(AF_INET6, src, &addr);
|
||||
memcpy(&dst->v6, addr.s6_addr, sizeof(addr.s6_addr));
|
||||
} else {
|
||||
struct in_addr addr;
|
||||
rv = inet_aton(src, &addr);
|
||||
dst->v4 = ntohl(addr.s_addr);
|
||||
}
|
||||
return rv == 1;
|
||||
}
|
||||
|
||||
void copy_ipaddr(union ipaddr_t *restrict dst,
|
||||
const union ipaddr_t *restrict src)
|
||||
{
|
||||
if (dhcp_version == VERSION_6) {
|
||||
memcpy(&dst->v6, &src->v6, sizeof(src->v6));
|
||||
} else {
|
||||
dst->v4 = src->v4;
|
||||
}
|
||||
}
|
||||
|
||||
const char *ntop_ipaddr(const union ipaddr_t *ip)
|
||||
{
|
||||
static char
|
||||
buffer[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
|
||||
if (dhcp_version == VERSION_6) {
|
||||
struct in6_addr addr;
|
||||
memcpy(addr.s6_addr, ip->v6, sizeof(addr.s6_addr));
|
||||
return inet_ntop(AF_INET6, &addr, buffer, sizeof(buffer));
|
||||
} else {
|
||||
struct in_addr addr;
|
||||
addr.s_addr = htonl(ip->v4);
|
||||
return inet_ntop(AF_INET, &addr, buffer, sizeof(buffer));
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long get_range_size(const struct range_t *r)
|
||||
{
|
||||
if (dhcp_version == VERSION_6) {
|
||||
unsigned long size = 0;
|
||||
int i;
|
||||
/* When calculating the size of an IPv6 range overflow may
|
||||
* occur. In that case only the last LONG_BIT bits are
|
||||
* preserved, thus we just skip the first (16 - LONG_BIT)
|
||||
* bits... */
|
||||
for (i = LONG_BIT / 8 < 16 ? 16 - LONG_BIT / 8 : 0; i < 16; i++) {
|
||||
size <<= 8;
|
||||
size += (int)r->last_ip.v6[i] - (int)r->first_ip.v6[i];
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
return size + 1;
|
||||
} else {
|
||||
return r->last_ip.v4 - r->first_ip.v4 + 1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
|
||||
|
|
|
|||
116
src/output.c
116
src/output.c
|
|
@ -53,11 +53,12 @@
|
|||
int output_txt(void)
|
||||
{
|
||||
unsigned int i;
|
||||
struct in_addr first, last;
|
||||
struct range_t *range_p;
|
||||
unsigned long range_size;
|
||||
struct shared_network_t *shared_p;
|
||||
int ret;
|
||||
FILE *outfile;
|
||||
int max_ipaddr_length = dhcp_version == VERSION_6 ? 39 : 16;
|
||||
|
||||
if (config.output_file[0]) {
|
||||
outfile = fopen(config.output_file, "w+");
|
||||
|
|
@ -69,13 +70,20 @@ int output_txt(void)
|
|||
}
|
||||
|
||||
range_p = ranges;
|
||||
range_size = get_range_size(range_p);
|
||||
shared_p = shared_networks;
|
||||
|
||||
if (config.output_limit[0] & output_limit_bit_1) {
|
||||
fprintf(outfile, "Ranges:\n");
|
||||
fprintf
|
||||
(outfile,
|
||||
"shared net name first ip last ip max cur percent touch t+c t+c perc");
|
||||
"%-20s%-*s %-*s %5s %5s %10s %5s %5s %9s",
|
||||
"shared net name",
|
||||
max_ipaddr_length,
|
||||
"first ip",
|
||||
max_ipaddr_length,
|
||||
"last ip",
|
||||
"max", "cur", "percent", "touch", "t+c", "t+c perc");
|
||||
if (0 < num_backups) {
|
||||
fprintf(outfile, " bu bu perc");
|
||||
}
|
||||
|
|
@ -83,40 +91,39 @@ int output_txt(void)
|
|||
}
|
||||
if (config.output_limit[1] & output_limit_bit_1) {
|
||||
for (i = 0; i < num_ranges; i++) {
|
||||
first.s_addr = ntohl(range_p->first_ip);
|
||||
last.s_addr = ntohl(range_p->last_ip);
|
||||
|
||||
if (range_p->shared_net) {
|
||||
fprintf(outfile, "%-20s",
|
||||
range_p->shared_net->name);
|
||||
} else {
|
||||
fprintf(outfile, "not_defined ");
|
||||
}
|
||||
fprintf(outfile, "%-16s", inet_ntoa(first));
|
||||
/* Outputting of first_ip and last_ip need to be
|
||||
* separate since ntop_ipaddr always returns the
|
||||
* same buffer */
|
||||
fprintf(outfile, "%-*s",
|
||||
max_ipaddr_length,
|
||||
ntop_ipaddr(&range_p->first_ip));
|
||||
fprintf(outfile,
|
||||
" - %-16s %5" PRIu32
|
||||
" %5lu %10.3f %5lu %5lu %9.3f",
|
||||
inet_ntoa(last),
|
||||
range_p->last_ip - range_p->first_ip + 1,
|
||||
" - %-*s %5lu %5lu %10.3f %5lu %5lu %9.3f",
|
||||
max_ipaddr_length,
|
||||
ntop_ipaddr(&range_p->last_ip),
|
||||
range_size,
|
||||
range_p->count,
|
||||
(float)(100 * range_p->count) /
|
||||
(range_p->last_ip - range_p->first_ip + 1),
|
||||
(float)(100 * range_p->count) / range_size,
|
||||
range_p->touched,
|
||||
range_p->touched + range_p->count,
|
||||
(float)(100 *
|
||||
(range_p->touched +
|
||||
range_p->count)) / (range_p->last_ip -
|
||||
range_p->first_ip +
|
||||
1));
|
||||
range_p->count)) / range_size);
|
||||
if (0 < num_backups) {
|
||||
fprintf(outfile, "%7lu %8.3f",
|
||||
range_p->backups,
|
||||
(float)(100 * range_p->backups) /
|
||||
(range_p->last_ip -
|
||||
range_p->first_ip + 1));
|
||||
range_size);
|
||||
}
|
||||
fprintf(outfile, "\n");
|
||||
range_p++;
|
||||
range_size = get_range_size(range_p);
|
||||
}
|
||||
}
|
||||
if (config.output_limit[1] & output_limit_bit_1
|
||||
|
|
@ -210,8 +217,8 @@ int output_txt(void)
|
|||
int output_xml(void)
|
||||
{
|
||||
unsigned int i;
|
||||
struct in_addr first, last;
|
||||
struct range_t *range_p;
|
||||
unsigned long range_size;
|
||||
struct shared_network_t *shared_p;
|
||||
struct macaddr_t *macaddr_p;
|
||||
int ret;
|
||||
|
|
@ -227,6 +234,7 @@ int output_xml(void)
|
|||
}
|
||||
|
||||
range_p = ranges;
|
||||
range_size = get_range_size(range_p);
|
||||
shared_p = shared_networks;
|
||||
|
||||
fprintf(outfile, "<dhcpstatus>\n");
|
||||
|
|
@ -242,8 +250,6 @@ int output_xml(void)
|
|||
|
||||
if (config.output_limit[1] & output_limit_bit_1) {
|
||||
for (i = 0; i < num_ranges; i++) {
|
||||
first.s_addr = ntohl(range_p->first_ip);
|
||||
last.s_addr = ntohl(range_p->last_ip);
|
||||
fprintf(outfile, "<subnet>\n");
|
||||
if (range_p->shared_net) {
|
||||
fprintf(outfile,
|
||||
|
|
@ -255,17 +261,19 @@ int output_xml(void)
|
|||
|
||||
fprintf(outfile, "\t<network></network>\n");
|
||||
fprintf(outfile, "\t<netmask></netmask>\n");
|
||||
fprintf(outfile, "\t<range>%s ", inet_ntoa(first));
|
||||
fprintf(outfile, "- %s</range>\n", inet_ntoa(last));
|
||||
fprintf(outfile, "\t<range>%s ",
|
||||
ntop_ipaddr(&range_p->first_ip));
|
||||
fprintf(outfile, "- %s</range>\n",
|
||||
ntop_ipaddr(&range_p->last_ip));
|
||||
fprintf(outfile, "\t<gateway></gateway>\n");
|
||||
fprintf(outfile, "\t<defined>%" PRIu32 "</defined>\n",
|
||||
range_p->last_ip - range_p->first_ip + 1);
|
||||
fprintf(outfile, "\t<defined>%lu</defined>\n",
|
||||
range_size);
|
||||
fprintf(outfile, "\t<used>%lu</used>\n",
|
||||
range_p->count);
|
||||
fprintf(outfile, "\t<free>%lu</free>\n",
|
||||
range_p->last_ip - range_p->first_ip + 1 -
|
||||
range_p->count);
|
||||
range_size - range_p->count);
|
||||
range_p++;
|
||||
range_size = get_range_size(range_p);
|
||||
fprintf(outfile, "</subnet>\n");
|
||||
}
|
||||
}
|
||||
|
|
@ -456,8 +464,8 @@ static void newsection(FILE *restrict f, char const *restrict title)
|
|||
int output_html(void)
|
||||
{
|
||||
unsigned int i;
|
||||
struct in_addr first, last;
|
||||
struct range_t *range_p;
|
||||
unsigned long range_size;
|
||||
struct shared_network_t *shared_p;
|
||||
int ret;
|
||||
FILE *outfile;
|
||||
|
|
@ -472,6 +480,7 @@ int output_html(void)
|
|||
}
|
||||
|
||||
range_p = ranges;
|
||||
range_size = get_range_size(range_p);
|
||||
shared_p = shared_networks;
|
||||
if (fullhtml) {
|
||||
html_header(outfile);
|
||||
|
|
@ -497,8 +506,6 @@ int output_html(void)
|
|||
}
|
||||
if (config.output_limit[1] & output_limit_bit_1) {
|
||||
for (i = 0; i < num_ranges; i++) {
|
||||
first.s_addr = ntohl(range_p->first_ip);
|
||||
last.s_addr = ntohl(range_p->last_ip);
|
||||
newrow(outfile);
|
||||
if (range_p->shared_net) {
|
||||
output_line(outfile, "td", "calign",
|
||||
|
|
@ -507,34 +514,32 @@ int output_html(void)
|
|||
output_line(outfile, "td", "calign",
|
||||
"not_defined");
|
||||
}
|
||||
output_line(outfile, "td", "calign", inet_ntoa(first));
|
||||
output_line(outfile, "td", "calign", inet_ntoa(last));
|
||||
output_long(outfile, "td",
|
||||
range_p->last_ip - range_p->first_ip + 1);
|
||||
output_line(outfile, "td", "calign",
|
||||
ntop_ipaddr(&range_p->first_ip));
|
||||
output_line(outfile, "td", "calign",
|
||||
ntop_ipaddr(&range_p->last_ip));
|
||||
output_long(outfile, "td", range_size);
|
||||
output_long(outfile, "td", range_p->count);
|
||||
output_float(outfile, "td",
|
||||
(float)(100 * range_p->count) /
|
||||
(range_p->last_ip -
|
||||
range_p->first_ip + 1));
|
||||
range_size);
|
||||
output_long(outfile, "td", range_p->touched);
|
||||
output_long(outfile, "td",
|
||||
range_p->touched + range_p->count);
|
||||
output_float(outfile, "td",
|
||||
(float)(100 *
|
||||
(range_p->touched +
|
||||
range_p->count)) /
|
||||
(range_p->last_ip -
|
||||
range_p->first_ip + 1));
|
||||
range_p->count)) / range_size);
|
||||
if (0 < num_backups) {
|
||||
output_long(outfile, "td", range_p->backups);
|
||||
output_float(outfile, "td",
|
||||
(float)(100 *
|
||||
range_p->backups) /
|
||||
(range_p->last_ip -
|
||||
range_p->first_ip + 1));
|
||||
range_size);
|
||||
}
|
||||
endrow(outfile);
|
||||
range_p++;
|
||||
range_size = get_range_size(range_p);
|
||||
}
|
||||
}
|
||||
table_end(outfile);
|
||||
|
|
@ -647,8 +652,8 @@ int output_html(void)
|
|||
int output_csv(void)
|
||||
{
|
||||
unsigned int i;
|
||||
struct in_addr first, last;
|
||||
struct range_t *range_p;
|
||||
unsigned long range_size;
|
||||
struct shared_network_t *shared_p;
|
||||
FILE *outfile;
|
||||
int ret;
|
||||
|
|
@ -662,6 +667,7 @@ int output_csv(void)
|
|||
}
|
||||
|
||||
range_p = ranges;
|
||||
range_size = get_range_size(range_p);
|
||||
shared_p = shared_networks;
|
||||
if (config.output_limit[0] & output_limit_bit_1) {
|
||||
fprintf(outfile, "\"Ranges:\"\n");
|
||||
|
|
@ -675,40 +681,34 @@ int output_csv(void)
|
|||
}
|
||||
if (config.output_limit[1] & output_limit_bit_1) {
|
||||
for (i = 0; i < num_ranges; i++) {
|
||||
first.s_addr = ntohl(range_p->first_ip);
|
||||
last.s_addr = ntohl(range_p->last_ip);
|
||||
if (range_p->shared_net) {
|
||||
fprintf(outfile, "\"%s\",",
|
||||
range_p->shared_net->name);
|
||||
} else {
|
||||
fprintf(outfile, "\"not_defined\",");
|
||||
}
|
||||
fprintf(outfile, "\"%s\",", inet_ntoa(first));
|
||||
fprintf(outfile, "\"%s\",",
|
||||
ntop_ipaddr(&range_p->first_ip));
|
||||
fprintf(outfile,
|
||||
"\"%s\",\"%" PRIu32
|
||||
"\",\"%lu\",\"%.3f\",\"%lu\",\"%lu\",\"%.3f\"",
|
||||
inet_ntoa(last),
|
||||
range_p->last_ip - range_p->first_ip + 1,
|
||||
"\"%s\",\"%lu\",\"%lu\",\"%.3f\",\"%lu\",\"%lu\",\"%.3f\"",
|
||||
ntop_ipaddr(&range_p->last_ip), range_size,
|
||||
range_p->count,
|
||||
(float)(100 * range_p->count) /
|
||||
(range_p->last_ip - range_p->first_ip + 1),
|
||||
(float)(100 * range_p->count) / range_size,
|
||||
range_p->touched,
|
||||
range_p->touched + range_p->count,
|
||||
(float)(100 *
|
||||
(range_p->touched +
|
||||
range_p->count)) / (range_p->last_ip -
|
||||
range_p->first_ip +
|
||||
1));
|
||||
range_p->count)) / range_size);
|
||||
if (0 < num_backups) {
|
||||
fprintf(outfile, ",\"%lu\",\"%.3f\"",
|
||||
range_p->backups,
|
||||
(float)(100 * range_p->backups) /
|
||||
(range_p->last_ip -
|
||||
range_p->first_ip + 1));
|
||||
range_size);
|
||||
}
|
||||
|
||||
fprintf(outfile, "\n");
|
||||
range_p++;
|
||||
range_size = get_range_size(range_p);
|
||||
}
|
||||
fprintf(outfile, "\n");
|
||||
}
|
||||
|
|
@ -796,6 +796,7 @@ int output_alarming(void)
|
|||
{
|
||||
FILE *outfile;
|
||||
struct range_t *range_p;
|
||||
unsigned long range_size;
|
||||
struct shared_network_t *shared_p;
|
||||
unsigned int i;
|
||||
float perc;
|
||||
|
|
@ -803,6 +804,7 @@ int output_alarming(void)
|
|||
int ret_val, ret;
|
||||
|
||||
range_p = ranges;
|
||||
range_size = get_range_size(range_p);
|
||||
shared_p = shared_networks;
|
||||
|
||||
if (config.output_file[0]) {
|
||||
|
|
@ -817,8 +819,7 @@ int output_alarming(void)
|
|||
|
||||
if (config.output_limit[1] & output_limit_bit_1) {
|
||||
for (i = 0; i < num_ranges; i++) {
|
||||
perc = (float)(100 * range_p->count) /
|
||||
(range_p->last_ip - range_p->first_ip + 1);
|
||||
perc = (float)(100 * range_p->count) / range_size;
|
||||
if (config.critical < perc)
|
||||
rc++;
|
||||
else if (config.warning < perc)
|
||||
|
|
@ -826,6 +827,7 @@ int output_alarming(void)
|
|||
else
|
||||
ro++;
|
||||
range_p++;
|
||||
range_size = get_range_size(range_p);
|
||||
}
|
||||
}
|
||||
if (config.output_limit[1] & output_limit_bit_2) {
|
||||
|
|
|
|||
37
src/sort.c
37
src/sort.c
|
|
@ -53,20 +53,35 @@ int intcomp(const void *restrict x, const void *restrict y)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int ipcomp(const union ipaddr_t *restrict a, const union ipaddr_t *restrict b)
|
||||
{
|
||||
if (dhcp_version == VERSION_6) {
|
||||
return memcmp(&a->v6, &b->v6, sizeof(a->v6));
|
||||
} else {
|
||||
if (a->v4 < b->v4)
|
||||
return -1;
|
||||
if (a->v4 > b->v4)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int leasecomp(const void *restrict a, const void *restrict b)
|
||||
{
|
||||
return ipcomp(&((const struct leases_t *)a)->ip,
|
||||
&((const struct leases_t *)b)->ip);
|
||||
}
|
||||
|
||||
int rangecomp(const void *restrict r1, const void *restrict r2)
|
||||
{
|
||||
if ((((struct range_t *)r1)->first_ip) <
|
||||
(((struct range_t *)r2)->first_ip))
|
||||
return -1;
|
||||
if ((((struct range_t *)r2)->first_ip) <
|
||||
(((struct range_t *)r1)->first_ip))
|
||||
return 1;
|
||||
return 0;
|
||||
return ipcomp(&((const struct range_t *)r1)->first_ip,
|
||||
&((const struct range_t *)r2)->first_ip);
|
||||
}
|
||||
|
||||
unsigned long int ret_ip(struct range_t r)
|
||||
{
|
||||
return (r.first_ip);
|
||||
/* FIXME: IPv6 */
|
||||
return (r.first_ip.v4);
|
||||
}
|
||||
|
||||
unsigned long int ret_cur(struct range_t r)
|
||||
|
|
@ -76,13 +91,13 @@ unsigned long int ret_cur(struct range_t r)
|
|||
|
||||
unsigned long int ret_max(struct range_t r)
|
||||
{
|
||||
return (r.last_ip - r.first_ip);
|
||||
return get_range_size(&r);
|
||||
}
|
||||
|
||||
unsigned long int ret_percent(struct range_t r)
|
||||
{
|
||||
float f;
|
||||
f = (float)r.count / (r.last_ip - r.first_ip - 1);
|
||||
f = (float)r.count / get_range_size(&r);
|
||||
return ((unsigned long int)(f * 100000));
|
||||
}
|
||||
|
||||
|
|
@ -99,7 +114,7 @@ unsigned long int ret_tc(struct range_t r)
|
|||
unsigned long int ret_tcperc(struct range_t r)
|
||||
{
|
||||
float f;
|
||||
f = (float)(r.count + r.touched) / (r.last_ip - r.first_ip - 1);
|
||||
f = (float)(r.count + r.touched) / get_range_size(&r);
|
||||
return ((unsigned long int)(f * 10000));
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue