void Socket::bind(const IPv4Address &ip){ sockaddr_in name; name.sin_family = AF_INET; name.sin_addr = *ip.address(); if(::bind(_socket, (struct sockaddr *)&name, sizeof(sockaddr_in)) != 0){ switch(errno){ default: NetworkException(errno); } } }
void IPForensics::update_host(std::set<Host>::iterator it, IPv4Address ipv4, IPv6Address ipv6) { Host h = *it; if (h.ipv4().address().empty() && !ipv4.address().empty()) { h.set_ipv4(ipv4); } if (h.ipv6().address().empty() && !ipv6.address().empty()) { h.set_ipv6(ipv6); } // replace previous IPv6 address if it is link-local if (!h.ipv6().address().empty() && !ipv6.address().empty()) { if (h.ipv6().address()[0] == ipf::kLinkLocalIPv6[0] && h.ipv6().address()[1] == ipf::kLinkLocalIPv6[1] && ipv6.address()[0] != ipf::kLinkLocalIPv6[0] && ipv6.address()[1] != ipf::kLinkLocalIPv6[1]) { h.set_ipv6(ipv6); } } hosts_.erase(it); hosts_.insert(h); }
OldUDPSocket::OldUDPSocket(const IPv4Address &addr, int _port){ #ifdef USE_EMBEDDED_CLASSNAMES setClassName(__xvr2_Net_OldUDPSocket); #endif flags = MSG_NOSIGNAL; port = _port; bzero(&ipv4addr, sizeof(struct ::sockaddr_in)); ipv4addr.sin_family = AF_INET; ipv4addr.sin_port = htons(_port); ipv4addr.sin_addr = *addr.address(); tsock = socket(ipv4addr.sin_family, SOCK_DGRAM, 0); if(tsock < 0){ switch(errno){ case EMFILE: throw ProcOutOfFileDescriptors(); break; case ENFILE: throw SysOutOfFileDescriptors(); break; default: throw IOException(); } } }
void CLogViewWindow::ProxyEvent(LogProxyEvent Event, const IPv4Address& addr) { CString msg = GetTranslateMessage(ID_PROXYEVENTHEADER, addr.GetPortNumber()).c_str(); switch (Event) { case kLogProxyNewRequest: msg += GetTranslateMessage(ID_PROXYNEWREQUEST).c_str(); break; case kLogProxyEndRequest: msg += GetTranslateMessage(ID_PROXYENDREQUEST).c_str(); break; default: ATLASSERT( FALSE ); return ; } SetWindowText(GetTranslateMessage(IDD_LOGVIEW, CLog::GetActiveRequestCount()).c_str()); if (m_bProxyEvent == false) return; _AppendText(msg, LOG_COLOR_PROXY); }
int ResolveUtil::getHostnameByAddress(bsl::string *canonicalHostname, const IPv4Address& address, int *errorCode) { BSLS_ASSERT(canonicalHostname); struct hostent *hp = NULL; unsigned int addr = address.ipAddress(); // in network order #if defined(BSLS_PLATFORM_OS_AIX) struct hostent hent; struct hostent_data hdt; if (gethostbyaddr_r(reinterpret_cast<char *>(&addr), sizeof (struct in_addr), AF_INET, &hent, &hdt)) { if (errorCode) { *errorCode = h_errno; } return -1; // RETURN } *canonicalHostname = hent.h_name; #elif defined(BSLS_PLATFORM_OS_SUNOS) || defined(BSLS_PLATFORM_OS_SOLARIS) struct hostent hent; char hdt[2048]; int err; hp = gethostbyaddr_r(reinterpret_cast<char *>(&addr), sizeof (struct in_addr), AF_INET, &hent, hdt, sizeof(hdt), &err); if (0 == hp) { if (errorCode) { *errorCode = err; } return -1; // RETURN } *canonicalHostname = hp->h_name; #elif defined(BSLS_PLATFORM_OS_LINUX) \ || defined(BSLS_PLATFORM_OS_FREEBSD) struct hostent hent; char hdt[2048]; int err; if (gethostbyaddr_r(reinterpret_cast<char *>(&addr), sizeof (struct in_addr), AF_INET, &hent, hdt, sizeof(hdt), &hp, &err) || 0 == hp) { if (errorCode) { *errorCode = err; } return -1; // RETURN } *canonicalHostname = hp->h_name; #elif defined(BSLS_PLATFORM_OS_UNIX) // Standard call cannot be assumed to be re-entrant (it often is not). { static bslmt::Mutex mutex; bslmt::LockGuard<bslmt::Mutex> guard(&mutex); hp = gethostbyaddr(reinterpret_cast<char *>(&addr), sizeof (struct in_addr), AF_INET); if (0 == hp) { if (errorCode) { #ifdef BSLS_PLATFORM_OS_HPUX *errorCode = h_errno; #else *errorCode = errno; #endif } return -1; // RETURN } *canonicalHostname = hp->h_name; } #elif defined(BSLS_PLATFORM_OS_WINDOWS) unsigned short port = address.portNumber(); // in host order struct sockaddr_in saGNI; char hostName[NI_MAXHOST]; char servInfo[NI_MAXSERV]; saGNI.sin_family = AF_INET; saGNI.sin_addr.s_addr = addr; saGNI.sin_port = htons(port); if (getnameinfo(reinterpret_cast<SOCKADDR *>(&saGNI), sizeof(sockaddr), hostName, sizeof(hostName), servInfo, sizeof(servInfo), NI_NUMERICSERV|NI_NAMEREQD)) { if (errorCode) { *errorCode = WSAGetLastError(); } return -1; // RETURN } *canonicalHostname = hostName; // a Fully Qualified Domain Name (FQDN) #else #error getHostnameByAddress does not handle current platform type! #endif return 0; }
IPv4Address::IPv4Address(const IPv4Address& _ip) : ipAddr(_ip.data()){}
bool IPv4Address::operator>(const IPv4Address& _rhs) const{ return ipAddr < _rhs.data(); }
IPv4Address NetworkUtils::getIPv4Address(std::string hostname, PcapLiveDevice* device, double& dnsResponseTimeMS, uint32_t& dnsTTL, int dnsTimeout, IPv4Address dnsServerIP, IPv4Address gatewayIP) { IPv4Address result = IPv4Address::Zero; // open the device if not already opened bool closeDeviceAtTheEnd = false; if (!device->isOpened()) { closeDeviceAtTheEnd = true; if (!device->open()) { LOG_ERROR("Cannot open device"); return result; } } // first - resolve gateway MAC address // if gateway IP wasn't provided - try to find the default gateway if (gatewayIP == IPv4Address::Zero) { gatewayIP = device->getDefaultGateway(); } if (!gatewayIP.isValid() || gatewayIP == IPv4Address::Zero) { LOG_ERROR("Gateway address isn't valid or couldn't find default gateway"); return result; } // send the ARP request to find gateway MAC address double arpResTime; MacAddress gatewayMacAddress = getMacAddress(gatewayIP, device, arpResTime); if (gatewayMacAddress == MacAddress::Zero) { LOG_ERROR("Coulnd't resolve gateway MAC address"); return result; } if (dnsTimeout <= 0) dnsTimeout = NetworkUtils::DefaultTimeout; // validate DNS server IP. If it wasn't provided - set the system-configured DNS server if (dnsServerIP == IPv4Address::Zero && device->getDnsServers().size() > 0) { dnsServerIP = device->getDnsServers().at(0); } if (!dnsServerIP.isValid()) { LOG_ERROR("DNS server IP isn't valid"); return result; } // create DNS request Packet dnsRequest(100); MacAddress sourceMac = device->getMacAddress(); EthLayer ethLayer(sourceMac, gatewayMacAddress, PCPP_ETHERTYPE_IP); IPv4Layer ipLayer(device->getIPv4Address(), dnsServerIP); ipLayer.getIPv4Header()->timeToLive = 128; // randomize source port to a number >= 10000 int srcPortLowest = 10000; int srcPortRange = (2^16) - srcPortLowest; uint16_t srcPort = (rand() % srcPortRange) + srcPortLowest; UdpLayer udpLayer(srcPort, DNS_PORT); // create the DNS request for the hostname DnsLayer dnsLayer; // randomize transaction ID uint16_t transactionID = rand() % (2^16); dnsLayer.getDnsHeader()->transactionID = htons(transactionID); dnsLayer.addQuery(hostname, DNS_TYPE_A, DNS_CLASS_IN); // add all layers to packet if (!dnsRequest.addLayer(ðLayer) || !dnsRequest.addLayer(&ipLayer) || !dnsRequest.addLayer(&udpLayer) || !dnsRequest.addLayer(&dnsLayer)) { LOG_ERROR("Couldn't construct DNS query"); return result; } dnsRequest.computeCalculateFields(); // set a DNS response filter on the device PortFilter dnsResponseFilter(53, SRC); if (!device->setFilter(dnsResponseFilter)) { LOG_ERROR("Couldn't set DNS respnse filter"); return result; } // since packet capture is done on another thread, I use a conditional mutex with timeout to synchronize between the capture // thread and the main thread. When the capture thread starts running the main thread is blocking on the conditional mutex. // When the DNS response are captured the capture thread signals the main thread and the main thread stops capturing and continues // to the next iteration. if a timeout passes and no DNS response is captured, the main thread stops capturing pthread_mutex_t mutex; pthread_cond_t cond; // init the conditonal mutex pthread_mutex_init(&mutex, 0); pthread_cond_init(&cond, 0); // this is the token that passes between the 2 threads DNSRecievedData data = { &mutex, &cond, hostname, transactionID, clock(), IPv4Address::Zero, 0, 0 }; struct timeval now; gettimeofday(&now,NULL); // create the timeout timespec timeout = { now.tv_sec + dnsTimeout, now.tv_usec }; // start capturing. The capture is done on another thread, hence "dnsResponseRecieved" is running on that thread device->startCapture(dnsResponseRecieved, &data); // send the DNS request device->sendPacket(&dnsRequest); pthread_mutex_lock(&mutex); // block on the conditional mutex until capture thread signals or until timeout expires int res = pthread_cond_timedwait(&cond, &mutex, &timeout); // stop the capturing thread device->stopCapture(); pthread_mutex_unlock(&mutex); // check if timeout expired if (res == ETIMEDOUT) { LOG_ERROR("DNS request time out"); return result; } pthread_mutex_destroy(&mutex); pthread_cond_destroy(&cond); if (closeDeviceAtTheEnd) device->close(); else device->clearFilter(); result = data.result; dnsResponseTimeMS = data.dnsResponseTime; dnsTTL = data.ttl; return result; }
sockaddr_in toSockaddr(const IPv4Address & address) { return address.getData()->address; }
void CLogViewWindow::HttpEvent(LogHttpEvent Event, const IPv4Address& addr, int RequestNumber, const std::string& text) { CString msg = GetTranslateMessage(ID_HTTPEVENTHEADER, addr.GetPortNumber(), RequestNumber).c_str(); switch (Event) { case kLogHttpNewRequest: { CString url = text.c_str(); CString temp; temp.Format(_T("#%d %s"), RequestNumber, (LPCWSTR)url); int nSel = m_cmbRequest.AddString(temp); m_cmbRequest.SetItemData(nSel, RequestNumber); return; } break; case kLogHttpRecvOut: if (!m_bBrowserToProxy) return ; msg += GetTranslateMessage(ID_HTTPRECVOUT).c_str(); break; case kLogHttpSendOut: if (!m_bProxyToWeb) return ; msg += GetTranslateMessage(ID_HTTPSENDOUT).c_str(); break; case kLogHttpRecvIn: if (!m_bProxyFromWeb) return ; msg += GetTranslateMessage(ID_HTTPRECVIN).c_str(); break; case kLogHttpSendIn: if (!m_bBrowserFromProxy) return ; msg += GetTranslateMessage(ID_HTTPSENDIN).c_str(); break; case kLogHttpPostOut: if (!m_bViewPostData) return ; msg += L"PostData"; break; default: return ; } msg += _T("\n"); msg += UTF16fromUTF8(text).c_str(); msg += _T("\n"); // Colors depends on Outgoing or Incoming COLORREF color = LOG_COLOR_REQUEST; if (Event == kLogHttpRecvIn || Event == kLogHttpSendIn) { color = LOG_COLOR_RESPONSE; } else if (Event == kLogHttpPostOut) { color = LOG_COLOR_DEFAULT; std::string unescText = CUtil::UESC(text); std::string charaCode = DetectCharaCode(unescText); if (charaCode.length()) { UErrorCode err = UErrorCode::U_ZERO_ERROR; auto pConverter = ucnv_open(charaCode.c_str(), &err); if (pConverter) { std::wstring utf16PostData = UTF16fromConverter(unescText, pConverter); msg.AppendFormat(_T(">> Decode Data [%s]\n%s\n"), UTF16fromUTF8(charaCode).c_str(), utf16PostData.c_str()); ucnv_close(pConverter); } } msg += _T("\n"); } { CCritSecLock lock(m_csRequestLog); bool bFound = false; for (auto& reqLog : m_vecRquestLog) { if (reqLog->RequestNumber == RequestNumber) { reqLog->vecLog.emplace_back(new TextLog(msg, color)); lock.Unlock(); int nCurSel = m_cmbRequest.GetCurSel(); if (nCurSel > 0 && m_cmbRequest.GetItemData(nCurSel) == RequestNumber) { _AppendRequestLogText(msg, color); } bFound = true; break; } } if (bFound == false) { m_vecRquestLog.emplace_back(new RequestLog(RequestNumber)); m_vecRquestLog.back()->vecLog.emplace_back(new TextLog(msg, color)); } } _AppendText(msg, color); }
/** * main method of the application. Responsible for parsing user args, preparing worker thread configuration, creating the worker threads and activate them. * At program termination worker threads are stopped, statistics are collected from them and printed to console */ int main(int argc, char* argv[]) { std::vector<int> dpdkPortVec; bool writePacketsToDisk = false; string packetFilePath = ""; CoreMask coreMaskToUse = getCoreMaskForAllMachineCores(); int sendPacketsToPort = -1; int optionIndex = 0; char opt = 0; uint32_t mBufPoolSize = DEFAULT_MBUF_POOL_SIZE; IPv4Address srcIPToMatch = IPv4Address::Zero; IPv4Address dstIPToMatch = IPv4Address::Zero; uint16_t srcPortToMatch = 0; uint16_t dstPortToMatch = 0; ProtocolType protocolToMatch = Unknown; while((opt = getopt_long (argc, argv, "d:c:s:f:m:i:I:p:P:r:hl", FilterTrafficOptions, &optionIndex)) != -1) { switch (opt) { case 0: { break; } case 'd': { string portListAsString = string(optarg); stringstream stream(portListAsString); string portAsString; int port; // break comma-separated string into string list while(getline(stream, portAsString, ',')) { char c; std::stringstream stream2(portAsString); stream2 >> port; if (stream2.fail() || stream2.get(c)) { // not an integer EXIT_WITH_ERROR_AND_PRINT_USAGE("DPDK ports list is invalid"); } dpdkPortVec.push_back(port); } // verify list is not empty if (dpdkPortVec.empty()) { EXIT_WITH_ERROR_AND_PRINT_USAGE("DPDK ports list is empty"); } break; } case 's': { sendPacketsToPort = atoi(optarg); break; } case 'c': { coreMaskToUse = atoi(optarg); break; } case 'f': { packetFilePath = string(optarg); writePacketsToDisk = true; if (packetFilePath.empty()) { EXIT_WITH_ERROR_AND_PRINT_USAGE("Filename to write packets is empty"); } break; } case 'm': { mBufPoolSize = atoi(optarg); break; } case 'i': { srcIPToMatch = IPv4Address(optarg); if (!srcIPToMatch.isValid()) { EXIT_WITH_ERROR_AND_PRINT_USAGE("Source IP to match isn't a valid IP address"); } break; } case 'I': { dstIPToMatch = IPv4Address(optarg); if (!dstIPToMatch.isValid()) { EXIT_WITH_ERROR_AND_PRINT_USAGE("Destination IP to match isn't a valid IP address"); } break; } case 'p': { srcPortToMatch = atoi(optarg); if (srcPortToMatch <= 0) { EXIT_WITH_ERROR_AND_PRINT_USAGE("Source port to match isn't a valid TCP/UDP port"); } break; } case 'P': { dstPortToMatch = atoi(optarg); if (dstPortToMatch <= 0) { EXIT_WITH_ERROR_AND_PRINT_USAGE("Destination port to match isn't a valid TCP/UDP port"); } break; } case 'r': { string protocol = string(optarg); if (protocol == "TCP") protocolToMatch = TCP; else if (protocol == "UDP") protocolToMatch = UDP; else { EXIT_WITH_ERROR_AND_PRINT_USAGE("Protocol to match isn't TCP or UDP"); } break; } case 'h': { printUsage(); exit(0); } case 'l': { listDpdkPorts(); exit(0); } default: { printUsage(); exit(0); } } } // verify list is not empty if (dpdkPortVec.empty()) { EXIT_WITH_ERROR_AND_PRINT_USAGE("DPDK ports list is empty. Please use the -d switch"); } // initialize DPDK if (!DpdkDeviceList::initDpdk(coreMaskToUse, mBufPoolSize)) { EXIT_WITH_ERROR("couldn't initialize DPDK"); } // removing DPDK master core from core mask because DPDK worker threads cannot run on master core coreMaskToUse = coreMaskToUse & ~(DpdkDeviceList::getInstance().getDpdkMasterCore().Mask); // extract core vector from core mask vector<SystemCore> coresToUse; createCoreVectorFromCoreMask(coreMaskToUse, coresToUse); // collect the list of DPDK devices vector<DpdkDevice*> dpdkDevicesToUse; for (vector<int>::iterator iter = dpdkPortVec.begin(); iter != dpdkPortVec.end(); iter++) { DpdkDevice* dev = DpdkDeviceList::getInstance().getDeviceByPort(*iter); if (dev == NULL) { EXIT_WITH_ERROR("DPDK device for port %d doesn't exist", *iter); } dpdkDevicesToUse.push_back(dev); } // get DPDK device to send packets to (or NULL if doesn't exist) DpdkDevice* sendPacketsTo = DpdkDeviceList::getInstance().getDeviceByPort(sendPacketsToPort); if (sendPacketsTo != NULL && !sendPacketsTo->open()) { EXIT_WITH_ERROR("Could not open port#%d for sending matched packets", sendPacketsToPort); } // go over all devices and open them for (vector<DpdkDevice*>::iterator iter = dpdkDevicesToUse.begin(); iter != dpdkDevicesToUse.end(); iter++) { if (!(*iter)->openMultiQueues((*iter)->getTotalNumOfRxQueues(), (*iter)->getTotalNumOfTxQueues())) { EXIT_WITH_ERROR("Couldn't open DPDK device #%d, PMD '%s'", (*iter)->getDeviceId(), (*iter)->getPMDName().c_str()); } } // prepare configuration for every core AppWorkerConfig workerConfigArr[coresToUse.size()]; prepareCoreConfiguration(dpdkDevicesToUse, coresToUse, writePacketsToDisk, packetFilePath, sendPacketsTo, workerConfigArr, coresToUse.size()); PacketMatchingEngine matchingEngine(srcIPToMatch, dstIPToMatch, srcPortToMatch, dstPortToMatch, protocolToMatch); // create worker thread for every core vector<DpdkWorkerThread*> workerThreadVec; int i = 0; for (vector<SystemCore>::iterator iter = coresToUse.begin(); iter != coresToUse.end(); iter++) { AppWorkerThread* newWorker = new AppWorkerThread(workerConfigArr[i], matchingEngine); workerThreadVec.push_back(newWorker); i++; } // start all worker threads if (!DpdkDeviceList::getInstance().startDpdkWorkerThreads(coreMaskToUse, workerThreadVec)) { EXIT_WITH_ERROR("Couldn't start worker threads"); } // register the on app close event to print summary stats on app termination FiltetTrafficArgs args; args.workerThreadsVector = &workerThreadVec; ApplicationEventHandler::getInstance().onApplicationInterrupted(onApplicationInterrupted, &args); // infinite loop (until program is terminated) while (!args.shouldStop) { sleep(5); } }
/** * Send a file to the pitcher */ void sendFile(std::string filePath, IPv4Address pitcherIP, IPv4Address catcherIP, size_t blockSize) { // identify the interface to listen and send packets to PcapLiveDevice* dev = PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp(&catcherIP); if (dev == NULL) EXIT_WITH_ERROR("Cannot find network interface with IP '%s'", catcherIP.toString().c_str()); // try to open the interface (device) if (!dev->open()) EXIT_WITH_ERROR("Cannot open network interface"); // set an ICMP protocol filter so it'll capture only ICMP packets ProtoFilter protocolFilter(ICMP); if (!dev->setFilter(protocolFilter)) EXIT_WITH_ERROR("Can't set ICMP filter on device"); // try the open the file for reading std::ifstream file(filePath.c_str(), std::ios::in|std::ios::binary); if (file.is_open()) { // extract file size file.seekg(0, std::ios_base::end); uint32_t fileSize = file.tellg(); // go back to the beginning of the file file.seekg(0, std::ios::beg); // remove the path and keep just the file name. This is the name that will be delivered to the pitcher std::string fileName = getFileNameFromPath(filePath); printf("Waiting for pitcher to send a keep-alive signal...\n"); IcmpFileTransferStart icmpFTStart = { pitcherIP, catcherIP, fileName, 0 }; // first, establish a connection with the pitcher and send it the file name. This method waits for the pitcher to send an ICMP // request which indicates it's alive. The response to the request will contain the file name in the ICMP response data int res = dev->startCaptureBlockingMode(startFileTransfer, &icmpFTStart, -1); // if an error occurred if (!res) EXIT_WITH_ERROR("Cannot start capturing packets"); printf("Sending file '%s' ", fileName.c_str()); IcmpFileContentDataSend icmpFileContentData = { pitcherIP, catcherIP, &file, true, 0, blockSize, NULL }; // create the memory block that will contain the file data chunks that will be transferred to the pitcher icmpFileContentData.memblock = new char[blockSize]; // wait for ICMP requests coming from the pitcher and send file data chunks as a reply in the ICMP response data // this method returns when all file was transferred to the pitcher res = dev->startCaptureBlockingMode(sendContent, &icmpFileContentData, -1); // free the memory block data and close the file delete [] icmpFileContentData.memblock; file.close(); // if capture failed, exit the program if (!res) EXIT_WITH_ERROR("Cannot start capturing packets"); printf("\n\nFinished sending '%s' [sent %d bytes]\n", fileName.c_str(), fileSize); } else // if file couldn't be opened EXIT_WITH_ERROR("Cannot open file '%s'", filePath.c_str()); // close the device dev->close(); }
/** * Receive a file from the pitcher */ void receiveFile(IPv4Address pitcherIP, IPv4Address catcherIP) { // identify the interface to listen and send packets to PcapLiveDevice* dev = PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp(&catcherIP); if (dev == NULL) EXIT_WITH_ERROR("Cannot find network interface with IP '%s'", catcherIP.toString().c_str()); // try to open the interface (device) if (!dev->open()) EXIT_WITH_ERROR("Cannot open network interface"); // set an ICMP protocol filter so it'll capture only ICMP packets ProtoFilter protocolFilter(ICMP); if (!dev->setFilter(protocolFilter)) EXIT_WITH_ERROR("Can't set ICMP filter on device"); printf("Waiting for pitcher to send a file...\n"); IcmpFileTransferStart icmpFTStart = { pitcherIP, catcherIP, "", 0 }; // wait until the pitcher sends an ICMP request with the file name in its data int res = dev->startCaptureBlockingMode(waitForFileTransferStart, &icmpFTStart, -1); if (!res) EXIT_WITH_ERROR("Cannot start capturing packets"); // create a new file with the name provided by the pitcher std::ofstream file(icmpFTStart.fileName.c_str(), std::ios::out|std::ios::binary); if (file.is_open()) { printf("Getting file from pitcher: '%s' ", icmpFTStart.fileName.c_str()); IcmpFileContentDataRecv icmpFileContentData = { pitcherIP, catcherIP, &file, icmpFTStart.fileName, (uint16_t)(icmpFTStart.icmpId+1), 0, 0 }; // get all file data from the pitcher. This method blocks until all file is received res = dev->startCaptureBlockingMode(getFileContent, &icmpFileContentData, -1); if (!res) { file.close(); EXIT_WITH_ERROR_AND_RUN_COMMAND("Cannot start capturing packets", std::remove(icmpFTStart.fileName.c_str())); } printf("\n\nFinished getting file '%s' [received %d bytes]\n", icmpFTStart.fileName.c_str(), icmpFileContentData.fileSize); } else EXIT_WITH_ERROR("Cannot create file"); // remove the filter and close the device (interface) dev->clearFilter(); dev->close(); }
int main(int argc, char* argv[]) { PfRingDevice* dev = NULL; int totalNumOfCores = getNumOfCores(); int numOfCaptureThreads = totalNumOfCores-1; PfRingDevice* sendPacketsToIface = NULL; std::string packetFilePath = ""; bool writePacketsToDisk = true; IPv4Address srcIPToMatch = IPv4Address::Zero; IPv4Address dstIPToMatch = IPv4Address::Zero; uint16_t srcPortToMatch = 0; uint16_t dstPortToMatch = 0; ProtocolType protocolToMatch = Unknown; int optionIndex = 0; char opt = 0; while((opt = getopt_long (argc, argv, "n:s:t:f:i:I:p:P:r:hl", PfFilterTrafficOptions, &optionIndex)) != -1) { switch (opt) { case 0: { break; } case 'n': { std::string ifaceName = std::string(optarg); dev = PfRingDeviceList::getInstance().getPfRingDeviceByName(ifaceName); if (dev == NULL) EXIT_WITH_ERROR("Could not find PF_RING device '%s'", ifaceName.c_str()); break; } case 's': { std::string sendPacketsToIfaceName = std::string(optarg); sendPacketsToIface = PfRingDeviceList::getInstance().getPfRingDeviceByName(sendPacketsToIfaceName); if (sendPacketsToIface == NULL) EXIT_WITH_ERROR("Could not find PF_RING device '%s'", sendPacketsToIfaceName.c_str()); break; } case 't': { numOfCaptureThreads = atoi(optarg); if (numOfCaptureThreads < 1 || numOfCaptureThreads > totalNumOfCores-1) EXIT_WITH_ERROR("Number of capture threads must be in the range of 1 to %d", totalNumOfCores-1); break; } case 'f': { packetFilePath = string(optarg); // make sure the path ends with '/' if (packetFilePath.length() > 1 && (0 != packetFilePath.compare(packetFilePath.length()-1, 1, "/"))) packetFilePath += "/"; writePacketsToDisk = true; break; } case 'i': { srcIPToMatch = IPv4Address(optarg); if (!srcIPToMatch.isValid()) { EXIT_WITH_ERROR_AND_PRINT_USAGE("Source IP to match isn't a valid IP address"); } break; } case 'I': { dstIPToMatch = IPv4Address(optarg); if (!dstIPToMatch.isValid()) { EXIT_WITH_ERROR_AND_PRINT_USAGE("Destination IP to match isn't a valid IP address"); } break; } case 'p': { srcPortToMatch = atoi(optarg); if (srcPortToMatch <= 0) { EXIT_WITH_ERROR_AND_PRINT_USAGE("Source port to match isn't a valid TCP/UDP port"); } break; } case 'P': { dstPortToMatch = atoi(optarg); if (dstPortToMatch <= 0) { EXIT_WITH_ERROR_AND_PRINT_USAGE("Destination port to match isn't a valid TCP/UDP port"); } break; } case 'r': { string protocol = string(optarg); if (protocol == "TCP") protocolToMatch = TCP; else if (protocol == "UDP") protocolToMatch = UDP; else { EXIT_WITH_ERROR_AND_PRINT_USAGE("Protocol to match isn't TCP or UDP"); } break; } case 'h': { printUsage(); exit(0); } case 'l': { listPfRingDevices(); exit(0); } default: { printUsage(); exit(0); } } } if (dev == NULL) EXIT_WITH_ERROR_AND_PRINT_USAGE("Interface name was not provided"); // open the PF_RING device in multi-thread mode. Distribution of packets between threads will be done per-flow (as opposed to // round-robin) if (!dev->openMultiRxChannels(numOfCaptureThreads, PfRingDevice::PerFlow)) EXIT_WITH_ERROR("Couldn't open %d RX channels on interface '%s'", numOfCaptureThreads, dev->getDeviceName().c_str()); if (sendPacketsToIface != NULL && !sendPacketsToIface->open()) EXIT_WITH_ERROR("Couldn't open PF_RING device '%s' for sending matched packets", sendPacketsToIface->getDeviceName().c_str()); CoreMask coreMask = 0; int threadId = 0; int threadCount = 0; // create an array of packet stats with the size of all machine cores PacketStats packetStatsArr[totalNumOfCores]; // init each packet stats instance with an illegal core ID for (int coreId = 0; coreId < totalNumOfCores; coreId++) packetStatsArr[coreId].ThreadId = MAX_NUM_OF_CORES+1; // mark only relevant cores by adding them to core mask // mark only relevant packet stats instances by setting their core ID while (threadCount < numOfCaptureThreads) { if (SystemCores::IdToSystemCore[threadId].Id != dev->getCurrentCoreId().Id) { coreMask |= SystemCores::IdToSystemCore[threadId].Mask; packetStatsArr[threadId].ThreadId = SystemCores::IdToSystemCore[threadId].Id; threadCount++; } threadId++; } // create the matching engine instance PacketMatchingEngine matchingEngine(srcIPToMatch, dstIPToMatch, srcPortToMatch, dstPortToMatch, protocolToMatch); // create a flow table for each core map<uint32_t, bool> flowTables[totalNumOfCores]; PcapFileWriterDevice** pcapWriters = NULL; // if needed, prepare pcap writers for all capturing threads if (writePacketsToDisk) { pcapWriters = new PcapFileWriterDevice*[totalNumOfCores]; for (int coreId = 0; coreId < totalNumOfCores; coreId++) { // if core doesn't participate in capturing, skip it if ((coreMask & SystemCores::IdToSystemCore[coreId].Mask) == 0) { pcapWriters[coreId] = NULL; continue; } std::stringstream packetFileName; packetFileName << packetFilePath << "Thread" << coreId << ".pcap"; pcapWriters[coreId] = new PcapFileWriterDevice(packetFileName.str().c_str()); if (!pcapWriters[coreId]->open()) { EXIT_WITH_ERROR("Couldn't open pcap writer device for core %d", coreId); } } } printf("Start capturing on %d threads core mask = 0x%X\n", numOfCaptureThreads, coreMask); // prepare packet capture configuration CaptureThreadArgs args; args.packetStatArr = packetStatsArr; args.matchingEngine = &matchingEngine; args.flowTables = flowTables; args.sendPacketsTo = sendPacketsToIface; args.pcapWriters = pcapWriters; // start capturing packets on all threads if (!dev->startCaptureMultiThread(packetArrived, &args, coreMask)) EXIT_WITH_ERROR("Couldn't start capturing on core mask %X on interface '%s'", coreMask, dev->getDeviceName().c_str()); bool shouldStop = false; // register the on app close event to print summary stats on app termination ApplicationEventHandler::getInstance().onApplicationInterrupted(onApplicationInterrupted, &shouldStop); // infinite loop (until program is terminated) while (!shouldStop) { sleep(5); } // stop capturing packets, close the device dev->stopCapture(); dev->close(); // close and delete pcap writers if (writePacketsToDisk) { for (int coreId = 0; coreId < totalNumOfCores; coreId++) { if ((coreMask & SystemCores::IdToSystemCore[coreId].Mask) == 0) continue; pcapWriters[coreId]->close(); delete pcapWriters[coreId]; } } printf("\n\nApplication stopped\n"); // print final stats for every capture thread plus sum of all threads and free worker threads memory PacketStats aggregatedStats; bool printedStatsHeadline = false; for (int i = 0; i < totalNumOfCores; i++) { if (packetStatsArr[i].ThreadId == MAX_NUM_OF_CORES+1) continue; aggregatedStats.collectStats(packetStatsArr[i]); if (!printedStatsHeadline) { packetStatsArr[i].printStatsHeadline(); printedStatsHeadline = true; } packetStatsArr[i].printStats(); } aggregatedStats.printStats(); }
void UDPNetworkSocket::addTarget(const IPv4Address & address) { if (address.isValid()) data->targets.insert(address); }
static int daemonMain(int argc, char *argv[]) { try { std::string macAddressString = g_macAddress->val(); replace(macAddressString, "-", ""); if (macAddressString.size() != 12u) { std::cerr << "MAC address must be 12 characters" << std::endl; return -1; } std::string macAddress = dataFromHexstring(macAddressString); std::set<Address::ptr> blacklistedAddresses; std::vector<std::string> blacklistedAddressesString = split( g_blacklist->val(), ";, "); for(std::vector<std::string>::const_iterator it( blacklistedAddressesString.begin()); it != blacklistedAddressesString.end(); ++it) { if(it->empty()) continue; blacklistedAddresses.insert(IPAddress::create(it->c_str())); } std::vector<std::pair<Address::ptr, unsigned int> > addresses = Address::getInterfaceAddresses(g_interface->val(), AF_INET); if (addresses.empty()) { std::cerr << "Couldn't find interface " << g_interface->val() << std::endl; return -1; } IPAddress::ptr localAddress = boost::static_pointer_cast<IPAddress>( addresses.front().first); IPAddress::ptr broadcastAddress = localAddress->broadcastAddress( addresses.front().second); broadcastAddress->port(9u); IPv4Address multicastAddress("239.255.255.250", 1900); IOManager ioManager; Socket::ptr broadcastSocket(broadcastAddress->createSocket(ioManager, SOCK_DGRAM)); broadcastSocket->setOption(SOL_SOCKET, SO_BROADCAST, 1); broadcastSocket->connect(broadcastAddress); Socket::ptr listenSocket(multicastAddress.createSocket(ioManager, SOCK_DGRAM)); listenSocket->setOption(SOL_SOCKET, SO_REUSEADDR, 1); listenSocket->bind(IPv4Address(0u, 1900u)); // TODO: listenSocket->joinGroup(multicastAddress, addresses.front().first); struct ip_mreq multicastGroup; memcpy(&multicastGroup.imr_multiaddr, &((sockaddr_in *)multicastAddress.name())->sin_addr, sizeof(struct in_addr)); memcpy(&multicastGroup.imr_interface, &((sockaddr_in *)addresses.front().first->name())->sin_addr, sizeof(struct in_addr)); listenSocket->setOption(IPPROTO_IP, IP_ADD_MEMBERSHIP, multicastGroup); Daemon::onTerminate.connect(boost::bind(&Socket::cancelReceive, listenSocket)); try { IPv4Address sender; char buffer[4096]; size_t size; while((size = listenSocket->receiveFrom(buffer, 4096, sender))) { IPAddress::ptr senderDuplicate = sender.clone(); senderDuplicate->port(0u); if (blacklistedAddresses.find(senderDuplicate) != blacklistedAddresses.end()) { MORDOR_LOG_VERBOSE(Log::root()) << "Skipping broadcast from " << sender; continue; } HTTP::Request request; HTTP::RequestParser parser(request); parser.run(buffer, size); if (parser.complete() && !parser.error()) { if (request.requestLine.method == "M-SEARCH") { MORDOR_LOG_INFO(Log::root()) << "Relaying M-SEARCH to WOL from " << sender; wol(broadcastSocket, macAddress); } } else { MORDOR_LOG_WARNING(Log::root()) << "Unable to parse HTTP request from " << sender << ": " << charslice(buffer, size); } } } catch (OperationAbortedException &) { } catch (...) { MORDOR_LOG_FATAL(Log::root()) << boost::current_exception_diagnostic_information(); return -1; } } catch (...) { std::cerr << boost::current_exception_diagnostic_information() << std::endl; return -1; } return 0; }
void icmp_router_address_structure::setRouterAddress(IPv4Address addr, uint32_t preference) { routerAddress = addr.toInt(); preferenceLevel = htonl(preference); }
/** * main method of the application */ int main(int argc, char* argv[]) { std::string hostname; bool hostnameProvided = false; std::string interfaceNameOrIP; bool interfaceNameOrIPProvided = false; IPv4Address dnsServerIP = IPv4Address::Zero; IPv4Address gatewayIP = IPv4Address::Zero; int timeoutSec = -1; int optionIndex = 0; char opt = 0; while((opt = getopt_long (argc, argv, "i:d:g:s:t:hl", DNSResolverOptions, &optionIndex)) != -1) { switch (opt) { case 0: { break; } case 'h': { printUsage(); exit(0); } case 'l': { listInterfaces(); exit(0); } case 'i': { interfaceNameOrIP = optarg; interfaceNameOrIPProvided = true; break; } case 'd': { dnsServerIP = IPv4Address(optarg); break; } case 'g': { gatewayIP = IPv4Address(optarg); break; } case 's': { hostname = optarg; hostnameProvided = true; break; } case 't': { timeoutSec = atoi(optarg); break; } default: { printUsage(); exit(1); } } } // make sure that hostname is provided if (!hostnameProvided) EXIT_WITH_ERROR("Hostname not provided"); // find the interface to send the DNS request from PcapLiveDevice* dev = NULL; // if interface name or IP was provided - find the device accordingly if (interfaceNameOrIPProvided) { IPv4Address interfaceIP(interfaceNameOrIP); if (interfaceIP.isValid()) { dev = PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp(interfaceIP); if (dev == NULL) EXIT_WITH_ERROR("Couldn't find interface by provided IP"); } else { dev = PcapLiveDeviceList::getInstance().getPcapLiveDeviceByName(interfaceNameOrIP); if (dev == NULL) EXIT_WITH_ERROR("Couldn't find interface by provided name"); } } // if interface name or IP was not provided - find a device that has a default gateway else { const std::vector<PcapLiveDevice*>& devList = PcapLiveDeviceList::getInstance().getPcapLiveDevicesList(); for (std::vector<PcapLiveDevice*>::const_iterator iter = devList.begin(); iter != devList.end(); iter++) { if ((*iter)->getDefaultGateway() != IPv4Address::Zero) { dev = *iter; break; } } if (dev == NULL) EXIT_WITH_ERROR("Couldn't find an interface with a default gateway"); } printf("Using interface '%s'\n", dev->getIPv4Address().toString().c_str()); // find the IPv4 address for provided hostname double responseTime = 0; uint32_t dnsTTL = 0; IPv4Address resultIP = NetworkUtils::getInstance().getIPv4Address(hostname, dev, responseTime, dnsTTL, timeoutSec, dnsServerIP, gatewayIP); // print resolved IPv4 address if found if (resultIP == IPv4Address::Zero) printf("\nCould not resolve hostname [%s]\n", hostname.c_str()); else printf("\nIP address of [%s] is: %s DNS-TTL=%d time=%dms\n", hostname.c_str(), resultIP.toString().c_str(), dnsTTL, (int)responseTime); }