1 #ifndef SANCP_H
2 #include "sancp.h"
3 #endif
4 //#define DEBUG
5 /**************************************************************************
6  **SA Network Connection Profiler [sancp] - A TCP/IP statistical/collection tool
7  * ************************************************************************
8  * * Copyright (C) 2003 John Curry <john.curry@metre.net>
9  * *
10  * * This program is distributed under the terms of version 1.0 of the
11  * * Q Public License.  See LICENSE.QPL for further details.
12  * *
13  * * This program is distributed in the hope that it will be useful,
14  * * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  * *
17  * ***********************************************************************/
18 
19 void license();
20 void version();
21 struct acl *tacl_head=NULL, *tacl_tail=NULL;
22 struct t_ports *tports[MAX_IP_PROTO];
23 void set_bpf_filter( char *);
24 char * get_tok(char **rule, const char * accept);
25 void parse_default(char *rule, char *accept);
26 char * get_next_tok(char **rule, const char *delimiters);
27 char *rev_search_vars(char *key, struct vars *var_head, int );
28 
fgetcline(char ** buf,int size,FILE * fp)29 int fgetcline (char **buf, int size, FILE *fp){
30         int len;
31 	int c=0;
32         if( fp== NULL){
33 		syslog(LOG_ERR,"Invalid FILE handle\n");
34                 return -1;
35 	}
36         if(feof(fp)){
37 		syslog(LOG_ERR,"Early END OF FILE\n");
38                 return -1;
39 	}
40         if (*buf == NULL){
41                 if( size == 0)
42                         size=BUFSIZ;
43                 if((*buf = (char *)calloc(1,size)) == NULL){
44 			syslog(LOG_ERR,"Out of memory\n");
45                         return -1;
46 		}
47         }
48         len=0;
49 //  Get characters until EOF or ';'
50         while (((c = getc(fp)) != EOF) && c!='\n' && c!='\r'){
51 		if(c=='\\'){
52                       if((c = getc(fp))==EOF){
53 				break;
54 		      }
55 		      if(c=='\n'){
56 			 c=' ';
57 		      }else{
58 			ungetc(c,fp);
59 			c='\\';
60 		      }
61 		}
62                 if(c == '#'){
63                 // if comment mark, FF to end of line
64                         while( (c = getc(fp))!= EOF && c !='\n');
65 			//if(c=='\n'){ break;}
66                         //if(c==EOF){ break; }
67 			break;
68                 }
69                 if(len+1 >= size) {
70                         if(( *buf = (char *)realloc(*buf, size += BUFSIZ))==NULL){
71 			syslog(LOG_ERR,"Out of memory\n");
72                                 free(*buf);
73                                 return -1;
74                         }
75                 }
76 		if(c == ',' || c == '=' ) {
77 			c = ' ';
78 		}
79 		//
80 		// Make everything lower case for now
81 		//
82 		if(!(len==0 && (c==' ' || c=='\t')))
83                 	(*buf)[len++]=tolower(c);
84 
85                	if(c == '\t' || c == ' ' ){
86 			while( (c=fgetc(fp))!= EOF && c!='\n' && (c=='\t' || c==' '));
87 			//while( (c=fgetc(fp))!= EOF && c!='\n' && (c=='\t' || c==' ' || c==',' || c=='='));
88 			if(c=='\n'|| c==EOF){ break; }
89 			// Trunicate comments
90 			if(c=='#') (*buf)[len]='\0';
91 			ungetc(c,fp);
92 			// If we ran into a '#' sign, then just turn the last \t or space into a null.
93                	}
94         }
95         if (len == 0 && c == EOF){
96 		if(*buf!=NULL)
97                 	free(*buf);
98                 return -1;
99         }
100 	if(len>0 && ((*buf)[len-1]==' ' || (*buf)[len-1]=='\t')){
101 	       	(*buf)[len-1]='\0';
102 	        return len-1;
103 	}else{
104         	(*buf)[len++]='\0';
105 	        return len;
106 	}
107 }
108 
parse_args(int argc,char * argv[])109 void parse_args(int argc, char *argv[])
110 {
111 	extern struct gvars gVars;
112    	u_int64_t num;
113 	char *ftmp=0;
114 	//int ctr=0;
115 	for(int ctr=1; ctr < argc; ctr++)
116 	{
117 		if(strcmp(argv[ctr],"--schemas")==0)
118 		{
119 			// once we finished reading the config, we will print the schemas and exit
120 			gVars.print_schemas = 1;
121 		}else{
122                 if(strcmp(argv[ctr],"--shift")==0)
123 		                       {
124  			//  enable internal 2 byte shifting the packet read from file
125 		        //  'any' interface
126                         gVars.shift = 1;
127                 }else{
128 		if(strcmp(argv[ctr],"-K")==0 || strcmp(argv[ctr],"--console")==0)
129 		{
130 			// enable console mode - log realtimes to stdout
131 			gVars.console_mode = 1;
132 
133 		}else{
134 		if(strcmp(argv[ctr],"-D")==0 || strcmp(argv[ctr],"--daemon")==0)
135 		{
136 			// enable daemon mode
137 			gVars.daemon_mode = 1;
138 	                openlog(NAME,LOG_CONS,gVars.log_facility);
139 		}else{
140 		if(strcmp(argv[ctr],"-C")==0 || strcmp(argv[ctr],"--last_cnxid")==0)
141 		{
142 			// set last connection id to use - ~~~! Need to supply -d argument first !~~~
143 			if( ctr < argc-1 ){
144 				ctr++;
145 	                	ftmp=argv[ctr];
146 	                	num = (u_int64_t) strtoll(argv[ctr],&ftmp,0);
147 	                	if(argv[ctr]==ftmp)
148 	                	{
149         	                	syslog(LOG_ERR,"Format error, invalid last_cnxid: %s, using cnxid %llu\n",argv[ctr],(long long unsigned)gVars.cnx_id);
150 	                	}else
151 				manage_cid(0);
152 				if(gVars.cnx_id>num){
153         	                	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);
154 				}else{
155         	                	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);
156 					// Save the new cnx_id
157 					gVars.cnx_id=num;
158 					manage_cid(1);
159 				}
160 			}else{
161 				syslog(LOG_ERR,"No cnxid provided with -C/--last_cnxid  option\n");
162 				exit(0);
163 			}
164 		}else{
165 		if(strcmp(argv[ctr],"-i")==0)
166 		{
167 			// Set device name
168 			if( ctr < argc-1 ){
169 				if(gVars.default_device){ free(gVars.default_device); } ctr++;
170 				if( (gVars.default_device = (char *)calloc(strlen(argv[ctr])+ 1,1) ) ==NULL){
171 					syslog(LOG_ERR,"Unable to allocate memory for -i option\n");
172 					exit(0);
173 				}
174 				bcopy(argv[ctr],gVars.default_device,strlen(argv[ctr]));
175 				gVars.shift=0;	// disable shift (only needed for 'any' interface)
176 				if(strstr(gVars.default_device,DEFAULT_DEVICE))
177 					gVars.shift=1;
178 			}else{
179 				syslog(LOG_ERR,"No device name provided with -i option\n");
180 				exit(0);
181 			}
182 		}else{
183 		if(strcmp(argv[ctr],"-d")==0)
184 		{
185 			// Set log directory name
186 			if( ctr < argc-1 ){
187 				if(gVars.log_directory){ free(gVars.log_directory); } ctr++;
188 				if( (gVars.log_directory = (char *)calloc(strlen(argv[ctr])+ 2,1) ) ==NULL){
189 					syslog(LOG_ERR,"Unable to allocate memory for -d option\n");
190 					exit(0);
191 				}
192 				bcopy(argv[ctr],gVars.log_directory,strlen(argv[ctr]));
193 				// We allocated an extra space for this...
194 				*(gVars.log_directory+strlen(argv[ctr]))='/';
195 			}else{
196 				syslog(LOG_ERR,"No directory provided with -d option\n");
197 				exit(0);
198 			}
199 		}else{
200 		if(strcmp(argv[ctr],"-r")==0)
201 		{
202 			// Set pcap input file name
203 			if( ctr < argc-1 ){
204 				if(gVars.input_filename){ free(gVars.input_filename); } ctr++;
205 				if( (gVars.input_filename = (char *)calloc(strlen(argv[ctr])+1,1) ) ==NULL){
206 					syslog(LOG_ERR,"Unable to allocate memory for -r option\n");
207 					exit(0);
208 				}
209 				bcopy(argv[ctr],gVars.input_filename,strlen(argv[ctr]));
210 				gVars.shift=0;	// disable shift (only needed for 'any' interface)
211 			}else{
212 				syslog(LOG_ERR,"No pcap filename provided with -r option\n");
213 				exit(0);
214 			}
215 		}else{
216 		if(strcmp(argv[ctr],"-c")==0)
217 		{
218 			// Set configuration directory name
219 			if( ctr < argc-1 ){
220 				if(gVars.config_file){ free(gVars.config_file); } ctr++;
221 				if( (gVars.config_file = (char *)calloc(strlen(argv[ctr])+1,1) ) ==NULL){
222 					syslog(LOG_ERR,"Unable to allocate memory for -c option\n");
223 					exit(0);
224 				}
225 				bcopy(argv[ctr],gVars.config_file,strlen(argv[ctr]));
226 			}else{
227 				syslog(LOG_ERR,"No configuration filename provided with -c option\n");
228 				exit(0);
229 			}
230 		}else{
231 		if(strcmp(argv[ctr],"--log-facility")==0)
232 		{
233 			// Set log facility
234 		    if( ctr < argc-1 ){
235 			ctr++;
236 			if(strcmp(argv[ctr],"LOCAL1")==0)
237 				gVars.log_facility = LOG_LOCAL1;
238 			if(strcmp(argv[ctr],"LOCAL2")==0)
239 				gVars.log_facility = LOG_LOCAL2;
240 			if(strcmp(argv[ctr],"LOCAL3")==0)
241 				gVars.log_facility = LOG_LOCAL3;
242 			if(strcmp(argv[ctr],"LOCAL4")==0)
243 				gVars.log_facility = LOG_LOCAL4;
244 			if(strcmp(argv[ctr],"LOCAL5")==0)
245 				gVars.log_facility = LOG_LOCAL5;
246 			if(strcmp(argv[ctr],"LOCAL6")==0)
247 				gVars.log_facility = LOG_LOCAL6;
248 			if(strcmp(argv[ctr],"LOCAL7")==0)
249 				gVars.log_facility = LOG_LOCAL7;
250 		    }else{
251 			syslog(LOG_ERR,"No value provided with --log-facility option\n");
252 			exit(0);
253 		    }
254 		}else{
255 		if(strcmp(argv[ctr],"-u")==0)
256 		{
257 			// Set username name
258 		    if( ctr < argc-1 ){
259 			if(gVars.username){ free(gVars.username); gVars.username=0; } ctr++;
260 			if( (gVars.username = (char *)calloc(strlen(argv[ctr])+ 1,1) ) ==NULL){
261 				syslog(LOG_ERR,"Unable to allocate memory for -u option\n");
262 				exit(0);
263 			}
264 			bcopy(argv[ctr],gVars.username,strlen(argv[ctr]));
265 		    }else{
266 			syslog(LOG_ERR,"No user provided with -u option\n");
267 			exit(0);
268 		    }
269 		}else{
270 		if(strcmp(argv[ctr],"-g")==0)
271 		{
272 			// Set group name
273 		    if( ctr < argc-1 ){
274 			if(gVars.groupname){ free(gVars.groupname); gVars.groupname=0; } ctr++;
275 			if( (gVars.groupname = (char *)calloc(strlen(argv[ctr])+ 1,1) ) ==NULL){
276 				syslog(LOG_ERR,"Unable to allocate memory for -g option\n");
277 				exit(0);
278 			}
279 			bcopy(argv[ctr],gVars.groupname,strlen(argv[ctr]));
280 		    }else{
281 			syslog(LOG_ERR,"No group provided with -g option\n");
282 			exit(0);
283 		    }
284 		}else{
285 		if(strcmp(argv[ctr],"-F")==0)
286 		{
287 			// Set bp filter file name
288 			if( ctr < argc-1 ){
289 				ctr++;
290 				// We alloc mem here, but fileHandle will free it
291 				// This should be changed, but it works for now
292 				set_bpf_filter(argv[ctr]);
293 				syslog(LOG_INFO,"using file %s: %s\n",gVars.bpf_fname,argv[ctr]);
294 			//if(!gVars.daemon_mode)
295 				syslog(LOG_INFO,"enabling bpf filter from file %s: %s\n",gVars.bpf_fname,argv[ctr]);
296 
297 			}else{
298 				syslog(LOG_ERR,"No filename provided with -F option\n");
299 				exit(0);
300 			}
301 		}else{
302 		if(strcmp(argv[ctr],"--strip-80211")==0)
303 		{
304 			// enable removal of 80211 header
305 			gVars.strip_80211 = ENABLED;
306 			if(!gVars.daemon_mode)
307 				syslog(LOG_INFO,"enabling stripping of 80211 headers\n");
308 		}else{
309 		if(strcmp(argv[ctr],"--local-time")==0)
310 		{
311 			// disable GMT, enable localtime
312 			gVars.uselocaltime = 1;
313 			if(!gVars.daemon_mode)
314 				syslog(LOG_INFO,"enabling local timestamps instead of GMT\n");
315 		}else{
316 		if(strcmp(argv[ctr],"-A")==0)
317 		{
318 			// enable recording all data to tcpdump file before
319 			// processing, any strip-80211 option applies, however
320 			if(gVars.rpfH){ gVars.rpfH->destroy(); gVars.rpfH=0; }
321 		        ftmp=createFileName(PCAP_RAW_FNAME);
322 		        gVars.rpfH = new pcapFileHandle(ftmp);
323 			free(ftmp);
324 			gVars.pcap_raw = ENABLED;
325 			syslog(LOG_INFO,"enabling debug recording of all pcap data to a tcpdump file\n");
326 		}else{
327                 if(strcmp(argv[ctr],"-R")==0)
328                 {
329                         // disable realtime
330                         gVars.cmdl_realtimes_action = ACTION_PASS;
331 	                gVars.rmode = OMODE_PASS;
332                         syslog(LOG_INFO,"disabling default 'realtimes' logging mode\n");
333                 }else{
334                 if(strcmp(argv[ctr],"-P")==0)
335                 {
336                         // disable default collect action
337                         gVars.cmdl_pcap_action = ACTION_PASS;
338                         gVars.pmode = OMODE_PASS;
339                         syslog(LOG_INFO,"disabling default 'pcap' logging mode\n");
340 
341                 }else{
342                 if(strcmp(argv[ctr],"-S")==0)
343                 {
344                         // disable default log action
345                         gVars.cmdl_stats_action = ACTION_PASS;
346 	                gVars.smode = OMODE_PASS;
347                         syslog(LOG_INFO,"disabling default 'stats' logging mode\n");
348                 }else{
349 		if(strcmp(argv[ctr],"-I")==0 || strcmp(argv[ctr],"--enable-icmp-mixed")==0)
350 		{
351 			// enable  recording and tracking  ICMP type/code in src and dst port fields
352 			gVars.log_icmp_type_code = 1;
353 			syslog(LOG_INFO,"enabling logging icmp type/code for s_port and d_port fields\n");
354 		}else{
355 		if(strcmp(argv[ctr],"-B")==0)
356 		{
357 			// The rest of this line should be the bpf expression
358 			if(gVars.bpf_filter){ free(gVars.bpf_filter); } ctr++;
359 			if(argc>ctr){
360 		       	 	gVars.bpf_filter=(char *) calloc(1,strlen(argv[ctr])+1);
361 		        	strncpy(gVars.bpf_filter,argv[ctr],strlen(argv[ctr]));
362 				syslog(LOG_INFO,"enabling bpf expression %s\n",gVars.bpf_filter);
363 			}
364 
365 		}else{
366 		if(strcmp(argv[ctr],"-H")==0 || strcmp(argv[ctr],"--human-readable")==0)
367 		{
368 			// enable human readable mode - affects IP addressess and tcp flag fields
369 			gVars.human_readable = 1;
370 			syslog(LOG_INFO,"enabling human readable connection logging\n");
371 
372 		}else{
373 		if(strcmp(argv[ctr],"-V")==0||strcmp(argv[ctr],"-v")==0)
374 		{
375 			version();
376 			license();
377 			exit_all(0);
378 		}else{
379 		if(strcmp(argv[ctr],"-?")==0 || strcmp(argv[ctr],"-h")==0){
380 			version();
381 			usage();
382 			exit_all(0);
383 		}else{
384 			// See if this was a -option
385 			if(strstr(argv[ctr],"-")){
386 				syslog(LOG_ERR,"skipping unrecognized option: %s\n",argv[ctr]);
387 
388 			}else{
389 		// The rest of this line should be the bpf expression
390 			//if((argc-1)>(ctr++)){
391 				if(gVars.bpf_filter){ free(gVars.bpf_filter); gVars.bpf_filter=0; }
392 		        	gVars.bpf_filter=(char *) calloc(1,strlen(argv[ctr])+1);
393 			        strncpy(gVars.bpf_filter,argv[ctr],strlen(argv[ctr]));
394 				syslog(LOG_INFO,"enabling bpf expression %s\n",gVars.bpf_filter);
395 				//syslog(LOG_ERR,"Unknown option: %s\n",argv[ctr]);
396 				}
397 			//}
398 
399 		}}}}}}}}}}}}}}}}}}}}}}}}
400 	}
401 
402 
403 }
build_config(int a)404 void build_config(int a){
405 	extern struct gvars gVars;
406 	int lc=0;
407 	FILE *config_file;
408 	int size=0;
409 	int mylen=0;
410  	char *rule=NULL;
411 	char *accept="\t ,=";
412 	struct vars *tmp_var=NULL;
413 	struct acl *tmp_acl=0;
414 	struct t_ports *ports_head;
415 	struct t_ports *tmp_port;
416 	int p=0;
417 	if(!gVars.config_file){ return; }
418       	if((config_file=fopen(gVars.config_file,"r")) == NULL ) {
419 		return;
420       	}
421 	// Drop the vars now
422 	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;
423 	/* the first field should tell us everything we need to know about
424 	 * what to expect in the rule
425 	 */
426 #ifdef DEBUG
427 	fprintf(stdout,"Reading config\n");
428 #endif
429 	while((mylen=fgetcline(&rule, size, config_file)) >= 0){
430 		lc++;
431 		if(mylen<2){
432 #ifdef DEBUG
433 			fprintf(stdout,"Line: %d rule too small, skipping %s\n",lc, rule);
434 #endif
435 		continue; }
436 #ifdef DEBUG
437 		fprintf(stdout,"Processing %s\n",rule);
438 #endif
439 		if(strncmp(rule,"format",6)==0)
440 		{
441 			parse_format(rule,accept);
442 		}
443 		else if(strncmp(rule,"known_ports",11)==0)
444 		{
445 			parse_known_ports(rule,gVars.var_head,accept);
446 		}
447 		else if(strncmp(rule,"default",7)==0)
448 		{
449 			parse_default(rule,accept);
450 		}else if(strncmp(rule,"var",3)==0)
451 		{
452 			parse_var(rule,accept);
453 #ifdef DEBUG
454 			if(gVars.var_head!=NULL)
455 			fprintf(stdout,"Have var, %s/%s\n",gVars.var_head->key,gVars.var_head->value);
456 #endif
457 		}else{
458 			parse_connection_rule(rule,gVars.var_head,accept);
459 		}
460 		if(rule){
461 #ifdef DEBUG
462 			printf("freeing %X\n",(u_int32_t) &rule);
463 #endif
464 			free(rule);
465 			rule=NULL;
466 		}
467 
468 	}
469 	fclose(config_file);
470 #ifdef DEBUG
471 	printf("Done reading rules\n");
472 #endif
473 	// swap out old rules with new rules
474 	tmp_acl=gVars.acl_head;
475 	gVars.acl_head=tacl_head;
476 	tacl_head=tmp_acl;
477 #ifdef DEBUG
478 	printf("Disposing old rules\n");
479 #endif
480 	// dispose of previous rules
481 	while(tacl_head!=NULL){ tmp_acl=tacl_head; tacl_head=tacl_head->next; free(tmp_acl);}
482 	tacl_head=NULL; tacl_tail=NULL;
483 
484 #ifdef DEBUG
485 	printf("Disposing old ports\n");
486 #endif
487 	//while(acl_head!=NULL){ tmpptr=acl_head; acl_head=acl_head->next; free(tmpptr); }
488 	// dispose of previous ports
489 	for(p=0; p<MAX_IP_PROTO; p++)
490 	{
491 		ports_head=gVars.ports[p];
492 
493 		while(ports_head!=NULL){
494 			tmp_port=ports_head;
495 			ports_head=tmp_port->next;
496 			free(tmp_port);
497 		}
498 		gVars.ports[p]=tports[p];
499 		tports[p]=NULL;
500 	}
501 	// Dispose of temporary rule variables
502 	//
503 }
504 
parse_format(const char * c_rule,const char * accept)505 void parse_format(const char *c_rule,const char *accept)
506 {
507 	extern struct gvars gVars;
508 	extern char fmtnames[MAXFLDS][MAXFLDSIZE];
509 	char *rule=(char *)calloc(1,strlen(c_rule)+1);
510 	memcpy(rule,c_rule,strlen(c_rule));
511  	char *rules=rule;
512 	char *tok=0;
513 	if((tok = get_tok(&rules,accept))==NULL){
514 		syslog(LOG_ERR,"Skipping, Invalid default, rule trunicated %s\n",rule);
515 		return;
516 	}else if((tok = get_tok(&rules,accept))==NULL){
517 		syslog(LOG_ERR,"Skipping, Invalid default, rule trunicated %s\n",rule);
518 		return;
519 	}
520 
521 	int type=0;
522 	if(strcmp(tok,"realtime")==0)
523 		type=1;
524 	if(strcmp(tok,"stats")==0)
525 		type=2;
526 	if(strcmp(tok,"stdout")==0)
527 		type=4;
528 	char delimiter=0;
529 	if(strncmp(rules,"delimiter",9)==0){
530 		if((tok = get_tok(&rules,accept))==NULL){
531 			syslog(LOG_ERR,"Skipping, Invalid delimiter, rule trunicated %s\n",rule);
532 			return;
533 		}else if((tok = get_tok(&rules,accept))==NULL){
534 			syslog(LOG_ERR,"Skipping, Invalid delimiter, rule trunicated %s\n",rule);
535 			return;
536 		}
537 		delimiter=tok[0];
538 		if(delimiter=='\\'){
539 			if(tok[1]=='s')
540 				delimiter=' ';
541 			if(tok[1]=='t')
542 				delimiter='\t';
543 			if(tok[1]=='n')
544 				delimiter='\n';
545 		}
546 	}
547 
548 	char eor=0;
549 	if(strncmp(rules,"eor",3)==0){
550 		if((tok = get_tok(&rules,accept))==NULL){
551 			syslog(LOG_ERR,"Skipping, Invalid eor, rule trunicated %s\n",rule);
552 			return;
553 		}else if((tok = get_tok(&rules,accept))==NULL){
554 			syslog(LOG_ERR,"Skipping, Invalid eor, rule trunicated %s\n",rule);
555 			return;
556 		}
557 		eor=tok[0];
558 		if(eor=='\\'){
559 			if(tok[1]=='s')
560 				eor=' ';
561 			if(tok[1]=='t')
562 				eor='\t';
563 			if(tok[1]=='n')
564 				eor='\n';
565 		}
566 	}
567 
568 	char *tmpfldnames;
569 	int col=0;
570 	int icol=0;
571 	int fmtval=0;
572 	char fmt[MAXFLDS];
573 	while(rules && (tok = get_tok(&rules,accept))!=NULL && *tok != 0)
574 	{
575 		tmpfldnames=(char *)fmtnames;
576 		while((fmtval<MAXFLDS) && strncmp(tmpfldnames,tok,MAXFLDSIZE)){
577 			/* keep track of the current index of fmtnames in fmtval */
578 			tmpfldnames+=MAXFLDSIZE; fmtval++;
579 		}
580 		/* if our index (fmtval) exceeds MAXFLDS then we have no more room in our fmt array */
581 		if(fmtval<MAXFLDS){
582 			fmt[col]=fmtval;
583 			col++;
584 		}else{
585 			syslog(LOG_ERR,"Skipping, invalid format field name %s for column %d",tok,icol);
586 		}
587 		if(col>MAXFLDS-1){
588 			syslog(LOG_ERR,"Exceeded maximum columns allowed (%d) , skipping remaining format fields at column %d: %s",MAXFLDS,icol,rules);
589 			break;
590 		}
591 		icol++;
592 		fmtval=0;
593 	}
594 	if(type==1){
595 		if(gVars.realtime_fmt_len){
596 			free(gVars.realtime_fmt);
597 			gVars.realtime_fmt_len=0;
598 		}
599 		gVars.realtime_fmt=(char *) calloc(col,1);
600 		memcpy(gVars.realtime_fmt,fmt,col);
601 		gVars.realtime_fmt_len=col;
602 		if(eor)
603 			gVars.realtime_eor=eor;
604 		if(delimiter)
605 			gVars.realtime_delimiter=delimiter;
606 		if(gVars.rfH){
607 			gVars.rfH->setFormat(gVars.realtime_fmt,gVars.realtime_fmt_len);
608 	                gVars.rfH->setEor(gVars.realtime_eor);
609 	                gVars.rfH->setDelimiter(gVars.realtime_delimiter);
610 
611 		}
612 	}
613 	if(type==2){
614 		if(gVars.stats_fmt_len){
615 			free(gVars.stats_fmt);
616 			gVars.stats_fmt_len=0;
617 		}
618 		gVars.stats_fmt=(char *) calloc(col,1);
619 		memcpy(gVars.stats_fmt,fmt,col);
620 		gVars.stats_fmt_len=col;
621 		if(eor)
622 			gVars.stats_eor=eor;
623 		if(delimiter)
624 			gVars.stats_delimiter=delimiter;
625 		if(gVars.sfH){
626 			gVars.sfH->setFormat(gVars.stats_fmt,gVars.stats_fmt_len);
627 	                gVars.sfH->setEor(gVars.stats_eor);
628 	                gVars.sfH->setDelimiter(gVars.stats_delimiter);
629 		}
630 	}
631 	if(type==4){
632 		if(gVars.stdout_fmt_len){
633 			free(gVars.stdout_fmt);
634 			gVars.stdout_fmt_len=0;
635 		}
636 		gVars.stdout_fmt=(char *) calloc(col,1);
637 		memcpy(gVars.stdout_fmt,fmt,col);
638 		gVars.stdout_fmt_len=col;
639 		if(eor)
640 			gVars.stdout_eor=eor;
641 		if(delimiter)
642 			gVars.stdout_delimiter=delimiter;
643 		if(gVars.sdF){
644 			gVars.sdF->setFormat(gVars.stdout_fmt,gVars.stdout_fmt_len);
645 	                gVars.sdF->setEor(gVars.stdout_eor);
646 	                gVars.sdF->setDelimiter(gVars.stdout_delimiter);
647 		}
648 	}
649 	if(rule) free(rule);
650 
651 }
652 
parse_default(char * c_rule,char * accept)653 void parse_default(char *c_rule,char *accept)
654 {
655 	extern struct gvars gVars;
656         char *rule=(char *)calloc(1,strlen(c_rule)+1);
657         memcpy(rule,c_rule,strlen(c_rule));
658 	char *rules=rule;
659 	char *tok=0;
660 	char *tmp=0;
661 	char *ftmp=0;
662 	char *pptr=0;
663 
664 	if((tok = get_tok(&rules,accept))==NULL){
665 		syslog(LOG_ERR,"Skipping, Invalid default, rule trunicated %s\n",rule);
666 		free(rule);
667 		return;
668 	}else if((tok = get_tok(&rules,accept))==NULL){
669 		syslog(LOG_ERR,"Skipping, Invalid default, rule trunicated %s\n",rule);
670 		free(rule);
671 		return;
672 	}
673 	if(strcmp(tok,"expire_interval")==0)
674 	{
675 		if((tmp = get_tok(&rules,accept))==NULL)
676 		{
677 			syslog(LOG_ERR,"Format error, default expire_interval specified but none provided, using default expire_interval %d\n",DEFAULT_EXPIRE_INTERVAL);
678 			gVars.default_expire_interval = DEFAULT_EXPIRE_INTERVAL;
679 			free(rule);
680 			return;
681 		}
682 		pptr=tmp;
683 		gVars.default_expire_interval = (u_int16_t) strtol(tmp,&pptr,0);
684 		if(tmp==pptr)
685 		{
686 			syslog(LOG_ERR,"Format error, invalid expire_interval %s, using default expire_interval  %d\n",tmp,DEFAULT_EXPIRE_INTERVAL);
687 		}
688 		free(rule);
689 		return;
690 	}
691 	if(strcmp(tok,"flush_interval")==0)
692 	{
693 		int reset_alarm=gVars.default_flush_interval;
694 		if((tmp = get_tok(&rules,accept))==NULL)
695 		{
696 			syslog(LOG_ERR,"Format error, default flush_interval specified but none provided, using default flush_interval %d\n",DEFAULT_FLUSH_INTERVAL);
697 			gVars.default_flush_interval = DEFAULT_FLUSH_INTERVAL;
698 			free(rule);
699 			return;
700 		}
701 		pptr=tmp;
702 		gVars.default_flush_interval = (u_int16_t) strtol(tmp,&pptr,0);
703 		if(tmp==pptr)
704 		{
705 			syslog(LOG_ERR,"Format error, invalid flush_interval %s, using default flush_interval  %d\n",tmp,DEFAULT_FLUSH_INTERVAL);
706 		}
707 		// If the default flush_interval in the config file changed, we
708 		// need to reset the alarm to the new interval
709 		if(reset_alarm){
710 			alarm(gVars.default_flush_interval);
711 		}
712 		free(rule);
713 		return;
714 	}
715 	if(strcmp(tok,"zone")==0)
716 	{
717 		if((tmp = get_tok(&rules,accept))==NULL)
718 		{
719 			syslog(LOG_ERR,"Format error, default zone specified but none provided, using default zone %d\n",DEFAULT_ZONE);
720 			gVars.default_zone = DEFAULT_ZONE;
721 			free(rule);
722 			return;
723 		}
724 		pptr=tmp;
725 		gVars.default_zone = (u_int16_t) strtol(tmp,&pptr,0);
726 		if(tmp==pptr)
727 		{
728 			syslog(LOG_ERR,"Format error, invalid zone %s, using default zone %d\n",tmp,DEFAULT_ZONE);
729 		}
730 		free(rule);
731 		return;
732 	}
733 	if(strcmp(tok,"node")==0)
734 	{
735 		if((tmp = get_tok(&rules,accept))==NULL)
736 		{
737 			syslog(LOG_ERR,"Format error, default node specified but none provided, using default node %d\n",DEFAULT_NODE);
738 			gVars.default_node = DEFAULT_NODE;
739 			free(rule);
740 			return;
741 		}
742 		pptr=tmp;
743 		gVars.default_node = (u_int16_t) strtol(tmp,&pptr,0);
744 		if(tmp==pptr)
745 		{
746 			syslog(LOG_ERR,"Format error, invalid node %s, using default node %d\n",tmp,DEFAULT_NODE);
747 		}
748 		free(rule);
749 		return;
750 	}
751 	if(strcmp(tok,"rid")==0)
752 	{
753 		if((tmp = get_tok(&rules,accept))==NULL)
754 		{
755 			syslog(LOG_ERR,"Format error, default rid specified but none provided, using default rid %d\n",DEFAULT_RID);
756 			gVars.default_rid = DEFAULT_RID;
757 			free(rule);
758 			return;
759 		}
760 		pptr=tmp;
761 		gVars.default_rid = (u_int32_t) strtol(tmp,&pptr,0);
762 		if(tmp==pptr)
763 		{
764 			syslog(LOG_ERR,"Format error, invalid rid %s, using default rid %d\n",tmp,DEFAULT_RID);
765 		}
766 		free(rule);
767 		return;
768 	}
769 	if(strcmp(tok,"rgid")==0)
770 	{
771 		if((tmp = get_tok(&rules,accept))==NULL)
772 		{
773 			syslog(LOG_ERR,"Format error, default rgid specified but none provided, using default rgid %d\n",DEFAULT_RGID);
774 			gVars.default_rgid = DEFAULT_RGID;
775 			free(rule);
776 			return;
777 		}
778 		pptr=tmp;
779 		gVars.default_rgid = (u_int32_t) strtol(tmp,&pptr,0);
780 		if(tmp==pptr)
781 		{
782 			syslog(LOG_ERR,"Format error, invalid rid %s, using default rid %d\n",tmp,DEFAULT_RID);
783 		}
784 		free(rule);
785 		return;
786 	}
787 	if(strcmp(tok,"status")==0)
788 	{
789 		if((tmp = get_tok(&rules,accept))==NULL)
790 		{
791 			syslog(LOG_ERR,"Format error, default status specified but none provided, using default status %d\n",DEFAULT_STATUS);
792 			gVars.default_status = DEFAULT_STATUS;
793 			free(rule);
794 			return;
795 		}
796 		pptr=tmp;
797 		gVars.default_status = (u_int8_t) strtol(tmp,&pptr,0);
798 		if(tmp==pptr)
799 		{
800 			syslog(LOG_ERR,"Format error, invalid status %s, using default status %d\n",tmp,DEFAULT_STATUS);
801 		}
802 		free(rule);
803 		return;
804 	}
805 	if(strcmp(tok,"use_pcap_time")==0)
806 	{
807 		if((tmp = get_tok(&rules,accept))==NULL)
808 		{
809 			syslog(LOG_ERR,"Format error, default for use_pcap_time specified but no value provided%s\n",rule);
810 			free(rule);
811 			return;
812 		}
813 		if(strcmp(tmp,"enable")==0)
814 		{
815 			gVars.use_pcap_time = ENABLED;
816 		}
817 		if(strcmp(tmp,"disable")==0)
818 		{
819 			gVars.use_pcap_time = DISABLED;
820 		}
821 #ifdef DEBUG
822 		fprintf(stdout,"Setting default for %s to %s\n",tok,tmp);
823 #endif
824 		free(rule);
825 		return;
826 	}
827 	if(strcmp(tok,"burst_mode")==0)
828 	{
829 		if((tmp = get_tok(&rules,accept))==NULL)
830 		{
831 			syslog(LOG_ERR,"Format error, default for burst_mode specified but no value provided%s\n",rule);
832 			free(rule);
833 			return;
834 		}
835 		if(strcmp(tmp,"enable")==0)
836 		{
837 			gVars.burst_mode = ENABLED;
838 		}
839 		if(strcmp(tmp,"disable")==0)
840 		{
841 			gVars.burst_mode = DISABLED;
842 		}
843 #ifdef DEBUG
844 		fprintf(stdout,"Setting default for %s to %s\n",tok,tmp);
845 #endif
846 		free(rule);
847 		return;
848 	}
849 	if(strcmp(tok,"debug_pcap_raw")==0)
850 	{
851 		if((tmp = get_tok(&rules,accept))==NULL)
852 		{
853 			syslog(LOG_ERR,"Format error, default for debug_pcap_raw specified but no value provided%s\n",rule);
854 			free(rule);
855 			return;
856 		}
857 		if(strcmp(tmp,"enable")==0)
858 		{
859 			if(gVars.rpfH){ gVars.rpfH->destroy(); gVars.rpfH=0;  }
860 		        ftmp=createFileName("tcpdump");
861 		        gVars.rpfH = new pcapFileHandle(ftmp);
862 			free(ftmp);
863 			gVars.pcap_raw = ENABLED;
864 		}
865 		if(strcmp(tmp,"disable")==0)
866 		{
867 			if(gVars.rpfH){ gVars.rpfH->destroy(); gVars.rpfH=0;  }
868 			gVars.pcap_raw = DISABLED;
869 		}
870 #ifdef DEBUG
871 		fprintf(stdout,"Setting default for %s to %s\n",tok,tmp);
872 #endif
873 			free(rule);
874 		return;
875 	}
876 	if(strcmp(tok,"strip-80211")==0)
877 	{
878 		if((tmp = get_tok(&rules,accept))==NULL)
879 		{
880 			syslog(LOG_ERR,"Format error, default for strip_80211 specified but no value provided%s\n",rule);
881 			free(rule);
882 			return;
883 		}
884 		if(strcmp(tmp,"enable")==0)
885 		{
886 			gVars.strip_80211 = ENABLED;
887 		}
888 		if(strcmp(tmp,"disable")==0)
889 		{
890 			gVars.strip_80211 = DISABLED;
891 		}
892 #ifdef DEBUG
893 		fprintf(stdout,"Setting default for %s to %s\n",tok,tmp);
894 #endif
895 		free(rule);
896 		return;
897 	}
898 	if(strcmp(tok,"pcapfilter")==0)
899 	{
900 		// We don't parse pcapfilter after initial startup, so see if we have an open pcap handle
901 		if( gVars.ph!=0 ){ free(rule); return; }
902 		gVars.bpf_filter=(char *) calloc(1,strlen(rules)+1);
903 		strncpy(gVars.bpf_filter,rules,strlen(rules));
904 		syslog(LOG_INFO,"setting pcap filter expression %s\n",gVars.bpf_filter);
905 
906 #ifdef DEBUG
907 		fprintf(stdout,"Setting default for %s to %s\n",tok,tmp);
908 #endif
909 		free(rule);
910 		return;
911 	}
912 	if(strcmp(tok,"stats")==0)
913 	{
914 		if((tmp = get_tok(&rules,accept))==NULL)
915 		{
916 			syslog(LOG_ERR,"Format error, default for stats specified but no value provided%s\n",rule);
917 			free(rule);
918 			return;
919 		}
920 		if(strcmp(tmp,"log")==0) // log all matching traffic
921 		{
922                         if(gVars.stats_fname){ free(gVars.stats_fname); }
923 		        gVars.stats_fname=(char *) calloc(1,strlen(STATS_FNAME)+1);
924 		        strncpy(gVars.stats_fname,STATS_FNAME,strlen(STATS_FNAME));
925 			if(gVars.sfH){ gVars.sfH->destroy(); gVars.sfH=0;  }
926 		        ftmp=createFileName(gVars.stats_fname);
927 		        gVars.sfH = new outputFileHandle((const char*)ftmp,gVars.stats_fmt,gVars.stats_fmt_len,APPEND_MODE);
928 			free(ftmp);
929                         gVars.smode=OMODE_LOG;
930 		}
931 		if(strcmp(tmp,"pass")==0)
932 		{
933 			if(gVars.sfH){ gVars.sfH->destroy(); gVars.sfH=0; }
934                         gVars.smode=OMODE_PASS;
935 		}
936                 if(strcmp(tmp,"filename")==0)
937                 {
938                         if((tmp = get_tok(&rules,accept))==NULL)
939                         {
940                                 syslog(LOG_ERR,"Format error, default filename for stats specified but no value provided%s\n",rule);
941                                 return;
942                         }
943                         if(gVars.stats_fname){ free(gVars.stats_fname); }
944                         gVars.stats_fname=(char *) calloc(1,strlen(tmp)+1);
945                         strncpy(gVars.stats_fname,tmp,strlen(tmp));
946                         gVars.smode=OMODE_FILENAME;
947                         if(gVars.sfH){ gVars.sfH->destroy(); gVars.sfH=0; }
948                         ftmp=createFileName(gVars.stats_fname,gVars.smode == OMODE_TSFILENAME);
949 		        gVars.sfH = new outputFileHandle((const char*)ftmp,gVars.stats_fmt,gVars.stats_fmt_len,APPEND_MODE);
950                         gVars.sfH->setEor(gVars.stats_eor);
951                         gVars.sfH->setDelimiter(gVars.stats_delimiter);
952                         free(ftmp);
953                 }
954                 if(strcmp(tmp,"tsfilename")==0)
955                 {
956                         if((tmp = get_tok(&rules,accept))==NULL)
957                         {
958                                 syslog(LOG_ERR,"Format error, default tsfilename for stats specified but no value provided%s\n",rule);
959 				free(rule);
960                                 return;
961                         }
962                         if(gVars.stats_fname){ free(gVars.stats_fname); }
963                         gVars.stats_fname=(char *) calloc(1,strlen(tmp)+1);
964                         strncpy(gVars.stats_fname,tmp,strlen(tmp));
965                         gVars.smode=OMODE_TSFILENAME;
966                         if(gVars.sfH){ gVars.sfH->destroy(); gVars.sfH=0; }
967                         ftmp=createFileName(gVars.stats_fname,gVars.smode == OMODE_TSFILENAME);
968 		        gVars.sfH = new outputFileHandle((const char*)ftmp,gVars.stats_fmt,gVars.stats_fmt_len,APPEND_MODE);
969                         gVars.sfH->setEor(gVars.stats_eor);
970                         gVars.sfH->setDelimiter(gVars.stats_delimiter);
971                         free(ftmp);
972                 }
973 
974 #ifdef DEBUG
975 		fprintf(stdout,"Setting default for %s to %s\n",tok,tmp);
976 #endif
977 		free(rule);
978 		return;
979 	}
980 	if(strcmp(tok,"pcap")==0)
981 	{
982 		if((tmp = get_tok(&rules,accept))==NULL)
983 		{
984 			syslog(LOG_ERR,"Format error, default for pcap specified but no value provided%s\n",rule);
985 			free(rule);
986 			return;
987 		}
988 		if(strcmp(tmp,"log")==0) // log all matching traffic
989 		{
990 			gVars.pmode = OMODE_LOG;
991 			if(gVars.pcap_fname){ free(gVars.pcap_fname); }
992 		        gVars.pcap_fname=(char *) calloc(1,strlen(PCAP_FNAME)+1);
993 		        strncpy(gVars.pcap_fname,PCAP_FNAME,strlen(PCAP_FNAME));
994 			if(gVars.pfH){ gVars.pfH->destroy(); gVars.pfH=0; }
995 		        ftmp=createFileName(gVars.pcap_fname);
996 		        gVars.pfH = new pcapFileHandle(ftmp);
997 			free(ftmp);
998 		}
999 		if(strcmp(tmp,"pass")==0)
1000 		{
1001 			gVars.pmode=OMODE_PASS;
1002 			if(gVars.pfH){ gVars.pfH->destroy(); gVars.pfH=0; }
1003 		}
1004 		if(strcmp(tmp,"filename")==0)
1005 		{
1006 			if((tmp = get_tok(&rules,accept))==NULL)
1007 			{
1008 				syslog(LOG_ERR,"Format error, default filename for pcap specified but no value provided%s\n",rule);
1009 				free(rule);
1010 				return;
1011 			}
1012 			if(gVars.pcap_fname){ free(gVars.pcap_fname); }
1013 		        gVars.pcap_fname=(char *) calloc(1,strlen(tmp)+1);
1014 		        strncpy(gVars.pcap_fname,tmp,strlen(tmp));
1015 			gVars.pmode=OMODE_FILENAME;
1016 			if(gVars.pfH){ gVars.pfH->destroy(); gVars.pfH=0; }
1017 		        ftmp=createFileName(gVars.pcap_fname,gVars.pmode == OMODE_TSFILENAME );
1018 		        gVars.pfH = new pcapFileHandle(ftmp);
1019 			free(ftmp);
1020 		}
1021 		if(strcmp(tmp,"tsfilename")==0)
1022 		{
1023 			if((tmp = get_tok(&rules,accept))==NULL)
1024 			{
1025 				syslog(LOG_ERR,"Format error, default tsfilename for pcap specified but no value provided%s\n",rule);
1026 				free(rule);
1027 				return;
1028 			}
1029 			if(gVars.pcap_fname){ free(gVars.pcap_fname); }
1030 		        gVars.pcap_fname=(char *) calloc(1,strlen(tmp)+1);
1031 		        strncpy(gVars.pcap_fname,tmp,strlen(tmp));
1032 			gVars.pmode=OMODE_TSFILENAME;
1033 			if(gVars.pfH){ gVars.pfH->destroy(); gVars.pfH=0; }
1034 		        ftmp=createFileName(gVars.pcap_fname,gVars.pmode == OMODE_TSFILENAME);
1035 		        gVars.pfH = new pcapFileHandle(ftmp);
1036 			free(ftmp);
1037 		}
1038 
1039 #ifdef DEBUG
1040 		fprintf(stdout,"Setting default for %s to %s\n",tok,tmp);
1041 #endif
1042 		free(rule);
1043 		return;
1044 	}
1045 	if(strcmp(tok,"realtime")==0)
1046 	{
1047 		if((tmp = get_tok(&rules,accept))==NULL)
1048 		{
1049 			syslog(LOG_ERR,"Format error, default for realtime specified but no value provided%s\n",rule);
1050 			free(rule);
1051 			return;
1052 		}
1053 		if(strcmp(tmp,"log")==0) // log all matching traffic
1054 		{
1055                         if(gVars.realtime_fname){ free(gVars.realtime_fname); }
1056 		        gVars.realtime_fname=(char *) calloc(1,strlen(REALTIME_FNAME)+1);
1057 		        strncpy(gVars.realtime_fname,REALTIME_FNAME,strlen(REALTIME_FNAME));
1058 			if(gVars.rfH){ gVars.rfH->destroy(); gVars.rfH=0;  }
1059 		        ftmp=createFileName(gVars.realtime_fname);
1060 		        gVars.rfH = new outputFileHandle((const char*)ftmp,gVars.realtime_fmt,gVars.realtime_fmt_len,APPEND_MODE);
1061 			free(ftmp);
1062                         gVars.rmode=OMODE_LOG;
1063 		}
1064 		if(strcmp(tmp,"pass")==0)
1065 		{
1066 			if(gVars.rfH){ gVars.rfH->destroy(); gVars.rfH=0; }
1067                         gVars.rmode=OMODE_PASS;
1068 		}
1069                 if(strcmp(tmp,"filename")==0)
1070                 {
1071                         if((tmp = get_tok(&rules,accept))==NULL)
1072                         {
1073                                 syslog(LOG_ERR,"Format error, default filename for realtime specified but no value provided%s\n",rule);
1074 				free(rule);
1075                                 return;
1076                         }
1077                         if(gVars.realtime_fname){ free(gVars.realtime_fname); }
1078                         gVars.realtime_fname=(char *) calloc(1,strlen(tmp)+1);
1079                         strncpy(gVars.realtime_fname,tmp,strlen(tmp));
1080                         gVars.rmode=OMODE_FILENAME;
1081                         if(gVars.rfH){ gVars.rfH->destroy(); gVars.rfH=0; }
1082                         ftmp=createFileName(gVars.realtime_fname,gVars.rmode == OMODE_TSFILENAME);
1083 		        gVars.rfH = new outputFileHandle((const char*)ftmp,gVars.realtime_fmt,gVars.realtime_fmt_len,APPEND_MODE);
1084                         gVars.rfH->setEor(gVars.realtime_eor);
1085                         gVars.rfH->setDelimiter(gVars.realtime_delimiter);
1086                         free(ftmp);
1087                 }
1088                 if(strcmp(tmp,"tsfilename")==0)
1089                 {
1090                         if((tmp = get_tok(&rules,accept))==NULL)
1091                         {
1092                                 syslog(LOG_ERR,"Format error, default tsfilename for realtime specified but no value provided%s\n",rule);
1093 				free(rule);
1094                                 return;
1095                         }
1096                         if(gVars.realtime_fname){ free(gVars.realtime_fname); }
1097                         gVars.realtime_fname=(char *) calloc(1,strlen(tmp)+1);
1098                         strncpy(gVars.realtime_fname,tmp,strlen(tmp));
1099                         gVars.rmode=OMODE_TSFILENAME;
1100                         if(gVars.rfH){ gVars.rfH->destroy(); gVars.rfH=0; }
1101                         ftmp=createFileName(gVars.realtime_fname,gVars.rmode == OMODE_TSFILENAME);
1102 		        gVars.rfH = new outputFileHandle((const char*)ftmp,gVars.realtime_fmt,gVars.realtime_fmt_len,APPEND_MODE);
1103                         gVars.rfH->setEor(gVars.realtime_eor);
1104                         gVars.rfH->setDelimiter(gVars.realtime_delimiter);
1105                         free(ftmp);
1106                 }
1107 
1108 #ifdef DEBUG
1109 		fprintf(stdout,"Setting default for %s to '%s'\n",tok,tmp);
1110 #endif
1111 		free(rule);
1112 		return;
1113 	}
1114 	if(strcmp(tok,"limit")==0)
1115 	{
1116 		if((tmp = get_tok(&rules,accept))==NULL)
1117 		{
1118 			syslog(LOG_ERR,"Format error, limit specified but none provided, using default limit %d\n",DEFAULT_LIMIT);
1119 			free(rule);
1120 			return;
1121 		}
1122 		pptr=tmp;
1123 		gVars.default_limit = (u_int64_t) strtoll(tmp,&pptr,0);
1124 		if(tmp==pptr)
1125 		{
1126 			syslog(LOG_ERR,"Format error, invalid limit %s, using default limit %d\n",tmp,DEFAULT_LIMIT);
1127 			gVars.default_limit = DEFAULT_LIMIT;
1128 		}
1129 		free(rule);
1130 		return;
1131 	}
1132 	if(strcmp(tok,"timeout")==0)
1133 	{
1134 		if((tmp = get_tok(&rules,accept))==NULL)
1135 		{
1136 			syslog(LOG_ERR,"Format error, default timeout specified but none provided, using timeout value %d\n",DEFAULT_TIMEOUT);
1137 			free(rule);
1138 			return;
1139 		}
1140 		pptr=tmp;
1141 		gVars.default_timeout = (u_int16_t) strtol(tmp,&pptr,0);
1142 		if(tmp==pptr)
1143 		{
1144 			syslog(LOG_ERR,"Format error, invalid timeout %s, using default timeout %d\n",tmp,DEFAULT_TIMEOUT);
1145 			gVars.default_timeout = DEFAULT_TIMEOUT;
1146 		}
1147 		free(rule);
1148 		return;
1149 	}
1150 	if(strcmp(tok,"tcplag")==0)
1151 	{
1152 	 	if((tmp = get_tok(&rules,accept))==NULL)
1153 		{
1154 			syslog(LOG_ERR,"Format error, tcplag specified but none provided, using tcplag value %d\n",DEFAULT_LAG);
1155 			free(rule);
1156 			return;
1157 		}
1158 		pptr=tmp;
1159 		gVars.default_tcplag = (u_int16_t) strtol(tmp,&pptr,0);
1160 		if(tmp==pptr)
1161 		{
1162 			syslog(LOG_ERR,"Format error, invalid tcplag %s, using default tcplag %d\n",tmp,DEFAULT_LAG);
1163 			gVars.default_tcplag = DEFAULT_LAG;
1164 		}
1165 		free(rule);
1166 		return;
1167 #ifdef DEBUG
1168 	fprintf(stdout,"Didn't set default for %s to %s\n",tok,tmp);
1169 #endif
1170 	}
1171 }
1172 
parse_var(char * c_rule,char * accept)1173 void parse_var(char *c_rule, char *accept)
1174 {
1175 	extern struct gvars gVars;
1176         char *rule=(char *)calloc(1,strlen(c_rule)+1);
1177         memcpy(rule,c_rule,strlen(c_rule));
1178         char **rules=&rule;
1179 	char *tok=NULL;
1180 	struct vars *n_var;
1181 	rules=&rule;
1182 
1183         	if((n_var=(struct vars *)calloc(1,sizeof(struct vars)))==NULL){ printf ("Out of Memory?\n"); return;}
1184 
1185 		n_var->key=NULL;
1186 		n_var->value=NULL;
1187 		n_var->next=NULL;
1188 		if((tok = get_tok(rules,accept))==NULL || strcmp(tok,"var")!=0)
1189 		{
1190 			syslog(LOG_ERR,"Skipping, Invalid rule trunicated when expecting var type %s\n",rule);
1191 			free(n_var);
1192 			free(rule);
1193 			return;
1194 		}
1195 		else
1196 		{
1197 			if((tok = get_tok(rules,accept))==NULL)
1198 			{
1199 				syslog(LOG_ERR,"Skipping, Invalid rule trunicated when expecting var key %s\n",rule);
1200 				free(n_var);
1201 				free(rule);
1202 				return;
1203 			}
1204 			else
1205 			{
1206         			if((n_var->key=(char *)calloc(1,sizeof(char)*strlen(tok)+1))==NULL){ printf ("Out of Memory?\n"); free(n_var); free(rule); return;}
1207 				strncpy(n_var->key,tok,sizeof(char)*strlen(tok));
1208 
1209 				if((tok = get_tok(rules,accept))==NULL)
1210 				{
1211 					syslog(LOG_ERR,"Skipping, Invalid rule trunicated when expecting var value %s\n",rule);
1212 					free(n_var->key);
1213 					n_var->key=NULL; free(n_var);
1214 					free(rule);
1215 					return;
1216 				}
1217 				else
1218 				{
1219         				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;}
1220 					strncpy(n_var->value,tok,sizeof(char)*strlen(tok));
1221 				}
1222 			}
1223 		}
1224 
1225 		// If we made it this var, then we have a valid var
1226 		if(!gVars.var_head){
1227 			gVars.var_head=n_var;
1228 		}
1229 		else
1230 		{
1231 			n_var->next = gVars.var_head;
1232 			gVars.var_head=n_var;
1233 		}
1234 		free(rule);
1235 }
1236 
1237 
1238 
search_vars(char * key,struct vars * var_head,int vclass)1239 char *search_vars(char *key, struct vars *var_head,  int vclass)
1240 {
1241 	struct vars *tmp;
1242        	tmp = var_head;
1243 #ifdef DEBUG
1244 	syslog(LOG_ERR,"Searching for key '%s'\n",key);
1245 #endif
1246 	while(tmp!=NULL)
1247 	{
1248 #ifdef DEBUG
1249 		fprintf(stdout,"Checking key/value (%d) '%s'/'%s' for (%d) '%s'\n",strlen(tmp->key),tmp->key,tmp->value,strlen(key),key);
1250 #endif
1251 		if(strcmp(tmp->key,key)==0)
1252 		{
1253 #ifdef DEBUG
1254 			syslog(LOG_ERR,"Found key/value %s/%s\n",key,tmp->value);
1255 #endif
1256 			// Mark the variable class that we were looking in
1257 			// so we will 'remember' which values pertained to which
1258 			// class of keys when we do a reverse lookup later.
1259 			// i.e. The value of 8 may exist in two or more classes
1260 			// Different class variables, having the same name, may
1261 			// cause undefined results.
1262 			tmp->vclass=vclass;
1263 			return tmp->value;
1264 		}
1265 		tmp=tmp->next;
1266 	}
1267 #ifdef DEBUG
1268 	fprintf(stdout,"Key not found '%s'\n",key);
1269 #endif
1270 	return NULL;
1271 }
1272 
rev_search_vars(char * value,struct vars * var_head,int vclass)1273 char *rev_search_vars(char *value, struct vars *var_head, int vclass)
1274 {
1275 	struct vars *tmp;
1276        	tmp = var_head;
1277 #ifdef DEBUG
1278 	syslog(LOG_INFO,"REV Search %d:'%s' for %d:'%s'\n",tmp->vclass,tmp->value,vclass,value);
1279 #endif
1280 	while(tmp!=NULL)
1281 	{
1282 		if( tmp->vclass==vclass && strcmp(tmp->value,value)==0)
1283 		{
1284 #ifdef DEBUG
1285 			syslog(LOG_ERR,"Found key/value %s/'%s'\n",tmp->key,tmp->value);
1286 #endif
1287 			return tmp->key;
1288 		}
1289 		tmp=tmp->next;
1290 	}
1291 #ifdef DEBUG
1292 	fprintf(stdout,"Value not found '%s'\n",value);
1293 #endif
1294 	return NULL;
1295 }
1296 
parse_known_ports(char * rule,struct vars * var_head,char * accept)1297 void parse_known_ports(char *rule, struct vars *var_head, char *accept)
1298 {
1299 	extern struct t_ports *tports[MAX_IP_PROTO];
1300 	char *tmp=NULL, *pptr=NULL,*tok=NULL;
1301  	char **rules=NULL;
1302 	struct t_ports *n_ports=NULL;
1303 	int proto = 0;
1304 	char ptok[256];
1305 	u_int16_t port_h=0;
1306 	u_int16_t port_l=0;
1307 	rules=&rule;
1308 
1309 		if((tok = get_tok(rules,accept))!=NULL)
1310 		{
1311 			if((tok = get_tok(rules,accept))==NULL)
1312 			{
1313 				syslog(LOG_ERR,"Skipping, Invalid rule trunicated when expecting ports protocol %s\n",rule);
1314 				return;
1315 			}
1316 	    		if((tmp=search_vars(tok,var_head,VCLASS_2))!=NULL)
1317 		    	{
1318 			    bzero(ptok,256);
1319 			    strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
1320 			    tok=ptok;
1321 		    	}
1322 
1323 			pptr=tok;
1324 
1325 			proto = (u_int8_t) strtol(tok,&pptr,0);
1326 
1327 			if(tok==pptr)
1328 			{
1329 				syslog(LOG_ERR,"Skipping, Invalid protocol value found: %s\n",tok);
1330 				return;
1331 			}
1332 
1333 			while((tok = get_tok(rules,accept))!=NULL && *tok != 0)
1334 			{
1335 	    			if((tmp=search_vars(tok,var_head,VCLASS_3))!=NULL)
1336 			    	{
1337 				    bzero(ptok,256);
1338 				    strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
1339 				    tok=ptok;
1340 			    	}
1341 				if((tmp = get_next_tok(&tok,"-"))!=NULL)
1342 				{
1343 					pptr=tmp;
1344 					port_l = (u_int16_t) strtol(tmp,&pptr,0);
1345 					if(tmp==pptr)
1346 					{
1347 						syslog(LOG_ERR,"Skipping, Invalid port start of range found: %s\n",tmp);
1348 						return;
1349 					}
1350 					pptr=tok;
1351 					port_h = (u_int16_t) strtol(tok,&pptr,0);
1352 					if(tok==pptr)
1353 					{
1354 						syslog(LOG_ERR,"Skipping, Invalid port end of range found: %s\n",tok);
1355 						return;
1356 					}
1357 				}else{
1358 					pptr=tok;
1359 					port_l = (u_int16_t) strtol(tok,&pptr,0);
1360 					if(tok==pptr)
1361 					{
1362 						syslog(LOG_ERR,"Skipping, Invalid port found: %X.\n",*tok);
1363 						return;
1364 					}
1365 #ifdef DEBUG
1366 					syslog(LOG_ERR,"Port found: %s\n",tok);
1367 #endif
1368 					port_h=port_l;
1369 				}
1370 				// if we made it this far we have a valid oort
1371         			if((n_ports=(struct t_ports *)calloc(1,sizeof(struct t_ports)))==NULL){ printf ("Out of Memory?\n"); return;}
1372 
1373 				n_ports->h_port=port_h;
1374 				n_ports->l_port=port_l;
1375 				n_ports->next=NULL;
1376 				if(!tports[proto]){
1377 					tports[proto]=n_ports;
1378 				}
1379 				else
1380 				{
1381 					n_ports->next = tports[proto];
1382 					tports[proto]=n_ports;
1383 				}
1384 			}
1385 		}else{
1386 			syslog(LOG_ERR,"Skipping, Invalid rule trunicated when expecting ports protocol %s\n",rule);
1387 		}
1388 }
1389 
parse_connection_rule(char * rule,struct vars * var_head,char * accept)1390 void parse_connection_rule(char *rule, struct vars *var_head, char *accept)
1391 {
1392 	// THIS FUNCTION DOES NOT EXIT THE PROGRAM WHEN IT RECEIVES A
1393 	// BAD RULE!!! THIS IS DONE TO ENSURE THIS TOOL CONTINUES COLLECTION
1394 	// SPECIFICALLY IN CASE IT READS A BAD CONFIGURATION FILE AFTER RECEIVING
1395 	// A KILL -HUP SIGNAL - SO ALWAYS CHECK THE SYSLOG FOR ERRORS
1396 	// IF THE DEFAULT PCAP MODE IS TO RECORD EVERYTHING THEN BAD RULES WILL
1397 	// NOT MEAN LOST DATA.  YOU CAN ALWAYS RE-PROCESS PCAP DATA BUT CAN'T
1398 	// RECOVER FROM DATA YOU DIDN'T RECORD
1399 	char *tmp, *tok=NULL;
1400  	char **rules=NULL;
1401 	char *pptr=NULL;
1402 	char *ftmp=0;
1403 	char ptok[256];
1404         struct acl *n_acl;
1405 	extern struct gvars gVars;
1406         extern struct acl *tacl_head, *tacl_tail;
1407 	bzero(ptok,256);
1408 	rules=&rule;
1409         	if((n_acl=(struct acl *)calloc(1,sizeof(struct acl)))==NULL){ syslog (LOG_CRIT,"Unable to allocate ACL - Out of Memory!\n"); return;}
1410 		bzero(n_acl,sizeof(struct acl));
1411 		n_acl->next=NULL;
1412 		n_acl->cmode = CMODE_BOTH;
1413 		n_acl->pcap = gVars.pmode?1:0;
1414 		n_acl->pmode = gVars.pmode;
1415 		n_acl->stats = gVars.smode?1:0;
1416 		n_acl->smode = gVars.smode;
1417 		n_acl->realtime = gVars.rmode?1:0;
1418 		n_acl->rmode = gVars.rmode;
1419 		n_acl->timeout = gVars.default_timeout;
1420 		n_acl->limit = gVars.default_limit;
1421 		n_acl->status = gVars.default_status;
1422 		n_acl->rid = gVars.default_rid;
1423 		n_acl->tcplag = gVars.default_tcplag;
1424 		if(gVars.pfH && gVars.pmode){
1425 			n_acl->fH = gVars.pfH->attach();
1426 		}else{
1427 			n_acl->fH = 0;
1428 		}
1429 
1430 		// FIELD 0 - required - Get the h_proto
1431                 n_acl->h_proto_h = 0xFFFF;
1432                 n_acl->h_proto_l = 0x0000;
1433 		if((tok = get_tok(rules,accept))==NULL)
1434 		{
1435 			syslog(LOG_ERR,"Skipping, Invalid rule trunicated when expecting hw protocol %s\n",rule);
1436 			free(n_acl);
1437 			return;
1438 		}
1439 		else if(strcmp(tok,"any")){
1440 	    		if((tmp=search_vars(tok,gVars.var_head,VCLASS_0))!=NULL)
1441 		    	{
1442 			    bzero(ptok,256);
1443 			    strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
1444 			    tok=ptok;
1445 		    	}
1446 
1447 			if((tmp = get_next_tok(&tok,"-"))!=NULL)
1448 			{
1449 				pptr=tmp;
1450 				n_acl->h_proto_l = (u_int16_t) strtol(tmp,&pptr,0);
1451 				if(tmp==pptr)
1452 				{
1453 					syslog(LOG_ERR,"Skipping, Invalid start of h_proto range found: %s\n",tmp);
1454 					free(n_acl); return;
1455 				}
1456 				pptr=tok;
1457 				n_acl->h_proto_h = (u_int16_t) strtol(tok,&pptr,0);
1458 				if(tok==pptr)
1459 				{
1460 					syslog(LOG_ERR,"Skipping, Invalid end of h_proto range found: %s\n",tok);
1461 					free(n_acl); return;
1462 				}
1463 			}else{
1464 				pptr=tok;
1465 				n_acl->h_proto_l = (u_int16_t) strtol(tok,&pptr,0);
1466 				if(tok==pptr)
1467 				{
1468 					syslog(LOG_ERR,"Skipping, Invalid h_protocol value found: %s\n",tok);
1469 					free(n_acl);
1470 					return;
1471 				}
1472 				n_acl->h_proto_h = n_acl->h_proto_l;
1473 			}
1474 		}
1475 
1476 		// FIELD 1 - required - Get the source address and mask fields
1477                 n_acl->s_mask=0xFFFFFFFF;
1478                 n_acl->s_ip=0x00000000;
1479 
1480 		if((tok = get_tok(rules,accept))==NULL)
1481 		{
1482 			syslog(LOG_ERR,"Skipping, Invalid rule trunicated when expecting source address and mask %s\n",rule);
1483 			free(n_acl);
1484 			return;
1485 		}
1486 		else if(strcmp(tok,"any")){
1487 		    	if((tmp=search_vars(tok,gVars.var_head,VCLASS_1))!=NULL)
1488 		    	{
1489 			    bzero(ptok,256);
1490 			    strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
1491 			    tok=ptok;
1492 		    	}
1493 
1494 			if((tmp = get_next_tok(&tok,"/"))!=NULL)
1495 			{
1496 				if(inet_aton(tmp,(struct in_addr *)&n_acl->s_ip)==0)
1497 				{
1498 					syslog(LOG_ERR,"Skipping, Invalid source address found: %s/%s %s\n",tmp,tok,rule);
1499 					free(n_acl);
1500 					return;
1501 				}
1502 				if(strstr(tok,"."))
1503 				{
1504 					if(inet_aton(tok,(struct in_addr *)&n_acl->s_mask)==0)
1505 					{
1506 						syslog(LOG_ERR,"Skipping, Invalid source mask found: %s/%s %s\n",tmp,tok,rule);
1507 						free(n_acl);
1508 						return;
1509 					}
1510 				}
1511 				else
1512 				{
1513 					pptr=tok;
1514 					n_acl->s_mask=htonl(0xFFFFFFF<<(32-(u_int8_t)(strtol(tok,&pptr,0))));
1515 					if(tok==pptr)
1516 					{
1517 						syslog(LOG_ERR,"Skipping, Invalid source mask found: %s/%s %s\n",tmp,tok,rule);
1518 						free(n_acl);
1519 						return;
1520 					}
1521 				}
1522 			}else{
1523 				if(inet_aton(tok,(struct in_addr *)&n_acl->s_ip)==0)
1524 				{
1525 					syslog(LOG_ERR,"Skipping, Invalid source address found: %s %s\n",tok,rule);
1526 					free(n_acl);
1527 					return;
1528 				}
1529 			}
1530 		}
1531 		// FIELD 3 - required - Get the destination address and mask fields
1532 
1533                 n_acl->d_mask=0xFFFFFFFF;
1534                 n_acl->d_ip=0x00000000;
1535 
1536 		if((tok = get_tok(rules,accept))==NULL)
1537 		{
1538 			syslog(LOG_ERR,"Skipping, Invalid rule trunicated when expecting destination address and mask %s\n",rule);
1539 			free(n_acl);
1540 			return;
1541 		}
1542 		else if(strcmp(tok,"any")){
1543 			if((tmp=search_vars(tok,gVars.var_head,VCLASS_1))!=NULL)
1544 			{
1545 			    bzero(ptok,256);
1546 			    strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
1547 			    tok=ptok;
1548 			}
1549 			if((tmp = get_next_tok(&tok,"/"))!=NULL)
1550 			{
1551 				if(inet_aton(tmp,(struct in_addr *)&n_acl->d_ip)==0)
1552 				{
1553 					syslog(LOG_ERR,"Skipping, Invalid destination address found: %s/%s %s\n",tmp,tok,rule);
1554 					free(n_acl);
1555 					return;
1556 				}
1557 				if(strstr(tok,"."))
1558 				{
1559 					if(inet_aton(tok,(struct in_addr *)&n_acl->d_mask)==0)
1560 					{
1561 						syslog(LOG_ERR,"Skipping, Invalid destination mask found: %s/%s %s\n",tmp,tok,rule);
1562 						free(n_acl);
1563 						return;
1564 					}
1565 				}
1566 				else
1567 				{
1568 					pptr=tok;
1569 					n_acl->d_mask=htonl(0xFFFFFFFF<<(32-(u_int8_t)(strtol(tok,&pptr,0))));
1570 					if(tok==pptr)
1571 					{
1572 						syslog(LOG_ERR,"Skipping, Invalid destination mask found: %s/%s %s\n",tmp,tok,rule);
1573 						free(n_acl);
1574 						return;
1575 					}
1576 				}
1577 			}else{
1578 				if(inet_aton(tok,(struct in_addr *)&n_acl->d_ip)==0)
1579 				{
1580 					syslog(LOG_ERR,"Skipping, Invalid destination address found: %s %s\n",tok,rule);
1581 					free(n_acl);
1582 					return;
1583 				}
1584 			}
1585 		}
1586 
1587 		// FIELD 4 - required - Get the protocol field
1588 		n_acl->proto_l = 0x00;
1589 		n_acl->proto_h = 0xFF;
1590 		if((tok = get_tok(rules,accept))==NULL)
1591 		{
1592 			syslog(LOG_ERR,"Skipping, Invalid rule trunicated when expecting protocol %s\n",rule);
1593 			free(n_acl);
1594 			return;
1595 		}
1596 		else if(strcmp(tok,"any")){
1597 		    	if((tmp=search_vars(tok,gVars.var_head,VCLASS_2))!=NULL)
1598 		    	{
1599 			    bzero(ptok,256);
1600 			    strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
1601 			    tok=ptok;
1602 		    	}
1603 
1604 			// Use the defaults for ANY
1605 			if((tmp = get_next_tok(&tok,"-"))!=NULL)
1606 			{
1607 				pptr=tmp;
1608 				n_acl->proto_l = (u_int8_t) strtol(tmp,&pptr,0);
1609 				if(tmp==pptr)
1610 				{
1611 					syslog(LOG_ERR,"Skipping, Invalid start of proto range found: %s\n",tmp);
1612 					free(n_acl); return;
1613 				}
1614 				pptr=tok;
1615 				n_acl->proto_h = (u_int8_t) strtol(tok,&pptr,0);
1616 				if(tok==pptr)
1617 				{
1618 					syslog(LOG_ERR,"Skipping, Invalid end of proto range found: %s\n",tok);
1619 					free(n_acl); return;
1620 				}
1621 			}else{
1622 				pptr=tok;
1623 				n_acl->proto_l = (u_int8_t) strtol(tok,&pptr,0);
1624 				if(tok==pptr)
1625 				{
1626 					syslog(LOG_ERR,"Skipping, Invalid protocol value found: %s\n",tok);
1627 					free(n_acl);
1628 					return;
1629 				}
1630 				n_acl->proto_h = n_acl->proto_l;
1631 			}
1632 		}
1633 
1634 		// FIELD 5 - required - Get the source ports field
1635 
1636                 n_acl->s_port_l=0x0000;
1637                 n_acl->s_port_h=0xFFFF;
1638 
1639 		if((tok = get_tok(rules,accept))==NULL)
1640 		{
1641 			syslog(LOG_ERR,"Skipping, Invalid rule trunicated when expecting source ports %s\n",rule);
1642 			free(n_acl);
1643 			return;
1644 		}
1645 		else if(strcmp(tok,"any")){
1646 		    	if((tmp=search_vars(tok,gVars.var_head,VCLASS_3))!=NULL)
1647 		    	{
1648 			    bzero(ptok,256);
1649 			    strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
1650 			    tok=ptok;
1651 		    	}
1652 
1653 			// Use the defaults for ANY
1654 			if((tmp = get_next_tok(&tok,"-"))!=NULL)
1655 			{
1656 				pptr=tmp;
1657 				n_acl->s_port_l = (u_int16_t) strtol(tmp,&pptr,0);
1658 				if(tmp==pptr)
1659 				{
1660 					syslog(LOG_ERR,"Skipping, Invalid source port start of range found: %s\n",tmp);
1661 					free(n_acl);
1662 					return;
1663 				}
1664 				pptr=tok;
1665 				n_acl->s_port_h = (u_int16_t) strtol(tok,&pptr,0);
1666 				if(tok==pptr)
1667 				{
1668 					syslog(LOG_ERR,"Skipping, Invalid source port end of range found: %s\n",tok);
1669 					free(n_acl);
1670 					return;
1671 				}
1672 			}else{
1673 				pptr=tok;
1674 				n_acl->s_port_l = (u_int16_t) strtol(tok,&pptr,0);
1675 				if(tok==pptr)
1676 				{
1677 					syslog(LOG_ERR,"Skipping, Invalid source port found: %s\n",tok);
1678 					free(n_acl);
1679 					return;
1680 				}
1681 				n_acl->s_port_h=n_acl->s_port_l;
1682 			}
1683 		}
1684 		// FIELD 6 - required - Get the destination ports field
1685 
1686                 n_acl->d_port_l=0x0000;
1687                 n_acl->d_port_h=0xFFFF;
1688 
1689 		if((tok = get_tok(rules,accept))==NULL)
1690 		{
1691 			syslog(LOG_ERR,"Skipping, Invalid rule trunicated when expecting destination ports %s\n",rule);
1692 			free(n_acl);
1693 			return;
1694 		}
1695 		else if(strcmp(tok,"any")){
1696 
1697 
1698 		    	if((tmp=search_vars(tok,gVars.var_head,VCLASS_3))!=NULL)
1699 		    	{
1700 			    bzero(ptok,256);
1701 			    strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
1702 			    tok=ptok;
1703 		    	}
1704 
1705 			if((tmp = get_next_tok(&tok,"-"))!=NULL )
1706 			{
1707 				pptr=tmp;
1708 				n_acl->d_port_l = (u_int16_t) strtol(tmp,&pptr,0);
1709 				if(tmp==pptr)
1710 				{
1711 					syslog(LOG_ERR,"Skipping, Invalid destination port start of range found: %s\n",tmp);
1712 					free(n_acl);
1713 					return;
1714 				}
1715 				pptr=tok;
1716 				n_acl->d_port_h = (u_int16_t) strtol(tok,&pptr,0);
1717 				if(tok==pptr)
1718 				{
1719 					syslog(LOG_ERR,"Skipping, Invalid destination port end of range found: %s\n",tok);
1720 					free(n_acl);
1721 					return;
1722 				}
1723 			}else{
1724 				pptr=tok;
1725 				n_acl->d_port_l = (u_int16_t) strtol(tok,&pptr,0);
1726 				if(tok==pptr)
1727 				{
1728 					syslog(LOG_ERR,"Skipping, Invalid destination port found: %s\n",tok);
1729 					free(n_acl);
1730 					return;
1731 				}
1732 				n_acl->d_port_h=n_acl->d_port_l;
1733 			}
1734 		}
1735 
1736 		// REMAINING FIELDs - not required  - limit and timeout
1737 
1738 		while((tok = get_tok(rules,accept))!=NULL && *tok!=0 )
1739 		{
1740 			if(strcmp(tok,"rid")==0)
1741 			{
1742 				if((tmp = get_tok(rules,accept))==NULL)
1743 				{
1744 					syslog(LOG_ERR,"Format error, rid specified but none provided, using default rid %u\n",gVars.default_rid);
1745 					return;
1746 				}
1747 		    		if((tok=search_vars(tmp,gVars.var_head,VCLASS_4))!=NULL)
1748 			    	{
1749 				    bzero(ptok,256);
1750 				    strncpy(ptok,tok,sizeof(char)*strlen(tok));
1751 				    tmp=ptok;
1752 			    	}
1753 				pptr=tmp;
1754 				n_acl->rid = (u_int32_t) strtol(tmp,&pptr,0);
1755 				if(tmp==pptr)
1756 				{
1757 					syslog(LOG_ERR,"Format error, invalid rid %s, using default rid %u\n",tmp,gVars.default_rid);
1758 					// Let's restore the delimiter and put back our token
1759 					// this might be the next option
1760 					tmp[sizeof(tmp)-1]=' ';
1761 					*rules=tmp;
1762 				}
1763 				continue;
1764 			}
1765                         if(strcmp(tok,"rgid")==0)
1766                         {
1767                                 if((tmp = get_tok(rules,accept))==NULL)
1768                                 {
1769                                         syslog(LOG_ERR,"Format error, rgid specified but none provided, using default rgid %u\n",gVars.default_rgid);
1770                                         return;
1771                                 }
1772 		    		if((tok=search_vars(tmp,gVars.var_head,VCLASS_5))!=NULL)
1773 			    	{
1774 				    bzero(ptok,256);
1775 				    strncpy(ptok,tok,sizeof(char)*strlen(tok));
1776 				    tmp=ptok;
1777 			    	}
1778                                 pptr=tmp;
1779                                 n_acl->rgid = (u_int32_t) strtol(tmp,&pptr,0);
1780                                 if(tmp==pptr)
1781                                 {
1782                                         syslog(LOG_ERR,"Format error, invalid rgid %s, using default rgid %u\n",tmp,gVars.default_rgid);
1783                                         // Let's restore the delimiter and put back our token
1784                                         // this might be the next option
1785                                         tmp[sizeof(tmp)-1]=' ';
1786                                         *rules=tmp;
1787                                 }
1788                                 continue;
1789                         }
1790                         if(strcmp(tok,"zone")==0)
1791                         {
1792                                 if((tmp = get_tok(rules,accept))==NULL)
1793                                 {
1794                                         syslog(LOG_ERR,"Format error, zone specified but none provided, using default zone %d\n",gVars.default_zone);
1795                                         return;
1796                                 }
1797 		    		if((tok=search_vars(tmp,gVars.var_head,VCLASS_6))!=NULL)
1798 			    	{
1799 				    bzero(ptok,256);
1800 				    strncpy(ptok,tok,sizeof(char)*strlen(tok));
1801 				    tmp=ptok;
1802 			    	}
1803                                 pptr=tmp;
1804                                 n_acl->zone = (u_int16_t) strtol(tmp,&pptr,0);
1805                                 if(tmp==pptr)
1806                                 {
1807                                         syslog(LOG_ERR,"Format error, invalid zone %s, using default zone %d\n",tmp,gVars.default_zone);
1808                                         // Let's restore the delimiter and put back our token
1809                                         // this might be the next option
1810                                         tmp[sizeof(tmp)-1]=' ';
1811                                         *rules=tmp;
1812                                 }
1813                                 continue;
1814                         }
1815 			if(strcmp(tok,"node")==0)
1816 			{
1817 				if((tmp = get_tok(rules,accept))==NULL)
1818 				{
1819 					syslog(LOG_ERR,"Format error, node specified but none provided, using default node %d\n",gVars.default_node);
1820 					return;
1821 				}
1822 		    		if((tok=search_vars(tmp,gVars.var_head,VCLASS_7))!=NULL)
1823 			    	{
1824 				    bzero(ptok,256);
1825 				    strncpy(ptok,tok,sizeof(char)*strlen(tok));
1826 				    tmp=ptok;
1827 			    	}
1828 				pptr=tmp;
1829 				n_acl->node = (u_int16_t) strtol(tmp,&pptr,0);
1830 				if(tmp==pptr)
1831 				{
1832 					syslog(LOG_ERR,"Format error, invalid node %s, using default node %d\n",tmp,gVars.default_node);
1833 					// Let's restore the delimiter and put back our token
1834 					// this might be the next option
1835 					tmp[sizeof(tmp)-1]=' ';
1836 					*rules=tmp;
1837 				}
1838 				continue;
1839 			}
1840 			if(strcmp(tok,"status")==0)
1841 			{
1842 				if((tmp = get_tok(rules,accept))==NULL)
1843 				{
1844 					syslog(LOG_ERR,"Format error, status specified but none provided, using default status %d\n",gVars.default_status);
1845 					return;
1846 				}
1847 		    		if((tok=search_vars(tmp,gVars.var_head,VCLASS_8))!=NULL)
1848 			    	{
1849 				    bzero(ptok,256);
1850 				    strncpy(ptok,tok,sizeof(char)*strlen(tok));
1851 				    tmp=ptok;
1852 			    	}
1853 				pptr=tmp;
1854 				n_acl->status = (u_int8_t) strtol(tmp,&pptr,0);
1855 				if(tmp==pptr)
1856 				{
1857 					syslog(LOG_ERR,"Format error, invalid status %s, using default status %d\n",tmp,gVars.default_status);
1858 					// Let's restore the delimiter and put back our token
1859 					// this might be the next option
1860 					tmp[sizeof(tmp)-1]=' ';
1861 					*rules=tmp;
1862 				}
1863 				continue;
1864 			}
1865 			if(strcmp(tok,"timeout")==0)
1866 			{
1867 				if((tmp = get_tok(rules,accept))==NULL)
1868 				{
1869 					syslog(LOG_ERR,"Format error, timeout specified but none provided, using default timeout %d\n",gVars.default_timeout);
1870 					return;
1871 				}
1872 				pptr=tmp;
1873 				n_acl->timeout = (u_int16_t) strtol(tmp,&pptr,0);
1874 				if(tmp==pptr)
1875 				{
1876 					syslog(LOG_ERR,"Format error, invalid timeout %s, using default timeout\n",tmp);
1877 					// Let's restore the delimiter and put back our token
1878 					// this might be the next option
1879 					tmp[sizeof(tmp)-1]=' ';
1880 					*rules=tmp;
1881 				}
1882 				continue;
1883 			}
1884 			if(strcmp(tok,"tcplag")==0)
1885 			{
1886 			 	if((tmp = get_tok(rules,accept))==NULL)
1887 				{
1888 					syslog(LOG_ERR,"Format error, tcplag specified but none provided, using default tcplag %d\n",gVars.default_tcplag);
1889 					return;
1890 				}
1891 				pptr=tmp;
1892 				n_acl->tcplag = (u_int16_t) strtol(tmp,&pptr,0);
1893 				if(tmp==pptr)
1894 				{
1895 					syslog(LOG_ERR,"Format error, invalid tcplag %s, using default tcplag \n",tmp);
1896 
1897 					tmp[sizeof(tmp)-1]=' ';
1898 					*rules=tmp;
1899 				}
1900 				continue;
1901 			}
1902 			if(strcmp(tok,"limit")==0)
1903 			{
1904 				if((tmp = get_tok(rules,accept))==NULL)
1905 				{
1906 					syslog(LOG_ERR,"Format error, limit specified but none provided, using default limit %llu\n",(long long unsigned)gVars.default_limit);
1907 					return;
1908 				}
1909 				pptr=tmp;
1910 				n_acl->limit = (u_int64_t) strtol(tmp,&pptr,0);
1911 				if(tmp==pptr)
1912 				{
1913 					syslog(LOG_ERR,"Format error, invalid limit %s, using default limit %llu\n",tmp,(long long unsigned)gVars.default_limit);
1914 					// Let's restore the delimiter and put back our token
1915 					// this might be the next option
1916 					tmp[sizeof(tmp)-1]=' ';
1917 					*rules=tmp;
1918 				}
1919 				continue;
1920 			}
1921 			if(strcmp(tok,"realtime")==0)
1922 			{
1923 				if((tmp = get_tok(rules,accept))==NULL)
1924 				{
1925 					syslog(LOG_ERR,"Format error, realtime specified but no option provided%s\n",rule);
1926 					return;
1927 				}
1928 				if(strcmp(tmp,"log")==0) // log all matching traffic
1929 				{
1930 					n_acl->realtime = ACTION_LOG;
1931 					n_acl->rmode = OMODE_LOG;
1932 					continue;
1933 				}
1934 				if(strcmp(tmp,"pass")==0)
1935 				{
1936 					n_acl->realtime = ACTION_PASS;
1937 					n_acl->rmode = OMODE_PASS;
1938 					continue;
1939 				}
1940 				syslog(LOG_ERR,"Skipping, invalid realtime option in rule: %s %s\n",tok,tmp);
1941 				return;
1942 			}
1943 			if(strcmp(tok,"stats")==0)
1944 			{
1945 				if((tmp = get_tok(rules,accept))==NULL)
1946 				{
1947 					syslog(LOG_ERR,"Format error, stats specified but no option provided%s\n",rule);
1948 					return;
1949 				}
1950 				if(strcmp(tmp,"log")==0) // log all matching traffic
1951 				{
1952 					n_acl->stats=ACTION_LOG;
1953 					n_acl->smode=OMODE_LOG;
1954 					continue;
1955 				}
1956 				if(strcmp(tmp,"pass")==0)
1957 				{
1958 					n_acl->stats = ACTION_PASS;
1959 					n_acl->smode = OMODE_PASS;
1960 					continue;
1961 				}
1962 				syslog(LOG_ERR,"Skipping, invalid stats option in rule: %s %s\n",tok,tmp);
1963 				return;
1964 			}
1965 			if(strcmp(tok,"pcap")==0)
1966 			{
1967 				if((tmp = get_tok(rules,accept))==NULL)
1968 				{
1969 					syslog(LOG_ERR,"Format error, output specified but none provided, using default output%s\n",rule);
1970 					return;
1971 				}
1972 				if(strcmp(tmp,"log")==0) // log all matching traffic
1973 				{
1974 					if(n_acl->fH){ n_acl->fH->destroy(); n_acl->fH=0; }
1975 					n_acl->fH = gVars.pfH->attach();
1976 					n_acl->pcap = ACTION_LOG;
1977 					n_acl->pmode = OMODE_LOG;
1978 					continue;
1979 				}
1980 				if(strcmp(tmp,"pass")==0)
1981 				{
1982 					if(n_acl->fH){ n_acl->fH->destroy(); n_acl->fH=0; }
1983 					n_acl->fH = 0;
1984 					n_acl->pcap = ACTION_PASS;
1985 					n_acl->pmode = OMODE_PASS;
1986 					n_acl->cmode = CMODE_NONE;
1987 					continue;
1988 				}
1989 				if(strcmp(tmp,"rule")==0)
1990 				{
1991 					if(n_acl->fH){ n_acl->fH->destroy(); n_acl->fH=0; }
1992 					n_acl->fH = new pcapFileHandle(createPcapFileName(n_acl));
1993 					n_acl->pcap = ACTION_LOG;
1994 					n_acl->pmode=OMODE_RULE;
1995 					continue;
1996 				}
1997 				if(strcmp(tmp,"connection")==0)
1998 				{
1999 					n_acl->fH=0;
2000 					n_acl->pcap = ACTION_LOG;
2001 					n_acl->pmode=OMODE_UNIQ;
2002 					continue;
2003 				}
2004 				if(strcmp(tmp,"filename")==0)
2005 				{
2006 					if((tmp = get_tok(rules,accept))==NULL)
2007 					{
2008 						syslog(LOG_ERR,"Format error, filename specified but none provided, using default filename %s\n",rule);
2009 						return;
2010 					}else{
2011 						if(n_acl->fH){ n_acl->fH->destroy(); n_acl->fH=0; }
2012 						// Create this filename without a timestamp
2013 						ftmp=createFileName(tmp,false);
2014 						n_acl->fH = new pcapFileHandle(ftmp);
2015 						free(ftmp);
2016 						n_acl->pcap = ACTION_LOG;
2017 						n_acl->pmode=OMODE_FILENAME;
2018 					}
2019 					continue;
2020 				}
2021 				if(strcmp(tmp,"tsfilename")==0)
2022 				{
2023 					if((tmp = get_tok(rules,accept))==NULL)
2024 					{
2025 						syslog(LOG_ERR,"Format error, tsfilename specified but none provided, using default pcap output file%s\n",rule);
2026 						return;
2027 					}else{
2028 						if(n_acl->fH){ n_acl->fH->destroy(); n_acl->fH=0; }
2029 						// Create this filename with a timestamp
2030 						ftmp=createFileName(tmp,true);
2031 						n_acl->fH = new pcapFileHandle(ftmp);
2032 						free(ftmp);
2033 						n_acl->pcap = ACTION_LOG;
2034 						n_acl->pmode=OMODE_TSFILENAME;
2035 					}
2036 					continue;
2037 				}
2038 				syslog(LOG_ERR,"Skipping, invalid pcap option in rule: %s %s\n",tok,tmp);
2039 				return;
2040 			}
2041 			if(strcmp(tok,"logdst")==0)
2042 			{
2043 				n_acl->cmode = CMODE_DST;
2044 				continue;
2045 			}
2046 			if(strcmp(tok,"logsrc")==0)
2047 			{
2048 				n_acl->cmode = CMODE_SRC;
2049 				continue;
2050 			}
2051 			if(strcmp(tok,"ignore")==0)
2052 			{
2053 				// We should ignore everything for this rule
2054 				n_acl->stats=n_acl->realtime=n_acl->pcap=ACTION_PASS;
2055 				n_acl->cmode = CMODE_NONE;
2056 				n_acl->pmode = OMODE_PASS;
2057 				continue;
2058 			}
2059 			if(strcmp(tok,"retro")==0)  // Apply rule to pre-existing connections in memory
2060 			{
2061 				n_acl->retro = true;
2062 				continue;
2063 			}
2064 			syslog(LOG_ERR,"Skipping, invalid option in rule: %s %s\n", tok,*rules);
2065 			return;
2066 		}
2067 		// If we made it this far, the rule is good
2068 		// So we will add it to our list
2069 		if(tacl_head){
2070         		tacl_tail->next=n_acl;
2071 		}else{
2072 			tacl_head=n_acl;
2073 		}
2074         	tacl_tail=n_acl;
2075 		if(n_acl->retro){
2076 		#ifdef DEBUG
2077 			printf("Applying rule retro-actively!\n");
2078 		#endif
2079 			retroactive(n_acl);
2080 		}
2081 
2082 }
2083 /*
2084  *  char * get_tok (char **rule, const char *delimiters )
2085  *  Uses strpbrk to locate the first occurrance of a character in *delimiters,
2086  *  replaces this character with a null '\0', modifying **rule to point
2087  *  one byte past the delimiter character.
2088  *
2089  *  Returns pointer to beginning of token, or NULL if no delimiter is found.
2090  *
2091  */
2092 
2093 // Returns the rule you were pointing to and modifies rule
get_tok(char ** rule,const char * delimiters)2094 char * get_tok(char **rule, const char *delimiters)
2095 {
2096 	char *tok=*rule;
2097 	char *tmp=0;
2098 	int len=0;
2099 	if(*rule==NULL)
2100 		return NULL;
2101 	len=strlen(tok);
2102 
2103 	if((tmp = strpbrk(*rule,delimiters))!=NULL){
2104 		*tmp=0;
2105 		if(tmp>*rule)
2106 			*rule=++tmp;
2107 	} else {
2108 		*rule=NULL;
2109 	}
2110 	return tok;
2111 }
2112 
2113 // Returns next tok or NULL
get_next_tok(char ** rule,const char * delimiters)2114 char * get_next_tok(char **rule, const char *delimiters)
2115 {
2116 	char *tok=*rule;
2117 	char *tmp;
2118 	int len=0;
2119 	if(*rule==NULL)
2120 		return NULL;
2121 	len=strlen(tok);
2122 
2123 	if((tmp = strpbrk(*rule,delimiters))!=NULL){
2124 		*tmp='\0';
2125 		if(tmp>*rule)
2126 			*rule=++tmp;
2127 		return tok;
2128 	} else {
2129 		return NULL;
2130 	}
2131 }
2132 
print_acl(int a)2133 void print_acl(int a){
2134 	extern struct gvars gVars;
2135 	struct t_ports *tmp_port;
2136 	struct t_ports *ports_head;
2137 	char currenttime[80];
2138         time_t timestr=gVars.timeptr.tv_sec;
2139         struct acl* tmpptr;
2140 	int p, cidr,bits;
2141 	char ptok[256];
2142 	char *tmp;
2143 	u_int32_t tmpint;
2144 	char LOG[1024];
2145 	tmpptr=gVars.acl_head;
2146  	if(gVars.uselocaltime){
2147 	        strftime(currenttime,80,"%Y-%m-%d %T",(struct tm *)localtime(&timestr));
2148 	}else{
2149         	strftime(currenttime,80,"%Y-%m-%d %T GMT",(struct tm *)gmtime(&timestr));
2150 	}
2151         bzero(LOG,1024);
2152 	sprintf(LOG,"#\n#  Running configuration as of %s\n#\n",currenttime);
2153        	LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
2154 	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"}};
2155 	int unused=0;
2156 	struct vars *tvars=gVars.var_head;
2157 	for(int x=1; x<10; x++){
2158 		sprintf(LOG,"\n#\n# defined %s\n#\n",type[x]);
2159        		LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
2160 	        while(tvars!=NULL){
2161 			if(tvars->vclass==x){
2162 				sprintf(LOG,"var %s %s\n",tvars->key,tvars->value);
2163 		       		LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
2164 			}
2165 			if(tvars->vclass==0){ unused=1; }
2166 			tvars=tvars->next;
2167 		}
2168 		tvars=gVars.var_head;
2169 	}
2170 	if(unused){
2171 		sprintf(LOG,"\n#\n# %s\n#\n",type[0]);
2172       		LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
2173 	        while(tvars!=NULL){
2174 			if(tvars->vclass==0){
2175 				sprintf(LOG,"var %s %s\n",tvars->key,tvars->value);
2176 		       		LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
2177 			}
2178 			tvars=tvars->next;
2179 		}
2180 	}
2181 	sprintf(LOG,"\n#\n# define defaults\n#\n");
2182        	LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
2183 	if(gVars.rmode==OMODE_FILENAME){
2184 		sprintf(LOG,"default realtime filename %s\n",gVars.realtime_fname);
2185 	}else if(gVars.rmode==OMODE_TSFILENAME){
2186 		sprintf(LOG,"default realtime tsfilename %s\n",gVars.realtime_fname);
2187 	}else{
2188 		sprintf(LOG,"default realtime=%s\n",gVars.pmode?"log":"pass");
2189 	}
2190        	LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
2191 	if(gVars.smode==OMODE_FILENAME){
2192 		sprintf(LOG,"default stats filename %s\n",gVars.stats_fname);
2193 	}else if(gVars.smode==OMODE_TSFILENAME){
2194 		sprintf(LOG,"default stats tsfilename %s\n",gVars.stats_fname);
2195 	}else{
2196 		sprintf(LOG,"default stats=%s\n",gVars.smode?"log":"pass");
2197 	}
2198        	LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
2199 	if(gVars.pmode==OMODE_FILENAME){
2200 		sprintf(LOG,"default pcap filename %s\n",gVars.pcap_fname);
2201 	}else if(gVars.pmode==OMODE_TSFILENAME){
2202 		sprintf(LOG,"default pcap tsfilename %s\n",gVars.pcap_fname);
2203 	}else{
2204 		sprintf(LOG,"default pcap=%s\n",gVars.pmode?"log":"pass");
2205 	}
2206        	LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
2207 	if(gVars.pcap_raw){
2208 		sprintf(LOG,"default debug_pcap_raw=%s\n",gVars.pcap_raw?"enable":"disable");
2209        		LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
2210 	}
2211 	if(gVars.strip_80211){
2212 		sprintf(LOG,"default strip-80211=%s\n",gVars.strip_80211?"enable":"disable");
2213        		LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
2214 	}
2215 	sprintf(LOG,"default flush_interval=%u\n",gVars.default_flush_interval);
2216        	LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
2217 	sprintf(LOG,"default expire_interval=%u\n",gVars.default_expire_interval);
2218        	LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
2219 	sprintf(LOG,"default burst_mode=%s\n",gVars.burst_mode?"enable":"disable");
2220        	LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
2221 	sprintf(LOG,"default status=%u\n",gVars.default_status);
2222        	LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
2223 	sprintf(LOG,"default node=%u\n",gVars.default_node);
2224        	LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
2225 	sprintf(LOG,"default zone=%u\n",gVars.default_zone);
2226        	LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
2227 	sprintf(LOG,"default rid=%u\n",gVars.default_rid);
2228        	LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
2229 	sprintf(LOG,"default rgid=%u\n",gVars.default_rgid);
2230        	LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
2231 	sprintf(LOG,"default timeout=%d\n",gVars.default_timeout);
2232        	LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
2233 	sprintf(LOG,"default limit=%llu\n",(long long unsigned)gVars.default_limit);
2234        	LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
2235 	sprintf(LOG,"default tcplag=%d\n",gVars.default_tcplag);
2236        	LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
2237 	if(gVars.bpf_filter){
2238 		sprintf(LOG,"default pcapfilter \"%s\"\n",gVars.bpf_filter);
2239         	LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
2240 	}
2241 	sprintf(LOG,"\n#\n# define known_ports\n#\n");
2242        	LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
2243 	for(p=0; p<MAX_IP_PROTO; p++)
2244 	{
2245 		ports_head=gVars.ports[p];
2246 		if(ports_head!=NULL)
2247 		{
2248 			strcat(LOG,"known_ports");
2249 
2250 			bzero(ptok,256);
2251 			sprintf(ptok,"%d",p);
2252 			if((tmp=rev_search_vars(ptok,gVars.var_head,VCLASS_2))!=NULL)
2253 			{
2254 				bzero(ptok,256);
2255 				strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
2256 			}
2257 			sprintf(LOG,"%s %s ",LOG,ptok);
2258 
2259 			while(ports_head!=NULL){
2260 				tmp_port=ports_head;
2261 				ports_head=tmp_port->next;
2262 				bzero(ptok,256);
2263 				sprintf(ptok,"%d",tmp_port->l_port);
2264 				if(tmp_port->l_port!=tmp_port->h_port)
2265 					sprintf(ptok,"%s-%d",ptok,tmp_port->h_port);
2266 				if((tmp=rev_search_vars(ptok,gVars.var_head,VCLASS_3))!=NULL)
2267 				{
2268 					bzero(ptok,256);
2269 					strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
2270 				}
2271 				sprintf(LOG,"%s%s",LOG,ptok);
2272 				if(tmp_port->next)
2273 					strcat(LOG,",");
2274 			}
2275 			strcat(LOG,"\n");
2276 	        	LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
2277 		}
2278 	}
2279 	sprintf(LOG,"\n#\n#  Running rules as of %s\n#\n",currenttime);
2280        	LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
2281 	while(tmpptr!=NULL){
2282 		//
2283 		//  ETHPROTO   (VCLASS_0)
2284 		//
2285 
2286 		bzero(ptok,256);
2287 		if(tmpptr->h_proto_l==tmpptr->h_proto_h){
2288 			sprintf(ptok,"%d",tmpptr->h_proto_l);
2289 		}else{
2290 			sprintf(ptok,"%d-%d",tmpptr->h_proto_l,tmpptr->h_proto_h);
2291 		}
2292 		if((tmp=rev_search_vars(ptok,gVars.var_head,VCLASS_0))!=NULL){
2293 			bzero(ptok,256);
2294 			strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
2295 		}else if(tmpptr->h_proto_l==0 && tmpptr->h_proto_h==0xFFFF ){
2296 			bzero(ptok,256);
2297 			strncpy(ptok,"any",sizeof(char)*strlen("any"));
2298 		}
2299 		sprintf(LOG,"%s ",ptok);
2300         	LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
2301 
2302 		//
2303 		//  SOURCE IP (VCLASS_1)
2304 		//
2305 
2306 		bzero(ptok,256);
2307 		sprintf(ptok,"%s",inet_ntoa(*(struct in_addr*) &tmpptr->s_ip));
2308 		if(tmpptr->s_mask!=0xFFFFFFFF){
2309 			tmpint = htonl(tmpptr->s_mask);
2310 			cidr=bits=0;
2311 			while((tmpint&0xC0000000)!=0x40000000){
2312 				bits++;
2313 				if((tmpint&0xC0000000)!=0xC0000000){ cidr=bits; break; }
2314 				tmpint<<=1;
2315 			}
2316 			if(htonl(tmpptr->s_mask)==(u_int32_t)(0xFFFFFFFF<<(32-cidr))){
2317 			   sprintf(ptok,"%s/%d",ptok,cidr);
2318 			}else{
2319 			   sprintf(ptok,"%s/%s",ptok,inet_ntoa(*(struct in_addr*) &tmpptr->s_mask));
2320 			}
2321 		}
2322 		if((tmp=rev_search_vars(ptok,gVars.var_head,VCLASS_1))!=NULL) {
2323 			bzero(ptok,256);
2324 			strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
2325 		}else if(tmpptr->s_ip==0){
2326 			bzero(ptok,256);
2327 			strncpy(ptok,"any",sizeof(char)*strlen("any"));
2328 		}
2329 		sprintf(LOG,"%s ",ptok);
2330         	LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
2331 
2332 		//
2333 		//  DESTINATION IP (VCLASS_1)
2334 		//
2335 
2336 		bzero(ptok,256);
2337 		sprintf(ptok,"%s",inet_ntoa(*(struct in_addr*) &tmpptr->d_ip));
2338 		if(tmpptr->d_mask!=0xFFFFFFFF){
2339 			tmpint = htonl(tmpptr->d_mask);
2340 			cidr=bits=0;
2341 			while((tmpint&0xC0000000)!=0x40000000){
2342 				bits++;
2343 				if((tmpint&0xC0000000)!=0xC0000000){ cidr=bits; break; }
2344 				tmpint<<=1;
2345 			}
2346 			if(htonl(tmpptr->d_mask)==(u_int32_t)(0xFFFFFFFF<<(32-cidr))){
2347 			   sprintf(ptok,"%s/%d",ptok,cidr);
2348 			}else{
2349 			   sprintf(ptok,"%s/%s",ptok,inet_ntoa(*(struct in_addr*) &tmpptr->d_mask));
2350 			}
2351 		}
2352 		if((tmp=rev_search_vars(ptok,gVars.var_head,VCLASS_1))!=NULL) {
2353 			bzero(ptok,256);
2354 			strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
2355 		}else if(tmpptr->d_ip==0){
2356 			bzero(ptok,256);
2357 			strncpy(ptok,"any",sizeof(char)*strlen("any"));
2358 		}
2359 		sprintf(LOG,"%s ",ptok);
2360         	LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
2361 
2362 		//
2363 		//  IPPROTO (VCLASS_2)
2364 		//
2365 
2366 		bzero(ptok,256);
2367 		sprintf(ptok,"%d",tmpptr->proto_l);
2368 		if(tmpptr->proto_l!=tmpptr->proto_h){
2369 			sprintf(ptok,"%s-%d",ptok,tmpptr->proto_h);
2370 		}
2371 		if((tmp=rev_search_vars(ptok,gVars.var_head,VCLASS_2))!=NULL) {
2372 			bzero(ptok,256);
2373 			strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
2374 		}else if(tmpptr->proto_l==0x00 && tmpptr->proto_h==0xFF){
2375 			bzero(ptok,256);
2376 			strncpy(ptok,"any",sizeof(char)*strlen("any"));
2377 		}
2378 		sprintf(LOG,"%s ",ptok);
2379         	LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
2380 
2381 		//
2382 		//  Source TCP_UDP_PORT (VCLASS_3)
2383 		//
2384 
2385 		bzero(ptok,256);
2386 		sprintf(ptok,"%d",tmpptr->s_port_l);
2387                 if(tmpptr->s_port_l!=tmpptr->s_port_h){
2388 			sprintf(ptok,"%s-%d",ptok,tmpptr->s_port_h);
2389 		}
2390 		if((tmp=rev_search_vars(ptok,gVars.var_head,VCLASS_2))!=NULL) {
2391 			bzero(ptok,256);
2392 			strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
2393 		}else if(tmpptr->s_port_l==0 && tmpptr->s_port_h==0xFFFF){
2394 			bzero(ptok,256);
2395 			strncpy(ptok,"any",sizeof(char)*strlen("any"));
2396 		}
2397 		sprintf(LOG,"%s ",ptok);
2398         	LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
2399 
2400 		//
2401 		//  Destination TCP_UDP_PORT (VCLASS_3)
2402 		//
2403 
2404 		bzero(ptok,256);
2405 		sprintf(ptok,"%d",tmpptr->d_port_l);
2406                 if(tmpptr->d_port_l!=tmpptr->d_port_h){
2407 			sprintf(ptok,"%s-%d",ptok,tmpptr->d_port_h);
2408 		}
2409 		if((tmp=rev_search_vars(ptok,gVars.var_head,VCLASS_2))!=NULL) {
2410 			bzero(ptok,256);
2411 			strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
2412 		}else if(tmpptr->d_port_l==0 && tmpptr->d_port_h==0xFFFF){
2413 			bzero(ptok,256);
2414 			strncpy(ptok,"any",sizeof(char)*strlen("any"));
2415 		}
2416 		sprintf(LOG,"%s",ptok);
2417         	LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
2418 
2419 		//
2420 		//  Logging options
2421 		//
2422 
2423 		if(!tmpptr->stats && !tmpptr->realtime && !tmpptr->pcap){
2424 		// no logging options are enabled
2425 		   strcat(LOG,", ignore");
2426 		}else{
2427 		//
2428 		// Only display logging actions that differ from the default logging actions
2429 		//
2430 		//
2431 		// STATS
2432 		//
2433 		   if(tmpptr->stats!=gVars.smode){
2434    		      strcat(LOG,", stats");
2435 		      if(tmpptr->smode==OMODE_PASS)
2436 			strcat(LOG,"=pass");
2437 		      else if(tmpptr->smode==OMODE_LOG)
2438 			strcat(LOG,"=log");
2439 		   }
2440 		//
2441 		// REALTIME
2442 		//
2443 		   if(tmpptr->realtime!=gVars.rmode){
2444 		      strcat(LOG,", realtime");
2445 		      if(tmpptr->rmode==OMODE_PASS)
2446 			strcat(LOG,"=pass");
2447 		      else if(tmpptr->rmode==OMODE_LOG)
2448 			strcat(LOG,"=log");
2449 		   }
2450 		//
2451 		// PCAP
2452 		//
2453 		   if(tmpptr->pmode!=gVars.pmode){
2454 		      strcat(LOG,", pcap");
2455 		      if(tmpptr->pmode==OMODE_PASS)
2456 			strcat(LOG,"=pass");
2457 		      else if(tmpptr->pmode==OMODE_LOG)
2458 			strcat(LOG,"=log");
2459 		      else if(tmpptr->pmode==OMODE_RULE)
2460 			strcat(LOG,"=rule");
2461 		      else if(tmpptr->pmode==OMODE_UNIQ)
2462 			strcat(LOG,"=connection");
2463 		      else if(tmpptr->pmode==OMODE_FILENAME && gVars.pfH->getFileHandle()!=tmpptr->fH->getFileHandle())
2464 			sprintf(LOG,"%s filename=%s",LOG,tmpptr->fH->getFileName());
2465 		      else if(tmpptr->pmode==OMODE_TSFILENAME)
2466 			sprintf(LOG,"%s tsfilename=%s",LOG,tmpptr->fH->getFileName());
2467 		   }
2468 		 //
2469 		 // Half-stream direction collection flag
2470 		 //
2471 		   if(tmpptr->cmode==CMODE_SRC)
2472 			strcat(LOG,", logsrc");
2473 		   if(tmpptr->cmode==CMODE_DST)
2474 			strcat(LOG,", logdst");
2475 		}
2476 
2477 		//
2478 		// REMAINING OPTIONS
2479 		//
2480 
2481 		// LIMIT
2482 		if(tmpptr->limit!=gVars.default_limit)
2483 			sprintf(LOG,"%s, limit=%llu",LOG,(long long unsigned)tmpptr->limit);
2484 		// TIMEOUT
2485 		if(tmpptr->timeout!=gVars.default_timeout)
2486 			sprintf(LOG,"%s, timeout=%d",LOG,tmpptr->timeout);
2487 		// TCPLAG
2488 		if(tmpptr->tcplag!=gVars.default_tcplag)
2489 			sprintf(LOG,"%s, tcplag=%d",LOG,tmpptr->tcplag);
2490 		// RID   VCLASS_4
2491 		if(tmpptr->rid)
2492 		{
2493 			bzero(ptok,256);
2494 			sprintf(ptok,"%u",tmpptr->rid);
2495 			if((tmp=rev_search_vars(ptok,gVars.var_head,VCLASS_4))!=NULL) {
2496 				bzero(ptok,256);
2497 				strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
2498 			}
2499 			sprintf(LOG,"%s, rid=%s",LOG,ptok);
2500 		}
2501 		// RGID VCLASS_5
2502 		if(tmpptr->rgid)
2503 		{
2504 			bzero(ptok,256);
2505 			sprintf(ptok,"%u",tmpptr->rgid);
2506 			if((tmp=rev_search_vars(ptok,gVars.var_head,VCLASS_5))!=NULL) {
2507 				bzero(ptok,256);
2508 				strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
2509 			}
2510 			sprintf(LOG,"%s, rgid=%s",LOG,ptok);
2511 		}
2512 		// ZONE VCLASS_6
2513 		if(tmpptr->zone)
2514 		{
2515 			bzero(ptok,256);
2516 			sprintf(ptok,"%u",tmpptr->zone);
2517 			if((tmp=rev_search_vars(ptok,gVars.var_head,VCLASS_6))!=NULL) {
2518 				bzero(ptok,256);
2519 				strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
2520 			}
2521 			sprintf(LOG,"%s, zone=%s",LOG,ptok);
2522 		}
2523 		// NODE VCLASS_7
2524 		if(tmpptr->node)
2525 		{
2526 			bzero(ptok,256);
2527 			sprintf(ptok,"%u",tmpptr->node);
2528 			if((tmp=rev_search_vars(ptok,gVars.var_head,VCLASS_7))!=NULL) {
2529 				bzero(ptok,256);
2530 				strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
2531 			}
2532 			sprintf(LOG,"%s, node=%s",LOG,ptok);
2533 		}
2534 		// STATUS VCLASS_8
2535 		if(tmpptr->status!=gVars.default_status)
2536 		{
2537 			bzero(ptok,256);
2538 			sprintf(ptok,"%u",tmpptr->status);
2539 			if((tmp=rev_search_vars(ptok,gVars.var_head,VCLASS_8))!=NULL) {
2540 				bzero(ptok,256);
2541 				strncpy(ptok,tmp,sizeof(char)*strlen(tmp));
2542 			}
2543 			sprintf(LOG,"%s, status=%s",LOG,ptok);
2544 		}
2545 		// RETRO
2546 		if(tmpptr->retro)
2547 			strcat(LOG,", retro");
2548 
2549 		// DEFAULT RULE MATCHES
2550 		sprintf(LOG,"%s # Matches: %d\n",LOG,tmpptr->ctr);
2551 
2552 		tmpptr=tmpptr->next;
2553         	LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
2554 	}
2555 	sprintf(LOG,"# Implicit rule matches: %d\n",gVars.default_ctr);
2556         LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
2557 	if(gVars.username || gVars.groupname){
2558 		sprintf(LOG,"# Running as: %s:%s\n",gVars.username,gVars.groupname);
2559         	LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
2560 	}
2561 	if(gVars.config_file){
2562 		sprintf(LOG,"# Configuration file: %s \n",gVars.config_file?gVars.config_file:"CWD");
2563         	LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
2564 	}
2565 	if(gVars.log_directory){
2566 		sprintf(LOG,"# Output directory: %s \n",gVars.log_directory);
2567         	LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
2568 	}
2569 	if(gVars.input_filename){
2570 		sprintf(LOG,"# Reading from file: %s \n",gVars.input_filename);
2571         	LOG[1023]='\0'; gVars.sdF->write(LOG,strlen(LOG)); bzero(LOG,1024);
2572 	}
2573 
2574 }
2575 
license()2576 void license()
2577 {
2578 	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 ");
2579 }
2580 
version()2581 void version()
2582 {
2583 	fprintf(stdout,"SA Network Connection Profiler v %s\n",VERSION);
2584 }
2585 
set_bpf_filter(char * argv)2586 void set_bpf_filter(char *argv)
2587 {
2588         extern struct gvars gVars;
2589         long len;
2590 
2591 	if(gVars.bpf_fname){ free(gVars.bpf_fname); }
2592        	gVars.bpf_fname=(char *) calloc(1,strlen(argv)+1);
2593        	strncpy(gVars.bpf_fname,argv,strlen(argv));
2594 	if(gVars.bfH){ gVars.bfH->destroy(); gVars.bfH=0; }
2595 	gVars.bfH = new fileHandle(gVars.bpf_fname);
2596         gVars.bfH->setMode(READ_MODE);
2597         gVars.bfH->seek(0,SEEK_END);
2598         len=gVars.bfH->tell();
2599         if(gVars.bpf_filter){ free(gVars.bpf_filter); }
2600         if((gVars.bpf_filter = (char *) calloc(1,len+1))==NULL)
2601         {
2602 #ifdef DEBUG
2603                 syslog(LOG_CRIT,"Out of memory - bpf filter too big?\n");
2604                 return;
2605 #endif
2606         }
2607         gVars.bfH->seek(0,0);
2608         gVars.bfH->close();
2609         gVars.bfH->setMode(READ_MODE);
2610         if(gVars.bfH->read(gVars.bpf_filter,len)==-1)
2611         {
2612                 switch (errno){
2613                 case EINTR:
2614                         syslog(LOG_ERR,"Error reading bpf filter: EINTR\n");
2615                        break;
2616                 case EAGAIN:
2617                         syslog(LOG_ERR,"Error reading bpf filter: EAGAIN\n");
2618                        break;
2619                 case EIO:
2620                         syslog(LOG_ERR,"Error reading bpf filter: EIO\n");
2621                        break;
2622                 case EISDIR:
2623                         syslog(LOG_ERR,"Error reading bpf filter: EISDIR\n");
2624                        break;
2625                 case EBADF:
2626                         syslog(LOG_ERR,"Error reading bpf filter: EBADF\n");
2627                        break;
2628                 case EINVAL:
2629                         syslog(LOG_ERR,"Error reading bpf filter: EINVAL\n");
2630                        break;
2631                 case EFAULT:
2632                         syslog(LOG_ERR,"Error reading bpf filter: EFAULT\n");
2633                        break;
2634                 }
2635         }
2636         if(gVars.bpf_filter[len-1]=='\n')
2637         	gVars.bpf_filter[len-1]=0;
2638 	/* We'll get rid of bpF here - close_files()
2639 	 * is not a good place for this right now
2640 	 * cause it gets called by reload_config()
2641 	 * and that may be confusing, until we can apply
2642 	 * new bpf filters -after- start-up
2643 	 */
2644         if(gVars.bfH){
2645 	      gVars.bfH->destroy(); gVars.bfH=NULL;
2646         }
2647 
2648 }
2649