00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
#include <sys/types.h>
00024
#include <sys/socket.h>
00025
#include <sys/un.h>
00026
#include <netinet/in.h>
00027
#include <stdlib.h>
00028
#include <stdio.h>
00029
#include <errno.h>
00030
#include <unistd.h>
00031
#include <arpa/inet.h>
00032
00033
#include <qglobal.h>
00034
00035
00036
00037
00038
#include <netdb.h>
00039
00040
#include "config.h"
00041
#include "kdebug.h"
00042
#include "klocale.h"
00043
00044
#ifndef IN6_IS_ADDR_V4MAPPED
00045
#define NEED_IN6_TESTS
00046
#endif
00047
#undef CLOBBER_IN6
00048
#include "netsupp.h"
00049
00050
#if defined(__hpux) || defined(_HPUX_SOURCE)
00051
extern int h_errno;
00052
#endif
00053
00054
#if !defined(kde_sockaddr_in6)
00055
00056
00057
00058
00059
00060
00061
00062
# define sockaddr_in6 kde_sockaddr_in6
00063
# define in6_addr kde_in6_addr
00064
#endif
00065
00066
#ifdef offsetof
00067
#undef offsetof
00068
#endif
00069
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
00070
00071
00072
00073
00074
00075
00076
#define KRF_KNOWS_AF_INET6 0x01
00077
#define KRF_USING_OWN_GETADDRINFO 0x02
00078
#define KRF_USING_OWN_INET_NTOP 0x04
00079
#define KRF_USING_OWN_INET_PTON 0x08
00080
#define KRF_CAN_RESOLVE_UNIX 0x100
00081
#define KRF_CAN_RESOLVE_IPV4 0x200
00082
#define KRF_CAN_RESOLVE_IPV6 0x400
00083
00084
00085
static void dofreeaddrinfo(
struct addrinfo *ai)
00086 {
00087
while (ai)
00088 {
00089
struct addrinfo *ai2 = ai;
00090
if (ai->ai_canonname != NULL)
00091 free(ai->ai_canonname);
00092
00093
if (ai->ai_addr != NULL)
00094 free(ai->ai_addr);
00095
00096 ai = ai->ai_next;
00097 free(ai2);
00098 }
00099 }
00100
00101
void kde_freeaddrinfo(
struct kde_addrinfo *ai)
00102 {
00103
if (ai->origin == KAI_LOCALUNIX)
00104 {
00105
struct addrinfo *p, *last = NULL;
00106
00107
00108
for (p = ai->data; p; p = p->ai_next)
00109 {
00110
if (p->ai_family == AF_UNIX)
00111 {
00112
if (last)
00113 {
00114 last->ai_next = NULL;
00115 freeaddrinfo(ai->data);
00116 }
00117 dofreeaddrinfo(p);
00118
break;
00119 }
00120 last = p;
00121 }
00122 }
00123
else
00124 freeaddrinfo(ai->data);
00125
00126 free(ai);
00127 }
00128
00129
static struct addrinfo*
00130 make_unix(
const char *name,
const char *serv)
00131 {
00132
const char *buf;
00133
struct addrinfo *p;
00134
struct sockaddr_un *_sun;
00135
int len;
00136
00137 p = (addrinfo*)malloc(
sizeof(*p));
00138
if (p == NULL)
00139
return NULL;
00140 memset(p, 0,
sizeof(*p));
00141
00142
if (
name != NULL)
00143 buf =
name;
00144
else
00145 buf = serv;
00146
00147
00148 len = strlen(buf) + offsetof(
struct sockaddr_un, sun_path) + 1;
00149
if (*buf !=
'/')
00150 len += 5;
00151
00152 _sun = (sockaddr_un*)malloc(len);
00153
if (_sun == NULL)
00154 {
00155
00156 free(p);
00157
return NULL;
00158 }
00159
00160 _sun->sun_family = AF_UNIX;
00161
# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
00162
_sun->sun_len = len;
00163
# endif
00164
if (*buf ==
'/')
00165 *_sun->sun_path =
'\0';
00166
else
00167 strcpy(_sun->sun_path,
"/tmp/");
00168 strcat(_sun->sun_path, buf);
00169
00170
00171 p->ai_family = AF_UNIX;
00172 p->ai_addrlen = len;
00173 p->ai_addr = (sockaddr*)_sun;
00174 p->ai_canonname = strdup(buf);
00175
00176
return p;
00177 }
00178
00179
00180
00181
00182
00183
00184
00185
#if KDE_IPV6_LOOKUP_MODE == 1
00186
static int check_ipv6_stack()
00187 {
00188
# ifndef AF_INET6
00189
return 2;
00190
# else
00191
if (getenv(
"KDE_NO_IPV6"))
00192
return 2;
00193
int fd = ::socket(AF_INET6, SOCK_STREAM, 0);
00194
if (fd == -1)
00195
return 2;
00196
00197 ::close(fd);
00198
return 1;
00199
# endif
00200
}
00201
#endif
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
int kde_getaddrinfo(
const char *name,
const char *service,
00231
const struct addrinfo* hint,
00232
struct kde_addrinfo** result)
00233 {
00234
struct kde_addrinfo* res;
00235
struct addrinfo* p;
00236
int err = EAI_SERVICE;
00237
#if KDE_IPV6_LOOKUP_MODE == 1
00238
00239
static int ipv6_stack = 0;
00240
#endif
00241
00242
00243 res = (kde_addrinfo*)malloc(
sizeof(*res));
00244
if (res == NULL)
00245
return EAI_MEMORY;
00246 res->data = NULL;
00247 res->origin = KAI_SYSTEM;
00248
00249
struct addrinfo* last = NULL;
00250
00251
00252
if (hint && (hint->ai_family == PF_UNIX))
00253 {
00254
if (service == NULL || *service ==
'\0')
00255
goto out;
00256
00257
00258
00259
00260
if (
name != NULL && !(
name[0] ==
'\0' || (
name[0] ==
'*' &&
name[1] ==
'\0') ||
00261 strcmp(
"localhost", name) == 0))
00262
goto out;
00263
00264
goto do_unix;
00265 }
00266
00267
#if KDE_IPV6_LOOKUP_MODE != 0
00268
# if KDE_IPV6_LOOKUP_MODE == 1
00269
00270
if (ipv6_stack == 0)
00271 ipv6_stack = check_ipv6_stack();
00272
00273
if (ipv6_stack == 2)
00274 {
00275
# endif
00276
00277
00278
struct addrinfo our_hint;
00279
if (hint != NULL)
00280 {
00281 memcpy(&our_hint, hint,
sizeof(our_hint));
00282
if (our_hint.ai_family == AF_UNSPEC)
00283 our_hint.ai_family = AF_INET;
00284 }
00285
else
00286 {
00287 memset(&our_hint, 0,
sizeof(our_hint));
00288 our_hint.ai_family = AF_INET;
00289 }
00290
00291
00292 err = getaddrinfo(name, service, &our_hint, &res->data);
00293
# if KDE_IPV6_LOOKUP_MODE == 1
00294
}
00295
else
00296
# endif
00297
#endif
00298
#if KDE_IPV6_LOOKUP_MODE != 2
00299
00300 err = getaddrinfo(name, service, hint, &res->data);
00301
#endif
00302
00303
00304
00305
if (service == NULL || *service ==
'\0')
00306
goto out;
00307
00308
00309
00310
00311
if (
name != NULL && !(
name[0] ==
'\0' || (
name[0] ==
'*' &&
name[1] ==
'\0') ||
00312 strcmp(
"localhost", name) == 0))
00313
goto out;
00314
00315
00316
00317
if (hint != NULL && (hint->ai_family != PF_UNSPEC && hint->ai_family != PF_UNIX))
00318
goto out;
00319
00320
00321
00322
00323
00324
if (err == 0)
00325
for (p = res->data; p; p = p->ai_next)
00326 {
00327 last = p;
00328
if (p->ai_family == AF_UNIX)
00329
00330
goto out;
00331 }
00332
00333 do_unix:
00334
00335 p = make_unix(NULL, service);
00336
if (p == NULL)
00337 {
00338 err = EAI_MEMORY;
00339
goto out;
00340 }
00341
if (hint != NULL)
00342 p->ai_socktype = hint->ai_socktype;
00343
if (p->ai_socktype == 0)
00344 p->ai_socktype = SOCK_STREAM;
00345
00346
if (last)
00347 last->ai_next = p;
00348
else
00349 res->data = p;
00350 res->origin = KAI_LOCALUNIX;
00351 *result = res;
00352
return 0;
00353
00354 out:
00355
00356
if (err == 0)
00357 *result = res;
00358
else
00359 {
00360
if (res->data != NULL)
00361 freeaddrinfo(res->data);
00362 free(res);
00363 }
00364
return err;
00365 }
00366
00367
#if defined(HAVE_GETADDRINFO) && !defined(HAVE_BROKEN_GETADDRINFO)
00368
00369
#define KRF_getaddrinfo 0
00370
#define KRF_resolver 0
00371
00372
#else // !defined(HAVE_GETADDRINFO) || defined(HAVE_BROKEN_GETADDRINFO)
00373
00374
#define KRF_getaddrinfo KRF_USING_OWN_GETADDRINFO
00375
#define KRF_resolver KRF_CAN_RESOLVE_UNIX | KRF_CAN_RESOLVE_IPV4
00376
00377
00378
00379
00380
00381
00385
static int inet_lookup(
const char *name,
int portnum,
int protonum,
00386
struct addrinfo *p,
const struct addrinfo *hint,
00387
struct addrinfo** result)
00388 {
00389
struct addrinfo *q;
00390
struct hostent *h;
00391
struct sockaddr **psa = NULL;
00392
int len;
00393
00394
00395
00396
# ifdef AF_INET6
00397
if (hint->ai_family == AF_INET6)
00398 {
00399
if (p != NULL)
00400 {
00401 *result = p;
00402
return 0;
00403 }
00404
return EAI_FAIL;
00405 }
00406
# endif
00407
00408 q = (addrinfo*)malloc(
sizeof(*q));
00409
if (q == NULL)
00410 {
00411 freeaddrinfo(p);
00412
return EAI_MEMORY;
00413 }
00414
00415 h = gethostbyname(name);
00416
if (h == NULL)
00417 {
00418
if (p != NULL)
00419 {
00420
00421 *result = p;
00422
return 0;
00423 }
00424
00425
switch (h_errno)
00426 {
00427
case HOST_NOT_FOUND:
00428
return EAI_NONAME;
00429
case TRY_AGAIN:
00430
return EAI_AGAIN;
00431
case NO_RECOVERY:
00432
return EAI_FAIL;
00433
case NO_ADDRESS:
00434
return EAI_NODATA;
00435
default:
00436
00437
return EAI_FAIL;
00438 }
00439 }
00440
00441
00442
if (h->h_addrtype == AF_INET && (hint->ai_family == AF_INET || hint->ai_family == AF_UNSPEC))
00443 len =
sizeof(
struct sockaddr_in);
00444
# ifdef AF_INET6
00445
else if (h->h_addrtype == AF_INET6 && (hint->ai_family == AF_INET6 ||
00446 hint->ai_family == AF_UNSPEC))
00447 len =
sizeof(
struct sockaddr_in6);
00448
# endif
00449
else
00450 {
00451
00452
00453
if (p != NULL)
00454 {
00455 *result = p;
00456
return 0;
00457 }
00458
return EAI_NODATA;
00459 }
00460
00461 q->ai_flags = 0;
00462 q->ai_family = h->h_addrtype;
00463 q->ai_socktype = hint->ai_socktype;
00464 q->ai_protocol = protonum;
00465 q->ai_addrlen = len;
00466
00467 q->ai_addr = (sockaddr*)malloc(len);
00468
if (q->ai_addr == NULL)
00469 {
00470 free(q);
00471 freeaddrinfo(p);
00472
return EAI_MEMORY;
00473 }
00474
if (h->h_addrtype == AF_INET)
00475 {
00476
struct sockaddr_in *sin = (sockaddr_in*)q->ai_addr;
00477 sin->sin_family = AF_INET;
00478
# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
00479
sin->sin_len =
sizeof(*sin);
00480
# endif
00481
sin->sin_port = portnum;
00482 memcpy(&sin->sin_addr, h->h_addr, h->h_length);
00483 }
00484
# ifdef AF_INET6
00485
else if (h->h_addrtype == AF_INET6)
00486 {
00487
struct sockaddr_in6 *sin6 = (sockaddr_in6*)q->ai_addr;
00488 sin6->sin6_family = AF_INET6;
00489
# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
00490
sin6->sin6_len =
sizeof(*sin6);
00491
# endif
00492
sin6->sin6_port = portnum;
00493 sin6->sin6_flowinfo = 0;
00494 memcpy(&sin6->sin6_addr, h->h_addr, h->h_length);
00495 sin6->sin6_scope_id = 0;
00496 }
00497
# endif
00498
00499
if (hint->ai_flags & AI_CANONNAME)
00500 q->ai_canonname = strdup(h->h_name);
00501
else
00502 q->ai_canonname = NULL;
00503
00504 q->ai_next = p;
00505 p = q;
00506
00507
00508
for (psa = (sockaddr**)h->h_addr_list + 1; *psa; psa++)
00509 {
00510 q = (addrinfo*)malloc(
sizeof(*q));
00511
if (q == NULL)
00512 {
00513 freeaddrinfo(p);
00514
return EAI_MEMORY;
00515 }
00516 memcpy(q, p,
sizeof(*q));
00517
00518 q->ai_addr = (sockaddr*)malloc(h->h_length);
00519
if (q->ai_addr == NULL)
00520 {
00521 freeaddrinfo(p);
00522 free(q);
00523
return EAI_MEMORY;
00524 }
00525
if (h->h_addrtype == AF_INET)
00526 {
00527
struct sockaddr_in *sin = (sockaddr_in*)q->ai_addr;
00528 sin->sin_family = AF_INET;
00529
# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
00530
sin->sin_len =
sizeof(*sin);
00531
# endif
00532
sin->sin_port = portnum;
00533 memcpy(&sin->sin_addr, *psa, h->h_length);
00534 }
00535
# ifdef AF_INET6
00536
else if (h->h_addrtype == AF_INET6)
00537 {
00538
struct sockaddr_in6 *sin6 = (sockaddr_in6*)q->ai_addr;
00539 sin6->sin6_family = AF_INET6;
00540
# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
00541
sin6->sin6_len =
sizeof(*sin6);
00542
# endif
00543
sin6->sin6_port = portnum;
00544 sin6->sin6_flowinfo = 0;
00545 memcpy(&sin6->sin6_addr, *psa, h->h_length);
00546 sin6->sin6_scope_id = 0;
00547 }
00548
# endif
00549
00550
if (q->ai_canonname != NULL)
00551 q->ai_canonname = strdup(q->ai_canonname);
00552
00553 q->ai_next = p;
00554 p = q;
00555 }
00556
00557 *result = p;
00558
return 0;
00559 }
00560
00561
static int make_inet(
const char *name,
int portnum,
int protonum,
struct addrinfo *p,
00562
const struct addrinfo *hint,
struct addrinfo** result)
00563 {
00564
struct addrinfo *q;
00565
00566
do
00567 {
00568
00569
00570
if (
name != NULL)
00571 {
00572
00573
00574
struct sockaddr_in *sin;
00575
struct in_addr in;
00576
# ifdef AF_INET6
00577
struct sockaddr_in6 *sin6;
00578
struct in6_addr in6;
00579
00580
if (hint->ai_family == AF_INET6 || (hint->ai_family == AF_UNSPEC &&
00581 strchr(name,
':') != NULL))
00582 {
00583
00584
if (inet_pton(AF_INET6, name, &in6) != 1)
00585 {
00586
if (hint->ai_flags & AI_NUMERICHOST)
00587 {
00588 freeaddrinfo(p);
00589
return EAI_FAIL;
00590 }
00591
break;
00592 }
00593
00594 sin6 = (sockaddr_in6*)malloc(
sizeof(*sin6));
00595
if (sin6 == NULL)
00596 {
00597 freeaddrinfo(p);
00598
return EAI_MEMORY;
00599 }
00600 memcpy(&sin6->sin6_addr, &in6,
sizeof(in6));
00601
00602
if (strchr(name,
'%') != NULL)
00603 {
00604 errno = 0;
00605 sin6->sin6_scope_id = strtoul(strchr(name,
'%') + 1, NULL, 10);
00606
if (errno != 0)
00607 sin6->sin6_scope_id = 0;
00608 }
00609
00610 q = (addrinfo*)malloc(
sizeof(*q));
00611
if (q == NULL)
00612 {
00613 freeaddrinfo(p);
00614 free(sin6);
00615
return EAI_MEMORY;
00616 }
00617
00618 sin6->sin6_family = AF_INET6;
00619
# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
00620
sin6->sin6_len =
sizeof(*sin6);
00621
# endif
00622
sin6->sin6_port = portnum;
00623 sin6->sin6_flowinfo = 0;
00624
00625 q->ai_flags = 0;
00626 q->ai_family = AF_INET6;
00627 q->ai_socktype = hint->ai_socktype;
00628 q->ai_protocol = protonum;
00629 q->ai_addrlen =
sizeof(*sin6);
00630 q->ai_canonname = NULL;
00631 q->ai_addr = (sockaddr*)sin6;
00632 q->ai_next = p;
00633
00634 *result = q;
00635
return 0;
00636 }
00637
# endif // AF_INET6
00638
00639
if (hint->ai_family == AF_INET || hint->ai_family == AF_UNSPEC)
00640 {
00641
00642
if (inet_pton(AF_INET, name, &in) != 1)
00643 {
00644
if (hint->ai_flags & AI_NUMERICHOST)
00645 {
00646 freeaddrinfo(p);
00647
return EAI_FAIL;
00648 }
00649
break;
00650 }
00651
00652 sin = (sockaddr_in*)malloc(
sizeof(*sin));
00653
if (sin == NULL)
00654 {
00655 freeaddrinfo(p);
00656
return EAI_MEMORY;
00657 }
00658
00659 q = (addrinfo*)malloc(
sizeof(*q));
00660
if (q == NULL)
00661 {
00662 freeaddrinfo(p);
00663 free(sin);
00664
return EAI_MEMORY;
00665 }
00666
00667 sin->sin_family = AF_INET;
00668
# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
00669
sin->sin_len =
sizeof(*sin);
00670
# endif
00671
sin->sin_port = portnum;
00672 sin->sin_addr = in;
00673
00674 q->ai_flags = 0;
00675 q->ai_family = AF_INET;
00676 q->ai_socktype = hint->ai_socktype;
00677 q->ai_protocol = protonum;
00678 q->ai_addrlen =
sizeof(*sin);
00679 q->ai_canonname = NULL;
00680 q->ai_addr = (sockaddr*)sin;
00681 q->ai_next = p;
00682 *result = q;
00683
return 0;
00684 }
00685
00686
00687
00688 kdError() <<
"I wasn't supposed to get here!";
00689 }
00690 }
while (
false);
00691
00692
00693
if (
name == NULL)
00694 {
00695
struct sockaddr_in *sin = (sockaddr_in*)malloc(
sizeof(*sin));
00696
# ifdef AF_INET6
00697
struct sockaddr_in6 *sin6;
00698
# endif
00699
00700
if (hint->ai_family == AF_INET || hint->ai_family == AF_UNSPEC)
00701 {
00702
if (sin == NULL)
00703 {
00704 free(sin);
00705 freeaddrinfo(p);
00706
return EAI_MEMORY;
00707 }
00708
00709
00710 q = (addrinfo*)malloc(
sizeof(*q));
00711
if (q == NULL)
00712 {
00713 free(sin);
00714 freeaddrinfo(p);
00715
return EAI_MEMORY;
00716 }
00717
00718 sin->sin_family = AF_INET;
00719
# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
00720
sin->sin_len =
sizeof(*sin);
00721
# endif
00722
sin->sin_port = portnum;
00723
if (hint->ai_flags & AI_PASSIVE)
00724 *(Q_UINT32*)&sin->sin_addr = INADDR_ANY;
00725
else
00726 *(Q_UINT32*)&sin->sin_addr = htonl(INADDR_LOOPBACK);
00727 q->ai_flags = 0;
00728 q->ai_family = AF_INET;
00729 q->ai_socktype = hint->ai_socktype;
00730 q->ai_protocol = protonum;
00731 q->ai_addrlen =
sizeof(*sin);
00732 q->ai_canonname = NULL;
00733 q->ai_addr = (sockaddr*)sin;
00734 q->ai_next = p;
00735 p = q;
00736 }
00737
00738
# ifdef AF_INET6
00739
00740
00741
if (hint->ai_family == AF_INET6 || hint->ai_family == AF_UNSPEC)
00742 {
00743 sin6 = (sockaddr_in6*)malloc(
sizeof(*sin6));
00744 q = (addrinfo*)malloc(
sizeof(*q));
00745
if (q == NULL || sin6 == NULL)
00746 {
00747 free(sin6);
00748 free(q);
00749 freeaddrinfo(p);
00750
return EAI_MEMORY;
00751 }
00752
00753 sin6->sin6_family = AF_INET6;
00754
# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
00755
sin6->sin6_len =
sizeof(*sin6);
00756
# endif
00757
sin6->sin6_port = portnum;
00758 sin6->sin6_flowinfo = 0;
00759 sin6->sin6_scope_id = 0;
00760
00761
00762 memset(&sin6->sin6_addr, 0,
sizeof(sin6->sin6_addr));
00763
if ((hint->ai_flags & AI_PASSIVE) == 0)
00764 ((
char*)&sin6->sin6_addr)[15] = 1;
00765
00766 q->ai_flags = 0;
00767 q->ai_family = AF_INET6;
00768 q->ai_socktype = hint->ai_socktype;
00769 q->ai_protocol = protonum;
00770 q->ai_addrlen =
sizeof(*sin6);
00771 q->ai_canonname = NULL;
00772 q->ai_addr = (sockaddr*)sin6;
00773 q->ai_next = p;
00774 p = q;
00775 }
00776
00777
# endif // AF_INET6
00778
00779 *result = p;
00780
return 0;
00781 }
00782
00783
return inet_lookup(name, portnum, protonum, p, hint, result);
00784 }
00785
00786
00787
int getaddrinfo(
const char *name,
const char *serv,
00788
const struct addrinfo* hint,
00789
struct addrinfo** result)
00790 {
00791
unsigned short portnum;
00792
int protonum = IPPROTO_TCP;
00793
const char *proto =
"tcp";
00794
struct addrinfo *p = NULL;
00795
00796
00797
if (hint == NULL || result == NULL)
00798
return EAI_BADFLAGS;
00799
if (hint->ai_family != AF_UNSPEC && hint->ai_family != AF_UNIX &&
00800 hint->ai_family != AF_INET
00801
# ifdef AF_INET6
00802
&& hint->ai_family != AF_INET6
00803
# endif
00804
)
00805
return EAI_FAMILY;
00806
if (hint->ai_socktype != 0 && hint->ai_socktype != SOCK_STREAM &&
00807 hint->ai_socktype != SOCK_DGRAM)
00808
return EAI_SOCKTYPE;
00809
00810
00811
if (
name != NULL && ((*
name ==
'*' &&
name[1] ==
'\0') || *
name ==
'\0'))
00812
name = NULL;
00813
00814
if (serv != NULL && ((*serv ==
'*' && serv[1] ==
'\0') || *serv ==
'\0'))
00815 serv = NULL;
00816
00817
if (
name == NULL && serv == NULL)
00818
return EAI_NONAME;
00819
00820
00821
if (
name != NULL && strcmp(name,
"localhost") == 0)
00822
name = NULL;
00823
00824
00825
00826
00827
if (hint->ai_family == AF_UNIX || hint->ai_family == AF_UNSPEC)
00828 {
00829
if (
name != NULL && serv != NULL)
00830 {
00831
00832
if (hint->ai_family == AF_UNIX)
00833
return EAI_BADFLAGS;
00834 }
00835
else
00836 {
00837 p = make_unix(name, serv);
00838
if (p == NULL)
00839
return EAI_MEMORY;
00840
00841 p->ai_socktype = hint->ai_socktype;
00842
00843
00844
if (hint->ai_family == AF_UNIX || ((
name != NULL && *
name ==
'/') ||
00845 (serv != NULL && *serv ==
'/')))
00846 {
00847 *result = p;
00848
return 0;
00849 }
00850 }
00851 }
00852
00853
00854
if (serv != NULL)
00855 {
00856
char *tail;
00857
struct servent *sent;
00858
00859 portnum = htons((
unsigned)strtoul(serv, &tail, 10));
00860
if (*tail !=
'\0')
00861 {
00862
00863
if (hint->ai_socktype == SOCK_DGRAM)
00864 {
00865 proto =
"udp";
00866 protonum = IPPROTO_UDP;
00867 }
00868
00869 sent = getservbyname(serv, proto);
00870
if (sent == NULL)
00871 {
00872
if (p == NULL)
00873
return EAI_NONAME;
00874
else
00875
return 0;
00876 }
00877
00878 portnum = sent->s_port;
00879 }
00880 }
00881
else
00882 portnum = 0;
00883
00884
return make_inet(name, portnum, protonum, p, hint, result);
00885 }
00886
00887
void freeaddrinfo(
struct addrinfo *p)
00888 {
00889 dofreeaddrinfo(p);
00890 }
00891
00892
char *gai_strerror(
int errorcode)
00893 {
00894
static const char *
const messages[] =
00895 {
00896 I18N_NOOP(
"no error"),
00897 I18N_NOOP(
"address family for nodename not supported"),
00898 I18N_NOOP(
"temporary failure in name resolution"),
00899 I18N_NOOP(
"invalid value for 'ai_flags'"),
00900 I18N_NOOP(
"non-recoverable failure in name resolution"),
00901 I18N_NOOP(
"'ai_family' not supported"),
00902 I18N_NOOP(
"memory allocation failure"),
00903 I18N_NOOP(
"no address associated with nodename"),
00904 I18N_NOOP(
"name or service not known"),
00905 I18N_NOOP(
"servname not supported for ai_socktype"),
00906 I18N_NOOP(
"'ai_socktype' not supported"),
00907 I18N_NOOP(
"system error")
00908 };
00909
00910
if (errorcode > EAI_SYSTEM || errorcode < 0)
00911
return NULL;
00912
00913
static char buffer[200];
00914 strcpy(buffer, i18n(messages[errorcode]).local8Bit());
00915
return buffer;
00916 }
00917
00918
static void findport(
unsigned short port,
char *serv, size_t servlen,
int flags)
00919 {
00920
if (serv == NULL)
00921
return;
00922
00923
if ((flags & NI_NUMERICSERV) == 0)
00924 {
00925
struct servent *sent;
00926 sent = getservbyport(ntohs(port), flags & NI_DGRAM ?
"udp" :
"tcp");
00927
if (sent != NULL && servlen > strlen(sent->s_name))
00928 {
00929 strcpy(serv, sent->s_name);
00930
return;
00931 }
00932 }
00933
00934 snprintf(serv, servlen,
"%u", ntohs(port));
00935 }
00936
00937
int getnameinfo(
const struct sockaddr *sa, ksocklen_t salen,
00938
char *host, size_t hostlen,
char *serv, size_t servlen,
00939
int flags)
00940 {
00941
union
00942
{
00943
const sockaddr *sa;
00944
const sockaddr_un *_sun;
00945
const sockaddr_in *sin;
00946
const sockaddr_in6 *sin6;
00947 } s;
00948
00949
if ((host == NULL || hostlen == 0) && (serv == NULL || servlen == 0))
00950
return 1;
00951
00952 s.sa = sa;
00953
if (s.sa->sa_family == AF_UNIX)
00954 {
00955
if (salen < offsetof(
struct sockaddr_un, sun_path) + strlen(s._sun->sun_path) + 1)
00956
return 1;
00957
00958
if (servlen && serv != NULL)
00959 *serv =
'\0';
00960
if (host != NULL && hostlen > strlen(s._sun->sun_path))
00961 strcpy(host, s._sun->sun_path);
00962
00963
return 0;
00964 }
00965
else if (s.sa->sa_family == AF_INET)
00966 {
00967
if (salen < offsetof(
struct sockaddr_in, sin_addr) +
sizeof(s.sin->sin_addr))
00968
return 1;
00969
00970
if (flags & NI_NUMERICHOST)
00971 inet_ntop(AF_INET, &s.sin->sin_addr, host, hostlen);
00972
else
00973 {
00974
00975
struct hostent *h = gethostbyaddr((
const char*)&s.sin->sin_addr,
sizeof(s.sin->sin_addr),
00976 AF_INET);
00977
if (h == NULL && flags & NI_NAMEREQD)
00978
return 1;
00979
else if (h == NULL)
00980 inet_ntop(AF_INET, &s.sin->sin_addr, host, hostlen);
00981
else if (host != NULL && hostlen > strlen(h->h_name))
00982 strcpy(host, h->h_name);
00983
else
00984
return 1;
00985 }
00986
00987 findport(s.sin->sin_port, serv, servlen, flags);
00988 }
00989
# ifdef AF_INET6
00990
else if (s.sa->sa_family == AF_INET6)
00991 {
00992
if (salen < offsetof(
struct sockaddr_in6, sin6_addr) +
sizeof(s.sin6->sin6_addr))
00993
return 1;
00994
00995
if (flags & NI_NUMERICHOST)
00996 inet_ntop(AF_INET6, &s.sin6->sin6_addr, host, hostlen);
00997
else
00998 {
00999
01000
struct hostent *h = gethostbyaddr((
const char*)&s.sin->sin_addr,
sizeof(s.sin->sin_addr),
01001 AF_INET6);
01002
if (h == NULL && flags & NI_NAMEREQD)
01003
return 1;
01004
else if (h == NULL)
01005 inet_ntop(AF_INET6, &s.sin6->sin6_addr, host, hostlen);
01006
else if (host != NULL && hostlen > strlen(h->h_name))
01007 strcpy(host, h->h_name);
01008
else
01009
return 1;
01010 }
01011
01012 findport(s.sin6->sin6_port, serv, servlen, flags);
01013 }
01014
# endif // AF_INET6
01015
01016
return 1;
01017 }
01018
01019
#endif // HAVE_GETADDRINFO
01020
01021
#ifndef HAVE_INET_NTOP
01022
01023
#define KRF_inet_ntop KRF_USING_OWN_INET_NTOP
01024
01025
static void add_dwords(
char *buf, Q_UINT16 *dw,
int count)
01026 {
01027
int i = 1;
01028 sprintf(buf + strlen(buf),
"%x", ntohs(dw[0]));
01029
while (--count)
01030 sprintf(buf + strlen(buf),
":%x", ntohs(dw[i++]));
01031 }
01032
01033
const char* inet_ntop(
int af,
const void *cp,
char *buf, size_t len)
01034 {
01035
char buf2[
sizeof "1234:5678:9abc:def0:1234:5678:255.255.255.255" + 1];
01036 Q_UINT8 *data = (Q_UINT8*)cp;
01037
01038
if (af == AF_INET)
01039 {
01040 sprintf(buf2,
"%u.%u.%u.%u", data[0], data[1], data[2], data[3]);
01041
01042
if (len > strlen(buf2))
01043 {
01044 strcpy(buf, buf2);
01045
return buf;
01046 }
01047
01048 errno = ENOSPC;
01049
return NULL;
01050 }
01051
01052
# ifdef AF_INET6
01053
if (af == AF_INET6)
01054 {
01055 Q_UINT16 *p = (Q_UINT16*)data;
01056 Q_UINT16 *longest = NULL, *cur = NULL;
01057
int longest_length = 0, cur_length;
01058
int i;
01059
01060
if (KDE_IN6_IS_ADDR_V4MAPPED(p) || KDE_IN6_IS_ADDR_V4COMPAT(p))
01061 sprintf(buf2,
"::%s%u.%u.%u.%u",
01062 KDE_IN6_IS_ADDR_V4MAPPED(p) ?
"ffff:" :
"",
01063 buf[12], buf[13], buf[14], buf[15]);
01064
else
01065 {
01066
01067
for (i = 0; i < 8; i++)
01068
if (cur == NULL && p[i] == 0)
01069 {
01070
01071 cur = p + i;
01072 cur_length = 1;
01073 }
01074
else if (cur != NULL && p[i] == 0)
01075
01076 cur_length++;
01077
else if (cur != NULL && p[i] != 0)
01078 {
01079
01080
if (cur_length > longest_length)
01081 {
01082 longest_length = cur_length;
01083 longest = cur;
01084 }
01085 cur = NULL;
01086 }
01087
if (cur != NULL && cur_length > longest_length)
01088 {
01089 longest_length = cur_length;
01090 longest = cur;
01091 }
01092
01093
if (longest_length > 1)
01094 {
01095
01096 buf2[0] =
'\0';
01097
if (longest != p)
01098 add_dwords(buf2, p, longest - p);
01099 strcat(buf2,
"::");
01100
if (longest + longest_length < p + 8)
01101 add_dwords(buf2, longest + longest_length, 8 - (longest - p) - longest_length);
01102 }
01103
else
01104 {
01105
01106 buf2[0] =
'\0';
01107 add_dwords(buf2, p, 8);
01108 }
01109 }
01110
01111
if (strlen(buf2) < len)
01112 {
01113 strcpy(buf, buf2);
01114
return buf;
01115 }
01116
01117 errno = ENOSPC;
01118
return NULL;
01119 }
01120
# endif
01121
01122 errno = EAFNOSUPPORT;
01123
return NULL;
01124 }
01125
01126
#else // HAVE_INET_NTOP
01127
01128
#define KRF_inet_ntop 0
01129
01130
#endif // HAVE_INET_NTOP
01131
01132
#ifndef HAVE_INET_PTON
01133
01134
#define KRF_inet_pton KRF_USING_OWN_INET_PTON
01135
int inet_pton(
int af,
const char *cp,
void *buf)
01136 {
01137
if (af == AF_INET)
01138 {
01139
01140
unsigned p[4];
01141
unsigned char *q = (
unsigned char*)buf;
01142
if (sscanf(cp,
"%u.%u.%u.%u", p, p + 1, p + 2, p + 3) != 4)
01143
return 0;
01144
01145
if (p[0] > 0xff || p[1] > 0xff || p[2] > 0xff || p[3] > 0xff)
01146
return 0;
01147
01148 q[0] = p[0];
01149 q[1] = p[1];
01150 q[2] = p[2];
01151 q[3] = p[3];
01152
01153
return 1;
01154 }
01155
01156
# ifdef AF_INET6
01157
else if (af == AF_INET6)
01158 {
01159 Q_UINT16 addr[8];
01160
const char *p = cp;
01161
int n = 0, start = 8;
01162
bool has_v4 = strchr(p,
'.') != NULL;
01163
01164 memset(addr, 0,
sizeof(addr));
01165
01166
if (*p ==
'\0' || p[1] ==
'\0')
01167
return 0;
01168
01169
if (*p ==
':' && p[1] ==
':')
01170 {
01171 start = 0;
01172 p += 2;
01173 }
01174
while (*p)
01175 {
01176
if (has_v4 && inet_pton(AF_INET, p, addr + n) != 0)
01177 {
01178
01179 addr[n] = ntohs(addr[n]);
01180 n++;
01181 addr[n] = ntohs(addr[n]);
01182 n++;
01183
break;
01184 }
01185
if (sscanf(p,
"%hx", addr + n++) != 1)
01186
return 0;
01187
01188
while (*p && *p !=
':')
01189 p++;
01190
if (!*p)
01191
break;
01192 p++;
01193
01194
if (*p ==
':')
01195 {
01196
if (start != 8)
01197
return 0;
01198 start = n;
01199 p++;
01200 }
01201 }
01202
01203
01204
01205
01206
01207
if (start == 8 && n != 8)
01208
return 0;
01209 memmove(addr + start + (8 - n), addr + start, (n - start) *
sizeof(Q_UINT16));
01210 memset(addr + start, 0, (8 - n) *
sizeof(Q_UINT16));
01211
01212
01213
01214
if (htons(0x1234) != 0x1234)
01215
for (n = 0; n < 8; n++)
01216 addr[n] = htons(addr[n]);
01217
01218 memcpy(buf, addr,
sizeof(addr));
01219
return 1;
01220 }
01221
# endif
01222
01223 errno = EAFNOSUPPORT;
01224
return -1;
01225 }
01226
01227
#else // HAVE_INET_PTON
01228
01229
#define KRF_inet_pton 0
01230
01231
#endif // HAVE_INET_PTON
01232
01233
#ifdef AF_INET6
01234
# define KRF_afinet6 KRF_KNOWS_AF_INET6
01235
#else
01236
# define KRF_afinet6 0
01237
#endif
01238
01239
namespace KDE
01240 {
01242
extern const int resolverFlags = KRF_getaddrinfo | KRF_resolver | KRF_afinet6 | KRF_inet_ntop | KRF_inet_pton;
01243 }