-------------------------------------------------------------------------------

diff -r -P -d -C 3 ppp-2.3.5/pppd/Makefile ppp-2.3.5-2cbcps-radius-multiport/pppd/Makefile
*** ppp-2.3.5/pppd/Makefile	Thu Jan  1 05:00:00 1970
--- ppp-2.3.5-2cbcps-radius-multiport/pppd/Makefile	Thu Aug 19 15:20:02 1999
***************
*** 0 ****
--- 1,21 ----
+ #	$Id: Makefile.bsd,v 1.14 1998/03/25 01:27:00 paulus Exp $
+ 
+ BINDIR?= /usr/sbin
+ # -D_BITYPES is for FreeBSD, which doesn't define anything to
+ # tell us that u_int32_t gets defined if <sys/types.h> is included.
+ # Remove for older *BSD systems for which this isn't true.
+ CFLAGS+= -g -I../include -DHAVE_PATHS_H -D_BITYPES
+ 
+ PROG=	pppd
+ SRCS=	main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c ccp.c \
+ 	demand.c auth.c options.c sys-bsd.c cbcps.c pppdradius.c libradius.c \
+ 	callerid.c con_state.c
+ MAN=	pppd.cat8
+ MAN8=	pppd.8
+ BINMODE=4555
+ BINOWN=	root
+ 
+ LDADD=	-lcrypt -lutil
+ DPADD=	${LIBCRYPT} ${LIBUTIL}
+ 
+ .include <bsd.prog.mk>
diff -r -P -d -C 3 ppp-2.3.5/pppd/Makefile.NeXT ppp-2.3.5-2cbcps-radius-multiport/pppd/Makefile.NeXT
*** ppp-2.3.5/pppd/Makefile.NeXT	Wed Mar 25 06:26:53 1998
--- ppp-2.3.5-2cbcps-radius-multiport/pppd/Makefile.NeXT	Sun Jan 24 14:39:09 1999
***************
*** 11,17 ****
  MANDIR = /usr/local/ppp/man
  
  OBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o \
! 	auth.o options.o demand.o sys-NeXT.o
  
  #
  # For HPPA and SPARC, define FIXSIGS to get around posix bugs in
--- 11,17 ----
  MANDIR = /usr/local/ppp/man
  
  OBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o \
! 	auth.o options.o demand.o sys-NeXT.o cbcps.o pppdradius.o libradius.o
  
  #
  # For HPPA and SPARC, define FIXSIGS to get around posix bugs in
diff -r -P -d -C 3 ppp-2.3.5/pppd/Makefile.bsd ppp-2.3.5-2cbcps-radius-multiport/pppd/Makefile.bsd
*** ppp-2.3.5/pppd/Makefile.bsd	Wed Mar 25 06:26:56 1998
--- ppp-2.3.5-2cbcps-radius-multiport/pppd/Makefile.bsd	Thu Aug 19 15:20:02 1999
***************
*** 8,14 ****
  
  PROG=	pppd
  SRCS=	main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c ccp.c \
! 	demand.c auth.c options.c sys-bsd.c
  MAN=	pppd.cat8
  MAN8=	pppd.8
  BINMODE=4555
--- 8,15 ----
  
  PROG=	pppd
  SRCS=	main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c ccp.c \
! 	demand.c auth.c options.c sys-bsd.c cbcps.c pppdradius.c libradius.c \
! 	callerid.c con_state.c
  MAN=	pppd.cat8
  MAN8=	pppd.8
  BINMODE=4555
diff -r -P -d -C 3 ppp-2.3.5/pppd/Makefile.linux ppp-2.3.5-2cbcps-radius-multiport/pppd/Makefile.linux
*** ppp-2.3.5/pppd/Makefile.linux	Mon May  4 12:10:29 1998
--- ppp-2.3.5-2cbcps-radius-multiport/pppd/Makefile.linux	Sun Jan 24 14:42:28 1999
***************
*** 9,20 ****
  
  PPPDSRCS = main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c ccp.c \
  	   ipxcp.c auth.c options.c sys-linux.c md4.c chap_ms.c cbcp.c \
! 	   demand.c
  HEADERS =  callout.h pathnames.h patchlevel.h chap.h md5.h chap_ms.h md4.h \
! 	   ipxcp.h cbcp.h
  MANPAGES = pppd.8
  PPPDOBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o \
! 	   auth.o options.o demand.o sys-linux.o ipxcp.o
  
  all: pppd
  
--- 9,20 ----
  
  PPPDSRCS = main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c ccp.c \
  	   ipxcp.c auth.c options.c sys-linux.c md4.c chap_ms.c cbcp.c \
! 	   demand.c cbcps.c pppdradius.c libradius.c
  HEADERS =  callout.h pathnames.h patchlevel.h chap.h md5.h chap_ms.h md4.h \
! 	   ipxcp.h cbcp.h cbcps.h pppdradius.h radius.h libradius.h 
  MANPAGES = pppd.8
  PPPDOBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o \
! 	   auth.o options.o demand.o sys-linux.o ipxcp.o cbcps.o pppdradius.o libradius.o
  
  all: pppd
  
***************
*** 30,36 ****
  VER = 2.3.5
  LIBS =
  
! ifneq ($(wildcard /usr/lib/libcrypt*),)
  LIBS += -lcrypt
  endif
  
--- 30,36 ----
  VER = 2.3.5
  LIBS =
  
! ifneq ($(wildcard /usr/lib/libcrypt.*),)
  LIBS += -lcrypt
  endif
  
***************
*** 38,44 ****
  # MS-CHAP authentication protocol.
  CHAPMS=y
  USE_CRYPT=y
! ifneq ($(wildcard /usr/lib/libcrypt*),)
  HAVE_CRYPT_H=y
  endif
  
--- 38,44 ----
  # MS-CHAP authentication protocol.
  CHAPMS=y
  USE_CRYPT=y
! ifneq ($(wildcard /usr/lib/libcrypt.*),)
  HAVE_CRYPT_H=y
  endif
  
***************
*** 87,97 ****
  
  install: pppd
  	mkdir -p $(BINDIR) $(MANDIR)
! 	install -s -c -m 4555 -o root pppd $(BINDIR)/pppd
  	install -c -m 444 -o root pppd.8 $(MANDIR)/man8
  
  pppd: $(PPPDOBJS)
  	$(CC) $(CFLAGS) -o pppd $(PPPDOBJS) $(LIBS)
  
  clean:
  	rm -f $(PPPDOBJS) pppd *~ #* core
--- 87,100 ----
  
  install: pppd
  	mkdir -p $(BINDIR) $(MANDIR)
! 	install -s -c -m 4555 -o root -g dip pppd $(BINDIR)/pppd
  	install -c -m 444 -o root pppd.8 $(MANDIR)/man8
  
  pppd: $(PPPDOBJS)
  	$(CC) $(CFLAGS) -o pppd $(PPPDOBJS) $(LIBS)
+ 
+ testchap: testchap.c chap_ms.o md4.o
+ 	$(CC) $(CFLAGS) -o testchap $(^) $(LIBS)
  
  clean:
  	rm -f $(PPPDOBJS) pppd *~ #* core
diff -r -P -d -C 3 ppp-2.3.5/pppd/Makefile.netbsd-1.2 ppp-2.3.5-2cbcps-radius-multiport/pppd/Makefile.netbsd-1.2
*** ppp-2.3.5/pppd/Makefile.netbsd-1.2	Thu Mar 12 15:37:32 1998
--- ppp-2.3.5-2cbcps-radius-multiport/pppd/Makefile.netbsd-1.2	Sun Jan 24 14:42:46 1999
***************
*** 4,10 ****
  
  PROG=	pppd
  SRCS=	auth.c cbcp.c ccp.c chap.c chap_ms.c demand.c fsm.c ipcp.c \
! 	ipxcp.c lcp.c magic.c main.c options.c sys-bsd.c upap.c
  
  .PATH:	${PCAPDIR} ${.CURDIR}/../../sys/net
  MAN=	pppd.8 pppd.cbcp.8
--- 4,10 ----
  
  PROG=	pppd
  SRCS=	auth.c cbcp.c ccp.c chap.c chap_ms.c demand.c fsm.c ipcp.c \
! 	ipxcp.c lcp.c magic.c main.c options.c sys-bsd.c upap.c cbcps.c pppdradius.c libradius.c
  
  .PATH:	${PCAPDIR} ${.CURDIR}/../../sys/net
  MAN=	pppd.8 pppd.cbcp.8
diff -r -P -d -C 3 ppp-2.3.5/pppd/Makefile.osf ppp-2.3.5-2cbcps-radius-multiport/pppd/Makefile.osf
*** ppp-2.3.5/pppd/Makefile.osf	Wed Mar 25 06:27:00 1998
--- ppp-2.3.5-2cbcps-radius-multiport/pppd/Makefile.osf	Sun Jan 24 14:43:19 1999
***************
*** 7,16 ****
  MANDIR = /usr/local/man
  
  PPPDSRCS = main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c ccp.c \
! 	auth.c options.c demand.c sys-osf.c md4.c chap_ms.c
  
  PPPDOBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o \
! 	auth.o options.o demand.o sys-osf.o md4.o chap_ms.o
  
  CC = cc
  DEBUG_FLAGS = -DDEBUGALL
--- 7,16 ----
  MANDIR = /usr/local/man
  
  PPPDSRCS = main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c ccp.c \
! 	auth.c options.c demand.c sys-osf.c md4.c chap_ms.c cbcps.c pppdradius.c libradius.c
  
  PPPDOBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o \
! 	auth.o options.o demand.o sys-osf.o md4.o chap_ms.o cbcps.o pppdradius.o libradius.o
  
  CC = cc
  DEBUG_FLAGS = -DDEBUGALL
diff -r -P -d -C 3 ppp-2.3.5/pppd/Makefile.sol2 ppp-2.3.5-2cbcps-radius-multiport/pppd/Makefile.sol2
*** ppp-2.3.5/pppd/Makefile.sol2	Wed Mar 25 06:27:01 1998
--- ppp-2.3.5-2cbcps-radius-multiport/pppd/Makefile.sol2	Sun Jan 24 14:43:44 1999
***************
*** 11,17 ****
  all: pppd
  
  OBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o \
! 	auth.o options.o demand.o sys-svr4.o
  
  pppd:	$(OBJS)
  	$(CC) -o pppd $(OBJS) $(LIBS)
--- 11,17 ----
  all: pppd
  
  OBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o \
! 	auth.o options.o demand.o sys-svr4.o cbcps.o pppdradius.o libradius.o
  
  pppd:	$(OBJS)
  	$(CC) -o pppd $(OBJS) $(LIBS)
diff -r -P -d -C 3 ppp-2.3.5/pppd/Makefile.sunos4 ppp-2.3.5-2cbcps-radius-multiport/pppd/Makefile.sunos4
*** ppp-2.3.5/pppd/Makefile.sunos4	Wed Mar 25 06:27:03 1998
--- ppp-2.3.5-2cbcps-radius-multiport/pppd/Makefile.sunos4	Sun Jan 24 14:44:03 1999
***************
*** 12,18 ****
  all: pppd
  
  OBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o \
! 	auth.o options.o demand.o sys-sunos4.o
  
  pppd:	$(OBJS)
  	$(CC) -o pppd $(OBJS) $(LIBS)
--- 12,18 ----
  all: pppd
  
  OBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o \
! 	auth.o options.o demand.o sys-sunos4.o cbcps.o pppdradius.o libradius.o
  
  pppd:	$(OBJS)
  	$(CC) -o pppd $(OBJS) $(LIBS)
diff -r -P -d -C 3 ppp-2.3.5/pppd/Makefile.svr4 ppp-2.3.5-2cbcps-radius-multiport/pppd/Makefile.svr4
*** ppp-2.3.5/pppd/Makefile.svr4	Wed Mar 25 06:27:04 1998
--- ppp-2.3.5-2cbcps-radius-multiport/pppd/Makefile.svr4	Sun Jan 24 14:45:35 1999
***************
*** 11,17 ****
  all: pppd
  
  OBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o \
! 	auth.o options.o demand.o sys-svr4.o
  
  pppd:	$(OBJS)
  	$(CC) -o pppd $(OBJS) $(LIBS)
--- 11,17 ----
  all: pppd
  
  OBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o \
! 	auth.o options.o demand.o sys-svr4.o cbcps.o pppdradius.o libradius.o
  
  pppd:	$(OBJS)
  	$(CC) -o pppd $(OBJS) $(LIBS)
diff -r -P -d -C 3 ppp-2.3.5/pppd/Makefile.ultrix ppp-2.3.5-2cbcps-radius-multiport/pppd/Makefile.ultrix
*** ppp-2.3.5/pppd/Makefile.ultrix	Wed Mar 25 06:27:05 1998
--- ppp-2.3.5-2cbcps-radius-multiport/pppd/Makefile.ultrix	Sun Jan 24 14:45:23 1999
***************
*** 7,16 ****
  MANDIR = /usr/local/man
  
  PPPDSRCS = main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c ccp.c \
! 	auth.c options.c demand.c sys-ultrix.c
  
  PPPDOBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o \
! 	auth.o options.o demand.o sys-ultrix.o
  
  # CC = gcc
  DEBUG_FLAGS =
--- 7,16 ----
  MANDIR = /usr/local/man
  
  PPPDSRCS = main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c ccp.c \
! 	auth.c options.c demand.c sys-ultrix.c cbcps.c pppdradius.c libradius.c
  
  PPPDOBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o \
! 	auth.o options.o demand.o sys-ultrix.o cbcps.o pppdradius.o libradius.o
  
  # CC = gcc
  DEBUG_FLAGS =
diff -r -P -d -C 3 ppp-2.3.5/pppd/auth.c ppp-2.3.5-2cbcps-radius-multiport/pppd/auth.c
*** ppp-2.3.5/pppd/auth.c	Thu Mar 26 09:46:00 1998
--- ppp-2.3.5-2cbcps-radius-multiport/pppd/auth.c	Fri Dec  3 15:24:10 1999
***************
*** 68,73 ****
--- 68,74 ----
  #endif
  
  #include "pppd.h"
+ #include "cbcps.h"
  #include "fsm.h"
  #include "lcp.h"
  #include "ipcp.h"
***************
*** 77,82 ****
--- 78,84 ----
  #include "cbcp.h"
  #endif
  #include "pathnames.h"
+ #include "pppdradius.h"
  
  /* Used for storing a sequence of words.  Usually malloced. */
  struct wordlist {
***************
*** 102,107 ****
--- 104,110 ----
  /* Set if we have successfully called plogin() */
  static int logged_in;
  
+ int fd;
  /* Set if we have run the /etc/ppp/auth-up script. */
  static int did_authup;
  
***************
*** 117,122 ****
--- 120,128 ----
  /* Set if we got the contents of passwd[] from the pap-secrets file. */
  static int passwd_from_file;
  
+ /* we store here the user name for future use from akysposobppp() */
+ char user[256];
+ 
  /* Bits in auth_pending[] */
  #define PAP_WITHPEER	1
  #define PAP_PEER	2
***************
*** 127,133 ****
  
  /* Prototypes for procedures local to this file. */
  
! static void network_phase __P((int));
  static void check_idle __P((void *));
  static void connect_time_expired __P((void *));
  static int  plogin __P((char *, char *, char **, int *));
--- 133,140 ----
  
  /* Prototypes for procedures local to this file. */
  
! void network_phase __P((int));
! static void callback_phase __P((int));
  static void check_idle __P((void *));
  static void connect_time_expired __P((void *));
  static int  plogin __P((char *, char *, char **, int *));
***************
*** 165,170 ****
--- 172,179 ----
  	return;
      if (logged_in)
  	plogout();
+     if (radlogged_in) 
+         radlogout();
      phase = PHASE_DEAD;
      syslog(LOG_NOTICE, "Connection terminated.");
  }
***************
*** 233,238 ****
--- 242,255 ----
  	}
      }
  
+     if(*calleridtool) 
+         getcallerid(devnam);
+        /* if connection is ok, try to resolve caller's id */
+ 
+     if(*con_tool) 
+         getconstate(devnam);
+        /* get CONNECT string */
+ 
      phase = PHASE_AUTHENTICATE;
      auth = 0;
      if (go->neg_chap) {
***************
*** 256,269 ****
      }
      auth_pending[unit] = auth;
  
!     if (!auth)
! 	network_phase(unit);
  }
  
  /*
   * Proceed to the network phase.
   */
! static void
  network_phase(unit)
      int unit;
  {
--- 273,286 ----
      }
      auth_pending[unit] = auth;
  
!     if (!auth)  // ak neni auth tak priamo bez chap/pap ideme.
!        callback_phase(unit);
  }
  
  /*
   * Proceed to the network phase.
   */
! void
  network_phase(unit)
      int unit;
  {
***************
*** 308,313 ****
--- 325,361 ----
  	lcp_close(0, "No network protocols running");
  }
  
+ static void
+ callback_phase(int unit)   //faza callbacku ..  treba pozret ci sa moze obist.
+ {
+  lcp_options *wo=&lcp_wantoptions[unit];
+  lcp_options *go=&lcp_gotoptions[unit];
+ 
+  akysposobppp(user); /* figure out what callback options user has */
+ 
+  if(!cbcp_protent.enabled_flag) {
+            network_phase(unit);
+            return;
+     } // neni cb switch
+ 			// to sa pouzilo napr pri spatnom volani.
+  if(!wo->neg_cbcp || !go->neg_cbcp) {	//asi by stacilo len go pozerat.
+ /*
+   if(cbcp_priamo)      // smie sa obist nevylicitovanim ... inac je to podfuk.
+ */
+    network_phase(unit);             // pri licitacii alebo cez opt cb nepovolena
+ /*
+   else {
+    syslog(LOG_WARNING, "CBCP Nedovoleny pokus obist cb zlou licitaciu");
+    auth_peer_fail(unit,PPP_CBCP);
+    return;}
+ */
+   }
+  else {
+   phase = PHASE_CALLBACK;
+   cbcp_open(unit);        // toto ho prinuti poslat vyzvu ..
+  }
+ }
+ 
  /*
   * The peer has failed to authenticate himself using `protocol'.
   */
***************
*** 359,365 ****
       * proceed to the network (or callback) phase.
       */
      if ((auth_pending[unit] &= ~bit) == 0)
!         network_phase(unit);
  }
  
  /*
--- 407,414 ----
       * proceed to the network (or callback) phase.
       */
      if ((auth_pending[unit] &= ~bit) == 0)
!       { // syslog(LOG_DEBUG," bbo po auth_peer_success");
!        callback_phase(unit);}
  }
  
  /*
***************
*** 612,624 ****
      char **msg;
      int *msglen;
  {
!     int ret;
      char *filename;
      FILE *f;
      struct wordlist *addrs;
      u_int32_t remote;
      ipcp_options *ipwo = &ipcp_wantoptions[unit];
!     char passwd[256], user[256];
      char secret[MAXWORDLEN];
      static int attempts = 0;
  
--- 661,675 ----
      char **msg;
      int *msglen;
  {
!     int ret,i;
      char *filename;
      FILE *f;
+     char *tty;
      struct wordlist *addrs;
+     struct utmp utmp;
      u_int32_t remote;
      ipcp_options *ipwo = &ipcp_wantoptions[unit];
!     char passwd[256];
      char secret[MAXWORDLEN];
      static int attempts = 0;
  
***************
*** 630,636 ****
      BCOPY(auser, user, userlen);
      user[userlen] = '\0';
      *msg = (char *) 0;
! 
      /*
       * Open the file of pap secrets and scan for a suitable secret
       * for authenticating this user.
--- 681,687 ----
      BCOPY(auser, user, userlen);
      user[userlen] = '\0';
      *msg = (char *) 0;
!     akysposobppp(user);
      /*
       * Open the file of pap secrets and scan for a suitable secret
       * for authenticating this user.
***************
*** 638,661 ****
      filename = _PATH_UPAPFILE;
      addrs = NULL;
      ret = UPAP_AUTHACK;
      f = fopen(filename, "r");
      if (f == NULL) {
! 	syslog(LOG_ERR, "Can't open PAP password file %s: %m", filename);
! 	ret = UPAP_AUTHNAK;
  
      } else {
  	check_access(f, filename);
- 	remote = ipwo->accept_remote? 0: ipwo->hisaddr;
  	if (scan_authfile(f, user, our_name, remote,
  			  secret, &addrs, filename) < 0
  	    || (secret[0] != 0 && (cryptpap || strcmp(passwd, secret) != 0)
  		&& strcmp(crypt(passwd, secret), secret) != 0)) {
! 	    syslog(LOG_WARNING, "PAP authentication failure for %s", user);
  	    ret = UPAP_AUTHNAK;
  	}
  	fclose(f);
-     }
  
      if (uselogin && ret == UPAP_AUTHACK) {
  	ret = plogin(user, passwd, msg, msglen);
  	if (ret == UPAP_AUTHNAK) {
--- 689,729 ----
      filename = _PATH_UPAPFILE;
      addrs = NULL;
      ret = UPAP_AUTHACK;
+     remote = ipwo->accept_remote? 0: ipwo->hisaddr;
      f = fopen(filename, "r");
      if (f == NULL) {
! 	if(!useradius && !uselogin) {
!           syslog(LOG_ERR, "Can't open PAP password file %s: %m", filename);
! 	  ret = UPAP_AUTHNAK;
!       }
  
      } else {
+ 
  	check_access(f, filename);
  	if (scan_authfile(f, user, our_name, remote,
  			  secret, &addrs, filename) < 0
  	    || (secret[0] != 0 && (cryptpap || strcmp(passwd, secret) != 0)
  		&& strcmp(crypt(passwd, secret), secret) != 0)) {
! 	    syslog(LOG_WARNING, "upap: local base/pap-secrets authentication failure for %s", user);
  	    ret = UPAP_AUTHNAK;
  	}
+         else {
+     tty = devnam; 
+     if (strncmp(tty, "/dev/", 5) == 0)                                          
+         tty += 5;                                                               
+     for(i=0;i<sizeof(utmp.ut_name);i++) if(user[i]=='@') {user[i]=0;break;}
+     memset((void *)&utmp, 0, sizeof(utmp));                                     
+     (void)time(&utmp.ut_time);                                                  
+     (void)strncpy(utmp.ut_name,user, sizeof(utmp.ut_name));                     
+     if(cbcp_volit==1) (void)strncpy(utmp.ut_host, "CALLBACK", sizeof(utmp.ut_host));
+     else (void)strncpy(utmp.ut_host, "DIAL-IN", sizeof(utmp.ut_host));          
+     (void)strncpy(utmp.ut_line, tty, sizeof(utmp.ut_line));                     
+     login(&utmp);                                                               
+ 
+         }
  	fclose(f);
  
+     }
      if (uselogin && ret == UPAP_AUTHACK) {
  	ret = plogin(user, passwd, msg, msglen);
  	if (ret == UPAP_AUTHNAK) {
***************
*** 663,668 ****
--- 731,743 ----
  	}
      }
  
+         if (useradius)                                                        
+         {                                                                     
+             ret = radlogin(user, passwd);                                     
+             if (ret == UPAP_AUTHNAK)                                          
+                 syslog(LOG_WARNING, "upap radius login failure for %s", user);
+         }                                                                     
+ 
      if (ret == UPAP_AUTHNAK) {
          if (*msg == (char *) 0)
  	    *msg = "Login incorrect";
***************
*** 687,692 ****
--- 762,768 ----
  	if (*msg == (char *) 0)
  	    *msg = "Login ok";
  	*msglen = strlen(*msg);
+ syslog(LOG_ERR,"set_allowed_addrs: unit=%d, addr=%s",unit,addrs);
  	set_allowed_addrs(unit, addrs);
      }
  
***************
*** 777,782 ****
--- 853,861 ----
      int *msglen;
  {
  
+     int i;
+     struct utmp utmp;
+ 
  #ifdef USE_PAM
  
      struct pam_conv pam_conversation;
***************
*** 882,887 ****
--- 961,978 ----
  	tty += 5;
      logwtmp(tty, user, remote_name);		/* Add wtmp login entry */
  
