packetloss.c 68.6 KB
Newer Older
1
2
3
4
5
6
7
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <ncurses.h>
#include <rrd.h>
's avatar
committed
8
#include <netinet/in.h>
9
10
11
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
12
#include <netdb.h>
's avatar
committed
13
#include <mapi/expiredflowshash.h>
's avatar
committed
14
#include <mapi.h>
's avatar
committed
15
#include "cgi_headers_packetloss.h"
16

17
#define TIMEOUT 500         // time to drop an unmatched flow
18
#define HASHTABLE_SIZE 4096
19
20
#define WITH_NCURSES 0      // set to 1 if you want ncurses, 0 otherwise
#define REFRESH_TIME 10     // 10 seconds base interval with which data will be fed into the RRD
21

22
23
#define LOGFILE 1           //Log enabled
#define LOGFILENAME_FULL "packetloss.full.log" //Log filename
's avatar
committed
24
25
26
#define LOGFILENAME_LOST "packetloss.lost.log"
#define LOGFILENAME_UNMATCHED "packetloss.unmatched.log"

27
28
29
struct tstatistics {        // need for network load
	unsigned long long bytes;
	unsigned long long ts;
's avatar
committed
30
};
31

's avatar
committed
32
struct hash_bucket {
33
34
	struct hash_bucket *next;
	struct flow_data data;
35
36
37
38
	unsigned int hsvalue;
	unsigned int sensor;
	unsigned int sensor2;
	int assigned;
39
40
};

's avatar
committed
41
42
#define PCT(proto) ((proto.lost) == 0 ? 0 : (float) ((proto.lost) * 100) / (float) (proto.pkts))

43
44
45
46
47
48
49
50
51
52
53
struct tlcstat {
	union {
		unsigned long long pkts;
		unsigned long long count;
	};
	union {
		unsigned long long loss;
		unsigned long long lost;
	};
};

's avatar
committed
54
55
56
57
58
59
60
61
62
63
64
struct tlcmstat {
	unsigned long long loss;
	union {
		unsigned long long count;
		unsigned long long matched;
	};
};

struct tcmstat {
	unsigned int count;
	unsigned int matched;
's avatar
committed
65
	unsigned int unmatched;
's avatar
committed
66
67
68
69
70
71
	unsigned int timeouted;
};

struct tstats {
	struct tlcmstat totalpk;
	struct tcmstat totalflows;
72
73
};

's avatar
committed
74
// Variables for known ports 
75
76
77
78
79
80
81
82
83
84
85
86
87
struct tlcstat mapi    = {{0}, {0}};
struct tlcstat https   = {{0}, {0}};
struct tlcstat sftp    = {{0}, {0}};
struct tlcstat rtsp    = {{0}, {0}};
struct tlcstat http    = {{0}, {0}};
struct tlcstat dns     = {{0}, {0}};
struct tlcstat smtp    = {{0}, {0}};
struct tlcstat openvpn = {{0}, {0}};
struct tlcstat telnet  = {{0}, {0}};
struct tlcstat ssh     = {{0}, {0}};
struct tlcstat ftp     = {{0}, {0}};

struct tlcstat totalpk      = {{0}, {0}};
88
struct tlcstat old_totalpk  = {{0}, {0}};
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
struct tlcstat totalbytes   = {{0}, {0}};

struct t360stat {
	unsigned long long loss[360];
	unsigned long long count[360];
	unsigned long long pkloss;
	unsigned long long pkcount;
	unsigned long long counter;
};

struct t180stat {
	unsigned long long loss[180];
	unsigned long long count[180];
	unsigned long long pkloss;
	unsigned long long pkcount;
	unsigned long long counter;
};

struct t288stat {
	unsigned long long loss[288];
	unsigned long long count[288];
	unsigned long long pkloss;
	unsigned long long pkcount;
	unsigned long long counter;
};

struct t336stat {
	unsigned long long loss[336];
	unsigned long long count[336];
	unsigned long long pkloss;
	unsigned long long pkcount;
	unsigned long long counter;
};

struct t360stat onehour   = { {}, {}, 0, 0, 0};
struct t360stat onemonth  = { {}, {}, 0, 0, 0};
struct t360stat oneyear   = { {}, {}, 0, 0, 0};
struct t180stat threehour = { {}, {}, 0, 0, 0};
struct t288stat oneday    = { {}, {}, 0, 0, 0};
struct t336stat oneweek   = { {}, {}, 0, 0, 0};

's avatar
committed
130
unsigned long long lastmonth = 400, lastweek = 400;
131

's avatar
committed
132
133
134
// Log files pointers
FILE *fp_log = NULL, *fp_log_lost = NULL, *fp_log_unmatched = NULL;

135
struct hash_bucket *hashtable[HASHTABLE_SIZE];
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150

struct thost {
	char *name;            // host name from argv
//	struct hostent *ent; // hostent from gethostbyname
//	ip_addr ip;          // ip from gethostbyname
	struct mapi_stat *mapi_stats_dev;      // stats for devices (mapi, order not guaranteed, result of mapi_stat)
	struct mapi_stat **mapi_stats_devptr;  // stats for devices (pointers to mapi_stats_dev -- sorted)
	mapi_results_t *results_dev;           // results for devices
	mapi_results_t *results_netload_dev;   // results for devices (netload)
	struct tstatistics *netload_stats_dev; // stats for devices (netload)
	int devices;         // number of devices at host
	int fd;              // descriptor of a flow opened to this host
	int fid_loss;        // id of a function (EXPIREDR_FLOWS, BPF_FILTER)
	int fid_load;        // id of a function (BYTE_COUNTER)
	struct tstats stats;       // stats
151
152
153
154
	struct tstats *statsrelto;    // stats (in relation  to other hosts)
	struct tstats *statsdirto;    // stats (in direction to other hosts)
	struct tstats *oldstatsrelto; // old "
	struct tstats *oldstatsdirto; // old "
155
156
157
158
159
	struct tstats *stats_dev;  // stats (for interfaces/devices)
};

struct thost *host; // hosts
int hosts = 0;      // number of hosts (total)
160

's avatar
committed
161
// Functions declaration
's avatar
committed
162
static void terminate();
's avatar
committed
163
void print_protocols(FILE * fp, char *protocol, unsigned long long total_pkts, unsigned long long total_lost);
164
165
struct hash_bucket *compare_bucket(struct hash_bucket *bucket, struct flow_data *data, unsigned int sensor, int rev);
unsigned long long cmp_results(struct flow_data *data, unsigned int sensor);
166
int compare_ip(ip_addr ip1, ip_addr ip2);
167
void drop_old_and_unassigned_flows(void);
's avatar
committed
168
int print_flow(FILE * fp, flow_data * data, unsigned long long pkloss);
169
170
171
172
173
void my_rrd_create_packetloss(char *filename);  // need for packetloss graph
int create_packetloss_cgi();
void my_rrd_update(char *filename, char *data); // need for both graphs
void my_rrd_create_packetcount(char *filename);
int create_packetcount_cgi();
174
void store_results(unsigned int sensor, unsigned int count, struct flow_data *flowdata);
175

176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
//int getHostByIP(ip_addr ip) {
//	int h = 0;
//
//	for(h = 0; h < hosts; h++) {
//		if(compare_ip(host[h].ip, ip)) return h;
//	}
//	fprintf(stderr, "packetloss: ERROR getHostByIP(%d %d %d %d) FAILED\n", ip.byte1, ip.byte2, ip.byte3, ip.byte4);
//	exit(EXIT_FAILURE);
//}

