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