int processPacket(const Packet &packet) { // DNS query. if (packet.sourcePort() != ntohs(53)) { qr = DNS_QUERY; makeFlowID(flowID, packet.sourceIP(), packet.destinationIP(), packet.sourcePort(), packet.destinationPort()); } // DNS response. else { qr = DNS_RESPONSE; makeFlowID(flowID, packet.destinationIP(), packet.sourceIP(), packet.destinationPort(), packet.sourcePort()); } bucket = flowTable.bucket(flowID); // Prevents interference with flush(). pthread_mutex_lock(&(flowTableLocks[bucket])); flowItr = flowTable.find(flowID); if (flowItr == flowTable.end()) { if (flowTable.size() == maxFlows) { if (maxFlowsWarning) { cout << "dns: flow table is full" << endl; maxFlowsWarning = false; } pthread_mutex_unlock(&(flowTableLocks[bucket])); return 0; } flowItr = flowTable.insert(make_pair(flowID, new DNS)).first; flowItr -> second -> rawClientIP(*(uint32_t*)(flowID)); flowItr -> second -> rawServerIP(*(uint32_t*)(flowID + 4)); if (!getQuestion(flowItr -> second, packet.payload())) { ++numBadPackets; delete flowItr -> second; flowTable.erase(flowItr); pthread_mutex_unlock(&flowTableLocks[bucket]); return 0; } } // We only process supported resource record types. if (!isSupportedType(flowItr -> second -> queryType())) { delete flowItr -> second; flowTable.erase(flowItr); pthread_mutex_unlock(&flowTableLocks[bucket]); return 0; } if (qr == DNS_QUERY) { flowItr->second->queryTime(packet.time()); flowItr->second->rawQueryFlags(*(uint16_t*)(packet.payload() + 2)); } else { flowItr->second->responseTime(packet.time()); flowItr->second->rawResponseFlags(*(uint16_t*)(packet.payload() + 2)); if (getAnswers(flowItr->second, packet.payload(), packet.payloadSize())) { writer->write(flowItr -> second); } else { delete flowItr -> second; ++numBadPackets; } flowTable.erase(flowItr); } pthread_mutex_unlock(&flowTableLocks[bucket]); return 0; }