int getDevByName(struct thost host, char *dev, int tip) {
	int d = 0;

	// mapi_stats returned devices in expected order?
	if(strcmp(host.mapi_stats_devptr[tip]->dev, dev) == 0)
		return tip;
's avatar
committed
192
	// if not, lookup
193
194
195
196
197
	for(d = 0; d < host.devices; d++)
		if(strcmp(host.mapi_stats_devptr[d]->dev, dev) == 0)
			return d;
	fprintf(stderr, "packetloss: ERROR getDevByName(%s:%s, %s, %d) FAILED\n", host.name, host.mapi_stats_devptr[tip]->dev, dev, tip);
	exit(EXIT_FAILURE);
198
199
}

200
201
202
int nodroppedpkts() {
	int h = 0;
	int d = 0;
203

204
205
206
	for(h = 0; h < hosts; h++) {
		for(d = 0; d < host[h].devices; d++) {
			if(host[h].mapi_stats_devptr[d]->ps_drop != 0 || host[h].mapi_stats_devptr[d]->ps_ifdrop != 0) return 0;
207
208
209
210
211
		}
	}
	return 1;
}

212
213
214
215
char* statstostr() {
	int h = 0;
	int d = 0;

216
217
218
219
	char *toret;
	struct mapi_stat stats;
	
	//XXX fix the size
220
	toret = (char *)malloc(sizeof(char)*2048);
221
222
	toret[0] = '\0';
	
223
224
225
226
227
228
229
	for(h = 0; h < 2; h++) { // FIXME "2" => hosts
		sprintf(toret, "<center> <br> Sensor %d interfaces stats:<br>", h + 1);
		for(d = 0; d < host[h].devices; d++) {
			stats = host[h].mapi_stats_dev[d];
			sprintf(toret+strlen(toret), "<b>Interface: %s</b><br>received: %u<br>dropped: %u <br>dropped by interface: %u<br>Hostname: %s<br>", stats.dev, stats.ps_recv, stats.ps_drop, stats.ps_ifdrop, host[h].name);
		}
		sprintf(toret+strlen(toret), "</center>");
230
231
232
233
	}
	return(toret);
}

