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 #include <arpa/inet.h> 27 28 #include <ByteOrder.h> 29 #include <net_buffer.h> 30 #include <net_stack.h> 31 #include <ppp_device.h> 32 33 // now our headers... 34 #include <KPPPInterface.h> 35 36 // our other classes 37 #include <PPPControl.h> 38 #include <KPPPDevice.h> 39 #include <KPPPLCPExtension.h> 40 #include <KPPPOptionHandler.h> 41 #include <KPPPModule.h> 42 #include <KPPPManager.h> 43 #include <KPPPUtils.h> 44 45 // general helper classes not only belonging to us 46 // #include <lock.h> 47 // #include <util/AutoLock.h> 48 49 // tools only for us :) 50 #include "settings_tools.h" 51 52 // internal modules 53 #include "_KPPPMRUHandler.h" 54 #include "_KPPPAuthenticationHandler.h" 55 #include "_KPPPPFCHandler.h" 56 57 58 // TODO: 59 // - implement timers with support for setting next event instead of receiving timer 60 // events periodically 61 // - add missing settings support (ConnectRetryDelay, etc.) 62 63 64 //! Private structure needed for reconnecting. 65 typedef struct reconnect_info { 66 KPPPInterface *interface; 67 thread_id *thread; 68 uint32 delay; 69 } reconnect_info; 70 71 extern net_buffer_module_info *gBufferModule; 72 extern net_stack_module_info *gStackModule; 73 74 status_t reconnect_thread(void *data); 75 76 // other functions 77 status_t interface_deleter_thread(void *data); 78 79 80 /*! \brief Creates a new interface. 81 82 \param name Name of the PPP interface description file. 83 \param entry The PPP manager passes an internal structure to the constructor. 84 \param ID The interface's ID. 85 \param settings (Optional): If no name is given you must pass the settings here. 86 \param parent (Optional): Interface's parent (only used for multilink interfaces). 87 */ 88 KPPPInterface::KPPPInterface(const char *name, ppp_interface_entry *entry, 89 ppp_interface_id ID, const driver_settings *settings, KPPPInterface *parent) 90 : 91 KPPPLayer(name, PPP_INTERFACE_LEVEL, 2), 92 fID(ID), 93 fSettings(NULL), 94 fIfnet(NULL), 95 fReconnectThread(-1), 96 fConnectAttempt(1), 97 fConnectRetriesLimit(0), 98 fManager(NULL), 99 fConnectedSince(0), 100 fIdleSince(0), 101 fMRU(1500), 102 fInterfaceMTU(1498), 103 fHeaderLength(2), 104 fParent(NULL), 105 fIsMultilink(false), 106 fAutoReconnect(false), 107 fConnectOnDemand(true), 108 fAskBeforeConnecting(false), 109 fMode(PPP_CLIENT_MODE), 110 fLocalPFCState(PPP_PFC_DISABLED), 111 fPeerPFCState(PPP_PFC_DISABLED), 112 fPFCOptions(0), 113 fDevice(NULL), 114 fFirstProtocol(NULL), 115 fStateMachine(*this), 116 fLCP(*this), 117 fReportManager(StateMachine().fLock), 118 fLock(StateMachine().fLock), 119 fDeleteCounter(0) 120 { 121 entry->interface = this; 122 123 if (name) { 124 // load settings from description file 125 char path[B_PATH_NAME_LENGTH]; 126 sprintf(path, "ptpnet/%s", name); 127 128 void *handle = load_driver_settings(path); 129 if (!handle) { 130 ERROR("KPPPInterface: Unable to load %s PPP driver settings!\n", path); 131 fInitStatus = B_ERROR; 132 return; 133 } 134 135 fSettings = dup_driver_settings(get_driver_settings(handle)); 136 unload_driver_settings(handle); 137 } else 138 fSettings = dup_driver_settings(settings); 139 // use the given settings 140 141 if (!fSettings) { 142 ERROR("KPPPInterface: No fSettings!\n"); 143 fInitStatus = B_ERROR; 144 return; 145 } 146 147 // add internal modules 148 // LCP 149 if (!AddProtocol(&LCP())) { 150 ERROR("KPPPInterface: Could not add LCP protocol!\n"); 151 fInitStatus = B_ERROR; 152 return; 153 } 154 // MRU 155 _KPPPMRUHandler *mruHandler = 156 new _KPPPMRUHandler(*this); 157 if (!LCP().AddOptionHandler(mruHandler) || mruHandler->InitCheck() != B_OK) { 158 ERROR("KPPPInterface: Could not add MRU handler!\n"); 159 delete mruHandler; 160 } 161 // authentication 162 _KPPPAuthenticationHandler *authenticationHandler = 163 new _KPPPAuthenticationHandler(*this); 164 if (!LCP().AddOptionHandler(authenticationHandler) 165 || authenticationHandler->InitCheck() != B_OK) { 166 ERROR("KPPPInterface: Could not add authentication handler!\n"); 167 delete authenticationHandler; 168 } 169 // PFC 170 _KPPPPFCHandler *pfcHandler = 171 new _KPPPPFCHandler(fLocalPFCState, fPeerPFCState, *this); 172 if (!LCP().AddOptionHandler(pfcHandler) || pfcHandler->InitCheck() != B_OK) { 173 ERROR("KPPPInterface: Could not add PFC handler!\n"); 174 delete pfcHandler; 175 } 176 177 // set up connect delays 178 fConnectRetryDelay = 3000; 179 // 3s delay between each new attempt to reconnect 180 fReconnectDelay = 1000; 181 // 1s delay between lost connection and reconnect 182 183 if (get_module(PPP_INTERFACE_MODULE_NAME, (module_info**) &fManager) != B_OK) 184 ERROR("KPPPInterface: Manager module not found!\n"); 185 186 // are we a multilink subinterface? 187 if (parent && parent->IsMultilink()) { 188 fParent = parent; 189 fParent->AddChild(this); 190 fIsMultilink = true; 191 } 192 193 RegisterInterface(); 194 195 if (!fSettings) { 196 fInitStatus = B_ERROR; 197 return; 198 } 199 200 const char *value; 201 202 // get login 203 value = get_settings_value(PPP_USERNAME_KEY, fSettings); 204 fUsername = value ? strdup(value) : strdup(""); 205 value = get_settings_value(PPP_PASSWORD_KEY, fSettings); 206 fPassword = value ? strdup(value) : strdup(""); 207 208 // get DisonnectAfterIdleSince settings 209 value = get_settings_value(PPP_DISONNECT_AFTER_IDLE_SINCE_KEY, fSettings); 210 if (!value) 211 fDisconnectAfterIdleSince = 0; 212 else 213 fDisconnectAfterIdleSince = atoi(value) * 1000; 214 215 if (fDisconnectAfterIdleSince < 0) 216 fDisconnectAfterIdleSince = 0; 217 218 // get mode settings 219 value = get_settings_value(PPP_MODE_KEY, fSettings); 220 if (value && !strcasecmp(value, PPP_SERVER_MODE_VALUE)) 221 fMode = PPP_SERVER_MODE; 222 else 223 fMode = PPP_CLIENT_MODE; 224 // we are a client by default 225 226 SetAutoReconnect( 227 get_boolean_value( 228 get_settings_value(PPP_AUTO_RECONNECT_KEY, fSettings), 229 false) 230 ); 231 // auto reconnect is disabled by default 232 233 fAskBeforeConnecting = get_boolean_value( 234 get_settings_value(PPP_ASK_BEFORE_CONNECTING_KEY, fSettings), false); 235 236 // load all protocols and the device 237 if (!LoadModules(fSettings, 0, fSettings->parameter_count)) { 238 ERROR("KPPPInterface: Error loading modules!\n"); 239 fInitStatus = B_ERROR; 240 } 241 } 242 243 244 //! Destructor: Disconnects and marks interface for deletion. 245 KPPPInterface::~KPPPInterface() 246 { 247 TRACE("KPPPInterface: Destructor\n"); 248 249 // tell protocols to uninit (remove routes, etc.) 250 KPPPProtocol *protocol = FirstProtocol(); 251 for (; protocol; protocol = protocol->NextProtocol()) 252 protocol->Uninit(); 253 254 // make sure we are not accessible by any thread before we continue 255 UnregisterInterface(); 256 257 if (fManager) 258 fManager->RemoveInterface(ID()); 259 260 // Call Down() until we get a lock on an interface that is down. 261 // This lock is not released until we are actually deleted. 262 while (true) { 263 Down(); 264 { 265 MutexLocker locker(fLock); 266 if (State() == PPP_INITIAL_STATE && Phase() == PPP_DOWN_PHASE) 267 break; 268 } 269 } 270 271 Report(PPP_DESTRUCTION_REPORT, 0, &fID, sizeof(ppp_interface_id)); 272 // tell all listeners that we are being destroyed 273 274 int32 tmp; 275 send_data_with_timeout(fReconnectThread, 0, NULL, 0, 200); 276 // tell thread that we are being destroyed (200ms timeout) 277 wait_for_thread(fReconnectThread, &tmp); 278 279 while (CountChildren()) 280 delete ChildAt(0); 281 282 delete Device(); 283 284 while (FirstProtocol()) { 285 if (FirstProtocol() == &LCP()) 286 fFirstProtocol = fFirstProtocol->NextProtocol(); 287 else 288 delete FirstProtocol(); 289 // destructor removes protocol from list 290 } 291 292 for (int32 index = 0; index < fModules.CountItems(); index++) { 293 put_module(fModules.ItemAt(index)); 294 delete[] fModules.ItemAt(index); 295 } 296 297 free_driver_settings(fSettings); 298 299 if (Parent()) 300 Parent()->RemoveChild(this); 301 302 if (fManager) 303 put_module(PPP_INTERFACE_MODULE_NAME); 304 } 305 306 307 //! Marks interface for deletion. 308 void 309 KPPPInterface::Delete() 310 { 311 // MutexLocker locker(fLock); 312 // alreay locked in KPPPStatemachine::DownEvent 313 // uncomment this line will cause double lock 314 315 if (fDeleteCounter > 0) 316 return; 317 // only one thread should delete us! 318 319 fDeleteCounter = 1; 320 321 fManager->DeleteInterface(ID()); 322 // This will mark us for deletion. 323 // Any subsequent calls to delete_interface() will do nothing. 324 } 325 326 327 //! Returns if interface was initialized correctly. 328 status_t 329 KPPPInterface::InitCheck() const 330 { 331 if (fInitStatus != B_OK) 332 return fInitStatus; 333 334 if (!fSettings || !fManager) 335 return B_ERROR; 336 337 // sub-interfaces should have a device 338 if (IsMultilink()) { 339 if (Parent() && !fDevice) 340 return B_ERROR; 341 } else if (!fDevice) 342 return B_ERROR; 343 344 return B_OK; 345 } 346 347 348 //! The username used for authentication. 349 const char* 350 KPPPInterface::Username() const 351 { 352 // this data is not available before we authenticate 353 if (Phase() < PPP_AUTHENTICATION_PHASE) 354 return NULL; 355 356 return fUsername; 357 } 358 359 360 //! The password used for authentication. 361 const char* 362 KPPPInterface::Password() const 363 { 364 // this data is not available before we authenticate 365 if (Phase() < PPP_AUTHENTICATION_PHASE) 366 return NULL; 367 368 return fPassword; 369 } 370 371 372 //! Sets interface MRU. 373 bool 374 KPPPInterface::SetMRU(uint32 MRU) 375 { 376 TRACE("KPPPInterface: SetMRU(%ld)\n", MRU); 377 378 if (Device() && MRU > Device()->MTU() - 2) 379 return false; 380 381 // MutexLocker locker(fLock); 382 // uncomment this line will cause double lock 383 // alreay locked in ::Up and ::KPPPInterface 384 385 fMRU = MRU; 386 387 CalculateInterfaceMTU(); 388 389 return true; 390 } 391 392 393 //! Returns number of bytes spent for protocol overhead. Includes device overhead. 394 uint32 395 KPPPInterface::PacketOverhead() const 396 { 397 uint32 overhead = fHeaderLength + 2; 398 399 if (Device()) 400 overhead += Device()->Overhead(); 401 402 return overhead; 403 } 404 405 406 /*! \brief Allows accessing additional functions. 407 408 This is normally called by userland apps to get information about the interface. 409 410 \param op The op value (see ppp_control_ops enum). 411 \param data (Optional): Additional data may be needed for this op. 412 \param length Length of data. 413 414 \return 415 - \c B_OK: \c Control() was successful. 416 - \c B_ERROR: Either \a length is too small or data is NULL. 417 - \c B_NOT_ALLOWED: Operation not allowed (at this point in time). 418 - \c B_BAD_INDEX: Wrong index (e.g.: when accessing interface submodules). 419 - \c B_BAD_VALUE: Unknown op. 420 - Return value of submodule (when controlling one). 421 */ 422 status_t 423 KPPPInterface::Control(uint32 op, void *data, size_t length) 424 { 425 TRACE("%s:%s\n", __FILE__, __func__); 426 427 control_net_module_args* args = (control_net_module_args*)data; 428 if (op != NET_STACK_CONTROL_NET_MODULE) { 429 dprintf("unknow op!!\n"); 430 return B_BAD_VALUE; 431 } 432 433 switch (args->op) { 434 case PPPC_COUNT_INTERFACES: 435 { 436 // should be implepented 437 dprintf("PPPC_COUNT_INTERFACES should be implepentd\n"); 438 439 return B_OK; 440 } 441 442 case PPPC_GET_INTERFACES: 443 { 444 dprintf("PPPC_GET_INTERFACES\n"); 445 ppp_get_interfaces_info* info = (ppp_get_interfaces_info*)args->data; 446 dprintf("info->interfaces: %p\n", info->interfaces); 447 *(info->interfaces) = 1; 448 info->resultCount = 1; 449 450 return B_OK; 451 } 452 453 case PPPC_CONTROL_INTERFACE: 454 { 455 dprintf("PPPC_CONTROL_INTERFACE\n"); 456 ppp_control_info* control = (ppp_control_info*)args->data; 457 458 switch (control->op) { 459 case PPPC_GET_INTERFACE_INFO: 460 { 461 dprintf("PPPC_GET_INTERFACE_INFO\n"); 462 if (control->length < sizeof(ppp_interface_info_t) || !control->data) { 463 dprintf("size wrong!\n"); 464 return B_ERROR; 465 } 466 467 ppp_interface_info *info = (ppp_interface_info*) control->data; 468 dprintf("info addr:%p\n", info); 469 memset(info, 0, sizeof(ppp_interface_info_t)); 470 if (Name()) 471 strncpy(info->name, Name(), PPP_HANDLER_NAME_LENGTH_LIMIT); 472 473 if (Ifnet()) 474 info->if_unit = Ifnet()->index; 475 else 476 info->if_unit = -1; 477 info->mode = Mode(); 478 info->state = State(); 479 info->phase = Phase(); 480 info->localAuthenticationStatus = 481 StateMachine().LocalAuthenticationStatus(); 482 info->peerAuthenticationStatus = 483 StateMachine().PeerAuthenticationStatus(); 484 info->localPFCState = LocalPFCState(); 485 info->peerPFCState = PeerPFCState(); 486 info->pfcOptions = PFCOptions(); 487 info->protocolsCount = CountProtocols(); 488 info->optionHandlersCount = LCP().CountOptionHandlers(); 489 info->LCPExtensionsCount = 0; 490 info->childrenCount = CountChildren(); 491 info->MRU = MRU(); 492 info->interfaceMTU = InterfaceMTU(); 493 info->connectAttempt = fConnectAttempt; 494 info->connectRetriesLimit = fConnectRetriesLimit; 495 info->connectRetryDelay = ConnectRetryDelay(); 496 info->reconnectDelay = ReconnectDelay(); 497 info->connectedSince = ConnectedSince(); 498 info->idleSince = IdleSince(); 499 info->disconnectAfterIdleSince = DisconnectAfterIdleSince(); 500 info->doesConnectOnDemand = DoesConnectOnDemand(); 501 info->doesAutoReconnect = DoesAutoReconnect(); 502 info->hasDevice = Device(); 503 info->isMultilink = IsMultilink(); 504 info->hasParent = Parent(); 505 break; 506 } 507 508 case PPPC_SET_USERNAME: 509 { 510 dprintf("PPPC_SET_USERNAME\n"); 511 if (control->length > PPP_HANDLER_NAME_LENGTH_LIMIT || !control->data) { 512 dprintf("size wrong!\n"); 513 return B_ERROR; 514 } 515 516 MutexLocker locker(fLock); 517 // login information can only be changed before we authenticate 518 if (Phase() >= PPP_AUTHENTICATION_PHASE) 519 return B_NOT_ALLOWED; 520 521 free(fUsername); 522 fUsername = control->data ? strdup((const char*) control->data) : strdup(""); 523 dprintf("set ppp user name to %s\n", fUsername); 524 525 break; 526 } 527 528 case PPPC_SET_PASSWORD: 529 { 530 dprintf("PPPC_SET_PASSWORD\n"); 531 if (control->length > PPP_HANDLER_NAME_LENGTH_LIMIT || !control->data) { 532 dprintf("size wrong!\n"); 533 return B_ERROR; 534 } 535 536 MutexLocker locker(fLock); 537 // login information can only be changed before we authenticate 538 if (Phase() >= PPP_AUTHENTICATION_PHASE) 539 return B_NOT_ALLOWED; 540 541 free(fPassword); 542 fPassword = control->data ? strdup((const char*) control->data) : strdup(""); 543 dprintf("set ppp password to %s!\n", fPassword); 544 break; 545 } 546 547 case PPPC_SET_ASK_BEFORE_CONNECTING: 548 { 549 dprintf("PPPC_SET_ASK_BEFORE_CONNECTING\n"); 550 if (control->length < sizeof(uint32) || !control->data) { 551 dprintf("size wrong!\n"); 552 return B_ERROR; 553 } 554 555 SetAskBeforeConnecting(*((uint32*)control->data)); 556 dprintf("goto PPPC_SET_ASK_BEFORE_CONNECTING here!\n"); 557 break; 558 } 559 560 case PPPC_GET_STATISTICS: 561 { 562 dprintf("PPPC_GET_STATISTICS\n"); 563 if (control->length < sizeof(ppp_statistics) || !control->data) { 564 dprintf("size wrong!\n"); 565 return B_ERROR; 566 } 567 568 dprintf("should PPPC_GET_STATISTICS here!\n"); 569 570 memcpy(control->data, &fStatistics, sizeof(ppp_statistics)); 571 break; 572 } 573 574 case PPPC_HAS_INTERFACE_SETTINGS: 575 { 576 dprintf("PPPC_HAS_INTERFACE_SETTINGS\n"); 577 if (control->length < sizeof(driver_settings) || !control->data) { 578 dprintf("size wrong!\n"); 579 return B_ERROR; 580 } 581 582 dprintf("should PPPC_HAS_INTERFACE_SETTINGS here!\n"); 583 584 if (equal_interface_settings(Settings(), (driver_settings*)control->data)) 585 return B_OK; 586 else 587 return B_ERROR; 588 break; 589 590 } 591 592 case PPPC_ENABLE_REPORTS: 593 { 594 dprintf("PPPC_ENABLE_REPORTS\n"); 595 if (control->length < sizeof(ppp_report_request) || !control->data) { 596 dprintf("size wrong!\n"); 597 return B_ERROR; 598 } 599 600 dprintf("should PPPC_ENABLE_REPORTS here!\n"); 601 602 MutexLocker locker(fLock); 603 ppp_report_request *request = (ppp_report_request*) control->data; 604 // first, we send an initial state report 605 if (request->type == PPP_CONNECTION_REPORT) { 606 ppp_report_packet report; 607 report.type = PPP_CONNECTION_REPORT; 608 report.code = StateMachine().fLastConnectionReportCode; 609 report.length = sizeof(fID); 610 KPPPReportManager::SendReport(request->thread, &report); 611 if (request->flags & PPP_REMOVE_AFTER_REPORT) 612 return B_OK; 613 } 614 ReportManager().EnableReports(request->type, request->thread, 615 request->flags); 616 break; 617 } 618 619 case PPPC_DISABLE_REPORTS: 620 { 621 dprintf("PPPC_DISABLE_REPORTS\n"); 622 if (control->length < sizeof(ppp_report_request) || !control->data) { 623 dprintf("size wrong!\n"); 624 return B_ERROR; 625 } 626 627 dprintf("should PPPC_DISABLE_REPORTS here!\n"); 628 629 ppp_report_request *request = (ppp_report_request*) control->data; 630 ReportManager().DisableReports(request->type, request->thread); 631 break; 632 } 633 634 case PPPC_CONTROL_DEVICE: 635 { 636 dprintf("PPPC_CONTROL_DEVICE\n"); 637 if (control->length < sizeof(ppp_control_info) || !control->data) 638 return B_ERROR; 639 640 ppp_control_info *controlInfo = (ppp_control_info*) control->data; 641 if (controlInfo->index != 0 || !Device()) { 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 2026 2027 //! Reconnects. Waits a given delay (in miliseconds) before reconnecting. 2028 void 2029 KPPPInterface::Reconnect(uint32 delay) 2030 { 2031 TRACE("KPPPInterface: Reconnect(%ld)\n", delay); 2032 2033 MutexLocker locker(fLock); 2034 2035 if (fReconnectThread != -1) 2036 return; 2037 2038 ++fConnectAttempt; 2039 2040 // start a new thread that calls our Up() method 2041 reconnect_info info; 2042 info.interface = this; 2043 info.thread = &fReconnectThread; 2044 info.delay = delay; 2045 2046 fReconnectThread = spawn_kernel_thread(reconnect_thread, 2047 "KPPPInterface: reconnect_thread", B_NORMAL_PRIORITY, NULL); 2048 2049 resume_thread(fReconnectThread); 2050 2051 send_data(fReconnectThread, 0, &info, sizeof(reconnect_info)); 2052 } 2053 2054 2055 status_t 2056 reconnect_thread(void *data) 2057 { 2058 reconnect_info info; 2059 thread_id sender; 2060 int32 code; 2061 2062 receive_data(&sender, &info, sizeof(reconnect_info)); 2063 2064 // we try to receive data instead of snooze, so we can quit on destruction 2065 if (receive_data_with_timeout(&sender, &code, NULL, 0, info.delay) == B_OK) { 2066 *info.thread = -1; 2067 return B_OK; 2068 } 2069 2070 info.interface->Up(); 2071 *info.thread = -1; 2072 2073 return B_OK; 2074 } 2075