• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.14.38 API Reference
  • KDE Home
  • Contact Us
 

KDECore

  • kdecore
  • network
k3resolverstandardworkers.cpp
Go to the documentation of this file.
1/* -*- C++ -*-
2 * Copyright (C) 2003,2004 Thiago Macieira <thiago@kde.org>
3 *
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25#include "k3resolverstandardworkers_p.h"
26
27#include <config.h>
28#include <config-network.h>
29
30#include <sys/types.h>
31#include <sys/socket.h>
32#include <sys/un.h>
33#include <netinet/in.h>
34#include <netdb.h>
35#include <errno.h>
36#include <string.h>
37#include <stdlib.h>
38#include <unistd.h>
39
40#ifdef HAVE_NET_IF_H
41#include <net/if.h>
42#endif
43
44#include <QFile>
45#include <QList>
46#include <QMutex>
47#include <QTextStream>
48#include <QThread>
49#ifdef Q_WS_WIN
50#include <winsock2.h>
51#endif
52
53#include "kdebug.h"
54#include "kglobal.h"
55#include "kstandarddirs.h"
56
57#include "k3resolver.h"
58#include "k3socketaddress.h"
59
60struct hostent;
61struct addrinfo;
62
63using namespace KNetwork;
64using namespace KNetwork::Internal;
65
66static bool hasIPv6()
67{
68#ifdef Q_WS_WIN
69 extern void KNetwork_initSocket();
70 KNetwork_initSocket();
71#endif
72#ifdef AF_INET6
73 if (!qgetenv("KDE_NO_IPV6").isEmpty())
74 return false;
75
76# ifdef Q_WS_WIN
77 SOCKET s = ::socket(AF_INET6, SOCK_STREAM, 0);
78 if (s == INVALID_SOCKET)
79 return false;
80 ::closesocket(s);
81# else
82 int fd = ::socket(AF_INET6, SOCK_STREAM, 0);
83 if (fd == -1)
84 return false;
85 ::close(fd);
86# endif
87 return true;
88#else
89 return false;
90#endif
91}
92
93// blacklist management
94static QMutex blacklistMutex; // KDE4: change to a QReadWriteLock
95QStringList KBlacklistWorker::blacklist;
96
97void KBlacklistWorker::init()
98{
99 if (!KGlobal::hasMainComponent())
100 return;
101
102 static bool beenhere = false;
103
104 if (beenhere)
105 return;
106
107 beenhere = true;
108 loadBlacklist();
109}
110
111void KBlacklistWorker::loadBlacklist()
112{
113 QMutexLocker locker(&blacklistMutex);
114 QStringList filelist = KGlobal::dirs()->findAllResources("config", QLatin1String("ipv6blacklist"));
115
116 QStringList::ConstIterator it = filelist.constBegin(),
117 end = filelist.constEnd();
118 for ( ; it != end; ++it)
119 {
120 // for each file, each line is a domainname to be blacklisted
121 QFile f(*it);
122 if (!f.open(QIODevice::ReadOnly))
123 continue;
124
125 QTextStream stream(&f);
126 stream.setCodec("latin1");
127 for (QString line = stream.readLine(); !line.isNull();
128 line = stream.readLine())
129 {
130 if (line.isEmpty())
131 continue;
132
133 // make sure there are no surrounding whitespaces
134 // and that it starts with .
135 line = line.trimmed();
136 if (line[0] != QLatin1Char('.'))
137 line.prepend(QLatin1Char('.'));
138
139 blacklist.append(line.toLower());
140 }
141 }
142}
143
144// checks the blacklist to see if the domain is listed
145// it matches the domain ending part
146bool KBlacklistWorker::isBlacklisted(const QString& host)
147{
148 KBlacklistWorker::init();
149
150 // empty hostnames cannot be blacklisted
151 if (host.isEmpty())
152 return false;
153
154 QString ascii = QLatin1String(KResolver::domainToAscii(host));
155
156 QMutexLocker locker(&blacklistMutex);
157
158 // now find out if this hostname is present
159 QStringList::ConstIterator it = blacklist.constBegin(),
160 end = blacklist.constEnd();
161 for ( ; it != end; ++it)
162 if (ascii.endsWith(*it))
163 return true;
164
165 // no match:
166 return false;
167}
168
169bool KBlacklistWorker::preprocess()
170{
171 if (isBlacklisted(nodeName()))
172 {
173 results.setError(KResolver::NoName);
174 finished();
175 return true;
176 }
177 return false;
178}
179
180bool KBlacklistWorker::run()
181{
182 results.setError(KResolver::NoName);
183 finished();
184 return false; // resolution failure
185}
186
187namespace
188{
189 /*
190 * Note on the use of the system resolver functions:
191 *
192 * In all cases, we prefer to use the new getaddrinfo(3) call. That means
193 * it will always be used if it is found.
194 *
195 * If it's not found, we have the option to use gethostbyname2_r,
196 * gethostbyname_r, gethostbyname2 and gethostbyname. If gethostbyname2_r
197 * is defined, we will use it.
198 *
199 * If it's not defined, we have to choose between the non-reentrant
200 * gethostbyname2 and the reentrant but IPv4-only gethostbyname_r:
201 * we will choose gethostbyname2 if AF_INET6 is defined.
202 *
203 * Lastly, gethostbyname will be used if nothing else is present.
204 */
205
206#ifndef HAVE_GETADDRINFO
207
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)
214# else
215# define USE_GETHOSTBYNAME
216# endif
217
218 class GetHostByNameThread: public KResolverWorkerBase
219 {
220 public:
221 QByteArray m_hostname; // might be different!
222 quint16 m_port;
223 int m_scopeid;
224 int m_af;
225 KResolverResults& results;
226
227 GetHostByNameThread(const char * hostname, quint16 port,
228 int scopeid, int af, KResolverResults* res) :
229 m_hostname(hostname), m_port(port), m_scopeid(scopeid), m_af(af),
230 results(*res)
231 { }
232
233 ~GetHostByNameThread()
234 { }
235
236 virtual bool preprocess()
237 { return true; }
238
239 virtual bool run();
240
241 void processResults(hostent* he, int my_h_errno);
242 };
243
244 bool GetHostByNameThread::run()
245 {
246
247 hostent *resultptr;
248 hostent my_results;
249 unsigned buflen = 1024;
250 int res;
251 int my_h_errno;
252 char *buf = 0L;
253
254 // qDebug("ResolveThread::run(): started threaded gethostbyname for %s (af = %d)",
255 // m_hostname.data(), m_af);
256
257 ResolverLocker resLock( this );
258 do
259 {
260 res = 0;
261 my_h_errno = HOST_NOT_FOUND;
262
263 // check blacklist
264 if (m_af != AF_INET &&
265 KBlacklistWorker::isBlacklisted(QLatin1String(m_hostname)))
266 break;
267
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);
272
273# elif defined(USE_GETHOSTBYNAME_R)
274 if (m_af == AF_INET)
275 {
276 buf = new char[buflen];
277 res = gethostbyname_r(m_hostname, &my_results, buf, buflen,
278 &resultptr, &my_h_errno);
279 }
280 else
281 resultptr = 0; // signal error
282
283# elif defined(USE_GETHOSTBYNAME2)
284 // must lock mutex
285 resultptr = gethostbyname2(m_hostname, m_af);
286 my_h_errno = h_errno;
287
288# else
289 if (m_af == AF_INET)
290 {
291 // must lock mutex
292 resultptr = gethostbyname(m_hostname);
293 my_h_errno = h_errno;
294 }
295 else
296 resultptr = 0;
297# endif
298
299 if (resultptr != 0L)
300 my_h_errno = 0;
301 // qDebug("GetHostByNameThread::run(): gethostbyname for %s (af = %d) returned: %d",
302 // m_hostname.data(), m_af, my_h_errno);
303
304 if (res == ERANGE)
305 {
306 // Enlarge the buffer
307 buflen += 1024;
308 delete [] buf;
309 buf = new char[buflen];
310 }
311
312 if ((res == ERANGE || my_h_errno != 0) && checkResolver())
313 {
314 // resolver needs updating, so we might as well do it now
315 resLock.openClose();
316 }
317 }
318 while (res == ERANGE);
319 processResults(resultptr, my_h_errno);
320
321 delete [] buf;
322
323 finished();
324 return results.error() == KResolver::NoError;
325 }
326
327 void GetHostByNameThread::processResults(hostent *he, int herrno)
328 {
329 if (herrno)
330 {
331 qDebug("KStandardWorker::processResults: got error %d", herrno);
332 switch (herrno)
333 {
334 case HOST_NOT_FOUND:
335 results.setError(KResolver::NoName);
336 return;
337
338 case TRY_AGAIN:
339 results.setError(KResolver::TryAgain);
340 return;
341
342 case NO_RECOVERY:
343 results.setError(KResolver::NonRecoverable);
344 return;
345
346 case NO_ADDRESS:
347 results.setError(KResolver::NoName);
348 return;
349
350 default:
351 results.setError(KResolver::UnknownError);
352 return;
353 }
354 }
355 else if (he == 0L)
356 {
357 results.setError(KResolver::NoName);
358 return; // this was an error
359 }
360
361 // clear any errors
362 setError(KResolver::NoError);
363 results.setError(KResolver::NoError);
364
365 // we process results in the reverse order
366 // that is, we prepend each result to the list of results
367 int proto = protocol();
368 int socktype = socketType();
369 if (socktype == 0)
370 socktype = SOCK_STREAM; // default
371
372 QString canon = KResolver::domainToUnicode(QLatin1String(he->h_name));
373 KInetSocketAddress sa;
374 sa.setPort(m_port);
375 if (he->h_addrtype != AF_INET)
376 sa.setScopeId(m_scopeid); // this will also change the socket into IPv6
377
378 for (int i = 0; he->h_addr_list[i]; i++)
379 {
380 sa.setHost(KIpAddress(he->h_addr_list[i], he->h_addrtype == AF_INET ? 4 : 6));
381 results.prepend(KResolverEntry(sa, socktype, proto, canon, m_hostname));
382 // qDebug("KStandardWorker::processResults: adding %s", sa.toString().toLatin1().constData());
383 }
384 // qDebug("KStandardWorker::processResults: added %d entries", i);
385 }
386
387#else // HAVE_GETADDRINFO
388
389 class GetAddrInfoThread: public KResolverWorkerBase
390 {
391 public:
392 QByteArray m_node;
393 QByteArray m_serv;
394 int m_af;
395 int m_flags;
396 KResolverResults& results;
397
398 GetAddrInfoThread(const char* node, const char* serv, int af, int flags,
399 KResolverResults* res) :
400 m_node(node), m_serv(serv), m_af(af), m_flags(flags), results(*res)
401 { }
402
403 ~GetAddrInfoThread()
404 { }
405
406 virtual bool preprocess()
407 { return true; }
408
409 virtual bool run();
410
411 void processResults(addrinfo* ai, int ret_code, KResolverResults& rr);
412 };
413
414 bool GetAddrInfoThread::run()
415 {
416 // check blacklist
417 if ((m_af != AF_INET && m_af != AF_UNSPEC) &&
418 KBlacklistWorker::isBlacklisted(QLatin1String(m_node)))
419 {
420 results.setError(KResolver::NoName);
421 finished();
422 return false; // failed
423 }
424
425 do
426 {
427 ResolverLocker resLock( this );
428
429 // process hints
430 addrinfo hint;
431 memset(&hint, 0, sizeof(hint));
432 hint.ai_family = m_af;
433 hint.ai_socktype = socketType();
434 hint.ai_protocol = protocol();
435
436 if (hint.ai_socktype == 0)
437 hint.ai_socktype = SOCK_STREAM; // default
438
439 if (m_flags & KResolver::Passive)
440 hint.ai_flags |= AI_PASSIVE;
441 if (m_flags & KResolver::CanonName)
442 hint.ai_flags |= AI_CANONNAME;
443# ifdef AI_NUMERICHOST
444 if (m_flags & KResolver::NoResolve)
445 hint.ai_flags |= AI_NUMERICHOST;
446# endif
447# ifdef AI_ADDRCONFIG
448 hint.ai_flags |= AI_ADDRCONFIG;
449# endif
450
451 // now we do the blocking processing
452 if (m_node.isEmpty())
453 m_node = "*"; // krazy:exclude=doublequote_chars
454
455 addrinfo *result;
456 int res = getaddrinfo(m_node, m_serv, &hint, &result);
457 // kDebug(179) << "getaddrinfo(\""
458 // << m_node << "\", \"" << m_serv << "\", af="
459 // << m_af << ") returned " << res << endl;
460
461 if (res != 0)
462 {
463 if (checkResolver())
464 {
465 // resolver requires reinitialisation
466 resLock.openClose();
467 continue;
468 }
469
470 switch (res)
471 {
472 case EAI_BADFLAGS:
473 results.setError(KResolver::BadFlags);
474 break;
475
476#ifdef EAI_NODATA
477 // In some systems, EAI_NODATA was #define'd to EAI_NONAME which would break this case.
478#if EAI_NODATA != EAI_NONAME
479 case EAI_NODATA: // it was removed in RFC 3493
480#endif
481#endif
482 case EAI_NONAME:
483 results.setError(KResolver::NoName);
484 break;
485
486 case EAI_AGAIN:
487 results.setError(KResolver::TryAgain);
488 break;
489
490 case EAI_FAIL:
491 results.setError(KResolver::NonRecoverable);
492 break;
493
494 case EAI_FAMILY:
495 results.setError(KResolver::UnsupportedFamily);
496 break;
497
498 case EAI_SOCKTYPE:
499 results.setError(KResolver::UnsupportedSocketType);
500 break;
501
502 case EAI_SERVICE:
503 results.setError(KResolver::UnsupportedService);
504 break;
505
506 case EAI_MEMORY:
507 results.setError(KResolver::Memory);
508 break;
509
510#ifdef EAI_SYSTEM // not available on windows
511 case EAI_SYSTEM:
512 results.setError(KResolver::SystemError, errno);
513 break;
514#endif
515 default:
516 results.setError(KResolver::UnknownError, errno);
517 break;
518 }
519
520 finished();
521 return false; // failed
522 }
523
524 // if we are here, lookup succeeded
525 QString canon;
526 const char *previous_canon = 0L;
527
528 for (addrinfo* p = result; p; p = p->ai_next)
529 {
530 // cache the last canon name to avoid doing the ToUnicode processing unnecessarily
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))
535 {
536 canon = KResolver::domainToUnicode(QString::fromLatin1(p->ai_canonname));
537 previous_canon = p->ai_canonname;
538 }
539
540 results.append(KResolverEntry(p->ai_addr, p->ai_addrlen, p->ai_socktype,
541 p->ai_protocol, canon, m_node));
542 }
543
544 freeaddrinfo(result);
545 results.setError(KResolver::NoError);
546 finished();
547 return results.error() == KResolver::NoError;
548 }
549 while (true);
550 }
551
552#endif // HAVE_GETADDRINFO
553} // namespace
554
555KStandardWorker::~KStandardWorker()
556{
557 qDeleteAll(resultList);
558}
559
560bool KStandardWorker::sanityCheck()
561{
562 // check that the requested values are sensible
563
564 if (!nodeName().isEmpty())
565 {
566 QString node = nodeName();
567 if (node.indexOf(QLatin1Char('%')) != -1)
568 node.truncate(node.indexOf(QLatin1Char('%')));
569
570 if (node.isEmpty() || node == QLatin1String("*") ||
571 node == QLatin1String("localhost"))
572 m_encodedName.truncate(0);
573 else
574 {
575 m_encodedName = KResolver::domainToAscii(node);
576
577 if (m_encodedName.isNull())
578 {
579 qDebug("could not encode hostname '%s' (UTF-8)", node.toUtf8().data());
580 setError(KResolver::NoName);
581 return false; // invalid hostname!
582 }
583
584 // qDebug("Using encoded hostname '%s' for '%s' (UTF-8)", m_encodedName.data(),
585 // node.toUtf8().data());
586 }
587 }
588 else
589 m_encodedName.truncate(0); // just to be sure, but it should be clear already
590
591 if (protocol() == -1)
592 {
593 setError(KResolver::NonRecoverable);
594 return false; // user passed invalid protocol name
595 }
596
597 return true; // it's sane
598}
599
600bool KStandardWorker::resolveScopeId()
601{
602 // we must test the original name, not the encoded one
603 scopeid = 0;
604 int pos = nodeName().lastIndexOf(QLatin1Char('%'));
605 if (pos == -1)
606 return true;
607
608 QString scopename = nodeName().mid(pos + 1);
609
610 bool ok;
611 scopeid = scopename.toInt(&ok);
612 if (!ok)
613 {
614 // it's not a number
615 // therefore, it's an interface name
616#ifdef HAVE_IF_NAMETOINDEX
617 scopeid = if_nametoindex(scopename.toLatin1());
618#else
619 scopeid = 0;
620#endif
621 }
622
623 return true;
624}
625
626bool KStandardWorker::resolveService()
627{
628 // find the service first
629 bool ok;
630 port = serviceName().toUInt(&ok);
631 if (!ok)
632 {
633 // service name does not contain a port number
634 // must be a name
635
636 if (serviceName().isEmpty() || serviceName().compare(QLatin1String("*")) == 0)
637 port = 0;
638 else
639 {
640 // it's a name. We need the protocol name in order to lookup.
641 QByteArray protoname = protocolName();
642
643 if (protoname.isEmpty() && protocol())
644 {
645 protoname = KResolver::protocolName(protocol()).first();
646
647 // if it's still empty...
648 if (protoname.isEmpty())
649 {
650 // lookup failed!
651 setError(KResolver::NoName);
652 return false;
653 }
654 }
655 else
656 protoname = "tcp";
657
658 // it's not, so we can do a port lookup
659 int result = KResolver::servicePort(serviceName().toLatin1(), protoname);
660 if (result == -1)
661 {
662 // lookup failed!
663 setError(KResolver::NoName);
664 return false;
665 }
666
667 // it worked, we have a port number
668 port = (quint16)result;
669 }
670 }
671
672 // we found a port
673 return true;
674}
675
676KResolver::ErrorCodes KStandardWorker::addUnix()
677{
678 // before trying to add, see if the user wants Unix sockets
679 if ((familyMask() & KResolver::UnixFamily) == 0)
680 // no, Unix sockets are not wanted
681 return KResolver::UnsupportedFamily;
682
683 // now check if the requested data are good for a Unix socket
684 if (!m_encodedName.isEmpty())
685 return KResolver::AddrFamily; // non local hostname
686
687 if (protocol() || !protocolName().isNull())
688 return KResolver::BadFlags; // cannot have Unix sockets with protocols
689
690 QString pathname = serviceName();
691 if (pathname.isEmpty())
692 return KResolver::NoName;; // no path?
693
694 if (pathname[0] != QLatin1Char('/'))
695 // non absolute pathname
696 // put it in /tmp
697 pathname.prepend(QLatin1String("/tmp/"));
698
699 // qDebug("QNoResolveWorker::addUnix(): adding Unix socket for %s", pathname.toLocal8Bit().data());
700 KUnixSocketAddress sa(pathname);
701 int socktype = socketType();
702 if (socktype == 0)
703 socktype = SOCK_STREAM; // default
704
705 results.append(KResolverEntry(sa, socktype, 0));
706 setError(KResolver::NoError);
707
708 return KResolver::NoError;
709}
710
711bool KStandardWorker::resolveNumerically()
712{
713 // if the NoResolve flag is active, our result from this point forward
714 // will always be true, even if the resolution failed.
715 // that indicates that our result is authoritative.
716
717 bool wantV4 = familyMask() & KResolver::IPv4Family,
718 wantV6 = familyMask() & KResolver::IPv6Family;
719
720 if (!wantV6 && !wantV4)
721 // no Internet address is wanted!
722 return (flags() & KResolver::NoResolve);
723
724 // now try to find results
725 if (!resolveScopeId() || !resolveService())
726 return (flags() & KResolver::NoResolve);
727
728 // we have scope IDs and port numbers
729 // now try to resolve the hostname numerically
730 KInetSocketAddress sa;
731 setError(KResolver::NoError);
732 sa.setHost(KIpAddress(QLatin1String(m_encodedName)));
733
734 // if it failed, the length was reset to 0
735 bool ok = sa.length() != 0;
736
737 sa.setPort(port);
738 if (sa.ipVersion() == 6)
739 sa.setScopeId(scopeid);
740 int proto = protocol();
741 int socktype = socketType();
742 if (socktype == 0)
743 socktype = SOCK_STREAM;
744
745 if (ok)
746 {
747 // the given hostname was successfully converted to an IP address
748 // check if the user wanted this kind of address
749
750 if ((sa.ipVersion() == 4 && wantV4) ||
751 (sa.ipVersion() == 6 && wantV6))
752 results.append(KResolverEntry(sa, socktype, proto));
753 else
754 {
755 // Note: the address *IS* a numeric IP
756 // but it's not of the kind the user asked for
757 //
758 // that means that it cannot be a Unix socket (because it's an IP)
759 // and that means that no resolution will tell us otherwise
760 //
761 // This is a failed resolution
762
763 setError(KResolver::AddrFamily);
764 return true;
765 }
766 }
767 else if (m_encodedName.isEmpty())
768 {
769 // user wanted localhost
770 if (flags() & KResolver::Passive)
771 {
772 if (wantV6)
773 {
774 sa.setHost(KIpAddress::anyhostV6);
775 results.append(KResolverEntry(sa, socktype, proto));
776 }
777
778 if (wantV4)
779 {
780 sa.setHost(KIpAddress::anyhostV4);
781 results.append(KResolverEntry(sa, socktype, proto));
782 }
783 }
784 else
785 {
786 if (wantV6)
787 {
788 sa.setHost(KIpAddress::localhostV6);
789 results.append(KResolverEntry(sa, socktype, proto));
790 }
791
792 if (wantV4)
793 {
794 sa.setHost(KIpAddress::localhostV4);
795 results.append(KResolverEntry(sa, socktype, proto));
796 }
797 }
798
799 ok = true;
800 }
801 else
802 {
803 // probably bad flags, since the address is not convertible without
804 // resolution
805
806 setError(KResolver::BadFlags);
807 ok = false;
808 }
809
810 return ok || (flags() & KResolver::NoResolve);
811}
812
813bool KStandardWorker::preprocess()
814{
815 // check sanity
816 if (!sanityCheck())
817 return false;
818
819 // this worker class can only handle known families
820 if (familyMask() & KResolver::UnknownFamily)
821 {
822 setError(KResolver::UnsupportedFamily);
823 return false; // we don't know about this
824 }
825
826 // check the socket types
827 if (socketType() != SOCK_STREAM && socketType() != SOCK_DGRAM && socketType() != 0)
828 {
829 setError(KResolver::UnsupportedSocketType);
830 return false;
831 }
832
833 // check if we can resolve all numerically
834 // resolveNumerically always returns true if the NoResolve flag is set
835 if (resolveNumerically() || m_encodedName.isEmpty())
836 {
837 // indeed, we have resolved numerically
838 setError(addUnix());
839 if (results.count())
840 setError(KResolver::NoError);
841 finished();
842 return true;
843 }
844
845 // check if the user wants something we know about
846#ifdef AF_INET6
847# define mask (KResolver::IPv6Family | KResolver::IPv4Family | KResolver::UnixFamily)
848#else
849# define mask (KResolver::IPv4Family | KResolver::UnixFamily)
850#endif
851
852 if ((familyMask() & mask) == 0)
853 // errr... nothing we know about
854 return false;
855
856#undef mask
857
858 return true; // it's ok
859}
860
861bool KStandardWorker::run()
862{
863#ifndef HAVE_GETADDRINFO
864 // check the scope id first
865 // since most of the resolutions won't have a scope id, this should be fast
866 // and we won't have wasted time on services if this fails
867 if (!resolveScopeId())
868 return false;
869
870 // resolve the service now, before entering the blocking operation
871 if (!resolveService())
872 return false;
873#endif
874
875 // good
876 // now we need the hostname
877 setError(KResolver::NoName);
878
879 // these are the family types that we know of
880 struct
881 {
882 KResolver::SocketFamilies mask;
883 int af;
884 } families[] = { { KResolver::IPv4Family, AF_INET }
885#ifdef AF_INET6
886 , { KResolver::IPv6Family, AF_INET6 }
887#endif
888 };
889 int familyCount = sizeof(families)/sizeof(families[0]);
890 bool skipIPv6 = !hasIPv6();
891
892 for (int i = 0; i < familyCount; i++)
893 if (familyMask() & families[i].mask)
894 {
895#ifdef AF_INET6
896 if (skipIPv6 && families[i].af == AF_INET6)
897 continue;
898#endif
899
900 KResolverWorkerBase *worker;
901 KResolverResults *res = new KResolverResults;
902 resultList.append(res);
903#ifdef HAVE_GETADDRINFO
904 worker = new GetAddrInfoThread(m_encodedName,
905 serviceName().toLatin1(),
906 families[i].af, flags(), res);
907#else
908 worker = new GetHostByNameThread(m_encodedName, port, scopeid,
909 families[i].af, res);
910#endif
911
912 enqueue(worker);
913 }
914
915 // not finished
916 return true;
917}
918
919bool KStandardWorker::postprocess()
920{
921 if (results.count())
922 return true; // no need
923 // now copy over what we need from the underlying results
924
925 // start backwards because IPv6 was launched later (if at all)
926 if (resultList.isEmpty())
927 {
928 results.setError(KResolver::NoName);
929 return true;
930 }
931
932 for (int i = resultList.size(); i > 0; --i)
933 {
934 KResolverResults* rr = resultList.at(i - 1);
935 if (!rr->isEmpty())
936 {
937 results.setError(KResolver::NoError);
938 KResolverResults::Iterator it = rr->begin();
939 for ( ; it != rr->end(); ++it)
940 results.append(*it);
941 }
942 else if (results.isEmpty())
943 // this generated an error
944 // copy the error code over
945 setError(rr->error(), rr->systemError());
946
947 delete rr;
948 resultList[i - 1] = 0L;
949 }
950
951 resultList.clear();
952 return true;
953}
954
955#ifdef HAVE_GETADDRINFO
956KGetAddrinfoWorker::~KGetAddrinfoWorker()
957{
958}
959
960bool KGetAddrinfoWorker::preprocess()
961{
962 // getaddrinfo(3) can always handle any kind of request that makes sense
963 if (!sanityCheck())
964 return false;
965
966 if (flags() & KResolver::NoResolve)
967 // oops, numeric resolution?
968 return run();
969
970 return true;
971}
972
973bool KGetAddrinfoWorker::run()
974{
975 // make an AF_UNSPEC getaddrinfo(3) call
976 GetAddrInfoThread worker(m_encodedName, serviceName().toLatin1(),
977 AF_UNSPEC, flags(), &results);
978
979 if (!worker.run())
980 {
981 if (wantThis(AF_UNIX))
982 {
983 if (addUnix() == KResolver::NoError)
984 setError(KResolver::NoError);
985 }
986 else
987 setError(worker.results.error(), worker.results.systemError());
988
989 return false;
990 }
991
992 // The worker has finished working
993 // now copy over only what we may want
994 // keep track of any Unix-domain sockets
995
996 bool seen_unix = false;
997 int i = 0;
998 while ( i < results.count() )
999 {
1000 const KResolverEntry& res = results[i];
1001 if (res.family() == AF_UNIX)
1002 seen_unix = true;
1003 if (!wantThis(res.family()))
1004 results.removeAt(i);
1005 else
1006 ++i;
1007 }
1008
1009 if (!seen_unix)
1010 addUnix();
1011
1012 finished();
1013 return true;
1014}
1015
1016bool KGetAddrinfoWorker::wantThis(int family)
1017{
1018 // tells us if the user wants a socket of this family
1019
1020#ifdef AF_INET6
1021 if (family == AF_INET6 && familyMask() & KResolver::IPv6Family)
1022 return true;
1023#endif
1024 if (family == AF_INET && familyMask() & KResolver::IPv4Family)
1025 return true;
1026 if (family == AF_UNIX && familyMask() & KResolver::UnixFamily)
1027 return true;
1028
1029 // it's not a family we know about...
1030 if (familyMask() & KResolver::UnknownFamily)
1031 return true;
1032
1033 return false;
1034}
1035
1036#endif
1037
1038void KNetwork::Internal::initStandardWorkers()
1039{
1040 //KResolverWorkerFactoryBase::registerNewWorker(new KResolverWorkerFactory<KBlacklistWorker>);
1041 KResolverWorkerFactoryBase::registerNewWorker(new KResolverWorkerFactory<KStandardWorker>);
1042
1043#ifdef HAVE_GETADDRINFO
1044 KResolverWorkerFactoryBase::registerNewWorker(new KResolverWorkerFactory<KGetAddrinfoWorker>);
1045#endif
1046}
KNetwork::Internal::KBlacklistWorker::preprocess
virtual bool preprocess()
This function gets called during pre processing for this class and you must override it.
Definition: k3resolverstandardworkers.cpp:169
KNetwork::Internal::KBlacklistWorker::loadBlacklist
static void loadBlacklist()
Definition: k3resolverstandardworkers.cpp:111
KNetwork::Internal::KBlacklistWorker::isBlacklisted
static bool isBlacklisted(const QString &)
Definition: k3resolverstandardworkers.cpp:146
KNetwork::Internal::KBlacklistWorker::run
virtual bool run()
This is the function that should be overridden in derived classes.
Definition: k3resolverstandardworkers.cpp:180
KNetwork::Internal::KBlacklistWorker::init
static void init()
Definition: k3resolverstandardworkers.cpp:97
KNetwork::Internal::KBlacklistWorker::blacklist
static QStringList blacklist
Definition: k3resolverstandardworkers_p.h:52
KNetwork::Internal::KStandardWorker::resultList
QList< KNetwork::KResolverResults * > resultList
Definition: k3resolverstandardworkers_p.h:72
KNetwork::Internal::KStandardWorker::preprocess
virtual bool preprocess()
This function gets called during pre processing for this class and you must override it.
Definition: k3resolverstandardworkers.cpp:813
KNetwork::Internal::KStandardWorker::scopeid
int scopeid
Definition: k3resolverstandardworkers_p.h:71
KNetwork::Internal::KStandardWorker::resolveScopeId
bool resolveScopeId()
Definition: k3resolverstandardworkers.cpp:600
KNetwork::Internal::KStandardWorker::m_encodedName
QByteArray m_encodedName
Definition: k3resolverstandardworkers_p.h:69
KNetwork::Internal::KStandardWorker::addUnix
KNetwork::KResolver::ErrorCodes addUnix()
Definition: k3resolverstandardworkers.cpp:676
KNetwork::Internal::KStandardWorker::run
virtual bool run()
This is the function that should be overridden in derived classes.
Definition: k3resolverstandardworkers.cpp:861
KNetwork::Internal::KStandardWorker::port
quint16 port
Definition: k3resolverstandardworkers_p.h:70
KNetwork::Internal::KStandardWorker::postprocess
virtual bool postprocess()
This function gets called during post processing for this class.
Definition: k3resolverstandardworkers.cpp:919
KNetwork::Internal::KStandardWorker::~KStandardWorker
virtual ~KStandardWorker()
Definition: k3resolverstandardworkers.cpp:555
KNetwork::Internal::KStandardWorker::resolveNumerically
bool resolveNumerically()
Definition: k3resolverstandardworkers.cpp:711
KNetwork::Internal::KStandardWorker::sanityCheck
bool sanityCheck()
Definition: k3resolverstandardworkers.cpp:560
KNetwork::Internal::KStandardWorker::resolveService
bool resolveService()
Definition: k3resolverstandardworkers.cpp:626
KNetwork::KInetSocketAddress
an Internet socket address
Definition: k3socketaddress.h:644
KNetwork::KInetSocketAddress::setScopeId
KInetSocketAddress & setScopeId(int scopeid)
Sets the scope id for this IPv6 object.
Definition: k3socketaddress.cpp:882
KNetwork::KInetSocketAddress::ipVersion
int ipVersion() const
Returns the IP version of the address this object holds.
Definition: k3socketaddress.cpp:736
KNetwork::KInetSocketAddress::setHost
KInetSocketAddress & setHost(const KIpAddress &addr)
Sets the IP address to the given raw address.
Definition: k3socketaddress.cpp:773
KNetwork::KInetSocketAddress::setPort
KInetSocketAddress & setPort(quint16 port)
Sets the port number.
Definition: k3socketaddress.cpp:815
KNetwork::KIpAddress
An IP address.
Definition: k3socketaddress.h:63
KNetwork::KIpAddress::localhostV4
static const KIpAddress localhostV4
localhost in IPv4 (127.0.0.1)
Definition: k3socketaddress.h:394
KNetwork::KIpAddress::anyhostV6
static const KIpAddress anyhostV6
the any host or undefined address in IPv6 (::)
Definition: k3socketaddress.h:401
KNetwork::KIpAddress::localhostV6
static const KIpAddress localhostV6
localhost in IPv6 (::1)
Definition: k3socketaddress.h:399
KNetwork::KIpAddress::anyhostV4
static const KIpAddress anyhostV4
the any host or undefined address in IPv4 (0.0.0.0)
Definition: k3socketaddress.h:396
KNetwork::KResolverEntry
One resolution entry.
Definition: k3resolver.h:69
KNetwork::KResolverEntry::family
int family() const
Retrieves the family associated with this socket address.
Definition: k3resolver.cpp:147
KNetwork::KResolverResults
Name and service resolution results.
Definition: k3resolver.h:213
KNetwork::KResolverResults::systemError
int systemError() const
Retrieves the system error code, if any.
Definition: k3resolver.cpp:235
KNetwork::KResolverResults::error
int error() const
Retrieves the error code associated with this resolution.
Definition: k3resolver.cpp:229
KNetwork::KResolverResults::setError
void setError(int errorcode, int systemerror=0)
Sets the error codes.
Definition: k3resolver.cpp:241
KNetwork::KResolverWorkerBase
Definition: k3resolverworkerbase.h:65
KNetwork::KResolverWorkerBase::familyMask
int familyMask() const
gets the family mask
Definition: k3resolverworkerbase.cpp:71
KNetwork::KResolverWorkerBase::results
KResolverResults results
Derived classes will put their resolved data in this list, or will leave it empty in case of error.
Definition: k3resolverworkerbase.h:128
KNetwork::KResolverWorkerBase::socketType
int socketType() const
gets the socket type
Definition: k3resolverworkerbase.cpp:78
KNetwork::KResolverWorkerBase::protocol
int protocol() const
gets the protocol number
Definition: k3resolverworkerbase.cpp:85
KNetwork::KResolverWorkerBase::protocolName
QByteArray protocolName() const
gets the protocol name, if applicable
Definition: k3resolverworkerbase.cpp:92
KNetwork::KResolverWorkerBase::finished
void finished()
Call this function to indicate that processing has finished.
Definition: k3resolverworkerbase.cpp:100
KNetwork::KResolverWorkerBase::nodeName
QString nodeName() const
This is the hostname to be looked for.
Definition: k3resolverworkerbase.cpp:50
KNetwork::KResolverWorkerBase::enqueue
bool enqueue(KResolver *other)
Enqueue the given resolver for post-processing.
Definition: k3resolverworkerbase.cpp:110
KNetwork::KResolverWorkerBase::serviceName
QString serviceName() const
And this is the service name.
Definition: k3resolverworkerbase.cpp:57
KNetwork::KResolverWorkerBase::setError
void setError(int errorcode, int syserror=0)
Sets the error.
Definition: k3resolverworkerbase.h:230
KNetwork::KResolverWorkerBase::flags
int flags() const
gets the flags
Definition: k3resolverworkerbase.cpp:64
KNetwork::KResolverWorkerFactoryBase::registerNewWorker
static void registerNewWorker(KResolverWorkerFactoryBase *factory)
Wrapper call to register workers.
Definition: k3resolverworkerbase.cpp:148
KNetwork::KResolverWorkerFactory
Definition: k3resolverworkerbase.h:315
KNetwork::KResolver::domainToUnicode
static QString domainToUnicode(const QByteArray &asciiDomain)
Does the inverse of domainToAscii() and return an Unicode domain name from the given ACE-encoded doma...
Definition: k3resolver.cpp:1032
KNetwork::KResolver::SocketFamilies
SocketFamilies
Address family selection types.
Definition: k3resolver.h:335
KNetwork::KResolver::IPv4Family
@ IPv4Family
Definition: k3resolver.h:341
KNetwork::KResolver::IPv6Family
@ IPv6Family
Definition: k3resolver.h:342
KNetwork::KResolver::UnknownFamily
@ UnknownFamily
Definition: k3resolver.h:336
KNetwork::KResolver::UnixFamily
@ UnixFamily
Definition: k3resolver.h:338
KNetwork::KResolver::domainToAscii
static QByteArray domainToAscii(const QString &unicodeDomain)
Returns the domain name in an ASCII Compatible Encoding form, suitable for DNS lookups.
Definition: k3resolver.cpp:1026
KNetwork::KResolver::servicePort
static int servicePort(const char *servname, const char *protoname)
Resolves a service name to its port number.
Definition: k3resolver.cpp:785
KNetwork::KResolver::Passive
@ Passive
Definition: k3resolver.h:369
KNetwork::KResolver::NoResolve
@ NoResolve
Definition: k3resolver.h:371
KNetwork::KResolver::CanonName
@ CanonName
Definition: k3resolver.h:370
KNetwork::KResolver::ErrorCodes
ErrorCodes
Error codes.
Definition: k3resolver.h:398
KNetwork::KResolver::SystemError
@ SystemError
Definition: k3resolver.h:411
KNetwork::KResolver::AddrFamily
@ AddrFamily
Definition: k3resolver.h:401
KNetwork::KResolver::UnsupportedSocketType
@ UnsupportedSocketType
Definition: k3resolver.h:409
KNetwork::KResolver::UnknownError
@ UnknownError
Definition: k3resolver.h:410
KNetwork::KResolver::UnsupportedService
@ UnsupportedService
Definition: k3resolver.h:408
KNetwork::KResolver::NoName
@ NoName
Definition: k3resolver.h:406
KNetwork::KResolver::BadFlags
@ BadFlags
Definition: k3resolver.h:404
KNetwork::KResolver::Memory
@ Memory
Definition: k3resolver.h:405
KNetwork::KResolver::NonRecoverable
@ NonRecoverable
Definition: k3resolver.h:403
KNetwork::KResolver::UnsupportedFamily
@ UnsupportedFamily
Definition: k3resolver.h:407
KNetwork::KResolver::NoError
@ NoError
Definition: k3resolver.h:400
KNetwork::KResolver::TryAgain
@ TryAgain
Definition: k3resolver.h:402
KNetwork::KResolver::protocolName
static QList< QByteArray > protocolName(int protonum)
Resolves a protocol number to its names.
Definition: k3resolver.cpp:608
KNetwork::KSocketAddress::length
quint16 length() const
Returns the length of this socket address structure.
Definition: k3socketaddress.cpp:473
KNetwork::KUnixSocketAddress
A Unix (local) socket address.
Definition: k3socketaddress.h:834
KStandardDirs::findAllResources
QStringList findAllResources(const char *type, const QString &filter=QString(), SearchOptions options=NoSearchOptions) const
Tries to find all resources with the specified type.
Definition: kstandarddirs.cpp:900
QStringList
QString
k3resolver.h
hasIPv6
static bool hasIPv6()
Definition: k3resolverstandardworkers.cpp:66
blacklistMutex
static QMutex blacklistMutex
Definition: k3resolverstandardworkers.cpp:94
mask
#define mask
k3resolverstandardworkers_p.h
k3socketaddress.h
KNetwork_initSocket
void KNetwork_initSocket()
Definition: k3socketbase.cpp:37
kdebug.h
kglobal.h
setError
static void setError(QAbstractSocket *socket, QAbstractSocket::SocketError error, const QString &errorString)
Definition: ksocketfactory.cpp:44
kstandarddirs.h
KGlobal::hasMainComponent
bool hasMainComponent()
Definition: kglobal.cpp:151
KGlobal::dirs
KStandardDirs * dirs()
Returns the application standard dirs object.
KNetwork::Internal
Definition: k3resolver.h:48
KNetwork::Internal::initStandardWorkers
void initStandardWorkers() KDE_NO_EXPORT
Definition: k3resolverstandardworkers.cpp:1038
KNetwork
A namespace to store all networking-related (socket) classes.
Definition: k3bufferedsocket.h:35
EAI_NONAME
#define EAI_NONAME
Definition: netsupp.h:233
EAI_SOCKTYPE
#define EAI_SOCKTYPE
Definition: netsupp.h:239
EAI_FAMILY
#define EAI_FAMILY
Definition: netsupp.h:224
AI_NUMERICHOST
#define AI_NUMERICHOST
Definition: netsupp.h:194
EAI_MEMORY
#define EAI_MEMORY
Definition: netsupp.h:227
EAI_BADFLAGS
#define EAI_BADFLAGS
Definition: netsupp.h:218
getaddrinfo
#define getaddrinfo
Definition: netsupp.h:304
EAI_AGAIN
#define EAI_AGAIN
Definition: netsupp.h:215
EAI_SYSTEM
#define EAI_SYSTEM
Definition: netsupp.h:242
EAI_NODATA
#define EAI_NODATA
Definition: netsupp.h:230
AI_CANONNAME
#define AI_CANONNAME
Definition: netsupp.h:193
EAI_SERVICE
#define EAI_SERVICE
Definition: netsupp.h:236
EAI_FAIL
#define EAI_FAIL
Definition: netsupp.h:221
freeaddrinfo
#define freeaddrinfo
Definition: netsupp.h:305
AI_PASSIVE
#define AI_PASSIVE
Definition: netsupp.h:192
addrinfo
Definition: netsupp.h:173
addrinfo::ai_socktype
int ai_socktype
Definition: netsupp.h:176
addrinfo::ai_protocol
int ai_protocol
Definition: netsupp.h:177
addrinfo::ai_next
struct addrinfo * ai_next
Definition: netsupp.h:181
addrinfo::ai_flags
int ai_flags
Definition: netsupp.h:174
addrinfo::ai_family
int ai_family
Definition: netsupp.h:175
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDECore

Skip menu "KDECore"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal