diff --git a/src/analyze.c b/src/analyze.c index d38db6b..f66b150 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -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; diff --git a/src/dhcpd-pools.c b/src/dhcpd-pools.c index 26a353b..91c518c 100644 --- a/src/dhcpd-pools.c +++ b/src/dhcpd-pools.c @@ -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 = diff --git a/src/dhcpd-pools.h b/src/dhcpd-pools.h index 0b98497..287c153 100644 --- a/src/dhcpd-pools.h +++ b/src/dhcpd-pools.h @@ -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(); diff --git a/src/getdata.c b/src/getdata.c index 9270581..a792806 100644 --- a/src/getdata.c +++ b/src/getdata.c @@ -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: diff --git a/src/hash.c b/src/hash.c index 4978259..a9e41b8 100644 --- a/src/hash.c +++ b/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; } diff --git a/src/other.c b/src/other.c index 7c34578..a970c0e 100644 --- a/src/other.c +++ b/src/other.c @@ -45,6 +45,78 @@ #include #include #include +#include + +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) diff --git a/src/output.c b/src/output.c index 1eb3a65..78b54bb 100644 --- a/src/output.c +++ b/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, "\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, "\n"); if (range_p->shared_net) { fprintf(outfile, @@ -255,17 +261,19 @@ int output_xml(void) fprintf(outfile, "\t\n"); fprintf(outfile, "\t\n"); - fprintf(outfile, "\t%s ", inet_ntoa(first)); - fprintf(outfile, "- %s\n", inet_ntoa(last)); + fprintf(outfile, "\t%s ", + ntop_ipaddr(&range_p->first_ip)); + fprintf(outfile, "- %s\n", + ntop_ipaddr(&range_p->last_ip)); fprintf(outfile, "\t\n"); - fprintf(outfile, "\t%" PRIu32 "\n", - range_p->last_ip - range_p->first_ip + 1); + fprintf(outfile, "\t%lu\n", + range_size); fprintf(outfile, "\t%lu\n", range_p->count); fprintf(outfile, "\t%lu\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, "\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) { diff --git a/src/sort.c b/src/sort.c index c018e45..3d606fd 100644 --- a/src/sort.c +++ b/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)); }