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