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(×tr));
2148 }else{
2149 strftime(currenttime,80,"%Y-%m-%d %T GMT",(struct tm *)gmtime(×tr));
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