1 #ifndef HAVE_SOCKETS
2 #error getaddrinfo.c included by mistake! no socket support!
3 #else
4 #include <sys/types.h>
5 #include <sys/socket.h>
6 #ifdef HAVE_NETDB_H
7 #include <netdb.h>
8 #endif
9 #ifdef HAVE_NETINET_IN_H
10 #include <netinet/in.h>
11 #endif
12 #ifdef HAVE_ARPA_INET_H
13 #include <arpa/inet.h>
14 #endif
15 #include <errno.h>
16 #include <string.h> /* strerror */
17
18 #include "getaddrinfo.h"
19
20 void
21 freeaddrinfo(struct addrinfo *res)
22 {
23 if (res->ai_addr != NULL)
24 free(res->ai_addr);
25 free(res);
26 }
27
28 int
29 getaddrinfo(const char *hostname, const char *portname,
30 struct addrinfo *hints, struct addrinfo **res)
31 {
32 struct addrinfo *out;
33 if (res == NULL)
34 return EINVAL;
35
36 out = (struct addrinfo *) calloc(1, sizeof(*out));
37 if (out == NULL) {
38 *res = NULL;
39 return ENOMEM;
40 }
41
42 out->ai_addr = (struct sockaddr *) malloc(sizeof(struct sockaddr_in));
43 if (out->ai_addr == NULL) {
44 free(out);
45 *res = NULL;
46 return ENOMEM;
47 }
48
49 out->ai_socktype = SOCK_STREAM;
50 if (hints != NULL) {
51 if (hints->ai_socktype)
52 out->ai_socktype = hints->ai_socktype;
53 if (hints->ai_protocol)
54 out->ai_protocol = hints->ai_protocol;
55 }
56
57 if (out->ai_protocol == 0) {
58 switch (out->ai_socktype) {
59 case SOCK_STREAM:
60 out->ai_protocol = IPPROTO_TCP;
61 break;
62 case SOCK_DGRAM:
63 out->ai_protocol = IPPROTO_UDP;
64 break;
65 case SOCK_RAW:
66 out->ai_protocol = IPPROTO_RAW;
67 break;
68 }
69 }
70
71 out->ai_addrlen = sizeof(struct sockaddr_in);
72 memset(out->ai_addr, '\0', sizeof(struct sockaddr_in));
73
74 if (hostname != NULL) {
75 struct hostent *he;
76 he = gethostbyname(hostname);
77 if (he != NULL && he->h_addr_list != NULL) {
78 ((struct sockaddr_in *)out->ai_addr)->sin_addr.s_addr
79 = ((struct in_addr *)he->h_addr_list[0])->s_addr;
80 } else {
81 freeaddrinfo(out);
82 return EADDRNOTAVAIL;
83 }
84 } else {
85 if (!(out->ai_flags & AI_PASSIVE))
86 ((struct sockaddr_in *)out->ai_addr)->sin_addr.s_addr
87 = htonl(INADDR_ANY);
88 }
89 ((struct sockaddr_in *)out->ai_addr)->sin_family = AF_INET;
90 out->ai_family = AF_INET;
91
92 if (portname != NULL && *portname) {
93 long portnum;
94 char *end;
95 portnum = strtol(portname, &end, 10);
96 if (*end == '\0' && portnum > 0 && portnum < 65536) {
97 ((struct sockaddr_in *)out->ai_addr)->sin_port
98 = htons(portnum);
99 } else {
100 struct servent *se;
101 se = getservbyname(portname, NULL);
102 if (se != NULL) {
103 ((struct sockaddr_in *)out->ai_addr)->sin_port
104 = se->s_port;
105 }
106 }
107 }
108
109 *res = out;
110
111 return 0;
112 }
113
114 const char *
115 gai_strerror(int errcode)
116 {
117 return strerror(errcode);
118 }
119 #endif