fix CIDRFromMask() on s390x
authorSascha Steinbiss <satta@debian.org>
Wed, 1 Jun 2022 09:33:06 +0000 (10:33 +0100)
committerSascha Steinbiss <satta@debian.org>
Wed, 1 Jun 2022 09:33:06 +0000 (10:33 +0100)
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

src/runmode-unittests.c
src/util-cidr.c
src/util-cidr.h

index 518bf52a6621e42f834889ef2d1480c34a2dc824..a35d8f1d1b691bb5956ebcd7ad0d3121d61ad5d6 100644 (file)
@@ -208,6 +208,7 @@ static void RegisterUnittests(void)
     SourceWinDivertRegisterTests();
 #endif
     SCProtoNameRegisterTests();
+    UtilCIDRTests();
 }
 #endif
 
index 06a0c30bc2143d859c90992cd8e80d65729987c5..63c4abbf88399cb6d23ae8d068984703e1a27103 100644 (file)
 
 #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 */
+}
index a5d4a94bbba682436c6c42a7886a45adc76743ee..745f67823c61d28d65207b650ae926521a3df63c 100644 (file)
@@ -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__ */