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