#pragma module RADACC "RADACC-1-X" /* **++ ** FACILITY: RADIUS-VMS, RADIUS Server for OpenVMS ** ** MODULE DESCRIPTION: ** ** This is a standalone module to producing an accounting report generated by using ** binary data stored in the RADIUS_ACCBIN file. A format of the report is a traditional ** RADIUS .DETAIL format or CSL (Comma-separated List). To copy a selected source records as is to a new file /BINARY ** option can be used. ** ** AUTHORS: ** ** Ruslan R. Laishev ** ** CREATION DATE: 22-MAR-2002 ** ** DESIGN ISSUES: ** ** {@tbs@} ** ** [@optional module tags@]... ** ** MODIFICATION HISTORY: ** ** 21-APR-2002 RRL Added /STRIP_REALM option support. ** 19-MAR-2003 RRL Fixed bug with a time range selection. ** 20-MAR-2003 RRL Added /APPEND option to append output to existen file. ** 21-MAY-2003 RRL Fixed sharing problem on output file with /APPEND option. ** 2-NOV-2003 JGJr Add RMS options for performance improvement. ** 3-OCT-2006 RRL Added Calling-Station-Id to a standart output; ** added /BINARY option; ** 13-MAR-2007 RRL Added selection with /CLID - Called Station Id ** 20-JUN-2007 RRL Changed selection with /CLID to CLID or IMSI ** 21-MAY-2008 RRL Added /FORMAT= ** 22-MAY-2008 RRL Account-Session-Time is displayed as the VMS Delta Time if ** /FORMAT=CSL ** 30-JUN-2008 RRL Added FAB$M_NQL and some error handling. ** 10-APR-2009 RRL Show Class attribute to the reduced output list ** 2-MAR-2010 RRL Added /CLNG - Calling Station Id; ** renamed CLID to CLED. ** 21-APR-2010 RRL Added /FRAMED_IP_ADDRESS ** ** {@tbs@}... **-- */ /* ** ** INCLUDE FILES ** */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define __NEW_STARLET 1 #include #include "raddef.h" #include "radius.h" int format = 0; /* Default output format is TRADITIONAL */ /* ** CLI STUFF */ extern void *RADACC_CLD; $DESCRIPTOR(p_ifile, "INPUT"); $DESCRIPTOR(q_ofile, "OUTPUT"); $DESCRIPTOR(q_before, "BEFORE"); $DESCRIPTOR(q_since, "SINCE"); $DESCRIPTOR(q_all, "ALL"); $DESCRIPTOR(q_client_ip,"CLIENT_IP_ADRESS"); $DESCRIPTOR(q_framed_ip,"FRAMED_IP_ADRESS"); $DESCRIPTOR(q_strip, "STRIP_REALM"); $DESCRIPTOR(q_append, "APPEND"); $DESCRIPTOR(q_bin, "BINARY"); $DESCRIPTOR(q_cled, "CLED"); $DESCRIPTOR(q_clng, "CLNG"); $DESCRIPTOR(q_csl, "CSL"); $DESCRIPTOR(q_trad, "TRADITIONAL"); struct realm { struct dsc$descriptor realm; struct realm *next; } *list = NULL; int tm_context = 0; $DESCRIPTOR(tm_fmt,"|!WAC !MAAC !D0|!H04:!M0:!S0 !Y4|"); /* **++ ** FUNCTIONAL DESCRIPTION: ** ** Display a list of AVP to the device is idetified by RAB. If all parameters is ** zero dumping only start and stop records. ** ** FORMAL PARAMETERS: ** ** drab: A pointer to an output stream RAB ** pair: A pointer to AV pairs with accounting info ** client: A pointer to client entry ** date: A date of record in the VMS binary format ** all: A flag to put a full set of attributes. ** ** ** RETURN VALUE: ** ** None ** **-- */ void disp_record_csl ( struct RAB * drab, AUTH_REQ *req, char *client_ip, unsigned * date, int all ) { int status,flag = 0,operation = LIB$K_DELTA_SECONDS; DICT_VALUE *dval; char buf[8192],tmpbuf[32],*cp; short buflen = 0; VALUE_PAIR *pair = req->request; struct dsc$descriptor buf_dsc; $DESCRIPTOR(fao_dsc,"!%D,Client-Id = !UB.!UB.!UB.!UB,Auth-Hdr = (Code=!UB/Id=!UB)"); $DESCRIPTOR(afao_s_dsc,",!AC = \"!AF\""); $DESCRIPTOR(afao_v_dsc,",!AC = !AC"); $DESCRIPTOR(afao_z_dsc,",!AC = !AZ"); $DESCRIPTOR(afao_i_dsc,",!AC = !UL"); $DESCRIPTOR(afao_c_dsc,",!AC = \"!#AZ\""); $DESCRIPTOR(afao_t_dsc,",!AC = !%T"); /* ** Convert a time in VMS binary format to Unix text string. */ INIT_SDESC(buf_dsc,sizeof(tmpbuf),tmpbuf); if ( !(1 & (status = lib$format_date_time (&buf_dsc,date,&tm_context,0,0))) ) lib$signal(status); INIT_SDESC(buf_dsc,sizeof(buf),buf); if ( !(1 & (status = sys$fao(&fao_dsc,&buf_dsc,&buf_dsc.dsc$w_length,date, client_ip[3],client_ip[2],client_ip[1],client_ip[0], req->code,req->id))) ) lib$signal(status); buflen = buf_dsc.dsc$w_length; /* ** Format and put into the buffer other AV pair */ for (flag = 0;pair;pair = pair->next) { /* ** If flag ALL is not set put only a reduced set of attributes */ if ( !all && pair->attr->vendor ) continue; if ( !all && !pair->attr->vendor && ((pair->attr->id != ATTR$K_USER) && (pair->attr->id != ATTR$K_FRAMED_PROTOCOL) && (pair->attr->id != ATTR$K_ACCT_INPUT) && (pair->attr->id != ATTR$K_ACCT_OUTPUT) && (pair->attr->id != ATTR$K_ACCT_DURATION) && (pair->attr->id != ATTR$K_ACCT_TERMINATE_CAUSE) && (pair->attr->id != ATTR$K_ACCT_STATUS) && (pair->attr->id != ATTR$K_ACCT_SID)) && (pair->attr->id != ATTR$K_CALLING_ID) && (pair->attr->id != ATTR$K_CLASS) && (pair->attr->id != ATTR$K_CALLED_ID) ) continue; /* ** If ALL flag is not set display only Start and Stop records */ if ( !all && !flag) { if ( !pair->attr->vendor && (pair->attr->id == ATTR$K_ACCT_STATUS) && ((pair->lvalue == VAL$K_ACCT_START) || (pair->lvalue == VAL$K_ACCT_STOP)) ) flag = 1; } INIT_SDESC(buf_dsc,sizeof(buf)-buflen,buf+buflen); switch(pair->attr->type) { case PW_TYPE_FILTER: case PW_TYPE_STRING: /* ** Striping realms */ if ( (pair->attr->id == ATTR$K_USER) && (!pair->attr->vendor) && list && (cp = memchr(pair->strvalue,'@',pair->lvalue)) ) { struct realm *rlm; struct dsc$descriptor sts; INIT_SDESC(sts,pair->lvalue - (cp+1 - pair->strvalue),cp+1); if ( !pair->strvalue[pair->lvalue-1] ) sts.dsc$w_length--; str$upcase(&sts,&sts); /* ** Run over a list of realms and matching */ for ( rlm = list;rlm;rlm = rlm->next) { if ( STR$_MATCH == (status = str$match_wild(&sts,rlm)) ) { pair->lvalue = (cp - pair->strvalue); break; } } } /* ** Special workaround for NAS(es) what send an ASCIZ string */ if ( (pair->attr->id == ATTR$K_USER) && (!pair->attr->vendor) ) status = sys$fao(&afao_c_dsc,&buf_dsc,&buf_dsc.dsc$w_length, &pair->attr->namelen,pair->lvalue,pair->strvalue); else status = sys$fao(&afao_s_dsc,&buf_dsc,&buf_dsc.dsc$w_length, &pair->attr->namelen,pair->lvalue,pair->strvalue); break; case PW_TYPE_INTEGER: if ( dval = dict_valget(pair->attr->id,pair->attr->vendor,pair->lvalue, NULL,0) ) status = sys$fao(&afao_v_dsc,&buf_dsc,&buf_dsc.dsc$w_length, &pair->attr->namelen, &dval->namelen); else if ( (pair->attr->id == ATTR$K_ACCT_DURATION) && !pair->attr->vendor ) { status = lib$cvt_to_internal_time(&operation,&pair->lvalue,&tmpbuf); status = sys$fao(&afao_t_dsc,&buf_dsc,&buf_dsc.dsc$w_length, &pair->attr->namelen,&tmpbuf); } else status = sys$fao(&afao_i_dsc,&buf_dsc,&buf_dsc.dsc$w_length, &pair->attr->namelen, pair->lvalue); break; case PW_TYPE_IPADDR: status = sys$fao(&afao_z_dsc,&buf_dsc,&buf_dsc.dsc$w_length, &pair->attr->namelen,ipaddr2str(tmpbuf, pair->lvalue)); break; case PW_TYPE_DATE: strftime(tmpbuf, sizeof(tmpbuf), "%b %e %Y", gmtime((time_t *)&pair->lvalue)); status = sys$fao(&afao_z_dsc,&buf_dsc,&buf_dsc.dsc$w_length, &pair->attr->namelen,tmpbuf); break; } if ( !(1 & status) ) lib$signal(status); buflen += buf_dsc.dsc$w_length; } /* ** Setup the RAB, write record */ drab->rab$l_rbf = buf; drab->rab$w_rsz = buflen; if ( (flag || all) && !(1 & (status = sys$put(drab))) ) lib$signal(status,drab->rab$l_stv); } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** Display a list of AVP to the device is idetified by RAB. If all parameters is ** zero dumping only start and stop records. ** ** FORMAL PARAMETERS: ** ** drab: A pointer to an output stream RAB ** pair: A pointer to AV pairs with accounting info ** client: A pointer to client entry ** date: A date of record in the VMS binary format ** all: A flag to put a full set of attributes. ** ** ** RETURN VALUE: ** ** None ** **-- */ void disp_record_trad ( struct RAB * drab, AUTH_REQ *req, char *client_ip, unsigned * date, int all ) { int status,flag = 0; DICT_VALUE *dval; char buf[8192],tmpbuf[32],*cp; short buflen = 0; VALUE_PAIR *pair = req->request; struct dsc$descriptor buf_dsc; $DESCRIPTOR(fao_dsc,"!/!AD!/\tClient-Id = !UB.!UB.!UB.!UB!/\tAuth-Hdr = (Code=!UB/Id=!UB)!/"); $DESCRIPTOR(afao_s_dsc,"\t!AC = \"!AF\"!/"); $DESCRIPTOR(afao_v_dsc,"\t!AC = !AC!/"); $DESCRIPTOR(afao_z_dsc,"\t!AC = !AZ!/"); $DESCRIPTOR(afao_i_dsc,"\t!AC = !UL!/"); $DESCRIPTOR(afao_c_dsc,"\t!AC = \"!#AZ\"!/"); /* ** Convert a time in VMS binary format to Unix text string. */ INIT_SDESC(buf_dsc,sizeof(tmpbuf),tmpbuf); if ( !(1 & (status = lib$format_date_time (&buf_dsc,date,&tm_context,0,0))) ) lib$signal(status); INIT_SDESC(buf_dsc,sizeof(buf),buf); if ( !(1 & (status = sys$fao(&fao_dsc,&buf_dsc,&buf_dsc.dsc$w_length,24,tmpbuf, client_ip[3],client_ip[2],client_ip[1],client_ip[0], req->code,req->id))) ) lib$signal(status); buflen = buf_dsc.dsc$w_length; /* ** Format and put into the buffer other AV pair */ for (flag = 0;pair;pair = pair->next) { /* ** IF flag ALL is not set put only a reduced set of attributes */ if ( !all && pair->attr->vendor ) continue; if ( !all && !pair->attr->vendor && ((pair->attr->id != ATTR$K_USER) && (pair->attr->id != ATTR$K_FRAMED_PROTOCOL) && (pair->attr->id != ATTR$K_ACCT_INPUT) && (pair->attr->id != ATTR$K_ACCT_OUTPUT) && (pair->attr->id != ATTR$K_ACCT_DURATION) && (pair->attr->id != ATTR$K_ACCT_TERMINATE_CAUSE) && (pair->attr->id != ATTR$K_ACCT_STATUS) && (pair->attr->id != ATTR$K_ACCT_SID)) && (pair->attr->id != ATTR$K_CALLING_ID) && (pair->attr->id != ATTR$K_CALLED_ID) ) continue; /* ** If ALL flag is not set display only Start and Stop records */ if ( !all && !flag) { if ( !pair->attr->vendor && (pair->attr->id == ATTR$K_ACCT_STATUS) && ((pair->lvalue == VAL$K_ACCT_START) || (pair->lvalue == VAL$K_ACCT_STOP)) ) flag = 1; } INIT_SDESC(buf_dsc,sizeof(buf)-buflen,buf+buflen); switch(pair->attr->type) { case PW_TYPE_FILTER: case PW_TYPE_STRING: /* ** Striping realms */ if ( (pair->attr->id == ATTR$K_USER) && (!pair->attr->vendor) && list && (cp = memchr(pair->strvalue,'@',pair->lvalue)) ) { struct realm *rlm; struct dsc$descriptor sts; INIT_SDESC(sts,pair->lvalue - (cp+1 - pair->strvalue),cp+1); if ( !pair->strvalue[pair->lvalue-1] ) sts.dsc$w_length--; str$upcase(&sts,&sts); /* ** Run over a list of realms and matching */ for ( rlm = list;rlm;rlm = rlm->next) { if ( STR$_MATCH == (status = str$match_wild(&sts,rlm)) ) { pair->lvalue = (cp - pair->strvalue); break; } } } /* ** Special workaround for NAS(es) what send an ASCIZ string */ if ( (pair->attr->id == ATTR$K_USER) && (!pair->attr->vendor) ) status = sys$fao(&afao_c_dsc,&buf_dsc,&buf_dsc.dsc$w_length, &pair->attr->namelen,pair->lvalue,pair->strvalue); else status = sys$fao(&afao_s_dsc,&buf_dsc,&buf_dsc.dsc$w_length, &pair->attr->namelen,pair->lvalue,pair->strvalue); break; case PW_TYPE_INTEGER: if ( dval = dict_valget(pair->attr->id,pair->attr->vendor,pair->lvalue, NULL,0) ) status = sys$fao(&afao_v_dsc,&buf_dsc,&buf_dsc.dsc$w_length, &pair->attr->namelen, &dval->namelen); else status = sys$fao(&afao_i_dsc,&buf_dsc,&buf_dsc.dsc$w_length, &pair->attr->namelen, pair->lvalue); break; case PW_TYPE_IPADDR: status = sys$fao(&afao_z_dsc,&buf_dsc,&buf_dsc.dsc$w_length, &pair->attr->namelen,ipaddr2str(tmpbuf, pair->lvalue)); break; case PW_TYPE_DATE: strftime(tmpbuf, sizeof(tmpbuf), "%b %e %Y", gmtime((time_t *)&pair->lvalue)); status = sys$fao(&afao_z_dsc,&buf_dsc,&buf_dsc.dsc$w_length, &pair->attr->namelen,tmpbuf); break; } if ( !(1 & status) ) lib$signal(status); buflen += buf_dsc.dsc$w_length; } /* ** Setup the RAB, write record */ drab->rab$l_rbf = buf; drab->rab$w_rsz = buflen; if ( (flag || all) && !(1 & (status = sys$put(drab))) ) lib$signal(status,drab->rab$l_stv); } int radacc (void) { int status,component = LIB$K_OUTPUT_FORMAT; char buf [ RAD_MAXPKTSZ + RAD_GUARDSZ ],outbuf [ 128 ], input[] = "RADIUS_ACCBIN",output [] = "SYS$OUTPUT", cled [ 32 ], clng [32]; int tm_before [2]= {0,0},tm_since[2] = {0,0},tm_junk[2],all = 0, client_ip = 0, bin =0, cledlen = 0, clnglen = 0, framed_ip = 0; RADACC_HDR *hdr = (RADACC_HDR *) buf; AUTH_HDR *ahdr = (AUTH_HDR *) &buf[sizeof(RADACC_HDR)]; VALUE_PAIR *avp; short retlen; struct FAB bfab,dfab; struct RAB brab,drab; AUTH_REQ *req; struct dsc$descriptor out_dsc,junk; /* ** Initialize a context for date/time manipulations */ if ( !(1 & (status = lib$init_date_time_context (&tm_context,&component,&tm_fmt))) ) lib$signal(status); /* ** Is there the /ALL, BINARY options ? */ all = (CLI$_PRESENT == cli$present (&q_all)); bin = (CLI$_PRESENT == cli$present (&q_bin)); /* ** /FORMAT = ? */ format = (CLI$_PRESENT == cli$present (&q_csl)); /* ** Get a /STRIP_REALM option values */ if ( CLI$_PRESENT == cli$present (&q_strip) ) { struct realm *rlm = NULL,*prev = list; while ( 1 ) { /* ** Get first/next option value */ INIT_SDESC(junk,sizeof(outbuf),outbuf); if ( !(1 & (status = cli$get_value(&q_strip,&junk,&junk.dsc$w_length))) ) break; /* ** Allocate a memory to store realm mask */ if ( !(1 & (status = lib$get_vm(&sizeof(struct realm),&rlm,0))) ) lib$signal(status); /* ** Is there a realm in quotes ? */ if ( *junk.dsc$a_pointer == '"' ) { junk.dsc$a_pointer += 1; junk.dsc$w_length -= 2; } str$upcase(&junk,&junk); /* ** Store the realm into the list */ INIT_DDESC(rlm->realm); if ( !(1 & (status = str$copy_dx(&rlm->realm,&junk))) ) lib$signal(status); /* ** */ if ( !list ) list = rlm; else prev->next = rlm; prev = rlm; } } /* ** Get a /CLED */ if ( CLI$_PRESENT == cli$present (&q_cled) ) { INIT_SDESC(junk,sizeof(cled),cled); if ( !(1 & (status = cli$get_value(&q_cled,&junk,&cledlen))) ) lib$signal(status); } /* ** Get a /CLNG */ if ( CLI$_PRESENT == cli$present (&q_clng) ) { INIT_SDESC(junk,sizeof(cled),clng); if ( !(1 & (status = cli$get_value(&q_clng,&junk,&clnglen))) ) lib$signal(status); } /* ** Get a /CLIENT_IP_ADRESS option value */ if ( CLI$_PRESENT == cli$present (&q_client_ip) ) { INIT_SDESC(junk,sizeof(outbuf),outbuf); if ( !(1 & (status = cli$get_value(&q_client_ip,&junk,&junk.dsc$w_length))) ) lib$signal(status); /* ** Skip double-quotes */ if ( *junk.dsc$a_pointer == '"' ) { junk.dsc$a_pointer++; junk.dsc$w_length -= 2; } *(junk.dsc$a_pointer + junk.dsc$w_length) = '\0'; /* ** An IP address it expected */ client_ip = ntohl(inet_addr(junk.dsc$a_pointer)); } /* ** Get a /FRAMED_IP_ADRESS option value */ if ( CLI$_PRESENT == cli$present (&q_framed_ip) ) { INIT_SDESC(junk,sizeof(outbuf),outbuf); if ( !(1 & (status = cli$get_value(&q_framed_ip,&junk,&junk.dsc$w_length))) ) lib$signal(status); /* ** Skip double-quotes */ if ( *junk.dsc$a_pointer == '"' ) { junk.dsc$a_pointer++; junk.dsc$w_length -= 2; } *(junk.dsc$a_pointer + junk.dsc$w_length) = '\0'; /* ** An IP address it expected */ framed_ip = ntohl(inet_addr(junk.dsc$a_pointer)); } /* ** Get a /SINCE and a /BEFORE options values */ if ( CLI$_PRESENT == cli$present (&q_since) ) { INIT_SDESC(junk,sizeof(outbuf),outbuf); 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(outbuf),outbuf); 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 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 | FAB$M_NQL; 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(outbuf),outbuf); 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; } /* ** The following options should improve performance: ** ** RTV: 255 opens files with cathedral windows ** MBF: Count of blocks for each buffer ** MBC: Count of buffers (works well with WBH and RAH) */ brab = cc$rms_rab; brab.rab$l_fab = &bfab; bfab.fab$b_rtv = 255; brab.rab$b_mbf = 4; brab.rab$b_mbc = 64; if ( !(1 & (status = sys$open(&bfab))) ) lib$signal(status,bfab.fab$l_stv); 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; if ( !bin ) { dfab.fab$b_rat = FAB$M_CR; dfab.fab$b_rfm = FAB$C_STMLF; } /* ** The following options should improve performance: ** ** RTV: 255 opens files with cathedral windows ** MBF: Count of blocks for each buffer ** MBC: Count of buffers (works well with WBH and RAH) */ drab = cc$rms_rab; dfab.fab$b_rtv = 255; drab.rab$b_mbf = 4; drab.rab$b_mbc = 64; if ( CLI$_PRESENT == cli$present (&q_ofile) ) { INIT_SDESC(junk,sizeof(outbuf),outbuf); 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 so set Create-If option */ 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,dfab.fab$l_stv); 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; /* ** Initialize the RADIUS dictionary */ if( !(1 & dict_init())) sys$exit (SS$_ABORT); /* ** Initalize VM zones */ if ( !(1 & rad_init_vm (2)) ) sys$exit (SS$_ABORT); /* ** Run over */ while ( 1 & (status = sys$get(&brab)) ) { /* ** 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,&hdr->datetime,tm_junk))) ) continue; if ( (tm_before [0] || tm_before [1]) ) if ( 1 & (status = lib$sub_times(&hdr->datetime,tm_before,tm_junk)) ) continue; /* ** Select by client ip */ if ( client_ip && (client_ip != hdr->client) ) continue; if ( bin ) { /* ** Setup the RAB, write record */ drab.rab$l_rbf = brab.rab$l_rbf; drab.rab$w_rsz = brab.rab$w_rsz; if ( !(1 & (status = sys$put(&drab))) ) lib$signal(status,drab.rab$l_stv); } else if ( req = radrecv (hdr->client,0,buf+sizeof(RADACC_HDR),brab.rab$w_usz-sizeof(RADACC_HDR)) ) { /* ** Select with CLED=Called-Station-Id or IMSI */ if ( cledlen ) { if ( !(avp = get_attribute(req->request,ATTR$K_CALLED_ID,0)) ) if ( !(avp = get_attribute(req->request, VSA$K__3GPP2_IMSI,RAD_VENDOR_K_3GPP2)) ) { rad_free_vm_req(req); continue; } if ( memcmp(cled,avp->strvalue,min(cledlen,avp->lvalue)) ) { rad_free_vm_req(req); continue; } } /* ** Select by FRAMED_IP_ADDRESS */ if ( framed_ip ) { if ( !(avp = get_attribute(req->request,ATTR$K_FRAMED_ADDRESS,0)) ) { rad_free_vm_req(req); continue; } if ( framed_ip != avp->lvalue ) { rad_free_vm_req(req); continue; } } /* ** Select with CLNG=Calling-Station-Id */ if ( clnglen ) { if ( !(avp = get_attribute(req->request,ATTR$K_CALLING_ID,0)) ) { rad_free_vm_req(req); continue; } if ( memcmp(clng,avp->strvalue,min(clnglen,avp->lvalue)) ) { rad_free_vm_req(req); continue; } } /* ** Dump out an accounting record */ if ( !format) disp_record_trad(&drab,req,&hdr->client,&hdr->datetime,all); else disp_record_csl(&drab,req,&hdr->client,&hdr->datetime,all); /* ** Free resources */ rad_free_vm_req(req); } } /* ** 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] = {"RADACC "}; struct dsc$descriptor cmd_dsc; opcomlvl = -1; dns_lookup = 0; debug_flag = 0; /* ** Check the presence of the comand line agruments */ INIT_SDESC(cmd_dsc,sizeof(buf)-7,buf+7); if ( !(1 & (status = lib$get_foreign(&cmd_dsc,0,&cmd_dsc.dsc$w_length,&flag))) ) return status; cmd_dsc.dsc$w_length += 7; cmd_dsc.dsc$a_pointer -= 7; if ( CLI$_NORMAL == (status = cli$dcl_parse (&cmd_dsc,&RADACC_CLD,0,0,0)) ) status = cli$dispatch(); return status; }