diff --git a/src/Cedar/Connection.c b/src/Cedar/Connection.c index 700c718f..6e917388 100644 --- a/src/Cedar/Connection.c +++ b/src/Cedar/Connection.c @@ -21,6 +21,7 @@ #include "UdpAccel.h" #include "Virtual.h" +#include "Mayaqua/DNS.h" #include "Mayaqua/Kernel.h" #include "Mayaqua/Mayaqua.h" #include "Mayaqua/Memory.h" diff --git a/src/Cedar/Hub.c b/src/Cedar/Hub.c index 17d0b40e..605405b4 100644 --- a/src/Cedar/Hub.c +++ b/src/Cedar/Hub.c @@ -19,6 +19,7 @@ #include "Server.h" #include "Mayaqua/Cfg.h" +#include "Mayaqua/DNS.h" #include "Mayaqua/FileIO.h" #include "Mayaqua/Internat.h" #include "Mayaqua/Memory.h" diff --git a/src/Cedar/Logging.c b/src/Cedar/Logging.c index b8e0198d..82640001 100644 --- a/src/Cedar/Logging.c +++ b/src/Cedar/Logging.c @@ -17,6 +17,7 @@ #include "SecureNAT.h" #include "Server.h" +#include "Mayaqua/DNS.h" #include "Mayaqua/Internat.h" #include "Mayaqua/FileIO.h" #include "Mayaqua/Memory.h" diff --git a/src/Cedar/Protocol.c b/src/Cedar/Protocol.c index ecf9f5c8..3ac60f6d 100644 --- a/src/Cedar/Protocol.c +++ b/src/Cedar/Protocol.c @@ -30,6 +30,7 @@ #include "Wpc.h" #include "Mayaqua/Cfg.h" +#include "Mayaqua/DNS.h" #include "Mayaqua/FileIO.h" #include "Mayaqua/Internat.h" #include "Mayaqua/Memory.h" diff --git a/src/Cedar/Radius.c b/src/Cedar/Radius.c index 34d646aa..aa2b358e 100644 --- a/src/Cedar/Radius.c +++ b/src/Cedar/Radius.c @@ -11,6 +11,7 @@ #include "IPC.h" #include "Server.h" +#include "Mayaqua/DNS.h" #include "Mayaqua/Internat.h" #include "Mayaqua/Memory.h" #include "Mayaqua/Object.h" @@ -1717,7 +1718,7 @@ bool RadiusLogin(CONNECTION *c, char *server, UINT port, UCHAR *secret, UINT sec { Add(ip_list, tmp_ip); } - else if (GetIPEx(tmp_ip, token->Token[i], true)) + else if (GetIP(tmp_ip, token->Token[i])) { Add(ip_list, tmp_ip); } diff --git a/src/Cedar/Server.c b/src/Cedar/Server.c index a2294c94..3d54a533 100644 --- a/src/Cedar/Server.c +++ b/src/Cedar/Server.c @@ -25,6 +25,7 @@ #include "WinUi.h" #include "Mayaqua/Cfg.h" +#include "Mayaqua/DNS.h" #include "Mayaqua/FileIO.h" #include "Mayaqua/Internat.h" #include "Mayaqua/Memory.h" @@ -312,8 +313,8 @@ UINT SiDebugProcGetCurrentGetIPThreadCount(SERVER *s, char *in_str, char *ret_st return ERR_INVALID_PARAMETER; } - ToStr3(tmp1, 0, GetCurrentGetIpThreadNum()); - ToStr3(tmp2, 0, GetGetIpThreadMaxNum()); + ToStr3(tmp1, 0, DnsThreadNum()); + ToStr3(tmp2, 0, DnsThreadNumMax()); Format(ret_str, 0, "Current threads = %s\n" @@ -5629,11 +5630,11 @@ void SiLoadServerCfg(SERVER *s, FOLDER *f) i = CfgGetInt(f, "MaxConcurrentDnsClientThreads"); if (i != 0) { - SetGetIpThreadMaxNum(i); + DnsThreadNumMaxSet(i); } else { - SetGetIpThreadMaxNum(DEFAULT_GETIP_THREAD_MAX_NUM); + DnsThreadNumMaxSet(DNS_THREAD_DEFAULT_NUM_MAX); } s->DontBackupConfig = CfgGetBool(f, "DontBackupConfig"); @@ -6103,7 +6104,7 @@ void SiWriteServerCfg(FOLDER *f, SERVER *s) return; } - CfgAddInt(f, "MaxConcurrentDnsClientThreads", GetGetIpThreadMaxNum()); + CfgAddInt(f, "MaxConcurrentDnsClientThreads", DnsThreadNumMax()); CfgAddInt(f, "CurrentBuild", s->Cedar->Build); @@ -10766,7 +10767,7 @@ SERVER *SiNewServerEx(bool bridge, bool in_client_inner_server, bool relay_serve LISTENER *azure; LISTENER *rudp; - SetGetIpThreadMaxNum(DEFAULT_GETIP_THREAD_MAX_NUM); + DnsThreadNumMaxSet(DNS_THREAD_DEFAULT_NUM_MAX); s = ZeroMalloc(sizeof(SERVER)); diff --git a/src/Cedar/UdpAccel.c b/src/Cedar/UdpAccel.c index 9d6dc110..e19de467 100644 --- a/src/Cedar/UdpAccel.c +++ b/src/Cedar/UdpAccel.c @@ -9,6 +9,7 @@ #include "Connection.h" +#include "Mayaqua/DNS.h" #include "Mayaqua/Kernel.h" #include "Mayaqua/Memory.h" #include "Mayaqua/Object.h" diff --git a/src/Cedar/Virtual.c b/src/Cedar/Virtual.c index 90597602..e329a8cc 100644 --- a/src/Cedar/Virtual.c +++ b/src/Cedar/Virtual.c @@ -15,6 +15,7 @@ #include "NativeStack.h" #include "Server.h" +#include "Mayaqua/DNS.h" #include "Mayaqua/FileIO.h" #include "Mayaqua/Memory.h" #include "Mayaqua/Object.h" diff --git a/src/Cedar/Wpc.c b/src/Cedar/Wpc.c index 06271093..1e21b926 100644 --- a/src/Cedar/Wpc.c +++ b/src/Cedar/Wpc.c @@ -10,6 +10,7 @@ #include "Command.h" #include "Protocol.h" +#include "Mayaqua/DNS.h" #include "Mayaqua/Memory.h" #include "Mayaqua/Microsoft.h" #include "Mayaqua/Pack.h" diff --git a/src/Mayaqua/DNS.c b/src/Mayaqua/DNS.c new file mode 100644 index 00000000..9f89e043 --- /dev/null +++ b/src/Mayaqua/DNS.c @@ -0,0 +1,581 @@ +#include "DNS.h" + +#include "Memory.h" +#include "Network.h" +#include "Object.h" +#include "Str.h" +#include "Tick64.h" + +#ifdef OS_WIN32 +#include +#else +#include +#include +#endif + +static bool cache_enabled; + +static LIST *cache; +static LIST *cache_reverse; + +static COUNTER *threads_counter; +static UINT threads_max; + +int DnsCacheCompare(void *p1, void *p2) +{ + if (p1 == NULL || p2 == NULL) + { + return (p1 == NULL && p2 == NULL ? 0 : (p1 == NULL ? -1 : 1)); + } + + const DNS_CACHE *c1 = *(DNS_CACHE **)p1; + const DNS_CACHE *c2 = *(DNS_CACHE **)p2; + + return StrCmpi(c1->Hostname, c2->Hostname); +} + +int DnsCacheReverseCompare(void *p1, void *p2) +{ + if (p1 == NULL || p2 == NULL) + { + return (p1 == NULL && p2 == NULL ? 0 : (p1 == NULL ? -1 : 1)); + } + + const DNS_CACHE_REVERSE *c1 = *(DNS_CACHE_REVERSE **)p1; + const DNS_CACHE_REVERSE *c2 = *(DNS_CACHE_REVERSE **)p2; + + return CmpIpAddr(&c1->IP, &c2->IP); +} + +void DnsInit() +{ + threads_counter = NewCounter(); + DnsThreadNumMaxSet(DNS_THREAD_DEFAULT_NUM_MAX); + + cache = NewList(DnsCacheCompare); + cache_reverse = NewList(DnsCacheReverseCompare); + DnsCacheToggle(true); +} + +void DnsFree() +{ + DnsCacheToggle(false); + + LockList(cache); + { + for (UINT i = 0; i < LIST_NUM(cache); ++i) + { + DNS_CACHE *entry = LIST_DATA(cache, i); + Free((void *)entry->Hostname); + Free(entry); + } + } + UnlockList(cache); + + ReleaseList(cache); + cache = NULL; + + LockList(cache_reverse); + { + for (UINT i = 0; i < LIST_NUM(cache_reverse); ++i) + { + DNS_CACHE_REVERSE *entry = LIST_DATA(cache, i); + Free(entry->Hostname); + Free(entry); + } + } + UnlockList(cache_reverse); + + ReleaseList(cache_reverse); + cache_reverse = NULL; + + DeleteCounter(threads_counter); + threads_counter = NULL; +} + +UINT DnsThreadNum() +{ + return Count(threads_counter); +} + +UINT DnsThreadNumMax() +{ + return threads_max; +} + +void DnsThreadNumMaxSet(const UINT max) +{ + threads_max = max; +} + +bool DnsCacheIsEnabled() +{ + return cache_enabled; +} + +void DnsCacheToggle(const bool enabled) +{ + cache_enabled = enabled; +} + +DNS_CACHE *DnsCacheFind(const char *hostname) +{ + if (DnsCacheIsEnabled() == false || IsEmptyStr(hostname)) + { + return NULL; + } + + DNS_CACHE *entry; + + LockList(cache); + { + DNS_CACHE t; + t.Hostname = hostname; + entry = Search(cache, &t); + } + UnlockList(cache); + + return entry; +} + +DNS_CACHE *DnsCacheUpdate(const char *hostname, const IP *ipv6, const IP *ipv4) +{ + if (DnsCacheIsEnabled() == false || IsEmptyStr(hostname)) + { + return NULL; + } + + DNS_CACHE *entry; + + LockList(cache); + { + DNS_CACHE t; + t.Hostname = hostname; + entry = Search(cache, &t); + + if (ipv6 == NULL && ipv4 == NULL) + { + if (entry != NULL) + { + Delete(cache, entry); + Free(entry); + entry = NULL; + } + } + else + { + if (entry == NULL) + { + entry = ZeroMalloc(sizeof(DNS_CACHE)); + entry->Hostname = CopyStr(hostname); + + Add(cache, entry); + } + + entry->Expiration = Tick64(); + + if (ipv6 != NULL) + { + if (CmpIpAddr(&entry->IPv6, ipv6) != 0) + { + Copy(&entry->IPv6, ipv6, sizeof(entry->IPv6)); + } + } + else + { + if (CmpIpAddr(&entry->IPv4, ipv4) != 0) + { + Copy(&entry->IPv4, ipv4, sizeof(entry->IPv4)); + } + } + } + } + UnlockList(cache); + + return entry; +} + +DNS_CACHE_REVERSE *DnsCacheReverseFind(const IP *ip) +{ + if (DnsCacheIsEnabled() == false || ip == NULL) + { + return NULL; + } + + DNS_CACHE_REVERSE *entry; + + LockList(cache_reverse); + { + DNS_CACHE_REVERSE t; + Copy(&t.IP, ip, sizeof(t.IP)); + entry = Search(cache_reverse, &t); + } + UnlockList(cache_reverse); + + return entry; +} + +DNS_CACHE_REVERSE *DnsCacheReverseUpdate(const IP *ip, const char *hostname) +{ + if (DnsCacheIsEnabled() == false || IsZeroIP(&ip)) + { + return NULL; + } + + DNS_CACHE_REVERSE *entry; + + LockList(cache_reverse); + { + DNS_CACHE_REVERSE t; + Copy(&t.IP, ip, sizeof(t.IP)); + entry = Search(cache_reverse, &t); + + if (IsEmptyStr(hostname)) + { + if (entry != NULL) + { + Delete(cache, entry); + Free(entry); + entry = NULL; + } + } + else + { + if (entry == NULL) + { + entry = ZeroMalloc(sizeof(DNS_CACHE_REVERSE)); + Copy(&entry->IP, ip, sizeof(entry->IP)); + + Add(cache, entry); + } + + entry->Expiration = Tick64(); + + if (StrCmp(entry->Hostname, hostname) != 0) + { + Free(entry->Hostname); + entry->Hostname = CopyStr(hostname); + } + } + } + UnlockList(cache_reverse); + + return entry; +} + +bool DnsResolve(IP *ipv6, IP *ipv4, const char *hostname, UINT timeout, volatile const bool *cancel_flag) +{ + if ((ipv6 == NULL && ipv4 == NULL) || IsEmptyStr(hostname)) + { + return false; + } + + if (StrCmpi(hostname, "localhost") == 0) + { + GetLocalHostIP6(ipv6); + GetLocalHostIP4(ipv4); + return true; + } + + IP ip; + if (StrToIP(&ip, hostname)) + { + if (IsIP6(&ip)) + { + if (ipv6 != NULL) + { + ZeroIP4(ipv4); + Copy(ipv6, &ip, sizeof(IP)); + return true; + } + } + else + { + if (ipv4 != NULL) + { + Zero(ipv6, sizeof(IP)); + Copy(ipv4, &ip, sizeof(IP)); + return true; + } + } + + return false; + } + + if (DnsThreadNum() > DnsThreadNumMax()) + { + Debug("DnsResolve(): Too many threads! Current: %u, Maximum: %u\n", + DnsThreadNum(), DnsThreadNumMax()); + + goto CACHE; + } + + if (cancel_flag != NULL && *cancel_flag) + { + return false; + } + + if (timeout == 0) + { + timeout = DNS_RESOLVE_DEFAULT_TIMEOUT; + } + + Inc(threads_counter); + + DNS_RESOLVER resolver; + Zero(&resolver, sizeof(resolver)); + ZeroIP4(&resolver.IPv4); + resolver.Hostname = hostname; + + THREAD *worker = NewThread(DnsResolver, &resolver); + WaitThreadInit(worker); + + if (cancel_flag == NULL) + { + WaitThread(worker, timeout); + } + else + { + const UINT64 end = Tick64() + timeout; + + while (*cancel_flag == false) + { + const UINT64 now = Tick64(); + if (now >= end) + { + break; + } + + BYTE next = MIN(end - now, 100); + if (WaitThread(worker, next)) + { + break; + } + } + } + + ReleaseThread(worker); + + Dec(threads_counter); + + if (resolver.OK) + { + Copy(ipv6, &resolver.IPv6, sizeof(IP)); + Copy(ipv4, &resolver.IPv4, sizeof(IP)); + + DnsCacheUpdate(hostname, ipv6, ipv4); + + return true; + } +CACHE: + Debug("DnsResolve(): Could not resolve \"%s\". Searching for it in the cache...\n", hostname); + + const DNS_CACHE *cached = DnsCacheFind(hostname); + if (cached == NULL || cached->Expiration <= Tick64()) + { + return false; + } + + Copy(ipv6, &cached->IPv6, sizeof(IP)); + Copy(ipv4, &cached->IPv4, sizeof(IP)); + + return true; +} + +void DnsResolver(THREAD *t, void *param) +{ + if (t == NULL || param == NULL) + { + return; + } + + DNS_RESOLVER *resolver = param; + + NoticeThreadInit(t); + AddWaitThread(t); + + struct addrinfo hints; + Zero(&hints, sizeof(hints)); + + hints.ai_family = AF_INET6; + hints.ai_flags = AI_ALL | AI_ADDRCONFIG | AI_V4MAPPED; + + struct addrinfo *result; + const int ret = getaddrinfo(resolver->Hostname, NULL, &hints, &result); + if (ret == 0) + { + bool ipv6_ok = false; + bool ipv4_ok = false; + do + { + IP ip; + const struct sockaddr_in6 *in = (struct sockaddr_in6 *)result->ai_addr; + InAddrToIP6(&ip, &in->sin6_addr); + if (IsIP6(&ip) && ipv6_ok == false) + { + Copy(&resolver->IPv6, &ip, sizeof(resolver->IPv6)); + resolver->IPv6.ipv6_scope_id = in->sin6_scope_id; + ipv6_ok = true; + } + else if (ipv4_ok == false) + { + Copy(&resolver->IPv4, &ip, sizeof(resolver->IPv4)); + ipv4_ok = true; + } + + result = result->ai_next; + } while (result != NULL && (ipv6_ok == false || ipv4_ok == false)); + + resolver->OK = true; + } + else if (ret != EAI_NONAME) + { + Debug("DnsResolver(): getaddrinfo() failed with error %d!\n", ret); + } + + DelWaitThread(t); +} + +bool DnsResolveReverse(char *dst, const UINT size, const IP *ip, UINT timeout, volatile const bool *cancel_flag) +{ + if (dst == NULL || size == 0 || IsZeroIP(ip)) + { + return false; + } + + if (DnsThreadNum() > DnsThreadNumMax()) + { + Debug("DnsResolveReverse(): Too many threads! Current: %u, Maximum: %u\n", + DnsThreadNum(), DnsThreadNumMax()); + + goto CACHE; + } + + if (cancel_flag != NULL && *cancel_flag) + { + return false; + } + + if (timeout == 0) + { + timeout = DNS_RESOLVE_REVERSE_DEFAULT_TIMEOUT; + } + + Inc(threads_counter); + + DNS_RESOLVER_REVERSE resolver; + Zero(&resolver, sizeof(resolver)); + Copy(&resolver.IP, ip, sizeof(resolver.IP)); + + THREAD *worker = NewThread(DnsResolverReverse, &resolver); + WaitThreadInit(worker); + + if (cancel_flag == NULL) + { + WaitThread(worker, timeout); + } + else + { + const UINT64 end = Tick64() + timeout; + + while (*cancel_flag == false) + { + const UINT64 now = Tick64(); + if (now >= end) + { + break; + } + + BYTE next = MIN(end - now, 100); + if (WaitThread(worker, next)) + { + break; + } + } + } + + ReleaseThread(worker); + + Dec(threads_counter); + + if (resolver.OK) + { + StrCpy(dst, size, resolver.Hostname); + Free(resolver.Hostname); + + DnsCacheReverseUpdate(ip, dst); + + return true; + } +CACHE: + Debug("DnsResolveReverse(): Could not resolve \"%r\". Searching for it in the cache...\n", ip); + + const DNS_CACHE_REVERSE *cached = DnsCacheReverseFind(ip); + if (cached == NULL || cached->Expiration <= Tick64()) + { + return false; + } + + StrCpy(dst, size, cached->Hostname); + + return true; +} + +void DnsResolverReverse(THREAD *t, void *param) +{ + if (t == NULL || param == NULL) + { + return; + } + + DNS_RESOLVER_REVERSE *resolver = param; + + NoticeThreadInit(t); + AddWaitThread(t); + + struct sockaddr_in6 in; + Zero(&in, sizeof(in)); + in.sin6_family = AF_INET6; + IPToInAddr6(&in.sin6_addr, &resolver->IP); + + char tmp[NI_MAXHOST]; + const int ret = getnameinfo((struct sockaddr *)&in, sizeof(in), tmp, sizeof(tmp), NULL, 0, NI_NAMEREQD); + if (ret == 0) + { + resolver->Hostname = CopyStr(tmp); + resolver->OK = true; + } + else if (ret != EAI_NONAME) + { + Debug("DnsResolverReverse(): getnameinfo() failed with error %d!\n", ret); + } + + DelWaitThread(t); +} + +bool GetIPEx(IP *ip, const char *hostname, UINT timeout, volatile const bool *cancel_flag) +{ + if (ip == NULL || IsEmptyStr(hostname)) + { + return false; + } + + IP ipv6, ipv4; + if (DnsResolve(&ipv6, &ipv4, hostname, timeout, cancel_flag) == false) + { + return false; + } + + if (IsZeroIP(&ipv6) == false) + { + Copy(ip, &ipv6, sizeof(IP)); + return true; + } + else if (IsZeroIP(&ipv4) == false) + { + Copy(ip, &ipv4, sizeof(IP)); + return true; + } + + return false; +} diff --git a/src/Mayaqua/DNS.h b/src/Mayaqua/DNS.h new file mode 100644 index 00000000..235d6a97 --- /dev/null +++ b/src/Mayaqua/DNS.h @@ -0,0 +1,78 @@ +#ifndef DNS_H +#define DNS_H + +#include "Network.h" + +#define DNS_CACHE_EXPIRATION (10 * 60 * 1000) + +#ifndef USE_STRATEGY_LOW_MEMORY +#define DNS_THREAD_DEFAULT_NUM_MAX (512) +#else +#define DNS_THREAD_DEFAULT_NUM_MAX (64) +#endif + +#define DNS_RESOLVE_DEFAULT_TIMEOUT (2300) +#define DNS_RESOLVE_REVERSE_DEFAULT_TIMEOUT (500) + +#define GetIP(ip, hostname) (GetIPEx(ip, hostname, 0, NULL)) +#define GetIP4(ip, hostname) (GetIP4Ex(ip, hostname, 0, NULL)) +#define GetIP6(ip, hostname) (GetIP6Ex(ip, hostname, 0, NULL)) + +#define GetIP4Ex(ip, hostname, timeout, cancel_flag) (DnsResolve(NULL, ip, hostname, timeout, cancel_flag)) +#define GetIP6Ex(ip, hostname, timeout, cancel_flag) (DnsResolve(ip, NULL, hostname, timeout, cancel_flag)) + +struct DNS_CACHE +{ + const char *Hostname; + IP IPv4; + IP IPv6; + UINT64 Expiration; +}; + +struct DNS_CACHE_REVERSE +{ + IP IP; + char *Hostname; + UINT64 Expiration; +}; + +struct DNS_RESOLVER +{ + const char *Hostname; + IP IPv4; + IP IPv6; + bool OK; +}; + +struct DNS_RESOLVER_REVERSE +{ + IP IP; + char *Hostname; + bool OK; +}; + +void DnsInit(); +void DnsFree(); + +UINT DnsThreadNum(); +UINT DnsThreadNumMax(); +void DnsThreadNumMaxSet(const UINT num); + +bool DnsCacheIsEnabled(); +void DnsCacheToggle(const bool enabled); + +DNS_CACHE *DnsCacheFind(const char *hostname); +DNS_CACHE *DnsCacheUpdate(const char *hostname, const IP *ipv6, const IP *ipv4); + +DNS_CACHE_REVERSE *DnsCacheReverseFind(const IP *ip); +DNS_CACHE_REVERSE *DnsCacheReverseUpdate(const IP *ip, const char *hostname); + +bool DnsResolve(IP *ipv6, IP *ipv4, const char *hostname, UINT timeout, volatile const bool *cancel_flag); +void DnsResolver(THREAD *t, void *param); + +bool DnsResolveReverse(char *dst, const UINT size, const IP *ip, UINT timeout, volatile const bool *cancel_flag); +void DnsResolverReverse(THREAD *t, void *param); + +bool GetIPEx(IP *ip, const char *hostname, UINT timeout, volatile const bool *cancel_flag); + +#endif diff --git a/src/Mayaqua/MayaType.h b/src/Mayaqua/MayaType.h index 1efcb346..36b1eaea 100644 --- a/src/Mayaqua/MayaType.h +++ b/src/Mayaqua/MayaType.h @@ -352,7 +352,6 @@ typedef struct LANGLIST LANGLIST; // Network.h typedef struct IP IP; -typedef struct DNSCACHE DNSCACHE; typedef struct SOCK_EVENT SOCK_EVENT; typedef struct SOCK SOCK; typedef struct SOCKSET SOCKSET; @@ -362,7 +361,6 @@ typedef struct ROUTE_TABLE ROUTE_TABLE; typedef struct IP_CLIENT IP_CLIENT; typedef struct ROUTE_CHANGE ROUTE_CHANGE; typedef struct ROUTE_CHANGE_DATA ROUTE_CHANGE_DATA; -typedef struct GETIP_THREAD_PARAM GETIP_THREAD_PARAM; typedef struct WIN32_RELEASEADDRESS_THREAD_PARAM WIN32_RELEASEADDRESS_THREAD_PARAM; typedef struct IPV6_ADDR IPV6_ADDR; typedef struct TUBE TUBE; @@ -387,8 +385,6 @@ typedef struct TCP_PAIR_HEADER TCP_PAIR_HEADER; typedef struct NIC_ENTRY NIC_ENTRY; typedef struct HTTP_VALUE HTTP_VALUE; typedef struct HTTP_HEADER HTTP_HEADER; -typedef struct DNSPROXY_CLIENT DNSPROXY_CLIENT; -typedef struct DNSPROXY_CACHE DNSPROXY_CACHE; typedef struct QUERYIPTHREAD QUERYIPTHREAD; typedef struct IPBLOCK IPBLOCK; typedef struct SAFE_REQUEST SAFE_REQUEST; @@ -464,4 +460,10 @@ typedef struct HTTP_MIME_TYPE HTTP_MIME_TYPE; typedef struct PROXY_PARAM_IN PROXY_PARAM_IN; typedef struct PROXY_PARAM_OUT PROXY_PARAM_OUT; +// DNS.h +typedef struct DNS_CACHE DNS_CACHE; +typedef struct DNS_CACHE_REVERSE DNS_CACHE_REVERSE; +typedef struct DNS_RESOLVER DNS_RESOLVER; +typedef struct DNS_RESOLVER_REVERSE DNS_RESOLVER_REVERSE; + #endif // MAYATYPE_H diff --git a/src/Mayaqua/Network.c b/src/Mayaqua/Network.c index f233bd7f..72edb903 100644 --- a/src/Mayaqua/Network.c +++ b/src/Mayaqua/Network.c @@ -8,6 +8,7 @@ #include "Network.h" #include "Cfg.h" +#include "DNS.h" #include "FileIO.h" #include "HTTP.h" #include "Internat.h" @@ -69,41 +70,18 @@ struct ROUTE_CHANGE_DATA #define FIX_SSL_BLOCKING #endif -// IPV6_V6ONLY constant -#ifdef UNIX_LINUX -#ifndef IPV6_V6ONLY -#define IPV6_V6ONLY 26 -#endif // IPV6_V6ONLY -#endif // UNIX_LINUX - -#ifdef UNIX_SOLARIS -#ifndef IPV6_V6ONLY -#define IPV6_V6ONLY 0x27 -#endif // IPV6_V6ONLY -#endif // UNIX_SOLARIS - // HTTP constant static char http_detect_server_startwith[] = "\r\n\r\n403 Forbidden\r\n\r\n

