diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/include/ndpi_util.h | 150 | ||||
-rw-r--r-- | src/lib/Makefile.am | 1 | ||||
-rw-r--r-- | src/lib/ndpi_util.c | 841 |
3 files changed, 0 insertions, 992 deletions
diff --git a/src/include/ndpi_util.h b/src/include/ndpi_util.h deleted file mode 100644 index 44f7be03d..000000000 --- a/src/include/ndpi_util.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - * ndpi_util.h - * - * Copyright (C) 2011-15 - ntop.org - * Copyright (C) 2009-11 - ipoque GmbH - * - * This file is part of nDPI, an open source deep packet inspection - * library based on the OpenDPI and PACE technology by ipoque GmbH - * - * nDPI is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * nDPI is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with nDPI. If not, see <http://www.gnu.org/licenses/>. - * - */ - -/** - * This module contains routines to help setup a simple nDPI program. - * - * If you concern about performance or have to integrate nDPI in your - * application, you could need to reimplement them yourself. - * - * WARNING: this API is unstable! Use it at your own risk! - */ - -#ifndef __NDPI_UTIL_H__ -#define __NDPI_UTIL_H__ - -#include <pcap.h> - -// flow tracking -typedef struct ndpi_flow_info { - u_int32_t lower_ip; - u_int32_t upper_ip; - u_int16_t lower_port; - u_int16_t upper_port; - u_int8_t detection_completed, protocol; - u_int16_t vlan_id; - struct ndpi_flow_struct *ndpi_flow; - char lower_name[48], upper_name[48]; - u_int8_t ip_version; - u_int64_t last_seen; - u_int64_t bytes; - u_int32_t packets; - - // result only, not used for flow identification - ndpi_protocol detected_protocol; - - char host_server_name[192]; - char bittorent_hash[41]; - - struct { - char client_certificate[48], server_certificate[48]; - } ssl; - - void *src_id, *dst_id; -} ndpi_flow_info_t; - -typedef struct ndpi_stats { - u_int32_t guessed_flow_protocols; - u_int64_t raw_packet_count; - u_int64_t ip_packet_count; - u_int64_t total_wire_bytes, total_ip_bytes, total_discarded_bytes; - u_int64_t protocol_counter[NDPI_MAX_SUPPORTED_PROTOCOLS + NDPI_MAX_NUM_CUSTOM_PROTOCOLS + 1]; - u_int64_t protocol_counter_bytes[NDPI_MAX_SUPPORTED_PROTOCOLS + NDPI_MAX_NUM_CUSTOM_PROTOCOLS + 1]; - u_int32_t protocol_flows[NDPI_MAX_SUPPORTED_PROTOCOLS + NDPI_MAX_NUM_CUSTOM_PROTOCOLS + 1]; - u_int32_t ndpi_flow_count; - u_int64_t tcp_count, udp_count; - u_int64_t mpls_count, pppoe_count, vlan_count, fragmented_count; - u_int64_t packet_len[6]; - u_int16_t max_packet_len; -} ndpi_stats_t; - -typedef struct ndpi_workflow_prefs { - u_int8_t decode_tunnels; - u_int8_t quiet_mode; - u_int32_t num_roots; - u_int32_t max_ndpi_flows; - u_int32_t detection_tick_resolution; -} ndpi_workflow_prefs_t; - -struct ndpi_workflow; -/** workflow, flow, user data */ -typedef void (*ndpi_workflow_callback_ptr) (struct ndpi_workflow *, struct ndpi_flow_info *, void *); - -typedef struct ndpi_workflow { - u_int64_t last_time; - - struct ndpi_workflow_prefs prefs; - struct ndpi_stats stats; - - ndpi_workflow_callback_ptr __flow_detected_callback; - void * __flow_detected_udata; - ndpi_workflow_callback_ptr __flow_giveup_callback; - void * __flow_giveup_udata; - - /* outside referencies */ - pcap_t *pcap_handle; - - /* allocated by prefs */ - void **ndpi_flows_root; - struct ndpi_detection_module_struct *ndpi_struct; -} ndpi_workflow_t; - -/* TODO: remove wrappers parameters and use ndpi global, when their initialization will be fixed... */ -struct ndpi_workflow * ndpi_workflow_init(const struct ndpi_workflow_prefs * prefs, - pcap_t * pcap_handle, - void * (*malloc_wrapper)(size_t), - void (*free_wrapper)(void*), - ndpi_debug_function_ptr ndpi_debug_printf); - -void ndpi_workflow_free(struct ndpi_workflow * workflow); - -/** Free flow_info ndpi support structures but not the flow_info itself - * - * TODO remove! Half freeing things is bad! - */ -void ndpi_free_flow_info_half(struct ndpi_flow_info *flow); - -/** Process a @packet and update the @workflow. */ -void ndpi_workflow_process_packet (struct ndpi_workflow * workflow, - const struct pcap_pkthdr *header, - const u_char *packet); - -/* flow callbacks: ndpi_flow_info will be freed right after */ -static inline void ndpi_workflow_set_flow_detected_callback(struct ndpi_workflow * workflow, - ndpi_workflow_callback_ptr callback, - void * udata) { - workflow->__flow_detected_callback = callback; - workflow->__flow_detected_udata = udata; -} - -static inline void ndpi_workflow_set_flow_giveup_callback(struct ndpi_workflow * workflow, - ndpi_workflow_callback_ptr callback, - void * udata) { - workflow->__flow_giveup_callback = callback; - workflow->__flow_giveup_udata = udata; -} - -int ndpi_workflow_node_cmp(const void *a, const void *b); - -#endif diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 312cdc88c..d83fdd5c0 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -16,7 +16,6 @@ libndpi_la_include_HEADERS = ../include/ndpi_api.h \ libndpi_la_SOURCES = ndpi_content_match.c.inc \ ndpi_main.c \ - ndpi_util.c \ protocols/afp.c \ protocols/aimini.c \ protocols/applejuice.c \ diff --git a/src/lib/ndpi_util.c b/src/lib/ndpi_util.c deleted file mode 100644 index 36897cf2d..000000000 --- a/src/lib/ndpi_util.c +++ /dev/null @@ -1,841 +0,0 @@ -/* - * ndpi_util.c - * - * Copyright (C) 2011-15 - ntop.org - * Copyright (C) 2009-11 - ipoque GmbH - * - * This file is part of nDPI, an open source deep packet inspection - * library based on the OpenDPI and PACE technology by ipoque GmbH - * - * nDPI is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * nDPI is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with nDPI. If not, see <http://www.gnu.org/licenses/>. - * - */ - -#include <stdlib.h> - -#ifdef WIN32 -#include <winsock2.h> /* winsock.h is included automatically */ -#include <process.h> -#include <io.h> -#else -#include <unistd.h> -#include <netinet/in.h> -#endif - -#ifndef ETH_P_IP -#define ETH_P_IP 0x0800 /* IPv4 */ -#endif - -#ifndef ETH_P_IPv6 -#define ETH_P_IPV6 0x86dd /* IPv6 */ -#endif - -#define SLARP 0x8035 /* Cisco Slarp */ -#define CISCO_D_PROTO 0x2000 /* Cisco Discovery Protocol */ - -#define VLAN 0x8100 -#define MPLS_UNI 0x8847 -#define MPLS_MULTI 0x8848 -#define PPPoE 0x8864 -#define SNAP 0xaa - -/* mask for FCF */ -#define WIFI_DATA 0x2 /* 0000 0010 */ -#define FCF_TYPE(fc) (((fc) >> 2) & 0x3) /* 0000 0011 = 0x3 */ -#define FCF_SUBTYPE(fc) (((fc) >> 4) & 0xF) /* 0000 1111 = 0xF */ -#define FCF_TO_DS(fc) ((fc) & 0x0100) -#define FCF_FROM_DS(fc) ((fc) & 0x0200) - -/* mask for Bad FCF presence */ -#define BAD_FCS 0x50 /* 0101 0000 */ - -#define GTP_U_V1_PORT 2152 -#define TZSP_PORT 37008 - -#define SIZEOF_ID_STRUCT (sizeof(struct ndpi_id_struct)) -#define SIZEOF_FLOW_STRUCT (sizeof(struct ndpi_flow_struct)) - -#include "ndpi_main.h" -#include "ndpi_util.h" - -/* ***************************************************** */ - -void ndpi_free_flow_info_half(struct ndpi_flow_info *flow) { - if(flow->ndpi_flow) { ndpi_free_flow(flow->ndpi_flow); flow->ndpi_flow = NULL; } - if(flow->src_id) { ndpi_free(flow->src_id); flow->src_id = NULL; } - if(flow->dst_id) { ndpi_free(flow->dst_id); flow->dst_id = NULL; } - -} - -/* ***************************************************** */ - -static const u_int8_t nDPI_traceLevel = 0; - -/* ***************************************************** */ -/* TODO remove in future... */ -static void (*removeme_free_wrapper)(void*); - -struct ndpi_workflow * ndpi_workflow_init(const struct ndpi_workflow_prefs * prefs, - pcap_t * pcap_handle, - void * (*malloc_wrapper)(size_t), - void (*free_wrapper)(void*), - ndpi_debug_function_ptr ndpi_debug_printf) { - - /* TODO: just needed here to init ndpi malloc wrapper */ - struct ndpi_detection_module_struct * module = ndpi_init_detection_module( - prefs->detection_tick_resolution, malloc_wrapper, free_wrapper, ndpi_debug_printf); - - struct ndpi_workflow * workflow = ndpi_calloc(1, sizeof(struct ndpi_workflow)); - - removeme_free_wrapper = free_wrapper; - - workflow->pcap_handle = pcap_handle; - workflow->prefs = *prefs; - workflow->ndpi_struct = module; - - if(workflow->ndpi_struct == NULL) { - NDPI_LOG(0, NULL, NDPI_LOG_ERROR, "global structure initialization failed\n"); - exit(-1); - } - - workflow->ndpi_flows_root = ndpi_calloc(workflow->prefs.num_roots, sizeof(void *)); - return workflow; -} - -/* ***************************************************** */ - -static void ndpi_flow_info_freer(void *node) { - struct ndpi_flow_info *flow = (struct ndpi_flow_info*)node; - - ndpi_free_flow_info_half(flow); - ndpi_free(flow); -} - -/* ***************************************************** */ - -void ndpi_workflow_free(struct ndpi_workflow * workflow) { - int i; - - for(i=0; i<workflow->prefs.num_roots; i++) - ndpi_tdestroy(workflow->ndpi_flows_root[i], ndpi_flow_info_freer); - - ndpi_exit_detection_module(workflow->ndpi_struct, removeme_free_wrapper); - free(workflow->ndpi_flows_root); - free(workflow); -} - -/* ***************************************************** */ - -int ndpi_workflow_node_cmp(const void *a, const void *b) { - struct ndpi_flow_info *fa = (struct ndpi_flow_info*)a; - struct ndpi_flow_info *fb = (struct ndpi_flow_info*)b; - - if(fa->vlan_id < fb->vlan_id ) return(-1); else { if(fa->vlan_id > fb->vlan_id ) return(1); } - if(fa->lower_ip < fb->lower_ip ) return(-1); else { if(fa->lower_ip > fb->lower_ip ) return(1); } - if(fa->lower_port < fb->lower_port) return(-1); else { if(fa->lower_port > fb->lower_port) return(1); } - if(fa->upper_ip < fb->upper_ip ) return(-1); else { if(fa->upper_ip > fb->upper_ip ) return(1); } - if(fa->upper_port < fb->upper_port) return(-1); else { if(fa->upper_port > fb->upper_port) return(1); } - if(fa->protocol < fb->protocol ) return(-1); else { if(fa->protocol > fb->protocol ) return(1); } - - return(0); -} - -/* ***************************************************** */ - -static struct ndpi_flow_info *get_ndpi_flow_info(struct ndpi_workflow * workflow, - const u_int8_t version, - u_int16_t vlan_id, - const struct ndpi_iphdr *iph, - const struct ndpi_ipv6hdr *iph6, - u_int16_t ip_offset, - u_int16_t ipsize, - u_int16_t l4_packet_len, - struct ndpi_tcphdr **tcph, - struct ndpi_udphdr **udph, - u_int16_t *sport, u_int16_t *dport, - struct ndpi_id_struct **src, - struct ndpi_id_struct **dst, - u_int8_t *proto, - u_int8_t **payload, - u_int16_t *payload_len, - u_int8_t *src_to_dst_direction) { - u_int32_t idx, l4_offset; - u_int32_t lower_ip; - u_int32_t upper_ip; - u_int16_t lower_port; - u_int16_t upper_port; - struct ndpi_flow_info flow; - void *ret; - u_int8_t *l3, *l4; - - /* - Note: to keep things simple (ndpiReader is just a demo app) - we handle IPv6 a-la-IPv4. - */ - 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; - - l4_offset = iph->ihl * 4; - l3 = (u_int8_t*)iph; - } else { - l4_offset = sizeof(struct ndpi_ipv6hdr); - l3 = (u_int8_t*)iph6; - } - - if(l4_packet_len < 64) - workflow->stats.packet_len[0]++; - else if(l4_packet_len >= 64 && l4_packet_len < 128) - workflow->stats.packet_len[1]++; - else if(l4_packet_len >= 128 && l4_packet_len < 256) - workflow->stats.packet_len[2]++; - else if(l4_packet_len >= 256 && l4_packet_len < 1024) - workflow->stats.packet_len[3]++; - else if(l4_packet_len >= 1024 && l4_packet_len < 1500) - workflow->stats.packet_len[4]++; - else if(l4_packet_len >= 1500) - workflow->stats.packet_len[5]++; - - if(l4_packet_len > workflow->stats.max_packet_len) - workflow->stats.max_packet_len = l4_packet_len; - - 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 = ((u_int8_t *) l3 + l4_offset); - - if(iph->protocol == 6 && l4_packet_len >= 20) { - u_int tcp_len; - - workflow->stats.tcp_count++; - - // tcp - *tcph = (struct ndpi_tcphdr *)l4; - *sport = ntohs((*tcph)->source), *dport = ntohs((*tcph)->dest); - - if(iph->saddr < iph->daddr) { - lower_port = (*tcph)->source, upper_port = (*tcph)->dest; - *src_to_dst_direction = 1; - } else { - lower_port = (*tcph)->dest; - upper_port = (*tcph)->source; - - *src_to_dst_direction = 0; - if(iph->saddr == iph->daddr) { - if(lower_port > upper_port) { - u_int16_t p = lower_port; - - lower_port = upper_port; - upper_port = p; - } - } - } - - tcp_len = ndpi_min(4*(*tcph)->doff, l4_packet_len); - *payload = &l4[tcp_len]; - *payload_len = ndpi_max(0, l4_packet_len-4*(*tcph)->doff); - } else if(iph->protocol == 17 && l4_packet_len >= 8) { - // udp - workflow->stats.udp_count++; - - *udph = (struct ndpi_udphdr *)l4; - *sport = ntohs((*udph)->source), *dport = ntohs((*udph)->dest); - *payload = &l4[sizeof(struct ndpi_udphdr)]; - *payload_len = ndpi_max(0, l4_packet_len-sizeof(struct ndpi_udphdr)); - - if(iph->saddr < iph->daddr) { - lower_port = (*udph)->source, upper_port = (*udph)->dest; - *src_to_dst_direction = 1; - } else { - lower_port = (*udph)->dest, upper_port = (*udph)->source; - - *src_to_dst_direction = 0; - - if(iph->saddr == iph->daddr) { - if(lower_port > upper_port) { - u_int16_t p = lower_port; - - lower_port = upper_port; - upper_port = p; - } - } - } - - *sport = ntohs(lower_port), *dport = ntohs(upper_port); - } else { - // non tcp/udp protocols - lower_port = 0; - upper_port = 0; - } - - flow.protocol = iph->protocol, flow.vlan_id = vlan_id; - flow.lower_ip = lower_ip, flow.upper_ip = upper_ip; - flow.lower_port = lower_port, flow.upper_port = upper_port; - - if(0) - NDPI_LOG(0, workflow.ndpi_struct, NDPI_LOG_DEBUG, "[NDPI] [%u][%u:%u <-> %u:%u]\n", - iph->protocol, lower_ip, ntohs(lower_port), upper_ip, ntohs(upper_port)); - - idx = (vlan_id + lower_ip + upper_ip + iph->protocol + lower_port + upper_port) % workflow->prefs.num_roots; - ret = ndpi_tfind(&flow, &workflow->ndpi_flows_root[idx], ndpi_workflow_node_cmp); - - if(ret == NULL) { - if(workflow->stats.ndpi_flow_count == workflow->prefs.max_ndpi_flows) { - NDPI_LOG(0, workflow.ndpi_struct, NDPI_LOG_ERROR, "maximum flow count (%u) has been exceeded\n", workflow->prefs.max_ndpi_flows); - exit(-1); - } else { - struct ndpi_flow_info *newflow = (struct ndpi_flow_info*)malloc(sizeof(struct ndpi_flow_info)); - - if(newflow == NULL) { - NDPI_LOG(0, workflow.ndpi_struct, NDPI_LOG_ERROR, "[NDPI] %s(1): not enough memory\n", __FUNCTION__); - return(NULL); - } - - memset(newflow, 0, sizeof(struct ndpi_flow_info)); - newflow->protocol = iph->protocol, newflow->vlan_id = vlan_id; - newflow->lower_ip = lower_ip, newflow->upper_ip = upper_ip; - newflow->lower_port = lower_port, newflow->upper_port = upper_port; - newflow->ip_version = version; - - if(version == 4) { - inet_ntop(AF_INET, &lower_ip, newflow->lower_name, sizeof(newflow->lower_name)); - inet_ntop(AF_INET, &upper_ip, newflow->upper_name, sizeof(newflow->upper_name)); - } else { - inet_ntop(AF_INET6, &iph6->ip6_src, newflow->lower_name, sizeof(newflow->lower_name)); - inet_ntop(AF_INET6, &iph6->ip6_dst, newflow->upper_name, sizeof(newflow->upper_name)); - } - - if((newflow->ndpi_flow = ndpi_malloc(SIZEOF_FLOW_STRUCT)) == NULL) { - NDPI_LOG(0, workflow.ndpi_struct, NDPI_LOG_ERROR, "[NDPI] %s(2): not enough memory\n", __FUNCTION__); - free(newflow); - return(NULL); - } else - memset(newflow->ndpi_flow, 0, SIZEOF_FLOW_STRUCT); - - if((newflow->src_id = ndpi_malloc(SIZEOF_ID_STRUCT)) == NULL) { - NDPI_LOG(0, workflow.ndpi_struct, NDPI_LOG_ERROR, "[NDPI] %s(3): not enough memory\n", __FUNCTION__); - free(newflow); - return(NULL); - } else - memset(newflow->src_id, 0, SIZEOF_ID_STRUCT); - - if((newflow->dst_id = ndpi_malloc(SIZEOF_ID_STRUCT)) == NULL) { - NDPI_LOG(0, workflow.ndpi_struct, NDPI_LOG_ERROR, "[NDPI] %s(4): not enough memory\n", __FUNCTION__); - free(newflow); - return(NULL); - } else - memset(newflow->dst_id, 0, SIZEOF_ID_STRUCT); - - ndpi_tsearch(newflow, &workflow->ndpi_flows_root[idx], ndpi_workflow_node_cmp); /* Add */ - workflow->stats.ndpi_flow_count++; - - *src = newflow->src_id, *dst = newflow->dst_id; - - return newflow; - } - } else { - struct ndpi_flow_info *flow = *(struct ndpi_flow_info**)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_info *get_ndpi_flow_info6(struct ndpi_workflow * workflow, - u_int16_t vlan_id, - const struct ndpi_ipv6hdr *iph6, - u_int16_t ip_offset, - struct ndpi_tcphdr **tcph, - struct ndpi_udphdr **udph, - u_int16_t *sport, u_int16_t *dport, - struct ndpi_id_struct **src, - struct ndpi_id_struct **dst, - u_int8_t *proto, - u_int8_t **payload, - u_int16_t *payload_len, - u_int8_t *src_to_dst_direction) { - struct ndpi_iphdr iph; - - memset(&iph, 0, sizeof(iph)); - iph.version = 4; - iph.saddr = iph6->ip6_src.u6_addr.u6_addr32[2] + iph6->ip6_src.u6_addr.u6_addr32[3]; - iph.daddr = iph6->ip6_dst.u6_addr.u6_addr32[2] + iph6->ip6_dst.u6_addr.u6_addr32[3]; - iph.protocol = iph6->ip6_ctlun.ip6_un1.ip6_un1_nxt; - - if(iph.protocol == 0x3C /* IPv6 destination option */) { - u_int8_t *options = (u_int8_t*)iph6 + sizeof(const struct ndpi_ipv6hdr); - - iph.protocol = options[0]; - } - - return(get_ndpi_flow_info(workflow, 6, vlan_id, &iph, iph6, ip_offset, - sizeof(struct ndpi_ipv6hdr), - ntohs(iph6->ip6_ctlun.ip6_un1.ip6_un1_plen), - tcph, udph, sport, dport, - src, dst, proto, payload, payload_len, src_to_dst_direction)); -} - -/* ****************************************************** */ - -// ipsize = header->len - ip_offset ; rawsize = header->len -static unsigned int packet_processing(struct ndpi_workflow * workflow, - const u_int64_t time, - u_int16_t vlan_id, - const struct ndpi_iphdr *iph, - struct ndpi_ipv6hdr *iph6, - u_int16_t ip_offset, - u_int16_t ipsize, u_int16_t rawsize) { - struct ndpi_id_struct *src, *dst; - struct ndpi_flow_info *flow; - struct ndpi_flow_struct *ndpi_flow = NULL; - u_int8_t proto; - struct ndpi_tcphdr *tcph = NULL; - struct ndpi_udphdr *udph = NULL; - u_int16_t sport, dport, payload_len; - u_int8_t *payload; - u_int8_t src_to_dst_direction= 1; - - if(iph) - flow = get_ndpi_flow_info(workflow, 4, vlan_id, iph, NULL, - ip_offset, ipsize, - ntohs(iph->tot_len) - (iph->ihl * 4), - &tcph, &udph, &sport, &dport, - &src, &dst, &proto, - &payload, &payload_len, &src_to_dst_direction); - else - flow = get_ndpi_flow_info6(workflow, vlan_id, iph6, ip_offset, - &tcph, &udph, &sport, &dport, - &src, &dst, &proto, - &payload, &payload_len, &src_to_dst_direction); - - if(flow != NULL) { - workflow->stats.ip_packet_count++; - workflow->stats.total_wire_bytes += rawsize + 24 /* CRC etc */, workflow->stats.total_ip_bytes += rawsize; - ndpi_flow = flow->ndpi_flow; - flow->packets++, flow->bytes += rawsize; - flow->last_seen = time; - } else { - return(0); - } - - /* Protocol already detected */ - if(flow->detection_completed) return(0); - - flow->detected_protocol = ndpi_detection_process_packet(workflow->ndpi_struct, ndpi_flow, - iph ? (uint8_t *)iph : (uint8_t *)iph6, - ipsize, time, src, dst); - - if((flow->detected_protocol.protocol != NDPI_PROTOCOL_UNKNOWN) - || ((proto == IPPROTO_UDP) && (flow->packets > 8)) - || ((proto == IPPROTO_TCP) && (flow->packets > 10))) { - /* New protocol detected or give up */ - flow->detection_completed = 1; - - if((flow->detected_protocol.protocol == NDPI_PROTOCOL_UNKNOWN) && (ndpi_flow->num_stun_udp_pkts > 0)) - ndpi_set_detected_protocol(workflow->ndpi_struct, ndpi_flow, NDPI_PROTOCOL_STUN, NDPI_PROTOCOL_UNKNOWN); - - snprintf(flow->host_server_name, sizeof(flow->host_server_name), "%s", flow->ndpi_flow->host_server_name); - - if(flow->detected_protocol.protocol == NDPI_PROTOCOL_BITTORRENT) { - int i, j, n = 0; - - for(i=0, j = 0; i<20; i++) { - sprintf(&flow->bittorent_hash[j], "%02x", flow->ndpi_flow->bittorent_hash[i]); - j += 2, n += flow->ndpi_flow->bittorent_hash[i]; - } - - if(n == 0) flow->bittorent_hash[0] = '\0'; - } - - if((proto == IPPROTO_TCP) && (flow->detected_protocol.protocol != NDPI_PROTOCOL_DNS)) { - snprintf(flow->ssl.client_certificate, sizeof(flow->ssl.client_certificate), "%s", flow->ndpi_flow->protos.ssl.client_certificate); - snprintf(flow->ssl.server_certificate, sizeof(flow->ssl.server_certificate), "%s", flow->ndpi_flow->protos.ssl.server_certificate); - } - - if(flow->detected_protocol.protocol == NDPI_PROTOCOL_UNKNOWN) { - flow->detected_protocol = ndpi_detection_giveup(workflow->ndpi_struct, flow->ndpi_flow); - - if (workflow->__flow_giveup_callback != NULL) - workflow->__flow_giveup_callback(workflow, flow, workflow->__flow_giveup_udata); - } else { - if (workflow->__flow_detected_callback != NULL) - workflow->__flow_detected_callback(workflow, flow, workflow->__flow_detected_udata); - } - - ndpi_free_flow_info_half(flow); - } - - return 0; -} - -/* ****************************************************** */ -void ndpi_workflow_process_packet (struct ndpi_workflow * workflow, - const struct pcap_pkthdr *header, - const u_char *packet) { - /* - * Declare pointers to packet headers - */ - - /* --- Ethernet header --- */ - const struct ndpi_ethhdr *ethernet; - /* --- Ethernet II header --- */ - const struct ndpi_ethhdr *ethernet_2; - /* --- LLC header --- */ - const struct ndpi_llc_header *llc; - - /* --- Cisco HDLC header --- */ - const struct ndpi_chdlc *chdlc; - /* --- SLARP frame --- */ - struct ndpi_slarp *slarp; - /* --- CDP --- */ - struct ndpi_cdp *cdp; - - /* --- Radio Tap header --- */ - const struct ndpi_radiotap_header *radiotap; - /* --- Wifi header --- */ - const struct ndpi_wifi_header *wifi; - - /* --- MPLS header --- */ - struct ndpi_mpls_header *mpls; - - /** --- IP header --- **/ - struct ndpi_iphdr *iph; - /** --- IPv6 header --- **/ - struct ndpi_ipv6hdr *iph6; - - /* lengths and offsets */ - u_int16_t eth_offset = 0; - u_int16_t radio_len; - u_int16_t fc; - u_int16_t type; - int wifi_len; - int llc_off; - int pyld_eth_len = 0; - int check; - u_int32_t fcs; - u_int64_t time; - u_int16_t ip_offset, ip_len, ip6_offset; - u_int16_t frag_off = 0, vlan_id = 0; - u_int8_t proto = 0; - u_int32_t label; - - /* counters */ - u_int8_t malformed_pkts = 0, vlan_packet = 0; - u_int8_t slarp_pkts = 0, cdp_pkts = 0; - - /* Increment raw packet counter */ - workflow->stats.raw_packet_count++; - - /* setting time */ - time = ((uint64_t) header->ts.tv_sec) * workflow->prefs.detection_tick_resolution + - header->ts.tv_usec / (1000000 / workflow->prefs.detection_tick_resolution); - - /* safety check */ - if(workflow->last_time > time) { - /* printf("\nWARNING: timestamp bug in the pcap file (ts delta: %llu, repairing)\n", ndpi_thread_info[thread_id].last_time - time); */ - time = workflow->last_time; - } - /* update last time value */ - workflow->last_time = time; - - /*** check Data Link type ***/ - const int datalink_type = pcap_datalink(workflow->pcap_handle); - - datalink_check: - switch(datalink_type) { - case DLT_NULL : - if(ntohl(*((u_int32_t*)&packet[eth_offset])) == 2) - type = ETH_P_IP; - else - type = ETH_P_IPV6; - - ip_offset = 4 + eth_offset; - - /* Cisco PPP in HDLC-like framing - 50 */ - case DLT_PPP_SERIAL: - chdlc = (struct ndpi_chdlc *) &packet[eth_offset]; - ip_offset = sizeof(struct ndpi_chdlc); /* CHDLC_OFF = 4 */ - type = ntohs(chdlc->proto_code); - break; - - /* Cisco PPP with HDLC framing - 104 */ - case DLT_C_HDLC: - chdlc = (struct ndpi_chdlc *) &packet[eth_offset]; - ip_offset = sizeof(struct ndpi_chdlc); /* CHDLC_OFF = 4 */ - type = ntohs(chdlc->proto_code); - break; - - /* IEEE 802.3 Ethernet - 1 */ - case DLT_EN10MB : - ethernet = (struct ndpi_ethhdr *) &packet[eth_offset]; - ip_offset = sizeof(struct ndpi_ethhdr) + eth_offset; - check = ntohs(ethernet->h_proto); - - if(check <= 1500) - pyld_eth_len = check; - else if (check >= 1536) - type = check; - - if(pyld_eth_len != 0) { - /* check for LLC layer with SNAP extension */ - if(packet[ip_offset] == SNAP) { - llc = (struct ndpi_llc_header *)(&packet[ip_offset]); - type = llc->snap.proto_ID; - ip_offset += + 8; - } - } - break; - - /* Linux Cooked Capture - 113 */ - case DLT_LINUX_SLL : - type = (packet[eth_offset+14] << 8) + packet[eth_offset+15]; - ip_offset = 16 + eth_offset; - break; - - /* Radiotap link-layer - 127 */ - case DLT_IEEE802_11_RADIO : - radiotap = (struct ndpi_radiotap_header *) &packet[eth_offset]; - radio_len = radiotap->len; - - /* Check Bad FCS presence */ - if((radiotap->flags & BAD_FCS) == BAD_FCS) { - malformed_pkts += 1; - workflow->stats.total_discarded_bytes += header->len; - return; - } - - fcs = header->len - 4; - - /* Calculate 802.11 header length (variable) */ - wifi = (struct ndpi_wifi_header*)( packet + eth_offset + radio_len); - fc = wifi->fc; - - /* check wifi data presence */ - if(FCF_TYPE(fc) == WIFI_DATA) { - if((FCF_TO_DS(fc) && FCF_FROM_DS(fc) == 0x0) || - (FCF_TO_DS(fc) == 0x0 && FCF_FROM_DS(fc))) - wifi_len = 26; /* + 4 byte fcs */ - } else /* no data frames */ - break; - - /* Check ether_type from LLC */ - llc = (struct ndpi_llc_header*)(packet + eth_offset + wifi_len + radio_len); - if(llc->dsap == SNAP) - type = ntohs(llc->snap.proto_ID); - - /* Set IP header offset */ - ip_offset = wifi_len + radio_len + sizeof(struct ndpi_llc_header) + eth_offset; - break; - - case DLT_RAW: - ip_offset = eth_offset = 0; - break; - - default: - /* printf("Unknown datalink %d\n", datalink_type); */ - return; - } - - /* check ether type */ - if(type == VLAN) { - vlan_id = ((packet[ip_offset] << 8) + packet[ip_offset+1]) & 0xFFF; - type = (packet[ip_offset+2] << 8) + packet[ip_offset+3]; - ip_offset += 4; - vlan_packet = 1; - } else if(type == MPLS_UNI || type == MPLS_MULTI) { - mpls = (struct ndpi_mpls_header *) &packet[ip_offset]; - label = ntohl(mpls->label); - /* label = ntohl(*((u_int32_t*)&packet[ip_offset])); */ - workflow->stats.mpls_count++; - type = ETH_P_IP, ip_offset += 4; - - while((label & 0x100) != 0x100) { - ip_offset += 4; - label = ntohl(mpls->label); - } - } - else if(type == SLARP) { - slarp = (struct ndpi_slarp *) &packet[ip_offset]; - if(slarp->slarp_type == 0x02 || slarp->slarp_type == 0x00 || slarp->slarp_type == 0x01) { - /* TODO if info are needed */ - } - slarp_pkts++; - } - else if(type == CISCO_D_PROTO) { - cdp = (struct ndpi_cdp *) &packet[ip_offset]; - cdp_pkts++; - } - else if(type == PPPoE) { - workflow->stats.pppoe_count++; - type = ETH_P_IP; - ip_offset += 8; - } - - workflow->stats.vlan_count += vlan_packet; - - iph_check: - /* Check and set IP header size and total packet length */ - iph = (struct ndpi_iphdr *) &packet[ip_offset]; - - /* just work on Ethernet packets that contain IP */ - if(type == ETH_P_IP && header->caplen >= ip_offset) { - frag_off = ntohs(iph->frag_off); - - proto = iph->protocol; - if(header->caplen < header->len) { - static u_int8_t cap_warning_used = 0; - - if(cap_warning_used == 0) { - if(!workflow->prefs.quiet_mode) - NDPI_LOG(0, workflow.ndpi_struct, NDPI_LOG_DEBUG, "\n\nWARNING: packet capture size is smaller than packet size, DETECTION MIGHT NOT WORK CORRECTLY\n\n"); - cap_warning_used = 1; - } - } - } - - if(iph->version == 4) { - ip_len = ((u_short)iph->ihl * 4); - iph6 = NULL; - - if(iph->protocol == 41) { - ip_offset += ip_len; - goto iph_check; - } - - if((frag_off & 0x3FFF) != 0) { - static u_int8_t ipv4_frags_warning_used = 0; - workflow->stats.fragmented_count++; - - if(ipv4_frags_warning_used == 0) { - if(!workflow->prefs.quiet_mode) - NDPI_LOG(0, workflow.ndpi_struct, NDPI_LOG_DEBUG, "\n\nWARNING: IPv4 fragments are not handled by this demo (nDPI supports them)\n"); - ipv4_frags_warning_used = 1; - } - - workflow->stats.total_discarded_bytes += header->len; - return; - } - } else if(iph->version == 6) { - iph6 = (struct ndpi_ipv6hdr *)&packet[ip_offset]; - proto = iph6->ip6_ctlun.ip6_un1.ip6_un1_nxt; - ip_len = sizeof(struct ndpi_ipv6hdr); - - if(proto == 0x3C /* IPv6 destination option */) { - - u_int8_t *options = (u_int8_t*)&packet[ip_offset+ip_len]; - proto = options[0]; - ip_len += 8 * (options[1] + 1); - } - iph = NULL; - - } else { - static u_int8_t ipv4_warning_used = 0; - - v4_warning: - if(ipv4_warning_used == 0) { - if(!workflow->prefs.quiet_mode) - NDPI_LOG(0, workflow.ndpi_struct, NDPI_LOG_DEBUG, "\n\nWARNING: only IPv4/IPv6 packets are supported in this demo (nDPI supports both IPv4 and IPv6), all other packets will be discarded\n\n"); - ipv4_warning_used = 1; - } - workflow->stats.total_discarded_bytes += header->len; - return; - } - - if(workflow->prefs.decode_tunnels && (proto == IPPROTO_UDP)) { - struct ndpi_udphdr *udp = (struct ndpi_udphdr *)&packet[ip_offset+ip_len]; - u_int16_t sport = ntohs(udp->source), dport = ntohs(udp->dest); - - if((sport == GTP_U_V1_PORT) || (dport == GTP_U_V1_PORT)) { - /* Check if it's GTPv1 */ - u_int offset = ip_offset+ip_len+sizeof(struct ndpi_udphdr); - u_int8_t flags = packet[offset]; - u_int8_t message_type = packet[offset+1]; - - if((((flags & 0xE0) >> 5) == 1 /* GTPv1 */) && - (message_type == 0xFF /* T-PDU */)) { - - ip_offset = ip_offset+ip_len+sizeof(struct ndpi_udphdr)+8; /* GTPv1 header len */ - if(flags & 0x04) ip_offset += 1; /* next_ext_header is present */ - if(flags & 0x02) ip_offset += 4; /* sequence_number is present (it also includes next_ext_header and pdu_number) */ - if(flags & 0x01) ip_offset += 1; /* pdu_number is present */ - - iph = (struct ndpi_iphdr *) &packet[ip_offset]; - - if(iph->version != 4) { - // printf("WARNING: not good (packet_id=%u)!\n", (unsigned int)workflow->stats.raw_packet_count); - goto v4_warning; - } - } - } else if((sport == TZSP_PORT) || (dport == TZSP_PORT)) { - /* https://en.wikipedia.org/wiki/TZSP */ - u_int offset = ip_offset+ip_len+sizeof(struct ndpi_udphdr); - u_int8_t version = packet[offset]; - u_int8_t type = packet[offset+1]; - u_int16_t encapsulates = ntohs(*((u_int16_t*)&packet[offset+2])); - - if((version == 1) && (type == 0) && (encapsulates == 1)) { - u_int8_t stop = 0; - - offset += 4; - - while((!stop) && (offset < header->caplen)) { - u_int8_t tag_type = packet[offset]; - u_int8_t tag_len; - - switch(tag_type) { - case 0: /* PADDING Tag */ - tag_len = 1; - break; - case 1: /* END Tag */ - tag_len = 1, stop = 1; - break; - default: - tag_len = packet[offset+1]; - break; - } - - offset += tag_len; - - if(offset >= header->caplen) - return; /* Invalid packet */ - else { - eth_offset = offset; - goto datalink_check; - } - } - } - } - } - - /* process the packet */ - packet_processing(workflow, time, vlan_id, iph, iph6, - ip_offset, header->len - ip_offset, header->len); -} |