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