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