From cf1e02010cf358b50d7744d61fa2bc8184fbffcb Mon Sep 17 00:00:00 2001 From: Francesco Rollo Date: Fri, 7 Jun 2024 12:58:21 +0200 Subject: [PATCH] fix: change ipv6 addresses processing for CIDR matching Signed-off-by: Francesco Rollo Reviewed-by: Jakub Jelen --- src/config.c | 1 + src/match.c | 26 +++++++++------- .../torture_config_match_localnetwork.c | 30 ++++++++++--------- 3 files changed, 32 insertions(+), 25 deletions(-) diff --git a/src/config.c b/src/config.c index 79839007..1c3fd482 100644 --- a/src/config.c +++ b/src/config.c @@ -41,6 +41,7 @@ # include # include # include +# include #endif #include "libssh/config_parser.h" diff --git a/src/match.c b/src/match.c index d04d66e0..65fb156f 100644 --- a/src/match.c +++ b/src/match.c @@ -40,6 +40,11 @@ #include #include #include +#ifndef _WIN32 +#include +#include +#include +#endif #include "libssh/priv.h" @@ -219,29 +224,28 @@ cidr_match_6(struct in6_addr *host_addr, struct in6_addr *net_addr, unsigned int bits) { - const uint32_t *a = host_addr->s6_addr32; - const uint32_t *b = net_addr->s6_addr32; + const uint8_t *a = host_addr->s6_addr; + const uint8_t *b = net_addr->s6_addr; - unsigned int qwords_whole, bits_left; + unsigned int byte_whole, bits_left; - /* The number of complete 32-bit words covered by the prefix */ - qwords_whole = bits / 32; + /* The number of a complete byte covered by the prefix */ + byte_whole = bits / 8; /* - * The number of bits remaining in the incomplete (last) 32-bit word + * The number of bits remaining in the incomplete (last) byte * covered by the prefix */ - bits_left = bits % 32; + bits_left = bits % 8; - if (qwords_whole) { - if (memcmp(a, b, qwords_whole * 4) != 0) { + if (byte_whole) { + if (memcmp(a, b, byte_whole) != 0) { return 0; } } if (bits_left) { - if ((a[qwords_whole] ^ b[qwords_whole]) & - htonl((0xFFFFFFFFu << (32 - bits_left)) & 0xFFFFFFFFu)) { + if ((a[byte_whole] ^ b[byte_whole]) & (0xFFu << (8 - bits_left))) { return 0; } } diff --git a/tests/unittests/torture_config_match_localnetwork.c b/tests/unittests/torture_config_match_localnetwork.c index e4461ed3..33ed05d1 100644 --- a/tests/unittests/torture_config_match_localnetwork.c +++ b/tests/unittests/torture_config_match_localnetwork.c @@ -103,20 +103,22 @@ subnet_mask_to_prefix_length_4(struct in_addr subnet_mask) static int subnet_mask_to_prefix_length_6(struct in6_addr subnet_mask) { - uint32_t *mask = NULL, chunk; - int i, prefix_length = 0; + uint8_t *mask = NULL, chunk; + int i, j, prefix_length = 0; - mask = (uint32_t *)&subnet_mask.s6_addr[0]; + mask = subnet_mask.s6_addr; - /* Count the number of consecutive 1 bits in each 32-bit chunk */ - for (i = 0; i < 4; i++) { - chunk = ntohl(mask[i]); + /* Count the number of consecutive 1 bits in each byte chunk */ + for (i = 0; i < 16; i++) { + chunk = mask[i]; while (chunk) { - if (chunk & 0x80000000) { - prefix_length++; - chunk <<= 1; - } else { - break; + for (j = 0; j < 8; j++) { + if (chunk & 0x80) { + prefix_length++; + chunk <<= 1; + } else { + break; + } } } } @@ -244,9 +246,9 @@ get_network_id(char *net_id_4, char *net_id_6) } /* Calculate the network ID */ - for (i = 0; i < 4; i++) { - network_id_6.s6_addr32[i] = - addr6.s6_addr32[i] & subnet_mask_6.s6_addr32[i]; + for (i = 0; i < 16; i++) { + network_id_6.s6_addr[i] = + addr6.s6_addr[i] & subnet_mask_6.s6_addr[i]; } /* Convert network ID to string and compute prefix length */