From 1c4cb6303647901affac8320bf49c388e34e515d Mon Sep 17 00:00:00 2001 From: Bruno Jesus <00cpxxx@gmail.com> Date: Mon, 8 Dec 2014 20:55:45 -0200 Subject: [PATCH] ws2_32: Implement getsockopt(SO_BSP_STATE). --- dlls/ws2_32/socket.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++ dlls/ws2_32/tests/sock.c | 21 ++++++++++++-- include/winsock.h | 1 + 3 files changed, 93 insertions(+), 2 deletions(-) diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 1864dfd0f14..b6aad67c02a 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -3095,6 +3095,79 @@ INT WINAPI WS_getsockopt(SOCKET s, INT level, } release_sock_fd( s, fd ); return ret; + case WS_SO_BSP_STATE: + { + int req_size, addr_size; + WSAPROTOCOL_INFOW infow; + CSADDR_INFO *csinfo; + + ret = ws_protocol_info(s, TRUE, &infow, &addr_size); + if (ret) + { + if (infow.iAddressFamily == WS_AF_INET) + addr_size = sizeof(struct sockaddr_in); + else if (infow.iAddressFamily == WS_AF_INET6) + addr_size = sizeof(struct sockaddr_in6); + else + { + FIXME("Family %d is unsupported for SO_BSP_STATE", infow.iAddressFamily); + SetLastError(WSAEAFNOSUPPORT); + return SOCKET_ERROR; + } + + req_size = sizeof(CSADDR_INFO) + addr_size * 2; + if (*optlen < req_size) + { + ret = 0; + SetLastError(WSAEFAULT); + } + else + { + union generic_unix_sockaddr uaddr; + socklen_t uaddrlen = sizeof(uaddr); + + if ( (fd = get_sock_fd( s, 0, NULL )) == -1) + return SOCKET_ERROR; + + csinfo = (CSADDR_INFO*) optval; + + /* Check if the sock is bound */ + if (!getsockname(fd, &uaddr.addr, &uaddrlen) && + is_sockaddr_bound(&uaddr.addr, uaddrlen)) + { + csinfo->LocalAddr.lpSockaddr = + (LPSOCKADDR) (optval + sizeof(CSADDR_INFO)); + ws_sockaddr_u2ws(&uaddr.addr, csinfo->LocalAddr.lpSockaddr, &addr_size); + csinfo->LocalAddr.iSockaddrLength = addr_size; + } + else + { + csinfo->LocalAddr.lpSockaddr = NULL; + csinfo->LocalAddr.iSockaddrLength = 0; + } + + /* Check if the sock is connected */ + if (!getpeername(fd, &uaddr.addr, &uaddrlen) && + is_sockaddr_bound(&uaddr.addr, uaddrlen)) + { + csinfo->RemoteAddr.lpSockaddr = + (LPSOCKADDR) (optval + sizeof(CSADDR_INFO) + addr_size); + ws_sockaddr_u2ws(&uaddr.addr, csinfo->RemoteAddr.lpSockaddr, &addr_size); + csinfo->RemoteAddr.iSockaddrLength = addr_size; + } + else + { + csinfo->RemoteAddr.lpSockaddr = NULL; + csinfo->RemoteAddr.iSockaddrLength = 0; + } + + csinfo->iSocketType = infow.iSocketType; + csinfo->iProtocol = infow.iProtocol; + release_sock_fd( s, fd ); + } + } + return ret ? 0 : SOCKET_ERROR; + } case WS_SO_DONTLINGER: { struct linger lingval; diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index f0946c996b6..49ebbf51582 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -1486,9 +1486,9 @@ todo_wine } /* Test SO_BSP_STATE - Present only in >= Win 2008 */ - s = socket(AF_INET, SOCK_STREAM, 0); + s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); ok(s != INVALID_SOCKET, "Failed to create socket\n"); - s2 = socket(AF_INET, SOCK_STREAM, 0); + s2 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); ok(s2 != INVALID_SOCKET, "Failed to create socket\n"); SetLastError(0xdeadbeef); @@ -1571,6 +1571,23 @@ todo_wine ok(!err, "Expected 0, got %d\n", err); ok(!memcmp(&saddr, csinfoB.cs.LocalAddr.lpSockaddr, size), "Expected matching addresses\n"); ok(!memcmp(&saddr, csinfoA.cs.RemoteAddr.lpSockaddr, size), "Expected matching addresses\n"); + + SetLastError(0xdeadbeef); + size = sizeof(CSADDR_INFO); + err = getsockopt(s, SOL_SOCKET, SO_BSP_STATE, (char *) &csinfoA, &size); + ok(err, "Expected non-zero\n"); + ok(size == sizeof(CSADDR_INFO), "Got %d\n", size); + ok(GetLastError() == WSAEFAULT, "Expected 10014, got %d\n", GetLastError()); + + /* At least for IPv4 the size is exactly 56 bytes */ + size = sizeof(*csinfoA.cs.LocalAddr.lpSockaddr) * 2 + sizeof(csinfoA.cs); + err = getsockopt(s, SOL_SOCKET, SO_BSP_STATE, (char *) &csinfoA, &size); + ok(!err, "Expected 0, got %d\n", err); + size--; + SetLastError(0xdeadbeef); + err = getsockopt(s, SOL_SOCKET, SO_BSP_STATE, (char *) &csinfoA, &size); + ok(err, "Expected non-zero\n"); + ok(GetLastError() == WSAEFAULT, "Expected 10014, got %d\n", GetLastError()); } else ok(GetLastError() == WSAENOPROTOOPT, "Expected 10042, got %d\n", GetLastError()); diff --git a/include/winsock.h b/include/winsock.h index 21e984c3ce9..50237e864af 100644 --- a/include/winsock.h +++ b/include/winsock.h @@ -697,6 +697,7 @@ typedef struct WS(WSAData) #define WS_SO_RCVTIMEO 0x1006 #define WS_SO_ERROR 0x1007 #define WS_SO_TYPE 0x1008 +#define WS_SO_BSP_STATE 0x1009 #define WS_IOCPARM_MASK 0x7f #define WS_IOC_VOID 0x20000000 -- 2.11.4.GIT