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 <QtCore/QBool>
00032
00033 #include <kdebug.h>
00034
00035
00036
00037
00038 #include <netdb.h>
00039
00040 #include <config.h>
00041 #include <config-network.h>
00042 #include "klocale.h"
00043
00044 #ifndef IN6_IS_ADDR_V4MAPPED
00045 #define NEED_IN6_TESTS
00046 #endif
00047 #undef CLOBBER_IN6
00048 #include "netsupp.h"
00049
00050 #if defined(__hpux) || defined(_HPUX_SOURCE)
00051 extern int h_errno;
00052 #endif
00053
00054 #if !defined(kde_sockaddr_in6)
00055
00056
00057
00058
00059
00060
00061
00062 # define sockaddr_in6 kde_sockaddr_in6
00063 # define in6_addr kde_in6_addr
00064 #endif
00065
00066 #ifdef offsetof
00067 #undef offsetof
00068 #endif
00069 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
00070
00071
00072
00073
00074
00075
00076 #define KRF_KNOWS_AF_INET6 0x01
00077 #define KRF_USING_OWN_GETADDRINFO 0x02
00078 #define KRF_USING_OWN_INET_NTOP 0x04
00079 #define KRF_USING_OWN_INET_PTON 0x08
00080 #define KRF_CAN_RESOLVE_UNIX 0x100
00081 #define KRF_CAN_RESOLVE_IPV4 0x200
00082 #define KRF_CAN_RESOLVE_IPV6 0x400
00083
00084
00085 static void dofreeaddrinfo(struct addrinfo *ai)
00086 {
00087 while (ai)
00088 {
00089 struct addrinfo *ai2 = ai;
00090 if (ai->ai_canonname != NULL)
00091 free(ai->ai_canonname);
00092
00093 if (ai->ai_addr != NULL)
00094 free(ai->ai_addr);
00095
00096 ai = ai->ai_next;
00097 free(ai2);
00098 }
00099 }
00100
00101 void kde_freeaddrinfo(struct kde_addrinfo *ai)
00102 {
00103 if (ai->origin == KAI_LOCALUNIX)
00104 {
00105 struct addrinfo *p, *last = NULL;
00106
00107
00108 for (p = ai->data; p; p = p->ai_next)
00109 {
00110 if (p->ai_family == AF_UNIX)
00111 {
00112 if (last)
00113 {
00114 last->ai_next = NULL;
00115 freeaddrinfo(ai->data);
00116 }
00117 dofreeaddrinfo(p);
00118 break;
00119 }
00120 last = p;
00121 }
00122 }
00123 else
00124 freeaddrinfo(ai->data);
00125
00126 free(ai);
00127 }
00128
00129 static struct addrinfo*
00130 make_unix(const char *name, const char *serv)
00131 {
00132 const char *buf;
00133 struct addrinfo *p;
00134 struct sockaddr_un *_sun;
00135 int len;
00136
00137 p = (addrinfo*)malloc(sizeof(*p));
00138 if (p == NULL)
00139 return NULL;
00140 memset(p, 0, sizeof(*p));
00141
00142 if (name != NULL)
00143 buf = name;
00144 else
00145 buf = serv;
00146
00147
00148 len = strlen(buf) + offsetof(struct sockaddr_un, sun_path) + 1;
00149 if (*buf != '/')
00150 len += 5;
00151
00152 _sun = (sockaddr_un*)malloc(len);
00153 if (_sun == NULL)
00154 {
00155
00156 free(p);
00157 return NULL;
00158 }
00159
00160 _sun->sun_family = AF_UNIX;
00161 # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
00162 _sun->sun_len = len;
00163 # endif
00164 if (*buf == '/')
00165 *_sun->sun_path = '\0';
00166 else
00167 strcpy(_sun->sun_path, "/tmp/");
00168 strcat(_sun->sun_path, buf);
00169
00170
00171 p->ai_family = AF_UNIX;
00172 p->ai_addrlen = len;
00173 p->ai_addr = (sockaddr*)_sun;
00174 p->ai_canonname = strdup(buf);
00175
00176 return p;
00177 }
00178
00179
00180
00181
00182
00183
00184
00185 #if 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 (!qgetenv("KDE_NO_IPV6").isEmpty())
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 kError() << "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 *(quint32*)&sin->sin_addr = INADDR_ANY;
00719 else
00720 *(quint32*)&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 #ifndef HAVE_GAI_STRERROR_PROTO
00887 char *gai_strerror(int errorcode)
00888 {
00889 static const char messages[] =
00890 {
00891 I18N_NOOP("no error")"\0"
00892 I18N_NOOP("address family for nodename not supported")"\0"
00893 I18N_NOOP("temporary failure in name resolution")"\0"
00894 I18N_NOOP("invalid value for 'ai_flags'")"\0"
00895 I18N_NOOP("non-recoverable failure in name resolution")"\0"
00896 I18N_NOOP("'ai_family' not supported")"\0"
00897 I18N_NOOP("memory allocation failure")"\0"
00898 I18N_NOOP("no address associated with nodename")"\0"
00899 I18N_NOOP("name or service not known")"\0"
00900 I18N_NOOP("servname not supported for ai_socktype")"\0"
00901 I18N_NOOP("'ai_socktype' not supported")"\0"
00902 I18N_NOOP("system error")"\0"
00903 "\0"
00904 };
00905
00906 static const int messages_indices[] =
00907 {
00908 0, 9, 51, 88, 117, 160, 186, 212,
00909 248, 274, 313, 341, 0
00910 };
00911
00912 Q_ASSERT(sizeof(messages_indices)/sizeof(messages_indices[0]) >= EAI_SYSTEM);
00913 if (errorcode > EAI_SYSTEM || errorcode < 0)
00914 return NULL;
00915
00916 static char buffer[200];
00917 strcpy(buffer, i18n(messages + messages_indices[errorcode]).toLocal8Bit());
00918 return buffer;
00919 }
00920 #endif
00921
00922 static void findport(unsigned short port, char *serv, size_t servlen, int flags)
00923 {
00924 if (serv == NULL)
00925 return;
00926
00927 if ((flags & NI_NUMERICSERV) == 0)
00928 {
00929 struct servent *sent;
00930 sent = getservbyport(ntohs(port), flags & NI_DGRAM ? "udp" : "tcp");
00931 if (sent != NULL && servlen > strlen(sent->s_name))
00932 {
00933 strcpy(serv, sent->s_name);
00934 return;
00935 }
00936 }
00937
00938 qsnprintf(serv, servlen, "%u", ntohs(port));
00939 }
00940
00941 int getnameinfo(const struct sockaddr *sa, kde_socklen_t salen,
00942 char *host, size_t hostlen, char *serv, size_t servlen,
00943 int flags)
00944 {
00945 union
00946 {
00947 const sockaddr *sa;
00948 const sockaddr_un *_sun;
00949 const sockaddr_in *sin;
00950 const sockaddr_in6 *sin6;
00951 } s;
00952
00953 if ((host == NULL || hostlen == 0) && (serv == NULL || servlen == 0))
00954 return 1;
00955
00956 s.sa = sa;
00957 if (s.sa->sa_family == AF_UNIX)
00958 {
00959 if (salen < offsetof(struct sockaddr_un, sun_path) + strlen(s._sun->sun_path) + 1)
00960 return 1;
00961
00962 if (servlen && serv != NULL)
00963 *serv = '\0';
00964 if (host != NULL && hostlen > strlen(s._sun->sun_path))
00965 strcpy(host, s._sun->sun_path);
00966
00967 return 0;
00968 }
00969 else if (s.sa->sa_family == AF_INET)
00970 {
00971 if (salen < offsetof(struct sockaddr_in, sin_addr) + sizeof(s.sin->sin_addr))
00972 return 1;
00973
00974 if (flags & NI_NUMERICHOST)
00975 inet_ntop(AF_INET, &s.sin->sin_addr, host, hostlen);
00976 else
00977 {
00978
00979 struct hostent *h = gethostbyaddr((const char*)&s.sin->sin_addr, sizeof(s.sin->sin_addr),
00980 AF_INET);
00981 if (h == NULL && flags & NI_NAMEREQD)
00982 return 1;
00983 else if (h == NULL)
00984 inet_ntop(AF_INET, &s.sin->sin_addr, host, hostlen);
00985 else if (host != NULL && hostlen > strlen(h->h_name))
00986 strcpy(host, h->h_name);
00987 else
00988 return 1;
00989 }
00990
00991 findport(s.sin->sin_port, serv, servlen, flags);
00992 }
00993 # ifdef AF_INET6
00994 else if (s.sa->sa_family == AF_INET6)
00995 {
00996 if (salen < offsetof(struct sockaddr_in6, sin6_addr) + sizeof(s.sin6->sin6_addr))
00997 return 1;
00998
00999 if (flags & NI_NUMERICHOST)
01000 inet_ntop(AF_INET6, &s.sin6->sin6_addr, host, hostlen);
01001 else
01002 {
01003
01004 struct hostent *h = gethostbyaddr((const char*)&s.sin->sin_addr, sizeof(s.sin->sin_addr),
01005 AF_INET6);
01006 if (h == NULL && flags & NI_NAMEREQD)
01007 return 1;
01008 else if (h == NULL)
01009 inet_ntop(AF_INET6, &s.sin6->sin6_addr, host, hostlen);
01010 else if (host != NULL && hostlen > strlen(h->h_name))
01011 strcpy(host, h->h_name);
01012 else
01013 return 1;
01014 }
01015
01016 findport(s.sin6->sin6_port, serv, servlen, flags);
01017 }
01018 # endif // AF_INET6
01019
01020 return 1;
01021 }
01022
01023 #endif // HAVE_GETADDRINFO
01024
01025 #ifndef HAVE_INET_NTOP
01026
01027 #define KRF_inet_ntop KRF_USING_OWN_INET_NTOP
01028
01029 static void add_dwords(char *buf, quint16 *dw, int count)
01030 {
01031 int i = 1;
01032 sprintf(buf + strlen(buf), "%x", ntohs(dw[0]));
01033 while (--count)
01034 sprintf(buf + strlen(buf), ":%x", ntohs(dw[i++]));
01035 }
01036
01037 const char* inet_ntop(int af, const void *cp, char *buf, size_t len)
01038 {
01039 char buf2[sizeof "1234:5678:9abc:def0:1234:5678:255.255.255.255" + 1];
01040 quint8 *data = (quint8*)cp;
01041
01042 if (af == AF_INET)
01043 {
01044 sprintf(buf2, "%u.%u.%u.%u", data[0], data[1], data[2], data[3]);
01045
01046 if (len > strlen(buf2))
01047 {
01048 strcpy(buf, buf2);
01049 return buf;
01050 }
01051
01052 errno = ENOSPC;
01053 return NULL;
01054 }
01055
01056 # ifdef AF_INET6
01057 if (af == AF_INET6)
01058 {
01059 quint16 *p = (quint16*)data;
01060 quint16 *longest = NULL, *cur = NULL;
01061 int longest_length = 0, cur_length;
01062 int i;
01063
01064 if (KDE_IN6_IS_ADDR_V4MAPPED(p) || KDE_IN6_IS_ADDR_V4COMPAT(p))
01065 sprintf(buf2, "::%s%u.%u.%u.%u",
01066 KDE_IN6_IS_ADDR_V4MAPPED(p) ? "ffff:" : "",
01067 buf[12], buf[13], buf[14], buf[15]);
01068 else
01069 {
01070
01071 for (i = 0; i < 8; i++)
01072 if (cur == NULL && p[i] == 0)
01073 {
01074
01075 cur = p + i;
01076 cur_length = 1;
01077 }
01078 else if (cur != NULL && p[i] == 0)
01079
01080 cur_length++;
01081 else if (cur != NULL && p[i] != 0)
01082 {
01083
01084 if (cur_length > longest_length)
01085 {
01086 longest_length = cur_length;
01087 longest = cur;
01088 }
01089 cur = NULL;
01090 }
01091 if (cur != NULL && cur_length > longest_length)
01092 {
01093 longest_length = cur_length;
01094 longest = cur;
01095 }
01096
01097 if (longest_length > 1)
01098 {
01099
01100 buf2[0] = '\0';
01101 if (longest != p)
01102 add_dwords(buf2, p, longest - p);
01103 strcat(buf2, "::");
01104 if (longest + longest_length < p + 8)
01105 add_dwords(buf2, longest + longest_length, 8 - (longest - p) - longest_length);
01106 }
01107 else
01108 {
01109
01110 buf2[0] = '\0';
01111 add_dwords(buf2, p, 8);
01112 }
01113 }
01114
01115 if (strlen(buf2) < len)
01116 {
01117 strcpy(buf, buf2);
01118 return buf;
01119 }
01120
01121 errno = ENOSPC;
01122 return NULL;
01123 }
01124 # endif
01125
01126 errno = EAFNOSUPPORT;
01127 return NULL;
01128 }
01129
01130 #else // HAVE_INET_NTOP
01131
01132 #define KRF_inet_ntop 0
01133
01134 #endif // HAVE_INET_NTOP
01135
01136 #ifndef HAVE_INET_PTON
01137
01138 #define KRF_inet_pton KRF_USING_OWN_INET_PTON
01139 int inet_pton(int af, const char *cp, void *buf)
01140 {
01141 if (af == AF_INET)
01142 {
01143
01144 unsigned p[4];
01145 unsigned char *q = (unsigned char*)buf;
01146 if (sscanf(cp, "%u.%u.%u.%u", p, p + 1, p + 2, p + 3) != 4)
01147 return 0;
01148
01149 if (p[0] > 0xff || p[1] > 0xff || p[2] > 0xff || p[3] > 0xff)
01150 return 0;
01151
01152 q[0] = p[0];
01153 q[1] = p[1];
01154 q[2] = p[2];
01155 q[3] = p[3];
01156
01157 return 1;
01158 }
01159
01160 # ifdef AF_INET6
01161 else if (af == AF_INET6)
01162 {
01163 quint16 addr[8];
01164 const char *p = cp;
01165 int n = 0, start = 8;
01166 bool has_v4 = strchr(p, '.') != NULL;
01167
01168 memset(addr, 0, sizeof(addr));
01169
01170 if (*p == '\0' || p[1] == '\0')
01171 return 0;
01172
01173 if (*p == ':' && p[1] == ':')
01174 {
01175 start = 0;
01176 p += 2;
01177 }
01178 while (*p)
01179 {
01180 if (has_v4 && inet_pton(AF_INET, p, addr + n) != 0)
01181 {
01182
01183 addr[n] = ntohs(addr[n]);
01184 n++;
01185 addr[n] = ntohs(addr[n]);
01186 n++;
01187 break;
01188 }
01189 if (sscanf(p, "%hx", addr + n++) != 1)
01190 return 0;
01191
01192 while (*p && *p != ':')
01193 p++;
01194 if (!*p)
01195 break;
01196 p++;
01197
01198 if (*p == ':')
01199 {
01200 if (start != 8)
01201 return 0;
01202 start = n;
01203 p++;
01204 }
01205 }
01206
01207
01208
01209
01210
01211 if (start == 8 && n != 8)
01212 return 0;
01213 memmove(addr + start + (8 - n), addr + start, (n - start) * sizeof(quint16));
01214 memset(addr + start, 0, (8 - n) * sizeof(quint16));
01215
01216
01217
01218 if (htons(0x1234) != 0x1234)
01219 for (n = 0; n < 8; n++)
01220 addr[n] = htons(addr[n]);
01221
01222 memcpy(buf, addr, sizeof(addr));
01223 return 1;
01224 }
01225 # endif
01226
01227 errno = EAFNOSUPPORT;
01228 return -1;
01229 }
01230
01231 #else // HAVE_INET_PTON
01232
01233 #define KRF_inet_pton 0
01234
01235 #endif // HAVE_INET_PTON
01236
01237 #ifdef AF_INET6
01238 # define KRF_afinet6 KRF_KNOWS_AF_INET6
01239 #else
01240 # define KRF_afinet6 0
01241 #endif
01242
01243 namespace KDE
01244 {
01246 extern const int resolverFlags = KRF_getaddrinfo | KRF_resolver | KRF_afinet6 | KRF_inet_ntop | KRF_inet_pton;
01247 }