Damjan Jovanovic : ws2_32: getsockname should fail on unbound socket.
Alexandre Julliard
julliard at wine.codeweavers.com
Fri Jun 15 07:23:04 CDT 2007
Module: wine
Branch: master
Commit: 1cf9436efe47b858a4cae33c956a78b8bcf83fbf
URL: http://source.winehq.org/git/wine.git/?a=commit;h=1cf9436efe47b858a4cae33c956a78b8bcf83fbf
Author: Damjan Jovanovic <damjan.jov at gmail.com>
Date: Thu Jun 14 15:27:29 2007 +0200
ws2_32: getsockname should fail on unbound socket.
---
dlls/ws2_32/socket.c | 33 +++++++++++++++++++++++++++++++++
dlls/ws2_32/tests/sock.c | 10 ++++++++++
2 files changed, 43 insertions(+), 0 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index 456be21..aab3888 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -927,6 +927,35 @@ static unsigned int ws_sockaddr_ws2u(const struct WS_sockaddr* wsaddr, int wsadd
return uaddrlen;
}
+static BOOL is_sockaddr_bound(const struct sockaddr *uaddr, int uaddrlen)
+{
+ switch (uaddr->sa_family)
+ {
+#ifdef HAVE_IPX
+ case AF_IPX:
+ FIXME("don't know how to tell if IPX socket is bound, assuming it is!\n");
+ return TRUE;
+#endif
+ case AF_INET6:
+ {
+ static const struct sockaddr_in6 emptyAddr;
+ const struct sockaddr_in6 *in6 = (const struct sockaddr_in6*) uaddr;
+ return in6->sin6_port || memcmp(&in6->sin6_addr, &emptyAddr.sin6_addr, sizeof(struct in6_addr));
+ }
+ case AF_INET:
+ {
+ static const struct sockaddr_in emptyAddr;
+ const struct sockaddr_in *in = (const struct sockaddr_in*) uaddr;
+ return in->sin_port || memcmp(&in->sin_addr, &emptyAddr.sin_addr, sizeof(struct in_addr));
+ }
+ case AF_UNSPEC:
+ return FALSE;
+ default:
+ FIXME("unknown address family %d\n", uaddr->sa_family);
+ return TRUE;
+ }
+}
+
/* Returns 0 if successful, -1 if the buffer is too small */
static int ws_sockaddr_u2ws(const struct sockaddr* uaddr, struct WS_sockaddr* wsaddr, int* wsaddrlen)
{
@@ -1590,6 +1619,10 @@ int WINAPI WS_getsockname(SOCKET s, struct WS_sockaddr *name, int *namelen)
{
SetLastError(wsaErrno());
}
+ else if (!is_sockaddr_bound(&uaddr.addr, uaddrlen))
+ {
+ SetLastError(WSAEINVAL);
+ }
else if (ws_sockaddr_u2ws(&uaddr.addr, name, namelen) != 0)
{
/* The buffer was too small */
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
index 3403715..cc41320 100644
--- a/dlls/ws2_32/tests/sock.c
+++ b/dlls/ws2_32/tests/sock.c
@@ -1644,6 +1644,16 @@ static void test_getsockname(void)
return;
}
+ memcpy(&sa_get, &sa_set, sizeof(sa_set));
+ if (getsockname(sock, (struct sockaddr*) &sa_get, &sa_get_len) == 0)
+ ok(0, "getsockname on unbound socket should fail\n");
+ else {
+ ok(WSAGetLastError() == WSAEINVAL, "getsockname on unbound socket "
+ "failed with %d, expected %d\n", WSAGetLastError(), WSAEINVAL);
+ ok(memcmp(&sa_get, &sa_set, sizeof(sa_get)) == 0,
+ "failed getsockname modified sockaddr when it shouldn't\n");
+ }
+
if(bind(sock, (struct sockaddr *) &sa_set, sa_set_len) < 0){
trace("Failed to bind socket: %d\n", WSAGetLastError());
closesocket(sock);
More information about the wine-cvs
mailing list