static inline void ProcessTCPFlow(FlowSource_t *fs, struct FlowNode *NewNode ) { struct FlowNode *Node; assert(NewNode->memflag == NODE_IN_USE); Node = Insert_Node(NewNode); // Return existing Node if flow exists already, otherwise insert es new if ( Node == NULL ) { // Insert as new dbg_printf("New TCP flow: Packets: %u, Bytes: %u\n", NewNode->packets, NewNode->bytes); // in case it's a FIN/RST only packet - immediately flush it if ( NewNode->fin == FIN_NODE ) { // flush node if ( StorePcapFlow(fs, NewNode) ) { Remove_Node(NewNode); } } if ( !CacheCheck() ) { uint32_t NumFlows; LogError("Node cache exhausted! - Immediate flush - increase flow cache!!"); NumFlows = Flush_FlowTree(fs); LogError("Flushed flows: %u", NumFlows); } if ( Link_RevNode(NewNode)) { // if we could link this new node, it is the server answer // -> calculate server latency SetServer_latency(NewNode); } return; } assert(Node->memflag == NODE_IN_USE); // check for first client ACK for client latency if ( Node->latency.flag == 1 ) { SetClient_latency(Node, &(NewNode->t_first)); } else if ( Node->latency.flag == 2 ) { SetApplication_latency(Node, &(NewNode->t_first)); } // update existing flow Node->flags |= NewNode->flags; Node->packets++; Node->bytes += NewNode->bytes; Node->t_last = NewNode->t_last; dbg_printf("Existing TCP flow: Packets: %u, Bytes: %u\n", Node->packets, Node->bytes); if ( NewNode->fin == FIN_NODE) { // flush node Node->fin = FIN_NODE; if ( StorePcapFlow(fs, Node) ) { Remove_Node(Node); } } else { Free_Node(NewNode); } } // End of ProcessTCPFlow
static inline void ProcessTCPFlow (FlowSource_t *fs, struct FlowNode *NewNode) { struct FlowNode *Node; assert (NewNode->memflag == NODE_IN_USE); Node = Insert_Node (NewNode); // if insert fails, the existing node is returned -> flow exists already if (Node == NULL) { dbg_printf ("New TCP flow: Packets: %u, Bytes: %u\n", NewNode->packets, NewNode->bytes); // in case it's a FIN/RST only packet - immediately flush it if (NewNode->fin == FIN_NODE) { // flush node if (StorePcapFlow (fs, NewNode)) { Remove_Node (NewNode); } } if (!CacheCheck()) { uint32_t NumFlows; LogError ("Node cache exhausted! - Immediate flush - increase flow cache!!"); NumFlows = Flush_FlowTree (fs); LogError ("Flushed flows: %u", NumFlows); } return; } assert (Node->memflag == NODE_IN_USE); // update existing flow Node->flags |= NewNode->flags; Node->packets++; Node->bytes += NewNode->bytes; Node->t_last = NewNode->t_last; dbg_printf ("Existing TCP flow: Packets: %u, Bytes: %u\n", Node->packets, Node->bytes); if (NewNode->fin == FIN_NODE) { // flush node Node->fin = FIN_NODE; if (StorePcapFlow (fs, Node)) { Remove_Node (Node); } } else { Free_Node (NewNode); } } // End of ProcessTCPFlow
static inline void ProcessUDPFlow(FlowSource_t *fs, struct FlowNode *NewNode ) { struct FlowNode *Node; assert(NewNode->memflag == NODE_IN_USE); // Flush DNS queries directly if ( NewNode->src_port == 53 || NewNode->dst_port == 53 ) { StorePcapFlow(fs, NewNode); Free_Node(NewNode); return; } // insert other UDP traffic Node = Insert_Node(NewNode); // if insert fails, the existing node is returned -> flow exists already if ( Node == NULL ) { dbg_printf("New UDP flow: Packets: %u, Bytes: %u\n", NewNode->packets, NewNode->bytes); return; } assert(Node->memflag == NODE_IN_USE); // update existing flow Node->packets++; Node->bytes += NewNode->bytes; Node->t_last = NewNode->t_last; dbg_printf("Existing UDP flow: Packets: %u, Bytes: %u\n", Node->packets, Node->bytes); Free_Node(NewNode); } // End of ProcessUDPFlow
uint32_t Flush_FlowTree(FlowSource_t *fs) { struct FlowNode *node, *nxt; uint32_t n = NumFlows; // Dump all incomplete flows to the file for (node = RB_MIN(FlowTree, FlowTree); node != NULL; node = nxt) { StorePcapFlow(fs, node); nxt = RB_NEXT(FlowTree, FlowTree, node); #ifdef DEVEL if ( node->left || node->right ) { assert(node->proto == 17); node->left = node->right = NULL; } #endif Remove_Node(node); } #ifdef DEVEL if ( NumFlows != 0 ) LogError("### Flush_FlowTree() remaining flows: %u\n", NumFlows); #endif UDP_list.list = NULL; UDP_list.tail = NULL; UDP_list.size = 0; return n; } // End of Flush_FlowTree
static inline void ProcessICMPFlow(FlowSource_t *fs, struct FlowNode *NewNode ) { // Flush ICMP directly StorePcapFlow(fs, NewNode); dbg_printf("Flush ICMP flow: Packets: %u, Bytes: %u\n", NewNode->packets, NewNode->bytes); Free_Node(NewNode); } // End of ProcessICMPFlow
static inline void ProcessOtherFlow(FlowSource_t *fs, struct FlowNode *NewNode ) { // Flush Other packets directly StorePcapFlow(fs, NewNode); dbg_printf("Flush Other flow: Proto: %u, Packets: %u, Bytes: %u\n", NewNode->proto, NewNode->packets, NewNode->bytes); Free_Node(NewNode); } // End of ProcessOtherFlow
void UDPexpire(FlowSource_t *fs, time_t t_expire) { struct FlowNode *node; uint32_t num = 0; node = UDP_list.list; while ( node && (node->t_last.tv_sec < t_expire) ) { struct FlowNode *n = node; node = node->right; DisconnectFlowNode(&UDP_list, n); StorePcapFlow(fs, n); Remove_Node(n); num++; } dbg_printf("UDP expired %u flows - left %u\n", num, UDP_list.size); } // End of UDPexpire