bool LimitedSocket::bindSocket(QAbstractSocket* sock, QHostAddress addr) { if(addr.isNull()) return true; int error; if(addr.protocol() == QAbstractSocket::IPv4Protocol) { sockaddr_in in; memset(&in, 0, sizeof(in)); in.sin_addr.s_addr = addr.toIPv4Address(); in.sin_family = AF_INET; error = ::bind(sock->socketDescriptor(), (sockaddr*) &in, sizeof(in)); } else { sockaddr_in6 in6; Q_IPV6ADDR a = addr.toIPv6Address(); memset(&in6, 0, sizeof(in6)); memcpy(in6.sin6_addr.s6_addr, a.c, 16); in6.sin6_family = AF_INET6; error = ::bind(sock->socketDescriptor(), (sockaddr*) &in6, sizeof(in6)); } return !error; }
bool SocksConnection::SerializeSocksAddress(const QString &host, quint16 port, QByteArray &socks_addr) { socks_addr.clear(); QDataStream stream(&socks_addr, QIODevice::WriteOnly); QHostAddress addr; if(addr.setAddress(host)) { switch(addr.protocol()) { case QAbstractSocket::IPv4Protocol: stream << static_cast<quint8>(SocksAddress_IPv4); stream << addr.toIPv4Address(); break; case QAbstractSocket::IPv6Protocol: stream << static_cast<quint8>(SocksAddress_IPv6); stream.writeRawData(reinterpret_cast<const char *> (addr.toIPv6Address().c), 16); break; default: stream << static_cast<quint8>(SocksAddress_Illegal); } } else { stream << static_cast<quint8>(SocksAddress_DomainName); stream << static_cast<quint8>(host.size()); stream.writeRawData(host.toUtf8().constData(), host.size()); } stream << port; return true; }
void setPortAndAddress(quint16 port, const QHostAddress &address, QAbstractSocket::NetworkLayerProtocol socketProtocol, qt_sockaddr *aa, int *sockAddrSize) { if (address.protocol() == QAbstractSocket::IPv6Protocol || address.protocol() == QAbstractSocket::AnyIPProtocol || socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) { memset(&aa->a6, 0, sizeof(sockaddr_in6)); aa->a6.sin6_family = AF_INET6; //#if QT_CONFIG(networkinterface) // aa->a6.sin6_scope_id = scopeIdFromString(address.scopeId()); //#endif aa->a6.sin6_port = htons(port); Q_IPV6ADDR tmp = address.toIPv6Address(); memcpy(&aa->a6.sin6_addr, &tmp, sizeof(tmp)); *sockAddrSize = sizeof(sockaddr_in6); SetSALen::set(&aa->a, sizeof(sockaddr_in6)); } else { memset(&aa->a, 0, sizeof(sockaddr_in)); aa->a4.sin_family = AF_INET; aa->a4.sin_port = htons(port); aa->a4.sin_addr.s_addr = htonl(address.toIPv4Address()); *sockAddrSize = sizeof(sockaddr_in); SetSALen::set(&aa->a, sizeof(sockaddr_in)); } }
/*! \internal 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, quint16 port, const QHostAddress & address, sockaddr ** sockAddrPtr, QT_SOCKLEN_T *sockAddrSize) { #if !defined(QT_NO_IPV6) if (address.protocol() == QAbstractSocket::IPv6Protocol) { memset(sockAddrIPv6, 0, sizeof(qt_sockaddr_in6)); sockAddrIPv6->sin6_family = AF_INET6; sockAddrIPv6->sin6_scope_id = address.scopeId().toInt(); WSAHtons(socketDescriptor, port, &(sockAddrIPv6->sin6_port)); Q_IPV6ADDR tmp = address.toIPv6Address(); memcpy(&(sockAddrIPv6->sin6_addr.qt_s6_addr), &tmp, sizeof(tmp)); *sockAddrSize = sizeof(qt_sockaddr_in6); *sockAddrPtr = (struct sockaddr *) sockAddrIPv6; } else #endif if (address.protocol() == QAbstractSocket::IPv4Protocol || address.protocol() == QAbstractSocket::UnknownNetworkLayerProtocol) { memset(sockAddrIPv4, 0, sizeof(sockaddr_in)); sockAddrIPv4->sin_family = AF_INET; WSAHtons(socketDescriptor, port, &(sockAddrIPv4->sin_port)); WSAHtonl(socketDescriptor, address.toIPv4Address(), &(sockAddrIPv4->sin_addr.s_addr)); *sockAddrSize = sizeof(sockaddr_in); *sockAddrPtr = (struct sockaddr *) sockAddrIPv4; } else { // unreachable } }
// connectRequest static QByteArray sp_set_request(const QHostAddress &addr, unsigned short port, unsigned char cmd1) { int at = 0; QByteArray a; a.resize(4); a[at++] = 0x05; // socks version 5 a[at++] = cmd1; a[at++] = 0x00; // reserved if(addr.protocol() == QAbstractSocket::IPv4Protocol || addr.protocol() == QAbstractSocket::UnknownNetworkLayerProtocol) { a[at++] = 0x01; // address type = ipv4 quint32 ip4 = htonl(addr.toIPv4Address()); a.resize(at+4); memcpy(a.data() + at, &ip4, 4); at += 4; } else { a[at++] = 0x04; Q_IPV6ADDR ip6 = addr.toIPv6Address(); a.resize(at+16); for(int i = 0; i < 16; ++i) a[at++] = ip6[i]; } // port a.resize(at+2); quint16 p = htons(port); memcpy(a.data() + at, &p, 2); return a; }
qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 len, const QHostAddress &host, quint16 port) { struct sockaddr_in sockAddrIPv4; struct sockaddr *sockAddrPtr = 0; QT_SOCKLEN_T sockAddrSize = 0; #if !defined(QT_NO_IPV6) struct sockaddr_in6 sockAddrIPv6; if (host.protocol() == QAbstractSocket::IPv6Protocol) { 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)); 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 #endif 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 qt_ignore_sigpipe(); ssize_t sentBytes = qt_safe_sendto(socketDescriptor, data, len, 0, sockAddrPtr, sockAddrSize); if (sentBytes < 0) { switch (errno) { case EMSGSIZE: setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString); break; default: setError(QAbstractSocket::NetworkError, SendDatagramErrorString); } } #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QNativeSocketEngine::sendDatagram(%p \"%s\", %lli, \"%s\", %i) == %lli", data, qt_prettyDebug(data, qMin<int>(len, 16), len).data(), len, host.toString().toLatin1().constData(), port, (qint64) sentBytes); #endif return qint64(sentBytes); }
void Worker::targetConnectedHandler(void) { this->m_target = new QTcpSocket(this); this->m_connector->assignTo(this->m_target); delete this->m_connector; this->m_connector = 0; union { quint32 v4; Q_IPV6ADDR v6; quint16 port; char ptr; } data; QByteArray response("\x05\x00\x00", 3); QHostAddress a; if (qobject_cast<QAbstractSocket*>(this->m_peer)) { a = (qobject_cast<QAbstractSocket*>(this->m_peer))->peerAddress(); } if (a.protocol() == QAbstractSocket::IPv4Protocol) { response.append('\x01'); data.v4 = qToBigEndian(a.toIPv4Address()); response.append(QByteArray::fromRawData(&data.ptr, sizeof(data.v4))); } else if (a.protocol() == QAbstractSocket::IPv6Protocol) { response.append('\x04'); data.v6 = a.toIPv6Address(); response.append(QByteArray::fromRawData(&data.ptr, sizeof(data.v6))); } else { Q_ASSERT(false); } if (qobject_cast<QAbstractSocket*>(this->m_peer)) { data.port = qToBigEndian<quint16>((qobject_cast<QAbstractSocket*>(this->m_peer))->peerPort()); } else { data.port = 0; } response.append(QByteArray::fromRawData(&data.ptr, sizeof(data.port))); QObject::connect(this->m_target, SIGNAL(readyRead()), this, SLOT(targetReadyReadHandler())); QObject::connect(this->m_target, SIGNAL(disconnected()), this, SLOT(disconnectHandler())); if (this->writeAndFlush(this->m_peer, response) == response.size()) { this->m_state = Worker::ConnectionProxiedState; } else { if (this->m_peer) { this->m_peer->close(); } this->m_state = Worker::FatalErrorState; } }
HostAddress::HostAddress(const QHostAddress &address) { if (address.protocol() == QAbstractSocket::IPv6Protocol) { const Q_IPV6ADDR &a = address.toIPv6Address(); memcpy(qip6.c, a.c, 16); } else { addr[0] = 0ULL; shorts[4] = 0; shorts[5] = 0xffff; hash[3] = htonl(address.toIPv4Address()); } }
QByteArray NetworkManager::Utils::ipv6AddressFromHostAddress(const QHostAddress &address) { // Q_ASSERT(address.protocol() == QAbstractSocket::IPv6Protocol); Q_IPV6ADDR tmp = address.toIPv6Address(); QByteArray assembledAddress; for (int i = 0; i < 16; ++i) { assembledAddress[i] = tmp[i]; } return assembledAddress; }
///Fonction auxiliaire pour appliquer les masques QHostAddress operator&(const QHostAddress& network, const QHostAddress& netmask) { if(network.isNull() || netmask.isNull() || network.protocol() != netmask.protocol()) return QHostAddress(); switch(network.protocol()) { case QAbstractSocket::IPv4Protocol: return QHostAddress(network.toIPv4Address() & netmask.toIPv4Address()); case QAbstractSocket::IPv6Protocol: { Q_IPV6ADDR networkValue = network.toIPv6Address(); Q_IPV6ADDR netmaskValue = netmask.toIPv6Address(); for(int i = 0 ; i < 16 ; i++) networkValue[i] &= netmaskValue[i]; return QHostAddress(networkValue); } default: return QHostAddress(); } }
std::string Common::packAddress(const QHostAddress &addr, const uint16_t &port) { std::string addrBin; char typeChar; std::string portNs(2, '\0'); qToBigEndian(port, reinterpret_cast<uchar*>(&portNs[0])); if (addr.protocol() == QAbstractSocket::IPv4Protocol) { uint32_t ipv4Address = qToBigEndian(addr.toIPv4Address()); typeChar = static_cast<char>(Address::IPV4); addrBin = std::string(reinterpret_cast<char*>(&ipv4Address), 4); } else { typeChar = static_cast<char>(Address::IPV6); Q_IPV6ADDR ipv6Address = addr.toIPv6Address(); addrBin = std::string(reinterpret_cast<char*>(ipv6Address.c), 16); } return typeChar + addrBin + portNs; }
QString GeoIPDatabase::lookup(const QHostAddress &hostAddr) const { Q_IPV6ADDR addr = hostAddr.toIPv6Address(); const uchar *ptr = m_data; for (int i = 0; i < 16; ++i) { for (int j = 0; j < 8; ++j) { bool right = static_cast<bool>((addr[i] >> (7 - j)) & 1); // Interpret the left/right record as number if (right) ptr += m_recordBytes; quint32 id = 0; uchar *idPtr = reinterpret_cast<uchar *>(&id); memcpy(&idPtr[4 - m_recordBytes], ptr, m_recordBytes); fromBigEndian(idPtr, 4); if (id == m_nodeCount) { return QString(); } else if (id > m_nodeCount) { QString country = m_countries.value(id); if (country.isEmpty()) { const quint32 offset = id - m_nodeCount - sizeof(DATA_SECTION_SEPARATOR); quint32 tmp = offset + m_indexSize + sizeof(DATA_SECTION_SEPARATOR); QVariant val = readDataField(tmp); if (val.userType() == QMetaType::QVariantHash) { country = val.toHash()["country"].toHash()["iso_code"].toString(); m_countries[id] = country; } } return country; } else { ptr = m_data + (id * m_nodeSize); } } } return QString(); }
bool isIPInRange(const QHostAddress &addr, const QList<Subnet> &subnets) { QHostAddress protocolEquivalentAddress; bool addrConversionOk = false; if (addr.protocol() == QAbstractSocket::IPv4Protocol) { // always succeeds protocolEquivalentAddress = QHostAddress(addr.toIPv6Address()); addrConversionOk = true; } else { // only succeeds when addr is an ipv4-mapped ipv6 address protocolEquivalentAddress = QHostAddress(addr.toIPv4Address(&addrConversionOk)); } for (const Subnet &subnet : subnets) if (addr.isInSubnet(subnet) || (addrConversionOk && protocolEquivalentAddress.isInSubnet(subnet))) return true; return false; }
/*! \internal Adjusts the incoming \a address family to match the currently bound address (if any). This function will convert v4-mapped IPv6 addresses to IPv4 and vice-versa. All other address types and values will be left unchanged. */ QHostAddress QNativeSocketEnginePrivate::adjustAddressProtocol(const QHostAddress &address) const { QAbstractSocket::NetworkLayerProtocol targetProtocol = socketProtocol; if (Q_LIKELY(targetProtocol == QAbstractSocket::UnknownNetworkLayerProtocol)) return address; QAbstractSocket::NetworkLayerProtocol sourceProtocol = address.protocol(); if (targetProtocol == QAbstractSocket::AnyIPProtocol) targetProtocol = QAbstractSocket::IPv6Protocol; if (targetProtocol == QAbstractSocket::IPv6Protocol && sourceProtocol == QAbstractSocket::IPv4Protocol) { // convert to IPv6 v4-mapped address. This always works return QHostAddress(address.toIPv6Address()); } if (targetProtocol == QAbstractSocket::IPv4Protocol && sourceProtocol == QAbstractSocket::IPv6Protocol) { // convert to IPv4 if the source is a v4-mapped address quint32 ip4 = address.toIPv4Address(); if (ip4) return QHostAddress(ip4); } return address; }
QHostInfo QHostInfoAgent::fromName(const QString &hostName) { QHostInfo results; #if defined(QHOSTINFO_DEBUG) qDebug("QHostInfoAgent::fromName(%s) looking up...", hostName.toLatin1().constData()); #endif // Load res_init on demand. static volatile bool triedResolve = false; if (!triedResolve) { QMutexLocker locker(QMutexPool::globalInstanceGet(&local_res_init)); if (!triedResolve) { resolveLibrary(); triedResolve = true; } } // If res_init is available, poll it. if (local_res_init) local_res_init(); QHostAddress address; if (address.setAddress(hostName)) { // Reverse lookup // Reverse lookups using getnameinfo are broken on darwin, use gethostbyaddr instead. #if !defined (QT_NO_GETADDRINFO) && !defined (Q_OS_DARWIN) sockaddr_in sa4; #ifndef QT_NO_IPV6 sockaddr_in6 sa6; #endif sockaddr *sa = 0; QT_SOCKLEN_T saSize = 0; if (address.protocol() == QAbstractSocket::IPv4Protocol) { sa = (sockaddr *)&sa4; saSize = sizeof(sa4); memset(&sa4, 0, sizeof(sa4)); sa4.sin_family = AF_INET; sa4.sin_addr.s_addr = htonl(address.toIPv4Address()); } #ifndef QT_NO_IPV6 else { sa = (sockaddr *)&sa6; saSize = sizeof(sa6); memset(&sa6, 0, sizeof(sa6)); sa6.sin6_family = AF_INET6; memcpy(sa6.sin6_addr.s6_addr, address.toIPv6Address().c, sizeof(sa6.sin6_addr.s6_addr)); } #endif char hbuf[NI_MAXHOST]; if (sa && getnameinfo(sa, saSize, hbuf, sizeof(hbuf), 0, 0, 0) == 0) results.setHostName(QString::fromLatin1(hbuf)); #else in_addr_t inetaddr = qt_safe_inet_addr(hostName.toLatin1().constData()); struct hostent *ent = gethostbyaddr((const char *)&inetaddr, sizeof(inetaddr), AF_INET); if (ent) results.setHostName(QString::fromLatin1(ent->h_name)); #endif if (results.hostName().isEmpty()) results.setHostName(address.toString()); results.setAddresses(QList<QHostAddress>() << address); return results; } // IDN support QByteArray aceHostname = QUrl::toAce(hostName); results.setHostName(hostName); if (aceHostname.isEmpty()) { results.setError(QHostInfo::HostNotFound); results.setErrorString(hostName.isEmpty() ? QCoreApplication::translate("QHostInfoAgent", "No host name given") : QCoreApplication::translate("QHostInfoAgent", "Invalid hostname")); return results; } #if !defined (QT_NO_GETADDRINFO) // Call getaddrinfo, and place all IPv4 addresses at the start and // the IPv6 addresses at the end of the address list in results. addrinfo *res = 0; struct addrinfo hints; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; #ifdef Q_ADDRCONFIG hints.ai_flags = Q_ADDRCONFIG; #endif int result = getaddrinfo(aceHostname.constData(), 0, &hints, &res); # ifdef Q_ADDRCONFIG if (result == EAI_BADFLAGS) { // if the lookup failed with AI_ADDRCONFIG set, try again without it hints.ai_flags = 0; result = getaddrinfo(aceHostname.constData(), 0, &hints, &res); } # endif if (result == 0) { addrinfo *node = res; QList<QHostAddress> addresses; while (node) { #ifdef QHOSTINFO_DEBUG qDebug() << "getaddrinfo node: flags:" << node->ai_flags << "family:" << node->ai_family << "ai_socktype:" << node->ai_socktype << "ai_protocol:" << node->ai_protocol << "ai_addrlen:" << node->ai_addrlen; #endif if (node->ai_family == AF_INET) { QHostAddress addr; addr.setAddress(ntohl(((sockaddr_in *) node->ai_addr)->sin_addr.s_addr)); if (!addresses.contains(addr)) addresses.append(addr); } #ifndef QT_NO_IPV6 else if (node->ai_family == AF_INET6) { QHostAddress addr; sockaddr_in6 *sa6 = (sockaddr_in6 *) node->ai_addr; addr.setAddress(sa6->sin6_addr.s6_addr); if (sa6->sin6_scope_id) addr.setScopeId(QString::number(sa6->sin6_scope_id)); if (!addresses.contains(addr)) addresses.append(addr); } #endif node = node->ai_next; } if (addresses.isEmpty() && node == 0) { // Reached the end of the list, but no addresses were found; this // means the list contains one or more unknown address types. results.setError(QHostInfo::UnknownError); results.setErrorString(tr("Unknown address type")); } results.setAddresses(addresses); freeaddrinfo(res); } else if (result == EAI_NONAME || result == EAI_FAIL #ifdef EAI_NODATA // EAI_NODATA is deprecated in RFC 3493 || result == EAI_NODATA #endif ) { results.setError(QHostInfo::HostNotFound); results.setErrorString(tr("Host not found")); } else { results.setError(QHostInfo::UnknownError); results.setErrorString(QString::fromLocal8Bit(gai_strerror(result))); } #else // Fall back to gethostbyname for platforms that don't define // getaddrinfo. gethostbyname does not support IPv6, and it's not // reentrant on all platforms. For now this is okay since we only // use one QHostInfoAgent, but if more agents are introduced, locking // must be provided. QMutexLocker locker(::getHostByNameMutex()); hostent *result = gethostbyname(aceHostname.constData()); if (result) { if (result->h_addrtype == AF_INET) { QList<QHostAddress> addresses; for (char **p = result->h_addr_list; *p != 0; p++) { QHostAddress addr; addr.setAddress(ntohl(*((quint32 *)*p))); if (!addresses.contains(addr)) addresses.prepend(addr); } results.setAddresses(addresses); } else { results.setError(QHostInfo::UnknownError); results.setErrorString(tr("Unknown address type")); } #if !defined(Q_OS_VXWORKS) } else if (h_errno == HOST_NOT_FOUND || h_errno == NO_DATA || h_errno == NO_ADDRESS) { results.setError(QHostInfo::HostNotFound); results.setErrorString(tr("Host not found")); #endif } else { results.setError(QHostInfo::UnknownError); results.setErrorString(tr("Unknown error")); } #endif // !defined (QT_NO_GETADDRINFO) #if defined(QHOSTINFO_DEBUG) if (results.error() != QHostInfo::NoError) { qDebug("QHostInfoAgent::fromName(): error #%d %s", h_errno, results.errorString().toLatin1().constData()); } else { QString tmp; QList<QHostAddress> addresses = results.addresses(); for (int i = 0; i < addresses.count(); ++i) { if (i != 0) tmp += ", "; tmp += addresses.at(i).toString(); } qDebug("QHostInfoAgent::fromName(): found %i entries for \"%s\": {%s}", addresses.count(), hostName.toLatin1().constData(), tmp.toLatin1().constData()); } #endif return results; }
/*! Assigns a name to an unnamed socket. The name is the host address \a address and the port number \a port. If the operation succeeds, bind() returns true; otherwise it returns false without changing what port() and address() return. bind() is used by servers for setting up incoming connections. Call bind() before listen(). */ bool MSocketDevice::bind( const QHostAddress &address, quint16 port ) { if ( !isValid() ) return false; int r; struct sockaddr_in a4; #if !defined(QT_NO_IPV6) struct sockaddr_in6 a6; if ( address.protocol() == QAbstractSocket::IPv6Protocol ) { memset( &a6, 0, sizeof(a6) ); a6.sin6_family = AF_INET6; a6.sin6_port = htons( port ); Q_IPV6ADDR tmp = address.toIPv6Address(); memcpy( &a6.sin6_addr.s6_addr, &tmp, sizeof(tmp) ); r = QT_SOCKET_BIND( fd, (struct sockaddr *)&a6, sizeof(a6) ); } else #endif if ( address.protocol() == QAbstractSocket::IPv4Protocol ) { memset( &a4, 0, sizeof(a4) ); a4.sin_family = AF_INET; a4.sin_port = htons( port ); a4.sin_addr.s_addr = htonl( address.toIPv4Address() ); r = QT_SOCKET_BIND( fd, (struct sockaddr*)&a4, sizeof(a4) ); } else { e = Impossible; return false; } if ( r < 0 ) { switch( errno ) { case EINVAL: e = AlreadyBound; break; case EACCES: e = Inaccessible; break; case ENOMEM: e = NoResources; break; case EFAULT: // a was illegal case ENAMETOOLONG: // sz was wrong e = InternalError; break; case EBADF: // AF_UNIX only case ENOTSOCK: // AF_UNIX only case EROFS: // AF_UNIX only case ENOENT: // AF_UNIX only case ENOTDIR: // AF_UNIX only case ELOOP: // AF_UNIX only e = Impossible; break; default: e = UnknownError; break; } return false; } fetchConnectionParameters(); return true; }
/*! \overload Writes \a len bytes to the socket from \a data and returns the number of bytes written. Returns -1 if an error occurred. This is used for MSocketDevice::Datagram sockets. You must specify the \a host and \a port of the destination of the data. */ qint64 MSocketDevice::writeBlock( const char * data, quint64 len, const QHostAddress & host, quint16 port ) { if ( len == 0 ) return 0; if ( t != Datagram ) { VERBOSE(VB_SOCKET|VB_EXTRA, "MSocketDevice::sendBlock: Not datagram"); return -1; // for now - later we can do t/tcp } if ( data == 0 ) { VERBOSE(VB_SOCKET|VB_EXTRA, "MSocketDevice::sendBlock: Null pointer error"); return -1; } if ( !isValid() ) { VERBOSE(VB_SOCKET|VB_EXTRA, "MSocketDevice::sendBlock: Invalid socket"); return -1; } if ( !isOpen() ) { VERBOSE(VB_SOCKET|VB_EXTRA, "MSocketDevice::sendBlock: Device is not open"); return -1; } if ( !isWritable() ) { VERBOSE(VB_SOCKET|VB_EXTRA, "MSocketDevice::sendBlock: Write operation not permitted"); return -1; } struct sockaddr_in a4; struct sockaddr *aa; QT_SOCKLEN_T slen; #if !defined(QT_NO_IPV6) struct sockaddr_in6 a6; if ( host.protocol() == QAbstractSocket::IPv6Protocol ) { memset( &a6, 0, sizeof(a6) ); a6.sin6_family = AF_INET6; a6.sin6_port = htons( port ); Q_IPV6ADDR tmp = host.toIPv6Address(); memcpy( &a6.sin6_addr.s6_addr, &tmp, sizeof(tmp) ); slen = sizeof( a6 ); aa = (struct sockaddr *)&a6; } else #endif if ( host.protocol() == QAbstractSocket::IPv4Protocol ) { memset( &a4, 0, sizeof(a4) ); a4.sin_family = AF_INET; a4.sin_port = htons( port ); a4.sin_addr.s_addr = htonl( host.toIPv4Address() ); slen = sizeof(a4); aa = (struct sockaddr *)&a4; } else { e = Impossible; return -1; } // we'd use MSG_DONTWAIT + MSG_NOSIGNAL if Stevens were right. // but apparently Stevens and most implementors disagree bool done = false; int r = 0; while ( !done ) { r = ::sendto( fd, data, len, 0, aa, slen); done = true; if ( r < 0 && e == NoError && errno != EAGAIN && errno != EWOULDBLOCK ) { switch( errno ) { case EINTR: // signal - call read() or whatever again done = false; break; case ENOSPC: case EPIPE: case EIO: case EISDIR: case EBADF: case EINVAL: case EFAULT: case ENOTCONN: case ENOTSOCK: e = Impossible; break; #if defined(ENONET) case ENONET: #endif case EHOSTUNREACH: case ENETDOWN: case ENETUNREACH: case ETIMEDOUT: e = NetworkFailure; break; default: e = UnknownError; break; } } } return r; }
QHostInfo QHostInfoAgent::fromName(const QString &hostName) { QHostInfo results; #if defined(QHOSTINFO_DEBUG) qDebug("QHostInfoAgent::fromName(%s) looking up...", hostName.toLatin1().constData()); #endif // Load res_init on demand. resolveLibrary(); // If res_init is available, poll it. if (local_res_init) local_res_init(); QHostAddress address; if (address.setAddress(hostName)) { // Reverse lookup sockaddr_in sa4; sockaddr_in6 sa6; sockaddr *sa = 0; QT_SOCKLEN_T saSize = 0; if (address.protocol() == QAbstractSocket::IPv4Protocol) { sa = (sockaddr *)&sa4; saSize = sizeof(sa4); memset(&sa4, 0, sizeof(sa4)); sa4.sin_family = AF_INET; sa4.sin_addr.s_addr = htonl(address.toIPv4Address()); } else { sa = (sockaddr *)&sa6; saSize = sizeof(sa6); memset(&sa6, 0, sizeof(sa6)); sa6.sin6_family = AF_INET6; memcpy(sa6.sin6_addr.s6_addr, address.toIPv6Address().c, sizeof(sa6.sin6_addr.s6_addr)); } char hbuf[NI_MAXHOST]; if (sa && getnameinfo(sa, saSize, hbuf, sizeof(hbuf), 0, 0, 0) == 0) results.setHostName(QString::fromLatin1(hbuf)); if (results.hostName().isEmpty()) results.setHostName(address.toString()); results.setAddresses(QList<QHostAddress>() << address); return results; } // IDN support QByteArray aceHostname = QUrl::toAce(hostName); results.setHostName(hostName); if (aceHostname.isEmpty()) { results.setError(QHostInfo::HostNotFound); results.setErrorString(hostName.isEmpty() ? QCoreApplication::translate("QHostInfoAgent", "No host name given") : QCoreApplication::translate("QHostInfoAgent", "Invalid hostname")); return results; } // Call getaddrinfo, and place all IPv4 addresses at the start and // the IPv6 addresses at the end of the address list in results. addrinfo *res = 0; struct addrinfo hints; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; #ifdef Q_ADDRCONFIG hints.ai_flags = Q_ADDRCONFIG; #endif int result = getaddrinfo(aceHostname.constData(), 0, &hints, &res); # ifdef Q_ADDRCONFIG if (result == EAI_BADFLAGS) { // if the lookup failed with AI_ADDRCONFIG set, try again without it hints.ai_flags = 0; result = getaddrinfo(aceHostname.constData(), 0, &hints, &res); } # endif if (result == 0) { addrinfo *node = res; QList<QHostAddress> addresses; while (node) { #ifdef QHOSTINFO_DEBUG qDebug() << "getaddrinfo node: flags:" << node->ai_flags << "family:" << node->ai_family << "ai_socktype:" << node->ai_socktype << "ai_protocol:" << node->ai_protocol << "ai_addrlen:" << node->ai_addrlen; #endif if (node->ai_family == AF_INET) { QHostAddress addr; addr.setAddress(ntohl(((sockaddr_in *) node->ai_addr)->sin_addr.s_addr)); if (!addresses.contains(addr)) addresses.append(addr); } else if (node->ai_family == AF_INET6) { QHostAddress addr; sockaddr_in6 *sa6 = (sockaddr_in6 *) node->ai_addr; addr.setAddress(sa6->sin6_addr.s6_addr); if (sa6->sin6_scope_id) addr.setScopeId(QString::number(sa6->sin6_scope_id)); if (!addresses.contains(addr)) addresses.append(addr); } node = node->ai_next; } if (addresses.isEmpty() && node == 0) { // Reached the end of the list, but no addresses were found; this // means the list contains one or more unknown address types. results.setError(QHostInfo::UnknownError); results.setErrorString(tr("Unknown address type")); } results.setAddresses(addresses); freeaddrinfo(res); } else if (result == EAI_NONAME || result == EAI_FAIL #ifdef EAI_NODATA // EAI_NODATA is deprecated in RFC 3493 || result == EAI_NODATA #endif ) { results.setError(QHostInfo::HostNotFound); results.setErrorString(tr("Host not found")); } else { results.setError(QHostInfo::UnknownError); results.setErrorString(QString::fromLocal8Bit(gai_strerror(result))); } #if defined(QHOSTINFO_DEBUG) if (results.error() != QHostInfo::NoError) { qDebug("QHostInfoAgent::fromName(): error #%d %s", h_errno, results.errorString().toLatin1().constData()); } else { QString tmp; QList<QHostAddress> addresses = results.addresses(); for (int i = 0; i < addresses.count(); ++i) { if (i != 0) tmp += ", "; tmp += addresses.at(i).toString(); } qDebug("QHostInfoAgent::fromName(): found %i entries for \"%s\": {%s}", addresses.count(), hostName.toLatin1().constData(), tmp.toLatin1().constData()); } #endif return results; }
/*! Connects to the IP address and port specified by \a addr and \a port. Returns true if it establishes a connection; otherwise returns false. If it returns false, error() explains why. Note that error() commonly returns NoError for non-blocking sockets; this just means that you can call connect() again in a little while and it'll probably succeed. */ bool MSocketDevice::connect( const QHostAddress &addr, quint16 port ) { if ( !isValid() ) { #if !defined(QT_NO_IPV6) if ( addr.protocol() == QAbstractSocket::IPv6Protocol ) { setProtocol(IPv6); VERBOSE(VB_SOCKET, "MSocketDevice::connect: setting Protocol to IPv6"); } else #endif if ( addr.protocol() == QAbstractSocket::IPv4Protocol ) { setProtocol(IPv4); VERBOSE(VB_SOCKET, "MSocketDevice::connect: setting Protocol to IPv4"); } VERBOSE(VB_SOCKET, "MSocketDevice::connect: attempting to create new socket"); MSocketDevice::setSocket( createNewSocket(), t); // If still not valid, give up. if ( !isValid() ) return false; } pa = addr; pp = port; struct sockaddr_in a4; struct sockaddr *aa; QT_SOCKLEN_T aalen; #if !defined(QT_NO_IPV6) struct sockaddr_in6 a6; if ( addr.protocol() == QAbstractSocket::IPv6Protocol ) { memset( &a6, 0, sizeof(a6) ); a6.sin6_family = AF_INET6; a6.sin6_port = htons( port ); Q_IPV6ADDR ip6 = addr.toIPv6Address(); memcpy( &a6.sin6_addr.s6_addr, &ip6, sizeof(ip6) ); aalen = sizeof( a6 ); aa = (struct sockaddr *)&a6; } else #endif if ( addr.protocol() == QAbstractSocket::IPv4Protocol ) { memset( &a4, 0, sizeof(a4) ); a4.sin_family = AF_INET; a4.sin_port = htons( port ); a4.sin_addr.s_addr = htonl( addr.toIPv4Address() ); aalen = sizeof(a4); aa = (struct sockaddr *)&a4; } else { e = Impossible; return false; } int r = QT_SOCKET_CONNECT( fd, aa, aalen ); if ( r == 0 ) { fetchConnectionParameters(); return true; } if ( errno == EISCONN || errno == EALREADY || errno == EINPROGRESS ) { fetchConnectionParameters(); return true; } if ( e != NoError || errno == EAGAIN || errno == EWOULDBLOCK ) { return false; } switch( errno ) { case EBADF: case ENOTSOCK: e = Impossible; break; case EFAULT: case EAFNOSUPPORT: e = InternalError; break; case ECONNREFUSED: e = ConnectionRefused; break; case ETIMEDOUT: case ENETUNREACH: e = NetworkFailure; break; case EADDRINUSE: e = NoResources; break; case EACCES: case EPERM: e = Inaccessible; break; default: e = UnknownError; break; } return false; }
bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16 port) { struct sockaddr_in sockAddrIPv4; struct sockaddr *sockAddrPtr = 0; QT_SOCKLEN_T sockAddrSize = 0; #if !defined(QT_NO_IPV6) struct sockaddr_in6 sockAddrIPv6; if (addr.protocol() == QAbstractSocket::IPv6Protocol) { memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6)); sockAddrIPv6.sin6_family = AF_INET6; sockAddrIPv6.sin6_port = htons(port); #ifndef QT_NO_IPV6IFNAME sockAddrIPv6.sin6_scope_id = ::if_nametoindex(addr.scopeId().toLatin1().data()); #else sockAddrIPv6.sin6_scope_id = addr.scopeId().toInt(); #endif Q_IPV6ADDR ip6 = addr.toIPv6Address(); memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &ip6, sizeof(ip6)); sockAddrSize = sizeof(sockAddrIPv6); sockAddrPtr = (struct sockaddr *) &sockAddrIPv6; } else #if 0 {} #endif #endif if (addr.protocol() == QAbstractSocket::IPv4Protocol) { memset(&sockAddrIPv4, 0, sizeof(sockAddrIPv4)); sockAddrIPv4.sin_family = AF_INET; sockAddrIPv4.sin_port = htons(port); sockAddrIPv4.sin_addr.s_addr = htonl(addr.toIPv4Address()); sockAddrSize = sizeof(sockAddrIPv4); sockAddrPtr = (struct sockaddr *) &sockAddrIPv4; } else { // unreachable } int connectResult = QT_SOCKET_CONNECT(socketDescriptor, sockAddrPtr, sockAddrSize); if (connectResult == -1) { switch (errno) { case EISCONN: socketState = QAbstractSocket::ConnectedState; break; case ECONNREFUSED: case EINVAL: setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString); socketState = QAbstractSocket::UnconnectedState; break; case ETIMEDOUT: setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString); break; case EHOSTUNREACH: setError(QAbstractSocket::NetworkError, HostUnreachableErrorString); socketState = QAbstractSocket::UnconnectedState; break; case ENETUNREACH: setError(QAbstractSocket::NetworkError, NetworkUnreachableErrorString); socketState = QAbstractSocket::UnconnectedState; break; case EADDRINUSE: setError(QAbstractSocket::NetworkError, AddressInuseErrorString); break; case EINPROGRESS: case EALREADY: setError(QAbstractSocket::UnfinishedSocketOperationError, InvalidSocketErrorString); socketState = QAbstractSocket::ConnectingState; break; case EAGAIN: setError(QAbstractSocket::UnfinishedSocketOperationError, InvalidSocketErrorString); setError(QAbstractSocket::SocketResourceError, ResourceErrorString); break; case EACCES: case EPERM: setError(QAbstractSocket::SocketAccessError, AccessErrorString); socketState = QAbstractSocket::UnconnectedState; break; case EAFNOSUPPORT: case EBADF: case EFAULT: case ENOTSOCK: socketState = QAbstractSocket::UnconnectedState; default: break; } if (socketState != QAbstractSocket::ConnectedState) { #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QNativeSocketEnginePrivate::nativeConnect(%s, %i) == false (%s)", addr.toString().toLatin1().constData(), port, socketState == QAbstractSocket::ConnectingState ? "Connection in progress" : socketErrorString.toLatin1().constData()); #endif return false; } } #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QNativeSocketEnginePrivate::nativeConnect(%s, %i) == true", addr.toString().toLatin1().constData(), port); #endif socketState = QAbstractSocket::ConnectedState; return true; }
bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16 port) { struct sockaddr_in sockAddrIPv4; struct sockaddr *sockAddrPtr = 0; QT_SOCKLEN_T sockAddrSize = 0; #if !defined(QT_NO_IPV6) struct sockaddr_in6 sockAddrIPv6; if (address.protocol() == QAbstractSocket::IPv6Protocol) { memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6)); sockAddrIPv6.sin6_family = AF_INET6; sockAddrIPv6.sin6_port = htons(port); #ifndef QT_NO_IPV6IFNAME sockAddrIPv6.sin6_scope_id = ::if_nametoindex(address.scopeId().toLatin1().data()); #else sockAddrIPv6.sin6_scope_id = address.scopeId().toInt(); #endif Q_IPV6ADDR tmp = address.toIPv6Address(); memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &tmp, sizeof(tmp)); sockAddrSize = sizeof(sockAddrIPv6); sockAddrPtr = (struct sockaddr *) &sockAddrIPv6; } else #endif if (address.protocol() == QAbstractSocket::IPv4Protocol) { memset(&sockAddrIPv4, 0, sizeof(sockAddrIPv4)); sockAddrIPv4.sin_family = AF_INET; sockAddrIPv4.sin_port = htons(port); sockAddrIPv4.sin_addr.s_addr = htonl(address.toIPv4Address()); sockAddrSize = sizeof(sockAddrIPv4); sockAddrPtr = (struct sockaddr *) &sockAddrIPv4; } else { // unreachable } int bindResult = QT_SOCKET_BIND(socketDescriptor, sockAddrPtr, sockAddrSize); if (bindResult < 0) { switch(errno) { case EADDRINUSE: setError(QAbstractSocket::AddressInUseError, AddressInuseErrorString); break; case EACCES: setError(QAbstractSocket::SocketAccessError, AddressProtectedErrorString); break; case EINVAL: setError(QAbstractSocket::UnsupportedSocketOperationError, OperationUnsupportedErrorString); break; case EADDRNOTAVAIL: setError(QAbstractSocket::SocketAddressNotAvailableError, AddressNotAvailableErrorString); break; default: break; } #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QNativeSocketEnginePrivate::nativeBind(%s, %i) == false (%s)", address.toString().toLatin1().constData(), port, socketErrorString.toLatin1().constData()); #endif return false; } #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QNativeSocketEnginePrivate::nativeBind(%s, %i) == true", address.toString().toLatin1().constData(), port); #endif socketState = QAbstractSocket::BoundState; return true; }
static bool multicastMembershipHelper(QNativeSocketEnginePrivate *d, int how6, int how4, const QHostAddress &groupAddress, const QNetworkInterface &interface) { int level = 0; int sockOpt = 0; void *sockArg; int sockArgSize; ip_mreq mreq4; ipv6_mreq mreq6; if (groupAddress.protocol() == QAbstractSocket::IPv6Protocol) { level = IPPROTO_IPV6; sockOpt = how6; sockArg = &mreq6; sockArgSize = sizeof(mreq6); memset(&mreq6, 0, sizeof(mreq6)); Q_IPV6ADDR ip6 = groupAddress.toIPv6Address(); memcpy(&mreq6.ipv6mr_multiaddr, &ip6, sizeof(ip6)); mreq6.ipv6mr_interface = interface.index(); } else if (groupAddress.protocol() == QAbstractSocket::IPv4Protocol) { level = IPPROTO_IP; sockOpt = how4; sockArg = &mreq4; sockArgSize = sizeof(mreq4); memset(&mreq4, 0, sizeof(mreq4)); mreq4.imr_multiaddr.s_addr = htonl(groupAddress.toIPv4Address()); if (interface.isValid()) { QList<QNetworkAddressEntry> addressEntries = interface.addressEntries(); if (!addressEntries.isEmpty()) { QHostAddress firstIP = addressEntries.first().ip(); mreq4.imr_interface.s_addr = htonl(firstIP.toIPv4Address()); } else { d->setError(QAbstractSocket::NetworkError, QNativeSocketEnginePrivate::NetworkUnreachableErrorString); return false; } } else { mreq4.imr_interface.s_addr = INADDR_ANY; } } else { // unreachable d->setError(QAbstractSocket::UnsupportedSocketOperationError, QNativeSocketEnginePrivate::ProtocolUnsupportedErrorString); return false; } int res = setsockopt(d->socketDescriptor, level, sockOpt, sockArg, sockArgSize); if (res == -1) { switch (errno) { case ENOPROTOOPT: d->setError(QAbstractSocket::UnsupportedSocketOperationError, QNativeSocketEnginePrivate::OperationUnsupportedErrorString); break; case EADDRNOTAVAIL: d->setError(QAbstractSocket::SocketAddressNotAvailableError, QNativeSocketEnginePrivate::AddressNotAvailableErrorString); break; default: d->setError(QAbstractSocket::UnknownSocketError, QNativeSocketEnginePrivate::UnknownSocketErrorString); break; } return false; } return true; }
bool Q3SocketDevice::connect( const QHostAddress &addr, quint16 port ) { if ( !isValid() ) return false; pa = addr; pp = port; struct sockaddr_in a4; struct sockaddr *aa; SOCKLEN_T aalen; #if !defined(QT_NO_IPV6) qt_sockaddr_in6 a6; if ( initialized >= 0x20 && addr.isIPv6Address() ) { memset(&a6, 0, sizeof(a6)); a6.sin6_family = AF_INET6; a6.sin6_port = htons( port ); Q_IPV6ADDR ip6 = addr.toIPv6Address(); memcpy( &a6.sin6_addr.qt_s6_addr, &ip6, sizeof(ip6) ); aalen = sizeof( a6 ); aa = (struct sockaddr *)&a6; } else #endif if ( addr.isIPv4Address() ) { memset(&a4, 0, sizeof(a4)); a4.sin_family = AF_INET; a4.sin_port = htons(port); a4.sin_addr.s_addr = htonl(addr.toIPv4Address()); aalen = sizeof(a4); aa = (struct sockaddr *)&a4; } else { e = Impossible; return false; } int r = ::connect( fd, aa, aalen ); if ( r == SOCKET_ERROR ) { switch( WSAGetLastError() ) { case WSANOTINITIALISED: e = Impossible; break; case WSAENETDOWN: e = NetworkFailure; break; case WSAEADDRINUSE: case WSAEINPROGRESS: case WSAENOBUFS: e = NoResources; break; case WSAEINTR: e = UnknownError; // ### ? break; case WSAEALREADY: // ### ? break; case WSAEADDRNOTAVAIL: e = ConnectionRefused; // ### ? break; case WSAEAFNOSUPPORT: case WSAEFAULT: e = InternalError; break; case WSAEINVAL: break; case WSAECONNREFUSED: e = ConnectionRefused; break; case WSAEISCONN: goto successful; case WSAENETUNREACH: case WSAETIMEDOUT: e = NetworkFailure; break; case WSAENOTSOCK: e = Impossible; break; case WSAEWOULDBLOCK: break; case WSAEACCES: e = Inaccessible; break; case 10107: // Workaround for a problem with the WinSock Proxy Server. See // also support/arc-12/25557 for details on the problem. goto successful; default: e = UnknownError; break; } return false; } successful: fetchConnectionParameters(); return true; }
QHostInfo QHostInfoAgent::fromName(const QString &hostName) { QHostInfo results; results.setHostName(hostName); #if defined(QHOSTINFO_DEBUG) qDebug("QHostInfoAgent::fromName(%s) looking up...", hostName.toLatin1().constData()); #endif QHostAddress address; if (address.setAddress(hostName)) { // Reverse lookup // Reverse lookups using getnameinfo are broken on darwin, use gethostbyaddr instead. #if !defined (QT_NO_GETADDRINFO) && !defined (Q_OS_DARWIN) sockaddr_in sa4; sockaddr_in6 sa6; sockaddr *sa; QT_SOCKLEN_T saSize; if (address.protocol() == QAbstractSocket::IPv4Protocol) { sa = (sockaddr *)&sa4; saSize = sizeof(sa4); memset(&sa4, 0, sizeof(sa4)); sa4.sin_family = AF_INET; sa4.sin_addr.s_addr = htonl(address.toIPv4Address()); } else { sa = (sockaddr *)&sa6; saSize = sizeof(sa6); memset(&sa6, 0, sizeof(sa6)); sa6.sin6_family = AF_INET6; memcpy(sa6.sin6_addr.s6_addr, address.toIPv6Address().c, sizeof(sa6.sin6_addr.s6_addr)); } char hbuf[NI_MAXHOST]; if (getnameinfo(sa, saSize, hbuf, sizeof(hbuf), 0, 0, 0) != 0) { results.setError(QHostInfo::HostNotFound); results.setErrorString(tr("Host not found")); return results; } results.setHostName(QString::fromLatin1(hbuf)); #else in_addr_t inetaddr = inet_addr(hostName.toLatin1().constData()); struct hostent *ent = gethostbyaddr((const char *)&inetaddr, sizeof(inetaddr), AF_INET); if (!ent) { results.setError(QHostInfo::HostNotFound); results.setErrorString(tr("Host not found")); return results; } results.setHostName(QString::fromLatin1(ent->h_name)); #endif } #if !defined (QT_NO_GETADDRINFO) // Call getaddrinfo, and place all IPv4 addresses at the start and // the IPv6 addresses at the end of the address list in results. addrinfo *res = 0; struct addrinfo hints; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; int result = getaddrinfo(hostName.toLatin1().constData(), 0, &hints, &res); if (result == 0) { addrinfo *node = res; QList<QHostAddress> addresses; while (node) { if (node->ai_family == AF_INET) { QHostAddress addr; addr.setAddress(ntohl(((sockaddr_in *) node->ai_addr)->sin_addr.s_addr)); if (!addresses.contains(addr)) addresses.prepend(addr); } else if (node->ai_family == AF_INET6) { QHostAddress addr; addr.setAddress(((sockaddr_in6 *) node->ai_addr)->sin6_addr.s6_addr); if (!addresses.contains(addr)) addresses.append(addr); } else { results.setError(QHostInfo::UnknownError); results.setErrorString(tr("Unknown address type")); break; } node = node->ai_next; } results.setAddresses(addresses); freeaddrinfo(res); } else if (result == EAI_NONAME || result == EAI_FAIL || result == EAI_FAIL #ifdef EAI_NODATA // EAI_NODATA is deprecated in RFC 3493 || result == EAI_NODATA #endif ) { results.setError(QHostInfo::HostNotFound); results.setErrorString(tr("Host not found")); } else { results.setError(QHostInfo::UnknownError); results.setErrorString(QString::fromLocal8Bit(gai_strerror(result))); } #else // Fall back to gethostbyname for platforms that don't define // getaddrinfo. gethostbyname does not support IPv6, and it's not // reentrant on all platforms. For now this is okay since we only // use one QHostInfoAgent, but if more agents are introduced, locking // must be provided. QMutexLocker locker(::getHostByNameMutex()); hostent *result = gethostbyname(hostName.toLatin1().constData()); if (result) { if (result->h_addrtype == AF_INET) { QList<QHostAddress> addresses; for (char **p = result->h_addr_list; *p != 0; p++) { QHostAddress addr; addr.setAddress(ntohl(*((quint32 *)*p))); if (!addresses.contains(addr)) addresses.prepend(addr); } results.setAddresses(addresses); } else { results.setError(QHostInfo::UnknownError); results.setErrorString(tr("Unknown address type")); } } else if (h_errno == HOST_NOT_FOUND || h_errno == NO_DATA || h_errno == NO_ADDRESS) { results.setError(QHostInfo::HostNotFound); results.setErrorString(tr("Host not found")); } else { results.setError(QHostInfo::UnknownError); results.setErrorString(tr("Unknown error")); } #endif // !defined (QT_NO_GETADDRINFO) #if defined(QHOSTINFO_DEBUG) if (results.error() != QHostInfo::NoError) { qDebug("QHostInfoAgent::fromName(): error #%d %s", h_errno, results.errorString().toLatin1().constData()); } else { QString tmp; QList<QHostAddress> addresses = results.addresses(); for (int i = 0; i < addresses.count(); ++i) { if (i != 0) tmp += ", "; tmp += addresses.at(i).toString(); } qDebug("QHostInfoAgent::fromName(): found %i entries for \"%s\": {%s}", addresses.count(), hostName.toLatin1().constData(), tmp.toLatin1().constData()); } #endif return results; }
bool Q3SocketDevice::bind( const QHostAddress &address, quint16 port ) { if ( !isValid() ) return false; int r; struct sockaddr_in a4; #if !defined(QT_NO_IPV6) qt_sockaddr_in6 a6; if ( initialized >= 0x20 && address.isIPv6Address() ) { memset( &a6, 0, sizeof(a6) ); a6.sin6_family = AF_INET6; a6.sin6_port = htons( port ); Q_IPV6ADDR tmp = address.toIPv6Address(); memcpy( &a6.sin6_addr.qt_s6_addr, &tmp, sizeof(tmp) ); r = ::bind( fd, (struct sockaddr *)&a6, sizeof(struct qt_sockaddr_storage) ); } else #endif if ( address.isIPv4Address() ) { memset( &a4, 0, sizeof(a4) ); a4.sin_family = AF_INET; a4.sin_port = htons( port ); a4.sin_addr.s_addr = htonl( address.toIPv4Address() ); r = ::bind( fd, (struct sockaddr*)&a4, sizeof(struct sockaddr_in) ); } else { e = Impossible; return false; } if ( r == SOCKET_ERROR ) { switch( WSAGetLastError() ) { case WSANOTINITIALISED: e = Impossible; break; case WSAENETDOWN: e = NetworkFailure; break; case WSAEACCES: e = Inaccessible; break; case WSAEADDRNOTAVAIL: e = Inaccessible; break; case WSAEFAULT: e = InternalError; break; case WSAEINPROGRESS: case WSAENOBUFS: e = NoResources; break; case WSAEADDRINUSE: case WSAEINVAL: e = AlreadyBound; break; case WSAENOTSOCK: e = Impossible; break; default: e = UnknownError; break; } return false; } fetchConnectionParameters(); return true; }
Q_LONG Q3SocketDevice::writeBlock( const char * data, Q_ULONG len, const QHostAddress & host, quint16 port ) { if ( t != Datagram ) { #if defined(QT_CHECK_STATE) || defined(QSOCKETDEVICE_DEBUG) qWarning( "Q3SocketDevice::sendBlock: Not datagram" ); #endif return -1; // for now - later we can do t/tcp } if ( data == 0 && len != 0 ) { #if defined(QT_CHECK_NULL) || defined(QSOCKETDEVICE_DEBUG) qWarning( "Q3SocketDevice::sendBlock: Null pointer error" ); #endif return -1; } if ( !isValid() ) { #if defined(QT_CHECK_STATE) || defined(QSOCKETDEVICE_DEBUG) qWarning( "Q3SocketDevice::sendBlock: Invalid socket" ); #endif return -1; } if ( !isOpen() ) { #if defined(QT_CHECK_STATE) || defined(QSOCKETDEVICE_DEBUG) qWarning( "Q3SocketDevice::sendBlock: Device is not open" ); #endif return -1; } if ( !isWritable() ) { #if defined(QT_CHECK_STATE) || defined(QSOCKETDEVICE_DEBUG) qWarning( "Q3SocketDevice::sendBlock: Write operation not permitted" ); #endif return -1; } struct sockaddr_in a4; struct sockaddr *aa; SOCKLEN_T slen; #if !defined(QT_NO_IPV6) qt_sockaddr_in6 a6; if ( initialized >= 0x20 && host.isIPv6Address() ) { memset( &a6, 0, sizeof(a6) ); a6.sin6_family = AF_INET6; a6.sin6_port = htons( port ); Q_IPV6ADDR tmp = host.toIPv6Address(); memcpy( &a6.sin6_addr.qt_s6_addr, &tmp, sizeof(tmp) ); slen = sizeof( a6 ); aa = (struct sockaddr *)&a6; } else #endif if ( host.isIPv4Address() ) { memset( &a4, 0, sizeof(a4) ); a4.sin_family = AF_INET; a4.sin_port = htons( port ); a4.sin_addr.s_addr = htonl( host.toIPv4Address() ); slen = sizeof(a4); aa = (struct sockaddr *)&a4; } else { e = Impossible; return -1; } // we'd use MSG_DONTWAIT + MSG_NOSIGNAL if Stevens were right. // but apparently Stevens and most implementors disagree bool done = false; qint64 r = 0; while ( !done ) { r = ::sendto( fd, data, len, 0, aa, slen ); done = true; if ( r == SOCKET_ERROR && e == NoError ) {//&& e != EAGAIN ) { switch( WSAGetLastError() ) { case WSANOTINITIALISED: e = Impossible; break; case WSAENETDOWN: case WSAEACCES: case WSAENETRESET: case WSAESHUTDOWN: case WSAEHOSTUNREACH: case WSAECONNABORTED: case WSAECONNRESET: case WSAEADDRNOTAVAIL: case WSAENETUNREACH: case WSAETIMEDOUT: e = NetworkFailure; break; case WSAEINTR: done = false; break; case WSAEINPROGRESS: e = NoResources; // ### perhaps try it later? break; case WSAEFAULT: case WSAEOPNOTSUPP: case WSAEAFNOSUPPORT: e = InternalError; break; case WSAENOBUFS: case WSAEMSGSIZE: e = NoResources; break; case WSAENOTCONN: case WSAENOTSOCK: case WSAEINVAL: case WSAEDESTADDRREQ: e = Impossible; break; case WSAEWOULDBLOCK: r = 0; break; default: e = UnknownError; break; } } } return r; }
bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &a, quint16 port) { QHostAddress address = a; switch (address.protocol()) { case QAbstractSocket::IPv6Protocol: if (address.toIPv6Address()[0] == 0xff) { // binding to a multicast address address = QHostAddress(QHostAddress::AnyIPv6); } break; case QAbstractSocket::IPv4Protocol: if ((address.toIPv4Address() & 0xffff0000) == 0xefff0000) { // binding to a multicast address address = QHostAddress(QHostAddress::Any); } break; default: break; } struct sockaddr_in sockAddrIPv4; qt_sockaddr_in6 sockAddrIPv6; struct sockaddr *sockAddrPtr = 0; QT_SOCKLEN_T sockAddrSize = 0; qt_socket_setPortAndAddress(socketDescriptor, &sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize); int bindResult = ::bind(socketDescriptor, sockAddrPtr, sockAddrSize); if (bindResult == SOCKET_ERROR) { int err = WSAGetLastError(); WS_ERROR_DEBUG(err); switch (err) { case WSANOTINITIALISED: //### break; case WSAEADDRINUSE: case WSAEINVAL: setError(QAbstractSocket::AddressInUseError, AddressInuseErrorString); break; case WSAEACCES: setError(QAbstractSocket::SocketAccessError, AddressProtectedErrorString); break; case WSAEADDRNOTAVAIL: setError(QAbstractSocket::SocketAddressNotAvailableError, AddressNotAvailableErrorString); break; default: break; } #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QNativeSocketEnginePrivate::nativeBind(%s, %i) == false (%s)", address.toString().toLatin1().constData(), port, socketErrorString.toLatin1().constData()); #endif return false; } #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QNativeSocketEnginePrivate::nativeBind(%s, %i) == true", address.toString().toLatin1().constData(), port); #endif socketState = QAbstractSocket::BoundState; return true; }
bool Q3SocketDevice::connect( const QHostAddress &addr, Q_UINT16 port ) { if ( !isValid() ) return false; pa = addr; pp = port; struct sockaddr_in a4; struct sockaddr *aa; QT_SOCKLEN_T aalen; #if !defined(QT_NO_IPV6) struct sockaddr_in6 a6; if ( addr.isIPv6Address() ) { memset( &a6, 0, sizeof(a6) ); a6.sin6_family = AF_INET6; a6.sin6_port = htons( port ); Q_IPV6ADDR ip6 = addr.toIPv6Address(); memcpy( &a6.sin6_addr.s6_addr, &ip6, sizeof(ip6) ); aalen = sizeof( a6 ); aa = (struct sockaddr *)&a6; } else #endif if ( addr.isIPv4Address() ) { memset( &a4, 0, sizeof(a4) ); a4.sin_family = AF_INET; a4.sin_port = htons( port ); a4.sin_addr.s_addr = htonl( addr.toIPv4Address() ); aalen = sizeof(a4); aa = (struct sockaddr *)&a4; } else { e = Impossible; return false; } int r = QT_SOCKET_CONNECT( fd, aa, aalen ); if ( r == 0 ) { fetchConnectionParameters(); return true; } if ( errno == EISCONN || errno == EALREADY || errno == EINPROGRESS ) { fetchConnectionParameters(); return true; } if ( e != NoError || errno == EAGAIN || errno == EWOULDBLOCK ) { return false; } switch( errno ) { case EBADF: case ENOTSOCK: e = Impossible; break; case EFAULT: case EAFNOSUPPORT: e = InternalError; break; case ECONNREFUSED: e = ConnectionRefused; break; case ETIMEDOUT: case ENETUNREACH: e = NetworkFailure; break; case EADDRINUSE: e = NoResources; break; case EACCES: case EPERM: e = Inaccessible; break; default: e = UnknownError; break; } return false; }
static bool multicastMembershipHelper(QNativeSocketEnginePrivate *d, int how6, int how4, const QHostAddress &groupAddress, const QNetworkInterface &iface) { int level = 0; int sockOpt = 0; char *sockArg; int sockArgSize; struct ip_mreq mreq4; #ifndef QT_NO_IPV6 struct ipv6_mreq mreq6; if (groupAddress.protocol() == QAbstractSocket::IPv6Protocol) { level = IPPROTO_IPV6; sockOpt = how6; sockArg = reinterpret_cast<char *>(&mreq6); sockArgSize = sizeof(mreq6); memset(&mreq6, 0, sizeof(mreq6)); Q_IPV6ADDR ip6 = groupAddress.toIPv6Address(); memcpy(&mreq6.ipv6mr_multiaddr, &ip6, sizeof(ip6)); mreq6.ipv6mr_interface = iface.index(); } else #endif if (groupAddress.protocol() == QAbstractSocket::IPv4Protocol) { level = IPPROTO_IP; sockOpt = how4; sockArg = reinterpret_cast<char *>(&mreq4); sockArgSize = sizeof(mreq4); memset(&mreq4, 0, sizeof(mreq4)); mreq4.imr_multiaddr.s_addr = htonl(groupAddress.toIPv4Address()); if (iface.isValid()) { QList<QNetworkAddressEntry> addressEntries = iface.addressEntries(); if (!addressEntries.isEmpty()) { QHostAddress firstIP = addressEntries.first().ip(); mreq4.imr_interface.s_addr = htonl(firstIP.toIPv4Address()); } else { d->setError(QAbstractSocket::NetworkError, QNativeSocketEnginePrivate::NetworkUnreachableErrorString); return false; } } else { mreq4.imr_interface.s_addr = INADDR_ANY; } } else { // unreachable d->setError(QAbstractSocket::UnsupportedSocketOperationError, QNativeSocketEnginePrivate::ProtocolUnsupportedErrorString); return false; } int res = setsockopt(d->socketDescriptor, level, sockOpt, sockArg, sockArgSize); if (res == -1) { d->setError(QAbstractSocket::UnsupportedSocketOperationError, QNativeSocketEnginePrivate::OperationUnsupportedErrorString); return false; } return true; }
void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestName, const QHostAddress &nameserver, QDnsLookupReply *reply) { // Load dn_expand, res_ninit and res_nquery on demand. static QBasicAtomicInt triedResolve = Q_BASIC_ATOMIC_INITIALIZER(false); if (!triedResolve.loadAcquire()) { QMutexLocker locker(QMutexPool::globalInstanceGet(&local_res_ninit)); if (!triedResolve.load()) { resolveLibrary(); triedResolve.storeRelease(true); } } // If dn_expand, res_ninit or res_nquery is missing, fail. if (!local_dn_expand || !local_res_nclose || !local_res_ninit || !local_res_nquery) { reply->error = QDnsLookup::ResolverError; reply->errorString = tr("Resolver functions not found"); return; } // Initialize state. struct __res_state state; memset(&state, 0, sizeof(state)); if (local_res_ninit(&state) < 0) { reply->error = QDnsLookup::ResolverError; reply->errorString = tr("Resolver initialization failed"); return; } //Check if a nameserver was set. If so, use it if (!nameserver.isNull()) { if (nameserver.protocol() == QAbstractSocket::IPv4Protocol) { state.nsaddr_list[0].sin_addr.s_addr = htonl(nameserver.toIPv4Address()); state.nscount = 1; } else if (nameserver.protocol() == QAbstractSocket::IPv6Protocol) { #if defined(Q_OS_LINUX) struct sockaddr_in6 *ns; ns = state._u._ext.nsaddrs[0]; // nsaddrs will be NULL if no nameserver is set in /etc/resolv.conf if (!ns) { // Memory allocated here will be free'd in res_close() as we // have done res_init() above. ns = (struct sockaddr_in6*) calloc(1, sizeof(struct sockaddr_in6)); Q_CHECK_PTR(ns); state._u._ext.nsaddrs[0] = ns; } // Set nsmap[] to indicate that nsaddrs[0] is an IPv6 address // See: https://sourceware.org/ml/libc-hacker/2002-05/msg00035.html state._u._ext.nsmap[0] = MAXNS + 1; state._u._ext.nscount6 = 1; ns->sin6_family = AF_INET6; ns->sin6_port = htons(53); Q_IPV6ADDR ipv6Address = nameserver.toIPv6Address(); for (int i=0; i<16; i++) { ns->sin6_addr.s6_addr[i] = ipv6Address[i]; } #else qWarning() << Q_FUNC_INFO << "IPv6 addresses for nameservers is currently not supported"; reply->error = QDnsLookup::ResolverError; reply->errorString = tr("IPv6 addresses for nameservers is currently not supported"); return; #endif } } #ifdef QDNSLOOKUP_DEBUG state.options |= RES_DEBUG; #endif QScopedPointer<struct __res_state, QDnsLookupStateDeleter> state_ptr(&state); // Perform DNS query. unsigned char response[PACKETSZ]; memset(response, 0, sizeof(response)); const int responseLength = local_res_nquery(&state, requestName, C_IN, requestType, response, sizeof(response)); // Check the response header. HEADER *header = (HEADER*)response; const int answerCount = ntohs(header->ancount); switch (header->rcode) { case NOERROR: break; case FORMERR: reply->error = QDnsLookup::InvalidRequestError; reply->errorString = tr("Server could not process query"); return; case SERVFAIL: reply->error = QDnsLookup::ServerFailureError; reply->errorString = tr("Server failure"); return; case NXDOMAIN: reply->error = QDnsLookup::NotFoundError; reply->errorString = tr("Non existent domain"); return; case REFUSED: reply->error = QDnsLookup::ServerRefusedError; reply->errorString = tr("Server refused to answer"); return; default: reply->error = QDnsLookup::InvalidReplyError; reply->errorString = tr("Invalid reply received"); return; } // Check the reply is valid. if (responseLength < int(sizeof(HEADER))) { reply->error = QDnsLookup::InvalidReplyError; reply->errorString = tr("Invalid reply received"); return; } // Skip the query host, type (2 bytes) and class (2 bytes). char host[PACKETSZ], answer[PACKETSZ]; unsigned char *p = response + sizeof(HEADER); int status = local_dn_expand(response, response + responseLength, p, host, sizeof(host)); if (status < 0) { reply->error = QDnsLookup::InvalidReplyError; reply->errorString = tr("Could not expand domain name"); return; } p += status + 4; // Extract results. int answerIndex = 0; while ((p < response + responseLength) && (answerIndex < answerCount)) { status = local_dn_expand(response, response + responseLength, p, host, sizeof(host)); if (status < 0) { reply->error = QDnsLookup::InvalidReplyError; reply->errorString = tr("Could not expand domain name"); return; } const QString name = QUrl::fromAce(host); p += status; const quint16 type = (p[0] << 8) | p[1]; p += 2; // RR type p += 2; // RR class const quint32 ttl = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; p += 4; const quint16 size = (p[0] << 8) | p[1]; p += 2; if (type == QDnsLookup::A) { if (size != 4) { reply->error = QDnsLookup::InvalidReplyError; reply->errorString = tr("Invalid IPv4 address record"); return; } const quint32 addr = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; QDnsHostAddressRecord record; record.d->name = name; record.d->timeToLive = ttl; record.d->value = QHostAddress(addr); reply->hostAddressRecords.append(record); } else if (type == QDnsLookup::AAAA) { if (size != 16) { reply->error = QDnsLookup::InvalidReplyError; reply->errorString = tr("Invalid IPv6 address record"); return; } QDnsHostAddressRecord record; record.d->name = name; record.d->timeToLive = ttl; record.d->value = QHostAddress(p); reply->hostAddressRecords.append(record); } else if (type == QDnsLookup::CNAME) { status = local_dn_expand(response, response + responseLength, p, answer, sizeof(answer)); if (status < 0) { reply->error = QDnsLookup::InvalidReplyError; reply->errorString = tr("Invalid canonical name record"); return; } QDnsDomainNameRecord record; record.d->name = name; record.d->timeToLive = ttl; record.d->value = QUrl::fromAce(answer); reply->canonicalNameRecords.append(record); } else if (type == QDnsLookup::NS) { status = local_dn_expand(response, response + responseLength, p, answer, sizeof(answer)); if (status < 0) { reply->error = QDnsLookup::InvalidReplyError; reply->errorString = tr("Invalid name server record"); return; } QDnsDomainNameRecord record; record.d->name = name; record.d->timeToLive = ttl; record.d->value = QUrl::fromAce(answer); reply->nameServerRecords.append(record); } else if (type == QDnsLookup::PTR) { status = local_dn_expand(response, response + responseLength, p, answer, sizeof(answer)); if (status < 0) { reply->error = QDnsLookup::InvalidReplyError; reply->errorString = tr("Invalid pointer record"); return; } QDnsDomainNameRecord record; record.d->name = name; record.d->timeToLive = ttl; record.d->value = QUrl::fromAce(answer); reply->pointerRecords.append(record); } else if (type == QDnsLookup::MX) { const quint16 preference = (p[0] << 8) | p[1]; status = local_dn_expand(response, response + responseLength, p + 2, answer, sizeof(answer)); if (status < 0) { reply->error = QDnsLookup::InvalidReplyError; reply->errorString = tr("Invalid mail exchange record"); return; } QDnsMailExchangeRecord record; record.d->exchange = QUrl::fromAce(answer); record.d->name = name; record.d->preference = preference; record.d->timeToLive = ttl; reply->mailExchangeRecords.append(record); } else if (type == QDnsLookup::SRV) { const quint16 priority = (p[0] << 8) | p[1]; const quint16 weight = (p[2] << 8) | p[3]; const quint16 port = (p[4] << 8) | p[5]; status = local_dn_expand(response, response + responseLength, p + 6, answer, sizeof(answer)); if (status < 0) { reply->error = QDnsLookup::InvalidReplyError; reply->errorString = tr("Invalid service record"); return; } QDnsServiceRecord record; record.d->name = name; record.d->target = QUrl::fromAce(answer); record.d->port = port; record.d->priority = priority; record.d->timeToLive = ttl; record.d->weight = weight; reply->serviceRecords.append(record); } else if (type == QDnsLookup::TXT) { unsigned char *txt = p; QDnsTextRecord record; record.d->name = name; record.d->timeToLive = ttl; while (txt < p + size) { const unsigned char length = *txt; txt++; if (txt + length > p + size) { reply->error = QDnsLookup::InvalidReplyError; reply->errorString = tr("Invalid text record"); return; } record.d->values << QByteArray((char*)txt, length); txt += length; } reply->textRecords.append(record); } p += size; answerIndex++; } }