diff -crN ppp-2.3.5.orig/pppd/Makefile.linux ppp-2.3.5/pppd/Makefile.linux
*** ppp-2.3.5.orig/pppd/Makefile.linux	Tue Mar 30 13:10:49 1999
--- ppp-2.3.5/pppd/Makefile.linux	Tue Mar 30 16:27:09 1999
***************
*** 24,34 ****
  include .depend
  endif
  
! # CC = gcc
  #
  COPTS = -O2 -pipe -Wall -g
  VER = 2.3.5
  LIBS =
  
  ifneq ($(wildcard /usr/lib/libcrypt.*),)
  LIBS += -lcrypt
--- 24,35 ----
  include .depend
  endif
  
! CC = gcc
  #
  COPTS = -O2 -pipe -Wall -g
  VER = 2.3.5
  LIBS =
+ # -lbsd
  
  ifneq ($(wildcard /usr/lib/libcrypt.*),)
  LIBS += -lcrypt
***************
*** 42,47 ****
--- 43,53 ----
  HAVE_CRYPT_H=y
  endif
  
+ #undef if you want RADIUS support.
+ #You also need the radclient package from
+ #<http://www.cityline.net/~lf/radius/>
+ #
+ RADIUS = 1
  
  HAS_SHADOW=y
  #USE_PAM=y
***************
*** 66,71 ****
--- 72,88 ----
  ifdef MSLANMAN
  CFLAGS   += -DMSLANMAN=1
  endif
+ endif
+ 
+ ifdef RADIUS
+ CFLAGS   += -DRADIUS -I/usr/include 
+ CFLAGS   += -D_PATH_ETC_RADIUSCLIENT_CONF=\"/etc/radiusclient/radiusclient.conf\"
+ LIBS     += -L/usr/lib -lradiusclient
+ PPPDOBJS += radius.o
+ endif
+ 
+ ifdef OPTIONS_TTY_FIRST
+ CFLAGS	 += _DOPTIONS_TTY_FIRST
  endif
  
  ifdef HAS_SHADOW
diff -crN ppp-2.3.5.orig/pppd/auth.c ppp-2.3.5/pppd/auth.c
*** ppp-2.3.5.orig/pppd/auth.c	Thu Mar 26 05:46:00 1998
--- ppp-2.3.5/pppd/auth.c	Tue Mar 30 15:26:41 1999
***************
*** 32,40 ****
   * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
   */
  
! #ifndef lint
  static char rcsid[] = "$Id: auth.c,v 1.37 1998/03/26 04:46:03 paulus Exp $";
! #endif
  
  #include <stdio.h>
  #include <stddef.h>
--- 32,40 ----
   * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
   */
  
! /*#ifndef lint
  static char rcsid[] = "$Id: auth.c,v 1.37 1998/03/26 04:46:03 paulus Exp $";
! #endif*/
  
  #include <stdio.h>
  #include <stddef.h>
***************
*** 63,70 ****
  #ifdef HAS_SHADOW
  #include <shadow.h>
  #ifndef PW_PPP
- #define PW_PPP PW_LOGIN
  #endif
  #endif
  
  #include "pppd.h"
--- 63,81 ----
  #ifdef HAS_SHADOW
  #include <shadow.h>
  #ifndef PW_PPP
  #endif
+ #define PW_PPP 1
+ #ifndef PW_LOGIN
+ #define PW_LOGIN 1
+ #endif
+ #endif
+ 
+ #ifdef RADIUS
+ #include <radiusclient.h>
+ int  radius_upap_auth __P((char *, char *, char **, int *));
+ void radius_acct_stop __P((void));
+ extern int radius_in;
+ int radius_pap_auth (char *, char *, char **, int *);
  #endif
  
  #include "pppd.h"
***************
*** 165,170 ****
--- 176,185 ----
  	return;
      if (logged_in)
  	plogout();
+ #ifdef RADIUS
+     if (radius_in)
+     radius_acct_stop();    
+ #endif
      phase = PHASE_DEAD;
      syslog(LOG_NOTICE, "Connection terminated.");
  }
***************
*** 529,536 ****
--- 544,560 ----
       * Check whether we have appropriate secrets to use
       * to authenticate the peer.
       */
+ #ifdef RADIUS
+     can_auth = wo->neg_upap && (uselogin || have_pap_secret() || useradius);
+ #else
      can_auth = wo->neg_upap && (uselogin || have_pap_secret());
