21 #include <sys/types.h> 22 #include <sys/socket.h> 24 #include <netinet/in.h> 29 #include <arpa/inet.h> 42 #ifndef IN6_IS_ADDR_V4MAPPED 43 #define NEED_IN6_TESTS 47 #include "ksockaddr.h" 49 #if defined(__hpux) || defined(_HPUX_SOURCE) 53 #include <kdemacros.h> 55 #if !defined(kde_sockaddr_in6) 63 # define sockaddr_in6 kde_sockaddr_in6 64 # define in6_addr kde_in6_addr 70 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 77 #define KRF_KNOWS_AF_INET6 0x01 78 #define KRF_USING_OWN_GETADDRINFO 0x02 79 #define KRF_USING_OWN_INET_NTOP 0x04 80 #define KRF_USING_OWN_INET_PTON 0x08 81 #define KRF_CAN_RESOLVE_UNIX 0x100 82 #define KRF_CAN_RESOLVE_IPV4 0x200 83 #define KRF_CAN_RESOLVE_IPV6 0x400 86 static void dofreeaddrinfo(
struct addrinfo *ai)
90 struct addrinfo *ai2 = ai;
91 if (ai->ai_canonname != NULL)
92 free(ai->ai_canonname);
94 if (ai->ai_addr != NULL)
102 void kde_freeaddrinfo(
struct kde_addrinfo *ai)
104 if (ai->origin == KAI_LOCALUNIX)
106 struct addrinfo *p, *last = NULL;
109 for (p = ai->data; p; p = p->ai_next)
111 if (p->ai_family == AF_UNIX)
115 last->ai_next = NULL;
116 freeaddrinfo(ai->data);
125 freeaddrinfo(ai->data);
130 static struct addrinfo*
131 make_unix(
const char *name,
const char *serv)
135 struct sockaddr_un *_sun;
138 p = (addrinfo*)malloc(
sizeof(*p));
141 memset(p, 0,
sizeof(*p));
149 len = strlen(buf) + offsetof(
struct sockaddr_un, sun_path) + 1;
153 _sun = (sockaddr_un*)malloc(len);
161 _sun->sun_family = AF_UNIX;
162 # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN 166 *_sun->sun_path =
'\0';
168 strcpy(_sun->sun_path,
"/tmp/");
169 strcat(_sun->sun_path, buf);
172 p->ai_family = AF_UNIX;
174 p->ai_addr = (sockaddr*)_sun;
175 p->ai_canonname = strdup(buf);
186 #if defined(KDE_IPV6_LOOKUP_MODE) && KDE_IPV6_LOOKUP_MODE == 1 187 static int check_ipv6_stack()
192 if (getenv(
"TDE_NO_IPV6"))
194 int fd = ::socket(AF_INET6, SOCK_STREAM, 0);
231 int kde_getaddrinfo(
const char *name,
const char *service,
232 const struct addrinfo* hint,
233 struct kde_addrinfo** result)
235 struct kde_addrinfo* res;
237 int err = EAI_SERVICE;
238 #if defined(KDE_IPV6_LOOKUP_MODE) && KDE_IPV6_LOOKUP_MODE == 1 240 static int ipv6_stack = 0;
244 res = (kde_addrinfo*)malloc(
sizeof(*res));
248 res->origin = KAI_SYSTEM;
250 struct addrinfo* last = NULL;
253 if (hint && (hint->ai_family == PF_UNIX))
255 if (service == NULL || *service ==
'\0')
261 if (name != NULL && !(name[0] ==
'\0' || (name[0] ==
'*' && name[1] ==
'\0') ||
262 strcmp(
"localhost", name) == 0))
268 #if defined(KDE_IPV6_LOOKUP_MODE) && KDE_IPV6_LOOKUP_MODE != 0 269 # if KDE_IPV6_LOOKUP_MODE == 1 272 ipv6_stack = check_ipv6_stack();
279 struct addrinfo our_hint;
282 memcpy(&our_hint, hint,
sizeof(our_hint));
283 if (our_hint.ai_family == AF_UNSPEC)
284 our_hint.ai_family = AF_INET;
288 memset(&our_hint, 0,
sizeof(our_hint));
289 our_hint.ai_family = AF_INET;
293 err = getaddrinfo(name, service, &our_hint, &res->data);
294 # if KDE_IPV6_LOOKUP_MODE == 1 299 #if defined(KDE_IPV6_LOOKUP_MODE) && KDE_IPV6_LOOKUP_MODE != 2 301 err = getaddrinfo(name, service, hint, &res->data);
306 if (service == NULL || *service ==
'\0')
312 if (name != NULL && !(name[0] ==
'\0' || (name[0] ==
'*' && name[1] ==
'\0') ||
313 strcmp(
"localhost", name) == 0))
318 if (hint != NULL && (hint->ai_family != PF_UNSPEC && hint->ai_family != PF_UNIX))
326 for (p = res->data; p; p = p->ai_next)
329 if (p->ai_family == AF_UNIX)
336 p = make_unix(NULL, service);
343 p->ai_socktype = hint->ai_socktype;
344 if (p->ai_socktype == 0)
345 p->ai_socktype = SOCK_STREAM;
351 res->origin = KAI_LOCALUNIX;
356 if (res->data != NULL)
357 freeaddrinfo(res->data);
362 #if defined(HAVE_GETADDRINFO) && !defined(HAVE_BROKEN_GETADDRINFO) 364 #define KRF_getaddrinfo 0 365 #define KRF_resolver 0 367 #else // !defined(HAVE_GETADDRINFO) || defined(HAVE_BROKEN_GETADDRINFO) 369 #define KRF_getaddrinfo KRF_USING_OWN_GETADDRINFO 370 #define KRF_resolver KRF_CAN_RESOLVE_UNIX | KRF_CAN_RESOLVE_IPV4 380 static int inet_lookup(
const char *name,
int portnum,
int protonum,
381 struct addrinfo *p,
const struct addrinfo *hint,
382 struct addrinfo** result)
386 struct sockaddr **psa = NULL;
392 if (hint->ai_family == AF_INET6)
403 q = (addrinfo*)malloc(
sizeof(*q));
410 h = gethostbyname(name);
437 if (h->h_addrtype == AF_INET && (hint->ai_family == AF_INET || hint->ai_family == AF_UNSPEC))
438 len =
sizeof(
struct sockaddr_in);
440 else if (h->h_addrtype == AF_INET6 && (hint->ai_family == AF_INET6 ||
441 hint->ai_family == AF_UNSPEC))
442 len =
sizeof(
struct sockaddr_in6);
457 q->ai_family = h->h_addrtype;
458 q->ai_socktype = hint->ai_socktype;
459 q->ai_protocol = protonum;
462 q->ai_addr = (sockaddr*)malloc(len);
463 if (q->ai_addr == NULL)
469 if (h->h_addrtype == AF_INET)
471 struct sockaddr_in *sin = (sockaddr_in*)q->ai_addr;
472 sin->sin_family = AF_INET;
473 # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
474 sin->sin_len =
sizeof(*sin);
476 sin->sin_port = portnum;
477 memcpy(&sin->sin_addr, h->h_addr, h->h_length);
480 else if (h->h_addrtype == AF_INET6)
482 struct sockaddr_in6 *sin6 = (sockaddr_in6*)q->ai_addr;
483 sin6->sin6_family = AF_INET6;
484 # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
485 sin6->sin6_len =
sizeof(*sin6);
487 sin6->sin6_port = portnum;
488 sin6->sin6_flowinfo = 0;
489 memcpy(&sin6->sin6_addr, h->h_addr, h->h_length);
490 sin6->sin6_scope_id = 0;
494 if (hint->ai_flags & AI_CANONNAME)
495 q->ai_canonname = strdup(h->h_name);
497 q->ai_canonname = NULL;
503 for (psa = (sockaddr**)h->h_addr_list + 1; *psa; psa++)
505 q = (addrinfo*)malloc(
sizeof(*q));
511 memcpy(q, p,
sizeof(*q));
513 q->ai_addr = (sockaddr*)malloc(h->h_length);
514 if (q->ai_addr == NULL)
520 if (h->h_addrtype == AF_INET)
522 struct sockaddr_in *sin = (sockaddr_in*)q->ai_addr;
523 sin->sin_family = AF_INET;
524 # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
525 sin->sin_len =
sizeof(*sin);
527 sin->sin_port = portnum;
528 memcpy(&sin->sin_addr, *psa, h->h_length);
531 else if (h->h_addrtype == AF_INET6)
533 struct sockaddr_in6 *sin6 = (sockaddr_in6*)q->ai_addr;
534 sin6->sin6_family = AF_INET6;
535 # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
536 sin6->sin6_len =
sizeof(*sin6);
538 sin6->sin6_port = portnum;
539 sin6->sin6_flowinfo = 0;
540 memcpy(&sin6->sin6_addr, *psa, h->h_length);
541 sin6->sin6_scope_id = 0;
545 if (q->ai_canonname != NULL)
546 q->ai_canonname = strdup(q->ai_canonname);
556 static int make_inet(
const char *name,
int portnum,
int protonum,
struct addrinfo *p,
557 const struct addrinfo *hint,
struct addrinfo** result)
569 struct sockaddr_in *sin;
572 struct sockaddr_in6 *sin6;
575 if (hint->ai_family == AF_INET6 || (hint->ai_family == AF_UNSPEC &&
576 strchr(name,
':') != NULL))
579 if (inet_pton(AF_INET6, name, &in6) != 1)
581 if (hint->ai_flags & AI_NUMERICHOST)
589 sin6 = (sockaddr_in6*)malloc(
sizeof(*sin6));
595 memcpy(&sin6->sin6_addr, &in6,
sizeof(in6));
597 if (strchr(name,
'%') != NULL)
600 sin6->sin6_scope_id = strtoul(strchr(name,
'%') + 1, NULL, 10);
602 sin6->sin6_scope_id = 0;
605 q = (addrinfo*)malloc(
sizeof(*q));
613 sin6->sin6_family = AF_INET6;
614 # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN 615 sin6->sin6_len =
sizeof(*sin6);
617 sin6->sin6_port = portnum;
618 sin6->sin6_flowinfo = 0;
621 q->ai_family = AF_INET6;
622 q->ai_socktype = hint->ai_socktype;
623 q->ai_protocol = protonum;
624 q->ai_addrlen =
sizeof(*sin6);
625 q->ai_canonname = NULL;
626 q->ai_addr = (sockaddr*)sin6;
634 if (hint->ai_family == AF_INET || hint->ai_family == AF_UNSPEC)
637 if (inet_pton(AF_INET, name, &in) != 1)
639 if (hint->ai_flags & AI_NUMERICHOST)
647 sin = (sockaddr_in*)malloc(
sizeof(*sin));
654 q = (addrinfo*)malloc(
sizeof(*q));
662 sin->sin_family = AF_INET;
663 # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN 664 sin->sin_len =
sizeof(*sin);
666 sin->sin_port = portnum;
670 q->ai_family = AF_INET;
671 q->ai_socktype = hint->ai_socktype;
672 q->ai_protocol = protonum;
673 q->ai_addrlen =
sizeof(*sin);
674 q->ai_canonname = NULL;
675 q->ai_addr = (sockaddr*)sin;
683 kdError() <<
"I wasn't supposed to get here!";
690 struct sockaddr_in *sin = (sockaddr_in*)malloc(
sizeof(*sin));
692 struct sockaddr_in6 *sin6;
695 if (hint->ai_family == AF_INET || hint->ai_family == AF_UNSPEC)
705 q = (addrinfo*)malloc(
sizeof(*q));
713 sin->sin_family = AF_INET;
714 # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN 715 sin->sin_len =
sizeof(*sin);
717 sin->sin_port = portnum;
718 if (hint->ai_flags & AI_PASSIVE)
719 *(TQ_UINT32*)&sin->sin_addr = INADDR_ANY;
721 *(TQ_UINT32*)&sin->sin_addr = htonl(INADDR_LOOPBACK);
723 q->ai_family = AF_INET;
724 q->ai_socktype = hint->ai_socktype;
725 q->ai_protocol = protonum;
726 q->ai_addrlen =
sizeof(*sin);
727 q->ai_canonname = NULL;
728 q->ai_addr = (sockaddr*)sin;
736 if (hint->ai_family == AF_INET6 || hint->ai_family == AF_UNSPEC)
738 sin6 = (sockaddr_in6*)malloc(
sizeof(*sin6));
739 q = (addrinfo*)malloc(
sizeof(*q));
740 if (q == NULL || sin6 == NULL)
748 sin6->sin6_family = AF_INET6;
749 # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN 750 sin6->sin6_len =
sizeof(*sin6);
752 sin6->sin6_port = portnum;
753 sin6->sin6_flowinfo = 0;
754 sin6->sin6_scope_id = 0;
757 memset(&sin6->sin6_addr, 0,
sizeof(sin6->sin6_addr));
758 if ((hint->ai_flags & AI_PASSIVE) == 0)
759 ((
char*)&sin6->sin6_addr)[15] = 1;
762 q->ai_family = AF_INET6;
763 q->ai_socktype = hint->ai_socktype;
764 q->ai_protocol = protonum;
765 q->ai_addrlen =
sizeof(*sin6);
766 q->ai_canonname = NULL;
767 q->ai_addr = (sockaddr*)sin6;
778 return inet_lookup(name, portnum, protonum, p, hint, result);
782 int getaddrinfo(
const char *name,
const char *serv,
783 const struct addrinfo* hint,
784 struct addrinfo** result)
786 unsigned short portnum;
787 int protonum = IPPROTO_TCP;
788 const char *proto =
"tcp";
789 struct addrinfo *p = NULL;
792 if (hint == NULL || result == NULL)
794 if (hint->ai_family != AF_UNSPEC && hint->ai_family != AF_UNIX &&
795 hint->ai_family != AF_INET
797 && hint->ai_family != AF_INET6
801 if (hint->ai_socktype != 0 && hint->ai_socktype != SOCK_STREAM &&
802 hint->ai_socktype != SOCK_DGRAM)
806 if (name != NULL && ((*name ==
'*' && name[1] ==
'\0') || *name ==
'\0'))
809 if (serv != NULL && ((*serv ==
'*' && serv[1] ==
'\0') || *serv ==
'\0'))
812 if (name == NULL && serv == NULL)
816 if (name != NULL && strcmp(name,
"localhost") == 0)
822 if (hint->ai_family == AF_UNIX || hint->ai_family == AF_UNSPEC)
824 if (name != NULL && serv != NULL)
827 if (hint->ai_family == AF_UNIX)
832 p = make_unix(name, serv);
836 p->ai_socktype = hint->ai_socktype;
839 if (hint->ai_family == AF_UNIX || ((name != NULL && *name ==
'/') ||
840 (serv != NULL && *serv ==
'/')))
852 struct servent *sent;
854 portnum = htons((
unsigned)strtoul(serv, &tail, 10));
858 if (hint->ai_socktype == SOCK_DGRAM)
861 protonum = IPPROTO_UDP;
864 sent = getservbyname(serv, proto);
873 portnum = sent->s_port;
879 return make_inet(name, portnum, protonum, p, hint, result);
882 void freeaddrinfo(
struct addrinfo *p)
887 char *gai_strerror(
int errorcode)
889 static const char *
const messages[] =
892 I18N_NOOP(
"address family for nodename not supported"),
893 I18N_NOOP(
"temporary failure in name resolution"),
894 I18N_NOOP(
"invalid value for 'ai_flags'"),
895 I18N_NOOP(
"non-recoverable failure in name resolution"),
898 I18N_NOOP(
"no address associated with nodename"),
900 I18N_NOOP(
"servname not supported for ai_socktype"),
901 I18N_NOOP(
"'ai_socktype' not supported"),
905 if (errorcode > EAI_SYSTEM || errorcode < 0)
908 static char buffer[200];
909 strcpy(buffer,
i18n(messages[errorcode]).local8Bit());
913 static void findport(
unsigned short port,
char *serv,
size_t servlen,
int flags)
918 if ((flags & NI_NUMERICSERV) == 0)
920 struct servent *sent;
921 sent = getservbyport(ntohs(port), flags & NI_DGRAM ?
"udp" :
"tcp");
922 if (sent != NULL && servlen > strlen(sent->s_name))
924 strcpy(serv, sent->s_name);
929 snprintf(serv, servlen,
"%u", ntohs(port));
932 int getnameinfo(
const struct sockaddr *sa, ksocklen_t salen,
933 char *host,
size_t hostlen,
char *serv,
size_t servlen,
939 const sockaddr_un *_sun;
940 const sockaddr_in *sin;
941 const sockaddr_in6 *sin6;
944 if ((host == NULL || hostlen == 0) && (serv == NULL || servlen == 0))
948 if (s.sa->sa_family == AF_UNIX)
950 if (salen < offsetof(
struct sockaddr_un, sun_path) + strlen(s._sun->sun_path) + 1)
953 if (servlen && serv != NULL)
955 if (host != NULL && hostlen > strlen(s._sun->sun_path))
956 strcpy(host, s._sun->sun_path);
960 else if (s.sa->sa_family == AF_INET)
962 if (salen < offsetof(
struct sockaddr_in, sin_addr) +
sizeof(s.sin->sin_addr))
965 if (flags & NI_NUMERICHOST)
966 inet_ntop(AF_INET, &s.sin->sin_addr, host, hostlen);
970 struct hostent *h = gethostbyaddr((
const char*)&s.sin->sin_addr,
sizeof(s.sin->sin_addr),
972 if (h == NULL && flags & NI_NAMEREQD)
975 inet_ntop(AF_INET, &s.sin->sin_addr, host, hostlen);
976 else if (host != NULL && hostlen > strlen(h->h_name))
977 strcpy(host, h->h_name);
982 findport(s.sin->sin_port, serv, servlen, flags);
985 else if (s.sa->sa_family == AF_INET6)
987 if (salen < offsetof(
struct sockaddr_in6, sin6_addr) +
sizeof(s.sin6->sin6_addr))
990 if (flags & NI_NUMERICHOST)
991 inet_ntop(AF_INET6, &s.sin6->sin6_addr, host, hostlen);
995 struct hostent *h = gethostbyaddr((
const char*)&s.sin->sin_addr,
sizeof(s.sin->sin_addr),
997 if (h == NULL && flags & NI_NAMEREQD)
1000 inet_ntop(AF_INET6, &s.sin6->sin6_addr, host, hostlen);
1001 else if (host != NULL && hostlen > strlen(h->h_name))
1002 strcpy(host, h->h_name);
1007 findport(s.sin6->sin6_port, serv, servlen, flags);
1014 #endif // HAVE_GETADDRINFO 1016 #ifndef HAVE_INET_NTOP 1018 #define KRF_inet_ntop KRF_USING_OWN_INET_NTOP 1020 static void add_dwords(
char *buf, TQ_UINT16 *dw,
int count)
1023 sprintf(buf + strlen(buf),
"%x", ntohs(dw[0]));
1025 sprintf(buf + strlen(buf),
":%x", ntohs(dw[i++]));
1028 const char* inet_ntop(
int af,
const void *cp,
char *buf,
size_t len)
1030 char buf2[
sizeof "1234:5678:9abc:def0:1234:5678:255.255.255.255" + 1];
1031 TQ_UINT8 *data = (TQ_UINT8*)cp;
1035 sprintf(buf2,
"%u.%u.%u.%u", data[0], data[1], data[2], data[3]);
1037 if (len > strlen(buf2))
1050 TQ_UINT16 *p = (TQ_UINT16*)data;
1051 TQ_UINT16 *longest = NULL, *cur = NULL;
1052 int longest_length = 0, cur_length;
1055 if (KDE_IN6_IS_ADDR_V4MAPPED(p) || KDE_IN6_IS_ADDR_V4COMPAT(p))
1056 sprintf(buf2,
"::%s%u.%u.%u.%u",
1057 KDE_IN6_IS_ADDR_V4MAPPED(p) ?
"ffff:" :
"",
1058 buf[12], buf[13], buf[14], buf[15]);
1062 for (i = 0; i < 8; i++)
1063 if (cur == NULL && p[i] == 0)
1069 else if (cur != NULL && p[i] == 0)
1072 else if (cur != NULL && p[i] != 0)
1075 if (cur_length > longest_length)
1077 longest_length = cur_length;
1082 if (cur != NULL && cur_length > longest_length)
1084 longest_length = cur_length;
1088 if (longest_length > 1)
1093 add_dwords(buf2, p, longest - p);
1095 if (longest + longest_length < p + 8)
1096 add_dwords(buf2, longest + longest_length, 8 - (longest - p) - longest_length);
1102 add_dwords(buf2, p, 8);
1106 if (strlen(buf2) < len)
1117 errno = EAFNOSUPPORT;
1121 #else // HAVE_INET_NTOP 1123 #define KRF_inet_ntop 0 1125 #endif // HAVE_INET_NTOP 1127 #ifndef HAVE_INET_PTON 1129 #define KRF_inet_pton KRF_USING_OWN_INET_PTON 1130 int inet_pton(
int af,
const char *cp,
void *buf)
1136 unsigned char *q = (
unsigned char*)buf;
1137 if (sscanf(cp,
"%u.%u.%u.%u", p, p + 1, p + 2, p + 3) != 4)
1140 if (p[0] > 0xff || p[1] > 0xff || p[2] > 0xff || p[3] > 0xff)
1152 else if (af == AF_INET6)
1156 int n = 0, start = 8;
1157 bool has_v4 = strchr(p,
'.') != NULL;
1159 memset(addr, 0,
sizeof(addr));
1161 if (*p ==
'\0' || p[1] ==
'\0')
1164 if (*p ==
':' && p[1] ==
':')
1171 if (has_v4 && inet_pton(AF_INET, p, addr + n) != 0)
1174 addr[n] = ntohs(addr[n]);
1176 addr[n] = ntohs(addr[n]);
1180 if (sscanf(p,
"%hx", addr + n++) != 1)
1183 while (*p && *p !=
':')
1202 if (start == 8 && n != 8)
1204 memmove(addr + start + (8 - n), addr + start, (n - start) *
sizeof(TQ_UINT16));
1205 memset(addr + start, 0, (8 - n) *
sizeof(TQ_UINT16));
1209 if (htons(0x1234) != 0x1234)
1210 for (n = 0; n < 8; n++)
1211 addr[n] = htons(addr[n]);
1213 memcpy(buf, addr,
sizeof(addr));
1218 errno = EAFNOSUPPORT;
1222 #else // HAVE_INET_PTON 1224 #define KRF_inet_pton 0 1226 #endif // HAVE_INET_PTON 1229 # define KRF_afinet6 KRF_KNOWS_AF_INET6 1231 # define KRF_afinet6 0 1237 extern const int KDE_EXPORT resolverFlags = KRF_getaddrinfo | KRF_resolver | KRF_afinet6 | KRF_inet_ntop | KRF_inet_pton;
kdbgstream kdError(int area=0)
TQString i18n(const char *text)
Namespace for general KDE functions.