's avatar
committed
234
235
int main(int argc, char *argv[])
{
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
	int i = 0;  // universal counters
	int counter = 0;
	unsigned int count;

	int h = 0;  // host counters
	int h1 = 0;
	int h2 = 0;
	int d = 0;  // device counter

	FILE *fp = NULL;                    // log
	FILE *fp_packetloss = NULL;         // packetloss log
	FILE *fp_packetloss_packets = NULL; // packetcount log

	unsigned int *results;      // number of results/flowdata = (unsigned int *) ...
	struct flow_data *flowdata; // result/flowdata            = (struct flow_data *)((char *) ... + sizeof(unsigned int));

	unsigned long long pkloss = 0;

	char filter[1024]; // pcap filter

	char *p;
	char *p2;
	char *tmp1 = NULL;
	char *k = NULL;

	// OBSOLETE or TODO ???
	//char load[512];
	//char *nl;

	// GUI - CGI
	char top_page_buf[2048];
	char sample[2][512];       // 0 - packetcount, 1 - packetloss
	char *sensorstats;
	char sensorstatslink[256];

	// GUI - ncurses
	struct tstatistics netload_stats = {0, 0}; // current values of netload stats
	int row, col;
	int maxpad = 13;
's avatar
committed
275
	float speed = 0.0;
276
277
278
279
280
281
282
283

	//int devices = 0;   // number of devices (total)
	//int flows = 0;     // number of flows (total)

	char error[512];
	int  err_no = 0;

	int malloc_size = 0;
284

's avatar
committed
285
286
	unsigned int starttime;

287
288
289
	signal(SIGINT, terminate);
	signal(SIGQUIT, terminate);
	signal(SIGTERM, terminate);
's avatar
committed
290

's avatar
committed
291
292
	starttime = (unsigned int) time(NULL);

293
294
295
296
	// Check arguments {{{
	if (argc < 4) {
		fprintf(stderr, "\nUsage: %s \"host1:interface1, host1:interface2, ...\" \"hostB:interface1, ...\" ... \"pcap filter\"\n\n", argv[0]);
		exit(EXIT_FAILURE);
297
	}
298
299
300
301
302
303
304
305
306

	hosts = argc - 2;

	for(h = 0; h < hosts; h++) {
		tmp1 = strchr(argv[h + 1], ':');
		if (tmp1 == NULL) {
			fprintf(stderr, "Error!! You must provide an interface (e.g eth0) for each IP.\n");
			exit(EXIT_FAILURE);
		}
307
	}
308
309
310
311
312
313
	// }}}

	// Initialize host {{{
	if((host = (struct thost *) malloc(malloc_size = (hosts * sizeof(struct thost)))) == NULL) {
		fprintf(stderr, "malloc(): could not allocate memory");
		return -1;
314
	}
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
	memset(host, 0, malloc_size);
	// }}}

	// Get host names, ents/IPs, # of devices {{{
	for(h = 0; h < hosts; h++) {
		// get host name
		tmp1 = strchr(argv[h + 1], ':');
		*tmp1 = '\0';
		host[h].name = strdup(argv[h + 1]);
		*tmp1 = ':';

		// count devices per host + total
		host[h].devices = 0;
		k = strtok(strdup(argv[h + 1]), ", ");
		while (k != NULL) {
			host[h].devices++;
			k = strtok(NULL,", ");
		}
		//devices += host[h].devices;

		// get host IPs by names
//		if((host[h].ent = gethostbyname(host[h].name)) == NULL) {
//			fprintf(stderr, "Cannot gethostbyname(\"%s\")\n", host[h].name);
//			exit(EXIT_FAILURE);
//		}
//		if(host[h].ent->h_addr == NULL) {
//			fprintf(stderr, "Cannot gethostbyname(\"%s\") - h_addr_list empty\n", host[h].name);
//		}
//		host[h].ip.byte1 = host[h].ent->h_addr[0];
//		host[h].ip.byte2 = host[h].ent->h_addr[1];
//		host[h].ip.byte3 = host[h].ent->h_addr[2];
//		host[h].ip.byte4 = host[h].ent->h_addr[3];

		// count flows/links
		//for(i = h; i > 0; i--) {
		//	flows += 2;
		//}
352
	}
353
	// }}}
's avatar
committed
354

355
356
	// Initialize host arrays {{{
	for(h = 0; h < hosts; h++) {
357
		if((host[h].statsrelto = (struct tstats *) malloc(malloc_size = (hosts * sizeof(struct tstats)))) == NULL) {
358
359
360
			fprintf(stderr, "malloc(): could not allocate memory");
			return -1;
		}
361
		memset(host[h].statsrelto, 0, malloc_size);
's avatar
test    
committed
362

363
364
365
366
		// we do not recognize flow direction yet :(
		host[h].statsdirto = host[h].statsrelto;

		if((host[h].oldstatsrelto = (struct tstats *) malloc(malloc_size = (hosts * sizeof(struct tstats)))) == NULL) {
367
368
369
			fprintf(stderr, "malloc(): could not allocate memory");
			return -1;
		}
370
371
372
373
		memset(host[h].oldstatsrelto, 0, malloc_size);

		// we do not recognize flow direction yet :(
		host[h].oldstatsdirto = host[h].oldstatsrelto;
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399

		if((host[h].mapi_stats_dev = (struct mapi_stat *) malloc(malloc_size = (host[h].devices * sizeof(struct mapi_stat)))) == NULL) {
			fprintf(stderr, "malloc(): could not allocate memory");
			return -1;
		}
		memset(host[h].mapi_stats_dev, 0, malloc_size);
		
		if((host[h].mapi_stats_devptr = (struct mapi_stat **) malloc(malloc_size = (host[h].devices * sizeof(struct mapi_stat *)))) == NULL) {
			fprintf(stderr, "malloc(): could not allocate memory");
			return -1;
		}
		memset(host[h].mapi_stats_devptr, 0, malloc_size);
		for(d = 0; d < host[h].devices; d++) host[h].mapi_stats_devptr[d] = &host[h].mapi_stats_dev[d];

		if((host[h].netload_stats_dev = (struct tstatistics *) malloc(malloc_size = (host[h].devices * sizeof(struct tstatistics)))) == NULL) {
			fprintf(stderr, "malloc(): could not allocate memory");
			return -1;
		}
		memset(host[h].netload_stats_dev, 0, malloc_size);

		if((host[h].stats_dev = (struct tstats *) malloc(malloc_size = (host[h].devices * sizeof(struct tstats)))) == NULL) {
			fprintf(stderr, "malloc(): could not allocate memory");
			return -1;
		}
		memset(host[h].stats_dev, 0, malloc_size);
		
400
	}
401
	// }}}
's avatar
committed
402

403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
	// Create flows at hosts, build and apply filters, connect {{{
	for(h = 0; h < hosts; h++) {

		fprintf(stdout, "mapi_create_flow(%s)\n", argv[h + 1]); fflush(stdout);
	
		if ((host[h].fd = mapi_create_flow(argv[h + 1])) < 0) {
			fprintf(stderr, "Could not create flow using '%s'\n", argv[h + 1]);
			mapi_read_error(&err_no, error);
			fprintf(stderr, "Errorcode: %d description: %s\n", err_no, error);
			exit(EXIT_FAILURE);
		}

		// build pcap filter
//		sprintf(filter, "host %s and (host ", host[h].name);
//		p = strchr(filter, '\0');
//		h1 = 0;
//		for(h2 = 0; h2 < hosts; h2++) {
//			if(h2 != h) {
//				if(h1 < hosts - 2) sprintf(p, "%s or host ", host[h2].name);
//				else sprintf(p, "%s)", host[h2].name);
//				p = strchr(p, '\0');
//				h1++;
//			}
//		}
		sprintf(filter, argv[argc - 1]);

		fprintf(stdout, "packetloss: apply BPF_FILTER: \"%s\"\n", filter); fflush(stdout);

		if ((host[h].fid_loss = mapi_apply_function(host[h].fd, "BPF_FILTER", filter)) < 0) {
				fprintf(stderr, "Count not apply function BPF_FILTER to flow %d\n", host[h].fd);
				mapi_read_error(&err_no, error);
				fprintf(stderr, "Errorcode: %d description: %s\n", err_no, error);
				exit(EXIT_FAILURE);
		}

		if ((host[h].fid_load = mapi_apply_function(host[h].fd, "BYTE_COUNTER")) < 0) {	// need for netload
			fprintf(stderr, "Count not apply function BYTE_COUNTER to flow %d\n", host[h].fd);
			mapi_read_error(&err_no, error);
			fprintf(stderr, "Errorcode :%d description: %s\n", err_no, error);
			exit(EXIT_FAILURE);
		}

		if ((host[h].fid_loss = mapi_apply_function(host[h].fd, "EXPIRED_FLOWS")) < 0) {
			fprintf(stderr, "Count not apply function EXPIRED_FLOWS to flow %d\n", host[h].fd);
			mapi_read_error(&err_no, error);
			fprintf(stderr, "Errorcode: %d description: %s\n", err_no, error);
			exit(EXIT_FAILURE);
		}
's avatar
committed
451
452
	}

453
454
455
456
457
458
459
	for(h = 0; h < hosts; h++) {
		if (mapi_connect(host[h].fd) < 0) {
			fprintf(stderr, "Could not connect to flow %d\n", host[h].fd);
			mapi_read_error(&err_no, error);
			fprintf(stderr, "Errorcode: %d description: %s\n", err_no, error);
			exit(EXIT_FAILURE);
		}
460
	}
461
	// }}}
's avatar
test    
committed
462

463
	// RRD Files descriptors - init {{{
's avatar
committed
464
	if ((fp_packetloss = fopen(RRD_FILENAME, "r")) == NULL)	// packetloss graph
465
		my_rrd_create_packetloss(RRD_FILENAME);
's avatar
committed
466
	else {
467
		fclose(fp_packetloss);
's avatar
committed
468
	}
469
	if ((fp_packetloss_packets = fopen(RRD_FILENAME_PACKETS, "r")) == NULL)	// packetloss graph
470
		my_rrd_create_packetcount(RRD_FILENAME_PACKETS);
471
472
473
	else {
		fclose(fp_packetloss_packets);
	}
474
	// }}}
's avatar
committed
475

476
	// Log Files descriptors - init {{{
's avatar
committed
477
	if (LOGFILE) {
478
		if ((fp_log = fopen(LOGFILENAME_FULL, "a")) != NULL) {
's avatar
committed
479
			fprintf(stdout, "Writing log to %s...\n", LOGFILENAME_FULL);
's avatar
committed
480
			fprintf(fp_log, "\n\nPacketloss application started at %u\n\n", starttime); fflush(fp_log);
481
		}
's avatar
committed
482
483
484
485
		else {
			fprintf(stderr, "Log file %s couldn't be opened for writing!\nAborting!\n", LOGFILENAME_FULL);
			exit(EXIT_FAILURE);
		}
486
		if (((fp_log_lost = fopen(LOGFILENAME_LOST, "a")) != NULL))	{
's avatar
committed
487
			fprintf(stdout, "Writing log to %s...\n", LOGFILENAME_LOST);
's avatar
committed
488
			fprintf(fp_log_lost, "\n\nPacketloss application started at %u\n\n", starttime); fflush(fp_log);
489
		}
's avatar
committed
490
491
492
493
		else {
			fprintf(stderr, "Log file %s couldn't be opened for writing!\nAborting!\n", LOGFILENAME_LOST);
			exit(EXIT_FAILURE);
		}
494
		if ((fp_log_unmatched = fopen(LOGFILENAME_UNMATCHED, "a")) != NULL)	{
's avatar
committed
495
			fprintf(stdout, "Writing log to %s...\n", LOGFILENAME_UNMATCHED);
's avatar
committed
496
			fprintf(fp_log_unmatched, "\n\nPacketloss application started at %u\n\n", starttime); fflush(fp_log);
497
		}
's avatar
committed
498
499
500
501
		else {
			fprintf(stderr, "Log file %s couldn't be opened for writing!\nAborting!\n", LOGFILENAME_UNMATCHED);
			exit(EXIT_FAILURE);
		}
502
503
	}
	// }}}
's avatar
committed
504

505
506
507
508
	// GUI - ncurses - init {{{
	if (WITH_NCURSES) {
		initscr();				// start curses mode 
		getmaxyx(stdscr, row, col);	// places the current cursor position of the given window in the two integer variables row and col
's avatar
committed
509
	}
510
	// }}}
's avatar
committed
511

512
	// GUI - CGI - init {{{
's avatar
committed
513
	create_packetloss_cgi();  // packetloss graph
514
515
	create_packetcount_cgi(); // packetcount graph
	// }}}
's avatar
committed
516

517
	// Initialize counters {{{
518
	for(counter = 0; counter < 360; counter++) {
519
520
521
		onehour.loss[counter] = onehour.count[counter] = 0;
		onemonth.loss[counter] = onemonth.count[counter] = 0;
		oneyear.loss[counter] = oneyear.count[counter] = 0;
522
		if(counter < 180 )
523
			threehour.loss[counter] = threehour.count[counter] = 0;
524
		if(counter < 288)
525
			oneday.loss[counter] = oneday.count[counter] = 0;
526
		if(counter < 336) 
527
			oneweek.loss[counter] = oneweek.count[counter] = 0;
528
	}
529
	// }}}
530

531
532
	// Initialize netload (all devices) {{{
	// }}}
's avatar
committed
533

534
	// Main loop
's avatar
committed
535

536
	while (1) { // Infinite Loop. Forever, report the load and packet loss
's avatar
committed
537

538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
		// Read host results from hosts {{{
		for (h = 0; h < hosts; h++) {
			host[h].results_dev = (mapi_results_t *) mapi_read_results(host[h].fd, host[h].fid_loss);
			host[h].results_netload_dev = (mapi_results_t *) mapi_read_results(host[h].fd, host[h].fid_load);
		}
		// }}}
	
		// Read host stats from hosts {{{
		for(h = 0; h < hosts; h++) {
			if (mapi_stats(argv[h + 1], host[h].mapi_stats_dev) < 0) {
				fprintf(stderr, "Error in mapi_stats using '%s'\n", argv[h + 1]);
				mapi_read_error(&err_no, error);
				fprintf(stderr,"Errorcode :%d description: %s \n" ,err_no, error);
				return -1;
			}	
			for(d = 0; d < host[h].devices; d++) {
				i = getDevByName(host[h], host[h].mapi_stats_devptr[d]->dev, d);
				host[h].mapi_stats_devptr[d] = &host[h].mapi_stats_dev[i];
			}
		}
		// }}}
's avatar
committed
559

560
561
562
563
564
565
566
567
		// Store host results in the hashtable {{{
		for (h = 0; h < hosts; h++) {
			for (d = 0; d < host[h].devices; d++) {
				results = (unsigned int *) host[h].results_dev[d].res; // number of results/flows at host h, dev d
				flowdata = (struct flow_data *)((char *) host[h].results_dev[d].res + sizeof(unsigned int)); // results/flows array
				if(*results) {
					store_results(h, *results, flowdata);
				}
's avatar
committed
568
			}
569
570
		}
		// }}}
571

572
573
574
575
576
577
578
579
580
581
582
583
584
585
		// Process results {{{
		i = 0;
		for (h = 0; h < hosts; h++) {
			for (d = 0; d < host[h].devices; d++, i++) {

				// GUI - ncurses - report network load {{{
				//XXX this is obselete, it should be updated!
				netload_stats.bytes = *((unsigned long long *) host[h].results_netload_dev[d].res);
				netload_stats.ts = host[h].results_netload_dev[d].ts;
				speed = (float) ((netload_stats.bytes - host[h].netload_stats_dev[d].bytes) * 8) / (float) (netload_stats.ts - host[h].netload_stats_dev[d].ts);

				if (WITH_NCURSES) {
					mvprintw(row / 2 + i + 2, 8, "%*s\t %6.2f Mbit/s  %8llu bytes in %1.2lf seconds\n", maxpad, argv[i + 1], speed, (netload_stats.bytes - host[h].netload_stats_dev[d].bytes), (double) (netload_stats.ts - host[h].netload_stats_dev[d].ts) / 1000000.0);
					refresh();		// refresh curses windows and lines
's avatar
committed
586
				}
587
588
589
590
591
592
				host[h].netload_stats_dev[d].bytes = netload_stats.bytes;
				host[h].netload_stats_dev[d].ts = netload_stats.ts;
				// }}}

				results = (unsigned int *) host[h].results_dev[d].res; // number of results/flows
				flowdata = (struct flow_data *) ((char *) host[h].results_dev[d].res + sizeof(unsigned int)); // results/flows array
's avatar
committed
593

594
				for (count = *results; count > 0; count--) {
's avatar
committed
595
					if (LOGFILE) {
596
597
598
						fprintf(fp_log, "[%d]\t%u\t", h, (unsigned int)time(0));
						print_flow(fp_log, flowdata, 0);
						fflush(fp_log);
's avatar
committed
599
600
					}

601
602
603
604
605
606
607
608
					if ((pkloss = cmp_results(flowdata, h)) != 0) {
						totalpk.loss += pkloss;
						if (LOGFILE) {
							fprintf(fp_log_lost, "%u\t",(unsigned int) time(0));
							print_flow(fp_log_lost, flowdata, pkloss);
							fflush(fp_log_lost);
						}

's avatar
committed
609
						host[h].stats.totalpk.loss += pkloss;
610
611
612
613
614
615
616
617
618
619
620
621
622
623

						// Loss by protocols {{{
						if      (flowdata->sport == 2233 || flowdata->dport == 2233) mapi.lost += pkloss;
						else if (flowdata->sport == 1194 || flowdata->dport == 1194) openvpn.lost += pkloss;
						else if (flowdata->sport == 554  || flowdata->dport == 554)  rtsp.lost += pkloss;
						else if (flowdata->sport == 443  || flowdata->dport == 443)  https.lost += pkloss;
						else if (flowdata->sport == 115  || flowdata->dport == 115)  sftp.lost += pkloss;
						else if (flowdata->sport == 80   || flowdata->dport == 80)   http.lost += pkloss;
						else if (flowdata->sport == 53   || flowdata->dport == 53)   dns.lost += pkloss;
						else if (flowdata->sport == 25   || flowdata->dport == 25)   smtp.lost += pkloss;
						else if (flowdata->sport == 23   || flowdata->dport == 23)   telnet.lost += pkloss;
						else if (flowdata->sport == 22   || flowdata->dport == 22)   ssh.lost += pkloss;
						else if (flowdata->sport == 21   || flowdata->dport == 21)   ftp.lost += pkloss;
						// }}}
's avatar
committed
624

625
					}
's avatar
committed
626

's avatar
committed
627
628
					host[h].stats.totalpk.count += flowdata->packets_count;
					host[h].stats_dev[d].totalpk.count += flowdata->packets_count;
629
630
631
					flowdata = flowdata + 1;

				}
632
633
			}
		}
634
		// }}}
's avatar
test    
committed
635

636
637
		// Network load graph {{{ // OBSOLETE or TODO ???
		/*
638
639
		nl = load;				// need for network load graph
		nl += snprintf(load, 24, "%u", (unsigned int) time(0));
's avatar
committed
640
		nl += snprintf(nl, 24, ":%f", speed);	// left frame
641
642
643
644
645
646
		*/
		// }}}

		// RRD - packetloss - update {{{
		p = sample[0];				// need for packetloss graph
		p += snprintf(sample[0], 24, "%u", (unsigned int) time(0));
647
		if ((totalpk.count - old_totalpk.count == 0) || (totalpk.loss - old_totalpk.loss == 0)) {	// left frame
648
649
650
			for(h = 0; h < hosts * (hosts - 1); h++) {
				p += snprintf(p, 24, ":%f", 0.0);
			}
's avatar
committed
651
		}
652
653
654
		else { // FIXME
			for(h1 = 0; h1 < hosts; h1++) {
				for(h2 = 0; h2 < hosts; h2++) {
655
					if(h2 != h1) p += snprintf(p, 24, ":%f", (float) (h2 > h1 ? -1 : 1) * ((host[h1].statsrelto[h2].totalpk.loss - host[h1].oldstatsdirto[h2].totalpk.loss) * 100) / (float) (totalpk.count - old_totalpk.count));
656
657
				}
			}
658
		}
659
660
		my_rrd_update(RRD_FILENAME, sample[0]);	// update packetloss graph
		// }}}
661

662
663
664
665
666
667
668
669
670
671
672
		// RRD - packetcount - update {{{
		p2 = sample[1];				// need for packetcount graph
		p2 += snprintf(sample[1], 24, "%u", (unsigned int) time(0));
		if ((totalpk.count - old_totalpk.count == 0) ) {
			for(h = 0; h < hosts * (hosts - 1); h++) {
				p2 += snprintf(p2, 24, ":%f", 0.0);
			}
		}
		else { // FIXME
			for(h1 = 0; h1 < hosts; h1++) {
				for(h2 = 0; h2 < hosts; h2++) {
673
					if(h2 != h1) p2 += snprintf(p2, 24, ":%f", (float) (h2 > h1 ? -1 : 1) * (host[h1].statsrelto[h2].totalpk.loss - host[h1].oldstatsdirto[h2].totalpk.loss));
674
675
676
677
678
				}
			}
		}
		my_rrd_update(RRD_FILENAME_PACKETS, sample[1]);	// update packetloss graph
		// }}}
's avatar
test    
committed
679

680
		// Total packet loss and count - calculations {{{
681
		// One hour packet loss calculation
682
683
684
		onehour.pkloss -= onehour.loss[onehour.counter];                // - old 10s result
		onehour.loss[onehour.counter] = totalpk.loss - old_totalpk.loss; // save new 10s result
		onehour.pkloss += onehour.loss[onehour.counter];                // + new 10s result
685
		// One hour packet count calculation
686
687
688
		onehour.pkcount -= onehour.count[onehour.counter];
		onehour.count[onehour.counter] = totalpk.count - old_totalpk.count;
		onehour.pkcount += onehour.count[onehour.counter];
689

690
		onehour.counter = (onehour.counter+1)%360; // % (3600 / REFRESH_TIME)
691
692
693


		// Three hours
694
		if( onehour.counter % 6 == 0) {
695
			// Three hour packet loss and count calculation
696
697
698
699
			threehour.pkloss -= threehour.loss[threehour.counter];
			threehour.pkcount -= threehour.count[threehour.counter];
			threehour.loss[threehour.counter] = 0;
			threehour.count[threehour.counter] = 0;
700
			for(counter = 0; counter < 6; counter++) {
701
702
				threehour.loss[threehour.counter] += onehour.loss[((onehour.counter+354+counter)%360)];
				threehour.count[threehour.counter] += onehour.count[((onehour.counter+354+counter)%360)];
703
			}
704
705
			threehour.pkloss += threehour.loss[threehour.counter];
			threehour.pkcount += threehour.count[threehour.counter];
706

707
			threehour.counter = (threehour.counter+1)%180;
708
709
710
		}

		// One day
711
		if( onehour.counter % 30 == 0) { 
712
			// One day packet loss and count calculation
713
714
715
716
			oneday.pkloss -= oneday.loss[oneday.counter];
			oneday.pkcount -= oneday.count[oneday.counter];
			oneday.count[oneday.counter] = 0;
			oneday.loss[oneday.counter] = 0;
717
			for(counter = 0; counter < 30; counter++) {
718
719
				oneday.loss[oneday.counter] += onehour.loss[((onehour.counter+330+counter)%360)];
				oneday.count[oneday.counter] += onehour.count[((onehour.counter+330+counter)%360) ];
720
			}
721
722
			oneday.pkloss += oneday.loss[oneday.counter];
			oneday.pkcount += oneday.count[oneday.counter];
723

724
			oneday.counter = (oneday.counter+1)%288;
725
726
727
		}

		// One Week
728
		if( onehour.counter % 180 == 0) { 
729
			// One week packet loss and count calculation
730
731
732
733
			oneweek.pkloss -= oneweek.loss[oneweek.counter];
			oneweek.pkcount -= oneweek.count[oneweek.counter];
			oneweek.count[oneweek.counter] = 0;
			oneweek.loss[oneweek.counter] = 0;
734
			for(counter = 0; counter < 180; counter++) {
735
736
				oneweek.loss[oneweek.counter] += onehour.loss[((onehour.counter+180+counter)%360)];
				oneweek.count[oneweek.counter] += onehour.count[((onehour.counter+180+counter)%360)];
737
			}
738
739
			oneweek.pkloss += oneweek.loss[oneweek.counter];
			oneweek.pkcount += oneweek.count[oneweek.counter];
740

741
			oneweek.counter = (oneweek.counter+1)%336;
742
743
744
		}

		// One Month
745
746
		if( (oneweek.counter % 4 == 0) && (lastweek != oneweek.counter)) { 
			lastweek = oneweek.counter;
747
			// One month packet loss and count calculation
748
749
750
751
			onemonth.pkloss -= onemonth.loss[onemonth.counter];
			onemonth.pkcount -= onemonth.count[onemonth.counter];
			onemonth.count[onemonth.counter] = 0;
			onemonth.loss[onemonth.counter] = 0;
752
			for(counter = 0; counter < 4; counter++) {
753
754
				onemonth.loss[onemonth.counter] += oneweek.loss[((oneweek.counter+332+counter)%336)];
				onemonth.count[onemonth.counter] += oneweek.count[((oneweek.counter+332+counter)%336)];
755
			}
756
757
			onemonth.pkloss += onemonth.loss[onemonth.counter];
			onemonth.pkcount += onemonth.count[onemonth.counter];
's avatar
committed
758
		
759
			onemonth.counter = (onemonth.counter+1)%360;
760
761
762
		}

		// One Year
763
764
		if( (onemonth.counter % 12 == 0) && (lastmonth != onemonth.counter)) { 
			lastmonth = onemonth.counter;
765
			// One year packet loss and count calculation
766
767
768
769
			oneyear.pkloss -= oneyear.loss[oneyear.counter];
			oneyear.pkcount -= oneyear.count[oneyear.counter];
			oneyear.count[oneyear.counter] = 0;
			oneyear.loss[oneyear.counter] = 0;
770
			for(counter = 0; counter < 12; counter++) {
771
772
				oneyear.loss[oneyear.counter] += onemonth.loss[((onemonth.counter+348+counter)%360)];
				oneyear.count[oneyear.counter] += onemonth.count[((onemonth.counter+348+counter)%360)];
773
			}
774
775
			oneyear.pkloss += oneyear.loss[oneyear.counter];
			oneyear.pkcount += oneyear.count[oneyear.counter];
776

777
			oneyear.counter = (oneyear.counter+1)%360;
778
		}
779
		// }}}
780

781
782
		// Total packet loss and count - update old values {{{
		old_totalpk.count = totalpk.count;
783
		old_totalpk.loss = totalpk.loss;
784
785
		for(h1 = 0; h1 < hosts; h1++) {
			for(h2 = 0; h2 < hosts; h2++) {
786
				if(h2 != h1) host[h1].oldstatsdirto[h2].totalpk.loss = host[h1].statsrelto[h2].totalpk.loss;
787
788
789
			}
		}
		// }}}
's avatar
test    
committed
790

's avatar
committed
791
792
793
		// remove old unmatched flow from hashtable
		drop_old_and_unassigned_flows();

794
		// GUI - ncurses {{{
's avatar
committed
795
		if (WITH_NCURSES) {
796
			if (totalpk.count == 0) {
's avatar
committed
797
798
				mvprintw(row / 2 - 5, 8, "Total packet loss ratio : 0.00 %% (0 pkts)");
				mvprintw(row / 2 - 4, 8, "Total byte loss ratio : 0.00 %% (0 Kbytes)");
799
800
				mvprintw(row / 2 - 1, 8, "Packet lost from %s : 0 (0.00 %%)", host[0].name);
				mvprintw(row / 2, 8, "Packet lost from %s : 0 (0.00 %%)", host[1].name);
's avatar
committed
801
			} else {
802
803
				mvprintw(row / 2 - 5, 8, "Total packet loss ratio : %.2f %% (%llu pkts)", (float) (totalpk.loss * 100) / (float) totalpk.count, totalpk.loss);
				mvprintw(row / 2 - 4, 8, "Total byte loss ratio : %.2f %% (%.2f Kbytes)", (float) (totalbytes.lost * 100) / (float) totalbytes.count, (float) (totalbytes.lost / (float) 1024));
804
805
				mvprintw(row / 2 - 1, 8, "Total packets lost from %s : %llu (%.2f %%)", host[0].name, host[0].statsdirto[1].totalpk.loss, (float) (host[0].statsdirto[1].totalpk.loss * 100) / (float) totalpk.count);
				mvprintw(row / 2, 8, "Total packets lost from %s : %llu (%.2f %%)", host[1].name, host[1].statsdirto[0].totalpk.loss, (float) (host[1].statsdirto[0].totalpk.loss * 100) / (float) totalpk.count);
's avatar
committed
806
			}
's avatar
committed
807
808
			mvprintw(row / 2 - 3, 8, "Total packets captured at host %s : %llu", host[0].name, host[0].stats.totalpk.count);
			mvprintw(row / 2 - 2, 8, "Total packets captured at host %s : %llu", host[1].name, host[1].stats.totalpk.count);
's avatar
committed
809
			refresh();			// refresh curses windows and lines
's avatar
committed
810
		}
811
		// }}}
's avatar
committed
812

813
		// GUI - CSV - (new) {{{
's avatar
committed
814

815
816
817
818
819
820
821
822
		if ((fp = fopen(TOP_FILENAME_CSV, "w")) != NULL) {
			fprintf(stdout, "Writing data to %s...\n", TOP_FILENAME_CSV);
		}
		else {
			fprintf(stderr, "CSV file %s couldn't be opened for writing!\nAborting!\n", TOP_FILENAME_CSV);
			exit(EXIT_FAILURE);
		}
		//if( host[0].mapi_stats_dev.ps_drop != 0 || host[1].mapi_stats_dev.ps_drop != 0 || host[0].mapi_stats_dev.ps_ifdrop != 0 || host[1].mapi_stats_dev.ps_ifdrop != 0)
's avatar
committed
823
824
825
		//	sprintf(sensorstatslink, "red");
		//else
		//	sprintf(sensorstatslink, "green");
's avatar
committed
826
827
		fprintf(fp, "misc;starttime;Measurement started at;%d\n", starttime);
		fprintf(fp, "misc;ts;Data valid to;%d\n", (unsigned int) time(NULL));
's avatar
committed
828
		fprintf(fp, "\n");
829
830
831
832
833
834
835
836
837
838
839
		for(h = 0; h < hosts; h++) {
			fprintf(fp, "host;h%d;hostname;Hostname;%s\n", h, host[h].name);
			fprintf(fp, "host;h%d;rrddsid;RRD DS ID;h%d\n", h, h);
			//fprintf(fp, "host;h%d;recv;Received;%u\n",     h, host[h].mapi_stats_devptr[0]->ps_recv);
			//fprintf(fp, "host;h%d;drop;Dropped;%u\n",      h, host[h].mapi_stats_devptr[0]->ps_drop);
			for(d = 0; d < host[h].devices; d++) {
				fprintf(fp, "host;h%d;if%d;Interface;%s\n",    h, d, host[h].mapi_stats_devptr[d]->dev);
				fprintf(fp, "host;h%d;if%drecv;Received;%u\n", h, d, host[h].mapi_stats_devptr[d]->ps_recv);
				fprintf(fp, "host;h%d;if%ddrop;Dropped (ps_drop);%u\n",  h, d, host[h].mapi_stats_devptr[d]->ps_drop);
				fprintf(fp, "host;h%d;if%ddropif;Dropped (ps_ifdrop) by interface %s;%u\n", h, d, host[h].mapi_stats_devptr[d]->dev, host[h].mapi_stats_devptr[d]->ps_ifdrop);
			}
's avatar
committed
840
841
842
843
844
845
846
847
848
849
850
		fprintf(fp, "\n");
		}
		fprintf(fp, "top;tplr;Total Packet Loss Ratio;%.2f %% (%llu pkts)\n", (float) (totalpk.count ? (totalpk.loss * 100) / (float) totalpk.count : totalpk.count), totalpk.loss);
		fprintf(fp, "top;tblr;Total Byte Loss Ratio;%.2f %% (%.2f Kbytes);\n", (float) (totalbytes.count ? (totalbytes.lost * 100) / (float) totalbytes.count :totalbytes.count) , (float) (totalbytes.lost / (float) 1024));
		fprintf(fp, "\n");
		fprintf(fp, "top;plr1h;Last Hour Packet Loss Ratio;%.2f %% (%llu pkts)\n", (float) (onehour.pkcount ? (onehour.pkloss * 100) / (float) onehour.pkcount : onehour.pkcount), onehour.pkloss);
		fprintf(fp, "top;plr3h;Last 3 Hours Packet Loss Ratio;%.2f %% (%llu pkts)\n", (float) ( threehour.pkcount ? (threehour.pkloss * 100) / (float) threehour.pkcount: threehour.pkcount), threehour.pkloss);
		fprintf(fp, "top;plr1d;Last 1 Day Packet Loss Ratio;%.2f %% (%llu pkts)\n", (float) (oneday.pkcount ? (oneday.pkloss * 100) / (float) oneday.pkcount : oneday.pkcount), oneday.pkloss);
		fprintf(fp, "top;plr1w;Last 1 Week Packet Loss Ratio;%.2f %% (%llu pkts)\n", (float) ( oneweek.pkcount ? (oneweek.pkloss * 100) / (float) oneweek.pkcount : oneweek.pkcount) , oneweek.pkloss);	
		fprintf(fp, "top;plr1m;Last 1 Month Packet Loss Ratio;%.2f %% (%llu pkts)\n", (float) (onemonth.pkcount ? (onemonth.pkloss * 100) / (float) onemonth.pkcount : onemonth.pkcount), onemonth.pkloss);
		fprintf(fp, "top;plr1y;Last 1 Year Packet Loss Ratio;%.2f %% (%llu pkts)\n", (float) (oneyear.pkcount ? (oneyear.pkloss * 100) / (float) oneyear.pkcount : oneyear.pkcount), oneyear.pkloss);
851
    //TODO fprintf(fp, "top;blr1h;Last Hour Byte Loss Ratio;%.2f %% (%.2f Kbytes);\n", (float) (totalbytes.lost * 100) / (float) totalbytes.count, (float) (totalbytes.lost / (float) 1024));
's avatar
committed
852
		fprintf(fp, "\n");
853
		for(h1 = 0; h1 < hosts; h1++) {
854
855
856
857
858
			fprintf(fp, "top;tfch%d;Total flows captured at %s;%u\n", h1, host[h1].name, host[h1].stats.totalflows.count);
			fprintf(fp, "top;tfmh%d;Total flows matched at %s;%u\n", h1, host[h1].name, host[h1].stats.totalflows.matched);
			fprintf(fp, "top;tfuh%d;Total flows unmatched at %s;%u\n", h1, host[h1].name, host[h1].stats.totalflows.unmatched);
			fprintf(fp, "top;tfth%d;Total flows timeouted at %s;%u\n", h1, host[h1].name, host[h1].stats.totalflows.timeouted);
			fprintf(fp, "top;tpch%d;Total packets captured at %s;%llu\n", h1, host[h1].name, host[h1].stats.totalpk.count);
859
			for(d = 0; d < host[h1].devices; d++) {
860
				fprintf(fp, "top;tpch%dd%d;Total packets captured at %s:%s;%llu\n", h1, d, host[h1].name, host[h1].mapi_stats_dev[d].dev, host[h1].stats_dev[d].totalpk.count);
861
862
863
			}
			for(h2 = 0; h2 < hosts; h2++) {
				if(h2 != h1) {
864
865
866
867
					fprintf(fp, "top;tfmrh%dh%d;Total flows matched at %s in relation to %s;%u\n", h1, h2, host[h1].name, host[h2].name, host[h1].statsrelto[h2].totalflows.matched);
					fprintf(fp, "top;tftrh%dh%d;Total flows timeouted at %s in relation to %s;%u\n", h1, h2, host[h1].name, host[h2].name, host[h1].statsrelto[h2].totalflows.timeouted);
					fprintf(fp, "top;tpmrh%dh%d;Total packets matched at %s in relation to %s;%llu\n", h1, h2, host[h1].name, host[h2].name, host[h1].statsrelto[h2].totalpk.matched);
					fprintf(fp, "top;tplrh%dh%d;Total packets lost at %s in relation to %s;%llu (%.2f %%)\n", h1, h2, host[h1].name, host[h2].name, host[h1].statsrelto[h2].totalpk.loss, (float)(totalpk.count ? (host[h1].statsrelto[h2].totalpk.loss * 100) / (float) totalpk.count: totalpk.count));
868
869
870
871
					fprintf(fp, "\n");
				}
			}
		}
's avatar
committed
872
873
		fprintf(fp, "top;load;Network Load;%f Mbit/s\n", speed);
		fprintf(fp, "\n");
874
875
876
877
878
879
880
881
882
883
884
		fprintf(fp, "protocol;http;HTTP;%llu;%llu (%.2f %%)\n",       http.pkts,    http.lost,    PCT(http));    // HyperText Transfer Protocol
		fprintf(fp, "protocol;https;HTTPs;%llu;%llu (%.2f %%)\n",     https.pkts,   https.lost,   PCT(https));   // HTTP over SSL/TLS
		fprintf(fp, "protocol;ftp;FTP;%llu;%llu (%.2f %%)\n",         ftp.pkts,     ftp.lost,     PCT(ftp));     // File Transfer Protocol (control)
		fprintf(fp, "protocol;sftp;SFTP;%llu;%llu (%.2f %%)\n",       sftp.pkts,    sftp.lost,    PCT(sftp));    // Simple File Transfer Protocol
		fprintf(fp, "protocol;smtp;SMTP;%llu;%llu (%.2f %%)\n",       smtp.pkts,    smtp.lost,    PCT(smtp));    // Simple Mail Transfer Protocol
		fprintf(fp, "protocol;telnet;TELNET;%llu;%llu (%.2f %%)\n",   telnet.pkts,  telnet.lost,  PCT(telnet));  // Telecommunication Network
		fprintf(fp, "protocol;openvpn;OpenVPN;%llu;%llu (%.2f %%)\n", openvpn.pkts, openvpn.lost, PCT(openvpn)); // Full-featured SSL VPN solution
		fprintf(fp, "protocol;ssh;SSH;%llu;%llu (%.2f %%)\n",         ssh.pkts,     ssh.lost,     PCT(ssh));     // Secure Shell
		fprintf(fp, "protocol;dns;DNS;%llu;%llu (%.2f %%)\n",         dns.pkts,     dns.lost,     PCT(dns));     // Domain Name System
		fprintf(fp, "protocol;rtsp;RTSP;%llu;%llu (%.2f %%)\n",       rtsp.pkts,    rtsp.lost,    PCT(rtsp));    // Real Time Streaming Protocol
		fprintf(fp, "protocol;mapi;MAPI;%llu;%llu (%.2f %%)\n",       mapi.pkts,    mapi.lost,    PCT(mapi));    // Monitoring Application Programming Interface
's avatar
committed
885
886
887
888
		fclose(fp);

		// }}}

889
		// GUI - CGI - right frame {{{
890
		fp = fopen(TOP_FILENAME, "w");
891
		if(nodroppedpkts())
892
893
894
895
			sprintf(sensorstatslink, "<center><a href='#' id='link' onClick='toggleDisplay(document.getElementById(\\\"sensorstats\\\"),1)'>Sensors Statistics</a><img src='./led-red.gif'>");
		else
			sprintf(sensorstatslink, "<center><a href='#' id='link' onClick='toggleDisplay(document.getElementById(\\\"sensorstats\\\"),1)'>Sensors Statistics</a><img src='./led-green.gif'>");

896
		sensorstats = statstostr();
897
		sprintf(top_page_buf, top_page, sensorstats, sensorstatslink, TOP_FILENAME);
's avatar
committed
898
899
		fprintf(fp, "%s", top_page_buf);

900
901
902
903
904
905
906
907
908
		fprintf(fp, "<center> Total Packet Loss Ratio : %.2f %% (%llu pkts)<br>\n", (float) (totalpk.count ? (totalpk.loss * 100) / (float) totalpk.count : totalpk.count), totalpk.loss);
		fprintf(fp, "<center> Total Byte Loss Ratio : %.2f %% (%.2f Kbytes)<br><hr>\n", (float) (totalbytes.count ? (totalbytes.lost * 100) / (float) totalbytes.count :totalbytes.count) , (float) (totalbytes.lost / (float) 1024));
		fprintf(fp, "<center> Last Hour Packet Loss Ratio : %.2f %% (%llu pkts)<br>\n", (float) (onehour.pkcount ? (onehour.pkloss * 100) / (float) onehour.pkcount : onehour.pkcount), onehour.pkloss);
		fprintf(fp, "<center> Last 3 Hours Packet Loss Ratio : %.2f %% (%llu pkts)<br>\n", (float) ( threehour.pkcount ? (threehour.pkloss * 100) / (float) threehour.pkcount: threehour.pkcount), threehour.pkloss);
		fprintf(fp, "<center> Last 1 Day Packet Loss Ratio : %.2f %% (%llu pkts)<br>\n", (float) (oneday.pkcount ? (oneday.pkloss * 100) / (float) oneday.pkcount : oneday.pkcount), oneday.pkloss);
		fprintf(fp, "<center> Last 1 Week Packet Loss Ratio : %.2f %% (%llu pkts)<br>\n", (float) ( oneweek.pkcount ? (oneweek.pkloss * 100) / (float) oneweek.pkcount : oneweek.pkcount) , oneweek.pkloss);	
		fprintf(fp, "<center> Last 1 Month Packet Loss Ratio : %.2f %% (%llu pkts)<br>\n", (float) (onemonth.pkcount ? (onemonth.pkloss * 100) / (float) onemonth.pkcount : onemonth.pkcount), onemonth.pkloss);
		fprintf(fp, "<center> Last 1 Year Packet Loss Ratio : %.2f %% (%llu pkts)<br><hr>\n", (float) (oneyear.pkcount ? (oneyear.pkloss * 100) / (float) oneyear.pkcount : oneyear.pkcount), oneyear.pkloss);
//TODO			fprintf(fp, "<center> Last Hour Byte Loss Ratio : %.2f %% (%.2f Kbytes)<br><hr>\n", (float) (totalbytes.lost * 100) / (float) totalbytes.count, (float) (totalbytes.lost / (float) 1024));
909
910
		fprintf(fp, "<center> Total packets lost from <font color='#00FF00'><b>%s</b></font> : %llu (%.2f %%) <br>\n", host[0].name, host[0].statsdirto[1].totalpk.loss, (float)(totalpk.count ? (host[0].statsdirto[1].totalpk.loss * 100) / (float) totalpk.count: totalpk.count));
		fprintf(fp, "<center> Total packets lost from <font color=\"#0066FF\"><b>%s</b></font> : %llu (%.2f %%) <br><hr>\n", host[1].name, host[1].statsdirto[0].totalpk.loss, (float) (totalpk.count ? (host[1].statsdirto[0].totalpk.loss * 100) / (float) totalpk.count : totalpk.count));
911
		
's avatar
committed
912
913
		fprintf(fp, "<center> Total packets captured at host <font color=\"#00FF00\"><b>%s</b></font> : %llu <br>\n", host[0].name, host[0].stats.totalpk.count);
		fprintf(fp, "<center> Total packets captured at host <font color=\"#0066FF\"><b>%s</b></font> : %llu <br><hr>\n", host[1].name, host[1].stats.totalpk.count);
914
915
		fprintf(fp, "<center> Total packets matched at host <font color=\"#00FF00\"><b>%s</b></font> : %llu <br>\n", host[0].name, host[0].statsdirto[1].totalpk.matched);
		fprintf(fp, "<center> Total packets matched at host <font color=\"#0066FF\"><b>%s</b></font> : %llu <br><hr>\n", host[1].name, host[1].statsdirto[0].totalpk.matched);
916
917
918
919
		fprintf(fp, "<center><i><u>Network Load</u></i> : %f Mbit/s<br><hr>\n", speed);

		fprintf(fp, "</div><div id='protocolstable' ><center><table border=\"0\" width=75%% bgcolor=\"#999999\" cellpadding=\"1\" cellspacing=\"1\" class=style9>\n");		
		fprintf(fp, "<hr><tr bgcolor=\"#ffffff\" align=center><th>Protocol</th><th>Total pkts</th><th>Lost pkts</th></tr>\n");
's avatar
committed
920

921
922
923
924
925
926
927
928
929
930
931
		print_protocols(fp, "HTTP", http.pkts, http.lost);	// HyperText Transfer Protocol
		print_protocols(fp, "HTTPs", https.pkts, https.lost);	// HTTP over SSL/TLS
		print_protocols(fp, "FTP", ftp.pkts, ftp.lost);	// File Transfer Protocol (control)
		print_protocols(fp, "SFTP", sftp.pkts, sftp.lost);	// Simple File Transfer Protocol
		print_protocols(fp, "SMTP", smtp.pkts, smtp.lost);	// Simple Mail Transfer Protocol
		print_protocols(fp, "TELNET", telnet.pkts, telnet.lost);	// Telecommunication Network
		print_protocols(fp, "OpenVPN", openvpn.pkts, openvpn.lost);	// Full-featured SSL VPN solution
		print_protocols(fp, "SSH", ssh.pkts, ssh.lost);	// Secure Shell
		print_protocols(fp, "DNS", dns.pkts, dns.lost);	// Domain Name System
		print_protocols(fp, "RTSP", rtsp.pkts, rtsp.lost);	// Real Time Streaming Protocol
		print_protocols(fp, "MAPI", mapi.pkts, mapi.lost);	// Monitoring Application Programming Interface
's avatar
committed
932

933
		fprintf(fp, "</table></center></div></div></body></html>");
's avatar
committed
934
		fclose(fp);
935
		// }}}
's avatar
committed
936

937
		sleep(REFRESH_TIME);
's avatar
committed
938

939
	}
's avatar
committed
940
941
942
	return 0;
}

