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

KDECore

  • sources
  • kde-4.14
  • kdelibs
  • 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 
60 struct hostent;
61 struct addrinfo;
62 
63 using namespace KNetwork;
64 using namespace KNetwork::Internal;
65 
66 static 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
94 static QMutex blacklistMutex; // KDE4: change to a QReadWriteLock
95 QStringList KBlacklistWorker::blacklist;
96 
97 void 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 
111 void 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
146 bool 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 
169 bool KBlacklistWorker::preprocess()
170 {
171  if (isBlacklisted(nodeName()))
172  {
173  results.setError(KResolver::NoName);
174  finished();
175  return true;
176  }
177  return false;
178 }
179 
180 bool KBlacklistWorker::run()
181 {
182  results.setError(KResolver::NoName);
183  finished();
184  return false; // resolution failure
185 }
186 
187 namespace
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 
555 KStandardWorker::~KStandardWorker()
556 {
557  qDeleteAll(resultList);
558 }
559 
560 bool 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 
600 bool 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 
626 bool 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 
676 KResolver::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 
711 bool 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 
813 bool 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 
861 bool 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 
919 bool 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
956 KGetAddrinfoWorker::~KGetAddrinfoWorker()
957 {
958 }
959 
960 bool 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 
973 bool 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 
1016 bool 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 
1038 void 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::KIpAddress::anyhostV6
static const KIpAddress anyhostV6
the any host or undefined address in IPv6 (::)
Definition: k3socketaddress.h:401
QTextStream::setCodec
void setCodec(QTextCodec *codec)
KNetwork::Internal::KStandardWorker::postprocess
virtual bool postprocess()
This function gets called during post processing for this class.
Definition: k3resolverstandardworkers.cpp:919
KNetwork::KUnixSocketAddress
A Unix (local) socket address.
Definition: k3socketaddress.h:833
KNetwork::Internal::KBlacklistWorker::init
static void init()
Definition: k3resolverstandardworkers.cpp:97
k3socketaddress.h
QString::indexOf
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
QMutex
KNetwork::Internal::KStandardWorker::resolveService
bool resolveService()
Definition: k3resolverstandardworkers.cpp:626
KNetwork::KInetSocketAddress
an Internet socket address
Definition: k3socketaddress.h:643
QString::truncate
void truncate(int position)
KNetwork::KResolverWorkerBase::serviceName
QString serviceName() const
And this is the service name.
Definition: k3resolverworkerbase.cpp:57
kdebug.h
KNetwork::KIpAddress
An IP address.
Definition: k3socketaddress.h:62
KNetwork::KResolver::UnixFamily
Definition: k3resolver.h:338
KNetwork::KResolverWorkerBase::enqueue
bool enqueue(KResolver *other)
Enqueue the given resolver for post-processing.
Definition: k3resolverworkerbase.cpp:110
KNetwork::KResolver::SystemError
Definition: k3resolver.h:411
KNetwork::Internal::KStandardWorker::addUnix
KNetwork::KResolver::ErrorCodes addUnix()
Definition: k3resolverstandardworkers.cpp:676
QTextStream::readLine
QString readLine(qint64 maxlen)
QByteArray
KNetwork::KResolver::UnknownFamily
Definition: k3resolver.h:336
KNetwork::KResolver::UnsupportedFamily
Definition: k3resolver.h:407
EAI_MEMORY
#define EAI_MEMORY
Definition: netsupp.h:227
KNetwork::KResolverWorkerBase::protocol
int protocol() const
gets the protocol number
Definition: k3resolverworkerbase.cpp:85
KNetwork::KResolver::ErrorCodes
ErrorCodes
Error codes.
Definition: k3resolver.h:397
EAI_SOCKTYPE
#define EAI_SOCKTYPE
Definition: netsupp.h:239
EAI_NODATA
#define EAI_NODATA
Definition: netsupp.h:230
mask
#define mask
KNetwork::KResolverEntry
One resolution entry.
Definition: k3resolver.h:68
QString::prepend
QString & prepend(QChar ch)
KNetwork::KResolverWorkerFactory
Definition: k3resolverworkerbase.h:314
KNetwork::Internal::KStandardWorker::port
quint16 port
Definition: k3resolverstandardworkers_p.h:70
QByteArray::isNull
bool isNull() const
KNetwork::KResolver::NoName
Definition: k3resolver.h:406
KNetwork::Internal::initStandardWorkers
void initStandardWorkers() KDE_NO_EXPORT
Definition: k3resolverstandardworkers.cpp:1038
KGlobal::dirs
KStandardDirs * dirs()
Returns the application standard dirs object.
QByteArray::isEmpty
bool isEmpty() const
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
blacklistMutex
static QMutex blacklistMutex
Definition: k3resolverstandardworkers.cpp:94
KNetwork::KResolver::CanonName
Definition: k3resolver.h:370
KNetwork::KResolverWorkerBase::finished
void finished()
Call this function to indicate that processing has finished.
Definition: k3resolverworkerbase.cpp:100
EAI_FAMILY
#define EAI_FAMILY
Definition: netsupp.h:224
KNetwork::KResolverResults
Name and service resolution results.
Definition: k3resolver.h:212
QFile
KNetwork::Internal::KStandardWorker::resolveScopeId
bool resolveScopeId()
Definition: k3resolverstandardworkers.cpp:600
QTextStream
KNetwork::KResolverWorkerBase::flags
int flags() const
gets the flags
Definition: k3resolverworkerbase.cpp:64
setError
static void setError(QAbstractSocket *socket, QAbstractSocket::SocketError error, const QString &errorString)
Definition: ksocketfactory.cpp:44
QString::lastIndexOf
int lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
QString::isNull
bool isNull() const
KNetwork::KResolverWorkerBase::setError
void setError(int errorcode, int syserror=0)
Sets the error.
Definition: k3resolverworkerbase.h:230
KNetwork::Internal::KBlacklistWorker::blacklist
static QStringList blacklist
Definition: k3resolverstandardworkers_p.h:52
AI_CANONNAME
#define AI_CANONNAME
Definition: netsupp.h:193
KNetwork::KIpAddress::localhostV4
static const KIpAddress localhostV4
localhost in IPv4 (127.0.0.1)
Definition: k3socketaddress.h:394
kglobal.h
KNetwork_initSocket
void KNetwork_initSocket()
Definition: k3socketbase.cpp:37
QList::count
int count(const T &value) const
KNetwork::KResolver::NonRecoverable
Definition: k3resolver.h:403
QList::append
void append(const T &value)
KNetwork::Internal::KStandardWorker::~KStandardWorker
virtual ~KStandardWorker()
Definition: k3resolverstandardworkers.cpp:555
KNetwork::KInetSocketAddress::setPort
KInetSocketAddress & setPort(quint16 port)
Sets the port number.
Definition: k3socketaddress.cpp:815
AI_NUMERICHOST
#define AI_NUMERICHOST
Definition: netsupp.h:194
QString::toInt
int toInt(bool *ok, int base) const
QList::isEmpty
bool isEmpty() const
KNetwork::KResolverResults::systemError
int systemError() const
Retrieves the system error code, if any.
Definition: k3resolver.cpp:235
QString::isEmpty
bool isEmpty() const
KNetwork::KResolver::AddrFamily
Definition: k3resolver.h:401
KNetwork::KInetSocketAddress::ipVersion
int ipVersion() const
Returns the IP version of the address this object holds.
Definition: k3socketaddress.cpp:736
KNetwork::Internal::KStandardWorker::sanityCheck
bool sanityCheck()
Definition: k3resolverstandardworkers.cpp:560
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::KResolver::UnsupportedSocketType
Definition: k3resolver.h:409
QString::endsWith
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const
QList< KResolverEntry >::Iterator
typedef Iterator
QByteArray::truncate
void truncate(int pos)
QtConcurrent::run
QFuture< T > run(Function function,...)
QList::first
T & first()
QString
getaddrinfo
int getaddrinfo(const char *name, const char *serv, const struct addrinfo *hint, struct addrinfo **result)
Definition: netsupp.cpp:784
KNetwork::KIpAddress::anyhostV4
static const KIpAddress anyhostV4
the any host or undefined address in IPv4 (0.0.0.0)
Definition: k3socketaddress.h:396
KNetwork::Internal::KBlacklistWorker::run
virtual bool run()
This is the function that should be overridden in derived classes.
Definition: k3resolverstandardworkers.cpp:180
KNetwork::Internal::KStandardWorker::resolveNumerically
bool resolveNumerically()
Definition: k3resolverstandardworkers.cpp:711
KNetwork::KResolver::IPv6Family
Definition: k3resolver.h:342
QFile::open
virtual bool open(QFlags< QIODevice::OpenModeFlag > mode)
KNetwork::Internal::KStandardWorker::m_encodedName
QByteArray m_encodedName
Definition: k3resolverstandardworkers_p.h:69
QStringList
KNetwork::KInetSocketAddress::setScopeId
KInetSocketAddress & setScopeId(int scopeid)
Sets the scope id for this IPv6 object.
Definition: k3socketaddress.cpp:882
EAI_FAIL
#define EAI_FAIL
Definition: netsupp.h:221
k3resolverstandardworkers_p.h
KNetwork::KResolverWorkerBase::nodeName
QString nodeName() const
This is the hostname to be looked for.
Definition: k3resolverworkerbase.cpp:50
KNetwork::KResolver::protocolName
static QList< QByteArray > protocolName(int protonum)
Resolves a protocol number to its names.
Definition: k3resolver.cpp:608
QList::end
iterator end()
k3resolver.h
KNetwork::KInetSocketAddress::setHost
KInetSocketAddress & setHost(const KIpAddress &addr)
Sets the IP address to the given raw address.
Definition: k3socketaddress.cpp:773
QLatin1Char
AI_PASSIVE
#define AI_PASSIVE
Definition: netsupp.h:192
KNetwork::KResolver::Memory
Definition: k3resolver.h:405
KNetwork::Internal::KStandardWorker::resultList
QList< KNetwork::KResolverResults * > resultList
Definition: k3resolverstandardworkers_p.h:72
EAI_SERVICE
#define EAI_SERVICE
Definition: netsupp.h:236
EAI_SYSTEM
#define EAI_SYSTEM
Definition: netsupp.h:242
KNetwork::Internal::KStandardWorker::run
virtual bool run()
This is the function that should be overridden in derived classes.
Definition: k3resolverstandardworkers.cpp:861
KNetwork::KResolver::UnknownError
Definition: k3resolver.h:410
EAI_AGAIN
#define EAI_AGAIN
Definition: netsupp.h:215
KNetwork::KResolver::BadFlags
Definition: k3resolver.h:404
addrinfo::ai_protocol
int ai_protocol
Definition: netsupp.h:177
QString::toLatin1
QByteArray toLatin1() const
QString::mid
QString mid(int position, int n) const
KNetwork::KResolverWorkerBase::familyMask
int familyMask() const
gets the family mask
Definition: k3resolverworkerbase.cpp:71
EAI_BADFLAGS
#define EAI_BADFLAGS
Definition: netsupp.h:218
QLatin1String
KNetwork::Internal::KBlacklistWorker::loadBlacklist
static void loadBlacklist()
Definition: k3resolverstandardworkers.cpp:111
QMutexLocker
kstandarddirs.h
KNetwork::KResolverWorkerBase::socketType
int socketType() const
gets the socket type
Definition: k3resolverworkerbase.cpp:78
addrinfo::ai_socktype
int ai_socktype
Definition: netsupp.h:176
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::KSocketAddress::length
quint16 length() const
Returns the length of this socket address structure.
Definition: k3socketaddress.cpp:473
KNetwork::KResolver::Passive
Definition: k3resolver.h:369
QList::ConstIterator
typedef ConstIterator
KNetwork::KResolver::TryAgain
Definition: k3resolver.h:402
KNetwork::KResolverEntry::family
int family() const
Retrieves the family associated with this socket address.
Definition: k3resolver.cpp:147
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::NoError
Definition: k3resolver.h:400
KGlobal::hasMainComponent
bool hasMainComponent()
Definition: kglobal.cpp:151
QByteArray::data
char * data()
QString::fromLatin1
QString fromLatin1(const char *str, int size)
addrinfo::ai_next
struct addrinfo * ai_next
Definition: netsupp.h:181
KNetwork::Internal::KStandardWorker::scopeid
int scopeid
Definition: k3resolverstandardworkers_p.h:71
KNetwork::KResolverResults::setError
void setError(int errorcode, int systemerror=0)
Sets the error codes.
Definition: k3resolver.cpp:241
EAI_NONAME
#define EAI_NONAME
Definition: netsupp.h:233
KNetwork::Internal::KBlacklistWorker::isBlacklisted
static bool isBlacklisted(const QString &)
Definition: k3resolverstandardworkers.cpp:146
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
QList::constEnd
const_iterator constEnd() const
QList::constBegin
const_iterator constBegin() const
KNetwork::KResolverWorkerBase
Definition: k3resolverworkerbase.h:64
KNetwork::KResolverWorkerFactoryBase::registerNewWorker
static void registerNewWorker(KResolverWorkerFactoryBase *factory)
Wrapper call to register workers.
Definition: k3resolverworkerbase.cpp:148
addrinfo
Definition: netsupp.h:172
addrinfo::ai_flags
int ai_flags
Definition: netsupp.h:174
KNetwork::KResolverResults::error
int error() const
Retrieves the error code associated with this resolution.
Definition: k3resolver.cpp:229
KNetwork::KResolver::SocketFamilies
SocketFamilies
Address family selection types.
Definition: k3resolver.h:334
QList::begin
iterator begin()
KNetwork::KIpAddress::localhostV6
static const KIpAddress localhostV6
localhost in IPv6 (::1)
Definition: k3socketaddress.h:399
KNetwork::KResolver::IPv4Family
Definition: k3resolver.h:341
hasIPv6
static bool hasIPv6()
Definition: k3resolverstandardworkers.cpp:66
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::KResolverWorkerBase::protocolName
QByteArray protocolName() const
gets the protocol name, if applicable
Definition: k3resolverworkerbase.cpp:92
KNetwork::KResolver::UnsupportedService
Definition: k3resolver.h:408
freeaddrinfo
void freeaddrinfo(struct addrinfo *p)
Definition: netsupp.cpp:884
QString::toUInt
uint toUInt(bool *ok, int base) const
KNetwork::KResolver::NoResolve
Definition: k3resolver.h:371
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
QString::toUtf8
QByteArray toUtf8() const
addrinfo::ai_family
int ai_family
Definition: netsupp.h:175
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:22:10 by doxygen 1.8.7 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 API Reference

Skip menu "kdelibs 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

Search



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