diff --git a/src/tests/kits/net/ppp/headers/KPPPConfigurePacket.h b/src/tests/kits/net/ppp/headers/KPPPConfigurePacket.h index c5786287c9..338f290e57 100644 --- a/src/tests/kits/net/ppp/headers/KPPPConfigurePacket.h +++ b/src/tests/kits/net/ppp/headers/KPPPConfigurePacket.h @@ -44,7 +44,7 @@ class PPPConfigurePacket { int32 CountItems() const; configure_item *ItemAt(int32 index) const; - mbuf *ToMbuf(); + mbuf *ToMbuf(uint32 reserve = 0, uint32 maxSize = 0); // the user is responsible for freeing the mbuf private: diff --git a/src/tests/kits/net/ppp/headers/KPPPDefs.h b/src/tests/kits/net/ppp/headers/KPPPDefs.h index bcf84c362f..22c3d20513 100644 --- a/src/tests/kits/net/ppp/headers/KPPPDefs.h +++ b/src/tests/kits/net/ppp/headers/KPPPDefs.h @@ -11,29 +11,35 @@ #include +typedef uint32 interface_id; + +// various constants +#define PPP_PULSE_RATE 750000 + // settings keys -#define PPP_MODE_KEY "Mode" -#define PPP_DIAL_ON_DEMAND_KEY "DialOnDemand" -#define PPP_AUTO_REDIAL_KEY "AutoRedial" -#define PPP_LOAD_MODULE_KEY "LoadModule" -#define PPP_PROTOCOL_KEY "Protocol" -#define PPP_DEVICE_KEY "Device" -#define PPP_AUTHENTICATOR_KEY "Authenticator" -#define PPP_PEER_AUTHENTICATOR_KEY "Peer-Authenticator" -#define PPP_MULTILINK_KEY "Multilink-Protocol" +#define PPP_DISONNECT_AFTER_IDLE_SINCE_KEY "DisonnectAfterIdleSince" +#define PPP_MODE_KEY "Mode" +#define PPP_DIAL_ON_DEMAND_KEY "DialOnDemand" +#define PPP_AUTO_REDIAL_KEY "AutoRedial" +#define PPP_LOAD_MODULE_KEY "LoadModule" +#define PPP_PROTOCOL_KEY "Protocol" +#define PPP_DEVICE_KEY "Device" +#define PPP_AUTHENTICATOR_KEY "Authenticator" +#define PPP_PEER_AUTHENTICATOR_KEY "Peer-Authenticator" +#define PPP_MULTILINK_KEY "Multilink-Protocol" // settings values -#define PPP_CLIENT_MODE_VALUE "Client" -#define PPP_SERVER_MODE_VALUE "Server" +#define PPP_CLIENT_MODE_VALUE "Client" +#define PPP_SERVER_MODE_VALUE "Server" // path defines -#define PPP_MODULES_PATH "network/ppp-modules" +#define PPP_MODULES_PATH "network/ppp-modules" // built-in protocols -#define PPP_LCP_PROTOCOL 0xC021 +#define PPP_LCP_PROTOCOL 0xC021 -#define PPP_ERROR_BASE B_ERRORS_END +#define PPP_ERROR_BASE B_ERRORS_END // return values for Send()/Receive() methods in addition to B_ERROR and B_OK // PPP_UNHANDLED is also used by PPPOptionHandler diff --git a/src/tests/kits/net/ppp/headers/KPPPDevice.h b/src/tests/kits/net/ppp/headers/KPPPDevice.h index bb776ac546..fa261ef191 100644 --- a/src/tests/kits/net/ppp/headers/KPPPDevice.h +++ b/src/tests/kits/net/ppp/headers/KPPPDevice.h @@ -13,11 +13,11 @@ class PPPDevice { public: - PPPDevice(const char *fName, uint32 overhead, PPPInterface *interface, + PPPDevice(const char *name, uint32 overhead, PPPInterface *interface, driver_parameter *settings); virtual ~PPPDevice(); - virtual status_t InitCheck() const = 0; + virtual status_t InitCheck() const; const char *Name() const { return fName; } @@ -58,18 +58,20 @@ class PPPDevice { // This will pass the packet to the interface's queue. // Do not call Interface::ReceiveFromDevice directly // if this can block a Send()! + + virtual void Pulse(); protected: // Report that we are going up/down // (from now on, the Up() process can be aborted). // Abort if false is returned! - bool UpStarted(); - bool DownStarted(); + bool UpStarted() const; + bool DownStarted() const; // report up/down events - void UpEvent(); - void UpFailedEvent(); - void DownEvent(); + void UpFailedEvent() const; + void UpEvent() const; + void DownEvent() const; protected: bool fIsUp; diff --git a/src/tests/kits/net/ppp/headers/KPPPEncapsulator.h b/src/tests/kits/net/ppp/headers/KPPPEncapsulator.h index 4807cd366a..c22b91dadc 100644 --- a/src/tests/kits/net/ppp/headers/KPPPEncapsulator.h +++ b/src/tests/kits/net/ppp/headers/KPPPEncapsulator.h @@ -19,7 +19,7 @@ class PPPEncapsulator { int32 flags = PPP_NO_FLAGS); virtual ~PPPEncapsulator(); - virtual status_t InitCheck() const = 0; + virtual status_t InitCheck() const; const char *Name() const { return fName; } @@ -46,7 +46,8 @@ class PPPEncapsulator { bool IsEnabled() const { return fEnabled; } - void SetUpRequested(bool requested = true); + void SetUpRequested(bool requested = true) + { fUpRequested = requested; } bool IsUpRequested() const { return fUpRequested; } @@ -71,10 +72,12 @@ class PPPEncapsulator { virtual status_t Send(mbuf *packet, uint16 protocol) = 0; virtual status_t Receive(mbuf *packet, uint16 protocol) = 0; - status_t SendToNext(mbuf *packet, uint16 protocol); + status_t SendToNext(mbuf *packet, uint16 protocol) const; // this will send your packet to the next (up) encapsulator // if there is no next encapsulator (==NULL), it will // call the interface's SendToDevice function + + virtual void Pulse(); protected: void UpStarted(); @@ -91,10 +94,11 @@ class PPPEncapsulator { private: char *fName; PPP_ENCAPSULATION_LEVEL fLevel; + uint16 fProtocol; + int32 fAddressFamily; PPPInterface *fInterface; driver_parameter *fSettings; - uint16 fProtocol; - int32 fAddressFamily, fFlags; + int32 fFlags; PPPEncapsulator *fNext; diff --git a/src/tests/kits/net/ppp/headers/KPPPInterface.h b/src/tests/kits/net/ppp/headers/KPPPInterface.h index 991ea02423..9b883f555a 100644 --- a/src/tests/kits/net/ppp/headers/KPPPInterface.h +++ b/src/tests/kits/net/ppp/headers/KPPPInterface.h @@ -34,13 +34,17 @@ class PPPInterface { PPPInterface& operator= (const PPPInterface& copy); public: - PPPInterface(driver_settings *settings, PPPInterface *parent = NULL); + PPPInterface(interface_id ID, driver_settings *settings, + PPPInterface *parent = NULL); ~PPPInterface(); void Delete(); status_t InitCheck() const; + interface_id ID() const + { return fID; } + driver_settings* Settings() { return fSettings; } @@ -55,6 +59,12 @@ class PPPInterface { struct ifq *InQueue() const { return fInQueue; } + // idle handling + bigtime_t IdleSince() const + { return fIdleSince; } + bigtime_t DisconnectAfterIdleSince() const + { return fDisconnectAfterIdleSince; } + void SetLinkMTU(uint32 linkMTU); uint32 LinkMTU() const { return fLinkMTU; } @@ -142,6 +152,7 @@ class PPPInterface { bool UnregisterInterface(); void CalculateMRU(); + void CalculateBaudRate(); void Redial(); @@ -150,7 +161,9 @@ class PPPInterface { { fParent = parent; } private: - driver_parameter *fSettings; + interface_id fID; + // the manager assigns an ID to every interface + driver_settings *fSettings; PPPStateMachine fStateMachine; PPPLCP fLCP; PPPReportManager fReportManager; @@ -164,6 +177,7 @@ class PPPInterface { ppp_manager_info *fManager; + bigtime_t fIdleSince, fDisconnectAfterIdleSince; uint32 fLinkMTU, fMRU, fHeaderLength; PPPInterface *fParent; diff --git a/src/tests/kits/net/ppp/headers/KPPPLCP.h b/src/tests/kits/net/ppp/headers/KPPPLCP.h index 8c8265a041..524ffb38ee 100644 --- a/src/tests/kits/net/ppp/headers/KPPPLCP.h +++ b/src/tests/kits/net/ppp/headers/KPPPLCP.h @@ -41,10 +41,15 @@ class PPPLCP : public PPPProtocol { { return fOptionHandlers.CountItems(); } PPPOptionHandler *OptionHandlerAt(int32 index) const; + PPPEncapsulator *Target() const + { return fTarget; } void SetTarget(PPPEncapsulator *target) { fTarget = target; } // if target != all packtes will be passed to the encapsulator // instead of the interface/device + + uint32 AdditionalOverhead() const; + // the overhead caused by the target, the device, and the interface private: List fOptionHandlers; diff --git a/src/tests/kits/net/ppp/headers/KPPPManager.h b/src/tests/kits/net/ppp/headers/KPPPManager.h index b2e3406a61..b9fde301b1 100644 --- a/src/tests/kits/net/ppp/headers/KPPPManager.h +++ b/src/tests/kits/net/ppp/headers/KPPPManager.h @@ -13,25 +13,30 @@ #define PPP_MANAGER_MODULE_NAME "network/interfaces/ppp" +// this allows you to ask for specific interface_ids +enum PPP_INTERFACE_FILTER { + PPP_ALL_INTERFACES, + PPP_REGISTERED_INTERFACES, + PPP_UNREGISTERED_INTERFACES +}; typedef struct ppp_manager_info { kernel_net_module_info knminfo; - // when you want to iterate through interfaces you should use locking - void (*lock)(); - void (*unlock)(); + uint32 (*create_interface)(driver_settings *settings, interface_id parent); + // you should always create interfaces using this function + void (*delete_interface)(interface_id ID); + // this marks the interface for deletion - ifnet* (*add_interface)(PPPInterface *interface); - bool (*remove_interface)(PPPInterface *interface); + ifnet* (*register_interface)(interface_id ID); + bool (*unregister_interface)(interface_id ID); - int32 (*count_interfaces)(int32 index); + status_t (*control)(interface_id ID, uint32 op, void *data, size_t length); - PPPInterface *(*get_interface_at)(int32 index); - void (*put_interface)(PPPInterface *interface); - - void (*delete_interface)(PPPInterface *interface); - // this deletes the interface when it is not needed anymore -} ppp_manager; + status_t (*get_interfaces)(interface_id **interfaces, uint32 *count, + PPP_INTERFACE_FILTER filter = PPP_REGISTERED_INTERFACES); + // the user is responsible for free()'ing the interface_id array +} ppp_manager_info; #endif diff --git a/src/tests/kits/net/ppp/headers/KPPPOptionHandler.h b/src/tests/kits/net/ppp/headers/KPPPOptionHandler.h index d804f22e19..b91b70b296 100644 --- a/src/tests/kits/net/ppp/headers/KPPPOptionHandler.h +++ b/src/tests/kits/net/ppp/headers/KPPPOptionHandler.h @@ -18,7 +18,7 @@ class PPPOptionHandler { driver_parameter *settings); virtual ~PPPOptionHandler(); - virtual status_t InitCheck() = 0; + virtual status_t InitCheck() const; void SetEnabled(bool enabled = true); bool IsEnabled() const diff --git a/src/tests/kits/net/ppp/headers/KPPPProtocol.h b/src/tests/kits/net/ppp/headers/KPPPProtocol.h index c647843e76..6095ee3c0f 100644 --- a/src/tests/kits/net/ppp/headers/KPPPProtocol.h +++ b/src/tests/kits/net/ppp/headers/KPPPProtocol.h @@ -18,7 +18,7 @@ class PPPProtocol { driver_parameter *settings, int32 flags = PPP_NO_FLAGS); virtual ~PPPProtocol(); - virtual status_t InitCheck() const = 0; + virtual status_t InitCheck() const; const char *Name() const { return fName; } @@ -41,7 +41,8 @@ class PPPProtocol { bool IsEnabled() const { return fEnabled; } - void SetUpRequested(bool requested = true); + void SetUpRequested(bool requested = true) + { fUpRequested = requested; } bool IsUpRequested() const { return fUpRequested; } @@ -60,6 +61,8 @@ class PPPProtocol { virtual status_t Send(mbuf *packet) = 0; virtual status_t Receive(mbuf *packet) = 0; + + virtual void Pulse(); protected: void UpStarted(); @@ -74,9 +77,10 @@ class PPPProtocol { char *name; PPP_PHASE fPhase; uint16 fProtocol; - int32 fAddressFamily, fFlags; + int32 fAddressFamily; PPPInterface fInterface; driver_parameter fSettings; + int32 fFlags; bool fEnabled; bool fUpRequested; diff --git a/src/tests/kits/net/ppp/headers/KPPPReportDefs.h b/src/tests/kits/net/ppp/headers/KPPPReportDefs.h index b43fb29f76..b68aa682af 100644 --- a/src/tests/kits/net/ppp/headers/KPPPReportDefs.h +++ b/src/tests/kits/net/ppp/headers/KPPPReportDefs.h @@ -26,7 +26,8 @@ enum PPP_REPORT_FLAGS { enum PPP_REPORT_TYPE { PPP_DESTRUCTION_REPORT = 0, // the interface is being destroyed (no code is needed) - PPP_CONNECTION_REPORT = 1 + PPP_CONNECTION_REPORT = 1, + PPP_AUTHENTICATION_REPORT = 2 }; // report codes (type-specific) @@ -36,10 +37,13 @@ enum PPP_CONNECTION_REPORT_CODES { PPP_REPORT_DOWN_SUCCESSFUL = 2, PPP_REPORT_UP_ABORTED = 3, PPP_REPORT_DEVICE_UP_FAILED = 4, - PPP_REPORT_AUTHENTICATION_FAILED = 5, - PPP_REPORT_CONNECTION_LOST = 6 + PPP_REPORT_AUTHENTICATION_SUCCESSFUL = 5, + PPP_REPORT_PEER_AUTHENTICATION_SUCCESSFUL = 6, + PPP_REPORT_AUTHENTICATION_FAILED = 7, + PPP_REPORT_CONNECTION_LOST = 8 }; + typedef struct ppp_report_packet { int32 type; int32 code; diff --git a/src/tests/kits/net/ppp/src/KPPPDevice.cpp b/src/tests/kits/net/ppp/src/KPPPDevice.cpp index 9c6044dd6a..d8b31f31bf 100644 --- a/src/tests/kits/net/ppp/src/KPPPDevice.cpp +++ b/src/tests/kits/net/ppp/src/KPPPDevice.cpp @@ -6,3 +6,127 @@ //--------------------------------------------------------------------- #include "KPPPDevice.h" + + +PPPDevice::PPPDevice(const char *name, uint32 overhead, PPPInterface *interface, + driver_parameter *settings) + : fOverhead(overhead), fInterface(interface), + fSettings(settings) +{ + fName = name ? strdup(name) : NULL; + + SetMTU(PreferredMTU()); + + if(interface) + interface->SetDevice(this); +} + + +PPPDevice::~PPPDevice() +{ + free(fName); + + if(Interface()) + Interface()->SetDevice(NULL); +} + + +status_t +PPPDevice::InitCheck() const +{ + if(!Interface() || !Settings()) + return B_ERROR; + + return B_OK; +} + + +status_t +PPPDevice::Control(uint32 op, void *data, size_t length) +{ + switch(op) { + // TODO: + // get: + // - name + // - mtu (+ preferred) + // - status + // - transfer rates + + default: + return B_ERROR; + } + + return B_OK; +} + +status_t +PPPDevice::PassToInterface(mbuf *packet) +{ + if(!Interface() || !Interface()->InQueue()) + return B_ERROR; + + IFQ_ENQUEUE(Interface()->InQueue(), packet); +} + + +void +PPPDevice::Pulse() +{ + // do nothing by default +} + + +bool +PPPDevice::UpStarted() const +{ + if(!Interface()) + return false; + + return Interface()->StateMachine().TLSNotify(); +} + + +bool +PPPDevice::DownStarted() const +{ + if(!Interface()) + return false; + + return Interface()->StateMachine().TLFNotify(); +} + + +void +PPPDevice::UpFailedEvent() +{ + fIsUp = false; + + if(!Interface()) + return; + + Interface()->StateMachine().UpFailedEvent(); +} + + +void +PPPDevice::UpEvent() +{ + fIsUp = true; + + if(!Interface()) + return; + + Interface()->StateMachine().UpEvent(); +} + + +void +PPPDevice::DownEvent() +{ + fIsUp = false; + + if(!Interface()) + return; + + Interface()->StateMachine().DownEvent(); +} diff --git a/src/tests/kits/net/ppp/src/KPPPEncapsulator.cpp b/src/tests/kits/net/ppp/src/KPPPEncapsulator.cpp index ceed3f3bfb..1fe032086f 100644 --- a/src/tests/kits/net/ppp/src/KPPPEncapsulator.cpp +++ b/src/tests/kits/net/ppp/src/KPPPEncapsulator.cpp @@ -6,3 +6,143 @@ //--------------------------------------------------------------------- #include "KPPPEncapsulator.h" + + +PPPEncapsulator::PPPEncapsulator(const char *name, PPP_ENCAPSULATION_LEVEL level, + uint16 protocol, int32 addressFamily, uint32 overhead, + PPPInterface *interface, driver_parameter *settings, + int32 flags = PPP_NO_FLAGS) + : fOverhead(overhead), fLevel(level), fProtocol(protocol), + fAddressFamily(addressFamily), fInterface(interface), + fSettings(settings), fFlags(flags), fEnabled(true), + fUpRequested(true), fConnectionStatus(PPP_DOWN_PHASE) +{ + fName = name ? strdup(name) : NULL; + + if(interface) + interface->AddEncapsulator(this); +} + + +PPPEncapsulator::~PPPEncapsulator() +{ + free(fName); + + if(Interface()) + Interface()->RemoveEncapsulator(this); +} + + +status_t +PPPEncapsulator::InitCheck() const +{ + if(!Interface() || !Settings()) + return B_ERROR; + + return B_OK; +} + + +void +PPPEncapsulator::SetEnabled(bool enabled = true) +{ + fEnabled = enabled; + + if(!Interface()) + return; + + if(!enabled) { + if(IsUp() || IsGoingUp())) + Down(); + } else if(!IsUp() && !IsGoingUp() && IsUpRequested() && Interface()->IsUp()) + Up(); +} + + +status_t +PPPEncapsulator::Control(uint32 op, void *data, size_t length) +{ + switch(op) { + // TODO: + // get: + // - name + // - level, protocol, address family, overhead + // - status (Is(Going)Up/Down/UpRequested/Enabled) + // set: + // - enabled + + default: + return B_ERROR; + } + + return B_OK; +} + + +status_t +PPPEncapsulator::SendToNext(mbuf *packet, uint16 protocol) const +{ + if(Next()) + return Next()->Send(packet, protocol); + else if(Interface()) + return Interface()->SendToDevice(packet, protocol); + else + return B_ERROR; +} + + +void +PPPEncapsulator::Pulse() +{ + // do nothing by default +} + + +void +PPPEncapsulator::UpStarted() +{ + fConnectionStatus = PPP_ESTABLISHMENT_PHASE; +} + + +void +PPPEncapsulator::DownStarted() +{ + fConnectionStatus = PPP_TERMINATION_PHASE; +} + + +void +PPPEncapsulator::UpFailedEvent() +{ + fConnectionStatus = PPP_DOWN_PHASE; + + if(!Interface()) + return; + + Interface()->StateMachine().UpFailedEvent(this); +} + + +void +PPPEncapsulator::UpEvent() +{ + fConnectionStatus = PPP_ESTABLISHED_PHASE; + + if(!Interface()) + return; + + Interface()->StateMachine().UpEvent(this); +} + + +void +PPPEncapsulator::DownEvent() +{ + fConnectionStatus = PPP_DOWN_PHASE; + + if(!Interface()) + return; + + Interface()->StateMachine().DownEvent(this); +} diff --git a/src/tests/kits/net/ppp/src/KPPPInterface.cpp b/src/tests/kits/net/ppp/src/KPPPInterface.cpp index 032ca1e1b4..1f841aa79c 100644 --- a/src/tests/kits/net/ppp/src/KPPPInterface.cpp +++ b/src/tests/kits/net/ppp/src/KPPPInterface.cpp @@ -12,7 +12,6 @@ #include "KPPPManager.h" // general helper classes not only belonging to us -#include "AccessHelper.h" #include "LockerHelper.h" // tools only for us :) @@ -43,13 +42,15 @@ status_t redial_func(void *data); status_t in_queue_thread(void *data); -PPPInterface::PPPInterface(driver_settings *settings, PPPInterface *parent = NULL) - : fSettings(dup_driver_settings(settings)), +PPPInterface::PPPInterface(uint32 ID, driver_settings *settings, + PPPInterface *parent = NULL) + : fID(ID), fSettings(dup_driver_settings(settings)), fStateMachine(*this), fLCP(*this), ReportManager()(StateMachine().Locker()), fIfnet(NULL), fUpThread(-1), fRedialThread(-1), fDialRetry(0), - fDialRetriesLimit(0), fLinkMTU(1500), fAccessing(0), fChildrenCount(0), - fDevice(NULL), fFirstEncapsulator(NULL), fLock(StateMachine().Locker()) + fDialRetriesLimit(0), fIdleSince(0), fLinkMTU(1500), fDevice(NULL), + fFirstEncapsulator(NULL), fLock(StateMachine().Locker()) { + // set up queue fInQueue = start_ifq(); fInQueueThread = spawn_kernel_thread(in_queue_thread, "PPPInterface: Input", B_NORMAL_PRIORITY, this); @@ -61,17 +62,32 @@ PPPInterface::PPPInterface(driver_settings *settings, PPPInterface *parent = NUL // are we a multilink subinterface? if(parent && parent->IsMultilink()) { fParent = parent; + fParent->AddChild(this); fIsMultilink = true; } else { fParent = NULL; fIsMultilink = false; } - if(!fSettings) + if(!fSettings) { + fMode = PPP_CLIENT_MODE; + fDisconnectAfterIdleSince = 0; return; + } const char *value; + // get DisonnectAfterIdleSince settings + value = get_settings_value(PPP_DISONNECT_AFTER_IDLE_SINCE_KEY, fSettings); + if(!value) + fDisconnectAfterIdleSince = 0; + else + fDisconnectAfterIdleSince = atoi(value); + + if(fDisconnectAfterIdleSince < 0) + fDisconnectAfterIdleSince = 0; + + // get mode settings value = get_settings_value(PPP_MODE_KEY, fSettings); if(!strcasecmp(value, PPP_SERVER_MODE_VALUE)) fMode = PPP_SERVER_MODE; @@ -132,7 +148,7 @@ PPPInterface::~PPPInterface() void PPPInterface::Delete() { - fManager->delete_interface(this); + fManager->delete_interface(ID()); } @@ -177,7 +193,7 @@ PPPInterface::Control(uint32 op, void *data, size_t length) default: - return B_ERROR; + return B_ERROR; } return B_OK; @@ -206,11 +222,9 @@ PPPInterface::SetDevice(PPPDevice *device) fDevice = device; fLinkMTU = fDevice->MTU(); - if(Ifnet()) - Ifnet()->if_baudrate = max(fDevice->InputTransferRate(), - fDevice->OutputTransferRate()); CalculateMRU(); + CalculateBaudRate(); } @@ -407,9 +421,7 @@ PPPInterface::RemoveChild(PPPInterface *child) // parents cannot exist without their children if(CountChildren() == 0 && fManager && Ifnet()) - fManager->delete_interface(this); - - CalculateMRU(); + fManager->delete_interface(ID()); return true; } @@ -534,7 +546,7 @@ PPPInterface::Up() fUpThread = -1; if(!DoesDialOnDemand() && report.code != PPP_REPORT_DOWN_SUCCESSFUL) - fManager->delete_interface(this); + fManager->delete_interface(ID()); } PPP_REPLY(sender, B_OK); @@ -572,7 +584,7 @@ PPPInterface::Up() if(!DoesDialOnDemand() && report.code != PPP_REPORT_DOWN_SUCCESSFUL) - fManager->delete_interface(this); + fManager->delete_interface(ID()); PPP_REPLY(sender, B_OK); ReportManager().DisableReports(PPP_CONNECTION_REPORT, me); @@ -599,12 +611,15 @@ PPPInterface::Up() if(!DoesDialOnDemand() && report.code != PPP_REPORT_DOWN_SUCCESSFUL) - fManager->delete_interface(this); + fManager->delete_interface(ID()); return false; } } } + + // if the code is unknown we continue + PPP_REPLY(sender, B_OK); } return false; @@ -644,7 +659,7 @@ PPPInterface::Down() } if(!DoesDialOnDemand()) - fManager->delete_interface(this); + fManager->delete_interface(ID()); return true; } @@ -674,12 +689,11 @@ PPPInterface::LoadModules(const driver_settings *settings, // multilink handling for(int32 i = start; - i < settings->parameter_count && i < start + count; - i++) { + i < settings->parameter_count && i < start + count; i++) { if(!strcasecmp(settings->parameters[i].name, PPP_MULTILINK_KEY) - && settings->parameters[i].value_count > 0) { + && settings->parameters[i].value_count > 0) { if(!LoadModule(settings->parameters[i].value[0], - parameters[i].parameters, PPP_MULTILINK_TYPE)) + parameters[i].parameters, PPP_MULTILINK_TYPE)) return false; break; } @@ -690,14 +704,12 @@ PPPInterface::LoadModules(const driver_settings *settings, if(IsMultilink() && !Parent()) { // main interfaces only load the multilink module // and create a child using their settings - AddChild(new PPPInterface(settings, this)); + fManager->create_interface(settings, ID()); return true; } for(int32 i = start; - i < settings->parameter_count && i < start + count; - i++) { - + i < settings->parameter_count && i < start + count; i++) { type = -1; name = settings->parameters[i].name; @@ -715,9 +727,9 @@ PPPInterface::LoadModules(const driver_settings *settings, if(type >= 0) for(int32 value_id = 0; value_id < settings->parameters[i].value_count; - value_id++) + value_id++) if(!LoadModule(settings->parameters[i].value[value_id], - settings->parameters[i].parameters, type)) + settings->parameters[i].parameters, type)) return false; } @@ -756,8 +768,6 @@ PPPInterface::LoadModule(const char *name, const driver_parameter *parameter, status_t PPPInterface::Send(mbuf *packet, uint16 protocol) { - AccessHelper access(&fAccessing); - if(!packet) return B_ERROR; @@ -781,8 +791,10 @@ PPPInterface::Send(mbuf *packet, uint16 protocol) // Note that these protocols are not passed to encapsulators! PPPProtocol *sending_protocol = ProtocolFor(protocol); if(sending_protocol && sending_protocol->Flags() & PPP_ALWAYS_ALLOWED - && sending_protocol->IsEnabled() && fDevice->IsUp()) + && sending_protocol->IsEnabled() && fDevice->IsUp()) { + fIdleSince = system_time(); return SendToDevice(packet, protocol); + } // never send normal protocols when we are down if(!IsUp()) { @@ -790,6 +802,8 @@ PPPInterface::Send(mbuf *packet, uint16 protocol) return B_ERROR; } + fIdleSince = system_time(); + // send to next up encapsulator if(!fFirstEncapsulator) return SendToDevice(packet, protocol); @@ -804,8 +818,6 @@ PPPInterface::Send(mbuf *packet, uint16 protocol) status_t PPPInterface::Receive(mbuf *packet, uint16 protocol) { - AccessHelper access(&fAccessing); - if(!packet) return B_ERROR; @@ -874,8 +886,6 @@ PPPInterface::Receive(mbuf *packet, uint16 protocol) status_t PPPInterface::SendToDevice(mbuf *packet, uint16 protocol) { - AccessHelper access(&fAccessing); - if(!packet) return B_ERROR; @@ -914,7 +924,7 @@ PPPInterface::SendToDevice(mbuf *packet, uint16 protocol) } // encode in ppp frame - packet = M_PREPEND(packet, sizeof(uint16)); + M_PREPEND(packet, sizeof(uint16)); if(packet == NULL) return B_ERROR; @@ -924,11 +934,13 @@ PPPInterface::SendToDevice(mbuf *packet, uint16 protocol) uint16 *header = mtod(packet, uint16*); *header = protocol; + fIdleSince = system_time(); + // pass to device/children if(!IsMultilink() || Parent()) { // check if packet is too big for device - if((packet->m_flags & M_PKTHDR && packet->m_pkt_hdr.len > LinkMTU()) - || packet->m_len > LinkMTU()) { + if((packet->m_flags & M_PKTHDR && packet->m_pkthdr.len > LinkMTU()) + || packet->m_len > LinkMTU()) { m_freem(packet); return B_ERROR; } @@ -945,8 +957,6 @@ PPPInterface::SendToDevice(mbuf *packet, uint16 protocol) status_t PPPInterface::ReceiveFromDevice(mbuf *packet) { - AccessHelper access(&fAccessing); - if(!packet) return B_ERROR; @@ -961,16 +971,12 @@ PPPInterface::ReceiveFromDevice(mbuf *packet) m_adj(packet, sizeof(uint16)); - if(packet->m_flags & M_PKTHDR) { + // Set our interface as the receiver. + // This might be NULL, so protocols that belong to the network stack (IP, etc.) + // will probably be confused (as there is no interface from which the packet came). + // Protocols that live only in the PPP interface should have no problems with this. + if(packet->m_flags & M_PKTHDR) packet->m_pkthdr.rcvif = Ifnet(); - // make sure the protocols think we received - // the packet - - if(!packet->m_pkthdr.rcvif) { - m_freem(packet); - return B_ERROR; - } - } return Receive(packet, protocol); } @@ -979,10 +985,24 @@ PPPInterface::ReceiveFromDevice(mbuf *packet) void PPPInterface::Pulse() { - // TODO: - // check our idle time + // check our idle time and disconnect if needed + if(fDisconnectAfterIdleSince > 0 && fIdleSince != 0 + && fIdleSince - system_time() >= fDisconnectAfterIdleSince) { + StateMachine().CloseEvent(); + return; + } StateMachine().TimerEvent(); + + if(Device()) + Device()->Pulse(); + + for(int32 index = 0; index < CountProtocols(); index++) + ProtocolAt(index)->Pulse(); + + PPPEncapsulator *encapsulator = fFirstEncapsulator; + for(; encapsulator; encapsulator = encapsulator->Next()) + encapsulator->Pulse(); } @@ -1004,14 +1024,12 @@ PPPInterface::RegisterInterface() if(!fManager) return false; - fIfnet = fManager->add_interface(this); + fIfnet = fManager->register_interface(ID()); if(!fIfnet) return false; - if(Device()) - fIfnet->if_baudrate = max(Device()->InputTransferRate(), - Device()->OutputTransferRate()); + CalculateBaudRate(); return true; } @@ -1031,7 +1049,7 @@ PPPInterface::UnregisterInterface() if(!fManager) return false; - fManager->remove_interface(this); + fManager->unregister_interface(ID()); fIfnet = NULL; return true; @@ -1047,10 +1065,8 @@ PPPInterface::CalculateMRU() fHeaderLength = sizeof(uint16); PPPEncapsulator encapsulator = fFirstEncapsulator; - while(encapsulator) { + for(; encapsulator; encapsulator = encapsulator->Next()) fHeaderLength += encapsulator->Overhead(); - encapsulator = encapsulator->Next(); - } fMRU -= fHeaderLength; @@ -1064,6 +1080,24 @@ PPPInterface::CalculateMRU() } +void +PPPInterface::CalculateBaudRate() +{ + if(!Ifnet()) + return; + + if(Device()) + fIfnet->if_baudrate = max(Device()->InputTransferRate(), + Device()->OutputTransferRate()); + else { + fIfnet->if_baudrate = 0; + for(int32 index = 0; index < CountChildren(); index++) + if(ChildAt(index)->Ifnet()) + fIfnet->if_baudrate += ChildAt(index)->Ifnet()->if_baudrate; + } +} + + void PPPInterface::Redial() { diff --git a/src/tests/kits/net/ppp/src/KPPPLCP.cpp b/src/tests/kits/net/ppp/src/KPPPLCP.cpp index 709d6c974f..d22955deca 100644 --- a/src/tests/kits/net/ppp/src/KPPPLCP.cpp +++ b/src/tests/kits/net/ppp/src/KPPPLCP.cpp @@ -64,3 +64,16 @@ PPPLCP::OptionHandlerAt(int32 index) const return handler; } + +uint32 +PPPLCP::AdditionalOverhead const +{ + uint32 overhead += PPP_PROTOCOL_OVERHEAD; + + if(Target()) + overhead += Target()->Overhead(); + if(Interface()->Device()) + overhead += Interface()->Device()->Overhead(); + + return overhead; +} diff --git a/src/tests/kits/net/ppp/src/KPPPOptionHandler.cpp b/src/tests/kits/net/ppp/src/KPPPOptionHandler.cpp index 9443c29efe..0a9d971ca9 100644 --- a/src/tests/kits/net/ppp/src/KPPPOptionHandler.cpp +++ b/src/tests/kits/net/ppp/src/KPPPOptionHandler.cpp @@ -6,3 +6,33 @@ //--------------------------------------------------------------------- #include "KPPPOptionHandler.h" + + +PPPOptionHandler::PPPOptionHandler(const char *name, PPPInterface *interface, + driver_parameter *settings) + : fInterface(interface), fSettings(settings) +{ + fName = name ? strdup(name) : NULL; + + if(interface) + interface->LCP().AddOptionHandler(this); +} + + +PPPOptionHandler::~PPPOptionHandler() +{ + free(fName); + + if(Interface()) + Interface()->LCP().RemoveOptionHandler(this); +} + + +status_t +PPPOptionHandler::InitCheck() const +{ + if(!Interface() || !Settings()) + return B_ERROR; + + return B_OK; +} diff --git a/src/tests/kits/net/ppp/src/KPPPProtocol.cpp b/src/tests/kits/net/ppp/src/KPPPProtocol.cpp index 98570f5d44..216eeb4681 100644 --- a/src/tests/kits/net/ppp/src/KPPPProtocol.cpp +++ b/src/tests/kits/net/ppp/src/KPPPProtocol.cpp @@ -6,3 +6,129 @@ //--------------------------------------------------------------------- #include "KPPPProtocol.h" + + +PPPProtocol::PPPProtocol(const char *name, PPP_PHASE phase, uint16 protocol, + int32 addressFamily, PPPInterface *interface, + driver_parameter *settings, int32 flags = PPP_NO_FLAGS) + : fPhase(phase), fProtocol(protocol), fAddressFamily(addressFamily), + fInterface(interface), fSettings(settings), fFlags(flags), + fEnabled(true), fUpRequested(true), fConnectionStatus(PPP_DOWN_PHASE) +{ + fName = name ? strdup(name) : NULL; + + if(interface) + interface->AddProtocol(this); +} + + +PPPProtocol::~PPPProtocol() +{ + free(fName); + + if(Interface()) + Interface()->RemoveProtocol(this); +} + + +status_t +PPPProtocol::InitCheck() const +{ + if(!Interface() || !Settings()) + return B_ERROR; + + return B_OK; +} + + +void +PPPProtocol::SetEnabled(bool enabled = true) +{ + fEnabled = enabled; + + if(!Interface()) + return; + + if(!enabled) { + if(IsUp() || IsGoingUp())) + Down(); + } else if(!IsUp() && !IsGoingUp() && IsUpRequested() && Interface()->IsUp()) + Up(); +} + + +status_t +PPPProtocol::Control(uint32 op, void *data, size_t length) +{ + switch(op) { + // TODO: + // get: + // - name + // - protocol, address family + // - status (Is(Going)Up/Down/UpRequested/Enabled) + // set: + // - enabled + + default: + return B_ERROR; + } + + return B_OK; +} + + +void +PPPProtocol::Pulse() +{ + // do nothing by default +} + + +void +PPPProtocol::UpStarted() +{ + fConnectionStatus = PPP_ESTABLISHMENT_PHASE; +} + + +void +PPPProtocol::DownStarted() +{ + fConnectionStatus = PPP_TERMINATION_PHASE; +} + + +void +PPPProtocol::UpFailedEvent() +{ + fConnectionStatus = PPP_DOWN_PHASE; + + if(!Interface()) + return; + + Interface()->StateMachine().UpFailedEvent(this); +} + + +void +PPPProtocol::UpEvent() +{ + fConnectionStatus = PPP_ESTABLISHED_PHASE; + + if(!Interface()) + return; + + Interface()->StateMachine().UpEvent(this); +} + + +void +PPPProtocol::DownEvent() +{ + fConnectionStatus = PPP_DOWN_PHASE; + + if(!Interface()) + return; + + Interface()->StateMachine().DownEvent(this); +} diff --git a/src/tests/kits/net/ppp/src/KPPPStateMachine.cpp b/src/tests/kits/net/ppp/src/KPPPStateMachine.cpp index 2d54adc64d..e53dc5582f 100644 --- a/src/tests/kits/net/ppp/src/KPPPStateMachine.cpp +++ b/src/tests/kits/net/ppp/src/KPPPStateMachine.cpp @@ -105,6 +105,8 @@ PPPStateMachine::AuthenticationAccepted(const char *name) fAuthenticationStatus = PPP_AUTHENTICATION_SUCCESSFUL; free(fAuthenticationName); fAuthenticationName = strdup(name); + + Interface()->Report(PPP_CONNECTION_REPORT, PPP_REPORT_AUTHENTICATION_SUCCESSFUL, 0); } @@ -147,6 +149,9 @@ PPPStateMachine::PeerAuthenticationAccepted(const char *name) fPeerAuthenticationStatus = PPP_AUTHENTICATION_SUCCESSFUL; free(fPeerAuthenticationName); fPeerAuthenticationName = strdup(name); + + Interface()->Report(PPP_CONNECTION_REPORT, + PPP_REPORT_PEER_AUTHENTICATION_SUCCESSFUL, 0); } @@ -183,17 +188,23 @@ PPPStateMachine::UpEvent(PPPInterface *interface) { LockerHelper locker(fLock); - if(Phase() <= PPP_TERMINATION_PHASE || State() != PPP_STARTING_STATE) { + if(Phase() <= PPP_TERMINATION_PHASE) { interface->StateMachine().CloseEvent(); return; } - NewState(PPP_OPENED_STATE); + Interface()->CalculateBaudRate(); + if(Phase() == PPP_ESTABLISHMENT_PHASE) { - NewPhase(PPP_AUTHENTICATION_PHASE); + // this is the first interface that went up + Interface()->SetLinkMTU(interface->LinkMTU()); locker.UnlockNow(); ThisLayerUp(); - } + } else if(Interface()->LinkMTU() > interface->LinkMTU()) + Interface()->SetLinkMTU(interface->LinkMTU()); + // linkMTU should always be the smallest value of all children + + NewState(PPP_OPENED_STATE); } @@ -202,6 +213,11 @@ PPPStateMachine::DownEvent(PPPInterface *interface) { LockerHelper locker(fLock); + uint32 linkMTU = 0; + // the new linkMTU + + Interface()->CalculateBaudRate(); + // when all children are down we should not be running if(Interface()->IsMultilink() && !Interface()->Parent()) { uint32 count = 0; @@ -209,10 +225,19 @@ PPPStateMachine::DownEvent(PPPInterface *interface) for(int32 index = 0; index < Interface()->CountChildren(); index++) { child = Interface()->ChildAt(index); - if(child && child->IsUp()) + if(child && child->IsUp()) { + // set linkMTU to the smallest value of all children + if(linkMTU == 0) + linkMTU = child->LinkMTU(); + else if(linkMTU > child->LinkMTU()) + linkMTU = child->LinkMTU(); + ++count; + } } + Interface()->SetLinkMTU(linkMTU); + if(count == 0) { locker.UnlockNow(); DownEvent(); @@ -372,10 +397,7 @@ PPPStateMachine::UpEvent() return; // it is not our device that went up... - if(Interface()->Ifnet()) - Interface()->Ifnet()->if_baudrate = max( - Interface()->Device()->InputTransferRate(), - Interface()->Device()->OutputTransferRate()); + Interface()->CalculateBaudRate(); switch(State()) { case PPP_INITIAL_STATE: @@ -428,14 +450,14 @@ PPPStateMachine::DownEvent() { LockerHelper locker(fLock); - if(!Interface()->Device() || Interface()->Device->IsUp()) + if(Interface()->Device() && Interface()->Device->IsUp()) return; // it is not our device that went up... - if(Interface()->Ifnet()) - Interface()->Ifnet()->if_baudrate = max( - Interface()->Device()->InputTransferRate(), - Interface()->Device()->OutputTransferRate()); + Interface()->CalculateBaudRate(); + + // reset IdleSince + Interface()->fIdleSince = 0; switch(State()) { case PPP_CLOSED_STATE: @@ -1150,7 +1172,7 @@ PPPStateMachine::RCREvent(mbuf *packet) handled = false; for(int32 index = 0; index < LCP().CountOptionHandlers(); - index++) { + index++) { handler = LCP().OptionHandlerAt(index); error = handler->ParseRequest(&request, item, &nak, &reject); if(error == PPP_UNHANLED) @@ -1171,9 +1193,9 @@ PPPStateMachine::RCREvent(mbuf *packet) } if(nak.CountItems() > 0) - RCRBadEvent(nak.ToMbuf(), NULL); + RCRBadEvent(nak.ToMbuf(LCP().AdditionalOverhead()), NULL); else if(reject.CountItmes() > 0) - RCRBadEvent(NULL, reject.ToMbuf()); + RCRBadEvent(NULL, reject.ToMbuf(LCP().AdditionalOverhead())); else RCRGoodEvent(packet); } @@ -1326,7 +1348,7 @@ PPPStateMachine::SendConfigureRequest() } } - LCP().Send(request.ToMbuf()); + LCP().Send(request.ToMbuf(LCP().AdditionalOverhead())); } @@ -1369,11 +1391,7 @@ PPPStateMachine::SendTerminateRequest() --fTerminateCounter; // reserve some space for other protocols - m->m_data += PPP_PROTOCOL_OVERHEAD; - if(LCP().Encapsulator()) - m->m_data += LCP().Encapsulator()->Overhead(); - if(Interface()->Device()) - m->m_data += Interface()->Device()->Overhead(); + m->m_data += LCP().AdditionalOverhead(); lcp_packet *request = mtod(m, lcp_packet*); request->code = PPP_TERMINATE_REQUEST; @@ -1398,8 +1416,36 @@ PPPStateMachine::SendTerminateAck(mbuf *request) void PPPStateMachine::SendCodeReject(mbuf *packet, uint16 protocol, uint8 type) { - // TODO: - // add the packet to the reject and truncate it if needed + int32 length; + // additional space needed for this reject + if(type == PPP_PROTOCOL_REJECT) + length = 6; + else + length = 4; + + M_PREPEND(packet, length + LCP().AdditionalOverhead()); + + int32 adjust = 0; + // adjust packet size by this value if packet is too big + if(packet->m_flags & M_PKTHDR) { + if(packet->m_pkthdr.len > Interface()->LinkMTU()) + adjust = Interface()->LinkMTU() - packet->m_pkthdr.len; + } else if(packet->m_len > Interface()->LinkMTU()) + adjust = Interface()->LinkMTU() - packet->m_len; + + if(adjust != 0) + m_adj(packet, adjust); + + lcp_packet *reject = mtod(packet, lcp_packet*); + data->code = type; + data->id = NextID(); + data->length = (uint16) htons(reject->m_pkthdr.len); + + protocol = (uint16) htons(protocol); + if(type == PPP_PROTOCOL_REJECT) + memcpy(&data->data, &protocol, sizeof(protocol)); + + LCP().Send(packet); } @@ -1483,7 +1529,8 @@ void PPPStateMachine::DownProtocols() { for(int32 index = 0; index < Interface()->CountProtocols(); index++) - Interface()->ProtocolAt(index)->Down(); + if(Interface()->ProtocolAt(index)->IsEnabled()) + Interface()->ProtocolAt(index)->Down(); } @@ -1494,7 +1541,8 @@ PPPStateMachine::DownEncapsulators() for(; encapsulator_handler; encapsulator_handler = encapsulator_handler->Next()) - encapsualtor_handler->Down(); + if(encapsulator_handler->IsEnabled()) + encapsualtor_handler->Down(); }