*
***********************************************************************/
static char const RCSID[] =
-"$Id: radius.c,v 1.12 2002/07/24 20:13:12 dfs Exp $";
+"$Id: radius.c,v 1.15 2002/09/12 05:41:49 fcusack Exp $";
#include "pppd.h"
#include "chap.h"
#include <syslog.h>
#include <sys/types.h>
#include <sys/time.h>
+#include <string.h>
#define BUF_LEN 1024
static int radius_init(char *msg);
static int get_client_port(char *ifname);
static int radius_allowed_address(u_int32_t addr);
+static void radius_acct_interim(void *);
#ifdef MPPE
static int radius_setmppekeys(VALUE_PAIR *vp, REQUEST_INFO *req_info,
chap_state *);
#define MAXSESSIONID 32
#endif
+#ifndef MAXCLASSLEN
+#define MAXCLASSLEN 500
+#endif
+
struct radius_state {
int accounting_started;
int initialized;
char config_file[MAXPATHLEN];
char session_id[MAXSESSIONID + 1];
time_t start_time;
+ int acct_interim_interval;
SERVER *authserver; /* Authentication server to use */
SERVER *acctserver; /* Accounting server to use */
+ int class_len;
+ char class[MAXCLASSLEN];
};
void (*radius_attributes_hook)(VALUE_PAIR *) = NULL;
break;
case PW_OCTETS_DIRECTION:
/* Session traffic limit direction check */
- maxoctets_dir = ( vp->lvalue > 4 ) 0 : vp->lvalue ;
+ maxoctets_dir = ( vp->lvalue > 4 ) ? 0 : vp->lvalue ;
+ break;
+#endif
+ case PW_ACCT_INTERIM_INTERVAL:
+ /* Send accounting updates every few seconds */
+ rstate.acct_interim_interval = vp->lvalue;
+ /* RFC says it MUST NOT be less than 60 seconds */
+ /* We use "0" to signify not sending updates */
+ if (rstate.acct_interim_interval &&
+ rstate.acct_interim_interval < 60) {
+ rstate.acct_interim_interval = 60;
+ }
break;
-#endif
case PW_FRAMED_IP_ADDRESS:
/* seting up remote IP addresses */
remote = vp->lvalue;
rstate.ip_addr = remote;
}
break;
+ case PW_CLASS:
+ /* Save Class attribute to pass it in accounting request */
+ if (vp->lvalue <= MAXCLASSLEN) {
+ rstate.class_len=vp->lvalue;
+ memcpy(rstate.class, vp->strvalue, rstate.class_len);
+ } /* else too big for our buffer - ignore it */
+ break;
}
+
+
#ifdef CHAPMS
} else if (vp->vendorcode == VENDOR_MICROSOFT) {
switch (vp->attribute) {
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_START;
rc_avpair_add(&send, PW_ACCT_STATUS_TYPE, &av_type, 0, VENDOR_NONE);
"Accounting START failed for %s", rstate.user);
} else {
rstate.accounting_started = 1;
+ /* Kick off periodic accounting reports */
+ if (rstate.acct_interim_interval) {
+ TIMEOUT(radius_acct_interim, NULL, rstate.acct_interim_interval);
+ }
}
}
* Sends an interim accounting message to the RADIUS server
***********************************************************************/
static void
-radius_acct_interim(void)
+radius_acct_interim(void *ignored)
{
UINT4 av_type;
VALUE_PAIR *send = NULL;
"Interim accounting failed for %s", rstate.user);
}
rc_avpair_free(send);
+
+ /* Schedule another one */
+ TIMEOUT(radius_acct_interim, NULL, rstate.acct_interim_interval);
}
/**********************************************************************