aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--example/ndpiReader.c179
-rw-r--r--example/ndpi_util.h3
2 files changed, 172 insertions, 10 deletions
diff --git a/example/ndpiReader.c b/example/ndpiReader.c
index 59ca8b3a1..63e33d783 100644
--- a/example/ndpiReader.c
+++ b/example/ndpiReader.c
@@ -84,9 +84,24 @@ static time_t capture_for = 0;
static time_t capture_until = 0;
static u_int32_t num_flows;
+struct info_pair{
+ u_int32_t addr;
+ int count;
+};
+
+typedef struct node_a{
+ u_int32_t addr;
+ int count;
+ struct node_a *left, *right;
+}addr_node;
+
struct port_stats {
u_int32_t port; /* we'll use this field as the key */
u_int32_t num_pkts, num_bytes;
+ u_int32_t num_addr; /*to hold number of distinct IP addresses*/
+ u_int32_t cumulative_addr; /*to hold cumulative some of IP addresses*/
+ addr_node *addr_tree; /* to hold distinct IP addresses*/
+ struct info_pair top_ip_addrs[MAX_NUM_IP_ADDRESS];
UT_hash_handle hh; /* makes this structure hashable */
};
@@ -136,6 +151,9 @@ FILE *trace = NULL;
/********************** FUNCTIONS ********************* */
+
+
+
/**
* @brief Set main components necessary to the detection
*/
@@ -764,8 +782,99 @@ static void node_proto_guess_walker(const void *node, ndpi_VISIT which, int dept
/* *********************************************** */
-static void updatePortStats(struct port_stats **stats, u_int32_t port, u_int32_t num_pkts, u_int32_t num_bytes) {
+int updateIpTree(const u_int32_t key, addr_node **vrootp){
+ addr_node *q;
+ addr_node **rootp = vrootp;
+
+ if(rootp == (addr_node **)0)
+ return 0;
+
+ while (*rootp != (addr_node *)0) { /* Knuth's T1: */
+
+ if(key == ((*rootp)->addr)) { /* T2: */
+ return ++((*rootp)->count);
+ }
+
+ rootp = (key < ((*rootp)->addr)) ?
+ &(*rootp)->left : /* T3: follow left branch */
+ &(*rootp)->right; /* T4: follow right branch */
+ }
+ q = (addr_node *) malloc(sizeof(addr_node)); /* T5: key not found */
+ if(q != (addr_node *)0) { /* make new node */
+ *rootp = q; /* link new node to old */
+ q->addr = key; /* initialize new node */
+ q->count = 1;
+ q->left = q->right = (addr_node *)0;
+ return q->count;
+ }
+
+}
+
+/* *********************************************** */
+
+void freeIpTree(addr_node *root) {
+ while (root != NULL) {
+ addr_node *left = root->left;
+ if (left == NULL) {
+ addr_node *right = root->right;
+ root->right = NULL;
+ root = right;
+ } else {
+ /* Rotate the left child up.*/
+ root->left = left->right;
+ left->right = root;
+ root = left;
+ }
+ }
+}
+
+/* *********************************************** */
+
+void updateTopIpAddress(u_int32_t addr, int count, struct info_pair top[], int size){
+ int update = 0;
+ int min_i = 0;
+ int min = count;
+
+ if(count == 0) return;
+
+ struct info_pair pair;
+ pair.addr = addr, pair.count = count;
+
+ /* if the same ip with a bigger
+ count just update it */
+ for(int i=0; i<size; i++) {
+ if (top[i].addr == addr) {
+ top[i].count = count;
+ return;
+ }
+ }
+
+ /* if array is not full yet
+ add it to the first empty place */
+ for(int i=0; i<size; i++) {
+ if (top[i].addr != addr && top[i].count == 0) {
+ top[i] = pair;
+ return;
+ }
+ }
+
+ /* if bigger than the smallest one, replace it */
+ for(int i=0; i<size; i++) {
+ if(top[i].count < count && top[i].count < min){
+ min = top[i].count;
+ min_i = i;
+ update = 1;
+ }
+ }
+
+ if(update)
+ top[min_i] = pair;
+}
+
+/* *********************************************** */
+static void updatePortStats(struct port_stats **stats, u_int32_t port, u_int32_t addr, u_int32_t num_pkts, u_int32_t num_bytes) {
struct port_stats *s;
+ char ipname[48];
HASH_FIND_INT(*stats, &port, s);
if(s == NULL) {
@@ -773,10 +882,31 @@ static void updatePortStats(struct port_stats **stats, u_int32_t port, u_int32_t
if(!s) return;
s->port = port, s->num_pkts = 0, s->num_bytes = 0;
+ s->num_addr = 1, s->cumulative_addr = 1;
+
+ memset(s->top_ip_addrs, 0, MAX_NUM_IP_ADDRESS*sizeof(struct info_pair));
+ updateTopIpAddress(addr, 1, s->top_ip_addrs, MAX_NUM_IP_ADDRESS);
+
+ s->addr_tree = (addr_node *) malloc(sizeof(addr_node));
+ if(!s->addr_tree) return;
+
+ s->addr_tree->addr = addr;
+ s->addr_tree->count = 1;
+ s->addr_tree->left = NULL;
+ s->addr_tree->right = NULL;
+
HASH_ADD_INT(*stats, port, s);
}
+ int count = updateIpTree(addr, &(*s).addr_tree);
+ if(count == UPDATED_TREE) s->num_addr++;
+ if(count) {
+ s->cumulative_addr++;
+ updateTopIpAddress(addr, count, s->top_ip_addrs, MAX_NUM_IP_ADDRESS);
+ }
+
s->num_pkts += num_pkts, s->num_bytes += num_bytes;
+
}
/* *********************************************** */
@@ -786,6 +916,8 @@ static void deletePortsStats(struct port_stats *stats) {
HASH_ITER(hh, stats, current_port, tmp) {
HASH_DEL(stats, current_port);
+ freeIpTree(current_port->addr_tree);
+ free(current_port->addr_tree);
free(current_port);
}
}
@@ -798,14 +930,18 @@ static void deletePortsStats(struct port_stats *stats) {
static void port_stats_walker(const void *node, ndpi_VISIT which, int depth, void *user_data) {
struct ndpi_flow_info *flow = *(struct ndpi_flow_info **) node;
u_int16_t sport, dport;
+ u_int32_t saddr, daddr;
- if(flow->src_to_dst_direction == 1)
- sport = ntohs(flow->lower_port), dport = ntohs(flow->upper_port);
- else
- sport = ntohs(flow->upper_port), dport = ntohs(flow->lower_port);
-
- updatePortStats(&srcStats, sport, flow->packets, flow->bytes);
- updatePortStats(&dstStats, dport, flow->packets, flow->bytes);
+ if(flow->src_to_dst_direction == 1) {
+ sport = ntohs(flow->lower_port), dport = ntohs(flow->upper_port);
+ saddr = flow->lower_ip, daddr = flow->upper_ip;
+ }
+ else {
+ sport = ntohs(flow->upper_port), dport = ntohs(flow->lower_port);
+ saddr = flow->upper_ip, daddr = flow->lower_ip;
+ }
+ updatePortStats(&srcStats, sport, saddr, flow->packets, flow->bytes);
+ updatePortStats(&dstStats, dport, daddr, flow->packets, flow->bytes);
}
/* *********************************************** */
@@ -1050,13 +1186,38 @@ static int port_stats_sort(void *_a, void *_b) {
/* *********************************************** */
+static int info_pair_cmp (const void *_a, const void *_b)
+{
+ struct info_pair *a = (struct info_pair *)_a;
+ struct info_pair *b = (struct info_pair *)_b;
+ return b->count - a->count;
+}
+
+/* *********************************************** */
+
void printPortStats(struct port_stats *stats) {
struct port_stats *s, *tmp;
+ char ip_name[48];
int i = 0;
+ int first = 1;
+
HASH_ITER(hh, stats, s, tmp) {
i++;
- printf("\t%2d\tPort %5u\t[%u pkts/%u bytes]\n", i, s->port, s->num_pkts, s->num_bytes);
+ printf("\t%2d\tPort %5u\t[%u IP address/%u pkts/%u bytes]\n", i, s->port, s->num_addr, s->num_pkts, s->num_bytes);
+
+ qsort(&s->top_ip_addrs[0], MAX_NUM_IP_ADDRESS, sizeof(struct info_pair), info_pair_cmp);
+
+ for(int i=0;i<MAX_NUM_IP_ADDRESS;i++) {
+ if (s->top_ip_addrs[i].count != 0) {
+ inet_ntop(AF_INET, &s->top_ip_addrs[i].addr, ip_name, sizeof(ip_name));
+ printf("\t\t\t\t%s\t%s ~ %.2f%%\n", (first) ? "Top IP Stats:" : "\t",
+ ip_name, ((s->top_ip_addrs[i].count) * 100.0) / s->cumulative_addr);
+ first = 0;
+ }
+ }
+ printf("\n");
+ first = 1;
if(i >= 10) break;
}
}
diff --git a/example/ndpi_util.h b/example/ndpi_util.h
index 9d8f1e446..ca9f20274 100644
--- a/example/ndpi_util.h
+++ b/example/ndpi_util.h
@@ -38,7 +38,8 @@
#define NUM_ROOTS 512
#define MAX_NDPI_FLOWS 200000000
#define TICK_RESOLUTION 1000
-
+#define MAX_NUM_IP_ADDRESS 5 /* len of ip address array */
+#define UPDATED_TREE 1
// flow tracking
typedef struct ndpi_flow_info {