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 // cstdio must be included before KPPPModule.h/KPPPManager.h because 9 // ddprintf is defined twice with different return values, once with 10 // void (KernelExport.h) and once with int (stdio.h). 11 #include <cstdio> 12 #include <cstring> 13 #include <core_funcs.h> 14 15 // now our headers... 16 #include <KPPPInterface.h> 17 18 // our other classes 19 #include <PPPControl.h> 20 #include <KPPPDevice.h> 21 #include <KPPPLCPExtension.h> 22 #include <KPPPOptionHandler.h> 23 #include <KPPPModule.h> 24 #include <KPPPManager.h> 25 #include <KPPPUtils.h> 26 27 // general helper classes not only belonging to us 28 #include <LockerHelper.h> 29 30 // tools only for us :) 31 #include "settings_tools.h" 32 33 // internal modules 34 #include "_KPPPMRUHandler.h" 35 #include "_KPPPAuthenticationHandler.h" 36 #include "_KPPPPFCHandler.h" 37 38 39 // TODO: 40 // - implement timers with support for settings next time instead of receiving timer 41 // events periodically 42 // - add missing settings support (DialRetryDelay, etc.) 43 44 45 // needed for redial: 46 typedef struct redial_info { 47 KPPPInterface *interface; 48 thread_id *thread; 49 uint32 delay; 50 } redial_info; 51 52 status_t redial_thread(void *data); 53 54 // other functions 55 status_t interface_deleter_thread(void *data); 56 status_t call_open_event_thread(void *data); 57 status_t call_close_event_thread(void *data); 58 59 60 KPPPInterface::KPPPInterface(const char *name, ppp_interface_entry *entry, 61 ppp_interface_id ID, const driver_settings *settings, 62 const driver_settings *profile, KPPPInterface *parent = NULL) 63 : KPPPLayer(name, PPP_INTERFACE_LEVEL, 2), 64 fID(ID), 65 fSettings(NULL), 66 fIfnet(NULL), 67 fUpThread(-1), 68 fOpenEventThread(-1), 69 fCloseEventThread(-1), 70 fRedialThread(-1), 71 fDialRetry(0), 72 fDialRetriesLimit(0), 73 fManager(NULL), 74 fIdleSince(0), 75 fMRU(1500), 76 fInterfaceMTU(1498), 77 fHeaderLength(2), 78 fParent(NULL), 79 fIsMultilink(false), 80 fAutoRedial(false), 81 fDialOnDemand(false), 82 fMode(PPP_CLIENT_MODE), 83 fLocalPFCState(PPP_PFC_DISABLED), 84 fPeerPFCState(PPP_PFC_DISABLED), 85 fPFCOptions(0), 86 fDevice(NULL), 87 fFirstProtocol(NULL), 88 fStateMachine(*this), 89 fLCP(*this), 90 fProfile(*this), 91 fReportManager(StateMachine().fLock), 92 fLock(StateMachine().fLock), 93 fDeleteCounter(0) 94 { 95 entry->interface = this; 96 97 if(name) { 98 // load settings from description file 99 char path[B_PATH_NAME_LENGTH]; 100 sprintf(path, "pppidf/%s", name); 101 // XXX: TODO: change base path to "/etc/ppp" when settings API supports it 102 103 void *handle = load_driver_settings(path); 104 if(!handle) { 105 fInitStatus = B_ERROR; 106 return; 107 } 108 109 fSettings = dup_driver_settings(get_driver_settings(handle)); 110 unload_driver_settings(handle); 111 } else 112 fSettings = dup_driver_settings(settings); 113 // use the given settings 114 115 if(!fSettings) { 116 fInitStatus = B_ERROR; 117 return; 118 } 119 fProfile.LoadSettings(profile, fSettings); 120 121 // add internal modules 122 // LCP 123 if(!AddProtocol(&LCP())) { 124 fInitStatus = B_ERROR; 125 return; 126 } 127 // MRU 128 _KPPPMRUHandler *mruHandler = 129 new _KPPPMRUHandler(*this); 130 if(!LCP().AddOptionHandler(mruHandler) || mruHandler->InitCheck() != B_OK) { 131 dprintf("KPPPInterface: Could not add MRU handler!\n"); 132 delete mruHandler; 133 } 134 // authentication 135 _KPPPAuthenticationHandler *authenticationHandler = 136 new _KPPPAuthenticationHandler(*this); 137 if(!LCP().AddOptionHandler(authenticationHandler) 138 || authenticationHandler->InitCheck() != B_OK) { 139 dprintf("KPPPInterface: Could not add authentication handler!\n"); 140 delete authenticationHandler; 141 } 142 // PFC 143 _KPPPPFCHandler *pfcHandler = 144 new _KPPPPFCHandler(fLocalPFCState, fPeerPFCState, *this); 145 if(!LCP().AddOptionHandler(pfcHandler) || pfcHandler->InitCheck() != B_OK) { 146 dprintf("KPPPInterface: Could not add PFC handler!\n"); 147 delete pfcHandler; 148 } 149 150 // set up dial delays 151 fDialRetryDelay = 3000; 152 // 3s delay between each new attempt to redial 153 fRedialDelay = 1000; 154 // 1s delay between lost connection and redial 155 156 if(get_module(PPP_INTERFACE_MODULE_NAME, (module_info**) &fManager) != B_OK) 157 dprintf("KPPPInterface: Manager module not found!\n"); 158 159 // are we a multilink subinterface? 160 if(parent && parent->IsMultilink()) { 161 fParent = parent; 162 fParent->AddChild(this); 163 fIsMultilink = true; 164 } 165 166 RegisterInterface(); 167 168 if(!fSettings) { 169 fInitStatus = B_ERROR; 170 return; 171 } 172 173 const char *value; 174 175 // get DisonnectAfterIdleSince settings 176 value = get_settings_value(PPP_DISONNECT_AFTER_IDLE_SINCE_KEY, fSettings); 177 if(!value) 178 fDisconnectAfterIdleSince = 0; 179 else 180 fDisconnectAfterIdleSince = atoi(value) * 1000; 181 182 if(fDisconnectAfterIdleSince < 0) 183 fDisconnectAfterIdleSince = 0; 184 185 // get mode settings 186 value = get_settings_value(PPP_MODE_KEY, fSettings); 187 if(value && !strcasecmp(value, PPP_SERVER_MODE_VALUE)) 188 fMode = PPP_SERVER_MODE; 189 else 190 fMode = PPP_CLIENT_MODE; 191 // we are a client by default 192 193 SetAutoRedial( 194 get_boolean_value( 195 get_settings_value(PPP_AUTO_REDIAL_KEY, fSettings), 196 false) 197 ); 198 // auto redial is disabled by default 199 200 // load all protocols and the device 201 if(!LoadModules(fSettings, 0, fSettings->parameter_count)) { 202 dprintf("KPPPInterface: Error loading modules!\n"); 203 fInitStatus = B_ERROR; 204 } 205 } 206 207 208 KPPPInterface::~KPPPInterface() 209 { 210 #if DEBUG 211 dprintf("KPPPInterface: Destructor\n"); 212 #endif 213 214 ++fDeleteCounter; 215 216 // tell protocols to uninit (remove routes, etc.) 217 KPPPProtocol *protocol = FirstProtocol(); 218 for(; protocol; protocol = protocol->NextProtocol()) 219 protocol->Uninit(); 220 221 // make sure we are not accessible by any thread before we continue 222 UnregisterInterface(); 223 224 if(fManager) 225 fManager->RemoveInterface(ID()); 226 227 // Call Down() until we get a lock on an interface that is down. 228 // This lock is not released until we are actually deleted. 229 while(true) { 230 Down(); 231 fLock.Lock(); 232 if(State() == PPP_INITIAL_STATE && Phase() == PPP_DOWN_PHASE) 233 break; 234 fLock.Unlock(); 235 } 236 237 Report(PPP_DESTRUCTION_REPORT, 0, &fID, sizeof(ppp_interface_id)); 238 // tell all listeners that we are being destroyed 239 240 int32 tmp; 241 send_data_with_timeout(fRedialThread, 0, NULL, 0, 200); 242 // tell thread that we are being destroyed (200ms timeout) 243 wait_for_thread(fRedialThread, &tmp); 244 wait_for_thread(fOpenEventThread, &tmp); 245 wait_for_thread(fCloseEventThread, &tmp); 246 247 while(CountChildren()) 248 delete ChildAt(0); 249 250 delete Device(); 251 252 while(FirstProtocol()) { 253 if(FirstProtocol() == &LCP()) 254 fFirstProtocol = fFirstProtocol->NextProtocol(); 255 else 256 delete FirstProtocol(); 257 // destructor removes protocol from list 258 } 259 260 for(int32 index = 0; index < fModules.CountItems(); index++) { 261 put_module(fModules.ItemAt(index)); 262 delete[] fModules.ItemAt(index); 263 } 264 265 free_driver_settings(fSettings); 266 267 if(Parent()) 268 Parent()->RemoveChild(this); 269 270 if(fManager) 271 put_module(PPP_INTERFACE_MODULE_NAME); 272 } 273 274 275 void 276 KPPPInterface::Delete() 277 { 278 if(atomic_add(&fDeleteCounter, 1) > 0) 279 return; 280 // only one thread should delete us! 281 282 if(fManager) 283 fManager->DeleteInterface(ID()); 284 // This will mark us for deletion. 285 // Any subsequent calls to delete_interface() will do nothing. 286 else { 287 // We were not created by the manager. 288 // Spawn a thread that will delete us. 289 thread_id interfaceDeleterThread 290 = spawn_kernel_thread(interface_deleter_thread, 291 "KPPPInterface: interface_deleter_thread", B_NORMAL_PRIORITY, this); 292 resume_thread(interfaceDeleterThread); 293 } 294 } 295 296 297 status_t 298 KPPPInterface::InitCheck() const 299 { 300 if(fInitStatus != B_OK) 301 return fInitStatus; 302 303 if(!fSettings || !fManager) 304 return B_ERROR; 305 306 // sub-interfaces should have a device 307 if(IsMultilink()) { 308 if(Parent() && !fDevice) 309 return B_ERROR; 310 } else if(!fDevice) 311 return B_ERROR; 312 313 return B_OK; 314 } 315 316 317 bool 318 KPPPInterface::SetMRU(uint32 MRU) 319 { 320 #if DEBUG 321 dprintf("KPPPInterface: SetMRU(%ld)\n", MRU); 322 #endif 323 324 if(Device() && MRU > Device()->MTU() - 2) 325 return false; 326 327 LockerHelper locker(fLock); 328 329 fMRU = MRU; 330 331 CalculateInterfaceMTU(); 332 333 return true; 334 } 335 336 337 uint32 338 KPPPInterface::PacketOverhead() const 339 { 340 uint32 overhead = fHeaderLength + 2; 341 342 if(Device()) 343 overhead += Device()->Overhead(); 344 345 return overhead; 346 } 347 348 349 status_t 350 KPPPInterface::Control(uint32 op, void *data, size_t length) 351 { 352 switch(op) { 353 case PPPC_GET_INTERFACE_INFO: { 354 if(length < sizeof(ppp_interface_info_t) || !data) 355 return B_NO_MEMORY; 356 357 ppp_interface_info *info = (ppp_interface_info*) data; 358 memset(info, 0, sizeof(ppp_interface_info_t)); 359 if(Name()) 360 strncpy(info->name, Name(), PPP_HANDLER_NAME_LENGTH_LIMIT); 361 if(Ifnet()) 362 info->if_unit = Ifnet()->if_unit; 363 else 364 info->if_unit = -1; 365 info->mode = Mode(); 366 info->state = State(); 367 info->phase = Phase(); 368 info->localAuthenticationStatus = 369 StateMachine().LocalAuthenticationStatus(); 370 info->peerAuthenticationStatus = 371 StateMachine().PeerAuthenticationStatus(); 372 info->localPFCState = LocalPFCState(); 373 info->peerPFCState = PeerPFCState(); 374 info->pfcOptions = PFCOptions(); 375 info->protocolsCount = CountProtocols(); 376 info->optionHandlersCount = LCP().CountOptionHandlers(); 377 info->LCPExtensionsCount = 0; 378 info->childrenCount = CountChildren(); 379 info->MRU = MRU(); 380 info->interfaceMTU = InterfaceMTU(); 381 info->dialRetry = fDialRetry; 382 info->dialRetriesLimit = fDialRetriesLimit; 383 info->dialRetryDelay = DialRetryDelay(); 384 info->redialDelay = RedialDelay(); 385 info->idleSince = IdleSince(); 386 info->disconnectAfterIdleSince = DisconnectAfterIdleSince(); 387 info->doesDialOnDemand = DoesDialOnDemand(); 388 info->doesAutoRedial = DoesAutoRedial(); 389 info->hasDevice = Device(); 390 info->isMultilink = IsMultilink(); 391 info->hasParent = Parent(); 392 } break; 393 394 case PPPC_SET_MRU: 395 if(length < sizeof(uint32) || !data) 396 return B_ERROR; 397 398 SetMRU(*((uint32*)data)); 399 break; 400 401 case PPPC_SET_DIAL_ON_DEMAND: 402 if(length < sizeof(uint32) || !data) 403 return B_NO_MEMORY; 404 405 SetDialOnDemand(*((uint32*)data)); 406 break; 407 408 case PPPC_SET_AUTO_REDIAL: 409 if(length < sizeof(uint32) || !data) 410 return B_NO_MEMORY; 411 412 SetAutoRedial(*((uint32*)data)); 413 break; 414 415 case PPPC_HAS_INTERFACE_SETTINGS: 416 if(length < sizeof(driver_settings) || !data) 417 return B_ERROR; 418 419 if(equal_interface_settings(Settings(), (driver_settings*) data)) 420 return B_OK; 421 else 422 return B_ERROR; 423 break; 424 425 case PPPC_ENABLE_REPORTS: { 426 if(length < sizeof(ppp_report_request) || !data) 427 return B_ERROR; 428 429 ppp_report_request *request = (ppp_report_request*) data; 430 ReportManager().EnableReports(request->type, request->thread, 431 request->flags); 432 } break; 433 434 case PPPC_DISABLE_REPORTS: { 435 if(length < sizeof(ppp_report_request) || !data) 436 return B_ERROR; 437 438 ppp_report_request *request = (ppp_report_request*) data; 439 ReportManager().DisableReports(request->type, request->thread); 440 } break; 441 442 case PPPC_SET_PROFILE: { 443 if(!data) 444 return B_ERROR; 445 446 driver_settings *profile = (driver_settings*) data; 447 fProfile.LoadSettings(profile, fSettings); 448 449 UpdateProfile(); 450 } break; 451 452 case PPPC_CONTROL_DEVICE: { 453 if(length < sizeof(ppp_control_info) || !data) 454 return B_ERROR; 455 456 ppp_control_info *control = (ppp_control_info*) data; 457 if(control->index != 0 || !Device()) 458 return B_BAD_INDEX; 459 460 return Device()->Control(control->op, control->data, control->length); 461 } break; 462 463 case PPPC_CONTROL_PROTOCOL: { 464 if(length < sizeof(ppp_control_info) || !data) 465 return B_ERROR; 466 467 ppp_control_info *control = (ppp_control_info*) data; 468 KPPPProtocol *protocol = ProtocolAt(control->index); 469 if(!protocol) 470 return B_BAD_INDEX; 471 472 return protocol->Control(control->op, control->data, control->length); 473 } break; 474 475 case PPPC_CONTROL_OPTION_HANDLER: { 476 if(length < sizeof(ppp_control_info) || !data) 477 return B_ERROR; 478 479 ppp_control_info *control = (ppp_control_info*) data; 480 KPPPOptionHandler *optionHandler = LCP().OptionHandlerAt(control->index); 481 if(!optionHandler) 482 return B_BAD_INDEX; 483 484 return optionHandler->Control(control->op, control->data, 485 control->length); 486 } break; 487 488 case PPPC_CONTROL_LCP_EXTENSION: { 489 if(length < sizeof(ppp_control_info) || !data) 490 return B_ERROR; 491 492 ppp_control_info *control = (ppp_control_info*) data; 493 KPPPLCPExtension *lcpExtension = LCP().LCPExtensionAt(control->index); 494 if(!lcpExtension) 495 return B_BAD_INDEX; 496 497 return lcpExtension->Control(control->op, control->data, 498 control->length); 499 } break; 500 501 case PPPC_CONTROL_CHILD: { 502 if(length < sizeof(ppp_control_info) || !data) 503 return B_ERROR; 504 505 ppp_control_info *control = (ppp_control_info*) data; 506 KPPPInterface *child = ChildAt(control->index); 507 if(!child) 508 return B_BAD_INDEX; 509 510 return child->Control(control->op, control->data, control->length); 511 } break; 512 513 default: 514 return B_BAD_VALUE; 515 } 516 517 return B_OK; 518 } 519 520 521 bool 522 KPPPInterface::SetDevice(KPPPDevice *device) 523 { 524 #if DEBUG 525 dprintf("KPPPInterface: SetDevice(%p)\n", device); 526 #endif 527 528 if(device && &device->Interface() != this) 529 return false; 530 531 if(IsMultilink() && !Parent()) 532 return false; 533 // main interfaces do not have devices 534 535 LockerHelper locker(fLock); 536 537 if(Phase() != PPP_DOWN_PHASE) 538 return false; 539 // a running connection may not change 540 541 if(fDevice && (IsUp() || fDevice->IsUp())) 542 Down(); 543 544 fDevice = device; 545 SetNext(device); 546 547 if(fDevice) 548 fMRU = fDevice->MTU() - 2; 549 550 CalculateInterfaceMTU(); 551 CalculateBaudRate(); 552 553 return true; 554 } 555 556 557 bool 558 KPPPInterface::AddProtocol(KPPPProtocol *protocol) 559 { 560 // Find instert position after the last protocol 561 // with the same level. 562 563 #if DEBUG 564 dprintf("KPPPInterface: AddProtocol(%X)\n", 565 protocol ? protocol->ProtocolNumber() : 0); 566 #endif 567 568 if(!protocol || &protocol->Interface() != this 569 || protocol->Level() == PPP_INTERFACE_LEVEL) 570 return false; 571 572 LockerHelper locker(fLock); 573 574 if(Phase() != PPP_DOWN_PHASE) 575 return false; 576 // a running connection may not change 577 578 KPPPProtocol *current = fFirstProtocol, *previous = NULL; 579 580 while(current) { 581 if(current->Level() < protocol->Level()) 582 break; 583 584 previous = current; 585 current = current->NextProtocol(); 586 } 587 588 if(!current) { 589 if(!previous) 590 fFirstProtocol = protocol; 591 else 592 previous->SetNextProtocol(protocol); 593 594 // set up the last protocol in the chain 595 protocol->SetNextProtocol(NULL); 596 // this also sets next to NULL 597 protocol->SetNext(this); 598 // we need to set us as the next layer for the last protocol 599 } else { 600 protocol->SetNextProtocol(current); 601 602 if(!previous) 603 fFirstProtocol = protocol; 604 else 605 previous->SetNextProtocol(protocol); 606 } 607 608 if(protocol->Level() < PPP_PROTOCOL_LEVEL) 609 CalculateInterfaceMTU(); 610 611 if(IsUp() || Phase() >= protocol->ActivationPhase()) 612 protocol->Up(); 613 614 return true; 615 } 616 617 618 bool 619 KPPPInterface::RemoveProtocol(KPPPProtocol *protocol) 620 { 621 #if DEBUG 622 dprintf("KPPPInterface: RemoveProtocol(%X)\n", 623 protocol ? protocol->ProtocolNumber() : 0); 624 #endif 625 626 LockerHelper locker(fLock); 627 628 if(Phase() != PPP_DOWN_PHASE) 629 return false; 630 // a running connection may not change 631 632 KPPPProtocol *current = fFirstProtocol, *previous = NULL; 633 634 while(current) { 635 if(current == protocol) { 636 if(!protocol->IsDown()) 637 protocol->Down(); 638 639 if(previous) { 640 previous->SetNextProtocol(current->NextProtocol()); 641 642 // set us as next layer if needed 643 if(!previous->Next()) 644 previous->SetNext(this); 645 } else 646 fFirstProtocol = current->NextProtocol(); 647 648 current->SetNextProtocol(NULL); 649 650 CalculateInterfaceMTU(); 651 652 return true; 653 } 654 655 previous = current; 656 current = current->NextProtocol(); 657 } 658 659 return false; 660 } 661 662 663 int32 664 KPPPInterface::CountProtocols() const 665 { 666 KPPPProtocol *protocol = FirstProtocol(); 667 668 int32 count = 0; 669 for(; protocol; protocol = protocol->NextProtocol()) 670 ++count; 671 672 return count; 673 } 674 675 676 KPPPProtocol* 677 KPPPInterface::ProtocolAt(int32 index) const 678 { 679 KPPPProtocol *protocol = FirstProtocol(); 680 681 int32 currentIndex = 0; 682 for(; protocol && currentIndex != index; protocol = protocol->NextProtocol()) 683 ++currentIndex; 684 685 return protocol; 686 } 687 688 689 KPPPProtocol* 690 KPPPInterface::ProtocolFor(uint16 protocolNumber, KPPPProtocol *start = NULL) const 691 { 692 #if DEBUG 693 dprintf("KPPPInterface: ProtocolFor(%X)\n", protocolNumber); 694 #endif 695 696 KPPPProtocol *current = start ? start : FirstProtocol(); 697 698 for(; current; current = current->NextProtocol()) { 699 if(current->ProtocolNumber() == protocolNumber 700 || (current->Flags() & PPP_INCLUDES_NCP 701 && (current->ProtocolNumber() & 0x7FFF) 702 == (protocolNumber & 0x7FFF))) 703 return current; 704 } 705 706 return NULL; 707 } 708 709 710 bool 711 KPPPInterface::AddChild(KPPPInterface *child) 712 { 713 #if DEBUG 714 dprintf("KPPPInterface: AddChild(%lX)\n", 715 child ? child->ID() : 0); 716 #endif 717 718 if(!child) 719 return false; 720 721 LockerHelper locker(fLock); 722 723 if(fChildren.HasItem(child) || !fChildren.AddItem(child)) 724 return false; 725 726 child->SetParent(this); 727 728 return true; 729 } 730 731 732 bool 733 KPPPInterface::RemoveChild(KPPPInterface *child) 734 { 735 #if DEBUG 736 dprintf("KPPPInterface: RemoveChild(%lX)\n", 737 child ? child->ID() : 0); 738 #endif 739 740 LockerHelper locker(fLock); 741 742 if(!fChildren.RemoveItem(child)) 743 return false; 744 745 child->SetParent(NULL); 746 747 // parents cannot exist without their children 748 if(CountChildren() == 0 && fManager && Ifnet()) 749 Delete(); 750 751 return true; 752 } 753 754 755 KPPPInterface* 756 KPPPInterface::ChildAt(int32 index) const 757 { 758 #if DEBUG 759 dprintf("KPPPInterface: ChildAt(%ld)\n", index); 760 #endif 761 762 KPPPInterface *child = fChildren.ItemAt(index); 763 764 if(child == fChildren.GetDefaultItem()) 765 return NULL; 766 767 return child; 768 } 769 770 771 void 772 KPPPInterface::SetAutoRedial(bool autoRedial = true) 773 { 774 #if DEBUG 775 dprintf("KPPPInterface: SetAutoRedial(%s)\n", autoRedial ? "true" : "false"); 776 #endif 777 778 if(Mode() != PPP_CLIENT_MODE) 779 return; 780 781 LockerHelper locker(fLock); 782 783 fAutoRedial = autoRedial; 784 } 785 786 787 void 788 KPPPInterface::SetDialOnDemand(bool dialOnDemand = true) 789 { 790 // All protocols must check if DialOnDemand was enabled/disabled after this 791 // interface went down. This is the only situation where a change is relevant. 792 793 #if DEBUG 794 dprintf("KPPPInterface: SetDialOnDemand(%s)\n", dialOnDemand ? "true" : "false"); 795 #endif 796 797 // Only clients support DialOnDemand. 798 if(Mode() != PPP_CLIENT_MODE) { 799 #if DEBUG 800 dprintf("KPPPInterface::SetDialOnDemand(): Wrong mode!\n"); 801 #endif 802 fDialOnDemand = false; 803 return; 804 } else if(DoesDialOnDemand() == dialOnDemand) 805 return; 806 807 LockerHelper locker(fLock); 808 809 fDialOnDemand = dialOnDemand; 810 811 // Do not allow changes when we are disconnected (only main interfaces). 812 // This would make no sense because 813 // - enabling: this cannot happen because hidden interfaces are deleted if they 814 // could not establish a connection (the user cannot access hidden interfaces) 815 // - disabling: the interface disappears as seen from the user, so we delete it 816 if(!Parent() && State() == PPP_INITIAL_STATE && Phase() == PPP_DOWN_PHASE) { 817 if(!dialOnDemand) 818 Delete(); 819 // as long as the protocols were not configured we can just delete us 820 821 return; 822 } 823 824 // check if we need to set/unset flags 825 if(dialOnDemand) { 826 if(Ifnet()) 827 Ifnet()->if_flags |= IFF_UP; 828 } else if(!dialOnDemand && Phase() < PPP_ESTABLISHED_PHASE) { 829 if(Ifnet()) 830 Ifnet()->if_flags &= ~IFF_UP; 831 } 832 } 833 834 835 bool 836 KPPPInterface::SetPFCOptions(uint8 pfcOptions) 837 { 838 #if DEBUG 839 dprintf("KPPPInterface: SetPFCOptions(0x%X)\n", pfcOptions); 840 #endif 841 842 if(PFCOptions() & PPP_FREEZE_PFC_OPTIONS) 843 return false; 844 845 fPFCOptions = pfcOptions; 846 return true; 847 } 848 849 850 bool 851 KPPPInterface::Up() 852 { 853 #if DEBUG 854 dprintf("KPPPInterface: Up()\n"); 855 #endif 856 857 if(InitCheck() != B_OK || Phase() == PPP_TERMINATION_PHASE) 858 return false; 859 860 if(IsUp()) 861 return true; 862 863 ppp_report_packet report; 864 thread_id me = find_thread(NULL), sender; 865 866 // One thread has to do the real task while all other threads are observers. 867 // Lock needs timeout because destructor could have locked the interface. 868 while(fLock.LockWithTimeout(100000) != B_NO_ERROR) 869 if(fDeleteCounter > 0) 870 return false; 871 if(fUpThread == -1) 872 fUpThread = me; 873 874 ReportManager().EnableReports(PPP_CONNECTION_REPORT, me, PPP_WAIT_FOR_REPLY); 875 876 // fUpThread/fRedialThread tells the state machine to go up (using a new thread 877 // because we might not receive report messages otherwise) 878 if(me == fUpThread || me == fRedialThread) { 879 if(fOpenEventThread != -1) { 880 int32 tmp; 881 wait_for_thread(fOpenEventThread, &tmp); 882 } 883 fOpenEventThread = spawn_kernel_thread(call_open_event_thread, 884 "KPPPInterface: call_open_event_thread", B_NORMAL_PRIORITY, this); 885 resume_thread(fOpenEventThread); 886 } 887 fLock.Unlock(); 888 889 if(me == fRedialThread && me != fUpThread) 890 return true; 891 // the redial thread is doing a DialRetry in this case (fUpThread 892 // is waiting for new reports) 893 894 while(true) { 895 // A wrong code usually happens when the redial thread gets notified 896 // of a Down() request. In that case a report will follow soon, so 897 // this can be ignored. 898 if(receive_data(&sender, &report, sizeof(report)) != PPP_REPORT_CODE) 899 continue; 900 901 //#if DEBUG 902 // dprintf("KPPPInterface::Up(): Report: Type = %ld Code = %ld\n", report.type, 903 // report.code); 904 //#endif 905 906 if(IsUp()) { 907 if(me == fUpThread) { 908 fDialRetry = 0; 909 fUpThread = -1; 910 } 911 912 PPP_REPLY(sender, B_OK); 913 ReportManager().DisableReports(PPP_CONNECTION_REPORT, me); 914 return true; 915 } 916 917 if(report.type == PPP_DESTRUCTION_REPORT) { 918 if(me == fUpThread) { 919 fDialRetry = 0; 920 fUpThread = -1; 921 } 922 923 PPP_REPLY(sender, B_OK); 924 ReportManager().DisableReports(PPP_CONNECTION_REPORT, me); 925 return false; 926 } else if(report.type != PPP_CONNECTION_REPORT) { 927 PPP_REPLY(sender, B_OK); 928 continue; 929 } 930 931 if(report.code == PPP_REPORT_GOING_UP) { 932 PPP_REPLY(sender, B_OK); 933 continue; 934 } else if(report.code == PPP_REPORT_UP_SUCCESSFUL) { 935 if(me == fUpThread) { 936 fDialRetry = 0; 937 fUpThread = -1; 938 send_data_with_timeout(fRedialThread, 0, NULL, 0, 200); 939 // notify redial thread that we do not need it anymore 940 } 941 942 PPP_REPLY(sender, B_OK); 943 ReportManager().DisableReports(PPP_CONNECTION_REPORT, me); 944 return true; 945 } else if(report.code == PPP_REPORT_DOWN_SUCCESSFUL 946 || report.code == PPP_REPORT_UP_ABORTED 947 || report.code == PPP_REPORT_LOCAL_AUTHENTICATION_FAILED 948 || report.code == PPP_REPORT_PEER_AUTHENTICATION_FAILED) { 949 if(me == fUpThread) { 950 fDialRetry = 0; 951 fUpThread = -1; 952 953 if(!DoesDialOnDemand() && report.code != PPP_REPORT_DOWN_SUCCESSFUL) 954 Delete(); 955 } 956 957 PPP_REPLY(sender, B_OK); 958 ReportManager().DisableReports(PPP_CONNECTION_REPORT, me); 959 return false; 960 } 961 962 if(me != fUpThread) { 963 // I am an observer 964 if(report.code == PPP_REPORT_DEVICE_UP_FAILED) { 965 if(fDialRetry >= fDialRetriesLimit || fUpThread == -1) { 966 PPP_REPLY(sender, B_OK); 967 ReportManager().DisableReports(PPP_CONNECTION_REPORT, me); 968 return false; 969 } else { 970 PPP_REPLY(sender, B_OK); 971 continue; 972 } 973 } else if(report.code == PPP_REPORT_CONNECTION_LOST) { 974 if(DoesAutoRedial()) { 975 PPP_REPLY(sender, B_OK); 976 continue; 977 } else { 978 PPP_REPLY(sender, B_OK); 979 ReportManager().DisableReports(PPP_CONNECTION_REPORT, me); 980 return false; 981 } 982 } 983 } else { 984 // I am the thread for the real task 985 if(report.code == PPP_REPORT_DEVICE_UP_FAILED) { 986 if(fDialRetry >= fDialRetriesLimit) { 987 #if DEBUG 988 dprintf("KPPPInterface::Up(): DEVICE_UP_FAILED: >=maxretries!\n"); 989 #endif 990 fDialRetry = 0; 991 fUpThread = -1; 992 993 if(!DoesDialOnDemand()) 994 Delete(); 995 996 PPP_REPLY(sender, B_OK); 997 ReportManager().DisableReports(PPP_CONNECTION_REPORT, me); 998 return false; 999 } else { 1000 #if DEBUG 1001 dprintf("KPPPInterface::Up(): DEVICE_UP_FAILED: <maxretries\n"); 1002 #endif 1003 ++fDialRetry; 1004 PPP_REPLY(sender, B_OK); 1005 #if DEBUG 1006 dprintf("KPPPInterface::Up(): DEVICE_UP_FAILED: replied\n"); 1007 #endif 1008 Redial(DialRetryDelay()); 1009 continue; 1010 } 1011 } else if(report.code == PPP_REPORT_CONNECTION_LOST) { 1012 // the state machine knows that we are going up and leaves 1013 // the redial task to us 1014 if(DoesAutoRedial() && fDialRetry < fDialRetriesLimit) { 1015 ++fDialRetry; 1016 PPP_REPLY(sender, B_OK); 1017 Redial(DialRetryDelay()); 1018 continue; 1019 } else { 1020 fDialRetry = 0; 1021 fUpThread = -1; 1022 PPP_REPLY(sender, B_OK); 1023 ReportManager().DisableReports(PPP_CONNECTION_REPORT, me); 1024 1025 if(!DoesDialOnDemand()) 1026 Delete(); 1027 1028 return false; 1029 } 1030 } 1031 } 1032 1033 // if the code is unknown we continue 1034 PPP_REPLY(sender, B_OK); 1035 } 1036 1037 return false; 1038 } 1039 1040 1041 bool 1042 KPPPInterface::Down() 1043 { 1044 #if DEBUG 1045 dprintf("KPPPInterface: Down()\n"); 1046 #endif 1047 1048 if(InitCheck() != B_OK) 1049 return false; 1050 else if(State() == PPP_INITIAL_STATE && Phase() == PPP_DOWN_PHASE) 1051 return true; 1052 1053 send_data_with_timeout(fRedialThread, 0, NULL, 0, 200); 1054 // the redial thread should be notified that the user wants to disconnect 1055 1056 // this locked section guarantees that there are no state changes before we 1057 // enable the connection reports 1058 LockerHelper locker(fLock); 1059 if(State() == PPP_INITIAL_STATE && Phase() == PPP_DOWN_PHASE) 1060 return true; 1061 1062 ReportManager().EnableReports(PPP_CONNECTION_REPORT, find_thread(NULL)); 1063 1064 thread_id sender; 1065 ppp_report_packet report; 1066 1067 if(fCloseEventThread != -1) { 1068 int32 tmp; 1069 wait_for_thread(fCloseEventThread, &tmp); 1070 } 1071 1072 fCloseEventThread = spawn_kernel_thread(call_close_event_thread, 1073 "KPPPInterface: call_close_event_thread", B_NORMAL_PRIORITY, this); 1074 resume_thread(fCloseEventThread); 1075 locker.UnlockNow(); 1076 1077 while(true) { 1078 if(receive_data(&sender, &report, sizeof(report)) != PPP_REPORT_CODE) 1079 continue; 1080 1081 if(report.type == PPP_DESTRUCTION_REPORT) 1082 return true; 1083 1084 if(report.type != PPP_CONNECTION_REPORT) 1085 continue; 1086 1087 if(report.code == PPP_REPORT_DOWN_SUCCESSFUL 1088 || report.code == PPP_REPORT_UP_ABORTED 1089 || (State() == PPP_INITIAL_STATE && Phase() == PPP_DOWN_PHASE)) { 1090 ReportManager().DisableReports(PPP_CONNECTION_REPORT, find_thread(NULL)); 1091 break; 1092 } 1093 } 1094 1095 if(!DoesDialOnDemand()) 1096 Delete(); 1097 1098 return true; 1099 } 1100 1101 1102 bool 1103 KPPPInterface::IsUp() const 1104 { 1105 LockerHelper locker(fLock); 1106 1107 return Phase() == PPP_ESTABLISHED_PHASE; 1108 } 1109 1110 1111 bool 1112 KPPPInterface::LoadModules(driver_settings *settings, int32 start, int32 count) 1113 { 1114 #if DEBUG 1115 dprintf("KPPPInterface: LoadModules()\n"); 1116 #endif 1117 1118 if(Phase() != PPP_DOWN_PHASE) 1119 return false; 1120 // a running connection may not change 1121 1122 ppp_module_key_type type; 1123 // which type key was used for loading this module? 1124 1125 const char *name = NULL; 1126 1127 // multilink handling 1128 for(int32 index = start; 1129 index < settings->parameter_count && index < start + count; index++) { 1130 if(!strcasecmp(settings->parameters[index].name, PPP_MULTILINK_KEY) 1131 && settings->parameters[index].value_count > 0) { 1132 if(!LoadModule(settings->parameters[index].values[0], 1133 &settings->parameters[index], PPP_MULTILINK_KEY_TYPE)) 1134 return false; 1135 break; 1136 } 1137 } 1138 1139 // are we a multilink main interface? 1140 if(IsMultilink() && !Parent()) { 1141 // main interfaces only load the multilink module 1142 // and create a child using their settings 1143 fManager->CreateInterface(settings, Profile().Settings(), ID()); 1144 return true; 1145 } 1146 1147 for(int32 index = start; 1148 index < settings->parameter_count && index < start + count; index++) { 1149 type = PPP_UNDEFINED_KEY_TYPE; 1150 1151 name = settings->parameters[index].name; 1152 1153 if(!strcasecmp(name, PPP_LOAD_MODULE_KEY)) 1154 type = PPP_LOAD_MODULE_KEY_TYPE; 1155 else if(!strcasecmp(name, PPP_DEVICE_KEY)) 1156 type = PPP_DEVICE_KEY_TYPE; 1157 else if(!strcasecmp(name, PPP_PROTOCOL_KEY)) 1158 type = PPP_PROTOCOL_KEY_TYPE; 1159 else if(!strcasecmp(name, PPP_AUTHENTICATOR_KEY)) 1160 type = PPP_AUTHENTICATOR_KEY_TYPE; 1161 1162 if(type >= 0) 1163 for(int32 value_id = 0; value_id < settings->parameters[index].value_count; 1164 value_id++) 1165 if(!LoadModule(settings->parameters[index].values[value_id], 1166 &settings->parameters[index], type)) 1167 return false; 1168 } 1169 1170 return true; 1171 } 1172 1173 1174 bool 1175 KPPPInterface::LoadModule(const char *name, driver_parameter *parameter, 1176 ppp_module_key_type type) 1177 { 1178 #if DEBUG 1179 dprintf("KPPPInterface: LoadModule(%s)\n", name ? name : "XXX: NO NAME"); 1180 #endif 1181 1182 if(Phase() != PPP_DOWN_PHASE) 1183 return false; 1184 // a running connection may not change 1185 1186 if(!name || strlen(name) > B_FILE_NAME_LENGTH) 1187 return false; 1188 1189 char *moduleName = new char[B_PATH_NAME_LENGTH]; 1190 1191 sprintf(moduleName, "%s/%s", PPP_MODULES_PATH, name); 1192 1193 ppp_module_info *module; 1194 if(get_module(moduleName, (module_info**) &module) != B_OK) { 1195 delete[] moduleName; 1196 return false; 1197 } 1198 1199 // add the module to the list of loaded modules 1200 // for putting them on our destruction 1201 fModules.AddItem(moduleName); 1202 1203 return module->add_to(Parent() ? *Parent() : *this, this, parameter, type); 1204 } 1205 1206 1207 bool 1208 KPPPInterface::IsAllowedToSend() const 1209 { 1210 return true; 1211 } 1212 1213 1214 status_t 1215 KPPPInterface::Send(struct mbuf *packet, uint16 protocolNumber) 1216 { 1217 #if DEBUG 1218 dprintf("KPPPInterface: Send(0x%X)\n", protocolNumber); 1219 #endif 1220 1221 if(!packet) 1222 return B_ERROR; 1223 1224 // we must pass the basic tests like: 1225 // do we have a device? 1226 // did we load all modules? 1227 if(InitCheck() != B_OK) { 1228 m_freem(packet); 1229 return B_ERROR; 1230 } 1231 1232 // go up if DialOnDemand enabled and we are down 1233 if(protocolNumber != PPP_LCP_PROTOCOL && DoesDialOnDemand() 1234 && (Phase() == PPP_DOWN_PHASE 1235 || Phase() == PPP_ESTABLISHMENT_PHASE) 1236 && !Up()) { 1237 m_freem(packet); 1238 return B_ERROR; 1239 } 1240 1241 // find the protocol handler for the current protocol number 1242 KPPPProtocol *protocol = ProtocolFor(protocolNumber); 1243 while(protocol && !protocol->IsEnabled()) 1244 protocol = protocol->NextProtocol() ? 1245 ProtocolFor(protocolNumber, protocol->NextProtocol()) : NULL; 1246 1247 #if DEBUG 1248 if(!protocol) 1249 dprintf("KPPPInterface::Send(): no protocol found!\n"); 1250 else if(!Device()->IsUp()) 1251 dprintf("KPPPInterface::Send(): device is not up!\n"); 1252 else if(!protocol->IsEnabled()) 1253 dprintf("KPPPInterface::Send(): protocol not enabled!\n"); 1254 else if(!IsProtocolAllowed(*protocol)) 1255 dprintf("KPPPInterface::Send(): protocol not allowed to send!\n"); 1256 else 1257 dprintf("KPPPInterface::Send(): protocol allowed\n"); 1258 #endif 1259 1260 // make sure that protocol is allowed to send and everything is up 1261 if(!Device()->IsUp() || !protocol || !protocol->IsEnabled() 1262 || !IsProtocolAllowed(*protocol)) { 1263 dprintf("KPPPInterface::Send(): cannot send!\n"); 1264 m_freem(packet); 1265 return B_ERROR; 1266 } 1267 1268 // encode in ppp frame and consider using PFC 1269 if(UseLocalPFC() && protocolNumber & 0xFF00 == 0) { 1270 M_PREPEND(packet, 1); 1271 1272 if(packet == NULL) 1273 return B_ERROR; 1274 1275 uint8 *header = mtod(packet, uint8*); 1276 *header = protocolNumber & 0xFF; 1277 } else { 1278 M_PREPEND(packet, 2); 1279 1280 if(packet == NULL) 1281 return B_ERROR; 1282 1283 // set protocol (the only header field) 1284 protocolNumber = htons(protocolNumber); 1285 uint16 *header = mtod(packet, uint16*); 1286 *header = protocolNumber; 1287 } 1288 1289 // pass to device/children 1290 if(!IsMultilink() || Parent()) { 1291 // check if packet is too big for device 1292 if((packet->m_flags & M_PKTHDR && (uint32) packet->m_pkthdr.len > MRU()) 1293 || packet->m_len > MRU()) { 1294 m_freem(packet); 1295 return B_ERROR; 1296 } 1297 1298 return SendToNext(packet, 0); 1299 // this is normally the device, but there can be something inbetween 1300 } else { 1301 // the multilink protocol should have sent it to some child interface 1302 m_freem(packet); 1303 return B_ERROR; 1304 } 1305 } 1306 1307 1308 status_t 1309 KPPPInterface::Receive(struct mbuf *packet, uint16 protocolNumber) 1310 { 1311 #if DEBUG 1312 dprintf("KPPPInterface: Receive(0x%X)\n", protocolNumber); 1313 #endif 1314 1315 if(!packet) 1316 return B_ERROR; 1317 1318 int32 result = PPP_REJECTED; 1319 // assume we have no handler 1320 1321 // Set our interface as the receiver. 1322 // The real netstack protocols (IP, IPX, etc.) might get confused if our 1323 // interface is a main interface and at the same time not registered 1324 // because then there is no receiver interface. 1325 // PPP NCPs should be aware of that! 1326 if(packet->m_flags & M_PKTHDR && Ifnet() != NULL) 1327 packet->m_pkthdr.rcvif = Ifnet(); 1328 1329 // Find handler and let it parse the packet. 1330 // The handler does need not be up because if we are a server 1331 // the handler might be upped by this packet. 1332 // If authenticating we only allow authentication phase protocols. 1333 KPPPProtocol *protocol = ProtocolFor(protocolNumber); 1334 for(; protocol; 1335 protocol = protocol->NextProtocol() ? 1336 ProtocolFor(protocolNumber, protocol->NextProtocol()) : NULL) { 1337 #if DEBUG 1338 dprintf("KPPPInterface::Receive(): trying protocol\n"); 1339 #endif 1340 1341 if(!protocol->IsEnabled() || !IsProtocolAllowed(*protocol)) 1342 continue; 1343 // skip handler if disabled or not allowed 1344 1345 result = protocol->Receive(packet, protocolNumber); 1346 if(result == PPP_UNHANDLED) 1347 continue; 1348 1349 return result; 1350 } 1351 1352 #if DEBUG 1353 dprintf("KPPPInterface::Receive(): trying parent\n"); 1354 #endif 1355 1356 // maybe the parent interface can handle the packet 1357 if(Parent()) 1358 return Parent()->Receive(packet, protocolNumber); 1359 1360 if(result == PPP_UNHANDLED) { 1361 m_freem(packet); 1362 return PPP_DISCARDED; 1363 } else { 1364 StateMachine().RUCEvent(packet, protocolNumber); 1365 return PPP_REJECTED; 1366 } 1367 } 1368 1369 1370 status_t 1371 KPPPInterface::ReceiveFromDevice(struct mbuf *packet) 1372 { 1373 #if DEBUG 1374 dprintf("KPPPInterface: ReceiveFromDevice()\n"); 1375 #endif 1376 1377 if(!packet) 1378 return B_ERROR; 1379 1380 if(InitCheck() != B_OK) { 1381 m_freem(packet); 1382 return B_ERROR; 1383 } 1384 1385 // decode ppp frame and recognize PFC 1386 uint16 protocolNumber = *mtod(packet, uint8*); 1387 if(protocolNumber & 1) { 1388 m_adj(packet, 1); 1389 } else { 1390 protocolNumber = ntohs(*mtod(packet, uint16*)); 1391 m_adj(packet, 2); 1392 } 1393 1394 return Receive(packet, protocolNumber); 1395 } 1396 1397 1398 void 1399 KPPPInterface::Pulse() 1400 { 1401 if(Device()) 1402 Device()->Pulse(); 1403 1404 KPPPProtocol *protocol = FirstProtocol(); 1405 for(; protocol; protocol = protocol->NextProtocol()) 1406 protocol->Pulse(); 1407 1408 uint32 currentTime = real_time_clock(); 1409 if(fUpdateIdleSince) { 1410 fIdleSince = currentTime; 1411 fUpdateIdleSince = false; 1412 } 1413 1414 // check our idle time and disconnect if needed 1415 if(fDisconnectAfterIdleSince > 0 && fIdleSince != 0 1416 && fIdleSince - currentTime >= fDisconnectAfterIdleSince) 1417 StateMachine().CloseEvent(); 1418 } 1419 1420 1421 bool 1422 KPPPInterface::RegisterInterface() 1423 { 1424 #if DEBUG 1425 dprintf("KPPPInterface: RegisterInterface()\n"); 1426 #endif 1427 1428 if(fIfnet) 1429 return true; 1430 // we are already registered 1431 1432 LockerHelper locker(fLock); 1433 1434 // only MainInterfaces get an ifnet 1435 if(IsMultilink() && Parent() && Parent()->RegisterInterface()) 1436 return true; 1437 1438 if(!fManager) 1439 return false; 1440 1441 fIfnet = fManager->RegisterInterface(ID()); 1442 1443 if(!fIfnet) 1444 return false; 1445 1446 if(DoesDialOnDemand()) 1447 fIfnet->if_flags |= IFF_UP; 1448 1449 CalculateInterfaceMTU(); 1450 CalculateBaudRate(); 1451 1452 return true; 1453 } 1454 1455 1456 bool 1457 KPPPInterface::UnregisterInterface() 1458 { 1459 #if DEBUG 1460 dprintf("KPPPInterface: UnregisterInterface()\n"); 1461 #endif 1462 1463 if(!fIfnet) 1464 return true; 1465 // we are already unregistered 1466 1467 LockerHelper locker(fLock); 1468 1469 // only MainInterfaces get an ifnet 1470 if(IsMultilink() && Parent()) 1471 return true; 1472 1473 if(!fManager) 1474 return false; 1475 1476 fManager->UnregisterInterface(ID()); 1477 // this will delete fIfnet, so do not access it anymore! 1478 fIfnet = NULL; 1479 1480 return true; 1481 } 1482 1483 1484 // called when profile changes 1485 void 1486 KPPPInterface::UpdateProfile() 1487 { 1488 KPPPLayer *layer = FirstProtocol(); 1489 for(; layer; layer = layer->Next()) 1490 layer->ProfileChanged(); 1491 } 1492 1493 1494 // called by KPPPManager: manager routes stack ioctls to interface 1495 status_t 1496 KPPPInterface::StackControl(uint32 op, void *data) 1497 { 1498 #if DEBUG 1499 dprintf("KPPPInterface: StackControl(0x%lX)\n", op); 1500 #endif 1501 1502 switch(op) { 1503 default: 1504 return StackControlEachHandler(op, data); 1505 } 1506 1507 return B_OK; 1508 } 1509 1510 1511 // used by ControlEachHandler() 1512 template<class T> 1513 class CallStackControl { 1514 public: 1515 inline CallStackControl(uint32 op, void *data, status_t& result) 1516 : fOp(op), fData(data), fResult(result) {} 1517 inline void operator() (T *item) 1518 { 1519 if(!item || !item->IsEnabled()) 1520 return; 1521 status_t tmp = item->StackControl(fOp, fData); 1522 if(tmp == B_OK && fResult == B_BAD_VALUE) 1523 fResult = B_OK; 1524 else if(tmp != B_BAD_VALUE) 1525 fResult = tmp; 1526 } 1527 private: 1528 uint32 fOp; 1529 void *fData; 1530 status_t& fResult; 1531 }; 1532 1533 // This calls Control() with the given parameters for each handler. 1534 // Return values: 1535 // B_OK: all handlers returned B_OK 1536 // B_BAD_VALUE: no handler was found 1537 // any other value: the error value that was returned by the last handler that failed 1538 status_t 1539 KPPPInterface::StackControlEachHandler(uint32 op, void *data) 1540 { 1541 #if DEBUG 1542 dprintf("KPPPInterface: StackControlEachHandler(0x%lX)\n", op); 1543 #endif 1544 1545 status_t result = B_BAD_VALUE, tmp; 1546 1547 KPPPProtocol *protocol = FirstProtocol(); 1548 for(; protocol; protocol = protocol->NextProtocol()) { 1549 tmp = protocol->StackControl(op, data); 1550 if(tmp == B_OK && result == B_BAD_VALUE) 1551 result = B_OK; 1552 else if(tmp != B_BAD_VALUE) 1553 result = tmp; 1554 } 1555 1556 ForEachItem(LCP().fLCPExtensions, 1557 CallStackControl<KPPPLCPExtension>(op, data, result)); 1558 ForEachItem(LCP().fOptionHandlers, 1559 CallStackControl<KPPPOptionHandler>(op, data, result)); 1560 1561 return result; 1562 } 1563 1564 1565 void 1566 KPPPInterface::CalculateInterfaceMTU() 1567 { 1568 #if DEBUG 1569 dprintf("KPPPInterface: CalculateInterfaceMTU()\n"); 1570 #endif 1571 1572 fInterfaceMTU = fMRU; 1573 fHeaderLength = 2; 1574 1575 // sum all headers (the protocol field is not counted) 1576 KPPPProtocol *protocol = FirstProtocol(); 1577 for(; protocol; protocol = protocol->NextProtocol()) { 1578 if(protocol->Level() < PPP_PROTOCOL_LEVEL) 1579 fHeaderLength += protocol->Overhead(); 1580 } 1581 1582 fInterfaceMTU -= fHeaderLength; 1583 1584 if(Ifnet()) { 1585 Ifnet()->if_mtu = fInterfaceMTU; 1586 Ifnet()->if_hdrlen = fHeaderLength; 1587 } 1588 1589 if(Parent()) 1590 Parent()->CalculateInterfaceMTU(); 1591 } 1592 1593 1594 void 1595 KPPPInterface::CalculateBaudRate() 1596 { 1597 #if DEBUG 1598 dprintf("KPPPInterface: CalculateBaudRate()\n"); 1599 #endif 1600 1601 if(!Ifnet()) 1602 return; 1603 1604 if(Device()) 1605 fIfnet->if_baudrate = max_c(Device()->InputTransferRate(), 1606 Device()->OutputTransferRate()); 1607 else { 1608 fIfnet->if_baudrate = 0; 1609 for(int32 index = 0; index < CountChildren(); index++) 1610 if(ChildAt(index)->Ifnet()) 1611 fIfnet->if_baudrate += ChildAt(index)->Ifnet()->if_baudrate; 1612 } 1613 } 1614 1615 1616 void 1617 KPPPInterface::Redial(uint32 delay) 1618 { 1619 #if DEBUG 1620 dprintf("KPPPInterface: Redial(%ld)\n", delay); 1621 #endif 1622 1623 if(fRedialThread != -1) 1624 return; 1625 1626 // start a new thread that calls our Up() method 1627 redial_info info; 1628 info.interface = this; 1629 info.thread = &fRedialThread; 1630 info.delay = delay; 1631 1632 fRedialThread = spawn_kernel_thread(redial_thread, "KPPPInterface: redial_thread", 1633 B_NORMAL_PRIORITY, NULL); 1634 1635 resume_thread(fRedialThread); 1636 1637 send_data(fRedialThread, 0, &info, sizeof(redial_info)); 1638 } 1639 1640 1641 status_t 1642 redial_thread(void *data) 1643 { 1644 redial_info info; 1645 thread_id sender; 1646 int32 code; 1647 1648 receive_data(&sender, &info, sizeof(redial_info)); 1649 1650 // we try to receive data instead of snooze, so we can quit on destruction 1651 if(receive_data_with_timeout(&sender, &code, NULL, 0, info.delay) == B_OK) { 1652 *info.thread = -1; 1653 ppp_interface_id id = info.interface->ID(); 1654 info.interface->Report(PPP_CONNECTION_REPORT, PPP_REPORT_UP_ABORTED, 1655 &id, sizeof(ppp_interface_id)); 1656 return B_OK; 1657 } 1658 1659 info.interface->Up(); 1660 *info.thread = -1; 1661 1662 return B_OK; 1663 } 1664 1665 1666 // ---------------------------------- 1667 // Function: interface_deleter_thread 1668 // ---------------------------------- 1669 class KPPPInterfaceAccess { 1670 public: 1671 KPPPInterfaceAccess() {} 1672 1673 void Delete(KPPPInterface *interface) 1674 { delete interface; } 1675 void CallOpenEvent(KPPPInterface *interface) 1676 { 1677 while(interface->fLock.LockWithTimeout(100000) != B_NO_ERROR) 1678 if(interface->fDeleteCounter > 0) 1679 return; 1680 interface->CallOpenEvent(); 1681 interface->fOpenEventThread = -1; 1682 interface->fLock.Unlock(); 1683 } 1684 void CallCloseEvent(KPPPInterface *interface) 1685 { 1686 while(interface->fLock.LockWithTimeout(100000) != B_NO_ERROR) 1687 if(interface->fDeleteCounter > 0) 1688 return; 1689 interface->CallCloseEvent(); 1690 interface->fCloseEventThread = -1; 1691 interface->fLock.Unlock(); 1692 } 1693 }; 1694 1695 1696 status_t 1697 interface_deleter_thread(void *data) 1698 { 1699 KPPPInterfaceAccess access; 1700 access.Delete((KPPPInterface*) data); 1701 1702 return B_OK; 1703 } 1704 1705 1706 status_t 1707 call_open_event_thread(void *data) 1708 { 1709 KPPPInterfaceAccess access; 1710 access.CallOpenEvent((KPPPInterface*) data); 1711 1712 return B_OK; 1713 } 1714 1715 1716 status_t 1717 call_close_event_thread(void *data) 1718 { 1719 KPPPInterfaceAccess access; 1720 access.CallCloseEvent((KPPPInterface*) data); 1721 1722 return B_OK; 1723 } 1724