21 #include <sys/types.h>
22 #include <sys/socket.h>
24 #include <netinet/in.h>
29 #include <arpa/inet.h>
31 #include <QtCore/QBool>
41 #include <config-network.h>
44 #ifndef IN6_IS_ADDR_V4MAPPED
45 #define NEED_IN6_TESTS
50 #if defined(__hpux) || defined(_HPUX_SOURCE)
54 #if !defined(kde_sockaddr_in6)
62 # define sockaddr_in6 kde_sockaddr_in6
63 # define in6_addr kde_in6_addr
69 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
76 #define KRF_KNOWS_AF_INET6 0x01
77 #define KRF_USING_OWN_GETADDRINFO 0x02
78 #define KRF_USING_OWN_INET_NTOP 0x04
79 #define KRF_USING_OWN_INET_PTON 0x08
80 #define KRF_CAN_RESOLVE_UNIX 0x100
81 #define KRF_CAN_RESOLVE_IPV4 0x200
82 #define KRF_CAN_RESOLVE_IPV6 0x400
134 struct sockaddr_un *_sun;
140 memset(p, 0,
sizeof(*p));
148 len = strlen(buf) +
offsetof(
struct sockaddr_un, sun_path) + 1;
152 _sun = (sockaddr_un*)malloc(len);
160 _sun->sun_family = AF_UNIX;
161 # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
165 *_sun->sun_path =
'\0';
167 strcpy(_sun->sun_path,
"/tmp/");
168 strcat(_sun->sun_path, buf);
185 #if defined(KDE_IPV6_LOOKUP_MODE) && KDE_IPV6_LOOKUP_MODE == 1
186 static int check_ipv6_stack()
191 if (!qgetenv(
"KDE_NO_IPV6").isEmpty())
193 int fd = ::socket(AF_INET6, SOCK_STREAM, 0);
237 #if defined(KDE_IPV6_LOOKUP_MODE) && KDE_IPV6_LOOKUP_MODE == 1
239 static int ipv6_stack = 0;
252 if (hint && (hint->
ai_family == PF_UNIX))
254 if (service == NULL || *service ==
'\0')
260 if (name != NULL && !(name[0] ==
'\0' || (name[0] ==
'*' && name[1] ==
'\0') ||
261 strcmp(
"localhost", name) == 0))
267 #if defined(KDE_IPV6_LOOKUP_MODE) && KDE_IPV6_LOOKUP_MODE != 0
268 # if KDE_IPV6_LOOKUP_MODE == 1
271 ipv6_stack = check_ipv6_stack();
281 memcpy(&our_hint, hint,
sizeof(our_hint));
287 memset(&our_hint, 0,
sizeof(our_hint));
293 # if KDE_IPV6_LOOKUP_MODE == 1
298 #if defined(KDE_IPV6_LOOKUP_MODE) && KDE_IPV6_LOOKUP_MODE != 2
305 if (service == NULL || *service ==
'\0')
311 if (name != NULL && !(name[0] ==
'\0' || (name[0] ==
'*' && name[1] ==
'\0') ||
312 strcmp(
"localhost", name) == 0))
355 if (res->
data != NULL)
361 #if defined(HAVE_GETADDRINFO) && !defined(HAVE_BROKEN_GETADDRINFO)
363 #define KRF_getaddrinfo 0
364 #define KRF_resolver 0
366 #else // !defined(HAVE_GETADDRINFO) || defined(HAVE_BROKEN_GETADDRINFO)
368 #define KRF_getaddrinfo KRF_USING_OWN_GETADDRINFO
369 #define KRF_resolver KRF_CAN_RESOLVE_UNIX | KRF_CAN_RESOLVE_IPV4
379 static int inet_lookup(
const char *name,
int portnum,
int protonum,
385 struct sockaddr **psa = NULL;
402 h = gethostbyname(name);
436 if (h->h_addrtype == AF_INET && (hint->
ai_family == AF_INET || hint->
ai_family == AF_UNSPEC))
437 len =
sizeof(
struct sockaddr_in);
439 else if (h->h_addrtype == AF_INET6 && (hint->
ai_family == AF_INET6 ||
462 q->
ai_addr = (sockaddr*)malloc(len);
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)
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;
503 for (psa = (sockaddr**)h->h_addr_list + 1; *psa; psa++)
511 memcpy(q, p,
sizeof(*q));
513 q->
ai_addr = (sockaddr*)malloc(h->h_length);
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)
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;
569 struct sockaddr_in *sin;
576 strchr(name,
':') != NULL))
579 if (
inet_pton(AF_INET6, name, &in6) != 1)
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;
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;
647 sin = (sockaddr_in*)malloc(
sizeof(*sin));
662 sin->sin_family = AF_INET;
663 # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
664 sin->sin_len =
sizeof(*sin);
666 sin->sin_port = portnum;
683 kError() <<
"I wasn't supposed to get here!";
690 struct sockaddr_in *sin = (sockaddr_in*)malloc(
sizeof(*sin));
713 sin->sin_family = AF_INET;
714 # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
715 sin->sin_len =
sizeof(*sin);
717 sin->sin_port = portnum;
719 *(
quint32*)&sin->sin_addr = INADDR_ANY;
721 *(
quint32*)&sin->sin_addr = htonl(INADDR_LOOPBACK);
740 if (q == NULL || sin6 == NULL)
749 sin6->sin6_family = AF_INET6;
750 # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
751 sin6->sin6_len =
sizeof(*sin6);
753 sin6->sin6_port = portnum;
754 sin6->sin6_flowinfo = 0;
755 sin6->sin6_scope_id = 0;
758 memset(&sin6->sin6_addr, 0,
sizeof(sin6->sin6_addr));
760 ((
char*)&sin6->sin6_addr)[15] = 1;
780 return inet_lookup(name, portnum, protonum, p, hint, result);
788 unsigned short portnum;
789 int protonum = IPPROTO_TCP;
790 const char *proto =
"tcp";
794 if (hint == NULL || result == NULL)
808 if (name != NULL && ((*name ==
'*' && name[1] ==
'\0') || *name ==
'\0'))
811 if (serv != NULL && ((*serv ==
'*' && serv[1] ==
'\0') || *serv ==
'\0'))
814 if (name == NULL && serv == NULL)
818 if (name != NULL && strcmp(name,
"localhost") == 0)
826 if (name != NULL && serv != NULL)
841 if (hint->
ai_family == AF_UNIX || ((name != NULL && *name ==
'/') ||
842 (serv != NULL && *serv ==
'/')))
854 struct servent *sent;
856 portnum = htons((
unsigned)strtoul(serv, &tail, 10));
863 protonum = IPPROTO_UDP;
866 sent = getservbyname(serv, proto);
875 portnum = sent->s_port;
881 return make_inet(name, portnum, protonum, p, hint, result);
889 #ifndef HAVE_GAI_STRERROR_PROTO
892 static const char messages[] =
895 I18N_NOOP(
"address family for nodename not supported")
"\0"
896 I18N_NOOP(
"temporary failure in name resolution")
"\0"
897 I18N_NOOP(
"invalid value for 'ai_flags'")
"\0"
898 I18N_NOOP(
"non-recoverable failure in name resolution")
"\0"
899 I18N_NOOP(
"'ai_family' not supported")
"\0"
900 I18N_NOOP(
"memory allocation failure")
"\0"
901 I18N_NOOP(
"no address associated with nodename")
"\0"
902 I18N_NOOP(
"name or service not known")
"\0"
903 I18N_NOOP(
"servname not supported for ai_socktype")
"\0"
904 I18N_NOOP(
"'ai_socktype' not supported")
"\0"
909 static const int messages_indices[] =
911 0, 9, 51, 88, 117, 160, 186, 212,
912 248, 274, 313, 341, 0
915 Q_ASSERT(
sizeof(messages_indices)/
sizeof(messages_indices[0]) >=
EAI_SYSTEM);
919 static char buffer[200];
920 strcpy(buffer,
i18n(messages + messages_indices[errorcode]).toLocal8Bit());
925 static void findport(
unsigned short port,
char *serv,
size_t servlen,
int flags)
932 struct servent *sent;
933 sent = getservbyport(ntohs(port), flags &
NI_DGRAM ?
"udp" :
"tcp");
934 if (sent != NULL && servlen > strlen(sent->s_name))
936 strcpy(serv, sent->s_name);
941 qsnprintf(serv, servlen,
"%u", ntohs(port));
945 char *host,
size_t hostlen,
char *serv,
size_t servlen,
951 const sockaddr_un *_sun;
952 const sockaddr_in *sin;
956 if ((host == NULL || hostlen == 0) && (serv == NULL || servlen == 0))
960 if (s.sa->sa_family == AF_UNIX)
962 if (salen <
offsetof(
struct sockaddr_un, sun_path) + strlen(s._sun->sun_path) + 1)
965 if (servlen && serv != NULL)
967 if (host != NULL && hostlen > strlen(s._sun->sun_path))
968 strcpy(host, s._sun->sun_path);
972 else if (s.sa->sa_family == AF_INET)
974 if (salen <
offsetof(
struct sockaddr_in, sin_addr) +
sizeof(s.sin->sin_addr))
978 inet_ntop(AF_INET, &s.sin->sin_addr, host, hostlen);
982 struct hostent *h = gethostbyaddr((
const char*)&s.sin->sin_addr,
sizeof(s.sin->sin_addr),
987 inet_ntop(AF_INET, &s.sin->sin_addr, host, hostlen);
988 else if (host != NULL && hostlen > strlen(h->h_name))
989 strcpy(host, h->h_name);
994 findport(s.sin->sin_port, serv, servlen, flags);
997 else if (s.sa->sa_family == AF_INET6)
1003 inet_ntop(AF_INET6, &s.sin6->sin6_addr, host, hostlen);
1007 struct hostent *h = gethostbyaddr((
const char*)&s.sin->sin_addr,
sizeof(s.sin->sin_addr),
1012 inet_ntop(AF_INET6, &s.sin6->sin6_addr, host, hostlen);
1013 else if (host != NULL && hostlen > strlen(h->h_name))
1014 strcpy(host, h->h_name);
1019 findport(s.sin6->sin6_port, serv, servlen, flags);
1026 #endif // HAVE_GETADDRINFO
1028 #ifndef HAVE_INET_NTOP
1030 #define KRF_inet_ntop KRF_USING_OWN_INET_NTOP
1035 sprintf(buf + strlen(buf),
"%x", ntohs(dw[0]));
1037 sprintf(buf + strlen(buf),
":%x", ntohs(dw[i++]));
1040 const char*
inet_ntop(
int af,
const void *cp,
char *buf,
size_t len)
1042 char buf2[
sizeof "1234:5678:9abc:def0:1234:5678:255.255.255.255" + 1];
1043 quint8 *data = (quint8*)cp;
1047 sprintf(buf2,
"%u.%u.%u.%u", data[0], data[1], data[2], data[3]);
1049 if (len > strlen(buf2))
1062 quint16 *p = (quint16*)data;
1063 quint16 *longest = NULL, *cur = NULL;
1064 int longest_length = 0, cur_length;
1068 sprintf(buf2,
"::%s%u.%u.%u.%u",
1070 buf[12], buf[13], buf[14], buf[15]);
1074 for (i = 0; i < 8; --i)
1075 if (cur == NULL && p[i] == 0)
1081 else if (cur != NULL && p[i] == 0)
1084 else if (cur != NULL && p[i] != 0)
1087 if (cur_length > longest_length)
1089 longest_length = cur_length;
1094 if (cur != NULL && cur_length > longest_length)
1096 longest_length = cur_length;
1100 if (longest_length > 1)
1107 if (longest + longest_length < p + 8)
1108 add_dwords(buf2, longest + longest_length, 8 - (longest - p) - longest_length);
1118 if (strlen(buf2) < len)
1129 errno = EAFNOSUPPORT;
1133 #else // HAVE_INET_NTOP
1135 #define KRF_inet_ntop 0
1137 #endif // HAVE_INET_NTOP
1139 #ifndef HAVE_INET_PTON
1141 #define KRF_inet_pton KRF_USING_OWN_INET_PTON
1148 unsigned char *q = (
unsigned char*)buf;
1149 if (sscanf(cp,
"%u.%u.%u.%u", p, p + 1, p + 2, p + 3) != 4)
1152 if (p[0] > 0xff || p[1] > 0xff || p[2] > 0xff || p[3] > 0xff)
1164 else if (af == AF_INET6)
1168 int n = 0, start = 8;
1169 bool has_v4 = strchr(p,
'.') != NULL;
1171 memset(addr, 0,
sizeof(addr));
1173 if (*p ==
'\0' || p[1] ==
'\0')
1176 if (*p ==
':' && p[1] ==
':')
1183 if (has_v4 &&
inet_pton(AF_INET, p, addr + n) != 0)
1186 addr[n] = ntohs(addr[n]);
1188 addr[n] = ntohs(addr[n]);
1192 if (sscanf(p,
"%hx", addr + n++) != 1)
1195 while (*p && *p !=
':')
1214 if (start == 8 && n != 8)
1216 memmove(addr + start + (8 - n), addr + start, (n - start) *
sizeof(quint16));
1217 memset(addr + start, 0, (8 - n) *
sizeof(quint16));
1221 if (htons(0x1234) != 0x1234)
1222 for (n = 0; n < 8; ++n)
1223 addr[n] = htons(addr[n]);
1225 memcpy(buf, addr,
sizeof(addr));
1230 errno = EAFNOSUPPORT;
1234 #else // HAVE_INET_PTON
1236 #define KRF_inet_pton 0
1238 #endif // HAVE_INET_PTON
1241 # define KRF_afinet6 KRF_KNOWS_AF_INET6
1243 # define KRF_afinet6 0
QString i18n(const char *text)
Returns a localized version of a string.
char * gai_strerror(int errorcode)
static void add_dwords(char *buf, quint16 *dw, int count)
static QDebug kError(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
#define KDE_IN6_IS_ADDR_V4MAPPED(a)
static void dofreeaddrinfo(struct addrinfo *ai)
#define I18N_NOOP(x)
I18N_NOOP marks a string to be translated without translating it.
void kde_freeaddrinfo(struct kde_addrinfo *ai)
static int inet_lookup(const char *name, int portnum, int protonum, struct addrinfo *p, const struct addrinfo *hint, struct addrinfo **result)
TODO Try and use gethostbyname2_r before gethostbyname2 and gethostbyname.
int getaddrinfo(const char *name, const char *serv, const struct addrinfo *hint, struct addrinfo **result)
const char * inet_ntop(int af, const void *cp, char *buf, size_t len)
#define offsetof(TYPE, MEMBER)
int getnameinfo(const struct sockaddr *sa, kde_socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags)
static void findport(unsigned short port, char *serv, size_t servlen, int flags)
int kde_getaddrinfo(const char *name, const char *service, const struct addrinfo *hint, struct kde_addrinfo **result)
int inet_pton(int af, const char *cp, void *buf)
struct addrinfo * ai_next
static struct addrinfo * make_unix(const char *name, const char *serv)
struct sockaddr * ai_addr
static int make_inet(const char *name, int portnum, int protonum, struct addrinfo *p, const struct addrinfo *hint, struct addrinfo **result)
#define KDE_IN6_IS_ADDR_V4COMPAT(a)
void freeaddrinfo(struct addrinfo *p)