diff options
-rw-r--r-- | example/ndpiReader.c | 10 | ||||
-rw-r--r-- | example/ndpi_util.c | 85 | ||||
-rw-r--r-- | wireshark/README.md | 20 | ||||
-rw-r--r-- | wireshark/ndpi.lua | 47 |
4 files changed, 114 insertions, 48 deletions
diff --git a/example/ndpiReader.c b/example/ndpiReader.c index 2b02093cb..254934ba9 100644 --- a/example/ndpiReader.c +++ b/example/ndpiReader.c @@ -93,6 +93,7 @@ struct port_stats *srcStats = NULL, *dstStats = NULL; struct ndpi_packet_trailer { u_int32_t magic; /* 0x19682017 */ u_int16_t master_protocol /* e.g. HTTP */, app_protocol /* e.g. FaceBook */; + char name[16]; }; static pcap_dumper_t *extcap_dumper = NULL; @@ -249,14 +250,12 @@ void extcap_config() { int i, argidx = 0; struct ndpi_detection_module_struct *ndpi_mod; -#if 1 + /* -i <interface> */ printf("arg {number=%u}{call=-i}{display=Capture Interface Name}{type=string}" "{tooltip=The interface name}\n", argidx++); -#else printf("arg {number=%u}{call=-i}{display=Pcap File to Analize}{type=fileselect}" "{tooltip=The pcap file to analyze (if the interface is unspecified)}\n", argidx++); -#endif printf("arg {number=%u}{call=-9}{display=nDPI Protocol}{type=selector}" "{tooltip=nDPI Protocol to be filtered}\n", argidx); @@ -1494,8 +1493,9 @@ static void pcap_packet_callback_checked(u_char *args, struct ndpi_packet_trailer *trailer = (struct ndpi_packet_trailer*)&extcap_buf[h->caplen]; memcpy(extcap_buf, packet, h->caplen); - trailer->magic = 0x19682017; - trailer->master_protocol = p.master_protocol, trailer->app_protocol = p.app_protocol; + trailer->magic = htonl(0x19680924); + trailer->master_protocol = htons(p.master_protocol), trailer->app_protocol = htons(p.app_protocol); + ndpi_protocol2name(ndpi_thread_info[thread_id].workflow->ndpi_struct, p, trailer->name, sizeof(trailer->name)); crc = (uint32_t*)&extcap_buf[h->caplen+sizeof(struct ndpi_packet_trailer)]; *crc = 0; ethernet_crc32((const void*)extcap_buf, h->caplen+sizeof(struct ndpi_packet_trailer), crc); diff --git a/example/ndpi_util.c b/example/ndpi_util.c index d6be479a0..941e7f88d 100644 --- a/example/ndpi_util.c +++ b/example/ndpi_util.c @@ -260,7 +260,7 @@ static struct ndpi_flow_info *get_ndpi_flow_info(struct ndpi_workflow * workflow if(iph->protocol == IPPROTO_TCP && l4_packet_len >= 20) { u_int tcp_len; - // tcp + // tcp workflow->stats.tcp_count++; *tcph = (struct ndpi_tcphdr *)l4; *sport = ntohs((*tcph)->source), *dport = ntohs((*tcph)->dest); @@ -288,7 +288,7 @@ static struct ndpi_flow_info *get_ndpi_flow_info(struct ndpi_workflow * workflow *payload_len = ndpi_max(0, l4_packet_len-4*(*tcph)->doff); } else if(iph->protocol == IPPROTO_UDP && l4_packet_len >= 8) { // udp - + workflow->stats.udp_count++; *udph = (struct ndpi_udphdr *)l4; *sport = ntohs((*udph)->source), *dport = ntohs((*udph)->dest); @@ -350,7 +350,7 @@ static struct ndpi_flow_info *get_ndpi_flow_info(struct ndpi_workflow * workflow newflow->lower_port = lower_port, newflow->upper_port = upper_port; newflow->ip_version = version; newflow->src_to_dst_direction = *src_to_dst_direction; - + if(version == IPVERSION) { 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)); @@ -442,19 +442,19 @@ static struct ndpi_flow_info *get_ndpi_flow_info6(struct ndpi_workflow * workflo void process_ndpi_collected_info(struct ndpi_workflow * workflow, struct ndpi_flow_info *flow) { if(!flow->ndpi_flow) return; - - snprintf(flow->host_server_name, sizeof(flow->host_server_name), "%s", + + snprintf(flow->host_server_name, sizeof(flow->host_server_name), "%s", flow->ndpi_flow->host_server_name); /* BITTORRENT */ if(flow->detected_protocol.app_protocol == NDPI_PROTOCOL_BITTORRENT) { int i, j, n = 0; - + for(i=0, j = 0; j < sizeof(flow->bittorent_hash)-1; 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'; } /* MDNS */ @@ -545,7 +545,7 @@ static struct ndpi_proto packet_processing(struct ndpi_workflow * workflow, flow->last_seen = time; } else { // flow is NULL workflow->stats.total_discarded_bytes++; - return (nproto); + return(nproto); } /* Protocol already detected */ @@ -558,17 +558,16 @@ static struct ndpi_proto packet_processing(struct ndpi_workflow * workflow, if((flow->detected_protocol.app_protocol != NDPI_PROTOCOL_UNKNOWN) || ((proto == IPPROTO_UDP) && (flow->packets > 8)) || ((proto == IPPROTO_TCP) && (flow->packets > 10))) { - /* New protocol detected or give up */ + /* New protocol detected or give up */ flow->detection_completed = 1; - } - if(flow->detection_completed) { + process_ndpi_collected_info(workflow, flow); + if(flow->detected_protocol.app_protocol == NDPI_PROTOCOL_UNKNOWN) flow->detected_protocol = ndpi_detection_giveup(workflow->ndpi_struct, flow->ndpi_flow); - } + } - process_ndpi_collected_info(workflow, flow); return(flow->detected_protocol); } @@ -602,7 +601,7 @@ struct ndpi_proto ndpi_workflow_process_packet (struct ndpi_workflow * workflow, struct ndpi_ipv6hdr *iph6; struct ndpi_proto nproto = { NDPI_PROTOCOL_UNKNOWN, NDPI_PROTOCOL_UNKNOWN }; - + /* lengths and offsets */ u_int16_t eth_offset = 0; u_int16_t radio_len; @@ -916,11 +915,11 @@ struct ndpi_proto ndpi_workflow_process_packet (struct ndpi_workflow * workflow, /* ********************************************************** */ static uint32_t crc32_for_byte(uint32_t r) { - int j; - - for(j = 0; j < 8; ++j) - r = (r & 1? 0: (uint32_t)0xEDB88320L) ^ r >> 1; - return r ^ (uint32_t)0xFF000000L; + int j; + + for(j = 0; j < 8; ++j) + r = (r & 1? 0: (uint32_t)0xEDB88320L) ^ r >> 1; + return r ^ (uint32_t)0xFF000000L; } /* Any unsigned integer type with at least 32 bits may be used as @@ -929,31 +928,31 @@ static uint32_t crc32_for_byte(uint32_t r) { typedef unsigned long accum_t; static void init_tables(uint32_t* table, uint32_t* wtable) { - size_t i, k, w, j; - - for(i = 0; i < 0x100; ++i) - table[i] = crc32_for_byte(i); - for(k = 0; k < sizeof(accum_t); ++k) - for(i = 0; i < 0x100; ++i) { - for(j = w = 0; j < sizeof(accum_t); ++j) - w = table[(uint8_t)(j == k? w ^ i: w)] ^ w >> 8; - wtable[(k << 8) + i] = w ^ (k? wtable[0]: 0); - } + size_t i, k, w, j; + + for(i = 0; i < 0x100; ++i) + table[i] = crc32_for_byte(i); + for(k = 0; k < sizeof(accum_t); ++k) + for(i = 0; i < 0x100; ++i) { + for(j = w = 0; j < sizeof(accum_t); ++j) + w = table[(uint8_t)(j == k? w ^ i: w)] ^ w >> 8; + wtable[(k << 8) + i] = w ^ (k? wtable[0]: 0); + } } void ethernet_crc32(const void* data, size_t n_bytes, uint32_t* crc) { - static uint32_t table[0x100], wtable[0x100*sizeof(accum_t)]; - size_t n_accum = n_bytes/sizeof(accum_t); - size_t i, k, j; - - if(!*table) - init_tables(table, wtable); - for(i = 0; i < n_accum; ++i) { - accum_t a = *crc ^ ((accum_t*)data)[i]; - for(j = *crc = 0; j < sizeof(accum_t); ++j) - *crc ^= wtable[(j << 8) + (uint8_t)(a >> 8*j)]; - } - - for(i = n_accum*sizeof(accum_t); i < n_bytes; ++i) - *crc = table[(uint8_t)*crc ^ ((uint8_t*)data)[i]] ^ *crc >> 8; + static uint32_t table[0x100], wtable[0x100*sizeof(accum_t)]; + size_t n_accum = n_bytes/sizeof(accum_t); + size_t i, k, j; + + if(!*table) + init_tables(table, wtable); + for(i = 0; i < n_accum; ++i) { + accum_t a = *crc ^ ((accum_t*)data)[i]; + for(j = *crc = 0; j < sizeof(accum_t); ++j) + *crc ^= wtable[(j << 8) + (uint8_t)(a >> 8*j)]; + } + + for(i = n_accum*sizeof(accum_t); i < n_bytes; ++i) + *crc = table[(uint8_t)*crc ^ ((uint8_t*)data)[i]] ^ *crc >> 8; } diff --git a/wireshark/README.md b/wireshark/README.md new file mode 100644 index 000000000..1811c663e --- /dev/null +++ b/wireshark/README.md @@ -0,0 +1,20 @@ +# nDPI Wireshark Plugin + +## Introduction + +nDPI can provide Wireshark protocol dissection to complement internal protocol decoding. In order to do this, the ndpiReader application is used to provide Wireshark nDPI protocol dissection, and a Wireshark plugin interprets nDPI information. + +## Installation + +- Copy the ndpiReader application (it is located under nDPI/example) to the Extcap path. See Wireshark -> About menu for identifying the extcap directory. Under OSX it is usually /Applications/Wireshark.app/Contents/MacOS/extcap +- Copy the ndpi.lua plugin under ~/.wireshark/plugins (or in the global Wireshark plugins directory) + +## Usage + +At Wireshark startup you will find a new extcap interface named "nDPI interface". Select that interface and specify an interface name (for live capture) or a pcap file path (for reading packets from a pcap file). You can choose a nDPI protocol list from the dropdown menu in case you want Wireshark to dissect only protocols of the specified nDPI application protocol. + +During capture the ndpiReader plugin will pass Wireshark the nDPI protocol information adding an ethernet packet trailer that contains nDPI information. The lua plugin interprets this information and it displays it in the Wireshark GUI. + +## nDPI Packet Filtering + +As nDPI is natively integrated into Wireshark, you can filter packets using the usual filtering mechanism. Example use "ndpi.protocol.name==BitTorrent" to filter all BitTorrent traffic. diff --git a/wireshark/ndpi.lua b/wireshark/ndpi.lua new file mode 100644 index 000000000..2065d2335 --- /dev/null +++ b/wireshark/ndpi.lua @@ -0,0 +1,47 @@ +-- +-- (C) 2017 - ntop.org +-- +-- This plugin is part of nDPI (https://github.com/ntop/nDPI) +-- +-- +local ndpi_proto = Proto("ndpi", "nDPI", "nDPI Protocol Interpreter") + +ndpi_proto.fields = {} +local fds = ndpi_proto.fields + +fds.network_protocol = ProtoField.new("nDPI Network Protocol", "ndpi.protocol.network", ftypes.UINT8, nil, base.DEC) +fds.application_protocol = ProtoField.new("nDPI Application Protocol", "ndpi.protocol.application", ftypes.UINT8, nil, base.DEC) +fds.name = ProtoField.new("nDPI Protocol Name", "ndpi.protocol.name", ftypes.STRING) + +local f_eth_trailer = Field.new("eth.trailer") + +-- ############################################### + +-- the dissector function callback +function ndpi_proto.dissector(tvb, pinfo, tree) + local pktlen = tvb:len() + local eth_trailer = f_eth_trailer() + local magic = tostring(tvb(pktlen-28,4)) + + if(magic == "19680924") then + local ndpi_subtree = tree:add(ndpi_proto, tvb(), "nDPI Protocol") + local network_protocol = tvb(pktlen-24,2) + local application_protocol = tvb(pktlen-22,2) + local name = tvb(pktlen-20,16) + local name_str = name:string(ENC_UTF_8) + + ndpi_subtree:add(fds.network_protocol, network_protocol) + ndpi_subtree:add(fds.application_protocol, application_protocol) + ndpi_subtree:add(fds.name, name) + + local pname = ""..application_protocol + if(pname ~= "0000") then + -- Set protocol name in the wireshark protocol column (if not Unknown) + pinfo.cols.protocol = name_str + end + end +end + +register_postdissector(ndpi_proto) + +-- ############################################### |