diff --git a/src/dhcpd-pools.c b/src/dhcpd-pools.c index 692c4ff..c50fcfb 100644 --- a/src/dhcpd-pools.c +++ b/src/dhcpd-pools.c @@ -248,7 +248,7 @@ int main(int argc, char **argv) /* Do the job */ prepare_memory(); - xstrstr = xstrstr_init; + set_ipv_functions(VERSION_UNKNOWN); parse_config(true, config.dhcpdconf_file, shared_networks); parse_leases(); diff --git a/src/dhcpd-pools.h b/src/dhcpd-pools.h index 5068380..29d5e4c 100644 --- a/src/dhcpd-pools.h +++ b/src/dhcpd-pools.h @@ -189,6 +189,7 @@ unsigned int RANGES; /* Function prototypes */ int prepare_memory(void); +void set_ipv_functions(int version); int parse_leases(void); void parse_config(int, const char *__restrict, struct shared_network_t *__restrict) @@ -199,11 +200,26 @@ 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); -double get_range_size(const struct range_t *r); +int (*parse_ipaddr)(const char *restrict src, union ipaddr_t *restrict dst); +int parse_ipaddr_init(const char *restrict src, union ipaddr_t *restrict dst); +int parse_ipaddr_v4(const char *restrict src, union ipaddr_t *restrict dst); +int parse_ipaddr_v6(const char *restrict src, union ipaddr_t *restrict dst); + +void (*copy_ipaddr)(union ipaddr_t *restrict dst, const union ipaddr_t *restrict src); +void copy_ipaddr_init(union ipaddr_t *restrict dst, const union ipaddr_t *restrict src); +void copy_ipaddr_v4(union ipaddr_t *restrict dst, const union ipaddr_t *restrict src); +void copy_ipaddr_v6(union ipaddr_t *restrict dst, const union ipaddr_t *restrict src); + +const char *(*ntop_ipaddr)(const union ipaddr_t *ip); +const char *ntop_ipaddr_init(const union ipaddr_t *ip); +const char *ntop_ipaddr_v4(const union ipaddr_t *ip); +const char *ntop_ipaddr_v6(const union ipaddr_t *ip); + +double (*get_range_size)(const struct range_t *r); +double get_range_size_init(const struct range_t *r); +double get_range_size_v4(const struct range_t *r); +double get_range_size_v6(const struct range_t *r); + int (*xstrstr)(const char *__restrict str); int xstrstr_init(const char *__restrict str) # if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) @@ -227,7 +243,11 @@ void print_version(void) __attribute__ ((noreturn)); void usage(int status) __attribute__ ((noreturn)); /* qsort required functions... */ /* ...for ranges and... */ -int ipcomp(const union ipaddr_t *restrict a, const union ipaddr_t *restrict b); +int (*ipcomp)(const union ipaddr_t *restrict a, const union ipaddr_t *restrict b); +int ipcomp_init(const union ipaddr_t *restrict a, const union ipaddr_t *restrict b); +int ipcomp_v4(const union ipaddr_t *restrict a, const union ipaddr_t *restrict b); +int ipcomp_v6(const union ipaddr_t *restrict a, const union ipaddr_t *restrict b); + int comp_cur(struct range_t *r1, struct range_t *r2); int comp_double(double f1, double f2); int comp_ip(struct range_t *r1, struct range_t *r2); @@ -258,8 +278,16 @@ int output_alarming(void); /* Memory release, file closing etc */ void clean_up(void); /* Hash functions */ -void add_lease(union ipaddr_t *ip, enum ltype type); -struct leases_t *find_lease(union ipaddr_t *ip); +void (*add_lease)(union ipaddr_t *ip, enum ltype type); +void add_lease_init(union ipaddr_t *ip, enum ltype type); +void add_lease_v4(union ipaddr_t *ip, enum ltype type); +void add_lease_v6(union ipaddr_t *ip, enum ltype type); + +struct leases_t *(*find_lease)(union ipaddr_t *ip); +struct leases_t *find_lease_init(union ipaddr_t *ip); +struct leases_t *find_lease_v4(union ipaddr_t *ip); +struct leases_t *find_lease_v6(union ipaddr_t *ip); + void delete_lease(struct leases_t *lease); void delete_all_leases(void); diff --git a/src/hash.c b/src/hash.c index d9a1d77..d598b74 100644 --- a/src/hash.c +++ b/src/hash.c @@ -47,17 +47,27 @@ /*! \brief Add a lease to hash array. * \param addr Binary IP to be added in leases hash. * \param type Lease state of the IP. */ -void add_lease(union ipaddr_t *addr, enum ltype type) +void add_lease_init(union ipaddr_t *addr __attribute__((unused)), enum ltype type __attribute__((unused))) +{ +} + +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; - if (config.dhcp_version == VERSION_6) { - HASH_ADD_V6(leases, ip.v6, l); - } else { - HASH_ADD_INT(leases, ip.v4, l); - } + HASH_ADD_INT(leases, ip.v4, l); + l->ethernet = NULL; +} + +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; + HASH_ADD_V6(leases, ip.v6, l); l->ethernet = NULL; } @@ -65,15 +75,22 @@ void add_lease(union ipaddr_t *addr, enum ltype type) * \param addr Binary IP searched from leases hash. * \return A lease structure about requested IP, or NULL. */ -struct leases_t *find_lease(union ipaddr_t *addr) +struct leases_t *find_lease_init(union ipaddr_t *addr __attribute__((unused))) +{ + return NULL; +} + +struct leases_t *find_lease_v4(union ipaddr_t *addr) { struct leases_t *l; + HASH_FIND_INT(leases, &addr->v4, l); + return l; +} - if (config.dhcp_version == VERSION_6) { - HASH_FIND_V6(leases, &addr->v6, l); - } else { - HASH_FIND_INT(leases, &addr->v4, l); - } +struct leases_t *find_lease_v6(union ipaddr_t *addr) +{ + struct leases_t *l; + HASH_FIND_V6(leases, &addr->v4, l); return l; } diff --git a/src/other.c b/src/other.c index 4e56e86..75158a0 100644 --- a/src/other.c +++ b/src/other.c @@ -55,36 +55,90 @@ #include #include +/*! \brief Set function pointers depending on IP version. + * \param ip IP version. + */ +void set_ipv_functions(int version) +{ + switch (version) { + + case VERSION_4: + config.dhcp_version = version; + add_lease = add_lease_v4; + copy_ipaddr = copy_ipaddr_v4; + find_lease = find_lease_v4; + get_range_size = get_range_size_v4; + ipcomp = ipcomp_v4; + ntop_ipaddr = ntop_ipaddr_v4; + parse_ipaddr = parse_ipaddr_v4; + xstrstr = xstrstr_v4; + break; + + case VERSION_6: + config.dhcp_version = version; + add_lease = add_lease_v6; + copy_ipaddr = copy_ipaddr_v6; + find_lease = find_lease_v6; + get_range_size = get_range_size_v6; + ipcomp = ipcomp_v6; + ntop_ipaddr = ntop_ipaddr_v6; + parse_ipaddr = parse_ipaddr_v6; + xstrstr = xstrstr_v6; + break; + + case VERSION_UNKNOWN: + config.dhcp_version = version; + add_lease = add_lease_init; + copy_ipaddr = copy_ipaddr_init; + find_lease = find_lease_init; + get_range_size = get_range_size_init; + ipcomp = ipcomp_init; + ntop_ipaddr = ntop_ipaddr_init; + parse_ipaddr = parse_ipaddr_init; + xstrstr = xstrstr_init; + break; + + default: + abort(); + + } + return; +} + /*! \brief Convert text string IP address from either IPv4 or IPv6 to an integer. * \param src An IP string in either format. * \param dst An union which will hold conversion result. * \return Was parsing successful. */ -int parse_ipaddr(const char *restrict src, union ipaddr_t *restrict dst) +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) { + set_ipv_functions(VERSION_4); + } else if (inet_pton(AF_INET6, src, &addr6) == 1) { + set_ipv_functions(VERSION_6); + } else { + return 0; + } + return parse_ipaddr(src, dst); +} + +int parse_ipaddr_v4(const char *restrict src, union ipaddr_t *restrict dst) { int rv; - if (config.dhcp_version == VERSION_UNKNOWN) { - struct in_addr addr; - struct in6_addr addr6; - if (inet_aton(src, &addr) == 1) { - config.dhcp_version = VERSION_4; - xstrstr = xstrstr_v4; - } else if (inet_pton(AF_INET6, src, &addr6) == 1) { - config.dhcp_version = VERSION_6; - xstrstr = xstrstr_v6; - } else { - return 0; - } - } - if (config.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); - } + struct in_addr addr; + rv = inet_aton(src, &addr); + dst->v4 = ntohl(addr.s_addr); + return rv == 1; +} + +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; } @@ -92,14 +146,21 @@ int parse_ipaddr(const char *restrict src, union ipaddr_t *restrict dst) * * \param dst Destination for a binary IP address. * \param src Sourse of an IP address. */ -void copy_ipaddr(union ipaddr_t *restrict dst, +void copy_ipaddr_init(union ipaddr_t *restrict dst __attribute__((unused)), + const union ipaddr_t *restrict src __attribute__((unused))) +{ +} + +void copy_ipaddr_v4(union ipaddr_t *restrict dst, + const union ipaddr_t *restrict src) +{ + dst->v4 = src->v4; +} + +void copy_ipaddr_v6(union ipaddr_t *restrict dst, const union ipaddr_t *restrict src) { - if (config.dhcp_version == VERSION_6) { - memcpy(&dst->v6, &src->v6, sizeof(src->v6)); - } else { - dst->v4 = src->v4; - } + memcpy(&dst->v6, &src->v6, sizeof(src->v6)); } /*! \brief Convert an address to string. This function will convert the @@ -110,19 +171,27 @@ void copy_ipaddr(union ipaddr_t *restrict dst, * \param ip Binary IP address. * \return Printable address. */ -const char *ntop_ipaddr(const union ipaddr_t *ip) +const char *ntop_ipaddr_init(const union ipaddr_t *ip __attribute__((unused))) +{ + static char buffer = '\0'; + return &buffer; +} + +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)); +} + +const char *ntop_ipaddr_v6(const union ipaddr_t *ip) { static char buffer[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")]; - if (config.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)); - } + struct in6_addr addr; + memcpy(addr.s6_addr, ip->v6, sizeof(addr.s6_addr)); + return inet_ntop(AF_INET6, &addr, buffer, sizeof(buffer)); } /*! \brief Calculate how many addresses there are in a range. @@ -131,23 +200,28 @@ const char *ntop_ipaddr(const union ipaddr_t *ip) * and last IP in the range. * \return Size of a range. */ -double get_range_size(const struct range_t *r) +double get_range_size_init(const struct range_t *r __attribute__((unused))) { - if (config.dhcp_version == VERSION_6) { - 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... */ - for (i = 0; i < 16; i++) { - size *= 256; - size += (int)r->last_ip.v6[i] - (int)r->first_ip.v6[i]; - } - return size + 1; - } else { - return r->last_ip.v4 - r->first_ip.v4 + 1; + return 0; +} + +double get_range_size_v4(const struct range_t *r) +{ + return r->last_ip.v4 - r->first_ip.v4 + 1; +} + +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... */ + for (i = 0; i < 16; i++) { + size *= 256; + size += (int)r->last_ip.v6[i] - (int)r->first_ip.v6[i]; } + return size + 1; } /*! \fn xstrstr_init(const char *restrict str) @@ -164,12 +238,10 @@ int xstrstr_init(const char *restrict str) { if (memcmp("lease ", str, 6)) { - config.dhcp_version = VERSION_4; - xstrstr = xstrstr_v4; + set_ipv_functions(VERSION_4); return PREFIX_LEASE; } else if (memcmp(" iaaddr ", str, 9)) { - config.dhcp_version = VERSION_6; - xstrstr = xstrstr_v6; + set_ipv_functions(VERSION_6); return PREFIX_LEASE; } return NUM_OF_PREFIX; diff --git a/src/sort.c b/src/sort.c index badb2ab..a2eaa18 100644 --- a/src/sort.c +++ b/src/sort.c @@ -54,17 +54,26 @@ * \param b Binary IP address. * \return If a < b return -1, if a < b return 1, when they are equal return 0. */ -int ipcomp(const union ipaddr_t *restrict a, const union ipaddr_t *restrict b) +int ipcomp_init(const union ipaddr_t *restrict a __attribute__((unused)), + const union ipaddr_t *restrict b __attribute__((unused))) { - if (config.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; - } + return 0; +} + +int ipcomp_v4(const union ipaddr_t *restrict a, + const union ipaddr_t *restrict b) +{ + if (a->v4 < b->v4) + return -1; + if (a->v4 > b->v4) + return 1; + return 0; +} + +int ipcomp_v6(const union ipaddr_t *restrict a, + const union ipaddr_t *restrict b) +{ + return memcmp(&a->v6, &b->v6, sizeof(a->v6)); } /*! \brief Compare IP address in leases. Suitable for sorting range table.