diff options
Diffstat (limited to 'src/network/socket/qnativesocketengine_unix.cpp')
-rw-r--r-- | src/network/socket/qnativesocketengine_unix.cpp | 63 |
1 files changed, 54 insertions, 9 deletions
diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index 0671854ccee..bcd9aecdea9 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -11,6 +11,7 @@ #include "qhostaddress.h" #include "qvarlengtharray.h" #include "qnetworkinterface.h" +#include "qnetworkinterface_p.h" #include "qendian.h" #ifdef Q_OS_WASM #include <private/qeventdispatcher_wasm_p.h> @@ -82,6 +83,9 @@ static void convertToLevelAndOption(QNativeSocketEngine::SocketOption opt, case QNativeSocketEngine::MaxStreamsSocketOption: Q_UNREACHABLE(); + case QNativeSocketEngine::BindInterfaceIndex: + Q_UNREACHABLE(); // handled directly in setOption() + case QNativeSocketEngine::BroadcastSocketOption: n = SO_BROADCAST; break; @@ -236,6 +240,20 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc return false; } + // Attempt to enable dual-stack + if (domain == AF_INET6) { + const int ipv6only = 0; + [[maybe_unused]] const int ret = ::setsockopt(socket, IPPROTO_IPV6, IPV6_V6ONLY, + &ipv6only, sizeof(ipv6only)); +#if defined (QNATIVESOCKETENGINE_DEBUG) + if (ret != 0) { + qDebug("QNativeSocketEnginePrivate::createNewSocket(%d, %d): " + "failed to set IPV6_V6ONLY to %d.", + socketType, socketProtocol, ipv6only); + } +#endif + } + #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QNativeSocketEnginePrivate::createNewSocket(%d, %d) == true", socketType, socketProtocol); @@ -359,7 +377,27 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt #endif return false; } - + case QNativeSocketEngine::BindInterfaceIndex: { +#if defined(SO_BINDTOIFINDEX) // seen on Linux + return ::setsockopt(socketDescriptor, SOL_SOCKET, SO_BINDTOIFINDEX, + &v, sizeof(v)) == 0; +#elif defined(IPV6_BOUND_IF) && defined(IP_BOUND_IF) // seen on Darwin + // note: on Darwin, this only limits sending the data, not receiving it + if (socketProtocol == QAbstractSocket::IPv6Protocol + || socketProtocol == QAbstractSocket::AnyIPProtocol) { + return ::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_BOUND_IF, &v, sizeof(v)) == 0; + } else { + return ::setsockopt(socketDescriptor, IPPROTO_IP, IP_BOUND_IF, &v, sizeof(v)) == 0; + } +#elif defined(SO_BINDTODEVICE) && QT_CONFIG(networkinterface) + // need to convert to interface name + const QByteArray name = QNetworkInterfaceManager::interfaceNameFromIndex(v).toLatin1(); + return ::setsockopt(socketDescriptor, SOL_SOCKET, SO_BINDTODEVICE, + name.data(), socklen_t(name.size())) == 0; +#else + return false; +#endif + } default: break; } @@ -1206,6 +1244,7 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters() QT_SOCKOPTLEN_T valueSize = sizeof(int); if (::getsockopt(socketDescriptor, SOL_SOCKET, SO_TYPE, &value, &valueSize) == 0) { if (value == SOCK_STREAM) { + socketType = QAbstractSocket::TcpSocket; #ifndef QT_NO_SCTP if (option(QNativeSocketEngine::MaxStreamsSocketOption) != -1) { socketType = QAbstractSocket::SctpSocket; @@ -1228,17 +1267,23 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters() return false; } } - } else { - socketType = QAbstractSocket::TcpSocket; } -#else - socketType = QAbstractSocket::TcpSocket; +#endif + } else if (value == SOCK_DGRAM) { + socketType = QAbstractSocket::UdpSocket; +#ifdef SOCK_SEQPACKET + } else if (value == SOCK_SEQPACKET) { + // We approximate the SEQPACKET socket type to TCP, because + // this enum is actually used to determine if the socket type has + // a notion of connection. SOCK_DGRAM are connectionless, while + // SOCK_STREAM and SOCK_SEQPACKET are connection-orientired. + // This mapping is still suboptimal, because it is possible to send + // a 0-byte packet via SEQPACKET socket and Qt will treat it as + // a disconnect. + socketType = QAbstractSocket::TcpSocket; #endif } else { - if (value == SOCK_DGRAM) - socketType = QAbstractSocket::UdpSocket; - else - socketType = QAbstractSocket::UnknownSocketType; + socketType = QAbstractSocket::UnknownSocketType; } } #if defined (QNATIVESOCKETENGINE_DEBUG) |