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