28 #include <config-network.h>
30 #include <sys/types.h>
31 #include <sys/socket.h>
33 #include <netinet/in.h>
47 #include <QTextStream>
63 using namespace KNetwork;
64 using namespace KNetwork::Internal;
73 if (!qgetenv(
"KDE_NO_IPV6").isEmpty())
77 SOCKET s = ::socket(AF_INET6, SOCK_STREAM, 0);
78 if (s == INVALID_SOCKET)
82 int fd = ::socket(AF_INET6, SOCK_STREAM, 0);
97 void KBlacklistWorker::init()
102 static bool beenhere =
false;
111 void KBlacklistWorker::loadBlacklist()
116 QStringList::ConstIterator it = filelist.constBegin(),
117 end = filelist.constEnd();
118 for ( ; it != end; ++it)
122 if (!f.open(QIODevice::ReadOnly))
125 QTextStream stream(&f);
126 stream.setCodec(
"latin1");
127 for (
QString line = stream.readLine(); !line.isNull();
128 line = stream.readLine())
135 line = line.trimmed();
136 if (line[0] != QLatin1Char(
'.'))
137 line.prepend(QLatin1Char(
'.'));
139 blacklist.append(line.toLower());
146 bool KBlacklistWorker::isBlacklisted(
const QString& host)
148 KBlacklistWorker::init();
159 QStringList::ConstIterator it = blacklist.constBegin(),
160 end = blacklist.constEnd();
161 for ( ; it != end; ++it)
162 if (ascii.endsWith(*it))
169 bool KBlacklistWorker::preprocess()
171 if (isBlacklisted(nodeName()))
180 bool KBlacklistWorker::run()
206 #ifndef HAVE_GETADDRINFO
208 # if defined(HAVE_GETHOSTBYNAME2_R)
209 # define USE_GETHOSTBYNAME2_R
210 # elif defined(HAVE_GETHOSTBYNAME_R) && (!defined(AF_INET6) || !defined(HAVE_GETHOSTBYNAME2))
211 # define USE_GETHOSTBYNAME_R
212 # elif defined(HAVE_GETHOSTBYNAME2)
213 # define USE_GETHOSTBYNAME2)
215 # define USE_GETHOSTBYNAME
221 QByteArray m_hostname;
227 GetHostByNameThread(
const char * hostname, quint16 port,
229 m_hostname(hostname), m_port(port), m_scopeid(scopeid), m_af(af),
233 ~GetHostByNameThread()
236 virtual bool preprocess()
241 void processResults(hostent* he,
int my_h_errno);
244 bool GetHostByNameThread::run()
249 unsigned buflen = 1024;
257 ResolverLocker resLock(
this );
261 my_h_errno = HOST_NOT_FOUND;
264 if (m_af != AF_INET &&
265 KBlacklistWorker::isBlacklisted(QLatin1String(m_hostname)))
268 # ifdef USE_GETHOSTBYNAME2_R
269 buf =
new char[buflen];
270 res = gethostbyname2_r(m_hostname, m_af, &my_results, buf, buflen,
271 &resultptr, &my_h_errno);
273 # elif defined(USE_GETHOSTBYNAME_R)
276 buf =
new char[buflen];
277 res = gethostbyname_r(m_hostname, &my_results, buf, buflen,
278 &resultptr, &my_h_errno);
283 # elif defined(USE_GETHOSTBYNAME2)
285 resultptr = gethostbyname2(m_hostname, m_af);
286 my_h_errno = h_errno;
292 resultptr = gethostbyname(m_hostname);
293 my_h_errno = h_errno;
309 buf =
new char[buflen];
312 if ((res == ERANGE || my_h_errno != 0) && checkResolver())
318 while (res == ERANGE);
319 processResults(resultptr, my_h_errno);
327 void GetHostByNameThread::processResults(hostent *he,
int herrno)
331 qDebug(
"KStandardWorker::processResults: got error %d", herrno);
367 int proto = protocol();
368 int socktype = socketType();
370 socktype = SOCK_STREAM;
375 if (he->h_addrtype != AF_INET)
378 for (
int i = 0; he->h_addr_list[i]; i++)
381 results.prepend(
KResolverEntry(sa, socktype, proto, canon, m_hostname));
387 #else // HAVE_GETADDRINFO
398 GetAddrInfoThread(
const char* node,
const char* serv,
int af,
int flags,
400 m_node(node), m_serv(serv), m_af(af), m_flags(flags), results(*res)
406 virtual bool preprocess()
414 bool GetAddrInfoThread::run()
417 if ((m_af != AF_INET && m_af != AF_UNSPEC) &&
418 KBlacklistWorker::isBlacklisted(QLatin1String(m_node)))
427 ResolverLocker resLock(
this );
431 memset(&hint, 0,
sizeof(hint));
443 # ifdef AI_NUMERICHOST
447 # ifdef AI_ADDRCONFIG
452 if (m_node.isEmpty())
456 int res =
getaddrinfo(m_node, m_serv, &hint, &result);
478 #if EAI_NODATA != EAI_NONAME
510 #ifdef EAI_SYSTEM // not available on windows
526 const char *previous_canon = 0L;
531 if ((previous_canon && !p->ai_canonname) ||
532 (!previous_canon && p->ai_canonname) ||
533 (p->ai_canonname != previous_canon &&
534 strcmp(p->ai_canonname, previous_canon) != 0))
537 previous_canon = p->ai_canonname;
540 results.append(
KResolverEntry(p->ai_addr, p->ai_addrlen, p->ai_socktype,
541 p->ai_protocol, canon, m_node));
552 #endif // HAVE_GETADDRINFO
555 KStandardWorker::~KStandardWorker()
557 qDeleteAll(resultList);
560 bool KStandardWorker::sanityCheck()
564 if (!nodeName().isEmpty())
567 if (node.indexOf(QLatin1Char(
'%')) != -1)
568 node.truncate(node.indexOf(QLatin1Char(
'%')));
570 if (node.isEmpty() || node == QLatin1String(
"*") ||
571 node == QLatin1String(
"localhost"))
572 m_encodedName.truncate(0);
577 if (m_encodedName.isNull())
579 qDebug(
"could not encode hostname '%s' (UTF-8)", node.toUtf8().data());
589 m_encodedName.truncate(0);
591 if (protocol() == -1)
600 bool KStandardWorker::resolveScopeId()
604 int pos = nodeName().lastIndexOf(QLatin1Char(
'%'));
608 QString scopename = nodeName().mid(pos + 1);
611 scopeid = scopename.toInt(&ok);
616 #ifdef HAVE_IF_NAMETOINDEX
617 scopeid = if_nametoindex(scopename.toLatin1());
626 bool KStandardWorker::resolveService()
630 port = serviceName().toUInt(&ok);
636 if (serviceName().isEmpty() || serviceName().compare(QLatin1String(
"*")) == 0)
641 QByteArray protoname = protocolName();
643 if (protoname.isEmpty() && protocol())
648 if (protoname.isEmpty())
668 port = (quint16)result;
684 if (!m_encodedName.isEmpty())
687 if (protocol() || !protocolName().isNull())
690 QString pathname = serviceName();
691 if (pathname.isEmpty())
694 if (pathname[0] != QLatin1Char(
'/'))
697 pathname.prepend(QLatin1String(
"/tmp/"));
701 int socktype = socketType();
703 socktype = SOCK_STREAM;
711 bool KStandardWorker::resolveNumerically()
720 if (!wantV6 && !wantV4)
722 return (flags() & KResolver::NoResolve);
725 if (!resolveScopeId() || !resolveService())
726 return (flags() & KResolver::NoResolve);
735 bool ok = sa.
length() != 0;
740 int proto = protocol();
741 int socktype = socketType();
743 socktype = SOCK_STREAM;
767 else if (m_encodedName.isEmpty())
813 bool KStandardWorker::preprocess()
827 if (socketType() != SOCK_STREAM && socketType() != SOCK_DGRAM && socketType() != 0)
835 if (resolveNumerically() || m_encodedName.isEmpty())
847 # define mask (KResolver::IPv6Family | KResolver::IPv4Family | KResolver::UnixFamily)
849 # define mask (KResolver::IPv4Family | KResolver::UnixFamily)
852 if ((familyMask() &
mask) == 0)
861 bool KStandardWorker::run()
863 #ifndef HAVE_GETADDRINFO
867 if (!resolveScopeId())
871 if (!resolveService())
889 int familyCount =
sizeof(families)/
sizeof(families[0]);
892 for (
int i = 0; i < familyCount; i++)
893 if (familyMask() & families[i].
mask)
896 if (skipIPv6 && families[i].af == AF_INET6)
902 resultList.append(res);
903 #ifdef HAVE_GETADDRINFO
904 worker =
new GetAddrInfoThread(m_encodedName,
905 serviceName().toLatin1(),
906 families[i].af, flags(), res);
908 worker =
new GetHostByNameThread(m_encodedName, port, scopeid,
909 families[i].af, res);
919 bool KStandardWorker::postprocess()
926 if (resultList.isEmpty())
932 for (
int i = resultList.size(); i > 0; --i)
938 KResolverResults::Iterator it = rr->begin();
939 for ( ; it != rr->end(); ++it)
942 else if (results.isEmpty())
948 resultList[i - 1] = 0L;
955 #ifdef HAVE_GETADDRINFO
956 KGetAddrinfoWorker::~KGetAddrinfoWorker()
960 bool KGetAddrinfoWorker::preprocess()
966 if (flags() & KResolver::NoResolve)
973 bool KGetAddrinfoWorker::run()
976 GetAddrInfoThread worker(m_encodedName, serviceName().toLatin1(),
977 AF_UNSPEC, flags(), &results);
981 if (wantThis(AF_UNIX))
987 setError(worker.results.error(), worker.results.systemError());
996 bool seen_unix =
false;
998 while ( i < results.count() )
1001 if (res.
family() == AF_UNIX)
1003 if (!wantThis(res.
family()))
1004 results.removeAt(i);
1016 bool KGetAddrinfoWorker::wantThis(
int family)
1043 #ifdef HAVE_GETADDRINFO