diff options
author | Shane Kearns <shane.kearns@accenture.com> | 2012-05-09 17:13:59 +0100 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-05-11 17:39:13 +0200 |
commit | 6abc66e076826b24cc3700c3a0702f552ab50429 (patch) | |
tree | 6d6800b5cb4f0b10ffc776f16a7b5afdcf0d88ad /src/network | |
parent | b72c8dd8a248d67b1192e3baa1fca07244a3719d (diff) |
Fix sending UDP packets to link local addresses
When the scope ID is not set, Mac and Windows will not transmit
packets to link local addresses. This patch implements setting
the scope in the native socket engines and adds a test case.
(it was partially implemented already, though UDP specific code
paths were missed in the unix engine)
Task-number: QTBUG-25634
Change-Id: I23300bdc9856e38458078e913daaa59cd05a74b5
Reviewed-by: Martin Petersson <Martin.Petersson@nokia.com>
Diffstat (limited to 'src/network')
-rw-r--r-- | src/network/socket/qnativesocketengine_unix.cpp | 37 | ||||
-rw-r--r-- | src/network/socket/qnativesocketengine_win.cpp | 10 |
2 files changed, 27 insertions, 20 deletions
diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index 91299f5f92..f5f9bba1ff 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -862,23 +862,28 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l if (host.protocol() == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) { - memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6)); - sockAddrIPv6.sin6_family = AF_INET6; - sockAddrIPv6.sin6_port = htons(port); - - Q_IPV6ADDR tmp = host.toIPv6Address(); - memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &tmp, sizeof(tmp)); - sockAddrSize = sizeof(sockAddrIPv6); - sockAddrPtr = (struct sockaddr *)&sockAddrIPv6; - } else + memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6)); + sockAddrIPv6.sin6_family = AF_INET6; + sockAddrIPv6.sin6_port = htons(port); - if (host.protocol() == QAbstractSocket::IPv4Protocol) { - memset(&sockAddrIPv4, 0, sizeof(sockAddrIPv4)); - sockAddrIPv4.sin_family = AF_INET; - sockAddrIPv4.sin_port = htons(port); - sockAddrIPv4.sin_addr.s_addr = htonl(host.toIPv4Address()); - sockAddrSize = sizeof(sockAddrIPv4); - sockAddrPtr = (struct sockaddr *)&sockAddrIPv4; + Q_IPV6ADDR tmp = host.toIPv6Address(); + memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &tmp, sizeof(tmp)); + QString scopeid = host.scopeId(); + bool ok; + sockAddrIPv6.sin6_scope_id = scopeid.toInt(&ok); +#ifndef QT_NO_IPV6IFNAME + if (!ok) + sockAddrIPv6.sin6_scope_id = ::if_nametoindex(scopeid.toLatin1()); +#endif + sockAddrSize = sizeof(sockAddrIPv6); + sockAddrPtr = (struct sockaddr *)&sockAddrIPv6; + } else if (host.protocol() == QAbstractSocket::IPv4Protocol) { + memset(&sockAddrIPv4, 0, sizeof(sockAddrIPv4)); + sockAddrIPv4.sin_family = AF_INET; + sockAddrIPv4.sin_port = htons(port); + sockAddrIPv4.sin_addr.s_addr = htonl(host.toIPv4Address()); + sockAddrSize = sizeof(sockAddrIPv4); + sockAddrPtr = (struct sockaddr *)&sockAddrIPv4; } // ignore the SIGPIPE signal diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index 4bf2a6c6e3..bd9550e207 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -170,10 +170,12 @@ static inline void qt_socket_getPortAndAddress(SOCKET socketDescriptor, const qt Q_IPV6ADDR tmp; for (int i = 0; i < 16; ++i) tmp.c[i] = sa6->sin6_addr.qt_s6_addr[i]; - QHostAddress a; - a.setAddress(tmp); - if (address) - *address = a; + if (address) { + QHostAddress a; + a.setAddress(tmp); + a.setScopeId(QString::number(sa6->sin6_scope_id)); + *address = a; + } if (port) WSANtohs(socketDescriptor, sa6->sin6_port, port); } else |