readme for call-back control protocol
[ppp.git] / README.cbcp
1              Microsoft Call Back Configuration Protocol.
2                         by Pedro Roque Marques
3
4 The CBCP is a method by which the Microsoft Windows NT Server may
5 implement additional security. It is possible to configure the server
6 in such a manner so as to require that the client systems which
7 connect with it are required that following a valid authentication to
8 leave a method by which the number may be returned call.
9
10 It is a requirement of servers so configured that the protocol be
11 exchanged.
12
13 So, this set of patches may be applied to the pppd process to enable
14 the cbcp client *only* portion of the specification. It is primarily
15 meant to permit connection with Windows NT Servers.
16
17 The ietf-working specification may be obtained from ftp.microsoft.com
18 in the developr/rfc directory.
19
20 The ietf task group has decided to recommend that the LCP sequence be
21 extended to permit the callback operation. For this reason, these
22 patches are not 'part' of pppd but are an adjunct to the code. I
23 hopefully have included enough of the context to permit the patch
24 program so that minor changes to the program should not effect the
25 patch by more than a few lines in the 'fuzz' factor.
26
27
28
29 diff -r --unified=10 ppp-2.2a5.orig/linux/ppp_defs.h ppp-2.2a5/linux/ppp_defs.h
30 --- ppp-2.2a5.orig/linux/ppp_defs.h     Sat May 13 12:38:19 1995
31 +++ ppp-2.2a5/linux/ppp_defs.h  Sat May 13 13:46:36 1995
32 @@ -56,20 +56,21 @@
33  #define PPP_IP         0x21    /* Internet Protocol */
34  #define        PPP_VJC_COMP    0x2d    /* VJ compressed TCP */
35  #define        PPP_VJC_UNCOMP  0x2f    /* VJ uncompressed TCP */
36  #define PPP_COMP       0xfd    /* compressed packet */
37  #define PPP_IPCP       0x8021  /* IP Control Protocol */
38  #define PPP_CCP                0x80fd  /* Compression Control Protocol */
39  #define PPP_LCP                0xc021  /* Link Control Protocol */
40  #define PPP_PAP                0xc023  /* Password Authentication Protocol */
41  #define PPP_LQR                0xc025  /* Link Quality Report protocol */
42  #define PPP_CHAP       0xc223  /* Cryptographic Handshake Auth. Protocol */
43 +#define PPP_CBCP        0xc029  /* Callback Control Protocol */
44  
45  /*
46   * Values for FCS calculations.
47   */
48  #define PPP_INITFCS    0xffff  /* Initial FCS value */
49  #define PPP_GOODFCS    0xf0b8  /* Good final FCS value */
50  #define PPP_FCS(fcs, c)        (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
51  
52  /*
53   * A 32-bit unsigned integral type.
54 diff -r --unified=10 ppp-2.2a5.orig/net/ppp_defs.h ppp-2.2a5/net/ppp_defs.h
55 --- ppp-2.2a5.orig/net/ppp_defs.h       Sat May 13 12:38:19 1995
56 +++ ppp-2.2a5/net/ppp_defs.h    Sat May 13 13:57:14 1995
57 @@ -56,20 +56,21 @@
58  #define PPP_IP         0x21    /* Internet Protocol */
59  #define        PPP_VJC_COMP    0x2d    /* VJ compressed TCP */
60  #define        PPP_VJC_UNCOMP  0x2f    /* VJ uncompressed TCP */
61  #define PPP_COMP       0xfd    /* compressed packet */
62  #define PPP_IPCP       0x8021  /* IP Control Protocol */
63  #define PPP_CCP                0x80fd  /* Compression Control Protocol */
64  #define PPP_LCP                0xc021  /* Link Control Protocol */
65  #define PPP_PAP                0xc023  /* Password Authentication Protocol */
66  #define PPP_LQR                0xc025  /* Link Quality Report protocol */
67  #define PPP_CHAP       0xc223  /* Cryptographic Handshake Auth. Protocol */
68 +#define PPP_CBCP        0xc029  /* Callback Control Protocol */
69  
70  /*
71   * Values for FCS calculations.
72   */
73  #define PPP_INITFCS    0xffff  /* Initial FCS value */
74  #define PPP_GOODFCS    0xf0b8  /* Good final FCS value */
75  #define PPP_FCS(fcs, c)        (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
76  
77  /*
78   * A 32-bit unsigned integral type.
79 diff -r --unified=10 ppp-2.2a5.orig/pppd/Makefile.aix4 ppp-2.2a5/pppd/Makefile.aix4
80 --- ppp-2.2a5.orig/pppd/Makefile.aix4   Sat May 13 12:38:20 1995
81 +++ ppp-2.2a5/pppd/Makefile.aix4        Sat May 13 14:09:17 1995
82 @@ -3,26 +3,26 @@
83  # $Id: README.cbcp,v 1.1 1997/04/30 05:37:27 paulus Exp $
84  #
85  #ifndef BINDIR
86  BINDIR = /usr/sbin
87  #endif
88  #ifndef MANDIR
89  MANDIR = /usr/man
90  #ENDIF
91  
92  PPPDSRCS = main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c \
93 -       auth.c options.c sys-bsd.c sys-str.c sys-aix4.c ccp.c
94 -HEADERS = callout.h pathnames.h patchlevel.h chap.h md5.h
95 +       auth.c options.c sys-bsd.c sys-str.c sys-aix4.c ccp.c cbcp.c
96 +HEADERS = callout.h pathnames.h patchlevel.h chap.h md5.h cbc.h
97  MANPAGES = pppd.8
98  
99  PPPDOBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o \
100 -       auth.o options.o sys-aix4.o ccp.o
101 +       auth.o options.o sys-aix4.o ccp.o cbcp.o
102  
103  CC = xlc
104  DEBUG_FLAGS = -DDEBUGALL
105  # SECURE_FLAGS = -DREQ_SYSOPTIONS=1
106  COMPILE_FLAGS = -DSTREAMS
107  COPTS = -O
108  LIBS= -bI:/lib/pse.exp
109  LOCK_PREFIX=\"/var/locks/LCK..\"
110  
111  CFLAGS = -I.. $(COPTS) $(DEBUG_FLAGS) $(COMPILE_FLAGS) $(SECURE_FLAGS)
112 diff -r --unified=10 ppp-2.2a5.orig/pppd/Makefile.bsd ppp-2.2a5/pppd/Makefile.bsd
113 --- ppp-2.2a5.orig/pppd/Makefile.bsd    Sat May 13 12:38:20 1995
114 +++ ppp-2.2a5/pppd/Makefile.bsd Sat May 13 14:09:36 1995
115 @@ -1,18 +1,18 @@
116  #      $Id: README.cbcp,v 1.1 1997/04/30 05:37:27 paulus Exp $
117  
118  BINDIR?= /usr/sbin
119  CFLAGS+= -I.. -DHAVE_PATHS_H
120  
121  PROG=  pppd
122  SRCS=  main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c ccp.c \
123 -       auth.c options.c sys-bsd.c
124 +       auth.c options.c sys-bsd.c cbcp.c
125  MAN8=  pppd.0
126  # The next line is for NetBSD-current systems.
127  MAN=   pppd.cat8
128  BINMODE=4555
129  BINOWN=        root
130  
131  LDADD= -lcrypt -lutil
132  DPADD= ${LIBCRYPT} ${LIBUTIL}
133  
134  .include <bsd.prog.mk>
135 diff -r --unified=10 ppp-2.2a5.orig/pppd/Makefile.linux ppp-2.2a5/pppd/Makefile.linux
136 --- ppp-2.2a5.orig/pppd/Makefile.linux  Sat May 13 12:38:20 1995
137 +++ ppp-2.2a5/pppd/Makefile.linux       Sat May 13 13:46:36 1995
138 @@ -1,25 +1,25 @@
139  #
140  # pppd makefile for Linux
141  # $Id: README.cbcp,v 1.1 1997/04/30 05:37:27 paulus Exp $
142  #
143  
144  BINDIR = /usr/etc
145  MANDIR = /usr/man
146  
147  PPPDSRCS = main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c ccp.c \
148 -       auth.c options.c sys-linux.c
149 -HEADERS = callout.h pathnames.h patchlevel.h chap.h md5.h
150 +       auth.c options.c sys-linux.c cbcp.c
151 +HEADERS = callout.h pathnames.h patchlevel.h chap.h md5.h cbcp.h
152  MANPAGES = pppd.8
153  
154  PPPDOBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o \
155 -       auth.o options.o sys-linux.o
156 +       auth.o options.o sys-linux.o cbcp.o
157  
158  all: pppd
159  
160  #
161  # include dependancies if present and backup if as a header file
162  ifeq (.depend,$(wildcard .depend))
163  include .depend
164  HEADERS := $(HEADERS) .depend
165  endif
166  
167 diff -r --unified=10 ppp-2.2a5.orig/pppd/Makefile.osf ppp-2.2a5/pppd/Makefile.osf
168 --- ppp-2.2a5.orig/pppd/Makefile.osf    Sat May 13 12:38:20 1995
169 +++ ppp-2.2a5/pppd/Makefile.osf Sat May 13 14:09:54 1995
170 @@ -1,26 +1,26 @@
171  #
172  # pppd makefile for OSF/1 on DEC Alpha
173  # $Id: README.cbcp,v 1.1 1997/04/30 05:37:27 paulus Exp $
174  #
175  
176  BINDIR = /usr/local/etc
177  MANDIR = /usr/local/man
178  
179  PPPDSRCS = main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c ccp.c \
180         auth.c options.c sys-bsd.c sys-str.c sys-ultrix.c sys-linux.c \
181 -       sys-osf.c
182 -HEADERS = callout.h pathnames.h patchlevel.h chap.h md5.h
183 +       sys-osf.c cbcp.c
184 +HEADERS = callout.h pathnames.h patchlevel.h chap.h md5.h cbcp.h
185  MANPAGES = pppd.8
186  
187  PPPDOBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o \
188 -       auth.o options.o sys-osf.o
189 +       auth.o options.o sys-osf.o cbcp.o
190  
191  CC = cc
192  DEBUG_FLAGS = -DDEBUGALL
193  COMPILE_FLAGS = -DSTREAMS -DGIDSET_TYPE=int
194  COPTS = -O2
195  LIBS = 
196  
197  CFLAGS = -I.. $(COPTS) $(COMPILE_FLAGS)
198  
199  SOURCE= RELNOTES Makefile \
200 diff -r --unified=10 ppp-2.2a5.orig/pppd/Makefile.sol2 ppp-2.2a5/pppd/Makefile.sol2
201 --- ppp-2.2a5.orig/pppd/Makefile.sol2   Sat May 13 12:38:20 1995
202 +++ ppp-2.2a5/pppd/Makefile.sol2        Sat May 13 14:10:09 1995
203 @@ -6,21 +6,21 @@
204  BINDIR = /usr/local/etc
205  MANDIR = /usr/local/man
206  
207  CC = gcc
208  COPTS = -g -O2
209  CFLAGS = $(COPTS) -I..
210  
211  INSTALL = /usr/sbin/install
212  
213  OBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o \
214 -       auth.o options.o sys-sol2.o
215 +       auth.o options.o sys-sol2.o cbcp.o
216  
217  pppd:  $(OBJS)
218         $(CC) -o pppd $(OBJS) -lnsl
219  
220  install:
221         $(INSTALL) -f $(BINDIR) -m 4755 -u root pppd
222         $(INSTALL) -f $(MANDIR)/man8 pppd.8
223  
224  clean:
225         rm -f $(OBJS) pppd *~ core
226 diff -r --unified=10 ppp-2.2a5.orig/pppd/Makefile.sun ppp-2.2a5/pppd/Makefile.sun
227 --- ppp-2.2a5.orig/pppd/Makefile.sun    Sat May 13 12:38:20 1995
228 +++ ppp-2.2a5/pppd/Makefile.sun Sat May 13 14:10:27 1995
229 @@ -2,26 +2,26 @@
230  # pppd makefile for Suns
231  # $Id: README.cbcp,v 1.1 1997/04/30 05:37:27 paulus Exp $
232  #
233  
234  BINDIR = /usr/local/etc
235  MANDIR = /usr/local/man
236  
237  INSTALL= install -o root -g daemon
238  
239  PPPDSRCS = main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c ccp.c \
240 -       auth.c options.c sys-bsd.c sys-str.c sys-ultrix.c sys-linux.c
241 -HEADERS = callout.h pathnames.h patchlevel.h chap.h md5.h
242 +       auth.c options.c sys-bsd.c sys-str.c sys-ultrix.c sys-linux.c cbcp.c
243 +HEADERS = callout.h pathnames.h patchlevel.h chap.h md5.h cbcp.h
244  MANPAGES = pppd.8
245  
246  PPPDOBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o \
247 -       auth.o options.o sys-str.o
248 +       auth.o options.o sys-str.o cbcp.o
249  
250  # CC = gcc
251  DEBUG_FLAGS =
252  COMPILE_FLAGS =
253  COPTS = -O
254  LIBS = -lkvm
255  
256  CFLAGS = -I.. $(COPTS) $(DEBUG_FLAGS) $(COMPILE_FLAGS)
257  
258  SOURCE= RELNOTES Makefile \
259 diff -r --unified=10 ppp-2.2a5.orig/pppd/Makefile.ultrix ppp-2.2a5/pppd/Makefile.ultrix
260 --- ppp-2.2a5.orig/pppd/Makefile.ultrix Sat May 13 12:38:20 1995
261 +++ ppp-2.2a5/pppd/Makefile.ultrix      Sat May 13 14:10:44 1995
262 @@ -1,25 +1,25 @@
263  #
264  # pppd makefile for Ultrix
265  # $Id: README.cbcp,v 1.1 1997/04/30 05:37:27 paulus Exp $
266  #
267  
268  BINDIR = /usr/local/etc
269  MANDIR = /usr/local/man
270  
271  PPPDSRCS = main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c ccp.c \
272 -       auth.c options.c sys-bsd.c sys-str.c sys-ultrix.c sys-linux.c
273 -HEADERS = callout.h pathnames.h patchlevel.h chap.h md5.h
274 +       auth.c options.c sys-bsd.c sys-str.c sys-ultrix.c sys-linux.c cbcp.c
275 +HEADERS = callout.h pathnames.h patchlevel.h chap.h md5.h cbcp.h
276  MANPAGES = pppd.8
277  
278  PPPDOBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o \
279 -       auth.o options.o sys-ultrix.o
280 +       auth.o options.o sys-ultrix.o cbcp.o
281  
282  # CC = gcc
283  DEBUG_FLAGS =
284  COMPILE_FLAGS = -DNO_DRAND48 -DGIDSET_TYPE=int
285  COPTS = -O
286  LIBS =
287  
288  CFLAGS = -I.. $(COPTS) $(DEBUG_FLAGS) $(COMPILE_FLAGS)
289  
290  SOURCE= RELNOTES Makefile \
291 diff -r --unified=10 ppp-2.2a5.orig/pppd/auth.c ppp-2.2a5/pppd/auth.c
292 --- ppp-2.2a5.orig/pppd/auth.c  Sat May 13 12:38:20 1995
293 +++ ppp-2.2a5/pppd/auth.c       Sat May 13 13:46:36 1995
294 @@ -55,20 +55,21 @@
295  #ifndef PW_PPP
296  #define PW_PPP PW_LOGIN
297  #endif
298  #endif
299  
300  #include "pppd.h"
301  #include "fsm.h"
302  #include "lcp.h"
303  #include "upap.h"
304  #include "chap.h"
305 +#include "cbcp.h"
306  #include "ipcp.h"
307  #include "ccp.h"
308  #include "pathnames.h"
309  
310  #ifdef sparc
311  #include <alloca.h>
312  #endif /*sparc*/
313  
314  /* Used for storing a sequence of words.  Usually malloced. */
315  struct wordlist {
316 @@ -93,20 +94,21 @@
317  /* Bits in auth_pending[] */
318  #define UPAP_WITHPEER  1
319  #define UPAP_PEER      2
320  #define CHAP_WITHPEER  4
321  #define CHAP_PEER      8
322  
323  /* Prototypes */
324  void check_access __P((FILE *, char *));
325  
326  static void network_phase __P((int));
327 +static void callback_phase __P((int));
328  static int  login __P((char *, char *, char **, int *));
329  static void logout __P((void));
330  static int  null_login __P((int));
331  static int  get_upap_passwd __P((void));
332  static int  have_upap_secret __P((void));
333  static int  have_chap_secret __P((char *, char *));
334  static int  scan_authfile __P((FILE *, char *, char *, char *,
335                                   struct wordlist **, char *));
336  static void free_wordlist __P((struct wordlist *));
337  
338 @@ -140,20 +142,21 @@
339  
340  /*
341   * LCP has gone down; it will either die or try to re-establish.
342   */
343  void
344  link_down(unit)
345      int unit;
346  {
347      ipcp_close(0);
348      ccp_close(0);
349 +    cbcp_close(0);
350      phase = PHASE_TERMINATE;
351  }
352  
353  /*
354   * The link is established.
355   * Proceed to the Dead, Authenticate or Network phase as appropriate.
356   */
357  void
358  link_established(unit)
359      int unit;
360 @@ -189,36 +192,53 @@
361      if (ho->neg_chap) {
362         ChapAuthWithPeer(unit, our_name, ho->chap_mdtype);
363         auth |= CHAP_WITHPEER;
364      } else if (ho->neg_upap) {
365         upap_authwithpeer(unit, user, passwd);
366         auth |= UPAP_WITHPEER;
367      }
368      auth_pending[unit] = auth;
369  
370      if (!auth)
371 -       network_phase(unit);
372 +       callback_phase(unit);
373  }
374  
375  /*
376   * Proceed to the network phase.
377   */
378  static void
379  network_phase(unit)
380      int unit;
381  {
382      phase = PHASE_NETWORK;
383      ipcp_open(unit);
384      ccp_open(unit);
385  }
386  
387  /*
388 + * Proceed to the callback phase which may be empty.
389 + */
390 +static void
391 +callback_phase(unit)
392 +     int unit;
393 +{
394 +    lcp_options *wo = &lcp_wantoptions[unit];
395 +
396 +    if (!wo->neg_cbcp)
397 +        network_phase(unit);
398 +    else {
399 +        phase = PHASE_CALLBACK;
400 +        cbcp_open(unit);
401 +    }
402 +}
403 +
404 +/*
405   * The peer has failed to authenticate himself using `protocol'.
406   */
407  void
408  auth_peer_fail(unit, protocol)
409      int unit, protocol;
410  {
411      /*
412       * Authentication failure: take the link down
413       */
414      lcp_close(unit);
415 @@ -242,27 +262,24 @@
416         bit = UPAP_PEER;
417         break;
418      default:
419         syslog(LOG_WARNING, "auth_peer_success: unknown protocol %x",
420                protocol);
421         return;
422      }
423  
424      /*
425       * If there is no more authentication still to be done,
426 -     * proceed to the network phase.
427 +     * go to the next phase.
428       */
429 -    if ((auth_pending[unit] &= ~bit) == 0) {
430 -       phase = PHASE_NETWORK;
431 -       ipcp_open(unit);
432 -       ccp_open(unit);
433 -    }
434 +    if ((auth_pending[unit] &= ~bit) == 0)
435 +       callback_phase(unit);
436  }
437  
438  /*
439   * We have failed to authenticate ourselves to the peer using `protocol'.
440   */
441  void
442  auth_withpeer_fail(unit, protocol)
443      int unit, protocol;
444  {
445      /*
446 @@ -291,22 +308,23 @@
447      default:
448         syslog(LOG_WARNING, "auth_peer_success: unknown protocol %x",
449                protocol);
450         bit = 0;
451      }
452  
453      /*
454       * If there is no more authentication still being done,
455       * proceed to the network phase.
456       */
457 +
458      if ((auth_pending[unit] &= ~bit) == 0)
459 -       network_phase(unit);
460 +       callback_phase(unit);
461  }
462  
463  
464  /*
465   * check_auth_options - called to check authentication options.
466   */
467  void
468  check_auth_options()
469  {
470      lcp_options *wo = &lcp_wantoptions[0];
471 @@ -335,21 +353,20 @@
472      if (ao->neg_chap && !have_chap_secret(our_name, remote_name))
473         ao->neg_chap = 0;
474      if (wo->neg_chap && !have_chap_secret(remote_name, our_name))
475         wo->neg_chap = 0;
476  
477      if (auth_required && !wo->neg_chap && !wo->neg_upap) {
478         fprintf(stderr, "\
479  pppd: peer authentication required but no authentication files accessible\n");
480         exit(1);
481      }
482 -
483  }
484  
485  
486  /*
487   * check_passwd - Check the user name and passwd against the PAP secrets
488   * file.  If requested, also check against the system password database,
489   * and login the user if OK.
490   *
491   * returns:
492   *     UPAP_AUTHNAK: Authentication failed.
493 diff -r --unified=10 ppp-2.2a5.orig/pppd/cbcp.c ppp-2.2a5/pppd/cbcp.c
494 --- ppp-2.2a5.orig/pppd/cbcp.c  Sat May 13 14:08:45 1995
495 +++ ppp-2.2a5/pppd/cbcp.c       Sat May 13 14:15:12 1995
496 @@ -0,0 +1,370 @@
497 +/*
498 + * cbcp - Call Back Configuration Protocol.
499 + *
500 + * Copyright (c) 1995 Pedro Roque Marques
501 + * All rights reserved.
502 + *
503 + * Redistribution and use in source and binary forms are permitted
504 + * provided that the above copyright notice and this paragraph are
505 + * duplicated in all such forms and that any documentation,
506 + * advertising materials, and other materials related to such
507 + * distribution and use acknowledge that the software was developed
508 + * by Pedro Roque Marques.  The name of the author may not be used to
509 + * endorse or promote products derived from this software without
510 + * specific prior written permission.
511 + *
512 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
513 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
514 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
515 + */
516 +
517 +#ifndef lint
518 +static char rcsid[] = "$Id: README.cbcp,v 1.1 1997/04/30 05:37:27 paulus Exp $";
519 +#endif
520 +
521 +#include <stdio.h>
522 +#include <string.h>
523 +#include <sys/types.h>
524 +#include <sys/time.h>
525 +#include <syslog.h>
526 +
527 +#include "pppd.h"
528 +#include "cbcp.h"
529 +#include "fsm.h"
530 +#include "lcp.h"
531 +#include "ipcp.h"
532 +
533 +cbcp_state cbcp[NUM_PPP];      
534 +
535 +/* internal prototypes */
536 +
537 +void cbcp_recvreq(cbcp_state *us, char *pckt, int len);
538 +void cbcp_resp(cbcp_state *us);
539 +void cbcp_up(cbcp_state *us);
540 +void cbcp_recvack(cbcp_state *us, char *pckt, int len);
541 +void cbcp_send(cbcp_state *us, u_char code, u_char *buf, int len);
542 +
543 +/* init state */
544 +void cbcp_init(int iface)
545 +{
546 +    cbcp_state *us;
547 +
548 +    us = &cbcp[iface];
549 +    memset(us, 0, sizeof(cbcp_state));
550 +    us->us_unit = iface;
551 +    us->us_type |= (1 << CB_CONF_NO);
552 +}
553 +
554 +/* lower layer is up */
555 +void cbcp_lowerup(int iface)
556 +{
557 +    cbcp_state *us = &cbcp[iface];
558 +
559 +    syslog(LOG_DEBUG, "cbcp_lowerup");
560 +    syslog(LOG_DEBUG, "want: %d", us->us_type);
561 +
562 +    if (us->us_type == CB_CONF_USER)
563 +        syslog(LOG_DEBUG, "phone no: %s", us->us_number);
564 +}
565 +
566 +void cbcp_open(int unit)
567 +{
568 +    syslog(LOG_DEBUG, "cbcp_open");
569 +}
570 +
571 +void cbcp_close(int unit)
572 +{
573 +}
574 +
575 +/* process an incomming packet */
576 +void cbcp_input(int unit, u_char *inpacket, int pktlen)
577 +{
578 +    u_char *inp;
579 +    u_char code, id;
580 +    u_short len;
581 +
582 +    cbcp_state *us = &cbcp[unit];
583 +
584 +    inp = inpacket;
585 +
586 +    if (pktlen < CBCP_MINLEN) {
587 +        syslog(LOG_ERR, "CBCP packet is too small");
588 +       return;
589 +    }
590 +
591 +    GETCHAR(code, inp);
592 +    GETCHAR(id, inp);
593 +    GETSHORT(len, inp);
594 +
595 +#if 0
596 +    if (len > pktlen) {
597 +        syslog(LOG_ERR, "CBCP packet: invalid length");
598 +        return;
599 +    }
600 +#endif
601 +
602 +    len -= CBCP_MINLEN;
603
604 +    switch(code) {
605 +    case CBCP_REQ:
606 +        us->us_id = id;
607 +       cbcp_recvreq(us, inp, len);
608 +       break;
609 +
610 +    case CBCP_RESP:
611 +       syslog(LOG_DEBUG, "CBCP_RESP received");
612 +       break;
613 +
614 +    case CBCP_ACK:
615 +       if (id != us->us_id)
616 +           syslog(LOG_DEBUG, "id doesn't match: expected %d recv %d",
617 +                  us->us_id, id);
618 +
619 +       cbcp_recvack(us, inp, len);
620 +       break;
621 +
622 +    default:
623 +       break;
624 +    }
625 +}
626 +
627 +/* protocol was rejected by foe */
628 +void cbcp_protrej(int iface)
629 +{
630 +}
631 +
632 +char *cbcp_codenames[] = {"Request", "Response", "Ack"};
633 +
634 +char *cbcp_optionnames[] = {  "NoCallback",
635 +                             "UserDefined",
636 +                             "AdminDefined",
637 +                             "List"};
638 +/* pretty print a packet */
639 +int cbcp_printpkt(u_char *p, int plen,
640 +                  void (*printer) __P((void *, char *, ...)),
641 +                  void *arg)
642 +{
643 +    int code, opt, id, len, olen, delay;
644 +    u_char *pstart, *optend;
645 +    u_short cishort;
646 +    u_long cilong;
647 +
648 +    if (plen < HEADERLEN)
649 +       return 0;
650 +    pstart = p;
651 +    GETCHAR(code, p);
652 +    GETCHAR(id, p);
653 +    GETSHORT(len, p);
654 +    if (len < HEADERLEN || len > plen)
655 +       return 0;
656 +
657 +    if (code >= 1 && code <= sizeof(cbcp_codenames) / sizeof(char *))
658 +       printer(arg, " %s", cbcp_codenames[code-1]);
659 +    else
660 +       printer(arg, " code=0x%x", code); 
661 +
662 +    printer(arg, " id=0x%x", id);
663 +    len -= HEADERLEN;
664 +
665 +    switch (code) {
666 +    case CBCP_REQ:
667 +    case CBCP_RESP:
668 +    case CBCP_ACK:
669 +        while(len >= 2) {
670 +           GETCHAR(opt, p);
671 +           GETCHAR(olen, p);
672 +
673 +           if (olen < 2 || olen > len) {
674 +               break;
675 +           }
676 +
677 +           printer(arg, " <");
678 +           len -= olen;
679 +
680 +           if (opt >= 1 && opt <= sizeof(cbcp_optionnames) / sizeof(char *))
681 +               printer(arg, " %s", cbcp_optionnames[opt-1]);
682 +           else
683 +               printer(arg, " option=0x%x", opt); 
684 +
685 +           if (olen > 2) {
686 +               GETCHAR(delay, p);
687 +               printer(arg, " delay = %d", delay);
688 +           }
689 +
690 +           if (olen > 3) {
691 +               int addrt;
692 +               char str[256];
693 +
694 +               GETCHAR(addrt, p);
695 +               memcpy(str, p, olen - 4);
696 +               str[olen - 4] = 0;
697 +               printer(arg, " number = %s", str);
698 +           }
699 +           printer(arg, ">");
700 +       break;
701 +       }
702 +
703 +      default:
704 +       break;
705 +    }
706 +
707 +    for (; len > 0; --len) {
708 +       GETCHAR(code, p);
709 +       printer(arg, " %.2x", code);
710 +    }
711 +
712 +    return p - pstart;
713 +}
714 +
715 +/* received CBCP request */
716 +
717 +void cbcp_recvreq(cbcp_state *us, char *pckt, int pcktlen)
718 +{
719 +    u_char type, opt_len, delay, addr_type;
720 +    char address[256];
721 +    int len = pcktlen;
722 +
723 +    address[0] = 0;
724 +
725 +    while (len) {
726 +        syslog(LOG_DEBUG, "length: %d", len);
727 +
728 +       GETCHAR(type, pckt);
729 +       GETCHAR(opt_len, pckt);
730 +
731 +       if (opt_len > 2)
732 +           GETCHAR(delay, pckt);
733 +
734 +       us->us_allowed |= (1 << type);
735 +
736 +       switch(type) {
737 +       case CB_CONF_NO:
738 +           syslog(LOG_DEBUG, "no callback allowed");
739 +           break;
740 +
741 +      case CB_CONF_USER:
742 +           syslog(LOG_DEBUG, "user callback allowed");
743 +           if (opt_len > 4) {
744 +               GETCHAR(addr_type, pckt);
745 +               memcpy(address, pckt, opt_len - 4);
746 +               address[opt_len - 4] = 0;
747 +               if (address[0])
748 +                   syslog(LOG_DEBUG, "address: %s", address);
749 +           }
750 +       break;
751 +
752 +      case CB_CONF_ADMIN:
753 +           syslog(LOG_DEBUG, "user admin defined allowed");
754 +           break;
755 +
756 +      case CB_CONF_LIST:
757 +           break;
758 +       }
759 +       len -= opt_len;
760 +    }
761 +
762 +  cbcp_resp(us);
763 +}
764 +
765 +void cbcp_resp(cbcp_state *us)
766 +{
767 +    u_char cb_type;
768 +    u_char buf[256];
769 +    u_char *bufp = buf;
770 +    int len = 0;
771 +
772 +    cb_type = us->us_allowed & us->us_type;
773 +    syslog(LOG_DEBUG, "cbcp_resp cb_type=%d", cb_type);
774 +
775 +#if 0
776 +    if (!cb_type)
777 +        lcp_down(us->us_unit);
778 +#endif
779 +
780 +    if (cb_type & ( 1 << CB_CONF_USER ) ) {
781 +       syslog(LOG_DEBUG, "cbcp_resp CONF_USER");
782 +       PUTCHAR(CB_CONF_USER, bufp);
783 +       len = 3 + 1 + strlen(us->us_number) + 1;
784 +       PUTCHAR(len , bufp);
785 +       PUTCHAR(5, bufp); /* delay */
786 +       PUTCHAR(1, bufp);
787 +       BCOPY(us->us_number, bufp, strlen(us->us_number) + 1);
788 +       cbcp_send(us, CBCP_RESP, buf, len);
789 +       return;
790 +    }
791 +
792 +    if (cb_type & ( 1 << CB_CONF_ADMIN ) ) {
793 +        PUTCHAR(CB_CONF_ADMIN, bufp);
794 +       len = 3;
795 +       PUTCHAR(len , bufp);
796 +       PUTCHAR(0, bufp);
797 +       cbcp_send(us, CBCP_RESP, buf, len);
798 +       return;
799 +    }
800 +
801 +    if (cb_type & ( 1 << CB_CONF_NO ) ) {
802 +        syslog(LOG_DEBUG, "cbcp_resp CONF_NO");
803 +       PUTCHAR(CB_CONF_NO, bufp);
804 +       len = 3;
805 +       PUTCHAR(len , bufp);
806 +       PUTCHAR(0, bufp);
807 +       cbcp_send(us, CBCP_RESP, buf, len);
808 +       ipcp_open(us->us_unit);
809 +       return;
810 +    }
811 +}
812 +
813 +void cbcp_send(cbcp_state *us, u_char code, u_char *buf, int len)
814 +{
815 +    u_char *outp;
816 +    int outlen;
817 +
818 +    outp = outpacket_buf;
819 +
820 +    outlen = 4 + len;
821 +    
822 +    MAKEHEADER(outp, PPP_CBCP);
823 +
824 +    PUTCHAR(code, outp);
825 +    PUTCHAR(us->us_id, outp);
826 +    PUTSHORT(outlen, outp);
827 +    
828 +    if (len)
829 +        BCOPY(buf, outp, len);
830 +
831 +    output(us->us_unit, outpacket_buf, outlen + PPP_HDRLEN);
832 +}
833 +
834 +void cbcp_recvack(cbcp_state *us, char *pckt, int len)
835 +{
836 +    u_char type, delay, addr_type;
837 +    int opt_len;
838 +    char address[256];
839 +
840 +    if (len) {
841 +        GETCHAR(type, pckt);
842 +       GETCHAR(opt_len, pckt);
843 +     
844 +       if (opt_len > 2)
845 +           GETCHAR(delay, pckt);
846 +
847 +       if (opt_len > 4) {
848 +           GETCHAR(addr_type, pckt);
849 +           memcpy(address, pckt, opt_len - 4);
850 +           address[opt_len - 4] = 0;
851 +           if (address[0])
852 +               syslog(LOG_DEBUG, "peer will call: %s", address);
853 +       }
854 +    }
855 +
856 +    cbcp_up(us);
857 +}
858 +
859 +extern int persist;
860 +
861 +/* ok peer will do callback */
862 +void cbcp_up(cbcp_state *us)
863 +{
864 +    persist = 0;
865 +    lcp_close(0);
866 +}
867 diff -r --unified=10 ppp-2.2a5.orig/pppd/cbcp.h ppp-2.2a5/pppd/cbcp.h
868 --- ppp-2.2a5.orig/pppd/cbcp.h  Sat May 13 14:08:40 1995
869 +++ ppp-2.2a5/pppd/cbcp.h       Sat May 13 13:56:20 1995
870 @@ -0,0 +1,33 @@
871 +#ifndef CBCP_H
872 +#define CBCP_H
873 +
874 +typedef struct cbcp_state {
875 +    int    us_unit;    /* Interface unit number */
876 +    u_char us_id;              /* Current id */
877 +    u_char us_allowed;
878 +    int    us_type;
879 +    char   *us_number;    /* Telefone Number */
880 +} cbcp_state;
881 +
882 +void cbcp_init      __P((int));
883 +void cbcp_open      __P((int));
884 +void cbcp_lowerup   __P((int));
885 +void cbcp_input     __P((int, u_char *, int));
886 +void cbcp_protrej   __P((int));
887 +int  cbcp_printpkt  __P((u_char *, int,
888 +                           void (*) __P((void *, char *, ...)),
889 +                           void *));
890 +
891 +extern cbcp_state cbcp[];
892 +
893 +#define CBCP_MINLEN 4
894 +
895 +#define CBCP_REQ    1
896 +#define CBCP_RESP   2
897 +#define CBCP_ACK    3
898 +
899 +#define CB_CONF_NO     1
900 +#define CB_CONF_USER   2
901 +#define CB_CONF_ADMIN  3
902 +#define CB_CONF_LIST   4
903 +#endif
904 diff -r --unified=10 ppp-2.2a5.orig/pppd/lcp.c ppp-2.2a5/pppd/lcp.c
905 --- ppp-2.2a5.orig/pppd/lcp.c   Sat May 13 12:38:20 1995
906 +++ ppp-2.2a5/pppd/lcp.c        Sat May 13 13:46:36 1995
907 @@ -112,24 +112,26 @@
908      lcp_extcode,               /* Called to handle LCP-specific codes */
909      "LCP"                      /* String name of protocol */
910  };
911  
912  int lcp_warnloops = DEFWARNLOOPS; /* Warn about a loopback this often */
913  
914  /*
915   * Length of each type of configuration option (in octets)
916   */
917  #define CILEN_VOID     2
918 +#define CILEN_CHAR      3
919  #define CILEN_SHORT    4       /* CILEN_VOID + sizeof(short) */
920  #define CILEN_CHAP     5       /* CILEN_VOID + sizeof(short) + 1 */
921  #define CILEN_LONG     6       /* CILEN_VOID + sizeof(long) */
922  #define CILEN_LQR      8       /* CILEN_VOID + sizeof(short) + sizeof(long) */
923 +#define CILEN_CBCP      3
924  
925  #define CODENAME(x)    ((x) == CONFACK ? "ACK" : \
926                          (x) == CONFNAK ? "NAK" : "REJ")
927  
928  
929  /*
930   * lcp_init - Initialize LCP.
931   */
932  void
933  lcp_init(unit)
934 @@ -153,32 +155,34 @@
935      wo->mru = DEFMRU;
936      wo->neg_asyncmap = 0;
937      wo->asyncmap = 0;
938      wo->neg_chap = 0;                  /* Set to 1 on server */
939      wo->neg_upap = 0;                  /* Set to 1 on server */
940      wo->chap_mdtype = CHAP_DIGEST_MD5;
941      wo->neg_magicnumber = 1;
942      wo->neg_pcompression = 1;
943      wo->neg_accompression = 1;
944      wo->neg_lqr = 0;                   /* no LQR implementation yet */
945 +    wo->neg_cbcp = 0;
946  
947      ao->neg_mru = 1;
948      ao->mru = MAXMRU;
949      ao->neg_asyncmap = 1;
950      ao->asyncmap = 0;
951      ao->neg_chap = 1;
952      ao->chap_mdtype = CHAP_DIGEST_MD5;
953      ao->neg_upap = 1;
954      ao->neg_magicnumber = 1;
955      ao->neg_pcompression = 1;
956      ao->neg_accompression = 1;
957      ao->neg_lqr = 0;                   /* no LQR implementation yet */
958 +    ao->neg_cbcp = 1;
959  
960      memset(xmit_accm[unit], 0, sizeof(xmit_accm[0]));
961      xmit_accm[unit][3] = 0x60000000;
962  }
963  
964  
965  /*
966   * lcp_open - LCP is allowed to come up.
967   */
968  void
969 @@ -478,29 +482,31 @@
970  lcp_cilen(f)
971      fsm *f;
972  {
973      lcp_options *go = &lcp_gotoptions[f->unit];
974  
975  #define LENCIVOID(neg) (neg ? CILEN_VOID : 0)
976  #define LENCICHAP(neg) (neg ? CILEN_CHAP : 0)
977  #define LENCISHORT(neg)        (neg ? CILEN_SHORT : 0)
978  #define LENCILONG(neg) (neg ? CILEN_LONG : 0)
979  #define LENCILQR(neg)  (neg ? CILEN_LQR: 0)
980 +#define LENCICBCP(neg) (neg ? CILEN_CBCP: 0)
981      /*
982       * NB: we only ask for one of CHAP and UPAP, even if we will
983       * accept either.
984       */
985      return (LENCISHORT(go->neg_mru) +
986             LENCILONG(go->neg_asyncmap) +
987             LENCICHAP(go->neg_chap) +
988             LENCISHORT(!go->neg_chap && go->neg_upap) +
989             LENCILQR(go->neg_lqr) +
990 +           LENCICBCP(go->neg_cbcp) +
991             LENCILONG(go->neg_magicnumber) +
992             LENCIVOID(go->neg_pcompression) +
993             LENCIVOID(go->neg_accompression));
994  }
995  
996  
997  /*
998   * lcp_addci - Add our desired CIs to a packet.
999   */
1000  static void
1001 @@ -537,25 +543,33 @@
1002         PUTLONG(val, ucp); \
1003      }
1004  #define ADDCILQR(opt, neg, val) \
1005      if (neg) { \
1006         PUTCHAR(opt, ucp); \
1007         PUTCHAR(CILEN_LQR, ucp); \
1008         PUTSHORT(PPP_LQR, ucp); \
1009         PUTLONG(val, ucp); \
1010      }
1011  
1012 +#define ADDCICHAR(opt, neg, val) \
1013 +    if (neg) { \
1014 +       PUTCHAR(opt, ucp); \
1015 +       PUTCHAR(CILEN_CHAR, ucp); \
1016 +       PUTCHAR(val, ucp); \
1017 +    }
1018 +
1019      ADDCISHORT(CI_MRU, go->neg_mru, go->mru);
1020      ADDCILONG(CI_ASYNCMAP, go->neg_asyncmap, go->asyncmap);
1021      ADDCICHAP(CI_AUTHTYPE, go->neg_chap, PPP_CHAP, go->chap_mdtype);
1022      ADDCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP);
1023      ADDCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period);
1024 +    ADDCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT);
1025      ADDCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber);
1026      ADDCIVOID(CI_PCOMPRESSION, go->neg_pcompression);
1027      ADDCIVOID(CI_ACCOMPRESSION, go->neg_accompression);
1028  
1029      if (ucp - start_ucp != *lenp) {
1030         /* this should never happen, because peer_mtu should be 1500 */
1031         syslog(LOG_ERR, "Bug in lcp_addci: wrong length");
1032      }
1033  }
1034  
1035 @@ -600,20 +614,33 @@
1036             goto bad; \
1037         GETCHAR(citype, p); \
1038         GETCHAR(cilen, p); \
1039         if (cilen != CILEN_SHORT || \
1040             citype != opt) \
1041             goto bad; \
1042         GETSHORT(cishort, p); \
1043         if (cishort != val) \
1044             goto bad; \
1045      }
1046 +#define ACKCICHAR(opt, neg, val) \
1047 +    if (neg) { \
1048 +       if ((len -= CILEN_CHAR) < 0) \
1049 +           goto bad; \
1050 +       GETCHAR(citype, p); \
1051 +       GETCHAR(cilen, p); \
1052 +       if (cilen != CILEN_CHAR || \
1053 +           citype != opt) \
1054 +           goto bad; \
1055 +       GETCHAR(cichar, p); \
1056 +       if (cichar != val) \
1057 +           goto bad; \
1058 +    }
1059  #define ACKCICHAP(opt, neg, val, digest) \
1060      if (neg) { \
1061         if ((len -= CILEN_CHAP) < 0) \
1062             goto bad; \
1063         GETCHAR(citype, p); \
1064         GETCHAR(cilen, p); \
1065         if (cilen != CILEN_CHAP || \
1066             citype != opt) \
1067             goto bad; \
1068         GETSHORT(cishort, p); \
1069 @@ -651,20 +678,21 @@
1070         GETLONG(cilong, p); \
1071         if (cilong != val) \
1072           goto bad; \
1073      }
1074  
1075      ACKCISHORT(CI_MRU, go->neg_mru, go->mru);
1076      ACKCILONG(CI_ASYNCMAP, go->neg_asyncmap, go->asyncmap);
1077      ACKCICHAP(CI_AUTHTYPE, go->neg_chap, PPP_CHAP, go->chap_mdtype);
1078      ACKCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP);
1079      ACKCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period);
1080 +    ACKCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT);
1081      ACKCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber);
1082      ACKCIVOID(CI_PCOMPRESSION, go->neg_pcompression);
1083      ACKCIVOID(CI_ACCOMPRESSION, go->neg_accompression);
1084  
1085      /*
1086       * If there are any remaining CIs, then this packet is bad.
1087       */
1088      if (len != 0)
1089         goto bad;
1090      return (1);
1091 @@ -722,20 +750,31 @@
1092         len >= CILEN_CHAP && \
1093         p[1] == CILEN_CHAP && \
1094         p[0] == opt) { \
1095         len -= CILEN_CHAP; \
1096         INCPTR(2, p); \
1097         GETSHORT(cishort, p); \
1098         GETCHAR(cichar, p); \
1099         no.neg = 1; \
1100         code \
1101      }
1102 +#define NAKCICHAR(opt, neg, code) \
1103 +    if (go->neg && \
1104 +       len >= CILEN_CHAR && \
1105 +       p[1] == CILEN_CHAR && \
1106 +       p[0] == opt) { \
1107 +       len -= CILEN_CHAR; \
1108 +       INCPTR(2, p); \
1109 +       GETCHAR(cichar, p); \
1110 +       no.neg = 1; \
1111 +       code \
1112 +    }
1113  #define NAKCISHORT(opt, neg, code) \
1114      if (go->neg && \
1115         len >= CILEN_SHORT && \
1116         p[1] == CILEN_SHORT && \
1117         p[0] == opt) { \
1118         len -= CILEN_SHORT; \
1119         INCPTR(2, p); \
1120         GETSHORT(cishort, p); \
1121         no.neg = 1; \
1122         code \
1123 @@ -851,20 +890,27 @@
1124       * If they Nak the reporting period, take their value XXX ?
1125       */
1126      NAKCILQR(CI_QUALITY, neg_lqr,
1127              if (cishort != PPP_LQR)
1128                  try.neg_lqr = 0;
1129              else
1130                  try.lqr_period = cilong;
1131              );
1132  
1133      /*
1134 +     * Only implementing CBCP... not the rest of the callback options
1135 +     */
1136 +    NAKCICHAR(CI_CALLBACK, neg_cbcp,
1137 +             try.neg_cbcp = 0;
1138 +             );
1139 +
1140 +    /*
1141       * Check for a looped-back line.
1142       */
1143      NAKCILONG(CI_MAGICNUMBER, neg_magicnumber,
1144               try.magicnumber = magic();
1145               ++try.numloops;
1146               looped_back = 1;
1147               );
1148  
1149      NAKCIVOID(CI_PCOMPRESSION, neg_pcompression,
1150               try.neg_pcompression = 0;
1151 @@ -1045,28 +1091,43 @@
1152         len -= CILEN_LQR; \
1153         INCPTR(2, p); \
1154         GETSHORT(cishort, p); \
1155         GETLONG(cilong, p); \
1156         /* Check rejected value. */ \
1157         if (cishort != PPP_LQR || cilong != val) \
1158             goto bad; \
1159         try.neg = 0; \
1160         LCPDEBUG((LOG_INFO,"lcp_rejci rejected LQR opt %d", opt)); \
1161      }
1162 +#define REJCICBCP(opt, neg, val) \
1163 +    if (go->neg && \
1164 +       len >= CILEN_CBCP && \
1165 +       p[1] == CILEN_CBCP && \
1166 +       p[0] == opt) { \
1167 +       len -= CILEN_CBCP; \
1168 +       INCPTR(2, p); \
1169 +       GETCHAR(cichar, p); \
1170 +       /* Check rejected value. */ \
1171 +       if (cichar != val) \
1172 +           goto bad; \
1173 +       try.neg = 0; \
1174 +       LCPDEBUG((LOG_INFO,"lcp_rejci rejected Callback opt %d", opt)); \
1175 +    }
1176  
1177      REJCISHORT(CI_MRU, neg_mru, go->mru);
1178      REJCILONG(CI_ASYNCMAP, neg_asyncmap, go->asyncmap);
1179      REJCICHAP(CI_AUTHTYPE, neg_chap, PPP_CHAP, go->chap_mdtype);
1180      if (!go->neg_chap) {
1181         REJCISHORT(CI_AUTHTYPE, neg_upap, PPP_PAP);
1182      }
1183      REJCILQR(CI_QUALITY, neg_lqr, go->lqr_period);
1184 +    REJCICBCP(CI_CALLBACK, neg_cbcp, CBCP_OPT);
1185      REJCILONG(CI_MAGICNUMBER, neg_magicnumber, go->magicnumber);
1186      REJCIVOID(CI_PCOMPRESSION, neg_pcompression);
1187      REJCIVOID(CI_ACCOMPRESSION, neg_accompression);
1188  
1189      /*
1190       * If there are any remaining CIs, then this packet is bad.
1191       */
1192      if (len != 0)
1193         goto bad;
1194      /*
1195 @@ -1447,20 +1508,21 @@
1196       */
1197      ppp_recv_config(f->unit, (go->neg_mru? MAX(wo->mru, go->mru): PPP_MRU),
1198                     (go->neg_asyncmap? go->asyncmap: 0x00000000),
1199                     go->neg_pcompression, go->neg_accompression);
1200  
1201      if (ho->neg_mru)
1202         peer_mru[f->unit] = ho->mru;
1203  
1204      ChapLowerUp(f->unit);      /* Enable CHAP */
1205      upap_lowerup(f->unit);     /* Enable UPAP */
1206 +    cbcp_lowerup(f->unit);      /* Enable CBCP */
1207      ipcp_lowerup(f->unit);     /* Enable IPCP */
1208      ccp_lowerup(f->unit);      /* Enable CCP */
1209      lcp_echo_lowerup(f->unit);  /* Enable echo messages */
1210  
1211      link_established(f->unit);
1212  }
1213  
1214  
1215  /*
1216   * lcp_down - LCP has gone DOWN.
1217 @@ -1593,20 +1655,34 @@
1218                 }
1219                 break;
1220             case CI_QUALITY:
1221                 if (olen >= CILEN_SHORT) {
1222                     p += 2;
1223                     printer(arg, "quality ");
1224                     GETSHORT(cishort, p);
1225                     switch (cishort) {
1226                     case PPP_LQR:
1227                         printer(arg, "lqr");
1228 +                       break;
1229 +                   default:
1230 +                       printer(arg, "0x%x", cishort);
1231 +                   }
1232 +               }
1233 +               break;
1234 +           case CI_CALLBACK:
1235 +               if (olen >= CILEN_CHAR) {
1236 +                   p += 2;
1237 +                   printer(arg, "callback ");
1238 +                   GETSHORT(cishort, p);
1239 +                   switch (cishort) {
1240 +                   case CBCP_OPT:
1241 +                       printer(arg, "CBCP");
1242                         break;
1243                     default:
1244                         printer(arg, "0x%x", cishort);
1245                     }
1246                 }
1247                 break;
1248             case CI_MAGICNUMBER:
1249                 if (olen == CILEN_LONG) {
1250                     p += 2;
1251                     GETLONG(cilong, p);
1252 diff -r --unified=10 ppp-2.2a5.orig/pppd/lcp.h ppp-2.2a5/pppd/lcp.h
1253 --- ppp-2.2a5.orig/pppd/lcp.h   Sat May 13 12:38:20 1995
1254 +++ ppp-2.2a5/pppd/lcp.h        Sat May 13 13:46:36 1995
1255 @@ -22,44 +22,47 @@
1256  /*
1257   * Options.
1258   */
1259  #define CI_MRU         1       /* Maximum Receive Unit */
1260  #define CI_ASYNCMAP    2       /* Async Control Character Map */
1261  #define CI_AUTHTYPE    3       /* Authentication Type */
1262  #define CI_QUALITY     4       /* Quality Protocol */
1263  #define CI_MAGICNUMBER 5       /* Magic Number */
1264  #define CI_PCOMPRESSION        7       /* Protocol Field Compression */
1265  #define CI_ACCOMPRESSION 8     /* Address/Control Field Compression */
1266 +#define CI_CALLBACK      13     /* callback */
1267  
1268  /*
1269   * LCP-specific packet types.
1270   */
1271  #define PROTREJ                8       /* Protocol Reject */
1272  #define ECHOREQ                9       /* Echo Request */
1273  #define ECHOREP                10      /* Echo Reply */
1274  #define DISCREQ                11      /* Discard Request */
1275 +#define CBCP_OPT        6       /* Use callback control protocol */
1276  
1277  /*
1278   * The state of options is described by an lcp_options structure.
1279   */
1280  typedef struct lcp_options {
1281      int passive : 1;           /* Don't die if we don't get a response */
1282      int silent : 1;            /* Wait for the other end to start first */
1283      int restart : 1;           /* Restart vs. exit after close */
1284      int neg_mru : 1;           /* Negotiate the MRU? */
1285      int neg_asyncmap : 1;      /* Negotiate the async map? */
1286      int neg_upap : 1;          /* Ask for UPAP authentication? */
1287      int neg_chap : 1;          /* Ask for CHAP authentication? */
1288      int neg_magicnumber : 1;   /* Ask for magic number? */
1289      int neg_pcompression : 1;  /* HDLC Protocol Field Compression? */
1290      int neg_accompression : 1; /* HDLC Address/Control Field Compression? */
1291      int neg_lqr : 1;           /* Negotiate use of Link Quality Reports */
1292 +    int neg_cbcp : 1;           /* Negotiate use of CBCP */
1293      u_short mru;               /* Value of MRU */
1294      u_char chap_mdtype;                /* which MD type (hashing algorithm) */
1295      u_int32_t asyncmap;                /* Value of async map */
1296      u_int32_t magicnumber;
1297      int numloops;              /* Number of loops during magic number neg. */
1298      u_int32_t lqr_period;      /* Reporting period for link quality */
1299  } lcp_options;
1300  
1301  extern fsm lcp_fsm[];
1302  extern lcp_options lcp_wantoptions[];
1303 diff -r --unified=10 ppp-2.2a5.orig/pppd/main.c ppp-2.2a5/pppd/main.c
1304 --- ppp-2.2a5.orig/pppd/main.c  Sat May 13 12:38:20 1995
1305 +++ ppp-2.2a5/pppd/main.c       Sat May 13 13:46:36 1995
1306 @@ -40,20 +40,21 @@
1307  #include <sys/socket.h>
1308  #include <net/if.h>
1309  
1310  #include "pppd.h"
1311  #include "magic.h"
1312  #include "fsm.h"
1313  #include "lcp.h"
1314  #include "ipcp.h"
1315  #include "upap.h"
1316  #include "chap.h"
1317 +#include "cbcp.h"
1318  #include "ccp.h"
1319  #include "pathnames.h"
1320  #include "patchlevel.h"
1321  
1322  /*
1323   * If REQ_SYSOPTIONS is defined to 1, pppd will not run unless
1324   * /etc/ppp/options exists.
1325   */
1326  #ifndef        REQ_SYSOPTIONS
1327  #define REQ_SYSOPTIONS 1
1328 @@ -129,20 +130,22 @@
1329      int  (*printpkt)();
1330      void (*datainput)();
1331      char *name;
1332  } prottbl[] = {
1333      { PPP_LCP, lcp_init, lcp_input, lcp_protrej,
1334           lcp_printpkt, NULL, "LCP" },
1335      { PPP_IPCP, ipcp_init, ipcp_input, ipcp_protrej,
1336           ipcp_printpkt, NULL, "IPCP" },
1337      { PPP_PAP, upap_init, upap_input, upap_protrej,
1338           upap_printpkt, NULL, "PAP" },
1339 +    { PPP_CBCP, cbcp_init, cbcp_input, cbcp_protrej,
1340 +         cbcp_printpkt, NULL, "CBCP" },
1341      { PPP_CHAP, ChapInit, ChapInput, ChapProtocolReject,
1342           ChapPrintPkt, NULL, "CHAP" },
1343      { PPP_CCP, ccp_init, ccp_input, ccp_protrej,
1344           ccp_printpkt, ccp_datainput, "CCP" },
1345  };
1346  
1347  #define N_PROTO                (sizeof(prottbl) / sizeof(prottbl[0]))
1348  
1349  main(argc, argv)
1350      int argc;
1351 diff -r --unified=10 ppp-2.2a5.orig/pppd/options.c ppp-2.2a5/pppd/options.c
1352 --- ppp-2.2a5.orig/pppd/options.c       Sat May 13 12:38:21 1995
1353 +++ ppp-2.2a5/pppd/options.c    Sat May 13 13:59:24 1995
1354 @@ -36,20 +36,21 @@
1355  #include <netinet/in.h>
1356  
1357  #include "pppd.h"
1358  #include "pathnames.h"
1359  #include "patchlevel.h"
1360  #include "fsm.h"
1361  #include "lcp.h"
1362  #include "ipcp.h"
1363  #include "upap.h"
1364  #include "chap.h"
1365 +#include "cbcp.h"
1366  #include "ccp.h"
1367  
1368  #include <net/ppp-comp.h>
1369  
1370  #define FALSE  0
1371  #define TRUE   1
1372  
1373  #if defined(ultrix) || defined(NeXT)
1374  char *strdup __P((char *));
1375  #endif
1376 @@ -112,20 +113,21 @@
1377  static int reqchap __P((void));
1378  static int setspeed __P((char *));
1379  static int noaccomp __P((void));
1380  static int noasyncmap __P((void));
1381  static int noipaddr __P((void));
1382  static int nomagicnumber __P((void));
1383  static int setasyncmap __P((char **));
1384  static int setescape __P((char **));
1385  static int setmru __P((char **));
1386  static int setmtu __P((char **));
1387 +static int setcbcp __P((char **));
1388  static int nomru __P((void));
1389  static int nopcomp __P((void));
1390  static int setconnector __P((char **));
1391  static int setdisconnector __P((char **));
1392  static int setdomain __P((char **));
1393  static int setnetmask __P((char **));
1394  static int setcrtscts __P((void));
1395  static int setnocrtscts __P((void));
1396  static int setxonxoff __P((void));
1397  static int setnodetach __P((void));
1398 @@ -202,20 +204,21 @@
1399      {"connect", 1, setconnector}, /* A program to set up a connection */
1400      {"disconnect", 1, setdisconnector},        /* program to disconnect serial dev. */
1401      {"crtscts", 0, setcrtscts},        /* set h/w flow control */
1402      {"-crtscts", 0, setnocrtscts}, /* clear h/w flow control */
1403      {"xonxoff", 0, setxonxoff},        /* set s/w flow control */
1404      {"debug", 0, setdebug},    /* Increase debugging level */
1405      {"kdebug", 1, setkdebug},  /* Enable kernel-level debugging */
1406      {"domain", 1, setdomain},  /* Add given domain name to hostname*/
1407      {"mru", 1, setmru},                /* Set MRU value for negotiation */
1408      {"mtu", 1, setmtu},                /* Set our MTU */
1409 +    {"cb", 1, setcbcp},                /* Set CBCP */
1410      {"netmask", 1, setnetmask},        /* set netmask */
1411      {"passive", 0, setpassive},        /* Set passive mode */
1412      {"silent", 0, setsilent},  /* Set silent mode */
1413      {"modem", 0, setmodem},    /* Use modem control lines */
1414      {"local", 0, setlocal},    /* Don't use modem control lines */
1415      {"lock", 0, setlock},      /* Lock serial device (with lock file) */
1416      {"name", 1, setname},      /* Set local name for authentication */
1417      {"user", 1, setuser},      /* Set username for PAP auth with peer */
1418      {"usehostname", 0, setusehostname},        /* Must use hostname for auth. */
1419      {"remotename", 1, setremote}, /* Set remote name for authentication */
1420 @@ -775,20 +778,31 @@
1421         return 0;
1422      if (mtu < MINMRU || mtu > MAXMRU) {
1423         fprintf(stderr, "mtu option value of %ld is too %s\n", mtu,
1424                 (mtu < MINMRU? "small": "large"));
1425         return 0;
1426      }
1427      lcp_allowoptions[0].mru = mtu;
1428      return (1);
1429  }
1430  
1431 +static int
1432 +setcbcp(argv)
1433 +    char **argv;
1434 +{
1435 +    lcp_wantoptions[0].neg_cbcp = 1;
1436 +   
1437 +    cbcp[0].us_number = (char *) malloc(strlen(*argv) + 1);
1438 +    strcpy(cbcp[0].us_number, *argv);
1439 +    cbcp[0].us_type |= (1 << CB_CONF_USER);
1440 +    return (1);
1441 +}
1442  
1443  /*
1444   * nopcomp - Disable Protocol field compression negotiation.
1445   */
1446  static int
1447  nopcomp()
1448  {
1449      lcp_wantoptions[0].neg_pcompression = 0;
1450      lcp_allowoptions[0].neg_pcompression = 0;
1451      return (1);
1452 diff -r --unified=10 ppp-2.2a5.orig/pppd/pppd.8 ppp-2.2a5/pppd/pppd.8
1453 --- ppp-2.2a5.orig/pppd/pppd.8  Sat May 13 12:38:21 1995
1454 +++ ppp-2.2a5/pppd/pppd.8       Sat May 13 13:52:26 1995
1455 @@ -221,20 +221,31 @@
1456  .B -pap
1457  Don't agree to authenticate using PAP.
1458  .TP
1459  .B +chap
1460  Require the peer to authenticate itself using CHAP [Cryptographic
1461  Handshake Authentication Protocol] authentication.
1462  .TP
1463  .B -chap
1464  Don't agree to authenticate using CHAP.
1465  .TP
1466 +.B cb \fItelephone_number
1467 +Configure the current execution of pppd to negotiate the \fIclient\fR
1468 +portion of '\fIC\fRall \fIB\fRack \fIC\fRonfiguration
1469 +\fIP\fRrotocol'. The use of this protocol will permit the client to
1470 +authenticate itself with the server and then supply a telephone number
1471 +for the reverse connection. Once the telephone number is accepted, the
1472 +connection will be terminated. You should then wait for the server to
1473 +recall your location and re-authenticate yourself. This second step
1474 +will require a second execution of \fIpppd\fR. This second execution should
1475 +not include the \fIcb\fR option.
1476 +.TP
1477  .B -vj
1478  Disable negotiation of Van Jacobson style IP header compression (use
1479  default, i.e. no compression).
1480  .TP
1481  .B bsdcomp \fInr,nt
1482  Request that the peer compress packets that it sends, using the
1483  BSD-Compress scheme, with a maximum code size of \fInr\fR bits, and
1484  agree to compress packets sent to the peer with a maximum code size of
1485  \fInt\fR bits.  If \fInt\fR is not specified, it defaults to the value
1486  given for \fInr\fR.  Values in the range 9 to 15 may be used for
1487 diff -r --unified=10 ppp-2.2a5.orig/pppd/pppd.h ppp-2.2a5/pppd/pppd.h
1488 --- ppp-2.2a5.orig/pppd/pppd.h  Sat May 13 12:38:21 1995
1489 +++ ppp-2.2a5/pppd/pppd.h       Sat May 13 13:46:36 1995
1490 @@ -85,22 +85,23 @@
1491  extern int     disable_defaultip; /* Don't use hostname for default IP adrs */
1492  extern char    *ipparam;       /* Extra parameter for ip up/down scripts */
1493  extern int     cryptpap;       /* Others' PAP passwords are encrypted */
1494  
1495  /*
1496   * Values for phase.
1497   */
1498  #define PHASE_DEAD             0
1499  #define PHASE_ESTABLISH                1
1500  #define PHASE_AUTHENTICATE     2
1501 -#define PHASE_NETWORK          3
1502 -#define PHASE_TERMINATE                4
1503 +#define PHASE_CALLBACK          3
1504 +#define PHASE_NETWORK          4
1505 +#define PHASE_TERMINATE                5
1506  
1507  /*
1508   * Prototypes.
1509   */
1510  void quit __P((void)); /* Cleanup and exit */
1511  void timeout __P((void (*)(), caddr_t, int));
1512                                 /* Look-alike of kernel's timeout() */
1513  void untimeout __P((void (*)(), caddr_t));
1514                                 /* Look-alike of kernel's untimeout() */
1515  void output __P((int, u_char *, int));