aboutsummaryrefslogtreecommitdiff
path: root/example/ndpiReader.c
diff options
context:
space:
mode:
Diffstat (limited to 'example/ndpiReader.c')
-rw-r--r--example/ndpiReader.c124
1 files changed, 121 insertions, 3 deletions
diff --git a/example/ndpiReader.c b/example/ndpiReader.c
index 32321aa94..e5ccc5648 100644
--- a/example/ndpiReader.c
+++ b/example/ndpiReader.c
@@ -82,7 +82,7 @@ static u_int8_t live_capture = 0;
static u_int8_t undetected_flows_deleted = 0;
/** User preferences **/
u_int8_t enable_protocol_guess = 1;
-u_int8_t verbose = 0, json_flag = 0;
+u_int8_t verbose = 0, json_flag = 0, enable_joy_stats = 0;
int nDPI_LogLevel = 0;
char *_debug_protocols = NULL;
static u_int8_t stats_flag = 0, bpf_filter_flag = 0;
@@ -225,6 +225,110 @@ FILE *trace = NULL;
*/
static void setupDetection(u_int16_t thread_id, pcap_t * pcap_handle);
+static void reduceBDbits(uint32_t *bd, unsigned int len) {
+ int mask = 0;
+ int shift = 0;
+ unsigned int i = 0;
+
+ for(i = 0; i < len; i++)
+ mask = mask | bd[i];
+
+ mask = mask >> 8;
+ for(i = 0; i < 24 && mask; i++) {
+ mask = mask >> 1;
+ if (mask == 0) {
+ shift = i+1;
+ break;
+ }
+ }
+
+ for(i = 0; i < len; i++)
+ bd[i] = bd[i] >> shift;
+}
+
+/**
+ * @brief Get flow byte distribution mean and variance
+ */
+static void
+flowGetBDMeanandVariance(struct ndpi_flow_info* flow) {
+ FILE *out = results_file ? results_file : stdout;
+
+ const uint32_t *array = NULL;
+ uint32_t tmp[256], i;
+ unsigned int num_bytes;
+ double mean = 0.0, variance = 0.0;
+
+ fflush(out);
+
+ /*
+ * Sum up the byte_count array for outbound and inbound flows,
+ * if this flow is bidirectional
+ */
+ if (!flow->bidirectional) {
+ array = flow->src2dst_byte_count;
+ num_bytes = flow->src2dst_l4_bytes;
+ for (i=0; i<256; i++) {
+ tmp[i] = flow->src2dst_byte_count[i];
+ }
+
+ if (flow->src2dst_num_bytes != 0) {
+ mean = flow->src2dst_bd_mean;
+ variance = flow->src2dst_bd_variance/(flow->src2dst_num_bytes - 1);
+ variance = sqrt(variance);
+
+ if (flow->src2dst_num_bytes == 1) {
+ variance = 0.0;
+ }
+ }
+ } else {
+ for (i=0; i<256; i++) {
+ tmp[i] = flow->src2dst_byte_count[i] + flow->dst2src_byte_count[i];
+ }
+ array = tmp;
+ num_bytes = flow->src2dst_l4_bytes + flow->dst2src_l4_bytes;
+
+ if (flow->src2dst_num_bytes + flow->dst2src_num_bytes != 0) {
+ mean = ((double)flow->src2dst_num_bytes)/((double)(flow->src2dst_num_bytes+flow->dst2src_num_bytes))*flow->src2dst_bd_mean +
+ ((double)flow->dst2src_num_bytes)/((double)(flow->dst2src_num_bytes+flow->src2dst_num_bytes))*flow->dst2src_bd_mean;
+
+ variance = ((double)flow->src2dst_num_bytes)/((double)(flow->src2dst_num_bytes+flow->dst2src_num_bytes))*flow->src2dst_bd_variance +
+ ((double)flow->dst2src_num_bytes)/((double)(flow->dst2src_num_bytes+flow->src2dst_num_bytes))*flow->dst2src_bd_variance;
+
+ variance = variance/((double)(flow->src2dst_num_bytes + flow->dst2src_num_bytes - 1));
+ variance = sqrt(variance);
+ if (flow->src2dst_num_bytes + flow->dst2src_num_bytes == 1) {
+ variance = 0.0;
+ }
+ }
+ }
+
+ if(enable_joy_stats) {
+ if(verbose > 1) {
+ reduceBDbits(tmp, 256);
+ array = tmp;
+
+ fprintf(out, " [byte_dist: ");
+ for(i = 0; i < 255; i++)
+ fprintf(out, "%u,", (unsigned char)array[i]);
+
+ fprintf(out, "%u]", (unsigned char)array[i]);
+ }
+
+ /* Output the mean */
+ if(num_bytes != 0) {
+ fprintf(out, "][byte_dist_mean: %f", mean);
+ fprintf(out, "][byte_dist_std: %f]", variance);
+ }
+
+ if(num_bytes != 0) {
+ double entropy = ndpi_flow_get_byte_count_entropy(array, num_bytes);
+
+ fprintf(out, "[entropy: %f]", entropy);
+ fprintf(out, "[total_entropy: %f]", entropy * num_bytes);
+ }
+ }
+}
+
/**
* @brief Print help instructions
*/
@@ -236,7 +340,7 @@ static void help(u_int long_help) {
"-i <file|device> "
#endif
"[-f <filter>][-s <duration>][-m <duration>]\n"
- " [-p <protos>][-l <loops> [-q][-d][-h][-e <len>][-t][-v <level>]\n"
+ " [-p <protos>][-l <loops> [-q][-d][-J][-h][-e <len>][-t][-v <level>]\n"
" [-n <threads>][-w <file>][-c <file>][-j <file>][-x <file>]\n\n"
"Usage:\n"
" -i <file.pcap|device> | Specify a pcap file/playlist to read packets from or a\n"
@@ -255,6 +359,8 @@ static void help(u_int long_help) {
" -d | Disable protocol guess and use only DPI\n"
" -e <len> | Min human readeable string match len. Default %u\n"
" -q | Quiet mode\n"
+ " -J | Display flow SPLT (sequence of packet length and time)\n"
+ " | and BD (byte distribution). See https://github.com/cisco/joy\n"
" -t | Dissect GTP/TZSP tunnels\n"
" -r | Print nDPI version and git revision\n"
" -c <path> | Load custom categories from the specified file\n"
@@ -327,6 +433,7 @@ static struct option longopts[] = {
{ "version", no_argument, NULL, 'V'},
{ "help", no_argument, NULL, 'h'},
{ "json", required_argument, NULL, 'j'},
+ { "joy", required_argument, NULL, 'J'},
{ "result-path", required_argument, NULL, 'w'},
{ "quiet", no_argument, NULL, 'q'},
@@ -477,7 +584,7 @@ static void parseOptions(int argc, char **argv) {
}
#endif
- while((opt = getopt_long(argc, argv, "e:c:df:g:i:hp:l:s:tv:V:n:j:rp:w:q0123:456:7:89:m:b:x:", longopts, &option_idx)) != EOF) {
+ while((opt = getopt_long(argc, argv, "e:c:df:g:i:hp:l:s:tv:V:n:j:Jrp:w:q0123:456:7:89:m:b:x:", longopts, &option_idx)) != EOF) {
#ifdef DEBUG_TRACE
if(trace) fprintf(trace, " #### -%c [%s] #### \n", opt, optarg ? optarg : "");
#endif
@@ -573,6 +680,10 @@ static void parseOptions(int argc, char **argv) {
help(1);
break;
+ case 'J':
+ enable_joy_stats = 1;
+ break;
+
case 'j':
#ifndef HAVE_JSON_C
printf("WARNING: this copy of ndpiReader has been compiled without json-c: JSON export disabled\n");
@@ -799,6 +910,13 @@ static void printFlow(u_int16_t id, struct ndpi_flow_info *flow, u_int16_t threa
if(flow->vlan_id > 0) fprintf(out, "[VLAN: %u]", flow->vlan_id);
+ if(enable_joy_stats) {
+ /* Print entropy values for monitored flows. */
+ flowGetBDMeanandVariance(flow);
+ fflush(out);
+ fprintf(out, "[score: %.4f]", flow->score);
+ }
+
if(flow->detected_protocol.master_protocol) {
char buf[64];