summaryrefslogtreecommitdiffstats
path: root/src/network
diff options
context:
space:
mode:
Diffstat (limited to 'src/network')
-rw-r--r--src/network/kernel/qhostaddress.cpp62
-rw-r--r--src/network/kernel/qhostaddress.h3
-rw-r--r--src/network/socket/qabstractsocket.h1
-rw-r--r--src/network/socket/qnativesocketengine_p.h9
-rw-r--r--src/network/socket/qnativesocketengine_unix.cpp14
-rw-r--r--src/network/socket/qnativesocketengine_win.cpp39
-rw-r--r--src/network/socket/qsocks5socketengine.cpp10
7 files changed, 111 insertions, 27 deletions
diff --git a/src/network/kernel/qhostaddress.cpp b/src/network/kernel/qhostaddress.cpp
index 7eeb4e5a51..bff351c34f 100644
--- a/src/network/kernel/qhostaddress.cpp
+++ b/src/network/kernel/qhostaddress.cpp
@@ -134,15 +134,40 @@ QHostAddressPrivate::QHostAddressPrivate()
void QHostAddressPrivate::setAddress(quint32 a_)
{
a = a_;
+ //create mapped address
+ memset(&a6, 0, sizeof(a6));
+ int i;
+ for (i=15; a_ != 0; i--) {
+ a6[i] = a_ & 0xFF;
+ a_ >>=8;
+ }
+ Q_ASSERT(i >= 11);
+ a6[11] = 0xFF;
+ a6[10] = 0xFF;
protocol = QAbstractSocket::IPv4Protocol;
isParsed = true;
}
+static bool parseMappedAddress(quint32& a, const Q_IPV6ADDR &a6)
+{
+ int i;
+ for (i=0;i<10;i++)
+ if (a6[i]) return false;
+ for (;i<12;i++)
+ if (a6[i] != 0xFF) return false;
+ a=(a6[12] << 24) | (a6[13] << 16) | (a6[14] << 8) | a6[15];
+ return true;
+}
+
void QHostAddressPrivate::setAddress(const quint8 *a_)
{
for (int i = 0; i < 16; i++)
a6[i] = a_[i];
- protocol = QAbstractSocket::IPv6Protocol;
+ a = 0;
+ if (parseMappedAddress(a, a6))
+ protocol = QAbstractSocket::IPv4Protocol;
+ else
+ protocol = QAbstractSocket::IPv6Protocol;
isParsed = true;
}
@@ -150,7 +175,10 @@ void QHostAddressPrivate::setAddress(const Q_IPV6ADDR &a_)
{
a6 = a_;
a = 0;
- protocol = QAbstractSocket::IPv6Protocol;
+ if (parseMappedAddress(a, a6))
+ protocol = QAbstractSocket::IPv4Protocol;
+ else
+ protocol = QAbstractSocket::IPv6Protocol;
isParsed = true;
}
@@ -447,8 +475,9 @@ void QNetmaskAddress::setPrefixLength(QAbstractSocket::NetworkLayerProtocol prot
\value LocalHost The IPv4 localhost address. Equivalent to QHostAddress("127.0.0.1").
\value LocalHostIPv6 The IPv6 localhost address. Equivalent to QHostAddress("::1").
\value Broadcast The IPv4 broadcast address. Equivalent to QHostAddress("255.255.255.255").
- \value Any The IPv4 any-address. Equivalent to QHostAddress("0.0.0.0").
- \value AnyIPv6 The IPv6 any-address. Equivalent to QHostAddress("::").
+ \value AnyIPv4 The IPv4 any-address. Equivalent to QHostAddress("0.0.0.0"). A socket bound with this address will listen only on IPv4 interaces.
+ \value AnyIPv6 The IPv6 any-address. Equivalent to QHostAddress("::"). A socket bound with this address will listen only on IPv6 interaces.
+ \value Any The dual stack any-address. A socket bound with this address will listen on both IPv4 and IPv6 interfaces.
*/
/*! Constructs a host address object with the IP address 0.0.0.0.
@@ -548,12 +577,16 @@ QHostAddress::QHostAddress(SpecialAddress address)
case LocalHostIPv6:
setAddress(QLatin1String("::1"));
break;
- case Any:
+ case AnyIPv4:
setAddress(QLatin1String("0.0.0.0"));
break;
case AnyIPv6:
setAddress(QLatin1String("::"));
break;
+ case Any:
+ d->clear();
+ d->protocol = QAbstractSocket::AnyIPProtocol;
+ break;
}
}
@@ -679,8 +712,11 @@ void QHostAddress::setAddress(const struct sockaddr *sockaddr)
For example, if the address is 127.0.0.1, the returned value is
2130706433 (i.e. 0x7f000001).
- This value is only valid if the Protocol() is
- \l{QAbstractSocket::}{IPv4Protocol}.
+ This value is valid if the protocol() is
+ \l{QAbstractSocket::}{IPv4Protocol},
+ or if the protocol is
+ \l{QAbstractSocket::}{IPv6Protocol},
+ and the IPv6 address is an IPv4 mapped address. (RFC4291)
\sa toString()
*/
@@ -705,8 +741,11 @@ QAbstractSocket::NetworkLayerProtocol QHostAddress::protocol() const
\snippet doc/src/snippets/code/src_network_kernel_qhostaddress.cpp 0
- This value is only valid if the protocol() is
+ This value is valid if the protocol() is
\l{QAbstractSocket::}{IPv6Protocol}.
+ If the protocol is
+ \l{QAbstractSocket::}{IPv4Protocol},
+ then the address is returned an an IPv4 mapped IPv6 address. (RFC4291)
\sa toString()
*/
@@ -722,13 +761,15 @@ Q_IPV6ADDR QHostAddress::toIPv6Address() const
For example, if the address is the IPv4 address 127.0.0.1, the
returned string is "127.0.0.1". For IPv6 the string format will
follow the RFC5952 recommendation.
+ For QHostAddress::Any, its IPv4 address will be returned ("0.0.0.0")
\sa toIPv4Address()
*/
QString QHostAddress::toString() const
{
QT_ENSURE_PARSED(this);
- if (d->protocol == QAbstractSocket::IPv4Protocol) {
+ if (d->protocol == QAbstractSocket::IPv4Protocol
+ || d->protocol == QAbstractSocket::AnyIPProtocol) {
quint32 i = toIPv4Address();
QString s;
s.sprintf("%d.%d.%d.%d", (i>>24) & 0xff, (i>>16) & 0xff,
@@ -1183,6 +1224,9 @@ QDataStream &operator>>(QDataStream &in, QHostAddress &address)
address.setScopeId(scope);
}
break;
+ case QAbstractSocket::AnyIPProtocol:
+ address = QHostAddress::Any;
+ break;
default:
address.clear();
in.setStatus(QDataStream::ReadCorruptData);
diff --git a/src/network/kernel/qhostaddress.h b/src/network/kernel/qhostaddress.h
index 486f2322ae..efb3198fc0 100644
--- a/src/network/kernel/qhostaddress.h
+++ b/src/network/kernel/qhostaddress.h
@@ -76,7 +76,8 @@ public:
LocalHost,
LocalHostIPv6,
Any,
- AnyIPv6
+ AnyIPv6,
+ AnyIPv4
};
QHostAddress();
diff --git a/src/network/socket/qabstractsocket.h b/src/network/socket/qabstractsocket.h
index 1959fabdfc..2717ceb58a 100644
--- a/src/network/socket/qabstractsocket.h
+++ b/src/network/socket/qabstractsocket.h
@@ -74,6 +74,7 @@ public:
enum NetworkLayerProtocol {
IPv4Protocol,
IPv6Protocol,
+ AnyIPProtocol,
UnknownNetworkLayerProtocol = -1
};
enum SocketError {
diff --git a/src/network/socket/qnativesocketengine_p.h b/src/network/socket/qnativesocketengine_p.h
index c5c4b325d0..a024cd42d1 100644
--- a/src/network/socket/qnativesocketengine_p.h
+++ b/src/network/socket/qnativesocketengine_p.h
@@ -74,6 +74,11 @@ struct qt_sockaddr_storage {
char __ss_pad2[QT_SS_PAD2SIZE];
};
+#ifdef Q_OS_WIN
+#define QT_SOCKLEN_T int
+#define QT_SOCKOPTLEN_T int
+#endif
+
// sockaddr_in6 size changed between old and new SDK
// Only the new version is the correct one, so always
// use this structure.
@@ -265,6 +270,10 @@ public:
int nativeSelect(int timeout, bool selectForRead) const;
int nativeSelect(int timeout, bool checkRead, bool checkWrite,
bool *selectForRead, bool *selectForWrite) const;
+#ifdef Q_OS_WIN
+ void setPortAndAddress(sockaddr_in * sockAddrIPv4, qt_sockaddr_in6 * sockAddrIPv6,
+ quint16 port, const QHostAddress & address, sockaddr ** sockAddrPtr, QT_SOCKLEN_T *sockAddrSize);
+#endif
void nativeClose();
diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp
index 39570c8c04..26053981ce 100644
--- a/src/network/socket/qnativesocketengine_unix.cpp
+++ b/src/network/socket/qnativesocketengine_unix.cpp
@@ -163,7 +163,7 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc
QAbstractSocket::NetworkLayerProtocol socketProtocol)
{
#ifndef QT_NO_IPV6
- int protocol = (socketProtocol == QAbstractSocket::IPv6Protocol) ? AF_INET6 : AF_INET;
+ int protocol = (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) ? AF_INET6 : AF_INET;
#else
Q_UNUSED(socketProtocol);
int protocol = AF_INET;
@@ -495,7 +495,14 @@ bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16
#if !defined(QT_NO_IPV6)
struct sockaddr_in6 sockAddrIPv6;
- if (address.protocol() == QAbstractSocket::IPv6Protocol) {
+ if (address.protocol() == QAbstractSocket::IPv6Protocol || address.protocol() == QAbstractSocket::AnyIPProtocol) {
+#ifdef IPV6_V6ONLY
+ int ipv6only = 0;
+ if (address.protocol() == QAbstractSocket::IPv6Protocol)
+ ipv6only = 1;
+ //default value of this socket option varies depending on unix variant (or system configuration on BSD), so always set it explicitly
+ ::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6only, sizeof(ipv6only) );
+#endif
memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6));
sockAddrIPv6.sin6_family = AF_INET6;
sockAddrIPv6.sin6_port = htons(port);
@@ -866,7 +873,8 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l
#if !defined(QT_NO_IPV6)
struct sockaddr_in6 sockAddrIPv6;
- if (host.protocol() == QAbstractSocket::IPv6Protocol) {
+ if (host.protocol() == QAbstractSocket::IPv6Protocol
+ || socketProtocol == QAbstractSocket::IPv6Protocol) {
memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6));
sockAddrIPv6.sin6_family = AF_INET6;
sockAddrIPv6.sin6_port = htons(port);
diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp
index 88b87b98fe..ba62bd6da2 100644
--- a/src/network/socket/qnativesocketengine_win.cpp
+++ b/src/network/socket/qnativesocketengine_win.cpp
@@ -159,11 +159,6 @@ static QByteArray qt_prettyDebug(const char *data, int len, int maxLength)
#define SO_EXCLUSIVEADDRUSE ((int)(~SO_REUSEADDR)) /* disallow local address reuse */
#endif
-//###
-#define QT_SOCKLEN_T int
-#define QT_SOCKOPTLEN_T int
-
-
/*
Extracts the port and address from a sockaddr, and stores them in
\a port and \a addr if they are non-null.
@@ -202,11 +197,13 @@ static inline void qt_socket_getPortAndAddress(SOCKET socketDescriptor, const qt
Sets the port and address to a sockaddr. Requires that sa point to the IPv6 struct if the address is IPv6.
*/
-static inline void qt_socket_setPortAndAddress(SOCKET socketDescriptor, sockaddr_in * sockAddrIPv4, qt_sockaddr_in6 * sockAddrIPv6,
+void QNativeSocketEnginePrivate::setPortAndAddress(sockaddr_in * sockAddrIPv4, qt_sockaddr_in6 * sockAddrIPv6,
quint16 port, const QHostAddress & address, sockaddr ** sockAddrPtr, QT_SOCKLEN_T *sockAddrSize)
{
#if !defined(QT_NO_IPV6)
- if (address.protocol() == QAbstractSocket::IPv6Protocol) {
+ if (address.protocol() == QAbstractSocket::IPv6Protocol
+ || address.protocol() == QAbstractSocket::AnyIPProtocol
+ || socketProtocol == QAbstractSocket::IPv6Protocol) {
memset(sockAddrIPv6, 0, sizeof(qt_sockaddr_in6));
sockAddrIPv6->sin6_family = AF_INET6;
sockAddrIPv6->sin6_scope_id = address.scopeId().toInt();
@@ -306,7 +303,9 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc
}
*/
- int protocol = (socketProtocol == QAbstractSocket::IPv6Protocol) ? AF_INET6 : AF_INET;
+ //Windows XP and 2003 support IPv6 but not dual stack sockets
+ int protocol = (socketProtocol == QAbstractSocket::IPv6Protocol
+ || (socketProtocol == QAbstractSocket::AnyIPProtocol && QSysInfo::windowsVersion() >= QSysInfo::WV_6_0)) ? AF_INET6 : AF_INET;
int type = (socketType == QAbstractSocket::UdpSocket) ? SOCK_DGRAM : SOCK_STREAM;
// MSDN KB179942 states that on winnt 4 WSA_FLAG_OVERLAPPED is needed if socket is to be non blocking
// and recomends alwasy doing it for cross windows version comapablity.
@@ -602,7 +601,7 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &address, quin
struct sockaddr *sockAddrPtr = 0;
QT_SOCKLEN_T sockAddrSize = 0;
- qt_socket_setPortAndAddress(socketDescriptor, &sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize);
+ setPortAndAddress(&sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize);
forever {
int connectResult = ::WSAConnect(socketDescriptor, sockAddrPtr, sockAddrSize, 0,0,0,0);
@@ -708,19 +707,35 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &address, quin
bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &a, quint16 port)
{
QHostAddress address = a;
+ DWORD ipv6only = 0;
switch (address.protocol()) {
case QAbstractSocket::IPv6Protocol:
if (address.toIPv6Address()[0] == 0xff) {
// binding to a multicast address
address = QHostAddress(QHostAddress::AnyIPv6);
}
+#if !defined (QT_NO_IPV6) && defined (IPV6_V6ONLY)
+ //This is default in current windows versions, it may change in future so set it explicitly
+ if (QSysInfo::windowsVersion() >= QSysInfo::WV_6_0) {
+ ipv6only = 1;
+ ipv6only = ::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6only, sizeof(ipv6only) );
+ }
+#endif
break;
case QAbstractSocket::IPv4Protocol:
if ((address.toIPv4Address() & 0xffff0000) == 0xefff0000) {
// binding to a multicast address
- address = QHostAddress(QHostAddress::Any);
+ address = QHostAddress(QHostAddress::AnyIPv4);
}
break;
+ case QAbstractSocket::AnyIPProtocol:
+#if !defined (QT_NO_IPV6) && defined (IPV6_V6ONLY)
+ if (QSysInfo::windowsVersion() >= QSysInfo::WV_6_0)
+ ipv6only = ::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6only, sizeof(ipv6only) );
+ else
+#endif
+ address = QHostAddress(QHostAddress::AnyIPv4); //xp/WS2003 and earlier don't support dual stack, so bind to IPv4
+ break;
default:
break;
}
@@ -730,7 +745,7 @@ bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &a, quint16 port)
struct sockaddr *sockAddrPtr = 0;
QT_SOCKLEN_T sockAddrSize = 0;
- qt_socket_setPortAndAddress(socketDescriptor, &sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize);
+ setPortAndAddress(&sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize);
int bindResult = ::bind(socketDescriptor, sockAddrPtr, sockAddrSize);
@@ -1182,7 +1197,7 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l
struct sockaddr *sockAddrPtr = 0;
QT_SOCKLEN_T sockAddrSize = 0;
- qt_socket_setPortAndAddress(socketDescriptor, &sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize);
+ setPortAndAddress(&sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize);
WSABUF buf;
#if !defined(Q_OS_WINCE)
diff --git a/src/network/socket/qsocks5socketengine.cpp b/src/network/socket/qsocks5socketengine.cpp
index ab757987f6..514a7a0f6f 100644
--- a/src/network/socket/qsocks5socketengine.cpp
+++ b/src/network/socket/qsocks5socketengine.cpp
@@ -827,7 +827,7 @@ void QSocks5SocketEnginePrivate::sendRequestMethod()
//### set error code ....
return;
} else if (!peerName.isEmpty() && !qt_socks5_set_host_name_and_port(peerName, port, &buf)) {
- QSOCKS5_DEBUG << "error setting address" << address << " : " << port;
+ QSOCKS5_DEBUG << "error setting peer name" << peerName << " : " << port;
//### set error code ....
return;
}
@@ -1325,12 +1325,18 @@ void QSocks5SocketEnginePrivate::_q_udpSocketReadNotification()
}
#endif // QT_NO_UDPSOCKET
-bool QSocks5SocketEngine::bind(const QHostAddress &address, quint16 port)
+bool QSocks5SocketEngine::bind(const QHostAddress &addr, quint16 port)
{
Q_D(QSocks5SocketEngine);
// when bind wee will block until the bind is finished as the info from the proxy server is needed
+ QHostAddress address;
+ if (addr.protocol() == QAbstractSocket::AnyIPProtocol)
+ address = QHostAddress::AnyIPv4; //SOCKS5 doesnt support dual stack, and there isn't any implementation of udp on ipv6 yet
+ else
+ address = addr;
+
if (!d->data) {
if (socketType() == QAbstractSocket::TcpSocket) {
d->initialize(QSocks5SocketEnginePrivate::BindMode);