2 * Acess2 POSIX Sockets Library
3 * - By John Hodge (thePowersGang)
6 * - getaddrinfo/freeaddrinfo/getnameinfo/gai_strerror
9 #include <netinet/in.h>
10 #include <net.h> // Net_ParseAddress
11 #include <stdlib.h> // malloc
12 #include <string.h> // memcpy
13 #include <stdlib.h> // strtol
14 #include <acess/sys.h>
17 int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res)
19 static const struct addrinfo defhints = {
20 .ai_family = AF_UNSPEC,
21 .ai_flags = AI_V4MAPPED | AI_ADDRCONFIG
23 struct addrinfo *ret = NULL;
25 _SysDebug("getaddrinfo('%s','%s',%p,%p)", node, service, hints, res);
28 if( !node && !service ) return EAI_NONAME;
35 if( !(hints->ai_flags & AI_PASSIVE) )
42 // 1. Check if the node is an IP address
43 // TODO: Break this function out into inet_pton?
47 type = Net_ParseAddress(node, addrdata);
53 ret = malloc(sizeof(struct addrinfo) + sizeof(struct sockaddr_in));
54 ret->ai_family = AF_INET;
57 ret->ai_addrlen = sizeof(struct in_addr);
58 ret->ai_addr = (void*)( ret + 1 );
59 ret->ai_canonname = 0;
61 ((struct sockaddr_in*)ret->ai_addr)->sin_family = AF_INET;
62 ((struct sockaddr_in*)ret->ai_addr)->sin_port = 0;
63 memcpy( &((struct sockaddr_in*)ret->ai_addr)->sin_addr, addrdata, 4 );
66 _SysDebug("getaddrinfo: Unknown address family %i", type);
71 // 2. Check for a DNS name
72 // - No luck with above, and hints->ai_flags doesn't have AI_NUMERICHOST set
73 if( !ret && !(hints->ai_flags & AI_NUMERICHOST) )
75 _SysDebug("getaddrinfo: TODO DNS Lookups");
77 // ? /Acess/Conf/Nameservers
78 // ? /Acess/Conf/Hosts
81 // 3. No Match, chuck sad
88 int default_socktype = hints->ai_socktype;
89 int default_protocol = hints->ai_protocol;
93 if( default_protocol == 0 )
95 switch(default_socktype)
103 // Convert `node` into types
108 default_port = strtol(service, &end, 0);
109 if( *end != '\0' && !(hints->ai_flags & AI_NUMERICSERV) )
111 // TODO: Read something like /Acess/Conf/services
112 _SysDebug("getaddrinfo: TODO Service translation");
122 for( ai = ret; ai; ai = ai->ai_next)
124 struct sockaddr_in *in = (void*)ai->ai_addr;
125 struct sockaddr_in6 *in6 = (void*)ai->ai_addr;
127 // Check ai_socktype/ai_protocol
128 // TODO: Do both of these need to be zero for defaults to apply?
129 if( ai->ai_socktype == 0 )
130 ai->ai_socktype = default_socktype;
131 if( ai->ai_protocol == 0 )
132 ai->ai_protocol = default_protocol;
134 switch(ai->ai_family)
137 if( in->sin_port == 0 )
138 in->sin_port = default_port;
139 _SysDebug("%p: IPv4 [%s]:%i %i,%i",
140 ai, Net_PrintAddress(4, &in->sin_addr),
141 in->sin_port, ai->ai_socktype, ai->ai_protocol);
144 if( in6->sin6_port == 0 )
145 in6->sin6_port = default_port;
146 _SysDebug("%p: IPv6 [%s]:%i %i,%i",
147 ai, Net_PrintAddress(6, &in6->sin6_addr),
148 in6->sin6_port, ai->ai_socktype, ai->ai_protocol);
151 _SysDebug("getaddrinfo: Unknown address family %i (setting port)", ai->ai_family);
160 void freeaddrinfo(struct addrinfo *res)
165 int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags)
167 // Determine hostname
173 if( !(flags & NI_NUMERICHOST) )
177 // Numeric hostname or the hostname was unresolvable
178 if( host[0] == '\0' )
180 if( (flags & NI_NAMEREQD) )
185 // Determine service name
191 if( !(flags & NI_NUMERICSERV) )
195 if( serv[0] == '\0' )
204 const char *gai_strerror(int errnum)
208 case EAI_SUCCESS: return "No error";
209 case EAI_FAIL: return "Permanent resolution failure";
210 default: return "UNKNOWN";