1 /*- 2 * Copyright (c) 1998 Brian Somers <brian (at) 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: src/usr.sbin/ppp/cbcp.c,v 1.26.26.1 2010/12/21 17:10:29 kensmith Exp $ 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(unsigned 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(unsigned 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[sizeof ((struct cbcp_data *)0)->addr_start - 1]; /* 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 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); 290 } else 291 log_Printf(LogWARN, "CBCP ADDR \"%s\" skipped - packet too large\n", 292 next); 293 } 294 data.length = (char *)addr - (char *)&data; 295 break; 296 297 case CBCP_SERVERNUM: 298 data.length = data.addr_start - (char *)&data; 299 break; 300 301 default: 302 data.length = (char *)&data.delay - (char *)&data; 303 break; 304 } 305 306 cbcp_data_Show(&data); 307 cbcp_Output(cbcp, CBCP_REQ, &data); 308 cbcp->fsm.restart--; 309 cbcp_StartTimer(cbcp, cbcp->fsm.delay); 310 cbcp_NewPhase(cbcp, CBCP_REQSENT); /* Wait for a RESPONSE */ 311 } 312 313 void 314 cbcp_Up(struct cbcp *cbcp) 315 { 316 struct lcp *lcp = &cbcp->p->link.lcp; 317 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'; 325 } 326 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'; 333 } else 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); 337 } else { 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; 345 else 346 cbcp->fsm.type = CBCP_SERVERNUM; 347 cbcp->fsm.restart = DEF_FSMTRIES; 348 cbcp_SendReq(cbcp); 349 } 350 } 351 352 static int 353 cbcp_AdjustResponse(struct cbcp *cbcp, struct cbcp_data *data) 354 { 355 /* 356 * We've received a REQ (data). Adjust our reponse (cbcp->fsm.*) 357 * so that we (hopefully) agree with the peer 358 */ 359 struct cbcp_addr *addr; 360 361 switch (data->type) { 362 case CBCP_NONUM: 363 if (cbcp->p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_NONE)) 364 /* 365 * if ``none'' is a configured callback possibility 366 * (ie, ``set callback cbcp none''), go along with the callees 367 * request 368 */ 369 cbcp->fsm.type = CBCP_NONUM; 370 371 /* 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.... 375 */ 376 377 return 1; 378 379 case CBCP_CLIENTNUM: 380 if (cbcp->fsm.type == CBCP_CLIENTNUM) { 381 char *ptr; 382 383 if (data->length > data->addr_start - (char *)data) { 384 /* 385 * The peer has given us an address type spec - make sure we 386 * understand ! 387 */ 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", 391 (int)addr->type); 392 return 0; 393 } 394 } 395 /* we accept the REQ even if the peer didn't specify an addr->type */ 396 ptr = strchr(cbcp->fsm.phone, ','); 397 if (ptr) 398 *ptr = '\0'; /* Just use the first number in our list */ 399 return 1; 400 } 401 log_Printf(LogPHASE, "CBCP: no number to pass to the peer !\n"); 402 return 0; 403 404 case CBCP_SERVERNUM: 405 if (cbcp->fsm.type == CBCP_SERVERNUM) { 406 *cbcp->fsm.phone = '\0'; 407 return 1; 408 } 409 if (data->length > data->addr_start - (char *)data) { 410 /* 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 414 * number 415 */ 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", 419 (int)addr->type); 420 return 0; 421 } else if (cbcp->fsm.type == CBCP_CLIENTNUM) { 422 /* 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 :-) 426 */ 427 char list[sizeof cbcp->fsm.phone], *next; 428 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); 435 return 1; 436 } 437 } 438 } 439 log_Printf(LogPHASE, "CBCP: Peer won't allow local decision !\n"); 440 return 0; 441 442 case CBCP_LISTNUM: 443 if (cbcp->fsm.type == CBCP_CLIENTNUM || cbcp->fsm.type == CBCP_LISTNUM) { 444 /* 445 * Search through ``data''s addresses and see if cbcp->fsm.phone 446 * contains any of them 447 */ 448 char list[sizeof cbcp->fsm.phone], *next, *end; 449 450 addr = (struct cbcp_addr *)data->addr_start; 451 end = (char *)data + data->length; 452 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); 461 return 1; 462 } 463 } else 464 log_Printf(LogCBCP, "Warning: Unrecognised address type %d !\n", 465 (int)addr->type); 466 addr = (struct cbcp_addr *)(addr->addr + strlen(addr->addr) + 1); 467 } 468 } 469 log_Printf(LogPHASE, "CBCP: no good number to pass to the peer !\n"); 470 return 0; 471 } 472 473 log_Printf(LogCBCP, "Unrecognised REQ type %d !\n", (int)data->type); 474 return 0; 475 } 476 477 static void 478 cbcp_SendResponse(struct cbcp *cbcp) 479 { 480 struct cbcp_data data; 481 struct cbcp_addr *addr; 482 483 /* Only callers send RESPONSEs */ 484 485 log_Printf(LogCBCP, "%s: SendResponse(%d) state = %s\n", cbcp->p->dl->name, 486 cbcp->fsm.id, cbcpstate(cbcp->fsm.state)); 487 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; 498 } else 499 data.length = data.addr_start - (char *)&data; 500 501 cbcp_data_Show(&data); 502 cbcp_Output(cbcp, CBCP_RESPONSE, &data); 503 cbcp->fsm.restart--; 504 cbcp_StartTimer(cbcp, cbcp->fsm.delay); 505 cbcp_NewPhase(cbcp, CBCP_RESPSENT); /* Wait for an ACK */ 506 } 507 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) 512 513 static int 514 cbcp_CheckResponse(struct cbcp *cbcp, struct cbcp_data *data) 515 { 516 /* 517 * We've received a RESPONSE (data). Check if it agrees with 518 * our REQ (cbcp->fsm) 519 */ 520 struct cbcp_addr *addr; 521 522 addr = (struct cbcp_addr *)data->addr_start; 523 524 if (data->type == cbcp->fsm.type) { 525 switch (cbcp->fsm.type) { 526 case CBCP_NONUM: 527 return CBCP_ACTION_ACK; 528 529 case CBCP_CLIENTNUM: 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", 534 addr->type); 535 else { 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; 540 } 541 return CBCP_ACTION_DOWN; 542 543 case CBCP_SERVERNUM: 544 cbcp->fsm.delay = data->delay; 545 return CBCP_ACTION_ACK; 546 547 case CBCP_LISTNUM: 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", 552 addr->type); 553 else { 554 char list[sizeof cbcp->fsm.phone], *next; 555 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; 563 } 564 log_Printf(LogPHASE, "CBCP: peer didn't respond with a " 565 "valid number !\n"); 566 } 567 return CBCP_ACTION_DOWN; 568 } 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) { 573 /* 574 * Client doesn't want CBCP after all.... 575 * We only allow this when ``set cbcp *'' has been specified. 576 */ 577 cbcp->fsm.type = CBCP_NONUM; 578 return CBCP_ACTION_ACK; 579 } 580 log_Printf(LogCBCP, "Invalid peer RESPONSE\n"); 581 return CBCP_ACTION_REQ; 582 } 583 584 static void 585 cbcp_SendAck(struct cbcp *cbcp) 586 { 587 struct cbcp_data data; 588 struct cbcp_addr *addr; 589 590 /* Only callees send ACKs */ 591 592 log_Printf(LogCBCP, "%s: SendAck(%d) state = %s\n", cbcp->p->dl->name, 593 cbcp->fsm.id, cbcpstate(cbcp->fsm.state)); 594 595 data.type = cbcp->fsm.type; 596 switch (data.type) { 597 case CBCP_NONUM: 598 data.length = (char *)&data.delay - (char *)&data; 599 break; 600 case CBCP_CLIENTNUM: 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; 607 break; 608 default: 609 data.delay = cbcp->fsm.delay; 610 data.length = data.addr_start - (char *)&data; 611 break; 612 } 613 614 cbcp_data_Show(&data); 615 cbcp_Output(cbcp, CBCP_ACK, &data); 616 cbcp->fsm.restart--; 617 cbcp_StartTimer(cbcp, cbcp->fsm.delay); 618 cbcp_NewPhase(cbcp, CBCP_ACKSENT); /* Wait for an ACK */ 619 } 620 621 extern struct mbuf * 622 cbcp_Input(struct bundle *bundle __unused, struct link *l, struct mbuf *bp) 623 { 624 struct physical *p = link2physical(l); 625 struct cbcp_header *head; 626 struct cbcp_data *data; 627 struct cbcp *cbcp = &p->dl->cbcp; 628 size_t len; 629 630 if (p == NULL) { 631 log_Printf(LogERROR, "cbcp_Input: Not a physical link - dropped\n"); 632 m_freem(bp); 633 return NULL; 634 } 635 636 bp = m_pullup(bp); 637 len = m_length(bp); 638 if (len < sizeof(struct cbcp_header)) { 639 m_freem(bp); 640 return NULL; 641 } 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); 646 m_freem(bp); 647 return NULL; 648 } 649 m_settype(bp, MB_CBCPIN); 650 651 /* XXX check the id */ 652 653 bp->m_offset += sizeof(struct cbcp_header); 654 bp->m_len -= sizeof(struct cbcp_header); 655 data = (struct cbcp_data *)MBUF_CTOP(bp); 656 657 switch (head->code) { 658 case CBCP_REQ: 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); 668 } else 669 datalink_CBCPFailed(cbcp->p->dl); 670 } else 671 log_Printf(LogCBCP, "%s: unexpected REQ dropped\n", p->dl->name); 672 break; 673 674 case CBCP_RESPONSE: 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; 682 } 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: 687 cbcp_SendReq(cbcp); 688 break; 689 690 case CBCP_ACTION_ACK: 691 cbcp->fsm.restart = DEF_FSMTRIES; 692 cbcp_SendAck(cbcp); 693 if (cbcp->fsm.type == CBCP_NONUM) { 694 /* 695 * Don't change state in case the peer doesn't get our ACK, 696 * just bring the layer up. 697 */ 698 timer_Stop(&cbcp->fsm.timer); 699 datalink_NCPUp(cbcp->p->dl); 700 } 701 break; 702 703 default: 704 datalink_CBCPFailed(cbcp->p->dl); 705 break; 706 } 707 } else 708 log_Printf(LogCBCP, "%s: unexpected RESPONSE dropped\n", p->dl->name); 709 break; 710 711 case CBCP_ACK: 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; 719 } 720 if (cbcp->fsm.type == CBCP_NONUM) { 721 /* 722 * Don't change state in case the peer doesn't get our ACK, 723 * just bring the layer up. 724 */ 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); 731 } else 732 log_Printf(LogCBCP, "%s: unexpected ACK dropped\n", p->dl->name); 733 break; 734 735 default: 736 log_Printf(LogWARN, "Unrecognised CBCP packet (code %d, length %zd)\n", 737 head->code, len); 738 break; 739 } 740 741 m_freem(bp); 742 return NULL; 743 } 744 745 void 746 cbcp_Down(struct cbcp *cbcp) 747 { 748 timer_Stop(&cbcp->fsm.timer); 749 cbcp_NewPhase(cbcp, CBCP_CLOSED); 750 cbcp->required = 0; 751 } 752 753 void 754 cbcp_ReceiveTerminateReq(struct physical *p) 755 { 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); 761 } else 762 cbcp_NewPhase(&p->dl->cbcp, CBCP_CLOSED); 763 } 764