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
}