int GetHostsByName(const char *Name, const char *Agent, StringList *out) { ThreadContext Context; InitContext(&Context, NULL); if( GetAnswersByName(&Context, Name, DNS_TYPE_A, Agent) <= 0 ) { return 0; } else { return GetHostsByRaw(ExtendableBuffer_GetData(Context.ResponseBuffer), out); } }
int DNSFetchFromCache(__in ThreadContext *Context) { int RecordsCount, RecordsLength; char *Header; int32_t HeaderOffset; Header = ExtendableBuffer_Expand(Context -> ResponseBuffer, Context -> RequestLength, &HeaderOffset); if( Header == NULL ) { return -1; } memcpy(Header, Context -> RequestEntity, Context -> RequestLength); ((DNSHeader *)Header) -> Flags.Direction = 1; ((DNSHeader *)Header) -> Flags.AuthoritativeAnswer = 0; ((DNSHeader *)Header) -> Flags.RecursionAvailable = 1; ((DNSHeader *)Header) -> Flags.ResponseCode = 0; ((DNSHeader *)Header) -> Flags.Type = 0; RecordsCount = DNSCache_GetByQuestion(Context -> RequestEntity, Context -> ResponseBuffer, &RecordsLength, Context -> CurrentTime); if( RecordsCount > 0 ) { Header = ExtendableBuffer_GetData(Context -> ResponseBuffer) + HeaderOffset; ((DNSHeader *)Header) -> AnswerCount = htons(RecordsCount); if(Context -> Compress != FALSE) { int UnCompressedLength = Context -> RequestLength + RecordsLength; int CompressedLength = DNSCompress(Header, UnCompressedLength); ExtendableBuffer_Eliminate_Tail(Context -> ResponseBuffer, UnCompressedLength - CompressedLength); ShowNormalMassage(Context, HeaderOffset, 'C'); return CompressedLength; } else { ShowNormalMassage(Context, HeaderOffset, 'C'); return Context -> RequestLength + RecordsLength; } } else { return -1; } }
int DNSFetchFromHosts(__in ThreadContext *Context) { char *Header; int RecordsLength; int32_t HeaderOffset; int AnswerCount; Header = ExtendableBuffer_Expand(Context -> ResponseBuffer, Context -> RequestLength, &HeaderOffset); if( Header == NULL ) { return -1; } RecordsLength = DynamicHosts_GetByQuestion(Context, &AnswerCount); if( RecordsLength > 0 ) { Header = ExtendableBuffer_GetData(Context -> ResponseBuffer) + HeaderOffset; memcpy(Header, Context -> RequestEntity, Context -> RequestLength); ((DNSHeader *)Header) -> Flags.Direction = 1; ((DNSHeader *)Header) -> Flags.AuthoritativeAnswer = 0; ((DNSHeader *)Header) -> Flags.RecursionAvailable = 0; ((DNSHeader *)Header) -> Flags.ResponseCode = 0; ((DNSHeader *)Header) -> AnswerCount = htons(AnswerCount); if( AnswerCount != 1 && Context -> Compress != FALSE ) { int UnCompressedLength = Context -> RequestLength + RecordsLength; int CompressedLength = DNSCompress(Header, UnCompressedLength); ExtendableBuffer_Eliminate_Tail(Context -> ResponseBuffer, UnCompressedLength - CompressedLength); ShowNormalMassage(Context, HeaderOffset, 'H'); return CompressedLength; } else { ShowNormalMassage(Context, HeaderOffset, 'H'); return Context -> RequestLength + RecordsLength; } } else { return -1; } }
static int Query(ThreadContext *Context, CompatibleAddr *ClientAddr) { int State; char RequestingDomain[256]; char ClientIP[LENGTH_OF_IPV6_ADDRESS_ASCII + 1]; if( Family == AF_INET ) { strcpy(ClientIP, inet_ntoa(ClientAddr -> Addr4.sin_addr)); } else { IPv6AddressToAsc(&(ClientAddr -> Addr6.sin6_addr), ClientIP); } Context -> ClientIP = ClientIP; RequestingDomain[0] = '\0'; DNSGetHostName(Context -> RequestEntity, DNSJumpHeader(Context -> RequestEntity), RequestingDomain ); StrToLower(RequestingDomain); Context -> RequestingDomain = RequestingDomain; Context -> RequestingType = (DNSRecordType)DNSGetRecordType(DNSJumpHeader(Context -> RequestEntity)); Context -> RequestingDomainHashValue = ELFHash(RequestingDomain, 0); Context -> CurrentTime = time(NULL); State = QueryBase(Context); switch( State ) { case QUERY_RESULT_DISABLE: ((DNSHeader *)(Context -> RequestEntity)) -> Flags.Direction = 1; ((DNSHeader *)(Context -> RequestEntity)) -> Flags.RecursionAvailable = 1; ((DNSHeader *)(Context -> RequestEntity)) -> Flags.ResponseCode = RefusingResponseCode; if( Family == AF_INET ) { _SendTo(ListenSocketUDP, Context -> RequestEntity, Context -> RequestLength, 0, (struct sockaddr *)&(ClientAddr -> Addr4), sizeof(struct sockaddr) ); } else { _SendTo(ListenSocketUDP, Context -> RequestEntity, Context -> RequestLength, 0, (struct sockaddr *)&(ClientAddr -> Addr6), sizeof(struct sockaddr_in6) ); } return -1; break; case QUERY_RESULT_ERROR: ((DNSHeader *)(Context -> RequestEntity)) -> Flags.Direction = 1; ((DNSHeader *)(Context -> RequestEntity)) -> Flags.RecursionAvailable = 1; ((DNSHeader *)(Context -> RequestEntity)) -> Flags.ResponseCode = 2; if( Family == AF_INET ) { _SendTo(ListenSocketUDP, Context -> RequestEntity, Context -> RequestLength, 0, (struct sockaddr *)&(ClientAddr -> Addr4), sizeof(struct sockaddr) ); } else { _SendTo(ListenSocketUDP, Context -> RequestEntity, Context -> RequestLength, 0, (struct sockaddr *)&(ClientAddr -> Addr6), sizeof(struct sockaddr_in6) ); } return -1; break; default: /* Succeed */ if(State > MaximumMessageSize) { State = MaximumMessageSize; ((DNSHeader *)(ExtendableBuffer_GetData(Context -> ResponseBuffer))) -> Flags.TrunCation = 1; } if( Family == AF_INET ) { _SendTo(ListenSocketUDP, ExtendableBuffer_GetData(Context -> ResponseBuffer), State, 0, (struct sockaddr *)&(ClientAddr -> Addr4), sizeof(struct sockaddr) ); } else { _SendTo(ListenSocketUDP, ExtendableBuffer_GetData(Context -> ResponseBuffer), State, 0, (struct sockaddr *)&(ClientAddr -> Addr6), sizeof(struct sockaddr_in6) ); } return 0; } }
static int Query( SOCKET *PrimarySocket, SOCKET *SecondarySocket, DNSQuaryProtocol PrimaryProtocol, char *QueryContent, int QueryContentLength, SOCKET *ClientSocket, CompatibleAddr *ClientAddr, ExtendableBuffer *Buffer ) { int State; DNSRecordType SourceType; char *DNSBody = DNSGetDNSBody(QueryContent); char ProtocolCharacter = ' '; char QueryDomain[256]; char DateAndTime[32]; QueryContext Context; GetCurDateAndTime(DateAndTime, sizeof(DateAndTime)); QueryDomain[0] = '\0'; DNSGetHostName(DNSBody, DNSJumpHeader(DNSBody), QueryDomain); SourceType = (DNSRecordType)DNSGetRecordType(DNSJumpHeader(DNSBody)); Context.PrimarySocket = PrimarySocket; Context.SecondarySocket = SecondarySocket; Context.PrimaryProtocolToServer = PrimaryProtocol; Context.ProtocolToSrc = DNS_QUARY_PROTOCOL_TCP; Context.Compress = TRUE; State = QueryBase(&Context, QueryContent, QueryContentLength, Buffer, QueryDomain, SourceType, &ProtocolCharacter ); switch( State ) { case QUERY_RESULT_DISABLE: ((DNSHeader *)DNSBody) -> Flags.Direction = 1; ((DNSHeader *)DNSBody) -> Flags.ResponseCode = 5; send(*ClientSocket, QueryContent, QueryContentLength, 0); if( Family == AF_INET ) { PRINT("%s[R][%s:%d][%s][%s] Refused.\n", DateAndTime, inet_ntoa(ClientAddr -> Addr4.sin_addr), ClientAddr -> Addr4.sin_port, DNSGetTypeName(SourceType), QueryDomain); } else { char Addr[LENGTH_OF_IPV6_ADDRESS_ASCII] = {0}; IPv6AddressToAsc(&(ClientAddr -> Addr6.sin6_addr), Addr); PRINT("%s[R][%s:%d][%s][%s] Refused.\n", DateAndTime, Addr, ClientAddr -> Addr6.sin6_port, DNSGetTypeName(SourceType), QueryDomain); } return -1; break; case QUERY_RESULT_ERROR: if( ErrorMessages == TRUE ) { int ErrorNum = GET_LAST_ERROR(); char ErrorMessage[320]; ErrorMessage[0] ='\0'; GetErrorMsg(ErrorNum, ErrorMessage, sizeof(ErrorMessage)); if( Family == AF_INET ) { printf("%s[%c][%s][%s][%s] Error occured : %d : %s .\n", DateAndTime, ProtocolCharacter, inet_ntoa(ClientAddr -> Addr4.sin_addr), DNSGetTypeName(SourceType), QueryDomain, ErrorNum, ErrorMessage ); } else { char Addr[LENGTH_OF_IPV6_ADDRESS_ASCII] = {0}; IPv6AddressToAsc(&(ClientAddr -> Addr6.sin6_addr), Addr); printf("%s[%c][%s][%s][%s] Error occured : %d : %s .\n", DateAndTime, ProtocolCharacter, Addr, DNSGetTypeName(SourceType), QueryDomain, ErrorNum, ErrorMessage ); } } return -1; break; default: /* Succeed */ send(*ClientSocket, ExtendableBuffer_GetData(Buffer), State, 0); if( ShowMassages == TRUE ) { char InfoBuffer[3072]; InfoBuffer[0] = '\0'; GetAllAnswers(DNSGetDNSBody(ExtendableBuffer_GetData(Buffer)), InfoBuffer); if( Family == AF_INET ) { PRINT("%s[%c][%s][%s][%s] :\n%s", DateAndTime, ProtocolCharacter, inet_ntoa(ClientAddr ->Addr4.sin_addr), DNSGetTypeName(SourceType), QueryDomain, InfoBuffer); } else { char Addr[LENGTH_OF_IPV6_ADDRESS_ASCII] = {0}; IPv6AddressToAsc(&(ClientAddr -> Addr6.sin6_addr), Addr); PRINT("%s[%c][%s][%s][%s] :\n%s", DateAndTime, ProtocolCharacter, Addr, DNSGetTypeName(SourceType), QueryDomain, InfoBuffer); } } return 0; break; } }
static int Hosts_RecursivelyQuery(const char *IPOrCName, int *AnswerCount, ThreadContext *Context) { int PrependLength = 2 + 2 + 2 + 4 + 2 + strlen(IPOrCName) + 2; BOOL OriCompress = Context -> Compress; int State; int StartOffset = ExtendableBuffer_GetEndOffset(Context -> ResponseBuffer); char *StartPos; int EndOffset; const char *AnswerPos; int MoreSpaceNeeded = 0; char *HereSaved; HereSaved = ExtendableBuffer_Expand(Context -> ResponseBuffer, PrependLength, NULL); if( HereSaved == NULL ) { return -1; } Context -> Compress = FALSE; DNSGenResourceRecord(HereSaved + 1, INT_MAX, "", DNS_TYPE_CNAME, DNS_CLASS_IN, 60, IPOrCName, strlen(IPOrCName) + 1, TRUE); HereSaved[0] = 0xC0; HereSaved[1] = 0x0C; StartOffset = ExtendableBuffer_GetEndOffset(Context -> ResponseBuffer); State = GetAnswersByName(Context, IPOrCName, Context -> RequestingType, "CNameRedirect"); if( State < 0 ) { Context -> Compress = OriCompress; return -1; } StartPos = ExtendableBuffer_GetPositionByOffset(Context -> ResponseBuffer, StartOffset); EndOffset = DNSJumpOverAnswerRecords(StartPos) - ExtendableBuffer_GetData(Context -> ResponseBuffer); (*AnswerCount) = (int)DNSGetAnswerCount(StartPos) + 1; ExtendableBuffer_Eliminate(Context -> ResponseBuffer, EndOffset, StartOffset + State - EndOffset); MoreSpaceNeeded = DNSExpandCName_MoreSpaceNeeded(StartPos); if( ExtendableBuffer_Expand(Context -> ResponseBuffer, MoreSpaceNeeded, NULL) == NULL ) { Context -> Compress = OriCompress; return -1; } EndOffset += MoreSpaceNeeded; StartPos = ExtendableBuffer_GetPositionByOffset(Context -> ResponseBuffer, StartOffset); DNSExpandCName(StartPos); AnswerPos = DNSJumpOverQuestionRecords(StartPos); ExtendableBuffer_Eliminate(Context -> ResponseBuffer, StartOffset, AnswerPos - StartPos); Context -> Compress = OriCompress; return EndOffset - StartOffset - (AnswerPos - StartPos) + PrependLength; }