diff options
author | Luca Deri <deri@ntop.org> | 2024-09-15 19:38:33 +0200 |
---|---|---|
committer | Luca Deri <deri@ntop.org> | 2024-09-15 19:38:33 +0200 |
commit | fda3730cf0bdec6b4a1cd8e38d3a88c33f0d0ef1 (patch) | |
tree | 1935fc4a8fdcb7992649f6fe941b0013995e5927 /example/reader_util.c | |
parent | 9e5d0e05d341b58bb4de76e16a6102e55eac9cc1 (diff) |
Added -E option for dumping flow fingerprint
Diffstat (limited to 'example/reader_util.c')
-rw-r--r-- | example/reader_util.c | 69 |
1 files changed, 47 insertions, 22 deletions
diff --git a/example/reader_util.c b/example/reader_util.c index 014574503..d2b60859d 100644 --- a/example/reader_util.c +++ b/example/reader_util.c @@ -78,6 +78,7 @@ extern u_int8_t enable_flow_stats, enable_payload_analyzer; extern u_int8_t verbose, human_readeable_string_len; extern u_int8_t max_num_udp_dissected_pkts /* 24 */, max_num_tcp_dissected_pkts /* 80 */; static u_int32_t flow_id = 0; +extern FILE *fingerprint_fp; u_int8_t enable_doh_dot_detection = 0; @@ -462,7 +463,7 @@ static void ndpi_free_flow_tls_data(struct ndpi_flow_info *flow) { ndpi_free(flow->dhcp_fingerprint); flow->dhcp_fingerprint = NULL; } - + if(flow->dhcp_class_ident) { ndpi_free(flow->dhcp_class_ident); flow->dhcp_class_ident = NULL; @@ -477,7 +478,7 @@ static void ndpi_free_flow_tls_data(struct ndpi_flow_info *flow) { ndpi_free(flow->telnet.username); flow->telnet.username = NULL; } - + if(flow->telnet.password) { ndpi_free(flow->telnet.password); flow->telnet.password = NULL; @@ -784,7 +785,7 @@ static struct ndpi_flow_info *get_ndpi_flow_info(struct ndpi_workflow * workflow flow.protocol = iph->protocol, flow.vlan_id = vlan_id; flow.src_ip = iph->saddr, flow.dst_ip = iph->daddr; flow.src_port = htons(*sport), flow.dst_port = htons(*dport); - flow.hashval = hashval = flow.protocol + ntohl(flow.src_ip) + ntohl(flow.dst_ip) + flow.hashval = hashval = flow.protocol + ntohl(flow.src_ip) + ntohl(flow.dst_ip) + ntohs(flow.src_port) + ntohs(flow.dst_port); #if 0 @@ -1041,10 +1042,31 @@ u_int8_t plen2slot(u_int16_t plen) { /* ****************************************************** */ +static void dump_raw_fingerprint(struct ndpi_workflow * workflow, + struct ndpi_flow_info *flow, + char *fingerprint_family, + char *fingerprint) { + char buf[64]; + + fprintf(fingerprint_fp, "%u|%s|%s|%u|%s|%s|%s\n", + flow->protocol,flow->src_name, flow->dst_name, ntohs(flow->dst_port), + ndpi_protocol2name(workflow->ndpi_struct, flow->detected_protocol, buf, sizeof(buf)), + fingerprint_family, fingerprint); +} + +/* ****************************************************** */ + +static void dump_flow_fingerprint(struct ndpi_workflow * workflow, struct ndpi_flow_info *flow) { + if(flow->ndpi_flow->protos.tls_quic.ja4_client_raw != NULL) + dump_raw_fingerprint(workflow, flow, "JA4r", flow->ndpi_flow->protos.tls_quic.ja4_client_raw); +} + +/* ****************************************************** */ + void process_ndpi_collected_info(struct ndpi_workflow * workflow, struct ndpi_flow_info *flow) { u_int i, is_quic = 0; char out[128], *s; - + if(!flow->ndpi_flow) return; flow->info_type = INFO_INVALID; @@ -1052,8 +1074,8 @@ void process_ndpi_collected_info(struct ndpi_workflow * workflow, struct ndpi_fl s = ndpi_get_flow_risk_info(flow->ndpi_flow, out, sizeof(out), 0 /* text */); if(s != NULL) - flow->risk_str = ndpi_strdup(s); - + flow->risk_str = ndpi_strdup(s); + flow->confidence = flow->ndpi_flow->confidence; flow->fpc = flow->ndpi_flow->fpc; @@ -1067,7 +1089,7 @@ void process_ndpi_collected_info(struct ndpi_workflow * workflow, struct ndpi_fl ndpi_snprintf(flow->mining.currency, sizeof(flow->mining.currency), "%s", flow->ndpi_flow->protos.mining.currency); } - + flow->risk = flow->ndpi_flow->risk; if(is_ndpi_proto(flow, NDPI_PROTOCOL_DHCP)) { @@ -1084,7 +1106,7 @@ void process_ndpi_collected_info(struct ndpi_workflow * workflow, struct ndpi_fl if(flow->ndpi_flow->protos.bittorrent.hash[0] != '\0') { u_int avail = sizeof(flow->ndpi_flow->protos.bittorrent.hash) * 2 + 1; flow->bittorent_hash = ndpi_malloc(avail); - + if(flow->bittorent_hash) { for(i=0, j = 0; i < sizeof(flow->ndpi_flow->protos.bittorrent.hash); i++) { @@ -1093,7 +1115,7 @@ void process_ndpi_collected_info(struct ndpi_workflow * workflow, struct ndpi_fl j += 2; } - + flow->bittorent_hash[j] = '\0'; } } @@ -1125,7 +1147,7 @@ void process_ndpi_collected_info(struct ndpi_workflow * workflow, struct ndpi_fl /* SERVICE_LOCATION */ else if(is_ndpi_proto(flow, NDPI_PROTOCOL_SERVICE_LOCATION)) { size_t i; - + flow->info_type = INFO_GENERIC; flow->info[0] = 0; if (flow->ndpi_flow->protos.slp.url_count > 0) @@ -1133,7 +1155,7 @@ void process_ndpi_collected_info(struct ndpi_workflow * workflow, struct ndpi_fl for (i = 0; i < flow->ndpi_flow->protos.slp.url_count; ++i) { size_t length = strlen(flow->info); - + strncat(flow->info + length, flow->ndpi_flow->protos.slp.url[i], sizeof(flow->info) - length); length = strlen(flow->info); @@ -1325,7 +1347,7 @@ void process_ndpi_collected_info(struct ndpi_workflow * workflow, struct ndpi_fl memcpy(&flow->stun.other_address, &flow->ndpi_flow->stun.other_address, sizeof(ndpi_address_port)); flow->multimedia_flow_type = flow->ndpi_flow->flow_multimedia_type; - + /* HTTP metadata are "global" not in `flow->ndpi_flow->protos` union; for example, we can have HTTP/BitTorrent and in that case we want to export also HTTP attributes */ if(is_ndpi_proto(flow, NDPI_PROTOCOL_HTTP) @@ -1358,18 +1380,21 @@ void process_ndpi_collected_info(struct ndpi_workflow * workflow, struct ndpi_fl LOG(NDPI_LOG_ERROR, "flow2json failed\n"); return; } - + ndpi_serialize_string_uint32(&flow->ndpi_flow_serializer, "detection_completed", flow->detection_completed); ndpi_serialize_string_uint32(&flow->ndpi_flow_serializer, "check_extra_packets", flow->check_extra_packets); } - if(flow->detection_completed && (!flow->check_extra_packets)) { + if(flow->detection_completed && (!flow->check_extra_packets)) { flow->flow_payload = flow->ndpi_flow->flow_payload, flow->flow_payload_len = flow->ndpi_flow->flow_payload_len; flow->ndpi_flow->flow_payload = NULL; /* We'll free the memory */ if(workflow->flow_callback != NULL) workflow->flow_callback(workflow, flow, workflow->flow_callback_userdata); + if(fingerprint_fp) + dump_flow_fingerprint(workflow, flow); + ndpi_free_flow_info_half(flow); } } @@ -1693,7 +1718,7 @@ static struct ndpi_proto packet_processing(struct ndpi_workflow * workflow, } malloc_size_stats = 0; } - + #if 0 if(flow->risk != 0) { FILE *r = fopen("/tmp/e", "a"); @@ -1746,7 +1771,7 @@ static bool ndpi_is_valid_vxlan(const struct pcap_pkthdr *header, const u_char * struct ndpi_udphdr *udp = (struct ndpi_udphdr *)&packet[ip_offset+ip_len]; u_int offset = ip_offset + ip_len + sizeof(struct ndpi_udphdr); /** - * rfc-7348 + * rfc-7348 * VXLAN Header: This is an 8-byte field that has: - Flags (8 bits): where the I flag MUST be set to 1 for a valid @@ -1784,8 +1809,8 @@ static inline u_int ndpi_skip_vxlan(u_int16_t ip_offset, u_int16_t ip_len){ return ip_offset + ip_len + sizeof(struct ndpi_udphdr) + sizeof(struct ndpi_vxlanhdr); } -static uint32_t ndpi_is_valid_gre_tunnel(const struct pcap_pkthdr *header, - const u_char *packet, const u_int16_t ip_offset, +static uint32_t ndpi_is_valid_gre_tunnel(const struct pcap_pkthdr *header, + const u_char *packet, const u_int16_t ip_offset, const u_int16_t ip_len) { if(header->caplen < ip_offset + ip_len + sizeof(struct ndpi_gre_basehdr)) return 0; /* Too short for GRE header*/ @@ -1829,7 +1854,7 @@ static uint32_t ndpi_is_valid_gre_tunnel(const struct pcap_pkthdr *header, return 0; if(NDPI_GRE_IS_STRICT(grehdr->flags)) return 0; - if(grehdr->protocol != NDPI_GRE_PROTO_PPP) + if(grehdr->protocol != NDPI_GRE_PROTO_PPP) return 0; /*key field*/ if(header->caplen < offset + 4) @@ -2364,11 +2389,11 @@ struct ndpi_proto ndpi_workflow_process_packet(struct ndpi_workflow * workflow, if((offset = ndpi_is_valid_gre_tunnel(header, packet, ip_offset, ip_len))) { tunnel_type = ndpi_gre_tunnel; struct ndpi_gre_basehdr *grehdr = (struct ndpi_gre_basehdr*)&packet[ip_offset + ip_len]; - if(grehdr->protocol == ntohs(ETH_P_IP) || grehdr->protocol == ntohs(ETH_P_IPV6)) { + if(grehdr->protocol == ntohs(ETH_P_IP) || grehdr->protocol == ntohs(ETH_P_IPV6)) { ip_offset = offset; - goto iph_check; + goto iph_check; } else if(grehdr->protocol == NDPI_GRE_PROTO_PPP) { // ppp protocol - ip_offset = offset + NDPI_PPP_HDRLEN; + ip_offset = offset + NDPI_PPP_HDRLEN; goto iph_check; } else { eth_offset = offset; |