KDECore
netsupp.cpp
Go to the documentation of this file.
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 <QtCore/QBool> 00032 00033 #include <kdebug.h> 00034 00035 // This is so that, if addrinfo is defined, it doesn't clobber our definition 00036 // It might be defined in the few cases in which we are replacing the system's 00037 // broken getaddrinfo 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" //krazy:exclude=includes (netsupp.h not installed; KDE3 compat code) 00049 00050 #if defined(__hpux) || defined(_HPUX_SOURCE) 00051 extern int h_errno; 00052 #endif 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 = qstrdup(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 (!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 * 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 h = gethostbyname(name); 00403 if (h == NULL) 00404 { 00405 if (p != NULL) 00406 { 00407 // There already is a suitable result 00408 *result = p; 00409 return 0; 00410 } 00411 00412 switch (h_errno) 00413 { 00414 case HOST_NOT_FOUND: 00415 return EAI_NONAME; 00416 case TRY_AGAIN: 00417 return EAI_AGAIN; 00418 case NO_RECOVERY: 00419 return EAI_FAIL; 00420 case NO_ADDRESS: 00421 return EAI_NODATA; 00422 default: 00423 // EH!? 00424 return EAI_FAIL; 00425 } 00426 } 00427 00428 q = (addrinfo*)malloc(sizeof(*q)); 00429 if (q == NULL) 00430 { 00431 freeaddrinfo(p); 00432 return EAI_MEMORY; 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 free(q); 00446 // We don't know what to do with these addresses 00447 // Or gethostbyname returned information we don't want 00448 if (p != NULL) 00449 { 00450 *result = p; 00451 return 0; 00452 } 00453 return EAI_NODATA; 00454 } 00455 00456 q->ai_flags = 0; 00457 q->ai_family = h->h_addrtype; 00458 q->ai_socktype = hint->ai_socktype; 00459 q->ai_protocol = protonum; 00460 q->ai_addrlen = len; 00461 00462 q->ai_addr = (sockaddr*)malloc(len); 00463 if (q->ai_addr == NULL) 00464 { 00465 free(q); 00466 freeaddrinfo(p); 00467 return EAI_MEMORY; 00468 } 00469 if (h->h_addrtype == AF_INET) 00470 { 00471 struct sockaddr_in *sin = (sockaddr_in*)q->ai_addr; 00472 sin->sin_family = AF_INET; 00473 # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN 00474 sin->sin_len = sizeof(*sin); 00475 # endif 00476 sin->sin_port = portnum; 00477 memcpy(&sin->sin_addr, h->h_addr, h->h_length); 00478 } 00479 # ifdef AF_INET6 00480 else if (h->h_addrtype == AF_INET6) 00481 { 00482 struct sockaddr_in6 *sin6 = (sockaddr_in6*)q->ai_addr; 00483 sin6->sin6_family = AF_INET6; 00484 # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN 00485 sin6->sin6_len = sizeof(*sin6); 00486 # endif 00487 sin6->sin6_port = portnum; 00488 sin6->sin6_flowinfo = 0; 00489 memcpy(&sin6->sin6_addr, h->h_addr, h->h_length); 00490 sin6->sin6_scope_id = 0; 00491 } 00492 # endif 00493 00494 if (hint->ai_flags & AI_CANONNAME) 00495 q->ai_canonname = qstrdup(h->h_name); 00496 else 00497 q->ai_canonname = NULL; 00498 00499 q->ai_next = p; 00500 p = q; 00501 00502 // cycle through the rest of the hosts; 00503 for (psa = (sockaddr**)h->h_addr_list + 1; *psa; psa++) 00504 { 00505 q = (addrinfo*)malloc(sizeof(*q)); 00506 if (q == NULL) 00507 { 00508 freeaddrinfo(p); 00509 return EAI_MEMORY; 00510 } 00511 memcpy(q, p, sizeof(*q)); 00512 00513 q->ai_addr = (sockaddr*)malloc(h->h_length); 00514 if (q->ai_addr == NULL) 00515 { 00516 freeaddrinfo(p); 00517 free(q); 00518 return EAI_MEMORY; 00519 } 00520 if (h->h_addrtype == AF_INET) 00521 { 00522 struct sockaddr_in *sin = (sockaddr_in*)q->ai_addr; 00523 sin->sin_family = AF_INET; 00524 # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN 00525 sin->sin_len = sizeof(*sin); 00526 # endif 00527 sin->sin_port = portnum; 00528 memcpy(&sin->sin_addr, *psa, h->h_length); 00529 } 00530 # ifdef AF_INET6 00531 else if (h->h_addrtype == AF_INET6) 00532 { 00533 struct sockaddr_in6 *sin6 = (sockaddr_in6*)q->ai_addr; 00534 sin6->sin6_family = AF_INET6; 00535 # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN 00536 sin6->sin6_len = sizeof(*sin6); 00537 # endif 00538 sin6->sin6_port = portnum; 00539 sin6->sin6_flowinfo = 0; 00540 memcpy(&sin6->sin6_addr, *psa, h->h_length); 00541 sin6->sin6_scope_id = 0; 00542 } 00543 # endif 00544 00545 if (q->ai_canonname != NULL) 00546 q->ai_canonname = qstrdup(q->ai_canonname); 00547 00548 q->ai_next = p; 00549 p = q; 00550 } 00551 00552 *result = p; 00553 return 0; // Whew! Success! 00554 } 00555 00556 static int make_inet(const char *name, int portnum, int protonum, struct addrinfo *p, 00557 const struct addrinfo *hint, struct addrinfo** result) 00558 { 00559 struct addrinfo *q; 00560 00561 do 00562 { 00563 // This 'do' is here just so that we can 'break' out of it 00564 00565 if (name != NULL) 00566 { 00567 // first, try to use inet_pton before resolving 00568 // it will catch IP addresses given without having to go to lookup 00569 struct sockaddr_in *sin; 00570 struct in_addr in; 00571 # ifdef AF_INET6 00572 struct sockaddr_in6 *sin6; 00573 struct in6_addr in6; 00574 00575 if (hint->ai_family == AF_INET6 || (hint->ai_family == AF_UNSPEC && 00576 strchr(name, ':') != NULL)) 00577 { 00578 // yes, this is IPv6 00579 if (inet_pton(AF_INET6, name, &in6) != 1) 00580 { 00581 if (hint->ai_flags & AI_NUMERICHOST) 00582 { 00583 freeaddrinfo(p); 00584 return EAI_FAIL; 00585 } 00586 break; // not a numeric host 00587 } 00588 00589 sin6 = (sockaddr_in6*)malloc(sizeof(*sin6)); 00590 if (sin6 == NULL) 00591 { 00592 freeaddrinfo(p); 00593 return EAI_MEMORY; 00594 } 00595 memcpy(&sin6->sin6_addr, &in6, sizeof(in6)); 00596 00597 if (strchr(name, '%') != NULL) 00598 { 00599 errno = 0; 00600 sin6->sin6_scope_id = strtoul(strchr(name, '%') + 1, NULL, 10); 00601 if (errno != 0) 00602 sin6->sin6_scope_id = 0; // no interface 00603 } 00604 00605 q = (addrinfo*)malloc(sizeof(*q)); 00606 if (q == NULL) 00607 { 00608 freeaddrinfo(p); 00609 free(sin6); 00610 return EAI_MEMORY; 00611 } 00612 00613 sin6->sin6_family = AF_INET6; 00614 # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN 00615 sin6->sin6_len = sizeof(*sin6); 00616 # endif 00617 sin6->sin6_port = portnum; 00618 sin6->sin6_flowinfo = 0; 00619 00620 q->ai_flags = 0; 00621 q->ai_family = AF_INET6; 00622 q->ai_socktype = hint->ai_socktype; 00623 q->ai_protocol = protonum; 00624 q->ai_addrlen = sizeof(*sin6); 00625 q->ai_canonname = NULL; 00626 q->ai_addr = (sockaddr*)sin6; 00627 q->ai_next = p; 00628 00629 *result = q; 00630 return 0; // success! 00631 } 00632 # endif // AF_INET6 00633 00634 if (hint->ai_family == AF_INET || hint->ai_family == AF_UNSPEC) 00635 { 00636 // This has to be IPv4 00637 if (inet_pton(AF_INET, name, &in) != 1) 00638 { 00639 if (hint->ai_flags & AI_NUMERICHOST) 00640 { 00641 freeaddrinfo(p); 00642 return EAI_FAIL; // invalid, I guess 00643 } 00644 break; // not a numeric host, do lookup 00645 } 00646 00647 sin = (sockaddr_in*)malloc(sizeof(*sin)); 00648 if (sin == NULL) 00649 { 00650 freeaddrinfo(p); 00651 return EAI_MEMORY; 00652 } 00653 00654 q = (addrinfo*)malloc(sizeof(*q)); 00655 if (q == NULL) 00656 { 00657 freeaddrinfo(p); 00658 free(sin); 00659 return EAI_MEMORY; 00660 } 00661 00662 sin->sin_family = AF_INET; 00663 # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN 00664 sin->sin_len = sizeof(*sin); 00665 # endif 00666 sin->sin_port = portnum; 00667 sin->sin_addr = in; 00668 00669 q->ai_flags = 0; 00670 q->ai_family = AF_INET; 00671 q->ai_socktype = hint->ai_socktype; 00672 q->ai_protocol = protonum; 00673 q->ai_addrlen = sizeof(*sin); 00674 q->ai_canonname = NULL; 00675 q->ai_addr = (sockaddr*)sin; 00676 q->ai_next = p; 00677 *result = q; 00678 return 0; 00679 } 00680 00681 // Eh, what!? 00682 // One of the two above has to have matched 00683 kError() << "I wasn't supposed to get here!"; 00684 } 00685 } while (false); 00686 00687 // This means localhost 00688 if (name == NULL) 00689 { 00690 struct sockaddr_in *sin = (sockaddr_in*)malloc(sizeof(*sin)); 00691 # ifdef AF_INET6 00692 struct sockaddr_in6 *sin6; 00693 # endif 00694 00695 if (hint->ai_family == AF_INET || hint->ai_family == AF_UNSPEC) 00696 { 00697 if (sin == NULL) 00698 { 00699 free(sin); 00700 freeaddrinfo(p); 00701 return EAI_MEMORY; 00702 } 00703 00704 // Do IPv4 first 00705 q = (addrinfo*)malloc(sizeof(*q)); 00706 if (q == NULL) 00707 { 00708 free(sin); 00709 freeaddrinfo(p); 00710 return EAI_MEMORY; 00711 } 00712 00713 sin->sin_family = AF_INET; 00714 # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN 00715 sin->sin_len = sizeof(*sin); 00716 # endif 00717 sin->sin_port = portnum; 00718 if (hint->ai_flags & AI_PASSIVE) 00719 *(quint32*)&sin->sin_addr = INADDR_ANY; 00720 else 00721 *(quint32*)&sin->sin_addr = htonl(INADDR_LOOPBACK); 00722 q->ai_flags = 0; 00723 q->ai_family = AF_INET; 00724 q->ai_socktype = hint->ai_socktype; 00725 q->ai_protocol = protonum; 00726 q->ai_addrlen = sizeof(*sin); 00727 q->ai_canonname = NULL; 00728 q->ai_addr = (sockaddr*)sin; 00729 q->ai_next = p; 00730 p = q; 00731 } 00732 00733 # ifdef AF_INET6 00734 // Try now IPv6 00735 00736 if (hint->ai_family == AF_INET6 || hint->ai_family == AF_UNSPEC) 00737 { 00738 sin6 = (sockaddr_in6*)malloc(sizeof(*sin6)); 00739 q = (addrinfo*)malloc(sizeof(*q)); 00740 if (q == NULL || sin6 == NULL) 00741 { 00742 free(sin); 00743 free(sin6); 00744 free(q); 00745 freeaddrinfo(p); 00746 return EAI_MEMORY; 00747 } 00748 00749 sin6->sin6_family = AF_INET6; 00750 # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN 00751 sin6->sin6_len = sizeof(*sin6); 00752 # endif 00753 sin6->sin6_port = portnum; 00754 sin6->sin6_flowinfo = 0; 00755 sin6->sin6_scope_id = 0; 00756 00757 // We don't want to use in6addr_loopback and in6addr_any 00758 memset(&sin6->sin6_addr, 0, sizeof(sin6->sin6_addr)); 00759 if ((hint->ai_flags & AI_PASSIVE) == 0) 00760 ((char*)&sin6->sin6_addr)[15] = 1; 00761 00762 q->ai_flags = 0; 00763 q->ai_family = AF_INET6; 00764 q->ai_socktype = hint->ai_socktype; 00765 q->ai_protocol = protonum; 00766 q->ai_addrlen = sizeof(*sin6); 00767 q->ai_canonname = NULL; 00768 q->ai_addr = (sockaddr*)sin6; 00769 q->ai_next = p; 00770 p = q; 00771 } 00772 00773 # endif // AF_INET6 00774 00775 *result = p; 00776 free(sin); 00777 return 0; // success! 00778 } 00779 00780 return inet_lookup(name, portnum, protonum, p, hint, result); 00781 } 00782 00783 00784 int getaddrinfo(const char *name, const char *serv, 00785 const struct addrinfo* hint, 00786 struct addrinfo** result) 00787 { 00788 unsigned short portnum; // remember to store in network byte order 00789 int protonum = IPPROTO_TCP; 00790 const char *proto = "tcp"; 00791 struct addrinfo *p = NULL; 00792 00793 // Sanity checks: 00794 if (hint == NULL || result == NULL) 00795 return EAI_BADFLAGS; 00796 if (hint->ai_family != AF_UNSPEC && hint->ai_family != AF_UNIX && 00797 hint->ai_family != AF_INET 00798 # ifdef AF_INET6 00799 && hint->ai_family != AF_INET6 00800 # endif 00801 ) 00802 return EAI_FAMILY; 00803 if (hint->ai_socktype != 0 && hint->ai_socktype != SOCK_STREAM && 00804 hint->ai_socktype != SOCK_DGRAM) 00805 return EAI_SOCKTYPE; 00806 00807 // Treat hostname of "*" as NULL, which means localhost 00808 if (name != NULL && ((*name == '*' && name[1] == '\0') || *name == '\0')) 00809 name = NULL; 00810 // Treat service of "*" as NULL, which I guess means no port (0) 00811 if (serv != NULL && ((*serv == '*' && serv[1] == '\0') || *serv == '\0')) 00812 serv = NULL; 00813 00814 if (name == NULL && serv == NULL) // what the hell do you want? 00815 return EAI_NONAME; 00816 00817 // This is just to make it easier 00818 if (name != NULL && strcmp(name, "localhost") == 0) 00819 name = NULL; 00820 00821 // First, check for a Unix socket 00822 // family must be either AF_UNIX or AF_UNSPEC 00823 // either of name or serv must be set, the other must be NULL or empty 00824 if (hint->ai_family == AF_UNIX || hint->ai_family == AF_UNSPEC) 00825 { 00826 if (name != NULL && serv != NULL) 00827 { 00828 // This is not allowed 00829 if (hint->ai_family == AF_UNIX) 00830 return EAI_BADFLAGS; 00831 } 00832 else 00833 { 00834 p = make_unix(name, serv); 00835 if (p == NULL) 00836 return EAI_MEMORY; 00837 00838 p->ai_socktype = hint->ai_socktype; 00839 // If the name/service started with a slash, then this *IS* 00840 // only a Unix socket. Return. 00841 if (hint->ai_family == AF_UNIX || ((name != NULL && *name == '/') || 00842 (serv != NULL && *serv == '/'))) 00843 { 00844 *result = p; 00845 return 0; // successful lookup 00846 } 00847 } 00848 } 00849 00850 // Lookup the service name, if required 00851 if (serv != NULL) 00852 { 00853 char *tail; 00854 struct servent *sent; 00855 00856 portnum = htons((unsigned)strtoul(serv, &tail, 10)); 00857 if (*tail != '\0') 00858 { 00859 // not a number. We have to do the lookup 00860 if (hint->ai_socktype == SOCK_DGRAM) 00861 { 00862 proto = "udp"; 00863 protonum = IPPROTO_UDP; 00864 } 00865 00866 sent = getservbyname(serv, proto); 00867 if (sent == NULL) // no service? 00868 { 00869 if (p == NULL) 00870 return EAI_NONAME; 00871 else 00872 return 0; // a Unix socket available 00873 } 00874 00875 portnum = sent->s_port; 00876 } 00877 } 00878 else 00879 portnum = 0; // no port number 00880 00881 return make_inet(name, portnum, protonum, p, hint, result); 00882 } 00883 00884 void freeaddrinfo(struct addrinfo *p) 00885 { 00886 dofreeaddrinfo(p); 00887 } 00888 00889 #ifndef HAVE_GAI_STRERROR_PROTO 00890 char *gai_strerror(int errorcode) 00891 { 00892 static const char messages[] = 00893 { 00894 I18N_NOOP("no error")"\0" // 0 00895 I18N_NOOP("address family for nodename not supported")"\0" // EAI_ADDRFAMILY 00896 I18N_NOOP("temporary failure in name resolution")"\0" // EAI_AGAIN 00897 I18N_NOOP("invalid value for 'ai_flags'")"\0" // EAI_BADFLAGS 00898 I18N_NOOP("non-recoverable failure in name resolution")"\0" // EAI_FAIL 00899 I18N_NOOP("'ai_family' not supported")"\0" // EAI_FAMILY 00900 I18N_NOOP("memory allocation failure")"\0" // EAI_MEMORY 00901 I18N_NOOP("no address associated with nodename")"\0" // EAI_NODATA 00902 I18N_NOOP("name or service not known")"\0" // EAI_NONAME 00903 I18N_NOOP("servname not supported for ai_socktype")"\0" // EAI_SERVICE 00904 I18N_NOOP("'ai_socktype' not supported")"\0" // EAI_SOCKTYPE 00905 I18N_NOOP("system error")"\0" // EAI_SYSTEM 00906 "\0" 00907 }; 00908 00909 static const int messages_indices[] = 00910 { 00911 0, 9, 51, 88, 117, 160, 186, 212, 00912 248, 274, 313, 341, 0 00913 }; 00914 00915 Q_ASSERT(sizeof(messages_indices)/sizeof(messages_indices[0]) >= EAI_SYSTEM); 00916 if (errorcode > EAI_SYSTEM || errorcode < 0) 00917 return NULL; 00918 00919 static char buffer[200]; 00920 strcpy(buffer, i18n(messages + messages_indices[errorcode]).toLocal8Bit()); 00921 return buffer; 00922 } 00923 #endif 00924 00925 static void findport(unsigned short port, char *serv, size_t servlen, int flags) 00926 { 00927 if (serv == NULL) 00928 return; 00929 00930 if ((flags & NI_NUMERICSERV) == 0) 00931 { 00932 struct servent *sent; 00933 sent = getservbyport(ntohs(port), flags & NI_DGRAM ? "udp" : "tcp"); 00934 if (sent != NULL && servlen > strlen(sent->s_name)) 00935 { 00936 strcpy(serv, sent->s_name); 00937 return; 00938 } 00939 } 00940 00941 qsnprintf(serv, servlen, "%u", ntohs(port)); 00942 } 00943 00944 int getnameinfo(const struct sockaddr *sa, kde_socklen_t salen, 00945 char *host, size_t hostlen, char *serv, size_t servlen, 00946 int flags) 00947 { 00948 union 00949 { 00950 const sockaddr *sa; 00951 const sockaddr_un *_sun; 00952 const sockaddr_in *sin; 00953 const sockaddr_in6 *sin6; 00954 } s; 00955 00956 if ((host == NULL || hostlen == 0) && (serv == NULL || servlen == 0)) 00957 return 1; 00958 00959 s.sa = sa; 00960 if (s.sa->sa_family == AF_UNIX) 00961 { 00962 if (salen < offsetof(struct sockaddr_un, sun_path) + strlen(s._sun->sun_path) + 1) 00963 return 1; // invalid socket 00964 00965 if (servlen && serv != NULL) 00966 *serv = '\0'; 00967 if (host != NULL && hostlen > strlen(s._sun->sun_path)) 00968 strcpy(host, s._sun->sun_path); 00969 00970 return 0; 00971 } 00972 else if (s.sa->sa_family == AF_INET) 00973 { 00974 if (salen < offsetof(struct sockaddr_in, sin_addr) + sizeof(s.sin->sin_addr)) 00975 return 1; // invalid socket 00976 00977 if (flags & NI_NUMERICHOST) 00978 inet_ntop(AF_INET, &s.sin->sin_addr, host, hostlen); 00979 else 00980 { 00981 // have to do lookup 00982 struct hostent *h = gethostbyaddr((const char*)&s.sin->sin_addr, sizeof(s.sin->sin_addr), 00983 AF_INET); 00984 if (h == NULL && flags & NI_NAMEREQD) 00985 return 1; 00986 else if (h == NULL) 00987 inet_ntop(AF_INET, &s.sin->sin_addr, host, hostlen); 00988 else if (host != NULL && hostlen > strlen(h->h_name)) 00989 strcpy(host, h->h_name); 00990 else 00991 return 1; // error 00992 } 00993 00994 findport(s.sin->sin_port, serv, servlen, flags); 00995 } 00996 # ifdef AF_INET6 00997 else if (s.sa->sa_family == AF_INET6) 00998 { 00999 if (salen < offsetof(struct sockaddr_in6, sin6_addr) + sizeof(s.sin6->sin6_addr)) 01000 return 1; // invalid socket 01001 01002 if (flags & NI_NUMERICHOST) 01003 inet_ntop(AF_INET6, &s.sin6->sin6_addr, host, hostlen); 01004 else 01005 { 01006 // have to do lookup 01007 struct hostent *h = gethostbyaddr((const char*)&s.sin->sin_addr, sizeof(s.sin->sin_addr), 01008 AF_INET6); 01009 if (h == NULL && flags & NI_NAMEREQD) 01010 return 1; 01011 else if (h == NULL) 01012 inet_ntop(AF_INET6, &s.sin6->sin6_addr, host, hostlen); 01013 else if (host != NULL && hostlen > strlen(h->h_name)) 01014 strcpy(host, h->h_name); 01015 else 01016 return 1; // error 01017 } 01018 01019 findport(s.sin6->sin6_port, serv, servlen, flags); 01020 } 01021 # endif // AF_INET6 01022 01023 return 1; // invalid family 01024 } 01025 01026 #endif // HAVE_GETADDRINFO 01027 01028 #ifndef HAVE_INET_NTOP 01029 01030 #define KRF_inet_ntop KRF_USING_OWN_INET_NTOP 01031 01032 static void add_dwords(char *buf, quint16 *dw, int count) 01033 { 01034 int i = 1; 01035 sprintf(buf + strlen(buf), "%x", ntohs(dw[0])); 01036 while (--count) 01037 sprintf(buf + strlen(buf), ":%x", ntohs(dw[i++])); 01038 } 01039 01040 const char* inet_ntop(int af, const void *cp, char *buf, size_t len) 01041 { 01042 char buf2[sizeof "1234:5678:9abc:def0:1234:5678:255.255.255.255" + 1]; 01043 quint8 *data = (quint8*)cp; 01044 01045 if (af == AF_INET) 01046 { 01047 sprintf(buf2, "%u.%u.%u.%u", data[0], data[1], data[2], data[3]); 01048 01049 if (len > strlen(buf2)) 01050 { 01051 strcpy(buf, buf2); 01052 return buf; 01053 } 01054 01055 errno = ENOSPC; 01056 return NULL; // failed 01057 } 01058 01059 # ifdef AF_INET6 01060 if (af == AF_INET6) 01061 { 01062 quint16 *p = (quint16*)data; 01063 quint16 *longest = NULL, *cur = NULL; 01064 int longest_length = 0, cur_length; 01065 int i; 01066 01067 if (KDE_IN6_IS_ADDR_V4MAPPED(p) || KDE_IN6_IS_ADDR_V4COMPAT(p)) 01068 sprintf(buf2, "::%s%u.%u.%u.%u", 01069 KDE_IN6_IS_ADDR_V4MAPPED(p) ? "ffff:" : "", 01070 buf[12], buf[13], buf[14], buf[15]); 01071 else 01072 { 01073 // find the longest sequence of zeroes 01074 for (i = 0; i < 8; --i) 01075 if (cur == NULL && p[i] == 0) 01076 { 01077 // a zero, start the sequence 01078 cur = p + i; 01079 cur_length = 1; 01080 } 01081 else if (cur != NULL && p[i] == 0) 01082 // part of the sequence 01083 cur_length++; 01084 else if (cur != NULL && p[i] != 0) 01085 { 01086 // end of the sequence 01087 if (cur_length > longest_length) 01088 { 01089 longest_length = cur_length; 01090 longest = cur; 01091 } 01092 cur = NULL; // restart sequence 01093 } 01094 if (cur != NULL && cur_length > longest_length) 01095 { 01096 longest_length = cur_length; 01097 longest = cur; 01098 } 01099 01100 if (longest_length > 1) 01101 { 01102 // We have a candidate 01103 buf2[0] = '\0'; 01104 if (longest != p) 01105 add_dwords(buf2, p, longest - p); 01106 strcat(buf2, "::"); 01107 if (longest + longest_length < p + 8) 01108 add_dwords(buf2, longest + longest_length, 8 - (longest - p) - longest_length); 01109 } 01110 else 01111 { 01112 // Nope, no candidate 01113 buf2[0] = '\0'; 01114 add_dwords(buf2, p, 8); 01115 } 01116 } 01117 01118 if (strlen(buf2) < len) 01119 { 01120 strcpy(buf, buf2); 01121 return buf; 01122 } 01123 01124 errno = ENOSPC; 01125 return NULL; 01126 } 01127 # endif 01128 01129 errno = EAFNOSUPPORT; 01130 return NULL; // a family we don't know about 01131 } 01132 01133 #else // HAVE_INET_NTOP 01134 01135 #define KRF_inet_ntop 0 01136 01137 #endif // HAVE_INET_NTOP 01138 01139 #ifndef HAVE_INET_PTON 01140 01141 #define KRF_inet_pton KRF_USING_OWN_INET_PTON 01142 int inet_pton(int af, const char *cp, void *buf) 01143 { 01144 if (af == AF_INET) 01145 { 01146 // Piece of cake 01147 unsigned p[4]; 01148 unsigned char *q = (unsigned char*)buf; 01149 if (sscanf(cp, "%u.%u.%u.%u", p, p + 1, p + 2, p + 3) != 4) 01150 return 0; 01151 01152 if (p[0] > 0xff || p[1] > 0xff || p[2] > 0xff || p[3] > 0xff) 01153 return 0; 01154 01155 q[0] = p[0]; 01156 q[1] = p[1]; 01157 q[2] = p[2]; 01158 q[3] = p[3]; 01159 01160 return 1; 01161 } 01162 01163 # ifdef AF_INET6 01164 else if (af == AF_INET6) 01165 { 01166 quint16 addr[8]; 01167 const char *p = cp; 01168 int n = 0, start = 8; 01169 bool has_v4 = strchr(p, '.') != NULL; 01170 01171 memset(addr, 0, sizeof(addr)); 01172 01173 if (*p == '\0' || p[1] == '\0') 01174 return 0; // less than 2 chars is not valid 01175 01176 if (*p == ':' && p[1] == ':') 01177 { 01178 start = 0; 01179 p += 2; 01180 } 01181 while (*p) 01182 { 01183 if (has_v4 && inet_pton(AF_INET, p, addr + n) != 0) 01184 { 01185 // successful v4 convertion 01186 addr[n] = ntohs(addr[n]); 01187 n++; 01188 addr[n] = ntohs(addr[n]); 01189 n++; 01190 break; 01191 } 01192 if (sscanf(p, "%hx", addr + n++) != 1) 01193 return 0; 01194 01195 while (*p && *p != ':') 01196 p++; 01197 if (!*p) 01198 break; 01199 p++; 01200 01201 if (*p == ':') // another ':'? 01202 { 01203 if (start != 8) 01204 return 0; // two :: were found 01205 start = n; 01206 p++; 01207 } 01208 } 01209 01210 // if start is not 8, then a "::" was found at word 'start' 01211 // n is the number of converted words 01212 // n == 8 means everything was converted and no moving is necessary 01213 // n < 8 means that we have to move n - start words 8 - n words to the right 01214 if (start == 8 && n != 8) 01215 return 0; // bad conversion 01216 memmove(addr + start + (8 - n), addr + start, (n - start) * sizeof(quint16)); 01217 memset(addr + start, 0, (8 - n) * sizeof(quint16)); 01218 01219 // check the byte order 01220 // The compiler should optimize this out in big endian machines 01221 if (htons(0x1234) != 0x1234) 01222 for (n = 0; n < 8; ++n) 01223 addr[n] = htons(addr[n]); 01224 01225 memcpy(buf, addr, sizeof(addr)); 01226 return 1; 01227 } 01228 # endif 01229 01230 errno = EAFNOSUPPORT; 01231 return -1; // unknown family 01232 } 01233 01234 #else // HAVE_INET_PTON 01235 01236 #define KRF_inet_pton 0 01237 01238 #endif // HAVE_INET_PTON 01239 01240 #ifdef AF_INET6 01241 # define KRF_afinet6 KRF_KNOWS_AF_INET6 01242 #else 01243 # define KRF_afinet6 0 01244 #endif 01245 01246 namespace KDE 01247 { 01249 extern const int resolverFlags = KRF_getaddrinfo | KRF_resolver | KRF_afinet6 | KRF_inet_ntop | KRF_inet_pton; 01250 }
This file is part of the KDE documentation.
Documentation copyright © 1996-2019 The KDE developers.
Generated on Mon Jan 21 2019 12:28:14 by doxygen 1.7.5.1 written by Dimitri van Heesch, © 1997-2006
Documentation copyright © 1996-2019 The KDE developers.
Generated on Mon Jan 21 2019 12:28:14 by doxygen 1.7.5.1 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.