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 * $FreeBSD$ 27 */ 28 29 #include <sys/param.h> 30 31 #ifdef __FreeBSD__ 32 #include <netinet/in.h> 33 #endif 34 #include <sys/un.h> 35 36 #include <string.h> 37 #include <termios.h> 38 39 #include "layer.h" 40 #include "defs.h" 41 #include "log.h" 42 #include "timer.h" 43 #include "descriptor.h" 44 #include "lqr.h" 45 #include "mbuf.h" 46 #include "fsm.h" 47 #include "throughput.h" 48 #include "hdlc.h" 49 #include "lcp.h" 50 #include "ccp.h" 51 #include "link.h" 52 #include "async.h" 53 #include "physical.h" 54 #include "proto.h" 55 #include "cbcp.h" 56 #include "mp.h" 57 #include "chat.h" 58 #include "auth.h" 59 #include "chap.h" 60 #include "datalink.h" 61 62 void 63 cbcp_Init(struct cbcp *cbcp, struct physical *p) 64 { 65 cbcp->required = 0; 66 cbcp->fsm.state = CBCP_CLOSED; 67 cbcp->fsm.id = 0; 68 cbcp->fsm.delay = 0; 69 *cbcp->fsm.phone = '\0'; 70 memset(&cbcp->fsm.timer, '\0', sizeof cbcp->fsm.timer); 71 cbcp->p = p; 72 } 73 74 static void cbcp_SendReq(struct cbcp *); 75 static void cbcp_SendResponse(struct cbcp *); 76 static void cbcp_SendAck(struct cbcp *); 77 78 static void 79 cbcp_Timeout(void *v) 80 { 81 struct cbcp *cbcp = (struct cbcp *)v; 82 83 timer_Stop(&cbcp->fsm.timer); 84 if (cbcp->fsm.restart) { 85 switch (cbcp->fsm.state) { 86 case CBCP_CLOSED: 87 case CBCP_STOPPED: 88 log_Printf(LogCBCP, "%s: Urk - unexpected CBCP timeout !\n", 89 cbcp->p->dl->name); 90 break; 91 92 case CBCP_REQSENT: 93 cbcp_SendReq(cbcp); 94 break; 95 case CBCP_RESPSENT: 96 cbcp_SendResponse(cbcp); 97 break; 98 case CBCP_ACKSENT: 99 cbcp_SendAck(cbcp); 100 break; 101 } 102 } else { 103 const char *missed; 104 105 switch (cbcp->fsm.state) { 106 case CBCP_STOPPED: 107 missed = "REQ"; 108 break; 109 case CBCP_REQSENT: 110 missed = "RESPONSE"; 111 break; 112 case CBCP_RESPSENT: 113 missed = "ACK"; 114 break; 115 case CBCP_ACKSENT: 116 missed = "Terminate REQ"; 117 break; 118 default: 119 log_Printf(LogCBCP, "%s: Urk - unexpected CBCP timeout !\n", 120 cbcp->p->dl->name); 121 missed = NULL; 122 break; 123 } 124 if (missed) 125 log_Printf(LogCBCP, "%s: Timeout waiting for peer %s\n", 126 cbcp->p->dl->name, missed); 127 datalink_CBCPFailed(cbcp->p->dl); 128 } 129 } 130 131 static void 132 cbcp_StartTimer(struct cbcp *cbcp, int timeout) 133 { 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); 140 } 141 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 */ 147 148 static const char * const cbcpname[] = { 149 "closed", "stopped", "req-sent", "resp-sent", "ack-sent" 150 }; 151 152 static const char * 153 cbcpstate(int s) 154 { 155 if (s < sizeof cbcpname / sizeof cbcpname[0]) 156 return cbcpname[s]; 157 return HexStr(s, NULL, 0); 158 } 159 160 static void 161 cbcp_NewPhase(struct cbcp *cbcp, int new) 162 { 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; 167 } 168 } 169 170 struct cbcp_header { 171 u_char code; 172 u_char id; 173 u_int16_t length; /* Network byte order */ 174 }; 175 176 177 /* cbcp_header::code values */ 178 #define CBCP_REQ (1) 179 #define CBCP_RESPONSE (2) 180 #define CBCP_ACK (3) 181 182 struct cbcp_data { 183 u_char type; 184 u_char length; 185 u_char delay; 186 char addr_start[253]; /* max cbcp_data length 255 + 1 for NULL */ 187 }; 188 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) 194 195 static void 196 cbcp_Output(struct cbcp *cbcp, u_char code, struct cbcp_data *data) 197 { 198 struct cbcp_header *head; 199 struct mbuf *bp; 200 201 bp = m_get(sizeof *head + data->length, MB_CBCPOUT); 202 head = (struct cbcp_header *)MBUF_CTOP(bp); 203 head->code = code; 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); 210 } 211 212 static const char * 213 cbcp_data_Type(int type) 214 { 215 static const char * const types[] = { 216 "No callback", "User-spec", "Server-spec", "list" 217 }; 218 219 if (type < 1 || type > sizeof types / sizeof types[0]) 220 return HexStr(type, NULL, 0); 221 return types[type-1]; 222 } 223 224 struct cbcp_addr { 225 u_char type; 226 char addr[1]; /* Really ASCIIZ */ 227 }; 228 229 /* cbcp_data::type values */ 230 #define CBCP_ADDR_PSTN (1) 231 232 static void 233 cbcp_data_Show(struct cbcp_data *data) 234 { 235 struct cbcp_addr *addr; 236 char *end; 237 238 addr = (struct cbcp_addr *)data->addr_start; 239 end = (char *)data + data->length; 240 *end = '\0'; 241 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); 248 else 249 log_Printf(LogCBCP, " ADDR type %d ??\n", (int)addr->type); 250 addr = (struct cbcp_addr *)(addr->addr + strlen(addr->addr) + 1); 251 } 252 } 253 } 254 255 static void 256 cbcp_SendReq(struct cbcp *cbcp) 257 { 258 struct cbcp_data data; 259 struct cbcp_addr *addr; 260 char list[sizeof cbcp->fsm.phone], *next; 261 int len, max; 262 263 /* Only callees send REQs */ 264 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; 268 data.delay = 0; 269 strncpy(list, cbcp->fsm.phone, sizeof list - 1); 270 list[sizeof list - 1] = '\0'; 271 272 switch (data.type) { 273 case CBCP_CLIENTNUM: 274 addr = (struct cbcp_addr *)data.addr_start; 275 addr->type = CBCP_ADDR_PSTN; 276 *addr->addr = '\0'; 277 data.length = addr->addr - (char *)&data; 278 break; 279 280 case CBCP_LISTNUM: 281 addr = (struct cbcp_addr *)data.addr_start; 282 for (next = strtok(list, ","); next; next = strtok(NULL, ",")) { 283 len = strlen(next); 284 max = data.addr_start + sizeof data.addr_start - addr->addr - 1; 285 if (len <= max) { 286 addr->type = CBCP_ADDR_PSTN; 287 strcpy(addr->addr, next); 288 addr = (struct cbcp_addr *)((char *)addr + len + 2); 289 } else 290 log_Printf(LogWARN, "CBCP ADDR \"%s\" skipped - packet too large\n", 291 next); 292 } 293 data.length = (char *)addr - (char *)&data; 294 break; 295 296 case CBCP_SERVERNUM: 297 data.length = data.addr_start - (char *)&data; 298 break; 299 300 default: 301 data.length = (char *)&data.delay - (char *)&data; 302 break; 303 } 304 305 cbcp_data_Show(&data); 306 cbcp_Output(cbcp, CBCP_REQ, &data); 307 cbcp->fsm.restart--; 308 cbcp_StartTimer(cbcp, cbcp->fsm.delay); 309 cbcp_NewPhase(cbcp, CBCP_REQSENT); /* Wait for a RESPONSE */ 310 } 311 312 void 313 cbcp_Up(struct cbcp *cbcp) 314 { 315 struct lcp *lcp = &cbcp->p->link.lcp; 316 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'; 324 } 325 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'; 332 } else 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); 336 } else { 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; 344 else 345 cbcp->fsm.type = CBCP_SERVERNUM; 346 cbcp->fsm.restart = DEF_FSMTRIES; 347 cbcp_SendReq(cbcp); 348 } 349 } 350 351 static int 352 cbcp_AdjustResponse(struct cbcp *cbcp, struct cbcp_data *data) 353 { 354 /* 355 * We've received a REQ (data). Adjust our reponse (cbcp->fsm.*) 356 * so that we (hopefully) agree with the peer 357 */ 358 struct cbcp_addr *addr; 359 360 switch (data->type) { 361 case CBCP_NONUM: 362 if (cbcp->p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_NONE)) 363 /* 364 * if ``none'' is a configured callback possibility 365 * (ie, ``set callback cbcp none''), go along with the callees 366 * request 367 */ 368 cbcp->fsm.type = CBCP_NONUM; 369 370 /* 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.... 374 */ 375 376 return 1; 377 378 case CBCP_CLIENTNUM: 379 if (cbcp->fsm.type == CBCP_CLIENTNUM) { 380 char *ptr; 381 382 if (data->length > data->addr_start - (char *)data) { 383 /* 384 * The peer has given us an address type spec - make sure we 385 * understand ! 386 */ 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", 390 (int)addr->type); 391 return 0; 392 } 393 } 394 /* we accept the REQ even if the peer didn't specify an addr->type */ 395 ptr = strchr(cbcp->fsm.phone, ','); 396 if (ptr) 397 *ptr = '\0'; /* Just use the first number in our list */ 398 return 1; 399 } 400 log_Printf(LogPHASE, "CBCP: no number to pass to the peer !\n"); 401 return 0; 402 403 case CBCP_SERVERNUM: 404 if (cbcp->fsm.type == CBCP_SERVERNUM) { 405 *cbcp->fsm.phone = '\0'; 406 return 1; 407 } 408 if (data->length > data->addr_start - (char *)data) { 409 /* 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 413 * number 414 */ 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", 418 (int)addr->type); 419 return 0; 420 } else if (cbcp->fsm.type == CBCP_CLIENTNUM) { 421 /* 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 :-) 425 */ 426 char list[sizeof cbcp->fsm.phone], *next; 427 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); 434 return 1; 435 } 436 } 437 } 438 log_Printf(LogPHASE, "CBCP: Peer won't allow local decision !\n"); 439 return 0; 440 441 case CBCP_LISTNUM: 442 if (cbcp->fsm.type == CBCP_CLIENTNUM || cbcp->fsm.type == CBCP_LISTNUM) { 443 /* 444 * Search through ``data''s addresses and see if cbcp->fsm.phone 445 * contains any of them 446 */ 447 char list[sizeof cbcp->fsm.phone], *next, *end; 448 449 addr = (struct cbcp_addr *)data->addr_start; 450 end = (char *)data + data->length; 451 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); 460 return 1; 461 } 462 } else 463 log_Printf(LogCBCP, "Warning: Unrecognised address type %d !\n", 464 (int)addr->type); 465 addr = (struct cbcp_addr *)(addr->addr + strlen(addr->addr) + 1); 466 } 467 } 468 log_Printf(LogPHASE, "CBCP: no good number to pass to the peer !\n"); 469 return 0; 470 } 471 472 log_Printf(LogCBCP, "Unrecognised REQ type %d !\n", (int)data->type); 473 return 0; 474 } 475 476 static void 477 cbcp_SendResponse(struct cbcp *cbcp) 478 { 479 struct cbcp_data data; 480 struct cbcp_addr *addr; 481 482 /* Only callers send RESPONSEs */ 483 484 log_Printf(LogCBCP, "%s: SendResponse(%d) state = %s\n", cbcp->p->dl->name, 485 cbcp->fsm.id, cbcpstate(cbcp->fsm.state)); 486 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; 496 } else 497 data.length = data.addr_start - (char *)&data; 498 499 cbcp_data_Show(&data); 500 cbcp_Output(cbcp, CBCP_RESPONSE, &data); 501 cbcp->fsm.restart--; 502 cbcp_StartTimer(cbcp, cbcp->fsm.delay); 503 cbcp_NewPhase(cbcp, CBCP_RESPSENT); /* Wait for an ACK */ 504 } 505 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) 510 511 static int 512 cbcp_CheckResponse(struct cbcp *cbcp, struct cbcp_data *data) 513 { 514 /* 515 * We've received a RESPONSE (data). Check if it agrees with 516 * our REQ (cbcp->fsm) 517 */ 518 struct cbcp_addr *addr; 519 520 addr = (struct cbcp_addr *)data->addr_start; 521 522 if (data->type == cbcp->fsm.type) { 523 switch (cbcp->fsm.type) { 524 case CBCP_NONUM: 525 return CBCP_ACTION_ACK; 526 527 case CBCP_CLIENTNUM: 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", 532 addr->type); 533 else { 534 strcpy(cbcp->fsm.phone, addr->addr); 535 cbcp->fsm.delay = data->delay; 536 return CBCP_ACTION_ACK; 537 } 538 return CBCP_ACTION_DOWN; 539 540 case CBCP_SERVERNUM: 541 cbcp->fsm.delay = data->delay; 542 return CBCP_ACTION_ACK; 543 544 case CBCP_LISTNUM: 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", 549 addr->type); 550 else { 551 char list[sizeof cbcp->fsm.phone], *next; 552 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; 560 } 561 log_Printf(LogPHASE, "CBCP: peer didn't respond with a " 562 "valid number !\n"); 563 } 564 return CBCP_ACTION_DOWN; 565 } 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) { 570 /* 571 * Client doesn't want CBCP after all.... 572 * We only allow this when ``set cbcp *'' has been specified. 573 */ 574 cbcp->fsm.type = CBCP_NONUM; 575 return CBCP_ACTION_ACK; 576 } 577 log_Printf(LogCBCP, "Invalid peer RESPONSE\n"); 578 return CBCP_ACTION_REQ; 579 } 580 581 static void 582 cbcp_SendAck(struct cbcp *cbcp) 583 { 584 struct cbcp_data data; 585 struct cbcp_addr *addr; 586 587 /* Only callees send ACKs */ 588 589 log_Printf(LogCBCP, "%s: SendAck(%d) state = %s\n", cbcp->p->dl->name, 590 cbcp->fsm.id, cbcpstate(cbcp->fsm.state)); 591 592 data.type = cbcp->fsm.type; 593 switch (data.type) { 594 case CBCP_NONUM: 595 data.length = (char *)&data.delay - (char *)&data; 596 break; 597 case CBCP_CLIENTNUM: 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; 603 break; 604 default: 605 data.delay = cbcp->fsm.delay; 606 data.length = data.addr_start - (char *)&data; 607 break; 608 } 609 610 cbcp_data_Show(&data); 611 cbcp_Output(cbcp, CBCP_ACK, &data); 612 cbcp->fsm.restart--; 613 cbcp_StartTimer(cbcp, cbcp->fsm.delay); 614 cbcp_NewPhase(cbcp, CBCP_ACKSENT); /* Wait for an ACK */ 615 } 616 617 extern struct mbuf * 618 cbcp_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) 619 { 620 struct physical *p = link2physical(l); 621 struct cbcp_header *head; 622 struct cbcp_data *data; 623 struct cbcp *cbcp = &p->dl->cbcp; 624 int len; 625 626 if (p == NULL) { 627 log_Printf(LogERROR, "cbcp_Input: Not a physical link - dropped\n"); 628 m_freem(bp); 629 return NULL; 630 } 631 632 bp = m_pullup(bp); 633 len = m_length(bp); 634 if (len < sizeof(struct cbcp_header)) { 635 m_freem(bp); 636 return NULL; 637 } 638 head = (struct cbcp_header *)MBUF_CTOP(bp); 639 if (ntohs(head->length) != len) { 640 log_Printf(LogWARN, "Corrupt CBCP packet (code %d, length %d not %d)" 641 " - ignored\n", head->code, ntohs(head->length), len); 642 m_freem(bp); 643 return NULL; 644 } 645 m_settype(bp, MB_CBCPIN); 646 647 /* XXX check the id */ 648 649 bp->m_offset += sizeof(struct cbcp_header); 650 bp->m_len -= sizeof(struct cbcp_header); 651 data = (struct cbcp_data *)MBUF_CTOP(bp); 652 653 switch (head->code) { 654 case CBCP_REQ: 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); 664 } else 665 datalink_CBCPFailed(cbcp->p->dl); 666 } else 667 log_Printf(LogCBCP, "%s: unexpected REQ dropped\n", p->dl->name); 668 break; 669 670 case CBCP_RESPONSE: 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; 678 } 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: 683 cbcp_SendReq(cbcp); 684 break; 685 686 case CBCP_ACTION_ACK: 687 cbcp->fsm.restart = DEF_FSMTRIES; 688 cbcp_SendAck(cbcp); 689 if (cbcp->fsm.type == CBCP_NONUM) { 690 /* 691 * Don't change state in case the peer doesn't get our ACK, 692 * just bring the layer up. 693 */ 694 timer_Stop(&cbcp->fsm.timer); 695 datalink_NCPUp(cbcp->p->dl); 696 } 697 break; 698 699 default: 700 datalink_CBCPFailed(cbcp->p->dl); 701 break; 702 } 703 } else 704 log_Printf(LogCBCP, "%s: unexpected RESPONSE dropped\n", p->dl->name); 705 break; 706 707 case CBCP_ACK: 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; 715 } 716 if (cbcp->fsm.type == CBCP_NONUM) { 717 /* 718 * Don't change state in case the peer doesn't get our ACK, 719 * just bring the layer up. 720 */ 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); 727 } else 728 log_Printf(LogCBCP, "%s: unexpected ACK dropped\n", p->dl->name); 729 break; 730 731 default: 732 log_Printf(LogWARN, "Unrecognised CBCP packet (code %d, length %d)\n", 733 head->code, len); 734 break; 735 } 736 737 m_freem(bp); 738 return NULL; 739 } 740 741 void 742 cbcp_Down(struct cbcp *cbcp) 743 { 744 timer_Stop(&cbcp->fsm.timer); 745 cbcp_NewPhase(cbcp, CBCP_CLOSED); 746 cbcp->required = 0; 747 } 748 749 void 750 cbcp_ReceiveTerminateReq(struct physical *p) 751 { 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); 757 } else 758 cbcp_NewPhase(&p->dl->cbcp, CBCP_CLOSED); 759 } 760