1 
2 #ifndef NCP_H
3 #include "sancp.h"
4 #endif
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 
print_schemas()19 void print_schemas(){
20     extern struct gvars gVars;
21     if(gVars.stats_fname){
22         write_schema(gVars.stats_fname, gVars.stats_fmt, gVars.stats_fmt_len);
23     }
24     if(gVars.realtime_fname){
25         write_schema(gVars.realtime_fname, gVars.realtime_fmt, gVars.realtime_fmt_len);
26     }
27 }
28 
write_schema(char * name,char * fmt,int fmtlen)29 void write_schema(char *name, char *fmt, int fmtlen){
30     if(name && fmtlen){
31         char *tmp;
32         char BUF[MAXENTRYLEN];
33         bzero(BUF,MAXENTRYLEN);
34         // Create the schema filename
35         snprintf(BUF,MAXENTRYLEN-1,"%s.schema",name);
36         tmp=createFileName(BUF,false);
37         outputFileHandle *fH = new outputFileHandle(tmp,fmt,fmtlen,WRITE_MODE);
38         bzero(BUF,MAXENTRYLEN);
39         // Print table header
40         fH->write(BUF,snprintf(BUF,MAXENTRYLEN,"\nCREATE TABLE %s ( \n",name));
41         // Print field entries in order
42         print_output_schema(fH,fmt,fmtlen);
43         bzero(BUF,MAXENTRYLEN);
44         // Print table footer
45         fH->write(BUF,snprintf(BUF,MAXENTRYLEN,") TYPE=InnoDB; \n\n"));
46         fH->destroy();
47         syslog(LOG_INFO,"Created %s\n",tmp);
48         if(tmp) free(tmp);
49     }
50 }
51 
erase_idle(int a)52 void erase_idle(int a) {
53 	extern struct gvars gVars;
54     struct cnx *cn, *tmpptr;
55     char *tmp;
56     // Since this is the only function that gets the timer alarm, we better
57     // check for expired connections (just in case we haven't processed any packets for a while)
58     if((gVars.timeptr.tv_sec - gVars.lastrun)>gVars.default_expire_interval){
59         expire_connections();
60         gVars.lastrun=gVars.timeptr.tv_sec;
61     }
62     reopen_files(2);
63     // Now check for connections to erase
64     cn=gVars.expired_cnxs.head;
65     while(cn) {
66 #ifdef DEBUG
67 		printf("Erasing key:%d id:%lld\n",cn->hash,cn->cid);
68 #endif
69 		if(cn->stats){
70 		// We really need to check whether we actually received
71 		// any bytes from the source 'first' before we record.
72 		     if(cn->reversed==CNX_REVERSED && cn->d_total_pkts==0){
73 			        cn->reversed=CNX_REREVERSED;
74 		     }
75              if(gVars.sfH) record(cn,gVars.sfH);
76 		}
77 		if(cn->fH){ cn->fH->destroy(); cn->fH=0; }
78 		tmpptr=cn;
79         cn=tmpptr->next;
80 		if(gVars.expired_cnxs.tail==tmpptr){
81             gVars.expired_cnxs.head=NULL;
82             gVars.expired_cnxs.tail=NULL;
83         }
84         tmpptr->CBufferPtr->Free();
85         tmpptr=NULL;
86 	}
87     gVars.lastrun=gVars.timeptr.tv_sec;
88     if(gVars.burst_mode){
89          // Close current stats filehandle now, and prepare the name for the next  output file
90          //  it won't actually 'open' till we try to write to the file (when we're called again
91          //  or when we exit and clear connections from memory)
92         if(gVars.sfH){
93             gVars.sfH->destroy(); gVars.sfH=NULL;
94         }
95         if(!gVars.sfH && gVars.smode){
96             tmp=createFileName(gVars.stats_fname,gVars.smode == OMODE_TSFILENAME);
97             gVars.sfH = new outputFileHandle(tmp,gVars.stats_fmt,gVars.stats_fmt_len,APPEND_MODE);
98             gVars.sfH->setFormat(gVars.stats_fmt,gVars.stats_fmt_len);
99             gVars.sfH->setEor(gVars.stats_eor);
100             gVars.sfH->setDelimiter(gVars.stats_delimiter);
101             free(tmp);
102         }
103 
104      }else{
105         // We do nothing and leave the file open
106         // We'll close the file when we terminate or receive a kill HUP signal
107 
108      }
109     // Call pthread_wait here - when we decide to use threads
110 #ifdef DEBUG
111     printf("Rearming alarm for %d secs\n",gVars.default_flush_interval);
112 #endif
113     alarm(gVars.default_flush_interval);
114 }
115 
expire_connections()116 void expire_connections()
117 {
118     extern gvars gVars;
119     struct cnx *cn, *tmpptr;
120 	int x, y;
121 	int cKey = 0;
122 #ifdef DEBUG
123     printf("Expiring connections (%d secs)\n",gVars.default_expire_interval);
124 #endif
125 	y=0;
126 	for( cKey = 0; cKey < HASH_KEYS; cKey++)
127 	{
128         cn=gVars.cnx_tail[cKey];
129 	    x=0;
130 
131        while((cn!=NULL) && ( ((gVars.timeptr.tv_sec - cn->last_pkt) > cn->timeout) || ( cn->proto==IPPROTO_TCP && (((cn->tcpCFlags & 0x33) == 0x33) || ((cn->tcpCFlags & 0x0c)>0) ) && ( (gVars.timeptr.tv_sec - cn->last_pkt) > cn->tcplag) )) ) {
132 #ifdef DEBUG
133 		printf("Erasing key:%d #:%d id:%lld\n",cKey,x,cn->cid);
134 #endif
135 
136             // Remove connection from current list
137     		tmpptr=cn;
138             if(tmpptr->prev){
139     			tmpptr->prev->next=NULL;
140               	gVars.cnx_tail[cKey]=tmpptr->prev;
141             }else{
142               	gVars.cnx_head[cKey]=NULL;
143               	gVars.cnx_tail[cKey]=NULL;
144             }
145             cn=tmpptr->prev;
146 
147             // Add expired connection to a different list to be recorded and freed from memory
148             if(!gVars.expired_cnxs.head){
149                 gVars.expired_cnxs.head=tmpptr;
150                 gVars.expired_cnxs.tail=tmpptr;
151                 tmpptr->next=tmpptr->prev=0;
152             }else{
153                 gVars.expired_cnxs.tail->next=tmpptr;
154                 gVars.expired_cnxs.tail=tmpptr;
155             }
156        }
157 
158     }
159 
160 }
161 
snprintf_inaddr_toa(char * buf,int len,struct in_addr * in_addr,const char delimiter)162 void snprintf_inaddr_toa(char *buf, int len, struct in_addr *in_addr, const char delimiter)
163 {
164     snprintf(buf,len,"%s",inet_ntoa(*in_addr));
165 }
166 
snprintf_inaddr_tohl(char * buf,int len,struct in_addr * inaddr,const char delimiter)167 void snprintf_inaddr_tohl(char *buf, int len, struct in_addr *inaddr, const char delimiter)
168 {
169     snprintf(buf,len,"%lu",(unsigned long) ntohl(*(unsigned long*)(inaddr)));
170 }
171 
snprintf_gmtime(char * buf,int len,time_t timeval,const char delimiter)172 void snprintf_gmtime(char *buf, int len, time_t timeval, const char delimiter)
173 {
174     char currenttime[80];
175     strftime(currenttime,80,"%Y-%m-%d %T",(struct tm*)gmtime(&timeval));
176     snprintf(buf,len,"%s",currenttime);
177 }
178 
snprintf_localtime(char * buf,int len,time_t timeval,const char delimiter)179 void snprintf_localtime(char *buf, int len, time_t timeval, const char delimiter)
180 {
181     char currenttime[80];
182     strftime(currenttime,80,"%Y-%m-%d %T",(struct tm*)localtime(&timeval));
183     snprintf(buf,len,"%s",currenttime);
184 }
185 
186 
record(struct cnx * cn,outputFileHandle * fH)187 void record(struct cnx *cn, outputFileHandle *fH)
188 {
189     extern struct gvars gVars;
190     char LOG[MAXENTRYLEN];
191 
192     time_t timeval=gVars.timeptr.tv_sec;
193 
194 	char *fmtcols=fH->getFormat();
195 
196 	int fmtlen=fH->getFormatLen();
197 
198 	char delimiter=fH->getDelimiter();
199 
200 	char eor=fH->getEor();
201 
202     bzero(LOG,MAXENTRYLEN);
203 
204 
205 /*
206  * Structure of a 48-bit Ethernet address.
207  *
208 struct  ether_addr {
209         u_char octet[ETHER_ADDR_LEN];
210 };
211 
212 
213 
214 
215 
216 
217 */
218 
219 	for(char x=0; x<fmtlen; x++)
220 	{
221 		switch ((int)*(fmtcols+x))
222 		{
223             case src_mac: {
224                 struct myether_addr *es=(struct myether_addr *)&cn->eth_hdr.ether_shost;
225                 snprintf(LOG,MAXENTRYLEN,"%0x:%0x:%0x:%0x:%0x:%0x",es->octet[0],es->octet[1],es->octet[2],es->octet[3],es->octet[4],es->octet[5]);
226                 es=NULL;
227                 break;
228             }
229             case dst_mac: {
230                 struct myether_addr *ed=(struct myether_addr *)&cn->eth_hdr.ether_dhost;
231                 snprintf(LOG,MAXENTRYLEN,"%0x:%0x:%0x:%0x:%0x:%0x",ed->octet[0],ed->octet[1],ed->octet[2],ed->octet[3],ed->octet[4],ed->octet[5]);
232                 ed=NULL;
233                 break;
234             }
235             case sancp_id: {
236                 snprintf(LOG,MAXENTRYLEN,"%lld",cn->cid);
237                 break;
238             }
239             case start_time_gmt: {
240                 snprintf_gmtime(LOG,MAXENTRYLEN,cn->start_time,delimiter);
241                 break;
242             }
243             case start_time_local: {
244                 snprintf_localtime(LOG,MAXENTRYLEN,cn->start_time,delimiter);
245                 break;
246             }
247             case stop_time_gmt: {
248                 snprintf_gmtime(LOG,MAXENTRYLEN,cn->last_pkt,delimiter);
249                 break;
250             }
251             case stop_time_local: {
252                 snprintf_localtime(LOG,MAXENTRYLEN,cn->last_pkt,delimiter);
253                 break;
254             }
255             case erased_time_gmt: {
256                 snprintf_gmtime(LOG,MAXENTRYLEN,timeval,delimiter);
257                 break;
258             }
259             case erased_time_local: {
260                 snprintf_localtime(LOG,MAXENTRYLEN,timeval,delimiter);
261                 break;
262             }
263             case src_ip_decimal: {
264                 if(cn->reversed==CNX_REVERSED){
265                     snprintf_inaddr_tohl(LOG,MAXENTRYLEN,(struct in_addr*) &cn->d_ip,delimiter);
266                 }else{
267                     snprintf_inaddr_tohl(LOG,MAXENTRYLEN,(struct in_addr*) &cn->s_ip,delimiter);
268                 }
269                 break;
270             }
271             case src_ip_dotted: {
272                 if(cn->reversed==CNX_REVERSED){
273                     snprintf_inaddr_toa(LOG,MAXENTRYLEN,(struct in_addr*) &cn->d_ip,delimiter);
274                 }else{
275                     snprintf_inaddr_toa(LOG,MAXENTRYLEN,(struct in_addr*) &cn->s_ip,delimiter);
276                 }
277                 break;
278             }
279             case dst_ip_decimal: {
280                 if(cn->reversed==CNX_REVERSED){
281                     snprintf_inaddr_tohl(LOG,MAXENTRYLEN,(struct in_addr*) &cn->s_ip,delimiter);
282                 }else{
283                     snprintf_inaddr_tohl(LOG,MAXENTRYLEN,(struct in_addr*) &cn->d_ip,delimiter);
284                 }
285                 break;
286             }
287             case dst_ip_dotted: {
288                 if(cn->reversed==CNX_REVERSED){
289                     snprintf_inaddr_toa(LOG,MAXENTRYLEN,(struct in_addr*) &cn->s_ip,delimiter);
290                 }else{
291                     snprintf_inaddr_toa(LOG,MAXENTRYLEN,(struct in_addr*) &cn->d_ip,delimiter);
292                 }
293                 break;
294             }
295             case eth_proto_hex: {
296                 snprintf(LOG,MAXENTRYLEN,"%02X",ntohs(cn->h_proto));
297                 break;
298             }
299             case eth_proto: {
300                 snprintf(LOG,MAXENTRYLEN,"%u",(cn->h_proto));
301                 break;
302             }
303             case ip_proto: {
304                 snprintf(LOG,MAXENTRYLEN,"%u",(cn->proto));
305                 break;
306             }
307             case src_port: {
308                 if(cn->reversed==CNX_REVERSED){
309                     snprintf(LOG,MAXENTRYLEN,"%u",ntohs(cn->d_port));
310                 }else{
311                     snprintf(LOG,MAXENTRYLEN,"%u",ntohs(cn->s_port));
312                 }
313                 break;
314             }
315             case dst_port: {
316                 if(cn->reversed==CNX_REVERSED){
317                     snprintf(LOG,MAXENTRYLEN,"%u",ntohs(cn->s_port));
318                 }else{
319                     snprintf(LOG,MAXENTRYLEN,"%u",ntohs(cn->d_port));
320                 }
321                 break;
322             }
323             case duration: {
324                 snprintf(LOG,MAXENTRYLEN,"%lu",(long)(cn->last_pkt-cn->start_time));
325                 break;
326             }
327             case timeout: {
328                 snprintf(LOG,MAXENTRYLEN,"%u",cn->timeout);
329                 break;
330             }
331             case src_pkts: {
332                 if(cn->reversed==CNX_REVERSED){
333                     snprintf(LOG,MAXENTRYLEN,"%llu",cn->d_total_pkts);
334                 }else{
335                     snprintf(LOG,MAXENTRYLEN,"%llu",cn->s_total_pkts);
336                 }
337                 break;
338             }
339             case dst_pkts: {
340                 if(cn->reversed==CNX_REVERSED){
341                     snprintf(LOG,MAXENTRYLEN,"%llu",cn->s_total_pkts);
342                 }else{
343                     snprintf(LOG,MAXENTRYLEN,"%llu",cn->d_total_pkts);
344                 }
345                 break;
346             }
347             case src_bytes: {
348                 if(cn->reversed==CNX_REVERSED){
349                     snprintf(LOG,MAXENTRYLEN,"%llu",cn->d_total_bytes);
350                 }else{
351                     snprintf(LOG,MAXENTRYLEN,"%llu",cn->s_total_bytes);
352                 }
353                 break;
354             }
355             case dst_bytes: {
356                 if(cn->reversed==CNX_REVERSED){
357                     snprintf(LOG,MAXENTRYLEN,"%llu",cn->s_total_bytes);
358                 }else{
359                     snprintf(LOG,MAXENTRYLEN,"%llu",cn->d_total_bytes);
360                 }
361                 break;
362             }
363             case sflags_hex: {
364                     snprintf(LOG,MAXENTRYLEN,"%02X",cn->tcpFlags[(cn->reversed==1?1:0)]);
365                 break;
366             }
367             case sflags: {
368                     snprintf(LOG,MAXENTRYLEN,"%u",cn->tcpFlags[(cn->reversed==1?1:0)]);
369                 break;
370             }
371             case dflags_hex: {
372                     snprintf(LOG,MAXENTRYLEN,"%02X",cn->tcpFlags[(cn->reversed==1?0:1)]);
373                 break;
374             }
375             case dflags: {
376                     snprintf(LOG,MAXENTRYLEN,"%u",cn->tcpFlags[(cn->reversed==1?0:1)]);
377                 break;
378             }
379             case cflags_hex: {
380                 snprintf(LOG,MAXENTRYLEN,"%02X",cn->reversed==1?((cn->tcpCFlags&0x15)<<1)|((cn->tcpCFlags&0x2A)>>1):cn->tcpCFlags);
381                 break;
382             }
383             case cflags: {
384                 snprintf(LOG,MAXENTRYLEN,"%u",cn->reversed==1?((cn->tcpCFlags&0x15)<<1)|((cn->tcpCFlags&0x2A)>>1):cn->tcpCFlags);
385                 break;
386             }
387             case ip_len_s: {
388                 if(cn->reversed==1){
389                     snprintf(LOG,MAXENTRYLEN,"%u",cn->os_info2.len);
390                 }else{
391                     snprintf(LOG,MAXENTRYLEN,"%u",cn->os_info.len);
392                 }
393                 break;
394             }
395             case ip_ttl_s: {
396                 if(cn->reversed==1){
397                     snprintf(LOG,MAXENTRYLEN,"%u",cn->os_info2.ttl);
398                 }else{
399                     snprintf(LOG,MAXENTRYLEN,"%u",cn->os_info.ttl);
400                 }
401                 break;
402             }
403             case ip_df_s: {
404                 if(cn->reversed==1){
405                     snprintf(LOG,MAXENTRYLEN,"%u",cn->os_info2.df?Y:N);
406                 }else{
407                     snprintf(LOG,MAXENTRYLEN,"%u",cn->os_info.df?Y:N);
408                 }
409                 break;
410             }
411             case tcp_wss_s: {
412                 if(cn->reversed==1){
413                     snprintf(LOG,MAXENTRYLEN,"%u",cn->os_info2.wss);
414                 }else{
415                     snprintf(LOG,MAXENTRYLEN,"%u",cn->os_info.wss);
416                 }
417                 break;
418             }
419 #ifdef EXPERIMENTAL_TCPOPTIONS
420             case tcp_mss_s: {
421                 if(cn->reversed==1){
422                     snprintf(LOG,MAXENTRYLEN,"%u",cn->os_info2.mss);
423                 }else{
424                     snprintf(LOG,MAXENTRYLEN,"%u",cn->os_info.mss);
425                 }
426                 break;
427             }
428             case tcp_wscale_s: {
429                 if(cn->reversed==1){
430                     snprintf(LOG,MAXENTRYLEN,"%u",cn->os_info2.wscale);
431                 }else{
432                     snprintf(LOG,MAXENTRYLEN,"%u",cn->os_info.wscale);
433                 }
434                 break;
435             }
436             case tcp_sack_ok_s: {
437                 if(cn->reversed==1){
438                     snprintf(LOG,MAXENTRYLEN,"%c",cn->os_info2.sack_ok?Y:N);
439                 }else{
440                     snprintf(LOG,MAXENTRYLEN,"%c",cn->os_info.sack_ok?Y:N);
441                 }
442                 break;
443             }
444             case tcp_nop_s: {
445                 if(cn->reversed==1){
446                     snprintf(LOG,MAXENTRYLEN,"%c",cn->os_info2.nop?Y:N);
447                 }else{
448                     snprintf(LOG,MAXENTRYLEN,"%c",cn->os_info.nop?Y:N);
449                 }
450                 break;
451             }
452 #endif
453             case ip_len_d: {
454                 if(cn->reversed==1){
455                     snprintf(LOG,MAXENTRYLEN,"%u",cn->os_info.len);
456                 }else{
457                     snprintf(LOG,MAXENTRYLEN,"%u",cn->os_info2.len);
458                 }
459                 break;
460             }
461             case ip_ttl_d: {
462                 if(cn->reversed==1){
463                     snprintf(LOG,MAXENTRYLEN,"%u",cn->os_info.ttl);
464                 }else{
465                     snprintf(LOG,MAXENTRYLEN,"%u",cn->os_info2.ttl);
466                 }
467                 break;
468             }
469             case ip_df_d: {
470                 if(cn->reversed==1){
471                     snprintf(LOG,MAXENTRYLEN,"%u",cn->os_info.df?Y:N);
472                 }else{
473                     snprintf(LOG,MAXENTRYLEN,"%u",cn->os_info2.df?Y:N);
474                 }
475                 break;
476             }
477             case tcp_wss_d: {
478                 if(cn->reversed==1){
479                     snprintf(LOG,MAXENTRYLEN,"%u",cn->os_info.wss);
480                 }else{
481                     snprintf(LOG,MAXENTRYLEN,"%u",cn->os_info2.wss);
482                 }
483                 break;
484             }
485 #ifdef EXPERIMENTAL_TCPOPTIONS
486             case tcp_mss_d: {
487                 if(cn->reversed==1){
488                     snprintf(LOG,MAXENTRYLEN,"%u",cn->os_info.mss);
489                 }else{
490                     snprintf(LOG,MAXENTRYLEN,"%u",cn->os_info2.mss);
491                 }
492                 break;
493             }
494             case tcp_wscale_d: {
495                 if(cn->reversed==1){
496                     snprintf(LOG,MAXENTRYLEN,"%u",cn->os_info.wscale);
497                 }else{
498                     snprintf(LOG,MAXENTRYLEN,"%u",cn->os_info2.wscale);
499                 }
500                 break;
501             }
502             case tcp_sack_ok_d: {
503                 if(cn->reversed==1){
504                     snprintf(LOG,MAXENTRYLEN,"%c",cn->os_info.sack_ok?Y:N);
505                 }else{
506                     snprintf(LOG,MAXENTRYLEN,"%c",cn->os_info2.sack_ok?Y:N);
507                 }
508                 break;
509             }
510             case tcp_nop_d: {
511                 if(cn->reversed==1){
512                     snprintf(LOG,MAXENTRYLEN,"%c",cn->os_info.nop?Y:N);
513                 }else{
514                     snprintf(LOG,MAXENTRYLEN,"%c",cn->os_info2.nop?Y:N);
515                 }
516                 break;
517             }
518 #endif
519             case total_bytes: {
520                     snprintf(LOG,MAXENTRYLEN,"%llu",cn->total_bytes);
521                 break;
522             }
523             case collect: {
524                     snprintf(LOG,MAXENTRYLEN,"%u",cn->cmode);
525                 break;
526             }
527             case collected: {
528                     snprintf(LOG,MAXENTRYLEN,"%llu",cn->collected);
529                 break;
530             }
531             case climit: {
532                     snprintf(LOG,MAXENTRYLEN,"%llu",cn->limit);
533                 break;
534             }
535             case tcplag: {
536                     snprintf(LOG,MAXENTRYLEN,"%u",cn->tcplag);
537                 break;
538             }
539             case pcap: {
540                     snprintf(LOG,MAXENTRYLEN,"%c",cn->pcap?Y:N);
541                 break;
542             }
543             case realtime: {
544                     snprintf(LOG,MAXENTRYLEN,"%c",cn->realtime?Y:N);
545                 break;
546             }
547             case stats: {
548                     snprintf(LOG,MAXENTRYLEN,"%c",cn->stats?Y:N);
549                 break;
550             }
551             case reversed: {
552                     snprintf(LOG,MAXENTRYLEN,"%u",cn->reversed);
553                 break;
554             }
555             case hash: {
556                     snprintf(LOG,MAXENTRYLEN,"%u",cn->hash);
557                 break;
558             }
559             case rid: {
560                     snprintf(LOG,MAXENTRYLEN,"%u",cn->rid);
561                 break;
562             }
563             case rgid: {
564                     snprintf(LOG,MAXENTRYLEN,"%u",cn->rgid);
565                 break;
566             }
567             case node: {
568                     snprintf(LOG,MAXENTRYLEN,"%u",cn->node);
569                 break;
570             }
571             case zone: {
572                     snprintf(LOG,MAXENTRYLEN,"%u",cn->zone);
573                 break;
574             }
575             case status: {
576                     snprintf(LOG,MAXENTRYLEN,"%u",cn->status);
577                 break;
578             }
579             case retro: {
580                     snprintf(LOG,MAXENTRYLEN,"%c",cn->retro?Y:N);
581                 break;
582             }
583             case sflags_1: {
584                     snprintf(LOG,MAXENTRYLEN,"%c",(cn->tcpFlags[(cn->reversed==1?1:0)]&0x80)?Y:N);
585                 break;
586             }
587             case sflags_2: {
588                     snprintf(LOG,MAXENTRYLEN,"%c",(cn->tcpFlags[(cn->reversed==1?1:0)]&0x40)?Y:N);
589                 break;
590             }
591             case sflags_U: {
592                     snprintf(LOG,MAXENTRYLEN,"%c",(cn->tcpFlags[(cn->reversed==1?1:0)]&0x20)?Y:N);
593                 break;
594             }
595             case sflags_A: {
596                     snprintf(LOG,MAXENTRYLEN,"%c",(cn->tcpFlags[(cn->reversed==1?1:0)]&0x10)?Y:N);
597                 break;
598             }
599             case sflags_P: {
600                     snprintf(LOG,MAXENTRYLEN,"%c",(cn->tcpFlags[(cn->reversed==1?1:0)]&0x08)?Y:N);
601                 break;
602             }
603             case sflags_R: {
604                     snprintf(LOG,MAXENTRYLEN,"%c",(cn->tcpFlags[(cn->reversed==1?1:0)]&0x04)?Y:N);
605                 break;
606             }
607             case sflags_S: {
608                     snprintf(LOG,MAXENTRYLEN,"%c",(cn->tcpFlags[(cn->reversed==1?1:0)]&0x02)?Y:N);
609                 break;
610             }
611             case sflags_F: {
612                     snprintf(LOG,MAXENTRYLEN,"%c",(cn->tcpFlags[(cn->reversed==1?1:0)]&0x01)?Y:N);
613                 break;
614             }
615             case dflags_1: {
616                     snprintf(LOG,MAXENTRYLEN,"%c",(cn->tcpFlags[(cn->reversed==1?0:1)]&0x80)?Y:N);
617                 break;
618             }
619             case dflags_2: {
620                     snprintf(LOG,MAXENTRYLEN,"%c",(cn->tcpFlags[(cn->reversed==1?0:1)]&0x40)?Y:N);
621                 break;
622             }
623             case dflags_U: {
624                     snprintf(LOG,MAXENTRYLEN,"%c",(cn->tcpFlags[(cn->reversed==1?0:1)]&0x20)?Y:N);
625                 break;
626             }
627             case dflags_A: {
628                     snprintf(LOG,MAXENTRYLEN,"%c",(cn->tcpFlags[(cn->reversed==1?0:1)]&0x10)?Y:N);
629                 break;
630             }
631             case dflags_P: {
632                     snprintf(LOG,MAXENTRYLEN,"%c",(cn->tcpFlags[(cn->reversed==1?0:1)]&0x08)?Y:N);
633                 break;
634             }
635             case dflags_R: {
636                     snprintf(LOG,MAXENTRYLEN,"%c",(cn->tcpFlags[(cn->reversed==1?0:1)]&0x04)?Y:N);
637                 break;
638             }
639             case dflags_S: {
640                     snprintf(LOG,MAXENTRYLEN,"%c",(cn->tcpFlags[(cn->reversed==1?0:1)]&0x02)?Y:N);
641                 break;
642             }
643             case dflags_F: {
644                     snprintf(LOG,MAXENTRYLEN,"%c",(cn->tcpFlags[(cn->reversed==1?0:1)]&0x01)?Y:N);
645                 break;
646             }
647             case cflags_DA: {
648                     snprintf(LOG,MAXENTRYLEN,"%c",(cn->tcpCFlags&(cn->reversed==1)?0x10:0x20)?Y:N);
649                 break;
650             }
651             case cflags_SA: {
652                     snprintf(LOG,MAXENTRYLEN,"%c",(cn->tcpCFlags&(cn->reversed==1)?0x20:0x10)?Y:N);
653                 break;
654             }
655             case cflags_DR: {
656                     snprintf(LOG,MAXENTRYLEN,"%c",(cn->tcpCFlags&(cn->reversed==1)?0x04:0x08)?Y:N);
657                 break;
658             }
659             case cflags_SR: {
660                     snprintf(LOG,MAXENTRYLEN,"%c",(cn->tcpCFlags&(cn->reversed==1)?0x08:0x04)?Y:N);
661                 break;
662             }
663             case cflags_DF: {
664                     snprintf(LOG,MAXENTRYLEN,"%c",(cn->tcpCFlags&(cn->reversed==1)?0x01:0x02)?Y:N);
665                 break;
666             }
667             case cflags_SF: {
668                     snprintf(LOG,MAXENTRYLEN,"%c",(cn->tcpCFlags&(cn->reversed==1)?0x02:0x01)?Y:N);
669                 break;
670             }
671 
672 	        default:
673 		        break;
674 
675         }
676         if(x>0)
677             fH->write(&delimiter,sizeof(char));
678         fH->write(LOG,strlen(LOG)); bzero(LOG,MAXENTRYLEN);
679 	}
680     fH->write(&eor,sizeof(char));
681 }
682 
683 /* vim: set ts=4 sw=4 expandtab: */
684 
685 /*
686  *  We define our DB field types here, so we can change
687  *  them easier... need config options
688  */
689 
690 #define DB_8BIT "INT1"
691 #define DB_16BIT "INT2"
692 #define DB_32BIT "INT4"
693 #define DB_64BIT "INT8"
694 #define DB_CHAR1   "CHAR(1)"
695 #define DB_CHAR4   "CHAR(4)"
696 #define DB_CHAR16  "CHAR(16)"
697 #define DB_DATETIME "datetime"
698 
print_output_schema(outputFileHandle * fH,char * fmtcols,int fmtlen)699 void print_output_schema(outputFileHandle *fH, char *fmtcols, int fmtlen)
700 {
701     char LOG[MAXENTRYLEN];
702 
703     bzero(LOG,MAXENTRYLEN);
704 
705 	for(char x=0; x<fmtlen; x++)
706 	{
707 		switch ((int)*(fmtcols+x))
708 		{
709             // Print 64 bit field
710             case sancp_id:
711                 snprintf(LOG,MAXENTRYLEN,"\tsancp_id    %s  NOT NULL,\n",DB_64BIT);
712                 break;
713             // Print Date/Time field
714             case start_time_gmt:
715                 snprintf(LOG,MAXENTRYLEN,"\tstart_time_gmt     %s NOT NULL default '0000-00-00 00:00:00',\n",DB_DATETIME);
716 		        break;
717             case start_time_local:
718                 snprintf(LOG,MAXENTRYLEN,"\tstart_time_local    %s NOT NULL default '0000-00-00 00:00:00',\n",DB_DATETIME);
719 		        break;
720             case stop_time_gmt:
721                 snprintf(LOG,MAXENTRYLEN,"\tstop_time_gmt       %s NOT NULL default '0000-00-00 00:00:00',\n",DB_DATETIME);
722 		        break;
723             case stop_time_local:
724                 snprintf(LOG,MAXENTRYLEN,"\tstop_time_local     %s NOT NULL default '0000-00-00 00:00:00',\n",DB_DATETIME);
725 		        break;
726             case erased_time_gmt:
727                 snprintf(LOG,MAXENTRYLEN,"\terased_time_gmt     %s NOT NULL default '0000-00-00 00:00:00',\n",DB_DATETIME);
728 		        break;
729             case erased_time_local:
730                 snprintf(LOG,MAXENTRYLEN,"\terased_time_gmt     %s NOT NULL default '0000-00-00 00:00:00',\n",DB_DATETIME);
731 		        break;
732             // Print 32 bit field
733             case src_ip_decimal:
734                 snprintf(LOG,MAXENTRYLEN,"\tsrc_ip      %s  NOT NULL,\n",DB_32BIT);
735 		        break;
736             case dst_ip_decimal:
737                 snprintf(LOG,MAXENTRYLEN,"\tsrc_ip      %s  NOT NULL,\n",DB_32BIT);
738 		        break;
739             case duration:
740                 snprintf(LOG,MAXENTRYLEN,"\tduration    %s  NOT NULL,\n",DB_32BIT);
741 		        break;
742             case src_pkts:
743                 snprintf(LOG,MAXENTRYLEN,"\tsrc_pkts    %s  NOT NULL,\n",DB_64BIT);
744 		        break;
745             case dst_pkts:
746                 snprintf(LOG,MAXENTRYLEN,"\tdst_pkts    %s  NOT NULL,\n",DB_64BIT);
747 		        break;
748             case src_bytes:
749                 snprintf(LOG,MAXENTRYLEN,"\tsrc_bytes   %s  NOT NULL,\n",DB_64BIT);
750 		        break;
751             case dst_bytes:
752                 snprintf(LOG,MAXENTRYLEN,"\tdst_bytes   %s  NOT NULL,\n",DB_64BIT);
753 		        break;
754             case total_bytes:
755                 snprintf(LOG,MAXENTRYLEN,"\ttotal_bytes %s  NOT NULL,\n",DB_64BIT);
756 		        break;
757             case collected:
758                 snprintf(LOG,MAXENTRYLEN,"\tcollected   %s  NOT NULL,\n",DB_64BIT);
759 		        break;
760             case climit:
761                 snprintf(LOG,MAXENTRYLEN,"\tclimit      %s  NOT NULL,\n",DB_64BIT);
762 		        break;
763             case rid:
764                 snprintf(LOG,MAXENTRYLEN,"\trid         %s  NOT NULL,\n",DB_32BIT);
765 		        break;
766             case rgid:
767                 snprintf(LOG,MAXENTRYLEN,"\trgid        %s  NOT NULL,\n",DB_32BIT);
768 		        break;
769             // Print text field
770             case src_ip_dotted:
771                 snprintf(LOG,MAXENTRYLEN,"\tsrc_ip_dotted %s  NOT NULL,\n",DB_CHAR16);
772 		        break;
773             case dst_ip_dotted:
774                 snprintf(LOG,MAXENTRYLEN,"\tdst_ip_dotted %s  NOT NULL,\n",DB_CHAR16);
775 		        break;
776             case eth_proto_hex:
777                 snprintf(LOG,MAXENTRYLEN,"\teth_proto_hex %s   NOT NULL,\n",DB_CHAR4);
778 		        break;
779             case sflags_hex:
780                 snprintf(LOG,MAXENTRYLEN,"\tsflags_hex  %s     NOT NULL,\n",DB_CHAR4);
781 		        break;
782             case dflags_hex:
783                 snprintf(LOG,MAXENTRYLEN,"\tdflags_hex  %s     NOT NULL,\n",DB_CHAR4);
784 		        break;
785             case cflags_hex:
786                 snprintf(LOG,MAXENTRYLEN,"\tcflags_hex  %s     NOT NULL,\n",DB_CHAR4);
787 		        break;
788             // Print 16bit field
789             case eth_proto:
790                 snprintf(LOG,MAXENTRYLEN,"\teth_proto   %s  NOT NULL,\n",DB_16BIT);
791 		        break;
792             case src_port:
793                 snprintf(LOG,MAXENTRYLEN,"\tsrc_port    %s  NOT NULL,\n",DB_16BIT);
794 		        break;
795             case dst_port:
796                 snprintf(LOG,MAXENTRYLEN,"\tdst_port    %s  NOT NULL,\n",DB_16BIT);
797 		        break;
798             case timeout:
799                 snprintf(LOG,MAXENTRYLEN,"\ttimeout     %s  NOT NULL,\n",DB_16BIT);
800 		        break;
801             case ip_len_s:
802                 snprintf(LOG,MAXENTRYLEN,"\tip_len_s    %s  NOT NULL,\n",DB_16BIT);
803 		        break;
804             case ip_len_d:
805                 snprintf(LOG,MAXENTRYLEN,"\tip_len_d    %s  NOT NULL,\n",DB_16BIT);
806 		        break;
807             case tcp_wss_s:
808                 snprintf(LOG,MAXENTRYLEN,"\ttcp_wss_s   %s  NOT NULL,\n",DB_16BIT);
809 		        break;
810             case tcp_wss_d:
811                 snprintf(LOG,MAXENTRYLEN,"\ttcp_wss_d   %s  NOT NULL,\n",DB_16BIT);
812 		        break;
813             case tcp_mss_s:
814                 snprintf(LOG,MAXENTRYLEN,"\ttcp_mss_s   %s  NOT NULL,\n",DB_16BIT);
815 		        break;
816             case tcp_mss_d:
817                 snprintf(LOG,MAXENTRYLEN,"\ttcp_mss_d   %s  NOT NULL,\n",DB_16BIT);
818 		        break;
819             case tcplag:
820                 snprintf(LOG,MAXENTRYLEN,"\ttcplag      %s  NOT NULL,\n",DB_16BIT);
821 		        break;
822             case hash:
823                 snprintf(LOG,MAXENTRYLEN,"\thash        %s  NOT NULL,\n",DB_16BIT);
824 		        break;
825             case node:
826                 snprintf(LOG,MAXENTRYLEN,"\tnode        %s  NOT NULL,\n",DB_16BIT);
827 		        break;
828             case zone:
829                 snprintf(LOG,MAXENTRYLEN,"\tzone        %s  NOT NULL,\n",DB_16BIT);
830 		        break;
831             // Print 8bit field
832             case ip_proto:
833                 snprintf(LOG,MAXENTRYLEN,"\tip_proto    %s  NOT NULL,\n",DB_8BIT);
834 		        break;
835             case sflags:
836                 snprintf(LOG,MAXENTRYLEN,"\tsflags      %s  NOT NULL,\n",DB_8BIT);
837 		        break;
838             case dflags:
839                 snprintf(LOG,MAXENTRYLEN,"\tdflags      %s  NOT NULL,\n",DB_8BIT);
840 		        break;
841             case cflags:
842                 snprintf(LOG,MAXENTRYLEN,"\tcflags      %s  NOT NULL,\n",DB_8BIT);
843 		        break;
844             case ip_ttl_s:
845                 snprintf(LOG,MAXENTRYLEN,"\tip_ttl_s    %s  NOT NULL,\n",DB_8BIT);
846 		        break;
847             case ip_ttl_d:
848                 snprintf(LOG,MAXENTRYLEN,"\tip_ttl_d    %s  NOT NULL,\n",DB_8BIT);
849 		        break;
850             case collect:
851                 snprintf(LOG,MAXENTRYLEN,"\tcollect     %s  NOT NULL,\n",DB_8BIT);
852 		        break;
853             case reversed:
854                 snprintf(LOG,MAXENTRYLEN,"\treversed    %s  NOT NULL,\n",DB_8BIT);
855 		        break;
856             case status:
857                 snprintf(LOG,MAXENTRYLEN,"\tstatus      %s  NOT NULL,\n",DB_8BIT);
858 		        break;
859 
860             // Print a char(1) field
861             case retro:
862                 snprintf(LOG,MAXENTRYLEN,"\tretro       %s  NOT NULL,\n",DB_CHAR1);
863 		        break;
864             case pcap:
865                 snprintf(LOG,MAXENTRYLEN,"\tpcap        %s  NOT NULL,\n",DB_CHAR1);
866 		        break;
867             case realtime:
868                 snprintf(LOG,MAXENTRYLEN,"\trealtime    %s  NOT NULL,\n",DB_CHAR1);
869 		        break;
870             case stats:
871                 snprintf(LOG,MAXENTRYLEN,"\tstats       %s  NOT NULL,\n",DB_CHAR1);
872 		        break;
873             case ip_df_s:
874                 snprintf(LOG,MAXENTRYLEN,"\tip_df_s     %s  NOT NULL,\n",DB_CHAR1);
875 		        break;
876             case tcp_wscale_s:
877                 snprintf(LOG,MAXENTRYLEN,"\ttcp_wscale_s %s  NOT NULL,\n",DB_CHAR1);
878 		        break;
879             case tcp_sack_ok_s:
880                 snprintf(LOG,MAXENTRYLEN,"\ttcp_sack_ok_s %s NOT NULL,\n",DB_CHAR1);
881 		        break;
882             case tcp_nop_s:
883                 snprintf(LOG,MAXENTRYLEN,"\ttcp_nop_s   %s  NOT NULL,\n",DB_CHAR1);
884 		        break;
885             case ip_df_d:
886                 snprintf(LOG,MAXENTRYLEN,"\tip_df_d     %s  NOT NULL,\n",DB_CHAR1);
887 		        break;
888             case tcp_wscale_d:
889                 snprintf(LOG,MAXENTRYLEN,"\ttcp_wscale_d %s  NOT NULL,\n",DB_CHAR1);
890 		        break;
891             case tcp_sack_ok_d:
892                 snprintf(LOG,MAXENTRYLEN,"\ttcp_sack_ok_d %s NOT NULL,\n",DB_CHAR1);
893 		        break;
894             case tcp_nop_d:
895                 snprintf(LOG,MAXENTRYLEN,"\ttcp_nop_d   %s  NOT NULL,\n",DB_CHAR1);
896 		        break;
897             case sflags_1:
898                 snprintf(LOG,MAXENTRYLEN,"\tsflags_1    %s  NOT NULL,\n",DB_CHAR1);
899 		        break;
900             case sflags_2:
901                 snprintf(LOG,MAXENTRYLEN,"\tsflags_2    %s  NOT NULL,\n",DB_CHAR1);
902 		        break;
903             case sflags_U:
904                 snprintf(LOG,MAXENTRYLEN,"\tsflags_U    %s  NOT NULL,\n",DB_CHAR1);
905 		        break;
906             case sflags_A:
907                 snprintf(LOG,MAXENTRYLEN,"\tsflags_A    %s  NOT NULL,\n",DB_CHAR1);
908 		        break;
909             case sflags_P:
910                 snprintf(LOG,MAXENTRYLEN,"\tsflags_P    %s  NOT NULL,\n",DB_CHAR1);
911 		        break;
912             case sflags_R:
913                 snprintf(LOG,MAXENTRYLEN,"\tsflags_R    %s  NOT NULL,\n",DB_CHAR1);
914 		        break;
915             case sflags_S:
916                 snprintf(LOG,MAXENTRYLEN,"\tsflags_S    %s  NOT NULL,\n",DB_CHAR1);
917 		        break;
918             case sflags_F:
919                 snprintf(LOG,MAXENTRYLEN,"\tsflags_F    %s  NOT NULL,\n",DB_CHAR1);
920 		        break;
921             case dflags_1:
922                 snprintf(LOG,MAXENTRYLEN,"\tdflags_1    %s  NOT NULL,\n",DB_CHAR1);
923 		        break;
924             case dflags_2:
925                 snprintf(LOG,MAXENTRYLEN,"\tdflags_2    %s  NOT NULL,\n",DB_CHAR1);
926 		        break;
927             case dflags_U:
928                 snprintf(LOG,MAXENTRYLEN,"\tdflags_U    %s  NOT NULL,\n",DB_CHAR1);
929 		        break;
930             case dflags_A:
931                 snprintf(LOG,MAXENTRYLEN,"\tdflags_A    %s  NOT NULL,\n",DB_CHAR1);
932 		        break;
933             case dflags_P:
934                 snprintf(LOG,MAXENTRYLEN,"\tdflags_P    %s  NOT NULL,\n",DB_CHAR1);
935 		        break;
936             case dflags_R:
937                 snprintf(LOG,MAXENTRYLEN,"\tdflags_R    %s  NOT NULL,\n",DB_CHAR1);
938 		        break;
939             case dflags_S:
940                 snprintf(LOG,MAXENTRYLEN,"\tdflags_S    %s  NOT NULL,\n",DB_CHAR1);
941 		        break;
942             case dflags_F:
943                 snprintf(LOG,MAXENTRYLEN,"\tdflags_F    %s  NOT NULL,\n",DB_CHAR1);
944 		        break;
945             case cflags_DA:
946                 snprintf(LOG,MAXENTRYLEN,"\tcflags_DA   %s  NOT NULL,\n",DB_CHAR1);
947 		        break;
948             case cflags_SA:
949                 snprintf(LOG,MAXENTRYLEN,"\tcflags_SA   %s  NOT NULL,\n",DB_CHAR1);
950 		        break;
951             case cflags_DR:
952                 snprintf(LOG,MAXENTRYLEN,"\tcflags_DR   %s  NOT NULL,\n",DB_CHAR1);
953 		        break;
954             case cflags_SR:
955                 snprintf(LOG,MAXENTRYLEN,"\tcflags_SR   %s  NOT NULL,\n",DB_CHAR1);
956 		        break;
957             case cflags_DF:
958                 snprintf(LOG,MAXENTRYLEN,"\tcflags_DF   %s  NOT NULL,\n",DB_CHAR1);
959 		        break;
960             case cflags_SF:
961                 snprintf(LOG,MAXENTRYLEN,"\tcflags_SF   %s  NOT NULL,\n",DB_CHAR1);
962 		        break;
963 	        default:
964 		        break;
965 
966         }
967         if(x>0)
968         fH->write(LOG,strlen(LOG)); bzero(LOG,MAXENTRYLEN);
969 	}
970     fH->write("\n",sizeof(char));
971 }
972 
973 /* vim: set ts=4 sw=4 expandtab: */
974