• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdecore
 

tdecore

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

tdecore

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

tdecore

Skip menu "tdecore"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  •     tdecore
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  • tdeioslave
  •   http
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdecore by doxygen 1.8.8
This website is maintained by Timothy Pearson.