static struct ndpi_flow *get_ndpi_flow(const u_int8_t version, const struct ndpi_iphdr *iph, u_int16_t ip_offset, u_int16_t ipsize, u_int16_t l4_packet_len, struct ndpi_id_struct **src, struct ndpi_id_struct **dst, u_int8_t *proto) { u_int32_t idx, l4_offset; struct ndpi_tcphdr *tcph = NULL; struct ndpi_udphdr *udph = NULL; u_int32_t lower_ip; u_int32_t upper_ip; u_int16_t lower_port; u_int16_t upper_port; struct ndpi_flow flow; void *ret; if(version == 4) { if(ipsize < 20) return NULL; if((iph->ihl * 4) > ipsize || ipsize < ntohs(iph->tot_len) || (iph->frag_off & htons(0x1FFF)) != 0) return NULL; } if(iph->saddr < iph->daddr) { lower_ip = iph->saddr; upper_ip = iph->daddr; } else { lower_ip = iph->daddr; upper_ip = iph->saddr; } *proto = iph->protocol; l4_offset = iph->ihl * 4; if(iph->protocol == 6 && l4_packet_len >= 20) { // tcp tcph = (struct ndpi_tcphdr *) ((u_int8_t *) iph + l4_offset); if(iph->saddr < iph->daddr) { lower_port = tcph->source; upper_port = tcph->dest; } else { lower_port = tcph->dest; upper_port = tcph->source; } } else if(iph->protocol == 17 && l4_packet_len >= 8) { // udp udph = (struct ndpi_udphdr *) ((u_int8_t *) iph + l4_offset); if(iph->saddr < iph->daddr) { lower_port = udph->source; upper_port = udph->dest; } else { lower_port = udph->dest; upper_port = udph->source; } } else { // non tcp/udp protocols lower_port = 0; upper_port = 0; } flow.protocol = iph->protocol; flow.lower_ip = lower_ip; flow.upper_ip = upper_ip; flow.lower_port = lower_port; flow.upper_port = upper_port; /* printf("[NDPI] [%u][%u:%u <-> %u:%u]\n", iph->protocol, lower_ip, lower_port, upper_ip, upper_port); */ idx = (lower_ip + upper_ip + iph->protocol + lower_port + upper_port) % NUM_ROOTS; ret = ndpi_tfind(&flow, (void*)&ndpi_flows_root[idx], node_cmp); if(ret == NULL) { if(ndpi_flow_count == MAX_NDPI_FLOWS) { printf("ERROR: maximum flow count (%u) has been exceeded\n", MAX_NDPI_FLOWS); exit(-1); } else { struct ndpi_flow *newflow = (struct ndpi_flow*)malloc(sizeof(struct ndpi_flow)); if(newflow == NULL) { printf("[NDPI] %s(1): not enough memory\n", __FUNCTION__); return(NULL); } memset(newflow, 0, sizeof(struct ndpi_flow)); newflow->protocol = iph->protocol; newflow->lower_ip = lower_ip, newflow->upper_ip = upper_ip; newflow->lower_port = lower_port, newflow->upper_port = upper_port; if((newflow->ndpi_flow = calloc(1, size_flow_struct)) == NULL) { printf("[NDPI] %s(2): not enough memory\n", __FUNCTION__); return(NULL); } if((newflow->src_id = calloc(1, size_id_struct)) == NULL) { printf("[NDPI] %s(3): not enough memory\n", __FUNCTION__); return(NULL); } if((newflow->dst_id = calloc(1, size_id_struct)) == NULL) { printf("[NDPI] %s(4): not enough memory\n", __FUNCTION__); return(NULL); } ndpi_tsearch(newflow, (void*)&ndpi_flows_root[idx], node_cmp); /* Add */ ndpi_flow_count += 1; //printFlow(newflow); *src = newflow->src_id, *dst = newflow->dst_id; return(newflow); } } else { struct ndpi_flow *flow = *(struct ndpi_flow**)ret; if(flow->lower_ip == lower_ip && flow->upper_ip == upper_ip && flow->lower_port == lower_port && flow->upper_port == upper_port) *src = flow->src_id, *dst = flow->dst_id; else *src = flow->dst_id, *dst = flow->src_id; return flow; } }
static struct ndpi_flow *get_ndpi_flow(const struct pcap_pkthdr *header, const struct ndpi_iphdr *iph, u_int16_t ipsize) { u_int32_t i; u_int16_t l4_packet_len; struct ndpi_tcphdr *tcph = NULL; struct ndpi_udphdr *udph = NULL; u_int32_t lower_ip; u_int32_t upper_ip; u_int16_t lower_port; u_int16_t upper_port; struct ndpi_flow flow; void *ret; if (ipsize < 20) return NULL; if ((iph->ihl * 4) > ipsize || ipsize < ntohs(iph->tot_len) || (iph->frag_off & htons(0x1FFF)) != 0) return NULL; l4_packet_len = ntohs(iph->tot_len) - (iph->ihl * 4); if (iph->saddr < iph->daddr) { lower_ip = iph->saddr; upper_ip = iph->daddr; } else { lower_ip = iph->daddr; upper_ip = iph->saddr; } if (iph->protocol == 6 && l4_packet_len >= 20) { // tcp tcph = (struct ndpi_tcphdr *) ((u_int8_t *) iph + iph->ihl * 4); if (iph->saddr < iph->daddr) { lower_port = tcph->source; upper_port = tcph->dest; } else { lower_port = tcph->dest; upper_port = tcph->source; } } else if (iph->protocol == 17 && l4_packet_len >= 8) { // udp udph = (struct ndpi_udphdr *) ((u_int8_t *) iph + iph->ihl * 4); if (iph->saddr < iph->daddr) { lower_port = udph->source; upper_port = udph->dest; } else { lower_port = udph->dest; upper_port = udph->source; } } else { // non tcp/udp protocols lower_port = 0; upper_port = 0; } flow.protocol = iph->protocol; flow.lower_ip = lower_ip; flow.upper_ip = upper_ip; flow.lower_port = lower_port; flow.upper_port = upper_port; flow.first_packet_time_sec = header->ts.tv_sec; flow.first_packet_time_usec = header->ts.tv_usec; ret = ndpi_tfind(&flow, (void*)&ndpi_flows_root, node_cmp); if(ret == NULL) { if (ndpi_flow_count == MAX_NDPI_FLOWS) { printf("ERROR: maximum flow count (%u) has been exceeded\n", MAX_NDPI_FLOWS); exit(-1); } else { struct ndpi_flow *newflow = (struct ndpi_flow*)malloc(sizeof(struct ndpi_flow)); if(newflow == NULL) { printf("[NDPI] %s(1): not enough memory\n", __FUNCTION__); return(NULL); } memset(newflow, 0, sizeof(struct ndpi_flow)); newflow->protocol = iph->protocol; newflow->lower_ip = lower_ip, newflow->upper_ip = upper_ip; newflow->lower_port = lower_port, newflow->upper_port = upper_port; newflow->first_packet_time_sec = header->ts.tv_sec; newflow->first_packet_time_usec = header->ts.tv_usec; if((newflow->ndpi_flow = calloc(1, size_flow_struct)) == NULL) { printf("[NDPI] %s(2): not enough memory\n", __FUNCTION__); return(NULL); } if((newflow->src_id = calloc(1, size_id_struct)) == NULL) { printf("[NDPI] %s(3): not enough memory\n", __FUNCTION__); return(NULL); } if((newflow->dst_id = calloc(1, size_id_struct)) == NULL) { printf("[NDPI] %s(4): not enough memory\n", __FUNCTION__); return(NULL); } ndpi_tsearch(newflow, (void*)&ndpi_flows_root, node_cmp); /* Add */ ndpi_flow_count += 1; //printFlow(newflow); return(newflow); } } else return *(struct ndpi_flow**)ret; }