diff options
Diffstat (limited to 'lib/src/name.c')
-rw-r--r-- | lib/src/name.c | 741 |
1 files changed, 339 insertions, 402 deletions
diff --git a/lib/src/name.c b/lib/src/name.c index 54b2a76aa..f363eea90 100644 --- a/lib/src/name.c +++ b/lib/src/name.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -19,533 +19,470 @@ */ #ifndef _WIN32 -#include <arpa/inet.h> // inet_ptin +#include <arpa/inet.h> // inet_ptin #endif #include <errno.h> #include <stdio.h> -#include <stdlib.h> // strtoul -#include <string.h> // memcpy +#include <stdlib.h> // strtoul +#include <string.h> // memcpy #include <hicn/common.h> #include <hicn/error.h> #include <hicn/name.h> +#include <hicn/util/sstrncpy.h> + +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#if ! HICN_VPP_PLUGIN int -hicn_name_create (const char *ip_address, u32 id, hicn_name_t * name) +hicn_name_create (const char *ip_address, u32 id, hicn_name_t *name) { int af, rc; - af = get_addr_family (ip_address); - - switch (af) - { - case AF_INET: - if (name->type == HNT_UNSPEC) - { - name->type = HNT_CONTIGUOUS_V4; - } - name->len = IPV4_ADDR_LEN; - break; - case AF_INET6: - if (name->type == HNT_UNSPEC) - { - name->type = HNT_CONTIGUOUS_V6; - } - name->len = IPV6_ADDR_LEN; - break; - default: - return HICN_LIB_ERROR_INVALID_IP_ADDRESS; - } + memset (name, 0, sizeof (hicn_name_t)); - if ((name->type != HNT_CONTIGUOUS_V4) && (name->type != HNT_CONTIGUOUS_V6)) - { - return HICN_LIB_ERROR_NOT_IMPLEMENTED; - } + af = get_addr_family (ip_address); + int v4 = (af == AF_INET); + u8 *dst = (u8 *) (v4 * (intptr_t) (name->prefix.v4.as_u8) + + (1 - v4) * (intptr_t) (name->prefix.v6.as_u8)); + rc = inet_pton (af, ip_address, dst); - rc = inet_pton (af, ip_address, name->buffer); - if (rc <= 0) + if (rc != 1) { return HICN_LIB_ERROR_UNKNOWN_ADDRESS; } - *(u32 *) (name->buffer + name->len) = id; + + name->suffix = id; return HICN_LIB_ERROR_NONE; } int -hicn_name_create_from_ip_prefix (const ip_prefix_t * prefix, u32 id, - hicn_name_t * name) +hicn_name_create_from_ip_address (const hicn_ip_address_t ip_address, + u32 suffix, hicn_name_t *name) { - switch (prefix->family) - { - case AF_INET: - name->type = HNT_CONTIGUOUS_V4; - memcpy (name->buffer, prefix->address.v4.buffer, - ip_address_len(prefix->family)); - name->len = IPV4_ADDR_LEN; - break; - case AF_INET6: - name->type = HNT_CONTIGUOUS_V6; - memcpy (name->buffer, prefix->address.v6.buffer, - ip_address_len(prefix->family)); - name->len = IPV6_ADDR_LEN; - break; - default: - return HICN_LIB_ERROR_INVALID_IP_ADDRESS; - } - - *(u32 *) (name->buffer + name->len) = id; + name->prefix = ip_address; + name->suffix = suffix; return HICN_LIB_ERROR_NONE; } -u8 -hicn_name_get_length (const hicn_name_t * name) +int +hicn_name_create_from_ip_prefix (const hicn_ip_prefix_t *prefix, u32 id, + hicn_name_t *name) { - return name->len; + name->prefix = prefix->address; + name->suffix = id; + + return HICN_LIB_ERROR_NONE; } int -hicn_name_compare (const hicn_name_t * name_1, const hicn_name_t * name_2, - bool consider_segment) +hicn_name_compare (const hicn_name_t *name_1, const hicn_name_t *name_2, + bool consider_segment) { - hicn_name_t *name1 = (hicn_name_t *) name_1; - hicn_name_t *name2 = (hicn_name_t *) name_2; + int ret; + ret = memcmp (&name_1->prefix.v6.buffer, &name_2->prefix.v6.buffer, + sizeof (name_1->prefix.v6)); - if ((name1->type == HNT_CONTIGUOUS_V4 && name2->type == HNT_CONTIGUOUS_V6) - || (name1->type == HNT_CONTIGUOUS_V6 - && name2->type == HNT_CONTIGUOUS_V4)) - { - return -1; - } + if (consider_segment) + ret |= !(name_1->suffix == name_2->suffix); - if ((name1->type == HNT_IOV_V4 && name2->type == HNT_IOV_V6) || - (name1->type == HNT_IOV_V6 && name2->type == HNT_IOV_V4)) - { - return -1; - } + return ret; +} - if ((name1->type == HNT_IOV_V4 && name2->type == HNT_CONTIGUOUS_V6) || - (name1->type == HNT_IOV_V6 && name2->type == HNT_CONTIGUOUS_V4)) - { - return -1; - } +uint32_t +_hicn_name_get_hash (const hicn_name_t *name, bool consider_suffix) +{ + uint32_t hash = hash32 (&name->prefix, sizeof (name->prefix)); - if (name1->type == HNT_UNSPEC || name2->type == HNT_UNSPEC) - { - return -1; - } + if (consider_suffix) + hash = cumulative_hash32 (&name->suffix, sizeof (name->suffix), hash); - size_t len1 = 0, len2 = 0; + return hash; +} - u8 *buffer11, *buffer12, *buffer21, *buffer22; +int +hicn_name_empty (hicn_name_t *name) +{ + return _is_unspec (name); +} - switch (name1->type) - { - case HNT_CONTIGUOUS_V4: - buffer11 = name1->buffer; - buffer12 = name1->buffer + IPV4_ADDR_LEN; - len1 = IPV4_ADDR_LEN; - break; - case HNT_CONTIGUOUS_V6: - buffer11 = name1->buffer; - buffer12 = name1->buffer + IPV6_ADDR_LEN; - len1 = IPV6_ADDR_LEN; - break; - case HNT_IOV_V4: - buffer11 = name1->iov.buffers[0].iov_base; - buffer12 = name1->iov.buffers[1].iov_base; - len1 = IPV4_ADDR_LEN; - break; - case HNT_IOV_V6: - buffer11 = name1->iov.buffers[0].iov_base; - buffer12 = name1->iov.buffers[1].iov_base; - len1 = IPV6_ADDR_LEN; - break; - default: - return HICN_LIB_ERROR_NOT_IMPLEMENTED; - } +int +hicn_name_copy (hicn_name_t *dst, const hicn_name_t *src) +{ + *dst = *src; + return HICN_LIB_ERROR_NONE; +} - switch (name2->type) - { - case HNT_CONTIGUOUS_V4: - buffer21 = name2->buffer; - buffer22 = name2->buffer + IPV4_ADDR_LEN; - len2 = IPV4_ADDR_LEN; - break; - case HNT_CONTIGUOUS_V6: - buffer21 = name2->buffer; - buffer22 = name2->buffer + IPV6_ADDR_LEN; - len2 = IPV6_ADDR_LEN; - break; - case HNT_IOV_V4: - buffer21 = name2->iov.buffers[0].iov_base; - buffer22 = name2->iov.buffers[1].iov_base; - len2 = IPV4_ADDR_LEN; - break; - case HNT_IOV_V6: - buffer21 = name2->iov.buffers[0].iov_base; - buffer22 = name2->iov.buffers[1].iov_base; - len2 = IPV6_ADDR_LEN; - break; - default: - return HICN_LIB_ERROR_NOT_IMPLEMENTED; - } +int +hicn_name_copy_prefix_to_destination (u8 *dst, const hicn_name_t *name) +{ + int v4 = _is_inet4 (name); + const u8 *src = (u8 *) (v4 * (intptr_t) (name->prefix.v4.as_u8) + + (1 - v4) * (intptr_t) (name->prefix.v6.as_u8)); + size_t size = v4 * IPV4_ADDR_LEN + (1 - v4) * IPV6_ADDR_LEN; + memcpy (dst, src, size); - // Sanity check - if (len1 != len2) - { - return HICN_LIB_ERROR_UNEXPECTED; - } + return HICN_LIB_ERROR_NONE; +} - int ret1 = memcmp ((u8 *) buffer11, (u8 *) buffer21, len1); +int +hicn_name_set_suffix (hicn_name_t *name, hicn_name_suffix_t suffix) +{ + name->suffix = suffix; + return HICN_LIB_ERROR_NONE; +} - if (!consider_segment) +int +hicn_name_to_sockaddr_address (const hicn_name_t *name, + struct sockaddr *ip_address) +{ + struct sockaddr_in6 *tmp6 = (struct sockaddr_in6 *) ip_address; + struct sockaddr_in *tmp4 = (struct sockaddr_in *) ip_address; + + assert (!_is_unspec (name)); + + if (_is_inet4 (name)) + { + tmp4->sin_family = AF_INET; + tmp4->sin_port = DUMMY_PORT; + memcpy (&tmp4->sin_addr, &name->prefix.v4, IPV4_ADDR_LEN); + } + else { - return ret1; + tmp6->sin6_family = AF_INET6; + tmp6->sin6_scope_id = 0; + tmp6->sin6_port = DUMMY_PORT; + memcpy (&tmp6->sin6_addr, &name->prefix.v6, IPV6_ADDR_LEN); } - int ret2 = memcmp ((u8 *) buffer12, (u8 *) buffer22, HICN_SEGMENT_LEN); - - return ret1 || ret2; + return HICN_LIB_ERROR_NONE; } int -hicn_name_hash (const hicn_name_t * name, u32 * hash, bool consider_suffix) +hicn_name_to_hicn_ip_prefix (const hicn_name_t *name, hicn_ip_prefix_t *prefix) { - switch (name->type) - { - case HNT_CONTIGUOUS_V4: - *hash = hash32 (name->buffer, consider_suffix ? HICN_V4_NAME_LEN : HICN_V4_PREFIX_LEN); - break; - case HNT_CONTIGUOUS_V6: - *hash = hash32 (name->buffer, consider_suffix ? HICN_V6_NAME_LEN : HICN_V6_PREFIX_LEN); - break; - case HNT_IOV_V4: - case HNT_IOV_V6: - *hash = - hash32 (name->iov.buffers[0].iov_base, name->iov.buffers[0].iov_len); - if (consider_suffix) - { - *hash = cumulative_hash32 (name->iov.buffers[1].iov_base, - name->iov.buffers[1].iov_len, *hash); - } - break; - default: - return HICN_LIB_ERROR_NOT_IMPLEMENTED; - } - + int family, rc; + rc = hicn_name_get_family (name, &family); + if (rc) + return rc; + + prefix->family = family; + prefix->address.v6.as_u64[0] = name->prefix.v6.as_u64[0]; + prefix->address.v6.as_u64[1] = name->prefix.v6.as_u64[1]; + prefix->len = 128; return HICN_LIB_ERROR_NONE; } int -hicn_name_empty (hicn_name_t * name) +hicn_name_get_seq_number (const hicn_name_t *name, u32 *seq_number) { - return name->type == HNT_UNSPEC ? 1 : 0; + *seq_number = name->suffix; + return HICN_LIB_ERROR_NONE; } int -hicn_name_copy (hicn_name_t * dst, const hicn_name_t * src) +hicn_name_ntop (const hicn_name_t *src, char *dst, size_t len) { - switch (src->type) + int offset; + const char *rc = NULL; + int v4 = _is_inet4 (src); + const u8 *addr = (u8 *) (v4 * (intptr_t) src->prefix.v4.as_u8 + + (1 - v4) * (intptr_t) src->prefix.v6.as_u8); + int family = v4 * AF_INET + (1 - v4) * AF_INET6; + rc = inet_ntop (family, addr, dst, (socklen_t) len); + + if (!rc) { - case HNT_CONTIGUOUS_V4: - case HNT_CONTIGUOUS_V6: - *dst = *src; - break; - case HNT_IOV_V4: - case HNT_IOV_V6: - dst->type = - src->type == HNT_IOV_V4 ? HNT_CONTIGUOUS_V4 : HNT_CONTIGUOUS_V6; - memcpy (dst->buffer, src->iov.buffers[0].iov_base, - src->iov.buffers[0].iov_len); - memcpy (dst->buffer + src->iov.buffers[0].iov_len, - src->iov.buffers[1].iov_base, src->iov.buffers[1].iov_len); - break; - default: - return HICN_LIB_ERROR_NOT_IMPLEMENTED; + return HICN_LIB_ERROR_UNSPECIFIED; } + offset = (int) strnlen_s (dst, len); + dst[offset] = '|'; + + snprintf (dst + offset + 1, len - offset - 1, "%lu", + (unsigned long) (src->suffix)); + return HICN_LIB_ERROR_NONE; } int -hicn_name_copy_to_destination (u8 * dst, const hicn_name_t * src, - bool copy_suffix) +hicn_name_pton (const char *src, hicn_name_t *dst) { - size_t length; + return HICN_LIB_ERROR_NOT_IMPLEMENTED; +} - switch (src->type) - { - case HNT_CONTIGUOUS_V4: - if (copy_suffix) - { - length = HICN_V4_NAME_LEN; - } - else - { - length = IPV4_ADDR_LEN; - } - memcpy (dst, src->buffer, length); - break; - case HNT_CONTIGUOUS_V6: - if (copy_suffix) - { - length = HICN_V6_NAME_LEN; - } - else - { - length = IPV6_ADDR_LEN; - } - memcpy (dst, src->buffer, length); - break; - case HNT_IOV_V4: - case HNT_IOV_V6: - memcpy (dst, src->iov.buffers[0].iov_base, src->iov.buffers[0].iov_len); - if (copy_suffix) - { - memcpy (dst + src->iov.buffers[0].iov_len, - src->iov.buffers[1].iov_base, src->iov.buffers[1].iov_len); - } - break; - default: - return HICN_LIB_ERROR_NOT_IMPLEMENTED; - } +int +hicn_name_get_family (const hicn_name_t *name, int *family) +{ + assert (!_is_unspec (name)); + int v4 = _is_inet4 (name); + *family = v4 * AF_INET + (1 - v4) * AF_INET6; return HICN_LIB_ERROR_NONE; } +bool +hicn_name_is_v4 (const hicn_name_t *name) +{ + return _is_inet4 (name); +} + int -hicn_name_set_seq_number (hicn_name_t * name, u32 seq_number) +hicn_name_snprintf (char *s, size_t size, const hicn_name_t *name) { - u8 *sequence_number = NULL; + int n, rc; + n = hicn_ip_address_snprintf (s, size, &name->prefix); + if (n < 0 || n >= size) + return n; + rc = snprintf (s + n, size - n, "|%d", name->suffix); + if (rc < 0) + return rc; + return rc + n; +} - switch (name->type) - { - case HNT_CONTIGUOUS_V6: - sequence_number = name->buffer + IPV6_ADDR_LEN; - break; - case HNT_CONTIGUOUS_V4: - sequence_number = name->buffer + IPV4_ADDR_LEN; - break; - case HNT_IOV_V6: - case HNT_IOV_V4: - sequence_number = name->iov.buffers[1].iov_base; - break; - case HNT_UNSPEC: - return HICN_LIB_ERROR_UNEXPECTED; - } +int +hicn_name_no_suffix_snprintf (char *s, size_t size, const hicn_name_t *name) +{ + return hicn_ip_address_snprintf (s, size, &name->prefix); +} - if (sequence_number) - { - *(u32 *) sequence_number = seq_number; - } - else - { - return HICN_LIB_ERROR_UNEXPECTED; - } +int +hicn_prefix_create_from_ip_prefix (const hicn_ip_prefix_t *hicn_ip_prefix, + hicn_prefix_t *prefix) +{ + if (hicn_ip_prefix->family != AF_INET && hicn_ip_prefix->family != AF_INET6) + return HICN_LIB_ERROR_INVALID_IP_ADDRESS; + prefix->name = hicn_ip_prefix->address; + prefix->len = (u8) (hicn_ip_prefix->len); return HICN_LIB_ERROR_NONE; } int -hicn_name_to_sockaddr_address (const hicn_name_t * name, - struct sockaddr *ip_address) +hicn_name_cmp (const hicn_name_t *n1, const hicn_name_t *n2) { - struct sockaddr_in6 *tmp6 = (struct sockaddr_in6 *) ip_address; - struct sockaddr_in *tmp4 = (struct sockaddr_in *) ip_address; - - switch (name->type) - { - case HNT_CONTIGUOUS_V6: - tmp6->sin6_family = AF_INET6; - tmp6->sin6_scope_id = 0; - tmp6->sin6_port = DUMMY_PORT; - memcpy (&tmp6->sin6_addr, name->buffer, IPV6_ADDR_LEN); - break; - case HNT_IOV_V6: - tmp6->sin6_family = AF_INET6; - tmp6->sin6_scope_id = 0; - tmp6->sin6_port = DUMMY_PORT; - memcpy (&tmp6->sin6_addr, name->iov.buffers[0].iov_base, - name->iov.buffers[0].iov_len); - break; - case HNT_CONTIGUOUS_V4: - tmp4->sin_family = AF_INET; - tmp4->sin_port = DUMMY_PORT; - memcpy (&tmp4->sin_addr, name->buffer, IPV4_ADDR_LEN); - break; - case HNT_IOV_V4: - tmp4->sin_family = AF_INET; - tmp4->sin_port = DUMMY_PORT; - memcpy (&tmp4->sin_addr, name->iov.buffers[0].iov_base, - name->iov.buffers[0].iov_len); - break; - default: - return HICN_LIB_ERROR_UNEXPECTED; - } + int rc = hicn_ip_address_cmp (&n1->prefix, &n2->prefix); + if (rc != 0) + return rc; + return n2->suffix - n1->suffix; +} - return HICN_LIB_ERROR_NONE; +bool +hicn_name_equals (const hicn_name_t *n1, const hicn_name_t *n2) +{ + return (hicn_name_cmp (n1, n2) == 0); } int -hicn_name_to_ip_prefix (const hicn_name_t * name, ip_prefix_t * prefix) +hicn_prefix_create_from_ip_address_len (const hicn_ip_address_t *ip_address, + uint8_t len, hicn_prefix_t *prefix) { - switch (name->type) - { - case HNT_CONTIGUOUS_V6: - memcpy (&prefix->address.v6.buffer, name->buffer, IPV6_ADDR_LEN); - prefix->family = AF_INET6; - break; - case HNT_IOV_V6: - memcpy (&prefix->address.v6.buffer, name->iov.buffers[0].iov_base, - name->iov.buffers[0].iov_len); - prefix->family = AF_INET6; - break; - case HNT_CONTIGUOUS_V4: - memcpy (&prefix->address.v4.buffer, name->buffer, IPV4_ADDR_LEN); - prefix->family = AF_INET; - break; - case HNT_IOV_V4: - memcpy (&prefix->address.v4.buffer, name->iov.buffers[0].iov_base, - name->iov.buffers[0].iov_len); - prefix->family = AF_INET; - break; - default: - return HICN_LIB_ERROR_UNEXPECTED; - } + prefix->name = *ip_address; + prefix->len = len; return HICN_LIB_ERROR_NONE; } +hicn_prefix_t * +hicn_prefix_dup (const hicn_prefix_t *prefix) +{ + hicn_prefix_t *copy = malloc (sizeof (hicn_prefix_t)); + if (!copy) + goto ERR_MALLOC; + if (hicn_prefix_copy (copy, prefix) < 0) + goto ERR_COPY; + return copy; + +ERR_COPY: + free (copy); +ERR_MALLOC: + return NULL; +} + int -hicn_name_get_seq_number (const hicn_name_t * name, u32 * seq_number) +hicn_prefix_copy (hicn_prefix_t *dst, const hicn_prefix_t *src) { - const u8 *sequence_number = NULL; + dst->name = src->name; + dst->len = src->len; + return 0; +} - switch (name->type) +bool +hicn_prefix_is_v4 (const hicn_prefix_t *prefix) +{ + return hicn_ip_address_is_v4 (&prefix->name); +} + +/* + * The ip address is in network byte order (big endian, msb last) in + * hicn_{prefix,name}_t, as in ip_address_t which builds upon struct in*_addr, + * But the bits are in host order... so we cannot use builtin functions to get + * the position of the first 1 unless we swap bytes as was done previously, + * which is costly and non-essential. + * + * + * Example: + * + * bits | 127 .. 120 | ... | 8 9 10 11 12 13 14 15 | 0 .. 7 | + * diff | | ... | 1 0 1 0 0 0 0 0 | | + * ^ + * bit of interest ----------------+ + */ + +uint64_t +_log2_nbo (uint64_t val) +{ + assert (val != 0); /* There is at least 1 bit set (network byte order) */ + + uint64_t result = 0; + + /* Search for the first 1, starting from left */ + + /* The first 32 bits of val are 0 */ + if (!(val & 0x00000000FFFFFFFF)) { - case HNT_CONTIGUOUS_V6: - sequence_number = name->buffer + IPV6_ADDR_LEN; - break; - case HNT_CONTIGUOUS_V4: - sequence_number = name->buffer + IPV4_ADDR_LEN; - break; - case HNT_IOV_V6: - case HNT_IOV_V4: - sequence_number = name->iov.buffers[1].iov_base; - break; - default: - return HICN_LIB_ERROR_UNEXPECTED; + val = val >> 32; + result = result | 32; } - if (sequence_number) + if (!(val & 0x0000FFFF)) { - *seq_number = *(u32 *) sequence_number; + val = val >> 16; + result = result | 16; } - else + + if (!(val & 0x00FF)) { - return HICN_LIB_ERROR_UNEXPECTED; + val = val >> 8; + result = result | 8; } - return HICN_LIB_ERROR_NONE; + /* Val now contains the byte with at last 1 bit set (host bit order) */ + if (val & 0xF0) + val = val >> 4; + else + result = result | 4; + + if (val & 0xC) + val = val >> 2; + else + result = result | 2; + + if (val & 0x2) + val = val >> 1; + else + result = result | 1; + + return result; } -int -hicn_name_ntop (const hicn_name_t * src, char *dst, size_t len) +uint32_t +hicn_prefix_lpm (const hicn_prefix_t *p1, const hicn_prefix_t *p2) { - int offset; - const char *rc; - void *seg_number = NULL; - - switch (src->type) + uint32_t prefix_len = 0; + /* Test each block of 64 bits as a whole */ + for (unsigned i = 0; i < 2; i++) { - case HNT_CONTIGUOUS_V6: - rc = inet_ntop (AF_INET6, src->buffer, dst, (socklen_t)len); - seg_number = (u8 *) src->buffer + IPV6_ADDR_LEN; - break; - case HNT_CONTIGUOUS_V4: - rc = inet_ntop (AF_INET, src->buffer, dst, (socklen_t)len); - seg_number = (u8 *) src->buffer + IPV4_ADDR_LEN; - break; - case HNT_IOV_V6: - rc = inet_ntop (AF_INET6, src->iov.buffers[0].iov_base, dst, (socklen_t)len); - seg_number = src->iov.buffers[1].iov_base; - break; - case HNT_IOV_V4: - rc = inet_ntop (AF_INET, src->iov.buffers[0].iov_base, dst, (socklen_t)len); - seg_number = src->iov.buffers[1].iov_base; - break; - default: - return HICN_LIB_ERROR_NOT_IMPLEMENTED; - } - if (!rc) - { - goto ERR; + /* Check for differences in the two u64 */ + uint64_t diff = p1->name.v6.as_u64[i] ^ p2->name.v6.as_u64[i]; + if (diff) + { + /* + * As the ip_address_t mimics in*_addr and has network byte order + * (and host bit order, we cannot directly use 64-bit operations: + */ + prefix_len += _log2_nbo (diff); + break; + } + prefix_len += 8 * sizeof (uint64_t); } - offset = (int) strlen (dst); - dst[offset] = '|'; - - sprintf (dst + offset + 1, "%lu", (unsigned long) (*(u32 *) seg_number)); - - return HICN_LIB_ERROR_NONE; + /* Bound the returned prefix length by the length of all input */ + return MIN (prefix_len, + MIN (hicn_prefix_get_len (p1), hicn_prefix_get_len (p2))); +} -ERR: - return HICN_LIB_ERROR_UNSPECIFIED; +void +hicn_prefix_clear (hicn_prefix_t *prefix, uint8_t start_from) +{ + uint8_t *buffer = prefix->name.v6.as_u8; + + /* Compute the offset of the byte from which to clear the name... */ + uint8_t offset = start_from / 8; + if (hicn_prefix_is_v4 (prefix)) + offset += IP_ADDRESS_V4_OFFSET_LEN; /* Ignore padding */ + /* ... and the position of the first bit to clear */ + uint8_t pos = start_from % 8; + + /* Mask to clear specific bits at offset... + * pos 7 6 5 4 3 2 1 0 (eg. start_from = 19, pos = 3) + * mask 0 0 0 0 0 1 1 1 (= 1<<pos - 1) + * */ + uint8_t mask = 0xFF ^ ((1 << (8 - pos)) - 1); + buffer[offset] &= mask; + + /* ... then fully clear remaining bytes */ + for (uint8_t i = offset + 1; i < HICN_PREFIX_MAX_LEN; i++) + buffer[i] = 0; } -int -hicn_name_pton (const char *src, hicn_name_t * dst) +void +hicn_prefix_truncate (hicn_prefix_t *prefix, uint8_t len) { - return HICN_LIB_ERROR_NOT_IMPLEMENTED; + hicn_prefix_clear (prefix, len); + prefix->len = len; } int -hicn_name_get_family (const hicn_name_t * name, int *family) +hicn_prefix_cmp (const hicn_prefix_t *p1, const hicn_prefix_t *p2) { - switch (name->type) - { - case HNT_CONTIGUOUS_V6: - case HNT_IOV_V6: - *family = AF_INET6; - break; - case HNT_CONTIGUOUS_V4: - case HNT_IOV_V4: - *family = AF_INET; - break; - default: - return HICN_LIB_ERROR_UNEXPECTED; - } + if (p1->len != p2->len) + return p2->len - p1->len; + return hicn_ip_address_cmp (&p1->name, &p2->name); +} - return HICN_LIB_ERROR_NONE; +bool +hicn_prefix_equals (const hicn_prefix_t *p1, const hicn_prefix_t *p2) +{ + return hicn_prefix_cmp (p1, p2) == 0; } int -hicn_prefix_create_from_ip_prefix (const ip_prefix_t * ip_prefix, - hicn_prefix_t * prefix) +hicn_prefix_snprintf (char *s, size_t size, const hicn_prefix_t *prefix) { - switch (ip_prefix->family) - { - case AF_INET: - prefix->name.ip4.as_u32 = ip_prefix->address.v4.as_u32; - break; - case AF_INET6: - prefix->name.ip6.as_u64[0] = ip_prefix->address.v6.as_u64[0]; - prefix->name.ip6.as_u64[1] = ip_prefix->address.v6.as_u64[1]; - break; - default: - return HICN_LIB_ERROR_INVALID_IP_ADDRESS; - } - prefix->len = (u8) (ip_prefix->len); + hicn_ip_prefix_t ip_prefix = { .family = + hicn_ip_address_get_family (&prefix->name), + .address = prefix->name, + .len = prefix->len }; + return hicn_ip_prefix_snprintf (s, size, &ip_prefix); +} - return HICN_LIB_ERROR_NONE; +uint8_t +_hicn_prefix_get_bit (const hicn_prefix_t *prefix, uint8_t pos) +{ + const hicn_ip_address_t *address = hicn_prefix_get_ip_address (prefix); + return hicn_ip_address_get_bit (address, pos); } -#endif /* ! HICN_VPP_PLUGIN */ +uint8_t +hicn_prefix_get_bit (const hicn_prefix_t *prefix, uint8_t pos) +{ + assert (pos <= hicn_prefix_get_len (prefix)); + return _hicn_prefix_get_bit (prefix, pos); +} +int +hicn_prefix_get_ip_prefix (const hicn_prefix_t *prefix, + hicn_ip_prefix_t *ip_prefix) +{ + *ip_prefix = + (hicn_ip_prefix_t){ .family = hicn_ip_address_get_family (&prefix->name), + .address = prefix->name, + .len = prefix->len }; + return HICN_LIB_ERROR_NONE; +} /* * fd.io coding-style-patch-verification: ON |