#include <net.h> // Net_ParseAddress
#include <stdlib.h> // malloc
#include <string.h> // memcpy
+#include <stdlib.h> // strtol
#include <acess/sys.h>
+// === TYPES ===
+struct sLookupInfo {
+ struct addrinfo **ret_p;
+};
+
+// === PROTOTYPES ===
+struct addrinfo *int_new_addrinfo(int af, const void *addrdata);
+int int_getaddinfo_lookupcb(void *info, int addr_type, const void *addr);
+
+// === GLOBALS ===
+static const struct {
+ const char *Name;
+ int SockType;
+ int Protocol;
+ int Port;
+} caLocalServices[] = {
+ {"telnet", SOCK_STREAM, 0, 23},
+ {"http", SOCK_STREAM, 0, 80},
+};
+static const int ciNumLocalServices = sizeof(caLocalServices)/sizeof(caLocalServices[0]);
+
// === CODE ===
int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res)
{
- static const struct addrinfo defhints = {.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG};
+ static const struct addrinfo defhints = {
+ .ai_family = AF_UNSPEC,
+ .ai_flags = AI_V4MAPPED | AI_ADDRCONFIG
+ };
struct addrinfo *ret = NULL;
+ _SysDebug("getaddrinfo('%s','%s',%p,%p)", node, service, hints, res);
+
// Error checks
if( !node && !service ) return EAI_NONAME;
else
{
// 1. Check if the node is an IP address
- // TODO: Break this function out into inet_pton?
{
- int type;
char addrdata[16];
- type = Net_ParseAddress(node, addrdata);
+ int type = Net_ParseAddress(node, addrdata);
switch(type)
{
- case 0:
+ case NET_ADDRTYPE_NULL:
+ break;
+ case NET_ADDRTYPE_IPV4:
+ ret = int_new_addrinfo(AF_INET, addrdata);
break;
- case 4: // IPv4
- ret = malloc(sizeof(struct addrinfo) + sizeof(struct sockaddr_in));
- ret->ai_family = AF_INET;
- ret->ai_socktype = 0;
- ret->ai_protocol = 0;
- ret->ai_addrlen = sizeof(struct in_addr);
- ret->ai_addr = (void*)( ret + 1 );
- ret->ai_canonname = 0;
- ret->ai_next = 0;
- ((struct sockaddr_in*)ret->ai_addr)->sin_family = AF_INET;
- ((struct sockaddr_in*)ret->ai_addr)->sin_port = 0;
- memcpy( &((struct sockaddr_in*)ret->ai_addr)->sin_addr, addrdata, 4 );
+ case NET_ADDRTYPE_IPV6:
+ ret = int_new_addrinfo(AF_INET6, addrdata);
break;
default:
- _SysDebug("getaddrinfo: Unknown address family %i", type);
+ _SysDebug("getaddrinfo: Unknown address type %i", type);
return 1;
}
}
// - No luck with above, and hints->ai_flags doesn't have AI_NUMERICHOST set
if( !ret && !(hints->ai_flags & AI_NUMERICHOST) )
{
- // TODO: DNS Lookups
- // ? /Acess/Conf/Nameservers
- // ? /Acess/Conf/Hosts
+ // Just does a basic A record lookup
+ // TODO: Support SRV records
+ // TODO: Ensure that CNAMEs are handled correctly
+ struct sLookupInfo info = {
+ .ret_p = &ret,
+ };
+ if( Net_Lookup_Addrs(node, &info, int_getaddinfo_lookupcb) ) {
+ // Lookup failed, quick return
+ return EAI_NONAME;
+ }
}
- // 3. No Match, chuck sad
+ // 3. No Match, return sad
if( !ret )
{
return EAI_NONAME;
}
}
- int default_socktype = 0;
- int default_protocol = 0;
+ int default_socktype = hints->ai_socktype;
+ int default_protocol = hints->ai_protocol;
int default_port = 0;
+ #if 0
+ if( default_protocol == 0 )
+ {
+ switch(default_socktype)
+ {
+ case SOCK_DGRAM:
+ default_protocol =
+ }
+ }
+ #endif
+
// Convert `node` into types
if( service )
{
- // TODO: Read something like /Acess/Conf/services
+ const char *end;
+
+ default_port = strtol(service, (char**)&end, 0);
+ if( *end != '\0' && (hints->ai_flags & AI_NUMERICSERV) )
+ {
+ return EAI_NONAME;
+ }
+
+ if( *end != '\0' )
+ {
+ // TODO: Read something like /Acess/Conf/services
+ for( int i = 0; i < ciNumLocalServices; i ++ )
+ {
+ if( strcmp(service, caLocalServices[i].Name) == 0 ) {
+ end = service + strlen(service);
+ default_socktype = caLocalServices[i].SockType;
+ default_protocol = caLocalServices[i].Protocol;
+ default_port = caLocalServices[i].Port;
+ break;
+ }
+ }
+ }
+
+ if( *end != '\0' )
+ {
+ _SysDebug("getaddrinfo: TODO Service translation");
+ }
}
- struct addrinfo *ai;
- for( ai = ret; ai; ai = ai->ai_next)
+ for( struct addrinfo *ai = ret; ai; ai = ai->ai_next)
{
struct sockaddr_in *in = (void*)ai->ai_addr;
struct sockaddr_in6 *in6 = (void*)ai->ai_addr;
case AF_INET:
if( in->sin_port == 0 )
in->sin_port = default_port;
+ _SysDebug("%p: IPv4 [%s]:%i %i,%i",
+ ai, Net_PrintAddress(4, &in->sin_addr),
+ in->sin_port, ai->ai_socktype, ai->ai_protocol);
break;
case AF_INET6:
if( in6->sin6_port == 0 )
in6->sin6_port = default_port;
+ _SysDebug("%p: IPv6 [%s]:%i %i,%i",
+ ai, Net_PrintAddress(6, &in6->sin6_addr),
+ in6->sin6_port, ai->ai_socktype, ai->ai_protocol);
break;
default:
_SysDebug("getaddrinfo: Unknown address family %i (setting port)", ai->ai_family);
return 0;
}
+/**
+ * \brief Allocate a new zeroed addrinfo for the specified address
+ */
+struct addrinfo *int_new_addrinfo(int af, const void *addrdata)
+{
+ size_t addrlen = 0;
+ switch(af)
+ {
+ case AF_INET:
+ addrlen = sizeof(struct sockaddr_in);
+ break;
+ case AF_INET6:
+ addrlen = sizeof(struct sockaddr_in6);
+ break;
+ default:
+ _SysDebug("int_new_addrinfo: ERROR - Unknown AF %i", af);
+ return NULL;
+ }
+ struct addrinfo* ret = malloc(sizeof(struct addrinfo) + addrlen);
+ ret->ai_family = af;
+ ret->ai_socktype = 0;
+ ret->ai_protocol = 0;
+ ret->ai_addrlen = addrlen;
+ ret->ai_addr = (void*)( ret + 1 );
+ ret->ai_canonname = 0;
+ ret->ai_next = 0;
+ switch(af)
+ {
+ case AF_INET:
+ ((struct sockaddr_in*)ret->ai_addr)->sin_family = AF_INET;
+ ((struct sockaddr_in*)ret->ai_addr)->sin_port = 0;
+ memcpy( &((struct sockaddr_in*)ret->ai_addr)->sin_addr, addrdata, 4 );
+ break;
+ case AF_INET6:
+ ((struct sockaddr_in6*)ret->ai_addr)->sin6_family = AF_INET6;
+ ((struct sockaddr_in6*)ret->ai_addr)->sin6_port = 0;
+ memcpy( &((struct sockaddr_in6*)ret->ai_addr)->sin6_addr, addrdata, 16 );
+ break;
+ default:
+ _SysDebug("int_new_addrinfo: BUGCHECK - Unhandled AF %i", af);
+ return NULL;
+ }
+ return ret;
+}
+
+// Callback for getaddrinfo's call to Net_Lookup_Addrs
+int int_getaddinfo_lookupcb(void *info_v, int addr_type, const void *addr)
+{
+ struct sLookupInfo *info = info_v;
+ struct addrinfo *ent;
+ switch( addr_type )
+ {
+ case NET_ADDRTYPE_IPV4:
+ ent = int_new_addrinfo(AF_INET, addr);
+ break;
+ case NET_ADDRTYPE_IPV6:
+ ent = int_new_addrinfo(AF_INET6, addr);
+ break;
+ default:
+ // Huh... unknown address type, just ignore it
+ return 0;
+ }
+ ent->ai_next = *info->ret_p;
+ *info->ret_p = ent;
+ return 0;
+}
+
void freeaddrinfo(struct addrinfo *res)
{
-
+ while( res )
+ {
+ struct addrinfo *next = res->ai_next;
+ free(res);
+ res = next;
+ }
}
int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags)
}
}
+struct hostent *gethostbyname(const char *name)
+{
+ return NULL;
+}
+