int GetHostsByRaw(const char *RawPackage, StringList *out) { int AnswerCount = DNSGetAnswerCount(RawPackage); int loop; const char *AnswerRecordPosition; const char *DataPos; int IpAddressCount = 0; char Data[] = " "; for( loop = 1; loop <= AnswerCount; ++loop ) { AnswerRecordPosition = DNSGetAnswerRecordPosition(RawPackage, loop); if( DNSGetRecordType(AnswerRecordPosition) == DNS_TYPE_A ) { DataPos = DNSGetResourceDataPos(AnswerRecordPosition); DNSParseData(RawPackage, DataPos, 1, Data, sizeof(Data), DNS_RECORD_A, NUM_OF_DNS_RECORD_A, 1); StringList_Add(out, Data, ','); ++IpAddressCount; } } return IpAddressCount; }
char *GetAllAnswers(const char *DNSBody, char *Buffer, size_t BufferLength) { int AnswerCount; const char *Itr; int UsedCount; DNSRecordType ResourceType; char TempBuffer[1024]; int RecordLength; if( BufferLength < strlen(" And More ...\n") ) { return NULL; } AnswerCount = DNSGetAnswerCount(DNSBody) + DNSGetNameServerCount(DNSBody); if( AnswerCount == 0 ) { strcpy(Buffer, " Nothing.\n"); return Buffer + strlen(" Nothing.\n"); } BufferLength -= strlen(" And More ...\n"); UsedCount = 0; while(UsedCount != AnswerCount){ Itr = DNSGetAnswerRecordPosition(DNSBody, UsedCount + 1); ResourceType = (DNSRecordType)DNSGetRecordType(Itr); RecordLength = GetAnswer(DNSBody, DNSGetResourceDataPos(Itr), DNSGetResourceDataLength(Itr), TempBuffer, ResourceType) - TempBuffer; if( RecordLength < BufferLength ) { strcpy(Buffer, TempBuffer); BufferLength -= RecordLength; Buffer += RecordLength; } else { break; } ++UsedCount; } if( UsedCount < AnswerCount ) { Buffer += sprintf(Buffer, " And %d More ...\n", AnswerCount - UsedCount); } return Buffer; }
/* You should meke sure there is no additional record and nameserver record */ void DNSExpandCName(const char *DNSBody) { int AnswerCount = DNSGetAnswerCount(DNSBody); int Itr = 1; const char *Answer; DNSRecordType Type; char *Resource; int ResourceLength; int NameLength; char *NameEnd; /* After terminated-zero */ char *DNSEnd; if( AnswerCount < 1 ) { return; } do { Answer = DNSGetAnswerRecordPosition(DNSBody, Itr); Type = DNSGetRecordType(Answer); if( Type == DNS_TYPE_CNAME ) { ResourceLength = DNSGetResourceDataLength(Answer); Resource = (char *)DNSGetResourceDataPos(Answer); NameLength = DNSGetHostNameLength(DNSBody, Resource); NameEnd = Resource + ResourceLength; DNSEnd = (char *)DNSGetAnswerRecordPosition(DNSBody, AnswerCount + 1); SET_16_BIT_U_INT(Resource - 2, NameLength + 1); memmove(Resource + NameLength + 1, NameEnd, DNSEnd - NameEnd); DNSCopyLable(DNSBody, Resource, Resource); } ++Itr; }while( Itr <= AnswerCount ); }
int DNSExpandCName_MoreSpaceNeeded(const char *DNSBody) { int AnswerCount = DNSGetAnswerCount(DNSBody); int Itr = 1; int MoreSpaceNeeded = 0; const char *Answer; DNSRecordType Type; const char *Resource; int ResourceLength; int NameLength; if( AnswerCount < 1 ) { return 0; } do { Answer = DNSGetAnswerRecordPosition(DNSBody, Itr); Type = DNSGetRecordType(Answer); if( Type == DNS_TYPE_CNAME ) { ResourceLength = DNSGetResourceDataLength(Answer); Resource = DNSGetResourceDataPos(Answer); NameLength = DNSGetHostNameLength(DNSBody, Resource); MoreSpaceNeeded += (NameLength + 1) - ResourceLength; } ++Itr; }while( Itr <= AnswerCount ); return MoreSpaceNeeded; }
void DNSParser(char *dns_over_tcp, char *buffer){ char *dnsovertcp = dns_over_tcp; char InnerBuffer[128] = {0}; unsigned short qc, ac; buffer += sprintf(buffer, "TCPLength:%hu\n", DNSGetTCPLength(DNSGetDNSBody(dnsovertcp))); buffer += sprintf(buffer, "QueryIdentifier:%hu\n", DNSGetQueryIdentifier(DNSGetDNSBody(dnsovertcp))); buffer += sprintf(buffer, "Flags:%x\n", DNSGetFlags(DNSGetDNSBody(dnsovertcp))); qc = DNSGetQuestionCount(DNSGetDNSBody(dnsovertcp)); buffer += sprintf(buffer, "QuestionCount:%hu\n", qc); ac = DNSGetAnswerCount(DNSGetDNSBody(dnsovertcp)); buffer += sprintf(buffer, "AnswerCount:%hu\n", ac); buffer += sprintf(buffer, "NameServerCount:%hu\n", DNSGetNameServerCount(DNSGetDNSBody(dnsovertcp))); buffer += sprintf(buffer, "AdditionalCount:%hu\n", DNSGetAdditionalCount(DNSGetDNSBody(dnsovertcp))); dnsovertcp = DNSJumpHeader(DNSGetDNSBody(dns_over_tcp)); for(; qc != 0; --qc){ DNSGetHostName(dns_over_tcp + 2, dnsovertcp, InnerBuffer); buffer += sprintf(buffer, "QuestionName:%s\n", InnerBuffer); buffer += sprintf(buffer, "QuestionType:%hu\n", DNSGetRecordType(dnsovertcp)); buffer += sprintf(buffer, "QuestionClass:%hu\n", DNSGetRecordClass(dnsovertcp)); } dnsovertcp = DNSJumpOverQuestionRecords(DNSGetDNSBody(dns_over_tcp)); while(ac != 0){ unsigned short rt, dl; dnsovertcp = DNSGetAnswerRecordPosition(DNSGetDNSBody(dns_over_tcp), DNSGetAnswerCount(DNSGetDNSBody(dns_over_tcp)) - ac + 1); DNSGetHostName(dns_over_tcp + 2, dnsovertcp, InnerBuffer); buffer += sprintf(buffer, "ResourceName:%s\n", InnerBuffer); rt = DNSGetRecordType(dnsovertcp); buffer += sprintf(buffer, "ResourceType:%hu\n", rt); buffer += sprintf(buffer, "ResourceClass:%hu\n", DNSGetRecordClass(dnsovertcp)); buffer += sprintf(buffer, "TimeToLive:%u\n", (unsigned int)DNSGetTTL(dnsovertcp)); dl = DNSGetResourceDataLength(dnsovertcp); buffer += sprintf(buffer, "ResourceDataLength:%hu\n", dl); dnsovertcp = DNSGetResourceDataPos(dnsovertcp); switch(rt){ case DNS_TYPE_A: /* A, IPv4 address */ buffer += sprintf(buffer, "IPv4Addres:%d.%d.%d.%d\n", GET_8_BIT_U_INT(dnsovertcp), GET_8_BIT_U_INT(dnsovertcp + 1), GET_8_BIT_U_INT(dnsovertcp + 2), GET_8_BIT_U_INT(dnsovertcp + 3)); break; case DNS_TYPE_AAAA: /* AAAA, IPv6 address */ buffer += sprintf(buffer, "IPv6Addres:%x:%x:%x:%x:%x:%x:%x:%x\n", GET_16_BIT_U_INT(dnsovertcp), GET_16_BIT_U_INT(dnsovertcp + 2), GET_16_BIT_U_INT(dnsovertcp + 4), GET_16_BIT_U_INT(dnsovertcp + 6), GET_16_BIT_U_INT(dnsovertcp + 8), GET_16_BIT_U_INT(dnsovertcp + 10), GET_16_BIT_U_INT(dnsovertcp + 12), GET_16_BIT_U_INT(dnsovertcp + 14) ); break; case DNS_TYPE_CNAME: /* CNAME */ DNSGetHostName(dns_over_tcp + 2, dnsovertcp, InnerBuffer); buffer += sprintf(buffer, "CName:%s\n", InnerBuffer); break; default: break; } dnsovertcp = DNSGetAnswerRecordPosition(DNSGetDNSBody(dns_over_tcp), DNSGetAnswerCount(dns_over_tcp) - ac + 1); --ac; } }
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; } }