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>
21 } caLocalServices[] = {
22 {"telnet", SOCK_STREAM, 0, 23},
23 {"http", SOCK_STREAM, 0, 80},
25 static const int ciNumLocalServices = sizeof(caLocalServices)/sizeof(caLocalServices[0]);
28 int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res)
30 static const struct addrinfo defhints = {
31 .ai_family = AF_UNSPEC,
32 .ai_flags = AI_V4MAPPED | AI_ADDRCONFIG
34 struct addrinfo *ret = NULL;
36 _SysDebug("getaddrinfo('%s','%s',%p,%p)", node, service, hints, res);
39 if( !node && !service ) return EAI_NONAME;
46 if( !(hints->ai_flags & AI_PASSIVE) )
53 // 1. Check if the node is an IP address
57 type = Net_ParseAddress(node, addrdata);
63 ret = malloc(sizeof(struct addrinfo) + sizeof(struct sockaddr_in));
64 ret->ai_family = AF_INET;
67 ret->ai_addrlen = sizeof(struct in_addr);
68 ret->ai_addr = (void*)( ret + 1 );
69 ret->ai_canonname = 0;
71 ((struct sockaddr_in*)ret->ai_addr)->sin_family = AF_INET;
72 ((struct sockaddr_in*)ret->ai_addr)->sin_port = 0;
73 memcpy( &((struct sockaddr_in*)ret->ai_addr)->sin_addr, addrdata, 4 );
76 _SysDebug("getaddrinfo: Unknown address family %i", type);
81 // 2. Check for a DNS name
82 // - No luck with above, and hints->ai_flags doesn't have AI_NUMERICHOST set
83 if( !ret && !(hints->ai_flags & AI_NUMERICHOST) )
85 _SysDebug("getaddrinfo: TODO DNS Lookups");
87 // ? /Acess/Conf/Nameservers
88 // ? /Acess/Conf/Hosts
91 // 3. No Match, chuck sad
98 int default_socktype = hints->ai_socktype;
99 int default_protocol = hints->ai_protocol;
100 int default_port = 0;
103 if( default_protocol == 0 )
105 switch(default_socktype)
113 // Convert `node` into types
118 default_port = strtol(service, &end, 0);
119 if( *end != '\0' && (hints->ai_flags & AI_NUMERICSERV) )
126 // TODO: Read something like /Acess/Conf/services
127 for( int i = 0; i < ciNumLocalServices; i ++ )
129 if( strcmp(service, caLocalServices[i].Name) == 0 ) {
130 end = service + strlen(service);
131 default_socktype = caLocalServices[i].SockType;
132 default_protocol = caLocalServices[i].Protocol;
133 default_port = caLocalServices[i].Port;
141 _SysDebug("getaddrinfo: TODO Service translation");
146 for( ai = ret; ai; ai = ai->ai_next)
148 struct sockaddr_in *in = (void*)ai->ai_addr;
149 struct sockaddr_in6 *in6 = (void*)ai->ai_addr;
151 // Check ai_socktype/ai_protocol
152 // TODO: Do both of these need to be zero for defaults to apply?
153 if( ai->ai_socktype == 0 )
154 ai->ai_socktype = default_socktype;
155 if( ai->ai_protocol == 0 )
156 ai->ai_protocol = default_protocol;
158 switch(ai->ai_family)
161 if( in->sin_port == 0 )
162 in->sin_port = default_port;
163 _SysDebug("%p: IPv4 [%s]:%i %i,%i",
164 ai, Net_PrintAddress(4, &in->sin_addr),
165 in->sin_port, ai->ai_socktype, ai->ai_protocol);
168 if( in6->sin6_port == 0 )
169 in6->sin6_port = default_port;
170 _SysDebug("%p: IPv6 [%s]:%i %i,%i",
171 ai, Net_PrintAddress(6, &in6->sin6_addr),
172 in6->sin6_port, ai->ai_socktype, ai->ai_protocol);
175 _SysDebug("getaddrinfo: Unknown address family %i (setting port)", ai->ai_family);
184 void freeaddrinfo(struct addrinfo *res)
189 int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags)
191 // Determine hostname
197 if( !(flags & NI_NUMERICHOST) )
201 // Numeric hostname or the hostname was unresolvable
202 if( host[0] == '\0' )
204 if( (flags & NI_NAMEREQD) )
209 // Determine service name
215 if( !(flags & NI_NUMERICSERV) )
219 if( serv[0] == '\0' )
228 const char *gai_strerror(int errnum)
232 case EAI_SUCCESS: return "No error";
233 case EAI_FAIL: return "Permanent resolution failure";
234 default: return "UNKNOWN";