00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <sys/types.h>
00024 #include <sys/socket.h>
00025 #include <sys/un.h>
00026 #include <netinet/in.h>
00027 #include <stdlib.h>
00028 #include <stdio.h>
00029 #include <errno.h>
00030 #include <unistd.h>
00031 #include <arpa/inet.h>
00032
00033 #include <qglobal.h>
00034
00035
00036
00037
00038 #include <netdb.h>
00039
00040 #include "config.h"
00041 #include "kdebug.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_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 KDE_IPV6_LOOKUP_MODE == 1
00186 static int check_ipv6_stack()
00187 {
00188 # ifndef AF_INET6
00189 return 2;
00190 # else
00191 int fd = ::socket(AF_INET6, SOCK_STREAM, 0);
00192 if (fd == -1)
00193 return 2;
00194
00195 ::close(fd);
00196 return 1;
00197 # endif
00198 }
00199 #endif
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228 int kde_getaddrinfo(const char *name, const char *service,
00229 const struct addrinfo* hint,
00230 struct kde_addrinfo** result)
00231 {
00232 struct kde_addrinfo* res;
00233 struct addrinfo* p;
00234 int err = EAI_SERVICE;
00235 #if KDE_IPV6_LOOKUP_MODE == 1
00236
00237 static int ipv6_stack = 0;
00238 #endif
00239
00240
00241 res = (kde_addrinfo*)malloc(sizeof(*res));
00242 if (res == NULL)
00243 return EAI_MEMORY;
00244 res->data = NULL;
00245 res->origin = KAI_SYSTEM;
00246
00247 struct addrinfo* last = NULL;
00248
00249
00250 if (hint && (hint->ai_family == PF_UNIX))
00251 {
00252 if (service == NULL || *service == '\0')
00253 goto out;
00254
00255
00256
00257
00258 if (name != NULL && !(name[0] == '\0' || (name[0] == '*' && name[1] == '\0') ||
00259 strcmp("localhost", name) == 0))
00260 goto out;
00261
00262 goto do_unix;
00263 }
00264
00265 #if KDE_IPV6_LOOKUP_MODE != 0
00266 # if KDE_IPV6_LOOKUP_MODE == 1
00267
00268 if (ipv6_stack == 0)
00269 ipv6_stack = check_ipv6_stack();
00270
00271 if (ipv6_stack == 2)
00272 {
00273 # endif
00274
00275
00276 struct addrinfo our_hint;
00277 if (hint != NULL)
00278 {
00279 memcpy(&our_hint, hint, sizeof(our_hint));
00280 if (our_hint.ai_family == AF_UNSPEC)
00281 our_hint.ai_family = AF_INET;
00282 }
00283 else
00284 {
00285 memset(&our_hint, 0, sizeof(our_hint));
00286 our_hint.ai_family = AF_INET;
00287 }
00288
00289
00290 err = getaddrinfo(name, service, &our_hint, &res->data);
00291 # if KDE_IPV6_LOOKUP_MODE == 1
00292 }
00293 else
00294 # endif
00295 #endif
00296 #if KDE_IPV6_LOOKUP_MODE != 2
00297
00298 err = getaddrinfo(name, service, hint, &res->data);
00299 #endif
00300
00301
00302
00303 if (service == NULL || *service == '\0')
00304 goto out;
00305
00306
00307
00308
00309 if (name != NULL && !(name[0] == '\0' || (name[0] == '*' && name[1] == '\0') ||
00310 strcmp("localhost", name) == 0))
00311 goto out;
00312
00313
00314
00315 if (hint != NULL && (hint->ai_family != PF_UNSPEC && hint->ai_family != PF_UNIX))
00316 goto out;
00317
00318
00319
00320
00321
00322 if (err == 0)
00323 for (p = res->data; p; p = p->ai_next)
00324 {
00325 last = p;
00326 if (p->ai_family == AF_UNIX)
00327
00328 goto out;
00329 }
00330
00331 do_unix:
00332
00333 p = make_unix(NULL, service);
00334 if (p == NULL)
00335 {
00336 err = EAI_MEMORY;
00337 goto out;
00338 }
00339 if (hint != NULL)
00340 p->ai_socktype = hint->ai_socktype;
00341 if (p->ai_socktype == 0)
00342 p->ai_socktype = SOCK_STREAM;
00343
00344 if (last)
00345 last->ai_next = p;
00346 else
00347 res->data = p;
00348 res->origin = KAI_LOCALUNIX;
00349 *result = res;
00350 return 0;
00351
00352 out:
00353
00354 if (err == 0)
00355 *result = res;
00356 else
00357 {
00358 if (res->data != NULL)
00359 freeaddrinfo(res->data);
00360 free(res);
00361 }
00362 return err;
00363 }
00364
00365 #if defined(HAVE_GETADDRINFO) && !defined(HAVE_BROKEN_GETADDRINFO)
00366
00367 #define KRF_getaddrinfo 0
00368 #define KRF_resolver 0
00369
00370 #else // !defined(HAVE_GETADDRINFO) || defined(HAVE_BROKEN_GETADDRINFO)
00371
00372 #define KRF_getaddrinfo KRF_USING_OWN_GETADDRINFO
00373 #define KRF_resolver KRF_CAN_RESOLVE_UNIX | KRF_CAN_RESOLVE_IPV4
00374
00375
00376
00377
00378
00379
00383 static int inet_lookup(const char *name, int portnum, int protonum,
00384 struct addrinfo *p, const struct addrinfo *hint,
00385 struct addrinfo** result)
00386 {
00387 struct addrinfo *q;
00388 struct hostent *h;
00389 struct sockaddr **psa = NULL;
00390 int len;
00391
00392
00393
00394 # ifdef AF_INET6
00395 if (hint->ai_family == AF_INET6)
00396 {
00397 if (p != NULL)
00398 {
00399 *result = p;
00400 return 0;
00401 }
00402 return EAI_FAIL;
00403 }
00404 # endif
00405
00406 q = (addrinfo*)malloc(sizeof(*q));
00407 if (q == NULL)
00408 {
00409 freeaddrinfo(p);
00410 return EAI_MEMORY;
00411 }
00412
00413 h = gethostbyname(name);
00414 if (h == NULL)
00415 {
00416 if (p != NULL)
00417 {
00418
00419 *result = p;
00420 return 0;
00421 }
00422
00423 switch (h_errno)
00424 {
00425 case HOST_NOT_FOUND:
00426 return EAI_NONAME;
00427 case TRY_AGAIN:
00428 return EAI_AGAIN;
00429 case NO_RECOVERY:
00430 return EAI_FAIL;
00431 case NO_ADDRESS:
00432 return EAI_NODATA;
00433 default:
00434
00435 return EAI_FAIL;
00436 }
00437 }
00438
00439
00440 if (h->h_addrtype == AF_INET && (hint->ai_family == AF_INET || hint->ai_family == AF_UNSPEC))
00441 len = sizeof(struct sockaddr_in);
00442 # ifdef AF_INET6
00443 else if (h->h_addrtype == AF_INET6 && (hint->ai_family == AF_INET6 ||
00444 hint->ai_family == AF_UNSPEC))
00445 len = sizeof(struct sockaddr_in6);
00446 # endif
00447 else
00448 {
00449
00450
00451 if (p != NULL)
00452 {
00453 *result = p;
00454 return 0;
00455 }
00456 return EAI_NODATA;
00457 }
00458
00459 q->ai_flags = 0;
00460 q->ai_family = h->h_addrtype;
00461 q->ai_socktype = hint->ai_socktype;
00462 q->ai_protocol = protonum;
00463 q->ai_addrlen = len;
00464
00465 q->ai_addr = (sockaddr*)malloc(len);
00466 if (q->ai_addr == NULL)
00467 {
00468 free(q);
00469 freeaddrinfo(p);
00470 return EAI_MEMORY;
00471 }
00472 if (h->h_addrtype == AF_INET)
00473 {
00474 struct sockaddr_in *sin = (sockaddr_in*)q->ai_addr;
00475 sin->sin_family = AF_INET;
00476 # ifdef HAVE_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_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_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_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_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_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_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_SOCKADDR_SA_LEN
00753 sin6->sin6_len = sizeof(*sin6);
00754 # endif
00755 sin6->sin6_port = portnum;
00756 sin6->sin6_flowinfo = 0;
00757 sin6->sin6_scope_id = 0;
00758
00759
00760 memset(&sin6->sin6_addr, 0, sizeof(sin6->sin6_addr));
00761 if ((hint->ai_flags & AI_PASSIVE) == 0)
00762 ((char*)&sin6->sin6_addr)[15] = 1;
00763
00764 q->ai_flags = 0;
00765 q->ai_family = AF_INET6;
00766 q->ai_socktype = hint->ai_socktype;
00767 q->ai_protocol = protonum;
00768 q->ai_addrlen = sizeof(*sin6);
00769 q->ai_canonname = NULL;
00770 q->ai_addr = (sockaddr*)sin6;
00771 q->ai_next = p;
00772 p = q;
00773 }
00774
00775 # endif // AF_INET6
00776
00777 *result = p;
00778 return 0;
00779 }
00780
00781 return inet_lookup(name, portnum, protonum, p, hint, result);
00782 }
00783
00784
00785 int getaddrinfo(const char *name, const char *serv,
00786 const struct addrinfo* hint,
00787 struct addrinfo** result)
00788 {
00789 unsigned short portnum;
00790 int protonum = IPPROTO_TCP;
00791 const char *proto = "tcp";
00792 struct addrinfo *p = NULL;
00793
00794
00795 if (hint == NULL || result == NULL)
00796 return EAI_BADFLAGS;
00797 if (hint->ai_family != AF_UNSPEC && hint->ai_family != AF_UNIX &&
00798 hint->ai_family != AF_INET
00799 # ifdef AF_INET6
00800 && hint->ai_family != AF_INET6
00801 # endif
00802 )
00803 return EAI_FAMILY;
00804 if (hint->ai_socktype != 0 && hint->ai_socktype != SOCK_STREAM &&
00805 hint->ai_socktype != SOCK_DGRAM)
00806 return EAI_SOCKTYPE;
00807
00808
00809 if (name != NULL && ((*name == '*' && name[1] == '\0') || *name == '\0'))
00810 name = NULL;
00811
00812 if (serv != NULL && ((*serv == '*' && serv[1] == '\0') || *serv == '\0'))
00813 serv = NULL;
00814
00815 if (name == NULL && serv == NULL)
00816 return EAI_NONAME;
00817
00818
00819 if (name != NULL && strcmp(name, "localhost") == 0)
00820 name = NULL;
00821
00822
00823
00824
00825 if (hint->ai_family == AF_UNIX || hint->ai_family == AF_UNSPEC)
00826 {
00827 if (name != NULL && serv != NULL)
00828 {
00829
00830 if (hint->ai_family == AF_UNIX)
00831 return EAI_BADFLAGS;
00832 }
00833 else
00834 {
00835 p = make_unix(name, serv);
00836 if (p == NULL)
00837 return EAI_MEMORY;
00838
00839 p->ai_socktype = hint->ai_socktype;
00840
00841
00842 if (hint->ai_family == AF_UNIX || ((name != NULL && *name == '/') ||
00843 (serv != NULL && *serv == '/')))
00844 {
00845 *result = p;
00846 return 0;
00847 }
00848 }
00849 }
00850
00851
00852 if (serv != NULL)
00853 {
00854 char *tail;
00855 struct servent *sent;
00856
00857 portnum = htons((unsigned)strtoul(serv, &tail, 10));
00858 if (*tail != '\0')
00859 {
00860
00861 if (hint->ai_socktype == SOCK_DGRAM)
00862 {
00863 proto = "udp";
00864 protonum = IPPROTO_UDP;
00865 }
00866
00867 sent = getservbyname(serv, proto);
00868 if (sent == NULL)
00869 {
00870 if (p == NULL)
00871 return EAI_NONAME;
00872 else
00873 return 0;
00874 }
00875
00876 portnum = sent->s_port;
00877 }
00878 }
00879 else
00880 portnum = 0;
00881
00882 return make_inet(name, portnum, protonum, p, hint, result);
00883 }
00884
00885 void freeaddrinfo(struct addrinfo *p)
00886 {
00887 dofreeaddrinfo(p);
00888 }
00889
00890 char *gai_strerror(int errorcode)
00891 {
00892 static const char * const messages[] =
00893 {
00894 I18N_NOOP("no error"),
00895 I18N_NOOP("address family for nodename not supported"),
00896 I18N_NOOP("temporary failure in name resolution"),
00897 I18N_NOOP("invalid value for 'ai_flags'"),
00898 I18N_NOOP("non-recoverable failure in name resolution"),
00899 I18N_NOOP("'ai_family' not supported"),
00900 I18N_NOOP("memory allocation failure"),
00901 I18N_NOOP("no address associated with nodename"),
00902 I18N_NOOP("name or service not known"),
00903 I18N_NOOP("servname not supported for ai_socktype"),
00904 I18N_NOOP("'ai_socktype' not supported"),
00905 I18N_NOOP("system error")
00906 };
00907
00908 if (errorcode > EAI_SYSTEM || errorcode < 0)
00909 return NULL;
00910
00911 static char buffer[200];
00912 strcpy(buffer, i18n(messages[errorcode]).local8Bit());
00913 return buffer;
00914 }
00915
00916 static void findport(unsigned short port, char *serv, size_t servlen, int flags)
00917 {
00918 if (serv == NULL)
00919 return;
00920
00921 if ((flags & NI_NUMERICSERV) == 0)
00922 {
00923 struct servent *sent;
00924 sent = getservbyport(ntohs(port), flags & NI_DGRAM ? "udp" : "tcp");
00925 if (sent != NULL && servlen > strlen(sent->s_name))
00926 {
00927 strcpy(serv, sent->s_name);
00928 return;
00929 }
00930 }
00931
00932 snprintf(serv, servlen, "%u", ntohs(port));
00933 }
00934
00935 int getnameinfo(const struct sockaddr *sa, ksocklen_t salen,
00936 char *host, size_t hostlen, char *serv, size_t servlen,
00937 int flags)
00938 {
00939 union
00940 {
00941 const sockaddr *sa;
00942 const sockaddr_un *_sun;
00943 const sockaddr_in *sin;
00944 const sockaddr_in6 *sin6;
00945 } s;
00946
00947 if ((host == NULL || hostlen == 0) && (serv == NULL || servlen == 0))
00948 return 1;
00949
00950 s.sa = sa;
00951 if (s.sa->sa_family == AF_UNIX)
00952 {
00953 if (salen < offsetof(struct sockaddr_un, sun_path) + strlen(s._sun->sun_path) + 1)
00954 return 1;
00955
00956 if (servlen && serv != NULL)
00957 *serv = '\0';
00958 if (host != NULL && hostlen > strlen(s._sun->sun_path))
00959 strcpy(host, s._sun->sun_path);
00960
00961 return 0;
00962 }
00963 else if (s.sa->sa_family == AF_INET)
00964 {
00965 if (salen < offsetof(struct sockaddr_in, sin_addr) + sizeof(s.sin->sin_addr))
00966 return 1;
00967
00968 if (flags & NI_NUMERICHOST)
00969 inet_ntop(AF_INET, &s.sin->sin_addr, host, hostlen);
00970 else
00971 {
00972
00973 struct hostent *h = gethostbyaddr((const char*)&s.sin->sin_addr, sizeof(s.sin->sin_addr),
00974 AF_INET);
00975 if (h == NULL && flags & NI_NAMEREQD)
00976 return 1;
00977 else if (h == NULL)
00978 inet_ntop(AF_INET, &s.sin->sin_addr, host, hostlen);
00979 else if (host != NULL && hostlen > strlen(h->h_name))
00980 strcpy(host, h->h_name);
00981 else
00982 return 1;
00983 }
00984
00985 findport(s.sin->sin_port, serv, servlen, flags);
00986 }
00987 # ifdef AF_INET6
00988 else if (s.sa->sa_family == AF_INET6)
00989 {
00990 if (salen < offsetof(struct sockaddr_in6, sin6_addr) + sizeof(s.sin6->sin6_addr))
00991 return 1;
00992
00993 if (flags & NI_NUMERICHOST)
00994 inet_ntop(AF_INET6, &s.sin6->sin6_addr, host, hostlen);
00995 else
00996 {
00997
00998 struct hostent *h = gethostbyaddr((const char*)&s.sin->sin_addr, sizeof(s.sin->sin_addr),
00999 AF_INET6);
01000 if (h == NULL && flags & NI_NAMEREQD)
01001 return 1;
01002 else if (h == NULL)
01003 inet_ntop(AF_INET6, &s.sin6->sin6_addr, host, hostlen);
01004 else if (host != NULL && hostlen > strlen(h->h_name))
01005 strcpy(host, h->h_name);
01006 else
01007 return 1;
01008 }
01009
01010 findport(s.sin6->sin6_port, serv, servlen, flags);
01011 }
01012 # endif // AF_INET6
01013
01014 return 1;
01015 }
01016
01017 #endif // HAVE_GETADDRINFO
01018
01019 #ifndef HAVE_INET_NTOP
01020
01021 #define KRF_inet_ntop KRF_USING_OWN_INET_NTOP
01022
01023 static void add_dwords(char *buf, Q_UINT16 *dw, int count)
01024 {
01025 int i = 1;
01026 sprintf(buf + strlen(buf), "%x", ntohs(dw[0]));
01027 while (--count)
01028 sprintf(buf + strlen(buf), ":%x", ntohs(dw[i++]));
01029 }
01030
01031 const char* inet_ntop(int af, const void *cp, char *buf, size_t len)
01032 {
01033 char buf2[sizeof "1234:5678:9abc:def0:1234:5678:255.255.255.255" + 1];
01034 Q_UINT8 *data = (Q_UINT8*)cp;
01035
01036 if (af == AF_INET)
01037 {
01038 sprintf(buf2, "%u.%u.%u.%u", data[0], data[1], data[2], data[3]);
01039
01040 if (len > strlen(buf2))
01041 {
01042 strcpy(buf, buf2);
01043 return buf;
01044 }
01045
01046 errno = ENOSPC;
01047 return NULL;
01048 }
01049
01050 # ifdef AF_INET6
01051 if (af == AF_INET6)
01052 {
01053 Q_UINT16 *p = (Q_UINT16*)data;
01054 Q_UINT16 *longest = NULL, *cur = NULL;
01055 int longest_length = 0, cur_length;
01056 int i;
01057
01058 if (KDE_IN6_IS_ADDR_V4MAPPED(p) || KDE_IN6_IS_ADDR_V4COMPAT(p))
01059 sprintf(buf2, "::%s%u.%u.%u.%u",
01060 KDE_IN6_IS_ADDR_V4MAPPED(p) ? "ffff:" : "",
01061 buf[12], buf[13], buf[14], buf[15]);
01062 else
01063 {
01064
01065 for (i = 0; i < 8; i++)
01066 if (cur == NULL && p[i] == 0)
01067 {
01068
01069 cur = p + i;
01070 cur_length = 1;
01071 }
01072 else if (cur != NULL && p[i] == 0)
01073
01074 cur_length++;
01075 else if (cur != NULL && p[i] != 0)
01076 {
01077
01078 if (cur_length > longest_length)
01079 {
01080 longest_length = cur_length;
01081 longest = cur;
01082 }
01083 cur = NULL;
01084 }
01085 if (cur != NULL && cur_length > longest_length)
01086 {
01087 longest_length = cur_length;
01088 longest = cur;
01089 }
01090
01091 if (longest_length > 1)
01092 {
01093
01094 buf2[0] = '\0';
01095 if (longest != p)
01096 add_dwords(buf2, p, longest - p);
01097 strcat(buf2, "::");
01098 if (longest + longest_length < p + 8)
01099 add_dwords(buf2, longest + longest_length, 8 - (longest - p) - longest_length);
01100 }
01101 else
01102 {
01103
01104 buf2[0] = '\0';
01105 add_dwords(buf2, p, 8);
01106 }
01107 }
01108
01109 if (strlen(buf2) < len)
01110 {
01111 strcpy(buf, buf2);
01112 return buf;
01113 }
01114
01115 errno = ENOSPC;
01116 return NULL;
01117 }
01118 # endif
01119
01120 errno = EAFNOSUPPORT;
01121 return NULL;
01122 }
01123
01124 #else // HAVE_INET_NTOP
01125
01126 #define KRF_inet_ntop 0
01127
01128 #endif // HAVE_INET_NTOP
01129
01130 #ifndef HAVE_INET_PTON
01131
01132 #define KRF_inet_pton KRF_USING_OWN_INET_PTON
01133 int inet_pton(int af, const char *cp, void *buf)
01134 {
01135 if (af == AF_INET)
01136 {
01137
01138 unsigned p[4];
01139 unsigned char *q = (unsigned char*)buf;
01140 if (sscanf(cp, "%u.%u.%u.%u", p, p + 1, p + 2, p + 3) != 4)
01141 return 0;
01142
01143 if (p[0] > 0xff || p[1] > 0xff || p[2] > 0xff || p[3] > 0xff)
01144 return 0;
01145
01146 q[0] = p[0];
01147 q[1] = p[1];
01148 q[2] = p[2];
01149 q[3] = p[3];
01150
01151 return 1;
01152 }
01153
01154 # ifdef AF_INET6
01155 else if (af == AF_INET6)
01156 {
01157 Q_UINT16 addr[8];
01158 const char *p = cp;
01159 int n = 0, start = 8;
01160 bool has_v4 = strchr(p, '.') != NULL;
01161
01162 memset(addr, 0, sizeof(addr));
01163
01164 if (*p == '\0' || p[1] == '\0')
01165 return 0;
01166
01167 if (*p == ':' && p[1] == ':')
01168 {
01169 start = 0;
01170 p += 2;
01171 }
01172 while (*p)
01173 {
01174 if (has_v4 && inet_pton(AF_INET, p, addr + n) != 0)
01175 {
01176
01177 addr[n] = ntohs(addr[n]);
01178 n++;
01179 addr[n] = ntohs(addr[n]);
01180 n++;
01181 break;
01182 }
01183 if (sscanf(p, "%hx", addr + n++) != 1)
01184 return 0;
01185
01186 while (*p && *p != ':')
01187 p++;
01188 if (!*p)
01189 break;
01190 p++;
01191
01192 if (*p == ':')
01193 {
01194 if (start != 8)
01195 return 0;
01196 start = n;
01197 p++;
01198 }
01199 }
01200
01201
01202
01203
01204
01205 if (start == 8 && n != 8)
01206 return 0;
01207 memmove(addr + start + (8 - n), addr + start, (n - start) * sizeof(Q_UINT16));
01208 memset(addr + start, 0, (8 - n) * sizeof(Q_UINT16));
01209
01210
01211
01212 if (htons(0x1234) != 0x1234)
01213 for (n = 0; n < 8; n++)
01214 addr[n] = htons(addr[n]);
01215
01216 memcpy(buf, addr, sizeof(addr));
01217 return 1;
01218 }
01219 # endif
01220
01221 errno = EAFNOSUPPORT;
01222 return -1;
01223 }
01224
01225 #else // HAVE_INET_PTON
01226
01227 #define KRF_inet_pton 0
01228
01229 #endif // HAVE_INET_PTON
01230
01231 #ifdef AF_INET6
01232 # define KRF_afinet6 KRF_KNOWS_AF_INET6
01233 #else
01234 # define KRF_afinet6 0
01235 #endif
01236
01237 namespace KDE
01238 {
01239 extern const int resolverFlags = KRF_getaddrinfo | KRF_resolver | KRF_afinet6 | KRF_inet_ntop | KRF_inet_pton;
01240 }