remap: *actually* build, and fix masked logic errors
[tftp-hpa.git] / lib / getaddrinfo.c
blobef7c9ae114019203a6ba4004edb5d1ffebf1e81e
1 /*
2 * getaddrinfo.c
4 * Simple version of getaddrinfo()
6 */
8 #include "config.h"
10 extern int errno;
11 extern int h_errno;
13 void freeaddrinfo(struct addrinfo *res)
15 if (!res)
16 return;
17 if (res->ai_next)
18 freeaddrinfo(res->ai_next);
19 if (res->ai_addr)
20 free(res->ai_addr);
21 if (res->ai_canonname)
22 free(res->ai_canonname);
23 free(res);
26 int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints,
27 struct addrinfo **res)
29 struct hostent *host;
30 struct sockaddr *sa;
31 int err, size = 0;
33 if ((!node) || (!res)) {
34 errno = EINVAL;
35 return EAI_SYSTEM;
37 *res = NULL;
38 /* we do not support service in this version */
39 if (service) {
40 errno = EINVAL;
41 return EAI_SYSTEM;
43 host = gethostbyname(node);
44 if (!host)
45 return EAI_NONAME;
46 if (hints) {
47 if (hints->ai_family != AF_UNSPEC) {
48 if (hints->ai_family != host->h_addrtype)
49 return EAI_ADDRFAMILY;
52 *res = malloc(sizeof(struct addrinfo));
53 if (!*res) {
54 return EAI_MEMORY;
56 memset(*res, 0, sizeof(struct addrinfo));
57 (*res)->ai_family = host->h_addrtype;
58 if (host->h_length) {
59 if (host->h_addrtype == AF_INET)
60 size = sizeof(struct sockaddr_in);
61 #ifdef HAVE_IPV6
62 else if (host->h_addrtype == AF_INET6)
63 size = sizeof(struct sockaddr_in6);
64 #endif
65 else {
66 free(*res);
67 *res = NULL;
68 return EAI_ADDRFAMILY;
70 sa = malloc(size);
71 if (!sa) {
72 free(*res);
73 *res = NULL;
74 return EAI_MEMORY;
76 memset(sa, 0, size);
77 (*res)->ai_addr = sa;
78 (*res)->ai_addrlen = size;
79 sa->sa_family = host->h_addrtype;
80 if (host->h_addrtype == AF_INET)
81 memcpy(&((struct sockaddr_in *)sa)->sin_addr, host->h_addr, host->h_length);
82 #ifdef HAVE_IPV6
83 else
84 memcpy(&((struct sockaddr_in6 *)sa)->sin6_addr, host->h_addr, host->h_length);
85 #endif
87 if (host->h_name)
88 (*res)->ai_canonname = strdup(host->h_name);
90 /* we only handle the first address entry and do not build a list now */
91 return 0;
96 const char *gai_strerror(int errcode)
98 const char *s = NULL;
100 switch(errcode) {
101 case 0:
102 s = "no error";
103 break;
104 case EAI_MEMORY:
105 s = "no memory";
106 break;
107 case EAI_SYSTEM:
108 s = strerror(errno);
109 break;
110 case EAI_NONAME:
111 s = hstrerror(h_errno);
112 break;
113 case EAI_ADDRFAMILY:
114 s = "address does not match address family";
115 break;
116 default:
117 s = "unknown error code";
118 break;
120 return s;