summaryrefslogtreecommitdiffstats
path: root/kdecore/netsupp.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kdecore/netsupp.cpp')
-rw-r--r--kdecore/netsupp.cpp1237
1 files changed, 0 insertions, 1237 deletions
diff --git a/kdecore/netsupp.cpp b/kdecore/netsupp.cpp
deleted file mode 100644
index 83aec8bc0..000000000
--- a/kdecore/netsupp.cpp
+++ /dev/null
@@ -1,1237 +0,0 @@
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 2000,2001 Thiago Macieira <thiago.macieira@kdemail.net>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- **/
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <netinet/in.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <unistd.h>
-#include <arpa/inet.h>
-
-#include <tqglobal.h>
-
-// This is so that, if addrinfo is defined, it doesn't clobber our definition
-// It might be defined in the few cases in which we are replacing the system's
-// broken getaddrinfo
-#include <netdb.h>
-
-#include "config.h"
-#include "kdebug.h"
-#include "klocale.h"
-
-#ifndef IN6_IS_ADDR_V4MAPPED
-#define NEED_IN6_TESTS
-#endif
-#undef CLOBBER_IN6
-#include "netsupp.h"
-
-#if defined(__hpux) || defined(_HPUX_SOURCE)
-extern int h_errno;
-#endif
-
-#include <kdemacros.h>
-
-#if !defined(kde_sockaddr_in6)
-/*
- * kde_sockaddr_in6 might have got defined even though we #undef'ed
- * CLOBBER_IN6. This happens when we are compiling under --enable-final.
- * However, in that case, if it was defined, that's because ksockaddr.cpp
- * had it defined because sockaddr_in6 didn't exist, and so sockaddr_in6
- * exists and is our kde_sockaddr_in6
- */
-# define sockaddr_in6 kde_sockaddr_in6
-# define in6_addr kde_in6_addr
-#endif
-
-#ifdef offsetof
-#undef offsetof
-#endif
-#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
-
-/*
- * These constants tell the flags in KDE::resolverFlags
- * The user could (but shouldn't) test the variable to know what kind of
- * resolution is supported
- */
-#define KRF_KNOWS_AF_INET6 0x01 /* if present, the code knows about AF_INET6 */
-#define KRF_USING_OWN_GETADDRINFO 0x02 /* if present, we are using our own getaddrinfo */
-#define KRF_USING_OWN_INET_NTOP 0x04 /* if present, we are using our own inet_ntop */
-#define KRF_USING_OWN_INET_PTON 0x08 /* if present, we are using our own inet_pton */
-#define KRF_CAN_RESOLVE_UNIX 0x100 /* if present, the resolver can resolve Unix sockets */
-#define KRF_CAN_RESOLVE_IPV4 0x200 /* if present, the resolver can resolve to IPv4 */
-#define KRF_CAN_RESOLVE_IPV6 0x400 /* if present, the resolver can resolve to IPv6 */
-
-
-static void dofreeaddrinfo(struct addrinfo *ai)
-{
- while (ai)
- {
- struct addrinfo *ai2 = ai;
- if (ai->ai_canonname != NULL)
- free(ai->ai_canonname);
-
- if (ai->ai_addr != NULL)
- free(ai->ai_addr);
-
- ai = ai->ai_next;
- free(ai2);
- }
-}
-
-void kde_freeaddrinfo(struct kde_addrinfo *ai)
-{
- if (ai->origin == KAI_LOCALUNIX)
- {
- struct addrinfo *p, *last = NULL;
- /* We've added one AF_UNIX socket in here, to the
- * tail of the linked list. We have to find it */
- for (p = ai->data; p; p = p->ai_next)
- {
- if (p->ai_family == AF_UNIX)
- {
- if (last)
- {
- last->ai_next = NULL;
- freeaddrinfo(ai->data);
- }
- dofreeaddrinfo(p);
- break;
- }
- last = p;
- }
- }
- else
- freeaddrinfo(ai->data);
-
- free(ai);
-}
-
-static struct addrinfo*
-make_unix(const char *name, const char *serv)
-{
- const char *buf;
- struct addrinfo *p;
- struct sockaddr_un *_sun;
- int len;
-
- p = (addrinfo*)malloc(sizeof(*p));
- if (p == NULL)
- return NULL;
- memset(p, 0, sizeof(*p));
-
- if (name != NULL)
- buf = name;
- else
- buf = serv;
-
- // Calculate length of the binary representation
- len = strlen(buf) + offsetof(struct sockaddr_un, sun_path) + 1;
- if (*buf != '/')
- len += 5; // strlen("/tmp/");
-
- _sun = (sockaddr_un*)malloc(len);
- if (_sun == NULL)
- {
- // Oops
- free(p);
- return NULL;
- }
-
- _sun->sun_family = AF_UNIX;
-# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
- _sun->sun_len = len;
-# endif
- if (*buf == '/')
- *_sun->sun_path = '\0'; // empty it
- else
- strcpy(_sun->sun_path, "/tmp/");
- strcat(_sun->sun_path, buf);
-
- // Set the addrinfo
- p->ai_family = AF_UNIX;
- p->ai_addrlen = len;
- p->ai_addr = (sockaddr*)_sun;
- p->ai_canonname = strdup(buf);
-
- return p;
-}
-
-// Ugh. I hate #ifdefs
-// Anyways, here's what this does:
-// KDE_IPV6_LOOKUP_MODE != 1, this function doesn't exist
-// AF_INET6 not defined, we say there is no IPv6 stack
-// otherwise, we try to create a socket.
-// returns: 1 for IPv6 stack available, 2 for not available
-#if defined(KDE_IPV6_LOOKUP_MODE) && KDE_IPV6_LOOKUP_MODE == 1
-static int check_ipv6_stack()
-{
-# ifndef AF_INET6
- return 2; // how can we check?
-# else
- if (getenv("KDE_NO_IPV6"))
- return 2;
- int fd = ::socket(AF_INET6, SOCK_STREAM, 0);
- if (fd == -1)
- return 2;
-
- ::close(fd);
- return 1;
-# endif
-}
-#endif
-
-
-/*
- * Reason for using this function: kde_getaddrinfo
- *
- * I decided to add this wrapper function for getaddrinfo
- * and have this be called by KExtendedSocket instead of
- * the real getaddrinfo so that we can make sure that the
- * behavior is the desired one.
- *
- * Currently, the only "undesired" behavior is getaddrinfo
- * not returning PF_UNIX sockets in some implementations.
- *
- * getaddrinfo and family are defined in POSIX 1003.1g
- * (Protocol Independent Interfaces) and in RFC 2553
- * (Basic Socket Interface for IPv6). Whereas the RFC is ambiguosly
- * vague whether this family of functions should return Internet
- * sockets only or not, the name of the POSIX draft says
- * otherwise: it should be independent of protocol.
- *
- * So, my interpretation is that they should return every
- * kind of socket available and known and that's how I
- * designed KExtendedSocket on top of it.
- *
- * That's why there's this wrapper, to make sure PF_UNIX
- * sockets are returned when expected.
- */
-
-int kde_getaddrinfo(const char *name, const char *service,
- const struct addrinfo* hint,
- struct kde_addrinfo** result)
-{
- struct kde_addrinfo* res;
- struct addrinfo* p;
- int err = EAI_SERVICE;
-#if defined(KDE_IPV6_LOOKUP_MODE) && KDE_IPV6_LOOKUP_MODE == 1
- // mode 1: do a check on whether we have an IPv6 stack
- static int ipv6_stack = 0; // 0: unknown, 1: yes, 2: no
-#endif
-
- // allocate memory for results
- res = (kde_addrinfo*)malloc(sizeof(*res));
- if (res == NULL)
- return EAI_MEMORY;
- res->data = NULL;
- res->origin = KAI_SYSTEM; // at first, it'll be only system data
-
- struct addrinfo* last = NULL;
-
- // Skip the getaddrinfo call and the ipv6 check for a UNIX socket.
- if (hint && (hint->ai_family == PF_UNIX))
- {
- if (service == NULL || *service == '\0')
- goto out; // can't be Unix if no service was requested
-
- // Unix sockets must be localhost
- // That is, either name is NULL or, if it's not, it must be empty,
- // "*" or "localhost"
- if (name != NULL && !(name[0] == '\0' || (name[0] == '*' && name[1] == '\0') ||
- strcmp("localhost", name) == 0))
- goto out; // isn't localhost
-
- goto do_unix;
- }
-
-#if defined(KDE_IPV6_LOOKUP_MODE) && KDE_IPV6_LOOKUP_MODE != 0
-# if KDE_IPV6_LOOKUP_MODE == 1
- // mode 1: do a check on whether we have an IPv6 stack
- if (ipv6_stack == 0)
- ipv6_stack = check_ipv6_stack();
-
- if (ipv6_stack == 2)
- {
-# endif
- // here we have modes 1 and 2 (no lookups)
- // this is shared code
- struct addrinfo our_hint;
- if (hint != NULL)
- {
- memcpy(&our_hint, hint, sizeof(our_hint));
- if (our_hint.ai_family == AF_UNSPEC)
- our_hint.ai_family = AF_INET;
- }
- else
- {
- memset(&our_hint, 0, sizeof(our_hint));
- our_hint.ai_family = AF_INET;
- }
-
- // do the actual resolution
- err = getaddrinfo(name, service, &our_hint, &res->data);
-# if KDE_IPV6_LOOKUP_MODE == 1
- }
- else
-# endif
-#endif
-#if defined(KDE_IPV6_LOOKUP_MODE) && KDE_IPV6_LOOKUP_MODE != 2
- // do the IPV6 resolution
- err = getaddrinfo(name, service, hint, &res->data);
-#endif
-
- // Now we have to check whether the user could want a Unix socket
-
- if (service == NULL || *service == '\0')
- goto out; // can't be Unix if no service was requested
-
- // Unix sockets must be localhost
- // That is, either name is NULL or, if it's not, it must be empty,
- // "*" or "localhost"
- if (name != NULL && !(name[0] == '\0' || (name[0] == '*' && name[1] == '\0') ||
- strcmp("localhost", name) == 0))
- goto out; // isn't localhost
-
- // Unix sockets can only be returned if the user asked for a PF_UNSPEC
- // or PF_UNIX socket type or gave us a NULL hint
- if (hint != NULL && (hint->ai_family != PF_UNSPEC && hint->ai_family != PF_UNIX))
- goto out; // user doesn't want Unix
-
- // If we got here, then it means that the user might be expecting Unix
- // sockets. The user wants a local socket, with a non-null service and
- // has told us that they accept PF_UNIX sockets
- // Check whether the system implementation returned Unix
- if (err == 0)
- for (p = res->data; p; p = p->ai_next)
- {
- last = p; // we have to find out which one is last anyways
- if (p->ai_family == AF_UNIX)
- // there is an Unix node
- goto out;
- }
-
- do_unix:
- // So, give the user a PF_UNIX socket
- p = make_unix(NULL, service);
- if (p == NULL)
- {
- err = EAI_MEMORY;
- goto out;
- }
- if (hint != NULL)
- p->ai_socktype = hint->ai_socktype;
- if (p->ai_socktype == 0)
- p->ai_socktype = SOCK_STREAM; // default
-
- if (last)
- last->ai_next = p;
- else
- res->data = p;
- res->origin = KAI_LOCALUNIX;
- *result = res;
- return 0;
-
- out:
- if (res->data != NULL)
- freeaddrinfo(res->data);
- free(res);
- return err;
-}
-
-#if defined(HAVE_GETADDRINFO) && !defined(HAVE_BROKEN_GETADDRINFO)
-
-#define KRF_getaddrinfo 0
-#define KRF_resolver 0
-
-#else // !defined(HAVE_GETADDRINFO) || defined(HAVE_BROKEN_GETADDRINFO)
-
-#define KRF_getaddrinfo KRF_USING_OWN_GETADDRINFO
-#define KRF_resolver KRF_CAN_RESOLVE_UNIX | KRF_CAN_RESOLVE_IPV4
-
-/*
- * No getaddrinfo() in this system.
- * We shall provide our own
- */
-
-/** TODO
- * Try and use gethostbyname2_r before gethostbyname2 and gethostbyname
- */
-static int inet_lookup(const char *name, int portnum, int protonum,
- struct addrinfo *p, const struct addrinfo *hint,
- struct addrinfo** result)
-{
- struct addrinfo *q;
- struct hostent *h;
- struct sockaddr **psa = NULL;
- int len;
-
- // TODO
- // Currently, this never resolves IPv6 (need gethostbyname2, etc.)
-# ifdef AF_INET6
- if (hint->ai_family == AF_INET6)
- {
- if (p != NULL)
- {
- *result = p;
- return 0;
- }
- return EAI_FAIL;
- }
-# endif
-
- q = (addrinfo*)malloc(sizeof(*q));
- if (q == NULL)
- {
- freeaddrinfo(p);
- return EAI_MEMORY;
- }
-
- h = gethostbyname(name);
- if (h == NULL)
- {
- if (p != NULL)
- {
- // There already is a suitable result
- *result = p;
- return 0;
- }
-
- switch (h_errno)
- {
- case HOST_NOT_FOUND:
- return EAI_NONAME;
- case TRY_AGAIN:
- return EAI_AGAIN;
- case NO_RECOVERY:
- return EAI_FAIL;
- case NO_ADDRESS:
- return EAI_NODATA;
- default:
- // EH!?
- return EAI_FAIL;
- }
- }
-
- // convert the hostent to addrinfo
- if (h->h_addrtype == AF_INET && (hint->ai_family == AF_INET || hint->ai_family == AF_UNSPEC))
- len = sizeof(struct sockaddr_in);
-# ifdef AF_INET6
- else if (h->h_addrtype == AF_INET6 && (hint->ai_family == AF_INET6 ||
- hint->ai_family == AF_UNSPEC))
- len = sizeof(struct sockaddr_in6);
-# endif
- else
- {
- // We don't know what to do with these addresses
- // Or gethostbyname returned information we don't want
- if (p != NULL)
- {
- *result = p;
- return 0;
- }
- return EAI_NODATA;
- }
-
- q->ai_flags = 0;
- q->ai_family = h->h_addrtype;
- q->ai_socktype = hint->ai_socktype;
- q->ai_protocol = protonum;
- q->ai_addrlen = len;
-
- q->ai_addr = (sockaddr*)malloc(len);
- if (q->ai_addr == NULL)
- {
- free(q);
- freeaddrinfo(p);
- return EAI_MEMORY;
- }
- if (h->h_addrtype == AF_INET)
- {
- struct sockaddr_in *sin = (sockaddr_in*)q->ai_addr;
- sin->sin_family = AF_INET;
-# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
- sin->sin_len = sizeof(*sin);
-# endif
- sin->sin_port = portnum;
- memcpy(&sin->sin_addr, h->h_addr, h->h_length);
- }
-# ifdef AF_INET6
- else if (h->h_addrtype == AF_INET6)
- {
- struct sockaddr_in6 *sin6 = (sockaddr_in6*)q->ai_addr;
- sin6->sin6_family = AF_INET6;
-# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
- sin6->sin6_len = sizeof(*sin6);
-# endif
- sin6->sin6_port = portnum;
- sin6->sin6_flowinfo = 0;
- memcpy(&sin6->sin6_addr, h->h_addr, h->h_length);
- sin6->sin6_scope_id = 0;
- }
-# endif
-
- if (hint->ai_flags & AI_CANONNAME)
- q->ai_canonname = strdup(h->h_name);
- else
- q->ai_canonname = NULL;
-
- q->ai_next = p;
- p = q;
-
- // cycle through the rest of the hosts;
- for (psa = (sockaddr**)h->h_addr_list + 1; *psa; psa++)
- {
- q = (addrinfo*)malloc(sizeof(*q));
- if (q == NULL)
- {
- freeaddrinfo(p);
- return EAI_MEMORY;
- }
- memcpy(q, p, sizeof(*q));
-
- q->ai_addr = (sockaddr*)malloc(h->h_length);
- if (q->ai_addr == NULL)
- {
- freeaddrinfo(p);
- free(q);
- return EAI_MEMORY;
- }
- if (h->h_addrtype == AF_INET)
- {
- struct sockaddr_in *sin = (sockaddr_in*)q->ai_addr;
- sin->sin_family = AF_INET;
-# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
- sin->sin_len = sizeof(*sin);
-# endif
- sin->sin_port = portnum;
- memcpy(&sin->sin_addr, *psa, h->h_length);
- }
-# ifdef AF_INET6
- else if (h->h_addrtype == AF_INET6)
- {
- struct sockaddr_in6 *sin6 = (sockaddr_in6*)q->ai_addr;
- sin6->sin6_family = AF_INET6;
-# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
- sin6->sin6_len = sizeof(*sin6);
-# endif
- sin6->sin6_port = portnum;
- sin6->sin6_flowinfo = 0;
- memcpy(&sin6->sin6_addr, *psa, h->h_length);
- sin6->sin6_scope_id = 0;
- }
-# endif
-
- if (q->ai_canonname != NULL)
- q->ai_canonname = strdup(q->ai_canonname);
-
- q->ai_next = p;
- p = q;
- }
-
- *result = p;
- return 0; // Whew! Success!
-}
-
-static int make_inet(const char *name, int portnum, int protonum, struct addrinfo *p,
- const struct addrinfo *hint, struct addrinfo** result)
-{
- struct addrinfo *q;
-
- do
- {
- // This 'do' is here just so that we can 'break' out of it
-
- if (name != NULL)
- {
- // first, try to use inet_pton before resolving
- // it will catch IP addresses given without having to go to lookup
- struct sockaddr_in *sin;
- struct in_addr in;
-# ifdef AF_INET6
- struct sockaddr_in6 *sin6;
- struct in6_addr in6;
-
- if (hint->ai_family == AF_INET6 || (hint->ai_family == AF_UNSPEC &&
- strchr(name, ':') != NULL))
- {
- // yes, this is IPv6
- if (inet_pton(AF_INET6, name, &in6) != 1)
- {
- if (hint->ai_flags & AI_NUMERICHOST)
- {
- freeaddrinfo(p);
- return EAI_FAIL;
- }
- break; // not a numeric host
- }
-
- sin6 = (sockaddr_in6*)malloc(sizeof(*sin6));
- if (sin6 == NULL)
- {
- freeaddrinfo(p);
- return EAI_MEMORY;
- }
- memcpy(&sin6->sin6_addr, &in6, sizeof(in6));
-
- if (strchr(name, '%') != NULL)
- {
- errno = 0;
- sin6->sin6_scope_id = strtoul(strchr(name, '%') + 1, NULL, 10);
- if (errno != 0)
- sin6->sin6_scope_id = 0; // no interface
- }
-
- q = (addrinfo*)malloc(sizeof(*q));
- if (q == NULL)
- {
- freeaddrinfo(p);
- free(sin6);
- return EAI_MEMORY;
- }
-
- sin6->sin6_family = AF_INET6;
-# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
- sin6->sin6_len = sizeof(*sin6);
-# endif
- sin6->sin6_port = portnum;
- sin6->sin6_flowinfo = 0;
-
- q->ai_flags = 0;
- q->ai_family = AF_INET6;
- q->ai_socktype = hint->ai_socktype;
- q->ai_protocol = protonum;
- q->ai_addrlen = sizeof(*sin6);
- q->ai_canonname = NULL;
- q->ai_addr = (sockaddr*)sin6;
- q->ai_next = p;
-
- *result = q;
- return 0; // success!
- }
-# endif // AF_INET6
-
- if (hint->ai_family == AF_INET || hint->ai_family == AF_UNSPEC)
- {
- // This has to be IPv4
- if (inet_pton(AF_INET, name, &in) != 1)
- {
- if (hint->ai_flags & AI_NUMERICHOST)
- {
- freeaddrinfo(p);
- return EAI_FAIL; // invalid, I guess
- }
- break; // not a numeric host, do lookup
- }
-
- sin = (sockaddr_in*)malloc(sizeof(*sin));
- if (sin == NULL)
- {
- freeaddrinfo(p);
- return EAI_MEMORY;
- }
-
- q = (addrinfo*)malloc(sizeof(*q));
- if (q == NULL)
- {
- freeaddrinfo(p);
- free(sin);
- return EAI_MEMORY;
- }
-
- sin->sin_family = AF_INET;
-# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
- sin->sin_len = sizeof(*sin);
-# endif
- sin->sin_port = portnum;
- sin->sin_addr = in;
-
- q->ai_flags = 0;
- q->ai_family = AF_INET;
- q->ai_socktype = hint->ai_socktype;
- q->ai_protocol = protonum;
- q->ai_addrlen = sizeof(*sin);
- q->ai_canonname = NULL;
- q->ai_addr = (sockaddr*)sin;
- q->ai_next = p;
- *result = q;
- return 0;
- }
-
- // Eh, what!?
- // One of the two above has to have matched
- kdError() << "I wasn't supposed to get here!";
- }
- } while (false);
-
- // This means localhost
- if (name == NULL)
- {
- struct sockaddr_in *sin = (sockaddr_in*)malloc(sizeof(*sin));
-# ifdef AF_INET6
- struct sockaddr_in6 *sin6;
-# endif
-
- if (hint->ai_family == AF_INET || hint->ai_family == AF_UNSPEC)
- {
- if (sin == NULL)
- {
- free(sin);
- freeaddrinfo(p);
- return EAI_MEMORY;
- }
-
- // Do IPv4 first
- q = (addrinfo*)malloc(sizeof(*q));
- if (q == NULL)
- {
- free(sin);
- freeaddrinfo(p);
- return EAI_MEMORY;
- }
-
- sin->sin_family = AF_INET;
-# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
- sin->sin_len = sizeof(*sin);
-# endif
- sin->sin_port = portnum;
- if (hint->ai_flags & AI_PASSIVE)
- *(TQ_UINT32*)&sin->sin_addr = INADDR_ANY;
- else
- *(TQ_UINT32*)&sin->sin_addr = htonl(INADDR_LOOPBACK);
- q->ai_flags = 0;
- q->ai_family = AF_INET;
- q->ai_socktype = hint->ai_socktype;
- q->ai_protocol = protonum;
- q->ai_addrlen = sizeof(*sin);
- q->ai_canonname = NULL;
- q->ai_addr = (sockaddr*)sin;
- q->ai_next = p;
- p = q;
- }
-
-# ifdef AF_INET6
- // Try now IPv6
-
- if (hint->ai_family == AF_INET6 || hint->ai_family == AF_UNSPEC)
- {
- sin6 = (sockaddr_in6*)malloc(sizeof(*sin6));
- q = (addrinfo*)malloc(sizeof(*q));
- if (q == NULL || sin6 == NULL)
- {
- free(sin6);
- free(q);
- freeaddrinfo(p);
- return EAI_MEMORY;
- }
-
- sin6->sin6_family = AF_INET6;
-# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
- sin6->sin6_len = sizeof(*sin6);
-# endif
- sin6->sin6_port = portnum;
- sin6->sin6_flowinfo = 0;
- sin6->sin6_scope_id = 0;
-
- // We don't want to use in6addr_loopback and in6addr_any
- memset(&sin6->sin6_addr, 0, sizeof(sin6->sin6_addr));
- if ((hint->ai_flags & AI_PASSIVE) == 0)
- ((char*)&sin6->sin6_addr)[15] = 1;
-
- q->ai_flags = 0;
- q->ai_family = AF_INET6;
- q->ai_socktype = hint->ai_socktype;
- q->ai_protocol = protonum;
- q->ai_addrlen = sizeof(*sin6);
- q->ai_canonname = NULL;
- q->ai_addr = (sockaddr*)sin6;
- q->ai_next = p;
- p = q;
- }
-
-# endif // AF_INET6
-
- *result = p;
- return 0; // success!
- }
-
- return inet_lookup(name, portnum, protonum, p, hint, result);
-}
-
-
-int getaddrinfo(const char *name, const char *serv,
- const struct addrinfo* hint,
- struct addrinfo** result)
-{
- unsigned short portnum; // remember to store in network byte order
- int protonum = IPPROTO_TCP;
- const char *proto = "tcp";
- struct addrinfo *p = NULL;
-
- // Sanity checks:
- if (hint == NULL || result == NULL)
- return EAI_BADFLAGS;
- if (hint->ai_family != AF_UNSPEC && hint->ai_family != AF_UNIX &&
- hint->ai_family != AF_INET
-# ifdef AF_INET6
- && hint->ai_family != AF_INET6
-# endif
- )
- return EAI_FAMILY;
- if (hint->ai_socktype != 0 && hint->ai_socktype != SOCK_STREAM &&
- hint->ai_socktype != SOCK_DGRAM)
- return EAI_SOCKTYPE;
-
- // Treat hostname of "*" as NULL, which means localhost
- if (name != NULL && ((*name == '*' && name[1] == '\0') || *name == '\0'))
- name = NULL;
- // Treat service of "*" as NULL, which I guess means no port (0)
- if (serv != NULL && ((*serv == '*' && serv[1] == '\0') || *serv == '\0'))
- serv = NULL;
-
- if (name == NULL && serv == NULL) // what the hell do you want?
- return EAI_NONAME;
-
- // This is just to make it easier
- if (name != NULL && strcmp(name, "localhost") == 0)
- name = NULL;
-
- // First, check for a Unix socket
- // family must be either AF_UNIX or AF_UNSPEC
- // either of name or serv must be set, the other must be NULL or empty
- if (hint->ai_family == AF_UNIX || hint->ai_family == AF_UNSPEC)
- {
- if (name != NULL && serv != NULL)
- {
- // This is not allowed
- if (hint->ai_family == AF_UNIX)
- return EAI_BADFLAGS;
- }
- else
- {
- p = make_unix(name, serv);
- if (p == NULL)
- return EAI_MEMORY;
-
- p->ai_socktype = hint->ai_socktype;
- // If the name/service started with a slash, then this *IS*
- // only a Unix socket. Return.
- if (hint->ai_family == AF_UNIX || ((name != NULL && *name == '/') ||
- (serv != NULL && *serv == '/')))
- {
- *result = p;
- return 0; // successful lookup
- }
- }
- }
-
- // Lookup the service name, if required
- if (serv != NULL)
- {
- char *tail;
- struct servent *sent;
-
- portnum = htons((unsigned)strtoul(serv, &tail, 10));
- if (*tail != '\0')
- {
- // not a number. We have to do the lookup
- if (hint->ai_socktype == SOCK_DGRAM)
- {
- proto = "udp";
- protonum = IPPROTO_UDP;
- }
-
- sent = getservbyname(serv, proto);
- if (sent == NULL) // no service?
- {
- if (p == NULL)
- return EAI_NONAME;
- else
- return 0; // a Unix socket available
- }
-
- portnum = sent->s_port;
- }
- }
- else
- portnum = 0; // no port number
-
- return make_inet(name, portnum, protonum, p, hint, result);
-}
-
-void freeaddrinfo(struct addrinfo *p)
-{
- dofreeaddrinfo(p);
-}
-
-char *gai_strerror(int errorcode)
-{
- static const char * const messages[] =
- {
- I18N_NOOP("no error"), // 0
- I18N_NOOP("address family for nodename not supported"), // EAI_ADDRFAMILY
- I18N_NOOP("temporary failure in name resolution"), // EAI_AGAIN
- I18N_NOOP("invalid value for 'ai_flags'"), // EAI_BADFLAGS
- I18N_NOOP("non-recoverable failure in name resolution"), // EAI_FAIL
- I18N_NOOP("'ai_family' not supported"), // EAI_FAMILY
- I18N_NOOP("memory allocation failure"), // EAI_MEMORY
- I18N_NOOP("no address associated with nodename"), // EAI_NODATA
- I18N_NOOP("name or service not known"), // EAI_NONAME
- I18N_NOOP("servname not supported for ai_socktype"), // EAI_SERVICE
- I18N_NOOP("'ai_socktype' not supported"), // EAI_SOCKTYPE
- I18N_NOOP("system error") // EAI_SYSTEM
- };
-
- if (errorcode > EAI_SYSTEM || errorcode < 0)
- return NULL;
-
- static char buffer[200];
- strcpy(buffer, i18n(messages[errorcode]).local8Bit());
- return buffer;
-}
-
-static void findport(unsigned short port, char *serv, size_t servlen, int flags)
-{
- if (serv == NULL)
- return;
-
- if ((flags & NI_NUMERICSERV) == 0)
- {
- struct servent *sent;
- sent = getservbyport(ntohs(port), flags & NI_DGRAM ? "udp" : "tcp");
- if (sent != NULL && servlen > strlen(sent->s_name))
- {
- strcpy(serv, sent->s_name);
- return;
- }
- }
-
- snprintf(serv, servlen, "%u", ntohs(port));
-}
-
-int getnameinfo(const struct sockaddr *sa, ksocklen_t salen,
- char *host, size_t hostlen, char *serv, size_t servlen,
- int flags)
-{
- union
- {
- const sockaddr *sa;
- const sockaddr_un *_sun;
- const sockaddr_in *sin;
- const sockaddr_in6 *sin6;
- } s;
-
- if ((host == NULL || hostlen == 0) && (serv == NULL || servlen == 0))
- return 1;
-
- s.sa = sa;
- if (s.sa->sa_family == AF_UNIX)
- {
- if (salen < offsetof(struct sockaddr_un, sun_path) + strlen(s._sun->sun_path) + 1)
- return 1; // invalid socket
-
- if (servlen && serv != NULL)
- *serv = '\0';
- if (host != NULL && hostlen > strlen(s._sun->sun_path))
- strcpy(host, s._sun->sun_path);
-
- return 0;
- }
- else if (s.sa->sa_family == AF_INET)
- {
- if (salen < offsetof(struct sockaddr_in, sin_addr) + sizeof(s.sin->sin_addr))
- return 1; // invalid socket
-
- if (flags & NI_NUMERICHOST)
- inet_ntop(AF_INET, &s.sin->sin_addr, host, hostlen);
- else
- {
- // have to do lookup
- struct hostent *h = gethostbyaddr((const char*)&s.sin->sin_addr, sizeof(s.sin->sin_addr),
- AF_INET);
- if (h == NULL && flags & NI_NAMEREQD)
- return 1;
- else if (h == NULL)
- inet_ntop(AF_INET, &s.sin->sin_addr, host, hostlen);
- else if (host != NULL && hostlen > strlen(h->h_name))
- strcpy(host, h->h_name);
- else
- return 1; // error
- }
-
- findport(s.sin->sin_port, serv, servlen, flags);
- }
-# ifdef AF_INET6
- else if (s.sa->sa_family == AF_INET6)
- {
- if (salen < offsetof(struct sockaddr_in6, sin6_addr) + sizeof(s.sin6->sin6_addr))
- return 1; // invalid socket
-
- if (flags & NI_NUMERICHOST)
- inet_ntop(AF_INET6, &s.sin6->sin6_addr, host, hostlen);
- else
- {
- // have to do lookup
- struct hostent *h = gethostbyaddr((const char*)&s.sin->sin_addr, sizeof(s.sin->sin_addr),
- AF_INET6);
- if (h == NULL && flags & NI_NAMEREQD)
- return 1;
- else if (h == NULL)
- inet_ntop(AF_INET6, &s.sin6->sin6_addr, host, hostlen);
- else if (host != NULL && hostlen > strlen(h->h_name))
- strcpy(host, h->h_name);
- else
- return 1; // error
- }
-
- findport(s.sin6->sin6_port, serv, servlen, flags);
- }
-# endif // AF_INET6
-
- return 1; // invalid family
-}
-
-#endif // HAVE_GETADDRINFO
-
-#ifndef HAVE_INET_NTOP
-
-#define KRF_inet_ntop KRF_USING_OWN_INET_NTOP
-
-static void add_dwords(char *buf, TQ_UINT16 *dw, int count)
-{
- int i = 1;
- sprintf(buf + strlen(buf), "%x", ntohs(dw[0]));
- while (--count)
- sprintf(buf + strlen(buf), ":%x", ntohs(dw[i++]));
-}
-
-const char* inet_ntop(int af, const void *cp, char *buf, size_t len)
-{
- char buf2[sizeof "1234:5678:9abc:def0:1234:5678:255.255.255.255" + 1];
- TQ_UINT8 *data = (TQ_UINT8*)cp;
-
- if (af == AF_INET)
- {
- sprintf(buf2, "%u.%u.%u.%u", data[0], data[1], data[2], data[3]);
-
- if (len > strlen(buf2))
- {
- strcpy(buf, buf2);
- return buf;
- }
-
- errno = ENOSPC;
- return NULL; // failed
- }
-
-# ifdef AF_INET6
- if (af == AF_INET6)
- {
- TQ_UINT16 *p = (TQ_UINT16*)data;
- TQ_UINT16 *longest = NULL, *cur = NULL;
- int longest_length = 0, cur_length;
- int i;
-
- if (KDE_IN6_IS_ADDR_V4MAPPED(p) || KDE_IN6_IS_ADDR_V4COMPAT(p))
- sprintf(buf2, "::%s%u.%u.%u.%u",
- KDE_IN6_IS_ADDR_V4MAPPED(p) ? "ffff:" : "",
- buf[12], buf[13], buf[14], buf[15]);
- else
- {
- // find the longest sequence of zeroes
- for (i = 0; i < 8; i++)
- if (cur == NULL && p[i] == 0)
- {
- // a zero, start the sequence
- cur = p + i;
- cur_length = 1;
- }
- else if (cur != NULL && p[i] == 0)
- // part of the sequence
- cur_length++;
- else if (cur != NULL && p[i] != 0)
- {
- // end of the sequence
- if (cur_length > longest_length)
- {
- longest_length = cur_length;
- longest = cur;
- }
- cur = NULL; // restart sequence
- }
- if (cur != NULL && cur_length > longest_length)
- {
- longest_length = cur_length;
- longest = cur;
- }
-
- if (longest_length > 1)
- {
- // We have a candidate
- buf2[0] = '\0';
- if (longest != p)
- add_dwords(buf2, p, longest - p);
- strcat(buf2, "::");
- if (longest + longest_length < p + 8)
- add_dwords(buf2, longest + longest_length, 8 - (longest - p) - longest_length);
- }
- else
- {
- // Nope, no candidate
- buf2[0] = '\0';
- add_dwords(buf2, p, 8);
- }
- }
-
- if (strlen(buf2) < len)
- {
- strcpy(buf, buf2);
- return buf;
- }
-
- errno = ENOSPC;
- return NULL;
- }
-# endif
-
- errno = EAFNOSUPPORT;
- return NULL; // a family we don't know about
-}
-
-#else // HAVE_INET_NTOP
-
-#define KRF_inet_ntop 0
-
-#endif // HAVE_INET_NTOP
-
-#ifndef HAVE_INET_PTON
-
-#define KRF_inet_pton KRF_USING_OWN_INET_PTON
-int inet_pton(int af, const char *cp, void *buf)
-{
- if (af == AF_INET)
- {
- // Piece of cake
- unsigned p[4];
- unsigned char *q = (unsigned char*)buf;
- if (sscanf(cp, "%u.%u.%u.%u", p, p + 1, p + 2, p + 3) != 4)
- return 0;
-
- if (p[0] > 0xff || p[1] > 0xff || p[2] > 0xff || p[3] > 0xff)
- return 0;
-
- q[0] = p[0];
- q[1] = p[1];
- q[2] = p[2];
- q[3] = p[3];
-
- return 1;
- }
-
-# ifdef AF_INET6
- else if (af == AF_INET6)
- {
- TQ_UINT16 addr[8];
- const char *p = cp;
- int n = 0, start = 8;
- bool has_v4 = strchr(p, '.') != NULL;
-
- memset(addr, 0, sizeof(addr));
-
- if (*p == '\0' || p[1] == '\0')
- return 0; // less than 2 chars is not valid
-
- if (*p == ':' && p[1] == ':')
- {
- start = 0;
- p += 2;
- }
- while (*p)
- {
- if (has_v4 && inet_pton(AF_INET, p, addr + n) != 0)
- {
- // successful v4 convertion
- addr[n] = ntohs(addr[n]);
- n++;
- addr[n] = ntohs(addr[n]);
- n++;
- break;
- }
- if (sscanf(p, "%hx", addr + n++) != 1)
- return 0;
-
- while (*p && *p != ':')
- p++;
- if (!*p)
- break;
- p++;
-
- if (*p == ':') // another ':'?
- {
- if (start != 8)
- return 0; // two :: were found
- start = n;
- p++;
- }
- }
-
- // if start is not 8, then a "::" was found at word 'start'
- // n is the number of converted words
- // n == 8 means everything was converted and no moving is necessary
- // n < 8 means that we have to move n - start words 8 - n words to the right
- if (start == 8 && n != 8)
- return 0; // bad conversion
- memmove(addr + start + (8 - n), addr + start, (n - start) * sizeof(TQ_UINT16));
- memset(addr + start, 0, (8 - n) * sizeof(TQ_UINT16));
-
- // check the byte order
- // The compiler should optimise this out in big endian machines
- if (htons(0x1234) != 0x1234)
- for (n = 0; n < 8; n++)
- addr[n] = htons(addr[n]);
-
- memcpy(buf, addr, sizeof(addr));
- return 1;
- }
-# endif
-
- errno = EAFNOSUPPORT;
- return -1; // unknown family
-}
-
-#else // HAVE_INET_PTON
-
-#define KRF_inet_pton 0
-
-#endif // HAVE_INET_PTON
-
-#ifdef AF_INET6
-# define KRF_afinet6 KRF_KNOWS_AF_INET6
-#else
-# define KRF_afinet6 0
-#endif
-
-namespace KDE
-{
- /** @internal */
- extern const int KDE_EXPORT resolverFlags = KRF_getaddrinfo | KRF_resolver | KRF_afinet6 | KRF_inet_ntop | KRF_inet_pton;
-}