Index: /trunk/include/iprt/mangling.h
===================================================================
--- /trunk/include/iprt/mangling.h	(revision 50417)
+++ /trunk/include/iprt/mangling.h	(revision 50418)
@@ -985,4 +985,5 @@
 # define RTNetStrToMacAddr                              RT_MANGLER(RTNetStrToMacAddr)
 # define RTNetIsIPv4AddrStr                             RT_MANGLER(RTNetIsIPv4AddrStr)
+# define RTNetStrToIPv4AddrEx                           RT_MANGLER(RTNetStrToIPv4AddrEx)
 # define RTNetStrToIPv4Addr                             RT_MANGLER(RTNetStrToIPv4Addr)
 # define RTNetIsIPv6AddrStr                             RT_MANGLER(RTNetIsIPv6AddrStr)
Index: /trunk/include/iprt/net.h
===================================================================
--- /trunk/include/iprt/net.h	(revision 50417)
+++ /trunk/include/iprt/net.h	(revision 50418)
@@ -66,19 +66,32 @@
  *
  * @returns boolean.
- * @param   pszAddress          String which may be an IPv4 address.
- */
-RTDECL(bool) RTNetIsIPv4AddrStr(const char *pszAddress);
-
-/**
- * Converts an stringified IPv4 address into the RTNETADDRIPV4 representation.
+ * @param   pcszAddr        String which may be an IPv4 address.
+ */
+RTDECL(bool) RTNetIsIPv4AddrStr(const char *pcszAddr);
+
+/**
+ * Parses dotted-decimal IPv4 address into RTNETADDRIPV4 representation.
  *
  * @returns VINF_SUCCESS on success, VERR_INVALID_PARAMETER on
  *          failure.
  *
- * @param   pszAddr         The value to convert.
+ * @param   pcszAddr        The value to convert.
+ * @param   ppszNext        Where to store the pointer to the first char
+ *                            following the address. (Optional)
  * @param   pAddr           Where to store the result.
  */
