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