Index: /trunk/include/iprt/mangling.h
===================================================================
--- /trunk/include/iprt/mangling.h	(revision 76060)
+++ /trunk/include/iprt/mangling.h	(revision 76061)
@@ -1550,4 +1550,5 @@
 # define RTNetStrToIPv4AddrEx                           RT_MANGLER(RTNetStrToIPv4AddrEx)
 # define RTNetStrToIPv4Addr                             RT_MANGLER(RTNetStrToIPv4Addr)
+# define RTNetStrToIPv4Cidr                             RT_MANGLER(RTNetStrToIPv4Cidr)
 # define RTNetIsIPv6AddrStr                             RT_MANGLER(RTNetIsIPv6AddrStr)
 # define RTNetStrIsIPv6AddrAny                          RT_MANGLER(RTNetStrIsIPv6AddrAny)
Index: /trunk/include/iprt/net.h
===================================================================
--- /trunk/include/iprt/net.h	(revision 76060)
+++ /trunk/include/iprt/net.h	(revision 76061)
@@ -102,4 +102,19 @@
  */
 RTDECL(int) RTNetStrToIPv4Addr(const char *pcszAddr, PRTNETADDRIPV4 pAddr);
+
+/**
+ * Parses dotted-decimal IPv4 CIDR notation into RTNETADDRIPV4
+ * representation and prefix length.  Missing prefix specification is
+ * treated as exact address specification (prefix length 32).  Leading
+ * and trailing whitespace is ignored.
+ *
+ * @returns VINF_SUCCESS on success, VERR_INVALID_PARAMETER on
+ *          failure.
+ *
+ * @param   pcszAddr        The value to convert.
+ * @param   pAddr           Where to store the address.
+ * @param   piPrefix        Where to store the prefix length;
+ */
+RTDECL(int) RTNetStrToIPv4Cidr(const char *pcszAddr, PRTNETADDRIPV4 pAddr, int *piPrefix);
 
 /**
Index: /trunk/src/VBox/Runtime/common/net/netaddrstr2.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/net/netaddrstr2.cpp	(revision 76060)
+++ /trunk/src/VBox/Runtime/common/net/netaddrstr2.cpp	(revision 76061)
@@ -196,4 +196,46 @@
 
 
+RTDECL(int) RTNetStrToIPv4Cidr(const char *pcszAddr, PRTNETADDRIPV4 pAddr, int *piPrefix)
+{
+    RTNETADDRIPV4 Addr;
+    uint8_t u8Prefix;
+    char *pszNext;
+    int rc;
+
+    AssertPtrReturn(pcszAddr, VERR_INVALID_PARAMETER);
+    AssertPtrReturn(pAddr, VERR_INVALID_PARAMETER);
+    AssertPtrReturn(piPrefix, VERR_INVALID_PARAMETER);
+
+    pcszAddr = RTStrStripL(pcszAddr);
+    rc = rtNetStrToIPv4AddrEx(pcszAddr, &Addr, &pszNext);
+    if (RT_FAILURE(rc))
+        return rc;
+
+    /* if prefix is missing, treat is as exact (/32) address specification */
+    if (*pszNext == '\0' || rc == VWRN_TRAILING_SPACES)
+    {
+        *pAddr = Addr;
+        *piPrefix = 32;
+        return VINF_SUCCESS;
+    }
+
+    if (*pszNext != '/')
+        return VERR_INVALID_PARAMETER;
+
+    ++pszNext;
+    rc = RTStrToUInt8Ex(pszNext, &pszNext, 10, &u8Prefix);
+    if (RT_FAILURE(rc) || rc == VWRN_TRAILING_CHARS)
+        return VERR_INVALID_PARAMETER;
+
+    if (u8Prefix == 0 || u8Prefix > 32)
+        return VERR_INVALID_PARAMETER;
+
+    *pAddr = Addr;
+    *piPrefix = u8Prefix;
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTNetStrToIPv4Cidr);
+
+
 static int rtNetStrToHexGroup(const char *pcszValue, char **ppszNext,
                               uint16_t *pu16)