+     for(i=0;i<sizeof(utmp.ut_name);i++) 
+          if(user[i]=='@') {user[i]=0;break;}
+     memset((void *)&utmp, 0, sizeof(utmp));
+     (void)time(&utmp.ut_time);
+     (void)strncpy(utmp.ut_name,user, sizeof(utmp.ut_name));
+     (void)strncpy(utmp.ut_line, tty, sizeof(utmp.ut_line));
+     if(cbcp_volit==1) 
+          (void)strncpy(utmp.ut_host, "CALLBACK", sizeof(utmp.ut_host));
+     else (void)strncpy(utmp.ut_host, "DIAL-IN", sizeof(utmp.ut_host));
+     login(&utmp);
+ 
+ 
  #if defined(_PATH_LASTLOG)
      {
  	    struct lastlog ll;
***************
*** 1107,1112 ****
--- 1198,1206 ----
      addrs = NULL;
      secbuf[0] = 0;
  
+     BCOPY(client,cbcpuser,strlen(client)>19 ? 19: strlen(client));
+     cbcpuser[19]=0;
+     if (akysposobppp(cbcpuser)<1) return 0;
      f = fopen(filename, "r");
      if (f == NULL) {
  	syslog(LOG_ERR, "Can't open chap secret file %s: %m", filename);
***************
*** 1197,1203 ****
  	return 0;
  
      if (addrs == NULL)
! 	return !auth_required;		/* no addresses authorized */
  
      for (; addrs != NULL; addrs = addrs->next) {
  	/* "-" means no addresses authorized, "*" means any address allowed */
--- 1291,1297 ----
  	return 0;
  
      if (addrs == NULL)
! 	return -1; // what the fucking animal did this: !auth_required;		/* no addresses authorized */
  
      for (; addrs != NULL; addrs = addrs->next) {
  	/* "-" means no addresses authorized, "*" means any address allowed */
diff -r -P -d -C 3 ppp-2.3.5/pppd/callerid.c ppp-2.3.5-2cbcps-radius-multiport/pppd/callerid.c
*** ppp-2.3.5/pppd/callerid.c	Thu Jan  1 05:00:00 1970
--- ppp-2.3.5-2cbcps-radius-multiport/pppd/callerid.c	Thu Aug 19 15:38:50 1999
***************
*** 0 ****
--- 1,33 ----
+ /*
+  *   Implimentation of Caller's ID
+  *   by Ruslan Zalata, 1999, rz@tyumen.ru
+  */
+ #include <stdio.h>
+ #include <string.h>
+ #include <sys/types.h>
+ #include <sys/time.h>
+ #include <syslog.h>
+ 
+ #include "pppd.h"
+ 
+ void getcallerid(char *device)
+ {
+    int fd[2];
+    int i,pid,status;
+ 
+    pipe(fd);
+ 
+    if((pid=fork())==NULL) {
+     close(1);
+     dup(fd[1]);
+     if(execlp(calleridtool,calleridtool,device,NULL) == -1) 
+       syslog(LOG_ERR,"Can't execute %s",calleridtool);
+    }
+ 
+   read(fd[0],&callerid,16);
+   wait(&status);
+   for(i=0;i<16;i++) if(callerid[i]==13 || callerid[i]==10) callerid[i]=0;  
+   callerid[15]=0;
+ 
+   syslog(LOG_WARNING,"Caller's ID is: %s",callerid);
+ }
diff -r -P -d -C 3 ppp-2.3.5/pppd/cbcps.c ppp-2.3.5-2cbcps-radius-multiport/pppd/cbcps.c
*** ppp-2.3.5/pppd/cbcps.c	Thu Jan  1 05:00:00 1970
--- ppp-2.3.5-2cbcps-radius-multiport/pppd/cbcps.c	Sun Aug 15 16:35:47 1999
***************
*** 0 ****
--- 1,284 ----
+ /*
+  * cbcps - Call Back Configuration Protocol. SERVER
+  * Miro Bobovsky , 7.11.1998 ver2.0
+  * robte s tym co chete - GPL a lubovolny iny vse povoliaci.
+  * ocakavam za pppd prepinac auth +chap -pap cb ip:ip 
+  * ocakavam subor /etc/ppp/callbusers kde su user (nestaci chap-s) 
+  * s patricnym sytaxom meno!P!V!A!cislo!.
+  * snazim sa spustit /etc/ppp/callbackser pre volanie. (pppd chat).
+ */
+ #include <stdio.h>
+ #include <string.h>
+ #include <sys/types.h>
+ #include <sys/time.h>
+ #include <syslog.h>
+ 
+ #include "pppd.h"
+ #include "fsm.h"
+ #include "lcp.h"
+ #include "ipcp.h"
+ #include "cbcps.h"
+  
+ extern void network_phase __P((int));
+ 
+ void cbcp_recvresp(cbcp_state *us, char *pckt, int len);
+ void cbcp_sendack(cbcp_state *us,u_char type,u_char delay );
+ 
+ cbcp_state cbcp[NUM_PPP];
+ char cbcpuser[20];
+ int cbcp_priamo=1,cbcp_volit=0,cbcp_admin=0;
+ char cbcp_adminn[]="********************";
+ struct protent cbcp_protent = {
+     PPP_CBCP,
+     cbcp_init,
+     cbcp_input,
+     cbcp_protrej,
+     cbcp_lowerup,
+     NULL,
+     cbcp_open,
+     NULL,
+     cbcp_printpkt,
+     NULL,
+     0,
+     "CBCP",
+     NULL,
+     NULL,
+     NULL
+ };
+ 
+ 
+ void cbcp_lowerup(int iface)	//vola lcp.c
+ {
+ LCPDEBUG((LOG_DEBUG," bbo cbcp_lowerup"));
+ }
+ 
+ void cbcp_init(int iface)	// z main.c
+ {
+     cbcp_state *us;
+ 
+     LCPDEBUG((LOG_DEBUG," bbo cbcp_init"));
+     cbcpuser[0]=0;
+     cbcp_volit=cbcp_admin=0;
+     cbcp_priamo=1;
+     cbcp_adminn[0]=0;
+     us = &cbcp[iface];
+     memset(us, 0, sizeof(cbcp_state));
+     us->us_unit = iface;
+ }
+ 
+ void cbcp_open(int unit)  //z auth -- startuje cbcp komunikaciu
+ {
+     u_char buf[256];
+     u_char *bufp = buf;
+     u_char *outp;
+     int outlen;
+     cbcp_state *us = &cbcp[unit];
+ 
+     us->us_id = 1;
+     outp = outpacket_buf;
+     outlen=4;                //hlavicka
+     if(cbcp_priamo) { outlen+=2;
+       PUTCHAR(CB_CONF_NO, bufp);PUTCHAR(2 , bufp);}
+     if(cbcp_volit) { outlen+=5;
+       PUTCHAR(CB_CONF_USER, bufp);PUTCHAR(5 , bufp); //typ,dlzka
+       PUTCHAR(0, bufp);PUTCHAR(1, bufp);PUTCHAR(0, bufp);} //delay,atyp,cisloZ
+     if(cbcp_admin) { outlen+=2;
+       PUTCHAR(CB_CONF_ADMIN, bufp);PUTCHAR(2 , bufp);}
+     LCPDEBUG((LOG_DEBUG, "bbo cbcp_open"));
+     MAKEHEADER(outp, PPP_CBCP);  // a dorobim paket , dlzky a ...
+     PUTCHAR(CBCP_REQ, outp);  // prikaz
+     PUTCHAR(us->us_id,outp); //id
+     PUTSHORT(outlen, outp);       // IBAZE WINNT posiela to kazde 2 sek.
+     BCOPY(buf, outp, outlen-4);   // s novym id a ja len raz .. ale ide.
+     output(1, outpacket_buf, outlen + PPP_HDRLEN);
+ }
+ 
+ void cbcp_close(int unit)
+ {
+     LCPDEBUG((LOG_DEBUG, "bbo cbcp_close"));
+ }
+ 
+ /* process an incomming packet */
+ void cbcp_input(int unit, u_char *inpacket, int pktlen)
+ {
+     u_char *inp;
+     u_char code, id;
+     u_short len;
+ 
+     cbcp_state *us = &cbcp[unit];
+     inp = inpacket;
+     LCPDEBUG((LOG_DEBUG," bbo cbcp_input"));
+     if (pktlen < CBCP_MINLEN) {
+         syslog(LOG_ERR, "CBCP packet is too small");
+         return;
+     }
+ 
+     GETCHAR(code, inp);
+     GETCHAR(id, inp);
+     GETSHORT(len, inp);
+ 
+     if (len > pktlen) {
+         syslog(LOG_ERR, "CBCP packet: invalid length");
+         return;
+     }
+ 
+     len -= CBCP_MINLEN;
+ 
+     switch(code) {
+     case CBCP_REQ:	// toto je neosetrene bo nema co prist.
+         syslog(LOG_ERR, "CBCP_REQ received !!!!");
+         break;
+ 
+     case CBCP_RESP:
+         LCPDEBUG((LOG_DEBUG, "CBCP_RESP received"));
+         if (id != us->us_id)
+           syslog(LOG_ERR,"CBCP RESP zle id, caka %d dostal %d",us->us_id,id);
+         cbcp_recvresp(us,inp,len);
+         break;
+ 
+     case CBCP_ACK:    // toto je neosetrene bo nema co prist.
+         syslog(LOG_ERR, "CBCP_ACK received !!!!");
+         break;
+ 
+     default:
+         break;
+     }
+ }
+ 
+ /* protocol was rejected by foe */
+ void cbcp_protrej(int iface)
+ {
+    LCPDEBUG((LOG_DEBUG," bbo cbcp_protrej"));
+ }
+ int cbcp_printpkt(u_char *p, int plen,
+                    void (*printer) __P((void *, char *, ...)),
+                    void *arg)
+ {
+  LCPDEBUG((LOG_DEBUG," bbo cbcp_printpkt"));
+  return 0; //urcite zle lebo mal vratit kolko asi pochopil znakov.
+ }
+ 
+ void cbcp_recvresp(cbcp_state *us, char *pckt, int len)
+ {
+     u_char type, delay=0, addr_type;
+     int opt_len,dlzka;
+ 
+     if (len<2) {  
+         syslog(LOG_ERR, "CBCP recvresp: kratky, %d",len);
+         phase=PHASE_TERMINATE; return;}
+ 
+       GETCHAR(type, pckt);
+       GETCHAR(opt_len, pckt);
+ 
+       if (opt_len > 2)
+           GETCHAR(delay, pckt);
+       switch(type) {
+        case CB_CONF_NO:
+          if(cbcp_admin)
+           {syslog(LOG_ERR,"CBCP got CB_CONF_NO while cbcp_admin is set");
+            phase=PHASE_TERMINATE; type=CB_CONF_NOT_ALLOWED; break;}
+ /*         if(!cbcp_priamo)
+           {syslog(LOG_ERR, "CBCP Podvadza - vratil co som nenukal");
+            phase=PHASE_TERMINATE; return;}
+ */
+          break;
+        case CB_CONF_ADMIN:
+          if(!cbcp_admin)
+           {syslog(LOG_ERR, "CBCP Podvadza - vratil co som nenukal");
+            phase=PHASE_TERMINATE; return;}
+          break;
+        default:   // t.j. asi voli ale pozreme.
+ 	 if(!cbcp_volit)
+           {syslog(LOG_ERR, "CBCP Podvadza - vratil co som nenukal");
+            phase=PHASE_TERMINATE; return;}
+ 	 if(opt_len>4) {
+ 	   GETCHAR(addr_type, pckt);
+            dlzka=opt_len - 4<20?opt_len - 4:19;
+            memcpy(cbcp_adminn, pckt, dlzka);
+            cbcp_adminn[dlzka]=0;
+            LCPDEBUG((LOG_DEBUG, "mam cislo: %s", cbcp_adminn));
+ 	 }
+       }
+       cbcp_sendack(us,type,delay);      
+ }
+ 
+ void cbcp_sendack( cbcp_state *us,u_char type,u_char delay )
+ {
+     u_char buf[256];
+     u_char *bufp = buf;
+     int len = 0;
+     u_char *outp;
+     int outlen;
+ 
+     outp = outpacket_buf;
+     switch(type) {
+      case CB_CONF_NO:
+ 	len=2;PUTCHAR(CB_CONF_NO, bufp);PUTCHAR(len , bufp);
+         break;
+      case CB_CONF_USER:
+         len=strlen(cbcp_adminn)+5;
+ 	PUTCHAR(CB_CONF_USER, bufp);PUTCHAR(len, bufp);PUTCHAR(delay, bufp);
+ 	PUTCHAR(1, bufp);BCOPY(cbcp_adminn,bufp,len-5);bufp+=len-5;
+ 	PUTCHAR(0, bufp);break;
+      case CB_CONF_ADMIN:
+ 	len=3;PUTCHAR(CB_CONF_ADMIN,bufp);PUTCHAR(len,bufp);PUTCHAR(delay,bufp);
+ 	break;
+      default:
+ 	syslog(LOG_ERR, "CBCP Podvadza - v type");
+         phase=PHASE_TERMINATE; break;
+     }
+     LCPDEBUG((LOG_DEBUG, "bbo cbcp_sendack"));
+     outlen = 4 + len;
+     MAKEHEADER(outp, PPP_CBCP);
+     PUTCHAR(CBCP_ACK, outp);
+     PUTCHAR(us->us_id,outp);
+     PUTSHORT(outlen, outp);
+     BCOPY(buf, outp, len);
+     output(1, outpacket_buf, outlen + PPP_HDRLEN);
+     if(phase != PHASE_TERMINATE) network_phase(us->us_unit);
+ 
+ if(type==CB_CONF_ADMIN || type==CB_CONF_USER){ //spustenie programu na volanie
+ char *argv[4];
+     argv[0] = "/etc/ppp/callbackser";    //progam
+     argv[1] = devnam;		// /dev/ttyS?
+     argv[2] = cbcpuser;    //ID
+     argv[3] = cbcp_adminn;        // cislo
+     argv[4] = user;
+     argv[5] = NULL;
+     run_program(argv[0], argv, 0);
+  }
+ }
+ 
+ int akysposobppp(char *kto)
+ {
+  FILE *fp;
+  char *a,*b;
+  char riadok[81];
+ 
+  cbcp_volit=cbcp_admin=0;
+  cbcp_priamo=1;
+  cbcp_adminn[0]=0;
+  if(strlen(kto)<2) {syslog(LOG_ERR,"CBCP - kratke meno"); return 0;}
+  if((fp=fopen("/etc/ppp/callbusers","r"))==NULL)
+    {syslog(LOG_ERR,"CBCP neviem otvorit callbusers");return 0;}
+  while(fgets(riadok,80,fp)!=NULL){
+    if( *riadok=='#' ) continue;
+    if( (a=strchr(riadok,'!'))!=NULL ) *(a++)=0;
+    if(strcmp(riadok,kto)==0) {
+     if( strlen(a)<5 ) {syslog(LOG_ERR,"CBCP chybny riadok");
+ 		       fclose(fp);return 0;}
+     if( *(a++)=='P') {a++;cbcp_priamo=1;}
+     if( *(a++)=='V') {a++;cbcp_volit=1;cbcp_priamo=0;}
+     if( *(a++)=='A') {
+ 	a++;
+ 	if( (b=strchr(a,'!'))!=NULL ) 
+ 	  {*b=0;strncpy(cbcp_adminn,a,20);cbcp_admin=1;}
+ 	}
+     fclose(fp); 
+     syslog(LOG_INFO,"meno:%s P:%d V:%d A:%d cislo:[%s]\n",
+ 	kto,cbcp_priamo,cbcp_volit,cbcp_admin,cbcp_adminn);
+      return 1;}
+  }
+  fclose(fp);syslog(LOG_ERR,"CBCP neni v callbusers");return 0;
+ }
+ 
diff -r -P -d -C 3 ppp-2.3.5/pppd/cbcps.h ppp-2.3.5-2cbcps-radius-multiport/pppd/cbcps.h
*** ppp-2.3.5/pppd/cbcps.h	Thu Jan  1 05:00:00 1970
--- ppp-2.3.5-2cbcps-radius-multiport/pppd/cbcps.h	Sun Aug 15 15:56:04 1999
***************
*** 0 ****
--- 1,40 ----
+ /*
+  * cbcps - Call Back Configuration Protocol. SERVER
+  * Miro Bobovsky , 7.11.1998 ver2.0
+  * robte s tym co chete - GPL a lubovolny iny vse povoliaci.
+ */
+  
+ #define PPP_CBCP        0xc029  /* Callback Control Protocol */
+ typedef struct cbcp_state {
+     int    us_unit;     /* Interface unit number */
+     u_char us_id;               /* Current id */
+ } cbcp_state;
+ 
+ void cbcp_init      __P((int));
+ void cbcp_open      __P((int));
+ void cbcp_lowerup   __P((int));
+ void cbcp_input     __P((int, u_char *, int));
+ void cbcp_protrej   __P((int));
+ int  cbcp_printpkt  __P((u_char *, int,void (*) __P((void *, char *, ...)),
+                             void *));
+ extern cbcp_state cbcp[];
+ extern struct protent cbcp_protent;
+ extern char cbcpuser[];
+ extern int cbcp_volit;		// ci sme si uzer volit callb cislo
+ extern int cbcp_admin;		// cislo zadava admin a user ho ani nevie.
+ extern int cbcp_priamo;	// smie ist bez callbacku.
+ extern char cbcp_adminn[];	// cislo (ad admina alebo od usera ak moze.
+ int akysposobppp(char *kto);	// fcia co pozera callbusers a nastavi param.
+ 
+ #define CBCP_MINLEN 4
+ 
+ #define CBCP_REQ    1
+ #define CBCP_RESP   2
+ #define CBCP_ACK    3
+ 
+ #define CB_CONF_NO     1
+ #define CB_CONF_USER   2
+ #define CB_CONF_ADMIN  3
+ #define CB_CONF_LIST   4
+ #define CB_CONF_NOT_ALLOWED  254 
+ 
diff -r -P -d -C 3 ppp-2.3.5/pppd/chap.c ppp-2.3.5-2cbcps-radius-multiport/pppd/chap.c
*** ppp-2.3.5/pppd/chap.c	Thu Nov 27 11:07:48 1997
--- ppp-2.3.5-2cbcps-radius-multiport/pppd/chap.c	Sun Jan 24 14:36:52 1999
***************
*** 579,584 ****
--- 579,585 ----
      ChapSendStatus(cstate, code);
  
      if (code == CHAP_SUCCESS) {
+         syslog(LOG_NOTICE, "CHAP %s login ok:%s",devnam,rhostname);
  	old_state = cstate->serverstate;
  	cstate->serverstate = CHAPSS_OPEN;
  	if (old_state == CHAPSS_INITIAL_CHAL) {
***************
*** 590,595 ****
--- 591,597 ----
  	       rhostname);
  
      } else {
+         syslog(LOG_NOTICE, "CHAP %s login error:%s",devnam,rhostname);
  	syslog(LOG_ERR, "CHAP peer authentication failed for remote host %s",
  	       rhostname);
  	cstate->serverstate = CHAPSS_BADAUTH;
diff -r -P -d -C 3 ppp-2.3.5/pppd/con_state.c ppp-2.3.5-2cbcps-radius-multiport/pppd/con_state.c
*** ppp-2.3.5/pppd/con_state.c	Thu Jan  1 05:00:00 1970
--- ppp-2.3.5-2cbcps-radius-multiport/pppd/con_state.c	Thu Aug 19 15:45:32 1999
***************
*** 0 ****
--- 1,33 ----
+ /*
+  *   Implimentation of 'Get connection string from mgetty log' 
+  *   by Ruslan Zalata, 1999, rz@tyumen.ru
+  */
+ #include <stdio.h>
+ #include <string.h>
+ #include <sys/types.h>
+ #include <sys/time.h>
+ #include <syslog.h>
+ 
+ #include "pppd.h"
+ 
+ void getconstate(char *device)
+ {
+    int fd[2];
+    int i,pid,status;
+ 
+    pipe(fd);
+ 
+    if((pid=fork())==NULL) {
+     close(1);
+     dup(fd[1]);
+     if(execlp(con_tool,con_tool,device,NULL) == -1)
+       syslog(LOG_ERR,"Can't execute %s",con_tool);
+    }
+ 
+   read(fd[0],&con_state,32);
+   wait(&status);
+   for(i=0;i<32;i++) if(con_state[i]==13 || con_state[i]==10) con_state[i]=0;  
+   con_state[31]=0;
+ 
+   syslog(LOG_WARNING,"Caller's CONNECT: %s",con_state);
+ }
diff -r -P -d -C 3 ppp-2.3.5/pppd/ipcp.c ppp-2.3.5-2cbcps-radius-multiport/pppd/ipcp.c
*** ppp-2.3.5/pppd/ipcp.c	Wed Apr 29 05:38:10 1998
--- ppp-2.3.5-2cbcps-radius-multiport/pppd/ipcp.c	Sun Jan 24 14:36:51 1999
***************
*** 134,139 ****
--- 134,146 ----
  #define CODENAME(x)	((x) == CONFACK ? "ACK" : \
  			 (x) == CONFNAK ? "NAK" : "REJ")
  
+ /*
+  * Added to allow static and dynamic ips(s)
+  * Hold the static address from pap-secrets
+  */
+ u_int32_t staticaddr;
+ /******************************************/
+ 
  
  /*
   * Make a string representation of a network IP address.
***************
*** 824,829 ****
--- 831,845 ----
  		orc = CONFNAK;
  		if (!reject_if_disagree) {
  		    DECPTR(sizeof(u_int32_t), p);
+ 	
+ 	    /*
+ 	     * Added to allow static and dynamic ip(s) 
+ 	     * Are they asking for their static ip from pap-secrets?
+ 	     */
+ 	    if(ciaddr1 !=0 && ciaddr1 == staticaddr)
+ 	       wo->hisaddr = staticaddr;      /* Let them use the static ip */
+ 	    /*******************************************/	
+ 	
  		    tl = ntohl(wo->hisaddr);
  		    PUTLONG(tl, p);
  		}
***************
*** 885,890 ****
--- 901,915 ----
  		orc = CONFNAK;
  		if (!reject_if_disagree) {
  		    DECPTR(sizeof(u_int32_t), p);
+ 	
+ 	    /*
+ 	     * Added to allow static and dynamic ip(s) 
+ 	     * Are they asking for their static ip from pap-secrets?
+ 	     */
+ 	    if(ciaddr1 !=0 && ciaddr1 == staticaddr)
+ 	       wo->hisaddr = staticaddr;      /* Let them use the static ip */
+ 	    /*******************************************/
+ 	         
  		    tl = ntohl(wo->hisaddr);
  		    PUTLONG(tl, p);
  		}
diff -r -P -d -C 3 ppp-2.3.5/pppd/ipcp.h ppp-2.3.5-2cbcps-radius-multiport/pppd/ipcp.h
*** ppp-2.3.5/pppd/ipcp.h	Wed Apr 29 05:38:11 1998
--- ppp-2.3.5-2cbcps-radius-multiport/pppd/ipcp.h	Sun Jan 24 14:36:51 1999
***************
*** 67,70 ****
--- 67,76 ----
  
  char *ip_ntoa __P((u_int32_t));
  
+ /* Added to allow static and dynamic ip(s).
+  * Holds the static ip from pap-secrets
+  */
+ u_int32_t staticaddr;
+ /******************************************/
+ 
  extern struct protent ipcp_protent;
diff -r -P -d -C 3 ppp-2.3.5/pppd/ipxcp.c ppp-2.3.5-2cbcps-radius-multiport/pppd/ipxcp.c
*** ppp-2.3.5/pppd/ipxcp.c	Wed Mar 25 08:08:16 1998
--- ppp-2.3.5-2cbcps-radius-multiport/pppd/ipxcp.c	Sun Jan 24 14:36:51 1999
***************
*** 146,152 ****
  {
      short int  external;
  
!     if (internal & IPX_NONE)
          external = IPX_NONE;
      else
          external = RIP_SAP;
--- 146,152 ----
  {
      short int  external;
  
!     if (internal & BIT(IPX_NONE))
          external = IPX_NONE;
      else
          external = RIP_SAP;
***************
*** 532,540 ****
  	ACKCINETWORK  (IPX_NETWORK_NUMBER,  go->neg_nn,	    go->our_network);
  	ACKCINODE     (IPX_NODE_NUMBER,	    go->neg_node,   go->our_node);
  	ACKCINAME     (IPX_ROUTER_NAME,	    go->neg_name,   go->name);
! 	ACKCIPROTO    (IPX_ROUTER_PROTOCOL, go->neg_router, go->router);
! 	ACKCIPROTO    (IPX_ROUTER_PROTOCOL, go->neg_router, go->router);
! 	ACKCIPROTO    (IPX_ROUTER_PROTOCOL, go->neg_router, go->router);
  /*
   * This is the end of the record.
   */
--- 532,539 ----
  	ACKCINETWORK  (IPX_NETWORK_NUMBER,  go->neg_nn,	    go->our_network);
  	ACKCINODE     (IPX_NODE_NUMBER,	    go->neg_node,   go->our_node);
  	ACKCINAME     (IPX_ROUTER_NAME,	    go->neg_name,   go->name);
! 	if (len > 0)
! 		ACKCIPROTO    (IPX_ROUTER_PROTOCOL, go->neg_router, go->router);
  /*
   * This is the end of the record.
   */
diff -r -P -d -C 3 ppp-2.3.5/pppd/lcp.c ppp-2.3.5-2cbcps-radius-multiport/pppd/lcp.c
*** ppp-2.3.5/pppd/lcp.c	Thu Nov 27 11:08:44 1997
--- ppp-2.3.5-2cbcps-radius-multiport/pppd/lcp.c	Sun Aug 15 14:53:42 1999
***************
*** 1398,1403 ****
--- 1398,1412 ----
  	    }
  	    ho->neg_accompression = 1;
  	    break;
+ 	case  CI_CALLBACK:   // on mi ponuka cbcp a co ja na to.
+ 	    LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd Bbo callback"));
+ 	    if (!ao->neg_cbcp ||
+ 		cilen != CILEN_CBCP) {
+ 		orc = CONFREJ;
+ 		break;
+ 	    }
+             ho->neg_cbcp = 1;
+            break;
  
  	default:
  	    LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd unknown option %d",
diff -r -P -d -C 3 ppp-2.3.5/pppd/libradius.c ppp-2.3.5-2cbcps-radius-multiport/pppd/libradius.c
*** ppp-2.3.5/pppd/libradius.c	Thu Jan  1 05:00:00 1970
--- ppp-2.3.5-2cbcps-radius-multiport/pppd/libradius.c	Thu Aug 19 15:48:52 1999
***************
*** 0 ****
--- 1,421 ----
+ /*   Copyright (c) 1997      Cyril A. Vechera      St.-Petersburg, RUSSIA
+  *
+  *  Redistribution and use in source and binary forms, with or without
+  *  modification, are permitted provided that the following conditions
+  *  are met:
+  *  1. Redistributions of source code must retain the above copyright
+  *     notice, this list of conditions and the following disclaimer.
+  *  2. Redistributions in binary form must reproduce the above copyright
+  *     notice, this list of conditions and the following disclaimer in the
+  *     documentation and/or other materials provided with the distribution.
+  *  3. The name of the author may not be used to endorse or promote products
+  *     derived from this software without specific prior written permission.
+  *  4. Any form of use of source and binaries are permitted only for
+  *     noncommercial purpose. Any forms of commercial usage require
+  *     direct author's permission.
+  */
+ 
+ /*			RADIUS-client library
+ */
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <string.h>
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+ #include <time.h>
+ #include <sys/time.h>
+ 
+ #include "radius.h"
+ #include "libradius.h"
+ 
+ /*************************************************************************/
+ 
+ /* macro definitions for construction your own RADIUS packets */
+ /* usially, requires two arguments - ptr (the place where we should insert
+    atribute and value. Note, that ptr must be a lvalue */
+ 
+ /* User Name */
+ #define RADINS_USER_NAME(ptr, value) \
+ 	*ptr++ = PW_USER_NAME; \
+ 	*ptr++ = strlen(value) + 2; \
+ 	strcpy (ptr, value); \
+ 	ptr += strlen(value);
+ 
+ /* Calling-Station-ID */
+ #define RADINS_CALLING_STATION_ID(ptr, value) \
+ 	*ptr++ = PW_CALLING_STATION_ID; \
+ 	*ptr++ = strlen(value) + 2; \
+ 	strcpy (ptr, value); \
+ 	ptr += strlen(value);
+ 
+ /* State / connection string */
+ #define RADINS_STATE(ptr, value) \
+ 	*ptr++ = PW_STATE; \
+ 	*ptr++ = strlen(value) + 2; \
+ 	strcpy (ptr, value); \
+ 	ptr += strlen(value);
+ 
+ /* NAS-IP-Address */
+ #define RADINS_NAS_IP_ADDRESS(ptr, value) \
+ 	*ptr++ = PW_NAS_IP_ADDRESS; \
+ 	*ptr++ = 6; \
+ 	memcpy(ptr, value, 4); \
+ 	ptr += 4;
+ 
+ /* NAS-Port */
+ #define RADINS_NAS_PORT(ptr, value) \
+ 	*ptr++ = PW_NAS_PORT; \
+ 	*ptr++ = 6; \
+ 	*(u_long *)ptr = htonl (value); \
+ 	ptr += 4;
+ 
+ /* Acct-Status-Type */
+ #define RADINS_ACCT_STATUS_TYPE(ptr, value) \
+ 	*ptr++ = PW_ACCT_STATUS_TYPE; \
+ 	*ptr++ = 6; \
+ 	*(u_long *)ptr = htonl(value); \
+ 	ptr += 4;
+ 
+ /* Acct-Session-Id */
+ #define RADINS_ACCT_SESSION_ID(ptr, value) \
+ 	*ptr++ = PW_ACCT_SESSION_ID; \
+ 	*ptr++ = 2+strlen(value); \
+ 	strcpy (ptr, value); \
+ 	ptr += strlen (value);
+ 
+ /* Acct-Session-Time */
+ #define RADINS_ACCT_SESSION_TIME(ptr, value) \
+ 	*ptr++ = PW_ACCT_SESSION_TIME; \
+ 	*ptr++ = 6; \
+ 	*(u_long *)ptr = htonl(value); \
+ 	ptr += 4;
+ 
+ /* Service-Type */
+ #define RADINS_SERVICE_TYPE(ptr, value) \
+ 	*ptr++ = PW_SERVICE_TYPE; \
+ 	*ptr++ = 6; \
+ 	*(u_long *) ptr = htonl(value); \
+ 	ptr += 4;
+ 
+ /* Framed-Protocol */
+ #define RADINS_FRAMED_PROTOCOL(ptr, value) \
+ 	*ptr++ = PW_FRAMED_PROTOCOL; \
+ 	*ptr++ = 6; \
+ 	*(u_long *)ptr = htonl(value); \
+ 	ptr += 4;
+ 
+ /* User Password */
+ #define RADINS_USER_PASSWORD(ptr, value, auth) \
+ 	*ptr++ = PW_USER_PASSWORD; \
+ 	*ptr++ = 18; \
+ 	radius_encrypt_password(ptr, value, auth); \
+ 	ptr += 16;
+ 
+ 
+ 
+ int			radius_retry_max = RADLIB_DEFAULT_RETRY_MAX;
+ char			radius_secret[16] = "\0";
+ struct sockaddr_in	radius_me = {0, PF_INET, 0, {0}, "\0\0\0\0\0\0\0\0"};
+ struct sockaddr_in	radius_server = {0, PF_INET, 0, {0}, "\0\0\0\0\0\0\0\0"};
+ struct sockaddr_in	radius_servac = {0, PF_INET, 0, {0}, "\0\0\0\0\0\0\0\0"};
+ struct timeval		radius_timeout = {RADLIB_DEFAULT_TIMEOUT, 0};
+ int			radius_id = 0;
+ time_t			radius_session_start_time;
+ char			radius_session_id[254];
+ int			radius_accounting = 0;
+ int			radius_debug = 0;
+ 
+ /* initialization of all variables needed for the RADIUS access routines.
+    local ip-addres for source, address and port of a RADIUS-server,
+    shared secret */
+ 
+ int radius_init (char *config_file)
+ {
+ 	FILE * fil;
+ 	char argnam[128];
+ 	char argval[128];
+ 	
+ 	if ( (fil = fopen (config_file, "r")) == NULL)
+ 		return (0);
+ 	radius_server.sin_port = htons(RADLIB_DEFAULT_RADIUS_PORT);
+ 	radius_servac.sin_port = htons(RADLIB_DEFAULT_RADACC_PORT);
+ 	while ( !feof (fil) )
+ 	{
+ 		fscanf (fil, "%s %s\n", argnam, argval);
+ 		if ( !strcasecmp (argnam, "secret"))
+ 			strncpy (radius_secret, argval, 16);
+ 		else
+ 		if ( !strcasecmp (argnam, "retry_max"))
+ 			radius_retry_max = atoi (argval);
+ 		else
+ 		if ( !strcasecmp (argnam, "timeout"))
+ 			radius_timeout.tv_sec = atoi (argval);
+ 		else
+ 		if ( !strcasecmp (argnam, "my_address"))
+ 			radius_me.sin_addr.s_addr = inet_addr (argval);
+ 		else
+ 		if ( !strcasecmp (argnam, "rs_address"))
+ 			radius_server.sin_addr.s_addr = inet_addr (argval);
+ 		else
+ 		if ( !strcasecmp (argnam, "rs_port"))
+ 			radius_server.sin_port = htons (atoi(argval));
+ 		if ( !strcasecmp (argnam, "ra_address"))
+ 		{
+ 			radius_accounting = 1;
+ 			radius_servac.sin_addr.s_addr = inet_addr (argval);
+ 		}
+ 		else
+ 		if ( !strcasecmp (argnam, "ra_port"))
+ 			radius_servac.sin_port = htons (atoi(argval));
+ 	}
+ 
+ 	radius_session_start_time = time (NULL);
+ 
+ /* session identifier  =  ip_addr + pid + time */
+ 	sprintf(radius_session_id, "%s %u %s",
+ 		 inet_ntoa (radius_me.sin_addr),
+ 		 getpid(),
+ 		 ctime(&radius_session_start_time));
+ 	return (1);
+ }
+ 
+ /* sends the query to a RADIUS server, waits an answer and returns it */
+ int radius_send_query (u_char *packet, u_char *reply, struct sockaddr_in *whom)
+ {
+ #define ERROR(x) {printf(x); return(0);}
+ 
+ 	int sock;
+ 	fd_set fd_wait;
+ 	int retries = 0;
+ 	struct sockaddr from;
+ 	int fromlen;
+ 
+ 	if ((sock = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
+ 		ERROR("Can't socket\n");
+ 
+ 	if (bind (sock, (struct sockaddr *) &radius_me, sizeof(radius_me)))
+ 		ERROR("can't bind\n");
+ 
+ 	for (;;)
+ 	{
+ 		if (sendto ( sock, packet, ntohs(*((u_short *)(packet + 2))), 0,
+ 			 (struct sockaddr *)whom,
+ 			 sizeof(struct sockaddr_in)) < 0)
+ 			ERROR("can't sendto\n");
+ 
+ 		FD_ZERO (&fd_wait);
+ 		FD_SET (sock, &fd_wait);
+ 		if ( select (sock+1, &fd_wait, NULL, NULL, &radius_timeout) < 0)
+ 			ERROR("can't select\n");
+ 		if (FD_ISSET (sock, &fd_wait))
+ 			break;
+ 		if ( ++retries == radius_retry_max)
+ 			return (0);
+ 	}
+ 
+ 	fromlen = sizeof (from);
+ 	if (recvfrom(sock, reply, RADLIB_MAX_PACKET_SIZE, 0, &from, &fromlen) < 0)
+ 		ERROR("bad packet recieved\n");
+ 
+ 	return(1);
+ #undef ERROR
+ }
+ 
+ /* encrypt password */
+ void radius_encrypt_password(char *ptr, char *passwd, char *auth)
+ {
+ 	int slen;
+ 	char buf[32];
+ 	int i;
+ 
+ 	slen = strlen (radius_secret);
+ 	strcpy (buf, radius_secret);
+ 	memcpy (buf + slen, auth, 16);
+ 	md5_calc (ptr, buf, slen + 16);
+ 	for (i = 0; i < strlen (passwd); i++)
+ 		ptr[i] ^= passwd[i];
+ }
+ 
+ /* create Authenicator */
+ void radius_create_auth (char *ptr)
+ {
+ 	char md5buf[128];
+ 	int slen = strlen (radius_secret);
+ 	TRadiusHeader *hdr;
+ 
+ 	hdr = (TRadiusHeader *)ptr;
+ 	strcpy (ptr+ntohs(hdr->length), radius_secret);
+ 	md5_calc (md5buf, ptr, slen + ntohs (hdr->length));
+ 	memcpy (hdr->auth, md5buf, 16);
+ }
+ 
+ int radius_response_auth (char *resp, char *auth)
+ {
+ 	u_char tmp[RADLIB_MAX_PACKET_SIZE];
+ 	u_char md5buf[128];
+ 	int len;
+ 	
+ 	len = ntohs (*(u_short*)(resp+2));
+ 	memcpy (tmp, resp, len);
+ 	memcpy (tmp + 4, auth, 16);
+ 	memcpy (tmp + len, radius_secret, strlen(radius_secret));
+ 
+ 	md5_calc (md5buf, tmp, len + strlen(radius_secret));
+ 	return (!memcmp (md5buf, resp + 4, 16));
+ }
+ 
+ int radius_account_start (u_char *user_name, u_long port)
+ {
+ 	u_char reply[RADLIB_MAX_PACKET_SIZE];
+ 	u_char request[RADLIB_MAX_PACKET_SIZE];
+ 	TRadiusHeader *hdr;
+ 	TRadiusHeader *rep;
+ 	u_char *ptr;
+ 	int i;
+ 
+ 	hdr = (TRadiusHeader *)request;
+ 	hdr->code = PW_ACCOUNTING_REQUEST;
+ 	hdr->id = radius_id++;
+ 	for (i = 0; i < 4; i++)
+ 		hdr->auth[i] = 0L;
+ 	ptr = request + 20;
+ 	RADINS_USER_NAME (ptr, user_name);
+ 	RADINS_NAS_IP_ADDRESS (ptr, &radius_me.sin_addr.s_addr);
+ 	RADINS_NAS_PORT (ptr, port);
+ 	RADINS_CALLING_STATION_ID (ptr, callerid);
+ 	RADINS_STATE (ptr, con_state);
+ 	RADINS_ACCT_STATUS_TYPE (ptr, PW_STATUS_START);
+ 	RADINS_ACCT_SESSION_ID (ptr, radius_session_id);
+ 	hdr->length = htons ((unsigned)ptr - (unsigned)request);
+ 	radius_create_auth (request);
+ 
+ /* Ok, packet is now assembled. send it */
+ 	if (!radius_send_query (request, reply, &radius_servac))
+ 		return(RADLIB_NO_RESPONSE);
+ /* verify */
+ 	rep = (TRadiusHeader *)reply;
+ 	if (rep->id != hdr->id)
+ 		return(RADLIB_BAD_ID);
+ 	if (!radius_response_auth (reply, (char *)hdr->auth))
+ 		return(RADLIB_BAD_AUTH);
+ 	if (rep->code != PW_ACCOUNTING_RESPONSE)
+ 		return(RADLIB_ACCESS_DENIED);
+ 	return (0); /* all right */
+ }
+ 
+ int radius_account_stop (u_char *user_name, u_long port, time_t stime)
+ {
+ 	u_char reply[RADLIB_MAX_PACKET_SIZE];
+ 	u_char request[RADLIB_MAX_PACKET_SIZE];
+ 	TRadiusHeader *hdr;
+ 	TRadiusHeader *rep;
+ 	u_char *ptr;
+ 	int i;
+ 
+ 	hdr = (TRadiusHeader *)request;
+ 	hdr->code = PW_ACCOUNTING_REQUEST;
+ 	hdr->id = radius_id++;
+ 	for (i = 0; i < 4; i++)
+ 		hdr->auth[i] = 0L;
+ 	ptr = request + 20;
+ 	RADINS_USER_NAME (ptr, user_name);
+ 	RADINS_NAS_IP_ADDRESS (ptr, &radius_me.sin_addr.s_addr);
+ 	RADINS_NAS_PORT (ptr, port);
+ 	RADINS_CALLING_STATION_ID (ptr, callerid);
+ 	RADINS_STATE (ptr, con_state);
+ 	RADINS_ACCT_STATUS_TYPE (ptr, PW_STATUS_STOP);
+ 	RADINS_ACCT_SESSION_ID (ptr, radius_session_id);
+ 	RADINS_ACCT_SESSION_TIME (ptr, stime);
+ 	hdr->length = htons ((int)ptr - (int)request);
+ 	radius_create_auth (request);
+ 
+ 	if (!radius_send_query (request, reply, &radius_servac))
+ 		return(RADLIB_NO_RESPONSE);
+ /* verify */
+ 	rep = (TRadiusHeader *)reply;
+ 	if (rep->id != hdr->id)
+ 		return(RADLIB_BAD_ID);
+ 	if (!radius_response_auth (reply, (char *)hdr->auth))
+ 		return(RADLIB_BAD_AUTH);
+ 	if (rep->code != PW_ACCOUNTING_RESPONSE)
+ 		return(RADLIB_ACCESS_DENIED);
+ 	return (0); /* all right */
+ }
+ 
+ /* returns client's ip-addres, netmask, MTU, Compression type */
+ int radius_request_ppp_PAP (char *user_name, char *user_passwd, u_long port,
+ 	u_long	**address, u_long **netmask, u_long **mtu, u_long **compress)
+ {
+ 	u_char reply[RADLIB_MAX_PACKET_SIZE];
+ 	u_char request[RADLIB_MAX_PACKET_SIZE];
+ 	TRadiusHeader *hdr;
+ 	TRadiusHeader *rep;
+ 	u_char *ptr;
+ 	int i;
+ 
+ 	int is_address = 0;
+ 	int is_netmask = 0;
+ 	int is_mtu = 0;
+ 	int is_compress = 0;
+ 
+ 	hdr = (TRadiusHeader *)request;
+ 	hdr->code = PW_ACCESS_REQUEST;
+ 	hdr->id = radius_id++;
+ 	srandom (time (NULL));
+ 	for (i = 0; i < 4; i++)
+ 		hdr->auth[i] = random();
+ 	ptr = request + 20;
+ 	RADINS_USER_NAME(ptr, user_name);
+ 	RADINS_USER_PASSWORD(ptr, user_passwd, hdr->auth);
+ 	RADINS_SERVICE_TYPE (ptr, PW_FRAMED);
+ 	RADINS_FRAMED_PROTOCOL (ptr, PW_PPP);
+ 	RADINS_NAS_IP_ADDRESS(ptr, &radius_me.sin_addr.s_addr);
+ 	RADINS_NAS_PORT (ptr, port);
+ 	RADINS_CALLING_STATION_ID (ptr, callerid);
+ 	RADINS_STATE (ptr, con_state);
+ 	hdr->length = htons ((int)ptr - (int)request);
+ 	if (!radius_send_query (request, reply, &radius_server))
+ 		return(RADLIB_NO_RESPONSE);
+ /* verify */
+ 	rep = (TRadiusHeader *)reply;
+ 	if (rep->id != hdr->id)
+ 		return(RADLIB_BAD_ID);
+ 	if (!radius_response_auth (reply, (char *)hdr->auth))
+ 		return(RADLIB_BAD_AUTH);
+ 	if (rep->code == PW_ACCESS_REJECT)
+ 		return(RADLIB_ACCESS_DENIED);
+ 	if (rep->code != PW_ACCESS_ACCEPT)
+ 		return(RADLIB_BAD_CODE);
+ 	for  (  ptr = reply + sizeof(TRadiusHeader);
+ 		ptr < reply + ntohs(rep->length);
+ 		ptr += *(ptr+1))
+ 	{
+ 		switch (*ptr)
+ 		{
+ 			case PW_FRAMED_IP_ADDRESS:
+ 				is_address = 1;
+ 				memcpy (*address, ptr + 2, 4);
+ 				break;
+ 			case PW_FRAMED_IP_NETMASK:
+ 				is_netmask = 1;
+ 				memcpy (*netmask, ptr + 2, 4);
+ 				break;
+ 			case PW_FRAMED_MTU:
+ 				is_mtu = 1;
+ 				**mtu = ntohl(*(u_long*)(ptr + 2));
+ 				break;
+ 			case PW_FRAMED_COMPRESSION:
+ 				is_compress = 1;
+ 				**compress = ntohl(*(u_long*)(ptr + 2));
+ 				break;
+ 		}			
+ 
+ 	}
+ 	if (!is_address) *address = NULL;
+ 	if (!is_netmask) *netmask = NULL;
+ 	if (!is_mtu) *mtu = NULL;
+ 	if (!is_compress) *compress = NULL;
+ 	return (0); /* all right */
+ }
diff -r -P -d -C 3 ppp-2.3.5/pppd/libradius.h ppp-2.3.5-2cbcps-radius-multiport/pppd/libradius.h
*** ppp-2.3.5/pppd/libradius.h	Thu Jan  1 05:00:00 1970
--- ppp-2.3.5-2cbcps-radius-multiport/pppd/libradius.h	Thu Aug 19 16:09:08 1999
***************
*** 0 ****
--- 1,63 ----
+ #ifndef LIBRADIUS_H
+ #define LIBRADIUS_H
+ 
+ #include <netinet/in.h>
+ #include <sys/time.h>
+ 
+ /* sizes */
+ #define RADLIB_MAX_PACKET_SIZE	1024
+ #define RADLIB_DEFAULT_RETRY_MAX	3
+ #define RADLIB_DEFAULT_TIMEOUT		1
+ #define RADLIB_DEFAULT_RADIUS_PORT	1645
+ #define RADLIB_DEFAULT_RADACC_PORT	1646
+ 
+ /* error codes */
+ #define RADLIB_ACCESS_DENIED	1
+ #define RADLIB_NO_RESPONSE	2
+ #define RADLIB_BAD_ID		3
+ #define RADLIB_BAD_AUTH		4
+ #define RADLIB_BAD_CODE		5
+ 
+ 
+ 
+ 
+ #define u_char unsigned char
+ #define u_long unsigned long
+ #define u_short unsigned short
+ 
+ 
+ typedef struct
+ {
+ 	u_char code;
+ 	u_char id;
+ 	u_short length;
+ 	u_long auth[4];
+ } TRadiusHeader;
+ 
+ int radius_init(char *);
+ int radius_send_query (u_char *, u_char *, struct sockaddr_in *);
+ int radius_response_auth (char *, char *);
+ int radius_request_ppp_PAP (char *, char *, u_long, u_long **, u_long **, u_long **, u_long **);
+ int radius_account_start (u_char *, u_long);
+ int radius_account_stop (u_char *, u_long, time_t);
+ void radius_encrypt_password (char *, char *, char *);
+ void radius_create_auth (char *);
+ 
+ int md5_calc (u_char *, u_char *, int);
+ 
+ extern char			callerid[];
+ extern char			con_state[];
+ 
+ extern int			radius_retry_max;
+ extern char			radius_secret[];
+ extern struct sockaddr_in	radius_me;
+ extern struct sockaddr_in	radius_server;
+ extern struct sockaddr_in	radius_servac;
+ extern struct timeval		radius_timeout;
+ extern int			radius_id;
+ extern time_t			radius_session_start_time;
+ extern char			radius_session_id[];
+ extern int			radius_accounting;
+ extern int			radius_debug;
+ 
+ #endif
diff -r -P -d -C 3 ppp-2.3.5/pppd/main.c ppp-2.3.5-2cbcps-radius-multiport/pppd/main.c
*** ppp-2.3.5/pppd/main.c	Tue May  5 11:24:17 1998
--- ppp-2.3.5-2cbcps-radius-multiport/pppd/main.c	Sun Jan 16 14:03:38 2000
***************
*** 51,56 ****
--- 51,57 ----
  #include "ccp.h"
  #include "pathnames.h"
  #include "patchlevel.h"
+ #include "cbcps.h"
  
  #ifdef CBCP_SUPPORT
  #include "cbcp.h"
***************
*** 145,150 ****
--- 146,152 ----
      &lcp_protent,
      &pap_protent,
      &chap_protent,
+     &cbcp_protent,
  #ifdef CBCP_SUPPORT
      &cbcp_protent,
  #endif
***************
*** 409,414 ****
--- 411,470 ----
  	     * Now we want to bring up the link.
  	     */
  	    demand_block();
+ 	    /* !!! begin multiport section */
+ 	    if(usemultiport){
+ 		(void) strncpy(devnam, staticdevnam, MAXPATHLEN);
+ 	        if ((p = (char *) malloc(MAXPATHLEN)) == NULL) {
+ 		    syslog(LOG_ERR, "Out of memory in multiport section (find free device)!");
+ 		    die(1);
+ 		}
+ 		if(multiportend == -1){
+ #ifdef _linux_
+ 		    sprintf(p, "/etc/mg-pid.ttyS%x", multiportfist);
+ #else
+ 		    sprintf(p, "/etc/mg-pid.cuaa%x", multiportfist);
+ #endif
+ 		    if( !(access(p, F_OK)) ){
+ #ifdef _linux_
+ 			sprintf(p, "/var/spool/locks/LCK..ttyS%x", multiportfist);
+ #else
+ 			sprintf(p, "/var/spool/locks/LCK..cuaa%x", multiportfist);
+ #endif
+ 			if( access(p, F_OK) == -1 ){
+ #ifdef _linux_
+ 		    	    sprintf( devnam, "/dev/ttyS%x", multiportfist);
+ #else
+ 		    	    sprintf( devnam, "/dev/cuaa%x", multiportfist);
+ #endif
+ 			}
+ 		    }
+ 		}else{
+ 		    for(i=multiportfist; i<(multiportend+1); i++){
+ #ifdef _linux_
+ 			sprintf(p, "/etc/mg-pid.ttyS%x", i);
+ #else
+ 			sprintf(p, "/etc/mg-pid.cuaa%x", i);
+ #endif
+ 			if( !(access(p, F_OK)) ){
+ #ifdef _linux_
+     			    sprintf(p, "/var/spool/locks/LCK..ttyS%x", i);
+ #else
+     			    sprintf(p, "/var/spool/locks/LCK..cuaa%x", i);
+ #endif
+ 			    if( access(p, F_OK) == -1 ){
+ #ifdef _linux_
+ 				sprintf( devnam, "/dev/ttyS%x", i);
+ #else
+ 				sprintf( devnam, "/dev/cuaa%x", i);
+ #endif
+ 				break;
+ 			    }
+ 			}
+ 		    }
+ 		}
+ 		syslog(LOG_NOTICE, "Multiport: Set device (%s).", devnam);
+ 	    }
+ 	    /* !!! end multiport section */
  	    syslog(LOG_INFO, "Starting link");
  	}
  
diff -r -P -d -C 3 ppp-2.3.5/pppd/main.c.orig ppp-2.3.5-2cbcps-radius-multiport/pppd/main.c.orig
*** ppp-2.3.5/pppd/main.c.orig	Thu Jan  1 05:00:00 1970
--- ppp-2.3.5-2cbcps-radius-multiport/pppd/main.c.orig	Sun Jan 24 14:36:51 1999
***************
*** 0 ****
--- 1,1680 ----
+ /*
+  * main.c - Point-to-Point Protocol main module
+  *
+  * Copyright (c) 1989 Carnegie Mellon University.
+  * All rights reserved.
+  *
+  * Redistribution and use in source and binary forms are permitted
+  * provided that the above copyright notice and this paragraph are
+  * duplicated in all such forms and that any documentation,
+  * advertising materials, and other materials related to such
+  * distribution and use acknowledge that the software was developed
+  * by Carnegie Mellon University.  The name of the
+  * University may not be used to endorse or promote products derived
+  * from this software without specific prior written permission.
+  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+  */
+ 
+ #ifndef lint
+ static char rcsid[] = "$Id: main.c,v 1.49 1998/05/05 05:24:17 paulus Exp $";
+ #endif
+ 
+ #include <stdio.h>
+ #include <ctype.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <unistd.h>
+ #include <signal.h>
+ #include <errno.h>
+ #include <fcntl.h>
+ #include <syslog.h>
+ #include <netdb.h>
+ #include <utmp.h>
+ #include <pwd.h>
+ #include <sys/param.h>
+ #include <sys/types.h>
+ #include <sys/wait.h>
+ #include <sys/time.h>
+ #include <sys/resource.h>
+ #include <sys/stat.h>
+ #include <sys/socket.h>
+ 
+ #include "pppd.h"
+ #include "magic.h"
+ #include "fsm.h"
+ #include "lcp.h"
+ #include "ipcp.h"
+ #include "upap.h"
+ #include "chap.h"
+ #include "ccp.h"
+ #include "pathnames.h"
+ #include "patchlevel.h"
+ #include "cbcps.h"
+ 
+ #ifdef CBCP_SUPPORT
+ #include "cbcp.h"
+ #endif
+ 
+ #if defined(SUNOS4)
+ extern char *strerror();
+ #endif
+ 
+ #ifdef IPX_CHANGE
+ #include "ipxcp.h"
+ #endif /* IPX_CHANGE */
+ #ifdef AT_CHANGE
+ #include "atcp.h"
+ #endif
+ 
+ /* interface vars */
+ char ifname[32];		/* Interface name */
+ int ifunit;			/* Interface unit number */
+ 
+ char *progname;			/* Name of this program */
+ char hostname[MAXNAMELEN];	/* Our hostname */
+ static char pidfilename[MAXPATHLEN];	/* name of pid file */
+ static char default_devnam[MAXPATHLEN];	/* name of default device */
+ static pid_t pid;		/* Our pid */
+ static uid_t uid;		/* Our real user-id */
+ static int conn_running;	/* we have a [dis]connector running */
+ 
+ int ttyfd = -1;			/* Serial port file descriptor */
+ mode_t tty_mode = -1;		/* Original access permissions to tty */
+ int baud_rate;			/* Actual bits/second for serial device */
+ int hungup;			/* terminal has been hung up */
+ int privileged;			/* we're running as real uid root */
+ int need_holdoff;		/* need holdoff period before restarting */
+ int detached;			/* have detached from terminal */
+ 
+ int phase;			/* where the link is at */
+ int kill_link;
+ int open_ccp_flag;
+ 
+ char **script_env;		/* Env. variable values for scripts */
+ int s_env_nalloc;		/* # words avail at script_env */
+ 
+ u_char outpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for outgoing packet */
+ u_char inpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for incoming packet */
+ 
+ static int n_children;		/* # child processes still running */
+ 
+ static int locked;		/* lock() has succeeded */
+ 
+ char *no_ppp_msg = "Sorry - this system lacks PPP kernel support\n";
+ 
+ /* Prototypes for procedures local to this file. */
+ 
+ static void create_pidfile __P((void));
+ static void cleanup __P((void));
+ static void close_tty __P((void));
+ static void get_input __P((void));
+ static void calltimeout __P((void));
+ static struct timeval *timeleft __P((struct timeval *));
+ static void kill_my_pg __P((int));
+ static void hup __P((int));
+ static void term __P((int));
+ static void chld __P((int));
+ static void toggle_debug __P((int));
+ static void open_ccp __P((int));
+ static void bad_signal __P((int));
+ static void holdoff_end __P((void *));
+ static int device_script __P((char *, int, int));
+ static void reap_kids __P((void));
+ static void pr_log __P((void *, char *, ...));
+ 
+ extern	char	*ttyname __P((int));
+ extern	char	*getlogin __P((void));
+ int main __P((int, char *[]));
+ 
+ #ifdef ultrix
+ #undef	O_NONBLOCK
+ #define	O_NONBLOCK	O_NDELAY
+ #endif
+ 
+ #ifdef ULTRIX
+ #define setlogmask(x)
+ #endif
+ 
+ /*
+  * PPP Data Link Layer "protocol" table.
+  * One entry per supported protocol.
+  * The last entry must be NULL.
+  */
+ struct protent *protocols[] = {
+     &lcp_protent,
+     &pap_protent,
+     &chap_protent,
+     &cbcp_protent,
+ #ifdef CBCP_SUPPORT
+     &cbcp_protent,
+ #endif
+     &ipcp_protent,
+     &ccp_protent,
+ #ifdef IPX_CHANGE
+     &ipxcp_protent,
+ #endif
+ #ifdef AT_CHANGE
+     &atcp_protent,
+ #endif
+     NULL
+ };
+ 
+ int
+ main(argc, argv)
+     int argc;
+     char *argv[];
+ {
+     int i, fdflags;
+     struct sigaction sa;
+     char *p;
+     struct passwd *pw;
+     struct timeval timo;
+     sigset_t mask;
+     struct protent *protp;
+     struct stat statbuf;
+     char numbuf[16];
+ 
+     phase = PHASE_INITIALIZE;
+     p = ttyname(0);
+     if (p)
+ 	strcpy(devnam, p);
+     strcpy(default_devnam, devnam);
+ 
+     script_env = NULL;
+ 
+     /* Initialize syslog facilities */
+ #ifdef ULTRIX
+     openlog("pppd", LOG_PID);
+ #else
+     openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP);
+     setlogmask(LOG_UPTO(LOG_INFO));
+ #endif
+ 
+     if (gethostname(hostname, MAXNAMELEN) < 0 ) {
+ 	option_error("Couldn't get hostname: %m");
+ 	die(1);
+     }
+     hostname[MAXNAMELEN-1] = 0;
+ 
+     uid = getuid();
+     privileged = uid == 0;
+     sprintf(numbuf, "%d", uid);
+     script_setenv("UID", numbuf);
+ 
+     /*
+      * Initialize to the standard option set, then parse, in order,
+      * the system options file, the user's options file,
+      * the tty's options file, and the command line arguments.
+      */
+     for (i = 0; (protp = protocols[i]) != NULL; ++i)
+         (*protp->init)(0);
+ 
+     progname = *argv;
+ 
+     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))
+ 	exit(1);
+ 
+     /*
+      * Check that we are running as root.
+      */
+     if (geteuid() != 0) {
+ 	option_error("must be root to run %s, since it is not setuid-root",
+ 		     argv[0]);
+ 	die(1);
+     }
+ 
+     if (!ppp_available()) {
+ 	option_error(no_ppp_msg);
+ 	exit(1);
+     }
+ 
+     /*
+      * Check that the options given are valid and consistent.
+      */
+     sys_check_options();
+     auth_check_options();
+     for (i = 0; (protp = protocols[i]) != NULL; ++i)
+ 	if (protp->check_options != NULL)
+ 	    (*protp->check_options)();
+     if (demand && connector == 0) {
+ 	option_error("connect script required for demand-dialling\n");
+ 	exit(1);
+     }
+ 
+     script_setenv("DEVICE", devnam);
+     sprintf(numbuf, "%d", baud_rate);
+     script_setenv("SPEED", numbuf);
+ 
+     /*
+      * If the user has specified the default device name explicitly,
+      * pretend they hadn't.
+      */
+     if (!default_device && strcmp(devnam, default_devnam) == 0)
+ 	default_device = 1;
+     if (default_device)
+ 	nodetach = 1;
+ 
+     /*
+      * Initialize system-dependent stuff and magic number package.
+      */
+     sys_init();
+     magic_init();
+     if (debug)
+ 	setlogmask(LOG_UPTO(LOG_DEBUG));
+ 
+     /*
+      * Detach ourselves from the terminal, if required,
+      * and identify who is running us.
+      */
+     if (nodetach == 0)
+ 	detach();
+     pid = getpid();
+     p = getlogin();
+     if (p == NULL) {
+ 	pw = getpwuid(uid);
+ 	if (pw != NULL && pw->pw_name != NULL)
+ 	    p = pw->pw_name;
+ 	else
+ 	    p = "(unknown)";
+     }
+     syslog(LOG_NOTICE, "pppd %s.%d%s started by %s, uid %d",
+ 	   VERSION, PATCHLEVEL, IMPLEMENTATION, p, uid);
+   
+     /*
+      * Compute mask of all interesting signals and install signal handlers
+      * for each.  Only one signal handler may be active at a time.  Therefore,
+      * all other signals should be masked when any handler is executing.
+      */
+     sigemptyset(&mask);
+     sigaddset(&mask, SIGHUP);
+     sigaddset(&mask, SIGINT);
+     sigaddset(&mask, SIGTERM);
+     sigaddset(&mask, SIGCHLD);
+ 
+ #define SIGNAL(s, handler)	{ \
+ 	sa.sa_handler = handler; \
+ 	if (sigaction(s, &sa, NULL) < 0) { \
+ 	    syslog(LOG_ERR, "Couldn't establish signal handler (%d): %m", s); \
+ 	    die(1); \
+ 	} \
+     }
+ 
+     sa.sa_mask = mask;
+     sa.sa_flags = 0;
+     SIGNAL(SIGHUP, hup);		/* Hangup */
+     SIGNAL(SIGINT, term);		/* Interrupt */
+     SIGNAL(SIGTERM, term);		/* Terminate */
+     SIGNAL(SIGCHLD, chld);
+ 
+     SIGNAL(SIGUSR1, toggle_debug);	/* Toggle debug flag */
+     SIGNAL(SIGUSR2, open_ccp);		/* Reopen CCP */
+ 
+     /*
+      * Install a handler for other signals which would otherwise
+      * cause pppd to exit without cleaning up.
+      */
+     SIGNAL(SIGABRT, bad_signal);
+     SIGNAL(SIGALRM, bad_signal);
+     SIGNAL(SIGFPE, bad_signal);
+     SIGNAL(SIGILL, bad_signal);
+     SIGNAL(SIGPIPE, bad_signal);
+     SIGNAL(SIGQUIT, bad_signal);
+     SIGNAL(SIGSEGV, bad_signal);
+ #ifdef SIGBUS
+     SIGNAL(SIGBUS, bad_signal);
+ #endif
+ #ifdef SIGEMT
+     SIGNAL(SIGEMT, bad_signal);
+ #endif
+ #ifdef SIGPOLL
+     SIGNAL(SIGPOLL, bad_signal);
+ #endif
+ #ifdef SIGPROF
+     SIGNAL(SIGPROF, bad_signal);
+ #endif
+ #ifdef SIGSYS
+     SIGNAL(SIGSYS, bad_signal);
+ #endif
+ #ifdef SIGTRAP
+     SIGNAL(SIGTRAP, bad_signal);
+ #endif
+ #ifdef SIGVTALRM
+     SIGNAL(SIGVTALRM, bad_signal);
+ #endif
+ #ifdef SIGXCPU
+     SIGNAL(SIGXCPU, bad_signal);
+ #endif
+ #ifdef SIGXFSZ
+     SIGNAL(SIGXFSZ, bad_signal);
+ #endif
+ 
+     /*
+      * Apparently we can get a SIGPIPE when we call syslog, if
+      * syslogd has died and been restarted.  Ignoring it seems
+      * be sufficient.
+      */
+     signal(SIGPIPE, SIG_IGN);
+ 
+     /*
+      * If we're doing dial-on-demand, set up the interface now.
+      */
+     if (demand) {
+ 	/*
+ 	 * Open the loopback channel and set it up to be the ppp interface.
+ 	 */
+ 	open_ppp_loopback();
+ 
+ 	syslog(LOG_INFO, "Using interface ppp%d", ifunit);
+ 	(void) sprintf(ifname, "ppp%d", ifunit);
+ 	script_setenv("IFNAME", ifname);
+ 
+ 	create_pidfile();	/* write pid to file */
+ 
+ 	/*
+ 	 * Configure the interface and mark it up, etc.
+ 	 */
+ 	demand_conf();
+     }
+ 
+     for (;;) {
+ 
+ 	need_holdoff = 1;
+ 
+ 	if (demand) {
+ 	    /*
+ 	     * Don't do anything until we see some activity.
+ 	     */
+ 	    phase = PHASE_DORMANT;
+ 	    kill_link = 0;
+ 	    demand_unblock();
+ 	    for (;;) {
+ 		wait_loop_output(timeleft(&timo));
+ 		calltimeout();
+ 		if (kill_link) {
+ 		    if (!persist)
+ 			die(0);
+ 		    kill_link = 0;
+ 		}
+ 		if (get_loop_output())
+ 		    break;
+ 		reap_kids();
+ 	    }
+ 
+ 	    /*
+ 	     * Now we want to bring up the link.
+ 	     */
+ 	    demand_block();
+ 	    syslog(LOG_INFO, "Starting link");
+ 	}
+ 
+ 	/*
+ 	 * Lock the device if we've been asked to.
+ 	 */
+ 	if (lockflag && !default_device) {
+ 	    if (lock(devnam) < 0)
+ 		goto fail;
+ 	    locked = 1;
+ 	}
+ 
+ 	/*
+ 	 * Open the serial device and set it up to be the ppp interface.
+ 	 * First we open it in non-blocking mode so we can set the
+ 	 * various termios flags appropriately.  If we aren't dialling
+ 	 * out and we want to use the modem lines, we reopen it later
+ 	 * in order to wait for the carrier detect signal from the modem.
+ 	 */
+ 	while ((ttyfd = open(devnam, O_NONBLOCK | O_RDWR, 0)) < 0) {
+ 	    if (errno != EINTR)
+ 		syslog(LOG_ERR, "Failed to open %s: %m", devnam);
+ 	    if (!persist || errno != EINTR)
+ 		goto fail;
+ 	}
+ 	if ((fdflags = fcntl(ttyfd, F_GETFL)) == -1
+ 	    || fcntl(ttyfd, F_SETFL, fdflags & ~O_NONBLOCK) < 0)
+ 	    syslog(LOG_WARNING,
+ 		   "Couldn't reset non-blocking mode on device: %m");
+ 
+ 	hungup = 0;
+ 	kill_link = 0;
+ 
+ 	/*
+ 	 * Do the equivalent of `mesg n' to stop broadcast messages.
+ 	 */
+ 	if (fstat(ttyfd, &statbuf) < 0
+ 	    || fchmod(ttyfd, statbuf.st_mode & ~(S_IWGRP | S_IWOTH)) < 0) {
+ 	    syslog(LOG_WARNING,
+ 		   "Couldn't restrict write permissions to %s: %m", devnam);
+ 	} else
+ 	    tty_mode = statbuf.st_mode;
+ 
+ 	/* run connection script */
+ 	if (connector && connector[0]) {
+ 	    MAINDEBUG((LOG_INFO, "Connecting with <%s>", connector));
+ 
+ 	    /*
+ 	     * Set line speed, flow control, etc.
+ 	     * On most systems we set CLOCAL for now so that we can talk
+ 	     * to the modem before carrier comes up.  But this has the
+ 	     * side effect that we might miss it if CD drops before we
+ 	     * get to clear CLOCAL below.  On systems where we can talk
+ 	     * successfully to the modem with CLOCAL clear and CD down,
+ 	     * we can clear CLOCAL at this point.
+ 	     */
+ 	    set_up_tty(ttyfd, 1);
+ 
+ 	    /* drop dtr to hang up in case modem is off hook */
+ 	    if (!default_device && modem) {
+ 		setdtr(ttyfd, FALSE);
+ 		sleep(1);
+ 		setdtr(ttyfd, TRUE);
+ 	    }
+ 
+ 	    if (device_script(connector, ttyfd, ttyfd) < 0) {
+ 		syslog(LOG_ERR, "Connect script failed");
+ 		setdtr(ttyfd, FALSE);
+ 		goto fail;
+ 	    }
+ 
+ 
+ 	    syslog(LOG_INFO, "Serial connection established.");
+ 	    sleep(1);		/* give it time to set up its terminal */
+ 	}
+ 
+ 	/* set line speed, flow control, etc.; clear CLOCAL if modem option */
+ 	set_up_tty(ttyfd, 0);
+ 
+ 	/* reopen tty if necessary to wait for carrier */
+ 	if (connector == NULL && modem) {
+ 	    while ((i = open(devnam, O_RDWR)) < 0) {
+ 		if (errno != EINTR)
+ 		    syslog(LOG_ERR, "Failed to reopen %s: %m", devnam);
+ 		if (!persist || errno != EINTR || hungup || kill_link)
+ 		    goto fail;
+ 	    }
+ 	    close(i);
+ 	}
+ 
+ 	/* run welcome script, if any */
+ 	if (welcomer && welcomer[0]) {
+ 	    if (device_script(welcomer, ttyfd, ttyfd) < 0)
+ 		syslog(LOG_WARNING, "Welcome script failed");
+ 	}
+ 
+ 	/* set up the serial device as a ppp interface */
+ 	establish_ppp(ttyfd);
+ 
+ 	if (!demand) {
+ 	    
+ 	    syslog(LOG_INFO, "Using interface ppp%d", ifunit);
+ 	    (void) sprintf(ifname, "ppp%d", ifunit);
+ 	    script_setenv("IFNAME", ifname);
+ 
+ 	    create_pidfile();	/* write pid to file */
+ 	}
+ 
+ 	/*
+ 	 * Start opening the connection and wait for
+ 	 * incoming events (reply, timeout, etc.).
+ 	 */
+ 	syslog(LOG_NOTICE, "Connect: %s <--> %s", ifname, devnam);
+ 	lcp_lowerup(0);
+ 	lcp_open(0);		/* Start protocol */
+ 	for (phase = PHASE_ESTABLISH; phase != PHASE_DEAD; ) {
+ 	    wait_input(timeleft(&timo));
+ 	    calltimeout();
+ 	    get_input();
+ 	    if (kill_link) {
+ 		lcp_close(0, "User request");
+ 		kill_link = 0;
+ 	    }
+ 	    if (open_ccp_flag) {
+ 		if (phase == PHASE_NETWORK) {
+ 		    ccp_fsm[0].flags = OPT_RESTART; /* clears OPT_SILENT */
+ 		    (*ccp_protent.open)(0);
+ 		}
+ 		open_ccp_flag = 0;
+ 	    }
+ 	    reap_kids();	/* Don't leave dead kids lying around */
+ 	}
+ 
+ 	/*
+ 	 * If we may want to bring the link up again, transfer
+ 	 * the ppp unit back to the loopback.  Set the
+ 	 * real serial device back to its normal mode of operation.
+ 	 */
+ 	clean_check();
+ 	if (demand)
+ 	    restore_loop();
+ 	disestablish_ppp(ttyfd);
+ 
+ 	/*
+ 	 * Run disconnector script, if requested.
+ 	 * XXX we may not be able to do this if the line has hung up!
+ 	 */
+ 	if (disconnector && !hungup) {
+ 	    set_up_tty(ttyfd, 1);
+ 	    if (device_script(disconnector, ttyfd, ttyfd) < 0) {
+ 		syslog(LOG_WARNING, "disconnect script failed");
+ 	    } else {
+ 		syslog(LOG_INFO, "Serial link disconnected.");
+ 	    }
+ 	}
+ 
+     fail:
+ 	if (ttyfd >= 0)
+ 	    close_tty();
+ 	if (locked) {
+ 	    unlock();
+ 	    locked = 0;
+ 	}
+ 
+ 	if (!demand) {
+ 	    if (pidfilename[0] != 0
+ 		&& unlink(pidfilename) < 0 && errno != ENOENT) 
+ 		syslog(LOG_WARNING, "unable to delete pid file: %m");
+ 	    pidfilename[0] = 0;
+ 	}
+ 
+ 	if (!persist)
+ 	    die(1);
+ 
+ 	if (demand)
+ 	    demand_discard();
+ 	if (holdoff > 0 && need_holdoff) {
+ 	    phase = PHASE_HOLDOFF;
+ 	    TIMEOUT(holdoff_end, NULL, holdoff);
+ 	    do {
+ 		wait_time(timeleft(&timo));
+ 		calltimeout();
+ 		if (kill_link) {
+ 		    if (!persist)
+ 			die(0);
+ 		    kill_link = 0;
+ 		    phase = PHASE_DORMANT; /* allow signal to end holdoff */
+ 		}
+ 		reap_kids();
+ 	    } while (phase == PHASE_HOLDOFF);
+ 	}
+     }
+ 
+     die(0);
+     return 0;
+ }
+ 
+ /*
+  * detach - detach us from the controlling terminal.
+  */
+ void
+ detach()
+ {
+     if (detached)
+ 	return;
+     if (daemon(0, 0) < 0) {
+ 	perror("Couldn't detach from controlling terminal");
+ 	die(1);
+     }
+     detached = 1;
+     pid = getpid();
+     /* update pid file if it has been written already */
+     if (pidfilename[0])
+ 	create_pidfile();
+ }
+ 
+ /*
+  * Create a file containing our process ID.
+  */
+ static void
+ create_pidfile()
+ {
+     FILE *pidfile;
+ 
+     (void) sprintf(pidfilename, "%s%s.pid", _PATH_VARRUN, ifname);
+     if ((pidfile = fopen(pidfilename, "w")) != NULL) {
+ 	fprintf(pidfile, "%d\n", pid);
+ 	(void) fclose(pidfile);
+     } else {
+ 	syslog(LOG_ERR, "Failed to create pid file %s: %m", pidfilename);
+ 	pidfilename[0] = 0;
+     }
+ }
+ 
+ /*
+  * holdoff_end - called via a timeout when the holdoff period ends.
+  */
+ static void
+ holdoff_end(arg)
+     void *arg;
+ {
+     phase = PHASE_DORMANT;
+ }
+ 
+ /*
+  * get_input - called when incoming data is available.
+  */
+ static void
+ get_input()
+ {
+     int len, i;
+     u_char *p;
+     u_short protocol;
+     struct protent *protp;
+ 
+     p = inpacket_buf;	/* point to beginning of packet buffer */
+ 
+     len = read_packet(inpacket_buf);
+     if (len < 0)
+ 	return;
+ 
+     if (len == 0) {
+ 	syslog(LOG_NOTICE, "Modem hangup");
+ 	hungup = 1;
+ 	lcp_lowerdown(0);	/* serial link is no longer available */
+ 	link_terminated(0);
+ 	return;
+     }
+ 
+     if (debug /*&& (debugflags & DBG_INPACKET)*/)
+ 	log_packet(p, len, "rcvd ", LOG_DEBUG);
+ 
+     if (len < PPP_HDRLEN) {
+ 	MAINDEBUG((LOG_INFO, "io(): Received short packet."));
+ 	return;
+     }
+ 
+     p += 2;				/* Skip address and control */
+     GETSHORT(protocol, p);
+     len -= PPP_HDRLEN;
+ 
+     /*
+      * Toss all non-LCP packets unless LCP is OPEN.
+      */
+     if (protocol != PPP_LCP && lcp_fsm[0].state != OPENED) {
+ 	MAINDEBUG((LOG_INFO,
+ 		   "get_input: Received non-LCP packet when LCP not open."));
+ 	return;
+     }
+ 
+     /*
+      * Until we get past the authentication phase, toss all packets
+      * except LCP, LQR and authentication packets.
+      */
+     if (phase <= PHASE_AUTHENTICATE
+ 	&& !(protocol == PPP_LCP || protocol == PPP_LQR
+ 	     || protocol == PPP_PAP || protocol == PPP_CHAP)) {
+ 	MAINDEBUG((LOG_INFO, "get_input: discarding proto 0x%x in phase %d",
+ 		   protocol, phase));
+ 	return;
+     }
+ 
+     /*
+      * Upcall the proper protocol input routine.
+      */
+     for (i = 0; (protp = protocols[i]) != NULL; ++i) {
+ 	if (protp->protocol == protocol && protp->enabled_flag) {
+ 	    (*protp->input)(0, p, len);
+ 	    return;
+ 	}
+         if (protocol == (protp->protocol & ~0x8000) && protp->enabled_flag
+ 	    && protp->datainput != NULL) {
+ 	    (*protp->datainput)(0, p, len);
+ 	    return;
+ 	}
+     }
+ 
+     if (debug)
+     	syslog(LOG_WARNING, "Unsupported protocol (0x%x) received", protocol);
+     lcp_sprotrej(0, p - PPP_HDRLEN, len + PPP_HDRLEN);
+ }
+ 
+ 
+ /*
+  * quit - Clean up state and exit (with an error indication).
+  */
+ void 
+ quit()
+ {
+     die(1);
+ }
+ 
+ /*
+  * die - like quit, except we can specify an exit status.
+  */
+ void
+ die(status)
+     int status;
+ {
+     cleanup();
+     syslog(LOG_INFO, "Exit.");
+     exit(status);
+ }
+ 
+ /*
+  * cleanup - restore anything which needs to be restored before we exit
+  */
+ /* ARGSUSED */
+ static void
+ cleanup()
+ {
+     sys_cleanup();
+ 
+     if (ttyfd >= 0)
+ 	close_tty();
+ 
+     if (pidfilename[0] != 0 && unlink(pidfilename) < 0 && errno != ENOENT) 
+ 	syslog(LOG_WARNING, "unable to delete pid file: %m");
+     pidfilename[0] = 0;
+ 
+     if (locked)
+ 	unlock();
+ }
+ 
+ /*
+  * close_tty - restore the terminal device and close it.
+  */
+ static void
+ close_tty()
+ {
+     disestablish_ppp(ttyfd);
+ 
+     /* drop dtr to hang up */
+     if (modem) {
+ 	setdtr(ttyfd, FALSE);
+ 	/*
+ 	 * This sleep is in case the serial port has CLOCAL set by default,
+ 	 * and consequently will reassert DTR when we close the device.
+ 	 */
+ 	sleep(1);
+     }
+ 
+     restore_tty(ttyfd);
+ 
+     if (tty_mode != (mode_t) -1)
+ 	chmod(devnam, tty_mode);
+ 
+     close(ttyfd);
+     ttyfd = -1;
+ }
+ 
+ 
+ struct	callout {
+     struct timeval	c_time;		/* time at which to call routine */
+     void		*c_arg;		/* argument to routine */
+     void		(*c_func) __P((void *)); /* routine */
+     struct		callout *c_next;
+ };
+ 
+ static struct callout *callout = NULL;	/* Callout list */
+ static struct timeval timenow;		/* Current time */
+ 
+ /*
+  * timeout - Schedule a timeout.
+  *
+  * Note that this timeout takes the number of seconds, NOT hz (as in
+  * the kernel).
+  */
+ void
+ timeout(func, arg, time)
+     void (*func) __P((void *));
+     void *arg;
+     int time;
+ {
+     struct callout *newp, *p, **pp;
+   
+     MAINDEBUG((LOG_DEBUG, "Timeout %lx:%lx in %d seconds.",
+ 	       (long) func, (long) arg, time));
+   
+     /*
+      * Allocate timeout.
+      */
+     if ((newp = (struct callout *) malloc(sizeof(struct callout))) == NULL) {
+ 	syslog(LOG_ERR, "Out of memory in timeout()!");
+ 	die(1);
+     }
+     newp->c_arg = arg;
+     newp->c_func = func;
+     gettimeofday(&timenow, NULL);
+     newp->c_time.tv_sec = timenow.tv_sec + time;
+     newp->c_time.tv_usec = timenow.tv_usec;
+   
+     /*
+      * Find correct place and link it in.
+      */
+     for (pp = &callout; (p = *pp); pp = &p->c_next)
+ 	if (newp->c_time.tv_sec < p->c_time.tv_sec
+ 	    || (newp->c_time.tv_sec == p->c_time.tv_sec
+ 		&& newp->c_time.tv_usec < p->c_time.tv_sec))
+ 	    break;
+     newp->c_next = p;
+     *pp = newp;
+ }
+ 
+ 
+ /*
+  * untimeout - Unschedule a timeout.
+  */
+ void
+ untimeout(func, arg)
+     void (*func) __P((void *));
+     void *arg;
+ {
+     struct callout **copp, *freep;
+   
+     MAINDEBUG((LOG_DEBUG, "Untimeout %lx:%lx.", (long) func, (long) arg));
+   
+     /*
+      * Find first matching timeout and remove it from the list.
+      */
+     for (copp = &callout; (freep = *copp); copp = &freep->c_next)
+ 	if (freep->c_func == func && freep->c_arg == arg) {
+ 	    *copp = freep->c_next;
+ 	    (void) free((char *) freep);
+ 	    break;
+ 	}
+ }
+ 
+ 
+ /*
+  * calltimeout - Call any timeout routines which are now due.
+  */
+ static void
+ calltimeout()
+ {
+     struct callout *p;
+ 
+     while (callout != NULL) {
+ 	p = callout;
+ 
+ 	if (gettimeofday(&timenow, NULL) < 0) {
+ 	    syslog(LOG_ERR, "Failed to get time of day: %m");
+ 	    die(1);
+ 	}
+ 	if (!(p->c_time.tv_sec < timenow.tv_sec
+ 	      || (p->c_time.tv_sec == timenow.tv_sec
+ 		  && p->c_time.tv_usec <= timenow.tv_usec)))
+ 	    break;		/* no, it's not time yet */
+ 
+ 	callout = p->c_next;
+ 	(*p->c_func)(p->c_arg);
+ 
+ 	free((char *) p);
+     }
+ }
+ 
+ 
+ /*
+  * timeleft - return the length of time until the next timeout is due.
+  */
+ static struct timeval *
+ timeleft(tvp)
+     struct timeval *tvp;
+ {
+     if (callout == NULL)
+ 	return NULL;
+ 
+     gettimeofday(&timenow, NULL);
+     tvp->tv_sec = callout->c_time.tv_sec - timenow.tv_sec;
+     tvp->tv_usec = callout->c_time.tv_usec - timenow.tv_usec;
+     if (tvp->tv_usec < 0) {
+ 	tvp->tv_usec += 1000000;
+ 	tvp->tv_sec -= 1;
+     }
+     if (tvp->tv_sec < 0)
+ 	tvp->tv_sec = tvp->tv_usec = 0;
+ 
+     return tvp;
+ }
+ 
+ 
+ /*
+  * kill_my_pg - send a signal to our process group, and ignore it ourselves.
+  */
+ static void
+ kill_my_pg(sig)
+     int sig;
+ {
+     struct sigaction act, oldact;
+ 
+     act.sa_handler = SIG_IGN;
+     act.sa_flags = 0;
+     kill(0, sig);
+     sigaction(sig, &act, &oldact);
+     sigaction(sig, &oldact, NULL);
+ }
+ 
+ 
+ /*
+  * hup - Catch SIGHUP signal.
+  *
+  * Indicates that the physical layer has been disconnected.
+  * We don't rely on this indication; if the user has sent this
+  * signal, we just take the link down.
+  */
+ static void
+ hup(sig)
+     int sig;
+ {
+     syslog(LOG_INFO, "Hangup (SIGHUP)");
+     kill_link = 1;
+     if (conn_running)
+ 	/* Send the signal to the [dis]connector process(es) also */
+ 	kill_my_pg(sig);
+ }
+ 
+ 
+ /*
+  * term - Catch SIGTERM signal and SIGINT signal (^C/del).
+  *
+  * Indicates that we should initiate a graceful disconnect and exit.
+  */
+ /*ARGSUSED*/
+ static void
+ term(sig)
+     int sig;
+ {
+     syslog(LOG_INFO, "Terminating on signal %d.", sig);
+     persist = 0;		/* don't try to restart */
+     kill_link = 1;
+     if (conn_running)
+ 	/* Send the signal to the [dis]connector process(es) also */
+ 	kill_my_pg(sig);
+ }
+ 
+ 
+ /*
+  * chld - Catch SIGCHLD signal.
+  * Calls reap_kids to get status for any dead kids.
+  */
+ static void
+ chld(sig)
+     int sig;
+ {
+     reap_kids();
+ }
+ 
+ 
+ /*
+  * toggle_debug - Catch SIGUSR1 signal.
+  *
+  * Toggle debug flag.
+  */
+ /*ARGSUSED*/
+ static void
+ toggle_debug(sig)
+     int sig;
+ {
+     debug = !debug;
+     if (debug) {
+ 	setlogmask(LOG_UPTO(LOG_DEBUG));
+     } else {
+ 	setlogmask(LOG_UPTO(LOG_WARNING));
+     }
+ }
+ 
+ 
+ /*
+  * open_ccp - Catch SIGUSR2 signal.
+  *
+  * Try to (re)negotiate compression.
+  */
+ /*ARGSUSED*/
+ static void
+ open_ccp(sig)
+     int sig;
+ {
+     open_ccp_flag = 1;
+ }
+ 
+ 
+ /*
+  * bad_signal - We've caught a fatal signal.  Clean up state and exit.
+  */
+ static void
+ bad_signal(sig)
+     int sig;
+ {
+     static int crashed = 0;
+ 
+     if (crashed)
+ 	_exit(127);
+     crashed = 1;
+     syslog(LOG_ERR, "Fatal signal %d", sig);
+     if (conn_running)
+ 	kill_my_pg(SIGTERM);
+     die(1);
+ }
+ 
+ 
+ /*
+  * device_script - run a program to connect or disconnect the
+  * serial device.
+  */
+ static int
+ device_script(program, in, out)
+     char *program;
+     int in, out;
+ {
+     int pid;
+     int status;
+     int errfd;
+ 
+     conn_running = 1;
+     pid = fork();
+ 
+     if (pid < 0) {
+ 	conn_running = 0;
+ 	syslog(LOG_ERR, "Failed to create child process: %m");
+ 	die(1);
+     }
+ 
+     if (pid == 0) {
+ 	sys_close();
+ 	closelog();
+ 	if (in == out) {
+ 	    if (in != 0) {
+ 		dup2(in, 0);
+ 		close(in);
+ 	    }
+ 	    dup2(0, 1);
+ 	} else {
+ 	    if (out == 0)
+ 		out = dup(out);
+ 	    if (in != 0) {
+ 		dup2(in, 0);
+ 		close(in);
+ 	    }
+ 	    if (out != 1) {
+ 		dup2(out, 1);
+ 		close(out);
+ 	    }
+ 	}
+ 	if (nodetach == 0) {
+ 	    close(2);
+ 	    errfd = open(_PATH_CONNERRS, O_WRONLY | O_APPEND | O_CREAT, 0600);
+ 	    if (errfd >= 0 && errfd != 2) {
+ 		dup2(errfd, 2);
+ 		close(errfd);
+ 	    }
+ 	}
+ 	setuid(getuid());
+ 	setgid(getgid());
+ 	execl("/bin/sh", "sh", "-c", program, (char *)0);
+ 	syslog(LOG_ERR, "could not exec /bin/sh: %m");
+ 	_exit(99);
+ 	/* NOTREACHED */
+     }
+ 
+     while (waitpid(pid, &status, 0) < 0) {
+ 	if (errno == EINTR)
+ 	    continue;
+ 	syslog(LOG_ERR, "error waiting for (dis)connection process: %m");
+ 	die(1);
+     }
+     conn_running = 0;
+ 
+     return (status == 0 ? 0 : -1);
+ }
+ 
+ 
+ /*
+  * run-program - execute a program with given arguments,
+  * but don't wait for it.
+  * If the program can't be executed, logs an error unless
+  * must_exist is 0 and the program file doesn't exist.
+  */
+ int
+ run_program(prog, args, must_exist)
+     char *prog;
+     char **args;
+     int must_exist;
+ {
+     int pid;
+ 
+     pid = fork();
+     if (pid == -1) {
+ 	syslog(LOG_ERR, "Failed to create child process for %s: %m", prog);
+ 	return -1;
+     }
+     if (pid == 0) {
+ 	int new_fd;
+ 
+ 	/* Leave the current location */
+ 	(void) setsid();    /* No controlling tty. */
+ 	(void) umask (S_IRWXG|S_IRWXO);
+ 	(void) chdir ("/"); /* no current directory. */
+ 	setuid(geteuid());
+ 	setgid(getegid());
+ 
+ 	/* Ensure that nothing of our device environment is inherited. */
+ 	sys_close();
+ 	closelog();
+ 	close (0);
+ 	close (1);
+ 	close (2);
+ 	close (ttyfd);  /* tty interface to the ppp device */
+ 
+         /* Don't pass handles to the PPP device, even by accident. */
+ 	new_fd = open (_PATH_DEVNULL, O_RDWR);
+ 	if (new_fd >= 0) {
+ 	    if (new_fd != 0) {
+ 	        dup2  (new_fd, 0); /* stdin <- /dev/null */
+ 		close (new_fd);
+ 	    }
+ 	    dup2 (0, 1); /* stdout -> /dev/null */
+ 	    dup2 (0, 2); /* stderr -> /dev/null */
+ 	}
+ 
+ #ifdef BSD
+ 	/* Force the priority back to zero if pppd is running higher. */
+ 	if (setpriority (PRIO_PROCESS, 0, 0) < 0)
+ 	    syslog (LOG_WARNING, "can't reset priority to 0: %m"); 
+ #endif
+ 
+ 	/* SysV recommends a second fork at this point. */
+ 
+ 	/* run the program; give it a null environment */
+ 	execve(prog, args, script_env);
+ 	if (must_exist || errno != ENOENT)
+ 	    syslog(LOG_WARNING, "Can't execute %s: %m", prog);
+ 	_exit(-1);
+     }
+     MAINDEBUG((LOG_DEBUG, "Script %s started; pid = %d", prog, pid));
+     ++n_children;
+     return 0;
+ }
+ 
+ 
+ /*
+  * reap_kids - get status from any dead child processes,
+  * and log a message for abnormal terminations.
+  */
+ static void
+ reap_kids()
+ {
+     int pid, status;
+ 
+     if (n_children == 0)
+ 	return;
+     if ((pid = waitpid(-1, &status, WNOHANG)) == -1) {
+ 	if (errno != ECHILD)
+ 	    syslog(LOG_ERR, "Error waiting for child process: %m");
+ 	return;
+     }
+     if (pid > 0) {
+ 	--n_children;
+ 	if (WIFSIGNALED(status)) {
+ 	    syslog(LOG_WARNING, "Child process %d terminated with signal %d",
+ 		   pid, WTERMSIG(status));
+ 	}
+     }
+ }
+ 
+ 
+ /*
+  * log_packet - format a packet and log it.
+  */
+ 
+ char line[256];			/* line to be logged accumulated here */
+ char *linep;
+ 
+ void
+ log_packet(p, len, prefix, level)
+     u_char *p;
+     int len;
+     char *prefix;
+     int level;
+ {
+     strcpy(line, prefix);
+     linep = line + strlen(line);
+     format_packet(p, len, pr_log, NULL);
+     if (linep != line)
+ 	syslog(level, "%s", line);
+ }
+ 
+ /*
+  * format_packet - make a readable representation of a packet,
+  * calling `printer(arg, format, ...)' to output it.
+  */
+ void
+ format_packet(p, len, printer, arg)
+     u_char *p;
+     int len;
+     void (*printer) __P((void *, char *, ...));
+     void *arg;
+ {
+     int i, n;
+     u_short proto;
+     u_char x;
+     struct protent *protp;
+ 
+     if (len >= PPP_HDRLEN && p[0] == PPP_ALLSTATIONS && p[1] == PPP_UI) {
+ 	p += 2;
+ 	GETSHORT(proto, p);
+ 	len -= PPP_HDRLEN;
+ 	for (i = 0; (protp = protocols[i]) != NULL; ++i)
+ 	    if (proto == protp->protocol)
+ 		break;
+ 	if (protp != NULL) {
+ 	    printer(arg, "[%s", protp->name);
+ 	    n = (*protp->printpkt)(p, len, printer, arg);
+ 	    printer(arg, "]");
+ 	    p += n;
+ 	    len -= n;
+ 	} else {
+ 	    printer(arg, "[proto=0x%x]", proto);
+ 	}
+     }
+ 
+     for (; len > 0; --len) {
+ 	GETCHAR(x, p);
+ 	printer(arg, " %.2x", x);
+     }
+ }
+ 
+ static void
+ pr_log __V((void *arg, char *fmt, ...))
+ {
+     int n;
+     va_list pvar;
+     char buf[256];
+ 
+ #if __STDC__
+     va_start(pvar, fmt);
+ #else
+     void *arg;
+     char *fmt;
+     va_start(pvar);
+     arg = va_arg(pvar, void *);
+     fmt = va_arg(pvar, char *);
+ #endif
+ 
+     n = vfmtmsg(buf, sizeof(buf), fmt, pvar);
+     va_end(pvar);
+ 
+     if (linep + n + 1 > line + sizeof(line)) {
+ 	syslog(LOG_DEBUG, "%s", line);
+ 	linep = line;
+     }
+     strcpy(linep, buf);
+     linep += n;
+ }
+ 
+ /*
+  * print_string - print a readable representation of a string using
+  * printer.
+  */
+ void
+ print_string(p, len, printer, arg)
+     char *p;
+     int len;
+     void (*printer) __P((void *, char *, ...));
+     void *arg;
+ {
+     int c;
+ 
+     printer(arg, "\"");
+     for (; len > 0; --len) {
+ 	c = *p++;
+ 	if (' ' <= c && c <= '~') {
+ 	    if (c == '\\' || c == '"')
+ 		printer(arg, "\\");
+ 	    printer(arg, "%c", c);
+ 	} else {
+ 	    switch (c) {
+ 	    case '\n':
+ 		printer(arg, "\\n");
+ 		break;
+ 	    case '\r':
+ 		printer(arg, "\\r");
+ 		break;
+ 	    case '\t':
+ 		printer(arg, "\\t");
+ 		break;
+ 	    default:
+ 		printer(arg, "\\%.3o", c);
+ 	    }
+ 	}
+     }
+     printer(arg, "\"");
+ }
+ 
+ /*
+  * novm - log an error message saying we ran out of memory, and die.
+  */
+ void
+ novm(msg)
+     char *msg;
+ {
+     syslog(LOG_ERR, "Virtual memory exhausted allocating %s\n", msg);
+     die(1);
+ }
+ 
+ /*
+  * fmtmsg - format a message into a buffer.  Like sprintf except we
+  * also specify the length of the output buffer, and we handle
+  * %r (recursive format), %m (error message) and %I (IP address) formats.
+  * Doesn't do floating-point formats.
+  * Returns the number of chars put into buf.
+  */
+ int
+ fmtmsg __V((char *buf, int buflen, char *fmt, ...))
+ {
+     va_list args;
+     int n;
+ 
+ #if __STDC__
+     va_start(args, fmt);
+ #else
+     char *buf;
+     int buflen;
+     char *fmt;
+     va_start(args);
+     buf = va_arg(args, char *);
+     buflen = va_arg(args, int);
+     fmt = va_arg(args, char *);
+ #endif
+     n = vfmtmsg(buf, buflen, fmt, args);
+     va_end(args);
+     return n;
+ }
+ 
+ /*
+  * vfmtmsg - like fmtmsg, takes a va_list instead of a list of args.
+  */
+ #define OUTCHAR(c)	(buflen > 0? (--buflen, *buf++ = (c)): 0)
+ 
+ int
+ vfmtmsg(buf, buflen, fmt, args)
+     char *buf;
+     int buflen;
+     char *fmt;
+     va_list args;
+ {
+     int c, i, n;
+     int width, prec, fillch;
+     int base, len, neg, quoted;
+     unsigned long val = 0;
+     char *str, *f, *buf0;
+     unsigned char *p;
+     char num[32];
+     time_t t;
+     static char hexchars[] = "0123456789abcdef";
+ 
+     buf0 = buf;
+     --buflen;
+     while (buflen > 0) {
+ 	for (f = fmt; *f != '%' && *f != 0; ++f)
+ 	    ;
+ 	if (f > fmt) {
+ 	    len = f - fmt;
+ 	    if (len > buflen)
+ 		len = buflen;
+ 	    memcpy(buf, fmt, len);
+ 	    buf += len;
+ 	    buflen -= len;
+ 	    fmt = f;
+ 	}
+ 	if (*fmt == 0)
+ 	    break;
+ 	c = *++fmt;
+ 	width = prec = 0;
+ 	fillch = ' ';
+ 	if (c == '0') {
+ 	    fillch = '0';
+ 	    c = *++fmt;
+ 	}
+ 	if (c == '*') {
+ 	    width = va_arg(args, int);
+ 	    c = *++fmt;
+ 	} else {
+ 	    while (isdigit(c)) {
+ 		width = width * 10 + c - '0';
+ 		c = *++fmt;
+ 	    }
+ 	}
+ 	if (c == '.') {
+ 	    c = *++fmt;
+ 	    if (c == '*') {
+ 		prec = va_arg(args, int);
+ 		c = *++fmt;
+ 	    } else {
+ 		while (isdigit(c)) {
+ 		    prec = prec * 10 + c - '0';
+ 		    c = *++fmt;
+ 		}
+ 	    }
+ 	}
+ 	str = 0;
+ 	base = 0;
+ 	neg = 0;
+ 	++fmt;
+ 	switch (c) {
+ 	case 'd':
+ 	    i = va_arg(args, int);
+ 	    if (i < 0) {
+ 		neg = 1;
+ 		val = -i;
+ 	    } else
+ 		val = i;
+ 	    base = 10;
+ 	    break;
+ 	case 'o':
+ 	    val = va_arg(args, unsigned int);
+ 	    base = 8;
+ 	    break;
+ 	case 'x':
+ 	    val = va_arg(args, unsigned int);
+ 	    base = 16;
+ 	    break;
+ 	case 'p':
+ 	    val = (unsigned long) va_arg(args, void *);
+ 	    base = 16;
+ 	    neg = 2;
+ 	    break;
+ 	case 's':
+ 	    str = va_arg(args, char *);
+ 	    break;
+ 	case 'c':
+ 	    num[0] = va_arg(args, int);
+ 	    num[1] = 0;
+ 	    str = num;
+ 	    break;
+ 	case 'm':
+ 	    str = strerror(errno);
+ 	    break;
+ 	case 'I':
+ 	    str = ip_ntoa(va_arg(args, u_int32_t));
+ 	    break;
+ 	case 'r':
+ 	    f = va_arg(args, char *);
+ #ifndef __powerpc__
+ 	    n = vfmtmsg(buf, buflen + 1, f, va_arg(args, va_list));
+ #else
+ 	    /* On the powerpc, a va_list is an array of 1 structure */
+ 	    n = vfmtmsg(buf, buflen + 1, f, va_arg(args, void *));
+ #endif
+ 	    buf += n;
+ 	    buflen -= n;
+ 	    continue;
+ 	case 't':
+ 	    time(&t);
+ 	    str = ctime(&t);
+ 	    str += 4;		/* chop off the day name */
+ 	    str[15] = 0;	/* chop off year and newline */
+ 	    break;
+ 	case 'v':		/* "visible" string */
+ 	case 'q':		/* quoted string */
+ 	    quoted = c == 'q';
+ 	    p = va_arg(args, unsigned char *);
+ 	    if (fillch == '0' && prec > 0) {
+ 		n = prec;
+ 	    } else {
+ 		n = strlen((char *)p);
+ 		if (prec > 0 && prec < n)
+ 		    n = prec;
+ 	    }
+ 	    while (n > 0 && buflen > 0) {
+ 		c = *p++;
+ 		--n;
+ 		if (!quoted && c >= 0x80) {
+ 		    OUTCHAR('M');
+ 		    OUTCHAR('-');
+ 		    c -= 0x80;
+ 		}
+ 		if (quoted && (c == '"' || c == '\\'))
+ 		    OUTCHAR('\\');
+ 		if (c < 0x20 || (0x7f <= c && c < 0xa0)) {
+ 		    if (quoted) {
+ 			OUTCHAR('\\');
+ 			switch (c) {
+ 			case '\t':	OUTCHAR('t');	break;
+ 			case '\n':	OUTCHAR('n');	break;
+ 			case '\b':	OUTCHAR('b');	break;
+ 			case '\f':	OUTCHAR('f');	break;
+ 			default:
+ 			    OUTCHAR('x');
+ 			    OUTCHAR(hexchars[c >> 4]);
+ 			    OUTCHAR(hexchars[c & 0xf]);
+ 			}
+ 		    } else {
+ 			if (c == '\t')
+ 			    OUTCHAR(c);
+ 			else {
+ 			    OUTCHAR('^');
+ 			    OUTCHAR(c ^ 0x40);
+ 			}
+ 		    }
+ 		} else
+ 		    OUTCHAR(c);
+ 	    }
+ 	    continue;
+ 	default:
+ 	    *buf++ = '%';
+ 	    if (c != '%')
+ 		--fmt;		/* so %z outputs %z etc. */
+ 	    --buflen;
+ 	    continue;
+ 	}
+ 	if (base != 0) {
+ 	    str = num + sizeof(num);
+ 	    *--str = 0;
+ 	    while (str > num + neg) {
+ 		*--str = hexchars[val % base];
+ 		val = val / base;
+ 		if (--prec <= 0 && val == 0)
+ 		    break;
+ 	    }
+ 	    switch (neg) {
+ 	    case 1:
+ 		*--str = '-';
+ 		break;
+ 	    case 2:
+ 		*--str = 'x';
+ 		*--str = '0';
+ 		break;
+ 	    }
+ 	    len = num + sizeof(num) - 1 - str;
+ 	} else {
+ 	    len = strlen(str);
+ 	    if (prec > 0 && len > prec)
+ 		len = prec;
+ 	}
+ 	if (width > 0) {
+ 	    if (width > buflen)
+ 		width = buflen;
+ 	    if ((n = width - len) > 0) {
+ 		buflen -= n;
+ 		for (; n > 0; --n)
+ 		    *buf++ = fillch;
+ 	    }
+ 	}
+ 	if (len > buflen)
+ 	    len = buflen;
+ 	memcpy(buf, str, len);
+ 	buf += len;
+ 	buflen -= len;
+     }
+     *buf = 0;
+     return buf - buf0;
+ }
+ 
+ /*
+  * script_setenv - set an environment variable value to be used
+  * for scripts that we run (e.g. ip-up, auth-up, etc.)
+  */
+ void
+ script_setenv(var, value)
+     char *var, *value;
+ {
+     int vl = strlen(var);
+     int i;
+     char *p, *newstring;
+ 
+     newstring = (char *) malloc(vl + strlen(value) + 2);
+     if (newstring == 0)
+ 	return;
+     strcpy(newstring, var);
+     newstring[vl] = '=';
+     strcpy(newstring+vl+1, value);
+ 
+     /* check if this variable is already set */
+     if (script_env != 0) {
+ 	for (i = 0; (p = script_env[i]) != 0; ++i) {
+ 	    if (strncmp(p, var, vl) == 0 && p[vl] == '=') {
+ 		free(p);
+ 		script_env[i] = newstring;
+ 		return;
+ 	    }
+ 	}
+     } else {
+ 	i = 0;
+ 	script_env = (char **) malloc(16 * sizeof(char *));
+ 	if (script_env == 0)
+ 	    return;
+ 	s_env_nalloc = 16;
+     }
+ 
+     /* reallocate script_env with more space if needed */
+     if (i + 1 >= s_env_nalloc) {
+ 	int new_n = i + 17;
+ 	char **newenv = (char **) realloc((void *)script_env,
+ 					  new_n * sizeof(char *));
+ 	if (newenv == 0)
+ 	    return;
+ 	script_env = newenv;
+ 	s_env_nalloc = new_n;
+     }
+ 
+     script_env[i] = newstring;
+     script_env[i+1] = 0;
+ }
+ 
+ /*
+  * script_unsetenv - remove a variable from the environment
+  * for scripts.
+  */
+ void
+ script_unsetenv(var)
+     char *var;
+ {
+     int vl = strlen(var);
+     int i;
+     char *p;
+ 
+     if (script_env == 0)
+ 	return;
+     for (i = 0; (p = script_env[i]) != 0; ++i) {
+ 	if (strncmp(p, var, vl) == 0 && p[vl] == '=') {
+ 	    free(p);
+ 	    while ((script_env[i] = script_env[i+1]) != 0)
+ 		++i;
+ 	    break;
+ 	}
+     }
+ }
diff -r -P -d -C 3 ppp-2.3.5/pppd/md5.c ppp-2.3.5-2cbcps-radius-multiport/pppd/md5.c
*** ppp-2.3.5/pppd/md5.c	Wed Mar 12 09:32:27 1997
--- ppp-2.3.5-2cbcps-radius-multiport/pppd/md5.c	Sun Jan 24 14:36:50 1999
***************
*** 1,306 ****
  
  
! /*
!  ***********************************************************************
!  ** md5.c -- the source code for MD5 routines                         **
!  ** RSA Data Security, Inc. MD5 Message-Digest Algorithm              **
!  ** Created: 2/17/90 RLR                                              **
!  ** Revised: 1/91 SRD,AJ,BSK,JT Reference C ver., 7/10 constant corr. **
!  ***********************************************************************
!  */
  
! /*
!  ***********************************************************************
!  ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved.  **
!  **                                                                   **
!  ** License to copy and use this software is granted provided that    **
!  ** it is identified as the "RSA Data Security, Inc. MD5 Message-     **
!  ** Digest Algorithm" in all material mentioning or referencing this  **
!  ** software or this function.                                        **
!  **                                                                   **
!  ** License is also granted to make and use derivative works          **
!  ** provided that such works are identified as "derived from the RSA  **
!  ** Data Security, Inc. MD5 Message-Digest Algorithm" in all          **
!  ** material mentioning or referencing the derived work.              **
!  **                                                                   **
!  ** RSA Data Security, Inc. makes no representations concerning       **
!  ** either the merchantability of this software or the suitability    **
!  ** of this software for any particular purpose.  It is provided "as  **
!  ** is" without express or implied warranty of any kind.              **
!  **                                                                   **
!  ** These notices must be retained in any copies of any part of this  **
!  ** documentation and/or software.                                    **
!  ***********************************************************************
   */
  
  #include "md5.h"
  
! /*
!  ***********************************************************************
!  **  Message-digest routines:                                         **
!  **  To form the message digest for a message M                       **
!  **    (1) Initialize a context buffer mdContext using MD5Init        **
!  **    (2) Call MD5Update on mdContext and M                          **
!  **    (3) Call MD5Final on mdContext                                 **
!  **  The message digest is now in mdContext->digest[0...15]           **
!  ***********************************************************************
   */
  
! /* forward declaration */
! static void Transform ();
  
  static unsigned char PADDING[64] = {
!   0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
!   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
!   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
!   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
!   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
!   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
!   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
!   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  };
  
! /* F, G, H and I are basic MD5 functions */
  #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
  #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
  #define H(x, y, z) ((x) ^ (y) ^ (z))
  #define I(x, y, z) ((y) ^ ((x) | (~z)))
  
! /* ROTATE_LEFT rotates x left n bits */
  #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
  
! /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */
! /* Rotation is separate from addition to prevent recomputation */
! #define FF(a, b, c, d, x, s, ac) \
!   {(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
!    (a) = ROTATE_LEFT ((a), (s)); \
!    (a) += (b); \
    }
! #define GG(a, b, c, d, x, s, ac) \
!   {(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
!    (a) = ROTATE_LEFT ((a), (s)); \
!    (a) += (b); \
    }
! #define HH(a, b, c, d, x, s, ac) \
!   {(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
!    (a) = ROTATE_LEFT ((a), (s)); \
!    (a) += (b); \
    }
! #define II(a, b, c, d, x, s, ac) \
!   {(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
!    (a) = ROTATE_LEFT ((a), (s)); \
!    (a) += (b); \
    }
  
! #ifdef __STDC__
! #define UL(x)	x##U
! #else
! #define UL(x)	x
! #endif
  
! /* The routine MD5Init initializes the message-digest context
!    mdContext. All fields are set to zero.
   */
! void MD5Init (mdContext)
! MD5_CTX *mdContext;
  {
!   mdContext->i[0] = mdContext->i[1] = (UINT4)0;
  
!   /* Load magic initialization constants.
!    */
!   mdContext->buf[0] = (UINT4)0x67452301;
!   mdContext->buf[1] = (UINT4)0xefcdab89;
!   mdContext->buf[2] = (UINT4)0x98badcfe;
!   mdContext->buf[3] = (UINT4)0x10325476;
  }
  
! /* The routine MD5Update updates the message-digest context to
!    account for the presence of each of the characters inBuf[0..inLen-1]
!    in the message whose digest is being computed.
   */
! void MD5Update (mdContext, inBuf, inLen)
! MD5_CTX *mdContext;
! unsigned char *inBuf;
! unsigned int inLen;
  {
!   UINT4 in[16];
!   int mdi;
!   unsigned int i, ii;
  
!   /* compute number of bytes mod 64 */
!   mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
  
!   /* update number of bits */
!   if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0])
!     mdContext->i[1]++;
!   mdContext->i[0] += ((UINT4)inLen << 3);
!   mdContext->i[1] += ((UINT4)inLen >> 29);
  
!   while (inLen--) {
!     /* add new character to buffer, increment mdi */
!     mdContext->in[mdi++] = *inBuf++;
  
!     /* transform if necessary */
!     if (mdi == 0x40) {
!       for (i = 0, ii = 0; i < 16; i++, ii += 4)
!         in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
!                 (((UINT4)mdContext->in[ii+2]) << 16) |
!                 (((UINT4)mdContext->in[ii+1]) << 8) |
!                 ((UINT4)mdContext->in[ii]);
!       Transform (mdContext->buf, in);
!       mdi = 0;
!     }
!   }
  }
  
! /* The routine MD5Final terminates the message-digest computation and
!    ends with the desired message digest in mdContext->digest[0...15].
   */
! void MD5Final (hash, mdContext)
! unsigned char hash[];
! MD5_CTX *mdContext;
  {
!   UINT4 in[16];
!   int mdi;
!   unsigned int i, ii;
!   unsigned int padLen;
  
!   /* save number of bits */
!   in[14] = mdContext->i[0];
!   in[15] = mdContext->i[1];
  
!   /* compute number of bytes mod 64 */
!   mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
  
!   /* pad out to 56 mod 64 */
!   padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi);
!   MD5Update (mdContext, PADDING, padLen);
  
!   /* append length in bits and transform */
!   for (i = 0, ii = 0; i < 14; i++, ii += 4)
!     in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
!             (((UINT4)mdContext->in[ii+2]) << 16) |
!             (((UINT4)mdContext->in[ii+1]) << 8) |
!             ((UINT4)mdContext->in[ii]);
!   Transform (mdContext->buf, in);
  
!   /* store buffer in digest */
!   for (i = 0, ii = 0; i < 4; i++, ii += 4) {
!     mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF);
!     mdContext->digest[ii+1] =
!       (unsigned char)((mdContext->buf[i] >> 8) & 0xFF);
!     mdContext->digest[ii+2] =
!       (unsigned char)((mdContext->buf[i] >> 16) & 0xFF);
!     mdContext->digest[ii+3] =
!       (unsigned char)((mdContext->buf[i] >> 24) & 0xFF);
!   }
!   memcpy(hash, mdContext->digest, 16);
  }
  
! /* Basic MD5 step. Transforms buf based on in.
   */
! static void Transform (buf, in)
! UINT4 *buf;
! UINT4 *in;
  {
!   UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
  
!   /* Round 1 */
! #define S11 7
! #define S12 12
! #define S13 17
! #define S14 22
!   FF ( a, b, c, d, in[ 0], S11, UL(3614090360)); /* 1 */
!   FF ( d, a, b, c, in[ 1], S12, UL(3905402710)); /* 2 */
!   FF ( c, d, a, b, in[ 2], S13, UL( 606105819)); /* 3 */
!   FF ( b, c, d, a, in[ 3], S14, UL(3250441966)); /* 4 */
!   FF ( a, b, c, d, in[ 4], S11, UL(4118548399)); /* 5 */
!   FF ( d, a, b, c, in[ 5], S12, UL(1200080426)); /* 6 */
!   FF ( c, d, a, b, in[ 6], S13, UL(2821735955)); /* 7 */
!   FF ( b, c, d, a, in[ 7], S14, UL(4249261313)); /* 8 */
!   FF ( a, b, c, d, in[ 8], S11, UL(1770035416)); /* 9 */
!   FF ( d, a, b, c, in[ 9], S12, UL(2336552879)); /* 10 */
!   FF ( c, d, a, b, in[10], S13, UL(4294925233)); /* 11 */
!   FF ( b, c, d, a, in[11], S14, UL(2304563134)); /* 12 */
!   FF ( a, b, c, d, in[12], S11, UL(1804603682)); /* 13 */
!   FF ( d, a, b, c, in[13], S12, UL(4254626195)); /* 14 */
!   FF ( c, d, a, b, in[14], S13, UL(2792965006)); /* 15 */
!   FF ( b, c, d, a, in[15], S14, UL(1236535329)); /* 16 */
  
!   /* Round 2 */
! #define S21 5
! #define S22 9
! #define S23 14
! #define S24 20
!   GG ( a, b, c, d, in[ 1], S21, UL(4129170786)); /* 17 */
!   GG ( d, a, b, c, in[ 6], S22, UL(3225465664)); /* 18 */
!   GG ( c, d, a, b, in[11], S23, UL( 643717713)); /* 19 */
!   GG ( b, c, d, a, in[ 0], S24, UL(3921069994)); /* 20 */
!   GG ( a, b, c, d, in[ 5], S21, UL(3593408605)); /* 21 */
!   GG ( d, a, b, c, in[10], S22, UL(  38016083)); /* 22 */
!   GG ( c, d, a, b, in[15], S23, UL(3634488961)); /* 23 */
!   GG ( b, c, d, a, in[ 4], S24, UL(3889429448)); /* 24 */
!   GG ( a, b, c, d, in[ 9], S21, UL( 568446438)); /* 25 */
!   GG ( d, a, b, c, in[14], S22, UL(3275163606)); /* 26 */
!   GG ( c, d, a, b, in[ 3], S23, UL(4107603335)); /* 27 */
!   GG ( b, c, d, a, in[ 8], S24, UL(1163531501)); /* 28 */
!   GG ( a, b, c, d, in[13], S21, UL(2850285829)); /* 29 */
!   GG ( d, a, b, c, in[ 2], S22, UL(4243563512)); /* 30 */
!   GG ( c, d, a, b, in[ 7], S23, UL(1735328473)); /* 31 */
!   GG ( b, c, d, a, in[12], S24, UL(2368359562)); /* 32 */
  
!   /* Round 3 */
! #define S31 4
! #define S32 11
! #define S33 16
! #define S34 23
!   HH ( a, b, c, d, in[ 5], S31, UL(4294588738)); /* 33 */
!   HH ( d, a, b, c, in[ 8], S32, UL(2272392833)); /* 34 */
!   HH ( c, d, a, b, in[11], S33, UL(1839030562)); /* 35 */
!   HH ( b, c, d, a, in[14], S34, UL(4259657740)); /* 36 */
!   HH ( a, b, c, d, in[ 1], S31, UL(2763975236)); /* 37 */
!   HH ( d, a, b, c, in[ 4], S32, UL(1272893353)); /* 38 */
!   HH ( c, d, a, b, in[ 7], S33, UL(4139469664)); /* 39 */
!   HH ( b, c, d, a, in[10], S34, UL(3200236656)); /* 40 */
!   HH ( a, b, c, d, in[13], S31, UL( 681279174)); /* 41 */
!   HH ( d, a, b, c, in[ 0], S32, UL(3936430074)); /* 42 */
!   HH ( c, d, a, b, in[ 3], S33, UL(3572445317)); /* 43 */
!   HH ( b, c, d, a, in[ 6], S34, UL(  76029189)); /* 44 */
!   HH ( a, b, c, d, in[ 9], S31, UL(3654602809)); /* 45 */
!   HH ( d, a, b, c, in[12], S32, UL(3873151461)); /* 46 */
!   HH ( c, d, a, b, in[15], S33, UL( 530742520)); /* 47 */
!   HH ( b, c, d, a, in[ 2], S34, UL(3299628645)); /* 48 */
  
!   /* Round 4 */
! #define S41 6
! #define S42 10
! #define S43 15
! #define S44 21
!   II ( a, b, c, d, in[ 0], S41, UL(4096336452)); /* 49 */
!   II ( d, a, b, c, in[ 7], S42, UL(1126891415)); /* 50 */
!   II ( c, d, a, b, in[14], S43, UL(2878612391)); /* 51 */
!   II ( b, c, d, a, in[ 5], S44, UL(4237533241)); /* 52 */
!   II ( a, b, c, d, in[12], S41, UL(1700485571)); /* 53 */
!   II ( d, a, b, c, in[ 3], S42, UL(2399980690)); /* 54 */
!   II ( c, d, a, b, in[10], S43, UL(4293915773)); /* 55 */
!   II ( b, c, d, a, in[ 1], S44, UL(2240044497)); /* 56 */
!   II ( a, b, c, d, in[ 8], S41, UL(1873313359)); /* 57 */
!   II ( d, a, b, c, in[15], S42, UL(4264355552)); /* 58 */
!   II ( c, d, a, b, in[ 6], S43, UL(2734768916)); /* 59 */
!   II ( b, c, d, a, in[13], S44, UL(1309151649)); /* 60 */
!   II ( a, b, c, d, in[ 4], S41, UL(4149444226)); /* 61 */
!   II ( d, a, b, c, in[11], S42, UL(3174756917)); /* 62 */
!   II ( c, d, a, b, in[ 2], S43, UL( 718787259)); /* 63 */
!   II ( b, c, d, a, in[ 9], S44, UL(3951481745)); /* 64 */
  
!   buf[0] += a;
!   buf[1] += b;
!   buf[2] += c;
!   buf[3] += d;
  }
  
! /*
!  ***********************************************************************
!  ** End of md5.c                                                      **
!  ******************************** (cut) ********************************
   */
--- 1,370 ----
+ /* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
+  */
  
+ /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+ rights reserved.
  
! License to copy and use this software is granted provided that it
! is identified as the "RSA Data Security, Inc. MD5 Message-Digest
! Algorithm" in all material mentioning or referencing this software
! or this function.
  
! License is also granted to make and use derivative works provided
! that such works are identified as "derived from the RSA Data
! Security, Inc. MD5 Message-Digest Algorithm" in all material
! mentioning or referencing the derived work.
! 
! RSA Data Security, Inc. makes no representations concerning either
! the merchantability of this software or the suitability of this
! software for any particular purpose. It is provided "as is"
! without express or implied warranty of any kind.
! 
! These notices must be retained in any copies of any part of this
! documentation and/or software.
   */
  
  #include "md5.h"
  
! /* Constants for MD5Transform routine.
   */
+ #define S11 7
+ #define S12 12
+ #define S13 17
+ #define S14 22
+ #define S21 5
+ #define S22 9
+ #define S23 14
+ #define S24 20
+ #define S31 4
+ #define S32 11
+ #define S33 16
+ #define S34 23
+ #define S41 6
+ #define S42 10
+ #define S43 15
+ #define S44 21
  
! static void MD5Transform PROTO_LIST ((UINT4[4], unsigned char[64]));
! static void Encode PROTO_LIST
!                 ((unsigned char *, UINT4 *, unsigned int));
! static void Decode PROTO_LIST
!                 ((UINT4 *, unsigned char *, unsigned int));
! static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int));
! static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int));
  
  static unsigned char PADDING[64] = {
! 	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
! 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
! 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  };
  
