netsupp.cpp
00001 /* 00002 * This file is part of the KDE libraries 00003 * Copyright (C) 2000,2001 Thiago Macieira <thiago.macieira@kdemail.net> 00004 * 00005 * This library is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU Library General Public 00007 * License as published by the Free Software Foundation; either 00008 * version 2 of the License, or (at your option) any later version. 00009 * 00010 * This library is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 * Library General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU Library General Public License 00016 * along with this library; see the file COPYING.LIB. If not, write to 00017 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00018 * Boston, MA 02110-1301, USA. 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 <tqglobal.h> 00032 00033 // This is so that, if addrinfo is defined, it doesn't clobber our definition 00034 // It might be defined in the few cases in which we are replacing the system's 00035 // broken getaddrinfo 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 * kde_sockaddr_in6 might have got defined even though we #undef'ed 00057 * CLOBBER_IN6. This happens when we are compiling under --enable-final. 00058 * However, in that case, if it was defined, that's because ksockaddr.cpp 00059 * had it defined because sockaddr_in6 didn't exist, and so sockaddr_in6 00060 * exists and is our kde_sockaddr_in6 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 * These constants tell the flags in KDE::resolverFlags 00073 * The user could (but shouldn't) test the variable to know what kind of 00074 * resolution is supported 00075 */ 00076 #define KRF_KNOWS_AF_INET6 0x01 /* if present, the code knows about AF_INET6 */ 00077 #define KRF_USING_OWN_GETADDRINFO 0x02 /* if present, we are using our own getaddrinfo */ 00078 #define KRF_USING_OWN_INET_NTOP 0x04 /* if present, we are using our own inet_ntop */ 00079 #define KRF_USING_OWN_INET_PTON 0x08 /* if present, we are using our own inet_pton */ 00080 #define KRF_CAN_RESOLVE_UNIX 0x100 /* if present, the resolver can resolve Unix sockets */ 00081 #define KRF_CAN_RESOLVE_IPV4 0x200 /* if present, the resolver can resolve to IPv4 */ 00082 #define KRF_CAN_RESOLVE_IPV6 0x400 /* if present, the resolver can resolve to IPv6 */ 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 /* We've added one AF_UNIX socket in here, to the 00107 * tail of the linked list. We have to find it */ 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 // Calculate length of the binary representation 00148 len = strlen(buf) + offsetof(struct sockaddr_un, sun_path) + 1; 00149 if (*buf != '/') 00150 len += 5; // strlen("/tmp/"); 00151 00152 _sun = (sockaddr_un*)malloc(len); 00153 if (_sun == NULL) 00154 { 00155 // Oops 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'; // empty it 00166 else 00167 strcpy(_sun->sun_path, "/tmp/"); 00168 strcat(_sun->sun_path, buf); 00169 00170 // Set the addrinfo 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 // Ugh. I hate #ifdefs 00180 // Anyways, here's what this does: 00181 // KDE_IPV6_LOOKUP_MODE != 1, this function doesn't exist 00182 // AF_INET6 not defined, we say there is no IPv6 stack 00183 // otherwise, we try to create a socket. 00184 // returns: 1 for IPv6 stack available, 2 for not available 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; // how can we check? 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 * Reason for using this function: kde_getaddrinfo 00206 * 00207 * I decided to add this wrapper function for getaddrinfo 00208 * and have this be called by KExtendedSocket instead of 00209 * the real getaddrinfo so that we can make sure that the 00210 * behavior is the desired one. 00211 * 00212 * Currently, the only "undesired" behavior is getaddrinfo 00213 * not returning PF_UNIX sockets in some implementations. 00214 * 00215 * getaddrinfo and family are defined in POSIX 1003.1g 00216 * (Protocol Independent Interfaces) and in RFC 2553 00217 * (Basic Socket Interface for IPv6). Whereas the RFC is ambiguosly 00218 * vague whether this family of functions should return Internet 00219 * sockets only or not, the name of the POSIX draft says 00220 * otherwise: it should be independent of protocol. 00221 * 00222 * So, my interpretation is that they should return every 00223 * kind of socket available and known and that's how I 00224 * designed KExtendedSocket on top of it. 00225 * 00226 * That's why there's this wrapper, to make sure PF_UNIX 00227 * sockets are returned when expected. 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 // mode 1: do a check on whether we have an IPv6 stack 00239 static int ipv6_stack = 0; // 0: unknown, 1: yes, 2: no 00240 #endif 00241 00242 // allocate memory for results 00243 res = (kde_addrinfo*)malloc(sizeof(*res)); 00244 if (res == NULL) 00245 return EAI_MEMORY; 00246 res->data = NULL; 00247 res->origin = KAI_SYSTEM; // at first, it'll be only system data 00248 00249 struct addrinfo* last = NULL; 00250 00251 // Skip the getaddrinfo call and the ipv6 check for a UNIX socket. 00252 if (hint && (hint->ai_family == PF_UNIX)) 00253 { 00254 if (service == NULL || *service == '\0') 00255 goto out; // can't be Unix if no service was requested 00256 00257 // Unix sockets must be localhost 00258 // That is, either name is NULL or, if it's not, it must be empty, 00259 // "*" or "localhost" 00260 if (name != NULL && !(name[0] == '\0' || (name[0] == '*' && name[1] == '\0') || 00261 strcmp("localhost", name) == 0)) 00262 goto out; // isn't localhost 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 // mode 1: do a check on whether we have an IPv6 stack 00270 if (ipv6_stack == 0) 00271 ipv6_stack = check_ipv6_stack(); 00272 00273 if (ipv6_stack == 2) 00274 { 00275 # endif 00276 // here we have modes 1 and 2 (no lookups) 00277 // this is shared code 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 // do the actual resolution 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 // do the IPV6 resolution 00300 err = getaddrinfo(name, service, hint, &res->data); 00301 #endif 00302 00303 // Now we have to check whether the user could want a Unix socket 00304 00305 if (service == NULL || *service == '\0') 00306 goto out; // can't be Unix if no service was requested 00307 00308 // Unix sockets must be localhost 00309 // That is, either name is NULL or, if it's not, it must be empty, 00310 // "*" or "localhost" 00311 if (name != NULL && !(name[0] == '\0' || (name[0] == '*' && name[1] == '\0') || 00312 strcmp("localhost", name) == 0)) 00313 goto out; // isn't localhost 00314 00315 // Unix sockets can only be returned if the user asked for a PF_UNSPEC 00316 // or PF_UNIX socket type or gave us a NULL hint 00317 if (hint != NULL && (hint->ai_family != PF_UNSPEC && hint->ai_family != PF_UNIX)) 00318 goto out; // user doesn't want Unix 00319 00320 // If we got here, then it means that the user might be expecting Unix 00321 // sockets. The user wants a local socket, with a non-null service and 00322 // has told us that they accept PF_UNIX sockets 00323 // Check whether the system implementation returned Unix 00324 if (err == 0) 00325 for (p = res->data; p; p = p->ai_next) 00326 { 00327 last = p; // we have to find out which one is last anyways 00328 if (p->ai_family == AF_UNIX) 00329 // there is an Unix node 00330 goto out; 00331 } 00332 00333 do_unix: 00334 // So, give the user a PF_UNIX socket 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; // default 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 * No getaddrinfo() in this system. 00373 * We shall provide our own 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 // TODO 00389 // Currently, this never resolves IPv6 (need gethostbyname2, etc.) 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 // There already is a suitable result 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 // EH!? 00431 return EAI_FAIL; 00432 } 00433 } 00434 00435 // convert the hostent to addrinfo 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 // We don't know what to do with these addresses 00446 // Or gethostbyname returned information we don't want 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 // cycle through the rest of the hosts; 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; // Whew! Success! 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 // This 'do' is here just so that we can 'break' out of it 00563 00564 if (name != NULL) 00565 { 00566 // first, try to use inet_pton before resolving 00567 // it will catch IP addresses given without having to go to lookup 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 // yes, this is IPv6 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; // not a numeric host 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; // no interface 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; // success! 00630 } 00631 # endif // AF_INET6 00632 00633 if (hint->ai_family == AF_INET || hint->ai_family == AF_UNSPEC) 00634 { 00635 // This has to be IPv4 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; // invalid, I guess 00642 } 00643 break; // not a numeric host, do lookup 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 // Eh, what!? 00681 // One of the two above has to have matched 00682 kdError() << "I wasn't supposed to get here!"; 00683 } 00684 } while (false); 00685 00686 // This means localhost 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 // Do IPv4 first 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 *(TQ_UINT32*)&sin->sin_addr = INADDR_ANY; 00719 else 00720 *(TQ_UINT32*)&sin->sin_addr = htonl(INADDR_LOOPBACK); 00721 q->ai_flags = 0; 00722 q->ai_family = AF_INET; 00723 q->ai_socktype = hint->ai_socktype; 00724 q->ai_protocol = protonum; 00725 q->ai_addrlen = sizeof(*sin); 00726 q->ai_canonname = NULL; 00727 q->ai_addr = (sockaddr*)sin; 00728 q->ai_next = p; 00729 p = q; 00730 } 00731 00732 # ifdef AF_INET6 00733 // Try now IPv6 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 // We don't want to use in6addr_loopback and in6addr_any 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; // success! 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; // remember to store in network byte order 00786 int protonum = IPPROTO_TCP; 00787 const char *proto = "tcp"; 00788 struct addrinfo *p = NULL; 00789 00790 // Sanity checks: 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 // Treat hostname of "*" as NULL, which means localhost 00805 if (name != NULL && ((*name == '*' && name[1] == '\0') || *name == '\0')) 00806 name = NULL; 00807 // Treat service of "*" as NULL, which I guess means no port (0) 00808 if (serv != NULL && ((*serv == '*' && serv[1] == '\0') || *serv == '\0')) 00809 serv = NULL; 00810 00811 if (name == NULL && serv == NULL) // what the hell do you want? 00812 return EAI_NONAME; 00813 00814 // This is just to make it easier 00815 if (name != NULL && strcmp(name, "localhost") == 0) 00816 name = NULL; 00817 00818 // First, check for a Unix socket 00819 // family must be either AF_UNIX or AF_UNSPEC 00820 // either of name or serv must be set, the other must be NULL or empty 00821 if (hint->ai_family == AF_UNIX || hint->ai_family == AF_UNSPEC) 00822 { 00823 if (name != NULL && serv != NULL) 00824 { 00825 // This is not allowed 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 // If the name/service started with a slash, then this *IS* 00837 // only a Unix socket. Return. 00838 if (hint->ai_family == AF_UNIX || ((name != NULL && *name == '/') || 00839 (serv != NULL && *serv == '/'))) 00840 { 00841 *result = p; 00842 return 0; // successful lookup 00843 } 00844 } 00845 } 00846 00847 // Lookup the service name, if required 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 // not a number. We have to do the lookup 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) // no service? 00865 { 00866 if (p == NULL) 00867 return EAI_NONAME; 00868 else 00869 return 0; // a Unix socket available 00870 } 00871 00872 portnum = sent->s_port; 00873 } 00874 } 00875 else 00876 portnum = 0; // no port number 00877 00878 return make_inet(name, portnum, protonum, p, hint, result); 00879 } 00880 00881 void freeaddrinfo(struct addrinfo *p) 00882 { 00883 dofreeaddrinfo(p); 00884 } 00885 00886 char *gai_strerror(int errorcode) 00887 { 00888 static const char * const messages[] = 00889 { 00890 I18N_NOOP("no error"), // 0 00891 I18N_NOOP("address family for nodename not supported"), // EAI_ADDRFAMILY 00892 I18N_NOOP("temporary failure in name resolution"), // EAI_AGAIN 00893 I18N_NOOP("invalid value for 'ai_flags'"), // EAI_BADFLAGS 00894 I18N_NOOP("non-recoverable failure in name resolution"), // EAI_FAIL 00895 I18N_NOOP("'ai_family' not supported"), // EAI_FAMILY 00896 I18N_NOOP("memory allocation failure"), // EAI_MEMORY 00897 I18N_NOOP("no address associated with nodename"), // EAI_NODATA 00898 I18N_NOOP("name or service not known"), // EAI_NONAME 00899 I18N_NOOP("servname not supported for ai_socktype"), // EAI_SERVICE 00900 I18N_NOOP("'ai_socktype' not supported"), // EAI_SOCKTYPE 00901 I18N_NOOP("system error") // EAI_SYSTEM 00902 }; 00903 00904 if (errorcode > EAI_SYSTEM || errorcode < 0) 00905 return NULL; 00906 00907 static char buffer[200]; 00908 strcpy(buffer, i18n(messages[errorcode]).local8Bit()); 00909 return buffer; 00910 } 00911 00912 static void findport(unsigned short port, char *serv, size_t servlen, int flags) 00913 { 00914 if (serv == NULL) 00915 return; 00916 00917 if ((flags & NI_NUMERICSERV) == 0) 00918 { 00919 struct servent *sent; 00920 sent = getservbyport(ntohs(port), flags & NI_DGRAM ? "udp" : "tcp"); 00921 if (sent != NULL && servlen > strlen(sent->s_name)) 00922 { 00923 strcpy(serv, sent->s_name); 00924 return; 00925 } 00926 } 00927 00928 snprintf(serv, servlen, "%u", ntohs(port)); 00929 } 00930 00931 int getnameinfo(const struct sockaddr *sa, ksocklen_t salen, 00932 char *host, size_t hostlen, char *serv, size_t servlen, 00933 int flags) 00934 { 00935 union 00936 { 00937 const sockaddr *sa; 00938 const sockaddr_un *_sun; 00939 const sockaddr_in *sin; 00940 const sockaddr_in6 *sin6; 00941 } s; 00942 00943 if ((host == NULL || hostlen == 0) && (serv == NULL || servlen == 0)) 00944 return 1; 00945 00946 s.sa = sa; 00947 if (s.sa->sa_family == AF_UNIX) 00948 { 00949 if (salen < offsetof(struct sockaddr_un, sun_path) + strlen(s._sun->sun_path) + 1) 00950 return 1; // invalid socket 00951 00952 if (servlen && serv != NULL) 00953 *serv = '\0'; 00954 if (host != NULL && hostlen > strlen(s._sun->sun_path)) 00955 strcpy(host, s._sun->sun_path); 00956 00957 return 0; 00958 } 00959 else if (s.sa->sa_family == AF_INET) 00960 { 00961 if (salen < offsetof(struct sockaddr_in, sin_addr) + sizeof(s.sin->sin_addr)) 00962 return 1; // invalid socket 00963 00964 if (flags & NI_NUMERICHOST) 00965 inet_ntop(AF_INET, &s.sin->sin_addr, host, hostlen); 00966 else 00967 { 00968 // have to do lookup 00969 struct hostent *h = gethostbyaddr((const char*)&s.sin->sin_addr, sizeof(s.sin->sin_addr), 00970 AF_INET); 00971 if (h == NULL && flags & NI_NAMEREQD) 00972 return 1; 00973 else if (h == NULL) 00974 inet_ntop(AF_INET, &s.sin->sin_addr, host, hostlen); 00975 else if (host != NULL && hostlen > strlen(h->h_name)) 00976 strcpy(host, h->h_name); 00977 else 00978 return 1; // error 00979 } 00980 00981 findport(s.sin->sin_port, serv, servlen, flags); 00982 } 00983 # ifdef AF_INET6 00984 else if (s.sa->sa_family == AF_INET6) 00985 { 00986 if (salen < offsetof(struct sockaddr_in6, sin6_addr) + sizeof(s.sin6->sin6_addr)) 00987 return 1; // invalid socket 00988 00989 if (flags & NI_NUMERICHOST) 00990 inet_ntop(AF_INET6, &s.sin6->sin6_addr, host, hostlen); 00991 else 00992 { 00993 // have to do lookup 00994 struct hostent *h = gethostbyaddr((const char*)&s.sin->sin_addr, sizeof(s.sin->sin_addr), 00995 AF_INET6); 00996 if (h == NULL && flags & NI_NAMEREQD) 00997 return 1; 00998 else if (h == NULL) 00999 inet_ntop(AF_INET6, &s.sin6->sin6_addr, host, hostlen); 01000 else if (host != NULL && hostlen > strlen(h->h_name)) 01001 strcpy(host, h->h_name); 01002 else 01003 return 1; // error 01004 } 01005 01006 findport(s.sin6->sin6_port, serv, servlen, flags); 01007 } 01008 # endif // AF_INET6 01009 01010 return 1; // invalid family 01011 } 01012 01013 #endif // HAVE_GETADDRINFO 01014 01015 #ifndef HAVE_INET_NTOP 01016 01017 #define KRF_inet_ntop KRF_USING_OWN_INET_NTOP 01018 01019 static void add_dwords(char *buf, TQ_UINT16 *dw, int count) 01020 { 01021 int i = 1; 01022 sprintf(buf + strlen(buf), "%x", ntohs(dw[0])); 01023 while (--count) 01024 sprintf(buf + strlen(buf), ":%x", ntohs(dw[i++])); 01025 } 01026 01027 const char* inet_ntop(int af, const void *cp, char *buf, size_t len) 01028 { 01029 char buf2[sizeof "1234:5678:9abc:def0:1234:5678:255.255.255.255" + 1]; 01030 TQ_UINT8 *data = (TQ_UINT8*)cp; 01031 01032 if (af == AF_INET) 01033 { 01034 sprintf(buf2, "%u.%u.%u.%u", data[0], data[1], data[2], data[3]); 01035 01036 if (len > strlen(buf2)) 01037 { 01038 strcpy(buf, buf2); 01039 return buf; 01040 } 01041 01042 errno = ENOSPC; 01043 return NULL; // failed 01044 } 01045 01046 # ifdef AF_INET6 01047 if (af == AF_INET6) 01048 { 01049 TQ_UINT16 *p = (TQ_UINT16*)data; 01050 TQ_UINT16 *longest = NULL, *cur = NULL; 01051 int longest_length = 0, cur_length; 01052 int i; 01053 01054 if (KDE_IN6_IS_ADDR_V4MAPPED(p) || KDE_IN6_IS_ADDR_V4COMPAT(p)) 01055 sprintf(buf2, "::%s%u.%u.%u.%u", 01056 KDE_IN6_IS_ADDR_V4MAPPED(p) ? "ffff:" : "", 01057 buf[12], buf[13], buf[14], buf[15]); 01058 else 01059 { 01060 // find the longest sequence of zeroes 01061 for (i = 0; i < 8; i++) 01062 if (cur == NULL && p[i] == 0) 01063 { 01064 // a zero, start the sequence 01065 cur = p + i; 01066 cur_length = 1; 01067 } 01068 else if (cur != NULL && p[i] == 0) 01069 // part of the sequence 01070 cur_length++; 01071 else if (cur != NULL && p[i] != 0) 01072 { 01073 // end of the sequence 01074 if (cur_length > longest_length) 01075 { 01076 longest_length = cur_length; 01077 longest = cur; 01078 } 01079 cur = NULL; // restart sequence 01080 } 01081 if (cur != NULL && cur_length > longest_length) 01082 { 01083 longest_length = cur_length; 01084 longest = cur; 01085 } 01086 01087 if (longest_length > 1) 01088 { 01089 // We have a candidate 01090 buf2[0] = '\0'; 01091 if (longest != p) 01092 add_dwords(buf2, p, longest - p); 01093 strcat(buf2, "::"); 01094 if (longest + longest_length < p + 8) 01095 add_dwords(buf2, longest + longest_length, 8 - (longest - p) - longest_length); 01096 } 01097 else 01098 { 01099 // Nope, no candidate 01100 buf2[0] = '\0'; 01101 add_dwords(buf2, p, 8); 01102 } 01103 } 01104 01105 if (strlen(buf2) < len) 01106 { 01107 strcpy(buf, buf2); 01108 return buf; 01109 } 01110 01111 errno = ENOSPC; 01112 return NULL; 01113 } 01114 # endif 01115 01116 errno = EAFNOSUPPORT; 01117 return NULL; // a family we don't know about 01118 } 01119 01120 #else // HAVE_INET_NTOP 01121 01122 #define KRF_inet_ntop 0 01123 01124 #endif // HAVE_INET_NTOP 01125 01126 #ifndef HAVE_INET_PTON 01127 01128 #define KRF_inet_pton KRF_USING_OWN_INET_PTON 01129 int inet_pton(int af, const char *cp, void *buf) 01130 { 01131 if (af == AF_INET) 01132 { 01133 // Piece of cake 01134 unsigned p[4]; 01135 unsigned char *q = (unsigned char*)buf; 01136 if (sscanf(cp, "%u.%u.%u.%u", p, p + 1, p + 2, p + 3) != 4) 01137 return 0; 01138 01139 if (p[0] > 0xff || p[1] > 0xff || p[2] > 0xff || p[3] > 0xff) 01140 return 0; 01141 01142 q[0] = p[0]; 01143 q[1] = p[1]; 01144 q[2] = p[2]; 01145 q[3] = p[3]; 01146 01147 return 1; 01148 } 01149 01150 # ifdef AF_INET6 01151 else if (af == AF_INET6) 01152 { 01153 TQ_UINT16 addr[8]; 01154 const char *p = cp; 01155 int n = 0, start = 8; 01156 bool has_v4 = strchr(p, '.') != NULL; 01157 01158 memset(addr, 0, sizeof(addr)); 01159 01160 if (*p == '\0' || p[1] == '\0') 01161 return 0; // less than 2 chars is not valid 01162 01163 if (*p == ':' && p[1] == ':') 01164 { 01165 start = 0; 01166 p += 2; 01167 } 01168 while (*p) 01169 { 01170 if (has_v4 && inet_pton(AF_INET, p, addr + n) != 0) 01171 { 01172 // successful v4 convertion 01173 addr[n] = ntohs(addr[n]); 01174 n++; 01175 addr[n] = ntohs(addr[n]); 01176 n++; 01177 break; 01178 } 01179 if (sscanf(p, "%hx", addr + n++) != 1) 01180 return 0; 01181 01182 while (*p && *p != ':') 01183 p++; 01184 if (!*p) 01185 break; 01186 p++; 01187 01188 if (*p == ':') // another ':'? 01189 { 01190 if (start != 8) 01191 return 0; // two :: were found 01192 start = n; 01193 p++; 01194 } 01195 } 01196 01197 // if start is not 8, then a "::" was found at word 'start' 01198 // n is the number of converted words 01199 // n == 8 means everything was converted and no moving is necessary 01200 // n < 8 means that we have to move n - start words 8 - n words to the right 01201 if (start == 8 && n != 8) 01202 return 0; // bad conversion 01203 memmove(addr + start + (8 - n), addr + start, (n - start) * sizeof(TQ_UINT16)); 01204 memset(addr + start, 0, (8 - n) * sizeof(TQ_UINT16)); 01205 01206 // check the byte order 01207 // The compiler should optimise this out in big endian machines 01208 if (htons(0x1234) != 0x1234) 01209 for (n = 0; n < 8; n++) 01210 addr[n] = htons(addr[n]); 01211 01212 memcpy(buf, addr, sizeof(addr)); 01213 return 1; 01214 } 01215 # endif 01216 01217 errno = EAFNOSUPPORT; 01218 return -1; // unknown family 01219 } 01220 01221 #else // HAVE_INET_PTON 01222 01223 #define KRF_inet_pton 0 01224 01225 #endif // HAVE_INET_PTON 01226 01227 #ifdef AF_INET6 01228 # define KRF_afinet6 KRF_KNOWS_AF_INET6 01229 #else 01230 # define KRF_afinet6 0 01231 #endif 01232 01233 namespace KDE 01234 { 01236 extern const int KDE_EXPORT resolverFlags = KRF_getaddrinfo | KRF_resolver | KRF_afinet6 | KRF_inet_ntop | KRF_inet_pton; 01237 }