#pragma module NETFLOW_RPT "NETFLOW_RPT-1-A" /* **++ ** FACILITY: NetFlow Report Generator ** ** MODULE DESCRIPTION: ** ** This program is a report generator. ** ** AUTHORS: ** ** Ruslan R. Laishev ** ** CREATION DATE: 3-JUN-2003 ** ** ** MODIFICATION HISTORY: ** ** 18-JUN-2003 RRL Added selection of INPUT/OUTPUT interface with the /INTERFACE option. ** 8-AUG-2003 RRL Coded /PROTOCOL option. ** ** {@tbs@}... **-- */ /* ** ** INCLUDE FILES ** */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "netflowdef.h" #define INIT_SDESC(dsc, len, ptr) {(dsc).dsc$b_dtype = DSC$K_DTYPE_T;\ (dsc).dsc$b_class = DSC$K_CLASS_S; (dsc).dsc$w_length = (short) (len);\ (dsc).dsc$a_pointer = (ptr);} /* ** CLI STUFF */ extern void *NETFLOW_RPT_CLD; $DESCRIPTOR(p_ifile, "INPUT"); $DESCRIPTOR(q_ofile, "OUTPUT"); $DESCRIPTOR(q_before, "BEFORE"); $DESCRIPTOR(q_since, "SINCE"); $DESCRIPTOR(q_append, "APPEND"); $DESCRIPTOR(q_src_ip, "SRC_IP"); $DESCRIPTOR(q_dst_ip, "DST_IP"); $DESCRIPTOR(q_src_port, "SRC_PORT"); $DESCRIPTOR(q_dst_port, "DST_PORT"); $DESCRIPTOR(q_proto, "PROTOCOL"); $DESCRIPTOR(q_summary, "SUMMARY"); $DESCRIPTOR(q_iintf, "INTF_INP"); $DESCRIPTOR(q_ointf, "INTF_OUT"); $DESCRIPTOR(q_nexthop, "NEXTHOP"); $DESCRIPTOR(q_cont, "CONTINUOUS"); $DESCRIPTOR(q_sysip, "SYSIP"); char kwd_ip [] = {2,'I','P'}; char kwd_icmp[] = {4,'I','C','M','P'}; char kwd_igmp[] = {4,'I','G','M','P'}; char kwd_tcp[] = {3,'T','C','P'}; char kwd_udp[] = {3,'U','D','P'}; char kwd_all[] = {3,'A','L','L'}; unsigned kwd_arr [] = { 12, kwd_ip, 0, kwd_icmp, 1, kwd_igmp, 2, kwd_tcp, 6, kwd_udp, 17, kwd_all, -1}; char fname [] = "NETFLOW_DATA"; char fext [] = ".DAT"; /* **++ ** GLOBAL CONFIGURATION OPTION **-- */ unsigned tm_before[2],tm_since[2],summary; unsigned char sysip[15 + 1],src_ip[15 + 1],dst_ip[15 + 1],nexthop[15 + 1]; int iintf = -1, ointf = -1,cont = 0, proto = -1; unsigned short dst_port,src_port; __int64 inbytes,outbytes; struct FAB bfab,dfab; struct RAB brab,drab; void disp_rec ( struct RAB *drab, struct nf_recv5 *r ) { int status; struct in_addr *ina; $DESCRIPTOR(fao_dsc,"!%D !15AZ !15AZ:!5UW -> !15AZ:!5UW !12UL !3UB !3UW/!3UW !5UW->!5UW"); $DESCRIPTOR(hdr_dsc, " Date & Time Next Hop IP Source IP & Port -> Destination IP & Port Octets Pro In/Out"); $DESCRIPTOR(hdr__dsc,"----------------------- --------------- --------------- ----- --------------- ----- ------------ --- ---/---"); char buf[512]; struct dsc$descriptor buf_dsc; static flag = 0; if ( !flag ) { drab->rab$l_rbf = hdr_dsc.dsc$a_pointer; drab->rab$w_rsz = hdr_dsc.dsc$w_length; if ( !(1 & (status = sys$put(drab))) ) lib$signal(status,drab->rab$l_stv); drab->rab$l_rbf = hdr__dsc.dsc$a_pointer; drab->rab$w_rsz = hdr__dsc.dsc$w_length; if ( !(1 & (status = sys$put(drab))) ) lib$signal(status,drab->rab$l_stv); flag = 1; } INIT_SDESC(buf_dsc,sizeof(buf),buf); if ( !(1 & (status = sys$fao(&fao_dsc,&buf_dsc,&buf_dsc.dsc$w_length, &r->nf_rec$q_timestamp, r->nf_rec$t_nexthop, r->nf_rec$t_srcaddr,r->nf_rec$w_srcport, r->nf_rec$t_dstaddr,r->nf_rec$w_dstport, r->nf_rec$l_doctets,r->nf_rec$b_prot, r->nf_rec$w_input,r->nf_rec$w_output, r->nf_rec$w_src_as,r->nf_rec$w_dst_as))) ) lib$signal(status); drab->rab$l_rbf = buf_dsc.dsc$a_pointer; drab->rab$w_rsz = buf_dsc.dsc$w_length; if ( !(1 & (status = sys$put(drab))) ) lib$signal(status,drab->rab$l_stv); } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** Processing input command qalifiers and filling out program ** configuration vector. ** ** FORMAL PARAMETERS: ** ** None. ** ** RETURN VALUE: ** ** VMS Condition code ** ** **-- */ int netflow_rpt (void) { int status,tm_junk[2] = {0,0}; char buf[8192],input[] = "NETFLOW_DATA",output [] = "SYS$OUTPUT"; struct dsc$descriptor junk; struct nf_recv5 *prec = (struct nf_recv5 *) &buf; /* ** Protocol */ if ( CLI$_PRESENT == cli$present (&q_proto) ) { INIT_SDESC(junk,sizeof(buf),buf); if ( !(1 & (status = cli$get_value(&q_proto,&junk,&junk.dsc$w_length))) ) lib$signal(status); if ( !(1 & (status = LIB$LOOKUP_KEY(&junk, kwd_arr,&proto,0,0))) ) lib$signal(status,1,&junk); } cont = (CLI$_PRESENT == cli$present (&q_cont)); /* ** Time range criterias */ if ( CLI$_PRESENT == cli$present (&q_since) ) { INIT_SDESC(junk,sizeof(buf),buf); if ( !(1 & (status = cli$get_value(&q_since,&junk,&junk.dsc$w_length))) ) lib$signal(status); if ( !(1 & (status = lib$convert_date_string(&junk,tm_since))) ) lib$signal(status); } if ( CLI$_PRESENT == cli$present (&q_before) ) { INIT_SDESC(junk,sizeof(buf),buf); if ( !(1 & (status = cli$get_value(&q_before,&junk,&junk.dsc$w_length))) ) lib$signal(status); if ( !(1 & (status = lib$convert_date_string(&junk,tm_before))) ) lib$signal(status); } if ( (tm_since [0] || tm_since [1]) && (tm_before[0] || tm_before[1]) ) { if ( !(1 & (status = lib$sub_times (tm_before,tm_since,&tm_junk))) ) lib$signal(status); } /* ** Get a /SYSIP option values */ if ( CLI$_PRESENT == cli$present (&q_sysip) ) { INIT_SDESC(junk,sizeof(buf),buf); if ( !(1 & (status = cli$get_value(&q_sysip,&junk,&junk.dsc$w_length))) ) lib$signal(status); sprintf(sysip,"%15.15s",buf); } /* ** Get a /NEXTHOP option values */ if ( CLI$_PRESENT == cli$present (&q_nexthop) ) { INIT_SDESC(junk,sizeof(buf),buf); if ( !(1 & (status = cli$get_value(&q_nexthop,&junk,&junk.dsc$w_length))) ) lib$signal(status); sprintf(nexthop,"%15.15s",buf); } /* ** Get a /SRC_IP option values */ if ( CLI$_PRESENT == cli$present (&q_src_ip) ) { INIT_SDESC(junk,sizeof(buf),buf); if ( !(1 & (status = cli$get_value(&q_src_ip,&junk,&junk.dsc$w_length))) ) lib$signal(status); sprintf(src_ip,"%15.15s",buf); } /* ** Get a /DST_IP option values */ if ( CLI$_PRESENT == cli$present (&q_dst_ip) ) { INIT_SDESC(junk,sizeof(buf),buf); if ( !(1 & (status = cli$get_value(&q_dst_ip,&junk,&junk.dsc$w_length))) ) lib$signal(status); sprintf(dst_ip,"%15.15s",buf); } /* ** Get a /SRC_PORT option values */ if ( CLI$_PRESENT == cli$present (&q_src_port) ) { INIT_SDESC(junk,sizeof(buf),buf); if ( !(1 & (status = cli$get_value(&q_src_port,&junk,&junk.dsc$w_length))) ) lib$signal(status); *(junk.dsc$a_pointer + junk.dsc$w_length) = '\0'; src_port = atoi(buf); } /* ** Get a /DST_PORT option values */ if ( CLI$_PRESENT == cli$present (&q_dst_port) ) { INIT_SDESC(junk,sizeof(buf),buf); if ( !(1 & (status = cli$get_value(&q_dst_port,&junk,&junk.dsc$w_length))) ) lib$signal(status); *(junk.dsc$a_pointer + junk.dsc$w_length) = '\0'; dst_port = atoi(buf); } /* ** Get a /INTERFACE=INPUT option values */ if ( CLI$_PRESENT == cli$present (&q_iintf) ) { INIT_SDESC(junk,sizeof(buf),buf); if ( !(1 & (status = cli$get_value(&q_iintf,&junk,&junk.dsc$w_length))) ) lib$signal(status); *(junk.dsc$a_pointer + junk.dsc$w_length) = '\0'; iintf= atoi(buf); } /* ** Get a /INTERFACE=OUTPUT option values */ if ( CLI$_PRESENT == cli$present (&q_ointf) ) { INIT_SDESC(junk,sizeof(buf),buf); if ( !(1 & (status = cli$get_value(&q_ointf,&junk,&junk.dsc$w_length))) ) lib$signal(status); *(junk.dsc$a_pointer + junk.dsc$w_length) = '\0'; ointf= atoi(buf); } /* ** Get a binary accounting file name from command line, ** setup a FAB, open file, setup a RAB, connect stream. */ bfab = cc$rms_fab; bfab.fab$b_fac = FAB$M_GET; bfab.fab$b_shr = FAB$M_SHRGET | FAB$M_SHRPUT; bfab.fab$v_sqo = 1; bfab.fab$l_dna = ".DAT"; bfab.fab$b_dns = 4; if ( CLI$_PRESENT == cli$present (&p_ifile) ) { INIT_SDESC(junk,sizeof(buf),buf); if ( !(1 & (status = cli$get_value(&p_ifile,&junk,&junk.dsc$w_length))) ) lib$signal(status); bfab.fab$l_fna = junk.dsc$a_pointer; bfab.fab$b_fns = junk.dsc$w_length; } else { bfab.fab$l_fna = input; bfab.fab$b_fns = sizeof(input)-1; } if ( !(1 & (status = sys$open(&bfab))) ) lib$signal(status); brab = cc$rms_rab; brab.rab$l_fab = &bfab; brab.rab$v_nlk = brab.rab$v_rah = 1; if ( !(1 & (status = sys$connect(&brab))) ) lib$signal(status,brab.rab$l_stv); brab.rab$v_nlk = brab.rab$v_rah = 1; brab.rab$l_ubf = buf; brab.rab$w_usz = sizeof(buf); /* ** Get an output file name from command line, ** setup a FAB, open file, setup a RAB, connect stream. */ dfab = cc$rms_fab; dfab.fab$b_fac = FAB$M_PUT; dfab.fab$b_shr = FAB$M_SHRGET | FAB$M_SHRPUT; dfab.fab$v_sqo = 1; dfab.fab$l_dna = ".LIS"; dfab.fab$b_dns = 4; dfab.fab$b_rat = FAB$M_CR; dfab.fab$b_rfm = FAB$C_STMLF; if ( CLI$_PRESENT == cli$present (&q_ofile) ) { INIT_SDESC(junk,sizeof(buf),buf); if ( !(1 & (status = cli$get_value(&q_ofile,&junk,&junk.dsc$w_length))) ) lib$signal(status); dfab.fab$l_fna = junk.dsc$a_pointer; dfab.fab$b_fns = junk.dsc$w_length; /* ** IS there the /APPEND option ? If not set Create-If option then */ if ( CLI$_PRESENT == cli$present (&q_append) ) dfab.fab$v_cif = 1; } else { dfab.fab$l_fna = output; dfab.fab$b_fns = sizeof(output)-1; } drab = cc$rms_rab; drab.rab$l_fab = &dfab; drab.rab$v_wbh = drab.rab$v_eof = 1; /* ** If the was created clear eof option */ if ( !(1 & (status = sys$create(&dfab))) ) lib$signal(status); else if ( status == RMS$_CREATED ) drab.rab$v_eof = 0; if ( !(1 & (status = sys$connect(&drab))) ) lib$signal(status,drab.rab$l_stv); drab.rab$v_wbh = 1; /* ** Reading data from data file */ while ( 1 ) { if ( !(1 & (status = sys$get(&brab))) && (status != RMS$_EOF) ) break; else if ( (status == RMS$_EOF) && cont ) { sleep(5); continue; } /* ** If time intervals is set , check that gottent record hit to the time interval */ if ( (tm_since [0] || tm_since [1]) ) if ( (1 & (status = lib$sub_times(tm_since,prec->nf_rec$q_timestamp,tm_junk))) ) continue; if ( (tm_before [0] || tm_before [1]) ) if ( 1 & (status = lib$sub_times(prec->nf_rec$q_timestamp,tm_before,tm_junk)) ) continue; /* ** Select with IP Address options? */ if ( sysip[0] && (memcmp(sysip,prec->nf_rec$t_sysip,sizeof(prec->nf_rec$t_sysip))) ) continue; if ( src_ip[0] && (memcmp(src_ip,prec->nf_rec$t_srcaddr,sizeof(prec->nf_rec$t_srcaddr))) ) continue; if ( dst_ip[0] && (memcmp(dst_ip,prec->nf_rec$t_dstaddr,sizeof(prec->nf_rec$t_dstaddr))) ) continue; if ( nexthop[0] && (memcmp(nexthop,prec->nf_rec$t_nexthop,sizeof(prec->nf_rec$t_nexthop))) ) continue; /* ** Select with /PROTOCOL option ? */ if ( (proto != -1) && (proto != prec->nf_rec$b_prot) ) continue; /* ** Select with TCP/UDP port options? */ if ( src_port && (src_port != prec->nf_rec$w_srcport) ) continue; if ( dst_port && (dst_port != prec->nf_rec$w_dstport) ) continue; /* ** Select with INTERFACE index option ? */ if ( (iintf != -1) && (iintf != prec->nf_rec$w_input) ) continue; if ( (ointf != -1) && (ointf != prec->nf_rec$w_output) ) continue; disp_rec(&drab,prec); } /* ** Close all files */ sys$close(&bfab); sys$close(&dfab); if ( !(1 & status) && (status != RMS$_EOF) ) lib$signal(status,brab.rab$l_stv); return (status == RMS$_EOF)?SS$_NORMAL:status; } int main (void) { int status,flag = 0; char buf[255] = {"NETFLOW_RPT "}; struct dsc$descriptor cmd_dsc; /* ** Check the presence of the comand line agruments */ INIT_SDESC(cmd_dsc,sizeof(buf)-12,buf+12); if ( !(1 & (status = lib$get_foreign(&cmd_dsc,0,&cmd_dsc.dsc$w_length,&flag))) ) return status; cmd_dsc.dsc$w_length += 12; cmd_dsc.dsc$a_pointer -= 12; if ( CLI$_NORMAL == (status = cli$dcl_parse (&cmd_dsc,&NETFLOW_RPT_CLD,0,0,0)) ) status = cli$dispatch(); return status; }