diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:54:46 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:54:46 +0000 |
commit | cd7b005519ade8ab6c97fcb21590b71b7d1be6e3 (patch) | |
tree | c611a8d0cd5e8f68f41b8c2d16ba580e0f40a38d /rtrlib/lib | |
parent | Initial commit. (diff) | |
download | librtr-cd7b005519ade8ab6c97fcb21590b71b7d1be6e3.tar.xz librtr-cd7b005519ade8ab6c97fcb21590b71b7d1be6e3.zip |
Adding upstream version 0.8.0.upstream/0.8.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | rtrlib/lib/alloc_utils.c | 81 | ||||
-rw-r--r-- | rtrlib/lib/alloc_utils.h | 25 | ||||
-rw-r--r-- | rtrlib/lib/alloc_utils_private.h | 34 | ||||
-rw-r--r-- | rtrlib/lib/convert_byte_order.c | 34 | ||||
-rw-r--r-- | rtrlib/lib/convert_byte_order_private.h | 39 | ||||
-rw-r--r-- | rtrlib/lib/ip.c | 79 | ||||
-rw-r--r-- | rtrlib/lib/ip.h | 87 | ||||
-rw-r--r-- | rtrlib/lib/ip_private.h | 58 | ||||
-rw-r--r-- | rtrlib/lib/ipv4.c | 64 | ||||
-rw-r--r-- | rtrlib/lib/ipv4.h | 23 | ||||
-rw-r--r-- | rtrlib/lib/ipv4_private.h | 79 | ||||
-rw-r--r-- | rtrlib/lib/ipv6.c | 220 | ||||
-rw-r--r-- | rtrlib/lib/ipv6.h | 22 | ||||
-rw-r--r-- | rtrlib/lib/ipv6_private.h | 81 | ||||
-rw-r--r-- | rtrlib/lib/log.c | 48 | ||||
-rw-r--r-- | rtrlib/lib/log_private.h | 19 | ||||
-rw-r--r-- | rtrlib/lib/utils.c | 54 | ||||
-rw-r--r-- | rtrlib/lib/utils_private.h | 34 |
18 files changed, 1081 insertions, 0 deletions
diff --git a/rtrlib/lib/alloc_utils.c b/rtrlib/lib/alloc_utils.c new file mode 100644 index 0000000..e3d6831 --- /dev/null +++ b/rtrlib/lib/alloc_utils.c @@ -0,0 +1,81 @@ +/* + * This file is part of RTRlib. + * + * This file is subject to the terms and conditions of the MIT license. + * See the file LICENSE in the top level directory for more details. + * + * Website: http://rtrlib.realmv6.org/ + */ + +#include "alloc_utils_private.h" + +#include "rtrlib/rtrlib_export_private.h" + +#include <assert.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +static void *(*MALLOC_PTR)(size_t size) = malloc; +static void *(*REALLOC_PTR)(void *ptr, size_t size) = realloc; +static void (*FREE_PTR)(void *ptr) = free; + +/* cppcheck-suppress unusedFunction */ +RTRLIB_EXPORT void lrtr_set_alloc_functions(void *(*malloc_function)(size_t size), + void *(*realloc_function)(void *ptr, size_t size), + void(free_function)(void *ptr)) +{ + MALLOC_PTR = malloc_function; + REALLOC_PTR = realloc_function; + FREE_PTR = free_function; +} + +inline void *lrtr_malloc(size_t size) +{ + return MALLOC_PTR(size); +} + +/* cppcheck-suppress unusedFunction */ +void *lrtr_calloc(size_t nmemb, size_t size) +{ + int bytes = 0; + +#if __GNUC__ >= 5 + if (__builtin_mul_overflow(nmemb, size, &bytes)) { + errno = ENOMEM; + return 0; + } +#else + if (size && nmemb > (size_t)-1 / size) { + errno = ENOMEM; + return 0; + } + bytes = size * nmemb; +#endif + void *p = lrtr_malloc(bytes); + + if (!p) + return p; + + return memset(p, 0, bytes); +} + +inline void lrtr_free(void *ptr) +{ + return FREE_PTR(ptr); +} + +inline void *lrtr_realloc(void *ptr, size_t size) +{ + return REALLOC_PTR(ptr, size); +} + +char *lrtr_strdup(const char *string) +{ + assert(string); + + size_t length = strlen(string) + 1; + char *new_string = lrtr_malloc(length); + + return new_string ? memcpy(new_string, string, length) : NULL; +} diff --git a/rtrlib/lib/alloc_utils.h b/rtrlib/lib/alloc_utils.h new file mode 100644 index 0000000..b265915 --- /dev/null +++ b/rtrlib/lib/alloc_utils.h @@ -0,0 +1,25 @@ +/* + * This file is part of RTRlib. + * + * This file is subject to the terms and conditions of the MIT license. + * See the file LICENSE in the top level directory for more details. + * + * Website: http://rtrlib.realmv6.org/ + */ + +#ifndef LRTR_ALLOC_UTILS_H +#define LRTR_ALLOC_UTILS_H + +#include <stdlib.h> + +/** + * @brief Sets custom malloc, realloc and free function + * that is used throughout rtrlib. + * @param[in] Pointer to malloc function + * @param[in] Pointer to realloc function + * @param[in] Pointer to free function + */ +void lrtr_set_alloc_functions(void *(*malloc_function)(size_t size), void *(*realloc_function)(void *ptr, size_t size), + void (*free_function)(void *ptr)); + +#endif diff --git a/rtrlib/lib/alloc_utils_private.h b/rtrlib/lib/alloc_utils_private.h new file mode 100644 index 0000000..b6c67cc --- /dev/null +++ b/rtrlib/lib/alloc_utils_private.h @@ -0,0 +1,34 @@ +/* + * This file is part of RTRlib. + * + * This file is subject to the terms and conditions of the MIT license. + * See the file LICENSE in the top level directory for more details. + * + * Website: http://rtrlib.realmv6.org/ + */ + +#ifndef LRTR_ALLOC_UTILS_PRIVATE_H +#define LRTR_ALLOC_UTILS_PRIVATE_H + +#include "alloc_utils.h" + +#include <stdlib.h> + +void *lrtr_malloc(size_t size); + +void *lrtr_calloc(size_t nmemb, size_t size); + +void lrtr_free(void *ptr); + +void *lrtr_realloc(void *ptr, size_t size); + +/** + * @brief Duplicates a string + * @pre string != NULL + * @param[in] string + * @returns Duplicated string + * @returns NULL on error + */ +char *lrtr_strdup(const char *string); + +#endif diff --git a/rtrlib/lib/convert_byte_order.c b/rtrlib/lib/convert_byte_order.c new file mode 100644 index 0000000..402c141 --- /dev/null +++ b/rtrlib/lib/convert_byte_order.c @@ -0,0 +1,34 @@ +/* + * This file is part of RTRlib. + * + * This file is subject to the terms and conditions of the MIT license. + * See the file LICENSE in the top level directory for more details. + * + * Website: http://rtrlib.realmv6.org/ + */ + +#include "convert_byte_order_private.h" + +#include <arpa/inet.h> +#include <assert.h> +#include <inttypes.h> + +uint16_t lrtr_convert_short(const enum target_byte_order tbo, const uint16_t value) +{ + if (tbo == TO_NETWORK_BYTE_ORDER) + return htons(value); + else if (tbo == TO_HOST_HOST_BYTE_ORDER) + return ntohs(value); + + assert(0); +} + +uint32_t lrtr_convert_long(const enum target_byte_order tbo, const uint32_t value) +{ + if (tbo == TO_NETWORK_BYTE_ORDER) + return htonl(value); + else if (tbo == TO_HOST_HOST_BYTE_ORDER) + return ntohl(value); + + assert(0); +} diff --git a/rtrlib/lib/convert_byte_order_private.h b/rtrlib/lib/convert_byte_order_private.h new file mode 100644 index 0000000..839f82b --- /dev/null +++ b/rtrlib/lib/convert_byte_order_private.h @@ -0,0 +1,39 @@ +/* + * This file is part of RTRlib. + * + * This file is subject to the terms and conditions of the MIT license. + * See the file LICENSE in the top level directory for more details. + * + * Website: http://rtrlib.realmv6.org/ + */ + +#ifndef LRTR_CONVERT_BYTE_ORDER_PRIVATE_H +#define LRTR_CONVERT_BYTE_ORDER_PRIVATE_H + +#include <inttypes.h> + +/** + * @brief Target byte order for conversion. + */ +enum target_byte_order { + TO_NETWORK_BYTE_ORDER, + TO_HOST_HOST_BYTE_ORDER, +}; + +/** + * Converts the passed short value to the given target byte order. + * @param[in] tbo Target byte order. + * @param[in] value Input (uint16_t) for conversion. + * @result Converted uint16_t value. + */ +uint16_t lrtr_convert_short(const enum target_byte_order tbo, const uint16_t value); + +/** + * Converts the passed long value to the given target byte order. + * @param[in] tbo Target byte order. + * @param[in] value Input (uint32_t) for conversion. + * @result Converted uint32_t value. + */ +uint32_t lrtr_convert_long(const enum target_byte_order tbo, const uint32_t value); + +#endif /* LRTR_CONVERT_BYTE_ORDER_H */ diff --git a/rtrlib/lib/ip.c b/rtrlib/lib/ip.c new file mode 100644 index 0000000..39df774 --- /dev/null +++ b/rtrlib/lib/ip.c @@ -0,0 +1,79 @@ +/* + * This file is part of RTRlib. + * + * This file is subject to the terms and conditions of the MIT license. + * See the file LICENSE in the top level directory for more details. + * + * Website: http://rtrlib.realmv6.org/ + */ + +#include "ip_private.h" + +#include "rtrlib/rtrlib_export_private.h" + +#include <stdbool.h> +#include <string.h> + +bool lrtr_ip_addr_is_zero(const struct lrtr_ip_addr prefix) +{ + if (prefix.ver == LRTR_IPV6) { + if (prefix.u.addr6.addr[0] == 0 && prefix.u.addr6.addr[1] == 0 && prefix.u.addr6.addr[2] == 0 && + prefix.u.addr6.addr[3] == 0) { + return true; + } + } else if (prefix.u.addr4.addr == 0) { + return true; + } + + return false; +} + +struct lrtr_ip_addr lrtr_ip_addr_get_bits(const struct lrtr_ip_addr *val, const uint8_t from, const uint8_t number) +{ + struct lrtr_ip_addr result; + + if (val->ver == LRTR_IPV6) { + result.ver = LRTR_IPV6; + result.u.addr6 = lrtr_ipv6_get_bits(&(val->u.addr6), from, number); + } else { + result.ver = LRTR_IPV4; + result.u.addr4 = lrtr_ipv4_get_bits(&(val->u.addr4), from, number); + } + return result; +} + +RTRLIB_EXPORT bool lrtr_ip_addr_equal(const struct lrtr_ip_addr a, const struct lrtr_ip_addr b) +{ + if (a.ver != b.ver) + return false; + if (a.ver == LRTR_IPV6) + return lrtr_ipv6_addr_equal(&(a.u.addr6), &(b.u.addr6)); + return lrtr_ipv4_addr_equal(&(a.u.addr4), &(b.u.addr4)); +} + +RTRLIB_EXPORT int lrtr_ip_addr_to_str(const struct lrtr_ip_addr *ip, char *str, const unsigned int len) +{ + if (ip->ver == LRTR_IPV6) + return lrtr_ipv6_addr_to_str(&(ip->u.addr6), str, len); + return lrtr_ipv4_addr_to_str(&(ip->u.addr4), str, len); +} + +RTRLIB_EXPORT int lrtr_ip_str_to_addr(const char *str, struct lrtr_ip_addr *ip) +{ + if (!strchr(str, ':')) { + ip->ver = LRTR_IPV4; + return lrtr_ipv4_str_to_addr(str, &(ip->u.addr4)); + } + ip->ver = LRTR_IPV6; + return lrtr_ipv6_str_to_addr(str, &(ip->u.addr6)); +} + +// cppcheck-suppress unusedFunction +RTRLIB_EXPORT bool lrtr_ip_str_cmp(const struct lrtr_ip_addr *addr1, const char *addr2) +{ + struct lrtr_ip_addr tmp; + + if (lrtr_ip_str_to_addr(addr2, &tmp) == -1) + return false; + return lrtr_ip_addr_equal(*addr1, tmp); +} diff --git a/rtrlib/lib/ip.h b/rtrlib/lib/ip.h new file mode 100644 index 0000000..df3bb06 --- /dev/null +++ b/rtrlib/lib/ip.h @@ -0,0 +1,87 @@ +/* + * This file is part of RTRlib. + * + * This file is subject to the terms and conditions of the MIT license. + * See the file LICENSE in the top level directory for more details. + * + * Website: http://rtrlib.realmv6.org/ + */ + +#ifndef LRTR_IP_PUBLIC_H +#define LRTR_IP_PUBLIC_H + +#include "rtrlib/lib/ipv4.h" +#include "rtrlib/lib/ipv6.h" + +#include <stdbool.h> +/** + * @defgroup util_h Utility functions + * @{ + */ + +/** + * @brief Version of the IP protocol. + */ +enum lrtr_ip_version { + /** IPV4 */ + LRTR_IPV4, + + /** LRTR_IPV6 */ + LRTR_IPV6 +}; + +/** + * @brief The lrtr_ip_addr struct stores a IPv4 or IPv6 address in host byte order. + * @param ver Specifies the type of the stored address. + * @param u Union holding a lrtr_ipv4_addr or lrtr_ipv6_addr. + */ +struct lrtr_ip_addr { + enum lrtr_ip_version ver; + union { + struct lrtr_ipv4_addr addr4; + struct lrtr_ipv6_addr addr6; + } u; +}; + +/** + * Converts the passed lrtr_ip_addr struct to string representation. + * @param[in] ip lrtr_ip_addr + * @param[out] str Pointer to a char array. + * The array must be at least INET_ADDRSTRLEN bytes long if the passed lrtr_ip_addr stores an IPv4 address. + * If lrtr_ip_addr stores an IPv6 address, str must be at least INET6_ADDRSTRLEN bytes long. + * @param[in] len Length of the str array. + * @result 0 On success. + * @result -1 On error. + */ +int lrtr_ip_addr_to_str(const struct lrtr_ip_addr *ip, char *str, const unsigned int len); + +/** + * Converts the passed IP address in string representation to an lrtr_ip_addr. + * @param[in] str Pointer to a Null terminated char array. + * @param[out] ip Pointer to a lrtr_ip_addr struct. + * @result 0 On success. + * @result -1 On error. + */ +int lrtr_ip_str_to_addr(const char *str, struct lrtr_ip_addr *ip); + +/** + * + * @brief Checks if two lrtr_ip_addr structs are equal. + * @param[in] a lrtr_ip_addr + * @param[in] b lrtr_ip_addr + * @return true If a == b. + * @return false If a != b. + */ +bool lrtr_ip_addr_equal(const struct lrtr_ip_addr a, const struct lrtr_ip_addr b); + +/** + * Compares addr1 in the lrtr_ip_addr struct with addr2 in string representation. + * @param[in] addr1 lrtr_ip_addr + * @param[in] addr2 IP-address as string + * @return true If a == b + * @return false If a != b + */ +bool lrtr_ip_str_cmp(const struct lrtr_ip_addr *addr1, const char *addr2); + +#endif +/** @} */ diff --git a/rtrlib/lib/ip_private.h b/rtrlib/lib/ip_private.h new file mode 100644 index 0000000..623fd96 --- /dev/null +++ b/rtrlib/lib/ip_private.h @@ -0,0 +1,58 @@ +/* + * This file is part of RTRlib. + * + * This file is subject to the terms and conditions of the MIT license. + * See the file LICENSE in the top level directory for more details. + * + * Website: http://rtrlib.realmv6.org/ + */ + +#ifndef LRTR_IP_PRIVATE_H +#define LRTR_IP_PRIVATE_H + +#include "ip.h" + +#include "rtrlib/lib/ipv4_private.h" +#include "rtrlib/lib/ipv6_private.h" + +/** + * @brief Detects if the lrtr_ip_addr only contains 0 bits. + * @param[in] lrtr_ip_addr + * @returns true If the saved lrtr_ip_addr is 0. + * @returns false If the saved lrtr_ip_addr isn't 0. + */ +bool lrtr_ip_addr_is_zero(const struct lrtr_ip_addr); + +/** + * @brief Extracts number bits from the passed lrtr_ip_addr, starting at bit number from. The bit with the highest + * significance is bit 0. All bits that aren't in the specified range will be 0. + * @param[in] val lrtr_ip_addr + * @param[in] from Position of the first bit that is extracted. + * @param[in] number How many bits will be extracted. + * @returns An lrtr_ipv_addr, where all bits that aren't in the specified range are set to 0. + */ +struct lrtr_ip_addr lrtr_ip_addr_get_bits(const struct lrtr_ip_addr *val, const uint8_t from, const uint8_t number); + +/** + * @defgroup util_h Utility functions + * @{ + * + * @brief Checks if two lrtr_ip_addr structs are equal. + * @param[in] a lrtr_ip_addr + * @param[in] b lrtr_ip_addr + * @return true If a == b. + * @return false If a != b. + */ +bool lrtr_ip_addr_equal(const struct lrtr_ip_addr a, const struct lrtr_ip_addr b); + +/** + * Compares addr1 in the lrtr_ip_addr struct with addr2 in string representation. + * @param[in] addr1 lrtr_ip_addr + * @param[in] addr2 IP-address as string + * @return true If a == b + * @return false If a != b + */ +bool lrtr_ip_str_cmp(const struct lrtr_ip_addr *addr1, const char *addr2); + +#endif +/** @} */ diff --git a/rtrlib/lib/ipv4.c b/rtrlib/lib/ipv4.c new file mode 100644 index 0000000..d7f10e1 --- /dev/null +++ b/rtrlib/lib/ipv4.c @@ -0,0 +1,64 @@ +/* + * This file is part of RTRlib. + * + * This file is subject to the terms and conditions of the MIT license. + * See the file LICENSE in the top level directory for more details. + * + * Website: http://rtrlib.realmv6.org/ + */ + +#include "ipv4_private.h" + +#include "rtrlib/lib/convert_byte_order_private.h" +#include "rtrlib/lib/utils_private.h" + +#include <assert.h> +#include <stdio.h> + +struct lrtr_ipv4_addr lrtr_ipv4_get_bits(const struct lrtr_ipv4_addr *val, const uint8_t from, const uint8_t quantity) +{ + struct lrtr_ipv4_addr result; + + result.addr = lrtr_get_bits(val->addr, from, quantity); + return result; +} + +int lrtr_ipv4_addr_to_str(const struct lrtr_ipv4_addr *ip, char *str, unsigned int len) +{ + uint8_t buff[4]; + + buff[0] = ip->addr >> 24 & 0xff; + buff[1] = ip->addr >> 16 & 0xff; + buff[2] = ip->addr >> 8 & 0xff; + buff[3] = ip->addr & 0xff; + + if (snprintf(str, len, "%hhu.%hhu.%hhu.%hhu", buff[0], buff[1], buff[2], buff[3]) < 0) + return -1; + + return 0; +} + +int lrtr_ipv4_str_to_addr(const char *str, struct lrtr_ipv4_addr *ip) +{ + uint8_t buff[4]; + + if (sscanf(str, "%3hhu.%3hhu.%3hhu.%3hhu", &buff[0], &buff[1], &buff[2], &buff[3]) != 4) + return -1; + + ip->addr = buff[0] << 24 | buff[1] << 16 | buff[2] << 8 | buff[3]; + + return 0; +} + +bool lrtr_ipv4_addr_equal(const struct lrtr_ipv4_addr *a, const struct lrtr_ipv4_addr *b) +{ + if (a->addr == b->addr) + return true; + + return false; +} + +void lrtr_ipv4_addr_convert_byte_order(const uint32_t src, uint32_t *dest, const enum target_byte_order tbo) +{ + *dest = lrtr_convert_long(tbo, src); +} diff --git a/rtrlib/lib/ipv4.h b/rtrlib/lib/ipv4.h new file mode 100644 index 0000000..9aff5aa --- /dev/null +++ b/rtrlib/lib/ipv4.h @@ -0,0 +1,23 @@ +/* + * This file is part of RTRlib. + * + * This file is subject to the terms and conditions of the MIT license. + * See the file LICENSE in the top level directory for more details. + * + * Website: http://rtrlib.realmv6.org/ + */ + +#ifndef LRTR_IPV4_H +#define LRTR_IPV4_H + +#include <stdint.h> + +/** + * @brief Struct storing an IPv4 address in host byte order. + * @param addr The IPv4 address. + */ +struct lrtr_ipv4_addr { + uint32_t addr; +}; + +#endif diff --git a/rtrlib/lib/ipv4_private.h b/rtrlib/lib/ipv4_private.h new file mode 100644 index 0000000..73d0170 --- /dev/null +++ b/rtrlib/lib/ipv4_private.h @@ -0,0 +1,79 @@ +/* + * This file is part of RTRlib. + * + * This file is subject to the terms and conditions of the MIT license. + * See the file LICENSE in the top level directory for more details. + * + * Website: http://rtrlib.realmv6.org/ + */ + +#ifndef LRTR_IPV4_PRIVATE_H +#define LRTR_IPV4_PRIVATE_H + +#include "ipv4.h" + +#include "rtrlib/lib/convert_byte_order_private.h" + +#include <inttypes.h> +#include <stdbool.h> + +/** + * @brief Extracts number bits from the passed ipv4_addr, + * + * Starting at bit number from. The bit with the highest significance is bit 0. + * All bits that aren't in the specified range will be 0. + * + * @param[in] val ipv4_addr + * @param[in] from Position of the first bit that is extracted. + * @param[in] number How many bits will be extracted. + * + * @returns An ipv4_addr, with all bits not in the specified range set to 0. + */ +struct lrtr_ipv4_addr lrtr_ipv4_get_bits(const struct lrtr_ipv4_addr *val, const uint8_t from, const uint8_t number); + +/** + * @brief Converts ab IPv4 address from string to ipv4_addr struct. + * + * @param[in] str Pointer to a string buffer. + * @param[out] ip ipv4_addr + * + * @result 0 on success + * @result -1 on error + */ +int lrtr_ipv4_str_to_addr(const char *str, struct lrtr_ipv4_addr *ip); + +/** + * @brief Converts an ipv4_addr struct to its string representation. + * + * @param[in] ip ipv4_addr + * @param[out] str Pointer to a string buffer, of at least INET_ADDRSTRLEN. + * @param[in] length of *str + * + * @result 0 on success + * @result -1 on error + */ +int lrtr_ipv4_addr_to_str(const struct lrtr_ipv4_addr *ip, char *str, const unsigned int len); + +/** + * @brief Compares two ipv4_addr structs. + * + * @param[in] a ipv4_addr + * @param[in] b ipv4_addr + * + * @return true if a == b + * @return false if a != b + */ +bool lrtr_ipv4_addr_equal(const struct lrtr_ipv4_addr *a, const struct lrtr_ipv4_addr *b); + +/** + * @ingroup util_h[{ + * @brief Converts the passed IPv4 address to given byte order. + * + * @param[in] src IPv4 address in source byte order. + * @param[out] dest IPv4 address in target byte order. + * @param[in] tbo Target byte order for address conversion. + * } + */ +void lrtr_ipv4_addr_convert_byte_order(const uint32_t src, uint32_t *dest, const enum target_byte_order tbo); + +#endif diff --git a/rtrlib/lib/ipv6.c b/rtrlib/lib/ipv6.c new file mode 100644 index 0000000..5034c3c --- /dev/null +++ b/rtrlib/lib/ipv6.c @@ -0,0 +1,220 @@ +/* + * This file is part of RTRlib. + * + * This file is subject to the terms and conditions of the MIT license. + * See the file LICENSE in the top level directory for more details. + * + * Website: http://rtrlib.realmv6.org/ + */ + +#include "ipv6_private.h" + +#include "rtrlib/lib/convert_byte_order_private.h" +#include "rtrlib/lib/ipv4_private.h" +#include "rtrlib/lib/utils_private.h" + +#include <arpa/inet.h> +#include <assert.h> +#include <stdio.h> +#include <string.h> + +inline bool lrtr_ipv6_addr_equal(const struct lrtr_ipv6_addr *a, const struct lrtr_ipv6_addr *b) +{ + if (a->addr[0] == b->addr[0] && a->addr[1] == b->addr[1] && a->addr[2] == b->addr[2] && + a->addr[3] == b->addr[3]) + return true; + return false; +} + +struct lrtr_ipv6_addr lrtr_ipv6_get_bits(const struct lrtr_ipv6_addr *val, const uint8_t first_bit, + const uint8_t quantity) +{ + assert(first_bit <= 127); + assert(quantity <= 128); + assert(first_bit + quantity <= 128); + + // if no bytes get extracted the result has to be 0 + struct lrtr_ipv6_addr result; + + memset(&result, 0, sizeof(result)); + + uint8_t bits_left = quantity; + + if (first_bit <= 31) { + const uint8_t q = quantity > 32 ? 32 : quantity; + + assert(bits_left >= q); + bits_left -= q; + result.addr[0] = lrtr_get_bits(val->addr[0], first_bit, q); + } + + if ((first_bit <= 63) && ((first_bit + quantity) > 32)) { + const uint8_t fr = first_bit < 32 ? 0 : first_bit - 32; + const uint8_t q = bits_left > 32 ? 32 : bits_left; + + assert(bits_left >= q); + bits_left -= q; + result.addr[1] = lrtr_get_bits(val->addr[1], fr, q); + } + + if ((first_bit <= 95) && ((first_bit + quantity) > 64)) { + const uint8_t fr = first_bit < 64 ? 0 : first_bit - 64; + const uint8_t q = bits_left > 32 ? 32 : bits_left; + + assert(bits_left >= q); + bits_left -= q; + result.addr[2] = lrtr_get_bits(val->addr[2], fr, q); + } + + if ((first_bit <= 127) && ((first_bit + quantity) > 96)) { + const uint8_t fr = first_bit < 96 ? 0 : first_bit - 127; + const uint8_t q = bits_left > 32 ? 32 : bits_left; + + assert(bits_left >= q); + result.addr[3] = lrtr_get_bits(val->addr[3], fr, q); + } + return result; +} + +/* + * This function was copied from the bird routing daemon's ip_pton(..) function. + */ +int lrtr_ipv6_str_to_addr(const char *a, struct lrtr_ipv6_addr *ip) +{ + uint32_t *o = ip->addr; + uint16_t words[8]; + int i, j, k, l, hfil; + const char *start; + + if (a[0] == ':') { /* Leading :: */ + if (a[1] != ':') + return -1; + a++; + } + hfil = -1; + i = 0; + while (*a) { + if (*a == ':') { /* :: */ + if (hfil >= 0) + return -1; + hfil = i; + a++; + continue; + } + j = 0; + l = 0; + start = a; + for (;;) { + if (*a >= '0' && *a <= '9') + k = *a++ - '0'; + else if (*a >= 'A' && *a <= 'F') + k = *a++ - 'A' + 10; + else if (*a >= 'a' && *a <= 'f') + k = *a++ - 'a' + 10; + else + break; + j = (j << 4) + k; + if (j >= 0x10000 || ++l > 4) + return -1; + } + if (*a == ':' && a[1]) { + a++; + } else if (*a == '.' && (i == 6 || (i < 6 && hfil >= 0))) { /* Embedded IPv4 address */ + struct lrtr_ipv4_addr addr4; + + if (lrtr_ipv4_str_to_addr(start, &addr4) == -1) + return -1; + words[i++] = addr4.addr >> 16; + words[i++] = addr4.addr; + break; + } else if (*a) { + return -1; + } + if (i >= 8) + return -1; + words[i++] = j; + } + + /* Replace :: with an appropriate quantity of zeros */ + if (hfil >= 0) { + j = 8 - i; + for (i = 7; i - j >= hfil; i--) + words[i] = words[i - j]; + for (; i >= hfil; i--) + words[i] = 0; + } + + /* Convert the address to lrtr_ip_addr format */ + for (i = 0; i < 4; i++) + o[i] = (words[2 * i] << 16) | words[2 * i + 1]; + return 0; +} + +/* + * This function was copied from the bird routing daemon's ip_ntop(..) function. + */ +int lrtr_ipv6_addr_to_str(const struct lrtr_ipv6_addr *ip_addr, char *b, const unsigned int len) +{ + if (len < INET6_ADDRSTRLEN) + return -1; + const uint32_t *a = ip_addr->addr; + uint16_t words[8]; + int bestpos = 0; + int bestlen = 0; + int curpos = 0; + int curlen = 0; + int i; + + /* First of all, preprocess the address and find the longest run of zeros */ + for (i = 0; i < 8; i++) { + uint32_t x = a[i / 2]; + + words[i] = ((i % 2) ? x : (x >> 16)) & 0xffff; + if (words[i]) { + curlen = 0; + } else { + if (!curlen) + curpos = i; + curlen++; + if (curlen > bestlen) { + bestpos = curpos; + bestlen = curlen; + } + } + } + if (bestlen < 2) + bestpos = -1; + + /* Is it an encapsulated IPv4 address? */ + if (!bestpos && ((bestlen == 5 && a[2] == 0xffff) || bestlen == 6)) + // if (!bestpos && ((bestlen == 5 && (a[2] == 0xffff)) || bestlen == 6)) + { + uint32_t x = a[3]; + + b += sprintf(b, "::%s%d.%d.%d.%d", a[2] ? "ffff:" : "", ((x >> 24) & 0xff), ((x >> 16) & 0xff), + ((x >> 8) & 0xff), (x & 0xff)); + return 0; + } + + /* Normal IPv6 formatting, compress the largest sequence of zeros */ + for (i = 0; i < 8; i++) { + if (i == bestpos) { + i += bestlen - 1; + *b++ = ':'; + if (i == 7) + *b++ = ':'; + } else { + if (i) + *b++ = ':'; + b += sprintf(b, "%x", words[i]); + } + } + *b = '\0'; + return 0; +} + +void lrtr_ipv6_addr_convert_byte_order(const uint32_t *src, uint32_t *dest, const enum target_byte_order tbo) +{ + for (int i = 0; i < 4; i++) + dest[i] = lrtr_convert_long(tbo, src[i]); +} diff --git a/rtrlib/lib/ipv6.h b/rtrlib/lib/ipv6.h new file mode 100644 index 0000000..6be7485 --- /dev/null +++ b/rtrlib/lib/ipv6.h @@ -0,0 +1,22 @@ +/* + * This file is part of RTRlib. + * + * This file is subject to the terms and conditions of the MIT license. + * See the file LICENSE in the top level directory for more details. + * + * Website: http://rtrlib.realmv6.org/ + */ + +#ifndef LRTR_IPV6_PUBLIC_H +#define LRTR_IPV6_PUBLIC_H + +#include <stdint.h> + +/** + * @brief Struct holding an IPv6 address in host byte order. + */ +struct lrtr_ipv6_addr { + uint32_t addr[4]; /**< The IPv6 address. */ +}; + +#endif /* LRTR_IPV6_PUBLIC_H */ diff --git a/rtrlib/lib/ipv6_private.h b/rtrlib/lib/ipv6_private.h new file mode 100644 index 0000000..1007e73 --- /dev/null +++ b/rtrlib/lib/ipv6_private.h @@ -0,0 +1,81 @@ +/* + * This file is part of RTRlib. + * + * This file is subject to the terms and conditions of the MIT license. + * See the file LICENSE in the top level directory for more details. + * + * Website: http://rtrlib.realmv6.org/ + */ + +#ifndef LRTR_IPV6_PRIVATE_H +#define LRTR_IPV6_PRIVATE_H + +#include "ipv6.h" + +#include "rtrlib/lib/convert_byte_order_private.h" + +#include <stdbool.h> +#include <stdint.h> +#include <sys/types.h> + +/** + * @brief Compares two lrtr_ipv6_addr structs + * + * @param[in] a lrtr_ipv6_addr + * @param[in] b lrtr_ipv6_addr + * + * @return true if a == b + * @return false if a != b + */ +bool lrtr_ipv6_addr_equal(const struct lrtr_ipv6_addr *a, const struct lrtr_ipv6_addr *b); + +/** + * @brief Extracts quantity bits from an IPv6 address. + * + * The bit with the highest significance is bit 0. All bits that aren't in the + * specified range will be 0. + * + * @param[in] val ipv6_addr + * @param[in] first_bit Position of the first bit that is extracted, inclusive. + * @param[in] quantity How many bits will be extracted. + * + * @returns ipv6_addr, with all bits not in specified range set to 0. + */ +struct lrtr_ipv6_addr lrtr_ipv6_get_bits(const struct lrtr_ipv6_addr *val, const uint8_t first_bit, + const uint8_t quantity); + +/** + * @brief Converts the passed ipv6_addr to string representation + * + * @param[in] ip_addr Pointer to an IPv6 address + * @param[out] str Pointer to string buf, at least INET6_ADDRSTRLEN bytes. + * @param[in] len Length of string buffer @p str + * + * @result 0 on success + * @result -1 on error + */ +int lrtr_ipv6_addr_to_str(const struct lrtr_ipv6_addr *ip, char *str, const unsigned int len); + +/** + * @brief Converts the passed IPv6 address string in to lrtr_ipv6_addr struct. + * + * @param[in] str Pointer to a string buffer + * @param[out] ip Pointer to lrtr_ipv6_addr + * + * @result 0 on success + * @result -1 on error + */ +int lrtr_ipv6_str_to_addr(const char *str, struct lrtr_ipv6_addr *ip); + +/** + * @ingroup util_h + * @{ + * @brief Converts the passed IPv6 address to given byte order. + * + * @param[in] src IPv6 address (uint32_t array) in source byte order. + * @param[out] dest IPv6 address (uint32_t array) in target byte order. + * @param[in] tbo Target byte order for address conversion. + */ +void lrtr_ipv6_addr_convert_byte_order(const uint32_t *src, uint32_t *dest, const enum target_byte_order tbo); +/** @} */ +#endif /* LRTR_IPV6_H */ diff --git a/rtrlib/lib/log.c b/rtrlib/lib/log.c new file mode 100644 index 0000000..6ceaaa3 --- /dev/null +++ b/rtrlib/lib/log.c @@ -0,0 +1,48 @@ +/* + * This file is part of RTRlib. + * + * This file is subject to the terms and conditions of the MIT license. + * See the file LICENSE in the top level directory for more details. + * + * Website: http://rtrlib.realmv6.org/ + */ + +#include "log_private.h" + +#include <arpa/inet.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <sys/time.h> +#include <time.h> + +void lrtr_dbg(const char *frmt, ...) +{ +#ifndef NDEBUG + va_list argptr; + struct timeval tv; + struct timezone tz; + + va_start(argptr, frmt); + + bool fail = true; + + if (gettimeofday(&tv, &tz) == 0) { + struct tm tm; + + if (localtime_r(&tv.tv_sec, &tm)) { + fprintf(stderr, "(%04d/%02d/%02d %02d:%02d:%02d:%06ld): ", tm.tm_year + 1900, tm.tm_mon + 1, + tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, tv.tv_usec); + fail = false; + } + } + + if (fail) + fprintf(stderr, "(%jd): ", (intmax_t)time(0)); + + vfprintf(stderr, frmt, argptr); + fprintf(stderr, "\n"); + va_end(argptr); +#endif +} diff --git a/rtrlib/lib/log_private.h b/rtrlib/lib/log_private.h new file mode 100644 index 0000000..e33ebf3 --- /dev/null +++ b/rtrlib/lib/log_private.h @@ -0,0 +1,19 @@ +/* + * This file is part of RTRlib. + * + * This file is subject to the terms and conditions of the MIT license. + * See the file LICENSE in the top level directory for more details. + * + * Website: http://rtrlib.realmv6.org/ + */ + +#ifndef LRTR_LOG_PRIVATE_H +#define LRTR_LOG_PRIVATE_H + +/** + * @brief Writes a message to stdout if NDEBUG isn't defined. + * @param[in] frmt log message in printf format style. + */ +void lrtr_dbg(const char *frmt, ...) __attribute__((format(printf, 1, 2))); + +#endif diff --git a/rtrlib/lib/utils.c b/rtrlib/lib/utils.c new file mode 100644 index 0000000..ca708e9 --- /dev/null +++ b/rtrlib/lib/utils.c @@ -0,0 +1,54 @@ +/* + * This file is part of RTRlib. + * + * This file is subject to the terms and conditions of the MIT license. + * See the file LICENSE in the top level directory for more details. + * + * Website: http://rtrlib.realmv6.org/ + */ + +#include "utils_private.h" + +#include <assert.h> +#include <stdint.h> +#include <time.h> + +#ifdef __MACH__ +#include <mach/mach_time.h> +static double timeconvert = 0.0; +#endif + +int lrtr_get_monotonic_time(time_t *seconds) +{ +#ifdef __MACH__ + if (timeconvert == 0.0) { + mach_timebase_info_data_t time_base; + (void)mach_timebase_info(&time_base); + timeconvert = (double)time_base.numer / (double)time_base.denom / 1000000000.0; + } + *seconds = (time_t)mach_absolute_time() * timeconvert; +#else + struct timespec time; + + if (clock_gettime(CLOCK_MONOTONIC, &time) == -1) + return -1; + *seconds = time.tv_sec; + if ((time.tv_nsec * 1000000000) >= 5) + *seconds += 1; +#endif + return 0; +} + +uint32_t lrtr_get_bits(const uint32_t val, const uint8_t from, const uint8_t number) +{ + assert(number < 33); + assert(number > 0); + + uint32_t mask = ~0; + + if (number != 32) + mask = ~(mask >> number); + + mask >>= from; + return (mask & val); +} diff --git a/rtrlib/lib/utils_private.h b/rtrlib/lib/utils_private.h new file mode 100644 index 0000000..40e99ee --- /dev/null +++ b/rtrlib/lib/utils_private.h @@ -0,0 +1,34 @@ +/* + * This file is part of RTRlib. + * + * This file is subject to the terms and conditions of the MIT license. + * See the file LICENSE in the top level directory for more details. + * + * Website: http://rtrlib.realmv6.org/ + */ + +#ifndef LRTR_UTILS_PRIVATE_H +#define LRTR_UTILS_PRIVATE_H + +#include <stdint.h> +#include <time.h> + +/** + * @brief Returns the current time of the CLOCK_MONOTONIC clock. + * @param[in] seconds Time in seconds since some unspecified starting point. + * @return 0 on successs + * @return -1 on error + */ +int lrtr_get_monotonic_time(time_t *seconds); + +/** + * @brief Extracts number bits from the passed uint32_t, starting at bit number from. The bit with the highest + * significance is bit 0. All bits that aren't in the specified range will be 0. + * @param[in] val uint32_t + * @param[in] from Position of the first bit that is extracted. + * @param[in] number How many bits will be extracted. + * @returns a uint32_t, where all bits that aren't in the specified range are set to 0. + */ +uint32_t lrtr_get_bits(const uint32_t val, const uint8_t from, const uint8_t number); + +#endif |