• 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 "tdestandarddirs.h"
49#include "tdeapplication.h"
50
51#include "kresolver.h"
52#include "tdesocketaddress.h"
53#include "kresolverstandardworkers_p.h"
54
55struct hostent;
56struct addrinfo;
57
58using namespace KNetwork;
59using namespace KNetwork::Internal;
60
61static 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
79static TQMutex blacklistMutex; // KDE4: change to a QReadWriteLock
80TQStringList KBlacklistWorker::blacklist;
81
82void 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
99void 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
134bool 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
158bool KBlacklistWorker::preprocess()
159{
160 if (isBlacklisted(nodeName()))
161 {
162 results.setError(KResolver::NoName);
163 finished();
164 return true;
165 }
166 return false;
167}
168
169bool KBlacklistWorker::run()
170{
171 results.setError(KResolver::NoName);
172 finished();
173 return false; // resolution failure
174}
175
176namespace
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
543bool 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
583bool 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
609bool 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
659KResolver::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
694bool 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
796bool 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
844bool 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
903bool 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
939KGetAddrinfoWorker::~KGetAddrinfoWorker()
940{
941}
942
943bool 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
956bool 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
998bool 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
1020void 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::KInetSocketAddress
an Internet socket address
Definition: tdesocketaddress.h:652
KNetwork::KInetSocketAddress::setPort
KInetSocketAddress & setPort(TQ_UINT16 port)
Sets the port number.
Definition: tdesocketaddress.cpp:852
KNetwork::KInetSocketAddress::setScopeId
KInetSocketAddress & setScopeId(int scopeid)
Sets the scope id for this IPv6 object.
Definition: tdesocketaddress.cpp:923
KNetwork::KInetSocketAddress::ipVersion
int ipVersion() const
Returns the IP version of the address this object holds.
Definition: tdesocketaddress.cpp:761
KNetwork::KInetSocketAddress::setHost
KInetSocketAddress & setHost(const KIpAddress &addr)
Sets the IP address to the given raw address.
Definition: tdesocketaddress.cpp:806
KNetwork::KIpAddress
An IP address.
Definition: tdesocketaddress.h:63
KNetwork::KResolverEntry
One resolution entry.
Definition: kresolver.h:67
KNetwork::KResolverResults
Name and service resolution results.
Definition: kresolver.h:198
KNetwork::KResolverResults::systemError
int systemError() const
Retrieves the system error code, if any.
Definition: kresolver.cpp:253
KNetwork::KResolverResults::error
int error() const
Retrieves the error code associated with this resolution.
Definition: kresolver.cpp:247
KNetwork::KResolverResults::setError
void setError(int errorcode, int systemerror=0)
Sets the error codes.
Definition: kresolver.cpp:259
KNetwork::KResolver::SocketFamilies
SocketFamilies
Address family selection types.
Definition: kresolver.h:319
KNetwork::KResolver::ErrorCodes
ErrorCodes
Error codes.
Definition: kresolver.h:384
KNetwork::KUnixSocketAddress
A Unix (local) socket address.
Definition: tdesocketaddress.h:841
KNetwork::TDESocketAddress::length
TQ_UINT16 length() const
Returns the length of this socket address structure.
Definition: tdesocketaddress.cpp:485
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: tdestandarddirs.cpp:679
KNetwork
A namespace to store all networking-related (socket) classes.
Definition: kbufferedsocket.h:36
TDEStdAccel::end
const TDEShortcut & end()
Goto end of the document.
Definition: tdestdaccel.cpp:289

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
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdecore by doxygen 1.9.4
This website is maintained by Timothy Pearson.