00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
00036 #ifdef HAVE_NET_IF_H
00037 #include <net/if.h>
00038 #endif
00039
00040 #include <qthread.h>
00041 #include <qmutex.h>
00042 #include <qstrlist.h>
00043
00044 #include "kresolver.h"
00045 #include "ksocketaddress.h"
00046 #include "kresolver_p.h"
00047 #include "kresolverstandardworkers_p.h"
00048
00049 struct hostent;
00050 struct addrinfo;
00051
00052 using namespace KNetwork;
00053 using namespace KNetwork::Internal;
00054
00055 namespace
00056 {
00057 #ifndef HAVE_GETADDRINFO
00058 class GetHostByNameThread: public KResolverWorkerBase
00059 {
00060 public:
00061 QCString m_hostname;
00062 Q_UINT16 m_port;
00063 int m_scopeid;
00064 int m_af;
00065 KResolverResults& results;
00066
00067 GetHostByNameThread(const char * hostname, Q_UINT16 port,
00068 int scopeid, int af, KResolverResults* res) :
00069 m_hostname(hostname), m_port(port), m_scopeid(scopeid), m_af(af),
00070 results(*res)
00071 { }
00072
00073 ~GetHostByNameThread()
00074 { }
00075
00076 virtual bool preprocess()
00077 { return true; }
00078
00079 virtual bool run();
00080
00081 void processResults(hostent* he, int my_h_errno);
00082 };
00083
00084 bool GetHostByNameThread::run()
00085 {
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110 hostent *resultptr;
00111 hostent my_results;
00112 unsigned buflen = 1024;
00113 int res;
00114 int my_h_errno;
00115 char *buf = 0L;
00116
00117
00118
00119 do
00120 {
00121 res = 0;
00122 my_h_errno = HOST_NOT_FOUND;
00123
00124 # ifdef HAVE_GETHOSTBYNAME2_R
00125 buf = new char[buflen];
00126 res = gethostbyname2_r(m_hostname, m_af, &my_results, buf, buflen,
00127 &resultptr, &my_h_errno);
00128
00129 # elif defined(HAVE_GETHOSTBYNAME_R) && (!defined(AF_INET6) || !defined(HAVE_GETHOSTBYNAME2))
00130 if (m_af == AF_INET)
00131 {
00132 buf = new char[buflen];
00133 res = gethostbyname_r(m_hostname, &my_results, buf, buflen,
00134 &resultptr, &my_h_errno);
00135 }
00136 else
00137 resultptr = 0;
00138
00139 # elif defined(HAVE_GETHOSTBYNAME2)
00140
00141 QMutexLocker locker(&getXXbyYYmutex);
00142 resultptr = gethostbyname2(m_hostname, m_af);
00143 my_h_errno = h_errno;
00144
00145 # else
00146 if (m_af == AF_INET)
00147 {
00148
00149 QMutexLocker locker(&getXXbyYYmutex);
00150 resultptr = gethostbyname(m_hostname);
00151 my_h_errno = h_errno;
00152 }
00153 else
00154 resultptr = 0;
00155 # endif
00156
00157 if (resultptr != 0L)
00158 my_h_errno = 0;
00159
00160
00161
00162 if (res == ERANGE)
00163 {
00164
00165 buflen += 1024;
00166 delete [] buf;
00167 buf = new char[buflen];
00168 }
00169 }
00170 while (res == ERANGE);
00171 processResults(resultptr, my_h_errno);
00172
00173 delete [] buf;
00174
00175 finished();
00176 return results.error() == KResolver::NoError;
00177 }
00178
00179 void GetHostByNameThread::processResults(hostent *he, int herrno)
00180 {
00181 if (herrno)
00182 {
00183 qDebug("KStandardWorker::processResults: got error %d", herrno);
00184 switch (herrno)
00185 {
00186 case HOST_NOT_FOUND:
00187 results.setError(KResolver::NoName);
00188 return;
00189
00190 case TRY_AGAIN:
00191 results.setError(KResolver::TryAgain);
00192 return;
00193
00194 case NO_RECOVERY:
00195 results.setError(KResolver::NonRecoverable);
00196 return;
00197
00198 case NO_ADDRESS:
00199 results.setError(KResolver::NoName);
00200 return;
00201
00202 default:
00203 results.setError(KResolver::UnknownError);
00204 return;
00205 }
00206 }
00207 else if (he == 0L)
00208 {
00209 results.setError(KResolver::NoName);
00210 return;
00211 }
00212
00213
00214 setError(KResolver::NoError);
00215 results.setError(KResolver::NoError);
00216
00217
00218
00219 int proto = protocol();
00220 int socktype = socketType();
00221 if (socktype == 0)
00222 socktype = SOCK_STREAM;
00223
00224 QString canon = KResolver::domainToUnicode(QString::fromLatin1(he->h_name));
00225 KInetSocketAddress sa;
00226 sa.setPort(m_port);
00227 if (he->h_addrtype != AF_INET)
00228 sa.setScopeId(m_scopeid);
00229
00230 for (int i = 0; he->h_addr_list[i]; i++)
00231 {
00232 sa.setHost(KIpAddress(he->h_addr_list[i], he->h_addrtype == AF_INET ? 4 : 6));
00233 results.prepend(KResolverEntry(sa, socktype, proto, canon, m_hostname));
00234
00235 }
00236
00237 }
00238
00239 #else // HAVE_GETADDRINFO
00240
00241 class GetAddrInfoThread: public KResolverWorkerBase
00242 {
00243 public:
00244 QCString m_node;
00245 QCString m_serv;
00246 int m_af;
00247 KResolverResults& results;
00248
00249 GetAddrInfoThread(const char* node, const char* serv, int af,
00250 KResolverResults* res) :
00251 m_node(node), m_serv(serv), m_af(af), results(*res)
00252 { }
00253
00254 ~GetAddrInfoThread()
00255 { }
00256
00257 virtual bool preprocess()
00258 { return true; }
00259
00260 virtual bool run();
00261
00262 void processResults(addrinfo* ai, int ret_code, KResolverResults& rr);
00263 };
00264
00265 bool GetAddrInfoThread::run()
00266 {
00267 # ifdef NEED_MUTEX
00268
00269
00270
00271
00272 QMutexLocker locker(&getXXbyYYmutex);
00273 # endif
00274
00275
00276 addrinfo hint;
00277 memset(&hint, 0, sizeof(hint));
00278 hint.ai_family = m_af;
00279 hint.ai_socktype = socketType();
00280 hint.ai_protocol = protocol();
00281
00282 if (hint.ai_socktype == 0)
00283 hint.ai_socktype = SOCK_STREAM;
00284
00285 if (flags() & KResolver::Passive)
00286 hint.ai_flags |= AI_PASSIVE;
00287 if (flags() & KResolver::CanonName)
00288 hint.ai_flags |= AI_CANONNAME;
00289 # ifdef AI_NUMERICHOST
00290 if (flags() & KResolver::NoResolve)
00291 hint.ai_flags |= AI_NUMERICHOST;
00292 # endif
00293
00294
00295 if (m_node.isEmpty())
00296 m_node = "*";
00297
00298 addrinfo *result;
00299 int res = getaddrinfo(m_node, m_serv, &hint, &result);
00300
00301
00302
00303 if (res != 0)
00304 {
00305 switch (res)
00306 {
00307 case EAI_BADFLAGS:
00308 results.setError(KResolver::BadFlags);
00309 break;
00310
00311 #ifdef EAI_NODATA
00312
00313 #if EAI_NODATA != EAI_NONAME
00314 case EAI_NODATA:
00315 #endif
00316 #endif
00317 case EAI_NONAME:
00318 results.setError(KResolver::NoName);
00319 break;
00320
00321 case EAI_AGAIN:
00322 results.setError(KResolver::TryAgain);
00323 break;
00324
00325 case EAI_FAIL:
00326 results.setError(KResolver::NonRecoverable);
00327 break;
00328
00329 case EAI_FAMILY:
00330 results.setError(KResolver::UnsupportedFamily);
00331 break;
00332
00333 case EAI_SOCKTYPE:
00334 results.setError(KResolver::UnsupportedSocketType);
00335 break;
00336
00337 case EAI_SERVICE:
00338 results.setError(KResolver::UnsupportedService);
00339 break;
00340
00341 case EAI_MEMORY:
00342 results.setError(KResolver::Memory);
00343 break;
00344
00345 case EAI_SYSTEM:
00346 results.setError(KResolver::SystemError, errno);
00347 break;
00348
00349 default:
00350 results.setError(KResolver::UnknownError, errno);
00351 break;
00352 }
00353
00354 finished();
00355 return false;
00356 }
00357
00358
00359 QString canon;
00360 const char *previous_canon = 0L;
00361
00362 for (addrinfo* p = result; p; p = p->ai_next)
00363 {
00364
00365 if ((previous_canon && !p->ai_canonname) ||
00366 (!previous_canon && p->ai_canonname) ||
00367 (p->ai_canonname != previous_canon &&
00368 strcmp(p->ai_canonname, previous_canon) != 0))
00369 {
00370 canon = KResolver::domainToUnicode(QString::fromAscii(p->ai_canonname));
00371 previous_canon = p->ai_canonname;
00372 }
00373
00374 results.append(KResolverEntry(p->ai_addr, p->ai_addrlen, p->ai_socktype,
00375 p->ai_protocol, canon, m_node));
00376 }
00377
00378 freeaddrinfo(result);
00379 results.setError(KResolver::NoError);
00380 finished();
00381 return results.error() == KResolver::NoError;
00382 }
00383
00384 #endif // HAVE_GETADDRINFO
00385 }
00386
00387 bool KStandardWorker::sanityCheck()
00388 {
00389
00390
00391 if (!nodeName().isEmpty())
00392 {
00393 QString node = nodeName();
00394 if (node.find('%') != -1)
00395 node.truncate(node.find('%'));
00396
00397 if (node.isEmpty() || node == QString::fromLatin1("*") ||
00398 node == QString::fromLatin1("localhost"))
00399 m_encodedName.truncate(0);
00400 else
00401 {
00402 m_encodedName = KResolver::domainToAscii(node);
00403
00404 if (m_encodedName.isNull())
00405 {
00406 qDebug("could not encode hostname '%s' (UTF-8)", node.utf8().data());
00407 setError(KResolver::NoName);
00408 return false;
00409 }
00410
00411
00412
00413 }
00414 }
00415 else
00416 m_encodedName.truncate(0);
00417
00418 if (protocol() == -1)
00419 {
00420 setError(KResolver::NonRecoverable);
00421 return false;
00422 }
00423
00424 return true;
00425 }
00426
00427 bool KStandardWorker::resolveScopeId()
00428 {
00429
00430 scopeid = 0;
00431 int pos = nodeName().findRev('%');
00432 if (pos == -1)
00433 return true;
00434
00435 QString scopename = nodeName().mid(pos + 1);
00436
00437 bool ok;
00438 scopeid = scopename.toInt(&ok);
00439 if (!ok)
00440 {
00441
00442
00443 #ifdef HAVE_IF_NAMETOINDEX
00444 scopeid = if_nametoindex(scopename.latin1());
00445 #else
00446 scopeid = 0;
00447 #endif
00448 }
00449
00450 return true;
00451 }
00452
00453 bool KStandardWorker::resolveService()
00454 {
00455
00456 bool ok;
00457 port = serviceName().toUInt(&ok);
00458 if (!ok)
00459 {
00460
00461
00462
00463 if (serviceName().isEmpty() || serviceName().compare(QString::fromLatin1("*")) == 0)
00464 port = 0;
00465 else
00466 {
00467
00468 QCString protoname = protocolName();
00469
00470 if (protoname.isEmpty() && protocol())
00471 {
00472 protoname = KResolver::protocolName(protocol()).first();
00473
00474
00475 if (protoname.isEmpty())
00476 {
00477
00478 setError(KResolver::NoName);
00479 return false;
00480 }
00481 }
00482 else
00483 protoname = "tcp";
00484
00485
00486 int result = KResolver::servicePort(serviceName().latin1(), protoname);
00487 if (result == -1)
00488 {
00489
00490 setError(KResolver::NoName);
00491 return false;
00492 }
00493
00494
00495 port = (Q_UINT16)result;
00496 }
00497 }
00498
00499
00500 return true;
00501 }
00502
00503 KResolver::ErrorCodes KStandardWorker::addUnix()
00504 {
00505
00506 if ((familyMask() & KResolver::UnixFamily) == 0)
00507
00508 return KResolver::UnsupportedFamily;
00509
00510
00511 if (!m_encodedName.isEmpty())
00512 return KResolver::AddrFamily;
00513
00514 if (protocol() || protocolName())
00515 return KResolver::BadFlags;
00516
00517 QString pathname = serviceName();
00518 if (pathname.isEmpty())
00519 return KResolver::NoName;;
00520
00521 if (pathname[0] != '/')
00522
00523
00524 pathname.prepend("/tmp/");
00525
00526
00527 KUnixSocketAddress sa(pathname);
00528 int socktype = socketType();
00529 if (socktype == 0)
00530 socktype = SOCK_STREAM;
00531
00532 results.append(KResolverEntry(sa, socktype, 0));
00533 setError(KResolver::NoError);
00534
00535 return KResolver::NoError;
00536 }
00537
00538 bool KStandardWorker::resolveNumerically()
00539 {
00540
00541
00542
00543
00544 bool wantV4 = familyMask() & KResolver::IPv4Family,
00545 wantV6 = familyMask() & KResolver::IPv6Family;
00546
00547 if (!wantV6 && !wantV4)
00548
00549 return (flags() & KResolver::NoResolve);
00550
00551
00552 if (!resolveScopeId() || !resolveService())
00553 return (flags() & KResolver::NoResolve);
00554
00555
00556
00557 KInetSocketAddress sa;
00558 setError(KResolver::NoError);
00559 sa.setHost(KIpAddress(QString::fromLatin1(m_encodedName)));
00560
00561
00562 bool ok = sa.length() != 0;
00563
00564 sa.setPort(port);
00565 if (sa.ipVersion() == 6)
00566 sa.setScopeId(scopeid);
00567 int proto = protocol();
00568 int socktype = socketType();
00569 if (socktype == 0)
00570 socktype = SOCK_STREAM;
00571
00572 if (ok)
00573 {
00574
00575
00576
00577 if ((sa.ipVersion() == 4 && wantV4) ||
00578 (sa.ipVersion() == 6 && wantV6))
00579 results.append(KResolverEntry(sa, socktype, proto));
00580 else
00581 {
00582
00583
00584
00585
00586
00587
00588
00589
00590 setError(KResolver::AddrFamily);
00591 return true;
00592 }
00593 }
00594 else if (m_encodedName.isEmpty())
00595 {
00596
00597 if (flags() & KResolver::Passive)
00598 {
00599 if (wantV6)
00600 {
00601 sa.setHost(KIpAddress::anyhostV6);
00602 results.append(KResolverEntry(sa, socktype, proto));
00603 }
00604
00605 if (wantV4)
00606 {
00607 sa.setHost(KIpAddress::anyhostV4);
00608 results.append(KResolverEntry(sa, socktype, proto));
00609 }
00610 }
00611 else
00612 {
00613 if (wantV6)
00614 {
00615 sa.setHost(KIpAddress::localhostV6);
00616 results.append(KResolverEntry(sa, socktype, proto));
00617 }
00618
00619 if (wantV4)
00620 {
00621 sa.setHost(KIpAddress::localhostV4);
00622 results.append(KResolverEntry(sa, socktype, proto));
00623 }
00624 }
00625
00626 ok = true;
00627 }
00628 else
00629 {
00630
00631
00632
00633 setError(KResolver::BadFlags);
00634 ok = false;
00635 }
00636
00637 return ok || (flags() & KResolver::NoResolve);
00638 }
00639
00640 bool KStandardWorker::preprocess()
00641 {
00642
00643 if (!sanityCheck())
00644 return false;
00645
00646
00647 if (familyMask() & KResolver::UnknownFamily)
00648 {
00649 setError(KResolver::UnsupportedFamily);
00650 return false;
00651 }
00652
00653
00654 if (socketType() != SOCK_STREAM && socketType() != SOCK_DGRAM && socketType() != 0)
00655 {
00656 setError(KResolver::UnsupportedSocketType);
00657 return false;
00658 }
00659
00660
00661
00662 if (resolveNumerically() || m_encodedName.isEmpty())
00663 {
00664
00665 setError(addUnix());
00666 if (results.count())
00667 setError(KResolver::NoError);
00668 finished();
00669 return true;
00670 }
00671
00672
00673 #ifdef AF_INET6
00674 # define mask (KResolver::IPv6Family | KResolver::IPv4Family | KResolver::UnixFamily)
00675 #else
00676 # define mask (KResolver::IPv4Family | KResolver::UnixFamily)
00677 #endif
00678
00679 if ((familyMask() & mask) == 0)
00680
00681 return false;
00682
00683 #undef mask
00684
00685 return true;
00686 }
00687
00688 bool KStandardWorker::run()
00689 {
00690 #ifndef HAVE_GETADDRINFO
00691
00692
00693
00694 if (!resolveScopeId())
00695 return false;
00696
00697
00698 if (!resolveService())
00699 return false;
00700 #endif
00701
00702
00703
00704 setError(KResolver::NoName);
00705
00706
00707 struct
00708 {
00709 KResolver::SocketFamilies mask;
00710 int af;
00711 } families[] = { { KResolver::IPv4Family, AF_INET }
00712 #ifdef AF_INET6
00713 , { KResolver::IPv6Family, AF_INET6 }
00714 #endif
00715 };
00716 int familyCount = sizeof(families)/sizeof(families[0]);
00717 bool skipIPv6 = false;
00718 if (getenv("KDE_NO_IPV6"))
00719 skipIPv6 = true;
00720 resultList.setAutoDelete(true);
00721
00722 for (int i = 0; i < familyCount; i++)
00723 if (familyMask() & families[i].mask)
00724 {
00725 #ifdef AF_INET6
00726 if (skipIPv6 && families[i].af == AF_INET6)
00727 continue;
00728 #endif
00729
00730 KResolverWorkerBase *worker;
00731 KResolverResults *res = new KResolverResults;
00732 resultList.append(res);
00733 #ifdef HAVE_GETADDRINFO
00734 worker = new GetAddrInfoThread(m_encodedName,
00735 serviceName().latin1(),
00736 families[i].af, res);
00737 #else
00738 worker = new GetHostByNameThread(m_encodedName, port, scopeid,
00739 families[i].af, res);
00740 #endif
00741
00742 enqueue(worker);
00743 }
00744
00745
00746 return true;
00747 }
00748
00749 bool KStandardWorker::postprocess()
00750 {
00751 if (results.count())
00752 return true;
00753
00754
00755
00756 if (resultList.isEmpty())
00757 {
00758 results.setError(KResolver::NoName);
00759 return true;
00760 }
00761
00762 KResolverResults *rr = resultList.last();
00763 while (rr)
00764 {
00765 if (!rr->isEmpty())
00766 {
00767 results.setError(KResolver::NoError);
00768 KResolverResults::Iterator it = rr->begin();
00769 for ( ; it != rr->end(); ++it)
00770 results.append(*it);
00771 }
00772 else if (results.isEmpty())
00773
00774
00775 setError(rr->error(), rr->systemError());
00776
00777 rr = resultList.prev();
00778 }
00779
00780 resultList.clear();
00781 return true;
00782 }
00783
00784 #ifdef HAVE_GETADDRINFO
00785 KGetAddrinfoWorker::~KGetAddrinfoWorker()
00786 {
00787 }
00788
00789 bool KGetAddrinfoWorker::preprocess()
00790 {
00791
00792 if (!sanityCheck())
00793 return false;
00794
00795 if (flags() & KResolver::NoResolve)
00796
00797 return run();
00798
00799 return true;
00800 }
00801
00802 bool KGetAddrinfoWorker::run()
00803 {
00804
00805 GetAddrInfoThread worker(m_encodedName, serviceName().latin1(),
00806 AF_UNSPEC, &results);
00807
00808 if (!worker.run())
00809 {
00810 if (wantThis(AF_UNIX))
00811 {
00812 if (addUnix() == KResolver::NoError)
00813 setError(KResolver::NoError);
00814 }
00815 else
00816 setError(worker.results.error(), worker.results.systemError());
00817
00818 return false;
00819 }
00820
00821
00822
00823
00824
00825 bool seen_unix = false;
00826 KResolverResults::Iterator it = results.begin();
00827 for ( ; it != results.end(); )
00828 {
00829 if ((*it).family() == AF_UNIX)
00830 seen_unix = true;
00831 if (!wantThis((*it).family()))
00832 it = results.remove(it);
00833 else
00834 ++it;
00835 }
00836
00837 if (!seen_unix)
00838 addUnix();
00839
00840 finished();
00841 return true;
00842 }
00843
00844 bool KGetAddrinfoWorker::wantThis(int family)
00845 {
00846
00847
00848 #ifdef AF_INET6
00849 if (family == AF_INET6 && familyMask() & KResolver::IPv6Family)
00850 return true;
00851 #endif
00852 if (family == AF_INET && familyMask() & KResolver::IPv4Family)
00853 return true;
00854 if (family == AF_UNIX && familyMask() & KResolver::UnixFamily)
00855 return true;
00856
00857
00858 if (familyMask() & KResolver::UnknownFamily)
00859 return true;
00860
00861 return false;
00862 }
00863
00864 #endif
00865
00866 void KNetwork::Internal::initStandardWorkers()
00867 {
00868
00869
00870
00871
00872 KResolverWorkerFactoryBase::registerNewWorker(new KResolverWorkerFactory<KStandardWorker>);
00873
00874 #ifdef HAVE_GETADDRINFO
00875 KResolverWorkerFactoryBase::registerNewWorker(new KResolverWorkerFactory<KGetAddrinfoWorker>);
00876 #endif
00877 }