From: Paul Mackerras Date: Wed, 30 Apr 1997 05:37:27 +0000 (+0000) Subject: readme for call-back control protocol X-Git-Tag: RELEASE_2_3_6~236 X-Git-Url: https://git.ozlabs.org/?p=ppp.git;a=commitdiff_plain;h=911994aea6822d1e994e554abef9fefe7e141f51;ds=sidebyside readme for call-back control protocol --- diff --git a/README.cbcp b/README.cbcp new file mode 100644 index 0000000..8521021 --- /dev/null +++ b/README.cbcp @@ -0,0 +1,1515 @@ + Microsoft Call Back Configuration Protocol. + by Pedro Roque Marques + +The CBCP is a method by which the Microsoft Windows NT Server may +implement additional security. It is possible to configure the server +in such a manner so as to require that the client systems which +connect with it are required that following a valid authentication to +leave a method by which the number may be returned call. + +It is a requirement of servers so configured that the protocol be +exchanged. + +So, this set of patches may be applied to the pppd process to enable +the cbcp client *only* portion of the specification. It is primarily +meant to permit connection with Windows NT Servers. + +The ietf-working specification may be obtained from ftp.microsoft.com +in the developr/rfc directory. + +The ietf task group has decided to recommend that the LCP sequence be +extended to permit the callback operation. For this reason, these +patches are not 'part' of pppd but are an adjunct to the code. I +hopefully have included enough of the context to permit the patch +program so that minor changes to the program should not effect the +patch by more than a few lines in the 'fuzz' factor. + + + +diff -r --unified=10 ppp-2.2a5.orig/linux/ppp_defs.h ppp-2.2a5/linux/ppp_defs.h +--- ppp-2.2a5.orig/linux/ppp_defs.h Sat May 13 12:38:19 1995 ++++ ppp-2.2a5/linux/ppp_defs.h Sat May 13 13:46:36 1995 +@@ -56,20 +56,21 @@ + #define PPP_IP 0x21 /* Internet Protocol */ + #define PPP_VJC_COMP 0x2d /* VJ compressed TCP */ + #define PPP_VJC_UNCOMP 0x2f /* VJ uncompressed TCP */ + #define PPP_COMP 0xfd /* compressed packet */ + #define PPP_IPCP 0x8021 /* IP Control Protocol */ + #define PPP_CCP 0x80fd /* Compression Control Protocol */ + #define PPP_LCP 0xc021 /* Link Control Protocol */ + #define PPP_PAP 0xc023 /* Password Authentication Protocol */ + #define PPP_LQR 0xc025 /* Link Quality Report protocol */ + #define PPP_CHAP 0xc223 /* Cryptographic Handshake Auth. Protocol */ ++#define PPP_CBCP 0xc029 /* Callback Control Protocol */ + + /* + * Values for FCS calculations. + */ + #define PPP_INITFCS 0xffff /* Initial FCS value */ + #define PPP_GOODFCS 0xf0b8 /* Good final FCS value */ + #define PPP_FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff]) + + /* + * A 32-bit unsigned integral type. +diff -r --unified=10 ppp-2.2a5.orig/net/ppp_defs.h ppp-2.2a5/net/ppp_defs.h +--- ppp-2.2a5.orig/net/ppp_defs.h Sat May 13 12:38:19 1995 ++++ ppp-2.2a5/net/ppp_defs.h Sat May 13 13:57:14 1995 +@@ -56,20 +56,21 @@ + #define PPP_IP 0x21 /* Internet Protocol */ + #define PPP_VJC_COMP 0x2d /* VJ compressed TCP */ + #define PPP_VJC_UNCOMP 0x2f /* VJ uncompressed TCP */ + #define PPP_COMP 0xfd /* compressed packet */ + #define PPP_IPCP 0x8021 /* IP Control Protocol */ + #define PPP_CCP 0x80fd /* Compression Control Protocol */ + #define PPP_LCP 0xc021 /* Link Control Protocol */ + #define PPP_PAP 0xc023 /* Password Authentication Protocol */ + #define PPP_LQR 0xc025 /* Link Quality Report protocol */ + #define PPP_CHAP 0xc223 /* Cryptographic Handshake Auth. Protocol */ ++#define PPP_CBCP 0xc029 /* Callback Control Protocol */ + + /* + * Values for FCS calculations. + */ + #define PPP_INITFCS 0xffff /* Initial FCS value */ + #define PPP_GOODFCS 0xf0b8 /* Good final FCS value */ + #define PPP_FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff]) + + /* + * A 32-bit unsigned integral type. +diff -r --unified=10 ppp-2.2a5.orig/pppd/Makefile.aix4 ppp-2.2a5/pppd/Makefile.aix4 +--- ppp-2.2a5.orig/pppd/Makefile.aix4 Sat May 13 12:38:20 1995 ++++ ppp-2.2a5/pppd/Makefile.aix4 Sat May 13 14:09:17 1995 +@@ -3,26 +3,26 @@ + # $Id: README.cbcp,v 1.1 1997/04/30 05:37:27 paulus Exp $ + # + #ifndef BINDIR + BINDIR = /usr/sbin + #endif + #ifndef MANDIR + MANDIR = /usr/man + #ENDIF + + PPPDSRCS = main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c \ +- auth.c options.c sys-bsd.c sys-str.c sys-aix4.c ccp.c +-HEADERS = callout.h pathnames.h patchlevel.h chap.h md5.h ++ auth.c options.c sys-bsd.c sys-str.c sys-aix4.c ccp.c cbcp.c ++HEADERS = callout.h pathnames.h patchlevel.h chap.h md5.h cbc.h + MANPAGES = pppd.8 + + PPPDOBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o \ +- auth.o options.o sys-aix4.o ccp.o ++ auth.o options.o sys-aix4.o ccp.o cbcp.o + + CC = xlc + DEBUG_FLAGS = -DDEBUGALL + # SECURE_FLAGS = -DREQ_SYSOPTIONS=1 + COMPILE_FLAGS = -DSTREAMS + COPTS = -O + LIBS= -bI:/lib/pse.exp + LOCK_PREFIX=\"/var/locks/LCK..\" + + CFLAGS = -I.. $(COPTS) $(DEBUG_FLAGS) $(COMPILE_FLAGS) $(SECURE_FLAGS) +diff -r --unified=10 ppp-2.2a5.orig/pppd/Makefile.bsd ppp-2.2a5/pppd/Makefile.bsd +--- ppp-2.2a5.orig/pppd/Makefile.bsd Sat May 13 12:38:20 1995 ++++ ppp-2.2a5/pppd/Makefile.bsd Sat May 13 14:09:36 1995 +@@ -1,18 +1,18 @@ + # $Id: README.cbcp,v 1.1 1997/04/30 05:37:27 paulus Exp $ + + BINDIR?= /usr/sbin + CFLAGS+= -I.. -DHAVE_PATHS_H + + PROG= pppd + SRCS= main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c ccp.c \ +- auth.c options.c sys-bsd.c ++ auth.c options.c sys-bsd.c cbcp.c + MAN8= pppd.0 + # The next line is for NetBSD-current systems. + MAN= pppd.cat8 + BINMODE=4555 + BINOWN= root + + LDADD= -lcrypt -lutil + DPADD= ${LIBCRYPT} ${LIBUTIL} + + .include +diff -r --unified=10 ppp-2.2a5.orig/pppd/Makefile.linux ppp-2.2a5/pppd/Makefile.linux +--- ppp-2.2a5.orig/pppd/Makefile.linux Sat May 13 12:38:20 1995 ++++ ppp-2.2a5/pppd/Makefile.linux Sat May 13 13:46:36 1995 +@@ -1,25 +1,25 @@ + # + # pppd makefile for Linux + # $Id: README.cbcp,v 1.1 1997/04/30 05:37:27 paulus Exp $ + # + + BINDIR = /usr/etc + MANDIR = /usr/man + + PPPDSRCS = main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c ccp.c \ +- auth.c options.c sys-linux.c +-HEADERS = callout.h pathnames.h patchlevel.h chap.h md5.h ++ auth.c options.c sys-linux.c cbcp.c ++HEADERS = callout.h pathnames.h patchlevel.h chap.h md5.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 sys-linux.o ++ auth.o options.o sys-linux.o cbcp.o + + all: pppd + + # + # include dependancies if present and backup if as a header file + ifeq (.depend,$(wildcard .depend)) + include .depend + HEADERS := $(HEADERS) .depend + endif + +diff -r --unified=10 ppp-2.2a5.orig/pppd/Makefile.osf ppp-2.2a5/pppd/Makefile.osf +--- ppp-2.2a5.orig/pppd/Makefile.osf Sat May 13 12:38:20 1995 ++++ ppp-2.2a5/pppd/Makefile.osf Sat May 13 14:09:54 1995 +@@ -1,26 +1,26 @@ + # + # pppd makefile for OSF/1 on DEC Alpha + # $Id: README.cbcp,v 1.1 1997/04/30 05:37:27 paulus Exp $ + # + + BINDIR = /usr/local/etc + 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 sys-bsd.c sys-str.c sys-ultrix.c sys-linux.c \ +- sys-osf.c +-HEADERS = callout.h pathnames.h patchlevel.h chap.h md5.h ++ sys-osf.c cbcp.c ++HEADERS = callout.h pathnames.h patchlevel.h chap.h md5.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 sys-osf.o ++ auth.o options.o sys-osf.o cbcp.o + + CC = cc + DEBUG_FLAGS = -DDEBUGALL + COMPILE_FLAGS = -DSTREAMS -DGIDSET_TYPE=int + COPTS = -O2 + LIBS = + + CFLAGS = -I.. $(COPTS) $(COMPILE_FLAGS) + + SOURCE= RELNOTES Makefile \ +diff -r --unified=10 ppp-2.2a5.orig/pppd/Makefile.sol2 ppp-2.2a5/pppd/Makefile.sol2 +--- ppp-2.2a5.orig/pppd/Makefile.sol2 Sat May 13 12:38:20 1995 ++++ ppp-2.2a5/pppd/Makefile.sol2 Sat May 13 14:10:09 1995 +@@ -6,21 +6,21 @@ + BINDIR = /usr/local/etc + MANDIR = /usr/local/man + + CC = gcc + COPTS = -g -O2 + CFLAGS = $(COPTS) -I.. + + INSTALL = /usr/sbin/install + + OBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o \ +- auth.o options.o sys-sol2.o ++ auth.o options.o sys-sol2.o cbcp.o + + pppd: $(OBJS) + $(CC) -o pppd $(OBJS) -lnsl + + install: + $(INSTALL) -f $(BINDIR) -m 4755 -u root pppd + $(INSTALL) -f $(MANDIR)/man8 pppd.8 + + clean: + rm -f $(OBJS) pppd *~ core +diff -r --unified=10 ppp-2.2a5.orig/pppd/Makefile.sun ppp-2.2a5/pppd/Makefile.sun +--- ppp-2.2a5.orig/pppd/Makefile.sun Sat May 13 12:38:20 1995 ++++ ppp-2.2a5/pppd/Makefile.sun Sat May 13 14:10:27 1995 +@@ -2,26 +2,26 @@ + # pppd makefile for Suns + # $Id: README.cbcp,v 1.1 1997/04/30 05:37:27 paulus Exp $ + # + + BINDIR = /usr/local/etc + MANDIR = /usr/local/man + + INSTALL= install -o root -g daemon + + PPPDSRCS = main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c ccp.c \ +- auth.c options.c sys-bsd.c sys-str.c sys-ultrix.c sys-linux.c +-HEADERS = callout.h pathnames.h patchlevel.h chap.h md5.h ++ auth.c options.c sys-bsd.c sys-str.c sys-ultrix.c sys-linux.c cbcp.c ++HEADERS = callout.h pathnames.h patchlevel.h chap.h md5.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 sys-str.o ++ auth.o options.o sys-str.o cbcp.o + + # CC = gcc + DEBUG_FLAGS = + COMPILE_FLAGS = + COPTS = -O + LIBS = -lkvm + + CFLAGS = -I.. $(COPTS) $(DEBUG_FLAGS) $(COMPILE_FLAGS) + + SOURCE= RELNOTES Makefile \ +diff -r --unified=10 ppp-2.2a5.orig/pppd/Makefile.ultrix ppp-2.2a5/pppd/Makefile.ultrix +--- ppp-2.2a5.orig/pppd/Makefile.ultrix Sat May 13 12:38:20 1995 ++++ ppp-2.2a5/pppd/Makefile.ultrix Sat May 13 14:10:44 1995 +@@ -1,25 +1,25 @@ + # + # pppd makefile for Ultrix + # $Id: README.cbcp,v 1.1 1997/04/30 05:37:27 paulus Exp $ + # + + BINDIR = /usr/local/etc + 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 sys-bsd.c sys-str.c sys-ultrix.c sys-linux.c +-HEADERS = callout.h pathnames.h patchlevel.h chap.h md5.h ++ auth.c options.c sys-bsd.c sys-str.c sys-ultrix.c sys-linux.c cbcp.c ++HEADERS = callout.h pathnames.h patchlevel.h chap.h md5.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 sys-ultrix.o ++ auth.o options.o sys-ultrix.o cbcp.o + + # CC = gcc + DEBUG_FLAGS = + COMPILE_FLAGS = -DNO_DRAND48 -DGIDSET_TYPE=int + COPTS = -O + LIBS = + + CFLAGS = -I.. $(COPTS) $(DEBUG_FLAGS) $(COMPILE_FLAGS) + + SOURCE= RELNOTES Makefile \ +diff -r --unified=10 ppp-2.2a5.orig/pppd/auth.c ppp-2.2a5/pppd/auth.c +--- ppp-2.2a5.orig/pppd/auth.c Sat May 13 12:38:20 1995 ++++ ppp-2.2a5/pppd/auth.c Sat May 13 13:46:36 1995 +@@ -55,20 +55,21 @@ + #ifndef PW_PPP + #define PW_PPP PW_LOGIN + #endif + #endif + + #include "pppd.h" + #include "fsm.h" + #include "lcp.h" + #include "upap.h" + #include "chap.h" ++#include "cbcp.h" + #include "ipcp.h" + #include "ccp.h" + #include "pathnames.h" + + #ifdef sparc + #include + #endif /*sparc*/ + + /* Used for storing a sequence of words. Usually malloced. */ + struct wordlist { +@@ -93,20 +94,21 @@ + /* Bits in auth_pending[] */ + #define UPAP_WITHPEER 1 + #define UPAP_PEER 2 + #define CHAP_WITHPEER 4 + #define CHAP_PEER 8 + + /* Prototypes */ + void check_access __P((FILE *, char *)); + + static void network_phase __P((int)); ++static void callback_phase __P((int)); + static int login __P((char *, char *, char **, int *)); + static void logout __P((void)); + static int null_login __P((int)); + static int get_upap_passwd __P((void)); + static int have_upap_secret __P((void)); + static int have_chap_secret __P((char *, char *)); + static int scan_authfile __P((FILE *, char *, char *, char *, + struct wordlist **, char *)); + static void free_wordlist __P((struct wordlist *)); + +@@ -140,20 +142,21 @@ + + /* + * LCP has gone down; it will either die or try to re-establish. + */ + void + link_down(unit) + int unit; + { + ipcp_close(0); + ccp_close(0); ++ cbcp_close(0); + phase = PHASE_TERMINATE; + } + + /* + * The link is established. + * Proceed to the Dead, Authenticate or Network phase as appropriate. + */ + void + link_established(unit) + int unit; +@@ -189,36 +192,53 @@ + if (ho->neg_chap) { + ChapAuthWithPeer(unit, our_name, ho->chap_mdtype); + auth |= CHAP_WITHPEER; + } else if (ho->neg_upap) { + upap_authwithpeer(unit, user, passwd); + auth |= UPAP_WITHPEER; + } + auth_pending[unit] = auth; + + if (!auth) +- network_phase(unit); ++ callback_phase(unit); + } + + /* + * Proceed to the network phase. + */ + static void + network_phase(unit) + int unit; + { + phase = PHASE_NETWORK; + ipcp_open(unit); + ccp_open(unit); + } + + /* ++ * Proceed to the callback phase which may be empty. ++ */ ++static void ++callback_phase(unit) ++ int unit; ++{ ++ lcp_options *wo = &lcp_wantoptions[unit]; ++ ++ if (!wo->neg_cbcp) ++ network_phase(unit); ++ else { ++ phase = PHASE_CALLBACK; ++ cbcp_open(unit); ++ } ++} ++ ++/* + * The peer has failed to authenticate himself using `protocol'. + */ + void + auth_peer_fail(unit, protocol) + int unit, protocol; + { + /* + * Authentication failure: take the link down + */ + lcp_close(unit); +@@ -242,27 +262,24 @@ + bit = UPAP_PEER; + break; + default: + syslog(LOG_WARNING, "auth_peer_success: unknown protocol %x", + protocol); + return; + } + + /* + * If there is no more authentication still to be done, +- * proceed to the network phase. ++ * go to the next phase. + */ +- if ((auth_pending[unit] &= ~bit) == 0) { +- phase = PHASE_NETWORK; +- ipcp_open(unit); +- ccp_open(unit); +- } ++ if ((auth_pending[unit] &= ~bit) == 0) ++ callback_phase(unit); + } + + /* + * We have failed to authenticate ourselves to the peer using `protocol'. + */ + void + auth_withpeer_fail(unit, protocol) + int unit, protocol; + { + /* +@@ -291,22 +308,23 @@ + default: + syslog(LOG_WARNING, "auth_peer_success: unknown protocol %x", + protocol); + bit = 0; + } + + /* + * If there is no more authentication still being done, + * proceed to the network phase. + */ ++ + if ((auth_pending[unit] &= ~bit) == 0) +- network_phase(unit); ++ callback_phase(unit); + } + + + /* + * check_auth_options - called to check authentication options. + */ + void + check_auth_options() + { + lcp_options *wo = &lcp_wantoptions[0]; +@@ -335,21 +353,20 @@ + if (ao->neg_chap && !have_chap_secret(our_name, remote_name)) + ao->neg_chap = 0; + if (wo->neg_chap && !have_chap_secret(remote_name, our_name)) + wo->neg_chap = 0; + + if (auth_required && !wo->neg_chap && !wo->neg_upap) { + fprintf(stderr, "\ + pppd: peer authentication required but no authentication files accessible\n"); + exit(1); + } +- + } + + + /* + * check_passwd - Check the user name and passwd against the PAP secrets + * file. If requested, also check against the system password database, + * and login the user if OK. + * + * returns: + * UPAP_AUTHNAK: Authentication failed. +diff -r --unified=10 ppp-2.2a5.orig/pppd/cbcp.c ppp-2.2a5/pppd/cbcp.c +--- ppp-2.2a5.orig/pppd/cbcp.c Sat May 13 14:08:45 1995 ++++ ppp-2.2a5/pppd/cbcp.c Sat May 13 14:15:12 1995 +@@ -0,0 +1,370 @@ ++/* ++ * cbcp - Call Back Configuration Protocol. ++ * ++ * Copyright (c) 1995 Pedro Roque Marques ++ * 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 Pedro Roque Marques. The name of the author 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: README.cbcp,v 1.1 1997/04/30 05:37:27 paulus Exp $"; ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "pppd.h" ++#include "cbcp.h" ++#include "fsm.h" ++#include "lcp.h" ++#include "ipcp.h" ++ ++cbcp_state cbcp[NUM_PPP]; ++ ++/* internal prototypes */ ++ ++void cbcp_recvreq(cbcp_state *us, char *pckt, int len); ++void cbcp_resp(cbcp_state *us); ++void cbcp_up(cbcp_state *us); ++void cbcp_recvack(cbcp_state *us, char *pckt, int len); ++void cbcp_send(cbcp_state *us, u_char code, u_char *buf, int len); ++ ++/* init state */ ++void cbcp_init(int iface) ++{ ++ cbcp_state *us; ++ ++ us = &cbcp[iface]; ++ memset(us, 0, sizeof(cbcp_state)); ++ us->us_unit = iface; ++ us->us_type |= (1 << CB_CONF_NO); ++} ++ ++/* lower layer is up */ ++void cbcp_lowerup(int iface) ++{ ++ cbcp_state *us = &cbcp[iface]; ++ ++ syslog(LOG_DEBUG, "cbcp_lowerup"); ++ syslog(LOG_DEBUG, "want: %d", us->us_type); ++ ++ if (us->us_type == CB_CONF_USER) ++ syslog(LOG_DEBUG, "phone no: %s", us->us_number); ++} ++ ++void cbcp_open(int unit) ++{ ++ syslog(LOG_DEBUG, "cbcp_open"); ++} ++ ++void cbcp_close(int unit) ++{ ++} ++ ++/* 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; ++ ++ if (pktlen < CBCP_MINLEN) { ++ syslog(LOG_ERR, "CBCP packet is too small"); ++ return; ++ } ++ ++ GETCHAR(code, inp); ++ GETCHAR(id, inp); ++ GETSHORT(len, inp); ++ ++#if 0 ++ if (len > pktlen) { ++ syslog(LOG_ERR, "CBCP packet: invalid length"); ++ return; ++ } ++#endif ++ ++ len -= CBCP_MINLEN; ++ ++ switch(code) { ++ case CBCP_REQ: ++ us->us_id = id; ++ cbcp_recvreq(us, inp, len); ++ break; ++ ++ case CBCP_RESP: ++ syslog(LOG_DEBUG, "CBCP_RESP received"); ++ break; ++ ++ case CBCP_ACK: ++ if (id != us->us_id) ++ syslog(LOG_DEBUG, "id doesn't match: expected %d recv %d", ++ us->us_id, id); ++ ++ cbcp_recvack(us, inp, len); ++ break; ++ ++ default: ++ break; ++ } ++} ++ ++/* protocol was rejected by foe */ ++void cbcp_protrej(int iface) ++{ ++} ++ ++char *cbcp_codenames[] = {"Request", "Response", "Ack"}; ++ ++char *cbcp_optionnames[] = { "NoCallback", ++ "UserDefined", ++ "AdminDefined", ++ "List"}; ++/* pretty print a packet */ ++int cbcp_printpkt(u_char *p, int plen, ++ void (*printer) __P((void *, char *, ...)), ++ void *arg) ++{ ++ int code, opt, id, len, olen, delay; ++ u_char *pstart, *optend; ++ u_short cishort; ++ u_long cilong; ++ ++ if (plen < HEADERLEN) ++ return 0; ++ pstart = p; ++ GETCHAR(code, p); ++ GETCHAR(id, p); ++ GETSHORT(len, p); ++ if (len < HEADERLEN || len > plen) ++ return 0; ++ ++ if (code >= 1 && code <= sizeof(cbcp_codenames) / sizeof(char *)) ++ printer(arg, " %s", cbcp_codenames[code-1]); ++ else ++ printer(arg, " code=0x%x", code); ++ ++ printer(arg, " id=0x%x", id); ++ len -= HEADERLEN; ++ ++ switch (code) { ++ case CBCP_REQ: ++ case CBCP_RESP: ++ case CBCP_ACK: ++ while(len >= 2) { ++ GETCHAR(opt, p); ++ GETCHAR(olen, p); ++ ++ if (olen < 2 || olen > len) { ++ break; ++ } ++ ++ printer(arg, " <"); ++ len -= olen; ++ ++ if (opt >= 1 && opt <= sizeof(cbcp_optionnames) / sizeof(char *)) ++ printer(arg, " %s", cbcp_optionnames[opt-1]); ++ else ++ printer(arg, " option=0x%x", opt); ++ ++ if (olen > 2) { ++ GETCHAR(delay, p); ++ printer(arg, " delay = %d", delay); ++ } ++ ++ if (olen > 3) { ++ int addrt; ++ char str[256]; ++ ++ GETCHAR(addrt, p); ++ memcpy(str, p, olen - 4); ++ str[olen - 4] = 0; ++ printer(arg, " number = %s", str); ++ } ++ printer(arg, ">"); ++ break; ++ } ++ ++ default: ++ break; ++ } ++ ++ for (; len > 0; --len) { ++ GETCHAR(code, p); ++ printer(arg, " %.2x", code); ++ } ++ ++ return p - pstart; ++} ++ ++/* received CBCP request */ ++ ++void cbcp_recvreq(cbcp_state *us, char *pckt, int pcktlen) ++{ ++ u_char type, opt_len, delay, addr_type; ++ char address[256]; ++ int len = pcktlen; ++ ++ address[0] = 0; ++ ++ while (len) { ++ syslog(LOG_DEBUG, "length: %d", len); ++ ++ GETCHAR(type, pckt); ++ GETCHAR(opt_len, pckt); ++ ++ if (opt_len > 2) ++ GETCHAR(delay, pckt); ++ ++ us->us_allowed |= (1 << type); ++ ++ switch(type) { ++ case CB_CONF_NO: ++ syslog(LOG_DEBUG, "no callback allowed"); ++ break; ++ ++ case CB_CONF_USER: ++ syslog(LOG_DEBUG, "user callback allowed"); ++ if (opt_len > 4) { ++ GETCHAR(addr_type, pckt); ++ memcpy(address, pckt, opt_len - 4); ++ address[opt_len - 4] = 0; ++ if (address[0]) ++ syslog(LOG_DEBUG, "address: %s", address); ++ } ++ break; ++ ++ case CB_CONF_ADMIN: ++ syslog(LOG_DEBUG, "user admin defined allowed"); ++ break; ++ ++ case CB_CONF_LIST: ++ break; ++ } ++ len -= opt_len; ++ } ++ ++ cbcp_resp(us); ++} ++ ++void cbcp_resp(cbcp_state *us) ++{ ++ u_char cb_type; ++ u_char buf[256]; ++ u_char *bufp = buf; ++ int len = 0; ++ ++ cb_type = us->us_allowed & us->us_type; ++ syslog(LOG_DEBUG, "cbcp_resp cb_type=%d", cb_type); ++ ++#if 0 ++ if (!cb_type) ++ lcp_down(us->us_unit); ++#endif ++ ++ if (cb_type & ( 1 << CB_CONF_USER ) ) { ++ syslog(LOG_DEBUG, "cbcp_resp CONF_USER"); ++ PUTCHAR(CB_CONF_USER, bufp); ++ len = 3 + 1 + strlen(us->us_number) + 1; ++ PUTCHAR(len , bufp); ++ PUTCHAR(5, bufp); /* delay */ ++ PUTCHAR(1, bufp); ++ BCOPY(us->us_number, bufp, strlen(us->us_number) + 1); ++ cbcp_send(us, CBCP_RESP, buf, len); ++ return; ++ } ++ ++ if (cb_type & ( 1 << CB_CONF_ADMIN ) ) { ++ PUTCHAR(CB_CONF_ADMIN, bufp); ++ len = 3; ++ PUTCHAR(len , bufp); ++ PUTCHAR(0, bufp); ++ cbcp_send(us, CBCP_RESP, buf, len); ++ return; ++ } ++ ++ if (cb_type & ( 1 << CB_CONF_NO ) ) { ++ syslog(LOG_DEBUG, "cbcp_resp CONF_NO"); ++ PUTCHAR(CB_CONF_NO, bufp); ++ len = 3; ++ PUTCHAR(len , bufp); ++ PUTCHAR(0, bufp); ++ cbcp_send(us, CBCP_RESP, buf, len); ++ ipcp_open(us->us_unit); ++ return; ++ } ++} ++ ++void cbcp_send(cbcp_state *us, u_char code, u_char *buf, int len) ++{ ++ u_char *outp; ++ int outlen; ++ ++ outp = outpacket_buf; ++ ++ outlen = 4 + len; ++ ++ MAKEHEADER(outp, PPP_CBCP); ++ ++ PUTCHAR(code, outp); ++ PUTCHAR(us->us_id, outp); ++ PUTSHORT(outlen, outp); ++ ++ if (len) ++ BCOPY(buf, outp, len); ++ ++ output(us->us_unit, outpacket_buf, outlen + PPP_HDRLEN); ++} ++ ++void cbcp_recvack(cbcp_state *us, char *pckt, int len) ++{ ++ u_char type, delay, addr_type; ++ int opt_len; ++ char address[256]; ++ ++ if (len) { ++ GETCHAR(type, pckt); ++ GETCHAR(opt_len, pckt); ++ ++ if (opt_len > 2) ++ GETCHAR(delay, pckt); ++ ++ if (opt_len > 4) { ++ GETCHAR(addr_type, pckt); ++ memcpy(address, pckt, opt_len - 4); ++ address[opt_len - 4] = 0; ++ if (address[0]) ++ syslog(LOG_DEBUG, "peer will call: %s", address); ++ } ++ } ++ ++ cbcp_up(us); ++} ++ ++extern int persist; ++ ++/* ok peer will do callback */ ++void cbcp_up(cbcp_state *us) ++{ ++ persist = 0; ++ lcp_close(0); ++} +diff -r --unified=10 ppp-2.2a5.orig/pppd/cbcp.h ppp-2.2a5/pppd/cbcp.h +--- ppp-2.2a5.orig/pppd/cbcp.h Sat May 13 14:08:40 1995 ++++ ppp-2.2a5/pppd/cbcp.h Sat May 13 13:56:20 1995 +@@ -0,0 +1,33 @@ ++#ifndef CBCP_H ++#define CBCP_H ++ ++typedef struct cbcp_state { ++ int us_unit; /* Interface unit number */ ++ u_char us_id; /* Current id */ ++ u_char us_allowed; ++ int us_type; ++ char *us_number; /* Telefone Number */ ++} 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[]; ++ ++#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 ++#endif +diff -r --unified=10 ppp-2.2a5.orig/pppd/lcp.c ppp-2.2a5/pppd/lcp.c +--- ppp-2.2a5.orig/pppd/lcp.c Sat May 13 12:38:20 1995 ++++ ppp-2.2a5/pppd/lcp.c Sat May 13 13:46:36 1995 +@@ -112,24 +112,26 @@ + lcp_extcode, /* Called to handle LCP-specific codes */ + "LCP" /* String name of protocol */ + }; + + int lcp_warnloops = DEFWARNLOOPS; /* Warn about a loopback this often */ + + /* + * Length of each type of configuration option (in octets) + */ + #define CILEN_VOID 2 ++#define CILEN_CHAR 3 + #define CILEN_SHORT 4 /* CILEN_VOID + sizeof(short) */ + #define CILEN_CHAP 5 /* CILEN_VOID + sizeof(short) + 1 */ + #define CILEN_LONG 6 /* CILEN_VOID + sizeof(long) */ + #define CILEN_LQR 8 /* CILEN_VOID + sizeof(short) + sizeof(long) */ ++#define CILEN_CBCP 3 + + #define CODENAME(x) ((x) == CONFACK ? "ACK" : \ + (x) == CONFNAK ? "NAK" : "REJ") + + + /* + * lcp_init - Initialize LCP. + */ + void + lcp_init(unit) +@@ -153,32 +155,34 @@ + wo->mru = DEFMRU; + wo->neg_asyncmap = 0; + wo->asyncmap = 0; + wo->neg_chap = 0; /* Set to 1 on server */ + wo->neg_upap = 0; /* Set to 1 on server */ + wo->chap_mdtype = CHAP_DIGEST_MD5; + wo->neg_magicnumber = 1; + wo->neg_pcompression = 1; + wo->neg_accompression = 1; + wo->neg_lqr = 0; /* no LQR implementation yet */ ++ wo->neg_cbcp = 0; + + ao->neg_mru = 1; + ao->mru = MAXMRU; + ao->neg_asyncmap = 1; + ao->asyncmap = 0; + ao->neg_chap = 1; + ao->chap_mdtype = CHAP_DIGEST_MD5; + ao->neg_upap = 1; + ao->neg_magicnumber = 1; + ao->neg_pcompression = 1; + ao->neg_accompression = 1; + ao->neg_lqr = 0; /* no LQR implementation yet */ ++ ao->neg_cbcp = 1; + + memset(xmit_accm[unit], 0, sizeof(xmit_accm[0])); + xmit_accm[unit][3] = 0x60000000; + } + + + /* + * lcp_open - LCP is allowed to come up. + */ + void +@@ -478,29 +482,31 @@ + lcp_cilen(f) + fsm *f; + { + lcp_options *go = &lcp_gotoptions[f->unit]; + + #define LENCIVOID(neg) (neg ? CILEN_VOID : 0) + #define LENCICHAP(neg) (neg ? CILEN_CHAP : 0) + #define LENCISHORT(neg) (neg ? CILEN_SHORT : 0) + #define LENCILONG(neg) (neg ? CILEN_LONG : 0) + #define LENCILQR(neg) (neg ? CILEN_LQR: 0) ++#define LENCICBCP(neg) (neg ? CILEN_CBCP: 0) + /* + * NB: we only ask for one of CHAP and UPAP, even if we will + * accept either. + */ + return (LENCISHORT(go->neg_mru) + + LENCILONG(go->neg_asyncmap) + + LENCICHAP(go->neg_chap) + + LENCISHORT(!go->neg_chap && go->neg_upap) + + LENCILQR(go->neg_lqr) + ++ LENCICBCP(go->neg_cbcp) + + LENCILONG(go->neg_magicnumber) + + LENCIVOID(go->neg_pcompression) + + LENCIVOID(go->neg_accompression)); + } + + + /* + * lcp_addci - Add our desired CIs to a packet. + */ + static void +@@ -537,25 +543,33 @@ + PUTLONG(val, ucp); \ + } + #define ADDCILQR(opt, neg, val) \ + if (neg) { \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_LQR, ucp); \ + PUTSHORT(PPP_LQR, ucp); \ + PUTLONG(val, ucp); \ + } + ++#define ADDCICHAR(opt, neg, val) \ ++ if (neg) { \ ++ PUTCHAR(opt, ucp); \ ++ PUTCHAR(CILEN_CHAR, ucp); \ ++ PUTCHAR(val, ucp); \ ++ } ++ + ADDCISHORT(CI_MRU, go->neg_mru, go->mru); + ADDCILONG(CI_ASYNCMAP, go->neg_asyncmap, go->asyncmap); + ADDCICHAP(CI_AUTHTYPE, go->neg_chap, PPP_CHAP, go->chap_mdtype); + ADDCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP); + ADDCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period); ++ ADDCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT); + ADDCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber); + ADDCIVOID(CI_PCOMPRESSION, go->neg_pcompression); + ADDCIVOID(CI_ACCOMPRESSION, go->neg_accompression); + + if (ucp - start_ucp != *lenp) { + /* this should never happen, because peer_mtu should be 1500 */ + syslog(LOG_ERR, "Bug in lcp_addci: wrong length"); + } + } + +@@ -600,20 +614,33 @@ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_SHORT || \ + citype != opt) \ + goto bad; \ + GETSHORT(cishort, p); \ + if (cishort != val) \ + goto bad; \ + } ++#define ACKCICHAR(opt, neg, val) \ ++ if (neg) { \ ++ if ((len -= CILEN_CHAR) < 0) \ ++ goto bad; \ ++ GETCHAR(citype, p); \ ++ GETCHAR(cilen, p); \ ++ if (cilen != CILEN_CHAR || \ ++ citype != opt) \ ++ goto bad; \ ++ GETCHAR(cichar, p); \ ++ if (cichar != val) \ ++ goto bad; \ ++ } + #define ACKCICHAP(opt, neg, val, digest) \ + if (neg) { \ + if ((len -= CILEN_CHAP) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_CHAP || \ + citype != opt) \ + goto bad; \ + GETSHORT(cishort, p); \ +@@ -651,20 +678,21 @@ + GETLONG(cilong, p); \ + if (cilong != val) \ + goto bad; \ + } + + ACKCISHORT(CI_MRU, go->neg_mru, go->mru); + ACKCILONG(CI_ASYNCMAP, go->neg_asyncmap, go->asyncmap); + ACKCICHAP(CI_AUTHTYPE, go->neg_chap, PPP_CHAP, go->chap_mdtype); + ACKCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP); + ACKCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period); ++ ACKCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT); + ACKCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber); + ACKCIVOID(CI_PCOMPRESSION, go->neg_pcompression); + ACKCIVOID(CI_ACCOMPRESSION, go->neg_accompression); + + /* + * If there are any remaining CIs, then this packet is bad. + */ + if (len != 0) + goto bad; + return (1); +@@ -722,20 +750,31 @@ + len >= CILEN_CHAP && \ + p[1] == CILEN_CHAP && \ + p[0] == opt) { \ + len -= CILEN_CHAP; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETCHAR(cichar, p); \ + no.neg = 1; \ + code \ + } ++#define NAKCICHAR(opt, neg, code) \ ++ if (go->neg && \ ++ len >= CILEN_CHAR && \ ++ p[1] == CILEN_CHAR && \ ++ p[0] == opt) { \ ++ len -= CILEN_CHAR; \ ++ INCPTR(2, p); \ ++ GETCHAR(cichar, p); \ ++ no.neg = 1; \ ++ code \ ++ } + #define NAKCISHORT(opt, neg, code) \ + if (go->neg && \ + len >= CILEN_SHORT && \ + p[1] == CILEN_SHORT && \ + p[0] == opt) { \ + len -= CILEN_SHORT; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + no.neg = 1; \ + code \ +@@ -851,20 +890,27 @@ + * If they Nak the reporting period, take their value XXX ? + */ + NAKCILQR(CI_QUALITY, neg_lqr, + if (cishort != PPP_LQR) + try.neg_lqr = 0; + else + try.lqr_period = cilong; + ); + + /* ++ * Only implementing CBCP... not the rest of the callback options ++ */ ++ NAKCICHAR(CI_CALLBACK, neg_cbcp, ++ try.neg_cbcp = 0; ++ ); ++ ++ /* + * Check for a looped-back line. + */ + NAKCILONG(CI_MAGICNUMBER, neg_magicnumber, + try.magicnumber = magic(); + ++try.numloops; + looped_back = 1; + ); + + NAKCIVOID(CI_PCOMPRESSION, neg_pcompression, + try.neg_pcompression = 0; +@@ -1045,28 +1091,43 @@ + len -= CILEN_LQR; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETLONG(cilong, p); \ + /* Check rejected value. */ \ + if (cishort != PPP_LQR || cilong != val) \ + goto bad; \ + try.neg = 0; \ + LCPDEBUG((LOG_INFO,"lcp_rejci rejected LQR opt %d", opt)); \ + } ++#define REJCICBCP(opt, neg, val) \ ++ if (go->neg && \ ++ len >= CILEN_CBCP && \ ++ p[1] == CILEN_CBCP && \ ++ p[0] == opt) { \ ++ len -= CILEN_CBCP; \ ++ INCPTR(2, p); \ ++ GETCHAR(cichar, p); \ ++ /* Check rejected value. */ \ ++ if (cichar != val) \ ++ goto bad; \ ++ try.neg = 0; \ ++ LCPDEBUG((LOG_INFO,"lcp_rejci rejected Callback opt %d", opt)); \ ++ } + + REJCISHORT(CI_MRU, neg_mru, go->mru); + REJCILONG(CI_ASYNCMAP, neg_asyncmap, go->asyncmap); + REJCICHAP(CI_AUTHTYPE, neg_chap, PPP_CHAP, go->chap_mdtype); + if (!go->neg_chap) { + REJCISHORT(CI_AUTHTYPE, neg_upap, PPP_PAP); + } + REJCILQR(CI_QUALITY, neg_lqr, go->lqr_period); ++ REJCICBCP(CI_CALLBACK, neg_cbcp, CBCP_OPT); + REJCILONG(CI_MAGICNUMBER, neg_magicnumber, go->magicnumber); + REJCIVOID(CI_PCOMPRESSION, neg_pcompression); + REJCIVOID(CI_ACCOMPRESSION, neg_accompression); + + /* + * If there are any remaining CIs, then this packet is bad. + */ + if (len != 0) + goto bad; + /* +@@ -1447,20 +1508,21 @@ + */ + ppp_recv_config(f->unit, (go->neg_mru? MAX(wo->mru, go->mru): PPP_MRU), + (go->neg_asyncmap? go->asyncmap: 0x00000000), + go->neg_pcompression, go->neg_accompression); + + if (ho->neg_mru) + peer_mru[f->unit] = ho->mru; + + ChapLowerUp(f->unit); /* Enable CHAP */ + upap_lowerup(f->unit); /* Enable UPAP */ ++ cbcp_lowerup(f->unit); /* Enable CBCP */ + ipcp_lowerup(f->unit); /* Enable IPCP */ + ccp_lowerup(f->unit); /* Enable CCP */ + lcp_echo_lowerup(f->unit); /* Enable echo messages */ + + link_established(f->unit); + } + + + /* + * lcp_down - LCP has gone DOWN. +@@ -1593,20 +1655,34 @@ + } + break; + case CI_QUALITY: + if (olen >= CILEN_SHORT) { + p += 2; + printer(arg, "quality "); + GETSHORT(cishort, p); + switch (cishort) { + case PPP_LQR: + printer(arg, "lqr"); ++ break; ++ default: ++ printer(arg, "0x%x", cishort); ++ } ++ } ++ break; ++ case CI_CALLBACK: ++ if (olen >= CILEN_CHAR) { ++ p += 2; ++ printer(arg, "callback "); ++ GETSHORT(cishort, p); ++ switch (cishort) { ++ case CBCP_OPT: ++ printer(arg, "CBCP"); + break; + default: + printer(arg, "0x%x", cishort); + } + } + break; + case CI_MAGICNUMBER: + if (olen == CILEN_LONG) { + p += 2; + GETLONG(cilong, p); +diff -r --unified=10 ppp-2.2a5.orig/pppd/lcp.h ppp-2.2a5/pppd/lcp.h +--- ppp-2.2a5.orig/pppd/lcp.h Sat May 13 12:38:20 1995 ++++ ppp-2.2a5/pppd/lcp.h Sat May 13 13:46:36 1995 +@@ -22,44 +22,47 @@ + /* + * Options. + */ + #define CI_MRU 1 /* Maximum Receive Unit */ + #define CI_ASYNCMAP 2 /* Async Control Character Map */ + #define CI_AUTHTYPE 3 /* Authentication Type */ + #define CI_QUALITY 4 /* Quality Protocol */ + #define CI_MAGICNUMBER 5 /* Magic Number */ + #define CI_PCOMPRESSION 7 /* Protocol Field Compression */ + #define CI_ACCOMPRESSION 8 /* Address/Control Field Compression */ ++#define CI_CALLBACK 13 /* callback */ + + /* + * LCP-specific packet types. + */ + #define PROTREJ 8 /* Protocol Reject */ + #define ECHOREQ 9 /* Echo Request */ + #define ECHOREP 10 /* Echo Reply */ + #define DISCREQ 11 /* Discard Request */ ++#define CBCP_OPT 6 /* Use callback control protocol */ + + /* + * The state of options is described by an lcp_options structure. + */ + typedef struct lcp_options { + int passive : 1; /* Don't die if we don't get a response */ + int silent : 1; /* Wait for the other end to start first */ + int restart : 1; /* Restart vs. exit after close */ + int neg_mru : 1; /* Negotiate the MRU? */ + int neg_asyncmap : 1; /* Negotiate the async map? */ + int neg_upap : 1; /* Ask for UPAP authentication? */ + int neg_chap : 1; /* Ask for CHAP authentication? */ + int neg_magicnumber : 1; /* Ask for magic number? */ + int neg_pcompression : 1; /* HDLC Protocol Field Compression? */ + int neg_accompression : 1; /* HDLC Address/Control Field Compression? */ + int neg_lqr : 1; /* Negotiate use of Link Quality Reports */ ++ int neg_cbcp : 1; /* Negotiate use of CBCP */ + u_short mru; /* Value of MRU */ + u_char chap_mdtype; /* which MD type (hashing algorithm) */ + u_int32_t asyncmap; /* Value of async map */ + u_int32_t magicnumber; + int numloops; /* Number of loops during magic number neg. */ + u_int32_t lqr_period; /* Reporting period for link quality */ + } lcp_options; + + extern fsm lcp_fsm[]; + extern lcp_options lcp_wantoptions[]; +diff -r --unified=10 ppp-2.2a5.orig/pppd/main.c ppp-2.2a5/pppd/main.c +--- ppp-2.2a5.orig/pppd/main.c Sat May 13 12:38:20 1995 ++++ ppp-2.2a5/pppd/main.c Sat May 13 13:46:36 1995 +@@ -40,20 +40,21 @@ + #include + #include + + #include "pppd.h" + #include "magic.h" + #include "fsm.h" + #include "lcp.h" + #include "ipcp.h" + #include "upap.h" + #include "chap.h" ++#include "cbcp.h" + #include "ccp.h" + #include "pathnames.h" + #include "patchlevel.h" + + /* + * If REQ_SYSOPTIONS is defined to 1, pppd will not run unless + * /etc/ppp/options exists. + */ + #ifndef REQ_SYSOPTIONS + #define REQ_SYSOPTIONS 1 +@@ -129,20 +130,22 @@ + int (*printpkt)(); + void (*datainput)(); + char *name; + } prottbl[] = { + { PPP_LCP, lcp_init, lcp_input, lcp_protrej, + lcp_printpkt, NULL, "LCP" }, + { PPP_IPCP, ipcp_init, ipcp_input, ipcp_protrej, + ipcp_printpkt, NULL, "IPCP" }, + { PPP_PAP, upap_init, upap_input, upap_protrej, + upap_printpkt, NULL, "PAP" }, ++ { PPP_CBCP, cbcp_init, cbcp_input, cbcp_protrej, ++ cbcp_printpkt, NULL, "CBCP" }, + { PPP_CHAP, ChapInit, ChapInput, ChapProtocolReject, + ChapPrintPkt, NULL, "CHAP" }, + { PPP_CCP, ccp_init, ccp_input, ccp_protrej, + ccp_printpkt, ccp_datainput, "CCP" }, + }; + + #define N_PROTO (sizeof(prottbl) / sizeof(prottbl[0])) + + main(argc, argv) + int argc; +diff -r --unified=10 ppp-2.2a5.orig/pppd/options.c ppp-2.2a5/pppd/options.c +--- ppp-2.2a5.orig/pppd/options.c Sat May 13 12:38:21 1995 ++++ ppp-2.2a5/pppd/options.c Sat May 13 13:59:24 1995 +@@ -36,20 +36,21 @@ + #include + + #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 "cbcp.h" + #include "ccp.h" + + #include + + #define FALSE 0 + #define TRUE 1 + + #if defined(ultrix) || defined(NeXT) + char *strdup __P((char *)); + #endif +@@ -112,20 +113,21 @@ + static int reqchap __P((void)); + static int setspeed __P((char *)); + static int noaccomp __P((void)); + static int noasyncmap __P((void)); + static int noipaddr __P((void)); + static int nomagicnumber __P((void)); + static int setasyncmap __P((char **)); + static int setescape __P((char **)); + static int setmru __P((char **)); + static int setmtu __P((char **)); ++static int setcbcp __P((char **)); + static int nomru __P((void)); + static int nopcomp __P((void)); + static int setconnector __P((char **)); + static int setdisconnector __P((char **)); + static int setdomain __P((char **)); + static int setnetmask __P((char **)); + static int setcrtscts __P((void)); + static int setnocrtscts __P((void)); + static int setxonxoff __P((void)); + static int setnodetach __P((void)); +@@ -202,20 +204,21 @@ + {"connect", 1, setconnector}, /* A program to set up a connection */ + {"disconnect", 1, setdisconnector}, /* program to disconnect serial dev. */ + {"crtscts", 0, setcrtscts}, /* set 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", 1, setcbcp}, /* Set CBCP */ + {"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 username for PAP auth with peer */ + {"usehostname", 0, setusehostname}, /* Must use hostname for auth. */ + {"remotename", 1, setremote}, /* Set remote name for authentication */ +@@ -775,20 +778,31 @@ + return 0; + if (mtu < MINMRU || mtu > MAXMRU) { + fprintf(stderr, "mtu option value of %ld is too %s\n", mtu, + (mtu < MINMRU? "small": "large")); + return 0; + } + lcp_allowoptions[0].mru = mtu; + return (1); + } + ++static int ++setcbcp(argv) ++ char **argv; ++{ ++ lcp_wantoptions[0].neg_cbcp = 1; ++ ++ cbcp[0].us_number = (char *) malloc(strlen(*argv) + 1); ++ strcpy(cbcp[0].us_number, *argv); ++ cbcp[0].us_type |= (1 << CB_CONF_USER); ++ return (1); ++} + + /* + * nopcomp - Disable Protocol field compression negotiation. + */ + static int + nopcomp() + { + lcp_wantoptions[0].neg_pcompression = 0; + lcp_allowoptions[0].neg_pcompression = 0; + return (1); +diff -r --unified=10 ppp-2.2a5.orig/pppd/pppd.8 ppp-2.2a5/pppd/pppd.8 +--- ppp-2.2a5.orig/pppd/pppd.8 Sat May 13 12:38:21 1995 ++++ ppp-2.2a5/pppd/pppd.8 Sat May 13 13:52:26 1995 +@@ -221,20 +221,31 @@ + .B -pap + Don't agree to authenticate using PAP. + .TP + .B +chap + Require the peer to authenticate itself using CHAP [Cryptographic + Handshake Authentication Protocol] authentication. + .TP + .B -chap + Don't agree to authenticate using CHAP. + .TP ++.B cb \fItelephone_number ++Configure the current execution of pppd to negotiate the \fIclient\fR ++portion of '\fIC\fRall \fIB\fRack \fIC\fRonfiguration ++\fIP\fRrotocol'. The use of this protocol will permit the client to ++authenticate itself with the server and then supply a telephone number ++for the reverse connection. Once the telephone number is accepted, the ++connection will be terminated. You should then wait for the server to ++recall your location and re-authenticate yourself. This second step ++will require a second execution of \fIpppd\fR. This second execution should ++not include the \fIcb\fR option. ++.TP + .B -vj + Disable negotiation of Van Jacobson style IP header compression (use + default, i.e. no compression). + .TP + .B bsdcomp \fInr,nt + Request that the peer compress packets that it sends, using the + BSD-Compress scheme, with a maximum code size of \fInr\fR bits, and + agree to compress packets sent to the peer with a maximum code size of + \fInt\fR bits. If \fInt\fR is not specified, it defaults to the value + given for \fInr\fR. Values in the range 9 to 15 may be used for +diff -r --unified=10 ppp-2.2a5.orig/pppd/pppd.h ppp-2.2a5/pppd/pppd.h +--- ppp-2.2a5.orig/pppd/pppd.h Sat May 13 12:38:21 1995 ++++ ppp-2.2a5/pppd/pppd.h Sat May 13 13:46:36 1995 +@@ -85,22 +85,23 @@ + 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 */ + + /* + * Values for phase. + */ + #define PHASE_DEAD 0 + #define PHASE_ESTABLISH 1 + #define PHASE_AUTHENTICATE 2 +-#define PHASE_NETWORK 3 +-#define PHASE_TERMINATE 4 ++#define PHASE_CALLBACK 3 ++#define PHASE_NETWORK 4 ++#define PHASE_TERMINATE 5 + + /* + * Prototypes. + */ + void quit __P((void)); /* Cleanup and exit */ + void timeout __P((void (*)(), caddr_t, int)); + /* Look-alike of kernel's timeout() */ + void untimeout __P((void (*)(), caddr_t)); + /* Look-alike of kernel's untimeout() */ + void output __P((int, u_char *, int));