! /* F, G, H and I are basic MD5 functions.
!  */
  #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
  #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
  #define H(x, y, z) ((x) ^ (y) ^ (z))
  #define I(x, y, z) ((y) ^ ((x) | (~z)))
  
! /* ROTATE_LEFT rotates x left n bits.
!  */
  #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
  
! /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
! Rotation is separate from addition to prevent recomputation.
!  */
! #define FF(a, b, c, d, x, s, ac) { \
!  (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
!  (a) = ROTATE_LEFT ((a), (s)); \
!  (a) += (b); \
    }
! #define GG(a, b, c, d, x, s, ac) { \
!  (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
!  (a) = ROTATE_LEFT ((a), (s)); \
!  (a) += (b); \
    }
! #define HH(a, b, c, d, x, s, ac) { \
!  (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
!  (a) = ROTATE_LEFT ((a), (s)); \
!  (a) += (b); \
    }
! #define II(a, b, c, d, x, s, ac) { \
!  (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
!  (a) = ROTATE_LEFT ((a), (s)); \
!  (a) += (b); \
    }
  
! md5_calc (output, input, inlen)
! unsigned char  *output;
! unsigned char  *input;		/* input block */
! unsigned int    inlen;		/* length of input block */
! {
! 	MD5_CTX         context;
  
! 	MD5Init (&context);
! 	MD5Update (&context, input, inlen);
! 	MD5Final (output, &context);
! }
! 
! /* MD5 initialization. Begins an MD5 operation, writing a new context.
   */
