summaryrefslogtreecommitdiffstats
path: root/lib/getaddrinfo.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/getaddrinfo.c')
-rw-r--r--lib/getaddrinfo.c121
1 files changed, 121 insertions, 0 deletions
diff --git a/lib/getaddrinfo.c b/lib/getaddrinfo.c
new file mode 100644
index 0000000..ef7c9ae
--- /dev/null
+++ b/lib/getaddrinfo.c
@@ -0,0 +1,121 @@
+/*
+ * getaddrinfo.c
+ *
+ * Simple version of getaddrinfo()
+ *
+ */
+
+#include "config.h"
+
+extern int errno;
+extern int h_errno;
+
+void freeaddrinfo(struct addrinfo *res)
+{
+ if (!res)
+ return;
+ if (res->ai_next)
+ freeaddrinfo(res->ai_next);
+ if (res->ai_addr)
+ free(res->ai_addr);
+ if (res->ai_canonname)
+ free(res->ai_canonname);
+ free(res);
+}
+
+int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints,
+ struct addrinfo **res)
+{
+ struct hostent *host;
+ struct sockaddr *sa;
+ int err, size = 0;
+
+ if ((!node) || (!res)) {
+ errno = EINVAL;
+ return EAI_SYSTEM;
+ }
+ *res = NULL;
+ /* we do not support service in this version */
+ if (service) {
+ errno = EINVAL;
+ return EAI_SYSTEM;
+ }
+ host = gethostbyname(node);
+ if (!host)
+ return EAI_NONAME;
+ if (hints) {
+ if (hints->ai_family != AF_UNSPEC) {
+ if (hints->ai_family != host->h_addrtype)
+ return EAI_ADDRFAMILY;
+ }
+ }
+ *res = malloc(sizeof(struct addrinfo));
+ if (!*res) {
+ return EAI_MEMORY;
+ }
+ memset(*res, 0, sizeof(struct addrinfo));
+ (*res)->ai_family = host->h_addrtype;
+ if (host->h_length) {
+ if (host->h_addrtype == AF_INET)
+ size = sizeof(struct sockaddr_in);
+#ifdef HAVE_IPV6
+ else if (host->h_addrtype == AF_INET6)
+ size = sizeof(struct sockaddr_in6);
+#endif
+ else {
+ free(*res);
+ *res = NULL;
+ return EAI_ADDRFAMILY;
+ }
+ sa = malloc(size);
+ if (!sa) {
+ free(*res);
+ *res = NULL;
+ return EAI_MEMORY;
+ }
+ memset(sa, 0, size);
+ (*res)->ai_addr = sa;
+ (*res)->ai_addrlen = size;
+ sa->sa_family = host->h_addrtype;
+ if (host->h_addrtype == AF_INET)
+ memcpy(&((struct sockaddr_in *)sa)->sin_addr, host->h_addr, host->h_length);
+#ifdef HAVE_IPV6
+ else
+ memcpy(&((struct sockaddr_in6 *)sa)->sin6_addr, host->h_addr, host->h_length);
+#endif
+ }
+ if (host->h_name)
+ (*res)->ai_canonname = strdup(host->h_name);
+
+ /* we only handle the first address entry and do not build a list now */
+ return 0;
+}
+
+
+
+const char *gai_strerror(int errcode)
+{
+ const char *s = NULL;
+
+ switch(errcode) {
+ case 0:
+ s = "no error";
+ break;
+ case EAI_MEMORY:
+ s = "no memory";
+ break;
+ case EAI_SYSTEM:
+ s = strerror(errno);
+ break;
+ case EAI_NONAME:
+ s = hstrerror(h_errno);
+ break;
+ case EAI_ADDRFAMILY:
+ s = "address does not match address family";
+ break;
+ default:
+ s = "unknown error code";
+ break;
+ }
+ return s;
+}