diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2015-03-10 17:03:42 -0700 |
---|---|---|
committer | Thiago Macieira <thiago.macieira@intel.com> | 2015-08-22 22:26:37 +0000 |
commit | 28dfc33c3a10c7bc195bbca179891118b0e2f14d (patch) | |
tree | ae1a5349464c8de81ad5842fa91dcdb4adcde0ff /src/network/socket/qnativesocketengine_unix.cpp | |
parent | abe269bb72233b360bccbc8f54d3f13e8dc10b5a (diff) |
QNativeSocketEngine: add code to send extra IP header data
Change-Id: Iee8cbc07c4434ce9b560ffff13ca48c053bd88ed
Reviewed-by: Richard J. Moore <rich@kde.org>
Diffstat (limited to 'src/network/socket/qnativesocketengine_unix.cpp')
-rw-r--r-- | src/network/socket/qnativesocketengine_unix.cpp | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index 7e794e8c0f..f2fac66cd6 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -975,6 +975,10 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxS qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 len, const QIpPacketHeader &header) { + // we use quintptr to force the alignment + quintptr cbuf[(CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int)) + sizeof(quintptr) - 1) / sizeof(quintptr)]; + + struct cmsghdr *cmsgptr = reinterpret_cast<struct cmsghdr *>(cbuf); struct msghdr msg; struct iovec vec; qt_sockaddr aa; @@ -986,6 +990,7 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l msg.msg_iov = &vec; msg.msg_iovlen = 1; msg.msg_name = &aa.a; + msg.msg_control = &cbuf; if (header.destinationAddress.protocol() == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::IPv6Protocol @@ -997,17 +1002,70 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l Q_IPV6ADDR tmp = header.destinationAddress.toIPv6Address(); memcpy(&aa.a6.sin6_addr, &tmp, sizeof(tmp)); msg.msg_namelen = sizeof(aa.a6); + + if (header.hopLimit != -1) { + msg.msg_controllen += CMSG_SPACE(sizeof(int)); + cmsgptr->cmsg_len = CMSG_LEN(sizeof(int)); + cmsgptr->cmsg_level = IPPROTO_IPV6; + cmsgptr->cmsg_type = IPV6_HOPLIMIT; + memcpy(CMSG_DATA(cmsgptr), &header.hopLimit, sizeof(int)); + cmsgptr = reinterpret_cast<cmsghdr *>(reinterpret_cast<char *>(cmsgptr) + CMSG_SPACE(sizeof(int))); + } + if (header.ifindex != 0 || !header.senderAddress.isNull()) { + struct in6_pktinfo *data = reinterpret_cast<in6_pktinfo *>(CMSG_DATA(cmsgptr)); + memset(data, 0, sizeof(*data)); + msg.msg_controllen += CMSG_SPACE(sizeof(*data)); + cmsgptr->cmsg_len = CMSG_LEN(sizeof(*data)); + cmsgptr->cmsg_level = IPPROTO_IPV6; + cmsgptr->cmsg_type = IPV6_PKTINFO; + data->ipi6_ifindex = header.ifindex; + + tmp = header.senderAddress.toIPv6Address(); + memcpy(&data->ipi6_addr, &tmp, sizeof(tmp)); + cmsgptr = reinterpret_cast<cmsghdr *>(reinterpret_cast<char *>(cmsgptr) + CMSG_SPACE(sizeof(*data))); + } } else if (header.destinationAddress.protocol() == QAbstractSocket::IPv4Protocol) { aa.a4.sin_family = AF_INET; aa.a4.sin_port = htons(header.destinationPort); aa.a4.sin_addr.s_addr = htonl(header.destinationAddress.toIPv4Address()); msg.msg_namelen = sizeof(aa.a4); + + if (header.hopLimit != -1) { + msg.msg_controllen += CMSG_SPACE(sizeof(int)); + cmsgptr->cmsg_len = CMSG_LEN(sizeof(int)); + cmsgptr->cmsg_level = IPPROTO_IP; + cmsgptr->cmsg_type = IP_TTL; + memcpy(CMSG_DATA(cmsgptr), &header.hopLimit, sizeof(int)); + cmsgptr = reinterpret_cast<cmsghdr *>(reinterpret_cast<char *>(cmsgptr) + CMSG_SPACE(sizeof(int))); + } + +#if defined(IP_PKTINFO) || defined(IP_SENDSRCADDR) + if (header.ifindex != 0 || !header.senderAddress.isNull()) { +# ifdef IP_PKTINFO + struct in_pktinfo *data = reinterpret_cast<in_pktinfo *>(CMSG_DATA(cmsgptr)); + memset(data, 0, sizeof(*data)); + cmsgptr->cmsg_type = IP_PKTINFO; + data->ipi_ifindex = header.ifindex; + data->ipi_addr.s_addr = htonl(header.senderAddress.toIPv4Address()); +# elif defined(IP_SENDSRCADDR) + struct in_addr *data = reinterpret_cast<in_addr *>(CMSG_DATA(cmsgptr)); + cmsgptr->cmsg_type = IP_SENDSRCADDR; + addr->s_addr = htonl(header.senderAddress.toIPv4Address()); +# endif + cmsgptr->cmsg_level = IPPROTO_IP; + msg.msg_controllen += CMSG_SPACE(sizeof(*data)); + cmsgptr->cmsg_len = CMSG_LEN(sizeof(*data)); + cmsgptr = reinterpret_cast<cmsghdr *>(reinterpret_cast<char *>(cmsgptr) + CMSG_SPACE(sizeof(*data))); + } +#endif } else { // Don't know what IP type this is, let's hope it sends msg.msg_name = 0; msg.msg_namelen = 0; } + if (msg.msg_controllen == 0) + msg.msg_control = 0; ssize_t sentBytes = qt_safe_sendmsg(socketDescriptor, &msg, 0); if (sentBytes < 0) { |