diff -Naur radiusd-cistron-1.6.2-stable/Solaris/radiusd.init
radiusd-cistron-1.6.2-stable-PAM/Solaris/radiusd.init
--- radiusd-cistron-1.6.2-stable/Solaris/radiusd.init Thu Jan  1 01:00:00 1970
+++ radiusd-cistron-1.6.2-stable-PAM/Solaris/radiusd.init Thu Feb 24 15:53:17
2000
@@ -0,0 +1,27 @@
+#!/bin/sh
+#
+
+
+
+case "$1" in
+'start')
+  echo "Cistron radius server starting."
+  /usr/local/sbin/radiusd  -y 1>/dev/console
+ ;;
+'stop')
+ [ ! -f /var/run/radiusd.pid ] && exit 0
+ syspid=`cat /var/run/radiusd.pid`
+ if [ "$syspid" -gt 0 ]; then
+  echo "Stopping the radius server."
+               kill  $syspid 2>&1 | /usr/bin/grep -v "no such process"
+ fi
+ ;;
+'restart')
+ $0 stop
+ $0 start
+ ;;
+*)
+ echo "Usage: /etc/init.d/radiusd { start | stop }"
+ ;;
+esac
+exit 0
diff -Naur radiusd-cistron-1.6.2-stable/src/Make.inc
radiusd-cistron-1.6.2-stable-PAM/src/Make.inc
--- radiusd-cistron-1.6.2-stable/src/Make.inc Sun Sep 19 00:10:41 1999
+++ radiusd-cistron-1.6.2-stable-PAM/src/Make.inc Thu Feb 24 16:18:03 2000
@@ -15,7 +15,7 @@
    exec.c auth.c timestr.c cache.c
 INCLUDES       = radius.h conf.h

-all: radiusd radwho radzap raduse radtest
+all: radiusd radwho radzap raduse radtest authtest accttest

 dbm: radiusd.dbm builddbm

@@ -33,7 +33,7 @@
  $(CC) $(CFLAGS) $(DBM) -c radiusd.c -o radiusddbm.o

 acct.o: acct.c $(INCLUDES)
- $(CC) $(CFLAGS) -c acct.c
+ $(CC) $(CFLAGS)  $(PAM) -c acct.c

 attrprint.o: attrprint.c $(INCLUDES)
  $(CC) $(CFLAGS) -c attrprint.c
@@ -81,6 +81,20 @@
 radtest.o: radtest.c $(INCLUDES)
  $(CC) $(CFLAGS) -c radtest.c

+authtest: authtest.o md5.o util.o dict.o attrprint.o log.o
+ $(CC) $(LDFLAGS) -o authtest authtest.o md5.o util.o \
+  dict.o attrprint.o log.o $(LIBS)
+
+accttest: accttest.o md5.o util.o dict.o attrprint.o log.o
+ $(CC) $(LDFLAGS) -o accttest accttest.o md5.o util.o \
+  dict.o attrprint.o log.o $(LIBS)
+
+authtest.o: authtest.c $(INCLUDES)
+ $(CC) $(CFLAGS) -c authtest.c
+
+accttest.o: accttest.c $(INCLUDES)
+ $(CC) $(CFLAGS) -c accttest.c
+
 md5.o: md5.c md5.h
  $(CC) $(CFLAGS) -c md5.c

@@ -104,7 +118,7 @@
  -lint -hbacvx -DLINT ../radpass.c ../md5.c ../util.c

 clean:
- rm -f *.o radiusd radwho raduse radtest radzap builddbm radiusd.dbm
+ rm -f *.o radiusd radwho raduse radtest authtest accttest radzap builddbm
radiusd.dbm
  rm -f ../build ../debian/substvars ../debian/files

 install:
diff -Naur radiusd-cistron-1.6.2-stable/src/Makefile
radiusd-cistron-1.6.2-stable-PAM/src/Makefile
--- radiusd-cistron-1.6.2-stable/src/Makefile Sun Sep 19 00:10:41 1999
+++ radiusd-cistron-1.6.2-stable-PAM/src/Makefile Thu Feb 24 11:02:36 2000
@@ -1,29 +1,18 @@
 #
-# Makefile Radius Makefile for Linux (2.0.x, lib5 or libc6)
+# Makefile Radius Makefile for Solaris 2.5.x
 #
-#
-
-#
-# Autoselect -lshadow and -lcrypt
-#
-ifneq ($(wildcard /usr/lib/libshadow.a),)
-LSHADOW = -lshadow
-endif
-ifneq ($(wildcard /usr/lib/libcrypt.a),)
-LCRYPT = -lcrypt
-endif

 CC = gcc
-CFLAGS = -Wall -g # -DNOSHADOW
-LDFLAGS = # -s # tatic
-LIBS = $(LSHADOW)
+CFLAGS = -g # -DNOSHADOW
+LDFLAGS = # -s #tatic
+LIBS = -lsocket -lnsl
+LCRYPT =

-DBM = -DNDBM
-DBMLIB = -ldb
+DBM     = #-DNDBM
+DBMLIB  = #-ldb

-# Uncomment these if you want PAM support
-#PAM = -DPAM
-#PAMLIB = -lpam -ldl
+PAM = -DPAM
+PAMLIB = -lpam

 BINDIR  = /usr/local/bin
 SBINDIR = /usr/local/sbin
