//SHA-1 hash function bool __fastcall SHA1_Hash( FILE *Input) { //Parameters check if (HashFamilyID != HASH_ID_SHA1 || Input == nullptr) { fwprintf_s(stderr, L"Parameters error.\n"); return false; } //Initialization std::shared_ptr<char> Buffer(new char[FILE_BUFFER_SIZE]()), StringBuffer(new char[FILE_BUFFER_SIZE]()); auto HashInstance = std::make_shared<SHA1_State>(); memset(Buffer.get(), 0, FILE_BUFFER_SIZE); memset(StringBuffer.get(), 0, FILE_BUFFER_SIZE); memset(HashInstance.get(), 0, sizeof(SHA1_State)); size_t ReadLength = 0; //SHA-1 initialization SHA1_Init(HashInstance.get()); //Hash process while (!feof(Input)) { memset(Buffer.get(), 0, FILE_BUFFER_SIZE); ReadLength = fread_s(Buffer.get(), FILE_BUFFER_SIZE, sizeof(char), FILE_BUFFER_SIZE, Input); if (ReadLength == 0 && errno == EINVAL) { fwprintf_s(stderr, L"Hash process error.\n"); return false; } else { SHA1_Process(HashInstance.get(), (uint8_t *)Buffer.get(), (unsigned long)ReadLength); } } //Binary to hex memset(Buffer.get(), 0, FILE_BUFFER_SIZE); SHA1_Done(HashInstance.get(), (uint8_t *)Buffer.get()); if (sodium_bin2hex(StringBuffer.get(), FILE_BUFFER_SIZE, (const unsigned char *)Buffer.get(), SHA1_SIZE_DIGEST) == nullptr) { fwprintf_s(stderr, L"Convert binary to hex error.\n"); return false; } else { //Print to screen. std::string HashResult = StringBuffer.get(); CaseConvert(true, HashResult); for (size_t Index = 0;Index < HashResult.length();++Index) fwprintf_s(stderr, L"%c", HashResult.c_str()[Index]); fwprintf_s(stderr, L"\n"); } return true; }
int wmain( _In_ int argc, _In_ wchar_t* argv[]) { #elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX)) int main(int argc, char *argv[]) { #endif #if defined(ENABLE_LIBSODIUM) //Libsodium initialization if (sodium_init() != EXIT_SUCCESS) { wprintf_s(L"Libsodium initialization error\n"); #if defined(PLATFORM_WIN) system("Pause"); #endif return EXIT_FAILURE; } FILE *Output = nullptr; //Output. #if defined(PLATFORM_WIN) _wfopen_s(&Output, L"KeyPair.txt", L"w+,ccs=UTF-8"); #elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX)) Output = fopen("KeyPair.txt", "w+"); #endif if (Output != nullptr) { //Initialization and make keypair. size_t Index = 0; std::shared_ptr<char> Buffer(new char[KEYPAIR_MESSAGE_LEN]()); std::shared_ptr<uint8_t> PublicKey(new uint8_t[crypto_box_PUBLICKEYBYTES]()), SecretKey(new uint8_t[crypto_box_SECRETKEYBYTES]()); memset(Buffer.get(), 0, KEYPAIR_MESSAGE_LEN); memset(PublicKey.get(), 0, crypto_box_PUBLICKEYBYTES); memset(SecretKey.get(), 0, crypto_box_SECRETKEYBYTES); crypto_box_keypair(PublicKey.get(), SecretKey.get()); //Write public key. memset(Buffer.get(), 0, KEYPAIR_MESSAGE_LEN); if (sodium_bin2hex(Buffer.get(), KEYPAIR_MESSAGE_LEN, PublicKey.get(), crypto_box_PUBLICKEYBYTES) == nullptr) wprintf_s(L"Create ramdom key pair failed, please try again.\n"); CaseConvert(true, Buffer.get(), KEYPAIR_MESSAGE_LEN); fwprintf_s(Output, L"Client Public Key = "); for (Index = 0;Index < strnlen_s(Buffer.get(), KEYPAIR_MESSAGE_LEN);++Index) { if (Index > 0 && Index % KEYPAIR_INTERVAL == 0 && Index + 1U < strnlen_s(Buffer.get(), KEYPAIR_MESSAGE_LEN)) fwprintf_s(Output, L":"); fwprintf_s(Output, L"%c", Buffer.get()[Index]); } memset(Buffer.get(), 0, KEYPAIR_MESSAGE_LEN); fwprintf_s(Output, L"\n"); //Write secret key. if (sodium_bin2hex(Buffer.get(), KEYPAIR_MESSAGE_LEN, SecretKey.get(), crypto_box_SECRETKEYBYTES) == nullptr) wprintf_s(L"Create ramdom key pair failed, please try again.\n"); CaseConvert(true, Buffer.get(), KEYPAIR_MESSAGE_LEN); fwprintf_s(Output, L"Client Secret Key = "); for (Index = 0;Index < strnlen_s(Buffer.get(), KEYPAIR_MESSAGE_LEN);++Index) { if (Index > 0 && Index % KEYPAIR_INTERVAL == 0 && Index + 1U < strnlen_s(Buffer.get(), KEYPAIR_MESSAGE_LEN)) fwprintf_s(Output, L":"); fwprintf_s(Output, L"%c", Buffer.get()[Index]); } fwprintf_s(Output, L"\n"); //Close file. fclose(Output); } else { wprintf_s(L"Cannot create target file(KeyPair.txt)\n"); #if defined(PLATFORM_WIN) system("Pause"); #endif return EXIT_FAILURE; } wprintf_s(L"Create ramdom key pair success, please check KeyPair.txt.\n\n"); #if defined(PLATFORM_WIN) system("Pause"); #endif #else #if defined(PLATFORM_WIN) wprintf_s(L"LibSodium is disable.\n\n"); system("Pause"); #elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX)) wprintf(L"LibSodium is disable.\n\n"); #endif #endif return EXIT_SUCCESS; } //Convert lowercase/uppercase words to uppercase/lowercase words(Character version) #if defined(ENABLE_LIBSODIUM) void __fastcall CaseConvert( _In_ const bool IsLowerToUpper, _Inout_ char *Buffer, _In_ const size_t Length) { for (size_t Index = 0;Index < Length;++Index) { //Lowercase to uppercase if (IsLowerToUpper) Buffer[Index] = (char)toupper(Buffer[Index]); //Uppercase to lowercase else Buffer[Index] = (char)tolower(Buffer[Index]); } return; }
//Get data list from file void ReadSupport_GetParameterListData( std::vector<std::string> &ListData, const std::string &Data, const size_t DataOffset, const size_t Length, const uint8_t SeparatedSign, const bool IsCaseConvert, const bool IsKeepEmptyItem) { //Initialization std::string NameString; ListData.clear(); //Get all list data. for (auto Index = DataOffset;Index < Length;++Index) { //Last data if (Index + 1U == Length) { if (Data.at(Index) != SeparatedSign) NameString.append(Data, Index, 1U); if (NameString.empty()) { if (IsKeepEmptyItem) ListData.push_back(NameString); break; } else { if (IsCaseConvert) CaseConvert(NameString, false); //Add char to end. ListData.push_back(NameString); if (IsKeepEmptyItem && Data.at(Index) == SeparatedSign) { NameString.clear(); ListData.push_back(NameString); } break; } } //Separated else if (Data.at(Index) == SeparatedSign) { if (!NameString.empty()) { if (IsCaseConvert) CaseConvert(NameString, false); //Add char to end. ListData.push_back(NameString); NameString.clear(); } else if (IsKeepEmptyItem) { ListData.push_back(NameString); NameString.clear(); } } else { NameString.append(Data, Index, 1U); } } return; }
//Check hosts from list size_t __fastcall CheckHostsProcess(PSTR OriginalRequest, const size_t Length, PSTR Result, const size_t ResultSize) { //Initilization std::string Domain; auto DNS_Header = (pdns_hdr)OriginalRequest; memset(Result, 0, ResultSize); //Request check if (DNS_Header->Questions == htons(U16_NUM_ONE) && CheckQueryNameLength(OriginalRequest + sizeof(dns_hdr)) + 1U < DOMAIN_MAXSIZE) { if (DNSQueryToChar(OriginalRequest + sizeof(dns_hdr), Result) > DOMAIN_MINSIZE) { //Domain Case Conversion CaseConvert(false, Result, strnlen_s(Result, ResultSize)); //Copy domain string. Domain = Result; memset(Result, 0, ResultSize); } else { return EXIT_FAILURE; } } else { return EXIT_FAILURE; } //Response memcpy_s(Result, ResultSize, OriginalRequest, Length); DNS_Header = (pdns_hdr)Result; auto DNS_Query = (pdns_qry)(Result + DNS_PACKET_QUERY_LOCATE(Result)); //Check Classes. if (DNS_Query->Classes != htons(DNS_CLASS_IN)) return EXIT_FAILURE; //Check Accept Types list. if (Parameter.AcceptType) //Permit { for (auto AcceptTypeTableIter = Parameter.AcceptTypeList->begin();AcceptTypeTableIter != Parameter.AcceptTypeList->end();++AcceptTypeTableIter) { if (AcceptTypeTableIter + 1U == Parameter.AcceptTypeList->end()) { if (*AcceptTypeTableIter != DNS_Query->Type) { DNS_Header->Flags = htons(ntohs(DNS_Header->Flags) | DNS_SET_R_SNH); return Length; } } else if (*AcceptTypeTableIter == DNS_Query->Type) { break; } } } else { //Deny for (auto AcceptTypeTableIter:*Parameter.AcceptTypeList) { if (DNS_Query->Type == AcceptTypeTableIter) { DNS_Header->Flags = htons(ntohs(DNS_Header->Flags) | DNS_SET_R_SNH); return Length; } } } size_t DataLength = 0; //PTR Records #if !defined(PLATFORM_MACX) if (DNS_Query->Type == htons(DNS_RECORD_PTR) && Parameter.LocalServer_Length + Length <= ResultSize) { auto IsSendPTR = false; //IPv6 check if (Domain == ("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa") || //Loopback address(::1, Section 2.5.3 in RFC 4291) //IPv4 check Domain.find(".127.in-addr.arpa") != std::string::npos || //Loopback address(127.0.0.0/8, Section 3.2.1.3 in RFC 1122) Domain.find(".254.169.in-addr.arpa") != std::string::npos) //Link-local address(169.254.0.0/16, RFC 3927) { IsSendPTR = true; } else { //IPv6 check std::unique_lock<std::mutex> LocalAddressMutexIPv6(LocalAddressLock[0]); for (auto StringIter:*Parameter.LocalAddress_ResponsePTR[0]) { if (Domain == StringIter) { IsSendPTR = true; break; } } LocalAddressMutexIPv6.unlock(); //IPv4 check if (!IsSendPTR) { std::unique_lock<std::mutex> LocalAddressMutexIPv4(LocalAddressLock[1U]); for (auto StringIter:*Parameter.LocalAddress_ResponsePTR[1U]) { if (Domain == StringIter) { IsSendPTR = true; break; } } } } //Send Localhost PTR. if (IsSendPTR) { //Set header flags and copy response to buffer. DNS_Header->Flags = htons(ntohs(DNS_Header->Flags) | DNS_SER_RA); DNS_Header->Answer = htons(U16_NUM_ONE); memset(Result + DNS_PACKET_QUERY_LOCATE(Result) + sizeof(dns_qry), 0, ResultSize - (DNS_PACKET_QUERY_LOCATE(Result) + sizeof(dns_qry))); memcpy_s(Result + DNS_PACKET_QUERY_LOCATE(Result) + sizeof(dns_qry), ResultSize - (DNS_PACKET_QUERY_LOCATE(Result) + sizeof(dns_qry)), Parameter.LocalServer_Response, Parameter.LocalServer_Length); DataLength = DNS_PACKET_QUERY_LOCATE(Result) + sizeof(dns_qry) + Parameter.LocalServer_Length; //EDNS Label if (Parameter.EDNS_Label || DNS_Header->Additional > 0) { DNS_Header->Additional = 0; DataLength = AddEDNSLabelToAdditionalRR(Result, DataLength, ResultSize, false); } return DataLength; } } #endif //LocalFQDN check if (Domain == *Parameter.LocalFQDN_String) { //IPv6 if (DNS_Query->Type == htons(DNS_RECORD_AAAA)) { std::unique_lock<std::mutex> LocalAddressMutexIPv6(LocalAddressLock[0]); if (Parameter.LocalAddress_Length[0] >= DNS_PACKET_MINSIZE) { memset(Result + sizeof(uint16_t), 0, ResultSize - sizeof(uint16_t)); memcpy_s(Result + sizeof(uint16_t), ResultSize - sizeof(uint16_t), Parameter.LocalAddress_Response[0] + sizeof(uint16_t), Parameter.LocalAddress_Length[0] - sizeof(uint16_t)); return Parameter.LocalAddress_Length[0]; } } //IPv4 else if (DNS_Query->Type == htons(DNS_RECORD_A)) { std::unique_lock<std::mutex> LocalAddressMutexIPv4(LocalAddressLock[1U]); if (Parameter.LocalAddress_Length[1U] >= DNS_PACKET_MINSIZE) { memset(Result + sizeof(uint16_t), 0, ResultSize - sizeof(uint16_t)); memcpy_s(Result + sizeof(uint16_t), ResultSize - sizeof(uint16_t), Parameter.LocalAddress_Response[1U] + sizeof(uint16_t), Parameter.LocalAddress_Length[1U] - sizeof(uint16_t)); return Parameter.LocalAddress_Length[1U]; } } } //Main check auto IsLocal = false; std::unique_lock<std::mutex> HostsFileMutex(HostsFileLock); for (auto HostsFileSetIter:*HostsFileSetUsing) { for (auto HostsTableIter:HostsFileSetIter.HostsList) { if (std::regex_match(Domain, HostsTableIter.Pattern)) { //Check white list. if (HostsTableIter.Type_Hosts == HOSTS_TYPE_WHITE) { break; } //Check local request. else if (HostsTableIter.Type_Hosts == HOSTS_TYPE_LOCAL) { IsLocal = true; break; } //Check banned list. else if (HostsTableIter.Type_Hosts == HOSTS_TYPE_BANNED) { if (HostsTableIter.Type_Record.empty()) //Block all types { DNS_Header->Flags = htons(ntohs(DNS_Header->Flags) | DNS_SET_R_SNH); return Length; } else { //Permit or Deny if (HostsTableIter.Type_Operation) { //Only allow some types. for (auto RecordTypeIter = HostsTableIter.Type_Record.begin();RecordTypeIter != HostsTableIter.Type_Record.end();++RecordTypeIter) { if (DNS_Query->Type == *RecordTypeIter) { break; } else if (RecordTypeIter + 1U == HostsTableIter.Type_Record.end()) { DNS_Header->Flags = htons(ntohs(DNS_Header->Flags) | DNS_SET_R); return Length; } } } else { //Block some types. for (auto RecordTypeIter:HostsTableIter.Type_Record) { if (DNS_Query->Type == RecordTypeIter) { DNS_Header->Flags = htons(ntohs(DNS_Header->Flags) | DNS_SET_R); return Length; } } } } } //Check Hosts. else if (!HostsTableIter.Type_Record.empty()) { //IPv6 if (DNS_Query->Type == htons(DNS_RECORD_AAAA) && HostsTableIter.Type_Record.front() == htons(DNS_RECORD_AAAA)) { /* Old version(2015-07-19) //EDNS Label if (DNS_Header->Additional == htons(U16_NUM_ONE)) { memset(Result + Length - sizeof(dns_record_opt), 0, sizeof(dns_record_opt)); DNS_Header->Flags = htons(ntohs(DNS_Header->Flags) | DNS_SET_R); DNS_Header->Answer = htons((uint16_t)(HostsTableIter.Length / sizeof(dns_record_aaaa))); memcpy_s(Result + Length - sizeof(dns_record_opt), Length, HostsTableIter.Response.get(), HostsTableIter.Length); //Hosts load balancing if (ntohs(DNS_Header->Answer) > U16_NUM_ONE) { std::shared_ptr<dns_record_aaaa> DNS_AAAA_Temp(new dns_record_aaaa()); memset(DNS_AAAA_Temp.get(), 0, sizeof(dns_record_aaaa)); //Select a ramdom preferred result. std::uniform_int_distribution<int> RamdomDistribution(0, ntohs(DNS_Header->Answer) - 1U); size_t RamdomIndex = RamdomDistribution(*Parameter.RamdomEngine); if (RamdomIndex > 0) { memcpy_s(DNS_AAAA_Temp.get(), sizeof(dns_record_aaaa), Result + Length - sizeof(dns_record_opt), sizeof(dns_record_aaaa)); memset(Result + Length - sizeof(dns_record_opt), 0, sizeof(dns_record_aaaa)); memcpy_s(Result + Length - sizeof(dns_record_opt), ResultSize, Result + Length - sizeof(dns_record_opt) + sizeof(dns_record_aaaa) * RamdomIndex, sizeof(dns_record_aaaa)); memset(Result + Length - sizeof(dns_record_opt) + sizeof(dns_record_aaaa) * RamdomIndex, 0, sizeof(dns_record_aaaa)); memcpy_s(Result + Length - sizeof(dns_record_opt) + sizeof(dns_record_aaaa) * RamdomIndex, ResultSize, DNS_AAAA_Temp.get(), sizeof(dns_record_aaaa)); } } //Different result if (!Parameter.EDNS_Label) { auto DNS_Record_OPT = (pdns_record_opt)(Result + Length - sizeof(dns_record_opt) + HostsTableIter.Length); DNS_Record_OPT->Type = htons(DNS_RECORD_OPT); DNS_Record_OPT->UDPPayloadSize = htons((uint16_t)Parameter.EDNSPayloadSize); //DNSSEC if (Parameter.DNSSEC_Request) DNS_Record_OPT->Z_Field = htons(ntohs(DNS_Record_OPT->Z_Field) | EDNS_GET_BIT_DO); //Set Accepts DNSSEC security Resource Records bit. return Length + HostsTableIter.Length; DNS_Header->Additional = 0; return AddEDNSLabelToAdditionalRR(Result, Length - sizeof(dns_record_opt) + HostsTableIter.Length, ResultSize, false); } else { return Length - sizeof(dns_record_opt) + HostsTableIter.Length; } } else { DNS_Header->Flags = htons(ntohs(DNS_Header->Flags) | DNS_SET_R); DNS_Header->Answer = htons((uint16_t)(HostsTableIter.Length / sizeof(dns_record_aaaa))); memcpy_s(Result + Length, ResultSize, HostsTableIter.Response.get(), HostsTableIter.Length); //Hosts load balancing if (ntohs(DNS_Header->Answer) > U16_NUM_ONE) { std::shared_ptr<dns_record_aaaa> DNS_AAAA_Temp(new dns_record_aaaa()); memset(DNS_AAAA_Temp.get(), 0, sizeof(dns_record_aaaa)); //Select a ramdom preferred result. std::uniform_int_distribution<int> RamdomDistribution(0, ntohs(DNS_Header->Answer) - 1U); size_t RamdomIndex = RamdomDistribution(*Parameter.RamdomEngine); if (RamdomIndex > 0) { memcpy_s(DNS_AAAA_Temp.get(), sizeof(dns_record_aaaa), Result + Length, sizeof(dns_record_aaaa)); memset(Result + Length, 0, sizeof(dns_record_aaaa)); memcpy_s(Result + Length, ResultSize, Result + Length + sizeof(dns_record_aaaa) * RamdomIndex, sizeof(dns_record_aaaa)); memset(Result + Length + sizeof(dns_record_aaaa) * RamdomIndex, 0, sizeof(dns_record_aaaa)); memcpy_s(Result + Length + sizeof(dns_record_aaaa) * RamdomIndex, ResultSize, DNS_AAAA_Temp.get(), sizeof(dns_record_aaaa)); } } return Length + HostsTableIter.Length; } */ //Set header flags. DNS_Header->Flags = htons(ntohs(DNS_Header->Flags) | DNS_SET_R); DNS_Header->Answer = htons((uint16_t)(HostsTableIter.Length / sizeof(dns_record_aaaa))); //Hosts item length check DataLength = DNS_PACKET_QUERY_LOCATE(Result) + sizeof(dns_qry) + HostsTableIter.Length; if (Parameter.EDNS_Label || DNS_Header->Additional > 0) { while (DataLength > PACKET_MAXSIZE - EDNS_ADDITIONAL_MAXSIZE) { DataLength -= sizeof(dns_record_aaaa); DNS_Header->Answer = htons(ntohs(DNS_Header->Answer) - 1U); } } else { while (DataLength > PACKET_MAXSIZE) { DataLength -= sizeof(dns_record_aaaa); DNS_Header->Answer = htons(ntohs(DNS_Header->Answer) - 1U); } } //Copy response to buffer. memset(Result + DNS_PACKET_QUERY_LOCATE(Result) + sizeof(dns_qry), 0, ResultSize - (DNS_PACKET_QUERY_LOCATE(Result) + sizeof(dns_qry))); memcpy_s(Result + DNS_PACKET_QUERY_LOCATE(Result) + sizeof(dns_qry), ResultSize - (DNS_PACKET_QUERY_LOCATE(Result) + sizeof(dns_qry)), HostsTableIter.Response.get(), DataLength - (DNS_PACKET_QUERY_LOCATE(Result) + sizeof(dns_qry))); //Hosts load balancing if (ntohs(DNS_Header->Answer) > U16_NUM_ONE) { std::shared_ptr<dns_record_aaaa> DNS_AAAA_Temp(new dns_record_aaaa()); memset(DNS_AAAA_Temp.get(), 0, sizeof(dns_record_aaaa)); //Select a ramdom preferred result. std::uniform_int_distribution<int> RamdomDistribution(0, ntohs(DNS_Header->Answer) - 1U); size_t RamdomIndex = RamdomDistribution(*Parameter.RamdomEngine); if (RamdomIndex > 0) { memcpy_s(DNS_AAAA_Temp.get(), sizeof(dns_record_aaaa), Result + DNS_PACKET_QUERY_LOCATE(Result) + sizeof(dns_qry), sizeof(dns_record_aaaa)); memset(Result + DNS_PACKET_QUERY_LOCATE(Result) + sizeof(dns_qry), 0, sizeof(dns_record_aaaa)); memcpy_s(Result + DNS_PACKET_QUERY_LOCATE(Result) + sizeof(dns_qry), ResultSize - (DNS_PACKET_QUERY_LOCATE(Result) + sizeof(dns_qry)), Result + DNS_PACKET_QUERY_LOCATE(Result) + sizeof(dns_qry) + sizeof(dns_record_aaaa) * RamdomIndex, sizeof(dns_record_aaaa)); memset(Result + DNS_PACKET_QUERY_LOCATE(Result) + sizeof(dns_qry) + sizeof(dns_record_aaaa) * RamdomIndex, 0, sizeof(dns_record_aaaa)); memcpy_s(Result + DNS_PACKET_QUERY_LOCATE(Result) + sizeof(dns_qry) + sizeof(dns_record_aaaa) * RamdomIndex, sizeof(dns_record_aaaa), DNS_AAAA_Temp.get(), sizeof(dns_record_aaaa)); } } //EDNS Label if (Parameter.EDNS_Label || DNS_Header->Additional > 0) { DNS_Header->Additional = 0; DataLength = AddEDNSLabelToAdditionalRR(Result, DataLength, ResultSize, false); } return DataLength; } else if (DNS_Query->Type == htons(DNS_RECORD_A) && HostsTableIter.Type_Record.front() == htons(DNS_RECORD_A)) { /* Old version(2015-07-19) //EDNS Label if (DNS_Header->Additional == htons(U16_NUM_ONE)) { memset(Result + Length - sizeof(dns_record_opt), 0, sizeof(dns_record_opt)); DNS_Header->Flags = htons(ntohs(DNS_Header->Flags) | DNS_SET_R); DNS_Header->Answer = htons((uint16_t)(HostsTableIter.Length / sizeof(dns_record_a))); memcpy_s(Result + Length - sizeof(dns_record_opt), ResultSize, HostsTableIter.Response.get(), HostsTableIter.Length); //Hosts load balancing if (ntohs(DNS_Header->Answer) > U16_NUM_ONE) { std::shared_ptr<dns_record_a> DNS_A_Temp(new dns_record_a()); memset(DNS_A_Temp.get(), 0, sizeof(dns_record_a)); //Select a ramdom preferred result. std::uniform_int_distribution<int> RamdomDistribution(0, ntohs(DNS_Header->Answer) - 1U); size_t RamdomIndex = RamdomDistribution(*Parameter.RamdomEngine); if (RamdomIndex > 0) { memcpy_s(DNS_A_Temp.get(), sizeof(dns_record_a), Result + Length - sizeof(dns_record_opt), sizeof(dns_record_a)); memset(Result + Length - sizeof(dns_record_opt), 0, sizeof(dns_record_a)); memcpy_s(Result + Length - sizeof(dns_record_opt), ResultSize, Result + Length - sizeof(dns_record_opt) + sizeof(dns_record_a) * RamdomIndex, sizeof(dns_record_a)); memset(Result + Length - sizeof(dns_record_opt) + sizeof(dns_record_a) * RamdomIndex, 0, sizeof(dns_record_a)); memcpy_s(Result + Length - sizeof(dns_record_opt) + sizeof(dns_record_a) * RamdomIndex, ResultSize, DNS_A_Temp.get(), sizeof(dns_record_a)); } } //Different result if (!Parameter.EDNS_Label) { auto DNS_Record_OPT = (pdns_record_opt)(Result + Length - sizeof(dns_record_opt) + HostsTableIter.Length); DNS_Record_OPT->Type = htons(DNS_RECORD_OPT); DNS_Record_OPT->UDPPayloadSize = htons((uint16_t)Parameter.EDNSPayloadSize); //DNSSEC if (Parameter.DNSSEC_Request) DNS_Record_OPT->Z_Field = htons(ntohs(DNS_Record_OPT->Z_Field) | EDNS_GET_BIT_DO); //Set Accepts DNSSEC security Resource Records bit. return Length + HostsTableIter.Length; DNS_Header->Additional = 0; return AddEDNSLabelToAdditionalRR(Result, Length - sizeof(dns_record_opt) + HostsTableIter.Length, ResultSize, false); } else { return Length - sizeof(dns_record_opt) + HostsTableIter.Length; } } else { DNS_Header->Flags = htons(ntohs(DNS_Header->Flags) | DNS_SET_R); DNS_Header->Answer = htons((uint16_t)(HostsTableIter.Length / sizeof(dns_record_a))); memcpy_s(Result + Length, ResultSize, HostsTableIter.Response.get(), HostsTableIter.Length); //Hosts load balancing if (ntohs(DNS_Header->Answer) > U16_NUM_ONE) { std::shared_ptr<dns_record_a> DNS_A_Temp(new dns_record_a()); memset(DNS_A_Temp.get(), 0, sizeof(dns_record_a)); //Select a ramdom preferred result. std::uniform_int_distribution<int> RamdomDistribution(0, ntohs(DNS_Header->Answer) - 1U); size_t RamdomIndex = RamdomDistribution(*Parameter.RamdomEngine); if (RamdomIndex > 0) { memcpy_s(DNS_A_Temp.get(), sizeof(dns_record_a), Result + Length, sizeof(dns_record_a)); memset(Result + Length, 0, sizeof(dns_record_a)); memcpy_s(Result + Length, ResultSize, Result + Length + sizeof(dns_record_a) * RamdomIndex, sizeof(dns_record_a)); memset(Result + Length + sizeof(dns_record_a) * RamdomIndex, 0, sizeof(dns_record_a)); memcpy_s(Result + Length + sizeof(dns_record_a) * RamdomIndex, ResultSize, DNS_A_Temp.get(), sizeof(dns_record_a)); } } return Length + HostsTableIter.Length; } */ //Set header flags. DNS_Header->Flags = htons(ntohs(DNS_Header->Flags) | DNS_SET_R); DNS_Header->Answer = htons((uint16_t)(HostsTableIter.Length / sizeof(dns_record_a))); //Hosts item length check DataLength = DNS_PACKET_QUERY_LOCATE(Result) + sizeof(dns_qry) + HostsTableIter.Length; if (Parameter.EDNS_Label || DNS_Header->Additional > 0) { while (DataLength > PACKET_MAXSIZE - EDNS_ADDITIONAL_MAXSIZE) { DataLength -= sizeof(dns_record_a); DNS_Header->Answer = htons(ntohs(DNS_Header->Answer) - 1U); } } else { while (DataLength > PACKET_MAXSIZE) { DataLength -= sizeof(dns_record_a); DNS_Header->Answer = htons(ntohs(DNS_Header->Answer) - 1U); } } //Copy response to buffer. memset(Result + DNS_PACKET_QUERY_LOCATE(Result) + sizeof(dns_qry), 0, ResultSize - (DNS_PACKET_QUERY_LOCATE(Result) + sizeof(dns_qry))); memcpy_s(Result + DNS_PACKET_QUERY_LOCATE(Result) + sizeof(dns_qry), ResultSize - (DNS_PACKET_QUERY_LOCATE(Result) + sizeof(dns_qry)), HostsTableIter.Response.get(), DataLength - (DNS_PACKET_QUERY_LOCATE(Result) + sizeof(dns_qry))); //Hosts load balancing if (ntohs(DNS_Header->Answer) > U16_NUM_ONE) { std::shared_ptr<dns_record_a> DNS_A_Temp(new dns_record_a()); memset(DNS_A_Temp.get(), 0, sizeof(dns_record_a)); //Select a ramdom preferred result. std::uniform_int_distribution<int> RamdomDistribution(0, ntohs(DNS_Header->Answer) - 1U); size_t RamdomIndex = RamdomDistribution(*Parameter.RamdomEngine); if (RamdomIndex > 0) { memcpy_s(DNS_A_Temp.get(), sizeof(dns_record_a), Result + DNS_PACKET_QUERY_LOCATE(Result) + sizeof(dns_qry), sizeof(dns_record_a)); memset(Result + DNS_PACKET_QUERY_LOCATE(Result) + sizeof(dns_qry), 0, sizeof(dns_record_a)); memcpy_s(Result + DNS_PACKET_QUERY_LOCATE(Result) + sizeof(dns_qry), ResultSize - (DNS_PACKET_QUERY_LOCATE(Result) + sizeof(dns_qry)), Result + DNS_PACKET_QUERY_LOCATE(Result) + sizeof(dns_qry) + sizeof(dns_record_a) * RamdomIndex, sizeof(dns_record_a)); memset(Result + DNS_PACKET_QUERY_LOCATE(Result) + sizeof(dns_qry) + sizeof(dns_record_a) * RamdomIndex, 0, sizeof(dns_record_a)); memcpy_s(Result + DNS_PACKET_QUERY_LOCATE(Result) + sizeof(dns_qry) + sizeof(dns_record_a) * RamdomIndex, sizeof(dns_record_a), DNS_A_Temp.get(), sizeof(dns_record_a)); } } //EDNS Label if (Parameter.EDNS_Label || DNS_Header->Additional > 0) { DNS_Header->Additional = 0; DataLength = AddEDNSLabelToAdditionalRR(Result, DataLength, ResultSize, false); } return DataLength; } } } } } HostsFileMutex.unlock(); //Check DNS cache. std::unique_lock<std::mutex> DNSCacheListMutex(DNSCacheListLock); for (auto DNSCacheDataIter:DNSCacheList) { if (Domain == DNSCacheDataIter.Domain && DNS_Query->Type == DNSCacheDataIter.RecordType) { memset(Result + sizeof(uint16_t), 0, ResultSize - sizeof(uint16_t)); memcpy_s(Result + sizeof(uint16_t), ResultSize - sizeof(uint16_t), DNSCacheDataIter.Response.get(), DNSCacheDataIter.Length); return DNSCacheDataIter.Length + sizeof(uint16_t); } } DNSCacheListMutex.unlock(); //Domain Case Conversion if (Parameter.DomainCaseConversion) MakeDomainCaseConversion(OriginalRequest + sizeof(dns_hdr)); if (IsLocal) return EXIT_CHECK_HOSTS_TYPE_LOCAL; return EXIT_SUCCESS; }
//Mark responses to domains Cache bool __fastcall MarkDomainCache(const char *Buffer, const size_t Length) { //Check conditions. auto DNS_Header = (pdns_hdr)Buffer; if ( //Not a response packet (ntohs(DNS_Header->Flags) & DNS_GET_BIT_RESPONSE) == 0 || //Question Resource Records must be one. DNS_Header->Questions != htons(U16_NUM_ONE) || //Not any Answer Resource Records DNS_Header->Answer == 0 /* && DNS_Header->Authority == 0 && DNS_Header->Additional == 0 */ || //OPCode must be set Query/0. (ntohs(DNS_Header->Flags) & DNS_GET_BIT_OPCODE) != DNS_OPCODE_QUERY || //Truncated bit must not be set. (ntohs(DNS_Header->Flags) & DNS_GET_BIT_TC) != 0 || //RCode must be set No Error or Non-Existent Domain. (ntohs(DNS_Header->Flags) & DNS_GET_BIT_RCODE) != DNS_RCODE_NOERROR && (ntohs(DNS_Header->Flags) & DNS_GET_BIT_RCODE) != DNS_RCODE_NXDOMAIN) return false; //Initialization(A part) DNSCACHE_DATA DNSCacheDataTemp; DNSCacheDataTemp.Length = 0; DNSCacheDataTemp.ClearCacheTime = 0; auto DNS_Query = (pdns_qry)(Buffer + DNS_PACKET_QUERY_LOCATE(Buffer)); DNSCacheDataTemp.RecordType = DNS_Query->Type; uint32_t ResponseTTL = 0; //Mark DNS A records and AAAA records only. if (DNSCacheDataTemp.RecordType == htons(DNS_RECORD_AAAA) || DNSCacheDataTemp.RecordType == htons(DNS_RECORD_A)) { size_t DataLength = DNS_PACKET_RR_LOCATE(Buffer), TTLCounts = 0; pdns_record_standard DNS_Record_Standard = nullptr; uint16_t DNS_Pointer = 0; //Scan all Answers Resource Records. for (size_t Index = 0;Index < (size_t)ntohs(DNS_Header->Answer);++Index) { //Pointer check if (DataLength + sizeof(uint16_t) < Length && (UCHAR)Buffer[DataLength] >= DNS_POINTER_BITS) { DNS_Pointer = ntohs(*(uint16_t *)(Buffer + DataLength)) & DNS_POINTER_BITS_GET_LOCATE; if (DNS_Pointer >= Length || DNS_Pointer < sizeof(dns_hdr) || DNS_Pointer == DataLength || DNS_Pointer == DataLength + 1U) return false; } //Resource Records Name(Domain Name) DataLength += CheckQueryNameLength(Buffer + DataLength) + 1U; if (DataLength + sizeof(dns_record_standard) > Length) break; //Standard Resource Records DNS_Record_Standard = (pdns_record_standard)(Buffer + DataLength); DataLength += sizeof(dns_record_standard); if (DataLength > Length || DNS_Record_Standard != nullptr && DataLength + ntohs(DNS_Record_Standard->Length) > Length) break; //Resource Records Data if (DNS_Record_Standard->Classes == htons(DNS_CLASS_IN) && DNS_Record_Standard->TTL > 0 && (DNS_Record_Standard->Type == htons(DNS_RECORD_AAAA) && DNS_Record_Standard->Length == htons(sizeof(in6_addr)) || DNS_Record_Standard->Type == htons(DNS_RECORD_A) && DNS_Record_Standard->Length == htons(sizeof(in_addr)))) { ResponseTTL += ntohl(DNS_Record_Standard->TTL); ++TTLCounts; } DataLength += ntohs(DNS_Record_Standard->Length); } //Calculate average TTL. if (TTLCounts > 0) ResponseTTL = ResponseTTL / (uint32_t)TTLCounts + ResponseTTL % (uint32_t)TTLCounts; } //Set cache TTL. if (ResponseTTL == 0) //Only mark A and AAAA records. { return false; } else { if (Parameter.CacheType == CACHE_TYPE_TIMER) { if (ResponseTTL * SECOND_TO_MILLISECOND < Parameter.CacheParameter) ResponseTTL = (uint32_t)(Parameter.CacheParameter / SECOND_TO_MILLISECOND - ResponseTTL + STANDARD_TIMEOUT / SECOND_TO_MILLISECOND); } else { //CACHE_TYPE_QUEUE if (ResponseTTL < Parameter.HostsDefaultTTL) ResponseTTL = Parameter.HostsDefaultTTL - ResponseTTL + STANDARD_TIMEOUT / SECOND_TO_MILLISECOND; } } //Initialization(B part) if (Length <= DOMAIN_MAXSIZE) { std::shared_ptr<char> DNSCacheDataBufferTemp(new char[DOMAIN_MAXSIZE]()); memset(DNSCacheDataBufferTemp.get(), 0, DOMAIN_MAXSIZE); DNSCacheDataTemp.Response.swap(DNSCacheDataBufferTemp); } else { std::shared_ptr<char> DNSCacheDataBufferTemp(new char[Length]()); memset(DNSCacheDataBufferTemp.get(), 0, Length); DNSCacheDataTemp.Response.swap(DNSCacheDataBufferTemp); } //Mark to global list. if (DNSQueryToChar(Buffer + sizeof(dns_hdr), DNSCacheDataTemp.Response.get()) > DOMAIN_MINSIZE) { //Domain Case Conversion CaseConvert(false, DNSCacheDataTemp.Response.get(), strnlen_s(DNSCacheDataTemp.Response.get(), DOMAIN_MAXSIZE)); DNSCacheDataTemp.Domain = DNSCacheDataTemp.Response.get(); memset(DNSCacheDataTemp.Response.get(), 0, DOMAIN_MAXSIZE); memcpy_s(DNSCacheDataTemp.Response.get(), PACKET_MAXSIZE, Buffer + sizeof(uint16_t), Length - sizeof(uint16_t)); DNSCacheDataTemp.Length = Length - sizeof(uint16_t); //Minimum supported system of GetTickCount64() is Windows Vista(Windows XP with SP3 support). #if (defined(PLATFORM_WIN32) && !defined(PLATFORM_WIN64)) if (Parameter.FunctionPTR_GetTickCount64 != nullptr) DNSCacheDataTemp.ClearCacheTime = (size_t)((*Parameter.FunctionPTR_GetTickCount64)() + ResponseTTL * SECOND_TO_MILLISECOND); else DNSCacheDataTemp.ClearCacheTime = GetTickCount() + ResponseTTL * SECOND_TO_MILLISECOND; #else DNSCacheDataTemp.ClearCacheTime = GetTickCount64() + ResponseTTL * SECOND_TO_MILLISECOND; #endif std::unique_lock<std::mutex> DNSCacheListMutex(DNSCacheListLock); //Check repeating items, delete duque rear and add new item to deque front. for (auto DNSCacheDataIter = DNSCacheList.begin();DNSCacheDataIter != DNSCacheList.end();++DNSCacheDataIter) { if (DNSCacheDataTemp.Domain == DNSCacheDataIter->Domain && DNSCacheDataTemp.RecordType == DNSCacheDataIter->RecordType) { DNSCacheList.erase(DNSCacheDataIter); break; } } if (Parameter.CacheType == CACHE_TYPE_QUEUE) { while (DNSCacheList.size() > Parameter.CacheParameter) DNSCacheList.pop_front(); } else { //CACHE_TYPE_TIMER //Minimum supported system of GetTickCount64() is Windows Vista(Windows XP with SP3 support). #if (defined(PLATFORM_WIN32) && !defined(PLATFORM_WIN64)) while (!DNSCacheList.empty() && (Parameter.FunctionPTR_GetTickCount64 != nullptr && (*Parameter.FunctionPTR_GetTickCount64)() >= DNSCacheList.front().ClearCacheTime || GetTickCount() >= DNSCacheList.front().ClearCacheTime)) #else while (!DNSCacheList.empty() && GetTickCount64() >= DNSCacheList.front().ClearCacheTime) #endif DNSCacheList.pop_front(); } DNSCacheList.push_back(DNSCacheDataTemp); DNSCacheList.shrink_to_fit(); return true; } return false; }
//MD4 hash function bool __fastcall MD4_Hash( FILE *Input) { //Parameters check if ((HashFamilyID != HASH_ID_MD4 && HashFamilyID != HASH_ID_ED2K) || Input == nullptr) { fwprintf_s(stderr, L"Parameters error.\n"); return false; } //Initialization size_t ReadBlockSize = FILE_BUFFER_SIZE, ReadLength = 0, RoundCount = 0; if (HashFamilyID == HASH_ID_ED2K) ReadBlockSize = ED2K_SIZE_BLOCK; std::shared_ptr<char> Buffer(new char[ReadBlockSize]()), StringBuffer(new char[FILE_BUFFER_SIZE]()), BufferED2K(new char[MD4_SIZE_DIGEST]()); memset(Buffer.get(), 0, ReadBlockSize); memset(StringBuffer.get(), 0, FILE_BUFFER_SIZE); memset(BufferED2K.get(), 0, MD4_SIZE_DIGEST); MD4_CTX HashInstance, HashInstanceED2K; memset(&HashInstance, 0, sizeof(MD4_CTX)); memset(&HashInstanceED2K, 0, sizeof(MD4_CTX)); //MD4 initialization MD4_Init(&HashInstance); if (HashFamilyID == HASH_ID_ED2K) MD4_Init(&HashInstanceED2K); //Hash process while (!feof(Input)) { memset(Buffer.get(), 0, ReadBlockSize); _set_errno(0); ReadLength = fread_s(Buffer.get(), ReadBlockSize, sizeof(char), ReadBlockSize, Input); if (ReadLength == 0) { fwprintf_s(stderr, L"Hash process error"); if (errno > 0) fwprintf_s(stderr, L", error code is %d.\n", errno); else fwprintf_s(stderr, L".\n"); return false; } else { MD4_Update(&HashInstance, Buffer.get(), ReadLength); if (HashFamilyID == HASH_ID_ED2K) { MD4_Final((unsigned char *)Buffer.get(), &HashInstance); memcpy_s(BufferED2K.get(), MD4_SIZE_DIGEST, Buffer.get(), MD4_SIZE_DIGEST); MD4_Update(&HashInstanceED2K, Buffer.get(), MD4_SIZE_DIGEST); MD4_Init(&HashInstance); } ++RoundCount; } } //Binary to hex memset(Buffer.get(), 0, ReadBlockSize); if (HashFamilyID == HASH_ID_MD4) { MD4_Final((unsigned char *)Buffer.get(), &HashInstance); } else if (HashFamilyID == HASH_ID_ED2K) { if (RoundCount > 1U) MD4_Final((unsigned char *)Buffer.get(), &HashInstanceED2K); else memcpy_s(Buffer.get(), MD4_SIZE_DIGEST, BufferED2K.get(), MD4_SIZE_DIGEST); } else { return false; } if (sodium_bin2hex(StringBuffer.get(), FILE_BUFFER_SIZE, (const unsigned char *)Buffer.get(), MD4_SIZE_DIGEST) == nullptr) { fwprintf_s(stderr, L"Convert binary to hex error.\n"); return false; } else { //Print to screen. std::string HashResult = StringBuffer.get(); CaseConvert(true, HashResult); for (size_t Index = 0;Index < HashResult.length();++Index) fwprintf_s(stderr, L"%c", HashResult.c_str()[Index]); fwprintf_s(stderr, L"\n"); } return true; }
//MD2 hash function bool __fastcall MD2_Hash( FILE *Input) { //Parameters check if (HashFamilyID != HASH_ID_MD2 || Input == nullptr) { fwprintf_s(stderr, L"Parameters error.\n"); return false; } //Initialization std::shared_ptr<char> Buffer(new char[FILE_BUFFER_SIZE]()), StringBuffer(new char[FILE_BUFFER_SIZE]()); memset(Buffer.get(), 0, FILE_BUFFER_SIZE); memset(StringBuffer.get(), 0, FILE_BUFFER_SIZE); MD2_CTX HashInstance; memset(&HashInstance, 0, sizeof(MD2_CTX)); size_t ReadLength = 0; //MD2 initialization MD2_Init(&HashInstance); //Hash process while (!feof(Input)) { memset(Buffer.get(), 0, FILE_BUFFER_SIZE); _set_errno(0); ReadLength = fread_s(Buffer.get(), FILE_BUFFER_SIZE, sizeof(char), FILE_BUFFER_SIZE, Input); if (ReadLength == 0) { fwprintf_s(stderr, L"Hash process error"); if (errno > 0) fwprintf_s(stderr, L", error code is %d.\n", errno); else fwprintf_s(stderr, L".\n"); return false; } else { MD2_Update(&HashInstance, (uint8_t *)Buffer.get(), (uint32_t)ReadLength); } } //Binary to hex memset(Buffer.get(), 0, FILE_BUFFER_SIZE); MD2_Final(&HashInstance, (uint8_t *)Buffer.get()); if (sodium_bin2hex(StringBuffer.get(), FILE_BUFFER_SIZE, (const unsigned char *)Buffer.get(), MD2_DIGEST_SIZE) == nullptr) { fwprintf_s(stderr, L"Convert binary to hex error.\n"); return false; } else { //Print to screen. std::string HashResult = StringBuffer.get(); CaseConvert(true, HashResult); for (size_t Index = 0;Index < HashResult.length();++Index) fwprintf_s(stderr, L"%c", HashResult.c_str()[Index]); fwprintf_s(stderr, L"\n"); } return true; }
//Check hosts from global list size_t __fastcall CheckHostsProcess( DNS_PACKET_DATA *Packet, char *Result, const size_t ResultSize) { //Initilization std::string Domain; size_t DataLength = 0; auto DNS_Header = (pdns_hdr)Packet->Buffer; //Request check if (DNS_Header->Question == htons(U16_NUM_ONE) && CheckQueryNameLength(Packet->Buffer + sizeof(dns_hdr)) + 1U < DOMAIN_MAXSIZE) { if (DNSQueryToChar(Packet->Buffer + sizeof(dns_hdr), Domain) <= DOMAIN_MINSIZE) return EXIT_SUCCESS; else CaseConvert(false, Domain); } else { return EXIT_FAILURE; } //Response setting memset(Result, 0, ResultSize); memcpy_s(Result, ResultSize, Packet->Buffer, Packet->Length); DNS_Header = (pdns_hdr)Result; auto DNS_Query = (pdns_qry)(Result + DNS_PACKET_QUERY_LOCATE(Result)); //Check Classes. if (DNS_Query->Classes != htons(DNS_CLASS_IN)) return EXIT_FAILURE; //Check Accept Types list. if (Parameter.AcceptTypeList != nullptr) { //Permit if (Parameter.AcceptType) { for (auto AcceptTypeTableIter = Parameter.AcceptTypeList->begin();AcceptTypeTableIter != Parameter.AcceptTypeList->end();++AcceptTypeTableIter) { if (AcceptTypeTableIter + 1U == Parameter.AcceptTypeList->end()) { if (*AcceptTypeTableIter != DNS_Query->Type) { // DNS_Header->Flags = htons(ntohs(DNS_Header->Flags) | DNS_SET_R_SNH); DNS_Header->Flags = htons(DNS_SET_R_SNH); return Packet->Length; } } else if (*AcceptTypeTableIter == DNS_Query->Type) { break; } } } //Deny else { for (auto AcceptTypeTableIter:*Parameter.AcceptTypeList) { if (DNS_Query->Type == AcceptTypeTableIter) { // DNS_Header->Flags = htons(ntohs(DNS_Header->Flags) | DNS_SET_R_SNH); DNS_Header->Flags = htons(DNS_SET_R_SNH); return Packet->Length; } } } } //PTR Records //LLMNR protocol of Mac OS X powered by mDNS with PTR records #if (defined(PLATFORM_WIN) || defined(PLATFORM_LINUX)) if (DNS_Query->Type == htons(DNS_RECORD_PTR) && Parameter.LocalServer_Length + Packet->Length <= ResultSize) { auto IsSendPTR = false; //IPv6 check if (Domain == ("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa") || //Loopback address(::1, Section 2.5.3 in RFC 4291) //IPv4 check Domain.find(".127.in-addr.arpa") != std::string::npos || //Loopback address(127.0.0.0/8, Section 3.2.1.3 in RFC 1122) Domain.find(".254.169.in-addr.arpa") != std::string::npos) //Link-local address(169.254.0.0/16, RFC 3927) { IsSendPTR = true; } else { //IPv6 check std::unique_lock<std::mutex> LocalAddressMutexIPv6(LocalAddressLock[0]); for (auto StringIter:*GlobalRunningStatus.LocalAddress_ResponsePTR[0]) { if (Domain == StringIter) { IsSendPTR = true; break; } } LocalAddressMutexIPv6.unlock(); //IPv4 check if (!IsSendPTR) { std::lock_guard<std::mutex> LocalAddressMutexIPv4(LocalAddressLock[1U]); for (auto StringIter:*GlobalRunningStatus.LocalAddress_ResponsePTR[1U]) { if (Domain == StringIter) { IsSendPTR = true; break; } } } } //Send Localhost PTR. if (IsSendPTR) { //Set header flags and copy response to buffer. DNS_Header->Flags = htons(ntohs(DNS_Header->Flags) | DNS_SER_RA); DNS_Header->Answer = htons(U16_NUM_ONE); DNS_Header->Authority = 0; DNS_Header->Additional = 0; memset(Result + sizeof(dns_hdr) + Packet->Question, 0, Packet->Length - (sizeof(dns_hdr) + Packet->Question)); memcpy_s(Result + sizeof(dns_hdr) + Packet->Question, ResultSize - (sizeof(dns_hdr) + Packet->Question), Parameter.LocalServer_Response, Parameter.LocalServer_Length); DataLength = sizeof(dns_hdr) + Packet->Question + Parameter.LocalServer_Length; //EDNS Label if (Parameter.EDNS_Label || Packet->EDNS_Record > 0) DataLength = AddEDNSLabelToAdditionalRR(Result, DataLength, ResultSize, nullptr); return DataLength; } } #endif //LocalFQDN check if (Parameter.LocalFQDN_String != nullptr && Domain == *Parameter.LocalFQDN_String) { //IPv6 if (DNS_Query->Type == htons(DNS_RECORD_AAAA)) { std::lock_guard<std::mutex> LocalAddressMutexIPv6(LocalAddressLock[0]); if (GlobalRunningStatus.LocalAddress_Length[0] >= DNS_PACKET_MINSIZE) { memset(Result + sizeof(uint16_t), 0, ResultSize - sizeof(uint16_t)); memcpy_s(Result + sizeof(uint16_t), ResultSize - sizeof(uint16_t), GlobalRunningStatus.LocalAddress_Response[0] + sizeof(uint16_t), GlobalRunningStatus.LocalAddress_Length[0] - sizeof(uint16_t)); return GlobalRunningStatus.LocalAddress_Length[0]; } } //IPv4 else if (DNS_Query->Type == htons(DNS_RECORD_A)) { std::lock_guard<std::mutex> LocalAddressMutexIPv4(LocalAddressLock[1U]); if (GlobalRunningStatus.LocalAddress_Length[1U] >= DNS_PACKET_MINSIZE) { memset(Result + sizeof(uint16_t), 0, ResultSize - sizeof(uint16_t)); memcpy_s(Result + sizeof(uint16_t), ResultSize - sizeof(uint16_t), GlobalRunningStatus.LocalAddress_Response[1U] + sizeof(uint16_t), GlobalRunningStatus.LocalAddress_Length[1U] - sizeof(uint16_t)); return GlobalRunningStatus.LocalAddress_Length[1U]; } } } //Check DNS cache. std::unique_lock<std::mutex> DNSCacheListMutex(DNSCacheListLock); for (auto DNSCacheDataIter:DNSCacheList) { if (Domain == DNSCacheDataIter.Domain && DNS_Query->Type == DNSCacheDataIter.RecordType) { memset(Result + sizeof(uint16_t), 0, ResultSize - sizeof(uint16_t)); memcpy_s(Result + sizeof(uint16_t), ResultSize - sizeof(uint16_t), DNSCacheDataIter.Response.get(), DNSCacheDataIter.Length); return DNSCacheDataIter.Length + sizeof(uint16_t); } } DNSCacheListMutex.unlock(); //Local Main check if (Parameter.LocalMain) Packet->IsLocal = true; //Main check std::unique_lock<std::mutex> HostsFileMutex(HostsFileLock); for (auto HostsFileSetIter:*HostsFileSetUsing) { //Normal Hosts for (auto HostsTableIter:HostsFileSetIter.HostsList_Normal) { if (std::regex_match(Domain, HostsTableIter.Pattern)) { //Check white and banned hosts list, empty record type list check DataLength = CheckWhiteBannedHostsProcess(Packet->Length, HostsTableIter, DNS_Header, DNS_Query, &Packet->IsLocal); if (DataLength >= DNS_PACKET_MINSIZE) return DataLength; else if (DataLength == EXIT_FAILURE) goto StopLoop; //Initialization void *DNS_Record = nullptr; size_t RamdomIndex = 0, Index = 0; //IPv6(AAAA records) if (DNS_Query->Type == htons(DNS_RECORD_AAAA) && HostsTableIter.RecordTypeList.front() == htons(DNS_RECORD_AAAA)) { //Set header flags and convert DNS query to DNS response packet. // DNS_Header->Flags = htons(ntohs(DNS_Header->Flags) | DNS_SET_R); DNS_Header->Flags = htons(DNS_SQR_NE); DataLength = sizeof(dns_hdr) + Packet->Question; memset(Result + DataLength, 0, ResultSize - DataLength); //Hosts load balancing if (HostsTableIter.AddrList.size() > 1U) { std::uniform_int_distribution<size_t> RamdomDistribution(0, HostsTableIter.AddrList.size() - 1U); RamdomIndex = RamdomDistribution(*GlobalRunningStatus.RamdomEngine); } //Make response. for (Index = 0;Index < HostsTableIter.AddrList.size();++Index) { //Make resource records. DNS_Record = (pdns_record_aaaa)(Result + DataLength); DataLength += sizeof(dns_record_aaaa); ((pdns_record_aaaa)DNS_Record)->Name = htons(DNS_POINTER_QUERY); ((pdns_record_aaaa)DNS_Record)->Classes = htons(DNS_CLASS_IN); ((pdns_record_aaaa)DNS_Record)->TTL = htonl(Parameter.HostsDefaultTTL); ((pdns_record_aaaa)DNS_Record)->Type = htons(DNS_RECORD_AAAA); ((pdns_record_aaaa)DNS_Record)->Length = htons(sizeof(in6_addr)); if (Index == 0) ((pdns_record_aaaa)DNS_Record)->Addr = HostsTableIter.AddrList.at(RamdomIndex).IPv6.sin6_addr; else if (Index == RamdomIndex) ((pdns_record_aaaa)DNS_Record)->Addr = HostsTableIter.AddrList.at(0).IPv6.sin6_addr; else ((pdns_record_aaaa)DNS_Record)->Addr = HostsTableIter.AddrList.at(Index).IPv6.sin6_addr; //Hosts items length check if ((Parameter.EDNS_Label || Packet->EDNS_Record > 0) && DataLength + sizeof(dns_record_aaaa) + EDNS_ADDITIONAL_MAXSIZE >= ResultSize || //EDNS Label DataLength + sizeof(dns_record_aaaa) >= ResultSize) //Normal query { ++Index; break; } } //Set DNS counts and EDNS Label DNS_Header->Answer = htons((uint16_t)Index); DNS_Header->Authority = 0; DNS_Header->Additional = 0; if (Parameter.EDNS_Label || Packet->EDNS_Record > 0) DataLength = AddEDNSLabelToAdditionalRR(Result, DataLength, ResultSize, nullptr); return DataLength; } //IPv4(A records) else if (DNS_Query->Type == htons(DNS_RECORD_A) && HostsTableIter.RecordTypeList.front() == htons(DNS_RECORD_A)) { //Set header flags and convert DNS query to DNS response packet. // DNS_Header->Flags = htons(ntohs(DNS_Header->Flags) | DNS_SET_R); DNS_Header->Flags = htons(DNS_SQR_NE); DataLength = sizeof(dns_hdr) + Packet->Question; memset(Result + DataLength, 0, ResultSize - DataLength); //Hosts load balancing if (HostsTableIter.AddrList.size() > 1U) { std::uniform_int_distribution<size_t> RamdomDistribution(0, HostsTableIter.AddrList.size() - 1U); RamdomIndex = RamdomDistribution(*GlobalRunningStatus.RamdomEngine); } //Make response. for (Index = 0;Index < HostsTableIter.AddrList.size();++Index) { //Make resource records. DNS_Record = (pdns_record_a)(Result + DataLength); DataLength += sizeof(dns_record_a); ((pdns_record_a)DNS_Record)->Name = htons(DNS_POINTER_QUERY); ((pdns_record_a)DNS_Record)->Classes = htons(DNS_CLASS_IN); ((pdns_record_a)DNS_Record)->TTL = htonl(Parameter.HostsDefaultTTL); ((pdns_record_a)DNS_Record)->Type = htons(DNS_RECORD_A); ((pdns_record_a)DNS_Record)->Length = htons(sizeof(in_addr)); if (Index == 0) ((pdns_record_a)DNS_Record)->Addr = HostsTableIter.AddrList.at(RamdomIndex).IPv4.sin_addr; else if (Index == RamdomIndex) ((pdns_record_a)DNS_Record)->Addr = HostsTableIter.AddrList.at(0).IPv4.sin_addr; else ((pdns_record_a)DNS_Record)->Addr = HostsTableIter.AddrList.at(Index).IPv4.sin_addr; //Hosts items length check if ((Parameter.EDNS_Label || Packet->EDNS_Record > 0) && DataLength + sizeof(dns_record_a) + EDNS_ADDITIONAL_MAXSIZE >= ResultSize || //EDNS Label DataLength + sizeof(dns_record_a) >= ResultSize) //Normal query { ++Index; break; } } //Set DNS counts and EDNS Label DNS_Header->Answer = htons((uint16_t)Index); DNS_Header->Authority = 0; DNS_Header->Additional = 0; if (Parameter.EDNS_Label || Packet->EDNS_Record > 0) DataLength = AddEDNSLabelToAdditionalRR(Result, DataLength, ResultSize, nullptr); return DataLength; } } } //Local Hosts for (auto HostsTableIter:HostsFileSetIter.HostsList_Local) { if (std::regex_match(Domain, HostsTableIter.Pattern)) { //Check white and banned hosts list. DataLength = CheckWhiteBannedHostsProcess(Packet->Length, HostsTableIter, DNS_Header, DNS_Query, &Packet->IsLocal); if (DataLength >= DNS_PACKET_MINSIZE) return DataLength; else if (DataLength == EXIT_FAILURE) Packet->IsLocal = false; else //IsLocal flag setting Packet->IsLocal = true; goto StopLoop; } } } //Jump here to stop loop. StopLoop: HostsFileMutex.unlock(); //Domain Case Conversion if (Parameter.DomainCaseConversion) MakeDomainCaseConversion(Packet->Buffer + sizeof(dns_hdr)); return EXIT_SUCCESS; }
int wmain( _In_ int argc, _In_ wchar_t* argv[]) { #elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX)) int main(int argc, char *argv[]) { #endif #if defined(ENABLE_LIBSODIUM) //Initialization(Part 1) #if defined(PLATFORM_WIN) std::wstring FileName, Command; #elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX)) std::string FileName, Command; #endif //Read commands. if (argc < 2) { PrintDescription(); return EXIT_SUCCESS; } else if (argc == 2) //File name only, use default hash function. { //Commands check Command = argv[1U]; CaseConvert(true, Command); if (Command == COMMAND_LONG_PRINT_VERSION || Command == COMMAND_SHORT_PRINT_VERSION) { fwprintf_s(stderr, L"FileHash "); fwprintf_s(stderr, FULL_VERSION); fwprintf_s(stderr, L"\n"); return EXIT_SUCCESS; } else if (Command == COMMAND_LONG_HELP || Command == COMMAND_SHORT_HELP || Command == COMMAND_SIGN_HELP) { PrintDescription(); return EXIT_SUCCESS; } else if (Command == COMMAND_LIB_VERSION) { std::wstring LibVersion; if (MBSToWCSString(SODIUM_VERSION_STRING, strlen(SODIUM_VERSION_STRING), LibVersion)) fwprintf_s(stderr, L"LibSodium version %ls\n", LibVersion.c_str()); return EXIT_SUCCESS; } else { //Mark filename. FileName = argv[1U]; } } else if (argc == 3) //File name with hash function command { Command = argv[1U]; FileName = argv[2U]; //Commands check if (Command.length() < 3U) { fwprintf_s(stderr, L"Commands error.\n"); return EXIT_FAILURE; } else { CaseConvert(true, Command); } //CRC family if (Command.find(HASH_COMMAND_CRC) == 0) { HashFamilyID = HASH_ID_CRC; if (!ReadCommand_CRC(Command)) return EXIT_FAILURE; } //Internet Protocol Checksum else if (Command == HASH_COMMAND_CHECKSUM) { HashFamilyID = HASH_ID_CHECKSUM; } //MD2 else if (Command == HASH_COMMAND_MD2) { HashFamilyID = HASH_ID_MD2; } //MD4 family else if (Command == HASH_COMMAND_MD4) { HashFamilyID = HASH_ID_MD4; } else if (Command == HASH_COMMAND_ED2K) { HashFamilyID = HASH_ID_ED2K; } //MD5 else if (Command == HASH_COMMAND_MD || Command == HASH_COMMAND_MD5) { HashFamilyID = HASH_ID_MD5; } //SHA-1 else if (Command.find(HASH_COMMAND_SHA1) == 0) { HashFamilyID = HASH_ID_SHA1; } //SHA-2 family else if (Command == HASH_COMMAND_SHA2_384 || Command.find(HASH_COMMAND_SHA2_512) == 0 || Command.find(HASH_COMMAND_SHA2) == 0) { HashFamilyID = HASH_ID_SHA2; if (!ReadCommand_SHA2(Command)) return EXIT_FAILURE; } //SHA-3 family else if (Command == HASH_COMMAND_SHA || Command.find(HASH_COMMAND_SHA3) == 0) { HashFamilyID = HASH_ID_SHA3; if (!ReadCommand_SHA3(Command)) return EXIT_FAILURE; } //Commands error else { fwprintf_s(stderr, L"Commands error.\n"); return EXIT_FAILURE; } } else { fwprintf_s(stderr, L"Commands error.\n"); return EXIT_FAILURE; } Command.clear(); Command.shrink_to_fit(); //Open file. FILE *Input = nullptr; #if defined(PLATFORM_WIN) if (_wfopen_s(&Input, FileName.c_str(), L"rb") != 0 || Input == nullptr) #elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX)) Input = fopen(FileName.c_str(), "rb"); if (Input == nullptr) #endif { fwprintf_s(stderr, L"Open file error.\n"); return EXIT_FAILURE; } else { if (HashFamilyID == HASH_ID_CRC && !CRC_Hash(Input) || //CRC family HashFamilyID == HASH_ID_CHECKSUM && !Checksum_Hash(Input) || //Internet Protocol Checksum HashFamilyID == HASH_ID_MD2 && !MD2_Hash(Input) || //MD2 (HashFamilyID == HASH_ID_MD4 || HashFamilyID == HASH_ID_ED2K) && !MD4_Hash(Input) || //MD4 family HashFamilyID == HASH_ID_MD5 && !MD5_Hash(Input) || //MD5 HashFamilyID == HASH_ID_SHA1 && !SHA1_Hash(Input) || //SHA-1 HashFamilyID == HASH_ID_SHA2 && !SHA2_Hash(Input) || //SHA-2 family HashFamilyID == HASH_ID_SHA3 && !SHA3_Hash(Input)) //SHA-3 family { fclose(Input); return EXIT_FAILURE; } } fclose(Input); #else #if defined(PLATFORM_WIN) fwprintf_s(stderr, L"LibSodium is disable.\n\n"); system("PAUSE"); #elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX)) fwprintf(stderr, L"LibSodium is disable.\n\n"); #endif #endif return EXIT_SUCCESS; }
//Read ipfilter data from files bool ReadIPFilterData( std::string Data, const size_t FileIndex, const size_t Line, LABEL_IPFILTER_TYPE &LabelType, bool &IsStopLabel) { //Convert horizontal tab/HT to space, remove spaces before or after data, and check minimum length of ipfilter items. for (auto &StringIter:Data) { if (StringIter == ASCII_HT) StringIter = ASCII_SPACE; } while (!Data.empty() && Data.front() == ASCII_SPACE) Data.erase(0, 1U); while (!Data.empty() && Data.back() == ASCII_SPACE) Data.pop_back(); while (!Data.empty() && Data.find(" ") != std::string::npos) Data.erase(Data.find(" "), 1U); if (Data.length() < READ_IPFILTER_MINSIZE) return true; //Remove spaces, horizontal tab/HT, check comments(Number Sign/NS and double slashs). if (Data.compare(0, strlen("#"), "#") == 0 || Data.compare(0, strlen("/"), "/") == 0) return true; //Case insensitive std::string InsensitiveString(Data); CaseConvert(InsensitiveString, true); //[Local Routing] block(A part) if (LabelType == LABEL_IPFILTER_TYPE::NONE && (Parameter.Target_Server_Local_Main_IPv4.Storage.ss_family != 0 || Parameter.Target_Server_Local_Main_IPv6.Storage.ss_family != 0)) { std::wstring WCS_InsensitiveString(FileList_IPFilter.at(FileIndex).FileName); CaseConvert(WCS_InsensitiveString, true); if (CompareStringReversed(L"CHNROUTING.TXT", WCS_InsensitiveString.c_str()) || CompareStringReversed(L"CHNROUTE.TXT", WCS_InsensitiveString.c_str())) { LabelType = LABEL_IPFILTER_TYPE::LOCAL_ROUTING; IsStopLabel = false; } } //[IPFilter] block if (InsensitiveString.compare(0, strlen("[IPFILTER]"), "[IPFILTER]") == 0) { LabelType = LABEL_IPFILTER_TYPE::NORMAL; IsStopLabel = false; return true; } //[Blacklist] block(A part) else if (InsensitiveString.compare(0, strlen("[BLACKLIST]"), "[BLACKLIST]") == 0) { LabelType = LABEL_IPFILTER_TYPE::BLACKLIST; IsStopLabel = false; return true; } //[Local Routing] block(B part) else if (InsensitiveString.compare(0, strlen("[LOCAL ROUTING]"), "[LOCAL ROUTING]") == 0) { LabelType = LABEL_IPFILTER_TYPE::LOCAL_ROUTING; IsStopLabel = false; return true; } //Temporary stop read. else if (InsensitiveString.compare(0, strlen("[STOP"), "[STOP") == 0) { if (InsensitiveString.find("END]") != std::string::npos) { IsStopLabel = false; return true; } else if (InsensitiveString.compare(0, strlen("[STOP]"), "[STOP]") == 0) { IsStopLabel = true; return true; } } else if (IsStopLabel) { return true; } //[Blacklist] block(B part) if (LabelType == LABEL_IPFILTER_TYPE::NORMAL && Data.find(ASCII_MINUS) == std::string::npos) { PrintError(LOG_LEVEL_TYPE::LEVEL_1, LOG_ERROR_TYPE::IPFILTER, L"Data format error", 0, FileList_IPFilter.at(FileIndex).FileName.c_str(), Line); return false; } //Remove comments(Number Sign/NS and double slashs) and check minimum length. else if (Data.rfind(" //") != std::string::npos) { Data.erase(Data.rfind(" //"), Data.length() - Data.rfind(" //")); } else if (Data.rfind(" #") != std::string::npos) { Data.erase(Data.rfind(" #"), Data.length() - Data.rfind(" #")); } //Blacklist items if (LabelType == LABEL_IPFILTER_TYPE::BLACKLIST && Parameter.DataCheck_Blacklist) { //Remove spaces before or after verticals. while (Data.find(" |") != std::string::npos || Data.find("| ") != std::string::npos) { if (Data.find(" |") != std::string::npos) Data.erase(Data.find(" |"), strlen(" ")); if (Data.find("| ") != std::string::npos) Data.erase(Data.find("| ") + 1U, strlen("|")); } return ReadBlacklistData(Data, FileIndex, Line); } //Local Routing items else if (LabelType == LABEL_IPFILTER_TYPE::LOCAL_ROUTING && Parameter.IsLocalRouting) { while (Data.find(ASCII_SPACE) != std::string::npos) Data.erase(Data.find(ASCII_SPACE), 1U); if (Data.length() >= READ_IPFILTER_LOCAL_ROUTING_MINSIZE) return ReadLocalRoutingData(Data, FileIndex, Line); } //Main IPFilter items else if (LabelType == LABEL_IPFILTER_TYPE::NORMAL && Parameter.OperationMode == LISTEN_MODE::CUSTOM) { while (Data.find(ASCII_SPACE) != std::string::npos) Data.erase(Data.find(ASCII_SPACE), 1U); if (Data.length() >= READ_IPFILTER_MAIN_MINSIZE) return ReadMainIPFilterData(Data, FileIndex, Line); } return true; }
//Read Blacklist items in IPFilter file from data bool ReadBlacklistData( std::string Data, const size_t FileIndex, const size_t Line) { //Mark separated location. size_t Separated = 0; if (Data.find(ASCII_COMMA) != std::string::npos) { //Remove spaces before or after commas. while (Data.find(" ,") != std::string::npos) Data.erase(Data.find(" ,"), strlen(" ")); while (Data.find(ASCII_SPACE) != std::string::npos && Data.find(ASCII_SPACE) > Data.find(ASCII_COMMA)) Data.erase(Data.find(ASCII_SPACE), 1U); //Common format if (Data.find(ASCII_SPACE) != std::string::npos) { Separated = Data.find(ASCII_SPACE); } //Comma-Separated Values/CSV, RFC 4180(https://tools.ietf.org/html/rfc4180), Common Format and MIME Type for Comma-Separated Values (CSV) Files. else { Separated = Data.find(ASCII_COMMA); Data.erase(Separated, 1U); } } //Common format else if (Data.find(ASCII_SPACE) != std::string::npos) { Separated = Data.find(ASCII_SPACE); } else { PrintError(LOG_LEVEL_TYPE::LEVEL_1, LOG_ERROR_TYPE::IPFILTER, L"Data format error", 0, FileList_IPFilter.at(FileIndex).FileName.c_str(), Line); return false; } //Remove all spaces. while (Data.find(ASCII_SPACE) != std::string::npos) Data.erase(Data.find(ASCII_SPACE), 1U); //String length check. if (Data.length() < READ_IPFILTER_BLACKLIST_MINSIZE || (Data.find(ASCII_MINUS) != std::string::npos && Data.find(ASCII_VERTICAL) != std::string::npos && Data.find(ASCII_MINUS) < Separated && Data.find(ASCII_VERTICAL) < Separated && Data.find(ASCII_MINUS) < Data.find(ASCII_VERTICAL))) { PrintError(LOG_LEVEL_TYPE::LEVEL_1, LOG_ERROR_TYPE::IPFILTER, L"Data format error", 0, FileList_IPFilter.at(FileIndex).FileName.c_str(), Line); return false; } //Initialization RESULT_BLACKLIST_TABLE ResultBlacklistTableTemp; ADDRESS_RANGE_TABLE AddressRangeTableTemp; std::array<uint8_t, ADDRESS_STRING_MAXSIZE + MEMORY_RESERVED_BYTES> AddrBuffer{}; std::vector<std::string> ListData; GetParameterListData(ListData, Data, 0, Separated, ASCII_VERTICAL, false, false); ssize_t Result = 0; uint16_t PreviousType = 0; //Mark all data in list. for (const auto &StringIter:ListData) { //AAAA record(IPv6) if (StringIter.find(ASCII_COLON) != std::string::npos) { //Before type check if (PreviousType == 0) { PreviousType = AF_INET6; } else if (PreviousType != AF_INET6) { PrintError(LOG_LEVEL_TYPE::LEVEL_1, LOG_ERROR_TYPE::IPFILTER, L"Data format error", 0, FileList_IPFilter.at(FileIndex).FileName.c_str(), Line); return false; } //Address range format if (StringIter.find(ASCII_MINUS) != std::string::npos) { //Range check if (StringIter.length() + 1U <= StringIter.find(ASCII_MINUS)) { PrintError(LOG_LEVEL_TYPE::LEVEL_1, LOG_ERROR_TYPE::IPFILTER, L"IPv6 address format error", Result, FileList_IPFilter.at(FileIndex).FileName.c_str(), Line); return false; } //Convert address(Begin). AddrBuffer.fill(0); memcpy_s(AddrBuffer.data(), ADDRESS_STRING_MAXSIZE, StringIter.c_str(), StringIter.find(ASCII_MINUS)); if (!AddressStringToBinary(AF_INET6, AddrBuffer.data(), &reinterpret_cast<sockaddr_in6 *>(&AddressRangeTableTemp.Begin)->sin6_addr, &Result)) { PrintError(LOG_LEVEL_TYPE::LEVEL_1, LOG_ERROR_TYPE::IPFILTER, L"IPv6 address format error", Result, FileList_IPFilter.at(FileIndex).FileName.c_str(), Line); return false; } else { AddressRangeTableTemp.Begin.ss_family = AF_INET6; } //Convert address(End). AddrBuffer.fill(0); memcpy_s(AddrBuffer.data(), ADDRESS_STRING_MAXSIZE, StringIter.c_str() + StringIter.find(ASCII_MINUS) + 1U, StringIter.length() - StringIter.find(ASCII_MINUS) - 1U); if (!AddressStringToBinary(AF_INET6, AddrBuffer.data(), &reinterpret_cast<sockaddr_in6 *>(&AddressRangeTableTemp.End)->sin6_addr, &Result)) { PrintError(LOG_LEVEL_TYPE::LEVEL_1, LOG_ERROR_TYPE::IPFILTER, L"IPv6 address format error", Result, FileList_IPFilter.at(FileIndex).FileName.c_str(), Line); return false; } else { AddressRangeTableTemp.End.ss_family = AF_INET6; } //Check address range. if (AddressesComparing(AF_INET6, &reinterpret_cast<sockaddr_in6 *>(&AddressRangeTableTemp.Begin)->sin6_addr, &reinterpret_cast<sockaddr_in6 *>(&AddressRangeTableTemp.End)->sin6_addr) == ADDRESS_COMPARE_TYPE::GREATER) { PrintError(LOG_LEVEL_TYPE::LEVEL_1, LOG_ERROR_TYPE::IPFILTER, L"IPv6 address range error", 0, FileList_IPFilter.at(FileIndex).FileName.c_str(), Line); return false; } } //Normal format else { //Convert address. AddrBuffer.fill(0); memcpy_s(AddrBuffer.data(), ADDRESS_STRING_MAXSIZE, StringIter.c_str(), StringIter.length()); if (!AddressStringToBinary(AF_INET6, AddrBuffer.data(), &reinterpret_cast<sockaddr_in6 *>(&AddressRangeTableTemp.Begin)->sin6_addr, &Result)) { PrintError(LOG_LEVEL_TYPE::LEVEL_1, LOG_ERROR_TYPE::IPFILTER, L"IPv6 address format error", Result, FileList_IPFilter.at(FileIndex).FileName.c_str(), Line); return false; } //Check repeat items. if (CheckSpecialAddress(AF_INET6, &reinterpret_cast<sockaddr_in6 *>(&AddressRangeTableTemp.Begin)->sin6_addr, false, nullptr)) { PrintError(LOG_LEVEL_TYPE::LEVEL_2, LOG_ERROR_TYPE::IPFILTER, L"Repeat item error, this item will disabled", 0, FileList_IPFilter.at(FileIndex).FileName.c_str(), Line); return false; } AddressRangeTableTemp.Begin.ss_family = AF_INET6; AddressRangeTableTemp.End.ss_family = AF_INET6; reinterpret_cast<sockaddr_in6 *>(&AddressRangeTableTemp.End)->sin6_addr = reinterpret_cast<sockaddr_in6 *>(&AddressRangeTableTemp.Begin)->sin6_addr; } ResultBlacklistTableTemp.Addresses.push_back(AddressRangeTableTemp); memset(&AddressRangeTableTemp.Begin, 0, sizeof(AddressRangeTableTemp.Begin)); memset(&AddressRangeTableTemp.End, 0, sizeof(AddressRangeTableTemp.End)); AddressRangeTableTemp.Level = 0; } //A record(IPv4) else if (StringIter.find(ASCII_PERIOD) != std::string::npos) { //Before type check if (PreviousType == 0) { PreviousType = AF_INET; } else if (PreviousType != AF_INET) { PrintError(LOG_LEVEL_TYPE::LEVEL_1, LOG_ERROR_TYPE::IPFILTER, L"Data format error", 0, FileList_IPFilter.at(FileIndex).FileName.c_str(), Line); return false; } //Address range format if (StringIter.find(ASCII_MINUS) != std::string::npos) { //Range check if (StringIter.length() + 1U <= StringIter.find(ASCII_MINUS)) { PrintError(LOG_LEVEL_TYPE::LEVEL_1, LOG_ERROR_TYPE::IPFILTER, L"IPv4 address format error", Result, FileList_IPFilter.at(FileIndex).FileName.c_str(), Line); return false; } //Convert address(Begin). AddrBuffer.fill(0); memcpy_s(AddrBuffer.data(), ADDRESS_STRING_MAXSIZE, StringIter.c_str(), StringIter.find(ASCII_MINUS)); if (!AddressStringToBinary(AF_INET, AddrBuffer.data(), &reinterpret_cast<sockaddr_in *>(&AddressRangeTableTemp.Begin)->sin_addr, &Result)) { PrintError(LOG_LEVEL_TYPE::LEVEL_1, LOG_ERROR_TYPE::IPFILTER, L"IPv4 address format error", Result, FileList_IPFilter.at(FileIndex).FileName.c_str(), Line); return false; } else { AddressRangeTableTemp.Begin.ss_family = AF_INET; } //Convert address(End). AddrBuffer.fill(0); memcpy_s(AddrBuffer.data(), ADDRESS_STRING_MAXSIZE, StringIter.c_str() + StringIter.find(ASCII_MINUS) + 1U, StringIter.length() - StringIter.find(ASCII_MINUS) - 1U); if (!AddressStringToBinary(AF_INET, AddrBuffer.data(), &reinterpret_cast<sockaddr_in *>(&AddressRangeTableTemp.End)->sin_addr, &Result)) { PrintError(LOG_LEVEL_TYPE::LEVEL_1, LOG_ERROR_TYPE::IPFILTER, L"IPv4 address format error", Result, FileList_IPFilter.at(FileIndex).FileName.c_str(), Line); return false; } else { AddressRangeTableTemp.End.ss_family = AF_INET; } //Check address range. if (AddressesComparing(AF_INET, &reinterpret_cast<sockaddr_in *>(&AddressRangeTableTemp.Begin)->sin_addr, &reinterpret_cast<sockaddr_in *>(&AddressRangeTableTemp.End)->sin_addr) == ADDRESS_COMPARE_TYPE::GREATER) { PrintError(LOG_LEVEL_TYPE::LEVEL_1, LOG_ERROR_TYPE::IPFILTER, L"IPv4 address range error", 0, FileList_IPFilter.at(FileIndex).FileName.c_str(), Line); return false; } } //Normal format else { //Convert address. AddrBuffer.fill(0); memcpy_s(AddrBuffer.data(), ADDRESS_STRING_MAXSIZE, StringIter.c_str(), StringIter.length()); if (!AddressStringToBinary(AF_INET, AddrBuffer.data(), &reinterpret_cast<sockaddr_in *>(&AddressRangeTableTemp.Begin)->sin_addr, &Result)) { PrintError(LOG_LEVEL_TYPE::LEVEL_1, LOG_ERROR_TYPE::IPFILTER, L"IPv4 address format error", Result, FileList_IPFilter.at(FileIndex).FileName.c_str(), Line); return false; } //Check repeat items. if (CheckSpecialAddress(AF_INET, &reinterpret_cast<sockaddr_in *>(&AddressRangeTableTemp.Begin)->sin_addr, false, nullptr)) { PrintError(LOG_LEVEL_TYPE::LEVEL_2, LOG_ERROR_TYPE::IPFILTER, L"Repeat item error, this item will disabled", 0, FileList_IPFilter.at(FileIndex).FileName.c_str(), Line); return false; } AddressRangeTableTemp.Begin.ss_family = AF_INET; AddressRangeTableTemp.End.ss_family = AF_INET; reinterpret_cast<sockaddr_in *>(&AddressRangeTableTemp.End)->sin_addr = reinterpret_cast<sockaddr_in *>(&AddressRangeTableTemp.Begin)->sin_addr; } ResultBlacklistTableTemp.Addresses.push_back(AddressRangeTableTemp); memset(&AddressRangeTableTemp.Begin, 0, sizeof(AddressRangeTableTemp.Begin)); memset(&AddressRangeTableTemp.End, 0, sizeof(AddressRangeTableTemp.End)); AddressRangeTableTemp.Level = 0; } else { PrintError(LOG_LEVEL_TYPE::LEVEL_1, LOG_ERROR_TYPE::IPFILTER, L"Data format error", 0, FileList_IPFilter.at(FileIndex).FileName.c_str(), Line); return false; } } //Block these IP addresses from all request. ResultBlacklistTableTemp.PatternString.append(Data, Separated, Data.length() - Separated); std::string InsensitiveString(ResultBlacklistTableTemp.PatternString); CaseConvert(InsensitiveString, true); if (InsensitiveString == ("ALL")) { ResultBlacklistTableTemp.PatternString.clear(); ResultBlacklistTableTemp.PatternString.shrink_to_fit(); } //Other request else { try { std::regex PatternRegexTemp(ResultBlacklistTableTemp.PatternString); std::swap(ResultBlacklistTableTemp.PatternRegex, PatternRegexTemp); } catch (std::regex_error &Error) { PrintError(LOG_LEVEL_TYPE::LEVEL_1, LOG_ERROR_TYPE::IPFILTER, L"Regular expression pattern error", Error.code(), FileList_IPFilter.at(FileIndex).FileName.c_str(), Line); return false; } } //Register to global list. for (auto &IPFilterFileSetItem:*IPFilterFileSetModificating) { if (IPFilterFileSetItem.FileIndex == FileIndex) { IPFilterFileSetItem.ResultBlacklist.push_back(ResultBlacklistTableTemp); break; } } return true; }
//Capture process bool __fastcall CaptureModule(const pcap_if *pDrive, const bool IsCaptureList) { std::string CaptureDevice; //Devices name, address and type check if (pDrive->name == nullptr || pDrive->addresses == nullptr || pDrive->flags == PCAP_IF_LOOPBACK) goto DevicesSkip; //Pcap devices blacklist check if (pDrive->description != nullptr) { CaptureDevice.append(pDrive->description); CaseConvert(false, CaptureDevice); for (auto CaptureIter:*Parameter.PcapDevicesBlacklist) { if (CaptureIter.find(CaptureDevice) != std::string::npos) goto DevicesSkip; } } CaptureDevice.clear(); CaptureDevice.append(pDrive->name); CaseConvert(false, CaptureDevice); for (auto CaptureIter:*Parameter.PcapDevicesBlacklist) { if (CaptureIter.find(CaptureDevice) != std::string::npos) goto DevicesSkip; } //Skip this devices. goto DevicesNotSkip; DevicesSkip: if (IsCaptureList && pDrive->next != nullptr) { std::thread CaptureThread(CaptureModule, pDrive->next, true); CaptureThread.detach(); } return true; DevicesNotSkip: //Initialization(Part 1) pcap_t *DeviceHandle = nullptr; std::shared_ptr<char> Buffer(new char[ORIGINAL_PACKET_MAXSIZE + sizeof(uint16_t)]()); //Reserved 2 bytes for TCP header length. memset(Buffer.get(), 0, ORIGINAL_PACKET_MAXSIZE + sizeof(uint16_t)); CaptureDevice.clear(); CaptureDevice.append(pDrive->name); CaptureDevice.shrink_to_fit(); //Open device #if defined(PLATFORM_WIN) if ((DeviceHandle = pcap_open(pDrive->name, ORIGINAL_PACKET_MAXSIZE, PCAP_OPENFLAG_NOCAPTURE_LOCAL, (int)Parameter.PcapReadingTimeout, nullptr, Buffer.get())) == nullptr) #elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX)) if ((DeviceHandle = pcap_open_live(pDrive->name, ORIGINAL_PACKET_MAXSIZE, 0, (int)Parameter.PcapReadingTimeout, Buffer.get())) == nullptr) #endif { std::wstring ErrBuffer; if (MBSToWCSString(ErrBuffer, Buffer.get())) PrintError(LOG_ERROR_PCAP, ErrBuffer.c_str(), 0, nullptr, 0); return false; } //Check device type. uint16_t DeviceType = 0; if (pcap_datalink(DeviceHandle) == DLT_EN10MB || pcap_datalink(DeviceHandle) == DLT_PPP_ETHER || pcap_datalink(DeviceHandle) == DLT_EN3MB) //Ethernet II(Including PPPoE) DeviceType = DLT_EN10MB; else if (pcap_datalink(DeviceHandle) == DLT_APPLE_IP_OVER_IEEE1394) //Apple IEEE 1394 DeviceType = DLT_APPLE_IP_OVER_IEEE1394; if (DeviceType == 0) { pcap_close(DeviceHandle); return false; } //Compile the string into a filter program. std::shared_ptr<bpf_program> BPF_Code(new bpf_program()); memset(BPF_Code.get(), 0, sizeof(bpf_program)); #if defined(PLATFORM_WIN) if (pcap_compile(DeviceHandle, BPF_Code.get(), PcapFilterRules.c_str(), PCAP_COMPILE_OPTIMIZE, (bpf_u_int32)pDrive->addresses->netmask) == PCAP_ERROR) #elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX)) if (pcap_compile(DeviceHandle, BPF_Code.get(), PcapFilterRules.c_str(), PCAP_COMPILE_OPTIMIZE, 0) == PCAP_ERROR) #endif { std::wstring ErrBuffer; if (MBSToWCSString(ErrBuffer, pcap_geterr(DeviceHandle))) PrintError(LOG_ERROR_PCAP, ErrBuffer.c_str(), 0, nullptr, 0); pcap_close(DeviceHandle); return false; } //Specify a filter program. if (pcap_setfilter(DeviceHandle, BPF_Code.get()) == PCAP_ERROR) { std::wstring ErrBuffer; if (MBSToWCSString(ErrBuffer, pcap_geterr(DeviceHandle))) PrintError(LOG_ERROR_PCAP, ErrBuffer.c_str(), 0, nullptr, 0); pcap_freecode(BPF_Code.get()); pcap_close(DeviceHandle); return false; } //Start captures with other devices. PcapRunningList.push_back(CaptureDevice); if (IsCaptureList && pDrive->next != nullptr) { std::thread CaptureThread(CaptureModule, pDrive->next, IsCaptureList); CaptureThread.detach(); } //Initialization(Part 2) std::shared_ptr<CAPTURE_HANDLER_PARAM> ParamList(new CAPTURE_HANDLER_PARAM()); memset(ParamList.get(), 0, sizeof(CAPTURE_HANDLER_PARAM)); ParamList->Buffer = Buffer.get(); ParamList->DeviceType = DeviceType; SSIZE_T Result = 0; std::unique_lock<std::mutex> CaptureMutex(CaptureLock); CaptureMutex.unlock(); //Start monitor. for (;;) { Result = pcap_loop(DeviceHandle, PCAP_LOOP_INFINITY, CaptureHandler, (PUCHAR)ParamList.get()); // if (Result == PCAP_ERROR || Result == PCAP_ERROR_BREAK || Result == PCAP_ERROR_NO_SUCH_DEVICE || Result == PCAP_ERROR_RFMON_NOTSUP || Result == PCAP_ERROR_NOT_RFMON) if (Result < EXIT_SUCCESS) { //Delete this capture from devices list. CaptureMutex.lock(); for (auto CaptureIter = PcapRunningList.begin();CaptureIter != PcapRunningList.end();) { if (*CaptureIter == CaptureDevice) { CaptureIter = PcapRunningList.erase(CaptureIter); if (CaptureIter == PcapRunningList.end()) break; } else { ++CaptureIter; } } PcapRunningList.shrink_to_fit(); CaptureMutex.unlock(); //Exit this capture thread. pcap_freecode(BPF_Code.get()); pcap_close(DeviceHandle); return false; } else { Sleep(MONITOR_LOOP_INTERVAL_TIME); continue; } } //Monitor terminated pcap_freecode(BPF_Code.get()); pcap_close(DeviceHandle); PrintError(LOG_ERROR_SYSTEM, L"Capture module Monitor terminated", 0, nullptr, 0); return true; }