You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

3644 lines
116 KiB

# --- SDE-COPYRIGHT-NOTE-BEGIN ---
# This copyright note is auto-generated by ./scripts/Create-CopyPatch.
#
# Filename: package/.../sancp/sancp-1.6.1-stable-prelude-3.diff
# Copyright (C) 2007 The OpenSDE Project
#
# More information can be found in the files COPYING and README.
#
# This patch file is dual-licensed. It is available under the license the
# patched project is licensed under, as long as it is an OpenSource license
# as defined at http://www.opensource.org/ (e.g. BSD, X11) or under the terms
# of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
# --- SDE-COPYRIGHT-NOTE-END ---
diff -ruN sancp-1.6.1-stable.vanilla/Makefile sancp-1.6.1-stable/Makefile
--- sancp-1.6.1-stable.vanilla/Makefile 2007-07-07 00:46:11.000000000 +0200
+++ sancp-1.6.1-stable/Makefile 2007-07-24 13:44:01.000000000 +0200
@@ -9,7 +9,7 @@
# LINUX and BSD CFLAGS
-CFLAGS = -O3 -I/usr/include/pcap -I/usr/local/include/pcap -I./ -L/usr/lib/libsocket.so -g -L/opt/csw/lib -ggdb
+CFLAGS = -g -O3 -I/usr/include/pcap -I/usr/local/include/pcap -I./ -L/usr/lib/libsocket.so -g -L/opt/csw/lib -ggdb `libprelude-config --cflags`
# LINUX LFLAGS
LFLAGS = -lresolv -lnsl -lpcap -L/usr/lib/libpcap.so.0.6.2
@@ -41,10 +41,10 @@
bsd :
@(echo "#define PLATFORM_BSD" > platform.h)
@make final
- g++ -Wall $(BFLAGS) $(CFLAGS) -o sancp sancp.o misc_functs.o check_packet.o statefull_logging.o build_acl.o apply_rule.o decode.o pcap_functions.o pcapFileHandle.o fileHandle.o MemoryPool.o permissions.o outputFileHandle.o help.o
+ g++ -Wall $(BFLAGS) $(CFLAGS) -o sancp sancp.o misc_functs.o check_packet.o statefull_logging.o build_acl.o apply_rule.o decode.o pcap_functions.o pcapFileHandle.o fileHandle.o MemoryPool.o permissions.o outputFileHandle.o help.o `libprelude-config --libs` `libprelude-config --ldflags`
linux :
@(echo "#define PLATFORM_LINUX" > platform.h)
@make final
- g++ -Wall $(LFLAGS) $(CFLAGS) -o sancp sancp.o misc_functs.o check_packet.o statefull_logging.o build_acl.o apply_rule.o decode.o pcap_functions.o pcapFileHandle.o fileHandle.o MemoryPool.o permissions.o outputFileHandle.o help.o
+ g++ -Wall $(LFLAGS) $(CFLAGS) -o sancp sancp.o misc_functs.o check_packet.o statefull_logging.o build_acl.o apply_rule.o decode.o pcap_functions.o pcapFileHandle.o fileHandle.o MemoryPool.o permissions.o outputFileHandle.o help.o `libprelude-config --libs` `libprelude-config --ldflags`
diff -ruN sancp-1.6.1-stable.vanilla/apply_rule.cc sancp-1.6.1-stable/apply_rule.cc
--- sancp-1.6.1-stable.vanilla/apply_rule.cc 2007-07-05 18:12:20.000000000 +0200
+++ sancp-1.6.1-stable/apply_rule.cc 2007-07-24 13:44:01.000000000 +0200
@@ -47,6 +47,12 @@
tc->tcplag=myacl->tcplag;
tc->status=myacl->status;
tc->rid=myacl->rid;
+ tc->prelude_impact_severity=myacl->prelude_impact_severity;
+ tc->prelude_impact_completion=myacl->prelude_impact_completion;
+ tc->prelude_impact_type=myacl->prelude_impact_type;
+ tc->prelude_confidence_rating=myacl->prelude_confidence_rating;
+
+
if(myacl->pmode==OMODE_UNIQ)
{
@@ -112,6 +118,10 @@
nc->rgid=myacl->rgid;
nc->zone=myacl->zone;
nc->node=myacl->node;
+ nc->prelude_impact_severity=myacl->prelude_impact_severity;
+ nc->prelude_impact_completion=myacl->prelude_impact_completion;
+ nc->prelude_impact_type=myacl->prelude_impact_type;
+ nc->prelude_confidence_rating=myacl->prelude_confidence_rating;
myacl->ctr++;
return;
}
@@ -130,6 +140,10 @@
nc->timeout=gVars.default_timeout;
nc->tcplag=gVars.default_tcplag;
nc->node=gVars.default_node;
+ nc->prelude_impact_severity=gVars.prelude_impact_severity;
+ nc->prelude_impact_completion=gVars.prelude_impact_completion;
+ nc->prelude_impact_type=gVars.prelude_impact_type;
+ nc->prelude_confidence_rating=gVars.prelude_confidence_rating;
gVars.default_ctr++;
#ifdef DEBUG
printf("Setting stats: %d pcap: %d realtime: %d limit: %d timeout: %d tcplag: %d\n", nc->stats, nc->pcap, nc->realtime, nc->limit, nc->timeout, nc->tcplag);
diff -ruN sancp-1.6.1-stable.vanilla/build_acl.cc sancp-1.6.1-stable/build_acl.cc
--- sancp-1.6.1-stable.vanilla/build_acl.cc 2007-07-05 18:12:20.000000000 +0200
+++ sancp-1.6.1-stable/build_acl.cc 2007-07-24 13:44:01.000000000 +0200
@@ -1168,6 +1168,62 @@
fprintf(stdout,"Didn't set default for %s to %s\n",tok,tmp);
#endif
}
+ if(strcmp(tok,"prelude_impact_severity")==0)
+ {
+ if((tmp = get_tok(&rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, prelude_impact_severity specified but none provided, using prelude_impact_severity %s\n",PRELUDE_IMPACT_SEVERITY);
+ free(rule);
+ return;
+ }
+ gVars.prelude_impact_severity = strdup(tmp);
+ free(rule);
+ }
+ if(strcmp(tok,"prelude_impact_completion")==0)
+ {
+ if((tmp = get_tok(&rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, prelude_impact_completion specified but none provided, using prelude_impact_completion %s\n",PRELUDE_IMPACT_COMPLETION);
+ free(rule);
+ return;
+ }
+ gVars.prelude_impact_completion = strdup(tmp);
+ free(rule);
+ }
+ if(strcmp(tok,"prelude_impact_type")==0)
+ {
+ if((tmp = get_tok(&rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, prelude_impact_type specified but none provided, using prelude_impact_type %s\n",PRELUDE_IMPACT_TYPE);
+ free(rule);
+ return;
+ }
+ gVars.prelude_impact_type = strdup(tmp);
+ free(rule);
+ }
+ if(strcmp(tok,"prelude_confidence_rating")==0)
+ {
+ if((tmp = get_tok(&rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, prelude_confidence_rating specified but none provided, using prelude_confidence_rating %s\n",PRELUDE_CONFIDENCE_RATING);
+ free(rule);
+ return;
+ }
+ gVars.prelude_confidence_rating = strdup(tmp);
+ free(rule);
+ }
+ if(strcmp(tok,"prelude_profile")==0)
+ {
+ if((tmp = get_tok(&rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, prelude_profile specified but none provided, using prelude_profile %s\n",PRELUDE_PROFILE);
+ free(rule);
+ return;
+ }
+ gVars.prelude_profile = strdup(tmp);
+ free(rule);
+ }
+
}
void parse_var(char *c_rule, char *accept)
@@ -1426,6 +1482,10 @@
}else{
n_acl->fH = 0;
}
+ n_acl->prelude_impact_severity = gVars.prelude_impact_severity;
+ n_acl->prelude_impact_completion = gVars.prelude_impact_completion;
+ n_acl->prelude_impact_type = gVars.prelude_impact_type;
+ n_acl->prelude_confidence_rating = gVars.prelude_confidence_rating;
// FIELD 0 - required - Get the h_proto
n_acl->h_proto_h = 0xFFFF;
@@ -2061,6 +2121,46 @@
n_acl->retro = true;
continue;
}
+ if(strcmp(tok,"severity")==0)
+ {
+ if((tmp = get_tok(rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, severity specified but no option provided%s\n",rule);
+ return;
+ }
+ n_acl->prelude_impact_severity = strdup(tmp);
+ continue;
+ }
+ if(strcmp(tok,"completion")==0)
+ {
+ if((tmp = get_tok(rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, completion specified but no option provided%s\n",rule);
+ return;
+ }
+ n_acl->prelude_impact_completion = strdup(tmp);
+ continue;
+ }
+ if(strcmp(tok,"type")==0)
+ {
+ if((tmp = get_tok(rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, type specified but no option provided%s\n",rule);
+ return;
+ }
+ n_acl->prelude_impact_type = strdup(tmp);
+ continue;
+ }
+ if(strcmp(tok,"confidence")==0)
+ {
+ if((tmp = get_tok(rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, confidence specified but no option provided%s\n",rule);
+ return;
+ }
+ n_acl->prelude_confidence_rating = strdup(tmp);
+ continue;
+ }
syslog(LOG_ERR,"Skipping, invalid option in rule: %s %s\n", tok,*rules);
return;
}
diff -ruN sancp-1.6.1-stable.vanilla/build_acl.cc~ sancp-1.6.1-stable/build_acl.cc~
--- sancp-1.6.1-stable.vanilla/build_acl.cc~ 1970-01-01 01:00:00.000000000 +0100
+++ sancp-1.6.1-stable/build_acl.cc~ 2007-07-05 18:12:20.000000000 +0200
@@ -0,0 +1,2648 @@
+#ifndef SANCP_H
+#include "sancp.h"
+#endif
+//#define DEBUG
+/**************************************************************************
+ **SA Network Connection Profiler [sancp] - A TCP/IP statistical/collection tool
+ * ************************************************************************
+ * * Copyright (C) 2003 John Curry <john.curry@metre.net>
+ * *
+ * * This program is distributed under the terms of version 1.0 of the
+ * * Q Public License. See LICENSE.QPL for further details.
+ * *
+ * * This program is distributed in the hope that it will be useful,
+ * * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * *
+ * ***********************************************************************/
+
+void license();
+void version();
+struct acl *tacl_head=NULL, *tacl_tail=NULL;
+struct t_ports *tports[MAX_IP_PROTO];
+void set_bpf_filter( char *);
+char * get_tok(char **rule, const char * accept);
+void parse_default(char *rule, char *accept);
+char * get_next_tok(char **rule, const char *delimiters);
+char *rev_search_vars(char *key, struct vars *var_head, int );
+
+int fgetcline (char **buf, int size, FILE *fp){
+ int len;
+ int c=0;
+ if( fp== NULL){
+ syslog(LOG_ERR,"Invalid FILE handle\n");
+ return -1;
+ }
+ if(feof(fp)){
+ syslog(LOG_ERR,"Early END OF FILE\n");
+ return -1;
+ }
+ if (*buf == NULL){
+ if( size == 0)
+ size=BUFSIZ;
+ if((*buf = (char *)calloc(1,size)) == NULL){
+ syslog(LOG_ERR,"Out of memory\n");
+ return -1;
+ }
+ }
+ len=0;
+// Get characters until EOF or ';'
+ while (((c = getc(fp)) != EOF) && c!='\n' && c!='\r'){
+ if(c=='\\'){
+ if((c = getc(fp))==EOF){
+ break;
+ }
+ if(c=='\n'){
+ c=' ';
+ }else{
+ ungetc(c,fp);
+ c='\\';
+ }
+ }
+ if(c == '#'){
+ // if comment mark, FF to end of line
+ while( (c = getc(fp))!= EOF && c !='\n');
+ //if(c=='\n'){ break;}
+ //if(c==EOF){ break; }
+ break;
+ }
+ if(len+1 >= size) {
+ if(( *buf = (char *)realloc(*buf, size += BUFSIZ))==NULL){
+ syslog(LOG_ERR,"Out of memory\n");
+ free(*buf);
+ return -1;
+ }
+ }
+ if(c == ',' || c == '=' ) {
+ c = ' ';
+ }
+ //
+ // Make everything lower case for now
+ //
+ if(!(len==0 && (c==' ' || c=='\t')))
+ (*buf)[len++]=tolower(c);
+
+ if(c == '\t' || c == ' ' ){
+ while( (c=fgetc(fp))!= EOF && c!='\n' && (c=='\t' || c==' '));
+ //while( (c=fgetc(fp))!= EOF && c!='\n' && (c=='\t' || c==' ' || c==',' || c=='='));
+ if(c=='\n'|| c==EOF){ break; }
+ // Trunicate comments
+ if(c=='#') (*buf)[len]='\0';
+ ungetc(c,fp);
+ // If we ran into a '#' sign, then just turn the last \t or space into a null.
+ }
+ }
+ if (len == 0 && c == EOF){
+ if(*buf!=NULL)
+ free(*buf);
+ return -1;
+ }
+ if(len>0 && ((*buf)[len-1]==' ' || (*buf)[len-1]=='\t')){
+ (*buf)[len-1]='\0';
+ return len-1;
+ }else{
+ (*buf)[len++]='\0';
+ return len;
+ }
+}
+
+void parse_args(int argc, char *argv[])
+{
+ extern struct gvars gVars;
+ u_int64_t num;
+ char *ftmp=0;
+ //int ctr=0;
+ for(int ctr=1; ctr < argc; ctr++)
+ {
+ if(strcmp(argv[ctr],"--schemas")==0)
+ {
+ // once we finished reading the config, we will print the schemas and exit
+ gVars.print_schemas = 1;
+ }else{
+ if(strcmp(argv[ctr],"--shift")==0)
+ {
+ // enable internal 2 byte shifting the packet read from file
+ // 'any' interface
+ gVars.shift = 1;
+ }else{
+ if(strcmp(argv[ctr],"-K")==0 || strcmp(argv[ctr],"--console")==0)
+ {
+ // enable console mode - log realtimes to stdout
+ gVars.console_mode = 1;
+
+ }else{
+ if(strcmp(argv[ctr],"-D")==0 || strcmp(argv[ctr],"--daemon")==0)
+ {
+ // enable daemon mode
+ gVars.daemon_mode = 1;
+ openlog(NAME,LOG_CONS,gVars.log_facility);
+ }else{
+ if(strcmp(argv[ctr],"-C")==0 || strcmp(argv[ctr],"--last_cnxid")==0)
+ {
+ // set last connection id to use - ~~~! Need to supply -d argument first !~~~
+ if( ctr < argc-1 ){
+ ctr++;
+ ftmp=argv[ctr];
+ num = (u_int64_t) strtoll(argv[ctr],&ftmp,0);
+ if(argv[ctr]==ftmp)
+ {
+ syslog(LOG_ERR,"Format error, invalid last_cnxid: %s, using cnxid %llu\n",argv[ctr],(long long unsigned)gVars.cnx_id);
+ }else
+ manage_cid(0);
+ if(gVars.cnx_id>num){
+ syslog(LOG_ERR,"cnxid provided (%llu) is less than 64bit cnxid in the '.cnxid' cache file, using cnxid %llu from cache instead\n",num,(long long unsigned) gVars.cnx_id);
+ }else{
+ syslog(LOG_ERR,"Using cnxid provided (%llu) rather than the last cnxid in the '.cnxid' cache file (%llu)\n",num,(long long unsigned) gVars.cnx_id);
+ // Save the new cnx_id
+ gVars.cnx_id=num;
+ manage_cid(1);
+ }
+ }else{
+ syslog(LOG_ERR,"No cnxid provided with -C/--last_cnxid option\n");
+ exit(0);
+ }
+ }else{
+ if(strcmp(argv[ctr],"-i")==0)
+ {
+ // Set device name
+ if( ctr < argc-1 ){
+ if(gVars.default_device){ free(gVars.default_device); } ctr++;
+ if( (gVars.default_device = (char *)calloc(strlen(argv[ctr])+ 1,1) ) ==NULL){
+ syslog(LOG_ERR,"Unable to allocate memory for -i option\n");
+ exit(0);
+ }
+ bcopy(argv[ctr],gVars.default_device,strlen(argv[ctr]));
+ gVars.shift=0; // disable shift (only needed for 'any' interface)
+ if(strstr(gVars.default_device,DEFAULT_DEVICE))
+ gVars.shift=1;
+ }else{
+ syslog(LOG_ERR,"No device name provided with -i option\n");
+ exit(0);
+ }
+ }else{
+ if(strcmp(argv[ctr],"-d")==0)
+ {
+ // Set log directory name
+ if( ctr < argc-1 ){
+ if(gVars.log_directory){ free(gVars.log_directory); } ctr++;
+ if( (gVars.log_directory = (char *)calloc(strlen(argv[ctr])+ 2,1) ) ==NULL){
+ syslog(LOG_ERR,"Unable to allocate memory for -d option\n");
+ exit(0);
+ }
+ bcopy(argv[ctr],gVars.log_directory,strlen(argv[ctr]));
+ // We allocated an extra space for this...
+ *(gVars.log_directory+strlen(argv[ctr]))='/';
+ }else{
+ syslog(LOG_ERR,"No directory provided with -d option\n");
+ exit(0);
+ }
+ }else{
+ if(strcmp(argv[ctr],"-r")==0)
+ {
+ // Set pcap input file name
+ if( ctr < argc-1 ){
+ if(gVars.input_filename){ free(gVars.input_filename); } ctr++;
+ if( (gVars.input_filename = (char *)calloc(strlen(argv[ctr])+1,1) ) ==NULL){
+ syslog(LOG_ERR,"Unable to allocate memory for -r option\n");
+ exit(0);
+ }
+ bcopy(argv[ctr],gVars.input_filename,strlen(argv[ctr]));
+ gVars.shift=0; // disable shift (only needed for 'any' interface)
+ }else{
+ syslog(LOG_ERR,"No pcap filename provided with -r option\n");
+ exit(0);
+ }
+ }else{
+ if(strcmp(argv[ctr],"-c")==0)
+ {
+ // Set configuration directory name
+ if( ctr < argc-1 ){
+ if(gVars.config_file){ free(gVars.config_file); } ctr++;
+ if( (gVars.config_file = (char *)calloc(strlen(argv[ctr])+1,1) ) ==NULL){
+ syslog(LOG_ERR,"Unable to allocate memory for -c option\n");
+ exit(0);
+ }
+ bcopy(argv[ctr],gVars.config_file,strlen(argv[ctr]));
+ }else{
+ syslog(LOG_ERR,"No configuration filename provided with -c option\n");
+ exit(0);
+ }
+ }else{
+ if(strcmp(argv[ctr],"--log-facility")==0)
+ {
+ // Set log facility
+ if( ctr < argc-1 ){
+ ctr++;
+ if(strcmp(argv[ctr],"LOCAL1")==0)
+ gVars.log_facility = LOG_LOCAL1;
+ if(strcmp(argv[ctr],"LOCAL2")==0)
+ gVars.log_facility = LOG_LOCAL2;
+ if(strcmp(argv[ctr],"LOCAL3")==0)
+ gVars.log_facility = LOG_LOCAL3;
+ if(strcmp(argv[ctr],"LOCAL4")==0)
+ gVars.log_facility = LOG_LOCAL4;
+ if(strcmp(argv[ctr],"LOCAL5")==0)
+ gVars.log_facility = LOG_LOCAL5;
+ if(strcmp(argv[ctr],"LOCAL6")==0)
+ gVars.log_facility = LOG_LOCAL6;
+ if(strcmp(argv[ctr],"LOCAL7")==0)
+ gVars.log_facility = LOG_LOCAL7;
+ }else{
+ syslog(LOG_ERR,"No value provided with --log-facility option\n");
+ exit(0);
+ }
+ }else{
+ if(strcmp(argv[ctr],"-u")==0)
+ {
+ // Set username name
+ if( ctr < argc-1 ){
+ if(gVars.username){ free(gVars.username); gVars.username=0; } ctr++;
+ if( (gVars.username = (char *)calloc(strlen(argv[ctr])+ 1,1) ) ==NULL){
+ syslog(LOG_ERR,"Unable to allocate memory for -u option\n");
+ exit(0);
+ }
+ bcopy(argv[ctr],gVars.username,strlen(argv[ctr]));
+ }else{
+ syslog(LOG_ERR,"No user provided with -u option\n");
+ exit(0);
+ }
+ }else{
+ if(strcmp(argv[ctr],"-g")==0)
+ {
+ // Set group name
+ if( ctr < argc-1 ){
+ if(gVars.groupname){ free(gVars.groupname); gVars.groupname=0; } ctr++;
+ if( (gVars.groupname = (char *)calloc(strlen(argv[ctr])+ 1,1) ) ==NULL){
+ syslog(LOG_ERR,"Unable to allocate memory for -g option\n");
+ exit(0);
+ }
+ bcopy(argv[ctr],gVars.groupname,strlen(argv[ctr]));
+ }else{
+ syslog(LOG_ERR,"No group provided with -g option\n");
+ exit(0);
+ }
+ }else{
+ if(strcmp(argv[ctr],"-F")==0)
+ {
+ // Set bp filter file name
+ if( ctr < argc-1 ){
+ ctr++;
+ // We alloc mem here, but fileHandle will free it
+ // This should be changed, but it works for now
+ set_bpf_filter(argv[ctr]);
+ syslog(LOG_INFO,"using file %s: %s\n",gVars.bpf_fname,argv[ctr]);
+ //if(!gVars.daemon_mode)
+ syslog(LOG_INFO,"enabling bpf filter from file %s: %s\n",gVars.bpf_fname,argv[ctr]);
+
+ }else{
+ syslog(LOG_ERR,"No filename provided with -F option\n");
+ exit(0);
+ }
+ }else{
+ if(strcmp(argv[ctr],"--strip-80211")==0)
+ {
+ // enable removal of 80211 header
+ gVars.strip_80211 = ENABLED;
+ if(!gVars.daemon_mode)
+ syslog(LOG_INFO,"enabling stripping of 80211 headers\n");
+ }else{
+ if(strcmp(argv[ctr],"--local-time")==0)
+ {
+ // disable GMT, enable localtime
+ gVars.uselocaltime = 1;
+ if(!gVars.daemon_mode)
+ syslog(LOG_INFO,"enabling local timestamps instead of GMT\n");
+ }else{
+ if(strcmp(argv[ctr],"-A")==0)
+ {
+ // enable recording all data to tcpdump file before
+ // processing, any strip-80211 option applies, however
+ if(gVars.rpfH){ gVars.rpfH->destroy(); gVars.rpfH=0; }
+ ftmp=createFileName(PCAP_RAW_FNAME);
+ gVars.rpfH = new pcapFileHandle(ftmp);
+ free(ftmp);
+ gVars.pcap_raw = ENABLED;
+ syslog(LOG_INFO,"enabling debug recording of all pcap data to a tcpdump file\n");
+ }else{
+ if(strcmp(argv[ctr],"-R")==0)
+ {
+ // disable realtime
+ gVars.cmdl_realtimes_action = ACTION_PASS;
+ gVars.rmode = OMODE_PASS;
+ syslog(LOG_INFO,"disabling default 'realtimes' logging mode\n");
+ }else{
+ if(strcmp(argv[ctr],"-P")==0)
+ {
+ // disable default collect action
+ gVars.cmdl_pcap_action = ACTION_PASS;
+ gVars.pmode = OMODE_PASS;
+ syslog(LOG_INFO,"disabling default 'pcap' logging mode\n");
+
+ }else{
+ if(strcmp(argv[ctr],"-S")==0)
+ {
+ // disable default log action
+ gVars.cmdl_stats_action = ACTION_PASS;
+ gVars.smode = OMODE_PASS;
+ syslog(LOG_INFO,"disabling default 'stats' logging mode\n");
+ }else{
+ if(strcmp(argv[ctr],"-I")==0 || strcmp(argv[ctr],"--enable-icmp-mixed")==0)
+ {
+ // enable recording and tracking ICMP type/code in src and dst port fields
+ gVars.log_icmp_type_code = 1;
+ syslog(LOG_INFO,"enabling logging icmp type/code for s_port and d_port fields\n");
+ }else{
+ if(strcmp(argv[ctr],"-B")==0)
+ {
+ // The rest of this line should be the bpf expression
+ if(gVars.bpf_filter){ free(gVars.bpf_filter); } ctr++;
+ if(argc>ctr){
+ gVars.bpf_filter=(char *) calloc(1,strlen(argv[ctr])+1);
+ strncpy(gVars.bpf_filter,argv[ctr],strlen(argv[ctr]));
+ syslog(LOG_INFO,"enabling bpf expression %s\n",gVars.bpf_filter);
+ }
+
+ }else{
+ if(strcmp(argv[ctr],"-H")==0 || strcmp(argv[ctr],"--human-readable")==0)
+ {
+ // enable human readable mode - affects IP addressess and tcp flag fields
+ gVars.human_readable = 1;
+ syslog(LOG_INFO,"enabling human readable connection logging\n");
+
+ }else{
+ if(strcmp(argv[ctr],"-V")==0||strcmp(argv[ctr],"-v")==0)
+ {
+ version();
+ license();
+ exit_all(0);
+ }else{
+ if(strcmp(argv[ctr],"-?")==0 || strcmp(argv[ctr],"-h")==0){
+ version();
+ usage();
+ exit_all(0);
+ }else{
+ // See if this was a -option
+ if(strstr(argv[ctr],"-")){
+ syslog(LOG_ERR,"skipping unrecognized option: %s\n",argv[ctr]);
+
+ }else{
+ // The rest of this line should be the bpf expression
+ //if((argc-1)>(ctr++)){
+ if(gVars.bpf_filter){ free(gVars.bpf_filter); gVars.bpf_filter=0; }
+ gVars.bpf_filter=(char *) calloc(1,strlen(argv[ctr])+1);
+ strncpy(gVars.bpf_filter,argv[ctr],strlen(argv[ctr]));
+ syslog(LOG_INFO,"enabling bpf expression %s\n",gVars.bpf_filter);
+ //syslog(LOG_ERR,"Unknown option: %s\n",argv[ctr]);
+ }
+ //}
+
+ }}}}}}}}}}}}}}}}}}}}}}}}
+ }
+
+
+}
+void build_config(int a){
+ extern struct gvars gVars;
+ int lc=0;
+ FILE *config_file;
+ int size=0;
+ int mylen=0;
+ char *rule=NULL;
+ char *accept="\t ,=";
+ struct vars *tmp_var=NULL;
+ struct acl *tmp_acl=0;
+ struct t_ports *ports_head;
+ struct t_ports *tmp_port;
+ int p=0;
+ if(!gVars.config_file){ return; }
+ if((config_file=fopen(gVars.config_file,"r")) == NULL ) {
+ return;
+ }
+ // Drop the vars now
+ while(gVars.var_head!=NULL){ tmp_var=gVars.var_head; gVars.var_head=gVars.var_head->next; if(tmp_var->key)free(tmp_var->key); if(tmp_var->value)free(tmp_var->value); free(tmp_var); } gVars.var_head=NULL;
+ /* the first field should tell us everything we need to know about
+ * what to expect in the rule
+ */
+#ifdef DEBUG
+ fprintf(stdout,"Reading config\n");
+#endif
+ while((mylen=fgetcline(&rule, size, config_file)) >= 0){
+ lc++;
+ if(mylen<2){
+#ifdef DEBUG
+ fprintf(stdout,"Line: %d rule too small, skipping %s\n",lc, rule);
+#endif
+ continue; }
+#ifdef DEBUG
+ fprintf(stdout,"Processing %s\n",rule);
+#endif
+ if(strncmp(rule,"format",6)==0)
+ {
+ parse_format(rule,accept);
+ }
+ else if(strncmp(rule,"known_ports",11)==0)
+ {
+ parse_known_ports(rule,gVars.var_head,accept);
+ }
+ else if(strncmp(rule,"default",7)==0)
+ {
+ parse_default(rule,accept);
+ }else if(strncmp(rule,"var",3)==0)
+ {
+ parse_var(rule,accept);
+#ifdef DEBUG
+ if(gVars.var_head!=NULL)
+ fprintf(stdout,"Have var, %s/%s\n",gVars.var_head->key,gVars.var_head->value);
+#endif
+ }else{
+ parse_connection_rule(rule,gVars.var_head,accept);
+ }
+ if(rule){
+#ifdef DEBUG
+ printf("freeing %X\n",(u_int32_t) &rule);
+#endif
+ free(rule);
+ rule=NULL;
+ }
+
+ }
+ fclose(config_file);
+#ifdef DEBUG
+ printf("Done reading rules\n");
+#endif
+ // swap out old rules with new rules
+ tmp_acl=gVars.acl_head;
+ gVars.acl_head=tacl_head;
+ tacl_head=tmp_acl;
+#ifdef DEBUG
+ printf("Disposing old rules\n");
+#endif
+ // dispose of previous rules
+ while(tacl_head!=NULL){ tmp_acl=tacl_head; tacl_head=tacl_head->next; free(tmp_acl);}
+ tacl_head=NULL; tacl_tail=NULL;
+
+#ifdef DEBUG
+ printf("Disposing old ports\n");
+#endif
+ //while(acl_head!=NULL){ tmpptr=acl_head; acl_head=acl_head->next; free(tmpptr); }
+ // dispose of previous ports
+ for(p=0; p<MAX_IP_PROTO; p++)
+ {
+ ports_head=gVars.ports[p];
+
+ while(ports_head!=NULL){
+ tmp_port=ports_head;
+ ports_head=tmp_port->next;
+ free(tmp_port);
+ }
+ gVars.ports[p]=tports[p];
+ tports[p]=NULL;
+ }
+ // Dispose of temporary rule variables
+ //
+}
+
+void parse_format(const char *c_rule,const char *accept)
+{
+ extern struct gvars gVars;
+ extern char fmtnames[MAXFLDS][MAXFLDSIZE];
+ char *rule=(char *)calloc(1,strlen(c_rule)+1);
+ memcpy(rule,c_rule,strlen(c_rule));
+ char *rules=rule;
+ char *tok=0;
+ if((tok = get_tok(&rules,accept))==NULL){
+ syslog(LOG_ERR,"Skipping, Invalid default, rule trunicated %s\n",rule);
+ return;
+ }else if((tok = get_tok(&rules,accept))==NULL){
+ syslog(LOG_ERR,"Skipping, Invalid default, rule trunicated %s\n",rule);
+ return;
+ }
+
+ int type=0;
+ if(strcmp(tok,"realtime")==0)
+ type=1;
+ if(strcmp(tok,"stats")==0)
+ type=2;
+ if(strcmp(tok,"stdout")==0)
+ type=4;
+ char delimiter=0;
+ if(strncmp(rules,"delimiter",9)==0){
+ if((tok = get_tok(&rules,accept))==NULL){
+ syslog(LOG_ERR,"Skipping, Invalid delimiter, rule trunicated %s\n",rule);
+ return;
+ }else if((tok = get_tok(&rules,accept))==NULL){
+ syslog(LOG_ERR,"Skipping, Invalid delimiter, rule trunicated %s\n",rule);
+ return;
+ }
+ delimiter=tok[0];
+ if(delimiter=='\\'){
+ if(tok[1]=='s')
+ delimiter=' ';
+ if(tok[1]=='t')
+ delimiter='\t';
+ if(tok[1]=='n')
+ delimiter='\n';
+ }
+ }
+
+ char eor=0;
+ if(strncmp(rules,"eor",3)==0){
+ if((tok = get_tok(&rules,accept))==NULL){
+ syslog(LOG_ERR,"Skipping, Invalid eor, rule trunicated %s\n",rule);
+ return;
+ }else if((tok = get_tok(&rules,accept))==NULL){
+ syslog(LOG_ERR,"Skipping, Invalid eor, rule trunicated %s\n",rule);
+ return;
+ }
+ eor=tok[0];
+ if(eor=='\\'){
+ if(tok[1]=='s')
+ eor=' ';
+ if(tok[1]=='t')
+ eor='\t';
+ if(tok[1]=='n')
+ eor='\n';
+ }
+ }
+
+ char *tmpfldnames;
+ int col=0;
+ int icol=0;
+ int fmtval=0;
+ char fmt[MAXFLDS];
+ while(rules && (tok = get_tok(&rules,accept))!=NULL && *tok != 0)
+ {
+ tmpfldnames=(char *)fmtnames;
+ while((fmtval<MAXFLDS) && strncmp(tmpfldnames,tok,MAXFLDSIZE)){
+ /* keep track of the current index of fmtnames in fmtval */
+ tmpfldnames+=MAXFLDSIZE; fmtval++;
+ }
+ /* if our index (fmtval) exceeds MAXFLDS then we have no more room in our fmt array */
+ if(fmtval<MAXFLDS){
+ fmt[col]=fmtval;
+ col++;
+ }else{
+ syslog(LOG_ERR,"Skipping, invalid format field name %s for column %d",tok,icol);
+ }
+ if(col>MAXFLDS-1){
+ syslog(LOG_ERR,"Exceeded maximum columns allowed (%d) , skipping remaining format fields at column %d: %s",MAXFLDS,icol,rules);
+ break;
+ }
+ icol++;
+ fmtval=0;
+ }
+ if(type==1){
+ if(gVars.realtime_fmt_len){
+ free(gVars.realtime_fmt);
+ gVars.realtime_fmt_len=0;
+ }
+ gVars.realtime_fmt=(char *) calloc(col,1);
+ memcpy(gVars.realtime_fmt,fmt,col);
+ gVars.realtime_fmt_len=col;
+ if(eor)
+ gVars.realtime_eor=eor;
+ if(delimiter)
+ gVars.realtime_delimiter=delimiter;
+ if(gVars.rfH){
+ gVars.rfH->setFormat(gVars.realtime_fmt,gVars.realtime_fmt_len);
+ gVars.rfH->setEor(gVars.realtime_eor);
+ gVars.rfH->setDelimiter(gVars.realtime_delimiter);
+
+ }
+ }
+ if(type==2){
+ if(gVars.stats_fmt_len){
+ free(gVars.stats_fmt);
+ gVars.stats_fmt_len=0;
+ }
+ gVars.stats_fmt=(char *) calloc(col,1);
+ memcpy(gVars.stats_fmt,fmt,col);
+ gVars.stats_fmt_len=col;
+ if(eor)
+ gVars.stats_eor=eor;
+ if(delimiter)
+ gVars.stats_delimiter=delimiter;
+ if(gVars.sfH){
+ gVars.sfH->setFormat(gVars.stats_fmt,gVars.stats_fmt_len);
+ gVars.sfH->setEor(gVars.stats_eor);
+ gVars.sfH->setDelimiter(gVars.stats_delimiter);
+ }
+ }
+ if(type==4){
+ if(gVars.stdout_fmt_len){
+ free(gVars.stdout_fmt);
+ gVars.stdout_fmt_len=0;
+ }
+ gVars.stdout_fmt=(char *) calloc(col,1);
+ memcpy(gVars.stdout_fmt,fmt,col);
+ gVars.stdout_fmt_len=col;
+ if(eor)
+ gVars.stdout_eor=eor;
+ if(delimiter)
+ gVars.stdout_delimiter=delimiter;
+ if(gVars.sdF){
+ gVars.sdF->setFormat(gVars.stdout_fmt,gVars.stdout_fmt_len);
+ gVars.sdF->setEor(gVars.stdout_eor);
+ gVars.sdF->setDelimiter(gVars.stdout_delimiter);
+ }
+ }
+ if(rule) free(rule);
+
+}
+
+void parse_default(char *c_rule,char *accept)
+{
+ extern struct gvars gVars;
+ char *rule=(char *)calloc(1,strlen(c_rule)+1);
+ memcpy(rule,c_rule,strlen(c_rule));
+ char *rules=rule;
+ char *tok=0;
+ char *tmp=0;
+ char *ftmp=0;
+ char *pptr=0;
+
+ if((tok = get_tok(&rules,accept))==NULL){
+ syslog(LOG_ERR,"Skipping, Invalid default, rule trunicated %s\n",rule);
+ free(rule);
+ return;
+ }else if((tok = get_tok(&rules,accept))==NULL){
+ syslog(LOG_ERR,"Skipping, Invalid default, rule trunicated %s\n",rule);
+ free(rule);
+ return;
+ }
+ if(strcmp(tok,"expire_interval")==0)
+ {
+ if((tmp = get_tok(&rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, default expire_interval specified but none provided, using default expire_interval %d\n",DEFAULT_EXPIRE_INTERVAL);
+ gVars.default_expire_interval = DEFAULT_EXPIRE_INTERVAL;
+ free(rule);
+ return;
+ }
+ pptr=tmp;
+ gVars.default_expire_interval = (u_int16_t) strtol(tmp,&pptr,0);
+ if(tmp==pptr)
+ {
+ syslog(LOG_ERR,"Format error, invalid expire_interval %s, using default expire_interval %d\n",tmp,DEFAULT_EXPIRE_INTERVAL);
+ }
+ free(rule);
+ return;
+ }
+ if(strcmp(tok,"flush_interval")==0)
+ {
+ int reset_alarm=gVars.default_flush_interval;
+ if((tmp = get_tok(&rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, default flush_interval specified but none provided, using default flush_interval %d\n",DEFAULT_FLUSH_INTERVAL);
+ gVars.default_flush_interval = DEFAULT_FLUSH_INTERVAL;
+ free(rule);
+ return;
+ }
+ pptr=tmp;
+ gVars.default_flush_interval = (u_int16_t) strtol(tmp,&pptr,0);
+ if(tmp==pptr)
+ {
+ syslog(LOG_ERR,"Format error, invalid flush_interval %s, using default flush_interval %d\n",tmp,DEFAULT_FLUSH_INTERVAL);
+ }
+ // If the default flush_interval in the config file changed, we
+ // need to reset the alarm to the new interval
+ if(reset_alarm){
+ alarm(gVars.default_flush_interval);
+ }
+ free(rule);
+ return;
+ }
+ if(strcmp(tok,"zone")==0)
+ {
+ if((tmp = get_tok(&rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, default zone specified but none provided, using default zone %d\n",DEFAULT_ZONE);
+ gVars.default_zone = DEFAULT_ZONE;
+ free(rule);
+ return;
+ }
+ pptr=tmp;
+ gVars.default_zone = (u_int16_t) strtol(tmp,&pptr,0);
+ if(tmp==pptr)
+ {
+ syslog(LOG_ERR,"Format error, invalid zone %s, using default zone %d\n",tmp,DEFAULT_ZONE);
+ }
+ free(rule);
+ return;
+ }
+ if(strcmp(tok,"node")==0)
+ {
+ if((tmp = get_tok(&rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, default node specified but none provided, using default node %d\n",DEFAULT_NODE);
+ gVars.default_node = DEFAULT_NODE;
+ free(rule);
+ return;
+ }
+ pptr=tmp;
+ gVars.default_node = (u_int16_t) strtol(tmp,&pptr,0);
+ if(tmp==pptr)
+ {
+ syslog(LOG_ERR,"Format error, invalid node %s, using default node %d\n",tmp,DEFAULT_NODE);
+ }
+ free(rule);
+ return;
+ }
+ if(strcmp(tok,"rid")==0)
+ {
+ if((tmp = get_tok(&rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, default rid specified but none provided, using default rid %d\n",DEFAULT_RID);
+ gVars.default_rid = DEFAULT_RID;
+ free(rule);
+ return;
+ }
+ pptr=tmp;
+ gVars.default_rid = (u_int32_t) strtol(tmp,&pptr,0);
+ if(tmp==pptr)
+ {
+ syslog(LOG_ERR,"Format error, invalid rid %s, using default rid %d\n",tmp,DEFAULT_RID);
+ }
+ free(rule);
+ return;
+ }
+ if(strcmp(tok,"rgid")==0)
+ {
+ if((tmp = get_tok(&rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, default rgid specified but none provided, using default rgid %d\n",DEFAULT_RGID);
+ gVars.default_rgid = DEFAULT_RGID;
+ free(rule);
+ return;
+ }
+ pptr=tmp;
+ gVars.default_rgid = (u_int32_t) strtol(tmp,&pptr,0);
+ if(tmp==pptr)
+ {
+ syslog(LOG_ERR,"Format error, invalid rid %s, using default rid %d\n",tmp,DEFAULT_RID);
+ }
+ free(rule);
+ return;
+ }
+ if(strcmp(tok,"status")==0)
+ {
+ if((tmp = get_tok(&rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, default status specified but none provided, using default status %d\n",DEFAULT_STATUS);
+ gVars.default_status = DEFAULT_STATUS;
+ free(rule);
+ return;
+ }
+ pptr=tmp;
+ gVars.default_status = (u_int8_t) strtol(tmp,&pptr,0);
+ if(tmp==pptr)
+ {
+ syslog(LOG_ERR,"Format error, invalid status %s, using default status %d\n",tmp,DEFAULT_STATUS);
+ }
+ free(rule);
+ return;
+ }
+ if(strcmp(tok,"use_pcap_time")==0)
+ {
+ if((tmp = get_tok(&rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, default for use_pcap_time specified but no value provided%s\n",rule);
+ free(rule);
+ return;
+ }
+ if(strcmp(tmp,"enable")==0)
+ {
+ gVars.use_pcap_time = ENABLED;
+ }
+ if(strcmp(tmp,"disable")==0)
+ {
+ gVars.use_pcap_time = DISABLED;
+ }
+#ifdef DEBUG
+ fprintf(stdout,"Setting default for %s to %s\n",tok,tmp);
+#endif
+ free(rule);
+ return;
+ }
+ if(strcmp(tok,"burst_mode")==0)
+ {
+ if((tmp = get_tok(&rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, default for burst_mode specified but no value provided%s\n",rule);
+ free(rule);
+ return;
+ }
+ if(strcmp(tmp,"enable")==0)
+ {
+ gVars.burst_mode = ENABLED;
+ }
+ if(strcmp(tmp,"disable")==0)
+ {
+ gVars.burst_mode = DISABLED;
+ }
+#ifdef DEBUG
+ fprintf(stdout,"Setting default for %s to %s\n",tok,tmp);
+#endif
+ free(rule);
+ return;
+ }
+ if(strcmp(tok,"debug_pcap_raw")==0)
+ {
+ if((tmp = get_tok(&rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, default for debug_pcap_raw specified but no value provided%s\n",rule);
+ free(rule);
+ return;
+ }
+ if(strcmp(tmp,"enable")==0)
+ {
+ if(gVars.rpfH){ gVars.rpfH->destroy(); gVars.rpfH=0; }
+ ftmp=createFileName("tcpdump");
+ gVars.rpfH = new pcapFileHandle(ftmp);
+ free(ftmp);
+ gVars.pcap_raw = ENABLED;
+ }
+ if(strcmp(tmp,"disable")==0)
+ {
+ if(gVars.rpfH){ gVars.rpfH->destroy(); gVars.rpfH=0; }
+ gVars.pcap_raw = DISABLED;
+ }
+#ifdef DEBUG
+ fprintf(stdout,"Setting default for %s to %s\n",tok,tmp);
+#endif
+ free(rule);
+ return;
+ }
+ if(strcmp(tok,"strip-80211")==0)
+ {
+ if((tmp = get_tok(&rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, default for strip_80211 specified but no value provided%s\n",rule);
+ free(rule);
+ return;
+ }
+ if(strcmp(tmp,"enable")==0)
+ {
+ gVars.strip_80211 = ENABLED;
+ }
+ if(strcmp(tmp,"disable")==0)
+ {
+ gVars.strip_80211 = DISABLED;
+ }
+#ifdef DEBUG
+ fprintf(stdout,"Setting default for %s to %s\n",tok,tmp);
+#endif
+ free(rule);
+ return;
+ }
+ if(strcmp(tok,"pcapfilter")==0)
+ {
+ // We don't parse pcapfilter after initial startup, so see if we have an open pcap handle
+ if( gVars.ph!=0 ){ free(rule); return; }
+ gVars.bpf_filter=(char *) calloc(1,strlen(rules)+1);
+ strncpy(gVars.bpf_filter,rules,strlen(rules));
+ syslog(LOG_INFO,"setting pcap filter expression %s\n",gVars.bpf_filter);
+
+#ifdef DEBUG
+ fprintf(stdout,"Setting default for %s to %s\n",tok,tmp);
+#endif
+ free(rule);
+ return;
+ }
+ if(strcmp(tok,"stats")==0)
+ {
+ if((tmp = get_tok(&rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, default for stats specified but no value provided%s\n",rule);
+ free(rule);
+ return;
+ }
+ if(strcmp(tmp,"log")==0) // log all matching traffic
+ {
+ if(gVars.stats_fname){ free(gVars.stats_fname); }
+ gVars.stats_fname=(char *) calloc(1,strlen(STATS_FNAME)+1);
+ strncpy(gVars.stats_fname,STATS_FNAME,strlen(STATS_FNAME));
+ if(gVars.sfH){ gVars.sfH->destroy(); gVars.sfH=0; }
+ ftmp=createFileName(gVars.stats_fname);
+ gVars.sfH = new outputFileHandle((const char*)ftmp,gVars.stats_fmt,gVars.stats_fmt_len,APPEND_MODE);
+ free(ftmp);
+ gVars.smode=OMODE_LOG;
+ }
+ if(strcmp(tmp,"pass")==0)
+ {
+ if(gVars.sfH){ gVars.sfH->destroy(); gVars.sfH=0; }
+ gVars.smode=OMODE_PASS;
+ }
+ if(strcmp(tmp,"filename")==0)
+ {
+ if((tmp = get_tok(&rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, default filename for stats specified but no value provided%s\n",rule);
+ return;
+ }
+ if(gVars.stats_fname){ free(gVars.stats_fname); }
+ gVars.stats_fname=(char *) calloc(1,strlen(tmp)+1);
+ strncpy(gVars.stats_fname,tmp,strlen(tmp));
+ gVars.smode=OMODE_FILENAME;
+ if(gVars.sfH){ gVars.sfH->destroy(); gVars.sfH=0; }
+ ftmp=createFileName(gVars.stats_fname,gVars.smode == OMODE_TSFILENAME);
+ gVars.sfH = new outputFileHandle((const char*)ftmp,gVars.stats_fmt,gVars.stats_fmt_len,APPEND_MODE);
+ gVars.sfH->setEor(gVars.stats_eor);
+ gVars.sfH->setDelimiter(gVars.stats_delimiter);
+ free(ftmp);
+ }
+ if(strcmp(tmp,"tsfilename")==0)
+ {
+ if((tmp = get_tok(&rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, default tsfilename for stats specified but no value provided%s\n",rule);
+ free(rule);
+ return;
+ }
+ if(gVars.stats_fname){ free(gVars.stats_fname); }
+ gVars.stats_fname=(char *) calloc(1,strlen(tmp)+1);
+ strncpy(gVars.stats_fname,tmp,strlen(tmp));
+ gVars.smode=OMODE_TSFILENAME;
+ if(gVars.sfH){ gVars.sfH->destroy(); gVars.sfH=0; }
+ ftmp=createFileName(gVars.stats_fname,gVars.smode == OMODE_TSFILENAME);
+ gVars.sfH = new outputFileHandle((const char*)ftmp,gVars.stats_fmt,gVars.stats_fmt_len,APPEND_MODE);
+ gVars.sfH->setEor(gVars.stats_eor);
+ gVars.sfH->setDelimiter(gVars.stats_delimiter);
+ free(ftmp);
+ }
+
+#ifdef DEBUG
+ fprintf(stdout,"Setting default for %s to %s\n",tok,tmp);
+#endif
+ free(rule);
+ return;
+ }
+ if(strcmp(tok,"pcap")==0)
+ {
+ if((tmp = get_tok(&rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, default for pcap specified but no value provided%s\n",rule);
+ free(rule);
+ return;
+ }
+ if(strcmp(tmp,"log")==0) // log all matching traffic
+ {
+ gVars.pmode = OMODE_LOG;
+ if(gVars.pcap_fname){ free(gVars.pcap_fname); }
+ gVars.pcap_fname=(char *) calloc(1,strlen(PCAP_FNAME)+1);
+ strncpy(gVars.pcap_fname,PCAP_FNAME,strlen(PCAP_FNAME));
+ if(gVars.pfH){ gVars.pfH->destroy(); gVars.pfH=0; }
+ ftmp=createFileName(gVars.pcap_fname);
+ gVars.pfH = new pcapFileHandle(ftmp);
+ free(ftmp);
+ }
+ if(strcmp(tmp,"pass")==0)
+ {
+ gVars.pmode=OMODE_PASS;
+ if(gVars.pfH){ gVars.pfH->destroy(); gVars.pfH=0; }
+ }
+ if(strcmp(tmp,"filename")==0)
+ {
+ if((tmp = get_tok(&rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, default filename for pcap specified but no value provided%s\n",rule);
+ free(rule);
+ return;
+ }
+ if(gVars.pcap_fname){ free(gVars.pcap_fname); }
+ gVars.pcap_fname=(char *) calloc(1,strlen(tmp)+1);
+ strncpy(gVars.pcap_fname,tmp,strlen(tmp));
+ gVars.pmode=OMODE_FILENAME;
+ if(gVars.pfH){ gVars.pfH->destroy(); gVars.pfH=0; }
+ ftmp=createFileName(gVars.pcap_fname,gVars.pmode == OMODE_TSFILENAME );
+ gVars.pfH = new pcapFileHandle(ftmp);
+ free(ftmp);
+ }
+ if(strcmp(tmp,"tsfilename")==0)
+ {
+ if((tmp = get_tok(&rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, default tsfilename for pcap specified but no value provided%s\n",rule);
+ free(rule);
+ return;
+ }
+ if(gVars.pcap_fname){ free(gVars.pcap_fname); }
+ gVars.pcap_fname=(char *) calloc(1,strlen(tmp)+1);
+ strncpy(gVars.pcap_fname,tmp,strlen(tmp));
+ gVars.pmode=OMODE_TSFILENAME;
+ if(gVars.pfH){ gVars.pfH->destroy(); gVars.pfH=0; }
+ ftmp=createFileName(gVars.pcap_fname,gVars.pmode == OMODE_TSFILENAME);
+ gVars.pfH = new pcapFileHandle(ftmp);
+ free(ftmp);
+ }
+
+#ifdef DEBUG
+ fprintf(stdout,"Setting default for %s to %s\n",tok,tmp);
+#endif
+ free(rule);
+ return;
+ }
+ if(strcmp(tok,"realtime")==0)
+ {
+ if((tmp = get_tok(&rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, default for realtime specified but no value provided%s\n",rule);
+ free(rule);
+ return;
+ }
+ if(strcmp(tmp,"log")==0) // log all matching traffic
+ {
+ if(gVars.realtime_fname){ free(gVars.realtime_fname); }
+ gVars.realtime_fname=(char *) calloc(1,strlen(REALTIME_FNAME)+1);
+ strncpy(gVars.realtime_fname,REALTIME_FNAME,strlen(REALTIME_FNAME));
+ if(gVars.rfH){ gVars.rfH->destroy(); gVars.rfH=0; }
+ ftmp=createFileName(gVars.realtime_fname);
+ gVars.rfH = new outputFileHandle((const char*)ftmp,gVars.realtime_fmt,gVars.realtime_fmt_len,APPEND_MODE);
+ free(ftmp);
+ gVars.rmode=OMODE_LOG;
+ }
+ if(strcmp(tmp,"pass")==0)
+ {
+ if(gVars.rfH){ gVars.rfH->destroy(); gVars.rfH=0; }
+ gVars.rmode=OMODE_PASS;
+ }
+ if(strcmp(tmp,"filename")==0)
+ {
+ if((tmp = get_tok(&rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, default filename for realtime specified but no value provided%s\n",rule);
+ free(rule);
+ return;
+ }
+ if(gVars.realtime_fname){ free(gVars.realtime_fname); }
+ gVars.realtime_fname=(char *) calloc(1,strlen(tmp)+1);
+ strncpy(gVars.realtime_fname,tmp,strlen(tmp));
+ gVars.rmode=OMODE_FILENAME;
+ if(gVars.rfH){ gVars.rfH->destroy(); gVars.rfH=0; }
+ ftmp=createFileName(gVars.realtime_fname,gVars.rmode == OMODE_TSFILENAME);
+ gVars.rfH = new outputFileHandle((const char*)ftmp,gVars.realtime_fmt,gVars.realtime_fmt_len,APPEND_MODE);
+ gVars.rfH->setEor(gVars.realtime_eor);
+ gVars.rfH->setDelimiter(gVars.realtime_delimiter);
+ free(ftmp);
+ }
+ if(strcmp(tmp,"tsfilename")==0)
+ {
+ if((tmp = get_tok(&rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, default tsfilename for realtime specified but no value provided%s\n",rule);
+ free(rule);
+ return;
+ }
+ if(gVars.realtime_fname){ free(gVars.realtime_fname); }
+ gVars.realtime_fname=(char *) calloc(1,strlen(tmp)+1);
+ strncpy(gVars.realtime_fname,tmp,strlen(tmp));
+ gVars.rmode=OMODE_TSFILENAME;
+ if(gVars.rfH){ gVars.rfH->destroy(); gVars.rfH=0; }
+ ftmp=createFileName(gVars.realtime_fname,gVars.rmode == OMODE_TSFILENAME);
+ gVars.rfH = new outputFileHandle((const char*)ftmp,gVars.realtime_fmt,gVars.realtime_fmt_len,APPEND_MODE);
+ gVars.rfH->setEor(gVars.realtime_eor);
+ gVars.rfH->setDelimiter(gVars.realtime_delimiter);
+ free(ftmp);
+ }
+
+#ifdef DEBUG
+ fprintf(stdout,"Setting default for %s to '%s'\n",tok,tmp);
+#endif
+ free(rule);
+ return;
+ }
+ if(strcmp(tok,"limit")==0)
+ {
+ if((tmp = get_tok(&rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, limit specified but none provided, using default limit %d\n",DEFAULT_LIMIT);
+ free(rule);
+ return;
+ }
+ pptr=tmp;
+ gVars.default_limit = (u_int64_t) strtoll(tmp,&pptr,0);
+ if(tmp==pptr)
+ {
+ syslog(LOG_ERR,"Format error, invalid limit %s, using default limit %d\n",tmp,DEFAULT_LIMIT);
+ gVars.default_limit = DEFAULT_LIMIT;
+ }
+ free(rule);
+ return;
+ }
+ if(strcmp(tok,"timeout")==0)
+ {
+ if((tmp = get_tok(&rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, default timeout specified but none provided, using timeout value %d\n",DEFAULT_TIMEOUT);
+ free(rule);
+ return;
+ }
+ pptr=tmp;
+ gVars.default_timeout = (u_int16_t) strtol(tmp,&pptr,0);
+ if(tmp==pptr)
+ {
+ syslog(LOG_ERR,"Format error, invalid timeout %s, using default timeout %d\n",tmp,DEFAULT_TIMEOUT);
+ gVars.default_timeout = DEFAULT_TIMEOUT;
+ }
+ free(rule);
+ return;
+ }
+ if(strcmp(tok,"tcplag")==0)
+ {
+ if((tmp = get_tok(&rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, tcplag specified but none provided, using tcplag value %d\n",DEFAULT_LAG);
+ free(rule);
+ return;
+ }
+ pptr=tmp;
+ gVars.default_tcplag = (u_int16_t) strtol(tmp,&pptr,0);
+ if(tmp==pptr)
+ {
+ syslog(LOG_ERR,"Format error, invalid tcplag %s, using default tcplag %d\n",tmp,DEFAULT_LAG);
+ gVars.default_tcplag = DEFAULT_LAG;
+ }
+ free(rule);
+ return;
+#ifdef DEBUG
+ fprintf(stdout,"Didn't set default for %s to %s\n",tok,tmp);
+#endif
+ }
+}
+
+void parse_var(char *c_rule, char *accept)
+{
+ extern struct gvars gVars;
+ char *rule=(char *)calloc(1,strlen(c_rule)+1);
+ memcpy(rule,c_rule,strlen(c_rule));
+ char **rules=&rule;
+ char *tok=NULL;
+ struct vars *n_var;
+ rules=&rule;
+
+ if((n_var=(struct vars *)calloc(1,sizeof(struct vars)))==NULL){ printf ("Out of Memory?\n"); return;}
+
+ n_var->key=NULL;
+ n_var->value=NULL;
+ n_var->next=NULL;
+ if((tok = get_tok(rules,accept))==NULL || strcmp(tok,"var")!=0)
+ {
+ syslog(LOG_ERR,"Skipping, Invalid rule trunicated when expecting var type %s\n",rule);
+ free(n_var);
+ free(rule);
+ return;
+ }
+ else
+ {
+ if((tok = get_tok(rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Skipping, Invalid rule trunicated when expecting var key %s\n",rule);
+ free(n_var);
+ free(rule);
+ return;
+ }
+ else
+ {
+ if((n_var->key=(char *)calloc(1,sizeof(char)*strlen(tok)+1))==NULL){ printf ("Out of Memory?\n"); free(n_var); free(rule); return;}
+ strncpy(n_var->key,tok,sizeof(char)*strlen(tok));
+
+ if((tok = get_tok(rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Skipping, Invalid rule trunicated when expecting var value %s\n",rule);
+ free(n_var->key);
+ n_var->key=NULL; free(n_var);
+ free(rule);
+ return;
+ }
+ else
+ {
+ if((n_var->value=(char *)calloc(1,sizeof(char)*strlen(tok)+1))==NULL){ printf ("Out of Memory?\n"); free(n_var->key); free(n_var); free(rule); return;}
+ strncpy(n_var->value,tok,sizeof(char)*strlen(tok));
+ }
+ }
+ }
+
+ // If we made it this var, then we have a valid var
+ if(!gVars.var_head){
+ gVars.var_head=n_var;
+ }
+ else
+ {
+ n_var->next = gVars.var_head;
+ gVars.var_head=n_var;
+ }
+ free(rule);
+}
+
+
+
+char *search_vars(char *key, struct vars *var_head, int vclass)
+{
+ struct vars *tmp;
+ tmp = var_head;
+#ifdef DEBUG
+ syslog(LOG_ERR,"Searching for key '%s'\n",key);
+#endif
+ while(tmp!=NULL)
+ {
+#ifdef DEBUG
+ fprintf(stdout,"Checking key/value (%d) '%s'/'%s' for (%d) '%s'\n",strlen(tmp->key),tmp->key,tmp->value,strlen(key),key);
+#endif
+ if(strcmp(tmp->key,key)==0)
+ {
+#ifdef DEBUG
+ syslog(LOG_ERR,"Found key/value %s/%s\n",key,tmp->value);
+#endif
+ // Mark the variable class that we were looking in
+ // so we will 'remember' which values pertained to which
+ // class of keys when we do a reverse lookup later.
+ // i.e. The value of 8 may exist in two or more classes
+ // Different class variables, having the same name, may
+ // cause undefined results.
+ tmp->vclass=vclass;
+ return tmp->value;
+ }
+ tmp=tmp->next;
+ }
+#ifdef DEBUG
+ fprintf(stdout,"Key not found '%s'\n",key);
+#endif
+ return NULL;
+}
+
+char *rev_search_vars(char *value, struct vars *var_head, int vclass)
+{
+ struct vars *tmp;
+ tmp = var_head;
+#ifdef DEBUG
+ syslog(LOG_INFO,"REV Search %d:'%s' for %d:'%s'\n",tmp->vclass,tmp->value,vclass,value);
+#endif
+ while(tmp!=NULL)
+ {
+ if( tmp->vclass==vclass && strcmp(tmp->value,value)==0)
+ {
+#ifdef DEBUG
+ syslog(LOG_ERR,"Found key/value %s/'%s'\n",tmp->key,tmp->value);
+#endif
+ return tmp->key;
+ }
+ tmp=tmp->next;
+ }
+#ifdef DEBUG
+ fprintf(stdout,"Value not found '%s'\n",value);
+#endif
+ return NULL;
+}
+
+void parse_known_ports(char *rule, struct vars *var_head, char *accept)
+{
+ extern struct t_ports *tports[MAX_IP_PROTO];
+ char *tmp=NULL, *pptr=NULL,*tok=NULL;
+ char **rules=NULL;
+ struct t_ports *n_ports=NULL;
+ int proto = 0;
+ char ptok[256];
+ u_int16_t port_h=0;
+ u_int16_t port_l=0;
+ rules=&rule;
+
+ if((tok = get_tok(rules,accept))!=NULL)
+ {
+ if((tok = get_tok(rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Skipping, Invalid rule trunicated when expecting ports protocol %s\n",rule);
+ return;
+ }
+ if((tmp=search_vars(tok,var_head,VCLASS_2))!=NULL)
+ {
+ bzero(ptok,256);
+ strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
+ tok=ptok;
+ }
+
+ pptr=tok;
+
+ proto = (u_int8_t) strtol(tok,&pptr,0);
+
+ if(tok==pptr)
+ {
+ syslog(LOG_ERR,"Skipping, Invalid protocol value found: %s\n",tok);
+ return;
+ }
+
+ while((tok = get_tok(rules,accept))!=NULL && *tok != 0)
+ {
+ if((tmp=search_vars(tok,var_head,VCLASS_3))!=NULL)
+ {
+ bzero(ptok,256);
+ strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
+ tok=ptok;
+ }
+ if((tmp = get_next_tok(&tok,"-"))!=NULL)
+ {
+ pptr=tmp;
+ port_l = (u_int16_t) strtol(tmp,&pptr,0);
+ if(tmp==pptr)
+ {
+ syslog(LOG_ERR,"Skipping, Invalid port start of range found: %s\n",tmp);
+ return;
+ }
+ pptr=tok;
+ port_h = (u_int16_t) strtol(tok,&pptr,0);
+ if(tok==pptr)
+ {
+ syslog(LOG_ERR,"Skipping, Invalid port end of range found: %s\n",tok);
+ return;
+ }
+ }else{
+ pptr=tok;
+ port_l = (u_int16_t) strtol(tok,&pptr,0);
+ if(tok==pptr)
+ {
+ syslog(LOG_ERR,"Skipping, Invalid port found: %X.\n",*tok);
+ return;
+ }
+#ifdef DEBUG
+ syslog(LOG_ERR,"Port found: %s\n",tok);
+#endif
+ port_h=port_l;
+ }
+ // if we made it this far we have a valid oort
+ if((n_ports=(struct t_ports *)calloc(1,sizeof(struct t_ports)))==NULL){ printf ("Out of Memory?\n"); return;}
+
+ n_ports->h_port=port_h;
+ n_ports->l_port=port_l;
+ n_ports->next=NULL;
+ if(!tports[proto]){
+ tports[proto]=n_ports;
+ }
+ else
+ {
+ n_ports->next = tports[proto];
+ tports[proto]=n_ports;
+ }
+ }
+ }else{
+ syslog(LOG_ERR,"Skipping, Invalid rule trunicated when expecting ports protocol %s\n",rule);
+ }
+}
+
+void parse_connection_rule(char *rule, struct vars *var_head, char *accept)
+{
+ // THIS FUNCTION DOES NOT EXIT THE PROGRAM WHEN IT RECEIVES A
+ // BAD RULE!!! THIS IS DONE TO ENSURE THIS TOOL CONTINUES COLLECTION
+ // SPECIFICALLY IN CASE IT READS A BAD CONFIGURATION FILE AFTER RECEIVING
+ // A KILL -HUP SIGNAL - SO ALWAYS CHECK THE SYSLOG FOR ERRORS
+ // IF THE DEFAULT PCAP MODE IS TO RECORD EVERYTHING THEN BAD RULES WILL
+ // NOT MEAN LOST DATA. YOU CAN ALWAYS RE-PROCESS PCAP DATA BUT CAN'T
+ // RECOVER FROM DATA YOU DIDN'T RECORD
+ char *tmp, *tok=NULL;
+ char **rules=NULL;
+ char *pptr=NULL;
+ char *ftmp=0;
+ char ptok[256];
+ struct acl *n_acl;
+ extern struct gvars gVars;
+ extern struct acl *tacl_head, *tacl_tail;
+ bzero(ptok,256);
+ rules=&rule;
+ if((n_acl=(struct acl *)calloc(1,sizeof(struct acl)))==NULL){ syslog (LOG_CRIT,"Unable to allocate ACL - Out of Memory!\n"); return;}
+ bzero(n_acl,sizeof(struct acl));
+ n_acl->next=NULL;
+ n_acl->cmode = CMODE_BOTH;
+ n_acl->pcap = gVars.pmode?1:0;
+ n_acl->pmode = gVars.pmode;
+ n_acl->stats = gVars.smode?1:0;
+ n_acl->smode = gVars.smode;
+ n_acl->realtime = gVars.rmode?1:0;
+ n_acl->rmode = gVars.rmode;
+ n_acl->timeout = gVars.default_timeout;
+ n_acl->limit = gVars.default_limit;
+ n_acl->status = gVars.default_status;
+ n_acl->rid = gVars.default_rid;
+ n_acl->tcplag = gVars.default_tcplag;
+ if(gVars.pfH && gVars.pmode){
+ n_acl->fH = gVars.pfH->attach();
+ }else{
+ n_acl->fH = 0;
+ }
+
+ // FIELD 0 - required - Get the h_proto
+ n_acl->h_proto_h = 0xFFFF;
+ n_acl->h_proto_l = 0x0000;
+ if((tok = get_tok(rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Skipping, Invalid rule trunicated when expecting hw protocol %s\n",rule);
+ free(n_acl);
+ return;
+ }
+ else if(strcmp(tok,"any")){
+ if((tmp=search_vars(tok,gVars.var_head,VCLASS_0))!=NULL)
+ {
+ bzero(ptok,256);
+ strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
+ tok=ptok;
+ }
+
+ if((tmp = get_next_tok(&tok,"-"))!=NULL)
+ {
+ pptr=tmp;
+ n_acl->h_proto_l = (u_int16_t) strtol(tmp,&pptr,0);
+ if(tmp==pptr)
+ {
+ syslog(LOG_ERR,"Skipping, Invalid start of h_proto range found: %s\n",tmp);
+ free(n_acl); return;
+ }
+ pptr=tok;
+ n_acl->h_proto_h = (u_int16_t) strtol(tok,&pptr,0);
+ if(tok==pptr)
+ {
+ syslog(LOG_ERR,"Skipping, Invalid end of h_proto range found: %s\n",tok);
+ free(n_acl); return;
+ }
+ }else{
+ pptr=tok;
+ n_acl->h_proto_l = (u_int16_t) strtol(tok,&pptr,0);
+ if(tok==pptr)
+ {
+ syslog(LOG_ERR,"Skipping, Invalid h_protocol value found: %s\n",tok);
+ free(n_acl);
+ return;
+ }
+ n_acl->h_proto_h = n_acl->h_proto_l;
+ }
+ }
+
+ // FIELD 1 - required - Get the source address and mask fields
+ n_acl->s_mask=0xFFFFFFFF;
+ n_acl->s_ip=0x00000000;
+
+ if((tok = get_tok(rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Skipping, Invalid rule trunicated when expecting source address and mask %s\n",rule);
+ free(n_acl);
+ return;
+ }
+ else if(strcmp(tok,"any")){
+ if((tmp=search_vars(tok,gVars.var_head,VCLASS_1))!=NULL)
+ {
+ bzero(ptok,256);
+ strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
+ tok=ptok;
+ }
+
+ if((tmp = get_next_tok(&tok,"/"))!=NULL)
+ {
+ if(inet_aton(tmp,(struct in_addr *)&n_acl->s_ip)==0)
+ {
+ syslog(LOG_ERR,"Skipping, Invalid source address found: %s/%s %s\n",tmp,tok,rule);
+ free(n_acl);
+ return;
+ }
+ if(strstr(tok,"."))
+ {
+ if(inet_aton(tok,(struct in_addr *)&n_acl->s_mask)==0)
+ {
+ syslog(LOG_ERR,"Skipping, Invalid source mask found: %s/%s %s\n",tmp,tok,rule);
+ free(n_acl);
+ return;
+ }
+ }
+ else
+ {
+ pptr=tok;
+ n_acl->s_mask=htonl(0xFFFFFFF<<(32-(u_int8_t)(strtol(tok,&pptr,0))));
+ if(tok==pptr)
+ {
+ syslog(LOG_ERR,"Skipping, Invalid source mask found: %s/%s %s\n",tmp,tok,rule);
+ free(n_acl);
+ return;
+ }
+ }
+ }else{
+ if(inet_aton(tok,(struct in_addr *)&n_acl->s_ip)==0)
+ {
+ syslog(LOG_ERR,"Skipping, Invalid source address found: %s %s\n",tok,rule);
+ free(n_acl);
+ return;
+ }
+ }
+ }
+ // FIELD 3 - required - Get the destination address and mask fields
+
+ n_acl->d_mask=0xFFFFFFFF;
+ n_acl->d_ip=0x00000000;
+
+ if((tok = get_tok(rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Skipping, Invalid rule trunicated when expecting destination address and mask %s\n",rule);
+ free(n_acl);
+ return;
+ }
+ else if(strcmp(tok,"any")){
+ if((tmp=search_vars(tok,gVars.var_head,VCLASS_1))!=NULL)
+ {
+ bzero(ptok,256);
+ strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
+ tok=ptok;
+ }
+ if((tmp = get_next_tok(&tok,"/"))!=NULL)
+ {
+ if(inet_aton(tmp,(struct in_addr *)&n_acl->d_ip)==0)
+ {
+ syslog(LOG_ERR,"Skipping, Invalid destination address found: %s/%s %s\n",tmp,tok,rule);
+ free(n_acl);
+ return;
+ }
+ if(strstr(tok,"."))
+ {
+ if(inet_aton(tok,(struct in_addr *)&n_acl->d_mask)==0)
+ {
+ syslog(LOG_ERR,"Skipping, Invalid destination mask found: %s/%s %s\n",tmp,tok,rule);
+ free(n_acl);
+ return;
+ }
+ }
+ else
+ {
+ pptr=tok;
+ n_acl->d_mask=htonl(0xFFFFFFFF<<(32-(u_int8_t)(strtol(tok,&pptr,0))));
+ if(tok==pptr)
+ {
+ syslog(LOG_ERR,"Skipping, Invalid destination mask found: %s/%s %s\n",tmp,tok,rule);
+ free(n_acl);
+ return;
+ }
+ }
+ }else{
+ if(inet_aton(tok,(struct in_addr *)&n_acl->d_ip)==0)
+ {
+ syslog(LOG_ERR,"Skipping, Invalid destination address found: %s %s\n",tok,rule);
+ free(n_acl);
+ return;
+ }
+ }
+ }
+
+ // FIELD 4 - required - Get the protocol field
+ n_acl->proto_l = 0x00;
+ n_acl->proto_h = 0xFF;
+ if((tok = get_tok(rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Skipping, Invalid rule trunicated when expecting protocol %s\n",rule);
+ free(n_acl);
+ return;
+ }
+ else if(strcmp(tok,"any")){
+ if((tmp=search_vars(tok,gVars.var_head,VCLASS_2))!=NULL)
+ {
+ bzero(ptok,256);
+ strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
+ tok=ptok;
+ }
+
+ // Use the defaults for ANY
+ if((tmp = get_next_tok(&tok,"-"))!=NULL)
+ {
+ pptr=tmp;
+ n_acl->proto_l = (u_int8_t) strtol(tmp,&pptr,0);
+ if(tmp==pptr)
+ {
+ syslog(LOG_ERR,"Skipping, Invalid start of proto range found: %s\n",tmp);
+ free(n_acl); return;
+ }
+ pptr=tok;
+ n_acl->proto_h = (u_int8_t) strtol(tok,&pptr,0);
+ if(tok==pptr)
+ {
+ syslog(LOG_ERR,"Skipping, Invalid end of proto range found: %s\n",tok);
+ free(n_acl); return;
+ }
+ }else{
+ pptr=tok;
+ n_acl->proto_l = (u_int8_t) strtol(tok,&pptr,0);
+ if(tok==pptr)
+ {
+ syslog(LOG_ERR,"Skipping, Invalid protocol value found: %s\n",tok);
+ free(n_acl);
+ return;
+ }
+ n_acl->proto_h = n_acl->proto_l;
+ }
+ }
+
+ // FIELD 5 - required - Get the source ports field
+
+ n_acl->s_port_l=0x0000;
+ n_acl->s_port_h=0xFFFF;
+
+ if((tok = get_tok(rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Skipping, Invalid rule trunicated when expecting source ports %s\n",rule);
+ free(n_acl);
+ return;
+ }
+ else if(strcmp(tok,"any")){
+ if((tmp=search_vars(tok,gVars.var_head,VCLASS_3))!=NULL)
+ {
+ bzero(ptok,256);
+ strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
+ tok=ptok;
+ }
+
+ // Use the defaults for ANY
+ if((tmp = get_next_tok(&tok,"-"))!=NULL)
+ {
+ pptr=tmp;
+ n_acl->s_port_l = (u_int16_t) strtol(tmp,&pptr,0);
+ if(tmp==pptr)
+ {
+ syslog(LOG_ERR,"Skipping, Invalid source port start of range found: %s\n",tmp);
+ free(n_acl);
+ return;
+ }
+ pptr=tok;
+ n_acl->s_port_h = (u_int16_t) strtol(tok,&pptr,0);
+ if(tok==pptr)
+ {
+ syslog(LOG_ERR,"Skipping, Invalid source port end of range found: %s\n",tok);
+ free(n_acl);
+ return;
+ }
+ }else{
+ pptr=tok;
+ n_acl->s_port_l = (u_int16_t) strtol(tok,&pptr,0);
+ if(tok==pptr)
+ {
+ syslog(LOG_ERR,"Skipping, Invalid source port found: %s\n",tok);
+ free(n_acl);
+ return;
+ }
+ n_acl->s_port_h=n_acl->s_port_l;
+ }
+ }
+ // FIELD 6 - required - Get the destination ports field
+
+ n_acl->d_port_l=0x0000;
+ n_acl->d_port_h=0xFFFF;
+
+ if((tok = get_tok(rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Skipping, Invalid rule trunicated when expecting destination ports %s\n",rule);
+ free(n_acl);
+ return;
+ }
+ else if(strcmp(tok,"any")){
+
+
+ if((tmp=search_vars(tok,gVars.var_head,VCLASS_3))!=NULL)
+ {
+ bzero(ptok,256);
+ strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
+ tok=ptok;
+ }
+
+ if((tmp = get_next_tok(&tok,"-"))!=NULL )
+ {
+ pptr=tmp;
+ n_acl->d_port_l = (u_int16_t) strtol(tmp,&pptr,0);
+ if(tmp==pptr)
+ {
+ syslog(LOG_ERR,"Skipping, Invalid destination port start of range found: %s\n",tmp);
+ free(n_acl);
+ return;
+ }
+ pptr=tok;
+ n_acl->d_port_h = (u_int16_t) strtol(tok,&pptr,0);
+ if(tok==pptr)
+ {
+ syslog(LOG_ERR,"Skipping, Invalid destination port end of range found: %s\n",tok);
+ free(n_acl);
+ return;
+ }
+ }else{
+ pptr=tok;
+ n_acl->d_port_l = (u_int16_t) strtol(tok,&pptr,0);
+ if(tok==pptr)
+ {
+ syslog(LOG_ERR,"Skipping, Invalid destination port found: %s\n",tok);
+ free(n_acl);
+ return;
+ }
+ n_acl->d_port_h=n_acl->d_port_l;
+ }
+ }
+
+ // REMAINING FIELDs - not required - limit and timeout
+
+ while((tok = get_tok(rules,accept))!=NULL && *tok!=0 )
+ {
+ if(strcmp(tok,"rid")==0)
+ {
+ if((tmp = get_tok(rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, rid specified but none provided, using default rid %u\n",gVars.default_rid);
+ return;
+ }
+ if((tok=search_vars(tmp,gVars.var_head,VCLASS_4))!=NULL)
+ {
+ bzero(ptok,256);
+ strncpy(ptok,tok,sizeof(char)*strlen(tok));
+ tmp=ptok;
+ }
+ pptr=tmp;
+ n_acl->rid = (u_int32_t) strtol(tmp,&pptr,0);
+ if(tmp==pptr)
+ {
+ syslog(LOG_ERR,"Format error, invalid rid %s, using default rid %u\n",tmp,gVars.default_rid);
+ // Let's restore the delimiter and put back our token
+ // this might be the next option
+ tmp[sizeof(tmp)-1]=' ';
+ *rules=tmp;
+ }
+ continue;
+ }
+ if(strcmp(tok,"rgid")==0)
+ {
+ if((tmp = get_tok(rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, rgid specified but none provided, using default rgid %u\n",gVars.default_rgid);
+ return;
+ }
+ if((tok=search_vars(tmp,gVars.var_head,VCLASS_5))!=NULL)
+ {
+ bzero(ptok,256);
+ strncpy(ptok,tok,sizeof(char)*strlen(tok));
+ tmp=ptok;
+ }
+ pptr=tmp;
+ n_acl->rgid = (u_int32_t) strtol(tmp,&pptr,0);
+ if(tmp==pptr)
+ {
+ syslog(LOG_ERR,"Format error, invalid rgid %s, using default rgid %u\n",tmp,gVars.default_rgid);
+ // Let's restore the delimiter and put back our token
+ // this might be the next option
+ tmp[sizeof(tmp)-1]=' ';
+ *rules=tmp;
+ }
+ continue;
+ }
+ if(strcmp(tok,"zone")==0)
+ {
+ if((tmp = get_tok(rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, zone specified but none provided, using default zone %d\n",gVars.default_zone);
+ return;
+ }
+ if((tok=search_vars(tmp,gVars.var_head,VCLASS_6))!=NULL)
+ {
+ bzero(ptok,256);
+ strncpy(ptok,tok,sizeof(char)*strlen(tok));
+ tmp=ptok;
+ }
+ pptr=tmp;
+ n_acl->zone = (u_int16_t) strtol(tmp,&pptr,0);
+ if(tmp==pptr)
+ {
+ syslog(LOG_ERR,"Format error, invalid zone %s, using default zone %d\n",tmp,gVars.default_zone);
+ // Let's restore the delimiter and put back our token
+ // this might be the next option
+ tmp[sizeof(tmp)-1]=' ';
+ *rules=tmp;
+ }
+ continue;
+ }
+ if(strcmp(tok,"node")==0)
+ {
+ if((tmp = get_tok(rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, node specified but none provided, using default node %d\n",gVars.default_node);
+ return;
+ }
+ if((tok=search_vars(tmp,gVars.var_head,VCLASS_7))!=NULL)
+ {
+ bzero(ptok,256);
+ strncpy(ptok,tok,sizeof(char)*strlen(tok));
+ tmp=ptok;
+ }
+ pptr=tmp;
+ n_acl->node = (u_int16_t) strtol(tmp,&pptr,0);
+ if(tmp==pptr)
+ {
+ syslog(LOG_ERR,"Format error, invalid node %s, using default node %d\n",tmp,gVars.default_node);
+ // Let's restore the delimiter and put back our token
+ // this might be the next option
+ tmp[sizeof(tmp)-1]=' ';
+ *rules=tmp;
+ }
+ continue;
+ }
+ if(strcmp(tok,"status")==0)
+ {
+ if((tmp = get_tok(rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, status specified but none provided, using default status %d\n",gVars.default_status);
+ return;
+ }
+ if((tok=search_vars(tmp,gVars.var_head,VCLASS_8))!=NULL)
+ {
+ bzero(ptok,256);
+ strncpy(ptok,tok,sizeof(char)*strlen(tok));
+ tmp=ptok;
+ }
+ pptr=tmp;
+ n_acl->status = (u_int8_t) strtol(tmp,&pptr,0);
+ if(tmp==pptr)
+ {
+ syslog(LOG_ERR,"Format error, invalid status %s, using default status %d\n",tmp,gVars.default_status);
+ // Let's restore the delimiter and put back our token
+ // this might be the next option
+ tmp[sizeof(tmp)-1]=' ';
+ *rules=tmp;
+ }
+ continue;
+ }
+ if(strcmp(tok,"timeout")==0)
+ {
+ if((tmp = get_tok(rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, timeout specified but none provided, using default timeout %d\n",gVars.default_timeout);
+ return;
+ }
+ pptr=tmp;
+ n_acl->timeout = (u_int16_t) strtol(tmp,&pptr,0);
+ if(tmp==pptr)
+ {
+ syslog(LOG_ERR,"Format error, invalid timeout %s, using default timeout\n",tmp);
+ // Let's restore the delimiter and put back our token
+ // this might be the next option
+ tmp[sizeof(tmp)-1]=' ';
+ *rules=tmp;
+ }
+ continue;
+ }
+ if(strcmp(tok,"tcplag")==0)
+ {
+ if((tmp = get_tok(rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, tcplag specified but none provided, using default tcplag %d\n",gVars.default_tcplag);
+ return;
+ }
+ pptr=tmp;
+ n_acl->tcplag = (u_int16_t) strtol(tmp,&pptr,0);
+ if(tmp==pptr)
+ {
+ syslog(LOG_ERR,"Format error, invalid tcplag %s, using default tcplag \n",tmp);
+
+ tmp[sizeof(tmp)-1]=' ';
+ *rules=tmp;
+ }
+ continue;
+ }
+ if(strcmp(tok,"limit")==0)
+ {
+ if((tmp = get_tok(rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, limit specified but none provided, using default limit %llu\n",(long long unsigned)gVars.default_limit);
+ return;
+ }
+ pptr=tmp;
+ n_acl->limit = (u_int64_t) strtol(tmp,&pptr,0);
+ if(tmp==pptr)
+ {
+ syslog(LOG_ERR,"Format error, invalid limit %s, using default limit %llu\n",tmp,(long long unsigned)gVars.default_limit);
+ // Let's restore the delimiter and put back our token
+ // this might be the next option
+ tmp[sizeof(tmp)-1]=' ';
+ *rules=tmp;
+ }
+ continue;
+ }
+ if(strcmp(tok,"realtime")==0)
+ {
+ if((tmp = get_tok(rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, realtime specified but no option provided%s\n",rule);
+ return;
+ }
+ if(strcmp(tmp,"log")==0) // log all matching traffic
+ {
+ n_acl->realtime = ACTION_LOG;
+ n_acl->rmode = OMODE_LOG;
+ continue;
+ }
+ if(strcmp(tmp,"pass")==0)
+ {
+ n_acl->realtime = ACTION_PASS;
+ n_acl->rmode = OMODE_PASS;
+ continue;
+ }
+ syslog(LOG_ERR,"Skipping, invalid realtime option in rule: %s %s\n",tok,tmp);
+ return;
+ }
+ if(strcmp(tok,"stats")==0)
+ {
+ if((tmp = get_tok(rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, stats specified but no option provided%s\n",rule);
+ return;
+ }
+ if(strcmp(tmp,"log")==0) // log all matching traffic
+ {
+ n_acl->stats=ACTION_LOG;
+ n_acl->smode=OMODE_LOG;
+ continue;
+ }
+ if(strcmp(tmp,"pass")==0)
+ {
+ n_acl->stats = ACTION_PASS;
+ n_acl->smode = OMODE_PASS;
+ continue;
+ }
+ syslog(LOG_ERR,"Skipping, invalid stats option in rule: %s %s\n",tok,tmp);
+ return;
+ }
+ if(strcmp(tok,"pcap")==0)
+ {
+ if((tmp = get_tok(rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, output specified but none provided, using default output%s\n",rule);
+ return;
+ }
+ if(strcmp(tmp,"log")==0) // log all matching traffic
+ {
+ if(n_acl->fH){ n_acl->fH->destroy(); n_acl->fH=0; }
+ n_acl->fH = gVars.pfH->attach();
+ n_acl->pcap = ACTION_LOG;
+ n_acl->pmode = OMODE_LOG;
+ continue;
+ }
+ if(strcmp(tmp,"pass")==0)
+ {
+ if(n_acl->fH){ n_acl->fH->destroy(); n_acl->fH=0; }
+ n_acl->fH = 0;
+ n_acl->pcap = ACTION_PASS;
+ n_acl->pmode = OMODE_PASS;
+ n_acl->cmode = CMODE_NONE;
+ continue;
+ }
+ if(strcmp(tmp,"rule")==0)
+ {
+ if(n_acl->fH){ n_acl->fH->destroy(); n_acl->fH=0; }
+ n_acl->fH = new pcapFileHandle(createPcapFileName(n_acl));
+ n_acl->pcap = ACTION_LOG;
+ n_acl->pmode=OMODE_RULE;
+ continue;
+ }
+ if(strcmp(tmp,"connection")==0)
+ {
+ n_acl->fH=0;
+ n_acl->pcap = ACTION_LOG;
+ n_acl->pmode=OMODE_UNIQ;
+ continue;
+ }
+ if(strcmp(tmp,"filename")==0)
+ {
+ if((tmp = get_tok(rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, filename specified but none provided, using default filename %s\n",rule);
+ return;
+ }else{
+ if(n_acl->fH){ n_acl->fH->destroy(); n_acl->fH=0; }
+ // Create this filename without a timestamp
+ ftmp=createFileName(tmp,false);
+ n_acl->fH = new pcapFileHandle(ftmp);
+ free(ftmp);
+ n_acl->pcap = ACTION_LOG;
+ n_acl->pmode=OMODE_FILENAME;
+ }
+ continue;
+ }
+ if(strcmp(tmp,"tsfilename")==0)
+ {
+ if((tmp = get_tok(rules,accept))==NULL)
+ {
+ syslog(LOG_ERR,"Format error, tsfilename specified but none provided, using default pcap output file%s\n",rule);
+ return;
+ }else{
+ if(n_acl->fH){ n_acl->fH->destroy(); n_acl->fH=0; }
+ // Create this filename with a timestamp
+ ftmp=createFileName(tmp,true);
+ n_acl->fH = new pcapFileHandle(ftmp);
+ free(ftmp);
+ n_acl->pcap = ACTION_LOG;
+ n_acl->pmode=OMODE_TSFILENAME;
+ }
+ continue;
+ }
+ syslog(LOG_ERR,"Skipping, invalid pcap option in rule: %s %s\n",tok,tmp);
+ return;
+ }
+ if(strcmp(tok,"logdst")==0)
+ {
+ n_acl->cmode = CMODE_DST;
+ continue;
+ }
+ if(strcmp(tok,"logsrc")==0)
+ {
+ n_acl->cmode = CMODE_SRC;
+ continue;
+ }
+ if(strcmp(tok,"ignore")==0)
+ {
+ // We should ignore everything for this rule
+ n_acl->stats=n_acl->realtime=n_acl->pcap=ACTION_PASS;
+ n_acl->cmode = CMODE_NONE;
+ n_acl->pmode = OMODE_PASS;
+ continue;
+ }
+ if(strcmp(tok,"retro")==0) // Apply rule to pre-existing connections in memory
+ {
+ n_acl->retro = true;
+ continue;
+ }
+ syslog(LOG_ERR,"Skipping, invalid option in rule: %s %s\n", tok,*rules);
+ return;
+ }
+ // If we made it this far, the rule is good
+ // So we will add it to our list
+ if(tacl_head){
+ tacl_tail->next=n_acl;
+ }else{
+ tacl_head=n_acl;
+ }
+ tacl_tail=n_acl;
+ if(n_acl->retro){
+ #ifdef DEBUG
+ printf("Applying rule retro-actively!\n");
+ #endif
+ retroactive(n_acl);
+ }
+
+}
+/*
+ * char * get_tok (char **rule, const char *delimiters )
+ * Uses strpbrk to locate the first occurrance of a character in *delimiters,
+ * replaces this character with a null '\0', modifying **rule to point
+ * one byte past the delimiter character.
+ *
+ * Returns pointer to beginning of token, or NULL if no delimiter is found.
+ *
+ */
+
+// Returns the rule you were pointing to and modifies rule
+char * get_tok(char **rule, const char *delimiters)
+{
+ char *tok=*rule;
+ char *tmp=0;
+ int len=0;
+ if(*rule==NULL)
+ return NULL;
+ len=strlen(tok);
+
+ if((tmp = strpbrk(*rule,delimiters))!=NULL){
+ *tmp=0;
+ if(tmp>*rule)
+ *rule=++tmp;
+ } else {
+ *rule=NULL;
+ }
+ return tok;
+}
+
+// Returns next tok or NULL
+char * get_next_tok(char **rule, const char *delimiters)
+{
+ char *tok=*rule;
+ char *tmp;
+ int len=0;
+ if(*rule==NULL)
+ return NULL;
+ len=strlen(tok);
+
+ if((tmp = strpbrk(*rule,delimiters))!=NULL){
+ *tmp='\0';
+ if(tmp>*rule)
+ *rule=++tmp;
+ return tok;
+ } else {
+ return NULL;
+ }
+}
+
+void print_acl(int a){
+ extern struct gvars gVars;
+ struct t_ports *tmp_port;
+ struct t_ports *ports_head;
+ char currenttime[80];
+ time_t timestr=gVars.timeptr.tv_sec;
+ struct acl* tmpptr;
+ int p, cidr,bits;
+ char ptok[256];
+ char *tmp;
+ u_int32_t tmpint;
+ char LOG[1024];
+ tmpptr=gVars.acl_head;
+ if(gVars.uselocaltime){
+ strftime(currenttime,80,"%Y-%m-%d %T",(struct tm *)localtime(&timestr));
+ }else{
+ strftime(currenttime,80,"%Y-%m-%d %T GMT",(struct tm *)gmtime(&timestr));
+ }
+ bzero(LOG,1024);
+ sprintf(LOG,"#\n# Running configuration as of %s\n#\n",currenttime);
+ LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
+ char type[10][36]={ {"unused or unassociated vars"},{"ethernet protocols"},{"networks and hosts"},{"ip protocols"},{"udp/tcp ports"},{ "rule ids"},{"rule groups (kinds of traffic)"},{"zones"},{"nodes"},{"status"}};
+ int unused=0;
+ struct vars *tvars=gVars.var_head;
+ for(int x=1; x<10; x++){
+ sprintf(LOG,"\n#\n# defined %s\n#\n",type[x]);
+ LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
+ while(tvars!=NULL){
+ if(tvars->vclass==x){
+ sprintf(LOG,"var %s %s\n",tvars->key,tvars->value);
+ LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
+ }
+ if(tvars->vclass==0){ unused=1; }
+ tvars=tvars->next;
+ }
+ tvars=gVars.var_head;
+ }
+ if(unused){
+ sprintf(LOG,"\n#\n# %s\n#\n",type[0]);
+ LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
+ while(tvars!=NULL){
+ if(tvars->vclass==0){
+ sprintf(LOG,"var %s %s\n",tvars->key,tvars->value);
+ LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
+ }
+ tvars=tvars->next;
+ }
+ }
+ sprintf(LOG,"\n#\n# define defaults\n#\n");
+ LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
+ if(gVars.rmode==OMODE_FILENAME){
+ sprintf(LOG,"default realtime filename %s\n",gVars.realtime_fname);
+ }else if(gVars.rmode==OMODE_TSFILENAME){
+ sprintf(LOG,"default realtime tsfilename %s\n",gVars.realtime_fname);
+ }else{
+ sprintf(LOG,"default realtime=%s\n",gVars.pmode?"log":"pass");
+ }
+ LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
+ if(gVars.smode==OMODE_FILENAME){
+ sprintf(LOG,"default stats filename %s\n",gVars.stats_fname);
+ }else if(gVars.smode==OMODE_TSFILENAME){
+ sprintf(LOG,"default stats tsfilename %s\n",gVars.stats_fname);
+ }else{
+ sprintf(LOG,"default stats=%s\n",gVars.smode?"log":"pass");
+ }
+ LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
+ if(gVars.pmode==OMODE_FILENAME){
+ sprintf(LOG,"default pcap filename %s\n",gVars.pcap_fname);
+ }else if(gVars.pmode==OMODE_TSFILENAME){
+ sprintf(LOG,"default pcap tsfilename %s\n",gVars.pcap_fname);
+ }else{
+ sprintf(LOG,"default pcap=%s\n",gVars.pmode?"log":"pass");
+ }
+ LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
+ if(gVars.pcap_raw){
+ sprintf(LOG,"default debug_pcap_raw=%s\n",gVars.pcap_raw?"enable":"disable");
+ LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
+ }
+ if(gVars.strip_80211){
+ sprintf(LOG,"default strip-80211=%s\n",gVars.strip_80211?"enable":"disable");
+ LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
+ }
+ sprintf(LOG,"default flush_interval=%u\n",gVars.default_flush_interval);
+ LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
+ sprintf(LOG,"default expire_interval=%u\n",gVars.default_expire_interval);
+ LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
+ sprintf(LOG,"default burst_mode=%s\n",gVars.burst_mode?"enable":"disable");
+ LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
+ sprintf(LOG,"default status=%u\n",gVars.default_status);
+ LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
+ sprintf(LOG,"default node=%u\n",gVars.default_node);
+ LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
+ sprintf(LOG,"default zone=%u\n",gVars.default_zone);
+ LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
+ sprintf(LOG,"default rid=%u\n",gVars.default_rid);
+ LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
+ sprintf(LOG,"default rgid=%u\n",gVars.default_rgid);
+ LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
+ sprintf(LOG,"default timeout=%d\n",gVars.default_timeout);
+ LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
+ sprintf(LOG,"default limit=%llu\n",(long long unsigned)gVars.default_limit);
+ LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
+ sprintf(LOG,"default tcplag=%d\n",gVars.default_tcplag);
+ LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
+ if(gVars.bpf_filter){
+ sprintf(LOG,"default pcapfilter \"%s\"\n",gVars.bpf_filter);
+ LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
+ }
+ sprintf(LOG,"\n#\n# define known_ports\n#\n");
+ LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
+ for(p=0; p<MAX_IP_PROTO; p++)
+ {
+ ports_head=gVars.ports[p];
+ if(ports_head!=NULL)
+ {
+ strcat(LOG,"known_ports");
+
+ bzero(ptok,256);
+ sprintf(ptok,"%d",p);
+ if((tmp=rev_search_vars(ptok,gVars.var_head,VCLASS_2))!=NULL)
+ {
+ bzero(ptok,256);
+ strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
+ }
+ sprintf(LOG,"%s %s ",LOG,ptok);
+
+ while(ports_head!=NULL){
+ tmp_port=ports_head;
+ ports_head=tmp_port->next;
+ bzero(ptok,256);
+ sprintf(ptok,"%d",tmp_port->l_port);
+ if(tmp_port->l_port!=tmp_port->h_port)
+ sprintf(ptok,"%s-%d",ptok,tmp_port->h_port);
+ if((tmp=rev_search_vars(ptok,gVars.var_head,VCLASS_3))!=NULL)
+ {
+ bzero(ptok,256);
+ strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
+ }
+ sprintf(LOG,"%s%s",LOG,ptok);
+ if(tmp_port->next)
+ strcat(LOG,",");
+ }
+ strcat(LOG,"\n");
+ LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
+ }
+ }
+ sprintf(LOG,"\n#\n# Running rules as of %s\n#\n",currenttime);
+ LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
+ while(tmpptr!=NULL){
+ //
+ // ETHPROTO (VCLASS_0)
+ //
+
+ bzero(ptok,256);
+ if(tmpptr->h_proto_l==tmpptr->h_proto_h){
+ sprintf(ptok,"%d",tmpptr->h_proto_l);
+ }else{
+ sprintf(ptok,"%d-%d",tmpptr->h_proto_l,tmpptr->h_proto_h);
+ }
+ if((tmp=rev_search_vars(ptok,gVars.var_head,VCLASS_0))!=NULL){
+ bzero(ptok,256);
+ strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
+ }else if(tmpptr->h_proto_l==0 && tmpptr->h_proto_h==0xFFFF ){
+ bzero(ptok,256);
+ strncpy(ptok,"any",sizeof(char)*strlen("any"));
+ }
+ sprintf(LOG,"%s ",ptok);
+ LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
+
+ //
+ // SOURCE IP (VCLASS_1)
+ //
+
+ bzero(ptok,256);
+ sprintf(ptok,"%s",inet_ntoa(*(struct in_addr*) &tmpptr->s_ip));
+ if(tmpptr->s_mask!=0xFFFFFFFF){
+ tmpint = htonl(tmpptr->s_mask);
+ cidr=bits=0;
+ while((tmpint&0xC0000000)!=0x40000000){
+ bits++;
+ if((tmpint&0xC0000000)!=0xC0000000){ cidr=bits; break; }
+ tmpint<<=1;
+ }
+ if(htonl(tmpptr->s_mask)==(u_int32_t)(0xFFFFFFFF<<(32-cidr))){
+ sprintf(ptok,"%s/%d",ptok,cidr);
+ }else{
+ sprintf(ptok,"%s/%s",ptok,inet_ntoa(*(struct in_addr*) &tmpptr->s_mask));
+ }
+ }
+ if((tmp=rev_search_vars(ptok,gVars.var_head,VCLASS_1))!=NULL) {
+ bzero(ptok,256);
+ strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
+ }else if(tmpptr->s_ip==0){
+ bzero(ptok,256);
+ strncpy(ptok,"any",sizeof(char)*strlen("any"));
+ }
+ sprintf(LOG,"%s ",ptok);
+ LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
+
+ //
+ // DESTINATION IP (VCLASS_1)
+ //
+
+ bzero(ptok,256);
+ sprintf(ptok,"%s",inet_ntoa(*(struct in_addr*) &tmpptr->d_ip));
+ if(tmpptr->d_mask!=0xFFFFFFFF){
+ tmpint = htonl(tmpptr->d_mask);
+ cidr=bits=0;
+ while((tmpint&0xC0000000)!=0x40000000){
+ bits++;
+ if((tmpint&0xC0000000)!=0xC0000000){ cidr=bits; break; }
+ tmpint<<=1;
+ }
+ if(htonl(tmpptr->d_mask)==(u_int32_t)(0xFFFFFFFF<<(32-cidr))){
+ sprintf(ptok,"%s/%d",ptok,cidr);
+ }else{
+ sprintf(ptok,"%s/%s",ptok,inet_ntoa(*(struct in_addr*) &tmpptr->d_mask));
+ }
+ }
+ if((tmp=rev_search_vars(ptok,gVars.var_head,VCLASS_1))!=NULL) {
+ bzero(ptok,256);
+ strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
+ }else if(tmpptr->d_ip==0){
+ bzero(ptok,256);
+ strncpy(ptok,"any",sizeof(char)*strlen("any"));
+ }
+ sprintf(LOG,"%s ",ptok);
+ LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
+
+ //
+ // IPPROTO (VCLASS_2)
+ //
+
+ bzero(ptok,256);
+ sprintf(ptok,"%d",tmpptr->proto_l);
+ if(tmpptr->proto_l!=tmpptr->proto_h){
+ sprintf(ptok,"%s-%d",ptok,tmpptr->proto_h);
+ }
+ if((tmp=rev_search_vars(ptok,gVars.var_head,VCLASS_2))!=NULL) {
+ bzero(ptok,256);
+ strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
+ }else if(tmpptr->proto_l==0x00 && tmpptr->proto_h==0xFF){
+ bzero(ptok,256);
+ strncpy(ptok,"any",sizeof(char)*strlen("any"));
+ }
+ sprintf(LOG,"%s ",ptok);
+ LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
+
+ //
+ // Source TCP_UDP_PORT (VCLASS_3)
+ //
+
+ bzero(ptok,256);
+ sprintf(ptok,"%d",tmpptr->s_port_l);
+ if(tmpptr->s_port_l!=tmpptr->s_port_h){
+ sprintf(ptok,"%s-%d",ptok,tmpptr->s_port_h);
+ }
+ if((tmp=rev_search_vars(ptok,gVars.var_head,VCLASS_2))!=NULL) {
+ bzero(ptok,256);
+ strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
+ }else if(tmpptr->s_port_l==0 && tmpptr->s_port_h==0xFFFF){
+ bzero(ptok,256);
+ strncpy(ptok,"any",sizeof(char)*strlen("any"));
+ }
+ sprintf(LOG,"%s ",ptok);
+ LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
+
+ //
+ // Destination TCP_UDP_PORT (VCLASS_3)
+ //
+
+ bzero(ptok,256);
+ sprintf(ptok,"%d",tmpptr->d_port_l);
+ if(tmpptr->d_port_l!=tmpptr->d_port_h){
+ sprintf(ptok,"%s-%d",ptok,tmpptr->d_port_h);
+ }
+ if((tmp=rev_search_vars(ptok,gVars.var_head,VCLASS_2))!=NULL) {
+ bzero(ptok,256);
+ strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
+ }else if(tmpptr->d_port_l==0 && tmpptr->d_port_h==0xFFFF){
+ bzero(ptok,256);
+ strncpy(ptok,"any",sizeof(char)*strlen("any"));
+ }
+ sprintf(LOG,"%s",ptok);
+ LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
+
+ //
+ // Logging options
+ //
+
+ if(!tmpptr->stats && !tmpptr->realtime && !tmpptr->pcap){
+ // no logging options are enabled
+ strcat(LOG,", ignore");
+ }else{
+ //
+ // Only display logging actions that differ from the default logging actions
+ //
+ //
+ // STATS
+ //
+ if(tmpptr->stats!=gVars.smode){
+ strcat(LOG,", stats");
+ if(tmpptr->smode==OMODE_PASS)
+ strcat(LOG,"=pass");
+ else if(tmpptr->smode==OMODE_LOG)
+ strcat(LOG,"=log");
+ }
+ //
+ // REALTIME
+ //
+ if(tmpptr->realtime!=gVars.rmode){
+ strcat(LOG,", realtime");
+ if(tmpptr->rmode==OMODE_PASS)
+ strcat(LOG,"=pass");
+ else if(tmpptr->rmode==OMODE_LOG)
+ strcat(LOG,"=log");
+ }
+ //
+ // PCAP
+ //
+ if(tmpptr->pmode!=gVars.pmode){
+ strcat(LOG,", pcap");
+ if(tmpptr->pmode==OMODE_PASS)
+ strcat(LOG,"=pass");
+ else if(tmpptr->pmode==OMODE_LOG)
+ strcat(LOG,"=log");
+ else if(tmpptr->pmode==OMODE_RULE)
+ strcat(LOG,"=rule");
+ else if(tmpptr->pmode==OMODE_UNIQ)
+ strcat(LOG,"=connection");
+ else if(tmpptr->pmode==OMODE_FILENAME && gVars.pfH->getFileHandle()!=tmpptr->fH->getFileHandle())
+ sprintf(LOG,"%s filename=%s",LOG,tmpptr->fH->getFileName());
+ else if(tmpptr->pmode==OMODE_TSFILENAME)
+ sprintf(LOG,"%s tsfilename=%s",LOG,tmpptr->fH->getFileName());
+ }
+ //
+ // Half-stream direction collection flag
+ //
+ if(tmpptr->cmode==CMODE_SRC)
+ strcat(LOG,", logsrc");
+ if(tmpptr->cmode==CMODE_DST)
+ strcat(LOG,", logdst");
+ }
+
+ //
+ // REMAINING OPTIONS
+ //
+
+ // LIMIT
+ if(tmpptr->limit!=gVars.default_limit)
+ sprintf(LOG,"%s, limit=%llu",LOG,(long long unsigned)tmpptr->limit);
+ // TIMEOUT
+ if(tmpptr->timeout!=gVars.default_timeout)
+ sprintf(LOG,"%s, timeout=%d",LOG,tmpptr->timeout);
+ // TCPLAG
+ if(tmpptr->tcplag!=gVars.default_tcplag)
+ sprintf(LOG,"%s, tcplag=%d",LOG,tmpptr->tcplag);
+ // RID VCLASS_4
+ if(tmpptr->rid)
+ {
+ bzero(ptok,256);
+ sprintf(ptok,"%u",tmpptr->rid);
+ if((tmp=rev_search_vars(ptok,gVars.var_head,VCLASS_4))!=NULL) {
+ bzero(ptok,256);
+ strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
+ }
+ sprintf(LOG,"%s, rid=%s",LOG,ptok);
+ }
+ // RGID VCLASS_5
+ if(tmpptr->rgid)
+ {
+ bzero(ptok,256);
+ sprintf(ptok,"%u",tmpptr->rgid);
+ if((tmp=rev_search_vars(ptok,gVars.var_head,VCLASS_5))!=NULL) {
+ bzero(ptok,256);
+ strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
+ }
+ sprintf(LOG,"%s, rgid=%s",LOG,ptok);
+ }
+ // ZONE VCLASS_6
+ if(tmpptr->zone)
+ {
+ bzero(ptok,256);
+ sprintf(ptok,"%u",tmpptr->zone);
+ if((tmp=rev_search_vars(ptok,gVars.var_head,VCLASS_6))!=NULL) {
+ bzero(ptok,256);
+ strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
+ }
+ sprintf(LOG,"%s, zone=%s",LOG,ptok);
+ }
+ // NODE VCLASS_7
+ if(tmpptr->node)
+ {
+ bzero(ptok,256);
+ sprintf(ptok,"%u",tmpptr->node);
+ if((tmp=rev_search_vars(ptok,gVars.var_head,VCLASS_7))!=NULL) {
+ bzero(ptok,256);
+ strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
+ }
+ sprintf(LOG,"%s, node=%s",LOG,ptok);
+ }
+ // STATUS VCLASS_8
+ if(tmpptr->status!=gVars.default_status)
+ {
+ bzero(ptok,256);
+ sprintf(ptok,"%u",tmpptr->status);
+ if((tmp=rev_search_vars(ptok,gVars.var_head,VCLASS_8))!=NULL) {
+ bzero(ptok,256);
+ strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
+ }
+ sprintf(LOG,"%s, status=%s",LOG,ptok);
+ }
+ // RETRO
+ if(tmpptr->retro)
+ strcat(LOG,", retro");
+
+ // DEFAULT RULE MATCHES
+ sprintf(LOG,"%s # Matches: %d\n",LOG,tmpptr->ctr);
+
+ tmpptr=tmpptr->next;
+ LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
+ }
+ sprintf(LOG,"# Implicit rule matches: %d\n",gVars.default_ctr);
+ LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
+ if(gVars.username || gVars.groupname){
+ sprintf(LOG,"# Running as: %s:%s\n",gVars.username,gVars.groupname);
+ LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
+ }
+ if(gVars.config_file){
+ sprintf(LOG,"# Configuration file: %s \n",gVars.config_file?gVars.config_file:"CWD");
+ LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
+ }
+ if(gVars.log_directory){
+ sprintf(LOG,"# Output directory: %s \n",gVars.log_directory);
+ LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
+ }
+ if(gVars.input_filename){
+ sprintf(LOG,"# Reading from file: %s \n",gVars.input_filename);
+ LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
+ }
+
+}
+
+void license()
+{
+ fprintf(stdout,"\n -- Released under the QPL LICENSE --\n \n Copyright (C) 2003 John Curry <john.curry@metre.net>\n \n No Warranty Expressed or Implied\n ");
+}
+
+void version()
+{
+ fprintf(stdout,"SA Network Connection Profiler v %s\n",VERSION);
+}
+
+void set_bpf_filter(char *argv)
+{
+ extern struct gvars gVars;
+ long len;
+
+ if(gVars.bpf_fname){ free(gVars.bpf_fname); }
+ gVars.bpf_fname=(char *) calloc(1,strlen(argv)+1);
+ strncpy(gVars.bpf_fname,argv,strlen(argv));
+ if(gVars.bfH){ gVars.bfH->destroy(); gVars.bfH=0; }
+ gVars.bfH = new fileHandle(gVars.bpf_fname);
+ gVars.bfH->setMode(READ_MODE);
+ gVars.bfH->seek(0,SEEK_END);
+ len=gVars.bfH->tell();
+ if(gVars.bpf_filter){ free(gVars.bpf_filter); }
+ if((gVars.bpf_filter = (char *) calloc(1,len+1))==NULL)
+ {
+#ifdef DEBUG
+ syslog(LOG_CRIT,"Out of memory - bpf filter too big?\n");
+ return;
+#endif
+ }
+ gVars.bfH->seek(0,0);
+ gVars.bfH->close();
+ gVars.bfH->setMode(READ_MODE);
+ if(gVars.bfH->read(gVars.bpf_filter,len)==-1)
+ {
+ switch (errno){
+ case EINTR:
+ syslog(LOG_ERR,"Error reading bpf filter: EINTR\n");
+ break;
+ case EAGAIN:
+ syslog(LOG_ERR,"Error reading bpf filter: EAGAIN\n");
+ break;
+ case EIO:
+ syslog(LOG_ERR,"Error reading bpf filter: EIO\n");
+ break;
+ case EISDIR:
+ syslog(LOG_ERR,"Error reading bpf filter: EISDIR\n");
+ break;
+ case EBADF:
+ syslog(LOG_ERR,"Error reading bpf filter: EBADF\n");
+ break;
+ case EINVAL:
+ syslog(LOG_ERR,"Error reading bpf filter: EINVAL\n");
+ break;
+ case EFAULT:
+ syslog(LOG_ERR,"Error reading bpf filter: EFAULT\n");
+ break;
+ }
+ }
+ if(gVars.bpf_filter[len-1]=='\n')
+ gVars.bpf_filter[len-1]=0;
+ /* We'll get rid of bpF here - close_files()
+ * is not a good place for this right now
+ * cause it gets called by reload_config()
+ * and that may be confusing, until we can apply
+ * new bpf filters -after- start-up
+ */
+ if(gVars.bfH){
+ gVars.bfH->destroy(); gVars.bfH=NULL;
+ }
+
+}
diff -ruN sancp-1.6.1-stable.vanilla/docs/README sancp-1.6.1-stable/docs/README
--- sancp-1.6.1-stable.vanilla/docs/README 2007-07-06 03:33:14.000000000 +0200
+++ sancp-1.6.1-stable/docs/README 2007-07-24 13:44:01.000000000 +0200
@@ -277,6 +277,10 @@
strip-80211 { disable|enable }
node <number>
debug_pcap_raw { disable|enable }
+ prelude_impact_severity [string]
+ prelude_impact_completion [string]
+ prelude_impact_type [string]
+ prelude_confidence_rating [string]
known_port syntax:
-----------------------:
@@ -310,6 +314,9 @@
b) tagging options
i.e. status=16 rid=1112 node=2
+ c) prelude options
+ i.e. severity=severe, completion=succeeded, type=other, confidence=high
+
[<ether protocol>[-<end_range>] [<src_ip{/<CIDR>|<dotted>}>] [<dst_ip{/<CIDR>|<dotted>}>] [{tcp|udp|icmp|<proto number>[-<end_range>] }]
[<src_port>{-[<end_port_range>]}] [<dst_port>{-[<end_port_range>]}]
{ ignore | stats [{log|pass}] | realtime [{log|pass}] |
diff -ruN sancp-1.6.1-stable.vanilla/gvars.h sancp-1.6.1-stable/gvars.h
--- sancp-1.6.1-stable.vanilla/gvars.h 2007-07-05 18:12:20.000000000 +0200
+++ sancp-1.6.1-stable/gvars.h 2007-07-24 13:44:01.000000000 +0200
@@ -17,7 +17,8 @@
/* Make certain all id's are represented in the same order (as strings) in fmtnames[] */
/* 'null' is a place holder - in the list for field 0 */
-enum id {null,sancp_id,start_time_gmt,start_time_local,stop_time_gmt,stop_time_local,erased_time_gmt,erased_time_local,eth_proto_hex,eth_proto,ip_proto,src_ip_decimal,src_ip_dotted,src_port,dst_ip_decimal,dst_ip_dotted,dst_port,duration,timeout,src_pkts,dst_pkts,src_bytes,dst_bytes,sflags_hex,sflags,sflags_1,sflags_2,sflags_U,sflags_A,sflags_P,sflags_R,sflags_S,sflags_F,dflags_hex,dflags,dflags_1,dflags_2,dflags_U,dflags_A,dflags_P,dflags_R,dflags_S,dflags_F,cflags_hex,cflags,cflags_DA,cflags_SA,cflags_DR,cflags_SR,cflags_DF,cflags_SF,ip_len_s,ip_ttl_s,ip_df_s,tcp_wss_s,tcp_mss_s,tcp_wscale_s,tcp_sack_ok_s,tcp_nop_s,ip_len_d,ip_ttl_d,ip_df_d,tcp_wss_d,tcp_mss_d,tcp_wscale_d,tcp_sack_ok_d,tcp_nop_d,total_bytes,collect,collected,climit,tcplag,pcap,realtime,stats,reversed,hash,rid,rgid,node,zone,status,retro,src_mac,dst_mac };
+enum id
+{null,sancp_id,start_time_gmt,start_time_local,stop_time_gmt,stop_time_local,erased_time_gmt,erased_time_local,eth_proto_hex,eth_proto,ip_proto,src_ip_decimal,src_ip_dotted,src_port,dst_ip_decimal,dst_ip_dotted,dst_port,duration,timeout,src_pkts,dst_pkts,src_bytes,dst_bytes,sflags_hex,sflags,sflags_1,sflags_2,sflags_U,sflags_A,sflags_P,sflags_R,sflags_S,sflags_F,dflags_hex,dflags,dflags_1,dflags_2,dflags_U,dflags_A,dflags_P,dflags_R,dflags_S,dflags_F,cflags_hex,cflags,cflags_DA,cflags_SA,cflags_DR,cflags_SR,cflags_DF,cflags_SF,ip_len_s,ip_ttl_s,ip_df_s,tcp_wss_s,tcp_mss_s,tcp_wscale_s,tcp_sack_ok_s,tcp_nop_s,ip_len_d,ip_ttl_d,ip_df_d,tcp_wss_d,tcp_mss_d,tcp_wscale_d,tcp_sack_ok_d,tcp_nop_d,total_bytes,collect,collected,climit,tcplag,pcap,realtime,stats,reversed,hash,rid,rgid,node,zone,status,retro,src_mac,dst_mac,prelude_impact_sevirty,prelude_impact_completion,prelude_impact_type,prelude_confidence_rating,prelude_profile };
struct cnx_queue {
struct cnx *head;
@@ -102,5 +103,10 @@
int stdout_fmt_len;
pcap_t *ph; // pcap handle
struct pcap_pkthdr *g_pkthdr;//
+ char *prelude_impact_severity;
+ char *prelude_impact_completion;
+ char *prelude_impact_type;
+ char *prelude_confidence_rating;
+ char *prelude_profile;
};
diff -ruN sancp-1.6.1-stable.vanilla/sancp.cc sancp-1.6.1-stable/sancp.cc
--- sancp-1.6.1-stable.vanilla/sancp.cc 2007-07-05 18:12:20.000000000 +0200
+++ sancp-1.6.1-stable/sancp.cc 2007-07-24 13:44:01.000000000 +0200
@@ -48,7 +48,40 @@
//char dfltfmt[]= { sancp_id,start_time_gmt,src_mac,dst_mac,eth_proto,src_ip_dotted,dst_ip_dotted,ip_proto,src_port,dst_port };
char dfltfmt_human_readable[]= { sancp_id,start_time_gmt,stop_time_gmt,erased_time_gmt,eth_proto,ip_proto,src_ip_dotted,src_port,dst_ip_dotted,dst_port,duration,timeout,src_pkts,dst_pkts,src_bytes,dst_bytes,sflags_hex,dflags_hex,cflags_hex,ip_len_s,ip_ttl_s,ip_df_s,tcp_wss_s,tcp_mss_s,tcp_wscale_s,tcp_sack_ok_s,tcp_nop_s,ip_len_d,ip_ttl_d,ip_df_d,tcp_wss_d,tcp_mss_d,tcp_wscale_d,tcp_sack_ok_d,tcp_nop_d,total_bytes,collect,collected,climit,tcplag,pcap,realtime,stats,reversed,hash,rid,rgid,node,zone,status,retro,src_mac,dst_mac };
+prelude_client_t *client;
+static idmef_analyzer_t *idmef_analyzer;
+int sancp_alert_init(prelude_client_t *client)
+{
+ int ret;
+ prelude_string_t *string;
+
+ idmef_analyzer = prelude_client_get_analyzer(client);
+ if ( ! idmef_analyzer )
+ return -1;
+
+ ret = idmef_analyzer_new_model(idmef_analyzer, &string);
+ if ( ret < 0 )
+ return -1;
+ prelude_string_set_constant(string, PRELUDE_ANALYZER_MODEL);
+
+ ret = idmef_analyzer_new_class(idmef_analyzer, &string);
+ if ( ret < 0 )
+ return -1;
+ prelude_string_set_constant(string, PRELUDE_ANALYZER_CLASS);
+
+ ret = idmef_analyzer_new_manufacturer(idmef_analyzer, &string);
+ if ( ret < 0 )
+ return -1;
+ prelude_string_set_constant(string, PRELUDE_ANALYZER_MANUFACTURER);
+
+ ret = idmef_analyzer_new_version(idmef_analyzer, &string);
+ if ( ret < 0 )
+ return -1;
+ prelude_string_set_constant(string, VERSION);
+
+ return 0;
+}
/*************
* Main *
*************/
@@ -56,6 +89,7 @@
int main(int argc, char *argv[]) {
extern struct gvars gVars;
int cKey;
+ int ret;
pid_t pid=0;
/*
@@ -102,6 +136,14 @@
gVars.stdout_delimiter=DEFAULT_DELIMITER;
gVars.stdout_eor=DEFAULT_EOR;
+ gVars.prelude_impact_severity=PRELUDE_IMPACT_SEVERITY;
+ gVars.prelude_impact_completion=PRELUDE_IMPACT_COMPLETION;
+ gVars.prelude_impact_type=PRELUDE_IMPACT_TYPE;
+ gVars.prelude_confidence_rating=PRELUDE_CONFIDENCE_RATING;
+ gVars.prelude_profile=PRELUDE_PROFILE;
+
+
+
for(cKey=0; cKey<HASH_KEYS; cKey++)
{
gVars.cnx_head[cKey]=NULL;
@@ -116,6 +158,8 @@
parse_args(argc, argv);
+
+
if(gVars.human_readable){
if(gVars.realtime_fmt_len!=sizeof(dfltfmt_human_readable)){
free(gVars.realtime_fmt);
@@ -143,7 +187,15 @@
setsid();
}
+ prelude_log_set_flags((prelude_log_flags_t)PRELUDE_LOG_FLAGS_SYSLOG);
}
+
+ /* Initialize prelude */
+ ret = prelude_init(&argc, argv);
+ if (ret < 0) {
+ prelude_perror(ret, "unable to initialize the prelude library");
+ exit_all(0);
+ }
/* Retrieve the last cnxid from cache file if we haven't already in parse_args() */
if(!gVars.cnx_id)
@@ -197,6 +249,29 @@
build_config(1);
+ /* Create prelude sensor */
+
+ ret = prelude_client_new(&client, gVars.prelude_profile);
+ if ( ! client ) {
+ prelude_perror(ret, "Unable to create a prelude client object");
+ exit_all(0);
+ }
+
+ /* Start prelude sensor */
+ sancp_alert_init(client);
+ ret = prelude_client_start(client);
+ if ( ret < 0 ) {
+ prelude_perror(ret, "Unable to start prelude client");
+ exit_all(0);
+ }
+
+ ret = prelude_client_set_flags(client, (prelude_client_flags_t)
+ (PRELUDE_CLIENT_FLAGS_ASYNC_SEND|PRELUDE_CLIENT_FLAGS_ASYNC_TIMER));
+ if ( ret < 0 ) {
+ fprintf(stderr, "Unable to set asynchronous send and timer.\n");
+ exit_all(0);
+ }
+
/* Open files for output */
/* Be r3al l33t h3r3 */
diff -ruN sancp-1.6.1-stable.vanilla/sancp.h sancp-1.6.1-stable/sancp.h
--- sancp-1.6.1-stable.vanilla/sancp.h 2007-07-06 06:18:04.000000000 +0200
+++ sancp-1.6.1-stable/sancp.h 2007-07-24 13:44:01.000000000 +0200
@@ -47,6 +47,10 @@
#include "gvars.h"
#endif
+#include <libprelude/prelude.h>
+#include <libprelude/prelude-log.h>
+#include <netdb.h>
+
#define NCP_H
#define Y 'Y'
#define N 'N'
@@ -79,6 +83,7 @@
struct vars *next;
};
+extern prelude_client_t *client;
int main(int argc, char *argv[]);
struct cnx *process(struct cnx*, int len, u_char * pkt);
char * createPcapFileName();
@@ -185,6 +190,15 @@
#define OMODE_RULE 5
#define OMODE_UNIQ 6
+#define PRELUDE_IMPACT_SEVERITY "medium"
+#define PRELUDE_IMPACT_COMPLETION "succeeded"
+#define PRELUDE_IMPACT_TYPE "other"
+#define PRELUDE_CONFIDENCE_RATING "high"
+#define PRELUDE_ANALYZER_MODEL "Sancp"
+#define PRELUDE_ANALYZER_CLASS "NIDS"
+#define PRELUDE_ANALYZER_MANUFACTURER "http://www.metre.net/sancp.html"
+#define PRELUDE_PROFILE "sancp"
+
// Need to distinguish between classes of variables
#define VCLASS_0 1 // eth_proto class vars
#define VCLASS_1 2 // ip_addr class vars
@@ -276,6 +290,10 @@
u_int16_t rgid;
u_int16_t node;
u_int16_t zone;
+ char *prelude_impact_severity;
+ char *prelude_impact_completion;
+ char *prelude_impact_type;
+ char *prelude_confidence_rating;
CBuffer *CBufferPtr;
struct acl *next;
};
@@ -314,6 +332,10 @@
u_int16_t rgid;
u_int16_t node;
u_int16_t zone;
+ char *prelude_impact_severity;
+ char *prelude_impact_completion;
+ char *prelude_impact_type;
+ char *prelude_confidence_rating;
CBuffer *CBufferPtr;
struct os_info os_info;
struct os_info os_info2;
diff -ruN sancp-1.6.1-stable.vanilla/sancp.h~ sancp-1.6.1-stable/sancp.h~
--- sancp-1.6.1-stable.vanilla/sancp.h~ 1970-01-01 01:00:00.000000000 +0100
+++ sancp-1.6.1-stable/sancp.h~ 2007-07-06 06:18:04.000000000 +0200
@@ -0,0 +1,327 @@
+/**************************************************************************
+ **SA Network Connection Profiler [sancp] - A TCP/IP statistical/collection tool
+ * ************************************************************************
+ * * Copyright (C) 2003 John Curry <john.curry@metre.net>
+ * *
+ * * This program is distributed under the terms of version 1.0 of the
+ * * Q Public License. See LICENSE.QPL for further details.
+ * *
+ * * This program is distributed in the hope that it will be useful,
+ * * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * *
+ * ***********************************************************************/
+
+#define SANCP_H
+
+
+//#define DEBUG 1
+
+#include <signal.h> // set_signals(), SIGHUP, signal, SIGUSR1, SIGUSR2, SIGTERM, SIGINT, SIGKILL, SIGQUIT
+#include <arpa/inet.h> // inet_aton(), inet_ntoa()
+#include <errno.h> // errno, EINTR, EAGAIN, EIO, EISDIR, EBADF, EINVAL, EFAULT
+#include <syslog.h> // LOG_ERR, LOG_CONS, LOG_INFO, LOG_CRIT
+ // LOG_LOCAL1, LOG_LOCAL2, LOG_LOCAL3, LOG_LOCAL4, LOG_LOCAL5, LOG_LOCAL6, LOG_LOCAL7
+
+#include <ctype.h>
+#include <time.h>
+//#include <net/ethernet.h>
+
+//#include <stdio.h>
+//#include <unistd.h>
+//#include <sys/socket.h>
+
+// Required for BSD
+#include <netinet/in.h>
+
+//#include <net/if.h>
+//#include <fcntl.h>
+//#include <stdlib.h>
+//#include <sys/ioctl.h>
+//#include <time.h>
+//#include <sys/time.h>
+//#include <ctype.h>
+//#include <string.h>
+
+#ifndef GVARS_H
+#include "gvars.h"
+#endif
+
+#define NCP_H
+#define Y 'Y'
+#define N 'N'
+#define MIN_WAIT_TIME 4 // We will wait at least this many seconds before expiring a closed connection
+
+// Include our own version of ether_addr since linux/solaris
+// differ from bsd systems on definition of struct ether_addr
+
+#define ETHER_ADDR_LEN 6 /* length of an Ethernet address */
+
+struct myether_addr {
+ u_char octet[ETHER_ADDR_LEN];
+};
+
+/*
+ * Structure of a 10Mb/s Ethernet header.
+ */
+struct ether_header { // we pulled this from net/ethernet.h
+ u_char ether_dhost[ETHER_ADDR_LEN];
+ u_char ether_shost[ETHER_ADDR_LEN];
+ u_short ether_type;
+};
+
+
+
+struct vars {
+ char *key;
+ char *value;
+ int vclass; // variable class
+ struct vars *next;
+};
+
+int main(int argc, char *argv[]);
+struct cnx *process(struct cnx*, int len, u_char * pkt);
+char * createPcapFileName();
+char * createFileName(const char* filename);
+char * createFileName(const char* filename, bool);
+char * createPcapFileName(const struct acl* tacl);
+char * createPcapFileName(const struct cnx* tcnx);
+extern "C" pcap_t * open_pcap_live(char *,char *);
+extern "C" pcap_t * open_pcap_file(char *,char *);
+extern "C" void close_pcap_file(pcap_t *);
+extern "C" void start_pcap_loop(pcap_t *);
+extern "C" void print_linktype(pcap_t *);
+void erase_idle(int a);
+void reopen_files(int a);
+void expire_connections();
+struct cnx *update_state_node(struct cnx *);
+void build_config(int a);
+void parse_args(int arg, char* argv[]);
+void parse_format(const char *,const char *);
+void print_acl(int a);
+void print_stats(int a);
+void print_output_schema(outputFileHandle *fH, char *fmtcols, int fmtlen);
+void write_schema(char *name, char *fmt, int fmtlen);
+void print_schemas();
+int fgetcline(char **buf, int size, FILE *fp);
+int promisc_mode(char *, int);
+void close_files(int a);
+void open_files();
+void reload_config(int a);
+void record_all(int a);
+void free_all(int a);
+void exit_all(int a);
+void manage_cid(int a);
+
+void record(struct cnx *, outputFileHandle *fH);
+void set_signals();
+void decode(struct cnx*, int len, const u_char * pkt);
+void decode_pcap(struct cnx*,struct pcap_pkthdr * pkthdr, u_char * pkt);
+int CheckPort(u_int8_t proto,u_int16_t port);
+void SChangeUserGroup();
+void apply_rule(struct cnx*);
+void parse_var(char *,char *);
+void parse_known_ports(char *, struct vars*, char *);
+void parse_connection_rule(char *, struct vars*, char *);
+void open_pcap_output();
+
+/* Hash Table Protos */
+#define DEFAULT_FLUSH_INTERVAL 1800
+#define DEFAULT_EXPIRE_INTERVAL 10
+#define VERSION "1.6.1-stable"
+#define NAME "sancp"
+#define LOG_DIR "./" /* default relative to current working directory */
+#define CONFIG_DIR "/etc/sancp/"
+#define CONFIG_FILE "sancp.conf"
+#define PCAP_RAW_FNAME "debug_pcap_raw"
+#define PCAP_FNAME "pcap"
+#define STATS_FNAME "stats"
+#define REALTIME_FNAME "realtime"
+#define true 1
+#define false 0
+#define PROMISC 1
+#define MAX_VAR 256
+#define MAXFLDS 85 // define number of elements in fmtnames[]
+#define MAXFLDSIZE 19 // define largest element in fmtnames[MAXFLDS][MAXFLDLEN]
+#define MAXENTRYLEN 256
+#define DELIMITER '|'
+#define READ_TIMEOUT 500
+#define ETHPROTO_IP 0x0008
+// network order bytes 0x0806
+#define ETHPROTO_ARP 0x0608
+// network order bytes 0x8035
+#define ETHPROTO_RARP 0x3580
+// network order bytes 0x8100
+#define ETHPROTO_8021Q 0x0081
+#define DEFAULT_DEVICE "any"
+#define DEFAULT_NODE 0
+#define DEFAULT_LIMIT 0
+#define DEFAULT_RID 0
+#define DEFAULT_RGID 0
+#define DEFAULT_ZONE 0
+//#define TCP_TIMEOUT 120
+//#define UDP_TIMEOUT 300
+//#define ICMP_TIMEOUT 120
+#define DEFAULT_TIMEOUT 300
+#define DEFAULT_STATUS 0
+#define DEFAULT_LAG 0
+#define DEFAULT_DELIMITER '|'
+#define DEFAULT_EOR '\n'
+#define MAX_PORTS 65536
+#define FROM_INITIATOR 0
+#define FROM_TARGET 1
+#define ACTION_PASS 0
+#define ACTION_LOG 1
+#define ACTION_DEFAULT 2
+#define CMODE_NONE 0
+#define CMODE_BOTH 1
+#define CMODE_SRC 2
+#define CMODE_DST 3
+#define OMODE_PASS 0
+#define OMODE_LOG 1
+#define OMODE_DEFAULT 2
+#define OMODE_FILENAME 3
+#define OMODE_TSFILENAME 4
+#define OMODE_RULE 5
+#define OMODE_UNIQ 6
+
+// Need to distinguish between classes of variables
+#define VCLASS_0 1 // eth_proto class vars
+#define VCLASS_1 2 // ip_addr class vars
+#define VCLASS_2 3 // ip_proto class vars
+#define VCLASS_3 4 // port class vars
+#define VCLASS_4 5 // rid class vars
+#define VCLASS_5 6 // rgid class vars
+#define VCLASS_6 7 // zone class vars
+#define VCLASS_7 8 // node class vars
+#define VCLASS_8 9 // status class vars
+
+#define DISABLED 0
+#define ENABLED 1
+#define CNX_REVERSED 1
+#define CNX_BOTH_PORTS_KNOWN 2
+#define CNX_BOTH_PORTS_UNKNOWN 3
+#define CNX_REREVERSED 4
+#define MAX_PACK_LEN 20000 /* Sufficient for ethernet packets. */
+#define ETHER_SIZE 14
+#ifdef EXPERIMENTAL_TCPOPTIONS
+#define TCPOPT_EOL 0
+#define TCPOPT_NOP 1
+#define TCPOPT_MAXSEG 2
+#define TCPOPT_SACKOK 4 /* Experimental */
+#define TCPOPT_WSCALE 3
+#define TCPOPTIONS_MAX 8 /* Maximum number of tcpoptions to parse */
+#endif
+
+
+#define R_FIN 0x01
+#define R_SYN 0x02
+#define R_RST 0x04
+#define R_PSH 0x08
+#define R_ACK 0x10
+#define R_URG 0x20
+#define R_RES2 0x40
+#define R_RES1 0x80
+#define max(i,j) (((i)>(j)) ? (i) : (j))
+#define SIZE_OF_CLASS_C 11
+
+struct t_ports {
+ u_int16_t l_port;
+ u_int16_t h_port;
+ struct t_ports *next;
+};
+
+
+struct os_info {
+ u_int8_t ttl;
+ u_int16_t len;
+ u_int16_t wss;
+#ifdef EXPERIMENTAL_TCPOPTIONS
+ u_int8_t df:1, nop:1, sack_ok:1;
+ u_int16_t mss;
+ short wscale;
+#else
+ u_int8_t df:1;
+#endif
+
+};
+
+
+struct acl {
+ struct ether_header eth_hdr;
+ u_int16_t h_proto_h;
+ u_int16_t h_proto_l;
+ u_int32_t s_ip;
+ u_int32_t s_mask;
+ u_int16_t s_port_l;
+ u_int16_t s_port_h;
+ u_int32_t d_ip;
+ u_int32_t d_mask;
+ u_int16_t d_port_l;
+ u_int16_t d_port_h;
+ u_int8_t proto_l;
+ u_int8_t proto_h;
+ u_int32_t offset;
+ u_int32_t mask;
+ u_int32_t value;
+ pcapFileHandle * fH;
+ u_int8_t stats:1, realtime:1, pcap:1, retro:1, smode:2, rmode:2;
+ u_int8_t cmode:2, pmode:4;
+ u_int16_t tcplag;
+ u_int16_t timeout;
+ u_int64_t limit;
+ u_int16_t status;
+ u_int32_t ctr;
+ u_int32_t rid;
+ u_int16_t rgid;
+ u_int16_t node;
+ u_int16_t zone;
+ CBuffer *CBufferPtr;
+ struct acl *next;
+};
+
+void retroactive(struct acl*);
+
+struct cnx {
+ struct ether_header eth_hdr;
+ u_int16_t h_proto;
+ u_int8_t proto;
+ u_int32_t s_ip;
+ u_int32_t d_ip;
+ u_int16_t s_port;
+ u_int16_t d_port;
+ u_int64_t s_total_pkts;
+ u_int64_t s_total_bytes;
+ u_int64_t d_total_pkts;
+ u_int64_t d_total_bytes;
+ u_int64_t total_bytes;
+ time_t start_time;
+ time_t last_pkt;
+ u_int8_t free:1,direction:1;
+ pcapFileHandle *fH;
+ u_int8_t cmode:4, pcap:1, realtime:1, stats:1, retro:1;
+ u_int8_t tcpFlags[2];
+ u_int8_t tcpCFlags;
+ u_int8_t reversed;
+ u_int16_t tcplag;
+ u_int64_t limit;
+ u_int16_t status;
+ u_int64_t collected;
+ u_int64_t cid;
+ u_int16_t timeout;
+ u_int16_t hash;
+ u_int32_t rid;
+ u_int16_t rgid;
+ u_int16_t node;
+ u_int16_t zone;
+ CBuffer *CBufferPtr;
+ struct os_info os_info;
+ struct os_info os_info2;
+ struct cnx *next;
+ struct cnx *prev;
+};
+
+
+void usage();
+void outputfields();
+void rule_syntax();
diff -ruN sancp-1.6.1-stable.vanilla/statefull_logging.cc sancp-1.6.1-stable/statefull_logging.cc
--- sancp-1.6.1-stable.vanilla/statefull_logging.cc 2007-07-05 18:12:20.000000000 +0200
+++ sancp-1.6.1-stable/statefull_logging.cc 2007-07-24 13:44:01.000000000 +0200
@@ -183,6 +183,208 @@
snprintf(buf,len,"%s",currenttime);
}
+static int add_idmef_object(idmef_message_t *message, const char *object, const char *value)
+{
+ int ret;
+ idmef_value_t *val;
+ idmef_path_t *path;
+
+ ret = idmef_path_new(&path, object);
+ if ( ret < 0 )
+ return -1;
+
+ ret = idmef_value_new_from_path(&val, path, value);
+ if ( ret < 0 ) {
+ idmef_path_destroy(path);
+ return -1;
+ }
+
+ ret = idmef_path_set(path, message, val);
+
+ idmef_value_destroy(val);
+ idmef_path_destroy(path);
+
+ return ret;
+}
+
+#define IDMEF(x) { \
+ int ret = (x); \
+ if (ret < 0) { idmef_message_destroy(idmef); printf("error\n"); return; } \
+ }
+
+void record_prelude(struct cnx *cn) {
+ char LOG[MAXENTRYLEN];
+
+ idmef_message_t *idmef;
+ idmef_alert_t *alert;
+ idmef_time_t *time;
+
+ struct servent *sourceservent;
+ struct protoent *protoent;
+
+ IDMEF(idmef_message_new(&idmef));
+ IDMEF(idmef_message_new_alert(idmef, &alert));
+
+ /* alert.detecttime */
+ if (cn->start_time) {
+ IDMEF(idmef_time_new_from_time(&time, &cn->start_time));
+ } else {
+ /* using the curen time */
+ IDMEF(idmef_time_new_from_gettimeofday(&time));
+ }
+ idmef_alert_set_detect_time(alert, time);
+
+ /* alert.createtime */
+ time = NULL;
+ IDMEF(idmef_time_new_from_gettimeofday(&time));
+ idmef_alert_set_create_time(alert, time);
+
+ /* alert.analyzer */
+ idmef_alert_set_analyzer(alert,idmef_analyzer_ref(prelude_client_get_analyzer(client)),0);
+
+ /* alert.classification.text */
+ add_idmef_object(idmef, "alert.classification.text",
+ "Unauthorized network connectivity");
+
+ /* alert.messageid */
+ snprintf(LOG,MAXENTRYLEN,"%lld",cn->cid);
+ add_idmef_object(idmef, "alert.messageid", LOG);
+
+ /* alert.impact.severity */
+ add_idmef_object(idmef, "alert.assessment.impact.severity",
+ cn->prelude_impact_severity);
+
+ /* alert.impact.completion */
+ add_idmef_object(idmef, "alert.assessment.impact.completion",
+ cn->prelude_impact_completion);
+
+ /* alert.impact.type */
+ add_idmef_object(idmef, "alert.assessment.impact.type",
+ cn->prelude_impact_type);
+
+ /* alert.confidence.rating */
+ add_idmef_object(idmef, "alert.assessment.confidence.rating",
+ cn->prelude_confidence_rating);
+
+ /* alert.additionaldata(0) */
+ add_idmef_object(idmef, "alert.additionaldata(0).type", "integer");
+ add_idmef_object(idmef, "alert.additionaldata(0).meaning", "status");
+ snprintf(LOG,MAXENTRYLEN,"%u",cn->status);
+ add_idmef_object(idmef, "alert.additionaldata(0).integer", LOG);
+
+ /* alert.additionaldata(1) */
+ add_idmef_object(idmef, "alert.additionaldata(1).type", "integer");
+ add_idmef_object(idmef, "alert.additionaldata(1).meaning", "Network node");
+ snprintf(LOG,MAXENTRYLEN,"%u",cn->node);
+ add_idmef_object(idmef, "alert.additionaldata(1).integer", LOG);
+
+ /* IP versios */
+ if (cn->h_proto == 8) {
+ add_idmef_object(idmef, "alert.source(0).service.ip_version", "4");
+ add_idmef_object(idmef, "alert.target(0).service.ip_version", "4");
+ } else {
+ /* bail out */
+ idmef_message_destroy(idmef);
+ return;
+ }
+
+ /* alert.source(0).node.address(0) (ip address) */
+ if(cn->reversed==CNX_REVERSED){
+ snprintf_inaddr_toa(LOG,MAXENTRYLEN,(struct in_addr*) &cn->d_ip,'\0');
+ }else{
+ snprintf_inaddr_toa(LOG,MAXENTRYLEN,(struct in_addr*) &cn->s_ip,'\0');
+ }
+ add_idmef_object(idmef, "alert.source(0).node.address(0).category",
+ "ipv4-addr");
+ add_idmef_object(idmef, "alert.source(0).node.address(0).address", LOG);
+
+ /* alert.source(0).node.address(1) (mac address) */
+ add_idmef_object(idmef, "alert.source(0).node.address(1).category", "mac");
+ {
+ struct myether_addr *es=(struct myether_addr *)&cn->eth_hdr.ether_shost;
+ snprintf(LOG,MAXENTRYLEN,"%0x:%0x:%0x:%0x:%0x:%0x",es->octet[0],es->octet[1],es->octet[2],es->octet[3],es->octet[4],es->octet[5]);
+ }
+ add_idmef_object(idmef, "alert.source(0).node.address(1).address", LOG);
+
+ protoent = getprotobynumber(cn->proto);
+
+ /* alert.source(0).iana_protocol_number */
+ snprintf(LOG,MAXENTRYLEN,"%u",(cn->proto));
+ add_idmef_object(idmef, "alert.source(0).service.iana_protocol_number", LOG);
+
+ /* alert.target(0).iana_protocol_number */
+ add_idmef_object(idmef, "alert.target(0).service.iana_protocol_number", LOG);
+
+
+ if (protoent) {
+ /* alert.source(0).iana_protocol_name */
+ add_idmef_object(idmef, "alert.source(0).service.iana_protocol_name",
+ protoent->p_name);
+
+ /* alert.target(0).iana_protocol_name */
+ add_idmef_object(idmef, "alert.target(0).service.iana_protocol_name",
+ protoent->p_name);
+
+ /* alert.source(0).service */
+ setservent(1);
+ if(cn->reversed==CNX_REVERSED){
+ snprintf(LOG,MAXENTRYLEN,"%u",ntohs(cn->d_port));
+ sourceservent = getservbyport(ntohs(cn->d_port), protoent->p_name);
+ }else{
+ snprintf(LOG,MAXENTRYLEN,"%u",ntohs(cn->s_port));
+ sourceservent = getservbyport(ntohs(cn->s_port), protoent->p_name);
+ }
+
+ if (sourceservent && sourceservent->s_name)
+ add_idmef_object(idmef, "alert.source(0).service.name",
+ sourceservent->s_name );
+ add_idmef_object(idmef, "alert.source(0).service.port",
+ LOG);
+ add_idmef_object(idmef, "alert.source(0).service.protocol",
+ protoent->p_name);
+
+ /* alert.target(0).service */
+ if(cn->reversed==CNX_REVERSED){
+ snprintf(LOG,MAXENTRYLEN,"%u",ntohs(cn->s_port));
+ sourceservent = getservbyport(ntohs(cn->s_port), protoent->p_name);
+ }else{
+ snprintf(LOG,MAXENTRYLEN,"%u",ntohs(cn->d_port));
+ sourceservent = getservbyport(ntohs(cn->d_port), protoent->p_name);
+ }
+
+ if (sourceservent && sourceservent->s_name)
+ add_idmef_object(idmef, "alert.target(0).service.name",
+ sourceservent->s_name );
+ add_idmef_object(idmef, "alert.target(0).service.port",
+ LOG);
+ add_idmef_object(idmef, "alert.target(0).service.protocol",
+ protoent->p_name);
+ }
+/*
+*/
+
+ /* alert.target(0).node.address(0) (ip address) */
+ if(cn->reversed==CNX_REVERSED){
+ snprintf_inaddr_toa(LOG,MAXENTRYLEN,(struct in_addr*) &cn->s_ip,'\0');
+ }else{
+ snprintf_inaddr_toa(LOG,MAXENTRYLEN,(struct in_addr*) &cn->d_ip,'\0');
+ }
+ add_idmef_object(idmef, "alert.target(0).node.address(0).category",
+ "ipv4-addr");
+ add_idmef_object(idmef, "alert.target(0).node.address(0).address", LOG);
+
+ /* alert.target(0).node_address(1) (mac address) */
+ add_idmef_object(idmef, "alert.target(0).node.address(1).category", "mac");
+ {
+ struct myether_addr *es=(struct myether_addr *)&cn->eth_hdr.ether_dhost;
+ snprintf(LOG,MAXENTRYLEN,"%0x:%0x:%0x:%0x:%0x:%0x",es->octet[0],es->octet[1],es->octet[2],es->octet[3],es->octet[4],es->octet[5]);
+ }
+ add_idmef_object(idmef, "alert.target(0).node.address(1).address", LOG);
+
+ prelude_client_send_idmef(client, idmef);
+ idmef_message_destroy(idmef);
+}
+
void record(struct cnx *cn, outputFileHandle *fH)
{
@@ -199,8 +401,15 @@
char eor=fH->getEor();
+ /* do we want prelude alert generation for this record? */
+
bzero(LOG,MAXENTRYLEN);
+ if (fH == gVars.sfH) {
+ record_prelude(cn);
+ }
+
+
/*
* Structure of a 48-bit Ethernet address.