Signed-off-by: Alex Henrie alexhenrie24@gmail.com --- FelgoLiveClient.exe from https://felgo.com/ sets this option. --- dlls/ntdll/unix/socket.c | 30 +++++++++++++++++++++++++++++- dlls/ws2_32/socket.c | 7 +++++++ dlls/ws2_32/tests/sock.c | 7 ------- include/wine/afd.h | 2 ++ 4 files changed, 38 insertions(+), 8 deletions(-)
diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c index 0e52db178d8..babc5990593 100644 --- a/dlls/ntdll/unix/socket.c +++ b/dlls/ntdll/unix/socket.c @@ -39,7 +39,8 @@ #include <sys/socket.h> #endif #ifdef HAVE_NETINET_IN_H -#include <netinet/in.h> +# define __APPLE_USE_RFC_3542 +# include <netinet/in.h> #endif #ifdef HAVE_NETINET_TCP_H # include <netinet/tcp.h> @@ -452,6 +453,25 @@ static int convert_control_headers(struct msghdr *hdr, WSABUF *control) } break;
+ case IPPROTO_IPV6: + switch (cmsg_unix->cmsg_type) + { +#if defined(IPV6_HOPLIMIT) + case IPV6_HOPLIMIT: + { + ptr = fill_control_message( WS_IPPROTO_IPV6, WS_IPV6_HOPLIMIT, ptr, &ctlsize, + CMSG_DATA(cmsg_unix), sizeof(INT) ); + if (!ptr) goto error; + break; + } +#endif /* IPV6_HOPLIMIT */ + + default: + FIXME("Unhandled IPPROTO_IPV6 message header type %d\n", cmsg_unix->cmsg_type); + break; + } + break; + default: FIXME("Unhandled message header level %d\n", cmsg_unix->cmsg_level); break; @@ -1882,6 +1902,14 @@ 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 );
+#ifdef IPV6_RECVHOPLIMIT + case IOCTL_AFD_WINE_GET_IPV6_RECVHOPLIMIT: + return do_getsockopt( handle, io, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, out_buffer, out_size ); + + case IOCTL_AFD_WINE_SET_IPV6_RECVHOPLIMIT: + return do_setsockopt( handle, io, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, 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 f7996410db1..8026bc62ace 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -312,6 +312,7 @@ static inline const char *debugstr_sockopt(int level, int optname) { DEBUG_SOCKOPT(WS_IPV6_ADD_MEMBERSHIP); DEBUG_SOCKOPT(WS_IPV6_DROP_MEMBERSHIP); + DEBUG_SOCKOPT(WS_IPV6_HOPLIMIT); DEBUG_SOCKOPT(WS_IPV6_MULTICAST_IF); DEBUG_SOCKOPT(WS_IPV6_MULTICAST_HOPS); DEBUG_SOCKOPT(WS_IPV6_MULTICAST_LOOP); @@ -2096,6 +2097,9 @@ INT WINAPI WS_getsockopt(SOCKET s, INT level, case WS_IPV6_DONTFRAG: return server_getsockopt( s, IOCTL_AFD_WINE_GET_IPV6_DONTFRAG, optval, optlen );
+ case WS_IPV6_HOPLIMIT: + return server_getsockopt( s, IOCTL_AFD_WINE_GET_IPV6_RECVHOPLIMIT, optval, optlen ); + case WS_IPV6_MULTICAST_HOPS: return server_getsockopt( s, IOCTL_AFD_WINE_GET_IPV6_MULTICAST_HOPS, optval, optlen );
@@ -3302,6 +3306,9 @@ int WINAPI WS_setsockopt(SOCKET s, int level, int optname, case WS_IPV6_DROP_MEMBERSHIP: return server_setsockopt( s, IOCTL_AFD_WINE_SET_IPV6_DROP_MEMBERSHIP, optval, optlen );
+ case WS_IPV6_HOPLIMIT: + return server_setsockopt( s, IOCTL_AFD_WINE_SET_IPV6_RECVHOPLIMIT, optval, optlen ); + case WS_IPV6_MULTICAST_HOPS: return server_setsockopt( s, IOCTL_AFD_WINE_SET_IPV6_MULTICAST_HOPS, optval, optlen );
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index 3aaacfea281..12c1a859336 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -2028,28 +2028,21 @@ static void test_ipv6_cmsg(void) memset(control, 0, sizeof(control)); msg.Control.len = sizeof(control); rc = setsockopt(server, IPPROTO_IPV6, IPV6_HOPLIMIT, (const char *)&on, sizeof(on)); -todo_wine ok(!rc, "failed to set IPV6_HOPLIMIT, error %u\n", WSAGetLastError()); state = 0; count = sizeof(state); rc = getsockopt(server, IPPROTO_IPV6, IPV6_HOPLIMIT, (char *)&state, (INT *)&count); -todo_wine ok(!rc, "failed to get IPV6_HOPLIMIT, error %u\n", WSAGetLastError()); -todo_wine 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); -todo_wine ok(header->cmsg_level == IPPROTO_IPV6, "expected IPPROTO_IPV6, got %i\n", header->cmsg_level); -todo_wine ok(header->cmsg_type == IPV6_HOPLIMIT, "expected IPV6_HOPLIMIT, got %i\n", header->cmsg_type); -todo_wine ok(header->cmsg_len == sizeof(*header) + sizeof(INT), "expected length %i, got %i\n", (INT)(sizeof(*header) + sizeof(INT)), (INT)header->cmsg_len); -todo_wine ok(*hop_limit >= 32, "expected at least 32, got %i\n", *hop_limit); setsockopt(server, IPPROTO_IPV6, IPV6_HOPLIMIT, (const char *)&off, sizeof(off)); ok(!rc, "failed to clear IPV6_HOPLIMIT, error %u\n", WSAGetLastError()); diff --git a/include/wine/afd.h b/include/wine/afd.h index 1c5f8020c2c..0be0678606d 100644 --- a/include/wine/afd.h +++ b/include/wine/afd.h @@ -228,6 +228,8 @@ struct afd_get_events_params #define IOCTL_AFD_WINE_GET_IRLMP_ENUMDEVICES WINE_AFD_IOC(283) #define IOCTL_AFD_WINE_GET_TCP_NODELAY WINE_AFD_IOC(284) #define IOCTL_AFD_WINE_SET_TCP_NODELAY WINE_AFD_IOC(285) +#define IOCTL_AFD_WINE_GET_IPV6_RECVHOPLIMIT WINE_AFD_IOC(286) +#define IOCTL_AFD_WINE_SET_IPV6_RECVHOPLIMIT WINE_AFD_IOC(287)
struct afd_create_params {