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
static const KIpAddress anyhostV6
the any host or undefined address in IPv6 (::)
A Unix (local) socket address.
an Internet socket address
void initStandardWorkers() KDE_NO_EXPORT
KStandardDirs * dirs()
Returns the application standard dirs object.
static QMutex blacklistMutex
Name and service resolution results.
static void setError(QAbstractSocket *socket, QAbstractSocket::SocketError error, const QString &errorString)
static const KIpAddress localhostV4
localhost in IPv4 (127.0.0.1)
void KNetwork_initSocket()
KInetSocketAddress & setPort(quint16 port)
Sets the port number.
int systemError() const
Retrieves the system error code, if any.
int ipVersion() const
Returns the IP version of the address this object holds.
int getaddrinfo(const char *name, const char *serv, const struct addrinfo *hint, struct addrinfo **result)
static const KIpAddress anyhostV4
the any host or undefined address in IPv4 (0.0.0.0)
KInetSocketAddress & setScopeId(int scopeid)
Sets the scope id for this IPv6 object.
static QList< QByteArray > protocolName(int protonum)
Resolves a protocol number to its names.
KInetSocketAddress & setHost(const KIpAddress &addr)
Sets the IP address to the given raw address.
static QString domainToUnicode(const QByteArray &asciiDomain)
Does the inverse of domainToAscii() and return an Unicode domain name from the given ACE-encoded doma...
quint16 length() const
Returns the length of this socket address structure.
int family() const
Retrieves the family associated with this socket address.
static int servicePort(const char *servname, const char *protoname)
Resolves a service name to its port number.
struct addrinfo * ai_next
void setError(int errorcode, int systemerror=0)
Sets the error codes.
QStringList findAllResources(const char *type, const QString &filter=QString(), SearchOptions options=NoSearchOptions) const
Tries to find all resources with the specified type.
static void registerNewWorker(KResolverWorkerFactoryBase *factory)
Wrapper call to register workers.
int error() const
Retrieves the error code associated with this resolution.
SocketFamilies
Address family selection types.
static const KIpAddress localhostV6
localhost in IPv6 (::1)
static QByteArray domainToAscii(const QString &unicodeDomain)
Returns the domain name in an ASCII Compatible Encoding form, suitable for DNS lookups.
void freeaddrinfo(struct addrinfo *p)