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