return 1;
}
-/** Check whether `addr` points to an `AF_INET6` address and whether the address
- * is link-local. */
-static bool ip6_link_local(struct sockaddr_in6 *addr)
-{
- if (addr->sin6_family != AF_INET6)
- return false;
-
- /* Link-local: https://tools.ietf.org/html/rfc4291#section-2.4 */
- const uint8_t prefix[] = { 0xFE, 0x80 };
- return kr_bitcmp((char *) addr->sin6_addr.s6_addr, (char *) prefix, 10) == 0;
-}
-
/** List available interfaces. */
static int net_interfaces(lua_State *L)
{
buf[0] = '\0';
}
- if (ip6_link_local(&iface.address.address6)) {
+ if (kr_sockaddr_link_local((struct sockaddr *) &iface.address)) {
/* Link-local IPv6: add %interface prefix */
auto_free char *str = NULL;
int ret = asprintf(&str, "%s%%%s", buf, iface.name);
#include <sys/statvfs.h>
#include <sys/un.h>
+struct __attribute__((packed)) kr_sockaddr_key {
+ int family;
+};
+
+struct __attribute__((packed)) kr_sockaddr_in_key {
+ int family;
+ char address[sizeof(((struct sockaddr_in *) NULL)->sin_addr)];
+ uint16_t port;
+};
+
+struct __attribute__((packed)) kr_sockaddr_in6_key {
+ int family;
+ char address[sizeof(((struct sockaddr_in6 *) NULL)->sin6_addr)];
+ uint32_t scope;
+ uint16_t port;
+};
+
+struct __attribute((packed)) kr_sockaddr_un_key {
+ int family;
+ char path[sizeof(((struct sockaddr_un *) NULL)->sun_path)];
+};
+
/* Logging & debugging */
bool kr_dbg_assertion_abort = DBG_ASSERTION_ABORT;
int kr_dbg_assertion_fork = DBG_ASSERTION_FORK;
}
}
+ssize_t kr_sockaddr_key(struct kr_sockaddr_key_storage *dst,
+ const struct sockaddr *addr)
+{
+ kr_require(addr);
+
+ switch (addr->sa_family) {
+ case AF_INET:;
+ const struct sockaddr_in *addr_in = (const struct sockaddr_in *) addr;
+ struct kr_sockaddr_in_key *inkey = (struct kr_sockaddr_in_key *) dst;
+ inkey->family = AF_INET;
+ memcpy(&inkey->address, &addr_in->sin_addr, sizeof(inkey->address));
+ memcpy(&inkey->port, &addr_in->sin_port, sizeof(inkey->port));
+ return sizeof(*inkey);
+
+ case AF_INET6:;
+ const struct sockaddr_in6 *addr_in6 = (const struct sockaddr_in6 *) addr;
+ struct kr_sockaddr_in6_key *in6key = (struct kr_sockaddr_in6_key *) dst;
+ in6key->family = AF_INET6;
+ memcpy(&in6key->address, &addr_in6->sin6_addr, sizeof(in6key->address));
+ memcpy(&in6key->port, &addr_in6->sin6_port, sizeof(in6key->port));
+ if (kr_sockaddr_link_local(addr))
+ memcpy(&in6key->scope, &addr_in6->sin6_scope_id, sizeof(in6key->scope));
+ else
+ in6key->scope = 0;
+ return sizeof(*in6key);
+
+ case AF_UNIX:;
+ const struct sockaddr_un *addr_un = (const struct sockaddr_un *) addr;
+ struct kr_sockaddr_un_key *unkey = (struct kr_sockaddr_un_key *) dst;
+ unkey->family = AF_UNIX;
+ strncpy(unkey->path, addr_un->sun_path, sizeof(unkey->path));
+ size_t pathlen = strnlen(unkey->path, sizeof(unkey->path));
+ if (pathlen < sizeof(unkey->path)) /* Include null-terminator */
+ pathlen += 1;
+ return offsetof(struct kr_sockaddr_un_key, path) + pathlen;
+
+ default:
+ return kr_error(EAFNOSUPPORT);
+ }
+}
+
+struct sockaddr *kr_sockaddr_from_key(struct sockaddr_storage *dst,
+ const char *key)
+{
+ kr_require(key);
+
+ switch (((struct kr_sockaddr_key *) key)->family) {
+ case AF_INET:;
+ const struct kr_sockaddr_in_key *inkey = (struct kr_sockaddr_in_key *) key;
+ struct sockaddr_in *addr_in = (struct sockaddr_in *) dst;
+ addr_in->sin_family = AF_INET;
+ memcpy(&addr_in->sin_addr, &inkey->address, sizeof(inkey->address));
+ memcpy(&addr_in->sin_port, &inkey->port, sizeof(inkey->port));
+ return (struct sockaddr *) addr_in;
+
+ case AF_INET6:;
+ const struct kr_sockaddr_in6_key *in6key = (struct kr_sockaddr_in6_key *) key;
+ struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *) dst;
+ addr_in6->sin6_family = AF_INET6;
+ memcpy(&addr_in6->sin6_addr, &in6key->address, sizeof(in6key->address));
+ memcpy(&addr_in6->sin6_port, &in6key->port, sizeof(in6key->port));
+ memcpy(&addr_in6->sin6_scope_id, &in6key->scope, sizeof(in6key->scope));
+ return (struct sockaddr *) addr_in6;
+
+ case AF_UNIX:;
+ const struct kr_sockaddr_un_key *unkey = (struct kr_sockaddr_un_key *) key;
+ struct sockaddr_un *addr_un = (struct sockaddr_un *) dst;
+ addr_un->sun_family = AF_UNIX;
+ strncpy(addr_un->sun_path, unkey->path, sizeof(unkey->path));
+ return (struct sockaddr *) addr_un;
+
+ default:
+ return NULL;
+ }
+}
+
int kr_sockaddr_cmp(const struct sockaddr *left, const struct sockaddr *right)
{
if (!left || !right) {
#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.
/** 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.
*/
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)