From: Sascha Steinbiss Date: Wed, 1 Jun 2022 09:33:06 +0000 (+0100) Subject: fix CIDRFromMask() on s390x X-Git-Tag: archive/raspbian/1%6.0.5-3+rpi1^2~2 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=1a7e54e9bbd5db775ea002e2b1106cb1de4c0c6f;p=suricata.git fix CIDRFromMask() on s390x Forwarded: https://github.com/OISF/suricata/pull/7332 Last-Update: 2022-04-30 This addresses a segfault on that platform which breaks testing transition. Gbp-Pq: Name bigendian-cidr.patch --- diff --git a/src/runmode-unittests.c b/src/runmode-unittests.c index 518bf52a..a35d8f1d 100644 --- a/src/runmode-unittests.c +++ b/src/runmode-unittests.c @@ -208,6 +208,7 @@ static void RegisterUnittests(void) SourceWinDivertRegisterTests(); #endif SCProtoNameRegisterTests(); + UtilCIDRTests(); } #endif diff --git a/src/util-cidr.c b/src/util-cidr.c index 06a0c30b..63c4abbf 100644 --- a/src/util-cidr.c +++ b/src/util-cidr.c @@ -25,10 +25,38 @@ #include "suricata-common.h" #include "util-cidr.h" +#include "util-unittest.h" /** \brief turn 32 bit mask into CIDR * \retval cidr cidr value or -1 if the netmask can't be expressed as cidr */ + +#if (defined(__s390__) || defined(__s390x__) || defined(__zarch__)) + +int CIDRFromMask(uint32_t netmask) +{ + netmask = ntohl(netmask); + if (netmask == 0) { + return 0; + } + int p = 0; + bool seen_1 = false; + while (netmask > 0) { + if (netmask & 1) { + seen_1 = true; + p++; + } else { + if (seen_1) { + return -1; + } + } + netmask >>= 1; + } + return p; +} + +#else + int CIDRFromMask(uint32_t netmask) { if (netmask == 0) { @@ -52,6 +80,8 @@ int CIDRFromMask(uint32_t netmask) return lead_1; } +#endif + uint32_t CIDRGet(int cidr) { if (cidr <= 0 || cidr > 32) @@ -95,3 +125,61 @@ void CIDRGetIPv6(int cidr, struct in6_addr *in6) in6->s6_addr[i] = in6->s6_addr[i] >> 1; } } + +#ifdef UNITTESTS + +static int CIDRFromMaskTest01(void) +{ + struct in_addr in; + int v = inet_pton(AF_INET, "255.255.255.0", &in); + + FAIL_IF(v <= 0); + FAIL_IF_NOT(24 == CIDRFromMask(in.s_addr)); + + PASS; +} + +static int CIDRFromMaskTest02(void) +{ + struct in_addr in; + int v = inet_pton(AF_INET, "255.255.0.42", &in); + + FAIL_IF(v <= 0); + FAIL_IF_NOT(-1 == CIDRFromMask(in.s_addr)); + + PASS; +} + +static int CIDRFromMaskTest03(void) +{ + struct in_addr in; + int v = inet_pton(AF_INET, "0.0.0.0", &in); + + FAIL_IF(v <= 0); + FAIL_IF_NOT(0 == CIDRFromMask(in.s_addr)); + + PASS; +} + +static int CIDRFromMaskTest04(void) +{ + struct in_addr in; + int v = inet_pton(AF_INET, "255.255.255.255", &in); + + FAIL_IF(v <= 0); + FAIL_IF_NOT(32 == CIDRFromMask(in.s_addr)); + + PASS; +} + +#endif /* UNITTESTS */ + +void UtilCIDRTests(void) +{ +#ifdef UNITTESTS + UtRegisterTest("CIDRFromMaskTest01", CIDRFromMaskTest01); + UtRegisterTest("CIDRFromMaskTest02", CIDRFromMaskTest02); + UtRegisterTest("CIDRFromMaskTest03", CIDRFromMaskTest03); + UtRegisterTest("CIDRFromMaskTest04", CIDRFromMaskTest04); +#endif /* UNITTESTS */ +} diff --git a/src/util-cidr.h b/src/util-cidr.h index a5d4a94b..745f6782 100644 --- a/src/util-cidr.h +++ b/src/util-cidr.h @@ -28,5 +28,7 @@ int CIDRFromMask(uint32_t netmask); uint32_t CIDRGet(int); void CIDRGetIPv6(int cidr, struct in6_addr *in6); +void UtilCIDRTests(void); + #endif /* __UTIL_NETMASK_H__ */