From 341d51ca40a4a26ed89914feaacc940c64b22197 Mon Sep 17 00:00:00 2001 From: "John Hodge (sonata)" Date: Mon, 16 Feb 2015 09:18:54 +0800 Subject: [PATCH] Usermode/(libnet,libpsocket) - Call new DNS code from getaddrinfo --- Usermode/Libraries/libnet.so_src/hostnames.c | 83 ++++++++---- .../Libraries/libnet.so_src/include/dns.h | 2 +- .../Libraries/libnet.so_src/include_exp/net.h | 10 ++ .../Libraries/libpsocket.so_src/getaddrinfo.c | 126 ++++++++++++++---- 4 files changed, 173 insertions(+), 48 deletions(-) diff --git a/Usermode/Libraries/libnet.so_src/hostnames.c b/Usermode/Libraries/libnet.so_src/hostnames.c index 203f4aa4..88093de3 100644 --- a/Usermode/Libraries/libnet.so_src/hostnames.c +++ b/Usermode/Libraries/libnet.so_src/hostnames.c @@ -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" // - "* " 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]) diff --git a/Usermode/Libraries/libnet.so_src/include/dns.h b/Usermode/Libraries/libnet.so_src/include/dns.h index 8a6ba440..62204f05 100644 --- a/Usermode/Libraries/libnet.so_src/include/dns.h +++ b/Usermode/Libraries/libnet.so_src/include/dns.h @@ -28,7 +28,7 @@ enum eClass { CLASS_IN, CLASS_CH, // "Chaos" - CLASS_STAR = 255, + QCLASS_STAR = 255, }; /** diff --git a/Usermode/Libraries/libnet.so_src/include_exp/net.h b/Usermode/Libraries/libnet.so_src/include_exp/net.h index f02c0a43..cd2cb6c8 100644 --- a/Usermode/Libraries/libnet.so_src/include_exp/net.h +++ b/Usermode/Libraries/libnet.so_src/include_exp/net.h @@ -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]); diff --git a/Usermode/Libraries/libpsocket.so_src/getaddrinfo.c b/Usermode/Libraries/libpsocket.so_src/getaddrinfo.c index 5c21c06e..e1a0e424 100644 --- a/Usermode/Libraries/libpsocket.so_src/getaddrinfo.c +++ b/Usermode/Libraries/libpsocket.so_src/getaddrinfo.c @@ -13,6 +13,16 @@ #include // strtol #include +// === 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) -- 2.20.1