Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/ntdll/unix/socket.c | 3 +++ dlls/ws2_32/socket.c | 2 ++ include/wine/afd.h | 1 + 3 files changed, 6 insertions(+)
diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c index e9239bd7bb9..0a0ba7e2a98 100644 --- a/dlls/ntdll/unix/socket.c +++ b/dlls/ntdll/unix/socket.c @@ -1882,6 +1882,9 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc case IOCTL_AFD_WINE_SET_IPV6_MULTICAST_LOOP: return do_setsockopt( handle, io, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, in_buffer, in_size );
+ case IOCTL_AFD_WINE_GET_IPV6_UNICAST_HOPS: + return do_getsockopt( handle, io, IPPROTO_IPV6, IPV6_UNICAST_HOPS, out_buffer, out_size ); + default: { if ((code >> 16) == FILE_DEVICE_NETWORK) diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 1f8020b5c3e..87f864d3c2b 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -2422,6 +2422,8 @@ INT WINAPI WS_getsockopt(SOCKET s, INT level, return server_getsockopt( s, IOCTL_AFD_WINE_GET_IPV6_MULTICAST_LOOP, optval, optlen );
case WS_IPV6_UNICAST_HOPS: + return server_getsockopt( s, IOCTL_AFD_WINE_GET_IPV6_UNICAST_HOPS, optval, optlen ); + case WS_IPV6_V6ONLY: #ifdef IPV6_UNICAST_IF case WS_IPV6_UNICAST_IF: diff --git a/include/wine/afd.h b/include/wine/afd.h index 6c84b72c028..9427ce46535 100644 --- a/include/wine/afd.h +++ b/include/wine/afd.h @@ -217,6 +217,7 @@ struct afd_get_events_params #define IOCTL_AFD_WINE_SET_IPV6_MULTICAST_IF WINE_AFD_IOC(272) #define IOCTL_AFD_WINE_GET_IPV6_MULTICAST_LOOP WINE_AFD_IOC(273) #define IOCTL_AFD_WINE_SET_IPV6_MULTICAST_LOOP WINE_AFD_IOC(274) +#define IOCTL_AFD_WINE_GET_IPV6_UNICAST_HOPS WINE_AFD_IOC(275)
struct afd_create_params {
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/ntdll/unix/socket.c | 3 +++ dlls/ws2_32/socket.c | 5 ++++- include/wine/afd.h | 1 + 3 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c index 0a0ba7e2a98..efbfc375969 100644 --- a/dlls/ntdll/unix/socket.c +++ b/dlls/ntdll/unix/socket.c @@ -1885,6 +1885,9 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc case IOCTL_AFD_WINE_GET_IPV6_UNICAST_HOPS: return do_getsockopt( handle, io, IPPROTO_IPV6, IPV6_UNICAST_HOPS, out_buffer, out_size );
+ case IOCTL_AFD_WINE_SET_IPV6_UNICAST_HOPS: + return do_setsockopt( handle, io, IPPROTO_IPV6, IPV6_UNICAST_HOPS, in_buffer, in_size ); + default: { if ((code >> 16) == FILE_DEVICE_NETWORK) diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 87f864d3c2b..3ca2ce545b4 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -3642,7 +3642,6 @@ int WINAPI WS_setsockopt(SOCKET s, int level, int optname, case WS_IPV6_MULTICAST_LOOP: return server_setsockopt( s, IOCTL_AFD_WINE_SET_IPV6_MULTICAST_LOOP, optval, optlen );
- case WS_IPV6_UNICAST_HOPS: #ifdef IPV6_UNICAST_IF case WS_IPV6_UNICAST_IF: #endif @@ -3651,6 +3650,10 @@ int WINAPI WS_setsockopt(SOCKET s, int level, int optname, case WS_IPV6_PROTECTION_LEVEL: FIXME("IPV6_PROTECTION_LEVEL is ignored!\n"); return 0; + + case WS_IPV6_UNICAST_HOPS: + return server_setsockopt( s, IOCTL_AFD_WINE_SET_IPV6_UNICAST_HOPS, optval, optlen ); + case WS_IPV6_V6ONLY: { union generic_unix_sockaddr uaddr; diff --git a/include/wine/afd.h b/include/wine/afd.h index 9427ce46535..64d555889f5 100644 --- a/include/wine/afd.h +++ b/include/wine/afd.h @@ -218,6 +218,7 @@ struct afd_get_events_params #define IOCTL_AFD_WINE_GET_IPV6_MULTICAST_LOOP WINE_AFD_IOC(273) #define IOCTL_AFD_WINE_SET_IPV6_MULTICAST_LOOP WINE_AFD_IOC(274) #define IOCTL_AFD_WINE_GET_IPV6_UNICAST_HOPS WINE_AFD_IOC(275) +#define IOCTL_AFD_WINE_SET_IPV6_UNICAST_HOPS WINE_AFD_IOC(276)
struct afd_create_params {
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/ntdll/unix/socket.c | 5 +++++ dlls/ws2_32/socket.c | 6 +++--- include/wine/afd.h | 1 + 3 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c index efbfc375969..09318a279ed 100644 --- a/dlls/ntdll/unix/socket.c +++ b/dlls/ntdll/unix/socket.c @@ -1888,6 +1888,11 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc case IOCTL_AFD_WINE_SET_IPV6_UNICAST_HOPS: return do_setsockopt( handle, io, IPPROTO_IPV6, IPV6_UNICAST_HOPS, in_buffer, in_size );
+#ifdef IPV6_UNICAST_IF + case IOCTL_AFD_WINE_GET_IPV6_UNICAST_IF: + return do_getsockopt( handle, io, IPPROTO_IPV6, IPV6_UNICAST_IF, out_buffer, out_size ); +#endif + default: { if ((code >> 16) == FILE_DEVICE_NETWORK) diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 3ca2ce545b4..2ca4f2c1831 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -2424,10 +2424,10 @@ INT WINAPI WS_getsockopt(SOCKET s, INT level, case WS_IPV6_UNICAST_HOPS: return server_getsockopt( s, IOCTL_AFD_WINE_GET_IPV6_UNICAST_HOPS, optval, optlen );
- case WS_IPV6_V6ONLY: -#ifdef IPV6_UNICAST_IF case WS_IPV6_UNICAST_IF: -#endif + return server_getsockopt( s, IOCTL_AFD_WINE_GET_IPV6_UNICAST_IF, optval, optlen ); + + case WS_IPV6_V6ONLY: if ( (fd = get_sock_fd( s, 0, NULL )) == -1) return SOCKET_ERROR; convert_sockopt(&level, &optname); diff --git a/include/wine/afd.h b/include/wine/afd.h index 64d555889f5..b43d53522a4 100644 --- a/include/wine/afd.h +++ b/include/wine/afd.h @@ -219,6 +219,7 @@ struct afd_get_events_params #define IOCTL_AFD_WINE_SET_IPV6_MULTICAST_LOOP WINE_AFD_IOC(274) #define IOCTL_AFD_WINE_GET_IPV6_UNICAST_HOPS WINE_AFD_IOC(275) #define IOCTL_AFD_WINE_SET_IPV6_UNICAST_HOPS WINE_AFD_IOC(276) +#define IOCTL_AFD_WINE_GET_IPV6_UNICAST_IF WINE_AFD_IOC(277)
struct afd_create_params {
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/ntdll/unix/socket.c | 3 +++ dlls/ws2_32/socket.c | 8 +++----- include/wine/afd.h | 1 + 3 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c index 09318a279ed..27d7e1c06d2 100644 --- a/dlls/ntdll/unix/socket.c +++ b/dlls/ntdll/unix/socket.c @@ -1891,6 +1891,9 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc #ifdef IPV6_UNICAST_IF case IOCTL_AFD_WINE_GET_IPV6_UNICAST_IF: return do_getsockopt( handle, io, IPPROTO_IPV6, IPV6_UNICAST_IF, out_buffer, out_size ); + + case IOCTL_AFD_WINE_SET_IPV6_UNICAST_IF: + return do_setsockopt( handle, io, IPPROTO_IPV6, IPV6_UNICAST_IF, in_buffer, in_size ); #endif
default: diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 2ca4f2c1831..769b6e5cea0 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -3642,11 +3642,6 @@ int WINAPI WS_setsockopt(SOCKET s, int level, int optname, case WS_IPV6_MULTICAST_LOOP: return server_setsockopt( s, IOCTL_AFD_WINE_SET_IPV6_MULTICAST_LOOP, optval, optlen );
-#ifdef IPV6_UNICAST_IF - case WS_IPV6_UNICAST_IF: -#endif - convert_sockopt(&level, &optname); - break; case WS_IPV6_PROTECTION_LEVEL: FIXME("IPV6_PROTECTION_LEVEL is ignored!\n"); return 0; @@ -3654,6 +3649,9 @@ int WINAPI WS_setsockopt(SOCKET s, int level, int optname, case WS_IPV6_UNICAST_HOPS: return server_setsockopt( s, IOCTL_AFD_WINE_SET_IPV6_UNICAST_HOPS, optval, optlen );
+ case WS_IPV6_UNICAST_IF: + return server_setsockopt( s, IOCTL_AFD_WINE_SET_IPV6_UNICAST_IF, optval, optlen ); + case WS_IPV6_V6ONLY: { union generic_unix_sockaddr uaddr; diff --git a/include/wine/afd.h b/include/wine/afd.h index b43d53522a4..8aba4dd3c71 100644 --- a/include/wine/afd.h +++ b/include/wine/afd.h @@ -220,6 +220,7 @@ struct afd_get_events_params #define IOCTL_AFD_WINE_GET_IPV6_UNICAST_HOPS WINE_AFD_IOC(275) #define IOCTL_AFD_WINE_SET_IPV6_UNICAST_HOPS WINE_AFD_IOC(276) #define IOCTL_AFD_WINE_GET_IPV6_UNICAST_IF WINE_AFD_IOC(277) +#define IOCTL_AFD_WINE_SET_IPV6_UNICAST_IF WINE_AFD_IOC(278)
struct afd_create_params {
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/ntdll/unix/socket.c | 3 +++ dlls/ws2_32/socket.c | 11 +---------- include/wine/afd.h | 1 + 3 files changed, 5 insertions(+), 10 deletions(-)
diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c index 27d7e1c06d2..bda23d0b9b1 100644 --- a/dlls/ntdll/unix/socket.c +++ b/dlls/ntdll/unix/socket.c @@ -1896,6 +1896,9 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc return do_setsockopt( handle, io, IPPROTO_IPV6, IPV6_UNICAST_IF, in_buffer, in_size ); #endif
+ case IOCTL_AFD_WINE_GET_IPV6_V6ONLY: + return do_getsockopt( handle, io, IPPROTO_IPV6, IPV6_V6ONLY, out_buffer, out_size ); + default: { if ((code >> 16) == FILE_DEVICE_NETWORK) diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 769b6e5cea0..30faad3a546 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -2428,16 +2428,7 @@ INT WINAPI WS_getsockopt(SOCKET s, INT level, return server_getsockopt( s, IOCTL_AFD_WINE_GET_IPV6_UNICAST_IF, optval, optlen );
case WS_IPV6_V6ONLY: - if ( (fd = get_sock_fd( s, 0, NULL )) == -1) - return SOCKET_ERROR; - convert_sockopt(&level, &optname); - if (getsockopt(fd, level, optname, optval, (socklen_t *)optlen) != 0 ) - { - SetLastError(wsaErrno()); - ret = SOCKET_ERROR; - } - release_sock_fd( s, fd ); - return ret; + return server_getsockopt( s, IOCTL_AFD_WINE_GET_IPV6_V6ONLY, optval, optlen );
default: FIXME( "unrecognized IPv6 option %u\n", optname ); diff --git a/include/wine/afd.h b/include/wine/afd.h index 8aba4dd3c71..47ddd09f1c0 100644 --- a/include/wine/afd.h +++ b/include/wine/afd.h @@ -221,6 +221,7 @@ struct afd_get_events_params #define IOCTL_AFD_WINE_SET_IPV6_UNICAST_HOPS WINE_AFD_IOC(276) #define IOCTL_AFD_WINE_GET_IPV6_UNICAST_IF WINE_AFD_IOC(277) #define IOCTL_AFD_WINE_SET_IPV6_UNICAST_IF WINE_AFD_IOC(278) +#define IOCTL_AFD_WINE_GET_IPV6_V6ONLY WINE_AFD_IOC(279)
struct afd_create_params {
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/ntdll/unix/socket.c | 23 +++++++++++++ dlls/ws2_32/socket.c | 73 +--------------------------------------- include/wine/afd.h | 1 + 3 files changed, 25 insertions(+), 72 deletions(-)
diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c index bda23d0b9b1..24090c1a17b 100644 --- a/dlls/ntdll/unix/socket.c +++ b/dlls/ntdll/unix/socket.c @@ -1899,6 +1899,29 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc case IOCTL_AFD_WINE_GET_IPV6_V6ONLY: return do_getsockopt( handle, io, IPPROTO_IPV6, IPV6_V6ONLY, out_buffer, out_size );
+ case IOCTL_AFD_WINE_SET_IPV6_V6ONLY: + { + int fd, needs_close = FALSE; + union unix_sockaddr addr; + socklen_t len = sizeof(addr); + NTSTATUS status; + int ret; + + if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL ))) + return status; + + if (!getsockname( fd, &addr.addr, &len ) && addr.addr.sa_family == AF_INET && !addr.in.sin_port) + { + /* changing IPV6_V6ONLY succeeds on an unbound IPv4 socket */ + WARN( "ignoring IPV6_V6ONLY on an unbound IPv4 socket\n" ); + return STATUS_SUCCESS; + } + + ret = setsockopt( fd, IPPROTO_IPV6, IPV6_V6ONLY, in_buffer, in_size ); + if (needs_close) close( fd ); + return ret ? sock_errno_to_status( errno ) : STATUS_SUCCESS; + } + default: { if ((code >> 16) == FILE_DEVICE_NETWORK) diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 30faad3a546..a28c25ec697 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -1081,56 +1081,6 @@ unsigned int ws_sockaddr_ws2u( const struct WS_sockaddr *wsaddr, int wsaddrlen, return uaddrlen; }
-static BOOL is_sockaddr_bound(const struct sockaddr *uaddr, int uaddrlen) -{ - switch (uaddr->sa_family) - { -#ifdef HAS_IPX - case AF_IPX: - { - static const struct sockaddr_ipx emptyAddr; - struct sockaddr_ipx *ipx = (struct sockaddr_ipx*) uaddr; - return ipx->sipx_port - || memcmp(&ipx->sipx_network, &emptyAddr.sipx_network, sizeof(emptyAddr.sipx_network)) - || memcmp(&ipx->sipx_node, &emptyAddr.sipx_node, sizeof(emptyAddr.sipx_node)); - } -#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 -1 if getsockname fails, 0 if not bound, 1 otherwise */ -static int is_fd_bound(int fd, union generic_unix_sockaddr *uaddr, socklen_t *uaddrlen) -{ - union generic_unix_sockaddr inaddr; - socklen_t inlen; - int res; - - if (!uaddr) uaddr = &inaddr; - if (!uaddrlen) uaddrlen = &inlen; - - *uaddrlen = sizeof(inaddr); - res = getsockname(fd, &uaddr->addr, uaddrlen); - if (!res) res = is_sockaddr_bound(&uaddr->addr, *uaddrlen); - return res; -} - /* Returns 0 if successful, -1 if the buffer is too small */ int ws_sockaddr_u2ws(const struct sockaddr *uaddr, struct WS_sockaddr *wsaddr, int *wsaddrlen) { @@ -3644,29 +3594,8 @@ int WINAPI WS_setsockopt(SOCKET s, int level, int optname, return server_setsockopt( s, IOCTL_AFD_WINE_SET_IPV6_UNICAST_IF, optval, optlen );
case WS_IPV6_V6ONLY: - { - union generic_unix_sockaddr uaddr; - socklen_t uaddrlen; - int bound; + return server_setsockopt( s, IOCTL_AFD_WINE_SET_IPV6_V6ONLY, optval, optlen );
- fd = get_sock_fd( s, 0, NULL ); - if (fd == -1) return SOCKET_ERROR; - - bound = is_fd_bound(fd, &uaddr, &uaddrlen); - release_sock_fd( s, fd ); - if (bound == 0 && uaddr.addr.sa_family == AF_INET) - { - /* Changing IPV6_V6ONLY succeeds on AF_INET (IPv4) socket - * on Windows (with IPv6 support) if the socket is unbound. - * It is essentially a noop, though Windows does store the value - */ - WARN("Silently ignoring IPPROTO_IPV6+IPV6_V6ONLY on AF_INET socket\n"); - return 0; - } - level = IPPROTO_IPV6; - optname = IPV6_V6ONLY; - break; - } default: FIXME("Unknown IPPROTO_IPV6 optname 0x%08x\n", optname); return SOCKET_ERROR; diff --git a/include/wine/afd.h b/include/wine/afd.h index 47ddd09f1c0..9a1edb1fda6 100644 --- a/include/wine/afd.h +++ b/include/wine/afd.h @@ -222,6 +222,7 @@ struct afd_get_events_params #define IOCTL_AFD_WINE_GET_IPV6_UNICAST_IF WINE_AFD_IOC(277) #define IOCTL_AFD_WINE_SET_IPV6_UNICAST_IF WINE_AFD_IOC(278) #define IOCTL_AFD_WINE_GET_IPV6_V6ONLY WINE_AFD_IOC(279) +#define IOCTL_AFD_WINE_SET_IPV6_V6ONLY WINE_AFD_IOC(280)
struct afd_create_params {