2 * Copyright (c) 1998 Brian Somers <brian@Awfulhak.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
26 * $FreeBSD: src/usr.sbin/ppp/cbcp.c,v 1.18.2.3 2002/09/01 02:12:22 brian Exp $
27 * $DragonFly: src/usr.sbin/ppp/cbcp.c,v 1.3 2004/02/03 07:11:47 dillon Exp $
30 #include <sys/param.h>
33 #include <netinet/in.h>
44 #include "descriptor.h"
48 #include "throughput.h"
64 cbcp_Init(struct cbcp
*cbcp
, struct physical
*p
)
67 cbcp
->fsm
.state
= CBCP_CLOSED
;
70 *cbcp
->fsm
.phone
= '\0';
71 memset(&cbcp
->fsm
.timer
, '\0', sizeof cbcp
->fsm
.timer
);
75 static void cbcp_SendReq(struct cbcp
*);
76 static void cbcp_SendResponse(struct cbcp
*);
77 static void cbcp_SendAck(struct cbcp
*);
82 struct cbcp
*cbcp
= (struct cbcp
*)v
;
84 timer_Stop(&cbcp
->fsm
.timer
);
85 if (cbcp
->fsm
.restart
) {
86 switch (cbcp
->fsm
.state
) {
89 log_Printf(LogCBCP
, "%s: Urk - unexpected CBCP timeout !\n",
97 cbcp_SendResponse(cbcp
);
106 switch (cbcp
->fsm
.state
) {
117 missed
= "Terminate REQ";
120 log_Printf(LogCBCP
, "%s: Urk - unexpected CBCP timeout !\n",
126 log_Printf(LogCBCP
, "%s: Timeout waiting for peer %s\n",
127 cbcp
->p
->dl
->name
, missed
);
128 datalink_CBCPFailed(cbcp
->p
->dl
);
133 cbcp_StartTimer(struct cbcp
*cbcp
, int timeout
)
135 timer_Stop(&cbcp
->fsm
.timer
);
136 cbcp
->fsm
.timer
.func
= cbcp_Timeout
;
137 cbcp
->fsm
.timer
.name
= "cbcp";
138 cbcp
->fsm
.timer
.load
= timeout
* SECTICKS
;
139 cbcp
->fsm
.timer
.arg
= cbcp
;
140 timer_Start(&cbcp
->fsm
.timer
);
143 #define CBCP_CLOSED (0) /* Not in use */
144 #define CBCP_STOPPED (1) /* Waiting for a REQ */
145 #define CBCP_REQSENT (2) /* Waiting for a RESP */
146 #define CBCP_RESPSENT (3) /* Waiting for an ACK */
147 #define CBCP_ACKSENT (4) /* Waiting for an LCP Term REQ */
149 static const char * const cbcpname
[] = {
150 "closed", "stopped", "req-sent", "resp-sent", "ack-sent"
156 if (s
< sizeof cbcpname
/ sizeof cbcpname
[0])
158 return HexStr(s
, NULL
, 0);
162 cbcp_NewPhase(struct cbcp
*cbcp
, int new)
164 if (cbcp
->fsm
.state
!= new) {
165 log_Printf(LogCBCP
, "%s: State change %s --> %s\n", cbcp
->p
->dl
->name
,
166 cbcpstate(cbcp
->fsm
.state
), cbcpstate(new));
167 cbcp
->fsm
.state
= new;
174 u_int16_t length
; /* Network byte order */
178 /* cbcp_header::code values */
180 #define CBCP_RESPONSE (2)
187 char addr_start
[253]; /* max cbcp_data length 255 + 1 for NULL */
190 /* cbcp_data::type values */
191 #define CBCP_NONUM (1)
192 #define CBCP_CLIENTNUM (2)
193 #define CBCP_SERVERNUM (3)
194 #define CBCP_LISTNUM (4)
197 cbcp_Output(struct cbcp
*cbcp
, u_char code
, struct cbcp_data
*data
)
199 struct cbcp_header
*head
;
202 bp
= m_get(sizeof *head
+ data
->length
, MB_CBCPOUT
);
203 head
= (struct cbcp_header
*)MBUF_CTOP(bp
);
205 head
->id
= cbcp
->fsm
.id
;
206 head
->length
= htons(sizeof *head
+ data
->length
);
207 memcpy(MBUF_CTOP(bp
) + sizeof *head
, data
, data
->length
);
208 log_DumpBp(LogDEBUG
, "cbcp_Output", bp
);
209 link_PushPacket(&cbcp
->p
->link
, bp
, cbcp
->p
->dl
->bundle
,
210 LINK_QUEUES(&cbcp
->p
->link
) - 1, PROTO_CBCP
);
214 cbcp_data_Type(int type
)
216 static const char * const types
[] = {
217 "No callback", "User-spec", "Server-spec", "list"
220 if (type
< 1 || type
> sizeof types
/ sizeof types
[0])
221 return HexStr(type
, NULL
, 0);
222 return types
[type
-1];
227 char addr
[1]; /* Really ASCIIZ */
230 /* cbcp_data::type values */
231 #define CBCP_ADDR_PSTN (1)
234 cbcp_data_Show(struct cbcp_data
*data
)
236 struct cbcp_addr
*addr
;
239 addr
= (struct cbcp_addr
*)data
->addr_start
;
240 end
= (char *)data
+ data
->length
;
243 log_Printf(LogCBCP
, " TYPE %s\n", cbcp_data_Type(data
->type
));
244 if ((char *)&data
->delay
< end
) {
245 log_Printf(LogCBCP
, " DELAY %d\n", data
->delay
);
246 while (addr
->addr
< end
) {
247 if (addr
->type
== CBCP_ADDR_PSTN
)
248 log_Printf(LogCBCP
, " ADDR %s\n", addr
->addr
);
250 log_Printf(LogCBCP
, " ADDR type %d ??\n", (int)addr
->type
);
251 addr
= (struct cbcp_addr
*)(addr
->addr
+ strlen(addr
->addr
) + 1);
257 cbcp_SendReq(struct cbcp
*cbcp
)
259 struct cbcp_data data
;
260 struct cbcp_addr
*addr
;
261 char list
[sizeof cbcp
->fsm
.phone
], *next
;
264 /* Only callees send REQs */
266 log_Printf(LogCBCP
, "%s: SendReq(%d) state = %s\n", cbcp
->p
->dl
->name
,
267 cbcp
->fsm
.id
, cbcpstate(cbcp
->fsm
.state
));
268 data
.type
= cbcp
->fsm
.type
;
270 strncpy(list
, cbcp
->fsm
.phone
, sizeof list
- 1);
271 list
[sizeof list
- 1] = '\0';
275 addr
= (struct cbcp_addr
*)data
.addr_start
;
276 addr
->type
= CBCP_ADDR_PSTN
;
278 data
.length
= addr
->addr
- (char *)&data
;
282 addr
= (struct cbcp_addr
*)data
.addr_start
;
283 for (next
= strtok(list
, ","); next
; next
= strtok(NULL
, ",")) {
285 max
= data
.addr_start
+ sizeof data
.addr_start
- addr
->addr
- 1;
287 addr
->type
= CBCP_ADDR_PSTN
;
288 strcpy(addr
->addr
, next
);
289 addr
= (struct cbcp_addr
*)((char *)addr
+ len
+ 2);
291 log_Printf(LogWARN
, "CBCP ADDR \"%s\" skipped - packet too large\n",
294 data
.length
= (char *)addr
- (char *)&data
;
298 data
.length
= data
.addr_start
- (char *)&data
;
302 data
.length
= (char *)&data
.delay
- (char *)&data
;
306 cbcp_data_Show(&data
);
307 cbcp_Output(cbcp
, CBCP_REQ
, &data
);
309 cbcp_StartTimer(cbcp
, cbcp
->fsm
.delay
);
310 cbcp_NewPhase(cbcp
, CBCP_REQSENT
); /* Wait for a RESPONSE */
314 cbcp_Up(struct cbcp
*cbcp
)
316 struct lcp
*lcp
= &cbcp
->p
->link
.lcp
;
318 cbcp
->fsm
.delay
= cbcp
->p
->dl
->cfg
.cbcp
.delay
;
319 if (*cbcp
->p
->dl
->peer
.authname
== '\0' ||
320 !auth_SetPhoneList(cbcp
->p
->dl
->peer
.authname
, cbcp
->fsm
.phone
,
321 sizeof cbcp
->fsm
.phone
)) {
322 strncpy(cbcp
->fsm
.phone
, cbcp
->p
->dl
->cfg
.cbcp
.phone
,
323 sizeof cbcp
->fsm
.phone
- 1);
324 cbcp
->fsm
.phone
[sizeof cbcp
->fsm
.phone
- 1] = '\0';
327 if (lcp
->want_callback
.opmask
) {
328 if (*cbcp
->fsm
.phone
== '\0')
329 cbcp
->fsm
.type
= CBCP_NONUM
;
330 else if (!strcmp(cbcp
->fsm
.phone
, "*")) {
331 cbcp
->fsm
.type
= CBCP_SERVERNUM
;
332 *cbcp
->fsm
.phone
= '\0';
334 cbcp
->fsm
.type
= CBCP_CLIENTNUM
;
335 cbcp_NewPhase(cbcp
, CBCP_STOPPED
); /* Wait for a REQ */
336 cbcp_StartTimer(cbcp
, cbcp
->fsm
.delay
* DEF_FSMTRIES
);
338 if (*cbcp
->fsm
.phone
== '\0')
339 cbcp
->fsm
.type
= CBCP_NONUM
;
340 else if (!strcmp(cbcp
->fsm
.phone
, "*")) {
341 cbcp
->fsm
.type
= CBCP_CLIENTNUM
;
342 *cbcp
->fsm
.phone
= '\0';
343 } else if (strchr(cbcp
->fsm
.phone
, ','))
344 cbcp
->fsm
.type
= CBCP_LISTNUM
;
346 cbcp
->fsm
.type
= CBCP_SERVERNUM
;
347 cbcp
->fsm
.restart
= DEF_FSMTRIES
;
353 cbcp_AdjustResponse(struct cbcp
*cbcp
, struct cbcp_data
*data
)
356 * We've received a REQ (data). Adjust our reponse (cbcp->fsm.*)
357 * so that we (hopefully) agree with the peer
359 struct cbcp_addr
*addr
;
361 switch (data
->type
) {
363 if (cbcp
->p
->dl
->cfg
.callback
.opmask
& CALLBACK_BIT(CALLBACK_NONE
))
365 * if ``none'' is a configured callback possibility
366 * (ie, ``set callback cbcp none''), go along with the callees
369 cbcp
->fsm
.type
= CBCP_NONUM
;
372 * Otherwise, we send our desired response anyway. This seems to be
373 * what Win95 does - although I can't find this behaviour documented
374 * in the CBCP spec....
380 if (cbcp
->fsm
.type
== CBCP_CLIENTNUM
) {
383 if (data
->length
> data
->addr_start
- (char *)data
) {
385 * The peer has given us an address type spec - make sure we
388 addr
= (struct cbcp_addr
*)data
->addr_start
;
389 if (addr
->type
!= CBCP_ADDR_PSTN
) {
390 log_Printf(LogPHASE
, "CBCP: Unrecognised address type %d !\n",
395 /* we accept the REQ even if the peer didn't specify an addr->type */
396 ptr
= strchr(cbcp
->fsm
.phone
, ',');
398 *ptr
= '\0'; /* Just use the first number in our list */
401 log_Printf(LogPHASE
, "CBCP: no number to pass to the peer !\n");
405 if (cbcp
->fsm
.type
== CBCP_SERVERNUM
) {
406 *cbcp
->fsm
.phone
= '\0';
409 if (data
->length
> data
->addr_start
- (char *)data
) {
411 * This violates the spec, but if the peer has told us the
412 * number it wants to call back, take advantage of this fact
413 * and allow things to proceed if we've specified the same
416 addr
= (struct cbcp_addr
*)data
->addr_start
;
417 if (addr
->type
!= CBCP_ADDR_PSTN
) {
418 log_Printf(LogPHASE
, "CBCP: Unrecognised address type %d !\n",
421 } else if (cbcp
->fsm
.type
== CBCP_CLIENTNUM
) {
423 * If the peer's insisting on deciding the number, make sure
424 * it's one of the ones in our list. If it is, let the peer
425 * think it's in control :-)
427 char list
[sizeof cbcp
->fsm
.phone
], *next
;
429 strncpy(list
, cbcp
->fsm
.phone
, sizeof list
- 1);
430 list
[sizeof list
- 1] = '\0';
431 for (next
= strtok(list
, ","); next
; next
= strtok(NULL
, ","))
432 if (!strcmp(next
, addr
->addr
)) {
433 cbcp
->fsm
.type
= CBCP_SERVERNUM
;
434 strcpy(cbcp
->fsm
.phone
, next
);
439 log_Printf(LogPHASE
, "CBCP: Peer won't allow local decision !\n");
443 if (cbcp
->fsm
.type
== CBCP_CLIENTNUM
|| cbcp
->fsm
.type
== CBCP_LISTNUM
) {
445 * Search through ``data''s addresses and see if cbcp->fsm.phone
446 * contains any of them
448 char list
[sizeof cbcp
->fsm
.phone
], *next
, *end
;
450 addr
= (struct cbcp_addr
*)data
->addr_start
;
451 end
= (char *)data
+ data
->length
;
453 while (addr
->addr
< end
) {
454 if (addr
->type
== CBCP_ADDR_PSTN
) {
455 strncpy(list
, cbcp
->fsm
.phone
, sizeof list
- 1);
456 list
[sizeof list
- 1] = '\0';
457 for (next
= strtok(list
, ","); next
; next
= strtok(NULL
, ","))
458 if (!strcmp(next
, addr
->addr
)) {
459 cbcp
->fsm
.type
= CBCP_LISTNUM
;
460 strcpy(cbcp
->fsm
.phone
, next
);
464 log_Printf(LogCBCP
, "Warning: Unrecognised address type %d !\n",
466 addr
= (struct cbcp_addr
*)(addr
->addr
+ strlen(addr
->addr
) + 1);
469 log_Printf(LogPHASE
, "CBCP: no good number to pass to the peer !\n");
473 log_Printf(LogCBCP
, "Unrecognised REQ type %d !\n", (int)data
->type
);
478 cbcp_SendResponse(struct cbcp
*cbcp
)
480 struct cbcp_data data
;
481 struct cbcp_addr
*addr
;
483 /* Only callers send RESPONSEs */
485 log_Printf(LogCBCP
, "%s: SendResponse(%d) state = %s\n", cbcp
->p
->dl
->name
,
486 cbcp
->fsm
.id
, cbcpstate(cbcp
->fsm
.state
));
488 data
.type
= cbcp
->fsm
.type
;
489 data
.delay
= cbcp
->fsm
.delay
;
490 addr
= (struct cbcp_addr
*)data
.addr_start
;
491 if (data
.type
== CBCP_NONUM
)
492 data
.length
= (char *)&data
.delay
- (char *)&data
;
493 else if (*cbcp
->fsm
.phone
) {
494 addr
->type
= CBCP_ADDR_PSTN
;
495 strcpy(addr
->addr
, cbcp
->fsm
.phone
);
496 data
.length
= (addr
->addr
+ strlen(addr
->addr
) + 1) - (char *)&data
;
498 data
.length
= data
.addr_start
- (char *)&data
;
500 cbcp_data_Show(&data
);
501 cbcp_Output(cbcp
, CBCP_RESPONSE
, &data
);
503 cbcp_StartTimer(cbcp
, cbcp
->fsm
.delay
);
504 cbcp_NewPhase(cbcp
, CBCP_RESPSENT
); /* Wait for an ACK */
507 /* What to do after checking an incoming response */
508 #define CBCP_ACTION_DOWN (0)
509 #define CBCP_ACTION_REQ (1)
510 #define CBCP_ACTION_ACK (2)
513 cbcp_CheckResponse(struct cbcp
*cbcp
, struct cbcp_data
*data
)
516 * We've received a RESPONSE (data). Check if it agrees with
517 * our REQ (cbcp->fsm)
519 struct cbcp_addr
*addr
;
521 addr
= (struct cbcp_addr
*)data
->addr_start
;
523 if (data
->type
== cbcp
->fsm
.type
) {
524 switch (cbcp
->fsm
.type
) {
526 return CBCP_ACTION_ACK
;
529 if ((char *)data
+ data
->length
<= addr
->addr
)
530 log_Printf(LogPHASE
, "CBCP: peer didn't respond with a number !\n");
531 else if (addr
->type
!= CBCP_ADDR_PSTN
)
532 log_Printf(LogPHASE
, "CBCP: Unrecognised address type %d !\n",
535 strcpy(cbcp
->fsm
.phone
, addr
->addr
);
536 cbcp
->fsm
.delay
= data
->delay
;
537 return CBCP_ACTION_ACK
;
539 return CBCP_ACTION_DOWN
;
542 cbcp
->fsm
.delay
= data
->delay
;
543 return CBCP_ACTION_ACK
;
546 if ((char *)data
+ data
->length
<= addr
->addr
)
547 log_Printf(LogPHASE
, "CBCP: peer didn't respond with a number !\n");
548 else if (addr
->type
!= CBCP_ADDR_PSTN
)
549 log_Printf(LogPHASE
, "CBCP: Unrecognised address type %d !\n",
552 char list
[sizeof cbcp
->fsm
.phone
], *next
;
554 strncpy(list
, cbcp
->fsm
.phone
, sizeof list
- 1);
555 list
[sizeof list
- 1] = '\0';
556 for (next
= strtok(list
, ","); next
; next
= strtok(NULL
, ","))
557 if (!strcmp(addr
->addr
, next
)) {
558 strcpy(cbcp
->fsm
.phone
, next
);
559 cbcp
->fsm
.delay
= data
->delay
;
560 return CBCP_ACTION_ACK
;
562 log_Printf(LogPHASE
, "CBCP: peer didn't respond with a "
565 return CBCP_ACTION_DOWN
;
567 log_Printf(LogPHASE
, "Internal CBCP error - agreed on %d !\n",
568 (int)cbcp
->fsm
.type
);
569 return CBCP_ACTION_DOWN
;
570 } else if (data
->type
== CBCP_NONUM
&& cbcp
->fsm
.type
== CBCP_CLIENTNUM
) {
572 * Client doesn't want CBCP after all....
573 * We only allow this when ``set cbcp *'' has been specified.
575 cbcp
->fsm
.type
= CBCP_NONUM
;
576 return CBCP_ACTION_ACK
;
578 log_Printf(LogCBCP
, "Invalid peer RESPONSE\n");
579 return CBCP_ACTION_REQ
;
583 cbcp_SendAck(struct cbcp
*cbcp
)
585 struct cbcp_data data
;
586 struct cbcp_addr
*addr
;
588 /* Only callees send ACKs */
590 log_Printf(LogCBCP
, "%s: SendAck(%d) state = %s\n", cbcp
->p
->dl
->name
,
591 cbcp
->fsm
.id
, cbcpstate(cbcp
->fsm
.state
));
593 data
.type
= cbcp
->fsm
.type
;
596 data
.length
= (char *)&data
.delay
- (char *)&data
;
599 addr
= (struct cbcp_addr
*)data
.addr_start
;
600 addr
->type
= CBCP_ADDR_PSTN
;
601 strcpy(addr
->addr
, cbcp
->fsm
.phone
);
602 data
.delay
= cbcp
->fsm
.delay
;
603 data
.length
= addr
->addr
+ strlen(addr
->addr
) + 1 - (char *)&data
;
606 data
.delay
= cbcp
->fsm
.delay
;
607 data
.length
= data
.addr_start
- (char *)&data
;
611 cbcp_data_Show(&data
);
612 cbcp_Output(cbcp
, CBCP_ACK
, &data
);
614 cbcp_StartTimer(cbcp
, cbcp
->fsm
.delay
);
615 cbcp_NewPhase(cbcp
, CBCP_ACKSENT
); /* Wait for an ACK */
619 cbcp_Input(struct bundle
*bundle
, struct link
*l
, struct mbuf
*bp
)
621 struct physical
*p
= link2physical(l
);
622 struct cbcp_header
*head
;
623 struct cbcp_data
*data
;
624 struct cbcp
*cbcp
= &p
->dl
->cbcp
;
628 log_Printf(LogERROR
, "cbcp_Input: Not a physical link - dropped\n");
635 if (len
< sizeof(struct cbcp_header
)) {
639 head
= (struct cbcp_header
*)MBUF_CTOP(bp
);
640 if (ntohs(head
->length
) != len
) {
641 log_Printf(LogWARN
, "Corrupt CBCP packet (code %d, length %d not %d)"
642 " - ignored\n", head
->code
, ntohs(head
->length
), len
);
646 m_settype(bp
, MB_CBCPIN
);
648 /* XXX check the id */
650 bp
->m_offset
+= sizeof(struct cbcp_header
);
651 bp
->m_len
-= sizeof(struct cbcp_header
);
652 data
= (struct cbcp_data
*)MBUF_CTOP(bp
);
654 switch (head
->code
) {
656 log_Printf(LogCBCP
, "%s: RecvReq(%d) state = %s\n",
657 p
->dl
->name
, head
->id
, cbcpstate(cbcp
->fsm
.state
));
658 cbcp_data_Show(data
);
659 if (cbcp
->fsm
.state
== CBCP_STOPPED
|| cbcp
->fsm
.state
== CBCP_RESPSENT
) {
660 timer_Stop(&cbcp
->fsm
.timer
);
661 if (cbcp_AdjustResponse(cbcp
, data
)) {
662 cbcp
->fsm
.restart
= DEF_FSMTRIES
;
663 cbcp
->fsm
.id
= head
->id
;
664 cbcp_SendResponse(cbcp
);
666 datalink_CBCPFailed(cbcp
->p
->dl
);
668 log_Printf(LogCBCP
, "%s: unexpected REQ dropped\n", p
->dl
->name
);
672 log_Printf(LogCBCP
, "%s: RecvResponse(%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
;
680 if (cbcp
->fsm
.state
== CBCP_REQSENT
|| cbcp
->fsm
.state
== CBCP_ACKSENT
) {
681 timer_Stop(&cbcp
->fsm
.timer
);
682 switch (cbcp_CheckResponse(cbcp
, data
)) {
683 case CBCP_ACTION_REQ
:
687 case CBCP_ACTION_ACK
:
688 cbcp
->fsm
.restart
= DEF_FSMTRIES
;
690 if (cbcp
->fsm
.type
== CBCP_NONUM
) {
692 * Don't change state in case the peer doesn't get our ACK,
693 * just bring the layer up.
695 timer_Stop(&cbcp
->fsm
.timer
);
696 datalink_NCPUp(cbcp
->p
->dl
);
701 datalink_CBCPFailed(cbcp
->p
->dl
);
705 log_Printf(LogCBCP
, "%s: unexpected RESPONSE dropped\n", p
->dl
->name
);
709 log_Printf(LogCBCP
, "%s: RecvAck(%d) state = %s\n",
710 p
->dl
->name
, head
->id
, cbcpstate(cbcp
->fsm
.state
));
711 cbcp_data_Show(data
);
712 if (cbcp
->fsm
.id
!= head
->id
) {
713 log_Printf(LogCBCP
, "Warning: Expected id was %d, not %d\n",
714 cbcp
->fsm
.id
, head
->id
);
715 cbcp
->fsm
.id
= head
->id
;
717 if (cbcp
->fsm
.type
== CBCP_NONUM
) {
719 * Don't change state in case the peer doesn't get our ACK,
720 * just bring the layer up.
722 timer_Stop(&cbcp
->fsm
.timer
);
723 datalink_NCPUp(cbcp
->p
->dl
);
724 } else if (cbcp
->fsm
.state
== CBCP_RESPSENT
) {
725 timer_Stop(&cbcp
->fsm
.timer
);
726 datalink_CBCPComplete(cbcp
->p
->dl
);
727 log_Printf(LogPHASE
, "%s: CBCP: Peer will dial back\n", p
->dl
->name
);
729 log_Printf(LogCBCP
, "%s: unexpected ACK dropped\n", p
->dl
->name
);
733 log_Printf(LogWARN
, "Unrecognised CBCP packet (code %d, length %d)\n",
743 cbcp_Down(struct cbcp
*cbcp
)
745 timer_Stop(&cbcp
->fsm
.timer
);
746 cbcp_NewPhase(cbcp
, CBCP_CLOSED
);
751 cbcp_ReceiveTerminateReq(struct physical
*p
)
753 if (p
->dl
->cbcp
.fsm
.state
== CBCP_ACKSENT
) {
754 /* Don't change our state in case the peer doesn't get the ACK */
755 p
->dl
->cbcp
.required
= 1;
756 log_Printf(LogPHASE
, "%s: CBCP: Will dial back on %s\n", p
->dl
->name
,
757 p
->dl
->cbcp
.fsm
.phone
);
759 cbcp_NewPhase(&p
->dl
->cbcp
, CBCP_CLOSED
);