const char *DNSGetAnswerRecordPosition(const char *DNSBody, int Num) { const char *SR = DNSJumpOverQuestionRecords(DNSBody); if(Num > DNSGetAnswerCount(DNSBody)) Num = DNSGetAnswerCount(DNSBody) + 1; if(Num < 1) return NULL; for(; Num != 1; --Num) SR = DNSJumpOverName(SR) + 10 + DNSGetResourceDataLength(SR); return SR; }
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; }
static int QueryFromServer(ThreadContext *Context) { char ProtocolCharacter; int StateOfReceiving; SOCKET *SocketUsed; DNSQuaryProtocol ProtocolUsed; struct sockaddr *ServerAddr; int NumberOfAddresses; sa_family_t Family; BOOL UseSecondary; int32_t StartOffset = ExtendableBuffer_GetEndOffset(Context -> ResponseBuffer); int AnswerCount; /* Determine whether the secondaries are used */ if( NullSecondary != TRUE && (IsExcludedDomain(Context -> RequestingDomain, &(Context -> RequestingDomainHashValue)) || GfwList_Match(Context -> RequestingDomain, &(Context -> RequestingDomainHashValue))) ) { UseSecondary = TRUE; } else { UseSecondary = FALSE; } SelectSocketAndProtocol(Context, &SocketUsed, &ProtocolUsed, UseSecondary); SetAddressAndPrococolLetter(Context, ProtocolUsed, &ServerAddr, &NumberOfAddresses, &Family, &ProtocolCharacter ); StateOfReceiving = QueryFromServerBase(SocketUsed, ServerAddr, NumberOfAddresses, ProtocolUsed, Context -> RequestEntity, Context -> RequestLength, Context -> ResponseBuffer, Context -> RequestingDomain ); if(StateOfReceiving < 0) /* Failed */ { ShowErrorMassage(Context, ProtocolCharacter); /* Move pointer to the next */ AddressChunk_Advance(&Addresses, ProtocolUsed); if( UseSecondary == FALSE && NullSecondary != TRUE && AllowFallBack == TRUE ) { INFO("Fallback from %c for %s .\n", ProtocolCharacter, Context -> RequestingDomain ); SelectSocketAndProtocol(Context, &SocketUsed, &ProtocolUsed, TRUE ); SetAddressAndPrococolLetter(Context, ProtocolUsed, &ServerAddr, &NumberOfAddresses, &Family, &ProtocolCharacter ); StateOfReceiving = QueryFromServerBase(SocketUsed, ServerAddr, NumberOfAddresses, ProtocolUsed, Context -> RequestEntity, Context -> RequestLength, Context -> ResponseBuffer, Context -> RequestingDomain ); if( StateOfReceiving < 0 ) { ShowErrorMassage(Context, ProtocolCharacter); /* Move pointer to the next */ AddressChunk_Advance(&Addresses, ProtocolUsed); return QUERY_RESULT_ERROR; } } else { return QUERY_RESULT_ERROR; } } AnswerCount = DNSGetAnswerCount(ExtendableBuffer_GetPositionByOffset(Context -> ResponseBuffer, StartOffset)); if( AnswerCount < 1 ) { AddressChunk_Advance(&Addresses, ProtocolUsed); } ShowNormalMassage(Context, StartOffset, ProtocolCharacter); return StateOfReceiving; }
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 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; }