943
944


's avatar
committed
945
946
int print_flow(FILE * fp, flow_data * data, unsigned long long pkloss)
{
947
	char tmp[30], spaces[] = "                           ";
's avatar
committed
948
949
950
951
952
953
954
955
956
957
958
959
960
961
	if (fp == NULL)
		return -1;

	switch (data->ptcl) {
	case IPPROTO_TCP:
		fprintf(fp, "TCP ");
		break;
	case IPPROTO_UDP:
		fprintf(fp, "UDP ");
		break;
	default:
		fprintf(fp, "IP  ");
		break;
	}
962
963
964
965
966
967
968
	sprintf(tmp, "%d.%d.%d.%d:%d\t", data->saddr.byte1, data->saddr.byte2, data->saddr.byte3, data->saddr.byte4, data->sport);
	spaces[21-strlen(tmp)] = '\0';
	fprintf(fp, "src %d.%d.%d.%d:%d%s\t", data->saddr.byte1, data->saddr.byte2, data->saddr.byte3, data->saddr.byte4, data->sport, spaces);
	spaces[21-strlen(tmp)] = ' ';
	sprintf(tmp, "%d.%d.%d.%d:%d\t", data->daddr.byte1, data->daddr.byte2, data->daddr.byte3, data->daddr.byte4, data->dport);
	spaces[21-strlen(tmp)] = '\0';
	fprintf(fp, "dst %d.%d.%d.%d:%d%s\t", data->daddr.byte1, data->daddr.byte2, data->daddr.byte3, data->daddr.byte4, data->dport, spaces);
's avatar
committed
969
970
971
972
	if (pkloss == 0)
		fprintf(fp, "packets: %lld\t bytes: %lld\n", data->packets_count, data->bytes_count);
	else
		fprintf(fp, "lost packets: %lld\n", pkloss);
973

's avatar
committed
974
975
976
977
978
979
980
981
	return 1;
}


void print_protocols(FILE * fp, char *protocol, unsigned long long total_pkts, unsigned long long total_lost)
{

	if (total_pkts == 0)
's avatar
committed
982
983
		fprintf(fp, "<tr bgcolor=\"#ffffff\" align=center><td>%s</td><td>0</td><td>0 (0.00 %%)</td></tr>\n", protocol);
	else
's avatar
committed
984
		fprintf(fp, "<tr bgcolor=\"#ffffff\" align=center><td>%s</td><td>%llu</td><td>%llu (%.2f %%)</td></tr>\n", protocol, total_pkts, total_lost, (float) (total_lost * 100) / (float) total_pkts);
985
986
987
	return;
}

's avatar
committed
988
989
void terminate()
{
's avatar
test    
committed
990

991
992
	int i, h;
	int err_no = 0;
993
	struct hash_bucket *tmp;
's avatar
committed
994
	char error[512];
995

's avatar
committed
996
997
998
	if (WITH_NCURSES)
		endwin();				// end curses

's avatar
committed
999
	fprintf(stdout, "Packet Loss Application Terminated\n");
's avatar
test    
committed
1000

For faster browsing, not all history is shown. View entire blame