! void 
! MD5Init (context)
! MD5_CTX        *context;	/* context */
  {
! 	context->count[0] = context->count[1] = 0;
  
! 	/*
! 	 * Load magic initialization constants.
! 	 */
! 	context->state[0] = 0x67452301;
! 	context->state[1] = 0xefcdab89;
! 	context->state[2] = 0x98badcfe;
! 	context->state[3] = 0x10325476;
  }
  
! /* MD5 block update operation. Continues an MD5 message-digest
!   operation, processing another message block, and updating the
!   context.
   */
! void 
! MD5Update (context, input, inputLen)
! MD5_CTX        *context;	/* context */
! unsigned char  *input;		/* input block */
! unsigned int    inputLen;	/* length of input block */
  {
! 	unsigned int    i,
! 	                index,
! 	                partLen;
  
! 	/* Compute number of bytes mod 64 */
! 	index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
  
! 	/* Update number of bits */
! 	if ((context->count[0] += ((UINT4) inputLen << 3))
! 			< ((UINT4) inputLen << 3))
! 		context->count[1]++;
! 	context->count[1] += ((UINT4) inputLen >> 29);
  
! 	partLen = 64 - index;
  
! 	/*
! 	 * Transform as many times as possible.
! 	 */
! 	if (inputLen >= partLen)
! 	{
! 		MD5_memcpy
! 			((POINTER) & context->buffer[index], (POINTER) input, partLen);
! 		MD5Transform (context->state, context->buffer);
! 
! 		for (i = partLen; i + 63 < inputLen; i += 64)
! 			MD5Transform (context->state, &input[i]);
! 
! 		index = 0;
! 	}
! 	else
! 		i = 0;
! 
! 	/* Buffer remaining input */
! 	MD5_memcpy
! 		((POINTER) & context->buffer[index], (POINTER) & input[i],
! 		 inputLen - i);
  }
  
! /* MD5 finalization. Ends an MD5 message-digest operation, writing the
!   the message digest and zeroizing the context.
   */
! void 
! MD5Final (digest, context)
! unsigned char   digest[16];	/* message digest */
! MD5_CTX        *context;	/* context */
  {
! 	unsigned char   bits[8];
! 	unsigned int    index,
! 	                padLen;
  
! 	/* Save number of bits */
! 	Encode (bits, context->count, 8);
  
! 	/*
! 	 * Pad out to 56 mod 64.
! 	 */
! 	index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
! 	padLen = (index < 56) ? (56 - index) : (120 - index);
! 	MD5Update (context, PADDING, padLen);
  
! 	/* Append length (before padding) */
! 	MD5Update (context, bits, 8);
  
! 	/* Store state in digest */
! 	Encode (digest, context->state, 16);
  
! 	/*
! 	 * Zeroize sensitive information.
! 	 */
! 	MD5_memset ((POINTER) context, 0, sizeof (*context));
  }
  
! /* MD5 basic transformation. Transforms state based on block.
   */
! static void 
! MD5Transform (state, block)
! UINT4           state[4];
! unsigned char   block[64];
  {
! 	UINT4           a = state[0],
! 	                b = state[1],
! 	                c = state[2],
! 	                d = state[3],
! 	                x[16];
  
! 	Decode (x, block, 64);
  
! 	/* Round 1 */
! 	FF (a, b, c, d, x[0], S11, 0xd76aa478);	/* 1 */
! 	FF (d, a, b, c, x[1], S12, 0xe8c7b756);	/* 2 */
! 	FF (c, d, a, b, x[2], S13, 0x242070db);	/* 3 */
! 	FF (b, c, d, a, x[3], S14, 0xc1bdceee);	/* 4 */
! 	FF (a, b, c, d, x[4], S11, 0xf57c0faf);	/* 5 */
! 	FF (d, a, b, c, x[5], S12, 0x4787c62a);	/* 6 */
! 	FF (c, d, a, b, x[6], S13, 0xa8304613);	/* 7 */
! 	FF (b, c, d, a, x[7], S14, 0xfd469501);	/* 8 */
! 	FF (a, b, c, d, x[8], S11, 0x698098d8);	/* 9 */
! 	FF (d, a, b, c, x[9], S12, 0x8b44f7af);	/* 10 */
! 	FF (c, d, a, b, x[10], S13, 0xffff5bb1);	/* 11 */
! 	FF (b, c, d, a, x[11], S14, 0x895cd7be);	/* 12 */
! 	FF (a, b, c, d, x[12], S11, 0x6b901122);	/* 13 */
! 	FF (d, a, b, c, x[13], S12, 0xfd987193);	/* 14 */
! 	FF (c, d, a, b, x[14], S13, 0xa679438e);	/* 15 */
! 	FF (b, c, d, a, x[15], S14, 0x49b40821);	/* 16 */
  
! 	/* Round 2 */
! 	GG (a, b, c, d, x[1], S21, 0xf61e2562);	/* 17 */
! 	GG (d, a, b, c, x[6], S22, 0xc040b340);	/* 18 */
! 	GG (c, d, a, b, x[11], S23, 0x265e5a51);	/* 19 */
! 	GG (b, c, d, a, x[0], S24, 0xe9b6c7aa);	/* 20 */
! 	GG (a, b, c, d, x[5], S21, 0xd62f105d);	/* 21 */
! 	GG (d, a, b, c, x[10], S22, 0x2441453);	/* 22 */
! 	GG (c, d, a, b, x[15], S23, 0xd8a1e681);	/* 23 */
! 	GG (b, c, d, a, x[4], S24, 0xe7d3fbc8);	/* 24 */
! 	GG (a, b, c, d, x[9], S21, 0x21e1cde6);	/* 25 */
! 	GG (d, a, b, c, x[14], S22, 0xc33707d6);	/* 26 */
! 	GG (c, d, a, b, x[3], S23, 0xf4d50d87);	/* 27 */
! 	GG (b, c, d, a, x[8], S24, 0x455a14ed);	/* 28 */
! 	GG (a, b, c, d, x[13], S21, 0xa9e3e905);	/* 29 */
! 	GG (d, a, b, c, x[2], S22, 0xfcefa3f8);	/* 30 */
! 	GG (c, d, a, b, x[7], S23, 0x676f02d9);	/* 31 */
! 	GG (b, c, d, a, x[12], S24, 0x8d2a4c8a);	/* 32 */
  
! 	/* Round 3 */
! 	HH (a, b, c, d, x[5], S31, 0xfffa3942);	/* 33 */
! 	HH (d, a, b, c, x[8], S32, 0x8771f681);	/* 34 */
! 	HH (c, d, a, b, x[11], S33, 0x6d9d6122);	/* 35 */
! 	HH (b, c, d, a, x[14], S34, 0xfde5380c);	/* 36 */
! 	HH (a, b, c, d, x[1], S31, 0xa4beea44);	/* 37 */
! 	HH (d, a, b, c, x[4], S32, 0x4bdecfa9);	/* 38 */
! 	HH (c, d, a, b, x[7], S33, 0xf6bb4b60);	/* 39 */
! 	HH (b, c, d, a, x[10], S34, 0xbebfbc70);	/* 40 */
! 	HH (a, b, c, d, x[13], S31, 0x289b7ec6);	/* 41 */
! 	HH (d, a, b, c, x[0], S32, 0xeaa127fa);	/* 42 */
! 	HH (c, d, a, b, x[3], S33, 0xd4ef3085);	/* 43 */
! 	HH (b, c, d, a, x[6], S34, 0x4881d05);	/* 44 */
! 	HH (a, b, c, d, x[9], S31, 0xd9d4d039);	/* 45 */
! 	HH (d, a, b, c, x[12], S32, 0xe6db99e5);	/* 46 */
! 	HH (c, d, a, b, x[15], S33, 0x1fa27cf8);	/* 47 */
! 	HH (b, c, d, a, x[2], S34, 0xc4ac5665);	/* 48 */
  
! 	/* Round 4 */
! 	II (a, b, c, d, x[0], S41, 0xf4292244);	/* 49 */
! 	II (d, a, b, c, x[7], S42, 0x432aff97);	/* 50 */
! 	II (c, d, a, b, x[14], S43, 0xab9423a7);	/* 51 */
! 	II (b, c, d, a, x[5], S44, 0xfc93a039);	/* 52 */
! 	II (a, b, c, d, x[12], S41, 0x655b59c3);	/* 53 */
! 	II (d, a, b, c, x[3], S42, 0x8f0ccc92);	/* 54 */
! 	II (c, d, a, b, x[10], S43, 0xffeff47d);	/* 55 */
! 	II (b, c, d, a, x[1], S44, 0x85845dd1);	/* 56 */
! 	II (a, b, c, d, x[8], S41, 0x6fa87e4f);	/* 57 */
! 	II (d, a, b, c, x[15], S42, 0xfe2ce6e0);	/* 58 */
! 	II (c, d, a, b, x[6], S43, 0xa3014314);	/* 59 */
! 	II (b, c, d, a, x[13], S44, 0x4e0811a1);	/* 60 */
! 	II (a, b, c, d, x[4], S41, 0xf7537e82);	/* 61 */
! 	II (d, a, b, c, x[11], S42, 0xbd3af235);	/* 62 */
! 	II (c, d, a, b, x[2], S43, 0x2ad7d2bb);	/* 63 */
! 	II (b, c, d, a, x[9], S44, 0xeb86d391);	/* 64 */
! 
! 	state[0] += a;
! 	state[1] += b;
! 	state[2] += c;
! 	state[3] += d;
! 
! 	/*
! 	 * Zeroize sensitive information.
! 	 */
! 	MD5_memset ((POINTER) x, 0, sizeof (x));
  }
  
! /* Encodes input (UINT4) into output (unsigned char). Assumes len is
!   a multiple of 4.
!  */
! static void 
! Encode (output, input, len)
! unsigned char  *output;
! UINT4          *input;
! unsigned int    len;
! {
! 	unsigned int    i,
! 	                j;
! 
! 	for (i = 0, j = 0; j < len; i++, j += 4)
! 	{
! 		output[j] = (unsigned char) (input[i] & 0xff);
! 		output[j + 1] = (unsigned char) ((input[i] >> 8) & 0xff);
! 		output[j + 2] = (unsigned char) ((input[i] >> 16) & 0xff);
! 		output[j + 3] = (unsigned char) ((input[i] >> 24) & 0xff);
! 	}
! }
! 
! /* Decodes input (unsigned char) into output (UINT4). Assumes len is
!   a multiple of 4.
!  */
! static void 
! Decode (output, input, len)
! UINT4          *output;
! unsigned char  *input;
! unsigned int    len;
! {
! 	unsigned int    i,
! 	                j;
! 
! 	for (i = 0, j = 0; j < len; i++, j += 4)
! 		output[i] = ((UINT4) input[j]) | (((UINT4) input[j + 1]) << 8) |
! 			(((UINT4) input[j + 2]) << 16) | (((UINT4) input[j + 3]) << 24);
! }
! 
! /* Note: Replace "for loop" with standard memcpy if possible.
   */
