summaryrefslogtreecommitdiffstats
path: root/lib/utils.h
diff options
context:
space:
mode:
authorOto Šťáva <oto.stava@nic.cz>2022-04-29 08:50:35 +0200
committerVladimír Čunát <vladimir.cunat@nic.cz>2022-05-02 12:17:49 +0200
commit08d66491af0123d9b4af4fee38e8a8b27bd80a71 (patch)
treec6e58ac7b73c795d9b16f4a99174cda2dd222204 /lib/utils.h
parentMerge branch !1285: daemon/zimport: close transaction after importing batch (diff)
downloadknot-resolver-08d66491af0123d9b4af4fee38e8a8b27bd80a71.tar.xz
knot-resolver-08d66491af0123d9b4af4fee38e8a8b27bd80a71.zip
lib/utils: sockaddr key generation
Diffstat (limited to '')
-rw-r--r--lib/utils.h36
1 files changed, 35 insertions, 1 deletions
diff --git a/lib/utils.h b/lib/utils.h
index cdcda131..d9aadfa1 100644
--- a/lib/utils.h
+++ b/lib/utils.h
@@ -28,10 +28,15 @@
#include "lib/generic/array.h"
#include "lib/log.h"
-
/** When knot_pkt is passed from cache without ->wire, this is the ->size. */
static const size_t KR_PKT_SIZE_NOWIRE = -1;
+/** Used for reserving enough space for the `kr_sockaddr_key` function
+ * output. */
+struct kr_sockaddr_key_storage {
+ char bytes[sizeof(struct sockaddr_storage)];
+};
+
/*
* Logging and debugging.
@@ -262,6 +267,22 @@ int kr_inaddr_len(const struct sockaddr *addr);
/** Sockaddr length for given family, i.e. sizeof(struct sockaddr_in*). */
KR_EXPORT KR_PURE
int kr_sockaddr_len(const struct sockaddr *addr);
+
+/** Creates a packed structure from the specified `addr`, safe for use as a key
+ * in containers like `trie_t`, and writes it into `dst`. On success, returns
+ * the actual length of the key.
+ *
+ * Returns `kr_error(EAFNOSUPPORT)` if the family of `addr` is unsupported. */
+KR_EXPORT
+ssize_t kr_sockaddr_key(struct kr_sockaddr_key_storage *dst,
+ const struct sockaddr *addr);
+
+/** Creates a `struct sockaddr` from the specified `key` created using the
+ * `kr_sockaddr_key()` function. */
+KR_EXPORT
+struct sockaddr *kr_sockaddr_from_key(struct sockaddr_storage *dst,
+ const char *key);
+
/** Compare two given sockaddr.
* return 0 - addresses are equal, error code otherwise.
*/
@@ -353,6 +374,19 @@ int kr_bitcmp(const char *a, const char *b, int bits);
KR_EXPORT
void kr_bitmask(unsigned char *a, size_t a_len, int bits);
+/** Check whether `addr` points to an `AF_INET6` address and whether the address
+ * is link-local. */
+static inline bool kr_sockaddr_link_local(const struct sockaddr *addr)
+{
+ if (addr->sa_family != AF_INET6)
+ return false;
+
+ /* Link-local: https://tools.ietf.org/html/rfc4291#section-2.4 */
+ const uint8_t prefix[] = { 0xFE, 0x80 };
+ const struct sockaddr_in6 *ip6 = (const struct sockaddr_in6 *) addr;
+ return kr_bitcmp((char *) ip6->sin6_addr.s6_addr, (char *) prefix, 10) == 0;
+}
+
/** @internal RR map flags. */
static const uint8_t KEY_FLAG_RRSIG = 0x02;
static inline uint8_t KEY_FLAG_RANK(const char *key)