5 // Created by Terrin Eager on 9/26/12.
11 #define DNS_LABEL_MAX_LENGTH 63
12 #define DNS_NAME_MAX_LENGTH 255
14 void CDNSRecord::GetDnsRecordName(BJString& ReturnString,int nLabelToSkip,int nMaxLabel)
16 GetDnsRecordNameFromBuffer(m_pStartofRec, ReturnString, nLabelToSkip, nMaxLabel);
19 void CDNSRecord::GetDnsRecordNameFromBuffer(BJ_UINT8* pBuffer,BJString& ReturnString,int nLabelToSkip,int nMaxLabel)
21 BJ_UINT8* pNameBuffer = NULL;
23 // char* pTemp = pReturnBuffer;
25 int nSkippedLabels = 0;
26 int nLabelProcessed = 0;
27 ReturnString.Set(NULL,255);
29 if (ReturnString.GetBuffer() == NULL)
32 pNameBuffer = pBuffer;
33 if (pNameBuffer == NULL)
38 while (ReturnString.GetBufferLength() < 1024)
40 nCharCount = *pNameBuffer++;
44 if ((nCharCount&(DNS_NAME_OFFSET_MASK)) == DNS_NAME_OFFSET_MASK)
46 nOffset = *pNameBuffer++;
47 nOffset |= (nCharCount&(~DNS_NAME_OFFSET_MASK)) << 8;
48 pNameBuffer = m_pDNSFrame->GetBuffer() + nOffset;
52 if (nCharCount > DNS_LABEL_MAX_LENGTH)
54 printf("label too long %d\n",nCharCount);
58 if (ReturnString.GetLength() + nCharCount + 1 > DNS_NAME_MAX_LENGTH) // + 1 is for the '.' added later on
60 printf("Name exceeded limit allowed for DNS: %d\n", ReturnString.GetLength() + nCharCount + 1);
64 if (nLabelToSkip > nSkippedLabels)
67 pNameBuffer += nCharCount;
70 ReturnString.Append((char*)pNameBuffer, nCharCount);
71 pNameBuffer+= nCharCount;
74 if (nLabelProcessed >= nMaxLabel)
84 CDNSFrame::CDNSFrame()
87 for(int nIndex=0; nIndex < MAX_DNS_RECORDS_PER_FRAME; nIndex++)
88 m_dnsItems[nIndex].m_pDNSFrame = this;
92 CDNSRecord* CDNSFrame::GetDnsRecord(int nIndex)
94 if (nIndex > m_nMaxItems)
96 return &m_dnsItems[nIndex];
99 bool CDNSFrame::ParseDNSFrame(BJ_UINT8* pBuffer,BJ_INT32 nLength, BJ_UINT64 frameTime)
106 m_Servicev4Address.Empty();
107 m_Servicev6Address.Empty();
109 m_pStartBuffer = pBuffer;
110 m_nFrameLen = (BJ_UINT32) nLength;
112 m_pCurrentBuffer = m_pStartBuffer;
113 m_pEndBuffer = m_pStartBuffer + m_nFrameLen;
116 m_nId = PF_GET_UINT16(m_pStartBuffer,0);
117 m_nFlags = PF_GET_UINT16(m_pStartBuffer,2);
118 m_nQuestionCount = PF_GET_UINT16(m_pStartBuffer,4);
119 m_nAnswersCount = PF_GET_UINT16(m_pStartBuffer,6);
120 m_NSCOUNT = PF_GET_UINT16(m_pStartBuffer,8);
121 m_ARCOUNT = PF_GET_UINT16(m_pStartBuffer,10);
127 // printf("FrameNum= %d,nQuestionCount= %d nAnswersCount= %d NSCOUNT= %d ARCOUNT= %d\n",nFrameCount++,m_nQuestionCount, m_nAnswersCount,m_NSCOUNT, m_ARCOUNT);
129 m_pCurrentBuffer = m_pStartBuffer + 12;
132 for (nIndex =0; nIndex < m_nQuestionCount;nIndex++)
134 // printf("FramePosition= %ld ",m_pCurrentBuffer);
135 ParseDnsRecord(CDNSRecord::Question);
138 for (nIndex =0; nIndex < m_nAnswersCount;nIndex++)
140 // printf("FramePosition= %ld ",m_pCurrentBuffer);
141 ParseDnsRecord(CDNSRecord::Answer);
143 for (nIndex =0; nIndex < m_NSCOUNT;nIndex++)
145 // printf("FramePosition= %ld ",m_pCurrentBuffer);
146 ParseDnsRecord(CDNSRecord::Answer);
148 for (nIndex =0; nIndex < m_ARCOUNT;nIndex++)
150 // printf("FramePosition= %ld ",m_pCurrentBuffer);
151 ParseDnsRecord(CDNSRecord::Answer);
152 CDNSRecord* pRecord = &m_dnsItems[m_nMaxItems-1];
153 if (pRecord->m_RecType == DNS_TYPE_AAAA && m_Servicev6Address.IsEmpty())
155 m_Servicev6Address.Setv6Raw(pRecord->GetStartofRdata());
157 if (pRecord->m_RecType == DNS_TYPE_A && m_Servicev4Address.IsEmpty())
159 m_Servicev4Address.Setv4Raw(pRecord->GetStartofRdata());
163 /// for (dnsItemsIndex =0; dnsItemsIndex < m_nQuestionCount+m_nAnswersCount;dnsItemsIndex++)
165 /// printf("Name = %s\n", GetDnsRecordName(&Frame,dnsItemsIndex,tempBuffer,sizeof(tempBuffer)));
170 BJ_BOOL CDNSFrame::ParseDnsRecord(CDNSRecord::dnsItemType eItemType)
172 unsigned char nCharCount = 0;
173 BJ_UINT8* pTemp = m_pCurrentBuffer;
174 CDNSRecord* pRecord = &m_dnsItems[m_nMaxItems++];
177 BJ_UINT16 nRdataLen = 0;
178 BJ_UINT16 nRdataLen2 = 0;
180 if (pTemp > m_pEndBuffer)
182 printf("Error in ParseDnsRecord pBuffer > pEndBuffer\n");
183 pRecord->m_pStartofRec = NULL;
184 pRecord->m_nNameLength = 0;
189 pRecord->m_pStartofRec = pTemp;
190 pRecord->m_nNameLength = 0;
191 pRecord->m_nRdataLen = 0;
195 while (pTemp < m_pEndBuffer)
203 if ((nCharCount&(DNS_NAME_OFFSET_MASK)) == DNS_NAME_OFFSET_MASK)
209 if (nCharCount > DNS_LABEL_MAX_LENGTH)
211 printf("%d. label too long %d\n",m_nMaxItems-1,nCharCount);
214 if (pTemp + nCharCount < m_pEndBuffer)
217 pTemp = m_pEndBuffer;
220 pRecord->m_nNameLength = (BJ_UINT32)(pTemp - pRecord->m_pStartofRec);
222 if (eItemType == CDNSRecord::Question)
224 pRecord->m_RecType = PF_GET_UINT16(pTemp,0);
225 pRecord->m_RecClass = PF_GET_UINT16(pTemp,2);
226 pRecord->m_nTTL = PF_GET_UINT16(pTemp,4);
228 // printf("Namelen=%u, Type=%u, class=%u, TTL=%u, RDLength=%u\n", m_dnsItems[ndnsIndex].nNameLength,nType,nClass,nTTL,nRdataLen);
235 pRecord->m_RecType = PF_GET_UINT16(pTemp,0);
236 pRecord->m_RecClass = PF_GET_UINT16(pTemp,2);
238 pRecord->m_nTTL = PF_GET_UINT32(pTemp,4);
239 pRecord->m_nRdataLen = PF_GET_UINT16(pTemp,8);
240 if (nRdataLen > 1024*10)
242 printf("large Rdata ??");
243 nRdataLen2 = (pTemp[8] << 8) | pTemp[9];
246 // printf("Namelen=%u, Type=%u, class=%u, TTL=%u, RDLength=%u\n", m_dnsItems[ndnsIndex].nNameLength,m_dnsItems[ndnsIndex].RecType,nClass,nTTL,m_dnsItems[ndnsIndex].nRdataLen);
247 pTemp += 10 + pRecord->m_nRdataLen;
250 m_pCurrentBuffer = pTemp;
255 BJ_BOOL CDNSFrame::IsQueryFrame()
257 return !(m_nFlags&0x8000);
260 #define UNICAST_RESPONDS_REQUESTED 0x8000
261 BJ_BOOL CDNSFrame::IsWakeFrame()
264 for (int i=0; i < m_nQuestionCount; i++)
266 if (m_dnsItems[i].m_RecType == DNS_TYPE_PTR && m_dnsItems[i].m_RecClass & UNICAST_RESPONDS_REQUESTED)
272 #define DNS_HEADER_TRUNCATEED 0x0200
273 BJ_BOOL CDNSFrame::IsTruncatedFrame()
275 return (m_nFlags&DNS_HEADER_TRUNCATEED);
279 BJ_BOOL CDNSFrame::HasOnlyService(BJString sName, BJ_INT16 nRecType)
281 /* if (IsQueryFrame())
283 for (int i=0; i < m_nQuestionCount; i++)
285 CBJString sRecordName;
286 m_dnsItems[i].GetDnsRecordName(sRecordName, 0);
287 if (m_dnsItems[i].m_RecType != nRecType && nRecType != -1)
290 if (!sRecordName.Contains(sName.GetBuffer()))
296 for (int i=0; i < m_nQuestionCount+m_nAnswersCount; i++)
298 BJString sRecordName;
299 m_dnsItems[i].GetDnsRecordName(sRecordName, 0,99);
300 if (m_dnsItems[i].m_RecType != nRecType && nRecType != -1)
303 if (!sRecordName.Contains(sName.GetBuffer()))
314 CDNSRecord* CDNSFrame::FindAdditionRecord(BJString& sName,BJ_INT16 nRecType)
316 for (int i = 0; i < m_nMaxItems; i++)
318 if (m_dnsItems[i].m_RecType != nRecType && nRecType != -1)
320 BJString sRecordName;
321 m_dnsItems[i].GetDnsRecordName(sRecordName, 0,99);
322 if (sRecordName == sName)
323 return &m_dnsItems[i];
328 void CDNSFrame::SetAddress(BJIPAddr *pSourceIPAddress,BJMACAddr *pSourceMACAddress)
330 m_SourceIPAddress = *pSourceIPAddress;
331 m_SourceMACAddress = *pSourceMACAddress;
337 bool CDNSFrame::GetTracingInfo(BJ_UINT8 &platform, BJ_UINT32 &version, BJMACAddr &)
340 for (int i = m_nQuestionCount + m_nAnswersCount + m_NSCOUNT; i < m_nMaxItems; i++)
342 if (m_dnsItems[i].m_RecType == DNS_TYPE_OPT)
344 BJ_UINT8* rdata = m_dnsItems[i].GetStartofRdata();
346 BJ_UINT8* rdataEnd = rdata + m_dnsItems[i].m_nRdataLen;
348 while (rdata < rdataEnd)
350 BJ_UINT16 type = PF_GET_UINT16(rdata,0);
351 BJ_UINT16 len = PF_GET_UINT16(rdata,2);
353 if (type == DNS_EDNS0_TRACE)
355 platform = PF_GET_UINT8(rdata,4);
356 if (len == 3) // EDNS field of length 3 <rdar://15101783>
358 version = static_cast<BJ_UINT32>(PF_GET_UINT16(rdata,5));
360 else if (len == 5) // EDNS field of length 5 <rdar://15235603>
362 version = static_cast<BJ_UINT32>(PF_GET_UINT32(rdata, 5));
372 rdata += sizeof(BJ_UINT16)*2 + len;