+/**********************************************************************
+* %FUNCTION: radius_acct_interim
+* %ARGUMENTS:
+* None
+* %RETURNS:
+* Nothing
+* %DESCRIPTION:
+* Sends an interim accounting message to the RADIUS server
+***********************************************************************/
+static void
+radius_acct_interim(void *ignored)
+{
+ UINT4 av_type;
+ VALUE_PAIR *send = NULL;
+ ipcp_options *ho = &ipcp_hisoptions[0];
+ u_int32_t hisaddr;
+ int result;
+ const char *remote_number;
+ const char *ipparam;
+ ppp_link_stats_st stats;
+
+ if (!rstate.initialized) {
+ return;
+ }
+
+ rc_avpair_add(&send, PW_ACCT_SESSION_ID, rstate.session_id,
+ 0, VENDOR_NONE);
+
+ rc_avpair_add(&send, PW_USER_NAME, rstate.user, 0, VENDOR_NONE);
+
+ if (rstate.class_len > 0)
+ rc_avpair_add(&send, PW_CLASS,
+ rstate.class, rstate.class_len, VENDOR_NONE);
+
+ av_type = PW_STATUS_ALIVE;
+ rc_avpair_add(&send, PW_ACCT_STATUS_TYPE, &av_type, 0, VENDOR_NONE);
+
+ av_type = PW_FRAMED;
+ rc_avpair_add(&send, PW_SERVICE_TYPE, &av_type, 0, VENDOR_NONE);
+
+ av_type = PW_PPP;
+ rc_avpair_add(&send, PW_FRAMED_PROTOCOL, &av_type, 0, VENDOR_NONE);
+
+ av_type = PW_RADIUS;
+ rc_avpair_add(&send, PW_ACCT_AUTHENTIC, &av_type, 0, VENDOR_NONE);
+
+ if (ppp_get_link_stats(&stats)) {
+
+ av_type = ppp_get_link_uptime();
+ rc_avpair_add(&send, PW_ACCT_SESSION_TIME, &av_type, 0, VENDOR_NONE);
+
+ av_type = stats.bytes_out & 0xFFFFFFFF;
+ rc_avpair_add(&send, PW_ACCT_OUTPUT_OCTETS, &av_type, 0, VENDOR_NONE);
+
+ if (stats.bytes_out > 0xFFFFFFFF) {
+ av_type = stats.bytes_out >> 32;
+ rc_avpair_add(&send, PW_ACCT_OUTPUT_GIGAWORDS, &av_type, 0, VENDOR_NONE);
+ }
+
+ av_type = stats.bytes_in & 0xFFFFFFFF;
+ rc_avpair_add(&send, PW_ACCT_INPUT_OCTETS, &av_type, 0, VENDOR_NONE);
+
+ if (stats.bytes_in > 0xFFFFFFFF) {
+ av_type = stats.bytes_in >> 32;
+ rc_avpair_add(&send, PW_ACCT_INPUT_GIGAWORDS, &av_type, 0, VENDOR_NONE);
+ }
+
+ av_type = stats.pkts_out;
+ rc_avpair_add(&send, PW_ACCT_OUTPUT_PACKETS, &av_type, 0, VENDOR_NONE);
+
+ av_type = stats.pkts_in;
+ rc_avpair_add(&send, PW_ACCT_INPUT_PACKETS, &av_type, 0, VENDOR_NONE);
+ }
+
+ remote_number = ppp_get_remote_number();
+ ipparam = ppp_ipparam();
+ if (remote_number) {
+ rc_avpair_add(&send, PW_CALLING_STATION_ID,
+ remote_number, 0, VENDOR_NONE);
+ } else if (ipparam)
+ rc_avpair_add(&send, PW_CALLING_STATION_ID, ipparam, 0, VENDOR_NONE);
+
+ av_type = ( ppp_using_pty() ? PW_VIRTUAL : ( ppp_sync_serial() ? PW_SYNC : PW_ASYNC ) );
+ rc_avpair_add(&send, PW_NAS_PORT_TYPE, &av_type, 0, VENDOR_NONE);
+
+ hisaddr = ho->hisaddr;
+ av_type = htonl(hisaddr);
+ rc_avpair_add(&send, PW_FRAMED_IP_ADDRESS , &av_type , 0, VENDOR_NONE);
+
+ /* Add user specified vp's */
+ if (rstate.avp)
+ rc_avpair_insert(&send, NULL, rc_avpair_copy(rstate.avp));
+
+ if (rstate.acctserver) {
+ result = rc_acct_using_server(rstate.acctserver,
+ rstate.client_port, send);
+ } else {
+ result = rc_acct(rstate.client_port, send);
+ }
+
+ if (result != OK_RC) {
+ /* RADIUS server could be down so make this a warning */
+ syslog(LOG_WARNING,
+ "Interim accounting failed for %s", rstate.user);
+ }
+ rc_avpair_free(send);
+
+ /* Schedule another one */
+ ppp_timeout(radius_acct_interim, NULL, rstate.acct_interim_interval, 0);
+}
+