aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--example/ndpiReader.c5
-rw-r--r--src/include/Makefile.am2
-rw-r--r--src/include/ndpi_api.h6
-rw-r--r--src/include/ndpi_typedefs.h6
-rw-r--r--src/lib/ndpi_main.c48
-rw-r--r--src/lib/protocols/http.c19
-rw-r--r--src/lib/protocols/ookla.c17
-rw-r--r--src/lib/protocols/ssl.c4
-rw-r--r--src/lib/third_party/include/lruc.h55
-rw-r--r--src/lib/third_party/src/lruc.c294
10 files changed, 79 insertions, 377 deletions
diff --git a/example/ndpiReader.c b/example/ndpiReader.c
index 6c3dfeee8..8996ea1a5 100644
--- a/example/ndpiReader.c
+++ b/example/ndpiReader.c
@@ -761,6 +761,9 @@ static void printFlow(u_int16_t id, struct ndpi_flow_info *flow, u_int16_t threa
if((verbose != 1) && (verbose != 2))
return;
+ if(5222 == ntohs(flow->dst_port))
+ printf("************\n");
+
if(!json_flag) {
fprintf(out, "\t%u", id);
@@ -913,7 +916,7 @@ static void node_proto_guess_walker(const void *node, ndpi_VISIT which, int dept
struct ndpi_flow_info *flow = *(struct ndpi_flow_info **) node;
u_int16_t thread_id = *((u_int16_t *) user_data);
- if((which == ndpi_preorder) || (which == ndpi_leaf)) { /* Avoid walking the same node multiple times */
+ if((which == ndpi_preorder) || (which == ndpi_leaf)) { /* Avoid walking the same node multiple times */
if((!flow->detection_completed) && flow->ndpi_flow)
flow->detected_protocol = ndpi_detection_giveup(ndpi_thread_info[0].workflow->ndpi_struct, flow->ndpi_flow, enable_protocol_guess);
diff --git a/src/include/Makefile.am b/src/include/Makefile.am
index 6eeca93b4..47fcbd224 100644
--- a/src/include/Makefile.am
+++ b/src/include/Makefile.am
@@ -1,4 +1,4 @@
-library_includedir=$(includedir)/libndpi-@VERSION@/libndpi
+plibrary_includedir=$(includedir)/libndpi-@VERSION@/libndpi
library_include_HEADERS = ndpi_api.h \
ndpi_define.h \
diff --git a/src/include/ndpi_api.h b/src/include/ndpi_api.h
index e57f3a568..e09c91c8e 100644
--- a/src/include/ndpi_api.h
+++ b/src/include/ndpi_api.h
@@ -756,6 +756,12 @@ extern "C" {
u_int ndpi_get_ndpi_num_custom_protocols(struct ndpi_detection_module_struct *ndpi_mod);
u_int ndpi_get_ndpi_detection_module_size();
void ndpi_set_log_level(struct ndpi_detection_module_struct *ndpi_mod, u_int l);
+
+ /* LRU cache */
+ struct ndpi_lru_cache* ndpi_lru_cache_init(u_int32_t num_entries);
+ void ndpi_lru_free_cache(struct ndpi_lru_cache *c);
+ u_int8_t ndpi_lru_find_cache(struct ndpi_lru_cache *c, u_int32_t key, u_int8_t clean_key_when_found);
+ void ndpi_lru_add_to_cache(struct ndpi_lru_cache *c, u_int32_t key);
/**
* Add a string to match to an automata
diff --git a/src/include/ndpi_typedefs.h b/src/include/ndpi_typedefs.h
index 34d308e2e..cf1af8bc3 100644
--- a/src/include/ndpi_typedefs.h
+++ b/src/include/ndpi_typedefs.h
@@ -367,6 +367,10 @@ typedef enum {
HTTP_METHOD_CONNECT
} ndpi_http_method;
+struct ndpi_lru_cache {
+ u_int32_t num_entries, *entries;
+};
+
struct ndpi_id_struct {
/**
detected_protocol_bitmask:
@@ -997,7 +1001,7 @@ struct ndpi_detection_module_struct {
int bt_ann_len;
/* NDPI_PROTOCOL_OOKLA */
- void *ookla_cache;
+ struct ndpi_lru_cache *ookla_cache;
/* NDPI_PROTOCOL_TINC */
struct cache *tinc_cache;
diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c
index 863943c4a..594d521d3 100644
--- a/src/lib/ndpi_main.c
+++ b/src/lib/ndpi_main.c
@@ -30,7 +30,6 @@
#include <sys/types.h>
#include "ahocorasick.h"
#include "libcache.h"
-#include "lruc.h"
#define NDPI_CURRENT_PROTO NDPI_PROTOCOL_UNKNOWN
@@ -2433,7 +2432,7 @@ void ndpi_exit_detection_module(struct ndpi_detection_module_struct *ndpi_struct
cache_free((cache_t)(ndpi_struct->tinc_cache));
if(ndpi_struct->ookla_cache)
- lruc_free((lruc*)ndpi_struct->ookla_cache);
+ ndpi_lru_free_cache(ndpi_struct->ookla_cache);
if(ndpi_struct->protocols_ptree)
ndpi_Destroy_Patricia((patricia_tree_t*)ndpi_struct->protocols_ptree, free_ptree_data);
@@ -3995,6 +3994,9 @@ ndpi_protocol ndpi_detection_giveup(struct ndpi_detection_module_struct *ndpi_st
if(flow == NULL) return(ret);
+ if(flow->packet.tcp && (5222 == ntohs(flow->packet.tcp->dest)))
+ printf("%u - %u\n", ntohs(flow->packet.tcp->source), ntohs(flow->packet.tcp->dest));
+
/* TODO: add the remaining stage_XXXX protocols */
if(flow->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) {
u_int16_t guessed_protocol_id, guessed_host_protocol_id;
@@ -6171,6 +6173,48 @@ void ndpi_set_log_level(struct ndpi_detection_module_struct *ndpi_mod, u_int l)
/* ******************************************************************** */
+/* LRU cache */
+
+struct ndpi_lru_cache* ndpi_lru_cache_init(u_int32_t num_entries) {
+ struct ndpi_lru_cache *c = (struct ndpi_lru_cache*)malloc(sizeof(struct ndpi_lru_cache));
+
+ if(!c) return(NULL);
+
+ c->entries = (u_int32_t*)calloc(num_entries, sizeof(u_int32_t));
+
+ if(!c->entries) {
+ free(c);
+ return(NULL);
+ } else
+ c->num_entries = num_entries;
+
+ return(c);
+}
+
+void ndpi_lru_free_cache(struct ndpi_lru_cache *c) {
+ free(c->entries);
+ free(c);
+}
+
+
+u_int8_t ndpi_lru_find_cache(struct ndpi_lru_cache *c, u_int32_t key, u_int8_t clean_key_when_found) {
+ u_int32_t slot = key % c->num_entries;
+
+ if(c->entries[slot] == key) {
+ if(clean_key_when_found) c->entries[slot] = 0;
+ return(1);
+ } else
+ return(0);
+}
+
+void ndpi_lru_add_to_cache(struct ndpi_lru_cache *c, u_int32_t key) {
+ u_int32_t slot = key % c->num_entries;
+
+ c->entries[slot] = key;
+}
+
+/* ******************************************************************** */
+
/*
NOTE:
- Leave fields empty/zero when information is missing (e.g. with ICMP ports are zero)
diff --git a/src/lib/protocols/http.c b/src/lib/protocols/http.c
index 661e55732..16b122d06 100644
--- a/src/lib/protocols/http.c
+++ b/src/lib/protocols/http.c
@@ -26,7 +26,6 @@
#define NDPI_CURRENT_PROTO NDPI_PROTOCOL_HTTP
#include "ndpi_api.h"
-#include "lruc.h"
static void ndpi_int_http_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow,
@@ -642,19 +641,15 @@ static void ndpi_check_http_tcp(struct ndpi_detection_module_struct *ndpi_struct
ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_OOKLA, NDPI_PROTOCOL_UNKNOWN);
if(ndpi_struct->ookla_cache == NULL)
- ndpi_struct->ookla_cache = lruc_new(4*1024, 1024);
-
+ ndpi_struct->ookla_cache = ndpi_lru_cache_init(1024);
+
if(packet->iph != NULL && ndpi_struct->ookla_cache != NULL) {
- u_int8_t *dummy = (u_int8_t*)ndpi_malloc(sizeof(u_int8_t));
-
- if(dummy) {
- if(packet->tcp->source == htons(8080))
- lruc_set((lruc*)ndpi_struct->ookla_cache, (void*)&packet->iph->saddr, 4, dummy, 1);
- else
- lruc_set((lruc*)ndpi_struct->ookla_cache, (void*)&packet->iph->daddr, 4, dummy, 1);
- }
+ if(packet->tcp->source == htons(8080))
+ ndpi_lru_add_to_cache(ndpi_struct->ookla_cache, packet->iph->saddr);
+ else
+ ndpi_lru_add_to_cache(ndpi_struct->ookla_cache, packet->iph->daddr);
}
-
+
return;
}
diff --git a/src/lib/protocols/ookla.c b/src/lib/protocols/ookla.c
index 4d46dbf58..06d97e216 100644
--- a/src/lib/protocols/ookla.c
+++ b/src/lib/protocols/ookla.c
@@ -22,36 +22,32 @@
#define NDPI_CURRENT_PROTO NDPI_PROTOCOL_OOKLA
#include "ndpi_api.h"
-#include "lruc.h"
void ndpi_search_ookla(struct ndpi_detection_module_struct* ndpi_struct, struct ndpi_flow_struct* flow) {
-#if 0
struct ndpi_packet_struct* packet = &flow->packet;
u_int32_t addr = 0;
void *value;
-
+
NDPI_LOG_DBG(ndpi_struct, "Ookla detection\n");
-
+
if(packet->tcp->source == htons(8080))
addr = packet->iph->saddr;
else if(packet->tcp->dest == htons(8080))
addr = packet->iph->daddr;
else
goto ookla_exclude;
-
+
if(ndpi_struct->ookla_cache != NULL) {
- if(lruc_get(ndpi_struct->ookla_cache, &addr, sizeof(addr), &value) == LRUC_NO_ERROR) {
- /* Don't remove it as it can be used for other connections */
+ if(ndpi_lru_find_cache(ndpi_struct->ookla_cache, addr, 0 /* Don't remove it as it can be used for other connections */)) {
NDPI_LOG_INFO(ndpi_struct, "found ookla tcp connection\n");
ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_OOKLA, NDPI_PROTOCOL_UNKNOWN);
return;
- }
+ }
}
ookla_exclude:
-#endif
- NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
+ NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
}
void init_ookla_dissector(struct ndpi_detection_module_struct *ndpi_struct,
@@ -65,4 +61,3 @@ void init_ookla_dissector(struct ndpi_detection_module_struct *ndpi_struct,
*id += 1;
}
-
diff --git a/src/lib/protocols/ssl.c b/src/lib/protocols/ssl.c
index 25d535a57..785ffa70d 100644
--- a/src/lib/protocols/ssl.c
+++ b/src/lib/protocols/ssl.c
@@ -626,6 +626,10 @@ void ndpi_search_ssl_tcp(struct ndpi_detection_module_struct *ndpi_struct, struc
struct ndpi_packet_struct *packet = &flow->packet;
u_int8_t ret;
+ if(flow->packet.tcp && (5222 == ntohs(flow->packet.tcp->dest)))
+ printf("%u - %u\n", ntohs(flow->packet.tcp->source), ntohs(flow->packet.tcp->dest));
+
+
if(packet->detected_protocol_stack[0] == NDPI_PROTOCOL_SSL) {
if(flow->l4.tcp.ssl_stage == 3 && packet->payload_packet_len > 20 && flow->packet_counter < 5) {
/* this should only happen, when we detected SSL with a packet that had parts of the certificate in subsequent packets
diff --git a/src/lib/third_party/include/lruc.h b/src/lib/third_party/include/lruc.h
deleted file mode 100644
index 55fb271fe..000000000
--- a/src/lib/third_party/include/lruc.h
+++ /dev/null
@@ -1,55 +0,0 @@
-#include <pthread.h>
-#include <stdint.h>
-#include <time.h>
-
-#ifndef __lruc_header__
-#define __lruc_header__
-
-// ------------------------------------------
-// errors
-// ------------------------------------------
-typedef enum {
- LRUC_NO_ERROR = 0,
- LRUC_MISSING_CACHE,
- LRUC_MISSING_KEY,
- LRUC_MISSING_VALUE,
- LRUC_PTHREAD_ERROR,
- LRUC_VALUE_TOO_LARGE
-} lruc_error;
-
-
-// ------------------------------------------
-// types
-// ------------------------------------------
-typedef struct {
- void *value;
- void *key;
- uint32_t value_length;
- uint32_t key_length;
- uint64_t access_count;
- void *next;
-} lruc_item;
-
-typedef struct {
- lruc_item **items;
- uint64_t access_count;
- uint64_t free_memory;
- uint64_t total_memory;
- uint64_t average_item_length;
- uint32_t hash_table_size;
- time_t seed;
- lruc_item *free_items;
- pthread_mutex_t *mutex;
-} lruc;
-
-
-// ------------------------------------------
-// api
-// ------------------------------------------
-lruc *lruc_new(uint64_t cache_size, uint32_t average_length);
-lruc_error lruc_free(lruc *cache);
-lruc_error lruc_set(lruc *cache, void *key, uint32_t key_length, void *value, uint32_t value_length);
-lruc_error lruc_get(lruc *cache, void *key, uint32_t key_length, void **value);
-lruc_error lruc_delete(lruc *cache, void *key, uint32_t key_length);
-
-#endif
diff --git a/src/lib/third_party/src/lruc.c b/src/lib/third_party/src/lruc.c
deleted file mode 100644
index f08fb2ce1..000000000
--- a/src/lib/third_party/src/lruc.c
+++ /dev/null
@@ -1,294 +0,0 @@
-/* https://github.com/willcannings/C-LRU-Cache */
-
-#include "lruc.h"
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <err.h>
-
-// ------------------------------------------
-// private functions
-// ------------------------------------------
-// MurmurHash2, by Austin Appleby
-// http://sites.google.com/site/murmurhash/
-uint32_t lruc_hash(lruc *cache, void *key, uint32_t key_length) {
- uint32_t m = 0x5bd1e995;
- uint32_t r = 24;
- uint32_t h = cache->seed ^ key_length;
- char* data = (char *)key;
-
- while(key_length >= 4) {
- uint32_t k = *(uint32_t *)data;
- k *= m;
- k ^= k >> r;
- k *= m;
- h *= m;
- h ^= k;
- data += 4;
- key_length -= 4;
- }
-
- switch(key_length) {
- case 3: h ^= data[2] << 16;
- case 2: h ^= data[1] << 8;
- case 1: h ^= data[0];
- h *= m;
- };
-
- h ^= h >> 13;
- h *= m;
- h ^= h >> 15;
- return h % cache->hash_table_size;
-}
-
-// compare a key against an existing item's key
-int lruc_cmp_keys(lruc_item *item, void *key, uint32_t key_length) {
- if(key_length != item->key_length)
- return 1;
- else
- return memcmp(key, item->key, key_length);
-}
-
-// remove an item and push it to the free items queue
-void lruc_remove_item(lruc *cache, lruc_item *prev, lruc_item *item, uint32_t hash_index) {
- if(prev)
- prev->next = item->next;
- else
- cache->items[hash_index] = (lruc_item *) item->next;
-
- // free memory and update the free memory counter
- cache->free_memory += item->value_length;
- free(item->value);
- free(item->key);
-
- // push the item to the free items queue
- memset(item, 0, sizeof(lruc_item));
- item->next = cache->free_items;
- cache->free_items = item;
-}
-
-// remove the least recently used item
-// TODO: we can optimise this by finding the n lru items, where n = required_space / average_length
-void lruc_remove_lru_item(lruc *cache) {
- lruc_item *min_item = NULL, *min_prev = NULL;
- lruc_item *item = NULL, *prev = NULL;
- uint32_t i = 0, min_index = -1;
- uint64_t min_access_count = -1;
-
- for(; i < cache->hash_table_size; i++) {
- item = cache->items[i];
- prev = NULL;
-
- while(item) {
- if(item->access_count < min_access_count || min_access_count == -1) {
- min_access_count = item->access_count;
- min_item = item;
- min_prev = prev;
- min_index = i;
- }
- prev = item;
- item = item->next;
- }
- }
-
- if(min_item)
- lruc_remove_item(cache, min_prev, min_item, min_index);
-}
-
-// pop an existing item off the free queue, or create a new one
-lruc_item *lruc_pop_or_create_item(lruc *cache) {
- lruc_item *item = NULL;
-
- if(cache->free_items) {
- item = cache->free_items;
- cache->free_items = item->next;
- } else {
- item = (lruc_item *) calloc(sizeof(lruc_item), 1);
- }
-
- return item;
-}
-
-// error helpers
-#define error_for(conditions, error) if(conditions) {return error;}
-#define test_for_missing_cache() error_for(!cache, LRUC_MISSING_CACHE)
-#define test_for_missing_key() error_for(!key || key_length == 0, LRUC_MISSING_KEY)
-#define test_for_missing_value() error_for(!value || value_length == 0, LRUC_MISSING_VALUE)
-#define test_for_value_too_large() error_for(value_length > cache->total_memory, LRUC_VALUE_TOO_LARGE)
-
-// lock helpers
-#define lock_cache() if(pthread_mutex_lock(cache->mutex)) {\
- perror("LRU Cache unable to obtain mutex lock");\
- return LRUC_PTHREAD_ERROR;\
-}
-
-#define unlock_cache() if(pthread_mutex_unlock(cache->mutex)) {\
- perror("LRU Cache unable to release mutex lock");\
- return LRUC_PTHREAD_ERROR;\
-}
-
-
-// ------------------------------------------
-// public api
-// ------------------------------------------
-lruc *lruc_new(uint64_t cache_size, uint32_t average_length) {
- // create the cache
- lruc *cache = (lruc *) calloc(sizeof(lruc), 1);
- if(!cache) {
- perror("LRU Cache unable to create cache object");
- return NULL;
- }
- cache->hash_table_size = cache_size / average_length;
- cache->average_item_length = average_length;
- cache->free_memory = cache_size;
- cache->total_memory = cache_size;
- cache->seed = time(NULL);
-
- // size the hash table to a guestimate of the number of slots required (assuming a perfect hash)
- cache->items = (lruc_item **) calloc(sizeof(lruc_item *), cache->hash_table_size);
- if(!cache->items) {
- perror("LRU Cache unable to create cache hash table");
- free(cache);
- return NULL;
- }
-
- // all cache calls are guarded by a mutex
- cache->mutex = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t));
- if(pthread_mutex_init(cache->mutex, NULL)) {
- perror("LRU Cache unable to initialise mutex");
- free(cache->items);
- free(cache);
- return NULL;
- }
- return cache;
-}
-
-
-lruc_error lruc_free(lruc *cache) {
- test_for_missing_cache();
-
- // free each of the cached items, and the hash table
- lruc_item *item = NULL, *next = NULL;
- uint32_t i = 0;
- if(cache->items) {
- for(; i < cache->hash_table_size; i++) {
- item = cache->items[i];
- while(item) {
- next = (lruc_item *) item->next;
- free(item);
- item = next;
- }
- }
- free(cache->items);
- }
-
- // free the cache
- if(cache->mutex) {
- if(pthread_mutex_destroy(cache->mutex)) {
- perror("LRU Cache unable to destroy mutex");
- return LRUC_PTHREAD_ERROR;
- }
- }
- free(cache);
-
- return LRUC_NO_ERROR;
-}
-
-
-lruc_error lruc_set(lruc *cache, void *key, uint32_t key_length, void *value, uint32_t value_length) {
- test_for_missing_cache();
- test_for_missing_key();
- test_for_missing_value();
- test_for_value_too_large();
- lock_cache();
-
- // see if the key already exists
- uint32_t hash_index = lruc_hash(cache, key, key_length), required = 0;
- lruc_item *item = NULL, *prev = NULL;
- item = cache->items[hash_index];
-
- while(item && lruc_cmp_keys(item, key, key_length)) {
- prev = item;
- item = (lruc_item *) item->next;
- }
-
- if(item) {
- // update the value and value_lengths
- required = value_length - item->value_length;
- free(item->value);
- item->value = value;
- item->value_length = value_length;
-
- } else {
- // insert a new item
- item = lruc_pop_or_create_item(cache);
- item->value = value;
- item->key = key;
- item->value_length = value_length;
- item->key_length = key_length;
- required = value_length;
-
- if(prev)
- prev->next = item;
- else
- cache->items[hash_index] = item;
- }
- item->access_count = ++cache->access_count;
-
- // remove as many items as necessary to free enough space
- if(required > 0 && required > cache->free_memory) {
- while(cache->free_memory < required)
- lruc_remove_lru_item(cache);
- }
- cache->free_memory -= required;
- unlock_cache();
- return LRUC_NO_ERROR;
-}
-
-
-lruc_error lruc_get(lruc *cache, void *key, uint32_t key_length, void **value) {
- test_for_missing_cache();
- test_for_missing_key();
- lock_cache();
-
- // loop until we find the item, or hit the end of a chain
- uint32_t hash_index = lruc_hash(cache, key, key_length);
- lruc_item *item = cache->items[hash_index];
-
- while(item && lruc_cmp_keys(item, key, key_length))
- item = (lruc_item *) item->next;
-
- if(item) {
- *value = item->value;
- item->access_count = ++cache->access_count;
- } else {
- *value = NULL;
- }
-
- unlock_cache();
- return LRUC_NO_ERROR;
-}
-
-
-lruc_error lruc_delete(lruc *cache, void *key, uint32_t key_length) {
- test_for_missing_cache();
- test_for_missing_key();
- lock_cache();
-
- // loop until we find the item, or hit the end of a chain
- lruc_item *item = NULL, *prev = NULL;
- uint32_t hash_index = lruc_hash(cache, key, key_length);
- item = cache->items[hash_index];
-
- while(item && lruc_cmp_keys(item, key, key_length)) {
- prev = item;
- item = (lruc_item *) item->next;
- }
-
- if(item) {
- lruc_remove_item(cache, prev, item, hash_index);
- }
-
- unlock_cache();
- return LRUC_NO_ERROR;
-}