ws2_32: Add tests and implement inet_pton

Bruno Jesus 00cpxxx at gmail.com
Mon Nov 3 15:16:14 CST 2014


Special thanks to Erich Hoover.

Fixes https://bugs.winehq.org/show_bug.cgi?id=36713
-------------- next part --------------
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index 0bcce40..b3db306 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -6911,6 +6911,40 @@ PCSTR WINAPI WS_inet_ntop( INT family, PVOID addr, PSTR buffer, SIZE_T len )
 }
 
 /***********************************************************************
+*              inet_pton                      (WS2_32.@)
+*/
+INT WINAPI WS_inet_pton( INT family, PCSTR addr, PVOID buffer)
+{
+#ifdef HAVE_INET_PTON
+    int unixaf, ret;
+
+    TRACE("family %d, addr '%s', buffer (%p)\n", family, addr ? addr : "(null)", buffer);
+
+    if (!addr || !buffer)
+    {
+        SetLastError(WSAEFAULT);
+        return SOCKET_ERROR;
+    }
+
+    unixaf = convert_af_w2u(family);
+    if (unixaf != AF_INET && unixaf != AF_INET6)
+    {
+        SetLastError(WSAEAFNOSUPPORT);
+        return SOCKET_ERROR;
+    }
+
+    ret = inet_pton(unixaf, addr, buffer);
+    if (ret == -1) SetLastError(wsaErrno());
+    return ret;
+#else
+    FIXME( "not supported on this platform\n" );
+    WSASetLastError( WSAEAFNOSUPPORT );
+    return SOCKET_ERROR;
+#endif
+}
+
+
+/***********************************************************************
  *              WSAStringToAddressA                      (WS2_32.80)
  */
 INT WINAPI WSAStringToAddressA(LPSTR AddressString,
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
index 0ad6e8a..0c39545 100644
--- a/dlls/ws2_32/tests/sock.c
+++ b/dlls/ws2_32/tests/sock.c
@@ -67,6 +67,7 @@ static int   (WINAPI *pgetaddrinfo)(LPCSTR,LPCSTR,const struct addrinfo *,struct
 static void  (WINAPI *pFreeAddrInfoW)(PADDRINFOW);
 static int   (WINAPI *pGetAddrInfoW)(LPCWSTR,LPCWSTR,const ADDRINFOW *,PADDRINFOW *);
 static PCSTR (WINAPI *pInetNtop)(INT,LPVOID,LPSTR,ULONG);
+static int   (WINAPI *pInetPton)(INT,LPSTR,LPVOID);
 static int   (WINAPI *pWSALookupServiceBeginW)(LPWSAQUERYSETW,DWORD,LPHANDLE);
 static int   (WINAPI *pWSALookupServiceEnd)(HANDLE);
 static int   (WINAPI *pWSALookupServiceNextW)(HANDLE,DWORD,LPDWORD,LPWSAQUERYSETW);
@@ -1139,6 +1140,7 @@ static void Init (void)
     pFreeAddrInfoW = (void *)GetProcAddress(hws2_32, "FreeAddrInfoW");
     pGetAddrInfoW = (void *)GetProcAddress(hws2_32, "GetAddrInfoW");
     pInetNtop = (void *)GetProcAddress(hws2_32, "inet_ntop");
+    pInetPton = (void *)GetProcAddress(hws2_32, "inet_pton");
     pWSALookupServiceBeginW = (void *)GetProcAddress(hws2_32, "WSALookupServiceBeginW");
     pWSALookupServiceEnd = (void *)GetProcAddress(hws2_32, "WSALookupServiceEnd");
     pWSALookupServiceNextW = (void *)GetProcAddress(hws2_32, "WSALookupServiceNextW");
@@ -3987,6 +3989,117 @@ static void test_addr_to_print(void)
     pdst = pInetNtop(AF_INET6, (void*)&in6.s6_addr, dst6, 18);
     ok(pdst != NULL, "The pointer should be returned (%p)\n", pdst);
 }
+static void test_inet_pton(void)
+{
+    struct TEST_DATA
+    {
+        int family, ret;
+        DWORD err;
+        const char *printable, *collapsed, *raw_data;
+    } tests[] = {
+        {AF_UNSPEC, -1, WSAEFAULT,    /* Test 0 */
+        NULL, NULL, NULL},
+        {AF_INET, -1, WSAEFAULT,
+        NULL, NULL, NULL},
+        {AF_INET6, -1, WSAEFAULT,
+        NULL, NULL, NULL},
+        {AF_UNSPEC, -1, WSAEAFNOSUPPORT,
+        "127.0.0.1", NULL, NULL},
+        {AF_INET, 1, 0,
+        "127.0.0.1", "127.0.0.1",
+        "\x7f\x00\x00\x01"},
+        {AF_INET6, 0, 0,
+        "127.0.0.1", "127.0.0.1", NULL},
+        {AF_INET, 0, 0,
+        "::1/128", NULL, NULL},
+        {AF_INET6, 0, 0,
+        "::1/128", NULL, NULL},
+        {AF_UNSPEC, -1, WSAEAFNOSUPPORT,
+        "broken", NULL, NULL},
+        {AF_INET, 0, 0,
+        "broken", NULL, NULL},
+        {AF_INET6, 0, 0,              /* Test 10 */
+        "broken", NULL, NULL},
+        {AF_UNSPEC, -1, WSAEAFNOSUPPORT,
+        "177.32.45.20", NULL, NULL},
+        {AF_INET, 1, 0,
+        "177.32.45.20", "177.32.45.20",
+        "\xb1\x20\x2d\x14"},
+        {AF_INET6, 0, 0,
+        "177.32.45.20", NULL, NULL},
+        {AF_INET, 0, 0,
+        "2607:f0d0:1002:51::4", NULL, NULL},
+        {AF_INET6, 1, 0,
+        "2607:f0d0:1002:51::4", "2607:f0d0:1002:51::4",
+        "\x26\x07\xf0\xd0\x10\x02\x00\x51\x00\x00\x00\x00\x00\x00\x00\x04"},
+        {AF_INET, 0, 0,
+        "::177.32.45.20", NULL, NULL},
+        {AF_INET6, 1, 0,
+        "::177.32.45.20", "::177.32.45.20",
+        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb1\x20\x2d\x14"},
+        {AF_INET, 0, 0,
+        "fe80::0202:b3ff:fe1e:8329", NULL, NULL},
+        {AF_INET6, 1, 0,
+        "fe80::0202:b3ff:fe1e:8329", "fe80::202:b3ff:fe1e:8329",
+        "\xfe\x80\x00\x00\x00\x00\x00\x00\x02\x02\xb3\xff\xfe\x1e\x83\x29"},
+        {AF_INET6, 1, 0,              /* Test 20 */
+        "fe80::202:b3ff:fe1e:8329", "fe80::202:b3ff:fe1e:8329",
+        "\xfe\x80\x00\x00\x00\x00\x00\x00\x02\x02\xb3\xff\xfe\x1e\x83\x29"},
+        {AF_INET, 0, 0,
+        "a", NULL, NULL},
+        {AF_INET, 0, 0,
+        "a.b", NULL, NULL},
+        {AF_INET, 0, 0,
+        "a.b.c",  NULL, NULL},
+        {AF_INET, 0, 0,
+        "a.b.c.d", NULL, NULL},
+        {AF_INET6, 1, 0,
+        "2001:cdba:0000:0000:0000:0000:3257:9652", "2001:cdba::3257:9652",
+        "\x20\x01\xcd\xba\x00\x00\x00\x00\x00\x00\x00\x00\x32\x57\x96\x52"},
+        {AF_INET6, 1, 0,
+        "2001:cdba::3257:9652", "2001:cdba::3257:9652",
+        "\x20\x01\xcd\xba\x00\x00\x00\x00\x00\x00\x00\x00\x32\x57\x96\x52"},
+        {AF_INET6, 1, 0,
+        "2001:cdba:0:0:0:0:3257:9652", "2001:cdba::3257:9652",
+        "\x20\x01\xcd\xba\x00\x00\x00\x00\x00\x00\x00\x00\x32\x57\x96\x52"}
+    };
+    int i, ret;
+    DWORD err;
+    char buffer[64],str[64];
+    const char *ptr;
+
+    /* InetNtop and InetPton became available in Vista and Win2008 */
+    if (!pInetNtop || !pInetPton)
+    {
+        win_skip("InetNtop and/or InetPton not present, not executing tests\n");
+        return;
+    }
+
+    for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
+    {
+        WSASetLastError(0xdeadbeef);
+        ret = pInetPton(tests[i].family, (char *)tests[i].printable, buffer);
+        ok (ret == tests[i].ret, "Test [%d]: Expected %d, got %d\n", i, tests[i].ret, ret);
+        if (tests[i].ret == -1)
+        {
+            err = WSAGetLastError();
+            ok (tests[i].err == err, "Test [%d]: Expected 0x%x, got 0x%x\n", i, tests[i].err, err);
+        }
+        if (tests[i].ret != 1) continue;
+        ok (memcmp(buffer, tests[i].raw_data,
+            tests[i].family == AF_INET ? sizeof(struct in_addr) : sizeof(struct in6_addr)) == 0,
+            "Test [%d]: Expected binary data differs\n", i);
+
+        /* Test the result from Pton with Ntop */
+        strcpy (str, "deadbeef");
+        ptr = pInetNtop(tests[i].family, buffer, str, sizeof(str));
+        ok (ptr != NULL, "Test [%d]: Failed with NULL\n", i);
+        ok (ptr == str, "Test [%d]: Pointers differ (%p != %p)\n", i, ptr, str);
+        if (!ptr) continue;
+        ok (strcmp(ptr, tests[i].collapsed) == 0, "Test [%d]: Expected '%s', got '%s'\n",
+            i, tests[i].collapsed, ptr);
+    }
+}
 
 static void test_ioctlsocket(void)
 {
@@ -7739,6 +7852,7 @@ START_TEST( sock )
     Init();
 
     test_inet_ntoa();
+    test_inet_pton();
     test_set_getsockopt();
     test_so_reuseaddr();
     test_ip_pktinfo();
diff --git a/dlls/ws2_32/ws2_32.spec b/dlls/ws2_32/ws2_32.spec
index 0811b74..f7c6c2d 100644
--- a/dlls/ws2_32/ws2_32.spec
+++ b/dlls/ws2_32/ws2_32.spec
@@ -121,3 +121,4 @@
 @ stdcall getaddrinfo(str str ptr ptr) WS_getaddrinfo
 @ stdcall getnameinfo(ptr long ptr long ptr long long) WS_getnameinfo
 @ stdcall inet_ntop(long ptr ptr long) WS_inet_ntop
+@ stdcall inet_pton(long ptr ptr) WS_inet_pton


More information about the wine-patches mailing list