Signed-off-by: Alex Henrie alexhenrie24@gmail.com --- dlls/ntdll/unix/socket.c | 18 ++++++++++++++++++ dlls/ws2_32/socket.c | 7 +++++++ dlls/ws2_32/tests/sock.c | 26 ++++++++++++++++++++++++-- include/wine/afd.h | 2 ++ 4 files changed, 51 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c index 35c846eb7ae..4f0c83597df 100644 --- a/dlls/ntdll/unix/socket.c +++ b/dlls/ntdll/unix/socket.c @@ -462,6 +462,16 @@ static int convert_control_headers(struct msghdr *hdr, WSABUF *control) } #endif /* IPV6_PKTINFO */
+#if defined(IPV6_TCLASS) + case IPV6_TCLASS: + { + ptr = fill_control_message( WS_IPPROTO_IPV6, WS_IPV6_TCLASS, ptr, &ctlsize, + CMSG_DATA(cmsg_unix), sizeof(INT) ); + if (!ptr) goto error; + break; + } +#endif /* IPV6_TCLASS */ + default: FIXME("Unhandled IPPROTO_IPV6 message header type %d\n", cmsg_unix->cmsg_type); break; @@ -1916,6 +1926,14 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc return do_setsockopt( handle, io, IPPROTO_IPV6, IPV6_RECVPKTINFO, in_buffer, in_size ); #endif
+#ifdef IPV6_RECVTCLASS + case IOCTL_AFD_WINE_GET_IPV6_RECVTCLASS: + return do_getsockopt( handle, io, IPPROTO_IPV6, IPV6_RECVTCLASS, out_buffer, out_size ); + + case IOCTL_AFD_WINE_SET_IPV6_RECVTCLASS: + return do_setsockopt( handle, io, IPPROTO_IPV6, IPV6_RECVTCLASS, in_buffer, in_size ); +#endif + case IOCTL_AFD_WINE_GET_IPV6_UNICAST_HOPS: return do_getsockopt( handle, io, IPPROTO_IPV6, IPV6_UNICAST_HOPS, out_buffer, out_size );
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 8f0ab12303a..3d88e45c66e 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -311,6 +311,7 @@ static inline const char *debugstr_sockopt(int level, int optname) DEBUG_SOCKOPT(IPV6_MULTICAST_HOPS); DEBUG_SOCKOPT(IPV6_MULTICAST_LOOP); DEBUG_SOCKOPT(IPV6_PKTINFO); + DEBUG_SOCKOPT(IPV6_RECVTCLASS); DEBUG_SOCKOPT(IPV6_UNICAST_HOPS); DEBUG_SOCKOPT(IPV6_V6ONLY); DEBUG_SOCKOPT(IPV6_UNICAST_IF); @@ -1734,6 +1735,9 @@ int WINAPI getsockopt( SOCKET s, int level, int optname, char *optval, int *optl case IPV6_PKTINFO: return server_getsockopt( s, IOCTL_AFD_WINE_GET_IPV6_RECVPKTINFO, optval, optlen );
+ case IPV6_RECVTCLASS: + return server_getsockopt( s, IOCTL_AFD_WINE_GET_IPV6_RECVTCLASS, optval, optlen ); + case IPV6_UNICAST_HOPS: return server_getsockopt( s, IOCTL_AFD_WINE_GET_IPV6_UNICAST_HOPS, optval, optlen );
@@ -2942,6 +2946,9 @@ int WINAPI setsockopt( SOCKET s, int level, int optname, const char *optval, int FIXME("IPV6_PROTECTION_LEVEL is ignored!\n"); return 0;
+ case IPV6_RECVTCLASS: + return server_setsockopt( s, IOCTL_AFD_WINE_SET_IPV6_RECVTCLASS, optval, optlen ); + case IPV6_UNICAST_HOPS: return server_setsockopt( s, IOCTL_AFD_WINE_SET_IPV6_UNICAST_HOPS, optval, optlen );
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index dd8c83374d0..6693c469dce 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -2002,7 +2002,7 @@ static void test_ipv6_cmsg(void) WSAMSG msg = {NULL, 0, &payload_buf, 1, {sizeof(control), control}, 0}; WSACMSGHDR *header = (WSACMSGHDR *)control; LPFN_WSARECVMSG pWSARecvMsg; - INT *hop_limit = (INT *)WSA_CMSG_DATA(header); + INT *int_data = (INT *)WSA_CMSG_DATA(header); IN6_PKTINFO *pkt_info = (IN6_PKTINFO *)WSA_CMSG_DATA(header); DWORD count, state; int rc; @@ -2043,7 +2043,7 @@ static void test_ipv6_cmsg(void) ok(header->cmsg_type == IPV6_HOPLIMIT, "expected IPV6_HOPLIMIT, got %i\n", header->cmsg_type); ok(header->cmsg_len == sizeof(*header) + sizeof(INT), "expected length %i, got %i\n", (INT)(sizeof(*header) + sizeof(INT)), (INT)header->cmsg_len); - ok(*hop_limit >= 32, "expected at least 32, got %i\n", *hop_limit); + ok(*int_data >= 32, "expected at least 32, got %i\n", *int_data); setsockopt(server, IPPROTO_IPV6, IPV6_HOPLIMIT, (const char *)&off, sizeof(off)); ok(!rc, "failed to clear IPV6_HOPLIMIT, error %u\n", WSAGetLastError());
@@ -2069,6 +2069,28 @@ static void test_ipv6_cmsg(void) rc = setsockopt(server, IPPROTO_IPV6, IPV6_PKTINFO, (const char *)&off, sizeof(off)); ok(!rc, "failed to clear IPV6_PKTINFO, error %u\n", WSAGetLastError());
+ memset(control, 0, sizeof(control)); + msg.Control.len = sizeof(control); + rc = setsockopt(server, IPPROTO_IPV6, IPV6_RECVTCLASS, (const char *)&on, sizeof(on)); + ok(!rc, "failed to set IPV6_RECVTCLASS, error %u\n", WSAGetLastError()); + state = 0; + count = sizeof(state); + rc = getsockopt(server, IPPROTO_IPV6, IPV6_RECVTCLASS, (char *)&state, (INT *)&count); + ok(!rc, "failed to get IPV6_RECVTCLASS, error %u\n", WSAGetLastError()); + ok(state == 1, "expected 1, got %u\n", state); + rc = send(client, payload, sizeof(payload), 0); + ok(rc == sizeof(payload), "send failed, error %u\n", WSAGetLastError()); + rc = pWSARecvMsg(server, &msg, &count, NULL, NULL); + ok(!rc, "WSARecvMsg failed, error %u\n", WSAGetLastError()); + ok(count == sizeof(payload), "expected length %i, got %i\n", (INT)sizeof(payload), count); + ok(header->cmsg_level == IPPROTO_IPV6, "expected IPPROTO_IPV6, got %i\n", header->cmsg_level); + ok(header->cmsg_type == IPV6_TCLASS, "expected IPV6_TCLASS, got %i\n", header->cmsg_type); + ok(header->cmsg_len == sizeof(*header) + sizeof(INT), + "expected length %i, got %i\n", (INT)(sizeof(*header) + sizeof(INT)), (INT)header->cmsg_len); + ok(*int_data == 0, "expected 0, got %i\n", *int_data); + rc = setsockopt(server, IPPROTO_IPV6, IPV6_RECVTCLASS, (const char *)&off, sizeof(off)); + ok(!rc, "failed to clear IPV6_RECVTCLASS, error %u\n", WSAGetLastError()); + closesocket(server); closesocket(client); } diff --git a/include/wine/afd.h b/include/wine/afd.h index 3936dbd87b1..49bbcccd3af 100644 --- a/include/wine/afd.h +++ b/include/wine/afd.h @@ -231,6 +231,8 @@ struct afd_get_events_params #define IOCTL_AFD_WINE_SET_IPV6_RECVHOPLIMIT WINE_AFD_IOC(287) #define IOCTL_AFD_WINE_GET_IPV6_RECVPKTINFO WINE_AFD_IOC(288) #define IOCTL_AFD_WINE_SET_IPV6_RECVPKTINFO WINE_AFD_IOC(289) +#define IOCTL_AFD_WINE_GET_IPV6_RECVTCLASS WINE_AFD_IOC(290) +#define IOCTL_AFD_WINE_SET_IPV6_RECVTCLASS WINE_AFD_IOC(291)
struct afd_create_params {
Signed-off-by: Alex Henrie alexhenrie24@gmail.com --- dlls/ws2_32/socket.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 3d88e45c66e..9a45124cd9e 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -2842,6 +2842,7 @@ int WINAPI setsockopt( SOCKET s, int level, int optname, const char *optval, int
default: FIXME("opt_name:%x\n", optname); + SetLastError(WSAENOPROTOOPT); return SOCKET_ERROR; } break; /* case NSPROTO_IPX */ @@ -2854,6 +2855,7 @@ int WINAPI setsockopt( SOCKET s, int level, int optname, const char *optval, int
default: FIXME("Unknown IPPROTO_TCP optname 0x%08x\n", optname); + SetLastError(WSAENOPROTOOPT); return SOCKET_ERROR; } break; @@ -2911,6 +2913,7 @@ int WINAPI setsockopt( SOCKET s, int level, int optname, const char *optval, int
default: FIXME("Unknown IPPROTO_IP optname 0x%08x\n", optname); + SetLastError(WSAENOPROTOOPT); return SOCKET_ERROR; } break; @@ -2960,6 +2963,7 @@ int WINAPI setsockopt( SOCKET s, int level, int optname, const char *optval, int
default: FIXME("Unknown IPPROTO_IPV6 optname 0x%08x\n", optname); + SetLastError(WSAENOPROTOOPT); return SOCKET_ERROR; } break;
Windows only supports setting this option, not getting it.
Signed-off-by: Alex Henrie alexhenrie24@gmail.com --- dlls/ntdll/unix/socket.c | 3 --- dlls/ws2_32/socket.c | 3 --- dlls/ws2_32/tests/sock.c | 12 ++++-------- include/wine/afd.h | 1 - 4 files changed, 4 insertions(+), 15 deletions(-)
diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c index 4f0c83597df..1ac4365c012 100644 --- a/dlls/ntdll/unix/socket.c +++ b/dlls/ntdll/unix/socket.c @@ -1762,9 +1762,6 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc return do_setsockopt( handle, io, IPPROTO_IP, IP_DROP_SOURCE_MEMBERSHIP, in_buffer, in_size );
#ifdef IP_HDRINCL - case IOCTL_AFD_WINE_GET_IP_HDRINCL: - return do_getsockopt( handle, io, IPPROTO_IP, IP_HDRINCL, out_buffer, out_size ); - case IOCTL_AFD_WINE_SET_IP_HDRINCL: return do_setsockopt( handle, io, IPPROTO_IP, IP_HDRINCL, in_buffer, in_size ); #endif diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 9a45124cd9e..c1bbfe4d775 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -1677,9 +1677,6 @@ int WINAPI getsockopt( SOCKET s, int level, int optname, char *optval, int *optl case IP_DONTFRAGMENT: return server_getsockopt( s, IOCTL_AFD_WINE_GET_IP_DONTFRAGMENT, optval, optlen );
- case IP_HDRINCL: - return server_getsockopt( s, IOCTL_AFD_WINE_GET_IP_HDRINCL, optval, optlen ); - case IP_MULTICAST_IF: return server_getsockopt( s, IOCTL_AFD_WINE_GET_IP_MULTICAST_IF, optval, optlen );
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index 6693c469dce..7605a172fef 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -1437,12 +1437,10 @@ todo_wine k = 99; SetLastError(0xdeadbeef); err = getsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *) &k, &size); + ok(err == -1, "Expected -1, got %d\n", err); todo_wine - { - ok(err == -1, "Expected -1, got %d\n", err); ok(GetLastError() == WSAEINVAL, "Expected 10022, got %d\n", GetLastError()); - ok(k == 99, "Expected 99, got %d\n", k); - } + ok(k == 99, "Expected 99, got %d\n", k);
size = sizeof(k); k = 0; @@ -1453,12 +1451,10 @@ todo_wine k = 99; SetLastError(0xdeadbeef); err = getsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *) &k, &size); + ok(err == -1, "Expected -1, got %d\n", err); todo_wine - { - ok(err == -1, "Expected -1, got %d\n", err); ok(GetLastError() == WSAEINVAL, "Expected 10022, got %d\n", GetLastError()); - ok(k == 99, "Expected 99, got %d\n", k); - } + ok(k == 99, "Expected 99, got %d\n", k); } else /* <= 2003 the tests differ between TCP and UDP, UDP silently accepts */ { diff --git a/include/wine/afd.h b/include/wine/afd.h index 49bbcccd3af..43e140c91c6 100644 --- a/include/wine/afd.h +++ b/include/wine/afd.h @@ -187,7 +187,6 @@ struct afd_get_events_params #define IOCTL_AFD_WINE_SET_IP_DONTFRAGMENT WINE_AFD_IOC(243) #define IOCTL_AFD_WINE_SET_IP_DROP_MEMBERSHIP WINE_AFD_IOC(244) #define IOCTL_AFD_WINE_SET_IP_DROP_SOURCE_MEMBERSHIP WINE_AFD_IOC(245) -#define IOCTL_AFD_WINE_GET_IP_HDRINCL WINE_AFD_IOC(246) #define IOCTL_AFD_WINE_SET_IP_HDRINCL WINE_AFD_IOC(247) #define IOCTL_AFD_WINE_GET_IP_MULTICAST_IF WINE_AFD_IOC(248) #define IOCTL_AFD_WINE_SET_IP_MULTICAST_IF WINE_AFD_IOC(249)
On 8/13/21 12:56 AM, Alex Henrie wrote:
@@ -1453,12 +1451,10 @@ todo_wine k = 99; SetLastError(0xdeadbeef); err = getsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *) &k, &size);
ok(err == -1, "Expected -1, got %d\n", err); todo_wine
{
ok(err == -1, "Expected -1, got %d\n", err); ok(GetLastError() == WSAEINVAL, "Expected 10022, got %d\n", GetLastError());
ok(k == 99, "Expected 99, got %d\n", k);
}
ok(k == 99, "Expected 99, got %d\n", k); } else /* <= 2003 the tests differ between TCP and UDP, UDP silently accepts */ {
If this is supposed to return WSAEINVAL, any reason not to do so in this patch?
On Mon, Aug 16, 2021 at 10:19 AM Zebediah Figura (she/her) zfigura@codeweavers.com wrote:
On 8/13/21 12:56 AM, Alex Henrie wrote:
@@ -1453,12 +1451,10 @@ todo_wine k = 99; SetLastError(0xdeadbeef); err = getsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *) &k, &size);
ok(err == -1, "Expected -1, got %d\n", err); todo_wine
{
ok(err == -1, "Expected -1, got %d\n", err); ok(GetLastError() == WSAEINVAL, "Expected 10022, got %d\n", GetLastError());
ok(k == 99, "Expected 99, got %d\n", k);
}
ok(k == 99, "Expected 99, got %d\n", k); } else /* <= 2003 the tests differ between TCP and UDP, UDP silently accepts */ {
If this is supposed to return WSAEINVAL, any reason not to do so in this patch?
There are a lot of options that should cause WSAEINVAL (usually due to using an IPv4 option on an IPv6 socket or vice-versa). I figured I would send another patch later to add a block of case statements for all of them, but it would also be fine to start with just IP_HDRINCL. I can send a revised patch tonight.
-Alex
Signed-off-by: Alex Henrie alexhenrie24@gmail.com --- dlls/ntdll/unix/socket.c | 26 ++++++++++++++++++++++++++ dlls/ws2_32/socket.c | 1 + 2 files changed, 27 insertions(+)
diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c index 1ac4365c012..4523ded1be7 100644 --- a/dlls/ntdll/unix/socket.c +++ b/dlls/ntdll/unix/socket.c @@ -1200,6 +1200,14 @@ static NTSTATUS do_setsockopt( HANDLE handle, IO_STATUS_BLOCK *io, int level, }
+static BOOL is_datagram_socket( HANDLE handle, IO_STATUS_BLOCK *io ) +{ + int sock_type = -1; + do_getsockopt( handle, io, SOL_SOCKET, SO_TYPE, &sock_type, sizeof(sock_type) ); + return sock_type == SOCK_DGRAM; +} + + NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc_user, IO_STATUS_BLOCK *io, ULONG code, void *in_buffer, ULONG in_size, void *out_buffer, ULONG out_size ) { @@ -1767,18 +1775,23 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc #endif
case IOCTL_AFD_WINE_GET_IP_MULTICAST_IF: + if (!is_datagram_socket( handle, io )) return STATUS_INVALID_PARAMETER; return do_getsockopt( handle, io, IPPROTO_IP, IP_MULTICAST_IF, out_buffer, out_size );
case IOCTL_AFD_WINE_SET_IP_MULTICAST_IF: + if (!is_datagram_socket( handle, io )) return STATUS_INVALID_PARAMETER; return do_setsockopt( handle, io, IPPROTO_IP, IP_MULTICAST_IF, in_buffer, in_size );
case IOCTL_AFD_WINE_GET_IP_MULTICAST_LOOP: + if (!is_datagram_socket( handle, io )) return STATUS_INVALID_PARAMETER; return do_getsockopt( handle, io, IPPROTO_IP, IP_MULTICAST_LOOP, out_buffer, out_size );
case IOCTL_AFD_WINE_SET_IP_MULTICAST_LOOP: + if (!is_datagram_socket( handle, io )) return STATUS_INVALID_PARAMETER; return do_setsockopt( handle, io, IPPROTO_IP, IP_MULTICAST_LOOP, in_buffer, in_size );
case IOCTL_AFD_WINE_GET_IP_MULTICAST_TTL: + if (!is_datagram_socket( handle, io )) return STATUS_INVALID_PARAMETER; return do_getsockopt( handle, io, IPPROTO_IP, IP_MULTICAST_TTL, out_buffer, out_size );
case IOCTL_AFD_WINE_SET_IP_MULTICAST_TTL: @@ -1792,15 +1805,19 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc
#ifdef IP_PKTINFO case IOCTL_AFD_WINE_GET_IP_PKTINFO: + if (!is_datagram_socket( handle, io )) return STATUS_INVALID_PARAMETER; return do_getsockopt( handle, io, IPPROTO_IP, IP_PKTINFO, out_buffer, out_size );
case IOCTL_AFD_WINE_SET_IP_PKTINFO: + if (!is_datagram_socket( handle, io )) return STATUS_INVALID_PARAMETER; return do_setsockopt( handle, io, IPPROTO_IP, IP_PKTINFO, in_buffer, in_size ); #elif defined(IP_RECVDSTADDR) case IOCTL_AFD_WINE_GET_IP_PKTINFO: + if (!is_datagram_socket( handle, io )) return STATUS_INVALID_PARAMETER; return do_getsockopt( handle, io, IPPROTO_IP, IP_RECVDSTADDR, out_buffer, out_size );
case IOCTL_AFD_WINE_SET_IP_PKTINFO: + if (!is_datagram_socket( handle, io )) return STATUS_INVALID_PARAMETER; return do_setsockopt( handle, io, IPPROTO_IP, IP_RECVDSTADDR, in_buffer, in_size ); #endif
@@ -1890,18 +1907,21 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc #endif
case IOCTL_AFD_WINE_GET_IPV6_MULTICAST_HOPS: + if (!is_datagram_socket( handle, io )) return STATUS_INVALID_PARAMETER; return do_getsockopt( handle, io, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, out_buffer, out_size );
case IOCTL_AFD_WINE_SET_IPV6_MULTICAST_HOPS: return do_setsockopt( handle, io, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, in_buffer, in_size );
case IOCTL_AFD_WINE_GET_IPV6_MULTICAST_IF: + if (!is_datagram_socket( handle, io )) return STATUS_INVALID_PARAMETER; return do_getsockopt( handle, io, IPPROTO_IPV6, IPV6_MULTICAST_IF, out_buffer, out_size );
case IOCTL_AFD_WINE_SET_IPV6_MULTICAST_IF: return do_setsockopt( handle, io, IPPROTO_IPV6, IPV6_MULTICAST_IF, in_buffer, in_size );
case IOCTL_AFD_WINE_GET_IPV6_MULTICAST_LOOP: + if (!is_datagram_socket( handle, io )) return STATUS_INVALID_PARAMETER; return do_getsockopt( handle, io, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, out_buffer, out_size );
case IOCTL_AFD_WINE_SET_IPV6_MULTICAST_LOOP: @@ -1909,25 +1929,31 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc
#ifdef IPV6_RECVHOPLIMIT case IOCTL_AFD_WINE_GET_IPV6_RECVHOPLIMIT: + if (!is_datagram_socket( handle, io )) return STATUS_INVALID_PARAMETER; return do_getsockopt( handle, io, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, out_buffer, out_size );
case IOCTL_AFD_WINE_SET_IPV6_RECVHOPLIMIT: + if (!is_datagram_socket( handle, io )) return STATUS_INVALID_PARAMETER; return do_setsockopt( handle, io, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, in_buffer, in_size ); #endif
#ifdef IPV6_RECVPKTINFO case IOCTL_AFD_WINE_GET_IPV6_RECVPKTINFO: + if (!is_datagram_socket( handle, io )) return STATUS_INVALID_PARAMETER; return do_getsockopt( handle, io, IPPROTO_IPV6, IPV6_RECVPKTINFO, out_buffer, out_size );
case IOCTL_AFD_WINE_SET_IPV6_RECVPKTINFO: + if (!is_datagram_socket( handle, io )) return STATUS_INVALID_PARAMETER; return do_setsockopt( handle, io, IPPROTO_IPV6, IPV6_RECVPKTINFO, in_buffer, in_size ); #endif
#ifdef IPV6_RECVTCLASS case IOCTL_AFD_WINE_GET_IPV6_RECVTCLASS: + if (!is_datagram_socket( handle, io )) return STATUS_INVALID_PARAMETER; return do_getsockopt( handle, io, IPPROTO_IPV6, IPV6_RECVTCLASS, out_buffer, out_size );
case IOCTL_AFD_WINE_SET_IPV6_RECVTCLASS: + if (!is_datagram_socket( handle, io )) return STATUS_INVALID_PARAMETER; return do_setsockopt( handle, io, IPPROTO_IPV6, IPV6_RECVTCLASS, in_buffer, in_size ); #endif
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index c1bbfe4d775..b6e6c53f3d3 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -438,6 +438,7 @@ static DWORD NtStatusToWSAError( NTSTATUS status ) {STATUS_ACCESS_VIOLATION, WSAEFAULT}, {STATUS_PAGEFILE_QUOTA, WSAENOBUFS}, {STATUS_INVALID_HANDLE, WSAENOTSOCK}, + {STATUS_INVALID_PARAMETER, WSAEINVAL}, {STATUS_NO_SUCH_DEVICE, WSAENETDOWN}, {STATUS_NO_SUCH_FILE, WSAENETDOWN}, {STATUS_NO_MEMORY, WSAENOBUFS},
On 8/13/21 12:56 AM, Alex Henrie wrote:
Signed-off-by: Alex Henrie alexhenrie24@gmail.com
dlls/ntdll/unix/socket.c | 26 ++++++++++++++++++++++++++ dlls/ws2_32/socket.c | 1 + 2 files changed, 27 insertions(+)
Do these options not return EINVAL on a known system? What do they return instead? At least the commit message, if not the code, should mention this.
...
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index c1bbfe4d775..b6e6c53f3d3 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -438,6 +438,7 @@ static DWORD NtStatusToWSAError( NTSTATUS status ) {STATUS_ACCESS_VIOLATION, WSAEFAULT}, {STATUS_PAGEFILE_QUOTA, WSAENOBUFS}, {STATUS_INVALID_HANDLE, WSAENOTSOCK},
{STATUS_INVALID_PARAMETER, WSAEINVAL}, {STATUS_NO_SUCH_DEVICE, WSAENETDOWN}, {STATUS_NO_SUCH_FILE, WSAENETDOWN}, {STATUS_NO_MEMORY, WSAENOBUFS},
You don't need this hunk; all errors not otherwise translated are converted to WSAEINVAL.
On Fri, Aug 13, 2021 at 10:05 AM Zebediah Figura (she/her) zfigura@codeweavers.com wrote:
Do these options not return EINVAL on a known system? What do they return instead? At least the commit message, if not the code, should mention this.
These protocol+option combinations result in WSAEINVAL on every version of Windows from XP on; no need to mark any of them as BROKEN in the tests.
On 8/13/21 12:56 AM, Alex Henrie wrote:
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index c1bbfe4d775..b6e6c53f3d3 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -438,6 +438,7 @@ static DWORD NtStatusToWSAError( NTSTATUS status ) {STATUS_ACCESS_VIOLATION, WSAEFAULT}, {STATUS_PAGEFILE_QUOTA, WSAENOBUFS}, {STATUS_INVALID_HANDLE, WSAENOTSOCK},
{STATUS_INVALID_PARAMETER, WSAEINVAL}, {STATUS_NO_SUCH_DEVICE, WSAENETDOWN}, {STATUS_NO_SUCH_FILE, WSAENETDOWN}, {STATUS_NO_MEMORY, WSAENOBUFS},
You don't need this hunk; all errors not otherwise translated are converted to WSAEINVAL.
Thanks for pointing that out; I will resend the patch without it. The first three patches in the series were good though, right?
-Alex
On 8/15/21 1:58 PM, Alex Henrie wrote:
On Fri, Aug 13, 2021 at 10:05 AM Zebediah Figura (she/her) zfigura@codeweavers.com wrote:
Do these options not return EINVAL on a known system? What do they return instead? At least the commit message, if not the code, should mention this.
These protocol+option combinations result in WSAEINVAL on every version of Windows from XP on; no need to mark any of them as BROKEN in the tests.
I mean on the host Unix system. If they already return EINVAL there's no need to handle them specially.
On 8/13/21 12:56 AM, Alex Henrie wrote:
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index c1bbfe4d775..b6e6c53f3d3 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -438,6 +438,7 @@ static DWORD NtStatusToWSAError( NTSTATUS status ) {STATUS_ACCESS_VIOLATION, WSAEFAULT}, {STATUS_PAGEFILE_QUOTA, WSAENOBUFS}, {STATUS_INVALID_HANDLE, WSAENOTSOCK},
{STATUS_INVALID_PARAMETER, WSAEINVAL}, {STATUS_NO_SUCH_DEVICE, WSAENETDOWN}, {STATUS_NO_SUCH_FILE, WSAENETDOWN}, {STATUS_NO_MEMORY, WSAENOBUFS},
You don't need this hunk; all errors not otherwise translated are converted to WSAEINVAL.
Thanks for pointing that out; I will resend the patch without it. The first three patches in the series were good though, right?
-Alex
On Sun, Aug 15, 2021 at 1:03 PM Zebediah Figura (she/her) zfigura@codeweavers.com wrote:
On 8/15/21 1:58 PM, Alex Henrie wrote:
On Fri, Aug 13, 2021 at 10:05 AM Zebediah Figura (she/her) zfigura@codeweavers.com wrote:
Do these options not return EINVAL on a known system? What do they return instead? At least the commit message, if not the code, should mention this.
These protocol+option combinations result in WSAEINVAL on every version of Windows from XP on; no need to mark any of them as BROKEN in the tests.
I mean on the host Unix system. If they already return EINVAL there's no need to handle them specially.
Linux supports every one of these options on UDP sockets.
Mac OS supports IP_PKTINFO, IPV6_PKTINFO, IPV6_HOPLIMIT, and IPV6_RECVTCLASS on UDP.
However, Mac OS sets EOPNOTSUPP for IP_MULTICAST_IF, IP_MULTICAST_TTL, IP_MULTICAST_LOOP, IPV6_MULTICAST_IF, IPV6_MULTICAST_HOPS, and IPV6_MULTICAST_LOOP on UDP.
So, if we are to replicate the Windows behavior, the TCP/UDP check has to happen in Wine. I'll add an explanatory note to the commit message.
-Alex
On Sun, Aug 15, 2021 at 11:49 PM Alex Henrie alexhenrie24@gmail.com wrote:
On Sun, Aug 15, 2021 at 1:03 PM Zebediah Figura (she/her) zfigura@codeweavers.com wrote:
On 8/15/21 1:58 PM, Alex Henrie wrote:
On Fri, Aug 13, 2021 at 10:05 AM Zebediah Figura (she/her) zfigura@codeweavers.com wrote:
Do these options not return EINVAL on a known system? What do they return instead? At least the commit message, if not the code, should mention this.
These protocol+option combinations result in WSAEINVAL on every version of Windows from XP on; no need to mark any of them as BROKEN in the tests.
I mean on the host Unix system. If they already return EINVAL there's no need to handle them specially.
Linux supports every one of these options on UDP sockets.
Mac OS supports IP_PKTINFO, IPV6_PKTINFO, IPV6_HOPLIMIT, and IPV6_RECVTCLASS on UDP.
However, Mac OS sets EOPNOTSUPP for IP_MULTICAST_IF, IP_MULTICAST_TTL, IP_MULTICAST_LOOP, IPV6_MULTICAST_IF, IPV6_MULTICAST_HOPS, and IPV6_MULTICAST_LOOP on UDP.
Ugh, I meant to say TCP in every place where I said UDP in these three sentences. I'll be sure to get it right in the commit message.
-Alex
Signed-off-by: Alex Henrie alexhenrie24@gmail.com --- Changes from previous attempt: - Align table columns - Skip setsockopt tests if getsockopt is expected to fail - Rebase on top of getsockopt and setsockopt fixes, removing the need for multiple TODO flags --- dlls/ws2_32/tests/sock.c | 239 ++++++++++++++++++++++++++++++++++----- 1 file changed, 210 insertions(+), 29 deletions(-)
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index 7605a172fef..f44252d3b41 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -11431,47 +11431,228 @@ static void test_so_debug(void) closesocket(s); }
-static void test_set_only_options(void) +enum sockopt_validity_flags { - unsigned int i; - int ret, len; - int value; - SOCKET s; + BROKEN = 1, + TODO = 2 +};
- static const struct - { - int level; - int option; - } - tests[] = - { - {IPPROTO_IP, IP_ADD_MEMBERSHIP}, - {IPPROTO_IP, IP_DROP_MEMBERSHIP}, - {IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP}, - {IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP}, - }; +struct sockopt_validity_test +{ + int opt; + int get_error; + enum sockopt_validity_flags get_flags; + int set_error; + enum sockopt_validity_flags set_flags; +};
- for (i = 0; i < ARRAY_SIZE(tests); ++i) +static void do_sockopt_validity_tests(const char *type, SOCKET sock, int level, + const struct sockopt_validity_test *tests) +{ + static const struct sockopt_validity_test default_test = {0, WSAENOPROTOOPT, 0}; + const struct sockopt_validity_test *test; + char value[256]; + int opt, count, rc, expected_rc, i = 0; + + for (opt = 0; opt < 100; opt++) { - if (tests[i].level == IPPROTO_IPV6) + if (tests[i].opt && opt == tests[i].opt) { - s = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); - if (s == INVALID_SOCKET) continue; + test = &tests[i]; + i++; } else { - s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + test = &default_test; }
- len = sizeof(value); - ret = getsockopt(s, tests[i].level, tests[i].option, (char *)&value, &len); - ok(ret == -1, "expected failure\n"); - ok(WSAGetLastError() == WSAENOPROTOOPT, "got error %u\n", WSAGetLastError()); - - closesocket(s); + memset(value, 0, sizeof(value)); + count = sizeof(value); + + WSASetLastError(0); + rc = getsockopt(sock, level, opt, value, &count); + expected_rc = test->get_error ? SOCKET_ERROR : 0; +todo_wine_if(!test->get_error && test->get_flags & TODO) + ok(rc == expected_rc || broken(rc == SOCKET_ERROR && test->get_flags & BROKEN), + "expected getting %s option %i to return %i, got %i\n", type, opt, expected_rc, rc); +todo_wine_if(test->get_flags & TODO) + ok(WSAGetLastError() == test->get_error || broken(rc == SOCKET_ERROR && test->get_flags & BROKEN), + "expected getting %s option %i to cause error %i, got %i\n", type, opt, test->get_error, WSAGetLastError()); + + if (test->get_error) + continue; + + WSASetLastError(0); + rc = setsockopt(sock, level, opt, value, count); + expected_rc = test->set_error ? SOCKET_ERROR : 0; +todo_wine_if(!test->set_error && test->set_flags & TODO) + ok(rc == expected_rc || broken(rc == SOCKET_ERROR && test->set_flags & BROKEN), + "expected setting %s option %i to return %i, got %i\n", type, opt, expected_rc, rc); +todo_wine_if(test->set_flags & TODO) + ok(WSAGetLastError() == test->set_error || broken(rc == SOCKET_ERROR && test->set_flags & BROKEN), + "expected setting %s option %i to cause error %i, got %i\n", type, opt, test->set_error, WSAGetLastError()); } }
+static void test_sockopt_validity(void) +{ + static const struct sockopt_validity_test ipv4_tcp_tests[] = + { + { IP_OPTIONS }, + { IP_HDRINCL, WSAEINVAL, TODO }, + { IP_TOS }, + { IP_TTL }, + { IP_MULTICAST_IF, WSAEINVAL }, + { IP_MULTICAST_TTL, WSAEINVAL }, + { IP_MULTICAST_LOOP, WSAEINVAL }, + { IP_DONTFRAGMENT }, + { IP_PKTINFO, WSAEINVAL }, + { IP_RECVTTL, WSAEINVAL, TODO }, + { IP_RECEIVE_BROADCAST, WSAEINVAL, TODO }, + { 23, 0, TODO, 0, TODO }, + { IP_RECVIF, WSAEINVAL, TODO }, + { IP_RECVDSTADDR, WSAEINVAL, TODO }, + { IP_IFLIST, 0, TODO, 0, TODO }, + { IP_UNICAST_IF }, + { IP_RTHDR, 0, TODO, 0, TODO }, + { IP_GET_IFLIST, WSAEINVAL, BROKEN /* win8 */ | TODO }, + { IP_RECVRTHDR, WSAEINVAL, TODO }, + { IP_RECVTCLASS, WSAEINVAL, TODO }, + { IP_ORIGINAL_ARRIVAL_IF, WSAEINVAL, BROKEN /* vista */ | TODO }, + { IP_ECN, WSAEINVAL, BROKEN /* win7 */ | TODO }, + { IP_PKTINFO_EX, WSAEINVAL, BROKEN /* win7 */ | TODO }, + { IP_WFP_REDIRECT_RECORDS, WSAEINVAL, BROKEN /* win7 */ | TODO }, + { IP_WFP_REDIRECT_CONTEXT, WSAEINVAL, BROKEN /* win7 */ | TODO }, + { IP_MTU_DISCOVER, 0, BROKEN /* win8 */ | TODO, WSAEINVAL, BROKEN /* win8 */ | TODO }, + { IP_MTU, WSAENOTCONN, BROKEN /* win8 */ | TODO }, + { IP_RECVERR, WSAEINVAL, BROKEN /* win8 */ | TODO }, + { IP_USER_MTU, 0, BROKEN /* win8 */ | TODO, 0, BROKEN /* win8 */ | TODO }, + {} + }; + static const struct sockopt_validity_test ipv4_udp_tests[] = + { + { IP_OPTIONS }, + { IP_HDRINCL, WSAEINVAL, TODO }, + { IP_TOS }, + { IP_TTL }, + { IP_MULTICAST_IF }, + { IP_MULTICAST_TTL }, + { IP_MULTICAST_LOOP }, + { IP_DONTFRAGMENT }, + { IP_PKTINFO }, + { IP_RECVTTL, 0, TODO, 0, TODO }, + { IP_RECEIVE_BROADCAST, 0, TODO, 0, TODO }, + { 23, 0, TODO, 0, TODO }, + { IP_RECVIF, 0, TODO, 0, TODO }, + { IP_RECVDSTADDR, 0, TODO, 0, TODO }, + { IP_IFLIST, 0, TODO, 0, TODO }, + { IP_UNICAST_IF }, + { IP_RTHDR, 0, TODO, 0, TODO }, + { IP_GET_IFLIST, WSAEINVAL, BROKEN /* win8 */ | TODO }, + { IP_RECVRTHDR, 0, TODO, 0, BROKEN /* win8 */ | TODO }, + { IP_RECVTCLASS, 0, TODO, 0, TODO }, + { IP_ORIGINAL_ARRIVAL_IF, 0, BROKEN /* vista */ | TODO, 0, BROKEN /* vista */ | TODO }, + { IP_ECN, 0, BROKEN /* win7 */ | TODO, 0, BROKEN /* win7 */ | TODO }, + { IP_PKTINFO_EX, 0, BROKEN /* win7 */ | TODO, 0, BROKEN /* win7 */ | TODO }, + { IP_WFP_REDIRECT_RECORDS, 0, BROKEN /* win7 */ | TODO, 0, BROKEN /* win7 */ | TODO }, + { IP_WFP_REDIRECT_CONTEXT, 0, BROKEN /* win7 */ | TODO, 0, BROKEN /* win7 */ | TODO }, + { IP_MTU_DISCOVER, 0, BROKEN /* win8 */ | TODO, WSAEINVAL, BROKEN /* win8 */ | TODO }, + { IP_MTU, WSAENOTCONN, BROKEN /* win8 */ | TODO }, + { IP_RECVERR, 0, BROKEN /* win8 */ | TODO, 0, BROKEN /* win8 */ | TODO }, + { IP_USER_MTU, 0, BROKEN /* win8 */ | TODO, 0, BROKEN /* win8 */ | TODO }, + {} + }; + static const struct sockopt_validity_test ipv6_tcp_tests[] = + { + { IPV6_HOPOPTS, 0, TODO, 0, TODO }, + { 2, WSAEINVAL, TODO }, + { 3, 0, TODO, 0, TODO }, + { IPV6_UNICAST_HOPS }, + { IPV6_MULTICAST_IF, WSAEINVAL }, + { IPV6_MULTICAST_HOPS, WSAEINVAL }, + { IPV6_MULTICAST_LOOP, WSAEINVAL }, + { IPV6_DONTFRAG }, + { IPV6_PKTINFO, WSAEINVAL }, + { IPV6_HOPLIMIT, WSAEINVAL }, + { 22, WSAEINVAL, TODO }, + { IPV6_PROTECTION_LEVEL, 0, TODO, 0, 0 }, + { IPV6_RECVIF, WSAEINVAL, TODO }, + { IPV6_RECVDSTADDR, WSAEINVAL, TODO }, + { IPV6_V6ONLY }, + { IPV6_IFLIST, 0, TODO, 0, TODO }, + { IPV6_UNICAST_IF }, + { IPV6_RTHDR, 0, TODO, 0, TODO }, + { IPV6_GET_IFLIST, WSAEINVAL, BROKEN /* win8 */ | TODO }, + { IPV6_RECVRTHDR, WSAEINVAL, TODO }, + { IPV6_RECVTCLASS, WSAEINVAL }, + { 47, WSAEINVAL, BROKEN /* vista */ | TODO }, + { IPV6_ECN, WSAEINVAL, BROKEN /* win7 */ | TODO }, + { IPV6_PKTINFO_EX, WSAEINVAL, BROKEN /* win7 */ | TODO }, + { IPV6_WFP_REDIRECT_RECORDS, WSAEINVAL, BROKEN /* win7 */ | TODO }, + { IPV6_WFP_REDIRECT_CONTEXT, WSAEINVAL, BROKEN /* win7 */ | TODO }, + { IPV6_MTU_DISCOVER, 0, BROKEN /* win8 */ | TODO, WSAEINVAL, BROKEN /* win8 */ | TODO }, + { IPV6_MTU, WSAENOTCONN, BROKEN /* win8 */ | TODO }, + { IPV6_RECVERR, WSAEINVAL, BROKEN /* win8 */ | TODO }, + { IPV6_USER_MTU, 0, BROKEN /* win8 */ | TODO, 0, BROKEN /* win8 */ | TODO }, + {} + }; + static const struct sockopt_validity_test ipv6_udp_tests[] = + { + { IPV6_HOPOPTS, 0, TODO, 0, TODO }, + { 2, WSAEINVAL, TODO }, + { 3, 0, TODO, 0, TODO }, + { IPV6_UNICAST_HOPS }, + { IPV6_MULTICAST_IF }, + { IPV6_MULTICAST_HOPS }, + { IPV6_MULTICAST_LOOP }, + { IPV6_DONTFRAG }, + { IPV6_PKTINFO }, + { IPV6_HOPLIMIT }, + { 22, 0, TODO, 0, TODO }, + { IPV6_PROTECTION_LEVEL, 0, TODO, 0, 0 }, + { IPV6_RECVIF, 0, TODO, 0, TODO }, + { IPV6_RECVDSTADDR, 0, TODO, 0, TODO }, + { IPV6_V6ONLY }, + { IPV6_IFLIST, 0, TODO, 0, TODO }, + { IPV6_UNICAST_IF }, + { IPV6_RTHDR, 0, TODO, 0, TODO }, + { IPV6_GET_IFLIST, WSAEINVAL, BROKEN /* win8 */ | TODO }, + { IPV6_RECVRTHDR, 0, TODO, 0, BROKEN /* win8 */ | TODO }, + { IPV6_RECVTCLASS }, + { 47, 0, BROKEN /* vista */ | TODO, 0, BROKEN /* vista */ | TODO }, + { IPV6_ECN, 0, BROKEN /* win7 */ | TODO, 0, BROKEN /* win7 */ | TODO }, + { IPV6_PKTINFO_EX, 0, BROKEN /* win7 */ | TODO, 0, BROKEN /* win7 */ | TODO }, + { IPV6_WFP_REDIRECT_RECORDS, 0, BROKEN /* win7 */ | TODO, 0, BROKEN /* win7 */ | TODO }, + { IPV6_WFP_REDIRECT_CONTEXT, 0, BROKEN /* win7 */ | TODO, 0, BROKEN /* win7 */ | TODO }, + { IPV6_MTU_DISCOVER, 0, BROKEN /* win8 */ | TODO, WSAEINVAL, BROKEN /* win8 */ | TODO }, + { IPV6_MTU, WSAENOTCONN, BROKEN /* win8 */ | TODO }, + { IPV6_RECVERR, 0, BROKEN /* win8 */ | TODO, 0, BROKEN /* win8 */ | TODO }, + { IPV6_USER_MTU, 0, BROKEN /* win8 */ | TODO, 0, BROKEN /* win8 */ | TODO }, + {} + }; + SOCKET sock; + + sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + ok(sock != INVALID_SOCKET, "failed to create socket, error %u\n", WSAGetLastError()); + do_sockopt_validity_tests("IPv4 TCP", sock, IPPROTO_IP, ipv4_tcp_tests); + closesocket(sock); + + sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + ok(sock != INVALID_SOCKET, "failed to create socket, error %u\n", WSAGetLastError()); + do_sockopt_validity_tests("IPv4 UDP", sock, IPPROTO_IP, ipv4_udp_tests); + closesocket(sock); + + sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); + ok(sock != INVALID_SOCKET, "failed to create socket, error %u\n", WSAGetLastError()); + do_sockopt_validity_tests("IPv6 TCP", sock, IPPROTO_IPV6, ipv6_tcp_tests); + closesocket(sock); + + sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); + ok(sock != INVALID_SOCKET, "failed to create socket, error %u\n", WSAGetLastError()); + do_sockopt_validity_tests("IPv6 UDP", sock, IPPROTO_IPV6, ipv6_udp_tests); + closesocket(sock); +} + START_TEST( sock ) { int i; @@ -11489,7 +11670,7 @@ START_TEST( sock ) test_ipv6_cmsg(); test_extendedSocketOptions(); test_so_debug(); - test_set_only_options(); + test_sockopt_validity();
for (i = 0; i < ARRAY_SIZE(tests); i++) do_test(&tests[i]);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=95572
Your paranoid android.
=== debiant2 (32 bit Chinese:China report) ===
ws2_32: sock.c:5059: Test failed: expected timeout
This patch loses the tests for IP_ADD_MEMBERSHIP et al.
Also:
- for (opt = 0; opt < 100; opt++)
I'm not a huge fan of this. It kind of works for IP options, but it wouldn't work if we extended these tests to e.g. SOL_SOCKET. I'm also not sure I see the value in exhaustively testing undocumented or invalid sockopts. Maybe check one or two obviously invalid numbers just to show what the invalid behaviour is (and of course put that in the table proper).
{ IPV6_GET_IFLIST, WSAEINVAL, BROKEN /* win8 */ | TODO },
This still isn't clear enough to me; it looks like it means "broken on windows 8", not "broken on anything before windows 8".
Also, what's the broken case anyway? If it's just a matter of some versions not supporting the option yet and returning WSAENOPROTOOPT, is it even worth putting it in the table? Can we just have a blanket "|| broken(ret == -1 && WSAGetLastError() == WSAENOPROTOOPT)"?
{ 2, WSAEINVAL, TODO },
This is IPV6_HDRINCL.
{ 47, WSAEINVAL, BROKEN /* vista */ | TODO },
IP_ORIGINAL_ARRIVAL_IF (yes, used with IPPROTO_IPV6; see [1].)
[1] https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ipv6-socket-o...
On Mon, Aug 16, 2021 at 10:42 AM Zebediah Figura (she/her) zfigura@codeweavers.com wrote:
This patch loses the tests for IP_ADD_MEMBERSHIP et al.
IP(V6)_ADD_MEMBERSHIP is 12 and IP(V6)_DROP_MEMBERSHIP is 13. The new tests for them are as rigorous as the old ones, they just don't appear in the tables because they fall into the default case.
Also:
- for (opt = 0; opt < 100; opt++)
I'm not a huge fan of this. It kind of works for IP options, but it wouldn't work if we extended these tests to e.g. SOL_SOCKET. I'm also not sure I see the value in exhaustively testing undocumented or invalid sockopts. Maybe check one or two obviously invalid numbers just to show what the invalid behaviour is (and of course put that in the table proper).
OK, I'll make those changes.
{ IPV6_GET_IFLIST, WSAEINVAL, BROKEN /* win8 */ | TODO },
This still isn't clear enough to me; it looks like it means "broken on windows 8", not "broken on anything before windows 8".
Also, what's the broken case anyway? If it's just a matter of some versions not supporting the option yet and returning WSAENOPROTOOPT, is it even worth putting it in the table? Can we just have a blanket "|| broken(ret == -1 && WSAGetLastError() == WSAENOPROTOOPT)"?
Yes, we can have a blanket broken statement, that would be fine.
{ 2, WSAEINVAL, TODO },
This is IPV6_HDRINCL.
{ 47, WSAEINVAL, BROKEN /* vista */ | TODO },
IP_ORIGINAL_ARRIVAL_IF (yes, used with IPPROTO_IPV6; see [1].)
[1] https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ipv6-socket-o...
Thanks for catching those!
-Alex
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=95568
Your paranoid android.
=== debiant2 (32 bit Hebrew:Israel report) ===
ws2_32: sock.c:1135: Test failed: wait failed, error 258