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 $
29 #include <sys/param.h>
32 #include <netinet/in.h>
43 #include "descriptor.h"
47 #include "throughput.h"
63 cbcp_Init(struct cbcp
*cbcp
, struct physical
*p
)
66 cbcp
->fsm
.state
= CBCP_CLOSED
;
69 *cbcp
->fsm
.phone
= '\0';
70 memset(&cbcp
->fsm
.timer
, '\0', sizeof cbcp
->fsm
.timer
);
74 static void cbcp_SendReq(struct cbcp
*);
75 static void cbcp_SendResponse(struct cbcp
*);
76 static void cbcp_SendAck(struct cbcp
*);
81 struct cbcp
*cbcp
= (struct cbcp
*)v
;
83 timer_Stop(&cbcp
->fsm
.timer
);
84 if (cbcp
->fsm
.restart
) {
85 switch (cbcp
->fsm
.state
) {
88 log_Printf(LogCBCP
, "%s: Urk - unexpected CBCP timeout !\n",
96 cbcp_SendResponse(cbcp
);
105 switch (cbcp
->fsm
.state
) {
116 missed
= "Terminate REQ";
119 log_Printf(LogCBCP
, "%s: Urk - unexpected CBCP timeout !\n",
125 log_Printf(LogCBCP
, "%s: Timeout waiting for peer %s\n",
126 cbcp
->p
->dl
->name
, missed
);
127 datalink_CBCPFailed(cbcp
->p
->dl
);
132 cbcp_StartTimer(struct cbcp
*cbcp
, int timeout
)
134 timer_Stop(&cbcp
->fsm
.timer
);
135 cbcp
->fsm
.timer
.func
= cbcp_Timeout
;
136 cbcp
->fsm
.timer
.name
= "cbcp";
137 cbcp
->fsm
.timer
.load
= timeout
* SECTICKS
;
138 cbcp
->fsm
.timer
.arg
= cbcp
;
139 timer_Start(&cbcp
->fsm
.timer
);
142 #define CBCP_CLOSED (0) /* Not in use */
143 #define CBCP_STOPPED (1) /* Waiting for a REQ */
144 #define CBCP_REQSENT (2) /* Waiting for a RESP */
145 #define CBCP_RESPSENT (3) /* Waiting for an ACK */
146 #define CBCP_ACKSENT (4) /* Waiting for an LCP Term REQ */
148 static const char * const cbcpname
[] = {
149 "closed", "stopped", "req-sent", "resp-sent", "ack-sent"
153 cbcpstate(unsigned s
)
155 if (s
< NELEM(cbcpname
))
157 return HexStr(s
, NULL
, 0);
161 cbcp_NewPhase(struct cbcp
*cbcp
, int new)
163 if (cbcp
->fsm
.state
!= new) {
164 log_Printf(LogCBCP
, "%s: State change %s --> %s\n", cbcp
->p
->dl
->name
,
165 cbcpstate(cbcp
->fsm
.state
), cbcpstate(new));
166 cbcp
->fsm
.state
= new;
173 u_int16_t length
; /* Network byte order */
177 /* cbcp_header::code values */
179 #define CBCP_RESPONSE (2)
186 char addr_start
[253]; /* max cbcp_data length 255 + 1 for NULL */
189 /* cbcp_data::type values */
190 #define CBCP_NONUM (1)
191 #define CBCP_CLIENTNUM (2)
192 #define CBCP_SERVERNUM (3)
193 #define CBCP_LISTNUM (4)
196 cbcp_Output(struct cbcp
*cbcp
, u_char code
, struct cbcp_data
*data
)
198 struct cbcp_header
*head
;
201 bp
= m_get(sizeof *head
+ data
->length
, MB_CBCPOUT
);
202 head
= (struct cbcp_header
*)MBUF_CTOP(bp
);
204 head
->id
= cbcp
->fsm
.id
;
205 head
->length
= htons(sizeof *head
+ data
->length
);
206 memcpy(MBUF_CTOP(bp
) + sizeof *head
, data
, data
->length
);
207 log_DumpBp(LogDEBUG
, "cbcp_Output", bp
);
208 link_PushPacket(&cbcp
->p
->link
, bp
, cbcp
->p
->dl
->bundle
,
209 LINK_QUEUES(&cbcp
->p
->link
) - 1, PROTO_CBCP
);
213 cbcp_data_Type(unsigned type
)
215 static const char * const types
[] = {
216 "No callback", "User-spec", "Server-spec", "list"
219 if (type
< 1 || type
> NELEM(types
))
220 return HexStr(type
, NULL
, 0);
221 return types
[type
-1];
226 char addr
[1]; /* Really ASCIIZ */
229 /* cbcp_data::type values */
230 #define CBCP_ADDR_PSTN (1)
233 cbcp_data_Show(struct cbcp_data
*data
)
235 struct cbcp_addr
*addr
;
238 addr
= (struct cbcp_addr
*)data
->addr_start
;
239 end
= (char *)data
+ data
->length
;
242 log_Printf(LogCBCP
, " TYPE %s\n", cbcp_data_Type(data
->type
));
243 if ((char *)&data
->delay
< end
) {
244 log_Printf(LogCBCP
, " DELAY %d\n", data
->delay
);
245 while (addr
->addr
< end
) {
246 if (addr
->type
== CBCP_ADDR_PSTN
)
247 log_Printf(LogCBCP
, " ADDR %s\n", addr
->addr
);
249 log_Printf(LogCBCP
, " ADDR type %d ??\n", (int)addr
->type
);
250 addr
= (struct cbcp_addr
*)(addr
->addr
+ strlen(addr
->addr
) + 1);
256 cbcp_SendReq(struct cbcp
*cbcp
)
258 struct cbcp_data data
;
259 struct cbcp_addr
*addr
;
260 char list
[sizeof cbcp
->fsm
.phone
], *next
;
263 /* Only callees send REQs */
265 log_Printf(LogCBCP
, "%s: SendReq(%d) state = %s\n", cbcp
->p
->dl
->name
,
266 cbcp
->fsm
.id
, cbcpstate(cbcp
->fsm
.state
));
267 data
.type
= cbcp
->fsm
.type
;
269 strncpy(list
, cbcp
->fsm
.phone
, sizeof list
- 1);
270 list
[sizeof list
- 1] = '\0';
274 addr
= (struct cbcp_addr
*)data
.addr_start
;
275 addr
->type
= CBCP_ADDR_PSTN
;
277 data
.length
= addr
->addr
- (char *)&data
;
281 addr
= (struct cbcp_addr
*)data
.addr_start
;
282 for (next
= strtok(list
, ","); next
; next
= strtok(NULL
, ",")) {
284 max
= data
.addr_start
+ sizeof data
.addr_start
- addr
->addr
- 1;
286 addr
->type
= CBCP_ADDR_PSTN
;
287 strcpy(addr
->addr
, next
);
288 addr
= (struct cbcp_addr
*)((char *)addr
+ len
+ 2);
290 log_Printf(LogWARN
, "CBCP ADDR \"%s\" skipped - packet too large\n",
293 data
.length
= (char *)addr
- (char *)&data
;
297 data
.length
= data
.addr_start
- (char *)&data
;
301 data
.length
= (char *)&data
.delay
- (char *)&data
;
305 cbcp_data_Show(&data
);
306 cbcp_Output(cbcp
, CBCP_REQ
, &data
);
308 cbcp_StartTimer(cbcp
, cbcp
->fsm
.delay
);
309 cbcp_NewPhase(cbcp
, CBCP_REQSENT
); /* Wait for a RESPONSE */
313 cbcp_Up(struct cbcp
*cbcp
)
315 struct lcp
*lcp
= &cbcp
->p
->link
.lcp
;
317 cbcp
->fsm
.delay
= cbcp
->p
->dl
->cfg
.cbcp
.delay
;
318 if (*cbcp
->p
->dl
->peer
.authname
== '\0' ||
319 !auth_SetPhoneList(cbcp
->p
->dl
->peer
.authname
, cbcp
->fsm
.phone
,
320 sizeof cbcp
->fsm
.phone
)) {
321 strncpy(cbcp
->fsm
.phone
, cbcp
->p
->dl
->cfg
.cbcp
.phone
,
322 sizeof cbcp
->fsm
.phone
- 1);
323 cbcp
->fsm
.phone
[sizeof cbcp
->fsm
.phone
- 1] = '\0';
326 if (lcp
->want_callback
.opmask
) {
327 if (*cbcp
->fsm
.phone
== '\0')
328 cbcp
->fsm
.type
= CBCP_NONUM
;
329 else if (!strcmp(cbcp
->fsm
.phone
, "*")) {
330 cbcp
->fsm
.type
= CBCP_SERVERNUM
;
331 *cbcp
->fsm
.phone
= '\0';
333 cbcp
->fsm
.type
= CBCP_CLIENTNUM
;
334 cbcp_NewPhase(cbcp
, CBCP_STOPPED
); /* Wait for a REQ */
335 cbcp_StartTimer(cbcp
, cbcp
->fsm
.delay
* DEF_FSMTRIES
);
337 if (*cbcp
->fsm
.phone
== '\0')
338 cbcp
->fsm
.type
= CBCP_NONUM
;
339 else if (!strcmp(cbcp
->fsm
.phone
, "*")) {
340 cbcp
->fsm
.type
= CBCP_CLIENTNUM
;
341 *cbcp
->fsm
.phone
= '\0';
342 } else if (strchr(cbcp
->fsm
.phone
, ','))
343 cbcp
->fsm
.type
= CBCP_LISTNUM
;
345 cbcp
->fsm
.type
= CBCP_SERVERNUM
;
346 cbcp
->fsm
.restart
= DEF_FSMTRIES
;
352 cbcp_AdjustResponse(struct cbcp
*cbcp
, struct cbcp_data
*data
)
355 * We've received a REQ (data). Adjust our reponse (cbcp->fsm.*)
356 * so that we (hopefully) agree with the peer
358 struct cbcp_addr
*addr
;
360 switch (data
->type
) {
362 if (cbcp
->p
->dl
->cfg
.callback
.opmask
& CALLBACK_BIT(CALLBACK_NONE
))
364 * if ``none'' is a configured callback possibility
365 * (ie, ``set callback cbcp none''), go along with the callees
368 cbcp
->fsm
.type
= CBCP_NONUM
;
371 * Otherwise, we send our desired response anyway. This seems to be
372 * what Win95 does - although I can't find this behaviour documented
373 * in the CBCP spec....
379 if (cbcp
->fsm
.type
== CBCP_CLIENTNUM
) {
382 if (data
->length
> data
->addr_start
- (char *)data
) {
384 * The peer has given us an address type spec - make sure we
387 addr
= (struct cbcp_addr
*)data
->addr_start
;
388 if (addr
->type
!= CBCP_ADDR_PSTN
) {
389 log_Printf(LogPHASE
, "CBCP: Unrecognised address type %d !\n",
394 /* we accept the REQ even if the peer didn't specify an addr->type */
395 ptr
= strchr(cbcp
->fsm
.phone
, ',');
397 *ptr
= '\0'; /* Just use the first number in our list */
400 log_Printf(LogPHASE
, "CBCP: no number to pass to the peer !\n");
404 if (cbcp
->fsm
.type
== CBCP_SERVERNUM
) {
405 *cbcp
->fsm
.phone
= '\0';
408 if (data
->length
> data
->addr_start
- (char *)data
) {
410 * This violates the spec, but if the peer has told us the
411 * number it wants to call back, take advantage of this fact
412 * and allow things to proceed if we've specified the same
415 addr
= (struct cbcp_addr
*)data
->addr_start
;
416 if (addr
->type
!= CBCP_ADDR_PSTN
) {
417 log_Printf(LogPHASE
, "CBCP: Unrecognised address type %d !\n",
420 } else if (cbcp
->fsm
.type
== CBCP_CLIENTNUM
) {
422 * If the peer's insisting on deciding the number, make sure
423 * it's one of the ones in our list. If it is, let the peer
424 * think it's in control :-)
426 char list
[sizeof cbcp
->fsm
.phone
], *next
;
428 strncpy(list
, cbcp
->fsm
.phone
, sizeof list
- 1);
429 list
[sizeof list
- 1] = '\0';
430 for (next
= strtok(list
, ","); next
; next
= strtok(NULL
, ","))
431 if (!strcmp(next
, addr
->addr
)) {
432 cbcp
->fsm
.type
= CBCP_SERVERNUM
;
433 strcpy(cbcp
->fsm
.phone
, next
);
438 log_Printf(LogPHASE
, "CBCP: Peer won't allow local decision !\n");
442 if (cbcp
->fsm
.type
== CBCP_CLIENTNUM
|| cbcp
->fsm
.type
== CBCP_LISTNUM
) {
444 * Search through ``data''s addresses and see if cbcp->fsm.phone
445 * contains any of them
447 char list
[sizeof cbcp
->fsm
.phone
], *next
, *end
;
449 addr
= (struct cbcp_addr
*)data
->addr_start
;
450 end
= (char *)data
+ data
->length
;
452 while (addr
->addr
< end
) {
453 if (addr
->type
== CBCP_ADDR_PSTN
) {
454 strncpy(list
, cbcp
->fsm
.phone
, sizeof list
- 1);
455 list
[sizeof list
- 1] = '\0';
456 for (next
= strtok(list
, ","); next
; next
= strtok(NULL
, ","))
457 if (!strcmp(next
, addr
->addr
)) {
458 cbcp
->fsm
.type
= CBCP_LISTNUM
;
459 strcpy(cbcp
->fsm
.phone
, next
);
463 log_Printf(LogCBCP
, "Warning: Unrecognised address type %d !\n",
465 addr
= (struct cbcp_addr
*)(addr
->addr
+ strlen(addr
->addr
) + 1);
468 log_Printf(LogPHASE
, "CBCP: no good number to pass to the peer !\n");
472 log_Printf(LogCBCP
, "Unrecognised REQ type %d !\n", (int)data
->type
);
477 cbcp_SendResponse(struct cbcp
*cbcp
)
479 struct cbcp_data data
;
480 struct cbcp_addr
*addr
;
482 /* Only callers send RESPONSEs */
484 log_Printf(LogCBCP
, "%s: SendResponse(%d) state = %s\n", cbcp
->p
->dl
->name
,
485 cbcp
->fsm
.id
, cbcpstate(cbcp
->fsm
.state
));
487 data
.type
= cbcp
->fsm
.type
;
488 data
.delay
= cbcp
->fsm
.delay
;
489 addr
= (struct cbcp_addr
*)data
.addr_start
;
490 if (data
.type
== CBCP_NONUM
)
491 data
.length
= (char *)&data
.delay
- (char *)&data
;
492 else if (*cbcp
->fsm
.phone
) {
493 addr
->type
= CBCP_ADDR_PSTN
;
494 strcpy(addr
->addr
, cbcp
->fsm
.phone
);
495 data
.length
= (addr
->addr
+ strlen(addr
->addr
) + 1) - (char *)&data
;
497 data
.length
= data
.addr_start
- (char *)&data
;
499 cbcp_data_Show(&data
);
500 cbcp_Output(cbcp
, CBCP_RESPONSE
, &data
);
502 cbcp_StartTimer(cbcp
, cbcp
->fsm
.delay
);
503 cbcp_NewPhase(cbcp
, CBCP_RESPSENT
); /* Wait for an ACK */
506 /* What to do after checking an incoming response */
507 #define CBCP_ACTION_DOWN (0)
508 #define CBCP_ACTION_REQ (1)
509 #define CBCP_ACTION_ACK (2)
512 cbcp_CheckResponse(struct cbcp
*cbcp
, struct cbcp_data
*data
)
515 * We've received a RESPONSE (data). Check if it agrees with
516 * our REQ (cbcp->fsm)
518 struct cbcp_addr
*addr
;
520 addr
= (struct cbcp_addr
*)data
->addr_start
;
522 if (data
->type
== cbcp
->fsm
.type
) {
523 switch (cbcp
->fsm
.type
) {
525 return CBCP_ACTION_ACK
;
528 if ((char *)data
+ data
->length
<= addr
->addr
)
529 log_Printf(LogPHASE
, "CBCP: peer didn't respond with a number !\n");
530 else if (addr
->type
!= CBCP_ADDR_PSTN
)
531 log_Printf(LogPHASE
, "CBCP: Unrecognised address type %d !\n",
534 strcpy(cbcp
->fsm
.phone
, addr
->addr
);
535 cbcp
->fsm
.delay
= data
->delay
;
536 return CBCP_ACTION_ACK
;
538 return CBCP_ACTION_DOWN
;
541 cbcp
->fsm
.delay
= data
->delay
;
542 return CBCP_ACTION_ACK
;
545 if ((char *)data
+ data
->length
<= addr
->addr
)
546 log_Printf(LogPHASE
, "CBCP: peer didn't respond with a number !\n");
547 else if (addr
->type
!= CBCP_ADDR_PSTN
)
548 log_Printf(LogPHASE
, "CBCP: Unrecognised address type %d !\n",
551 char list
[sizeof cbcp
->fsm
.phone
], *next
;
553 strncpy(list
, cbcp
->fsm
.phone
, sizeof list
- 1);
554 list
[sizeof list
- 1] = '\0';
555 for (next
= strtok(list
, ","); next
; next
= strtok(NULL
, ","))
556 if (!strcmp(addr
->addr
, next
)) {
557 strcpy(cbcp
->fsm
.phone
, next
);
558 cbcp
->fsm
.delay
= data
->delay
;
559 return CBCP_ACTION_ACK
;
561 log_Printf(LogPHASE
, "CBCP: peer didn't respond with a "
564 return CBCP_ACTION_DOWN
;
566 log_Printf(LogPHASE
, "Internal CBCP error - agreed on %d !\n",
567 (int)cbcp
->fsm
.type
);
568 return CBCP_ACTION_DOWN
;
569 } else if (data
->type
== CBCP_NONUM
&& cbcp
->fsm
.type
== CBCP_CLIENTNUM
) {
571 * Client doesn't want CBCP after all....
572 * We only allow this when ``set cbcp *'' has been specified.
574 cbcp
->fsm
.type
= CBCP_NONUM
;
575 return CBCP_ACTION_ACK
;
577 log_Printf(LogCBCP
, "Invalid peer RESPONSE\n");
578 return CBCP_ACTION_REQ
;
582 cbcp_SendAck(struct cbcp
*cbcp
)
584 struct cbcp_data data
;
585 struct cbcp_addr
*addr
;
587 /* Only callees send ACKs */
589 log_Printf(LogCBCP
, "%s: SendAck(%d) state = %s\n", cbcp
->p
->dl
->name
,
590 cbcp
->fsm
.id
, cbcpstate(cbcp
->fsm
.state
));
592 data
.type
= cbcp
->fsm
.type
;
595 data
.length
= (char *)&data
.delay
- (char *)&data
;
598 addr
= (struct cbcp_addr
*)data
.addr_start
;
599 addr
->type
= CBCP_ADDR_PSTN
;
600 strcpy(addr
->addr
, cbcp
->fsm
.phone
);
601 data
.delay
= cbcp
->fsm
.delay
;
602 data
.length
= addr
->addr
+ strlen(addr
->addr
) + 1 - (char *)&data
;
605 data
.delay
= cbcp
->fsm
.delay
;
606 data
.length
= data
.addr_start
- (char *)&data
;
610 cbcp_data_Show(&data
);
611 cbcp_Output(cbcp
, CBCP_ACK
, &data
);
613 cbcp_StartTimer(cbcp
, cbcp
->fsm
.delay
);
614 cbcp_NewPhase(cbcp
, CBCP_ACKSENT
); /* Wait for an ACK */
618 cbcp_Input(struct bundle
*bundle __unused
, struct link
*l
, struct mbuf
*bp
)
620 struct physical
*p
= link2physical(l
);
621 struct cbcp_header
*head
;
622 struct cbcp_data
*data
;
623 struct cbcp
*cbcp
= &p
->dl
->cbcp
;
627 log_Printf(LogERROR
, "cbcp_Input: Not a physical link - dropped\n");
634 if (len
< sizeof(struct cbcp_header
)) {
638 head
= (struct cbcp_header
*)MBUF_CTOP(bp
);
639 if (ntohs(head
->length
) != len
) {
640 log_Printf(LogWARN
, "Corrupt CBCP packet (code %d, length %u not %zu)"
641 " - ignored\n", head
->code
, ntohs(head
->length
), len
);
645 m_settype(bp
, MB_CBCPIN
);
647 /* XXX check the id */
649 bp
->m_offset
+= sizeof(struct cbcp_header
);
650 bp
->m_len
-= sizeof(struct cbcp_header
);
651 data
= (struct cbcp_data
*)MBUF_CTOP(bp
);
653 switch (head
->code
) {
655 log_Printf(LogCBCP
, "%s: RecvReq(%d) state = %s\n",
656 p
->dl
->name
, head
->id
, cbcpstate(cbcp
->fsm
.state
));
657 cbcp_data_Show(data
);
658 if (cbcp
->fsm
.state
== CBCP_STOPPED
|| cbcp
->fsm
.state
== CBCP_RESPSENT
) {
659 timer_Stop(&cbcp
->fsm
.timer
);
660 if (cbcp_AdjustResponse(cbcp
, data
)) {
661 cbcp
->fsm
.restart
= DEF_FSMTRIES
;
662 cbcp
->fsm
.id
= head
->id
;
663 cbcp_SendResponse(cbcp
);
665 datalink_CBCPFailed(cbcp
->p
->dl
);
667 log_Printf(LogCBCP
, "%s: unexpected REQ dropped\n", p
->dl
->name
);
671 log_Printf(LogCBCP
, "%s: RecvResponse(%d) state = %s\n",
672 p
->dl
->name
, head
->id
, cbcpstate(cbcp
->fsm
.state
));
673 cbcp_data_Show(data
);
674 if (cbcp
->fsm
.id
!= head
->id
) {
675 log_Printf(LogCBCP
, "Warning: Expected id was %d, not %d\n",
676 cbcp
->fsm
.id
, head
->id
);
677 cbcp
->fsm
.id
= head
->id
;
679 if (cbcp
->fsm
.state
== CBCP_REQSENT
|| cbcp
->fsm
.state
== CBCP_ACKSENT
) {
680 timer_Stop(&cbcp
->fsm
.timer
);
681 switch (cbcp_CheckResponse(cbcp
, data
)) {
682 case CBCP_ACTION_REQ
:
686 case CBCP_ACTION_ACK
:
687 cbcp
->fsm
.restart
= DEF_FSMTRIES
;
689 if (cbcp
->fsm
.type
== CBCP_NONUM
) {
691 * Don't change state in case the peer doesn't get our ACK,
692 * just bring the layer up.
694 timer_Stop(&cbcp
->fsm
.timer
);
695 datalink_NCPUp(cbcp
->p
->dl
);
700 datalink_CBCPFailed(cbcp
->p
->dl
);
704 log_Printf(LogCBCP
, "%s: unexpected RESPONSE dropped\n", p
->dl
->name
);
708 log_Printf(LogCBCP
, "%s: RecvAck(%d) state = %s\n",
709 p
->dl
->name
, head
->id
, cbcpstate(cbcp
->fsm
.state
));
710 cbcp_data_Show(data
);
711 if (cbcp
->fsm
.id
!= head
->id
) {
712 log_Printf(LogCBCP
, "Warning: Expected id was %d, not %d\n",
713 cbcp
->fsm
.id
, head
->id
);
714 cbcp
->fsm
.id
= head
->id
;
716 if (cbcp
->fsm
.type
== CBCP_NONUM
) {
718 * Don't change state in case the peer doesn't get our ACK,
719 * just bring the layer up.
721 timer_Stop(&cbcp
->fsm
.timer
);
722 datalink_NCPUp(cbcp
->p
->dl
);
723 } else if (cbcp
->fsm
.state
== CBCP_RESPSENT
) {
724 timer_Stop(&cbcp
->fsm
.timer
);
725 datalink_CBCPComplete(cbcp
->p
->dl
);
726 log_Printf(LogPHASE
, "%s: CBCP: Peer will dial back\n", p
->dl
->name
);
728 log_Printf(LogCBCP
, "%s: unexpected ACK dropped\n", p
->dl
->name
);
732 log_Printf(LogWARN
, "Unrecognised CBCP packet (code %d, length %zu)\n",
742 cbcp_Down(struct cbcp
*cbcp
)
744 timer_Stop(&cbcp
->fsm
.timer
);
745 cbcp_NewPhase(cbcp
, CBCP_CLOSED
);
750 cbcp_ReceiveTerminateReq(struct physical
*p
)
752 if (p
->dl
->cbcp
.fsm
.state
== CBCP_ACKSENT
) {
753 /* Don't change our state in case the peer doesn't get the ACK */
754 p
->dl
->cbcp
.required
= 1;
755 log_Printf(LogPHASE
, "%s: CBCP: Will dial back on %s\n", p
->dl
->name
,
756 p
->dl
->cbcp
.fsm
.phone
);
758 cbcp_NewPhase(&p
->dl
->cbcp
, CBCP_CLOSED
);