kresolverstandardworkers.cpp
00001 /* -*- C++ -*- 00002 * Copyright (C) 2003,2004 Thiago Macieira <thiago.macieira@kdemail.net> 00003 * 00004 * 00005 * Permission is hereby granted, free of charge, to any person obtaining 00006 * a copy of this software and associated documentation files (the 00007 * "Software"), to deal in the Software without restriction, including 00008 * without limitation the rights to use, copy, modify, merge, publish, 00009 * distribute, sublicense, and/or sell copies of the Software, and to 00010 * permit persons to whom the Software is furnished to do so, subject to 00011 * the following conditions: 00012 * 00013 * The above copyright notice and this permission notice shall be included 00014 * in all copies or substantial portions of the Software. 00015 * 00016 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 00017 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00018 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00019 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 00020 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 00021 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 00022 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00023 */ 00024 00025 #include <config.h> 00026 00027 #include <sys/types.h> 00028 #include <sys/socket.h> 00029 #include <sys/un.h> 00030 #include <netinet/in.h> 00031 #include <netdb.h> 00032 #include <errno.h> 00033 #include <string.h> 00034 #include <stdlib.h> 00035 #include <unistd.h> 00036 00037 #ifdef HAVE_NET_IF_H 00038 #include <net/if.h> 00039 #endif 00040 00041 #include <tqthread.h> 00042 #include <tqmutex.h> 00043 #include <tqstrlist.h> 00044 #include <tqfile.h> 00045 00046 #include "kdebug.h" 00047 #include "tdeglobal.h" 00048 #include "kstandarddirs.h" 00049 #include "tdeapplication.h" 00050 00051 #include "kresolver.h" 00052 #include "tdesocketaddress.h" 00053 #include "kresolverstandardworkers_p.h" 00054 00055 struct hostent; 00056 struct addrinfo; 00057 00058 using namespace KNetwork; 00059 using namespace KNetwork::Internal; 00060 00061 static bool hasIPv6() 00062 { 00063 #ifndef AF_INET6 00064 return false; 00065 #else 00066 if (getenv("TDE_NO_IPV6") != 0L) 00067 return false; 00068 00069 int fd = ::socket(AF_INET6, SOCK_STREAM, 0); 00070 if (fd == -1) 00071 return false; 00072 00073 ::close(fd); 00074 return true; 00075 #endif 00076 } 00077 00078 // blacklist management 00079 static TQMutex blacklistMutex; // KDE4: change to a QReadWriteLock 00080 TQStringList KBlacklistWorker::blacklist; 00081 00082 void KBlacklistWorker::init() 00083 { 00084 // HACK! 00085 // FIXME KDE4: How do I detect there is an instance, without triggering 00086 // its creation or an assertion fault? 00087 if (!TDEGlobal::_instance) 00088 return; 00089 00090 static bool beenhere = false; 00091 00092 if (beenhere) 00093 return; 00094 00095 beenhere = true; 00096 loadBlacklist(); 00097 } 00098 00099 void KBlacklistWorker::loadBlacklist() 00100 { 00101 TQMutexLocker locker(&blacklistMutex); 00102 TQStringList filelist = TDEGlobal::dirs()->findAllResources("config", "ipv6blacklist"); 00103 00104 TQStringList::ConstIterator it = filelist.constBegin(), 00105 end = filelist.constEnd(); 00106 for ( ; it != end; ++it) 00107 { 00108 // for each file, each line is a domainname to be blacklisted 00109 TQFile f(*it); 00110 if (!f.open(IO_ReadOnly)) 00111 continue; 00112 00113 TQTextStream stream(&f); 00114 stream.setEncoding(TQTextStream::Latin1); 00115 for (TQString line = stream.readLine(); !line.isNull(); 00116 line = stream.readLine()) 00117 { 00118 if (line.isEmpty()) 00119 continue; 00120 00121 // make sure there are no surrounding whitespaces 00122 // and that it starts with . 00123 line = line.stripWhiteSpace(); 00124 if (line[0] != '.') 00125 line.prepend('.'); 00126 00127 blacklist.append(line.lower()); 00128 } 00129 } 00130 } 00131 00132 // checks the blacklist to see if the domain is listed 00133 // it matches the domain ending part 00134 bool KBlacklistWorker::isBlacklisted(const TQString& host) 00135 { 00136 KBlacklistWorker::init(); 00137 00138 // empty hostnames cannot be blacklisted 00139 if (host.isEmpty()) 00140 return false; 00141 00142 // KDE4: QLatin1String 00143 TQString ascii = TQString::fromLatin1(KResolver::domainToAscii(host)); 00144 00145 TQMutexLocker locker(&blacklistMutex); 00146 00147 // now find out if this hostname is present 00148 TQStringList::ConstIterator it = blacklist.constBegin(), 00149 end = blacklist.constEnd(); 00150 for ( ; it != end; ++it) 00151 if (ascii.endsWith(*it)) 00152 return true; 00153 00154 // no match: 00155 return false; 00156 } 00157 00158 bool KBlacklistWorker::preprocess() 00159 { 00160 if (isBlacklisted(nodeName())) 00161 { 00162 results.setError(KResolver::NoName); 00163 finished(); 00164 return true; 00165 } 00166 return false; 00167 } 00168 00169 bool KBlacklistWorker::run() 00170 { 00171 results.setError(KResolver::NoName); 00172 finished(); 00173 return false; // resolution failure 00174 } 00175 00176 namespace 00177 { 00178 /* 00179 * Note on the use of the system resolver functions: 00180 * 00181 * In all cases, we prefer to use the new getaddrinfo(3) call. That means 00182 * it will always be used if it is found. 00183 * 00184 * If it's not found, we have the option to use gethostbyname2_r, 00185 * gethostbyname_r, gethostbyname2 and gethostbyname. If gethostbyname2_r 00186 * is defined, we will use it. 00187 * 00188 * If it's not defined, we have to choose between the non-reentrant 00189 * gethostbyname2 and the reentrant but IPv4-only gethostbyname_r: 00190 * we will choose gethostbyname2 if AF_INET6 is defined. 00191 * 00192 * Lastly, gethostbyname will be used if nothing else is present. 00193 */ 00194 00195 #ifndef HAVE_GETADDRINFO 00196 00197 # if defined(HAVE_GETHOSTBYNAME2_R) 00198 # define USE_GETHOSTBYNAME2_R 00199 # elif defined(HAVE_GETHOSTBYNAME_R) && (!defined(AF_INET6) || !defined(HAVE_GETHOSTBYNAME2)) 00200 # define USE_GETHOSTBYNAME_R 00201 # elif defined(HAVE_GETHOSTBYNAME2) 00202 # define USE_GETHOSTBYNAME2) 00203 # else 00204 # define USE_GETHOSTBYNAME 00205 # endif 00206 00207 class GetHostByNameThread: public KResolverWorkerBase 00208 { 00209 public: 00210 TQCString m_hostname; // might be different! 00211 TQ_UINT16 m_port; 00212 int m_scopeid; 00213 int m_af; 00214 KResolverResults& results; 00215 00216 GetHostByNameThread(const char * hostname, TQ_UINT16 port, 00217 int scopeid, int af, KResolverResults* res) : 00218 m_hostname(hostname), m_port(port), m_scopeid(scopeid), m_af(af), 00219 results(*res) 00220 { } 00221 00222 ~GetHostByNameThread() 00223 { } 00224 00225 virtual bool preprocess() 00226 { return true; } 00227 00228 virtual bool run(); 00229 00230 void processResults(hostent* he, int my_h_errno); 00231 }; 00232 00233 bool GetHostByNameThread::run() 00234 { 00235 00236 hostent *resultptr; 00237 hostent my_results; 00238 unsigned buflen = 1024; 00239 int res; 00240 int my_h_errno; 00241 char *buf = 0L; 00242 00243 // tqDebug("ResolveThread::run(): started threaded gethostbyname for %s (af = %d)", 00244 // m_hostname.data(), m_af); 00245 00246 ResolverLocker resLock( this ); 00247 do 00248 { 00249 res = 0; 00250 my_h_errno = HOST_NOT_FOUND; 00251 00252 // check blacklist 00253 if (m_af != AF_INET && 00254 KBlacklistWorker::isBlacklisted(TQString::fromLatin1(m_hostname))) 00255 break; 00256 00257 # ifdef USE_GETHOSTBYNAME2_R 00258 buf = new char[buflen]; 00259 res = gethostbyname2_r(m_hostname, m_af, &my_results, buf, buflen, 00260 &resultptr, &my_h_errno); 00261 00262 # elif defined(USE_GETHOSTBYNAME_R) 00263 if (m_af == AF_INET) 00264 { 00265 buf = new char[buflen]; 00266 res = gethostbyname_r(m_hostname, &my_results, buf, buflen, 00267 &resultptr, &my_h_errno); 00268 } 00269 else 00270 resultptr = 0; // signal error 00271 00272 # elif defined(USE_GETHOSTBYNAME2) 00273 // must lock mutex 00274 resultptr = gethostbyname2(m_hostname, m_af); 00275 my_h_errno = h_errno; 00276 00277 # else 00278 if (m_af == AF_INET) 00279 { 00280 // must lock mutex 00281 resultptr = gethostbyname(m_hostname); 00282 my_h_errno = h_errno; 00283 } 00284 else 00285 resultptr = 0; 00286 # endif 00287 00288 if (resultptr != 0L) 00289 my_h_errno = 0; 00290 // tqDebug("GetHostByNameThread::run(): gethostbyname for %s (af = %d) returned: %d", 00291 // m_hostname.data(), m_af, my_h_errno); 00292 00293 if (res == ERANGE) 00294 { 00295 // Enlarge the buffer 00296 buflen += 1024; 00297 delete [] buf; 00298 buf = new char[buflen]; 00299 } 00300 00301 if ((res == ERANGE || my_h_errno != 0) && checkResolver()) 00302 { 00303 // resolver needs updating, so we might as well do it now 00304 resLock.openClose(); 00305 } 00306 } 00307 while (res == ERANGE); 00308 processResults(resultptr, my_h_errno); 00309 00310 delete [] buf; 00311 00312 finished(); 00313 return results.error() == KResolver::NoError; 00314 } 00315 00316 void GetHostByNameThread::processResults(hostent *he, int herrno) 00317 { 00318 if (herrno) 00319 { 00320 tqDebug("TDEStandardWorker::processResults: got error %d", herrno); 00321 switch (herrno) 00322 { 00323 case HOST_NOT_FOUND: 00324 results.setError(KResolver::NoName); 00325 return; 00326 00327 case TRY_AGAIN: 00328 results.setError(KResolver::TryAgain); 00329 return; 00330 00331 case NO_RECOVERY: 00332 results.setError(KResolver::NonRecoverable); 00333 return; 00334 00335 case NO_ADDRESS: 00336 results.setError(KResolver::NoName); 00337 return; 00338 00339 default: 00340 results.setError(KResolver::UnknownError); 00341 return; 00342 } 00343 } 00344 else if (he == 0L) 00345 { 00346 results.setError(KResolver::NoName); 00347 return; // this was an error 00348 } 00349 00350 // clear any errors 00351 setError(KResolver::NoError); 00352 results.setError(KResolver::NoError); 00353 00354 // we process results in the reverse order 00355 // that is, we prepend each result to the list of results 00356 int proto = protocol(); 00357 int socktype = socketType(); 00358 if (socktype == 0) 00359 socktype = SOCK_STREAM; // default 00360 00361 TQString canon = KResolver::domainToUnicode(TQString::fromLatin1(he->h_name)); 00362 KInetSocketAddress sa; 00363 sa.setPort(m_port); 00364 if (he->h_addrtype != AF_INET) 00365 sa.setScopeId(m_scopeid); // this will also change the socket into IPv6 00366 00367 for (int i = 0; he->h_addr_list[i]; i++) 00368 { 00369 sa.setHost(KIpAddress(he->h_addr_list[i], he->h_addrtype == AF_INET ? 4 : 6)); 00370 results.prepend(KResolverEntry(sa, socktype, proto, canon, m_hostname)); 00371 // tqDebug("TDEStandardWorker::processResults: adding %s", sa.toString().latin1()); 00372 } 00373 // tqDebug("TDEStandardWorker::processResults: added %d entries", i); 00374 } 00375 00376 #else // HAVE_GETADDRINFO 00377 00378 class GetAddrInfoThread: public KResolverWorkerBase 00379 { 00380 public: 00381 TQCString m_node; 00382 TQCString m_serv; 00383 int m_af; 00384 int m_flags; 00385 KResolverResults& results; 00386 00387 GetAddrInfoThread(const char* node, const char* serv, int af, int flags, 00388 KResolverResults* res) : 00389 m_node(node), m_serv(serv), m_af(af), m_flags(flags), results(*res) 00390 { } 00391 00392 ~GetAddrInfoThread() 00393 { } 00394 00395 virtual bool preprocess() 00396 { return true; } 00397 00398 virtual bool run(); 00399 00400 void processResults(addrinfo* ai, int ret_code, KResolverResults& rr); 00401 }; 00402 00403 bool GetAddrInfoThread::run() 00404 { 00405 // check blacklist 00406 if ((m_af != AF_INET && m_af != AF_UNSPEC) && 00407 KBlacklistWorker::isBlacklisted(TQString::fromLatin1(m_node))) 00408 { 00409 results.setError(KResolver::NoName); 00410 finished(); 00411 return false; // failed 00412 } 00413 00414 do 00415 { 00416 ResolverLocker resLock( this ); 00417 00418 // process hints 00419 addrinfo hint; 00420 memset(&hint, 0, sizeof(hint)); 00421 hint.ai_family = m_af; 00422 hint.ai_socktype = socketType(); 00423 hint.ai_protocol = protocol(); 00424 00425 if (hint.ai_socktype == 0) 00426 hint.ai_socktype = SOCK_STREAM; // default 00427 00428 if (m_flags & KResolver::Passive) 00429 hint.ai_flags |= AI_PASSIVE; 00430 if (m_flags & KResolver::CanonName) 00431 hint.ai_flags |= AI_CANONNAME; 00432 # ifdef AI_NUMERICHOST 00433 if (m_flags & KResolver::NoResolve) 00434 hint.ai_flags |= AI_NUMERICHOST; 00435 # endif 00436 # ifdef AI_ADDRCONFIG 00437 hint.ai_flags |= AI_ADDRCONFIG; 00438 # endif 00439 00440 // now we do the blocking processing 00441 if (m_node.isEmpty()) 00442 m_node = "*"; 00443 00444 addrinfo *result; 00445 int res = getaddrinfo(m_node, m_serv, &hint, &result); 00446 // kdDebug(179) << k_funcinfo << "getaddrinfo(\"" 00447 // << m_node << "\", \"" << m_serv << "\", af=" 00448 // << m_af << ") returned " << res << endl; 00449 00450 if (res != 0) 00451 { 00452 if (checkResolver()) 00453 { 00454 // resolver requires reinitialisation 00455 resLock.openClose(); 00456 continue; 00457 } 00458 00459 switch (res) 00460 { 00461 case EAI_BADFLAGS: 00462 results.setError(KResolver::BadFlags); 00463 break; 00464 00465 #ifdef EAI_NODATA 00466 // In some systems, EAI_NODATA was #define'd to EAI_NONAME which would break this case. 00467 #if EAI_NODATA != EAI_NONAME 00468 case EAI_NODATA: // it was removed in RFC 3493 00469 #endif 00470 #endif 00471 case EAI_NONAME: 00472 results.setError(KResolver::NoName); 00473 break; 00474 00475 case EAI_AGAIN: 00476 results.setError(KResolver::TryAgain); 00477 break; 00478 00479 case EAI_FAIL: 00480 results.setError(KResolver::NonRecoverable); 00481 break; 00482 00483 case EAI_FAMILY: 00484 results.setError(KResolver::UnsupportedFamily); 00485 break; 00486 00487 case EAI_SOCKTYPE: 00488 results.setError(KResolver::UnsupportedSocketType); 00489 break; 00490 00491 case EAI_SERVICE: 00492 results.setError(KResolver::UnsupportedService); 00493 break; 00494 00495 case EAI_MEMORY: 00496 results.setError(KResolver::Memory); 00497 break; 00498 00499 case EAI_SYSTEM: 00500 results.setError(KResolver::SystemError, errno); 00501 break; 00502 00503 default: 00504 results.setError(KResolver::UnknownError, errno); 00505 break; 00506 } 00507 00508 finished(); 00509 return false; // failed 00510 } 00511 00512 // if we are here, lookup succeeded 00513 TQString canon; 00514 const char *previous_canon = 0L; 00515 00516 for (addrinfo* p = result; p; p = p->ai_next) 00517 { 00518 // cache the last canon name to avoid doing the ToUnicode processing unnecessarily 00519 if ((previous_canon && !p->ai_canonname) || 00520 (!previous_canon && p->ai_canonname) || 00521 (p->ai_canonname != previous_canon && 00522 strcmp(p->ai_canonname, previous_canon) != 0)) 00523 { 00524 canon = KResolver::domainToUnicode(TQString::fromAscii(p->ai_canonname)); 00525 previous_canon = p->ai_canonname; 00526 } 00527 00528 results.append(KResolverEntry(p->ai_addr, p->ai_addrlen, p->ai_socktype, 00529 p->ai_protocol, canon, m_node)); 00530 } 00531 00532 freeaddrinfo(result); 00533 results.setError(KResolver::NoError); 00534 finished(); 00535 return results.error() == KResolver::NoError; 00536 } 00537 while (true); 00538 } 00539 00540 #endif // HAVE_GETADDRINFO 00541 } // namespace 00542 00543 bool TDEStandardWorker::sanityCheck() 00544 { 00545 // check that the requested values are sensible 00546 00547 if (!nodeName().isEmpty()) 00548 { 00549 TQString node = nodeName(); 00550 if (node.find('%') != -1) 00551 node.truncate(node.find('%')); 00552 00553 if (node.isEmpty() || node == TQString::fromLatin1("*") || 00554 node == TQString::fromLatin1("localhost")) 00555 m_encodedName.truncate(0); 00556 else 00557 { 00558 m_encodedName = KResolver::domainToAscii(node); 00559 00560 if (m_encodedName.isNull()) 00561 { 00562 tqDebug("could not encode hostname '%s' (UTF-8)", node.utf8().data()); 00563 setError(KResolver::NoName); 00564 return false; // invalid hostname! 00565 } 00566 00567 // tqDebug("Using encoded hostname '%s' for '%s' (UTF-8)", m_encodedName.data(), 00568 // node.utf8().data()); 00569 } 00570 } 00571 else 00572 m_encodedName.truncate(0); // just to be sure, but it should be clear already 00573 00574 if (protocol() == -1) 00575 { 00576 setError(KResolver::NonRecoverable); 00577 return false; // user passed invalid protocol name 00578 } 00579 00580 return true; // it's sane 00581 } 00582 00583 bool TDEStandardWorker::resolveScopeId() 00584 { 00585 // we must test the original name, not the encoded one 00586 scopeid = 0; 00587 int pos = nodeName().findRev('%'); 00588 if (pos == -1) 00589 return true; 00590 00591 TQString scopename = nodeName().mid(pos + 1); 00592 00593 bool ok; 00594 scopeid = scopename.toInt(&ok); 00595 if (!ok) 00596 { 00597 // it's not a number 00598 // therefore, it's an interface name 00599 #ifdef HAVE_IF_NAMETOINDEX 00600 scopeid = if_nametoindex(scopename.latin1()); 00601 #else 00602 scopeid = 0; 00603 #endif 00604 } 00605 00606 return true; 00607 } 00608 00609 bool TDEStandardWorker::resolveService() 00610 { 00611 // find the service first 00612 bool ok; 00613 port = serviceName().toUInt(&ok); 00614 if (!ok) 00615 { 00616 // service name does not contain a port number 00617 // must be a name 00618 00619 if (serviceName().isEmpty() || serviceName().compare(TQString::fromLatin1("*")) == 0) 00620 port = 0; 00621 else 00622 { 00623 // it's a name. We need the protocol name in order to lookup. 00624 TQCString protoname = protocolName(); 00625 00626 if (protoname.isEmpty() && protocol()) 00627 { 00628 protoname = KResolver::protocolName(protocol()).first(); 00629 00630 // if it's still empty... 00631 if (protoname.isEmpty()) 00632 { 00633 // lookup failed! 00634 setError(KResolver::NoName); 00635 return false; 00636 } 00637 } 00638 else 00639 protoname = "tcp"; 00640 00641 // it's not, so we can do a port lookup 00642 int result = KResolver::servicePort(serviceName().latin1(), protoname); 00643 if (result == -1) 00644 { 00645 // lookup failed! 00646 setError(KResolver::NoName); 00647 return false; 00648 } 00649 00650 // it worked, we have a port number 00651 port = (TQ_UINT16)result; 00652 } 00653 } 00654 00655 // we found a port 00656 return true; 00657 } 00658 00659 KResolver::ErrorCodes TDEStandardWorker::addUnix() 00660 { 00661 // before trying to add, see if the user wants Unix sockets 00662 if ((familyMask() & KResolver::UnixFamily) == 0) 00663 // no, Unix sockets are not wanted 00664 return KResolver::UnsupportedFamily; 00665 00666 // now check if the requested data are good for a Unix socket 00667 if (!m_encodedName.isEmpty()) 00668 return KResolver::AddrFamily; // non local hostname 00669 00670 if (protocol() || !protocolName().isEmpty()) 00671 return KResolver::BadFlags; // cannot have Unix sockets with protocols 00672 00673 TQString pathname = serviceName(); 00674 if (pathname.isEmpty()) 00675 return KResolver::NoName;; // no path? 00676 00677 if (pathname[0] != '/') 00678 // non absolute pathname 00679 // put it in /tmp 00680 pathname.prepend("/tmp/"); 00681 00682 // tqDebug("QNoResolveWorker::addUnix(): adding Unix socket for %s", pathname.local8Bit().data()); 00683 KUnixSocketAddress sa(pathname); 00684 int socktype = socketType(); 00685 if (socktype == 0) 00686 socktype = SOCK_STREAM; // default 00687 00688 results.append(KResolverEntry(sa, socktype, 0)); 00689 setError(KResolver::NoError); 00690 00691 return KResolver::NoError; 00692 } 00693 00694 bool TDEStandardWorker::resolveNumerically() 00695 { 00696 // if the NoResolve flag is active, our result from this point forward 00697 // will always be true, even if the resolution failed. 00698 // that indicates that our result is authoritative. 00699 00700 bool wantV4 = familyMask() & KResolver::IPv4Family, 00701 wantV6 = familyMask() & KResolver::IPv6Family; 00702 00703 if (!wantV6 && !wantV4) 00704 // no Internet address is wanted! 00705 return (flags() & KResolver::NoResolve); 00706 00707 // now try to find results 00708 if (!resolveScopeId() || !resolveService()) 00709 return (flags() & KResolver::NoResolve); 00710 00711 // we have scope IDs and port numbers 00712 // now try to resolve the hostname numerically 00713 KInetSocketAddress sa; 00714 setError(KResolver::NoError); 00715 sa.setHost(KIpAddress(TQString::fromLatin1(m_encodedName))); 00716 00717 // if it failed, the length was reset to 0 00718 bool ok = sa.length() != 0; 00719 00720 sa.setPort(port); 00721 if (sa.ipVersion() == 6) 00722 sa.setScopeId(scopeid); 00723 int proto = protocol(); 00724 int socktype = socketType(); 00725 if (socktype == 0) 00726 socktype = SOCK_STREAM; 00727 00728 if (ok) 00729 { 00730 // the given hostname was successfully converted to an IP address 00731 // check if the user wanted this kind of address 00732 00733 if ((sa.ipVersion() == 4 && wantV4) || 00734 (sa.ipVersion() == 6 && wantV6)) 00735 results.append(KResolverEntry(sa, socktype, proto)); 00736 else 00737 { 00738 // Note: the address *IS* a numeric IP 00739 // but it's not of the kind the user asked for 00740 // 00741 // that means that it cannot be a Unix socket (because it's an IP) 00742 // and that means that no resolution will tell us otherwise 00743 // 00744 // This is a failed resolution 00745 00746 setError(KResolver::AddrFamily); 00747 return true; 00748 } 00749 } 00750 else if (m_encodedName.isEmpty()) 00751 { 00752 // user wanted localhost 00753 if (flags() & KResolver::Passive) 00754 { 00755 if (wantV6) 00756 { 00757 sa.setHost(KIpAddress::anyhostV6); 00758 results.append(KResolverEntry(sa, socktype, proto)); 00759 } 00760 00761 if (wantV4) 00762 { 00763 sa.setHost(KIpAddress::anyhostV4); 00764 results.append(KResolverEntry(sa, socktype, proto)); 00765 } 00766 } 00767 else 00768 { 00769 if (wantV6) 00770 { 00771 sa.setHost(KIpAddress::localhostV6); 00772 results.append(KResolverEntry(sa, socktype, proto)); 00773 } 00774 00775 if (wantV4) 00776 { 00777 sa.setHost(KIpAddress::localhostV4); 00778 results.append(KResolverEntry(sa, socktype, proto)); 00779 } 00780 } 00781 00782 ok = true; 00783 } 00784 else 00785 { 00786 // probably bad flags, since the address is not convertible without 00787 // resolution 00788 00789 setError(KResolver::BadFlags); 00790 ok = false; 00791 } 00792 00793 return ok || (flags() & KResolver::NoResolve); 00794 } 00795 00796 bool TDEStandardWorker::preprocess() 00797 { 00798 // check sanity 00799 if (!sanityCheck()) 00800 return false; 00801 00802 // this worker class can only handle known families 00803 if (familyMask() & KResolver::UnknownFamily) 00804 { 00805 setError(KResolver::UnsupportedFamily); 00806 return false; // we don't know about this 00807 } 00808 00809 // check the socket types 00810 if (socketType() != SOCK_STREAM && socketType() != SOCK_DGRAM && socketType() != 0) 00811 { 00812 setError(KResolver::UnsupportedSocketType); 00813 return false; 00814 } 00815 00816 // check if we can resolve all numerically 00817 // resolveNumerically always returns true if the NoResolve flag is set 00818 if (resolveNumerically() || m_encodedName.isEmpty()) 00819 { 00820 // indeed, we have resolved numerically 00821 setError(addUnix()); 00822 if (results.count()) 00823 setError(KResolver::NoError); 00824 finished(); 00825 return true; 00826 } 00827 00828 // check if the user wants something we know about 00829 #ifdef AF_INET6 00830 # define mask (KResolver::IPv6Family | KResolver::IPv4Family | KResolver::UnixFamily) 00831 #else 00832 # define mask (KResolver::IPv4Family | KResolver::UnixFamily) 00833 #endif 00834 00835 if ((familyMask() & mask) == 0) 00836 // errr... nothing we know about 00837 return false; 00838 00839 #undef mask 00840 00841 return true; // it's ok 00842 } 00843 00844 bool TDEStandardWorker::run() 00845 { 00846 #ifndef HAVE_GETADDRINFO 00847 // check the scope id first 00848 // since most of the resolutions won't have a scope id, this should be fast 00849 // and we won't have wasted time on services if this fails 00850 if (!resolveScopeId()) 00851 return false; 00852 00853 // resolve the service now, before entering the blocking operation 00854 if (!resolveService()) 00855 return false; 00856 #endif 00857 00858 // good 00859 // now we need the hostname 00860 setError(KResolver::NoName); 00861 00862 // these are the family types that we know of 00863 struct 00864 { 00865 KResolver::SocketFamilies mask; 00866 int af; 00867 } families[] = { { KResolver::IPv4Family, AF_INET } 00868 #ifdef AF_INET6 00869 , { KResolver::IPv6Family, AF_INET6 } 00870 #endif 00871 }; 00872 int familyCount = sizeof(families)/sizeof(families[0]); 00873 bool skipIPv6 = !hasIPv6(); 00874 resultList.setAutoDelete(true); 00875 00876 for (int i = 0; i < familyCount; i++) 00877 if (familyMask() & families[i].mask) 00878 { 00879 #ifdef AF_INET6 00880 if (skipIPv6 && families[i].af == AF_INET6) 00881 continue; 00882 #endif 00883 00884 KResolverWorkerBase *worker; 00885 KResolverResults *res = new KResolverResults; 00886 resultList.append(res); 00887 #ifdef HAVE_GETADDRINFO 00888 worker = new GetAddrInfoThread(m_encodedName, 00889 serviceName().latin1(), 00890 families[i].af, flags(), res); 00891 #else 00892 worker = new GetHostByNameThread(m_encodedName, port, scopeid, 00893 families[i].af, res); 00894 #endif 00895 00896 enqueue(worker); 00897 } 00898 00899 // not finished 00900 return true; 00901 } 00902 00903 bool TDEStandardWorker::postprocess() 00904 { 00905 if (results.count()) 00906 return true; // no need 00907 // now copy over what we need from the underlying results 00908 00909 // start backwards because IPv6 was launched later (if at all) 00910 if (resultList.isEmpty()) 00911 { 00912 results.setError(KResolver::NoName); 00913 return true; 00914 } 00915 00916 KResolverResults *rr = resultList.last(); 00917 while (rr) 00918 { 00919 if (!rr->isEmpty()) 00920 { 00921 results.setError(KResolver::NoError); 00922 KResolverResults::Iterator it = rr->begin(); 00923 for ( ; it != rr->end(); ++it) 00924 results.append(*it); 00925 } 00926 else if (results.isEmpty()) 00927 // this generated an error 00928 // copy the error code over 00929 setError(rr->error(), rr->systemError()); 00930 00931 rr = resultList.prev(); 00932 } 00933 00934 resultList.clear(); 00935 return true; 00936 } 00937 00938 #ifdef HAVE_GETADDRINFO 00939 KGetAddrinfoWorker::~KGetAddrinfoWorker() 00940 { 00941 } 00942 00943 bool KGetAddrinfoWorker::preprocess() 00944 { 00945 // getaddrinfo(3) can always handle any kind of request that makes sense 00946 if (!sanityCheck()) 00947 return false; 00948 00949 if (flags() & KResolver::NoResolve) 00950 // oops, numeric resolution? 00951 return run(); 00952 00953 return true; 00954 } 00955 00956 bool KGetAddrinfoWorker::run() 00957 { 00958 // make an AF_UNSPEC getaddrinfo(3) call 00959 GetAddrInfoThread worker(m_encodedName, serviceName().latin1(), 00960 AF_UNSPEC, flags(), &results); 00961 00962 if (!worker.run()) 00963 { 00964 if (wantThis(AF_UNIX)) 00965 { 00966 if (addUnix() == KResolver::NoError) 00967 setError(KResolver::NoError); 00968 } 00969 else 00970 setError(worker.results.error(), worker.results.systemError()); 00971 00972 return false; 00973 } 00974 00975 // The worker has finished working 00976 // now copy over only what we may want 00977 // keep track of any Unix-domain sockets 00978 00979 bool seen_unix = false; 00980 KResolverResults::Iterator it = results.begin(); 00981 for ( ; it != results.end(); ) 00982 { 00983 if ((*it).family() == AF_UNIX) 00984 seen_unix = true; 00985 if (!wantThis((*it).family())) 00986 it = results.remove(it); 00987 else 00988 ++it; 00989 } 00990 00991 if (!seen_unix) 00992 addUnix(); 00993 00994 finished(); 00995 return true; 00996 } 00997 00998 bool KGetAddrinfoWorker::wantThis(int family) 00999 { 01000 // tells us if the user wants a socket of this family 01001 01002 #ifdef AF_INET6 01003 if (family == AF_INET6 && familyMask() & KResolver::IPv6Family) 01004 return true; 01005 #endif 01006 if (family == AF_INET && familyMask() & KResolver::IPv4Family) 01007 return true; 01008 if (family == AF_UNIX && familyMask() & KResolver::UnixFamily) 01009 return true; 01010 01011 // it's not a family we know about... 01012 if (familyMask() & KResolver::UnknownFamily) 01013 return true; 01014 01015 return false; 01016 } 01017 01018 #endif 01019 01020 void KNetwork::Internal::initStandardWorkers() 01021 { 01022 //KResolverWorkerFactoryBase::registerNewWorker(new KResolverWorkerFactory<KBlacklistWorker>); 01023 KResolverWorkerFactoryBase::registerNewWorker(new KResolverWorkerFactory<TDEStandardWorker>); 01024 01025 #ifdef HAVE_GETADDRINFO 01026 KResolverWorkerFactoryBase::registerNewWorker(new KResolverWorkerFactory<KGetAddrinfoWorker>); 01027 #endif 01028 }