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
89 //count = Net_LookupDNS(node, service, NULL);
93 // 3. No Match, chuck sad
100 int default_socktype = hints->ai_socktype;
101 int default_protocol = hints->ai_protocol;
102 int default_port = 0;
105 if( default_protocol == 0 )
107 switch(default_socktype)
115 // Convert `node` into types
120 default_port = strtol(service, (char**)&end, 0);
121 if( *end != '\0' && (hints->ai_flags & AI_NUMERICSERV) )
128 // TODO: Read something like /Acess/Conf/services
129 for( int i = 0; i < ciNumLocalServices; i ++ )
131 if( strcmp(service, caLocalServices[i].Name) == 0 ) {
132 end = service + strlen(service);
133 default_socktype = caLocalServices[i].SockType;
134 default_protocol = caLocalServices[i].Protocol;
135 default_port = caLocalServices[i].Port;
143 _SysDebug("getaddrinfo: TODO Service translation");
147 for( struct addrinfo *ai = ret; ai; ai = ai->ai_next)
149 struct sockaddr_in *in = (void*)ai->ai_addr;
150 struct sockaddr_in6 *in6 = (void*)ai->ai_addr;
152 // Check ai_socktype/ai_protocol
153 // TODO: Do both of these need to be zero for defaults to apply?
154 if( ai->ai_socktype == 0 )
155 ai->ai_socktype = default_socktype;
156 if( ai->ai_protocol == 0 )
157 ai->ai_protocol = default_protocol;
159 switch(ai->ai_family)
162 if( in->sin_port == 0 )
163 in->sin_port = default_port;
164 _SysDebug("%p: IPv4 [%s]:%i %i,%i",
165 ai, Net_PrintAddress(4, &in->sin_addr),
166 in->sin_port, ai->ai_socktype, ai->ai_protocol);
169 if( in6->sin6_port == 0 )
170 in6->sin6_port = default_port;
171 _SysDebug("%p: IPv6 [%s]:%i %i,%i",
172 ai, Net_PrintAddress(6, &in6->sin6_addr),
173 in6->sin6_port, ai->ai_socktype, ai->ai_protocol);
176 _SysDebug("getaddrinfo: Unknown address family %i (setting port)", ai->ai_family);
185 void freeaddrinfo(struct addrinfo *res)
190 int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags)
192 // Determine hostname
198 if( !(flags & NI_NUMERICHOST) )
202 // Numeric hostname or the hostname was unresolvable
203 if( host[0] == '\0' )
205 if( (flags & NI_NAMEREQD) )
210 // Determine service name
216 if( !(flags & NI_NUMERICSERV) )
220 if( serv[0] == '\0' )
229 const char *gai_strerror(int errnum)
233 case EAI_SUCCESS: return "No error";
234 case EAI_FAIL: return "Permanent resolution failure";
235 default: return "UNKNOWN";
239 struct hostent *gethostbyname(const char *name)