Usermode/(libnet,libpsocket) - Call new DNS code from getaddrinfo
authorJohn Hodge (sonata) <[email protected]>
Mon, 16 Feb 2015 01:18:54 +0000 (09:18 +0800)
committerJohn Hodge (sonata) <[email protected]>
Mon, 16 Feb 2015 01:18:54 +0000 (09:18 +0800)
Usermode/Libraries/libnet.so_src/hostnames.c
Usermode/Libraries/libnet.so_src/include/dns.h
Usermode/Libraries/libnet.so_src/include_exp/net.h
Usermode/Libraries/libpsocket.so_src/getaddrinfo.c

index 203f4aa..88093de 100644 (file)
@@ -24,16 +24,23 @@ struct sHostEntry
        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 ===
@@ -44,6 +51,28 @@ struct sHostEntry    *gaHostEntries;
 
 // === 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)
@@ -53,33 +82,29 @@ int Net_Lookup_AnyAddr(const char *Name, int AddrType, void *Addr)
        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;
                        }
@@ -96,18 +121,30 @@ int Net_Lookup_AnyAddr(const char *Name, int AddrType, void *Addr)
 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])
index 8a6ba44..62204f0 100644 (file)
@@ -28,7 +28,7 @@ enum eClass
 {
        CLASS_IN,
        CLASS_CH,       // "Chaos"
-       CLASS_STAR = 255,
+       QCLASS_STAR = 255,
 };
 
 /**
index f02c0a4..cd2cb6c 100644 (file)
@@ -72,6 +72,16 @@ extern int   Net_OpenSocket_UDP(int AddrType, const void *Addr, int RAddr, int LAd
  */
 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]);
index 5c21c06..e1a0e42 100644 (file)
 #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;
@@ -52,28 +62,20 @@ int getaddrinfo(const char *node, const char *service, const struct addrinfo *hi
        {
                // 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;
                        }
                }
@@ -82,15 +84,19 @@ int getaddrinfo(const char *node, const char *service, const struct addrinfo *hi
                // - 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;
@@ -182,9 +188,81 @@ int getaddrinfo(const char *node, const char *service, const struct addrinfo *hi
        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)

UCC git Repository :: git.ucc.asn.au