diff options
Diffstat (limited to 'src/lib/ndpi_main.c')
-rw-r--r-- | src/lib/ndpi_main.c | 229 |
1 files changed, 179 insertions, 50 deletions
diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c index 4ca4bf415..eb883d677 100644 --- a/src/lib/ndpi_main.c +++ b/src/lib/ndpi_main.c @@ -66,6 +66,11 @@ static void (*_ndpi_flow_free)(void *ptr); static void *(*_ndpi_malloc)(size_t size); static void (*_ndpi_free)(void *ptr); +#ifdef FRAG_MAN +extern void add_segment_to_buffer( struct ndpi_flow_struct *flow, struct ndpi_tcphdr const * tcph); +extern uint8_t check_for_sequence( struct ndpi_flow_struct *flow, struct ndpi_tcphdr const * tcph); +#endif // FRAG_MAN + /* ****************************************** */ /* Forward */ @@ -3490,6 +3495,40 @@ int ndpi_handle_ipv6_extension_headers(struct ndpi_detection_module_struct *ndpi #endif /* NDPI_DETECTION_SUPPORT_IPV6 */ static u_int8_t ndpi_iph_is_valid_and_not_fragmented(const struct ndpi_iphdr *iph, const u_int16_t ipsize) { + + #ifdef FRAG_MAN + /* + the logic has been inverted!!! returned value: + 0: not fragmented (instead of fragmented) + 1: packet too small + 2: fragmented and last, reassemble + 3: fragmented but not the last, add to buffer + */ + u_int16_t tot_len = ntohs(iph->tot_len); + if ( ipsize < iph->ihl * 4 || ipsize < tot_len || tot_len < iph->ihl * 4 ) + // packet too small + return(1); + else if ((iph->frag_off & htons(0x2000)) != 0) { + // MF=1 : this is a fragment and not the last -> add to buffer + //printf("DBG(ndpi_iph_is_valid_and_not_fragmented): ipv4 fragment and not the last! (off=%u) \n", (htons(iph->frag_off) & 0x1FFF)<<3); + + // MUST add to buffer + return(3); + } else if ((iph->frag_off & htons(0x1FFF)) != 0) { + // MF=0, this is (a fragment, but) the last fragment! + //printf("DBG(ndpi_iph_is_valid_and_not_fragmented): ipv4 fragment and the last! (0ff=%u) \n", (htons(iph->frag_off) & 0x1FFF)<<3); + + // MUST to reassemble the packet! + return(2); + } + return (0); + +#else // FRAG_MAN + /* + returned value: + 0: fragmented + 1: not fragmented + */ //#ifdef REQUIRE_FULL_PACKETS if(ipsize < iph->ihl * 4 || ipsize < ntohs(iph->tot_len) || ntohs(iph->tot_len) < iph->ihl * 4 || (iph->frag_off & htons(0x1FFF)) != 0) { @@ -3498,8 +3537,21 @@ static u_int8_t ndpi_iph_is_valid_and_not_fragmented(const struct ndpi_iphdr *ip //#endif return(1); + +#endif // FRAG_MAN } +/* +extract the l4 payload, if available +returned value: +FRAG_MAN + 0: ok, extracted + 1: packet too small + 2,3: fragmented, .... +else + 0: ok, extracted + 1: error or not available +*/ static u_int8_t ndpi_detection_get_l4_internal(struct ndpi_detection_module_struct *ndpi_str, const u_int8_t *l3, u_int16_t l3_len, const u_int8_t **l4_return, u_int16_t *l4_len_return, u_int8_t *l4_protocol_return, u_int32_t flags) { @@ -3542,6 +3594,27 @@ static u_int8_t ndpi_detection_get_l4_internal(struct ndpi_detection_module_stru } #endif +#ifdef FRAG_MAN + if(iph != NULL) { + u_int8_t check4Frag = ndpi_iph_is_valid_and_not_fragmented(iph, l3_len); + /* 0: not fragmented; 1: too small; 2,3: fragmented */ + if (!check4Frag) { + u_int16_t len = ntohs(iph->tot_len); + u_int16_t hlen = (iph->ihl * 4); + + l4ptr = (((const u_int8_t *) iph) + hlen); + + if(len == 0) + len = l3_len; + + l4len = (len > hlen) ? (len - hlen) : 0; + l4protocol = iph->protocol; + } + else + return check4Frag; + } +#else //FRAGMAN + /* 0: fragmented; 1: not fragmented */ if(iph != NULL && ndpi_iph_is_valid_and_not_fragmented(iph, l3_len)) { u_int16_t len = ntohs(iph->tot_len); u_int16_t hlen = (iph->ihl * 4); @@ -3554,6 +3627,7 @@ static u_int8_t ndpi_detection_get_l4_internal(struct ndpi_detection_module_stru l4len = (len > hlen) ? (len - hlen) : 0; l4protocol = iph->protocol; } +#endif //FRAGMAN #ifdef NDPI_DETECTION_SUPPORT_IPV6 else if(iph_v6 != NULL && (l3_len - sizeof(struct ndpi_ipv6hdr)) >= ntohs(iph_v6->ip6_hdr.ip6_un1_plen)) { l4ptr = (((const u_int8_t *) iph_v6) + sizeof(struct ndpi_ipv6hdr)); @@ -3683,53 +3757,63 @@ static int ndpi_init_packet_header(struct ndpi_detection_module_struct *ndpi_str * idea: reset detection state if a connection is unknown */ if(flow->packet.tcp->syn != 0 && flow->packet.tcp->ack == 0 && flow->init_finished != 0 && - flow->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) { - u_int8_t backup; - u_int16_t backup1, backup2; - - if(flow->http.url) { - ndpi_free(flow->http.url); - flow->http.url = NULL; - } - - if(flow->http.content_type) { - ndpi_free(flow->http.content_type); - flow->http.content_type = NULL; - } - - if(flow->http.request_content_type) { - ndpi_free(flow->http.request_content_type); - flow->http.request_content_type = NULL; - } - - if(flow->http.user_agent) { - ndpi_free(flow->http.user_agent); - flow->http.user_agent = NULL; - } - - if(flow->kerberos_buf.pktbuf) { - ndpi_free(flow->kerberos_buf.pktbuf); - flow->kerberos_buf.pktbuf = NULL; - } - - if(flow->l4.tcp.tls.message.buffer) { - ndpi_free(flow->l4.tcp.tls.message.buffer); - flow->l4.tcp.tls.message.buffer = NULL; - flow->l4.tcp.tls.message.buffer_len = flow->l4.tcp.tls.message.buffer_used = 0; - } - - backup = flow->num_processed_pkts; - backup1 = flow->guessed_protocol_id; - backup2 = flow->guessed_host_protocol_id; - memset(flow, 0, sizeof(*(flow))); - - /* Restore pointers */ - flow->num_processed_pkts = backup; - flow->guessed_protocol_id = backup1; - flow->guessed_host_protocol_id = backup2; - flow->packet.tcp = (struct ndpi_tcphdr *) l4ptr; - - NDPI_LOG_DBG(ndpi_str, "tcp syn packet for unknown protocol, reset detection state\n"); + flow->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) { + + u_int8_t backup; + u_int16_t backup1, backup2; + +#ifdef FRAG_MAN + /* initialize the buffer to manage segments for a new http/dns connection */ + flow->tcp_segments_management=1; + for (int i=0; i<2; i++ ) { + // reset counter tcp segments management lists + flow->tcp_segments_list[i].ct_frag=0; + } +#endif // FRAG_MAN + + if(flow->http.url) { + ndpi_free(flow->http.url); + flow->http.url = NULL; + } + + if(flow->http.content_type) { + ndpi_free(flow->http.content_type); + flow->http.content_type = NULL; + } + + if(flow->http.request_content_type) { + ndpi_free(flow->http.request_content_type); + flow->http.request_content_type = NULL; + } + + if(flow->http.user_agent) { + ndpi_free(flow->http.user_agent); + flow->http.user_agent = NULL; + } + + if(flow->kerberos_buf.pktbuf) { + ndpi_free(flow->kerberos_buf.pktbuf); + flow->kerberos_buf.pktbuf = NULL; + } + + if(flow->l4.tcp.tls.message.buffer) { + ndpi_free(flow->l4.tcp.tls.message.buffer); + flow->l4.tcp.tls.message.buffer = NULL; + flow->l4.tcp.tls.message.buffer_len = flow->l4.tcp.tls.message.buffer_used = 0; + } + + backup = flow->num_processed_pkts; + backup1 = flow->guessed_protocol_id; + backup2 = flow->guessed_host_protocol_id; + memset(flow, 0, sizeof(*(flow))); + + /* Restore pointers */ + flow->num_processed_pkts = backup; + flow->guessed_protocol_id = backup1; + flow->guessed_host_protocol_id = backup2; + flow->packet.tcp = (struct ndpi_tcphdr *) l4ptr; + + NDPI_LOG_DBG(ndpi_str, "tcp syn packet for unknown protocol, reset detection state\n"); } } else { /* tcp header not complete */ @@ -3752,10 +3836,19 @@ static int ndpi_init_packet_header(struct ndpi_detection_module_struct *ndpi_str /* ************************************************ */ +#ifdef FRAG_MAN +uint8_t ndpi_connection_tracking(struct ndpi_detection_module_struct *ndpi_str, + struct ndpi_flow_struct *flow) { +#else // FRAG_MAN void ndpi_connection_tracking(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow) { +#endif // FRAG_MAN if(!flow) { +#ifdef FRAG_MAN + return 0; +#else // FRAG_MAN return; +#endif // FRAG_MAN } else { /* const for gcc code optimization and cleaner code */ struct ndpi_packet_struct *packet = &flow->packet; @@ -3764,7 +3857,7 @@ void ndpi_connection_tracking(struct ndpi_detection_module_struct *ndpi_str, const struct ndpi_ipv6hdr *iphv6 = packet->iphv6; #endif const struct ndpi_tcphdr *tcph = packet->tcp; - const struct ndpi_udphdr *udph = flow->packet.udp; + const struct ndpi_udphdr *udph = packet->udp; packet->tcp_retransmission = 0, packet->packet_direction = 0; @@ -3797,15 +3890,25 @@ void ndpi_connection_tracking(struct ndpi_detection_module_struct *ndpi_str, if(tcph->syn != 0 && tcph->ack == 0 && flow->l4.tcp.seen_syn == 0 && flow->l4.tcp.seen_syn_ack == 0 && flow->l4.tcp.seen_ack == 0) { flow->l4.tcp.seen_syn = 1; - } + } else if(tcph->syn != 0 && tcph->ack != 0 && flow->l4.tcp.seen_syn == 1 && flow->l4.tcp.seen_syn_ack == 0 && flow->l4.tcp.seen_ack == 0) { flow->l4.tcp.seen_syn_ack = 1; - } + } else if(tcph->syn == 0 && tcph->ack == 1 && flow->l4.tcp.seen_syn == 1 && flow->l4.tcp.seen_syn_ack == 1 && flow->l4.tcp.seen_ack == 0) { flow->l4.tcp.seen_ack = 1; } + +#ifdef FRAG_MAN + // check sequence, if there is missing packet, add it to buffer + if ( check_for_sequence(flow, tcph) ) { + // if here added segment to list for next elaboration + // and skip extra processing for after... + return 0; + } +#endif //FRAG_MAN + if((flow->next_tcp_seq_nr[0] == 0 && flow->next_tcp_seq_nr[1] == 0) || (flow->next_tcp_seq_nr[0] == 0 || flow->next_tcp_seq_nr[1] == 0)) { /* initialize tcp sequence counters */ @@ -3873,6 +3976,9 @@ void ndpi_connection_tracking(struct ndpi_detection_module_struct *ndpi_str, flow->byte_counter[packet->packet_direction] += packet->payload_packet_len; } } +#ifdef FRAG_MAN + return 1; +#endif // FRAG_MAN } /* ************************************************ */ @@ -4256,7 +4362,12 @@ void ndpi_process_extra_packet(struct ndpi_detection_module_struct *ndpi_str, st /* detect traffic for tcp or udp only */ flow->src = src, flow->dst = dst; + +#ifdef FRAG_MAN + if ( ndpi_connection_tracking(ndpi_str, flow) ) { +#else // FRAG_MAN ndpi_connection_tracking(ndpi_str, flow); +#endif // FRAG_MAN /* call the extra packet function (which may add more data/info to flow) */ if(flow->extra_packets_func) { @@ -4266,8 +4377,13 @@ void ndpi_process_extra_packet(struct ndpi_detection_module_struct *ndpi_str, st if(++flow->num_extra_packets_checked == flow->max_extra_packets_to_check) flow->extra_packets_func = NULL; /* Enough packets detected */ } +#ifdef FRAG_MAN + } +#endif // FRAG_MAN } + + /* ********************************************************************************* */ int ndpi_load_ip_category(struct ndpi_detection_module_struct *ndpi_str, const char *ip_address_and_mask, @@ -4620,6 +4736,9 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct } flow->num_processed_pkts++; +#ifdef FRAG_MAN + flow->tcp_segments_management=1; +#endif // FRAG_MAN /* Init default */ ret.master_protocol = flow->detected_protocol_stack[1], @@ -4896,6 +5015,16 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct flow->fail_with_unknown = 1; invalidate_ptr: +#ifdef FRAG_MAN +if (flow->must_free[flow->packet.packet_direction] && + flow->packet.payload_packet_len>0 && flow->packet.payload) { + // if the payload is allocated for segments reassembling, it must be free + ndpi_free((void*)flow->packet.payload); + // flow->packet.payload=NULL; done after + flow->packet.payload_packet_len=0; + flow->must_free[flow->packet.packet_direction]=0; + } +#endif // FRAG_MAN /* Invalidate packet memory to avoid accessing the pointers below when the packet is no longer accessible |