+ #endif
+ 
+ #ifdef RADIUS
+     if (!can_auth && !useradius && wo->neg_chap) {
+ #else 
      if (!can_auth && wo->neg_chap) {
+ #endif
  	remote = ipwo->accept_remote? 0: ipwo->hisaddr;
  	can_auth = have_chap_secret(remote_name, our_name, remote);
      }
***************
*** 639,645 ****
--- 663,673 ----
      addrs = NULL;
      ret = UPAP_AUTHACK;
      f = fopen(filename, "r");
+ #ifdef RADIUS
+     if (f == NULL && !useradius) { 
+ #else
      if (f == NULL) {
+ #endif
  	syslog(LOG_ERR, "Can't open PAP password file %s: %m", filename);
  	ret = UPAP_AUTHNAK;
  
***************
*** 656,667 ****
  	fclose(f);
      }
  
      if (uselogin && ret == UPAP_AUTHACK) {
  	ret = plogin(user, passwd, msg, msglen);
  	if (ret == UPAP_AUTHNAK) {
  	    syslog(LOG_WARNING, "PAP login failure for %s", user);
  	}
!     }
  
      if (ret == UPAP_AUTHNAK) {
          if (*msg == (char *) 0)
--- 684,733 ----
  	fclose(f);
      }
  
+ 
      if (uselogin && ret == UPAP_AUTHACK) {
+ #ifndef RADIUS
  	ret = plogin(user, passwd, msg, msglen);
  	if (ret == UPAP_AUTHNAK) {
  	    syslog(LOG_WARNING, "PAP login failure for %s", user);
  	}
! #else
! /* Mark 1 */
!        int auth_order = rc_conf_int("auth_order");
! 
! 	  if (ret == UPAP_AUTHACK)
! 	    {
! 	      if (uselogin && useradius)
! 		{
! 		  if (auth_order & AUTH_LOCAL_FST)
! 		    {
! 		      ret = plogin(user, passwd, msg, msglen);
! 		      if ((auth_order & AUTH_RADIUS_SND) && (ret == UPAP_AUTHNAK))
! 			ret = radius_pap_auth( user, passwd, msg, msglen );
! 		    }
! 		  else if (auth_order & AUTH_RADIUS_FST)
! 		    {
! 		      ret = radius_pap_auth( user, passwd, msg, msglen );
! 		      if ((auth_order & AUTH_LOCAL_SND) && (ret == UPAP_AUTHNAK))
! 			ret = plogin(user, passwd, msg, msglen );
! 		    }
!         	}
! 	      else if (uselogin)
! 		{
! 		  ret = plogin(user, passwd, msg, msglen);
!         	}
! 	      else if (useradius)
! 		{
! 		  ret = radius_pap_auth( user, passwd, msg, msglen);
!         	}
! 	    }
! 	     
! 	  if (ret == UPAP_AUTHNAK)
! 	    {
! 	      syslog(LOG_WARNING, "PAP login failure for %s", user);
! 	    }
!      }
! #endif    
  
      if (ret == UPAP_AUTHNAK) {
          if (*msg == (char *) 0)
diff -crN ppp-2.3.5.orig/pppd/chap.c ppp-2.3.5/pppd/chap.c
*** ppp-2.3.5.orig/pppd/chap.c	Thu Nov 27 07:07:48 1997
--- ppp-2.3.5/pppd/chap.c	Tue Mar 30 15:35:51 1999
***************
*** 33,41 ****
   * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
   */
  
! #ifndef lint
  static char rcsid[] = "$Id: chap.c,v 1.15 1997/11/27 06:07:48 paulus Exp $";
! #endif
  
  /*
   * TODO:
--- 33,41 ----
   * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
   */
  
! /*#ifndef lint
  static char rcsid[] = "$Id: chap.c,v 1.15 1997/11/27 06:07:48 paulus Exp $";
! #endif*/
  
  /*
   * TODO:
***************
*** 54,59 ****
--- 54,71 ----
  #include "chap_ms.h"
  #endif
  
+ 
+ #ifdef RADIUS
+ #ifndef RADIUSCLIENT_H
+ #include <radiusclient.h>
+ #endif
+ int  radius_upap_auth __P((char *, char *, char **, int *));
+ void radius_acct_stop __P((void));
+ extern int radius_in;
+ u_char *remmd;
+ int radius_chap_auth (char *, u_char *, chap_state *);
+ #endif
+ 
  /*
   * Protocol entry points.
   */
***************
*** 100,105 ****
--- 112,118 ----
  extern double drand48 __P((void));
  extern void srand48 __P((long));
  
+ 
  /*
   * ChapInit - Initialize a CHAP unit.
   */
***************
*** 116,121 ****
--- 129,136 ----
      cstate->timeouttime = CHAP_DEFTIMEOUT;
      cstate->max_transmits = CHAP_DEFTRANSMITS;
      /* random number generator is initialized in magic_init */
+ 
+ 
  }
  
  
***************
*** 384,389 ****
--- 399,405 ----
      int id;
      int len;
  {
+     int code;
      int rchallenge_len;
      u_char *rchallenge;
      int secret_len;
***************
*** 436,442 ****
--- 452,464 ----
  	secret_len = 0;		/* assume null secret if can't find one */
  	syslog(LOG_WARNING, "No CHAP secret found for authenticating us to %s",
  	       rhostname);
+ #ifdef RADIUS
      }
+     if (radius_chap_auth(rhostname, remmd, cstate) == 0) {
+       code = CHAP_SUCCESS;
+ #else
+      } else {
+ #endif 
  
      /* cancel response send timeout if necessary */
      if (cstate->clientstate == CHAPCS_RESPONSE)
***************
*** 468,473 ****
--- 490,498 ----
  	CHAPDEBUG((LOG_INFO, "unknown digest type %d", cstate->resp_type));
  	return;
      }
+ }
+ 
+     syslog(LOG_WARNING, "@@mla@@ Before ChapSendStatus");
  
      BZERO(secret, sizeof(secret));
      ChapSendResponse(cstate);
diff -crN ppp-2.3.5.orig/pppd/chap.h ppp-2.3.5/pppd/chap.h
*** ppp-2.3.5.orig/pppd/chap.h	Wed Mar 12 05:09:10 1997
--- ppp-2.3.5/pppd/chap.h	Tue Mar 30 14:15:57 1999
***************
*** 33,38 ****
--- 33,39 ----
   * $Id: chap.h,v 1.7 1996/10/08 06:43:27 paulus Exp $
   */
  
+ 
  #ifndef __CHAP_INCLUDE__
  
  /* Code + ID + length */
diff -crN ppp-2.3.5.orig/pppd/main.c ppp-2.3.5/pppd/main.c
*** ppp-2.3.5.orig/pppd/main.c	Tue May  5 07:24:17 1998
--- ppp-2.3.5/pppd/main.c	Tue Mar 30 13:47:38 1999
***************
*** 211,224 ****
--- 211,239 ----
  
      progname = *argv;
  
+ #ifdef OPTIONS_TTY_FIRST
+     if (!options_from_file(_PATH_SYSOPTIONS, REQ_SYSOPTIONS, 0) ||
+ 	!options_for_tty() ||
+         !options_from_user() ||
+         !parse_args(argc-1, argv+1))
+ #else
      if (!options_from_file(_PATH_SYSOPTIONS, !privileged, 0, 1)
  	|| !options_from_user())
  	exit(1);
      scan_args(argc-1, argv+1);	/* look for tty name on command line */
      if (!options_for_tty()
  	|| !parse_args(argc-1, argv+1))
+ #endif
  	exit(1);
  
+ #ifdef RADIUS
+     if (radius_init()< 0)
+       {
+ 	fprintf(stderr, "Cannot initialize RADIUS\n");
+ 	exit(1);
+       }
+ #endif
+ 
      /*
       * Check that we are running as root.
       */
***************
*** 318,324 ****
--- 333,341 ----
       * Install a handler for other signals which would otherwise
       * cause pppd to exit without cleaning up.
       */
+ #ifndef RADIUS
      SIGNAL(SIGABRT, bad_signal);
+ #endif
      SIGNAL(SIGALRM, bad_signal);
      SIGNAL(SIGFPE, bad_signal);
      SIGNAL(SIGILL, bad_signal);
diff -crN ppp-2.3.5.orig/pppd/options.c ppp-2.3.5/pppd/options.c
*** ppp-2.3.5.orig/pppd/options.c	Thu Mar 26 05:46:07 1998
--- ppp-2.3.5/pppd/options.c	Tue Mar 30 13:42:03 1999
***************
*** 96,101 ****
--- 96,104 ----
  int	auth_required = 0;	/* Peer is required to authenticate */
  int	defaultroute = 0;	/* assign default route through interface */
  int	proxyarp = 0;		/* Set up proxy ARP entry for peer */
+ #ifdef RADIUS
+ int     useradius = 0;          /* Use RADIUS server checking PAP */
+ #endif
  int	persist = 0;		/* Reopen link after it goes down */
  int	uselogin = 0;		/* Use /etc/passwd for checking PAP */
  int	lcp_echo_interval = 0; 	/* Interval between LCP echo-requests */
***************
*** 191,196 ****
--- 194,202 ----
  static int setpersist __P((char **));
  static int setnopersist __P((char **));
  static int setdologin __P((char **));
+ #ifdef RADIUS
+ static int setdoradius __P((void));
+ #endif
  static int setusehostname __P((char **));
  static int setnoipdflt __P((char **));
  static int setlcptimeout __P((char **));
***************
*** 344,349 ****
--- 350,358 ----
      {"nopersist", 0, setnopersist},  /* Turn off persist option */
      {"demand", 0, setdemand},	/* Dial on demand */
      {"login", 0, setdologin},	/* Use system password database for UPAP */
+ #ifdef RADIUS
+     {"radius", 0, setdoradius},   /* Use RADIUS server for UPAP */
+ #endif
      {"noipdefault", 0, setnoipdflt}, /* Don't use name for default IP adrs */
      {"lcp-echo-failure", 1, setlcpechofails}, /* consecutive echo failures */
      {"lcp-echo-interval", 1, setlcpechointv}, /* time for lcp echo events */
***************
*** 2042,2047 ****
--- 2051,2065 ----
      uselogin = 1;
      return 1;
  }
