]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSMacOSX/BonjourTop/source/DNSFrame.cpp
mDNSResponder-1096.0.2.tar.gz
[apple/mdnsresponder.git] / mDNSMacOSX / BonjourTop / source / DNSFrame.cpp
1 //
2 // DNSFrame.cpp
3 // TestTB
4 //
5 // Created by Terrin Eager on 9/26/12.
6 //
7 //
8
9 #include "DNSFrame.h"
10
11 #define DNS_LABEL_MAX_LENGTH 63
12 #define DNS_NAME_MAX_LENGTH 255
13
14 void CDNSRecord::GetDnsRecordName(BJString& ReturnString,int nLabelToSkip,int nMaxLabel)
15 {
16 GetDnsRecordNameFromBuffer(m_pStartofRec, ReturnString, nLabelToSkip, nMaxLabel);
17 }
18
19 void CDNSRecord::GetDnsRecordNameFromBuffer(BJ_UINT8* pBuffer,BJString& ReturnString,int nLabelToSkip,int nMaxLabel)
20 {
21 BJ_UINT8* pNameBuffer = NULL;
22 int nOffset = 0;
23 // char* pTemp = pReturnBuffer;
24 int nCharCount = 0;
25 int nSkippedLabels = 0;
26 int nLabelProcessed = 0;
27 ReturnString.Set(NULL,255);
28
29 if (ReturnString.GetBuffer() == NULL)
30 return;
31
32 pNameBuffer = pBuffer;
33 if (pNameBuffer == NULL)
34 {
35 return;
36 }
37
38 while (ReturnString.GetBufferLength() < 1024)
39 {
40 nCharCount = *pNameBuffer++;
41 if (nCharCount == 0)
42 break;
43
44 if ((nCharCount&(DNS_NAME_OFFSET_MASK)) == DNS_NAME_OFFSET_MASK)
45 {
46 nOffset = *pNameBuffer++;
47 nOffset |= (nCharCount&(~DNS_NAME_OFFSET_MASK)) << 8;
48 pNameBuffer = m_pDNSFrame->GetBuffer() + nOffset;
49 continue;
50 }
51
52 if (nCharCount > DNS_LABEL_MAX_LENGTH)
53 {
54 printf("label too long %d\n",nCharCount);
55 break;
56 }
57
58 if (ReturnString.GetLength() + nCharCount + 1 > DNS_NAME_MAX_LENGTH) // + 1 is for the '.' added later on
59 {
60 printf("Name exceeded limit allowed for DNS: %d\n", ReturnString.GetLength() + nCharCount + 1);
61 break;
62 }
63
64 if (nLabelToSkip > nSkippedLabels)
65 {
66 nSkippedLabels++;
67 pNameBuffer += nCharCount;
68 continue;
69 }
70 ReturnString.Append((char*)pNameBuffer, nCharCount);
71 pNameBuffer+= nCharCount;
72 nLabelProcessed++;
73
74 if (nLabelProcessed >= nMaxLabel)
75 return;
76
77 ReturnString += ".";
78 }
79 }
80
81
82
83
84 CDNSFrame::CDNSFrame()
85 {
86
87 for(int nIndex=0; nIndex < MAX_DNS_RECORDS_PER_FRAME; nIndex++)
88 m_dnsItems[nIndex].m_pDNSFrame = this;
89
90 }
91
92 CDNSRecord* CDNSFrame::GetDnsRecord(int nIndex)
93 {
94 if (nIndex > m_nMaxItems)
95 return NULL;
96 return &m_dnsItems[nIndex];
97 }
98
99 bool CDNSFrame::ParseDNSFrame(BJ_UINT8* pBuffer,BJ_INT32 nLength, BJ_UINT64 frameTime)
100 {
101 if (pBuffer == NULL)
102 return false;
103
104 int nIndex = 0;
105
106 m_Servicev4Address.Empty();
107 m_Servicev6Address.Empty();
108
109 m_pStartBuffer = pBuffer;
110 m_nFrameLen = (BJ_UINT32) nLength;
111
112 m_pCurrentBuffer = m_pStartBuffer;
113 m_pEndBuffer = m_pStartBuffer + m_nFrameLen;
114 m_Time = frameTime;
115
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);
122
123 m_nMaxItems = 0;
124
125
126
127 // printf("FrameNum= %d,nQuestionCount= %d nAnswersCount= %d NSCOUNT= %d ARCOUNT= %d\n",nFrameCount++,m_nQuestionCount, m_nAnswersCount,m_NSCOUNT, m_ARCOUNT);
128
129 m_pCurrentBuffer = m_pStartBuffer + 12;
130
131
132 for (nIndex =0; nIndex < m_nQuestionCount;nIndex++)
133 {
134 // printf("FramePosition= %ld ",m_pCurrentBuffer);
135 ParseDnsRecord(CDNSRecord::Question);
136
137 }
138 for (nIndex =0; nIndex < m_nAnswersCount;nIndex++)
139 {
140 // printf("FramePosition= %ld ",m_pCurrentBuffer);
141 ParseDnsRecord(CDNSRecord::Answer);
142 }
143 for (nIndex =0; nIndex < m_NSCOUNT;nIndex++)
144 {
145 // printf("FramePosition= %ld ",m_pCurrentBuffer);
146 ParseDnsRecord(CDNSRecord::Answer);
147 }
148 for (nIndex =0; nIndex < m_ARCOUNT;nIndex++)
149 {
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())
154 {
155 m_Servicev6Address.Setv6Raw(pRecord->GetStartofRdata());
156 }
157 if (pRecord->m_RecType == DNS_TYPE_A && m_Servicev4Address.IsEmpty())
158 {
159 m_Servicev4Address.Setv4Raw(pRecord->GetStartofRdata());
160 }
161 }
162 //
163 /// for (dnsItemsIndex =0; dnsItemsIndex < m_nQuestionCount+m_nAnswersCount;dnsItemsIndex++)
164 /// {
165 /// printf("Name = %s\n", GetDnsRecordName(&Frame,dnsItemsIndex,tempBuffer,sizeof(tempBuffer)));
166 // }
167 return true;
168 }
169
170 BJ_BOOL CDNSFrame::ParseDnsRecord(CDNSRecord::dnsItemType eItemType)
171 {
172 unsigned char nCharCount = 0;
173 BJ_UINT8* pTemp = m_pCurrentBuffer;
174 CDNSRecord* pRecord = &m_dnsItems[m_nMaxItems++];
175
176 //temp
177 BJ_UINT16 nRdataLen = 0;
178
179 if (pTemp > m_pEndBuffer)
180 {
181 printf("Error in ParseDnsRecord pBuffer > pEndBuffer\n");
182 pRecord->m_pStartofRec = NULL;
183 pRecord->m_nNameLength = 0;
184 return false;
185 }
186
187
188 pRecord->m_pStartofRec = pTemp;
189 pRecord->m_nNameLength = 0;
190 pRecord->m_nRdataLen = 0;
191
192
193 // Skip over Name;
194 while (pTemp < m_pEndBuffer)
195 {
196 nCharCount = *pTemp;
197 pTemp++;
198
199 if (nCharCount == 0)
200 break;
201
202 if ((nCharCount&(DNS_NAME_OFFSET_MASK)) == DNS_NAME_OFFSET_MASK)
203 { // offset string
204 pTemp++;
205 break;
206 }
207
208 if (nCharCount > DNS_LABEL_MAX_LENGTH)
209 {
210 printf("%d. label too long %d\n",m_nMaxItems-1,nCharCount);
211 }
212
213 if (pTemp + nCharCount < m_pEndBuffer)
214 pTemp += nCharCount;
215 else
216 pTemp = m_pEndBuffer;
217 }
218
219 pRecord->m_nNameLength = (BJ_UINT32)(pTemp - pRecord->m_pStartofRec);
220
221 if (eItemType == CDNSRecord::Question)
222 {
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);
226
227 // printf("Namelen=%u, Type=%u, class=%u, TTL=%u, RDLength=%u\n", m_dnsItems[ndnsIndex].nNameLength,nType,nClass,nTTL,nRdataLen);
228
229 pTemp += 4;
230 }
231 else
232 {
233
234 pRecord->m_RecType = PF_GET_UINT16(pTemp,0);
235 pRecord->m_RecClass = PF_GET_UINT16(pTemp,2);
236
237 pRecord->m_nTTL = PF_GET_UINT32(pTemp,4);
238 pRecord->m_nRdataLen = PF_GET_UINT16(pTemp,8);
239 if (nRdataLen > 1024*10)
240 {
241 printf("large Rdata ??");
242 }
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;
245 }
246
247 m_pCurrentBuffer = pTemp;
248
249 return true;
250 }
251
252 BJ_BOOL CDNSFrame::IsQueryFrame()
253 {
254 return !(m_nFlags&0x8000);
255 }
256
257 #define UNICAST_RESPONDS_REQUESTED 0x8000
258 BJ_BOOL CDNSFrame::IsWakeFrame()
259 {
260
261 for (int i=0; i < m_nQuestionCount; i++)
262 {
263 if (m_dnsItems[i].m_RecType == DNS_TYPE_PTR && m_dnsItems[i].m_RecClass & UNICAST_RESPONDS_REQUESTED)
264 return true;
265 }
266
267 return false;
268 }
269 #define DNS_HEADER_TRUNCATEED 0x0200
270 BJ_BOOL CDNSFrame::IsTruncatedFrame()
271 {
272 return (m_nFlags&DNS_HEADER_TRUNCATEED);
273 }
274
275
276 BJ_BOOL CDNSFrame::HasOnlyService(BJString sName, BJ_INT16 nRecType)
277 {
278 /* if (IsQueryFrame())
279 {
280 for (int i=0; i < m_nQuestionCount; i++)
281 {
282 CBJString sRecordName;
283 m_dnsItems[i].GetDnsRecordName(sRecordName, 0);
284 if (m_dnsItems[i].m_RecType != nRecType && nRecType != -1)
285 return false;
286
287 if (!sRecordName.Contains(sName.GetBuffer()))
288 return false;
289 }
290 }
291 else*/
292 {
293 for (int i=0; i < m_nQuestionCount+m_nAnswersCount; i++)
294 {
295 BJString sRecordName;
296 m_dnsItems[i].GetDnsRecordName(sRecordName, 0,99);
297 if (m_dnsItems[i].m_RecType != nRecType && nRecType != -1)
298 return false;
299
300 if (!sRecordName.Contains(sName.GetBuffer()))
301 return false;
302 }
303
304
305 }
306
307
308 return true;
309 }
310
311 CDNSRecord* CDNSFrame::FindAdditionRecord(BJString& sName,BJ_INT16 nRecType)
312 {
313 for (int i = 0; i < m_nMaxItems; i++)
314 {
315 if (m_dnsItems[i].m_RecType != nRecType && nRecType != -1)
316 continue;
317 BJString sRecordName;
318 m_dnsItems[i].GetDnsRecordName(sRecordName, 0,99);
319 if (sRecordName == sName)
320 return &m_dnsItems[i];
321 }
322 return NULL;
323 }
324
325 void CDNSFrame::SetAddress(BJIPAddr *pSourceIPAddress,BJMACAddr *pSourceMACAddress)
326 {
327 m_SourceIPAddress = *pSourceIPAddress;
328 m_SourceMACAddress = *pSourceMACAddress;
329
330
331 }
332
333
334 bool CDNSFrame::GetTracingInfo(BJ_UINT8 &platform, BJ_UINT32 &version, BJMACAddr &)
335 {
336 // Find OPT record
337 for (int i = m_nQuestionCount + m_nAnswersCount + m_NSCOUNT; i < m_nMaxItems; i++)
338 {
339 if (m_dnsItems[i].m_RecType == DNS_TYPE_OPT)
340 {
341 BJ_UINT8* rdata = m_dnsItems[i].GetStartofRdata();
342
343 BJ_UINT8* rdataEnd = rdata + m_dnsItems[i].m_nRdataLen;
344
345 while (rdata < rdataEnd)
346 {
347 BJ_UINT16 type = PF_GET_UINT16(rdata,0);
348 BJ_UINT16 len = PF_GET_UINT16(rdata,2);
349
350 if (type == DNS_EDNS0_TRACE)
351 {
352 platform = PF_GET_UINT8(rdata,4);
353 if (len == 3) // EDNS field of length 3 <rdar://15101783>
354 {
355 version = static_cast<BJ_UINT32>(PF_GET_UINT16(rdata,5));
356 }
357 else if (len == 5) // EDNS field of length 5 <rdar://15235603>
358 {
359 version = static_cast<BJ_UINT32>(PF_GET_UINT32(rdata, 5));
360 }
361 else
362 {
363 return false;
364 }
365 return true;
366 }
367
368
369 rdata += sizeof(BJ_UINT16)*2 + len;
370 }
371
372 }
373 }
374 return false;
375
376 }
377
378
379
380
381