Forbidden

\r\nYou don't have permission to access "; static char http_detect_server_tag_future[] = "9C37197CA7C2428388C2E6E59B829B30"; -// DNS cache list -static LIST *DnsCache; - // Lock related static LOCK *machine_name_lock = NULL; static LOCK *disconnect_function_lock = NULL; -static LOCK *aho = NULL; -static LOCK *socket_library_lock = NULL; extern LOCK *openssl_lock; -static LOCK *ssl_accept_lock = NULL; -static LOCK *ssl_connect_lock = NULL; static COUNTER *num_tcp_connections = NULL; -static LOCK *dns_lock = NULL; static LOCK *unix_dns_server_addr_lock = NULL; static IP unix_dns_server; -static LIST *HostCacheList = NULL; static LIST *WaitThreadList = NULL; -static bool disable_cache = false; static UCHAR machine_ip_process_hash[SHA1_SIZE]; static LOCK *machine_ip_process_hash_lock = NULL; static LOCK *current_global_ip_lock = NULL; @@ -119,8 +97,6 @@ static LOCK *host_ip_address_list_cache_lock = NULL; static UINT64 host_ip_address_list_cache_last = 0; static LIST *host_ip_address_cache = NULL; static bool disable_gethostname_by_accept = false; -static COUNTER *getip_thread_counter = NULL; -static UINT max_getip_thread = 0; static LIST *ip_clients = NULL; @@ -384,12 +360,6 @@ int GetCurrentTimezone() return ret; } -// Flag of whether to use the DNS proxy -bool IsUseDnsProxy() -{ - return false; -} - // Flag of whether to use an alternate host name bool IsUseAlternativeHostname() { @@ -684,7 +654,7 @@ bool GetIPViaDnsProxyForJapanFlets(IP *ip_ret, char *hostname, bool ipv6, UINT t else { // FLET'S NEXT - if (GetIP4Ex6Ex2(&dns_proxy_ip, dns_proxy_hostname, FLETS_NGN_DNS_QUERY_TIMEOUT, true, cancel, true) == false) + if (GetIP6Ex(&dns_proxy_ip, dns_proxy_hostname, FLETS_NGN_DNS_QUERY_TIMEOUT, cancel) == false) { return false; } @@ -780,7 +750,7 @@ bool GetIPViaDnsProxyForJapanFlets(IP *ip_ret, char *hostname, bool ipv6, UINT t if (ret) { - NewDnsCache(hostname, ip_ret); + DnsCacheUpdate(hostname, ipv6 ? ip_ret : NULL, ipv6 ? NULL : ip_ret); } return ret; @@ -9936,144 +9906,6 @@ bool IsIPv6Supported() #endif // NO_IPV6 } -// Get the host name from the host cache -bool GetHostCache(char *hostname, UINT size, IP *ip) -{ - bool ret; - // Validate arguments - if (hostname == NULL || ip == NULL) - { - return false; - } - - ret = false; - - LockList(HostCacheList); - { - HOSTCACHE t, *c; - Zero(&t, sizeof(t)); - Copy(&t.IpAddress, ip, sizeof(IP)); - - c = Search(HostCacheList, &t); - if (c != NULL) - { - if (IsEmptyStr(c->HostName) == false) - { - ret = true; - StrCpy(hostname, size, c->HostName); - } - else - { - ret = true; - StrCpy(hostname, size, ""); - } - } - } - UnlockList(HostCacheList); - - return ret; -} - -// Add to the host name cache -void AddHostCache(IP *ip, char *hostname) -{ - // Validate arguments - if (ip == NULL || hostname == NULL) - { - return; - } - if (IsNetworkNameCacheEnabled() == false) - { - return; - } - - LockList(HostCacheList); - { - HOSTCACHE t, *c; - UINT i; - LIST *o; - - Zero(&t, sizeof(t)); - Copy(&t.IpAddress, ip, sizeof(IP)); - - c = Search(HostCacheList, &t); - if (c == NULL) - { - c = ZeroMalloc(sizeof(HOSTCACHE)); - Copy(&c->IpAddress, ip, sizeof(IP)); - Add(HostCacheList, c); - } - - StrCpy(c->HostName, sizeof(c->HostName), hostname); - c->Expires = Tick64() + (UINT64)EXPIRES_HOSTNAME; - - o = NewListFast(NULL); - - for (i = 0; i < LIST_NUM(HostCacheList); i++) - { - HOSTCACHE *c = LIST_DATA(HostCacheList, i); - - if (c->Expires <= Tick64()) - { - Add(o, c); - } - } - - for (i = 0; i < LIST_NUM(o); i++) - { - HOSTCACHE *c = LIST_DATA(o, i); - - if (Delete(HostCacheList, c)) - { - Free(c); - } - } - - ReleaseList(o); - } - UnlockList(HostCacheList); -} - -// Comparison of host name cache entries -int CompareHostCache(void *p1, void *p2) -{ - HOSTCACHE *c1, *c2; - if (p1 == NULL || p2 == NULL) - { - return 0; - } - c1 = *(HOSTCACHE **)p1; - c2 = *(HOSTCACHE **)p2; - if (c1 == NULL || c2 == NULL) - { - return 0; - } - - return CmpIpAddr(&c1->IpAddress, &c2->IpAddress); -} - -// Release of the host name cache -void FreeHostCache() -{ - UINT i; - - for (i = 0; i < LIST_NUM(HostCacheList); i++) - { - HOSTCACHE *c = LIST_DATA(HostCacheList, i); - - Free(c); - } - - ReleaseList(HostCacheList); - HostCacheList = NULL; -} - -// Initialization of the host name cache -void InitHostCache() -{ - HostCacheList = NewList(CompareHostCache); -} - // Add the thread to the thread waiting list void AddWaitThread(THREAD *t) { @@ -12008,11 +11840,9 @@ bool StartSSLEx(SOCK *sock, X *x, K *priv, UINT ssl_timeout, char *sni_hostname) { prev_timeout = GetTimeout(sock); SetTimeout(sock, ssl_timeout); - Lock(ssl_connect_lock); // Client mode if (SSL_connect(sock->ssl) <= 0) { - Unlock(ssl_connect_lock); // SSL-connect failure Lock(openssl_lock); { @@ -12027,7 +11857,6 @@ bool StartSSLEx(SOCK *sock, X *x, K *priv, UINT ssl_timeout, char *sni_hostname) FreeSSLCtx(ssl_ctx); return false; } - Unlock(ssl_connect_lock); SetTimeout(sock, prev_timeout); } @@ -14140,7 +13969,7 @@ SOCK *ConnectEx4(char *hostname, UINT port, UINT timeout, bool *cancel_flag, cha else { // Forward resolution - if (GetIP46Ex(&ip4, &ip6, hostname_original, 0, cancel_flag) == false) + if (DnsResolve(&ip6, &ip4, hostname_original, 0, cancel_flag) == false) { return NULL; } @@ -15183,191 +15012,26 @@ void GetMachineNameEx(char *name, UINT size, bool no_load_hosts) Unlock(machine_name_lock); } -// Host name acquisition thread -void GetHostNameThread(THREAD *t, void *p) -{ - IP *ip; - char hostname[256]; - // Validate arguments - if (t == NULL || p == NULL) - { - return; - } - - ip = (IP *)p; - - AddWaitThread(t); - - NoticeThreadInit(t); - - if (GetHostNameInner(hostname, sizeof(hostname), ip)) - { - AddHostCache(ip, hostname); - } - - Free(ip); - - DelWaitThread(t); -} - // Get the host name bool GetHostName(char *hostname, UINT size, IP *ip) { - THREAD *t; - IP *p_ip; - bool ret; - // Validate arguments - if (hostname == NULL || ip == NULL) + if (hostname == NULL || size == 0 || ip == NULL) { return false; } - if (GetHostCache(hostname, size, ip)) + if (DnsResolveReverse(hostname, size, ip, 0, NULL)) { - if (IsEmptyStr(hostname) == false) - { - return true; - } - else - { - return false; - } + return true; } - p_ip = ZeroMalloc(sizeof(IP)); - Copy(p_ip, ip, sizeof(IP)); - - t = NewThread(GetHostNameThread, p_ip); - - WaitThreadInit(t); - - WaitThread(t, TIMEOUT_HOSTNAME); - - ReleaseThread(t); - - ret = GetHostCache(hostname, size, ip); - if (ret == false) + if (IsIP4(ip) && GetNetBiosName(hostname, size, ip)) { - if (IsIP4(ip)) - { - ret = GetNetBiosName(hostname, size, ip); - if (ret) - { - AddHostCache(ip, hostname); - } - } - } - else - { - if (IsEmptyStr(hostname)) - { - ret = false; - } - } - if (ret == false) - { - AddHostCache(ip, ""); - StrCpy(hostname, size, ""); + DnsCacheReverseUpdate(ip, hostname); + return true; } - return ret; -} - -// Perform a DNS reverse query -bool GetHostNameInner(char *hostname, UINT size, IP *ip) -{ - struct in_addr addr; - struct sockaddr_in sa; - char tmp[MAX_SIZE]; - char ip_str[64]; - // Validate arguments - if (hostname == NULL || ip == NULL) - { - return false; - } - - if (IsIP6(ip)) - { - return GetHostNameInner6(hostname, size, ip); - } - - // Reverse resolution - IPToInAddr(&addr, ip); - Zero(&sa, sizeof(sa)); - sa.sin_family = AF_INET; - -#if defined(UNIX_BSD) || defined(UNIX_MACOS) - sa.sin_len = INET_ADDRSTRLEN; -#endif // UNIX_BSD || UNIX_MACOS - - Copy(&sa.sin_addr, &addr, sizeof(struct in_addr)); - sa.sin_port = 0; - - if (getnameinfo((struct sockaddr *)&sa, sizeof(sa), tmp, sizeof(tmp), NULL, 0, 0) != 0) - { - return false; - } - - IPToStr(ip_str, sizeof(ip_str), ip); - - if (StrCmpi(tmp, ip_str) == 0) - { - return false; - } - - if (IsEmptyStr(tmp)) - { - return false; - } - - StrCpy(hostname, size, tmp); - - return true; -} -bool GetHostNameInner6(char *hostname, UINT size, IP *ip) -{ - struct in6_addr addr; - struct sockaddr_in6 sa; - char tmp[MAX_SIZE]; - char ip_str[256]; - // Validate arguments - if (hostname == NULL || ip == NULL) - { - return false; - } - - // Reverse resolution - IPToInAddr6(&addr, ip); - Zero(&sa, sizeof(sa)); - sa.sin6_family = AF_INET6; - -#if defined(UNIX_BSD) || defined(UNIX_MACOS) - sa.sin6_len = INET6_ADDRSTRLEN; -#endif // UNIX_BSD || UNIX_MACOS - - Copy(&sa.sin6_addr, &addr, sizeof(struct in6_addr)); - sa.sin6_port = 0; - - if (getnameinfo((struct sockaddr *)&sa, sizeof(sa), tmp, sizeof(tmp), NULL, 0, 0) != 0) - { - return false; - } - - IPToStr(ip_str, sizeof(ip_str), ip); - - if (StrCmpi(tmp, ip_str) == 0) - { - return false; - } - - if (IsEmptyStr(tmp)) - { - return false; - } - - StrCpy(hostname, size, tmp); - - return true; + return false; } #define NUM_NBT_QUERYS_SEND 3 @@ -15538,572 +15202,6 @@ UINT SetIP32(UCHAR a1, UCHAR a2, UCHAR a3, UCHAR a4) return IPToUINT(&ip); } -// Obtain in both v4 and v6 results with a DNS forward lookup -bool GetIP46Ex(IP *ip4, IP *ip6, char *hostname, UINT timeout, bool *cancel) -{ - IP a, b; - bool ok_a, ok_b; - // Validate arguments - if (ip4 == NULL || ip6 == NULL || hostname == NULL) - { - return false; - } - - ZeroIP4(ip4); - Zero(ip6, sizeof(IP)); - - ok_a = ok_b = false; - - if (GetIP6Ex(&a, hostname, timeout, cancel)) - { - ok_a = true; - } - - if (GetIP4Ex(&b, hostname, timeout, cancel)) - { - ok_b = true; - } - - if (ok_a) - { - if (IsIP4(&a)) - { - Copy(ip4, &a, sizeof(IP)); - } - } - if (ok_b) - { - if (IsIP4(&b)) - { - Copy(ip4, &b, sizeof(IP)); - } - - if (IsIP6(&b)) - { - Copy(ip6, &b, sizeof(IP)); - } - } - if (ok_a) - { - if (IsIP6(&a)) - { - Copy(ip6, &a, sizeof(IP)); - } - } - - if (IsZeroIp(ip4) && IsZeroIp(ip6)) - { - return false; - } - - return true; -} - -// Clean-up of the parameters for GetIP thread -void CleanupGetIPThreadParam(GETIP_THREAD_PARAM *p) -{ - // Validate arguments - if (p == NULL) - { - return; - } - - Free(p); -} - -// Release of the parameters of the GetIP for thread -void ReleaseGetIPThreadParam(GETIP_THREAD_PARAM *p) -{ - // Validate arguments - if (p == NULL) - { - return; - } - - if (Release(p->Ref) == 0) - { - CleanupGetIPThreadParam(p); - } -} - -// Thread to perform to query the DNS forward lookup (with timeout) -void GetIP4Ex6ExThread(THREAD *t, void *param) -{ - GETIP_THREAD_PARAM *p; - // Validate arguments - if (t == NULL || param == NULL) - { - return; - } - - p = (GETIP_THREAD_PARAM *)param; - - AddRef(p->Ref); - - NoticeThreadInit(t); - - AddWaitThread(t); - - // Execution of resolution - if (p->IPv6 == false) - { - // IPv4 - p->Ok = GetIP4Inner(&p->Ip, p->HostName); - } - else - { - // IPv6 - p->Ok = GetIP6Inner(&p->Ip, p->HostName); - } - - ReleaseGetIPThreadParam(p); - - DelWaitThread(t); - - Dec(getip_thread_counter); -} - -// Perform a forward DNS query (with timeout) -bool GetIP4Ex6Ex(IP *ip, char *hostname_arg, UINT timeout, bool ipv6, bool *cancel) -{ - return GetIP4Ex6Ex2(ip, hostname_arg, timeout, ipv6, cancel, false); -} -bool GetIP4Ex6Ex2(IP *ip, char *hostname_arg, UINT timeout, bool ipv6, bool *cancel, bool only_direct_dns) -{ - GETIP_THREAD_PARAM *p; - THREAD *t; - bool ret = false; - UINT64 start_tick = 0; - UINT64 end_tick = 0; - UINT64 spent_time = 0; - UINT64 now; - UINT n; - bool use_dns_proxy = false; - char hostname[260]; - UINT i; - bool timed_out; - // Validate arguments - if (ip == NULL || hostname_arg == NULL) - { - return false; - } - if (timeout == 0) - { - timeout = TIMEOUT_GETIP; - } - - Zero(hostname, sizeof(hostname)); - StrCpy(hostname, sizeof(hostname), hostname_arg); - - i = SearchStrEx(hostname, "/", 0, true); - if (i != INFINITE) - { - hostname[i] = 0; - } - - if (ipv6 == false) - { - IP ip2; - - if (StrToIP(&ip2, hostname) && IsZeroIp(&ip2) == false) - { - if (IsIP4(&ip2)) - { - // IPv4 address direct specification - Copy(ip, &ip2, sizeof(IP)); - return true; - } - else - { - // IPv6 address direct specification - return false; - } - } - } - else - { - IP ip2; - - if (StrToIP(&ip2, hostname) && IsZeroIp(&ip2) == false) - { - if (IsIP6(&ip2)) - { - // IPv6 address direct specification - Copy(ip, &ip2, sizeof(IP)); - return true; - } - else - { - // IPv4 address direct specification - return false; - } - } - } - - if (only_direct_dns == false) - { - if (ipv6 == false) - { - if (IsUseDnsProxy()) - { - use_dns_proxy = true; - } - } - } - - - // check the quota - start_tick = Tick64(); - end_tick = start_tick + (UINT64)timeout; - - n = 0; - - timed_out = false; - - while (true) - { - UINT64 now = Tick64(); - UINT64 remain; - UINT remain32; - - if (GetGetIpThreadMaxNum() > GetCurrentGetIpThreadNum()) - { - // below the quota - break; - } - - if (now >= end_tick) - { - // timeouted - timed_out = true; - break; - } - - if (cancel != NULL && (*cancel)) - { - // cancelled - timed_out = true; - break; - } - - remain = end_tick - now; - remain32 = MIN((UINT)remain, 100); - - SleepThread(remain32); - n++; - } - - now = Tick64(); - spent_time = now - start_tick; - - if (n == 0) - { - spent_time = 0; - } - - if ((UINT)spent_time >= timeout) - { - timed_out = true; - } - - if (timed_out) - { - IP ip2; - - // timed out, cancelled - if (QueryDnsCache(&ip2, hostname)) - { - ret = true; - - Copy(ip, &ip2, sizeof(IP)); - } - - Debug("GetIP4Ex6Ex2: Worker thread quota exceeded: max=%u current=%u\n", - GetGetIpThreadMaxNum(), GetCurrentGetIpThreadNum()); - - return ret; - } - - // Increment the counter - Inc(getip_thread_counter); - - if (spent_time != 0) - { - Debug("GetIP4Ex6Ex2: Waited for %u msecs to create a worker thread.\n", - spent_time); - } - - timeout -= (UINT)spent_time; - - p = ZeroMalloc(sizeof(GETIP_THREAD_PARAM)); - p->Ref = NewRef(); - StrCpy(p->HostName, sizeof(p->HostName), hostname); - p->IPv6 = ipv6; - p->Timeout = timeout; - p->Ok = false; - - t = NewThread(GetIP4Ex6ExThread, p); - WaitThreadInit(t); - - if (cancel == NULL) - { - WaitThread(t, timeout); - } - else - { - start_tick = Tick64(); - end_tick = start_tick + (UINT64)timeout; - - while (true) - { - UINT64 now = Tick64(); - UINT64 remain; - UINT remain32; - - if (*cancel) - { - break; - } - - if (now >= end_tick) - { - break; - } - - remain = end_tick - now; - remain32 = MIN((UINT)remain, 100); - - if (WaitThread(t, remain32)) - { - break; - } - } - } - - ReleaseThread(t); - - if (p->Ok) - { - ret = true; - Copy(ip, &p->Ip, sizeof(IP)); - } - else - { - IP ip2; - -#if 0 - if (only_direct_dns == false) - { - if (ipv6) - { - UINT flets_type = DetectFletsType(); - - // if I'm in the FLETs of NTT East, - // try to get an IP address using the DNS proxy server - if ((flets_type & FLETS_DETECT_TYPE_EAST_BFLETS_PRIVATE) && - GetIPViaDnsProxyForJapanFlets(ip, hostname, true, 0, cancel, NULL)) - { - // B FLETs - ret = true; - } - else if ((flets_type & FLETS_DETECT_TYPE_EAST_NGN_PRIVATE) && - GetIPViaDnsProxyForJapanFlets(ip, hostname, true, 0, cancel, FLETS_NGN_EAST_DNS_PROXY_HOSTNAME)) - { - // FLET'S Hikar-Next (NTT East) - ret = true; - } - else if ((flets_type & FLETS_DETECT_TYPE_WEST_NGN_PRIVATE) && - GetIPViaDnsProxyForJapanFlets(ip, hostname, true, 0, cancel, FLETS_NGN_WEST_DNS_PROXY_HOSTNAME)) - { - // FLET'S Hikar-Next (NTT West) - ret = true; - } - } - } -#endif - - if (QueryDnsCache(&ip2, hostname)) - { - ret = true; - - Copy(ip, &ip2, sizeof(IP)); - } - } - - - ReleaseGetIPThreadParam(p); - - return ret; -} -bool GetIP4Ex(IP *ip, char *hostname, UINT timeout, bool *cancel) -{ - return GetIP4Ex6Ex(ip, hostname, timeout, false, cancel); -} -bool GetIP6Ex(IP *ip, char *hostname, UINT timeout, bool *cancel) -{ - return GetIP4Ex6Ex(ip, hostname, timeout, true, cancel); -} -bool GetIP4(IP *ip, char *hostname) -{ - return GetIP4Ex(ip, hostname, 0, NULL); -} -bool GetIP6(IP *ip, char *hostname) -{ - return GetIP6Ex(ip, hostname, 0, NULL); -} - -// Perform a DNS forward lookup query -bool GetIP(IP *ip, char *hostname) -{ - return GetIPEx(ip, hostname, false); -} -bool GetIPEx(IP *ip, char *hostname, bool ipv6) -{ - if (ipv6 == false) - { - return GetIP4(ip, hostname); - } - else - { - return GetIP6(ip, hostname); - } -} -bool GetIP6Inner(IP *ip, char *hostname) -{ - struct sockaddr_in6 in; - struct in6_addr addr; - struct addrinfo hint; - struct addrinfo *info; - // Validate arguments - if (ip == NULL || hostname == NULL) - { - return false; - } - - if (IsEmptyStr(hostname)) - { - return false; - } - - if (StrCmpi(hostname, "localhost") == 0) - { - GetLocalHostIP6(ip); - return true; - } - - if (StrToIP6(ip, hostname) == false && StrToIP(ip, hostname) == false) - { - // Forward resolution - Zero(&hint, sizeof(hint)); - hint.ai_family = AF_INET6; - hint.ai_socktype = SOCK_STREAM; - hint.ai_protocol = IPPROTO_TCP; - info = NULL; - - if (getaddrinfo(hostname, NULL, &hint, &info) != 0 || - info->ai_family != AF_INET6) - { - if (info) - { - freeaddrinfo(info); - } - return QueryDnsCacheEx(ip, hostname, true); - } - // Forward resolution success - Copy(&in, info->ai_addr, sizeof(struct sockaddr_in6)); - freeaddrinfo(info); - - Copy(&addr, &in.sin6_addr, sizeof(addr)); - InAddrToIP6(ip, &addr); - } - - // Save Cache - NewDnsCache(hostname, ip); - - return true; -} -bool GetIP4Inner(IP *ip, char *hostname) -{ - struct sockaddr_in in; - struct in_addr addr; - struct addrinfo hint; - struct addrinfo *info; - // Validate arguments - if (ip == NULL || hostname == NULL) - { - return false; - } - - if (IsEmptyStr(hostname)) - { - return false; - } - - if (StrCmpi(hostname, "localhost") == 0) - { - SetIP(ip, 127, 0, 0, 1); - return true; - } - - if (StrToIP6(ip, hostname) == false && StrToIP(ip, hostname) == false) - { - // Forward resolution - Zero(&hint, sizeof(hint)); - hint.ai_family = AF_INET; - hint.ai_socktype = SOCK_STREAM; - hint.ai_protocol = IPPROTO_TCP; - info = NULL; - - if (getaddrinfo(hostname, NULL, &hint, &info) != 0 || - info->ai_family != AF_INET) - { - if (info) - { - freeaddrinfo(info); - } - return QueryDnsCache(ip, hostname); - } - // Forward resolution success - Copy(&in, info->ai_addr, sizeof(struct sockaddr_in)); - freeaddrinfo(info); - Copy(&addr, &in.sin_addr, sizeof(addr)); - InAddrToIP(ip, &addr); - } - - // Save Cache - NewDnsCache(hostname, ip); - - return true; -} - -// Search in the DNS cache -bool QueryDnsCache(IP *ip, char *hostname) -{ - return QueryDnsCacheEx(ip, hostname, false); -} -bool QueryDnsCacheEx(IP *ip, char *hostname, bool ipv6) -{ - DNSCACHE *c; - char tmp[MAX_SIZE]; - // Validate arguments - if (ip == NULL || hostname == NULL) - { - return false; - } - - GenDnsCacheKeyName(tmp, sizeof(tmp), hostname, ipv6); - - c = FindDnsCache(tmp); - if (c == NULL) - { - return false; - } - - Copy(ip, &c->IpAddress, sizeof(IP)); - - return true; -} - // Convert the IP to a string void IPToUniStr(wchar_t *str, UINT size, IP *ip) { @@ -16332,160 +15430,6 @@ void InAddrToIP6(IP *ip, struct in6_addr *addr) } } -// Search in the DNS cache -DNSCACHE *FindDnsCache(char *hostname) -{ - return FindDnsCacheEx(hostname, false); -} -DNSCACHE *FindDnsCacheEx(char *hostname, bool ipv6) -{ - DNSCACHE *c; - char tmp[MAX_SIZE]; - if (hostname == NULL) - { - return NULL; - } - - GenDnsCacheKeyName(tmp, sizeof(tmp), hostname, ipv6); - - LockDnsCache(); - { - DNSCACHE t; - t.HostName = tmp; - c = Search(DnsCache, &t); - } - UnlockDnsCache(); - - return c; -} - -// Generate the IPv4 / IPv6 key name for the DNS cache -void GenDnsCacheKeyName(char *dst, UINT size, char *src, bool ipv6) -{ - // Validate arguments - if (dst == NULL || src == NULL) - { - return; - } - - if (ipv6 == false) - { - StrCpy(dst, size, src); - } - else - { - Format(dst, size, "%s@ipv6", src); - } -} - -// Registration of the new DNS cache -void NewDnsCache(char *hostname, IP *ip) -{ - NewDnsCacheEx(hostname, ip, IsIP6(ip)); -} -void NewDnsCacheEx(char *hostname, IP *ip, bool ipv6) -{ - DNSCACHE *c; - char tmp[MAX_PATH]; - // Validate arguments - if (hostname == NULL || ip == NULL) - { - return; - } - - if (IsNetworkNameCacheEnabled() == false) - { - return; - } - - GenDnsCacheKeyName(tmp, sizeof(tmp), hostname, ipv6); - - LockDnsCache(); - { - DNSCACHE t; - - // Search for anything matches to the hostname first - t.HostName = tmp; - c = Search(DnsCache, &t); - - if (c == NULL) - { - // Newly register - c = ZeroMalloc(sizeof(DNSCACHE)); - c->HostName = CopyStr(tmp); - - Copy(&c->IpAddress, ip, sizeof(IP)); - - Add(DnsCache, c); - } - else - { - // Update - Copy(&c->IpAddress, ip, sizeof(IP)); - } - } - UnlockDnsCache(); -} - -// Name comparison of the DNS cache entries -int CompareDnsCache(void *p1, void *p2) -{ - DNSCACHE *c1, *c2; - if (p1 == NULL || p2 == NULL) - { - return 0; - } - c1 = *(DNSCACHE **)p1; - c2 = *(DNSCACHE **)p2; - if (c1 == NULL || c2 == NULL) - { - return 0; - } - - return StrCmpi(c1->HostName, c2->HostName); -} - -// Initialization of the DNS cache -void InitDnsCache() -{ - // Creating a List - DnsCache = NewList(CompareDnsCache); -} - -// Release of the DNS cache -void FreeDnsCache() -{ - LockDnsCache(); - { - DNSCACHE *c; - UINT i; - for (i = 0; i < LIST_NUM(DnsCache); i++) - { - // Release the memory for the entry - c = LIST_DATA(DnsCache, i); - Free(c->HostName); - Free(c); - } - } - UnlockDnsCache(); - - // Release the list - ReleaseList(DnsCache); - DnsCache = NULL; -} - -// Lock the DNS cache -void LockDnsCache() -{ - LockList(DnsCache); -} - -// Unlock the DNS cache -void UnlockDnsCache() -{ - UnlockList(DnsCache); -} - // DH temp key callback DH *TmpDhCallback(SSL *ssl, int is_export, int keylength) { @@ -16572,27 +15516,6 @@ UINT GetOSSecurityLevel() return security_level_set_ssl_version; } -// The number of get ip threads -void SetGetIpThreadMaxNum(UINT num) -{ - max_getip_thread = num; -} -UINT GetGetIpThreadMaxNum() -{ - UINT ret = max_getip_thread; - - if (ret == 0) - { - ret = 0x7FFFFFFF; - } - - return ret; -} -UINT GetCurrentGetIpThreadNum() -{ - return Count(getip_thread_counter); -} - // Initialize the network communication module void InitNetwork() { @@ -16607,17 +15530,12 @@ void InitNetwork() num_tcp_connections = NewCounter(); - getip_thread_counter = NewCounter(); - // Initialization of client list InitIpClientList(); // Thread related initialization InitWaitThread(); - // Initialization of the host name cache - InitHostCache(); - #ifdef OS_WIN32 // Initializing the socket library Win32InitSocketLibrary(); @@ -16625,18 +15543,12 @@ void InitNetwork() UnixInitSocketLibrary(); #endif // OS_WIN32 - // Initialization of the DNS cache - InitDnsCache(); + DnsInit(); // Locking initialization machine_name_lock = NewLock(); disconnect_function_lock = NewLock(); - aho = NewLock(); machine_ip_process_hash_lock = NewLock(); - socket_library_lock = NewLock(); - //ssl_connect_lock = NewLock(); //2012.9.28 Not required for recent OpenSSL -// ssl_accept_lock = NewLock(); - dns_lock = NewLock(); unix_dns_server_addr_lock = NewLock(); Zero(&unix_dns_server, sizeof(unix_dns_server)); local_mac_list_lock = NewLock(); @@ -16645,29 +15557,7 @@ void InitNetwork() current_fqdn_lock = NewLock(); current_global_ip_set = false; - disable_cache = false; - Zero(rand_port_numbers, sizeof(rand_port_numbers)); - - SetGetIpThreadMaxNum(DEFAULT_GETIP_THREAD_MAX_NUM); -} - -// Enable the network name cache -void EnableNetworkNameCache() -{ - disable_cache = false; -} - -// Disable the network name cache -void DisableNetworkNameCache() -{ - disable_cache = true; -} - -// Get whether the network name cache is enabled -bool IsNetworkNameCacheEnabled() -{ - return !disable_cache; } // Get the cipher algorithm list @@ -17121,23 +16011,12 @@ void FreeNetwork() // Release the locks DeleteLock(unix_dns_server_addr_lock); - DeleteLock(dns_lock); - DeleteLock(ssl_accept_lock); DeleteLock(machine_name_lock); DeleteLock(disconnect_function_lock); - DeleteLock(aho); - DeleteLock(socket_library_lock); - DeleteLock(ssl_connect_lock); DeleteLock(machine_ip_process_hash_lock); - machine_name_lock = NULL; - ssl_accept_lock = machine_name_lock = disconnect_function_lock = - aho = socket_library_lock = ssl_connect_lock = machine_ip_process_hash_lock = NULL; + machine_name_lock = disconnect_function_lock = machine_ip_process_hash_lock = NULL; - // Release of the DNS cache - FreeDnsCache(); - - // Release of the host name cache - FreeHostCache(); + DnsFree(); #ifdef OS_WIN32 // Release of the socket library @@ -17174,12 +16053,7 @@ void FreeNetwork() FreeHostIPAddressList(host_ip_address_cache); host_ip_address_cache = NULL; - FreeDynList(); - - DeleteCounter(getip_thread_counter); - getip_thread_counter = NULL; - } // Stop all the sockets in the list and delete it diff --git a/src/Mayaqua/Network.h b/src/Mayaqua/Network.h index 5fbffd36..b8faee9c 100644 --- a/src/Mayaqua/Network.h +++ b/src/Mayaqua/Network.h @@ -27,20 +27,14 @@ struct DYN_VALUE #define MAX_HOST_NAME_LEN 255 // Maximum length of the host name -#define TIMEOUT_GETIP 2300 - #define TIMEOUT_INFINITE (0x7fffffff) #define TIMEOUT_TCP_PORT_CHECK (10 * 1000) #define TIMEOUT_SSL_CONNECT (15 * 1000) -#define TIMEOUT_HOSTNAME (500) #define TIMEOUT_NETBIOS_HOSTNAME (100) -#define EXPIRES_HOSTNAME (10 * 60 * 1000) #define SOCKET_BUFFER_SIZE 0x10000000 -#define IPV6_DUMMY_FOR_IPV4 0xFEFFFFDF - #define UDPLISTENER_CHECK_INTERVAL 1000ULL #define UDPLISTENER_WAIT_INTERVAL 1234 @@ -48,12 +42,6 @@ struct DYN_VALUE #define MAX_NUM_IGNORE_ERRORS 1024 -#ifndef USE_STRATEGY_LOW_MEMORY -#define DEFAULT_GETIP_THREAD_MAX_NUM 512 -#else // USE_STRATEGY_LOW_MEMORY -#define DEFAULT_GETIP_THREAD_MAX_NUM 64 -#endif // USE_STRATEGY_LOW_MEMORY - #define DEFAULT_CIPHER_LIST "ECDHE+AESGCM:ECDHE+CHACHA20:DHE+AESGCM:DHE+CHACHA20:ECDHE+AES256:DHE+AES256:RSA+AES" // SSL logging function @@ -115,14 +103,6 @@ struct IPV6_ADDR #define IPV6_ADDR_ZERO 128 // All zeros #define IPV6_ADDR_LOOPBACK 256 // Loop-back - -// DNS cache list -struct DNSCACHE -{ - char *HostName; - IP IpAddress; -}; - // Client list struct IP_CLIENT { @@ -328,15 +308,6 @@ struct ICMP_RESULT IP IpAddress; // IP address }; - -// Host name cache list -typedef struct HOSTCACHE -{ - UINT64 Expires; // Expiration - IP IpAddress; // IP address - char HostName[256]; // Host name -} HOSTCACHE; - // NETBIOS name requests typedef struct NBTREQUEST { @@ -376,17 +347,6 @@ typedef struct SOCKET_TIMEOUT_PARAM { bool unblocked; } SOCKET_TIMEOUT_PARAM; -// Parameters for GetIP thread -struct GETIP_THREAD_PARAM -{ - REF *Ref; - char HostName[MAX_PATH]; - bool IPv6; - UINT Timeout; - IP Ip; - bool Ok; -}; - // Parameters for the IP address release thread struct WIN32_RELEASEADDRESS_THREAD_PARAM { @@ -900,7 +860,6 @@ bool GetSniNameFromSslPacket(UCHAR *packet_buf, UINT packet_size, char *sni, UIN void SetDhParam(DH_CTX *dh); -bool IsUseDnsProxy(); bool IsUseAlternativeHostname(); #ifdef OS_WIN32 @@ -1066,18 +1025,7 @@ void UnixSetSocketNonBlockingMode(int fd, bool nonblock); // Function prototype void InitNetwork(); void FreeNetwork(); -void InitDnsCache(); -void FreeDnsCache(); -void LockDnsCache(); -void UnlockDnsCache(); -int CompareDnsCache(void *p1, void *p2); -void GenDnsCacheKeyName(char *dst, UINT size, char *src, bool ipv6); -void NewDnsCacheEx(char *hostname, IP *ip, bool ipv6); -DNSCACHE *FindDnsCacheEx(char *hostname, bool ipv6); -bool QueryDnsCacheEx(IP *ip, char *hostname, bool ipv6); -void NewDnsCache(char *hostname, IP *ip); -DNSCACHE *FindDnsCache(char *hostname); -bool QueryDnsCache(IP *ip, char *hostname); + void InAddrToIP(IP *ip, struct in_addr *addr); void InAddrToIP6(IP *ip, struct in6_addr *addr); void IPToInAddr(struct in_addr *addr, IP *ip); @@ -1090,24 +1038,7 @@ void IPToStr32(char *str, UINT size, UINT ip); void IPToStr4or6(char *str, UINT size, UINT ip_4_uint, UCHAR *ip_6_bytes); void IPToUniStr(wchar_t *str, UINT size, IP *ip); void IPToUniStr32(wchar_t *str, UINT size, UINT ip); -bool GetIPEx(IP *ip, char *hostname, bool ipv6); -bool GetIP46Ex(IP *ip4, IP *ip6, char *hostname, UINT timeout, bool *cancel); -bool GetIP(IP *ip, char *hostname); -bool GetIP4(IP *ip, char *hostname); -bool GetIP6(IP *ip, char *hostname); -bool GetIP4Ex(IP *ip, char *hostname, UINT timeout, bool *cancel); -bool GetIP6Ex(IP *ip, char *hostname, UINT timeout, bool *cancel); -bool GetIP4Ex6Ex(IP *ip, char *hostname, UINT timeout, bool ipv6, bool *cancel); -bool GetIP4Ex6Ex2(IP *ip, char *hostname, UINT timeout, bool ipv6, bool *cancel, bool only_direct_dns); -void GetIP4Ex6ExThread(THREAD *t, void *param); -void ReleaseGetIPThreadParam(GETIP_THREAD_PARAM *p); -void CleanupGetIPThreadParam(GETIP_THREAD_PARAM *p); -bool GetIP4Inner(IP *ip, char *hostname); -bool GetIP6Inner(IP *ip, char *hostname); -bool GetHostNameInner(char *hostname, UINT size, IP *ip); -bool GetHostNameInner6(char *hostname, UINT size, IP *ip); bool GetHostName(char *hostname, UINT size, IP *ip); -void GetHostNameThread(THREAD *t, void *p); void GetMachineName(char *name, UINT size); void GetMachineNameEx(char *name, UINT size, bool no_load_hosts); bool GetMachineNameFromHosts(char *name, UINT size); @@ -1212,11 +1143,6 @@ void InitWaitThread(); void FreeWaitThread(); void AddWaitThread(THREAD *t); void DelWaitThread(THREAD *t); -void InitHostCache(); -void FreeHostCache(); -int CompareHostCache(void *p1, void *p2); -void AddHostCache(IP *ip, char *hostname); -bool GetHostCache(char *hostname, UINT size, IP *ip); bool IsSubnetMask(IP *ip); bool IsSubnetMask4(IP *ip); bool IsSubnetMask32(UINT ip); @@ -1245,9 +1171,6 @@ IP_CLIENT *SearchIpClient(IP *ip); UINT GetNumIpClient(IP *ip); void SetLinuxArpFilter(); int connect_timeout(SOCKET s, struct sockaddr *addr, int size, int timeout, bool *cancel_flag); -void EnableNetworkNameCache(); -void DisableNetworkNameCache(); -bool IsNetworkNameCacheEnabled(); ROUTE_CHANGE *NewRouteChange(); void FreeRouteChange(ROUTE_CHANGE *r); bool IsRouteChanged(ROUTE_CHANGE *r); @@ -1466,10 +1389,6 @@ QUERYIPTHREAD *NewQueryIpThread(char *hostname, UINT interval_last_ok, UINT inte bool GetQueryIpThreadResult(QUERYIPTHREAD *t, IP *ip); void FreeQueryIpThread(QUERYIPTHREAD *t); -void SetGetIpThreadMaxNum(UINT num); -UINT GetGetIpThreadMaxNum(); -UINT GetCurrentGetIpThreadNum(); - #ifdef OS_WIN32 LIST *Win32GetNicList(); #endif // OS_WIN32 diff --git a/src/Mayaqua/Proxy.c b/src/Mayaqua/Proxy.c index ad599f77..9636a5a2 100644 --- a/src/Mayaqua/Proxy.c +++ b/src/Mayaqua/Proxy.c @@ -3,6 +3,7 @@ // TODO: Mayaqua should not depend on Cedar. #include "Cedar/WinUi.h" +#include "DNS.h" #include "Memory.h" #include "Str.h" @@ -550,8 +551,8 @@ UINT ProxySocks4Connect(PROXY_PARAM_OUT *out, PROXY_PARAM_IN *in, volatile bool Zero(out, sizeof(PROXY_PARAM_OUT)); - // Get the IP address of the destination server - if (GetIP(&target_ip, in->TargetHostname) == false) + // Get the IPv4 address of the destination server (SOCKS4 does not support IPv6). + if (GetIP4(&target_ip, in->TargetHostname) == false) { return PROXY_ERROR_CONNECTION; } diff --git a/src/Mayaqua/Table.c b/src/Mayaqua/Table.c index 5d3bba84..b2f55ecf 100644 --- a/src/Mayaqua/Table.c +++ b/src/Mayaqua/Table.c @@ -8,6 +8,7 @@ #include "Table.h" #include "Cfg.h" +#include "DNS.h" #include "FileIO.h" #include "Internat.h" #include "Mayaqua.h" @@ -1206,9 +1207,9 @@ bool LoadUnicodeCache(wchar_t *strfilename, UINT strfilesize, UCHAR *hash) Zero(&c, sizeof(c)); UniToStr(c.StrFileName, sizeof(c.StrFileName), strfilename); c.StrFileSize = strfilesize; - DisableNetworkNameCache(); + DnsCacheToggle(false); GetMachineName(c.MachineName, sizeof(c.MachineName)); - EnableNetworkNameCache(); + DnsCacheToggle(true); c.OsType = GetOsInfo()->OsType; Copy(c.hash, hash, MD5_SIZE);