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 #include <kdemacros.h>
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 defined(KDE_IPV6_LOOKUP_MODE) && 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 defined(KDE_IPV6_LOOKUP_MODE) && 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 defined(KDE_IPV6_LOOKUP_MODE) && 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 defined(KDE_IPV6_LOOKUP_MODE) && 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 if (res->data != NULL)
00356 freeaddrinfo(res->data);
00357 free(res);
00358 return err;
00359 }
00360
00361 #if defined(HAVE_GETADDRINFO) && !defined(HAVE_BROKEN_GETADDRINFO)
00362
00363 #define KRF_getaddrinfo 0
00364 #define KRF_resolver 0
00365
00366 #else // !defined(HAVE_GETADDRINFO) || defined(HAVE_BROKEN_GETADDRINFO)
00367
00368 #define KRF_getaddrinfo KRF_USING_OWN_GETADDRINFO
00369 #define KRF_resolver KRF_CAN_RESOLVE_UNIX | KRF_CAN_RESOLVE_IPV4
00370
00371
00372
00373
00374
00375
00379 static int inet_lookup(const char *name, int portnum, int protonum,
00380 struct addrinfo *p, const struct addrinfo *hint,
00381 struct addrinfo** result)
00382 {
00383 struct addrinfo *q;
00384 struct hostent *h;
00385 struct sockaddr **psa = NULL;
00386 int len;
00387
00388
00389
00390 # ifdef AF_INET6
00391 if (hint->ai_family == AF_INET6)
00392 {
00393 if (p != NULL)
00394 {
00395 *result = p;
00396 return 0;
00397 }
00398 return EAI_FAIL;
00399 }
00400 # endif
00401
00402 q = (addrinfo*)malloc(sizeof(*q));
00403 if (q == NULL)
00404 {
00405 freeaddrinfo(p);
00406 return EAI_MEMORY;
00407 }
00408
00409 h = gethostbyname(name);
00410 if (h == NULL)
00411 {
00412 if (p != NULL)
00413 {
00414
00415 *result = p;
00416 return 0;
00417 }
00418
00419 switch (h_errno)
00420 {
00421 case HOST_NOT_FOUND:
00422 return EAI_NONAME;
00423 case TRY_AGAIN:
00424 return EAI_AGAIN;
00425 case NO_RECOVERY:
00426 return EAI_FAIL;
00427 case NO_ADDRESS:
00428 return EAI_NODATA;
00429 default:
00430
00431 return EAI_FAIL;
00432 }
00433 }
00434
00435
00436 if (h->h_addrtype == AF_INET && (hint->ai_family == AF_INET || hint->ai_family == AF_UNSPEC))
00437 len = sizeof(struct sockaddr_in);
00438 # ifdef AF_INET6
00439 else if (h->h_addrtype == AF_INET6 && (hint->ai_family == AF_INET6 ||
00440 hint->ai_family == AF_UNSPEC))
00441 len = sizeof(struct sockaddr_in6);
00442 # endif
00443 else
00444 {
00445
00446
00447 if (p != NULL)
00448 {
00449 *result = p;
00450 return 0;
00451 }
00452 return EAI_NODATA;
00453 }
00454
00455 q->ai_flags = 0;
00456 q->ai_family = h->h_addrtype;
00457 q->ai_socktype = hint->ai_socktype;
00458 q->ai_protocol = protonum;
00459 q->ai_addrlen = len;
00460
00461 q->ai_addr = (sockaddr*)malloc(len);
00462 if (q->ai_addr == NULL)
00463 {
00464 free(q);
00465 freeaddrinfo(p);
00466 return EAI_MEMORY;
00467 }
00468 if (h->h_addrtype == AF_INET)
00469 {
00470 struct sockaddr_in *sin = (sockaddr_in*)q->ai_addr;
00471 sin->sin_family = AF_INET;
00472 # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
00473 sin->sin_len = sizeof(*sin);
00474 # endif
00475 sin->sin_port = portnum;
00476 memcpy(&sin->sin_addr, h->h_addr, h->h_length);
00477 }
00478 # ifdef AF_INET6
00479 else if (h->h_addrtype == AF_INET6)
00480 {
00481 struct sockaddr_in6 *sin6 = (sockaddr_in6*)q->ai_addr;
00482 sin6->sin6_family = AF_INET6;
00483 # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
00484 sin6->sin6_len = sizeof(*sin6);
00485 # endif
00486 sin6->sin6_port = portnum;
00487 sin6->sin6_flowinfo = 0;
00488 memcpy(&sin6->sin6_addr, h->h_addr, h->h_length);
00489 sin6->sin6_scope_id = 0;
00490 }
00491 # endif
00492
00493 if (hint->ai_flags & AI_CANONNAME)
00494 q->ai_canonname = strdup(h->h_name);
00495 else
00496 q->ai_canonname = NULL;
00497
00498 q->ai_next = p;
00499 p = q;
00500
00501
00502 for (psa = (sockaddr**)h->h_addr_list + 1; *psa; psa++)
00503 {
00504 q = (addrinfo*)malloc(sizeof(*q));
00505 if (q == NULL)
00506 {
00507 freeaddrinfo(p);
00508 return EAI_MEMORY;
00509 }
00510 memcpy(q, p, sizeof(*q));
00511
00512 q->ai_addr = (sockaddr*)malloc(h->h_length);
00513 if (q->ai_addr == NULL)
00514 {
00515 freeaddrinfo(p);
00516 free(q);
00517 return EAI_MEMORY;
00518 }
00519 if (h->h_addrtype == AF_INET)
00520 {
00521 struct sockaddr_in *sin = (sockaddr_in*)q->ai_addr;
00522 sin->sin_family = AF_INET;
00523 # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
00524 sin->sin_len = sizeof(*sin);
00525 # endif
00526 sin->sin_port = portnum;
00527 memcpy(&sin->sin_addr, *psa, h->h_length);
00528 }
00529 # ifdef AF_INET6
00530 else if (h->h_addrtype == AF_INET6)
00531 {
00532 struct sockaddr_in6 *sin6 = (sockaddr_in6*)q->ai_addr;
00533 sin6->sin6_family = AF_INET6;
00534 # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
00535 sin6->sin6_len = sizeof(*sin6);
00536 # endif
00537 sin6->sin6_port = portnum;
00538 sin6->sin6_flowinfo = 0;
00539 memcpy(&sin6->sin6_addr, *psa, h->h_length);
00540 sin6->sin6_scope_id = 0;
00541 }
00542 # endif
00543
00544 if (q->ai_canonname != NULL)
00545 q->ai_canonname = strdup(q->ai_canonname);
00546
00547 q->ai_next = p;
00548 p = q;
00549 }
00550
00551 *result = p;
00552 return 0;
00553 }
00554
00555 static int make_inet(const char *name, int portnum, int protonum, struct addrinfo *p,
00556 const struct addrinfo *hint, struct addrinfo** result)
00557 {
00558 struct addrinfo *q;
00559
00560 do
00561 {
00562
00563
00564 if (name != NULL)
00565 {
00566
00567
00568 struct sockaddr_in *sin;
00569 struct in_addr in;
00570 # ifdef AF_INET6
00571 struct sockaddr_in6 *sin6;
00572 struct in6_addr in6;
00573
00574 if (hint->ai_family == AF_INET6 || (hint->ai_family == AF_UNSPEC &&
00575 strchr(name, ':') != NULL))
00576 {
00577
00578 if (inet_pton(AF_INET6, name, &in6) != 1)
00579 {
00580 if (hint->ai_flags & AI_NUMERICHOST)
00581 {
00582 freeaddrinfo(p);
00583 return EAI_FAIL;
00584 }
00585 break;
00586 }
00587
00588 sin6 = (sockaddr_in6*)malloc(sizeof(*sin6));
00589 if (sin6 == NULL)
00590 {
00591 freeaddrinfo(p);
00592 return EAI_MEMORY;
00593 }
00594 memcpy(&sin6->sin6_addr, &in6, sizeof(in6));
00595
00596 if (strchr(name, '%') != NULL)
00597 {
00598 errno = 0;
00599 sin6->sin6_scope_id = strtoul(strchr(name, '%') + 1, NULL, 10);
00600 if (errno != 0)
00601 sin6->sin6_scope_id = 0;
00602 }
00603
00604 q = (addrinfo*)malloc(sizeof(*q));
00605 if (q == NULL)
00606 {
00607 freeaddrinfo(p);
00608 free(sin6);
00609 return EAI_MEMORY;
00610 }
00611
00612 sin6->sin6_family = AF_INET6;
00613 # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
00614 sin6->sin6_len = sizeof(*sin6);
00615 # endif
00616 sin6->sin6_port = portnum;
00617 sin6->sin6_flowinfo = 0;
00618
00619 q->ai_flags = 0;
00620 q->ai_family = AF_INET6;
00621 q->ai_socktype = hint->ai_socktype;
00622 q->ai_protocol = protonum;
00623 q->ai_addrlen = sizeof(*sin6);
00624 q->ai_canonname = NULL;
00625 q->ai_addr = (sockaddr*)sin6;
00626 q->ai_next = p;
00627
00628 *result = q;
00629 return 0;
00630 }
00631 # endif // AF_INET6
00632
00633 if (hint->ai_family == AF_INET || hint->ai_family == AF_UNSPEC)
00634 {
00635
00636 if (inet_pton(AF_INET, name, &in) != 1)
00637 {
00638 if (hint->ai_flags & AI_NUMERICHOST)
00639 {
00640 freeaddrinfo(p);
00641 return EAI_FAIL;
00642 }
00643 break;
00644 }
00645
00646 sin = (sockaddr_in*)malloc(sizeof(*sin));
00647 if (sin == NULL)
00648 {
00649 freeaddrinfo(p);
00650 return EAI_MEMORY;
00651 }
00652
00653 q = (addrinfo*)malloc(sizeof(*q));
00654 if (q == NULL)
00655 {
00656 freeaddrinfo(p);
00657 free(sin);
00658 return EAI_MEMORY;
00659 }
00660
00661 sin->sin_family = AF_INET;
00662 # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
00663 sin->sin_len = sizeof(*sin);
00664 # endif
00665 sin->sin_port = portnum;
00666 sin->sin_addr = in;
00667
00668 q->ai_flags = 0;
00669 q->ai_family = AF_INET;
00670 q->ai_socktype = hint->ai_socktype;
00671 q->ai_protocol = protonum;
00672 q->ai_addrlen = sizeof(*sin);
00673 q->ai_canonname = NULL;
00674 q->ai_addr = (sockaddr*)sin;
00675 q->ai_next = p;
00676 *result = q;
00677 return 0;
00678 }
00679
00680
00681
00682 kdError() << "I wasn't supposed to get here!";
00683 }
00684 } while (false);
00685
00686
00687 if (name == NULL)
00688 {
00689 struct sockaddr_in *sin = (sockaddr_in*)malloc(sizeof(*sin));
00690 # ifdef AF_INET6
00691 struct sockaddr_in6 *sin6;
00692 # endif
00693
00694 if (hint->ai_family == AF_INET || hint->ai_family == AF_UNSPEC)
00695 {
00696 if (sin == NULL)
00697 {
00698 free(sin);
00699 freeaddrinfo(p);
00700 return EAI_MEMORY;
00701 }
00702
00703
00704 q = (addrinfo*)malloc(sizeof(*q));
00705 if (q == NULL)
00706 {
00707 free(sin);
00708 freeaddrinfo(p);
00709 return EAI_MEMORY;
00710 }
00711
00712 sin->sin_family = AF_INET;
00713 # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
00714 sin->sin_len = sizeof(*sin);
00715 # endif
00716 sin->sin_port = portnum;
00717 if (hint->ai_flags & AI_PASSIVE)
00718 *(Q_UINT32*)&sin->sin_addr = INADDR_ANY;
00719 else
00720 *(Q_UINT32*)&sin->sin_addr = htonl(INADDR_LOOPBACK);
00721 q->ai_flags = 0;
00722 q->ai_family = AF_INET;
00723 q->ai_socktype = hint->ai_socktype;
00724 q->ai_protocol = protonum;
00725 q->ai_addrlen = sizeof(*sin);
00726 q->ai_canonname = NULL;
00727 q->ai_addr = (sockaddr*)sin;
00728 q->ai_next = p;
00729 p = q;
00730 }
00731
00732 # ifdef AF_INET6
00733
00734
00735 if (hint->ai_family == AF_INET6 || hint->ai_family == AF_UNSPEC)
00736 {
00737 sin6 = (sockaddr_in6*)malloc(sizeof(*sin6));
00738 q = (addrinfo*)malloc(sizeof(*q));
00739 if (q == NULL || sin6 == NULL)
00740 {
00741 free(sin6);
00742 free(q);
00743 freeaddrinfo(p);
00744 return EAI_MEMORY;
00745 }
00746
00747 sin6->sin6_family = AF_INET6;
00748 # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
00749 sin6->sin6_len = sizeof(*sin6);
00750 # endif
00751 sin6->sin6_port = portnum;
00752 sin6->sin6_flowinfo = 0;
00753 sin6->sin6_scope_id = 0;
00754
00755
00756 memset(&sin6->sin6_addr, 0, sizeof(sin6->sin6_addr));
00757 if ((hint->ai_flags & AI_PASSIVE) == 0)
00758 ((char*)&sin6->sin6_addr)[15] = 1;
00759
00760 q->ai_flags = 0;
00761 q->ai_family = AF_INET6;
00762 q->ai_socktype = hint->ai_socktype;
00763 q->ai_protocol = protonum;
00764 q->ai_addrlen = sizeof(*sin6);
00765 q->ai_canonname = NULL;
00766 q->ai_addr = (sockaddr*)sin6;
00767 q->ai_next = p;
00768 p = q;
00769 }
00770
00771 # endif // AF_INET6
00772
00773 *result = p;
00774 return 0;
00775 }
00776
00777 return inet_lookup(name, portnum, protonum, p, hint, result);
00778 }
00779
00780
00781 int getaddrinfo(const char *name, const char *serv,
00782 const struct addrinfo* hint,
00783 struct addrinfo** result)
00784 {
00785 unsigned short portnum;
00786 int protonum = IPPROTO_TCP;
00787 const char *proto = "tcp";
00788 struct addrinfo *p = NULL;
00789
00790
00791 if (hint == NULL || result == NULL)
00792 return EAI_BADFLAGS;
00793 if (hint->ai_family != AF_UNSPEC && hint->ai_family != AF_UNIX &&
00794 hint->ai_family != AF_INET
00795 # ifdef AF_INET6
00796 && hint->ai_family != AF_INET6
00797 # endif
00798 )
00799 return EAI_FAMILY;
00800 if (hint->ai_socktype != 0 && hint->ai_socktype != SOCK_STREAM &&
00801 hint->ai_socktype != SOCK_DGRAM)
00802 return EAI_SOCKTYPE;
00803
00804
00805 if (name != NULL && ((*name == '*' && name[1] == '\0') || *name == '\0'))
00806 name = NULL;
00807
00808 if (serv != NULL && ((*serv == '*' && serv[1] == '\0') || *serv == '\0'))
00809 serv = NULL;
00810
00811 if (name == NULL && serv == NULL)
00812 return EAI_NONAME;
00813
00814
00815 if (name != NULL && strcmp(name, "localhost") == 0)
00816 name = NULL;
00817
00818
00819
00820
00821 if (hint->ai_family == AF_UNIX || hint->ai_family == AF_UNSPEC)
00822 {
00823 if (name != NULL && serv != NULL)
00824 {
00825
00826 if (hint->ai_family == AF_UNIX)
00827 return EAI_BADFLAGS;
00828 }
00829 else
00830 {
00831 p = make_unix(name, serv);
00832 if (p == NULL)
00833 return EAI_MEMORY;
00834
00835 p->ai_socktype = hint->ai_socktype;
00836
00837
00838 if (hint->ai_family == AF_UNIX || ((name != NULL && *name == '/') ||
00839 (serv != NULL && *serv == '/')))
00840 {
00841 *result = p;
00842 return 0;
00843 }
00844 }
00845 }
00846
00847
00848 if (serv != NULL)
00849 {
00850 char *tail;
00851 struct servent *sent;
00852
00853 portnum = htons((unsigned)strtoul(serv, &tail, 10));
00854 if (*tail != '\0')
00855 {
00856
00857 if (hint->ai_socktype == SOCK_DGRAM)
00858 {
00859 proto = "udp";
00860 protonum = IPPROTO_UDP;
00861 }
00862
00863 sent = getservbyname(serv, proto);
00864 if (sent == NULL)
00865 {
00866 if (p == NULL)
00867 return EAI_NONAME;
00868 else
00869 return 0;
00870 }
00871
00872 portnum = sent->s_port;
00873 }
00874 }
00875 else
00876 portnum = 0;
00877
00878 return make_inet(name, portnum, protonum, p, hint, result);
00879 }
00880
00881 void freeaddrinfo(struct addrinfo *p)
00882 {
00883 dofreeaddrinfo(p);
00884 }
00885
00886 char *gai_strerror(int errorcode)
00887 {
00888 static const char * const messages[] =
00889 {
00890 I18N_NOOP("no error"),
00891 I18N_NOOP("address family for nodename not supported"),
00892 I18N_NOOP("temporary failure in name resolution"),
00893 I18N_NOOP("invalid value for 'ai_flags'"),
00894 I18N_NOOP("non-recoverable failure in name resolution"),
00895 I18N_NOOP("'ai_family' not supported"),
00896 I18N_NOOP("memory allocation failure"),
00897 I18N_NOOP("no address associated with nodename"),
00898 I18N_NOOP("name or service not known"),
00899 I18N_NOOP("servname not supported for ai_socktype"),
00900 I18N_NOOP("'ai_socktype' not supported"),
00901 I18N_NOOP("system error")
00902 };
00903
00904 if (errorcode > EAI_SYSTEM || errorcode < 0)
00905 return NULL;
00906
00907 static char buffer[200];
00908 strcpy(buffer, i18n(messages[errorcode]).local8Bit());
00909 return buffer;
00910 }
00911
00912 static void findport(unsigned short port, char *serv, size_t servlen, int flags)
00913 {
00914 if (serv == NULL)
00915 return;
00916
00917 if ((flags & NI_NUMERICSERV) == 0)
00918 {
00919 struct servent *sent;
00920 sent = getservbyport(ntohs(port), flags & NI_DGRAM ? "udp" : "tcp");
00921 if (sent != NULL && servlen > strlen(sent->s_name))
00922 {
00923 strcpy(serv, sent->s_name);
00924 return;
00925 }
00926 }
00927
00928 snprintf(serv, servlen, "%u", ntohs(port));
00929 }
00930
00931 int getnameinfo(const struct sockaddr *sa, ksocklen_t salen,
00932 char *host, size_t hostlen, char *serv, size_t servlen,
00933 int flags)
00934 {
00935 union
00936 {
00937 const sockaddr *sa;
00938 const sockaddr_un *_sun;
00939 const sockaddr_in *sin;
00940 const sockaddr_in6 *sin6;
00941 } s;
00942
00943 if ((host == NULL || hostlen == 0) && (serv == NULL || servlen == 0))
00944 return 1;
00945
00946 s.sa = sa;
00947 if (s.sa->sa_family == AF_UNIX)
00948 {
00949 if (salen < offsetof(struct sockaddr_un, sun_path) + strlen(s._sun->sun_path) + 1)
00950 return 1;
00951
00952 if (servlen && serv != NULL)
00953 *serv = '\0';
00954 if (host != NULL && hostlen > strlen(s._sun->sun_path))
00955 strcpy(host, s._sun->sun_path);
00956
00957 return 0;
00958 }
00959 else if (s.sa->sa_family == AF_INET)
00960 {
00961 if (salen < offsetof(struct sockaddr_in, sin_addr) + sizeof(s.sin->sin_addr))
00962 return 1;
00963
00964 if (flags & NI_NUMERICHOST)
00965 inet_ntop(AF_INET, &s.sin->sin_addr, host, hostlen);
00966 else
00967 {
00968
00969 struct hostent *h = gethostbyaddr((const char*)&s.sin->sin_addr, sizeof(s.sin->sin_addr),
00970 AF_INET);
00971 if (h == NULL && flags & NI_NAMEREQD)
00972 return 1;
00973 else if (h == NULL)
00974 inet_ntop(AF_INET, &s.sin->sin_addr, host, hostlen);
00975 else if (host != NULL && hostlen > strlen(h->h_name))
00976 strcpy(host, h->h_name);
00977 else
00978 return 1;
00979 }
00980
00981 findport(s.sin->sin_port, serv, servlen, flags);
00982 }
00983 # ifdef AF_INET6
00984 else if (s.sa->sa_family == AF_INET6)
00985 {
00986 if (salen < offsetof(struct sockaddr_in6, sin6_addr) + sizeof(s.sin6->sin6_addr))
00987 return 1;
00988
00989 if (flags & NI_NUMERICHOST)
00990 inet_ntop(AF_INET6, &s.sin6->sin6_addr, host, hostlen);
00991 else
00992 {
00993
00994 struct hostent *h = gethostbyaddr((const char*)&s.sin->sin_addr, sizeof(s.sin->sin_addr),
00995 AF_INET6);
00996 if (h == NULL && flags & NI_NAMEREQD)
00997 return 1;
00998 else if (h == NULL)
00999 inet_ntop(AF_INET6, &s.sin6->sin6_addr, host, hostlen);
01000 else if (host != NULL && hostlen > strlen(h->h_name))
01001 strcpy(host, h->h_name);
01002 else
01003 return 1;
01004 }
01005
01006 findport(s.sin6->sin6_port, serv, servlen, flags);
01007 }
01008 # endif // AF_INET6
01009
01010 return 1;
01011 }
01012
01013 #endif // HAVE_GETADDRINFO
01014
01015 #ifndef HAVE_INET_NTOP
01016
01017 #define KRF_inet_ntop KRF_USING_OWN_INET_NTOP
01018
01019 static void add_dwords(char *buf, Q_UINT16 *dw, int count)
01020 {
01021 int i = 1;
01022 sprintf(buf + strlen(buf), "%x", ntohs(dw[0]));
01023 while (--count)
01024 sprintf(buf + strlen(buf), ":%x", ntohs(dw[i++]));
01025 }
01026
01027 const char* inet_ntop(int af, const void *cp, char *buf, size_t len)
01028 {
01029 char buf2[sizeof "1234:5678:9abc:def0:1234:5678:255.255.255.255" + 1];
01030 Q_UINT8 *data = (Q_UINT8*)cp;
01031
01032 if (af == AF_INET)
01033 {
01034 sprintf(buf2, "%u.%u.%u.%u", data[0], data[1], data[2], data[3]);
01035
01036 if (len > strlen(buf2))
01037 {
01038 strcpy(buf, buf2);
01039 return buf;
01040 }
01041
01042 errno = ENOSPC;
01043 return NULL;
01044 }
01045
01046 # ifdef AF_INET6
01047 if (af == AF_INET6)
01048 {
01049 Q_UINT16 *p = (Q_UINT16*)data;
01050 Q_UINT16 *longest = NULL, *cur = NULL;
01051 int longest_length = 0, cur_length;
01052 int i;
01053
01054 if (KDE_IN6_IS_ADDR_V4MAPPED(p) || KDE_IN6_IS_ADDR_V4COMPAT(p))
01055 sprintf(buf2, "::%s%u.%u.%u.%u",
01056 KDE_IN6_IS_ADDR_V4MAPPED(p) ? "ffff:" : "",
01057 buf[12], buf[13], buf[14], buf[15]);
01058 else
01059 {
01060
01061 for (i = 0; i < 8; i++)
01062 if (cur == NULL && p[i] == 0)
01063 {
01064
01065 cur = p + i;
01066 cur_length = 1;
01067 }
01068 else if (cur != NULL && p[i] == 0)
01069
01070 cur_length++;
01071 else if (cur != NULL && p[i] != 0)
01072 {
01073
01074 if (cur_length > longest_length)
01075 {
01076 longest_length = cur_length;
01077 longest = cur;
01078 }
01079 cur = NULL;
01080 }
01081 if (cur != NULL && cur_length > longest_length)
01082 {
01083 longest_length = cur_length;
01084 longest = cur;
01085 }
01086
01087 if (longest_length > 1)
01088 {
01089
01090 buf2[0] = '\0';
01091 if (longest != p)
01092 add_dwords(buf2, p, longest - p);
01093 strcat(buf2, "::");
01094 if (longest + longest_length < p + 8)
01095 add_dwords(buf2, longest + longest_length, 8 - (longest - p) - longest_length);
01096 }
01097 else
01098 {
01099
01100 buf2[0] = '\0';
01101 add_dwords(buf2, p, 8);
01102 }
01103 }
01104
01105 if (strlen(buf2) < len)
01106 {
01107 strcpy(buf, buf2);
01108 return buf;
01109 }
01110
01111 errno = ENOSPC;
01112 return NULL;
01113 }
01114 # endif
01115
01116 errno = EAFNOSUPPORT;
01117 return NULL;
01118 }
01119
01120 #else // HAVE_INET_NTOP
01121
01122 #define KRF_inet_ntop 0
01123
01124 #endif // HAVE_INET_NTOP
01125
01126 #ifndef HAVE_INET_PTON
01127
01128 #define KRF_inet_pton KRF_USING_OWN_INET_PTON
01129 int inet_pton(int af, const char *cp, void *buf)
01130 {
01131 if (af == AF_INET)
01132 {
01133
01134 unsigned p[4];
01135 unsigned char *q = (unsigned char*)buf;
01136 if (sscanf(cp, "%u.%u.%u.%u", p, p + 1, p + 2, p + 3) != 4)
01137 return 0;
01138
01139 if (p[0] > 0xff || p[1] > 0xff || p[2] > 0xff || p[3] > 0xff)
01140 return 0;
01141
01142 q[0] = p[0];
01143 q[1] = p[1];
01144 q[2] = p[2];
01145 q[3] = p[3];
01146
01147 return 1;
01148 }
01149
01150 # ifdef AF_INET6
01151 else if (af == AF_INET6)
01152 {
01153 Q_UINT16 addr[8];
01154 const char *p = cp;
01155 int n = 0, start = 8;
01156 bool has_v4 = strchr(p, '.') != NULL;
01157
01158 memset(addr, 0, sizeof(addr));
01159
01160 if (*p == '\0' || p[1] == '\0')
01161 return 0;
01162
01163 if (*p == ':' && p[1] == ':')
01164 {
01165 start = 0;
01166 p += 2;
01167 }
01168 while (*p)
01169 {
01170 if (has_v4 && inet_pton(AF_INET, p, addr + n) != 0)
01171 {
01172
01173 addr[n] = ntohs(addr[n]);
01174 n++;
01175 addr[n] = ntohs(addr[n]);
01176 n++;
01177 break;
01178 }
01179 if (sscanf(p, "%hx", addr + n++) != 1)
01180 return 0;
01181
01182 while (*p && *p != ':')
01183 p++;
01184 if (!*p)
01185 break;
01186 p++;
01187
01188 if (*p == ':')
01189 {
01190 if (start != 8)
01191 return 0;
01192 start = n;
01193 p++;
01194 }
01195 }
01196
01197
01198
01199
01200
01201 if (start == 8 && n != 8)
01202 return 0;
01203 memmove(addr + start + (8 - n), addr + start, (n - start) * sizeof(Q_UINT16));
01204 memset(addr + start, 0, (8 - n) * sizeof(Q_UINT16));
01205
01206
01207
01208 if (htons(0x1234) != 0x1234)
01209 for (n = 0; n < 8; n++)
01210 addr[n] = htons(addr[n]);
01211
01212 memcpy(buf, addr, sizeof(addr));
01213 return 1;
01214 }
01215 # endif
01216
01217 errno = EAFNOSUPPORT;
01218 return -1;
01219 }
01220
01221 #else // HAVE_INET_PTON
01222
01223 #define KRF_inet_pton 0
01224
01225 #endif // HAVE_INET_PTON
01226
01227 #ifdef AF_INET6
01228 # define KRF_afinet6 KRF_KNOWS_AF_INET6
01229 #else
01230 # define KRF_afinet6 0
01231 #endif
01232
01233 namespace KDE
01234 {
01236 extern const int KDE_EXPORT resolverFlags = KRF_getaddrinfo | KRF_resolver | KRF_afinet6 | KRF_inet_ntop | KRF_inet_pton;
01237 }