From: Paul Gofman pgofman@codeweavers.com
--- dlls/ntdll/unix/socket.c | 8 ++++++++ dlls/ws2_32/tests/sock.c | 21 +++++++++++++++++++++ 2 files changed, 29 insertions(+)
diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c index 53292246648..05cbaf9aaaa 100644 --- a/dlls/ntdll/unix/socket.c +++ b/dlls/ntdll/unix/socket.c @@ -983,6 +983,14 @@ static NTSTATUS try_send( int fd, struct async_send_ioctl *async ) ERR( "failed to convert address\n" ); return STATUS_ACCESS_VIOLATION; } + if (sock_type == SOCK_DGRAM && ((unix_addr.addr.sa_family == AF_INET && !unix_addr.in.sin_port) + || (unix_addr.addr.sa_family == AF_INET6 && !unix_addr.in6.sin6_port))) + { + /* Sending to port 0 succeeds on Windows. Use 'discard' service instead so sendmsg() works on Unix + * while still goes through other parameters validation. */ + WARN( "Trying to use destination port 0, substituing 9.\n" ); + unix_addr.in.sin_port = htons( 9 ); + }
#if defined(HAS_IPX) && defined(SOL_IPX) if (async->addr->sa_family == WS_AF_IPX) diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index 0015aae67a5..437ee813611 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -3187,6 +3187,7 @@ static void test_UDP(void) struct sock_info peer[NUM_UDP_PEERS]; char buf[16], sockaddr_buf[1024]; int ss, i, n_recv, n_sent, ret; + struct sockaddr_in6 addr6; struct sockaddr_in addr; int sock; struct send_udp_thread_param udp_thread_param; @@ -3298,6 +3299,26 @@ static void test_UDP(void) CloseHandle( udp_thread_param.start_event );
closesocket(sock); + + /* Test sending to port 0. */ + sock = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ); + ok( sock != INVALID_SOCKET, "got error %u.\n", WSAGetLastError() ); + memset( &addr, 0, sizeof(addr) ); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = inet_addr( "127.0.0.1" ); + ret = sendto( sock, buf, sizeof(buf), 0, (struct sockaddr *)&addr, sizeof(addr) ); + ok( ret == sizeof(buf), "got ret %d, error %u.\n", ret, WSAGetLastError() ); + closesocket(sock); + + sock = socket( AF_INET6, SOCK_DGRAM, 0 ); + ok( sock != INVALID_SOCKET, "got error %u.\n", WSAGetLastError() ); + memset( &addr6, 0, sizeof(addr6) ); + addr6.sin6_family = AF_INET6; + ret = inet_pton( AF_INET6, "::1", &addr6.sin6_addr ); + ok( ret, "got error %u.\n", WSAGetLastError() ); + ret = sendto( sock, buf, sizeof(buf), 0, (struct sockaddr *)&addr6, sizeof(addr6) ); + ok( ret == sizeof(buf), "got ret %d, error %u.\n", ret, WSAGetLastError() ); + closesocket(sock); }
static void test_WSASocket(void)