From aaf908e3cf90cab8e203b7343e9e3dbd150c243f Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 16 Oct 2025 10:09:03 -0700 Subject: QNativeSocketEngine/Unix: implement IP_RECVIF in setOption() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This amends and complements abe269bb72233b360bccbc8f54d3f13e8dc10b5a, which added QNativeSocketEngine::ReceivePacketInformation and actually did implement the heretofore-dead code to handle the IP_RECVIF ancilary data in nativeReceiveDatagram(), but we never asked the OS for the information via setsockopt(). Similar to what e9778dfe6ead0c4d704570816a56aead084a0263 did for Windows. Tested on FreeBSD. dtruss says: socket(PF_INET,SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK,0) = 7 (0x7) setsockopt(7,SOL_SOCKET,SO_BROADCAST,0xb1cf40aece4,4) = 0 (0x0) setsockopt(7,IPPROTO_IP,IP_RECVDSTADDR,0xb1cf40aece4,4) = 0 (0x0) setsockopt(7,IPPROTO_IP,IP_RECVIF,0xb1cf40aece4,4) = 0 (0x0) setsockopt(7,IPPROTO_IP,IP_RECVTTL,0xb1cf40aece4,4) = 0 (0x0) bind(7,{ AF_INET 127.0.0.1:0 },16) = 0 (0x0) ... ppoll({ 7/POLLIN },1,{ 8.999999439 },0x0) = 1 (0x1) recvfrom(7,"@",1,MSG_PEEK,NULL,0x0) = 1 (0x1) recvmsg(7,{{ AF_INET 127.0.0.1:55621 },16,[{"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"...,1200}],1, { {level=IPPROTO_IP,type=IP_RECVDSTADDR,data={0x7f,0x00,0x00,0x01}}, {level=IPPROTO_IP,type=IP_RECVTTL,data={0x40}}, {level=IPPROTO_IP,type=IP_RECVIF,data={0x38,0x12,0x02,0x00,0x18,0x03,0x00,0x00,0x6c,0x6f,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} },120,0},0) = 600 (0x258) lldb decodes the sockaddr_dl as: (lldb) p *sdl (sockaddr_dl) { sdl_len = '8' sdl_family = '\x12' sdl_index = 2 sdl_type = '\x18' sdl_nlen = '\x03' sdl_alen = '\0' sdl_slen = '\0' sdl_data = "lo0" } And interface index 2 is lo0: lo0: flags=1008049 metric 0 mtu 16384 options=680003 inet 127.0.0.1 netmask 0xff000000 inet6 ::1 prefixlen 128 inet6 fe80::1%lo0 prefixlen 64 scopeid 0x2 groups: lo nd6 options=21 Change-Id: I37b88bfce40421117d99fffd1110eced5d102430 Reviewed-by: MÃ¥rten Nordheim --- src/network/socket/qnativesocketengine_unix.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'src/network/socket/qnativesocketengine_unix.cpp') diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index 120d2ecbc78..885af248ea7 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -142,10 +142,6 @@ static void convertToLevelAndOption(QNativeSocketEngine::SocketOption opt, level = IPPROTO_IP; #ifdef IP_PKTINFO n = IP_PKTINFO; -#elif defined(IP_RECVDSTADDR) - // variant found in QNX and FreeBSD; it will get us only the - // destination address, not the interface; we need IP_RECVIF for that. - n = IP_RECVDSTADDR; #endif } break; @@ -360,6 +356,18 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt case QNativeSocketEngine::BindExclusively: return true; + case QNativeSocketEngine::ReceivePacketInformation: + if (socketProtocol == QAbstractSocket::IPv4Protocol) { +#if !defined(IP_PKTINFO) && defined(IP_RECVDSTADDR) && defined(IP_RECVIF) + // Seen on FreeBSD and QNX. We need both to get the information we want. + int r = 0; + r += ::setsockopt(socketDescriptor, IPPROTO_IP, IP_RECVDSTADDR, &v, sizeof(v)); + r += ::setsockopt(socketDescriptor, IPPROTO_IP, IP_RECVIF, &v, sizeof(v)); + return r == 0; +#endif + } + break; + case QNativeSocketEngine::MaxStreamsSocketOption: { #ifndef QT_NO_SCTP sctp_initmsg sctpInitMsg; -- cgit v1.2.3