-RTDECL(int) RTNetStrToIPv4Addr(const char *pszAddr, PRTNETADDRIPV4 pAddr);
-
+RTDECL(int) RTNetStrToIPv4AddrEx(const char *pcszAddr, PRTNETADDRIPV4 pAddr, char **ppszNext);
+
+/**
+ * Parses dotted-decimal IPv4 address into RTNETADDRIPV4 representation.
+ * 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 result.
+ */
+RTDECL(int) RTNetStrToIPv4Addr(const char *pcszAddr, PRTNETADDRIPV4 pAddr);
 
 /**
Index: /trunk/src/VBox/Runtime/common/net/netaddrstr.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/net/netaddrstr.cpp	(revision 50417)
+++ /trunk/src/VBox/Runtime/common/net/netaddrstr.cpp	(revision 50418)
@@ -1229,62 +1229,2 @@
 }
 RT_EXPORT_SYMBOL(RTNetIsIPv6AddrStr);
-
-
-RTDECL(bool) RTNetIsIPv4AddrStr(const char *pszAddress)
-{
-    static char const s_szIpV4Digits[] = "0123456789.";
-
-    size_t cchAddress = strlen(pszAddress);
-    if (cchAddress < 7 || cchAddress > 15)
-        return false;
-
-    const char *pStart, *pFrom, *pTo, *pNow;
-    pStart = pNow = pFrom = pTo = pszAddress;
-
-    unsigned cOctets = 0;
-    while (*pNow != '\0')
-    {
-        const char *pChar  = (const char *)memchr(s_szIpV4Digits, *pNow, sizeof(s_szIpV4Digits) - 1);
-        const char *pDigit = (const char *)memchr(s_szIpV4Digits, *pNow, sizeof(s_szIpV4Digits) - 2);
-        const char *pNext  = pNow + 1;
-
-        if (!pChar)
-            return false;
-
-        if (pDigit && *pNext != '\0')
-        {
-            pTo = pNow;
-            pNow++;
-            continue;
-        }
-
-        if (*pNow == '.' || *pNext == '\0')
-        {
-            if (*pNext == '\0')
-                pTo = pNow;
-
-            size_t cchSub = pTo - pFrom;
-            if (cchSub > 2)
-                return false;
-
-            char szDummy[4] = { 0, 0, 0, 0 };
-            memcpy(szDummy, pFrom, cchSub + 1);
-
-            int rc = RTStrToUInt8Ex(szDummy, NULL, 10, NULL);
-            if (rc != VINF_SUCCESS)
-                return false;
-
-            cOctets++;
-            if (cOctets > 4)
-                return false;
-            pFrom = pNext;
-        }
-        pNow++;
-    }
-
-    if (cOctets != 4)
-        return false;
-
-    return true;
-}
-RT_EXPORT_SYMBOL(RTNetIsIPv4AddrStr);
Index: /trunk/src/VBox/Runtime/common/net/netaddrstr2.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/net/netaddrstr2.cpp	(revision 50417)
+++ /trunk/src/VBox/Runtime/common/net/netaddrstr2.cpp	(revision 50418)
@@ -36,11 +36,15 @@
 #include "internal/string.h"
 
-RTDECL(int) RTNetStrToIPv4Addr(const char *pszAddr, PRTNETADDRIPV4 pAddr)
+
+DECLHIDDEN(int) rtNetStrToIPv4AddrEx(const char *pcszAddr, PRTNETADDRIPV4 pAddr,
+                                     char **ppszNext)
 {
     char *pszNext;
-    AssertPtrReturn(pszAddr, VERR_INVALID_PARAMETER);
+    int rc;
+
+    AssertPtrReturn(pcszAddr, VERR_INVALID_PARAMETER);
     AssertPtrReturn(pAddr, VERR_INVALID_PARAMETER);
 
-    int rc = RTStrToUInt8Ex(RTStrStripL(pszAddr), &pszNext, 10, &pAddr->au8[0]);
+    rc = RTStrToUInt8Ex(pcszAddr, &pszNext, 10, &pAddr->au8[0]);
     if (rc != VINF_SUCCESS && rc != VWRN_TRAILING_CHARS)
         return VERR_INVALID_PARAMETER;
@@ -61,8 +65,36 @@
 
     rc = RTStrToUInt8Ex(pszNext, &pszNext, 10, &pAddr->au8[3]);
-    if (rc != VINF_SUCCESS && rc != VWRN_TRAILING_SPACES)
+    if (rc != VINF_SUCCESS && rc != VWRN_TRAILING_SPACES && rc != VWRN_TRAILING_CHARS)
         return VERR_INVALID_PARAMETER;
+
+    if (ppszNext != NULL)
+        *ppszNext = pszNext;
+    return VINF_SUCCESS;
+}
+
+
+RTDECL(int) RTNetStrToIPv4AddrEx(const char *pcszAddr, PRTNETADDRIPV4 pAddr,
+                                 char **ppszNext)
+{
+    return rtNetStrToIPv4AddrEx(pcszAddr, pAddr, ppszNext);
+}
+RT_EXPORT_SYMBOL(RTNetStrToIPv4AddrEx);
+
+
+RTDECL(int) RTNetStrToIPv4Addr(const char *pcszAddr, PRTNETADDRIPV4 pAddr)
+{
+    char *pszNext;
+    int rc;
+
+    AssertPtrReturn(pcszAddr, VERR_INVALID_PARAMETER);
+    AssertPtrReturn(pAddr, VERR_INVALID_PARAMETER);
+
+    pcszAddr = RTStrStripL(pcszAddr);
+    rc = rtNetStrToIPv4AddrEx(pcszAddr, pAddr, &pszNext);
+    if (rc != VINF_SUCCESS)
+        return VERR_INVALID_PARAMETER;
+
     pszNext = RTStrStripL(pszNext);
-    if (*pszNext)
+    if (*pszNext != '\0')
         return VERR_INVALID_PARAMETER;
 
@@ -71,2 +103,22 @@
 RT_EXPORT_SYMBOL(RTNetStrToIPv4Addr);
 
+
+RTDECL(bool) RTNetIsIPv4AddrStr(const char *pcszAddr)
+{
+    RTNETADDRIPV4 addrIPv4;
+    char *pszNext;
+    int rc;
+
+    if (pcszAddr == NULL)
+        return false;
+
+    rc = rtNetStrToIPv4AddrEx(pcszAddr, &addrIPv4, &pszNext);
+    if (rc != VINF_SUCCESS)
+        return false;
+
+    if (*pszNext != '\0')
+        return false;
+
+    return true;
+}
+RT_EXPORT_SYMBOL(RTNetIsIPv4AddrStr);
Index: /trunk/src/VBox/Runtime/testcase/tstRTNetIPv4.cpp
===================================================================
--- /trunk/src/VBox/Runtime/testcase/tstRTNetIPv4.cpp	(revision 50417)
+++ /trunk/src/VBox/Runtime/testcase/tstRTNetIPv4.cpp	(revision 50418)
@@ -66,4 +66,35 @@
 
 
+#define CHECKADDREX(String, Trailer, rcExpected, ExpectedAddr)          \
+    do {                                                                \
+        RTNETADDRIPV4 Addr;                                             \
+        const char *strAll = String /* concat */ Trailer;               \
+        const char *pTrailer = strAll + sizeof(String) - 1;             \
+        char *pNext = NULL;                                             \
+        int rc2 = RTNetStrToIPv4AddrEx(strAll, &Addr, &pNext);          \
+        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           \
+                         || pTrailer != pNext)))                        \
+        {                                                               \
+            RTTestIFailed("at line %d: '%s': expected %Rrc got %Rrc,"   \
+                          " expected address %RTnaipv4 got %RTnaipv4"   \
+                          " expected trailer \"%s\" got %s%s%s"         \
+                          "\n",                                         \
+                          __LINE__, String, rcExpected, rc2,            \
+                          RT_H2N_U32_C(ExpectedAddr), Addr.u,           \
+                          pTrailer,                                     \
+                          pNext ? "\"" : "",                            \
+                          pNext ? pNext : "(null)",                     \
+                          pNext ? "\"" : "");                           \
+        }                                                               \
+    } while (0)
+
+
 int main()
 {
@@ -91,4 +122,13 @@
     BADADDR("1.2.3.666");
 
+    /*
+     * Parsing itself is covered by the tests above, here we only
+     * check trailers
+     */
+    CHECKADDREX("1.2.3.4",  "",   VINF_SUCCESS,           0x01020304);
+    CHECKADDREX("1.2.3.4",  " ",  VINF_SUCCESS,           0x01020304);
+    CHECKADDREX("1.2.3.4",  "x",  VINF_SUCCESS,           0x01020304);
+    CHECKADDREX("1.2.3.444", "",  VERR_INVALID_PARAMETER,          0);
+
     return RTTestSummaryAndDestroy(hTest);
 }
