#include #include "C_Sniffer.h" std::queue C_Sniffer::m_Packets; CRITICAL_SECTION C_Sniffer::m_PacketsSection; C_Sniffer::C_Sniffer(void) : m_ThreadCapturingRunning(false), m_ThreadProcessingRunning(false) { InitializeCriticalSection(&m_PacketsSection); } C_Sniffer::~C_Sniffer(void) { DeleteCriticalSection(&m_PacketsSection); } bool C_Sniffer::IsRunning() { return m_ThreadCapturingRunning; } bool C_Sniffer::Start() { pcap_if_t *alldevs; pcap_if_t *d; int inum; int i=0; char errbuf[PCAP_ERRBUF_SIZE]; if(m_ThreadCapturingRunning == true) { return false; } // Retrieve the device list if(pcap_findalldevs(&alldevs, errbuf) == -1) { fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf); exit(1); } // Print the list for(d=alldevs; d; d=d->next) { printf("%d. %s", ++i, d->name); if (d->description) printf(" (%s)\n", d->description); else printf(" (No description available)\n"); } if(i==0) { printf("\nNo interfaces found! Make sure WinPcap is installed.\n"); return false; } printf("Enter the interface number (1-%d):",i); scanf("%d", &inum); if(inum < 1 || inum > i) { printf("\nInterface number out of range.\n"); // Free the device list pcap_freealldevs(alldevs); return false; } // Jump to the selected adapter for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++); // Open the device // Open the adapter if ((m_CapturingArgs.m_Handle = pcap_open_live(d->name, // name of the device 65536, // portion of the packet to capture. // 65536 grants that the whole packet will be captured on all the MACs. 1, // promiscuous mode (nonzero means promiscuous) 1000, // read timeout errbuf // error buffer )) == NULL) { fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", d->name); // Free the device list pcap_freealldevs(alldevs); return false; } printf("\nlistening on %s...\n", d->description); // At this point, we don't need any more the device list. Free it pcap_freealldevs(alldevs); m_ThreadProcessingId = 0; m_ProcessingArgs.m_Instance = this; m_ProcessingArgs.m_Running = true; m_ThreadProcessingRunning = true; m_ThreadProcessing = CreateThread( NULL, // default security attributes 0, // use default stack size ThreadProcessingProc, // thread function &m_ProcessingArgs, // argument to thread function 0, // use default creation flags &m_ThreadProcessingId); // returns the thread identi // start the capture if(m_ThreadProcessing == NULL) { m_ThreadProcessingRunning = false; return false; } m_ThreadCapturingId = 0; m_CapturingArgs.m_Instance = this; m_CapturingArgs.m_Running = true; m_ThreadCapturingRunning = true; m_ThreadCapturing = CreateThread( NULL, // default security attributes 0, // use default stack size ThreadCapturingProc, // thread function &m_CapturingArgs, // argument to thread function 0, // use default creation flags &m_ThreadCapturingId); // returns the thread identi // start the capture if(m_ThreadCapturing == NULL) { m_ThreadCapturingRunning = false; return false; } return true; } bool C_Sniffer::Stop() { if(m_ThreadCapturingRunning == false) { return false; } m_CapturingArgs.m_Running = false; // Ukoncime vlakno Sleep(250); SuspendThread(m_ThreadCapturing); CloseHandle(m_ThreadCapturing); pcap_close(m_CapturingArgs.m_Handle); m_ProcessingArgs.m_Running = false; // Ukoncime vlakno Sleep(250); SuspendThread(m_ThreadProcessing); CloseHandle(m_ThreadProcessing); return true; } DWORD WINAPI C_Sniffer::ThreadCapturingProc( LPVOID lpParam ) { S_ThreadArgs* args = (S_ThreadArgs*)lpParam; pcap_loop(args->m_Handle, 0, Callback, NULL); return EXIT_SUCCESS; } DWORD WINAPI C_Sniffer::ThreadProcessingProc( LPVOID lpParam ) { S_ThreadArgs* args = (S_ThreadArgs*)lpParam; static bool inside = false; struct tm *ltime; char timestr[16]; ip_header *ih; udp_header *uh; u_int ip_len; u_short sport,dport; time_t local_tv_sec; while(args->m_Running) { if(m_Packets.size() <= 0) { continue; } EnterCriticalSection(&m_PacketsSection); S_WinPcapPacket packet = m_Packets.front(); m_Packets.pop(); LeaveCriticalSection(&m_PacketsSection); /* convert the timestamp to readable format */ local_tv_sec = packet.header.ts.tv_sec; ltime=localtime(&local_tv_sec); /* retireve the position of the ip header */ ih = (ip_header *) (packet.data +14); //length of ethernet headers /* retireve the position of the udp header */ ip_len = (ih->ver_ihl & 0xf) * 4; uh = (udp_header *) ((u_char*)ih + ip_len); /* convert from network byte order to host byte order */ sport = ntohs( uh->sport ); dport = ntohs( uh->dport ); char hostname_source[255]; char hostname_destination[255]; struct hostent* host; T_ResolveMap::iterator it; it = args->m_Instance->m_IpResolver.find(*(long*)&ih->saddr); if(it != args->m_Instance->m_IpResolver.end()) { strncpy(hostname_source,it->second.c_str(), sizeof(hostname_source)/sizeof(hostname_source[0])); } else { host = gethostbyaddr((char *) &ih->saddr, 4, AF_INET); hostname_source[0] = '\0'; if(host) { strncpy(hostname_source, host->h_name, sizeof(hostname_source)/sizeof(hostname_source[0])); args->m_Instance->m_IpResolver.insert(T_ResolvePair(*(long*)&ih->saddr, host->h_name)); } else { strcpy(hostname_source,"N/A"); args->m_Instance->m_IpResolver.insert(T_ResolvePair(*(long*)&ih->saddr, "N/A")); } } it = args->m_Instance->m_IpResolver.find(*(long*)&ih->daddr); if(it != args->m_Instance->m_IpResolver.end()) { strncpy(hostname_destination, it->second.c_str(), sizeof(hostname_destination)/sizeof(hostname_destination[0])); } else { host = gethostbyaddr((char *) &ih->daddr, 4, AF_INET); hostname_destination[0] = '\0'; if(host) { strncpy(hostname_destination, host->h_name, sizeof(hostname_destination)/sizeof(hostname_destination[0])); args->m_Instance->m_IpResolver.insert(T_ResolvePair(*(long*)&ih->saddr, host->h_name)); } else { strcpy(hostname_destination,"N/A"); args->m_Instance->m_IpResolver.insert(T_ResolvePair(*(long*)&ih->saddr, "N/A")); } } if(ltime) { strftime( timestr, sizeof timestr, "%H:%M:%S", ltime); } else { timestr[0] = '\0'; } /* print ip addresses and udp ports */ // /* printf("%s,%.6d len:%d %d.%d.%d.%d:%d (%s) -> %d.%d.%d.%d:%d (%s)\n", timestr, packet.header.ts.tv_usec, packet.header.len, ih->saddr.byte1, ih->saddr.byte2, ih->saddr.byte3, ih->saddr.byte4, sport, hostname_source, ih->daddr.byte1, ih->daddr.byte2, ih->daddr.byte3, ih->daddr.byte4, dport, hostname_destination ); // */ /* std::cout << timestr ", " << packet.header->ts.tv_usec << " len:" << packet.header->len << ih->saddr.byte1 << "." << ih->saddr.byte2 << "." << ih->saddr.byte3 << "." ih->saddr.byte4 << ":" <daddr.byte1, ih->daddr.byte2, ih->daddr.byte3, ih->daddr.byte4, dport, hostname_destination // */ } return EXIT_SUCCESS; } void C_Sniffer::Callback(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data) { S_WinPcapPacket packet(header,pkt_data); EnterCriticalSection(&m_PacketsSection); m_Packets.push(packet); LeaveCriticalSection(&m_PacketsSection); return; }