+ 
+ static void 
+ MD5_memcpy (output, input, len)
+ POINTER         output;
+ POINTER         input;
+ unsigned int    len;
+ {
+ 	unsigned int    i;
+ 
+ 	for (i = 0; i < len; i++)
+ 		output[i] = input[i];
+ }
+ 
+ /* Note: Replace "for loop" with standard memset if possible.
+  */
+ static void 
+ MD5_memset (output, value, len)
+ POINTER         output;
+ int             value;
+ unsigned int    len;
+ {
+ 	unsigned int    i;
+ 
+ 	for (i = 0; i < len; i++)
+ 		((char *) output)[i] = (char) value;
+ }
diff -r -P -d -C 3 ppp-2.3.5/pppd/md5.h ppp-2.3.5-2cbcps-radius-multiport/pppd/md5.h
*** ppp-2.3.5/pppd/md5.h	Fri Sep 13 09:52:53 1996
--- ppp-2.3.5-2cbcps-radius-multiport/pppd/md5.h	Sun Jan 24 14:36:50 1999
***************
*** 1,58 ****
! /*
!  ***********************************************************************
!  ** md5.h -- header file for implementation of MD5                    **
!  ** RSA Data Security, Inc. MD5 Message-Digest Algorithm              **
!  ** Created: 2/17/90 RLR                                              **
!  ** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version               **
!  ** Revised (for MD5): RLR 4/27/91                                    **
!  **   -- G modified to have y&~z instead of y&z                       **
!  **   -- FF, GG, HH modified to add in last register done             **
!  **   -- Access pattern: round 2 works mod 5, round 3 works mod 3     **
!  **   -- distinct additive constant for each step                     **
!  **   -- round 4 added, working mod 7                                 **
!  ***********************************************************************
   */
  
! /*
!  ***********************************************************************
!  ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved.  **
!  **                                                                   **
!  ** License to copy and use this software is granted provided that    **
!  ** it is identified as the "RSA Data Security, Inc. MD5 Message-     **
!  ** Digest Algorithm" in all material mentioning or referencing this  **
!  ** software or this function.                                        **
!  **                                                                   **
!  ** License is also granted to make and use derivative works          **
!  ** provided that such works are identified as "derived from the RSA  **
!  ** Data Security, Inc. MD5 Message-Digest Algorithm" in all          **
!  ** material mentioning or referencing the derived work.              **
!  **                                                                   **
!  ** RSA Data Security, Inc. makes no representations concerning       **
!  ** either the merchantability of this software or the suitability    **
!  ** of this software for any particular purpose.  It is provided "as  **
!  ** is" without express or implied warranty of any kind.              **
!  **                                                                   **
!  ** These notices must be retained in any copies of any part of this  **
!  ** documentation and/or software.                                    **
!  ***********************************************************************
   */
  
! #ifndef __MD5_INCLUDE__
  
! /* typedef a 32-bit type */
  typedef unsigned int UINT4;
  
! /* Data structure for MD5 (Message-Digest) computation */
! typedef struct {
!   UINT4 i[2];                   /* number of _bits_ handled mod 2^64 */
!   UINT4 buf[4];                                    /* scratch buffer */
!   unsigned char in[64];                              /* input buffer */
!   unsigned char digest[16];     /* actual digest after MD5Final call */
! } MD5_CTX;
  
! void MD5Init ();
! void MD5Update ();
! void MD5Final ();
  
! #define __MD5_INCLUDE__
! #endif /* __MD5_INCLUDE__ */
--- 1,73 ----
! /* GLOBAL.H - RSAREF types and constants
   */
  
! /* PROTOTYPES should be set to one if and only if the compiler supports
!   function argument prototyping.
!   The following makes PROTOTYPES default to 0 if it has not already
!   been defined with C compiler flags.
   */
  
! #ifndef PROTOTYPES
! #define PROTOTYPES 0
! #endif
  
! /* POINTER defines a generic pointer type */
! typedef unsigned char *POINTER;
! 
! /* UINT2 defines a two byte word */
! typedef unsigned short int UINT2;
! 
! /* UINT4 defines a four byte word */
! #if defined(__alpha) && defined(__osf__)
  typedef unsigned int UINT4;
+ #else
+ typedef unsigned long int UINT4;
+ #endif
  
! /* PROTO_LIST is defined depending on how PROTOTYPES is defined above.
!    If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it
!   returns an empty list.
!  */
  
! #if PROTOTYPES
! #define PROTO_LIST(list) list
! #else
! #define PROTO_LIST(list) ()
! #endif
  
! /* MD5.H - header file for MD5C.C
!  */
! 
! /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
! rights reserved.
! 
! License to copy and use this software is granted provided that it
! is identified as the "RSA Data Security, Inc. MD5 Message-Digest
! Algorithm" in all material mentioning or referencing this software
! or this function.
! 
! License is also granted to make and use derivative works provided
! that such works are identified as "derived from the RSA Data
! Security, Inc. MD5 Message-Digest Algorithm" in all material
! mentioning or referencing the derived work.
! 
! RSA Data Security, Inc. makes no representations concerning either
! the merchantability of this software or the suitability of this
! software for any particular purpose. It is provided "as is"
! without express or implied warranty of any kind.
! 
! These notices must be retained in any copies of any part of this
! documentation and/or software.
!  */
! 
! /* MD5 context. */
! typedef struct
! {
! 	UINT4           state[4];  /* state (ABCD) */
! 	UINT4           count[2];  /* number of bits, modulo 2^64 (lsb first) */
! 	unsigned char   buffer[64]; /* input buffer */
! } MD5_CTX;
! 
! void MD5Init    PROTO_LIST ((MD5_CTX *));
! void MD5Update  PROTO_LIST ((MD5_CTX *, unsigned char *, unsigned int));
! void MD5Final   PROTO_LIST ((unsigned char[16], MD5_CTX *));
diff -r -P -d -C 3 ppp-2.3.5/pppd/options.c ppp-2.3.5-2cbcps-radius-multiport/pppd/options.c
*** ppp-2.3.5/pppd/options.c	Thu Mar 26 09:46:07 1998
--- ppp-2.3.5-2cbcps-radius-multiport/pppd/options.c	Sun Jan 16 14:16:59 2000
***************
*** 50,55 ****
--- 50,56 ----
  #include "upap.h"
  #include "chap.h"
  #include "ccp.h"
+ #include "cbcps.h"
  #ifdef CBCP_SUPPORT
  #include "cbcp.h"
  #endif
***************
*** 108,117 ****
--- 109,128 ----
  int	demand = 0;		/* do dial-on-demand */
  char	*ipparam = NULL;	/* Extra parameter for ip up/down scripts */
  int	cryptpap;		/* Passwords in pap-secrets are encrypted */
+ char    staticdevnam[MAXPATHLEN] = "/dev/tty";  /* Reserv value - Device name */
+ int     useradius = 0;
+ int     usemultiport = 0;       /* Use Multiport device (c) Ilya Ismailov, TTS, Tyumen, Russian*/
+ int     multiportfist = 0;      /* Fist Multiport device (c) Ilya Ismailov, TTS,Tyumen, Russian*/
+ int     multiportend = 0;       /* End Multiport device (c) Ilya Ismailov, TTS, Tyumen, Russian*/
  int	idle_time_limit = 0;	/* Disconnect if idle for this many seconds */
  int	holdoff = 30;		/* # seconds to pause before reconnecting */
  int	refuse_pap = 0;		/* Set to say we won't do PAP */
  int	refuse_chap = 0;	/* Set to say we won't do CHAP */
+ char	callerid[64];		/* Caller's ID */
+ char	calleridtool[MAXPATHLEN];/* program called to get ID */
+ char	con_state[32];		/* CONNECT string from mgetty log */
+ char	con_tool[MAXPATHLEN];	/* a tool which is called to fill up con_state*/
+  
  
  #ifdef MSLANMAN
  int	ms_lanman = 0;    	/* Nonzero if use LanMan password instead of NT */
***************
*** 158,163 ****
--- 169,177 ----
  static int setescape __P((char **));
  static int setmru __P((char **));
  static int setmtu __P((char **));
+ static int setcbcps __P((char **));
+ static int setcallerid __P((char **));
+ static int setconstate __P((char **));
  #ifdef CBCP_SUPPORT
  static int setcbcp __P((char **));
  #endif
***************
*** 222,227 ****
--- 236,243 ----
  static int setnopred1comp __P((char **));
  static int setipparam __P((char **));
  static int setpapcrypt __P((char **));
+ static int setradius __P((char **));
+ static int setmultiport __P((char **));
  static int setidle __P((char **));
  static int setholdoff __P((char **));
  static int setdnsaddr __P((char **));
***************
*** 317,322 ****
--- 333,341 ----
      {"domain", 1, setdomain},	/* Add given domain name to hostname*/
      {"mru", 1, setmru},		/* Set MRU value for negotiation */
      {"mtu", 1, setmtu},		/* Set our MTU */
+     {"cb", 0, setcbcps},
+     {"callerid", 1, setcallerid},
+     {"connect_state", 1, setconstate},
  #ifdef CBCP_SUPPORT
      {"callback", 1, setcbcp},	/* Ask for callback */
  #endif
***************
*** 377,382 ****
--- 396,403 ----
      {"-predictor1", 0, setnopred1comp},	/* don't allow Predictor-1 */
      {"ipparam", 1, setipparam},		/* set ip script parameter */
      {"papcrypt", 0, setpapcrypt},	/* PAP passwords encrypted */
+     {"radius", 1, setradius},
+     {"multiport", 1, setmultiport},     /* Use Multiport device (c) Ilya Ismailov, TTS, Tyumen, Russian*/
      {"idle", 1, setidle},		/* idle time limit (seconds) */
      {"holdoff", 1, setholdoff},		/* set holdoff time (seconds) */
      {"ms-dns", 1, setdnsaddr},		/* DNS address for the peer's use */
***************
*** 1289,1294 ****
--- 1310,1341 ----
      return (1);
  }
  
+ 
+ static int
+ setcallerid(argv)
+     char **argv;
+ {
+   strcpy(calleridtool,*argv);
+   return (1);
+ }
+ 
+ static int
+ setconstate(argv)
+     char **argv;
+ {
+   strcpy(con_tool,*argv);
+   return (1);
+ }
+ 
+ static int
+ setcbcps(argv)
+     char **argv;
+ {
+  lcp_wantoptions[0].neg_cbcp = 1;   // poslem licitaciu na cbcp
+  lcp_allowoptions[0].neg_cbcp = 1;  // ak bude pytat cbcp potvrdim.
+  cbcp_protent.enabled_flag = 1;     // povolovanie protokolu po novom.
+  return(1);
+ }
  #ifdef CBCP_SUPPORT
  static int
  setcbcp(argv)
***************
*** 1669,1686 ****
       * Check if there is a device by this name.
       */
      if (stat(cp, &statbuf) < 0) {
! 	if (errno == ENOENT || quiet)
! 	    return 0;
! 	option_error("Couldn't stat %s: %m", cp);
! 	return -1;
      }
  
      (void) strncpy(devnam, cp, MAXPATHLEN);
      devnam[MAXPATHLEN-1] = 0;
      default_device = FALSE;
      devnam_info.priv = privileged_option;
-     devnam_info.source = option_source;
-   
      return 1;
  }
  
--- 1716,1733 ----
       * Check if there is a device by this name.
       */
      if (stat(cp, &statbuf) < 0) {
!         if (errno == ENOENT || quiet)
!             return 0;
!         option_error("Couldn't stat %s: %m", cp);
!         return -1;
      }
  
      (void) strncpy(devnam, cp, MAXPATHLEN);
      devnam[MAXPATHLEN-1] = 0;
+     (void) strncpy(staticdevnam, cp, MAXPATHLEN);
+     staticdevnam[MAXPATHLEN-1] = 0;
      default_device = FALSE;
      devnam_info.priv = privileged_option;
      return 1;
  }
  
***************
*** 1776,1781 ****
--- 1823,1894 ----
      return 1;
  }
  
