xref: /freebsd/usr.sbin/ppp/cbcp.c (revision 0640d357f29fb1c0daaaffadd0416c5981413afd)
1 /*-
2  * Copyright (c) 1998 Brian Somers <brian@Awfulhak.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  *	$Id: cbcp.c,v 1.6 1998/10/25 23:35:15 brian Exp $
27  */
28 
29 #include <sys/types.h>
30 
31 #include <sys/un.h>
32 
33 #include <string.h>
34 #include <termios.h>
35 
36 #include "defs.h"
37 #include "log.h"
38 #include "timer.h"
39 #include "descriptor.h"
40 #include "lqr.h"
41 #include "mbuf.h"
42 #include "fsm.h"
43 #include "lcp.h"
44 #include "throughput.h"
45 #include "hdlc.h"
46 #include "ccp.h"
47 #include "link.h"
48 #include "async.h"
49 #include "physical.h"
50 #include "lcpproto.h"
51 #include "cbcp.h"
52 #include "mp.h"
53 #include "chat.h"
54 #include "auth.h"
55 #include "chap.h"
56 #include "datalink.h"
57 
58 void
59 cbcp_Init(struct cbcp *cbcp, struct physical *p)
60 {
61   cbcp->required = 0;
62   cbcp->fsm.state = CBCP_CLOSED;
63   cbcp->fsm.id = 0;
64   cbcp->fsm.delay = 0;
65   *cbcp->fsm.phone = '\0';
66   memset(&cbcp->fsm.timer, '\0', sizeof cbcp->fsm.timer);
67   cbcp->p = p;
68 }
69 
70 static void cbcp_SendReq(struct cbcp *);
71 static void cbcp_SendResponse(struct cbcp *);
72 static void cbcp_SendAck(struct cbcp *);
73 
74 static void
75 cbcp_Timeout(void *v)
76 {
77   struct cbcp *cbcp = (struct cbcp *)v;
78 
79   timer_Stop(&cbcp->fsm.timer);
80   if (cbcp->fsm.restart) {
81     switch (cbcp->fsm.state) {
82       case CBCP_CLOSED:
83       case CBCP_STOPPED:
84         log_Printf(LogCBCP, "%s: Urk - unexpected CBCP timeout !\n",
85                    cbcp->p->dl->name);
86         break;
87 
88       case CBCP_REQSENT:
89         cbcp_SendReq(cbcp);
90         break;
91       case CBCP_RESPSENT:
92         cbcp_SendResponse(cbcp);
93         break;
94       case CBCP_ACKSENT:
95         cbcp_SendAck(cbcp);
96         break;
97     }
98   } else {
99     const char *missed;
100 
101     switch (cbcp->fsm.state) {
102       case CBCP_STOPPED:
103         missed = "REQ";
104         break;
105       case CBCP_REQSENT:
106         missed = "RESPONSE";
107         break;
108       case CBCP_RESPSENT:
109         missed = "ACK";
110         break;
111       case CBCP_ACKSENT:
112         missed = "Terminate REQ";
113         break;
114       default:
115         log_Printf(LogCBCP, "%s: Urk - unexpected CBCP timeout !\n",
116                    cbcp->p->dl->name);
117         missed = NULL;
118         break;
119     }
120     if (missed)
121       log_Printf(LogCBCP, "%s: Timeout waiting for peer %s\n",
122                  cbcp->p->dl->name, missed);
123     datalink_CBCPFailed(cbcp->p->dl);
124   }
125 }
126 
127 static void
128 cbcp_StartTimer(struct cbcp *cbcp, int timeout)
129 {
130   timer_Stop(&cbcp->fsm.timer);
131   cbcp->fsm.timer.func = cbcp_Timeout;
132   cbcp->fsm.timer.name = "cbcp";
133   cbcp->fsm.timer.load = timeout * SECTICKS;
134   cbcp->fsm.timer.arg = cbcp;
135   timer_Start(&cbcp->fsm.timer);
136 }
137 
138 #define CBCP_CLOSED	(0)	/* Not in use */
139 #define CBCP_STOPPED	(1)	/* Waiting for a REQ */
140 #define CBCP_REQSENT	(2)	/* Waiting for a RESP */
141 #define CBCP_RESPSENT	(3)	/* Waiting for an ACK */
142 #define CBCP_ACKSENT	(4)	/* Waiting for an LCP Term REQ */
143 
144 static const char *cbcpname[] = {
145   "closed", "stopped", "req-sent", "resp-sent", "ack-sent"
146 };
147 
148 static const char *
149 cbcpstate(int s)
150 {
151   if (s < sizeof cbcpname / sizeof cbcpname[0])
152     return cbcpname[s];
153   return "???";
154 }
155 
156 static void
157 cbcp_NewPhase(struct cbcp *cbcp, int new)
158 {
159   if (cbcp->fsm.state != new) {
160     log_Printf(LogCBCP, "%s: State change %s --> %s\n", cbcp->p->dl->name,
161                cbcpstate(cbcp->fsm.state), cbcpstate(new));
162     cbcp->fsm.state = new;
163   }
164 }
165 
166 struct cbcp_header {
167   u_char code;
168   u_char id;
169   u_int16_t length;	/* Network byte order */
170 };
171 
172 
173 /* cbcp_header::code values */
174 #define CBCP_REQ	(1)
175 #define CBCP_RESPONSE	(2)
176 #define CBCP_ACK	(3)
177 
178 struct cbcp_data {
179   u_char type;
180   u_char length;
181   u_char delay;
182   char addr_start[253];	/* max cbcp_data length 255 + 1 for NULL */
183 };
184 
185 /* cbcp_data::type values */
186 #define CBCP_NONUM	(1)
187 #define CBCP_CLIENTNUM	(2)
188 #define CBCP_SERVERNUM	(3)
189 #define CBCP_LISTNUM	(4)
190 
191 static void
192 cbcp_Output(struct cbcp *cbcp, u_char code, struct cbcp_data *data)
193 {
194   struct cbcp_header *head;
195   struct mbuf *bp;
196 
197   bp = mbuf_Alloc(sizeof *head + data->length, MB_CBCP);
198   head = (struct cbcp_header *)MBUF_CTOP(bp);
199   head->code = code;
200   head->id = cbcp->fsm.id;
201   head->length = htons(sizeof *head + data->length);
202   memcpy(MBUF_CTOP(bp) + sizeof *head, data, data->length);
203   log_DumpBp(LogDEBUG, "cbcp_Output", bp);
204   hdlc_Output(&cbcp->p->link, PRI_LINK, PROTO_CBCP, bp);
205 }
206 
207 static const char *
208 cbcp_data_Type(int type)
209 {
210   static const char *types[] = {
211     "No callback", "User-spec", "Server-spec", "list"
212   };
213 
214   if (type < 1 || type > sizeof types / sizeof types[0])
215     return "???";
216   return types[type-1];
217 }
218 
219 struct cbcp_addr {
220   u_char type;
221   char addr[1];		/* Really ASCIIZ */
222 };
223 
224 /* cbcp_data::type values */
225 #define CBCP_ADDR_PSTN	(1)
226 
227 static void
228 cbcp_data_Show(struct cbcp_data *data)
229 {
230   struct cbcp_addr *addr;
231   char *end;
232 
233   addr = (struct cbcp_addr *)data->addr_start;
234   end = (char *)data + data->length;
235   *end = '\0';
236 
237   log_Printf(LogCBCP, " TYPE %s\n", cbcp_data_Type(data->type));
238   if ((char *)&data->delay < end) {
239     log_Printf(LogCBCP, " DELAY %d\n", data->delay);
240     while (addr->addr < end) {
241       if (addr->type == CBCP_ADDR_PSTN)
242         log_Printf(LogCBCP, " ADDR %s\n", addr->addr);
243       else
244         log_Printf(LogCBCP, " ADDR type %d ??\n", (int)addr->type);
245       addr = (struct cbcp_addr *)(addr->addr + strlen(addr->addr) + 1);
246     }
247   }
248 }
249 
250 static void
251 cbcp_SendReq(struct cbcp *cbcp)
252 {
253   struct cbcp_data data;
254   struct cbcp_addr *addr;
255   char list[sizeof cbcp->fsm.phone], *next;
256   int len, max;
257 
258   /* Only callees send REQs */
259 
260   log_Printf(LogCBCP, "%s: SendReq(%d) state = %s\n", cbcp->p->dl->name,
261              cbcp->fsm.id, cbcpstate(cbcp->fsm.state));
262   data.type = cbcp->fsm.type;
263   data.delay = 0;
264   strncpy(list, cbcp->fsm.phone, sizeof list - 1);
265   list[sizeof list - 1] = '\0';
266 
267   switch (data.type) {
268     case CBCP_CLIENTNUM:
269       addr = (struct cbcp_addr *)data.addr_start;
270       addr->type = CBCP_ADDR_PSTN;
271       *addr->addr = '\0';
272       data.length = addr->addr - (char *)&data;
273       break;
274 
275     case CBCP_LISTNUM:
276       addr = (struct cbcp_addr *)data.addr_start;
277       for (next = strtok(list, ","); next; next = strtok(NULL, ",")) {
278         len = strlen(next);
279         max = data.addr_start + sizeof data.addr_start - addr->addr - 1;
280         if (len <= max) {
281           addr->type = CBCP_ADDR_PSTN;
282           strcpy(addr->addr, next);
283           addr = (struct cbcp_addr *)((char *)addr + len + 2);
284         } else
285           log_Printf(LogWARN, "CBCP ADDR \"%s\" skipped - packet too large\n",
286                      next);
287       }
288       data.length = (char *)addr - (char *)&data;
289       break;
290 
291     case CBCP_SERVERNUM:
292       data.length = data.addr_start - (char *)&data;
293       break;
294 
295     default:
296       data.length = (char *)&data.delay - (char *)&data;
297       break;
298   }
299 
300   cbcp_data_Show(&data);
301   cbcp_Output(cbcp, CBCP_REQ, &data);
302   cbcp->fsm.restart--;
303   cbcp_StartTimer(cbcp, cbcp->fsm.delay);
304   cbcp_NewPhase(cbcp, CBCP_REQSENT);		/* Wait for a RESPONSE */
305 }
306 
307 void
308 cbcp_Up(struct cbcp *cbcp)
309 {
310   struct lcp *lcp = &cbcp->p->link.lcp;
311 
312   cbcp->fsm.delay = cbcp->p->dl->cfg.cbcp.delay;
313   if (*cbcp->p->dl->peer.authname == '\0' ||
314       !auth_SetPhoneList(cbcp->p->dl->peer.authname, cbcp->fsm.phone,
315                          sizeof cbcp->fsm.phone)) {
316     strncpy(cbcp->fsm.phone, cbcp->p->dl->cfg.cbcp.phone,
317             sizeof cbcp->fsm.phone - 1);
318     cbcp->fsm.phone[sizeof cbcp->fsm.phone - 1] = '\0';
319   }
320 
321   if (lcp->want_callback.opmask) {
322     if (*cbcp->fsm.phone == '\0')
323       cbcp->fsm.type = CBCP_NONUM;
324     else if (!strcmp(cbcp->fsm.phone, "*")) {
325       cbcp->fsm.type = CBCP_SERVERNUM;
326       *cbcp->fsm.phone = '\0';
327     } else
328       cbcp->fsm.type = CBCP_CLIENTNUM;
329     cbcp_NewPhase(cbcp, CBCP_STOPPED);		/* Wait for a REQ */
330     cbcp_StartTimer(cbcp, cbcp->fsm.delay * DEF_REQs);
331   } else {
332     if (*cbcp->fsm.phone == '\0')
333       cbcp->fsm.type = CBCP_NONUM;
334     else if (!strcmp(cbcp->fsm.phone, "*")) {
335       cbcp->fsm.type = CBCP_CLIENTNUM;
336       *cbcp->fsm.phone = '\0';
337     } else if (strchr(cbcp->fsm.phone, ','))
338       cbcp->fsm.type = CBCP_LISTNUM;
339     else
340       cbcp->fsm.type = CBCP_SERVERNUM;
341     cbcp->fsm.restart = DEF_REQs;
342     cbcp_SendReq(cbcp);
343   }
344 }
345 
346 static int
347 cbcp_AdjustResponse(struct cbcp *cbcp, struct cbcp_data *data)
348 {
349   /*
350    * We've received a REQ (data).  Adjust our reponse (cbcp->fsm.*)
351    * so that we (hopefully) agree with the peer
352    */
353   struct cbcp_addr *addr;
354 
355   switch (data->type) {
356     case CBCP_NONUM:
357       /*
358        * If the callee offers no callback, we send our desired response
359        * anyway.  This is what Win95 does - although I can't find this
360        * behaviour documented in the spec....
361        */
362       return 1;
363 
364     case CBCP_CLIENTNUM:
365       if (cbcp->fsm.type == CBCP_CLIENTNUM) {
366         char *ptr;
367 
368         if (data->length > data->addr_start - (char *)data) {
369           /*
370            * The peer has given us an address type spec - make sure we
371            * understand !
372            */
373           addr = (struct cbcp_addr *)data->addr_start;
374           if (addr->type != CBCP_ADDR_PSTN) {
375             log_Printf(LogPHASE, "CBCP: Unrecognised address type %d !\n",
376                        (int)addr->type);
377             return 0;
378           }
379         }
380         /* we accept the REQ even if the peer didn't specify an addr->type */
381         ptr = strchr(cbcp->fsm.phone, ',');
382         if (ptr)
383           *ptr = '\0';		/* Just use the first number in our list */
384         return 1;
385       }
386       log_Printf(LogPHASE, "CBCP: no number to pass to the peer !\n");
387       return 0;
388 
389     case CBCP_SERVERNUM:
390       if (cbcp->fsm.type == CBCP_SERVERNUM) {
391         *cbcp->fsm.phone = '\0';
392         return 1;
393       }
394       if (data->length > data->addr_start - (char *)data) {
395         /*
396          * This violates the spec, but if the peer has told us the
397          * number it wants to call back, take advantage of this fact
398          * and allow things to proceed if we've specified the same
399          * number
400          */
401         addr = (struct cbcp_addr *)data->addr_start;
402         if (addr->type != CBCP_ADDR_PSTN) {
403           log_Printf(LogPHASE, "CBCP: Unrecognised address type %d !\n",
404                      (int)addr->type);
405           return 0;
406         } else if (cbcp->fsm.type == CBCP_CLIENTNUM) {
407           /*
408            * If the peer's insisting on deciding the number, make sure
409            * it's one of the ones in our list.  If it is, let the peer
410            * think it's in control :-)
411            */
412           char list[sizeof cbcp->fsm.phone], *next;
413 
414           strncpy(list, cbcp->fsm.phone, sizeof list - 1);
415           list[sizeof list - 1] = '\0';
416           for (next = strtok(list, ","); next; next = strtok(NULL, ","))
417             if (!strcmp(next, addr->addr)) {
418               cbcp->fsm.type = CBCP_SERVERNUM;
419               strcpy(cbcp->fsm.phone, next);
420               return 1;
421             }
422         }
423       }
424       log_Printf(LogPHASE, "CBCP: Peer won't allow local decision !\n");
425       return 0;
426 
427     case CBCP_LISTNUM:
428       if (cbcp->fsm.type == CBCP_CLIENTNUM || cbcp->fsm.type == CBCP_LISTNUM) {
429         /*
430          * Search through ``data''s addresses and see if cbcp->fsm.phone
431          * contains any of them
432          */
433         char list[sizeof cbcp->fsm.phone], *next, *end;
434 
435         addr = (struct cbcp_addr *)data->addr_start;
436         end = (char *)data + data->length;
437 
438         while (addr->addr < end) {
439           if (addr->type == CBCP_ADDR_PSTN) {
440             strncpy(list, cbcp->fsm.phone, sizeof list - 1);
441             list[sizeof list - 1] = '\0';
442             for (next = strtok(list, ","); next; next = strtok(NULL, ","))
443               if (!strcmp(next, addr->addr)) {
444                 cbcp->fsm.type = CBCP_LISTNUM;
445                 strcpy(cbcp->fsm.phone, next);
446                 return 1;
447               }
448           } else
449             log_Printf(LogCBCP, "Warning: Unrecognised address type %d !\n",
450                        (int)addr->type);
451           addr = (struct cbcp_addr *)(addr->addr + strlen(addr->addr) + 1);
452         }
453       }
454       log_Printf(LogPHASE, "CBCP: no good number to pass to the peer !\n");
455       return 0;
456   }
457 
458   log_Printf(LogCBCP, "Unrecognised REQ type %d !\n", (int)data->type);
459   return 0;
460 }
461 
462 static void
463 cbcp_SendResponse(struct cbcp *cbcp)
464 {
465   struct cbcp_data data;
466   struct cbcp_addr *addr;
467 
468   /* Only callers send RESPONSEs */
469 
470   log_Printf(LogCBCP, "%s: SendResponse(%d) state = %s\n", cbcp->p->dl->name,
471              cbcp->fsm.id, cbcpstate(cbcp->fsm.state));
472 
473   data.type = cbcp->fsm.type;
474   data.delay = cbcp->fsm.delay;
475   addr = (struct cbcp_addr *)data.addr_start;
476   if (data.type == CBCP_NONUM)
477     data.length = (char *)&data.delay - (char *)&data;
478   else if (*cbcp->fsm.phone) {
479     addr->type = CBCP_ADDR_PSTN;
480     strcpy(addr->addr, cbcp->fsm.phone);
481     data.length = (addr->addr + strlen(addr->addr) + 1) - (char *)&data;
482   } else
483     data.length = data.addr_start - (char *)&data;
484 
485   cbcp_data_Show(&data);
486   cbcp_Output(cbcp, CBCP_RESPONSE, &data);
487   cbcp->fsm.restart--;
488   cbcp_StartTimer(cbcp, cbcp->fsm.delay);
489   cbcp_NewPhase(cbcp, CBCP_RESPSENT);	/* Wait for an ACK */
490 }
491 
492 /* What to do after checking an incoming response */
493 #define CBCP_ACTION_DOWN (0)
494 #define CBCP_ACTION_REQ (1)
495 #define CBCP_ACTION_ACK (2)
496 
497 static int
498 cbcp_CheckResponse(struct cbcp *cbcp, struct cbcp_data *data)
499 {
500   /*
501    * We've received a RESPONSE (data).  Check if it agrees with
502    * our REQ (cbcp->fsm)
503    */
504   struct cbcp_addr *addr;
505 
506   addr = (struct cbcp_addr *)data->addr_start;
507 
508   if (data->type == cbcp->fsm.type) {
509     switch (cbcp->fsm.type) {
510       case CBCP_NONUM:
511         return CBCP_ACTION_ACK;
512 
513       case CBCP_CLIENTNUM:
514         if ((char *)data + data->length <= addr->addr)
515           log_Printf(LogPHASE, "CBCP: peer didn't respond with a number !\n");
516         else if (addr->type != CBCP_ADDR_PSTN)
517           log_Printf(LogPHASE, "CBCP: Unrecognised address type %d !\n",
518                      addr->type);
519         else {
520           strcpy(cbcp->fsm.phone, addr->addr);
521           cbcp->fsm.delay = data->delay;
522           return CBCP_ACTION_ACK;
523         }
524         return CBCP_ACTION_DOWN;
525 
526       case CBCP_SERVERNUM:
527         cbcp->fsm.delay = data->delay;
528         return CBCP_ACTION_ACK;
529 
530       case CBCP_LISTNUM:
531         if ((char *)data + data->length <= addr->addr)
532           log_Printf(LogPHASE, "CBCP: peer didn't respond with a number !\n");
533         else if (addr->type != CBCP_ADDR_PSTN)
534           log_Printf(LogPHASE, "CBCP: Unrecognised address type %d !\n",
535                      addr->type);
536         else {
537           char list[sizeof cbcp->fsm.phone], *next;
538 
539           strncpy(list, cbcp->fsm.phone, sizeof list - 1);
540           list[sizeof list - 1] = '\0';
541           for (next = strtok(list, ","); next; next = strtok(NULL, ","))
542             if (!strcmp(addr->addr, next)) {
543               strcpy(cbcp->fsm.phone, next);
544               cbcp->fsm.delay = data->delay;
545               return CBCP_ACTION_ACK;
546             }
547           log_Printf(LogPHASE, "CBCP: peer didn't respond with a "
548                      "valid number !\n");
549         }
550         return CBCP_ACTION_DOWN;
551     }
552     log_Printf(LogPHASE, "Internal CBCP error - agreed on %d ??!?\n",
553                (int)cbcp->fsm.type);
554     return CBCP_ACTION_DOWN;
555   } else if (data->type == CBCP_NONUM && cbcp->fsm.type == CBCP_CLIENTNUM) {
556     /*
557      * Client doesn't want CBCP after all....
558      * We only allow this when ``set cbcp *'' has been specified.
559      */
560     cbcp->fsm.type = CBCP_NONUM;
561     return CBCP_ACTION_ACK;
562   }
563   log_Printf(LogCBCP, "Invalid peer RESPONSE\n");
564   return CBCP_ACTION_REQ;
565 }
566 
567 static void
568 cbcp_SendAck(struct cbcp *cbcp)
569 {
570   struct cbcp_data data;
571   char *end;
572 
573   /* Only callees send ACKs */
574 
575   log_Printf(LogCBCP, "%s: SendAck(%d) state = %s\n", cbcp->p->dl->name,
576              cbcp->fsm.id, cbcpstate(cbcp->fsm.state));
577 
578   data.type = cbcp->fsm.type;
579   data.delay = cbcp->fsm.delay;
580   end = data.type == CBCP_NONUM ? (char *)&data.delay : data.addr_start;
581   data.length = end - (char *)&data;
582 
583   cbcp_data_Show(&data);
584   cbcp_Output(cbcp, CBCP_ACK, &data);
585   cbcp->fsm.restart--;
586   cbcp_StartTimer(cbcp, cbcp->fsm.delay);
587   cbcp_NewPhase(cbcp, CBCP_ACKSENT);	/* Wait for an ACK */
588 }
589 
590 void
591 cbcp_Input(struct physical *p, struct mbuf *bp)
592 {
593   struct cbcp_header *head;
594   struct cbcp_data *data;
595   struct cbcp *cbcp = &p->dl->cbcp;
596   int len;
597 
598   len = mbuf_Length(bp);
599   if (len < sizeof(struct cbcp_header)) {
600     mbuf_Free(bp);
601     return;
602   }
603   head = (struct cbcp_header *)MBUF_CTOP(bp);
604   if (ntohs(head->length) != len) {
605     log_Printf(LogWARN, "Corrupt CBCP packet (code %d, length %d not %d)"
606                " - ignored\n", head->code, ntohs(head->length), len);
607     mbuf_Free(bp);
608     return;
609   }
610 
611   /* XXX check the id */
612 
613   bp->offset += sizeof(struct cbcp_header);
614   bp->cnt -= sizeof(struct cbcp_header);
615   data = (struct cbcp_data *)MBUF_CTOP(bp);
616 
617   switch (head->code) {
618     case CBCP_REQ:
619       log_Printf(LogCBCP, "%s: RecvReq(%d) state = %s\n",
620                  p->dl->name, head->id, cbcpstate(cbcp->fsm.state));
621       cbcp_data_Show(data);
622       if (cbcp->fsm.state == CBCP_STOPPED || cbcp->fsm.state == CBCP_RESPSENT) {
623         timer_Stop(&cbcp->fsm.timer);
624         if (cbcp_AdjustResponse(cbcp, data)) {
625           cbcp->fsm.restart = DEF_REQs;
626           cbcp->fsm.id = head->id;
627           cbcp_SendResponse(cbcp);
628         } else
629           datalink_CBCPFailed(cbcp->p->dl);
630       } else
631         log_Printf(LogCBCP, "%s: unexpected REQ dropped\n", p->dl->name);
632       break;
633 
634     case CBCP_RESPONSE:
635       log_Printf(LogCBCP, "%s: RecvResponse(%d) state = %s\n",
636 	         p->dl->name, head->id, cbcpstate(cbcp->fsm.state));
637       cbcp_data_Show(data);
638       if (cbcp->fsm.id != head->id) {
639         log_Printf(LogCBCP, "Warning: Expected id was %d, not %d\n",
640                    cbcp->fsm.id, head->id);
641         cbcp->fsm.id = head->id;
642       }
643       if (cbcp->fsm.state == CBCP_REQSENT || cbcp->fsm.state == CBCP_ACKSENT) {
644         timer_Stop(&cbcp->fsm.timer);
645         switch (cbcp_CheckResponse(cbcp, data)) {
646           case CBCP_ACTION_REQ:
647             cbcp_SendReq(cbcp);
648             break;
649 
650           case CBCP_ACTION_ACK:
651             cbcp->fsm.restart = DEF_REQs;
652             cbcp_SendAck(cbcp);
653             if (cbcp->fsm.type == CBCP_NONUM) {
654               /*
655                * Don't change state in case the peer doesn't get our ACK,
656                * just bring the layer up.
657                */
658               timer_Stop(&cbcp->fsm.timer);
659               datalink_NCPUp(cbcp->p->dl);
660             }
661             break;
662 
663           default:
664             datalink_CBCPFailed(cbcp->p->dl);
665             break;
666         }
667       } else
668         log_Printf(LogCBCP, "%s: unexpected RESPONSE dropped\n", p->dl->name);
669       break;
670 
671     case CBCP_ACK:
672       log_Printf(LogCBCP, "%s: RecvAck(%d) state = %s\n",
673 	         p->dl->name, head->id, cbcpstate(cbcp->fsm.state));
674       cbcp_data_Show(data);
675       if (cbcp->fsm.id != head->id) {
676         log_Printf(LogCBCP, "Warning: Expected id was %d, not %d\n",
677                    cbcp->fsm.id, head->id);
678         cbcp->fsm.id = head->id;
679       }
680       if (cbcp->fsm.state == CBCP_RESPSENT) {
681         timer_Stop(&cbcp->fsm.timer);
682         datalink_CBCPComplete(cbcp->p->dl);
683         log_Printf(LogPHASE, "%s: CBCP: Peer will dial back\n", p->dl->name);
684       } else
685         log_Printf(LogCBCP, "%s: unexpected ACK dropped\n", p->dl->name);
686       break;
687 
688     default:
689       log_Printf(LogWARN, "Unrecognised CBCP packet (code %d, length %d)\n",
690                head->code, len);
691       break;
692   }
693 
694   mbuf_Free(bp);
695 }
696 
697 void
698 cbcp_Down(struct cbcp *cbcp)
699 {
700   timer_Stop(&cbcp->fsm.timer);
701   cbcp_NewPhase(cbcp, CBCP_CLOSED);
702   cbcp->required = 0;
703 }
704 
705 void
706 cbcp_ReceiveTerminateReq(struct physical *p)
707 {
708   if (p->dl->cbcp.fsm.state == CBCP_ACKSENT) {
709     /* Don't change our state in case the peer doesn't get the ACK */
710     p->dl->cbcp.required = 1;
711     log_Printf(LogPHASE, "%s: CBCP: Will dial back on %s\n", p->dl->name,
712                p->dl->cbcp.fsm.phone);
713   } else
714     cbcp_NewPhase(&p->dl->cbcp, CBCP_CLOSED);
715 }
716