]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSMacOSX/BonjourTop/source/BonjourTop.cpp
mDNSResponder-1096.0.2.tar.gz
[apple/mdnsresponder.git] / mDNSMacOSX / BonjourTop / source / BonjourTop.cpp
1 //
2 // BonjourTop.cpp
3 // TestTB
4 //
5 // Created by Terrin Eager on 9/26/12.
6 //
7 //
8
9 #include <stdio.h>
10 #include <errno.h>
11 #include <string.h>
12 #include <sys/socket.h>
13 #include <sys/types.h>
14 #include <netinet/in.h>
15 #include <unistd.h>
16 #include <stdlib.h>
17 #include <arpa/inet.h>
18 #include <ncurses.h>
19
20 #include "BonjourTop.h"
21 #include "DNSFrame.h"
22 #include "CaptureFile.h"
23 #include "bjsocket.h"
24 #include "bjstring.h"
25
26 #include <sys/sysctl.h>
27 #include <mach/mach.h>
28
29 #define SERVICE_IPV4 0
30 #define SERVICE_IPV6 1
31 #define APP_IPV4 2
32 #define APP_IPV6 3
33
34 #define TRACE_PLATFORM_UNKNOWN 0
35 #define TRACE_PLATFORM_OSX 1
36 #define TRACE_PLATFORM_iOS 2
37 #define TRACE_PLATFORM_APPLE_TV 3
38 #define TRACE_PLATFORM_NON_APPLE_PLATFORM 4
39 #define DISCOVERYD_TRACE_PLATFORM_OSX (1 | 0x80)
40 #define DISCOVERYD_TRACE_PLATFORM_iOS (2 | 0x80)
41 #define DISCOVERYD_TRACE_PLATFORM_APPLE_TV (3 | 0x80)
42 #define DISCOVERYD_TRACE_PLATFORM_NON_APPLE_PLATFORM (4 | 0x80)
43
44 int CDeviceNode::nCreateCount = 0;
45 static integer_t Usage(void);
46
47 char CVSFileNameExample[] ="BonjourTop";
48 char DeviceNameExample[] ="BonjourTopDevice.csv";
49
50 char Service2App[][50] = {
51 // Service_Name, Application_Name, Browse_OS_Type, Register_OS_Type
52 "_device-info._tcp.local.", "Device-Info", "?" , "?",
53 "_rfb._tcp.local.", "Finder", "X" , "?",
54 "_afpovertcp._tcp.local.", "Finder", "?" , "X",
55 "_adisk._tcp.local.", "Finder", "?" , "X",
56 "_odisk._tcp.local.", "Finder", "?" , "X",
57 "_smb._tcp.local.", "Finder", "X" , "X",
58 "_smb2._tcp.local.", "Finder", "X" , "X",
59 "_workstation._tcp.local.", "Finder", "X" , "X",
60 "_kerberos.", "Finder", "X" , "X",
61 "_nfs._tcp.local.", "Finder", "X" , "X",
62 "_ftp._tcp.local.", "Finder", "X" , "X",
63
64 "_appletv._tcp.local.", "AppleTV", "?" , "t",
65 "_appletv-v2._tcp.local.", "AppleTV", "?" , "?",
66 "_appletv-pair._tcp.local.", "AppleTV", "?" , "?",
67
68 "A", "LinkLocal", "?" , "?",
69 "AAAA", "LinkLocal", "?" , "?",
70 "*.ip6.arpa.", "LinkLocal", "?" , "?",
71 "*.arpa.", "LinkLocal", "?" , "?",
72
73 "_airplay._tcp.local.", "AirPlay", "?" , "t",
74 "_airplayTXT", "AirPlay","?" , "t",
75 "_raop._tcp.local.", "AirPlay","?" , "?",
76
77 "_ubd._tcp.local.", "Ubiquity", "?" , "?",
78 "_ubiquity._tcp.local.", "Ubiquity", "?" , "?",
79 "_ubiquityV1._tcp.local.", "Ubiquity", "?" , "?",
80 "_ubiquityV2._tcp.local.", "Ubiquity", "?" , "?",
81
82 " _ipps._tcp.local.", "Printing", "?" , "?",
83 "_ipp._tcp.local.", "Printing", "?" , "?",
84 "_ipps._tcp.local.", "Printing", "?" , "?",
85 "_ipp-tls._tcp.local.", "Printing", "?" , "?",
86 "_printer._tcp.local.", "Printing", "?" , "?",
87 "_scanner._tcp.local.", "Printing", "?" , "?",
88 "_pdl-datastream._tcp.local.", "Printing", "?" , "?",
89 "_fax-ipp._tcp.local.", "Printing", "?" , "?",
90
91 "_apple-mobdev._tcp.local.", "iTunes-WiFiSync","?" , "i",
92 "_daap._tcp.local.", "iTunes", "?" , "?",
93
94 "_sftp-ssh._tcp.local.", "Terminal", "?" , "X",
95 "_ssh._tcp.local.", "Terminal", "?" , "X",
96
97 "_sleep-proxy._udp.local.", "Sleep Proxy", "?" , "?",
98 "_keepalive._dns-sd._udp.local.","Sleep Proxy", "X" , "?",
99 "_services._dns-sd._udp.local.", "Services", "?" , "?",
100 "ANY *.ip6.arpa.", "Sleep Proxy", "?" , "?",
101 "ANY *.arpa.", "Sleep Proxy", "?" , "?",
102
103 "AirPort_presence._tcp.local.", "AirPort", "?" , "?",
104 "_airport._tcp.local.", "AirPort", "?" , "?",
105 "_presence._tcp.local.", "iChat", "X" , "X",
106 "_home-sharing._tcp.local.", "HomeSharing", "?" , "X",
107
108 "_ptp._tcp.local.", "iPhoto", "?" , "X",
109 "_ica-networking2._tcp.local.", "iPhoto", "X" , "X",
110 "_mobileiphoto._udp.local.", "iPhoto", "?" , "?",
111 "_mobileiphoto2._udp.local.", "iPhoto", "?" , "?",
112 "_dpap._tcp.local.", "iPhoto", "?" , "X",
113 "_airdrop._tcp.local.", "AirDrop", "?" , "?",
114 "_http._tcp.local.", "Safari", "X" , "X",
115 "_net-assistant._udp.local.","Apple Remote Desktop","X" , "X",
116 "_servermgr._tcp.local.", "OSX Server", "X" , "X",
117 ""
118 };
119
120 char DeviceInfo2DeviceOS[][50] = {
121 // deviceModel, deviceType
122 "MacBookAir", "X",
123 "MacBookPro", "X",
124 "Macmini", "X",
125 "iMac", "X",
126 "MacPro", "X",
127 "MacBook", "X",
128 "AAPLJ15", "X",
129 "AAPLJ41", "X",
130 "AAPLJ43", "X",
131 "AAPLJ45", "X",
132 "AAPLJ90", "X",
133 "AAPLJ17", "X",
134 "PowerMac", "X",
135
136
137 "J33AP", "t",
138 "J33iAP", "t",
139 "J71AP", "i",
140 "J72AP", "i",
141 "J75AP", "i",
142 "J85DEV", "i",
143 "K66AP", "t",
144 "N41AP", "i",
145 "N42AP", "i",
146 "N48AP", "i",
147 "N51AP", "i",
148 "N53AP", "i",
149 "N78AP", "i",
150 "P101AP", "i",
151 "P102AP", "i",
152 "P103AP", "i",
153 "P105AP", "i",
154 "P106AP", "i",
155 "P107AP", "i",
156 "AirPort", "b",
157 "TimeCapsule", "b",
158 ""
159 };
160
161 char Name2DeviceOS[][50] = {
162 // Name contains, osType
163 "iPhone", "i",
164 "phone", "i",
165 "Phone", "i",
166 "iPod", "i",
167 "iPad", "i",
168 "ipad", "i",
169 "Apple-TV", "t",
170 "AppleTV", "t",
171 "MacBook", "X",
172 "macbook", "X",
173 "iMac", "X",
174 "macmini", "X",
175 ""
176 };
177
178 BJ_UINT64 Hash(const char* pStr);
179 BJ_UINT64 Hash2(char* pStr);
180
181
182 CSocketStats::CSocketStats()
183 {
184 Init();
185
186 }
187 void CSocketStats::Init()
188 {
189 m_nFrameCount = 0;
190
191 m_nQuestionOnlyFrames = 0;
192 m_nAnswerOnlyFrames = 0;
193 m_nQandAFrames = 0;
194
195 m_SampleDay = 0;
196 }
197
198 void CSocketStats::Clear()
199 {
200 Init();
201 }
202
203 CBonjourTop::CBonjourTop()
204 {
205
206 m_bCursers = true;
207 m_pTcpDumpFileName = NULL;
208 m_pExportFileName = CVSFileNameExample;
209 m_DeviceFileName = DeviceNameExample;
210
211 m_nFrameCount = 0;
212 m_nTotalBytes = 0;
213
214 m_StartTime = m_EndTime = time(NULL);
215
216 m_SnapshotSeconds = 0;
217
218 m_MinAnswerCountForTruncatedFrames = 0;
219 m_AvgAnswerCountForTruncatedFrames = 0;
220 m_MaxAnswerCountForTruncatedFrames = 0;
221
222 window_size_changed = false;
223 m_bImportExportDeviceMap = false;
224
225 // loadup application mapping
226 for(int i=0; Service2App[i][0] != 0;)
227 {
228 BJString a(Service2App[i++]);
229
230 m_Service2AppMap.FindwithAddRecord(&a)->value = Service2App[i++];
231 m_Service2osBrowseMap.FindwithAddRecord(&a)->value = Service2App[i++];
232 m_Service2osRegisterMap.FindwithAddRecord(&a)->value = Service2App[i++];
233
234 }
235
236
237 m_CurrentDisplay = CBonjourTop::BJ_DISPLAY_APP;
238 // m_CurrentDisplay = CBonjourTop::BJ_DISPLAY_SERVICE;
239
240 Usage();
241
242 }
243
244 static int CbClearDataDevice(const void* pNode, const void*)
245 {
246 CDeviceNode* pDeviceRecord = (CDeviceNode*)pNode;
247
248 pDeviceRecord->ClearData();
249 return 0;
250 }
251
252 void CBonjourTop::Reset()
253 {
254 m_nFrameCount = 0;
255 m_nTotalBytes = 0;
256
257 m_MinAnswerCountForTruncatedFrames = 0;
258 m_AvgAnswerCountForTruncatedFrames = 0;
259 m_MaxAnswerCountForTruncatedFrames = 0;
260
261 m_StartTime = m_EndTime = time(NULL);
262
263 m_ServicePtrCache.ClearAll();
264 m_ApplPtrCache.ClearAll();
265
266 m_ServicePtrCacheIPv6.ClearAll();
267 m_ApplPtrCacheIPv6.ClearAll();
268
269 // Clear all data in the map
270 m_AppBreakdownIPv4OSX.clear();
271 m_AppBreakdownIPv4iOS.clear();
272 m_AppBreakdownIPv6OSX.clear();
273 m_AppBreakdownIPv6iOS.clear();
274
275 m_ServiceBreakdownIPv4OSX.clear();
276 m_ServiceBreakdownIPv4iOS.clear();
277 m_ServiceBreakdownIPv6OSX.clear();
278 m_ServiceBreakdownIPv6iOS.clear();
279
280 // Clear Socket Status
281 for (int i = 0; i < NUM_SOCKET_STATUS; i++)
282 {
283 m_SocketStatus[i].Clear();
284 }
285
286 for (int i = 0; i < HOURS_IN_DAY; i++)
287 {
288 for (int j = 0; j < MINUTES_IN_HOUR; j++)
289 {
290 m_MinSnapshot[i][j].Clear();
291 }
292 }
293
294 CDeviceNode* pDeviceNode = m_DeviceMap.GetRoot();
295 if (pDeviceNode)
296 {
297 pDeviceNode->CallBack(&CbClearDataDevice,NULL);
298 }
299
300 }
301
302 void CBonjourTop::SetIPAddr(const char* pStr)
303 {
304 m_IPv4Addr.Set(pStr);
305
306 }
307
308 void CBonjourTop::UpdateRecord(CStringTree& Cache,CDNSRecord* pDNSRecord,BJString& RecordName,BJString& ServiceName,BJ_UINT32 nBytes,bool bGoodbye)
309 {
310 BJ_UINT64 nHashValue = 0;
311 char deviceOS = '?';
312
313 nHashValue = Hash(RecordName.GetBuffer());
314 CStringNode* pRecord = Cache.Find(&nHashValue);
315 if (pRecord == NULL)
316 {
317 pRecord = (CStringNode*) Cache.FindwithAddRecord(&nHashValue);
318 strlcpy(pRecord->m_Value, RecordName.GetBuffer(), sizeof(pRecord->m_Value));
319 }
320
321 if (pRecord == NULL)
322 return;
323 CDeviceNode dummyDevice;
324 CDeviceNode *device;
325 CIPDeviceNode *pipNode = m_IPtoNameMap.Find(&m_Frame.m_SourceIPAddress);
326
327 device = (pipNode)? pipNode->pDeviceNode : &dummyDevice;
328 pRecord->m_nBytes += 10 + nBytes;
329 deviceOS = device->GetDeviceOS();
330 device->frameTotal.Increment(m_nFrameCount);
331
332 if (pRecord->m_nLastFrameIndex != m_nFrameCount)
333 {
334 pRecord->m_nLastFrameIndex = m_nFrameCount;
335
336 pRecord->m_nFrames++;
337 if (deviceOS == 't' || deviceOS == 'i')
338 {
339 pRecord->m_nFramesiOS++;
340 }
341 else if (deviceOS == 'X')
342 {
343 pRecord->m_nFramesOSX++;
344 }
345 }
346
347 // Update Total Device Count
348 if (pRecord->m_DeviceTotalTree.Find(&m_Frame.m_SourceIPAddress) == NULL)
349 {
350 pRecord->m_nDeviceTotalCount++;
351 pRecord->m_DeviceTotalTree.FindwithAddRecord(&m_Frame.m_SourceIPAddress);
352 }
353
354 if (m_Frame.IsQueryFrame())
355 {
356 GetOSTypeFromQuery(pDNSRecord, ServiceName);
357 device->questionFrame.Increment(m_nFrameCount);
358 if (pRecord->m_nLastQueryFrameIndex != m_nFrameCount)
359 {
360 pRecord->m_nLastQueryFrameIndex = m_nFrameCount;
361
362 pRecord->m_nQuestionFrames++;
363
364 if (deviceOS == 't' || deviceOS == 'i')
365 {
366 pRecord->m_nQuestionFramesiOS++;
367 }
368 else if (deviceOS == 'X')
369 {
370 pRecord->m_nQuestionFramesOSX++;
371 }
372
373 if (pRecord->m_DeviceAskingTree.Find(&m_Frame.m_SourceIPAddress) == NULL)
374 {
375 pRecord->m_nDeviceAskingCount++;
376 pRecord->m_DeviceAskingTree.FindwithAddRecord(&m_Frame.m_SourceIPAddress);
377 }
378 }
379 }
380 else
381 {
382 GetOSTypeFromRegistration(pDNSRecord,ServiceName);
383
384 device->answerFrame.Increment(m_nFrameCount);
385 if (pRecord->m_nLastRespondsFrameIndex != m_nFrameCount)
386 {
387 pRecord->m_nLastRespondsFrameIndex = m_nFrameCount;
388
389 pRecord->m_nAnswerFrames++;
390 if (deviceOS == 't' || deviceOS == 'i')
391 {
392 pRecord->m_nAnswerFramesiOS++;
393 }
394 else if (deviceOS == 'X')
395 {
396 pRecord->m_nAnswerFramesOSX++;
397 }
398
399 if (bGoodbye)
400 {
401 pRecord->m_nGoodbyeFrames++;
402 }
403
404 if (pRecord->m_DeviceAnsweringTree.Find(&m_Frame.m_SourceIPAddress) == NULL)
405 {
406 pRecord->m_nDeviceAnsweringCount++;
407 pRecord->m_DeviceAnsweringTree.FindwithAddRecord(&m_Frame.m_SourceIPAddress);
408 }
409 }
410 }
411
412 if (m_Frame.IsWakeFrame())
413 {
414 if (pRecord->m_nLastWakeFrameIndex != m_nFrameCount)
415 {
416 pRecord->m_nLastWakeFrameIndex = m_nFrameCount;
417 if (pRecord->m_lastQUFrameTime +1000000ll < m_Frame.GetTime() || pRecord->m_lastQUFrameTime == 0) // last qu frame has been over 1 sec
418 {
419 pRecord->m_nWakeFrames++;
420 pRecord->m_lastQUFrameTime = m_Frame.GetTime();
421 device->QUFrame.Increment(m_nFrameCount);
422 }
423 pRecord->m_lastQUFrameTime = m_Frame.GetTime();
424 }
425 }
426
427
428 }
429
430 void CBonjourTop::UpdateShortRecordHelper(BJ_UINT32 cacheType, BJ_UINT32 tracePlatform, BJ_UINT32 traceVersion, char deviceOS, CDNSRecord* pDNSRecord,BJString& RecordName,BJString& ServiceName,BJ_UINT32 nBytes,bool bGoodbye)
431 {
432 bool isOSX = false;
433 BJString versionNumber = "mDNSResponder-";
434 const int version_max_length = 11; // largest number is 0xffffffff = 4294967295
435 char versionChar[version_max_length];
436
437 CStringShortTree *cache;
438 map<BJString, CStringShortTree*>* myMap;
439
440 if ((tracePlatform | 0x80) == tracePlatform)
441 {
442 versionNumber = "Discoveryd-";
443 }
444
445 snprintf(versionChar, sizeof(versionChar), "%u", 0); // Set versionChar to "0" by default
446 if (tracePlatform == TRACE_PLATFORM_UNKNOWN) // Pre iOS 7 or Pre OSX 10.9
447 {
448 if (deviceOS == 'i' || deviceOS == 't') // Pre iOS 7
449 {
450 isOSX = false;
451 }
452 else if (deviceOS == 'X') // Pre OSX 10.9
453 {
454 isOSX = true;
455 }
456 }
457 else if ((tracePlatform == TRACE_PLATFORM_OSX) || (tracePlatform == DISCOVERYD_TRACE_PLATFORM_OSX)) // >= OSX 10.9
458 {
459 isOSX = true;
460 snprintf(versionChar, sizeof(versionChar), "%u", traceVersion);
461 }
462 else if ((tracePlatform == TRACE_PLATFORM_iOS) || (tracePlatform == DISCOVERYD_TRACE_PLATFORM_iOS)) // >= iOS 7.x
463 {
464 isOSX = false;
465 snprintf(versionChar, sizeof(versionChar), "%u", traceVersion);
466 }
467 else if ((tracePlatform == TRACE_PLATFORM_APPLE_TV) || (tracePlatform == DISCOVERYD_TRACE_PLATFORM_APPLE_TV))
468 {
469 snprintf(versionChar, sizeof(versionChar), "%u", traceVersion);
470 }
471
472 versionNumber += (const char*)versionChar;
473
474 switch (cacheType) {
475 case SERVICE_IPV4:
476 if (isOSX)
477 {
478 myMap = &m_ServiceBreakdownIPv4OSX;
479 }
480 else
481 {
482 myMap = &m_ServiceBreakdownIPv4iOS;
483 }
484 break;
485 case SERVICE_IPV6:
486 if (isOSX)
487 {
488 myMap = &m_ServiceBreakdownIPv6OSX;
489 }
490 else
491 {
492 myMap = &m_ServiceBreakdownIPv6iOS;
493 }
494 break;
495 case APP_IPV4:
496 if (isOSX)
497 {
498 myMap = &m_AppBreakdownIPv4OSX;
499 }
500 else
501 {
502 myMap = &m_AppBreakdownIPv4iOS;
503 }
504 break;
505 case APP_IPV6:
506 if (isOSX)
507 {
508 myMap = &m_AppBreakdownIPv6OSX;
509 }
510 else
511 {
512 myMap = &m_AppBreakdownIPv6iOS;
513 }
514 break;
515
516 default:
517 return;
518 break;
519 }
520
521 if (myMap->find(versionNumber) == myMap->end()) // Version number not found. Create new record
522 {
523 myMap->insert(std::pair<BJString, CStringShortTree*>(versionNumber, new CStringShortTree()));
524 }
525 cache = (*myMap)[versionNumber];
526 UpdateShortRecord(cache, pDNSRecord, RecordName, ServiceName, nBytes, bGoodbye);
527 }
528
529 void CBonjourTop::UpdateShortRecord(CStringShortTree* Cache,CDNSRecord* pDNSRecord,BJString& RecordName,BJString& ServiceName,BJ_UINT32 nBytes,bool bGoodbye)
530 {
531 if (Cache == NULL)
532 {
533 return;
534 }
535
536 BJ_UINT64 nHashValue = 0;
537
538 nHashValue = Hash(RecordName.GetBuffer());
539 CStringShortNode* pRecord = Cache->Find(&nHashValue);
540 if (pRecord == NULL)
541 {
542 pRecord = (CStringShortNode*) Cache->FindwithAddRecord(&nHashValue);
543 if (pRecord)
544 strlcpy(pRecord->m_Value, RecordName.GetBuffer(), sizeof(pRecord->m_Value));
545 }
546
547 if (pRecord == NULL)
548 {
549 return;
550 }
551
552 CDeviceNode dummyDevice;
553 CDeviceNode *device;
554 CIPDeviceNode *pipNode = m_IPtoNameMap.Find(&m_Frame.m_SourceIPAddress);
555
556 device = (pipNode)? pipNode->pDeviceNode : &dummyDevice;
557 pRecord->m_nBytes += 10 + nBytes;
558 device->frameTotal.Increment(m_nFrameCount);
559
560 if (pRecord->m_nLastFrameIndex != m_nFrameCount)
561 {
562 pRecord->m_nLastFrameIndex = m_nFrameCount;
563 pRecord->m_nFrames++;
564 }
565
566 // Update Total Device Count
567 if (pRecord->m_DeviceTotalTree.Find(&m_Frame.m_SourceIPAddress) == NULL)
568 {
569 pRecord->m_nDeviceTotalCount++;
570 pRecord->m_DeviceTotalTree.FindwithAddRecord(&m_Frame.m_SourceIPAddress);
571 }
572
573 if (m_Frame.IsQueryFrame())
574 {
575 GetOSTypeFromQuery(pDNSRecord, ServiceName);
576 device->questionFrame.Increment(m_nFrameCount);
577 if (pRecord->m_nLastQueryFrameIndex != m_nFrameCount)
578 {
579 pRecord->m_nLastQueryFrameIndex = m_nFrameCount;
580
581 pRecord->m_nQuestionFrames++;
582
583 if (pRecord->m_DeviceAskingTree.Find(&m_Frame.m_SourceIPAddress) == NULL)
584 {
585 pRecord->m_nDeviceAskingCount++;
586 pRecord->m_DeviceAskingTree.FindwithAddRecord(&m_Frame.m_SourceIPAddress);
587 }
588
589 }
590 }
591 else
592 {
593 GetOSTypeFromRegistration(pDNSRecord,ServiceName);
594
595 device->answerFrame.Increment(m_nFrameCount);
596 if (pRecord->m_nLastRespondsFrameIndex != m_nFrameCount)
597 {
598 pRecord->m_nLastRespondsFrameIndex = m_nFrameCount;
599
600 pRecord->m_nAnswerFrames++;
601
602 if (bGoodbye)
603 {
604 pRecord->m_nGoodbyeFrames++;
605 }
606
607 if (pRecord->m_DeviceAnsweringTree.Find(&m_Frame.m_SourceIPAddress) == NULL)
608 {
609 pRecord->m_nDeviceAnsweringCount++;
610 pRecord->m_DeviceAnsweringTree.FindwithAddRecord(&m_Frame.m_SourceIPAddress);
611 }
612 }
613 }
614
615 if (m_Frame.IsWakeFrame())
616 {
617 if (pRecord->m_nLastWakeFrameIndex != m_nFrameCount)
618 {
619 pRecord->m_nLastWakeFrameIndex = m_nFrameCount;
620 if (pRecord->m_lastQUFrameTime +1000000ll < m_Frame.GetTime() || pRecord->m_lastQUFrameTime == 0) // last qu frame has been over 1 sec
621 {
622 pRecord->m_nWakeFrames++;
623 pRecord->m_lastQUFrameTime = m_Frame.GetTime();
624 device->QUFrame.Increment(m_nFrameCount);
625 }
626 pRecord->m_lastQUFrameTime = m_Frame.GetTime();
627 }
628 }
629
630
631 }
632
633 void CBonjourTop::GetOSTypeFromQuery(CDNSRecord *pDNSRecord,BJString& ServiceName)
634 {
635 if (pDNSRecord->m_RecType == DNS_TYPE_PTR)
636 {
637 StringMapNode* pStringNode = m_Service2osBrowseMap.Find(&ServiceName);
638 if (pStringNode && *pStringNode->value.GetBuffer() != '?')
639 {
640 CIPDeviceNode *ipNode = m_IPtoNameMap.FindwithAddRecord(&m_Frame.m_SourceIPAddress);
641 if (ipNode->pDeviceNode)
642 {
643 StringMapNode* pStringNode_temp = m_Service2osBrowseMap.Find(&ServiceName);
644 ipNode->pDeviceNode->SetDeviceOS(*pStringNode_temp->value.GetBuffer(),ServiceName.GetBuffer());
645 }
646 }
647 }
648 }
649
650 void CBonjourTop::GetOSTypeFromRegistration(CDNSRecord *pDNSRecord,BJString& ServiceName)
651 {
652 CDeviceNode* deviceNode = NULL;
653 BJString sDeviceName;
654
655 if (pDNSRecord->m_RecType == DNS_TYPE_PTR)
656 {
657 BJString sInstanceName;
658 pDNSRecord->GetRdata(sInstanceName,0,99);
659 CDNSRecord* pSRVRecord = m_Frame.FindAdditionRecord(sInstanceName, DNS_TYPE_SRV);
660 if (pSRVRecord)
661 {
662 pSRVRecord->GetRdata(sDeviceName,0,1);
663 }
664 else
665 {
666 sDeviceName = sInstanceName;
667 }
668 deviceNode = m_DeviceMap.Find(&sDeviceName);
669 }
670
671 // Name guess
672 if (Name2OSType(sDeviceName,deviceNode))
673 return;
674
675 StringMapNode* pStringNode = m_Service2osRegisterMap.Find(&ServiceName);
676
677 if (pStringNode == NULL || *pStringNode->value.GetBuffer() == '?')
678 return;
679
680
681
682 if (sDeviceName.GetLength() > 0)
683 {
684 // update global device table with os type
685 if (deviceNode)
686 {
687 deviceNode->SetDeviceOS(*pStringNode->value.GetBuffer(),ServiceName.GetBuffer());
688 }
689 }
690 }
691 bool CBonjourTop::Name2OSType(BJString name,CDeviceNode* device)
692 {
693 if (device == NULL)
694 return false;
695 // try to set device type from common names
696 for (int i=0; Name2DeviceOS[i][0] != 0; i +=2)
697 {
698 if (name.Contains(Name2DeviceOS[i]))
699 {
700 device->SetDeviceOS(Name2DeviceOS[i+1][0], "Name Mapping");
701 return true;
702 }
703 }
704 return false;
705 }
706 void CBonjourTop::ProcessFrame(BJ_UINT8* pBuffer,BJ_INT32 nLength,BJ_UINT64 nFrameTime)
707 {
708
709 m_Frame.ParseDNSFrame(pBuffer, nLength, nFrameTime);
710
711 if (m_Collection.IsValid())
712 {
713 // setup static collectby
714 CollectByPacketCount::nFrameIndex = m_nFrameCount;
715 CollectBySameSubnetDiffSubnet::bSameSubnet = m_Frame.m_SourceIPAddress.IsIPv6()? true: m_IPv4Addr.IsSameSubNet(&m_Frame.m_SourceIPAddress);
716 m_Collection.ProcessFrame(&m_Frame);
717 return;
718 }
719
720 if (m_Frame.IsTruncatedFrame())
721 {
722 if (m_Frame.GetAnswerCount() > 0)
723 {
724 if (m_AvgAnswerCountForTruncatedFrames)
725 {
726 m_AvgAnswerCountForTruncatedFrames += m_Frame.GetAnswerCount();
727 m_AvgAnswerCountForTruncatedFrames /=2;
728 }
729 else
730 m_AvgAnswerCountForTruncatedFrames += m_Frame.GetAnswerCount();
731
732 if (m_MinAnswerCountForTruncatedFrames > m_Frame.GetAnswerCount() || m_MinAnswerCountForTruncatedFrames == 0)
733 m_MinAnswerCountForTruncatedFrames = m_Frame.GetAnswerCount();
734 if (m_MaxAnswerCountForTruncatedFrames < m_Frame.GetAnswerCount())
735 m_MaxAnswerCountForTruncatedFrames = m_Frame.GetAnswerCount();
736
737 }
738 }
739
740 // find min snapshot bucket
741 time_t now = time(NULL);
742 struct tm* timeStruct = localtime(&now);
743 if (m_MinSnapshot[timeStruct->tm_hour][timeStruct->tm_min].m_SampleDay != timeStruct->tm_mday)
744 {
745 //Reset Snapshot 24 hour wrap around
746 m_MinSnapshot[timeStruct->tm_hour][timeStruct->tm_min].Init();
747 m_MinSnapshot[timeStruct->tm_hour][timeStruct->tm_min].m_SampleDay = timeStruct->tm_mday;
748
749 }
750 m_MinSnapshot[timeStruct->tm_hour][timeStruct->tm_min].m_nFrameCount++;
751
752 if (m_Frame.GetQuestionCount() == 0 && m_Frame.GetAnswerCount() > 0)
753 m_SocketStatus[0].m_nAnswerOnlyFrames++;
754 else if (m_Frame.GetQuestionCount() > 0 && m_Frame.GetAnswerCount() == 0)
755 m_SocketStatus[0].m_nQuestionOnlyFrames++;
756 else
757 m_SocketStatus[0].m_nQandAFrames++;
758
759 BJString InstanceName;
760 BJString RecordName;
761 BJString ApplRecordName;
762
763 /// first get the name to address
764 for (int dnsItemsIndex =m_Frame.GetQuestionCount(); dnsItemsIndex < m_Frame.GetMaxRecords();dnsItemsIndex++)
765 {
766 CDNSRecord* pDNSRecord = m_Frame.GetDnsRecord(dnsItemsIndex);
767 if (pDNSRecord == NULL)
768 continue;
769
770 if (pDNSRecord->m_RecType == DNS_TYPE_A)
771 {
772 BJString sName;
773 pDNSRecord->GetDnsRecordName(sName, 0, 1);
774 BJIPAddr ip;
775 ip.Setv4Raw(pDNSRecord->GetStartofRdata());
776
777 CDeviceNode* device = m_DeviceMap.FindwithAddRecord(&sName);
778 device->ipAddressv4 = ip;
779
780 // create ip to name mapping
781 CIPDeviceNode* pipNode = m_IPtoNameMap.FindwithAddRecord(&ip);
782
783 if (pipNode->pDeviceNode && pipNode->pDeviceNode->bIPName && pipNode->pDeviceNode->m_Key != device->m_Key)
784 {
785 pipNode->pDeviceNode->bDuplicate = true;
786 device->MergeData(pipNode->pDeviceNode);
787 pipNode->pDeviceNode->ClearData();
788 // remap IPv6
789 if (!pipNode->pDeviceNode->ipAddressv6.IsEmpty())
790 {
791 CIPDeviceNode* ipv6Node = m_IPtoNameMap.Find(&pipNode->pDeviceNode->ipAddressv6);
792 if (ipv6Node)
793 ipv6Node->pDeviceNode = device;
794 }
795 }
796
797 pipNode->pDeviceNode = device;
798 Name2OSType(sName,device);
799 }
800
801 if (pDNSRecord->m_RecType == DNS_TYPE_AAAA)
802 {
803 BJString sName;
804 pDNSRecord->GetDnsRecordName(sName, 0, 1);
805 BJIPAddr ip;
806 ip.Setv6Raw(pDNSRecord->GetStartofRdata());
807
808 if (ip.IsIPv6LinkLocal())
809 {
810 CDeviceNode* device = m_DeviceMap.FindwithAddRecord(&sName);
811 device->ipAddressv6 = ip;
812
813 // create ip to name mapping
814 CIPDeviceNode* pipNode = m_IPtoNameMap.FindwithAddRecord(&ip);
815
816 if (pipNode->pDeviceNode && pipNode->pDeviceNode->bIPName && pipNode->pDeviceNode->m_Key != device->m_Key)
817 {
818 pipNode->pDeviceNode->bDuplicate = true;
819 device->MergeData(pipNode->pDeviceNode);
820 pipNode->pDeviceNode->ClearData();
821 // remap IPv4
822 if (!pipNode->pDeviceNode->ipAddressv4.IsEmpty())
823 {
824 CIPDeviceNode* ipv4Node = m_IPtoNameMap.Find(&pipNode->pDeviceNode->ipAddressv4);
825 if (ipv4Node)
826 ipv4Node->pDeviceNode = device;
827 }
828 }
829
830 pipNode->pDeviceNode = device;
831 Name2OSType(sName,device);
832 }
833 }
834 if (pDNSRecord->m_RecType == DNS_TYPE_SRV)
835 { // Save SVR to Target
836 BJString sName;
837 pDNSRecord->GetDnsRecordName(sName, 0, 1);
838 StringMapNode *node = SVRtoDeviceName.FindwithAddRecord(&sName);
839 pDNSRecord->GetRdata(node->value, 0, 1);
840 }
841 }
842
843 CIPDeviceNode* pipNode = m_IPtoNameMap.FindwithAddRecord(&m_Frame.m_SourceIPAddress);
844 CDeviceNode* device = pipNode->pDeviceNode;
845 if (device == NULL)
846 {
847 // find the device by mac address
848 CMACAddrDeviceNode *macDevice = m_MACtoDevice.FindwithAddRecord(&m_Frame.m_SourceMACAddress);
849 device = macDevice->device;
850 if (device == NULL)
851 {
852 // auto create a device record
853 BJString name = m_Frame.m_SourceIPAddress.GetString();
854 device = m_DeviceMap.FindwithAddRecord(&name);
855 device->bIPName = true;
856 macDevice->device = device;
857 }
858
859 if (m_Frame.m_SourceIPAddress.IsIPv4())
860 device->ipAddressv4 = m_Frame.m_SourceIPAddress;
861 else
862 device->ipAddressv6 = m_Frame.m_SourceIPAddress;
863 if (device->macAddress.IsEmpty())
864 device->macAddress = m_Frame.m_SourceMACAddress;
865
866 pipNode->pDeviceNode = device;
867 }
868 device->bHasFrames = true;
869 // update mac address
870 if (m_Frame.IsQueryFrame() || device->GetDeviceOS() == 'i' ) // iOS don't use BSP so we can use SourceIP
871 {
872 if (m_Frame.m_SourceIPAddress.IsIPv4())
873 device->ipAddressv4 = m_Frame.m_SourceIPAddress;
874 if (m_Frame.m_SourceIPAddress.IsIPv6())
875 device->ipAddressv6 =m_Frame.m_SourceIPAddress;
876 device->macAddress = m_Frame.m_SourceMACAddress;
877 }
878
879 BJ_UINT8 traceplatform = TRACE_PLATFORM_UNKNOWN;
880 BJ_UINT32 traceversion = 0;
881 BJMACAddr traceMac;
882 if (device /*&& device->GetDeviceOS() == '?' */&& m_Frame.GetTracingInfo(traceplatform, traceversion, traceMac))
883 {
884 // printf("Tracing Data found platform=%d traceversion=%d\n",traceplatform,traceversion);
885 char platformMap[]= "?Xitw";
886 device->SetDeviceOS((traceplatform < 5) ? platformMap[traceplatform] : '?', "EDNS0 Trace");
887 if ((traceplatform == TRACE_PLATFORM_OSX) || (traceplatform == DISCOVERYD_TRACE_PLATFORM_OSX))
888 {
889 device->bOSXWithEDNSField = true;
890 }
891 else if ((traceplatform == TRACE_PLATFORM_iOS) || (traceplatform == DISCOVERYD_TRACE_PLATFORM_iOS))
892 {
893 device->biOSWithEDNSField = true;
894 }
895 }
896
897 for (int dnsItemsIndex =0; dnsItemsIndex < m_Frame.GetQuestionCount()+m_Frame.GetAnswerCount();dnsItemsIndex++)
898 {
899 RecordName = "";
900 ApplRecordName = "";
901 InstanceName = "";
902 // printf("Name = %s\n", GetDnsRecordName(&Frame,dnsItemsIndex,tempBuffer,sizeof(tempBuffer),0));
903
904 CDNSRecord* pDNSRecord = m_Frame.GetDnsRecord(dnsItemsIndex);
905 if (pDNSRecord == NULL)
906 continue;
907
908 pDNSRecord->GetDnsRecordName(RecordName,0,99);
909 InstanceName = RecordName;
910
911 if (RecordName.Contains("_kerberos."))
912 {
913 RecordName = "_kerberos.";
914 }
915 else
916 pDNSRecord->GetDnsRecordName(RecordName, (pDNSRecord->m_RecType == DNS_TYPE_PTR)?0:1,99);
917
918 if (pDNSRecord->m_RecType == DNS_TYPE_PTR)
919 {
920 if (RecordName.Contains(".ip6.arpa."))
921 RecordName = "*.ip6.arpa.";
922 else if (RecordName.Contains(".arpa."))
923 RecordName = "*.arpa.";
924 }
925 if (pDNSRecord->m_RecType == DNS_TYPE_A)
926 RecordName = "A";
927 if (pDNSRecord->m_RecType == DNS_TYPE_AAAA)
928 RecordName = "AAAA";
929 if (pDNSRecord->m_RecType == 255)
930 {
931 if (RecordName.Contains(".ip6.arpa."))
932 RecordName = "ANY *.ip6.arpa.";
933 else if (RecordName.Contains(".arpa."))
934 RecordName = "ANY *.arpa.";
935 else
936 RecordName = "Any";
937 }
938 if (RecordName.Contains("_sub."))
939 {
940 pDNSRecord->GetDnsRecordName(RecordName,2,99); /// skip first label and _sub. label
941 }
942
943 BJ_UINT32 nBytes = pDNSRecord->m_nNameLength + pDNSRecord->m_nRdataLen;
944
945 m_nTotalBytes += 10 + nBytes;
946
947 if (m_Frame.m_SourceIPAddress.IsIPv4())
948 {
949 UpdateRecord(m_ServicePtrCache,pDNSRecord,RecordName,RecordName, nBytes, (pDNSRecord->m_nTTL == 0));
950 UpdateShortRecordHelper(SERVICE_IPV4, traceplatform, traceversion, device->GetDeviceOS(), pDNSRecord, RecordName, RecordName, nBytes, (pDNSRecord->m_nTTL == 0));
951 }
952 else
953 {
954 UpdateRecord(m_ServicePtrCacheIPv6,pDNSRecord,RecordName,RecordName, nBytes, (pDNSRecord->m_nTTL == 0));
955 UpdateShortRecordHelper(SERVICE_IPV6, traceplatform, traceversion, device->GetDeviceOS(), pDNSRecord, RecordName, RecordName, nBytes, (pDNSRecord->m_nTTL == 0));
956 }
957
958 // Add application to cache
959 if (RecordName.GetLength() != 0)
960 {
961
962 ApplRecordName = RecordName;
963 StringMapNode* pNode;
964 pNode = m_Service2AppMap.Find(&ApplRecordName);
965 if (pNode && ApplRecordName.GetBuffer() != NULL)
966 {
967 ApplRecordName = pNode->value.GetBuffer();
968 if ( ApplRecordName == "Device-Info")
969 {
970 // find device record
971 BJString svrName;
972 pDNSRecord->GetDnsRecordName(svrName, 0, 1);
973 StringMapNode *nodeName = SVRtoDeviceName.Find(&svrName);
974
975 CDeviceNode* pDeviceNode = nodeName ? m_DeviceMap.Find(&nodeName->value) : NULL;
976
977 if (pDeviceNode)
978 {
979 BJString DeviceInfo;
980 DeviceInfo.Set((char*)pDNSRecord->GetStartofRdata(),MIN(pDNSRecord->m_nRdataLen,50));
981 char osType = '?';
982
983 for (int i=0; DeviceInfo2DeviceOS[i][0] != 0; i+=2)
984 {
985 if (DeviceInfo.Contains(DeviceInfo2DeviceOS[i]))
986 {
987 osType = *DeviceInfo2DeviceOS[i+1];
988 if (pDeviceNode->GetDeviceOS() != *DeviceInfo2DeviceOS[i])
989 {
990 pDeviceNode->SetDeviceOS(osType,"_device-info._tcp.local.");
991 pDeviceNode->SetModel(DeviceInfo2DeviceOS[i]);
992 }
993 break;
994 }
995 }
996
997
998 if (osType == 'X' || (pDeviceNode && pDeviceNode->GetDeviceOS() == 'X'))
999 ApplRecordName = "Finder";
1000 if (osType == 't' || (pDeviceNode && pDeviceNode->GetDeviceOS() == 't'))
1001 ApplRecordName = "AirPlay";
1002
1003 if (pDeviceNode && pDeviceNode->GetDeviceOS() == '?' && pDNSRecord->m_nRdataLen > 0)
1004 {
1005 BJString DeviceInfo_temp;
1006 DeviceInfo_temp.Set((char*)pDNSRecord->GetStartofRdata(),MIN(pDNSRecord->m_nRdataLen,25));
1007 }
1008 }
1009 }
1010 }
1011 else
1012 {
1013 ApplRecordName = "Other";
1014 }
1015
1016 if (m_Frame.m_SourceIPAddress.IsIPv4())
1017 {
1018 UpdateRecord(m_ApplPtrCache,pDNSRecord,ApplRecordName,RecordName, nBytes, (pDNSRecord->m_nTTL == 0));
1019 UpdateShortRecordHelper(APP_IPV4, traceplatform, traceversion, device->GetDeviceOS(), pDNSRecord, ApplRecordName, RecordName, nBytes, (pDNSRecord->m_nTTL == 0));
1020
1021 }
1022 else
1023 {
1024 UpdateRecord(m_ApplPtrCacheIPv6,pDNSRecord,ApplRecordName,RecordName, nBytes, (pDNSRecord->m_nTTL == 0));
1025 UpdateShortRecordHelper(APP_IPV6, traceplatform, traceversion, device->GetDeviceOS(), pDNSRecord, ApplRecordName, RecordName, nBytes, (pDNSRecord->m_nTTL == 0));
1026 }
1027
1028 }
1029
1030 }
1031 }
1032
1033
1034 class CSortOptions
1035 {
1036
1037 public:
1038 CStringTree m_SortedCache;
1039 int m_nSortCol;
1040
1041 };
1042 static int CbPrintResults(const void* pNode, const void* pParam)
1043 {
1044 CStringNode* pRecord = (CStringNode*)pNode;
1045 CSortOptions* pSortedOption = (CSortOptions*)pParam;
1046
1047 CStringNode* pNewRecord;
1048
1049 BJ_UINT64 SortKey =0;
1050 switch (pSortedOption->m_nSortCol) {
1051 case 0:
1052 SortKey = Hash2(pRecord->m_Value); // cheat the sort to the first 8 char
1053 break;
1054 case 1:
1055 SortKey = pRecord->m_nBytes;
1056 break;
1057 case 2:
1058 SortKey = pRecord->m_nFrames;
1059 break;
1060 case 3:
1061 SortKey = pRecord->m_nQuestionFrames;
1062 break;
1063 case 4:
1064 SortKey = pRecord->m_nAnswerFrames;
1065 break;
1066 default:
1067 break;
1068 }
1069
1070
1071 pNewRecord = pSortedOption->m_SortedCache.AddRecord(&SortKey);
1072
1073 if (pNewRecord)
1074 {
1075 pNewRecord->CopyNode(pRecord);
1076
1077 }
1078
1079 return 0;
1080 }
1081
1082 #if 0 // Not used
1083 static int CbPrintUnknownDevice(const void* pNode, const void*)
1084 {
1085 CDeviceNode* pDeviceRecord = (CDeviceNode*)pNode;
1086
1087 if (pDeviceRecord->GetDeviceOS() != '?')
1088 return 0;
1089
1090 // printf("%s %s\n",pDeviceRecord->m_Key.GetBuffer(), pDeviceRecord->macAddress.GetString());
1091 return 0;
1092
1093 }
1094 #endif
1095
1096 static int CbBuildMacMap(const void* pNode, const void* pParam)
1097 {
1098 CDeviceNode* pDeviceNode = (CDeviceNode*)pNode;
1099 CMACAddrTree* pMacMap = (CMACAddrTree*)pParam;
1100
1101
1102 BJMACAddr vendorMac;
1103 vendorMac.CopyVendor(pDeviceNode->macAddress);
1104 if (vendorMac.IsEmpty())
1105 return 0;
1106
1107
1108
1109 if (pDeviceNode->GetDeviceOS() == '?')
1110 {
1111 // try to set device type from MAC address
1112 CMACAddrNode* pMacRecord = pMacMap->Find(&vendorMac);
1113 if (pMacRecord != NULL && pDeviceNode->GetDeviceOS() == '?')
1114 {
1115 pDeviceNode->SetDeviceOS(pMacRecord->deviceOS, "MAC Mapping");
1116 // printf("update device %s %c\n",vendorMac.GetStringVendor(),pMacRecord->deviceOS);
1117 }
1118
1119 if (pDeviceNode->GetDeviceOS() == '?')
1120 return 0;
1121 }
1122
1123
1124 CMACAddrNode* pMacRecord = pMacMap->Find(&vendorMac);
1125 if (pMacRecord == NULL)
1126 {
1127 pMacRecord = pMacMap->FindwithAddRecord(&vendorMac);
1128 pMacRecord->deviceOS = pDeviceNode->GetDeviceOS();
1129 pMacRecord->model = pDeviceNode->model;
1130 pMacRecord->method = pDeviceNode->settingService;
1131 }
1132 else
1133 {
1134 // Check mapping
1135 /// if (pMacRecord && pMacRecord->deviceOS != pDeviceNode->GetDeviceOS())
1136 // printf("Mac Mapping Bad deviceOS %c != %c %s %s %s\n", pMacRecord->deviceOS, pDeviceNode->GetDeviceOS(),pMacRecord->method.GetBuffer(), pDeviceNode->settingService.GetBuffer(),vendorMac.GetStringVendor());
1137 // if (pMacRecord && !(pMacRecord->model == pDeviceNode->model) && pMacRecord->model.GetLength() > 0 && pDeviceNode->model.GetLength() > 0)
1138 // printf("Mac Mapping Bad model %s != %s\n", pMacRecord->model.GetBuffer(), pDeviceNode->model.GetBuffer());
1139
1140 }
1141 return 0;
1142
1143 }
1144
1145 CStringNode* CBonjourTop::GetCurrentDisplayRoot(BJString &sTitle)
1146 {
1147 CStringNode* pRecord = NULL;
1148
1149 switch(m_CurrentDisplay)
1150 {
1151 case BJ_DISPLAY_APP:
1152 pRecord = m_ApplPtrCache.GetRoot();
1153 sTitle = "Application (IPv4)";
1154 break;
1155 case BJ_DISPLAY_APPv6:
1156 pRecord = m_ApplPtrCacheIPv6.GetRoot();
1157 sTitle = "Application (IPv6)";
1158 break;
1159 case BJ_DISPLAY_SERVICE:
1160 pRecord = m_ServicePtrCache.GetRoot();
1161 sTitle = "Services (IPv4)";
1162 break;
1163 case BJ_DISPLAY_SERVICEv6:
1164 pRecord = m_ServicePtrCacheIPv6.GetRoot();
1165 sTitle = "Services (IPv6)";
1166 break;
1167 case BJ_DISPLAY_24_MIN:
1168 printf("Error");
1169 break;
1170 }
1171 return pRecord;
1172 }
1173 void CBonjourTop::UpdateOSCounts()
1174 {
1175
1176
1177 CDeviceNode* pDeviceNode = m_DeviceMap.GetRoot();
1178 if (pDeviceNode)
1179 {
1180 pDeviceNode->CallBack(&CbBuildMacMap,&m_MacMap);
1181 // pDeviceNode->CallBack(&CbPrintUnknownDevice,NULL);
1182 }
1183
1184
1185 // Update Application Caches
1186 CStringNode* pCacheRoot = m_ApplPtrCache.GetRoot();
1187
1188 if (pCacheRoot)
1189 {
1190 pCacheRoot->UpdateOSTypeCounts(&m_DeviceMap,&m_IPtoNameMap);
1191 }
1192 pCacheRoot = m_ApplPtrCacheIPv6.GetRoot();
1193
1194 if (pCacheRoot)
1195 {
1196 pCacheRoot->UpdateOSTypeCounts(&m_DeviceMap,&m_IPtoNameMap);
1197 }
1198
1199 // Update Service caches
1200 pCacheRoot = m_ServicePtrCache.GetRoot();
1201
1202 if (pCacheRoot)
1203 {
1204 pCacheRoot->UpdateOSTypeCounts(&m_DeviceMap,&m_IPtoNameMap);
1205 }
1206 pCacheRoot = m_ServicePtrCacheIPv6.GetRoot();
1207
1208 if (pCacheRoot)
1209 {
1210 pCacheRoot->UpdateOSTypeCounts(&m_DeviceMap,&m_IPtoNameMap);
1211 }
1212
1213
1214 }
1215 void CBonjourTop::PrintResults(int nSortCol, bool bSortAsc)
1216 {
1217
1218 BJString sTitle;
1219 GetCurrentDisplayRoot(sTitle);
1220 device_count devCount;
1221 BJString sTableTitle;
1222
1223 UpdateOSCounts();
1224
1225 /////
1226 BJ_UINT64 nRate = 0;
1227 BJ_UINT64 nElapsedTime = m_EndTime-m_StartTime;
1228 if (nElapsedTime > 0)
1229 {
1230 nRate = (m_nFrameCount *3600) /nElapsedTime;
1231 }
1232 if (m_bCursers)
1233 {
1234 resizeterm(0,0);
1235 clear();
1236
1237 printw("While running the follow keys may be used:\n");
1238 printw("[p = sort by Packets (default)], [b = sort by Bytes], [n = sort by Name]\n");
1239 printw("[a = Display Application Names (default)], [s = Display Services Names], [t = Display 24 hour packet per min]\n");
1240 printw("[o = flip sort order], [e = export to BonjourTop.csv], [q = quit]\n\n");
1241
1242 printw("Total Packets: %llu, Total Bytes: %llu, Elapse Time: %lld sec, Rate: %llu packet/hr\n",m_nFrameCount,m_nTotalBytes,nElapsedTime,nRate);
1243 printw("IPv4 multicast: %llu, IPv6 multicast: %llu, IPv4 Unicast: %lld, IPv6 Unicast: %llu\n",m_SocketStatus[0].m_nFrameCount,m_SocketStatus[1].m_nFrameCount,m_SocketStatus[2].m_nFrameCount,m_SocketStatus[3].m_nFrameCount);
1244 printw("IPv4 Wrong subnet: %llu, IPv6 Wrong subnet: %llu\n",m_SocketStatus[4].m_nFrameCount,m_SocketStatus[5].m_nFrameCount);
1245 printw("QuestionOnly Packets: %llu, AnswerOnly Packets: %llu, Q&A Packets %llu\n",m_SocketStatus[0].m_nQuestionOnlyFrames,m_SocketStatus[0].m_nAnswerOnlyFrames,m_SocketStatus[0].m_nQandAFrames);
1246 printw("AnswerCount for truncated frames(min,avg,max): %llu,%llu,%llu\n\n",m_MinAnswerCountForTruncatedFrames,m_AvgAnswerCountForTruncatedFrames,m_MaxAnswerCountForTruncatedFrames);
1247
1248 bzero(&devCount, sizeof(devCount));
1249 m_DeviceMap.GetDeviceOSTypes(m_DeviceMap.GetRoot(),NULL, devCount);
1250 printw("Total Devices: %llu, iOS Devices: %llu(>= iOS7: %llu), OSX Devices %llu(>= OSX 10.9: %llu)\n",devCount.iOS+devCount.OSX+devCount.unknownOS,devCount.iOS, devCount.iOSWithEDNSField, devCount.OSX,devCount.OSXWithEDNSField);
1251 }
1252 else
1253 {
1254 printf("\nTotal Packets: %llu, Total Bytes: %llu, Elapse Time: %lld sec, Rate: %llu packet/hr\n",m_nFrameCount,m_nTotalBytes,nElapsedTime,nRate);
1255 printf("IPv4 multicast: %llu, IPv6 multicast: %llu, IPv4 Unicast: %lld, IPv6 Unicast: %llu\n",m_SocketStatus[0].m_nFrameCount,m_SocketStatus[1].m_nFrameCount,m_SocketStatus[2].m_nFrameCount,m_SocketStatus[3].m_nFrameCount);
1256 printf("IPv4 Wrong subnet: %llu, IPv6 Wrong subnet: %llu\n",m_SocketStatus[4].m_nFrameCount,m_SocketStatus[5].m_nFrameCount);
1257 printf("QuestionOnly Packets: %llu, AnswerOnly Packets: %llu, Q&A Packets %llu\n",m_SocketStatus[0].m_nQuestionOnlyFrames,m_SocketStatus[0].m_nAnswerOnlyFrames,m_SocketStatus[0].m_nQandAFrames);
1258
1259 bzero(&devCount, sizeof(devCount));
1260 m_DeviceMap.GetDeviceOSTypes(m_DeviceMap.GetRoot(),NULL, devCount);
1261
1262 printf("Total Devices: %llu, iOS Devices: %llu(>= iOS7: %llu), OSX Devices %llu(>= OSX 10.9: %llu), unknown Devices %llu\n",devCount.iOS+devCount.OSX+devCount.unknownOS,devCount.iOS, devCount.iOSWithEDNSField,devCount.OSX,devCount.OSXWithEDNSField,devCount.unknownOS);
1263 printf("AnswerCount for truncated frames(min,avg,max): %llu,%llu,%llu\n\n",m_MinAnswerCountForTruncatedFrames,m_AvgAnswerCountForTruncatedFrames,m_MaxAnswerCountForTruncatedFrames);
1264 }
1265 PrintDetailResults(nSortCol, bSortAsc);
1266 if (m_bCursers)
1267 refresh();
1268 }
1269 void CBonjourTop::PrintDetailResults(int nSortCol, bool bSortAsc)
1270 {
1271 BJString sTitle;
1272 CStringNode* pCacheRoot = GetCurrentDisplayRoot(sTitle);
1273
1274 if (m_bCursers)
1275 {
1276 if(m_CurrentDisplay == CBonjourTop::BJ_DISPLAY_24_MIN)
1277 {
1278 printw(" ");
1279 for(int i=0;i<24;i++)
1280 printw(" %02d ",i);
1281 printw("\n");
1282 }
1283 else
1284 {
1285 printw("\n%s\n",sTitle.GetBuffer());
1286 printw(" %- 30s %10s %10s%24s%24s%24s%24s%24s\n","","","Total","Question","Answer","Asking","Answering", "Total");
1287 printw(" %- 30s %10s%24s%24s%24s %23s%24s%24s %11s %10s\n","Name","Bytes","Packets( iOS/ OSX)","Packets( iOS/ OSX)","Packets( iOS/ OSX)","Devices( iOS/ OSX)","Devices( iOS/ OSX)","Devices( iOS/ OSX)", "QU Bit","Goodbye");
1288 }
1289 }
1290 else
1291 {
1292 if(m_CurrentDisplay == CBonjourTop::BJ_DISPLAY_24_MIN)
1293 {
1294
1295 }
1296 else
1297 {
1298 printf("\n%s\n",sTitle.GetBuffer());
1299 printf(" %-30s %10s %10s%24s%24s%24s%24s%24s\n","","","Total","Question","Answer","Asking","Answering", "Total");
1300 printf(" %-30s %10s%24s%24s%24s %23s%24s%24s %11s %10s\n","Name","Bytes","Packets( iOS/ OSX)","Packets( iOS/ OSX)","Packets( iOS/ OSX)","Devices( iOS/ OSX)","Devices( iOS/ OSX)","Devices( iOS/ OSX)", "QU Bit","Goodbye");
1301 }
1302 }
1303 if (m_CurrentDisplay == CBonjourTop::BJ_DISPLAY_24_MIN)
1304 {
1305
1306 for(int m=0;m<60;m++)
1307 {
1308 printw(" %02d ",m);
1309 for (int h=0;h<24;h++)
1310 printw("%5d ",m_MinSnapshot[h][m].m_nFrameCount);
1311 printw("\n");
1312 }
1313 }
1314 else
1315 {
1316 // sort list
1317 CSortOptions SortOptions;
1318 SortOptions.m_nSortCol = nSortCol;
1319
1320 if (pCacheRoot)
1321 pCacheRoot->UpdateOSTypeCounts(&m_DeviceMap,&m_IPtoNameMap);
1322
1323 if (pCacheRoot)
1324 pCacheRoot->CallBack(&CbPrintResults,&SortOptions);
1325
1326 // print list
1327
1328 CStringNode* pRecord = SortOptions.m_SortedCache.GetRoot();
1329 BJ_UINT32 nIndex = 1;
1330
1331 if (pRecord)
1332 pRecord->Print(m_bCursers,bSortAsc, nIndex,0,40);
1333 }
1334
1335
1336 }
1337
1338 void CBonjourTop::LiveCapture()
1339 {
1340 /// Live Capture
1341 const BJ_UINT16 BonjourPort = 5353;
1342 BJSocket Sockv4;
1343 BJSocket Sockv6;
1344 BJSelect SockSelect;
1345
1346 Sockv4.CreateListenerIPv4(interfaceName);
1347 Sockv6.CreateListenerIPv6(interfaceName);
1348
1349 SockSelect.Add(Sockv4);
1350 SockSelect.Add(Sockv6);
1351
1352
1353 m_StartTime = time(NULL);
1354
1355 bool bSortAsc = false;
1356 int nSortCol = 1;
1357
1358 while (1)
1359 {
1360 SockSelect.Add(Sockv4);
1361 SockSelect.Add(Sockv6);
1362
1363 int result = SockSelect.Wait(1);
1364 if (result < 0)
1365 {
1366 // if SockSelect.Wait failed due to an interrupt, then we want to continue processing the packets
1367 if (errno == EINTR)
1368 {
1369 continue;
1370 }
1371 printf("Error in Select\n");
1372 break;
1373 }
1374
1375 if (SockSelect.IsReady(Sockv4))
1376 {
1377
1378 int recvsize = Sockv4.Read();
1379
1380 if ((recvsize != 0) &&
1381 (Sockv4.GetSrcAddr()->GetPortNumber() == BonjourPort))
1382 {
1383 m_nFrameCount++;
1384 m_SocketStatus[Sockv4.IsMulticastPacket()? 0:2].m_nFrameCount++;
1385
1386 if (!m_IPv4Addr.IsSameSubNet(Sockv4.GetSrcAddr()))
1387 {
1388 m_SocketStatus[4].m_nFrameCount++;
1389 }
1390 m_Frame.m_SourceIPAddress = *Sockv4.GetSrcAddr();
1391 ProcessFrame(Sockv4.GetBuffer(),recvsize,Sockv4.m_CurrentFrame.GetTime());
1392 }
1393 }
1394
1395 if (SockSelect.IsReady(Sockv6))
1396 {
1397 int recvsize = Sockv6.Read();
1398 if ((recvsize != 0) &&
1399 (Sockv6.GetSrcAddr()->GetPortNumber() == BonjourPort))
1400 {
1401 m_nFrameCount++;
1402 m_SocketStatus[Sockv6.IsMulticastPacket()? 1:3].m_nFrameCount++;
1403 m_Frame.m_SourceIPAddress = *Sockv6.GetSrcAddr();
1404
1405 ProcessFrame(Sockv6.GetBuffer(),recvsize,Sockv6.m_CurrentFrame.GetTime());
1406 }
1407 }
1408
1409 if (m_bCursers)
1410 {
1411 int ch = getch();
1412 switch (ch)
1413 {
1414 case 'o':
1415 bSortAsc = !bSortAsc;
1416 result = 0; // force an update
1417 break;
1418 case 'n':
1419 nSortCol = 0;
1420 result = 0; // force an update
1421 break;
1422 case 'b':
1423 nSortCol = 1;
1424 result = 0; // force an update
1425 break;
1426 case 'p':
1427 if (nSortCol == 2)
1428 nSortCol = 3;
1429 else if (nSortCol == 3)
1430 nSortCol = 4;
1431 else
1432 nSortCol = 2;
1433 result = 0; // force an update
1434 break;
1435 case 'a':
1436 case 'A':
1437 if (m_CurrentDisplay == CBonjourTop::BJ_DISPLAY_APP)
1438 m_CurrentDisplay = CBonjourTop::BJ_DISPLAY_APPv6;
1439 else
1440 m_CurrentDisplay = CBonjourTop::BJ_DISPLAY_APP;
1441
1442 result = 0;
1443 break;
1444 case 's':
1445 case 'S':
1446 if (m_CurrentDisplay == CBonjourTop::BJ_DISPLAY_SERVICE)
1447 m_CurrentDisplay = CBonjourTop::BJ_DISPLAY_SERVICEv6;
1448 else
1449 m_CurrentDisplay = CBonjourTop::BJ_DISPLAY_SERVICE;
1450 result = 0;
1451 break;
1452 case 't':
1453 case 'T':
1454 m_CurrentDisplay = CBonjourTop::BJ_DISPLAY_24_MIN;
1455 result = 0;
1456 break;
1457 case 'q':
1458 return;
1459 case 'e':
1460 ExportResults();
1461 printf("\a");
1462 break;
1463 case KEY_RESIZE:
1464 endwin();
1465 initscr();
1466 result = 0; // force an update
1467 break;
1468 case KEY_DOWN:
1469 result = 0; // force an update
1470 break;
1471 }
1472 if (window_size_changed)
1473 {
1474 endwin();
1475 initscr();
1476 window_size_changed = false;
1477 }
1478 }
1479 if (m_EndTime != time(NULL) || result == 0)
1480 {
1481 m_EndTime = time(NULL);
1482 PrintResults(nSortCol,bSortAsc);
1483 if (m_SnapshotSeconds && (time(NULL) - m_StartTime) > m_SnapshotSeconds)
1484 {
1485 ExportResults();
1486 if (m_bImportExportDeviceMap)
1487 {
1488 WriteDeviceFile();
1489 WriteVendorFile();
1490 }
1491 Reset();
1492 }
1493 }
1494 }
1495 }
1496
1497
1498
1499 void CBonjourTop::CaptureFile()
1500 {
1501 CCaptureFile CaptureFile;
1502 BJIPAddr* pIPSrcAddr;
1503 BJIPAddr* pIPDestAddr;
1504
1505 CIPAddrMap LocalSubnetIPv6;
1506
1507
1508 CaptureFile.Open(m_pTcpDumpFileName);
1509
1510 m_StartTime = 0;
1511 int nFrameIndex = 0;
1512
1513 while (CaptureFile.NextFrame())
1514 {
1515 nFrameIndex++;
1516
1517 BJ_UINT8* pBonjourBuffer = (BJ_UINT8*)CaptureFile.m_CurrentFrame.GetBonjourStart();
1518 if (!pBonjourBuffer)
1519 continue;
1520
1521 m_nFrameCount++;
1522 m_nTotalBytes += CaptureFile.GetWiredLength();
1523
1524 pIPSrcAddr = CaptureFile.m_CurrentFrame.GetSrcIPAddr();
1525 pIPDestAddr = CaptureFile.m_CurrentFrame.GetDestIPAddr();
1526 m_Frame.m_SourceIPAddress = *CaptureFile.m_CurrentFrame.GetSrcIPAddr();;
1527 m_Frame.m_SourceMACAddress = *CaptureFile.m_CurrentFrame.GetSrcMACAddr();
1528
1529 if (pIPSrcAddr->IsIPv4())
1530 {
1531 // check fragment flag
1532 BJ_UINT8* pIP = CaptureFile.m_CurrentFrame.GetIPStart();
1533 BJ_UINT16 flags = * ((BJ_UINT16*)(pIP+6));
1534 if (flags)
1535 continue;
1536
1537 if (!m_IPv4Addr.IsEmptySubnet())
1538 {
1539 if (m_IPv4Addr.IsSameSubNet(pIPSrcAddr))
1540 {
1541 BJ_UINT8* pSourceMac = CaptureFile.m_CurrentFrame.GetEthernetStart()+6;
1542 BJIPAddr IPv6Addr;
1543 IPv6Addr.CreateLinkLocalIPv6(pSourceMac);
1544 LocalSubnetIPv6.FindwithAddRecord(&IPv6Addr);
1545
1546 }
1547 else
1548 {
1549 m_SocketStatus[4].m_nFrameCount++;
1550
1551 if (!m_Collection.IsValid())
1552 continue;
1553 }
1554 }
1555 m_SocketStatus[(pIPDestAddr->IsBonjourMulticast())?0:2].m_nFrameCount++;
1556 }
1557 if (pIPSrcAddr->IsIPv6())
1558 {
1559 if (!LocalSubnetIPv6.Find(pIPSrcAddr) && !m_IPv4Addr.IsEmptySubnet())
1560 {
1561 m_SocketStatus[5].m_nFrameCount++;
1562 if (!m_Collection.IsValid())
1563 continue;
1564 }
1565 m_SocketStatus[(pIPDestAddr->IsBonjourMulticast())?1:3].m_nFrameCount++;
1566 }
1567
1568 ProcessFrame(pBonjourBuffer,CaptureFile.GetBufferLen((pBonjourBuffer)),CaptureFile.m_CurrentFrame.GetTime());
1569
1570 }
1571 m_EndTime = CaptureFile.GetDeltaTime();
1572
1573 PrintResults(2,false);
1574 if ( m_CurrentDisplay == BJ_DISPLAY_APP)
1575 m_CurrentDisplay = BJ_DISPLAY_APPv6;
1576 else
1577 m_CurrentDisplay = BJ_DISPLAY_SERVICEv6;
1578
1579 PrintDetailResults(2,false);
1580
1581 }
1582
1583 void CBonjourTop::ExportPtrCache(FILE* hFile, BJString sTitle,CStringNode* pRoot)
1584 {
1585 fprintf(hFile,"%s\n",sTitle.GetBuffer());
1586 fprintf(hFile,"Name,Bytes,Total Packets,Total Packets iOS,Total Packets OSX,Question Packets,Question Packets iOS,Question Packets OSX,Answer Packets,Answer Packets iOS,Answer Packets OSX,Asking Devices, Asking Devices iOS,Asking Devices OSX,Answering Devices,Answering Devices iOS,Answering Devices OSX,Total Devices,Total Devices iOS, Total Devices OSX,QU Bit,Goodbye\n");
1587
1588 if (pRoot)
1589 pRoot->Export(hFile);
1590 }
1591
1592 void CBonjourTop::ExportShortCacheHelper(FILE* hFile, BJString sTitle, CStringShortNode* pRoot)
1593 {
1594 fprintf(hFile,"%s\n",sTitle.GetBuffer());
1595 fprintf(hFile,"Name,Bytes,Total Packets,Question Packets,Answer Packets,Asking Devices,Answering Devices,Total Devices,QU Bit,Goodbye\n");
1596
1597 if (pRoot)
1598 {
1599 pRoot->Export(hFile);
1600 }
1601
1602 }
1603
1604 void CBonjourTop::ExportShortCache(FILE* hFile, BJString sTitle, map<BJString, CStringShortTree*>* myMap)
1605 {
1606 CStringShortTree* cache;
1607 BJString versionNumber;
1608
1609 fprintf(hFile,"%s\n",sTitle.GetBuffer());
1610
1611 for (map<BJString, CStringShortTree*>::iterator it = myMap->begin(); it != myMap->end(); ++it)
1612 {
1613 versionNumber = (*it).first;
1614 cache = (*it).second;
1615
1616 ExportShortCacheHelper(hFile, versionNumber, cache->GetRoot());
1617 }
1618 }
1619
1620 void CBonjourTop::ExportResults()
1621 {
1622
1623 BJString sTempFileName;
1624 device_count devCount;
1625 sTempFileName = m_pExportFileName;
1626
1627 if (m_SnapshotSeconds)
1628 {
1629 BJString sTimeStamp;
1630 sTimeStamp.Format(time(NULL), BJString::BJSS_TIME);
1631 sTempFileName += "_";
1632 sTempFileName += sTimeStamp;
1633 }
1634 sTempFileName += ".csv";
1635
1636 if (m_Collection.IsValid())
1637 {
1638 m_Collection.ExportCollection(sTempFileName);
1639 return;
1640 }
1641
1642 FILE* hFile = fopen(sTempFileName.GetBuffer(),"w");
1643
1644 if (hFile == NULL)
1645 {
1646 printf("file open failed %s\n",m_pExportFileName);
1647 return;
1648 }
1649
1650 fprintf(hFile,"Total Number of Frames, %llu\n",m_nFrameCount);
1651 fprintf(hFile,"Total Number of Bytes, %llu\n",m_nTotalBytes);
1652 fprintf(hFile,"Total Number of Sec, %llu\n",m_EndTime-m_StartTime);
1653
1654 bzero(&devCount, sizeof(devCount));
1655 m_DeviceMap.GetDeviceOSTypes(m_DeviceMap.GetRoot(),NULL, devCount);
1656 fprintf(hFile,"Total Number of Devices, %llu\n\n",devCount.iOS+devCount.OSX+devCount.unknownOS);
1657 fprintf(hFile,"Total Number of iOS Devices, %llu\n",devCount.iOS);
1658 fprintf(hFile,"Total Number of iOS Devices (>= iOS7), %llu\n", devCount.iOSWithEDNSField);
1659 fprintf(hFile,"Total Number of OSX Devices, %llu\n",devCount.OSX);
1660 fprintf(hFile,"Total Number of OSX Devices (>= OSX 10.9), %llu\n",devCount.OSXWithEDNSField);
1661
1662 fprintf(hFile,"IPv4 multicast, %llu\n",m_SocketStatus[0].m_nFrameCount);
1663 fprintf(hFile,"IPv6 multicast, %llu\n",m_SocketStatus[1].m_nFrameCount);
1664 fprintf(hFile,"IPv4 Unicast, %llu\n",m_SocketStatus[2].m_nFrameCount);
1665 fprintf(hFile,"IPv6 Unicast, %llu\n",m_SocketStatus[3].m_nFrameCount);
1666 fprintf(hFile,"IPv4 Wrong subnet, %llu\n",m_SocketStatus[4].m_nFrameCount);
1667 fprintf(hFile,"IPv6 Wrong subnet, %llu\n\n",m_SocketStatus[5].m_nFrameCount);
1668
1669 fprintf(hFile,"QuestionOnly Packets, %llu\n", m_SocketStatus[0].m_nQuestionOnlyFrames);
1670 fprintf(hFile,"AnswerOnly Packets, %llu\n", m_SocketStatus[0].m_nAnswerOnlyFrames);
1671 fprintf(hFile,"Q&A Packets, %llu\n\n", m_SocketStatus[0].m_nQandAFrames);
1672
1673 fprintf(hFile,"AnswerCount for truncated frames min, %llu\n", m_MinAnswerCountForTruncatedFrames);
1674 fprintf(hFile,"AnswerCount for truncated frames avg, %llu\n", m_AvgAnswerCountForTruncatedFrames);
1675 fprintf(hFile,"AnswerCount for truncated frames max, %llu\n\n", m_MaxAnswerCountForTruncatedFrames);
1676
1677 // Export Cache
1678 UpdateOSCounts();
1679 ExportPtrCache(hFile,"Application IPv4 Cache",m_ApplPtrCache.GetRoot());
1680 ExportShortCache(hFile, "OSX", &m_AppBreakdownIPv4OSX);
1681 ExportShortCache(hFile, "iOS", &m_AppBreakdownIPv4iOS);
1682
1683 ExportPtrCache(hFile,"Application IPv6 Cache",m_ApplPtrCacheIPv6.GetRoot());
1684 ExportShortCache(hFile, "OSX", &m_AppBreakdownIPv6OSX);
1685 ExportShortCache(hFile, "iOS", &m_AppBreakdownIPv6iOS);
1686
1687 ExportPtrCache(hFile,"Service IPv4 Cache",m_ServicePtrCache.GetRoot());
1688 ExportShortCache(hFile, "OSX", &m_ServiceBreakdownIPv4OSX);
1689 ExportShortCache(hFile, "iOS", &m_ServiceBreakdownIPv4iOS);
1690
1691 ExportPtrCache(hFile,"Service IPv6 Cache",m_ServicePtrCacheIPv6.GetRoot());
1692 ExportShortCache(hFile, "OSX", &m_ServiceBreakdownIPv6OSX);
1693 ExportShortCache(hFile, "iOS", &m_ServiceBreakdownIPv6iOS);
1694
1695 /// min snapshot table
1696
1697 fprintf(hFile,"Min Snapshot table\n");
1698
1699 for (int h=0;h<24;h++)
1700 {
1701 for(int m=0;m<60;m++)
1702 {
1703 if (m_MinSnapshot[h][m].m_nFrameCount)
1704 {
1705 fprintf(hFile,"%02d:%02d,%llu\n",h,m,m_MinSnapshot[h][m].m_nFrameCount);
1706 }
1707 }
1708
1709 }
1710
1711 fclose(hFile);
1712
1713 }
1714
1715 void CBonjourTop::WriteDeviceFile()
1716 {
1717 BJString sTempFileName;
1718 BJString sTimeStamp;
1719
1720 sTempFileName = m_DeviceFileName;
1721 sTimeStamp.Format(time(NULL), BJString::BJSS_TIME);
1722 sTempFileName += "_";
1723 sTempFileName += sTimeStamp;
1724 sTempFileName += ".csv";
1725
1726 FILE* hFile = fopen(sTempFileName.GetBuffer(),"w");
1727
1728 if (hFile == NULL)
1729 {
1730 printf("file open failed %s\n",sTempFileName.GetBuffer());
1731 return;
1732 }
1733
1734 fprintf(hFile,"\"Name\",\"IPv4Address\",\"IPv6Address\",\"MACAddress\",O,\"Model\",\"Method\",\"total frames\",\"question frames\",\"QU frames\",\"answer frames\"\n");
1735
1736 CDeviceNode *pDeviceNode = m_DeviceMap.GetRoot();
1737
1738 if (pDeviceNode)
1739 pDeviceNode->Export(hFile);
1740
1741 fclose(hFile);
1742
1743 printf("devicemap count %llu %d\n",m_DeviceMap.GetCount(),CDeviceNode::nCreateCount);
1744
1745 }
1746
1747 void CBonjourTop::WriteVendorFile()
1748 {
1749 BJString sTempFileName = "BonjourTopVendor";
1750 BJString sTimeStamp;
1751
1752 sTimeStamp.Format(time(NULL), BJString::BJSS_TIME);
1753 sTempFileName += "_";
1754 sTempFileName += sTimeStamp;
1755 sTempFileName += ".csv";
1756
1757 FILE* hFile = fopen(sTempFileName.GetBuffer(),"w");
1758
1759 if (hFile == NULL)
1760 {
1761 printf("file open failed %s\n",sTempFileName.GetBuffer());
1762 return;
1763 }
1764 fprintf(hFile,"\"MACAddress\",O,\"Model\",\"Method\"\n");
1765
1766 CMACAddrNode *node = m_MacMap.GetRoot();
1767
1768 if (node)
1769 node->Export(hFile);
1770
1771 fclose(hFile);
1772 }
1773
1774 void CBonjourTop::WindowSizeChanged()
1775 {
1776 window_size_changed = true;
1777 }
1778
1779 BJ_UINT64 Hash(const char* pStr)
1780 {
1781 // to fix
1782 BJ_UINT64 hash = 0;
1783 int c;
1784
1785 while ((c = *pStr++))
1786 hash += c;
1787
1788 return hash;
1789
1790
1791 }
1792
1793 BJ_UINT64 Hash2(char* pStr)
1794 {
1795 // to fix
1796 BJ_UINT64 hash = 0;
1797 int c;
1798 int i = 0;
1799
1800 while ((c = *pStr++) && i++ < 8)
1801 {
1802 hash = hash << 8;
1803 hash |= c;
1804 }
1805
1806 return hash;
1807
1808
1809 }
1810
1811 static integer_t Usage(void)
1812 {
1813 task_t targetTask = mach_task_self();
1814 struct task_basic_info ti;
1815 mach_msg_type_number_t count = TASK_BASIC_INFO_64_COUNT;
1816
1817 kern_return_t kr = task_info(targetTask, TASK_BASIC_INFO_64,
1818 (task_info_t) &ti, &count);
1819 if (kr != KERN_SUCCESS)
1820 {
1821 printf("Kernel returned error during memory usage query");
1822 return 0;
1823 }
1824
1825 // On Mac OS X, the resident_size is in bytes, not pages!
1826 // (This differs from the GNU Mach kernel)
1827 // return ti.resident_size;
1828 return ti.user_time.seconds;
1829 }
1830
1831 ///////////////
1832
1833
1834 /* CStringNode */
1835
1836 void CStringNode::UpdateOSTypeCounts(CDeviceMap* pGlobalDeviceMap,CIPAddrMap *pIp2NameMap)
1837 {
1838 if (m_rbLeft)
1839 ((CStringNode*)m_rbLeft)->UpdateOSTypeCounts(pGlobalDeviceMap,pIp2NameMap);
1840 if (m_rbRight)
1841 ((CStringNode*)m_rbRight)->UpdateOSTypeCounts(pGlobalDeviceMap,pIp2NameMap);
1842
1843 BJ_UINT64 nDeviceUnknown = 0;
1844 m_nDeviceAskingiOSCount = 0;
1845 m_nDeviceAskingOSXCount = 0;
1846 m_nDeviceAnsweringiOSCount = 0;
1847 m_nDeviceAnsweringOSXCount = 0;
1848 m_nDeviceTotaliOSCount = 0;
1849 m_nDeviceTotalOSXCount = 0;
1850 m_DeviceAskingTree.GetDeviceOSTypes(m_DeviceAskingTree.GetRoot(),pIp2NameMap,m_nDeviceAskingiOSCount,m_nDeviceAskingOSXCount,nDeviceUnknown);
1851 nDeviceUnknown = 0;
1852 m_DeviceAnsweringTree.GetDeviceOSTypes(m_DeviceAnsweringTree.GetRoot(),pIp2NameMap,m_nDeviceAnsweringiOSCount,m_nDeviceAnsweringOSXCount,nDeviceUnknown);
1853 nDeviceUnknown = 0;
1854 m_DeviceTotalTree.GetDeviceOSTypes(m_DeviceTotalTree.GetRoot(), pIp2NameMap, m_nDeviceTotaliOSCount, m_nDeviceTotalOSXCount, nDeviceUnknown);
1855 }
1856
1857 void CStringNode::Print(bool bCursers,bool bDescendingSort,BJ_UINT32 &nIndex, BJ_UINT32 nStartIndex,BJ_UINT32 nEndIndex)
1858 {
1859 if (bDescendingSort)
1860 {
1861 if (m_rbLeft)
1862 ((CStringNode*)m_rbLeft)->Print(bCursers,bDescendingSort,nIndex,nStartIndex,nEndIndex);
1863
1864 if (nIndex >= nStartIndex && nIndex <= nEndIndex)
1865 {
1866 if (bCursers)
1867 {
1868 printw("%3d. %-30s %10llu %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu %10llu\n",nIndex,(char*)&(m_Value),m_nBytes,m_nFrames, m_nFramesiOS, m_nFramesOSX, m_nQuestionFrames, m_nQuestionFramesiOS, m_nQuestionFramesOSX, m_nAnswerFrames,m_nAnswerFramesiOS, m_nAnswerFramesOSX, m_nDeviceAskingCount,m_nDeviceAskingiOSCount,m_nDeviceAskingOSXCount, m_nDeviceAnsweringCount,m_nDeviceAnsweringiOSCount,m_nDeviceAnsweringOSXCount, m_nDeviceTotalCount, m_nDeviceTotaliOSCount, m_nDeviceTotalOSXCount, m_nWakeFrames,m_nGoodbyeFrames);
1869
1870 }
1871 else
1872 {
1873 printf("%3d. %-30s %10llu %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu %10llu\n",nIndex,(char*)&(m_Value),m_nBytes,m_nFrames, m_nFramesiOS, m_nFramesOSX, m_nQuestionFrames, m_nQuestionFramesiOS, m_nQuestionFramesOSX, m_nAnswerFrames,m_nAnswerFramesiOS, m_nAnswerFramesOSX, m_nDeviceAskingCount,m_nDeviceAskingiOSCount,m_nDeviceAskingOSXCount, m_nDeviceAnsweringCount,m_nDeviceAnsweringiOSCount,m_nDeviceAnsweringOSXCount, m_nDeviceTotalCount, m_nDeviceTotaliOSCount, m_nDeviceTotalOSXCount, m_nWakeFrames,m_nGoodbyeFrames);
1874
1875 }
1876 }
1877 nIndex++;
1878 if (m_rbRight)
1879 ((CStringNode*)m_rbRight)->Print(bCursers,bDescendingSort,nIndex,nStartIndex,nEndIndex);
1880 }
1881 else
1882 {
1883 if (m_rbRight)
1884 ((CStringNode*)m_rbRight)->Print(bCursers,bDescendingSort,nIndex,nStartIndex,nEndIndex);
1885
1886 if (nIndex >= nStartIndex && nIndex <= nEndIndex)
1887 {
1888 if (bCursers)
1889 {
1890 printw("%3d. %-30s %10llu %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu %10llu\n",nIndex,(char*)&(m_Value),m_nBytes,m_nFrames, m_nFramesiOS, m_nFramesOSX, m_nQuestionFrames, m_nQuestionFramesiOS, m_nQuestionFramesOSX, m_nAnswerFrames,m_nAnswerFramesiOS, m_nAnswerFramesOSX, m_nDeviceAskingCount,m_nDeviceAskingiOSCount,m_nDeviceAskingOSXCount, m_nDeviceAnsweringCount,m_nDeviceAnsweringiOSCount,m_nDeviceAnsweringOSXCount, m_nDeviceTotalCount, m_nDeviceTotaliOSCount, m_nDeviceTotalOSXCount, m_nWakeFrames,m_nGoodbyeFrames);
1891 }
1892 else
1893 {
1894 printf("%3d. %-30s %10llu %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu %10llu\n",nIndex,(char*)&(m_Value),m_nBytes,m_nFrames, m_nFramesiOS, m_nFramesOSX, m_nQuestionFrames, m_nQuestionFramesiOS, m_nQuestionFramesOSX, m_nAnswerFrames,m_nAnswerFramesiOS, m_nAnswerFramesOSX, m_nDeviceAskingCount,m_nDeviceAskingiOSCount,m_nDeviceAskingOSXCount, m_nDeviceAnsweringCount,m_nDeviceAnsweringiOSCount,m_nDeviceAnsweringOSXCount, m_nDeviceTotalCount, m_nDeviceTotaliOSCount, m_nDeviceTotalOSXCount, m_nWakeFrames,m_nGoodbyeFrames);
1895 }
1896 }
1897 nIndex++;
1898 if (m_rbLeft)
1899 ((CStringNode*)m_rbLeft)->Print(bCursers,bDescendingSort,nIndex,nStartIndex,nEndIndex);
1900 }
1901
1902 }
1903 void CStringNode::Export(FILE* hFile)
1904 {
1905 fprintf(hFile, "%s,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu\n",
1906 (char*)&(m_Value),m_nBytes,
1907 m_nFrames, m_nFramesiOS, m_nFramesOSX,
1908 m_nQuestionFrames, m_nQuestionFramesiOS, m_nQuestionFramesOSX,
1909 m_nAnswerFrames, m_nAnswerFramesiOS, m_nAnswerFramesOSX,
1910 m_nDeviceAskingCount, m_nDeviceAskingiOSCount,m_nDeviceAskingOSXCount,
1911 m_nDeviceAnsweringCount,m_nDeviceAnsweringiOSCount,m_nDeviceAnsweringOSXCount,
1912 m_nDeviceTotalCount, m_nDeviceTotaliOSCount, m_nDeviceTotalOSXCount,
1913 m_nWakeFrames,m_nGoodbyeFrames);
1914
1915 if (m_rbLeft)
1916 ((CStringNode*)m_rbLeft)->Export(hFile);
1917 if (m_rbRight)
1918 ((CStringNode*)m_rbRight)->Export(hFile);
1919
1920 }
1921
1922 /* CStringShortNode */
1923
1924 void CStringShortNode::Export(FILE *hFile)
1925 {
1926 fprintf(hFile, "%s,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu\n",
1927 (char*)&(m_Value),m_nBytes,
1928 m_nFrames, m_nQuestionFrames, m_nAnswerFrames,
1929 m_nDeviceAskingCount, m_nDeviceAnsweringCount, m_nDeviceTotalCount,
1930 m_nWakeFrames,m_nGoodbyeFrames);
1931
1932
1933 if (m_rbLeft)
1934 {
1935 ((CStringShortNode*)m_rbLeft)->Export(hFile);
1936 }
1937 if (m_rbRight)
1938 {
1939 ((CStringShortNode*)m_rbRight)->Export(hFile);
1940 }
1941 }
1942
1943 /* CDeviceMap */
1944
1945 void CDeviceMap::GetDeviceOSTypes(CDeviceNode *node, CDeviceMap *pGlobalDeviceMap, device_count& dev_cnt)
1946 {
1947 if (node == NULL)
1948 return;
1949
1950 GetDeviceOSTypes(dynamic_cast<CDeviceNode*>(node->m_rbLeft),pGlobalDeviceMap, dev_cnt);
1951 GetDeviceOSTypes(dynamic_cast<CDeviceNode*>(node->m_rbRight),pGlobalDeviceMap, dev_cnt);
1952
1953 if (node->bDuplicate || !node->bHasFrames)
1954 return;
1955
1956 char deviceType = '?';
1957 if (pGlobalDeviceMap)
1958 {
1959 CDeviceNode* globalDevice = pGlobalDeviceMap->Find(&node->m_Key);
1960 if (globalDevice)
1961 {
1962 deviceType = globalDevice->GetDeviceOS();
1963
1964 if (globalDevice->bOSXWithEDNSField && deviceType == 'X')
1965 {
1966 dev_cnt.OSXWithEDNSField++;
1967 }
1968 else if (globalDevice->biOSWithEDNSField && (deviceType == 't' || deviceType == 'i'))
1969 {
1970 dev_cnt.iOSWithEDNSField++;
1971 }
1972 }
1973 }
1974 else
1975 {
1976 deviceType = node->GetDeviceOS();
1977 if (node->bOSXWithEDNSField && deviceType == 'X')
1978 {
1979 dev_cnt.OSXWithEDNSField++;
1980 }
1981 else if (node->biOSWithEDNSField && (deviceType == 't' || deviceType == 'i'))
1982 {
1983 dev_cnt.iOSWithEDNSField++;
1984 }
1985 }
1986 switch (deviceType)
1987 {
1988 case 'i':
1989 case 't':
1990 dev_cnt.iOS++;
1991 break;
1992 case 'X':
1993 dev_cnt.OSX++;
1994 break;
1995 default:
1996 dev_cnt.unknownOS++;
1997 break;
1998 }
1999 }
2000
2001 void CIPAddrMap::GetDeviceOSTypes(CIPDeviceNode* node, CIPAddrMap* pGobalMap, BJ_UINT64& iOS,BJ_UINT64& OSX,BJ_UINT64& unknowOS)
2002 {
2003 if (node == NULL)
2004 return;
2005
2006 GetDeviceOSTypes(dynamic_cast<CIPDeviceNode*>(node->m_rbLeft),pGobalMap, iOS, OSX, unknowOS);
2007 GetDeviceOSTypes(dynamic_cast<CIPDeviceNode*>(node->m_rbRight),pGobalMap,iOS, OSX, unknowOS);
2008
2009 char deviceType = '?';
2010 if (pGobalMap)
2011 {
2012 CIPDeviceNode *ipDevice = pGobalMap->Find(&node->m_Key);
2013
2014 if (ipDevice && ipDevice->pDeviceNode )
2015 deviceType = ipDevice->pDeviceNode->GetDeviceOS();
2016
2017 }
2018
2019 switch (deviceType)
2020 {
2021 case 'i':
2022 case 't':
2023 iOS++;
2024 break;
2025 case 'X':
2026 OSX++;
2027 break;
2028 default:
2029 unknowOS++;
2030 }
2031
2032 }
2033
2034
2035 ///////////
2036