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
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
< sizeof cbcpname
/ sizeof cbcpname
[0])
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
> sizeof types
/ sizeof types
[0])
220 return HexStr(type
, NULL
, 0);
221 return types
[type
-1];
226 char addr
[sizeof ((struct cbcp_data
*)0)->addr_start
- 1]; /* 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 strncpy(addr
->addr
, next
, sizeof addr
->addr
- 1);
288 addr
->addr
[sizeof addr
->addr
- 1] = '\0';
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 strncpy(addr
->addr
, cbcp
->fsm
.phone
, sizeof addr
->addr
- 1);
496 addr
->addr
[sizeof addr
->addr
- 1] = '\0';
497 data
.length
= (addr
->addr
+ strlen(addr
->addr
) + 1) - (char *)&data
;
499 data
.length
= data
.addr_start
- (char *)&data
;
501 cbcp_data_Show(&data
);
502 cbcp_Output(cbcp
, CBCP_RESPONSE
, &data
);
504 cbcp_StartTimer(cbcp
, cbcp
->fsm
.delay
);
505 cbcp_NewPhase(cbcp
, CBCP_RESPSENT
); /* Wait for an ACK */
508 /* What to do after checking an incoming response */
509 #define CBCP_ACTION_DOWN (0)
510 #define CBCP_ACTION_REQ (1)
511 #define CBCP_ACTION_ACK (2)
514 cbcp_CheckResponse(struct cbcp
*cbcp
, struct cbcp_data
*data
)
517 * We've received a RESPONSE (data). Check if it agrees with
518 * our REQ (cbcp->fsm)
520 struct cbcp_addr
*addr
;
522 addr
= (struct cbcp_addr
*)data
->addr_start
;
524 if (data
->type
== cbcp
->fsm
.type
) {
525 switch (cbcp
->fsm
.type
) {
527 return CBCP_ACTION_ACK
;
530 if ((char *)data
+ data
->length
<= addr
->addr
)
531 log_Printf(LogPHASE
, "CBCP: peer didn't respond with a number !\n");
532 else if (addr
->type
!= CBCP_ADDR_PSTN
)
533 log_Printf(LogPHASE
, "CBCP: Unrecognised address type %d !\n",
536 strncpy(cbcp
->fsm
.phone
, addr
->addr
, sizeof cbcp
->fsm
.phone
- 1);
537 cbcp
->fsm
.phone
[sizeof cbcp
->fsm
.phone
- 1] = '\0';
538 cbcp
->fsm
.delay
= data
->delay
;
539 return CBCP_ACTION_ACK
;
541 return CBCP_ACTION_DOWN
;
544 cbcp
->fsm
.delay
= data
->delay
;
545 return CBCP_ACTION_ACK
;
548 if ((char *)data
+ data
->length
<= addr
->addr
)
549 log_Printf(LogPHASE
, "CBCP: peer didn't respond with a number !\n");
550 else if (addr
->type
!= CBCP_ADDR_PSTN
)
551 log_Printf(LogPHASE
, "CBCP: Unrecognised address type %d !\n",
554 char list
[sizeof cbcp
->fsm
.phone
], *next
;
556 strncpy(list
, cbcp
->fsm
.phone
, sizeof list
- 1);
557 list
[sizeof list
- 1] = '\0';
558 for (next
= strtok(list
, ","); next
; next
= strtok(NULL
, ","))
559 if (!strcmp(addr
->addr
, next
)) {
560 strcpy(cbcp
->fsm
.phone
, next
);
561 cbcp
->fsm
.delay
= data
->delay
;
562 return CBCP_ACTION_ACK
;
564 log_Printf(LogPHASE
, "CBCP: peer didn't respond with a "
567 return CBCP_ACTION_DOWN
;
569 log_Printf(LogPHASE
, "Internal CBCP error - agreed on %d !\n",
570 (int)cbcp
->fsm
.type
);
571 return CBCP_ACTION_DOWN
;
572 } else if (data
->type
== CBCP_NONUM
&& cbcp
->fsm
.type
== CBCP_CLIENTNUM
) {
574 * Client doesn't want CBCP after all....
575 * We only allow this when ``set cbcp *'' has been specified.
577 cbcp
->fsm
.type
= CBCP_NONUM
;
578 return CBCP_ACTION_ACK
;
580 log_Printf(LogCBCP
, "Invalid peer RESPONSE\n");
581 return CBCP_ACTION_REQ
;
585 cbcp_SendAck(struct cbcp
*cbcp
)
587 struct cbcp_data data
;
588 struct cbcp_addr
*addr
;
590 /* Only callees send ACKs */
592 log_Printf(LogCBCP
, "%s: SendAck(%d) state = %s\n", cbcp
->p
->dl
->name
,
593 cbcp
->fsm
.id
, cbcpstate(cbcp
->fsm
.state
));
595 data
.type
= cbcp
->fsm
.type
;
598 data
.length
= (char *)&data
.delay
- (char *)&data
;
601 addr
= (struct cbcp_addr
*)data
.addr_start
;
602 addr
->type
= CBCP_ADDR_PSTN
;
603 strncpy(addr
->addr
, cbcp
->fsm
.phone
, sizeof addr
->addr
- 1);
604 addr
->addr
[sizeof addr
->addr
- 1] = '\0';
605 data
.delay
= cbcp
->fsm
.delay
;
606 data
.length
= addr
->addr
+ strlen(addr
->addr
) + 1 - (char *)&data
;
609 data
.delay
= cbcp
->fsm
.delay
;
610 data
.length
= data
.addr_start
- (char *)&data
;
614 cbcp_data_Show(&data
);
615 cbcp_Output(cbcp
, CBCP_ACK
, &data
);
617 cbcp_StartTimer(cbcp
, cbcp
->fsm
.delay
);
618 cbcp_NewPhase(cbcp
, CBCP_ACKSENT
); /* Wait for an ACK */
622 cbcp_Input(struct bundle
*bundle __unused
, struct link
*l
, struct mbuf
*bp
)
624 struct physical
*p
= link2physical(l
);
625 struct cbcp_header
*head
;
626 struct cbcp_data
*data
;
627 struct cbcp
*cbcp
= &p
->dl
->cbcp
;
631 log_Printf(LogERROR
, "cbcp_Input: Not a physical link - dropped\n");
638 if (len
< sizeof(struct cbcp_header
)) {
642 head
= (struct cbcp_header
*)MBUF_CTOP(bp
);
643 if (ntohs(head
->length
) != len
) {
644 log_Printf(LogWARN
, "Corrupt CBCP packet (code %d, length %u not %zu)"
645 " - ignored\n", head
->code
, ntohs(head
->length
), len
);
649 m_settype(bp
, MB_CBCPIN
);
651 /* XXX check the id */
653 bp
->m_offset
+= sizeof(struct cbcp_header
);
654 bp
->m_len
-= sizeof(struct cbcp_header
);
655 data
= (struct cbcp_data
*)MBUF_CTOP(bp
);
657 switch (head
->code
) {
659 log_Printf(LogCBCP
, "%s: RecvReq(%d) state = %s\n",
660 p
->dl
->name
, head
->id
, cbcpstate(cbcp
->fsm
.state
));
661 cbcp_data_Show(data
);
662 if (cbcp
->fsm
.state
== CBCP_STOPPED
|| cbcp
->fsm
.state
== CBCP_RESPSENT
) {
663 timer_Stop(&cbcp
->fsm
.timer
);
664 if (cbcp_AdjustResponse(cbcp
, data
)) {
665 cbcp
->fsm
.restart
= DEF_FSMTRIES
;
666 cbcp
->fsm
.id
= head
->id
;
667 cbcp_SendResponse(cbcp
);
669 datalink_CBCPFailed(cbcp
->p
->dl
);
671 log_Printf(LogCBCP
, "%s: unexpected REQ dropped\n", p
->dl
->name
);
675 log_Printf(LogCBCP
, "%s: RecvResponse(%d) state = %s\n",
676 p
->dl
->name
, head
->id
, cbcpstate(cbcp
->fsm
.state
));
677 cbcp_data_Show(data
);
678 if (cbcp
->fsm
.id
!= head
->id
) {
679 log_Printf(LogCBCP
, "Warning: Expected id was %d, not %d\n",
680 cbcp
->fsm
.id
, head
->id
);
681 cbcp
->fsm
.id
= head
->id
;
683 if (cbcp
->fsm
.state
== CBCP_REQSENT
|| cbcp
->fsm
.state
== CBCP_ACKSENT
) {
684 timer_Stop(&cbcp
->fsm
.timer
);
685 switch (cbcp_CheckResponse(cbcp
, data
)) {
686 case CBCP_ACTION_REQ
:
690 case CBCP_ACTION_ACK
:
691 cbcp
->fsm
.restart
= DEF_FSMTRIES
;
693 if (cbcp
->fsm
.type
== CBCP_NONUM
) {
695 * Don't change state in case the peer doesn't get our ACK,
696 * just bring the layer up.
698 timer_Stop(&cbcp
->fsm
.timer
);
699 datalink_NCPUp(cbcp
->p
->dl
);
704 datalink_CBCPFailed(cbcp
->p
->dl
);
708 log_Printf(LogCBCP
, "%s: unexpected RESPONSE dropped\n", p
->dl
->name
);
712 log_Printf(LogCBCP
, "%s: RecvAck(%d) state = %s\n",
713 p
->dl
->name
, head
->id
, cbcpstate(cbcp
->fsm
.state
));
714 cbcp_data_Show(data
);
715 if (cbcp
->fsm
.id
!= head
->id
) {
716 log_Printf(LogCBCP
, "Warning: Expected id was %d, not %d\n",
717 cbcp
->fsm
.id
, head
->id
);
718 cbcp
->fsm
.id
= head
->id
;
720 if (cbcp
->fsm
.type
== CBCP_NONUM
) {
722 * Don't change state in case the peer doesn't get our ACK,
723 * just bring the layer up.
725 timer_Stop(&cbcp
->fsm
.timer
);
726 datalink_NCPUp(cbcp
->p
->dl
);
727 } else if (cbcp
->fsm
.state
== CBCP_RESPSENT
) {
728 timer_Stop(&cbcp
->fsm
.timer
);
729 datalink_CBCPComplete(cbcp
->p
->dl
);
730 log_Printf(LogPHASE
, "%s: CBCP: Peer will dial back\n", p
->dl
->name
);
732 log_Printf(LogCBCP
, "%s: unexpected ACK dropped\n", p
->dl
->name
);
736 log_Printf(LogWARN
, "Unrecognised CBCP packet (code %d, length %zd)\n",
746 cbcp_Down(struct cbcp
*cbcp
)
748 timer_Stop(&cbcp
->fsm
.timer
);
749 cbcp_NewPhase(cbcp
, CBCP_CLOSED
);
754 cbcp_ReceiveTerminateReq(struct physical
*p
)
756 if (p
->dl
->cbcp
.fsm
.state
== CBCP_ACKSENT
) {
757 /* Don't change our state in case the peer doesn't get the ACK */
758 p
->dl
->cbcp
.required
= 1;
759 log_Printf(LogPHASE
, "%s: CBCP: Will dial back on %s\n", p
->dl
->name
,
760 p
->dl
->cbcp
.fsm
.phone
);
762 cbcp_NewPhase(&p
->dl
->cbcp
, CBCP_CLOSED
);