+ 
+ 
+ #ifdef RADIUS
+ setdoradius()
+ {
+     useradius = 1;
+     return 1;
+ }
+ #endif
  
  /*
   * Functions to set the echo interval for modem-less monitors
diff -crN ppp-2.3.5.orig/pppd/pppd.h ppp-2.3.5/pppd/pppd.h
*** ppp-2.3.5.orig/pppd/pppd.h	Tue Mar 30 13:10:49 1999
--- ppp-2.3.5/pppd/pppd.h	Tue Mar 30 13:38:10 1999
***************
*** 55,60 ****
--- 55,64 ----
   * Global variables.
   */
  
+ #ifdef RADIUS
+ extern int      useradius;      /* Use RADIUS server for checking PAP */
+ #endif
+ 
  extern int	hungup;		/* Physical layer has disconnected */
  extern int	ifunit;		/* Interface unit number */
  extern char	ifname[];	/* Interface name */
diff -crN ppp-2.3.5.orig/pppd/radius.c ppp-2.3.5/pppd/radius.c
*** ppp-2.3.5.orig/pppd/radius.c	Thu Jan  1 01:00:00 1970
--- ppp-2.3.5/pppd/radius.c	Tue Mar 30 15:18:42 1999
***************
*** 0 ****
--- 1,593 ----
+ /*
+  * $Id: radius.c,v 1.1 1997/12/15 00:47:02 mla Exp $
+  *
+  * Copyright (C) 1996, Matjaz Godec <gody@elgo.si>
+  * Copyright (C) 1996, Lars Fenneberg <in5y050@public.uni-hamburg.de>
+  * Partly Copyright (C) 1997, Michael Lausch <mla@gams.at>
+  */
+ 
+ #include <syslog.h>
+ #include <time.h>
+ #include <string.h>
+ #include <unistd.h>
+ 
+ #ifdef RADIUS
+ #ifndef RADIUSCLIENT_H
+ #include <radiusclient.h>
+ #endif
+ #endif
+ 
+ #include "pppd.h"
+ #include "fsm.h"
+ #include "lcp.h"
+ #include "upap.h"
+ #include "chap.h"
+ #include "ipcp.h"
+ #include "ccp.h"
+ #include "pathnames.h"
+ 
+ extern int idle_time_limit;
+ 
+ char *ip_ntoa __P((u_int32_t));
+ int	bad_ip_adrs __P((u_int32_t));
+ 
+ int radius_in = FALSE;	
+ int session_time_limit = 0;
+ 
+ static char username[256]; 
+ static char session_id[32];	
+ static UINT4 client_port;
+ static time_t start_time;
+ static int called_radius_init = 0;
+ 
+ static void radius_acct_start __P((void));
+ 
+ int radius_init()
+ {
+   if (called_radius_init)
+     return 0;
+   if (rc_read_config (_PATH_ETC_RADIUSCLIENT_CONF) != 0)
+     return (-1);
+   
+   if (rc_read_dictionary (rc_conf_str ("dictionary")) != 0)
+     return (-1);
+   
+   if (rc_read_mapfile (rc_conf_str ("mapfile")) != 0)
+     return (-1);
+   
+   called_radius_init = 1;
+   
+   return 0;
+ }
+ 
+ int radius_setparams(vp)
+ 	VALUE_PAIR *vp;
+ {
+   ipcp_options *wo = &ipcp_wantoptions[0];
+   u_int32_t remote = 0;
+ 
+   /* 
+    * service type (if not framed then quit), 
+    * new IP address (so RADIUS can define static IP for some users),
+    * new netmask (not used at present)
+    * idle time limit 
+    * session time limit (not working at present)
+    */
+   
+   while (vp)
+     {
+       switch (vp->attribute)
+ 	{
+ 	case PW_SERVICE_TYPE:
+ 	  
+ 	  if (vp->lvalue != PW_FRAMED)
+ 	    {
+ 	      syslog (LOG_NOTICE, "RADIUS wrong service type %ld for %s", 
+ 		      vp->lvalue, username);
+ 	      return (-1);
+ 	    }
+ 	  break;
+ 	  
+ 	case PW_FRAMED_PROTOCOL:
+ 	  
+ 	  if (vp->lvalue != PW_PPP)
+ 	    {
+ 	      syslog (LOG_NOTICE, "RADIUS wrong framed protocol %ld for %s)", 
+ 		      vp->lvalue, username);
+ 	      return (-1);
+ 	    }
+ 	  break;
+ 	  
+ 	case PW_FRAMED_IP_ADDRESS:
+ 	  
+ 	  /* 0xfffffffe means NAS should select an ip address       */
+ 	  /* 0xffffffff means user should be allowed to select one  */
+ 	  /* the last case probably needs special handling ???      */
+ 	  if ((remote != 0xfffffffe) && (remote != 0xffffffff))
+ 	    {
+ 	      remote = htonl(vp->lvalue);
+ 	      if (bad_ip_adrs (remote))
+ 		{
+ 		  syslog (LOG_ERR, "RADIUS bad remote IP address %s for %s", 
+ 			  ip_ntoa (remote), username);
+ 		  return (-1);
+ 		}	
+ 					
+ 	      wo->hisaddr = remote;
+ 	    }
+ 	  break;
+ 	  
+ 	case PW_FRAMED_IP_NETMASK:
+ 	  
+ 	  netmask = htonl (vp->lvalue);
+ 	  break;
+ 	  
+ 	case PW_FRAMED_MTU:
+ 	  
+ 	  lcp_allowoptions[0].mru = vp->lvalue;
+ 	  break;
+ 	  
+ 	case PW_IDLE_TIMEOUT:
+ 	  
+ 	  idle_time_limit = vp->lvalue;
+ 	  break;
+ 	  
+ 	  /* doesn't work at the moment */
+ 	case PW_SESSION_TIMEOUT:
+ 	  
+ 	  session_time_limit = vp->lvalue;
+ 	  break;
+ 	}
+       
+       vp = vp->next;
+       
+     }
+   syslog(LOG_WARNING, "@@mla@@: radius_setparam left");
+   return 0;
+ }
+ 
+ /*
+  * rad_pap_auth - Check the user name and password against RADIUS server, 
+  * 				  and add accounting start record of the user if OK.
+  *
+  * Returns:
+  *
+  *		UPAP_AUTHNAK: Login failed.
+  *		UPAP_AUTHACK: Login succeeded.
+  *
+  *		In either case, msg points to an appropriate message.
+  *
+  */
+ 
+ int
+ radius_pap_auth (user, passwd, msg, msglen)
+      char *user;
+      char *passwd;
+      char **msg;
+      int *msglen;
+ {
+ 	VALUE_PAIR *send, *received;
+ 	UINT4 av_type;
+ 	char username_realm[256]; 
+ 	static char radius_msg[4096];
+ 	int result;
+   	char *default_realm;
+ 
+ 
+ 	send = NULL;
+ 
+ 	/* read in the config files if neccessary */
+ 	if(!called_radius_init && (radius_init() < 0))
+ 		return (UPAP_AUTHNAK);
+ 
+ 	/*  
+ 	 *  then we define and map tty to port
+ 	 */
+   	
+   	client_port = rc_map2id (devnam);
+ 
+ 	/*
+  	 * now we define service type and framed protocol
+  	 */
+ 
+     av_type = PW_FRAMED;
+   	rc_avpair_add (&send, PW_SERVICE_TYPE, &av_type, 0);
+ 
+   	av_type = PW_PPP;
+   	rc_avpair_add (&send, PW_FRAMED_PROTOCOL, &av_type, 0);
+ 
+ 	/* 
+  	 * for RADIUS we login in as username@realm eventualy so
+  	 * here we add an @realm part of username if not already
+  	 * specified.
+  	 */
+  	
+  	strncpy (username, user, sizeof(username)); 
+ 	strncpy (username_realm, user, sizeof (username_realm));
+ 
+ 	default_realm = rc_conf_str ("default_realm");
+ 
+ 	if ((strchr (username_realm, '@') == NULL) && default_realm &&
+       (*default_realm != '\0'))
+     {
+       strncat (username_realm, "@", sizeof (username_realm));
+       strncat (username_realm, default_realm, sizeof (username_realm));
+     }
+ 
+ 	/*
+  	 * we are sending username and password to RADIUS
+  	 */
+  	 
+ 	rc_avpair_add (&send, PW_USER_NAME, username_realm, 0);
+ 	rc_avpair_add (&send, PW_USER_PASSWORD, passwd, 0);
+ 	
+ 	/*
+  	 * make authentication with RADIUS server
+  	 */
+  	 
+   	result = rc_auth (client_port, send, &received, radius_msg);
+ 
+   	if (result == OK_RC) {
+ 		if (radius_setparams(received) < 0)
+ 			result = ERROR_RC;
+ 		else {
+ 			radius_in = TRUE;
+ 			radius_acct_start();
+ 		}
+ 
+ 		rc_avpair_free(received);
+ 	}
+ 	
+ 	/* free value pairs */
+ 	rc_avpair_free (send);
+ 	
+ 	*msg = radius_msg;
+ 	*msglen = strlen(radius_msg);
+ 	
+ 	return (result == OK_RC)?UPAP_AUTHACK:UPAP_AUTHNAK;
+ }
+ 
+ int
+ radius_chap_auth (user, remmd, cstate)
+ 	char *user;
+ 	u_char *remmd;
+ 	chap_state *cstate;
+ {
+ 	VALUE_PAIR *send, *received;
+ 	UINT4 av_type;
+ 	char username_realm[256]; 
+ 	static char radius_msg[4096];
+ 	int result;
+   	char *default_realm;
+ 	u_char cpassword[MD5_SIGNATURE_SIZE+1];
+ 
+ 	/* we handle md5 digest at the moment */
+ 	if (cstate->chal_type != CHAP_DIGEST_MD5)
+ 			return(-1);
+ 	syslog(LOG_WARNING,"@@mla@@ radius_chap_auth called(<%s>, <%s>, cstat)", user, remmd);
+ 	
+ 	send = NULL;
+ 
+ 	/* read in the config files if neccessary */
+ 	if(!called_radius_init && (radius_init() < 0))
+ 		return (-1);
+ 
+ 	/*  
+ 	 *  then we define and map tty to port
+ 	 */
+   	
+   	client_port = rc_map2id (devnam);
+ 	syslog(LOG_WARNING, "@@mla@@ client_port = %d", client_port);
+ 	/*
+  	 * now we define service type and framed protocol
+  	 */
+ 
+     av_type = PW_FRAMED;
+   	rc_avpair_add (&send, PW_SERVICE_TYPE, &av_type, 0);
+ 
+   	av_type = PW_PPP;
+   	rc_avpair_add (&send, PW_FRAMED_PROTOCOL, &av_type, 0);
+ 
+ 	/* 
+  	 * for RADIUS we login in as username@realm eventualy so
+  	 * here we add an @realm part of username if not already
+  	 * specified.
+  	 */
+  	
+  	strncpy (username, user, sizeof(username)); 
+ 	strncpy (username_realm, user, sizeof (username_realm));
+ 
+ 	default_realm = rc_conf_str ("default_realm");
+ 
+ 	if ((strchr (username_realm, '@') == NULL) && default_realm &&
+       (*default_realm != '\0'))
+     {
+       strncat (username_realm, "@", sizeof (username_realm));
+       strncat (username_realm, default_realm, sizeof (username_realm));
+     }
+ 
+ 	/*
+  	 * we are sending username and password to RADIUS
+  	 */
+ 	syslog(LOG_WARNING, "@@mla@@ username_realm= <%s>", username_realm);
+ 	rc_avpair_add (&send, PW_USER_NAME, username_realm, 0);
+ 
+ 	/*
+ 	 * add the CHAP-Password and CHAP-Challenge fields 
+ 	 */
+ 	 
+ 	cpassword[0] = cstate->chal_id;
+ 	memcpy(&cpassword[1], remmd, MD5_SIGNATURE_SIZE);
+ 	
+ 	syslog(LOG_WARNING, "@@mla@@ cpassword= <%s>", &cpassword[1]);
+ 	rc_avpair_add(&send, PW_CHAP_PASSWORD, cpassword, MD5_SIGNATURE_SIZE + 1);
+ 	rc_avpair_add(&send, PW_CHAP_CHALLENGE, cstate->challenge, cstate->chal_len); 
+ 	 
+ 	
+ 	/*
+  	 * make authentication with RADIUS server
+  	 */
+  	 
+   	result = rc_auth (client_port, send, &received, radius_msg);
+ 	syslog(LOG_WARNING, "@@mla@@ radius_auth result = %d", result);
+  	 
+   	if (result == OK_RC) {
+ 
+ 		if (radius_setparams(received) < 0)
+ 			result = ERROR_RC;
+ 		else {
+ 			radius_in = TRUE;
+ 			radius_acct_start();
+ 		}
+ 		syslog(LOG_WARNING, "@@mla@@ radius_auth: before freeing receveid");
+ 		rc_avpair_free(received);
+ 		syslog(LOG_WARNING, "@@mla@@ radius_auth: after freeing receveid");
+ 	}
+ 	
+ 	/* free value pairs */
+ 	syslog(LOG_WARNING, "@@mla@@ radius_auth: before freeing send");
+ 	rc_avpair_free (send);
+ 	syslog(LOG_WARNING, "@@mla@@ radius_auth: after freeing send");
+ 	
+ 	return (result == OK_RC)?0:(-1);
+ }
+ 
+ 
+ 
+ struct ifstats {
+   long rx_bytes;
+   long rx_packets;
+   long rx_errors;
+   long rx_dropped;
+   long rx_fifo_errors;
+   long rx_frame_errors;
+ 
+   long tx_bytes;
+   long tx_packets;
+   long tx_errors;
+   long tx_dropped;
+   long tx_fifo_errors;
+   long collisions;
+   long tx_carrier_errors;
+ };
+ 
+ static int __inline__ isspace(unsigned char c)
+ {
+   return c == ' ' || c == '\t' || c == '\n';
+ }
+ 
+ 
+ static void if_getipacct(char* ifname, struct ifstats* ifs)
+ {
+         FILE* f = fopen("/proc/net/ip_acct","r");
+         char  buf[256];
+         char  acctif[128];
+         long   dummy;
+         long  direction;
+         long   packets;
+         long   bytes;
+         int   rc;
+ 
+         fprintf(stderr,"if_getipacct called\n");
+         if (!f){
+                 perror("Cannot open /proc/net/ip_acct");
+                 return;
+         }
+         fgets(buf, sizeof(buf), f);
+         acctif[0] = '\0';
+         while (1){
+                 rc = fscanf(f, "%ld/%ld->%ld/%ld %s %ld %ld %ld %ld %ld %ld", &dummy,&dummy,&dummy,&dummy,acctif,&dummy, &direction, &dummy, &dummy, &packets, &bytes);
+                 fgets(buf, sizeof(buf), f);
+                 fprintf(stderr,"fscanf returns %d\n", rc);
+                 fprintf(stderr,"Interface <%s>\n", acctif);
+                 if (rc == EOF){
+                         break;
+                 }
+                 if (rc != 11){
+                         break;
+                 }
+                 if (strcmp(ifname, acctif) == 0) {
+                         fprintf(stderr,"Interface <%s> found\n",ifname);
+                         if (direction == 1000) { /* incoming bytes */
+                                 fprintf(stderr,"Incoming bytes/packets = %ld/%ld\n", bytes, packets);
+                                 ifs->rx_bytes = bytes;
+                                 ifs->rx_packets = packets;
+                         } else {
+                                 fprintf(stderr,"Outgoing bytes/packets = %ld/%ld\n", bytes, packets);
+                                 ifs->tx_bytes = bytes;
+                                 ifs->tx_packets = packets;
+                         }
+                 }
+         }
+         fclose(f);
+ }
+ 
+ static void if_getstats(char *ifname, struct ifstats *ife)
+ {
+   FILE *f = fopen("/proc/net/dev", "r");
+   char buf[256];
+   int have_byte_counters = 0;
+   char *bp;
+ 
+   fprintf(stderr,"@mla@: Reading statistics for interface <%s>\n", ifname);
+   if (f==NULL)
+     return;
+   fgets(buf, 255, f);  /* throw away first line of header */
+   fgets(buf, 255, f);
+   if (strstr(buf, "bytes")) have_byte_counters=1;
+   while(fgets(buf,255,f)) {
+     bp=buf;
+     while(*bp&&isspace(*bp))
+       bp++;
+     if(strncmp(bp,ifname,strlen(ifname))==0 && bp[strlen(ifname)]==':') {
+       bp=strchr(bp,':');
+       bp++;
+       if (have_byte_counters) {
+         sscanf(bp,"%ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld",
+                &ife->rx_bytes,
+                &ife->rx_packets,
+                &ife->rx_errors,
+                &ife->rx_dropped,
+                &ife->rx_fifo_errors,
+                &ife->rx_frame_errors,
+                &ife->tx_bytes,
+                &ife->tx_packets,
+                &ife->tx_errors,
+                &ife->tx_dropped,
+                &ife->tx_fifo_errors,
+                &ife->collisions,
+                &ife->tx_carrier_errors
+                );
+       } else {
+         sscanf(bp,"%ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld",
+                &ife->rx_packets,
+                &ife->rx_errors,
+                &ife->rx_dropped,
+                &ife->rx_fifo_errors,
+                &ife->rx_frame_errors,
+                &ife->tx_packets,
+                &ife->tx_errors,
+                &ife->tx_dropped,
+                &ife->tx_fifo_errors,
+                &ife->collisions,
+ 
+                &ife->tx_carrier_errors
+                );
+         ife->rx_bytes = 0;
+         ife->tx_bytes = 0;
+       }
+       break;
+     }
+   }
+   fclose(f);
+ }
+ 
+ static struct ifstats start_stats;
+ 
+ 
+ static void
+ radius_acct_start()
+ {
+ 	UINT4 av_type;
+ 	int result;
+ 	VALUE_PAIR *send = NULL;
+ 
+ 	start_time = time (NULL);
+ 	if_getstats(ifname, &start_stats);
+ 	if (start_stats.rx_bytes == -1)
+ 	  {
+ 	    /* fall back to ip accounting */
+ 	    if_getipacct(ifname, &start_stats);
+ 	    if (start_stats.rx_bytes == -1)
+ 	      {
+ 		start_stats.rx_bytes = 0;
+ 		start_stats.tx_bytes = 0;
+ 	      }
+ 	  }
+ 	
+ 	/* generate an id for this session */
+ 	strncpy (session_id, rc_mksid (), sizeof (session_id));
+ 	rc_avpair_add (&send, PW_ACCT_SESSION_ID, session_id, 0);
+ 	
+ 	rc_avpair_add (&send, PW_USER_NAME, username, 0);
+ 
+ 	av_type = PW_STATUS_START;
+ 	rc_avpair_add (&send, PW_ACCT_STATUS_TYPE, &av_type, 0);
+       
+ 	av_type = PW_FRAMED;
+ 	rc_avpair_add (&send, PW_SERVICE_TYPE, &av_type, 0);
+       
+ 	av_type = PW_PPP;
+ 	rc_avpair_add (&send, PW_FRAMED_PROTOCOL, &av_type, 0);
+ 
+ 	av_type = PW_RADIUS;
+ 	rc_avpair_add (&send, PW_ACCT_AUTHENTIC, &av_type, 0);
+       
+ 	result = rc_acct (client_port, send);
+ 
+ 	rc_avpair_free(send);
+ 	
+     if (result != OK_RC) {
+ 	  /* RADIUS server could be down so make this a warning */
+ 	  syslog (LOG_WARNING, "RADIUS accounting START failed for %s", username);
+ 	}
+ }
+ 
+ void
+ radius_acct_stop ()
+ {
+ 	UINT4 av_type;
+ 	int result;
+ 	VALUE_PAIR *send = NULL;
+ 	struct ifstats stop_stats;
+ 	
+ 	if_getstats(ifname, &stop_stats);
+ 	if (stop_stats.rx_bytes == -1)
+ 	  {
+ 	    /* fall back to ip accounting */
+ 	    if_getipacct(ifname, &stop_stats);
+ 	    if (stop_stats.rx_bytes == -1)
+ 	      {
+ 		stop_stats.rx_bytes = 0;
+ 		stop_stats.tx_bytes = 0;
+ 	      }
+ 	  }
+ 	
+ 	rc_avpair_add (&send, PW_ACCT_SESSION_ID, session_id, 0);
+ 	
+ 	rc_avpair_add (&send, PW_USER_NAME, username, 0);
+ 
+ 	av_type = PW_STATUS_STOP;
+ 	rc_avpair_add (&send, PW_ACCT_STATUS_TYPE, &av_type, 0);
+ 	
+ 	av_type = PW_FRAMED;
+ 	rc_avpair_add (&send, PW_SERVICE_TYPE, &av_type, 0);
+ 
+ 	av_type = PW_PPP;
+ 	rc_avpair_add (&send, PW_FRAMED_PROTOCOL, &av_type, 0);
+ 
+ 	av_type = PW_RADIUS;
+ 	rc_avpair_add (&send, PW_ACCT_AUTHENTIC, &av_type, 0);
+ 	
+ 	av_type = time (NULL) - start_time;
+ 	rc_avpair_add (&send, PW_ACCT_SESSION_TIME, &av_type, 0);
+ 
+ 	av_type = stop_stats.tx_bytes - start_stats.tx_bytes;
+         rc_avpair_add(&send, PW_ACCT_OUTPUT_OCTETS, &av_type, 0);
+ 
+         av_type = stop_stats.rx_bytes - start_stats.rx_bytes;
+         rc_avpair_add(&send, PW_ACCT_INPUT_OCTETS, &av_type, 0);
+ 
+ 
+ 	result = rc_acct (client_port, send);
+ 
+ 	rc_avpair_free(send);
+ 
+ 	if (result != OK_RC)
+     {
+       syslog(LOG_ERR, "RADIUS accounting STOP failed (%s)", username);
+     }
+     
+     /* mark RADIUS as down */
+ 	radius_in = FALSE;
+ }