diff -Naur radiusd-cistron-1.6.2-stable/src/acct.c
radiusd-cistron-1.6.2-stable-PAM/src/acct.c
--- radiusd-cistron-1.6.2-stable/src/acct.c Tue Sep 28 14:30:07 1999
+++ radiusd-cistron-1.6.2-stable-PAM/src/acct.c Thu Feb 24 16:06:31 2000
@@ -689,10 +689,17 @@
  */
 int rad_accounting(AUTH_REQ *authreq, int activefd)
 {
- int reply = 0;
- int auth;
- char pw_digest[16];
-
+ int             reply = 0;
+ int             auth;
+ int             session_type;
+ char            pw_digest[16];
+        VALUE_PAIR *vp;
+        VALUE_PAIR *user_name;
+ VALUE_PAIR *user_check;
+        VALUE_PAIR *user_reply;
+        char            *pamauth = NULL;
+        user_check = NULL;
+ user_reply = NULL;
  /*
   * See if we know this client, then check the
   * request authenticator.
@@ -704,6 +711,55 @@
   return -1;
  }

+#ifdef PAM
+ if ((user_name = pairfind(authreq->request, PW_USER_NAME)) != NULL) {
+        if(user_find(user_name->strvalue, authreq->request,
+           &user_check, &user_reply)==0)
+        {
+           if ((vp = pairfind(user_check, PW_AUTHTYPE)) != NULL)
+           session_type = vp->lvalue;
+           if(session_type==PW_AUTHTYPE_PAM)
+            {
+              if ((vp = pairfind(user_check, PAM_AUTH_ATTR)) != NULL) {
+       pamauth = vp->strvalue;
+           }
+           pamauth = pamauth ? pamauth : PAM_DEFAULT_TYPE;
+
+   if ((vp = pairfind(authreq->request, PW_ACCT_STATUS_TYPE)) != NULL) {
+
+            switch (vp->lvalue) {
+                     case PW_STATUS_START:
+                      if (pam_start_accounting(user_name->strvalue,
+                                               authreq,pamauth) != 0)
+                       {
+                         log(L_INFO, "Pam_start_accounting failure");
+                       }
+                      break;
+                     case  PW_STATUS_STOP:
+                      if (pam_stop_accounting(user_name->strvalue,
+                          authreq,pamauth) != 0)
+                       {
+                         log(L_INFO, "Pam_stop_accounting failure");
+                       }
+                      break;
+                     case PW_STATUS_ACCOUNTING_ON:
+                     case PW_STATUS_ACCOUNTING_OFF:
+                         log(L_INFO, "Status Accounting %d", vp->lvalue);
+                     break;
+                     default:
+                         log(L_ERR, "unknown packet type %d", vp->lvalue);
+                     break;
+         }
+
+      }
+   }
+ }
+           pairfree(user_check);
+           pairfree(user_reply);
+ }
+#endif
+
+
  if (log_stripped_names) {
   /*
    * rad_accounting_new strips authreq for us. If
@@ -913,7 +969,7 @@
     u.type = P_IDLE;
     write(fd, &u, sizeof(u));

-    if ((wfp = fopen(RADWTMP, "a")) != NULL) {
+                              if ((wfp = fopen(RADWTMP, "a")) != NULL) {
      make_wtmp(&u, &wt, PW_STATUS_STOP);
      fwrite(&wt, sizeof(wt), 1, wfp);
      fclose(wfp);
@@ -922,7 +978,7 @@
   }
  }
  close(fd);
-
+
  return (count < maxsimul) ? 0 : mpp;
 }

diff -Naur radiusd-cistron-1.6.2-stable/src/accttest.c
radiusd-cistron-1.6.2-stable-PAM/src/accttest.c
--- radiusd-cistron-1.6.2-stable/src/accttest.c Thu Jan  1 01:00:00 1970
+++ radiusd-cistron-1.6.2-stable-PAM/src/accttest.c Thu Feb 24 16:04:24 2000
@@ -0,0 +1,557 @@
+/*
+ *
+ * RADIUS
+ * Remote Authentication Dial In User Service
+ *
+ *
+ * Livingston Enterprises, Inc.
+ * 6920 Koll Center Parkway
+ * Pleasanton, CA   94566
+ *
+ * Copyright 1992 Livingston Enterprises, Inc.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose and without fee is hereby granted, provided that this
+ * copyright and permission notice appear on all copies and supporting
+ * documentation, the name of Livingston Enterprises, Inc. not be used
+ * in advertising or publicity pertaining to distribution of the
+ * program without specific prior permission, and notice be given
+ * in supporting documentation that copying and distribution is by
+ * permission of Livingston Enterprises, Inc.
+ *
+ * Livingston Enterprises, Inc. makes no representations about
+ * the suitability of this software for any purpose.  It is
+ * provided "as is" without express or implied warranty.
+ *
+ */
+
+char radtest_sccsid[] =
+"@(#)radpass.c 1.5 Copyright 1992 Livingston Enterprises Inc\n"
+"@(#)radtest.c 1.3 Copyright 1999 Cistron Internet Services B.V.";
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "radiusd.h"
+#include "conf.h"
+
+#define MAXPWNAM 32
+#define MAXPASS  16
+
+#define TEST_VENDOR 1
+#define TEST_USR 1
+
+int  i_send_buffer[2048];
+int  i_recv_buffer[2048];
+char  *send_buffer = (char *)i_send_buffer;
+char  *recv_buffer = (char *)i_recv_buffer;
+
+char  *progname;
+int  sockfd;
+char  vector[AUTH_VECTOR_LEN];
+char  *secretkey;
+
+char  *radius_dir = RADIUS_DIR;
+char  *radlog_dir = NULL;
+int  debug_flag = 0;
+
+/*
+ * Receive UDP client requests, build an authorization request
+ * structure, and attach attribute-value pairs contained in
+ * the request to the new structure.
+ */
+static AUTH_REQ *test_radrecv(UINT4 host, u_short udp_port,
+   char *buffer, int length)
+{
+ u_char  *ptr;
+ AUTH_HDR *auth;
+ int  totallen;
+ int  attribute;
+ int  attrlen;
+ DICT_ATTR *attr;
+ UINT4  lvalue;
+ VALUE_PAIR *first_pair;
+ VALUE_PAIR *prev;
+ VALUE_PAIR *pair;
+ AUTH_REQ *authreq;
+
+ /*
+  * Pre-allocate the new request data structure
+  */
+
+ if((authreq = (AUTH_REQ *)malloc(sizeof(AUTH_REQ))) ==
+      (AUTH_REQ *)NULL) {
+  fprintf(stderr, "%s: no memory\n", progname);
+  exit(1);
+ }
+
+ auth = (AUTH_HDR *)buffer;
+ totallen = ntohs(auth->length);
+
+ printf("radrecv: Reply from host %lx code=%d, id=%d, length=%d\n",
+    (u_long)host, auth->code, auth->id, totallen);
+
+ /*
+  * Fill header fields
+  */
+ authreq->ipaddr = host;
+ authreq->udp_port = udp_port;
+ authreq->id = auth->id;
+ authreq->code = auth->code;
+ memcpy(authreq->vector, auth->vector, AUTH_VECTOR_LEN);
+
+ /*
+  * Extract attribute-value pairs
+  */
+ ptr = (u_char *)auth->data;
+ length -= AUTH_HDR_LEN;
+ first_pair = (VALUE_PAIR *)NULL;
+ prev = (VALUE_PAIR *)NULL;
+
+ while(length > 0) {
+
+  attribute = *ptr++;
+  attrlen = *ptr++;
+  if(attrlen < 2) {
+   length = 0;
+   continue;
+  }
+  attrlen -= 2;
+  if((attr = dict_attrget(attribute)) == (DICT_ATTR *)NULL) {
+   printf("Received unknown attribute %d\n", attribute);
+  }
+  else if ( attrlen >= AUTH_STRING_LEN ) {
+   printf("attribute %d too long, %d >= %d\n", attribute,
+    attrlen, AUTH_STRING_LEN);
+  }
+  else {
+   if((pair = (VALUE_PAIR *)malloc(sizeof(VALUE_PAIR))) ==
+      (VALUE_PAIR *)NULL) {
+    fprintf(stderr, "%s: no memory\n",
+      progname);
+    exit(1);
+   }
+   /* Same size */
+   strcpy(pair->name, attr->name);
+   pair->attribute = attr->value;
+   pair->type = attr->type;
+   pair->next = (VALUE_PAIR *)NULL;
+
+   switch(attr->type) {
+
+   case PW_TYPE_STRING:
+    memcpy(pair->strvalue, ptr, attrlen);
+    pair->strvalue[attrlen] = '\0';
+    pair->length = attrlen;
+    if(first_pair == (VALUE_PAIR *)NULL) {
+     first_pair = pair;
+    }
+    else {
+     prev->next = pair;
+    }
+    prev = pair;
+    break;
+
+   case PW_TYPE_INTEGER:
+   case PW_TYPE_IPADDR:
+    memcpy(&lvalue, ptr, sizeof(UINT4));
+    pair->lvalue = ntohl(lvalue);
+    if(first_pair == (VALUE_PAIR *)NULL) {
+     first_pair = pair;
+    }
+    else {
+     prev->next = pair;
+    }
+    prev = pair;
+    break;
+
+   default:
+    printf("    %s (Unknown Type %d)\n", attr->name,attr->type);
+    free(pair);
+    break;
+   }
+
+  }
+  ptr += attrlen;
+  length -= attrlen + 2;
+ }
+ authreq->request = first_pair;
+ return(authreq);
+}
+
+
+/*
+ * Receive and print the result of the accounting request.
+ */
+int result_acct_recv(UINT4 host, u_short udp_port, char *buffer, int length)
+{
+ AUTH_HDR *auth;
+ int  totallen;
+ char  reply_digest[AUTH_VECTOR_LEN];
+ char  calc_digest[AUTH_VECTOR_LEN];
+ int  secretlen;
+ AUTH_REQ *authreq;
+ VALUE_PAIR *req;
+
+ auth = (AUTH_HDR *)buffer;
+ totallen = ntohs(auth->length);
+
+ if(totallen != length) {
+  printf("Received invalid reply length from server (want %d/ got %d)\n",
totallen, length);
+  exit(1);
+ }
+
+ authreq = test_radrecv(host, udp_port, buffer, length);
+
+ req = authreq->request;
+
+ while(req) {
+  printf("    ");
+  fprint_attr_val(stdout, req);
+  printf("\n");
+  req = req->next;
+ }
+ if(auth->code !=  PW_ACCOUNTING_RESPONSE ) {
+  printf("Access denied.\n");
+  return -1;
+ }
+ return 0;
+}
+
+
+
+
+
+/*
+ * Print usage message and exit.
+ */
+void usage(void)
+{
+ fprintf(stderr, "Usage: %s username  servername nas_port_id framed_ip_address
acct_status_type nasname [ppphint] \n",
+  progname);
+ exit(1);
+}
+
+
+/*
+ * Generate a random vector.
+ */
+static void random_vector(char *vector)
+{
+ int randno;
+ int i;
+
+ srand(time(0));
+ for(i = 0;i < AUTH_VECTOR_LEN;) {
+  randno = rand();
+  memcpy(vector, &randno, sizeof(int));
+  vector += sizeof(int);
+  i += sizeof(int);
+ }
+}
+
+
+int main(int argc, char **argv)
+{
+ int   salen,hh=0;
+ int   result;
+ struct sockaddr salocal;
+ struct sockaddr saremote;
+ struct sockaddr_in *sin;
+ struct servent  *svp;
+ struct timeval  tv;
+ fd_set   readfds;
+        u_short                 svc_port;
+ AUTH_HDR  *auth;
+ char   *username;
+ char   *framed_ip_addr;
+ char   *server;
+ char   passbuf[AUTH_PASS_LEN];
+ char   md5buf[256];
+ char   nasname[256];
+ UINT4   nas_ipaddr;
+ UINT4   framed_ipaddr;
+ UINT4   auth_ipaddr;
+ UINT4   ui;
+ u_short   local_port;
+ u_short   total_length;
+ int   portno;
+ int   acct_status;
+ int   acct_authen=1;
+ int   ppphint = 0;
+ char   *ptr;
+ int   length;
+ int   i,j;
+ int   bogus_packet = 0;
+
+ progname = argv[0];
+
+ if (argv[1] && strcmp(argv[1], "-b") == 0) {
+  argv++;
+  argc--;
+  bogus_packet = 1;
+ }
+ if (argc < 6 || argc > 8) {
+  usage();
+ }
+
+ username  = argv[1];
+ server    = argv[2];
+ ptr = argv[3];
+ if (*ptr == 's' || *ptr == 'S') ptr++;
+ portno = atoi(ptr);
+ framed_ip_addr = argv[4];
+ ptr = argv[5];
+ acct_status = atoi(ptr);
+
+ if (argc > 6)
+  strNcpy(nasname, argv[6], sizeof(nasname));
+ else
+  gethostname(nasname, sizeof(nasname));
+ nas_ipaddr = get_ipaddr(nasname);
+
+ if (argc > 7) ppphint = atoi(argv[7]);
+ dict_init(NULL);
+
+
+      for(j=0;j<=1;j++)
+      {
+
+        svp = getservbyname ("radacct", "udp");
+ if (svp == (struct servent *) 0)
+  svc_port = PW_ACCT_UDP_PORT;
+ else
+  svc_port = ntohs((u_short) svp->s_port);
+
+ /* Get the IP address of the accounting server */
+ if((auth_ipaddr = get_ipaddr(server)) == 0) {
+  fprintf(stderr, "Couldn't find host %s\n", server);
+  exit(1);
+ }
+
+        fprintf(stdout, "radius accounting server: %s\n", server);
+
+ sockfd = socket (AF_INET, SOCK_DGRAM, 0);
+ if (sockfd < 0) {
+  perror ("socket");
+  exit(1);
+ }
+
+ sin = (struct sockaddr_in *) &salocal;
+        memset (sin, 0, sizeof (salocal));
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = INADDR_ANY;
+
+ local_port = 1026;
+ do {
+  local_port++;
+  sin->sin_port = htons((u_short)local_port);
+ } while((bind(sockfd, &salocal, sizeof (struct sockaddr_in)) < 0) &&
+      local_port < 64000);
+ if (local_port >= 64000) {
+  close(sockfd);
+  perror ("bind");
+  exit(1);
+ }
+
+ /*
+  * Build an accounting request
+  */
+
+ auth = (AUTH_HDR *)send_buffer;
+ auth->code = PW_ACCOUNTING_REQUEST;
+ auth->id = getpid() % 256;
+ random_vector(vector);
+ memcpy(auth->vector, vector, AUTH_VECTOR_LEN);
+ total_length = AUTH_HDR_LEN;
+ ptr = auth->data;
+
+
+ /*
+  * User Name
+  */
+ *ptr++ = PW_USER_NAME;
+ length = strlen(username);
+ if(length > MAXPWNAM) {
+  length = MAXPWNAM;
+ }
+ *ptr++ = length + 2;
+ memcpy(ptr, username, length);
+ ptr += length;
+ total_length += length + 2;
+
+
+ /*
+  *nas-port
+  */
+ *ptr++ = PW_NAS_PORT_ID;
+ *ptr++ = 6;
+ ui = htonl(portno);
+ memcpy(ptr, &ui, sizeof(UINT4));
+ ptr += 4;
+ total_length += 6;
+
+ /*
+  *ip client
+  */
+       framed_ipaddr=ipstr2long(framed_ip_addr);
+ *ptr++ = PW_FRAMED_IP_ADDRESS;
+ *ptr++ = 6;
+ ui = htonl(framed_ipaddr);
+ memcpy(ptr, &ui, sizeof(UINT4));
+ ptr += 4;
+ total_length += 6;
+ *ptr++ = PW_ACCT_STATUS_TYPE;
+ *ptr++ = 6;
+ ui = htonl(acct_status);
+ memcpy(ptr, &ui, sizeof(UINT4));
+ ptr += 4;
+ total_length += 6;
+
+
+ *ptr++ = PW_ACCT_AUTHENTIC;
+ *ptr++ = 6;
+ ui = htonl(acct_authen);
+ memcpy(ptr, &ui, sizeof(UINT4));
+ ptr += 4;
+ total_length += 6;
+
+ *ptr++ = PW_ACCT_SESSION_ID;
+ length = strlen("124");
+ if(length > MAXPWNAM) {
+  length = MAXPWNAM;
+ }
+ *ptr++ = length + 2;
+ memcpy(ptr, "123", length);
+ ptr += length;
+ total_length += length + 2;
+#if TEST_VENDOR
+ *ptr++ = PW_VENDOR_SPECIFIC;
+ *ptr++ = 18;
+ ui = htonl(307); /* livingston */
+ memcpy(ptr, &ui, sizeof(UINT4));
+ ptr += 4;
+
+ *ptr++ = 2; /* LE-Terminate-Detail */
+ *ptr++ = 6; /* len */
+ strcpy(ptr, "test");
+ ptr += 4;
+
+ *ptr++ = 3; /* LE-Advice-of-Charge */
+ *ptr++ = 6; /* len */
+ strcpy(ptr, "TiNC");
+ ptr += 4;
+
+ total_length += 18;
+#endif
+
+#if TEST_USR
+ *ptr++ = PW_VENDOR_SPECIFIC;
+ *ptr++ = 14;
+ ui = htonl(429); /* USR */
+ memcpy(ptr, &ui, sizeof(UINT4));
+ ptr += 4;
+ ui = htonl(0x9823); /* Terminal-Type */
+ memcpy(ptr, &ui, sizeof(UINT4));
+ ptr += 4;
+ strcpy(ptr, "test");
+ ptr += 4;
+ total_length += 14;
+#endif
+
+
+ *ptr++ = PW_NAS_IP_ADDRESS;
+ *ptr++ = 6;
+ ui = htonl(nas_ipaddr);
+ memcpy(ptr, &ui, sizeof(UINT4));
+ ptr += 4;
+ total_length += 6;
+
+ /*
+  * We might need to add a PPP hint.
+  */
+ if (ppphint) {
+  *ptr++ = PW_FRAMED_PROTOCOL;
+  *ptr++ = 6;
+  ui = htonl(PW_PPP);
+  memcpy(ptr, &ui, sizeof(UINT4));
+  ptr += 4;
+  total_length += 6;
+ }
+
+ if (bogus_packet) {
+  *ptr++ = PW_FILTER_ID;
+  length = 4096;
+  *ptr++ = length + 2;
+  for(i = 0; i < 4096; i++)
+   *ptr++ = 'A';
+  ptr += length;
+  total_length += length + 2;
+ }
+
+ auth->length = htons(total_length);
+
+ /*
+  * Send the request we've built.
+  */
+ sin = (struct sockaddr_in *) &saremote;
+        memset (sin, 0, sizeof (saremote));
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = htonl(auth_ipaddr);
+ sin->sin_port = htons(svc_port);
+
+ printf("Sending accounting request for user: %s \n", username);
+ for (i = 0; i < 10; i++) {
+  if (i > 0) printf("Re-sending request.\n");
+  sendto(sockfd, (char *)auth, total_length, 0,
+   &saremote, sizeof(struct sockaddr_in));
+
+  tv.tv_sec = 3;
+  tv.tv_usec = 0;
+  FD_ZERO(&readfds);
+  FD_SET(sockfd, &readfds);
+  if (select(sockfd + 1, &readfds, NULL, NULL, &tv) == 0)
+   continue;
+  salen = sizeof (saremote);
+  result = recvfrom (sockfd, recv_buffer, sizeof(i_recv_buffer),
+   0, &saremote, &salen);
+  if (result >= 0)
+   break;
+  sleep(tv.tv_sec);
+ }
+ if (result > 0 && i < 10) {
+  if(result_acct_recv(sin->sin_addr.s_addr,
+    sin->sin_port, recv_buffer, result)!=0)
+                exit(1);
+ }
+        else
+  {
+         close(sockfd);
+                printf("acounting service failure \n");
+                exit(1);
+  }
+
+
+        if(acct_status==1)
+  {
+                printf("accounting started....\n");
+                sleep(12);
+         close(sockfd);
+                acct_status++;
+  }
+         else
+           break;
+
+ }
+ close(sockfd);
+ exit(0);
+}
diff -Naur radiusd-cistron-1.6.2-stable/src/auth.c
radiusd-cistron-1.6.2-stable-PAM/src/auth.c
--- radiusd-cistron-1.6.2-stable/src/auth.c Tue Nov 16 10:34:52 1999
+++ radiusd-cistron-1.6.2-stable-PAM/src/auth.c Thu Feb 24 14:56:13 2000
@@ -384,7 +384,7 @@
     * pam_pass with the extra info.
     */
    pamauth = pamauth ? pamauth : PAM_DEFAULT_TYPE;
-   if (pam_pass(name, string, pamauth) != 0)
+                        if (pam_pass(name, string, authreq,pamauth) != 0)
     result = -1;
 #else
    log(L_ERR, "%s: PAM authentication not available",
diff -Naur radiusd-cistron-1.6.2-stable/src/authtest.c
radiusd-cistron-1.6.2-stable-PAM/src/authtest.c
--- radiusd-cistron-1.6.2-stable/src/authtest.c Thu Jan  1 01:00:00 1970
+++ radiusd-cistron-1.6.2-stable-PAM/src/authtest.c Thu Feb 24 16:04:01 2000
@@ -0,0 +1,627 @@
+/*
+ *
+ * RADIUS
+ * Remote Authentication Dial In User Service
+ *
+ *
+ * Livingston Enterprises, Inc.
+ * 6920 Koll Center Parkway
+ * Pleasanton, CA   94566
+ *
+ * Copyright 1992 Livingston Enterprises, Inc.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose and without fee is hereby granted, provided that this
+ * copyright and permission notice appear on all copies and supporting
+ * documentation, the name of Livingston Enterprises, Inc. not be used
+ * in advertising or publicity pertaining to distribution of the
+ * program without specific prior permission, and notice be given
+ * in supporting documentation that copying and distribution is by
+ * permission of Livingston Enterprises, Inc.
+ *
+ * Livingston Enterprises, Inc. makes no representations about
+ * the suitability of this software for any purpose.  It is
+ * provided "as is" without express or implied warranty.
+ *
+ */
+
+char radtest_sccsid[] =
+"@(#)radpass.c 1.5 Copyright 1992 Livingston Enterprises Inc\n"
+"@(#)radtest.c 1.3 Copyright 1999 Cistron Internet Services B.V.";
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "radiusd.h"
+#include "conf.h"
+
+#define MAXPWNAM 32
+#define MAXPASS  16
+
+#define TEST_VENDOR 1
+#define TEST_USR 1
+
+int  i_send_buffer[2048];
+int  i_recv_buffer[2048];
+char  *send_buffer = (char *)i_send_buffer;
+char  *recv_buffer = (char *)i_recv_buffer;
+
+char  *progname;
+int  sockfd;
+char  vector[AUTH_VECTOR_LEN];
+char  *secretkey;
+
+char  *radius_dir = RADIUS_DIR;
+char  *radlog_dir = NULL;
+int  debug_flag = 0;
+
+/*
+ * Receive UDP client requests, build an authorization request
+ * structure, and attach attribute-value pairs contained in
+ * the request to the new structure.
+ */
+static AUTH_REQ *test_radrecv(UINT4 host, u_short udp_port,
+   char *buffer, int length)
+{
+ u_char  *ptr;
+ AUTH_HDR *auth;
+ int  totallen;
+ int  attribute;
+ int  attrlen;
+ DICT_ATTR *attr;
+ UINT4  lvalue;
+ VALUE_PAIR *first_pair;
+ VALUE_PAIR *prev;
+ VALUE_PAIR *pair;
+ AUTH_REQ *authreq;
+
+ /*
+  * Pre-allocate the new request data structure
+  */
+
+ if((authreq = (AUTH_REQ *)malloc(sizeof(AUTH_REQ))) ==
+      (AUTH_REQ *)NULL) {
+  fprintf(stderr, "%s: no memory\n", progname);
+  exit(1);
+ }
+
+ auth = (AUTH_HDR *)buffer;
+ totallen = ntohs(auth->length);
+
+ printf("radrecv: Reply from host %lx code=%d, id=%d, length=%d\n",
+    (u_long)host, auth->code, auth->id, totallen);
+
+ /*
+  * Fill header fields
+  */
+ authreq->ipaddr = host;
+ authreq->udp_port = udp_port;
+ authreq->id = auth->id;
+ authreq->code = auth->code;
+ memcpy(authreq->vector, auth->vector, AUTH_VECTOR_LEN);
+
+ /*
+  * Extract attribute-value pairs
+  */
+ ptr = (u_char *)auth->data;
+ length -= AUTH_HDR_LEN;
+ first_pair = (VALUE_PAIR *)NULL;
+ prev = (VALUE_PAIR *)NULL;
+
+ while(length > 0) {
+
+  attribute = *ptr++;
+  attrlen = *ptr++;
+  if(attrlen < 2) {
+   length = 0;
+   continue;
+  }
+  attrlen -= 2;
+  if((attr = dict_attrget(attribute)) == (DICT_ATTR *)NULL) {
+   printf("Received unknown attribute %d\n", attribute);
+  }
+  else if ( attrlen >= AUTH_STRING_LEN ) {
+   printf("attribute %d too long, %d >= %d\n", attribute,
+    attrlen, AUTH_STRING_LEN);
+  }
+  else {
+   if((pair = (VALUE_PAIR *)malloc(sizeof(VALUE_PAIR))) ==
+      (VALUE_PAIR *)NULL) {
+    fprintf(stderr, "%s: no memory\n",
+      progname);
+    exit(1);
+   }
+   /* Same size */
+   strcpy(pair->name, attr->name);
+   pair->attribute = attr->value;
+   pair->type = attr->type;
+   pair->next = (VALUE_PAIR *)NULL;
+
+   switch(attr->type) {
+
+   case PW_TYPE_STRING:
+    memcpy(pair->strvalue, ptr, attrlen);
+    pair->strvalue[attrlen] = '\0';
+    pair->length = attrlen;
+    if(first_pair == (VALUE_PAIR *)NULL) {
+     first_pair = pair;
+    }
+    else {
+     prev->next = pair;
+    }
+    prev = pair;
+    break;
+
+   case PW_TYPE_INTEGER:
+   case PW_TYPE_IPADDR:
+    memcpy(&lvalue, ptr, sizeof(UINT4));
+    pair->lvalue = ntohl(lvalue);
+    if(first_pair == (VALUE_PAIR *)NULL) {
+     first_pair = pair;
+    }
+    else {
+     prev->next = pair;
+    }
+    prev = pair;
+    break;
+
+   default:
+    printf("    %s (Unknown Type %d)\n", attr->name,attr->type);
+    free(pair);
+    break;
+   }
+
+  }
+  ptr += attrlen;
+  length -= attrlen + 2;
+ }
+ authreq->request = first_pair;
+ return(authreq);
+}
+
+
+/*
+ * Receive and print the result.
+ */
+int result_recv(UINT4 host, u_short udp_port, char *buffer, int length)
+{
+ AUTH_HDR *auth;
+ int  totallen;
+ char  reply_digest[AUTH_VECTOR_LEN];
+ char  calc_digest[AUTH_VECTOR_LEN];
+ int  secretlen;
+ AUTH_REQ *authreq;
+ VALUE_PAIR *req;
+
+ auth = (AUTH_HDR *)buffer;
+ totallen = ntohs(auth->length);
+
+ if(totallen != length) {
+  printf("Received invalid reply length from server (want %d/ got %d)\n",
totallen, length);
+  exit(1);
+ }
+
+ /* Verify the reply digest */
+ memcpy(reply_digest, auth->vector, AUTH_VECTOR_LEN);
+ memcpy(auth->vector, vector, AUTH_VECTOR_LEN);
+ secretlen = strlen(secretkey);
+ memcpy(buffer + length, secretkey, secretlen);
+ md5_calc(calc_digest, (char *)auth, length + secretlen);
+
+ if(memcmp(reply_digest, calc_digest, AUTH_VECTOR_LEN) != 0) {
+  printf("Warning: Received invalid reply digest from server\n");
+ }
+
+ authreq = test_radrecv(host, udp_port, buffer, length);
+
+ req = authreq->request;
+
+ while(req) {
+  printf("    ");
+  fprint_attr_val(stdout, req);
+  printf("\n");
+  req = req->next;
+ }
+ if(auth->code != PW_AUTHENTICATION_ACK) {
+  printf("Access denied.\n");
+  return -1;
+ }
+ return 0;
+}
+
+/*
+ * Receive and print the result of the accounting request.
+ */
+int result_acct_recv(UINT4 host, u_short udp_port, char *buffer, int length)
+{
+ AUTH_HDR *auth;
+ int  totallen;
+ char  reply_digest[AUTH_VECTOR_LEN];
+ char  calc_digest[AUTH_VECTOR_LEN];
+ int  secretlen;
+ AUTH_REQ *authreq;
+ VALUE_PAIR *req;
+
+ auth = (AUTH_HDR *)buffer;
+ totallen = ntohs(auth->length);
+
+ if(totallen != length) {
+  printf("Received invalid reply length from server (want %d/ got %d)\n",
totallen, length);
+  exit(1);
+ }
+
+ /* Verify the reply digest */
+ memcpy(reply_digest, auth->vector, AUTH_VECTOR_LEN);
+ memcpy(auth->vector, vector, AUTH_VECTOR_LEN);
+ secretlen = strlen(secretkey);
+ memcpy(buffer + length, secretkey, secretlen);
+ md5_calc(calc_digest, (char *)auth, length + secretlen);
+
+ if(memcmp(reply_digest, calc_digest, AUTH_VECTOR_LEN) != 0) {
+  printf("Warning: Received invalid reply digest from server\n");
+ }
+
+ authreq = test_radrecv(host, udp_port, buffer, length);
+
+ req = authreq->request;
+
+ while(req) {
+  printf("    ");
+  fprint_attr_val(stdout, req);
+  printf("\n");
+  req = req->next;
+ }
+ if(auth->code !=  PW_ACCOUNTING_RESPONSE ) {
+  printf("Access denied.\n");
+  return -1;
+ }
+ return 0;
+}
+
+
+
+
+
+/*
+ * Print usage message and exit.
+ */
+void usage(void)
+{
+ fprintf(stderr, "Usage: %s username passwd servername nas_port_id secretkey cli
called-station-id framed-ip-address [ppphint] [nasname]\n",
+  progname);
+ exit(1);
+}
+
+
+/*
+ * Generate a random vector.
+ */
+static void random_vector(char *vector)
+{
+ int randno;
+ int i;
+
+ srand(time(0));
+ for(i = 0;i < AUTH_VECTOR_LEN;) {
+  randno = rand();
+  memcpy(vector, &randno, sizeof(int));
+  vector += sizeof(int);
+  i += sizeof(int);
+ }
+}
+
+
+int main(int argc, char **argv)
+{
+ int   salen,hh=0;
+ int   result;
+ struct sockaddr salocal;
+ struct sockaddr saremote;
+ struct sockaddr_in *sin;
+ struct servent  *svp;
+ struct timeval  tv;
+ fd_set   readfds;
+        u_short                 svc_port;
+ AUTH_HDR  *auth;
+ char   *username;
+ char   *cli;
+ char   *called;
+ char   *framed_ip_addr;
+ char   *passwd;
+ char   *server;
+ char   passbuf[AUTH_PASS_LEN];
+ char   md5buf[256];
+ char   nasname[256];
+ UINT4   nas_ipaddr;
+ UINT4   framed_ipaddr;
+ UINT4   auth_ipaddr;
+ UINT4   ui;
+ u_short   local_port;
+ u_short   total_length;
+ int   portno;
+ int   ppphint = 0;
+ char   *ptr;
+ int   length;
+ int   secretlen;
+ int   i,j;
+ int   bogus_packet = 0;
+
+ progname = argv[0];
+
+ if (argv[1] && strcmp(argv[1], "-b") == 0) {
+  argv++;
+  argc--;
+  bogus_packet = 1;
+ }
+
+ if (argc < 9 || argc > 11) {
+  usage();
+ }
+ username  = argv[1];
+ passwd    = argv[2];
+ server    = argv[3];
+ secretkey = argv[5];
+ cli = argv[6];
+ called = argv[7];
+ framed_ip_addr = argv[8];
+ ptr = argv[4];
+ if (*ptr == 's' || *ptr == 'S') ptr++;
+ portno = atoi(ptr);
+ if (argc > 9) ppphint = atoi(argv[9]);
+
+ if (argc > 10)
+  strncpy(nasname, argv[10], sizeof(nasname));
+ else
+  gethostname(nasname, sizeof(nasname));
+ nas_ipaddr = get_ipaddr(nasname);
+
+ dict_init(NULL);
+
+ /*
+  * Open a connection to the server.
+  */
+ svp = getservbyname ("radius", "udp");
+ if (svp == (struct servent *) 0)
+  svc_port = PW_AUTH_UDP_PORT;
+ else
+  svc_port = ntohs((u_short) svp->s_port);
+
+ /* Get the IP address of the authentication server */
+ if((auth_ipaddr = get_ipaddr(server)) == 0) {
+  fprintf(stderr, "Couldn't find host %s\n", server);
+  exit(1);
+ }
+
+  fprintf(stdout, "radius authentication server: %s \n", server);
+ /*framed_ipaddr = get_ipaddr(framed_ip_addr);*/
+
+ sockfd = socket (AF_INET, SOCK_DGRAM, 0);
+ if (sockfd < 0) {
+  perror ("socket");
+  exit(1);
+ }
+
+ sin = (struct sockaddr_in *) &salocal;
+        memset (sin, 0, sizeof (salocal));
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = INADDR_ANY;
+
+ local_port = 1025;
+ do {
+  local_port++;
+  sin->sin_port = htons((u_short)local_port);
+ } while((bind(sockfd, &salocal, sizeof (struct sockaddr_in)) < 0) &&
+      local_port < 64000);
+ if (local_port >= 64000) {
+  close(sockfd);
+  perror ("bind");
+  exit(1);
+ }
+
+ /*
+  * Build an authentication request
+  */
+
+ auth = (AUTH_HDR *)send_buffer;
+ auth->code = PW_AUTHENTICATION_REQUEST;
+ auth->id = getpid() % 256;
+ random_vector(vector);
+ memcpy(auth->vector, vector, AUTH_VECTOR_LEN);
+ total_length = AUTH_HDR_LEN;
+ ptr = auth->data;
+
+ /*
+  *cli
+  */
+    *ptr++ =  PW_CALLING_STATION_ID;
+ length = strlen(cli);
+ if(length > 16) {
+  length = 16;
+ }
+ *ptr++ = length + 2;
+ memcpy(ptr, cli, length);
+ ptr += length;
+ total_length += length + 2;
+/****************/
+ /*
+  *called-station-id
+  */
+ *ptr++ =  PW_CALLED_STATION_ID;
+ length = strlen(called);
+ if(length > 16) {
+  length = 16;
+ }
+ *ptr++ = length + 2;
+ memcpy(ptr, called, length);
+ ptr += length;
+ total_length += length + 2;
+ /*
+  *ip client
+  */
+        framed_ipaddr=ipstr2long(framed_ip_addr);
+ *ptr++ = PW_FRAMED_IP_ADDRESS;
+ *ptr++ = 6;
+ ui = htonl(framed_ipaddr);
+ memcpy(ptr, &ui, sizeof(UINT4));
+ ptr += 4;
+ total_length += 6;
+
+ /*
+  * User Name
+  */
+ *ptr++ = PW_USER_NAME;
+ length = strlen(username);
+ if(length > MAXPWNAM) {
+  length = MAXPWNAM;
+ }
+ *ptr++ = length + 2;
+ memcpy(ptr, username, length);
+ ptr += length;
+ total_length += length + 2;
+
+ /*
+  * Password
+  */
+ *ptr++ = PW_PASSWORD;
+ *ptr++ = AUTH_PASS_LEN + 2;
+
+ length = strlen(passwd);
+ if(length > MAXPASS) {
+  length = MAXPASS;
+ }
+ memset(passbuf, 0, AUTH_PASS_LEN);
+ memcpy(passbuf, passwd, length);
+
+ /* Calculate the MD5 Digest */
+ secretlen = strlen(secretkey);
+ strNcpy(md5buf, secretkey, sizeof(md5buf));
+ memcpy(md5buf + secretlen, auth->vector, AUTH_VECTOR_LEN);
+ md5_calc(ptr, md5buf, secretlen + AUTH_VECTOR_LEN);
+
+ /* Xor the password into the MD5 digest */
+ for(i = 0;i < AUTH_PASS_LEN;i++) {
+  *ptr++ ^= passbuf[i];
+ }
+ total_length += AUTH_PASS_LEN + 2;
+
+ *ptr++ = PW_NAS_PORT_ID;
+ *ptr++ = 6;
+ ui = htonl(portno);
+ memcpy(ptr, &ui, sizeof(UINT4));
+ ptr += 4;
+ total_length += 6;
+
+
+#if TEST_VENDOR
+ *ptr++ = PW_VENDOR_SPECIFIC;
+ *ptr++ = 18;
+ ui = htonl(307); /* livingston */
+ memcpy(ptr, &ui, sizeof(UINT4));
+ ptr += 4;
+
+ *ptr++ = 2; /* LE-Terminate-Detail */
+ *ptr++ = 6; /* len */
+ strcpy(ptr, "test");
+ ptr += 4;
+
+ *ptr++ = 3; /* LE-Advice-of-Charge */
+ *ptr++ = 6; /* len */
+ strcpy(ptr, "TiNC");
+ ptr += 4;
+
+ total_length += 18;
+#endif
+
+#if TEST_USR
+ *ptr++ = PW_VENDOR_SPECIFIC;
+ *ptr++ = 14;
+ ui = htonl(429); /* USR */
+ memcpy(ptr, &ui, sizeof(UINT4));
+ ptr += 4;
+ ui = htonl(0x9823); /* Terminal-Type */
+ memcpy(ptr, &ui, sizeof(UINT4));
+ ptr += 4;
+ strcpy(ptr, "test");
+ ptr += 4;
+ total_length += 14;
+#endif
+
+ *ptr++ = PW_NAS_IP_ADDRESS;
+ *ptr++ = 6;
+ ui = htonl(nas_ipaddr);
+ memcpy(ptr, &ui, sizeof(UINT4));
+ ptr += 4;
+ total_length += 6;
+
+ /*
+  * We might need to add a PPP hint.
+  */
+ if (ppphint) {
+  *ptr++ = PW_FRAMED_PROTOCOL;
+  *ptr++ = 6;
+  ui = htonl(PW_PPP);
+  memcpy(ptr, &ui, sizeof(UINT4));
+  ptr += 4;
+  total_length += 6;
+ }
+
+ if (bogus_packet) {
+  *ptr++ = PW_FILTER_ID;
+  length = 4096;
+  *ptr++ = length + 2;
+  for(i = 0; i < 4096; i++)
+   *ptr++ = 'A';
+  ptr += length;
+  total_length += length + 2;
+ }
+
+ auth->length = htons(total_length);
+
+ /*
+  * Send the request we've built.
+  */
+ sin = (struct sockaddr_in *) &saremote;
+        memset (sin, 0, sizeof (saremote));
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = htonl(auth_ipaddr);
+ sin->sin_port = htons(svc_port);
+
+ printf("Sending autentication request for user: %s\n", username);
+ for (i = 0; i < 10; i++) {
+  if (i > 0) printf("Re-sending request.\n");
+  sendto(sockfd, (char *)auth, total_length, 0,
+   &saremote, sizeof(struct sockaddr_in));
+
+         sleep(2);
+  tv.tv_sec = 3;
+  tv.tv_usec = 0;
+  FD_ZERO(&readfds);
+  FD_SET(sockfd, &readfds);
+  if (select(sockfd + 1, &readfds, NULL, NULL, &tv) == 0)
+   continue;
+  salen = sizeof (saremote);
+  result = recvfrom (sockfd, recv_buffer, sizeof(i_recv_buffer),
+   0, &saremote, &salen);
+  if (result >= 0)
+   break;
+  sleep(tv.tv_sec);
+ }
+
+ if (result > 0 && i < 10) {
+                result_recv(sin->sin_addr.s_addr,
+                                        sin->sin_port, recv_buffer, result);
+                exit(0);
+        }
+        printf("No answer.\n");
+        close(sockfd);
+        exit(1);
+}
diff -Naur radiusd-cistron-1.6.2-stable/src/pam.c
radiusd-cistron-1.6.2-stable-PAM/src/pam.c
--- radiusd-cistron-1.6.2-stable/src/pam.c Sun Sep 19 00:10:41 1999
+++ radiusd-cistron-1.6.2-stable-PAM/src/pam.c Thu Feb 24 16:10:04 2000
@@ -26,7 +26,6 @@
 #include <security/pam_appl.h>

 #include "radiusd.h"
-
 /*************************************************************************
  *
  * Function: PAM_conv
@@ -103,16 +102,52 @@
  * allows you to have multiple authentication types (i.e. multiple
  * files associated with radius in /etc/pam.d)
  */
-int pam_pass(char *name, char *passwd, const char *pamauth)
+
+int pam_pass(char *name, char *passwd, AUTH_REQ *data, const char *pamauth)
 {
     pam_handle_t *pamh=NULL;
     int retval;
+    char ip_str[16];
+    char porta[16];
+    char *lpszRemoteUser=NULL;
+    VALUE_PAIR *framed_ip;
+    VALUE_PAIR *calling_id;
+    VALUE_PAIR *called_id;
+    VALUE_PAIR *nas_port;

     PAM_username = name;
     PAM_password = passwd;

-    DEBUG("pam_pass: using pamauth string <%s> for pam.conf lookup", pamauth);
+    if( (calling_id=pairfind(data->request, PW_CALLING_STATION_ID)) &&
(called_id=pairfind(data->request, PW_CALLED_STATION_ID))!= NULL  )
+     {
+      if( (lpszRemoteUser =
calloc(strlen(name)+strlen(calling_id->strvalue)+strlen(called_id->strvalue)+3,sizeof(char)))!=NULL)

+       sprintf(lpszRemoteUser,"%s:%s/%s",name,calling_id->strvalue,
called_id->strvalue);
+     }
+else
+     {
+       if( (calling_id=pairfind(data->request, PW_CALLING_STATION_ID)) &&
(called_id=pairfind(data->request, PW_CALLED_STATION_ID))== NULL  )
+       {
+         if(( lpszRemoteUser =
calloc(strlen(name)+strlen(calling_id->strvalue)+2,sizeof(char)))!=NULL)
+         sprintf(lpszRemoteUser,"%s:%s",name,calling_id->strvalue);
+       }
+     }
+
     retval = pam_start(pamauth, name, &conv, &pamh);
+    if(lpszRemoteUser!=NULL)
+     {
+       pam_set_item(pamh,PAM_RUSER,lpszRemoteUser);
+       free(lpszRemoteUser);
+     }
+    if( (framed_ip=pairfind(data->request, PW_FRAMED_IP_ADDRESS)) != NULL  )
+     {
+       ipaddr2str(ip_str,framed_ip->lvalue);
+       pam_set_item(pamh,PAM_RHOST,ip_str);
+     }
+    if ((nas_port=pairfind(data->request, PW_NAS_PORT_ID) )!= NULL  )
+     {
+       sprintf(porta,"%lu",nas_port->lvalue);
+       pam_set_item(pamh,PAM_TTY,porta);
+     }
     if (retval == PAM_SUCCESS) {
       DEBUG("pam_pass: function pam_start succeeded for <%s>", name);
       retval = pam_authenticate(pamh, 0);
@@ -125,12 +160,93 @@
       DEBUG("pam_pass: function pam_acct_mgmt succeeded for <%s>", name);
       pam_end(pamh, 0);
       return(0);
-    } else {
+    }
+
       DEBUG("pam_pass: PAM FAILED for <%s> failed", name);
       pam_end(pamh, 0);
-      return (-1);
-    }
+      return -1;
+
 }

+int pam_start_accounting(char *user_name, AUTH_REQ *data, const char *pamauth)
+{
+    pam_handle_t *pamh=NULL;
+    int retval;
+    char ip_str[16];
+    char porta[16];
+    VALUE_PAIR *framed_ip;
+    VALUE_PAIR *calling_id;
+    VALUE_PAIR *nas_port;
+
+    PAM_username = user_name;
+
+    retval = pam_start(pamauth, user_name, &conv, &pamh);
+
+    if (retval == PAM_SUCCESS) {
+    if ((framed_ip=pairfind(data->request, PW_FRAMED_IP_ADDRESS) )!= NULL  )
+     {
+       ipaddr2str(ip_str,framed_ip->lvalue);
+       pam_set_item(pamh,PAM_RHOST,ip_str);
+     }
+    if ((nas_port=pairfind(data->request, PW_NAS_PORT_ID) )!= NULL  )
+     {
+       sprintf(porta,"%lu",nas_port->lvalue);
+       pam_set_item(pamh,PAM_TTY,porta);
+     }
+      DEBUG("pam_start_accounting: function pam_start succeeded for %s",
user_name);
+      retval = pam_open_session(pamh, 0);
+    }
+    if (retval == PAM_SUCCESS) {
+      DEBUG("pam_start_accounting: function pam_open_session succeeded for %s",
user_name);
+      pam_end(pamh, 0);
+      return (0);
+    }
+     else {
+      DEBUG("pam_start_accounting: PAM FAILED for <%s> failed %s",user_name,
pam_strerror(pamh,retval));
+      pam_end(pamh, 0);
+      return -1;
+    }
+    return 0;
+    }
+
+int pam_stop_accounting(char *user_name,AUTH_REQ *data, const char *pamauth)
+{
+    pam_handle_t *pamh=NULL;
+    int retval;
+    char ip_str[16];
+    char porta[16];
+    VALUE_PAIR *framed_ip;
+    VALUE_PAIR *calling_id;
+    VALUE_PAIR *nas_port;
+
+    PAM_username = user_name;
+
+    retval = pam_start(pamauth, user_name, &conv, &pamh);
+    if (retval == PAM_SUCCESS) {
+      DEBUG("pam_stop_accounting: function pam_start succeeded for <%s>",
user_name);
+    if ((framed_ip=pairfind(data->request, PW_FRAMED_IP_ADDRESS) )!= NULL  )
+     {
+       ipaddr2str(ip_str,framed_ip->lvalue);
+       pam_set_item(pamh,PAM_RHOST,ip_str);
+     }
+    if ((nas_port=pairfind(data->request, PW_NAS_PORT_ID) )!= NULL  )
+     {
+       sprintf(porta,"%lu",nas_port->lvalue);
+       pam_set_item(pamh,PAM_TTY,porta);
+     }
+      retval = pam_close_session(pamh, 0);
+    }
+    if (retval == PAM_SUCCESS) {
+      DEBUG("pam_stop_accounting: function pam_close_session succeeded retval
<%d>", retval);
+      pam_end(pamh, 0);
+      return (0);
+    }
+     else {
+      DEBUG("pam_stop_accounting: PAM FAILED for <%s> failed %s",user_name,
pam_strerror(pamh,retval));
+      pam_end(pamh, 0);
+      return -1;
+    }
+    return 0;
+    }
 #endif /* PAM */

diff -Naur radiusd-cistron-1.6.2-stable/src/radiusd.h
radiusd-cistron-1.6.2-stable-PAM/src/radiusd.h
--- radiusd-cistron-1.6.2-stable/src/radiusd.h Wed Oct  6 23:25:43 1999
+++ radiusd-cistron-1.6.2-stable-PAM/src/radiusd.h Thu Feb 24 14:57:13 2000
@@ -261,7 +261,9 @@

 /* pam.c */
 #ifdef PAM
-int  pam_pass(char *name, char *passwd, const char *pamauth);
+int  pam_start_accounting(char *, AUTH_REQ *, const char *);
+int  pam_stop_accounting(char *, AUTH_REQ *, const char *);
+int  pam_pass(char *name, char *passwd, AUTH_REQ *, const char *pamauth);
 #define PAM_DEFAULT_TYPE    "radius"
 #endif
