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