diff --git a/lib/.gitignore b/lib/.gitignore index 8208f92..928a516 100644 --- a/lib/.gitignore +++ b/lib/.gitignore @@ -40,6 +40,9 @@ /fd-hook.h /fdopen.c /fflush.c +/float+.h +/float.c +/float.in.h /fopen.c /fpending.c /fpending.h @@ -60,6 +63,11 @@ /gettimeofday.c /inet_pton.c /intprops.h +/isnan.c +/isnand.c +/isnanf.c +/isnanl.c +/itold.c /langinfo.h /langinfo.in.h /libdhcpd_pools.la @@ -67,6 +75,9 @@ /localcharset.h /lseek.c /malloc.c +/math.c +/math.h +/math.in.h /mbrtowc.c /mbsinit.c /memchr.c diff --git a/src/.indent.pro b/src/.indent.pro index 16702c4..3d15003 100644 --- a/src/.indent.pro +++ b/src/.indent.pro @@ -9,3 +9,5 @@ -Tuintmax_t -l100 -ppi1 +-bad +-sob diff --git a/src/analyze.c b/src/analyze.c index 9c05a43..4c39b62 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -65,19 +65,16 @@ int do_counting(void) const struct leases_t *restrict l = leases; unsigned long i, k, block_size; - range_p = ranges; - /* Walk through ranges */ + range_p = ranges; for (i = 0; i < num_ranges; i++) { for (; l != NULL && ipcomp(&range_p->first_ip, &l->ip) < 0; l = l->hh.prev) /* rewind */ ; if (l == NULL) l = leases; 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; - } + if (ipcomp(&l->ip, &range_p->first_ip) < 0) + continue; /* cannot happen? */ /* IP in range */ switch (l->type) { case FREE: @@ -90,7 +87,6 @@ int do_counting(void) range_p->backups++; break; } - if (range_p->shared_net) { switch (l->type) { case FREE: @@ -105,16 +101,12 @@ int do_counting(void) } } } - /* Size of range, shared net & all networks */ block_size = get_range_size(range_p); - if (range_p->shared_net) { + if (range_p->shared_net) range_p->shared_net->available += block_size; - } - range_p++; } - /* FIXME: During count of other shared networks default network * and all networks got mixed together semantically. The below * fixes the problem, but is not elegant. */ @@ -129,6 +121,5 @@ int do_counting(void) shared_networks->backups += range_p->backups; range_p++; } - return 0; } diff --git a/src/dhcpd-pools.c b/src/dhcpd-pools.c index 974eaf6..bfb312b 100644 --- a/src/dhcpd-pools.c +++ b/src/dhcpd-pools.c @@ -99,7 +99,6 @@ int main(int argc, char **argv) }; int ret_val; - /* Options for getopt_long */ static struct option const long_options[] = { {"config", required_argument, NULL, 'c'}, {"leases", required_argument, NULL, 'l'}, @@ -118,20 +117,17 @@ int main(int argc, char **argv) atexit(close_stdout); set_program_name(argv[0]); - /* FIXME: These allocations should be fully dynamic, e.g., grow * if needed. */ config.dhcpdconf_file = xmalloc(sizeof(char) * MAXLEN); config.dhcpdlease_file = xmalloc(sizeof(char) * MAXLEN); config.output_file = xmalloc(sizeof(char) * MAXLEN); - /* Make sure string has zero length if there is no * command line option */ config.output_file[0] = '\0'; /* Alarming defaults. */ config.warning = ALARM_WARN; config.critical = ALARM_CRIT; - /* File location defaults */ strncpy(config.dhcpdconf_file, DHCPDCONF_FILE, MAXLEN - 1); strncpy(config.dhcpdlease_file, DHCPDLEASE_FILE, MAXLEN - 1); @@ -140,22 +136,18 @@ int main(int argc, char **argv) tmp++; config.output_limit[1] = (*tmp - '0'); config.fullhtml = false; - /* Make sure some output format is selected by default */ strncpy(config.output_format, OUTPUT_FORMAT, (size_t)1); - /* Default sort order is by IPs small to big */ config.reverse_order = false; config.backups_found = false; - /* Parse command line options */ while (1) { int c; - c = getopt_long(argc, argv, "c:l:f:o:s:rL:vh", long_options, &option_index); + c = getopt_long(argc, argv, "c:l:f:o:s:rL:vh", long_options, &option_index); if (c == EOF) break; - switch (c) { case 'c': /* config file */ @@ -176,12 +168,10 @@ int main(int argc, char **argv) warnx("main: only first 5 sort orders will be used"); strncpy(config.sort, optarg, (size_t)5); sorts = 5; - } else { + } else strncpy(config.sort, optarg, (size_t)sorts); - } - for (i = 0; i < sorts; i++) { + for (i = 0; i < sorts; i++) field_selector(config.sort[i]); - } break; case 'r': /* What ever sort in reverse order */ @@ -194,9 +184,9 @@ int main(int argc, char **argv) case 'L': /* Specification what will be printed */ for (i = 0; i < 2; i++) { - if (optarg[i] >= '0' && optarg[i] < '8') { + if (optarg[i] >= '0' && optarg[i] < '8') config.output_limit[i] = optarg[i] - '0'; - } else { + else { clean_up(); errx(EXIT_FAILURE, "main: output mask `%s' is illegal", optarg); @@ -224,7 +214,6 @@ int main(int argc, char **argv) errx(EXIT_FAILURE, "Try `%s --help' for more information.", program_name); } } - /* Output function selection */ switch (config.output_format[0]) { case 't': @@ -259,25 +248,20 @@ int main(int argc, char **argv) clean_up(); errx(EXIT_FAILURE, "main: unknown output format `%c'", config.output_format[0]); } - /* Do the job */ prepare_memory(); set_ipv_functions(VERSION_UNKNOWN); parse_config(true, config.dhcpdconf_file, shared_networks); - parse_leases(); prepare_data(); do_counting(); tmp_ranges = xmalloc(sizeof(struct range_t) * num_ranges); - if (sorts != 0) { + if (sorts != 0) mergesort_ranges(ranges, num_ranges, tmp_ranges); - } - if (config.reverse_order == true) { + if (config.reverse_order == true) flip_ranges(ranges, tmp_ranges); - } free(tmp_ranges); ret_val = output_analysis(); - clean_up(); return (ret_val); } @@ -291,14 +275,11 @@ int prepare_memory(void) RANGES = 64; num_ranges = num_shared_networks = 0; shared_networks = xmalloc(sizeof(struct shared_network_t) * SHARED_NETWORKS); - ranges = xmalloc(sizeof(struct range_t) * RANGES); - /* First shared network entry is all networks */ shared_networks->name = xstrdup("All networks"); shared_networks->used = 0; shared_networks->touched = 0; shared_networks->backups = 0; - return 0; } diff --git a/src/getdata.c b/src/getdata.c index 0f5e8ae..bf2de86 100644 --- a/src/getdata.c +++ b/src/getdata.c @@ -69,42 +69,33 @@ int parse_leases(void) struct leases_t *lease; dhcpd_leases = fopen(config.dhcpdlease_file, "r"); - if (dhcpd_leases == NULL) { + if (dhcpd_leases == NULL) err(EXIT_FAILURE, "parse_leases: %s", config.dhcpdlease_file); - } #ifdef HAVE_POSIX_FADVISE # ifdef POSIX_FADV_NOREUSE - if (posix_fadvise(fileno(dhcpd_leases), 0, 0, POSIX_FADV_NOREUSE) != 0) { + if (posix_fadvise(fileno(dhcpd_leases), 0, 0, POSIX_FADV_NOREUSE) != 0) err(EXIT_FAILURE, "parse_leases: fadvise %s", config.dhcpdlease_file); - } # endif /* POSIX_FADV_NOREUSE */ # ifdef POSIX_FADV_SEQUENTIAL - if (posix_fadvise(fileno(dhcpd_leases), 0, 0, POSIX_FADV_SEQUENTIAL) != 0) { + if (posix_fadvise(fileno(dhcpd_leases), 0, 0, POSIX_FADV_SEQUENTIAL) != 0) err(EXIT_FAILURE, "parse_leases: fadvise %s", config.dhcpdlease_file); - } # endif /* POSIX_FADV_SEQUENTIAL */ #endif /* HAVE_POSIX_FADVISE */ - /* I found out that there's one lease address per 300 bytes in * dhcpd.leases file. Malloc is little bit pessimistic and uses 250. * If someone has higher density in lease file I'm interested to * hear about that. */ - if (stat(config.dhcpdlease_file, &lease_file_stats)) { + if (stat(config.dhcpdlease_file, &lease_file_stats)) err(EXIT_FAILURE, "parse_leases: %s", config.dhcpdlease_file); - } - line = xmalloc(sizeof(char) * MAXLEN); line[0] = '\0'; ipstring = xmalloc(sizeof(char) * MAXLEN); ipstring[0] = '\0'; - if (config.output_format[0] == 'X' || config.output_format[0] == 'J') { + if (config.output_format[0] == 'X' || config.output_format[0] == 'J') ethernets = true; - } - while (!feof(dhcpd_leases)) { - if (!fgets(line, MAXLEN, dhcpd_leases) && ferror(dhcpd_leases)) { + if (!fgets(line, MAXLEN, dhcpd_leases) && ferror(dhcpd_leases)) err(EXIT_FAILURE, "parse_leases: %s", config.dhcpdlease_file); - } switch (xstrstr(line)) { /* It's a lease, save IP */ case PREFIX_LEASE: @@ -122,23 +113,20 @@ int parse_leases(void) case PREFIX_BINDING_STATE_ABANDONED: case PREFIX_BINDING_STATE_EXPIRED: case PREFIX_BINDING_STATE_RELEASED: - if ((lease = find_lease(&addr)) != NULL) { + if ((lease = find_lease(&addr)) != NULL) delete_lease(lease); - } add_lease(&addr, FREE); break; case PREFIX_BINDING_STATE_ACTIVE: /* remove old entry, if exists */ - if ((lease = find_lease(&addr)) != NULL) { + if ((lease = find_lease(&addr)) != NULL) delete_lease(lease); - } add_lease(&addr, ACTIVE); break; case PREFIX_BINDING_STATE_BACKUP: /* remove old entry, if exists */ - if ((lease = find_lease(&addr)) != NULL) { + if ((lease = find_lease(&addr)) != NULL) delete_lease(lease); - } add_lease(&addr, BACKUP); config.backups_found = true; break; @@ -147,9 +135,8 @@ int parse_leases(void) break; memcpy(macstring, line + 20, 17); macstring[17] = '\0'; - if ((lease = find_lease(&addr)) != NULL) { + if ((lease = find_lease(&addr)) != NULL) lease->ethernet = xstrdup(macstring); - } break; default: /* do nothing */ ; @@ -193,41 +180,34 @@ void parse_config(int is_include, const char *restrict config_file, struct range_t *range_p; word = xmalloc(sizeof(char) * MAXLEN); - - if (is_include) { + if (is_include) /* Default place holder for ranges "All networks". */ shared_p->name = shared_networks->name; - } - /* Open configuration file */ dhcpd_config = fopen(config_file, "r"); - if (dhcpd_config == NULL) { + if (dhcpd_config == NULL) err(EXIT_FAILURE, "parse_config: %s", config_file); - } #ifdef HAVE_POSIX_FADVISE # ifdef POSIX_FADV_NOREUSE - if (posix_fadvise(fileno(dhcpd_config), 0, 0, POSIX_FADV_NOREUSE) != 0) { + if (posix_fadvise(fileno(dhcpd_config), 0, 0, POSIX_FADV_NOREUSE) != 0) err(EXIT_FAILURE, "parse_config: fadvise %s", config_file); - } # endif /* POSIX_FADV_NOREUSE */ # ifdef POSIX_FADV_SEQUENTIAL - if (posix_fadvise(fileno(dhcpd_config), 0, 0, POSIX_FADV_SEQUENTIAL) != 0) { + if (posix_fadvise(fileno(dhcpd_config), 0, 0, POSIX_FADV_SEQUENTIAL) != 0) err(EXIT_FAILURE, "parse_config: fadvise %s", config_file); - } # endif /* POSIX_FADV_SEQUENTIAL */ #endif /* HAVE_POSIX_FADVISE */ - /* Very hairy stuff begins. */ while (unlikely(!feof(dhcpd_config))) { char c; + c = fgetc(dhcpd_config); /* Certain characters are magical */ switch (c) { /* Handle comments if they are not quoted */ case '#': - if (quote == 0) { + if (quote == 0) comment = true; - } continue; case '"': if (comment == false) { @@ -239,15 +219,13 @@ void parse_config(int is_include, const char *restrict config_file, case '\n': /* New line resets comment section, but * not if quoted */ - if (quote == 0) { + if (quote == 0) comment = false; - } break; case ';': /* Quoted colon does not mean new clause */ - if (0 < quote) { + if (0 < quote) break; - } if (comment == false && argument != ITS_A_RANGE_FIRST_IP && argument != ITS_A_RANGE_SECOND_IP && argument != ITS_AN_INCLUCE) { @@ -271,25 +249,21 @@ void parse_config(int is_include, const char *restrict config_file, } continue; case '{': - if (0 < quote) { + if (0 < quote) break; - } - if (comment == 0) { + if (comment == 0) braces++; - } /* i == 0 detects word that ends to brace like: * * shared-network DSL{ ... */ if (i == 0) { newclause = true; continue; - } else { + } else break; - } case '}': - if (0 < quote) { + if (0 < quote) break; - } if (comment == false) { braces--; /* End of shared-network */ @@ -307,16 +281,13 @@ void parse_config(int is_include, const char *restrict config_file, default: break; } - /* Either inside comment or Nth word of clause. */ - if (comment == true || (newclause == false && argument == ITS_NOTHING_INTERESTING)) { + if (comment == true || (newclause == false && argument == ITS_NOTHING_INTERESTING)) continue; - } /* Strip white spaces before new clause word. */ if ((newclause == true || argument != ITS_NOTHING_INTERESTING) - && isspace(c) && i == 0 && one_ip_range == false) { + && isspace(c) && i == 0 && one_ip_range == false) continue; - } /* Save to word which clause this is. */ if ((newclause == true || argument != ITS_NOTHING_INTERESTING) && (!isspace(c) || 0 < quote)) { @@ -335,14 +306,12 @@ void parse_config(int is_include, const char *restrict config_file, else if (newclause == true) { /* Insert string end & set state */ word[i] = '\0'; - if (word[i - 1] != '{') { + if (word[i - 1] != '{') newclause = false; - } i = 0; argument = is_interesting_config_clause(word); - if (argument == ITS_A_RANGE_FIRST_IP) { + if (argument == ITS_A_RANGE_FIRST_IP) one_ip_range = true; - } } /* words after range, shared-network or include */ else if (argument != ITS_NOTHING_INTERESTING) { @@ -377,11 +346,9 @@ void parse_config(int is_include, const char *restrict config_file, case ITS_A_RANGE_FIRST_IP: /* printf ("range 1nd ip: %s\n", word); */ range_p = ranges + num_ranges; - if (!(parse_ipaddr(word, &addr))) { - /* word was not ip, try - * again */ + if (!(parse_ipaddr(word, &addr))) + /* word was not ip, try again */ break; - } copy_ipaddr(&range_p->first_ip, &addr); one_ip_range = false; argument = ITS_A_RANGE_SECOND_IP; @@ -395,13 +362,10 @@ void parse_config(int is_include, const char *restrict config_file, shared_p->used = 0; shared_p->touched = 0; shared_p->backups = 0; - if (SHARED_NETWORKS < num_shared_networks + 2) { - /* FIXME: make this - * away by reallocating - * more space. */ + if (SHARED_NETWORKS < num_shared_networks + 2) + /* FIXME: make this to go away by reallocating more space. */ errx(EXIT_FAILURE, "parse_config: increase default.h SHARED_NETWORKS and recompile"); - } argument = ITS_NOTHING_INTERESTING; braces_shared = braces; break; diff --git a/src/hash.c b/src/hash.c index 4b42610..a75e9f4 100644 --- a/src/hash.c +++ b/src/hash.c @@ -55,6 +55,7 @@ void add_lease_init(union ipaddr_t *addr void add_lease_v4(union ipaddr_t *addr, enum ltype type) { struct leases_t *l; + l = xmalloc(sizeof(struct leases_t)); copy_ipaddr(&l->ip, addr); l->type = type; @@ -65,6 +66,7 @@ void add_lease_v4(union ipaddr_t *addr, enum ltype type) void add_lease_v6(union ipaddr_t *addr, enum ltype type) { struct leases_t *l; + l = xmalloc(sizeof(struct leases_t)); copy_ipaddr(&l->ip, addr); l->type = type; @@ -84,6 +86,7 @@ struct leases_t *find_lease_init(union ipaddr_t *addr __attribute__ ((unused))) struct leases_t *find_lease_v4(union ipaddr_t *addr) { struct leases_t *l; + HASH_FIND_INT(leases, &addr->v4, l); return l; } @@ -91,6 +94,7 @@ struct leases_t *find_lease_v4(union ipaddr_t *addr) struct leases_t *find_lease_v6(union ipaddr_t *addr) { struct leases_t *l; + HASH_FIND_V6(leases, &addr->v4, l); return l; } @@ -109,6 +113,7 @@ void delete_lease(struct leases_t *lease) void delete_all_leases(void) { struct leases_t *l, *tmp; + HASH_ITER(hh, leases, l, tmp) { free(l->ethernet); HASH_DEL(leases, l); @@ -120,6 +125,7 @@ void delete_all_leases(void) { while (leases) { struct leases_t *l; + l = leases; free(l->ethernet); HASH_DEL(leases, l); /* leases advances to next on delete */ diff --git a/src/other.c b/src/other.c index f81e506..e9f49c8 100644 --- a/src/other.c +++ b/src/other.c @@ -117,13 +117,13 @@ int parse_ipaddr_init(const char *restrict src, union ipaddr_t *restrict dst) { struct in_addr addr; struct in6_addr addr6; - if (inet_aton(src, &addr) == 1) { + + if (inet_aton(src, &addr) == 1) set_ipv_functions(VERSION_4); - } else if (inet_pton(AF_INET6, src, &addr6) == 1) { + else if (inet_pton(AF_INET6, src, &addr6) == 1) set_ipv_functions(VERSION_6); - } else { + else return 0; - } return parse_ipaddr(src, dst); } @@ -131,6 +131,7 @@ int parse_ipaddr_v4(const char *restrict src, union ipaddr_t *restrict dst) { int rv; struct in_addr addr; + rv = inet_aton(src, &addr); dst->v4 = ntohl(addr.s_addr); return rv == 1; @@ -140,6 +141,7 @@ int parse_ipaddr_v6(const char *restrict src, union ipaddr_t *restrict dst) { int rv; struct in6_addr addr; + rv = inet_pton(AF_INET6, src, &addr); memcpy(&dst->v6, addr.s6_addr, sizeof(addr.s6_addr)); return rv == 1; @@ -175,6 +177,7 @@ void copy_ipaddr_v6(union ipaddr_t *restrict dst, const union ipaddr_t *restrict const char *ntop_ipaddr_init(const union ipaddr_t *ip __attribute__ ((unused))) { static char buffer = '\0'; + return &buffer; } @@ -182,6 +185,7 @@ const char *ntop_ipaddr_v4(const union ipaddr_t *ip) { static char buffer[sizeof("255.255.255.255")]; struct in_addr addr; + addr.s_addr = htonl(ip->v4); return inet_ntop(AF_INET, &addr, buffer, sizeof(buffer)); } @@ -190,6 +194,7 @@ const char *ntop_ipaddr_v6(const union ipaddr_t *ip) { static char buffer[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")]; struct in6_addr addr; + memcpy(addr.s6_addr, ip->v6, sizeof(addr.s6_addr)); return inet_ntop(AF_INET6, &addr, buffer, sizeof(buffer)); } @@ -214,6 +219,7 @@ double get_range_size_v6(const struct range_t *r) { double 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... */ @@ -260,11 +266,11 @@ int xstrstr_v4(const char *restrict str) { size_t len; - if (str[2] == 'b' || str[2] == 'h') { + + if (str[2] == 'b' || str[2] == 'h') len = strlen(str); - } else { + else len = 0; - } if (15 < len) { switch (str[16]) { case 'f': @@ -295,9 +301,8 @@ int break; } } - if (!memcmp("lease ", str, 6)) { + if (!memcmp("lease ", str, 6)) return PREFIX_LEASE; - } return NUM_OF_PREFIX; } @@ -314,11 +319,11 @@ int xstrstr_v6(const char *restrict str) { size_t len; - if (str[4] == 'b' || str[2] == 'h') { + + if (str[4] == 'b' || str[2] == 'h') len = strlen(str); - } else { + else len = 0; - } if (17 < len) { switch (str[18]) { case 'f': @@ -349,9 +354,8 @@ int break; } } - if (!memcmp(" iaaddr ", str, 9)) { + if (!memcmp(" iaaddr ", str, 9)) return PREFIX_LEASE; - } return NUM_OF_PREFIX; } @@ -370,15 +374,12 @@ double strtod_or_err(const char *restrict str, const char *restrict errmesg) goto err; errno = 0; num = strtod(str, &end); - if (errno || str == end || (end && *end)) goto err; - return num; err: if (errno) err(EXIT_FAILURE, "%s: '%s'", errmesg, str); - errx(EXIT_FAILURE, "%s: '%s'", errmesg, str); } @@ -393,10 +394,8 @@ void flip_ranges(struct range_t *restrict flip_me, struct range_t *restrict tmp_ { unsigned int i = num_ranges - 1, j; - for (j = 0; j < num_ranges; j++, i--) { + for (j = 0; j < num_ranges; j++, i--) *(tmp_ranges + j) = *(flip_me + i); - } - memcpy(flip_me, tmp_ranges, num_ranges * sizeof(struct range_t)); } @@ -404,9 +403,8 @@ void flip_ranges(struct range_t *restrict flip_me, struct range_t *restrict tmp_ void clean_up(void) { /* Just in case there something in buffers */ - if (fflush(NULL)) { + if (fflush(NULL)) warn("clean_up: fflush"); - } free(config.dhcpdconf_file); free(config.dhcpdlease_file); free(config.output_file); @@ -414,10 +412,10 @@ void clean_up(void) delete_all_leases(); if (shared_networks) { unsigned int i; + num_shared_networks++; - for (i = 0; i < num_shared_networks; i++) { + for (i = 0; i < num_shared_networks; i++) free((shared_networks + i)->name); - } free(shared_networks); } } @@ -437,6 +435,7 @@ void __attribute__ ((__noreturn__)) print_version(void) void __attribute__ ((__noreturn__)) usage(int status) { FILE *out; + out = status != 0 ? stderr : stdout; fprintf(out, "\ diff --git a/src/sort.c b/src/sort.c index 666b11e..b01db91 100644 --- a/src/sort.c +++ b/src/sort.c @@ -265,20 +265,16 @@ static int merge(struct range_t *restrict left, struct range_t *restrict right) return (1); continue; } - /* Select which function is pointed by comparer */ comparer = field_selector(config.sort[i]); cmp = comparer(left, right); /* If fields are equal use next sort method */ - if (cmp == 0) { + if (cmp == 0) continue; - } - if (cmp < 0) { + if (cmp < 0) return (1); - } return (0); } - /* If all comparers where equal */ return (0); } @@ -300,23 +296,19 @@ void mergesort_ranges(struct range_t *restrict orig, int size, struct range_t *r for (left = 0; left < size; left++) { hold = *(orig + left); for (right = left - 1; 0 <= right; right--) { - if (merge((orig + right), &hold)) { + if (merge((orig + right), &hold)) break; - } *(orig + right + 1) = *(orig + right); } *(orig + right + 1) = hold; } return; } - mergesort_ranges(orig, size / 2, temp); mergesort_ranges(orig + size / 2, size - size / 2, temp); - left = 0; right = size / 2; i = 0; - while (left < size / 2 && right < size) { if (merge((orig + left), (orig + right))) { *(temp + i) = *(orig + left); @@ -337,6 +329,5 @@ void mergesort_ranges(struct range_t *restrict orig, int size, struct range_t *r right++; i++; } - memcpy(orig, temp, size * sizeof(struct range_t)); }