summaryrefslogtreecommitdiffstats
path: root/src/network/socket/qnativesocketengine_unix.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/socket/qnativesocketengine_unix.cpp')
-rw-r--r--src/network/socket/qnativesocketengine_unix.cpp63
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)