diff options
| author | Thiago Macieira <thiago.macieira@intel.com> | 2025-10-16 10:09:03 -0700 |
|---|---|---|
| committer | Thiago Macieira <thiago.macieira@intel.com> | 2025-10-21 16:56:17 -0700 |
| commit | aaf908e3cf90cab8e203b7343e9e3dbd150c243f (patch) | |
| tree | a3a68779d6d3a3d03823798e861d2a711f5a26de /src/network/socket/qnativesocketengine_unix.cpp | |
| parent | 9c77130f5617232b2aab85a8a76ec346015d708d (diff) | |
QNativeSocketEngine/Unix: implement IP_RECVIF in setOption()
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<UP,LOOPBACK,RUNNING,MULTICAST,LOWER_UP> metric 0 mtu 16384
options=680003<RXCSUM,TXCSUM,LINKSTATE,RXCSUM_IPV6,TXCSUM_IPV6>
inet 127.0.0.1 netmask 0xff000000
inet6 ::1 prefixlen 128
inet6 fe80::1%lo0 prefixlen 64 scopeid 0x2
groups: lo
nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>
Change-Id: I37b88bfce40421117d99fffd1110eced5d102430
Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io>
Diffstat (limited to 'src/network/socket/qnativesocketengine_unix.cpp')
| -rw-r--r-- | src/network/socket/qnativesocketengine_unix.cpp | 16 |
1 files changed, 12 insertions, 4 deletions
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; |
