Commit 044c886c authored by 's avatar
Browse files

Bug fixes


git-svn-id: file:///home/svn/mapi/trunk@383 8d5bb341-7cf1-0310-8cf6-ba355fef3186
parent 2cf94a9c
......@@ -17,7 +17,6 @@
#include "abw_conf.h"
global_spec_t global_spec;
flow_spec_t *flow_spec[MAX_FLOWS];
int debug=1;
......@@ -32,17 +31,25 @@ int main(int argc, char *argv[])
struct timeval next, wait;
int subject_id, parameters_id;
/* Create first flow specification so that it can be filled-in
by command-line options */
/* Create first flow specification, subject and parameters so that they
can be filled-in by command-line options */
if ((flow_spec[0]=new_flow_spec())==NULL) {
if ((global_spec.flow_spec[0]=new_flow_spec())==NULL) {
fprintf(stderr, "%s: new_flow_spec() failed\n", __func__);
return -1;
}
if ((global_spec.subject[0]=new_subject())==NULL) {
fprintf(stderr, "%s: new_subject() failed\n", __func__);
return -1;
}
if ((global_spec.parameters[0]=new_parameters())==NULL) {
fprintf(stderr, "%s: new_parameters() failed\n", __func__);
return -1;
}
/* Read command line */
if (read_command_line(argc, argv, &global_spec, flow_spec)<0) {
if (read_command_line(argc, argv, &global_spec)<0) {
fprintf(stderr, "%s: read_command_line() failed\n", __func__);
return -1;
}
......@@ -50,7 +57,7 @@ int main(int argc, char *argv[])
/* Read configuration file */
if (global_spec.conf_filename) {
if (read_conf_file(&global_spec, flow_spec)<0) {
if (read_conf_file(&global_spec)<0) {
fprintf(stderr, "%s: read_conf_file() failed\n", __func__);
return -1;
}
......@@ -65,21 +72,20 @@ int main(int argc, char *argv[])
/* Check if specified values are within acceptable limits */
if (check_conf(&global_spec, flow_spec)<0) {
if (check_conf(&global_spec)<0) {
fprintf(stderr, "%s: check_conf() failed\n", __func__);
exit(-1);
}
/* Remaining command-line arguments should form a header filter string */
if (read_header_filter(argc, argv, &(flow_spec[0]->header_filter))<0) {
fprintf(stderr, "%s: read_header_filter() failed\n", __func__);
return -1;
}
/* Print configuration */
print_conf(&global_spec, flow_spec);
if (!global_spec.conf_filename && !global_spec.conf_from_mysql) {
if (read_header_filter(argc, argv,
&(global_spec.parameters[0]->header_filter))<0) {
fprintf(stderr, "%s: read_header_filter() failed\n", __func__);
return -1;
}
}
if (global_spec.db) {
if (abw_mysql_start(&global_spec)<0) {
......@@ -96,38 +102,49 @@ int main(int argc, char *argv[])
}
if (global_spec.conf_from_mysql) {
if (abw_mysql_read_conf(global_spec.mysql, flow_spec)<0) {
if (abw_mysql_read_conf(&global_spec)<0) {
fprintf(stderr, "%s: abw_mysql_read_conf() failed\n", __func__);
return -1;
}
}
if (global_spec.conf_to_mysql) {
if (abw_mysql_write_conf(&global_spec, flow_spec)<0) {
if (abw_mysql_write_conf(&global_spec)<0) {
fprintf(stderr, "%s: abw_mysql_write_conf() failed\n", __func__);
return -1;
}
}
/*
* Go over all specified flows and for each flow:
* - find its subject and parameters in database or add them
* - go over all its protocols and for each protocol:
* - create a MAPI flow
* - apply MAPI functions to this flow according to flow spec.
* - connect MAPI to this flow
*/
/* Print configuration */
print_conf(&global_spec);
/* If we should not print results (just configuration operations
done above were requested) then finish. */
if (global_spec.no_results) {
if (global_spec.db) {
mysql_close(global_spec.mysql);
mysql_library_end();
}
return 0;
}
/* Go over all specified flows */
pp=flow_spec;
pp=global_spec.flow_spec;
i=0;
while (i<MAX_FLOWS && *pp) {
p=*pp;
/* If we should read from or write to MySQL, find subject and
parameters of this flow in MySQL or insert them */
if (global_spec.db) {
/* Find subject of this flow in tSubject or INSERT it */
if ((subject_id=abw_mysql_get_subject_id(&global_spec, p))<0) {
if ((subject_id=abw_mysql_get_subject_id(&global_spec, p->subject))<0) {
fprintf(stderr, "%s: abw_mysql_get_subject_id() failed\n",
__func__);
return -1;
......@@ -135,7 +152,7 @@ int main(int argc, char *argv[])
/* Find parameters of this flow in tParameters or INSERT it */
if ((parameters_id=
abw_mysql_get_parameters_id(&global_spec, p))<0) {
abw_mysql_get_parameters_id(&global_spec, p->parameters))<0) {
fprintf(stderr, "%s: abw_mysql_get_parameters_id() failed\n",
__func__);
return -1;
......@@ -153,6 +170,9 @@ int main(int argc, char *argv[])
return -1;
}
/* If we should do measurement, then create a MAPI flow for
each protocol, apply monitoring functions to it and connect to it */
if (!(global_spec.no_measure)) {
j=0;
......@@ -175,19 +195,19 @@ int main(int argc, char *argv[])
}
strcpy(q->protocol, p->protocols_array[j]);
if (protocol_filter(p->header_filter, q->protocol,
if (protocol_filter(p->parameters->header_filter, q->protocol,
&(q->header_filter))<0) {
fprintf(stderr, "%s: protocols_filter() failed\n", __func__);
return -1;
}
}
else
q->header_filter=p->header_filter;
printf("p->header_filter: %s, q->protocol: %s, q->header_filter: %s\n", p->header_filter, q->protocol, q->header_filter);
q->header_filter=p->parameters->header_filter;
printf("p->parameters->header_filter: %s, q->protocol: %s, q->header_filter: %s\n", p->parameters->header_filter, q->protocol, q->header_filter);
if ((q->fd=mapi_create_flow(p->device))<0) {
if ((q->fd=mapi_create_flow(p->subject->interface))<0) {
fprintf(stderr, "%s: mapi_create_flow(%s) failed\n", __func__,
p->device);
p->subject->interface);
return -1;
}
......@@ -203,19 +223,21 @@ int main(int argc, char *argv[])
}
}
if (p->sau_mode == 'd' && p->sau_packet_threshold != 1) {
if (p->parameters->sau_mode == 'd' &&
p->parameters->sau_threshold != 1) {
if ((q->sample_fid=
mapi_apply_function(q->fd, "SAMPLE", p->sau_packet_threshold),
PERIODIC)<0) {
mapi_apply_function(q->fd, "SAMPLE",
p->parameters->sau_threshold), PERIODIC)<0) {
fprintf(stderr, "%s: SAMPLE for flow %d failed\n",
__func__, i);
return -1;
}
}
else if (p->sau_mode == 'p' && p->sau_pass_probability != 1) {
else if (p->parameters->sau_mode == 'p' &&
p->parameters->sau_threshold != 1) {
if ((q->sample_fid=
mapi_apply_function(q->fd, "SAMPLE",
(p->sau_pass_probability)*100),
(p->parameters->sau_threshold)*100),
PROBABILISTIC)<0) {
fprintf(stderr, "%s: SAMPLE for flow %d failed\n",
__func__, i);
......@@ -223,10 +245,10 @@ int main(int argc, char *argv[])
}
}
if (p->payload_strings[0]) {
if (p->parameters->payload_strings[0]) {
if ((q->str_search_fid=
mapi_apply_function(q->fd, "STR_SEARCH",
p->payload_strings[0], 0, 0))<0) {
p->parameters->payload_strings[0], 0, 0))<0) {
fprintf(stderr, "%s: STR_SEARCH for flow %d failed\n",
__func__, i);
return -1;
......@@ -256,7 +278,11 @@ int main(int argc, char *argv[])
j++;
} /* while (j<MAX_PROTOCOLS && p->protocols_array[j]) */
} /* if (!(global_spec.no_measure)) */
else {
/* If we should not do measurement then read already
measured results from MySQL and print out */
else if (!(global_spec.no_results)) {
values_int_t *values;
char *characteristics[MAX_CHARACTERISTICS];
......@@ -279,6 +305,9 @@ int main(int argc, char *argv[])
i++;
} /* while (i<MAX_FLOWS && *pp) */
/* If we should do measurement, then periodically get results from
opened MAPI flows. */
if (!(global_spec.no_measure)) {
while (1) {
if (gettimeofday(&tm, &tz)<0) {
......@@ -286,7 +315,7 @@ int main(int argc, char *argv[])
exit(-1);
}
pp=flow_spec;
pp=global_spec.flow_spec;
i=0;
while (i<MAX_FLOWS && *pp) {
......@@ -357,7 +386,8 @@ int main(int argc, char *argv[])
/* TODO: wait until next checkpoint (not a fixed delay) of
the flow whose checkpoint is earliest */
abw_next_timestamp(&(flow_spec[0]->interval), &next, &wait);
abw_next_timestamp(&(global_spec.flow_spec[0]->parameters->interval),
&next, &wait);
/* printf("next.tv_sec: %d, next.tv_usec: %d, wait.tv_sec: %d, wait.tv_usec: %d\n", (int)(next.tv_sec), (int)(next.tv_usec), (int)(wait.tv_sec), (int)(wait.tv_usec)); */
usleep(wait.tv_sec * 1000000 + wait.tv_usec);
......
......@@ -7,51 +7,68 @@ db=abw
user=abw
passwd=lab10
# [node] section specifies link-ends where the measurement should be done.
# You MUST specify three things: 1) id, 2) hostname or ip_address and 3) device.
# Multiple [node] sections CAN be specified for several measurements done on
# diferent link-ends. You CAN optionally specify link_mbps. If you do not
# specify link_mbps, default is 1000.
# [interface] section specifies link-ends where the measurement should be done.
# You MUST specify:
# 1) id
# 2) hostname or ip
# 3) interface
# You CAN optionally specify link_mbps and direction. Default link_mbps is
# 1000 and default direction is in. Multiple [subject] sections CAN be
# specified for several measurements done on diferent link-ends.
[node]
[subject]
id=1
hostname=jra1-1.cesnet.cz
device=/dev/dag0
# link_mbps is used by abw_print, but not by abw_measure
interface=/dev/dag0
link_mbps=1000
[node]
[subject]
id=2
hostname=jra1-1.cesnet.cz
device=eth0
# [parameters] section specifies measurement parameters. You MUST specify two
# things: 1) id and 2) node_id which MUST refer to id of the [node] section
# where the measurement is done. You CAN specify more parameters (and in most
# cases you SHOULD): 1) header_filter (in libpcap format, default is no header
# filtering), 2) sau_mode (as d, b or p, default is d), 3) sau_threshold
# (default is 1), 4) payload_string (can be specified multiple times, default
# is no payload searching), 5) protocols (can be any combination of all, tcp,
# udp, multicast and ipv6, default is all), 6) interval_sec (default is 1),
# 7) interval_usec (default is 0), 8) start_time_string (default is
# 01.01.1970-01:00:00) and 9) end_time_string (default is 01.01.2038-01:00:00).
interface=eth0
# [parameters] section specifies measurement parameters. You MUST specify id.
# You CAN specify more parameters (and in most cases you SHOULD):
# 1) header_filter (in libpcap format, default is no header filtering),
# 2) sau_mode (as d, b or p, default is d)
# 3) sau_threshold (default is 1 for d, 3000 for b and 0.5 for p)
# 4) payload_string (can be specified multiple times, default is no payload
# searching),
# 5) interval_sec (default is 1) and interval_usec (default is 0)
# Values CANNOT include spaces except for header_filter, which CAN include
# spaces. Multiple [parameters] sections CAN be specified for several
# measurements done on the same or on different link-ends.
[parameters]
id=1
node_id=1
header_filter=src net 195.113.0.0/16
sau_mode=d
sau_threshold=1
sau_threshold=2
# payload_string=virus
protocols=all,tcp,udp,ipv6,multicast
interval_sec=1
interval_sec=3
#interval_usec=100000
[parameters]
id=2
# [measurement] section specifies one measurement to be done on some subject
# with some parameters. You MUST specify:
# 1) subject_id
# 2) parameters_id
# You CAN specify protocols (can be any combination of all, tcp, udp, multicast
# and ipv6, default is all), start_time_string (default is 01.01.1970-01:00:00)
# end_time_string (default is 01.01.2038-01:00:00) and id. Multiple
# [measurement] sections CAN be specified.
[measurement]
id=1
subject_id=1
parameters_id=1
start_time_string=01.01.2005-00:00:00
end_time_string=31.12.2037-23:59:59
protocols=all,tcp,udp,ipv6,multicast
[parameters]
[measurement]
id=2
node_id=2
subject_id=2
parameters_id=2
......@@ -40,51 +40,61 @@ typedef struct {
unsigned old_byte_counter; /* result of BYTE_COUNTER */
} flow_run_t;
/*
* Specified and computed properties of one flow as given on a command-line
* or in a configuration file. One such flow can later imply using multiple
* MAPI flows, one for each protocol to be monitored.
*/
typedef struct {
int id;
char *hostname;
char *device;
char *ip;
char *interface;
char *direction;
int link_mbps;
} subject_t;
/* Header filtering */
typedef struct {
int id;
char *header_filter;
/* Sampling */
char sau_mode; /* mode entered by user as d, b or p */
int sau_mode_encoded; /* mode for monitoring adapter */
unsigned int sau_threshold; /* sampling threshold for monitoring adapter */
int sau_packet_threshold; /* sampling threshold entered by user for d mode*/
int sau_byte_threshold; /* sampling threshold entered by user for b mode*/
float sau_pass_probability; /* sampling probability entered by user for p
mode */
/* Payload searching */
char sau_mode; /* d, b or p */
double sau_threshold; /* meaning is specific to sau_mode */
char *payload_strings[MAX_PAYLOAD_STRINGS];
struct timeval interval;
/* Other parameters */
/* Alternative representations, conversion done in check_conf() */
int sau_mode_encoded;
/* int sau_packet_threshold;
int sau_byte_threshold;
float sau_pass_probability; */
} parameters_t;
/*
* Specification of one flow. Can be read from command-line, configuration
* file or tMeasurement table. One such flow can imply using multiple MAPI
* flows, one for each protocol to be monitored.
*/
typedef struct {
int subject_id; /* id field in tSubject table */
int parameters_id; /* id field in tParameters table */
subject_t *subject;
parameters_t *parameters;
time_t start_time_timestamp;
time_t end_time_timestamp;
char *protocols;
char *protocols_array[MAX_PROTOCOLS];
struct timeval interval;
/* Alternative representations, conversion done in check_conf() */
char *start_time_string;
char *end_time_string;
struct tm start_time_tm;
struct tm end_time_tm;
time_t start_time_timestamp;
time_t end_time_timestamp;
int link_mbps;
/* Runtime flows created for all characteristics of this flow specification */
flow_run_t *flow_run[MAX_PROTOCOLS];
/* Alternative representation, conversion done in split_protocols() */
char *protocols_array[MAX_PROTOCOLS];
int subject_id; /* id field in tSubject table */
int parameters_id; /* id field in tParameters table */
/* Runtime flows created for protocols of this flow specification */
flow_run_t *flow_run[MAX_PROTOCOLS];
} flow_spec_t;
/* Global configuration */
typedef struct {
/* Following configuration can be read from command-line */
char *conf_filename; /* read flow configuration from this file */
int conf_from_mysql; /* if non-zero read flow configuration from MySQL */
int conf_to_mysql; /* if non-zero write flow configuration to MySQL */
......@@ -92,17 +102,31 @@ typedef struct {
configuration in MySQL */
int no_measure; /* if non-zero do not do measurements (only process
configuration or print results) */
int no_results; /* if non-zero do not print results */
int no_stdout; /* if non-zero do not print results to stdout */
/* Following configuration can be read from command-line or conf. file */
char *db; /* MySQL database name, if NULL do not insert results
into MySQL database */
char *user; /* username for MySQL connection */
char *passwd; /* password for MySQL connection */
/* Following configuration is maintained as runtime variables */
MYSQL *mysql; /* MySQL connection handler */
char *hostname; /* local hostname including domain name */
flow_spec_t *flow_spec[MAX_FLOWS];
subject_t *subject[MAX_FLOWS];
parameters_t *parameters[MAX_FLOWS];
} global_spec_t;
flow_spec_t *new_flow_spec(void);
subject_t *new_subject(void);
parameters_t *new_parameters(void);
flow_run_t *new_flow_run(void);
int split_protocols(char *protocols, char *protocols_array[]);
......
......@@ -16,22 +16,48 @@ flow_spec_t *new_flow_spec(void) {
memset(p, 0, sizeof(flow_spec_t));
p->device=DEFAULT_DEVICE;
p->header_filter=NULL;
p->sau_mode='d';
p->sau_packet_threshold=1;
p->sau_byte_threshold=3000;
p->sau_pass_probability=0.5;
p->protocols=NULL;
p->interval.tv_sec=1;
p->interval.tv_usec=0;
p->start_time_string=DEFAULT_START_TIME_STRING;
p->end_time_string=DEFAULT_END_TIME_STRING;
p->link_mbps=DEFAULT_LINK_MBPS;
return p;
} /* new_flow_spec() */
subject_t *new_subject(void) {
subject_t *p;
if ((p=malloc(sizeof(subject_t)))==NULL) {
fprintf(stderr, "%s: malloc() failed\n", __func__);
return NULL;
}
memset(p, 0, sizeof(subject_t));
p->interface=DEFAULT_DEVICE;
p->link_mbps=DEFAULT_LINK_MBPS;
return p;
} /* new_subject() */
parameters_t *new_parameters(void) {
parameters_t *p;
if ((p=malloc(sizeof(parameters_t)))==NULL) {
fprintf(stderr, "%s: malloc() failed\n", __func__);
return NULL;
}
memset(p, 0, sizeof(parameters_t));
p->sau_mode='d';
p->sau_threshold=1;
/* p->sau_byte_threshold=3000;
p->sau_pass_probability=0.5; */
p->interval.tv_sec=1;
p->interval.tv_usec=0;
return p;
} /* new_parameters() */
flow_run_t *new_flow_run(void) {
flow_run_t *p;
......
This diff is collapsed.
......@@ -20,15 +20,18 @@
/* Long option codes */
enum {
LO_HOSTNAME, LO_DEVICE, LO_SAU_MODE, LO_SAU_THRESHOLD, LO_PAYLOAD_STRING,
LO_HOSTNAME, LO_IP, LO_INTERFACE, LO_DIRECTION, LO_SAU_MODE,
LO_SAU_THRESHOLD, LO_PAYLOAD_STRING,
LO_PROTOCOLS, LO_INTERVAL, LO_START_TIME, LO_END_TIME, LO_LINK_MBPS,
LO_CONF_FILENAME, LO_CONF_FROM_MYSQL, LO_CONF_TO_MYSQL, LO_CLEAR_CONF,
LO_NO_MEASURE, LO_NO_STDOUT, LO_DB, LO_USER, LO_PASSWD };
LO_NO_MEASURE, LO_NO_RESULTS, LO_NO_STDOUT, LO_DB, LO_USER, LO_PASSWD };
/* Long option names and argument types */
static const struct option long_options[] = {
{ "hostname", required_argument, 0, LO_HOSTNAME },
{ "device", required_argument, 0, LO_DEVICE },
{ "ip", required_argument, 0, LO_IP },
{ "interface", required_argument, 0, LO_INTERFACE },
{ "direction", required_argument, 0, LO_DIRECTION },
{ "sau_mode", required_argument, 0, LO_SAU_MODE },
{ "sau_threshold", required_argument, 0, LO_SAU_THRESHOLD },
{ "payload_string", required_argument, 0, LO_PAYLOAD_STRING },
......@@ -42,6 +45,7 @@ static const struct option long_options[] = {
{ "conf_to_mysql", no_argument, 0, LO_CONF_TO_MYSQL },
{ "clear_conf", no_argument, 0, LO_CLEAR_CONF },
{ "no_measure", no_argument, 0, LO_NO_MEASURE },
{ "no_results", no_argument, 0, LO_NO_RESULTS },
{ "no_stdout", no_argument, 0, LO_NO_STDOUT },
{ "db", required_argument, 0, LO_DB },
{ "username", required_argument, 0, LO_USER },
......@@ -68,14 +72,13 @@ typedef enum {
void usage();
int read_command_line(int argc, char *argv[], global_spec_t *global_spec,
flow_spec_t **flow_spec);
int read_command_line(int argc, char *argv[], global_spec_t *global_spec);
int read_conf_file(global_spec_t *global_spec, flow_spec_t **flow_spec);
int read_conf_file(global_spec_t *global_spec);
int check_conf(global_spec_t *global_spec, flow_spec_t **flow_spec);
int check_conf(global_spec_t *global_spec);
void print_conf(global_spec_t *global_spec, flow_spec_t **flow_spec);
int print_conf(global_spec_t *global_spec);
int read_header_filter(int argc, char *argv[], char **p);
......
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <mysql/mysql.h>
......@@ -35,15 +36,16 @@ int abw_mysql_start(global_spec_t *global_spec) {
return 0;
} /* abw_mysql_start() */
int abw_mysql_get_subject_id(global_spec_t *global_spec, flow_spec_t *p) {
int abw_mysql_get_subject_id(global_spec_t *global_spec, subject_t *q) {
char query[MAX_QUERY+1];
MYSQL_RES *mysql_res;
MYSQL_ROW mysql_row;
int num;
int subject_id;
if (global_spec==NULL || p==NULL ||
(p->hostname==NULL && global_spec->hostname==NULL) ||
p->device==NULL) {
if (global_spec==NULL || q==NULL ||
(q->hostname==NULL && global_spec->hostname==NULL) ||
q->interface==NULL) {
fprintf(stderr, "%s: some required arguments were not supplied\n",
__func__);
return -1;
......@@ -55,14 +57,7 @@ int abw_mysql_get_subject_id(global_spec_t *global_spec, flow_spec_t *p) {
search hostname and device of monitoring card, direction is included
in the chosen monitoring card (but in future more ports on the card
can be used) */
strcpy(query, "SELECT * FROM tSubject WHERE hostname='");
if (p->hostname)
strcat(query, p->hostname);
else
strcat(query, global_spec->hostname);
strcat(query, "' AND interface='");