Index: /trunk/src/VBox/Runtime/testcase/tstRTNetIPv4.cpp
===================================================================
--- /trunk/src/VBox/Runtime/testcase/tstRTNetIPv4.cpp	(revision 76060)
+++ /trunk/src/VBox/Runtime/testcase/tstRTNetIPv4.cpp	(revision 76061)
@@ -97,4 +97,35 @@
 
 
+#define CHECKCIDR(String, rcExpected, ExpectedAddr, iExpectedPrefix)    \
+    do {                                                                \
+        RTNETADDRIPV4 Addr;                                             \
+        int iPrefix;                                                    \
+                                                                        \
+        int rc2 = RTNetStrToIPv4Cidr(String, &Addr, &iPrefix);          \
+        if ((rcExpected) && !rc2)                                       \
+        {                                                               \
+            RTTestIFailed("at line %d: '%s': expected %Rrc got %Rrc\n", \
+                          __LINE__, String, (rcExpected), rc2);         \
+        }                                                               \
+        else if (   (rcExpected) != rc2                                 \
+                 || (   rc2 == VINF_SUCCESS                             \
+                     && (   RT_H2N_U32_C(ExpectedAddr) != Addr.u        \
+                         || iExpectedPrefix != iPrefix)))               \
+        {                                                               \
+            RTTestIFailed("at line %d: '%s': expected %Rrc got %Rrc,"   \
+                          " expected address %RTnaipv4/%d got %RTnaipv4/%d\n", \
+                          __LINE__, String, rcExpected, rc2,            \
+                          RT_H2N_U32_C(ExpectedAddr), (iExpectedPrefix), \
+                          Addr.u, iPrefix);                             \
+        }                                                               \
+    } while (0)
+
+#define GOODCIDR(String, ExpectedAddr, iExpectedPrefix) \
+    CHECKCIDR(String, VINF_SUCCESS, ExpectedAddr, iExpectedPrefix)
+
+#define BADCIDR(String) \
+    CHECKCIDR(String, VERR_INVALID_PARAMETER, 0, 0)
+
+
 #define CHECKISADDR(String, fExpected)                                  \
     do {                                                                \
@@ -274,4 +305,30 @@
     CHECKADDREX("1.2.3.4",  "x",  VWRN_TRAILING_CHARS,    0x01020304);
     CHECKADDREX("1.2.3.444", "",  VERR_INVALID_PARAMETER,          0);
+
+
+    GOODCIDR("1.2.3.4",         0x01020304, 32);
+    GOODCIDR("1.2.3.4/32",      0x01020304, 32);
+    GOODCIDR("1.2.3.4/24",      0x01020304, 24); /* address is not truncated to prefix */
+
+    GOODCIDR("\t " "1.2.3.4/24",       0x01020304, 24); /* leading spaces ok */
+    GOODCIDR(      "1.2.3.4/24" " \t", 0x01020304, 24); /* trailing spaces ok */
+    GOODCIDR("\t " "1.2.3.4/24" " \t", 0x01020304, 24); /* both are ok */
+
+    BADCIDR("1.2.3.4/0");       /* prefix can't be zero */
+    BADCIDR("1.2.3.4/33");      /* prefix is too big */
+    BADCIDR("1.2.3.4/-1");      /* prefix is negative */
+    BADCIDR("1.2.3.4/");        /* prefix is missing */
+    BADCIDR("1.2.3.4/");        /* prefix is missing */
+    BADCIDR("1.2.3.4/a");       /* prefix is not a number */
+    BADCIDR("1.2.3.4/0xa");     /* prefix is not decimal */
+//  BADCIDR("1.2.3.0/024");     /* XXX: prefix is not decimal */
+
+    BADCIDR("1.2.3.0 /24");     /* no spaces after address */
+    BADCIDR("1.2.3.0/ 24");     /* no spaces after slash */
+
+    BADCIDR("1.2.3.0/24" "x");  /* trailing chars */
+    BADCIDR("1.2.3.0/24" " x"); /* trailing chars */
+
+
 
     /* NB: RTNetIsIPv4AddrStr does NOT allow leading/trailing whitespace */
