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 defined(KDE_IPV6_LOOKUP_MODE) && 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 defined(KDE_IPV6_LOOKUP_MODE) && 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 defined(KDE_IPV6_LOOKUP_MODE) && 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 defined(KDE_IPV6_LOOKUP_MODE) && 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
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
01013
01014 return 1;
01015 }
01016
01017 #endif
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
01226
01227 #define KRF_inet_pton 0
01228
01229 #endif
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 KDE_EXPORT const int resolverFlags = KRF_getaddrinfo | KRF_resolver | KRF_afinet6 | KRF_inet_ntop | KRF_inet_pton;
01241 }