aboutsummaryrefslogtreecommitdiff
path: root/src/lib/ndpi_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/ndpi_main.c')
-rw-r--r--src/lib/ndpi_main.c229
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