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;
179 if (pTemp
> m_pEndBuffer
)
181 printf("Error in ParseDnsRecord pBuffer > pEndBuffer\n");
182 pRecord
->m_pStartofRec
= NULL
;
183 pRecord
->m_nNameLength
= 0;
188 pRecord
->m_pStartofRec
= pTemp
;
189 pRecord
->m_nNameLength
= 0;
190 pRecord
->m_nRdataLen
= 0;
194 while (pTemp
< m_pEndBuffer
)
202 if ((nCharCount
&(DNS_NAME_OFFSET_MASK
)) == DNS_NAME_OFFSET_MASK
)
208 if (nCharCount
> DNS_LABEL_MAX_LENGTH
)
210 printf("%d. label too long %d\n",m_nMaxItems
-1,nCharCount
);
213 if (pTemp
+ nCharCount
< m_pEndBuffer
)
216 pTemp
= m_pEndBuffer
;
219 pRecord
->m_nNameLength
= (BJ_UINT32
)(pTemp
- pRecord
->m_pStartofRec
);
221 if (eItemType
== CDNSRecord::Question
)
223 pRecord
->m_RecType
= PF_GET_UINT16(pTemp
,0);
224 pRecord
->m_RecClass
= PF_GET_UINT16(pTemp
,2);
225 pRecord
->m_nTTL
= PF_GET_UINT16(pTemp
,4);
227 // printf("Namelen=%u, Type=%u, class=%u, TTL=%u, RDLength=%u\n", m_dnsItems[ndnsIndex].nNameLength,nType,nClass,nTTL,nRdataLen);
234 pRecord
->m_RecType
= PF_GET_UINT16(pTemp
,0);
235 pRecord
->m_RecClass
= PF_GET_UINT16(pTemp
,2);
237 pRecord
->m_nTTL
= PF_GET_UINT32(pTemp
,4);
238 pRecord
->m_nRdataLen
= PF_GET_UINT16(pTemp
,8);
239 if (nRdataLen
> 1024*10)
241 printf("large Rdata ??");
243 // 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);
244 pTemp
+= 10 + pRecord
->m_nRdataLen
;
247 m_pCurrentBuffer
= pTemp
;
252 BJ_BOOL
CDNSFrame::IsQueryFrame()
254 return !(m_nFlags
&0x8000);
257 #define UNICAST_RESPONDS_REQUESTED 0x8000
258 BJ_BOOL
CDNSFrame::IsWakeFrame()
261 for (int i
=0; i
< m_nQuestionCount
; i
++)
263 if (m_dnsItems
[i
].m_RecType
== DNS_TYPE_PTR
&& m_dnsItems
[i
].m_RecClass
& UNICAST_RESPONDS_REQUESTED
)
269 #define DNS_HEADER_TRUNCATEED 0x0200
270 BJ_BOOL
CDNSFrame::IsTruncatedFrame()
272 return (m_nFlags
&DNS_HEADER_TRUNCATEED
);
276 BJ_BOOL
CDNSFrame::HasOnlyService(BJString sName
, BJ_INT16 nRecType
)
278 /* if (IsQueryFrame())
280 for (int i=0; i < m_nQuestionCount; i++)
282 CBJString sRecordName;
283 m_dnsItems[i].GetDnsRecordName(sRecordName, 0);
284 if (m_dnsItems[i].m_RecType != nRecType && nRecType != -1)
287 if (!sRecordName.Contains(sName.GetBuffer()))
293 for (int i
=0; i
< m_nQuestionCount
+m_nAnswersCount
; i
++)
295 BJString sRecordName
;
296 m_dnsItems
[i
].GetDnsRecordName(sRecordName
, 0,99);
297 if (m_dnsItems
[i
].m_RecType
!= nRecType
&& nRecType
!= -1)
300 if (!sRecordName
.Contains(sName
.GetBuffer()))
311 CDNSRecord
* CDNSFrame::FindAdditionRecord(BJString
& sName
,BJ_INT16 nRecType
)
313 for (int i
= 0; i
< m_nMaxItems
; i
++)
315 if (m_dnsItems
[i
].m_RecType
!= nRecType
&& nRecType
!= -1)
317 BJString sRecordName
;
318 m_dnsItems
[i
].GetDnsRecordName(sRecordName
, 0,99);
319 if (sRecordName
== sName
)
320 return &m_dnsItems
[i
];
325 void CDNSFrame::SetAddress(BJIPAddr
*pSourceIPAddress
,BJMACAddr
*pSourceMACAddress
)
327 m_SourceIPAddress
= *pSourceIPAddress
;
328 m_SourceMACAddress
= *pSourceMACAddress
;
334 bool CDNSFrame::GetTracingInfo(BJ_UINT8
&platform
, BJ_UINT32
&version
, BJMACAddr
&)
337 for (int i
= m_nQuestionCount
+ m_nAnswersCount
+ m_NSCOUNT
; i
< m_nMaxItems
; i
++)
339 if (m_dnsItems
[i
].m_RecType
== DNS_TYPE_OPT
)
341 BJ_UINT8
* rdata
= m_dnsItems
[i
].GetStartofRdata();
343 BJ_UINT8
* rdataEnd
= rdata
+ m_dnsItems
[i
].m_nRdataLen
;
345 while (rdata
< rdataEnd
)
347 BJ_UINT16 type
= PF_GET_UINT16(rdata
,0);
348 BJ_UINT16 len
= PF_GET_UINT16(rdata
,2);
350 if (type
== DNS_EDNS0_TRACE
)
352 platform
= PF_GET_UINT8(rdata
,4);
353 if (len
== 3) // EDNS field of length 3 <rdar://15101783>
355 version
= static_cast<BJ_UINT32
>(PF_GET_UINT16(rdata
,5));
357 else if (len
== 5) // EDNS field of length 5 <rdar://15235603>
359 version
= static_cast<BJ_UINT32
>(PF_GET_UINT32(rdata
, 5));
369 rdata
+= sizeof(BJ_UINT16
)*2 + len
;