char *Names[];
};
-struct sDNSCallbackInfo
+struct sLookupAnyInfo
{
- int expected_size;
+ int expected_type;
void *dest_ptr;
+ bool have_result;
+};
+struct sDNSCallbackInfo
+{
+ void *cb_info;
+ tNet_LookupAddrs_Callback *callback;
enum eTypes desired_type;
enum eClass desired_class;
- bool have_result;
+ bool got_value;
};
// === PROTOTYPES ===
+ int int_lookupany_callback(void *info_v, int AddrType, const void *Addr);
void int_DNS_callback(void *info, const char *name, enum eTypes type, enum eClass class, unsigned int ttl, size_t rdlength, const void *rdata);
// === GLOBALS ===
// === CODE ===
int Net_Lookup_AnyAddr(const char *Name, int AddrType, void *Addr)
+{
+ struct sLookupAnyInfo cb_info = {
+ .expected_type = AddrType,
+ .dest_ptr = Addr,
+ .have_result = false,
+ };
+ return Net_Lookup_Addrs(Name, &cb_info, int_lookupany_callback);
+}
+int int_lookupany_callback(void *info_v, int AddrType, const void *Addr)
+{
+ struct sLookupAnyInfo *info = info_v;
+ if( AddrType == info->expected_type && info->have_result == false )
+ {
+ memcpy(info->dest_ptr, Addr, Net_GetAddressSize(AddrType));
+
+ info->have_result = true;
+ return 1;
+ }
+ return 0;
+}
+
+int Net_Lookup_Addrs(const char *Name, void *cb_info, tNet_LookupAddrs_Callback *callback)
{
// 1. Load (if not loaded) the DNS config from "/Acess/Conf/dns"
// - "* <ip> <ip>" for DNS server(s)
for( int i = 0; i < giNumHostEntries; i ++ )
{
const struct sHostEntry* he = &gaHostEntries[i];
- if( he->AddrType == AddrType )
+ for( const char * const *namep = (const char**)he->Names; *namep; namep ++ )
{
- for( const char * const *namep = (const char**)he->Names; *namep; namep ++ )
+ if( strcasecmp(Name, *namep) == 0 )
{
- if( strcasecmp(Name, *namep) == 0 )
- {
- memcpy(Addr, he->AddrData, Net_GetAddressSize(AddrType));
+ if( callback(cb_info, he->AddrType, he->AddrData) != 0 )
return 0;
- }
}
}
}
// 3. Contact DNS server specified in config
for( int i = 0; i < giNumDNSServers; i ++ )
{
- // TODO
const struct sDNSServer *s = &gaDNSServers[i];
struct sDNSCallbackInfo info = {
- .expected_size = Net_GetAddressSize(AddrType),
- .dest_ptr = Addr,
+ .cb_info = cb_info,
+ .callback = callback,
.desired_type = TYPE_A,
.desired_class = CLASS_IN,
- .have_result = false
+ .got_value = false,
};
if( ! DNS_Query(s->AddrType, s->AddrData, Name, info.desired_type, info.desired_class, int_DNS_callback, &info) )
{
- if( info.have_result )
+ if( info.got_value )
{
return 0;
}
void int_DNS_callback(void *info_v, const char *name, enum eTypes type, enum eClass class, unsigned int ttl, size_t rdlength, const void *rdata)
{
struct sDNSCallbackInfo *info = info_v;
- if( type == info->desired_type && class == info->desired_class && info->have_result == false )
+
+ // Check type matches (if pattern was provided)
+ if( info->desired_type != QTYPE_STAR && type != info->desired_type )
+ return ;
+ if( info->desired_class != QCLASS_STAR && class != info->desired_class )
+ return ;
+
+ switch( type )
{
- // We're just working with A and AAAA, so copying from rdata is safe
- if( rdlength != info->expected_size ) {
- // ... oh, that's not good
+ case TYPE_A:
+ if( rdlength != 4 )
return ;
- }
-
- memcpy(info->dest_ptr, rdata, rdlength);
-
- info->have_result = true;
+ info->callback( info->cb_info, 4, rdata );
+ break;
+ //case TYPE_AAAA:
+ // if( rdlength != 16 )
+ // return ;
+ // info->callback( info->cb_info, 6, rdata );
+ // break;
+ default:
+ // Ignore anything not A/AAAA
+ break;
}
+ info->got_value = true;
}
int Net_Lookup_Name(int AddrType, const void *Addr, char *Dest[256])
{
CLASS_IN,
CLASS_CH, // "Chaos"
- CLASS_STAR = 255,
+ QCLASS_STAR = 255,
};
/**
*/
extern int Net_Lookup_AnyAddr(const char *Name, int AddrType, void *Addr);
+/**
+ * \brief Callback for Net_Lookup_Addrs, returns non-zero when lookup should terminate
+ */
+typedef int tNet_LookupAddrs_Callback(void *info, int AddrType, const void *Addr);
+
+/**
+ * \brief Enumerate addresses for a host, calling the provided function for each
+ */
+extern int Net_Lookup_Addrs(const char *Name, void *info, tNet_LookupAddrs_Callback* callback);
+
/**
*/
extern int Net_Lookup_Name(int AddrType, const void *Addr, char *Dest[256]);
#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;
{
// 1. Check if the node is an IP address
{
- 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 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_IPV4:
+ ret = int_new_addrinfo(AF_INET, addrdata);
+ break;
+ 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) )
{
- _SysDebug("getaddrinfo: TODO DNS Lookups");
- // TODO: DNS Lookups
- // ? /Acess/Conf/Nameservers
- // ? /Acess/Conf/Hosts
- //count = Net_LookupDNS(node, service, NULL);
- //
+ // 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;
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)