1 /* 2 * Copyright 2003-2005, Waldemar Kornewald <wkornew@gmx.net> 3 * Distributed under the terms of the MIT License. 4 */ 5 6 #if DEBUG 7 #include <cstdio> 8 #endif 9 10 #include "Protocol.h" 11 #include "IPCP.h" 12 #include <KPPPConfigurePacket.h> 13 #include <KPPPInterface.h> 14 #include <settings_tools.h> 15 16 #include <LockerHelper.h> 17 18 #include <cstring> 19 #include <netinet/in_var.h> 20 #include <core_funcs.h> 21 #include <sys/sockio.h> 22 23 24 #if DEBUG 25 #include <unistd.h> 26 27 static int sFD; 28 // the file descriptor for debug output 29 static char sDigits[] = "0123456789ABCDEF"; 30 void 31 dump_packet(struct mbuf *packet, const char *direction) 32 { 33 if(!packet) 34 return; 35 36 uint8 *data = mtod(packet, uint8*); 37 uint8 buffer[128]; 38 uint8 bufferIndex = 0; 39 40 sprintf((char*) buffer, "Dumping %s packet;len=%ld;pkthdr.len=%d\n", direction, 41 packet->m_len, packet->m_flags & M_PKTHDR ? packet->m_pkthdr.len : -1); 42 write(sFD, buffer, strlen((char*) buffer)); 43 44 for(uint32 index = 0; index < packet->m_len; index++) { 45 buffer[bufferIndex++] = sDigits[data[index] >> 4]; 46 buffer[bufferIndex++] = sDigits[data[index] & 0x0F]; 47 if(bufferIndex == 32 || index == packet->m_len - 1) { 48 buffer[bufferIndex++] = '\n'; 49 buffer[bufferIndex] = 0; 50 write(sFD, buffer, strlen((char*) buffer)); 51 bufferIndex = 0; 52 } 53 } 54 } 55 #endif 56 57 58 static const bigtime_t kIPCPStateMachineTimeout = 3000000; 59 // 3 seconds 60 61 62 IPCP::IPCP(KPPPInterface& interface, driver_parameter *settings) 63 : KPPPProtocol("IPCP", PPP_NCP_PHASE, IPCP_PROTOCOL, PPP_PROTOCOL_LEVEL, 64 AF_INET, 0, interface, settings, PPP_INCLUDES_NCP), 65 fDefaultRoute(NULL), 66 fRequestPrimaryDNS(false), 67 fRequestSecondaryDNS(false), 68 fState(PPP_INITIAL_STATE), 69 fID(system_time() & 0xFF), 70 fMaxRequest(10), 71 fMaxTerminate(2), 72 fMaxNak(5), 73 fRequestID(0), 74 fTerminateID(0), 75 fNextTimeout(0), 76 fLock("IPCP") 77 { 78 // reset configurations 79 memset(&fLocalConfiguration, 0, sizeof(ipcp_configuration)); 80 memset(&fPeerConfiguration, 0, sizeof(ipcp_configuration)); 81 82 // reset requests 83 memset(&fLocalRequests, 0, sizeof(ipcp_requests)); 84 memset(&fPeerRequests, 0, sizeof(ipcp_requests)); 85 86 // Parse settings: 87 // "Local" and "Peer" describe each side's settings 88 ParseSideRequests(get_parameter_with_name(IPCP_LOCAL_SIDE_KEY, Settings()), 89 PPP_LOCAL_SIDE); 90 ParseSideRequests(get_parameter_with_name(IPCP_PEER_SIDE_KEY, Settings()), 91 PPP_PEER_SIDE); 92 93 #if DEBUG 94 sFD = open("/boot/home/ipcpdebug", O_WRONLY | O_CREAT | O_TRUNC); 95 #endif 96 } 97 98 99 IPCP::~IPCP() 100 { 101 #if DEBUG 102 close(sFD); 103 #endif 104 } 105 106 107 void 108 IPCP::Uninit() 109 { 110 RemoveRoutes(); 111 } 112 113 114 status_t 115 IPCP::StackControl(uint32 op, void *data) 116 { 117 TRACE("IPCP: StackControl(op=%ld)\n", op); 118 119 // TODO: 120 // check values 121 122 switch(op) { 123 case SIOCSIFADDR: 124 break; 125 126 case SIOCSIFFLAGS: 127 break; 128 129 case SIOCSIFDSTADDR: 130 break; 131 132 case SIOCSIFNETMASK: 133 break; 134 135 default: 136 ERROR("IPCP: Unknown ioctl: %ld\n", op); 137 return KPPPProtocol::StackControl(op, data); 138 } 139 140 return B_OK; 141 } 142 143 144 bool 145 IPCP::Up() 146 { 147 TRACE("IPCP: Up() state=%d\n", State()); 148 149 // Servers do not send a configure-request when Up() is called. They wait until 150 // the client requests this protocol. 151 if(Interface().Mode() == PPP_SERVER_MODE) 152 return true; 153 154 LockerHelper locker(fLock); 155 156 switch(State()) { 157 case PPP_INITIAL_STATE: 158 NewState(PPP_REQ_SENT_STATE); 159 InitializeRestartCount(); 160 locker.UnlockNow(); 161 SendConfigureRequest(); 162 break; 163 164 default: 165 ; 166 } 167 168 return true; 169 } 170 171 172 bool 173 IPCP::Down() 174 { 175 TRACE("IPCP: Down() state=%d\n", State()); 176 177 LockerHelper locker(fLock); 178 179 switch(Interface().Phase()) { 180 case PPP_DOWN_PHASE: 181 // interface finished terminating 182 NewState(PPP_INITIAL_STATE); 183 locker.UnlockNow(); 184 ReportDownEvent(); 185 // this will also reset and update addresses 186 break; 187 188 /* case PPP_TERMINATION_PHASE: 189 // interface is terminating 190 break; 191 192 case PPP_ESTABLISHMENT_PHASE: 193 // interface is reconfiguring 194 break; 195 */ 196 case PPP_ESTABLISHED_PHASE: 197 // terminate this NCP individually (block until we finished terminating) 198 if(State() != PPP_INITIAL_STATE && State() != PPP_CLOSING_STATE) { 199 NewState(PPP_CLOSING_STATE); 200 InitializeRestartCount(); 201 locker.UnlockNow(); 202 SendTerminateRequest(); 203 } 204 205 while(State() == PPP_CLOSING_STATE) 206 snooze(50000); 207 break; 208 209 default: 210 ; 211 } 212 213 return true; 214 } 215 216 217 status_t 218 IPCP::Send(struct mbuf *packet, uint16 protocolNumber) 219 { 220 TRACE("IPCP: Send(0x%X)\n", protocolNumber); 221 222 if((protocolNumber == IP_PROTOCOL && State() == PPP_OPENED_STATE) 223 || protocolNumber == IPCP_PROTOCOL) { 224 #if DEBUG 225 dump_packet(packet, "outgoing"); 226 #endif 227 Interface().UpdateIdleSince(); 228 return SendToNext(packet, protocolNumber); 229 } 230 231 ERROR("IPCP: Send() failed because of wrong state or protocol number!\n"); 232 233 m_freem(packet); 234 return B_ERROR; 235 } 236 237 238 status_t 239 IPCP::Receive(struct mbuf *packet, uint16 protocolNumber) 240 { 241 TRACE("IPCP: Receive(0x%X)\n", protocolNumber); 242 243 if(!packet) 244 return B_ERROR; 245 246 if(protocolNumber == IP_PROTOCOL) 247 return ReceiveIPPacket(packet, protocolNumber); 248 249 if(protocolNumber != IPCP_PROTOCOL) 250 return PPP_UNHANDLED; 251 252 ppp_lcp_packet *data = mtod(packet, ppp_lcp_packet*); 253 254 // remove padding 255 int32 length = packet->m_len; 256 if(packet->m_flags & M_PKTHDR) 257 length = packet->m_pkthdr.len; 258 length -= ntohs(data->length); 259 if(length) 260 m_adj(packet, -length); 261 262 if(ntohs(data->length) < 4) 263 return B_ERROR; 264 265 // packet is freed by event methods 266 switch(data->code) { 267 case PPP_CONFIGURE_REQUEST: 268 RCREvent(packet); 269 break; 270 271 case PPP_CONFIGURE_ACK: 272 RCAEvent(packet); 273 break; 274 275 case PPP_CONFIGURE_NAK: 276 case PPP_CONFIGURE_REJECT: 277 RCNEvent(packet); 278 break; 279 280 case PPP_TERMINATE_REQUEST: 281 RTREvent(packet); 282 break; 283 284 case PPP_TERMINATE_ACK: 285 RTAEvent(packet); 286 break; 287 288 case PPP_CODE_REJECT: 289 RXJBadEvent(packet); 290 // we implemented the minimum requirements 291 break; 292 293 default: 294 RUCEvent(packet); 295 return PPP_REJECTED; 296 } 297 298 return B_OK; 299 } 300 301 302 status_t 303 IPCP::ReceiveIPPacket(struct mbuf *packet, uint16 protocolNumber) 304 { 305 if(protocolNumber != IP_PROTOCOL || State() != PPP_OPENED_STATE) 306 return PPP_UNHANDLED; 307 308 // TODO: add VJC support (the packet would be decoded here) 309 310 if (gProto[IPPROTO_IP] && gProto[IPPROTO_IP]->pr_input) { 311 #if DEBUG 312 dump_packet(packet, "incoming"); 313 #endif 314 Interface().UpdateIdleSince(); 315 gProto[IPPROTO_IP]->pr_input(packet, 0); 316 return B_OK; 317 } else { 318 ERROR("IPCP: Error: Could not find input function for IP!\n"); 319 m_freem(packet); 320 return B_ERROR; 321 } 322 } 323 324 325 void 326 IPCP::Pulse() 327 { 328 LockerHelper locker(fLock); 329 if(fNextTimeout == 0 || fNextTimeout > system_time()) 330 return; 331 fNextTimeout = 0; 332 locker.UnlockNow(); 333 334 switch(State()) { 335 case PPP_CLOSING_STATE: 336 if(fTerminateCounter <= 0) 337 TOBadEvent(); 338 else 339 TOGoodEvent(); 340 break; 341 342 case PPP_REQ_SENT_STATE: 343 case PPP_ACK_RCVD_STATE: 344 case PPP_ACK_SENT_STATE: 345 if(fRequestCounter <= 0) 346 TOBadEvent(); 347 else 348 TOGoodEvent(); 349 break; 350 351 default: 352 ; 353 } 354 } 355 356 357 bool 358 IPCP::ParseSideRequests(const driver_parameter *requests, ppp_side side) 359 { 360 if(!requests) 361 return false; 362 363 ipcp_requests *selectedRequests; 364 365 if(side == PPP_LOCAL_SIDE) { 366 selectedRequests = &fLocalRequests; 367 fRequestPrimaryDNS = fRequestSecondaryDNS = false; 368 } else 369 selectedRequests = &fPeerRequests; 370 371 memset(selectedRequests, 0, sizeof(ipcp_requests)); 372 // reset current requests 373 374 // The following values are allowed: 375 // "Address" the ip address that will be suggested 376 // "Netmask" the netmask that should be used 377 // "PrimaryDNS" primary DNS server 378 // "SecondaryDNS" secondary DNS server 379 // Setting any value to 0.0.0.0 or "auto" means it should be chosen automatically. 380 381 in_addr_t address = INADDR_ANY; 382 for(int32 index = 0; index < requests->parameter_count; index++) { 383 if(requests->parameters[index].value_count == 0) 384 continue; 385 386 // all values are IP addresses, so parse the address here 387 if(strcasecmp(requests->parameters[index].values[0], "auto")) { 388 address = inet_addr(requests->parameters[index].values[0]); 389 if(address == INADDR_NONE) 390 continue; 391 } 392 393 if(!strcasecmp(requests->parameters[index].name, IPCP_IP_ADDRESS_KEY)) 394 selectedRequests->address = address; 395 else if(!strcasecmp(requests->parameters[index].name, IPCP_NETMASK_KEY)) 396 selectedRequests->netmask = address; 397 else if(!strcasecmp(requests->parameters[index].name, IPCP_PRIMARY_DNS_KEY)) { 398 selectedRequests->primaryDNS = address; 399 if(side == PPP_LOCAL_SIDE) 400 fRequestPrimaryDNS = true; 401 } else if(!strcasecmp(requests->parameters[index].name, 402 IPCP_SECONDARY_DNS_KEY)) { 403 selectedRequests->secondaryDNS = address; 404 if(side == PPP_LOCAL_SIDE) 405 fRequestSecondaryDNS = true; 406 } 407 } 408 409 return true; 410 } 411 412 413 void 414 IPCP::UpdateAddresses() 415 { 416 RemoveRoutes(); 417 418 if(State() != PPP_OPENED_STATE && !Interface().DoesConnectOnDemand()) 419 return; 420 421 struct in_aliasreq inreq; 422 struct ifreq ifreqAddress, ifreqDestination; 423 memset(&inreq, 0, sizeof(struct in_aliasreq)); 424 memset(&ifreqAddress, 0, sizeof(struct ifreq)); 425 memset(&ifreqDestination, 0, sizeof(struct ifreq)); 426 memset(&fGateway, 0, sizeof(struct sockaddr_in)); 427 428 // create local address 429 inreq.ifra_addr.sin_family = AF_INET; 430 if(fLocalRequests.address != INADDR_ANY) 431 inreq.ifra_addr.sin_addr.s_addr = fLocalRequests.address; 432 else if(fLocalConfiguration.address == INADDR_ANY) 433 inreq.ifra_addr.sin_addr.s_addr = 0x010F0F0F; // was: INADDR_BROADCAST 434 else 435 inreq.ifra_addr.sin_addr.s_addr = fLocalConfiguration.address; 436 inreq.ifra_addr.sin_len = sizeof(struct sockaddr_in); 437 memcpy(&ifreqAddress.ifr_addr, &inreq.ifra_addr, sizeof(struct sockaddr_in)); 438 439 // create destination address 440 fGateway.sin_family = AF_INET; 441 if(fPeerRequests.address != INADDR_ANY) 442 fGateway.sin_addr.s_addr = fPeerRequests.address; 443 else if(fPeerConfiguration.address == INADDR_ANY) 444 fGateway.sin_addr.s_addr = 0x020F0F0F; // was: INADDR_BROADCAST 445 else 446 fGateway.sin_addr.s_addr = fPeerConfiguration.address; 447 fGateway.sin_len = sizeof(struct sockaddr_in); 448 memcpy(&inreq.ifra_dstaddr, &fGateway, 449 sizeof(struct sockaddr_in)); 450 memcpy(&ifreqDestination.ifr_dstaddr, &inreq.ifra_dstaddr, 451 sizeof(struct sockaddr_in)); 452 453 // create netmask 454 inreq.ifra_mask.sin_family = AF_INET; 455 inreq.ifra_mask.sin_addr.s_addr = fLocalRequests.netmask; 456 inreq.ifra_mask.sin_len = sizeof(struct sockaddr_in); 457 458 // tell stack to use these values 459 if(in_control(NULL, SIOCAIFADDR, (caddr_t) &inreq, 460 Interface().Ifnet()) != B_OK) 461 ERROR("IPCP: UpdateAddress(): SIOCAIFADDR returned error!\n"); 462 if(in_control(NULL, SIOCSIFADDR, (caddr_t) &ifreqAddress, 463 Interface().Ifnet()) != B_OK) 464 ERROR("IPCP: UpdateAddress(): SIOCSIFADDR returned error!\n"); 465 if(in_control(NULL, SIOCSIFDSTADDR, (caddr_t) &ifreqDestination, 466 Interface().Ifnet()) != B_OK) 467 ERROR("IPCP: UpdateAddress(): SIOCSIFDSTADDR returned error!\n"); 468 memcpy(&inreq.ifra_addr, &inreq.ifra_mask, sizeof(struct sockaddr_in)); 469 // SIOCISFNETMASK wants the netmask to be in ifra_addr 470 if(in_control(NULL, SIOCSIFNETMASK, (caddr_t) &inreq, 471 Interface().Ifnet()) != B_OK) 472 ERROR("IPCP: UpdateAddress(): SIOCSIFNETMASK returned error!\n"); 473 474 // add default/subnet route 475 if(Side() == PPP_LOCAL_SIDE) { 476 if(rtrequest(RTM_ADD, (struct sockaddr*) &inreq.ifra_mask, 477 (struct sockaddr*) &fGateway, (struct sockaddr*) &inreq.ifra_mask, 478 RTF_UP | RTF_GATEWAY, &fDefaultRoute) != B_OK) 479 ERROR("IPCP: UpdateAddress(): could not add default/subnet route!\n"); 480 481 --fDefaultRoute->rt_refcnt; 482 } 483 } 484 485 486 void 487 IPCP::RemoveRoutes() 488 { 489 // note: netstack creates and deletes destination route automatically 490 491 if(fDefaultRoute) { 492 struct sockaddr_in netmask; 493 memset(&netmask, 0, sizeof(struct sockaddr_in)); 494 495 netmask.sin_family = AF_INET; 496 netmask.sin_addr.s_addr = fLocalRequests.netmask; 497 netmask.sin_len = sizeof(struct sockaddr_in); 498 499 if(rtrequest(RTM_DELETE, (struct sockaddr*) &netmask, 500 (struct sockaddr*) &fGateway, (struct sockaddr*) &netmask, 501 RTF_UP | RTF_GATEWAY, &fDefaultRoute) != B_OK) 502 ERROR("IPCP: RemoveRoutes(): could not remove default/subnet route!\n"); 503 504 fDefaultRoute = NULL; 505 } 506 } 507 508 509 uint8 510 IPCP::NextID() 511 { 512 return (uint8) atomic_add(&fID, 1); 513 } 514 515 516 void 517 IPCP::NewState(ppp_state next) 518 { 519 TRACE("IPCP: NewState(%d) state=%d\n", next, State()); 520 521 // report state changes 522 if(State() == PPP_INITIAL_STATE && next != State()) 523 UpStarted(); 524 else if(State() == PPP_OPENED_STATE && next != State()) 525 DownStarted(); 526 527 // maybe we do not need the timer anymore 528 if(next < PPP_CLOSING_STATE || next == PPP_OPENED_STATE) 529 fNextTimeout = 0; 530 531 fState = next; 532 } 533 534 535 void 536 IPCP::TOGoodEvent() 537 { 538 #if DEBUG 539 printf("IPCP: TOGoodEvent() state=%d\n", State()); 540 #endif 541 542 LockerHelper locker(fLock); 543 544 switch(State()) { 545 case PPP_CLOSING_STATE: 546 locker.UnlockNow(); 547 SendTerminateRequest(); 548 break; 549 550 case PPP_ACK_RCVD_STATE: 551 NewState(PPP_REQ_SENT_STATE); 552 553 case PPP_REQ_SENT_STATE: 554 case PPP_ACK_SENT_STATE: 555 locker.UnlockNow(); 556 SendConfigureRequest(); 557 break; 558 559 default: 560 IllegalEvent(PPP_TO_GOOD_EVENT); 561 } 562 } 563 564 565 void 566 IPCP::TOBadEvent() 567 { 568 TRACE("IPCP: TOBadEvent() state=%d\n", State()); 569 570 LockerHelper locker(fLock); 571 572 switch(State()) { 573 case PPP_CLOSING_STATE: 574 NewState(PPP_INITIAL_STATE); 575 locker.UnlockNow(); 576 ReportDownEvent(); 577 break; 578 579 case PPP_REQ_SENT_STATE: 580 case PPP_ACK_RCVD_STATE: 581 case PPP_ACK_SENT_STATE: 582 NewState(PPP_INITIAL_STATE); 583 locker.UnlockNow(); 584 ReportUpFailedEvent(); 585 break; 586 587 default: 588 IllegalEvent(PPP_TO_BAD_EVENT); 589 } 590 } 591 592 593 void 594 IPCP::RCREvent(struct mbuf *packet) 595 { 596 TRACE("IPCP: RCREvent() state=%d\n", State()); 597 598 KPPPConfigurePacket request(packet); 599 KPPPConfigurePacket nak(PPP_CONFIGURE_NAK); 600 KPPPConfigurePacket reject(PPP_CONFIGURE_REJECT); 601 602 // we should not use the same id as the peer 603 if(fID == mtod(packet, ppp_lcp_packet*)->id) 604 fID -= 128; 605 606 nak.SetID(request.ID()); 607 reject.SetID(request.ID()); 608 609 // parse each item 610 ppp_configure_item *item; 611 in_addr_t *requestedAddress, *wishedAddress = NULL; 612 for(int32 index = 0; index < request.CountItems(); index++) { 613 item = request.ItemAt(index); 614 if(!item) 615 continue; 616 617 // addresses have special handling to reduce code size 618 switch(item->type) { 619 case IPCP_ADDRESSES: 620 // abandoned by the standard 621 case IPCP_ADDRESS: 622 wishedAddress = &fPeerRequests.address; 623 break; 624 625 case IPCP_PRIMARY_DNS: 626 wishedAddress = &fPeerRequests.primaryDNS; 627 break; 628 629 case IPCP_SECONDARY_DNS: 630 wishedAddress = &fPeerRequests.secondaryDNS; 631 break; 632 } 633 634 // now parse item 635 switch(item->type) { 636 case IPCP_ADDRESSES: 637 // abandoned by the standard 638 case IPCP_ADDRESS: 639 case IPCP_PRIMARY_DNS: 640 case IPCP_SECONDARY_DNS: 641 if(item->length != 6) { 642 // the packet is invalid 643 m_freem(packet); 644 NewState(PPP_INITIAL_STATE); 645 ReportUpFailedEvent(); 646 return; 647 } 648 649 requestedAddress = (in_addr_t*) item->data; 650 if(*wishedAddress == INADDR_ANY) { 651 if(*requestedAddress == INADDR_ANY) { 652 // we do not have an address for you 653 m_freem(packet); 654 NewState(PPP_INITIAL_STATE); 655 ReportUpFailedEvent(); 656 return; 657 } 658 } else if(*requestedAddress != *wishedAddress) { 659 // we do not want this address 660 ip_item ipItem; 661 ipItem.type = item->type; 662 ipItem.length = 6; 663 ipItem.address = *wishedAddress; 664 nak.AddItem((ppp_configure_item*) &ipItem); 665 } 666 break; 667 668 // case IPCP_COMPRESSION_PROTOCOL: 669 // TODO: implement me! 670 // break; 671 672 default: 673 reject.AddItem(item); 674 } 675 } 676 677 // append additional values to the nak 678 if(!request.ItemWithType(IPCP_ADDRESS) && fPeerRequests.address == INADDR_ANY) { 679 // The peer did not provide us his address. Tell him to do so. 680 ip_item ipItem; 681 ipItem.type = IPCP_ADDRESS; 682 ipItem.length = 6; 683 ipItem.address = INADDR_ANY; 684 nak.AddItem((ppp_configure_item*) &ipItem); 685 } 686 687 if(nak.CountItems() > 0) { 688 RCRBadEvent(nak.ToMbuf(Interface().MRU(), Interface().PacketOverhead()), NULL); 689 m_freem(packet); 690 } else if(reject.CountItems() > 0) { 691 RCRBadEvent(NULL, reject.ToMbuf(Interface().MRU(), 692 Interface().PacketOverhead())); 693 m_freem(packet); 694 } else 695 RCRGoodEvent(packet); 696 } 697 698 699 void 700 IPCP::RCRGoodEvent(struct mbuf *packet) 701 { 702 TRACE("IPCP: RCRGoodEvent() state=%d\n", State()); 703 704 LockerHelper locker(fLock); 705 706 switch(State()) { 707 case PPP_INITIAL_STATE: 708 NewState(PPP_ACK_SENT_STATE); 709 InitializeRestartCount(); 710 locker.UnlockNow(); 711 SendConfigureRequest(); 712 SendConfigureAck(packet); 713 break; 714 715 case PPP_REQ_SENT_STATE: 716 NewState(PPP_ACK_SENT_STATE); 717 718 case PPP_ACK_SENT_STATE: 719 locker.UnlockNow(); 720 SendConfigureAck(packet); 721 break; 722 723 case PPP_ACK_RCVD_STATE: 724 NewState(PPP_OPENED_STATE); 725 locker.UnlockNow(); 726 SendConfigureAck(packet); 727 ReportUpEvent(); 728 break; 729 730 case PPP_OPENED_STATE: 731 NewState(PPP_ACK_SENT_STATE); 732 locker.UnlockNow(); 733 SendConfigureRequest(); 734 SendConfigureAck(packet); 735 break; 736 737 default: 738 m_freem(packet); 739 } 740 } 741 742 743 void 744 IPCP::RCRBadEvent(struct mbuf *nak, struct mbuf *reject) 745 { 746 TRACE("IPCP: RCRBadEvent() state=%d\n", State()); 747 748 LockerHelper locker(fLock); 749 750 switch(State()) { 751 case PPP_OPENED_STATE: 752 NewState(PPP_REQ_SENT_STATE); 753 locker.UnlockNow(); 754 SendConfigureRequest(); 755 756 case PPP_ACK_SENT_STATE: 757 if(State() == PPP_ACK_SENT_STATE) 758 NewState(PPP_REQ_SENT_STATE); 759 // OPENED_STATE might have set this already 760 761 case PPP_INITIAL_STATE: 762 case PPP_REQ_SENT_STATE: 763 case PPP_ACK_RCVD_STATE: 764 locker.UnlockNow(); 765 if(nak && ntohs(mtod(nak, ppp_lcp_packet*)->length) > 3) 766 SendConfigureNak(nak); 767 else if(reject && ntohs(mtod(reject, ppp_lcp_packet*)->length) > 3) 768 SendConfigureNak(reject); 769 return; 770 // prevents the nak/reject from being m_freem()'d 771 772 default: 773 ; 774 } 775 776 if(nak) 777 m_freem(nak); 778 if(reject) 779 m_freem(reject); 780 } 781 782 783 void 784 IPCP::RCAEvent(struct mbuf *packet) 785 { 786 TRACE("IPCP: RCAEvent() state=%d\n", State()); 787 788 LockerHelper locker(fLock); 789 790 if(fRequestID != mtod(packet, ppp_lcp_packet*)->id) { 791 // this packet is not a reply to our request 792 793 // TODO: log this event 794 m_freem(packet); 795 return; 796 } 797 798 // parse this ack 799 KPPPConfigurePacket ack(packet); 800 ppp_configure_item *item; 801 in_addr_t *requestedAddress, *wishedAddress = NULL, *configuredAddress = NULL; 802 for(int32 index = 0; index < ack.CountItems(); index++) { 803 item = ack.ItemAt(index); 804 if(!item) 805 continue; 806 807 // addresses have special handling to reduce code size 808 switch(item->type) { 809 case IPCP_ADDRESSES: 810 // abandoned by the standard 811 case IPCP_ADDRESS: 812 wishedAddress = &fLocalRequests.address; 813 configuredAddress = &fLocalConfiguration.address; 814 break; 815 816 case IPCP_PRIMARY_DNS: 817 wishedAddress = &fLocalRequests.primaryDNS; 818 configuredAddress = &fLocalConfiguration.primaryDNS; 819 break; 820 821 case IPCP_SECONDARY_DNS: 822 wishedAddress = &fLocalRequests.secondaryDNS; 823 configuredAddress = &fLocalConfiguration.secondaryDNS; 824 break; 825 } 826 827 // now parse item 828 switch(item->type) { 829 case IPCP_ADDRESSES: 830 // abandoned by the standard 831 case IPCP_ADDRESS: 832 case IPCP_PRIMARY_DNS: 833 case IPCP_SECONDARY_DNS: 834 requestedAddress = (in_addr_t*) item->data; 835 if((*wishedAddress == INADDR_ANY && *requestedAddress != INADDR_ANY) 836 || *wishedAddress == *requestedAddress) 837 *configuredAddress = *requestedAddress; 838 break; 839 840 // case IPCP_COMPRESSION_PROTOCOL: 841 // TODO: implement me 842 // break; 843 844 default: 845 ; 846 } 847 } 848 849 // if address was not specified we should select the given one 850 if(!ack.ItemWithType(IPCP_ADDRESS)) 851 fLocalConfiguration.address = fLocalRequests.address; 852 853 854 switch(State()) { 855 case PPP_INITIAL_STATE: 856 IllegalEvent(PPP_RCA_EVENT); 857 break; 858 859 case PPP_REQ_SENT_STATE: 860 NewState(PPP_ACK_RCVD_STATE); 861 InitializeRestartCount(); 862 break; 863 864 case PPP_ACK_RCVD_STATE: 865 NewState(PPP_REQ_SENT_STATE); 866 locker.UnlockNow(); 867 SendConfigureRequest(); 868 break; 869 870 case PPP_ACK_SENT_STATE: 871 NewState(PPP_OPENED_STATE); 872 InitializeRestartCount(); 873 locker.UnlockNow(); 874 ReportUpEvent(); 875 break; 876 877 case PPP_OPENED_STATE: 878 NewState(PPP_REQ_SENT_STATE); 879 locker.UnlockNow(); 880 SendConfigureRequest(); 881 break; 882 883 default: 884 ; 885 } 886 887 m_freem(packet); 888 } 889 890 891 void 892 IPCP::RCNEvent(struct mbuf *packet) 893 { 894 TRACE("IPCP: RCNEvent() state=%d\n", State()); 895 896 LockerHelper locker(fLock); 897 898 if(fRequestID != mtod(packet, ppp_lcp_packet*)->id) { 899 // this packet is not a reply to our request 900 901 // TODO: log this event 902 m_freem(packet); 903 return; 904 } 905 906 // parse this nak/reject 907 KPPPConfigurePacket nak_reject(packet); 908 ppp_configure_item *item; 909 in_addr_t *requestedAddress; 910 if(nak_reject.Code() == PPP_CONFIGURE_NAK) 911 for(int32 index = 0; index < nak_reject.CountItems(); index++) { 912 item = nak_reject.ItemAt(index); 913 if(!item) 914 continue; 915 916 switch(item->type) { 917 case IPCP_ADDRESSES: 918 // abandoned by the standard 919 case IPCP_ADDRESS: 920 if(item->length != 6) 921 continue; 922 923 requestedAddress = (in_addr_t*) item->data; 924 if(fLocalRequests.address == INADDR_ANY 925 && *requestedAddress != INADDR_ANY) 926 fLocalConfiguration.address = *requestedAddress; 927 // this will be used in our next request 928 break; 929 930 // case IPCP_COMPRESSION_PROTOCOL: 931 // TODO: implement me! 932 // break; 933 934 case IPCP_PRIMARY_DNS: 935 if(item->length != 6) 936 continue; 937 938 requestedAddress = (in_addr_t*) item->data; 939 if(fRequestPrimaryDNS 940 && fLocalRequests.primaryDNS == INADDR_ANY 941 && *requestedAddress != INADDR_ANY) 942 fLocalConfiguration.primaryDNS = *requestedAddress; 943 // this will be used in our next request 944 break; 945 946 case IPCP_SECONDARY_DNS: 947 if(item->length != 6) 948 continue; 949 950 requestedAddress = (in_addr_t*) item->data; 951 if(fRequestSecondaryDNS 952 && fLocalRequests.secondaryDNS == INADDR_ANY 953 && *requestedAddress != INADDR_ANY) 954 fLocalConfiguration.secondaryDNS = *requestedAddress; 955 // this will be used in our next request 956 break; 957 958 default: 959 ; 960 } 961 } 962 else if(nak_reject.Code() == PPP_CONFIGURE_REJECT) 963 for(int32 index = 0; index < nak_reject.CountItems(); index++) { 964 item = nak_reject.ItemAt(index); 965 if(!item) 966 continue; 967 968 switch(item->type) { 969 // case IPCP_COMPRESSION_PROTOCOL: 970 // TODO: implement me! 971 // break; 972 973 default: 974 // DNS and addresses must be supported if we set them to auto 975 m_freem(packet); 976 NewState(PPP_INITIAL_STATE); 977 ReportUpFailedEvent(); 978 return; 979 } 980 } 981 982 switch(State()) { 983 case PPP_INITIAL_STATE: 984 IllegalEvent(PPP_RCN_EVENT); 985 break; 986 987 case PPP_REQ_SENT_STATE: 988 case PPP_ACK_SENT_STATE: 989 InitializeRestartCount(); 990 991 case PPP_ACK_RCVD_STATE: 992 case PPP_OPENED_STATE: 993 if(State() == PPP_ACK_RCVD_STATE || State() == PPP_OPENED_STATE) 994 NewState(PPP_REQ_SENT_STATE); 995 locker.UnlockNow(); 996 SendConfigureRequest(); 997 break; 998 999 default: 1000 ; 1001 } 1002 1003 m_freem(packet); 1004 } 1005 1006 1007 void 1008 IPCP::RTREvent(struct mbuf *packet) 1009 { 1010 TRACE("IPCP: RTREvent() state=%d\n", State()); 1011 1012 LockerHelper locker(fLock); 1013 1014 // we should not use the same ID as the peer 1015 if(fID == mtod(packet, ppp_lcp_packet*)->id) 1016 fID -= 128; 1017 1018 switch(State()) { 1019 case PPP_INITIAL_STATE: 1020 IllegalEvent(PPP_RTR_EVENT); 1021 break; 1022 1023 case PPP_ACK_RCVD_STATE: 1024 case PPP_ACK_SENT_STATE: 1025 NewState(PPP_REQ_SENT_STATE); 1026 1027 case PPP_CLOSING_STATE: 1028 case PPP_REQ_SENT_STATE: 1029 locker.UnlockNow(); 1030 SendTerminateAck(packet); 1031 return; 1032 // do not m_freem() packet 1033 1034 case PPP_OPENED_STATE: 1035 NewState(PPP_CLOSING_STATE); 1036 ZeroRestartCount(); 1037 locker.UnlockNow(); 1038 SendTerminateAck(packet); 1039 return; 1040 // do not m_freem() packet 1041 1042 default: 1043 ; 1044 } 1045 1046 m_freem(packet); 1047 } 1048 1049 1050 void 1051 IPCP::RTAEvent(struct mbuf *packet) 1052 { 1053 TRACE("IPCP: RTAEvent() state=%d\n", State()); 1054 1055 LockerHelper locker(fLock); 1056 1057 if(fTerminateID != mtod(packet, ppp_lcp_packet*)->id) { 1058 // this packet is not a reply to our request 1059 1060 // TODO: log this event 1061 m_freem(packet); 1062 return; 1063 } 1064 1065 switch(State()) { 1066 case PPP_INITIAL_STATE: 1067 IllegalEvent(PPP_RTA_EVENT); 1068 break; 1069 1070 case PPP_CLOSING_STATE: 1071 NewState(PPP_INITIAL_STATE); 1072 locker.UnlockNow(); 1073 ReportDownEvent(); 1074 break; 1075 1076 case PPP_ACK_RCVD_STATE: 1077 NewState(PPP_REQ_SENT_STATE); 1078 break; 1079 1080 case PPP_OPENED_STATE: 1081 NewState(PPP_REQ_SENT_STATE); 1082 locker.UnlockNow(); 1083 SendConfigureRequest(); 1084 break; 1085 1086 default: 1087 ; 1088 } 1089 1090 m_freem(packet); 1091 } 1092 1093 1094 void 1095 IPCP::RUCEvent(struct mbuf *packet) 1096 { 1097 TRACE("IPCP: RUCEvent() state=%d\n", State()); 1098 1099 SendCodeReject(packet); 1100 } 1101 1102 1103 void 1104 IPCP::RXJBadEvent(struct mbuf *packet) 1105 { 1106 TRACE("IPCP: RXJBadEvent() state=%d\n", State()); 1107 1108 LockerHelper locker(fLock); 1109 1110 switch(State()) { 1111 case PPP_INITIAL_STATE: 1112 IllegalEvent(PPP_RXJ_BAD_EVENT); 1113 break; 1114 1115 case PPP_CLOSING_STATE: 1116 NewState(PPP_INITIAL_STATE); 1117 locker.UnlockNow(); 1118 ReportDownEvent(); 1119 break; 1120 1121 case PPP_REQ_SENT_STATE: 1122 case PPP_ACK_RCVD_STATE: 1123 case PPP_ACK_SENT_STATE: 1124 NewState(PPP_INITIAL_STATE); 1125 locker.UnlockNow(); 1126 ReportUpFailedEvent(); 1127 break; 1128 1129 case PPP_OPENED_STATE: 1130 NewState(PPP_CLOSING_STATE); 1131 InitializeRestartCount(); 1132 locker.UnlockNow(); 1133 SendTerminateRequest(); 1134 break; 1135 1136 default: 1137 ; 1138 } 1139 1140 m_freem(packet); 1141 } 1142 1143 1144 // actions 1145 void 1146 IPCP::IllegalEvent(ppp_event event) 1147 { 1148 // TODO: update error statistics 1149 ERROR("IPCP: IllegalEvent(event=%d) state=%d\n", event, State()); 1150 } 1151 1152 1153 void 1154 IPCP::ReportUpFailedEvent() 1155 { 1156 // reset configurations 1157 memset(&fLocalConfiguration, 0, sizeof(ipcp_configuration)); 1158 memset(&fPeerConfiguration, 0, sizeof(ipcp_configuration)); 1159 1160 UpdateAddresses(); 1161 1162 UpFailedEvent(); 1163 } 1164 1165 1166 void 1167 IPCP::ReportUpEvent() 1168 { 1169 UpdateAddresses(); 1170 1171 UpEvent(); 1172 } 1173 1174 1175 void 1176 IPCP::ReportDownEvent() 1177 { 1178 // reset configurations 1179 memset(&fLocalConfiguration, 0, sizeof(ipcp_configuration)); 1180 memset(&fPeerConfiguration, 0, sizeof(ipcp_configuration)); 1181 1182 UpdateAddresses(); 1183 1184 DownEvent(); 1185 } 1186 1187 1188 void 1189 IPCP::InitializeRestartCount() 1190 { 1191 fRequestCounter = fMaxRequest; 1192 fTerminateCounter = fMaxTerminate; 1193 fNakCounter = fMaxNak; 1194 } 1195 1196 1197 void 1198 IPCP::ZeroRestartCount() 1199 { 1200 fRequestCounter = 0; 1201 fTerminateCounter = 0; 1202 fNakCounter = 0; 1203 } 1204 1205 1206 bool 1207 IPCP::SendConfigureRequest() 1208 { 1209 TRACE("IPCP: SendConfigureRequest() state=%d\n", State()); 1210 1211 LockerHelper locker(fLock); 1212 --fRequestCounter; 1213 fNextTimeout = system_time() + kIPCPStateMachineTimeout; 1214 locker.UnlockNow(); 1215 1216 KPPPConfigurePacket request(PPP_CONFIGURE_REQUEST); 1217 request.SetID(NextID()); 1218 fRequestID = request.ID(); 1219 ip_item ipItem; 1220 ipItem.length = 6; 1221 1222 // add address 1223 ipItem.type = IPCP_ADDRESS; 1224 if(fLocalRequests.address == INADDR_ANY) 1225 ipItem.address = fLocalConfiguration.address; 1226 else 1227 ipItem.address = fLocalRequests.address; 1228 request.AddItem((ppp_configure_item*) &ipItem); 1229 1230 TRACE("IPCP: SCR: confaddr=%lX; reqaddr=%lX; addr=%lX\n", 1231 fLocalConfiguration.address, fLocalRequests.address, 1232 ((ip_item*)request.ItemAt(0))->address); 1233 1234 // add primary DNS (if needed) 1235 if(fRequestPrimaryDNS && fLocalRequests.primaryDNS == INADDR_ANY) { 1236 ipItem.type = IPCP_PRIMARY_DNS; 1237 ipItem.address = fLocalConfiguration.primaryDNS; 1238 // at first this is 0.0.0.0, but a nak might have set it to a correct value 1239 request.AddItem((ppp_configure_item*) &ipItem); 1240 } 1241 1242 // add secondary DNS (if needed) 1243 if(fRequestSecondaryDNS && fLocalRequests.primaryDNS == INADDR_ANY) { 1244 ipItem.type = IPCP_SECONDARY_DNS; 1245 ipItem.address = fLocalConfiguration.secondaryDNS; 1246 // at first this is 0.0.0.0, but a nak might have set it to a correct value 1247 request.AddItem((ppp_configure_item*) &ipItem); 1248 } 1249 1250 // TODO: add VJC support 1251 1252 return Send(request.ToMbuf(Interface().MRU(), 1253 Interface().PacketOverhead())) == B_OK; 1254 } 1255 1256 1257 bool 1258 IPCP::SendConfigureAck(struct mbuf *packet) 1259 { 1260 TRACE("IPCP: SendConfigureAck() state=%d\n", State()); 1261 1262 if(!packet) 1263 return false; 1264 1265 mtod(packet, ppp_lcp_packet*)->code = PPP_CONFIGURE_ACK; 1266 KPPPConfigurePacket ack(packet); 1267 1268 // verify items 1269 ppp_configure_item *item; 1270 in_addr_t *requestedAddress, *wishedAddress = NULL, *configuredAddress = NULL; 1271 for(int32 index = 0; index < ack.CountItems(); index++) { 1272 item = ack.ItemAt(index); 1273 if(!item) 1274 continue; 1275 1276 // addresses have special handling to reduce code size 1277 switch(item->type) { 1278 case IPCP_ADDRESSES: 1279 // abandoned by the standard 1280 case IPCP_ADDRESS: 1281 wishedAddress = &fPeerRequests.address; 1282 configuredAddress = &fPeerConfiguration.address; 1283 break; 1284 1285 case IPCP_PRIMARY_DNS: 1286 wishedAddress = &fPeerRequests.primaryDNS; 1287 configuredAddress = &fPeerConfiguration.primaryDNS; 1288 break; 1289 1290 case IPCP_SECONDARY_DNS: 1291 wishedAddress = &fPeerRequests.secondaryDNS; 1292 configuredAddress = &fPeerConfiguration.secondaryDNS; 1293 break; 1294 } 1295 1296 // now parse item 1297 switch(item->type) { 1298 case IPCP_ADDRESSES: 1299 // abandoned by the standard 1300 case IPCP_ADDRESS: 1301 case IPCP_PRIMARY_DNS: 1302 case IPCP_SECONDARY_DNS: 1303 requestedAddress = (in_addr_t*) item->data; 1304 if((*wishedAddress == INADDR_ANY && *requestedAddress != INADDR_ANY) 1305 || *wishedAddress == *requestedAddress) 1306 *configuredAddress = *requestedAddress; 1307 break; 1308 1309 // case IPCP_COMPRESSION_PROTOCOL: 1310 // TODO: implement me! 1311 // break; 1312 1313 default: 1314 ; 1315 } 1316 } 1317 1318 // if address was not specified we should select the given one 1319 if(!ack.ItemWithType(IPCP_ADDRESS)) 1320 fPeerConfiguration.address = fPeerRequests.address; 1321 1322 return Send(packet) == B_OK; 1323 } 1324 1325 1326 bool 1327 IPCP::SendConfigureNak(struct mbuf *packet) 1328 { 1329 TRACE("IPCP: SendConfigureNak() state=%d\n", State()); 1330 1331 if(!packet) 1332 return false; 1333 1334 ppp_lcp_packet *nak = mtod(packet, ppp_lcp_packet*); 1335 if(nak->code == PPP_CONFIGURE_NAK) { 1336 if(fNakCounter == 0) { 1337 // We sent enough naks. Let's try a reject. 1338 nak->code = PPP_CONFIGURE_REJECT; 1339 } else 1340 --fNakCounter; 1341 } 1342 1343 return Send(packet) == B_OK; 1344 } 1345 1346 1347 bool 1348 IPCP::SendTerminateRequest() 1349 { 1350 TRACE("IPCP: SendTerminateRequest() state=%d\n", State()); 1351 1352 LockerHelper locker(fLock); 1353 --fTerminateCounter; 1354 fNextTimeout = system_time() + kIPCPStateMachineTimeout; 1355 locker.UnlockNow(); 1356 1357 struct mbuf *packet = m_gethdr(MT_DATA); 1358 if(!packet) 1359 return false; 1360 1361 packet->m_pkthdr.len = packet->m_len = 4; 1362 1363 // reserve some space for other protocols 1364 packet->m_data += Interface().PacketOverhead(); 1365 1366 ppp_lcp_packet *request = mtod(packet, ppp_lcp_packet*); 1367 request->code = PPP_TERMINATE_REQUEST; 1368 request->id = fTerminateID = NextID(); 1369 request->length = htons(4); 1370 1371 return Send(packet) == B_OK; 1372 } 1373 1374 1375 bool 1376 IPCP::SendTerminateAck(struct mbuf *request) 1377 { 1378 TRACE("IPCP: SendTerminateAck() state=%d\n", State()); 1379 1380 struct mbuf *reply = request; 1381 1382 ppp_lcp_packet *ack; 1383 1384 if(!reply) { 1385 reply = m_gethdr(MT_DATA); 1386 if(!reply) 1387 return false; 1388 1389 reply->m_data += Interface().PacketOverhead(); 1390 reply->m_pkthdr.len = reply->m_len = 4; 1391 1392 ack = mtod(reply, ppp_lcp_packet*); 1393 ack->id = NextID(); 1394 } else 1395 ack = mtod(reply, ppp_lcp_packet*); 1396 1397 ack->code = PPP_TERMINATE_ACK; 1398 ack->length = htons(4); 1399 1400 return Send(reply) == B_OK; 1401 } 1402 1403 1404 bool 1405 IPCP::SendCodeReject(struct mbuf *packet) 1406 { 1407 TRACE("IPCP: SendCodeReject() state=%d\n", State()); 1408 1409 if(!packet) 1410 return false; 1411 1412 M_PREPEND(packet, 4); 1413 // add some space for the header 1414 1415 // adjust packet if too big 1416 int32 adjust = Interface().MRU(); 1417 if(packet->m_flags & M_PKTHDR) { 1418 adjust -= packet->m_pkthdr.len; 1419 } else 1420 adjust -= packet->m_len; 1421 1422 if(adjust < 0) 1423 m_adj(packet, adjust); 1424 1425 ppp_lcp_packet *reject = mtod(packet, ppp_lcp_packet*); 1426 reject->code = PPP_CODE_REJECT; 1427 reject->id = NextID(); 1428 if(packet->m_flags & M_PKTHDR) 1429 reject->length = htons(packet->m_pkthdr.len); 1430 else 1431 reject->length = htons(packet->m_len); 1432 1433 return Send(packet) == B_OK; 1434 } 1435