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