diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c index 9dc697ea959..9b43de17b29 100644 --- a/dlls/ntdll/unix/socket.c +++ b/dlls/ntdll/unix/socket.c @@ -39,7 +39,8 @@ #include #endif #ifdef HAVE_NETINET_IN_H -#include +# define __APPLE_USE_RFC_3542 +# include #endif #ifdef HAVE_NETINET_TCP_H # include @@ -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 b52e0d37e90..4babd888473 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -314,6 +314,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); @@ -1925,6 +1926,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 ); @@ -3131,6 +3135,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 {