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
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 KDE_EXPORT resolverFlags = KRF_getaddrinfo | KRF_resolver | KRF_afinet6 | KRF_inet_ntop | KRF_inet_pton;
01243 }