+ 
+ static int setradius (argv)
+     char **argv;
+ {
+     useradius = 1;
+     return radius_init(*argv);
+ }
+ 
+ /*
+  * Use Multiport device (c) Ilya Ismailov, TTS, Tyumen, Russian
+  */
+ static int setmultiport (argv)
+     char **argv;
+ {
+     char str[50];
+     int i, count;
+     char *p = argv[0];
+     char flag = 0;
+ 
+     for(i=0, count=0;i<strlen(p);i++){
+         if( (p[i] >= '0')&&( p[i] <= '9') ){
+             str[count] = p[i];
+             str[count+1] = '\0';
+             count++;
+         }else if( (p[i] == ':') ){
+                 str[i] = '\0';
+                 flag = 1;
+                 break;
+         }else{
+                 flag = 0;
+                 break;
+         }
+     }
+     if( count ){
+         multiportfist = atoi(str);
+         if(flag){
+             for(i = i+1, count=0;i<strlen(p);i++){
+                 if( (p[i] >= '0')&&( p[i] <= '9') ){
+                     str[count] = p[i];
+                     str[count+1] = '\0';
+                     count++;
+                 }else{
+                         break;
+                 }
+             }
+             if( count ){
+                 multiportend = atoi(str);
+                 if( multiportend < multiportfist){
+                     usemultiport = 0;
+                     /*  syslog(LOG_ERR, "Option 'multiport': invalid parameter '%s'.", *argv);*/
+                     option_error("option 'multiport': invalid parameter '%s'", *argv);
+                     return 0;
+                 }
+             }else{
+                 multiportend = -1;
+             }
+         }
+     }else{
+         usemultiport = 0;
+ /*      syslog(LOG_ERR, "Option 'multiport': invalid parameter '%s'.", *argv);*/
+         option_error("option 'multiport': invalid parameter '%s'", *argv);
+         return 0;
+     }
+     usemultiport = 1;
+     return 1;
+ }
  
  /*
   * setipcpaccr - accept peer's idea of its address
diff -r -P -d -C 3 ppp-2.3.5/pppd/options.c.orig ppp-2.3.5-2cbcps-radius-multiport/pppd/options.c.orig
*** ppp-2.3.5/pppd/options.c.orig	Thu Jan  1 05:00:00 1970
--- ppp-2.3.5-2cbcps-radius-multiport/pppd/options.c.orig	Thu Aug 19 15:19:32 1999
***************
*** 0 ****
--- 1,2627 ----
+ /*
+  * options.c - handles option processing for PPP.
+  *
+  * Copyright (c) 1989 Carnegie Mellon University.
+  * All rights reserved.
+  *
+  * Redistribution and use in source and binary forms are permitted
+  * provided that the above copyright notice and this paragraph are
+  * duplicated in all such forms and that any documentation,
+  * advertising materials, and other materials related to such
+  * distribution and use acknowledge that the software was developed
+  * by Carnegie Mellon University.  The name of the
+  * University may not be used to endorse or promote products derived
+  * from this software without specific prior written permission.
+  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+  */
+ 
+ #ifndef lint
+ static char rcsid[] = "$Id: options.c,v 1.42 1998/03/26 04:46:06 paulus Exp $";
+ #endif
+ 
+ #include <ctype.h>
+ #include <stdio.h>
+ #include <errno.h>
+ #include <unistd.h>
+ #include <limits.h>
+ #include <stdlib.h>
+ #include <termios.h>
+ #include <syslog.h>
+ #include <string.h>
+ #include <netdb.h>
+ #include <pwd.h>
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+ #ifdef PPP_FILTER
+ #include <pcap.h>
+ #include <pcap-int.h>	/* XXX: To get struct pcap */
+ #endif
+ 
+ #include "pppd.h"
+ #include "pathnames.h"
+ #include "patchlevel.h"
+ #include "fsm.h"
+ #include "lcp.h"
+ #include "ipcp.h"
+ #include "upap.h"
+ #include "chap.h"
+ #include "ccp.h"
+ #include "cbcps.h"
+ #ifdef CBCP_SUPPORT
+ #include "cbcp.h"
+ #endif
+ 
+ #ifdef IPX_CHANGE
+ #include "ipxcp.h"
+ #endif /* IPX_CHANGE */
+ 
+ #include <net/ppp-comp.h>
+ 
+ #define FALSE	0
+ #define TRUE	1
+ 
+ #if defined(ultrix) || defined(NeXT)
+ char *strdup __P((char *));
+ #endif
+ 
+ #ifndef GIDSET_TYPE
+ #define GIDSET_TYPE	gid_t
+ #endif
+ 
+ /*
+  * Option variables and default values.
+  */
+ #ifdef PPP_FILTER
+ int	dflag = 0;		/* Tell libpcap we want debugging */
+ #endif
+ int	debug = 0;		/* Debug flag */
+ int	kdebugflag = 0;		/* Tell kernel to print debug messages */
+ int	default_device = 1;	/* Using /dev/tty or equivalent */
+ char	devnam[MAXPATHLEN] = "/dev/tty";	/* Device name */
+ int	crtscts = 0;		/* Use hardware flow control */
+ int	modem = 1;		/* Use modem control lines */
+ int	inspeed = 0;		/* Input/Output speed requested */
+ u_int32_t netmask = 0;		/* IP netmask to set on interface */
+ int	lockflag = 0;		/* Create lock file to lock the serial dev */
+ int	nodetach = 0;		/* Don't detach from controlling tty */
+ char	*connector = NULL;	/* Script to establish physical link */
+ char	*disconnector = NULL;	/* Script to disestablish physical link */
+ char	*welcomer = NULL;	/* Script to run after phys link estab. */
+ int	maxconnect = 0;		/* Maximum connect time */
+ char	user[MAXNAMELEN];	/* Username for PAP */
+ char	passwd[MAXSECRETLEN];	/* Password for PAP */
+ 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 */
+ 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 */
+ int	lcp_echo_fails = 0;	/* Tolerance to unanswered echo-requests */
+ char	our_name[MAXNAMELEN];	/* Our name for authentication purposes */
+ char	remote_name[MAXNAMELEN]; /* Peer's name for authentication */
+ int	explicit_remote = 0;	/* User specified explicit remote name */
+ int	usehostname = 0;	/* Use hostname for our_name */
+ int	disable_defaultip = 0;	/* Don't use hostname for default IP adrs */
+ int	demand = 0;		/* do dial-on-demand */
+ char	*ipparam = NULL;	/* Extra parameter for ip up/down scripts */
+ int	cryptpap;		/* Passwords in pap-secrets are encrypted */
+ int     useradius = 0;
+ int	idle_time_limit = 0;	/* Disconnect if idle for this many seconds */
+ int	holdoff = 30;		/* # seconds to pause before reconnecting */
+ int	refuse_pap = 0;		/* Set to say we won't do PAP */
+ int	refuse_chap = 0;	/* Set to say we won't do CHAP */
+ char	callerid[64];		/* Caller's ID */
+ char	calleridtool[MAXPATHLEN];/* program called to get ID */
+ char	con_state[32];		/* CONNECT string from mgetty log */
+ char	con_tool[MAXPATHLEN];	/* a tool which is called to fill up con_state*/
+  
+ 
+ #ifdef MSLANMAN
+ int	ms_lanman = 0;    	/* Nonzero if use LanMan password instead of NT */
+ 			  	/* Has meaning only with MS-CHAP challenges */
+ #endif
+ 
+ struct option_info auth_req_info;
+ struct option_info connector_info;
+ struct option_info disconnector_info;
+ struct option_info welcomer_info;
+ struct option_info devnam_info;
+ #ifdef PPP_FILTER
+ struct	bpf_program pass_filter;/* Filter program for packets to pass */
+ struct	bpf_program active_filter; /* Filter program for link-active pkts */
+ pcap_t  pc;			/* Fake struct pcap so we can compile expr */
+ #endif
+ 
+ /*
+  * Prototypes
+  */
+ static int setdevname __P((char *, int));
+ static int setipaddr __P((char *));
+ static int setspeed __P((char *));
+ static int setdebug __P((char **));
+ static int setkdebug __P((char **));
+ static int setpassive __P((char **));
+ static int setsilent __P((char **));
+ static int noopt __P((char **));
+ static int setnovj __P((char **));
+ static int setnovjccomp __P((char **));
+ static int setvjslots __P((char **));
+ static int reqpap __P((char **));
+ static int nopap __P((char **));
+ #ifdef OLD_OPTIONS
+ static int setupapfile __P((char **));
+ #endif
+ static int nochap __P((char **));
+ static int reqchap __P((char **));
+ static int noaccomp __P((char **));
+ static int noasyncmap __P((char **));
+ static int noip __P((char **));
+ static int nomagicnumber __P((char **));
+ static int setasyncmap __P((char **));
+ static int setescape __P((char **));
+ static int setmru __P((char **));
+ static int setmtu __P((char **));
+ static int setcbcps __P((char **));
+ static int setcallerid __P((char **));
+ static int setconstate __P((char **));
+ #ifdef CBCP_SUPPORT
+ static int setcbcp __P((char **));
+ #endif
+ static int nomru __P((char **));
+ static int nopcomp __P((char **));
+ static int setconnector __P((char **));
+ static int setdisconnector __P((char **));
+ static int setwelcomer __P((char **));
+ static int setmaxconnect __P((char **));
+ static int setdomain __P((char **));
+ static int setnetmask __P((char **));
+ static int setcrtscts __P((char **));
+ static int setnocrtscts __P((char **));
+ static int setxonxoff __P((char **));
+ static int setnodetach __P((char **));
+ static int setupdetach __P((char **));
+ static int setmodem __P((char **));
+ static int setlocal __P((char **));
+ static int setlock __P((char **));
+ static int setname __P((char **));
+ static int setuser __P((char **));
+ static int setremote __P((char **));
+ static int setauth __P((char **));
+ static int setnoauth __P((char **));
+ static int readfile __P((char **));
+ static int callfile __P((char **));
+ static int setdefaultroute __P((char **));
+ static int setnodefaultroute __P((char **));
+ static int setproxyarp __P((char **));
+ static int setnoproxyarp __P((char **));
+ static int setpersist __P((char **));
+ static int setnopersist __P((char **));
+ static int setdologin __P((char **));
+ static int setusehostname __P((char **));
+ static int setnoipdflt __P((char **));
+ static int setlcptimeout __P((char **));
+ static int setlcpterm __P((char **));
+ static int setlcpconf __P((char **));
+ static int setlcpfails __P((char **));
+ static int setipcptimeout __P((char **));
+ static int setipcpterm __P((char **));
+ static int setipcpconf __P((char **));
+ static int setipcpfails __P((char **));
+ static int setpaptimeout __P((char **));
+ static int setpapreqs __P((char **));
+ static int setpapreqtime __P((char **));
+ static int setchaptimeout __P((char **));
+ static int setchapchal __P((char **));
+ static int setchapintv __P((char **));
+ static int setipcpaccl __P((char **));
+ static int setipcpaccr __P((char **));
+ static int setlcpechointv __P((char **));
+ static int setlcpechofails __P((char **));
+ static int noccp __P((char **));
+ static int setbsdcomp __P((char **));
+ static int setnobsdcomp __P((char **));
+ static int setdeflate __P((char **));
+ static int setnodeflate __P((char **));
+ static int setnodeflatedraft __P((char **));
+ static int setdemand __P((char **));
+ static int setpred1comp __P((char **));
+ static int setnopred1comp __P((char **));
+ static int setipparam __P((char **));
+ static int setpapcrypt __P((char **));
+ static int setradius __P((char **));
+ static int setidle __P((char **));
+ static int setholdoff __P((char **));
+ static int setdnsaddr __P((char **));
+ static int resetipxproto __P((char **));
+ static int setwinsaddr __P((char **));
+ static int showversion __P((char **));
+ static int showhelp __P((char **));
+ 
+ #ifdef PPP_FILTER
+ static int setpdebug __P((char **));
+ static int setpassfilter __P((char **));
+ static int setactivefilter __P((char **));
+ #endif
+ 
+ #ifdef IPX_CHANGE
+ static int setipxproto __P((char **));
+ static int setipxanet __P((char **));
+ static int setipxalcl __P((char **));
+ static int setipxarmt __P((char **));
+ static int setipxnetwork __P((char **));
+ static int setipxnode __P((char **));
+ static int setipxrouter __P((char **));
+ static int setipxname __P((char **));
+ static int setipxcptimeout __P((char **));
+ static int setipxcpterm __P((char **));
+ static int setipxcpconf __P((char **));
+ static int setipxcpfails __P((char **));
+ #endif /* IPX_CHANGE */
+ 
+ #ifdef MSLANMAN
+ static int setmslanman __P((char **));
+ #endif
+ 
+ static int number_option __P((char *, u_int32_t *, int));
+ static int int_option __P((char *, int *));
+ static int readable __P((int fd));
+ 
+ /*
+  * Valid arguments.
+  */
+ static struct cmd {
+     char *cmd_name;
+     int num_args;
+     int (*cmd_func) __P((char **));
+ } cmds[] = {
+     {"-all", 0, noopt},		/* Don't request/allow any options (useless) */
+     {"noaccomp", 0, noaccomp},	/* Disable Address/Control compression */
+     {"-ac", 0, noaccomp},	/* Disable Address/Control compress */
+     {"default-asyncmap", 0, noasyncmap}, /* Disable asyncmap negoatiation */
+     {"-am", 0, noasyncmap},	/* Disable asyncmap negotiation */
+     {"-as", 1, setasyncmap},	/* set the desired async map */
+     {"-d", 0, setdebug},	/* Increase debugging level */
+     {"nodetach", 0, setnodetach}, /* Don't detach from controlling tty */
+     {"-detach", 0, setnodetach}, /* don't fork */
+     {"updetach", 0, setupdetach}, /* Detach once an NP has come up */
+     {"noip", 0, noip},		/* Disable IP and IPCP */
+     {"-ip", 0, noip},		/* Disable IP and IPCP */
+     {"nomagic", 0, nomagicnumber}, /* Disable magic number negotiation */
+     {"-mn", 0, nomagicnumber},	/* Disable magic number negotiation */
+     {"default-mru", 0, nomru},	/* Disable MRU negotiation */
+     {"-mru", 0, nomru},		/* Disable mru negotiation */
+     {"-p", 0, setpassive},	/* Set passive mode */
+     {"nopcomp", 0, nopcomp},	/* Disable protocol field compression */
+     {"-pc", 0, nopcomp},	/* Disable protocol field compress */
+ #if OLD_OPTIONS
+     {"+ua", 1, setupapfile},	/* Get PAP user and password from file */
+ #endif
+     {"require-pap", 0, reqpap},	/* Require PAP authentication from peer */
+     {"+pap", 0, reqpap},	/* Require PAP auth from peer */
+     {"refuse-pap", 0, nopap},	/* Don't agree to auth to peer with PAP */
+     {"-pap", 0, nopap},		/* Don't allow UPAP authentication with peer */
+     {"require-chap", 0, reqchap}, /* Require CHAP authentication from peer */
+     {"+chap", 0, reqchap},	/* Require CHAP authentication from peer */
+     {"refuse-chap", 0, nochap},	/* Don't agree to auth to peer with CHAP */
+     {"-chap", 0, nochap},	/* Don't allow CHAP authentication with peer */
+     {"novj", 0, setnovj},	/* Disable VJ compression */
+     {"-vj", 0, setnovj},	/* disable VJ compression */
+     {"novjccomp", 0, setnovjccomp}, /* disable VJ connection-ID compression */
+     {"-vjccomp", 0, setnovjccomp}, /* disable VJ connection-ID compression */
+     {"vj-max-slots", 1, setvjslots}, /* Set maximum VJ header slots */
+     {"asyncmap", 1, setasyncmap}, /* set the desired async map */
+     {"escape", 1, setescape},	/* set chars to escape on transmission */
+     {"connect", 1, setconnector}, /* A program to set up a connection */
+     {"disconnect", 1, setdisconnector},	/* program to disconnect serial dev. */
+     {"welcome", 1, setwelcomer},/* Script to welcome client */
+     {"maxconnect", 1, setmaxconnect},  /* specify a maximum connect time */
+     {"crtscts", 0, setcrtscts},	/* set h/w flow control */
+     {"nocrtscts", 0, setnocrtscts}, /* clear h/w flow control */
+     {"-crtscts", 0, setnocrtscts}, /* clear h/w flow control */
+     {"xonxoff", 0, setxonxoff},	/* set s/w flow control */
+     {"debug", 0, setdebug},	/* Increase debugging level */
+     {"kdebug", 1, setkdebug},	/* Enable kernel-level debugging */
+     {"domain", 1, setdomain},	/* Add given domain name to hostname*/
+     {"mru", 1, setmru},		/* Set MRU value for negotiation */
+     {"mtu", 1, setmtu},		/* Set our MTU */
+     {"cb", 0, setcbcps},
+     {"callerid", 1, setcallerid},
+     {"connect_state", 1, setconstate},
+ #ifdef CBCP_SUPPORT
+     {"callback", 1, setcbcp},	/* Ask for callback */
+ #endif
+     {"netmask", 1, setnetmask},	/* set netmask */
+     {"passive", 0, setpassive},	/* Set passive mode */
+     {"silent", 0, setsilent},	/* Set silent mode */
+     {"modem", 0, setmodem},	/* Use modem control lines */
+     {"local", 0, setlocal},	/* Don't use modem control lines */
+     {"lock", 0, setlock},	/* Lock serial device (with lock file) */
+     {"name", 1, setname},	/* Set local name for authentication */
+     {"user", 1, setuser},	/* Set name for auth with peer */
+     {"usehostname", 0, setusehostname},	/* Must use hostname for auth. */
+     {"remotename", 1, setremote}, /* Set remote name for authentication */
+     {"auth", 0, setauth},	/* Require authentication from peer */
+     {"noauth", 0, setnoauth},	/* Don't require peer to authenticate */
+     {"file", 1, readfile},	/* Take options from a file */
+     {"call", 1, callfile},	/* Take options from a privileged file */
+     {"defaultroute", 0, setdefaultroute}, /* Add default route */
+     {"nodefaultroute", 0, setnodefaultroute}, /* disable defaultroute option */
+     {"-defaultroute", 0, setnodefaultroute}, /* disable defaultroute option */
+     {"proxyarp", 0, setproxyarp}, /* Add proxy ARP entry */
+     {"noproxyarp", 0, setnoproxyarp}, /* disable proxyarp option */
+     {"-proxyarp", 0, setnoproxyarp}, /* disable proxyarp option */
+     {"persist", 0, setpersist},	/* Keep on reopening connection after close */
+     {"nopersist", 0, setnopersist},  /* Turn off persist option */
+     {"demand", 0, setdemand},	/* Dial on demand */
+     {"login", 0, setdologin},	/* Use system password database for UPAP */
+     {"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 */
+     {"lcp-restart", 1, setlcptimeout}, /* Set timeout for LCP */
+     {"lcp-max-terminate", 1, setlcpterm}, /* Set max #xmits for term-reqs */
+     {"lcp-max-configure", 1, setlcpconf}, /* Set max #xmits for conf-reqs */
+     {"lcp-max-failure", 1, setlcpfails}, /* Set max #conf-naks for LCP */
+     {"ipcp-restart", 1, setipcptimeout}, /* Set timeout for IPCP */
+     {"ipcp-max-terminate", 1, setipcpterm}, /* Set max #xmits for term-reqs */
+     {"ipcp-max-configure", 1, setipcpconf}, /* Set max #xmits for conf-reqs */
+     {"ipcp-max-failure", 1, setipcpfails}, /* Set max #conf-naks for IPCP */
+     {"pap-restart", 1, setpaptimeout},	/* Set retransmit timeout for PAP */
+     {"pap-max-authreq", 1, setpapreqs}, /* Set max #xmits for auth-reqs */
+     {"pap-timeout", 1, setpapreqtime},	/* Set time limit for peer PAP auth. */
+     {"chap-restart", 1, setchaptimeout}, /* Set timeout for CHAP */
+     {"chap-max-challenge", 1, setchapchal}, /* Set max #xmits for challenge */
+     {"chap-interval", 1, setchapintv}, /* Set interval for rechallenge */
+     {"ipcp-accept-local", 0, setipcpaccl}, /* Accept peer's address for us */
+     {"ipcp-accept-remote", 0, setipcpaccr}, /* Accept peer's address for it */
+     {"noccp", 0, noccp},		/* Disable CCP negotiation */
+     {"-ccp", 0, noccp},			/* Disable CCP negotiation */
+     {"bsdcomp", 1, setbsdcomp},		/* request BSD-Compress */
+     {"nobsdcomp", 0, setnobsdcomp},	/* don't allow BSD-Compress */
+     {"-bsdcomp", 0, setnobsdcomp},	/* don't allow BSD-Compress */
+     {"deflate", 1, setdeflate},		/* request Deflate compression */
+     {"nodeflate", 0, setnodeflate},	/* don't allow Deflate compression */
+     {"-deflate", 0, setnodeflate},	/* don't allow Deflate compression */
+     {"nodeflatedraft", 0, setnodeflatedraft}, /* don't use draft deflate # */
+     {"predictor1", 0, setpred1comp},	/* request Predictor-1 */
+     {"nopredictor1", 0, setnopred1comp},/* don't allow Predictor-1 */
+     {"-predictor1", 0, setnopred1comp},	/* don't allow Predictor-1 */
+     {"ipparam", 1, setipparam},		/* set ip script parameter */
+     {"papcrypt", 0, setpapcrypt},	/* PAP passwords encrypted */
+     {"radius", 1, setradius},
+     {"idle", 1, setidle},		/* idle time limit (seconds) */
+     {"holdoff", 1, setholdoff},		/* set holdoff time (seconds) */
+     {"ms-dns", 1, setdnsaddr},		/* DNS address for the peer's use */
+     {"ms-wins", 1, setwinsaddr},	/* Nameserver for SMB over TCP/IP for peer */
+     {"noipx",  0, resetipxproto},	/* Disable IPXCP (and IPX) */
+     {"-ipx",   0, resetipxproto},	/* Disable IPXCP (and IPX) */
+     {"--version", 0, showversion},	/* Show version number */
+     {"--help", 0, showhelp},		/* Show brief listing of options */
+     {"-h", 0, showhelp},		/* ditto */
+ 
+ #ifdef PPP_FILTER
+     {"pdebug", 1, setpdebug},		/* libpcap debugging */
+     {"pass-filter", 1, setpassfilter},	/* set filter for packets to pass */
+     {"active-filter", 1, setactivefilter}, /* set filter for active pkts */
+ #endif
+ 
+ #ifdef IPX_CHANGE
+     {"ipx-network",          1, setipxnetwork}, /* IPX network number */
+     {"ipxcp-accept-network", 0, setipxanet},    /* Accept peer netowrk */
+     {"ipx-node",             1, setipxnode},    /* IPX node number */
+     {"ipxcp-accept-local",   0, setipxalcl},    /* Accept our address */
+     {"ipxcp-accept-remote",  0, setipxarmt},    /* Accept peer's address */
+     {"ipx-routing",          1, setipxrouter},  /* IPX routing proto number */
+     {"ipx-router-name",      1, setipxname},    /* IPX router name */
+     {"ipxcp-restart",        1, setipxcptimeout}, /* Set timeout for IPXCP */
+     {"ipxcp-max-terminate",  1, setipxcpterm},  /* max #xmits for term-reqs */
+     {"ipxcp-max-configure",  1, setipxcpconf},  /* max #xmits for conf-reqs */
+     {"ipxcp-max-failure",    1, setipxcpfails}, /* max #conf-naks for IPXCP */
+ #if 0
+     {"ipx-compression", 1, setipxcompression}, /* IPX compression number */
+ #endif
+     {"ipx",		     0, setipxproto},	/* Enable IPXCP (and IPX) */
+     {"+ipx",		     0, setipxproto},	/* Enable IPXCP (and IPX) */
+ #endif /* IPX_CHANGE */
+ 
+ #ifdef MSLANMAN
+     {"ms-lanman", 0, setmslanman},	/* Use LanMan psswd when using MS-CHAP */
+ #endif
+ 
+     {NULL, 0, NULL}
+ };
+ 
+ 
+ #ifndef IMPLEMENTATION
+ #define IMPLEMENTATION ""
+ #endif
+ 
+ static char *usage_string = "\
+ pppd version %s patch level %d%s\n\
+ Usage: %s [ options ], where options are:\n\
+ 	<device>	Communicate over the named device\n\
+ 	<speed>		Set the baud rate to <speed>\n\
+ 	<loc>:<rem>	Set the local and/or remote interface IP\n\
+ 			addresses.  Either one may be omitted.\n\
+ 	asyncmap <n>	Set the desired async map to hex <n>\n\
+ 	auth		Require authentication from peer\n\
+         connect <p>     Invoke shell command <p> to set up the serial line\n\
+ 	crtscts		Use hardware RTS/CTS flow control\n\
+ 	defaultroute	Add default route through interface\n\
+ 	file <f>	Take options from file <f>\n\
+ 	modem		Use modem control lines\n\
+ 	mru <n>		Set MRU value to <n> for negotiation\n\
+ See pppd(8) for more options.\n\
+ ";
+ 
+ static char *current_option;	/* the name of the option being parsed */
+ static int privileged_option;	/* set iff the current option came from root */
+ static char *option_source;	/* string saying where the option came from */
+ 
+ /*
+  * parse_args - parse a string of arguments from the command line.
+  */
+ int
+ parse_args(argc, argv)
+     int argc;
+     char **argv;
+ {
+     char *arg;
+     struct cmd *cmdp;
+     int ret;
+ 
+     privileged_option = privileged;
+     option_source = "command line";
+     while (argc > 0) {
+ 	arg = *argv++;
+ 	--argc;
+ 
+ 	/*
+ 	 * First see if it's a command.
+ 	 */
+ 	for (cmdp = cmds; cmdp->cmd_name; cmdp++)
+ 	    if (!strcmp(arg, cmdp->cmd_name))
+ 		break;
+ 
+ 	if (cmdp->cmd_name != NULL) {
+ 	    if (argc < cmdp->num_args) {
+ 		option_error("too few parameters for option %s", arg);
+ 		return 0;
+ 	    }
+ 	    current_option = arg;
+ 	    if (!(*cmdp->cmd_func)(argv))
+ 		return 0;
+ 	    argc -= cmdp->num_args;
+ 	    argv += cmdp->num_args;
+ 
+ 	} else {
+ 	    /*
+ 	     * Maybe a tty name, speed or IP address?
+ 	     */
+ 	    if ((ret = setdevname(arg, 0)) == 0
+ 		&& (ret = setspeed(arg)) == 0
+ 		&& (ret = setipaddr(arg)) == 0) {
+ 		option_error("unrecognized option '%s'", arg);
+ 		usage();
+ 		return 0;
+ 	    }
+ 	    if (ret < 0)	/* error */
+ 		return 0;
+ 	}
+     }
+     return 1;
+ }
+ 
+ /*
+  * scan_args - scan the command line arguments to get the tty name,
+  * if specified.
+  */
+ void
+ scan_args(argc, argv)
+     int argc;
+     char **argv;
+ {
+     char *arg;
+     struct cmd *cmdp;
+ 
+     while (argc > 0) {
+ 	arg = *argv++;
+ 	--argc;
+ 
+ 	/* Skip options and their arguments */
+ 	for (cmdp = cmds; cmdp->cmd_name; cmdp++)
+ 	    if (!strcmp(arg, cmdp->cmd_name))
+ 		break;
+ 
+ 	if (cmdp->cmd_name != NULL) {
+ 	    argc -= cmdp->num_args;
+ 	    argv += cmdp->num_args;
+ 	    continue;
+ 	}
+ 
+ 	/* Check if it's a tty name and copy it if so */
+ 	(void) setdevname(arg, 1);
+     }
+ }
+ 
+ /*
+  * usage - print out a message telling how to use the program.
+  */
+ void
+ usage()
+ {
+     if (phase == PHASE_INITIALIZE)
+ 	fprintf(stderr, usage_string, VERSION, PATCHLEVEL, IMPLEMENTATION,
+ 		progname);
+ }
+ 
+ /*
+  * showhelp - print out usage message and exit.
+  */
+ static int
+ showhelp(argv)
+     char **argv;
+ {
+     if (phase == PHASE_INITIALIZE) {
+ 	usage();
+ 	exit(0);
+     }
+     return 0;
+ }
+ 
+ /*
+  * showversion - print out the version number and exit.
+  */
+ static int
+ showversion(argv)
+     char **argv;
+ {
+     if (phase == PHASE_INITIALIZE) {
+ 	fprintf(stderr, "pppd version %s patch level %d%s\n",
+ 		VERSION, PATCHLEVEL, IMPLEMENTATION);
+ 	exit(0);
+     }
+     return 0;
+ }
+ 
+ /*
+  * options_from_file - Read a string of options from a file,
+  * and interpret them.
+  */
+ int
+ options_from_file(filename, must_exist, check_prot, priv)
+     char *filename;
+     int must_exist;
+     int check_prot;
+     int priv;
+ {
+     FILE *f;
+     int i, newline, ret;
+     struct cmd *cmdp;
+     int oldpriv;
+     char *argv[MAXARGS];
+     char args[MAXARGS][MAXWORDLEN];
+     char cmd[MAXWORDLEN];
+ 
+     if ((f = fopen(filename, "r")) == NULL) {
+ 	if (!must_exist && errno == ENOENT)
+ 	    return 1;
+ 	option_error("Can't open options file %s: %m", filename);
+ 	return 0;
+     }
+     if (check_prot && !readable(fileno(f))) {
+ 	option_error("Can't open options file %s: access denied", filename);
+ 	fclose(f);
+ 	return 0;
+     }
+ 
+     oldpriv = privileged_option;
+     privileged_option = priv;
+     ret = 0;
+     while (getword(f, cmd, &newline, filename)) {
+ 	/*
+ 	 * First see if it's a command.
+ 	 */
+ 	for (cmdp = cmds; cmdp->cmd_name; cmdp++)
+ 	    if (!strcmp(cmd, cmdp->cmd_name))
+ 		break;
+ 
+ 	if (cmdp->cmd_name != NULL) {
+ 	    for (i = 0; i < cmdp->num_args; ++i) {
+ 		if (!getword(f, args[i], &newline, filename)) {
+ 		    option_error(
+ 			"In file %s: too few parameters for option '%s'",
+ 			filename, cmd);
+ 		    goto err;
+ 		}
+ 		argv[i] = args[i];
+ 	    }
+ 	    current_option = cmd;
+ 	    if (!(*cmdp->cmd_func)(argv))
+ 		goto err;
+ 
+ 	} else {
+ 	    /*
+ 	     * Maybe a tty name, speed or IP address?
+ 	     */
+ 	    if ((i = setdevname(cmd, 0)) == 0
+ 		&& (i = setspeed(cmd)) == 0
+ 		&& (i = setipaddr(cmd)) == 0) {
+ 		option_error("In file %s: unrecognized option '%s'",
+ 			     filename, cmd);
+ 		goto err;
+ 	    }
+ 	    if (i < 0)		/* error */
+ 		goto err;
+ 	}
+     }
+     ret = 1;
+ 
+ err:
+     fclose(f);
+     privileged_option = oldpriv;
+     return ret;
+ }
+ 
+ /*
+  * options_from_user - See if the use has a ~/.ppprc file,
+  * and if so, interpret options from it.
+  */
+ int
+ options_from_user()
+ {
+     char *user, *path, *file;
+     int ret;
+     struct passwd *pw;
+ 
+     pw = getpwuid(getuid());
+     if (pw == NULL || (user = pw->pw_dir) == NULL || user[0] == 0)
+ 	return 1;
+     file = _PATH_USEROPT;
+     path = malloc(strlen(user) + strlen(file) + 2);
+     if (path == NULL)
+ 	novm("init file name");
+     strcpy(path, user);
+     strcat(path, "/");
+     strcat(path, file);
+     ret = options_from_file(path, 0, 1, privileged);
+     free(path);
+     return ret;
+ }
+ 
+ /*
+  * options_for_tty - See if an options file exists for the serial
+  * device, and if so, interpret options from it.
+  */
+ int
+ options_for_tty()
+ {
+     char *dev, *path, *p;
+     int ret;
+ 
+     dev = devnam;
+     if (strncmp(dev, "/dev/", 5) == 0)
+ 	dev += 5;
+     if (strcmp(dev, "tty") == 0)
+ 	return 1;		/* don't look for /etc/ppp/options.tty */
+     path = malloc(strlen(_PATH_TTYOPT) + strlen(dev) + 1);
+     if (path == NULL)
+ 	novm("tty init file name");
+     strcpy(path, _PATH_TTYOPT);
+     /* Turn slashes into dots, for Solaris case (e.g. /dev/term/a) */
+     for (p = path + strlen(path); *dev != 0; ++dev)
+ 	*p++ = (*dev == '/'? '.': *dev);
+     *p = 0;
+     ret = options_from_file(path, 0, 0, 1);
+     free(path);
+     return ret;
+ }
+ 
+ /*
+  * option_error - print a message about an error in an option.
+  * The message is logged, and also sent to
+  * stderr if phase == PHASE_INITIALIZE.
+  */
+ void
+ option_error __V((char *fmt, ...))
+ {
+     va_list args;
+     char buf[256];
+ 
+ #if __STDC__
+     va_start(args, fmt);
+ #else
+     char *fmt;
+     va_start(args);
+     fmt = va_arg(args, char *);
+ #endif
+     vfmtmsg(buf, sizeof(buf), fmt, args);
+     va_end(args);
+     if (phase == PHASE_INITIALIZE)
+ 	fprintf(stderr, "%s: %s\n", progname, buf);
+     syslog(LOG_ERR, "%s", buf);
+ }
+ 
+ /*
+  * readable - check if a file is readable by the real user.
+  */
+ static int
+ readable(fd)
+     int fd;
+ {
+     uid_t uid;
+     int ngroups, i;
+     struct stat sbuf;
+     GIDSET_TYPE groups[NGROUPS_MAX];
+ 
+     uid = getuid();
+     if (uid == 0)
+ 	return 1;
+     if (fstat(fd, &sbuf) != 0)
+ 	return 0;
+     if (sbuf.st_uid == uid)
+ 	return sbuf.st_mode & S_IRUSR;
+     if (sbuf.st_gid == getgid())
+ 	return sbuf.st_mode & S_IRGRP;
+     ngroups = getgroups(NGROUPS_MAX, groups);
+     for (i = 0; i < ngroups; ++i)
+ 	if (sbuf.st_gid == groups[i])
+ 	    return sbuf.st_mode & S_IRGRP;
+     return sbuf.st_mode & S_IROTH;
+ }
+ 
+ /*
+  * Read a word from a file.
+  * Words are delimited by white-space or by quotes (" or ').
+  * Quotes, white-space and \ may be escaped with \.
+  * \<newline> is ignored.
+  */
+ int
+ getword(f, word, newlinep, filename)
+     FILE *f;
+     char *word;
+     int *newlinep;
+     char *filename;
+ {
+     int c, len, escape;
+     int quoted, comment;
+     int value, digit, got, n;
+ 
+ #define isoctal(c) ((c) >= '0' && (c) < '8')
+ 
+     *newlinep = 0;
+     len = 0;
+     escape = 0;
+     comment = 0;
+ 
+     /*
+      * First skip white-space and comments.
+      */
+     for (;;) {
+ 	c = getc(f);
+ 	if (c == EOF)
+ 	    break;
+ 
+ 	/*
+ 	 * A newline means the end of a comment; backslash-newline
+ 	 * is ignored.  Note that we cannot have escape && comment.
+ 	 */
+ 	if (c == '\n') {
+ 	    if (!escape) {
+ 		*newlinep = 1;
+ 		comment = 0;
+ 	    } else
+ 		escape = 0;
+ 	    continue;
+ 	}
+ 
+ 	/*
+ 	 * Ignore characters other than newline in a comment.
+ 	 */
+ 	if (comment)
+ 	    continue;
+ 
+ 	/*
+ 	 * If this character is escaped, we have a word start.
+ 	 */
+ 	if (escape)
+ 	    break;
+ 
+ 	/*
+ 	 * If this is the escape character, look at the next character.
+ 	 */
+ 	if (c == '\\') {
+ 	    escape = 1;
+ 	    continue;
+ 	}
+ 
+ 	/*
+ 	 * If this is the start of a comment, ignore the rest of the line.
+ 	 */
+ 	if (c == '#') {
+ 	    comment = 1;
+ 	    continue;
+ 	}
+ 
+ 	/*
+ 	 * A non-whitespace character is the start of a word.
+ 	 */
+ 	if (!isspace(c))
+ 	    break;
+     }
+ 
+     /*
+      * Save the delimiter for quoted strings.
+      */
+     if (!escape && (c == '"' || c == '\'')) {
+         quoted = c;
+ 	c = getc(f);
+     } else
+         quoted = 0;
+ 
+     /*
+      * Process characters until the end of the word.
+      */
+     while (c != EOF) {
+ 	if (escape) {
+ 	    /*
+ 	     * This character is escaped: backslash-newline is ignored,
+ 	     * various other characters indicate particular values
+ 	     * as for C backslash-escapes.
+ 	     */
+ 	    escape = 0;
+ 	    if (c == '\n') {
+ 	        c = getc(f);
+ 		continue;
+ 	    }
+ 
+ 	    got = 0;
+ 	    switch (c) {
+ 	    case 'a':
+ 		value = '\a';
+ 		break;
+ 	    case 'b':
+ 		value = '\b';
+ 		break;
+ 	    case 'f':
+ 		value = '\f';
+ 		break;
+ 	    case 'n':
+ 		value = '\n';
+ 		break;
+ 	    case 'r':
+ 		value = '\r';
+ 		break;
+ 	    case 's':
+ 		value = ' ';
+ 		break;
+ 	    case 't':
+ 		value = '\t';
+ 		break;
+ 
+ 	    default:
+ 		if (isoctal(c)) {
+ 		    /*
+ 		     * \ddd octal sequence
+ 		     */
+ 		    value = 0;
+ 		    for (n = 0; n < 3 && isoctal(c); ++n) {
+ 			value = (value << 3) + (c & 07);
+ 			c = getc(f);
+ 		    }
+ 		    got = 1;
+ 		    break;
+ 		}
+ 
+ 		if (c == 'x') {
+ 		    /*
+ 		     * \x<hex_string> sequence
+ 		     */
+ 		    value = 0;
+ 		    c = getc(f);
+ 		    for (n = 0; n < 2 && isxdigit(c); ++n) {
+ 			digit = toupper(c) - '0';
+ 			if (digit > 10)
+ 			    digit += '0' + 10 - 'A';
+ 			value = (value << 4) + digit;
+ 			c = getc (f);
+ 		    }
+ 		    got = 1;
+ 		    break;
+ 		}
+ 
+ 		/*
+ 		 * Otherwise the character stands for itself.
+ 		 */
+ 		value = c;
+ 		break;
+ 	    }
+ 
+ 	    /*
+ 	     * Store the resulting character for the escape sequence.
+ 	     */
+ 	    if (len < MAXWORDLEN-1)
+ 		word[len] = value;
+ 	    ++len;
+ 
+ 	    if (!got)
+ 		c = getc(f);
+ 	    continue;
+ 
+ 	}
+ 
+ 	/*
+ 	 * Not escaped: see if we've reached the end of the word.
+ 	 */
+ 	if (quoted) {
+ 	    if (c == quoted)
+ 		break;
+ 	} else {
+ 	    if (isspace(c) || c == '#') {
+ 		ungetc (c, f);
+ 		break;
+ 	    }
+ 	}
+ 
+ 	/*
+ 	 * Backslash starts an escape sequence.
+ 	 */
+ 	if (c == '\\') {
+ 	    escape = 1;
+ 	    c = getc(f);
+ 	    continue;
+ 	}
+ 
+ 	/*
+ 	 * An ordinary character: store it in the word and get another.
+ 	 */
+ 	if (len < MAXWORDLEN-1)
+ 	    word[len] = c;
+ 	++len;
+ 
+ 	c = getc(f);
+     }
+ 
+     /*
+      * End of the word: check for errors.
+      */
+     if (c == EOF) {
+ 	if (ferror(f)) {
+ 	    if (errno == 0)
+ 		errno = EIO;
+ 	    option_error("Error reading %s: %m", filename);
+ 	    die(1);
+ 	}
+ 	/*
+ 	 * If len is zero, then we didn't find a word before the
+ 	 * end of the file.
+ 	 */
+ 	if (len == 0)
+ 	    return 0;
+     }
+ 
+     /*
+      * Warn if the word was too long, and append a terminating null.
+      */
+     if (len >= MAXWORDLEN) {
+ 	option_error("warning: word in file %s too long (%.20s...)",
+ 		     filename, word);
+ 	len = MAXWORDLEN - 1;
+     }
+     word[len] = 0;
+ 
+     return 1;
+ 
+ #undef isoctal
+ 
+ }
+ 
+ /*
+  * number_option - parse an unsigned numeric parameter for an option.
+  */
+ static int
+ number_option(str, valp, base)
+     char *str;
+     u_int32_t *valp;
+     int base;
+ {
+     char *ptr;
+ 
+     *valp = strtoul(str, &ptr, base);
+     if (ptr == str) {
+ 	option_error("invalid numeric parameter '%s' for %s option",
+ 		     str, current_option);
+ 	return 0;
+     }
+     return 1;
+ }
+ 
+ 
+ /*
+  * int_option - like number_option, but valp is int *,
+  * the base is assumed to be 0, and *valp is not changed
+  * if there is an error.
+  */
+ static int
+ int_option(str, valp)
+     char *str;
+     int *valp;
+ {
+     u_int32_t v;
+ 
+     if (!number_option(str, &v, 0))
+ 	return 0;
+     *valp = (int) v;
+     return 1;
+ }
+ 
+ 
+ /*
+  * The following procedures parse options.
+  */
+ 
+ /*
+  * readfile - take commands from a file.
+  */
+ static int
+ readfile(argv)
+     char **argv;
+ {
+     return options_from_file(*argv, 1, 1, privileged_option);
+ }
+ 
+ /*
+  * callfile - take commands from /etc/ppp/peers/<name>.
+  * Name may not contain /../, start with / or ../, or end in /..
+  */
+ static int
+ callfile(argv)
+     char **argv;
+ {
+     char *fname, *arg, *p;
+     int l, ok;
+ 
+     arg = *argv;
+     ok = 1;
+     if (arg[0] == '/' || arg[0] == 0)
+ 	ok = 0;
+     else {
+ 	for (p = arg; *p != 0; ) {
+ 	    if (p[0] == '.' && p[1] == '.' && (p[2] == '/' || p[2] == 0)) {
+ 		ok = 0;
+ 		break;
+ 	    }
+ 	    while (*p != '/' && *p != 0)
+ 		++p;
+ 	    if (*p == '/')
+ 		++p;
+ 	}
+     }
+     if (!ok) {
+ 	option_error("call option value may not contain .. or start with /");
+ 	return 0;
+     }
+ 
+     l = strlen(arg) + strlen(_PATH_PEERFILES) + 1;
+     if ((fname = (char *) malloc(l)) == NULL)
+ 	novm("call file name");
+     strcpy(fname, _PATH_PEERFILES);
+     strcat(fname, arg);
+ 
+     ok = options_from_file(fname, 1, 1, 1);
+ 
+     free(fname);
+     return ok;
+ }
+ 
+ 
+ /*
+  * setdebug - Set debug (command line argument).
+  */
+ static int
+ setdebug(argv)
+     char **argv;
+ {
+     debug++;
+     return (1);
+ }
+ 
+ /*
+  * setkdebug - Set kernel debugging level.
+  */
+ static int
+ setkdebug(argv)
+     char **argv;
+ {
+     return int_option(*argv, &kdebugflag);
+ }
+ 
+ #ifdef PPP_FILTER
+ /*
+  * setpdebug - Set libpcap debugging level.
+  */
+ static int
+ setpdebug(argv)
+     char **argv;
+ {
+     return int_option(*argv, &dflag);
+ }
+ 
+ /*
+  * setpassfilter - Set the pass filter for packets
+  */
+ static int
+ setpassfilter(argv)
+     char **argv;
+ {
+     pc.linktype = DLT_PPP;
+     pc.snapshot = PPP_HDRLEN;
+  
+     if (pcap_compile(&pc, &pass_filter, *argv, 1, netmask) == 0)
+ 	return 1;
+     option_error("error in pass-filter expression: %s\n", pcap_geterr(&pc));
+     return 0;
+ }
+ 
+ /*
+  * setactivefilter - Set the active filter for packets
+  */
+ static int
+ setactivefilter(argv)
+     char **argv;
+ {
+     pc.linktype = DLT_PPP;
+     pc.snapshot = PPP_HDRLEN;
+  
+     if (pcap_compile(&pc, &active_filter, *argv, 1, netmask) == 0)
+ 	return 1;
+     option_error("error in active-filter expression: %s\n", pcap_geterr(&pc));
+     return 0;
+ }
+ #endif
+ 
+ /*
+  * noopt - Disable all options.
+  */
+ static int
+ noopt(argv)
+     char **argv;
+ {
+     BZERO((char *) &lcp_wantoptions[0], sizeof (struct lcp_options));
+     BZERO((char *) &lcp_allowoptions[0], sizeof (struct lcp_options));
+     BZERO((char *) &ipcp_wantoptions[0], sizeof (struct ipcp_options));
+     BZERO((char *) &ipcp_allowoptions[0], sizeof (struct ipcp_options));
+ 
+ #ifdef IPX_CHANGE
+     BZERO((char *) &ipxcp_wantoptions[0], sizeof (struct ipxcp_options));
+     BZERO((char *) &ipxcp_allowoptions[0], sizeof (struct ipxcp_options));
+ #endif /* IPX_CHANGE */
+ 
+     return (1);
+ }
+ 
+ /*
+  * noaccomp - Disable Address/Control field compression negotiation.
+  */
+ static int
+ noaccomp(argv)
+     char **argv;
+ {
+     lcp_wantoptions[0].neg_accompression = 0;
+     lcp_allowoptions[0].neg_accompression = 0;
+     return (1);
+ }
+ 
+ 
+ /*
+  * noasyncmap - Disable async map negotiation.
+  */
+ static int
+ noasyncmap(argv)
+     char **argv;
+ {
+     lcp_wantoptions[0].neg_asyncmap = 0;
+     lcp_allowoptions[0].neg_asyncmap = 0;
+     return (1);
+ }
+ 
+ 
+ /*
+  * noip - Disable IP and IPCP.
+  */
+ static int
+ noip(argv)
+     char **argv;
+ {
+     ipcp_protent.enabled_flag = 0;
+     return (1);
+ }
+ 
+ 
+ /*
+  * nomagicnumber - Disable magic number negotiation.
+  */
+ static int
+ nomagicnumber(argv)
+     char **argv;
+ {
+     lcp_wantoptions[0].neg_magicnumber = 0;
+     lcp_allowoptions[0].neg_magicnumber = 0;
+     return (1);
+ }
+ 
+ 
+ /*
+  * nomru - Disable mru negotiation.
+  */
+ static int
+ nomru(argv)
+     char **argv;
+ {
+     lcp_wantoptions[0].neg_mru = 0;
+     lcp_allowoptions[0].neg_mru = 0;
+     return (1);
+ }
+ 
+ 
+ /*
+  * setmru - Set MRU for negotiation.
+  */
+ static int
+ setmru(argv)
+     char **argv;
+ {
+     u_int32_t mru;
+ 
+     if (!number_option(*argv, &mru, 0))
+ 	return 0;
+     lcp_wantoptions[0].mru = mru;
+     lcp_wantoptions[0].neg_mru = 1;
+     return (1);
+ }
+ 
+ 
+ /*
+  * setmru - Set the largest MTU we'll use.
+  */
+ static int
+ setmtu(argv)
+     char **argv;
+ {
+     u_int32_t mtu;
+ 
+     if (!number_option(*argv, &mtu, 0))
+ 	return 0;
+     if (mtu < MINMRU || mtu > MAXMRU) {
+ 	option_error("mtu option value of %u is too %s", mtu,
+ 		     (mtu < MINMRU? "small": "large"));
+ 	return 0;
+     }
+     lcp_allowoptions[0].mru = mtu;
+     return (1);
+ }
+ 
+ 
+ static int
+ setcallerid(argv)
+     char **argv;
+ {
+   strcpy(calleridtool,*argv);
+   return (1);
+ }
+ 
+ static int
+ setconstate(argv)
+     char **argv;
+ {
+   strcpy(con_tool,*argv);
+   return (1);
+ }
+ 
+ static int
+ setcbcps(argv)
+     char **argv;
+ {
+  lcp_wantoptions[0].neg_cbcp = 1;   // poslem licitaciu na cbcp
+  lcp_allowoptions[0].neg_cbcp = 1;  // ak bude pytat cbcp potvrdim.
+  cbcp_protent.enabled_flag = 1;     // povolovanie protokolu po novom.
+  return(1);
+ }
+ #ifdef CBCP_SUPPORT
+ static int
+ setcbcp(argv)
+     char **argv;
+ {
+     lcp_wantoptions[0].neg_cbcp = 1;
+     cbcp_protent.enabled_flag = 1;
+     cbcp[0].us_number = strdup(*argv);
+     if (cbcp[0].us_number == 0)
+ 	novm("callback number");
+     cbcp[0].us_type |= (1 << CB_CONF_USER);
+     cbcp[0].us_type |= (1 << CB_CONF_ADMIN);
+     return (1);
+ }
+ #endif
+ 
+ /*
+  * nopcomp - Disable Protocol field compression negotiation.
+  */
+ static int
+ nopcomp(argv)
+     char **argv;
+ {
+     lcp_wantoptions[0].neg_pcompression = 0;
+     lcp_allowoptions[0].neg_pcompression = 0;
+     return (1);
+ }
+ 
+ 
+ /*
+  * setpassive - Set passive mode (don't give up if we time out sending
+  * LCP configure-requests).
+  */
+ static int
+ setpassive(argv)
+     char **argv;
+ {
+     lcp_wantoptions[0].passive = 1;
+     return (1);
+ }
+ 
+ 
+ /*
+  * setsilent - Set silent mode (don't start sending LCP configure-requests
+  * until we get one from the peer).
+  */
+ static int
+ setsilent(argv)
+     char **argv;
+ {
+     lcp_wantoptions[0].silent = 1;
+     return 1;
+ }
+ 
+ 
+ /*
+  * nopap - Disable PAP authentication with peer.
+  */
+ static int
+ nopap(argv)
+     char **argv;
+ {
+     refuse_pap = 1;
+     return (1);
+ }
+ 
+ 
+ /*
+  * reqpap - Require PAP authentication from peer.
+  */
+ static int
+ reqpap(argv)
+     char **argv;
+ {
+     lcp_wantoptions[0].neg_upap = 1;
+     setauth(NULL);
+     return 1;
+ }
+ 
+ #if OLD_OPTIONS
+ /*
+  * setupapfile - specifies UPAP info for authenticating with peer.
+  */
+ static int
+ setupapfile(argv)
+     char **argv;
+ {
+     FILE * ufile;
+     int l;
+ 
+     lcp_allowoptions[0].neg_upap = 1;
+ 
+     /* open user info file */
+     if ((ufile = fopen(*argv, "r")) == NULL) {
+ 	option_error("unable to open user login data file %s", *argv);
+ 	return 0;
+     }
+     if (!readable(fileno(ufile))) {
+ 	option_error("%s: access denied", *argv);
+ 	return 0;
+     }
+     check_access(ufile, *argv);
+ 
+     /* get username */
+     if (fgets(user, MAXNAMELEN - 1, ufile) == NULL
+ 	|| fgets(passwd, MAXSECRETLEN - 1, ufile) == NULL){
+ 	option_error("unable to read user login data file %s", *argv);
+ 	return 0;
+     }
+     fclose(ufile);
+ 
+     /* get rid of newlines */
+     l = strlen(user);
+     if (l > 0 && user[l-1] == '\n')
+ 	user[l-1] = 0;
+     l = strlen(passwd);
+     if (l > 0 && passwd[l-1] == '\n')
+ 	passwd[l-1] = 0;
+ 
+     return (1);
+ }
+ #endif
+ 
+ /*
+  * nochap - Disable CHAP authentication with peer.
+  */
+ static int
+ nochap(argv)
+     char **argv;
+ {
+     refuse_chap = 1;
+     return (1);
+ }
+ 
+ 
+ /*
+  * reqchap - Require CHAP authentication from peer.
+  */
+ static int
+ reqchap(argv)
+     char **argv;
+ {
+     lcp_wantoptions[0].neg_chap = 1;
+     setauth(NULL);
+     return (1);
+ }
+ 
+ 
+ /*
+  * setnovj - disable vj compression
+  */
+ static int
+ setnovj(argv)
+     char **argv;
+ {
+     ipcp_wantoptions[0].neg_vj = 0;
+     ipcp_allowoptions[0].neg_vj = 0;
+     return (1);
+ }
+ 
+ 
+ /*
+  * setnovjccomp - disable VJ connection-ID compression
+  */
+ static int
+ setnovjccomp(argv)
+     char **argv;
+ {
+     ipcp_wantoptions[0].cflag = 0;
+     ipcp_allowoptions[0].cflag = 0;
+     return 1;
+ }
+ 
+ 
+ /*
+  * setvjslots - set maximum number of connection slots for VJ compression
+  */
+ static int
+ setvjslots(argv)
+     char **argv;
+ {
+     int value;
+ 
+     if (!int_option(*argv, &value))
+ 	return 0;
+     if (value < 2 || value > 16) {
+ 	option_error("vj-max-slots value must be between 2 and 16");
+ 	return 0;
+     }
+     ipcp_wantoptions [0].maxslotindex =
+         ipcp_allowoptions[0].maxslotindex = value - 1;
+     return 1;
+ }
+ 
+ 
+ /*
+  * setconnector - Set a program to connect to a serial line
+  */
+ static int
+ setconnector(argv)
+     char **argv;
+ {
+     connector = strdup(*argv);
+     if (connector == NULL)
+ 	novm("connect script");
+     connector_info.priv = privileged_option;
+     connector_info.source = option_source;
+ 
+     return (1);
+ }
+ 
+ /*
+  * setdisconnector - Set a program to disconnect from the serial line
+  */
+ static int
+ setdisconnector(argv)
+     char **argv;
+ {
+     disconnector = strdup(*argv);
+     if (disconnector == NULL)
+ 	novm("disconnect script");
+     disconnector_info.priv = privileged_option;
+     disconnector_info.source = option_source;
+   
+     return (1);
+ }
+ 
+ /*
+  * setwelcomer - Set a program to welcome a client after connection
+  */
+ static int
+ setwelcomer(argv)
+     char **argv;
+ {
+     welcomer = strdup(*argv);
+     if (welcomer == NULL)
+ 	novm("welcome script");
+     welcomer_info.priv = privileged_option;
+     welcomer_info.source = option_source;
+ 
+     return (1);
+ }
+ 
+ /*
+  * setmaxconnect - Set the maximum connect time
+  */
+ static int
+ setmaxconnect(argv)
+     char **argv;
+ {
+     int value;
+ 
+     if (!int_option(*argv, &value))
+ 	return 0;
+     if (value < 0) {
+ 	option_error("maxconnect time must be positive");
+ 	return 0;
+     }
+     if (maxconnect > 0 && (value == 0 || value > maxconnect)) {
+ 	option_error("maxconnect time cannot be increased");
+ 	return 0;
+     }
+     maxconnect = value;
+     return 1;
+ }
+ 
+ /*
+  * setdomain - Set domain name to append to hostname 
+  */
+ static int
+ setdomain(argv)
+     char **argv;
+ {
+     if (!privileged_option) {
+ 	option_error("using the domain option requires root privilege");
+ 	return 0;
+     }
+     gethostname(hostname, MAXNAMELEN);
+     if (**argv != 0) {
+ 	if (**argv != '.')
+ 	    strncat(hostname, ".", MAXNAMELEN - strlen(hostname));
+ 	strncat(hostname, *argv, MAXNAMELEN - strlen(hostname));
+     }
+     hostname[MAXNAMELEN-1] = 0;
+     return (1);
+ }
+ 
+ 
+ /*
+  * setasyncmap - add bits to asyncmap (what we request peer to escape).
+  */
+ static int
+ setasyncmap(argv)
+     char **argv;
+ {
+     u_int32_t asyncmap;
+ 
+     if (!number_option(*argv, &asyncmap, 16))
+ 	return 0;
+     lcp_wantoptions[0].asyncmap |= asyncmap;
+     lcp_wantoptions[0].neg_asyncmap = 1;
+     return(1);
+ }
+ 
+ 
+ /*
+  * setescape - add chars to the set we escape on transmission.
+  */
+ static int
+ setescape(argv)
+     char **argv;
+ {
+     int n, ret;
+     char *p, *endp;
+ 
+     p = *argv;
+     ret = 1;
+     while (*p) {
+ 	n = strtol(p, &endp, 16);
+ 	if (p == endp) {
+ 	    option_error("escape parameter contains invalid hex number '%s'",
+ 			 p);
+ 	    return 0;
+ 	}
+ 	p = endp;
+ 	if (n < 0 || (0x20 <= n && n <= 0x3F) || n == 0x5E || n > 0xFF) {
+ 	    option_error("can't escape character 0x%x", n);
+ 	    ret = 0;
+ 	} else
+ 	    xmit_accm[0][n >> 5] |= 1 << (n & 0x1F);
+ 	while (*p == ',' || *p == ' ')
+ 	    ++p;
+     }
+     return ret;
+ }
+ 
+ 
+ /*
+  * setspeed - Set the speed.
+  */
+ static int
+ setspeed(arg)
+     char *arg;
+ {
+     char *ptr;
+     int spd;
+ 
+     spd = strtol(arg, &ptr, 0);
+     if (ptr == arg || *ptr != 0 || spd == 0)
+ 	return 0;
+     inspeed = spd;
+     return 1;
+ }
+ 
+ 
+ /*
+  * setdevname - Set the device name.
+  */
+ static int
+ setdevname(cp, quiet)
+     char *cp;
+     int quiet;
+ {
+     struct stat statbuf;
+     char dev[MAXPATHLEN];
+ 
+     if (*cp == 0)
+ 	return 0;
+ 
+     if (strncmp("/dev/", cp, 5) != 0) {
+ 	strcpy(dev, "/dev/");
+ 	strncat(dev, cp, MAXPATHLEN - 5);
+ 	dev[MAXPATHLEN-1] = 0;
+ 	cp = dev;
+     }
+ 
+     /*
+      * Check if there is a device by this name.
+      */
+     if (stat(cp, &statbuf) < 0) {
+ 	if (errno == ENOENT || quiet)
+ 	    return 0;
+ 	option_error("Couldn't stat %s: %m", cp);
+ 	return -1;
+     }
+ 
+     (void) strncpy(devnam, cp, MAXPATHLEN);
+     devnam[MAXPATHLEN-1] = 0;
+     default_device = FALSE;
+     devnam_info.priv = privileged_option;
+     devnam_info.source = option_source;
+   
+     return 1;
+ }
+ 
+ 
+ /*
+  * setipaddr - Set the IP address
+  */
+ static int
+ setipaddr(arg)
+     char *arg;
+ {
+     struct hostent *hp;
+     char *colon;
+     u_int32_t local, remote;
+     ipcp_options *wo = &ipcp_wantoptions[0];
+   
+     /*
+      * IP address pair separated by ":".
+      */
+     if ((colon = strchr(arg, ':')) == NULL)
+ 	return 0;
+   
+     /*
+      * If colon first character, then no local addr.
+      */
+     if (colon != arg) {
+ 	*colon = '\0';
+ 	if ((local = inet_addr(arg)) == -1) {
+ 	    if ((hp = gethostbyname(arg)) == NULL) {
+ 		option_error("unknown host: %s", arg);
+ 		return -1;
+ 	    } else {
+ 		local = *(u_int32_t *)hp->h_addr;
+ 	    }
+ 	}
+ 	if (bad_ip_adrs(local)) {
+ 	    option_error("bad local IP address %s", ip_ntoa(local));
+ 	    return -1;
+ 	}
+ 	if (local != 0)
+ 	    wo->ouraddr = local;
+ 	*colon = ':';
+     }
+   
+     /*
+      * If colon last character, then no remote addr.
+      */
+     if (*++colon != '\0') {
+ 	if ((remote = inet_addr(colon)) == -1) {
+ 	    if ((hp = gethostbyname(colon)) == NULL) {
+ 		option_error("unknown host: %s", colon);
+ 		return -1;
+ 	    } else {
+ 		remote = *(u_int32_t *)hp->h_addr;
+ 		if (remote_name[0] == 0) {
+ 		    strncpy(remote_name, colon, MAXNAMELEN);
+ 		    remote_name[MAXNAMELEN-1] = 0;
+ 		}
+ 	    }
+ 	}
+ 	if (bad_ip_adrs(remote)) {
+ 	    option_error("bad remote IP address %s", ip_ntoa(remote));
+ 	    return -1;
+ 	}
+ 	if (remote != 0)
+ 	    wo->hisaddr = remote;
+     }
+ 
+     return 1;
+ }
+ 
+ 
+ /*
+  * setnoipdflt - disable setipdefault()
+  */
+ static int
+ setnoipdflt(argv)
+     char **argv;
+ {
+     disable_defaultip = 1;
+     return 1;
+ }
+ 
+ 
+ /*
+  * setipcpaccl - accept peer's idea of our address
+  */
+ static int
+ setipcpaccl(argv)
+     char **argv;
+ {
+     ipcp_wantoptions[0].accept_local = 1;
+     return 1;
+ }
+ 
+ 
+ static int setradius (argv)
+     char **argv;
+ {
+     useradius = 1;
+     return radius_init(*argv);
+ }
+ 
+ /*
+  * setipcpaccr - accept peer's idea of its address
+  */
+ static int
+ setipcpaccr(argv)
+     char **argv;
+ {
+     ipcp_wantoptions[0].accept_remote = 1;
+     return 1;
+ }
+ 
+ 
+ /*
+  * setnetmask - set the netmask to be used on the interface.
+  */
+ static int
+ setnetmask(argv)
+     char **argv;
+ {
+     u_int32_t mask, b;
+     int n, ok;
+     char *p, *endp;
+ 
+     /*
+      * Unfortunately, if we use inet_addr, we can't tell whether
+      * a result of all 1s is an error or a valid 255.255.255.255.
+      */
+     p = *argv;
+     ok = 0;
+     mask = 0;
+     for (n = 3;; --n) {
+ 	b = strtoul(p, &endp, 0);
+ 	if (endp == p)
+ 	    break;
+ 	if (b < 0 || b > 255) {
+ 	    if (n == 3) {
+ 		/* accept e.g. 0xffffff00 */
+ 		p = endp;
+ 		mask = b;
+ 	    }
+ 	    break;
+ 	}
+ 	mask |= b << (n * 8);
+ 	p = endp;
+ 	if (*p != '.' || n == 0)
+ 	    break;
+ 	++p;
+     }
+ 
+     mask = htonl(mask);
+ 
+     if (*p != 0 || (netmask & ~mask) != 0) {
+ 	option_error("invalid netmask value '%s'", *argv);
+ 	return 0;
+     }
+ 
+     netmask = mask;
+     return (1);
+ }
+ 
+ static int
+ setcrtscts(argv)
+     char **argv;
+ {
+     crtscts = 1;
+     return (1);
+ }
+ 
+ static int
+ setnocrtscts(argv)
+     char **argv;
+ {
+     crtscts = -1;
+     return (1);
+ }
+ 
+ static int
+ setxonxoff(argv)
+     char **argv;
+ {
+     lcp_wantoptions[0].asyncmap |= 0x000A0000;	/* escape ^S and ^Q */
+     lcp_wantoptions[0].neg_asyncmap = 1;
+ 
+     crtscts = -2;
+     return (1);
+ }
+ 
+ static int
+ setnodetach(argv)
+     char **argv;
+ {
+     nodetach = 1;
+     return (1);
+ }
+ 
+ static int
+ setupdetach(argv)
+     char **argv;
+ {
+     nodetach = -1;
+     return (1);
+ }
+ 
+ static int
+ setdemand(argv)
+     char **argv;
+ {
+     demand = 1;
+     persist = 1;
+     return 1;
+ }
+ 
+ static int
+ setmodem(argv)
+     char **argv;
+ {
+     modem = 1;
+     return 1;
+ }
+ 
+ static int
+ setlocal(argv)
+     char **argv;
+ {
+     modem = 0;
+     return 1;
+ }
+ 
+ static int
+ setlock(argv)
+     char **argv;
+ {
+     lockflag = 1;
+     return 1;
+ }
+ 
+ static int
+ setusehostname(argv)
+     char **argv;
+ {
+     usehostname = 1;
+     return 1;
+ }
+ 
+ static int
+ setname(argv)
+     char **argv;
+ {
+     if (!privileged_option) {
+ 	option_error("using the name option requires root privilege");
+ 	return 0;
+     }
+     strncpy(our_name, argv[0], MAXNAMELEN);
+     our_name[MAXNAMELEN-1] = 0;
+     return 1;
+ }
+ 
+ static int
+ setuser(argv)
+     char **argv;
+ {
+     strncpy(user, argv[0], MAXNAMELEN);
+     user[MAXNAMELEN-1] = 0;
+     return 1;
+ }
+ 
+ static int
+ setremote(argv)
+     char **argv;
+ {
+     strncpy(remote_name, argv[0], MAXNAMELEN);
+     remote_name[MAXNAMELEN-1] = 0;
+     return 1;
+ }
+ 
+ static int
+ setauth(argv)
+     char **argv;
+ {
+     auth_required = 1;
+     if (privileged_option > auth_req_info.priv) {
+ 	auth_req_info.priv = privileged_option;
+ 	auth_req_info.source = option_source;
+     }
+     return 1;
+ }
+ 
+ static int
+ setnoauth(argv)
+     char **argv;
+ {
+     if (auth_required && privileged_option < auth_req_info.priv) {
+ 	option_error("cannot override auth option set by %s",
+ 		     auth_req_info.source);
+ 	return 0;
+     }
+     auth_required = 0;
+     return 1;
+ }
+ 
+ static int
+ setdefaultroute(argv)
+     char **argv;
+ {
+     if (!ipcp_allowoptions[0].default_route) {
+ 	option_error("defaultroute option is disabled");
+ 	return 0;
+     }
+     ipcp_wantoptions[0].default_route = 1;
+     return 1;
+ }
+ 
+ static int
+ setnodefaultroute(argv)
+     char **argv;
+ {
+     ipcp_allowoptions[0].default_route = 0;
+     ipcp_wantoptions[0].default_route = 0;
+     return 1;
+ }
+ 
+ static int
+ setproxyarp(argv)
+     char **argv;
+ {
+     if (!ipcp_allowoptions[0].proxy_arp) {
+ 	option_error("proxyarp option is disabled");
+ 	return 0;
+     }
+     ipcp_wantoptions[0].proxy_arp = 1;
+     return 1;
+ }
+ 
+ static int
+ setnoproxyarp(argv)
+     char **argv;
+ {
+     ipcp_wantoptions[0].proxy_arp = 0;
+     ipcp_allowoptions[0].proxy_arp = 0;
+     return 1;
+ }
+ 
+ static int
+ setpersist(argv)
+     char **argv;
+ {
+     persist = 1;
+     return 1;
+ }
+ 
+ static int
+ setnopersist(argv)
+     char **argv;
+ {
+     persist = 0;
+     return 1;
+ }
+ 
+ static int
+ setdologin(argv)
+     char **argv;
+ {
+     uselogin = 1;
+     return 1;
+ }
+ 
+ /*
+  * Functions to set the echo interval for modem-less monitors
+  */
+ 
+ static int
+ setlcpechointv(argv)
+     char **argv;
+ {
+     return int_option(*argv, &lcp_echo_interval);
+ }
+ 
+ static int
+ setlcpechofails(argv)
+     char **argv;
+ {
+     return int_option(*argv, &lcp_echo_fails);
+ }
+ 
+ /*
+  * Functions to set timeouts, max transmits, etc.
+  */
+ static int
+ setlcptimeout(argv)
+     char **argv;
+ {
+     return int_option(*argv, &lcp_fsm[0].timeouttime);
+ }
+ 
+ static int
+ setlcpterm(argv)
+     char **argv;
+ {
+     return int_option(*argv, &lcp_fsm[0].maxtermtransmits);
+ }
+ 
+ static int
+ setlcpconf(argv)
+     char **argv;
+ {
+     return int_option(*argv, &lcp_fsm[0].maxconfreqtransmits);
+ }
+ 
+ static int
+ setlcpfails(argv)
+     char **argv;
+ {
+     return int_option(*argv, &lcp_fsm[0].maxnakloops);
+ }
+ 
+ static int
+ setipcptimeout(argv)
+     char **argv;
+ {
+     return int_option(*argv, &ipcp_fsm[0].timeouttime);
+ }
+ 
+ static int
+ setipcpterm(argv)
+     char **argv;
+ {
+     return int_option(*argv, &ipcp_fsm[0].maxtermtransmits);
+ }
+ 
+ static int
+ setipcpconf(argv)
+     char **argv;
+ {
+     return int_option(*argv, &ipcp_fsm[0].maxconfreqtransmits);
+ }
+ 
+ static int
+ setipcpfails(argv)
+     char **argv;
+ {
+     return int_option(*argv, &lcp_fsm[0].maxnakloops);
+ }
+ 
+ static int
+ setpaptimeout(argv)
+     char **argv;
+ {
+     return int_option(*argv, &upap[0].us_timeouttime);
+ }
+ 
+ static int
+ setpapreqtime(argv)
+     char **argv;
+ {
+     return int_option(*argv, &upap[0].us_reqtimeout);
+ }
+ 
+ static int
+ setpapreqs(argv)
+     char **argv;
+ {
+     return int_option(*argv, &upap[0].us_maxtransmits);
+ }
+ 
+ static int
+ setchaptimeout(argv)
+     char **argv;
+ {
+     return int_option(*argv, &chap[0].timeouttime);
+ }
+ 
+ static int
+ setchapchal(argv)
+     char **argv;
+ {
+     return int_option(*argv, &chap[0].max_transmits);
+ }
+ 
+ static int
+ setchapintv(argv)
+     char **argv;
+ {
+     return int_option(*argv, &chap[0].chal_interval);
+ }
+ 
+ static int
+ noccp(argv)
+     char **argv;
+ {
+     ccp_protent.enabled_flag = 0;
+     return 1;
+ }
+ 
+ static int
+ setbsdcomp(argv)
+     char **argv;
+ {
+     int rbits, abits;
+     char *str, *endp;
+ 
+     str = *argv;
+     abits = rbits = strtol(str, &endp, 0);
+     if (endp != str && *endp == ',') {
+ 	str = endp + 1;
+ 	abits = strtol(str, &endp, 0);
+     }
+     if (*endp != 0 || endp == str) {
+ 	option_error("invalid parameter '%s' for bsdcomp option", *argv);
+ 	return 0;
+     }
+     if ((rbits != 0 && (rbits < BSD_MIN_BITS || rbits > BSD_MAX_BITS))
+ 	|| (abits != 0 && (abits < BSD_MIN_BITS || abits > BSD_MAX_BITS))) {
+ 	option_error("bsdcomp option values must be 0 or %d .. %d",
+ 		     BSD_MIN_BITS, BSD_MAX_BITS);
+ 	return 0;
+     }
+     if (rbits > 0) {
+ 	ccp_wantoptions[0].bsd_compress = 1;
+ 	ccp_wantoptions[0].bsd_bits = rbits;
+     } else
+ 	ccp_wantoptions[0].bsd_compress = 0;
+     if (abits > 0) {
+ 	ccp_allowoptions[0].bsd_compress = 1;
+ 	ccp_allowoptions[0].bsd_bits = abits;
+     } else
+ 	ccp_allowoptions[0].bsd_compress = 0;
+     return 1;
+ }
+ 
+ static int
+ setnobsdcomp(argv)
+     char **argv;
+ {
+     ccp_wantoptions[0].bsd_compress = 0;
+     ccp_allowoptions[0].bsd_compress = 0;
+     return 1;
+ }
+ 
+ static int
+ setdeflate(argv)
+     char **argv;
+ {
+     int rbits, abits;
+     char *str, *endp;
+ 
+     str = *argv;
+     abits = rbits = strtol(str, &endp, 0);
+     if (endp != str && *endp == ',') {
+ 	str = endp + 1;
+ 	abits = strtol(str, &endp, 0);
+     }
+     if (*endp != 0 || endp == str) {
+ 	option_error("invalid parameter '%s' for deflate option", *argv);
+ 	return 0;
+     }
+     if ((rbits != 0 && (rbits < DEFLATE_MIN_SIZE || rbits > DEFLATE_MAX_SIZE))
+ 	|| (abits != 0 && (abits < DEFLATE_MIN_SIZE
+ 			  || abits > DEFLATE_MAX_SIZE))) {
+ 	option_error("deflate option values must be 0 or %d .. %d",
+ 		     DEFLATE_MIN_SIZE, DEFLATE_MAX_SIZE);
+ 	return 0;
+     }
+     if (rbits > 0) {
+ 	ccp_wantoptions[0].deflate = 1;
+ 	ccp_wantoptions[0].deflate_size = rbits;
+     } else
+ 	ccp_wantoptions[0].deflate = 0;
+     if (abits > 0) {
+ 	ccp_allowoptions[0].deflate = 1;
+ 	ccp_allowoptions[0].deflate_size = abits;
+     } else
+ 	ccp_allowoptions[0].deflate = 0;
+     return 1;
+ }
+ 
+ static int
+ setnodeflate(argv)
+     char **argv;
+ {
+     ccp_wantoptions[0].deflate = 0;
+     ccp_allowoptions[0].deflate = 0;
+     return 1;
+ }
+ 
+ static int
+ setnodeflatedraft(argv)
+     char **argv;
+ {
+     ccp_wantoptions[0].deflate_draft = 0;
+     ccp_allowoptions[0].deflate_draft = 0;
+     return 1;
+ }
+ 
+ static int
+ setpred1comp(argv)
+     char **argv;
+ {
+     ccp_wantoptions[0].predictor_1 = 1;
+     ccp_allowoptions[0].predictor_1 = 1;
+     return 1;
+ }
+ 
+ static int
+ setnopred1comp(argv)
+     char **argv;
+ {
+     ccp_wantoptions[0].predictor_1 = 0;
+     ccp_allowoptions[0].predictor_1 = 0;
+     return 1;
+ }
+ 
+ static int
+ setipparam(argv)
+     char **argv;
+ {
+     ipparam = strdup(*argv);
+     if (ipparam == NULL)
+ 	novm("ipparam string");
+ 
+     return 1;
+ }
+ 
+ static int
+ setpapcrypt(argv)
+     char **argv;
+ {
+     cryptpap = 1;
+     return 1;
+ }
+ 
+ static int
+ setidle(argv)
+     char **argv;
+ {
+     return int_option(*argv, &idle_time_limit);
+ }
+ 
+ static int
+ setholdoff(argv)
+     char **argv;
+ {
+     return int_option(*argv, &holdoff);
+ }
+ 
+ /*
+  * setdnsaddr - set the dns address(es)
+  */
+ static int
+ setdnsaddr(argv)
+     char **argv;
+ {
+     u_int32_t dns;
+     struct hostent *hp;
+ 
+     dns = inet_addr(*argv);
+     if (dns == -1) {
+ 	if ((hp = gethostbyname(*argv)) == NULL) {
+ 	    option_error("invalid address parameter '%s' for ms-dns option",
+ 			 *argv);
+ 	    return 0;
+ 	}
+ 	dns = *(u_int32_t *)hp->h_addr;
+     }
+ 
+     /* if there is no primary then update it. */
+     if (ipcp_allowoptions[0].dnsaddr[0] == 0)
+ 	ipcp_allowoptions[0].dnsaddr[0] = dns;
+ 
+     /* always set the secondary address value to the same value. */
+     ipcp_allowoptions[0].dnsaddr[1] = dns;
+ 
+     return (1);
+ }
+ 
+ /*
+  * setwinsaddr - set the wins address(es)
+  * This is primrarly used with the Samba package under UNIX or for pointing
+  * the caller to the existing WINS server on a Windows NT platform.
+  */
+ static int
+ setwinsaddr(argv)
+     char **argv;
+ {
+     u_int32_t wins;
+     struct hostent *hp;
+ 
+     wins = inet_addr(*argv);
+     if (wins == -1) {
+ 	if ((hp = gethostbyname(*argv)) == NULL) {
+ 	    option_error("invalid address parameter '%s' for ms-wins option",
+ 			 *argv);
+ 	    return 0;
+ 	}
+ 	wins = *(u_int32_t *)hp->h_addr;
+     }
+ 
+     /* if there is no primary then update it. */
+     if (ipcp_allowoptions[0].winsaddr[0] == 0)
+ 	ipcp_allowoptions[0].winsaddr[0] = wins;
+ 
+     /* always set the secondary address value to the same value. */
+     ipcp_allowoptions[0].winsaddr[1] = wins;
+ 
+     return (1);
+ }
+ 
+ #ifdef IPX_CHANGE
+ static int
+ setipxrouter (argv)
+     char **argv;
+ {
+     ipxcp_wantoptions[0].neg_router  = 1;
+     ipxcp_allowoptions[0].neg_router = 1;
+     return int_option(*argv, &ipxcp_wantoptions[0].router); 
+ }
+ 
+ static int
+ setipxname (argv)
+     char **argv;
+ {
+     char *dest = ipxcp_wantoptions[0].name;
+     char *src  = *argv;
+     int  count;
+     char ch;
+ 
+     ipxcp_wantoptions[0].neg_name  = 1;
+     ipxcp_allowoptions[0].neg_name = 1;
+     memset (dest, '\0', sizeof (ipxcp_wantoptions[0].name));
+ 
+     count = 0;
+     while (*src) {
+         ch = *src++;
+ 	if (! isalnum (ch) && ch != '_') {
+ 	    option_error("IPX router name must be alphanumeric or _");
+ 	    return 0;
+ 	}
+ 
+ 	if (count >= sizeof (ipxcp_wantoptions[0].name)) {
+ 	    option_error("IPX router name is limited to %d characters",
+ 			 sizeof (ipxcp_wantoptions[0].name) - 1);
+ 	    return 0;
+ 	}
+ 
+ 	dest[count++] = toupper (ch);
+     }
+ 
+     return 1;
+ }
+ 
+ static int
+ setipxcptimeout (argv)
+     char **argv;
+ {
+     return int_option(*argv, &ipxcp_fsm[0].timeouttime);
+ }
+ 
+ static int
+ setipxcpterm (argv)
+     char **argv;
+ {
+     return int_option(*argv, &ipxcp_fsm[0].maxtermtransmits);
+ }
+ 
+ static int
+ setipxcpconf (argv)
+     char **argv;
+ {
+     return int_option(*argv, &ipxcp_fsm[0].maxconfreqtransmits);
+ }
+ 
+ static int
+ setipxcpfails (argv)
+     char **argv;
+ {
+     return int_option(*argv, &ipxcp_fsm[0].maxnakloops);
+ }
+ 
+ static int
+ setipxnetwork(argv)
+     char **argv;
+ {
+     u_int32_t v;
+ 
+     if (!number_option(*argv, &v, 16))
+ 	return 0;
+ 
+     ipxcp_wantoptions[0].our_network = (int) v;
+     ipxcp_wantoptions[0].neg_nn      = 1;
+     return 1;
+ }
+ 
+ static int
+ setipxanet(argv)
+     char **argv;
+ {
+     ipxcp_wantoptions[0].accept_network = 1;
+     ipxcp_allowoptions[0].accept_network = 1;
+     return 1;
+ }
+ 
+ static int
+ setipxalcl(argv)
+     char **argv;
+ {
+     ipxcp_wantoptions[0].accept_local = 1;
+     ipxcp_allowoptions[0].accept_local = 1;
+     return 1;
+ }
+ 
+ static int
+ setipxarmt(argv)
+     char **argv;
+ {
+     ipxcp_wantoptions[0].accept_remote = 1;
+     ipxcp_allowoptions[0].accept_remote = 1;
+     return 1;
+ }
+ 
+ static u_char *
+ setipxnodevalue(src,dst)
+ u_char *src, *dst;
+ {
+     int indx;
+     int item;
+ 
+     for (;;) {
+         if (!isxdigit (*src))
+ 	    break;
+ 	
+ 	for (indx = 0; indx < 5; ++indx) {
+ 	    dst[indx] <<= 4;
+ 	    dst[indx] |= (dst[indx + 1] >> 4) & 0x0F;
+ 	}
+ 
+ 	item = toupper (*src) - '0';
+ 	if (item > 9)
+ 	    item -= 7;
+ 
+ 	dst[5] = (dst[5] << 4) | item;
+ 	++src;
+     }
+     return src;
+ }
+ 
+ static int
+ setipxnode(argv)
+     char **argv;
+ {
+     char *end;
+ 
+     memset (&ipxcp_wantoptions[0].our_node[0], 0, 6);
+     memset (&ipxcp_wantoptions[0].his_node[0], 0, 6);
+ 
+     end = setipxnodevalue (*argv, &ipxcp_wantoptions[0].our_node[0]);
+     if (*end == ':')
+ 	end = setipxnodevalue (++end, &ipxcp_wantoptions[0].his_node[0]);
+ 
+     if (*end == '\0') {
+         ipxcp_wantoptions[0].neg_node = 1;
+         return 1;
+     }
+ 
+     option_error("invalid parameter '%s' for ipx-node option", *argv);
+     return 0;
+ }
+ 
+ static int
+ setipxproto(argv)
+     char **argv;
+ {
+     ipxcp_protent.enabled_flag = 1;
+     return 1;
+ }
+ 
+ static int
+ resetipxproto(argv)
+     char **argv;
+ {
+     ipxcp_protent.enabled_flag = 0;
+     return 1;
+ }
+ #else
+ 
+ static int
+ resetipxproto(argv)
+     char **argv;
+ {
+     return 1;
+ }
+ #endif /* IPX_CHANGE */
+ 
+ #ifdef MSLANMAN
+ static int
+ setmslanman(argv)
+     char **argv;
+ {
+     ms_lanman = 1;
+     return (1);
+ }
+ #endif
Binary files ppp-2.3.5/pppd/pppd.core and ppp-2.3.5-2cbcps-radius-multiport/pppd/pppd.core differ
diff -r -P -d -C 3 ppp-2.3.5/pppd/pppd.h ppp-2.3.5-2cbcps-radius-multiport/pppd/pppd.h
*** ppp-2.3.5/pppd/pppd.h	Thu Mar 26 09:46:07 1998
--- ppp-2.3.5-2cbcps-radius-multiport/pppd/pppd.h	Sun Jan 16 14:08:28 2000
***************
*** 79,84 ****
--- 79,85 ----
  extern int	kdebugflag;	/* Tell kernel to print debug messages */
  extern int	default_device;	/* Using /dev/tty or equivalent */
  extern char	devnam[];	/* Device name */
+ extern char     staticdevnam[]; /* Reserv value - Device name */
  extern int	crtscts;	/* Use hardware flow control */
  extern int	modem;		/* Use modem control lines */
  extern int	inspeed;	/* Input/Output speed requested */
***************
*** 86,91 ****
--- 87,96 ----
  extern int	lockflag;	/* Create lock file to lock the serial dev */
  extern int	nodetach;	/* Don't detach from controlling tty */
  extern char	*connector;	/* Script to establish physical link */
+ extern int      useradius;      /* Using RADIUS for authentication */
+ extern int      usemultiport;   /* Use Multiport device (c) Ilya Ismailov, TTS, Tyumen, Russian*/
+ extern int      multiportfist;  /* Fist Multiport device (c) Ilya Ismailov, TTS,Tyumen, Russian*/
+ extern int      multiportend;   /* End Multiport device (c) Ilya Ismailov, TTS, Tyumen, Russian*/
  extern char	*disconnector;	/* Script to disestablish physical link */
  extern char	*welcomer;	/* Script to welcome client after connection */
  extern int	maxconnect;	/* Maximum connect time (seconds) */
***************
*** 113,119 ****
  extern struct	bpf_program pass_filter;   /* Filter for pkts to pass */
  extern struct	bpf_program active_filter; /* Filter for link-active pkts */
  #endif
! 
  
  #ifdef MSLANMAN
  extern int	ms_lanman;	/* Nonzero if use LanMan password instead of NT */
--- 118,127 ----
  extern struct	bpf_program pass_filter;   /* Filter for pkts to pass */
  extern struct	bpf_program active_filter; /* Filter for link-active pkts */
  #endif
! extern char	callerid[];
! extern char	calleridtool[];
! extern char	con_state[];
! extern char	con_tool[];
  
  #ifdef MSLANMAN
  extern int	ms_lanman;	/* Nonzero if use LanMan password instead of NT */
***************
*** 414,428 ****
  #define DEBUGCHAP	1
  #endif
  
- #ifndef LOG_PPP			/* we use LOG_LOCAL2 for syslog by default */
- #if defined(DEBUGMAIN) || defined(DEBUGFSM) || defined(DEBUGSYS) \
-   || defined(DEBUGLCP) || defined(DEBUGIPCP) || defined(DEBUGUPAP) \
-   || defined(DEBUGCHAP) || defined(DEBUG)
  #define LOG_PPP LOG_LOCAL2
- #else
- #define LOG_PPP LOG_DAEMON
- #endif
- #endif /* LOG_PPP */
  
  #ifdef DEBUGMAIN
  #define MAINDEBUG(x)	if (debug) syslog x
--- 422,428 ----
diff -r -P -d -C 3 ppp-2.3.5/pppd/pppd.h.orig ppp-2.3.5-2cbcps-radius-multiport/pppd/pppd.h.orig
*** ppp-2.3.5/pppd/pppd.h.orig	Thu Jan  1 05:00:00 1970
--- ppp-2.3.5-2cbcps-radius-multiport/pppd/pppd.h.orig	Thu Aug 19 15:19:10 1999
***************
*** 0 ****
--- 1,486 ----
+ /*
+  * pppd.h - PPP daemon global declarations.
+  *
+  * Copyright (c) 1989 Carnegie Mellon University.
+  * All rights reserved.
+  *
+  * Redistribution and use in source and binary forms are permitted
+  * provided that the above copyright notice and this paragraph are
+  * duplicated in all such forms and that any documentation,
+  * advertising materials, and other materials related to such
+  * distribution and use acknowledge that the software was developed
+  * by Carnegie Mellon University.  The name of the
+  * University may not be used to endorse or promote products derived
+  * from this software without specific prior written permission.
+  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+  *
+  * $Id: pppd.h,v 1.21 1998/03/26 04:46:08 paulus Exp $
+  */
+ 
+ /*
+  * TODO:
+  */
+ 
+ #ifndef __PPPD_H__
+ #define __PPPD_H__
+ 
+ #include <stdio.h>		/* for FILE */
+ #include <sys/param.h>		/* for MAXPATHLEN and BSD4_4, if defined */
+ #include <sys/types.h>		/* for u_int32_t, if defined */
+ #include <sys/time.h>		/* for struct timeval */
+ #include <net/ppp_defs.h>
+ 
+ #if __STDC__
+ #include <stdarg.h>
+ #define __V(x)	x
+ #else
+ #include <varargs.h>
+ #define __V(x)	(va_alist) va_dcl
+ #define const
+ #endif
+ 
+ /*
+  * Limits.
+  */
+ 
+ #define NUM_PPP		1	/* One PPP interface supported (per process) */
+ #define MAXWORDLEN	1024	/* max length of word in file (incl null) */
+ #define MAXARGS		1	/* max # args to a command */
+ #define MAXNAMELEN	256	/* max length of hostname or name for auth */
+ #define MAXSECRETLEN	256	/* max length of password or secret */
+ 
+ /*
+  * Global variables.
+  */
+ 
+ extern int	hungup;		/* Physical layer has disconnected */
+ extern int	ifunit;		/* Interface unit number */
+ extern char	ifname[];	/* Interface name */
+ extern int	ttyfd;		/* Serial device file descriptor */
+ extern char	hostname[];	/* Our hostname */
+ extern u_char	outpacket_buf[]; /* Buffer for outgoing packets */
+ extern int	phase;		/* Current state of link - see values below */
+ extern int	baud_rate;	/* Current link speed in bits/sec */
+ extern char	*progname;	/* Name of this program */
+ extern int	redirect_stderr;/* Connector's stderr should go to file */
+ extern char	peer_authname[];/* Authenticated name of peer */
+ extern int	privileged;	/* We were run by real-uid root */
+ extern int	need_holdoff;	/* Need holdoff period after link terminates */
+ extern char	**script_env;	/* Environment variables for scripts */
+ extern int	detached;	/* Have detached from controlling tty */
+ 
+ /*
+  * Variables set by command-line options.
+  */
+ 
+ extern int	debug;		/* Debug flag */
+ extern int	kdebugflag;	/* Tell kernel to print debug messages */
+ extern int	default_device;	/* Using /dev/tty or equivalent */
+ extern char	devnam[];	/* Device name */
+ extern int	crtscts;	/* Use hardware flow control */
+ extern int	modem;		/* Use modem control lines */
+ extern int	inspeed;	/* Input/Output speed requested */
+ extern u_int32_t netmask;	/* IP netmask to set on interface */
+ extern int	lockflag;	/* Create lock file to lock the serial dev */
+ extern int	nodetach;	/* Don't detach from controlling tty */
+ extern char	*connector;	/* Script to establish physical link */
+ extern int      useradius;      /* Using RADIUS for authentication */
+ extern char	*disconnector;	/* Script to disestablish physical link */
+ extern char	*welcomer;	/* Script to welcome client after connection */
+ extern int	maxconnect;	/* Maximum connect time (seconds) */
+ extern char	user[];		/* Our name for authenticating ourselves */
+ extern char	passwd[];	/* Password for PAP */
+ extern int	auth_required;	/* Peer is required to authenticate */
+ extern int	proxyarp;	/* Set up proxy ARP entry for peer */
+ extern int	persist;	/* Reopen link after it goes down */
+ extern int	uselogin;	/* Use /etc/passwd for checking PAP */
+ extern int	lcp_echo_interval; /* Interval between LCP echo-requests */
+ extern int	lcp_echo_fails;	/* Tolerance to unanswered echo-requests */
+ extern char	our_name[];	/* Our name for authentication purposes */
+ extern char	remote_name[];	/* Peer's name for authentication */
+ extern int	explicit_remote;/* remote_name specified with remotename opt */
+ extern int	usehostname;	/* Use hostname for our_name */
+ extern int	disable_defaultip; /* Don't use hostname for default IP adrs */
+ extern int	demand;		/* Do dial-on-demand */
+ extern char	*ipparam;	/* Extra parameter for ip up/down scripts */
+ extern int	cryptpap;	/* Others' PAP passwords are encrypted */
+ extern int	idle_time_limit;/* Shut down link if idle for this long */
+ extern int	holdoff;	/* Dead time before restarting */
+ extern int	refuse_pap;	/* Don't wanna auth. ourselves with PAP */
+ extern int	refuse_chap;	/* Don't wanna auth. ourselves with CHAP */
+ #ifdef PPP_FILTER
+ extern struct	bpf_program pass_filter;   /* Filter for pkts to pass */
+ extern struct	bpf_program active_filter; /* Filter for link-active pkts */
+ #endif
+ extern char	callerid[];
+ extern char	calleridtool[];
+ extern char	con_state[];
+ extern char	con_tool[];
+ 
+ #ifdef MSLANMAN
+ extern int	ms_lanman;	/* Nonzero if use LanMan password instead of NT */
+ 				/* Has meaning only with MS-CHAP challenges */
+ #endif
+ 
+ /*
+  * Values for phase.
+  */
+ #define PHASE_DEAD		0
+ #define PHASE_INITIALIZE	1
+ #define PHASE_DORMANT		2
+ #define PHASE_ESTABLISH		3
+ #define PHASE_AUTHENTICATE	4
+ #define PHASE_CALLBACK		5
+ #define PHASE_NETWORK		6
+ #define PHASE_TERMINATE		7
+ #define PHASE_HOLDOFF		8
+ 
+ /*
+  * The following struct gives the addresses of procedures to call
+  * for a particular protocol.
+  */
+ struct protent {
+     u_short protocol;		/* PPP protocol number */
+     /* Initialization procedure */
+     void (*init) __P((int unit));
+     /* Process a received packet */
+     void (*input) __P((int unit, u_char *pkt, int len));
+     /* Process a received protocol-reject */
+     void (*protrej) __P((int unit));
+     /* Lower layer has come up */
+     void (*lowerup) __P((int unit));
+     /* Lower layer has gone down */
+     void (*lowerdown) __P((int unit));
+     /* Open the protocol */
+     void (*open) __P((int unit));
+     /* Close the protocol */
+     void (*close) __P((int unit, char *reason));
+     /* Print a packet in readable form */
+     int  (*printpkt) __P((u_char *pkt, int len,
+ 			  void (*printer) __P((void *, char *, ...)),
+ 			  void *arg));
+     /* Process a received data packet */
+     void (*datainput) __P((int unit, u_char *pkt, int len));
+     int  enabled_flag;		/* 0 iff protocol is disabled */
+     char *name;			/* Text name of protocol */
+     /* Check requested options, assign defaults */
+     void (*check_options) __P((void));
+     /* Configure interface for demand-dial */
+     int  (*demand_conf) __P((int unit));
+     /* Say whether to bring up link for this pkt */
+     int  (*active_pkt) __P((u_char *pkt, int len));
+ };
+ 
+ /* Table of pointers to supported protocols */
+ extern struct protent *protocols[];
+ 
+ /*
+  * Prototypes.
+  */
+ 
+ /* Procedures exported from main.c. */
+ void detach __P((void));	/* Detach from controlling tty */
+ void die __P((int));		/* Cleanup and exit */
+ void quit __P((void));		/* like die(1) */
+ void novm __P((char *));	/* Say we ran out of memory, and die */
+ void timeout __P((void (*func)(void *), void *arg, int t));
+ 				/* Call func(arg) after t seconds */
+ void untimeout __P((void (*func)(void *), void *arg));
+ 				/* Cancel call to func(arg) */
+ int run_program __P((char *prog, char **args, int must_exist));
+ 				/* Run program prog with args in child */
+ void demuxprotrej __P((int, int));
+ 				/* Demultiplex a Protocol-Reject */
+ void format_packet __P((u_char *, int, void (*) (void *, char *, ...),
+ 		void *));	/* Format a packet in human-readable form */
+ void log_packet __P((u_char *, int, char *, int));
+ 				/* Format a packet and log it with syslog */
+ void print_string __P((char *, int,  void (*) (void *, char *, ...),
+ 		void *));	/* Format a string for output */
+ int fmtmsg __P((char *, int, char *, ...));		/* sprintf++ */
+ int vfmtmsg __P((char *, int, char *, va_list));	/* vsprintf++ */
+ void script_setenv __P((char *, char *));	/* set script env var */
+ void script_unsetenv __P((char *));		/* unset script env var */
+ 
+ /* Procedures exported from auth.c */
+ void link_required __P((int));	  /* we are starting to use the link */
+ void link_terminated __P((int));  /* we are finished with the link */
+ void link_down __P((int));	  /* the LCP layer has left the Opened state */
+ void link_established __P((int)); /* the link is up; authenticate now */
+ void np_up __P((int, int));	  /* a network protocol has come up */
+ void np_down __P((int, int));	  /* a network protocol has gone down */
+ void np_finished __P((int, int)); /* a network protocol no longer needs link */
+ void auth_peer_fail __P((int, int));
+ 				/* peer failed to authenticate itself */
+ void auth_peer_success __P((int, int, char *, int));
+ 				/* peer successfully authenticated itself */
+ void auth_withpeer_fail __P((int, int));
+ 				/* we failed to authenticate ourselves */
+ void auth_withpeer_success __P((int, int));
+ 				/* we successfully authenticated ourselves */
+ void auth_check_options __P((void));
+ 				/* check authentication options supplied */
+ void auth_reset __P((int));	/* check what secrets we have */
+ int  check_passwd __P((int, char *, int, char *, int, char **, int *));
+ 				/* Check peer-supplied username/password */
+ int  get_secret __P((int, char *, char *, char *, int *, int));
+ 				/* get "secret" for chap */
+ int  auth_ip_addr __P((int, u_int32_t));
+ 				/* check if IP address is authorized */
+ int  bad_ip_adrs __P((u_int32_t));
+ 				/* check if IP address is unreasonable */
+ void check_access __P((FILE *, char *));
+ 				/* check permissions on secrets file */
+ 
+ /* Procedures exported from demand.c */
+ void demand_conf __P((void));	/* config interface(s) for demand-dial */
+ void demand_block __P((void));	/* set all NPs to queue up packets */
+ void demand_unblock __P((void)); /* set all NPs to pass packets */
+ void demand_discard __P((void)); /* set all NPs to discard packets */
+ void demand_rexmit __P((int));	/* retransmit saved frames for an NP */
+ int  loop_chars __P((unsigned char *, int)); /* process chars from loopback */
+ int  loop_frame __P((unsigned char *, int)); /* process frame from loopback */
+ 
+ /* Procedures exported from sys-*.c */
+ void sys_init __P((void));	/* Do system-dependent initialization */
+ void sys_cleanup __P((void));	/* Restore system state before exiting */
+ void sys_check_options __P((void)); /* Check options specified */
+ void sys_close __P((void));	/* Clean up in a child before execing */
+ int  ppp_available __P((void));	/* Test whether ppp kernel support exists */
+ void open_ppp_loopback __P((void)); /* Open loopback for demand-dialling */
+ void establish_ppp __P((int));	/* Turn serial port into a ppp interface */
+ void restore_loop __P((void));	/* Transfer ppp unit back to loopback */
+ void disestablish_ppp __P((int)); /* Restore port to normal operation */
+ void clean_check __P((void));	/* Check if line was 8-bit clean */
+ void set_up_tty __P((int, int)); /* Set up port's speed, parameters, etc. */
+ void restore_tty __P((int));	/* Restore port's original parameters */
+ void setdtr __P((int, int));	/* Raise or lower port's DTR line */
+ void output __P((int, u_char *, int)); /* Output a PPP packet */
+ void wait_input __P((struct timeval *));
+ 				/* Wait for input, with timeout */
+ void wait_loop_output __P((struct timeval *));
+ 				/* Wait for pkt from loopback, with timeout */
+ void wait_time __P((struct timeval *)); /* Wait for given length of time */
+ int  read_packet __P((u_char *)); /* Read PPP packet */
+ int  get_loop_output __P((void)); /* Read pkts from loopback */
+ void ppp_send_config __P((int, int, u_int32_t, int, int));
+ 				/* Configure i/f transmit parameters */
+ void ppp_set_xaccm __P((int, ext_accm));
+ 				/* Set extended transmit ACCM */
+ void ppp_recv_config __P((int, int, u_int32_t, int, int));
+ 				/* Configure i/f receive parameters */
+ int  ccp_test __P((int, u_char *, int, int));
+ 				/* Test support for compression scheme */
+ void ccp_flags_set __P((int, int, int));
+ 				/* Set kernel CCP state */
+ int  ccp_fatal_error __P((int)); /* Test for fatal decomp error in kernel */
+ int  get_idle_time __P((int, struct ppp_idle *));
+ 				/* Find out how long link has been idle */
+ int  sifvjcomp __P((int, int, int, int));
+ 				/* Configure VJ TCP header compression */
+ int  sifup __P((int));		/* Configure i/f up (for IP) */
+ int  sifnpmode __P((int u, int proto, enum NPmode mode));
+ 				/* Set mode for handling packets for proto */
+ int  sifdown __P((int));	/* Configure i/f down (for IP) */
+ int  sifaddr __P((int, u_int32_t, u_int32_t, u_int32_t));
+ 				/* Configure IP addresses for i/f */
+ int  cifaddr __P((int, u_int32_t, u_int32_t));
+ 				/* Reset i/f IP addresses */
+ int  sifdefaultroute __P((int, u_int32_t, u_int32_t));
+ 				/* Create default route through i/f */
+ int  cifdefaultroute __P((int, u_int32_t, u_int32_t));
+ 				/* Delete default route through i/f */
+ int  sifproxyarp __P((int, u_int32_t));
+ 				/* Add proxy ARP entry for peer */
+ int  cifproxyarp __P((int, u_int32_t));
+ 				/* Delete proxy ARP entry for peer */
+ u_int32_t GetMask __P((u_int32_t)); /* Get appropriate netmask for address */
+ int  lock __P((char *));	/* Create lock file for device */
+ void unlock __P((void));	/* Delete previously-created lock file */
+ int  daemon __P((int, int));	/* Detach us from terminal session */
+ void logwtmp __P((const char *, const char *, const char *));
+ 				/* Write entry to wtmp file */
+ int  get_host_seed __P((void));	/* Get host-dependent random number seed */
+ #ifdef PPP_FILTER
+ int  set_filters __P((struct bpf_program *pass, struct bpf_program *active));
+ 				/* Set filter programs in kernel */
+ #endif
+ 
+ /* Procedures exported from options.c */
+ int  parse_args __P((int argc, char **argv));
+ 				/* Parse options from arguments given */
+ void usage __P((void));		/* Print a usage message */
+ int  options_from_file __P((char *filename, int must_exist, int check_prot,
+ 			    int privileged));
+ 				/* Parse options from an options file */
+ int  options_from_user __P((void)); /* Parse options from user's .ppprc */
+ int  options_for_tty __P((void)); /* Parse options from /etc/ppp/options.tty */
+ void scan_args __P((int argc, char **argv));
+ 				/* Look for tty name in command-line args */
+ int  getword __P((FILE *f, char *word, int *newlinep, char *filename));
+ 				/* Read a word from a file */
+ void option_error __P((char *fmt, ...));
+ 				/* Print an error message about an option */
+ 
+ /*
+  * This structure is used to store information about certain
+  * options, such as where the option value came from (/etc/ppp/options,
+  * command line, etc.) and whether it came from a privileged source.
+  */
+ 
+ struct option_info {
+     int	    priv;		/* was value set by sysadmin? */
+     char    *source;		/* where option came from */
+ };
+ 
+ extern struct option_info auth_req_info;
+ extern struct option_info connector_info;
+ extern struct option_info disconnector_info;
+ extern struct option_info welcomer_info;
+ extern struct option_info devnam_info;
+ 
+ /*
+  * Inline versions of get/put char/short/long.
+  * Pointer is advanced; we assume that both arguments
+  * are lvalues and will already be in registers.
+  * cp MUST be u_char *.
+  */
+ #define GETCHAR(c, cp) { \
+ 	(c) = *(cp)++; \
+ }
+ #define PUTCHAR(c, cp) { \
+ 	*(cp)++ = (u_char) (c); \
+ }
+ 
+ 
+ #define GETSHORT(s, cp) { \
+ 	(s) = *(cp)++ << 8; \
+ 	(s) |= *(cp)++; \
+ }
+ #define PUTSHORT(s, cp) { \
+ 	*(cp)++ = (u_char) ((s) >> 8); \
+ 	*(cp)++ = (u_char) (s); \
+ }
+ 
+ #define GETLONG(l, cp) { \
+ 	(l) = *(cp)++ << 8; \
+ 	(l) |= *(cp)++; (l) <<= 8; \
+ 	(l) |= *(cp)++; (l) <<= 8; \
+ 	(l) |= *(cp)++; \
+ }
+ #define PUTLONG(l, cp) { \
+ 	*(cp)++ = (u_char) ((l) >> 24); \
+ 	*(cp)++ = (u_char) ((l) >> 16); \
+ 	*(cp)++ = (u_char) ((l) >> 8); \
+ 	*(cp)++ = (u_char) (l); \
+ }
+ 
+ #define INCPTR(n, cp)	((cp) += (n))
+ #define DECPTR(n, cp)	((cp) -= (n))
+ 
+ #undef  FALSE
+ #define FALSE	0
+ #undef  TRUE
+ #define TRUE	1
+ 
+ /*
+  * System dependent definitions for user-level 4.3BSD UNIX implementation.
+  */
+ 
+ #define DEMUXPROTREJ(u, p)	demuxprotrej(u, p)
+ 
+ #define TIMEOUT(r, f, t)	timeout((r), (f), (t))
+ #define UNTIMEOUT(r, f)		untimeout((r), (f))
+ 
+ #define BCOPY(s, d, l)		memcpy(d, s, l)
+ #define BZERO(s, n)		memset(s, 0, n)
+ #define EXIT(u)			quit()
+ 
+ #define PRINTMSG(m, l)	{ m[l] = '\0'; syslog(LOG_INFO, "Remote message: %s", m); }
+ 
+ /*
+  * MAKEHEADER - Add Header fields to a packet.
+  */
+ #define MAKEHEADER(p, t) { \
+     PUTCHAR(PPP_ALLSTATIONS, p); \
+     PUTCHAR(PPP_UI, p); \
+     PUTSHORT(t, p); }
+ 
+ 
+ #ifdef DEBUGALL
+ #define DEBUGMAIN	1
+ #define DEBUGFSM	1
+ #define DEBUGLCP	1
+ #define DEBUGIPCP	1
+ #define DEBUGUPAP	1
+ #define DEBUGCHAP	1
+ #endif
+ 
+ #define LOG_PPP LOG_LOCAL2
+ 
+ #ifdef DEBUGMAIN
+ #define MAINDEBUG(x)	if (debug) syslog x
+ #else
+ #define MAINDEBUG(x)
+ #endif
+ 
+ #ifdef DEBUGSYS
+ #define SYSDEBUG(x)	if (debug) syslog x
+ #else
+ #define SYSDEBUG(x)
+ #endif
+ 
+ #ifdef DEBUGFSM
+ #define FSMDEBUG(x)	if (debug) syslog x
+ #else
+ #define FSMDEBUG(x)
+ #endif
+ 
+ #ifdef DEBUGLCP
+ #define LCPDEBUG(x)	if (debug) syslog x
+ #else
+ #define LCPDEBUG(x)
+ #endif
+ 
+ #ifdef DEBUGIPCP
+ #define IPCPDEBUG(x)	if (debug) syslog x
+ #else
+ #define IPCPDEBUG(x)
+ #endif
+ 
+ #ifdef DEBUGUPAP
+ #define UPAPDEBUG(x)	if (debug) syslog x
+ #else
+ #define UPAPDEBUG(x)
+ #endif
+ 
+ #ifdef DEBUGCHAP
+ #define CHAPDEBUG(x)	if (debug) syslog x
+ #else
+ #define CHAPDEBUG(x)
+ #endif
+ 
+ #ifdef DEBUGIPXCP
+ #define IPXCPDEBUG(x)	if (debug) syslog x
+ #else
+ #define IPXCPDEBUG(x)
+ #endif
+ 
+ #ifndef SIGTYPE
+ #if defined(sun) || defined(SYSV) || defined(POSIX_SOURCE)
+ #define SIGTYPE void
+ #else
+ #define SIGTYPE int
+ #endif /* defined(sun) || defined(SYSV) || defined(POSIX_SOURCE) */
+ #endif /* SIGTYPE */
+ 
+ #ifndef MIN
+ #define MIN(a, b)	((a) < (b)? (a): (b))
+ #endif
+ #ifndef MAX
+ #define MAX(a, b)	((a) > (b)? (a): (b))
+ #endif
+ 
+ #endif /* __PPP_H__ */
diff -r -P -d -C 3 ppp-2.3.5/pppd/pppdradius.c ppp-2.3.5-2cbcps-radius-multiport/pppd/pppdradius.c
*** ppp-2.3.5/pppd/pppdradius.c	Thu Jan  1 05:00:00 1970
--- ppp-2.3.5-2cbcps-radius-multiport/pppd/pppdradius.c	Mon Aug 16 11:22:31 1999
***************
*** 0 ****
--- 1,155 ----
+ /*   Copyright (c) 1997      Cyril A. Vechera      St.-Petersburg, RUSSIA
+  *
+  *  Redistribution and use in source and binary forms, with or without
+  *  modification, are permitted provided that the following conditions
+  *  are met:
+  *  1. Redistributions of source code must retain the above copyright
+  *     notice, this list of conditions and the following disclaimer.
+  *  2. Redistributions in binary form must reproduce the above copyright
+  *     notice, this list of conditions and the following disclaimer in the
+  *     documentation and/or other materials provided with the distribution.
+  *  3. The name of the author may not be used to endorse or promote products
+  *     derived from this software without specific prior written permission.
+  *  4. Any form of use of source and binaries are permitted only for
+  *     noncommercial purpose. Any forms of commercial usage require
+  *     direct author's permission.
+  */
+ 
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <syslog.h>
+ #include <utmp.h>
+ 
+ #include "fsm.h"
+ #include "ipcp.h"
+ #include "lcp.h"
+ #include "pppd.h"
+ #include "upap.h"
+ #include "libradius.h"
+ #include "pppdradius.h"
+ 
+ char 	rad_user[16] = "\0";
+ u_long	rad_port = 0;
+ u_long	rad_address = 0L;
+ u_long	rad_netmask = 0L;
+ u_long	rad_mtu = 0L;
+ u_long	rad_vj = 0L;
+ int	radlogged_in = 0;
+ 
+ extern int cbcp_volit;
+ 
+ int radlogin (char *name, char *passwd)
+ {
+     int err,i;
+     u_long *radppp_address;
+     u_long *radppp_netmask;
+     u_long *radppp_mtu;
+     u_long *radppp_vj;
+     struct stat s;
+     struct utmp utmp;    
+     char *tty;           
+ 
+     strncpy (rad_user, name, 16);
+     radppp_address = &rad_address;
+     radppp_netmask = &rad_netmask;
+     radppp_mtu = &rad_mtu;
+     radppp_vj = &rad_vj;
+ 
+     if (fstat (ttyfd, &s))
+ 	s.st_rdev = 0;
+     rad_port = (major(s.st_rdev) << 12) | (minor(s.st_rdev) & 0x0fff);
+ 
+     err = radius_request_ppp_PAP (rad_user, passwd, rad_port, &radppp_address,
+     		&radppp_netmask, &radppp_mtu, &radppp_vj);
+ 
+     syslog(LOG_WARNING,"RADIUS auth passed: err %d",err);
+     if (!err) /* if authenticated successfully - start accounting */
+     {
+ 	radius_session_start_time = time(NULL);
+ 
+ /* session id - nas-ip-address + tty-device + pid + time */
+ 	sprintf(radius_session_id, "%s %s [%u] %s",
+ 		 inet_ntoa (radius_me.sin_addr),
+ 		 devname (s.st_rdev, S_IFCHR),
+ 		 getpid(),
+ 		 ctime(&radius_session_start_time));
+ 
+ 	radius_account_start (rad_user, rad_port);
+         syslog(LOG_WARNING,"RADIUS accounting started: err %d",err);
+     }
+ 
+     switch (err)
+     {
+ 	case RADLIB_ACCESS_DENIED:
+ 		syslog(LOG_WARNING, "radlogin: access denied for user %s\n", name);
+ 		break;
+ 	case RADLIB_NO_RESPONSE:
+ 		syslog(LOG_ALERT, "radlogin: server doesn't respond\n");
+ 		break;
+ 	case RADLIB_BAD_ID:
+ 		syslog(LOG_ERR, "radlogin: bad response identifier\n");
+ 		break;
+ 	case RADLIB_BAD_AUTH:
+ 		syslog(LOG_ERR, "radlogin: server's response authentication failure\n");
+ 		break;
+ 	case RADLIB_BAD_CODE:
+ 		syslog(LOG_ERR, "radlogin: bad response code\n");
+ 		break;
+     }
+ 
+     if (err)
+ 	return UPAP_AUTHNAK;
+ 
+     radlogged_in = 1;
+ 
+     if (radppp_netmask)
+     {
+ 	memcpy (&netmask, radppp_netmask, 4);
+ 	syslog (LOG_DEBUG, "RADIUS netmask: %lx\n",netmask);
+     }
+ 
+     if (radppp_address)
+     {
+ 	memcpy (&ipcp_allowoptions[0].hisaddr, radppp_address, 4);
+ 	memcpy (&ipcp_wantoptions[0].hisaddr, radppp_address, 4);
+ 	syslog (LOG_DEBUG, "RADIUS address: %lx\n", ipcp_wantoptions[0].hisaddr);
+     }
+     tty = devnam;                     
+     if (strncmp(tty, "/dev/", 5) == 0)
+         tty += 5;                     
+     for(i=0;i<sizeof(utmp.ut_name);i++) if(user[i]=='@') {user[i]=0;break;}
+     memset((void *)&utmp, 0, sizeof(utmp));                   
+     (void)time(&utmp.ut_time);                                
+     (void)strncpy(utmp.ut_name,name, sizeof(utmp.ut_name));  
+     if(cbcp_volit==1) (void)strncpy(utmp.ut_host, "CALLBACK", sizeof(utmp.ut_host));
+     else (void)strncpy(utmp.ut_host, "DIAL-IN", sizeof(utmp.ut_host));
+     (void)strncpy(utmp.ut_line, tty, sizeof(utmp.ut_line));   
+     login(&utmp);                                             
+     return UPAP_AUTHACK;
+ }
+ 
+ void radlogout (void)
+ {
+     int err;
+ 
+     err=radius_account_stop(rad_user, rad_port, time(NULL)-radius_session_start_time);
+     switch (err)
+     {
+ 	case RADLIB_NO_RESPONSE:
+ 		syslog(LOG_ALERT, "radlogout: server doesn't respond\n");
+ 		break;
+ 	case RADLIB_BAD_ID:
+ 		syslog(LOG_ERR, "radlogout: bad response identifier\n");
+ 		break;
+ 	case RADLIB_BAD_AUTH:
+ 		syslog(LOG_ERR, "radlogout: server's response authentication failure\n");
+ 		break;
+ 	case RADLIB_BAD_CODE:
+ 		syslog(LOG_ERR, "radlogout: bad response code\n");
+ 		break;
+     }
+     radlogged_in = 0;
+     return;
+ }
diff -r -P -d -C 3 ppp-2.3.5/pppd/pppdradius.h ppp-2.3.5-2cbcps-radius-multiport/pppd/pppdradius.h
*** ppp-2.3.5/pppd/pppdradius.h	Thu Jan  1 05:00:00 1970
--- ppp-2.3.5-2cbcps-radius-multiport/pppd/pppdradius.h	Sun Jan 24 14:36:50 1999
***************
*** 0 ****
--- 1,16 ----
+ #ifndef PPPDRADIUS_H
+ #define PPPDRADIUS_H
+ 
+ #include "libradius.h"
+ 
+ extern char 	rad_user[16];
+ extern u_long	rad_address;
+ extern u_long	rad_netmask;
+ extern u_long	rad_mtu;
+ extern u_long	rad_cmprss;
+ extern int	radlogged_in;
+ 
+ int radlogin (char *, char *);
+ void radlogout (void);
+ 
+ #endif
\ No newline at end of file
diff -r -P -d -C 3 ppp-2.3.5/pppd/pppdradius.patch ppp-2.3.5-2cbcps-radius-multiport/pppd/pppdradius.patch
*** ppp-2.3.5/pppd/pppdradius.patch	Thu Jan  1 05:00:00 1970
--- ppp-2.3.5-2cbcps-radius-multiport/pppd/pppdradius.patch	Sun Jan 24 14:36:50 1999
***************
*** 0 ****
--- 1,174 ----
+ diff -r -c /usr/src/usr.sbin/pppd/Makefile pppd/Makefile
+ *** /usr/src/usr.sbin/pppd/Makefile	Thu Sep  5 02:43:20 1996
+ --- pppd/Makefile	Tue Aug 19 20:39:43 1997
+ ***************
+ *** 1,10 ****
+   #	$Id: Makefile,v 1.4 1996/09/04 22:43:20 bde Exp $
+   
+ ! CFLAGS+= -DHAVE_PATHS_H
+   
+   PROG=	pppd
+   SRCS=	main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c ccp.c \
+ ! 	auth.c options.c sys-bsd.c
+   MAN8=	pppd.8
+   # The next line is for NetBSD-current systems.
+   MAN=	pppd.cat8
+ --- 1,10 ----
+   #	$Id: Makefile,v 1.4 1996/09/04 22:43:20 bde Exp $
+   
+ ! CFLAGS+= -DHAVE_PATHS_H -ggdb
+   
+   PROG=	pppd
+   SRCS=	main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c ccp.c \
+ ! 	auth.c options.c sys-bsd.c pppdradius.c libradius.c md5.c
+   MAN8=	pppd.8
+   # The next line is for NetBSD-current systems.
+   MAN=	pppd.cat8
+ diff -r -c /usr/src/usr.sbin/pppd/auth.c pppd/auth.c
+ *** /usr/src/usr.sbin/pppd/auth.c	Mon Jan 13 01:06:13 1997
+ --- pppd/auth.c	Tue Aug 19 20:39:12 1997
+ ***************
+ *** 68,73 ****
+ --- 68,74 ----
+   #include "ipcp.h"
+   #include "ccp.h"
+   #include "pathnames.h"
+ + #include "pppdradius.h"
+   
+   #if defined(sun) && defined(sparc)
+   #include <alloca.h>
+ ***************
+ *** 135,140 ****
+ --- 136,143 ----
+   	return;
+       if (logged_in)
+   	ppplogout();
+ +     if (radlogged_in)
+ + 	radlogout();
+       phase = PHASE_DEAD;
+       syslog(LOG_NOTICE, "Connection terminated.");
+   }
+ ***************
+ *** 331,337 ****
+        */
+       if (ao->neg_upap && passwd[0] == 0 && !get_upap_passwd())
+   	ao->neg_upap = 0;
+ !     if (wo->neg_upap && !uselogin && !have_upap_secret())
+   	wo->neg_upap = 0;
+       if (ao->neg_chap && !have_chap_secret(our_name, remote_name))
+   	ao->neg_chap = 0;
+ --- 334,340 ----
+        */
+       if (ao->neg_upap && passwd[0] == 0 && !get_upap_passwd())
+   	ao->neg_upap = 0;
+ !     if (wo->neg_upap && !uselogin && !useradius && !have_upap_secret())
+   	wo->neg_upap = 0;
+       if (ao->neg_chap && !have_chap_secret(our_name, remote_name))
+   	ao->neg_chap = 0;
+ ***************
+ *** 395,401 ****
+       ret = UPAP_AUTHACK;
+       f = fopen(filename, "r");
+       if (f == NULL) {
+ ! 	if (!uselogin) {
+   	    syslog(LOG_ERR, "Can't open upap password file %s: %m", filename);
+   	    ret = UPAP_AUTHNAK;
+   	}
+ --- 398,404 ----
+       ret = UPAP_AUTHACK;
+       f = fopen(filename, "r");
+       if (f == NULL) {
+ ! 	if (!(uselogin || useradius)) {
+   	    syslog(LOG_ERR, "Can't open upap password file %s: %m", filename);
+   	    ret = UPAP_AUTHNAK;
+   	}
+ ***************
+ *** 417,422 ****
+ --- 420,439 ----
+   	    syslog(LOG_WARNING, "upap login failure for %s", user);
+   	}
+       }
+ + 
+ +     if (useradius)
+ + #ifdef RPPPD_DEBUG
+ +         {
+ + 	    int ret;
+ + #else
+ + 	if (ret == UPAP_AUTHNAK)
+ + 	{
+ + #endif
+ + 	    ret = radlogin(user, passwd);
+ + 	    if (ret == UPAP_AUTHNAK) {
+ + 		syslog(LOG_WARNING, "upap radius login failure for %s", user);
+ + 	    }
+ + 	}
+   
+       if (ret == UPAP_AUTHNAK) {
+   	*msg = "Login incorrect";
+ Only in pppd: config.sample
+ Only in pppd: libradius.c
+ Only in pppd: libradius.h
+ Only in pppd: md5.c
+ Only in pppd: md5.h
+ diff -r -c /usr/src/usr.sbin/pppd/options.c pppd/options.c
+ *** /usr/src/usr.sbin/pppd/options.c	Sun Aug 11 21:29:34 1996
+ --- pppd/options.c	Tue Aug 19 20:38:48 1997
+ ***************
+ *** 91,96 ****
+ --- 91,97 ----
+   int	disable_defaultip = 0;	/* Don't use hostname for default IP adrs */
+   char	*ipparam = NULL;	/* Extra parameter for ip up/down scripts */
+   int	cryptpap;		/* Passwords in pap-secrets are encrypted */
+ + int	useradius = 0;
+   
+   #ifdef _linux_
+   int idle_time_limit = 0;
+ ***************
+ *** 173,178 ****
+ --- 174,180 ----
+   static int setnobsdcomp __P((void));
+   static int setipparam __P((char **));
+   static int setpapcrypt __P((void));
+ + static int setradius __P((char **));
+   
+   static int number_option __P((char *, u_int32_t *, int));
+   static int readable __P((int fd));
+ ***************
+ *** 262,267 ****
+ --- 264,270 ----
+       {"-bsdcomp", 0, setnobsdcomp},	/* don't allow BSD-Compress */
+       {"ipparam", 1, setipparam},		/* set ip script parameter */
+       {"papcrypt", 0, setpapcrypt},	/* PAP passwords encrypted */
+ +     {"radius", 1, setradius},
+   #ifdef _linux_
+       {"idle-disconnect", 1, setidle}, /* seconds for disconnect of idle IP */
+   #endif
+ ***************
+ *** 1791,1793 ****
+ --- 1794,1803 ----
+       return int_option(*argv, &idle_time_limit);
+   }
+   #endif
+ + 
+ + static int setradius (argv)
+ +     char **argv;
+ + {
+ +     useradius = 1;
+ +     return radius_init(*argv);
+ + }
+ diff -r -c /usr/src/usr.sbin/pppd/pppd.h pppd/pppd.h
+ *** /usr/src/usr.sbin/pppd/pppd.h	Sun Aug 11 21:29:37 1996
+ --- pppd/pppd.h	Tue Aug 19 20:39:57 1997
+ ***************
+ *** 88,93 ****
+ --- 88,94 ----
+   extern int	disable_defaultip; /* Don't use hostname for default IP adrs */
+   extern char	*ipparam;	/* Extra parameter for ip up/down scripts */
+   extern int	cryptpap;	/* Others' PAP passwords are encrypted */
+ + extern int	useradius;	/* Using RADIUS for authentication */
+   
+   /*
+    * Values for phase.
+ Only in pppd: pppdradius.c
+ Only in pppd: pppdradius.h
+ Only in pppd: radius.h
diff -r -P -d -C 3 ppp-2.3.5/pppd/radius.h ppp-2.3.5-2cbcps-radius-multiport/pppd/radius.h
*** ppp-2.3.5/pppd/radius.h	Thu Jan  1 05:00:00 1970
--- ppp-2.3.5-2cbcps-radius-multiport/pppd/radius.h	Sun Jan 24 14:36:50 1999
***************
*** 0 ****
--- 1,329 ----
+ 
+ #define	COMMENT			'#'	/* comment char for config files */
+ 
+ #define AUTH_VECTOR_LEN		16
+ #define AUTH_PASS_LEN		16
+ #define AUTH_ID_LEN		64
+ #define AUTH_STRING_LEN		128	/* maximum of 253 */
+ 
+ #define FILTER_LEN		16
+ #define NAME_LENGTH		32
+ 
+ #define AUTH_HDR_LEN			20
+ #define MAX_SECRET_LENGTH		16
+ #define CHAP_VALUE_LENGTH		16
+ 
+ #define PW_AUTH_UDP_PORT		1645
+ #define PW_ACCT_UDP_PORT		1646
+ 
+ #define PW_TYPE_STRING			0
+ #define PW_TYPE_INTEGER			1
+ #define PW_TYPE_IPADDR			2
+ #define PW_TYPE_DATE			3
+ 
+ /* standard RADIUS codes */
+ 
+ #define	PW_ACCESS_REQUEST		1
+ #define	PW_ACCESS_ACCEPT		2
+ #define	PW_ACCESS_REJECT		3
+ #define	PW_ACCOUNTING_REQUEST		4
+ #define	PW_ACCOUNTING_RESPONSE		5
+ #define	PW_ACCOUNTING_STATUS		6
+ #define	PW_PASSWORD_REQUEST		7
+ #define	PW_PASSWORD_ACK			8
+ #define	PW_PASSWORD_REJECT		9
+ #define	PW_ACCOUNTING_MESSAGE		10
+ #define	PW_ACCESS_CHALLENGE		11
+ #define	PW_STATUS_SERVER		12
+ #define	PW_STATUS_CLIENT		13
+ 
+ 
+ /* standard RADIUS attribute-value pairs */
+ 
+ #define	PW_USER_NAME			1	/* string */
+ #define	PW_USER_PASSWORD		2	/* string */
+ #define	PW_CHAP_PASSWORD		3	/* string */
+ #define	PW_NAS_IP_ADDRESS		4	/* ipaddr */
+ #define	PW_NAS_PORT			5	/* integer */
+ #define	PW_SERVICE_TYPE			6	/* integer */
+ #define	PW_FRAMED_PROTOCOL		7	/* integer */
+ #define	PW_FRAMED_IP_ADDRESS		8	/* ipaddr */
+ #define	PW_FRAMED_IP_NETMASK		9	/* ipaddr */
+ #define	PW_FRAMED_ROUTING		10	/* integer */
+ #define	PW_FILTER_ID		        11	/* string */
+ #define	PW_FRAMED_MTU			12	/* integer */
+ #define	PW_FRAMED_COMPRESSION		13	/* integer */
+ #define	PW_LOGIN_IP_HOST		14	/* ipaddr */
+ #define	PW_LOGIN_SERVICE		15	/* integer */
+ #define	PW_LOGIN_PORT			16	/* integer */
+ #define	PW_OLD_PASSWORD			17	/* string */ /* deprecated */
+ #define	PW_REPLY_MESSAGE		18	/* string */
+ #define	PW_LOGIN_CALLBACK_NUMBER	19	/* string */
+ #define	PW_FRAMED_CALLBACK_ID		20	/* string */
+ #define	PW_EXPIRATION			21	/* date */ /* deprecated */
+ #define	PW_FRAMED_ROUTE			22	/* string */
+ #define	PW_FRAMED_IPX_NETWORK		23	/* integer */
+ #define	PW_STATE			24	/* string */
+ #define	PW_CLASS			25	/* string */
+ #define	PW_VENDOR_SPECIFIC		26	/* string */
+ #define	PW_SESSION_TIMEOUT		27	/* integer */
+ #define	PW_IDLE_TIMEOUT			28	/* integer */
+ #define	PW_TERMINATION_ACTION		29	/* integer */
+ #define	PW_CALLED_STATION_ID		30	/* string */
+ #define	PW_CALLING_STATION_ID		31	/* string */
+ #define	PW_NAS_IDENTIFIER		32	/* string */
+ #define	PW_PROXY_STATE			33	/* string */
+ #define	PW_LOGIN_LAT_SERVICE		34	/* string */
+ #define	PW_LOGIN_LAT_NODE		35	/* string */
+ #define	PW_LOGIN_LAT_GROUP		36	/* string */
+ #define	PW_FRAMED_APPLETALK_LINK	37	/* integer */
+ #define	PW_FRAMED_APPLETALK_NETWORK	38	/* integer */
+ #define	PW_FRAMED_APPLETALK_ZONE	39	/* string */
+ #define	PW_CHAP_CHALLENGE		60	/* string */
+ #define	PW_NAS_PORT_TYPE		61	/* integer */
+ #define	PW_PORT_LIMIT			62	/* integer */
+ 
+ /*	Accounting */
+ 
+ #define	PW_ACCT_STATUS_TYPE		40	/* integer */
+ #define	PW_ACCT_DELAY_TIME		41	/* integer */
+ #define	PW_ACCT_INPUT_OCTETS		42	/* integer */ /* not impl. */
+ #define	PW_ACCT_OUTPUT_OCTETS		43	/* integer */ /* not impl. */
+ #define	PW_ACCT_SESSION_ID		44	/* string */
+ #define	PW_ACCT_AUTHENTIC		45	/* integer */
+ #define	PW_ACCT_SESSION_TIME		46	/* integer */
+ #define	PW_ACCT_INPUT_PACKETS		47	/* integer */ /* not impl. */
+ #define	PW_ACCT_OUTPUT_PACKETS		48	/* integer */ /* not impl. */
+ #define	PW_ACCT_TERMINATE_CAUSE		49	/* integer */
+ 
+ /*	Merit Experimental Extensions */
+ 
+ #define	PW_AVAILABLE_TIME		209	/* integer */
+ #define	PW_INFO_PORT			210	/* integer */
+ #define	PW_PROXY_ACTION			211	/* string */
+ #define	PW_SIGNATURE			212	/* string */
+ #define	PW_TOKEN			213	/* string */
+ #define	PW_ACCT_RATE			214	/* string */
+ #define	PW_ACCT_CHARGE			215	/* string */
+ #define	PW_ACCT_TRANSACTION_ID		216	/* string */
+ #define	PW_ACCT_CHARGE_ALLOWED		217	/* string */
+ #define	PW_MAXIMUM_TIME			218	/* integer */
+ /* #define unavailable due to collision	219	*/ /* ??????? */
+ #define	PW_TIME_USED			220	/* integer */
+ #define	PW_HUNTGROUP_NAME		221	/* string */
+ #define	PW_USER_ID			222	/* string */
+ #define	PW_USER_REALM			223	/* string */
+ 
+ /*	Configuration Only Attributes (for check-items) */
+ 
+ #define	CI_COMMENT			1024	/* string */
+ #define	CI_XVALUE			1025	/* integer */
+ #define	CI_XSTRING			1026	/* string */
+ #define	CI_AUTHENTICATION_TYPE		1027	/* integer */
+ #define	CI_PROHIBIT			1028	/* integer */
+ #define	CI_USER_CATEGORY		1029	/* string */
+ #define	CI_GROUP_NAME			1030	/* string */
+ #define	CI_ENCRYPTED_PASSWORD		1031	/* string */
+ #define	CI_EXPIRATION			1032	/* date */
+ #define	CI_USER_PASSWORD		1033	/* string */
+ #define	CI_SIMULTANEOUS_USE		1034	/* integer */
+ #define	CI_SERVER_NAME			1035	/* string */
+ 
+ /*	Integer Translations */
+ 
+ /*	SERVICE TYPES	*/
+ 
+ #define	PW_LOGIN			1
+ #define	PW_FRAMED			2
+ #define	PW_CALLBACK_LOGIN		3
+ #define	PW_CALLBACK_FRAMED		4
+ #define	PW_OUTBOUND_USER		5
+ #define	PW_ADMINISTRATIVE_USER		6
+ #define	PW_SHELL_USER			7
+ #define PW_AUTHENTICATE_ONLY		8
+ #define PW_CALLBACK_ADMIN_USER		9
+ 
+ /*	FRAMED PROTOCOLS	*/
+ 
+ #define	PW_PPP				1
+ #define	PW_SLIP				2
+ 
+ /*	FRAMED ROUTING VALUES	*/
+ 
+ #define	PW_NONE				0
+ #define	PW_BROADCAST			1
+ #define	PW_LISTEN			2
+ #define	PW_BROADCAST_LISTEN		3
+ 
+ /*	FRAMED COMPRESSION TYPES	*/
+ 
+ #define	PW_VAN_JACOBSON_TCP_IP		1
+ #define	PW_IPX_HEADER_COMPRESSION	2
+ 
+ /*	LOGIN SERVICES	*/
+ 
+ #define	PW_TELNET			0
+ #define	PW_RLOGIN			1
+ #define	PW_TCP_CLEAR			2
+ #define	PW_PORTMASTER			3
+ #define	PW_LAT				4
+ 
+ /*	TERMINATION ACTIONS	*/
+ 
+ #define	PW_DEFAULT			0
+ #define	PW_RADIUS_REQUEST		1
+ 
+ /*	AUTHENTICATION TYPES */
+ 
+ #define AA_NONE		0	/* This is not a valid user id entry */
+ #define AA_UNIX		1	/* Use local Unix password file */
+ #define AA_AKRB		2	/* AFS Kerberos type authentication */
+ #define AA_MKRB		3	/* MIT Kerberos type authentication */
+ #define AA_RAD		4	/* Pass to remote RADIUS server */
+ #define AA_MNET		5	/* Do Merit specific authentication */
+ #define AA_KCHAP	6	/* Kerberos CHAP authentication */
+ #define AA_TACACS	7	/* Encrypted TACACS authentication */
+ #define AA_REALM	8	/* Find given realm in authfile */
+ #define AA_LOCAL	9
+ #define AA_FILE		10	/* ID/PW list in a file */
+ 
+ #define PW_AUTH_MAX	10	/* Highest authentication type */
+ 
+ /*	PROHIBIT PROTOCOL  */
+ 
+ #define PW_DUMB		0	/* 1 and 2 are defined in FRAMED PROTOCOLS */
+ #define PW_AUTH_ONLY	3
+ #define PW_ALL		255
+ 
+ /*	ACCOUNTING STATUS TYPES    */
+ 
+ #define PW_STATUS_START		1
+ #define PW_STATUS_STOP		2
+ #define PW_STATUS_ALIVE		3
+ #define PW_STATUS_MODEM_START	4
+ #define PW_STATUS_MODEM_STOP	5
+ #define PW_STATUS_CANCEL	6
+ #define PW_ACCOUNTING_ON	7
+ #define PW_ACCOUNTING_OFF	8
+ 
+ /*	ACCOUNTING TERMINATION CAUSES    */
+ 
+ #define PW_USER_REQUEST		1
+ #define PW_LOST_CARRIER		2
+ #define PW_LOST_SERVICE		3
+ #define PW_ACCT_IDLE_TIMEOUT	4
+ #define PW_ACCT_SESSION_TIMEOUT	5
+ #define PW_ADMIN_RESET		6
+ #define PW_ADMIN_REBOOT		7
+ #define PW_PORT_ERROR		8
+ #define PW_NAS_ERROR		9
+ #define PW_NAS_REQUEST		10
+ #define PW_NAS_REBOOT		11
+ #define PW_PORT_UNNEEDED	12
+ #define PW_PORT_PREEMPTED	13
+ #define PW_PORT_SUSPENDED	14
+ #define PW_SERVICE_UNAVAILABLE	15
+ #define PW_CALLBACK		16
+ 
+ /*	NAS PORT TYPES    */
+ 
+ #define PW_ASYNC		0
+ #define PW_SYNC			1
+ #define PW_ISDN_SYNC		2
+ #define PW_ISDN_SYNC_V120	3
+ #define PW_ISDN_SYNC_V110	4
+ 
+ /* Default Database File Names */
+ 
+ #ifndef RADIUS_DIR
+ #define RADIUS_DIR		"/usr/local/etc/raddb"
+ #endif
+ 
+ #ifndef RADACCT_DIR
+ #define RADACCT_DIR		"/usr/local/etc/radacct"
+ #endif
+ 
+ /*
+  *	Note:	To change where these files go, do not change the #defines
+  *		below, instead change the RADIUS_DIR #define above.
+  */
+ 
+ #define RADIUS_DICTIONARY	"dictionary"
+ #define RADIUS_CLIENTS		"clients"
+ #define RADIUS_USERS		"users"
+ #define RADIUS_HOLD		"holdusers"
+ #define RADIUS_LOG		"logfile"
+ #define RADIUS_AUTH		"authfile"
+ #define RADIUS_PID		"radiusd.pid"
+ #define RADIUS_FSM		"radius.fsm"
+ #define RADIUS_DEBUG		"radius.debug"
+ 
+ #ifndef RADIUS_COMPRESS
+ #define RADIUS_COMPRESS		"/usr/ucb/compress"  /* might be gzip, etc. */
+ #endif
+ 
+ #ifndef RADIUS_LOCALSERVER
+ #define RADIUS_LOCALSERVER	"localserver"
+ #endif
+ 
+ #ifndef DEFAULT_REALM
+ #define DEFAULT_REALM		"DEFAULT"
+ #endif
+ 
+ #ifndef NULL_REALM
+ #define NULL_REALM		"NULL"
+ #endif
+ 
+ 
+ /******************************************************************
+  *
+  *      PW_PROTTYPE & PW_PROTTYPES - define authentication protocol allowed
+  *                                   for particular realm entry in authfile.
+  *
+  *      The PW_PROTTYPE value is stored in the auth_ent.prot field.
+  *      The PW_PROTTYPE value corresponds to the order of PW_PROTTYPES.
+  *
+  *****************************************************************/
+ 
+ #define PW_PROTTYPE_DFLT	0	/* Use this entry for any protocol */
+ #define PW_PROTTYPE_CHAP	1	/* Entry is for CHAP style authent. */
+ #define PW_PROTTYPE_PW		2	/* Entry is for id/pw style authent. */
+ 
+ #define PW_PROTTYPES_DFLT	"DEFAULT"
+ #define PW_PROTTYPES_CHAP	"CHAP"
+ #define PW_PROTTYPES_PW		"PW"
+ 
+ #ifndef	LOG_CONS
+ #define	LOG_DAEMON		0
+ #define	LOG_AUTH		0
+ #endif
+ 
+ #define	MGMT_POLL_SECRET	"Hardlyasecret"
+ #define	MAX_REQUESTS		128
+ #define	MAX_REQUEST_TIME	30	/* Lifetime of a request */
+ #define	CLEANUP_DELAY		5	/* Hold onto old requests this long */
+ #define	DEFAULT_INETD_TIMEOUT	15	/* Fifteen minutes by default */
+ #define	DEFAULT_TIMER_VALUE	3	/* Three seconds by default */
+ #define	ADDRESS_AGING		60*60	/* One hour by default */
+ #define	DFLT_TACACS_UDP_PORT	49	/* Default TACACS server port */
+ #define	SESS_ID_LEN		8	/* session id length */
+ #define SECONDS_PER_DAY		86400
+ #define TRUNCATION_DAY		7   /* Sunday is zero (0), daily is seven (7) */
+ 
+ #ifndef PROTO
+ #ifdef __STDC__
+ #define PROTO(x) x
+ #else
+ #define PROTO(x) ()
+ #undef const
+ #endif /* !__STDC__ */
+ #endif /* !PROTO */
+ 
+ /*	Define event structure (for events generated by AATV action functions */
+ 
+ 
+ #define	AA_DIRECT	0	/* Function gives direct reply */
+ #define	AA_SOCKET	1	/* Deferred reply returned on socket */
+ #define	AA_FORK		2	/* Spawn a process to wait for reply */
+ #define	AA_FREPLY	3	/* Fork & get reply on server socket */
+ 
diff -r -P -d -C 3 ppp-2.3.5/pppd/sys-linux.c ppp-2.3.5-2cbcps-radius-multiport/pppd/sys-linux.c
*** ppp-2.3.5/pppd/sys-linux.c	Mon May  4 12:45:00 1998
--- ppp-2.3.5-2cbcps-radius-multiport/pppd/sys-linux.c	Sun Jan 24 14:36:50 1999
***************
*** 19,24 ****
--- 19,25 ----
   */
  
  #include <sys/ioctl.h>
+ #include <asm/types.h>
  #include <sys/types.h>
  #include <sys/socket.h>
  #include <sys/time.h>
***************
*** 64,70 ****
  #include <netinet/in.h>
  #include <arpa/inet.h>
  
! #include <linux/types.h>
  #include <linux/ppp_defs.h>
  #include <linux/if_ppp.h>
  
--- 65,71 ----
  #include <netinet/in.h>
  #include <arpa/inet.h>
  
! /*#include <linux/types.h>*/
  #include <linux/ppp_defs.h>
  #include <linux/if_ppp.h>
  
***************
*** 596,601 ****
--- 597,608 ----
  #endif
  #ifdef EXTB
      { 38400, EXTB },
+ #endif
+ #ifdef B230400
+     { 230400, B230400 },
+ #endif
+ #ifdef B460800
+     { 460800, B460800 },
  #endif
  #ifdef B230400
      { 230400, B230400 },
diff -r -P -d -C 3 ppp-2.3.5/pppd/testchap.c ppp-2.3.5-2cbcps-radius-multiport/pppd/testchap.c
*** ppp-2.3.5/pppd/testchap.c	Thu Jan  1 05:00:00 1970
--- ppp-2.3.5-2cbcps-radius-multiport/pppd/testchap.c	Sun Jan 24 14:36:49 1999
***************
*** 0 ****
--- 1,41 ----
+ #include <stdio.h>
+ 
+ #include "pppd.h"
+ #include "chap.h"
+ #include "chap_ms.h"
+ 
+ int main(argc, argv)
+     int     argc;
+     char    *argv[];
+ {
+     u_char          challenge[8];
+     int             challengeInt[sizeof(challenge)];
+     chap_state      cstate;
+     int             i;
+ 
+     if (argc != 3) {
+         fprintf(stderr, "Usage: %s <16-hexchar challenge> <password>\n",
+         argv[0]); exit(1);
+     }
+ 
+     sscanf(argv[1], "%2x%2x%2x%2x%2x%2x%2x%2x",
+            challengeInt + 0, challengeInt + 1, challengeInt + 2,
+            challengeInt + 3, challengeInt + 4, challengeInt + 5,
+            challengeInt + 6, challengeInt + 7);
+ 
+     for (i = 0; i < sizeof(challenge); i++)
+         challenge[i] = (u_char)challengeInt[i];
+ 
+     ChapMS(&cstate, challenge, sizeof(challenge), argv[2], strlen(argv[2]));
+     printf("Response length is %d, response is:", cstate.resp_length);
+ 
+     for (i = 0; i < cstate.resp_length; i++) {
+         if (i % 8 == 0)
+             putchar('\n');
+         printf("%02X ", (unsigned int)cstate.response[i]);
+     }
+ 
+     putchar('\n');
+ 
+     exit(0);
+ }
diff -r -P -d -C 3 ppp-2.3.5/pppd/upap.c ppp-2.3.5-2cbcps-radius-multiport/pppd/upap.c
*** ppp-2.3.5/pppd/upap.c	Wed Apr 30 11:59:56 1997
--- ppp-2.3.5-2cbcps-radius-multiport/pppd/upap.c	Sun Jan 24 14:36:49 1999
***************
*** 44,49 ****
--- 44,50 ----
  static void upap_protrej __P((int));
  static int  upap_printpkt __P((u_char *, int,
  			       void (*) __P((void *, char *, ...)), void *));
+ extern int cbcp_volit;
  
  struct protent pap_protent = {
      PPP_PAP,
***************
*** 389,394 ****
--- 390,396 ----
      if (retcode == UPAP_AUTHACK) {
  	u->us_serverstate = UPAPSS_OPEN;
  	auth_peer_success(u->us_unit, PPP_PAP, ruser, ruserlen);
+         syslog(LOG_ERR,"upap: user is %s, volit=%d\n",user,cbcp_volit);
      } else {
  	u->us_serverstate = UPAPSS_BADAUTH;
  	auth_peer_fail(u->us_unit, PPP_PAP);

