xref: /freebsd/usr.sbin/ppp/cbcp.c (revision a8445737e740901f5f2c8d24c12ef7fc8b00134e)
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.1 1998/08/07 18:44:16 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 = 2;
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       if (cbcp->fsm.type == CBCP_NONUM)
358           return 1;
359       log_Printf(LogPHASE, "CBCP: server wants no callback !\n");
360       return 0;
361 
362     case CBCP_CLIENTNUM:
363       if (cbcp->fsm.type == CBCP_CLIENTNUM) {
364         char *ptr;
365 
366         if (data->length > data->addr_start - (char *)data) {
367           /*
368            * The peer has given us an address type spec - make sure we
369            * understand !
370            */
371           addr = (struct cbcp_addr *)data->addr_start;
372           if (addr->type != CBCP_ADDR_PSTN) {
373             log_Printf(LogPHASE, "CBCP: Unrecognised address type %d !\n",
374                        (int)addr->type);
375             return 0;
376           }
377         }
378         /* we accept the REQ even if the peer didn't specify an addr->type */
379         ptr = strchr(cbcp->fsm.phone, ',');
380         if (ptr)
381           *ptr = '\0';		/* Just use the first number in our list */
382         return 1;
383       }
384       log_Printf(LogPHASE, "CBCP: no number to pass to the peer !\n");
385       return 0;
386 
387     case CBCP_SERVERNUM:
388       if (cbcp->fsm.type == CBCP_SERVERNUM) {
389         *cbcp->fsm.phone = '\0';
390         return 1;
391       }
392       if (data->length > data->addr_start - (char *)data) {
393         /*
394          * This violates the spec, but if the peer has told us the
395          * number it wants to call back, take advantage of this fact
396          * and allow things to proceed if we've specified the same
397          * number
398          */
399         addr = (struct cbcp_addr *)data->addr_start;
400         if (addr->type != CBCP_ADDR_PSTN) {
401           log_Printf(LogPHASE, "CBCP: Unrecognised address type %d !\n",
402                      (int)addr->type);
403           return 0;
404         } else if (cbcp->fsm.type == CBCP_CLIENTNUM) {
405           /*
406            * If the peer's insisting on deciding the number, make sure
407            * it's one of the ones in our list.  If it is, let the peer
408            * think it's in control :-)
409            */
410           char list[sizeof cbcp->fsm.phone], *next;
411 
412           strncpy(list, cbcp->fsm.phone, sizeof list - 1);
413           list[sizeof list - 1] = '\0';
414           for (next = strtok(list, ","); next; next = strtok(NULL, ","))
415             if (!strcmp(next, addr->addr)) {
416               cbcp->fsm.type = CBCP_SERVERNUM;
417               strcpy(cbcp->fsm.phone, next);
418               return 1;
419             }
420         }
421       }
422       log_Printf(LogPHASE, "CBCP: Peer won't allow local decision !\n");
423       return 0;
424 
425     case CBCP_LISTNUM:
426       if (cbcp->fsm.type == CBCP_CLIENTNUM || cbcp->fsm.type == CBCP_LISTNUM) {
427         /*
428          * Search through ``data''s addresses and see if cbcp->fsm.phone
429          * contains any of them
430          */
431         char list[sizeof cbcp->fsm.phone], *next, *end;
432 
433         addr = (struct cbcp_addr *)data->addr_start;
434         end = (char *)data + data->length;
435 
436         while (addr->addr < end) {
437           if (addr->type == CBCP_ADDR_PSTN) {
438             strncpy(list, cbcp->fsm.phone, sizeof list - 1);
439             list[sizeof list - 1] = '\0';
440             for (next = strtok(list, ","); next; next = strtok(NULL, ","))
441               if (!strcmp(next, addr->addr)) {
442                 cbcp->fsm.type = CBCP_LISTNUM;
443                 strcpy(cbcp->fsm.phone, next);
444                 return 1;
445               }
446           } else
447             log_Printf(LogCBCP, "Warning: Unrecognised address type %d !\n",
448                        (int)addr->type);
449           addr = (struct cbcp_addr *)(addr->addr + strlen(addr->addr) + 1);
450         }
451       }
452       log_Printf(LogPHASE, "CBCP: no good number to pass to the peer !\n");
453       return 0;
454   }
455 
456   log_Printf(LogCBCP, "Unrecognised REQ type %d !\n", (int)data->type);
457   return 0;
458 }
459 
460 static void
461 cbcp_SendResponse(struct cbcp *cbcp)
462 {
463   struct cbcp_data data;
464   struct cbcp_addr *addr;
465 
466   /* Only callers send RESPONSEs */
467 
468   log_Printf(LogCBCP, "%s: SendResponse(%d) state = %s\n", cbcp->p->dl->name,
469              cbcp->fsm.id, cbcpstate(cbcp->fsm.state));
470 
471   data.type = cbcp->fsm.type;
472   data.delay = cbcp->fsm.delay;
473   addr = (struct cbcp_addr *)data.addr_start;
474   if (*cbcp->fsm.phone) {
475     addr->type = CBCP_ADDR_PSTN;
476     strcpy(addr->addr, cbcp->fsm.phone);
477     data.length = (addr->addr + strlen(addr->addr) + 1) - (char *)&data;
478   } else
479     data.length = data.addr_start - (char *)&data;
480 
481   cbcp_data_Show(&data);
482   cbcp_Output(cbcp, CBCP_RESPONSE, &data);
483   cbcp->fsm.restart--;
484   cbcp_StartTimer(cbcp, cbcp->fsm.delay);
485   cbcp_NewPhase(cbcp, CBCP_RESPSENT);	/* Wait for an ACK */
486 }
487 
488 /* What to do after checking an incoming response */
489 #define CBCP_ACTION_DOWN (0)
490 #define CBCP_ACTION_REQ (1)
491 #define CBCP_ACTION_ACK (2)
492 
493 static int
494 cbcp_CheckResponse(struct cbcp *cbcp, struct cbcp_data *data)
495 {
496   /*
497    * We've received a RESPONSE (data).  Check if it agrees with
498    * our REQ (cbcp->fsm)
499    */
500   struct cbcp_addr *addr;
501 
502   addr = (struct cbcp_addr *)data->addr_start;
503 
504   if (data->type == cbcp->fsm.type) {
505     switch (cbcp->fsm.type) {
506       case CBCP_NONUM:
507         return CBCP_ACTION_ACK;
508 
509       case CBCP_CLIENTNUM:
510         if ((char *)data + data->length <= addr->addr)
511           log_Printf(LogPHASE, "CBCP: peer didn't respond with a number !\n");
512         else if (addr->type != CBCP_ADDR_PSTN)
513           log_Printf(LogPHASE, "CBCP: Unrecognised address type %d !\n",
514                      addr->type);
515         else {
516           strcpy(cbcp->fsm.phone, addr->addr);
517           cbcp->fsm.delay = data->delay;
518           return CBCP_ACTION_ACK;
519         }
520         return CBCP_ACTION_DOWN;
521 
522       case CBCP_SERVERNUM:
523         cbcp->fsm.delay = data->delay;
524         return CBCP_ACTION_ACK;
525 
526       case CBCP_LISTNUM:
527         if ((char *)data + data->length <= addr->addr)
528           log_Printf(LogPHASE, "CBCP: peer didn't respond with a number !\n");
529         else if (addr->type != CBCP_ADDR_PSTN)
530           log_Printf(LogPHASE, "CBCP: Unrecognised address type %d !\n",
531                      addr->type);
532         else {
533           char list[sizeof cbcp->fsm.phone], *next;
534 
535           strncpy(list, cbcp->fsm.phone, sizeof list - 1);
536           list[sizeof list - 1] = '\0';
537           for (next = strtok(list, ","); next; next = strtok(NULL, ","))
538             if (!strcmp(addr->addr, next)) {
539               strcpy(cbcp->fsm.phone, next);
540               cbcp->fsm.delay = data->delay;
541               return CBCP_ACTION_ACK;
542             }
543           log_Printf(LogPHASE, "CBCP: peer didn't respond with a "
544                      "valid number !\n");
545         }
546         return CBCP_ACTION_DOWN;
547     }
548     log_Printf(LogPHASE, "Internal CBCP error - agreed on %d ??!?\n",
549                (int)cbcp->fsm.type);
550     return CBCP_ACTION_DOWN;
551   }
552   log_Printf(LogCBCP, "Invalid peer RESPONSE\n");
553   return CBCP_ACTION_REQ;
554 }
555 
556 static void
557 cbcp_SendAck(struct cbcp *cbcp)
558 {
559   struct cbcp_data data;
560 
561   /* Only callees send ACKs */
562 
563   log_Printf(LogCBCP, "%s: SendAck(%d) state = %s\n", cbcp->p->dl->name,
564              cbcp->fsm.id, cbcpstate(cbcp->fsm.state));
565 
566   data.type = cbcp->fsm.type;
567   data.delay = cbcp->fsm.delay;
568   data.length = data.addr_start - (char *)&data;
569 
570   cbcp_data_Show(&data);
571   cbcp_Output(cbcp, CBCP_ACK, &data);
572   cbcp->fsm.restart--;
573   cbcp_StartTimer(cbcp, cbcp->fsm.delay);
574   cbcp_NewPhase(cbcp, CBCP_ACKSENT);	/* Wait for an ACK */
575 }
576 
577 void
578 cbcp_Input(struct physical *p, struct mbuf *bp)
579 {
580   struct cbcp_header *head;
581   struct cbcp_data *data;
582   struct cbcp *cbcp = &p->dl->cbcp;
583   int len;
584 
585   len = mbuf_Length(bp);
586   if (len < sizeof(struct cbcp_header)) {
587     mbuf_Free(bp);
588     return;
589   }
590   head = (struct cbcp_header *)MBUF_CTOP(bp);
591   if (ntohs(head->length) != len) {
592     log_Printf(LogWARN, "Corrupt CBCP packet (code %d, length %d not %d)"
593                " - ignored\n", head->code, ntohs(head->length), len);
594     mbuf_Free(bp);
595     return;
596   }
597 
598   /* XXX check the id */
599 
600   bp->offset += sizeof(struct cbcp_header);
601   bp->cnt -= sizeof(struct cbcp_header);
602   data = (struct cbcp_data *)MBUF_CTOP(bp);
603 
604   switch (head->code) {
605     case CBCP_REQ:
606       log_Printf(LogCBCP, "%s: RecvReq(%d) state = %s\n",
607                  p->dl->name, head->id, cbcpstate(cbcp->fsm.state));
608       cbcp_data_Show(data);
609       if (cbcp->fsm.state == CBCP_STOPPED || cbcp->fsm.state == CBCP_RESPSENT) {
610         timer_Stop(&cbcp->fsm.timer);
611         if (cbcp_AdjustResponse(cbcp, data)) {
612           cbcp->fsm.restart = DEF_REQs;
613           cbcp_SendResponse(cbcp);
614         } else
615           datalink_CBCPFailed(cbcp->p->dl);
616       } else
617         log_Printf(LogCBCP, "%s: unexpected REQ dropped\n", p->dl->name);
618       break;
619 
620     case CBCP_RESPONSE:
621       log_Printf(LogCBCP, "%s: RecvResponse(%d) state = %s\n",
622 	         p->dl->name, head->id, cbcpstate(cbcp->fsm.state));
623       cbcp_data_Show(data);
624       if (cbcp->fsm.state == CBCP_REQSENT || cbcp->fsm.state == CBCP_ACKSENT) {
625         timer_Stop(&cbcp->fsm.timer);
626         switch (cbcp_CheckResponse(cbcp, data)) {
627           case CBCP_ACTION_REQ:
628             cbcp_SendReq(cbcp);
629             break;
630 
631           case CBCP_ACTION_ACK:
632             cbcp->fsm.restart = DEF_REQs;
633             cbcp_SendAck(cbcp);
634             if (cbcp->fsm.type == CBCP_NONUM) {
635               /*
636                * Don't change state in case the peer doesn't get our ACK,
637                * just bring the layer up.
638                */
639               timer_Stop(&cbcp->fsm.timer);
640               datalink_NCPUp(cbcp->p->dl);
641             }
642             break;
643 
644           default:
645             datalink_CBCPFailed(cbcp->p->dl);
646             break;
647         }
648       } else
649         log_Printf(LogCBCP, "%s: unexpected RESPONSE dropped\n", p->dl->name);
650       break;
651 
652     case CBCP_ACK:
653       log_Printf(LogCBCP, "%s: RecvAck(%d) state = %s\n",
654 	         p->dl->name, head->id, cbcpstate(cbcp->fsm.state));
655       cbcp_data_Show(data);
656       if (cbcp->fsm.state == CBCP_RESPSENT) {
657         timer_Stop(&cbcp->fsm.timer);
658         datalink_CBCPComplete(cbcp->p->dl);
659         log_Printf(LogPHASE, "%s: CBCP: Peer will dial back\n", p->dl->name);
660       } else
661         log_Printf(LogCBCP, "%s: unexpected ACK dropped\n", p->dl->name);
662       break;
663 
664     default:
665       log_Printf(LogWARN, "Unrecognised CBCP packet (code %d, length %d)\n",
666                head->code, len);
667       break;
668   }
669 
670   mbuf_Free(bp);
671 }
672 
673 void
674 cbcp_Down(struct cbcp *cbcp)
675 {
676   timer_Stop(&cbcp->fsm.timer);
677   cbcp_NewPhase(cbcp, CBCP_CLOSED);
678   cbcp->required = 0;
679 }
680 
681 void
682 cbcp_ReceiveTerminateReq(struct physical *p)
683 {
684   if (p->dl->cbcp.fsm.state == CBCP_ACKSENT) {
685     /* Don't change our state in case the peer doesn't get the ACK */
686     p->dl->cbcp.required = 1;
687     log_Printf(LogPHASE, "%s: CBCP: Will dial back on %s\n", p->dl->name,
688                p->dl->cbcp.fsm.phone);
689   } else
690     cbcp_NewPhase(&p->dl->cbcp, CBCP_CLOSED);
691 }
692