From c6bb0e50118d08252eee308de8412751218442d6 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Thu, 28 Dec 2023 16:07:39 -0600 Subject: [PATCH] Add workaround for Apple kernel bug --- unix.c | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/unix.c b/unix.c index 6ee5ddd1..0903dadc 100644 --- a/unix.c +++ b/unix.c @@ -219,6 +219,27 @@ enet_time_set (enet_uint32 newTimeBase) timeBase = timeVal.tv_sec * 1000 + timeVal.tv_usec / 1000 - newTimeBase; } +#ifdef __APPLE__ +void +enet_address_make_v4mapped (ENetAddress * address) +{ + ENetAddress oldAddress = *address; + struct sockaddr_in *sin = ((struct sockaddr_in *)&oldAddress.address); + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&address->address; + + memset(sin6, 0, sizeof(*sin6)); + sin6->sin6_family = AF_INET6; + sin6->sin6_len = sizeof(*sin6); + sin6->sin6_port = sin->sin_port; + + sin6->sin6_addr.s6_addr[10] = 0xFF; + sin6->sin6_addr.s6_addr[11] = 0xFF; + memcpy(&sin6->sin6_addr.s6_addr[12], &sin->sin_addr, 4); + + address->addressLength = sizeof(*sin6); +} +#endif + int enet_address_equal (ENetAddress * address1, ENetAddress * address2) { @@ -729,8 +750,19 @@ enet_socket_receive (ENetSocket socket, } } - if (peerAddress != NULL) - peerAddress -> addressLength = msgHdr.msg_namelen; + if (peerAddress != NULL) { + peerAddress -> addressLength = msgHdr.msg_namelen; + +#ifdef __APPLE__ + // HACK: Apple platforms return AF_INET addresses in msg_name from recvmsg() on dual-stack sockets + // instead of AF_INET6 addresses then rejects those same addresses when they are passed to sendmsg(). + // Strangely, this only happens when the socket is bound, and IPV6_PKTINFO properly returns v4-mapped + // addresses in the same call. This is probably a kernel bug, so we fix it up here. + if (peerAddress -> address.ss_family == AF_INET && localAddress -> address.ss_family == AF_INET6) { + enet_address_make_v4mapped(peerAddress); + } +#endif + } return recvLength; #endif